md4ai 0.13.3 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.bundled.js +185 -96
- package/package.json +2 -2
package/dist/index.bundled.js
CHANGED
|
@@ -11,6 +11,7 @@ var __export = (target, all) => {
|
|
|
11
11
|
|
|
12
12
|
// dist/check-update.js
|
|
13
13
|
import chalk from "chalk";
|
|
14
|
+
import { execFileSync, spawn } from "node:child_process";
|
|
14
15
|
async function fetchLatest() {
|
|
15
16
|
try {
|
|
16
17
|
const controller = new AbortController();
|
|
@@ -27,6 +28,17 @@ async function fetchLatest() {
|
|
|
27
28
|
return null;
|
|
28
29
|
}
|
|
29
30
|
}
|
|
31
|
+
function runNpmInstall() {
|
|
32
|
+
try {
|
|
33
|
+
execFileSync("npm", ["install", "-g", "md4ai"], {
|
|
34
|
+
stdio: "inherit",
|
|
35
|
+
timeout: 6e4
|
|
36
|
+
});
|
|
37
|
+
return true;
|
|
38
|
+
} catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
30
42
|
function printUpdateBanner(latest) {
|
|
31
43
|
console.log("");
|
|
32
44
|
console.log(chalk.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
@@ -69,11 +81,48 @@ function isNewer(a, b) {
|
|
|
69
81
|
}
|
|
70
82
|
return false;
|
|
71
83
|
}
|
|
84
|
+
async function promptUpdateIfAvailable(originalArgs) {
|
|
85
|
+
try {
|
|
86
|
+
const latest = await fetchLatest();
|
|
87
|
+
if (!latest || !isNewer(latest, CURRENT_VERSION)) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
console.log("");
|
|
91
|
+
console.log(chalk.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
92
|
+
console.log(chalk.yellow("\u2502") + chalk.bold(" Update available! ") + chalk.dim(`${CURRENT_VERSION}`) + chalk.white(" \u2192 ") + chalk.green.bold(`${latest}`) + " " + chalk.yellow("\u2502"));
|
|
93
|
+
console.log(chalk.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
94
|
+
console.log("");
|
|
95
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
96
|
+
const wantUpdate = await confirm4({
|
|
97
|
+
message: `Update to v${latest} before continuing?`,
|
|
98
|
+
default: true
|
|
99
|
+
});
|
|
100
|
+
if (!wantUpdate) {
|
|
101
|
+
console.log(chalk.dim("Continuing with current version...\n"));
|
|
102
|
+
return true;
|
|
103
|
+
}
|
|
104
|
+
console.log(chalk.blue("\n Installing update...\n"));
|
|
105
|
+
const ok = runNpmInstall();
|
|
106
|
+
if (!ok) {
|
|
107
|
+
console.log(chalk.red("\n Update failed. Continuing with current version.\n"));
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
console.log(chalk.green("\n Updated successfully! Re-running command...\n"));
|
|
111
|
+
const child = spawn("md4ai", originalArgs, {
|
|
112
|
+
stdio: "inherit",
|
|
113
|
+
shell: false
|
|
114
|
+
});
|
|
115
|
+
child.on("exit", (code) => process.exit(code ?? 0));
|
|
116
|
+
return false;
|
|
117
|
+
} catch {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
72
121
|
var CURRENT_VERSION;
|
|
73
122
|
var init_check_update = __esm({
|
|
74
123
|
"dist/check-update.js"() {
|
|
75
124
|
"use strict";
|
|
76
|
-
CURRENT_VERSION = true ? "0.
|
|
125
|
+
CURRENT_VERSION = true ? "0.14.1" : "0.0.0-dev";
|
|
77
126
|
}
|
|
78
127
|
});
|
|
79
128
|
|
|
@@ -254,6 +303,59 @@ var init_login = __esm({
|
|
|
254
303
|
}
|
|
255
304
|
});
|
|
256
305
|
|
|
306
|
+
// dist/device-utils.js
|
|
307
|
+
import { hostname, platform } from "node:os";
|
|
308
|
+
function detectOs() {
|
|
309
|
+
const p = platform();
|
|
310
|
+
if (p === "win32")
|
|
311
|
+
return "windows";
|
|
312
|
+
if (p === "darwin")
|
|
313
|
+
return "macos";
|
|
314
|
+
if (p === "linux")
|
|
315
|
+
return "linux";
|
|
316
|
+
return "other";
|
|
317
|
+
}
|
|
318
|
+
function detectDeviceName() {
|
|
319
|
+
const os = detectOs();
|
|
320
|
+
const host = hostname().split(".")[0];
|
|
321
|
+
const osLabel = os.charAt(0).toUpperCase() + os.slice(1);
|
|
322
|
+
return `${host}-${osLabel}`;
|
|
323
|
+
}
|
|
324
|
+
async function resolveDeviceId(supabase, userId) {
|
|
325
|
+
const deviceName = detectDeviceName();
|
|
326
|
+
const osType = detectOs();
|
|
327
|
+
await supabase.from("devices").upsert({
|
|
328
|
+
user_id: userId,
|
|
329
|
+
device_name: deviceName,
|
|
330
|
+
os_type: osType,
|
|
331
|
+
last_cli_version: CURRENT_VERSION,
|
|
332
|
+
last_cli_seen_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
333
|
+
}, { onConflict: "user_id,device_name" });
|
|
334
|
+
const { data, error } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", deviceName).single();
|
|
335
|
+
if (error || !data) {
|
|
336
|
+
throw new Error(`Failed to resolve device ID: ${error?.message ?? "not found"}`);
|
|
337
|
+
}
|
|
338
|
+
return data.id;
|
|
339
|
+
}
|
|
340
|
+
async function updateDeviceCliVersion(supabase, userId) {
|
|
341
|
+
const deviceName = detectDeviceName();
|
|
342
|
+
const osType = detectOs();
|
|
343
|
+
await supabase.from("devices").upsert({
|
|
344
|
+
user_id: userId,
|
|
345
|
+
device_name: deviceName,
|
|
346
|
+
os_type: osType,
|
|
347
|
+
last_cli_version: CURRENT_VERSION,
|
|
348
|
+
last_cli_seen_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
349
|
+
}, { onConflict: "user_id,device_name" }).then(() => {
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
var init_device_utils = __esm({
|
|
353
|
+
"dist/device-utils.js"() {
|
|
354
|
+
"use strict";
|
|
355
|
+
init_check_update();
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
|
|
257
359
|
// dist/auth.js
|
|
258
360
|
import chalk5 from "chalk";
|
|
259
361
|
import { confirm, input as input2, password as password2 } from "@inquirer/prompts";
|
|
@@ -271,6 +373,8 @@ async function getAuthenticatedClient() {
|
|
|
271
373
|
}
|
|
272
374
|
const anonKey = getAnonKey();
|
|
273
375
|
const supabase = createSupabaseClient(anonKey, creds.accessToken);
|
|
376
|
+
updateDeviceCliVersion(supabase, creds.userId).catch(() => {
|
|
377
|
+
});
|
|
274
378
|
return { supabase, userId: creds.userId };
|
|
275
379
|
}
|
|
276
380
|
async function refreshSession() {
|
|
@@ -349,6 +453,7 @@ var init_auth = __esm({
|
|
|
349
453
|
"use strict";
|
|
350
454
|
init_dist();
|
|
351
455
|
init_config();
|
|
456
|
+
init_device_utils();
|
|
352
457
|
}
|
|
353
458
|
});
|
|
354
459
|
|
|
@@ -509,11 +614,11 @@ var init_file_parser = __esm({
|
|
|
509
614
|
});
|
|
510
615
|
|
|
511
616
|
// dist/scanner/git-dates.js
|
|
512
|
-
import { execFileSync } from "node:child_process";
|
|
617
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
513
618
|
import { statSync } from "node:fs";
|
|
514
619
|
function getGitLastModified(filePath, cwd) {
|
|
515
620
|
try {
|
|
516
|
-
const result =
|
|
621
|
+
const result = execFileSync2("git", ["log", "-1", "--format=%cI", "--", filePath], { cwd, encoding: "utf-8", timeout: 5e3 }).trim();
|
|
517
622
|
return result || null;
|
|
518
623
|
} catch {
|
|
519
624
|
try {
|
|
@@ -525,7 +630,7 @@ function getGitLastModified(filePath, cwd) {
|
|
|
525
630
|
}
|
|
526
631
|
function getGitCreationDate(filePath, cwd) {
|
|
527
632
|
try {
|
|
528
|
-
const result =
|
|
633
|
+
const result = execFileSync2("git", ["log", "--diff-filter=A", "--format=%cI", "--", filePath], { cwd, encoding: "utf-8", timeout: 5e3 }).trim();
|
|
529
634
|
return result || null;
|
|
530
635
|
} catch {
|
|
531
636
|
try {
|
|
@@ -671,7 +776,7 @@ var init_orphan_detector = __esm({
|
|
|
671
776
|
});
|
|
672
777
|
|
|
673
778
|
// dist/scanner/skills-parser.js
|
|
674
|
-
import { execFileSync as
|
|
779
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
675
780
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
676
781
|
import { existsSync as existsSync2 } from "node:fs";
|
|
677
782
|
import { join as join5 } from "node:path";
|
|
@@ -679,7 +784,7 @@ import { homedir as homedir3 } from "node:os";
|
|
|
679
784
|
async function parseSkills(projectRoot) {
|
|
680
785
|
const skills = /* @__PURE__ */ new Map();
|
|
681
786
|
try {
|
|
682
|
-
const output =
|
|
787
|
+
const output = execFileSync3("claude", ["plugin", "list"], { encoding: "utf-8", timeout: 1e4 }).trim();
|
|
683
788
|
if (output) {
|
|
684
789
|
for (const line of output.split("\n")) {
|
|
685
790
|
const name = line.trim().split(/\s+/)[0];
|
|
@@ -764,7 +869,7 @@ var init_skills_parser = __esm({
|
|
|
764
869
|
import { readFile as readFile4, readdir } from "node:fs/promises";
|
|
765
870
|
import { existsSync as existsSync3 } from "node:fs";
|
|
766
871
|
import { join as join6 } from "node:path";
|
|
767
|
-
import { execFileSync as
|
|
872
|
+
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
768
873
|
import { homedir as homedir4 } from "node:os";
|
|
769
874
|
async function detectToolings(projectRoot) {
|
|
770
875
|
const toolings = [];
|
|
@@ -932,7 +1037,7 @@ function detectFromCli(projectRoot) {
|
|
|
932
1037
|
continue;
|
|
933
1038
|
}
|
|
934
1039
|
try {
|
|
935
|
-
const output =
|
|
1040
|
+
const output = execFileSync4(command, args, {
|
|
936
1041
|
encoding: "utf-8",
|
|
937
1042
|
timeout: 3e3,
|
|
938
1043
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -1046,11 +1151,23 @@ var init_auth2 = __esm({
|
|
|
1046
1151
|
});
|
|
1047
1152
|
|
|
1048
1153
|
// dist/vercel/discover-projects.js
|
|
1049
|
-
import { readFile as readFile6,
|
|
1154
|
+
import { readFile as readFile6, readdir as readdir2 } from "node:fs/promises";
|
|
1050
1155
|
import { join as join8, dirname as dirname2, relative } from "node:path";
|
|
1051
1156
|
async function discoverVercelProjects(projectRoot) {
|
|
1052
1157
|
const found = /* @__PURE__ */ new Map();
|
|
1053
|
-
|
|
1158
|
+
let entries;
|
|
1159
|
+
try {
|
|
1160
|
+
entries = await readdir2(projectRoot, { recursive: true, withFileTypes: true });
|
|
1161
|
+
} catch {
|
|
1162
|
+
return [];
|
|
1163
|
+
}
|
|
1164
|
+
for (const entry of entries) {
|
|
1165
|
+
if (!entry.isFile() || entry.name !== "project.json")
|
|
1166
|
+
continue;
|
|
1167
|
+
const parentName = typeof entry.parentPath === "string" ? entry.parentPath : entry.path;
|
|
1168
|
+
if (!parentName.endsWith(".vercel"))
|
|
1169
|
+
continue;
|
|
1170
|
+
const filePath = join8(parentName, entry.name);
|
|
1054
1171
|
try {
|
|
1055
1172
|
const data = await readFile6(filePath, "utf-8");
|
|
1056
1173
|
const parsed = JSON.parse(data);
|
|
@@ -1145,7 +1262,7 @@ var init_fetch_env_vars = __esm({
|
|
|
1145
1262
|
});
|
|
1146
1263
|
|
|
1147
1264
|
// dist/scanner/env-manifest-scanner.js
|
|
1148
|
-
import { readFile as readFile7,
|
|
1265
|
+
import { readFile as readFile7, readdir as readdir3 } from "node:fs/promises";
|
|
1149
1266
|
import { execFile } from "node:child_process";
|
|
1150
1267
|
import { promisify } from "node:util";
|
|
1151
1268
|
import { join as join9, relative as relative2 } from "node:path";
|
|
@@ -1414,21 +1531,23 @@ async function parseWorkflowSecrets(projectRoot) {
|
|
|
1414
1531
|
return [];
|
|
1415
1532
|
const refs = [];
|
|
1416
1533
|
const secretRe = /\$\{\{\s*secrets\.([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1534
|
+
const files = await readdir3(workflowsDir);
|
|
1535
|
+
for (const file of files) {
|
|
1536
|
+
if (!file.endsWith(".yml") && !file.endsWith(".yaml"))
|
|
1537
|
+
continue;
|
|
1538
|
+
const filePath = join9(workflowsDir, file);
|
|
1539
|
+
const content = await readFile7(filePath, "utf-8");
|
|
1540
|
+
const secrets = /* @__PURE__ */ new Set();
|
|
1541
|
+
let m;
|
|
1542
|
+
while ((m = secretRe.exec(content)) !== null) {
|
|
1543
|
+
secrets.add(m[1]);
|
|
1544
|
+
}
|
|
1545
|
+
secretRe.lastIndex = 0;
|
|
1546
|
+
if (secrets.size > 0) {
|
|
1547
|
+
refs.push({
|
|
1548
|
+
workflowFile: relative2(projectRoot, filePath),
|
|
1549
|
+
secretsUsed: [...secrets].sort()
|
|
1550
|
+
});
|
|
1432
1551
|
}
|
|
1433
1552
|
}
|
|
1434
1553
|
return refs;
|
|
@@ -1555,7 +1674,7 @@ var init_env_manifest_scanner = __esm({
|
|
|
1555
1674
|
});
|
|
1556
1675
|
|
|
1557
1676
|
// dist/scanner/marketplace-scanner.js
|
|
1558
|
-
import { readFile as readFile8, readdir as
|
|
1677
|
+
import { readFile as readFile8, readdir as readdir4, stat } from "node:fs/promises";
|
|
1559
1678
|
import { join as join10, resolve as resolve3 } from "node:path";
|
|
1560
1679
|
import { existsSync as existsSync5 } from "node:fs";
|
|
1561
1680
|
import { homedir as homedir6 } from "node:os";
|
|
@@ -1624,7 +1743,7 @@ async function discoverSkills(installPath) {
|
|
|
1624
1743
|
return [];
|
|
1625
1744
|
const skills = [];
|
|
1626
1745
|
try {
|
|
1627
|
-
const entries = await
|
|
1746
|
+
const entries = await readdir4(skillsDir, { withFileTypes: true });
|
|
1628
1747
|
for (const entry of entries) {
|
|
1629
1748
|
if (!entry.isDirectory())
|
|
1630
1749
|
continue;
|
|
@@ -1881,7 +2000,7 @@ var init_doppler_scanner = __esm({
|
|
|
1881
2000
|
});
|
|
1882
2001
|
|
|
1883
2002
|
// dist/scanner/index.js
|
|
1884
|
-
import { readdir as
|
|
2003
|
+
import { readdir as readdir5 } from "node:fs/promises";
|
|
1885
2004
|
import { join as join12, relative as relative3 } from "node:path";
|
|
1886
2005
|
import { existsSync as existsSync7 } from "node:fs";
|
|
1887
2006
|
import { homedir as homedir7 } from "node:os";
|
|
@@ -1968,7 +2087,7 @@ async function discoverFiles(projectRoot) {
|
|
|
1968
2087
|
return [...new Set(files)];
|
|
1969
2088
|
}
|
|
1970
2089
|
async function walkDir(dir, projectRoot, files) {
|
|
1971
|
-
const entries = await
|
|
2090
|
+
const entries = await readdir5(dir, { withFileTypes: true });
|
|
1972
2091
|
for (const entry of entries) {
|
|
1973
2092
|
const fullPath = join12(dir, entry.name);
|
|
1974
2093
|
if (entry.isDirectory()) {
|
|
@@ -2294,44 +2413,6 @@ var init_push_health_results = __esm({
|
|
|
2294
2413
|
}
|
|
2295
2414
|
});
|
|
2296
2415
|
|
|
2297
|
-
// dist/device-utils.js
|
|
2298
|
-
import { hostname as hostname2, platform as platform2 } from "node:os";
|
|
2299
|
-
function detectOs2() {
|
|
2300
|
-
const p = platform2();
|
|
2301
|
-
if (p === "win32")
|
|
2302
|
-
return "windows";
|
|
2303
|
-
if (p === "darwin")
|
|
2304
|
-
return "macos";
|
|
2305
|
-
if (p === "linux")
|
|
2306
|
-
return "linux";
|
|
2307
|
-
return "other";
|
|
2308
|
-
}
|
|
2309
|
-
function detectDeviceName() {
|
|
2310
|
-
const os = detectOs2();
|
|
2311
|
-
const host = hostname2().split(".")[0];
|
|
2312
|
-
const osLabel = os.charAt(0).toUpperCase() + os.slice(1);
|
|
2313
|
-
return `${host}-${osLabel}`;
|
|
2314
|
-
}
|
|
2315
|
-
async function resolveDeviceId(supabase, userId) {
|
|
2316
|
-
const deviceName = detectDeviceName();
|
|
2317
|
-
const osType = detectOs2();
|
|
2318
|
-
await supabase.from("devices").upsert({
|
|
2319
|
-
user_id: userId,
|
|
2320
|
-
device_name: deviceName,
|
|
2321
|
-
os_type: osType
|
|
2322
|
-
}, { onConflict: "user_id,device_name" });
|
|
2323
|
-
const { data, error } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", deviceName).single();
|
|
2324
|
-
if (error || !data) {
|
|
2325
|
-
throw new Error(`Failed to resolve device ID: ${error?.message ?? "not found"}`);
|
|
2326
|
-
}
|
|
2327
|
-
return data.id;
|
|
2328
|
-
}
|
|
2329
|
-
var init_device_utils = __esm({
|
|
2330
|
-
"dist/device-utils.js"() {
|
|
2331
|
-
"use strict";
|
|
2332
|
-
}
|
|
2333
|
-
});
|
|
2334
|
-
|
|
2335
2416
|
// dist/commands/map.js
|
|
2336
2417
|
var map_exports = {};
|
|
2337
2418
|
__export(map_exports, {
|
|
@@ -2343,7 +2424,12 @@ import { existsSync as existsSync8 } from "node:fs";
|
|
|
2343
2424
|
import chalk12 from "chalk";
|
|
2344
2425
|
import { select as select4, input as input5, confirm as confirm2 } from "@inquirer/prompts";
|
|
2345
2426
|
async function mapCommand(path, options) {
|
|
2346
|
-
|
|
2427
|
+
const args = path ? ["scan", path] : ["scan"];
|
|
2428
|
+
if (options.offline)
|
|
2429
|
+
args.push("--offline");
|
|
2430
|
+
const shouldContinue = await promptUpdateIfAvailable(args);
|
|
2431
|
+
if (!shouldContinue)
|
|
2432
|
+
return;
|
|
2347
2433
|
const projectRoot = resolve4(path ?? process.cwd());
|
|
2348
2434
|
if (!existsSync8(projectRoot)) {
|
|
2349
2435
|
console.error(chalk12.red(`Path not found: ${projectRoot}`));
|
|
@@ -2555,7 +2641,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2555
2641
|
folderId = chosen;
|
|
2556
2642
|
}
|
|
2557
2643
|
const deviceName = detectDeviceName();
|
|
2558
|
-
const osType =
|
|
2644
|
+
const osType = detectOs();
|
|
2559
2645
|
await sb.from("devices").upsert({
|
|
2560
2646
|
user_id: userId2,
|
|
2561
2647
|
device_name: deviceName,
|
|
@@ -2806,7 +2892,7 @@ import { readFile as readFile12 } from "node:fs/promises";
|
|
|
2806
2892
|
import { join as join15 } from "node:path";
|
|
2807
2893
|
import { homedir as homedir9 } from "node:os";
|
|
2808
2894
|
import { existsSync as existsSync13 } from "node:fs";
|
|
2809
|
-
import { readdir as
|
|
2895
|
+
import { readdir as readdir6 } from "node:fs/promises";
|
|
2810
2896
|
async function readJsonSafe(path) {
|
|
2811
2897
|
try {
|
|
2812
2898
|
if (!existsSync13(path))
|
|
@@ -2882,14 +2968,14 @@ async function readAllMcpConfigs() {
|
|
|
2882
2968
|
const pluginsBase = join15(home, ".claude", "plugins", "marketplaces");
|
|
2883
2969
|
if (existsSync13(pluginsBase)) {
|
|
2884
2970
|
try {
|
|
2885
|
-
const marketplaces = await
|
|
2971
|
+
const marketplaces = await readdir6(pluginsBase, { withFileTypes: true });
|
|
2886
2972
|
for (const mp of marketplaces) {
|
|
2887
2973
|
if (!mp.isDirectory())
|
|
2888
2974
|
continue;
|
|
2889
2975
|
const extDir = join15(pluginsBase, mp.name, "external_plugins");
|
|
2890
2976
|
if (!existsSync13(extDir))
|
|
2891
2977
|
continue;
|
|
2892
|
-
const plugins = await
|
|
2978
|
+
const plugins = await readdir6(extDir, { withFileTypes: true });
|
|
2893
2979
|
for (const plugin of plugins) {
|
|
2894
2980
|
if (!plugin.isDirectory())
|
|
2895
2981
|
continue;
|
|
@@ -2903,16 +2989,16 @@ async function readAllMcpConfigs() {
|
|
|
2903
2989
|
const cacheBase = join15(home, ".claude", "plugins", "cache");
|
|
2904
2990
|
if (existsSync13(cacheBase)) {
|
|
2905
2991
|
try {
|
|
2906
|
-
const registries = await
|
|
2992
|
+
const registries = await readdir6(cacheBase, { withFileTypes: true });
|
|
2907
2993
|
for (const reg of registries) {
|
|
2908
2994
|
if (!reg.isDirectory())
|
|
2909
2995
|
continue;
|
|
2910
2996
|
const regDir = join15(cacheBase, reg.name);
|
|
2911
|
-
const plugins = await
|
|
2997
|
+
const plugins = await readdir6(regDir, { withFileTypes: true });
|
|
2912
2998
|
for (const plugin of plugins) {
|
|
2913
2999
|
if (!plugin.isDirectory())
|
|
2914
3000
|
continue;
|
|
2915
|
-
const versionDirs = await
|
|
3001
|
+
const versionDirs = await readdir6(join15(regDir, plugin.name), { withFileTypes: true });
|
|
2916
3002
|
for (const ver of versionDirs) {
|
|
2917
3003
|
if (!ver.isDirectory())
|
|
2918
3004
|
continue;
|
|
@@ -2945,7 +3031,7 @@ var init_read_configs = __esm({
|
|
|
2945
3031
|
});
|
|
2946
3032
|
|
|
2947
3033
|
// dist/mcp/scan-processes.js
|
|
2948
|
-
import { execFileSync as
|
|
3034
|
+
import { execFileSync as execFileSync5 } from "node:child_process";
|
|
2949
3035
|
import { readlinkSync } from "node:fs";
|
|
2950
3036
|
function parsePsOutput(output) {
|
|
2951
3037
|
const lines = output.trim().split("\n").slice(1);
|
|
@@ -3026,7 +3112,7 @@ function findProcessesForConfig(config2, processes) {
|
|
|
3026
3112
|
}
|
|
3027
3113
|
function getProcessTable() {
|
|
3028
3114
|
try {
|
|
3029
|
-
const output =
|
|
3115
|
+
const output = execFileSync5("ps", ["-eo", "pid,tty,etime,rss,args"], {
|
|
3030
3116
|
encoding: "utf-8",
|
|
3031
3117
|
timeout: 5e3
|
|
3032
3118
|
});
|
|
@@ -3067,11 +3153,11 @@ __export(mcp_watch_exports, {
|
|
|
3067
3153
|
mcpWatchCommand: () => mcpWatchCommand
|
|
3068
3154
|
});
|
|
3069
3155
|
import chalk21 from "chalk";
|
|
3070
|
-
import { execFileSync as
|
|
3156
|
+
import { execFileSync as execFileSync6 } from "node:child_process";
|
|
3071
3157
|
import { createHash as createHash2 } from "node:crypto";
|
|
3072
3158
|
function detectTty() {
|
|
3073
3159
|
try {
|
|
3074
|
-
const result =
|
|
3160
|
+
const result = execFileSync6("ps", ["-o", "tty=", "-p", String(process.pid)], {
|
|
3075
3161
|
encoding: "utf-8",
|
|
3076
3162
|
timeout: 3e3
|
|
3077
3163
|
}).trim();
|
|
@@ -3668,11 +3754,11 @@ Folder "${name}" created ${teamLabel} (${data.id})`));
|
|
|
3668
3754
|
// dist/commands/add-device.js
|
|
3669
3755
|
init_auth();
|
|
3670
3756
|
import { resolve } from "node:path";
|
|
3671
|
-
import { hostname, platform } from "node:os";
|
|
3757
|
+
import { hostname as hostname2, platform as platform2 } from "node:os";
|
|
3672
3758
|
import chalk7 from "chalk";
|
|
3673
3759
|
import { input as input4, select as select2 } from "@inquirer/prompts";
|
|
3674
|
-
function
|
|
3675
|
-
const p =
|
|
3760
|
+
function detectOs2() {
|
|
3761
|
+
const p = platform2();
|
|
3676
3762
|
if (p === "win32")
|
|
3677
3763
|
return "windows";
|
|
3678
3764
|
if (p === "darwin")
|
|
@@ -3682,8 +3768,8 @@ function detectOs() {
|
|
|
3682
3768
|
return "other";
|
|
3683
3769
|
}
|
|
3684
3770
|
function suggestDeviceName() {
|
|
3685
|
-
const os =
|
|
3686
|
-
const host =
|
|
3771
|
+
const os = detectOs2();
|
|
3772
|
+
const host = hostname2().split(".")[0];
|
|
3687
3773
|
const osLabel = os.charAt(0).toUpperCase() + os.slice(1);
|
|
3688
3774
|
return `${host}-${osLabel}`;
|
|
3689
3775
|
}
|
|
@@ -3718,7 +3804,7 @@ async function addDeviceCommand() {
|
|
|
3718
3804
|
{ name: "Linux", value: "linux" },
|
|
3719
3805
|
{ name: "Other", value: "other" }
|
|
3720
3806
|
],
|
|
3721
|
-
default:
|
|
3807
|
+
default: detectOs2()
|
|
3722
3808
|
});
|
|
3723
3809
|
const description = await input4({ message: "Description (optional):" });
|
|
3724
3810
|
const { error } = await supabase.from("device_paths").insert({
|
|
@@ -3911,10 +3997,13 @@ init_check_update();
|
|
|
3911
3997
|
import { resolve as resolve6 } from "node:path";
|
|
3912
3998
|
import chalk16 from "chalk";
|
|
3913
3999
|
async function linkCommand(projectId) {
|
|
4000
|
+
const shouldContinue = await promptUpdateIfAvailable(["link", projectId]);
|
|
4001
|
+
if (!shouldContinue)
|
|
4002
|
+
return;
|
|
3914
4003
|
const { supabase, userId } = await getAuthenticatedClient();
|
|
3915
4004
|
const cwd = resolve6(process.cwd());
|
|
3916
4005
|
const deviceName = detectDeviceName();
|
|
3917
|
-
const osType =
|
|
4006
|
+
const osType = detectOs();
|
|
3918
4007
|
const { data: folder, error: folderErr } = await supabase.from("claude_folders").select("id, name").eq("id", projectId).single();
|
|
3919
4008
|
if (folderErr || !folder) {
|
|
3920
4009
|
console.error(chalk16.red("Project not found, or you do not have access."));
|
|
@@ -4528,7 +4617,7 @@ init_check_update();
|
|
|
4528
4617
|
init_config();
|
|
4529
4618
|
init_auth();
|
|
4530
4619
|
import chalk23 from "chalk";
|
|
4531
|
-
import { execFileSync as
|
|
4620
|
+
import { execFileSync as execFileSync7, spawn as spawn2 } from "node:child_process";
|
|
4532
4621
|
async function fetchLatestVersion() {
|
|
4533
4622
|
try {
|
|
4534
4623
|
const controller = new AbortController();
|
|
@@ -4556,9 +4645,9 @@ function isNewer2(a, b) {
|
|
|
4556
4645
|
}
|
|
4557
4646
|
return false;
|
|
4558
4647
|
}
|
|
4559
|
-
function
|
|
4648
|
+
function runNpmInstall2() {
|
|
4560
4649
|
try {
|
|
4561
|
-
|
|
4650
|
+
execFileSync7("npm", ["install", "-g", "md4ai"], {
|
|
4562
4651
|
stdio: "inherit",
|
|
4563
4652
|
timeout: 6e4
|
|
4564
4653
|
});
|
|
@@ -4568,7 +4657,7 @@ function runNpmInstall() {
|
|
|
4568
4657
|
}
|
|
4569
4658
|
}
|
|
4570
4659
|
function spawnPostUpdate() {
|
|
4571
|
-
const child =
|
|
4660
|
+
const child = spawn2("md4ai", ["update", "--post-update"], {
|
|
4572
4661
|
stdio: "inherit",
|
|
4573
4662
|
shell: false
|
|
4574
4663
|
});
|
|
@@ -4674,7 +4763,7 @@ async function updateCommand(options) {
|
|
|
4674
4763
|
return;
|
|
4675
4764
|
}
|
|
4676
4765
|
console.log(chalk23.blue("\n Installing...\n"));
|
|
4677
|
-
const ok =
|
|
4766
|
+
const ok = runNpmInstall2();
|
|
4678
4767
|
if (!ok) {
|
|
4679
4768
|
console.log(chalk23.red("\n npm install failed. Try running manually:"));
|
|
4680
4769
|
console.log(chalk23.cyan(" npm install -g md4ai\n"));
|
|
@@ -4734,17 +4823,17 @@ async function startCommand() {
|
|
|
4734
4823
|
default: true
|
|
4735
4824
|
});
|
|
4736
4825
|
if (wantUpdate) {
|
|
4737
|
-
const { execFileSync:
|
|
4826
|
+
const { execFileSync: execFileSync8 } = await import("node:child_process");
|
|
4738
4827
|
console.log(chalk24.blue("\n Installing...\n"));
|
|
4739
4828
|
try {
|
|
4740
|
-
|
|
4829
|
+
execFileSync8("npm", ["install", "-g", "md4ai"], {
|
|
4741
4830
|
stdio: "inherit",
|
|
4742
4831
|
timeout: 6e4
|
|
4743
4832
|
});
|
|
4744
4833
|
console.log(chalk24.green(" Updated successfully."));
|
|
4745
4834
|
console.log(chalk24.dim(" Restarting with the new version...\n"));
|
|
4746
|
-
const { spawn:
|
|
4747
|
-
const child =
|
|
4835
|
+
const { spawn: spawn3 } = await import("node:child_process");
|
|
4836
|
+
const child = spawn3("md4ai", ["start"], { stdio: "inherit", shell: false });
|
|
4748
4837
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
4749
4838
|
return;
|
|
4750
4839
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "md4ai",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "CLI for MD4AI — scan Claude projects and sync to your dashboard",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"directory": "cli"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
34
|
-
"node": ">=
|
|
34
|
+
"node": ">=20"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@inquirer/prompts": "^8.3.0",
|