jinzd-ai-cli 0.4.27 → 0.4.29

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.
@@ -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.27";
9
+ var VERSION = "0.4.29";
10
10
  var APP_NAME = "ai-cli";
11
11
  var CONFIG_DIR_NAME = ".aicli";
12
12
  var CONFIG_FILE_NAME = "config.json";
@@ -7,7 +7,7 @@ import {
7
7
  ProviderNotFoundError,
8
8
  RateLimitError,
9
9
  schemaToJsonSchema
10
- } from "./chunk-22KSHJZJ.js";
10
+ } from "./chunk-SXL6H7XR.js";
11
11
  import {
12
12
  APP_NAME,
13
13
  CONFIG_DIR_NAME,
@@ -20,7 +20,7 @@ import {
20
20
  MCP_TOOL_PREFIX,
21
21
  PLUGINS_DIR_NAME,
22
22
  VERSION
23
- } from "./chunk-LVEJKGIN.js";
23
+ } from "./chunk-TE6QE7FJ.js";
24
24
 
25
25
  // src/config/config-manager.ts
26
26
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
@@ -1587,6 +1587,95 @@ Describing file content in text without calling the tool = the file does not exi
1587
1587
  If multiple files need to be generated, you MUST call write_file separately for each file \u2014 do not skip any.
