md4ai 0.17.1 → 0.17.3
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 +96 -23
- package/package.json +1 -1
package/dist/index.bundled.js
CHANGED
|
@@ -122,7 +122,7 @@ var CURRENT_VERSION;
|
|
|
122
122
|
var init_check_update = __esm({
|
|
123
123
|
"dist/check-update.js"() {
|
|
124
124
|
"use strict";
|
|
125
|
-
CURRENT_VERSION = true ? "0.17.
|
|
125
|
+
CURRENT_VERSION = true ? "0.17.3" : "0.0.0-dev";
|
|
126
126
|
}
|
|
127
127
|
});
|
|
128
128
|
|
|
@@ -365,14 +365,26 @@ import chalk5 from "chalk";
|
|
|
365
365
|
import { confirm, input as input2, password as password2 } from "@inquirer/prompts";
|
|
366
366
|
async function getAuthenticatedClient() {
|
|
367
367
|
const creds = await loadCredentials();
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
const reason = !creds?.accessToken ? "Not logged in." : "Session expired.";
|
|
371
|
-
console.log(chalk5.yellow(`${reason}`));
|
|
368
|
+
if (!creds?.accessToken) {
|
|
369
|
+
console.log(chalk5.yellow("Not logged in."));
|
|
372
370
|
const shouldLogin = await confirm({ message: "Would you like to log in now?" });
|
|
373
|
-
if (!shouldLogin)
|
|
371
|
+
if (!shouldLogin)
|
|
374
372
|
process.exit(0);
|
|
373
|
+
return promptLogin();
|
|
374
|
+
}
|
|
375
|
+
if (creds.refreshToken) {
|
|
376
|
+
const refreshed = await refreshSession();
|
|
377
|
+
if (refreshed) {
|
|
378
|
+
updateDeviceCliVersion(refreshed.supabase, refreshed.userId).catch(() => {
|
|
379
|
+
});
|
|
380
|
+
return refreshed;
|
|
375
381
|
}
|
|
382
|
+
}
|
|
383
|
+
if (Date.now() > creds.expiresAt) {
|
|
384
|
+
console.log(chalk5.yellow("Session expired."));
|
|
385
|
+
const shouldLogin = await confirm({ message: "Would you like to log in now?" });
|
|
386
|
+
if (!shouldLogin)
|
|
387
|
+
process.exit(0);
|
|
376
388
|
return promptLogin();
|
|
377
389
|
}
|
|
378
390
|
const anonKey = getAnonKey();
|
|
@@ -2069,6 +2081,11 @@ var init_doppler_scanner = __esm({
|
|
|
2069
2081
|
});
|
|
2070
2082
|
|
|
2071
2083
|
// dist/scanner/index.js
|
|
2084
|
+
var scanner_exports = {};
|
|
2085
|
+
__export(scanner_exports, {
|
|
2086
|
+
readClaudeConfigFiles: () => readClaudeConfigFiles,
|
|
2087
|
+
scanProject: () => scanProject
|
|
2088
|
+
});
|
|
2072
2089
|
import { readdir as readdir5 } from "node:fs/promises";
|
|
2073
2090
|
import { join as join12, relative as relative3 } from "node:path";
|
|
2074
2091
|
import { existsSync as existsSync7 } from "node:fs";
|
|
@@ -2619,7 +2636,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2619
2636
|
}
|
|
2620
2637
|
}
|
|
2621
2638
|
if (deviceId) {
|
|
2622
|
-
|
|
2639
|
+
const scanPayload = {
|
|
2623
2640
|
folder_id,
|
|
2624
2641
|
device_id: deviceId,
|
|
2625
2642
|
user_id: userId,
|
|
@@ -2635,7 +2652,14 @@ ${proposedFiles.length} file(s) proposed for deletion:
|
|
|
2635
2652
|
data_hash: result.dataHash,
|
|
2636
2653
|
scanned_at: result.scannedAt,
|
|
2637
2654
|
cli_version: CURRENT_VERSION
|
|
2638
|
-
}
|
|
2655
|
+
};
|
|
2656
|
+
const { data: updated, error: updateErr } = await supabase.from("device_scans").update(scanPayload).eq("folder_id", folder_id).eq("device_id", deviceId).select("id");
|
|
2657
|
+
if (updateErr || !updated?.length) {
|
|
2658
|
+
const { error: insertErr } = await supabase.from("device_scans").insert(scanPayload);
|
|
2659
|
+
if (insertErr) {
|
|
2660
|
+
console.error(chalk12.red(` Failed to save scan data: ${insertErr.message}`));
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2639
2663
|
}
|
|
2640
2664
|
await pushToolings(supabase, folder_id, result.toolings, deviceId);
|
|
2641
2665
|
const manifestForHealth = result.envManifest ?? storedManifest;
|
|
@@ -2803,8 +2827,14 @@ async function syncCommand(options) {
|
|
|
2803
2827
|
const currentDeviceName = detectDeviceName();
|
|
2804
2828
|
const { data: devices, error } = await supabase.from("device_paths").select("folder_id, device_name, path").eq("device_name", currentDeviceName);
|
|
2805
2829
|
if (error || !devices?.length) {
|
|
2806
|
-
console.
|
|
2807
|
-
|
|
2830
|
+
console.log(chalk15.yellow(`
|
|
2831
|
+
No projects linked on ${currentDeviceName} yet.
|
|
2832
|
+
`));
|
|
2833
|
+
console.log(chalk15.dim(" To link a project, cd into its folder and run:"));
|
|
2834
|
+
console.log(chalk15.cyan(" md4ai scan"));
|
|
2835
|
+
console.log(chalk15.dim(" Or link an existing project from the dashboard:"));
|
|
2836
|
+
console.log(chalk15.cyan(" md4ai link <project-id>\n"));
|
|
2837
|
+
return;
|
|
2808
2838
|
}
|
|
2809
2839
|
for (const device of devices) {
|
|
2810
2840
|
if (!isValidProjectPath(device.path)) {
|
|
@@ -3587,12 +3617,13 @@ async function checkPendingRescans(supabase, deviceId, deviceName) {
|
|
|
3587
3617
|
if (!paths?.length)
|
|
3588
3618
|
return;
|
|
3589
3619
|
const folderIds = paths.map((p) => p.folder_id);
|
|
3590
|
-
const { data: folders } = await supabase.from("claude_folders").select("id,
|
|
3620
|
+
const { data: folders } = await supabase.from("claude_folders").select("id, rescan_requested_at").in("id", folderIds).not("rescan_requested_at", "is", null);
|
|
3591
3621
|
if (!folders?.length)
|
|
3592
3622
|
return;
|
|
3593
3623
|
for (const folder of folders) {
|
|
3594
3624
|
const requested = new Date(folder.rescan_requested_at).getTime();
|
|
3595
|
-
const
|
|
3625
|
+
const { data: scanRow } = await supabase.from("device_scans").select("scanned_at").eq("folder_id", folder.id).eq("device_id", deviceId).maybeSingle();
|
|
3626
|
+
const scanned = scanRow?.scanned_at ? new Date(scanRow.scanned_at).getTime() : 0;
|
|
3596
3627
|
if (requested <= scanned)
|
|
3597
3628
|
continue;
|
|
3598
3629
|
const dp = paths.find((p) => p.folder_id === folder.id);
|
|
@@ -3600,24 +3631,46 @@ async function checkPendingRescans(supabase, deviceId, deviceName) {
|
|
|
3600
3631
|
continue;
|
|
3601
3632
|
try {
|
|
3602
3633
|
const result = await scanProject(dp.path);
|
|
3603
|
-
await supabase.
|
|
3634
|
+
const userId = (await supabase.auth.getUser()).data.user.id;
|
|
3635
|
+
const scanPayload = {
|
|
3604
3636
|
folder_id: folder.id,
|
|
3605
3637
|
device_id: deviceId,
|
|
3606
|
-
user_id:
|
|
3638
|
+
user_id: userId,
|
|
3607
3639
|
graph_json: result.graph,
|
|
3608
3640
|
orphans_json: result.orphans,
|
|
3609
3641
|
skills_table_json: result.skills,
|
|
3610
3642
|
stale_files_json: result.staleFiles,
|
|
3611
3643
|
broken_refs_json: result.brokenRefs,
|
|
3612
3644
|
env_manifest_json: result.envManifest,
|
|
3645
|
+
doppler_json: result.doppler,
|
|
3646
|
+
marketplace_plugins_json: result.marketplacePlugins,
|
|
3647
|
+
plugin_versions_json: result.pluginVersions,
|
|
3613
3648
|
data_hash: result.dataHash,
|
|
3614
3649
|
scanned_at: result.scannedAt,
|
|
3615
3650
|
cli_version: CURRENT_VERSION
|
|
3616
|
-
}
|
|
3651
|
+
};
|
|
3652
|
+
const { data: updated } = await supabase.from("device_scans").update(scanPayload).eq("folder_id", folder.id).eq("device_id", deviceId).select("id");
|
|
3653
|
+
if (!updated?.length) {
|
|
3654
|
+
await supabase.from("device_scans").insert(scanPayload);
|
|
3655
|
+
}
|
|
3617
3656
|
await supabase.from("claude_folders").update({
|
|
3618
3657
|
rescan_requested_at: null
|
|
3619
3658
|
}).eq("id", folder.id);
|
|
3620
3659
|
await pushToolings(supabase, folder.id, result.toolings, deviceId);
|
|
3660
|
+
const graphPaths = result.graph.nodes.map((n) => n.filePath);
|
|
3661
|
+
const { readClaudeConfigFiles: readClaudeConfigFiles2 } = await Promise.resolve().then(() => (init_scanner(), scanner_exports));
|
|
3662
|
+
const configFiles = await readClaudeConfigFiles2(dp.path, graphPaths);
|
|
3663
|
+
for (const cf of configFiles) {
|
|
3664
|
+
await supabase.from("folder_files").upsert({
|
|
3665
|
+
folder_id: folder.id,
|
|
3666
|
+
file_path: cf.filePath,
|
|
3667
|
+
content: cf.content,
|
|
3668
|
+
size_bytes: cf.sizeBytes,
|
|
3669
|
+
last_modified: cf.lastModified,
|
|
3670
|
+
synced_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3671
|
+
device_id: deviceId
|
|
3672
|
+
}, { onConflict: "folder_id,file_path,device_id" });
|
|
3673
|
+
}
|
|
3621
3674
|
await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", folder.id).eq("device_name", deviceName);
|
|
3622
3675
|
} catch {
|
|
3623
3676
|
await supabase.from("claude_folders").update({ rescan_requested_at: null }).eq("id", folder.id);
|
|
@@ -4334,7 +4387,15 @@ var VERSION_SOURCES = {
|
|
|
4334
4387
|
"turborepo": { type: "npm", package: "turbo" },
|
|
4335
4388
|
"npm": { type: "npm", package: "npm" },
|
|
4336
4389
|
"node": { type: "github", repo: "nodejs/node" },
|
|
4337
|
-
"supabase-cli": { type: "npm", package: "supabase" }
|
|
4390
|
+
"supabase-cli": { type: "npm", package: "supabase" },
|
|
4391
|
+
"vercel-cli": { type: "npm", package: "vercel" },
|
|
4392
|
+
"@sentry/node": { type: "npm", package: "@sentry/node" },
|
|
4393
|
+
"react-markdown": { type: "npm", package: "react-markdown" },
|
|
4394
|
+
"rehype-sanitize": { type: "npm", package: "rehype-sanitize" },
|
|
4395
|
+
"@react-email/render": { type: "npm", package: "@react-email/render" },
|
|
4396
|
+
"@anthropic-ai/sdk": { type: "npm", package: "@anthropic-ai/sdk" },
|
|
4397
|
+
"@xyflow/react": { type: "npm", package: "@xyflow/react" },
|
|
4398
|
+
"fflate": { type: "npm", package: "fflate" }
|
|
4338
4399
|
};
|
|
4339
4400
|
|
|
4340
4401
|
// dist/commands/admin-fetch-versions.js
|
|
@@ -4708,14 +4769,26 @@ ${lines.join("\n")}`;
|
|
|
4708
4769
|
}
|
|
4709
4770
|
const { select: selectPrompt } = await import("@inquirer/prompts");
|
|
4710
4771
|
const cwd = process.cwd();
|
|
4711
|
-
const
|
|
4772
|
+
const hasLinked = linkedPaths && linkedPaths.length > 0;
|
|
4773
|
+
const choices = [
|
|
4774
|
+
{ name: `Scan current folder (${cwd})`, value: "cwd" }
|
|
4775
|
+
];
|
|
4776
|
+
if (hasLinked) {
|
|
4777
|
+
const allLabel = `All ${linkedPaths.length} linked project${linkedPaths.length === 1 ? "" : "s"} on this device${linkedDisplay}`;
|
|
4778
|
+
choices.push({ name: allLabel, value: "all" });
|
|
4779
|
+
}
|
|
4780
|
+
choices.push({ name: "Skip", value: "skip" });
|
|
4781
|
+
if (!hasLinked) {
|
|
4782
|
+
console.log(chalk23.dim(` Device: ${currentDeviceName}`));
|
|
4783
|
+
console.log(chalk23.dim(" No projects linked on this device yet.\n"));
|
|
4784
|
+
console.log(chalk23.dim(" To link a project, cd into its folder and run:"));
|
|
4785
|
+
console.log(chalk23.cyan(" md4ai scan"));
|
|
4786
|
+
console.log(chalk23.dim(" Or link an existing project from the dashboard:"));
|
|
4787
|
+
console.log(chalk23.cyan(" md4ai link <project-id>\n"));
|
|
4788
|
+
}
|
|
4712
4789
|
const scanChoice = await selectPrompt({
|
|
4713
|
-
message: "What would you like to
|
|
4714
|
-
choices
|
|
4715
|
-
{ name: `Current folder (${cwd})`, value: "cwd" },
|
|
4716
|
-
{ name: allLabel, value: "all" },
|
|
4717
|
-
{ name: "Skip scanning", value: "skip" }
|
|
4718
|
-
]
|
|
4790
|
+
message: "What would you like to do?",
|
|
4791
|
+
choices
|
|
4719
4792
|
});
|
|
4720
4793
|
if (scanChoice === "cwd") {
|
|
4721
4794
|
console.log("");
|