jinzd-ai-cli 0.2.19 → 0.2.21

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.
@@ -16,7 +16,7 @@ import {
16
16
  SUBAGENT_MAX_ROUNDS_LIMIT,
17
17
  VERSION,
18
18
  runTestsTool
19
- } from "./chunk-HXEW5QYR.js";
19
+ } from "./chunk-YULS53ZT.js";
20
20
 
21
21
  // src/config/config-manager.ts
22
22
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -4540,11 +4540,23 @@ function formatResults(query, data, requested) {
4540
4540
  }
4541
4541
 
4542
4542
  // src/tools/truncate.ts
4543
- var MAX_TOOL_OUTPUT_CHARS = 12e3;
4544
- function truncateOutput(content, toolName) {
4545
- if (content.length <= MAX_TOOL_OUTPUT_CHARS) return content;
4546
- const keepHead = Math.floor(MAX_TOOL_OUTPUT_CHARS * 0.7);
4547
- const keepTail = Math.floor(MAX_TOOL_OUTPUT_CHARS * 0.2);
4543
+ var DEFAULT_MAX_TOOL_OUTPUT_CHARS = 12e3;
4544
+ function getMaxOutputChars(contextWindow) {
4545
+ if (!contextWindow || contextWindow <= 0) return DEFAULT_MAX_TOOL_OUTPUT_CHARS;
4546
+ return Math.max(DEFAULT_MAX_TOOL_OUTPUT_CHARS, Math.min(Math.floor(contextWindow / 4), 12e4));
4547
+ }
4548
+ var activeMaxChars = DEFAULT_MAX_TOOL_OUTPUT_CHARS;
4549
+ function setContextWindow(contextWindow) {
4550
+ activeMaxChars = getMaxOutputChars(contextWindow);
4551
+ }
4552
+ function getActiveMaxChars() {
4553
+ return activeMaxChars;
4554
+ }
4555
+ function truncateOutput(content, toolName, maxChars) {
4556
+ const limit = maxChars ?? activeMaxChars;
4557
+ if (content.length <= limit) return content;
4558
+ const keepHead = Math.floor(limit * 0.7);
4559
+ const keepTail = Math.floor(limit * 0.2);
4548
4560
  const omitted = content.length - keepHead - keepTail;
4549
4561
  const lines = content.split("\n").length;
4550
4562
  const head = content.slice(0, keepHead);
@@ -5979,7 +5991,8 @@ export {
5979
5991
  lastResponseStore,
5980
5992
  askUserContext,
5981
5993
  googleSearchContext,
5982
- MAX_TOOL_OUTPUT_CHARS,
5994
+ setContextWindow,
5995
+ getActiveMaxChars,
5983
5996
  truncateOutput,
5984
5997
  spawnAgentContext,
5985
5998
  ToolRegistry,
@@ -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.2.19";
11
+ var VERSION = "0.2.21";
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
@@ -2,7 +2,6 @@
2
2
  import {
3
3
  ConfigManager,
4
4
  HALLUCINATION_CORRECTION_MESSAGE,
5
- MAX_TOOL_OUTPUT_CHARS,
6
5
  McpManager,
7
6
  ProviderRegistry,
8
7
  SNAPSHOT_PROMPT,
@@ -15,6 +14,7 @@ import {
15
14
  clearDevState,
16
15
  detectsHallucinatedFileOp,
17
16
  formatGitContextForPrompt,
17
+ getActiveMaxChars,
18
18
  getContentText,
19
19
  getDangerLevel,
20
20
  getGitContext,
@@ -30,12 +30,13 @@ import {
30
30
  runHook,
31
31
  saveDevState,
32
32
  sessionHasMeaningfulContent,
33
+ setContextWindow,
33
34
  setupProxy,
34
35
  spawnAgentContext,
35
36
  theme,
36
37
  truncateOutput,
37
38
  undoStack
38
- } from "./chunk-J3IQYXYI.js";
39
+ } from "./chunk-TVSPBTDQ.js";
39
40
  import {
40
41
  AGENTIC_BEHAVIOR_GUIDELINE,
41
42
  AUTHOR,
@@ -55,7 +56,7 @@ import {
55
56
  REPO_URL,
56
57
  SKILLS_DIR_NAME,
57
58
  VERSION
58
- } from "./chunk-HXEW5QYR.js";
59
+ } from "./chunk-YULS53ZT.js";
59
60
 
60
61
  // src/index.ts
61
62
  import { program } from "commander";
@@ -1904,7 +1905,7 @@ ${hint}` : "")
1904
1905
  description: "Run project tests and show structured report",
1905
1906
  usage: "/test [command|filter]",
1906
1907
  async execute(args, _ctx) {
1907
- const { executeTests } = await import("./run-tests-SSWFSJWX.js");
1908
+ const { executeTests } = await import("./run-tests-WUWDJM5S.js");
1908
1909
  const argStr = args.join(" ").trim();
1909
1910
  let testArgs = {};
1910
1911
  if (argStr) {
@@ -2835,7 +2836,7 @@ var ToolExecutor = class {
2835
2836
  const moreLines = lines.length > maxLines ? theme.dim(`
2836
2837
  ... (${lines.length - maxLines} more lines)`) : "";
2837
2838
  const truncatedNote = wasTruncated ? theme.warning(`
2838
- \u26A1 Output truncated to ${MAX_TOOL_OUTPUT_CHARS} chars before sending to AI`) : "";
2839
+ \u26A1 Output truncated to ${getActiveMaxChars()} chars before sending to AI`) : "";
2839
2840
  console.log(theme.toolResult("\u2713 Result: ") + theme.dim(preview) + moreLines + truncatedNote);
2840
2841
  }
2841
2842
  console.log();
@@ -3397,6 +3398,8 @@ var Repl = class {
3397
3398
  _interjectionBuf = "";
3398
3399
  /** User interjection: stdin data handler reference */
3399
3400
  _interjectionHandler = null;
3401
+ /** Timestamp when confirm() completed — used to discard residual \n bytes from Windows \r\n */
3402
+ _confirmEndTime = 0;
3400
3403
  /** Multi-line input buffer: accumulates lines ending with \ */
3401
3404
  _multilineBuf = [];
3402
3405
  /** 运行时动态添加的额外上下文目录(/add-dir 命令) */
@@ -4034,6 +4037,7 @@ Session '${this.resumeSessionId}' not found.
4034
4037
  const welcomeProvider = this.providers.get(this.currentProvider);
4035
4038
  const welcomeModelInfo = welcomeProvider?.info.models.find((m) => m.id === this.currentModel);
4036
4039
  this.renderer.printWelcome(this.currentProvider, this.currentModel, welcomeModelInfo?.contextWindow);
4040
+ if (welcomeModelInfo?.contextWindow) setContextWindow(welcomeModelInfo.contextWindow);
4037
4041
  if (this.resumeSessionId) {
4038
4042
  const session = this.sessions.current;
4039
4043
  process.stdout.write(
@@ -4545,9 +4549,11 @@ Session '${this.resumeSessionId}' not found.
4545
4549
  this._interjectionBuf = "";
4546
4550
  const handler = (data) => {
4547
4551
  if (this.toolExecutor.confirming || askUserContext.prompting) return;
4548
- for (let i = 0; i < data.length; i++) {
4549
- const byte = data[i];
4550
- if (byte === 13 || byte === 10) {
4552
+ const str = data.toString("utf-8");
4553
+ for (const ch of str) {
4554
+ const code = ch.codePointAt(0);
4555
+ if (code === 13 || code === 10) {
4556
+ if (Date.now() - this._confirmEndTime < 100) continue;
4551
4557
  if (this._interjectionBuf.length > 0) {
4552
4558
  const line = this._interjectionBuf;
4553
4559
  this._interjectionBuf = "";
@@ -4560,13 +4566,16 @@ Session '${this.resumeSessionId}' not found.
4560
4566
  this._userInterjection = line;
4561
4567
  }
4562
4568
  }
4563
- } else if (byte === 127 || byte === 8) {
4569
+ } else if (code === 127 || code === 8) {
4564
4570
  if (this._interjectionBuf.length > 0) {
4565
- this._interjectionBuf = this._interjectionBuf.slice(0, -1);
4566
- process.stdout.write("\b \b");
4571
+ const chars = Array.from(this._interjectionBuf);
4572
+ const removed = chars.pop();
4573
+ this._interjectionBuf = chars.join("");
4574
+ const width = removed.codePointAt(0) > 255 ? 2 : 1;
4575
+ for (let w = 0; w < width; w++) process.stdout.write("\b \b");
4567
4576
  }
4568
- } else if (byte >= 32 && byte <= 126) {
4569
- const ch = String.fromCharCode(byte);
4577
+ } else if (code === 3 || code === 27) {
4578
+ } else if (code >= 32) {
4570
4579
  this._interjectionBuf += ch;
4571
4580
  process.stdout.write(ch);
4572
4581
  }
@@ -5091,6 +5100,7 @@ You have a maximum of ${MAX_TOOL_ROUNDS} tool call rounds for this task. Plan ef
5091
5100
  }
5092
5101
  }
5093
5102
  if (this._interjectionHandler) {
5103
+ this._confirmEndTime = Date.now();
5094
5104
  process.stdin.resume();
5095
5105
  }
5096
5106
  const reasoningContent = "reasoningContent" in result ? result.reasoningContent : void 0;
@@ -5310,6 +5320,8 @@ Tip: You can continue the conversation by asking the AI to proceed.`
5310
5320
  setProvider: (id, model) => {
5311
5321
  this.currentProvider = id;
5312
5322
  this.currentModel = model ?? this.config.get("defaultModels")[id] ?? this.providers.get(id).info.defaultModel;
5323
+ const ctxWin = this.getContextWindowSize();
5324
+ if (ctxWin > 0) setContextWindow(ctxWin);
5313
5325
  this.refreshPrompt();
5314
5326
  this.events.emit("provider.switch", {
5315
5327
  providerId: id,
@@ -5507,7 +5519,7 @@ program.command("web").description("Start Web UI server with browser-based chat
5507
5519
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
5508
5520
  process.exit(1);
5509
5521
  }
5510
- const { startWebServer } = await import("./server-HNAIE7Z3.js");
5522
+ const { startWebServer } = await import("./server-FVVKVJBX.js");
5511
5523
  await startWebServer({ port, host: options.host });
5512
5524
  });
5513
5525
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-HXEW5QYR.js";
5
+ } from "./chunk-YULS53ZT.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -20,10 +20,11 @@ import {
20
20
  loadDevState,
21
21
  renderDiff,
22
22
  runHook,
23
+ setContextWindow,
23
24
  setupProxy,
24
25
  spawnAgentContext,
25
26
  truncateOutput
26
- } from "./chunk-J3IQYXYI.js";
27
+ } from "./chunk-TVSPBTDQ.js";
27
28
  import {
28
29
  AGENTIC_BEHAVIOR_GUIDELINE,
29
30
  CONTEXT_FILE_CANDIDATES,
@@ -35,7 +36,7 @@ import {
35
36
  PLAN_MODE_SYSTEM_ADDON,
36
37
  SKILLS_DIR_NAME,
37
38
  VERSION
38
- } from "./chunk-HXEW5QYR.js";
39
+ } from "./chunk-YULS53ZT.js";
39
40
  import {
40
41
  AuthManager
41
42
  } from "./chunk-CPLT6CD3.js";
@@ -452,6 +453,7 @@ var SessionHandler = class {
452
453
  this.currentModel = "";
453
454
  }
454
455
  }
456
+ this.updateContextWindow();
455
457
  this.activeSystemPrompt = this.loadContextFiles();
456
458
  const hooks = this.config.get("hooks");
457
459
  const permissionRules = this.config.get("permissionRules");
@@ -530,6 +532,15 @@ var SessionHandler = class {
530
532
  this.pendingAskUser.clear();
531
533
  this.saveIfNeeded();
532
534
  }
535
+ /** 根据当前模型 context window 更新工具输出截断上限 */
536
+ updateContextWindow() {
537
+ try {
538
+ const provider = this.providers.get(this.currentProvider);
539
+ const modelInfo = provider?.info.models.find((m) => m.id === this.currentModel);
540
+ if (modelInfo?.contextWindow) setContextWindow(modelInfo.contextWindow);
541
+ } catch {
542
+ }
543
+ }
533
544
  /** Save session only if it exists and has messages (never persist empty "Untitled" sessions). */
534
545
  saveIfNeeded() {
535
546
  if (this.sessions.current && this.sessions.current.messages.length > 0) {
@@ -877,6 +888,7 @@ ${summaryResult.content}`,
877
888
  }
878
889
  this.currentProvider = id;
879
890
  this.currentModel = p.info.defaultModel;
891
+ this.updateContextWindow();
880
892
  this.send({ type: "info", message: `Switched to provider: ${id} (${this.currentModel})` });
881
893
  this.sendStatus();
882
894
  break;
@@ -894,6 +906,7 @@ ${summaryResult.content}`,
894
906
  return;
895
907
  }
896
908
  this.currentModel = modelId;
909
+ this.updateContextWindow();
897
910
  this.send({ type: "info", message: `Switched to model: ${modelId}` });
898
911
  this.sendStatus();
899
912
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.2.19",
3
+ "version": "0.2.21",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",