tokmon 0.28.2 → 0.28.4

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 (56) hide show
  1. package/README.md +156 -234
  2. package/THIRD_PARTY_NOTICES.md +62 -0
  3. package/dist/{bootstrap-ink-IMT3S5HU.js → bootstrap-ink-WG4WG3R2.js} +1579 -1136
  4. package/dist/chunk-5B3XCEMC.js +294 -0
  5. package/dist/chunk-7CH6S7BR.js +447 -0
  6. package/dist/{chunk-LCAHTRGP.js → chunk-CFKUZCMB.js} +56 -29
  7. package/dist/{chunk-LKYOWBD4.js → chunk-FLANGRI6.js} +21 -42
  8. package/dist/chunk-HNWEJ6MS.js +1094 -0
  9. package/dist/{chunk-WUK3MQUB.js → chunk-JZSZEHVD.js} +167 -10
  10. package/dist/{chunk-6ZEW2M6P.js → chunk-P57DVFNH.js} +125 -25
  11. package/dist/chunk-TN6V7XSL.js +512 -0
  12. package/dist/chunk-UYPDMVW5.js +21 -0
  13. package/dist/{cli-command-DCENRCO3.js → cli-command-I4GRR3MF.js} +249 -15
  14. package/dist/cli.js +6 -6
  15. package/dist/{config-HXFJTNLM.js → config-3DGZ47F7.js} +23 -3
  16. package/dist/daemon-ZXV3V5CS.js +384 -0
  17. package/dist/daemon-handle-G4OGPFR3.js +11 -0
  18. package/dist/server-EPSH52DR.js +12 -0
  19. package/dist/web/assets/{Area-CMXvOw33.js → Area-stRnp8Km.js} +1 -1
  20. package/dist/web/assets/analytics-moZZt9L_.js +2 -0
  21. package/dist/web/assets/breakdown-km9w7myU.js +4 -0
  22. package/dist/web/assets/button-DrX04Cc2.js +1 -0
  23. package/dist/web/assets/{chart-cZoLgpmG.js → chart-D0CtuL2k.js} +1 -1
  24. package/dist/web/assets/explore-B11uNJV1.js +22 -0
  25. package/dist/web/assets/index-RDhXsCNG.js +83 -0
  26. package/dist/web/assets/index-ZmOS8p9O.css +1 -0
  27. package/dist/web/assets/models-DYbZnY34.js +2 -0
  28. package/dist/web/assets/overview-CruICbfJ.js +2 -0
  29. package/dist/web/assets/panel-xckM3_GC.js +1 -0
  30. package/dist/web/assets/settings-sheet-G-BTSIF6.js +1 -0
  31. package/dist/web/assets/share-sheet-weIdd4DW.js +2 -0
  32. package/dist/web/assets/timeline-BHgniliZ.js +1 -0
  33. package/dist/web/index.html +30 -4
  34. package/package.json +13 -4
  35. package/site/THIRD_PARTY_NOTICES.md +83 -0
  36. package/site/public/fonts/OFL.txt +93 -0
  37. package/dist/chunk-44ZSQEOS.js +0 -299
  38. package/dist/chunk-HP5UZCXP.js +0 -436
  39. package/dist/chunk-J3JW3RFP.js +0 -196
  40. package/dist/chunk-M7XMV36F.js +0 -275
  41. package/dist/daemon-6Y4O7NXS.js +0 -241
  42. package/dist/daemon-handle-GVCYVDPO.js +0 -10
  43. package/dist/server-GXXOWUVZ.js +0 -11
  44. package/dist/web/assets/analytics-DqdZXOJL.js +0 -2
  45. package/dist/web/assets/breakdown-kOSSJ3mI.js +0 -4
  46. package/dist/web/assets/explore-vcsM8K9I.js +0 -22
  47. package/dist/web/assets/index-BErCXT7f.css +0 -1
  48. package/dist/web/assets/index-DH3dOnbg.js +0 -83
  49. package/dist/web/assets/models-B5ikm83_.js +0 -2
  50. package/dist/web/assets/overview-DD1kP8CP.js +0 -2
  51. package/dist/web/assets/panel-DTQBwExW.js +0 -1
  52. package/dist/web/assets/primitives-C36qJlA2.js +0 -1
  53. package/dist/web/assets/settings-sheet-_i2zTQjf.js +0 -1
  54. package/dist/web/assets/share-sheet-BLHmrFbm.js +0 -2
  55. package/dist/web/assets/timeline-B4uG-Emo.js +0 -1
  56. package/dist/web/assets/use-dialog-trap-bfaXEMz9.js +0 -1
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  attachOrSpawn
4
- } from "./chunk-LKYOWBD4.js";
5
- import "./chunk-J3JW3RFP.js";
4
+ } from "./chunk-FLANGRI6.js";
5
+ import "./chunk-5B3XCEMC.js";
6
+ import "./chunk-UYPDMVW5.js";
6
7
  import {
7
8
  createDaemonRpcClient
8
- } from "./chunk-M7XMV36F.js";
9
+ } from "./chunk-7CH6S7BR.js";
9
10
  import {
10
11
  PROVIDERS,
11
12
  antigravityStateDb,
@@ -25,12 +26,13 @@ import {
25
26
  startOfMonth,
26
27
  startOfWeek,
27
28
  withTimeout
28
- } from "./chunk-LCAHTRGP.js";
29
- import "./chunk-WUK3MQUB.js";
29
+ } from "./chunk-CFKUZCMB.js";
30
+ import "./chunk-JZSZEHVD.js";
30
31
  import {
32
+ DESKTOP_GRAPH_RANGES,
31
33
  PROVIDER_IDS,
32
34
  configLocation
33
- } from "./chunk-HP5UZCXP.js";
35
+ } from "./chunk-HNWEJ6MS.js";
34
36
 
