jinzd-ai-cli 0.4.217 → 0.4.219

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 +5 -2
  2. package/dist/{batch-YCOVKTXD.js → batch-CHAPYRVM.js} +2 -2
  3. package/dist/chunk-3I4RZYYO.js +638 -0
  4. package/dist/{chunk-KOPUCJXM.js → chunk-4ZN6L6K5.js} +3 -3
  5. package/dist/{chunk-VTH7BLXK.js → chunk-64NUW3WL.js} +1 -1
  6. package/dist/{chunk-QAYOI57M.js → chunk-EGMORH5W.js} +1 -1
  7. package/dist/{chunk-MGBMNCHG.js → chunk-GEN4O5QH.js} +94 -270
  8. package/dist/chunk-GGKQHPB3.js +604 -0
  9. package/dist/{chunk-WKOQ5CYC.js → chunk-KIEZBTVD.js} +1 -1
  10. package/dist/{chunk-OUAZOE5U.js → chunk-QUFYBR6Q.js} +47 -206
  11. package/dist/{chunk-XJGEQIYS.js → chunk-U7KVU25H.js} +1 -1
  12. package/dist/{chunk-WZ3VKLF3.js → chunk-VADHBW7T.js} +1 -1
  13. package/dist/{ci-52RZIYWB.js → ci-QPP66T53.js} +4 -4
  14. package/dist/{ci-format-73UXKE65.js → ci-format-5S3EEYRK.js} +2 -2
  15. package/dist/{constants-DIXAD35W.js → constants-FJOLBABC.js} +1 -1
  16. package/dist/doctor-cli-KB2LUDF3.js +17 -0
  17. package/dist/electron-server.js +921 -274
  18. package/dist/{hub-GIGBITZN.js → hub-DIM7SKKY.js} +1 -1
  19. package/dist/index.js +192 -200
  20. package/dist/{pr-KPQ5RPKB.js → pr-YQGH72N6.js} +4 -4
  21. package/dist/{run-tests-ZDSA3QES.js → run-tests-GEZSSNJM.js} +2 -2
  22. package/dist/{run-tests-K7QR5QN4.js → run-tests-O76JIBCW.js} +1 -1
  23. package/dist/{server-QT3SC2KI.js → server-5E2AIXVX.js} +108 -80
  24. package/dist/{server-22YF3U34.js → server-Z6O3G2LY.js} +9 -9
  25. package/dist/{task-orchestrator-BHQQCVTY.js → task-orchestrator-5HBW4O64.js} +9 -9
  26. package/dist/{usage-WZZFSFLM.js → usage-BMK6M5U3.js} +2 -2
  27. package/package.json +1 -1
  28. package/dist/chunk-524WZOKS.js +0 -166
  29. package/dist/chunk-SNJAOXFT.js +0 -129
  30. package/dist/doctor-cli-7GOQPULZ.js +0 -226
@@ -1,14 +1,31 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ indexProject
4
+ } from "./chunk-K3CF65QH.js";
2
5
  import {
3
6
  hasSemanticIndex,
4
7
  semanticSearch
5
8
  } from "./chunk-T2NL5ZIA.js";
6
9
  import {
7
10
  runTestsTool
8
- } from "./chunk-VTH7BLXK.js";
11
+ } from "./chunk-64NUW3WL.js";
12
+ import {
13
+ fileCheckpoints
14
+ } from "./chunk-4BKXL7SM.js";
9
15
  import {
16
+ loadChatIndex,
17
+ searchChatMemory
18
+ } from "./chunk-TB4W4Y4T.js";
19
+ import {
20
+ DEFAULT_PATTERNS,
21
+ redactString
22
+ } from "./chunk-SLSWPBK3.js";
23
+ import {
24
+ getActivePluginAssets,
25
+ runHook,
26
+ runLifecycleHooks,
10
27
  runTool
11
- } from "./chunk-SNJAOXFT.js";
28
+ } from "./chunk-GGKQHPB3.js";
12
29
  import {
13
30
  getDangerLevel,
14
31
  isFileWriteTool,
@@ -28,24 +45,10 @@ import {
28
45
  SUBAGENT_ALLOWED_TOOLS,
29
46
  SUBAGENT_DEFAULT_MAX_ROUNDS,
30
47
  SUBAGENT_MAX_ROUNDS_LIMIT
31
- } from "./chunk-XJGEQIYS.js";
48
+ } from "./chunk-U7KVU25H.js";
32
49
  import {
33
50
  getGitRoot
34
51
  } from "./chunk-HOSJZMQS.js";
35
- import {
36
- fileCheckpoints
37
- } from "./chunk-4BKXL7SM.js";
38
- import {
39
- loadChatIndex,
40
- searchChatMemory
41
- } from "./chunk-TB4W4Y4T.js";
42
- import {
43
- DEFAULT_PATTERNS,
44
- redactString
45
- } from "./chunk-SLSWPBK3.js";
46
- import {
47
- indexProject
48
- } from "./chunk-K3CF65QH.js";
49
52
  import {
50
53
  loadIndex
51
54
  } from "./chunk-CKH4KQ4E.js";