1588
1588
  Do NOT output fake "completion summaries" unless you have actually completed all file writes via tool_calls.`;
1589
1589
  var HALLUCINATION_CORRECTION_MESSAGE = "You did NOT actually call the write_file tool \u2014 the file was NOT created! Please immediately use the write_file tool via the function calling API to perform the actual file write. Do NOT describe file content in text \u2014 you MUST invoke write_file through the tool_calls mechanism.";
1590
+ function extractClaimedFilePaths(content) {
1591
+ const paths = /* @__PURE__ */ new Set();
1592
+ const add = (p) => {
1593
+ const trimmed = p.trim().replace(/[,,。、;;::]+$/, "");
1594
+ if (trimmed && /\.\w{1,6}$/.test(trimmed)) paths.add(trimmed);
1595
+ };
1596
+ const backtickRe = /`([^`\n]+?\.\w{1,6})`/g;
1597
+ let m;
1598
+ while ((m = backtickRe.exec(content)) !== null) add(m[1]);
1599
+ const zhRe = /(?:已保存(?:到)?|已写入(?:到)?|已创建|已生成|文件路径[::]|保存为|写入到)\s*[`'"“”]?([^\s`'"“”,,。\n]+?\.\w{1,6})/g;
1600
+ while ((m = zhRe.exec(content)) !== null) add(m[1]);
1601
+ const enRe = /(?:saved|written|created)\s+(?:to|as|at)\s+[`'"]?([^\s`'"\n,]+?\.\w{1,6})/gi;
1602
+ while ((m = enRe.exec(content)) !== null) add(m[1]);
1603
+ const checkRe = /✅[^\n`]*?[`'"]?([^\s`'"\n,,。]+?\.\w{1,6})/g;
1604
+ while ((m = checkRe.exec(content)) !== null) add(m[1]);
1605
+ return Array.from(paths);
1606
+ }
1607
+ function extractWrittenFilePaths(extraMessages) {
1608
+ const paths = /* @__PURE__ */ new Set();
1609
+ const msgs = extraMessages;
1610
+ const addFromArgs = (raw) => {
1611
+ if (typeof raw === "string") {
1612
+ try {
1613
+ const parsed = JSON.parse(raw);
1614
+ if (typeof parsed.path === "string") paths.add(parsed.path);
1615
+ } catch {
1616
+ }
1617
+ } else if (raw && typeof raw === "object") {
1618
+ const p = raw.path;
1619
+ if (typeof p === "string") paths.add(p);
1620
+ }
1621
+ };
1622
+ for (const msg of msgs) {
1623
+ if (msg.role === "assistant" && Array.isArray(msg.tool_calls)) {
1624
+ for (const tc of msg.tool_calls) {
1625
+ const fn = tc.function;
1626
+ const name = fn?.name ?? "";
1627
+ if (name === "write_file" || name === "edit_file") {
1628
+ addFromArgs(fn?.arguments);
1629
+ }
1630
+ }
1631
+ }
1632
+ if (msg.role === "assistant" && Array.isArray(msg.content)) {
1633
+ for (const block of msg.content) {
1634
+ if (block.type !== "tool_use") continue;
1635
+ const name = block.name ?? "";
1636
+ if (name === "write_file" || name === "edit_file") {
1637
+ addFromArgs(block.input);
1638
+ }
1639
+ }
1640
+ }
1641
+ if (msg.role === "model" && Array.isArray(msg.parts)) {
1642
+ for (const part of msg.parts) {
1643
+ const fc = part.functionCall;
1644
+ if (!fc) continue;
1645
+ const name = fc.name ?? "";
1646
+ if (name === "write_file" || name === "edit_file") {
1647
+ addFromArgs(fc.args);
1648
+ }
1649
+ }
1650
+ }
1651
+ }
1652
+ return Array.from(paths);
1653
+ }
1654
+ function findPhantomClaims(content, extraMessages) {
1655
+ const claimed = extractClaimedFilePaths(content);
1656
+ if (claimed.length === 0) return [];
1657
+ const normalize = (p) => p.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
1658
+ const basename2 = (p) => {
1659
+ const parts = normalize(p).split("/");
1660
+ return parts[parts.length - 1] ?? "";
1661
+ };
1662
+ const written = extractWrittenFilePaths(extraMessages).map(normalize);
1663
+ const writtenBases = new Set(written.map(basename2));
1664
+ const writtenFull = new Set(written);
1665
+ return claimed.filter((raw) => {
1666
+ const norm = normalize(raw);
1667
+ if (writtenFull.has(norm)) return false;
1668
+ for (const w of writtenFull) {
1669
+ if (w.endsWith("/" + norm) || norm.endsWith("/" + w)) return false;
1670
+ }
1671
+ if (writtenBases.has(basename2(norm))) return false;
1672
+ return true;
1673
+ });
1674
+ }
1675
+ function buildPhantomCorrectionMessage(phantoms) {
1676
+ const list = phantoms.map((p) => ` - ${p}`).join("\n");
1677
+ return "You claimed to have written the following file(s), but no matching write_file tool call was actually made in this turn:\n" + list + '\n\nEach of these files does NOT exist on disk. You MUST now invoke write_file (via the function calling API) for every missing file listed above. Do NOT output another "completion summary" until the tool calls have actually been made.';
1678
+ }
1590
1679
 
1591
1680
  // src/providers/kimi.ts
1592
1681
  var KIMI_XML_REMINDER = `
@@ -3335,6 +3424,8 @@ export {
3335
3424
  hadPreviousWriteToolCalls,
3336
3425
  TOOL_CALL_REMINDER,
3337
3426
  HALLUCINATION_CORRECTION_MESSAGE,
3427
+ findPhantomClaims,
3428
+ buildPhantomCorrectionMessage,
3338
3429
  ProviderRegistry,
3339
3430
  getContentText,
3340
3431
  SessionManager,
@@ -9,7 +9,7 @@ import {
9
9
  SUBAGENT_DEFAULT_MAX_ROUNDS,
10
10
  SUBAGENT_MAX_ROUNDS_LIMIT,
11
11
  runTestsTool
12
- } from "./chunk-LVEJKGIN.js";
12
+ } from "./chunk-TE6QE7FJ.js";
13
13
 
14
14
  // src/tools/builtin/bash.ts
15
15
  import { execSync } from "child_process";
@@ -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.4.27";
11
+ var VERSION = "0.4.29";
12
12
  var APP_NAME = "ai-cli";
13
13
  var CONFIG_DIR_NAME = ".aicli";
14
14
  var CONFIG_FILE_NAME = "config.json";
@@ -387,7 +387,7 @@ ${content}`);
387
387
  }
388
388
  }
389
389
  async function runTaskMode(config, providers, configManager, topic) {
390
- const { TaskOrchestrator } = await import("./task-orchestrator-42RXTDZD.js");
390
+ const { TaskOrchestrator } = await import("./task-orchestrator-LLCLCGR2.js");
391
391
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
392
392
  let interrupted = false;
393
393
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -8,8 +8,10 @@ import {
8
8
  SessionManager,
9
9
  SkillManager,
10
10
  TOOL_CALL_REMINDER,
11
+ buildPhantomCorrectionMessage,
11
12
  clearDevState,
12
13
  detectsHallucinatedFileOp,
14
+ findPhantomClaims,
13
15
  formatGitContextForPrompt,
14
16
  getContentText,
15
17
  getGitContext,
@@ -20,7 +22,7 @@ import {
20
22
  saveDevState,
21
23
  sessionHasMeaningfulContent,
22
24
  setupProxy
23
- } from "./chunk-MONMUTCS.js";
25
+ } from "./chunk-JHVH276O.js";
24
26
  import {
25
27
  ToolExecutor,
26
28
  ToolRegistry,
@@ -33,7 +35,7 @@ import {
33
35
  spawnAgentContext,
34
36
  theme,
35
37
  undoStack
36
- } from "./chunk-22KSHJZJ.js";
38
+ } from "./chunk-SXL6H7XR.js";
37
39
  import {
38
40
  fileCheckpoints
39
41
  } from "./chunk-4BKXL7SM.js";
@@ -57,7 +59,7 @@ import {
57
59
  SKILLS_DIR_NAME,
58
60
  VERSION,
59
61
  buildUserIdentityPrompt
60
- } from "./chunk-LVEJKGIN.js";
62
+ } from "./chunk-TE6QE7FJ.js";
61
63
 
62
64
  // src/index.ts
63
65
  import { program } from "commander";
@@ -2083,7 +2085,7 @@ ${hint}` : "")
2083
2085
  usage: "/test [command|filter]",
2084
2086
  async execute(args, ctx) {
2085
2087
  try {
2086
- const { executeTests } = await import("./run-tests-6PMTHGR3.js");
2088
+ const { executeTests } = await import("./run-tests-FNWRWJUI.js");
2087
2089
  const argStr = args.join(" ").trim();
2088
2090
  let testArgs = {};
2089
2091
  if (argStr) {
@@ -3089,17 +3091,27 @@ var CustomCommandManager = class {
3089
3091
  // src/repl/notify.ts
3090
3092
  import { spawn } from "child_process";
3091
3093
  import { platform as platform2 } from "os";
3094
+ function safeSpawn(cmd, args) {
3095
+ let child;
3096
+ try {
3097
+ child = spawn(cmd, args, { detached: true, stdio: "ignore" });
3098
+ } catch {
3099
+ return;
3100
+ }
3101
+ child.on("error", () => {
3102
+ });
3103
+ child.unref();
3104
+ }
3092
3105
  function sendNotification(title, body) {
3093
3106
  const plat = platform2();
3094
3107
  try {
3095
3108
  if (plat === "darwin") {
3096
3109
  const safeTitle = title.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
3097
3110
  const safeBody = body.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
3098
- spawn(
3099
- "osascript",
3100
- ["-e", `display notification "${safeBody}" with title "${safeTitle}"`],
3101
- { detached: true, stdio: "ignore" }
3102
- ).unref();
3111
+ safeSpawn("osascript", [
3112
+ "-e",
3113
+ `display notification "${safeBody}" with title "${safeTitle}"`
3114
+ ]);
3103
3115
  } else if (plat === "win32") {
3104
3116
  const safeTitle = title.replace(/`/g, "``").replace(/"/g, '`"');
3105
3117
  const safeBody = body.replace(/`/g, "``").replace(/"/g, '`"');
@@ -3114,13 +3126,16 @@ function sendNotification(title, body) {
3114
3126
  "Start-Sleep -Milliseconds 3500",
3115
3127
  "$n.Dispose()"
3116
3128
  ].join("; ");
3117
- spawn(
3118
- "powershell",
3119
- ["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-Command", script],
3120
- { detached: true, stdio: "ignore" }
3121
- ).unref();
3129
+ safeSpawn("powershell", [
3130
+ "-NoProfile",
3131
+ "-NonInteractive",
3132
+ "-WindowStyle",
3133
+ "Hidden",
3134
+ "-Command",
3135
+ script
3136
+ ]);
3122
3137
  } else {
3123
- spawn("notify-send", [title, body], { detached: true, stdio: "ignore" }).unref();
3138
+ safeSpawn("notify-send", [title, body]);
3124
3139
  }
3125
3140
  } catch {
3126
3141
  }
