tokentracker-cli 0.77.2 → 0.78.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 (80) hide show
  1. package/README.de.md +21 -0
  2. package/README.md +21 -0
  3. package/dashboard/dist/assets/ActivityHeatmap-5352XxLR.js +42 -0
  4. package/dashboard/dist/assets/{Card-D_aKGDr7.js → Card-Ca_hYHhx.js} +1 -1
  5. package/dashboard/dist/assets/{ClawdAnimated-vRiBiNhb.js → ClawdAnimated-DSgOS5ND.js} +1 -1
  6. package/dashboard/dist/assets/{CommunityStatsModal-CjetJZ-5.js → CommunityStatsModal-o8uQVQxu.js} +1 -1
  7. package/dashboard/dist/assets/ConfirmModal-D1hi9XUf.js +1 -0
  8. package/dashboard/dist/assets/Controls-CwnKP56V.js +1 -0
  9. package/dashboard/dist/assets/DashboardPage-CDv0TIOL.js +19 -0
  10. package/dashboard/dist/assets/{DevicePage-YAo4ert4.js → DevicePage-BlfIHcZX.js} +1 -1
  11. package/dashboard/dist/assets/DialogClose-CismfYwe.js +1 -0
  12. package/dashboard/dist/assets/DialogDescription-DWKp1yez.js +1 -0
  13. package/dashboard/dist/assets/{DialogTitle-CA5znwms.js → DialogTitle-DuuTVbUb.js} +1 -1
  14. package/dashboard/dist/assets/{FadeIn--ff4ZbC-.js → FadeIn-DpnitRKo.js} +1 -1
  15. package/dashboard/dist/assets/{HeaderGithubStar-CTZvanhz.js → HeaderGithubStar-D6zy-ADl.js} +1 -1
  16. package/dashboard/dist/assets/{IpCheckPage-Bg47gNVu.js → IpCheckPage-yUNp0VNe.js} +1 -1
  17. package/dashboard/dist/assets/{LandingPage-DZ8Mz38n.js → LandingPage-BvmpAaVn.js} +1 -1
  18. package/dashboard/dist/assets/LeaderboardAvatar-2WTIeXye.js +1 -0
  19. package/dashboard/dist/assets/LeaderboardPage-Bq3-VO7w.js +2 -0
  20. package/dashboard/dist/assets/{LeaderboardProfileModal-CfVMENby.js → LeaderboardProfileModal-DH0EEK6q.js} +3 -3
  21. package/dashboard/dist/assets/{LeaderboardProfilePage-C4bGXJCE.js → LeaderboardProfilePage-uJAng2JE.js} +3 -3
  22. package/dashboard/dist/assets/{LimitsPage-BAQ10X55.js → LimitsPage-D8UohgJm.js} +2 -2
  23. package/dashboard/dist/assets/{LocalOnlyNotice-gtHCn7Mx.js → LocalOnlyNotice-Dv_BnDVV.js} +1 -1
  24. package/dashboard/dist/assets/{LoginPage-TXvIBzoW.js → LoginPage-D6b6DZU3.js} +1 -1
  25. package/dashboard/dist/assets/PetPage-DfpBkuCa.js +1 -0
  26. package/dashboard/dist/assets/{PopoverPopup-CQxxgUXk.js → PopoverPopup-CjzdZn-9.js} +1 -1
  27. package/dashboard/dist/assets/{ResetPasswordPage-tN0tmSfP.js → ResetPasswordPage-BnOCFkwe.js} +1 -1
  28. package/dashboard/dist/assets/Select-CHtQAiLD.js +1 -0
  29. package/dashboard/dist/assets/{SelectItemText-2LjzGvo5.js → SelectItemText-Vjqvf8wO.js} +1 -1
  30. package/dashboard/dist/assets/SettingsPage-B-iHGL4q.js +1 -0
  31. package/dashboard/dist/assets/SkillsPage-DtG2aV-q.js +1 -0
  32. package/dashboard/dist/assets/WidgetsPage-4kqTtWfK.js +1 -0
  33. package/dashboard/dist/assets/{WrappedPage-YxshTScX.js → WrappedPage-DMMRpani.js} +1 -1
  34. package/dashboard/dist/assets/agent-logos-D0vYkEpX.js +1 -0
  35. package/dashboard/dist/assets/{arrow-up-right-Bm3t-iA0.js → arrow-up-right-BAQYGZkR.js} +1 -1
  36. package/dashboard/dist/assets/check-C3RPBZiS.js +1 -0
  37. package/dashboard/dist/assets/{copy-DUNz-xWm.js → copy-gG_BLBs8.js} +1 -1
  38. package/dashboard/dist/assets/{download-COSLX73O.js → download-BQOcg3gT.js} +1 -1
  39. package/dashboard/dist/assets/{format-tokens-CR28AiQO.js → format-tokens-CGK6lQAf.js} +1 -1
  40. package/dashboard/dist/assets/{info-Cm7V_KDO.js → info-C_BrDrcq.js} +1 -1
  41. package/dashboard/dist/assets/{link-2-CYqDGrkv.js → link-2-DFwCBbIZ.js} +1 -1
  42. package/dashboard/dist/assets/{loader-circle-6XAdy2ec.js → loader-circle-BMFI_BJ8.js} +1 -1
  43. package/dashboard/dist/assets/main-Dy8Y_qst.css +1 -0
  44. package/dashboard/dist/assets/main-w0hAaCsy.js +1190 -0
  45. package/dashboard/dist/assets/{trash-2-DKLewOQb.js → trash-2-GeZ6IzgV.js} +1 -1
  46. package/dashboard/dist/assets/{use-community-stats-AdPaun74.js → use-community-stats-pC8cmVof.js} +1 -1
  47. package/dashboard/dist/assets/{use-limits-display-prefs-Bau4ykMw.js → use-limits-display-prefs-DnFpPcA3.js} +1 -1
  48. package/dashboard/dist/assets/use-native-settings-CvcOSUhn.js +1 -0
  49. package/dashboard/dist/assets/{use-ordered-list-BVaEJaWa.js → use-ordered-list-CbMroVZ8.js} +2 -2
  50. package/dashboard/dist/assets/{use-quality-per-dollar-pref-Htlc-uFe.js → use-quality-per-dollar-pref-Bn3Al6yX.js} +1 -1
  51. package/dashboard/dist/assets/{use-usage-limits-BnzWTJQS.js → use-usage-limits-D08q_Dr8.js} +1 -1
  52. package/dashboard/dist/assets/{useCurrency-bd6TLRsc.js → useCurrency-h3kqF52v.js} +1 -1
  53. package/dashboard/dist/assets/{useScrollLock-ajoWrfku.js → useScrollLock-9au2731u.js} +1 -1
  54. package/dashboard/dist/index.html +2 -2
  55. package/dashboard/dist/share.html +2 -2
  56. package/package.json +1 -1
  57. package/src/commands/status.js +119 -12
  58. package/src/commands/sync.js +158 -83
  59. package/src/lib/install-resolver.js +1 -0
  60. package/src/lib/local-api.js +202 -56
  61. package/src/lib/pricing/seed-snapshot.json +1 -1
  62. package/src/lib/rollout.js +18 -2
  63. package/dashboard/dist/assets/ActivityHeatmap-CH6m_ZJM.js +0 -42
  64. package/dashboard/dist/assets/ConfirmModal-C6bZw6FZ.js +0 -1
  65. package/dashboard/dist/assets/Controls-Cj22oGL3.js +0 -1
  66. package/dashboard/dist/assets/DashboardPage-DPxiQkQw.js +0 -19
  67. package/dashboard/dist/assets/DialogClose-hhTDeRp1.js +0 -1
  68. package/dashboard/dist/assets/DialogDescription-gxEpcUbJ.js +0 -1
  69. package/dashboard/dist/assets/LeaderboardAvatar-3T57GKKK.js +0 -1
  70. package/dashboard/dist/assets/LeaderboardPage-wP_yCU9I.js +0 -2
  71. package/dashboard/dist/assets/PetPage-Dj1jrxYe.js +0 -1
  72. package/dashboard/dist/assets/Select-DnbHYPS4.js +0 -1
  73. package/dashboard/dist/assets/SettingsPage-DosKS_L6.js +0 -1
  74. package/dashboard/dist/assets/SkillsPage-DaCJ25vT.js +0 -1
  75. package/dashboard/dist/assets/WidgetsPage-CCGemQVD.js +0 -1
  76. package/dashboard/dist/assets/agent-logos-SeuxwQsp.js +0 -1
  77. package/dashboard/dist/assets/check-D8Owfjyw.js +0 -1
  78. package/dashboard/dist/assets/main-BCstrDYE.js +0 -1172
  79. package/dashboard/dist/assets/main-BYdJ5vWR.css +0 -1
  80. package/dashboard/dist/assets/use-native-settings-CidwlprT.js +0 -1
