jinzd-ai-cli 0.4.206 → 0.4.208

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 (27) hide show
  1. package/dist/{batch-6PORMJWT.js → batch-3T44NFLG.js} +2 -2
  2. package/dist/{chunk-QQYSZMET.js → chunk-2OVMMSGQ.js} +3 -3
  3. package/dist/{chunk-2WV6AGHM.js → chunk-J22B3OSQ.js} +1 -1
  4. package/dist/{chunk-QNUVZO5X.js → chunk-KV4GYNEA.js} +1 -1
  5. package/dist/{chunk-KJHMRAJU.js → chunk-P7JY3SWA.js} +1 -1
  6. package/dist/{chunk-BQIV4ZQT.js → chunk-QDY72ABW.js} +1 -1
  7. package/dist/{chunk-KOU4KX7J.js → chunk-TD7JEHCR.js} +2 -2
  8. package/dist/{chunk-TW47X5AO.js → chunk-TM4MS63K.js} +1 -1
  9. package/dist/{chunk-SFCNFX42.js → chunk-VWYUB22Y.js} +1 -1
  10. package/dist/{ci-AYMV66P3.js → ci-6QWBVRJX.js} +2 -2
  11. package/dist/{constants-NHGTSHKT.js → constants-SZTQNN7K.js} +1 -1
  12. package/dist/{doctor-cli-WKH7T4AW.js → doctor-cli-I2Y2YR4V.js} +4 -4
  13. package/dist/electron-server.js +5 -8
  14. package/dist/{hub-6R3M3NTC.js → hub-XVPFBODB.js} +1 -1
  15. package/dist/index.js +90 -88
  16. package/dist/{run-tests-5F2OBWIK.js → run-tests-D5SNUBYX.js} +2 -2
  17. package/dist/{run-tests-NBCA4KEG.js → run-tests-HZ2CRCTZ.js} +1 -1
  18. package/dist/{server-LDPQ3DLK.js → server-4EFTRFTN.js} +10 -13
  19. package/dist/{server-37EXC4EB.js → server-PVKLPRUP.js} +4 -4
  20. package/dist/{task-orchestrator-2DTDVCMR.js → task-orchestrator-2A5VCFLS.js} +4 -4
  21. package/dist/{usage-SZWZFX3T.js → usage-Q24E5636.js} +2 -2
  22. package/dist/web/client/actions.js +84 -0
  23. package/dist/web/client/app.js +20 -202
  24. package/dist/web/client/index.html +26 -41
  25. package/dist/web/client/sw.js +1 -1
  26. package/dist/web/client/templates.js +188 -0
  27. 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-KOU4KX7J.js";
18
+ } from "./chunk-TD7JEHCR.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-QQYSZMET.js";
38
+ } from "./chunk-2OVMMSGQ.js";
39
39
  import "./chunk-T2NL5ZIA.js";
40
40
  import "./chunk-BXP6YZ2P.js";
41
- import "./chunk-SFCNFX42.js";
41
+ import "./chunk-VWYUB22Y.js";
42
42
  import {
43
43
  SessionManager,
44
44
  getContentText
@@ -55,7 +55,7 @@ import {
55
55
  getConfigDirUsage,
56
56
  listRecentCrashes,
57
57
  writeCrashLog
58
- } from "./chunk-KJHMRAJU.js";
58
+ } from "./chunk-P7JY3SWA.js";
59
59
  import {
60
60
  ProviderRegistry
61
61
  } from "./chunk-QMXC327F.js";
@@ -64,7 +64,7 @@ import {
64
64
  getTopFailingTools,
65
65
  getTopUsedTools,
66
66
  installFlushOnExit
67
- } from "./chunk-2WV6AGHM.js";
67
+ } from "./chunk-J22B3OSQ.js";
68
68
  import {
69
69
  CONTENT_ONLY_STREAM_REMINDER,
70
70
  TEE_FINAL_USER_NUDGE,
@@ -86,7 +86,7 @@ import {
86
86
  } from "./chunk-XPBEJB27.js";
87
87
  import {
88
88
  ConfigManager
89
- } from "./chunk-TW47X5AO.js";
89
+ } from "./chunk-TM4MS63K.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-QNUVZO5X.js";
116
+ } from "./chunk-KV4GYNEA.js";
117
117
  import {
118
118
  formatGitContextForPrompt,
119
119
  getGitContext,
@@ -144,8 +144,8 @@ import { program } from "commander";
144
144
 
145
145
  // src/repl/repl.ts
146
146
  import * as readline from "readline";
147
- import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3, mkdirSync as mkdirSync4 } from "fs";
148
- 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";
149
149
  import chalk4 from "chalk";
