md4ai 0.16.2 → 0.17.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.
Files changed (2) hide show
  1. package/dist/index.bundled.js +36 -108
  2. package/package.json +1 -1
@@ -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.16.2" : "0.0.0-dev";
125
+ CURRENT_VERSION = true ? "0.17.0" : "0.0.0-dev";
126
126
  }
127
127
  });
128
128
 
@@ -1955,9 +1955,14 @@ async function scanDoppler(projectRoot, folderId) {
1955
1955
  let matchedVia = "doppler-yaml";
1956
1956
  if (!projectSlug && folderId) {
1957
1957
  const state = await loadState();
1958
- projectSlug = state.dopplerProjects?.[folderId] ?? null;
1959
- if (projectSlug)
1958
+ const savedSlug = state.dopplerProjects?.[folderId] ?? null;
1959
+ if (savedSlug === "__none__") {
1960
+ return null;
1961
+ }
1962
+ if (savedSlug) {
1963
+ projectSlug = savedSlug;
1960
1964
  matchedVia = "manual";
1965
+ }
1961
1966
  }
1962
1967
  if (!projectSlug) {
1963
1968
  if (!folderId || !process.stdin.isTTY) {
@@ -1980,13 +1985,25 @@ async function scanDoppler(projectRoot, folderId) {
1980
1985
  projectSlug = autoMatch.slug;
1981
1986
  console.log(chalk10.green(` Doppler: auto-matched project "${projectSlug}" from project name.`));
1982
1987
  } else {
1983
- projectSlug = await select3({
1988
+ const choice = await select3({
1984
1989
  message: `Which Doppler project holds secrets for "${projectName}"?`,
1985
- choices: projects.map((p) => ({
1986
- name: `${p.slug}${p.name !== p.slug ? ` (${p.name})` : ""}`,
1987
- value: p.slug
1988
- }))
1990
+ choices: [
1991
+ ...projects.map((p) => ({
1992
+ name: `${p.slug}${p.name !== p.slug ? ` (${p.name})` : ""}`,
1993
+ value: p.slug
1994
+ })),
1995
+ { name: "None \u2014 this project does not use Doppler", value: "__none__" }
1996
+ ]
1989
1997
  });
1998
+ if (choice === "__none__") {
1999
+ const state2 = await loadState();
2000
+ const dopplerProjects2 = state2.dopplerProjects ?? {};
2001
+ dopplerProjects2[folderId] = "__none__";
2002
+ await saveState({ dopplerProjects: dopplerProjects2 });
2003
+ console.log(chalk10.dim(" Doppler: skipped for this project. To change later: md4ai doppler set-project <slug>"));
2004
+ return null;
2005
+ }
2006
+ projectSlug = choice;
1990
2007
  }
1991
2008
  }
1992
2009
  const state = await loadState();
@@ -2599,35 +2616,11 @@ ${proposedFiles.length} file(s) proposed for deletion:
2599
2616
  }
2600
2617
  let storedManifest = null;
2601
2618
  if (!result.envManifest) {
2602
- const { data: stored, error: fetchErr } = await supabase.from("claude_folders").select("env_manifest_json").eq("id", folder_id).single();
2619
+ const { data: stored, error: fetchErr } = await supabase.from("device_scans").select("env_manifest_json").eq("folder_id", folder_id).eq("device_id", deviceId).maybeSingle();
2603
2620
  if (!fetchErr && stored?.env_manifest_json) {
2604
2621
  storedManifest = stored.env_manifest_json;
2605
2622
  }
2606
2623
  }
2607
- const updatePayload = {
2608
- graph_json: result.graph,
2609
- orphans_json: result.orphans,
2610
- broken_refs_json: result.brokenRefs,
2611
- skills_table_json: result.skills,
2612
- stale_files_json: result.staleFiles,
2613
- marketplace_plugins_json: result.marketplacePlugins,
2614
- last_scanned: result.scannedAt,
2615
- data_hash: result.dataHash
2616
- };
2617
- if (result.envManifest) {
2618
- updatePayload.env_manifest_json = result.envManifest;
2619
- }
2620
- if (result.doppler) {
2621
- updatePayload.doppler_json = result.doppler;
2622
- }
2623
- try {
2624
- const { error } = await supabase.from("claude_folders").update(updatePayload).eq("id", folder_id);
2625
- if (error) {
2626
- console.log(chalk12.dim(`Debug: claude_folders update skipped (${error.message})`));
2627
- }
2628
- } catch (err) {
2629
- console.log(chalk12.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
2630
- }
2631
2624
  if (deviceId) {
2632
2625
  await supabase.from("device_scans").upsert({
2633
2626
  folder_id,
@@ -2730,25 +2723,6 @@ ${proposedFiles.length} file(s) proposed for deletion:
2730
2723
  path: projectRoot,
2731
2724
  last_synced: (/* @__PURE__ */ new Date()).toISOString()
2732
2725
  }, { onConflict: "folder_id,device_name" });
2733
- try {
2734
- const { error: inlineFolderErr } = await sb.from("claude_folders").update({
2735
- graph_json: result.graph,
2736
- orphans_json: result.orphans,
2737
- broken_refs_json: result.brokenRefs,
2738
- skills_table_json: result.skills,
2739
- stale_files_json: result.staleFiles,
2740
- env_manifest_json: result.envManifest,
2741
- doppler_json: result.doppler,
2742
- marketplace_plugins_json: result.marketplacePlugins,
2743
- last_scanned: result.scannedAt,
2744
- data_hash: result.dataHash
2745
- }).eq("id", folderId);
2746
- if (inlineFolderErr) {
2747
- console.log(chalk12.dim(`Debug: claude_folders update skipped (${inlineFolderErr.message})`));
2748
- }
2749
- } catch (err) {
2750
- console.log(chalk12.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
2751
- }
2752
2726
  if (inlineDeviceId) {
2753
2727
  await sb.from("device_scans").upsert({
2754
2728
  folder_id: folderId,
@@ -2849,23 +2823,6 @@ async function syncCommand(options) {
2849
2823
  const result = await scanProject(device.path, device.folder_id);
2850
2824
  const { data: allDeviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", device.device_name).single();
2851
2825
  const allDeviceId = allDeviceRow?.id;
2852
- try {
2853
- const { error: allFolderErr } = await supabase.from("claude_folders").update({
2854
- graph_json: result.graph,
2855
- orphans_json: result.orphans,
2856
- broken_refs_json: result.brokenRefs,
2857
- skills_table_json: result.skills,
2858
- stale_files_json: result.staleFiles,
2859
- env_manifest_json: result.envManifest,
2860
- last_scanned: result.scannedAt,
2861
- data_hash: result.dataHash
2862
- }).eq("id", device.folder_id);
2863
- if (allFolderErr) {
2864
- console.log(chalk15.dim(` Debug: claude_folders update skipped (${allFolderErr.message})`));
2865
- }
2866
- } catch (folderErr) {
2867
- console.log(chalk15.dim(` Debug: claude_folders update skipped (${folderErr instanceof Error ? folderErr.message : String(folderErr)})`));
2868
- }
2869
2826
  if (allDeviceId) {
2870
2827
  await supabase.from("device_scans").upsert({
2871
2828
  folder_id: device.folder_id,
@@ -2915,22 +2872,6 @@ async function syncCommand(options) {
2915
2872
  const result = await scanProject(device.path, device.folder_id);
2916
2873
  const { data: singleDeviceRow } = await supabase.from("devices").select("id").eq("user_id", userId).eq("device_name", device.device_name).single();
2917
2874
  const singleDeviceId = singleDeviceRow?.id;
2918
- try {
2919
- const { error: singleFolderErr } = await supabase.from("claude_folders").update({
2920
- graph_json: result.graph,
2921
- orphans_json: result.orphans,
2922
- broken_refs_json: result.brokenRefs,
2923
- skills_table_json: result.skills,
2924
- stale_files_json: result.staleFiles,
2925
- last_scanned: result.scannedAt,
2926
- data_hash: result.dataHash
2927
- }).eq("id", device.folder_id);
2928
- if (singleFolderErr) {
2929
- console.log(chalk15.dim(`Debug: claude_folders update skipped (${singleFolderErr.message})`));
2930
- }
2931
- } catch (err) {
2932
- console.log(chalk15.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
2933
- }
2934
2875
  if (singleDeviceId) {
2935
2876
  await supabase.from("device_scans").upsert({
2936
2877
  folder_id: device.folder_id,
@@ -3618,7 +3559,7 @@ async function mcpWatchCommand() {
3618
3559
  if (hash === lastEnvHash)
3619
3560
  return;
3620
3561
  lastEnvHash = hash;
3621
- await supabase.from("claude_folders").update({ env_manifest_json: envManifest }).eq("id", state.lastFolderId);
3562
+ await supabase.from("device_scans").update({ env_manifest_json: envManifest }).eq("folder_id", state.lastFolderId).eq("device_id", deviceId);
3622
3563
  }
3623
3564
  await envCycle();
3624
3565
  envInterval = setInterval(envCycle, ENV_POLL_INTERVAL_MS);
@@ -3662,15 +3603,21 @@ async function checkPendingRescans(supabase, deviceId, deviceName) {
3662
3603
  continue;
3663
3604
  try {
3664
3605
  const result = await scanProject(dp.path);
3665
- await supabase.from("claude_folders").update({
3606
+ await supabase.from("device_scans").upsert({
3607
+ folder_id: folder.id,
3608
+ device_id: deviceId,
3609
+ user_id: (await supabase.auth.getUser()).data.user.id,
3666
3610
  graph_json: result.graph,
3667
3611
  orphans_json: result.orphans,
3668
- broken_refs_json: result.brokenRefs,
3669
3612
  skills_table_json: result.skills,
3670
3613
  stale_files_json: result.staleFiles,
3614
+ broken_refs_json: result.brokenRefs,
3671
3615
  env_manifest_json: result.envManifest,
3672
- last_scanned: result.scannedAt,
3673
3616
  data_hash: result.dataHash,
3617
+ scanned_at: result.scannedAt,
3618
+ cli_version: CURRENT_VERSION
3619
+ }, { onConflict: "folder_id,device_id" });
3620
+ await supabase.from("claude_folders").update({
3674
3621
  rescan_requested_at: null
3675
3622
  }).eq("id", folder.id);
3676
3623
  await pushToolings(supabase, folder.id, result.toolings, deviceId);
@@ -4129,25 +4076,6 @@ Linking "${folder.name}" to this device...
4129
4076
  console.log(` Env Vars: ${result.envManifest?.variables.length ?? 0} (${result.envManifest ? "manifest found" : "no manifest"})`);
4130
4077
  console.log(` Doppler: ${result.doppler ? `${result.doppler.configs.length} config(s) \u2014 ${result.doppler.project}` : "see above"}`);
4131
4078
  console.log(` Plugins: ${result.marketplacePlugins.length} (${result.marketplacePlugins.reduce((n, p) => n + p.skills.length, 0)} skills)`);
4132
- try {
4133
- const { error: scanErr } = await supabase.from("claude_folders").update({
4134
- graph_json: result.graph,
4135
- orphans_json: result.orphans,
4136
- broken_refs_json: result.brokenRefs,
4137
- skills_table_json: result.skills,
4138
- stale_files_json: result.staleFiles,
4139
- env_manifest_json: result.envManifest,
4140
- doppler_json: result.doppler,
4141
- marketplace_plugins_json: result.marketplacePlugins,
4142
- last_scanned: result.scannedAt,
4143
- data_hash: result.dataHash
4144
- }).eq("id", folder.id);
4145
- if (scanErr) {
4146
- console.log(chalk16.dim(`Debug: claude_folders update skipped (${scanErr.message})`));
4147
- }
4148
- } catch (err) {
4149
- console.log(chalk16.dim(`Debug: claude_folders update skipped (${err instanceof Error ? err.message : String(err)})`));
4150
- }
4151
4079
  await supabase.from("device_scans").upsert({
4152
4080
  folder_id: folder.id,
4153
4081
  device_id: deviceId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "md4ai",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "description": "CLI for MD4AI — scan Claude projects and sync to your dashboard",
5
5
  "type": "module",
6
6
  "bin": {