jinzd-ai-cli 0.1.45 → 0.1.47

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.
@@ -8,7 +8,7 @@ import { platform } from "os";
8
8
  import chalk from "chalk";
9
9
 
10
10
  // src/core/constants.ts
11
- var VERSION = "0.1.45";
11
+ var VERSION = "0.1.47";
12
12
  var APP_NAME = "ai-cli";
13
13
  var CONFIG_DIR_NAME = ".aicli";
14
14
  var CONFIG_FILE_NAME = "config.json";
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  SUBAGENT_MAX_ROUNDS_LIMIT,
30
30
  VERSION,
31
31
  runTestsTool
32
- } from "./chunk-ZF62G7VO.js";
32
+ } from "./chunk-ZUZDWQVG.js";
33
33
 
34
34
  // src/index.ts
35
35
  import { program } from "commander";
@@ -313,6 +313,39 @@ ${err}`
313
313
  getDefaultProvider() {
314
314
  return EnvLoader.getDefaultProvider() ?? this.config.defaultProvider;
315
315
  }
316
+ /** 点分路径读取配置值,如 `ui.theme` → config.ui.theme */
317
+ getByPath(path) {
318
+ const keys = path.split(".");
319
+ let current = this.config;
320
+ for (const key of keys) {
321
+ if (current == null || typeof current !== "object") return void 0;
322
+ current = current[key];
323
+ }
324
+ return current;
325
+ }
326
+ /** 点分路径写入配置值,自动类型转换(boolean/number/string)并持久化 */
327
+ setByPath(path, rawValue) {
328
+ const keys = path.split(".");
329
+ if (keys.length === 0) return;
330
+ let value = rawValue;
331
+ if (rawValue === "true") value = true;
332
+ else if (rawValue === "false") value = false;
333
+ else if (rawValue !== "" && !isNaN(Number(rawValue))) value = Number(rawValue);
334
+ let current = this.config;
335
+ for (let i = 0; i < keys.length - 1; i++) {
336
+ const key = keys[i];
337
+ if (current[key] == null || typeof current[key] !== "object") {
338
+ current[key] = {};
339
+ }
340
+ current = current[key];
341
+ }
342
+ current[keys[keys.length - 1]] = value;
343
+ this.save();
344
+ }
345
+ /** 获取完整配置对象的 JSON 字符串 */
346
+ toJSON() {
347
+ return JSON.stringify(this.config, null, 2);
348
+ }
316
349
  };
317
350
 
318
351
  // src/providers/claude.ts
@@ -1891,7 +1924,12 @@ var SessionManager = class {
1891
1924
  if (!existsSync2(filePath)) {
1892
1925
  throw new Error(`Session ${id} not found`);
1893
1926
  }
1894
- const data = JSON.parse(readFileSync2(filePath, "utf-8"));
1927
+ let data;
1928
+ try {
1929
+ data = JSON.parse(readFileSync2(filePath, "utf-8"));
1930
+ } catch (err) {
1931
+ throw new Error(`Session ${id} is corrupted: ${err instanceof Error ? err.message : String(err)}`);
1932
+ }
1895
1933
  const session = Session.fromJSON(data);
1896
1934
  this._current = session;
1897
1935
  return session;
@@ -2193,12 +2231,12 @@ var Renderer = class {
2193
2231
  console.log(tool("spawn_agent", "\u59D4\u6D3E\u72EC\u7ACB\u5B50\u4EE3\u7406\u6267\u884C\u7279\u5B9A\u4EFB\u52A1\uFF08\u9694\u79BB\u5BF9\u8BDD + \u81EA\u52A8\u5DE5\u5177\u8C03\u7528\u5FAA\u73AF\uFF09"));
2194
2232
  console.log(tool("run_tests", "\u8FD0\u884C\u9879\u76EE\u6D4B\u8BD5\u5E76\u8FD4\u56DE\u7ED3\u6784\u5316\u62A5\u544A\uFF08\u81EA\u52A8\u68C0\u6D4B Maven/npm/pytest \u7B49\uFF09"));
2195
2233
  console.log(HR);
2196
- console.log(theme.dim(" REPL \u547D\u4EE4\uFF0833\u4E2A\uFF09\uFF1A"));
2234
+ console.log(theme.dim(" REPL \u547D\u4EE4\uFF0834\u4E2A\uFF09\uFF1A"));
2197
2235
  console.log(theme.dim(" /help /about /provider /model /clear /compact /plan /session"));
2198
2236
  console.log(theme.dim(" /system /context /status /search /undo /export /copy /cost"));
2199
2237
  console.log(theme.dim(" /init /skill /tools /plugins /mcp /config /checkpoint /review"));
2200
2238
  console.log(theme.dim(" /commands /test /scaffold /add-dir /memory /doctor /bug /think"));
2201
- console.log(theme.dim(" /exit"));
2239
+ console.log(theme.dim(" /diff /exit"));
2202
2240
  console.log(HR);
2203
2241
  console.log(theme.dim(" \u4E3B\u8981\u7279\u6027\uFF1A"));
2204
2242
  console.log(feat("Agentic \u5FAA\u73AF\uFF08\u6700\u591A 25 \u8F6E\u5DE5\u5177\u8C03\u7528\uFF0C\u6700\u7EC8\u56DE\u7B54\u6D41\u5F0F\u8F93\u51FA\uFF09"));
@@ -2245,6 +2283,9 @@ var Renderer = class {
2245
2283
  console.log(feat("Extended Thinking\uFF1AClaude \u6DF1\u5EA6\u63A8\u7406\u6A21\u5F0F\uFF0C/think \u8FD0\u884C\u65F6\u5207\u6362\uFF0Cthinking \u5757\u6298\u53E0\u663E\u793A"));
2246
2284
  console.log(feat("theme \u5168\u8986\u76D6\uFF1A\u5168\u90E8\u7EC8\u7AEF\u8F93\u51FA\u7EDF\u4E00\u4F7F\u7528\u8BED\u4E49\u8272\u69FD\uFF0Cdark/light/custom \u4E00\u952E\u5207\u6362"));
2247
2285
  console.log(feat("edit_file \u667A\u80FD\u63D0\u793A\uFF1A\u5339\u914D\u5931\u8D25\u65F6\u663E\u793A did you mean \u76F8\u4F3C\u884C + ignore_whitespace \u5BB9\u9519\u6A21\u5F0F"));
2286
+ console.log(feat("/config set|get|show\uFF1AREPL \u5185\u5FEB\u6377\u8BFB\u5199\u914D\u7F6E\uFF0C\u65E0\u9700\u8FDB\u5165\u5411\u5BFC\uFF08\u70B9\u5206\u8DEF\u5F84 + \u81EA\u52A8\u7C7B\u578B\u8F6C\u6362\uFF09"));
2287
+ console.log(feat("\u5DE5\u5177\u8C03\u7528\u6700\u7EC8\u56DE\u7B54\u6D41\u5F0F\u5316\uFF1A\u6A21\u62DF\u6253\u5B57\u673A\u6548\u679C\u9010\u5757\u8F93\u51FA\uFF0C\u96F6\u989D\u5916 API \u8C03\u7528\uFF0C\u652F\u6301 Escape \u4E2D\u65AD"));
2288
+ console.log(feat("/diff \u547D\u4EE4\uFF1A\u663E\u793A\u5F53\u524D session \u5185\u6240\u6709\u6587\u4EF6\u4FEE\u6539\u7684\u6C47\u603B diff\uFF08\u5408\u5E76\u540C\u6587\u4EF6\u591A\u6B21\u4FEE\u6539\uFF09"));
2248
2289
  console.log();
2249
2290
  }
2250
2291
  printPrompt(provider, _model) {
@@ -2371,6 +2412,40 @@ var Renderer = class {
2371
2412
  process.stdout.write(finalOutput);
2372
2413
  process.stdout.write("\n\n");
2373
2414
  }
2415
+ /**
2416
+ * 将已有 content 以模拟流式效果逐块输出(打字机体验),零额外 API 调用。
2417
+ * 支持 AbortSignal 中断。
2418
+ */
2419
+ async renderContentAsStream(content, options) {
2420
+ process.stdout.write(theme.accent("Assistant: "));
2421
+ let displayed = content;
2422
+ if (content.includes("<think>")) {
2423
+ let hasThinking = false;
2424
+ displayed = content.replace(/<think>[\s\S]*?<\/think>/g, () => {
2425
+ hasThinking = true;
2426
+ return "";
2427
+ }).trimStart();
2428
+ if (hasThinking) {
2429
+ process.stdout.write(theme.dim("\n\u{1F4AD} Thinking...\n"));
2430
+ }
2431
+ }
2432
+ const CHUNK_SIZE = 12;
2433
+ const DELAY_MS = 8;
2434
+ let pos = 0;
2435
+ while (pos < displayed.length) {
2436
+ if (options?.signal?.aborted) {
2437
+ process.stdout.write(theme.dim("\n[interrupted]"));
2438
+ break;
2439
+ }
2440
+ const end = Math.min(pos + CHUNK_SIZE, displayed.length);
2441
+ process.stdout.write(displayed.slice(pos, end));
2442
+ pos = end;
2443
+ if (pos < displayed.length) {
2444
+ await new Promise((resolve5) => setTimeout(resolve5, DELAY_MS));
2445
+ }
2446
+ }
2447
+ process.stdout.write("\n\n");
2448
+ }
2374
2449
  renderError(err) {
2375
2450
  const message = err instanceof Error ? err.message : String(err);
2376
2451
  console.error(theme.error(`
