@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,50 @@
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
+ t
5
+ } from "./chunk-IAUOP25G.js";
6
+
7
+ // src/cli/ui/mcp-lifecycle.ts
8
+ var STATE = {
9
+ handshake: { glyph: "\u21BB", label: () => t("mcpLifecycle.handshake") },
10
+ connected: { glyph: "\u2713", label: () => t("mcpLifecycle.connected") },
11
+ failed: { glyph: "\u2716", label: () => t("mcpLifecycle.failed") },
12
+ disabled: { glyph: "\u25CB", label: () => t("mcpLifecycle.disabled") },
13
+ reconnect: { glyph: "\u21BB", label: () => t("mcpLifecycle.reconnect") },
14
+ "tools-ready": { glyph: "\u26A1", label: () => "tools ready" },
15
+ warn: { glyph: "\u26A0", label: () => "warn" }
16
+ };
17
+ var NAME_COL = 22;
18
+ var STATE_COL = 15;
19
+ function formatMcpLifecycleEvent(ev) {
20
+ const { glyph, label } = STATE[ev.state];
21
+ const namePart = `MCP \xB7 ${ev.name}`;
22
+ const namePad = " ".repeat(Math.max(1, NAME_COL - namePart.length));
23
+ const stateField = `${glyph} ${label()}`.padEnd(STATE_COL);
24
+ return `\u2318 ${namePart}${namePad}${stateField}${describeDetail(ev)}`;
25
+ }
26
+ function describeDetail(ev) {
27
+ if (ev.state === "handshake") return t("mcpLifecycle.initDetail");
28
+ if (ev.state === "failed") return ev.reason;
29
+ if (ev.state === "disabled") return t("mcpLifecycle.disabledDetail", { name: ev.name });
30
+ if (ev.state === "reconnect") return t("mcpLifecycle.reconnectDetail");
31
+ if (ev.state === "tools-ready") return `${ev.tools} tools \xB7 ${ev.ms}ms`;
32
+ if (ev.state === "warn") return ev.reason;
33
+ const parts = [`${ev.tools} tools`];
34
+ if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);
35
+ if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);
36
+ parts.push(`${ev.ms}ms`);
37
+ return parts.join(" \xB7 ");
38
+ }
39
+
40
+ // src/cli/ui/mcp-toast.ts
41
+ function formatMcpSlowToast(tst) {
42
+ const seconds = (tst.p95Ms / 1e3).toFixed(1);
43
+ return t("mcpHealth.slowToast", { name: tst.name, seconds, sampleSize: tst.sampleSize });
44
+ }
45
+
46
+ export {
47
+ formatMcpLifecycleEvent,
48
+ formatMcpSlowToast
49
+ };
50
+ //# sourceMappingURL=chunk-XJ5SRLKK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/ui/mcp-lifecycle.ts","../../src/cli/ui/mcp-toast.ts"],"sourcesContent":["/** Formats one-liner MCP lifecycle events per `docs/design/agent-tui-terminal.html` §37. */\n\nimport { t } from \"../../i18n/index.js\";\n\nexport type McpLifecycleEvent =\n | { state: \"handshake\"; name: string }\n | {\n state: \"connected\";\n name: string;\n tools: number;\n resources?: number;\n prompts?: number;\n ms: number;\n }\n | { state: \"failed\"; name: string; reason: string }\n | { state: \"disabled\"; name: string }\n | { state: \"reconnect\"; name: string }\n | { state: \"tools-ready\"; name: string; tools: number; ms: number }\n | { state: \"warn\"; name: string; reason: string };\n\nconst STATE: Record<McpLifecycleEvent[\"state\"], { glyph: string; label: () => string }> = {\n handshake: { glyph: \"↻\", label: () => t(\"mcpLifecycle.handshake\") },\n connected: { glyph: \"✓\", label: () => t(\"mcpLifecycle.connected\") },\n failed: { glyph: \"✖\", label: () => t(\"mcpLifecycle.failed\") },\n disabled: { glyph: \"○\", label: () => t(\"mcpLifecycle.disabled\") },\n reconnect: { glyph: \"↻\", label: () => t(\"mcpLifecycle.reconnect\") },\n \"tools-ready\": { glyph: \"⚡\", label: () => \"tools ready\" },\n warn: { glyph: \"⚠\", label: () => \"warn\" },\n};\n\nconst NAME_COL = 22;\nconst STATE_COL = 15;\n\nexport function formatMcpLifecycleEvent(ev: McpLifecycleEvent): string {\n const { glyph, label } = STATE[ev.state];\n const namePart = `MCP · ${ev.name}`;\n const namePad = \" \".repeat(Math.max(1, NAME_COL - namePart.length));\n const stateField = `${glyph} ${label()}`.padEnd(STATE_COL);\n return `⌘ ${namePart}${namePad}${stateField}${describeDetail(ev)}`;\n}\n\nfunction describeDetail(ev: McpLifecycleEvent): string {\n if (ev.state === \"handshake\") return t(\"mcpLifecycle.initDetail\");\n if (ev.state === \"failed\") return ev.reason;\n if (ev.state === \"disabled\") return t(\"mcpLifecycle.disabledDetail\", { name: ev.name });\n if (ev.state === \"reconnect\") return t(\"mcpLifecycle.reconnectDetail\");\n if (ev.state === \"tools-ready\") return `${ev.tools} tools · ${ev.ms}ms`;\n if (ev.state === \"warn\") return ev.reason;\n const parts: string[] = [`${ev.tools} tools`];\n if (ev.resources && ev.resources > 0) parts.push(`${ev.resources} resources`);\n if (ev.prompts && ev.prompts > 0) parts.push(`${ev.prompts} prompts`);\n parts.push(`${ev.ms}ms`);\n return parts.join(\" · \");\n}\n","/** One-line warn toast emitted when an MCP server's p95 crosses the slow threshold (design §32). */\n\nimport { t } from \"../../i18n/index.js\";\n\nexport interface McpSlowToast {\n name: string;\n p95Ms: number;\n sampleSize: number;\n}\n\nexport function formatMcpSlowToast(tst: McpSlowToast): string {\n const seconds = (tst.p95Ms / 1000).toFixed(1);\n return t(\"mcpHealth.slowToast\", { name: tst.name, seconds, sampleSize: tst.sampleSize });\n}\n"],"mappings":";;;;;;;AAoBA,IAAM,QAAoF;AAAA,EACxF,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,QAAQ,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,qBAAqB,EAAE;AAAA,EAC5D,UAAU,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,uBAAuB,EAAE;AAAA,EAChE,WAAW,EAAE,OAAO,UAAK,OAAO,MAAM,EAAE,wBAAwB,EAAE;AAAA,EAClE,eAAe,EAAE,OAAO,UAAK,OAAO,MAAM,cAAc;AAAA,EACxD,MAAM,EAAE,OAAO,UAAK,OAAO,MAAM,OAAO;AAC1C;AAEA,IAAM,WAAW;AACjB,IAAM,YAAY;AAEX,SAAS,wBAAwB,IAA+B;AACrE,QAAM,EAAE,OAAO,MAAM,IAAI,MAAM,GAAG,KAAK;AACvC,QAAM,WAAW,YAAS,GAAG,IAAI;AACjC,QAAM,UAAU,IAAI,OAAO,KAAK,IAAI,GAAG,WAAW,SAAS,MAAM,CAAC;AAClE,QAAM,aAAa,GAAG,KAAK,IAAI,MAAM,CAAC,GAAG,OAAO,SAAS;AACzD,SAAO,UAAK,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,eAAe,EAAE,CAAC;AAClE;AAEA,SAAS,eAAe,IAA+B;AACrD,MAAI,GAAG,UAAU,YAAa,QAAO,EAAE,yBAAyB;AAChE,MAAI,GAAG,UAAU,SAAU,QAAO,GAAG;AACrC,MAAI,GAAG,UAAU,WAAY,QAAO,EAAE,+BAA+B,EAAE,MAAM,GAAG,KAAK,CAAC;AACtF,MAAI,GAAG,UAAU,YAAa,QAAO,EAAE,8BAA8B;AACrE,MAAI,GAAG,UAAU,cAAe,QAAO,GAAG,GAAG,KAAK,eAAY,GAAG,EAAE;AACnE,MAAI,GAAG,UAAU,OAAQ,QAAO,GAAG;AACnC,QAAM,QAAkB,CAAC,GAAG,GAAG,KAAK,QAAQ;AAC5C,MAAI,GAAG,aAAa,GAAG,YAAY,EAAG,OAAM,KAAK,GAAG,GAAG,SAAS,YAAY;AAC5E,MAAI,GAAG,WAAW,GAAG,UAAU,EAAG,OAAM,KAAK,GAAG,GAAG,OAAO,UAAU;AACpE,QAAM,KAAK,GAAG,GAAG,EAAE,IAAI;AACvB,SAAO,MAAM,KAAK,QAAK;AACzB;;;AC3CO,SAAS,mBAAmB,KAA2B;AAC5D,QAAM,WAAW,IAAI,QAAQ,KAAM,QAAQ,CAAC;AAC5C,SAAO,EAAE,uBAAuB,EAAE,MAAM,IAAI,MAAM,SAAS,YAAY,IAAI,WAAW,CAAC;AACzF;","names":[]}
@@ -0,0 +1,54 @@
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
+ sanitizeName,
5
+ sessionsDir
6
+ } from "./chunk-U4IJVG32.js";
7
+
8
+ // src/adapters/event-sink-jsonl.ts
9
+ import { chmodSync, createWriteStream, mkdirSync } from "fs";
10
+ import { dirname, join } from "path";
11
+ function eventLogPath(sessionName) {
12
+ return join(sessionsDir(), `${sanitizeName(sessionName)}.events.jsonl`);
13
+ }
14
+ var JsonlEventSink = class {
15
+ constructor(stream) {
16
+ this.stream = stream;
17
+ }
18
+ stream;
19
+ buffered = 0;
20
+ append(ev) {
21
+ if (ev.type === "model.delta") return;
22
+ this.stream.write(`${JSON.stringify(ev)}
23
+ `);
24
+ this.buffered++;
25
+ }
26
+ flush() {
27
+ return new Promise((resolve) => {
28
+ if (this.buffered === 0) return resolve();
29
+ this.stream.uncork();
30
+ this.buffered = 0;
31
+ resolve();
32
+ });
33
+ }
34
+ close() {
35
+ return new Promise((resolve) => {
36
+ this.stream.end(() => resolve());
37
+ });
38
+ }
39
+ };
40
+ function openEventSink(path) {
41
+ mkdirSync(dirname(path), { recursive: true });
42
+ const stream = createWriteStream(path, { flags: "a" });
43
+ try {
44
+ chmodSync(path, 384);
45
+ } catch {
46
+ }
47
+ return new JsonlEventSink(stream);
48
+ }
49
+
50
+ export {
51
+ eventLogPath,
52
+ openEventSink
53
+ };
54
+ //# sourceMappingURL=chunk-YZSXRGFH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/adapters/event-sink-jsonl.ts"],"sourcesContent":["import { type WriteStream, chmodSync, createWriteStream, mkdirSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport type { Event } from \"../core/events.js\";\nimport { sanitizeName, sessionsDir } from \"../memory/session.js\";\nimport type { EventSink } from \"../ports/event-sink.js\";\n\nexport function eventLogPath(sessionName: string): string {\n return join(sessionsDir(), `${sanitizeName(sessionName)}.events.jsonl`);\n}\n\nexport class JsonlEventSink implements EventSink {\n private buffered = 0;\n\n constructor(private readonly stream: WriteStream) {}\n\n append(ev: Event): void {\n // Skip model.delta — recoverable from model.final.text, would balloon sidecar.\n if (ev.type === \"model.delta\") return;\n this.stream.write(`${JSON.stringify(ev)}\\n`);\n this.buffered++;\n }\n\n flush(): Promise<void> {\n return new Promise((resolve) => {\n if (this.buffered === 0) return resolve();\n this.stream.uncork();\n this.buffered = 0;\n resolve();\n });\n }\n\n close(): Promise<void> {\n return new Promise((resolve) => {\n this.stream.end(() => resolve());\n });\n }\n}\n\nexport function openEventSink(path: string): JsonlEventSink {\n mkdirSync(dirname(path), { recursive: true });\n const stream = createWriteStream(path, { flags: \"a\" });\n try {\n chmodSync(path, 0o600);\n } catch {\n /* chmod no-op on Windows */\n }\n return new JsonlEventSink(stream);\n}\n"],"mappings":";;;;;;;;AAAA,SAA2B,WAAW,mBAAmB,iBAAiB;AAC1E,SAAS,SAAS,YAAY;AAKvB,SAAS,aAAa,aAA6B;AACxD,SAAO,KAAK,YAAY,GAAG,GAAG,aAAa,WAAW,CAAC,eAAe;AACxE;AAEO,IAAM,iBAAN,MAA0C;AAAA,EAG/C,YAA6B,QAAqB;AAArB;AAAA,EAAsB;AAAA,EAAtB;AAAA,EAFrB,WAAW;AAAA,EAInB,OAAO,IAAiB;AAEtB,QAAI,GAAG,SAAS,cAAe;AAC/B,SAAK,OAAO,MAAM,GAAG,KAAK,UAAU,EAAE,CAAC;AAAA,CAAI;AAC3C,SAAK;AAAA,EACP;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,KAAK,aAAa,EAAG,QAAO,QAAQ;AACxC,WAAK,OAAO,OAAO;AACnB,WAAK,WAAW;AAChB,cAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEA,QAAuB;AACrB,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,WAAK,OAAO,IAAI,MAAM,QAAQ,CAAC;AAAA,IACjC,CAAC;AAAA,EACH;AACF;AAEO,SAAS,cAAc,MAA8B;AAC1D,YAAU,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC5C,QAAM,SAAS,kBAAkB,MAAM,EAAE,OAAO,IAAI,CAAC;AACrD,MAAI;AACF,cAAU,MAAM,GAAK;AAAA,EACvB,QAAQ;AAAA,EAER;AACA,SAAO,IAAI,eAAe,MAAM;AAClC;","names":[]}
@@ -0,0 +1,163 @@
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
+ chatCommand
5
+ } from "./chunk-J5BYPUB5.js";
6
+ import "./chunk-CXVWUPA3.js";
7
+ import "./chunk-JMBMLOBP.js";
8
+ import "./chunk-CPKCNHRR.js";
9
+ import {
10
+ buildCodeToolset
11
+ } from "./chunk-S2KIUQKQ.js";
12
+ import "./chunk-WLHH3OSR.js";
13
+ import "./chunk-XJ5SRLKK.js";
14
+ import "./chunk-VPMBGAND.js";
15
+ import {
16
+ markPhase
17
+ } from "./chunk-ECHSFYOY.js";
18
+ import "./chunk-4TVNJWMA.js";
19
+ import "./chunk-7L2WTRNU.js";
20
+ import "./chunk-T5TQ4NDT.js";
21
+ import "./chunk-GALC45Q2.js";
22
+ import "./chunk-QJG7OF27.js";
23
+ import "./chunk-FEZK652I.js";
24
+ import "./chunk-UI66BH6D.js";
25
+ import "./chunk-D5NFKRGO.js";
26
+ import "./chunk-X53B3JIX.js";
27
+ import {
28
+ resolvePreset
29
+ } from "./chunk-2425HK6U.js";
30
+ import "./chunk-BSINVTTL.js";
31
+ import "./chunk-5QCB62C4.js";
32
+ import "./chunk-6OWJV3YW.js";
33
+ import "./chunk-BSGCXZQN.js";
34
+ import "./chunk-25T6CVUP.js";
35
+ import {
36
+ loadDotenv
37
+ } from "./chunk-2UQP6H6T.js";
38
+ import "./chunk-4IBIPQVB.js";
39
+ import "./chunk-7EO27TB3.js";
40
+ import "./chunk-PJS34556.js";
41
+ import "./chunk-YZSXRGFH.js";
42
+ import "./chunk-4VR6XF4P.js";
43
+ import "./chunk-3OAR6NVL.js";
44
+ import "./chunk-TH756VLN.js";
45
+ import {
46
+ detectForeignAgentPlatform
47
+ } from "./chunk-M2UFZUX3.js";
48
+ import "./chunk-BHTZFEYE.js";
49
+ import "./chunk-JKGYMRX5.js";
50
+ import "./chunk-WRN65TRD.js";
51
+ import "./chunk-IX6XI2RG.js";
52
+ import "./chunk-S4XVGLRW.js";
53
+ import {
54
+ sanitizeName
55
+ } from "./chunk-U4IJVG32.js";
56
+ import "./chunk-QVC75MR3.js";
57
+ import "./chunk-ILJOIQ5W.js";
58
+ import {
59
+ t
60
+ } from "./chunk-IAUOP25G.js";
61
+ import {
62
+ loadApiKey,
63
+ loadPreset,
64
+ readConfig
65
+ } from "./chunk-4MQ3VURH.js";
66
+ import "./chunk-LN3B5PMX.js";
67
+ import "./chunk-TUK7OWJA.js";
68
+
69
+ // src/cli/commands/code.tsx
70
+ import { readFileSync } from "fs";
71
+ import { basename, resolve } from "path";
72
+ async function codeCommand(opts = {}) {
73
+ markPhase("code_command_enter");
74
+ const resolvedModel = opts.model ?? resolvePreset(loadPreset()).model;
75
+ loadDotenv();
76
+ const cfgKey = loadApiKey();
77
+ if (cfgKey && !process.env.DEEPSEEK_API_KEY) {
78
+ process.env.DEEPSEEK_API_KEY = cfgKey;
79
+ }
80
+ const { codeSystemPrompt } = await import("./prompt-3CDII3UO.js");
81
+ const rootDir = resolve(opts.dir ?? process.cwd());
82
+ const session = opts.noSession ? void 0 : `code-${sanitizeName(basename(rootDir))}`;
83
+ markPhase("semantic_bootstrap_start");
84
+ const { tools, jobs, registerRooted, reBootstrapSemantic, semantic } = await buildCodeToolset({
85
+ rootDir
86
+ });
87
+ markPhase(
88
+ semantic.enabled ? "semantic_bootstrap_done_enabled" : "semantic_bootstrap_done_skipped"
89
+ );
90
+ process.stderr.write(
91
+ `${t("startup.codeRooted", {
92
+ rootDir,
93
+ session: session ?? t("startup.ephemeral"),
94
+ tools: tools.size,
95
+ semantic: semantic.enabled ? t("startup.semanticOn") : ""
96
+ })}
97
+ `
98
+ );
99
+ const foreign = detectForeignAgentPlatform(rootDir);
100
+ if (foreign) {
101
+ process.stderr.write(t("code.workspaceConflict", { platforms: foreign.join(", ") }));
102
+ }
103
+ process.once("exit", () => {
104
+ void jobs.shutdown();
105
+ });
106
+ let systemAppendFileContents;
107
+ if (opts.systemAppend !== void 0 && opts.systemAppend.trim().length === 0) {
108
+ process.stderr.write(t("code.systemAppendEmpty"));
109
+ }
110
+ if (opts.systemAppendFile) {
111
+ const filePath = resolve(opts.systemAppendFile);
112
+ try {
113
+ systemAppendFileContents = readFileSync(filePath, "utf8");
114
+ } catch (err) {
115
+ const e = err;
116
+ const errorDetails = e.code ? `[${e.code}] ${e.message}` : e.message;
117
+ process.stderr.write(t("code.systemAppendFileReadError", { filePath, errorDetails }));
118
+ process.exit(1);
119
+ }
120
+ }
121
+ let currentRoot = rootDir;
122
+ let semanticEnabled = semantic.enabled;
123
+ const codeRebuildSystem = () => codeSystemPrompt(currentRoot, {
124
+ hasSemanticSearch: semanticEnabled,
125
+ systemAppend: opts.systemAppend,
126
+ systemAppendFile: systemAppendFileContents,
127
+ modelId: resolvedModel
128
+ });
129
+ await chatCommand({
130
+ model: resolvedModel,
131
+ budgetUsd: opts.budgetUsd,
132
+ system: codeRebuildSystem(),
133
+ rebuildSystem: codeRebuildSystem,
134
+ transcript: opts.transcript,
135
+ session,
136
+ seedTools: tools,
137
+ codeMode: {
138
+ rootDir,
139
+ jobs,
140
+ reregisterTools: registerRooted,
141
+ reBootstrapSemantic: async (root) => {
142
+ const r = await reBootstrapSemantic(root);
143
+ semanticEnabled = r.enabled;
144
+ return r;
145
+ },
146
+ onRootChange: (newRoot) => {
147
+ currentRoot = newRoot;
148
+ }
149
+ },
150
+ mcp: readConfig().mcp,
151
+ forceResume: opts.forceResume,
152
+ forceNew: opts.forceNew,
153
+ noDashboard: opts.noDashboard,
154
+ openDashboard: opts.openDashboard,
155
+ dashboardPort: opts.dashboardPort,
156
+ dashboardHost: opts.dashboardHost,
157
+ dashboardToken: opts.dashboardToken
158
+ });
159
+ }
160
+ export {
161
+ codeCommand
162
+ };
163
+ //# sourceMappingURL=code-4TUTAGO5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/commands/code.tsx"],"sourcesContent":["/**\n * `carboncode code [dir]` — opinionated wrapper around `carboncode chat` for\n * code-editing workflows.\n *\n * What it does differently from plain chat:\n * - Registers native filesystem tools rooted at the given directory\n * (CWD by default). No subprocess, no `npx install` step, R1-\n * friendly schemas. Replaced the old `@modelcontextprotocol/server-filesystem`\n * subprocess in 0.4.9 because its `edit_file` argv shape was the\n * biggest driver of R1 DSML hallucinations.\n * - Uses a coding-focused system prompt (src/code/prompt.ts) that\n * teaches the model to propose edits as SEARCH/REPLACE blocks.\n * - Defaults to the `smart` preset (reasoner + harvest) because\n * coding tasks pay back R1 thinking.\n * - Scopes its session to the directory so projects don't share\n * conversation history.\n * - Hooks `codeMode` into the TUI so assistant replies get parsed\n * for SEARCH/REPLACE blocks and applied on disk after each turn.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { basename, resolve } from \"node:path\";\nimport { buildCodeToolset } from \"../../code/setup.js\";\nimport { loadApiKey, loadPreset, readConfig } from \"../../config.js\";\nimport { loadDotenv } from \"../../env.js\";\nimport { t } from \"../../i18n/index.js\";\nimport { detectForeignAgentPlatform } from \"../../memory/project.js\";\nimport { sanitizeName } from \"../../memory/session.js\";\nimport { markPhase } from \"../startup-profile.js\";\nimport { resolvePreset } from \"../ui/presets.js\";\nimport { chatCommand } from \"./chat.js\";\n\nexport interface CodeOptions {\n /** Directory to root the filesystem tools at. Defaults to process.cwd(). */\n dir?: string;\n /** Override the default `smart` model. */\n model?: string;\n /** Disable session persistence. */\n noSession?: boolean;\n /** Transcript file for replay/diff. */\n transcript?: string;\n /** Skip the session picker — always resume prior messages. */\n forceResume?: boolean;\n /** Skip the session picker — always wipe prior messages and start fresh. */\n forceNew?: boolean;\n /**\n * Soft USD spend cap. Off by default. Same semantics as `chat`:\n * warns at 80%, refuses next turn at 100%. Mid-session adjustable\n * via `/budget <usd>` slash command.\n */\n budgetUsd?: number;\n /** Suppress the auto-launched embedded web dashboard. */\n noDashboard?: boolean;\n /** When true and the dashboard is enabled, open its URL in the system default browser as soon as the server is ready. */\n openDashboard?: boolean;\n /** Pin the dashboard to a fixed port. `undefined` keeps ephemeral assignment. */\n dashboardPort?: number;\n /** Dashboard bind address (#968). `undefined` keeps the default 127.0.0.1. */\n dashboardHost?: string;\n /** Stable dashboard URL token (#968). `undefined` mints a fresh per-boot token. */\n dashboardToken?: string;\n /** Inline string appended to the code system prompt after the generated base prompt. */\n systemAppend?: string;\n /** Path to a UTF-8 text file whose contents are appended to the code system prompt. */\n systemAppendFile?: string;\n}\n\nexport async function codeCommand(opts: CodeOptions = {}): Promise<void> {\n markPhase(\"code_command_enter\");\n const resolvedModel = opts.model ?? resolvePreset(loadPreset()).model;\n // Bridge .env + ~/.carboncode/config.json into process.env so buildCodeToolset's\n // eager DeepSeekClient constructions (subagent client; semantic embedder) can\n // pick up a key the user already configured via `carboncode setup`. chatCommand\n // does the same dance — code.tsx wraps chatCommand but must also seed env\n // before buildCodeToolset runs, which is BEFORE chatCommand.\n loadDotenv();\n const cfgKey = loadApiKey();\n if (cfgKey && !process.env.DEEPSEEK_API_KEY) {\n process.env.DEEPSEEK_API_KEY = cfgKey;\n }\n const { codeSystemPrompt } = await import(\"../../code/prompt.js\");\n const rootDir = resolve(opts.dir ?? process.cwd());\n // Per-directory session so switching projects doesn't mix histories.\n // `code-<sanitized-basename>` fits the session name rules without\n // truncating most project names.\n const session = opts.noSession ? undefined : `code-${sanitizeName(basename(rootDir))}`;\n\n markPhase(\"semantic_bootstrap_start\");\n const { tools, jobs, registerRooted, reBootstrapSemantic, semantic } = await buildCodeToolset({\n rootDir,\n });\n markPhase(\n semantic.enabled ? \"semantic_bootstrap_done_enabled\" : \"semantic_bootstrap_done_skipped\",\n );\n\n process.stderr.write(\n `${t(\"startup.codeRooted\", {\n rootDir,\n session: session ?? t(\"startup.ephemeral\"),\n tools: tools.size,\n semantic: semantic.enabled ? t(\"startup.semanticOn\") : \"\",\n })}\\n`,\n );\n\n const foreign = detectForeignAgentPlatform(rootDir);\n if (foreign) {\n process.stderr.write(t(\"code.workspaceConflict\", { platforms: foreign.join(\", \") }));\n }\n\n // Belt-and-suspenders cleanup: even though spawn(detached:false)\n // should tie child processes to the parent's lifetime, Windows cmd.exe\n // wrappers occasionally leak. We DON'T install SIGINT/SIGTERM\n // handlers here — that overrode Node's default \"exit on Ctrl+C\" with\n // a silent no-op, which made Ctrl+C feel broken in the TUI. App.tsx\n // owns the SIGINT path now (it shows the quit-armed banner and calls\n // exit() on confirmation); this 'exit' hook just guarantees the job\n // registry is drained on the way out, regardless of which exit path\n // fired.\n process.once(\"exit\", () => {\n void jobs.shutdown();\n });\n\n let systemAppendFileContents: string | undefined;\n if (opts.systemAppend !== undefined && opts.systemAppend.trim().length === 0) {\n process.stderr.write(t(\"code.systemAppendEmpty\"));\n }\n if (opts.systemAppendFile) {\n const filePath = resolve(opts.systemAppendFile);\n try {\n systemAppendFileContents = readFileSync(filePath, \"utf8\");\n } catch (err) {\n const e = err as NodeJS.ErrnoException;\n const errorDetails = e.code ? `[${e.code}] ${e.message}` : e.message;\n process.stderr.write(t(\"code.systemAppendFileReadError\", { filePath, errorDetails }));\n process.exit(1);\n }\n }\n\n // The rebuilder is re-invoked on `/new` and `/cwd`. `currentRoot` is the live\n // pointer; `/cwd` updates it via `onRootChange` so the rebuild picks up the\n // new workspace's project rules / memory without restarting the loop.\n let currentRoot = rootDir;\n let semanticEnabled = semantic.enabled;\n const codeRebuildSystem = () =>\n codeSystemPrompt(currentRoot, {\n hasSemanticSearch: semanticEnabled,\n systemAppend: opts.systemAppend,\n systemAppendFile: systemAppendFileContents,\n modelId: resolvedModel,\n });\n await chatCommand({\n model: resolvedModel,\n budgetUsd: opts.budgetUsd,\n system: codeRebuildSystem(),\n rebuildSystem: codeRebuildSystem,\n transcript: opts.transcript,\n session,\n seedTools: tools,\n codeMode: {\n rootDir,\n jobs,\n reregisterTools: registerRooted,\n reBootstrapSemantic: async (root: string) => {\n const r = await reBootstrapSemantic(root);\n semanticEnabled = r.enabled;\n return r;\n },\n onRootChange: (newRoot: string) => {\n currentRoot = newRoot;\n },\n },\n mcp: readConfig().mcp,\n forceResume: opts.forceResume,\n forceNew: opts.forceNew,\n noDashboard: opts.noDashboard,\n openDashboard: opts.openDashboard,\n dashboardPort: opts.dashboardPort,\n dashboardHost: opts.dashboardHost,\n dashboardToken: opts.dashboardToken,\n });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,356 @@
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
+ checkOllamaStatus,
5
+ pullOllamaModel,
6
+ startOllamaDaemon
7
+ } from "./chunk-JKGYMRX5.js";
8
+ import {
9
+ buildIndex
10
+ } from "./chunk-WRN65TRD.js";
11
+ import "./chunk-S4XVGLRW.js";
12
+ import {
13
+ loadIndexConfig,
14
+ resolveSemanticEmbeddingConfig
15
+ } from "./chunk-4MQ3VURH.js";
16
+ import "./chunk-TUK7OWJA.js";
17
+
18
+ // src/cli/commands/index.ts
19
+ import { resolve } from "path";
20
+
21
+ // src/index/semantic/i18n.ts
22
+ var cachedLocale = null;
23
+ function detectLocale() {
24
+ if (cachedLocale) return cachedLocale;
25
+ const override = (process.env.REASONIX_LANG ?? "").toLowerCase();
26
+ if (override === "zh" || override === "en") {
27
+ cachedLocale = override;
28
+ return cachedLocale;
29
+ }
30
+ const env = process.env.LANG ?? process.env.LC_ALL ?? process.env.LC_MESSAGES ?? "";
31
+ if (/^zh[-_]/i.test(env)) {
32
+ cachedLocale = "zh";
33
+ return "zh";
34
+ }
35
+ try {
36
+ const sys = new Intl.DateTimeFormat().resolvedOptions().locale ?? "";
37
+ if (/^zh[-_]/i.test(sys)) {
38
+ cachedLocale = "zh";
39
+ return "zh";
40
+ }
41
+ } catch {
42
+ }
43
+ cachedLocale = "en";
44
+ return "en";
45
+ }
46
+ function t(key, vars = {}) {
47
+ const loc = detectLocale();
48
+ const dict = loc === "zh" ? ZH : EN;
49
+ const tpl = dict[key] ?? EN[key];
50
+ return tpl.replace(/\{(\w+)\}/g, (_m, name) => {
51
+ const v = vars[name];
52
+ return v === void 0 ? `{${name}}` : String(v);
53
+ });
54
+ }
55
+ var EN = {
56
+ // ── preflight ─────────────────────────────────────────────────────
57
+ ollamaNotFound: "\u2717 `ollama` not found on PATH.\n Install from https://ollama.com (one-time, ~150 MB), then retry.\n",
58
+ daemonNotReachableHint: "\u2717 Ollama daemon not reachable. Run `ollama serve` and retry, or pass --yes to start it automatically.\n",
59
+ daemonStartConfirm: "Ollama daemon isn't running. Start `ollama serve` now?",
60
+ daemonAbortStart: "\u2717 aborted \u2014 start `ollama serve` yourself and retry.\n",
61
+ daemonStarting: "\u25B8 starting `ollama serve`\u2026\n",
62
+ daemonStartTimeout: "\u2717 daemon didn't come up within 15s. Try `ollama serve` in a separate terminal and retry.\n",
63
+ daemonReady: "\u2713 daemon up{pid}\n",
64
+ modelNotPulledHint: '\u2717 embedding model "{model}" not pulled. Run `ollama pull {model}` and retry, or pass --yes to pull it automatically.\n',
65
+ modelPullConfirm: `Embedding model "{model}" isn't pulled yet. Pull it now? (~274 MB for nomic-embed-text)`,
66
+ modelAbortPull: "\u2717 aborted \u2014 pull the model yourself and retry.\n",
67
+ modelPulling: "\u25B8 pulling {model}\u2026\n",
68
+ modelPullFailed: "\u2717 `ollama pull {model}` failed (exit {code}).\n",
69
+ modelPulled: "\u2713 {model} pulled\n",
70
+ // ── progress ─────────────────────────────────────────────────────
71
+ // The TTY-mode progress writer paints `<spinner> <status> <elapsed>s`
72
+ // every 120ms. The status itself comes from one of these keys based
73
+ // on the current phase. {files}, {done}, {total}, {pct} are
74
+ // substituted by the writer.
75
+ progressStarting: "starting\u2026",
76
+ progressScan: "scanning project \xB7 {files} files",
77
+ progressEmbed: "embedding {done}/{total} chunks \xB7 {pct}%",
78
+ progressEmbedHeartbeat: " {done}/{total}\n",
79
+ progressScanLine: "scanning files\u2026\n",
80
+ progressEmbedLine: "embedding {total} chunks across {files} files\u2026\n",
81
+ // Final result line after a successful build.
82
+ indexSuccess: "\u2713 indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed) in {seconds}s\n",
83
+ indexSuccessWithSkips: "\u2713 indexed {scanned} files ({changed} changed, {added} new chunks, {removed} stale removed, {skipped} skipped due to embed errors) in {seconds}s\n",
84
+ indexNothingToDo: " (nothing to do \u2014 re-run with --rebuild to force a full rebuild)\n",
85
+ indexFailed: "\u2717 index failed: {msg}\n",
86
+ // ── /semantic slash ──────────────────────────────────────────────
87
+ slashHeader: "semantic_search status",
88
+ slashEnabled: "\u2713 enabled \u2014 index built, tool registered.",
89
+ slashEnabledDetail: " index size: {chunks} chunks across {files} files",
90
+ slashEnabledHowto: " the model will call semantic_search automatically when it fits.",
91
+ slashIndexMissing: "\u2717 no index built yet for this project.",
92
+ slashHowToBuild: " to enable, exit Carbon Code and run in your shell:\n carboncode index",
93
+ slashOllamaMissing: " prerequisite: install Ollama from https://ollama.com",
94
+ slashDaemonDown: " Ollama is installed but the daemon isn't running. start it with: ollama serve",
95
+ slashIndexInfo: " what semantic_search does: cross-language code understanding via local embeddings.\n better than grep when you describe WHAT something does, not WHICH token to find."
96
+ };
97
+ var ZH = {
98
+ ollamaNotFound: "\u2717 \u672A\u627E\u5230 `ollama`\u3002\n \u8BF7\u8BBF\u95EE https://ollama.com \u5B89\u88C5\uFF08\u4E00\u6B21\u6027\uFF0C\u7EA6 150 MB\uFF09\uFF0C\u7136\u540E\u91CD\u8BD5\u3002\n",
99
+ daemonNotReachableHint: "\u2717 Ollama \u5B88\u62A4\u8FDB\u7A0B\u672A\u542F\u52A8\u3002\u8BF7\u8FD0\u884C `ollama serve` \u540E\u91CD\u8BD5\uFF0C\u6216\u52A0 --yes \u8BA9\u6211\u81EA\u52A8\u542F\u52A8\u3002\n",
100
+ daemonStartConfirm: "Ollama \u5B88\u62A4\u8FDB\u7A0B\u672A\u8FD0\u884C\u3002\u73B0\u5728\u542F\u52A8 `ollama serve` \u5417\uFF1F",
101
+ daemonAbortStart: "\u2717 \u5DF2\u53D6\u6D88\u2014\u2014\u8BF7\u81EA\u884C\u8FD0\u884C `ollama serve` \u540E\u91CD\u8BD5\u3002\n",
102
+ daemonStarting: "\u25B8 \u6B63\u5728\u542F\u52A8 `ollama serve`\u2026\n",
103
+ daemonStartTimeout: "\u2717 15 \u79D2\u5185\u5B88\u62A4\u8FDB\u7A0B\u672A\u5C31\u7EEA\u3002\u8BF7\u5728\u53E6\u4E00\u4E2A\u7EC8\u7AEF\u8FD0\u884C `ollama serve` \u540E\u91CD\u8BD5\u3002\n",
104
+ daemonReady: "\u2713 \u5B88\u62A4\u8FDB\u7A0B\u5DF2\u542F\u52A8{pid}\n",
105
+ modelNotPulledHint: '\u2717 \u5D4C\u5165\u6A21\u578B "{model}" \u672A\u4E0B\u8F7D\u3002\u8BF7\u8FD0\u884C `ollama pull {model}` \u540E\u91CD\u8BD5\uFF0C\u6216\u52A0 --yes \u8BA9\u6211\u81EA\u52A8\u4E0B\u8F7D\u3002\n',
106
+ modelPullConfirm: '\u5D4C\u5165\u6A21\u578B "{model}" \u8FD8\u672A\u4E0B\u8F7D\u3002\u73B0\u5728\u4E0B\u8F7D\u5417\uFF1F\uFF08nomic-embed-text \u7EA6 274 MB\uFF09',
107
+ modelAbortPull: "\u2717 \u5DF2\u53D6\u6D88\u2014\u2014\u8BF7\u81EA\u884C\u4E0B\u8F7D\u6A21\u578B\u540E\u91CD\u8BD5\u3002\n",
108
+ modelPulling: "\u25B8 \u6B63\u5728\u4E0B\u8F7D {model}\u2026\n",
109
+ modelPullFailed: "\u2717 `ollama pull {model}` \u5931\u8D25\uFF08\u9000\u51FA\u7801 {code}\uFF09\u3002\n",
110
+ modelPulled: "\u2713 {model} \u4E0B\u8F7D\u5B8C\u6210\n",
111
+ progressStarting: "\u6B63\u5728\u542F\u52A8\u2026",
112
+ progressScan: "\u626B\u63CF\u9879\u76EE \xB7 \u5DF2\u626B\u63CF {files} \u4E2A\u6587\u4EF6",
113
+ progressEmbed: "\u6B63\u5728\u5411\u91CF\u5316 {done}/{total} \u4E2A\u7247\u6BB5 \xB7 {pct}%",
114
+ progressEmbedHeartbeat: " {done}/{total}\n",
115
+ progressScanLine: "\u6B63\u5728\u626B\u63CF\u6587\u4EF6\u2026\n",
116
+ progressEmbedLine: "\u6B63\u5728\u5411\u91CF\u5316 {total} \u4E2A\u7247\u6BB5\uFF08\u6D89\u53CA {files} \u4E2A\u6587\u4EF6\uFF09\u2026\n",
117
+ indexSuccess: "\u2713 \u5DF2\u5EFA\u7ACB\u7D22\u5F15\uFF1A\u626B\u63CF {scanned} \u4E2A\u6587\u4EF6\uFF08{changed} \u4E2A\u6709\u53D8\u5316\uFF0C\u65B0\u589E {added} \u4E2A\u7247\u6BB5\uFF0C\u79FB\u9664 {removed} \u4E2A\u8FC7\u671F\uFF09\uFF1B\u8017\u65F6 {seconds}s\n",
118
+ indexSuccessWithSkips: "\u2713 \u5DF2\u5EFA\u7ACB\u7D22\u5F15\uFF1A\u626B\u63CF {scanned} \u4E2A\u6587\u4EF6\uFF08{changed} \u4E2A\u6709\u53D8\u5316\uFF0C\u65B0\u589E {added} \u4E2A\u7247\u6BB5\uFF0C\u79FB\u9664 {removed} \u4E2A\u8FC7\u671F\uFF0C\u8DF3\u8FC7 {skipped} \u4E2A\u5D4C\u5165\u5931\u8D25\u7684\u7247\u6BB5\uFF09\uFF1B\u8017\u65F6 {seconds}s\n",
119
+ indexNothingToDo: " \uFF08\u6CA1\u6709\u53D8\u5316\u2014\u2014\u52A0 --rebuild \u5F3A\u5236\u91CD\u5EFA\uFF09\n",
120
+ indexFailed: "\u2717 \u5EFA\u7ACB\u7D22\u5F15\u5931\u8D25\uFF1A{msg}\n",
121
+ slashHeader: "semantic_search \u72B6\u6001",
122
+ slashEnabled: "\u2713 \u5DF2\u542F\u7528\u2014\u2014\u7D22\u5F15\u5DF2\u5EFA\u597D\uFF0C\u5DE5\u5177\u5DF2\u6CE8\u518C\u3002",
123
+ slashEnabledDetail: " \u7D22\u5F15\u89C4\u6A21\uFF1A{chunks} \u4E2A\u7247\u6BB5\uFF0C{files} \u4E2A\u6587\u4EF6",
124
+ slashEnabledHowto: " \u6A21\u578B\u5728\u5408\u9002\u7684\u65F6\u5019\u4F1A\u81EA\u52A8\u8C03\u7528 semantic_search\u3002",
125
+ slashIndexMissing: "\u2717 \u5F53\u524D\u9879\u76EE\u8FD8\u6CA1\u6709\u7D22\u5F15\u3002",
126
+ slashHowToBuild: " \u542F\u7528\u65B9\u5F0F\uFF1A\u9000\u51FA Carbon Code\uFF0C\u5728\u7EC8\u7AEF\u8FD0\u884C\uFF1A\n carboncode index",
127
+ slashOllamaMissing: " \u524D\u7F6E\u4F9D\u8D56\uFF1A\u4ECE https://ollama.com \u5B89\u88C5 Ollama",
128
+ slashDaemonDown: " \u5DF2\u88C5 Ollama \u4F46\u5B88\u62A4\u8FDB\u7A0B\u672A\u542F\u52A8\uFF0C\u8BF7\u8FD0\u884C\uFF1Aollama serve",
129
+ slashIndexInfo: ' semantic_search \u7528\u672C\u5730 embedding \u505A\u8DE8\u8BED\u8A00\u4EE3\u7801\u7406\u89E3\u3002\n \u5F53\u4F60\u63CF\u8FF0"\u505A\u4EC0\u4E48"\u800C\u4E0D\u662F\u5177\u4F53 token \u65F6\uFF0C\u6BD4 grep \u66F4\u597D\u3002'
130
+ };
131
+
132
+ // src/index/semantic/preflight.ts
133
+ import { stdin, stdout } from "process";
134
+ import { createInterface } from "readline/promises";
135
+ async function ollamaPreflight(opts) {
136
+ const log = opts.log ?? ((line) => process.stderr.write(line));
137
+ const status = await checkOllamaStatus(opts.model, opts.baseUrl);
138
+ if (!status.binaryFound) {
139
+ log(t("ollamaNotFound"));
140
+ return false;
141
+ }
142
+ if (!status.daemonRunning) {
143
+ if (!opts.interactive && !opts.yesToAll) {
144
+ log(t("daemonNotReachableHint"));
145
+ return false;
146
+ }
147
+ const ok = opts.yesToAll || await confirm(t("daemonStartConfirm"), true);
148
+ if (!ok) {
149
+ log(t("daemonAbortStart"));
150
+ return false;
151
+ }
152
+ log(t("daemonStarting"));
153
+ const started = await startOllamaDaemon({ baseUrl: opts.baseUrl, timeoutMs: 15e3 });
154
+ if (!started.ready) {
155
+ log(t("daemonStartTimeout"));
156
+ return false;
157
+ }
158
+ log(t("daemonReady", { pid: started.pid ? ` (pid ${started.pid})` : "" }));
159
+ }
160
+ const after = status.daemonRunning ? status : await checkOllamaStatus(opts.model, opts.baseUrl);
161
+ if (!after.modelPulled) {
162
+ if (!opts.interactive && !opts.yesToAll) {
163
+ log(t("modelNotPulledHint", { model: opts.model }));
164
+ return false;
165
+ }
166
+ const ok = opts.yesToAll || await confirm(t("modelPullConfirm", { model: opts.model }), true);
167
+ if (!ok) {
168
+ log(t("modelAbortPull"));
169
+ return false;
170
+ }
171
+ log(t("modelPulling", { model: opts.model }));
172
+ const ESC = String.fromCharCode(27);
173
+ const ANSI_CSI = new RegExp(`${ESC}\\[[0-9;]*[A-Za-z]`, "g");
174
+ const code = await pullOllamaModel(opts.model, {
175
+ onLine: (line) => {
176
+ const cleaned = line.replace(ANSI_CSI, "").trim();
177
+ if (cleaned.length === 0) return;
178
+ log(` ${cleaned}
179
+ `);
180
+ }
181
+ });
182
+ if (code !== 0) {
183
+ log(t("modelPullFailed", { model: opts.model, code }));
184
+ return false;
185
+ }
186
+ log(t("modelPulled", { model: opts.model }));
187
+ }
188
+ return true;
189
+ }
190
+ async function semanticPreflight(config, opts) {
191
+ if (config.provider === "openai-compat") return true;
192
+ return await ollamaPreflight({
193
+ ...opts,
194
+ model: config.model,
195
+ baseUrl: config.baseUrl
196
+ });
197
+ }
198
+ async function confirm(question, defaultYes) {
199
+ const suffix = defaultYes ? "[Y/n]" : "[y/N]";
200
+ const rl = createInterface({ input: stdin, output: stdout });
201
+ try {
202
+ const raw = (await rl.question(`${question} ${suffix} `)).trim().toLowerCase();
203
+ if (raw === "") return defaultYes;
204
+ return raw === "y" || raw === "yes";
205
+ } finally {
206
+ rl.close();
207
+ }
208
+ }
209
+
210
+ // src/cli/commands/index.ts
211
+ async function indexCommand(opts = {}) {
212
+ const root = resolve(opts.dir ?? process.cwd());
213
+ const tty = process.stderr.isTTY === true && process.stdin.isTTY === true;
214
+ const resolved = resolveSemanticEmbeddingConfig();
215
+ const embedding = resolved.provider === "ollama" ? {
216
+ ...resolved,
217
+ model: opts.model ?? resolved.model,
218
+ baseUrl: opts.ollamaUrl ?? resolved.baseUrl
219
+ } : {
220
+ ...resolved,
221
+ model: opts.model ?? resolved.model
222
+ };
223
+ const preflightOk = await semanticPreflight(embedding, {
224
+ interactive: tty && !opts.yes,
225
+ yesToAll: opts.yes ?? false
226
+ });
227
+ if (!preflightOk) process.exit(1);
228
+ const writer = makeProgressWriter(tty);
229
+ const t0 = Date.now();
230
+ let result;
231
+ try {
232
+ result = await buildIndex(root, {
233
+ ...embedding,
234
+ rebuild: opts.rebuild,
235
+ indexConfig: loadIndexConfig(),
236
+ onProgress: (p) => writer.update(p)
237
+ });
238
+ } catch (err) {
239
+ writer.clear();
240
+ const msg = err instanceof Error ? err.message : String(err);
241
+ process.stderr.write(t("indexFailed", { msg }));
242
+ process.exit(1);
243
+ }
244
+ writer.clear();
245
+ const seconds = ((Date.now() - t0) / 1e3).toFixed(1);
246
+ const successKey = result.chunksSkipped > 0 ? "indexSuccessWithSkips" : "indexSuccess";
247
+ process.stderr.write(
248
+ t(successKey, {
249
+ scanned: result.filesScanned,
250
+ changed: result.filesChanged,
251
+ added: result.chunksAdded,
252
+ removed: result.chunksRemoved,
253
+ skipped: result.chunksSkipped,
254
+ seconds
255
+ })
256
+ );
257
+ const breakdown = renderSkipBreakdown(result.skipBuckets);
258
+ if (breakdown) process.stderr.write(`${breakdown}
259
+ `);
260
+ if (result.filesChanged === 0 && !opts.rebuild) {
261
+ process.stderr.write(t("indexNothingToDo"));
262
+ }
263
+ }
264
+ function renderSkipBreakdown(buckets) {
265
+ const total = Object.values(buckets).reduce((a, b) => a + b, 0);
266
+ if (total === 0) return "";
267
+ const parts = [];
268
+ if (buckets.gitignore) parts.push(`gitignore: ${buckets.gitignore}`);
269
+ if (buckets.pattern) parts.push(`pattern: ${buckets.pattern}`);
270
+ if (buckets.defaultDir) parts.push(`defaultDir: ${buckets.defaultDir}`);
271
+ if (buckets.defaultFile) parts.push(`defaultFile: ${buckets.defaultFile}`);
272
+ if (buckets.binaryExt) parts.push(`binaryExt: ${buckets.binaryExt}`);
273
+ if (buckets.binaryContent) parts.push(`binaryContent: ${buckets.binaryContent}`);
274
+ if (buckets.tooLarge) parts.push(`tooLarge: ${buckets.tooLarge}`);
275
+ if (buckets.readError) parts.push(`readError: ${buckets.readError}`);
276
+ return ` \xB7 skipped ${total} files (${parts.join(", ")})`;
277
+ }
278
+ var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
279
+ var SPINNER_INTERVAL_MS = 120;
280
+ function makeProgressWriter(tty) {
281
+ if (!tty) return makeNonTtyWriter();
282
+ return makeTtyWriter();
283
+ }
284
+ function makeNonTtyWriter() {
285
+ let lastPhase = null;
286
+ let lastChunks = 0;
287
+ return {
288
+ update(p) {
289
+ if (p.phase !== lastPhase) {
290
+ lastPhase = p.phase;
291
+ if (p.phase === "scan") {
292
+ process.stderr.write(t("progressScanLine"));
293
+ } else if (p.phase === "embed") {
294
+ process.stderr.write(
295
+ t("progressEmbedLine", {
296
+ total: p.chunksTotal ?? 0,
297
+ files: p.filesChanged ?? 0
298
+ })
299
+ );
300
+ }
301
+ }
302
+ if (p.phase === "embed" && p.chunksDone !== void 0 && p.chunksDone - lastChunks >= 50) {
303
+ lastChunks = p.chunksDone;
304
+ process.stderr.write(
305
+ t("progressEmbedHeartbeat", {
306
+ done: p.chunksDone,
307
+ total: p.chunksTotal ?? "?"
308
+ })
309
+ );
310
+ }
311
+ },
312
+ clear() {
313
+ }
314
+ };
315
+ }
316
+ function makeTtyWriter() {
317
+ let status = t("progressStarting");
318
+ let lastLineLen = 0;
319
+ let frameIdx = 0;
320
+ const startTs = Date.now();
321
+ const repaint = () => {
322
+ const frame = SPINNER_FRAMES[frameIdx % SPINNER_FRAMES.length];
323
+ frameIdx++;
324
+ const elapsed = ((Date.now() - startTs) / 1e3).toFixed(1);
325
+ const line = `${frame} ${status} ${elapsed}s`;
326
+ const padded = line + " ".repeat(Math.max(0, lastLineLen - line.length));
327
+ process.stderr.write(`\r${padded}`);
328
+ lastLineLen = line.length;
329
+ };
330
+ repaint();
331
+ const interval = setInterval(repaint, SPINNER_INTERVAL_MS);
332
+ return {
333
+ update(p) {
334
+ if (p.phase === "scan") {
335
+ status = t("progressScan", { files: p.filesScanned ?? 0 });
336
+ } else if (p.phase === "embed") {
337
+ const done = p.chunksDone ?? 0;
338
+ const total = p.chunksTotal ?? 0;
339
+ const pct = total > 0 ? (done / total * 100).toFixed(0) : "0";
340
+ status = t("progressEmbed", { done, total, pct });
341
+ }
342
+ repaint();
343
+ },
344
+ clear() {
345
+ clearInterval(interval);
346
+ if (lastLineLen > 0) {
347
+ process.stderr.write(`\r${" ".repeat(lastLineLen)}\r`);
348
+ lastLineLen = 0;
349
+ }
350
+ }
351
+ };
352
+ }
353
+ export {
354
+ indexCommand
355
+ };
356
+ //# sourceMappingURL=commands-KMOZEYCF.js.map