@ipv9/tokentracker-cli 0.39.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 (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +464 -0
  3. package/README.ko.md +464 -0
  4. package/README.md +476 -0
  5. package/README.zh-CN.md +469 -0
  6. package/bin/tracker.js +52 -0
  7. package/dashboard/dist/app-icon.png +0 -0
  8. package/dashboard/dist/apple-touch-icon.png +0 -0
  9. package/dashboard/dist/assets/ActivityHeatmap-BxBGHY1z.js +42 -0
  10. package/dashboard/dist/assets/Card-GROxUc_6.js +1 -0
  11. package/dashboard/dist/assets/DashboardPage-BZ5VFoBk.js +19 -0
  12. package/dashboard/dist/assets/DevicePage-CQts7ivB.js +1 -0
  13. package/dashboard/dist/assets/DialogTitle-DqFsk26U.js +1 -0
  14. package/dashboard/dist/assets/FadeIn-HBBXW_3q.js +1 -0
  15. package/dashboard/dist/assets/HeaderGithubStar-COD2HfaF.js +1 -0
  16. package/dashboard/dist/assets/IpCheckPage-Cn0l8-BQ.js +15 -0
  17. package/dashboard/dist/assets/LandingPage-CmV1BMU4.js +4356 -0
  18. package/dashboard/dist/assets/LeaderboardAvatar-CiIpWZwb.js +1 -0
  19. package/dashboard/dist/assets/LeaderboardPage-BU0mlR3g.js +6 -0
  20. package/dashboard/dist/assets/LeaderboardProfileModal-C49_3Xm9.js +72 -0
  21. package/dashboard/dist/assets/LeaderboardProfilePage-Bh1n0BAM.js +1 -0
  22. package/dashboard/dist/assets/LimitsPage-fZAmwLWT.js +2 -0
  23. package/dashboard/dist/assets/LocalOnlyNotice-D3rQdA-P.js +1 -0
  24. package/dashboard/dist/assets/LoginPage-enO4XP-c.js +1 -0
  25. package/dashboard/dist/assets/PopoverPopup-pitJEpN1.js +1 -0
  26. package/dashboard/dist/assets/Select-tT9x4ntD.js +1 -0
  27. package/dashboard/dist/assets/SelectItemText-C7F7eIm0.js +1 -0
  28. package/dashboard/dist/assets/SettingsPage-pDasZNU2.js +1 -0
  29. package/dashboard/dist/assets/SkillsPage-DEu7FY-2.js +1 -0
  30. package/dashboard/dist/assets/WidgetsPage-DGcO7rbp.js +1 -0
  31. package/dashboard/dist/assets/WrappedPage-D_1ID213.js +1 -0
  32. package/dashboard/dist/assets/agent-logos-DXQVg1xy.js +1 -0
  33. package/dashboard/dist/assets/arrow-up-right-DNLo92Ba.js +1 -0
  34. package/dashboard/dist/assets/download-DbBBBpJF.js +1 -0
  35. package/dashboard/dist/assets/geist-mono-cyrillic-400-normal-BPBWmzPh.woff +0 -0
  36. package/dashboard/dist/assets/geist-mono-cyrillic-400-normal-Ce5q_31Z.woff2 +0 -0
  37. package/dashboard/dist/assets/geist-mono-cyrillic-500-normal-CJBLNVQT.woff2 +0 -0
  38. package/dashboard/dist/assets/geist-mono-cyrillic-500-normal-mNhfPmgl.woff +0 -0
  39. package/dashboard/dist/assets/geist-mono-cyrillic-700-normal-DH5Q319x.woff +0 -0
  40. package/dashboard/dist/assets/geist-mono-cyrillic-700-normal-VCNRadI3.woff2 +0 -0
  41. package/dashboard/dist/assets/geist-mono-cyrillic-900-normal-BKC3PZkM.woff +0 -0
  42. package/dashboard/dist/assets/geist-mono-cyrillic-900-normal-DdrQ8KBw.woff2 +0 -0
  43. package/dashboard/dist/assets/geist-mono-latin-400-normal-CoULgQGM.woff +0 -0
  44. package/dashboard/dist/assets/geist-mono-latin-400-normal-LC9RFr9I.woff2 +0 -0
  45. package/dashboard/dist/assets/geist-mono-latin-500-normal-D3o2eNa9.woff2 +0 -0
  46. package/dashboard/dist/assets/geist-mono-latin-500-normal-DOxI7kZ4.woff +0 -0
  47. package/dashboard/dist/assets/geist-mono-latin-700-normal-D6izGJRP.woff2 +0 -0
  48. package/dashboard/dist/assets/geist-mono-latin-700-normal-QGw08Lff.woff +0 -0
  49. package/dashboard/dist/assets/geist-mono-latin-900-normal-CmoKXrdK.woff +0 -0
  50. package/dashboard/dist/assets/geist-mono-latin-900-normal-Cu5MFKsu.woff2 +0 -0
  51. package/dashboard/dist/assets/geist-mono-latin-ext-400-normal-Cgks_Qgx.woff2 +0 -0
  52. package/dashboard/dist/assets/geist-mono-latin-ext-400-normal-CxNRRMGd.woff +0 -0
  53. package/dashboard/dist/assets/geist-mono-latin-ext-500-normal-CQcGuCNt.woff2 +0 -0
  54. package/dashboard/dist/assets/geist-mono-latin-ext-500-normal-diTenJ8L.woff +0 -0
  55. package/dashboard/dist/assets/geist-mono-latin-ext-700-normal-BX9f1BHp.woff +0 -0
  56. package/dashboard/dist/assets/geist-mono-latin-ext-700-normal-YOllDaLV.woff2 +0 -0
  57. package/dashboard/dist/assets/geist-mono-latin-ext-900-normal-Br6WNUGb.woff +0 -0
  58. package/dashboard/dist/assets/geist-mono-latin-ext-900-normal-CrmBTzU2.woff2 +0 -0
  59. package/dashboard/dist/assets/index-BeoRn2gJ.js +2 -0
  60. package/dashboard/dist/assets/info-Bh5qTz6k.js +1 -0
  61. package/dashboard/dist/assets/main-BIY3Nj6I.js +969 -0
  62. package/dashboard/dist/assets/main-G_F9Iu_x.css +1 -0
  63. package/dashboard/dist/assets/use-limits-display-prefs-B4iJ-bBc.js +1 -0
  64. package/dashboard/dist/assets/use-native-settings-DHjPFDv8.js +1 -0
  65. package/dashboard/dist/assets/use-usage-limits-odqe9OY7.js +1 -0
  66. package/dashboard/dist/assets/useCurrency-BsSZiZMP.js +1 -0
  67. package/dashboard/dist/assets/useOpenInteractionType-BQhgq4rv.js +12 -0
  68. package/dashboard/dist/brand-logos/antigravity.svg +1 -0
  69. package/dashboard/dist/brand-logos/claude-code.svg +1 -0
  70. package/dashboard/dist/brand-logos/codebuddy.svg +1 -0
  71. package/dashboard/dist/brand-logos/codex.svg +15 -0
  72. package/dashboard/dist/brand-logos/copilot.svg +1 -0
  73. package/dashboard/dist/brand-logos/cursor.svg +1 -0
  74. package/dashboard/dist/brand-logos/gemini.svg +1 -0
  75. package/dashboard/dist/brand-logos/grok.svg +1 -0
  76. package/dashboard/dist/brand-logos/hermes.svg +1 -0
  77. package/dashboard/dist/brand-logos/kilo.svg +4 -0
  78. package/dashboard/dist/brand-logos/kimi.svg +1 -0
  79. package/dashboard/dist/brand-logos/kiro.svg +1 -0
  80. package/dashboard/dist/brand-logos/openclaw.svg +22 -0
  81. package/dashboard/dist/brand-logos/opencode.svg +3 -0
  82. package/dashboard/dist/clawd/happy.svg +161 -0
  83. package/dashboard/dist/clawd/idle/collapse.svg +101 -0
  84. package/dashboard/dist/clawd/idle/doze.svg +72 -0
  85. package/dashboard/dist/clawd/idle/follow.svg +64 -0
  86. package/dashboard/dist/clawd/idle/living.svg +196 -0
  87. package/dashboard/dist/clawd/idle/look.svg +115 -0
  88. package/dashboard/dist/clawd/idle/yawn.svg +158 -0
  89. package/dashboard/dist/clawd/mini/alert.svg +129 -0
  90. package/dashboard/dist/clawd/mini/crabwalk.svg +76 -0
  91. package/dashboard/dist/clawd/mini/enter-sleep.svg +65 -0
  92. package/dashboard/dist/clawd/mini/enter.svg +115 -0
  93. package/dashboard/dist/clawd/mini/happy.svg +124 -0
  94. package/dashboard/dist/clawd/mini/idle-tight.svg +15 -0
  95. package/dashboard/dist/clawd/mini/idle.svg +83 -0
  96. package/dashboard/dist/clawd/mini/peek.svg +82 -0
  97. package/dashboard/dist/clawd/mini/sleep.svg +112 -0
  98. package/dashboard/dist/clawd/react/double.svg +108 -0
  99. package/dashboard/dist/clawd/react/drag.svg +102 -0
  100. package/dashboard/dist/clawd/react/left.svg +102 -0
  101. package/dashboard/dist/clawd/react/right.svg +102 -0
  102. package/dashboard/dist/clawd/sleep/collapse-sleep.svg +247 -0
  103. package/dashboard/dist/clawd/sleep/sleeping.svg +118 -0
  104. package/dashboard/dist/clawd/sleep/wake.svg +277 -0
  105. package/dashboard/dist/clawd/static-base.svg +21 -0
  106. package/dashboard/dist/clawd/status/disconnected.svg +136 -0
  107. package/dashboard/dist/clawd/status/error.svg +94 -0
  108. package/dashboard/dist/clawd/status/notification.svg +134 -0
  109. package/dashboard/dist/clawd/working/building.svg +231 -0
  110. package/dashboard/dist/clawd/working/carrying.svg +107 -0
  111. package/dashboard/dist/clawd/working/conducting.svg +118 -0
  112. package/dashboard/dist/clawd/working/confused.svg +113 -0
  113. package/dashboard/dist/clawd/working/debugger.svg +91 -0
  114. package/dashboard/dist/clawd/working/juggling.svg +82 -0
  115. package/dashboard/dist/clawd/working/overheated.svg +75 -0
  116. package/dashboard/dist/clawd/working/pushing.svg +125 -0
  117. package/dashboard/dist/clawd/working/sweeping.svg +79 -0
  118. package/dashboard/dist/clawd/working/thinking.svg +119 -0
  119. package/dashboard/dist/clawd/working/typing.svg +153 -0
  120. package/dashboard/dist/clawd/working/ultrathink.svg +166 -0
  121. package/dashboard/dist/clawd/working/wizard.svg +98 -0
  122. package/dashboard/dist/dashboard-dark.png +0 -0
  123. package/dashboard/dist/favicon-16.png +0 -0
  124. package/dashboard/dist/favicon-32.png +0 -0
  125. package/dashboard/dist/favicon.ico +0 -0
  126. package/dashboard/dist/feed.xml +34 -0
  127. package/dashboard/dist/icon-192.png +0 -0
  128. package/dashboard/dist/icon-512.png +0 -0
  129. package/dashboard/dist/index.html +355 -0
  130. package/dashboard/dist/llms.txt +53 -0
  131. package/dashboard/dist/neon_bg.png +0 -0
  132. package/dashboard/dist/robots.txt +7 -0
  133. package/dashboard/dist/share.html +140 -0
  134. package/dashboard/dist/sitemap.xml +27 -0
  135. package/dashboard/dist/widgets-overview.png +0 -0
  136. package/package.json +78 -0
  137. package/scripts/install-local-service.sh +140 -0
  138. package/scripts/uninstall-local-service.sh +21 -0
  139. package/src/cli.js +95 -0
  140. package/src/commands/device-login.js +161 -0
  141. package/src/commands/diagnostics.js +38 -0
  142. package/src/commands/doctor.js +96 -0
  143. package/src/commands/init.js +1195 -0
  144. package/src/commands/serve.js +351 -0
  145. package/src/commands/status.js +609 -0
  146. package/src/commands/sync.js +2285 -0
  147. package/src/commands/uninstall.js +189 -0
  148. package/src/commands/wrapped.js +150 -0
  149. package/src/lib/antigravity-paths.js +48 -0
  150. package/src/lib/browser-auth.js +281 -0
  151. package/src/lib/categorizer-utils.js +232 -0
  152. package/src/lib/claude-categorizer.js +1319 -0
  153. package/src/lib/claude-config.js +204 -0
  154. package/src/lib/cli-ui.js +179 -0
  155. package/src/lib/codex-config.js +350 -0
  156. package/src/lib/codex-context-breakdown.js +400 -0
  157. package/src/lib/codex-rollout-parser.js +623 -0
  158. package/src/lib/codex-token-refresh.js +112 -0
  159. package/src/lib/cursor-config.js +425 -0
  160. package/src/lib/debug-flags.js +7 -0
  161. package/src/lib/diagnostics.js +272 -0
  162. package/src/lib/doctor.js +338 -0
  163. package/src/lib/fs.js +91 -0
  164. package/src/lib/gemini-config.js +288 -0
  165. package/src/lib/grok-hook.js +351 -0
  166. package/src/lib/init-flow.js +42 -0
  167. package/src/lib/local-api.js +1861 -0
  168. package/src/lib/openclaw-hook.js +420 -0
  169. package/src/lib/openclaw-session-plugin.js +520 -0
  170. package/src/lib/opencode-config.js +99 -0
  171. package/src/lib/passive-mode.js +185 -0
  172. package/src/lib/pricing/curated-overrides.json +79 -0
  173. package/src/lib/pricing/index.js +143 -0
  174. package/src/lib/pricing/litellm-fetcher.js +172 -0
  175. package/src/lib/pricing/matcher.js +255 -0
  176. package/src/lib/pricing/seed-snapshot.json +1 -0
  177. package/src/lib/progress.js +76 -0
  178. package/src/lib/project-usage-purge.js +106 -0
  179. package/src/lib/prompt.js +24 -0
  180. package/src/lib/proxy-env.js +131 -0
  181. package/src/lib/rollout.js +8442 -0
  182. package/src/lib/runtime-config.js +122 -0
  183. package/src/lib/skill-usage.js +267 -0
  184. package/src/lib/skills-manager.js +1127 -0
  185. package/src/lib/source-metadata.js +48 -0
  186. package/src/lib/sqlite-reader.js +136 -0
  187. package/src/lib/static-server.js +59 -0
  188. package/src/lib/subscriptions.js +453 -0
  189. package/src/lib/tracker-paths.js +16 -0
  190. package/src/lib/upload-throttle.js +148 -0
  191. package/src/lib/usage-limits.js +1806 -0
  192. package/src/lib/wrapped-aggregator.js +225 -0
@@ -0,0 +1,76 @@
1
+ function createProgress({ stream } = {}) {
2
+ const out = stream || process.stdout;
3
+ const enabled = Boolean(out && out.isTTY);
4
+ const frames = ["|", "/", "-", "\\"];
5
+ const intervalMs = 90;
6
+
7
+ let timer = null;
8
+ let text = "";
9
+ let frame = 0;
10
+ let lastLen = 0;
11
+
12
+ function render() {
13
+ if (!enabled) return;
14
+ const line = `${frames[frame++ % frames.length]} ${text}`;
15
+ const pad = lastLen > line.length ? " ".repeat(lastLen - line.length) : "";
16
+ lastLen = line.length;
17
+ out.write(`\r${line}${pad}`);
18
+ }
19
+
20
+ function start(initialText) {
21
+ if (!enabled) return;
22
+ text = initialText || "";
23
+ if (timer) clearInterval(timer);
24
+ timer = setInterval(render, intervalMs);
25
+ render();
26
+ }
27
+
28
+ function update(nextText) {
29
+ text = nextText || "";
30
+ render();
31
+ }
32
+
33
+ function stop() {
34
+ if (!enabled) return;
35
+ if (timer) clearInterval(timer);
36
+ timer = null;
37
+ out.write(`\r${" ".repeat(lastLen)}\r`);
38
+ lastLen = 0;
39
+ }
40
+
41
+ return { enabled, start, update, stop };
42
+ }
43
+
44
+ function renderBar(progress, width = 20) {
45
+ const p = Number.isFinite(progress) ? Math.min(1, Math.max(0, progress)) : 0;
46
+ const filled = Math.round(p * width);
47
+ const empty = Math.max(0, width - filled);
48
+ return `[${"=".repeat(filled)}${"-".repeat(empty)}] ${Math.round(p * 100)}%`;
49
+ }
50
+
51
+ function formatNumber(n) {
52
+ const v = Number(n);
53
+ if (!Number.isFinite(v)) return "0";
54
+ return Math.trunc(v).toLocaleString("en-US");
55
+ }
56
+
57
+ function formatBytes(bytes) {
58
+ const n = Number(bytes);
59
+ if (!Number.isFinite(n) || n <= 0) return "0 B";
60
+ const units = ["B", "KB", "MB", "GB", "TB"];
61
+ let v = n;
62
+ let i = 0;
63
+ while (v >= 1024 && i < units.length - 1) {
64
+ v /= 1024;
65
+ i += 1;
66
+ }
67
+ const fixed = i === 0 ? String(Math.trunc(v)) : v.toFixed(v >= 10 ? 1 : 2);
68
+ return `${fixed} ${units[i]}`;
69
+ }
70
+
71
+ module.exports = {
72
+ createProgress,
73
+ renderBar,
74
+ formatNumber,
75
+ formatBytes,
76
+ };
@@ -0,0 +1,106 @@
1
+ const fs = require("node:fs");
2
+ const fsp = require("node:fs/promises");
3
+ const path = require("node:path");
4
+ const readline = require("node:readline");
5
+
6
+ async function purgeProjectUsage({
7
+ projectKey,
8
+ projectQueuePath,
9
+ projectQueueStatePath,
10
+ projectState,
11
+ }) {
12
+ if (!projectKey || !projectQueuePath || !projectQueueStatePath || !projectState) {
13
+ return { removed: 0, kept: 0, removedBuckets: 0 };
14
+ }
15
+
16
+ let previousOffset = 0;
17
+ const previousState = await fsp.readFile(projectQueueStatePath, "utf8").catch(() => null);
18
+ if (previousState) {
19
+ try {
20
+ const parsed = JSON.parse(previousState);
21
+ const offset = Number(parsed?.offset || 0);
22
+ if (Number.isFinite(offset) && offset >= 0) previousOffset = offset;
23
+ } catch (_err) {
24
+ previousOffset = 0;
25
+ }
26
+ }
27
+
28
+ const buckets =
29
+ projectState.buckets && typeof projectState.buckets === "object" ? projectState.buckets : {};
30
+ let removedBuckets = 0;
31
+ const prefix = `${projectKey}|`;
32
+ for (const key of Object.keys(buckets)) {
33
+ if (key.startsWith(prefix)) {
34
+ delete buckets[key];
35
+ removedBuckets += 1;
36
+ }
37
+ }
38
+ projectState.buckets = buckets;
39
+
40
+ let removed = 0;
41
+ let kept = 0;
42
+ let nextOffset = 0;
43
+ const st = await fsp.stat(projectQueuePath).catch(() => null);
44
+ if (st && st.isFile()) {
45
+ const tmpPath = `${projectQueuePath}.tmp`;
46
+ await fsp.mkdir(path.dirname(projectQueuePath), { recursive: true });
47
+ const input = fs.createReadStream(projectQueuePath, "utf8");
48
+ const output = fs.createWriteStream(tmpPath, { encoding: "utf8" });
49
+ const rl = readline.createInterface({ input, crlfDelay: Infinity });
50
+
51
+ let inputOffset = 0;
52
+ let outputOffset = 0;
53
+ for await (const line of rl) {
54
+ const trimmed = line.trim();
55
+ const inputBytes = Buffer.byteLength(line, "utf8") + 1;
56
+ inputOffset += inputBytes;
57
+ if (!trimmed) continue;
58
+ let parsed = null;
59
+ try {
60
+ parsed = JSON.parse(trimmed);
61
+ } catch (_err) {
62
+ const entry = trimmed + "\n";
63
+ output.write(entry);
64
+ outputOffset += Buffer.byteLength(entry, "utf8");
65
+ kept += 1;
66
+ if (inputOffset <= previousOffset) {
67
+ nextOffset = outputOffset;
68
+ }
69
+ continue;
70
+ }
71
+ if (parsed && parsed.project_key === projectKey) {
72
+ removed += 1;
73
+ if (inputOffset <= previousOffset) {
74
+ nextOffset = outputOffset;
75
+ }
76
+ continue;
77
+ }
78
+ const entry = JSON.stringify(parsed) + "\n";
79
+ output.write(entry);
80
+ outputOffset += Buffer.byteLength(entry, "utf8");
81
+ kept += 1;
82
+ if (inputOffset <= previousOffset) {
83
+ nextOffset = outputOffset;
84
+ }
85
+ }
86
+
87
+ await new Promise((resolve, reject) => {
88
+ output.end(resolve);
89
+ output.on("error", reject);
90
+ });
91
+
92
+ await fsp.rename(tmpPath, projectQueuePath);
93
+ if (previousOffset >= inputOffset) {
94
+ nextOffset = outputOffset;
95
+ }
96
+ } else {
97
+ await fsp.writeFile(projectQueuePath, "", "utf8");
98
+ nextOffset = 0;
99
+ }
100
+
101
+ await fsp.writeFile(projectQueueStatePath, JSON.stringify({ offset: nextOffset }), "utf8");
102
+
103
+ return { removed, kept, removedBuckets };
104
+ }
105
+
106
+ module.exports = { purgeProjectUsage };
@@ -0,0 +1,24 @@
1
+ const readline = require("node:readline");
2
+
3
+ async function prompt(label) {
4
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
5
+ const value = await new Promise((resolve) => rl.question(label, resolve));
6
+ rl.close();
7
+ return String(value || "").trim();
8
+ }
9
+
10
+ async function promptHidden(label) {
11
+ const rl = readline.createInterface({
12
+ input: process.stdin,
13
+ output: process.stdout,
14
+ terminal: true,
15
+ });
16
+ const value = await new Promise((resolve) => {
17
+ rl._writeToOutput = function _writeToOutput() {};
18
+ rl.question(label, (answer) => resolve(answer));
19
+ });
20
+ rl.close();
21
+ return String(value || "").trim();
22
+ }
23
+
24
+ module.exports = { prompt, promptHidden };
@@ -0,0 +1,131 @@
1
+ const cp = require("node:child_process");
2
+
3
+ function hasProxyEnv(env = process.env) {
4
+ return Boolean(
5
+ env.HTTPS_PROXY ||
6
+ env.https_proxy ||
7
+ env.HTTP_PROXY ||
8
+ env.http_proxy ||
9
+ env.ALL_PROXY ||
10
+ env.all_proxy,
11
+ );
12
+ }
13
+
14
+ function parseMacProxyOutput(output) {
15
+ const values = {};
16
+ for (const line of String(output || "").split(/\r?\n/)) {
17
+ const match = line.match(/^\s*([A-Za-z]+)\s*:\s*(.+?)\s*$/);
18
+ if (match) values[match[1]] = match[2];
19
+ }
20
+ if (values.HTTPSEnable !== "1" || !values.HTTPSProxy || !values.HTTPSPort) return null;
21
+ return `http://${values.HTTPSProxy}:${values.HTTPSPort}`;
22
+ }
23
+
24
+ function resolveSystemProxyEnv({ env = process.env, platform = process.platform, commandRunner = cp.spawnSync } = {}) {
25
+ const out = {};
26
+ if (hasProxyEnv(env)) {
27
+ out.NODE_USE_ENV_PROXY = env.NODE_USE_ENV_PROXY || "1";
28
+ return out;
29
+ }
30
+
31
+ if (platform !== "darwin") return null;
32
+ const result = commandRunner("scutil", ["--proxy"], {
33
+ encoding: "utf8",
34
+ timeout: 2000,
35
+ });
36
+ if (result?.error || result?.status !== 0) return null;
37
+ const proxyUrl = parseMacProxyOutput(result.stdout);
38
+ if (!proxyUrl) return null;
39
+
40
+ return {
41
+ NODE_USE_ENV_PROXY: "1",
42
+ HTTPS_PROXY: proxyUrl,
43
+ HTTP_PROXY: proxyUrl,
44
+ };
45
+ }
46
+
47
+ function shouldRelaunchForProxy(argv, env = process.env) {
48
+ if (env.TOKENTRACKER_PROXY_ENV_APPLIED === "1") return false;
49
+ const command = Array.isArray(argv) ? argv[0] : null;
50
+ return !command || command === "serve";
51
+ }
52
+
53
+ function relaunchWithProxyEnvIfNeeded({
54
+ argv,
55
+ originalArgv,
56
+ env = process.env,
57
+ platform = process.platform,
58
+ commandRunner = cp.spawnSync,
59
+ nodePath = process.execPath,
60
+ } = {}) {
61
+ if (!shouldRelaunchForProxy(argv, env)) return null;
62
+ const proxyEnv = resolveSystemProxyEnv({ env, platform, commandRunner });
63
+ if (!proxyEnv || proxyEnv.NODE_USE_ENV_PROXY === env.NODE_USE_ENV_PROXY) return null;
64
+
65
+ const childEnv = {
66
+ ...env,
67
+ ...proxyEnv,
68
+ TOKENTRACKER_PROXY_ENV_APPLIED: "1",
69
+ };
70
+ return commandRunner(nodePath, originalArgv, {
71
+ stdio: "inherit",
72
+ env: childEnv,
73
+ });
74
+ }
75
+
76
+ function pickProxyUrl(env = process.env) {
77
+ return (
78
+ env.HTTPS_PROXY ||
79
+ env.https_proxy ||
80
+ env.HTTP_PROXY ||
81
+ env.http_proxy ||
82
+ env.ALL_PROXY ||
83
+ env.all_proxy ||
84
+ null
85
+ );
86
+ }
87
+
88
+ // Node's built-in NODE_USE_ENV_PROXY support only landed in v22.21 / v24.5.
89
+ // For older runtimes (including the v22.14 we historically embedded in the
90
+ // macOS app, and the v22.16 a community user hit on Discussion #68) the env
91
+ // var is silently ignored and fetch() bypasses the proxy. Setting an undici
92
+ // ProxyAgent dispatcher at startup gives us proxy support on every Node ≥ 18
93
+ // regardless of the env-proxy flag.
94
+ function applyUndiciProxyIfNeeded({
95
+ env = process.env,
96
+ setGlobalDispatcher,
97
+ ProxyAgent,
98
+ } = {}) {
99
+ const proxyUrl = pickProxyUrl(env);
100
+ if (!proxyUrl) return null;
101
+
102
+ let setter = setGlobalDispatcher;
103
+ let Agent = ProxyAgent;
104
+ if (!setter || !Agent) {
105
+ try {
106
+ // eslint-disable-next-line global-require
107
+ const undici = require("undici");
108
+ setter = setter || undici.setGlobalDispatcher;
109
+ Agent = Agent || undici.ProxyAgent;
110
+ } catch (_e) {
111
+ return null;
112
+ }
113
+ }
114
+ if (typeof setter !== "function" || typeof Agent !== "function") return null;
115
+
116
+ try {
117
+ setter(new Agent(proxyUrl));
118
+ return proxyUrl;
119
+ } catch (_e) {
120
+ return null;
121
+ }
122
+ }
123
+
124
+ module.exports = {
125
+ hasProxyEnv,
126
+ parseMacProxyOutput,
127
+ pickProxyUrl,
128
+ resolveSystemProxyEnv,
129
+ relaunchWithProxyEnvIfNeeded,
130
+ applyUndiciProxyIfNeeded,
131
+ };