@@ -2427,7 +2502,7 @@ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as
2427
2502
  import { execSync as execSync3 } from "child_process";
2428
2503
  import { platform } from "os";
2429
2504
  import { resolve, dirname as dirname2, join as join5, basename } from "path";
2430
- import chalk3 from "chalk";
2505
+ import chalk4 from "chalk";
2431
2506
 
2432
2507
  // src/tools/git-context.ts
2433
2508
  import { execSync } from "child_process";
@@ -2582,6 +2657,10 @@ var UndoStack = class {
2582
2657
  get depth() {
2583
2658
  return this.stack.length;
2584
2659
  }
2660
+ /** 返回栈的拷贝(所有文件修改记录),供 /diff 命令使用 */
2661
+ getHistory() {
2662
+ return [...this.stack];
2663
+ }
2585
2664
  /** 清空撤销栈(新会话时调用) */
2586
2665
  clear() {
2587
2666
  this.stack = [];
@@ -2589,6 +2668,159 @@ var UndoStack = class {
2589
2668
  };
2590
2669
  var undoStack = new UndoStack();
2591
2670
 
2671
+ // src/tools/diff-utils.ts
2672
+ import chalk3 from "chalk";
2673
+ function renderDiff(oldText, newText, opts = {}) {
2674
+ const contextLines = opts.contextLines ?? 3;
2675
+ const maxLines = opts.maxLines ?? 120;
2676
+ const filePath = opts.filePath ?? "";
2677
+ const oldLines = oldText.split("\n");
2678
+ const newLines = newText.split("\n");
2679
+ const hunks = computeHunks(oldLines, newLines, contextLines);
2680
+ if (hunks.length === 0) {
2681
+ return chalk3.dim(" (no changes)");
2682
+ }
2683
+ const output = [];
2684
+ if (filePath) {
2685
+ output.push(chalk3.bold.white(`--- ${filePath} (before)`));
2686
+ output.push(chalk3.bold.white(`+++ ${filePath} (after)`));
2687
+ }
2688
+ let totalDisplayed = 0;
2689
+ for (const hunk of hunks) {
2690
+ if (totalDisplayed >= maxLines) {
2691
+ output.push(chalk3.dim(` ... (diff truncated, too many changes)`));
2692
+ break;
2693
+ }
2694
+ output.push(
2695
+ chalk3.cyan(
2696
+ `@@ -${hunk.oldStart + 1},${hunk.oldCount} +${hunk.newStart + 1},${hunk.newCount} @@`
2697
+ )
2698
+ );
2699
+ for (const line of hunk.lines) {
2700
+ if (totalDisplayed >= maxLines) break;
2701
+ totalDisplayed++;
2702
+ if (line.type === "context") {
2703
+ output.push(chalk3.dim(` ${line.text}`));
2704
+ } else if (line.type === "remove") {
2705
+ output.push(chalk3.red(`- ${line.text}`));
2706
+ } else {
2707
+ output.push(chalk3.green(`+ ${line.text}`));
2708
+ }
2709
+ }
2710
+ }
2711
+ return output.join("\n");
2712
+ }
2713
+ function computeHunks(oldLines, newLines, contextLines) {
2714
+ const edits = diffLines(oldLines, newLines);
2715
+ if (edits.every((e) => e.type === "context")) return [];
2716
+ const hunks = [];
2717
+ let i = 0;
2718
+ while (i < edits.length) {
2719
+ if (edits[i].type === "context") {
2720
+ i++;
2721
+ continue;
2722
+ }
2723
+ const start = Math.max(0, i - contextLines);
2724
+ let end = i;
2725
+ while (end < edits.length) {
2726
+ if (edits[end].type !== "context") {
2727
+ end++;
2728
+ } else {
2729
+ let hasMoreChange = false;
2730
+ for (let j = end + 1; j < Math.min(edits.length, end + contextLines * 2 + 1); j++) {
2731
+ if (edits[j].type !== "context") {
2732
+ hasMoreChange = true;
2733
+ break;
2734
+ }
2735
+ }
2736
+ if (hasMoreChange) {
2737
+ end++;
2738
+ } else {
2739
+ break;
2740
+ }
2741
+ }
2742
+ }
2743
+ end = Math.min(edits.length, end + contextLines);
2744
+ const hunkEdits = edits.slice(start, end);
2745
+ let oldStart = 0;
2746
+ let newStart = 0;
2747
+ for (let k = 0; k < start; k++) {
2748
+ if (edits[k].type !== "add") oldStart++;
2749
+ if (edits[k].type !== "remove") newStart++;
2750
+ }
2751
+ let oldCount = 0;
2752
+ let newCount = 0;
2753
+ for (const e of hunkEdits) {
2754
+ if (e.type !== "add") oldCount++;
2755
+ if (e.type !== "remove") newCount++;
2756
+ }
2757
+ hunks.push({
2758
+ oldStart,
2759
+ oldCount,
2760
+ newStart,
2761
+ newCount,
2762
+ lines: hunkEdits.map((e) => ({ type: e.type, text: e.text }))
2763
+ });
2764
+ i = end;
2765
+ }
2766
+ return hunks;
2767
+ }
2768
+ function diffLines(oldLines, newLines) {
2769
+ const n = oldLines.length;
2770
+ const m = newLines.length;
2771
+ if (n * m > 25e4) {
2772
+ return simpleDiff(oldLines, newLines);
2773
+ }
2774
+ const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
2775
+ for (let i2 = 1; i2 <= n; i2++) {
2776
+ for (let j2 = 1; j2 <= m; j2++) {
2777
+ if (oldLines[i2 - 1] === newLines[j2 - 1]) {
2778
+ dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
2779
+ } else {
2780
+ dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
2781
+ }
2782
+ }
2783
+ }
2784
+ const result = [];
2785
+ let i = n;
2786
+ let j = m;
2787
+ while (i > 0 || j > 0) {
2788
+ if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
2789
+ result.unshift({ type: "context", text: oldLines[i - 1] });
2790
+ i--;
2791
+ j--;
2792
+ } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
2793
+ result.unshift({ type: "add", text: newLines[j - 1] });
2794
+ j--;
2795
+ } else {
2796
+ result.unshift({ type: "remove", text: oldLines[i - 1] });
2797
+ i--;
2798
+ }
2799
+ }
2800
+ return result;
2801
+ }
2802
+ function simpleDiff(oldLines, newLines) {
2803
+ const result = [];
2804
+ const maxLen = Math.max(oldLines.length, newLines.length);
2805
+ for (let i = 0; i < maxLen; i++) {
2806
+ const o = oldLines[i];
2807
+ const n = newLines[i];
2808
+ if (o !== void 0 && n !== void 0) {
2809
+ if (o === n) {
2810
+ result.push({ type: "context", text: o });
2811
+ } else {
2812
+ result.push({ type: "remove", text: o });
2813
+ result.push({ type: "add", text: n });
2814
+ }
2815
+ } else if (o !== void 0) {
2816
+ result.push({ type: "remove", text: o });
2817
+ } else if (n !== void 0) {
2818
+ result.push({ type: "add", text: n });
2819
+ }
2820
+ }
2821
+ return result;
2822
+ }
2823
+
2592
2824
  // src/repl/clipboard.ts
