jinzd-ai-cli 0.4.205 → 0.4.207

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +1 -1
  2. package/dist/{batch-RBPABHS7.js → batch-6PORMJWT.js} +2 -2
  3. package/dist/{chunk-XIYSFN4U.js → chunk-2WV6AGHM.js} +1 -1
  4. package/dist/{chunk-43H3D2PK.js → chunk-BQIV4ZQT.js} +1 -1
  5. package/dist/{chunk-JVYH66N2.js → chunk-KJHMRAJU.js} +1 -1
  6. package/dist/{chunk-ZSC4YLEJ.js → chunk-KOU4KX7J.js} +2 -2
  7. package/dist/{chunk-UZISJ3KZ.js → chunk-QMXC327F.js} +3 -3
  8. package/dist/{chunk-3RET7PL7.js → chunk-QNUVZO5X.js} +1 -1
  9. package/dist/{chunk-43MWRT2C.js → chunk-QQYSZMET.js} +20 -17
  10. package/dist/{chunk-VOV2PWZU.js → chunk-SFCNFX42.js} +1 -1
  11. package/dist/{chunk-TZ7SNVSG.js → chunk-TW47X5AO.js} +1 -1
  12. package/dist/{chunk-SMFRJCXB.js → chunk-XPBEJB27.js} +8 -1
  13. package/dist/{ci-ABE74AXH.js → ci-AYMV66P3.js} +9 -9
  14. package/dist/{constants-GMQMJRIO.js → constants-NHGTSHKT.js} +1 -1
  15. package/dist/{doctor-cli-M5PPO3L3.js → doctor-cli-WKH7T4AW.js} +6 -6
  16. package/dist/electron-server.js +46 -41
  17. package/dist/{hub-NCU5JNCK.js → hub-6R3M3NTC.js} +1 -1
  18. package/dist/index.js +102 -98
  19. package/dist/{run-tests-ZFAEFEYK.js → run-tests-5F2OBWIK.js} +2 -2
  20. package/dist/{run-tests-FGRWBNVF.js → run-tests-NBCA4KEG.js} +1 -1
  21. package/dist/{server-RKP7JRRE.js → server-37EXC4EB.js} +5 -5
  22. package/dist/{server-ML6ZL3J5.js → server-L2MXWYF7.js} +26 -26
  23. package/dist/{task-orchestrator-LJP5XZSC.js → task-orchestrator-2DTDVCMR.js} +5 -5
  24. package/dist/{usage-YX2235W5.js → usage-SZWZFX3T.js} +2 -2
  25. package/dist/web/client/actions.js +84 -0
  26. package/dist/web/client/app.js +23 -205
  27. package/dist/web/client/index.html +27 -42
  28. package/dist/web/client/sw.js +1 -1
  29. package/dist/web/client/templates.js +188 -0
  30. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  saveDevState,
16
16
  sessionHasMeaningfulContent,
17
17
  setupProxy
18
- } from "./chunk-ZSC4YLEJ.js";
18
+ } from "./chunk-KOU4KX7J.js";
19
19
  import {
20
20
  ToolExecutor,
21
21
  ToolRegistry,
@@ -35,10 +35,10 @@ import {
35
35
  spawnAgentContext,
36
36
  theme,
37
37
  undoStack
38
- } from "./chunk-43MWRT2C.js";
38
+ } from "./chunk-QQYSZMET.js";
39
39
  import "./chunk-T2NL5ZIA.js";
40
40
  import "./chunk-BXP6YZ2P.js";