35
37
  // src/provider-locations.ts
36
38
  import { access } from "fs/promises";
@@ -133,7 +135,7 @@ async function cliSource(account) {
133
135
  providerId: account.providerId,
134
136
  provider: PROVIDERS[account.providerId].name,
135
137
  accountId: account.id,
136
- account: account.email || account.displayName || account.name,
138
+ account: account.identity?.accessibleLabel ?? (account.email || account.displayName || account.name),
137
139
  homeDir: account.homeDir,
138
140
  locations: await providerLocations(account.providerId, account.homeDir ?? void 0)
139
141
  };
@@ -341,15 +343,38 @@ Options:
341
343
  --timeout <seconds> Startup/refresh timeout (default: 45)
342
344
  -h, --help Show this help
343
345
  `;
344
- var CONFIG_HELP = `tokmon config - Print tokmon's configuration file location
346
+ var CONFIG_HELP = `tokmon config - Read and update tokmon settings
345
347
 
346
348
  Usage:
347
349
  tokmon config [path]
348
350
  tokmon config --json
351
+ tokmon config get [--json]
352
+ tokmon config set <setting> <value> [--json]
353
+
354
+ Settings:
355
+ privacy <on|off>
356
+ privacy-key <char>
357
+ menu-bar-pins <ids|none> Comma-separated provider ids; at most 2
358
+ menu-bar-text <on|off>
359
+ summary-mode <smart|tightest>
360
+ expanded-providers <ids|none> Comma-separated provider ids
361
+ active-window <minutes> 1..1440
362
+ graph-range <7|14|30> Desktop spend graph days
363
+ auto-detect <on|off> Automatic account discovery
364
+ auto-detect-providers <ids|none>
365
+ launch-at-login <on|off>
349
366
 
350
367
  Options:
351
- --json Emit { "path": "..." }
368
+ --json Emit machine-readable JSON
369
+ --compact Emit compact JSON
370
+ --timeout <seconds> Daemon connection timeout (default: 45)
352
371
  -h, --help Show this help
372
+
373
+ Examples:
374
+ tokmon config get
375
+ tokmon config set privacy off
376
+ tokmon config set menu-bar-pins claude,codex
377
+ tokmon config set summary-mode smart --json
353
378
  `;
