jinzd-ai-cli 0.4.300 → 0.4.303

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 (34) hide show
  1. package/dist/{batch-ESHQ5NMB.js → batch-PEH5MTMC.js} +2 -2
  2. package/dist/{chunk-KQLKS3ZQ.js → chunk-3GOHR45I.js} +1 -1
  3. package/dist/{chunk-ZMIAVBFY.js → chunk-55AANMEM.js} +1 -1
  4. package/dist/{chunk-YFCGMH2R.js → chunk-6ZRLM3NG.js} +4 -4
  5. package/dist/{chunk-2MOYOMY5.js → chunk-7WD2TBWY.js} +1 -1
  6. package/dist/{chunk-NJ2E3ZYE.js → chunk-DHQCJC2B.js} +1 -1
  7. package/dist/{chunk-RXK3SNCO.js → chunk-EMLRCVY2.js} +1 -1
  8. package/dist/{chunk-Y56UGZPX.js → chunk-MI4SFZGX.js} +3 -1
  9. package/dist/{chunk-MZCMJC3K.js → chunk-ORDEOJXX.js} +1 -1
  10. package/dist/{chunk-QL5HASTV.js → chunk-PEDN3AWT.js} +1 -1
  11. package/dist/{chunk-LNGH6PEC.js → chunk-Q24BN6WF.js} +1 -1
  12. package/dist/{chunk-FBOVBL7P.js → chunk-VXEF2SWG.js} +1 -1
  13. package/dist/{chunk-4CEF4ROO.js → chunk-WCJR5HCF.js} +130 -10
  14. package/dist/{chunk-RPI74YNP.js → chunk-XEKMGE2G.js} +1 -1
  15. package/dist/{chunk-34TV5BBH.js → chunk-YK42KYKN.js} +4 -4
  16. package/dist/{chunk-ZBFNKCH4.js → chunk-ZMCZMR4R.js} +8 -8
  17. package/dist/{ci-5NGCQYUX.js → ci-UXULLQMN.js} +6 -6
  18. package/dist/{ci-format-EKOB2WRP.js → ci-format-23FWBZN6.js} +2 -2
  19. package/dist/{constants-3VGUBD6L.js → constants-A6VKRPMA.js} +1 -1
  20. package/dist/{constants-LZ5UUYEY.js → constants-HL7DYRDJ.js} +1 -1
  21. package/dist/{doctor-cli-5KEROB3Z.js → doctor-cli-FXBLI3EA.js} +6 -6
  22. package/dist/electron-server.js +137 -16
  23. package/dist/{hub-ARZNS7IH.js → hub-NLULKDKU.js} +1 -1
  24. package/dist/index.js +112 -56
  25. package/dist/{persistent-memory-2AWOTKKK.js → persistent-memory-NLXNNWOW.js} +2 -2
  26. package/dist/{persistent-memory-KKEM3K5D.js → persistent-memory-R4KLRI5Q.js} +2 -2
  27. package/dist/{pr-IFMDC3I4.js → pr-K6Z73QYN.js} +6 -6
  28. package/dist/{run-tests-LEY4IOUG.js → run-tests-PQ3SUDDN.js} +2 -2
  29. package/dist/{run-tests-3JIOK2H4.js → run-tests-RYUB6PVF.js} +2 -2
  30. package/dist/{server-4V3F2WSC.js → server-QCCH3277.js} +15 -15
  31. package/dist/{server-L53NTLYW.js → server-UJDYIBVR.js} +6 -6
  32. package/dist/{task-orchestrator-ZNLQD2SM.js → task-orchestrator-QAQFB7DG.js} +6 -6
  33. package/dist/{usage-ZS3LZOUI.js → usage-PMHXXU2P.js} +2 -2
  34. package/package.json +1 -1
@@ -50,7 +50,7 @@ import {
50
50
  touchMemoryReferences,
51
51
  updateMemoryApproval,
52
52
  updateMemoryEntry
53
- } from "./chunk-QL5HASTV.js";
53
+ } from "./chunk-PEDN3AWT.js";
54
54
  import {
55
55
  DEFAULT_PATTERNS,
56
56
  redactJson,
@@ -66,7 +66,7 @@ import {
66
66
  } from "./chunk-CGLYJRFA.js";
67
67
  import {
68
68
  runTestsTool
69
- } from "./chunk-RXK3SNCO.js";
69
+ } from "./chunk-EMLRCVY2.js";
70
70
  import {
71
71
  AGENTIC_BEHAVIOR_GUIDELINE,
72
72
  APP_NAME,
@@ -100,7 +100,7 @@ import {
100
100
  SUBAGENT_MAX_ROUNDS_LIMIT,
101
101
  VERSION,
102
102
  buildUserIdentityPrompt
103
- } from "./chunk-KQLKS3ZQ.js";
103
+ } from "./chunk-3GOHR45I.js";
104
104
 
105
105
  // src/web/server.ts
106
106
  import express from "express";
