@nuucognition/flint-cli 0.5.6-dev.1 → 0.5.6-dev.11
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/README.md +7 -11
- package/bin/flint-prod.js +0 -2
- package/bin/flint.js +2 -2
- package/dist/chunk-4LAWFN2H.js +6821 -0
- package/dist/{chunk-JSBRDJBE.js → chunk-4VNS5WPM.js} +13 -1
- package/dist/{chunk-X6OG5PEE.js → chunk-5P56DC5O.js} +2 -2
- package/dist/chunk-DSRNHRUX.js +768 -0
- package/dist/{chunk-6MPRSFXI.js → chunk-EFW5J46R.js} +5 -5
- package/dist/{chunk-M3NSYVYR.js → chunk-FZW47K7J.js} +2 -2
- package/dist/chunk-SCBMBMSG.js +12 -0
- package/dist/chunk-WW4R5MWW.js +939 -0
- package/dist/{chunk-WMXC6KO6.js → chunk-YFUMEQRR.js} +476 -972
- package/dist/{chunk-CBGQBE6C.js → chunk-YQMGDALR.js} +1 -747
- package/dist/dist-33SYCV6R.js +28 -0
- package/dist/{dist-EAYA2DAP.js → dist-3ZZYLR45.js} +36 -21
- package/dist/{exports-FO5IMLM7-4DUGQDXH.js → exports-OZQUMYQI-RIZGDBFL.js} +4 -3
- package/dist/index.js +8156 -9638
- package/dist/marked-terminal-G6SMT3U3.js +58815 -0
- package/dist/marked.esm-T6BYMIDL.js +2158 -0
- package/dist/{mesh-config-BAIYF4KD-Q3ZCQOCZ.js → mesh-config-NTGFUNZL-T5YSX3S3.js} +5 -2
- package/dist/{metadata-SJT4H53O-LEFHYM5Q.js → metadata-FASTWX6A-MAAQ2YNF.js} +4 -3
- package/dist/plates-4TK56CGM-6ACY6ZX6.js +43 -0
- package/dist/{registry-YN5W7EY7-J52KXGG5.js → registry-5CNUVQN3-MXXC35UE.js} +2 -2
- package/dist/{utils-BBA2XQZO-ETTV2PHU.js → utils-BBA2XQZO-Q2LR5RQU.js} +1 -1
- package/package.json +14 -11
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
registerFlint,
|
|
8
8
|
registerFlintByPath,
|
|
9
9
|
updateFlintEntry
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-5P56DC5O.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-FZW47K7J.js";
|
|
19
|
+
import {
|
|
20
|
+
syncPlateRepos
|
|
21
|
+
} from "./chunk-WW4R5MWW.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,
|
|
@@ -31,7 +32,6 @@ import {
|
|
|
31
32
|
hasFlintToml,
|
|
32
33
|
migrateShardConfig,
|
|
33
34
|
nameFormats,
|
|
34
|
-
parse,
|
|
35
35
|
readFlintToml,
|
|
36
36
|
removeShardFromConfig,
|
|
37
37
|
resolveShardMode,
|
|
@@ -39,7 +39,10 @@ import {
|
|
|
39
39
|
toKebabCase,
|
|
40
40
|
writeFlintJson,
|
|
41
41
|
writeFlintToml
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-DSRNHRUX.js";
|
|
43
|
+
import {
|
|
44
|
+
parse
|
|
45
|
+
} from "./chunk-YQMGDALR.js";
|
|
43
46
|
|
|
44
47
|
// ../../packages/flint/dist/index.js
|
|
45
48
|
import { mkdir as mkdir2, stat as stat9 } from "fs/promises";
|
|
@@ -57,35 +60,29 @@ import { homedir } from "os";
|
|
|
57
60
|
import { readFile as readFile5, writeFile as writeFile22, mkdir as mkdir32 } from "fs/promises";
|
|
58
61
|
import { readFileSync } from "fs";
|
|
59
62
|
import { join as join52 } from "path";
|
|
60
|
-
import {
|
|
63
|
+
import { createHash, randomUUID as randomUUID3 } from "crypto";
|
|
64
|
+
import { mkdir as mkdir52, readdir as readdir22, readFile as readFile32, rename as rename5, rm as rm6, writeFile as writeFile42 } from "fs/promises";
|
|
65
|
+
import { basename, dirname as dirname22, join as join72, relative } from "path";
|
|
66
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
67
|
+
import { readFile as readFile22, writeFile as writeFile32, mkdir as mkdir42, access as access22 } from "fs/promises";
|
|
68
|
+
import { join as join62 } from "path";
|
|
69
|
+
import { mkdir as mkdir6, stat as stat42 } from "fs/promises";
|
|
70
|
+
import { join as join82 } from "path";
|
|
61
71
|
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
72
|
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";
|
|
73
|
+
import { rm as rm22 } from "fs/promises";
|
|
77
74
|
import { execFile } from "child_process";
|
|
78
|
-
import { cp as cp3, mkdir as
|
|
75
|
+
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
76
|
import { homedir as homedir2 } from "os";
|
|
80
|
-
import { basename as
|
|
81
|
-
import { promisify as
|
|
82
|
-
import { readFile as
|
|
83
|
-
import { join as
|
|
77
|
+
import { basename as basename2, dirname as dirname3, join as join102, resolve as resolve3 } from "path";
|
|
78
|
+
import { promisify as promisify3 } from "util";
|
|
79
|
+
import { readFile as readFile42, writeFile as writeFile52, mkdir as mkdir7, rm as rm32, stat as stat52 } from "fs/promises";
|
|
80
|
+
import { join as join92 } from "path";
|
|
84
81
|
import { randomUUID as randomUUID22 } from "crypto";
|
|
85
|
-
import { mkdir as
|
|
86
|
-
import { join as
|
|
82
|
+
import { mkdir as mkdir9, readdir as readdir42, copyFile, rm as rm62, readFile as readFile7, writeFile as writeFile7, rmdir as rmdir2 } from "fs/promises";
|
|
83
|
+
import { join as join12, resolve as resolve5, dirname as dirname4 } from "path";
|
|
87
84
|
import { randomUUID as randomUUID32 } from "crypto";
|
|
88
|
-
import { parse as
|
|
85
|
+
import { parse as parseYaml3 } from "yaml";
|
|
89
86
|
|
|
90
87
|
// ../../packages/flint-migrations/dist/index.js
|
|
91
88
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
@@ -128,7 +125,7 @@ function parseWorkspaceToml(content) {
|
|
|
128
125
|
const config = {};
|
|
129
126
|
let currentSection = null;
|
|
130
127
|
let currentPath = null;
|
|
131
|
-
for (const line of content.split(
|
|
128
|
+
for (const line of content.split(/\r?\n/)) {
|
|
132
129
|
const trimmed = line.trim();
|
|
133
130
|
if (!trimmed || trimmed.startsWith("#")) {
|
|
134
131
|
continue;
|
|
@@ -353,7 +350,7 @@ async function findMarkdownFiles(dir) {
|
|
|
353
350
|
return results;
|
|
354
351
|
}
|
|
355
352
|
function stripLdTags(content) {
|
|
356
|
-
const lines = content.split(
|
|
353
|
+
const lines = content.split(/\r?\n/);
|
|
357
354
|
const filtered = lines.filter((line) => !LD_TAG_PATTERN.test(line));
|
|
358
355
|
if (filtered.length === lines.length) {
|
|
359
356
|
return { stripped: content, had: false };
|
|
@@ -726,7 +723,7 @@ function isRedundant(bareTag, allTags) {
|
|
|
726
723
|
return allTags.some((tag) => tag !== bareTag && isPrefixedTag(tag));
|
|
727
724
|
}
|
|
728
725
|
function migrateContent(content) {
|
|
729
|
-
const lines = content.split(
|
|
726
|
+
const lines = content.split(/\r?\n/);
|
|
730
727
|
let fmStart = -1;
|
|
731
728
|
let fmEnd = -1;
|
|
732
729
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -840,8 +837,8 @@ var artifactTemplateCleanup = {
|
|
|
840
837
|
if (changed) {
|
|
841
838
|
await ctx.write(relativePath, result);
|
|
842
839
|
filesModified++;
|
|
843
|
-
const origLines = content.split(
|
|
844
|
-
const newLines = result.split(
|
|
840
|
+
const origLines = content.split(/\r?\n/);
|
|
841
|
+
const newLines = result.split(/\r?\n/);
|
|
845
842
|
if (origLines.length !== newLines.length) {
|
|
846
843
|
tagsStripped += origLines.length - newLines.length;
|
|
847
844
|
}
|
|
@@ -1610,7 +1607,7 @@ function escapeRegExp(value) {
|
|
|
1610
1607
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1611
1608
|
}
|
|
1612
1609
|
function getSectionBody(toml, sectionName) {
|
|
1613
|
-
const lines = toml.split(
|
|
1610
|
+
const lines = toml.split(/\r?\n/);
|
|
1614
1611
|
const header = `[${sectionName}]`;
|
|
1615
1612
|
const start = lines.findIndex((line) => line.trim() === header);
|
|
1616
1613
|
if (start === -1) return null;
|
|
@@ -1851,7 +1848,7 @@ async function findMarkdownFiles3(dir) {
|
|
|
1851
1848
|
return results;
|
|
1852
1849
|
}
|
|
1853
1850
|
function parseFrontmatter(content) {
|
|
1854
|
-
const lines = content.split(
|
|
1851
|
+
const lines = content.split(/\r?\n/);
|
|
1855
1852
|
if (lines[0]?.trim() !== "---") {
|
|
1856
1853
|
return { hasFrontmatter: false, frontmatterLines: [], bodyStart: 0 };
|
|
1857
1854
|
}
|
|
@@ -1897,7 +1894,7 @@ function extractSessionValues(lines, startIdx) {
|
|
|
1897
1894
|
function rewriteFrontmatter(content) {
|
|
1898
1895
|
const { hasFrontmatter, frontmatterLines, bodyStart } = parseFrontmatter(content);
|
|
1899
1896
|
if (!hasFrontmatter) return null;
|
|
1900
|
-
const lines = content.split(
|
|
1897
|
+
const lines = content.split(/\r?\n/);
|
|
1901
1898
|
const allIds = [];
|
|
1902
1899
|
const linesToRemove = /* @__PURE__ */ new Set();
|
|
1903
1900
|
let hasOldFields = false;
|
|
@@ -2356,38 +2353,38 @@ async function runSingleMigration(flintPath, migrationId, options = {}) {
|
|
|
2356
2353
|
}
|
|
2357
2354
|
|
|
2358
2355
|
// ../../packages/flint/dist/index.js
|
|
2359
|
-
import { join as
|
|
2360
|
-
import { mkdtemp, rm as
|
|
2356
|
+
import { join as join112, resolve as resolve4, isAbsolute as isAbsolute2 } from "path";
|
|
2357
|
+
import { mkdtemp, rm as rm52 } from "fs/promises";
|
|
2361
2358
|
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
|
|
2359
|
+
import { exec as exec3 } from "child_process";
|
|
2360
|
+
import { promisify as promisify4 } from "util";
|
|
2361
|
+
import { parse as parseYaml2 } from "yaml";
|
|
2362
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
2363
|
+
import { join as join13 } from "path";
|
|
2364
|
+
import { readdir as readdir52, mkdir as mkdir10 } from "fs/promises";
|
|
2365
|
+
import { writeFile as writeFile8 } from "fs/promises";
|
|
2369
2366
|
import { execSync } from "child_process";
|
|
2370
2367
|
import { existsSync } from "fs";
|
|
2371
|
-
import { spawn
|
|
2372
|
-
import { readdir as
|
|
2373
|
-
import { join as
|
|
2368
|
+
import { spawn } from "child_process";
|
|
2369
|
+
import { readdir as readdir62, access as access3, constants } from "fs/promises";
|
|
2370
|
+
import { join as join14, resolve as resolve6 } from "path";
|
|
2374
2371
|
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
|
|
2372
|
+
import { basename as basename3, dirname as dirname5, join as join16 } from "path";
|
|
2373
|
+
import { exec as exec4 } from "child_process";
|
|
2374
|
+
import { promisify as promisify5 } from "util";
|
|
2375
|
+
import { readFile as readFile8, writeFile as writeFile9, readdir as readdir72 } from "fs/promises";
|
|
2376
|
+
import { join as join15 } from "path";
|
|
2377
|
+
import { stat as stat72, mkdir as mkdir11 } from "fs/promises";
|
|
2378
|
+
import { readdir as readdir82, readFile as readFile9, mkdir as mkdir12 } from "fs/promises";
|
|
2379
|
+
import { join as join17, dirname as dirname6, resolve as resolve7, sep } from "path";
|
|
2383
2380
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
2384
2381
|
import { fileURLToPath } from "url";
|
|
2385
2382
|
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync, readdirSync } from "fs";
|
|
2386
|
-
import { join as
|
|
2383
|
+
import { join as join18 } from "path";
|
|
2387
2384
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
2388
2385
|
import { watch, watchFile, unwatchFile, statSync, openSync, readSync, closeSync } from "fs";
|
|
2389
2386
|
import { existsSync as existsSync3 } from "fs";
|
|
2390
|
-
import { join as
|
|
2387
|
+
import { join as join19 } from "path";
|
|
2391
2388
|
import { homedir as homedir3 } from "os";
|
|
2392
2389
|
import { existsSync as existsSync4 } from "fs";
|
|
2393
2390
|
var STANDARD_DIRECTORIES = ["Mesh", "Media", "Shards", "Plates", "Sources", "Exports", "Workspace", "Workspace/Bench"];
|
|
@@ -2707,541 +2704,16 @@ async function getOpenApps() {
|
|
|
2707
2704
|
const config = await readGlobalConfig();
|
|
2708
2705
|
return config.open?.apps ?? ["obsidian"];
|
|
2709
2706
|
}
|
|
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
2707
|
function getIdentityStatePath(flintPath) {
|
|
3236
|
-
return
|
|
2708
|
+
return join62(getFlintConfigDir(flintPath), "identity.json");
|
|
3237
2709
|
}
|
|
3238
2710
|
function getPersonFilePath(flintPath, name) {
|
|
3239
2711
|
const personName = name.startsWith("@") ? name : `@${name}`;
|
|
3240
|
-
return
|
|
2712
|
+
return join62(flintPath, "Mesh", "People", `${personName}.md`);
|
|
3241
2713
|
}
|
|
3242
2714
|
async function readIdentityState(flintPath) {
|
|
3243
2715
|
try {
|
|
3244
|
-
const content = await
|
|
2716
|
+
const content = await readFile22(getIdentityStatePath(flintPath), "utf-8");
|
|
3245
2717
|
return JSON.parse(content);
|
|
3246
2718
|
} catch {
|
|
3247
2719
|
return null;
|
|
@@ -3249,8 +2721,8 @@ async function readIdentityState(flintPath) {
|
|
|
3249
2721
|
}
|
|
3250
2722
|
async function writeIdentityState(flintPath, state) {
|
|
3251
2723
|
const statePath = getIdentityStatePath(flintPath);
|
|
3252
|
-
await
|
|
3253
|
-
await
|
|
2724
|
+
await mkdir42(getFlintConfigDir(flintPath), { recursive: true });
|
|
2725
|
+
await writeFile32(statePath, JSON.stringify(state, null, 2));
|
|
3254
2726
|
}
|
|
3255
2727
|
async function personExists(flintPath, name) {
|
|
3256
2728
|
try {
|
|
@@ -3262,9 +2734,9 @@ async function personExists(flintPath, name) {
|
|
|
3262
2734
|
}
|
|
3263
2735
|
async function createPersonFile(flintPath, name) {
|
|
3264
2736
|
const filePath = getPersonFilePath(flintPath, name);
|
|
3265
|
-
const dir =
|
|
3266
|
-
await
|
|
3267
|
-
await
|
|
2737
|
+
const dir = join62(flintPath, "Mesh", "People");
|
|
2738
|
+
await mkdir42(dir, { recursive: true });
|
|
2739
|
+
await writeFile32(filePath, "");
|
|
3268
2740
|
return filePath;
|
|
3269
2741
|
}
|
|
3270
2742
|
async function setIdentity(flintPath, name) {
|
|
@@ -3282,26 +2754,26 @@ async function setIdentity(flintPath, name) {
|
|
|
3282
2754
|
async function getIdentity(flintPath) {
|
|
3283
2755
|
return readIdentityState(flintPath);
|
|
3284
2756
|
}
|
|
3285
|
-
var FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?/;
|
|
2757
|
+
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
|
|
3286
2758
|
function parseArtifactFile(content) {
|
|
3287
2759
|
const match = content.match(FRONTMATTER_RE);
|
|
3288
2760
|
if (!match) {
|
|
3289
|
-
return { frontmatter: {}, body: content };
|
|
2761
|
+
return { frontmatter: {}, body: content.replace(/\r\n/g, "\n") };
|
|
3290
2762
|
}
|
|
3291
2763
|
const frontmatterSource = match[1] ?? "";
|
|
3292
|
-
const frontmatter =
|
|
3293
|
-
const body = content.slice(match[0].length);
|
|
2764
|
+
const frontmatter = parseYaml(frontmatterSource, { logLevel: "error" }) ?? {};
|
|
2765
|
+
const body = content.slice(match[0].length).replace(/\r\n/g, "\n");
|
|
3294
2766
|
return { frontmatter, body };
|
|
3295
2767
|
}
|
|
3296
2768
|
function stringifyArtifact(frontmatter, body) {
|
|
3297
2769
|
return `---
|
|
3298
|
-
${
|
|
2770
|
+
${stringifyYaml(frontmatter).trimEnd()}
|
|
3299
2771
|
---
|
|
3300
2772
|
|
|
3301
2773
|
${body.trimStart()}`;
|
|
3302
2774
|
}
|
|
3303
2775
|
function normalizeRelativePath(flintPath, filePath) {
|
|
3304
|
-
return
|
|
2776
|
+
return relative(flintPath, filePath).replace(/\\/g, "/");
|
|
3305
2777
|
}
|
|
3306
2778
|
function getArtifactTitleFromFilename(filename) {
|
|
3307
2779
|
return filename.endsWith(".md") ? filename.slice(0, -3) : filename;
|
|
@@ -3335,10 +2807,10 @@ function normalizeIncrement(value) {
|
|
|
3335
2807
|
}
|
|
3336
2808
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["Agents", "Archive", "node_modules", ".git"]);
|
|
3337
2809
|
async function collectMarkdownFiles(dir, skipDirs = SKIP_DIRS) {
|
|
3338
|
-
const entries = await
|
|
2810
|
+
const entries = await readdir22(dir, { withFileTypes: true }).catch(() => []);
|
|
3339
2811
|
const files = [];
|
|
3340
2812
|
for (const entry of entries) {
|
|
3341
|
-
const entryPath =
|
|
2813
|
+
const entryPath = join72(dir, entry.name);
|
|
3342
2814
|
if (entry.isDirectory()) {
|
|
3343
2815
|
if (skipDirs.has(entry.name)) continue;
|
|
3344
2816
|
files.push(...await collectMarkdownFiles(entryPath, skipDirs));
|
|
@@ -3354,7 +2826,7 @@ function syntheticId(relativePath) {
|
|
|
3354
2826
|
return createHash("sha256").update(relativePath).digest("hex").slice(0, 32);
|
|
3355
2827
|
}
|
|
3356
2828
|
async function readArtifactAtPath(flintPath, filePath) {
|
|
3357
|
-
const content = await
|
|
2829
|
+
const content = await readFile32(filePath, "utf8").catch(() => null);
|
|
3358
2830
|
if (content === null) return null;
|
|
3359
2831
|
const parsed = parseArtifactFile(content);
|
|
3360
2832
|
const relPath = normalizeRelativePath(flintPath, filePath);
|
|
@@ -3362,15 +2834,15 @@ async function readArtifactAtPath(flintPath, filePath) {
|
|
|
3362
2834
|
return {
|
|
3363
2835
|
id,
|
|
3364
2836
|
path: relPath,
|
|
3365
|
-
filename:
|
|
2837
|
+
filename: basename(filePath),
|
|
3366
2838
|
frontmatter: parsed.frontmatter,
|
|
3367
2839
|
body: parsed.body
|
|
3368
2840
|
};
|
|
3369
2841
|
}
|
|
3370
2842
|
async function collectAllArtifactFiles(flintPath) {
|
|
3371
2843
|
const [meshFiles, shardFiles] = await Promise.all([
|
|
3372
|
-
collectMarkdownFiles(
|
|
3373
|
-
collectMarkdownFiles(
|
|
2844
|
+
collectMarkdownFiles(join72(flintPath, "Mesh")),
|
|
2845
|
+
collectMarkdownFiles(join72(flintPath, "Shards"))
|
|
3374
2846
|
]);
|
|
3375
2847
|
return [...meshFiles, ...shardFiles];
|
|
3376
2848
|
}
|
|
@@ -3452,7 +2924,7 @@ function sanitizeOffset(offset) {
|
|
|
3452
2924
|
return Math.max(0, Math.trunc(offset));
|
|
3453
2925
|
}
|
|
3454
2926
|
async function queryArtifacts(flintPath, query = {}) {
|
|
3455
|
-
const files = query.includeShards ? await collectAllArtifactFiles(flintPath) : await collectMarkdownFiles(
|
|
2927
|
+
const files = query.includeShards ? await collectAllArtifactFiles(flintPath) : await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3456
2928
|
const records = await Promise.all(files.map((filePath) => readArtifactAtPath(flintPath, filePath)));
|
|
3457
2929
|
const matching = records.filter((record) => record !== null).filter((record) => matchesArtifactQuery(record, query)).sort((left, right) => compareArtifactSearchMatch(left, right, query));
|
|
3458
2930
|
const limit = sanitizeLimit(query.limit);
|
|
@@ -3487,19 +2959,19 @@ async function updateArtifactById(flintPath, id, patch) {
|
|
|
3487
2959
|
...patch.frontmatter ?? {}
|
|
3488
2960
|
};
|
|
3489
2961
|
const nextBody = patch.body ?? found.artifact.body;
|
|
3490
|
-
await
|
|
2962
|
+
await writeFile42(found.absolutePath, stringifyArtifact(nextFrontmatter, nextBody), "utf8");
|
|
3491
2963
|
return (await getArtifactById(flintPath, id))?.artifact ?? null;
|
|
3492
2964
|
}
|
|
3493
2965
|
function getArchiveDestination(flintPath, absolutePath) {
|
|
3494
|
-
const meshRoot =
|
|
3495
|
-
const relativeToMesh =
|
|
2966
|
+
const meshRoot = join72(flintPath, "Mesh");
|
|
2967
|
+
const relativeToMesh = relative(meshRoot, absolutePath).replace(/\\/g, "/");
|
|
3496
2968
|
if (relativeToMesh.startsWith("Archive/")) {
|
|
3497
2969
|
throw new Error("Artifact is already archived");
|
|
3498
2970
|
}
|
|
3499
2971
|
if (relativeToMesh.startsWith("Types/")) {
|
|
3500
|
-
return
|
|
2972
|
+
return join72(meshRoot, "Archive", relativeToMesh.slice("Types/".length));
|
|
3501
2973
|
}
|
|
3502
|
-
return
|
|
2974
|
+
return join72(meshRoot, "Archive", relativeToMesh);
|
|
3503
2975
|
}
|
|
3504
2976
|
async function deleteArtifactById(flintPath, id, options = {}) {
|
|
3505
2977
|
const found = await getArtifactById(flintPath, id);
|
|
@@ -3507,18 +2979,18 @@ async function deleteArtifactById(flintPath, id, options = {}) {
|
|
|
3507
2979
|
return null;
|
|
3508
2980
|
}
|
|
3509
2981
|
if (!options.archive) {
|
|
3510
|
-
await
|
|
2982
|
+
await rm6(found.absolutePath);
|
|
3511
2983
|
return {
|
|
3512
2984
|
artifact: found.artifact,
|
|
3513
2985
|
archived: false
|
|
3514
2986
|
};
|
|
3515
2987
|
}
|
|
3516
2988
|
const destinationPath = getArchiveDestination(flintPath, found.absolutePath);
|
|
3517
|
-
const existing = await
|
|
2989
|
+
const existing = await readFile32(destinationPath, "utf8").then(() => true).catch(() => false);
|
|
3518
2990
|
if (existing) {
|
|
3519
2991
|
throw new Error(`Archive destination already exists: ${normalizeRelativePath(flintPath, destinationPath)}`);
|
|
3520
2992
|
}
|
|
3521
|
-
await
|
|
2993
|
+
await mkdir52(dirname22(destinationPath), { recursive: true });
|
|
3522
2994
|
await rename5(found.absolutePath, destinationPath);
|
|
3523
2995
|
const archivedArtifact = await readArtifactAtPath(flintPath, destinationPath);
|
|
3524
2996
|
if (!archivedArtifact) {
|
|
@@ -3561,7 +3033,7 @@ function rewriteWikilinks(content, oldTitle, newTitle) {
|
|
|
3561
3033
|
const targetPath = hashIndex >= 0 ? rawTarget.slice(0, hashIndex) : rawTarget;
|
|
3562
3034
|
const suffix = hashIndex >= 0 ? rawTarget.slice(hashIndex) : "";
|
|
3563
3035
|
const normalizedPath = targetPath.replace(/\\/g, "/");
|
|
3564
|
-
const segments = normalizedPath.split(
|
|
3036
|
+
const segments = normalizedPath.split(/[/\\]/);
|
|
3565
3037
|
const lastSegment = segments[segments.length - 1] ?? "";
|
|
3566
3038
|
const bareSegment = getArtifactTitleFromFilename(lastSegment);
|
|
3567
3039
|
if (bareSegment !== oldTitle) {
|
|
@@ -3577,7 +3049,7 @@ async function renameArtifact(flintPath, id, newTitle) {
|
|
|
3577
3049
|
return null;
|
|
3578
3050
|
}
|
|
3579
3051
|
const nextTitle = normalizeNewArtifactTitle(newTitle);
|
|
3580
|
-
const oldFilename =
|
|
3052
|
+
const oldFilename = basename(found.absolutePath);
|
|
3581
3053
|
const oldTitle = getArtifactTitleFromFilename(oldFilename);
|
|
3582
3054
|
const nextFilename = buildRenamedFilename(oldFilename, nextTitle);
|
|
3583
3055
|
const nextLinkTitle = getArtifactTitleFromFilename(nextFilename);
|
|
@@ -3589,19 +3061,19 @@ async function renameArtifact(flintPath, id, newTitle) {
|
|
|
3589
3061
|
modifiedFiles: []
|
|
3590
3062
|
};
|
|
3591
3063
|
}
|
|
3592
|
-
const destinationPath =
|
|
3593
|
-
const existing = await
|
|
3064
|
+
const destinationPath = join72(dirname22(found.absolutePath), nextFilename);
|
|
3065
|
+
const existing = await readFile32(destinationPath, "utf8").then(() => true).catch(() => false);
|
|
3594
3066
|
if (existing) {
|
|
3595
3067
|
throw new Error(`Artifact already exists at ${normalizeRelativePath(flintPath, destinationPath)}`);
|
|
3596
3068
|
}
|
|
3597
3069
|
await rename5(found.absolutePath, destinationPath);
|
|
3598
|
-
const meshFiles = await collectMarkdownFiles(
|
|
3070
|
+
const meshFiles = await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3599
3071
|
const modifiedFiles = /* @__PURE__ */ new Set([normalizeRelativePath(flintPath, destinationPath)]);
|
|
3600
3072
|
for (const filePath of meshFiles) {
|
|
3601
|
-
const content = await
|
|
3073
|
+
const content = await readFile32(filePath, "utf8");
|
|
3602
3074
|
const nextContent = rewriteWikilinks(content, oldTitle, nextLinkTitle);
|
|
3603
3075
|
if (nextContent !== content) {
|
|
3604
|
-
await
|
|
3076
|
+
await writeFile42(filePath, nextContent, "utf8");
|
|
3605
3077
|
modifiedFiles.add(normalizeRelativePath(flintPath, filePath));
|
|
3606
3078
|
}
|
|
3607
3079
|
}
|
|
@@ -3622,8 +3094,8 @@ function extractNumberFromFilename(filename, typeName) {
|
|
|
3622
3094
|
return number ? Number.parseInt(number, 10) : null;
|
|
3623
3095
|
}
|
|
3624
3096
|
async function getNextTypedArtifactNumber(flintPath, typeName) {
|
|
3625
|
-
const files = await collectMarkdownFiles(
|
|
3626
|
-
const numbers = files.map((filePath) => extractNumberFromFilename(
|
|
3097
|
+
const files = await collectMarkdownFiles(join72(flintPath, "Mesh"));
|
|
3098
|
+
const numbers = files.map((filePath) => extractNumberFromFilename(basename(filePath), typeName)).filter((value) => value !== null);
|
|
3627
3099
|
return numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
|
|
3628
3100
|
}
|
|
3629
3101
|
function asStringArray(value) {
|
|
@@ -3708,9 +3180,9 @@ async function createTaskArtifact(flintPath, data) {
|
|
|
3708
3180
|
...notes.length > 0 ? notes.map((note) => `- ${note}`) : ["-"],
|
|
3709
3181
|
""
|
|
3710
3182
|
];
|
|
3711
|
-
const filePath =
|
|
3712
|
-
await
|
|
3713
|
-
await
|
|
3183
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Tasks", `(Task) ${number} ${title}.md`);
|
|
3184
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3185
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3714
3186
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3715
3187
|
if (!created) {
|
|
3716
3188
|
throw new Error("Failed to create task artifact");
|
|
@@ -3731,9 +3203,9 @@ async function createNoteArtifact(flintPath, tag, data) {
|
|
|
3731
3203
|
frontmatter.authors = [`[[${identity.person}]]`];
|
|
3732
3204
|
}
|
|
3733
3205
|
const body = typeof data.body === "string" && data.body.trim() ? data.body.trim() : "";
|
|
3734
|
-
const filePath =
|
|
3735
|
-
await
|
|
3736
|
-
await
|
|
3206
|
+
const filePath = join72(flintPath, "Mesh", "Notes", `${title}.md`);
|
|
3207
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3208
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, body), "utf8");
|
|
3737
3209
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3738
3210
|
if (!created) {
|
|
3739
3211
|
throw new Error("Failed to create note artifact");
|
|
@@ -3804,9 +3276,9 @@ async function createProposalArtifact(flintPath, data) {
|
|
|
3804
3276
|
...notes.length > 0 ? notes.map((note) => `- ${note}`) : ["-"],
|
|
3805
3277
|
""
|
|
3806
3278
|
];
|
|
3807
|
-
const filePath =
|
|
3808
|
-
await
|
|
3809
|
-
await
|
|
3279
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Proposals", `(Proposal) ${number} ${title}.md`);
|
|
3280
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3281
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3810
3282
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3811
3283
|
if (!created) {
|
|
3812
3284
|
throw new Error("Failed to create proposal artifact");
|
|
@@ -3814,9 +3286,9 @@ async function createProposalArtifact(flintPath, data) {
|
|
|
3814
3286
|
return created;
|
|
3815
3287
|
}
|
|
3816
3288
|
async function writeStubExclusive(basePath, content) {
|
|
3817
|
-
await
|
|
3289
|
+
await mkdir52(dirname22(basePath), { recursive: true });
|
|
3818
3290
|
try {
|
|
3819
|
-
await
|
|
3291
|
+
await writeFile42(basePath, content, { flag: "wx" });
|
|
3820
3292
|
return basePath;
|
|
3821
3293
|
} catch (err) {
|
|
3822
3294
|
if (err.code !== "EEXIST") throw err;
|
|
@@ -3826,7 +3298,7 @@ async function writeStubExclusive(basePath, content) {
|
|
|
3826
3298
|
for (let n = 2; n < 1e4; n++) {
|
|
3827
3299
|
const candidate = `${stem} ${n}${ext}`;
|
|
3828
3300
|
try {
|
|
3829
|
-
await
|
|
3301
|
+
await writeFile42(candidate, content, { flag: "wx" });
|
|
3830
3302
|
return candidate;
|
|
3831
3303
|
} catch (err) {
|
|
3832
3304
|
if (err.code !== "EEXIST") throw err;
|
|
@@ -3834,6 +3306,33 @@ async function writeStubExclusive(basePath, content) {
|
|
|
3834
3306
|
}
|
|
3835
3307
|
throw new Error(`Could not find available stub number for ${basePath}`);
|
|
3836
3308
|
}
|
|
3309
|
+
async function createNotepadArtifact(flintPath, data) {
|
|
3310
|
+
const title = typeof data.title === "string" && data.title.trim() ? data.title.trim() : "New Notepad";
|
|
3311
|
+
const number = String(await getNextTypedArtifactNumber(flintPath, "Notepad")).padStart(3, "0");
|
|
3312
|
+
const identity = await getIdentity(flintPath);
|
|
3313
|
+
const frontmatter = {
|
|
3314
|
+
id: randomUUID3(),
|
|
3315
|
+
tags: ["#ntpd/notepad"],
|
|
3316
|
+
status: "active",
|
|
3317
|
+
template: "[[tmp-ntpd-notepad-v1.0]]"
|
|
3318
|
+
};
|
|
3319
|
+
if (identity) frontmatter.authors = [`[[${identity.person}]]`];
|
|
3320
|
+
const initialMessage = typeof data.initialMessage === "string" && data.initialMessage.trim() ? data.initialMessage.trim() : "";
|
|
3321
|
+
const bodyLines = [
|
|
3322
|
+
"# 1",
|
|
3323
|
+
"",
|
|
3324
|
+
initialMessage,
|
|
3325
|
+
""
|
|
3326
|
+
];
|
|
3327
|
+
const filePath = join72(flintPath, "Mesh", "Types", "Notepads", `(Notepad) ${number} ${title}.md`);
|
|
3328
|
+
await mkdir52(dirname22(filePath), { recursive: true });
|
|
3329
|
+
await writeFile42(filePath, stringifyArtifact(frontmatter, bodyLines.join("\n")), "utf8");
|
|
3330
|
+
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3331
|
+
if (!created) {
|
|
3332
|
+
throw new Error("Failed to create notepad artifact");
|
|
3333
|
+
}
|
|
3334
|
+
return created;
|
|
3335
|
+
}
|
|
3837
3336
|
async function createStubArtifact(flintPath, data) {
|
|
3838
3337
|
const relativePath = typeof data.path === "string" ? data.path : "";
|
|
3839
3338
|
if (!relativePath) {
|
|
@@ -3855,7 +3354,7 @@ async function createStubArtifact(flintPath, data) {
|
|
|
3855
3354
|
|
|
3856
3355
|
This artifact is being created by an agent session. Content will replace this stub shortly.
|
|
3857
3356
|
`;
|
|
3858
|
-
const basePath =
|
|
3357
|
+
const basePath = join72(flintPath, relativePath);
|
|
3859
3358
|
const filePath = await writeStubExclusive(basePath, stringifyArtifact(frontmatter, body));
|
|
3860
3359
|
const created = await readArtifactAtPath(flintPath, filePath);
|
|
3861
3360
|
if (!created) {
|
|
@@ -3871,6 +3370,9 @@ async function createArtifactFromTemplate(flintPath, request) {
|
|
|
3871
3370
|
case "tmp-prop-proposal-v0.1":
|
|
3872
3371
|
case "tmp-prop-proposal":
|
|
3873
3372
|
return createProposalArtifact(flintPath, request.data);
|
|
3373
|
+
case "tmp-ntpd-notepad-v1.0":
|
|
3374
|
+
case "tmp-ntpd-notepad":
|
|
3375
|
+
return createNotepadArtifact(flintPath, request.data);
|
|
3874
3376
|
case "tmp-f-concept-v0.1":
|
|
3875
3377
|
return createNoteArtifact(flintPath, "#note/concept", request.data);
|
|
3876
3378
|
case "tmp-f-record-v0.1":
|
|
@@ -3881,24 +3383,24 @@ async function createArtifactFromTemplate(flintPath, request) {
|
|
|
3881
3383
|
throw new Error(`Unsupported template: ${request.template}`);
|
|
3882
3384
|
}
|
|
3883
3385
|
}
|
|
3884
|
-
var
|
|
3386
|
+
var execAsync2 = promisify2(exec2);
|
|
3885
3387
|
async function pathExists2(path) {
|
|
3886
3388
|
try {
|
|
3887
|
-
await
|
|
3389
|
+
await stat42(path);
|
|
3888
3390
|
return true;
|
|
3889
3391
|
} catch {
|
|
3890
3392
|
return false;
|
|
3891
3393
|
}
|
|
3892
3394
|
}
|
|
3893
3395
|
function getWorkspaceRepositoriesDir(flintPath) {
|
|
3894
|
-
return
|
|
3396
|
+
return join82(flintPath, "Workspace", "Repos");
|
|
3895
3397
|
}
|
|
3896
3398
|
function getRepositoryPath(flintPath, name) {
|
|
3897
|
-
return
|
|
3399
|
+
return join82(getWorkspaceRepositoriesDir(flintPath), name);
|
|
3898
3400
|
}
|
|
3899
3401
|
async function createRepository(flintPath, name, remote) {
|
|
3900
3402
|
const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
|
|
3901
|
-
await
|
|
3403
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3902
3404
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3903
3405
|
if (await pathExists2(repoPath)) {
|
|
3904
3406
|
throw new Error(`Repository folder already exists: ${repoPath}`);
|
|
@@ -3906,25 +3408,25 @@ async function createRepository(flintPath, name, remote) {
|
|
|
3906
3408
|
if (remote) {
|
|
3907
3409
|
return cloneRepository(flintPath, name, remote);
|
|
3908
3410
|
}
|
|
3909
|
-
await
|
|
3411
|
+
await mkdir6(repoPath, { recursive: true });
|
|
3910
3412
|
try {
|
|
3911
|
-
await
|
|
3413
|
+
await execAsync2("git init", { cwd: repoPath });
|
|
3912
3414
|
} catch (error) {
|
|
3913
3415
|
const message = error instanceof Error ? error.message : String(error);
|
|
3914
|
-
await
|
|
3416
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3915
3417
|
throw new Error(`Failed to initialize repository: ${message}`);
|
|
3916
3418
|
}
|
|
3917
3419
|
return repoPath;
|
|
3918
3420
|
}
|
|
3919
3421
|
async function cloneRepository(flintPath, name, url) {
|
|
3920
3422
|
const repositoriesDir = getWorkspaceRepositoriesDir(flintPath);
|
|
3921
|
-
await
|
|
3423
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3922
3424
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3923
3425
|
if (await pathExists2(repoPath)) {
|
|
3924
3426
|
throw new Error(`Repository folder already exists: ${repoPath}`);
|
|
3925
3427
|
}
|
|
3926
3428
|
try {
|
|
3927
|
-
await
|
|
3429
|
+
await execAsync2(`git clone "${url}" "${repoPath}"`);
|
|
3928
3430
|
} catch (error) {
|
|
3929
3431
|
const message = error instanceof Error ? error.message : String(error);
|
|
3930
3432
|
throw new Error(`Failed to clone repository: ${message}`);
|
|
@@ -3936,19 +3438,19 @@ async function removeRepositoryFolder(flintPath, name) {
|
|
|
3936
3438
|
if (!await pathExists2(repoPath)) {
|
|
3937
3439
|
return false;
|
|
3938
3440
|
}
|
|
3939
|
-
await
|
|
3441
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3940
3442
|
return true;
|
|
3941
3443
|
}
|
|
3942
3444
|
async function updateRepository(flintPath, name, url) {
|
|
3943
3445
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
3944
3446
|
if (await pathExists2(repoPath)) {
|
|
3945
3447
|
try {
|
|
3946
|
-
await
|
|
3448
|
+
await execAsync2("git rev-parse HEAD", { cwd: repoPath });
|
|
3947
3449
|
} catch {
|
|
3948
|
-
await
|
|
3450
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
3949
3451
|
return cloneRepository(flintPath, name, url);
|
|
3950
3452
|
}
|
|
3951
|
-
await
|
|
3453
|
+
await execAsync2("git pull", { cwd: repoPath });
|
|
3952
3454
|
return repoPath;
|
|
3953
3455
|
}
|
|
3954
3456
|
return cloneRepository(flintPath, name, url);
|
|
@@ -3969,27 +3471,27 @@ async function getRepositoryStatus(flintPath) {
|
|
|
3969
3471
|
return statuses;
|
|
3970
3472
|
}
|
|
3971
3473
|
function getSourceRepositoriesDir(flintPath) {
|
|
3972
|
-
return
|
|
3474
|
+
return join82(flintPath, "Sources", "Repos");
|
|
3973
3475
|
}
|
|
3974
3476
|
function getSourceRepositoryPath(flintPath, name) {
|
|
3975
|
-
return
|
|
3477
|
+
return join82(getSourceRepositoriesDir(flintPath), name);
|
|
3976
3478
|
}
|
|
3977
3479
|
async function cloneSourceRepository(flintPath, name, url) {
|
|
3978
3480
|
const repositoriesDir = getSourceRepositoriesDir(flintPath);
|
|
3979
|
-
await
|
|
3481
|
+
await mkdir6(repositoriesDir, { recursive: true });
|
|
3980
3482
|
const repoPath = getSourceRepositoryPath(flintPath, name);
|
|
3981
3483
|
if (await pathExists2(repoPath)) {
|
|
3982
3484
|
throw new Error(`Source repository folder already exists: ${repoPath}`);
|
|
3983
3485
|
}
|
|
3984
3486
|
try {
|
|
3985
|
-
await
|
|
3487
|
+
await execAsync2(`git clone --depth 1 "${url}" "${repoPath}"`);
|
|
3986
3488
|
} catch (error) {
|
|
3987
3489
|
const message = error instanceof Error ? error.message : String(error);
|
|
3988
3490
|
throw new Error(`Failed to clone source repository: ${message}`);
|
|
3989
3491
|
}
|
|
3990
|
-
const gitDir =
|
|
3492
|
+
const gitDir = join82(repoPath, ".git");
|
|
3991
3493
|
try {
|
|
3992
|
-
await
|
|
3494
|
+
await rm22(gitDir, { recursive: true, force: true });
|
|
3993
3495
|
} catch {
|
|
3994
3496
|
}
|
|
3995
3497
|
return repoPath;
|
|
@@ -3999,7 +3501,7 @@ async function removeSourceRepositoryFolder(flintPath, name) {
|
|
|
3999
3501
|
if (!await pathExists2(repoPath)) {
|
|
4000
3502
|
return false;
|
|
4001
3503
|
}
|
|
4002
|
-
await
|
|
3504
|
+
await rm22(repoPath, { recursive: true, force: true });
|
|
4003
3505
|
return true;
|
|
4004
3506
|
}
|
|
4005
3507
|
async function updateSourceRepository(flintPath, name, url) {
|
|
@@ -4022,12 +3524,12 @@ async function getSourceRepositoryStatus(flintPath) {
|
|
|
4022
3524
|
return statuses;
|
|
4023
3525
|
}
|
|
4024
3526
|
function getStatePath(flintPath) {
|
|
4025
|
-
return
|
|
3527
|
+
return join92(getFlintConfigDir(flintPath), "references.json");
|
|
4026
3528
|
}
|
|
4027
3529
|
async function readReferencesState(flintPath) {
|
|
4028
3530
|
const statePath = getStatePath(flintPath);
|
|
4029
3531
|
try {
|
|
4030
|
-
const content = await
|
|
3532
|
+
const content = await readFile42(statePath, "utf-8");
|
|
4031
3533
|
const parsed = JSON.parse(content);
|
|
4032
3534
|
if (parsed.version === 2) {
|
|
4033
3535
|
return parsed;
|
|
@@ -4040,8 +3542,8 @@ async function readReferencesState(flintPath) {
|
|
|
4040
3542
|
async function writeReferencesState(flintPath, state) {
|
|
4041
3543
|
const statePath = getStatePath(flintPath);
|
|
4042
3544
|
const dir = getFlintConfigDir(flintPath);
|
|
4043
|
-
await
|
|
4044
|
-
await
|
|
3545
|
+
await mkdir7(dir, { recursive: true });
|
|
3546
|
+
await writeFile52(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
4045
3547
|
}
|
|
4046
3548
|
async function getCodebaseDeclarations(flintPath) {
|
|
4047
3549
|
const config = await readFlintToml(flintPath);
|
|
@@ -4103,7 +3605,7 @@ async function removeDeclaration(flintPath, name) {
|
|
|
4103
3605
|
}
|
|
4104
3606
|
async function pathExists22(p) {
|
|
4105
3607
|
try {
|
|
4106
|
-
await
|
|
3608
|
+
await stat52(p);
|
|
4107
3609
|
return true;
|
|
4108
3610
|
} catch {
|
|
4109
3611
|
return false;
|
|
@@ -4159,7 +3661,7 @@ async function unfulfill(flintPath, name) {
|
|
|
4159
3661
|
state.flints = state.flints.filter((f) => f.name.toLowerCase() !== name.toLowerCase());
|
|
4160
3662
|
await writeReferencesState(flintPath, state);
|
|
4161
3663
|
}
|
|
4162
|
-
async function
|
|
3664
|
+
async function resolve2(flintPath, type, name) {
|
|
4163
3665
|
const state = await readReferencesState(flintPath);
|
|
4164
3666
|
const normalized = name.toLowerCase();
|
|
4165
3667
|
if (type === "codebase") {
|
|
@@ -4262,29 +3764,29 @@ async function autoFulfillFlints(flintPath) {
|
|
|
4262
3764
|
return { fulfilled, failed };
|
|
4263
3765
|
}
|
|
4264
3766
|
function getReferencesMetadataDir(flintPath) {
|
|
4265
|
-
return
|
|
3767
|
+
return join92(flintPath, "Mesh", "Metadata", "References");
|
|
4266
3768
|
}
|
|
4267
3769
|
function getCodebaseMetadataDir(flintPath) {
|
|
4268
|
-
return
|
|
3770
|
+
return join92(flintPath, "Mesh", "Metadata", "References", "Codebase");
|
|
4269
3771
|
}
|
|
4270
3772
|
function getFlintMetadataDir(flintPath) {
|
|
4271
|
-
return
|
|
3773
|
+
return join92(flintPath, "Mesh", "Metadata", "References", "Flints");
|
|
4272
3774
|
}
|
|
4273
3775
|
function getCodebaseMetadataPath(flintPath, name) {
|
|
4274
3776
|
const { snake } = nameFormats(name);
|
|
4275
|
-
return
|
|
3777
|
+
return join92(getCodebaseMetadataDir(flintPath), `rf-cb-${snake}.md`);
|
|
4276
3778
|
}
|
|
4277
3779
|
function getFlintMetadataPath(flintPath, name) {
|
|
4278
3780
|
const { snake } = nameFormats(name);
|
|
4279
|
-
return
|
|
3781
|
+
return join92(getFlintMetadataDir(flintPath), `rf-fl-${snake}.md`);
|
|
4280
3782
|
}
|
|
4281
3783
|
async function ensureReferenceMetadataDirs(flintPath) {
|
|
4282
|
-
await
|
|
4283
|
-
await
|
|
3784
|
+
await mkdir7(getCodebaseMetadataDir(flintPath), { recursive: true });
|
|
3785
|
+
await mkdir7(getFlintMetadataDir(flintPath), { recursive: true });
|
|
4284
3786
|
}
|
|
4285
3787
|
async function extractMetadataPreserved(filePath) {
|
|
4286
3788
|
try {
|
|
4287
|
-
const content = await
|
|
3789
|
+
const content = await readFile42(filePath, "utf-8");
|
|
4288
3790
|
const idMatch = content.match(/^id:\s*(.+)$/m);
|
|
4289
3791
|
const id = idMatch ? idMatch[1].trim() : randomUUID22();
|
|
4290
3792
|
const notesMatch = content.match(/## Notes\n([\s\S]*)$/);
|
|
@@ -4311,11 +3813,11 @@ Execute \`flint resolve codebase "${name}"\` to get the local path.
|
|
|
4311
3813
|
${notes}
|
|
4312
3814
|
`;
|
|
4313
3815
|
try {
|
|
4314
|
-
const existing = await
|
|
3816
|
+
const existing = await readFile42(filePath, "utf-8");
|
|
4315
3817
|
if (existing === content) return false;
|
|
4316
3818
|
} catch {
|
|
4317
3819
|
}
|
|
4318
|
-
await
|
|
3820
|
+
await writeFile52(filePath, content);
|
|
4319
3821
|
return true;
|
|
4320
3822
|
}
|
|
4321
3823
|
async function generateFlintMetadata(flintPath, name) {
|
|
@@ -4335,11 +3837,11 @@ Execute \`flint resolve flint "${name}"\` to get the local path.
|
|
|
4335
3837
|
${notes}
|
|
4336
3838
|
`;
|
|
4337
3839
|
try {
|
|
4338
|
-
const existing = await
|
|
3840
|
+
const existing = await readFile42(filePath, "utf-8");
|
|
4339
3841
|
if (existing === content) return false;
|
|
4340
3842
|
} catch {
|
|
4341
3843
|
}
|
|
4342
|
-
await
|
|
3844
|
+
await writeFile52(filePath, content);
|
|
4343
3845
|
return true;
|
|
4344
3846
|
}
|
|
4345
3847
|
async function syncReferenceMetadata(flintPath) {
|
|
@@ -4367,14 +3869,14 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4367
3869
|
}
|
|
4368
3870
|
}
|
|
4369
3871
|
const removed = [];
|
|
4370
|
-
const { readdir:
|
|
3872
|
+
const { readdir: readdir9 } = await import("fs/promises");
|
|
4371
3873
|
try {
|
|
4372
3874
|
const cbDir = getCodebaseMetadataDir(flintPath);
|
|
4373
|
-
const files = await
|
|
3875
|
+
const files = await readdir9(cbDir);
|
|
4374
3876
|
const declaredSnakes = new Set(codebaseDecls.map((d) => `rf-cb-${nameFormats(d.name).snake}.md`));
|
|
4375
3877
|
for (const file of files) {
|
|
4376
3878
|
if (file.startsWith("rf-cb-") && !declaredSnakes.has(file)) {
|
|
4377
|
-
await
|
|
3879
|
+
await rm32(join92(cbDir, file)).catch(() => {
|
|
4378
3880
|
});
|
|
4379
3881
|
removed.push(file.replace(".md", ""));
|
|
4380
3882
|
}
|
|
@@ -4383,11 +3885,11 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4383
3885
|
}
|
|
4384
3886
|
try {
|
|
4385
3887
|
const flDir = getFlintMetadataDir(flintPath);
|
|
4386
|
-
const files = await
|
|
3888
|
+
const files = await readdir9(flDir);
|
|
4387
3889
|
const declaredSnakes = new Set(flintDecls.map((d) => `rf-fl-${nameFormats(d.name).snake}.md`));
|
|
4388
3890
|
for (const file of files) {
|
|
4389
3891
|
if (file.startsWith("rf-fl-") && !declaredSnakes.has(file)) {
|
|
4390
|
-
await
|
|
3892
|
+
await rm32(join92(flDir, file)).catch(() => {
|
|
4391
3893
|
});
|
|
4392
3894
|
removed.push(file.replace(".md", ""));
|
|
4393
3895
|
}
|
|
@@ -4396,7 +3898,7 @@ async function syncReferenceMetadata(flintPath) {
|
|
|
4396
3898
|
}
|
|
4397
3899
|
return { created, removed, unchanged };
|
|
4398
3900
|
}
|
|
4399
|
-
var execFileAsync =
|
|
3901
|
+
var execFileAsync = promisify3(execFile);
|
|
4400
3902
|
var TINDERBOX_CONFIG_FILENAME = "tinderbox.toml";
|
|
4401
3903
|
function isRecord(value) {
|
|
4402
3904
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -4414,7 +3916,7 @@ function isDirectionalConnection(value) {
|
|
|
4414
3916
|
return "from" in value && "to" in value;
|
|
4415
3917
|
}
|
|
4416
3918
|
function getConfigPath(root) {
|
|
4417
|
-
return
|
|
3919
|
+
return join102(root, TINDERBOX_CONFIG_FILENAME);
|
|
4418
3920
|
}
|
|
4419
3921
|
function getTinderboxFlintMode(declaration) {
|
|
4420
3922
|
if (declaration.mode) {
|
|
@@ -4427,7 +3929,7 @@ function getTinderboxFolderName(name) {
|
|
|
4427
3929
|
}
|
|
4428
3930
|
async function pathExists3(path) {
|
|
4429
3931
|
try {
|
|
4430
|
-
await
|
|
3932
|
+
await stat62(path);
|
|
4431
3933
|
return true;
|
|
4432
3934
|
} catch {
|
|
4433
3935
|
return false;
|
|
@@ -4474,7 +3976,7 @@ function formatTinderboxToml(config) {
|
|
|
4474
3976
|
`;
|
|
4475
3977
|
}
|
|
4476
3978
|
async function writeTinderboxToml(root, config) {
|
|
4477
|
-
await
|
|
3979
|
+
await writeFile6(getConfigPath(root), formatTinderboxToml(config));
|
|
4478
3980
|
}
|
|
4479
3981
|
function parseTinderboxToml(content) {
|
|
4480
3982
|
const parsed = parse(content);
|
|
@@ -4543,7 +4045,7 @@ function parseTinderboxToml(content) {
|
|
|
4543
4045
|
};
|
|
4544
4046
|
}
|
|
4545
4047
|
async function readTinderboxToml(root) {
|
|
4546
|
-
const content = await
|
|
4048
|
+
const content = await readFile52(getConfigPath(root), "utf-8");
|
|
4547
4049
|
const config = parseTinderboxToml(content);
|
|
4548
4050
|
await validateTinderboxToml(root, config);
|
|
4549
4051
|
return config;
|
|
@@ -4552,7 +4054,7 @@ async function validateTinderboxToml(root, config) {
|
|
|
4552
4054
|
if (!config.tinderbox.name.trim()) {
|
|
4553
4055
|
throw new Error("Invalid tinderbox.toml: [tinderbox].name must be a non-empty string");
|
|
4554
4056
|
}
|
|
4555
|
-
if (await pathExists3(
|
|
4057
|
+
if (await pathExists3(join102(root, "flint.toml"))) {
|
|
4556
4058
|
throw new Error("Invalid tinderbox root: the tinderbox root must not also be a Flint");
|
|
4557
4059
|
}
|
|
4558
4060
|
if (!config.flints.required.length) {
|
|
@@ -4624,17 +4126,17 @@ function resolveTinderboxConnections(config) {
|
|
|
4624
4126
|
return edges;
|
|
4625
4127
|
}
|
|
4626
4128
|
async function findTinderboxRoot(startPath) {
|
|
4627
|
-
let current =
|
|
4628
|
-
const home =
|
|
4129
|
+
let current = resolve3(startPath);
|
|
4130
|
+
const home = resolve3(homedir2());
|
|
4629
4131
|
try {
|
|
4630
|
-
const currentStat = await
|
|
4132
|
+
const currentStat = await stat62(current);
|
|
4631
4133
|
if (!currentStat.isDirectory()) {
|
|
4632
4134
|
current = dirname3(current);
|
|
4633
4135
|
}
|
|
4634
4136
|
} catch {
|
|
4635
4137
|
current = dirname3(current);
|
|
4636
4138
|
}
|
|
4637
|
-
let currentDevice = (await
|
|
4139
|
+
let currentDevice = (await stat62(current)).dev;
|
|
4638
4140
|
while (true) {
|
|
4639
4141
|
if (await pathExists3(getConfigPath(current))) {
|
|
4640
4142
|
return current;
|
|
@@ -4643,7 +4145,7 @@ async function findTinderboxRoot(startPath) {
|
|
|
4643
4145
|
if (current === parent || current === home) {
|
|
4644
4146
|
return null;
|
|
4645
4147
|
}
|
|
4646
|
-
const parentStat = await
|
|
4148
|
+
const parentStat = await stat62(parent);
|
|
4647
4149
|
if (parentStat.dev !== currentDevice) {
|
|
4648
4150
|
return null;
|
|
4649
4151
|
}
|
|
@@ -4652,13 +4154,13 @@ async function findTinderboxRoot(startPath) {
|
|
|
4652
4154
|
}
|
|
4653
4155
|
}
|
|
4654
4156
|
async function scanTinderboxFlints(root) {
|
|
4655
|
-
const entries = await
|
|
4157
|
+
const entries = await readdir32(root, { withFileTypes: true });
|
|
4656
4158
|
const flints = [];
|
|
4657
4159
|
for (const entry of entries) {
|
|
4658
4160
|
if (!entry.isDirectory()) continue;
|
|
4659
4161
|
if (entry.name.startsWith(".")) continue;
|
|
4660
|
-
const flintPath =
|
|
4661
|
-
if (!await pathExists3(
|
|
4162
|
+
const flintPath = join102(root, entry.name);
|
|
4163
|
+
if (!await pathExists3(join102(flintPath, "flint.toml"))) {
|
|
4662
4164
|
continue;
|
|
4663
4165
|
}
|
|
4664
4166
|
const config = await readFlintToml(flintPath);
|
|
@@ -4688,8 +4190,8 @@ async function reconcileTinderbox(root, config) {
|
|
|
4688
4190
|
matched.push({ declaration, actual });
|
|
4689
4191
|
continue;
|
|
4690
4192
|
}
|
|
4691
|
-
const expectedPath =
|
|
4692
|
-
if (await pathExists3(
|
|
4193
|
+
const expectedPath = join102(root, getTinderboxFolderName(declaration.name));
|
|
4194
|
+
if (await pathExists3(join102(expectedPath, "flint.toml"))) {
|
|
4693
4195
|
const expectedConfig = await readFlintToml(expectedPath);
|
|
4694
4196
|
const actualName = expectedConfig?.flint?.name;
|
|
4695
4197
|
if (actualName && actualName !== declaration.name) {
|
|
@@ -4698,10 +4200,10 @@ async function reconcileTinderbox(root, config) {
|
|
|
4698
4200
|
actual: {
|
|
4699
4201
|
name: actualName,
|
|
4700
4202
|
path: expectedPath,
|
|
4701
|
-
folderName:
|
|
4203
|
+
folderName: basename2(expectedPath)
|
|
4702
4204
|
}
|
|
4703
4205
|
});
|
|
4704
|
-
renamedPaths.add(
|
|
4206
|
+
renamedPaths.add(resolve3(expectedPath));
|
|
4705
4207
|
continue;
|
|
4706
4208
|
}
|
|
4707
4209
|
}
|
|
@@ -4714,14 +4216,14 @@ async function reconcileTinderbox(root, config) {
|
|
|
4714
4216
|
if (ownedNames.has(flint.name)) {
|
|
4715
4217
|
return false;
|
|
4716
4218
|
}
|
|
4717
|
-
return !renamedPaths.has(
|
|
4219
|
+
return !renamedPaths.has(resolve3(flint.path));
|
|
4718
4220
|
});
|
|
4719
4221
|
return { matched, undeclared, missing, renamed };
|
|
4720
4222
|
}
|
|
4721
4223
|
function buildFlintEntry(path, name, toml) {
|
|
4722
4224
|
const entry = {
|
|
4723
4225
|
name,
|
|
4724
|
-
path:
|
|
4226
|
+
path: resolve3(path),
|
|
4725
4227
|
source: "local"
|
|
4726
4228
|
};
|
|
4727
4229
|
if (toml?.flint.tags?.length) {
|
|
@@ -4737,7 +4239,7 @@ async function syncRegistryForFlint(flint) {
|
|
|
4737
4239
|
const entry = buildFlintEntry(flint.path, flint.name, toml);
|
|
4738
4240
|
const byPath = await findFlintByPath(flint.path);
|
|
4739
4241
|
if (byPath) {
|
|
4740
|
-
if (byPath.name === entry.name &&
|
|
4242
|
+
if (byPath.name === entry.name && resolve3(byPath.path) === entry.path) {
|
|
4741
4243
|
return false;
|
|
4742
4244
|
}
|
|
4743
4245
|
await updateFlintEntry(byPath.path, entry);
|
|
@@ -4745,7 +4247,7 @@ async function syncRegistryForFlint(flint) {
|
|
|
4745
4247
|
}
|
|
4746
4248
|
const byName = await findFlintByName(flint.name);
|
|
4747
4249
|
if (byName) {
|
|
4748
|
-
if (
|
|
4250
|
+
if (resolve3(byName.path) === entry.path) {
|
|
4749
4251
|
return false;
|
|
4750
4252
|
}
|
|
4751
4253
|
await updateFlintEntry(byName.path, entry);
|
|
@@ -4766,11 +4268,11 @@ var REQUIRED_FLINT_DIRS = [
|
|
|
4766
4268
|
];
|
|
4767
4269
|
async function ensureFlintStructure(flintPath) {
|
|
4768
4270
|
for (const dir of REQUIRED_FLINT_DIRS) {
|
|
4769
|
-
await
|
|
4271
|
+
await mkdir8(join102(flintPath, dir), { recursive: true });
|
|
4770
4272
|
}
|
|
4771
4273
|
}
|
|
4772
4274
|
async function materializeGitFlint(root, declaration) {
|
|
4773
|
-
const tempPath =
|
|
4275
|
+
const tempPath = join102(root, `.tinderbox-clone-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`);
|
|
4774
4276
|
try {
|
|
4775
4277
|
await execFileAsync("git", ["clone", declaration.source, tempPath]);
|
|
4776
4278
|
const config = await readFlintToml(tempPath);
|
|
@@ -4781,7 +4283,7 @@ async function materializeGitFlint(root, declaration) {
|
|
|
4781
4283
|
if (actualName !== declaration.name) {
|
|
4782
4284
|
throw new Error(`Cloned Flint name "${actualName}" does not match declared name "${declaration.name}"`);
|
|
4783
4285
|
}
|
|
4784
|
-
const destination =
|
|
4286
|
+
const destination = join102(root, getTinderboxFolderName(actualName));
|
|
4785
4287
|
if (await pathExists3(destination)) {
|
|
4786
4288
|
throw new Error(`Destination already exists: ${destination}`);
|
|
4787
4289
|
}
|
|
@@ -4790,11 +4292,11 @@ async function materializeGitFlint(root, declaration) {
|
|
|
4790
4292
|
return {
|
|
4791
4293
|
name: actualName,
|
|
4792
4294
|
path: destination,
|
|
4793
|
-
folderName:
|
|
4295
|
+
folderName: basename2(destination)
|
|
4794
4296
|
};
|
|
4795
4297
|
} finally {
|
|
4796
4298
|
if (await pathExists3(tempPath)) {
|
|
4797
|
-
await
|
|
4299
|
+
await rm42(tempPath, { recursive: true, force: true });
|
|
4798
4300
|
}
|
|
4799
4301
|
}
|
|
4800
4302
|
}
|
|
@@ -4816,7 +4318,7 @@ async function resolveDeclaredFlints(root, config, reconciliation) {
|
|
|
4816
4318
|
path: actual.path,
|
|
4817
4319
|
available: true,
|
|
4818
4320
|
presentInRoot: true,
|
|
4819
|
-
registered: !!registryEntry &&
|
|
4321
|
+
registered: !!registryEntry && resolve3(registryEntry.path) === resolve3(actual.path)
|
|
4820
4322
|
});
|
|
4821
4323
|
continue;
|
|
4822
4324
|
}
|
|
@@ -4915,7 +4417,7 @@ async function wireTinderboxConnections(config, resolvedFlints) {
|
|
|
4915
4417
|
}
|
|
4916
4418
|
const state = await readReferencesState(from.path);
|
|
4917
4419
|
const existing = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
4918
|
-
const isCurrent = !!existing &&
|
|
4420
|
+
const isCurrent = !!existing && resolve3(existing.path) === resolve3(to.path) && await pathExists3(existing.path);
|
|
4919
4421
|
if (!isCurrent) {
|
|
4920
4422
|
await fulfillFlint(from.path, edge.to, to.path);
|
|
4921
4423
|
changed = true;
|
|
@@ -4946,7 +4448,7 @@ async function syncTinderbox(root) {
|
|
|
4946
4448
|
try {
|
|
4947
4449
|
const existingEntry = await findFlintByName(declaration.name);
|
|
4948
4450
|
if (existingEntry && await pathExists3(existingEntry.path)) {
|
|
4949
|
-
const destination =
|
|
4451
|
+
const destination = join102(root, getTinderboxFolderName(declaration.name));
|
|
4950
4452
|
const moveResult = await moveFlint(existingEntry.path, destination);
|
|
4951
4453
|
moved.push({ name: declaration.name, from: moveResult.from, to: moveResult.to });
|
|
4952
4454
|
continue;
|
|
@@ -5009,7 +4511,7 @@ async function getConnectionDrift(config, resolvedFlints) {
|
|
|
5009
4511
|
const state = await readReferencesState(from.path);
|
|
5010
4512
|
const declarationExists = declarations.some((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5011
4513
|
const fulfillment = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5012
|
-
const fulfillmentValid = !!fulfillment &&
|
|
4514
|
+
const fulfillmentValid = !!fulfillment && resolve3(fulfillment.path) === resolve3(to.path) && await pathExists3(fulfillment.path);
|
|
5013
4515
|
if (!declarationExists || !fulfillmentValid) {
|
|
5014
4516
|
drift.push({
|
|
5015
4517
|
from: edge.from,
|
|
@@ -5029,7 +4531,7 @@ async function checkTinderbox(root) {
|
|
|
5029
4531
|
const staleRegistry = [];
|
|
5030
4532
|
for (const flint of discovered) {
|
|
5031
4533
|
const entry = await findFlintByName(flint.name);
|
|
5032
|
-
if (!entry ||
|
|
4534
|
+
if (!entry || resolve3(entry.path) !== resolve3(flint.path)) {
|
|
5033
4535
|
staleRegistry.push({
|
|
5034
4536
|
name: flint.name,
|
|
5035
4537
|
actualPath: flint.path,
|
|
@@ -5096,7 +4598,7 @@ async function getTinderboxStatus(root) {
|
|
|
5096
4598
|
for (const edge of expectedEdges) {
|
|
5097
4599
|
const target = resolvedByName.get(edge.to);
|
|
5098
4600
|
const fulfillment = state.flints.find((entry) => entry.name.toLowerCase() === edge.to.toLowerCase());
|
|
5099
|
-
if (target?.available && target.path && fulfillment &&
|
|
4601
|
+
if (target?.available && target.path && fulfillment && resolve3(fulfillment.path) === resolve3(target.path) && await pathExists3(fulfillment.path)) {
|
|
5100
4602
|
connectionsFulfilled++;
|
|
5101
4603
|
}
|
|
5102
4604
|
}
|
|
@@ -5137,20 +4639,20 @@ async function setTinderboxIdentity(root, name) {
|
|
|
5137
4639
|
return { applied, failed };
|
|
5138
4640
|
}
|
|
5139
4641
|
async function countFiles(path) {
|
|
5140
|
-
const stats = await
|
|
4642
|
+
const stats = await stat62(path);
|
|
5141
4643
|
if (!stats.isDirectory()) {
|
|
5142
4644
|
return 1;
|
|
5143
4645
|
}
|
|
5144
|
-
const entries = await
|
|
4646
|
+
const entries = await readdir32(path, { withFileTypes: true });
|
|
5145
4647
|
let count = 1;
|
|
5146
4648
|
for (const entry of entries) {
|
|
5147
|
-
count += await countFiles(
|
|
4649
|
+
count += await countFiles(join102(path, entry.name));
|
|
5148
4650
|
}
|
|
5149
4651
|
return count;
|
|
5150
4652
|
}
|
|
5151
4653
|
async function resolveMoveSource(nameOrPath) {
|
|
5152
|
-
const directPath =
|
|
5153
|
-
if (await pathExists3(
|
|
4654
|
+
const directPath = resolve3(nameOrPath);
|
|
4655
|
+
if (await pathExists3(join102(directPath, "flint.toml"))) {
|
|
5154
4656
|
const config = await readFlintToml(directPath);
|
|
5155
4657
|
const name = config?.flint?.name;
|
|
5156
4658
|
if (!name) {
|
|
@@ -5162,23 +4664,23 @@ async function resolveMoveSource(nameOrPath) {
|
|
|
5162
4664
|
if (!entry) {
|
|
5163
4665
|
throw new Error(`Flint not found: ${nameOrPath}`);
|
|
5164
4666
|
}
|
|
5165
|
-
return { path:
|
|
4667
|
+
return { path: resolve3(entry.path), name: entry.name };
|
|
5166
4668
|
}
|
|
5167
4669
|
async function moveFlint(nameOrPath, destination, options = {}) {
|
|
5168
4670
|
const source = await resolveMoveSource(nameOrPath);
|
|
5169
|
-
const targetPath =
|
|
4671
|
+
const targetPath = resolve3(destination);
|
|
5170
4672
|
const targetParent = dirname3(targetPath);
|
|
5171
4673
|
if (!await pathExists3(targetParent)) {
|
|
5172
4674
|
throw new Error(`Destination parent does not exist: ${targetParent}`);
|
|
5173
4675
|
}
|
|
5174
|
-
if (
|
|
4676
|
+
if (resolve3(source.path) === targetPath) {
|
|
5175
4677
|
throw new Error(`Destination is the same as source: ${targetPath}`);
|
|
5176
4678
|
}
|
|
5177
4679
|
if (await pathExists3(targetPath)) {
|
|
5178
4680
|
if (!options.force) {
|
|
5179
4681
|
throw new Error(`Destination already exists: ${targetPath}`);
|
|
5180
4682
|
}
|
|
5181
|
-
await
|
|
4683
|
+
await rm42(targetPath, { recursive: true, force: true });
|
|
5182
4684
|
}
|
|
5183
4685
|
let crossDevice = false;
|
|
5184
4686
|
try {
|
|
@@ -5195,10 +4697,10 @@ async function moveFlint(nameOrPath, destination, options = {}) {
|
|
|
5195
4697
|
countFiles(targetPath)
|
|
5196
4698
|
]);
|
|
5197
4699
|
if (sourceCount !== destinationCount) {
|
|
5198
|
-
await
|
|
4700
|
+
await rm42(targetPath, { recursive: true, force: true });
|
|
5199
4701
|
throw new Error("Cross-device move verification failed");
|
|
5200
4702
|
}
|
|
5201
|
-
await
|
|
4703
|
+
await rm42(source.path, { recursive: true, force: true });
|
|
5202
4704
|
}
|
|
5203
4705
|
const config = await readFlintToml(targetPath);
|
|
5204
4706
|
const entry = buildFlintEntry(targetPath, config?.flint?.name ?? source.name, config);
|
|
@@ -5221,12 +4723,12 @@ async function moveFlint(nameOrPath, destination, options = {}) {
|
|
|
5221
4723
|
async function removeTinderboxFlint(flint) {
|
|
5222
4724
|
const entry = await findFlintByPath(flint.path);
|
|
5223
4725
|
if (entry) {
|
|
5224
|
-
const { unregisterFlint: unregisterFlint2 } = await import("./registry-
|
|
4726
|
+
const { unregisterFlint: unregisterFlint2 } = await import("./registry-5CNUVQN3-MXXC35UE.js");
|
|
5225
4727
|
await unregisterFlint2(entry.path);
|
|
5226
4728
|
}
|
|
5227
|
-
await
|
|
4729
|
+
await rm42(flint.path, { recursive: true, force: true });
|
|
5228
4730
|
}
|
|
5229
|
-
var
|
|
4731
|
+
var execAsync3 = promisify4(exec3);
|
|
5230
4732
|
function normalizeManifest(raw, context) {
|
|
5231
4733
|
const { repos, ...rest } = raw;
|
|
5232
4734
|
if (repos !== void 0) {
|
|
@@ -5292,7 +4794,7 @@ async function resolveShardSource(source, flintPath, version) {
|
|
|
5292
4794
|
return cloneAndResolve(url, source, version);
|
|
5293
4795
|
}
|
|
5294
4796
|
case "path": {
|
|
5295
|
-
const resolvedPath = isAbsolute2(source.path) ? source.path :
|
|
4797
|
+
const resolvedPath = isAbsolute2(source.path) ? source.path : resolve4(flintPath, source.path);
|
|
5296
4798
|
if (!await exists(resolvedPath)) {
|
|
5297
4799
|
throw new Error(`Shard path does not exist: ${resolvedPath}`);
|
|
5298
4800
|
}
|
|
@@ -5310,15 +4812,15 @@ async function resolveShardSource(source, flintPath, version) {
|
|
|
5310
4812
|
}
|
|
5311
4813
|
}
|
|
5312
4814
|
async function cloneAndResolve(url, source, version) {
|
|
5313
|
-
const tempDir = await mkdtemp(
|
|
4815
|
+
const tempDir = await mkdtemp(join112(tmpdir(), "flint-shard-"));
|
|
5314
4816
|
try {
|
|
5315
4817
|
const branchArgs = version ? `--branch v${version}` : "";
|
|
5316
|
-
await
|
|
4818
|
+
await execAsync3(`git clone --depth 1 ${branchArgs} ${url} "${tempDir}"`, {
|
|
5317
4819
|
timeout: 6e4
|
|
5318
4820
|
// 60 second timeout
|
|
5319
4821
|
});
|
|
5320
4822
|
} catch (err) {
|
|
5321
|
-
await
|
|
4823
|
+
await rm52(tempDir, { recursive: true, force: true });
|
|
5322
4824
|
const message = err instanceof Error ? err.message : String(err);
|
|
5323
4825
|
if (version && message.includes("not found")) {
|
|
5324
4826
|
throw new Error(`Version v${version} not found for shard. Check available versions with: flint shard versions <name>`);
|
|
@@ -5327,7 +4829,7 @@ async function cloneAndResolve(url, source, version) {
|
|
|
5327
4829
|
}
|
|
5328
4830
|
const manifest = await readManifest(tempDir);
|
|
5329
4831
|
if (!manifest) {
|
|
5330
|
-
await
|
|
4832
|
+
await rm52(tempDir, { recursive: true, force: true });
|
|
5331
4833
|
throw new Error(`No shard.yaml found in cloned repository: ${url}`);
|
|
5332
4834
|
}
|
|
5333
4835
|
return {
|
|
@@ -5338,11 +4840,11 @@ async function cloneAndResolve(url, source, version) {
|
|
|
5338
4840
|
};
|
|
5339
4841
|
}
|
|
5340
4842
|
async function readManifest(dir) {
|
|
5341
|
-
const yamlPath =
|
|
4843
|
+
const yamlPath = join112(dir, "shard.yaml");
|
|
5342
4844
|
try {
|
|
5343
|
-
const content = await
|
|
4845
|
+
const content = await readFile6(yamlPath, "utf-8");
|
|
5344
4846
|
return normalizeManifest(
|
|
5345
|
-
|
|
4847
|
+
parseYaml2(content),
|
|
5346
4848
|
yamlPath
|
|
5347
4849
|
);
|
|
5348
4850
|
} catch {
|
|
@@ -5351,15 +4853,15 @@ async function readManifest(dir) {
|
|
|
5351
4853
|
}
|
|
5352
4854
|
async function cleanupResolvedSource(resolved) {
|
|
5353
4855
|
if (resolved.isTemp) {
|
|
5354
|
-
await
|
|
4856
|
+
await rm52(resolved.path, { recursive: true, force: true });
|
|
5355
4857
|
}
|
|
5356
4858
|
}
|
|
5357
4859
|
async function listRemoteVersionTags(source) {
|
|
5358
4860
|
const url = `https://github.com/${source.owner}/${source.repo}.git`;
|
|
5359
4861
|
try {
|
|
5360
|
-
const { stdout } = await
|
|
4862
|
+
const { stdout } = await execAsync3(`git ls-remote --tags ${url}`, { timeout: 3e4 });
|
|
5361
4863
|
const tags = [];
|
|
5362
|
-
for (const line of stdout.trim().split(
|
|
4864
|
+
for (const line of stdout.trim().split(/\r?\n/)) {
|
|
5363
4865
|
if (!line) continue;
|
|
5364
4866
|
const ref = line.split(" ")[1];
|
|
5365
4867
|
if (!ref) continue;
|
|
@@ -5400,7 +4902,7 @@ async function fetchRemoteShardVersion(source) {
|
|
|
5400
4902
|
return null;
|
|
5401
4903
|
}
|
|
5402
4904
|
const content = await response.text();
|
|
5403
|
-
const manifest =
|
|
4905
|
+
const manifest = parseYaml2(content);
|
|
5404
4906
|
return manifest?.version ?? null;
|
|
5405
4907
|
} catch {
|
|
5406
4908
|
if (attempt === 0) {
|
|
@@ -5424,11 +4926,11 @@ function normalizeManifest2(raw, context) {
|
|
|
5424
4926
|
};
|
|
5425
4927
|
}
|
|
5426
4928
|
function getShardVersionStatePath(flintPath, shardName) {
|
|
5427
|
-
return
|
|
4929
|
+
return join12(getFlintConfigDir(flintPath), "shards", `${shardName}.json`);
|
|
5428
4930
|
}
|
|
5429
4931
|
async function readShardVersionState(flintPath, shardName) {
|
|
5430
4932
|
try {
|
|
5431
|
-
const content = await
|
|
4933
|
+
const content = await readFile7(getShardVersionStatePath(flintPath, shardName), "utf-8");
|
|
5432
4934
|
return JSON.parse(content);
|
|
5433
4935
|
} catch {
|
|
5434
4936
|
return null;
|
|
@@ -5440,14 +4942,14 @@ async function getRecordedShardVersion(flintPath, shardName) {
|
|
|
5440
4942
|
}
|
|
5441
4943
|
async function recordShardVersion(flintPath, shardName, version) {
|
|
5442
4944
|
const statePath = getShardVersionStatePath(flintPath, shardName);
|
|
5443
|
-
await
|
|
4945
|
+
await mkdir9(dirname4(statePath), { recursive: true });
|
|
5444
4946
|
const state = {
|
|
5445
4947
|
version: 1,
|
|
5446
4948
|
shard: shardName,
|
|
5447
4949
|
currentVersion: version,
|
|
5448
4950
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
5449
4951
|
};
|
|
5450
|
-
await
|
|
4952
|
+
await writeFile7(statePath, JSON.stringify(state, null, 2) + "\n");
|
|
5451
4953
|
}
|
|
5452
4954
|
async function getDependencyWarnings(flintPath, manifest) {
|
|
5453
4955
|
if (!manifest.dependencies?.length) return [];
|
|
@@ -5469,12 +4971,12 @@ async function getDependencyWarnings(flintPath, manifest) {
|
|
|
5469
4971
|
return warnings;
|
|
5470
4972
|
}
|
|
5471
4973
|
async function copyDir2(src, dest, skip = []) {
|
|
5472
|
-
await
|
|
5473
|
-
const entries = await
|
|
4974
|
+
await mkdir9(dest, { recursive: true });
|
|
4975
|
+
const entries = await readdir42(src, { withFileTypes: true });
|
|
5474
4976
|
for (const entry of entries) {
|
|
5475
4977
|
if (skip.includes(entry.name)) continue;
|
|
5476
|
-
const srcPath =
|
|
5477
|
-
const destPath =
|
|
4978
|
+
const srcPath = join12(src, entry.name);
|
|
4979
|
+
const destPath = join12(dest, entry.name);
|
|
5478
4980
|
if (entry.isDirectory()) {
|
|
5479
4981
|
await copyDir2(srcPath, destPath, skip);
|
|
5480
4982
|
} else {
|
|
@@ -5483,12 +4985,12 @@ async function copyDir2(src, dest, skip = []) {
|
|
|
5483
4985
|
}
|
|
5484
4986
|
}
|
|
5485
4987
|
async function createShardStateFile(flintPath, name, shorthand) {
|
|
5486
|
-
const stateDir =
|
|
5487
|
-
const statePath =
|
|
4988
|
+
const stateDir = join12(flintPath, "Mesh", "Shards");
|
|
4989
|
+
const statePath = join12(stateDir, `(Shard) ${name}.md`);
|
|
5488
4990
|
if (await exists(statePath)) {
|
|
5489
4991
|
return false;
|
|
5490
4992
|
}
|
|
5491
|
-
await
|
|
4993
|
+
await mkdir9(stateDir, { recursive: true });
|
|
5492
4994
|
const content = `---
|
|
5493
4995
|
id: ${randomUUID32()}
|
|
5494
4996
|
tags:
|
|
@@ -5500,7 +5002,7 @@ shard: ${shorthand}
|
|
|
5500
5002
|
|
|
5501
5003
|
State for the ${name} shard.
|
|
5502
5004
|
`;
|
|
5503
|
-
await
|
|
5005
|
+
await writeFile7(statePath, content);
|
|
5504
5006
|
return true;
|
|
5505
5007
|
}
|
|
5506
5008
|
function processTemplate(content) {
|
|
@@ -5515,10 +5017,10 @@ function extractIdFromFrontmatter(content) {
|
|
|
5515
5017
|
return idMatch?.[1]?.trim() ?? null;
|
|
5516
5018
|
}
|
|
5517
5019
|
async function detectMigrations(shardPath, shorthand, fromVersion, toVersion) {
|
|
5518
|
-
const migrationsDir =
|
|
5020
|
+
const migrationsDir = join12(shardPath, "migrations");
|
|
5519
5021
|
if (!await exists(migrationsDir)) return [];
|
|
5520
5022
|
try {
|
|
5521
|
-
const entries = await
|
|
5023
|
+
const entries = await readdir42(migrationsDir, { withFileTypes: true });
|
|
5522
5024
|
const prefix = `mig-${shorthand}-`;
|
|
5523
5025
|
const allMigrations = [];
|
|
5524
5026
|
for (const entry of entries) {
|
|
@@ -5550,11 +5052,11 @@ async function detectMigrations(shardPath, shorthand, fromVersion, toVersion) {
|
|
|
5550
5052
|
}
|
|
5551
5053
|
}
|
|
5552
5054
|
async function readShardManifest(shardPath) {
|
|
5553
|
-
const yamlPath =
|
|
5055
|
+
const yamlPath = join12(shardPath, "shard.yaml");
|
|
5554
5056
|
try {
|
|
5555
|
-
const content = await
|
|
5057
|
+
const content = await readFile7(yamlPath, "utf-8");
|
|
5556
5058
|
return normalizeManifest2(
|
|
5557
|
-
|
|
5059
|
+
parseYaml3(content),
|
|
5558
5060
|
yamlPath
|
|
5559
5061
|
);
|
|
5560
5062
|
} catch {
|
|
@@ -5562,14 +5064,14 @@ async function readShardManifest(shardPath) {
|
|
|
5562
5064
|
}
|
|
5563
5065
|
}
|
|
5564
5066
|
async function applyShardManifestContent(flintPath, sourcePath, manifest, options = {}) {
|
|
5565
|
-
const resolvedFlintPath =
|
|
5067
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5566
5068
|
let foldersCreated = 0;
|
|
5567
5069
|
let filesInstalled = 0;
|
|
5568
5070
|
let stateCreated = false;
|
|
5569
5071
|
if (manifest.folders?.length) {
|
|
5570
5072
|
for (const folder of manifest.folders) {
|
|
5571
|
-
const folderPath =
|
|
5572
|
-
const resolvedFolderPath =
|
|
5073
|
+
const folderPath = join12(flintPath, folder);
|
|
5074
|
+
const resolvedFolderPath = resolve5(folderPath);
|
|
5573
5075
|
if (!resolvedFolderPath.startsWith(resolvedFlintPath)) {
|
|
5574
5076
|
console.warn(`Skipping folder outside flint: ${folder}`);
|
|
5575
5077
|
continue;
|
|
@@ -5577,15 +5079,15 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5577
5079
|
if (!await exists(folderPath)) {
|
|
5578
5080
|
foldersCreated++;
|
|
5579
5081
|
}
|
|
5580
|
-
await
|
|
5082
|
+
await mkdir9(folderPath, { recursive: true });
|
|
5581
5083
|
}
|
|
5582
5084
|
}
|
|
5583
5085
|
if (manifest.install?.length) {
|
|
5584
|
-
const installFolderPath =
|
|
5086
|
+
const installFolderPath = join12(sourcePath, "install");
|
|
5585
5087
|
for (const entry of manifest.install) {
|
|
5586
|
-
const srcFilePath =
|
|
5587
|
-
const destFilePath =
|
|
5588
|
-
const resolvedDestFilePath =
|
|
5088
|
+
const srcFilePath = join12(installFolderPath, entry.source);
|
|
5089
|
+
const destFilePath = join12(flintPath, entry.dest);
|
|
5090
|
+
const resolvedDestFilePath = resolve5(destFilePath);
|
|
5589
5091
|
if (!resolvedDestFilePath.startsWith(resolvedFlintPath)) {
|
|
5590
5092
|
console.warn(`Skipping file outside flint: ${entry.dest}`);
|
|
5591
5093
|
continue;
|
|
@@ -5598,7 +5100,7 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5598
5100
|
}
|
|
5599
5101
|
let content;
|
|
5600
5102
|
try {
|
|
5601
|
-
content = await
|
|
5103
|
+
content = await readFile7(srcFilePath, "utf-8");
|
|
5602
5104
|
} catch {
|
|
5603
5105
|
console.warn(`Failed to read install file: ${entry.source}`);
|
|
5604
5106
|
continue;
|
|
@@ -5606,7 +5108,7 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5606
5108
|
let existingId = null;
|
|
5607
5109
|
if (await exists(destFilePath)) {
|
|
5608
5110
|
try {
|
|
5609
|
-
const existingContent = await
|
|
5111
|
+
const existingContent = await readFile7(destFilePath, "utf-8");
|
|
5610
5112
|
existingId = extractIdFromFrontmatter(existingContent);
|
|
5611
5113
|
} catch {
|
|
5612
5114
|
}
|
|
@@ -5615,8 +5117,8 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5615
5117
|
if (existingId) {
|
|
5616
5118
|
content = content.replace(/^(id:\s*)[a-f0-9-]{36}/m, `$1${existingId}`);
|
|
5617
5119
|
}
|
|
5618
|
-
await
|
|
5619
|
-
await
|
|
5120
|
+
await mkdir9(dirname4(destFilePath), { recursive: true });
|
|
5121
|
+
await writeFile7(destFilePath, content);
|
|
5620
5122
|
filesInstalled++;
|
|
5621
5123
|
}
|
|
5622
5124
|
}
|
|
@@ -5626,16 +5128,16 @@ async function applyShardManifestContent(flintPath, sourcePath, manifest, option
|
|
|
5626
5128
|
return { foldersCreated, filesInstalled, stateCreated };
|
|
5627
5129
|
}
|
|
5628
5130
|
async function installShardFromSource(flintPath, sourcePath, manifest, options = {}) {
|
|
5629
|
-
const destPath =
|
|
5630
|
-
const resolvedFlintPath =
|
|
5631
|
-
const resolvedDestPath =
|
|
5131
|
+
const destPath = join12(flintPath, "Shards", manifest.name);
|
|
5132
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5133
|
+
const resolvedDestPath = resolve5(destPath);
|
|
5632
5134
|
if (!resolvedDestPath.startsWith(resolvedFlintPath)) {
|
|
5633
5135
|
throw new Error("Invalid shard path: outside flint directory");
|
|
5634
5136
|
}
|
|
5635
|
-
await
|
|
5636
|
-
await
|
|
5637
|
-
const shardYamlSrc =
|
|
5638
|
-
const shardYamlDest =
|
|
5137
|
+
await rm62(destPath, { recursive: true, force: true });
|
|
5138
|
+
await mkdir9(destPath, { recursive: true });
|
|
5139
|
+
const shardYamlSrc = join12(sourcePath, "shard.yaml");
|
|
5140
|
+
const shardYamlDest = join12(destPath, "shard.yaml");
|
|
5639
5141
|
if (await exists(shardYamlSrc)) {
|
|
5640
5142
|
await copyFile(shardYamlSrc, shardYamlDest);
|
|
5641
5143
|
}
|
|
@@ -5652,23 +5154,23 @@ async function installShardFromSource(flintPath, sourcePath, manifest, options =
|
|
|
5652
5154
|
return { name: manifest.name, path: destPath };
|
|
5653
5155
|
}
|
|
5654
5156
|
async function listInstalledShards(flintPath) {
|
|
5655
|
-
const shardsPath =
|
|
5157
|
+
const shardsPath = join12(flintPath, "Shards");
|
|
5656
5158
|
try {
|
|
5657
|
-
const entries = await
|
|
5159
|
+
const entries = await readdir42(shardsPath, { withFileTypes: true });
|
|
5658
5160
|
return entries.filter((e) => e.isDirectory() && !e.name.startsWith("(System)")).map((e) => e.name);
|
|
5659
5161
|
} catch {
|
|
5660
5162
|
return [];
|
|
5661
5163
|
}
|
|
5662
5164
|
}
|
|
5663
5165
|
async function getInstalledShardsWithVersions(flintPath) {
|
|
5664
|
-
const shardsPath =
|
|
5166
|
+
const shardsPath = join12(flintPath, "Shards");
|
|
5665
5167
|
const results = [];
|
|
5666
5168
|
try {
|
|
5667
|
-
const entries = await
|
|
5169
|
+
const entries = await readdir42(shardsPath, { withFileTypes: true });
|
|
5668
5170
|
const folders = entries.filter((e) => e.isDirectory() && !e.name.startsWith("(System)")).map((e) => e.name);
|
|
5669
5171
|
for (const folder of folders) {
|
|
5670
5172
|
try {
|
|
5671
|
-
const manifest = await readShardManifest(
|
|
5173
|
+
const manifest = await readShardManifest(join12(shardsPath, folder));
|
|
5672
5174
|
if (!manifest?.name || !manifest.shorthand || !manifest.version) {
|
|
5673
5175
|
continue;
|
|
5674
5176
|
}
|
|
@@ -5718,7 +5220,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5718
5220
|
if (pinnedVersion && pinnedVersion === info.version && !options.reinstall) {
|
|
5719
5221
|
return {
|
|
5720
5222
|
name: info.folderName,
|
|
5721
|
-
path:
|
|
5223
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5722
5224
|
status: "skipped",
|
|
5723
5225
|
localVersion: info.version,
|
|
5724
5226
|
remoteVersion: pinnedVersion,
|
|
@@ -5731,7 +5233,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5731
5233
|
if (remoteVersion && compareVersions(remoteVersion, info.version) <= 0) {
|
|
5732
5234
|
return {
|
|
5733
5235
|
name: info.folderName,
|
|
5734
|
-
path:
|
|
5236
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5735
5237
|
status: "skipped",
|
|
5736
5238
|
localVersion: info.version,
|
|
5737
5239
|
remoteVersion,
|
|
@@ -5742,7 +5244,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5742
5244
|
if (!source || !isGitHubSourceSpecifier(source)) {
|
|
5743
5245
|
return {
|
|
5744
5246
|
name: info.folderName,
|
|
5745
|
-
path:
|
|
5247
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5746
5248
|
status: "skipped",
|
|
5747
5249
|
localVersion: info.version,
|
|
5748
5250
|
reason: "no source configured"
|
|
@@ -5755,7 +5257,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5755
5257
|
} catch {
|
|
5756
5258
|
return {
|
|
5757
5259
|
name: info.folderName,
|
|
5758
|
-
path:
|
|
5260
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5759
5261
|
status: "failed",
|
|
5760
5262
|
localVersion: info.version,
|
|
5761
5263
|
reason: "failed to resolve source"
|
|
@@ -5767,7 +5269,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5767
5269
|
source,
|
|
5768
5270
|
version: pinnedVersion
|
|
5769
5271
|
});
|
|
5770
|
-
const shardPath =
|
|
5272
|
+
const shardPath = join12(flintPath, "Shards", info.folderName);
|
|
5771
5273
|
const shorthand = resolved.manifest.shorthand || info.shorthand;
|
|
5772
5274
|
const migrations2 = await detectMigrations(
|
|
5773
5275
|
shardPath,
|
|
@@ -5777,7 +5279,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5777
5279
|
);
|
|
5778
5280
|
return {
|
|
5779
5281
|
name: info.folderName,
|
|
5780
|
-
path:
|
|
5282
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5781
5283
|
status: "updated",
|
|
5782
5284
|
localVersion: info.version,
|
|
5783
5285
|
remoteVersion: resolved.manifest.version,
|
|
@@ -5787,7 +5289,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5787
5289
|
} catch {
|
|
5788
5290
|
return {
|
|
5789
5291
|
name: info.folderName,
|
|
5790
|
-
path:
|
|
5292
|
+
path: join12(flintPath, "Shards", info.folderName),
|
|
5791
5293
|
status: "failed",
|
|
5792
5294
|
localVersion: info.version,
|
|
5793
5295
|
reason: "failed to install from source"
|
|
@@ -5797,7 +5299,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5797
5299
|
}
|
|
5798
5300
|
}
|
|
5799
5301
|
}));
|
|
5800
|
-
const { runConcurrent: runConcurrent2 } = await import("./utils-BBA2XQZO-
|
|
5302
|
+
const { runConcurrent: runConcurrent2 } = await import("./utils-BBA2XQZO-Q2LR5RQU.js");
|
|
5801
5303
|
const concurrentResults = await runConcurrent2(updateTasks, {
|
|
5802
5304
|
concurrency: 5,
|
|
5803
5305
|
onStart: options.onStart,
|
|
@@ -5809,7 +5311,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5809
5311
|
if (r.status === "error") {
|
|
5810
5312
|
results.push({
|
|
5811
5313
|
name: r.name,
|
|
5812
|
-
path:
|
|
5314
|
+
path: join12(flintPath, "Shards", r.name),
|
|
5813
5315
|
status: "failed",
|
|
5814
5316
|
localVersion: "",
|
|
5815
5317
|
reason: r.error?.message || "Unknown error"
|
|
@@ -5825,7 +5327,7 @@ async function updateShards(flintPath, options = {}) {
|
|
|
5825
5327
|
}
|
|
5826
5328
|
async function isDirectoryEmpty(dirPath) {
|
|
5827
5329
|
try {
|
|
5828
|
-
const entries = await
|
|
5330
|
+
const entries = await readdir42(dirPath);
|
|
5829
5331
|
return entries.length === 0;
|
|
5830
5332
|
} catch {
|
|
5831
5333
|
return true;
|
|
@@ -5839,23 +5341,23 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5839
5341
|
throw new Error(`Shard "${identifier}" is not installed.`);
|
|
5840
5342
|
}
|
|
5841
5343
|
const shardName = matchingFolder;
|
|
5842
|
-
const shardPath =
|
|
5344
|
+
const shardPath = join12(flintPath, "Shards", matchingFolder);
|
|
5843
5345
|
const folderExists = await exists(shardPath);
|
|
5844
5346
|
if (!folderExists) {
|
|
5845
5347
|
throw new Error(`Shard "${shardName}" is not installed.`);
|
|
5846
5348
|
}
|
|
5847
|
-
const resolvedFlintPath =
|
|
5349
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5848
5350
|
const manifest = await readShardManifest(shardPath);
|
|
5849
5351
|
if (manifest) {
|
|
5850
5352
|
if (manifest.install?.length) {
|
|
5851
5353
|
for (const entry of manifest.install) {
|
|
5852
|
-
const filePath =
|
|
5853
|
-
const resolvedFilePath =
|
|
5354
|
+
const filePath = join12(flintPath, entry.dest);
|
|
5355
|
+
const resolvedFilePath = resolve5(filePath);
|
|
5854
5356
|
if (!resolvedFilePath.startsWith(resolvedFlintPath)) {
|
|
5855
5357
|
continue;
|
|
5856
5358
|
}
|
|
5857
5359
|
try {
|
|
5858
|
-
await
|
|
5360
|
+
await rm62(filePath, { force: true });
|
|
5859
5361
|
} catch {
|
|
5860
5362
|
}
|
|
5861
5363
|
}
|
|
@@ -5863,8 +5365,8 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5863
5365
|
if (manifest.folders?.length) {
|
|
5864
5366
|
const sortedFolders = [...manifest.folders].sort((a, b) => b.length - a.length);
|
|
5865
5367
|
for (const folder of sortedFolders) {
|
|
5866
|
-
const folderPath =
|
|
5867
|
-
const resolvedFolderPath =
|
|
5368
|
+
const folderPath = join12(flintPath, folder);
|
|
5369
|
+
const resolvedFolderPath = resolve5(folderPath);
|
|
5868
5370
|
if (!resolvedFolderPath.startsWith(resolvedFlintPath)) {
|
|
5869
5371
|
continue;
|
|
5870
5372
|
}
|
|
@@ -5877,11 +5379,11 @@ async function uninstallShard(flintPath, identifier) {
|
|
|
5877
5379
|
}
|
|
5878
5380
|
}
|
|
5879
5381
|
}
|
|
5880
|
-
const resolvedShardPath =
|
|
5382
|
+
const resolvedShardPath = resolve5(shardPath);
|
|
5881
5383
|
if (!resolvedShardPath.startsWith(resolvedFlintPath)) {
|
|
5882
5384
|
throw new Error(`Invalid shard path: outside flint directory`);
|
|
5883
5385
|
}
|
|
5884
|
-
await
|
|
5386
|
+
await rm62(shardPath, { recursive: true, force: true });
|
|
5885
5387
|
await removeShardFromConfig(flintPath, shardName);
|
|
5886
5388
|
return { name: shardName, removed: true };
|
|
5887
5389
|
}
|
|
@@ -5891,11 +5393,11 @@ async function removeOrphanedShard(flintPath, kebabName) {
|
|
|
5891
5393
|
(folder) => toKebabCase(folder) === kebabName
|
|
5892
5394
|
);
|
|
5893
5395
|
if (matchingFolder) {
|
|
5894
|
-
const shardPath =
|
|
5895
|
-
const resolvedFlintPath =
|
|
5896
|
-
const resolvedShardPath =
|
|
5396
|
+
const shardPath = join12(flintPath, "Shards", matchingFolder);
|
|
5397
|
+
const resolvedFlintPath = resolve5(flintPath);
|
|
5398
|
+
const resolvedShardPath = resolve5(shardPath);
|
|
5897
5399
|
if (resolvedShardPath.startsWith(resolvedFlintPath)) {
|
|
5898
|
-
await
|
|
5400
|
+
await rm62(shardPath, { recursive: true, force: true });
|
|
5899
5401
|
}
|
|
5900
5402
|
}
|
|
5901
5403
|
return { name: kebabName, removed: true };
|
|
@@ -5915,7 +5417,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
5915
5417
|
shardFolders = await listInstalledShards(flintPath);
|
|
5916
5418
|
}
|
|
5917
5419
|
for (const folder of shardFolders) {
|
|
5918
|
-
const shardPath =
|
|
5420
|
+
const shardPath = join12(flintPath, "Shards", folder);
|
|
5919
5421
|
const manifest = await readShardManifest(shardPath);
|
|
5920
5422
|
if (!manifest) continue;
|
|
5921
5423
|
const shardName = toKebabCase(manifest.name || folder);
|
|
@@ -5951,23 +5453,23 @@ async function scaffoldNewShard(flintPath, name, shorthand, description, options
|
|
|
5951
5453
|
const shardMode = options.mode || "dev";
|
|
5952
5454
|
const prefix = shardMode === "custom" ? "(Custom)" : "(Dev)";
|
|
5953
5455
|
const folderName = `${prefix} ${name}`;
|
|
5954
|
-
const shardPath =
|
|
5456
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
5955
5457
|
if (await exists(shardPath)) {
|
|
5956
5458
|
throw new Error(`Shard already exists: ${folderName}`);
|
|
5957
5459
|
}
|
|
5958
5460
|
const dirs = [
|
|
5959
5461
|
shardPath,
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
|
|
5963
|
-
|
|
5964
|
-
|
|
5965
|
-
|
|
5966
|
-
|
|
5967
|
-
|
|
5462
|
+
join12(shardPath, "skills"),
|
|
5463
|
+
join12(shardPath, "workflows"),
|
|
5464
|
+
join12(shardPath, "templates"),
|
|
5465
|
+
join12(shardPath, "knowledge"),
|
|
5466
|
+
join12(shardPath, "assets"),
|
|
5467
|
+
join12(shardPath, "install"),
|
|
5468
|
+
join12(shardPath, "migrations"),
|
|
5469
|
+
join12(shardPath, "scripts")
|
|
5968
5470
|
];
|
|
5969
5471
|
for (const dir of dirs) {
|
|
5970
|
-
await
|
|
5472
|
+
await mkdir9(dir, { recursive: true });
|
|
5971
5473
|
}
|
|
5972
5474
|
let shardYaml = `shard-spec: "0.1.0"
|
|
5973
5475
|
version: "0.1.0"
|
|
@@ -5979,7 +5481,7 @@ description: ${description}
|
|
|
5979
5481
|
shardYaml += `state: true
|
|
5980
5482
|
`;
|
|
5981
5483
|
}
|
|
5982
|
-
await
|
|
5484
|
+
await writeFile7(join12(shardPath, "shard.yaml"), shardYaml);
|
|
5983
5485
|
const setupLine = options.setup ? ` setup-${shorthand}.md # One-time setup guide
|
|
5984
5486
|
` : "";
|
|
5985
5487
|
const readmeContent = `# ${name}
|
|
@@ -6000,7 +5502,7 @@ ${setupLine} skills/ # sk-${shorthand}-{name}.md
|
|
|
6000
5502
|
install/ # Files to install into Mesh/
|
|
6001
5503
|
\`\`\`
|
|
6002
5504
|
`;
|
|
6003
|
-
await
|
|
5505
|
+
await writeFile7(join12(shardPath, "README.md"), readmeContent);
|
|
6004
5506
|
const setupRow = options.setup ? `
|
|
6005
5507
|
| Setup | \`setup-${shorthand}.md\` | One-time setup guide |` : "";
|
|
6006
5508
|
const stateRow = options.state ? `
|
|
@@ -6031,7 +5533,7 @@ ${description}
|
|
|
6031
5533
|
|
|
6032
5534
|
(No knowledge files yet)
|
|
6033
5535
|
`;
|
|
6034
|
-
await
|
|
5536
|
+
await writeFile7(join12(shardPath, `init-${shorthand}.md`), initContent);
|
|
6035
5537
|
if (options.setup) {
|
|
6036
5538
|
const setupContent = `# Setup ${name}
|
|
6037
5539
|
|
|
@@ -6041,11 +5543,11 @@ One-time setup actions for ${name}.
|
|
|
6041
5543
|
|
|
6042
5544
|
1. (Define setup actions here)
|
|
6043
5545
|
`;
|
|
6044
|
-
await
|
|
5546
|
+
await writeFile7(join12(shardPath, `setup-${shorthand}.md`), setupContent);
|
|
6045
5547
|
}
|
|
6046
5548
|
if (options.state) {
|
|
6047
|
-
const stateDir =
|
|
6048
|
-
await
|
|
5549
|
+
const stateDir = join12(flintPath, "Mesh", "Shards");
|
|
5550
|
+
await mkdir9(stateDir, { recursive: true });
|
|
6049
5551
|
const stateContent = `---
|
|
6050
5552
|
id: ${randomUUID32()}
|
|
6051
5553
|
tags:
|
|
@@ -6057,7 +5559,7 @@ shard: ${shorthand}
|
|
|
6057
5559
|
|
|
6058
5560
|
State for the ${name} shard.
|
|
6059
5561
|
`;
|
|
6060
|
-
await
|
|
5562
|
+
await writeFile7(join12(stateDir, `(Shard) ${name}.md`), stateContent);
|
|
6061
5563
|
}
|
|
6062
5564
|
if (shardMode === "dev") {
|
|
6063
5565
|
const { execSync: execSync2 } = await import("child_process");
|
|
@@ -6069,7 +5571,7 @@ State for the ${name} shard.
|
|
|
6069
5571
|
}
|
|
6070
5572
|
async function cloneShardToDev(flintPath, sourcePath, manifest) {
|
|
6071
5573
|
const devFolderName = `(Dev) ${manifest.name}`;
|
|
6072
|
-
const devPath =
|
|
5574
|
+
const devPath = join12(flintPath, "Shards", devFolderName);
|
|
6073
5575
|
if (await exists(devPath)) {
|
|
6074
5576
|
await addShardToConfig(flintPath, devFolderName, `path:./Shards/${devFolderName}`, { mode: "dev" });
|
|
6075
5577
|
await recordShardVersion(flintPath, toKebabCase(manifest.name), manifest.version);
|
|
@@ -6081,7 +5583,7 @@ async function cloneShardToDev(flintPath, sourcePath, manifest) {
|
|
|
6081
5583
|
return { name: devFolderName, path: devPath };
|
|
6082
5584
|
}
|
|
6083
5585
|
async function registerExistingShard(flintPath, folderName) {
|
|
6084
|
-
const shardPath =
|
|
5586
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6085
5587
|
if (!await exists(shardPath)) {
|
|
6086
5588
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6087
5589
|
}
|
|
@@ -6103,7 +5605,7 @@ async function registerExistingShard(flintPath, folderName) {
|
|
|
6103
5605
|
async function editShard(flintPath, folderName, source) {
|
|
6104
5606
|
const { execSync: execSync2 } = await import("child_process");
|
|
6105
5607
|
const { rename: rename42 } = await import("fs/promises");
|
|
6106
|
-
const shardPath =
|
|
5608
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6107
5609
|
if (!await exists(shardPath)) {
|
|
6108
5610
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6109
5611
|
}
|
|
@@ -6115,21 +5617,21 @@ async function editShard(flintPath, folderName, source) {
|
|
|
6115
5617
|
}
|
|
6116
5618
|
const baseName = folderName.replace(/^\([^)]*\)\s*/, "");
|
|
6117
5619
|
const devFolderName = `(Dev) ${baseName}`;
|
|
6118
|
-
const devPath =
|
|
5620
|
+
const devPath = join12(flintPath, "Shards", devFolderName);
|
|
6119
5621
|
if (await exists(devPath)) {
|
|
6120
5622
|
throw new Error(`Dev folder already exists: Shards/${devFolderName}`);
|
|
6121
5623
|
}
|
|
6122
5624
|
await rename42(shardPath, devPath);
|
|
6123
5625
|
if (isGitHubSourceSpecifier(source)) {
|
|
6124
|
-
const tmpDir =
|
|
5626
|
+
const tmpDir = join12(flintPath, ".flint", "_tmp_edit_" + Date.now());
|
|
6125
5627
|
try {
|
|
6126
5628
|
const parsed = parseShardSource(source);
|
|
6127
5629
|
execSync2(`git clone --depth 1 "https://github.com/${parsed.owner}/${parsed.repo}.git" "${tmpDir}"`, { stdio: "pipe", timeout: 6e4 });
|
|
6128
|
-
await copyDir2(
|
|
5630
|
+
await copyDir2(join12(tmpDir, ".git"), join12(devPath, ".git"));
|
|
6129
5631
|
} catch {
|
|
6130
5632
|
execSync2("git init", { cwd: devPath, stdio: "pipe" });
|
|
6131
5633
|
} finally {
|
|
6132
|
-
await
|
|
5634
|
+
await rm62(tmpDir, { recursive: true, force: true });
|
|
6133
5635
|
}
|
|
6134
5636
|
} else {
|
|
6135
5637
|
execSync2("git init", { cwd: devPath, stdio: "pipe" });
|
|
@@ -6142,14 +5644,14 @@ async function editShard(flintPath, folderName, source) {
|
|
|
6142
5644
|
async function freezeShard(flintPath, folderName) {
|
|
6143
5645
|
const { execSync: execSync2 } = await import("child_process");
|
|
6144
5646
|
const { rename: rename42 } = await import("fs/promises");
|
|
6145
|
-
const shardPath =
|
|
5647
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6146
5648
|
if (!await exists(shardPath)) {
|
|
6147
5649
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6148
5650
|
}
|
|
6149
5651
|
if (!folderName.startsWith("(Dev)")) {
|
|
6150
5652
|
throw new Error(`"${folderName}" is not a dev shard.`);
|
|
6151
5653
|
}
|
|
6152
|
-
const gitDir =
|
|
5654
|
+
const gitDir = join12(shardPath, ".git");
|
|
6153
5655
|
if (!await exists(gitDir)) {
|
|
6154
5656
|
throw new Error(`"${folderName}" has no .git directory.`);
|
|
6155
5657
|
}
|
|
@@ -6177,11 +5679,11 @@ async function freezeShard(flintPath, folderName) {
|
|
|
6177
5679
|
const decl = declarations[kebab];
|
|
6178
5680
|
const source = decl?.source || "";
|
|
6179
5681
|
const baseName = folderName.replace(/^\(Dev\)\s*/, "");
|
|
6180
|
-
const normalPath =
|
|
5682
|
+
const normalPath = join12(flintPath, "Shards", baseName);
|
|
6181
5683
|
if (await exists(normalPath)) {
|
|
6182
5684
|
throw new Error(`Normal folder already exists: Shards/${baseName}`);
|
|
6183
5685
|
}
|
|
6184
|
-
await
|
|
5686
|
+
await rm62(gitDir, { recursive: true, force: true });
|
|
6185
5687
|
await rename42(shardPath, normalPath);
|
|
6186
5688
|
await removeShardFromConfig(flintPath, kebab);
|
|
6187
5689
|
const normalSource = isGitHubSourceSpecifier(source) ? source : `path:./Shards/${baseName}`;
|
|
@@ -6190,14 +5692,14 @@ async function freezeShard(flintPath, folderName) {
|
|
|
6190
5692
|
}
|
|
6191
5693
|
async function addShardGitRemote(flintPath, folderName, url) {
|
|
6192
5694
|
const { execSync: execSync2 } = await import("child_process");
|
|
6193
|
-
const shardPath =
|
|
5695
|
+
const shardPath = join12(flintPath, "Shards", folderName);
|
|
6194
5696
|
if (!await exists(shardPath)) {
|
|
6195
5697
|
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
6196
5698
|
}
|
|
6197
5699
|
if (!folderName.startsWith("(Dev)")) {
|
|
6198
5700
|
throw new Error(`"${folderName}" is not a dev shard. Only dev shards can have git remotes added.`);
|
|
6199
5701
|
}
|
|
6200
|
-
const gitDir =
|
|
5702
|
+
const gitDir = join12(shardPath, ".git");
|
|
6201
5703
|
if (!await exists(gitDir)) {
|
|
6202
5704
|
throw new Error(`"${folderName}" has no .git directory. Run git init first.`);
|
|
6203
5705
|
}
|
|
@@ -6236,7 +5738,7 @@ async function installDependency(flintPath, source, version) {
|
|
|
6236
5738
|
}
|
|
6237
5739
|
async function countFiles2(dirPath) {
|
|
6238
5740
|
try {
|
|
6239
|
-
const entries = await
|
|
5741
|
+
const entries = await readdir52(dirPath, { withFileTypes: true });
|
|
6240
5742
|
return entries.filter((e) => e.isFile() && e.name.endsWith(".md")).length;
|
|
6241
5743
|
} catch {
|
|
6242
5744
|
return 0;
|
|
@@ -6250,7 +5752,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6250
5752
|
for (const folder of installedFolders) {
|
|
6251
5753
|
const kebab = toKebabCase(folder);
|
|
6252
5754
|
if (!declaredKebabNames.has(kebab)) {
|
|
6253
|
-
const shardPath =
|
|
5755
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6254
5756
|
const manifest = await readShardManifest(shardPath);
|
|
6255
5757
|
if (manifest?.name && manifest?.shorthand) {
|
|
6256
5758
|
const detectedMode = folder.startsWith("(Custom)") ? "custom" : "dev";
|
|
@@ -6276,7 +5778,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6276
5778
|
for (const [name, decl] of Object.entries(declarations)) {
|
|
6277
5779
|
if (decl.source.startsWith("path:")) {
|
|
6278
5780
|
const relativePath = decl.source.slice(5);
|
|
6279
|
-
const fullPath =
|
|
5781
|
+
const fullPath = join13(flintPath, relativePath);
|
|
6280
5782
|
if (!await exists(fullPath)) {
|
|
6281
5783
|
results.push({
|
|
6282
5784
|
check: `${name} (${decl.source})`,
|
|
@@ -6293,7 +5795,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6293
5795
|
for (const [name, decl] of Object.entries(declarations)) {
|
|
6294
5796
|
if (decl.source.startsWith("path:") && resolveShardMode(decl) === "dev") {
|
|
6295
5797
|
const relativePath = decl.source.slice(5);
|
|
6296
|
-
const fullPath =
|
|
5798
|
+
const fullPath = join13(flintPath, relativePath);
|
|
6297
5799
|
if (await exists(fullPath)) {
|
|
6298
5800
|
const remoteUrl = getGitRemoteUrl(fullPath);
|
|
6299
5801
|
if (remoteUrl) {
|
|
@@ -6316,7 +5818,7 @@ async function checkShardHealth(flintPath) {
|
|
|
6316
5818
|
}
|
|
6317
5819
|
}
|
|
6318
5820
|
for (const folder of installedFolders) {
|
|
6319
|
-
const shardPath =
|
|
5821
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6320
5822
|
const manifest = await readShardManifest(shardPath);
|
|
6321
5823
|
if (!manifest) {
|
|
6322
5824
|
results.push({
|
|
@@ -6332,7 +5834,7 @@ name: ${name}
|
|
|
6332
5834
|
shorthand: ${shorthand}
|
|
6333
5835
|
description: ${name} shard
|
|
6334
5836
|
`;
|
|
6335
|
-
await
|
|
5837
|
+
await writeFile8(join13(shardPath, "shard.yaml"), yaml);
|
|
6336
5838
|
},
|
|
6337
5839
|
actionLabel: `Create minimal shard.yaml for ${folder}`
|
|
6338
5840
|
});
|
|
@@ -6351,21 +5853,21 @@ description: ${name} shard
|
|
|
6351
5853
|
const SHARD_SPEC_DIRS_CONSUMER = ["skills", "workflows", "templates", "knowledge"];
|
|
6352
5854
|
const SHARD_SPEC_DIRS_DEV = [...SHARD_SPEC_DIRS_CONSUMER, "assets", "install", "migrations", "scripts"];
|
|
6353
5855
|
for (const folder of installedFolders) {
|
|
6354
|
-
const shardPath =
|
|
5856
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6355
5857
|
const manifest = await readShardManifest(shardPath);
|
|
6356
5858
|
const kebab = toKebabCase(folder);
|
|
6357
5859
|
const decl = declarations[kebab];
|
|
6358
5860
|
const mode = decl ? resolveShardMode(decl) : void 0;
|
|
6359
5861
|
const expectedDirs = mode === "dev" ? SHARD_SPEC_DIRS_DEV : SHARD_SPEC_DIRS_CONSUMER;
|
|
6360
5862
|
for (const dir of expectedDirs) {
|
|
6361
|
-
const dirPath =
|
|
5863
|
+
const dirPath = join13(shardPath, dir);
|
|
6362
5864
|
if (!await exists(dirPath)) {
|
|
6363
5865
|
results.push({
|
|
6364
5866
|
check: `Shards/${folder}/${dir}/`,
|
|
6365
5867
|
status: "warning",
|
|
6366
5868
|
message: "Missing shard-spec directory",
|
|
6367
5869
|
action: async () => {
|
|
6368
|
-
await
|
|
5870
|
+
await mkdir10(dirPath, { recursive: true });
|
|
6369
5871
|
},
|
|
6370
5872
|
actionLabel: `Create ${dir}/ in ${folder}`
|
|
6371
5873
|
});
|
|
@@ -6375,7 +5877,7 @@ description: ${name} shard
|
|
|
6375
5877
|
const installedWithVersions = await getInstalledShardsWithVersions(flintPath);
|
|
6376
5878
|
const installedVersionMap = new Map(installedWithVersions.map((s) => [s.name, s.version]));
|
|
6377
5879
|
for (const folder of installedFolders) {
|
|
6378
|
-
const shardPath =
|
|
5880
|
+
const shardPath = join13(flintPath, "Shards", folder);
|
|
6379
5881
|
const manifest = await readShardManifest(shardPath);
|
|
6380
5882
|
if (!manifest?.dependencies?.length) continue;
|
|
6381
5883
|
for (const dep of manifest.dependencies) {
|
|
@@ -6430,12 +5932,13 @@ description: ${name} shard
|
|
|
6430
5932
|
}
|
|
6431
5933
|
function getGitRemoteUrl(shardPath) {
|
|
6432
5934
|
try {
|
|
6433
|
-
const gitDir =
|
|
5935
|
+
const gitDir = join13(shardPath, ".git");
|
|
6434
5936
|
if (!existsSync(gitDir)) return null;
|
|
6435
5937
|
return execSync("git remote get-url origin", {
|
|
6436
5938
|
cwd: shardPath,
|
|
6437
5939
|
encoding: "utf-8",
|
|
6438
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
5940
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
5941
|
+
windowsHide: true
|
|
6439
5942
|
}).trim() || null;
|
|
6440
5943
|
} catch {
|
|
6441
5944
|
return null;
|
|
@@ -6443,7 +5946,7 @@ function getGitRemoteUrl(shardPath) {
|
|
|
6443
5946
|
}
|
|
6444
5947
|
async function healShard(flintPath, folderName) {
|
|
6445
5948
|
const results = [];
|
|
6446
|
-
const shardPath =
|
|
5949
|
+
const shardPath = join13(flintPath, "Shards", folderName);
|
|
6447
5950
|
const kebab = toKebabCase(folderName);
|
|
6448
5951
|
const manifest = await readShardManifest(shardPath);
|
|
6449
5952
|
if (!manifest) {
|
|
@@ -6460,7 +5963,7 @@ name: ${name}
|
|
|
6460
5963
|
shorthand: ${shorthand2}
|
|
6461
5964
|
description: ${name} shard
|
|
6462
5965
|
`;
|
|
6463
|
-
await
|
|
5966
|
+
await writeFile8(join13(shardPath, "shard.yaml"), yaml);
|
|
6464
5967
|
},
|
|
6465
5968
|
actionLabel: `Create shard.yaml`
|
|
6466
5969
|
});
|
|
@@ -6524,21 +6027,21 @@ description: ${name} shard
|
|
|
6524
6027
|
const mode = decl ? resolveShardMode(decl) : void 0;
|
|
6525
6028
|
const expectedDirs = mode === "dev" ? DEV_DIRS : CONSUMER_DIRS;
|
|
6526
6029
|
for (const dir of expectedDirs) {
|
|
6527
|
-
const dirPath =
|
|
6030
|
+
const dirPath = join13(shardPath, dir);
|
|
6528
6031
|
if (!await exists(dirPath)) {
|
|
6529
6032
|
results.push({
|
|
6530
6033
|
check: `${dir}/`,
|
|
6531
6034
|
status: "warning",
|
|
6532
6035
|
message: "Missing directory",
|
|
6533
6036
|
action: async () => {
|
|
6534
|
-
await
|
|
6037
|
+
await mkdir10(dirPath, { recursive: true });
|
|
6535
6038
|
},
|
|
6536
6039
|
actionLabel: `Create ${dir}/`
|
|
6537
6040
|
});
|
|
6538
6041
|
}
|
|
6539
6042
|
}
|
|
6540
6043
|
const shorthand = manifest?.shorthand || kebab.replace(/-/g, "").slice(0, 4);
|
|
6541
|
-
const initFile =
|
|
6044
|
+
const initFile = join13(shardPath, `init-${shorthand}.md`);
|
|
6542
6045
|
if (!await exists(initFile)) {
|
|
6543
6046
|
results.push({
|
|
6544
6047
|
check: `init-${shorthand}.md`,
|
|
@@ -6550,21 +6053,21 @@ description: ${name} shard
|
|
|
6550
6053
|
|
|
6551
6054
|
Describe the shard context here.
|
|
6552
6055
|
`;
|
|
6553
|
-
await
|
|
6056
|
+
await writeFile8(initFile, content);
|
|
6554
6057
|
},
|
|
6555
6058
|
actionLabel: `Create init-${shorthand}.md`
|
|
6556
6059
|
});
|
|
6557
6060
|
}
|
|
6558
6061
|
if (manifest?.folders) {
|
|
6559
6062
|
for (const folder of manifest.folders) {
|
|
6560
|
-
const meshPath =
|
|
6063
|
+
const meshPath = join13(flintPath, folder);
|
|
6561
6064
|
if (!await exists(meshPath)) {
|
|
6562
6065
|
results.push({
|
|
6563
6066
|
check: `${folder}`,
|
|
6564
6067
|
status: "warning",
|
|
6565
6068
|
message: "Declared Mesh folder missing",
|
|
6566
6069
|
action: async () => {
|
|
6567
|
-
await
|
|
6070
|
+
await mkdir10(meshPath, { recursive: true });
|
|
6568
6071
|
},
|
|
6569
6072
|
actionLabel: `Create ${folder}`
|
|
6570
6073
|
});
|
|
@@ -6573,7 +6076,7 @@ Describe the shard context here.
|
|
|
6573
6076
|
}
|
|
6574
6077
|
const checkFilePrefix = async (dir, prefix) => {
|
|
6575
6078
|
try {
|
|
6576
|
-
const entries = await
|
|
6079
|
+
const entries = await readdir52(join13(shardPath, dir), { withFileTypes: true });
|
|
6577
6080
|
for (const entry of entries) {
|
|
6578
6081
|
if (entry.isFile() && entry.name.endsWith(".md") && !entry.name.startsWith(prefix)) {
|
|
6579
6082
|
results.push({
|
|
@@ -6588,7 +6091,7 @@ Describe the shard context here.
|
|
|
6588
6091
|
};
|
|
6589
6092
|
const checkInstallNaming = async (shorthandValue) => {
|
|
6590
6093
|
try {
|
|
6591
|
-
const entries = await
|
|
6094
|
+
const entries = await readdir52(join13(shardPath, "install"), { withFileTypes: true });
|
|
6592
6095
|
for (const entry of entries) {
|
|
6593
6096
|
if (!entry.isFile()) continue;
|
|
6594
6097
|
const expectedPrefix = entry.name.startsWith("type-") ? `type-${shorthandValue}-` : entry.name.startsWith("inst-") ? `inst-${shorthandValue}-` : null;
|
|
@@ -6639,7 +6142,7 @@ async function getShardInfo(flintPath, identifier) {
|
|
|
6639
6142
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
6640
6143
|
const match = resolveInstalledShardInfo(installed, identifier);
|
|
6641
6144
|
if (match) {
|
|
6642
|
-
const shardPath =
|
|
6145
|
+
const shardPath = join13(flintPath, "Shards", match.folderName);
|
|
6643
6146
|
const manifest = await readShardManifest(shardPath);
|
|
6644
6147
|
const decl = declarations[match.name];
|
|
6645
6148
|
return {
|
|
@@ -6651,10 +6154,10 @@ async function getShardInfo(flintPath, identifier) {
|
|
|
6651
6154
|
dev: decl ? resolveShardMode(decl) === "dev" : false,
|
|
6652
6155
|
mode: decl ? resolveShardMode(decl) || "normal" : "normal",
|
|
6653
6156
|
folderName: match.folderName,
|
|
6654
|
-
skillCount: await countFiles2(
|
|
6655
|
-
templateCount: await countFiles2(
|
|
6656
|
-
workflowCount: await countFiles2(
|
|
6657
|
-
knowledgeCount: await countFiles2(
|
|
6157
|
+
skillCount: await countFiles2(join13(shardPath, "skills")),
|
|
6158
|
+
templateCount: await countFiles2(join13(shardPath, "templates")),
|
|
6159
|
+
workflowCount: await countFiles2(join13(shardPath, "workflows")),
|
|
6160
|
+
knowledgeCount: await countFiles2(join13(shardPath, "knowledge"))
|
|
6658
6161
|
};
|
|
6659
6162
|
}
|
|
6660
6163
|
return null;
|
|
@@ -6664,7 +6167,7 @@ async function findShardFolder(flintPath, identifier) {
|
|
|
6664
6167
|
return resolveInstalledShardInfo(installed, identifier)?.folderName ?? null;
|
|
6665
6168
|
}
|
|
6666
6169
|
function getShardScriptsDir(flintPath, shardFolder) {
|
|
6667
|
-
return
|
|
6170
|
+
return join14(flintPath, "Shards", shardFolder, "scripts");
|
|
6668
6171
|
}
|
|
6669
6172
|
async function listShardScripts(flintPath, shardIdentifier) {
|
|
6670
6173
|
const shardFolder = await findShardFolder(flintPath, shardIdentifier);
|
|
@@ -6673,14 +6176,14 @@ async function listShardScripts(flintPath, shardIdentifier) {
|
|
|
6673
6176
|
}
|
|
6674
6177
|
const scriptsDir = getShardScriptsDir(flintPath, shardFolder);
|
|
6675
6178
|
try {
|
|
6676
|
-
const entries = await
|
|
6179
|
+
const entries = await readdir62(scriptsDir, { withFileTypes: true });
|
|
6677
6180
|
const scripts = [];
|
|
6678
6181
|
for (const entry of entries) {
|
|
6679
6182
|
if (entry.isFile()) {
|
|
6680
6183
|
const name = entry.name.replace(/\.[^.]+$/, "");
|
|
6681
6184
|
scripts.push({
|
|
6682
6185
|
name,
|
|
6683
|
-
path:
|
|
6186
|
+
path: join14(scriptsDir, entry.name)
|
|
6684
6187
|
});
|
|
6685
6188
|
}
|
|
6686
6189
|
}
|
|
@@ -6691,15 +6194,15 @@ async function listShardScripts(flintPath, shardIdentifier) {
|
|
|
6691
6194
|
}
|
|
6692
6195
|
async function findScript(scriptsDir, scriptName) {
|
|
6693
6196
|
try {
|
|
6694
|
-
const entries = await
|
|
6197
|
+
const entries = await readdir62(scriptsDir);
|
|
6695
6198
|
if (entries.includes(scriptName)) {
|
|
6696
|
-
return
|
|
6199
|
+
return join14(scriptsDir, scriptName);
|
|
6697
6200
|
}
|
|
6698
6201
|
const extensions = [".sh", ".js", ".ts", ".mjs", ".py", ""];
|
|
6699
6202
|
for (const ext of extensions) {
|
|
6700
6203
|
const filename = scriptName + ext;
|
|
6701
6204
|
if (entries.includes(filename)) {
|
|
6702
|
-
return
|
|
6205
|
+
return join14(scriptsDir, filename);
|
|
6703
6206
|
}
|
|
6704
6207
|
}
|
|
6705
6208
|
return null;
|
|
@@ -6749,18 +6252,19 @@ async function runShardScript(flintPath, shardIdentifier, scriptName, args = [])
|
|
|
6749
6252
|
const scriptNames = available.map((s) => s.name).join(", ");
|
|
6750
6253
|
throw new Error(`Script "${scriptName}" not found. Available: ${scriptNames}`);
|
|
6751
6254
|
}
|
|
6752
|
-
const resolvedFlintPath =
|
|
6255
|
+
const resolvedFlintPath = resolve6(flintPath);
|
|
6753
6256
|
const runner = await getScriptRunner(scriptPath);
|
|
6754
6257
|
const fullArgs = [...runner.args, ...args];
|
|
6755
|
-
return new Promise((
|
|
6756
|
-
const child =
|
|
6258
|
+
return new Promise((resolve8, reject) => {
|
|
6259
|
+
const child = spawn(runner.command, fullArgs, {
|
|
6757
6260
|
cwd: resolvedFlintPath,
|
|
6758
6261
|
env: {
|
|
6759
6262
|
...process.env,
|
|
6760
6263
|
FLINT_ROOT: resolvedFlintPath,
|
|
6761
6264
|
FLINT_SHARD: shardFolder
|
|
6762
6265
|
},
|
|
6763
|
-
stdio: ["inherit", "pipe", "pipe"]
|
|
6266
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
6267
|
+
windowsHide: true
|
|
6764
6268
|
});
|
|
6765
6269
|
let stdout = "";
|
|
6766
6270
|
let stderr = "";
|
|
@@ -6774,7 +6278,7 @@ async function runShardScript(flintPath, shardIdentifier, scriptName, args = [])
|
|
|
6774
6278
|
reject(new Error(`Failed to run script: ${err.message}`));
|
|
6775
6279
|
});
|
|
6776
6280
|
child.on("close", (code) => {
|
|
6777
|
-
|
|
6281
|
+
resolve8({
|
|
6778
6282
|
exitCode: code ?? 1,
|
|
6779
6283
|
stdout: stdout.trim(),
|
|
6780
6284
|
stderr: stderr.trim()
|
|
@@ -6848,23 +6352,23 @@ function buildSourcesEntries(config) {
|
|
|
6848
6352
|
}
|
|
6849
6353
|
async function shardHasGitRemote(shardPath) {
|
|
6850
6354
|
try {
|
|
6851
|
-
const configPath =
|
|
6852
|
-
const config = await
|
|
6355
|
+
const configPath = join15(shardPath, ".git", "config");
|
|
6356
|
+
const config = await readFile8(configPath, "utf-8");
|
|
6853
6357
|
return config.includes("[remote");
|
|
6854
6358
|
} catch {
|
|
6855
6359
|
return false;
|
|
6856
6360
|
}
|
|
6857
6361
|
}
|
|
6858
6362
|
async function buildShardEntries(flintPath) {
|
|
6859
|
-
const shardsDir =
|
|
6363
|
+
const shardsDir = join15(flintPath, "Shards");
|
|
6860
6364
|
if (!await exists(shardsDir)) return [];
|
|
6861
6365
|
const entries = [];
|
|
6862
6366
|
try {
|
|
6863
|
-
const folders = await
|
|
6367
|
+
const folders = await readdir72(shardsDir, { withFileTypes: true });
|
|
6864
6368
|
for (const folder of folders) {
|
|
6865
6369
|
if (!folder.isDirectory() || folder.name.startsWith("(System)")) continue;
|
|
6866
|
-
const gitDir =
|
|
6867
|
-
if (await exists(gitDir) && await shardHasGitRemote(
|
|
6370
|
+
const gitDir = join15(shardsDir, folder.name, ".git");
|
|
6371
|
+
if (await exists(gitDir) && await shardHasGitRemote(join15(shardsDir, folder.name))) {
|
|
6868
6372
|
entries.push(`Shards/${folder.name}/`);
|
|
6869
6373
|
}
|
|
6870
6374
|
}
|
|
@@ -6877,10 +6381,10 @@ function formatManagedContent(sections) {
|
|
|
6877
6381
|
${section.entries.join("\n")}`).join("\n\n");
|
|
6878
6382
|
}
|
|
6879
6383
|
async function createGitignore(flintPath) {
|
|
6880
|
-
const gitignorePath =
|
|
6384
|
+
const gitignorePath = join15(flintPath, ".gitignore");
|
|
6881
6385
|
const sections = await buildGitignoreEntries(flintPath);
|
|
6882
6386
|
const content = formatManagedContent(sections);
|
|
6883
|
-
await
|
|
6387
|
+
await writeFile9(
|
|
6884
6388
|
gitignorePath,
|
|
6885
6389
|
`${MANAGED_SECTION_START}
|
|
6886
6390
|
${content}
|
|
@@ -6889,10 +6393,10 @@ ${MANAGED_SECTION_END}
|
|
|
6889
6393
|
);
|
|
6890
6394
|
}
|
|
6891
6395
|
async function updateGitignore(flintPath) {
|
|
6892
|
-
const gitignorePath =
|
|
6396
|
+
const gitignorePath = join15(flintPath, ".gitignore");
|
|
6893
6397
|
let existing = "";
|
|
6894
6398
|
try {
|
|
6895
|
-
existing = await
|
|
6399
|
+
existing = await readFile8(gitignorePath, "utf-8");
|
|
6896
6400
|
} catch {
|
|
6897
6401
|
await createGitignore(flintPath);
|
|
6898
6402
|
return;
|
|
@@ -6911,15 +6415,15 @@ ${MANAGED_SECTION_END}`;
|
|
|
6911
6415
|
} else {
|
|
6912
6416
|
existing = existing.trim() + "\n\n" + managedSection + "\n";
|
|
6913
6417
|
}
|
|
6914
|
-
await
|
|
6418
|
+
await writeFile9(gitignorePath, existing.trim() + "\n");
|
|
6915
6419
|
}
|
|
6916
6420
|
function escapeRegex(str) {
|
|
6917
6421
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6918
6422
|
}
|
|
6919
|
-
var
|
|
6423
|
+
var execAsync4 = promisify5(exec4);
|
|
6920
6424
|
async function isGitInitialized(flintPath) {
|
|
6921
6425
|
try {
|
|
6922
|
-
await
|
|
6426
|
+
await execAsync4("git rev-parse --git-dir", { cwd: flintPath });
|
|
6923
6427
|
return true;
|
|
6924
6428
|
} catch {
|
|
6925
6429
|
return false;
|
|
@@ -6927,7 +6431,7 @@ async function isGitInitialized(flintPath) {
|
|
|
6927
6431
|
}
|
|
6928
6432
|
async function initGit(flintPath) {
|
|
6929
6433
|
try {
|
|
6930
|
-
await
|
|
6434
|
+
await execAsync4("git init", { cwd: flintPath });
|
|
6931
6435
|
await createGitignore(flintPath);
|
|
6932
6436
|
return { success: true, output: "Git initialized with .gitignore" };
|
|
6933
6437
|
} catch (err) {
|
|
@@ -6950,13 +6454,13 @@ async function getGitStatus(flintPath) {
|
|
|
6950
6454
|
};
|
|
6951
6455
|
}
|
|
6952
6456
|
try {
|
|
6953
|
-
const { stdout: branchOut } = await
|
|
6457
|
+
const { stdout: branchOut } = await execAsync4("git branch --show-current", {
|
|
6954
6458
|
cwd: flintPath
|
|
6955
6459
|
});
|
|
6956
|
-
const { stdout: statusOut } = await
|
|
6460
|
+
const { stdout: statusOut } = await execAsync4("git status --porcelain", {
|
|
6957
6461
|
cwd: flintPath
|
|
6958
6462
|
});
|
|
6959
|
-
const lines = statusOut.trim().split(
|
|
6463
|
+
const lines = statusOut.trim().split(/\r?\n/).filter(Boolean);
|
|
6960
6464
|
const staged = [];
|
|
6961
6465
|
const unstaged = [];
|
|
6962
6466
|
const untracked = [];
|
|
@@ -6995,7 +6499,7 @@ async function runGit(flintPath, args, options) {
|
|
|
6995
6499
|
const quotedArgs = args.map(
|
|
6996
6500
|
(arg) => arg.includes(" ") ? `"${arg}"` : arg
|
|
6997
6501
|
);
|
|
6998
|
-
const { stdout, stderr } = await
|
|
6502
|
+
const { stdout, stderr } = await execAsync4(`git ${quotedArgs.join(" ")}`, {
|
|
6999
6503
|
cwd: flintPath,
|
|
7000
6504
|
env: options?.env ? { ...process.env, ...options.env } : void 0
|
|
7001
6505
|
});
|
|
@@ -7027,7 +6531,7 @@ async function listTags(cwd, pattern) {
|
|
|
7027
6531
|
const args = pattern ? ["tag", "-l", pattern] : ["tag", "-l"];
|
|
7028
6532
|
const result = await runGit(cwd, args);
|
|
7029
6533
|
if (!result.success) return [];
|
|
7030
|
-
return result.output.trim().split(
|
|
6534
|
+
return result.output.trim().split(/\r?\n/).filter(Boolean);
|
|
7031
6535
|
}
|
|
7032
6536
|
async function pushTags(cwd, remote = "origin") {
|
|
7033
6537
|
return runGit(cwd, ["push", remote, "--tags"]);
|
|
@@ -7072,11 +6576,11 @@ async function isRebaseInProgress(cwd) {
|
|
|
7072
6576
|
async function getRebaseBranch(cwd) {
|
|
7073
6577
|
const result = await runGit(cwd, ["rev-parse", "--git-path", "rebase-merge/head-name"]);
|
|
7074
6578
|
if (result.success) {
|
|
7075
|
-
const { readFile:
|
|
6579
|
+
const { readFile: readFile10 } = await import("fs/promises");
|
|
7076
6580
|
const path = await import("path");
|
|
7077
6581
|
const headNamePath = path.resolve(cwd, result.output.trim());
|
|
7078
6582
|
try {
|
|
7079
|
-
const ref = (await
|
|
6583
|
+
const ref = (await readFile10(headNamePath, "utf-8")).trim();
|
|
7080
6584
|
return ref.replace(/^refs\/heads\//, "");
|
|
7081
6585
|
} catch {
|
|
7082
6586
|
}
|
|
@@ -7086,22 +6590,22 @@ async function getRebaseBranch(cwd) {
|
|
|
7086
6590
|
async function getConflictFiles(cwd) {
|
|
7087
6591
|
const result = await runGit(cwd, ["diff", "--name-only", "--diff-filter=U"]);
|
|
7088
6592
|
if (result.success && result.output.trim()) {
|
|
7089
|
-
return result.output.trim().split(
|
|
6593
|
+
return result.output.trim().split(/\r?\n/).filter(Boolean);
|
|
7090
6594
|
}
|
|
7091
6595
|
return [];
|
|
7092
6596
|
}
|
|
7093
6597
|
async function hasConflictMarkers(cwd, files) {
|
|
7094
|
-
const { readFile:
|
|
6598
|
+
const { readFile: readFile10 } = await import("fs/promises");
|
|
7095
6599
|
const path = await import("path");
|
|
7096
6600
|
let filesToCheck = files;
|
|
7097
6601
|
if (!filesToCheck || filesToCheck.length === 0) {
|
|
7098
6602
|
const result = await runGit(cwd, ["diff", "--name-only", "HEAD"]);
|
|
7099
6603
|
if (result.success && result.output.trim()) {
|
|
7100
|
-
filesToCheck = result.output.trim().split(
|
|
6604
|
+
filesToCheck = result.output.trim().split(/\r?\n/).filter(Boolean);
|
|
7101
6605
|
} else {
|
|
7102
6606
|
const staged = await runGit(cwd, ["diff", "--name-only", "--cached"]);
|
|
7103
6607
|
if (staged.success && staged.output.trim()) {
|
|
7104
|
-
filesToCheck = staged.output.trim().split(
|
|
6608
|
+
filesToCheck = staged.output.trim().split(/\r?\n/).filter(Boolean);
|
|
7105
6609
|
} else {
|
|
7106
6610
|
return [];
|
|
7107
6611
|
}
|
|
@@ -7110,7 +6614,7 @@ async function hasConflictMarkers(cwd, files) {
|
|
|
7110
6614
|
const conflicted = [];
|
|
7111
6615
|
for (const file of filesToCheck) {
|
|
7112
6616
|
try {
|
|
7113
|
-
const content = await
|
|
6617
|
+
const content = await readFile10(path.resolve(cwd, file), "utf-8");
|
|
7114
6618
|
if (content.includes("<<<<<<<") && content.includes("=======") && content.includes(">>>>>>>")) {
|
|
7115
6619
|
conflicted.push(file);
|
|
7116
6620
|
}
|
|
@@ -7147,10 +6651,10 @@ async function syncFlint(flintPath, progress) {
|
|
|
7147
6651
|
};
|
|
7148
6652
|
const flintConfigDir = getFlintConfigDir(flintPath);
|
|
7149
6653
|
try {
|
|
7150
|
-
await
|
|
6654
|
+
await stat72(flintConfigDir);
|
|
7151
6655
|
} catch {
|
|
7152
6656
|
try {
|
|
7153
|
-
await
|
|
6657
|
+
await mkdir11(flintConfigDir, { recursive: true });
|
|
7154
6658
|
result.bootstrap.created = true;
|
|
7155
6659
|
} catch (err) {
|
|
7156
6660
|
result.errors.push({
|
|
@@ -7160,11 +6664,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7160
6664
|
}
|
|
7161
6665
|
}
|
|
7162
6666
|
for (const dir of STANDARD_DIRECTORIES) {
|
|
7163
|
-
const dirPath =
|
|
6667
|
+
const dirPath = join16(flintPath, dir);
|
|
7164
6668
|
try {
|
|
7165
|
-
await
|
|
6669
|
+
await stat72(dirPath);
|
|
7166
6670
|
} catch {
|
|
7167
|
-
await
|
|
6671
|
+
await mkdir11(dirPath, { recursive: true });
|
|
7168
6672
|
result.bootstrap.directories.push(dir);
|
|
7169
6673
|
}
|
|
7170
6674
|
}
|
|
@@ -7183,9 +6687,9 @@ async function syncFlint(flintPath, progress) {
|
|
|
7183
6687
|
error: `Failed to sync metadata: ${err instanceof Error ? err.message : String(err)}`
|
|
7184
6688
|
});
|
|
7185
6689
|
}
|
|
7186
|
-
const obsidianDir =
|
|
6690
|
+
const obsidianDir = join16(flintPath, ".obsidian");
|
|
7187
6691
|
try {
|
|
7188
|
-
await
|
|
6692
|
+
await stat72(obsidianDir);
|
|
7189
6693
|
result.obsidian.existed = true;
|
|
7190
6694
|
} catch {
|
|
7191
6695
|
try {
|
|
@@ -7209,8 +6713,8 @@ async function syncFlint(flintPath, progress) {
|
|
|
7209
6713
|
const shardsToUninstall = installedShards.filter((s) => !requiredShardSet.has(s.name)).map((s) => s.name);
|
|
7210
6714
|
{
|
|
7211
6715
|
const { exec: execCb } = await import("child_process");
|
|
7212
|
-
const { promisify:
|
|
7213
|
-
const
|
|
6716
|
+
const { promisify: promisify6 } = await import("util");
|
|
6717
|
+
const execAsync5 = promisify6(execCb);
|
|
7214
6718
|
const shardTasks = [];
|
|
7215
6719
|
for (const kebabName of shardsToInstall) {
|
|
7216
6720
|
const declaration = shardDeclarations[kebabName];
|
|
@@ -7233,9 +6737,9 @@ async function syncFlint(flintPath, progress) {
|
|
|
7233
6737
|
throw new Error(`Dev shard source is not a GitHub source: ${source}`);
|
|
7234
6738
|
}
|
|
7235
6739
|
const folderName = `(Dev) ${kebabName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ")}`;
|
|
7236
|
-
const devPath =
|
|
6740
|
+
const devPath = join16(flintPath, "Shards", folderName);
|
|
7237
6741
|
const cloneUrl = `https://github.com/${parsed.owner}/${parsed.repo}.git`;
|
|
7238
|
-
await
|
|
6742
|
+
await execAsync5(`git clone "${cloneUrl}" "${devPath}"`, { timeout: 6e4 });
|
|
7239
6743
|
await pullShard(flintPath, folderName, { force: true });
|
|
7240
6744
|
}
|
|
7241
6745
|
});
|
|
@@ -7292,28 +6796,28 @@ async function syncFlint(flintPath, progress) {
|
|
|
7292
6796
|
}
|
|
7293
6797
|
}
|
|
7294
6798
|
const requiredMeshExports = config.sources?.meshexports || [];
|
|
7295
|
-
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-
|
|
7296
|
-
const { readdir:
|
|
7297
|
-
const { syncSourceMeshExportMetadata: syncSourceMeshExportMetadata2 } = await import("./metadata-
|
|
6799
|
+
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-5CNUVQN3-MXXC35UE.js");
|
|
6800
|
+
const { readdir: readdir9, readFile: fsReadFile, rm: rm7, stat: fsStat, mkdir: fsMkdir, copyFile: fsCopyFile } = await import("fs/promises");
|
|
6801
|
+
const { syncSourceMeshExportMetadata: syncSourceMeshExportMetadata2 } = await import("./metadata-FASTWX6A-MAAQ2YNF.js");
|
|
7298
6802
|
const requiredMeshExportSet = new Set(requiredMeshExports);
|
|
7299
|
-
const sourcesFlintDir =
|
|
6803
|
+
const sourcesFlintDir = join16(flintPath, "Sources", "Flints");
|
|
7300
6804
|
try {
|
|
7301
|
-
const flintFolders = await
|
|
6805
|
+
const flintFolders = await readdir9(sourcesFlintDir, { withFileTypes: true });
|
|
7302
6806
|
for (const flintFolder of flintFolders) {
|
|
7303
6807
|
if (!flintFolder.isDirectory()) continue;
|
|
7304
6808
|
const flintFolderName = flintFolder.name;
|
|
7305
6809
|
const flintName = flintFolderName.replace(/^\(Flint\)\s*/, "");
|
|
7306
|
-
const flintSourcePath =
|
|
7307
|
-
const exportFolders = await
|
|
6810
|
+
const flintSourcePath = join16(sourcesFlintDir, flintFolderName);
|
|
6811
|
+
const exportFolders = await readdir9(flintSourcePath, { withFileTypes: true });
|
|
7308
6812
|
for (const exportFolder of exportFolders) {
|
|
7309
6813
|
if (!exportFolder.isDirectory()) continue;
|
|
7310
6814
|
const exportFolderName = exportFolder.name;
|
|
7311
6815
|
const exportName = exportFolderName.replace(/^\(Mesh Export\)\s*/, "");
|
|
7312
6816
|
const ref = `${flintName}/${exportName}`;
|
|
7313
6817
|
if (!requiredMeshExportSet.has(ref)) {
|
|
7314
|
-
const exportPath =
|
|
6818
|
+
const exportPath = join16(flintSourcePath, exportFolderName);
|
|
7315
6819
|
try {
|
|
7316
|
-
await
|
|
6820
|
+
await rm7(exportPath, { recursive: true });
|
|
7317
6821
|
result.meshexports.push({ ref, status: "removed" });
|
|
7318
6822
|
} catch (err) {
|
|
7319
6823
|
result.meshexports.push({
|
|
@@ -7324,10 +6828,10 @@ async function syncFlint(flintPath, progress) {
|
|
|
7324
6828
|
}
|
|
7325
6829
|
}
|
|
7326
6830
|
}
|
|
7327
|
-
const remaining = await
|
|
6831
|
+
const remaining = await readdir9(flintSourcePath);
|
|
7328
6832
|
if (remaining.length === 0) {
|
|
7329
6833
|
try {
|
|
7330
|
-
await
|
|
6834
|
+
await rm7(flintSourcePath, { recursive: true });
|
|
7331
6835
|
} catch {
|
|
7332
6836
|
}
|
|
7333
6837
|
}
|
|
@@ -7336,7 +6840,7 @@ async function syncFlint(flintPath, progress) {
|
|
|
7336
6840
|
}
|
|
7337
6841
|
if (requiredMeshExports.length > 0) {
|
|
7338
6842
|
const registry = await getFlintRegistry2();
|
|
7339
|
-
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-
|
|
6843
|
+
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-OZQUMYQI-RIZGDBFL.js");
|
|
7340
6844
|
for (const ref of requiredMeshExports) {
|
|
7341
6845
|
const parts = ref.split("/");
|
|
7342
6846
|
if (parts.length !== 2) {
|
|
@@ -7353,7 +6857,7 @@ async function syncFlint(flintPath, progress) {
|
|
|
7353
6857
|
return simpleName === flintName || f.name === flintName;
|
|
7354
6858
|
});
|
|
7355
6859
|
if (!sourceFlint) {
|
|
7356
|
-
const destDir2 =
|
|
6860
|
+
const destDir2 = join16(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh Export) ${exportName}`);
|
|
7357
6861
|
try {
|
|
7358
6862
|
await fsStat(destDir2);
|
|
7359
6863
|
result.meshexports.push({ ref, status: "unavailable" });
|
|
@@ -7381,34 +6885,34 @@ async function syncFlint(flintPath, progress) {
|
|
|
7381
6885
|
});
|
|
7382
6886
|
continue;
|
|
7383
6887
|
}
|
|
7384
|
-
const exportDir =
|
|
7385
|
-
const destDir =
|
|
6888
|
+
const exportDir = join16(sourceFlint.path, "Exports", `(Mesh Export) ${exportName}`);
|
|
6889
|
+
const destDir = join16(flintPath, "Sources", "Flints", `(Flint) ${flintName}`, `(Mesh Export) ${exportName}`);
|
|
7386
6890
|
try {
|
|
7387
6891
|
try {
|
|
7388
|
-
await
|
|
6892
|
+
await rm7(destDir, { recursive: true });
|
|
7389
6893
|
} catch {
|
|
7390
6894
|
}
|
|
7391
6895
|
let fileCount = 0;
|
|
7392
|
-
const meshSourceDir =
|
|
7393
|
-
const meshDestDir =
|
|
6896
|
+
const meshSourceDir = join16(exportDir, "Mesh");
|
|
6897
|
+
const meshDestDir = join16(destDir, "Mesh");
|
|
7394
6898
|
try {
|
|
7395
6899
|
await fsStat(meshSourceDir);
|
|
7396
6900
|
await fsMkdir(meshDestDir, { recursive: true });
|
|
7397
|
-
const meshFiles = await
|
|
6901
|
+
const meshFiles = await readdir9(meshSourceDir);
|
|
7398
6902
|
for (const file of meshFiles) {
|
|
7399
|
-
await fsCopyFile(
|
|
6903
|
+
await fsCopyFile(join16(meshSourceDir, file), join16(meshDestDir, file));
|
|
7400
6904
|
fileCount++;
|
|
7401
6905
|
}
|
|
7402
6906
|
} catch {
|
|
7403
6907
|
}
|
|
7404
|
-
const mediaSourceDir =
|
|
7405
|
-
const mediaDestDir =
|
|
6908
|
+
const mediaSourceDir = join16(exportDir, "Media");
|
|
6909
|
+
const mediaDestDir = join16(destDir, "Media");
|
|
7406
6910
|
try {
|
|
7407
6911
|
await fsStat(mediaSourceDir);
|
|
7408
6912
|
await fsMkdir(mediaDestDir, { recursive: true });
|
|
7409
|
-
const mediaFiles = await
|
|
6913
|
+
const mediaFiles = await readdir9(mediaSourceDir);
|
|
7410
6914
|
for (const file of mediaFiles) {
|
|
7411
|
-
await fsCopyFile(
|
|
6915
|
+
await fsCopyFile(join16(mediaSourceDir, file), join16(mediaDestDir, file));
|
|
7412
6916
|
fileCount++;
|
|
7413
6917
|
}
|
|
7414
6918
|
} catch {
|
|
@@ -7480,10 +6984,23 @@ async function syncFlint(flintPath, progress) {
|
|
|
7480
6984
|
error: `Failed to sync source repo metadata: ${err instanceof Error ? err.message : String(err)}`
|
|
7481
6985
|
});
|
|
7482
6986
|
}
|
|
7483
|
-
const { getPlateDeclarationsFromConfig } = await import("./mesh-config-
|
|
6987
|
+
const { getPlateDeclarationsFromConfig } = await import("./mesh-config-NTGFUNZL-T5YSX3S3.js");
|
|
7484
6988
|
const plateDeclarations = getPlateDeclarationsFromConfig(config);
|
|
6989
|
+
const hasSourcePlates = Object.values(plateDeclarations).some((d) => d.source);
|
|
7485
6990
|
const hasRepoPlates = Object.values(plateDeclarations).some((d) => d.repo);
|
|
7486
|
-
if (
|
|
6991
|
+
if (hasSourcePlates) {
|
|
6992
|
+
const { syncDeclaredPlates: syncDeclaredPlates2 } = await import("./plates-4TK56CGM-6ACY6ZX6.js");
|
|
6993
|
+
const plateResults = await syncDeclaredPlates2(flintPath, plateDeclarations);
|
|
6994
|
+
result.plates = plateResults;
|
|
6995
|
+
for (const pr of plateResults) {
|
|
6996
|
+
if (pr.status === "error") {
|
|
6997
|
+
result.errors.push({
|
|
6998
|
+
name: `plate:${pr.name}`,
|
|
6999
|
+
error: pr.error || "Unknown error"
|
|
7000
|
+
});
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
7003
|
+
} else if (hasRepoPlates) {
|
|
7487
7004
|
const plateResults = await syncPlateRepos(flintPath, plateDeclarations);
|
|
7488
7005
|
result.plates = plateResults;
|
|
7489
7006
|
for (const pr of plateResults) {
|
|
@@ -7500,11 +7017,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7500
7017
|
if (tomlName) {
|
|
7501
7018
|
try {
|
|
7502
7019
|
const registryEntry = await findFlintByPath(flintPath);
|
|
7503
|
-
const currentFolderName =
|
|
7020
|
+
const currentFolderName = basename3(flintPath);
|
|
7504
7021
|
const expectedFolderName = `(Flint) ${tomlName}`;
|
|
7505
7022
|
if (currentFolderName !== expectedFolderName) {
|
|
7506
7023
|
const parentDir = dirname5(flintPath);
|
|
7507
|
-
const newPath =
|
|
7024
|
+
const newPath = join16(parentDir, expectedFolderName);
|
|
7508
7025
|
try {
|
|
7509
7026
|
await rename32(flintPath, newPath);
|
|
7510
7027
|
currentFlintPath = newPath;
|
|
@@ -7550,11 +7067,11 @@ async function syncFlint(flintPath, progress) {
|
|
|
7550
7067
|
console.warn(`Registry sync warning: ${err instanceof Error ? err.message : String(err)}`);
|
|
7551
7068
|
}
|
|
7552
7069
|
}
|
|
7553
|
-
const inboxDir =
|
|
7070
|
+
const inboxDir = join16(currentFlintPath, "Inbox");
|
|
7554
7071
|
try {
|
|
7555
|
-
const inboxEntries = await
|
|
7072
|
+
const inboxEntries = await readdir9(inboxDir);
|
|
7556
7073
|
if (inboxEntries.length === 0) {
|
|
7557
|
-
await
|
|
7074
|
+
await rm7(inboxDir, { recursive: true });
|
|
7558
7075
|
}
|
|
7559
7076
|
} catch {
|
|
7560
7077
|
}
|
|
@@ -7583,23 +7100,23 @@ async function syncFlint(flintPath, progress) {
|
|
|
7583
7100
|
var __dirname = dirname6(fileURLToPath(import.meta.url));
|
|
7584
7101
|
var presetsCache = null;
|
|
7585
7102
|
function getBuiltinPresetsDir() {
|
|
7586
|
-
return
|
|
7103
|
+
return join17(__dirname, "presets");
|
|
7587
7104
|
}
|
|
7588
7105
|
function getUserPresetsDir() {
|
|
7589
|
-
return
|
|
7106
|
+
return join17(getGlobalFlintDir(), "presets");
|
|
7590
7107
|
}
|
|
7591
7108
|
function resolvePresetTarget(flintPath, targetPath) {
|
|
7592
|
-
const resolvedRoot =
|
|
7593
|
-
const resolvedTarget =
|
|
7109
|
+
const resolvedRoot = resolve7(flintPath);
|
|
7110
|
+
const resolvedTarget = resolve7(flintPath, targetPath);
|
|
7594
7111
|
if (!resolvedTarget.startsWith(resolvedRoot + sep)) {
|
|
7595
7112
|
throw new Error(`Preset template target escapes flint root: ${targetPath}`);
|
|
7596
7113
|
}
|
|
7597
7114
|
return resolvedTarget;
|
|
7598
7115
|
}
|
|
7599
7116
|
async function loadPresetFromDir(presetDir) {
|
|
7600
|
-
const tomlPath =
|
|
7117
|
+
const tomlPath = join17(presetDir, "preset.toml");
|
|
7601
7118
|
try {
|
|
7602
|
-
const content = await
|
|
7119
|
+
const content = await readFile9(tomlPath, "utf-8");
|
|
7603
7120
|
const parsed = parse(content);
|
|
7604
7121
|
return {
|
|
7605
7122
|
name: parsed.preset.name,
|
|
@@ -7615,10 +7132,10 @@ async function loadPresetFromDir(presetDir) {
|
|
|
7615
7132
|
async function discoverPresetsFromDir(presetsDir) {
|
|
7616
7133
|
const presets = /* @__PURE__ */ new Map();
|
|
7617
7134
|
try {
|
|
7618
|
-
const entries = await
|
|
7135
|
+
const entries = await readdir82(presetsDir, { withFileTypes: true });
|
|
7619
7136
|
for (const entry of entries) {
|
|
7620
7137
|
if (!entry.isDirectory()) continue;
|
|
7621
|
-
const presetDir =
|
|
7138
|
+
const presetDir = join17(presetsDir, entry.name);
|
|
7622
7139
|
const preset = await loadPresetFromDir(presetDir);
|
|
7623
7140
|
if (preset) {
|
|
7624
7141
|
presets.set(preset.name, preset);
|
|
@@ -7662,21 +7179,21 @@ async function hasPreset(name) {
|
|
|
7662
7179
|
async function applyPresetTemplates(flintPath, preset, flintName) {
|
|
7663
7180
|
for (const template of preset.templates) {
|
|
7664
7181
|
const templateUuid = randomUUID4();
|
|
7665
|
-
const sourcePath =
|
|
7182
|
+
const sourcePath = join17(preset.basePath, template.source);
|
|
7666
7183
|
const renderedTarget = template.target.replace(/\{\{name\}\}/g, flintName).replace(/\{\{uuid\}\}/g, templateUuid).replace(/\{\{date\}\}/g, (/* @__PURE__ */ new Date()).toISOString().split("T")[0]);
|
|
7667
7184
|
const resolvedTargetPath = resolvePresetTarget(flintPath, renderedTarget);
|
|
7668
|
-
await
|
|
7669
|
-
let content = await
|
|
7185
|
+
await mkdir12(dirname6(resolvedTargetPath), { recursive: true });
|
|
7186
|
+
let content = await readFile9(sourcePath, "utf-8");
|
|
7670
7187
|
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
|
|
7188
|
+
const { writeFile: writeFile10 } = await import("fs/promises");
|
|
7189
|
+
await writeFile10(resolvedTargetPath, content);
|
|
7673
7190
|
}
|
|
7674
7191
|
}
|
|
7675
7192
|
function getSessionsDir(flintPath) {
|
|
7676
|
-
return
|
|
7193
|
+
return join18(flintPath, ".orbh", "sessions");
|
|
7677
7194
|
}
|
|
7678
7195
|
function getSessionPath(flintPath, sessionId) {
|
|
7679
|
-
return
|
|
7196
|
+
return join18(getSessionsDir(flintPath), `${sessionId}.json`);
|
|
7680
7197
|
}
|
|
7681
7198
|
function ensureSessionsDir(flintPath) {
|
|
7682
7199
|
const dir = getSessionsDir(flintPath);
|
|
@@ -7825,7 +7342,7 @@ function listSessions(flintPath) {
|
|
|
7825
7342
|
const sessions = [];
|
|
7826
7343
|
for (const file of files) {
|
|
7827
7344
|
try {
|
|
7828
|
-
const content = readFileSync2(
|
|
7345
|
+
const content = readFileSync2(join18(dir, file), "utf-8");
|
|
7829
7346
|
sessions.push(JSON.parse(content));
|
|
7830
7347
|
} catch {
|
|
7831
7348
|
}
|
|
@@ -8033,7 +7550,7 @@ function mapClaudeEntry(raw, toolIdMap) {
|
|
|
8033
7550
|
return [];
|
|
8034
7551
|
}
|
|
8035
7552
|
function parseJsonl(text) {
|
|
8036
|
-
return text.split(
|
|
7553
|
+
return text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => {
|
|
8037
7554
|
try {
|
|
8038
7555
|
return JSON.parse(line);
|
|
8039
7556
|
} catch {
|
|
@@ -8043,7 +7560,7 @@ function parseJsonl(text) {
|
|
|
8043
7560
|
}
|
|
8044
7561
|
function resolveTranscriptPath(cwd, nativeSessionId) {
|
|
8045
7562
|
const sanitized = cwd.replace(/[^a-zA-Z0-9\-_]/g, "-");
|
|
8046
|
-
return
|
|
7563
|
+
return join19(homedir3(), ".claude", "projects", sanitized, `${nativeSessionId}.jsonl`);
|
|
8047
7564
|
}
|
|
8048
7565
|
var TranscriptWatcher = class {
|
|
8049
7566
|
transcriptPath = null;
|
|
@@ -8170,7 +7687,7 @@ var TranscriptWatcher = class {
|
|
|
8170
7687
|
}
|
|
8171
7688
|
this.byteOffset = fileSize;
|
|
8172
7689
|
const text = buffer.toString("utf-8");
|
|
8173
|
-
const lines = text.split(
|
|
7690
|
+
const lines = text.split(/\r?\n/).filter((line) => line.trim().length > 0);
|
|
8174
7691
|
const newEntries = [];
|
|
8175
7692
|
for (const line of lines) {
|
|
8176
7693
|
let raw;
|
|
@@ -8384,19 +7901,6 @@ export {
|
|
|
8384
7901
|
getConfigValue,
|
|
8385
7902
|
setConfigValue,
|
|
8386
7903
|
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
7904
|
getIdentityStatePath,
|
|
8401
7905
|
getPersonFilePath,
|
|
8402
7906
|
readIdentityState,
|
|
@@ -8436,7 +7940,7 @@ export {
|
|
|
8436
7940
|
fulfillCodebase,
|
|
8437
7941
|
fulfillFlint,
|
|
8438
7942
|
unfulfill,
|
|
8439
|
-
|
|
7943
|
+
resolve2,
|
|
8440
7944
|
getStatus,
|
|
8441
7945
|
getUnfulfilled,
|
|
8442
7946
|
getUnfulfilledCodebases,
|