150
150
 
151
151
  // src/session/title-generator.ts
@@ -637,10 +637,10 @@ Error${typeName}: ${lines.join("\n")}
637
637
  };
638
638
 
639
639
  // src/repl/commands/index.ts
640
- 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";
641
641
  import { execSync as execSync2 } from "child_process";
642
642
  import { platform } from "os";
643
- import { resolve, dirname as dirname2, join as join2, basename } from "path";
643
+ import { resolve, dirname as dirname2, join as join3, basename } from "path";
644
644
  import chalk2 from "chalk";
645
645
 
646
646
  // src/repl/clipboard.ts
@@ -730,12 +730,9 @@ function getClipboardHint() {
730
730
  return "";
731
731
  }
732
732
 
733
- // src/repl/commands/index.ts
734
- function fmtCtx(tokens) {
735
- if (tokens >= 1e6) return `${Math.round(tokens / 1e5) / 10}M`;
736
- if (tokens >= 1e3) return `${Math.round(tokens / 1024)}K`;
737
- return `${tokens}`;
738
- }
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";
739
736
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
740
737
  "node_modules",
741
738
  ".git",
@@ -793,7 +790,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
793
790
  const name = sorted[i];
794
791
  const fullPath = join2(d, name);
795
792
  const isLast = i === sorted.length - 1;
796
- const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
793
+ const connector = isLast ? "+-- " : "|-- ";
797
794
  let isDir;
798
795
  try {
799
796
  isDir = statSync2(fullPath).isDirectory();
@@ -803,7 +800,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
803
800
  lines.push(prefix + connector + name + (isDir ? "/" : ""));
804
801
  count++;
805
802
  if (isDir) {
806
- walk(fullPath, prefix + (isLast ? " " : "\u2502 "), depth + 1);
803
+ walk(fullPath, prefix + (isLast ? " " : "| "), depth + 1);
807
804
  }
808
805
  }
809
806
  };
