jinzd-ai-cli 0.4.122 → 0.4.124

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.
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ConfigManager
4
- } from "./chunk-JZDDHOG5.js";
4
+ } from "./chunk-NELLBZRA.js";
5
5
  import "./chunk-2ZD3YTVM.js";
6
- import "./chunk-TGFINUHW.js";
6
+ import "./chunk-I6U55T3H.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
 
9
9
  // src/cli/batch.ts
@@ -5,12 +5,12 @@ import {
5
5
  } from "./chunk-3BICTI5M.js";
6
6
  import {
7
7
  runTestsTool
8
- } from "./chunk-B5M3E7F5.js";
8
+ } from "./chunk-E56SNFYK.js";
9
9
  import {
10
10
  getDangerLevel,
11
11
  isFileWriteTool,
12
12
  runTool
13
- } from "./chunk-4GB6EG2Y.js";
13
+ } from "./chunk-JW4O67E3.js";
14
14
  import {
15
15
  EnvLoader,
16
16
  NetworkError,
@@ -23,7 +23,7 @@ import {
23
23
  SUBAGENT_ALLOWED_TOOLS,
24
24
  SUBAGENT_DEFAULT_MAX_ROUNDS,
25
25
  SUBAGENT_MAX_ROUNDS_LIMIT
26
- } from "./chunk-TGFINUHW.js";
26
+ } from "./chunk-I6U55T3H.js";
27
27
  import {
28
28
  fileCheckpoints
29
29
  } from "./chunk-4BKXL7SM.js";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  truncateForPersist
4
- } from "./chunk-TLDIOFCH.js";
4
+ } from "./chunk-2N6VKUH3.js";
5
5
  import {
6
6
  APP_NAME,
7
7
  CONFIG_DIR_NAME,
@@ -11,7 +11,7 @@ import {
11
11
  MCP_PROTOCOL_VERSION,
12
12
  MCP_TOOL_PREFIX,
13
13
  VERSION
14
- } from "./chunk-TGFINUHW.js";
14
+ } from "./chunk-I6U55T3H.js";
15
15
  import {
16
16
  redactJson
17
17
  } from "./chunk-7ZJN4KLV.js";
@@ -6,7 +6,7 @@ import { platform } from "os";
6
6
  import chalk from "chalk";
7
7
 
8
8
  // src/core/constants.ts
9
- var VERSION = "0.4.122";
9
+ var VERSION = "0.4.124";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TEST_TIMEOUT
4
- } from "./chunk-TGFINUHW.js";
4
+ } from "./chunk-I6U55T3H.js";
5
5
 
6
6
  // src/tools/builtin/run-tests.ts
7
7
  import { execSync, spawnSync } from "child_process";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  schemaToJsonSchema
4
- } from "./chunk-4GB6EG2Y.js";
4
+ } from "./chunk-JW4O67E3.js";
5
5
  import {
6
6
  AuthError,
7
7
  ProviderError,
@@ -1121,25 +1121,6 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1121
1121
  const usage = toUsage(response.usage);
1122
1122
  const contentStr = typeof message.content === "string" ? message.content : "";
1123
1123
  const hasToolCalls = !!(message.tool_calls && message.tool_calls.length > 0);
1124
- if (!hasToolCalls && contentStr.trim() === "") {
1125
- const providerId = this.info.id;
1126
- if (finishReason === "length") {
1127
- process.stderr.write(
1128
- `[${providerId}] \u26A0 Empty response with finish_reason='length' \u2014 output/context limit reached. Try /compact, raise maxTokens, or switch to a larger-context model.
1129
- `
1130
- );
1131
- } else if (finishReason === "content_filter") {
1132
- process.stderr.write(
1133
- `[${providerId}] \u26A0 Empty response with finish_reason='content_filter' \u2014 content was blocked.
1134
- `
1135
- );
1136
- } else {
1137
- process.stderr.write(
1138
- `[${providerId}] \u26A0 Empty response (finish_reason=${finishReason ?? "unknown"}). Model produced no text and no tool calls. Context window may be exhausted.
1139
- `
1140
- );
1141
- }
1142
- }
1143
1124
  const reasoningContent = message.reasoning_content;
1144
1125
  if (message.tool_calls && message.tool_calls.length > 0) {
1145
1126
  const toolCalls = message.tool_calls.map((tc) => {
@@ -1173,7 +1154,12 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1173
1154
  });
1174
1155
  return { toolCalls, usage, reasoningContent };
1175
1156
  }
1176
- return { content: message.content ?? "", usage, ...reasoningContent ? { reasoningContent } : {} };
1157
+ return {
1158
+ content: message.content ?? "",
1159
+ usage,
1160
+ ...reasoningContent ? { reasoningContent } : {},
1161
+ ...!hasToolCalls && (finishReason ?? "") ? { finishReason } : {}
1162
+ };
1177
1163
  } catch (err) {
1178
1164
  throw this.wrapError(err);
1179
1165
  }