@@ -4794,19 +4809,22 @@ You have a maximum of ${MAX_TOOL_ROUNDS} tool call rounds for this task. Plan ef
4794
4809
  if ("content" in result) {
4795
4810
  const hasWriteTools = toolDefs.some((t) => t.name === "write_file" || t.name === "edit_file");
4796
4811
  const alreadyWrote = hadPreviousWriteToolCalls(extraMessages);
4797
- if (!this.planMode && // Plan Mode 下跳过虚假声明检测
4798
- hasWriteTools && !alreadyWrote && result.content && detectsHallucinatedFileOp(result.content) && round < MAX_TOOL_ROUNDS - 1) {
4812
+ const phantomPaths = !this.planMode && hasWriteTools && result.content ? findPhantomClaims(result.content, extraMessages) : [];
4813
+ const coarseHallucination = !this.planMode && hasWriteTools && !alreadyWrote && !!result.content && detectsHallucinatedFileOp(result.content);
4814
+ if ((phantomPaths.length > 0 || coarseHallucination) && round < MAX_TOOL_ROUNDS - 1) {
4799
4815
  const providerName = this.currentProvider;
4816
+ const detail = phantomPaths.length > 0 ? ` phantom files: ${phantomPaths.join(", ")}` : "";
4800
4817
  process.stderr.write(
4801
- `[${providerName}] \u26A0 Hallucinated completion detected (AI claimed file was written but no tool was called), forcing retry...
4818
+ `[${providerName}] \u26A0 Hallucinated completion detected (AI claimed file was written but no tool was called), forcing retry...${detail}
4802
4819
  `
4803
4820
  );
4804
4821
  if (alreadyRendered) {
4805
4822
  process.stdout.write("\n");
4806
4823
  }
4824
+ const correctionMsg = phantomPaths.length > 0 ? buildPhantomCorrectionMessage(phantomPaths) : HALLUCINATION_CORRECTION_MESSAGE;
4807
4825
  extraMessages.push(
4808
4826
  { role: "assistant", content: result.content },
4809
- { role: "user", content: HALLUCINATION_CORRECTION_MESSAGE }
4827
+ { role: "user", content: correctionMsg }
4810
4828
  );
4811
4829
  spinner.start(`Retrying... (round ${round + 2}/${MAX_TOOL_ROUNDS})`);
4812
4830
  continue;
@@ -5365,7 +5383,7 @@ program.command("web").description("Start Web UI server with browser-based chat
5365
5383
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
5366
5384
  process.exit(1);
5367
5385
  }
5368
- const { startWebServer } = await import("./server-PVBEJXS6.js");
5386
+ const { startWebServer } = await import("./server-DSICPNYM.js");
5369
5387
  await startWebServer({ port, host: options.host });
5370
5388
  });
5371
5389
  program.command("user [action] [username]").description("Manage Web UI users (list | create <name> | delete <name> | reset-password <name> | migrate <name>)").action(async (action, username) => {
@@ -5598,7 +5616,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
5598
5616
  }),
5599
5617
  config.get("customProviders")
5600
5618
  );
5601
- const { startHub } = await import("./hub-VYCI73QC.js");
5619
+ const { startHub } = await import("./hub-RMUO6RN2.js");
5602
5620
  await startHub(
5603
5621
  {
5604
5622
  topic: topic ?? "",
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-LVEJKGIN.js";
5
+ } from "./chunk-TE6QE7FJ.js";
6
6
  export {
7
7
  executeTests,
8
8
  runTestsTool
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-H7OVRCEJ.js";
4
+ } from "./chunk-FETMBU6E.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -15,7 +15,7 @@ import {
15
15
  hadPreviousWriteToolCalls,
16
16
  loadDevState,
17
17
  setupProxy
18
- } from "./chunk-MONMUTCS.js";
18
+ } from "./chunk-JHVH276O.js";
19
19
  import {
20
20
  AuthManager
21
21
  } from "./chunk-BYNY5JPB.js";
@@ -33,7 +33,7 @@ import {
33
33
  spawnAgentContext,
34
34
  truncateOutput,
35
35
  undoStack
36
- } from "./chunk-22KSHJZJ.js";
36
+ } from "./chunk-SXL6H7XR.js";
37
37
  import "./chunk-4BKXL7SM.js";
38
38
  import {
39
39
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -52,7 +52,7 @@ import {
52
52
  SKILLS_DIR_NAME,
53
53
  VERSION,
54
54
  buildUserIdentityPrompt
55
- } from "./chunk-LVEJKGIN.js";
55
+ } from "./chunk-TE6QE7FJ.js";
56
56
 
57
57
  // src/web/server.ts
58
58
  import express from "express";
@@ -1606,7 +1606,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
1606
1606
  case "test": {
1607
1607
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
1608
1608
  try {
1609
- const { executeTests } = await import("./run-tests-6PMTHGR3.js");
1609
+ const { executeTests } = await import("./run-tests-FNWRWJUI.js");
1610
1610
  const argStr = args.join(" ").trim();
1611
1611
  let testArgs = {};
1612
1612
  if (argStr) {
@@ -4,11 +4,11 @@ import {
4
4
  getDangerLevel,
5
5
  googleSearchContext,
6
6
  truncateOutput
7
- } from "./chunk-22KSHJZJ.js";
7
+ } from "./chunk-SXL6H7XR.js";
8
8
  import "./chunk-4BKXL7SM.js";
9
9
  import {
10
10
  SUBAGENT_ALLOWED_TOOLS
11
- } from "./chunk-LVEJKGIN.js";
11
+ } from "./chunk-TE6QE7FJ.js";
12
12
 
13
13
  // src/hub/task-orchestrator.ts
14
14
  import { createInterface } from "readline";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.27",
3
+ "version": "0.4.29",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",