@@ -847,9 +844,9 @@ function scanProject(cwd) {
847
844
  try {
848
845
  const pkg = JSON.parse(readFileSync(join2(cwd, "package.json"), "utf-8"));
849
846
  const scripts = pkg.scripts ?? {};
850
- info.buildCommand = scripts.build ? `npm run build` : void 0;
851
- info.testCommand = scripts.test ? `npm test` : void 0;
852
- 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;
853
850
  const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
854
851
  if (allDeps["react"]) info.framework = "React";
855
852
  else if (allDeps["vue"]) info.framework = "Vue";
@@ -891,10 +888,8 @@ function scanProject(cwd) {
891
888
  }
892
889
  function buildInitPrompt(info, cwd) {
893
890
  const parts = [
894
- `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.`,
895
- `
896
- ## Project Info
897
- `,
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",
898
893
  `- Working directory: ${cwd}`,
899
894
  `- Type: ${info.type}`,
900
895
  `- Language: ${info.language}`
@@ -923,6 +918,13 @@ Please generate a structured Markdown file containing:
923
918
  Output the Markdown content directly, do not wrap the entire file in a code block. Keep it concise, within 200 lines.`);
924
919
  return parts.join("\n");
925
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
+ }
926
928
  function copyToClipboard(text) {
927
929
  const plat = platform();
928
930
  if (plat === "win32") {
@@ -1827,16 +1829,16 @@ No tools match "${filter}".
1827
1829
  usage: "/mcp [reconnect [serverId] | trust-project]",
1828
1830
  async execute(args, ctx) {
1829
1831
  if (args[0] === "trust-project") {
1830
- const { join: join5 } = await import("path");
1831
- const { existsSync: existsSync5 } = await import("fs");
1832
+ const { join: join6 } = await import("path");
1833
+ const { existsSync: existsSync6 } = await import("fs");
1832
1834
  const { getGitRoot: getGitRoot2 } = await import("./git-context-EXOEHQSF.js");
1833
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-NHGTSHKT.js");
1835
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-SZTQNN7K.js");
1834
1836
  const { approveProject, hashMcpFile } = await import("./project-trust-NKYHL3VZ.js");
1835
1837
  const cwd = process.cwd();
1836
1838
  const projectRoot = getGitRoot2(cwd) ?? cwd;
1837
- const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME2);
1839
+ const mcpPath = join6(projectRoot, MCP_PROJECT_CONFIG_NAME2);
1838
1840
  console.log();
1839
- if (!existsSync5(mcpPath)) {
1841
+ if (!existsSync6(mcpPath)) {
1840
1842
  console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
1841
1843
  console.log();
1842
1844
  return;
@@ -2169,9 +2171,9 @@ No tools match "${filter}".
2169
2171
  usage: "/init [--force]",
2170
2172
  async execute(args, ctx) {
2171
2173
  const cwd = process.cwd();
2172
- const targetPath = join2(cwd, "AICLI.md");
2174
+ const targetPath = join3(cwd, "AICLI.md");
2173
2175
  const force = args.includes("--force");
2174
- if (existsSync2(targetPath) && !force) {
2176
+ if (existsSync3(targetPath) && !force) {
2175
2177
  ctx.renderer.printInfo(`AICLI.md already exists at ${targetPath}`);
2176
2178
  ctx.renderer.printInfo("Use /init --force to overwrite, or edit it manually.");
2177
2179
  return;
@@ -2891,7 +2893,7 @@ ${hint}` : "")
2891
2893
  usage: "/test [command|filter]",
2892
2894
  async execute(args, ctx) {
2893
2895
  try {
2894
- const { executeTests } = await import("./run-tests-5F2OBWIK.js");
2896
+ const { executeTests } = await import("./run-tests-D5SNUBYX.js");
2895
2897
  const argStr = args.join(" ").trim();
2896
2898
  let testArgs = {};
2897
2899
  if (argStr) {
@@ -3049,7 +3051,7 @@ ${hint}` : "")
3049
3051
  description: "Persistent memory (memory.md) + chat memory recall index (v0.4.89+)",
3050
3052
  usage: "/memory [show|add <text>|clear|path|rebuild|refresh|status|recall <query>|index-clear]",
3051
3053
  async execute(args, ctx) {
3052
- const memoryFile = join2(ctx.config.getConfigDir(), MEMORY_FILE_NAME);
3054
+ const memoryFile = join3(ctx.config.getConfigDir(), MEMORY_FILE_NAME);
3053
3055
  const sub = args[0] ?? "show";
3054
3056
  if (sub === "rebuild" || sub === "refresh") {
3055
3057
  const full = sub === "rebuild";
@@ -3133,11 +3135,11 @@ ${hint}` : "")
3133
3135
  return;
3134
3136
  }
3135
3137
  if (sub === "show" || sub === "view") {
3136
- if (!existsSync2(memoryFile)) {
3138
+ if (!existsSync3(memoryFile)) {
3137
3139
  ctx.renderer.printInfo("Memory is empty (memory.md not found)");
3138
3140
  return;
3139
3141
  }
3140
- const content = readFileSync(memoryFile, "utf-8").trim();
3142
+ const content = readFileSync2(memoryFile, "utf-8").trim();
3141
3143
  if (!content) {
3142
3144
  ctx.renderer.printInfo("Memory is empty");
3143
3145
  return;
@@ -3168,7 +3170,7 @@ ${text}
3168
3170
  ctx.renderer.renderError(`Failed to write memory: ${err instanceof Error ? err.message : String(err)}`);
3169
3171
  }
3170
3172
  } else if (sub === "clear") {
3171
- if (!existsSync2(memoryFile)) {
3173
+ if (!existsSync3(memoryFile)) {
3172
3174
  ctx.renderer.printInfo("Memory is already empty");
3173
3175
  return;
3174
3176
  }
@@ -3204,20 +3206,20 @@ ${text}
3204
3206
  console.log(theme.heading("Config Files:"));
3205
3207
  console.log(` Dir: ${theme.accent(configDir)}`);
3206
3208
  const checkFile = (label, filePath) => {
3207
- const exists = existsSync2(filePath);
3209
+ const exists = existsSync3(filePath);
3208
3210
  const icon = exists ? theme.success("\u2713") : theme.dim("\u2013");
3209
3211
  let extra = "";
3210
3212
  if (exists) {
3211
3213
  try {
3212
- extra = theme.dim(` (${statSync2(filePath).size} bytes)`);
3214
+ extra = theme.dim(` (${statSync3(filePath).size} bytes)`);
3213
3215
  } catch {
3214
3216
  }
3215
3217
  }
3216
3218
  console.log(` ${icon} ${label.padEnd(14)} ${exists ? filePath : theme.dim("(not found)")}${extra}`);
3217
3219
  };
3218
- checkFile("config.json", join2(configDir, "config.json"));
3219
- checkFile("memory.md", join2(configDir, MEMORY_FILE_NAME));
3220
- 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"));
3221
3223
  console.log();
3222
3224
  const mcpManager = ctx.getMcpManager();
3223
3225
  if (mcpManager) {
@@ -3381,9 +3383,9 @@ ${text}
3381
3383
  let newFiles = 0;
3382
3384
  let modifiedFiles = 0;
3383
3385
  for (const [filePath, { earliest }] of fileMap) {
3384
- const currentContent = existsSync2(filePath) ? (() => {
3386
+ const currentContent = existsSync3(filePath) ? (() => {
3385
3387
  try {
3386
- return readFileSync(filePath, "utf-8");
3388
+ return readFileSync2(filePath, "utf-8");
3387
3389
  } catch {
3388
3390
  return null;
3389
3391
  }
@@ -3509,12 +3511,12 @@ Summary: ${fileMap.size} file(s) \u2014 ${newFiles} new, ${modifiedFiles} modifi
3509
3511
  if (scanAll) {
3510
3512
  const metas = ctx.sessions.listSessions();
3511
3513
  console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
3512
- const { readFileSync: readFileSync4 } = await import("fs");
3513
- const { join: join5 } = await import("path");
3514
+ const { readFileSync: readFileSync5 } = await import("fs");
3515
+ const { join: join6 } = await import("path");
3514
3516
  const historyDir = ctx.config.getHistoryDir();
3515
3517
  for (const m of metas) {
3516
3518
  try {
3517
- const content = readFileSync4(join5(historyDir, `${m.id}.json`), "utf-8");
3519
+ const content = readFileSync5(join6(historyDir, `${m.id}.json`), "utf-8");
3518
3520
  const hits2 = scanString(content, opts);
3519
3521
  if (hits2.length) {
3520
3522
  filesWithHits++;
@@ -4199,13 +4201,13 @@ Managing ${displayName} API Key`);
4199
4201
  };
4200
4202
 
4201
4203
  // src/repl/custom-commands.ts
4202
- import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync as readdirSync2, mkdirSync as mkdirSync3 } from "fs";
4203
- 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";
4204
4206
  import { execSync as execSync3 } from "child_process";
4205
4207
  function parseCommandFile(filePath) {
4206
4208
  let content;
4207
4209
  try {
4208
- content = readFileSync2(filePath, "utf-8");
4210
+ content = readFileSync3(filePath, "utf-8");
4209
4211
  } catch {
4210
4212
  return null;
4211
4213
  }
@@ -4229,7 +4231,7 @@ function expandTemplate(template, args) {
4229
4231
  result = result.replace(/\{\{input\}\}/g, args.join(" "));
4230
4232
  result = result.replace(/\{\{file:([^}]+)\}\}/g, (_m, p) => {
4231
4233
  try {
4232
- return readFileSync2(p.trim(), "utf-8");
4234
+ return readFileSync3(p.trim(), "utf-8");
4233
4235
  } catch {
4234
4236
  return `[Error: cannot read ${p.trim()}]`;
4235
4237
  }
@@ -4254,14 +4256,14 @@ var CustomCommandManager = class {
4254
4256
  commands = /* @__PURE__ */ new Map();
4255
4257
  loadCommands() {
4256
4258
  this.commands.clear();
4257
- if (!existsSync3(this.commandsDir)) {
4259
+ if (!existsSync4(this.commandsDir)) {
4258
4260
  mkdirSync3(this.commandsDir, { recursive: true });
4259
4261
  return 0;
4260
4262
  }
4261
4263
  let count = 0;
4262
4264
  for (const file of readdirSync2(this.commandsDir)) {
4263
4265
  if (extname(file) !== ".md") continue;
4264
- const cmd = parseCommandFile(join3(this.commandsDir, file));
4266
+ const cmd = parseCommandFile(join4(this.commandsDir, file));
4265
4267
  if (cmd) {
4266
4268
  this.commands.set(cmd.meta.name, cmd);
4267
4269
  count++;
@@ -4566,17 +4568,17 @@ function parseAtReferences(input2, cwd) {
4566
4568
  const absPath = resolve2(cwd, rawPath);
4567
4569
  const ext = extname2(rawPath).toLowerCase();
4568
4570
  const mime = IMAGE_MIME[ext];
4569
- if (!existsSync4(absPath)) {
4571
+ if (!existsSync5(absPath)) {
4570
4572
  refs.push({ path: rawPath, type: "notfound" });
4571
4573
  continue;
4572
4574
  }
4573
4575
  if (mime) {
4574
- const fileSize = statSync3(absPath).size;
4576
+ const fileSize = statSync4(absPath).size;
4575
4577
  if (fileSize > MAX_IMAGE_BYTES) {
4576
4578
  refs.push({ path: rawPath, type: "toolarge" });
4577
4579
  continue;
4578
4580
  }
4579
- const data = readFileSync3(absPath).toString("base64");
4581
+ const data = readFileSync4(absPath).toString("base64");
4580
4582
  imageParts.push({
4581
4583
  type: "image_url",
4582
4584
  image_url: { url: `data:${mime};base64,${data}` }
@@ -4584,7 +4586,7 @@ function parseAtReferences(input2, cwd) {
4584
4586
  refs.push({ path: rawPath, type: "image" });
4585
4587
  textBody = textBody.replace(match[0], "").trim();
4586
4588
  } else {
4587
- const content = readFileSync3(absPath, "utf-8");
4589
+ const content = readFileSync4(absPath, "utf-8");
4588
4590
  const inlined = `
4589
4591
 
4590
4592
  [File: ${rawPath}]
@@ -4809,12 +4811,12 @@ var Repl = class {
4809
4811
  const filtered = entries.filter((e) => !SKIP_DIRS_SET.has(e));
4810
4812
  for (let i = 0; i < filtered.length && entryCount < MAX_TREE_ENTRIES; i++) {
4811
4813
  const name = filtered[i];
4812
- const fullPath = join4(dir, name);
4814
+ const fullPath = join5(dir, name);
4813
4815
  const isLast = i === filtered.length - 1;
4814
4816
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4815
4817
  let isDir;
4816
4818
  try {
4817
- isDir = statSync3(fullPath).isDirectory();
4819
+ isDir = statSync4(fullPath).isDirectory();
4818
4820
  } catch {
4819
4821
  continue;
4820
4822
  }
@@ -4843,10 +4845,10 @@ ${treeLines.join("\n")}`
4843
4845
  for (const name of entries) {
4844
4846
  if (totalChars >= MAX_TOTAL_CHARS) break;
4845
4847
  if (SKIP_DIRS_SET.has(name)) continue;
4846
- const fullPath = join4(dir, name);
4848
+ const fullPath = join5(dir, name);
4847
4849
  let st;
4848
4850
  try {
4849
- st = statSync3(fullPath);
4851
+ st = statSync4(fullPath);
4850
4852
  } catch {
4851
4853
  continue;
4852
4854
  }
@@ -4858,7 +4860,7 @@ ${treeLines.join("\n")}`
4858
4860
  if (!TEXT_EXTS.has(ext) && !isSpecial) continue;
4859
4861
  if (st.size > MAX_FILE_CHARS * 3) continue;
4860
4862
  try {
4861
- let content = readFileSync3(fullPath, "utf-8");
4863
+ let content = readFileSync4(fullPath, "utf-8");
4862
4864
  if (content.length > MAX_FILE_CHARS) {
4863
4865
  content = content.slice(0, MAX_FILE_CHARS) + `
4864
4866
  ... (truncated, ${content.length} chars total)`;
@@ -4888,12 +4890,12 @@ ${content}
4888
4890
  */
4889
4891
  addExtraContextDir(dirPath) {
4890
4892
  const absPath = resolve2(dirPath);
4891
- if (!existsSync4(absPath)) {
4893
+ if (!existsSync5(absPath)) {
4892
4894
  return { success: false, charCount: 0, added: false, error: `Directory not found: ${dirPath}` };
4893
4895
  }
4894
4896
  let isDir;
4895
4897
  try {
4896
- isDir = statSync3(absPath).isDirectory();
4898
+ isDir = statSync4(absPath).isDirectory();
4897
4899
  } catch {
4898
4900
  return { success: false, charCount: 0, added: false, error: `Cannot access: ${dirPath}` };
4899
4901
  }
@@ -4922,9 +4924,9 @@ ${content}
4922
4924
  */
4923
4925
  findContextFile(dir, candidates = CONTEXT_FILE_CANDIDATES) {
4924
4926
  for (const candidate of candidates) {
4925
- const fullPath = join4(dir, candidate);
4926
- if (existsSync4(fullPath)) {
4927
- 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();
4928
4930
  if (content) return { filePath: fullPath, content };
4929
4931
  }
4930
4932
  }
@@ -4952,10 +4954,10 @@ ${content}
4952
4954
  const cwd = process.cwd();
4953
4955
  const gitRoot = getGitRoot(cwd);
4954
4956
  const projectRoot = gitRoot ?? cwd;
4955
- const mcpPath = join4(projectRoot, MCP_PROJECT_CONFIG_NAME);
4956
- if (!existsSync4(mcpPath)) return null;
4957
+ const mcpPath = join5(projectRoot, MCP_PROJECT_CONFIG_NAME);
4958
+ if (!existsSync5(mcpPath)) return null;
4957
4959
  try {
4958
- const raw = JSON.parse(readFileSync3(mcpPath, "utf-8"));
4960
+ const raw = JSON.parse(readFileSync4(mcpPath, "utf-8"));
4959
4961
  const servers = raw?.mcpServers;
4960
4962
  if (!servers || typeof servers !== "object") {
4961
4963
  process.stderr.write(
@@ -5001,8 +5003,8 @@ ${content}
5001
5003
  );
5002
5004
  return { layers: [], mergedContent: "" };
5003
5005
  }
5004
- if (existsSync4(fullPath)) {
5005
- const content = readFileSync3(fullPath, "utf-8").trim();
5006
+ if (existsSync5(fullPath)) {
5007
+ const content = readFileSync4(fullPath, "utf-8").trim();
5006
5008
  if (content) {
5007
5009
  const layer = {
5008
5010
  level: "project",
@@ -5059,9 +5061,9 @@ ${content}
5059
5061
  * 超过 MEMORY_MAX_CHARS 时只取末尾最新部分。
5060
5062
  */
5061
5063
  loadMemoryContent() {
5062
- const memoryPath = join4(this.config.getConfigDir(), MEMORY_FILE_NAME);
5063
- if (!existsSync4(memoryPath)) return null;
5064
- 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();
5065
5067
  if (!content) return null;
5066
5068
  if (content.length > MEMORY_MAX_CHARS) {
5067
5069
  content = content.slice(-MEMORY_MAX_CHARS);
@@ -5449,14 +5451,14 @@ Session '${this.resumeSessionId}' not found.
5449
5451
  process.stdout.write(theme.dim(` \u{1F50C} Plugins loaded: ${pluginCount} tool(s) from plugins/
5450
5452
  `));
5451
5453
  }
5452
- const skillsDir = join4(this.config.getConfigDir(), SKILLS_DIR_NAME);
5454
+ const skillsDir = join5(this.config.getConfigDir(), SKILLS_DIR_NAME);
5453
5455
  this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
5454
5456
  const skillCount = this.skillManager.loadSkills();
5455
5457
  if (skillCount > 0) {
5456
5458
  process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
5457
5459
  `));
5458
5460
  }
5459
- const commandsDir = join4(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
5461
+ const commandsDir = join5(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
5460
5462
  this.customCommandManager = new CustomCommandManager(commandsDir);
5461
5463
  const customCmdCount = this.customCommandManager.loadCommands();
5462
5464
  if (customCmdCount > 0) {
@@ -6092,15 +6094,15 @@ Session '${this.resumeSessionId}' not found.
6092
6094
  const dir = normalized.includes("/") ? dirname3(normalized) : ".";
6093
6095
  const prefix = normalized.includes("/") ? basename2(normalized) : normalized;
6094
6096
  const absDir = resolve2(process.cwd(), dir);
6095
- if (!existsSync4(absDir)) return [];
6097
+ if (!existsSync5(absDir)) return [];
6096
6098
  const entries = readdirSync3(absDir);
6097
6099
  const results = [];
6098
6100
  for (const entry of entries) {
6099
6101
  if (entry.startsWith(".")) continue;
6100
6102
  if (!entry.toLowerCase().startsWith(prefix.toLowerCase())) continue;
6101
6103
  try {
6102
- const fullPath = join4(absDir, entry);
6103
- const stat = statSync3(fullPath);
6104
+ const fullPath = join5(absDir, entry);
6105
+ const stat = statSync4(fullPath);
6104
6106
  const rel = dir === "." ? entry : `${dir}/${entry}`;
6105
6107
  results.push(stat.isDirectory() ? `${rel}/` : rel);
6106
6108
  } catch {
@@ -7269,7 +7271,7 @@ program.command("web").description("Start Web UI server with browser-based chat
7269
7271
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
7270
7272
  process.exit(1);
7271
7273
  }
7272
- const { startWebServer } = await import("./server-LDPQ3DLK.js");
7274
+ const { startWebServer } = await import("./server-4EFTRFTN.js");
7273
7275
  await startWebServer({ port, host: options.host });
7274
7276
  });
7275
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) => {
@@ -7436,16 +7438,16 @@ program.command("sessions").description("List recent conversation sessions").opt
7436
7438
  console.log(footer + "\n");
7437
7439
  });
7438
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) => {
7439
- const { runUsageCli } = await import("./usage-SZWZFX3T.js");
7441
+ const { runUsageCli } = await import("./usage-Q24E5636.js");
7440
7442
  await runUsageCli(options);
7441
7443
  });
7442
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) => {
7443
- const { runDoctorCli } = await import("./doctor-cli-WKH7T4AW.js");
7445
+ const { runDoctorCli } = await import("./doctor-cli-I2Y2YR4V.js");
7444
7446
  await runDoctorCli({ json: !!options.json, resetStats: !!options.resetStats });
7445
7447
  });
7446
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) => {
7447
7449
  try {
7448
- const batch = await import("./batch-6PORMJWT.js");
7450
+ const batch = await import("./batch-3T44NFLG.js");
7449
7451
  switch (action) {
7450
7452
  case "submit":
7451
7453
  if (!arg) {
@@ -7488,7 +7490,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
7488
7490
  }
7489
7491
  });
7490
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) => {
7491
- const { startMcpServer } = await import("./server-37EXC4EB.js");
7493
+ const { startMcpServer } = await import("./server-PVKLPRUP.js");
7492
7494
  await startMcpServer({
7493
7495
  allowDestructive: !!options.allowDestructive,
7494
7496
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -7497,7 +7499,7 @@ program.command("mcp-serve").description("Start an MCP server over STDIO, exposi
7497
7499
  });
7498
7500
  });
7499
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) => {
7500
- const { runCi } = await import("./ci-AYMV66P3.js");
7502
+ const { runCi } = await import("./ci-6QWBVRJX.js");
7501
7503
  const result = await runCi({
7502
7504
  pr: options.pr,
7503
7505
  base: options.base,
@@ -7643,7 +7645,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
7643
7645
  }),
7644
7646
  config.get("customProviders")
7645
7647
  );
7646
- const { startHub } = await import("./hub-6R3M3NTC.js");
7648
+ const { startHub } = await import("./hub-XVPFBODB.js");
7647
7649
  await startHub(
7648
7650
  {
7649
7651
  topic: topic ?? "",
@@ -2,8 +2,8 @@
2
2
  import {
3
3
  executeTests,
4
4
  runTestsTool
5
- } from "./chunk-SFCNFX42.js";
6
- import "./chunk-QNUVZO5X.js";
5
+ } from "./chunk-VWYUB22Y.js";
6
+ import "./chunk-KV4GYNEA.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-BQIV4ZQT.js";
4
+ } from "./chunk-QDY72ABW.js";
5
5
  export {
6
6
  executeTests,
7
7
  runTestsTool
@@ -19,7 +19,7 @@ import {
19
19
  loadDevState,
20
20
  persistToolRound,
21
21
  setupProxy
22
- } from "./chunk-KOU4KX7J.js";
22
+ } from "./chunk-TD7JEHCR.js";
23
23
  import {
24
24
  ToolExecutor,
25
25
  ToolRegistry,
@@ -38,10 +38,10 @@ import {
38
38
  spawnAgentContext,
39
39
  truncateOutput,
40
40
  undoStack
41
- } from "./chunk-QQYSZMET.js";
41
+ } from "./chunk-2OVMMSGQ.js";
42
42
  import "./chunk-T2NL5ZIA.js";
43
43
  import "./chunk-BXP6YZ2P.js";
44
- import "./chunk-SFCNFX42.js";
44
+ import "./chunk-VWYUB22Y.js";
45
45
  import {
46
46
  SessionManager,
47
47
  getContentText
@@ -55,7 +55,7 @@ import {
55
55
  } from "./chunk-QMXC327F.js";
56
56
  import {
57
57
  runTool
58
- } from "./chunk-2WV6AGHM.js";
58
+ } from "./chunk-J22B3OSQ.js";
59
59
  import {
60
60
  CONTENT_ONLY_STREAM_REMINDER,
61
61
  TEE_FINAL_USER_NUDGE,
@@ -74,7 +74,7 @@ import {
74
74
  } from "./chunk-XPBEJB27.js";
75
75
  import {
76
76
  ConfigManager
77
- } from "./chunk-TW47X5AO.js";
77
+ } from "./chunk-TM4MS63K.js";
78
78
  import "./chunk-TZQHYZKT.js";
79
79
  import {
80
80
  AGENTIC_BEHAVIOR_GUIDELINE,
@@ -94,7 +94,7 @@ import {
94
94
  SKILLS_DIR_NAME,
95
95
  VERSION,
96
96
  buildUserIdentityPrompt
97
- } from "./chunk-QNUVZO5X.js";
97
+ } from "./chunk-KV4GYNEA.js";
98
98
  import {
99
99
  formatGitContextForPrompt,
100
100
  getGitContext,
@@ -2458,7 +2458,7 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
2458
2458
  case "test": {
2459
2459
  this.send({ type: "info", message: "\u{1F9EA} Running tests..." });
2460
2460
  try {
2461
- const { executeTests } = await import("./run-tests-5F2OBWIK.js");
2461
+ const { executeTests } = await import("./run-tests-D5SNUBYX.js");
2462
2462
  const argStr = args.join(" ").trim();
2463
2463
  let testArgs = {};
2464
2464
  if (argStr) {
@@ -3528,12 +3528,9 @@ async function startWebServer(options = {}) {
3528
3528
  "Content-Security-Policy",
3529
3529
  [
3530
3530
  "default-src 'self'",
3531
- // v0.4.162: the client UI is driven by inline onclick= handlers and
3532
- // inline <script> blocks (SW registration, theme init). 'self' alone
3533
- // silently blocked EVERY button (click → nothing, no JS error, just a
3534
- // CSP violation in the console). localhost dev/admin tool — the
3535
- // unsafe-inline XSS surface is acceptable under that threat model.
3536
- "script-src 'self' 'unsafe-inline'",
3531
+ // Inline event handlers and startup scripts live in app.js, so script
3532
+ // execution stays locked to same-origin files only.
3533
+ "script-src 'self'",
3537
3534
  "style-src 'self' 'unsafe-inline'",
3538
3535
  "img-src 'self' data: blob:",
3539
3536
  "font-src 'self' data:",
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ToolRegistry
4
- } from "./chunk-QQYSZMET.js";
4
+ } from "./chunk-2OVMMSGQ.js";
5
5
  import "./chunk-T2NL5ZIA.js";
6
6
  import "./chunk-BXP6YZ2P.js";
7
- import "./chunk-SFCNFX42.js";
7
+ import "./chunk-VWYUB22Y.js";
8
8
  import {
9
9
  runTool
10
- } from "./chunk-2WV6AGHM.js";
10
+ } from "./chunk-J22B3OSQ.js";
11
11
  import {
12
12
  getDangerLevel,
13
13
  schemaToJsonSchema
@@ -15,7 +15,7 @@ import {
15
15
  import "./chunk-TZQHYZKT.js";
16
16
  import {
17
17
  VERSION
18
- } from "./chunk-QNUVZO5X.js";
18
+ } from "./chunk-KV4GYNEA.js";
19
19
  import "./chunk-4BKXL7SM.js";
20
20
  import "./chunk-TB4W4Y4T.js";
21
21
  import "./chunk-KHYD3WXE.js";