@@ -1059,12 +1062,12 @@ ${content}`;
1059
1062
  };
1060
1063
 
1061
1064
  // src/tools/builtin/write-file.ts
1062
- import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
1065
+ import { appendFileSync, mkdirSync } from "fs";
1063
1066
  import { dirname as dirname2 } from "path";
1064
1067
 
1065
1068
  // src/tools/executor.ts
1066
1069
  import chalk3 from "chalk";
1067
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
1070
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
1068
1071
  import { tmpdir } from "os";
1069
1072
 
1070
1073
  // src/core/readline-internal.ts
@@ -1270,184 +1273,6 @@ function simpleDiff(oldLines, newLines) {
1270
1273
  return result;
1271
1274
  }
1272
1275
 
1273
- // src/tools/hooks.ts
1274
- import { execSync } from "child_process";
1275
- import { createHash } from "crypto";
1276
- import { existsSync as existsSync4, mkdirSync, readFileSync as readFileSync3 } from "fs";
1277
- import { join } from "path";
1278
- var TRUST_FILE = "hooks-trust.json";
1279
- var DEFAULT_TIMEOUT_MS = 5e3;
1280
- function asArray(entry) {
1281
- if (!entry) return [];
1282
- const raw = Array.isArray(entry) ? entry : [entry];
1283
- return raw.map((item) => typeof item === "string" ? { command: item } : item);
1284
- }
1285
- function hookTrustPath(configDir) {
1286
- return join(configDir, TRUST_FILE);
1287
- }
1288
- function loadHookTrustStore(configDir) {
1289
- const file = hookTrustPath(configDir);
1290
- if (!existsSync4(file)) return { records: [] };
1291
- try {
1292
- const parsed = JSON.parse(readFileSync3(file, "utf-8"));
1293
- return { records: Array.isArray(parsed.records) ? parsed.records : [] };
1294
- } catch {
1295
- return { records: [] };
1296
- }
1297
- }
1298
- function saveHookTrustStore(configDir, store) {
1299
- mkdirSync(configDir, { recursive: true });
1300
- atomicWriteFileSync(hookTrustPath(configDir), JSON.stringify(store, null, 2));
1301
- }
1302
- function hashHook(event, command) {
1303
- return createHash("sha256").update(`${event}
1304
- ${command}`, "utf-8").digest("hex");
1305
- }
1306
- function isTrusted(source, event, hash, store) {
1307
- if (source === "user" || source === "managed") return true;
1308
- return store.records.some((r) => r.source === source && r.event === event && r.hash === hash);
1309
- }
1310
- function listHooks(config, configDir) {
1311
- if (!config || config.enabled === false) return [];
1312
- const store = loadHookTrustStore(configDir);
1313
- const out = [];
1314
- const push = (event, hook, index) => {
1315
- if (!hook.command) return;
1316
- const source = hook.source ?? "user";
1317
- const hash = hashHook(event, hook.command);
1318
- out.push({
1319
- id: `${event}:${index}`,
1320
- event,
1321
- command: hook.command,
1322
- source,
1323
- hash,
1324
- trusted: isTrusted(source, event, hash, store),
1325
- disabled: hook.disabled === true,
1326
- description: hook.description
1327
- });
1328
- };
1329
- if (config.preToolExecution) push("PreToolUse", { command: config.preToolExecution }, 0);
1330
- if (config.postToolExecution) push("PostToolUse", { command: config.postToolExecution }, 0);
1331
- for (const [event, entry] of Object.entries(config.events ?? {})) {
1332
- asArray(entry).forEach((hook, i) => push(event, hook, i));
1333
- }
1334
- return out;
1335
- }
1336
- function trustHook(configDir, hook) {
1337
- const store = loadHookTrustStore(configDir);
1338
- const next = store.records.filter((r) => !(r.source === hook.source && r.event === hook.event && r.id === hook.id));
1339
- next.push({ id: hook.id, event: hook.event, source: hook.source, hash: hook.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
1340
- saveHookTrustStore(configDir, { records: next });
1341
- }
1342
- function untrustHook(configDir, hook) {
1343
- const store = loadHookTrustStore(configDir);
1344
- saveHookTrustStore(configDir, {
1345
- records: store.records.filter((r) => !(r.source === hook.source && r.event === hook.event && r.hash === hook.hash))
1346
- });
1347
- }
1348
- function getPendingHookTrust(config, configDir) {
1349
- return listHooks(config, configDir).filter((h) => h.source === "project" && !h.disabled && !h.trusted);
1350
- }
1351
- function normalizeDecision(value, hook) {
1352
- if (!value || typeof value !== "object") return null;
1353
- const obj = value;
1354
- const action = obj.action;
1355
- if (action !== "allow" && action !== "deny" && action !== "ask") return null;
1356
- return {
1357
- action,
1358
- reason: typeof obj.reason === "string" ? obj.reason : void 0,
1359
- prompt: typeof obj.prompt === "string" ? obj.prompt : void 0,
1360
- contextAppend: typeof obj.contextAppend === "string" ? obj.contextAppend : void 0,
1361
- warning: typeof obj.warning === "string" ? obj.warning : void 0,
1362
- warnings: Array.isArray(obj.warnings) ? obj.warnings.filter((x) => typeof x === "string") : void 0,
1363
- hook
1364
- };
1365
- }
1366
- function runStructuredHook(hook, descriptor, payload) {
1367
- if (hook.disabled === true) return null;
1368
- const timeout = Math.max(100, Math.min(hook.timeoutMs ?? DEFAULT_TIMEOUT_MS, 3e4));
1369
- try {
1370
- const stdout = execSync(hook.command, {
1371
- timeout,
1372
- stdio: ["pipe", "pipe", "pipe"],
1373
- encoding: "utf-8",
1374
- env: {
1375
- ...process.env,
1376
- AICLI_HOOK_EVENT: payload.event,
1377
- AICLI_HOOK_EVENT_JSON: JSON.stringify(payload)
1378
- }
1379
- }).trim();
1380
- if (!stdout) return null;
1381
- return normalizeDecision(JSON.parse(stdout), descriptor);
1382
- } catch (err) {
1383
- process.stderr.write(`\u26A0 Hook failed: ${hook.command.slice(0, 100)}
1384
- `);
1385
- if (hook.required) {
1386
- return { action: "deny", reason: err instanceof Error ? err.message : String(err), hook: descriptor };
1387
- }
1388
- return null;
1389
- }
1390
- }
1391
- function runLifecycleHooks(config, event, payload, opts) {
1392
- if (!config || config.enabled === false) return [];
1393
- const options = typeof opts === "string" ? { configDir: opts } : opts;
1394
- const store = loadHookTrustStore(options.configDir);
1395
- const hooks = asArray(config.events?.[event]);
1396
- const decisions = [];
1397
- for (let i = 0; i < hooks.length; i++) {
1398
- const hook = hooks[i];
1399
- if (!hook.command || hook.disabled) continue;
1400
- const source = hook.source ?? "user";
1401
- const hash = hashHook(event, hook.command);
1402
- const descriptor = {
1403
- id: `${event}:${i}`,
1404
- event,
1405
- command: hook.command,
1406
- source,
1407
- hash,
1408
- trusted: isTrusted(source, event, hash, store),
1409
- disabled: false,
1410
- description: hook.description
1411
- };
1412
- if (!descriptor.trusted) {
1413
- options.onSummary?.(`hook skipped: ${event} project hook requires trust (${hash.slice(0, 12)})`);
1414
- continue;
1415
- }
1416
- const decision = runStructuredHook(hook, descriptor, { event, ...payload });
1417
- if (decision) {
1418
- decisions.push(decision);
1419
- options.onSummary?.(`hook ${event}: ${decision.action}${decision.reason ? ` (${decision.reason})` : ""}`);
1420
- }
1421
- }
1422
- return decisions;
1423
- }
1424
- function rewriteTemplate(template, isWindows) {
1425
- const ref = (name) => isWindows ? `%${name}%` : `$${name}`;
1426
- return template.replace(/\{tool\}/g, ref("AICLI_HOOK_TOOL")).replace(/\{dangerLevel\}/g, ref("AICLI_HOOK_DANGER_LEVEL")).replace(/\{args\}/g, ref("AICLI_HOOK_ARGS")).replace(/\{status\}/g, ref("AICLI_HOOK_STATUS"));
1427
- }
1428
- function runHook(template, vars) {
1429
- if (!template) return;
1430
- const isWindows = process.platform === "win32";
1431
- const cmd = rewriteTemplate(template, isWindows);
1432
- try {
1433
- execSync(cmd, {
1434
- timeout: DEFAULT_TIMEOUT_MS,
1435
- stdio: ["pipe", "pipe", "pipe"],
1436
- encoding: "utf-8",
1437
- env: {
1438
- ...process.env,
1439
- AICLI_HOOK_TOOL: vars.tool,
1440
- AICLI_HOOK_DANGER_LEVEL: vars.dangerLevel ?? "",
1441
- AICLI_HOOK_ARGS: vars.args ?? "",
1442
- AICLI_HOOK_STATUS: vars.status ?? ""
1443
- }
1444
- });
1445
- } catch {
1446
- process.stderr.write(`\u26A0 Hook failed: ${cmd.slice(0, 100)}
1447
- `);
1448
- }
1449
- }
1450
-
1451
1276
  // src/tools/permissions.ts
1452
1277
  import { isAbsolute, resolve as resolve3 } from "path";
1453
1278
  function checkPermission(toolName, args, dangerLevel, rules, defaultAction = "confirm") {
@@ -1870,8 +1695,8 @@ var theme = new Proxy(DARK_THEME, {
1870
1695
  });
1871
1696
 
1872
1697
  // src/tools/action-classifier.ts
1873
- import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
1874
- import { isAbsolute as isAbsolute2, join as join2, resolve as resolve4 } from "path";
1698
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1699
+ import { isAbsolute as isAbsolute2, join, resolve as resolve4 } from "path";
1875
1700
  var RECENT_DENIED_LIMIT = 50;
1876
1701
  var recentlyDenied = [];
1877
1702
  function recordRecentlyDeniedAutoAction(call, classification) {
@@ -1912,10 +1737,10 @@ function splitShellWords(command) {
1912
1737
  return out.filter(Boolean);
1913
1738
  }
1914
1739
  function readPackageManifest(root) {
1915
- const p = join2(root, "package.json");
1916
- if (!existsSync5(p)) return null;
1740
+ const p = join(root, "package.json");
1741
+ if (!existsSync4(p)) return null;
1917
1742
  try {
1918
- return JSON.parse(readFileSync4(p, "utf-8"));
1743
+ return JSON.parse(readFileSync3(p, "utf-8"));
1919
1744
  } catch {
1920
1745
  return null;
1921
1746
  }
@@ -1931,10 +1756,10 @@ function manifestHasDependency(root, name) {
1931
1756
  }
1932
1757
  function lockfileMentions(root, name) {
1933
1758
  for (const file of ["package-lock.json", "pnpm-lock.yaml", "yarn.lock"]) {
1934
- const p = join2(root, file);
1935
- if (!existsSync5(p)) continue;
1759
+ const p = join(root, file);
1760
+ if (!existsSync4(p)) continue;
1936
1761
  try {
1937
- if (readFileSync4(p, "utf-8").includes(name)) return true;
1762
+ if (readFileSync3(p, "utf-8").includes(name)) return true;
1938
1763
  } catch {
1939
1764
  }
1940
1765
  }
@@ -2498,10 +2323,10 @@ var ToolExecutor = class {
2498
2323
  const filePath = String(call.arguments["path"] ?? "");
2499
2324
  const newContent = String(call.arguments["content"] ?? "");
2500
2325
  if (!filePath) return;
2501
- if (existsSync6(filePath)) {
2326
+ if (existsSync5(filePath)) {
2502
2327
  let oldContent;
2503
2328
  try {
2504
- oldContent = readFileSync5(filePath, "utf-8");
2329
+ oldContent = readFileSync4(filePath, "utf-8");
2505
2330
  } catch {
2506
2331
  return;
2507
2332
  }
@@ -2524,7 +2349,7 @@ var ToolExecutor = class {
2524
2349
  }
2525
2350
  } else if (call.name === "edit_file") {
2526
2351
  const filePath = String(call.arguments["path"] ?? "");
2527
- if (!filePath || !existsSync6(filePath)) return;
2352
+ if (!filePath || !existsSync5(filePath)) return;
2528
2353
  const oldStr = call.arguments["old_str"];
2529
2354
  const newStr = call.arguments["new_str"];
2530
2355
  if (oldStr !== void 0) {
@@ -2551,7 +2376,7 @@ var ToolExecutor = class {
2551
2376
  const to = Number(call.arguments["delete_to_line"] ?? from);
2552
2377
  let fileContent;
2553
2378
  try {
2554
- fileContent = readFileSync5(filePath, "utf-8");
2379
+ fileContent = readFileSync4(filePath, "utf-8");
2555
2380
  } catch {
2556
2381
  return;
2557
2382
  }
@@ -2786,7 +2611,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
2786
2611
  }
2787
2612
  undoStack.push(filePath, `write_file${appendMode ? " (append)" : ""}: ${filePath}`);
2788
2613
  fileCheckpoints.snapshot(filePath, ToolExecutor.currentMessageIndex);
2789
- mkdirSync2(dirname2(filePath), { recursive: true });
2614
+ mkdirSync(dirname2(filePath), { recursive: true });
2790
2615
  if (appendMode) {
2791
2616
  appendFileSync(filePath, content, encoding);
2792
2617
  } else {
@@ -2806,7 +2631,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
2806
2631
  };
2807
2632
 
2808
2633
  // src/tools/builtin/edit-file.ts
2809
- import { readFileSync as readFileSync6, existsSync as existsSync7 } from "fs";
2634
+ import { readFileSync as readFileSync5, existsSync as existsSync6 } from "fs";
2810
2635
 
2811
2636
  // src/tools/builtin/patch-apply.ts
2812
2637
  function parseUnifiedDiff(patch) {
@@ -3167,7 +2992,7 @@ Note: Path can be absolute or relative to cwd.`,
3167
2992
  const filePath = String(args["path"] ?? "");