@@ -67,17 +67,19 @@ const {
67
67
  probeWslDistros,
68
68
  } = require("../lib/rollout");
69
69
  const wsl = require("../lib/wsl-probe");
70
- const { getWslMode, isInvalidWslMode, shouldProbeWsl } = wsl;
70
+ const { getWslMode, isInvalidWslMode, shouldProbeWsl, discoverWslHome } = wsl;
71
71
  const { resolveInstallPaths } = require("../lib/install-resolver");
72
72
  const { probeGrokHookState, resolveGrokHome } = require("../lib/grok-hook");
73
73
 
74
74
  function formatResolvedPaths(paths, filename) {
75
75
  const active = [];
76
76
  if (paths.native) {
77
- active.push(`native: ${filename ? path.join(paths.native, filename) : paths.native}`);
77
+ const file = filename ? path.join(paths.native, filename) : paths.native;
78
+ try { if (fssync.existsSync(file)) active.push(`native: ${file}`); } catch (_e) {}
78
79
  }
79
80
  if (paths.wsl) {
80
- active.push(`WSL: ${filename ? path.join(paths.wsl, filename) : paths.wsl}`);
81
+ const file = filename ? path.join(paths.wsl, filename) : paths.wsl;
82
+ try { if (fssync.existsSync(file)) active.push(`WSL: ${file}`); } catch (_e) {}
81
83
  }
82
84
  return active;
83
85
  }