41
- import "./chunk-VOV2PWZU.js";
41
+ import "./chunk-SFCNFX42.js";
42
42
  import {
43
43
  SessionManager,
44
44
  getContentText
@@ -55,16 +55,16 @@ import {
55
55
  getConfigDirUsage,
56
56
  listRecentCrashes,
57
57
  writeCrashLog
58
- } from "./chunk-JVYH66N2.js";
58
+ } from "./chunk-KJHMRAJU.js";
59
59
  import {
60
60
  ProviderRegistry
61
- } from "./chunk-UZISJ3KZ.js";
61
+ } from "./chunk-QMXC327F.js";
62
62
  import {
63
63
  getStatsSnapshot,
64
64
  getTopFailingTools,
65
65
  getTopUsedTools,
66
66
  installFlushOnExit
67
- } from "./chunk-XIYSFN4U.js";
67
+ } from "./chunk-2WV6AGHM.js";
68
68
  import {
69
69
  CONTENT_ONLY_STREAM_REMINDER,
70
70
  TEE_FINAL_USER_NUDGE,
@@ -83,10 +83,10 @@ import {
83
83
  stripOuterCodeFence,
84
84
  stripToolCallReminder,
85
85
  teeStreamErrorSummary
86
- } from "./chunk-SMFRJCXB.js";
86
+ } from "./chunk-XPBEJB27.js";
87
87
  import {
88
88
  ConfigManager
89
- } from "./chunk-TZ7SNVSG.js";
89
+ } from "./chunk-TW47X5AO.js";
90
90
  import {
91
91
  AuthError,
92
92
  ProviderError,
@@ -113,7 +113,7 @@ import {
113
113
  SKILLS_DIR_NAME,
114
114
  VERSION,
115
115
  buildUserIdentityPrompt
116
- } from "./chunk-3RET7PL7.js";
116
+ } from "./chunk-QNUVZO5X.js";
117
117
  import {
118
118
  formatGitContextForPrompt,
119
119
  getGitContext,
@@ -135,15 +135,17 @@ import {
135
135
  } from "./chunk-SLSWPBK3.js";
136
136
  import "./chunk-O6UFCEUZ.js";
137
137
  import "./chunk-CKH4KQ4E.js";
138
- import "./chunk-IW3Q7AE5.js";
138
+ import {
139
+ atomicWriteFileSync
140
+ } from "./chunk-IW3Q7AE5.js";
139
141
 
140
142
  // src/index.ts
141
143
  import { program } from "commander";
142
144
 
143
145
  // src/repl/repl.ts
144
146
  import * as readline from "readline";
145
- import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "fs";
146
- import { join as join4, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
147
+ import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync4, mkdirSync as mkdirSync4 } from "fs";
148
+ import { join as join5, resolve as resolve2, extname as extname2, dirname as dirname3, basename as basename2 } from "path";
147
149
  import chalk4 from "chalk";
148
150
 
149
151
  // src/session/title-generator.ts
@@ -635,10 +637,10 @@ Error${typeName}: ${lines.join("\n")}
635
637
  };
636
638
 
637
639
  // src/repl/commands/index.ts
638
- import { writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync2, readFileSync, readdirSync, statSync as statSync2, appendFileSync } from "fs";
640
+ import { writeFileSync, mkdirSync as mkdirSync2, existsSync as existsSync3, readFileSync as readFileSync2, statSync as statSync3, appendFileSync } from "fs";
639
641
  import { execSync as execSync2 } from "child_process";
640
642
  import { platform } from "os";
641
- import { resolve, dirname as dirname2, join as join2, basename } from "path";
643
+ import { resolve, dirname as dirname2, join as join3, basename } from "path";
642
644
  import chalk2 from "chalk";
643
645
 
644
646
  // src/repl/clipboard.ts
@@ -728,12 +730,9 @@ function getClipboardHint() {
728
730
  return "";
729
731
  }
730
732
 
731
- // src/repl/commands/index.ts
732
- function fmtCtx(tokens) {
733
- if (tokens >= 1e6) return `${Math.round(tokens / 1e5) / 10}M`;
734
- if (tokens >= 1e3) return `${Math.round(tokens / 1024)}K`;
735
- return `${tokens}`;
736
- }
733
+ // src/repl/commands/project-init.ts
734
+ import { existsSync as existsSync2, readFileSync, readdirSync, statSync as statSync2 } from "fs";
735
+ import { join as join2 } from "path";
737
736
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
738
737
  "node_modules",
739
738
  ".git",
@@ -791,7 +790,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
791
790
  const name = sorted[i];
792
791
  const fullPath = join2(d, name);
793
792
  const isLast = i === sorted.length - 1;
794
- const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
793
+ const connector = isLast ? "+-- " : "|-- ";
795
794
  let isDir;
796
795
  try {
797
796
  isDir = statSync2(fullPath).isDirectory();
@@ -801,7 +800,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
801
800
  lines.push(prefix + connector + name + (isDir ? "/" : ""));
802
801
  count++;
803
802
  if (isDir) {
804
- walk(fullPath, prefix + (isLast ? " " : "\u2502 "), depth + 1);
803
+ walk(fullPath, prefix + (isLast ? " " : "| "), depth + 1);
805
804
  }
806
805
  }
807
806
  };