@@ -1196,7 +1182,13 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1196
1182
  yield { type: "text_delta", delta: result.content };
1197
1183
  }
1198
1184
  const rc = "reasoningContent" in result ? result.reasoningContent : void 0;
1199
- yield { type: "done", usage: result.usage, ...rc ? { reasoningContent: rc } : {} };
1185
+ const fr = "finishReason" in result ? result.finishReason : void 0;
1186
+ yield {
1187
+ type: "done",
1188
+ usage: result.usage,
1189
+ ...rc ? { reasoningContent: rc } : {},
1190
+ ...fr ? { finishReason: fr } : {}
1191
+ };
1200
1192
  return;
1201
1193
  }
1202
1194
  const openaiTools = tools.map((t) => ({
@@ -1238,8 +1230,10 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1238
1230
  let toolCallsEnded = false;
1239
1231
  let thinkingStarted = false;
1240
1232
  let reasoningAccumulator = "";
1233
+ let lastFinishReason;
1241
1234
  for await (const chunk of stream) {
1242
1235
  const choice = chunk.choices[0];
1236
+ if (choice?.finish_reason) lastFinishReason = choice.finish_reason;
1243
1237
  if (!choice && chunk.usage) {
1244
1238
  if (thinkingStarted) {
1245
1239
  yield { type: "thinking_end" };
@@ -1254,7 +1248,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1254
1248
  yield {
1255
1249
  type: "done",
1256
1250
  usage: toUsage(chunk.usage),
1257
- ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {}
1251
+ ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {},
1252
+ ...lastFinishReason && lastFinishReason !== "stop" ? { finishReason: lastFinishReason } : {}
1258
1253
  };
1259
1254
  continue;
1260
1255
  }
@@ -1310,7 +1305,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1310
1305
  }
1311
1306
  yield {
1312
1307
  type: "done",
1313
- ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {}
1308
+ ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {},
1309
+ ...lastFinishReason && lastFinishReason !== "stop" ? { finishReason: lastFinishReason } : {}
1314
1310
  };
1315
1311
  } catch (err) {
1316
1312
  if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/core/constants.ts
4
- var VERSION = "0.4.122";
4
+ var VERSION = "0.4.124";
5
5
  var APP_NAME = "ai-cli";
6
6
  var CONFIG_DIR_NAME = ".aicli";
7
7
  var CONFIG_FILE_NAME = "config.json";
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  CONFIG_DIR_NAME
4
- } from "./chunk-TGFINUHW.js";
4
+ } from "./chunk-I6U55T3H.js";
5
5
 
6
6
  // src/diagnostics/tool-stats.ts
7
7
  import { existsSync, readFileSync, writeFileSync, mkdirSync, renameSync } from "fs";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CONFIG_DIR_NAME,
4
4
  VERSION
5
- } from "./chunk-TGFINUHW.js";
5
+ } from "./chunk-I6U55T3H.js";
6
6
 
7
7
  // src/diagnostics/crash-log.ts
8
8
  import {
@@ -8,7 +8,7 @@ import {
8
8
  CONFIG_FILE_NAME,
9
9
  HISTORY_DIR_NAME,
10
10
  PLUGINS_DIR_NAME
11
- } from "./chunk-TGFINUHW.js";
11
+ } from "./chunk-I6U55T3H.js";
12
12
 
13
13
  // src/config/config-manager.ts
14
14
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -36,7 +36,7 @@ import {
36
36
  TEST_TIMEOUT,
37
37
  VERSION,
38
38
  buildUserIdentityPrompt
39
- } from "./chunk-TGFINUHW.js";
39
+ } from "./chunk-I6U55T3H.js";
40
40
  import "./chunk-PDX44BCA.js";
41
41
  export {
42
42
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -2,25 +2,25 @@
2
2
  import {
3
3
  getConfigDirUsage,
4
4
  listRecentCrashes
5
- } from "./chunk-EYQZSLJR.js";
5
+ } from "./chunk-MANQVLVX.js";
6
6
  import {
7
7
  ProviderRegistry
8
- } from "./chunk-W52WG5R4.js";
8
+ } from "./chunk-HMZHKSGB.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-JZDDHOG5.js";
11
+ } from "./chunk-NELLBZRA.js";
12
12
  import {
13
13
  getStatsSnapshot,
14
14
  getTopFailingTools,
15
15
  getTopUsedTools,
16
16
  resetStats
17
- } from "./chunk-4GB6EG2Y.js";
17
+ } from "./chunk-JW4O67E3.js";
18
18
  import "./chunk-2ZD3YTVM.js";
19
19
  import {
20
20
  DEV_STATE_FILE_NAME,
21
21
  MEMORY_FILE_NAME,
22
22
  VERSION
23
- } from "./chunk-TGFINUHW.js";
23
+ } from "./chunk-I6U55T3H.js";
24
24
  import "./chunk-PDX44BCA.js";
25
25
 
26
26
  // src/diagnostics/doctor-cli.ts
@@ -156,10 +156,19 @@ async function runDoctorCli(options = {}) {
156
156
  }
157
157
  }
158
158
  out.push("");
159
+ const dirAnnotations = {
160
+ models: "semantic search model \u2192 aicli: /index semantic-clear",
161
+ index: "symbol index \u2192 aicli: /index clear",
162
+ history: "conversation history \u2192 auto-pruned after 30 days",
163
+ logs: "crash logs",
164
+ "memory-index": "chat memory index \u2192 aicli: /memory index-clear"
165
+ };
159
166
  out.push(`${B}Disk Usage (~/.aicli):${RESET}`);
160
167
  out.push(` total: ${formatBytes(report.diskUsage.totalBytes)}`);
161
- for (const e of report.diskUsage.entries.slice(0, 8)) {
162
- out.push(` ${e.name.padEnd(18)} ${formatBytes(e.bytes)}`);
168
+ for (const e of report.diskUsage.entries.slice(0, 10)) {
169
+ const note = dirAnnotations[e.name];
170
+ const noteStr = note ? ` ${D}\xB7 ${note}${RESET}` : "";
171
+ out.push(` ${e.name.padEnd(18)} ${formatBytes(e.bytes)}${noteStr}`);
163
172
  }
164
173
  out.push("");
165
174
  out.push(`${G}\u2713 Health check complete${RESET}`);
@@ -36,7 +36,7 @@ import {
36
36
  VERSION,
37
37
  buildUserIdentityPrompt,
38
38
  runTestsTool
39
- } from "./chunk-JDMTDRYD.js";
39
+ } from "./chunk-5PMDFNOC.js";
40
40
  import {
41
41
  hasSemanticIndex,
42
42
  semanticSearch
@@ -1667,25 +1667,6 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1667
1667
  const usage = toUsage(response.usage);
1668
1668
  const contentStr = typeof message.content === "string" ? message.content : "";
1669
1669
  const hasToolCalls = !!(message.tool_calls && message.tool_calls.length > 0);
1670
- if (!hasToolCalls && contentStr.trim() === "") {
1671
- const providerId = this.info.id;
1672
- if (finishReason === "length") {
1673
- process.stderr.write(
1674
- `[${providerId}] \u26A0 Empty response with finish_reason='length' \u2014 output/context limit reached. Try /compact, raise maxTokens, or switch to a larger-context model.
1675
- `
1676
- );
1677
- } else if (finishReason === "content_filter") {
1678
- process.stderr.write(
1679
- `[${providerId}] \u26A0 Empty response with finish_reason='content_filter' \u2014 content was blocked.
1680
- `
1681
- );
1682
- } else {
1683
- process.stderr.write(
1684
- `[${providerId}] \u26A0 Empty response (finish_reason=${finishReason ?? "unknown"}). Model produced no text and no tool calls. Context window may be exhausted.
1685
- `
1686
- );
1687
- }
1688
- }
1689
1670
  const reasoningContent = message.reasoning_content;
1690
1671
  if (message.tool_calls && message.tool_calls.length > 0) {
1691
1672
  const toolCalls = message.tool_calls.map((tc) => {
@@ -1719,7 +1700,12 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1719
1700
  });
1720
1701
  return { toolCalls, usage, reasoningContent };
1721
1702
  }
1722
- return { content: message.content ?? "", usage, ...reasoningContent ? { reasoningContent } : {} };
1703
+ return {
1704
+ content: message.content ?? "",
1705
+ usage,
1706
+ ...reasoningContent ? { reasoningContent } : {},
1707
+ ...!hasToolCalls && (finishReason ?? "") ? { finishReason } : {}
1708
+ };
1723
1709
  } catch (err) {
1724
1710
  throw this.wrapError(err);
1725
1711
  }
@@ -1742,7 +1728,13 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1742
1728
  yield { type: "text_delta", delta: result.content };
1743
1729
  }
1744
1730
  const rc = "reasoningContent" in result ? result.reasoningContent : void 0;
1745
- yield { type: "done", usage: result.usage, ...rc ? { reasoningContent: rc } : {} };
1731
+ const fr = "finishReason" in result ? result.finishReason : void 0;
1732
+ yield {
1733
+ type: "done",
1734
+ usage: result.usage,
1735
+ ...rc ? { reasoningContent: rc } : {},
1736
+ ...fr ? { finishReason: fr } : {}
1737
+ };
1746
1738
  return;
1747
1739
  }