@@ -2468,7 +2468,9 @@ function extractClaimedFilePaths(content) {
2468
2468
  const paths = /* @__PURE__ */ new Set();
2469
2469
  const add = (p) => {
2470
2470
  const trimmed = p.trim().replace(/[,,。、;;::]+$/, "");
2471
- if (trimmed && /\.\w{1,6}$/.test(trimmed)) paths.add(trimmed);
2471
+ if (!trimmed || !/\.\w{1,6}$/.test(trimmed)) return;
2472
+ if (trimmed.startsWith("@")) return;
2473
+ paths.add(trimmed);
2472
2474
  };
2473
2475
  let m;
2474
2476
  const backtickRe = /`([^`\n]+?\.\w{1,6})`/g;
@@ -5775,6 +5777,90 @@ function decodeWindowsBuffer(buf) {
5775
5777
  return utf8;
5776
5778
  }
5777
5779
  }
5780
+ var GBK_MOJIBAKE_FINGERPRINTS = [
5781
+ "\uFFFD",
5782
+ "\u9215",
5783
+ "\u951B",
5784
+ "\u9983",
5785
+ "\u9241",
5786
+ "\u6D93",
5787
+ "\u935B",
5788
+ "\u9428",
5789
+ "\u7EFE",
5790
+ "\u95AB",
5791
+ "\u9593",
5792
+ "\u95BF",
5793
+ "\u68E3",
5794
+ "\u95B4",
5795
+ "\u5A11",
5796
+ "\u95B8",
5797
+ "\u95BB",
5798
+ "\u7F01",
5799
+ "\u95C1"
5800
+ ];
5801
+ var gbkReverse = null;
5802
+ function gbkReverseMap() {
5803
+ if (gbkReverse) return gbkReverse;
5804
+ const map = /* @__PURE__ */ new Map();
5805
+ try {
5806
+ const dec = new TextDecoder("gbk");
5807
+ for (let hi = 129; hi <= 254; hi++) {
5808
+ for (let lo = 64; lo <= 254; lo++) {
5809
+ if (lo === 127) continue;
5810
+ const ch = dec.decode(new Uint8Array([hi, lo]));
5811
+ if (ch.length === 1 && ch !== "\uFFFD" && !map.has(ch)) map.set(ch, [hi, lo]);
5812
+ }
5813
+ }
5814
+ } catch {
5815
+ }
5816
+ gbkReverse = map;
5817
+ return map;
5818
+ }
5819
+ function decodeRunAsChinese(bytes) {
5820
+ for (let start = 0; start <= 2 && start < bytes.length; start++) {
5821
+ for (let end = 0; end <= 2 && bytes.length - end > start; end++) {
5822
+ const slice = bytes.slice(start, bytes.length - end);
5823
+ if (slice.length < 6) continue;
5824
+ try {
5825
+ const out = new TextDecoder("utf-8", { fatal: true }).decode(new Uint8Array(slice));
5826
+ if (/[一-鿿]/.test(out)) return out;
5827
+ } catch {
5828
+ }
5829
+ }
5830
+ }
5831
+ return null;
5832
+ }
5833
+ function recoverGbkMojibake(text) {
5834
+ if (!text) return null;
5835
+ const map = gbkReverseMap();
5836
+ if (map.size === 0) return null;
5837
+ let run = [];
5838
+ let best = null;
5839
+ const flush2 = () => {
5840
+ if (run.length >= 4) {
5841
+ const bytes = [];
5842
+ for (const p of run) bytes.push(p[0], p[1]);
5843
+ const out = decodeRunAsChinese(bytes);
5844
+ if (out && (!best || out.length > best.length)) best = out;
5845
+ }
5846
+ run = [];
5847
+ };
5848
+ for (const ch of text) {
5849
+ const pair = ch.codePointAt(0) < 128 ? void 0 : map.get(ch);
5850
+ if (pair) run.push(pair);
5851
+ else flush2();
5852
+ }
5853
+ flush2();
5854
+ return best;
5855
+ }
5856
+ function looksLikeGbkMojibake(text) {
5857
+ if (recoverGbkMojibake(text) !== null) return true;
5858
+ let hits = 0;
5859
+ for (const ch of GBK_MOJIBAKE_FINGERPRINTS) {
5860
+ if (text.includes(ch) && ++hits >= 2) return true;
5861
+ }
5862
+ return false;
5863
+ }
5778
5864
  function killProcessTree(proc) {
5779
5865
  if (proc.killed || proc.exitCode !== null) return;
5780
5866
  if (IS_WINDOWS && proc.pid) {
@@ -6166,7 +6252,7 @@ ${combined || formatFailureFallback(status)}
6166
6252
  }
6167
6253
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6168
6254
  updateCwdFromCommand(command, effectiveCwd);
6169
- return stdout || emptyOutputResult(command);
6255
+ return annotateSuccessOutput(command, stdout) || emptyOutputResult(command, stderr ?? "");
6170
6256
  }
6171
6257
  try {
6172
6258
  const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
@@ -6203,7 +6289,10 @@ ${combined || formatFailureFallback(status)}
6203
6289
  updateCwdFromCommand(command, effectiveCwd);
6204
6290
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6205
6291
  const result = Buffer.isBuffer(stdout) ? IS_WINDOWS3 ? decodeWindowsBuffer(stdout) : stdout.toString("utf-8") : String(stdout ?? "");
6206
- return result || emptyOutputResult(command);
6292
+ return annotateSuccessOutput(command, result) || emptyOutputResult(
6293
+ command,
6294
+ Buffer.isBuffer(stderr) ? IS_WINDOWS3 ? decodeWindowsBuffer(stderr) : stderr.toString("utf-8") : String(stderr ?? "")
6295
+ );
6207
6296
  } catch (err) {
6208
6297
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
6209
6298
  if (err && typeof err === "object") {
@@ -6304,10 +6393,26 @@ var BACKSLASH_QUOTE_SILENT_WARNING = `
6304
6393
 
