md4ai 0.14.1 → 0.15.0

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.
@@ -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.14.1" : "0.0.0-dev";
125
+ CURRENT_VERSION = true ? "0.15.0" : "0.0.0-dev";
126
126
  }
127
127
  });
128
128
 
@@ -1109,7 +1109,9 @@ var init_tooling_detector = __esm({
1109
1109
  { name: "pnpm", command: "pnpm", args: ["--version"], conditionFile: "pnpm-lock.yaml" },
1110
1110
  { name: "supabase-cli", command: "npx", args: ["supabase", "--version"] },
1111
1111
  { name: "vercel-cli", command: "npx", args: ["vercel", "--version"] },
1112
- { name: "claude-code", command: "claude", args: ["--version"] }
1112
+ { name: "claude-code", command: "claude", args: ["--version"] },
1113
+ { name: "gh", command: "gh", args: ["--version"] },
1114
+ { name: "git", command: "git", args: ["--version"] }
1113
1115
  ];
1114
1116
  }
1115
1117
  });
@@ -2288,12 +2290,14 @@ var init_html_generator = __esm({
2288
2290
  });
2289
2291
 
2290
2292
  // dist/commands/push-toolings.js
2291
- async function pushToolings(supabase, folderId, toolings) {
2293
+ async function pushToolings(supabase, folderId, toolings, deviceId) {
2292
2294
  if (!toolings.length)
2293
2295
  return;
2294
2296
  const { data: registry } = await supabase.from("tools_registry").select("id, name");
2295
2297
  const registryMap = new Map((registry ?? []).map((r) => [r.name, r.id]));
2296
- for (const tooling of toolings) {
2298
+ const projectToolings = toolings.filter((t) => t.detection_source !== "cli");
2299
+ const deviceToolings = toolings.filter((t) => t.detection_source === "cli");
2300
+ for (const tooling of projectToolings) {
2297
2301
  const toolId = registryMap.get(tooling.tool_name) ?? null;
2298
2302
  await supabase.from("project_toolings").upsert({
2299
2303
  folder_id: folderId,
@@ -2304,6 +2308,19 @@ async function pushToolings(supabase, folderId, toolings) {
2304
2308
  detected_at: (/* @__PURE__ */ new Date()).toISOString()
2305
2309
  }, { onConflict: "folder_id,tool_name,detection_source" });
2306
2310
  }
2311
+ if (deviceId && deviceToolings.length) {
2312
+ for (const tooling of deviceToolings) {
2313
+ const toolId = registryMap.get(tooling.tool_name) ?? null;
2314
+ await supabase.from("device_toolings").upsert({
2315
+ device_id: deviceId,
2316
+ tool_id: toolId,
2317
+ tool_name: tooling.tool_name,
2318
+ detected_version: tooling.detected_version,
2319
+ detection_source: tooling.detection_source,
2320
+ detected_at: (/* @__PURE__ */ new Date()).toISOString()
2321
+ }, { onConflict: "device_id,tool_name,detection_source" });
2322
+ }
2323
+ }
2307
2324
  }
2308
2325
  var init_push_toolings = __esm({
2309
2326
  "dist/commands/push-toolings.js"() {
@@ -2574,7 +2591,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
2574
2591
  cli_version: CURRENT_VERSION
2575
2592
  }, { onConflict: "folder_id,device_id" });
2576
2593
  }
2577
- await pushToolings(supabase, folder_id, result.toolings);
2594
+ await pushToolings(supabase, folder_id, result.toolings, deviceId);
2578
2595
  const manifestForHealth = result.envManifest ?? storedManifest;
2579
2596
  if (manifestForHealth) {
2580
2597
  await pushHealthResults(supabase, folder_id, manifestForHealth, deviceId);
@@ -2694,7 +2711,7 @@ ${proposedFiles.length} file(s) proposed for deletion:
2694
2711
  cli_version: CURRENT_VERSION
2695
2712
  }, { onConflict: "folder_id,device_id" });
2696
2713
  }
2697
- await pushToolings(sb, folderId, result.toolings);
2714
+ await pushToolings(sb, folderId, result.toolings, inlineDeviceId);
2698
2715
  if (result.envManifest) {
2699
2716
  await pushHealthResults(sb, folderId, result.envManifest, inlineDeviceId);
2700
2717
  }
@@ -2807,7 +2824,7 @@ async function syncCommand(options) {
2807
2824
  cli_version: CURRENT_VERSION
2808
2825
  }, { onConflict: "folder_id,device_id" });
