@nuucognition/flint-cli 0.2.0-beta.1 → 0.2.0-beta.2
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/bin/flint-prod.js +2 -0
- package/dist/{chunk-VO4ZYDCW.js → chunk-K5QP4OME.js} +13 -10
- package/dist/{chunk-5YLBX2W6.js → chunk-RAH2IR2Z.js} +11 -27
- package/dist/chunk-V7YA5RXL.js +43 -0
- package/dist/{chunk-UNMULXL5.js → chunk-VEO4E5HX.js} +7 -6
- package/dist/{exports-CA5QHVI7-6IDFKMCF.js → exports-KXKBTYJ2-A3QWNDEB.js} +1 -1
- package/dist/index.js +1370 -785
- package/dist/{mesh-config-VGFSHC2G-YCC4ZIAT.js → mesh-config-J6WB4RFV-G7RGPOZA.js} +1 -11
- package/dist/{registry-5QFQ3XPR-G7IB3KWS.js → registry-5PUMDGQP-YVSEVBB4.js} +3 -3
- package/dist/utils-BBA2XQZO-YU5SL3JY.js +8 -0
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -41,7 +41,11 @@ import {
|
|
|
41
41
|
toKebabCase,
|
|
42
42
|
writeFlintJson,
|
|
43
43
|
writeFlintToml
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-RAH2IR2Z.js";
|
|
45
|
+
import {
|
|
46
|
+
exists,
|
|
47
|
+
runConcurrent
|
|
48
|
+
} from "./chunk-V7YA5RXL.js";
|
|
45
49
|
import {
|
|
46
50
|
cleanRegistryFile,
|
|
47
51
|
findFlintByName,
|
|
@@ -49,22 +53,23 @@ import {
|
|
|
49
53
|
getFlintRegistry,
|
|
50
54
|
getFlintRegistryPath,
|
|
51
55
|
getGlobalFlintDir,
|
|
56
|
+
isFlintNameTaken,
|
|
52
57
|
registerFlint,
|
|
53
58
|
registerFlintByPath,
|
|
54
59
|
unregisterFlint,
|
|
55
60
|
updateFlintEntry,
|
|
56
61
|
upsertFlintEntry
|
|
57
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-VEO4E5HX.js";
|
|
58
63
|
import {
|
|
59
64
|
buildExport,
|
|
60
65
|
cleanupStaleExports,
|
|
61
66
|
scanExportEligible,
|
|
62
67
|
scanExports
|
|
63
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-K5QP4OME.js";
|
|
64
69
|
|
|
65
70
|
// src/index.ts
|
|
66
|
-
import { Command as
|
|
67
|
-
import { readFileSync as readFileSync2, existsSync as
|
|
71
|
+
import { Command as Command29 } from "commander";
|
|
72
|
+
import { readFileSync as readFileSync2, existsSync as existsSync7, cpSync, mkdirSync, readdirSync as readdirSync2 } from "fs";
|
|
68
73
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
69
74
|
import { dirname as dirname10, join as join35 } from "path";
|
|
70
75
|
import { homedir as homedir5 } from "os";
|
|
@@ -1376,7 +1381,6 @@ function createFeaturesCommand(config) {
|
|
|
1376
1381
|
var FEATURES = createFeatureRegistry([
|
|
1377
1382
|
// === Production Commands ===
|
|
1378
1383
|
{ id: "init", tier: "prod", type: "command", description: "Create a new flint workspace", requiresAuth: false },
|
|
1379
|
-
{ id: "clone", tier: "prod", type: "command", description: "Clone a flint from a git repository", requiresAuth: false },
|
|
1380
1384
|
{ id: "list", tier: "prod", type: "command", description: "List flints and mesh content", requiresAuth: false },
|
|
1381
1385
|
{ id: "sync", tier: "prod", type: "command", description: "Synchronize flint with shards", requiresAuth: false },
|
|
1382
1386
|
{ id: "shard", tier: "prod", type: "command", description: "Shard management", requiresAuth: false },
|
|
@@ -1404,19 +1408,24 @@ var FEATURES = createFeatureRegistry([
|
|
|
1404
1408
|
// === Dev Commands ===
|
|
1405
1409
|
{ id: "lattice", tier: "dev", type: "command", description: "Lattice integration", requiresAuth: false },
|
|
1406
1410
|
{ id: "agent", tier: "dev", type: "command", description: "AI agent integration", requiresAuth: false },
|
|
1407
|
-
{ id: "code", tier: "
|
|
1411
|
+
{ id: "code", tier: "exp", type: "command", description: "Launch AI coding agents", requiresAuth: false },
|
|
1408
1412
|
{ id: "server", tier: "dev", type: "command", description: "Flint runtime server", requiresAuth: false },
|
|
1409
1413
|
{ id: "runtime", tier: "dev", type: "command", description: "Flint runtime management", requiresAuth: false },
|
|
1410
|
-
{ id: "completions", tier: "dev", type: "command", description: "Shell completions", requiresAuth: false },
|
|
1411
1414
|
{ id: "obsidian.push", tier: "dev", type: "function", description: "Push obsidian config changes to remote", requiresAuth: false },
|
|
1412
1415
|
{ id: "agent.start", tier: "dev", type: "function", description: "Start AI agent session", requiresAuth: false }
|
|
1413
1416
|
]);
|
|
1414
1417
|
|
|
1415
1418
|
// src/commands/init.ts
|
|
1416
1419
|
import { Command as Command3 } from "commander";
|
|
1417
|
-
import
|
|
1418
|
-
import { execSync as
|
|
1420
|
+
import pc6 from "picocolors";
|
|
1421
|
+
import { execSync as execSync2 } from "child_process";
|
|
1419
1422
|
import { platform as platform2 } from "os";
|
|
1423
|
+
import { resolve as resolve8, join as join19 } from "path";
|
|
1424
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1425
|
+
import { mkdtemp as mkdtemp3, rm as rm8, rename as rename4 } from "fs/promises";
|
|
1426
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
1427
|
+
import { exec as exec6 } from "child_process";
|
|
1428
|
+
import { promisify as promisify7 } from "util";
|
|
1420
1429
|
|
|
1421
1430
|
// ../../packages/flint/dist/index.js
|
|
1422
1431
|
import { mkdir as mkdir4, stat as stat22 } from "fs/promises";
|
|
@@ -1425,40 +1434,42 @@ import { join as join9, dirname as dirname4, basename } from "path";
|
|
|
1425
1434
|
import { stat as stat32 } from "fs/promises";
|
|
1426
1435
|
import { dirname as dirname22, join as join33 } from "path";
|
|
1427
1436
|
import { join as join42 } from "path";
|
|
1428
|
-
import {
|
|
1437
|
+
import { exec } from "child_process";
|
|
1438
|
+
import { promisify as promisify6 } from "util";
|
|
1429
1439
|
import { readdir as readdir4, stat as stat42, access as access2 } from "fs/promises";
|
|
1430
1440
|
import { join as join52, resolve } from "path";
|
|
1431
1441
|
import { homedir as homedir3 } from "os";
|
|
1432
1442
|
import { readFile as readFile4, writeFile as writeFile23, mkdir as mkdir33, stat as stat52, unlink as unlink3, access as access22 } from "fs/promises";
|
|
1433
1443
|
import { join as join62 } from "path";
|
|
1434
|
-
import { exec } from "child_process";
|
|
1435
|
-
import { promisify as
|
|
1444
|
+
import { exec as exec2 } from "child_process";
|
|
1445
|
+
import { promisify as promisify22 } from "util";
|
|
1436
1446
|
import { rm as rm5 } from "fs/promises";
|
|
1437
1447
|
import { mkdir as mkdir5, readdir as readdir32, copyFile, rm as rm32, readFile as readFile32, writeFile as writeFile32, rmdir } from "fs/promises";
|
|
1438
1448
|
import { join as join92, resolve as resolve3, dirname as dirname32 } from "path";
|
|
1439
1449
|
import { randomUUID } from "crypto";
|
|
1440
1450
|
import { parse as parseYaml2 } from "yaml";
|
|
1441
|
-
import { access as access3 } from "fs/promises";
|
|
1442
1451
|
import { join as join82, resolve as resolve2, isAbsolute } from "path";
|
|
1443
1452
|
import { mkdtemp, rm as rm22 } from "fs/promises";
|
|
1444
1453
|
import { tmpdir } from "os";
|
|
1445
|
-
import {
|
|
1454
|
+
import { exec as exec3 } from "child_process";
|
|
1455
|
+
import { promisify as promisify32 } from "util";
|
|
1446
1456
|
import { parse as parseYaml } from "yaml";
|
|
1447
1457
|
import { readFile as readFile23 } from "fs/promises";
|
|
1448
1458
|
import { join as join10 } from "path";
|
|
1449
1459
|
import { readdir as readdir42, mkdir as mkdir6 } from "fs/promises";
|
|
1450
1460
|
import { writeFile as writeFile4 } from "fs/promises";
|
|
1451
1461
|
import { spawn } from "child_process";
|
|
1452
|
-
import { readdir as readdir5, access as
|
|
1462
|
+
import { readdir as readdir5, access as access3, constants } from "fs/promises";
|
|
1453
1463
|
import { join as join11, resolve as resolve4 } from "path";
|
|
1454
1464
|
import { mkdir as mkdir7, readFile as readFile5, writeFile as writeFile5, rm as rm52, readdir as readdir6, copyFile as copyFile2 } from "fs/promises";
|
|
1455
1465
|
import { join as join13, dirname as dirname42, resolve as resolve6, sep } from "path";
|
|
1456
|
-
import { execSync
|
|
1466
|
+
import { execSync } from "child_process";
|
|
1457
1467
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1458
1468
|
import { join as join12, resolve as resolve5, isAbsolute as isAbsolute2 } from "path";
|
|
1459
1469
|
import { mkdtemp as mkdtemp2, rm as rm42 } from "fs/promises";
|
|
1460
1470
|
import { tmpdir as tmpdir2 } from "os";
|
|
1461
|
-
import {
|
|
1471
|
+
import { exec as exec4 } from "child_process";
|
|
1472
|
+
import { promisify as promisify42 } from "util";
|
|
1462
1473
|
import { parse as parseYaml3 } from "yaml";
|
|
1463
1474
|
import { readFile as readFile42 } from "fs/promises";
|
|
1464
1475
|
|
|
@@ -2459,16 +2470,16 @@ var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
|
2459
2470
|
// ../../packages/flint/dist/index.js
|
|
2460
2471
|
import { rename as rename22 } from "fs/promises";
|
|
2461
2472
|
import { basename as basename3, dirname as dirname6, join as join18 } from "path";
|
|
2462
|
-
import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir8, access as
|
|
2473
|
+
import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir8, access as access4, rm as rm6 } from "fs/promises";
|
|
2463
2474
|
import { join as join14 } from "path";
|
|
2464
|
-
import { exec as
|
|
2465
|
-
import { promisify as
|
|
2466
|
-
import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
|
|
2475
|
+
import { exec as exec5 } from "child_process";
|
|
2476
|
+
import { promisify as promisify52 } from "util";
|
|
2477
|
+
import { readFile as readFile7, writeFile as writeFile7, readdir as readdir7 } from "fs/promises";
|
|
2467
2478
|
import { join as join15 } from "path";
|
|
2468
2479
|
import { stat as stat8, mkdir as mkdir11 } from "fs/promises";
|
|
2469
|
-
import { mkdir as mkdir10, readdir as
|
|
2480
|
+
import { mkdir as mkdir10, readdir as readdir9, rm as rm7, cp as cp3, rename as rename3, access as access5 } from "fs/promises";
|
|
2470
2481
|
import { join as join17 } from "path";
|
|
2471
|
-
import { readdir as
|
|
2482
|
+
import { readdir as readdir8, readFile as readFile8, mkdir as mkdir9 } from "fs/promises";
|
|
2472
2483
|
import { join as join16, dirname as dirname5, resolve as resolve7, sep as sep2 } from "path";
|
|
2473
2484
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2474
2485
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -2511,6 +2522,12 @@ async function createFlintStructure(options) {
|
|
|
2511
2522
|
if (invalidChars.test(name)) {
|
|
2512
2523
|
throw new Error(`Flint name contains invalid characters: ${name}`);
|
|
2513
2524
|
}
|
|
2525
|
+
if (register) {
|
|
2526
|
+
const existing = await isFlintNameTaken(name);
|
|
2527
|
+
if (existing) {
|
|
2528
|
+
throw new Error(`A flint named "${name}" already exists at: ${existing.path}`);
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2514
2531
|
const folderName = formatFlintFolderName(name);
|
|
2515
2532
|
const flintPath = join23(parentDir, folderName);
|
|
2516
2533
|
try {
|
|
@@ -2571,10 +2588,11 @@ async function isInsideFlint(path3) {
|
|
|
2571
2588
|
const flintRoot = await findFlintRoot(path3);
|
|
2572
2589
|
return flintRoot !== null;
|
|
2573
2590
|
}
|
|
2591
|
+
var execAsync = promisify6(exec);
|
|
2574
2592
|
var OBSIDIAN_REPO_URL = "https://github.com/NUU-Cognition/flint-dot-obsidian.git";
|
|
2575
2593
|
async function cloneObsidian(flintPath) {
|
|
2576
2594
|
const obsidianDir = join42(flintPath, ".obsidian");
|
|
2577
|
-
|
|
2595
|
+
await execAsync(`git clone ${OBSIDIAN_REPO_URL} "${obsidianDir}"`, { timeout: 6e4 });
|
|
2578
2596
|
}
|
|
2579
2597
|
async function isValidFlint(path3) {
|
|
2580
2598
|
try {
|
|
@@ -2676,7 +2694,7 @@ async function discoverFlints(options) {
|
|
|
2676
2694
|
}
|
|
2677
2695
|
return results;
|
|
2678
2696
|
}
|
|
2679
|
-
var
|
|
2697
|
+
var execAsync2 = promisify22(exec2);
|
|
2680
2698
|
var LEGACY_WORKSPACE_CONFIG_FILENAME = "workspace.toml";
|
|
2681
2699
|
function getWorkspaceReferencesDir(flintPath) {
|
|
2682
2700
|
return join62(flintPath, "Workspace", "References");
|
|
@@ -2853,8 +2871,8 @@ async function createRepository(flintPath, name, url) {
|
|
|
2853
2871
|
}
|
|
2854
2872
|
await mkdir33(repoPath, { recursive: true });
|
|
2855
2873
|
try {
|
|
2856
|
-
await
|
|
2857
|
-
await
|
|
2874
|
+
await execAsync2("git init", { cwd: repoPath });
|
|
2875
|
+
await execAsync2(`git remote add origin "${url}"`, { cwd: repoPath });
|
|
2858
2876
|
} catch (error3) {
|
|
2859
2877
|
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
2860
2878
|
await rm5(repoPath, { recursive: true, force: true });
|
|
@@ -2870,7 +2888,7 @@ async function cloneRepository(flintPath, name, url) {
|
|
|
2870
2888
|
throw new Error(`Repository folder already exists: ${repoPath}`);
|
|
2871
2889
|
}
|
|
2872
2890
|
try {
|
|
2873
|
-
await
|
|
2891
|
+
await execAsync2(`git clone "${url}" "${repoPath}"`);
|
|
2874
2892
|
} catch (error3) {
|
|
2875
2893
|
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
2876
2894
|
throw new Error(`Failed to clone repository: ${message}`);
|
|
@@ -2888,7 +2906,7 @@ async function removeRepositoryFolder(flintPath, name) {
|
|
|
2888
2906
|
async function updateRepository(flintPath, name, url) {
|
|
2889
2907
|
const repoPath = getRepositoryPath(flintPath, name);
|
|
2890
2908
|
if (await pathExists(repoPath)) {
|
|
2891
|
-
await
|
|
2909
|
+
await execAsync2("git pull", { cwd: repoPath });
|
|
2892
2910
|
return repoPath;
|
|
2893
2911
|
}
|
|
2894
2912
|
return cloneRepository(flintPath, name, url);
|
|
@@ -2927,7 +2945,7 @@ async function cloneSourceRepository(flintPath, name, url) {
|
|
|
2927
2945
|
throw new Error(`Source repository folder already exists: ${repoPath}`);
|
|
2928
2946
|
}
|
|
2929
2947
|
try {
|
|
2930
|
-
await
|
|
2948
|
+
await execAsync2(`git clone --depth 1 "${url}" "${repoPath}"`);
|
|
2931
2949
|
} catch (error3) {
|
|
2932
2950
|
const message = error3 instanceof Error ? error3.message : String(error3);
|
|
2933
2951
|
throw new Error(`Failed to clone source repository: ${message}`);
|
|
@@ -3013,14 +3031,7 @@ async function migrateWorkspaceConfig(flintPath) {
|
|
|
3013
3031
|
}
|
|
3014
3032
|
return result;
|
|
3015
3033
|
}
|
|
3016
|
-
|
|
3017
|
-
try {
|
|
3018
|
-
await access3(path3);
|
|
3019
|
-
return true;
|
|
3020
|
-
} catch {
|
|
3021
|
-
return false;
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3034
|
+
var execAsync3 = promisify32(exec3);
|
|
3024
3035
|
function isOwnerRepo(s) {
|
|
3025
3036
|
return /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/.test(s);
|
|
3026
3037
|
}
|
|
@@ -3075,8 +3086,7 @@ async function resolveShardSource(source, flintPath) {
|
|
|
3075
3086
|
async function cloneAndResolve(url, source) {
|
|
3076
3087
|
const tempDir = await mkdtemp(join82(tmpdir(), "flint-shard-"));
|
|
3077
3088
|
try {
|
|
3078
|
-
|
|
3079
|
-
stdio: "pipe",
|
|
3089
|
+
await execAsync3(`git clone --depth 1 ${url} "${tempDir}"`, {
|
|
3080
3090
|
timeout: 6e4
|
|
3081
3091
|
// 60 second timeout
|
|
3082
3092
|
});
|
|
@@ -3141,40 +3151,10 @@ async function fetchRemoteShardVersion(source) {
|
|
|
3141
3151
|
}
|
|
3142
3152
|
return null;
|
|
3143
3153
|
}
|
|
3144
|
-
var _installingDeps = /* @__PURE__ */ new Set();
|
|
3145
|
-
async function resolveDependency(flintPath, dep, installedNames, options = {}) {
|
|
3146
|
-
if (!isOwnerRepo(dep)) return;
|
|
3147
|
-
if (_installingDeps.has(dep)) return;
|
|
3148
|
-
_installingDeps.add(dep);
|
|
3149
|
-
try {
|
|
3150
|
-
const declarations = await getShardDeclarations(flintPath);
|
|
3151
|
-
const declValues = Object.values(declarations);
|
|
3152
|
-
const alreadyDeclared = declValues.some((d) => d.source === dep);
|
|
3153
|
-
if (alreadyDeclared) return;
|
|
3154
|
-
const installedKebabSet = new Set(installedNames.map((f) => toKebabCase(f)));
|
|
3155
|
-
const repoParts = dep.split("/");
|
|
3156
|
-
const repoName = repoParts[1] || "";
|
|
3157
|
-
const depKebab = repoName.startsWith("shard-") ? repoName.slice(6) : repoName;
|
|
3158
|
-
if (depKebab && installedKebabSet.has(depKebab)) return;
|
|
3159
|
-
const source = parseShardSource(dep);
|
|
3160
|
-
const resolved = await resolveShardSource(source, flintPath);
|
|
3161
|
-
try {
|
|
3162
|
-
const manifestKebab = toKebabCase(resolved.manifest.name);
|
|
3163
|
-
if (!installedKebabSet.has(manifestKebab)) {
|
|
3164
|
-
await installShardFromSource(flintPath, resolved.path, resolved.manifest, {
|
|
3165
|
-
force: options.force,
|
|
3166
|
-
source: dep
|
|
3167
|
-
});
|
|
3168
|
-
}
|
|
3169
|
-
} finally {
|
|
3170
|
-
await cleanupResolvedSource(resolved);
|
|
3171
|
-
}
|
|
3172
|
-
} finally {
|
|
3173
|
-
_installingDeps.delete(dep);
|
|
3174
|
-
}
|
|
3175
|
-
}
|
|
3176
3154
|
async function cloneShardRepos(flintPath, repos) {
|
|
3177
|
-
const {
|
|
3155
|
+
const { exec: exec62 } = await import("child_process");
|
|
3156
|
+
const { promisify: promisify62 } = await import("util");
|
|
3157
|
+
const execAsync62 = promisify62(exec62);
|
|
3178
3158
|
const reposDir = join92(flintPath, "Shards", "(System) Repos");
|
|
3179
3159
|
await mkdir5(reposDir, { recursive: true });
|
|
3180
3160
|
const gitignorePath = join92(reposDir, ".gitignore");
|
|
@@ -3189,7 +3169,7 @@ async function cloneShardRepos(flintPath, repos) {
|
|
|
3189
3169
|
const branchArgs = repo.branch ? ["--branch", repo.branch] : [];
|
|
3190
3170
|
const args = ["clone", ...branchArgs, "--depth", "1", repo.url, repoPath];
|
|
3191
3171
|
try {
|
|
3192
|
-
|
|
3172
|
+
await execAsync62(`git ${args.join(" ")}`, { timeout: 6e4 });
|
|
3193
3173
|
} catch (err) {
|
|
3194
3174
|
console.warn(`Failed to clone repo "${repo.name}" from ${repo.url}`);
|
|
3195
3175
|
}
|
|
@@ -3202,7 +3182,9 @@ async function removeShardRepos(flintPath, repos) {
|
|
|
3202
3182
|
}
|
|
3203
3183
|
}
|
|
3204
3184
|
async function pullShardRepos(flintPath, repos) {
|
|
3205
|
-
const {
|
|
3185
|
+
const { exec: exec62 } = await import("child_process");
|
|
3186
|
+
const { promisify: promisify62 } = await import("util");
|
|
3187
|
+
const execAsync62 = promisify62(exec62);
|
|
3206
3188
|
const reposDir = join92(flintPath, "Shards", "(System) Repos");
|
|
3207
3189
|
for (const repo of repos) {
|
|
3208
3190
|
const repoPath = join92(reposDir, repo.name);
|
|
@@ -3211,7 +3193,7 @@ async function pullShardRepos(flintPath, repos) {
|
|
|
3211
3193
|
continue;
|
|
3212
3194
|
}
|
|
3213
3195
|
try {
|
|
3214
|
-
|
|
3196
|
+
await execAsync62("git pull", { cwd: repoPath, timeout: 3e4 });
|
|
3215
3197
|
} catch {
|
|
3216
3198
|
console.warn(`Failed to pull repo "${repo.name}"`);
|
|
3217
3199
|
}
|
|
@@ -3278,12 +3260,6 @@ async function installShardFromSource(flintPath, sourcePath, manifest, options =
|
|
|
3278
3260
|
if (!resolvedDestPath.startsWith(resolvedFlintPath)) {
|
|
3279
3261
|
throw new Error("Invalid shard path: outside flint directory");
|
|
3280
3262
|
}
|
|
3281
|
-
if (manifest.depends?.length) {
|
|
3282
|
-
const installed = await listInstalledShards(flintPath);
|
|
3283
|
-
for (const dep of manifest.depends) {
|
|
3284
|
-
await resolveDependency(flintPath, dep, installed, { force: options.force });
|
|
3285
|
-
}
|
|
3286
|
-
}
|
|
3287
3263
|
await rm32(destPath, { recursive: true, force: true });
|
|
3288
3264
|
await mkdir5(destPath, { recursive: true });
|
|
3289
3265
|
const shardYamlSrc = join92(sourcePath, "shard.yaml");
|
|
@@ -3291,12 +3267,9 @@ async function installShardFromSource(flintPath, sourcePath, manifest, options =
|
|
|
3291
3267
|
if (await exists(shardYamlSrc)) {
|
|
3292
3268
|
await copyFile(shardYamlSrc, shardYamlDest);
|
|
3293
3269
|
}
|
|
3294
|
-
const
|
|
3295
|
-
|
|
3296
|
-
const
|
|
3297
|
-
const skipFiles = hasLegacyCopyDir ? [] : ["shard.yaml", "README.md", "install", ".git", "scripts"];
|
|
3298
|
-
await copyDir(shardFilesSource, destPath, skipFiles);
|
|
3299
|
-
const scriptsSrc = join92(sourcePath, hasLegacyCopyDir ? "copy/scripts" : "scripts");
|
|
3270
|
+
const skipFiles = ["shard.yaml", "README.md", "install", ".git", "scripts"];
|
|
3271
|
+
await copyDir(sourcePath, destPath, skipFiles);
|
|
3272
|
+
const scriptsSrc = join92(sourcePath, "scripts");
|
|
3300
3273
|
if (await exists(scriptsSrc)) {
|
|
3301
3274
|
await copyDir(scriptsSrc, join92(destPath, "scripts"));
|
|
3302
3275
|
}
|
|
@@ -3322,7 +3295,7 @@ async function installShardFromSource(flintPath, sourcePath, manifest, options =
|
|
|
3322
3295
|
continue;
|
|
3323
3296
|
}
|
|
3324
3297
|
if (await exists(destFilePath)) {
|
|
3325
|
-
const mode = entry.mode ??
|
|
3298
|
+
const mode = entry.mode ?? "once";
|
|
3326
3299
|
if (mode === "once") {
|
|
3327
3300
|
continue;
|
|
3328
3301
|
}
|
|
@@ -3405,77 +3378,95 @@ async function updateShards(flintPath, options = {}) {
|
|
|
3405
3378
|
return mode === "dev" || mode === "custom";
|
|
3406
3379
|
}).map(([k]) => k)
|
|
3407
3380
|
);
|
|
3408
|
-
const
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3381
|
+
const updatableShards = installed.filter((info2) => !localSet.has(info2.name));
|
|
3382
|
+
const updateTasks = updatableShards.map((info2) => ({
|
|
3383
|
+
name: info2.folderName,
|
|
3384
|
+
run: async () => {
|
|
3385
|
+
const declaration = declarations[info2.name];
|
|
3386
|
+
const source = declaration?.source;
|
|
3387
|
+
if (!options.reinstall && source && isOwnerRepo(source)) {
|
|
3388
|
+
const parsed2 = parseShardSource(source);
|
|
3389
|
+
const remoteVersion = await fetchRemoteShardVersion(parsed2);
|
|
3390
|
+
if (remoteVersion && remoteVersion === info2.version) {
|
|
3391
|
+
return {
|
|
3392
|
+
name: info2.folderName,
|
|
3393
|
+
path: join92(flintPath, "Shards", info2.folderName),
|
|
3394
|
+
status: "skipped",
|
|
3395
|
+
localVersion: info2.version,
|
|
3396
|
+
remoteVersion,
|
|
3397
|
+
reason: "up to date"
|
|
3398
|
+
};
|
|
3399
|
+
}
|
|
3400
|
+
}
|
|
3401
|
+
const shardPath = join92(flintPath, "Shards", info2.folderName);
|
|
3402
|
+
const manifest = await readShardManifest(shardPath);
|
|
3403
|
+
if (manifest?.repos?.length) {
|
|
3404
|
+
await pullShardRepos(flintPath, manifest.repos);
|
|
3405
|
+
}
|
|
3406
|
+
if (!source || !isOwnerRepo(source)) {
|
|
3407
|
+
return {
|
|
3418
3408
|
name: info2.folderName,
|
|
3419
3409
|
path: join92(flintPath, "Shards", info2.folderName),
|
|
3420
3410
|
status: "skipped",
|
|
3421
3411
|
localVersion: info2.version,
|
|
3422
|
-
|
|
3423
|
-
|
|
3412
|
+
reason: "no source configured"
|
|
3413
|
+
};
|
|
3414
|
+
}
|
|
3415
|
+
const parsed = parseShardSource(source);
|
|
3416
|
+
let resolved = null;
|
|
3417
|
+
try {
|
|
3418
|
+
resolved = await resolveShardSource(parsed, flintPath);
|
|
3419
|
+
} catch {
|
|
3420
|
+
return {
|
|
3421
|
+
name: info2.folderName,
|
|
3422
|
+
path: join92(flintPath, "Shards", info2.folderName),
|
|
3423
|
+
status: "failed",
|
|
3424
|
+
localVersion: info2.version,
|
|
3425
|
+
reason: "failed to resolve source"
|
|
3426
|
+
};
|
|
3427
|
+
}
|
|
3428
|
+
try {
|
|
3429
|
+
await installShardFromSource(flintPath, resolved.path, resolved.manifest, {
|
|
3430
|
+
force: true,
|
|
3431
|
+
source
|
|
3424
3432
|
});
|
|
3425
|
-
|
|
3433
|
+
return {
|
|
3434
|
+
name: info2.folderName,
|
|
3435
|
+
path: join92(flintPath, "Shards", info2.folderName),
|
|
3436
|
+
status: "updated",
|
|
3437
|
+
localVersion: info2.version,
|
|
3438
|
+
remoteVersion: resolved.manifest.version
|
|
3439
|
+
};
|
|
3440
|
+
} catch {
|
|
3441
|
+
return {
|
|
3442
|
+
name: info2.folderName,
|
|
3443
|
+
path: join92(flintPath, "Shards", info2.folderName),
|
|
3444
|
+
status: "failed",
|
|
3445
|
+
localVersion: info2.version,
|
|
3446
|
+
reason: "failed to install from source"
|
|
3447
|
+
};
|
|
3448
|
+
} finally {
|
|
3449
|
+
await cleanupResolvedSource(resolved);
|
|
3426
3450
|
}
|
|
3427
3451
|
}
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
reason: "no source configured"
|
|
3440
|
-
});
|
|
3441
|
-
continue;
|
|
3442
|
-
}
|
|
3443
|
-
const parsed = parseShardSource(source);
|
|
3444
|
-
let resolved = null;
|
|
3445
|
-
try {
|
|
3446
|
-
resolved = await resolveShardSource(parsed, flintPath);
|
|
3447
|
-
} catch {
|
|
3448
|
-
results.push({
|
|
3449
|
-
name: info2.folderName,
|
|
3450
|
-
path: join92(flintPath, "Shards", info2.folderName),
|
|
3451
|
-
status: "failed",
|
|
3452
|
-
localVersion: info2.version,
|
|
3453
|
-
reason: "failed to resolve source"
|
|
3454
|
-
});
|
|
3455
|
-
continue;
|
|
3456
|
-
}
|
|
3457
|
-
try {
|
|
3458
|
-
await installShardFromSource(flintPath, resolved.path, resolved.manifest, {
|
|
3459
|
-
force: true,
|
|
3460
|
-
source
|
|
3461
|
-
});
|
|
3462
|
-
results.push({
|
|
3463
|
-
name: info2.folderName,
|
|
3464
|
-
path: join92(flintPath, "Shards", info2.folderName),
|
|
3465
|
-
status: "updated",
|
|
3466
|
-
localVersion: info2.version,
|
|
3467
|
-
remoteVersion: resolved.manifest.version
|
|
3468
|
-
});
|
|
3469
|
-
} catch {
|
|
3452
|
+
}));
|
|
3453
|
+
const { runConcurrent: runConcurrent2 } = await import("./utils-BBA2XQZO-YU5SL3JY.js");
|
|
3454
|
+
const concurrentResults = await runConcurrent2(updateTasks, {
|
|
3455
|
+
concurrency: 5,
|
|
3456
|
+
onStart: options.onStart,
|
|
3457
|
+
onComplete: options.onComplete,
|
|
3458
|
+
onError: options.onError
|
|
3459
|
+
});
|
|
3460
|
+
const results = concurrentResults.filter((r) => r.status === "ok" && r.value).map((r) => r.value);
|
|
3461
|
+
for (const r of concurrentResults) {
|
|
3462
|
+
if (r.status === "error") {
|
|
3470
3463
|
results.push({
|
|
3471
|
-
name:
|
|
3472
|
-
path: join92(flintPath, "Shards",
|
|
3464
|
+
name: r.name,
|
|
3465
|
+
path: join92(flintPath, "Shards", r.name),
|
|
3473
3466
|
status: "failed",
|
|
3474
|
-
localVersion:
|
|
3475
|
-
reason:
|
|
3467
|
+
localVersion: "",
|
|
3468
|
+
reason: r.error?.message || "Unknown error"
|
|
3476
3469
|
});
|
|
3477
|
-
} finally {
|
|
3478
|
-
await cleanupResolvedSource(resolved);
|
|
3479
3470
|
}
|
|
3480
3471
|
}
|
|
3481
3472
|
return results;
|
|
@@ -3571,7 +3562,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
3571
3562
|
if (!manifest) continue;
|
|
3572
3563
|
const result = { name: folder, reposCloned: 0, reposPulled: 0, foldersCreated: 0, filesInstalled: 0 };
|
|
3573
3564
|
if (manifest.repos?.length) {
|
|
3574
|
-
const { execSync:
|
|
3565
|
+
const { execSync: execSync22 } = await import("child_process");
|
|
3575
3566
|
const reposDir = join92(flintPath, "Shards", "(System) Repos");
|
|
3576
3567
|
await mkdir5(reposDir, { recursive: true });
|
|
3577
3568
|
const gitignorePath = join92(reposDir, ".gitignore");
|
|
@@ -3582,7 +3573,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
3582
3573
|
const repoPath = join92(reposDir, repo.name);
|
|
3583
3574
|
if (await exists(repoPath)) {
|
|
3584
3575
|
try {
|
|
3585
|
-
|
|
3576
|
+
execSync22("git pull", { cwd: repoPath, stdio: "pipe" });
|
|
3586
3577
|
result.reposPulled++;
|
|
3587
3578
|
} catch {
|
|
3588
3579
|
console.warn(`Failed to pull repo "${repo.name}"`);
|
|
@@ -3591,7 +3582,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
3591
3582
|
const branchArgs = repo.branch ? ["--branch", repo.branch] : [];
|
|
3592
3583
|
const args = ["clone", ...branchArgs, "--depth", "1", repo.url, repoPath];
|
|
3593
3584
|
try {
|
|
3594
|
-
|
|
3585
|
+
execSync22(`git ${args.join(" ")}`, { stdio: "pipe" });
|
|
3595
3586
|
result.reposCloned++;
|
|
3596
3587
|
} catch {
|
|
3597
3588
|
console.warn(`Failed to clone repo "${repo.name}" from ${repo.url}`);
|
|
@@ -3620,7 +3611,7 @@ async function pullShard(flintPath, identifier, options) {
|
|
|
3620
3611
|
const resolvedDestFilePath = resolve3(destFilePath);
|
|
3621
3612
|
if (!resolvedDestFilePath.startsWith(resolvedFlintPath)) continue;
|
|
3622
3613
|
if (await exists(destFilePath)) {
|
|
3623
|
-
const mode = entry.mode ??
|
|
3614
|
+
const mode = entry.mode ?? "once";
|
|
3624
3615
|
if (!options?.force && mode === "once") continue;
|
|
3625
3616
|
}
|
|
3626
3617
|
let content;
|
|
@@ -3761,6 +3752,10 @@ State for the ${name} shard.
|
|
|
3761
3752
|
`;
|
|
3762
3753
|
await writeFile32(join92(stateDir, `(Shard) ${name}.md`), stateContent);
|
|
3763
3754
|
}
|
|
3755
|
+
if (shardMode === "dev") {
|
|
3756
|
+
const { execSync: execSync22 } = await import("child_process");
|
|
3757
|
+
execSync22("git init", { cwd: shardPath, stdio: "pipe" });
|
|
3758
|
+
}
|
|
3764
3759
|
await addShardToConfig(flintPath, folderName, `path:./Shards/${folderName}`, { mode: shardMode });
|
|
3765
3760
|
return { name: folderName, path: shardPath };
|
|
3766
3761
|
}
|
|
@@ -3795,24 +3790,121 @@ async function registerExistingShard(flintPath, folderName) {
|
|
|
3795
3790
|
path: shardPath
|
|
3796
3791
|
};
|
|
3797
3792
|
}
|
|
3798
|
-
function
|
|
3799
|
-
const
|
|
3800
|
-
|
|
3801
|
-
const
|
|
3802
|
-
|
|
3793
|
+
async function editShard(flintPath, folderName, source) {
|
|
3794
|
+
const { execSync: execSync22 } = await import("child_process");
|
|
3795
|
+
const { rename: rename32 } = await import("fs/promises");
|
|
3796
|
+
const shardPath = join92(flintPath, "Shards", folderName);
|
|
3797
|
+
if (!await exists(shardPath)) {
|
|
3798
|
+
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
3799
|
+
}
|
|
3800
|
+
if (folderName.startsWith("(Dev)")) {
|
|
3801
|
+
throw new Error(`"${folderName}" is already a dev shard.`);
|
|
3802
|
+
}
|
|
3803
|
+
if (folderName.startsWith("(Custom)")) {
|
|
3804
|
+
throw new Error(`"${folderName}" is a custom shard. Custom shards cannot be transitioned to dev mode.`);
|
|
3805
|
+
}
|
|
3806
|
+
const baseName = folderName.replace(/^\([^)]*\)\s*/, "");
|
|
3807
|
+
const devFolderName = `(Dev) ${baseName}`;
|
|
3808
|
+
const devPath = join92(flintPath, "Shards", devFolderName);
|
|
3809
|
+
if (await exists(devPath)) {
|
|
3810
|
+
throw new Error(`Dev folder already exists: Shards/${devFolderName}`);
|
|
3811
|
+
}
|
|
3812
|
+
await rename32(shardPath, devPath);
|
|
3813
|
+
if (isOwnerRepo(source)) {
|
|
3814
|
+
const tmpDir = join92(flintPath, ".flint", "_tmp_edit_" + Date.now());
|
|
3815
|
+
try {
|
|
3816
|
+
execSync22(`git clone --depth 1 "${source.includes("github.com") ? source : `https://github.com/${source}.git`}" "${tmpDir}"`, { stdio: "pipe", timeout: 6e4 });
|
|
3817
|
+
await copyDir(join92(tmpDir, ".git"), join92(devPath, ".git"));
|
|
3818
|
+
} catch {
|
|
3819
|
+
execSync22("git init", { cwd: devPath, stdio: "pipe" });
|
|
3820
|
+
} finally {
|
|
3821
|
+
await rm32(tmpDir, { recursive: true, force: true });
|
|
3822
|
+
}
|
|
3823
|
+
} else {
|
|
3824
|
+
execSync22("git init", { cwd: devPath, stdio: "pipe" });
|
|
3825
|
+
}
|
|
3826
|
+
const kebab = toKebabCase(folderName);
|
|
3827
|
+
await removeShardFromConfig(flintPath, kebab);
|
|
3828
|
+
await addShardToConfig(flintPath, devFolderName, isOwnerRepo(source) ? source : `path:./Shards/${devFolderName}`, { mode: "dev" });
|
|
3829
|
+
return { name: devFolderName, path: devPath, oldFolder: folderName };
|
|
3803
3830
|
}
|
|
3804
|
-
function
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3831
|
+
async function freezeShard(flintPath, folderName) {
|
|
3832
|
+
const { execSync: execSync22 } = await import("child_process");
|
|
3833
|
+
const { rename: rename32 } = await import("fs/promises");
|
|
3834
|
+
const shardPath = join92(flintPath, "Shards", folderName);
|
|
3835
|
+
if (!await exists(shardPath)) {
|
|
3836
|
+
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
3837
|
+
}
|
|
3838
|
+
if (!folderName.startsWith("(Dev)")) {
|
|
3839
|
+
throw new Error(`"${folderName}" is not a dev shard.`);
|
|
3840
|
+
}
|
|
3841
|
+
const gitDir = join92(shardPath, ".git");
|
|
3842
|
+
if (!await exists(gitDir)) {
|
|
3843
|
+
throw new Error(`"${folderName}" has no .git directory.`);
|
|
3844
|
+
}
|
|
3845
|
+
try {
|
|
3846
|
+
const status = execSync22("git status --porcelain", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
3847
|
+
if (status) {
|
|
3848
|
+
throw new Error(`"${folderName}" has uncommitted changes. Commit or stash them first.`);
|
|
3808
3849
|
}
|
|
3809
|
-
|
|
3810
|
-
if (
|
|
3811
|
-
|
|
3850
|
+
} catch (err) {
|
|
3851
|
+
if (err instanceof Error && err.message.includes("uncommitted changes")) throw err;
|
|
3852
|
+
}
|
|
3853
|
+
try {
|
|
3854
|
+
const remote = execSync22("git remote get-url origin", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
3855
|
+
if (remote) {
|
|
3856
|
+
const unpushed = execSync22("git log @{u}..HEAD --oneline", { cwd: shardPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
3857
|
+
if (unpushed) {
|
|
3858
|
+
throw new Error(`"${folderName}" has unpushed commits. Push them first.`);
|
|
3859
|
+
}
|
|
3812
3860
|
}
|
|
3813
|
-
|
|
3861
|
+
} catch (err) {
|
|
3862
|
+
if (err instanceof Error && err.message.includes("unpushed commits")) throw err;
|
|
3863
|
+
}
|
|
3864
|
+
const declarations = await getShardDeclarations(flintPath);
|
|
3865
|
+
const kebab = toKebabCase(folderName);
|
|
3866
|
+
const decl = declarations[kebab];
|
|
3867
|
+
const source = decl?.source || "";
|
|
3868
|
+
const baseName = folderName.replace(/^\(Dev\)\s*/, "");
|
|
3869
|
+
const normalPath = join92(flintPath, "Shards", baseName);
|
|
3870
|
+
if (await exists(normalPath)) {
|
|
3871
|
+
throw new Error(`Normal folder already exists: Shards/${baseName}`);
|
|
3872
|
+
}
|
|
3873
|
+
await rm32(gitDir, { recursive: true, force: true });
|
|
3874
|
+
await rename32(shardPath, normalPath);
|
|
3875
|
+
await removeShardFromConfig(flintPath, kebab);
|
|
3876
|
+
const normalSource = isOwnerRepo(source) ? source : `path:./Shards/${baseName}`;
|
|
3877
|
+
await addShardToConfig(flintPath, baseName, normalSource);
|
|
3878
|
+
return { name: baseName, path: normalPath, oldFolder: folderName };
|
|
3879
|
+
}
|
|
3880
|
+
async function addShardGitRemote(flintPath, folderName, url) {
|
|
3881
|
+
const { execSync: execSync22 } = await import("child_process");
|
|
3882
|
+
const shardPath = join92(flintPath, "Shards", folderName);
|
|
3883
|
+
if (!await exists(shardPath)) {
|
|
3884
|
+
throw new Error(`Shard folder not found: Shards/${folderName}`);
|
|
3885
|
+
}
|
|
3886
|
+
if (!folderName.startsWith("(Dev)")) {
|
|
3887
|
+
throw new Error(`"${folderName}" is not a dev shard. Only dev shards can have git remotes added.`);
|
|
3888
|
+
}
|
|
3889
|
+
const gitDir = join92(shardPath, ".git");
|
|
3890
|
+
if (!await exists(gitDir)) {
|
|
3891
|
+
throw new Error(`"${folderName}" has no .git directory. Run git init first.`);
|
|
3892
|
+
}
|
|
3893
|
+
try {
|
|
3894
|
+
const existing = execSync22("git remote get-url origin", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
3895
|
+
if (existing) {
|
|
3896
|
+
throw new Error(`"${folderName}" already has a remote: ${existing}. Use \`git remote set-url origin <url>\` to change it.`);
|
|
3897
|
+
}
|
|
3898
|
+
} catch (err) {
|
|
3899
|
+
if (err instanceof Error && err.message.includes("already has a remote")) throw err;
|
|
3814
3900
|
}
|
|
3815
|
-
|
|
3901
|
+
execSync22(`git remote add origin "${url}"`, { cwd: shardPath, stdio: "pipe" });
|
|
3902
|
+
const match = url.match(/(?:github\.com[/:])([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
3903
|
+
const ownerRepo = match?.[1] || url;
|
|
3904
|
+
const kebab = toKebabCase(folderName);
|
|
3905
|
+
await removeShardFromConfig(flintPath, kebab);
|
|
3906
|
+
await addShardToConfig(flintPath, folderName, ownerRepo, { mode: "dev" });
|
|
3907
|
+
return { ownerRepo };
|
|
3816
3908
|
}
|
|
3817
3909
|
async function countFiles(dirPath) {
|
|
3818
3910
|
try {
|
|
@@ -3882,12 +3974,11 @@ async function checkShardHealth(flintPath) {
|
|
|
3882
3974
|
action: async () => {
|
|
3883
3975
|
const name = folder.replace(/^\([^)]*\)\s*/, "");
|
|
3884
3976
|
const shorthand = name.toLowerCase().replace(/\s+/g, "").slice(0, 4);
|
|
3885
|
-
const yaml = `
|
|
3977
|
+
const yaml = `shard-spec: "0.1.0"
|
|
3978
|
+
version: "0.1.0"
|
|
3886
3979
|
name: ${name}
|
|
3887
3980
|
shorthand: ${shorthand}
|
|
3888
3981
|
description: ${name} shard
|
|
3889
|
-
depends:
|
|
3890
|
-
- core
|
|
3891
3982
|
`;
|
|
3892
3983
|
await writeFile4(join10(shardPath, "shard.yaml"), yaml);
|
|
3893
3984
|
},
|
|
@@ -3929,36 +4020,6 @@ depends:
|
|
|
3929
4020
|
}
|
|
3930
4021
|
}
|
|
3931
4022
|
}
|
|
3932
|
-
const shardDeclarations = await getShardDeclarations(flintPath);
|
|
3933
|
-
for (const folder of installedFolders) {
|
|
3934
|
-
const shardPath = join10(flintPath, "Shards", folder);
|
|
3935
|
-
const manifest = await readShardManifest(shardPath);
|
|
3936
|
-
if (manifest?.depends) {
|
|
3937
|
-
for (const dep of manifest.depends) {
|
|
3938
|
-
const depInstalled = isDepInstalled(dep, installedKebabSet, installedFolders, shardDeclarations);
|
|
3939
|
-
if (!depInstalled) {
|
|
3940
|
-
const healAction = isOwnerRepo(dep) ? {
|
|
3941
|
-
action: async () => {
|
|
3942
|
-
const source = parseShardSource(dep);
|
|
3943
|
-
const resolved = await resolveShardSource(source, flintPath);
|
|
3944
|
-
try {
|
|
3945
|
-
await installShardFromSource(flintPath, resolved.path, resolved.manifest, { source: dep });
|
|
3946
|
-
} finally {
|
|
3947
|
-
await cleanupResolvedSource(resolved);
|
|
3948
|
-
}
|
|
3949
|
-
},
|
|
3950
|
-
actionLabel: `Install dependency ${dep}`
|
|
3951
|
-
} : {};
|
|
3952
|
-
results.push({
|
|
3953
|
-
check: `${folder} \u2192 ${dep}`,
|
|
3954
|
-
status: "warning",
|
|
3955
|
-
message: `Dependency "${dep}" is not installed`,
|
|
3956
|
-
...healAction
|
|
3957
|
-
});
|
|
3958
|
-
}
|
|
3959
|
-
}
|
|
3960
|
-
}
|
|
3961
|
-
}
|
|
3962
4023
|
if (results.length === 0) {
|
|
3963
4024
|
const count = installedFolders.length;
|
|
3964
4025
|
results.push({
|
|
@@ -4071,33 +4132,6 @@ Describe the shard context here.
|
|
|
4071
4132
|
}
|
|
4072
4133
|
}
|
|
4073
4134
|
}
|
|
4074
|
-
if (manifest?.depends) {
|
|
4075
|
-
const installedFolders = await listInstalledShards(flintPath);
|
|
4076
|
-
const installedKebabSet = new Set(installedFolders.map((f) => toKebabCase(f)));
|
|
4077
|
-
for (const dep of manifest.depends) {
|
|
4078
|
-
const depInstalled = isDepInstalled(dep, installedKebabSet, installedFolders, declarations);
|
|
4079
|
-
if (!depInstalled) {
|
|
4080
|
-
const healAction = isOwnerRepo(dep) ? {
|
|
4081
|
-
action: async () => {
|
|
4082
|
-
const source = parseShardSource(dep);
|
|
4083
|
-
const resolved = await resolveShardSource(source, flintPath);
|
|
4084
|
-
try {
|
|
4085
|
-
await installShardFromSource(flintPath, resolved.path, resolved.manifest, { source: dep });
|
|
4086
|
-
} finally {
|
|
4087
|
-
await cleanupResolvedSource(resolved);
|
|
4088
|
-
}
|
|
4089
|
-
},
|
|
4090
|
-
actionLabel: `Install dependency ${dep}`
|
|
4091
|
-
} : {};
|
|
4092
|
-
results.push({
|
|
4093
|
-
check: `dependency: ${dep}`,
|
|
4094
|
-
status: "warning",
|
|
4095
|
-
message: `Not installed`,
|
|
4096
|
-
...healAction
|
|
4097
|
-
});
|
|
4098
|
-
}
|
|
4099
|
-
}
|
|
4100
|
-
}
|
|
4101
4135
|
const checkFilePrefix = async (dir, prefix) => {
|
|
4102
4136
|
try {
|
|
4103
4137
|
const entries = await readdir42(join10(shardPath, dir), { withFileTypes: true });
|
|
@@ -4128,6 +4162,20 @@ Describe the shard context here.
|
|
|
4128
4162
|
}
|
|
4129
4163
|
return results;
|
|
4130
4164
|
}
|
|
4165
|
+
async function healAllShards(flintPath) {
|
|
4166
|
+
const allResults = {};
|
|
4167
|
+
const installedFolders = await listInstalledShards(flintPath);
|
|
4168
|
+
await Promise.all(installedFolders.map(async (folder) => {
|
|
4169
|
+
const results = await healShard(flintPath, folder);
|
|
4170
|
+
for (const result of results) {
|
|
4171
|
+
if (result.action) {
|
|
4172
|
+
await result.action();
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
allResults[folder] = results;
|
|
4176
|
+
}));
|
|
4177
|
+
return allResults;
|
|
4178
|
+
}
|
|
4131
4179
|
async function getShardInfo(flintPath, identifier) {
|
|
4132
4180
|
const declarations = await getShardDeclarations(flintPath);
|
|
4133
4181
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
@@ -4145,10 +4193,9 @@ async function getShardInfo(flintPath, identifier) {
|
|
|
4145
4193
|
version: match.version,
|
|
4146
4194
|
description: manifest?.description || "",
|
|
4147
4195
|
source: decl?.source || "unknown",
|
|
4148
|
-
dev: decl ? resolveShardMode(decl) === "dev"
|
|
4196
|
+
dev: decl ? resolveShardMode(decl) === "dev" : false,
|
|
4149
4197
|
mode: decl ? resolveShardMode(decl) || "normal" : "normal",
|
|
4150
4198
|
folderName: match.folderName,
|
|
4151
|
-
depends: manifest?.depends || [],
|
|
4152
4199
|
skillCount: await countFiles(join10(shardPath, "skills")),
|
|
4153
4200
|
templateCount: await countFiles(join10(shardPath, "templates")),
|
|
4154
4201
|
workflowCount: await countFiles(join10(shardPath, "workflows")),
|
|
@@ -4229,7 +4276,7 @@ async function findScript(scriptsDir, scriptName) {
|
|
|
4229
4276
|
}
|
|
4230
4277
|
async function isExecutable(filePath) {
|
|
4231
4278
|
try {
|
|
4232
|
-
await
|
|
4279
|
+
await access3(filePath, constants.X_OK);
|
|
4233
4280
|
return true;
|
|
4234
4281
|
} catch {
|
|
4235
4282
|
return false;
|
|
@@ -4302,12 +4349,7 @@ async function runShardScript(flintPath, shardIdentifier, scriptName, args = [])
|
|
|
4302
4349
|
});
|
|
4303
4350
|
});
|
|
4304
4351
|
}
|
|
4305
|
-
|
|
4306
|
-
return [];
|
|
4307
|
-
}
|
|
4308
|
-
async function getBuiltinMod(shorthand) {
|
|
4309
|
-
return null;
|
|
4310
|
-
}
|
|
4352
|
+
var execAsync4 = promisify42(exec4);
|
|
4311
4353
|
function isOwnerRepo2(s) {
|
|
4312
4354
|
return /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/.test(s);
|
|
4313
4355
|
}
|
|
@@ -4365,8 +4407,7 @@ async function resolveModSource(source, flintPath) {
|
|
|
4365
4407
|
async function cloneAndResolve2(url, source) {
|
|
4366
4408
|
const tempDir = await mkdtemp2(join12(tmpdir2(), "flint-mod-"));
|
|
4367
4409
|
try {
|
|
4368
|
-
|
|
4369
|
-
stdio: "pipe",
|
|
4410
|
+
await execAsync4(`git clone --depth 1 ${url} "${tempDir}"`, {
|
|
4370
4411
|
timeout: 6e4
|
|
4371
4412
|
// 60 second timeout
|
|
4372
4413
|
});
|
|
@@ -4462,7 +4503,7 @@ function renderTemplate(template, variables) {
|
|
|
4462
4503
|
}
|
|
4463
4504
|
function runCommand(flintPath, command) {
|
|
4464
4505
|
try {
|
|
4465
|
-
|
|
4506
|
+
execSync(command, {
|
|
4466
4507
|
cwd: flintPath,
|
|
4467
4508
|
stdio: "pipe",
|
|
4468
4509
|
timeout: 3e4
|
|
@@ -4509,7 +4550,7 @@ async function processInstallEntries(flintPath, mod, variables, options) {
|
|
|
4509
4550
|
continue;
|
|
4510
4551
|
}
|
|
4511
4552
|
if (await exists(destFilePath)) {
|
|
4512
|
-
const mode = entry.mode ??
|
|
4553
|
+
const mode = entry.mode ?? "once";
|
|
4513
4554
|
if (!options?.force && mode === "once") continue;
|
|
4514
4555
|
if (mode === "force" || options?.force) {
|
|
4515
4556
|
try {
|
|
@@ -4567,16 +4608,7 @@ async function installMod(flintPath, shorthand, options = {}) {
|
|
|
4567
4608
|
}
|
|
4568
4609
|
}
|
|
4569
4610
|
}
|
|
4570
|
-
|
|
4571
|
-
if (!mod) {
|
|
4572
|
-
const available = await listBuiltinMods();
|
|
4573
|
-
const shorthands = available.map((m) => m.shorthand).join(", ");
|
|
4574
|
-
throw new Error(`Unknown mod: ${shorthand}. Available: ${shorthands || "none"}`);
|
|
4575
|
-
}
|
|
4576
|
-
return installModFromSource(flintPath, mod.path, mod, {
|
|
4577
|
-
source: options.source || "builtin",
|
|
4578
|
-
force: options.force
|
|
4579
|
-
});
|
|
4611
|
+
throw new Error(`Unknown mod: ${shorthand}. Provide a source (owner/repo or path:./local).`);
|
|
4580
4612
|
}
|
|
4581
4613
|
async function installModFromSource(flintPath, sourcePath, mod, options = {}) {
|
|
4582
4614
|
const destPath = join13(flintPath, "Mods", mod.name);
|
|
@@ -4661,11 +4693,7 @@ async function uninstallMod(flintPath, shorthand) {
|
|
|
4661
4693
|
return { name: modName, removed: true };
|
|
4662
4694
|
}
|
|
4663
4695
|
async function listAvailableMods() {
|
|
4664
|
-
return
|
|
4665
|
-
}
|
|
4666
|
-
async function isModInstalled(flintPath, shorthand) {
|
|
4667
|
-
const folder = await findInstalledModFolder(flintPath, shorthand);
|
|
4668
|
-
return folder !== null;
|
|
4696
|
+
return [];
|
|
4669
4697
|
}
|
|
4670
4698
|
async function findInstalledModFolder(flintPath, identifier) {
|
|
4671
4699
|
const modsDir = join13(flintPath, "Mods");
|
|
@@ -4751,27 +4779,13 @@ async function updateMods(flintPath, options = {}) {
|
|
|
4751
4779
|
}
|
|
4752
4780
|
}
|
|
4753
4781
|
if (!source || source === "builtin") {
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
status: "updated",
|
|
4762
|
-
localVersion: info2.version,
|
|
4763
|
-
remoteVersion: mod.version
|
|
4764
|
-
});
|
|
4765
|
-
} catch {
|
|
4766
|
-
results.push({
|
|
4767
|
-
name: info2.name,
|
|
4768
|
-
path: join13(flintPath, "Mods", info2.folderName),
|
|
4769
|
-
status: "failed",
|
|
4770
|
-
localVersion: info2.version,
|
|
4771
|
-
reason: "failed to reinstall from registry"
|
|
4772
|
-
});
|
|
4773
|
-
}
|
|
4774
|
-
}
|
|
4782
|
+
results.push({
|
|
4783
|
+
name: info2.name,
|
|
4784
|
+
path: join13(flintPath, "Mods", info2.folderName),
|
|
4785
|
+
status: "failed",
|
|
4786
|
+
localVersion: info2.version,
|
|
4787
|
+
reason: "no source configured (builtin mods no longer supported)"
|
|
4788
|
+
});
|
|
4775
4789
|
continue;
|
|
4776
4790
|
}
|
|
4777
4791
|
const parsed = parseModSource(source);
|
|
@@ -4890,22 +4904,6 @@ async function getModInfo(flintPath, identifier) {
|
|
|
4890
4904
|
}
|
|
4891
4905
|
} catch {
|
|
4892
4906
|
}
|
|
4893
|
-
const mod = await getBuiltinMod(identifier);
|
|
4894
|
-
if (mod) {
|
|
4895
|
-
return {
|
|
4896
|
-
name: mod.name,
|
|
4897
|
-
shorthand: mod.shorthand,
|
|
4898
|
-
version: mod.version,
|
|
4899
|
-
description: mod.description,
|
|
4900
|
-
folderName: mod.name,
|
|
4901
|
-
source: "builtin",
|
|
4902
|
-
dev: false,
|
|
4903
|
-
repos: mod.repos || [],
|
|
4904
|
-
folders: mod.folders || [],
|
|
4905
|
-
installEntries: mod.install?.length || 0,
|
|
4906
|
-
commands: mod.commands || {}
|
|
4907
|
-
};
|
|
4908
|
-
}
|
|
4909
4907
|
return null;
|
|
4910
4908
|
}
|
|
4911
4909
|
async function scaffoldNewMod(flintPath, name, shorthand, description) {
|
|
@@ -5019,14 +5017,14 @@ async function pullMod(flintPath, identifier, options) {
|
|
|
5019
5017
|
const repoDir = join13(reposDir, repo.name);
|
|
5020
5018
|
if (await exists(repoDir)) {
|
|
5021
5019
|
try {
|
|
5022
|
-
|
|
5020
|
+
execSync("git pull", { cwd: repoDir, stdio: "pipe", timeout: 3e4 });
|
|
5023
5021
|
result.reposPulled++;
|
|
5024
5022
|
} catch {
|
|
5025
5023
|
}
|
|
5026
5024
|
} else {
|
|
5027
5025
|
try {
|
|
5028
5026
|
const branch = repo.branch ? `-b ${repo.branch}` : "";
|
|
5029
|
-
|
|
5027
|
+
execSync(`git clone ${branch} "${repo.url}" "${repoDir}"`, { stdio: "pipe", timeout: 6e4 });
|
|
5030
5028
|
result.reposCloned++;
|
|
5031
5029
|
} catch {
|
|
5032
5030
|
}
|
|
@@ -5337,7 +5335,7 @@ async function runModScript(flintPath, identifier, scriptName, args = []) {
|
|
|
5337
5335
|
cmd = `"${script.path}" ${args.join(" ")}`;
|
|
5338
5336
|
}
|
|
5339
5337
|
try {
|
|
5340
|
-
const result =
|
|
5338
|
+
const result = execSync(cmd, {
|
|
5341
5339
|
cwd: flintPath,
|
|
5342
5340
|
timeout: 6e4,
|
|
5343
5341
|
encoding: "utf-8"
|
|
@@ -5526,7 +5524,7 @@ async function getConnectionStatus(flintPath) {
|
|
|
5526
5524
|
status.path = fulfillment.path;
|
|
5527
5525
|
status.fulfilledAt = fulfillment.fulfilled;
|
|
5528
5526
|
try {
|
|
5529
|
-
await
|
|
5527
|
+
await access4(fulfillment.path);
|
|
5530
5528
|
const isFlint2 = await isInsideFlint(fulfillment.path);
|
|
5531
5529
|
status.valid = isFlint2;
|
|
5532
5530
|
} catch {
|
|
@@ -5613,12 +5611,16 @@ async function buildGitignoreEntries(flintPath) {
|
|
|
5613
5611
|
const sections = [];
|
|
5614
5612
|
sections.push({
|
|
5615
5613
|
label: "Flint internals",
|
|
5616
|
-
entries: [".flint/", ".obsidian/", ".mesh/"]
|
|
5614
|
+
entries: [".flint/", ".obsidian/", ".mesh/", ".orbh/"]
|
|
5615
|
+
});
|
|
5616
|
+
sections.push({
|
|
5617
|
+
label: "Subflints",
|
|
5618
|
+
entries: ["Subflints/"]
|
|
5617
5619
|
});
|
|
5618
|
-
const shardEntries = buildShardEntries(
|
|
5620
|
+
const shardEntries = await buildShardEntries(flintPath);
|
|
5619
5621
|
if (shardEntries.length > 0) {
|
|
5620
5622
|
sections.push({
|
|
5621
|
-
label: "Shards (
|
|
5623
|
+
label: "Shards (git-managed)",
|
|
5622
5624
|
entries: shardEntries
|
|
5623
5625
|
});
|
|
5624
5626
|
}
|
|
@@ -5655,18 +5657,20 @@ function buildWorkspaceEntries(config) {
|
|
|
5655
5657
|
}
|
|
5656
5658
|
return entries;
|
|
5657
5659
|
}
|
|
5658
|
-
function buildShardEntries(
|
|
5659
|
-
|
|
5660
|
+
async function buildShardEntries(flintPath) {
|
|
5661
|
+
const shardsDir = join15(flintPath, "Shards");
|
|
5662
|
+
if (!await exists(shardsDir)) return [];
|
|
5660
5663
|
const entries = [];
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
const
|
|
5664
|
-
|
|
5665
|
-
const
|
|
5666
|
-
if (
|
|
5667
|
-
entries.push(`Shards/${
|
|
5664
|
+
try {
|
|
5665
|
+
const folders = await readdir7(shardsDir, { withFileTypes: true });
|
|
5666
|
+
for (const folder of folders) {
|
|
5667
|
+
if (!folder.isDirectory() || folder.name.startsWith("(System)")) continue;
|
|
5668
|
+
const gitDir = join15(shardsDir, folder.name, ".git");
|
|
5669
|
+
if (await exists(gitDir)) {
|
|
5670
|
+
entries.push(`Shards/${folder.name}/`);
|
|
5668
5671
|
}
|
|
5669
5672
|
}
|
|
5673
|
+
} catch {
|
|
5670
5674
|
}
|
|
5671
5675
|
return entries.sort();
|
|
5672
5676
|
}
|
|
@@ -5728,15 +5732,28 @@ ${MANAGED_SECTION_END}`;
|
|
|
5728
5732
|
function escapeRegex(str) {
|
|
5729
5733
|
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
5730
5734
|
}
|
|
5731
|
-
var
|
|
5735
|
+
var execAsync5 = promisify52(exec5);
|
|
5732
5736
|
async function isGitInitialized(flintPath) {
|
|
5733
5737
|
try {
|
|
5734
|
-
await
|
|
5738
|
+
await execAsync5("git rev-parse --git-dir", { cwd: flintPath });
|
|
5735
5739
|
return true;
|
|
5736
5740
|
} catch {
|
|
5737
5741
|
return false;
|
|
5738
5742
|
}
|
|
5739
5743
|
}
|
|
5744
|
+
async function initGit(flintPath) {
|
|
5745
|
+
try {
|
|
5746
|
+
await execAsync5("git init", { cwd: flintPath });
|
|
5747
|
+
await createGitignore(flintPath);
|
|
5748
|
+
return { success: true, output: "Git initialized with .gitignore" };
|
|
5749
|
+
} catch (err) {
|
|
5750
|
+
return {
|
|
5751
|
+
success: false,
|
|
5752
|
+
output: "",
|
|
5753
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5754
|
+
};
|
|
5755
|
+
}
|
|
5756
|
+
}
|
|
5740
5757
|
async function getGitStatus(flintPath) {
|
|
5741
5758
|
const initialized = await isGitInitialized(flintPath);
|
|
5742
5759
|
if (!initialized) {
|
|
@@ -5749,10 +5766,10 @@ async function getGitStatus(flintPath) {
|
|
|
5749
5766
|
};
|
|
5750
5767
|
}
|
|
5751
5768
|
try {
|
|
5752
|
-
const { stdout: branchOut } = await
|
|
5769
|
+
const { stdout: branchOut } = await execAsync5("git branch --show-current", {
|
|
5753
5770
|
cwd: flintPath
|
|
5754
5771
|
});
|
|
5755
|
-
const { stdout: statusOut } = await
|
|
5772
|
+
const { stdout: statusOut } = await execAsync5("git status --porcelain", {
|
|
5756
5773
|
cwd: flintPath
|
|
5757
5774
|
});
|
|
5758
5775
|
const lines = statusOut.trim().split("\n").filter(Boolean);
|
|
@@ -5794,7 +5811,7 @@ async function runGit(flintPath, args) {
|
|
|
5794
5811
|
const quotedArgs = args.map(
|
|
5795
5812
|
(arg) => arg.includes(" ") ? `"${arg}"` : arg
|
|
5796
5813
|
);
|
|
5797
|
-
const { stdout, stderr } = await
|
|
5814
|
+
const { stdout, stderr } = await execAsync5(`git ${quotedArgs.join(" ")}`, {
|
|
5798
5815
|
cwd: flintPath
|
|
5799
5816
|
});
|
|
5800
5817
|
return { success: true, output: stdout || stderr };
|
|
@@ -5843,7 +5860,7 @@ async function loadPresetFromDir(presetDir) {
|
|
|
5843
5860
|
async function discoverPresetsFromDir(presetsDir) {
|
|
5844
5861
|
const presets = /* @__PURE__ */ new Map();
|
|
5845
5862
|
try {
|
|
5846
|
-
const entries = await
|
|
5863
|
+
const entries = await readdir8(presetsDir, { withFileTypes: true });
|
|
5847
5864
|
for (const entry of entries) {
|
|
5848
5865
|
if (!entry.isDirectory()) continue;
|
|
5849
5866
|
const presetDir = join16(presetsDir, entry.name);
|
|
@@ -5908,7 +5925,7 @@ async function discoverSubflints(flintPath) {
|
|
|
5908
5925
|
const discovered = [];
|
|
5909
5926
|
let entries;
|
|
5910
5927
|
try {
|
|
5911
|
-
entries = await
|
|
5928
|
+
entries = await readdir9(subflintsDir, { withFileTypes: true });
|
|
5912
5929
|
} catch (err) {
|
|
5913
5930
|
if (err.code === "ENOENT") {
|
|
5914
5931
|
return discovered;
|
|
@@ -5952,7 +5969,7 @@ async function createSubflint(flintPath, options) {
|
|
|
5952
5969
|
}
|
|
5953
5970
|
const subflintPath = getSubflintPath(flintPath, name);
|
|
5954
5971
|
try {
|
|
5955
|
-
await
|
|
5972
|
+
await access5(subflintPath);
|
|
5956
5973
|
throw new Error(`Subflint "${name}" already exists`);
|
|
5957
5974
|
} catch (err) {
|
|
5958
5975
|
if (err.code !== "ENOENT") {
|
|
@@ -5995,14 +6012,14 @@ async function promoteSubflint(flintPath, options) {
|
|
|
5995
6012
|
}
|
|
5996
6013
|
const sourcePath = subflint.path;
|
|
5997
6014
|
try {
|
|
5998
|
-
await
|
|
6015
|
+
await access5(sourcePath);
|
|
5999
6016
|
} catch {
|
|
6000
6017
|
throw new Error(`Subflint path not found: ${sourcePath}`);
|
|
6001
6018
|
}
|
|
6002
6019
|
const targetPath = join17(destination, `(Flint) ${name}`);
|
|
6003
6020
|
await mkdir10(destination, { recursive: true });
|
|
6004
6021
|
try {
|
|
6005
|
-
await
|
|
6022
|
+
await access5(targetPath);
|
|
6006
6023
|
throw new Error(`Target already exists: ${targetPath}`);
|
|
6007
6024
|
} catch (err) {
|
|
6008
6025
|
if (err.code !== "ENOENT") {
|
|
@@ -6052,7 +6069,7 @@ async function syncSubflintName(flintPath, currentName) {
|
|
|
6052
6069
|
}
|
|
6053
6070
|
const targetPath = getSubflintPath(flintPath, configName);
|
|
6054
6071
|
try {
|
|
6055
|
-
await
|
|
6072
|
+
await access5(targetPath);
|
|
6056
6073
|
throw new Error(
|
|
6057
6074
|
`Cannot rename: subflint "${configName}" already exists at ${targetPath}`
|
|
6058
6075
|
);
|
|
@@ -6081,7 +6098,7 @@ function getSubflintParentPath(flintPath) {
|
|
|
6081
6098
|
}
|
|
6082
6099
|
return dirname6(subflintsDir);
|
|
6083
6100
|
}
|
|
6084
|
-
async function syncFlint(flintPath) {
|
|
6101
|
+
async function syncFlint(flintPath, progress) {
|
|
6085
6102
|
const result = {
|
|
6086
6103
|
bootstrap: { created: false, directories: [] },
|
|
6087
6104
|
migrations: { applied: [], skipped: [], failed: [] },
|
|
@@ -6163,28 +6180,76 @@ async function syncFlint(flintPath) {
|
|
|
6163
6180
|
const shardsToInstall = requiredShardNames.filter((name) => !installedShardNames.has(name));
|
|
6164
6181
|
const requiredShardSet = new Set(requiredShardNames);
|
|
6165
6182
|
const shardsToUninstall = installedShards.filter((s) => !requiredShardSet.has(s.name)).map((s) => s.name);
|
|
6166
|
-
|
|
6167
|
-
const
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
const
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6183
|
+
{
|
|
6184
|
+
const { exec: execCb } = await import("child_process");
|
|
6185
|
+
const { promisify: promisify62 } = await import("util");
|
|
6186
|
+
const execAsync62 = promisify62(execCb);
|
|
6187
|
+
const shardTasks = [];
|
|
6188
|
+
for (const kebabName of shardsToInstall) {
|
|
6189
|
+
const declaration = shardDeclarations[kebabName];
|
|
6190
|
+
if (!declaration) continue;
|
|
6191
|
+
const mode = declaration.mode;
|
|
6192
|
+
if (mode === "dev") {
|
|
6193
|
+
const source = declaration.source;
|
|
6194
|
+
if (source.startsWith("path:")) {
|
|
6195
|
+
result.errors.push({
|
|
6196
|
+
name: `shard:${kebabName}`,
|
|
6197
|
+
error: `Dev shard has no remote source (${source}) \u2014 cannot sync. Add a git remote first.`
|
|
6198
|
+
});
|
|
6199
|
+
continue;
|
|
6200
|
+
}
|
|
6201
|
+
shardTasks.push({
|
|
6202
|
+
name: kebabName,
|
|
6203
|
+
run: async () => {
|
|
6204
|
+
const folderName = `(Dev) ${kebabName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ")}`;
|
|
6205
|
+
const devPath = join18(flintPath, "Shards", folderName);
|
|
6206
|
+
const cloneUrl = `https://github.com/${source}.git`;
|
|
6207
|
+
await execAsync62(`git clone "${cloneUrl}" "${devPath}"`, { timeout: 6e4 });
|
|
6208
|
+
}
|
|
6209
|
+
});
|
|
6210
|
+
continue;
|
|
6211
|
+
}
|
|
6212
|
+
if (mode === "custom") {
|
|
6213
|
+
result.errors.push({
|
|
6214
|
+
name: `shard:${kebabName}`,
|
|
6215
|
+
error: `Custom shard folder missing \u2014 custom shards should be committed to the repository.`
|
|
6216
|
+
});
|
|
6217
|
+
continue;
|
|
6218
|
+
}
|
|
6219
|
+
shardTasks.push({
|
|
6220
|
+
name: kebabName,
|
|
6221
|
+
run: async () => {
|
|
6222
|
+
const source = parseShardSource(declaration.source);
|
|
6223
|
+
const resolved = await resolveShardSource(source, flintPath);
|
|
6224
|
+
try {
|
|
6225
|
+
await installShardFromSource(flintPath, resolved.path, resolved.manifest, {
|
|
6226
|
+
force: true,
|
|
6227
|
+
source: declaration.source
|
|
6228
|
+
});
|
|
6229
|
+
} finally {
|
|
6230
|
+
await cleanupResolvedSource(resolved);
|
|
6231
|
+
}
|
|
6232
|
+
}
|
|
6186
6233
|
});
|
|
6187
6234
|
}
|
|
6235
|
+
progress?.onShardPhase?.(shardTasks.length);
|
|
6236
|
+
if (shardTasks.length > 0) {
|
|
6237
|
+
const shardResults = await runConcurrent(shardTasks, {
|
|
6238
|
+
onStart: progress?.onShardStart,
|
|
6239
|
+
onComplete: (name) => progress?.onShardDone?.(name, true),
|
|
6240
|
+
onError: (name) => progress?.onShardDone?.(name, false)
|
|
6241
|
+
});
|
|
6242
|
+
for (const r of shardResults) {
|
|
6243
|
+
if (r.status === "ok") {
|
|
6244
|
+
result.shards.installed.push(r.name);
|
|
6245
|
+
} else {
|
|
6246
|
+
result.errors.push({
|
|
6247
|
+
name: `shard:${r.name}`,
|
|
6248
|
+
error: r.error?.message || "Unknown error"
|
|
6249
|
+
});
|
|
6250
|
+
}
|
|
6251
|
+
}
|
|
6252
|
+
}
|
|
6188
6253
|
}
|
|
6189
6254
|
for (const kebabName of shardsToUninstall) {
|
|
6190
6255
|
result.shards.orphaned.push(kebabName);
|
|
@@ -6209,16 +6274,29 @@ async function syncFlint(flintPath) {
|
|
|
6209
6274
|
const installedModNames = new Set(installedMods.map((m) => toKebabCase(m.name)));
|
|
6210
6275
|
const modsToInstall = [...declaredModNames].filter((name) => !installedModNames.has(name));
|
|
6211
6276
|
const modsToUninstall = installedMods.filter((m) => !declaredModNames.has(toKebabCase(m.name))).map((m) => m.shorthand);
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
|
|
6218
|
-
|
|
6219
|
-
|
|
6220
|
-
|
|
6221
|
-
|
|
6277
|
+
progress?.onModPhase?.(modsToInstall.length);
|
|
6278
|
+
if (modsToInstall.length > 0) {
|
|
6279
|
+
const modTasks = modsToInstall.map((kebabName) => ({
|
|
6280
|
+
name: kebabName,
|
|
6281
|
+
run: async () => {
|
|
6282
|
+
const declaration = modDeclarations[kebabName];
|
|
6283
|
+
await installMod(flintPath, kebabName, { force: true, source: declaration?.source });
|
|
6284
|
+
}
|
|
6285
|
+
}));
|
|
6286
|
+
const modResults = await runConcurrent(modTasks, {
|
|
6287
|
+
onStart: progress?.onModStart,
|
|
6288
|
+
onComplete: (name) => progress?.onModDone?.(name, true),
|
|
6289
|
+
onError: (name) => progress?.onModDone?.(name, false)
|
|
6290
|
+
});
|
|
6291
|
+
for (const r of modResults) {
|
|
6292
|
+
if (r.status === "ok") {
|
|
6293
|
+
result.mods.installed.push(r.name);
|
|
6294
|
+
} else {
|
|
6295
|
+
result.errors.push({
|
|
6296
|
+
name: `mod:${r.name}`,
|
|
6297
|
+
error: r.error?.message || "Unknown error"
|
|
6298
|
+
});
|
|
6299
|
+
}
|
|
6222
6300
|
}
|
|
6223
6301
|
}
|
|
6224
6302
|
for (const shorthand of modsToUninstall) {
|
|
@@ -6239,18 +6317,18 @@ async function syncFlint(flintPath) {
|
|
|
6239
6317
|
}
|
|
6240
6318
|
result.modCommands = await runModSyncCommands(flintPath);
|
|
6241
6319
|
const requiredImports = config.imports?.flints || config.imports?.required || [];
|
|
6242
|
-
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-
|
|
6243
|
-
const { readdir:
|
|
6320
|
+
const { getFlintRegistry: getFlintRegistry2 } = await import("./registry-5PUMDGQP-YVSEVBB4.js");
|
|
6321
|
+
const { readdir: readdir102, readFile: fsReadFile2, writeFile: fsWriteFile2, rm: rm82, stat: fsStat } = await import("fs/promises");
|
|
6244
6322
|
const requiredImportSet = new Set(requiredImports);
|
|
6245
6323
|
const importsDir = join18(flintPath, "Imports");
|
|
6246
6324
|
try {
|
|
6247
|
-
const flintFolders = await
|
|
6325
|
+
const flintFolders = await readdir102(importsDir, { withFileTypes: true });
|
|
6248
6326
|
for (const flintFolder of flintFolders) {
|
|
6249
6327
|
if (!flintFolder.isDirectory()) continue;
|
|
6250
6328
|
const flintFolderName = flintFolder.name;
|
|
6251
6329
|
const flintName = flintFolderName.replace(/^\(Flint\)\s*/, "");
|
|
6252
6330
|
const flintImportPath = join18(importsDir, flintFolderName);
|
|
6253
|
-
const exportFolders = await
|
|
6331
|
+
const exportFolders = await readdir102(flintImportPath, { withFileTypes: true });
|
|
6254
6332
|
for (const exportFolder of exportFolders) {
|
|
6255
6333
|
if (!exportFolder.isDirectory()) continue;
|
|
6256
6334
|
const exportFolderName = exportFolder.name;
|
|
@@ -6270,7 +6348,7 @@ async function syncFlint(flintPath) {
|
|
|
6270
6348
|
}
|
|
6271
6349
|
}
|
|
6272
6350
|
}
|
|
6273
|
-
const remainingExports = await
|
|
6351
|
+
const remainingExports = await readdir102(flintImportPath);
|
|
6274
6352
|
if (remainingExports.length === 0) {
|
|
6275
6353
|
try {
|
|
6276
6354
|
await rm82(flintImportPath, { recursive: true });
|
|
@@ -6282,7 +6360,7 @@ async function syncFlint(flintPath) {
|
|
|
6282
6360
|
}
|
|
6283
6361
|
if (requiredImports.length > 0) {
|
|
6284
6362
|
const registry = await getFlintRegistry2();
|
|
6285
|
-
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-
|
|
6363
|
+
const { buildExportByName: buildExportByName2, scanExports: scanExports2 } = await import("./exports-KXKBTYJ2-A3QWNDEB.js");
|
|
6286
6364
|
for (const ref of requiredImports) {
|
|
6287
6365
|
const parts = ref.split("/");
|
|
6288
6366
|
if (parts.length !== 2) {
|
|
@@ -6305,7 +6383,7 @@ async function syncFlint(flintPath) {
|
|
|
6305
6383
|
const manifests = await scanExports2(sourceFlint.path);
|
|
6306
6384
|
const hasExportManifest = manifests.some((m) => m.name === exportName);
|
|
6307
6385
|
if (!hasExportManifest) {
|
|
6308
|
-
result.imports.push({ ref, status: "
|
|
6386
|
+
result.imports.push({ ref, status: "export_not_found", error: `export '${exportName}' not found in '${flintName}'` });
|
|
6309
6387
|
continue;
|
|
6310
6388
|
}
|
|
6311
6389
|
try {
|
|
@@ -6335,7 +6413,7 @@ async function syncFlint(flintPath) {
|
|
|
6335
6413
|
} catch {
|
|
6336
6414
|
}
|
|
6337
6415
|
await mkdir11(destPath, { recursive: true });
|
|
6338
|
-
const entries = await
|
|
6416
|
+
const entries = await readdir102(sourcePath, { withFileTypes: true });
|
|
6339
6417
|
let fileCount = 0;
|
|
6340
6418
|
for (const entry of entries) {
|
|
6341
6419
|
if (entry.isFile() && entry.name !== "_manifest.json") {
|
|
@@ -6439,8 +6517,22 @@ async function syncFlint(flintPath) {
|
|
|
6439
6517
|
}
|
|
6440
6518
|
const connectionsMigration = await migrateConnections(currentFlintPath);
|
|
6441
6519
|
result.connectionsMigrated = connectionsMigration.migrated;
|
|
6442
|
-
|
|
6443
|
-
|
|
6520
|
+
try {
|
|
6521
|
+
await writeFlintToml(currentFlintPath, config);
|
|
6522
|
+
} catch (err) {
|
|
6523
|
+
result.errors.push({
|
|
6524
|
+
name: "flint.toml",
|
|
6525
|
+
error: `Failed to write flint.toml: ${err instanceof Error ? err.message : String(err)}`
|
|
6526
|
+
});
|
|
6527
|
+
}
|
|
6528
|
+
try {
|
|
6529
|
+
await updateGitignore(currentFlintPath);
|
|
6530
|
+
} catch (err) {
|
|
6531
|
+
result.errors.push({
|
|
6532
|
+
name: "gitignore",
|
|
6533
|
+
error: `Failed to update .gitignore: ${err instanceof Error ? err.message : String(err)}`
|
|
6534
|
+
});
|
|
6535
|
+
}
|
|
6444
6536
|
try {
|
|
6445
6537
|
await stampSynced(currentFlintPath);
|
|
6446
6538
|
} catch {
|
|
@@ -6448,9 +6540,64 @@ async function syncFlint(flintPath) {
|
|
|
6448
6540
|
return result;
|
|
6449
6541
|
}
|
|
6450
6542
|
|
|
6543
|
+
// src/progress.ts
|
|
6544
|
+
import pc5 from "picocolors";
|
|
6545
|
+
function createProgressDisplay(label, total) {
|
|
6546
|
+
if (total === 0) {
|
|
6547
|
+
return { onStart() {
|
|
6548
|
+
}, onComplete() {
|
|
6549
|
+
}, onError() {
|
|
6550
|
+
}, finish() {
|
|
6551
|
+
} };
|
|
6552
|
+
}
|
|
6553
|
+
const isTTY = process.stdout.isTTY;
|
|
6554
|
+
let completed = 0;
|
|
6555
|
+
let failures = 0;
|
|
6556
|
+
let finished = false;
|
|
6557
|
+
let linesBelow = 0;
|
|
6558
|
+
console.log(pc5.bold(label));
|
|
6559
|
+
return {
|
|
6560
|
+
onStart(_name) {
|
|
6561
|
+
},
|
|
6562
|
+
onComplete(name) {
|
|
6563
|
+
completed++;
|
|
6564
|
+
linesBelow++;
|
|
6565
|
+
console.log(` ${pc5.green("\u2713")} ${name}`);
|
|
6566
|
+
},
|
|
6567
|
+
onError(name) {
|
|
6568
|
+
completed++;
|
|
6569
|
+
failures++;
|
|
6570
|
+
linesBelow++;
|
|
6571
|
+
console.log(` ${pc5.red("\u2717")} ${name}`);
|
|
6572
|
+
},
|
|
6573
|
+
finish() {
|
|
6574
|
+
if (finished) return;
|
|
6575
|
+
finished = true;
|
|
6576
|
+
const successes = completed - failures;
|
|
6577
|
+
let summary = `${pc5.bold(label)} `;
|
|
6578
|
+
if (failures === 0) {
|
|
6579
|
+
summary += pc5.green(`\u2713 ${successes} done`);
|
|
6580
|
+
} else {
|
|
6581
|
+
summary += `${pc5.green(`\u2713 ${successes} done`)} ${pc5.red(`\u2717 ${failures} failed`)}`;
|
|
6582
|
+
}
|
|
6583
|
+
if (isTTY) {
|
|
6584
|
+
const up = linesBelow + 1;
|
|
6585
|
+
process.stdout.write(
|
|
6586
|
+
`\x1B[${up}A\x1B[2K\r` + // clear line
|
|
6587
|
+
summary + // write summary
|
|
6588
|
+
`\x1B[${up}B\r`
|
|
6589
|
+
// back down to original position
|
|
6590
|
+
);
|
|
6591
|
+
} else {
|
|
6592
|
+
console.log(summary);
|
|
6593
|
+
}
|
|
6594
|
+
}
|
|
6595
|
+
};
|
|
6596
|
+
}
|
|
6597
|
+
|
|
6451
6598
|
// src/utils.ts
|
|
6452
6599
|
import { homedir as homedir4 } from "os";
|
|
6453
|
-
import { access as
|
|
6600
|
+
import { access as access6 } from "fs/promises";
|
|
6454
6601
|
import { createInterface } from "readline";
|
|
6455
6602
|
function abbreviatePath(path3) {
|
|
6456
6603
|
const home = homedir4();
|
|
@@ -6467,7 +6614,7 @@ function expandPath(path3) {
|
|
|
6467
6614
|
}
|
|
6468
6615
|
async function checkPathExists(path3) {
|
|
6469
6616
|
try {
|
|
6470
|
-
await
|
|
6617
|
+
await access6(path3);
|
|
6471
6618
|
return true;
|
|
6472
6619
|
} catch {
|
|
6473
6620
|
return false;
|
|
@@ -6487,120 +6634,37 @@ async function confirm(message) {
|
|
|
6487
6634
|
}
|
|
6488
6635
|
|
|
6489
6636
|
// src/commands/init.ts
|
|
6637
|
+
var execAsync6 = promisify7(exec6);
|
|
6490
6638
|
function openObsidianVaultChooser() {
|
|
6491
6639
|
const os2 = platform2();
|
|
6492
6640
|
const uri = "obsidian://choose-vault";
|
|
6493
6641
|
try {
|
|
6494
6642
|
if (os2 === "darwin") {
|
|
6495
|
-
|
|
6643
|
+
execSync2(`open "${uri}"`, { stdio: "pipe" });
|
|
6496
6644
|
} else if (os2 === "win32") {
|
|
6497
|
-
|
|
6645
|
+
execSync2(`start "" "${uri}"`, { stdio: "pipe" });
|
|
6498
6646
|
} else {
|
|
6499
|
-
|
|
6647
|
+
execSync2(`xdg-open "${uri}"`, { stdio: "pipe" });
|
|
6500
6648
|
}
|
|
6501
6649
|
} catch {
|
|
6502
6650
|
}
|
|
6503
6651
|
}
|
|
6504
|
-
|
|
6505
|
-
if (
|
|
6506
|
-
console.
|
|
6507
|
-
|
|
6508
|
-
process.exit(1);
|
|
6509
|
-
}
|
|
6510
|
-
const presetName = options.preset || "blank";
|
|
6511
|
-
const preset = await getPreset(presetName);
|
|
6512
|
-
if (!preset) {
|
|
6513
|
-
const available = (await listPresets()).map((p) => p.name).join(", ");
|
|
6514
|
-
console.error(pc5.red(`Error: Unknown preset "${presetName}"`));
|
|
6515
|
-
console.log(`Available presets: ${available}`);
|
|
6516
|
-
process.exit(1);
|
|
6652
|
+
function reportSyncResult(result) {
|
|
6653
|
+
if (result.obsidian.cloned) {
|
|
6654
|
+
console.log();
|
|
6655
|
+
success("Cloned .obsidian/");
|
|
6517
6656
|
}
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
if (options.preset) {
|
|
6521
|
-
console.log(`
|
|
6522
|
-
Using preset: ${pc5.bold(preset.name)}`);
|
|
6657
|
+
if (!result.obsidian.cloned && result.shards.installed.length === 0 && result.mods.installed.length === 0 && result.errors.length === 0) {
|
|
6658
|
+
console.log(pc6.dim(" Already in sync"));
|
|
6523
6659
|
}
|
|
6524
|
-
|
|
6525
|
-
Creating flint: ${pc5.bold(name)}`);
|
|
6526
|
-
try {
|
|
6527
|
-
const entry = await createFlint({
|
|
6528
|
-
name,
|
|
6529
|
-
parentDir: options.path,
|
|
6530
|
-
shards,
|
|
6531
|
-
mods
|
|
6532
|
-
});
|
|
6533
|
-
success(`Created (Flint) ${name}/`);
|
|
6534
|
-
for (const dir of STANDARD_DIRECTORIES) {
|
|
6535
|
-
success(`Created ${dir}/`);
|
|
6536
|
-
}
|
|
6537
|
-
success("Created .flint/");
|
|
6538
|
-
success("Created flint.toml");
|
|
6539
|
-
success("Created flint.lock");
|
|
6540
|
-
success("Registered in ~/.flint/");
|
|
6541
|
-
if (preset && preset.templates.length > 0) {
|
|
6542
|
-
await applyPresetTemplates(entry.path, preset, name);
|
|
6543
|
-
success(`Applied ${preset.templates.length} template(s) from preset`);
|
|
6544
|
-
}
|
|
6545
|
-
console.log(`
|
|
6546
|
-
Flint created at: ${pc5.cyan(abbreviatePath(entry.path))}`);
|
|
6547
|
-
console.log(pc5.bold("\nSyncing configured features...\n"));
|
|
6548
|
-
const result = await syncFlint(entry.path);
|
|
6549
|
-
if (result.obsidian.cloned) {
|
|
6550
|
-
success("Cloned .obsidian/");
|
|
6551
|
-
}
|
|
6552
|
-
if (result.shards.installed.length > 0) {
|
|
6553
|
-
console.log(pc5.green("\nShards installed:"));
|
|
6554
|
-
for (const s of result.shards.installed) {
|
|
6555
|
-
console.log(` ${pc5.green("+")} ${s}`);
|
|
6556
|
-
}
|
|
6557
|
-
}
|
|
6558
|
-
if (result.mods.installed.length > 0) {
|
|
6559
|
-
console.log(pc5.green("\nMods installed:"));
|
|
6560
|
-
for (const s of result.mods.installed) {
|
|
6561
|
-
console.log(` ${pc5.green("+")} ${s}`);
|
|
6562
|
-
}
|
|
6563
|
-
const cmdResults = await runModSyncCommands(entry.path);
|
|
6564
|
-
const failedCmds = cmdResults.filter((r) => !r.success);
|
|
6565
|
-
if (failedCmds.length > 0) {
|
|
6566
|
-
console.log(pc5.yellow("\nMod command warnings:"));
|
|
6567
|
-
for (const c of failedCmds) {
|
|
6568
|
-
console.log(` ${pc5.yellow("!")} ${c.command}: ${c.error}`);
|
|
6569
|
-
}
|
|
6570
|
-
}
|
|
6571
|
-
}
|
|
6572
|
-
if (!result.obsidian.cloned && result.shards.installed.length === 0 && result.mods.installed.length === 0 && result.errors.length === 0) {
|
|
6573
|
-
console.log(pc5.dim("Flint is already in sync."));
|
|
6574
|
-
}
|
|
6575
|
-
if (result.errors.length > 0) {
|
|
6576
|
-
console.log(pc5.yellow("\nWarnings:"));
|
|
6577
|
-
for (const e of result.errors) {
|
|
6578
|
-
console.log(` ${pc5.yellow("!")} ${e.name}: ${e.error}`);
|
|
6579
|
-
}
|
|
6580
|
-
}
|
|
6581
|
-
if (result.obsidian.cloned) {
|
|
6582
|
-
console.log(pc5.dim("Opening Obsidian vault chooser..."));
|
|
6583
|
-
openObsidianVaultChooser();
|
|
6584
|
-
}
|
|
6660
|
+
if (result.errors.length > 0) {
|
|
6585
6661
|
console.log();
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
process.exit(1);
|
|
6662
|
+
for (const e of result.errors) {
|
|
6663
|
+
console.log(` ${pc6.yellow("!")} ${e.name}: ${e.error}`);
|
|
6664
|
+
}
|
|
6590
6665
|
}
|
|
6591
|
-
}
|
|
6592
|
-
|
|
6593
|
-
// src/commands/clone.ts
|
|
6594
|
-
import { Command as Command4 } from "commander";
|
|
6595
|
-
import pc6 from "picocolors";
|
|
6596
|
-
import { resolve as resolve8, join as join19 } from "path";
|
|
6597
|
-
import { existsSync as existsSync2 } from "fs";
|
|
6598
|
-
import { mkdtemp as mkdtemp3, rm as rm8, rename as rename4 } from "fs/promises";
|
|
6599
|
-
import { tmpdir as tmpdir3 } from "os";
|
|
6600
|
-
import { exec as exec3 } from "child_process";
|
|
6601
|
-
import { promisify as promisify7 } from "util";
|
|
6602
|
-
var execAsync3 = promisify7(exec3);
|
|
6603
|
-
var cloneCommand = new Command4("clone").description("Clone a flint from a git repository").argument("<url>", "Git repository URL").option("-p, --path <dir>", "Parent directory (default: current directory)").action(async (url, options) => {
|
|
6666
|
+
}
|
|
6667
|
+
async function handleFromGit(url, options) {
|
|
6604
6668
|
const parentDir = resolve8(options.path || process.cwd());
|
|
6605
6669
|
let tempDir = null;
|
|
6606
6670
|
try {
|
|
@@ -6609,7 +6673,7 @@ Cloning ${pc6.cyan(url)}...
|
|
|
6609
6673
|
`);
|
|
6610
6674
|
tempDir = await mkdtemp3(join19(tmpdir3(), "flint-clone-"));
|
|
6611
6675
|
try {
|
|
6612
|
-
await
|
|
6676
|
+
await execAsync6(`git clone "${url}" "${tempDir}"`, { timeout: 12e4 });
|
|
6613
6677
|
} catch (err) {
|
|
6614
6678
|
const message = err instanceof Error ? err.message : String(err);
|
|
6615
6679
|
throw new Error(`Git clone failed: ${message}`);
|
|
@@ -6625,6 +6689,13 @@ Cloning ${pc6.cyan(url)}...
|
|
|
6625
6689
|
}
|
|
6626
6690
|
const name = toml.flint.name;
|
|
6627
6691
|
success(`Found flint: ${pc6.bold(name)}`);
|
|
6692
|
+
const existing = await isFlintNameTaken(name);
|
|
6693
|
+
if (existing) {
|
|
6694
|
+
throw new Error(
|
|
6695
|
+
`A flint named "${name}" already exists at: ${existing.path}
|
|
6696
|
+
Each flint must have a unique name for commands like 'flint open' and 'flint import' to work.`
|
|
6697
|
+
);
|
|
6698
|
+
}
|
|
6628
6699
|
const prefix = getTypePrefix();
|
|
6629
6700
|
const folderName = `${prefix} ${name}`;
|
|
6630
6701
|
const finalPath = join19(parentDir, folderName);
|
|
@@ -6639,22 +6710,150 @@ Cloning ${pc6.cyan(url)}...
|
|
|
6639
6710
|
console.log(`
|
|
6640
6711
|
Flint cloned to: ${pc6.cyan(abbreviatePath(finalPath))}`);
|
|
6641
6712
|
console.log(pc6.bold("\nSyncing...\n"));
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6713
|
+
let shardProgress;
|
|
6714
|
+
let modProgress;
|
|
6715
|
+
const progress = {
|
|
6716
|
+
onShardPhase(total) {
|
|
6717
|
+
if (total > 0) shardProgress = createProgressDisplay("Installing shards", total);
|
|
6718
|
+
},
|
|
6719
|
+
onShardStart(name2) {
|
|
6720
|
+
shardProgress?.onStart(name2);
|
|
6721
|
+
},
|
|
6722
|
+
onShardDone(name2, ok) {
|
|
6723
|
+
ok ? shardProgress?.onComplete(name2) : shardProgress?.onError(name2);
|
|
6724
|
+
},
|
|
6725
|
+
onModPhase(total) {
|
|
6726
|
+
shardProgress?.finish();
|
|
6727
|
+
if (total > 0) modProgress = createProgressDisplay("Installing mods", total);
|
|
6728
|
+
},
|
|
6729
|
+
onModStart(name2) {
|
|
6730
|
+
modProgress?.onStart(name2);
|
|
6731
|
+
},
|
|
6732
|
+
onModDone(name2, ok) {
|
|
6733
|
+
ok ? modProgress?.onComplete(name2) : modProgress?.onError(name2);
|
|
6734
|
+
}
|
|
6735
|
+
};
|
|
6736
|
+
const result = await syncFlint(finalPath, progress);
|
|
6737
|
+
shardProgress?.finish();
|
|
6738
|
+
modProgress?.finish();
|
|
6739
|
+
reportSyncResult(result);
|
|
6740
|
+
console.log(pc6.bold("\nHealing shards...\n"));
|
|
6741
|
+
const healResults = await healAllShards(finalPath);
|
|
6742
|
+
let totalHealed = 0;
|
|
6743
|
+
for (const [folder, results] of Object.entries(healResults)) {
|
|
6744
|
+
const actions = results.filter((r) => r.action);
|
|
6745
|
+
if (actions.length > 0) {
|
|
6746
|
+
totalHealed += actions.length;
|
|
6747
|
+
for (const r of actions) {
|
|
6748
|
+
console.log(` ${pc6.green("+")} ${folder}: ${r.actionLabel}`);
|
|
6749
|
+
}
|
|
6750
|
+
}
|
|
6751
|
+
}
|
|
6752
|
+
if (totalHealed > 0) {
|
|
6753
|
+
success(`Healed ${totalHealed} issue(s) across shards`);
|
|
6754
|
+
} else {
|
|
6755
|
+
console.log(pc6.dim("All shards healthy."));
|
|
6645
6756
|
}
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6757
|
+
console.log(pc6.bold(`
|
|
6758
|
+
Ready to use!
|
|
6759
|
+
`));
|
|
6760
|
+
console.log(` cd ${abbreviatePath(finalPath)}`);
|
|
6761
|
+
console.log(` flint open ${pc6.dim("Open in Obsidian")}`);
|
|
6762
|
+
console.log(` flint sync ${pc6.dim("Update anytime")}`);
|
|
6763
|
+
console.log();
|
|
6764
|
+
} catch (err) {
|
|
6765
|
+
if (tempDir) {
|
|
6766
|
+
try {
|
|
6767
|
+
await rm8(tempDir, { recursive: true, force: true });
|
|
6768
|
+
} catch {
|
|
6650
6769
|
}
|
|
6651
6770
|
}
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6771
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
6772
|
+
error(message);
|
|
6773
|
+
process.exit(1);
|
|
6774
|
+
}
|
|
6775
|
+
}
|
|
6776
|
+
var initCommand = new Command3("init").description("Create a new Flint workspace").argument("[name]", "Name of the flint").option("-p, --path <dir>", "Parent directory (default: current directory)").option("--preset <name>", 'Use a preset (e.g., "default")').option("--from-git <url>", "Clone a flint from a git repository").action(async (name, options) => {
|
|
6777
|
+
if (options.fromGit) {
|
|
6778
|
+
await handleFromGit(options.fromGit, options);
|
|
6779
|
+
return;
|
|
6780
|
+
}
|
|
6781
|
+
if (!name) {
|
|
6782
|
+
console.error(pc6.red("Error: Flint name is required"));
|
|
6783
|
+
console.log("\nUsage: flint init <name> [options]");
|
|
6784
|
+
console.log(" flint init --from-git <url> [options]");
|
|
6785
|
+
process.exit(1);
|
|
6786
|
+
}
|
|
6787
|
+
const presetName = options.preset || "blank";
|
|
6788
|
+
const preset = await getPreset(presetName);
|
|
6789
|
+
if (!preset) {
|
|
6790
|
+
const available = (await listPresets()).map((p) => p.name).join(", ");
|
|
6791
|
+
console.error(pc6.red(`Error: Unknown preset "${presetName}"`));
|
|
6792
|
+
console.log(`Available presets: ${available}`);
|
|
6793
|
+
process.exit(1);
|
|
6794
|
+
}
|
|
6795
|
+
const shards = preset.shards;
|
|
6796
|
+
const mods = preset.mods;
|
|
6797
|
+
if (options.preset) {
|
|
6798
|
+
console.log(`
|
|
6799
|
+
Using preset: ${pc6.bold(preset.name)}`);
|
|
6800
|
+
}
|
|
6801
|
+
console.log(`
|
|
6802
|
+
Creating flint: ${pc6.bold(name)}
|
|
6803
|
+
`);
|
|
6804
|
+
try {
|
|
6805
|
+
const entry = await createFlint({
|
|
6806
|
+
name,
|
|
6807
|
+
parentDir: options.path,
|
|
6808
|
+
shards,
|
|
6809
|
+
mods
|
|
6810
|
+
});
|
|
6811
|
+
const dirs = STANDARD_DIRECTORIES.join(", ");
|
|
6812
|
+
success(`Created (Flint) ${name}/`);
|
|
6813
|
+
console.log(pc6.dim(` ${dirs}, .flint/, flint.toml, flint.lock
|
|
6814
|
+
`));
|
|
6815
|
+
success("Registered in ~/.nuucognition/flint/");
|
|
6816
|
+
if (preset && preset.templates.length > 0) {
|
|
6817
|
+
await applyPresetTemplates(entry.path, preset, name);
|
|
6818
|
+
success(`Applied ${preset.templates.length} template(s) from preset`);
|
|
6819
|
+
}
|
|
6820
|
+
console.log(`
|
|
6821
|
+
${pc6.cyan(abbreviatePath(entry.path))}
|
|
6822
|
+
`);
|
|
6823
|
+
if (shards.length > 0 || mods.length > 0) {
|
|
6824
|
+
console.log(pc6.bold("Syncing...\n"));
|
|
6825
|
+
}
|
|
6826
|
+
let initShardProgress;
|
|
6827
|
+
let initModProgress;
|
|
6828
|
+
const initProgress = {
|
|
6829
|
+
onShardPhase(total) {
|
|
6830
|
+
if (total > 0) initShardProgress = createProgressDisplay("Installing shards", total);
|
|
6831
|
+
},
|
|
6832
|
+
onShardStart(name2) {
|
|
6833
|
+
initShardProgress?.onStart(name2);
|
|
6834
|
+
},
|
|
6835
|
+
onShardDone(name2, ok) {
|
|
6836
|
+
ok ? initShardProgress?.onComplete(name2) : initShardProgress?.onError(name2);
|
|
6837
|
+
},
|
|
6838
|
+
onModPhase(total) {
|
|
6839
|
+
initShardProgress?.finish();
|
|
6840
|
+
if (total > 0) {
|
|
6841
|
+
console.log();
|
|
6842
|
+
initModProgress = createProgressDisplay("Installing mods", total);
|
|
6843
|
+
}
|
|
6844
|
+
},
|
|
6845
|
+
onModStart(name2) {
|
|
6846
|
+
initModProgress?.onStart(name2);
|
|
6847
|
+
},
|
|
6848
|
+
onModDone(name2, ok) {
|
|
6849
|
+
ok ? initModProgress?.onComplete(name2) : initModProgress?.onError(name2);
|
|
6656
6850
|
}
|
|
6657
|
-
|
|
6851
|
+
};
|
|
6852
|
+
const result = await syncFlint(entry.path, initProgress);
|
|
6853
|
+
initShardProgress?.finish();
|
|
6854
|
+
initModProgress?.finish();
|
|
6855
|
+
if (result.mods.installed.length > 0) {
|
|
6856
|
+
const cmdResults = await runModSyncCommands(entry.path);
|
|
6658
6857
|
const failedCmds = cmdResults.filter((r) => !r.success);
|
|
6659
6858
|
if (failedCmds.length > 0) {
|
|
6660
6859
|
console.log(pc6.yellow("\nMod command warnings:"));
|
|
@@ -6663,23 +6862,13 @@ Flint cloned to: ${pc6.cyan(abbreviatePath(finalPath))}`);
|
|
|
6663
6862
|
}
|
|
6664
6863
|
}
|
|
6665
6864
|
}
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
console.log(pc6.yellow("\nWarnings:"));
|
|
6671
|
-
for (const e of result.errors) {
|
|
6672
|
-
console.log(` ${pc6.yellow("!")} ${e.name}: ${e.error}`);
|
|
6673
|
-
}
|
|
6865
|
+
reportSyncResult(result);
|
|
6866
|
+
if (result.obsidian.cloned) {
|
|
6867
|
+
console.log(pc6.dim("\nOpening Obsidian vault chooser..."));
|
|
6868
|
+
openObsidianVaultChooser();
|
|
6674
6869
|
}
|
|
6675
6870
|
console.log();
|
|
6676
6871
|
} catch (err) {
|
|
6677
|
-
if (tempDir) {
|
|
6678
|
-
try {
|
|
6679
|
-
await rm8(tempDir, { recursive: true, force: true });
|
|
6680
|
-
} catch {
|
|
6681
|
-
}
|
|
6682
|
-
}
|
|
6683
6872
|
const message = err instanceof Error ? err.message : String(err);
|
|
6684
6873
|
error(message);
|
|
6685
6874
|
process.exit(1);
|
|
@@ -6687,7 +6876,7 @@ Flint cloned to: ${pc6.cyan(abbreviatePath(finalPath))}`);
|
|
|
6687
6876
|
});
|
|
6688
6877
|
|
|
6689
6878
|
// src/commands/list.ts
|
|
6690
|
-
import { Command as
|
|
6879
|
+
import { Command as Command4 } from "commander";
|
|
6691
6880
|
import pc7 from "picocolors";
|
|
6692
6881
|
function stripAnsi(str) {
|
|
6693
6882
|
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
@@ -6745,7 +6934,7 @@ function measureNameCol(flints) {
|
|
|
6745
6934
|
}
|
|
6746
6935
|
return max + 3;
|
|
6747
6936
|
}
|
|
6748
|
-
var listCmd = new
|
|
6937
|
+
var listCmd = new Command4("list").alias("ls").description("List all registered flints").option("--json", "Output as JSON").option("--full-path", "Show full paths (not abbreviated)").option("-s, --status", "Show valid/broken status for each entry").option("-g, --group", "Group flints by tag").option("-t, --tag <tag>", "Filter flints by tag").option("--search <query>", "Search flints by name or description").option("--tree", "Show parent/subflint hierarchy").option("--no-sub", "Hide subflints from output");
|
|
6749
6938
|
var listCommand = listCmd.action(async (options) => {
|
|
6750
6939
|
try {
|
|
6751
6940
|
let flints = await getFlintRegistry();
|
|
@@ -6876,10 +7065,11 @@ var listCommand = listCmd.action(async (options) => {
|
|
|
6876
7065
|
});
|
|
6877
7066
|
|
|
6878
7067
|
// src/commands/shard.ts
|
|
6879
|
-
import { Command as
|
|
7068
|
+
import { Command as Command5 } from "commander";
|
|
6880
7069
|
import { spawn as spawn2 } from "child_process";
|
|
6881
7070
|
import { join as join20 } from "path";
|
|
6882
7071
|
import { existsSync as existsSync3 } from "fs";
|
|
7072
|
+
import { readFile as readFile9 } from "fs/promises";
|
|
6883
7073
|
import pc8 from "picocolors";
|
|
6884
7074
|
var SUBCOMMANDS = [
|
|
6885
7075
|
"install",
|
|
@@ -6889,7 +7079,13 @@ var SUBCOMMANDS = [
|
|
|
6889
7079
|
"pull",
|
|
6890
7080
|
"create",
|
|
6891
7081
|
"dev",
|
|
7082
|
+
"edit",
|
|
7083
|
+
"freeze",
|
|
7084
|
+
"git",
|
|
6892
7085
|
"register",
|
|
7086
|
+
"publish",
|
|
7087
|
+
"unpublish",
|
|
7088
|
+
"published",
|
|
6893
7089
|
"check",
|
|
6894
7090
|
"heal",
|
|
6895
7091
|
"info",
|
|
@@ -6926,7 +7122,7 @@ function resolveInstalledShard(installed, identifier) {
|
|
|
6926
7122
|
return false;
|
|
6927
7123
|
});
|
|
6928
7124
|
}
|
|
6929
|
-
var shardCommand = new
|
|
7125
|
+
var shardCommand = new Command5("shard").description("Manage shards \u2014 install, create, and maintain shard packages").argument("[name]", "Shard name for overview or script execution").argument("[script]", "Script name to run").argument("[args...]", "Script arguments").option("-p, --path <dir>", "Path to flint").allowUnknownOption().action(async (shorthand, script, args, options) => {
|
|
6930
7126
|
if (!shorthand) {
|
|
6931
7127
|
shardCommand.help();
|
|
6932
7128
|
return;
|
|
@@ -6958,9 +7154,6 @@ Shard not found: "${shorthand}"`));
|
|
|
6958
7154
|
if (counts.length > 0) {
|
|
6959
7155
|
console.log(` ${pc8.dim("Contents:")} ${counts.join(", ")}`);
|
|
6960
7156
|
}
|
|
6961
|
-
if (detail2.depends.length > 0) {
|
|
6962
|
-
console.log(` ${pc8.dim("Depends:")} ${detail2.depends.join(", ")}`);
|
|
6963
|
-
}
|
|
6964
7157
|
let scripts = [];
|
|
6965
7158
|
try {
|
|
6966
7159
|
scripts = await listShardScripts(flintPath, shorthand);
|
|
@@ -7022,7 +7215,7 @@ Shard not installed: "${shorthand}"`));
|
|
|
7022
7215
|
handleError(err);
|
|
7023
7216
|
}
|
|
7024
7217
|
}).addCommand(
|
|
7025
|
-
new
|
|
7218
|
+
new Command5("install").description("Install a shard from a source (owner/repo or path:)").argument("<source>", "Source identifier (e.g. owner/repo, path:./local)").option("-f, --force", "Overwrite existing shard files").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
7026
7219
|
try {
|
|
7027
7220
|
const flintPath = await resolveFlint(options.path);
|
|
7028
7221
|
if (!isSourceIdentifier(source)) {
|
|
@@ -7058,7 +7251,7 @@ Installed ${pc8.bold(result.name)}`));
|
|
|
7058
7251
|
}
|
|
7059
7252
|
})
|
|
7060
7253
|
).addCommand(
|
|
7061
|
-
new
|
|
7254
|
+
new Command5("uninstall").description("Uninstall a shard and clean up its files").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7062
7255
|
try {
|
|
7063
7256
|
const flintPath = await resolveFlint(options.path);
|
|
7064
7257
|
const result = await uninstallShard(flintPath, shorthand);
|
|
@@ -7071,7 +7264,7 @@ Uninstalled ${pc8.bold(result.name)}`));
|
|
|
7071
7264
|
}
|
|
7072
7265
|
})
|
|
7073
7266
|
).addCommand(
|
|
7074
|
-
new
|
|
7267
|
+
new Command5("list").alias("ls").description("List installed shards").option("-s, --sources", "Show source declarations from flint.toml").option("-p, --path <dir>", "Path to flint").action(async (options) => {
|
|
7075
7268
|
try {
|
|
7076
7269
|
const flintPath = await resolveFlint(options.path);
|
|
7077
7270
|
if (options.sources) {
|
|
@@ -7105,7 +7298,7 @@ Uninstalled ${pc8.bold(result.name)}`));
|
|
|
7105
7298
|
modeMap.set(k, resolveShardMode(d) || "normal");
|
|
7106
7299
|
}
|
|
7107
7300
|
console.log(pc8.bold("\nInstalled shards:\n"));
|
|
7108
|
-
const { execSync:
|
|
7301
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
7109
7302
|
const gitRemotes = /* @__PURE__ */ new Map();
|
|
7110
7303
|
for (const shard of installed) {
|
|
7111
7304
|
if (modeMap.get(shard.name) !== "dev") continue;
|
|
@@ -7113,7 +7306,7 @@ Uninstalled ${pc8.bold(result.name)}`));
|
|
|
7113
7306
|
const gitDir = join20(shardPath, ".git");
|
|
7114
7307
|
if (!existsSync3(gitDir)) continue;
|
|
7115
7308
|
try {
|
|
7116
|
-
const url =
|
|
7309
|
+
const url = execSync4("git remote get-url origin", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
7117
7310
|
const match = url.match(/(?:github\.com[/:])([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
7118
7311
|
if (match) {
|
|
7119
7312
|
gitRemotes.set(shard.name, match[1]);
|
|
@@ -7145,7 +7338,7 @@ Uninstalled ${pc8.bold(result.name)}`));
|
|
|
7145
7338
|
}
|
|
7146
7339
|
})
|
|
7147
7340
|
).addCommand(
|
|
7148
|
-
new
|
|
7341
|
+
new Command5("update").description("Update remote shards (skips dev and custom, checks remote version)").option("-p, --path <dir>", "Path to flint").option("--reinstall", "Force re-download and reinstall all remote shards regardless of version").action(async (options) => {
|
|
7149
7342
|
try {
|
|
7150
7343
|
const flintPath = await resolveFlint(options.path);
|
|
7151
7344
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
@@ -7165,11 +7358,15 @@ Uninstalled ${pc8.bold(result.name)}`));
|
|
|
7165
7358
|
console.log();
|
|
7166
7359
|
return;
|
|
7167
7360
|
}
|
|
7168
|
-
const mode = options.reinstall ? "Reinstalling" : "
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7361
|
+
const mode = options.reinstall ? "Reinstalling" : "Updating";
|
|
7362
|
+
const progress = createProgressDisplay(`${mode} shards`, updatable.length);
|
|
7363
|
+
const results = await updateShards(flintPath, {
|
|
7364
|
+
reinstall: options.reinstall,
|
|
7365
|
+
onStart: (name) => progress.onStart(name),
|
|
7366
|
+
onComplete: (name) => progress.onComplete(name),
|
|
7367
|
+
onError: (name) => progress.onError(name)
|
|
7368
|
+
});
|
|
7369
|
+
progress.finish();
|
|
7173
7370
|
const updated = results.filter((r) => r.status === "updated");
|
|
7174
7371
|
const skippedResults = results.filter((r) => r.status === "skipped");
|
|
7175
7372
|
const failed = results.filter((r) => r.status === "failed");
|
|
@@ -7197,7 +7394,7 @@ ${mode} ${updatable.length} shard(s)...
|
|
|
7197
7394
|
}
|
|
7198
7395
|
})
|
|
7199
7396
|
).addCommand(
|
|
7200
|
-
new
|
|
7397
|
+
new Command5("pull").description("Sync shard repos and install entries from manifest").argument("[name]", "Shard to pull (omit for all)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7201
7398
|
try {
|
|
7202
7399
|
const flintPath = await resolveFlint(options.path);
|
|
7203
7400
|
if (shorthand) {
|
|
@@ -7234,7 +7431,7 @@ Pulling all shard repos...
|
|
|
7234
7431
|
}
|
|
7235
7432
|
})
|
|
7236
7433
|
).addCommand(
|
|
7237
|
-
new
|
|
7434
|
+
new Command5("create").description("Scaffold a new local shard (dev or custom)").argument("<mode>", 'Shard mode: "dev" (publishable) or "custom" (workspace-specific)').argument("<name>", 'Shard name (e.g. "Bookmarks", "Code Review")').option("-s, --shorthand <id>", "Shard shorthand identifier (default: derived from name)").option("-d, --description <text>", "Shard description").option("--setup", "Include a setup-<shorthand>.md file for one-time initialization").option("--state", "Create a (Shard) state file in Mesh/Shards/").option("-p, --path <dir>", "Path to flint").action(async (mode, name, options) => {
|
|
7238
7435
|
try {
|
|
7239
7436
|
if (mode !== "dev" && mode !== "custom") {
|
|
7240
7437
|
console.error(pc8.red(`
|
|
@@ -7274,7 +7471,7 @@ Created ${pc8.bold(result.name)} ${modeLabel}`));
|
|
|
7274
7471
|
}
|
|
7275
7472
|
})
|
|
7276
7473
|
).addCommand(
|
|
7277
|
-
new
|
|
7474
|
+
new Command5("dev").description("Clone an existing shard into a (Dev) folder for local editing").argument("<source>", "Source identifier (e.g. owner/repo, path:./local)").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
7278
7475
|
try {
|
|
7279
7476
|
const flintPath = await resolveFlint(options.path);
|
|
7280
7477
|
if (!isSourceIdentifier(source)) {
|
|
@@ -7303,7 +7500,87 @@ Cloned ${pc8.bold(result.name)} for development`));
|
|
|
7303
7500
|
}
|
|
7304
7501
|
})
|
|
7305
7502
|
).addCommand(
|
|
7306
|
-
new
|
|
7503
|
+
new Command5("edit").description("Transition a normal shard to dev mode (adds .git, renames to (Dev) prefix)").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
7504
|
+
try {
|
|
7505
|
+
const flintPath = await resolveFlint(options.path);
|
|
7506
|
+
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7507
|
+
const match = resolveInstalledShard(installed, name);
|
|
7508
|
+
if (!match) {
|
|
7509
|
+
console.error(pc8.red(`
|
|
7510
|
+
Shard "${name}" not found.`));
|
|
7511
|
+
console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
|
|
7512
|
+
console.log();
|
|
7513
|
+
return;
|
|
7514
|
+
}
|
|
7515
|
+
const declarations = await getShardDeclarations(flintPath);
|
|
7516
|
+
const decl = declarations[match.name];
|
|
7517
|
+
const source = decl?.source || "";
|
|
7518
|
+
console.log(pc8.dim(`
|
|
7519
|
+
Transitioning ${match.folderName} to dev mode...`));
|
|
7520
|
+
const result = await editShard(flintPath, match.folderName, source);
|
|
7521
|
+
await updateGitignore(flintPath);
|
|
7522
|
+
console.log(pc8.green(`
|
|
7523
|
+
${pc8.bold(result.name)} is now in dev mode`));
|
|
7524
|
+
console.log(pc8.dim(` Old: Shards/${result.oldFolder}`));
|
|
7525
|
+
console.log(pc8.dim(` New: ${abbreviatePath(result.path)}`));
|
|
7526
|
+
console.log(pc8.dim(` Git: initialized`));
|
|
7527
|
+
console.log();
|
|
7528
|
+
} catch (err) {
|
|
7529
|
+
handleError(err);
|
|
7530
|
+
}
|
|
7531
|
+
})
|
|
7532
|
+
).addCommand(
|
|
7533
|
+
new Command5("freeze").description("Transition a dev shard back to normal mode (removes .git, commits to parent)").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
7534
|
+
try {
|
|
7535
|
+
const flintPath = await resolveFlint(options.path);
|
|
7536
|
+
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7537
|
+
const match = resolveInstalledShard(installed, name);
|
|
7538
|
+
if (!match) {
|
|
7539
|
+
console.error(pc8.red(`
|
|
7540
|
+
Shard "${name}" not found.`));
|
|
7541
|
+
console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
|
|
7542
|
+
console.log();
|
|
7543
|
+
return;
|
|
7544
|
+
}
|
|
7545
|
+
console.log(pc8.dim(`
|
|
7546
|
+
Freezing ${match.folderName}...`));
|
|
7547
|
+
const result = await freezeShard(flintPath, match.folderName);
|
|
7548
|
+
await updateGitignore(flintPath);
|
|
7549
|
+
console.log(pc8.green(`
|
|
7550
|
+
${pc8.bold(result.name)} is now a normal shard`));
|
|
7551
|
+
console.log(pc8.dim(` Old: Shards/${result.oldFolder}`));
|
|
7552
|
+
console.log(pc8.dim(` New: ${abbreviatePath(result.path)}`));
|
|
7553
|
+
console.log(pc8.dim(` Git: removed (now committed to parent flint)`));
|
|
7554
|
+
console.log();
|
|
7555
|
+
} catch (err) {
|
|
7556
|
+
handleError(err);
|
|
7557
|
+
}
|
|
7558
|
+
})
|
|
7559
|
+
).addCommand(
|
|
7560
|
+
new Command5("git").description("Add a git remote to a dev shard and update its source declaration").argument("<name>", "Shard name (e.g. reports, living-documents)").argument("<url>", "Git remote URL (e.g., https://github.com/org/repo.git)").option("-p, --path <dir>", "Path to flint").action(async (name, url, options) => {
|
|
7561
|
+
try {
|
|
7562
|
+
const flintPath = await resolveFlint(options.path);
|
|
7563
|
+
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7564
|
+
const match = resolveInstalledShard(installed, name);
|
|
7565
|
+
if (!match) {
|
|
7566
|
+
console.error(pc8.red(`
|
|
7567
|
+
Shard "${name}" not found.`));
|
|
7568
|
+
console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
|
|
7569
|
+
console.log();
|
|
7570
|
+
return;
|
|
7571
|
+
}
|
|
7572
|
+
const result = await addShardGitRemote(flintPath, match.folderName, url);
|
|
7573
|
+
console.log(pc8.green(`
|
|
7574
|
+
Remote added to ${pc8.bold(match.folderName)}`));
|
|
7575
|
+
console.log(pc8.dim(` Remote: origin \u2192 ${url}`));
|
|
7576
|
+
console.log(pc8.dim(` Source: ${result.ownerRepo}`));
|
|
7577
|
+
console.log();
|
|
7578
|
+
} catch (err) {
|
|
7579
|
+
handleError(err);
|
|
7580
|
+
}
|
|
7581
|
+
})
|
|
7582
|
+
).addCommand(
|
|
7583
|
+
new Command5("register").description("Register an existing Shards/ folder as a dev shard in flint.toml").argument("<folder>", 'Folder name inside Shards/ (e.g. "(Dev) Bookmarks")').option("-p, --path <dir>", "Path to flint").action(async (folder, options) => {
|
|
7307
7584
|
try {
|
|
7308
7585
|
const flintPath = await resolveFlint(options.path);
|
|
7309
7586
|
const result = await registerExistingShard(flintPath, folder);
|
|
@@ -7319,7 +7596,7 @@ Registered ${pc8.bold(result.name)}`));
|
|
|
7319
7596
|
}
|
|
7320
7597
|
})
|
|
7321
7598
|
).addCommand(
|
|
7322
|
-
new
|
|
7599
|
+
new Command5("info").description("Show detailed information about a shard").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (identifier, options) => {
|
|
7323
7600
|
try {
|
|
7324
7601
|
const flintPath = await resolveFlint(options.path);
|
|
7325
7602
|
const detail2 = await getShardInfo(flintPath, identifier);
|
|
@@ -7344,9 +7621,6 @@ Shard not found: "${identifier}"`));
|
|
|
7344
7621
|
console.log(` Mode ${pc8.magenta("custom")}`);
|
|
7345
7622
|
}
|
|
7346
7623
|
console.log(` Folder Shards/${detail2.folderName}`);
|
|
7347
|
-
if (detail2.depends.length > 0) {
|
|
7348
|
-
console.log(` Depends ${detail2.depends.join(", ")}`);
|
|
7349
|
-
}
|
|
7350
7624
|
const counts = [];
|
|
7351
7625
|
if (detail2.skillCount > 0) counts.push(`${detail2.skillCount} skill${detail2.skillCount !== 1 ? "s" : ""}`);
|
|
7352
7626
|
if (detail2.templateCount > 0) counts.push(`${detail2.templateCount} template${detail2.templateCount !== 1 ? "s" : ""}`);
|
|
@@ -7368,7 +7642,7 @@ Shard not found: "${identifier}"`));
|
|
|
7368
7642
|
}
|
|
7369
7643
|
})
|
|
7370
7644
|
).addCommand(
|
|
7371
|
-
new
|
|
7645
|
+
new Command5("check").description("Check shard system integrity and report issues").option("-p, --path <dir>", "Path to flint").action(async (options) => {
|
|
7372
7646
|
try {
|
|
7373
7647
|
const flintPath = await resolveFlint(options.path);
|
|
7374
7648
|
console.log(pc8.bold("\nShard Health Check\n"));
|
|
@@ -7401,7 +7675,7 @@ Shard not found: "${identifier}"`));
|
|
|
7401
7675
|
}
|
|
7402
7676
|
})
|
|
7403
7677
|
).addCommand(
|
|
7404
|
-
new
|
|
7678
|
+
new Command5("heal").description("Check and fix a shard \u2014 ensures folders, manifest, naming, and declarations").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-n, --dry-run", "Preview fixes without applying them").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
7405
7679
|
try {
|
|
7406
7680
|
const flintPath = await resolveFlint(options.path);
|
|
7407
7681
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
@@ -7455,7 +7729,7 @@ Healing ${match.folderName}...
|
|
|
7455
7729
|
}
|
|
7456
7730
|
})
|
|
7457
7731
|
).addCommand(
|
|
7458
|
-
new
|
|
7732
|
+
new Command5("add").description("Add a shard source to flint.toml without installing files").argument("<source>", "Source identifier (owner/repo)").option("-n, --name <name>", "Override the shard name in config").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
7459
7733
|
try {
|
|
7460
7734
|
const flintPath = await resolveFlint(options.path);
|
|
7461
7735
|
const normalizedSource = source;
|
|
@@ -7479,7 +7753,7 @@ Added ${pc8.bold(shardName)}`));
|
|
|
7479
7753
|
}
|
|
7480
7754
|
})
|
|
7481
7755
|
).addCommand(
|
|
7482
|
-
new
|
|
7756
|
+
new Command5("remove").description("Remove a shard declaration from flint.toml (does not delete files)").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7483
7757
|
try {
|
|
7484
7758
|
const flintPath = await resolveFlint(options.path);
|
|
7485
7759
|
await removeShardFromConfig(flintPath, shorthand);
|
|
@@ -7492,7 +7766,7 @@ Removed ${pc8.bold(shorthand)} from flint.toml`));
|
|
|
7492
7766
|
}
|
|
7493
7767
|
})
|
|
7494
7768
|
).addCommand(
|
|
7495
|
-
new
|
|
7769
|
+
new Command5("reinstall").description("Re-run install entries for a shard (useful for dev testing)").argument("<name>", "Shard name (e.g. reports, living-documents)").option("--force", "Override once entries (re-install all files)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7496
7770
|
try {
|
|
7497
7771
|
const flintPath = await resolveFlint(options.path);
|
|
7498
7772
|
console.log(pc8.bold(`
|
|
@@ -7524,9 +7798,9 @@ Reinstalling ${shorthand}...
|
|
|
7524
7798
|
}
|
|
7525
7799
|
})
|
|
7526
7800
|
).addCommand(
|
|
7527
|
-
new
|
|
7801
|
+
new Command5("gitinit").description("Initialize git repo for a dev shard and push to a remote").argument("<name>", "Shard name (e.g. reports, living-documents)").argument("<url>", "Git remote URL (e.g., https://github.com/org/repo.git)").option("-p, --path <dir>", "Path to flint").action(async (name, url, options) => {
|
|
7528
7802
|
try {
|
|
7529
|
-
const { execSync:
|
|
7803
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
7530
7804
|
const flintPath = await resolveFlint(options.path);
|
|
7531
7805
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7532
7806
|
const match = resolveInstalledShard(installed, name);
|
|
@@ -7554,21 +7828,29 @@ Shard "${name}" not found.`));
|
|
|
7554
7828
|
}
|
|
7555
7829
|
const shardPath = join20(flintPath, "Shards", match.folderName);
|
|
7556
7830
|
const gitDir = join20(shardPath, ".git");
|
|
7557
|
-
|
|
7558
|
-
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7831
|
+
const hasGit = existsSync3(gitDir);
|
|
7832
|
+
if (hasGit) {
|
|
7833
|
+
try {
|
|
7834
|
+
const existing = execSync4("git remote get-url origin", { cwd: shardPath, stdio: "pipe" }).toString().trim();
|
|
7835
|
+
console.error(pc8.red(`
|
|
7836
|
+
"${match.folderName}" already has a remote: ${existing}`));
|
|
7837
|
+
console.log(pc8.dim(` Use ${pc8.cyan("flint shard push")} instead.`));
|
|
7838
|
+
console.log();
|
|
7839
|
+
return;
|
|
7840
|
+
} catch {
|
|
7841
|
+
}
|
|
7562
7842
|
}
|
|
7563
7843
|
console.log(pc8.bold(`
|
|
7564
7844
|
Initializing ${match.folderName}...
|
|
7565
7845
|
`));
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7846
|
+
if (!hasGit) {
|
|
7847
|
+
execSync4("git init", { cwd: shardPath, stdio: "pipe" });
|
|
7848
|
+
}
|
|
7849
|
+
execSync4(`git remote add origin "${url}"`, { cwd: shardPath, stdio: "pipe" });
|
|
7850
|
+
execSync4("git branch -M main", { cwd: shardPath, stdio: "pipe" });
|
|
7851
|
+
execSync4("git add -A", { cwd: shardPath, stdio: "pipe" });
|
|
7852
|
+
execSync4('git commit -m "initial commit"', { cwd: shardPath, stdio: "pipe" });
|
|
7853
|
+
execSync4("git push -u origin main", { cwd: shardPath, stdio: "inherit" });
|
|
7572
7854
|
console.log(pc8.green(`
|
|
7573
7855
|
${pc8.bold(match.folderName)} pushed to ${pc8.dim(url)}`));
|
|
7574
7856
|
console.log();
|
|
@@ -7577,9 +7859,9 @@ Initializing ${match.folderName}...
|
|
|
7577
7859
|
}
|
|
7578
7860
|
})
|
|
7579
7861
|
).addCommand(
|
|
7580
|
-
new
|
|
7862
|
+
new Command5("push").description("Commit and push a dev shard to its remote").argument("<name>", "Shard name (e.g. reports, living-documents)").option("-m, --message <msg>", "Commit message").option("-b, --bump <level>", "Bump version in shard.yaml (patch, minor, major)").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
7581
7863
|
try {
|
|
7582
|
-
const { execSync:
|
|
7864
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
7583
7865
|
const flintPath = await resolveFlint(options.path);
|
|
7584
7866
|
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7585
7867
|
const match = resolveInstalledShard(installed, name);
|
|
@@ -7614,15 +7896,15 @@ Shard "${name}" not found.`));
|
|
|
7614
7896
|
console.log();
|
|
7615
7897
|
return;
|
|
7616
7898
|
}
|
|
7617
|
-
const status =
|
|
7899
|
+
const status = execSync4("git status --porcelain", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
7618
7900
|
if (!status) {
|
|
7619
7901
|
try {
|
|
7620
|
-
const unpushed =
|
|
7902
|
+
const unpushed = execSync4("git log @{u}..HEAD --oneline", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
7621
7903
|
if (unpushed) {
|
|
7622
7904
|
console.log(pc8.bold(`
|
|
7623
7905
|
Pushing ${match.folderName}...
|
|
7624
7906
|
`));
|
|
7625
|
-
|
|
7907
|
+
execSync4("git push", { cwd: shardPath, stdio: "inherit" });
|
|
7626
7908
|
console.log(pc8.green(`
|
|
7627
7909
|
Pushed unpushed commits.`));
|
|
7628
7910
|
console.log();
|
|
@@ -7644,9 +7926,9 @@ Invalid bump level "${level}". Use: patch, minor, or major.`));
|
|
|
7644
7926
|
console.log();
|
|
7645
7927
|
return;
|
|
7646
7928
|
}
|
|
7647
|
-
const { readFile:
|
|
7929
|
+
const { readFile: readFile12, writeFile: writeFile10 } = await import("fs/promises");
|
|
7648
7930
|
const yamlPath = join20(shardPath, "shard.yaml");
|
|
7649
|
-
const yamlContent = await
|
|
7931
|
+
const yamlContent = await readFile12(yamlPath, "utf-8");
|
|
7650
7932
|
const versionMatch = yamlContent.match(/^version:\s*"?(\d+)\.(\d+)\.(\d+)"?/m);
|
|
7651
7933
|
if (!versionMatch) {
|
|
7652
7934
|
console.error(pc8.red(`
|
|
@@ -7666,13 +7948,13 @@ Could not parse version from shard.yaml.`));
|
|
|
7666
7948
|
console.log(pc8.bold(`
|
|
7667
7949
|
Pushing ${match.folderName}...
|
|
7668
7950
|
`));
|
|
7669
|
-
|
|
7670
|
-
|
|
7951
|
+
execSync4("git add -A", { cwd: shardPath, stdio: "pipe" });
|
|
7952
|
+
execSync4(`git commit -m "${message.replace(/"/g, '\\"')}"`, { cwd: shardPath, stdio: "pipe" });
|
|
7671
7953
|
try {
|
|
7672
|
-
|
|
7954
|
+
execSync4("git push", { cwd: shardPath, stdio: "inherit" });
|
|
7673
7955
|
} catch {
|
|
7674
|
-
const branch =
|
|
7675
|
-
|
|
7956
|
+
const branch = execSync4("git branch --show-current", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
7957
|
+
execSync4(`git push -u origin ${branch}`, { cwd: shardPath, stdio: "inherit" });
|
|
7676
7958
|
}
|
|
7677
7959
|
console.log(pc8.green(`
|
|
7678
7960
|
${pc8.bold(match.folderName)} pushed.`));
|
|
@@ -7683,7 +7965,261 @@ Pushing ${match.folderName}...
|
|
|
7683
7965
|
}
|
|
7684
7966
|
})
|
|
7685
7967
|
).addCommand(
|
|
7686
|
-
|
|
7968
|
+
(() => {
|
|
7969
|
+
const publishRuntime = resolveRuntimeSync({ cliname: "flint" });
|
|
7970
|
+
const publishDevAvailable = publishRuntime.mode === "dev";
|
|
7971
|
+
const REGISTRY_URL_PROD = "https://amicable-dog-262.convex.site";
|
|
7972
|
+
const REGISTRY_URL_DEV = "https://grateful-sardine-809.convex.site";
|
|
7973
|
+
const ORGS_URL_PROD = "https://impressive-ptarmigan-132.convex.site";
|
|
7974
|
+
const ORGS_URL_DEV = "https://steady-lobster-998.convex.site";
|
|
7975
|
+
const cmd = new Command5("publish").description("Publish a shard to the NUU Shard Registry (requires login)").argument("<name>", "Shard name (e.g. reports, notepad)").option("--org <slug>", "Publish as an organisation").option("-p, --path <dir>", "Path to flint");
|
|
7976
|
+
if (publishDevAvailable) cmd.option("--dev", "Use dev environment");
|
|
7977
|
+
cmd.action(async (name, options) => {
|
|
7978
|
+
try {
|
|
7979
|
+
const flintPath = await resolveFlint(options.path);
|
|
7980
|
+
const installed = await getInstalledShardsWithVersions(flintPath);
|
|
7981
|
+
const match = resolveInstalledShard(installed, name);
|
|
7982
|
+
if (!match) {
|
|
7983
|
+
console.error(pc8.red(`
|
|
7984
|
+
Shard "${name}" not found.`));
|
|
7985
|
+
console.log(pc8.dim(` Run ${pc8.cyan("flint shard list")} to see installed shards.`));
|
|
7986
|
+
console.log();
|
|
7987
|
+
process.exit(1);
|
|
7988
|
+
}
|
|
7989
|
+
const shardPath = join20(flintPath, "Shards", match.folderName);
|
|
7990
|
+
const detail2 = await getShardInfo(flintPath, name);
|
|
7991
|
+
if (!detail2) {
|
|
7992
|
+
console.error(pc8.red(`
|
|
7993
|
+
Cannot read shard info for "${name}".`));
|
|
7994
|
+
process.exit(1);
|
|
7995
|
+
}
|
|
7996
|
+
const declarations = await getShardDeclarations(flintPath);
|
|
7997
|
+
const declaration = declarations[match.name];
|
|
7998
|
+
let repo = "";
|
|
7999
|
+
if (declaration?.source) {
|
|
8000
|
+
const parsed = parseShardSource(declaration.source);
|
|
8001
|
+
if (parsed.type === "github") {
|
|
8002
|
+
repo = `${parsed.owner}/${parsed.repo}`;
|
|
8003
|
+
}
|
|
8004
|
+
}
|
|
8005
|
+
if (!repo) {
|
|
8006
|
+
try {
|
|
8007
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
8008
|
+
const gitDir = join20(shardPath, ".git");
|
|
8009
|
+
if (existsSync3(gitDir)) {
|
|
8010
|
+
const remoteUrl = execSync4("git remote get-url origin", { cwd: shardPath, encoding: "utf-8" }).trim();
|
|
8011
|
+
const ghMatch = remoteUrl.match(/github\.com[/:]([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
8012
|
+
if (ghMatch) {
|
|
8013
|
+
repo = ghMatch[1];
|
|
8014
|
+
}
|
|
8015
|
+
}
|
|
8016
|
+
} catch {
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
if (!repo) {
|
|
8020
|
+
console.error(pc8.red(`
|
|
8021
|
+
Cannot determine repo for "${name}".`));
|
|
8022
|
+
console.log(pc8.dim(" Ensure the shard has a GitHub source in flint.toml or a git remote."));
|
|
8023
|
+
console.log();
|
|
8024
|
+
process.exit(1);
|
|
8025
|
+
}
|
|
8026
|
+
let readme;
|
|
8027
|
+
const readmePath = join20(shardPath, "README.md");
|
|
8028
|
+
if (existsSync3(readmePath)) {
|
|
8029
|
+
readme = await readFile9(readmePath, "utf-8");
|
|
8030
|
+
}
|
|
8031
|
+
const env = options.dev ? "dev" : publishDevAvailable ? "dev" : "prod";
|
|
8032
|
+
const creds = await getValidAuth(
|
|
8033
|
+
{
|
|
8034
|
+
accountUrl: env === "dev" ? "https://dev-account.nuucognition.com" : "https://account.nuucognition.com",
|
|
8035
|
+
authEnv: env,
|
|
8036
|
+
cliname: "flint"
|
|
8037
|
+
},
|
|
8038
|
+
env
|
|
8039
|
+
);
|
|
8040
|
+
if (!creds) {
|
|
8041
|
+
error(`Not logged in. Run \`flint login${env === "dev" ? " --dev" : ""}\` to authenticate.`);
|
|
8042
|
+
process.exit(1);
|
|
8043
|
+
}
|
|
8044
|
+
let owner;
|
|
8045
|
+
let author;
|
|
8046
|
+
const orgSlug = options.org;
|
|
8047
|
+
if (orgSlug) {
|
|
8048
|
+
owner = orgSlug;
|
|
8049
|
+
const orgsUrl = env === "dev" ? ORGS_URL_DEV : ORGS_URL_PROD;
|
|
8050
|
+
const orgResponse = await fetch(`${orgsUrl}/api/orgs/${encodeURIComponent(orgSlug)}`, {
|
|
8051
|
+
headers: {
|
|
8052
|
+
"Content-Type": "application/json",
|
|
8053
|
+
Authorization: `Bearer ${creds.sessionToken}`
|
|
8054
|
+
}
|
|
8055
|
+
});
|
|
8056
|
+
if (!orgResponse.ok) {
|
|
8057
|
+
if (orgResponse.status === 401 || orgResponse.status === 403) {
|
|
8058
|
+
error(`You are not a member of organisation "${orgSlug}".`);
|
|
8059
|
+
} else if (orgResponse.status === 404) {
|
|
8060
|
+
error(`Organisation "${orgSlug}" not found.`);
|
|
8061
|
+
} else {
|
|
8062
|
+
error(`Failed to verify organisation "${orgSlug}" (HTTP ${orgResponse.status}).`);
|
|
8063
|
+
}
|
|
8064
|
+
process.exit(1);
|
|
8065
|
+
}
|
|
8066
|
+
const orgData = await orgResponse.json();
|
|
8067
|
+
author = orgData.org?.name || orgSlug;
|
|
8068
|
+
} else {
|
|
8069
|
+
const repoOwner = repo.split("/")[0];
|
|
8070
|
+
owner = repoOwner || creds.email.split("@")[0];
|
|
8071
|
+
}
|
|
8072
|
+
console.log(pc8.dim(`
|
|
8073
|
+
Publishing ${pc8.bold(detail2.name)} to shard registry...`));
|
|
8074
|
+
const registryUrl = env === "dev" ? REGISTRY_URL_DEV : REGISTRY_URL_PROD;
|
|
8075
|
+
const slug = `${owner}/${detail2.shorthand}`;
|
|
8076
|
+
const response = await fetch(`${registryUrl}/api/register`, {
|
|
8077
|
+
method: "POST",
|
|
8078
|
+
headers: {
|
|
8079
|
+
"Content-Type": "application/json",
|
|
8080
|
+
Authorization: `Bearer ${creds.sessionToken}`
|
|
8081
|
+
},
|
|
8082
|
+
body: JSON.stringify({
|
|
8083
|
+
repo,
|
|
8084
|
+
shorthand: detail2.shorthand,
|
|
8085
|
+
owner,
|
|
8086
|
+
name: detail2.name,
|
|
8087
|
+
description: detail2.description,
|
|
8088
|
+
readme,
|
|
8089
|
+
...author ? { author } : {}
|
|
8090
|
+
})
|
|
8091
|
+
});
|
|
8092
|
+
const data = await response.json();
|
|
8093
|
+
if (!response.ok) {
|
|
8094
|
+
const msg = data.error?.message || `HTTP ${response.status}`;
|
|
8095
|
+
console.error(pc8.red(`
|
|
8096
|
+
Failed to publish: ${msg}`));
|
|
8097
|
+
console.log();
|
|
8098
|
+
process.exit(1);
|
|
8099
|
+
}
|
|
8100
|
+
console.log(pc8.green(`
|
|
8101
|
+
Published ${pc8.bold(detail2.name)} (${slug})`));
|
|
8102
|
+
console.log(pc8.dim(` Repo: ${repo}`));
|
|
8103
|
+
if (data.url) {
|
|
8104
|
+
console.log(pc8.dim(` URL: ${data.url}`));
|
|
8105
|
+
}
|
|
8106
|
+
console.log();
|
|
8107
|
+
} catch (err) {
|
|
8108
|
+
handleError(err);
|
|
8109
|
+
}
|
|
8110
|
+
});
|
|
8111
|
+
return cmd;
|
|
8112
|
+
})()
|
|
8113
|
+
).addCommand(
|
|
8114
|
+
(() => {
|
|
8115
|
+
const unpubRuntime = resolveRuntimeSync({ cliname: "flint" });
|
|
8116
|
+
const unpubDevAvailable = unpubRuntime.mode === "dev";
|
|
8117
|
+
const REGISTRY_URL_PROD = "https://amicable-dog-262.convex.site";
|
|
8118
|
+
const REGISTRY_URL_DEV = "https://grateful-sardine-809.convex.site";
|
|
8119
|
+
const cmd = new Command5("unpublish").description("Remove a shard from the NUU Shard Registry (requires login)").argument("<slug>", "Shard slug (e.g. NUU-Cognition/notepad)").option("-p, --path <dir>", "Path to flint");
|
|
8120
|
+
if (unpubDevAvailable) cmd.option("--dev", "Use dev environment");
|
|
8121
|
+
cmd.action(async (slug, options) => {
|
|
8122
|
+
try {
|
|
8123
|
+
const env = options.dev ? "dev" : unpubDevAvailable ? "dev" : "prod";
|
|
8124
|
+
const creds = await getValidAuth(
|
|
8125
|
+
{
|
|
8126
|
+
accountUrl: env === "dev" ? "https://dev-account.nuucognition.com" : "https://account.nuucognition.com",
|
|
8127
|
+
authEnv: env,
|
|
8128
|
+
cliname: "flint"
|
|
8129
|
+
},
|
|
8130
|
+
env
|
|
8131
|
+
);
|
|
8132
|
+
if (!creds) {
|
|
8133
|
+
error(`Not logged in. Run \`flint login${env === "dev" ? " --dev" : ""}\` to authenticate.`);
|
|
8134
|
+
process.exit(1);
|
|
8135
|
+
}
|
|
8136
|
+
console.log(pc8.dim(`
|
|
8137
|
+
Unpublishing ${pc8.bold(slug)} from shard registry...`));
|
|
8138
|
+
const registryUrl = env === "dev" ? REGISTRY_URL_DEV : REGISTRY_URL_PROD;
|
|
8139
|
+
const response = await fetch(`${registryUrl}/api/register`, {
|
|
8140
|
+
method: "DELETE",
|
|
8141
|
+
headers: {
|
|
8142
|
+
"Content-Type": "application/json",
|
|
8143
|
+
Authorization: `Bearer ${creds.sessionToken}`
|
|
8144
|
+
},
|
|
8145
|
+
body: JSON.stringify({ slug })
|
|
8146
|
+
});
|
|
8147
|
+
const data = await response.json();
|
|
8148
|
+
if (!response.ok) {
|
|
8149
|
+
const msg = data.error?.message || `HTTP ${response.status}`;
|
|
8150
|
+
console.error(pc8.red(`
|
|
8151
|
+
Failed to unpublish: ${msg}`));
|
|
8152
|
+
console.log();
|
|
8153
|
+
process.exit(1);
|
|
8154
|
+
}
|
|
8155
|
+
success(`Unpublished ${pc8.bold(slug)} from shard registry.`);
|
|
8156
|
+
console.log();
|
|
8157
|
+
} catch (err) {
|
|
8158
|
+
handleError(err);
|
|
8159
|
+
}
|
|
8160
|
+
});
|
|
8161
|
+
return cmd;
|
|
8162
|
+
})()
|
|
8163
|
+
).addCommand(
|
|
8164
|
+
(() => {
|
|
8165
|
+
const pubListRuntime = resolveRuntimeSync({ cliname: "flint" });
|
|
8166
|
+
const pubListDevAvailable = pubListRuntime.mode === "dev";
|
|
8167
|
+
const REGISTRY_URL_PROD = "https://amicable-dog-262.convex.site";
|
|
8168
|
+
const REGISTRY_URL_DEV = "https://grateful-sardine-809.convex.site";
|
|
8169
|
+
const cmd = new Command5("published").description("List your published shards on the NUU Shard Registry");
|
|
8170
|
+
if (pubListDevAvailable) cmd.option("--dev", "Use dev environment");
|
|
8171
|
+
cmd.action(async (options) => {
|
|
8172
|
+
try {
|
|
8173
|
+
const env = options.dev ? "dev" : pubListDevAvailable ? "dev" : "prod";
|
|
8174
|
+
const creds = await getValidAuth(
|
|
8175
|
+
{
|
|
8176
|
+
accountUrl: env === "dev" ? "https://dev-account.nuucognition.com" : "https://account.nuucognition.com",
|
|
8177
|
+
authEnv: env,
|
|
8178
|
+
cliname: "flint"
|
|
8179
|
+
},
|
|
8180
|
+
env
|
|
8181
|
+
);
|
|
8182
|
+
if (!creds) {
|
|
8183
|
+
error(`Not logged in. Run \`flint login${env === "dev" ? " --dev" : ""}\` to authenticate.`);
|
|
8184
|
+
process.exit(1);
|
|
8185
|
+
}
|
|
8186
|
+
const registryUrl = env === "dev" ? REGISTRY_URL_DEV : REGISTRY_URL_PROD;
|
|
8187
|
+
const response = await fetch(`${registryUrl}/api/my-shards`, {
|
|
8188
|
+
headers: {
|
|
8189
|
+
"Content-Type": "application/json",
|
|
8190
|
+
Authorization: `Bearer ${creds.sessionToken}`
|
|
8191
|
+
}
|
|
8192
|
+
});
|
|
8193
|
+
if (!response.ok) {
|
|
8194
|
+
const data2 = await response.json();
|
|
8195
|
+
const msg = data2.error?.message || `HTTP ${response.status}`;
|
|
8196
|
+
console.error(pc8.red(`
|
|
8197
|
+
Failed to fetch published shards: ${msg}`));
|
|
8198
|
+
console.log();
|
|
8199
|
+
process.exit(1);
|
|
8200
|
+
}
|
|
8201
|
+
const data = await response.json();
|
|
8202
|
+
if (!data.shards.length) {
|
|
8203
|
+
console.log(pc8.dim("\nNo published shards found."));
|
|
8204
|
+
console.log(pc8.dim(` Run ${pc8.cyan("flint shard publish <name>")} to publish a shard.`));
|
|
8205
|
+
console.log();
|
|
8206
|
+
return;
|
|
8207
|
+
}
|
|
8208
|
+
console.log(pc8.dim(`
|
|
8209
|
+
${data.shards.length} published shard${data.shards.length === 1 ? "" : "s"}:
|
|
8210
|
+
`));
|
|
8211
|
+
for (const s of data.shards) {
|
|
8212
|
+
console.log(` ${pc8.bold(s.name)} ${pc8.dim(s.slug)} ${pc8.dim(s.repo)}`);
|
|
8213
|
+
}
|
|
8214
|
+
console.log();
|
|
8215
|
+
} catch (err) {
|
|
8216
|
+
handleError(err);
|
|
8217
|
+
}
|
|
8218
|
+
});
|
|
8219
|
+
return cmd;
|
|
8220
|
+
})()
|
|
8221
|
+
).addCommand(
|
|
8222
|
+
new Command5("scripts").description("List executable scripts provided by a shard").argument("<name>", "Shard name (e.g. projects, living-documents)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7687
8223
|
try {
|
|
7688
8224
|
const flintPath = await resolveFlint(options.path);
|
|
7689
8225
|
const scripts = await listShardScripts(flintPath, shorthand);
|
|
@@ -7709,7 +8245,7 @@ Scripts for ${shorthand}:
|
|
|
7709
8245
|
);
|
|
7710
8246
|
|
|
7711
8247
|
// src/commands/mod.ts
|
|
7712
|
-
import { Command as
|
|
8248
|
+
import { Command as Command6 } from "commander";
|
|
7713
8249
|
import { spawn as spawn3 } from "child_process";
|
|
7714
8250
|
import { join as join21 } from "path";
|
|
7715
8251
|
import { existsSync as existsSync4 } from "fs";
|
|
@@ -7760,7 +8296,7 @@ function resolveInstalledMod(installed, identifier) {
|
|
|
7760
8296
|
return false;
|
|
7761
8297
|
});
|
|
7762
8298
|
}
|
|
7763
|
-
var modCommand = new
|
|
8299
|
+
var modCommand = new Command6("mod").description("Manage mods \u2014 install, create, and maintain mod packages").argument("[identifier]", "Mod identifier for script execution").argument("[script]", "Script name to run").argument("[args...]", "Script arguments").option("-p, --path <dir>", "Path to flint").allowUnknownOption().action(async (identifier, script, args, options) => {
|
|
7764
8300
|
if (!identifier) {
|
|
7765
8301
|
modCommand.help();
|
|
7766
8302
|
return;
|
|
@@ -7854,7 +8390,7 @@ Mod not installed: "${identifier}"`));
|
|
|
7854
8390
|
handleError2(err);
|
|
7855
8391
|
}
|
|
7856
8392
|
}).addCommand(
|
|
7857
|
-
new
|
|
8393
|
+
new Command6("install").description("Install a mod from a source (owner/repo, path:, or builtin shorthand)").argument("<source>", "Source identifier (e.g. owner/repo, path:./local, or builtin shorthand like cc)").option("-f, --force", "Overwrite existing files").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
7858
8394
|
try {
|
|
7859
8395
|
const flintPath = await resolveFlint2(options.path);
|
|
7860
8396
|
if (isSourceIdentifier2(source)) {
|
|
@@ -7920,7 +8456,7 @@ Installed ${pc9.bold(result.name)}`));
|
|
|
7920
8456
|
}
|
|
7921
8457
|
})
|
|
7922
8458
|
).addCommand(
|
|
7923
|
-
new
|
|
8459
|
+
new Command6("uninstall").description("Uninstall a mod and clean up its files").argument("<shorthand>", "Mod shorthand or name").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
7924
8460
|
try {
|
|
7925
8461
|
const flintPath = await resolveFlint2(options.path);
|
|
7926
8462
|
const result = await uninstallMod(flintPath, shorthand);
|
|
@@ -7933,7 +8469,7 @@ Uninstalled ${pc9.bold(result.name)}`));
|
|
|
7933
8469
|
}
|
|
7934
8470
|
})
|
|
7935
8471
|
).addCommand(
|
|
7936
|
-
new
|
|
8472
|
+
new Command6("list").alias("ls").description("List installed or available mods").option("-a, --available", "Show mods available to install").option("-s, --sources", "Show source declarations from flint.toml").option("-p, --path <dir>", "Path to flint").action(async (options) => {
|
|
7937
8473
|
try {
|
|
7938
8474
|
if (options.available) {
|
|
7939
8475
|
const available = await listAvailableMods();
|
|
@@ -7984,7 +8520,7 @@ Uninstalled ${pc9.bold(result.name)}`));
|
|
|
7984
8520
|
Object.entries(declarations).filter(([, d]) => d.dev).map(([k]) => k)
|
|
7985
8521
|
);
|
|
7986
8522
|
console.log(pc9.bold("\nInstalled mods:\n"));
|
|
7987
|
-
const { execSync:
|
|
8523
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
7988
8524
|
const gitRemotes = /* @__PURE__ */ new Map();
|
|
7989
8525
|
for (const mod of installed) {
|
|
7990
8526
|
const kebab = toKebabCase(mod.name);
|
|
@@ -7993,7 +8529,7 @@ Uninstalled ${pc9.bold(result.name)}`));
|
|
|
7993
8529
|
const gitDir = join21(modPath, ".git");
|
|
7994
8530
|
if (!existsSync4(gitDir)) continue;
|
|
7995
8531
|
try {
|
|
7996
|
-
const url =
|
|
8532
|
+
const url = execSync4("git remote get-url origin", { cwd: modPath, encoding: "utf-8" }).trim();
|
|
7997
8533
|
const match = url.match(/(?:github\.com[/:])([\w.-]+\/[\w.-]+?)(?:\.git)?$/);
|
|
7998
8534
|
if (match) {
|
|
7999
8535
|
gitRemotes.set(mod.name, match[1]);
|
|
@@ -8023,7 +8559,7 @@ Uninstalled ${pc9.bold(result.name)}`));
|
|
|
8023
8559
|
}
|
|
8024
8560
|
})
|
|
8025
8561
|
).addCommand(
|
|
8026
|
-
new
|
|
8562
|
+
new Command6("update").description("Update non-dev mods (use --reinstall to force)").option("-p, --path <dir>", "Path to flint").option("--reinstall", "Force reinstall all non-dev mods").action(async (options) => {
|
|
8027
8563
|
try {
|
|
8028
8564
|
const flintPath = await resolveFlint2(options.path);
|
|
8029
8565
|
const installed = await getInstalledMods(flintPath);
|
|
@@ -8076,7 +8612,7 @@ ${mode} ${updatable.length} mod(s)...
|
|
|
8076
8612
|
}
|
|
8077
8613
|
})
|
|
8078
8614
|
).addCommand(
|
|
8079
|
-
new
|
|
8615
|
+
new Command6("pull").description("Sync mod repos and install entries from manifest").argument("[identifier]", "Mod to pull (omit for all)").option("-p, --path <dir>", "Path to flint").action(async (identifier, options) => {
|
|
8080
8616
|
try {
|
|
8081
8617
|
const flintPath = await resolveFlint2(options.path);
|
|
8082
8618
|
if (identifier) {
|
|
@@ -8113,7 +8649,7 @@ Pulling all mod repos...
|
|
|
8113
8649
|
}
|
|
8114
8650
|
})
|
|
8115
8651
|
).addCommand(
|
|
8116
|
-
new
|
|
8652
|
+
new Command6("create").description("Scaffold a new dev mod with standard structure").argument("<name>", 'Mod name (e.g. "Obsidian", "Docker")').option("-s, --shorthand <id>", "Mod shorthand identifier (default: derived from name)").option("-d, --description <text>", "Mod description").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
8117
8653
|
try {
|
|
8118
8654
|
const flintPath = await resolveFlint2(options.path);
|
|
8119
8655
|
const shorthand = options.shorthand || name.split(/\s+/).map((w) => w[0]).join("").toLowerCase().slice(0, 4) || name.toLowerCase().replace(/\s+/g, "").slice(0, 4);
|
|
@@ -8135,7 +8671,7 @@ Created ${pc9.bold(result.name)}`));
|
|
|
8135
8671
|
}
|
|
8136
8672
|
})
|
|
8137
8673
|
).addCommand(
|
|
8138
|
-
new
|
|
8674
|
+
new Command6("dev").description("Clone an existing mod into a (Dev) folder for local editing").argument("<source>", "Source identifier (e.g. owner/repo, path:./local, or builtin shorthand like cc)").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
8139
8675
|
try {
|
|
8140
8676
|
const flintPath = await resolveFlint2(options.path);
|
|
8141
8677
|
if (isSourceIdentifier2(source)) {
|
|
@@ -8172,31 +8708,18 @@ Cloned ${pc9.bold(result.name)} for development`));
|
|
|
8172
8708
|
await cleanupResolvedModSource(resolved);
|
|
8173
8709
|
}
|
|
8174
8710
|
} else {
|
|
8175
|
-
|
|
8176
|
-
|
|
8177
|
-
|
|
8178
|
-
const shorthands = available.map((m) => m.shorthand).join(", ");
|
|
8179
|
-
console.error(pc9.red(`
|
|
8180
|
-
Unknown mod: "${source}"`));
|
|
8181
|
-
console.log(pc9.dim(` Available: ${shorthands}`));
|
|
8182
|
-
console.log();
|
|
8183
|
-
process.exit(1);
|
|
8184
|
-
}
|
|
8185
|
-
console.log(pc9.dim(`
|
|
8186
|
-
Cloning ${mod.name}...`));
|
|
8187
|
-
const result = await cloneModToDev(flintPath, mod.path, mod);
|
|
8188
|
-
await updateGitignore(flintPath);
|
|
8189
|
-
console.log(pc9.green(`
|
|
8190
|
-
Cloned ${pc9.bold(result.name)} for development`));
|
|
8191
|
-
console.log(pc9.dim(` Path: ${abbreviatePath(result.path)}`));
|
|
8711
|
+
console.error(pc9.red(`
|
|
8712
|
+
Unknown mod source: "${source}"`));
|
|
8713
|
+
console.log(pc9.dim(` Provide an owner/repo source (e.g., "NUU-Cognition/flint-mod-agents")`));
|
|
8192
8714
|
console.log();
|
|
8715
|
+
process.exit(1);
|
|
8193
8716
|
}
|
|
8194
8717
|
} catch (err) {
|
|
8195
8718
|
handleError2(err);
|
|
8196
8719
|
}
|
|
8197
8720
|
})
|
|
8198
8721
|
).addCommand(
|
|
8199
|
-
new
|
|
8722
|
+
new Command6("register").description("Register an existing Mods/ folder as a dev mod in flint.toml").argument("<folder>", 'Folder name inside Mods/ (e.g., "(Dev) Docker")').option("-p, --path <dir>", "Path to flint").action(async (folder, options) => {
|
|
8200
8723
|
try {
|
|
8201
8724
|
const flintPath = await resolveFlint2(options.path);
|
|
8202
8725
|
const result = await registerExistingMod(flintPath, folder);
|
|
@@ -8212,7 +8735,7 @@ Registered ${pc9.bold(result.name)}`));
|
|
|
8212
8735
|
}
|
|
8213
8736
|
})
|
|
8214
8737
|
).addCommand(
|
|
8215
|
-
new
|
|
8738
|
+
new Command6("info").description("Show detailed information about a mod").argument("<name>", "Mod shorthand, name, or folder name").option("-p, --path <dir>", "Path to flint").action(async (identifier, options) => {
|
|
8216
8739
|
try {
|
|
8217
8740
|
const flintPath = await resolveFlint2(options.path);
|
|
8218
8741
|
const detail2 = await getModInfo(flintPath, identifier);
|
|
@@ -8266,7 +8789,7 @@ Mod not found: "${identifier}"`));
|
|
|
8266
8789
|
}
|
|
8267
8790
|
})
|
|
8268
8791
|
).addCommand(
|
|
8269
|
-
new
|
|
8792
|
+
new Command6("check").description("Check mod system integrity and report issues").option("-p, --path <dir>", "Path to flint").action(async (options) => {
|
|
8270
8793
|
try {
|
|
8271
8794
|
const flintPath = await resolveFlint2(options.path);
|
|
8272
8795
|
console.log(pc9.bold("\nMod Health Check\n"));
|
|
@@ -8299,7 +8822,7 @@ Mod not found: "${identifier}"`));
|
|
|
8299
8822
|
}
|
|
8300
8823
|
})
|
|
8301
8824
|
).addCommand(
|
|
8302
|
-
new
|
|
8825
|
+
new Command6("heal").description("Check and fix a mod \u2014 ensures folders, manifest, naming, and dependencies").argument("<name>", "Mod name (e.g. claude-code, agents)").option("-n, --dry-run", "Preview fixes without applying them").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
8303
8826
|
try {
|
|
8304
8827
|
const flintPath = await resolveFlint2(options.path);
|
|
8305
8828
|
const installed = await getInstalledMods(flintPath);
|
|
@@ -8353,7 +8876,7 @@ Healing ${match.folderName}...
|
|
|
8353
8876
|
}
|
|
8354
8877
|
})
|
|
8355
8878
|
).addCommand(
|
|
8356
|
-
new
|
|
8879
|
+
new Command6("add").description("Add a mod to flint.toml without installing files").argument("<source>", "Mod source (owner/repo, path:./local, or builtin shorthand)").option("-p, --path <dir>", "Path to flint").action(async (source, options) => {
|
|
8357
8880
|
try {
|
|
8358
8881
|
const flintPath = await resolveFlint2(options.path);
|
|
8359
8882
|
let modName;
|
|
@@ -8376,7 +8899,7 @@ Added ${pc9.bold(modName)}`));
|
|
|
8376
8899
|
}
|
|
8377
8900
|
})
|
|
8378
8901
|
).addCommand(
|
|
8379
|
-
new
|
|
8902
|
+
new Command6("remove").description("Remove a mod declaration from flint.toml (does not delete files)").argument("<name>", "Mod name").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
8380
8903
|
try {
|
|
8381
8904
|
const flintPath = await resolveFlint2(options.path);
|
|
8382
8905
|
await removeModFromConfig(flintPath, name);
|
|
@@ -8389,7 +8912,7 @@ Removed ${pc9.bold(name)} from flint.toml`));
|
|
|
8389
8912
|
}
|
|
8390
8913
|
})
|
|
8391
8914
|
).addCommand(
|
|
8392
|
-
new
|
|
8915
|
+
new Command6("reinstall").description("Re-run install entries for a mod (useful for dev testing)").argument("<shorthand>", "Mod shorthand or name").option("--force", "Override once entries (re-install all files)").option("-p, --path <dir>", "Path to flint").action(async (shorthand, options) => {
|
|
8393
8916
|
try {
|
|
8394
8917
|
const flintPath = await resolveFlint2(options.path);
|
|
8395
8918
|
console.log(pc9.bold(`
|
|
@@ -8421,9 +8944,9 @@ Reinstalling ${shorthand}...
|
|
|
8421
8944
|
}
|
|
8422
8945
|
})
|
|
8423
8946
|
).addCommand(
|
|
8424
|
-
new
|
|
8947
|
+
new Command6("gitinit").description("Initialize git repo for a dev mod and push to a remote").argument("<name>", "Mod name (e.g. claude-code, agents)").argument("<url>", "Git remote URL (e.g., https://github.com/org/repo.git)").option("-p, --path <dir>", "Path to flint").action(async (name, url, options) => {
|
|
8425
8948
|
try {
|
|
8426
|
-
const { execSync:
|
|
8949
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
8427
8950
|
const flintPath = await resolveFlint2(options.path);
|
|
8428
8951
|
const installed = await getInstalledMods(flintPath);
|
|
8429
8952
|
const match = resolveInstalledMod(installed, name);
|
|
@@ -8453,12 +8976,12 @@ Mod "${name}" not found.`));
|
|
|
8453
8976
|
console.log(pc9.bold(`
|
|
8454
8977
|
Initializing ${match.folderName}...
|
|
8455
8978
|
`));
|
|
8456
|
-
|
|
8457
|
-
|
|
8458
|
-
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8979
|
+
execSync4("git init", { cwd: modPath, stdio: "pipe" });
|
|
8980
|
+
execSync4(`git remote add origin "${url}"`, { cwd: modPath, stdio: "pipe" });
|
|
8981
|
+
execSync4("git branch -M main", { cwd: modPath, stdio: "pipe" });
|
|
8982
|
+
execSync4("git add -A", { cwd: modPath, stdio: "pipe" });
|
|
8983
|
+
execSync4('git commit -m "initial commit"', { cwd: modPath, stdio: "pipe" });
|
|
8984
|
+
execSync4("git push -u origin main", { cwd: modPath, stdio: "inherit" });
|
|
8462
8985
|
console.log(pc9.green(`
|
|
8463
8986
|
${pc9.bold(match.folderName)} pushed to ${pc9.dim(url)}`));
|
|
8464
8987
|
console.log();
|
|
@@ -8467,9 +8990,9 @@ Initializing ${match.folderName}...
|
|
|
8467
8990
|
}
|
|
8468
8991
|
})
|
|
8469
8992
|
).addCommand(
|
|
8470
|
-
new
|
|
8993
|
+
new Command6("push").description("Commit and push a dev mod to its remote").argument("<name>", "Mod name (e.g. claude-code, agents)").option("-m, --message <msg>", "Commit message").option("-p, --path <dir>", "Path to flint").action(async (name, options) => {
|
|
8471
8994
|
try {
|
|
8472
|
-
const { execSync:
|
|
8995
|
+
const { execSync: execSync4 } = await import("child_process");
|
|
8473
8996
|
const flintPath = await resolveFlint2(options.path);
|
|
8474
8997
|
const installed = await getInstalledMods(flintPath);
|
|
8475
8998
|
const match = resolveInstalledMod(installed, name);
|
|
@@ -8497,15 +9020,15 @@ Mod "${name}" not found.`));
|
|
|
8497
9020
|
console.log();
|
|
8498
9021
|
return;
|
|
8499
9022
|
}
|
|
8500
|
-
const status =
|
|
9023
|
+
const status = execSync4("git status --porcelain", { cwd: modPath, encoding: "utf-8" }).trim();
|
|
8501
9024
|
if (!status) {
|
|
8502
9025
|
try {
|
|
8503
|
-
const unpushed =
|
|
9026
|
+
const unpushed = execSync4("git log @{u}..HEAD --oneline", { cwd: modPath, encoding: "utf-8" }).trim();
|
|
8504
9027
|
if (unpushed) {
|
|
8505
9028
|
console.log(pc9.bold(`
|
|
8506
9029
|
Pushing ${match.folderName}...
|
|
8507
9030
|
`));
|
|
8508
|
-
|
|
9031
|
+
execSync4("git push", { cwd: modPath, stdio: "inherit" });
|
|
8509
9032
|
console.log(pc9.green(`
|
|
8510
9033
|
Pushed unpushed commits.`));
|
|
8511
9034
|
console.log();
|
|
@@ -8522,13 +9045,13 @@ No changes to push in "${match.folderName}".`));
|
|
|
8522
9045
|
console.log(pc9.bold(`
|
|
8523
9046
|
Pushing ${match.folderName}...
|
|
8524
9047
|
`));
|
|
8525
|
-
|
|
8526
|
-
|
|
9048
|
+
execSync4("git add -A", { cwd: modPath, stdio: "pipe" });
|
|
9049
|
+
execSync4(`git commit -m "${message.replace(/"/g, '\\"')}"`, { cwd: modPath, stdio: "pipe" });
|
|
8527
9050
|
try {
|
|
8528
|
-
|
|
9051
|
+
execSync4("git push", { cwd: modPath, stdio: "inherit" });
|
|
8529
9052
|
} catch {
|
|
8530
|
-
const branch =
|
|
8531
|
-
|
|
9053
|
+
const branch = execSync4("git branch --show-current", { cwd: modPath, encoding: "utf-8" }).trim();
|
|
9054
|
+
execSync4(`git push -u origin ${branch}`, { cwd: modPath, stdio: "inherit" });
|
|
8532
9055
|
}
|
|
8533
9056
|
console.log(pc9.green(`
|
|
8534
9057
|
${pc9.bold(match.folderName)} pushed.`));
|
|
@@ -8539,7 +9062,7 @@ Pushing ${match.folderName}...
|
|
|
8539
9062
|
}
|
|
8540
9063
|
})
|
|
8541
9064
|
).addCommand(
|
|
8542
|
-
new
|
|
9065
|
+
new Command6("scripts").description("List executable scripts provided by a mod").argument("<identifier>", "Mod shorthand (e.g., cc)").option("-p, --path <dir>", "Path to flint").action(async (identifier, options) => {
|
|
8543
9066
|
try {
|
|
8544
9067
|
const flintPath = await resolveFlint2(options.path);
|
|
8545
9068
|
const scripts = await listModScripts(flintPath, identifier);
|
|
@@ -8565,9 +9088,9 @@ Scripts for ${identifier}:
|
|
|
8565
9088
|
);
|
|
8566
9089
|
|
|
8567
9090
|
// src/commands/sync.ts
|
|
8568
|
-
import { Command as
|
|
9091
|
+
import { Command as Command7 } from "commander";
|
|
8569
9092
|
import pc10 from "picocolors";
|
|
8570
|
-
var syncCommand = new
|
|
9093
|
+
var syncCommand = new Command7("sync").description("Sync shards and mods from flint.toml").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
8571
9094
|
try {
|
|
8572
9095
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
8573
9096
|
if (!flintPath) {
|
|
@@ -8577,7 +9100,39 @@ var syncCommand = new Command8("sync").description("Sync shards and mods from fl
|
|
|
8577
9100
|
process.exit(1);
|
|
8578
9101
|
}
|
|
8579
9102
|
console.log(pc10.bold("\nSyncing flint...\n"));
|
|
8580
|
-
|
|
9103
|
+
let shardProgress;
|
|
9104
|
+
let modProgress;
|
|
9105
|
+
const progress = {
|
|
9106
|
+
onShardPhase(total) {
|
|
9107
|
+
if (total > 0) {
|
|
9108
|
+
shardProgress = createProgressDisplay("Installing shards", total);
|
|
9109
|
+
}
|
|
9110
|
+
},
|
|
9111
|
+
onShardStart(name) {
|
|
9112
|
+
shardProgress?.onStart(name);
|
|
9113
|
+
},
|
|
9114
|
+
onShardDone(name, ok) {
|
|
9115
|
+
if (ok) shardProgress?.onComplete(name);
|
|
9116
|
+
else shardProgress?.onError(name);
|
|
9117
|
+
},
|
|
9118
|
+
onModPhase(total) {
|
|
9119
|
+
shardProgress?.finish();
|
|
9120
|
+
if (total > 0) {
|
|
9121
|
+
console.log();
|
|
9122
|
+
modProgress = createProgressDisplay("Installing mods", total);
|
|
9123
|
+
}
|
|
9124
|
+
},
|
|
9125
|
+
onModStart(name) {
|
|
9126
|
+
modProgress?.onStart(name);
|
|
9127
|
+
},
|
|
9128
|
+
onModDone(name, ok) {
|
|
9129
|
+
if (ok) modProgress?.onComplete(name);
|
|
9130
|
+
else modProgress?.onError(name);
|
|
9131
|
+
}
|
|
9132
|
+
};
|
|
9133
|
+
const result = await syncFlint(flintPath, progress);
|
|
9134
|
+
shardProgress?.finish();
|
|
9135
|
+
modProgress?.finish();
|
|
8581
9136
|
if (result.bootstrap.created) {
|
|
8582
9137
|
console.log(pc10.green("Bootstrap:"));
|
|
8583
9138
|
console.log(` ${pc10.green("+")} Created .flint/ directory`);
|
|
@@ -8616,12 +9171,6 @@ var syncCommand = new Command8("sync").description("Sync shards and mods from fl
|
|
|
8616
9171
|
}
|
|
8617
9172
|
const hasShardChanges = result.shards.installed.length > 0 || result.shards.uninstalled.length > 0 || result.shards.orphaned.length > 0;
|
|
8618
9173
|
const hasModChanges = result.mods.installed.length > 0 || result.mods.uninstalled.length > 0;
|
|
8619
|
-
if (result.shards.installed.length > 0) {
|
|
8620
|
-
console.log(pc10.green("Shards installed:"));
|
|
8621
|
-
for (const s of result.shards.installed) {
|
|
8622
|
-
console.log(` ${pc10.green("+")} ${s}`);
|
|
8623
|
-
}
|
|
8624
|
-
}
|
|
8625
9174
|
if (result.shards.uninstalled.length > 0) {
|
|
8626
9175
|
console.log(pc10.yellow("Shards removed:"));
|
|
8627
9176
|
for (const s of result.shards.uninstalled) {
|
|
@@ -8635,12 +9184,6 @@ var syncCommand = new Command8("sync").description("Sync shards and mods from fl
|
|
|
8635
9184
|
}
|
|
8636
9185
|
console.log(pc10.dim(" Run `flint shard uninstall <shorthand>` to remove"));
|
|
8637
9186
|
}
|
|
8638
|
-
if (result.mods.installed.length > 0) {
|
|
8639
|
-
console.log(pc10.green("Mods installed:"));
|
|
8640
|
-
for (const s of result.mods.installed) {
|
|
8641
|
-
console.log(` ${pc10.green("+")} ${s}`);
|
|
8642
|
-
}
|
|
8643
|
-
}
|
|
8644
9187
|
if (result.mods.uninstalled.length > 0) {
|
|
8645
9188
|
console.log(pc10.yellow("Mods removed:"));
|
|
8646
9189
|
for (const s of result.mods.uninstalled) {
|
|
@@ -8683,6 +9226,9 @@ var syncCommand = new Command8("sync").description("Sync shards and mods from fl
|
|
|
8683
9226
|
case "not_found":
|
|
8684
9227
|
console.log(` ${pc10.yellow("\u26A0")} ${imp.ref} - flint not found in registry`);
|
|
8685
9228
|
break;
|
|
9229
|
+
case "export_not_found":
|
|
9230
|
+
console.log(` ${pc10.yellow("\u26A0")} ${imp.ref} - ${imp.error}`);
|
|
9231
|
+
break;
|
|
8686
9232
|
case "not_built":
|
|
8687
9233
|
console.log(` ${pc10.yellow("\u26A0")} ${imp.ref} - export not built`);
|
|
8688
9234
|
break;
|
|
@@ -8740,9 +9286,9 @@ var syncCommand = new Command8("sync").description("Sync shards and mods from fl
|
|
|
8740
9286
|
});
|
|
8741
9287
|
|
|
8742
9288
|
// src/commands/git.ts
|
|
8743
|
-
import { Command as
|
|
9289
|
+
import { Command as Command8 } from "commander";
|
|
8744
9290
|
import pc11 from "picocolors";
|
|
8745
|
-
var gitCommand = new
|
|
9291
|
+
var gitCommand = new Command8("git").description("Git operations for the Flint").enablePositionalOptions().passThroughOptions().option("-p, --path <dir>", "Path to flint (default: auto-detect)").argument("[args...]", "Git arguments").action(async (args, options) => {
|
|
8746
9292
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
8747
9293
|
if (!flintPath) {
|
|
8748
9294
|
console.error(pc11.red("Error: Not inside a Flint."));
|
|
@@ -8768,21 +9314,19 @@ var gitCommand = new Command9("git").description("Git operations for the Flint")
|
|
|
8768
9314
|
}
|
|
8769
9315
|
});
|
|
8770
9316
|
async function handleInit(flintPath) {
|
|
8771
|
-
const
|
|
8772
|
-
if (
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
await updateGitignore(flintPath);
|
|
8777
|
-
console.log(pc11.green("Updated .gitignore"));
|
|
8778
|
-
} else {
|
|
8779
|
-
console.log(pc11.yellow("Git mod installed but git not initialized. Run `git init` manually."));
|
|
8780
|
-
}
|
|
9317
|
+
const initialized = await isGitInitialized(flintPath);
|
|
9318
|
+
if (initialized) {
|
|
9319
|
+
console.log(pc11.yellow("Git already initialized. Updating .gitignore..."));
|
|
9320
|
+
await updateGitignore(flintPath);
|
|
9321
|
+
console.log(pc11.green("Updated .gitignore"));
|
|
8781
9322
|
return;
|
|
8782
9323
|
}
|
|
8783
9324
|
try {
|
|
8784
|
-
|
|
8785
|
-
|
|
9325
|
+
const result = await initGit(flintPath);
|
|
9326
|
+
if (!result.success) {
|
|
9327
|
+
console.error(pc11.red(`Error: ${result.error}`));
|
|
9328
|
+
process.exit(1);
|
|
9329
|
+
}
|
|
8786
9330
|
console.log(pc11.green("Initialized git repository"));
|
|
8787
9331
|
console.log(pc11.dim("Created .gitignore with Flint defaults"));
|
|
8788
9332
|
} catch (err) {
|
|
@@ -8808,23 +9352,21 @@ async function handleGitInit(flintPath, args) {
|
|
|
8808
9352
|
console.log(pc11.dim("Usage: flint git gitinit <repolink>"));
|
|
8809
9353
|
process.exit(1);
|
|
8810
9354
|
}
|
|
8811
|
-
const
|
|
8812
|
-
if (!
|
|
9355
|
+
const initialized = await isGitInitialized(flintPath);
|
|
9356
|
+
if (!initialized) {
|
|
8813
9357
|
try {
|
|
8814
|
-
|
|
8815
|
-
|
|
9358
|
+
const result = await initGit(flintPath);
|
|
9359
|
+
if (!result.success) {
|
|
9360
|
+
console.error(pc11.red(`Failed to initialize git: ${result.error}`));
|
|
9361
|
+
process.exit(1);
|
|
9362
|
+
}
|
|
8816
9363
|
console.log(pc11.green("\u2713 Initialized git repository"));
|
|
8817
9364
|
} catch (err) {
|
|
8818
|
-
console.error(pc11.red(`Failed to
|
|
9365
|
+
console.error(pc11.red(`Failed to initialize git: ${err instanceof Error ? err.message : String(err)}`));
|
|
8819
9366
|
process.exit(1);
|
|
8820
9367
|
}
|
|
8821
9368
|
} else {
|
|
8822
|
-
|
|
8823
|
-
if (!initialized) {
|
|
8824
|
-
console.error(pc11.red("Git mod installed but git not initialized. Run `git init` manually."));
|
|
8825
|
-
process.exit(1);
|
|
8826
|
-
}
|
|
8827
|
-
console.log(pc11.dim("Git mod already installed."));
|
|
9369
|
+
console.log(pc11.dim("Git already initialized."));
|
|
8828
9370
|
}
|
|
8829
9371
|
try {
|
|
8830
9372
|
console.log(pc11.dim("Syncing flint..."));
|
|
@@ -8914,9 +9456,9 @@ async function showFlintGitStatus(flintPath) {
|
|
|
8914
9456
|
}
|
|
8915
9457
|
|
|
8916
9458
|
// src/commands/repair.ts
|
|
8917
|
-
import { Command as
|
|
9459
|
+
import { Command as Command9 } from "commander";
|
|
8918
9460
|
import pc12 from "picocolors";
|
|
8919
|
-
import { mkdir as mkdir12, access as
|
|
9461
|
+
import { mkdir as mkdir12, access as access7 } from "fs/promises";
|
|
8920
9462
|
import { join as join24, basename as basename2 } from "path";
|
|
8921
9463
|
var REQUIRED_DIRS = [
|
|
8922
9464
|
"Mesh",
|
|
@@ -8930,7 +9472,7 @@ var REQUIRED_DIRS = [
|
|
|
8930
9472
|
];
|
|
8931
9473
|
async function exists2(path3) {
|
|
8932
9474
|
try {
|
|
8933
|
-
await
|
|
9475
|
+
await access7(path3);
|
|
8934
9476
|
return true;
|
|
8935
9477
|
} catch {
|
|
8936
9478
|
return false;
|
|
@@ -9063,7 +9605,7 @@ function printResults(title, results) {
|
|
|
9063
9605
|
}
|
|
9064
9606
|
console.log();
|
|
9065
9607
|
}
|
|
9066
|
-
var repairCommand = new
|
|
9608
|
+
var repairCommand = new Command9("repair").description("Repair a flint to match current specifications").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-n, --dry-run", "Show what would be fixed without making changes").action(async (options) => {
|
|
9067
9609
|
try {
|
|
9068
9610
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9069
9611
|
if (!flintPath) {
|
|
@@ -9151,9 +9693,9 @@ var repairCommand = new Command10("repair").description("Repair a flint to match
|
|
|
9151
9693
|
});
|
|
9152
9694
|
|
|
9153
9695
|
// src/commands/export.ts
|
|
9154
|
-
import { Command as
|
|
9696
|
+
import { Command as Command10 } from "commander";
|
|
9155
9697
|
import pc13 from "picocolors";
|
|
9156
|
-
import { readFile as
|
|
9698
|
+
import { readFile as readFile10, stat as stat7 } from "fs/promises";
|
|
9157
9699
|
import { join as join25, basename as basename4 } from "path";
|
|
9158
9700
|
import { createInterface as createInterface2 } from "readline";
|
|
9159
9701
|
async function exists3(path3) {
|
|
@@ -9208,7 +9750,7 @@ async function getExportStatus(flintPath) {
|
|
|
9208
9750
|
if (!await exists3(manifestPath)) {
|
|
9209
9751
|
manifestPath = join25(flintPath, "Exports", manifest.name, "_manifest.json");
|
|
9210
9752
|
}
|
|
9211
|
-
const manifestJson = JSON.parse(await
|
|
9753
|
+
const manifestJson = JSON.parse(await readFile10(manifestPath, "utf-8"));
|
|
9212
9754
|
fileCount = manifestJson.files?.length || 0;
|
|
9213
9755
|
} catch {
|
|
9214
9756
|
}
|
|
@@ -9222,7 +9764,7 @@ async function getExportStatus(flintPath) {
|
|
|
9222
9764
|
}
|
|
9223
9765
|
return results;
|
|
9224
9766
|
}
|
|
9225
|
-
var listCommand2 = new
|
|
9767
|
+
var listCommand2 = new Command10("list").description("List all declared exports").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
9226
9768
|
try {
|
|
9227
9769
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9228
9770
|
if (!flintPath) {
|
|
@@ -9259,7 +9801,7 @@ var listCommand2 = new Command11("list").description("List all declared exports"
|
|
|
9259
9801
|
process.exit(1);
|
|
9260
9802
|
}
|
|
9261
9803
|
});
|
|
9262
|
-
var scanCommand = new
|
|
9804
|
+
var scanCommand = new Command10("scan").description("Find #export-tagged files not yet declared").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
9263
9805
|
try {
|
|
9264
9806
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9265
9807
|
if (!flintPath) {
|
|
@@ -9301,9 +9843,23 @@ var scanCommand = new Command11("scan").description("Find #export-tagged files n
|
|
|
9301
9843
|
});
|
|
9302
9844
|
console.log(` ${pc13.green("\u2713")} Added ${pc13.cyan(exportName)}`);
|
|
9303
9845
|
}
|
|
9846
|
+
const manifests = await scanExports(flintPath);
|
|
9847
|
+
if (manifests.length > 0) {
|
|
9848
|
+
console.log();
|
|
9849
|
+
console.log(pc13.bold("Building exports..."));
|
|
9850
|
+
console.log();
|
|
9851
|
+
const removed = await cleanupStaleExports(flintPath);
|
|
9852
|
+
for (const r of removed) {
|
|
9853
|
+
console.log(` ${pc13.yellow("-")} ${r} ${pc13.dim("(removed stale)")}`);
|
|
9854
|
+
}
|
|
9855
|
+
for (const manifest of manifests) {
|
|
9856
|
+
const result = await buildExport(manifest, flintPath);
|
|
9857
|
+
console.log(` ${pc13.green("\u2713")} Built ${pc13.cyan(result.name)} \u2014 ${result.filesCopied} files`);
|
|
9858
|
+
}
|
|
9859
|
+
}
|
|
9304
9860
|
await refreshRegistryExports(flintPath);
|
|
9305
9861
|
console.log();
|
|
9306
|
-
console.log(pc13.
|
|
9862
|
+
console.log(pc13.green("Done!"));
|
|
9307
9863
|
console.log();
|
|
9308
9864
|
} catch (err) {
|
|
9309
9865
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -9311,7 +9867,7 @@ var scanCommand = new Command11("scan").description("Find #export-tagged files n
|
|
|
9311
9867
|
process.exit(1);
|
|
9312
9868
|
}
|
|
9313
9869
|
});
|
|
9314
|
-
var addCommand = new
|
|
9870
|
+
var addCommand = new Command10("add").description("Declare a file as an export").argument("<file>", "Source file name (must have #export tag)").argument("<name>", "Export name").argument("[mode]", "Export mode", "mesh").option("-d, --depth <n>", "Export depth (default: 1 for mesh mode)", parseInt).option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (file, name, mode, options) => {
|
|
9315
9871
|
try {
|
|
9316
9872
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9317
9873
|
if (!flintPath) {
|
|
@@ -9357,7 +9913,7 @@ var addCommand = new Command11("add").description("Declare a file as an export")
|
|
|
9357
9913
|
process.exit(1);
|
|
9358
9914
|
}
|
|
9359
9915
|
});
|
|
9360
|
-
var removeCommand = new
|
|
9916
|
+
var removeCommand = new Command10("remove").description("Remove an export declaration").argument("<name>", "Export name to remove").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
9361
9917
|
try {
|
|
9362
9918
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9363
9919
|
if (!flintPath) {
|
|
@@ -9381,7 +9937,7 @@ var removeCommand = new Command11("remove").description("Remove an export declar
|
|
|
9381
9937
|
process.exit(1);
|
|
9382
9938
|
}
|
|
9383
9939
|
});
|
|
9384
|
-
var buildCommand = new
|
|
9940
|
+
var buildCommand = new Command10("build").description("Build exports").argument("[name]", "Name of export to build (omit for all)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--all", "Build all exports").action(async (name, options) => {
|
|
9385
9941
|
try {
|
|
9386
9942
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9387
9943
|
if (!flintPath) {
|
|
@@ -9437,7 +9993,7 @@ var buildCommand = new Command11("build").description("Build exports").argument(
|
|
|
9437
9993
|
process.exit(1);
|
|
9438
9994
|
}
|
|
9439
9995
|
});
|
|
9440
|
-
var statusCommand = new
|
|
9996
|
+
var statusCommand = new Command10("status").description("Show export build status").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
9441
9997
|
try {
|
|
9442
9998
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9443
9999
|
if (!flintPath) {
|
|
@@ -9469,10 +10025,10 @@ var statusCommand = new Command11("status").description("Show export build statu
|
|
|
9469
10025
|
process.exit(1);
|
|
9470
10026
|
}
|
|
9471
10027
|
});
|
|
9472
|
-
var exportCommand = new
|
|
10028
|
+
var exportCommand = new Command10("export").description("Manage exports").addCommand(listCommand2).addCommand(scanCommand).addCommand(addCommand).addCommand(removeCommand).addCommand(buildCommand).addCommand(statusCommand);
|
|
9473
10029
|
|
|
9474
10030
|
// src/commands/import.ts
|
|
9475
|
-
import { Command as
|
|
10031
|
+
import { Command as Command11 } from "commander";
|
|
9476
10032
|
import pc14 from "picocolors";
|
|
9477
10033
|
import { rm as rm9, stat as stat9 } from "fs/promises";
|
|
9478
10034
|
import { join as join26, basename as basename5 } from "path";
|
|
@@ -9516,7 +10072,7 @@ async function exists4(path3) {
|
|
|
9516
10072
|
return false;
|
|
9517
10073
|
}
|
|
9518
10074
|
}
|
|
9519
|
-
var listCommand3 = new
|
|
10075
|
+
var listCommand3 = new Command11("list").description("List available imports from registered flints").argument("[flint]", "Flint name to show exports from").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (flintName, options) => {
|
|
9520
10076
|
try {
|
|
9521
10077
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9522
10078
|
console.log();
|
|
@@ -9583,7 +10139,7 @@ var listCommand3 = new Command12("list").description("List available imports fro
|
|
|
9583
10139
|
process.exit(1);
|
|
9584
10140
|
}
|
|
9585
10141
|
});
|
|
9586
|
-
var addCommand2 = new
|
|
10142
|
+
var addCommand2 = new Command11("add").description("Add an import to flint.toml").argument("<ref>", 'Import reference: "<flint>/<export>"').option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (ref, options) => {
|
|
9587
10143
|
try {
|
|
9588
10144
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9589
10145
|
if (!flintPath) {
|
|
@@ -9651,7 +10207,7 @@ var addCommand2 = new Command12("add").description("Add an import to flint.toml"
|
|
|
9651
10207
|
process.exit(1);
|
|
9652
10208
|
}
|
|
9653
10209
|
});
|
|
9654
|
-
var removeCommand2 = new
|
|
10210
|
+
var removeCommand2 = new Command11("remove").description("Remove an import from flint.toml").argument("<ref>", 'Import to remove: "<flint>/<export>"').option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--delete-files", "Also delete the imported files from Imports/").action(async (ref, options) => {
|
|
9655
10211
|
try {
|
|
9656
10212
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
9657
10213
|
if (!flintPath) {
|
|
@@ -9694,8 +10250,8 @@ var removeCommand2 = new Command12("remove").description("Remove an import from
|
|
|
9694
10250
|
if (deleted) {
|
|
9695
10251
|
const parentPath = join26(flintPath, "Imports", `(Flint) ${flintName}`);
|
|
9696
10252
|
try {
|
|
9697
|
-
const { readdir:
|
|
9698
|
-
const remaining = await
|
|
10253
|
+
const { readdir: readdir11 } = await import("fs/promises");
|
|
10254
|
+
const remaining = await readdir11(parentPath);
|
|
9699
10255
|
if (remaining.length === 0) {
|
|
9700
10256
|
await rm9(parentPath, { recursive: true });
|
|
9701
10257
|
}
|
|
@@ -9710,16 +10266,16 @@ var removeCommand2 = new Command12("remove").description("Remove an import from
|
|
|
9710
10266
|
process.exit(1);
|
|
9711
10267
|
}
|
|
9712
10268
|
});
|
|
9713
|
-
var importCommand = new
|
|
10269
|
+
var importCommand = new Command11("import").description("Manage imports from other flints").addCommand(listCommand3).addCommand(addCommand2).addCommand(removeCommand2);
|
|
9714
10270
|
|
|
9715
10271
|
// src/commands/open.ts
|
|
9716
|
-
import { Command as
|
|
9717
|
-
import { exec as
|
|
10272
|
+
import { Command as Command12 } from "commander";
|
|
10273
|
+
import { exec as exec7 } from "child_process";
|
|
9718
10274
|
import { promisify as promisify8 } from "util";
|
|
9719
10275
|
import { resolve as resolve9 } from "path";
|
|
9720
10276
|
import { platform as platform3 } from "os";
|
|
9721
10277
|
import pc15 from "picocolors";
|
|
9722
|
-
var
|
|
10278
|
+
var execAsync7 = promisify8(exec7);
|
|
9723
10279
|
var APP_NAMES = {
|
|
9724
10280
|
obsidian: {
|
|
9725
10281
|
darwin: "Obsidian",
|
|
@@ -9747,20 +10303,20 @@ async function openInApp(appId, path3) {
|
|
|
9747
10303
|
const appConfig = APP_NAMES[appId.toLowerCase()];
|
|
9748
10304
|
if (os2 === "darwin") {
|
|
9749
10305
|
const appName = appConfig?.darwin ?? appId;
|
|
9750
|
-
await
|
|
10306
|
+
await execAsync7(`open -a "${appName}" "${path3}"`);
|
|
9751
10307
|
} else if (os2 === "win32") {
|
|
9752
10308
|
const appName = appConfig?.win32 ?? appId;
|
|
9753
|
-
await
|
|
10309
|
+
await execAsync7(`start "" "${appName}" "${path3}"`);
|
|
9754
10310
|
} else {
|
|
9755
10311
|
const appName = appConfig?.linux ?? appId.toLowerCase();
|
|
9756
10312
|
try {
|
|
9757
|
-
await
|
|
10313
|
+
await execAsync7(`${appName} "${path3}"`);
|
|
9758
10314
|
} catch {
|
|
9759
|
-
await
|
|
10315
|
+
await execAsync7(`xdg-open "${path3}"`);
|
|
9760
10316
|
}
|
|
9761
10317
|
}
|
|
9762
10318
|
}
|
|
9763
|
-
var openCommand = new
|
|
10319
|
+
var openCommand = new Command12("open").argument("[flint-name]", "Name of the flint to open").description("Open a flint in configured applications").action(async (flintName) => {
|
|
9764
10320
|
try {
|
|
9765
10321
|
let flintPath;
|
|
9766
10322
|
if (flintName) {
|
|
@@ -9817,13 +10373,13 @@ var openCommand = new Command13("open").argument("[flint-name]", "Name of the fl
|
|
|
9817
10373
|
});
|
|
9818
10374
|
|
|
9819
10375
|
// src/commands/agent.ts
|
|
9820
|
-
import { Command as
|
|
10376
|
+
import { Command as Command13 } from "commander";
|
|
9821
10377
|
import pc16 from "picocolors";
|
|
9822
10378
|
import { spawn as spawn4 } from "child_process";
|
|
9823
10379
|
import { join as join27, dirname as dirname7 } from "path";
|
|
9824
10380
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9825
10381
|
var __dirname4 = dirname7(fileURLToPath4(import.meta.url));
|
|
9826
|
-
var agentCommand = new
|
|
10382
|
+
var agentCommand = new Command13("agent").description("Manage Flint agents");
|
|
9827
10383
|
agentCommand.command("start").description("Start an agent session").option("-p, --path <dir>", "Path to flint mesh (default: auto-detect)").option("-b, --backend <type>", "Agent backend: pydantic | claude-code", "pydantic").option("-m, --model <model>", "Model to use (default: openai/gpt-4o-mini)").option("-g, --goal <goal>", "Initial goal for the agent").option("-s, --skill <skill>", "Skill file to execute").option("--dry-run", "Show what would happen without starting agent").action(async (options) => {
|
|
9828
10384
|
try {
|
|
9829
10385
|
const meshPath = options.path || await findFlintRoot(process.cwd());
|
|
@@ -10039,7 +10595,7 @@ async function startClaudeCodeAgent(meshPath, options) {
|
|
|
10039
10595
|
}
|
|
10040
10596
|
|
|
10041
10597
|
// src/commands/register.ts
|
|
10042
|
-
import { Command as
|
|
10598
|
+
import { Command as Command14 } from "commander";
|
|
10043
10599
|
import pc17 from "picocolors";
|
|
10044
10600
|
import { createInterface as createInterface3 } from "readline";
|
|
10045
10601
|
import { resolve as resolve10 } from "path";
|
|
@@ -10074,7 +10630,7 @@ async function promptSelect(flints) {
|
|
|
10074
10630
|
});
|
|
10075
10631
|
});
|
|
10076
10632
|
}
|
|
10077
|
-
var registerCommand = new
|
|
10633
|
+
var registerCommand = new Command14("register").description("Register an existing flint in the global registry").argument("[paths...]", "Paths to flints to register (defaults to current directory)").option("-s, --scan", "Scan for flints in the specified paths (or default locations)").option("-d, --depth <n>", "Max recursion depth for scan (default: 5)", "5").option("--dry-run", "Show what would be registered without doing it").option("-f, --force", "Re-register even if already registered (updates entry)").action(async (pathArgs, options) => {
|
|
10078
10634
|
try {
|
|
10079
10635
|
const depth = parseInt(options.depth, 10) || 5;
|
|
10080
10636
|
if (options.scan) {
|
|
@@ -10199,10 +10755,10 @@ var registerCommand = new Command15("register").description("Register an existin
|
|
|
10199
10755
|
});
|
|
10200
10756
|
|
|
10201
10757
|
// src/commands/unregister.ts
|
|
10202
|
-
import { Command as
|
|
10758
|
+
import { Command as Command15 } from "commander";
|
|
10203
10759
|
import pc18 from "picocolors";
|
|
10204
10760
|
import { resolve as resolve11 } from "path";
|
|
10205
|
-
var unregisterCommand = new
|
|
10761
|
+
var unregisterCommand = new Command15("unregister").description("Unregister a flint from the global registry").argument("[path]", "Path to the flint (defaults to current directory)").option("-f, --force", "Skip confirmation prompt").action(async (pathArg, options) => {
|
|
10206
10762
|
try {
|
|
10207
10763
|
let targetPath;
|
|
10208
10764
|
if (pathArg) {
|
|
@@ -10248,9 +10804,9 @@ Flint to unregister:`);
|
|
|
10248
10804
|
});
|
|
10249
10805
|
|
|
10250
10806
|
// src/commands/registry.ts
|
|
10251
|
-
import { Command as
|
|
10807
|
+
import { Command as Command16 } from "commander";
|
|
10252
10808
|
import pc19 from "picocolors";
|
|
10253
|
-
var validateCommand = new
|
|
10809
|
+
var validateCommand = new Command16("validate").description("Validate registry and remove broken entries").option("--dry-run", "Check only, do not remove broken entries").option("--json", "Output as JSON").option("-f, --force", "Skip confirmation prompt when removing entries").action(async (options) => {
|
|
10254
10810
|
try {
|
|
10255
10811
|
const cleanResult = await cleanRegistryFile();
|
|
10256
10812
|
const flintEntries = await getFlintRegistry();
|
|
@@ -10352,7 +10908,7 @@ ${pc19.bold("Registry Validation")}
|
|
|
10352
10908
|
process.exit(1);
|
|
10353
10909
|
}
|
|
10354
10910
|
});
|
|
10355
|
-
var tagCommand = new
|
|
10911
|
+
var tagCommand = new Command16("tag").description("Add a tag to a registered flint").argument("<name>", "Flint name").argument("<tag>", "Tag to add").action(async (name, tag) => {
|
|
10356
10912
|
try {
|
|
10357
10913
|
const flint = await findFlintByName(name);
|
|
10358
10914
|
if (!flint) {
|
|
@@ -10373,7 +10929,7 @@ var tagCommand = new Command17("tag").description("Add a tag to a registered fli
|
|
|
10373
10929
|
process.exit(1);
|
|
10374
10930
|
}
|
|
10375
10931
|
});
|
|
10376
|
-
var untagCommand = new
|
|
10932
|
+
var untagCommand = new Command16("untag").description("Remove a tag from a registered flint").argument("<name>", "Flint name").argument("<tag>", "Tag to remove").action(async (name, tag) => {
|
|
10377
10933
|
try {
|
|
10378
10934
|
const flint = await findFlintByName(name);
|
|
10379
10935
|
if (!flint) {
|
|
@@ -10393,16 +10949,16 @@ var untagCommand = new Command17("untag").description("Remove a tag from a regis
|
|
|
10393
10949
|
process.exit(1);
|
|
10394
10950
|
}
|
|
10395
10951
|
});
|
|
10396
|
-
var registryCommand = new
|
|
10952
|
+
var registryCommand = new Command16("registry").description("Manage the flint registry").addCommand(validateCommand).addCommand(tagCommand).addCommand(untagCommand);
|
|
10397
10953
|
|
|
10398
10954
|
// src/commands/obsidian.ts
|
|
10399
|
-
import { Command as
|
|
10955
|
+
import { Command as Command17 } from "commander";
|
|
10400
10956
|
import pc20 from "picocolors";
|
|
10401
|
-
import { execSync as
|
|
10957
|
+
import { execSync as execSync3, spawnSync } from "child_process";
|
|
10402
10958
|
import { join as join28 } from "path";
|
|
10403
10959
|
import { stat as stat10, rm as rm10 } from "fs/promises";
|
|
10404
10960
|
var OBSIDIAN_REPO_URL2 = "https://github.com/NUU-Cognition/flint-dot-obsidian.git";
|
|
10405
|
-
var obsidianCommand = new
|
|
10961
|
+
var obsidianCommand = new Command17("obsidian").description("Manage .obsidian configuration").option("-p, --path <dir>", "Path to flint (default: auto-detect)");
|
|
10406
10962
|
obsidianCommand.command("update").description("Force pull latest .obsidian from remote (discards local changes)").action(async () => {
|
|
10407
10963
|
const options = obsidianCommand.opts();
|
|
10408
10964
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
@@ -10420,8 +10976,8 @@ obsidianCommand.command("update").description("Force pull latest .obsidian from
|
|
|
10420
10976
|
}
|
|
10421
10977
|
console.log(pc20.dim("Fetching latest from remote..."));
|
|
10422
10978
|
try {
|
|
10423
|
-
|
|
10424
|
-
|
|
10979
|
+
execSync3("git fetch origin", { cwd: obsidianDir, stdio: "pipe" });
|
|
10980
|
+
execSync3("git reset --hard origin/main", { cwd: obsidianDir, stdio: "pipe" });
|
|
10425
10981
|
console.log(pc20.green("Updated .obsidian to latest from remote."));
|
|
10426
10982
|
} catch (err) {
|
|
10427
10983
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -10446,17 +11002,19 @@ if (isFeatureEnabled(FEATURES, "obsidian.push", resolveRuntimeSync({ cliname: "f
|
|
|
10446
11002
|
}
|
|
10447
11003
|
console.log(pc20.dim("Staging changes..."));
|
|
10448
11004
|
try {
|
|
10449
|
-
|
|
10450
|
-
const status =
|
|
11005
|
+
execSync3("git add -A", { cwd: obsidianDir, stdio: "pipe" });
|
|
11006
|
+
const status = execSync3("git status --porcelain", { cwd: obsidianDir, encoding: "utf-8" });
|
|
10451
11007
|
if (!status.trim()) {
|
|
10452
11008
|
console.log(pc20.yellow("No changes to commit."));
|
|
10453
11009
|
return;
|
|
10454
11010
|
}
|
|
10455
11011
|
console.log(pc20.dim("Committing..."));
|
|
10456
|
-
const
|
|
10457
|
-
|
|
11012
|
+
const commitResult = spawnSync("git", ["commit", "-m", cmdOptions.message], { cwd: obsidianDir, stdio: "pipe" });
|
|
11013
|
+
if (commitResult.status !== 0) {
|
|
11014
|
+
throw new Error(commitResult.stderr?.toString() || "git commit failed");
|
|
11015
|
+
}
|
|
10458
11016
|
console.log(pc20.dim("Pushing to remote..."));
|
|
10459
|
-
|
|
11017
|
+
execSync3("git push origin main", { cwd: obsidianDir, stdio: "pipe" });
|
|
10460
11018
|
console.log(pc20.green("Pushed .obsidian changes to remote."));
|
|
10461
11019
|
} catch (err) {
|
|
10462
11020
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -10491,7 +11049,7 @@ obsidianCommand.command("reset").description("Delete and re-clone .obsidian from
|
|
|
10491
11049
|
await rm10(obsidianDir, { recursive: true, force: true });
|
|
10492
11050
|
}
|
|
10493
11051
|
console.log(pc20.dim("Cloning .obsidian from template repo..."));
|
|
10494
|
-
|
|
11052
|
+
execSync3(`git clone ${OBSIDIAN_REPO_URL2} "${obsidianDir}"`, { stdio: "pipe" });
|
|
10495
11053
|
console.log(pc20.green("Reset .obsidian to fresh state from template repo."));
|
|
10496
11054
|
} catch (err) {
|
|
10497
11055
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -10501,10 +11059,10 @@ obsidianCommand.command("reset").description("Delete and re-clone .obsidian from
|
|
|
10501
11059
|
});
|
|
10502
11060
|
|
|
10503
11061
|
// src/commands/config.ts
|
|
10504
|
-
import { Command as
|
|
11062
|
+
import { Command as Command18 } from "commander";
|
|
10505
11063
|
import pc21 from "picocolors";
|
|
10506
11064
|
var CONFIG_PATH = getConfigPath("flint");
|
|
10507
|
-
var configCommand = new
|
|
11065
|
+
var configCommand = new Command18("config").description("Manage global Flint configuration").argument("[action]", "Action: get, set, or omit to view all").argument("[key]", "Config key (e.g., open.apps)").argument("[value]", "Value to set (JSON for arrays/objects)").action(async (action, key, value) => {
|
|
10508
11066
|
try {
|
|
10509
11067
|
const config = resolveConfigSync({ cliname: "flint" });
|
|
10510
11068
|
if (!action) {
|
|
@@ -10600,10 +11158,10 @@ function getNestedValue(obj, key) {
|
|
|
10600
11158
|
}
|
|
10601
11159
|
|
|
10602
11160
|
// src/commands/connection.ts
|
|
10603
|
-
import { Command as
|
|
11161
|
+
import { Command as Command19 } from "commander";
|
|
10604
11162
|
import pc22 from "picocolors";
|
|
10605
|
-
var connectionCommand = new
|
|
10606
|
-
new
|
|
11163
|
+
var connectionCommand = new Command19("connection").description("Manage connections to other Flints").addCommand(
|
|
11164
|
+
new Command19("add").description("Add a connection to another Flint (must be registered)").argument("<name>", "Name of the registered Flint to connect").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--no-fulfill", "Only add declaration, do not auto-fulfill").action(async (targetName, options) => {
|
|
10607
11165
|
try {
|
|
10608
11166
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10609
11167
|
if (!flintPath) {
|
|
@@ -10631,7 +11189,7 @@ Added connection to ${pc22.bold(status.name)}`));
|
|
|
10631
11189
|
}
|
|
10632
11190
|
})
|
|
10633
11191
|
).addCommand(
|
|
10634
|
-
new
|
|
11192
|
+
new Command19("remove").description("Remove a connection").argument("<name>", "Name of the connected Flint to remove").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
10635
11193
|
try {
|
|
10636
11194
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10637
11195
|
if (!flintPath) {
|
|
@@ -10657,7 +11215,7 @@ Connection "${name}" not found`));
|
|
|
10657
11215
|
}
|
|
10658
11216
|
})
|
|
10659
11217
|
).addCommand(
|
|
10660
|
-
new
|
|
11218
|
+
new Command19("list").description("List all connections with status").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
10661
11219
|
try {
|
|
10662
11220
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10663
11221
|
if (!flintPath) {
|
|
@@ -10707,7 +11265,7 @@ Connection "${name}" not found`));
|
|
|
10707
11265
|
}
|
|
10708
11266
|
})
|
|
10709
11267
|
).addCommand(
|
|
10710
|
-
new
|
|
11268
|
+
new Command19("fulfill").description("Fulfill a connection by setting its local path").argument("[name]", "Name of the connection to fulfill").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--all", "Fulfill all unfulfilled connections interactively").option("--target <path>", "Path to the target Flint (auto-lookup from registry if omitted)").action(async (name, options) => {
|
|
10711
11269
|
try {
|
|
10712
11270
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10713
11271
|
if (!flintPath) {
|
|
@@ -10769,7 +11327,7 @@ Fulfilled connection to ${pc22.bold(fulfillment.name)}`));
|
|
|
10769
11327
|
}
|
|
10770
11328
|
})
|
|
10771
11329
|
).addCommand(
|
|
10772
|
-
new
|
|
11330
|
+
new Command19("status").description("Check connection status").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
10773
11331
|
try {
|
|
10774
11332
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10775
11333
|
if (!flintPath) {
|
|
@@ -10817,7 +11375,7 @@ Fulfilled connection to ${pc22.bold(fulfillment.name)}`));
|
|
|
10817
11375
|
);
|
|
10818
11376
|
|
|
10819
11377
|
// src/commands/workspace.ts
|
|
10820
|
-
import { Command as
|
|
11378
|
+
import { Command as Command20 } from "commander";
|
|
10821
11379
|
import pc23 from "picocolors";
|
|
10822
11380
|
import { stat as stat11 } from "fs/promises";
|
|
10823
11381
|
import * as readline from "readline";
|
|
@@ -10841,8 +11399,8 @@ async function pathExists2(path3) {
|
|
|
10841
11399
|
return false;
|
|
10842
11400
|
}
|
|
10843
11401
|
}
|
|
10844
|
-
var workspaceCommand = new
|
|
10845
|
-
new
|
|
11402
|
+
var workspaceCommand = new Command20("workspace").description("Manage workspace references to external resources").addCommand(
|
|
11403
|
+
new Command20("list").description("List workspace references").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
10846
11404
|
try {
|
|
10847
11405
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10848
11406
|
if (!flintPath) {
|
|
@@ -10889,7 +11447,7 @@ var workspaceCommand = new Command21("workspace").description("Manage workspace
|
|
|
10889
11447
|
}
|
|
10890
11448
|
})
|
|
10891
11449
|
).addCommand(
|
|
10892
|
-
new
|
|
11450
|
+
new Command20("reference").description("Declare a workspace reference and optionally set its local path").argument("<name>", "Name for this workspace reference").argument("[targetPath]", "Path to the external resource (optional)").option("-t, --type <type>", "Type of reference (codebase, drive, api, database, service)", "codebase").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, targetPath, options) => {
|
|
10893
11451
|
try {
|
|
10894
11452
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10895
11453
|
if (!flintPath) {
|
|
@@ -10928,7 +11486,7 @@ Declared workspace reference: ${pc23.bold(name)}`));
|
|
|
10928
11486
|
}
|
|
10929
11487
|
})
|
|
10930
11488
|
).addCommand(
|
|
10931
|
-
new
|
|
11489
|
+
new Command20("fulfill").description("Provide local paths for unfulfilled workspace references").argument("[name]", "Specific reference to fulfill (or all if omitted)").argument("[targetPath]", "Path to the resource (skips prompt if provided)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, targetPath, options) => {
|
|
10932
11490
|
try {
|
|
10933
11491
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
10934
11492
|
if (!flintPath) {
|
|
@@ -11011,7 +11569,7 @@ Workspace "${name}" is already fulfilled.`));
|
|
|
11011
11569
|
}
|
|
11012
11570
|
})
|
|
11013
11571
|
).addCommand(
|
|
11014
|
-
new
|
|
11572
|
+
new Command20("remove").description("Remove a workspace reference").argument("<name>", "Name of the workspace reference to remove").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
11015
11573
|
try {
|
|
11016
11574
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11017
11575
|
if (!flintPath) {
|
|
@@ -11039,7 +11597,7 @@ Removed workspace reference: ${pc23.bold(name)}`));
|
|
|
11039
11597
|
}
|
|
11040
11598
|
})
|
|
11041
11599
|
).addCommand(
|
|
11042
|
-
new
|
|
11600
|
+
new Command20("addrepo").description("Clone a full git repository into Workspace/Repositories/").argument("<name>", "Name for this repository").argument("<url>", "Git URL to clone").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, url, options) => {
|
|
11043
11601
|
try {
|
|
11044
11602
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11045
11603
|
if (!flintPath) {
|
|
@@ -11066,7 +11624,7 @@ Added repository: ${pc23.bold(name)}`));
|
|
|
11066
11624
|
}
|
|
11067
11625
|
})
|
|
11068
11626
|
).addCommand(
|
|
11069
|
-
new
|
|
11627
|
+
new Command20("createrepo").description("Create a new git repository in Workspace/Repositories/ with a remote origin").argument("<name>", "Name for this repository").argument("<url>", "Git remote URL to set as origin").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, url, options) => {
|
|
11070
11628
|
try {
|
|
11071
11629
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11072
11630
|
if (!flintPath) {
|
|
@@ -11093,7 +11651,7 @@ Created repository: ${pc23.bold(name)}`));
|
|
|
11093
11651
|
}
|
|
11094
11652
|
})
|
|
11095
11653
|
).addCommand(
|
|
11096
|
-
new
|
|
11654
|
+
new Command20("removerepo").description("Remove a cloned repository").argument("<name>", "Name of the repository to remove").option("-f, --force", "Skip confirmation prompt").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
11097
11655
|
try {
|
|
11098
11656
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11099
11657
|
if (!flintPath) {
|
|
@@ -11129,7 +11687,7 @@ Removed repository: ${pc23.bold(name)}`));
|
|
|
11129
11687
|
}
|
|
11130
11688
|
})
|
|
11131
11689
|
).addCommand(
|
|
11132
|
-
new
|
|
11690
|
+
new Command20("updaterepo").description("Pull latest changes for a repository (or fresh clone with --fresh)").argument("<name>", "Name of the repository to update").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--fresh", "Delete and re-clone instead of pulling").action(async (name, options) => {
|
|
11133
11691
|
try {
|
|
11134
11692
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11135
11693
|
if (!flintPath) {
|
|
@@ -11160,7 +11718,7 @@ Updated repository: ${pc23.bold(name)}`));
|
|
|
11160
11718
|
}
|
|
11161
11719
|
})
|
|
11162
11720
|
).addCommand(
|
|
11163
|
-
new
|
|
11721
|
+
new Command20("listrepo").description("List cloned repositories").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
11164
11722
|
try {
|
|
11165
11723
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11166
11724
|
if (!flintPath) {
|
|
@@ -11205,7 +11763,7 @@ Updated repository: ${pc23.bold(name)}`));
|
|
|
11205
11763
|
}
|
|
11206
11764
|
})
|
|
11207
11765
|
).addCommand(
|
|
11208
|
-
new
|
|
11766
|
+
new Command20("addreferencerepo").description("Clone a reference copy of a git repository into Workspace/Sources/Repositories/").argument("<name>", "Name for this source repository").argument("<url>", "Git URL to clone").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, url, options) => {
|
|
11209
11767
|
try {
|
|
11210
11768
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11211
11769
|
if (!flintPath) {
|
|
@@ -11233,7 +11791,7 @@ Added reference repository: ${pc23.bold(name)}`));
|
|
|
11233
11791
|
}
|
|
11234
11792
|
})
|
|
11235
11793
|
).addCommand(
|
|
11236
|
-
new
|
|
11794
|
+
new Command20("removereferencerepo").description("Remove a reference repository").argument("<name>", "Name of the reference repository to remove").option("-f, --force", "Skip confirmation prompt").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
11237
11795
|
try {
|
|
11238
11796
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11239
11797
|
if (!flintPath) {
|
|
@@ -11269,7 +11827,7 @@ Removed reference repository: ${pc23.bold(name)}`));
|
|
|
11269
11827
|
}
|
|
11270
11828
|
})
|
|
11271
11829
|
).addCommand(
|
|
11272
|
-
new
|
|
11830
|
+
new Command20("updatereferencerepo").description("Re-fetch a reference repository (delete and re-clone)").argument("<name>", "Name of the reference repository to update").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (name, options) => {
|
|
11273
11831
|
try {
|
|
11274
11832
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11275
11833
|
if (!flintPath) {
|
|
@@ -11300,7 +11858,7 @@ Updated reference repository: ${pc23.bold(name)}`));
|
|
|
11300
11858
|
}
|
|
11301
11859
|
})
|
|
11302
11860
|
).addCommand(
|
|
11303
|
-
new
|
|
11861
|
+
new Command20("listreferencerepo").description("List reference repositories").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
11304
11862
|
try {
|
|
11305
11863
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11306
11864
|
if (!flintPath) {
|
|
@@ -11347,7 +11905,7 @@ Updated reference repository: ${pc23.bold(name)}`));
|
|
|
11347
11905
|
);
|
|
11348
11906
|
|
|
11349
11907
|
// src/commands/subflint.ts
|
|
11350
|
-
import { Command as
|
|
11908
|
+
import { Command as Command21 } from "commander";
|
|
11351
11909
|
import pc24 from "picocolors";
|
|
11352
11910
|
import * as readline2 from "readline";
|
|
11353
11911
|
import { spawn as spawn5 } from "child_process";
|
|
@@ -11393,7 +11951,7 @@ async function resolveParentFlintPath(pathOverride) {
|
|
|
11393
11951
|
}
|
|
11394
11952
|
return getParentFlintPath(detected) ?? detected;
|
|
11395
11953
|
}
|
|
11396
|
-
var subflintCommand = new
|
|
11954
|
+
var subflintCommand = new Command21("subflint").description("Manage subflints (nested unregistered Flints)").argument("[name]", "Subflint name (wrapper mode)").argument("[command...]", "Command to run inside the subflint").option("-p, --path <dir>", "Path to parent flint (default: auto-detect)").allowUnknownOption(true).action(async (name, command, options, commandInstance) => {
|
|
11397
11955
|
if (!name || command.length === 0) {
|
|
11398
11956
|
commandInstance.help();
|
|
11399
11957
|
return;
|
|
@@ -11435,7 +11993,7 @@ var subflintCommand = new Command22("subflint").description("Manage subflints (n
|
|
|
11435
11993
|
process.exit(code ?? 1);
|
|
11436
11994
|
});
|
|
11437
11995
|
}).addCommand(
|
|
11438
|
-
new
|
|
11996
|
+
new Command21("create").description("Create a new subflint").argument("<name>", "Name of the subflint").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--preset <preset>", "Preset to use (e.g., blank, vessel, spec)", "blank").option("-d, --description <desc>", "Description for the subflint").action(async (name, options) => {
|
|
11439
11997
|
try {
|
|
11440
11998
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11441
11999
|
if (!flintPath) {
|
|
@@ -11510,7 +12068,7 @@ Subflint created at: ${pc24.cyan(abbreviatePath(entry.path))}`);
|
|
|
11510
12068
|
}
|
|
11511
12069
|
})
|
|
11512
12070
|
).addCommand(
|
|
11513
|
-
new
|
|
12071
|
+
new Command21("list").description("List all subflints").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
11514
12072
|
try {
|
|
11515
12073
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11516
12074
|
if (!flintPath) {
|
|
@@ -11544,7 +12102,7 @@ Subflint created at: ${pc24.cyan(abbreviatePath(entry.path))}`);
|
|
|
11544
12102
|
}
|
|
11545
12103
|
})
|
|
11546
12104
|
).addCommand(
|
|
11547
|
-
new
|
|
12105
|
+
new Command21("sync").description("Discover subflints and report status").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
11548
12106
|
try {
|
|
11549
12107
|
const flintPath = await resolveParentFlintPath(options.path);
|
|
11550
12108
|
if (!flintPath) {
|
|
@@ -11573,7 +12131,7 @@ Discovered ${subflints.length} subflint(s):
|
|
|
11573
12131
|
}
|
|
11574
12132
|
})
|
|
11575
12133
|
).addCommand(
|
|
11576
|
-
new
|
|
12134
|
+
new Command21("remove").description("Remove a subflint").argument("<name>", "Name of the subflint to remove").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-y, --yes", "Skip confirmation").action(async (name, options) => {
|
|
11577
12135
|
try {
|
|
11578
12136
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11579
12137
|
if (!flintPath) {
|
|
@@ -11609,7 +12167,7 @@ Removed subflint ${pc24.bold(removed.name)}`));
|
|
|
11609
12167
|
}
|
|
11610
12168
|
})
|
|
11611
12169
|
).addCommand(
|
|
11612
|
-
new
|
|
12170
|
+
new Command21("promote").description("Promote a subflint to a registered Flint").argument("<name>", "Name of the subflint to promote").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("-t, --to <destination>", "Destination path for the promoted Flint").option("-d, --dest <destination>", "Alias for --to").action(async (name, options) => {
|
|
11613
12171
|
try {
|
|
11614
12172
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
11615
12173
|
if (!flintPath) {
|
|
@@ -11658,7 +12216,7 @@ Promoted ${pc24.bold(name)} to registered Flint`));
|
|
|
11658
12216
|
);
|
|
11659
12217
|
|
|
11660
12218
|
// src/commands/lattice.ts
|
|
11661
|
-
import { Command as
|
|
12219
|
+
import { Command as Command22 } from "commander";
|
|
11662
12220
|
import pc25 from "picocolors";
|
|
11663
12221
|
|
|
11664
12222
|
// ../../packages/lattice/src/paths.ts
|
|
@@ -11695,7 +12253,7 @@ function resolveLatticePaths(latticePath, config) {
|
|
|
11695
12253
|
}
|
|
11696
12254
|
|
|
11697
12255
|
// ../../packages/lattice/src/config.ts
|
|
11698
|
-
import { readFile as
|
|
12256
|
+
import { readFile as readFile11, writeFile as writeFile8, stat as stat12 } from "fs/promises";
|
|
11699
12257
|
|
|
11700
12258
|
// ../../packages/lattice/src/utils.ts
|
|
11701
12259
|
function toSlug(name) {
|
|
@@ -11716,7 +12274,7 @@ function toMeshFileName(latticeName, exportName, fileName) {
|
|
|
11716
12274
|
async function readLatticeToml(latticePath) {
|
|
11717
12275
|
const configPath = getLatticeConfigPath(latticePath);
|
|
11718
12276
|
try {
|
|
11719
|
-
const content = await
|
|
12277
|
+
const content = await readFile11(configPath, "utf-8");
|
|
11720
12278
|
return parse(content);
|
|
11721
12279
|
} catch (error3) {
|
|
11722
12280
|
if (error3.code === "ENOENT") {
|
|
@@ -11913,7 +12471,7 @@ async function runExport(latticePath, config, exportType) {
|
|
|
11913
12471
|
}
|
|
11914
12472
|
|
|
11915
12473
|
// ../../packages/lattice/src/sync.ts
|
|
11916
|
-
import { mkdir as mkdir14, stat as stat14, writeFile as writeFile9, rm as rm11, readdir as
|
|
12474
|
+
import { mkdir as mkdir14, stat as stat14, writeFile as writeFile9, rm as rm11, readdir as readdir10, copyFile as copyFile3 } from "fs/promises";
|
|
11917
12475
|
import { join as join30 } from "path";
|
|
11918
12476
|
async function fileExists3(path3) {
|
|
11919
12477
|
try {
|
|
@@ -12067,7 +12625,7 @@ async function syncLatticeToMesh(latticePath, meshLatticeBase) {
|
|
|
12067
12625
|
async function copyExportsToMesh(sourceDir, targetDir, latticeName, exportName, meshFiles) {
|
|
12068
12626
|
let entries;
|
|
12069
12627
|
try {
|
|
12070
|
-
entries = await
|
|
12628
|
+
entries = await readdir10(sourceDir, { withFileTypes: true });
|
|
12071
12629
|
} catch {
|
|
12072
12630
|
return;
|
|
12073
12631
|
}
|
|
@@ -12103,8 +12661,8 @@ async function resolveFlintPath(pathOption) {
|
|
|
12103
12661
|
}
|
|
12104
12662
|
return flintPath;
|
|
12105
12663
|
}
|
|
12106
|
-
var latticeCommand = new
|
|
12107
|
-
new
|
|
12664
|
+
var latticeCommand = new Command22("lattice").description("Manage lattices configured in flint.toml").option("-p, --path <dir>", "Path to flint (default: auto-detect)").addCommand(
|
|
12665
|
+
new Command22("list").description("List lattices configured in flint.toml").action(async function() {
|
|
12108
12666
|
const options = this.parent?.opts();
|
|
12109
12667
|
const flintPath = await resolveFlintPath(options?.path);
|
|
12110
12668
|
const config = await readFlintToml(flintPath);
|
|
@@ -12120,7 +12678,7 @@ var latticeCommand = new Command23("lattice").description("Manage lattices confi
|
|
|
12120
12678
|
}
|
|
12121
12679
|
})
|
|
12122
12680
|
).addCommand(
|
|
12123
|
-
new
|
|
12681
|
+
new Command22("sync").description("Sync lattice exports to Mesh/Lattice/").argument("[name]", "Lattice name").option("--all", "Sync all lattices").action(async function(name, options) {
|
|
12124
12682
|
const parentOptions = this.parent?.opts();
|
|
12125
12683
|
const flintPath = await resolveFlintPath(parentOptions?.path);
|
|
12126
12684
|
const config = await readFlintToml(flintPath);
|
|
@@ -12170,7 +12728,7 @@ var latticeCommand = new Command23("lattice").description("Manage lattices confi
|
|
|
12170
12728
|
}
|
|
12171
12729
|
})
|
|
12172
12730
|
).addCommand(
|
|
12173
|
-
new
|
|
12731
|
+
new Command22("status").description("Check lattice connection status").argument("[name]", "Lattice name").option("--all", "Check all lattices").action(async function(name, options) {
|
|
12174
12732
|
const parentOptions = this.parent?.opts();
|
|
12175
12733
|
const flintPath = await resolveFlintPath(parentOptions?.path);
|
|
12176
12734
|
const config = await readFlintToml(flintPath);
|
|
@@ -12214,9 +12772,9 @@ var latticeCommand = new Command23("lattice").description("Manage lattices confi
|
|
|
12214
12772
|
);
|
|
12215
12773
|
|
|
12216
12774
|
// src/commands/server.ts
|
|
12217
|
-
import { Command as
|
|
12775
|
+
import { Command as Command23 } from "commander";
|
|
12218
12776
|
import pc26 from "picocolors";
|
|
12219
|
-
var serverCommand = new
|
|
12777
|
+
var serverCommand = new Command23("server").description("Manage the local Flint server");
|
|
12220
12778
|
serverCommand.command("start").description("Start the Flint server").option("-p, --port <port>", "Port to bind", "7433").option("--host <host>", "Host to bind", "127.0.0.1").action(async (options) => {
|
|
12221
12779
|
const port = Number(options.port);
|
|
12222
12780
|
const host = options.host;
|
|
@@ -12285,10 +12843,10 @@ serverCommand.command("stop").description("Stop the Flint server").option("--ser
|
|
|
12285
12843
|
});
|
|
12286
12844
|
|
|
12287
12845
|
// src/commands/runtime.ts
|
|
12288
|
-
import { Command as
|
|
12846
|
+
import { Command as Command24 } from "commander";
|
|
12289
12847
|
import pc27 from "picocolors";
|
|
12290
12848
|
import path2 from "path";
|
|
12291
|
-
var runtimeCommand = new
|
|
12849
|
+
var runtimeCommand = new Command24("runtime").description("Manage Flint runtimes");
|
|
12292
12850
|
runtimeCommand.command("start [flintPath]").description("Start runtime for a Flint").option("--server <url>", "Server URL", "http://127.0.0.1:7433").action(async (flintPath, options) => {
|
|
12293
12851
|
const serverUrl = options.server;
|
|
12294
12852
|
const resolvedPath = flintPath ? path2.resolve(flintPath) : await findFlintRoot(process.cwd());
|
|
@@ -12382,41 +12940,69 @@ ${pc27.bold("Active Runtimes")}
|
|
|
12382
12940
|
});
|
|
12383
12941
|
|
|
12384
12942
|
// src/commands/code.ts
|
|
12385
|
-
import { Command as
|
|
12943
|
+
import { Command as Command25 } from "commander";
|
|
12386
12944
|
import pc28 from "picocolors";
|
|
12387
12945
|
import { spawn as spawn7 } from "child_process";
|
|
12388
12946
|
import { createInterface as createInterface6 } from "readline";
|
|
12947
|
+
import { existsSync as existsSync5 } from "fs";
|
|
12389
12948
|
var CLIENT_INFO = {
|
|
12390
12949
|
name: "flint_code",
|
|
12391
12950
|
title: "Flint Code",
|
|
12392
12951
|
version: "0.1.0"
|
|
12393
12952
|
};
|
|
12394
|
-
async function
|
|
12953
|
+
async function bootstrapCodexSession(cwd, initPrompt) {
|
|
12395
12954
|
return new Promise((resolve16, reject) => {
|
|
12396
12955
|
const proc = spawn7("codex", ["app-server"], {
|
|
12397
|
-
stdio: ["pipe", "pipe", "
|
|
12956
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
12398
12957
|
cwd
|
|
12399
12958
|
});
|
|
12400
12959
|
const rl = createInterface6({ input: proc.stdout });
|
|
12401
12960
|
const send = (msg) => proc.stdin.write(`${JSON.stringify(msg)}
|
|
12402
12961
|
`);
|
|
12403
|
-
let
|
|
12962
|
+
let threadId = null;
|
|
12963
|
+
let sessionPath = null;
|
|
12404
12964
|
const timeout = setTimeout(() => {
|
|
12405
12965
|
proc.kill();
|
|
12406
|
-
reject(new Error("Timeout waiting for Codex
|
|
12966
|
+
reject(new Error("Timeout waiting for Codex session"));
|
|
12407
12967
|
}, 3e4);
|
|
12968
|
+
const cleanup = () => {
|
|
12969
|
+
clearTimeout(timeout);
|
|
12970
|
+
rl.close();
|
|
12971
|
+
};
|
|
12972
|
+
let pollInterval = null;
|
|
12973
|
+
const startPolling = () => {
|
|
12974
|
+
pollInterval = setInterval(() => {
|
|
12975
|
+
if (sessionPath && existsSync5(sessionPath)) {
|
|
12976
|
+
if (pollInterval) clearInterval(pollInterval);
|
|
12977
|
+
send({ method: "turn/interrupt", id: 4, params: { threadId } });
|
|
12978
|
+
setTimeout(() => {
|
|
12979
|
+
cleanup();
|
|
12980
|
+
proc.kill();
|
|
12981
|
+
resolve16(threadId);
|
|
12982
|
+
}, 500);
|
|
12983
|
+
}
|
|
12984
|
+
}, 200);
|
|
12985
|
+
};
|
|
12408
12986
|
rl.on("line", (line) => {
|
|
12409
12987
|
try {
|
|
12410
12988
|
const msg = JSON.parse(line);
|
|
12411
12989
|
if (msg.id === 2 && msg.result?.thread?.id) {
|
|
12412
|
-
|
|
12413
|
-
|
|
12414
|
-
|
|
12415
|
-
|
|
12990
|
+
threadId = msg.result.thread.id;
|
|
12991
|
+
sessionPath = msg.result.thread.path;
|
|
12992
|
+
send({
|
|
12993
|
+
method: "turn/start",
|
|
12994
|
+
id: 3,
|
|
12995
|
+
params: {
|
|
12996
|
+
threadId,
|
|
12997
|
+
input: [{ type: "text", text: initPrompt }]
|
|
12998
|
+
}
|
|
12999
|
+
});
|
|
13000
|
+
}
|
|
13001
|
+
if (msg.id === 3 && msg.result?.turn) {
|
|
13002
|
+
startPolling();
|
|
12416
13003
|
}
|
|
12417
|
-
if (msg.error && msg.id <=
|
|
12418
|
-
|
|
12419
|
-
rl.close();
|
|
13004
|
+
if (msg.error && msg.id <= 3) {
|
|
13005
|
+
cleanup();
|
|
12420
13006
|
proc.kill();
|
|
12421
13007
|
reject(new Error(msg.error.message));
|
|
12422
13008
|
}
|
|
@@ -12424,19 +13010,15 @@ async function getCodexThreadId(cwd) {
|
|
|
12424
13010
|
}
|
|
12425
13011
|
});
|
|
12426
13012
|
proc.on("error", (err) => {
|
|
12427
|
-
|
|
13013
|
+
cleanup();
|
|
12428
13014
|
reject(err);
|
|
12429
13015
|
});
|
|
12430
|
-
send({ method: "initialize", id:
|
|
13016
|
+
send({ method: "initialize", id: 0, params: { clientInfo: CLIENT_INFO } });
|
|
12431
13017
|
send({ method: "initialized", params: {} });
|
|
12432
|
-
send({
|
|
12433
|
-
method: "thread/start",
|
|
12434
|
-
id: 2,
|
|
12435
|
-
params: { cwd }
|
|
12436
|
-
});
|
|
13018
|
+
send({ method: "thread/start", id: 2, params: { cwd } });
|
|
12437
13019
|
});
|
|
12438
13020
|
}
|
|
12439
|
-
var codeCommand = new
|
|
13021
|
+
var codeCommand = new Command25("code").description("Launch AI coding agents in the current flint");
|
|
12440
13022
|
codeCommand.command("claude").description("Open Claude Code TUI").option("-p, --path <dir>", "Path to flint (default: auto-detect)").action(async (options) => {
|
|
12441
13023
|
try {
|
|
12442
13024
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
@@ -12483,10 +13065,11 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
|
|
|
12483
13065
|
);
|
|
12484
13066
|
process.exit(1);
|
|
12485
13067
|
}
|
|
13068
|
+
const bootstrapPrompt = "init, you are a codex session, please read init-f.md and (System) Flint Init.md";
|
|
12486
13069
|
console.log(pc28.dim("Starting Codex session..."));
|
|
12487
13070
|
let threadId;
|
|
12488
13071
|
try {
|
|
12489
|
-
threadId = await
|
|
13072
|
+
threadId = await bootstrapCodexSession(flintPath, bootstrapPrompt);
|
|
12490
13073
|
} catch (err) {
|
|
12491
13074
|
if (err.code === "ENOENT") {
|
|
12492
13075
|
console.error(pc28.red("Error: Codex is not installed."));
|
|
@@ -12499,13 +13082,14 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
|
|
|
12499
13082
|
}
|
|
12500
13083
|
console.log(pc28.green(`Session ID: ${threadId}`));
|
|
12501
13084
|
console.log("");
|
|
12502
|
-
const
|
|
13085
|
+
const resumePrompt = `your session id is ${threadId}`;
|
|
12503
13086
|
const child = spawn7("codex", [
|
|
12504
13087
|
"resume",
|
|
12505
13088
|
threadId,
|
|
12506
13089
|
"-a",
|
|
12507
13090
|
"never",
|
|
12508
|
-
|
|
13091
|
+
"--full-auto",
|
|
13092
|
+
resumePrompt
|
|
12509
13093
|
], {
|
|
12510
13094
|
cwd: flintPath,
|
|
12511
13095
|
stdio: "inherit"
|
|
@@ -12525,9 +13109,9 @@ codeCommand.command("codex").description("Open Codex TUI with session tracking")
|
|
|
12525
13109
|
});
|
|
12526
13110
|
|
|
12527
13111
|
// src/commands/helper.ts
|
|
12528
|
-
import { Command as
|
|
13112
|
+
import { Command as Command26 } from "commander";
|
|
12529
13113
|
import pc29 from "picocolors";
|
|
12530
|
-
import { readdirSync, existsSync as
|
|
13114
|
+
import { readdirSync, existsSync as existsSync6, statSync } from "fs";
|
|
12531
13115
|
import { join as join34, basename as basename8 } from "path";
|
|
12532
13116
|
function extractNumberFromFile(filename, typeName) {
|
|
12533
13117
|
const regex = new RegExp(`^\\(${typeName}\\)\\s+(\\d+)`, "i");
|
|
@@ -12536,7 +13120,7 @@ function extractNumberFromFile(filename, typeName) {
|
|
|
12536
13120
|
}
|
|
12537
13121
|
function collectFilesRecursively(dirPath) {
|
|
12538
13122
|
const files = [];
|
|
12539
|
-
if (!
|
|
13123
|
+
if (!existsSync6(dirPath)) {
|
|
12540
13124
|
return files;
|
|
12541
13125
|
}
|
|
12542
13126
|
const entries = readdirSync(dirPath);
|
|
@@ -12557,7 +13141,7 @@ function collectFilesRecursively(dirPath) {
|
|
|
12557
13141
|
}
|
|
12558
13142
|
function getNextNumber(flintPath, typeName) {
|
|
12559
13143
|
const meshDir = join34(flintPath, "Mesh");
|
|
12560
|
-
if (!
|
|
13144
|
+
if (!existsSync6(meshDir)) {
|
|
12561
13145
|
return 1;
|
|
12562
13146
|
}
|
|
12563
13147
|
const allFiles = collectFilesRecursively(meshDir);
|
|
@@ -12570,9 +13154,9 @@ function getNextNumber(flintPath, typeName) {
|
|
|
12570
13154
|
function formatNumber(num, padding = 3) {
|
|
12571
13155
|
return num.toString().padStart(padding, "0");
|
|
12572
13156
|
}
|
|
12573
|
-
var helperCommand = new
|
|
12574
|
-
new
|
|
12575
|
-
new
|
|
13157
|
+
var helperCommand = new Command26("helper").description("Helper utilities for Flint workflows").addCommand(
|
|
13158
|
+
new Command26("type").description("Type-specific helpers").addCommand(
|
|
13159
|
+
new Command26("newnumber").description("Get the next available number for a typed artifact").argument("<type>", "Type name (Task, Report, Notepad, Increment, etc.)").option("-p, --path <dir>", "Path to flint (default: auto-detect)").option("--raw", "Output raw number without padding").action(async (typeName, options) => {
|
|
12576
13160
|
try {
|
|
12577
13161
|
const flintPath = options.path || await findFlintRoot(process.cwd());
|
|
12578
13162
|
if (!flintPath) {
|
|
@@ -12595,7 +13179,7 @@ var helperCommand = new Command27("helper").description("Helper utilities for Fl
|
|
|
12595
13179
|
);
|
|
12596
13180
|
|
|
12597
13181
|
// src/commands/delete.ts
|
|
12598
|
-
import { Command as
|
|
13182
|
+
import { Command as Command27 } from "commander";
|
|
12599
13183
|
import pc30 from "picocolors";
|
|
12600
13184
|
import { rm as rm12 } from "fs/promises";
|
|
12601
13185
|
import { resolve as resolve15 } from "path";
|
|
@@ -12612,7 +13196,7 @@ async function prompt4(question) {
|
|
|
12612
13196
|
});
|
|
12613
13197
|
});
|
|
12614
13198
|
}
|
|
12615
|
-
var deleteCommand = new
|
|
13199
|
+
var deleteCommand = new Command27("delete").description("Permanently delete a flint (folder + registry)").argument("[name-or-path]", "Flint name or path (defaults to current directory)").option("-f, --force", "Skip confirmation prompt").action(async (nameOrPath, options) => {
|
|
12616
13200
|
try {
|
|
12617
13201
|
let entry;
|
|
12618
13202
|
if (nameOrPath) {
|
|
@@ -12638,18 +13222,20 @@ var deleteCommand = new Command28("delete").description("Permanently delete a fl
|
|
|
12638
13222
|
process.exit(1);
|
|
12639
13223
|
}
|
|
12640
13224
|
}
|
|
12641
|
-
|
|
12642
|
-
console.log(pc30.red(pc30.bold(" This will permanently delete:")));
|
|
12643
|
-
console.log();
|
|
12644
|
-
console.log(` Name: ${pc30.bold(entry.name)}`);
|
|
12645
|
-
console.log(` Path: ${pc30.cyan(abbreviatePath(entry.path))}`);
|
|
12646
|
-
console.log();
|
|
12647
|
-
const answer = await prompt4(` Type ${pc30.bold(entry.name)} to confirm: `);
|
|
12648
|
-
if (answer !== entry.name) {
|
|
13225
|
+
if (!options.force) {
|
|
12649
13226
|
console.log();
|
|
12650
|
-
console.log(pc30.
|
|
13227
|
+
console.log(pc30.red(pc30.bold(" This will permanently delete:")));
|
|
12651
13228
|
console.log();
|
|
12652
|
-
|
|
13229
|
+
console.log(` Name: ${pc30.bold(entry.name)}`);
|
|
13230
|
+
console.log(` Path: ${pc30.cyan(abbreviatePath(entry.path))}`);
|
|
13231
|
+
console.log();
|
|
13232
|
+
const answer = await prompt4(` Type ${pc30.bold(entry.name)} to confirm: `);
|
|
13233
|
+
if (answer !== entry.name) {
|
|
13234
|
+
console.log();
|
|
13235
|
+
console.log(pc30.dim(" Cancelled \u2014 name did not match."));
|
|
13236
|
+
console.log();
|
|
13237
|
+
process.exit(0);
|
|
13238
|
+
}
|
|
12653
13239
|
}
|
|
12654
13240
|
await unregisterFlint(entry.path);
|
|
12655
13241
|
await rm12(entry.path, { recursive: true });
|
|
@@ -12670,7 +13256,7 @@ var featuresCommand = createFeaturesCommand({
|
|
|
12670
13256
|
});
|
|
12671
13257
|
|
|
12672
13258
|
// src/commands/org.ts
|
|
12673
|
-
import { Command as
|
|
13259
|
+
import { Command as Command28 } from "commander";
|
|
12674
13260
|
import pc31 from "picocolors";
|
|
12675
13261
|
var ORGS_CONVEX_URL_PROD = "https://impressive-ptarmigan-132.convex.site";
|
|
12676
13262
|
var ORGS_CONVEX_URL_DEV = "https://steady-lobster-998.convex.site";
|
|
@@ -12703,7 +13289,7 @@ async function requireAuth(env) {
|
|
|
12703
13289
|
}
|
|
12704
13290
|
var runtime = resolveRuntimeSync({ cliname: "flint" });
|
|
12705
13291
|
var devAvailable = runtime.mode === "dev";
|
|
12706
|
-
var orgCommand = new
|
|
13292
|
+
var orgCommand = new Command28("org").description("Organisation management");
|
|
12707
13293
|
var registerCmd = orgCommand.command("register").description("Register this flint to an organisation").argument("<slug>", "Organisation slug");
|
|
12708
13294
|
if (devAvailable) registerCmd.option("--dev", "Use dev environment");
|
|
12709
13295
|
registerCmd.action(async (slug, options) => {
|
|
@@ -12758,7 +13344,7 @@ var newDir = getConfigDir("flint");
|
|
|
12758
13344
|
var oldDir = join35(homedir5(), ".flint");
|
|
12759
13345
|
var intermediateDir = join35(homedir5(), ".nuucognition", ".flint");
|
|
12760
13346
|
function migrateDir(sourceDir, label) {
|
|
12761
|
-
if (!
|
|
13347
|
+
if (!existsSync7(sourceDir)) return false;
|
|
12762
13348
|
try {
|
|
12763
13349
|
const entries = readdirSync2(sourceDir);
|
|
12764
13350
|
const filesToMigrate = entries.filter((e) => !e.startsWith(".DS_Store"));
|
|
@@ -12768,7 +13354,7 @@ function migrateDir(sourceDir, label) {
|
|
|
12768
13354
|
for (const entry of filesToMigrate) {
|
|
12769
13355
|
const src = join35(sourceDir, entry);
|
|
12770
13356
|
const dest = join35(newDir, entry);
|
|
12771
|
-
if (!
|
|
13357
|
+
if (!existsSync7(dest)) {
|
|
12772
13358
|
cpSync(src, dest, { recursive: true });
|
|
12773
13359
|
migrated++;
|
|
12774
13360
|
}
|
|
@@ -12810,7 +13396,7 @@ var authConfig = {
|
|
|
12810
13396
|
defaultEnv: devAvailable2 ? "dev" : "prod",
|
|
12811
13397
|
devAvailable: devAvailable2
|
|
12812
13398
|
};
|
|
12813
|
-
var program = new
|
|
13399
|
+
var program = new Command29();
|
|
12814
13400
|
program.name("flint").description("Flint cognitive workspace CLI").version(pkg.version).enablePositionalOptions().option("--verbose", "Show stack traces for errors");
|
|
12815
13401
|
program.addCommand(createLoginCommand(authConfig));
|
|
12816
13402
|
program.addCommand(createLogoutCommand(authConfig));
|
|
@@ -12818,7 +13404,6 @@ program.addCommand(createWhoamiCommand(authConfig));
|
|
|
12818
13404
|
var COMMAND_MAP = [
|
|
12819
13405
|
// Production commands
|
|
12820
13406
|
{ featureId: "init", command: initCommand },
|
|
12821
|
-
{ featureId: "clone", command: cloneCommand },
|
|
12822
13407
|
{ featureId: "list", command: listCommand },
|
|
12823
13408
|
{ featureId: "shard", command: shardCommand },
|
|
12824
13409
|
{ featureId: "sync", command: syncCommand },
|