6305
6394
  \u26A0 WARNING: this command contains \\" inside a double-quoted string, but PowerShell does NOT treat \\ as an escape \u2014 that quote CLOSED the string and the command was split into fragments. It exited 0 with no output because the outer program (e.g. ssh) still ran, but it very likely did NOT run what you intended. Do NOT assume this succeeded.
6306
6395
  Fix: write the payload to a local file with the 'write_file' tool, then 'scp' it over and run 'ssh host "psql -d <db> -f /tmp/x.sql"' (single level of quoting). Inside PowerShell strings, escape a quote with \`" or "" \u2014 never \\".`;
6307
- function emptyOutputResult(command) {
6396
+ function emptyOutputResult(command, stderr = "") {
6308
6397
  const base = "(command completed with no output)";
6398
+ const err = stderr.trim();
6399
+ if (err) {
6400
+ return `${base}, but stderr was not empty:
6401
+ ${err}`;
6402
+ }
6309
6403
  return detectPowerShellBackslashQuote(command) ? base + BACKSLASH_QUOTE_SILENT_WARNING : base;
6310
6404
  }
6405
+ var PS_TEXT_READ_CMDLET = /\b(?:Get-Content|gc|cat|type|Select-String|sls|Import-Csv)\b/i;
6406
+ function annotateSuccessOutput(command, stdout) {
6407
+ if (!IS_WINDOWS3 || !PS_TEXT_READ_CMDLET.test(command)) return stdout;
6408
+ if (!looksLikeGbkMojibake(stdout)) return stdout;
6409
+ const recovered = recoverGbkMojibake(stdout);
6410
+ return stdout + `
6411
+
6412
+ \u26A0 WARNING: this output is mojibake (UTF-8 text decoded as GBK). PowerShell's Get-Content / Select-String read BOM-less UTF-8 files using the system code page, so the content was corrupted BEFORE it reached you \u2014 what you see above is NOT what the file says. Do NOT rely on it, and do not quote it back to the user.
6413
+ ` + (recovered ? `Recovered fragment (proof, not the whole file): ${recovered}
6414
+ ` : "") + `Fix: use the 'read_file' tool instead (it decodes UTF-8 correctly). If you must stay in PowerShell, pass -Encoding utf8.`;
6415
+ }
6311
6416
  function buildErrorHint(command, stderr) {
6312
6417
  const hints = [];
6313
6418
  if (IS_WINDOWS3 && /\|\|/.test(command) && /(\|\||is not a valid argument|不是此版本中的有效|ParserError|Unexpected token)/i.test(stderr)) {
@@ -6720,6 +6825,16 @@ var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([
6720
6825
  ".class",
6721
6826
  ".pyc"
6722
6827
  ]);
6828
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
6829
+ ".png",
6830
+ ".jpg",
6831
+ ".jpeg",
6832
+ ".gif",
6833
+ ".bmp",
6834
+ ".ico",
6835
+ ".webp",
6836
+ ".tiff"
6837
+ ]);
6723
6838
  function isBinaryBuffer(buf) {
6724
6839
  const sample = buf.subarray(0, 512);
6725
6840
  let nullCount = 0;
@@ -6890,6 +7005,12 @@ ${err.message}`;
6890
7005
  }
6891
7006
  }
6892
7007
  if (BINARY_EXTENSIONS.has(ext)) {
7008
+ if (IMAGE_EXTENSIONS.has(ext)) {
7009
+ return `[Image file: ${filePath} (${ext})]
7010
+ read_file cannot return image content \u2014 tool results are text-only, so no tool can put an image into your context.
7011
+ To have an image looked at, ask the USER to reference it from their input line with @${filePath} (they can use a glob for a batch, e.g. @dir/*.png, up to 20 at a time). A vision-capable model must be active, or the reference is rejected.
7012
+ Do NOT claim you inspected this image \u2014 you have not seen it.`;
7013
+ }
6893
7014
  return `[Binary file: ${filePath} (${ext})]
6894
7015
  This is a binary file and cannot be read as text. If there is a text version (.md / .txt) in the project, please read that instead.`;
6895
7016
  }
@@ -8078,7 +8199,7 @@ var RuleBasedActionClassifier = class {
8078
8199
  var defaultActionClassifier = new RuleBasedActionClassifier();
8079
8200
 
8080
8201
  // src/tools/executor.ts
8081
- var PS_ERROR_RECORD_HEAD = /^(?:At line:\d+ char:\d+|所在位置\s+行:\d+\s+字符:\d+)\s*$/;
8202
+ var PS_ERROR_RECORD_HEAD = /^(?:[\w.\-]+\s:\s)?(?:At line:\d+ char:\s*\d+|所在位置\s+行:\d+\s+字符:\s*\d+)\s*$/;
8082
8203
  var ERROR_SIGNATURE = new RegExp(
8083
8204
  [
8084
8205
  // Python / .NET / Java: "OSError: …", "pkg.SomeException: …"
@@ -8095,7 +8216,7 @@ var ERROR_SIGNATURE = new RegExp(
8095
8216
  );
8096
8217
  var PY_TRACEBACK_FRAME = /^\s*File ".*", line \d+/;
8097
8218
  function buildErrorPreview(content) {
8098
- const raw = content.split("\n");
8219
+ const raw = content.split("\n").map((l) => l.replace(/\r+$/, ""));
8099
8220
  const undecorated = [];
8100
8221
  for (let i = 0; i < raw.length; i++) {
8101
8222
  if (PS_ERROR_RECORD_HEAD.test(raw[i])) {
@@ -17077,7 +17198,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
17077
17198
  Cost: ${formatCost(cost)}` : "";
17078
17199
  let memoryLine = "";
17079
17200
  try {
17080
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-2AWOTKKK.js");
17201
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-NLXNNWOW.js");
17081
17202
  const pending = countPendingMemories2(ctx.config.getConfigDir());
17082
17203
  if (pending > 0) memoryLine = `
17083
17204
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -18060,7 +18181,7 @@ async function handleTest(args, ctx) {
18060
18181
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
18061
18182
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
18062
18183
  }
18063
- const runTests = ctx.runTests ?? (await import("./run-tests-3JIOK2H4.js")).executeTests;
18184
+ const runTests = ctx.runTests ?? (await import("./run-tests-RYUB6PVF.js")).executeTests;
18064
18185
  const report = await runTests(testArgs);
18065
18186
  ctx.send({ type: "info", message: report });
18066
18187
  } catch (err) {
@@ -18450,7 +18571,7 @@ async function handleMemory(args, ctx) {
18450
18571
  }
18451
18572
  if (intent.kind === "status") {
18452
18573
  const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-DGUOUUQW.js");
18453
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-2AWOTKKK.js");
18574
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-NLXNNWOW.js");
18454
18575
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
18455
18576
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
18456
18577
  const view = buildMemoryStatusView({
@@ -18473,7 +18594,7 @@ async function handleMemory(args, ctx) {
18473
18594
  return;
18474
18595
  }
18475
18596
  if (intent.kind === "recall") {
18476
- const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-2AWOTKKK.js");
18597
+ const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-NLXNNWOW.js");
18477
18598
  const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-DGUOUUQW.js");
18478
18599
  const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
18479
18600
  if (persistentHits.length > 0) {
@@ -18594,7 +18715,7 @@ async function handleMemory(args, ctx) {
18594
18715
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
18595
18716
  } else if (intent.kind === "export") {
18596
18717
  if (args[1] === "md") {
18597
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-2AWOTKKK.js");
18718
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-NLXNNWOW.js");
18598
18719
  ctx.send({
18599
18720
  type: "export_data",
18600
18721
  format: "md",
@@ -19599,7 +19720,7 @@ No tools match "${filter}".
19599
19720
  const { join: join29 } = await import("path");
19600
19721
  const { existsSync: existsSync33 } = await import("fs");
19601
19722
  const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
19602
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-3VGUBD6L.js");
19723
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-A6VKRPMA.js");
19603
19724
  const { approveProject, hashMcpFile } = await import("./project-trust-MUG325AW.js");
19604
19725
  const cwd = process.cwd();
19605
19726
  const projectRoot = getGitRoot2(cwd) ?? cwd;
@@ -20518,7 +20639,7 @@ function createReviewCommands() {
20518
20639
  usage: "/test [command|filter]",
20519
20640
  async execute(args, ctx) {
20520
20641
  try {
20521
- const { executeTests } = await import("./run-tests-3JIOK2H4.js");
20642
+ const { executeTests } = await import("./run-tests-RYUB6PVF.js");
20522
20643
  const argStr = args.join(" ").trim();
20523
20644
  let testArgs = {};
20524
20645
  if (argStr) {
@@ -158,7 +158,7 @@ ${content}`);
158
158
  }
159
159
  }
160
160
  async function runTaskMode(config, providers, configManager, topic) {
161
- const { TaskOrchestrator } = await import("./task-orchestrator-ZNLQD2SM.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-QAQFB7DG.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  setupProxy,
25
25
  snapshotFile,
26
26
  stripRoutingTags
27
- } from "./chunk-ZBFNKCH4.js";
27
+ } from "./chunk-ZMCZMR4R.js";
28
28
  import {
29
29
  CostTracker,
30
30
  getPricing,
@@ -38,6 +38,7 @@ import {
38
38
  cleanupRejectedTeeFile,
39
39
  estimateTokens,
40
40
  formatPermissionProfileWarning,
41
+ globToRegex,
41
42
  googleSearchContext,
42
43
  isInterrupted,
43
44
  isToolCapableProvider,
@@ -49,7 +50,7 @@ import {
49
50
  setMaxOutputCap,
50
51
  spawnAgentContext,
51
52
  undoStack
52
- } from "./chunk-4CEF4ROO.js";
53
+ } from "./chunk-WCJR5HCF.js";
53
54
  import "./chunk-HLWUDRBO.js";
54
55
  import {
55
56
  NO_THINKING,
@@ -62,7 +63,7 @@ import {
62
63
  countPendingMemories,
63
64
  detectStaleLegacyMarkdownEdit,
64
65
  formatMemoryForPrompt
65
- } from "./chunk-NJ2E3ZYE.js";
66
+ } from "./chunk-DHQCJC2B.js";
66
67
  import "./chunk-4DEMGCK4.js";
67
68
  import "./chunk-UUSRWSSX.js";
68
69
  import "./chunk-CKH4KQ4E.js";
@@ -83,22 +84,22 @@ import {
83
84
  import {
84
85
  loadContextFiles,
85
86
  writeCrashLog
86
- } from "./chunk-YFCGMH2R.js";
87
+ } from "./chunk-6ZRLM3NG.js";
87
88
  import {
88
89
  getActivePluginAssets,
89
90
  getPendingHookTrust,
90
91
  installFlushOnExit,
91
92
  mergePluginHooks,
92
93
  runLifecycleHooks
93
- } from "./chunk-LNGH6PEC.js";
94
+ } from "./chunk-Q24BN6WF.js";
94
95
  import "./chunk-RS7SKYTS.js";
95
96
  import {
96
97
  ProviderRegistry,
97
98
  listBuiltInProviderMetadata
98
- } from "./chunk-FBOVBL7P.js";
99
+ } from "./chunk-VXEF2SWG.js";
99
100
  import {
100
101
  ConfigManager
101
- } from "./chunk-RPI74YNP.js";
102
+ } from "./chunk-XEKMGE2G.js";
102
103
  import {
103
104
  CONTENT_ONLY_STREAM_REMINDER,
104
105
  TEE_FINAL_USER_NUDGE,
@@ -116,7 +117,7 @@ import {
116
117
  runAgentLoop,
117
118
  stripToolCallReminder,
118
119
  teeStreamErrorSummary
119
- } from "./chunk-Y56UGZPX.js";
120
+ } from "./chunk-MI4SFZGX.js";
120
121
  import {
121
122
  AuthError,
122
123
  ProviderError,
@@ -132,7 +133,7 @@ import {
132
133
  } from "./chunk-IW3Q7AE5.js";
133
134
  import "./chunk-XNFIYS7G.js";
134
135
  import "./chunk-4BKXL7SM.js";
135
- import "./chunk-MZCMJC3K.js";
136
+ import "./chunk-ORDEOJXX.js";
136
137
  import {
137
138
  AGENTIC_BEHAVIOR_GUIDELINE,
138
139
  AUTHOR,
@@ -149,15 +150,15 @@ import {
149
150
  SKILLS_DIR_NAME,
150
151
  VERSION,
151
152
  buildUserIdentityPrompt
152
- } from "./chunk-2MOYOMY5.js";
153
+ } from "./chunk-7WD2TBWY.js";
153
154
 
154
155
  // src/index.ts
155
156
  import { program } from "commander";
156
157
 
157
158
  // src/repl/repl.ts
158
159
  import * as readline from "readline";
159
- import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync3, mkdirSync as mkdirSync3 } from "fs";
160
- import { join as join3, resolve as resolve2, dirname as dirname2, basename } from "path";
160
+ import { existsSync as existsSync3, readFileSync as readFileSync4, readdirSync as readdirSync4, statSync as statSync3, mkdirSync as mkdirSync3 } from "fs";
161
+ import { join as join4, resolve as resolve2, dirname as dirname3, basename as basename2 } from "path";
161
162
  import chalk3 from "chalk";
162
163
 
163
164
  // src/session/title-generator.ts
@@ -1091,8 +1092,8 @@ function getVisionModelHint(model, provider) {
1091
1092
  }
1092
1093
 
1093
1094
  // src/repl/at-references.ts
1094
- import { existsSync as existsSync2, readFileSync as readFileSync3, statSync as statSync2 } from "fs";
1095
- import { extname as extname3, resolve } from "path";
1095
+ import { existsSync as existsSync2, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
1096
+ import { basename, dirname as dirname2, extname as extname3, join as join3, resolve } from "path";
1096
1097
  var IMAGE_MIME = {
1097
1098
  ".png": "image/png",
1098
1099
  ".jpg": "image/jpeg",
@@ -1101,6 +1102,22 @@ var IMAGE_MIME = {
1101
1102
  ".webp": "image/webp"
1102
1103
  };
1103
1104
  var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
1105
+ var MAX_GLOB_MATCHES = 30;
1106
+ function expandGlob(rawPath, cwd) {
1107
+ const pat = basename(rawPath);
1108
+ if (!/[*?]/.test(pat)) return { kind: "notglob" };
1109
+ const dirPart = dirname2(rawPath);
1110
+ const absDir = resolve(cwd, dirPart);
1111
+ let entries;
1112
+ try {
1113
+ entries = readdirSync3(absDir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name);
1114
+ } catch {
1115
+ return { kind: "nodir", dir: dirPart };
1116
+ }
1117
+ const re = globToRegex(pat);
1118
+ const files = entries.filter((name) => re.test(name)).sort((a, b) => a.localeCompare(b, void 0, { numeric: true, sensitivity: "base" })).map((name) => dirPart === "." ? name : join3(dirPart, name));
1119
+ return { kind: "ok", files };
1120
+ }
1104
1121
  var MAX_PATH_SPACE_TOKENS = 8;
1105
1122
  function expandUnquotedPath(input, pathStart, rawPath, cwd) {
1106
1123
  const plain = { raw: rawPath, consumed: rawPath.length };
@@ -1136,37 +1153,58 @@ function parseAtReferences(input, cwd) {
1136
1153
  atPattern.lastIndex = pathStart + expanded.consumed;
1137
1154
  }
1138
1155
  }
1139
- const absPath = resolve(cwd, rawPath);
1140
- const ext = extname3(rawPath).toLowerCase();
1141
- const mime = IMAGE_MIME[ext];
1142
- if (!existsSync2(absPath)) {
1143
- refs.push({ path: rawPath, type: "notfound" });
1144
- continue;
1145
- }
1146
- if (mime) {
1147
- const fileSize = statSync2(absPath).size;
1148
- if (fileSize > MAX_IMAGE_BYTES) {
1149
- refs.push({ path: rawPath, type: "toolarge" });
1150
- continue;
1156
+ const handleOne = (p, replaceIn) => {
1157
+ const absPath = resolve(cwd, p);
1158
+ const ext = extname3(p).toLowerCase();
1159
+ const mime = IMAGE_MIME[ext];
1160
+ if (!existsSync2(absPath)) {
1161
+ refs.push({ path: p, type: "notfound" });
1162
+ return;
1151
1163
  }
1152
- const data = readFileSync3(absPath).toString("base64");
1153
- imageParts.push({
1154
- type: "image_url",
1155
- image_url: { url: `data:${mime};base64,${data}` }
1156
- });
1157
- refs.push({ path: rawPath, type: "image" });
1158
- textBody = textBody.replace(matchedText, "").trim();
1159
- } else {
1160
- const content = readFileSync3(absPath, "utf-8");
1161
- const inlined = `
1164
+ if (mime) {
1165
+ if (statSync2(absPath).size > MAX_IMAGE_BYTES) {
1166
+ refs.push({ path: p, type: "toolarge" });
1167
+ return;
1168
+ }
1169
+ const data = readFileSync3(absPath).toString("base64");
1170
+ imageParts.push({ type: "image_url", image_url: { url: `data:${mime};base64,${data}` } });
1171
+ refs.push({ path: p, type: "image" });
1172
+ if (replaceIn !== null) textBody = textBody.replace(replaceIn, "").trim();
1173
+ } else {
1174
+ const content = readFileSync3(absPath, "utf-8");
1175
+ const inlined = `
1162
1176
 
1163
- [File: ${rawPath}]
1177
+ [File: ${p}]
1164
1178
  \`\`\`
1165
1179
  ${content}
1166
1180
  \`\`\``;
1167
- textBody = textBody.replace(matchedText, inlined);
1168
- refs.push({ path: rawPath, type: "text" });
1181
+ if (replaceIn !== null) {
1182
+ textBody = textBody.replace(replaceIn, inlined);
1183
+ } else {
1184
+ textBody += inlined;
1185
+ }
1186
+ refs.push({ path: p, type: "text" });
1187
+ }
1188
+ };
1189
+ const globbed = existsSync2(resolve(cwd, rawPath)) ? { kind: "notglob" } : expandGlob(rawPath, cwd);
1190
+ if (globbed.kind === "nodir") {
1191
+ refs.push({ path: rawPath, type: "glob-nodir", dir: globbed.dir });
1192
+ continue;
1169
1193
  }
1194
+ if (globbed.kind === "ok") {
1195
+ if (globbed.files.length === 0) {
1196
+ refs.push({ path: rawPath, type: "glob-empty" });
1197
+ continue;
1198
+ }
1199
+ if (globbed.files.length > MAX_GLOB_MATCHES) {
1200
+ refs.push({ path: rawPath, type: "glob-toomany", matched: globbed.files.length });
1201
+ continue;
1202
+ }
1203
+ textBody = textBody.replace(matchedText, "").trim();
1204
+ for (const p of globbed.files) handleOne(p, null);
1205
+ continue;
1206
+ }
1207
+ handleOne(rawPath, matchedText);
1170
1208
  }
1171
1209
  const parts = [];
1172
1210
  if (textBody.trim()) {
@@ -1631,7 +1669,7 @@ var Repl = class {
1631
1669
  const cwd = process.cwd();
1632
1670
  const gitRoot = getGitRoot(cwd);
1633
1671
  const projectRoot = gitRoot ?? cwd;
1634
- const mcpPath = join3(projectRoot, MCP_PROJECT_CONFIG_NAME);
1672
+ const mcpPath = join4(projectRoot, MCP_PROJECT_CONFIG_NAME);
1635
1673
  if (!existsSync3(mcpPath)) return null;
1636
1674
  try {
1637
1675
  const raw = JSON.parse(readFileSync4(mcpPath, "utf-8"));
@@ -2106,7 +2144,7 @@ Session '${this.resumeSessionId}' not found.
2106
2144
  process.stdout.write(theme.dim(` \u{1F50C} Plugins loaded: ${pluginCount} tool(s) from plugins/
2107
2145
  `));
2108
2146
  }
2109
- const skillsDir = join3(this.config.getConfigDir(), SKILLS_DIR_NAME);
2147
+ const skillsDir = join4(this.config.getConfigDir(), SKILLS_DIR_NAME);
2110
2148
  this.skillManager = new SkillManager(skillsDir, this.config.get("ui").skillSizeWarn);
2111
2149
  const pluginAssets = getActivePluginAssets(this.config.getConfigDir());
2112
2150
  const skillCount = this.skillManager.loadSkills(pluginAssets.skillDirs);
@@ -2114,7 +2152,7 @@ Session '${this.resumeSessionId}' not found.
2114
2152
  process.stdout.write(theme.dim(` \u{1F3AF} Skills: ${skillCount} available (use /skill to manage)
2115
2153
  `));
2116
2154
  }
2117
- const commandsDir = join3(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
2155
+ const commandsDir = join4(this.config.getConfigDir(), CUSTOM_COMMANDS_DIR_NAME);
2118
2156
  this.customCommandManager = new CustomCommandManager(commandsDir);
2119
2157
  const customCmdCount = this.customCommandManager.loadCommands(pluginAssets.commandDirs);
2120
2158
  if (customCmdCount > 0) {
@@ -2397,6 +2435,24 @@ Session '${this.resumeSessionId}' not found.
2397
2435
  } else if (ref.type === "toolarge") {
2398
2436
  process.stdout.write(theme.warning(` \u26A0 Image too large (> 10 MB): ${ref.path}
2399
2437
  `));
2438
+ } else if (ref.type === "glob-nodir") {
2439
+ process.stdout.write(
2440
+ theme.warning(` \u26A0 Directory does not exist: ${ref.dir ?? ""} (from ${ref.path})
2441
+ `)
2442
+ );
2443
+ } else if (ref.type === "glob-empty") {
2444
+ process.stdout.write(
2445
+ theme.warning(` \u26A0 No files match: ${ref.path} (directory exists but nothing matched)
2446
+ `)
2447
+ );
2448
+ } else if (ref.type === "glob-toomany") {
2449
+ process.stdout.write(
2450
+ theme.warning(
2451
+ ` \u26A0 ${ref.path} matches ${ref.matched ?? 0} files (max 20 per reference).
2452
+ Narrow the pattern and go in batches, e.g. ${ref.path.replace(/\*/, "0*")} then ${ref.path.replace(/\*/, "1*")}
2453
+ `
2454
+ )
2455
+ );
2400
2456
  } else if (ref.type === "image") {
2401
2457
  process.stdout.write(theme.dim(` \u{1F4CE} Image: ${ref.path}
2402
2458
  `));
@@ -2744,17 +2800,17 @@ Session '${this.resumeSessionId}' not found.
2744
2800
  completeFilePath(partial) {
2745
2801
  try {
2746
2802
  const normalized = partial.replace(/\\/g, "/");
2747
- const dir = normalized.includes("/") ? dirname2(normalized) : ".";
2748
- const prefix = normalized.includes("/") ? basename(normalized) : normalized;
2803
+ const dir = normalized.includes("/") ? dirname3(normalized) : ".";
2804
+ const prefix = normalized.includes("/") ? basename2(normalized) : normalized;
2749
2805
  const absDir = resolve2(process.cwd(), dir);
2750
2806
  if (!existsSync3(absDir)) return [];
2751
- const entries = readdirSync3(absDir);
2807
+ const entries = readdirSync4(absDir);
2752
2808
  const results = [];
2753
2809
  for (const entry of entries) {
2754
2810
  if (entry.startsWith(".")) continue;
2755
2811
  if (!entry.toLowerCase().startsWith(prefix.toLowerCase())) continue;
2756
2812
  try {
2757
- const fullPath = join3(absDir, entry);
2813
+ const fullPath = join4(absDir, entry);
2758
2814
  const stat = statSync3(fullPath);
2759
2815
  const rel = dir === "." ? entry : `${dir}/${entry}`;
2760
2816
  results.push(stat.isDirectory() ? `${rel}/` : rel);
@@ -3342,7 +3398,7 @@ ${decision.displayMessage}
3342
3398
  });
3343
3399
  if (decision.kind === "save") {
3344
3400
  try {
3345
- mkdirSync3(dirname2(target), { recursive: true });
3401
+ mkdirSync3(dirname3(target), { recursive: true });
3346
3402
  atomicWriteFileSync(target, decision.body);
3347
3403
  undoStack.push(target, `save_last_response (deferred): ${target}`);
3348
3404
  const lines = decision.body.split("\n").length;
@@ -4005,7 +4061,7 @@ program.command("web").description("Start Web UI server with browser-based chat
4005
4061
  console.error("Error: Invalid port number. Must be between 1 and 65535.");
4006
4062
  process.exit(1);
4007
4063
  }
4008
- const { startWebServer } = await import("./server-4V3F2WSC.js");
4064
+ const { startWebServer } = await import("./server-QCCH3277.js");
4009
4065
  await startWebServer({ port, host: options.host });
4010
4066
  });
4011
4067
  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) => {
@@ -4172,11 +4228,11 @@ program.command("sessions").description("List recent conversation sessions").opt
4172
4228
  console.log(footer + "\n");
4173
4229
  });
4174
4230
  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) => {
4175
- const { runUsageCli } = await import("./usage-ZS3LZOUI.js");
4231
+ const { runUsageCli } = await import("./usage-PMHXXU2P.js");
4176
4232
  await runUsageCli(options);
4177
4233
  });
4178
4234
  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) => {
4179
- const { runDoctorCli } = await import("./doctor-cli-5KEROB3Z.js");
4235
+ const { runDoctorCli } = await import("./doctor-cli-FXBLI3EA.js");
4180
4236
  const argv = process.argv.slice(2);
4181
4237
  await runDoctorCli({
4182
4238
  json: !!options.json || argv.includes("--json"),
@@ -4185,7 +4241,7 @@ program.command("doctor").description("Health check: API keys, config, MCP, rece
4185
4241
  });
4186
4242
  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) => {
4187
4243
  try {
4188
- const batch = await import("./batch-ESHQ5NMB.js");
4244
+ const batch = await import("./batch-PEH5MTMC.js");
4189
4245
  switch (action) {
4190
4246
  case "submit":
4191
4247
  if (!arg) {
@@ -4228,7 +4284,7 @@ program.command("batch <action> [arg] [arg2]").description("Anthropic Message Ba
4228
4284
  }
4229
4285
  });
4230
4286
  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) => {
4231
- const { startMcpServer } = await import("./server-L53NTLYW.js");
4287
+ const { startMcpServer } = await import("./server-UJDYIBVR.js");
4232
4288
  await startMcpServer({
4233
4289
  allowDestructive: !!options.allowDestructive,
4234
4290
  allowOutsideCwd: !!options.allowOutsideCwd,
@@ -4241,7 +4297,7 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4241
4297
  console.error(`Unknown pr action: ${action}. Use review | security-review | summarize.`);
4242
4298
  process.exit(1);
4243
4299
  }
4244
- const { runPrCli } = await import("./pr-IFMDC3I4.js");
4300
+ const { runPrCli } = await import("./pr-K6Z73QYN.js");
4245
4301
  const result = await runPrCli({
4246
4302
  action,
4247
4303
  target,
@@ -4261,8 +4317,8 @@ program.command("pr <action> [target]").description("PR review helpers: review |
4261
4317
  process.exit(result.exitCode);
4262
4318
  });
4263
4319
  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 or URL; diff fetched via gh pr diff <value>", (v) => /^#?\d+$/.test(v) ? parseInt(v.replace(/^#/, ""), 10) : v).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)").option("--json", "Output a structured JSON report").option("--markdown", "Output Markdown report (default)").option("--sarif", "Output SARIF 2.1.0 for code scanning artifacts").option("--fail-on-security-high", "Fail when the security review contains HIGH/CRITICAL findings (default)").option("--no-fail-on-security-high", "Do not fail on security HIGH/CRITICAL findings").option("--fail-on-test-failure", "Fail when the report mentions test failures (default)").option("--no-fail-on-test-failure", "Do not fail on test failure findings").option("--fail-on-lint-failure", "Fail when the report mentions lint/typecheck failures (default)").option("--no-fail-on-lint-failure", "Do not fail on lint/typecheck failure findings").action(async (options) => {
4264
- const { runCi } = await import("./ci-5NGCQYUX.js");
4265
- const { formatCiResult } = await import("./ci-format-EKOB2WRP.js");
4320
+ const { runCi } = await import("./ci-UXULLQMN.js");
4321
+ const { formatCiResult } = await import("./ci-format-23FWBZN6.js");
4266
4322
  const formats = [options.json, options.markdown, options.sarif].filter(Boolean).length;
4267
4323
  if (formats > 1) {
4268
4324
  console.error("Choose only one output format: --json, --markdown, or --sarif.");
@@ -4421,7 +4477,7 @@ program.command("hub [topic]").description("Start multi-agent hub (discuss / bra
4421
4477
  config.get("customProviders"),
4422
4478
  config.getConfigDir()
4423
4479
  );
4424
- const { startHub } = await import("./hub-ARZNS7IH.js");
4480
+ const { startHub } = await import("./hub-NLULKDKU.js");
4425
4481
  await startHub(
4426
4482
  {
4427
4483
  topic: topic ?? "",