3168
2993
  const encoding = args["encoding"] ?? "utf-8";
3169
2994
  if (!filePath) throw new ToolError("edit_file", "path is required");
3170
- if (!existsSync7(filePath)) throw new ToolError("edit_file", `File not found: ${filePath}`);
2995
+ if (!existsSync6(filePath)) throw new ToolError("edit_file", `File not found: ${filePath}`);
3171
2996
  const verdict = classifyWritePath(filePath);
3172
2997
  if (verdict.sensitive && subAgentGuard.active) {
3173
2998
  throw new ToolError(
@@ -3175,7 +3000,7 @@ Note: Path can be absolute or relative to cwd.`,
3175
3000
  `Refused: sub-agents cannot edit sensitive paths \u2014 ${verdict.reason}. If this is genuinely needed, ask the parent agent to perform the edit so the user can approve it.`
3176
3001
  );
3177
3002
  }
3178
- const original = readFileSync6(filePath, encoding);
3003
+ const original = readFileSync5(filePath, encoding);
3179
3004
  if (args["patch"] !== void 0) {
3180
3005
  const patchText = String(args["patch"] ?? "");
3181
3006
  const stopOnError = args["stop_on_error"] !== false;
@@ -3333,8 +3158,8 @@ function truncatePreview(str, maxLen = 80) {
3333
3158
  }
3334
3159
 
3335
3160
  // src/tools/builtin/list-dir.ts
3336
- import { readdirSync as readdirSync3, statSync as statSync3, existsSync as existsSync8 } from "fs";
3337
- import { join as join3, basename as basename3 } from "path";
3161
+ import { readdirSync as readdirSync3, statSync as statSync3, existsSync as existsSync7 } from "fs";
3162
+ import { join as join2, basename as basename3 } from "path";
3338
3163
  var listDirTool = {
3339
3164
  definition: {
3340
3165
  name: "list_dir",
@@ -3356,7 +3181,7 @@ var listDirTool = {
3356
3181
  async execute(args) {
3357
3182
  const dirPath = String(args["path"] ?? process.cwd());
3358
3183
  const recursive = Boolean(args["recursive"] ?? false);
3359
- if (!existsSync8(dirPath)) {
3184
+ if (!existsSync7(dirPath)) {
3360
3185
  const targetName = basename3(dirPath).toLowerCase();
3361
3186
  const cwd = process.cwd();
3362
3187
  const suggestions = [];
@@ -3414,11 +3239,11 @@ function listRecursive(basePath, indent, recursive, lines) {
3414
3239
  if (entry.isDirectory()) {
3415
3240
  lines.push(`${indent}\u{1F4C1} ${entry.name}/`);
3416
3241
  if (recursive) {
3417
- listRecursive(join3(basePath, entry.name), indent + " ", true, lines);
3242
+ listRecursive(join2(basePath, entry.name), indent + " ", true, lines);
3418
3243
  }
3419
3244
  } else {
3420
3245
  try {
3421
- const stat = statSync3(join3(basePath, entry.name));
3246
+ const stat = statSync3(join2(basePath, entry.name));
3422
3247
  const size = formatSize(stat.size);
3423
3248
  lines.push(`${indent}\u{1F4C4} ${entry.name} (${size})`);
3424
3249
  } catch {
@@ -3434,9 +3259,9 @@ function formatSize(bytes) {
3434
3259
  }
3435
3260
 
3436
3261
  // src/tools/builtin/grep-files.ts
3437
- import { readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync4, existsSync as existsSync9 } from "fs";
3262
+ import { readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4, existsSync as existsSync8 } from "fs";
3438
3263
  import { readFile } from "fs/promises";
3439
- import { join as join4, relative } from "path";
3264
+ import { join as join3, relative } from "path";
3440
3265
  var grepFilesTool = {
3441
3266
  definition: {
3442
3267
  name: "grep_files",
@@ -3487,7 +3312,7 @@ Supports regex. Automatically skips node_modules, dist, .git directories.`,
3487
3312
  const contextLines = Math.max(0, Number(args["context_lines"] ?? 0));
3488
3313
  const maxResults = Math.max(1, Number(args["max_results"] ?? 50));
3489
3314
  if (!pattern) throw new ToolError("grep_files", "pattern is required");
3490
- if (!existsSync9(rootPath)) throw new ToolError("grep_files", `Path not found: ${rootPath}`);
3315
+ if (!existsSync8(rootPath)) throw new ToolError("grep_files", `Path not found: ${rootPath}`);
3491
3316
  const MAX_PATTERN_LENGTH = 1e3;
3492
3317
  if (pattern.length > MAX_PATTERN_LENGTH) {
3493
3318
  throw new ToolError("grep_files", `Pattern too long (${pattern.length} chars, max ${MAX_PATTERN_LENGTH}). Use a shorter pattern.`);
@@ -3581,11 +3406,11 @@ function collectFilePaths(rootPath, filePattern, maxFiles) {
3581
3406
  if (paths.length >= maxFiles) return;
3582
3407
  if (entry.isDirectory()) {
3583
3408
  if (SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
3584
- walk(join4(dirPath, entry.name));
3409
+ walk(join3(dirPath, entry.name));
3585
3410
  } else if (entry.isFile()) {
3586
3411
  if (isBinary(entry.name)) continue;
3587
3412
  if (filePattern && !matchesFilePattern(entry.name, filePattern)) continue;
3588
- const fullPath = join4(dirPath, entry.name);
3413
+ const fullPath = join3(dirPath, entry.name);
3589
3414
  try {
3590
3415
  if (statSync4(fullPath).size > 1e6) continue;
3591
3416
  } catch {
@@ -3640,7 +3465,7 @@ function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, re
3640
3465
  }
3641
3466
  let content;
3642
3467
  try {
3643
- content = readFileSync7(fullPath, "utf-8");
3468
+ content = readFileSync6(fullPath, "utf-8");
3644
3469
  } catch {
3645
3470
  return;
3646
3471
  }
@@ -3671,8 +3496,8 @@ function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, re
3671
3496
  }
3672
3497
 
3673
3498
  // src/tools/builtin/glob-files.ts
3674
- import { readdirSync as readdirSync5, statSync as statSync5, existsSync as existsSync10 } from "fs";
3675
- import { join as join5, relative as relative2, basename as basename4 } from "path";
3499
+ import { readdirSync as readdirSync5, statSync as statSync5, existsSync as existsSync9 } from "fs";
3500
+ import { join as join4, relative as relative2, basename as basename4 } from "path";
3676
3501
  var globFilesTool = {
3677
3502
  definition: {
3678
3503
  name: "glob_files",
@@ -3705,7 +3530,7 @@ Results sorted by most recent modification time. Automatically skips node_module
3705
3530
  const rootPath = String(args["path"] ?? process.cwd());
3706
3531
  const maxResults = Math.max(1, Number(args["max_results"] ?? 100));
3707
3532
  if (!pattern) throw new ToolError("glob_files", "pattern is required");
3708
- if (!existsSync10(rootPath)) throw new ToolError("glob_files", `Path not found: ${rootPath}`);
3533
+ if (!existsSync9(rootPath)) throw new ToolError("glob_files", `Path not found: ${rootPath}`);
3709
3534
  const regex = globToRegex(pattern);
3710
3535
  const matches = [];
3711
3536
  collectMatchingFiles(rootPath, rootPath, regex, matches, maxResults);
@@ -3782,7 +3607,7 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
3782
3607
  }
3783
3608
  for (const entry of entries) {
3784
3609
  if (results.length >= maxResults) break;
3785
- const fullPath = join5(dirPath, entry.name);
3610
+ const fullPath = join4(dirPath, entry.name);
3786
3611
  if (entry.isDirectory()) {
3787
3612
  if (SKIP_DIRS2.has(entry.name) || entry.name.startsWith(".")) continue;
3788
3613
  collectMatchingFiles(fullPath, rootPath, regex, results, maxResults);
@@ -4522,7 +4347,7 @@ ${preamble}`;
4522
4347
  }
4523
4348
 
4524
4349
  // src/tools/builtin/save-last-response.ts
4525
- import { mkdirSync as mkdirSync3, unlinkSync as unlinkSync2, rmdirSync as rmdirSync2 } from "fs";
4350
+ import { mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, rmdirSync as rmdirSync2 } from "fs";
4526
4351
  import { dirname as dirname3 } from "path";
4527
4352
  var lastResponseStore = { content: "" };
4528
4353
  function cleanupRejectedTeeFile(filePath) {
@@ -4572,7 +4397,7 @@ Any of these triggers means use save_last_response, NOT write_file:
4572
4397
  throw new ToolError("save_last_response", "No content to save: AI has not produced any response yet, or the last response was empty.");
4573
4398
  }
4574
4399
  undoStack.push(filePath, `save_last_response: ${filePath}`);
4575
- mkdirSync3(dirname3(filePath), { recursive: true });
4400
+ mkdirSync2(dirname3(filePath), { recursive: true });
4576
4401
  atomicWriteFileSync(filePath, content);
4577
4402
  const lines = content.split("\n").length;
4578
4403
  return `File saved: ${filePath} (${lines} lines, ${content.length} bytes)`;
@@ -4580,18 +4405,18 @@ Any of these triggers means use save_last_response, NOT write_file:
4580
4405
  };
4581
4406
 
4582
4407
  // src/tools/builtin/save-memory.ts
4583
- import { join as join7 } from "path";
4408
+ import { join as join6 } from "path";
4584
4409
  import { homedir as homedir3 } from "os";
4585
4410
 
4586
4411
  // src/memory/persistent-memory.ts
4587
- import { existsSync as existsSync11, mkdirSync as mkdirSync4, readFileSync as readFileSync8 } from "fs";
4588
- import { randomUUID, createHash as createHash2 } from "crypto";
4589
- import { dirname as dirname4, join as join6, resolve as resolve6 } from "path";
4412
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync7 } from "fs";
4413
+ import { randomUUID, createHash } from "crypto";
4414
+ import { dirname as dirname4, join as join5, resolve as resolve6 } from "path";
4590
4415
  function memoryStorePath(configDir) {
4591
- return join6(configDir, MEMORY_STORE_FILE_NAME);
4416
+ return join5(configDir, MEMORY_STORE_FILE_NAME);
4592
4417
  }
4593
4418
  function memoryMarkdownPath(configDir) {
4594
- return join6(configDir, MEMORY_FILE_NAME);
4419
+ return join5(configDir, MEMORY_FILE_NAME);
4595
4420
  }
4596
4421
  function getProjectKey(cwd = process.cwd()) {
4597
4422
  return resolve6(getGitRoot(cwd) ?? cwd);
@@ -4627,8 +4452,8 @@ function normalizeEntry(value) {
4627
4452
  }
4628
4453
  function legacyEntriesFromMarkdown(configDir) {
4629
4454
  const file = memoryMarkdownPath(configDir);
4630
- if (!existsSync11(file)) return [];
4631
- const content = readFileSync8(file, "utf-8").trim();
4455
+ if (!existsSync10(file)) return [];
4456
+ const content = readFileSync7(file, "utf-8").trim();
4632
4457
  if (!content) return [];
4633
4458
  const parts = content.split(/\n(?=##\s+\d{4}-\d{2}-\d{2})/g);
4634
4459
  const chunks = parts.length > 1 ? parts : [content];
@@ -4637,15 +4462,15 @@ function legacyEntriesFromMarkdown(configDir) {
4637
4462
  const body = (match ? match[2] : chunk).trim();
4638
4463
  const parsed = match ? Date.parse(match[1].replace(" ", "T")) : NaN;
4639
4464
  const createdAt = Number.isFinite(parsed) ? new Date(parsed).toISOString() : nowIso();
4640
- const id = "legacy-" + createHash2("sha1").update(`${index}
4465
+ const id = "legacy-" + createHash("sha1").update(`${index}
4641
4466
  ${chunk}`).digest("hex").slice(0, 12);
4642
4467
  return normalizeEntry({ id, content: body, scope: "personal", createdAt, updatedAt: createdAt, sensitivity: "low", approved: true });
4643
4468
  }).filter((entry) => Boolean(entry));
4644
4469
  }
4645
4470
  function loadMemoryEntries(configDir) {
4646
4471
  const file = memoryStorePath(configDir);
4647
- if (!existsSync11(file)) return legacyEntriesFromMarkdown(configDir);
4648
- const text = readFileSync8(file, "utf-8").trim();
4472
+ if (!existsSync10(file)) return legacyEntriesFromMarkdown(configDir);
4473
+ const text = readFileSync7(file, "utf-8").trim();
4649
4474
  if (!text) return [];
4650
4475
  const entries = [];
4651
4476
  for (const line of text.split("\n")) {
@@ -4660,7 +4485,7 @@ function loadMemoryEntries(configDir) {
4660
4485
  return entries;
4661
4486
  }
4662
4487
  function saveMemoryEntries(configDir, entries) {
4663
- mkdirSync4(configDir, { recursive: true });
4488
+ mkdirSync3(configDir, { recursive: true });
4664
4489
  const jsonl = entries.map((entry) => JSON.stringify(entry)).join("\n");
4665
4490
  atomicWriteFileSync(memoryStorePath(configDir), jsonl ? jsonl + "\n" : "");
4666
4491
  syncLegacyMarkdown(configDir, entries);
@@ -4735,7 +4560,7 @@ function findUnique(entries, idPrefix) {
4735
4560
  return matches[0];
4736
4561
  }
4737
4562
  function syncLegacyMarkdown(configDir, entries = loadMemoryEntries(configDir)) {
4738
- mkdirSync4(dirname4(memoryMarkdownPath(configDir)), { recursive: true });
4563
+ mkdirSync3(dirname4(memoryMarkdownPath(configDir)), { recursive: true });
4739
4564
  const active = entries.filter((entry) => entry.approved && !isMemoryExpired(entry));
4740
4565
  const markdown = active.map((entry) => {
4741
4566
  const date = entry.createdAt.replace("T", " ").slice(0, 19);
@@ -4778,7 +4603,7 @@ ${entry.content}`;
4778
4603
 
4779
4604
  // src/tools/builtin/save-memory.ts
4780
4605
  function getConfigDir() {
4781
- return join7(homedir3(), CONFIG_DIR_NAME);
4606
+ return join6(homedir3(), CONFIG_DIR_NAME);
4782
4607
  }
4783
4608
  function parseScope(value) {
4784
4609
  return value === "personal" || value === "project" || value === "session" || value === "team" ? value : void 0;
@@ -5112,8 +4937,8 @@ function formatResults2(query, data, _requested) {
5112
4937
  }
5113
4938
 
5114
4939
  // src/agents/agent-config.ts
5115
- import { existsSync as existsSync12, readdirSync as readdirSync6, readFileSync as readFileSync9 } from "fs";
5116
- import { join as join8 } from "path";
4940
+ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync8 } from "fs";
4941
+ import { join as join7 } from "path";
5117
4942
  import { homedir as homedir4 } from "os";
5118
4943
  var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
5119
4944
  "read_file",
@@ -5208,13 +5033,13 @@ function parseAgentConfig(raw, source, path3) {
5208
5033
  return cfg;
5209
5034
  }
5210
5035
  function loadAgentDir(dir, source) {
5211
- if (!existsSync12(dir)) return [];
5036
+ if (!existsSync11(dir)) return [];
5212
5037
  const out = [];
5213
5038
  for (const file of readdirSync6(dir)) {
5214
5039
  if (!file.endsWith(".json")) continue;
5215
- const path3 = join8(dir, file);
5040
+ const path3 = join7(dir, file);
5216
5041
  try {
5217
- const parsed = JSON.parse(readFileSync9(path3, "utf-8"));
5042
+ const parsed = JSON.parse(readFileSync8(path3, "utf-8"));
5218
5043
  const cfg = parseAgentConfig(parsed, source, path3);
5219
5044
  if (cfg) out.push(cfg);
5220
5045
  } catch {
@@ -5224,8 +5049,8 @@ function loadAgentDir(dir, source) {
5224
5049
  }
5225
5050
  function getAgentDirs(configDir, cwd = process.cwd()) {
5226
5051
  return {
5227
- user: join8(configDir ?? join8(homedir4(), CONFIG_DIR_NAME), "agents"),
5228
- project: join8(cwd, CONFIG_DIR_NAME, "agents")
5052
+ user: join7(configDir ?? join7(homedir4(), CONFIG_DIR_NAME), "agents"),
5053
+ project: join7(cwd, CONFIG_DIR_NAME, "agents")
5229
5054
  };
5230
5055
  }
5231
5056
  function listAgentConfigs(configDir, cwd = process.cwd()) {
@@ -5233,6 +5058,11 @@ function listAgentConfigs(configDir, cwd = process.cwd()) {
5233
5058
  const byName = /* @__PURE__ */ new Map();
5234
5059
  for (const cfg of BUILTIN_AGENTS) byName.set(normalizeName(cfg.name), { ...cfg });
5235
5060
  for (const cfg of loadAgentDir(dirs.user, "user")) byName.set(normalizeName(cfg.name), cfg);
5061
+ if (configDir) {
5062
+ for (const dir of getActivePluginAssets(configDir).agentDirs) {
5063
+ for (const cfg of loadAgentDir(dir, "plugin")) byName.set(normalizeName(cfg.name), cfg);
5064
+ }
5065
+ }
5236
5066
  for (const cfg of loadAgentDir(dirs.project, "project")) byName.set(normalizeName(cfg.name), cfg);
5237
5067
  return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
5238
5068
  }
@@ -5935,14 +5765,14 @@ var taskStopTool = {
5935
5765
 
5936
5766
  // src/tools/builtin/git-tools.ts
5937
5767
  import { execFileSync as execFileSync2 } from "child_process";
5938
- import { existsSync as existsSync13 } from "fs";
5939
- import { join as join9 } from "path";
5768
+ import { existsSync as existsSync12 } from "fs";
5769
+ import { join as join8 } from "path";
5940
5770
  function assertGitRepo(cwd) {
5941
5771
  let dir = cwd;
5942
5772
  const root = dir.split(/[\\/]/)[0] + (dir.includes("\\") ? "\\" : "/");
5943
5773
  while (dir && dir !== root) {
5944
- if (existsSync13(join9(dir, ".git"))) return;
5945
- const parent = join9(dir, "..");
5774
+ if (existsSync12(join8(dir, ".git"))) return;
5775
+ const parent = join8(dir, "..");
5946
5776
  if (parent === dir) break;
5947
5777
  dir = parent;
5948
5778
  }
@@ -6207,7 +6037,7 @@ ${commitOutput.trim()}`;
6207
6037
  };
6208
6038
 
6209
6039
  // src/tools/builtin/notebook-edit.ts
6210
- import { readFileSync as readFileSync10, existsSync as existsSync14 } from "fs";
6040
+ import { readFileSync as readFileSync9, existsSync as existsSync13 } from "fs";
6211
6041
  import { writeFile } from "fs/promises";
6212
6042
  import { resolve as resolve7, extname as extname2 } from "path";
6213
6043
  var notebookEditTool = {
@@ -6262,10 +6092,10 @@ var notebookEditTool = {
6262
6092
  if (extname2(absPath).toLowerCase() !== ".ipynb") {
6263
6093
  throw new ToolError("notebook_edit", "path must point to a .ipynb file");
6264
6094
  }
6265
- if (!existsSync14(absPath)) {
6095
+ if (!existsSync13(absPath)) {
6266
6096
  throw new ToolError("notebook_edit", `Notebook not found: ${filePath}`);
6267
6097
  }
6268
- const raw = readFileSync10(absPath, "utf-8");
6098
+ const raw = readFileSync9(absPath, "utf-8");
6269
6099
  const nb = parseNotebook(raw);
6270
6100
  const cellIdx0 = cellIndexRaw - 1;
6271
6101
  undoStack.push(absPath, `notebook_edit (${action}): ${filePath}`);
@@ -6682,8 +6512,8 @@ function estimateToolDefinitionTokens(def) {
6682
6512
 
6683
6513
  // src/tools/registry.ts
6684
6514
  import { pathToFileURL } from "url";
6685
- import { existsSync as existsSync15, mkdirSync as mkdirSync5, readdirSync as readdirSync7 } from "fs";
6686
- import { join as join10 } from "path";
6515
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, readdirSync as readdirSync7 } from "fs";
6516
+ import { join as join9 } from "path";
6687
6517
  var ToolRegistry = class {
6688
6518
  tools = /* @__PURE__ */ new Map();
6689
6519
  pluginToolNames = /* @__PURE__ */ new Set();
@@ -6844,9 +6674,9 @@ var ToolRegistry = class {
6844
6674
  * Returns the number of successfully loaded plugins.
6845
6675
  */
6846
6676
  async loadPlugins(pluginsDir, allowPlugins = false) {
6847
- if (!existsSync15(pluginsDir)) {
6677
+ if (!existsSync14(pluginsDir)) {
6848
6678
  try {
6849
- mkdirSync5(pluginsDir, { recursive: true });
6679
+ mkdirSync4(pluginsDir, { recursive: true });
6850
6680
  } catch {
6851
6681
  }
6852
6682
  return 0;
@@ -6870,12 +6700,12 @@ var ToolRegistry = class {
6870
6700
  process.stderr.write(
6871
6701
  `
6872
6702
  [plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
6873
- ` + files.map((f) => ` + ${join10(pluginsDir, f)}`).join("\n") + "\n\n"
6703
+ ` + files.map((f) => ` + ${join9(pluginsDir, f)}`).join("\n") + "\n\n"
6874
6704
  );
6875
6705
  let loaded = 0;
6876
6706
  for (const file of files) {
6877
6707
  try {
6878
- const fileUrl = pathToFileURL(join10(pluginsDir, file)).href;
6708
+ const fileUrl = pathToFileURL(join9(pluginsDir, file)).href;
6879
6709
  const mod = await import(fileUrl);
6880
6710
  const tool = mod.tool ?? mod.default?.tool ?? mod.default;
6881
6711
  if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
@@ -6907,12 +6737,6 @@ export {
6907
6737
  theme,
6908
6738
  undoStack,
6909
6739
  renderDiff,
6910
- listHooks,
6911
- trustHook,
6912
- untrustHook,
6913
- getPendingHookTrust,
6914
- runLifecycleHooks,
6915
- runHook,
6916
6740
  recordRecentlyDeniedAutoAction,
6917
6741
  getRecentlyDeniedAutoActions,
6918
6742
  clearRecentlyDeniedAutoActions,