2593
2825
  import { execSync as execSync2 } from "child_process";
2594
2826
  import { existsSync as existsSync5, statSync, unlinkSync as unlinkSync2 } from "fs";
@@ -2723,8 +2955,15 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
2723
2955
  }
2724
2956
  const filtered = entries.filter((e) => !e.startsWith(".") && !SCAN_SKIP_DIRS.has(e));
2725
2957
  const sorted = filtered.sort((a, b) => {
2726
- const aIsDir = statSync2(join5(d, a)).isDirectory();
2727
- const bIsDir = statSync2(join5(d, b)).isDirectory();
2958
+ let aIsDir = false, bIsDir = false;
2959
+ try {
2960
+ aIsDir = statSync2(join5(d, a)).isDirectory();
2961
+ } catch {
2962
+ }
2963
+ try {
2964
+ bIsDir = statSync2(join5(d, b)).isDirectory();
2965
+ } catch {
2966
+ }
2728
2967
  if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
2729
2968
  return a.localeCompare(b);
2730
2969
  });
@@ -2939,7 +3178,7 @@ function createDefaultCommands() {
2939
3178
  " /tools - List all AI tools available",
2940
3179
  " /plugins - Show plugin directory and loaded plugins",
2941
3180
  " /mcp [reconnect [id]] - Show MCP servers / reconnect disconnected",
2942
- " /config - Open configuration wizard (API keys, proxy, etc.)",
3181
+ " /config [set|get|show] - Config wizard, or get/set values, show all",
2943
3182
  " /copy - Copy last AI response to clipboard",
2944
3183
  " /cost [reset] - Show session token usage (or reset counters)",
2945
3184
  " /init [--force] - Generate AICLI.md by scanning project structure",
@@ -2953,6 +3192,7 @@ function createDefaultCommands() {
2953
3192
  " /memory [show|add|clear] - View or edit persistent memory (memory.md)",
2954
3193
  " /doctor - Health check (API keys, config, MCP status)",
2955
3194
  " /bug [--copy] - Generate bug report template (--copy to clipboard)",
3195
+ " /diff [--stats] - Show all file modifications in this session",
2956
3196
  " /exit - Exit"
2957
3197
  ] : [];
2958
3198
  console.log("\nAvailable commands:");
@@ -3468,10 +3708,45 @@ ${text}
3468
3708
  },