2809
2826
  }
2810
- await pushToolings(supabase, device.folder_id, result.toolings);
2827
+ await pushToolings(supabase, device.folder_id, result.toolings, allDeviceId);
2811
2828
  await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", device.folder_id).eq("device_name", device.device_name);
2812
2829
  console.log(chalk15.green(` Done: ${device.device_name}`));
2813
2830
  } catch (err) {
@@ -2870,7 +2887,7 @@ async function syncCommand(options) {
2870
2887
  cli_version: CURRENT_VERSION
2871
2888
  }, { onConflict: "folder_id,device_id" });
2872
2889
  }
2873
- await pushToolings(supabase, device.folder_id, result.toolings);
2890
+ await pushToolings(supabase, device.folder_id, result.toolings, singleDeviceId);
2874
2891
  await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", device.folder_id).eq("device_name", device.device_name);
2875
2892
  await saveState({ lastSyncAt: (/* @__PURE__ */ new Date()).toISOString() });
2876
2893
  console.log(chalk15.green("Synced."));
@@ -3595,7 +3612,7 @@ async function checkPendingRescans(supabase, deviceId, deviceName) {
3595
3612
  data_hash: result.dataHash,
3596
3613
  rescan_requested_at: null
3597
3614
  }).eq("id", folder.id);
3598
- await pushToolings(supabase, folder.id, result.toolings);
3615
+ await pushToolings(supabase, folder.id, result.toolings, deviceId);
3599
3616
  await supabase.from("device_paths").update({ last_synced: (/* @__PURE__ */ new Date()).toISOString() }).eq("folder_id", folder.id).eq("device_name", deviceName);
3600
3617
  } catch {
3601
3618
  await supabase.from("claude_folders").update({ rescan_requested_at: null }).eq("id", folder.id);
@@ -4086,7 +4103,7 @@ Linking "${folder.name}" to this device...
4086
4103
  scanned_at: result.scannedAt,
4087
4104
  cli_version: CURRENT_VERSION
4088
4105
  }, { onConflict: "folder_id,device_id" });
4089
- await pushToolings(supabase, folder.id, result.toolings);
4106
+ await pushToolings(supabase, folder.id, result.toolings, deviceId);
4090
4107
  const graphPaths = result.graph.nodes.map((n) => n.filePath);
4091
4108
  const configFiles = await readClaudeConfigFiles(cwd, graphPaths);
4092
4109
  if (configFiles.length > 0) {
@@ -5037,18 +5054,29 @@ initSentry();
5037
5054
  if (process.argv.length <= 2) {
5038
5055
  void startCommand();
5039
5056
  } else {
5040
- program.parse();
5041
- const ran = program.args[0];
5042
- const skipAutoCheck = ["update", "check-update", "mcp-watch", "start"];
5043
- if (!skipAutoCheck.includes(ran)) {
5044
- autoCheckForUpdate();
5045
- }
5057
+ program.parseAsync().then(() => {
5058
+ const ran = program.args[0];
5059
+ const skipAutoCheck = ["update", "check-update", "mcp-watch", "start"];
5060
+ if (!skipAutoCheck.includes(ran)) {
5061
+ autoCheckForUpdate();
5062
+ }
5063
+ }).catch(async (err) => {
5064
+ captureException2(err);
5065
+ const msg = err instanceof Error ? err.message : String(err);
5066
+ console.error(`\x1B[31mError: ${msg}\x1B[0m`);
5067
+ await flushSentry();
5068
+ process.exit(1);
5069
+ });
5046
5070
  }
5047
5071
  process.on("uncaughtException", async (err) => {
5048
5072
  captureException2(err);
5049
5073
  await flushSentry();
5050
5074
  process.exit(1);
5051
5075
  });
5052
- process.on("unhandledRejection", (reason) => {
5076
+ process.on("unhandledRejection", async (reason) => {
5053
5077
  captureException2(reason);
5078
+ const msg = reason instanceof Error ? reason.message : String(reason);
5079
+ console.error(`\x1B[31mError: ${msg}\x1B[0m`);
5080
+ await flushSentry();
5081
+ process.exit(1);
5054
5082
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md4ai",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "CLI for MD4AI — scan Claude projects and sync to your dashboard",
5
5
  "type": "module",
6
6
  "bin": {