1748
1740
  const openaiTools = tools.map((t) => ({
@@ -1784,8 +1776,10 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1784
1776
  let toolCallsEnded = false;
1785
1777
  let thinkingStarted = false;
1786
1778
  let reasoningAccumulator = "";
1779
+ let lastFinishReason;
1787
1780
  for await (const chunk of stream) {
1788
1781
  const choice = chunk.choices[0];
1782
+ if (choice?.finish_reason) lastFinishReason = choice.finish_reason;
1789
1783
  if (!choice && chunk.usage) {
1790
1784
  if (thinkingStarted) {
1791
1785
  yield { type: "thinking_end" };
@@ -1800,7 +1794,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1800
1794
  yield {
1801
1795
  type: "done",
1802
1796
  usage: toUsage(chunk.usage),
1803
- ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {}
1797
+ ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {},
1798
+ ...lastFinishReason && lastFinishReason !== "stop" ? { finishReason: lastFinishReason } : {}
1804
1799
  };
1805
1800
  continue;
1806
1801
  }
@@ -1856,7 +1851,8 @@ var OpenAICompatibleProvider = class extends BaseProvider {
1856
1851
  }
1857
1852
  yield {
1858
1853
  type: "done",
1859
- ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {}
1854
+ ...reasoningAccumulator ? { reasoningContent: reasoningAccumulator } : {},
1855
+ ...lastFinishReason && lastFinishReason !== "stop" ? { finishReason: lastFinishReason } : {}
1860
1856
  };
1861
1857
  } catch (err) {
1862
1858
  if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
@@ -12207,7 +12203,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
12207
12203
  case "test": {
12208
12204
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
12209
12205
  try {
12210
- const { executeTests } = await import("./run-tests-YMCRZ6PG.js");
12206
+ const { executeTests } = await import("./run-tests-47O4Z3BM.js");
12211
12207
  const argStr = args.join(" ").trim();
12212
12208
  let testArgs = {};
12213
12209
  if (argStr) {
@@ -386,7 +386,7 @@ ${content}`);
386
386
  }
387
387
  }
388
388
  async function runTaskMode(config, providers, configManager, topic) {
389
- const { TaskOrchestrator } = await import("./task-orchestrator-XMMM4YCB.js");
389
+ const { TaskOrchestrator } = await import("./task-orchestrator-ANBMXQ2E.js");
390
390
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
391
391
  let interrupted = false;
392
392
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -16,12 +16,12 @@ import {
16
16
  saveDevState,
17
17
  sessionHasMeaningfulContent,
18
18
  setupProxy
19
- } from "./chunk-QJVXLVMR.js";
19
+ } from "./chunk-2Q4TRDUS.js";
20
20
  import {
21
21
  getConfigDirUsage,
22
22
  listRecentCrashes,
23
23
  writeCrashLog
24
- } from "./chunk-EYQZSLJR.js";
24
+ } from "./chunk-MANQVLVX.js";
25
25
  import {
26
26
  CONTENT_ONLY_STREAM_REMINDER,
27
27
  HALLUCINATION_CORRECTION_MESSAGE,
@@ -39,10 +39,10 @@ import {
39
39
  looksLikeDocumentBody,
40
40
  stripPseudoToolCalls,
41
41
  stripToolCallReminder
42
- } from "./chunk-W52WG5R4.js";
42
+ } from "./chunk-HMZHKSGB.js";
43
43
  import {
44
44
  ConfigManager
45
- } from "./chunk-JZDDHOG5.js";
45
+ } from "./chunk-NELLBZRA.js";
46
46
  import {
47
47
  ToolExecutor,
48
48
  ToolRegistry,
@@ -61,16 +61,16 @@ import {
61
61
  spawnAgentContext,
62
62
  theme,
63
63
  undoStack
64
- } from "./chunk-TLDIOFCH.js";
64
+ } from "./chunk-2N6VKUH3.js";
65
65
  import "./chunk-3BICTI5M.js";
66
66
  import "./chunk-2DXY7UGF.js";
67
- import "./chunk-B5M3E7F5.js";
67
+ import "./chunk-E56SNFYK.js";
68
68
  import {
69
69
  getStatsSnapshot,
70
70
  getTopFailingTools,
71
71
  getTopUsedTools,
72
72
  installFlushOnExit
73
- } from "./chunk-4GB6EG2Y.js";
73
+ } from "./chunk-JW4O67E3.js";
74
74
  import "./chunk-2ZD3YTVM.js";
75
75
  import {
76
76
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -93,7 +93,7 @@ import {
93
93
  SKILLS_DIR_NAME,
94
94
  VERSION,
95
95
  buildUserIdentityPrompt
96
- } from "./chunk-TGFINUHW.js";
96
+ } from "./chunk-I6U55T3H.js";
97
97
  import {
98
98
  formatGitContextForPrompt,
99
99
  getGitContext,
@@ -1748,7 +1748,7 @@ No tools match "${filter}".
1748
1748
  const { join: join6 } = await import("path");
1749
1749
  const { existsSync: existsSync6 } = await import("fs");
1750
1750
  const { getGitRoot: getGitRoot2 } = await import("./git-context-7KIP4X2V.js");
1751
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-KQTYOOGP.js");
1751
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-SQ6ER44V.js");
1752
1752
  const { approveProject, hashMcpFile } = await import("./project-trust-IFM7FXEV.js");
1753
1753
  const cwd = process.cwd();
1754
1754
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -2809,7 +2809,7 @@ ${hint}` : "")
2809
2809
  usage: "/test [command|filter]",
2810
2810
  async execute(args, ctx) {
2811
2811
  try {
2812
- const { executeTests } = await import("./run-tests-EKFEFXDY.js");
2812
+ const { executeTests } = await import("./run-tests-V7Q3ZJW2.js");
2813
2813
  const argStr = args.join(" ").trim();
2814
2814
  let testArgs = {};
2815
2815
  if (argStr) {
@@ -3210,10 +3210,19 @@ ${text}
3210
3210
  if (n < 1024 * 1024 * 1024) return `${(n / 1024 / 1024).toFixed(1)} MB`;
3211
3211
  return `${(n / 1024 / 1024 / 1024).toFixed(2)} GB`;
3212
3212
  };
3213
+ const dirAnnotations = {
3214
+ models: "semantic search model \u2192 /index semantic-clear to free",
3215
+ index: "symbol index \u2192 /index clear to rebuild",
3216
+ history: "conversation history \u2192 auto-pruned after 30 days",
3217
+ logs: "crash logs",
3218
+ "memory-index": "chat memory index \u2192 /memory index-clear to free"
3219
+ };
3213
3220
  console.log(theme.heading("Disk Usage (~/.aicli):"));
3214
3221
  console.log(` total: ${theme.accent(fmt(usage.totalBytes))}`);
3215
- for (const e of usage.entries.slice(0, 8)) {
3216
- console.log(` ${e.name.padEnd(18)} ${theme.dim(fmt(e.bytes))}`);
3222
+ for (const e of usage.entries.slice(0, 10)) {
3223
+ const note = dirAnnotations[e.name];
3224
+ const noteStr = note ? ` ${theme.dim("\xB7")} ${theme.dim(note)}` : "";
3225
+ console.log(` ${e.name.padEnd(18)} ${theme.dim(fmt(e.bytes))}${noteStr}`);
3217
3226
  }
3218
3227
  console.log();
3219
3228
  console.log(theme.success("\u2713 Health check complete\n"));
@@ -6010,6 +6019,7 @@ Session '${this.resumeSessionId}' not found.
6010
6019
  let usage;
6011
6020
  let rawContent;
6012
6021
  let reasoningContent;
6022
+ let finishReason;
6013
6023
  let spinnerStopped = false;
6014
6024
  const stopSpinner = () => {
6015
6025
  if (!spinnerStopped) {
@@ -6059,6 +6069,7 @@ Session '${this.resumeSessionId}' not found.
6059
6069
  if (event.usage) usage = event.usage;
6060
6070
  if (event.rawContent) rawContent = event.rawContent;
6061
6071
  if (event.reasoningContent) reasoningContent = event.reasoningContent;
6072
+ if (event.finishReason) finishReason = event.finishReason;
6062
6073
  break;
6063
6074
  }
6064
6075
  }
@@ -6071,7 +6082,8 @@ Session '${this.resumeSessionId}' not found.
6071
6082
  toolCalls: [],
6072
6083
  usage,
6073
6084
  rawContent,
6074
- reasoningContent
6085
+ reasoningContent,
6086
+ finishReason
6075
6087
  };
6076
6088
  }
6077
6089
  throw err;
@@ -6102,7 +6114,8 @@ Session '${this.resumeSessionId}' not found.
6102
6114
  toolCalls,
6103
6115
  usage,
6104
6116
  rawContent,
6105
- reasoningContent
6117
+ reasoningContent,
6118
+ finishReason
6106
6119
  };
6107
6120
  }
6108
6121
  async handleChatWithTools(provider, messages, modelOverride) {
@@ -6322,7 +6335,8 @@ ${mcpBudgetNote}` : "");
6322
6335
  result = {
6323
6336
  content: streamResult.textContent,
6324
6337
  usage: streamResult.usage,
6325
- ...streamResult.reasoningContent ? { reasoningContent: streamResult.reasoningContent } : {}
6338
+ ...streamResult.reasoningContent ? { reasoningContent: streamResult.reasoningContent } : {},
6339
+ ...streamResult.finishReason ? { finishReason: streamResult.finishReason } : {}
6326
6340
  };
6327
6341
  alreadyRendered = true;
6328
6342
  }
@@ -6363,15 +6377,15 @@ ${mcpBudgetNote}` : "");
6363
6377
  continue;
6364
6378
  }
6365
6379
  if (!result.content || result.content.trim() === "") {
6380
+ const fr = "finishReason" in result ? result.finishReason : void 0;
6381
+ const reasonLabel = fr === "length" ? "output limit reached (finish_reason=length)" : fr === "content_filter" ? "content blocked (finish_reason=content_filter)" : fr ? `empty response (finish_reason=${fr})` : "empty response";
6366
6382
  if (emptyResponseRetries === 0 && round < maxToolRounds - 1) {
6367
6383
  emptyResponseRetries++;
6368
6384
  spinner.stop();
6369
6385
  if (alreadyRendered) process.stdout.write("\n");
6370
6386
  process.stderr.write(
6371
- theme.warning(
6372
- `\u26A0 AI returned an empty response (no text, no tool calls). Nudging to continue...
6373
- `
6374
- )
6387
+ theme.warning(`\u26A0 ${reasonLabel} \u2014 nudging AI to continue...
6388
+ `)
6375
6389
  );
6376
6390
  extraMessages.push({
6377
6391
  role: "user",
@@ -6382,20 +6396,17 @@ ${mcpBudgetNote}` : "");
6382
6396
  }
6383
6397
  spinner.stop();
6384
6398
  if (alreadyRendered) process.stdout.write("\n");
6399
+ const frHint = fr === "length" ? "Output token limit hit \u2014 try /compact to reduce context, raise maxTokens, or /model to switch." : fr === "content_filter" ? "Content was blocked by the provider filter." : "Context window may be exhausted or max_tokens too low.";
6385
6400
  process.stderr.write(
6386
- theme.error(
6387
- `
6401
+ theme.error(`
6388
6402
  \u26A0 AI returned empty responses twice in a row. Stopping agentic loop.
6389
- `
6390
- )
6403
+ `)
6391
6404
  );
6392
6405
  process.stderr.write(
6393
- theme.dim(
6394
- ` Likely causes: context window exhausted, max_tokens too low, or content filter.
6395
- Try: /compact to reduce context, /clear to reset, or /model to switch.
6406
+ theme.dim(` ${frHint}
6407
+ Try: /compact, /clear, or /model to switch.
6396
6408
 
6397
- `
6398
- )
6409
+ `)
6399
6410
  );
6400
6411
  if (roundUsage.inputTokens > 0 || roundUsage.outputTokens > 0) {
6401
6412
  this.addSessionUsage(roundUsage, effectiveModel);
@@ -7158,7 +7169,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7158
7169
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7159
7170
  process.exit(1);
7160
7171
  }
7161
- const { startWebServer } = await import("./server-5PVP7OLW.js");
7172
+ const { startWebServer } = await import("./server-NASNKJZP.js");
7162
7173
  await startWebServer({ port, host: options.host });
7163
7174
  });
7164
7175
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | logout-all <name> | migrate <name>)").action(async (action, username) => {
@@ -7272,33 +7283,65 @@ ${users.length} user(s) registered (auth enabled):
7272
7283
  console.error("Available: list, create, delete, reset-password, logout-all, migrate");
7273
7284
  process.exit(1);
7274
7285
  });
7275
- program.command("sessions").description("List recent conversation sessions").action(async () => {
7286
+ program.command("sessions").description("List recent conversation sessions").option("-n, --last <n>", "Show only the N most recent sessions", "20").option("--provider <id>", "Filter by provider (e.g. claude, openai)").action(async (options) => {
7287
+ const chalk5 = (await import("chalk")).default;
7276
7288
  const config = new ConfigManager();
7277
7289
  const sessions = new SessionManager(config);
7278
- const list = sessions.listSessions();
7290
+ let list = sessions.listSessions();
7291
+ if (options.provider) {
7292
+ const filterProv = options.provider.toLowerCase();
7293
+ list = list.filter((s) => s.provider.toLowerCase().includes(filterProv));
7294
+ }
7295
+ const limit = Math.max(1, parseInt(options.last ?? "20", 10) || 20);
7296
+ list = list.slice(0, limit);
7279
7297
  if (list.length === 0) {
7280
- console.log("\nNo saved sessions.\n");
7298
+ console.log("\n" + chalk5.dim("No saved sessions.") + "\n");
7281
7299
  return;
7282
7300
  }
7283
- console.log("\nRecent sessions:\n");
7284
- console.log(
7285
- "ID".padEnd(10) + "Provider".padEnd(12) + "Model".padEnd(30) + "Msgs".padEnd(6) + "Date".padEnd(12) + "Title"
7286
- );
7287
- console.log("-".repeat(80));
7301
+ const relDate = (d) => {
7302
+ const diffMs = Date.now() - d.getTime();
7303
+ const diffMin = Math.floor(diffMs / 6e4);
7304
+ if (diffMin < 1) return "just now";
7305
+ if (diffMin < 60) return `${diffMin}m ago`;
7306
+ const diffH = Math.floor(diffMin / 60);
7307
+ if (diffH < 24) return `${diffH}h ago`;
7308
+ const diffD = Math.floor(diffH / 24);
7309
+ if (diffD < 7) return `${diffD}d ago`;
7310
+ return d.toLocaleDateString();
7311
+ };
7312
+ const truncate = (s, n) => s.length > n ? s.slice(0, n - 1) + "\u2026" : s;
7313
+ console.log("");
7314
+ const hId = chalk5.bold("ID ");
7315
+ const hProvider = chalk5.bold("Provider ");
7316
+ const hModel = chalk5.bold("Model ");
7317
+ const hMsgs = chalk5.bold("Msgs");
7318
+ const hDate = chalk5.bold(" When ");
7319
+ const hTitle = chalk5.bold("Title");
7320
+ console.log(` ${hId} ${hProvider} ${hModel} ${hMsgs} ${hDate} ${hTitle}`);
7321
+ console.log(" " + chalk5.dim("\u2500".repeat(88)));
7288
7322
  for (const s of list) {
7289
- console.log(
7290
- s.id.slice(0, 8).padEnd(10) + s.provider.padEnd(12) + s.model.padEnd(30) + String(s.messageCount).padEnd(6) + s.updated.toLocaleDateString().padEnd(12) + (s.title ?? "(untitled)")
7291
- );
7292
- }
7293
- console.log();
7323
+ const id = chalk5.cyan(s.id.slice(0, 8));
7324
+ const provider = chalk5.yellow(truncate(s.provider, 11).padEnd(11));
7325
+ const model = chalk5.dim(truncate(s.model, 28).padEnd(28));
7326
+ const msgs = String(s.messageCount).padStart(4);
7327
+ const when = chalk5.dim(relDate(s.updated).padEnd(12));
7328
+ const title = s.title ? s.title : chalk5.dim("(untitled)");
7329
+ console.log(` ${id} ${provider} ${model} ${msgs} ${when} ${truncate(title, 40)}`);
7330
+ }
7331
+ const total = sessions.listSessions().length;
7332
+ const shown = list.length;
7333
+ const footer = shown < total ? chalk5.dim(`
7334
+ Showing ${shown} of ${total} sessions \xB7 use -n <count> or --provider <id> to filter`) : chalk5.dim(`
7335
+ ${total} session${total !== 1 ? "s" : ""} total`);
7336
+ console.log(footer + "\n");
7294
7337
  });
7295
7338
  program.command("doctor").description("Health check: API keys, config, MCP, recent crashes, tool usage, disk usage").option("--json", "Output as JSON (for scripting)").option("--reset-stats", "Reset accumulated tool usage statistics").action(async (options) => {
7296
- const { runDoctorCli } = await import("./doctor-cli-HUKR2SSS.js");
7339
+ const { runDoctorCli } = await import("./doctor-cli-YTMFJ6QY.js");
7297
7340
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7298
7341
  });
7299
7342
  program.command("batch <action> [arg] [arg2]").description("Anthropic Message Batches: submit | list | status <id> | results <id> [out] | cancel <id>").option("--dry-run", "Parse and validate input without submitting (submit only)").action(async (action, arg, arg2, options) => {
7300
7343
  try {
7301
- const batch = await import("./batch-TWT336TR.js");
7344
+ const batch = await import("./batch-CZPE7S25.js");
7302
7345
  switch (action) {
7303
7346
  case "submit":
7304
7347
  if (!arg) {
@@ -7341,7 +7384,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7341
7384
  }
7342
7385
  });
7343
7386
  program.command("mcp-serve").description("Start an MCP server over STDIO, exposing aicli's built-in tools to Claude Desktop / Cursor / other MCP clients").option("--allow-destructive", "Allow bash / run_interactive / task_create (always destructive in MCP mode)").option("--allow-outside-cwd", "Allow tool path arguments to escape the sandbox root \u2014 disabled by default").option("--tools <list>", "Comma-separated whitelist of tools to expose (default: all eligible tools)").option("--cwd <path>", "Working directory AND sandbox root (default: current directory)").action(async (options) => {
7344
- const { startMcpServer } = await import("./server-7FWUIWPE.js");
7387
+ const { startMcpServer } = await import("./server-QOVMOY2G.js");
7345
7388
  await startMcpServer({
7346
7389
  allowDestructive: !!options.allowDestructive,
7347
7390
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7468,7 +7511,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7468
7511
  }),
7469
7512
  config.get("customProviders")
7470
7513
  );
7471
- const { startHub } = await import("./hub-PLSKV3VL.js");
7514
+ const { startHub } = await import("./hub-KMLZPWBX.js");
7472
7515
  await startHub(
7473
7516
  {
7474
7517
  topic: topic ?? "",
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-JDMTDRYD.js";
4
+ } from "./chunk-5PMDFNOC.js";
5
5
  import "./chunk-3RG5ZIWI.js";
6
6
  export {
7
7
  executeTests,
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-B5M3E7F5.js";
6
- import "./chunk-TGFINUHW.js";
5
+ } from "./chunk-E56SNFYK.js";
6
+ import "./chunk-I6U55T3H.js";
7
7
  import "./chunk-PDX44BCA.js";
8
8
  export {
9
9
  executeTests,
@@ -14,7 +14,7 @@ import {
14
14
  loadDevState,
15
15
  persistToolRound,
16
16
  setupProxy
17
- } from "./chunk-QJVXLVMR.js";
17
+ } from "./chunk-2Q4TRDUS.js";
18
18
  import {
19
19
  CONTENT_ONLY_STREAM_REMINDER,
20
20
  HALLUCINATION_CORRECTION_MESSAGE,
@@ -28,10 +28,10 @@ import {
28
28
  looksLikeDocumentBody,
29
29
  stripPseudoToolCalls,
30
30
  stripToolCallReminder
31
- } from "./chunk-W52WG5R4.js";
31
+ } from "./chunk-HMZHKSGB.js";
32
32
  import {
33
33
  ConfigManager
34
- } from "./chunk-JZDDHOG5.js";
34
+ } from "./chunk-NELLBZRA.js";
35
35
  import {
36
36
  ToolExecutor,
37
37
  ToolRegistry,
@@ -49,14 +49,14 @@ import {
49
49
  spawnAgentContext,
50
50
  truncateOutput,
51
51
  undoStack
52
- } from "./chunk-TLDIOFCH.js";
52
+ } from "./chunk-2N6VKUH3.js";
53
53
  import "./chunk-3BICTI5M.js";
54
54
  import "./chunk-2DXY7UGF.js";
55
- import "./chunk-B5M3E7F5.js";
55
+ import "./chunk-E56SNFYK.js";
56
56
  import {
57
57
  getDangerLevel,
58
58
  runTool
59
- } from "./chunk-4GB6EG2Y.js";
59
+ } from "./chunk-JW4O67E3.js";
60
60
  import "./chunk-2ZD3YTVM.js";
61
61
  import {
62
62
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -76,7 +76,7 @@ import {
76
76
  SKILLS_DIR_NAME,
77
77
  VERSION,
78
78
  buildUserIdentityPrompt
79
- } from "./chunk-TGFINUHW.js";
79
+ } from "./chunk-I6U55T3H.js";
80
80
  import {
81
81
  formatGitContextForPrompt,
82
82
  getGitContext,
@@ -2460,7 +2460,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2460
2460
  case "test": {
2461
2461
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2462
2462
  try {
2463
- const { executeTests } = await import("./run-tests-EKFEFXDY.js");
2463
+ const { executeTests } = await import("./run-tests-V7Q3ZJW2.js");
2464
2464
  const argStr = args.join(" ").trim();
2465
2465
  let testArgs = {};
2466
2466
  if (argStr) {
@@ -1,19 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-TLDIOFCH.js";
4
+ } from "./chunk-2N6VKUH3.js";
5
5
  import "./chunk-3BICTI5M.js";
6
6
  import "./chunk-2DXY7UGF.js";
7
- import "./chunk-B5M3E7F5.js";
7
+ import "./chunk-E56SNFYK.js";
8
8
  import {
9
9
  getDangerLevel,
10
10
  runTool,
11
11
  schemaToJsonSchema
12
- } from "./chunk-4GB6EG2Y.js";
12
+ } from "./chunk-JW4O67E3.js";
13
13
  import "./chunk-2ZD3YTVM.js";
14
14
  import {
15
15
  VERSION
16
- } from "./chunk-TGFINUHW.js";
16
+ } from "./chunk-I6U55T3H.js";
17
17
  import "./chunk-4BKXL7SM.js";
18
18
  import "./chunk-7ZJN4KLV.js";
19
19
  import "./chunk-KHYD3WXE.js";
@@ -3,18 +3,18 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-TLDIOFCH.js";
6
+ } from "./chunk-2N6VKUH3.js";
7
7
  import "./chunk-3BICTI5M.js";
8
8
  import "./chunk-2DXY7UGF.js";
9
- import "./chunk-B5M3E7F5.js";
9
+ import "./chunk-E56SNFYK.js";
10
10
  import {
11
11
  getDangerLevel,
12
12
  runTool
13
- } from "./chunk-4GB6EG2Y.js";
13
+ } from "./chunk-JW4O67E3.js";
14
14
  import "./chunk-2ZD3YTVM.js";
15
15
  import {
16
16
  SUBAGENT_ALLOWED_TOOLS
17
- } from "./chunk-TGFINUHW.js";
17
+ } from "./chunk-I6U55T3H.js";
18
18
  import "./chunk-4BKXL7SM.js";
19
19
  import "./chunk-7ZJN4KLV.js";
20
20
  import "./chunk-KHYD3WXE.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.122",
3
+ "version": "0.4.124",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",