@@ -107,11 +109,11 @@ async function cmdStatus(argv = []) {
107
109
  const codeConfigPath = path.join(codeHome, "config.toml");
108
110
  const claudeSettingsPath = path.join(home, ".claude", "settings.json");
109
111
  const codebuddySettingsPath = path.join(
110
- process.env.CODEBUDDY_HOME || path.join(home, ".codebuddy"),
112
+ resolveCodebuddyHome(process.env) || path.join(home, ".codebuddy"),
111
113
  "settings.json",
112
114
  );
113
115
  const workbuddySettingsPath = path.join(
114
- process.env.WORKBUDDY_HOME || path.join(home, ".workbuddy"),
116
+ resolveWorkbuddyHome(process.env) || path.join(home, ".workbuddy"),
115
117
  "settings.json",
116
118
  );
117
119
  const geminiConfigDir = resolveGeminiConfigDir({ home, env: process.env });
@@ -226,7 +228,7 @@ async function cmdStatus(argv = []) {
226
228
  // CodeBuddy — passive scan only (no hooks). Surface the file count so
227
229
  // operators can confirm JSONL sessions and extension logs are discovered.
228
230
  const codebuddyHome = resolveCodebuddyHome(process.env);
229
- const codebuddyInstalled = fssync.existsSync(codebuddyHome);
231
+ const codebuddyInstalled = Boolean(codebuddyHome && fssync.existsSync(codebuddyHome));
230
232
  const codebuddyFiles = codebuddyInstalled
231
233
  ? resolveCodebuddyProjectFiles(process.env)
232
234
  : [];
@@ -234,7 +236,7 @@ async function cmdStatus(argv = []) {
234
236
  // WorkBuddy — passive scan (sibling Claude-Code fork). Surface both the
235
237
  // recursive JSONL count and SQLite fallback so operators can confirm coverage.
236
238
  const workbuddyHome = resolveWorkbuddyHome(process.env);
237
- const workbuddyInstalled = fssync.existsSync(workbuddyHome);
239
+ const workbuddyInstalled = Boolean(workbuddyHome && fssync.existsSync(workbuddyHome));
238
240
  const workbuddyFiles = workbuddyInstalled
239
241
  ? resolveWorkbuddyProjectFiles(process.env)
240
242
  : [];
@@ -256,7 +258,7 @@ async function cmdStatus(argv = []) {
256
258
 
257
259
  // Craft Agents — passive scan only (no hooks).
258
260
  const craftConfigDir = resolveCraftConfigDir(process.env);
259
- const craftInstalled = fssync.existsSync(craftConfigDir);
261
+ const craftInstalled = Boolean(craftConfigDir && fssync.existsSync(craftConfigDir));
260
262
  const craftFiles = craftInstalled ? resolveCraftSessionFiles(process.env) : [];
261
263
 
262
264
  // Kilo CLI (kilo.ai @kilocode/plugin) — passive scan of kilo.db.
@@ -299,6 +301,87 @@ async function cmdStatus(argv = []) {
299
301
  const zcodeInstalled = zcodeActive.length > 0;
300
302
  const zcodeDbPath = zcodeActive.join(" | ");
301
303
 
304
+ // OpenCode (JSON files + SQLite DB) — passive scan of storage/message/ and opencode.db.
305
+ const opencodeStorageNativeValue = process.env.OPENCODE_HOME || path.join(xdgDataHome, "opencode");
306
+ const wslOpencodeStorageDir = process.platform === "win32" && shouldProbeWsl(process.env)
307
+ ? discoverWslHome(".local/share/opencode")
308
+ : null;
309
+ const opencodeStoragePaths = resolveInstallPaths({
310
+ nativeValue: opencodeStorageNativeValue,
311
+ wslValue: wslOpencodeStorageDir,
312
+ });
313
+ const opencodeStorageActive = formatResolvedPaths(opencodeStoragePaths);
314
+
315
+ const opencodeDbNativeValue = process.env.OPENCODE_HOME || path.join(xdgDataHome, "opencode");
316
+ const wslOpencodeDbDir = process.platform === "win32" && shouldProbeWsl(process.env)
317
+ ? discoverWslHome(".local/share/opencode")
318
+ : null;
319
+ const opencodeDbPaths = resolveInstallPaths({
320
+ nativeValue: opencodeDbNativeValue,
321
+ wslValue: wslOpencodeDbDir,
322
+ });
323
+ const opencodeDbActive = formatResolvedPaths(opencodeDbPaths, "opencode.db");
324
+ const opencodeInstalled = opencodeStorageActive.length > 0 || opencodeDbActive.length > 0;
325
+
326
+ // Every Code (passive sessions scan)
327
+ const codePaths = resolveInstallPaths({
328
+ nativeValue: process.env.CODE_HOME || path.join(home, ".code"),
329
+ wslDir: ".code",
330
+ });
331
+ const codeActive = formatResolvedPaths(codePaths, "sessions");
332
+ const codeInstalled = codeActive.length > 0;
333
+
334
+ // Gemini CLI & Antigravity (shared home)
335
+ const geminiPaths = resolveInstallPaths({
336
+ nativeValue: process.env.GEMINI_HOME || path.join(home, ".gemini"),
337
+ wslDir: ".gemini",
338
+ });
339
+ const geminiActive = formatResolvedPaths(geminiPaths);
340
+ const geminiInstalledStatus = geminiActive.length > 0;
341
+
342
+ // Gemini CLI (passive sessions scan)
343
+ const geminiCliActive = formatResolvedPaths(geminiPaths, "tmp");
344
+ const geminiCliInstalled = geminiCliActive.length > 0;
345
+
346
+ // Antigravity (passive brains scan)
347
+ const antigravityActive = [];
348
+ if (geminiPaths.native) {
349
+ const dirs = [
350
+ path.join(geminiPaths.native, "antigravity", "brain"),
351
+ path.join(geminiPaths.native, "antigravity-ide", "brain"),
352
+ path.join(geminiPaths.native, "antigravity-cli", "brain"),
353
+ ];
354
+ if (dirs.some(d => { try { return fssync.existsSync(d); } catch (_) { return false; } })) {
355
+ antigravityActive.push(`native: ${geminiPaths.native}`);
356
+ }
357
+ }
358
+ if (geminiPaths.wsl) {
359
+ const dirs = [
360
+ path.join(geminiPaths.wsl, "antigravity", "brain"),
361
+ path.join(geminiPaths.wsl, "antigravity-ide", "brain"),
362
+ path.join(geminiPaths.wsl, "antigravity-cli", "brain"),
363
+ ];
364
+ if (dirs.some(d => { try { return fssync.existsSync(d); } catch (_) { return false; } })) {
365
+ antigravityActive.push(`WSL: ${geminiPaths.wsl}`);
366
+ }
367
+ }
368
+ const antigravityInstalled = antigravityActive.length > 0;
369
+
370
+ // Codex CLI (passive sessions scan)
371
+ const codexPaths = resolveInstallPaths({
372
+ nativeValue: process.env.CODEX_HOME || path.join(home, ".codex"),
373
+ wslDir: ".codex",
374
+ });
375
+ const codexActive = formatResolvedPaths(codexPaths, "sessions");
376
+ const codexInstalledStatus = codexActive.length > 0;
377
+
378
+ // Kimi (passive sessions scan)
379
+ const kimiPaths = resolveInstallPaths({
380
+ nativeValue: path.join(home, ".kimi"),
381
+ wslDir: ".kimi",
382
+ });
383
+ const kimiActive = formatResolvedPaths(kimiPaths, "sessions");
384
+
302
385
  // Kilo Code VS Code extension — passive scan of all VS Code-family
303
386
  // globalStorage/kilocode.kilo-code/tasks/ ui_messages.json files.
304
387
  const kilocodeTaskFiles = resolveKilocodeTaskFiles(process.env);
@@ -340,9 +423,15 @@ async function cmdStatus(argv = []) {
340
423
  // install / WSL auto-discovery. Surface the resolved path (UNC included) and,
341
424
  // on Windows, the discovered distros so WSL users can debug "why no sync"
342
425
  // without guessing the right UNC alias (#87).
343
- const hermesPath = resolveHermesPath();
344
- const hermesDbPath = resolveHermesDbPath();
345
- const hermesInstalled = Boolean(hermesDbPath && fssync.existsSync(hermesDbPath));
426
+ const hermesPaths = resolveInstallPaths({
427
+ nativeValue: process.env.TOKENTRACKER_HERMES_HOME || (process.platform === "win32" && typeof process.env.LOCALAPPDATA === "string"
428
+ ? path.join(process.env.LOCALAPPDATA.trim(), "hermes")
429
+ : path.join(home, ".hermes")),
430
+ wslDir: ".hermes",
431
+ });
432
+ const hermesActive = formatResolvedPaths(hermesPaths, "state.db");
433
+ const hermesInstalled = hermesActive.length > 0;
434
+ const hermesPath = hermesActive.join(" | ");
346
435
  const wslDistros = process.platform === "win32" && shouldProbeWsl(process.env) ? probeWslDistros() : [];
347
436
 
348
437
  const copilotToken = readCopilotOauthToken({ home });
@@ -634,7 +723,7 @@ async function cmdStatus(argv = []) {
634
723
  `- OpenClaw session plugin conversation access: ${openclawSessionPluginState?.conversationAccess ? "set" : "unset"}`,
635
724
  `- OpenClaw hook (legacy): ${openclawHookState?.configured ? "set" : "unset"}`,
636
725
  kimiInstalled || kimiCodeInstalled
637
- ? `- Kimi Code: passive reader (${kimiWireFiles.length + kimiCodeWireFiles.length} wire.jsonl file${(kimiWireFiles.length + kimiCodeWireFiles.length) !== 1 ? "s" : ""} found)`
726
+ ? `- Kimi Code: passive reader (${kimiWireFiles.length + kimiCodeWireFiles.length} wire.jsonl file${(kimiWireFiles.length + kimiCodeWireFiles.length) !== 1 ? "s" : ""} found, directories: ${kimiActive.join(" | ") || "none"})`
638
727
  : null,
639
728
  kiroCliInstalled
640
729
  ? `- Kiro CLI: SQLite data.sqlite3 found (tokens approximated from char lengths, merged under 'kiro' source)`
@@ -663,6 +752,24 @@ async function cmdStatus(argv = []) {
663
752
  zcodeInstalled
664
753
  ? `- ZCode: passive reader (${zcodeDbPath})`
665
754
  : null,
755
+ opencodeInstalled
756
+ ? `- OpenCode: passive reader (storage: ${opencodeStorageActive.join(" | ") || "not found"}, DB: ${opencodeDbActive.join(" | ") || "not found"})`
757
+ : null,
758
+ codeInstalled
759
+ ? `- Every Code: sessions found (${codeActive.join(" | ")})`
760
+ : null,
761
+ geminiCliInstalled
762
+ ? `- Gemini CLI: sessions found (${geminiCliActive.join(" | ")})`
763
+ : null,
764
+ antigravityInstalled
765
+ ? `- Antigravity: brain found (${antigravityActive.join(" | ")})`
766
+ : null,
767
+ (!geminiCliInstalled && !antigravityInstalled && geminiInstalledStatus)
768
+ ? `- Gemini CLI / Antigravity: home found (${geminiActive.join(" | ")})`
769
+ : null,
770
+ codexInstalledStatus
771
+ ? `- Codex CLI: sessions found (${codexActive.join(" | ")})`
772
+ : null,
666
773
  kilocodeInstalled
667
774
  ? `- Kilo Code (VS Code extension): passive reader (${kilocodeTaskFiles.length} task${kilocodeTaskFiles.length !== 1 ? "s" : ""} across ${new Set(kilocodeTaskFiles.map((t) => t.ide)).size} IDE${new Set(kilocodeTaskFiles.map((t) => t.ide)).size !== 1 ? "s" : ""})`
668
775
  : null,
@@ -313,14 +313,8 @@ async function cmdSync(argv) {
313
313
  }
314
314
  let grokHookSignalConsumed = false;
315
315
 
316
- const codexHome = process.env.CODEX_HOME || path.join(home, ".codex");
317
- const codeHome = process.env.CODE_HOME || path.join(home, ".code");
318
316
  const claudeProjectsDir = path.join(home, ".claude", "projects");
319
- const geminiHome = process.env.GEMINI_HOME || path.join(home, ".gemini");
320
- const geminiTmpDir = path.join(geminiHome, "tmp");
321
317
  const xdgDataHome = process.env.XDG_DATA_HOME || path.join(home, ".local", "share");
322
- const opencodeHome = process.env.OPENCODE_HOME || path.join(xdgDataHome, "opencode");
323
- const opencodeStorageDir = path.join(opencodeHome, "storage");
324
318
  const kiloHome = process.env.KILO_HOME || path.join(xdgDataHome, "kilo");
325
319
  const mimoHome = process.env.MIMO_HOME || path.join(xdgDataHome, "mimocode");
326
320
  const zcodeHome = process.env.ZCODE_HOME || path.join(home, ".zcode");
@@ -347,22 +341,36 @@ async function cmdSync(argv) {
347
341
 
348
342
  const sources = [];
349
343
  if (sourceAllowed("codex")) {
350
- sources.push({ source: "codex", sessionsDir: path.join(codexHome, "sessions"), codexInventoryCache: true });
351
- if (!isBackgroundLightweightSync) {
352
- sources.push(
353
- // Codex-Manager archives sessions to ~/.codex/archived_sessions/ on every
354
- // account/channel switch (issue #187). Scanning it too keeps that usage
355
- // counted instead of orphaning it in the cloud (a re-upload's upsert can
356
- // never delete cloud rows whose local source file has vanished). Safe
357
- // against double-counting: the codex event dedup keys on sessionUUID (in
358
- // the filename) + event timestamp, both stable across a sessions/ ->
359
- // archived_sessions/ move, so re-reading an archived copy is a no-op.
360
- { source: "codex", sessionsDir: path.join(codexHome, "archived_sessions"), deep: true },
361
- );
344
+ const codexNativeValue = process.env.CODEX_HOME || path.join(home, ".codex");
345
+ const wslCodexDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
346
+ ? wsl.discoverWslHome(".codex")
347
+ : null;
348
+ const codexPaths = resolveInstallPaths({ nativeValue: codexNativeValue, wslValue: wslCodexDir });
349
+ if (codexPaths.native) {
350
+ sources.push({ source: "codex", sessionsDir: path.join(codexPaths.native, "sessions"), codexInventoryCache: true });
351
+ if (!isBackgroundLightweightSync) {
352
+ sources.push({ source: "codex", sessionsDir: path.join(codexPaths.native, "archived_sessions"), deep: true });
353
+ }
354
+ }
355
+ if (codexPaths.wsl) {
356
+ sources.push({ source: "codex", sessionsDir: path.join(codexPaths.wsl, "sessions"), codexInventoryCache: true });
357
+ if (!isBackgroundLightweightSync) {
358
+ sources.push({ source: "codex", sessionsDir: path.join(codexPaths.wsl, "archived_sessions"), deep: true });
359
+ }
362
360
  }
363
361
  }
364
362
  if (sourceAllowed("every-code")) {
365
- sources.push({ source: "every-code", sessionsDir: path.join(codeHome, "sessions") });
363
+ const codeNativeValue = process.env.CODE_HOME || path.join(home, ".code");
364
+ const wslCodeDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
365
+ ? wsl.discoverWslHome(".code")
366
+ : null;
367
+ const codePaths = resolveInstallPaths({ nativeValue: codeNativeValue, wslValue: wslCodeDir });
368
+ if (codePaths.native) {
369
+ sources.push({ source: "every-code", sessionsDir: path.join(codePaths.native, "sessions") });
370
+ }
371
+ if (codePaths.wsl) {
372
+ sources.push({ source: "every-code", sessionsDir: path.join(codePaths.wsl, "sessions") });
373
+ }
366
374
  }
367
375
 
368
376
  const rolloutFiles = [];
@@ -532,7 +540,34 @@ async function cmdSync(argv) {
532
540
  }
533
541
  }
534
542
 
535
- const geminiFiles = sourceAllowed("gemini") ? await listGeminiSessionFiles(geminiTmpDir) : [];
543
+ let geminiPaths = null;
544
+ if (sourceAllowed("gemini") || sourceAllowed("antigravity")) {
545
+ const geminiNativeValue = process.env.GEMINI_HOME || path.join(home, ".gemini");
546
+ const wslGeminiDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
547
+ ? wsl.discoverWslHome(".gemini")
548
+ : null;
549
+ geminiPaths = resolveInstallPaths({ nativeValue: geminiNativeValue, wslValue: wslGeminiDir });
550
+ }
551
+
552
+ let geminiFiles = [];
553
+ if (sourceAllowed("gemini") && geminiPaths) {
554
+ const fileSets = [];
555
+ if (geminiPaths.native) {
556
+ fileSets.push(await listGeminiSessionFiles(path.join(geminiPaths.native, "tmp")));
557
+ }
558
+ if (geminiPaths.wsl) {
559
+ fileSets.push(await listGeminiSessionFiles(path.join(geminiPaths.wsl, "tmp")));
560
+ }
561
+ const seen = new Set();
562
+ for (const set of fileSets) {
563
+ for (const f of set) {
564
+ if (!seen.has(f)) {
565
+ seen.add(f);
566
+ geminiFiles.push(f);
567
+ }
568
+ }
569
+ }
570
+ }
536
571
  let geminiResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
537
572
  if (geminiFiles.length > 0) {
538
573
  if (progress?.enabled) {
@@ -562,7 +597,25 @@ async function cmdSync(argv) {
562
597
  }
563
598
  }
564
599
 
565
- const antigravityFiles = sourceAllowed("antigravity") ? await listAntigravityTranscripts(geminiHome) : [];
600
+ let antigravityFiles = [];
601
+ if (sourceAllowed("antigravity") && geminiPaths) {
602
+ const fileSets = [];
603
+ if (geminiPaths.native) {
604
+ fileSets.push(await listAntigravityTranscripts(geminiPaths.native));
605
+ }
606
+ if (geminiPaths.wsl) {
607
+ fileSets.push(await listAntigravityTranscripts(geminiPaths.wsl));
608
+ }
609
+ const seen = new Set();
610
+ for (const set of fileSets) {
611
+ for (const f of set) {
612
+ if (!seen.has(f)) {
613
+ seen.add(f);
614
+ antigravityFiles.push(f);
615
+ }
616
+ }
617
+ }
618
+ }
566
619
  let antigravityResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
567
620
  if (antigravityFiles.length > 0) {
568
621
  if (progress?.enabled) {
@@ -592,69 +645,89 @@ async function cmdSync(argv) {
592
645
  }
593
646
  }
594
647
 
595
- const opencodeFiles = sourceAllowed("opencode") ? await listOpencodeMessageFiles(opencodeStorageDir) : [];
596
648
  let opencodeResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
597
- if (opencodeFiles.length > 0) {
598
- if (progress?.enabled) {
599
- progress.start(
600
- `Parsing Opencode ${renderBar(0)} 0/${formatNumber(opencodeFiles.length)} files | buckets 0`,
601
- );
602
- }
603
- try {
604
- opencodeResult = await parseOpencodeIncremental({
605
- messageFiles: opencodeFiles,
606
- cursors,
607
- queuePath,
608
- projectQueuePath,
609
- onProgress: (p) => {
610
- if (!progress?.enabled) return;
611
- const pct = p.total > 0 ? p.index / p.total : 1;
612
- progress.update(
613
- `Parsing Opencode ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(
614
- p.total,
615
- )} files | buckets ${formatNumber(p.bucketsQueued)}`,
616
- );
617
- },
618
- source: "opencode",
619
- });
620
- } catch (err) {
621
- warnProviderParseFailure("Opencode", err, opts);
622
- }
623
- }
649
+ if (sourceAllowed("opencode")) {
650
+ const opencodeStorageNativeValue = process.env.OPENCODE_HOME || path.join(xdgDataHome, "opencode");
651
+ const wslOpencodeStorageDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
652
+ ? wsl.discoverWslHome(".local/share/opencode")
653
+ : null;
654
+ const storagePaths = resolveInstallPaths({
655
+ nativeValue: opencodeStorageNativeValue,
656
+ wslValue: wslOpencodeStorageDir,
657
+ });
624
658
 
625
- // OpenCode v1.2+ stores messages in SQLite (opencode.db) instead of JSON files.
626
- const opencodeDbPath = path.join(opencodeHome, "opencode.db");
627
- let opencodeDbResult = { messagesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
628
- const dbMessages = sourceAllowed("opencode") ? readOpencodeDbMessages(opencodeDbPath) : [];
629
- if (dbMessages.length > 0) {
630
- if (progress?.enabled) {
631
- progress.start(
632
- `Parsing Opencode DB ${renderBar(0)} 0/${formatNumber(dbMessages.length)} msgs | buckets 0`,
633
- );
634
- }
635
- try {
636
- opencodeDbResult = await parseOpencodeDbIncremental({
637
- dbMessages,
638
- cursors,
639
- queuePath,
640
- projectQueuePath,
641
- onProgress: (p) => {
642
- if (!progress?.enabled) return;
643
- const pct = p.total > 0 ? p.index / p.total : 1;
644
- progress.update(
645
- `Parsing Opencode DB ${renderBar(pct)} ${formatNumber(p.index)}/${formatNumber(
646
- p.total,
647
- )} msgs | buckets ${formatNumber(p.bucketsQueued)}`,
648
- );
649
- },
650
- source: "opencode",
651
- });
652
- } catch (err) {
653
- warnProviderParseFailure("Opencode DB", err, opts);
654
- }
655
- opencodeResult.filesProcessed += opencodeDbResult.messagesProcessed;
656
- opencodeResult.eventsAggregated += opencodeDbResult.eventsAggregated;
657
- opencodeResult.bucketsQueued += opencodeDbResult.bucketsQueued;
659
+ const opencodeDbNativeValue = process.env.OPENCODE_HOME || path.join(xdgDataHome, "opencode");
660
+ const wslOpencodeDbDir = process.platform === "win32" && wsl.shouldProbeWsl(process.env)
661
+ ? wsl.discoverWslHome(".local/share/opencode")
662
+ : null;
663
+ const dbPaths = resolveInstallPaths({
664
+ nativeValue: opencodeDbNativeValue,
665
+ wslValue: wslOpencodeDbDir,
666
+ });
667
+
668
+ const parseOpencodeForInstall = async (options) => {
669
+ const { storageDir, dbDir, cursors } = options;
670
+ let filesResult = { filesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
671
+ if (storageDir) {
672
+ const storagePath = path.join(storageDir, "storage");
673
+ const messageFiles = await listOpencodeMessageFiles(storagePath);
674
+ if (messageFiles.length > 0) {
675
+ filesResult = await parseOpencodeIncremental({
676
+ ...options,
677
+ messageFiles,
678
+ });
679
+ }
680
+ }
681
+
682
+ let dbResult = { messagesProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
683
+ if (dbDir) {
684
+ const dbPath = path.join(dbDir, "opencode.db");
685
+ const dbMessages = readOpencodeDbMessages(dbPath);
686
+ if (dbMessages.length > 0) {
687
+ dbResult = await parseOpencodeDbIncremental({
688
+ ...options,
689
+ dbMessages,
690
+ });
691
+ }
692
+ }
693
+
694
+ return {
695
+ recordsProcessed: filesResult.filesProcessed + dbResult.messagesProcessed,
696
+ eventsAggregated: filesResult.eventsAggregated + dbResult.eventsAggregated,
697
+ bucketsQueued: filesResult.bucketsQueued + dbResult.bucketsQueued,
698
+ };
699
+ };
700
+
701
+ const opencodePaths = {
702
+ native: storagePaths.native || dbPaths.native,
703
+ wsl: storagePaths.wsl || dbPaths.wsl,
704
+ };
705
+
706
+ const multiResult = await multiInstallParse({
707
+ paths: opencodePaths,
708
+ parserFn: parseOpencodeForInstall,
709
+ providerName: "opencode",
710
+ cursors,
711
+ queuePath,
712
+ projectQueuePath,
713
+ getParams: (p, key) => ({ storageDir: storagePaths[key], dbDir: dbPaths[key] }),
714
+ onProgress: (p) => {
715
+ if (!progress?.enabled) return;
716
+ const pct = p.total > 0 ? p.index / p.total : 1;
717
+ progress.update(
718
+ `Parsing Opencode (${p.install || "default"}) ${renderBar(pct)} ${formatNumber(
719
+ p.index,
720
+ )}/${formatNumber(p.total)} | buckets ${formatNumber(p.bucketsQueued)}`,
721
+ );
722
+ },
723
+ source: "opencode",
724
+ });
725
+
726
+ opencodeResult = {
727
+ filesProcessed: multiResult.recordsProcessed,
728
+ eventsAggregated: multiResult.eventsAggregated,
729
+ bucketsQueued: multiResult.bucketsQueued,
730
+ };
658
731
  }
659
732
 
660
733
  async function parseOpencodeDbForInstall({ dbPath, readFn, source, cursorKey, ...rest }) {
@@ -1097,7 +1170,9 @@ async function cmdSync(argv) {
1097
1170
 
1098
1171
  // ── Kimi (passive wire.jsonl reader) ──
1099
1172
  let kimiResult = { recordsProcessed: 0, eventsAggregated: 0, bucketsQueued: 0 };
1100
- const kimiWireFiles = sourceAllowed("kimi") ? resolveKimiWireFiles(process.env) : [];
1173
+ const kimiWireFiles = sourceAllowed("kimi")
1174
+ ? mergeBothFileSources({ resolveFiles: resolveKimiWireFiles, env: process.env })
1175
+ : [];
1101
1176
  if (kimiWireFiles.length > 0) {
1102
1177
  if (progress?.enabled) {
1103
1178
  progress.start(`Parsing Kimi Code ${renderBar(0)} | buckets 0`);
@@ -16,6 +16,7 @@ function resolveInstallPaths({ nativeValue, wslDir, wslValue } = {}, env = proce
16
16
  }
17
17
 
18
18
  function pathExists(p, existsSync) {
19
+ if (typeof p !== "string" || !p) return null;
19
20
  try { return (existsSync || fssync.existsSync)(p) ? p : null; } catch (_e) { return null; }
20
21
  }
21
22