3469
3709
  {
3470
3710
  name: "config",
3471
- description: "Open configuration wizard (API keys, proxy, default provider)",
3472
- usage: "/config",
3473
- async execute(_args, ctx) {
3474
- await ctx.runSetupWizard();
3711
+ description: "Configuration: wizard, get/set values, show all",
3712
+ usage: "/config [set <path> <value> | get <path> | show]",
3713
+ async execute(args, ctx) {
3714
+ const sub = args[0]?.toLowerCase();
3715
+ const config = ctx.config;
3716
+ if (!sub) {
3717
+ await ctx.runSetupWizard();
3718
+ return;
3719
+ }
3720
+ if (sub === "show") {
3721
+ console.log(config.toJSON());
3722
+ return;
3723
+ }
3724
+ if (sub === "get") {
3725
+ const path = args[1]?.trim();
3726
+ if (!path) {
3727
+ console.log(theme.warning("Usage: /config get <path> (e.g. ui.theme)"));
3728
+ return;
3729
+ }
3730
+ const val = config.getByPath(path);
3731
+ if (val === void 0) {
3732
+ console.log(theme.dim(` ${path} = (undefined)`));
3733
+ } else {
3734
+ console.log(theme.dim(` ${path} = `) + chalk4.white(typeof val === "object" ? JSON.stringify(val) : String(val)));
3735
+ }
3736
+ return;
3737
+ }
3738
+ if (sub === "set") {
3739
+ const path = args[1]?.trim();
3740
+ const value = args.slice(2).join(" ").trim();
3741
+ if (!path || value === "") {
3742
+ console.log(theme.warning("Usage: /config set <path> <value> (e.g. ui.theme light)"));
3743
+ return;
3744
+ }
3745
+ config.setByPath(path, value);
3746
+ console.log(theme.success(` \u2713 Set ${path} = ${value}`));
3747
+ return;
3748
+ }
3749
+ console.log(theme.warning("Usage: /config [set <path> <value> | get <path> | show]"));
3475
3750
  }
3476
3751
  },
3477
3752
  {
@@ -3737,9 +4012,9 @@ ${hint}` : "")
3737
4012
  console.log();
3738
4013
  console.log(theme.heading(" \u{1F4CA} Session Token Usage"));
3739
4014
  console.log(theme.dim(" " + "\u2500".repeat(40)));
3740
- console.log(theme.dim(" Input tokens : ") + chalk3.white(usage.inputTokens.toLocaleString()));
3741
- console.log(theme.dim(" Output tokens : ") + chalk3.white(usage.outputTokens.toLocaleString()));
3742
- console.log(theme.dim(" Total tokens : ") + chalk3.bold.white(totalTokens.toLocaleString()));
4015
+ console.log(theme.dim(" Input tokens : ") + chalk4.white(usage.inputTokens.toLocaleString()));
4016
+ console.log(theme.dim(" Output tokens : ") + chalk4.white(usage.outputTokens.toLocaleString()));
4017
+ console.log(theme.dim(" Total tokens : ") + chalk4.bold.white(totalTokens.toLocaleString()));
3743
4018
  console.log(theme.dim(" " + "\u2500".repeat(40)));
3744
4019
  const session = ctx.sessions.current;
3745
4020
  if (session) {
@@ -3898,7 +4173,7 @@ ${hint}` : "")
3898
4173
  description: "Run project tests and show structured report",
3899
4174
  usage: "/test [command|filter]",
3900
4175
  async execute(args, _ctx) {
3901
- const { executeTests } = await import("./run-tests-XB4TDIP3.js");
4176
+ const { executeTests } = await import("./run-tests-EM3QNRWV.js");
3902
4177
  const argStr = args.join(" ").trim();
3903
4178
  let testArgs = {};
3904
4179
  if (argStr) {
@@ -4009,7 +4284,7 @@ ${hint}` : "")
4009
4284
  }
4010
4285
  const lines = content.split("\n").length;
4011
4286
  console.log(theme.heading("\n\u{1F4DD} Persistent Memory:\n") + theme.dim("\u2500".repeat(60)));
4012
- console.log(chalk3.white(content));
4287
+ console.log(chalk4.white(content));
4013
4288
  console.log(theme.dim("\u2500".repeat(60)));
4014
4289
  console.log(theme.dim(` ${content.length} chars \xB7 ${lines} lines
4015
4290
  `));
@@ -4168,6 +4443,63 @@ ${text}
4168
4443
  }
4169
4444
  }
4170
4445
  },
4446
+ {
4447
+ name: "diff",
4448
+ description: "Show all file modifications in this session",
4449
+ usage: "/diff [--stats]",
4450
+ execute(args) {
4451
+ const history = undoStack.getHistory();
4452
+ if (history.length === 0) {
4453
+ console.log(theme.dim("No file modifications in this session."));
4454
+ return;
4455
+ }
4456
+ const fileMap = /* @__PURE__ */ new Map();
4457
+ for (const entry of history) {
4458
+ if (!fileMap.has(entry.filePath)) {
4459
+ fileMap.set(entry.filePath, { earliest: entry.previousContent });
4460
+ }
4461
+ }
4462
+ const statsOnly = args[0]?.toLowerCase() === "--stats";
4463
+ let newFiles = 0;
4464
+ let modifiedFiles = 0;
4465
+ for (const [filePath, { earliest }] of fileMap) {
4466
+ const currentContent = existsSync6(filePath) ? (() => {
4467
+ try {
4468
+ return readFileSync4(filePath, "utf-8");
4469
+ } catch {
4470
+ return null;
4471
+ }
4472
+ })() : null;
4473
+ const isNew = earliest === null;
4474
+ if (isNew) newFiles++;
4475
+ else modifiedFiles++;
4476
+ if (statsOnly) continue;
4477
+ if (isNew) {
4478
+ console.log(theme.success(`
4479
+ \u{1F4C4} [NEW] ${filePath}`));
4480
+ if (currentContent !== null) {
4481
+ const lines = currentContent.split("\n").length;
4482
+ console.log(theme.dim(` ${lines} lines`));
4483
+ } else {
4484
+ console.log(theme.dim(" (file was deleted after creation)"));
4485
+ }
4486
+ } else {
4487
+ console.log(theme.accent(`
4488
+ \u{1F4DD} [MODIFIED] ${filePath}`));
4489
+ const oldText = earliest ?? "";
4490
+ const newText = currentContent ?? "";
4491
+ if (oldText === newText) {
4492
+ console.log(theme.dim(" (no net change)"));
4493
+ } else {
4494
+ console.log(renderDiff(oldText, newText, { filePath, maxLines: 80 }));
4495
+ }
4496
+ }
4497
+ }
4498
+ console.log(theme.heading(`
4499
+ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modified`));
4500
+ console.log();
4501
+ }
4502
+ },
4171
4503
  {
4172
4504
  name: "exit",
4173
4505
  description: "Exit the REPL",
@@ -4180,7 +4512,7 @@ ${text}
4180
4512
  }
4181
4513
 
4182
4514
  // src/repl/select-list.ts
4183
- import chalk4 from "chalk";
4515
+ import chalk5 from "chalk";
4184
4516
  var CLEAR_LINE = "\r\x1B[2K";
4185
4517
  var MOVE_UP = (n) => n > 0 ? `\x1B[${n}A` : "";
4186
4518
  var IGNORE_ENTER_MS = 80;
@@ -4205,10 +4537,10 @@ function selectFromList(prompt, items, initialIndex = 0) {
4205
4537
  handleSequence(seq);
4206
4538
  };
4207
4539
  const renderLine = (item, active, absIdx) => {
4208
- const cursor = active ? chalk4.cyan("\u276F ") : " ";
4209
- const label = active ? chalk4.cyan(item.label) : item.label;
4210
- const hint = item.hint ? chalk4.dim(" " + item.hint) : "";
4211
- const num = chalk4.dim(String(absIdx + 1).padStart(2) + " ");
4540
+ const cursor = active ? chalk5.cyan("\u276F ") : " ";
4541
+ const label = active ? chalk5.cyan(item.label) : item.label;
4542
+ const hint = item.hint ? chalk5.dim(" " + item.hint) : "";
4543
+ const num = chalk5.dim(String(absIdx + 1).padStart(2) + " ");
4212
4544
  return cursor + num + label + hint;
4213
4545
  };
4214
4546
  const render = () => {
@@ -4217,16 +4549,16 @@ function selectFromList(prompt, items, initialIndex = 0) {
4217
4549
  const windowEnd = Math.min(windowStart + PAGE, items.length);
4218
4550
  const visible = items.slice(windowStart, windowEnd);
4219
4551
  const lines = [];
4220
- lines.push(chalk4.bold(prompt));
4552
+ lines.push(chalk5.bold(prompt));
4221
4553
  if (windowStart > 0)
4222
- lines.push(chalk4.dim(` \u2191 ${windowStart} more above`));
4554
+ lines.push(chalk5.dim(` \u2191 ${windowStart} more above`));
4223
4555
  visible.forEach(
4224
4556
  (item, i) => lines.push(renderLine(item, windowStart + i === selected, windowStart + i))
4225
4557
  );
4226
4558
  const below = items.length - windowEnd;
4227
4559
  if (below > 0)
4228
- lines.push(chalk4.dim(` \u2193 ${below} more below`));
4229
- lines.push(chalk4.dim(" \u2191\u2193 move \xB7 Enter select \xB7 Esc cancel"));
4560
+ lines.push(chalk5.dim(` \u2193 ${below} more below`));
4561
+ lines.push(chalk5.dim(" \u2191\u2193 move \xB7 Enter select \xB7 Esc cancel"));
4230
4562
  if (lastRenderedLines > 0) {
4231
4563
  process.stdout.write(MOVE_UP(lastRenderedLines) + CLEAR_LINE);
4232
4564
  for (let i = 1; i < lastRenderedLines; i++)
@@ -4259,7 +4591,7 @@ function selectFromList(prompt, items, initialIndex = 0) {
4259
4591
  process.stdout.write(MOVE_UP(lastRenderedLines - 1));
4260
4592
  }
4261
4593
  if (result !== null) {
4262
- process.stdout.write(chalk4.dim(` \u2714 ${result}
4594
+ process.stdout.write(chalk5.dim(` \u2714 ${result}
4263
4595
  `));
4264
4596
  }
4265
4597
  resolve5(result);
@@ -5680,7 +6012,7 @@ ${content}
5680
6012
  };
5681
6013
 
5682
6014
  // src/tools/builtin/ask-user.ts
5683
- import chalk5 from "chalk";
6015
+ import chalk6 from "chalk";
5684
6016
  var askUserContext = {
5685
6017
  prompting: false
5686
6018
  };
@@ -5717,8 +6049,8 @@ function promptUser(rl, question) {
5717
6049
  rl.resume();
5718
6050
  askUserContext.prompting = true;
5719
6051
  console.log();
5720
- console.log(chalk5.cyan("\u2753 ") + chalk5.bold(question));
5721
- process.stdout.write(chalk5.cyan("> "));
6052
+ console.log(chalk6.cyan("\u2753 ") + chalk6.bold(question));
6053
+ process.stdout.write(chalk6.cyan("> "));
5722
6054
  return new Promise((resolve5) => {
5723
6055
  let completed = false;
5724
6056
  const cleanup = (answer) => {
@@ -5735,7 +6067,7 @@ function promptUser(rl, question) {
5735
6067
  cleanup(line);
5736
6068
  };
5737
6069
  askUserContext.cancelFn = () => {
5738
- process.stdout.write(chalk5.gray("\n(cancelled)\n"));
6070
+ process.stdout.write(chalk6.gray("\n(cancelled)\n"));
5739
6071
  cleanup(null);
5740
6072
  };
5741
6073
  rl.once("line", onLine);
@@ -5743,7 +6075,7 @@ function promptUser(rl, question) {
5743
6075
  }
5744
6076
 
5745
6077
  // src/tools/builtin/write-todos.ts
5746
- import chalk6 from "chalk";
6078
+ import chalk7 from "chalk";
5747
6079
  var VALID_STATUSES = /* @__PURE__ */ new Set(["pending", "in_progress", "completed"]);
5748
6080
  var currentTodos = [];
5749
6081
  var writeTodosTool = {
@@ -5806,25 +6138,25 @@ function renderTodoList(todos) {
5806
6138
  const total = todos.length;
5807
6139
  console.log();
5808
6140
  console.log(
5809
- chalk6.bold.cyan("\u{1F4CB} Todo List") + chalk6.dim(` (${completed}/${total} completed)`)
6141
+ chalk7.bold.cyan("\u{1F4CB} Todo List") + chalk7.dim(` (${completed}/${total} completed)`)
5810
6142
  );
5811
- console.log(chalk6.dim(" " + "\u2500".repeat(40)));
6143
+ console.log(chalk7.dim(" " + "\u2500".repeat(40)));
5812
6144
  for (const todo of todos) {
5813
6145
  let icon;
5814
6146
  let text;
5815
6147
  switch (todo.status) {
5816
6148
  case "completed":
5817
- icon = chalk6.green(" \u2713 ");
5818
- text = chalk6.strikethrough.gray(todo.title);
6149
+ icon = chalk7.green(" \u2713 ");
6150
+ text = chalk7.strikethrough.gray(todo.title);
5819
6151
  break;
5820
6152
  case "in_progress":
5821
- icon = chalk6.yellow(" \u2192 ");
5822
- text = chalk6.white(todo.title);
6153
+ icon = chalk7.yellow(" \u2192 ");
6154
+ text = chalk7.white(todo.title);
5823
6155
  break;
5824
6156
  case "pending":
5825
6157
  default:
5826
- icon = chalk6.gray(" \u25CB ");
5827
- text = chalk6.gray(todo.title);
6158
+ icon = chalk7.gray(" \u25CB ");
6159
+ text = chalk7.gray(todo.title);
5828
6160
  break;
5829
6161
  }
5830
6162
  console.log(icon + text);
@@ -5950,7 +6282,7 @@ function formatResults(query, data, requested) {
5950
6282
  }
5951
6283
 
5952
6284
  // src/tools/builtin/spawn-agent.ts
5953
- import chalk7 from "chalk";
6285
+ import chalk8 from "chalk";
5954
6286
  var spawnAgentContext = {
5955
6287
  provider: null,
5956
6288
  model: "",
@@ -5958,7 +6290,7 @@ var spawnAgentContext = {
5958
6290
  modelParams: {},
5959
6291
  configManager: null
5960
6292
  };
5961
- var PREFIX = chalk7.dim(" \u2503 ");
6293
+ var PREFIX = chalk8.dim(" \u2503 ");
5962
6294
  var MAX_TOOL_OUTPUT_CHARS = 12e3;
5963
6295
  function truncateOutput(content, toolName) {
5964
6296
  if (content.length <= MAX_TOOL_OUTPUT_CHARS) return content;
@@ -5996,7 +6328,7 @@ var SubAgentExecutor = class {
5996
6328
  const dangerLevel = getDangerLevel(call.name, call.arguments);
5997
6329
  if (dangerLevel === "destructive") {
5998
6330
  this.printPrefixed(
5999
- chalk7.red("\u26A0 BLOCKED: ") + `Destructive operation ${chalk7.bold(call.name)} not allowed in sub-agent`
6331
+ chalk8.red("\u26A0 BLOCKED: ") + `Destructive operation ${chalk8.bold(call.name)} not allowed in sub-agent`
6000
6332
  );
6001
6333
  return {
6002
6334
  callId: call.id,
@@ -6032,9 +6364,9 @@ var SubAgentExecutor = class {
6032
6364
  }
6033
6365
  printToolCall(call, dangerLevel) {
6034
6366
  console.log(PREFIX);
6035
- const icon = dangerLevel === "write" ? chalk7.yellow("\u270E Tool: ") : chalk7.bold.cyan("\u2699 Tool: ");
6036
- const roundBadge = this.totalRounds > 0 ? chalk7.dim(` [${this.round}/${this.totalRounds}]`) : "";
6037
- console.log(PREFIX + icon + chalk7.white(call.name) + roundBadge);
6367
+ const icon = dangerLevel === "write" ? chalk8.yellow("\u270E Tool: ") : chalk8.bold.cyan("\u2699 Tool: ");
6368
+ const roundBadge = this.totalRounds > 0 ? chalk8.dim(` [${this.round}/${this.totalRounds}]`) : "";
6369
+ console.log(PREFIX + icon + chalk8.white(call.name) + roundBadge);
6038
6370
  for (const [key, val] of Object.entries(call.arguments)) {
6039
6371
  let valStr;
6040
6372
  if (Array.isArray(val)) {
@@ -6045,22 +6377,22 @@ var SubAgentExecutor = class {
6045
6377
  } else {
6046
6378
  valStr = String(val);
6047
6379
  }
6048
- console.log(PREFIX + chalk7.gray(` ${key}: `) + chalk7.white(valStr));
6380
+ console.log(PREFIX + chalk8.gray(` ${key}: `) + chalk8.white(valStr));
6049
6381
  }
6050
6382
  }
6051
6383
  printToolResult(name, content, isError, wasTruncated) {
6052
6384
  if (isError) {
6053
6385
  console.log(
6054
- PREFIX + chalk7.red(`\u26A0 ${name} error: `) + chalk7.gray(content.slice(0, 300))
6386
+ PREFIX + chalk8.red(`\u26A0 ${name} error: `) + chalk8.gray(content.slice(0, 300))
6055
6387
  );
6056
6388
  } else {
6057
6389
  const lines = content.split("\n");
6058
6390
  const maxLines = name === "run_interactive" ? 40 : 8;
6059
6391
  const preview = lines.slice(0, maxLines);
6060
- const prefixedPreview = preview.map((l) => PREFIX + " " + chalk7.gray(l)).join("\n");
6061
- const moreLines = lines.length > maxLines ? "\n" + PREFIX + chalk7.gray(` ... (${lines.length - maxLines} more lines)`) : "";
6062
- const truncNote = wasTruncated ? "\n" + PREFIX + chalk7.yellow(` \u26A1 \u8F93\u51FA\u5DF2\u622A\u65AD\u81F3 ${MAX_TOOL_OUTPUT_CHARS} \u5B57\u7B26`) : "";
6063
- console.log(PREFIX + chalk7.green("\u2713 Result:"));
6392
+ const prefixedPreview = preview.map((l) => PREFIX + " " + chalk8.gray(l)).join("\n");
6393
+ const moreLines = lines.length > maxLines ? "\n" + PREFIX + chalk8.gray(` ... (${lines.length - maxLines} more lines)`) : "";
6394
+ const truncNote = wasTruncated ? "\n" + PREFIX + chalk8.yellow(` \u26A1 \u8F93\u51FA\u5DF2\u622A\u65AD\u81F3 ${MAX_TOOL_OUTPUT_CHARS} \u5B57\u7B26`) : "";
6395
+ console.log(PREFIX + chalk8.green("\u2713 Result:"));
6064
6396
  console.log(prefixedPreview + moreLines + truncNote);
6065
6397
  }
6066
6398
  }
@@ -6090,25 +6422,25 @@ ${task}
6090
6422
  }
6091
6423
  function printSubAgentHeader(task, maxRounds) {
6092
6424
  console.log();
6093
- console.log(chalk7.dim(" \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
6094
- console.log(PREFIX + chalk7.bold.magenta("\u{1F916} Sub-Agent Spawned"));
6425
+ console.log(chalk8.dim(" \u250F\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
6426
+ console.log(PREFIX + chalk8.bold.magenta("\u{1F916} Sub-Agent Spawned"));
6095
6427
  console.log(
6096
- PREFIX + chalk7.gray("Task: ") + chalk7.white(task.slice(0, 120) + (task.length > 120 ? "..." : ""))
6428
+ PREFIX + chalk8.gray("Task: ") + chalk8.white(task.slice(0, 120) + (task.length > 120 ? "..." : ""))
6097
6429
  );
6098
- console.log(PREFIX + chalk7.gray(`Max rounds: ${maxRounds}`));
6099
- console.log(chalk7.dim(" \u2503"));
6430
+ console.log(PREFIX + chalk8.gray(`Max rounds: ${maxRounds}`));
6431
+ console.log(chalk8.dim(" \u2503"));
6100
6432
  }
6101
6433
  function printSubAgentFooter(usage) {
6102
6434
  console.log(PREFIX);
6103
- console.log(PREFIX + chalk7.bold.magenta("Sub-Agent Complete"));
6435
+ console.log(PREFIX + chalk8.bold.magenta("Sub-Agent Complete"));
6104
6436
  if (usage.inputTokens > 0 || usage.outputTokens > 0) {
6105
6437
  console.log(
6106
- PREFIX + chalk7.dim(
6438
+ PREFIX + chalk8.dim(
6107
6439
  `Tokens: ${usage.inputTokens} in / ${usage.outputTokens} out`
6108
6440
  )
6109
6441
  );
6110
6442
  }
6111
- console.log(chalk7.dim(" \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
6443
+ console.log(chalk8.dim(" \u2517\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
6112
6444
  console.log();
6113
6445
  }
6114
6446
  var spawnAgentTool = {
@@ -6357,159 +6689,6 @@ var ToolRegistry = class {
6357
6689
  import chalk9 from "chalk";
6358
6690
  import { existsSync as existsSync15, readFileSync as readFileSync9 } from "fs";
6359
6691
 
6360
- // src/tools/diff-utils.ts
6361
- import chalk8 from "chalk";
6362
- function renderDiff(oldText, newText, opts = {}) {
6363
- const contextLines = opts.contextLines ?? 3;
6364
- const maxLines = opts.maxLines ?? 120;
6365
- const filePath = opts.filePath ?? "";
6366
- const oldLines = oldText.split("\n");
6367
- const newLines = newText.split("\n");
6368
- const hunks = computeHunks(oldLines, newLines, contextLines);
6369
- if (hunks.length === 0) {
6370
- return chalk8.dim(" (no changes)");
6371
- }
6372
- const output = [];
6373
- if (filePath) {
6374
- output.push(chalk8.bold.white(`--- ${filePath} (before)`));
6375
- output.push(chalk8.bold.white(`+++ ${filePath} (after)`));
6376
- }
6377
- let totalDisplayed = 0;
6378
- for (const hunk of hunks) {
6379
- if (totalDisplayed >= maxLines) {
6380
- output.push(chalk8.dim(` ... (diff truncated, too many changes)`));
6381
- break;
6382
- }
6383
- output.push(
6384
- chalk8.cyan(
6385
- `@@ -${hunk.oldStart + 1},${hunk.oldCount} +${hunk.newStart + 1},${hunk.newCount} @@`
6386
- )
6387
- );
6388
- for (const line of hunk.lines) {
6389
- if (totalDisplayed >= maxLines) break;
6390
- totalDisplayed++;
6391
- if (line.type === "context") {
6392
- output.push(chalk8.dim(` ${line.text}`));
6393
- } else if (line.type === "remove") {
6394
- output.push(chalk8.red(`- ${line.text}`));
6395
- } else {
6396
- output.push(chalk8.green(`+ ${line.text}`));
6397
- }
6398
- }
6399
- }
6400
- return output.join("\n");
6401
- }
6402
- function computeHunks(oldLines, newLines, contextLines) {
6403
- const edits = diffLines(oldLines, newLines);
6404
- if (edits.every((e) => e.type === "context")) return [];
6405
- const hunks = [];
6406
- let i = 0;
6407
- while (i < edits.length) {
6408
- if (edits[i].type === "context") {
6409
- i++;
6410
- continue;
6411
- }
6412
- const start = Math.max(0, i - contextLines);
6413
- let end = i;
6414
- while (end < edits.length) {
6415
- if (edits[end].type !== "context") {
6416
- end++;
6417
- } else {
6418
- let hasMoreChange = false;
6419
- for (let j = end + 1; j < Math.min(edits.length, end + contextLines * 2 + 1); j++) {
6420
- if (edits[j].type !== "context") {
6421
- hasMoreChange = true;
6422
- break;
6423
- }
6424
- }
6425
- if (hasMoreChange) {
6426
- end++;
6427
- } else {
6428
- break;
6429
- }
6430
- }
6431
- }
6432
- end = Math.min(edits.length, end + contextLines);
6433
- const hunkEdits = edits.slice(start, end);
6434
- let oldStart = 0;
6435
- let newStart = 0;
6436
- for (let k = 0; k < start; k++) {
6437
- if (edits[k].type !== "add") oldStart++;
6438
- if (edits[k].type !== "remove") newStart++;
6439
- }
6440
- let oldCount = 0;
6441
- let newCount = 0;
6442
- for (const e of hunkEdits) {
6443
- if (e.type !== "add") oldCount++;
6444
- if (e.type !== "remove") newCount++;
6445
- }
6446
- hunks.push({
6447
- oldStart,
6448
- oldCount,
6449
- newStart,
6450
- newCount,
6451
- lines: hunkEdits.map((e) => ({ type: e.type, text: e.text }))
6452
- });
6453
- i = end;
6454
- }
6455
- return hunks;
6456
- }
6457
- function diffLines(oldLines, newLines) {
6458
- const n = oldLines.length;
6459
- const m = newLines.length;
6460
- if (n * m > 25e4) {
6461
- return simpleDiff(oldLines, newLines);
6462
- }
6463
- const dp = Array.from({ length: n + 1 }, () => new Array(m + 1).fill(0));
6464
- for (let i2 = 1; i2 <= n; i2++) {
6465
- for (let j2 = 1; j2 <= m; j2++) {
6466
- if (oldLines[i2 - 1] === newLines[j2 - 1]) {
6467
- dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
6468
- } else {
6469
- dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
6470
- }
6471
- }
6472
- }
6473
- const result = [];
6474
- let i = n;
6475
- let j = m;
6476
- while (i > 0 || j > 0) {
6477
- if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
6478
- result.unshift({ type: "context", text: oldLines[i - 1] });
6479
- i--;
6480
- j--;
6481
- } else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
6482
- result.unshift({ type: "add", text: newLines[j - 1] });
6483
- j--;
6484
- } else {
6485
- result.unshift({ type: "remove", text: oldLines[i - 1] });
6486
- i--;
6487
- }
6488
- }
6489
- return result;
6490
- }
6491
- function simpleDiff(oldLines, newLines) {
6492
- const result = [];
6493
- const maxLen = Math.max(oldLines.length, newLines.length);
6494
- for (let i = 0; i < maxLen; i++) {
6495
- const o = oldLines[i];
6496
- const n = newLines[i];
6497
- if (o !== void 0 && n !== void 0) {
6498
- if (o === n) {
6499
- result.push({ type: "context", text: o });
6500
- } else {
6501
- result.push({ type: "remove", text: o });
6502
- result.push({ type: "add", text: n });
6503
- }
6504
- } else if (o !== void 0) {
6505
- result.push({ type: "remove", text: o });
6506
- } else if (n !== void 0) {
6507
- result.push({ type: "add", text: n });
6508
- }
6509
- }
6510
- return result;
6511
- }
6512
-
6513
6692
  // src/tools/hooks.ts
6514
6693
  import { execSync as execSync5 } from "child_process";
6515
6694
  function runHook(template, vars) {
@@ -8939,17 +9118,17 @@ Session '${this.resumeSessionId}' not found.
8939
9118
  this.renderer.renderError(err);
8940
9119
  } finally {
8941
9120
  processing = false;
8942
- }
8943
- if (this.running) {
8944
- rlAny.output = savedOutput;
8945
- const rlInternal = this.rl;
8946
- rlInternal.line = "";
8947
- rlInternal.cursor = 0;
8948
- rlInternal.paused = false;
8949
- process.stdin.resume();
8950
- this.showPrompt();
8951
- } else {
8952
- resolve5();
9121
+ if (this.running) {
9122
+ rlAny.output = savedOutput;
9123
+ const rlInternal = this.rl;
9124
+ rlInternal.line = "";
9125
+ rlInternal.cursor = 0;
9126
+ rlInternal.paused = false;
9127
+ process.stdin.resume();
9128
+ this.showPrompt();
9129
+ } else {
9130
+ resolve5();
9131
+ }
8953
9132
  }
8954
9133
  });
8955
9134
  this.rl.on("close", () => {
@@ -9435,7 +9614,16 @@ Session '${this.resumeSessionId}' not found.
9435
9614
  if ("content" in result) {
9436
9615
  spinner.stop();
9437
9616
  const finalContent = result.content;
9438
- this.renderer.renderResponse(finalContent);
9617
+ if (useStreaming) {
9618
+ const streamAc = this.setupStreamInterrupt();
9619
+ try {
9620
+ await this.renderer.renderContentAsStream(finalContent, { signal: streamAc.signal });
9621
+ } finally {
9622
+ this.teardownStreamInterrupt();
9623
+ }
9624
+ } else {
9625
+ this.renderer.renderResponse(finalContent);
9626
+ }
9439
9627
  lastResponseStore.content = finalContent;
9440
9628
  session.addMessage({
9441
9629
  role: "assistant",
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-ZF62G7VO.js";
5
+ } from "./chunk-ZUZDWQVG.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",