@carboncode/cli 0.1.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 (159) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/DeepSeek-Reasonix-MIT.txt +21 -0
  3. package/README.md +109 -0
  4. package/README.zh-CN.md +91 -0
  5. package/THIRD_PARTY_NOTICES.md +14 -0
  6. package/dashboard/app.css +3233 -0
  7. package/dashboard/dist/app.js +30444 -0
  8. package/dashboard/dist/app.js.map +1 -0
  9. package/dashboard/dist/vendor-hljs.css +10 -0
  10. package/dashboard/dist/vendor-uplot.css +1 -0
  11. package/dashboard/index.html +19 -0
  12. package/data/deepseek-tokenizer.json.gz +0 -0
  13. package/dist/cli/acp-35C4ME6Y.js +711 -0
  14. package/dist/cli/acp-35C4ME6Y.js.map +1 -0
  15. package/dist/cli/chat-A6UJDPGV.js +51 -0
  16. package/dist/cli/chat-A6UJDPGV.js.map +1 -0
  17. package/dist/cli/chunk-2425HK6U.js +54 -0
  18. package/dist/cli/chunk-2425HK6U.js.map +1 -0
  19. package/dist/cli/chunk-25T6CVUP.js +172 -0
  20. package/dist/cli/chunk-25T6CVUP.js.map +1 -0
  21. package/dist/cli/chunk-2UQP6H6T.js +31 -0
  22. package/dist/cli/chunk-2UQP6H6T.js.map +1 -0
  23. package/dist/cli/chunk-3OAR6NVL.js +96 -0
  24. package/dist/cli/chunk-3OAR6NVL.js.map +1 -0
  25. package/dist/cli/chunk-3T6VBZCL.js +54 -0
  26. package/dist/cli/chunk-3T6VBZCL.js.map +1 -0
  27. package/dist/cli/chunk-4IBIPQVB.js +153 -0
  28. package/dist/cli/chunk-4IBIPQVB.js.map +1 -0
  29. package/dist/cli/chunk-4MQ3VURH.js +3106 -0
  30. package/dist/cli/chunk-4MQ3VURH.js.map +1 -0
  31. package/dist/cli/chunk-4TVNJWMA.js +11619 -0
  32. package/dist/cli/chunk-4TVNJWMA.js.map +1 -0
  33. package/dist/cli/chunk-4VR6XF4P.js +341 -0
  34. package/dist/cli/chunk-4VR6XF4P.js.map +1 -0
  35. package/dist/cli/chunk-5QCB62C4.js +25319 -0
  36. package/dist/cli/chunk-5QCB62C4.js.map +1 -0
  37. package/dist/cli/chunk-6OWJV3YW.js +390 -0
  38. package/dist/cli/chunk-6OWJV3YW.js.map +1 -0
  39. package/dist/cli/chunk-7EO27TB3.js +130 -0
  40. package/dist/cli/chunk-7EO27TB3.js.map +1 -0
  41. package/dist/cli/chunk-7L2WTRNU.js +308 -0
  42. package/dist/cli/chunk-7L2WTRNU.js.map +1 -0
  43. package/dist/cli/chunk-BHTZFEYE.js +47 -0
  44. package/dist/cli/chunk-BHTZFEYE.js.map +1 -0
  45. package/dist/cli/chunk-BSGCXZQN.js +343 -0
  46. package/dist/cli/chunk-BSGCXZQN.js.map +1 -0
  47. package/dist/cli/chunk-BSINVTTL.js +464 -0
  48. package/dist/cli/chunk-BSINVTTL.js.map +1 -0
  49. package/dist/cli/chunk-CPKCNHRR.js +323 -0
  50. package/dist/cli/chunk-CPKCNHRR.js.map +1 -0
  51. package/dist/cli/chunk-CXVWUPA3.js +96 -0
  52. package/dist/cli/chunk-CXVWUPA3.js.map +1 -0
  53. package/dist/cli/chunk-D5NFKRGO.js +160 -0
  54. package/dist/cli/chunk-D5NFKRGO.js.map +1 -0
  55. package/dist/cli/chunk-ECHSFYOY.js +109 -0
  56. package/dist/cli/chunk-ECHSFYOY.js.map +1 -0
  57. package/dist/cli/chunk-FEZK652I.js +3644 -0
  58. package/dist/cli/chunk-FEZK652I.js.map +1 -0
  59. package/dist/cli/chunk-GALC45Q2.js +696 -0
  60. package/dist/cli/chunk-GALC45Q2.js.map +1 -0
  61. package/dist/cli/chunk-IAUOP25G.js +2984 -0
  62. package/dist/cli/chunk-IAUOP25G.js.map +1 -0
  63. package/dist/cli/chunk-ILJOIQ5W.js +163 -0
  64. package/dist/cli/chunk-ILJOIQ5W.js.map +1 -0
  65. package/dist/cli/chunk-IX6XI2RG.js +225 -0
  66. package/dist/cli/chunk-IX6XI2RG.js.map +1 -0
  67. package/dist/cli/chunk-J5BYPUB5.js +62795 -0
  68. package/dist/cli/chunk-J5BYPUB5.js.map +1 -0
  69. package/dist/cli/chunk-J5XJHLWM.js +55 -0
  70. package/dist/cli/chunk-J5XJHLWM.js.map +1 -0
  71. package/dist/cli/chunk-JKGYMRX5.js +101 -0
  72. package/dist/cli/chunk-JKGYMRX5.js.map +1 -0
  73. package/dist/cli/chunk-JMBMLOBP.js +26 -0
  74. package/dist/cli/chunk-JMBMLOBP.js.map +1 -0
  75. package/dist/cli/chunk-LN3B5PMX.js +128 -0
  76. package/dist/cli/chunk-LN3B5PMX.js.map +1 -0
  77. package/dist/cli/chunk-M2UFZUX3.js +635 -0
  78. package/dist/cli/chunk-M2UFZUX3.js.map +1 -0
  79. package/dist/cli/chunk-PJS34556.js +809 -0
  80. package/dist/cli/chunk-PJS34556.js.map +1 -0
  81. package/dist/cli/chunk-QJG7OF27.js +655 -0
  82. package/dist/cli/chunk-QJG7OF27.js.map +1 -0
  83. package/dist/cli/chunk-QVC75MR3.js +232 -0
  84. package/dist/cli/chunk-QVC75MR3.js.map +1 -0
  85. package/dist/cli/chunk-S2KIUQKQ.js +378 -0
  86. package/dist/cli/chunk-S2KIUQKQ.js.map +1 -0
  87. package/dist/cli/chunk-S4XVGLRW.js +499 -0
  88. package/dist/cli/chunk-S4XVGLRW.js.map +1 -0
  89. package/dist/cli/chunk-T5TQ4NDT.js +190 -0
  90. package/dist/cli/chunk-T5TQ4NDT.js.map +1 -0
  91. package/dist/cli/chunk-TH756VLN.js +1924 -0
  92. package/dist/cli/chunk-TH756VLN.js.map +1 -0
  93. package/dist/cli/chunk-TUK7OWJA.js +51 -0
  94. package/dist/cli/chunk-TUK7OWJA.js.map +1 -0
  95. package/dist/cli/chunk-U4IJVG32.js +363 -0
  96. package/dist/cli/chunk-U4IJVG32.js.map +1 -0
  97. package/dist/cli/chunk-UI66BH6D.js +624 -0
  98. package/dist/cli/chunk-UI66BH6D.js.map +1 -0
  99. package/dist/cli/chunk-VPMBGAND.js +53 -0
  100. package/dist/cli/chunk-VPMBGAND.js.map +1 -0
  101. package/dist/cli/chunk-WLHH3OSR.js +522 -0
  102. package/dist/cli/chunk-WLHH3OSR.js.map +1 -0
  103. package/dist/cli/chunk-WRN65TRD.js +908 -0
  104. package/dist/cli/chunk-WRN65TRD.js.map +1 -0
  105. package/dist/cli/chunk-X53B3JIX.js +34320 -0
  106. package/dist/cli/chunk-X53B3JIX.js.map +1 -0
  107. package/dist/cli/chunk-XJ5SRLKK.js +50 -0
  108. package/dist/cli/chunk-XJ5SRLKK.js.map +1 -0
  109. package/dist/cli/chunk-YZSXRGFH.js +54 -0
  110. package/dist/cli/chunk-YZSXRGFH.js.map +1 -0
  111. package/dist/cli/code-4TUTAGO5.js +163 -0
  112. package/dist/cli/code-4TUTAGO5.js.map +1 -0
  113. package/dist/cli/commands-KMOZEYCF.js +356 -0
  114. package/dist/cli/commands-KMOZEYCF.js.map +1 -0
  115. package/dist/cli/commit-DTFA56VQ.js +292 -0
  116. package/dist/cli/commit-DTFA56VQ.js.map +1 -0
  117. package/dist/cli/desktop-7N3MHNBD.js +1274 -0
  118. package/dist/cli/desktop-7N3MHNBD.js.map +1 -0
  119. package/dist/cli/devtools-HW3WDT3Q.js +91 -0
  120. package/dist/cli/devtools-HW3WDT3Q.js.map +1 -0
  121. package/dist/cli/diff-E5OWTF4C.js +165 -0
  122. package/dist/cli/diff-E5OWTF4C.js.map +1 -0
  123. package/dist/cli/doctor-IEJQRJMN.js +27 -0
  124. package/dist/cli/doctor-IEJQRJMN.js.map +1 -0
  125. package/dist/cli/events-4625EGXI.js +340 -0
  126. package/dist/cli/events-4625EGXI.js.map +1 -0
  127. package/dist/cli/index.js +3536 -0
  128. package/dist/cli/index.js.map +1 -0
  129. package/dist/cli/mcp-PDI2PDLG.js +277 -0
  130. package/dist/cli/mcp-PDI2PDLG.js.map +1 -0
  131. package/dist/cli/mcp-browse-OSPXOFPZ.js +178 -0
  132. package/dist/cli/mcp-browse-OSPXOFPZ.js.map +1 -0
  133. package/dist/cli/mcp-inspect-QRFVTHMF.js +148 -0
  134. package/dist/cli/mcp-inspect-QRFVTHMF.js.map +1 -0
  135. package/dist/cli/package.json +3 -0
  136. package/dist/cli/prompt-3CDII3UO.js +16 -0
  137. package/dist/cli/prompt-3CDII3UO.js.map +1 -0
  138. package/dist/cli/prune-sessions-KZX4SXKW.js +44 -0
  139. package/dist/cli/prune-sessions-KZX4SXKW.js.map +1 -0
  140. package/dist/cli/replay-HYOSRQIV.js +291 -0
  141. package/dist/cli/replay-HYOSRQIV.js.map +1 -0
  142. package/dist/cli/run-2ZHADOUP.js +220 -0
  143. package/dist/cli/run-2ZHADOUP.js.map +1 -0
  144. package/dist/cli/server-X75PAZG5.js +3572 -0
  145. package/dist/cli/server-X75PAZG5.js.map +1 -0
  146. package/dist/cli/sessions-POOZA5CQ.js +120 -0
  147. package/dist/cli/sessions-POOZA5CQ.js.map +1 -0
  148. package/dist/cli/setup-YLPFI3OH.js +618 -0
  149. package/dist/cli/setup-YLPFI3OH.js.map +1 -0
  150. package/dist/cli/stats-NXJ3TO2D.js +16 -0
  151. package/dist/cli/stats-NXJ3TO2D.js.map +1 -0
  152. package/dist/cli/update-ZUO5MKQ6.js +15 -0
  153. package/dist/cli/update-ZUO5MKQ6.js.map +1 -0
  154. package/dist/cli/version-NXXWE3WN.js +33 -0
  155. package/dist/cli/version-NXXWE3WN.js.map +1 -0
  156. package/dist/index.d.ts +2523 -0
  157. package/dist/index.js +15408 -0
  158. package/dist/index.js.map +1 -0
  159. package/package.json +112 -0
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+
4
+ // src/adapters/event-source-jsonl.ts
5
+ import { existsSync, readFileSync, readdirSync, statSync } from "fs";
6
+ import { join } from "path";
7
+ var DAY_MS = 864e5;
8
+ function recentEventFiles(dir, now, cap = 8, staleDays = 30) {
9
+ if (!existsSync(dir)) return [];
10
+ let names;
11
+ try {
12
+ names = readdirSync(dir);
13
+ } catch {
14
+ return [];
15
+ }
16
+ const cutoff = now - staleDays * DAY_MS;
17
+ const candidates = [];
18
+ for (const name of names) {
19
+ if (!name.endsWith(".events.jsonl")) continue;
20
+ const path = join(dir, name);
21
+ let mtime;
22
+ try {
23
+ mtime = statSync(path).mtimeMs;
24
+ } catch {
25
+ continue;
26
+ }
27
+ if (mtime < cutoff) continue;
28
+ candidates.push({ path, mtime });
29
+ }
30
+ candidates.sort((a, b) => b.mtime - a.mtime);
31
+ return candidates.slice(0, cap).map((c) => c.path);
32
+ }
33
+ function readEventLogFile(path) {
34
+ if (!existsSync(path)) return [];
35
+ const raw = readFileSync(path, "utf8");
36
+ const out = [];
37
+ for (const line of raw.split(/\r?\n/)) {
38
+ const trimmed = line.trim();
39
+ if (!trimmed) continue;
40
+ try {
41
+ const ev = JSON.parse(trimmed);
42
+ if (ev && typeof ev === "object" && typeof ev.type === "string") {
43
+ out.push(ev);
44
+ }
45
+ } catch {
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+
51
+ export {
52
+ recentEventFiles,
53
+ readEventLogFile
54
+ };
55
+ //# sourceMappingURL=chunk-J5XJHLWM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/event-source-jsonl.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Event } from \"../core/events.js\";\nimport type { EventSource } from \"../ports/event-sink.js\";\nimport { eventLogPath } from \"./event-sink-jsonl.js\";\n\nconst DAY_MS = 86_400_000;\n\n/** Most-recently-modified `*.events.jsonl` files, capped + filtered by stale-mtime cutoff. */\nexport function recentEventFiles(dir: string, now: number, cap = 8, staleDays = 30): string[] {\n if (!existsSync(dir)) return [];\n let names: string[];\n try {\n names = readdirSync(dir);\n } catch {\n return [];\n }\n const cutoff = now - staleDays * DAY_MS;\n const candidates: Array<{ path: string; mtime: number }> = [];\n for (const name of names) {\n if (!name.endsWith(\".events.jsonl\")) continue;\n const path = join(dir, name);\n let mtime: number;\n try {\n mtime = statSync(path).mtimeMs;\n } catch {\n continue;\n }\n if (mtime < cutoff) continue;\n candidates.push({ path, mtime });\n }\n candidates.sort((a, b) => b.mtime - a.mtime);\n return candidates.slice(0, cap).map((c) => c.path);\n}\n\nexport function readEventLogFile(path: string): Event[] {\n if (!existsSync(path)) return [];\n const raw = readFileSync(path, \"utf8\");\n const out: Event[] = [];\n for (const line of raw.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const ev = JSON.parse(trimmed) as Event;\n if (ev && typeof ev === \"object\" && typeof (ev as { type?: unknown }).type === \"string\") {\n out.push(ev);\n }\n } catch {\n /* malformed mid-line write — best-effort skip */\n }\n }\n return out;\n}\n\nexport class JsonlEventSource implements EventSource {\n async *read(sessionName: string): AsyncIterable<Event> {\n const events = readEventLogFile(eventLogPath(sessionName));\n for (const ev of events) yield ev;\n }\n}\n"],"mappings":";;;;AAAA,SAAS,YAAY,cAAc,aAAa,gBAAgB;AAChE,SAAS,YAAY;AAKrB,IAAM,SAAS;AAGR,SAAS,iBAAiB,KAAa,KAAa,MAAM,GAAG,YAAY,IAAc;AAC5F,MAAI,CAAC,WAAW,GAAG,EAAG,QAAO,CAAC;AAC9B,MAAI;AACJ,MAAI;AACF,YAAQ,YAAY,GAAG;AAAA,EACzB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACA,QAAM,SAAS,MAAM,YAAY;AACjC,QAAM,aAAqD,CAAC;AAC5D,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,KAAK,SAAS,eAAe,EAAG;AACrC,UAAM,OAAO,KAAK,KAAK,IAAI;AAC3B,QAAI;AACJ,QAAI;AACF,cAAQ,SAAS,IAAI,EAAE;AAAA,IACzB,QAAQ;AACN;AAAA,IACF;AACA,QAAI,QAAQ,OAAQ;AACpB,eAAW,KAAK,EAAE,MAAM,MAAM,CAAC;AAAA,EACjC;AACA,aAAW,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAC3C,SAAO,WAAW,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI;AACnD;AAEO,SAAS,iBAAiB,MAAuB;AACtD,MAAI,CAAC,WAAW,IAAI,EAAG,QAAO,CAAC;AAC/B,QAAM,MAAM,aAAa,MAAM,MAAM;AACrC,QAAM,MAAe,CAAC;AACtB,aAAW,QAAQ,IAAI,MAAM,OAAO,GAAG;AACrC,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,CAAC,QAAS;AACd,QAAI;AACF,YAAM,KAAK,KAAK,MAAM,OAAO;AAC7B,UAAI,MAAM,OAAO,OAAO,YAAY,OAAQ,GAA0B,SAAS,UAAU;AACvF,YAAI,KAAK,EAAE;AAAA,MACb;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+ import {
4
+ probeOllama
5
+ } from "./chunk-WRN65TRD.js";
6
+
7
+ // src/index/semantic/ollama-launcher.ts
8
+ import { spawn, spawnSync } from "child_process";
9
+ import { existsSync } from "fs";
10
+ import { join } from "path";
11
+ import { setTimeout as sleep } from "timers/promises";
12
+ function findOllamaBinary() {
13
+ const cmd = process.platform === "win32" ? "where" : "which";
14
+ const out = spawnSync(cmd, ["ollama"], { encoding: "utf8" });
15
+ if (out.status === 0) {
16
+ const first = out.stdout.split(/\r?\n/).find((l) => l.trim().length > 0);
17
+ if (first) return first.trim();
18
+ }
19
+ if (process.platform === "win32") {
20
+ const local = process.env.LOCALAPPDATA;
21
+ if (local) {
22
+ const candidate = join(local, "Programs", "Ollama", "ollama.exe");
23
+ if (existsSync(candidate)) return candidate;
24
+ }
25
+ }
26
+ return null;
27
+ }
28
+ async function checkOllamaStatus(modelName, baseUrl) {
29
+ const binary = findOllamaBinary();
30
+ const probe = await probeOllama({ baseUrl });
31
+ const installedModels = probe.ok ? probe.models : [];
32
+ const wanted = modelName.includes(":") ? modelName : `${modelName}:latest`;
33
+ const modelPulled = installedModels.some((m) => m === modelName || m === wanted);
34
+ return {
35
+ binaryFound: binary !== null,
36
+ daemonRunning: probe.ok,
37
+ modelPulled,
38
+ modelName,
39
+ installedModels
40
+ };
41
+ }
42
+ async function startOllamaDaemon(opts = {}) {
43
+ const timeoutMs = opts.timeoutMs ?? 15e3;
44
+ const child = spawn(findOllamaBinary() ?? "ollama", ["serve"], {
45
+ detached: true,
46
+ stdio: "ignore",
47
+ windowsHide: true
48
+ });
49
+ child.unref();
50
+ const pid = child.pid ?? null;
51
+ const start = Date.now();
52
+ while (Date.now() - start < timeoutMs) {
53
+ if (opts.signal?.aborted) return { ready: false, pid };
54
+ const probe = await probeOllama({ baseUrl: opts.baseUrl, signal: opts.signal });
55
+ if (probe.ok) return { ready: true, pid };
56
+ await sleep(500);
57
+ }
58
+ return { ready: false, pid };
59
+ }
60
+ async function pullOllamaModel(modelName, opts = {}) {
61
+ return new Promise((resolve) => {
62
+ const child = spawn(findOllamaBinary() ?? "ollama", ["pull", modelName], {
63
+ stdio: ["ignore", "pipe", "pipe"],
64
+ windowsHide: true
65
+ });
66
+ if (opts.signal) {
67
+ const onAbort = () => child.kill();
68
+ opts.signal.addEventListener("abort", onAbort, { once: true });
69
+ child.once("exit", () => opts.signal?.removeEventListener("abort", onAbort));
70
+ }
71
+ streamLines(child.stdout, (l) => opts.onLine?.(l, "stdout"));
72
+ streamLines(child.stderr, (l) => opts.onLine?.(l, "stderr"));
73
+ child.once("exit", (code) => resolve(code ?? -1));
74
+ child.once("error", () => resolve(-1));
75
+ });
76
+ }
77
+ function streamLines(stream, cb) {
78
+ if (!stream) return;
79
+ let buf = "";
80
+ stream.setEncoding("utf8");
81
+ stream.on("data", (chunk) => {
82
+ buf += chunk;
83
+ let nl = buf.indexOf("\n");
84
+ while (nl !== -1) {
85
+ const line = buf.slice(0, nl).replace(/\r$/, "");
86
+ buf = buf.slice(nl + 1);
87
+ if (line.length > 0) cb(line);
88
+ nl = buf.indexOf("\n");
89
+ }
90
+ });
91
+ stream.on("end", () => {
92
+ if (buf.length > 0) cb(buf.replace(/\r$/, ""));
93
+ });
94
+ }
95
+
96
+ export {
97
+ checkOllamaStatus,
98
+ startOllamaDaemon,
99
+ pullOllamaModel
100
+ };
101
+ //# sourceMappingURL=chunk-JKGYMRX5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index/semantic/ollama-launcher.ts"],"sourcesContent":["/** Daemon spawn is detached + unref'd so it outlives the CLI; non-TTY shells error instead of prompting. */\n\nimport { spawn, spawnSync } from \"node:child_process\";\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { setTimeout as sleep } from \"node:timers/promises\";\nimport { probeOllama } from \"./embedding.js\";\n\nexport interface OllamaStatus {\n /** `ollama` binary resolvable on PATH or at the Windows installer path. */\n binaryFound: boolean;\n /** HTTP daemon reachable at the configured base URL. */\n daemonRunning: boolean;\n /** True if `<model>` (or `<model>:latest`) appears in `ollama list`. */\n modelPulled: boolean;\n /** Model the caller asked about — echoed for log clarity. */\n modelName: string;\n /** Models the daemon reported, for diagnostics. Empty when daemon down. */\n installedModels: string[];\n}\n\n/** Falls back to the Windows installer path because PATH refresh is per-shell — daemon may be up while the dashboard process inherited a stale PATH. */\nexport function findOllamaBinary(): string | null {\n const cmd = process.platform === \"win32\" ? \"where\" : \"which\";\n const out = spawnSync(cmd, [\"ollama\"], { encoding: \"utf8\" });\n if (out.status === 0) {\n const first = out.stdout.split(/\\r?\\n/).find((l) => l.trim().length > 0);\n if (first) return first.trim();\n }\n if (process.platform === \"win32\") {\n const local = process.env.LOCALAPPDATA;\n if (local) {\n const candidate = join(local, \"Programs\", \"Ollama\", \"ollama.exe\");\n if (existsSync(candidate)) return candidate;\n }\n }\n return null;\n}\n\n/** Treats `<model>` and `<model>:latest` as the same — Ollama appends `:latest` to plain pulls. */\nexport async function checkOllamaStatus(\n modelName: string,\n baseUrl?: string,\n): Promise<OllamaStatus> {\n const binary = findOllamaBinary();\n const probe = await probeOllama({ baseUrl });\n const installedModels = probe.ok ? probe.models : [];\n const wanted = modelName.includes(\":\") ? modelName : `${modelName}:latest`;\n const modelPulled = installedModels.some((m) => m === modelName || m === wanted);\n return {\n binaryFound: binary !== null,\n daemonRunning: probe.ok,\n modelPulled,\n modelName,\n installedModels,\n };\n}\n\n/** Detached + unref'd so daemon survives the CLI; output discarded so no ghost cmd window on Windows. */\nexport async function startOllamaDaemon(\n opts: { baseUrl?: string; timeoutMs?: number; signal?: AbortSignal } = {},\n): Promise<{ ready: boolean; pid: number | null }> {\n const timeoutMs = opts.timeoutMs ?? 15_000;\n const child = spawn(findOllamaBinary() ?? \"ollama\", [\"serve\"], {\n detached: true,\n stdio: \"ignore\",\n windowsHide: true,\n });\n child.unref();\n\n const pid = child.pid ?? null;\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (opts.signal?.aborted) return { ready: false, pid };\n const probe = await probeOllama({ baseUrl: opts.baseUrl, signal: opts.signal });\n if (probe.ok) return { ready: true, pid };\n await sleep(500);\n }\n return { ready: false, pid };\n}\n\n/** `onLine` called per line so the CLI can render its own bar instead of ollama's TTY output. */\nexport async function pullOllamaModel(\n modelName: string,\n opts: { onLine?: (line: string, stream: \"stdout\" | \"stderr\") => void; signal?: AbortSignal } = {},\n): Promise<number> {\n return new Promise<number>((resolve) => {\n const child = spawn(findOllamaBinary() ?? \"ollama\", [\"pull\", modelName], {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n });\n if (opts.signal) {\n const onAbort = () => child.kill();\n opts.signal.addEventListener(\"abort\", onAbort, { once: true });\n child.once(\"exit\", () => opts.signal?.removeEventListener(\"abort\", onAbort));\n }\n streamLines(child.stdout, (l) => opts.onLine?.(l, \"stdout\"));\n streamLines(child.stderr, (l) => opts.onLine?.(l, \"stderr\"));\n child.once(\"exit\", (code) => resolve(code ?? -1));\n child.once(\"error\", () => resolve(-1));\n });\n}\n\nfunction streamLines(stream: NodeJS.ReadableStream | null, cb: (line: string) => void): void {\n if (!stream) return;\n let buf = \"\";\n stream.setEncoding(\"utf8\");\n stream.on(\"data\", (chunk: string) => {\n buf += chunk;\n let nl = buf.indexOf(\"\\n\");\n while (nl !== -1) {\n const line = buf.slice(0, nl).replace(/\\r$/, \"\");\n buf = buf.slice(nl + 1);\n if (line.length > 0) cb(line);\n nl = buf.indexOf(\"\\n\");\n }\n });\n stream.on(\"end\", () => {\n if (buf.length > 0) cb(buf.replace(/\\r$/, \"\"));\n });\n}\n"],"mappings":";;;;;;;AAEA,SAAS,OAAO,iBAAiB;AACjC,SAAS,kBAAkB;AAC3B,SAAS,YAAY;AACrB,SAAS,cAAc,aAAa;AAiB7B,SAAS,mBAAkC;AAChD,QAAM,MAAM,QAAQ,aAAa,UAAU,UAAU;AACrD,QAAM,MAAM,UAAU,KAAK,CAAC,QAAQ,GAAG,EAAE,UAAU,OAAO,CAAC;AAC3D,MAAI,IAAI,WAAW,GAAG;AACpB,UAAM,QAAQ,IAAI,OAAO,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC;AACvE,QAAI,MAAO,QAAO,MAAM,KAAK;AAAA,EAC/B;AACA,MAAI,QAAQ,aAAa,SAAS;AAChC,UAAM,QAAQ,QAAQ,IAAI;AAC1B,QAAI,OAAO;AACT,YAAM,YAAY,KAAK,OAAO,YAAY,UAAU,YAAY;AAChE,UAAI,WAAW,SAAS,EAAG,QAAO;AAAA,IACpC;AAAA,EACF;AACA,SAAO;AACT;AAGA,eAAsB,kBACpB,WACA,SACuB;AACvB,QAAM,SAAS,iBAAiB;AAChC,QAAM,QAAQ,MAAM,YAAY,EAAE,QAAQ,CAAC;AAC3C,QAAM,kBAAkB,MAAM,KAAK,MAAM,SAAS,CAAC;AACnD,QAAM,SAAS,UAAU,SAAS,GAAG,IAAI,YAAY,GAAG,SAAS;AACjE,QAAM,cAAc,gBAAgB,KAAK,CAAC,MAAM,MAAM,aAAa,MAAM,MAAM;AAC/E,SAAO;AAAA,IACL,aAAa,WAAW;AAAA,IACxB,eAAe,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGA,eAAsB,kBACpB,OAAuE,CAAC,GACvB;AACjD,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,QAAQ,MAAM,iBAAiB,KAAK,UAAU,CAAC,OAAO,GAAG;AAAA,IAC7D,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,EACf,CAAC;AACD,QAAM,MAAM;AAEZ,QAAM,MAAM,MAAM,OAAO;AACzB,QAAM,QAAQ,KAAK,IAAI;AACvB,SAAO,KAAK,IAAI,IAAI,QAAQ,WAAW;AACrC,QAAI,KAAK,QAAQ,QAAS,QAAO,EAAE,OAAO,OAAO,IAAI;AACrD,UAAM,QAAQ,MAAM,YAAY,EAAE,SAAS,KAAK,SAAS,QAAQ,KAAK,OAAO,CAAC;AAC9E,QAAI,MAAM,GAAI,QAAO,EAAE,OAAO,MAAM,IAAI;AACxC,UAAM,MAAM,GAAG;AAAA,EACjB;AACA,SAAO,EAAE,OAAO,OAAO,IAAI;AAC7B;AAGA,eAAsB,gBACpB,WACA,OAA+F,CAAC,GAC/E;AACjB,SAAO,IAAI,QAAgB,CAAC,YAAY;AACtC,UAAM,QAAQ,MAAM,iBAAiB,KAAK,UAAU,CAAC,QAAQ,SAAS,GAAG;AAAA,MACvE,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,aAAa;AAAA,IACf,CAAC;AACD,QAAI,KAAK,QAAQ;AACf,YAAM,UAAU,MAAM,MAAM,KAAK;AACjC,WAAK,OAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAC7D,YAAM,KAAK,QAAQ,MAAM,KAAK,QAAQ,oBAAoB,SAAS,OAAO,CAAC;AAAA,IAC7E;AACA,gBAAY,MAAM,QAAQ,CAAC,MAAM,KAAK,SAAS,GAAG,QAAQ,CAAC;AAC3D,gBAAY,MAAM,QAAQ,CAAC,MAAM,KAAK,SAAS,GAAG,QAAQ,CAAC;AAC3D,UAAM,KAAK,QAAQ,CAAC,SAAS,QAAQ,QAAQ,EAAE,CAAC;AAChD,UAAM,KAAK,SAAS,MAAM,QAAQ,EAAE,CAAC;AAAA,EACvC,CAAC;AACH;AAEA,SAAS,YAAY,QAAsC,IAAkC;AAC3F,MAAI,CAAC,OAAQ;AACb,MAAI,MAAM;AACV,SAAO,YAAY,MAAM;AACzB,SAAO,GAAG,QAAQ,CAAC,UAAkB;AACnC,WAAO;AACP,QAAI,KAAK,IAAI,QAAQ,IAAI;AACzB,WAAO,OAAO,IAAI;AAChB,YAAM,OAAO,IAAI,MAAM,GAAG,EAAE,EAAE,QAAQ,OAAO,EAAE;AAC/C,YAAM,IAAI,MAAM,KAAK,CAAC;AACtB,UAAI,KAAK,SAAS,EAAG,IAAG,IAAI;AAC5B,WAAK,IAAI,QAAQ,IAAI;AAAA,IACvB;AAAA,EACF,CAAC;AACD,SAAO,GAAG,OAAO,MAAM;AACrB,QAAI,IAAI,SAAS,EAAG,IAAG,IAAI,QAAQ,OAAO,EAAE,CAAC;AAAA,EAC/C,CAAC;AACH;","names":[]}
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+
4
+ // src/mcp/marketplace-overlay/loader.ts
5
+ import { readFileSync } from "fs";
6
+ import { dirname, join } from "path";
7
+ import { fileURLToPath } from "url";
8
+ var cache = null;
9
+ var cachedLang = null;
10
+ function loadOverlay(lang) {
11
+ if (cachedLang === lang && cache) return cache;
12
+ try {
13
+ const dir = dirname(fileURLToPath(import.meta.url));
14
+ const raw = readFileSync(join(dir, `${lang}.json`), "utf8");
15
+ cache = JSON.parse(raw);
16
+ cachedLang = lang;
17
+ return cache;
18
+ } catch {
19
+ return null;
20
+ }
21
+ }
22
+
23
+ export {
24
+ loadOverlay
25
+ };
26
+ //# sourceMappingURL=chunk-JMBMLOBP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/mcp/marketplace-overlay/loader.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport interface OverlayEntry {\n title: string;\n description: string;\n}\n\nlet cache: Record<string, OverlayEntry> | null = null;\nlet cachedLang: string | null = null;\n\nexport function loadOverlay(lang: string): Record<string, OverlayEntry> | null {\n if (cachedLang === lang && cache) return cache;\n try {\n const dir = dirname(fileURLToPath(import.meta.url));\n const raw = readFileSync(join(dir, `${lang}.json`), \"utf8\");\n cache = JSON.parse(raw) as Record<string, OverlayEntry>;\n cachedLang = lang;\n return cache;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAO9B,IAAI,QAA6C;AACjD,IAAI,aAA4B;AAEzB,SAAS,YAAY,MAAmD;AAC7E,MAAI,eAAe,QAAQ,MAAO,QAAO;AACzC,MAAI;AACF,UAAM,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAClD,UAAM,MAAM,aAAa,KAAK,KAAK,GAAG,IAAI,OAAO,GAAG,MAAM;AAC1D,YAAQ,KAAK,MAAM,GAAG;AACtB,iBAAa;AACb,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
3
+
4
+ // src/version.ts
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
6
+ import { homedir } from "os";
7
+ import { dirname, join } from "path";
8
+ import { fileURLToPath } from "url";
9
+ var REGISTRY_URL = "https://registry.npmjs.org/@carboncode/cli/latest";
10
+ var LATEST_CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
11
+ var LATEST_FETCH_TIMEOUT_MS = 2e3;
12
+ function readPackageVersion() {
13
+ try {
14
+ let dir = dirname(fileURLToPath(import.meta.url));
15
+ for (let i = 0; i < 6; i++) {
16
+ const p = join(dir, "package.json");
17
+ if (existsSync(p)) {
18
+ const pkg = JSON.parse(readFileSync(p, "utf8"));
19
+ if (pkg?.name === "@carboncode/cli" && typeof pkg.version === "string") {
20
+ return pkg.version;
21
+ }
22
+ }
23
+ const parent = dirname(dir);
24
+ if (parent === dir) break;
25
+ dir = parent;
26
+ }
27
+ } catch {
28
+ }
29
+ return "0.0.0-dev";
30
+ }
31
+ var VERSION = readPackageVersion();
32
+ function cachePath(homeDirOverride) {
33
+ return join(homeDirOverride ?? homedir(), ".carboncode", "version-cache.json");
34
+ }
35
+ function readCache(homeDirOverride) {
36
+ try {
37
+ const raw = readFileSync(cachePath(homeDirOverride), "utf8");
38
+ const parsed = JSON.parse(raw);
39
+ if (parsed && typeof parsed.version === "string" && typeof parsed.checkedAt === "number") {
40
+ return parsed;
41
+ }
42
+ } catch {
43
+ }
44
+ return null;
45
+ }
46
+ function writeCache(entry, homeDirOverride) {
47
+ try {
48
+ const p = cachePath(homeDirOverride);
49
+ mkdirSync(dirname(p), { recursive: true });
50
+ writeFileSync(p, JSON.stringify(entry), "utf8");
51
+ } catch {
52
+ }
53
+ }
54
+ async function getLatestVersion(opts = {}) {
55
+ const ttl = opts.ttlMs ?? LATEST_CACHE_TTL_MS;
56
+ if (!opts.force) {
57
+ const cached = readCache(opts.homeDir);
58
+ if (cached && Date.now() - cached.checkedAt < ttl) return cached.version;
59
+ }
60
+ const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
61
+ if (!fetchImpl) return null;
62
+ const url = opts.registryUrl ?? REGISTRY_URL;
63
+ const timeout = opts.timeoutMs ?? LATEST_FETCH_TIMEOUT_MS;
64
+ const controller = new AbortController();
65
+ const timer = setTimeout(() => controller.abort(), timeout);
66
+ try {
67
+ const res = await fetchImpl(url, {
68
+ signal: controller.signal,
69
+ headers: { accept: "application/json" }
70
+ });
71
+ if (!res.ok) return null;
72
+ const body = await res.json();
73
+ if (typeof body.version !== "string") return null;
74
+ writeCache({ version: body.version, checkedAt: Date.now() }, opts.homeDir);
75
+ return body.version;
76
+ } catch {
77
+ return null;
78
+ } finally {
79
+ clearTimeout(timer);
80
+ }
81
+ }
82
+ function compareVersions(a, b) {
83
+ const [aCore = "0", aPre = ""] = a.split("-", 2);
84
+ const [bCore = "0", bPre = ""] = b.split("-", 2);
85
+ const aParts = aCore.split(".").map((p) => Number.parseInt(p, 10) || 0);
86
+ const bParts = bCore.split(".").map((p) => Number.parseInt(p, 10) || 0);
87
+ for (let i = 0; i < 3; i++) {
88
+ const diff = (aParts[i] ?? 0) - (bParts[i] ?? 0);
89
+ if (diff !== 0) return diff;
90
+ }
91
+ if (!aPre && !bPre) return 0;
92
+ if (!aPre) return 1;
93
+ if (!bPre) return -1;
94
+ return aPre < bPre ? -1 : aPre > bPre ? 1 : 0;
95
+ }
96
+ function detectInstallSource(bin) {
97
+ const raw = bin ?? process.argv[1] ?? "";
98
+ if (!raw) return "unknown";
99
+ const norm = raw.replace(/\\/g, "/").toLowerCase();
100
+ if (/\/_npx\//.test(norm)) return "npx";
101
+ if (/\/\.pnpm\//.test(norm) && /dlx/i.test(norm)) return "npx";
102
+ const ua = (process.env.npm_config_user_agent ?? "").toLowerCase();
103
+ if (ua.includes("npx/")) return "npx";
104
+ if (/\/\.bun\//.test(norm) || /\/bun\/install\//.test(norm)) return "bun";
105
+ if (/\/pnpm\/global\//.test(norm) || /\/pnpm\/[^/]+\/node_modules\//.test(norm)) return "pnpm";
106
+ if (/\/yarn\/global\//.test(norm) || /\/\.yarn\/global\//.test(norm)) return "yarn";
107
+ if (/\/node_modules\/@carboncode\/cli(\b|\/)/.test(norm)) return "npm";
108
+ return "unknown";
109
+ }
110
+ function detectNpmInstallPrefix(bin) {
111
+ const raw = bin ?? process.argv[1] ?? "";
112
+ if (!raw) return null;
113
+ const norm = raw.replace(/\\/g, "/");
114
+ const posix = norm.match(/^(.+?)\/lib\/node_modules\/@carboncode\/cli(?:\/|$)/i);
115
+ if (posix) return posix[1] ?? null;
116
+ const win = norm.match(/^(.+?)\/node_modules\/@carboncode\/cli(?:\/|$)/i);
117
+ if (win) return win[1] ?? null;
118
+ return null;
119
+ }
120
+
121
+ export {
122
+ VERSION,
123
+ getLatestVersion,
124
+ compareVersions,
125
+ detectInstallSource,
126
+ detectNpmInstallPrefix
127
+ };
128
+ //# sourceMappingURL=chunk-LN3B5PMX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/version.ts"],"sourcesContent":["/** VERSION sourced from package.json so it never drifts from npm; latest-check returns null on any failure. */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\n/** npm registry endpoint for the `latest` dist-tag of this package. */\nconst REGISTRY_URL = \"https://registry.npmjs.org/@carboncode/cli/latest\";\n\n/** TTL for the on-disk cache entry. 24h keeps noise low; users who\n * want a fresh check can run `carboncode update` which passes\n * `force: true`. */\nexport const LATEST_CACHE_TTL_MS = 24 * 60 * 60 * 1000;\n\n/** Network timeout. Short — we never block the UI waiting on this. */\nexport const LATEST_FETCH_TIMEOUT_MS = 2_000;\n\n/** Package-name guard avoids picking up an outer package.json when loaded as a dep. */\nfunction readPackageVersion(): string {\n try {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 6; i++) {\n const p = join(dir, \"package.json\");\n if (existsSync(p)) {\n const pkg = JSON.parse(readFileSync(p, \"utf8\"));\n if (pkg?.name === \"@carboncode/cli\" && typeof pkg.version === \"string\") {\n return pkg.version;\n }\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n } catch {\n /* fall through to fallback */\n }\n return \"0.0.0-dev\";\n}\n\nexport const VERSION: string = readPackageVersion();\n\ninterface VersionCacheEntry {\n version: string;\n /** Epoch millis the entry was written. Drives TTL comparisons. */\n checkedAt: number;\n}\n\nfunction cachePath(homeDirOverride?: string): string {\n return join(homeDirOverride ?? homedir(), \".carboncode\", \"version-cache.json\");\n}\n\nfunction readCache(homeDirOverride?: string): VersionCacheEntry | null {\n try {\n const raw = readFileSync(cachePath(homeDirOverride), \"utf8\");\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.version === \"string\" && typeof parsed.checkedAt === \"number\") {\n return parsed;\n }\n } catch {\n /* missing or malformed → no cached entry */\n }\n return null;\n}\n\nfunction writeCache(entry: VersionCacheEntry, homeDirOverride?: string): void {\n try {\n const p = cachePath(homeDirOverride);\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, JSON.stringify(entry), \"utf8\");\n } catch {\n /* cache is best-effort — a failed write just means we'll re-fetch\n * next launch. No reason to surface this to the user. */\n }\n}\n\nexport interface GetLatestVersionOptions {\n /** Ignore the cached entry and always fetch fresh. Used by `carboncode update`. */\n force?: boolean;\n /** Registry URL override (tests). */\n registryUrl?: string;\n /** Home-directory override (tests). */\n homeDir?: string;\n /** Fetch implementation override (tests). Defaults to `globalThis.fetch`. */\n fetchImpl?: typeof fetch;\n /** TTL override (tests). */\n ttlMs?: number;\n /** Network timeout override (tests). */\n timeoutMs?: number;\n}\n\n/** Returns null on failure; cache only writes on success so bad responses can't poison it. */\nexport async function getLatestVersion(opts: GetLatestVersionOptions = {}): Promise<string | null> {\n const ttl = opts.ttlMs ?? LATEST_CACHE_TTL_MS;\n if (!opts.force) {\n const cached = readCache(opts.homeDir);\n if (cached && Date.now() - cached.checkedAt < ttl) return cached.version;\n }\n\n const fetchImpl = opts.fetchImpl ?? globalThis.fetch;\n if (!fetchImpl) return null;\n const url = opts.registryUrl ?? REGISTRY_URL;\n const timeout = opts.timeoutMs ?? LATEST_FETCH_TIMEOUT_MS;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeout);\n try {\n const res = await fetchImpl(url, {\n signal: controller.signal,\n headers: { accept: \"application/json\" },\n });\n if (!res.ok) return null;\n const body = (await res.json()) as { version?: unknown };\n if (typeof body.version !== \"string\") return null;\n writeCache({ version: body.version, checkedAt: Date.now() }, opts.homeDir);\n return body.version;\n } catch {\n return null;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** Pre-release with same core sorts BELOW the bare version — matches npm `latest` dist-tag semantics. */\nexport function compareVersions(a: string, b: string): number {\n const [aCore = \"0\", aPre = \"\"] = a.split(\"-\", 2);\n const [bCore = \"0\", bPre = \"\"] = b.split(\"-\", 2);\n const aParts = aCore.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n const bParts = bCore.split(\".\").map((p) => Number.parseInt(p, 10) || 0);\n for (let i = 0; i < 3; i++) {\n const diff = (aParts[i] ?? 0) - (bParts[i] ?? 0);\n if (diff !== 0) return diff;\n }\n if (!aPre && !bPre) return 0;\n if (!aPre) return 1;\n if (!bPre) return -1;\n return aPre < bPre ? -1 : aPre > bPre ? 1 : 0;\n}\n\nexport type InstallSource = \"npm\" | \"bun\" | \"pnpm\" | \"yarn\" | \"npx\" | \"unknown\";\n\n/** Each manager owns a unique global path segment, so argv[1] tells us who installed us. */\nexport function detectInstallSource(bin?: string): InstallSource {\n const raw = bin ?? process.argv[1] ?? \"\";\n if (!raw) return \"unknown\";\n const norm = raw.replace(/\\\\/g, \"/\").toLowerCase();\n if (/\\/_npx\\//.test(norm)) return \"npx\";\n if (/\\/\\.pnpm\\//.test(norm) && /dlx/i.test(norm)) return \"npx\";\n const ua = (process.env.npm_config_user_agent ?? \"\").toLowerCase();\n if (ua.includes(\"npx/\")) return \"npx\";\n if (/\\/\\.bun\\//.test(norm) || /\\/bun\\/install\\//.test(norm)) return \"bun\";\n if (/\\/pnpm\\/global\\//.test(norm) || /\\/pnpm\\/[^/]+\\/node_modules\\//.test(norm)) return \"pnpm\";\n if (/\\/yarn\\/global\\//.test(norm) || /\\/\\.yarn\\/global\\//.test(norm)) return \"yarn\";\n if (/\\/node_modules\\/@carboncode\\/cli(\\b|\\/)/.test(norm)) return \"npm\";\n return \"unknown\";\n}\n\n/** Returns null when no path is given. Callers must check installSource first. */\nexport function isNpxInstall(): boolean {\n return detectInstallSource() === \"npx\";\n}\n\n/** Pin npm to the install location via --prefix so `nvm use` doesn't redirect the install elsewhere. */\nexport function detectNpmInstallPrefix(bin?: string): string | null {\n const raw = bin ?? process.argv[1] ?? \"\";\n if (!raw) return null;\n const norm = raw.replace(/\\\\/g, \"/\");\n const posix = norm.match(/^(.+?)\\/lib\\/node_modules\\/@carboncode\\/cli(?:\\/|$)/i);\n if (posix) return posix[1] ?? null;\n const win = norm.match(/^(.+?)\\/node_modules\\/@carboncode\\/cli(?:\\/|$)/i);\n if (win) return win[1] ?? null;\n return null;\n}\n"],"mappings":";;;;AAEA,SAAS,YAAY,WAAW,cAAc,qBAAqB;AACnE,SAAS,eAAe;AACxB,SAAS,SAAS,YAAY;AAC9B,SAAS,qBAAqB;AAG9B,IAAM,eAAe;AAKd,IAAM,sBAAsB,KAAK,KAAK,KAAK;AAG3C,IAAM,0BAA0B;AAGvC,SAAS,qBAA6B;AACpC,MAAI;AACF,QAAI,MAAM,QAAQ,cAAc,YAAY,GAAG,CAAC;AAChD,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,IAAI,KAAK,KAAK,cAAc;AAClC,UAAI,WAAW,CAAC,GAAG;AACjB,cAAM,MAAM,KAAK,MAAM,aAAa,GAAG,MAAM,CAAC;AAC9C,YAAI,KAAK,SAAS,qBAAqB,OAAO,IAAI,YAAY,UAAU;AACtE,iBAAO,IAAI;AAAA,QACb;AAAA,MACF;AACA,YAAM,SAAS,QAAQ,GAAG;AAC1B,UAAI,WAAW,IAAK;AACpB,YAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,IAAM,UAAkB,mBAAmB;AAQlD,SAAS,UAAU,iBAAkC;AACnD,SAAO,KAAK,mBAAmB,QAAQ,GAAG,eAAe,oBAAoB;AAC/E;AAEA,SAAS,UAAU,iBAAoD;AACrE,MAAI;AACF,UAAM,MAAM,aAAa,UAAU,eAAe,GAAG,MAAM;AAC3D,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,UAAU,OAAO,OAAO,YAAY,YAAY,OAAO,OAAO,cAAc,UAAU;AACxF,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEA,SAAS,WAAW,OAA0B,iBAAgC;AAC5E,MAAI;AACF,UAAM,IAAI,UAAU,eAAe;AACnC,cAAU,QAAQ,CAAC,GAAG,EAAE,WAAW,KAAK,CAAC;AACzC,kBAAc,GAAG,KAAK,UAAU,KAAK,GAAG,MAAM;AAAA,EAChD,QAAQ;AAAA,EAGR;AACF;AAkBA,eAAsB,iBAAiB,OAAgC,CAAC,GAA2B;AACjG,QAAM,MAAM,KAAK,SAAS;AAC1B,MAAI,CAAC,KAAK,OAAO;AACf,UAAM,SAAS,UAAU,KAAK,OAAO;AACrC,QAAI,UAAU,KAAK,IAAI,IAAI,OAAO,YAAY,IAAK,QAAO,OAAO;AAAA,EACnE;AAEA,QAAM,YAAY,KAAK,aAAa,WAAW;AAC/C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,MAAM,KAAK,eAAe;AAChC,QAAM,UAAU,KAAK,aAAa;AAClC,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO;AAC1D,MAAI;AACF,UAAM,MAAM,MAAM,UAAU,KAAK;AAAA,MAC/B,QAAQ,WAAW;AAAA,MACnB,SAAS,EAAE,QAAQ,mBAAmB;AAAA,IACxC,CAAC;AACD,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,UAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAI,OAAO,KAAK,YAAY,SAAU,QAAO;AAC7C,eAAW,EAAE,SAAS,KAAK,SAAS,WAAW,KAAK,IAAI,EAAE,GAAG,KAAK,OAAO;AACzE,WAAO,KAAK;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAGO,SAAS,gBAAgB,GAAW,GAAmB;AAC5D,QAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC/C,QAAM,CAAC,QAAQ,KAAK,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC/C,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,KAAK,CAAC;AACtE,QAAM,SAAS,MAAM,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,OAAO,SAAS,GAAG,EAAE,KAAK,CAAC;AACtE,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,UAAM,QAAQ,OAAO,CAAC,KAAK,MAAM,OAAO,CAAC,KAAK;AAC9C,QAAI,SAAS,EAAG,QAAO;AAAA,EACzB;AACA,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,OAAO,OAAO,KAAK,OAAO,OAAO,IAAI;AAC9C;AAKO,SAAS,oBAAoB,KAA6B;AAC/D,QAAM,MAAM,OAAO,QAAQ,KAAK,CAAC,KAAK;AACtC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,OAAO,IAAI,QAAQ,OAAO,GAAG,EAAE,YAAY;AACjD,MAAI,WAAW,KAAK,IAAI,EAAG,QAAO;AAClC,MAAI,aAAa,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,EAAG,QAAO;AACzD,QAAM,MAAM,QAAQ,IAAI,yBAAyB,IAAI,YAAY;AACjE,MAAI,GAAG,SAAS,MAAM,EAAG,QAAO;AAChC,MAAI,YAAY,KAAK,IAAI,KAAK,mBAAmB,KAAK,IAAI,EAAG,QAAO;AACpE,MAAI,mBAAmB,KAAK,IAAI,KAAK,gCAAgC,KAAK,IAAI,EAAG,QAAO;AACxF,MAAI,mBAAmB,KAAK,IAAI,KAAK,qBAAqB,KAAK,IAAI,EAAG,QAAO;AAC7E,MAAI,0CAA0C,KAAK,IAAI,EAAG,QAAO;AACjE,SAAO;AACT;AAQO,SAAS,uBAAuB,KAA6B;AAClE,QAAM,MAAM,OAAO,QAAQ,KAAK,CAAC,KAAK;AACtC,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,OAAO,IAAI,QAAQ,OAAO,GAAG;AACnC,QAAM,QAAQ,KAAK,MAAM,sDAAsD;AAC/E,MAAI,MAAO,QAAO,MAAM,CAAC,KAAK;AAC9B,QAAM,MAAM,KAAK,MAAM,iDAAiD;AACxE,MAAI,IAAK,QAAO,IAAI,CAAC,KAAK;AAC1B,SAAO;AACT;","names":[]}