354
379
  function valueAfter(args, index, name) {
355
380
  const value = args[index + 1];
@@ -430,6 +455,15 @@ function isSnapshot(value) {
430
455
  var delay = (ms) => new Promise((resolve) => {
431
456
  setTimeout(resolve, ms);
432
457
  });
458
+ async function connectDaemonConfig(timeoutMs) {
459
+ const handle = await attachOrSpawn({ timeoutMs });
460
+ if (handle.kind !== "spawned" || !handle.baseUrl) throw new Error("tokmon daemon is unavailable");
461
+ return createDaemonRpcClient(handle.baseUrl, {
462
+ transport: "node",
463
+ reconnectAttempts: 2,
464
+ reconnectBaseDelayMs: 100
465
+ });
466
+ }
433
467
  async function fetchDaemonSnapshot(timeoutMs, refresh) {
434
468
  const handle = await attachOrSpawn({ timeoutMs });
435
469
  if (handle.kind !== "spawned" || !handle.baseUrl) throw new Error("tokmon daemon is unavailable");
@@ -475,6 +509,209 @@ function rejectsOption(args, names) {
475
509
  }
476
510
  return null;
477
511
  }
512
+ var CONFIG_SETTINGS = [
513
+ "privacy",
514
+ "privacy-key",
515
+ "menu-bar-pins",
516
+ "menu-bar-text",
517
+ "summary-mode",
518
+ "expanded-providers",
519
+ "active-window",
520
+ "graph-range",
521
+ "auto-detect",
522
+ "auto-detect-providers",
523
+ "launch-at-login"
524
+ ];
525
+ function configReport(config) {
526
+ return {
527
+ revision: config.revision,
528
+ privacy: config.privacyMode ? "on" : "off",
529
+ privacyKey: config.privacyToggleKey,
530
+ menuBarPins: [...config.tray.pinnedProviders],
531
+ menuBarText: config.tray.showMenuBarText ? "on" : "off",
532
+ summaryMode: config.tray.displayMetric === "smartHeadroom" ? "smart" : "tightest",
533
+ expandedProviders: [...config.desktop.expandedProviders],
534
+ activeWindowMinutes: config.tray.activeTimeoutMin,
535
+ graphRangeDays: config.desktop.graphRangeDays,
536
+ autoDetect: config.accountDetection.enabled ? "on" : "off",
537
+ autoDetectProviders: PROVIDER_IDS.filter((id) => !config.accountDetection.disabledProviders.includes(id)),
538
+ launchAtLogin: config.tray.launchAtLogin ? "on" : "off"
539
+ };
540
+ }
541
+ function formatConfigReport(report) {
542
+ const list = (values) => values.length > 0 ? values.join(",") : "none";
543
+ return [
544
+ `privacy ${report.privacy}`,
545
+ `privacy-key ${report.privacyKey}`,
546
+ `menu-bar-pins ${list(report.menuBarPins)}`,
547
+ `menu-bar-text ${report.menuBarText}`,
548
+ `summary-mode ${report.summaryMode}`,
549
+ `expanded-providers ${list(report.expandedProviders)}`,
550
+ `active-window ${report.activeWindowMinutes}m`,
551
+ `graph-range ${report.graphRangeDays}d`,
552
+ `auto-detect ${report.autoDetect}`,
553
+ `auto-detect-providers ${list(report.autoDetectProviders)}`,
554
+ `launch-at-login ${report.launchAtLogin}`
555
+ ].join("\n") + "\n";
556
+ }
557
+ function onOff(value, setting) {
558
+ if (value === "on") return true;
559
+ if (value === "off") return false;
560
+ throw new Error(`${setting} must be on or off`);
561
+ }
562
+ function providerList(value, setting, max = PROVIDER_IDS.length) {
563
+ if (value === "none") return [];
564
+ const raw = value.split(",").map((item) => item.trim());
565
+ if (raw.length === 0 || raw.some((item) => item.length === 0)) {
566
+ throw new Error(`${setting} must be a comma-separated provider list or none`);
567
+ }
568
+ const unique2 = [...new Set(raw)];
569
+ for (const provider of unique2) {
570
+ if (!PROVIDER_IDS.includes(provider)) throw new Error(`unknown provider: ${provider}`);
571
+ }
572
+ if (unique2.length > max) throw new Error(`${setting} accepts at most ${max} providers`);
573
+ return unique2;
574
+ }
575
+ function settingMutation(setting, value) {
576
+ if (setting === "privacy") {
577
+ const enabled2 = onOff(value, setting);
578
+ return { mutate: (config) => ({ ...config, privacyMode: enabled2 }), display: value };
579
+ }
580
+ if (setting === "privacy-key") {
581
+ if (value.length !== 1 || new RegExp("\\s|\\p{Cc}", "u").test(value)) throw new Error("privacy-key must be one printable non-whitespace character");
582
+ return { mutate: (config) => ({ ...config, privacyToggleKey: value }), display: value };
583
+ }
584
+ if (setting === "menu-bar-pins") {
585
+ const providers = providerList(value, setting, 2);
586
+ return {
587
+ mutate: (config) => ({
588
+ ...config,
589
+ tray: { ...config.tray, pinnedProviders: providers, pins: [], pinnedAccount: null }
590
+ }),
591
+ display: providers
592
+ };
593
+ }
594
+ if (setting === "menu-bar-text") {
595
+ const enabled2 = onOff(value, setting);
596
+ return { mutate: (config) => ({ ...config, tray: { ...config.tray, showMenuBarText: enabled2 } }), display: value };
597
+ }
598
+ if (setting === "summary-mode") {
599
+ if (value !== "smart" && value !== "tightest") throw new Error("summary-mode must be smart or tightest");
600
+ const displayMetric = value === "smart" ? "smartHeadroom" : "tightestRemaining";
601
+ return { mutate: (config) => ({ ...config, tray: { ...config.tray, displayMetric } }), display: value };
602
+ }
603
+ if (setting === "expanded-providers") {
604
+ const providers = providerList(value, setting);
605
+ return {
606
+ mutate: (config) => ({ ...config, desktop: { ...config.desktop, expandedProviders: providers } }),
607
+ display: providers
608
+ };
609
+ }
610
+ if (setting === "active-window") {
611
+ const minutes = Number(value);
612
+ if (!Number.isInteger(minutes) || minutes < 1 || minutes > 1440) throw new Error("active-window must be an integer from 1 to 1440 minutes");
613
+ return { mutate: (config) => ({ ...config, tray: { ...config.tray, activeTimeoutMin: minutes } }), display: minutes };
614
+ }
615
+ if (setting === "graph-range") {
616
+ const days = Number(value);
617
+ if (!DESKTOP_GRAPH_RANGES.includes(days)) throw new Error("graph-range must be 7, 14, or 30 days");
618
+ return {
619
+ mutate: (config) => ({ ...config, desktop: { ...config.desktop, graphRangeDays: days } }),
620
+ display: days
621
+ };
622
+ }
623
+ if (setting === "auto-detect") {
624
+ const enabled2 = onOff(value, setting);
625
+ return {
626
+ mutate: (config) => ({ ...config, accountDetection: { ...config.accountDetection, enabled: enabled2 } }),
627
+ display: value
628
+ };
629
+ }
630
+ if (setting === "auto-detect-providers") {
631
+ const enabled2 = providerList(value, setting);
632
+ return {
633
+ mutate: (config) => ({
634
+ ...config,
635
+ accountDetection: {
636
+ ...config.accountDetection,
637
+ disabledProviders: PROVIDER_IDS.filter((provider) => !enabled2.includes(provider))
638
+ }
639
+ }),
640
+ display: enabled2
641
+ };
642
+ }
643
+ if (setting !== "launch-at-login") throw new Error(`unsupported config setting: ${setting}`);
644
+ const enabled = onOff(value, setting);
645
+ return { mutate: (config) => ({ ...config, tray: { ...config.tray, launchAtLogin: enabled } }), display: value };
646
+ }
647
+ function isConfigConflict(cause) {
648
+ return !!cause && typeof cause === "object" && cause.kind === "conflict";
649
+ }
650
+ async function readDaemonConfig(timeoutMs, connect) {
651
+ const client = await connect(timeoutMs);
652
+ try {
653
+ const state = await withTimeout(client.getConfig(), timeoutMs);
654
+ return {
655
+ state,
656
+ close: () => client.close(),
657
+ get: () => withTimeout(client.getConfig(), timeoutMs),
658
+ set: (update) => withTimeout(client.setConfig(update), timeoutMs)
659
+ };
660
+ } catch (cause) {
661
+ await client.close().catch(() => {
662
+ });
663
+ throw cause;
664
+ }
665
+ }
666
+ async function runConfigCommand(args, configPath, connect) {
667
+ const [action, settingName, value, ...extra] = args.positionals;
668
+ if (!action || action === "path") {
669
+ if (settingName || value || extra.length > 0) throw new Error("usage: tokmon config [path] [--json]");
670
+ return args.json ? json({ path: configPath() }, args.compact) : `${configPath()}
671
+ `;
672
+ }
673
+ if (action !== "get" && action !== "set") throw new Error("usage: tokmon config [path|get|set]");
674
+ if (action === "get") {
675
+ if (settingName || value || extra.length > 0) throw new Error("usage: tokmon config get [--json]");
676
+ const daemon2 = await readDaemonConfig(args.timeoutMs, connect);
677
+ try {
678
+ const report = configReport(daemon2.state.config);
679
+ return args.json ? json(report, args.compact) : formatConfigReport(report);
680
+ } finally {
681
+ await daemon2.close().catch(() => {
682
+ });
683
+ }
684
+ }
685
+ if (!settingName || !CONFIG_SETTINGS.includes(settingName) || value === void 0 || extra.length > 0) {
686
+ throw new Error("usage: tokmon config set <setting> <value>");
687
+ }
688
+ const setting = settingName;
689
+ const update = settingMutation(setting, value);
690
+ const daemon = await readDaemonConfig(args.timeoutMs, connect);
691
+ try {
692
+ let base = daemon.state;
693
+ let saved = null;
694
+ for (let attempt = 0; attempt < 2; attempt++) {
695
+ try {
696
+ saved = await daemon.set({
697
+ expectedRevision: base.config.revision,
698
+ config: update.mutate(base.config)
699
+ });
700
+ break;
701
+ } catch (cause) {
702
+ if (attempt > 0 || !isConfigConflict(cause)) throw cause;
703
+ base = await daemon.get();
704
+ }
705
+ }
706
+ if (!saved) throw new Error("config update failed");
707
+ const result = { setting, value: update.display, revision: saved.config.revision };
708
+ return args.json ? json(result, args.compact) : `${setting} ${Array.isArray(update.display) ? update.display.join(",") || "none" : update.display}
709
+ `;
710
+ } finally {
711
+ await daemon.close().catch(() => {
712
+ });
713
+ }
714
+ }
478
715
  function queryHelp(command) {
479
716
  if (command === "providers") return PROVIDERS_HELP;
480
717
  if (command === "snapshot") return SNAPSHOT_HELP;
@@ -486,13 +723,9 @@ async function runQueryCommand(command, args, dependencies = {}) {
486
723
  if (parsed.help) return queryHelp(command);
487
724
  const getConfigPath = dependencies.configPath ?? configLocation;
488
725
  if (command === "config") {
489
- const invalid = rejectsOption(args, ["--period", "--provider", "--account", "--model", "--refresh", "--cached", "--no-refresh", "--timeout"]);
726
+ const invalid = rejectsOption(args, ["--period", "--provider", "--account", "--model", "--refresh", "--cached", "--no-refresh"]);
490
727
  if (invalid) throw new Error(`${invalid} is not valid for tokmon config`);
491
- if (parsed.positionals.length > 1 || parsed.positionals[0] && parsed.positionals[0] !== "path") {
492
- throw new Error("usage: tokmon config [path] [--json]");
493
- }
494
- return parsed.json ? json({ path: getConfigPath() }, parsed.compact) : `${getConfigPath()}
495
- `;
728
+ return runConfigCommand(parsed, getConfigPath, dependencies.connectConfig ?? connectDaemonConfig);
496
729
  }
497
730
  if (command === "providers" || command === "snapshot") {
498
731
  const invalid = rejectsOption(args, ["--period", "--provider", "--account", "--model", "--cached", "--no-refresh"]);
@@ -519,6 +752,7 @@ async function runQueryCommand(command, args, dependencies = {}) {
519
752
  `;
520
753
  }
521
754
  export {
755
+ connectDaemonConfig,
522
756
  fetchDaemonSnapshot,
523
757
  parseQueryArgs,
524
758
  queryHelp,
package/dist/cli.js CHANGED
@@ -41,7 +41,7 @@ function validateServeArgs(serveArgs) {
41
41
  }
42
42
  async function main() {
43
43
  if (subcommand && ["usage", "models", "query", "providers", "snapshot", "config"].includes(subcommand)) {
44
- const { runQueryCommand } = await import("./cli-command-DCENRCO3.js");
44
+ const { runQueryCommand } = await import("./cli-command-I4GRR3MF.js");
45
45
  try {
46
46
  const output = await runQueryCommand(
47
47
  subcommand,
@@ -60,14 +60,14 @@ Run tokmon ${subcommand} --help for usage.
60
60
  return;
61
61
  }
62
62
  if (subcommand === "__daemon") {
63
- const { runDaemon } = await import("./daemon-6Y4O7NXS.js");
63
+ const { runDaemon } = await import("./daemon-ZXV3V5CS.js");
64
64
  await runDaemon(args.slice(1), { foreground: false });
65
65
  process.exitCode ??= 0;
66
66
  return;
67
67
  }
68
68
  if (subcommand === "serve" || subcommand === "web") {
69
69
  validateServeArgs(args.slice(1));
70
- const { runDaemon } = await import("./daemon-6Y4O7NXS.js");
70
+ const { runDaemon } = await import("./daemon-ZXV3V5CS.js");
71
71
  await runDaemon(args.slice(1), { foreground: true });
72
72
  process.exitCode ??= 0;
73
73
  return;
@@ -115,9 +115,9 @@ Run tokmon ${subcommand} --help for usage.
115
115
  return;
116
116
  }
117
117
  }
118
- const { loadConfig } = await import("./config-HXFJTNLM.js");
118
+ const { loadConfig } = await import("./config-3DGZ47F7.js");
119
119
  const { resolveGlyphs, setGlyphs } = await import("./glyphs-NKCSZLGO.js");
120
- const { attachOrSpawn } = await import("./daemon-handle-GVCYVDPO.js");
120
+ const { attachOrSpawn } = await import("./daemon-handle-G4OGPFR3.js");
121
121
  const config = await loadConfig();
122
122
  setGlyphs(resolveGlyphs({
123
123
  flag: asciiFlag,
@@ -128,7 +128,7 @@ Run tokmon ${subcommand} --help for usage.
128
128
  }));
129
129
  const daemon = await attachOrSpawn();
130
130
  const mode = daemon.kind === "spawned" ? "connected" : "degraded";
131
- const { bootstrapInk } = await import("./bootstrap-ink-IMT3S5HU.js");
131
+ const { bootstrapInk } = await import("./bootstrap-ink-WG4WG3R2.js");
132
132
  await bootstrapInk({ interval, config, daemon, mode });
133
133
  }
134
134
  void main().catch((error) => {
@@ -3,10 +3,15 @@ import {
3
3
  ACCENT_COLORS,
4
4
  COLOR_PALETTE,
5
5
  DEFAULTS,
6
+ DEFAULT_ACCOUNT_DETECTION_CONFIG,
7
+ DEFAULT_TRAY_CONFIG,
8
+ DESKTOP_GRAPH_RANGES,
9
+ MAX_PINNED_PROVIDERS,
6
10
  PROVIDER_IDS,
7
11
  PROVIDER_META,
8
12
  cacheDir,
9
13
  clampNum,
14
+ cleanProviderSelection,
10
15
  configLocation,
11
16
  containsEmail,
12
17
  envDir,
@@ -15,26 +20,36 @@ import {
15
20
  generateAccountId,
16
21
  getTrackedAccountRows,
17
22
  loadConfig,
23
+ moveProviderSelection,
18
24
  normalizeAllowedHost,
19
25
  normalizeAllowedHosts,
20
26
  normalizeConfig,
21
27
  pickAccentColor,
28
+ providerDetectionEnabled,
22
29
  redactEmail,
23
30
  repairConfig,
24
31
  sanitizeTyped,
25
32
  saveConfig,
26
33
  saveConfigSync,
34
+ setDetectedAccountExcluded,
35
+ setProviderDetectionEnabled,
27
36
  slugify,
28
- snapshotCacheFile
29
- } from "./chunk-HP5UZCXP.js";
37
+ snapshotCacheFile,
38
+ toggleProviderSelection
39
+ } from "./chunk-HNWEJ6MS.js";
30
40
  export {
31
41
  ACCENT_COLORS,
32
42
  COLOR_PALETTE,
33
43
  DEFAULTS,
44
+ DEFAULT_ACCOUNT_DETECTION_CONFIG,
45
+ DEFAULT_TRAY_CONFIG,
46
+ DESKTOP_GRAPH_RANGES,
47
+ MAX_PINNED_PROVIDERS,
34
48
  PROVIDER_IDS,
35
49
  PROVIDER_META,
36
50
  cacheDir,
37
51
  clampNum,
52
+ cleanProviderSelection,
38
53
  configLocation,
39
54
  containsEmail,
40
55
  envDir,
@@ -43,15 +58,20 @@ export {
43
58
  generateAccountId,
44
59
  getTrackedAccountRows,
45
60
  loadConfig,
61
+ moveProviderSelection,
46
62
  normalizeAllowedHost,
47
63
  normalizeAllowedHosts,
48
64
  normalizeConfig,
49
65
  pickAccentColor,
66
+ providerDetectionEnabled,
50
67
  redactEmail,
51
68
  repairConfig,
52
69
  sanitizeTyped,
53
70
  saveConfig,
54
71
  saveConfigSync,
72
+ setDetectedAccountExcluded,
73
+ setProviderDetectionEnabled,
55
74
  slugify,
56
- snapshotCacheFile
75
+ snapshotCacheFile,
76
+ toggleProviderSelection
57
77
  };