@@ -845,9 +844,9 @@ function scanProject(cwd) {
845
844
  try {
846
845
  const pkg = JSON.parse(readFileSync(join2(cwd, "package.json"), "utf-8"));
847
846
  const scripts = pkg.scripts ?? {};
848
- info.buildCommand = scripts.build ? `npm run build` : void 0;
849
- info.testCommand = scripts.test ? `npm test` : void 0;
850
- info.devCommand = scripts.dev ? `npm run dev` : void 0;
847
+ info.buildCommand = scripts.build ? "npm run build" : void 0;
848
+ info.testCommand = scripts.test ? "npm test" : void 0;
849
+ info.devCommand = scripts.dev ? "npm run dev" : void 0;
851
850
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
852
851
  if (allDeps["react"]) info.framework = "React";
853
852
  else if (allDeps["vue"]) info.framework = "Vue";
@@ -889,10 +888,8 @@ function scanProject(cwd) {
889
888
  }
890
889
  function buildInitPrompt(info, cwd) {
891
890
  const parts = [
892
- `Please generate an AICLI.md context file (Markdown format) for the following project. This file will be injected into the AI conversation's system prompt to help the AI understand the project structure and coding conventions.`,
893
- `
894
- ## Project Info
895
- `,
891
+ "Please generate an AICLI.md context file (Markdown format) for the following project. This file will be injected into the AI conversation system prompt to help the AI understand the project structure and coding conventions.",
892
+ "\n## Project Info\n",
896
893
  `- Working directory: ${cwd}`,
897
894
  `- Type: ${info.type}`,
898
895
  `- Language: ${info.language}`
@@ -921,6 +918,13 @@ Please generate a structured Markdown file containing:
921
918
  Output the Markdown content directly, do not wrap the entire file in a code block. Keep it concise, within 200 lines.`);
922
919
  return parts.join("\n");
923
920
  }
921
+
922
+ // src/repl/commands/index.ts
923
+ function fmtCtx(tokens) {
924
+ if (tokens >= 1e6) return `${Math.round(tokens / 1e5) / 10}M`;
925
+ if (tokens >= 1e3) return `${Math.round(tokens / 1024)}K`;
926
+ return `${tokens}`;
927
+ }
924
928
  function copyToClipboard(text) {
925
929
  const plat = platform();
926
930
  if (plat === "win32") {
@@ -1825,16 +1829,16 @@ No tools match "${filter}".
1825
1829
  usage: "/mcp [reconnect [serverId] | trust-project]",
1826
1830
  async execute(args, ctx) {
1827
1831
  if (args[0] === "trust-project") {
1828
- const { join: join5 } = await import("path");
1829
- const { existsSync: existsSync5 } = await import("fs");
1832
+ const { join: join6 } = await import("path");
1833
+ const { existsSync: existsSync6 } = await import("fs");
1830
1834
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1831
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-GMQMJRIO.js");
1835
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-NHGTSHKT.js");
1832
1836
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1833
1837
  const cwd = process.cwd();
1834
1838
  const projectRoot = getGitRoot2(cwd) ?? cwd;
1835
- const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME2);
1839
+ const mcpPath = join6(projectRoot, MCP_PROJECT_CONFIG_NAME2);
1836
1840
  console.log();
1837
- if (!existsSync5(mcpPath)) {
1841
+ if (!existsSync6(mcpPath)) {
1838
1842
  console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
1839
1843
  console.log();
1840
1844
  return;
@@ -2167,9 +2171,9 @@ No tools match "${filter}".
2167
2171
  usage: "/init [--force]",
2168
2172
  async execute(args, ctx) {
2169
2173
  const cwd = process.cwd();
2170
- const targetPath = join2(cwd, "AICLI.md");
2174
+ const targetPath = join3(cwd, "AICLI.md");
2171
2175
  const force = args.includes("--force");
2172
- if (existsSync2(targetPath) && !force) {
2176
+ if (existsSync3(targetPath) && !force) {
2173
2177
  ctx.renderer.printInfo(`AICLI.md already exists at ${targetPath}`);
2174
2178
  ctx.renderer.printInfo("Use /init --force to overwrite, or edit it manually.");
2175
2179
  return;
@@ -2889,7 +2893,7 @@ ${hint}` : "")
2889
2893
  usage: "/test [command|filter]",
2890
2894
  async execute(args, ctx) {
2891
2895
  try {
2892
- const { executeTests } = await import("./run-tests-ZFAEFEYK.js");
2896
+ const { executeTests } = await import("./run-tests-5F2OBWIK.js");
2893
2897
  const argStr = args.join(" ").trim();
2894
2898
  let testArgs = {};
2895
2899
  if (argStr) {
@@ -3047,7 +3051,7 @@ ${hint}` : "")
3047
3051
  description: "Persistent memory (memory.md) + chat memory recall index (v0.4.89+)",
3048
3052
  usage: "/memory [show|add <text>|clear|path|rebuild|refresh|status|recall <query>|index-clear]",
3049
3053
  async execute(args, ctx) {
3050
- const memoryFile = join2(ctx.config.getConfigDir(), MEMORY_FILE_NAME);
3054
+ const memoryFile = join3(ctx.config.getConfigDir(), MEMORY_FILE_NAME);
3051
3055
  const sub = args[0] ?? "show";
3052
3056
  if (sub === "rebuild" || sub === "refresh") {
3053
3057
  const full = sub === "rebuild";
@@ -3131,11 +3135,11 @@ ${hint}` : "")
3131
3135
  return;
3132
3136
  }
3133
3137
  if (sub === "show" || sub === "view") {
3134
- if (!existsSync2(memoryFile)) {
3138
+ if (!existsSync3(memoryFile)) {
3135
3139
  ctx.renderer.printInfo("Memory is empty (memory.md not found)");
3136
3140
  return;
3137
3141
  }
3138
- const content = readFileSync(memoryFile, "utf-8").trim();
3142
+ const content = readFileSync2(memoryFile, "utf-8").trim();
3139
3143
  if (!content) {
3140
3144
  ctx.renderer.printInfo("Memory is empty");
3141
3145
  return;
@@ -3166,7 +3170,7 @@ ${text}
3166
3170
  ctx.renderer.renderError(`Failed to write memory: ${err instanceof Error ? err.message : String(err)}`);
3167
3171
  }
3168
3172
  } else if (sub === "clear") {
3169
- if (!existsSync2(memoryFile)) {
3173
+ if (!existsSync3(memoryFile)) {
3170
3174
  ctx.renderer.printInfo("Memory is already empty");
3171
3175
  return;
3172
3176
  }
@@ -3202,20 +3206,20 @@ ${text}
3202
3206
  console.log(theme.heading("Config Files:"));
3203
3207
  console.log(` Dir: ${theme.accent(configDir)}`);
3204
3208
  const checkFile = (label, filePath) => {
3205
- const exists = existsSync2(filePath);
3209
+ const exists = existsSync3(filePath);
3206
3210
  const icon = exists ? theme.success("\u2713") : theme.dim("\u2013");
3207
3211
  let extra = "";
3208
3212
  if (exists) {
3209
3213
  try {
3210
- extra = theme.dim(` (${statSync2(filePath).size} bytes)`);
3214
+ extra = theme.dim(` (${statSync3(filePath).size} bytes)`);
3211
3215
  } catch {
3212
3216
  }
3213
3217
  }
3214
3218
  console.log(` ${icon} ${label.padEnd(14)} ${exists ? filePath : theme.dim("(not found)")}${extra}`);
3215
3219
  };
3216
- checkFile("config.json", join2(configDir, "config.json"));
3217
- checkFile("memory.md", join2(configDir, MEMORY_FILE_NAME));
3218
- checkFile("dev-state.md", join2(configDir, "dev-state.md"));
3220
+ checkFile("config.json", join3(configDir, "config.json"));
3221
+ checkFile("memory.md", join3(configDir, MEMORY_FILE_NAME));
3222
+ checkFile("dev-state.md", join3(configDir, "dev-state.md"));
3219
3223
  console.log();
3220
3224
  const mcpManager = ctx.getMcpManager();
3221
3225
  if (mcpManager) {
@@ -3379,9 +3383,9 @@ ${text}
3379
3383
  let newFiles = 0;
3380
3384
  let modifiedFiles = 0;
3381
3385
  for (const [filePath, { earliest }] of fileMap) {
3382
- const currentContent = existsSync2(filePath) ? (() => {
3386
+ const currentContent = existsSync3(filePath) ? (() => {
3383
3387
  try {
3384
- return readFileSync(filePath, "utf-8");
3388
+ return readFileSync2(filePath, "utf-8");
3385
3389
  } catch {
3386
3390
  return null;
3387
3391
  }
@@ -3507,12 +3511,12 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3507
3511
  if (scanAll) {
3508
3512
  const metas = ctx.sessions.listSessions();
3509
3513
  console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
3510
- const { readFileSync: readFileSync4 } = await import("fs");
3511
- const { join: join5 } = await import("path");
3514
+ const { readFileSync: readFileSync5 } = await import("fs");
3515
+ const { join: join6 } = await import("path");
3512
3516
  const historyDir = ctx.config.getHistoryDir();
3513
3517
  for (const m of metas) {
3514
3518
  try {
3515
- const content = readFileSync4(join5(historyDir, `${m.id}.json`), "utf-8");
3519
+ const content = readFileSync5(join6(historyDir, `${m.id}.json`), "utf-8");
3516
3520
  const hits2 = scanString(content, opts);
3517
3521
  if (hits2.length) {
3518
3522
  filesWithHits++;
@@ -3567,7 +3571,7 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3567
3571
  console.log(theme.info(" \u{1F512} Auto-approve disabled \u2014 confirmations restored for this session."));
3568
3572
  } else {
3569
3573
  executor.sessionAutoApprove = true;
3570
- console.log(theme.warning(" \u26A1 YOLO mode ON \u2014 all write/destructive tools auto-approved for this session."));
3574
+ console.log(theme.warning(" \u26A1 YOLO mode ON \u2014 write tools auto-approved; destructive tools still require confirmation."));
3571
3575
  console.log(theme.dim(" Use /yolo off to re-enable confirmations."));
3572
3576
  }
3573
3577
  console.log();
@@ -4047,11 +4051,11 @@ Managing ${displayName} API Key`);
4047
4051
  console.log(" alwaysYolo: " + (current ? theme.warning("ON") : theme.dim("off")));
4048
4052
  console.log(
4049
4053
  theme.dim(
4050
- " When ON, REPL starts with sessionAutoApprove enabled \u2014 all write/destructive\n tools (edit_file, bash, etc.) run without confirmation prompts. Only enable this\n if you fully trust the working directory you run aicli in.\n"
4054
+ " When ON, REPL starts with sessionAutoApprove enabled \u2014 write\n tools (write_file/edit_file, etc.) run without confirmation prompts. Destructive tools still require confirmation. Only enable this\n if you fully trust the working directory you run aicli in.\n"
4051
4055
  )
4052
4056
  );
4053
4057
  const next = await confirm({
4054
- message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip ALL write/destructive confirmations)?",
4058
+ message: current ? "Keep alwaysYolo enabled?" : "Enable alwaysYolo (skip write confirmations; destructive still confirms)?",
4055
4059
  default: current
4056
4060
  });
4057
4061
  if (next === current) {
@@ -4197,13 +4201,13 @@ Managing ${displayName} API Key`);
4197
4201
  };
4198
4202
 
4199
4203
  // src/repl/custom-commands.ts
4200
- import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync as readdirSync2, mkdirSync as mkdirSync3 } from "fs";
4201
- import { join as join3, extname } from "path";
4204
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, mkdirSync as mkdirSync3 } from "fs";
4205
+ import { join as join4, extname } from "path";
4202
4206
  import { execSync as execSync3 } from "child_process";
4203
4207
  function parseCommandFile(filePath) {
4204
4208
  let content;
4205
4209
  try {
4206
- content = readFileSync2(filePath, "utf-8");
4210
+ content = readFileSync3(filePath, "utf-8");
4207
4211
  } catch {
4208
4212
  return null;
4209
4213
  }
@@ -4227,7 +4231,7 @@ function expandTemplate(template, args) {
4227
4231
  result = result.replace(/\{\{input\}\}/g, args.join(" "));
4228
4232
  result = result.replace(/\{\{file:([^}]+)\}\}/g, (_m, p) => {
4229
4233
  try {
4230
- return readFileSync2(p.trim(), "utf-8");
4234
+ return readFileSync3(p.trim(), "utf-8");
4231
4235
  } catch {
4232
4236
  return `[Error: cannot read ${p.trim()}]`;
4233
4237
  }
@@ -4252,14 +4256,14 @@ var CustomCommandManager = class {
4252
4256
  commands = /* @__PURE__ */ new Map();
4253
4257
  loadCommands() {
4254
4258
  this.commands.clear();
4255
- if (!existsSync3(this.commandsDir)) {
4259
+ if (!existsSync4(this.commandsDir)) {
4256
4260
  mkdirSync3(this.commandsDir, { recursive: true });
4257
4261
  return 0;
4258
4262
  }
4259
4263
  let count = 0;
4260
4264
  for (const file of readdirSync2(this.commandsDir)) {
4261
4265
  if (extname(file) !== ".md") continue;
4262
- const cmd = parseCommandFile(join3(this.commandsDir, file));
4266
+ const cmd = parseCommandFile(join4(this.commandsDir, file));
4263
4267
  if (cmd) {
4264
4268
  this.commands.set(cmd.meta.name, cmd);
4265
4269
  count++;
@@ -4564,17 +4568,17 @@ function parseAtReferences(input2, cwd) {
4564
4568
  const absPath = resolve2(cwd, rawPath);
4565
4569
  const ext = extname2(rawPath).toLowerCase();
4566
4570
  const mime = IMAGE_MIME[ext];
4567
- if (!existsSync4(absPath)) {
4571
+ if (!existsSync5(absPath)) {
4568
4572
  refs.push({ path: rawPath, type: "notfound" });
4569
4573
  continue;
4570
4574
  }
4571
4575
  if (mime) {
4572
- const fileSize = statSync3(absPath).size;
4576
+ const fileSize = statSync4(absPath).size;
4573
4577
  if (fileSize > MAX_IMAGE_BYTES) {
4574
4578
  refs.push({ path: rawPath, type: "toolarge" });
4575
4579
  continue;
4576
4580
  }
4577
- const data = readFileSync3(absPath).toString("base64");
4581
+ const data = readFileSync4(absPath).toString("base64");
4578
4582
  imageParts.push({
4579
4583
  type: "image_url",
4580
4584
  image_url: { url: `data:${mime};base64,${data}` }
@@ -4582,7 +4586,7 @@ function parseAtReferences(input2, cwd) {
4582
4586
  refs.push({ path: rawPath, type: "image" });
4583
4587
  textBody = textBody.replace(match[0], "").trim();
4584
4588
  } else {
4585
- const content = readFileSync3(absPath, "utf-8");
4589
+ const content = readFileSync4(absPath, "utf-8");
4586
4590
  const inlined = `
4587
4591
 
4588
4592
  [File: ${rawPath}]
@@ -4807,12 +4811,12 @@ var Repl = class {
4807
4811
  const filtered = entries.filter((e) => !SKIP_DIRS_SET.has(e));
4808
4812
  for (let i = 0; i < filtered.length && entryCount < MAX_TREE_ENTRIES; i++) {
4809
4813
  const name = filtered[i];
4810
- const fullPath = join4(dir, name);
4814
+ const fullPath = join5(dir, name);
4811
4815
  const isLast = i === filtered.length - 1;
4812
4816
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4813
4817
  let isDir;
4814
4818
  try {
4815
- isDir = statSync3(fullPath).isDirectory();
4819
+ isDir = statSync4(fullPath).isDirectory();
4816
4820
  } catch {
4817
4821
  continue;
4818
4822
  }
@@ -4841,10 +4845,10 @@ ${treeLines.join("\n")}`
4841
4845
  for (const name of entries) {
4842
4846
  if (totalChars >= MAX_TOTAL_CHARS) break;
4843
4847
  if (SKIP_DIRS_SET.has(name)) continue;
4844
- const fullPath = join4(dir, name);
4848
+ const fullPath = join5(dir, name);
4845
4849
  let st;
4846
4850
  try {
4847
- st = statSync3(fullPath);
4851
+ st = statSync4(fullPath);
4848
4852
  } catch {
4849
4853
  continue;
4850
4854
  }
@@ -4856,7 +4860,7 @@ ${treeLines.join("\n")}`
4856
4860
  if (!TEXT_EXTS.has(ext) && !isSpecial) continue;
4857
4861
  if (st.size > MAX_FILE_CHARS * 3) continue;
4858
4862
  try {
4859
- let content = readFileSync3(fullPath, "utf-8");
4863
+ let content = readFileSync4(fullPath, "utf-8");
4860
4864
  if (content.length > MAX_FILE_CHARS) {
4861
4865
  content = content.slice(0, MAX_FILE_CHARS) + `
4862
4866
  ... (truncated, ${content.length} chars total)`;
@@ -4886,12 +4890,12 @@ ${content}
4886
4890
  */
4887
4891
  addExtraContextDir(dirPath) {
4888
4892
  const absPath = resolve2(dirPath);
4889
- if (!existsSync4(absPath)) {
4893
+ if (!existsSync5(absPath)) {
4890
4894
  return { success: false, charCount: 0, added: false, error: `Directory not found: ${dirPath}` };
4891
4895
  }
4892
4896
  let isDir;
4893
4897
  try {
4894
- isDir = statSync3(absPath).isDirectory();
4898
+ isDir = statSync4(absPath).isDirectory();
4895
4899
  } catch {
4896
4900
  return { success: false, charCount: 0, added: false, error: `Cannot access: ${dirPath}` };
4897
4901
  }
@@ -4920,9 +4924,9 @@ ${content}
4920
4924
  */
4921
4925
  findContextFile(dir, candidates = CONTEXT_FILE_CANDIDATES) {
4922
4926
  for (const candidate of candidates) {
4923
- const fullPath = join4(dir, candidate);
4924
- if (existsSync4(fullPath)) {
4925
- const content = readFileSync3(fullPath, "utf-8").trim();
4927
+ const fullPath = join5(dir, candidate);
4928
+ if (existsSync5(fullPath)) {
4929
+ const content = readFileSync4(fullPath, "utf-8").trim();
4926
4930
  if (content) return { filePath: fullPath, content };
4927
4931
  }
4928
4932
  }
@@ -4950,10 +4954,10 @@ ${content}
4950
4954
  const cwd = process.cwd();
4951
4955
  const gitRoot = getGitRoot(cwd);
4952
4956
  const projectRoot = gitRoot ?? cwd;
4953
- const mcpPath = join4(projectRoot, MCP_PROJECT_CONFIG_NAME);
4954
- if (!existsSync4(mcpPath)) return null;
4957
+ const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME);
4958
+ if (!existsSync5(mcpPath)) return null;
4955
4959
  try {
4956
- const raw = JSON.parse(readFileSync3(mcpPath, "utf-8"));
4960
+ const raw = JSON.parse(readFileSync4(mcpPath, "utf-8"));
4957
4961
  const servers = raw?.mcpServers;
4958
4962
  if (!servers || typeof servers !== "object") {
4959
4963
  process.stderr.write(
@@ -4999,8 +5003,8 @@ ${content}
4999
5003
  );
5000
5004
  return { layers: [], mergedContent: "" };
5001
5005
  }
5002
- if (existsSync4(fullPath)) {
5003
- const content = readFileSync3(fullPath, "utf-8").trim();
5006
+ if (existsSync5(fullPath)) {
5007
+ const content = readFileSync4(fullPath, "utf-8").trim();
5004
5008
  if (content) {
5005
5009
  const layer = {
5006
5010
  level: "project",
@@ -5057,9 +5061,9 @@ ${content}
5057
5061
  * 超过 MEMORY_MAX_CHARS 时只取末尾最新部分。
5058
5062
  */
5059
5063
  loadMemoryContent() {
5060
- const memoryPath = join4(this.config.getConfigDir(), MEMORY_FILE_NAME);
5061
- if (!existsSync4(memoryPath)) return null;
5062
- let content = readFileSync3(memoryPath, "utf-8").trim();
5064
+ const memoryPath = join5(this.config.getConfigDir(), MEMORY_FILE_NAME);
5065
+ if (!existsSync5(memoryPath)) return null;
5066
+ let content = readFileSync4(memoryPath, "utf-8").trim();
5063
5067
  if (!content) return null;
5064
5068
  if (content.length > MEMORY_MAX_CHARS) {
5065
5069
  content = content.slice(-MEMORY_MAX_CHARS);
@@ -5391,7 +5395,7 @@ Session '${this.resumeSessionId}' not found.
5391
5395
  this.renderer.printWelcome(this.currentProvider, this.currentModel, welcomeModelInfo?.contextWindow, profileNickname);
5392
5396
  if (this.toolExecutor.sessionAutoApprove && this.config.get("alwaysYolo") === true) {
5393
5397
  process.stdout.write(
5394
- theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 all write/destructive tools auto-approved.\n")
5398
+ theme.warning(" \u26A1 YOLO mode ON (alwaysYolo=true in config) \u2014 write tools auto-approved; destructive tools still require confirmation.\n")
5395
5399
  );
5396
5400
  }
5397
5401
  const cfgOutputCap = this.config.get("maxToolOutputChars");
@@ -5447,14 +5451,14 @@ Session '${this.resumeSessionId}' not found.
5447
5451
  process.stdout.write(theme.dim(` \u{1F50C} Plugins loaded: ${pluginCount} tool(s) from plugins/
5448
5452
  `));
5449
5453
  }
5450
- const skillsDir = join4(this.config.getConfigDir(), SKILLS_DIR_NAME);
5454
+ const skillsDir = join5(this.config.getConfigDir(), SKILLS_DIR_NAME);
5451
5455
  this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
5452
5456
  const skillCount = this.skillManager.loadSkills();
5453
5457
  if (skillCount > 0) {
5454
5458
  process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
5455
5459
  `));
5456
5460
  }
5457
- const commandsDir = join4(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
5461
+ const commandsDir = join5(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
5458
5462
  this.customCommandManager = new CustomCommandManager(commandsDir);
5459
5463
  const customCmdCount = this.customCommandManager.loadCommands();
5460
5464
  if (customCmdCount > 0) {
@@ -6090,15 +6094,15 @@ Session '${this.resumeSessionId}' not found.
6090
6094
  const dir = normalized.includes("/") ? dirname3(normalized) : ".";
6091
6095
  const prefix = normalized.includes("/") ? basename2(normalized) : normalized;
6092
6096
  const absDir = resolve2(process.cwd(), dir);
6093
- if (!existsSync4(absDir)) return [];
6097
+ if (!existsSync5(absDir)) return [];
6094
6098
  const entries = readdirSync3(absDir);
6095
6099
  const results = [];
6096
6100
  for (const entry of entries) {
6097
6101
  if (entry.startsWith(".")) continue;
6098
6102
  if (!entry.toLowerCase().startsWith(prefix.toLowerCase())) continue;
6099
6103
  try {
6100
- const fullPath = join4(absDir, entry);
6101
- const stat = statSync3(fullPath);
6104
+ const fullPath = join5(absDir, entry);
6105
+ const stat = statSync4(fullPath);
6102
6106
  const rel = dir === "." ? entry : `${dir}/${entry}`;
6103
6107
  results.push(stat.isDirectory() ? `${rel}/` : rel);
6104
6108
  } catch {
@@ -6642,7 +6646,7 @@ ${decision.displayMessage}
6642
6646
  try {
6643
6647
  mkdirSync4(dirname3(pendingTeeSave), { recursive: true });
6644
6648
  const bodyToSave = stripOuterCodeFence(content);
6645
- writeFileSync2(pendingTeeSave, bodyToSave, "utf-8");
6649
+ atomicWriteFileSync(pendingTeeSave, bodyToSave);
6646
6650
  undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
6647
6651
  const lines = bodyToSave.split("\n").length;
6648
6652
  process.stdout.write(theme.success(
@@ -6911,7 +6915,7 @@ Tip: You can continue the conversation by asking the AI to proceed.`
6911
6915
  }
6912
6916
  if (verdict.kind === "salvaged" || verdict.kind === "fallback") {
6913
6917
  try {
6914
- writeFileSync2(saveToFile, verdict.content, "utf-8");
6918
+ atomicWriteFileSync(saveToFile, verdict.content);
6915
6919
  const banner = verdict.kind === "fallback" ? `
6916
6920
  \u26A0 Fallback save: fresh stream had no usable body (matched: ${verdict.matched})
6917
6921
  ${saveToFile} now holds the response you previously saw (${verdict.content.length} chars).
@@ -7267,7 +7271,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7267
7271
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7268
7272
  process.exit(1);
7269
7273
  }
7270
- const { startWebServer } = await import("./server-ML6ZL3J5.js");
7274
+ const { startWebServer } = await import("./server-L2MXWYF7.js");
7271
7275
  await startWebServer({ port, host: options.host });
7272
7276
  });
7273
7277
  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) => {
@@ -7434,16 +7438,16 @@ program.command("sessions").description("List recent conversation sessions").opt
7434
7438
  console.log(footer + "\n");
7435
7439
  });
7436
7440
  program.command("usage").description("Show token + cost usage grouped by provider/model (cross-session)").option("--days <n>", "Only the last N days (inclusive of today)").option("--month <ym>", "Only a specific month, format YYYY-MM (e.g. 2026-06)").option("--json", "Output as JSON (for scripting)").action(async (options) => {
7437
- const { runUsageCli } = await import("./usage-YX2235W5.js");
7441
+ const { runUsageCli } = await import("./usage-SZWZFX3T.js");
7438
7442
  await runUsageCli(options);
7439
7443
  });
7440
7444
  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) => {
7441
- const { runDoctorCli } = await import("./doctor-cli-M5PPO3L3.js");
7445
+ const { runDoctorCli } = await import("./doctor-cli-WKH7T4AW.js");
7442
7446
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7443
7447
  });
7444
7448
  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) => {
7445
7449
  try {
7446
- const batch = await import("./batch-RBPABHS7.js");
7450
+ const batch = await import("./batch-6PORMJWT.js");
7447
7451
  switch (action) {
7448
7452
  case "submit":
7449
7453
  if (!arg) {
@@ -7486,7 +7490,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7486
7490
  }
7487
7491
  });
7488
7492
  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) => {
7489
- const { startMcpServer } = await import("./server-RKP7JRRE.js");
7493
+ const { startMcpServer } = await import("./server-37EXC4EB.js");
7490
7494
  await startMcpServer({
7491
7495
  allowDestructive: !!options.allowDestructive,
7492
7496
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7495,7 +7499,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
7495
7499
  });
7496
7500
  });
7497
7501
  program.command("ci").description("Headless PR review (code + security) \u2014 reads git/gh diff, optionally posts to PR. Designed for GitHub Actions.").option("--pr <num>", "PR number; diff fetched via `gh pr diff <num>`", (v) => parseInt(v, 10)).option("--base <ref>", "Base ref for `git diff <ref>...HEAD` (ignored when --pr set)").option("--post", "Post review as a PR comment (requires gh CLI + GH_TOKEN, needs --pr)").option("--no-update", "Always create a new comment instead of updating the previous aicli review").option("--skip-code", "Skip the code review section").option("--skip-security", "Skip the security review section").option("--detailed", "Use the detailed code-review prompt").option("--max-diff <n>", "Max diff chars sent to the model (default 30000)", (v) => parseInt(v, 10)).option("--provider <id>", "Override provider (default: config.defaultProvider)").option("--model <id>", "Override model").option("--dry-run", "Print result to stdout instead of posting (overrides --post)").action(async (options) => {
7498
- const { runCi } = await import("./ci-ABE74AXH.js");
7502
+ const { runCi } = await import("./ci-AYMV66P3.js");
7499
7503
  const result = await runCi({
7500
7504
  pr: options.pr,
7501
7505
  base: options.base,
@@ -7593,7 +7597,7 @@ program.command("help").description("Show a comprehensive guide to all aicli fea
7593
7597
  ` ${M}/checkpoint${R} ${M}/fork${R} Save/restore/fork session state`,
7594
7598
  ` ${M}/branch${R} List/create/switch/delete conversation branches (B2)`,
7595
7599
  ` ${M}/undo${R} Undo file operations`,
7596
- ` ${M}/yolo${R} Skip all tool confirmations`,
7600
+ ` ${M}/yolo${R} Skip write confirmations`,
7597
7601
  ` ${M}/mcp${R} Manage MCP server connections`,
7598
7602
  ` ${M}/skill${R} Manage agent skills`,
7599
7603
  ` ${M}/memory${R} View/edit persistent memory`,
@@ -7641,7 +7645,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7641
7645
  }),
7642
7646
  config.get("customProviders")
7643
7647
  );
7644
- const { startHub } = await import("./hub-NCU5JNCK.js");
7648
+ const { startHub } = await import("./hub-6R3M3NTC.js");
7645
7649
  await startHub(
7646
7650
  {
7647
7651
  topic: topic ?? "",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-VOV2PWZU.js";
6
- import "./chunk-3RET7PL7.js";
5
+ } from "./chunk-SFCNFX42.js";
6
+ import "./chunk-QNUVZO5X.js";
7
7
  export {
8
8
  executeTests,
9
9
  runTestsTool
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  executeTests,
3
3
  runTestsTool
4
- } from "./chunk-43H3D2PK.js";
4
+ } from "./chunk-BQIV4ZQT.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool