jinzd-ai-cli 0.4.218 → 0.4.220

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 (33) hide show
  1. package/README.md +102 -99
  2. package/README.zh-CN.md +40 -38
  3. package/dist/{batch-7V7OTMUP.js → batch-QBSKTLTO.js} +3 -3
  4. package/dist/{chunk-TZQHYZKT.js → chunk-5ULLIOVC.js} +1 -0
  5. package/dist/{chunk-P4VBLXKS.js → chunk-5WBNXYDJ.js} +2 -2
  6. package/dist/chunk-ALQN7VUJ.js +604 -0
  7. package/dist/{chunk-C2Z42DI5.js → chunk-CAUHLHDR.js} +1 -1
  8. package/dist/{chunk-GX3HSGJX.js → chunk-IZW5LMI6.js} +166 -638
  9. package/dist/chunk-P3LKFA54.js +639 -0
  10. package/dist/{chunk-5CA2TJ5F.js → chunk-P4DYAGUI.js} +1 -1
  11. package/dist/{chunk-L4UREAID.js → chunk-P4PTXCHY.js} +6 -5
  12. package/dist/{chunk-QMXC327F.js → chunk-PUBCJF7E.js} +213 -175
  13. package/dist/{chunk-NTCB7CMT.js → chunk-QZYNRCPX.js} +1 -1
  14. package/dist/{chunk-H2UIHGHH.js → chunk-VHX7KZDY.js} +29 -189
  15. package/dist/{chunk-VGFTM3XT.js → chunk-Y25MSSUP.js} +1 -1
  16. package/dist/{ci-L6GH2WVC.js → ci-5SNXGM3M.js} +6 -6
  17. package/dist/{ci-format-WW7454AY.js → ci-format-57QQTHQE.js} +2 -2
  18. package/dist/{constants-NCTFSHDU.js → constants-ML5KFEOH.js} +1 -1
  19. package/dist/doctor-cli-ZRH3XZ3R.js +17 -0
  20. package/dist/electron-server.js +836 -470
  21. package/dist/{hub-CDL6T7CP.js → hub-IPLMJ6TJ.js} +1 -1
  22. package/dist/index.js +125 -194
  23. package/dist/{pr-D6PEKEGK.js → pr-GJYDAPK4.js} +8 -7
  24. package/dist/{run-tests-NXVVKAK2.js → run-tests-GK5AIAV2.js} +1 -1
  25. package/dist/{run-tests-SWU2XEV7.js → run-tests-KLQAI5CX.js} +2 -2
  26. package/dist/{server-WUT7VYTD.js → server-5FZDALHH.js} +10 -10
  27. package/dist/{server-LHYSS6CK.js → server-RU36PRSH.js} +74 -83
  28. package/dist/{task-orchestrator-C5AA2BI5.js → task-orchestrator-JMHPVNUO.js} +10 -10
  29. package/dist/{usage-6ZUUJBI2.js → usage-IRMRCCKN.js} +3 -3
  30. package/package.json +1 -1
  31. package/dist/chunk-MWKE2TNS.js +0 -129
  32. package/dist/chunk-OUC75QCF.js +0 -166
  33. package/dist/doctor-cli-EWMFBP5Q.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-VGFTM3XT.js";
11
+ } from "./chunk-Y25MSSUP.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-MWKE2TNS.js";
28
+ } from "./chunk-ALQN7VUJ.js";
12
29
  import {
13
30
  getDangerLevel,
14
31
  isFileWriteTool,
@@ -18,35 +35,20 @@ import {
18
35
  EnvLoader,
19
36
  NetworkError,
20
37
  ToolError
21
- } from "./chunk-TZQHYZKT.js";
38
+ } from "./chunk-5ULLIOVC.js";
22
39
  import {
23
40
  CONFIG_DIR_NAME,
24
41
  DEFAULT_MAX_TOOL_OUTPUT_CHARS_CAP,
25
42
  MEMORY_FILE_NAME,
26
43
  MEMORY_MAX_CHARS,
27
44
  MEMORY_STORE_FILE_NAME,
28
- PLUGINS_DIR_NAME,
29
45
  SUBAGENT_ALLOWED_TOOLS,
30
46
  SUBAGENT_DEFAULT_MAX_ROUNDS,
31
47
  SUBAGENT_MAX_ROUNDS_LIMIT
32
- } from "./chunk-NTCB7CMT.js";
48
+ } from "./chunk-QZYNRCPX.js";
33
49
  import {
34
50
  getGitRoot
35
51
  } from "./chunk-HOSJZMQS.js";
36
- import {
37
- fileCheckpoints
38
- } from "./chunk-4BKXL7SM.js";
39
- import {
40
- loadChatIndex,
41
- searchChatMemory
42
- } from "./chunk-TB4W4Y4T.js";
43
- import {
44
- DEFAULT_PATTERNS,
45
- redactString
46
- } from "./chunk-SLSWPBK3.js";
47
- import {
48
- indexProject
49
- } from "./chunk-K3CF65QH.js";
50
52
  import {
51
53
  loadIndex
52
54
  } from "./chunk-CKH4KQ4E.js";
@@ -54,295 +56,14 @@ import {
54
56
  atomicWriteFileSync
55
57
  } from "./chunk-IW3Q7AE5.js";
56
58
 
57
- // src/plugins/plugin-manager.ts
58
- import { existsSync, mkdirSync, readdirSync, readFileSync, cpSync, rmSync, statSync } from "fs";
59
- import { basename, dirname, join, resolve } from "path";
60
- import { createHash } from "crypto";
61
- import { z } from "zod";
62
- var MANIFEST_RELATIVE = ".aicli-plugin/plugin.json";
63
- var STATE_FILE = "plugin-state.json";
64
- var HookCommandSchema = z.union([
65
- z.string(),
66
- z.object({
67
- command: z.string(),
68
- source: z.enum(["user", "project", "managed"]).optional(),
69
- description: z.string().optional(),
70
- required: z.boolean().optional(),
71
- timeoutMs: z.number().int().min(100).max(3e4).optional(),
72
- disabled: z.boolean().optional()
73
- }),
74
- z.array(z.union([
75
- z.string(),
76
- z.object({
77
- command: z.string(),
78
- source: z.enum(["user", "project", "managed"]).optional(),
79
- description: z.string().optional(),
80
- required: z.boolean().optional(),
81
- timeoutMs: z.number().int().min(100).max(3e4).optional(),
82
- disabled: z.boolean().optional()
83
- })
84
- ]))
85
- ]);
86
- var HookEventNameSchema = z.enum([
87
- "SessionStart",
88
- "UserPromptSubmit",
89
- "PreToolUse",
90
- "PermissionRequest",
91
- "PostToolUse",
92
- "PreCompact",
93
- "PostCompact",
94
- "Stop",
95
- "SubagentStart",
96
- "SubagentStop"
97
- ]);
98
- var McpServerSchema = z.object({
99
- command: z.string(),
100
- args: z.array(z.string()).default([]),
101
- env: z.record(z.string()).optional(),
102
- timeout: z.number().default(3e4)
103
- });
104
- var PluginManifestSchema = z.object({
105
- name: z.string().regex(/^[a-zA-Z0-9._-]{1,80}$/),
106
- version: z.string().min(1),
107
- description: z.string().optional(),
108
- skills: z.array(z.string()).default([]),
109
- hooks: z.object({
110
- enabled: z.boolean().optional(),
111
- events: z.record(HookEventNameSchema, HookCommandSchema).default({})
112
- }).default({ events: {} }),
113
- commands: z.array(z.string()).default([]),
114
- mcpServers: z.record(McpServerSchema).default({}),
115
- agents: z.array(z.string()).default([]),
116
- permissionHints: z.array(z.string()).default([])
117
- }).strict();
118
- function pluginRoot(configDir) {
119
- return join(configDir, PLUGINS_DIR_NAME);
120
- }
121
- function pluginManifestPath(pluginDir) {
122
- return join(pluginDir, MANIFEST_RELATIVE);
123
- }
124
- function statePath(configDir) {
125
- return join(pluginRoot(configDir), STATE_FILE);
126
- }
127
- function loadState(configDir) {
128
- const file = statePath(configDir);
129
- if (!existsSync(file)) return { version: 1, plugins: [] };
130
- try {
131
- const parsed = JSON.parse(readFileSync(file, "utf-8"));
132
- return { version: 1, plugins: Array.isArray(parsed.plugins) ? parsed.plugins : [] };
133
- } catch {
134
- return { version: 1, plugins: [] };
135
- }
136
- }
137
- function saveState(configDir, state) {
138
- mkdirSync(pluginRoot(configDir), { recursive: true });
139
- atomicWriteFileSync(statePath(configDir), JSON.stringify(state, null, 2));
140
- }
141
- function hashPluginManifest(manifestPath) {
142
- return createHash("sha256").update(readFileSync(manifestPath)).digest("hex");
143
- }
144
- function readPluginManifest(manifestPath) {
145
- return PluginManifestSchema.parse(JSON.parse(readFileSync(manifestPath, "utf-8")));
146
- }
147
- function findPluginSourceDir(inputPath) {
148
- const abs = resolve(inputPath);
149
- const direct = statSync(abs).isDirectory() ? abs : dirname(abs);
150
- if (existsSync(pluginManifestPath(direct))) return direct;
151
- const nested = join(direct, ".aicli-plugin");
152
- if (existsSync(join(nested, "plugin.json"))) return direct;
153
- throw new Error(`plugin manifest not found: ${MANIFEST_RELATIVE}`);
154
- }
155
- function installPlugin(configDir, inputPath) {
156
- const sourceDir = findPluginSourceDir(inputPath);
157
- const manifest = readPluginManifest(pluginManifestPath(sourceDir));
158
- const targetDir = join(pluginRoot(configDir), manifest.name);
159
- mkdirSync(pluginRoot(configDir), { recursive: true });
160
- if (existsSync(targetDir)) rmSync(targetDir, { recursive: true, force: true });
161
- cpSync(sourceDir, targetDir, { recursive: true });
162
- const manifestPath = pluginManifestPath(targetDir);
163
- const hash = hashPluginManifest(manifestPath);
164
- const state = loadState(configDir);
165
- const previous = state.plugins.find((p) => p.name === manifest.name);
166
- const next = {
167
- name: manifest.name,
168
- enabled: previous?.enabled ?? false,
169
- trusted: false,
170
- hash,
171
- installedAt: (/* @__PURE__ */ new Date()).toISOString()
172
- };
173
- state.plugins = [...state.plugins.filter((p) => p.name !== manifest.name), next];
174
- saveState(configDir, state);
175
- return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash, enabled: next.enabled, trusted: false, valid: true };
176
- }
177
- function setPluginEnabled(configDir, name, enabled) {
178
- const plugin = getInstalledPlugin(configDir, name);
179
- if (!plugin.valid) throw new Error(plugin.error ?? `invalid plugin: ${name}`);
180
- const state = loadState(configDir);
181
- const current = state.plugins.find((p) => p.name === plugin.name) ?? {
182
- name: plugin.name,
183
- enabled: false,
184
- trusted: false,
185
- hash: plugin.hash,
186
- installedAt: (/* @__PURE__ */ new Date()).toISOString()
187
- };
188
- const next = { ...current, enabled, hash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
189
- state.plugins = [...state.plugins.filter((p) => p.name !== plugin.name), next];
190
- saveState(configDir, state);
191
- return next;
192
- }
193
- function trustPlugin(configDir, name) {
194
- const plugin = getInstalledPlugin(configDir, name);
195
- if (!plugin.valid) throw new Error(plugin.error ?? `invalid plugin: ${name}`);
196
- const state = loadState(configDir);
197
- const current = state.plugins.find((p) => p.name === plugin.name) ?? {
198
- name: plugin.name,
199
- enabled: false,
200
- trusted: false,
201
- hash: plugin.hash,
202
- installedAt: (/* @__PURE__ */ new Date()).toISOString()
203
- };
204
- const next = { ...current, trusted: true, hash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
205
- state.plugins = [...state.plugins.filter((p) => p.name !== plugin.name), next];
206
- saveState(configDir, state);
207
- return next;
208
- }
209
- function getInstalledPlugin(configDir, name) {
210
- const plugins = listInstalledPlugins(configDir);
211
- const matches = plugins.filter((p) => p.name === name || p.name.startsWith(name));
212
- if (matches.length === 0) throw new Error(`plugin not found: ${name}`);
213
- if (matches.length > 1) throw new Error(`plugin name is ambiguous: ${name}`);
214
- return matches[0];
215
- }
216
- function listInstalledPlugins(configDir) {
217
- const root = pluginRoot(configDir);
218
- if (!existsSync(root)) return [];
219
- const state = loadState(configDir);
220
- const out = [];
221
- for (const entry of readdirSync(root)) {
222
- const dir = join(root, entry);
223
- try {
224
- if (!statSync(dir).isDirectory()) continue;
225
- } catch {
226
- continue;
227
- }
228
- const manifestPath = pluginManifestPath(dir);
229
- if (!existsSync(manifestPath)) continue;
230
- try {
231
- const manifest = readPluginManifest(manifestPath);
232
- const hash = hashPluginManifest(manifestPath);
233
- const st = state.plugins.find((p) => p.name === manifest.name);
234
- const trusted = st?.trusted === true && st.hash === hash;
235
- out.push({
236
- name: manifest.name,
237
- dir,
238
- manifestPath,
239
- manifest,
240
- hash,
241
- enabled: st?.enabled === true,
242
- trusted,
243
- valid: true
244
- });
245
- } catch (err) {
246
- out.push({
247
- name: entry,
248
- dir,
249
- manifestPath,
250
- manifest: { name: entry, version: "invalid", skills: [], commands: [], agents: [], hooks: { events: {} }, mcpServers: {}, permissionHints: [] },
251
- hash: "",
252
- enabled: false,
253
- trusted: false,
254
- valid: false,
255
- error: err instanceof Error ? err.message : String(err)
256
- });
257
- }
258
- }
259
- return out.sort((a, b) => a.name.localeCompare(b.name));
260
- }
261
- function activePlugins(configDir) {
262
- return listInstalledPlugins(configDir).filter((p) => p.valid && p.enabled && p.trusted);
263
- }
264
- function uniqueDirs(plugin, rels) {
265
- const dirs = /* @__PURE__ */ new Set();
266
- for (const rel of rels) {
267
- const abs = resolve(plugin.dir, rel);
268
- if (!abs.startsWith(resolve(plugin.dir))) continue;
269
- if (existsSync(abs)) dirs.add(statSync(abs).isDirectory() ? abs : dirname(abs));
270
- }
271
- return [...dirs];
272
- }
273
- function prefixCommand(plugin, command) {
274
- return command.replaceAll("{pluginDir}", plugin.dir).replaceAll("$PLUGIN_DIR", plugin.dir);
275
- }
276
- function pluginHooks(plugin) {
277
- const events = plugin.manifest.hooks?.events ?? {};
278
- const out = {};
279
- for (const [event, raw] of Object.entries(events)) {
280
- const normalize = (item) => {
281
- if (typeof item === "string") return { command: prefixCommand(plugin, item), source: "project", description: `plugin:${plugin.name}` };
282
- if (item && typeof item === "object") {
283
- const obj = item;
284
- return { ...obj, command: prefixCommand(plugin, String(obj.command ?? "")), source: "project", description: obj.description ?? `plugin:${plugin.name}` };
285
- }
286
- return item;
287
- };
288
- out[event] = Array.isArray(raw) ? raw.map(normalize) : normalize(raw);
289
- }
290
- return Object.keys(out).length > 0 ? { enabled: plugin.manifest.hooks?.enabled ?? true, events: out } : void 0;
291
- }
292
- function mergePluginHooks(base, configDir) {
293
- const plugins = activePlugins(configDir);
294
- if (plugins.length === 0) return base;
295
- const merged = { ...base ?? {}, enabled: base?.enabled ?? true, events: { ...base?.events ?? {} } };
296
- for (const plugin of plugins) {
297
- const hooks = pluginHooks(plugin);
298
- if (!hooks?.events) continue;
299
- for (const [event, entry] of Object.entries(hooks.events)) {
300
- const key = event;
301
- const existing = merged.events?.[key];
302
- const existingItems = existing === void 0 ? [] : Array.isArray(existing) ? existing : [existing];
303
- const newItems = Array.isArray(entry) ? entry : [entry];
304
- merged.events[key] = [...existingItems, ...newItems];
305
- }
306
- }
307
- return merged;
308
- }
309
- function getActivePluginAssets(configDir) {
310
- const plugins = activePlugins(configDir);
311
- const mcpServers = {};
312
- const skillDirs = [];
313
- const commandDirs = [];
314
- const agentDirs = [];
315
- for (const plugin of plugins) {
316
- skillDirs.push(...uniqueDirs(plugin, plugin.manifest.skills));
317
- commandDirs.push(...uniqueDirs(plugin, plugin.manifest.commands));
318
- agentDirs.push(...uniqueDirs(plugin, plugin.manifest.agents));
319
- for (const [serverName, server] of Object.entries(plugin.manifest.mcpServers)) {
320
- mcpServers[`plugin_${plugin.name}_${serverName}`] = server;
321
- }
322
- }
323
- return { plugins, skillDirs, commandDirs, agentDirs, hooks: mergePluginHooks(void 0, configDir), mcpServers };
324
- }
325
- function describePlugin(plugin) {
326
- const m = plugin.manifest;
327
- return [
328
- `${plugin.name}@${m.version}`,
329
- ` status: ${plugin.enabled ? "enabled" : "disabled"} \xB7 ${plugin.trusted ? "trusted" : "untrusted"}${plugin.valid ? "" : " \xB7 invalid"}`,
330
- ` dir: ${plugin.dir}`,
331
- m.description ? ` description: ${m.description}` : void 0,
332
- ` assets: ${m.skills.length} skill(s), ${m.commands.length} command(s), ${m.agents.length} agent(s), ${Object.keys(m.mcpServers).length} MCP server(s), ${Object.keys(m.hooks?.events ?? {}).length} hook event(s)`,
333
- m.permissionHints.length ? ` permission hints: ${m.permissionHints.join("; ")}` : void 0,
334
- plugin.error ? ` error: ${plugin.error}` : void 0
335
- ].filter((line) => Boolean(line));
336
- }
337
-
338
59
  // src/tools/builtin/bash.ts
339
60
  import { spawn } from "child_process";
340
- import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
61
+ import { existsSync as existsSync2, readdirSync, statSync } from "fs";
341
62
  import { platform as platform2 } from "os";
342
- import { resolve as resolve2 } from "path";
63
+ import { resolve } from "path";
343
64
 
344
65
  // src/tools/undo-stack.ts
345
- import { readFileSync as readFileSync2, writeFileSync, unlinkSync, rmdirSync, existsSync as existsSync2 } from "fs";
66
+ import { readFileSync, writeFileSync, unlinkSync, rmdirSync, existsSync } from "fs";
346
67
  var MAX_UNDO_DEPTH = 20;
347
68
  var UndoStack = class {
348
69
  stack = [];
@@ -353,9 +74,9 @@ var UndoStack = class {
353
74
  */
354
75
  push(filePath, description) {
355
76
  let previousContent = null;
356
- if (existsSync2(filePath)) {
77
+ if (existsSync(filePath)) {
357
78
  try {
358
- previousContent = readFileSync2(filePath, "utf-8");
79
+ previousContent = readFileSync(filePath, "utf-8");
359
80
  } catch {
360
81
  return;
361
82
  }
@@ -409,7 +130,7 @@ var UndoStack = class {
409
130
  try {
410
131
  if (entry.previousContent === null) {
411
132
  if (entry.isDirectory) {
412
- if (existsSync2(entry.filePath)) {
133
+ if (existsSync(entry.filePath)) {
413
134
  try {
414
135
  rmdirSync(entry.filePath);
415
136
  return { entry, result: `Removed newly created directory: ${entry.filePath}` };
@@ -419,7 +140,7 @@ var UndoStack = class {
419
140
  }
420
141
  return { entry, result: `Directory already removed: ${entry.filePath}` };
421
142
  } else {
422
- if (existsSync2(entry.filePath)) {
143
+ if (existsSync(entry.filePath)) {
423
144
  unlinkSync(entry.filePath);
424
145
  }
425
146
  return { entry, result: `Deleted newly created file: ${entry.filePath}` };
@@ -578,7 +299,7 @@ Important rules:
578
299
  throw new ToolError("bash", blockingHint);
579
300
  }
580
301
  let currentCwd = getCwd();
581
- if (!existsSync3(currentCwd)) {
302
+ if (!existsSync2(currentCwd)) {
582
303
  const fallback = process.cwd();
583
304
  process.stderr.write(
584
305
  `[bash] Previous cwd "${currentCwd}" no longer exists, reset to "${fallback}"
@@ -589,8 +310,8 @@ Important rules:
589
310
  }
590
311
  let effectiveCwd = currentCwd;
591
312
  if (cwdArg) {
592
- const resolved = resolve2(currentCwd, cwdArg);
593
- if (!existsSync3(resolved)) {
313
+ const resolved = resolve(currentCwd, cwdArg);
314
+ if (!existsSync2(resolved)) {
594
315
  throw new ToolError(
595
316
  "bash",
596
317
  `cwd directory does not exist: "${resolved}". Create it first (e.g. mkdir -p "${resolved}") before specifying it as cwd.`
@@ -610,7 +331,7 @@ Important rules:
610
331
  const parsedTargets = parseCreationTargets(command, effectiveCwd);
611
332
  const parsedTargetsBefore = /* @__PURE__ */ new Map();
612
333
  for (const t of parsedTargets) {
613
- parsedTargetsBefore.set(t, existsSync3(t));
334
+ parsedTargetsBefore.set(t, existsSync2(t));
614
335
  }
615
336
  try {
616
337
  const { stdout, stderr, status, signal, timedOut, aborted } = await runShell(
@@ -790,7 +511,7 @@ Then poll readiness with SHORT bash calls (these DO exit), e.g.:
790
511
  }
791
512
  function snapshotDir(dir) {
792
513
  try {
793
- return new Set(readdirSync2(dir).map((name) => resolve2(dir, name)));
514
+ return new Set(readdirSync(dir).map((name) => resolve(dir, name)));
794
515
  } catch {
795
516
  return /* @__PURE__ */ new Set();
796
517
  }
@@ -798,25 +519,25 @@ function snapshotDir(dir) {
798
519
  function parseCreationTargets(command, cwd) {
799
520
  const targets = [];
800
521
  for (const m of command.matchAll(/(?:echo|cat|printf)\s+[^>]*>\s*(['"]?)([^\s;&|'"]+)\1/g)) {
801
- if (m[2]) targets.push(resolve2(cwd, m[2]));
522
+ if (m[2]) targets.push(resolve(cwd, m[2]));
802
523
  }
803
524
  for (const m of command.matchAll(/\btouch\s+((?:['"]?[^\s;&|'"]+['"]?\s*)+)/g)) {
804
525
  for (const f of m[1].trim().split(/\s+/)) {
805
526
  const clean = f.replace(/^['"]|['"]$/g, "");
806
- if (clean && !clean.startsWith("-")) targets.push(resolve2(cwd, clean));
527
+ if (clean && !clean.startsWith("-")) targets.push(resolve(cwd, clean));
807
528
  }
808
529
  }
809
530
  for (const m of command.matchAll(/\bmkdir\s+(?:-\w+\s+)*((?:['"]?[^\s;&|'"]+['"]?\s*)+)/g)) {
810
531
  for (const d of m[1].trim().split(/\s+/)) {
811
532
  const clean = d.replace(/^['"]|['"]$/g, "");
812
- if (clean && !clean.startsWith("-")) targets.push(resolve2(cwd, clean));
533
+ if (clean && !clean.startsWith("-")) targets.push(resolve(cwd, clean));
813
534
  }
814
535
  }
815
536
  for (const m of command.matchAll(/\bcp\s+(?:-\w+\s+)*['"]?[^\s;&|'"]+['"]?\s+(['"]?)([^\s;&|'"]+)\1/g)) {
816
- if (m[2]) targets.push(resolve2(cwd, m[2]));
537
+ if (m[2]) targets.push(resolve(cwd, m[2]));
817
538
  }
818
539
  for (const m of command.matchAll(/\bNew-Item\s+(?:-(?:Path|ItemType)\s+\w+\s+)*['"]?([^\s;&|'"]+)['"]?/gi)) {
819
- if (m[1] && !m[1].startsWith("-")) targets.push(resolve2(cwd, m[1]));
540
+ if (m[1] && !m[1].startsWith("-")) targets.push(resolve(cwd, m[1]));
820
541
  }
821
542
  return [...new Set(targets)];
822
543
  }
@@ -826,7 +547,7 @@ function pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, cwd) {
826
547
  for (const absPath of afterSnapshot) {
827
548
  if (!beforeSnapshot.has(absPath)) {
828
549
  try {
829
- const st = statSync2(absPath);
550
+ const st = statSync(absPath);
830
551
  if (st.isDirectory()) {
831
552
  undoStack.pushNewDir(absPath, `bash (new dir): ${absPath}`);
832
553
  } else {
@@ -838,9 +559,9 @@ function pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, cwd) {
838
559
  }
839
560
  }
840
561
  for (const [target, existedBefore] of parsedTargetsBefore) {
841
- if (!existedBefore && !tracked.has(target) && existsSync3(target)) {
562
+ if (!existedBefore && !tracked.has(target) && existsSync2(target)) {
842
563
  try {
843
- const st = statSync2(target);
564
+ const st = statSync(target);
844
565
  if (st.isDirectory()) {
845
566
  undoStack.pushNewDir(target, `bash (new dir): ${target}`);
846
567
  } else {
@@ -950,8 +671,8 @@ function updateCwdFromCommand(command, baseCwd) {
950
671
  const target = lastMatch?.[2];
951
672
  if (!target || target.startsWith("$") || target === "~") return;
952
673
  try {
953
- const newDir = resolve2(baseCwd, target);
954
- if (existsSync3(newDir)) {
674
+ const newDir = resolve(baseCwd, target);
675
+ if (existsSync2(newDir)) {
955
676
  setCwd(newDir);
956
677
  }
957
678
  } catch {
@@ -959,9 +680,9 @@ function updateCwdFromCommand(command, baseCwd) {
959
680
  }
960
681
 
961
682
  // src/tools/builtin/read-file.ts
962
- import { readFileSync as readFileSync3, existsSync as existsSync4, statSync as statSync3, readdirSync as readdirSync3 } from "fs";
683
+ import { readFileSync as readFileSync2, existsSync as existsSync3, statSync as statSync2, readdirSync as readdirSync2 } from "fs";
963
684
  import { execFileSync } from "child_process";
964
- import { extname, resolve as resolve3, basename as basename2, sep, dirname as dirname2 } from "path";
685
+ import { extname, resolve as resolve2, basename, sep, dirname } from "path";
965
686
  import { homedir } from "os";
966
687
 
967
688
  // src/tools/builtin/notebook-utils.ts
@@ -1071,7 +792,7 @@ var MAX_FILE_BYTES = 10 * 1024 * 1024;
1071
792
  function getHardRefusal(normalizedPath) {
1072
793
  const home2 = homedir();
1073
794
  const p = normalizedPath.toLowerCase();
1074
- const base = basename2(normalizedPath).toLowerCase();
795
+ const base = basename(normalizedPath).toLowerCase();
1075
796
  if (normalizedPath.startsWith(home2) && p.includes(".aicli") && base === "config.json") {
1076
797
  return `[Refused] Reading ${normalizedPath} is blocked because it contains all of your provider API keys.
1077
798
  If you genuinely need to inspect or edit it, open it manually outside ai-cli (e.g. via your editor).
@@ -1085,7 +806,7 @@ For programmatic access, use \`aicli config\` or \`aicli config get <key>\` whic
1085
806
  function getSensitiveWarning(normalizedPath) {
1086
807
  const home2 = homedir();
1087
808
  const p = normalizedPath.toLowerCase();
1088
- const base = basename2(normalizedPath).toLowerCase();
809
+ const base = basename(normalizedPath).toLowerCase();
1089
810
  if (normalizedPath.startsWith(home2) && p.includes(".aicli") && base === "config.json") {
1090
811
  return "[\u26A0 Security Warning: This file contains API keys. Be careful not to share this content.]\n\n";
1091
812
  }
@@ -1148,19 +869,19 @@ function isBinaryBuffer(buf) {
1148
869
  return nullCount / sample.length > 0.1;
1149
870
  }
1150
871
  function findSimilarFiles(filePath) {
1151
- const targetName = basename2(filePath).toLowerCase();
872
+ const targetName = basename(filePath).toLowerCase();
1152
873
  if (!targetName) return [];
1153
874
  const cwd = process.cwd();
1154
875
  const candidates = [];
1155
876
  try {
1156
- for (const entry of readdirSync3(cwd, { withFileTypes: true })) {
877
+ for (const entry of readdirSync2(cwd, { withFileTypes: true })) {
1157
878
  if (entry.isFile() && entry.name.toLowerCase() === targetName) {
1158
879
  candidates.push(entry.name);
1159
880
  }
1160
881
  if (entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules") {
1161
882
  try {
1162
- const subDir = resolve3(cwd, entry.name);
1163
- for (const sub of readdirSync3(subDir, { withFileTypes: true })) {
883
+ const subDir = resolve2(cwd, entry.name);
884
+ for (const sub of readdirSync2(subDir, { withFileTypes: true })) {
1164
885
  if (sub.isFile() && sub.name.toLowerCase() === targetName) {
1165
886
  candidates.push(`${entry.name}/${sub.name}`);
1166
887
  }
@@ -1233,10 +954,10 @@ var readFileTool = {
1233
954
  const offsetLine = typeof rawOffset === "number" && Number.isFinite(rawOffset) && rawOffset > 0 ? Math.floor(rawOffset) : void 0;
1234
955
  const limitLines = typeof rawLimit === "number" && Number.isFinite(rawLimit) && rawLimit > 0 ? Math.floor(rawLimit) : void 0;
1235
956
  if (!filePath) throw new ToolError("read_file", "path is required");
1236
- const normalizedPath = resolve3(filePath);
957
+ const normalizedPath = resolve2(filePath);
1237
958
  const refusal = getHardRefusal(normalizedPath);
1238
959
  if (refusal) return refusal;
1239
- if (!existsSync4(normalizedPath)) {
960
+ if (!existsSync3(normalizedPath)) {
1240
961
  const suggestions = findSimilarFiles(filePath);
1241
962
  if (suggestions.length > 0) {
1242
963
  throw new ToolError(
@@ -1255,7 +976,7 @@ Current working directory: ${process.cwd()}
1255
976
  Please use list_dir to verify the file path and retry.`
1256
977
  );
1257
978
  }
1258
- const { size } = statSync3(normalizedPath);
979
+ const { size } = statSync2(normalizedPath);
1259
980
  if (size > MAX_FILE_BYTES) {
1260
981
  const mb = (size / 1024 / 1024).toFixed(1);
1261
982
  return `[File too large: ${filePath} (${mb} MB)]
@@ -1275,13 +996,13 @@ Use the bash tool to read in segments, e.g.:
1275
996
 
1276
997
  ${pdfText}`;
1277
998
  }
1278
- const dir = dirname2(normalizedPath);
1279
- const nameNoExt = basename2(normalizedPath, ext);
1280
- const textAlts = [".md", ".txt", ".html"].map((e) => resolve3(dir, nameNoExt + e)).filter(existsSync4);
999
+ const dir = dirname(normalizedPath);
1000
+ const nameNoExt = basename(normalizedPath, ext);
1001
+ const textAlts = [".md", ".txt", ".html"].map((e) => resolve2(dir, nameNoExt + e)).filter(existsSync3);
1281
1002
  if (textAlts.length > 0) {
1282
1003
  return `[PDF file: ${filePath}]
1283
1004
  Cannot extract text from this PDF, but found alternative text versions:
1284
- ` + textAlts.map((p) => ` \u2192 ${basename2(p)}`).join("\n") + `
1005
+ ` + textAlts.map((p) => ` \u2192 ${basename(p)}`).join("\n") + `
1285
1006
  Please use read_file to read the above files.`;
1286
1007
  }
1287
1008
  return `[PDF file: ${filePath}]
@@ -1290,7 +1011,7 @@ Suggestion: read existing text versions (.md / .txt) in the project, or install
1290
1011
  }
1291
1012
  if (ext === ".ipynb") {
1292
1013
  try {
1293
- const raw = readFileSync3(normalizedPath, "utf-8");
1014
+ const raw = readFileSync2(normalizedPath, "utf-8");
1294
1015
  const nb = parseNotebook(raw);
1295
1016
  return renderNotebookAsText(nb, filePath);
1296
1017
  } catch (err) {
@@ -1303,7 +1024,7 @@ ${err.message}`;
1303
1024
  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.`;
1304
1025
  }
1305
1026
  const { readFile: readFile2 } = await import("fs/promises");
1306
- const buf = size > 1048576 ? await readFile2(normalizedPath) : readFileSync3(normalizedPath);
1027
+ const buf = size > 1048576 ? await readFile2(normalizedPath) : readFileSync2(normalizedPath);
1307
1028
  if (encoding === "base64") {
1308
1029
  return `[File: ${filePath} | base64]
1309
1030
 
@@ -1341,12 +1062,12 @@ ${content}`;
1341
1062
  };
1342
1063
 
1343
1064
  // src/tools/builtin/write-file.ts
1344
- import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
1345
- import { dirname as dirname3 } from "path";
1065
+ import { appendFileSync, mkdirSync } from "fs";
1066
+ import { dirname as dirname2 } from "path";
1346
1067
 
1347
1068
  // src/tools/executor.ts
1348
1069
  import chalk3 from "chalk";
1349
- import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
1070
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "fs";
1350
1071
  import { tmpdir } from "os";
1351
1072
 
1352
1073
  // src/core/readline-internal.ts
@@ -1552,186 +1273,8 @@ function simpleDiff(oldLines, newLines) {
1552
1273
  return result;
1553
1274
  }
1554
1275
 
1555
- // src/tools/hooks.ts
1556
- import { execSync } from "child_process";
1557
- import { createHash as createHash2 } from "crypto";
1558
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "fs";
1559
- import { join as join2 } from "path";
1560
- var TRUST_FILE = "hooks-trust.json";
1561
- var DEFAULT_TIMEOUT_MS = 5e3;
1562
- function asArray(entry) {
1563
- if (!entry) return [];
1564
- const raw = Array.isArray(entry) ? entry : [entry];
1565
- return raw.map((item) => typeof item === "string" ? { command: item } : item);
1566
- }
1567
- function hookTrustPath(configDir) {
1568
- return join2(configDir, TRUST_FILE);
1569
- }
1570
- function loadHookTrustStore(configDir) {
1571
- const file = hookTrustPath(configDir);
1572
- if (!existsSync5(file)) return { records: [] };
1573
- try {
1574
- const parsed = JSON.parse(readFileSync4(file, "utf-8"));
1575
- return { records: Array.isArray(parsed.records) ? parsed.records : [] };
1576
- } catch {
1577
- return { records: [] };
1578
- }
1579
- }
1580
- function saveHookTrustStore(configDir, store) {
1581
- mkdirSync2(configDir, { recursive: true });
1582
- atomicWriteFileSync(hookTrustPath(configDir), JSON.stringify(store, null, 2));
1583
- }
1584
- function hashHook(event, command) {
1585
- return createHash2("sha256").update(`${event}
1586
- ${command}`, "utf-8").digest("hex");
1587
- }
1588
- function isTrusted(source, event, hash, store) {
1589
- if (source === "user" || source === "managed") return true;
1590
- return store.records.some((r) => r.source === source && r.event === event && r.hash === hash);
1591
- }
1592
- function listHooks(config, configDir) {
1593
- if (!config || config.enabled === false) return [];
1594
- const store = loadHookTrustStore(configDir);
1595
- const out = [];
1596
- const push = (event, hook, index) => {
1597
- if (!hook.command) return;
1598
- const source = hook.source ?? "user";
1599
- const hash = hashHook(event, hook.command);
1600
- out.push({
1601
- id: `${event}:${index}`,
1602
- event,
1603
- command: hook.command,
1604
- source,
1605
- hash,
1606
- trusted: isTrusted(source, event, hash, store),
1607
- disabled: hook.disabled === true,
1608
- description: hook.description
1609
- });
1610
- };
1611
- if (config.preToolExecution) push("PreToolUse", { command: config.preToolExecution }, 0);
1612
- if (config.postToolExecution) push("PostToolUse", { command: config.postToolExecution }, 0);
1613
- for (const [event, entry] of Object.entries(config.events ?? {})) {
1614
- asArray(entry).forEach((hook, i) => push(event, hook, i));
1615
- }
1616
- return out;
1617
- }
1618
- function trustHook(configDir, hook) {
1619
- const store = loadHookTrustStore(configDir);
1620
- const next = store.records.filter((r) => !(r.source === hook.source && r.event === hook.event && r.id === hook.id));
1621
- next.push({ id: hook.id, event: hook.event, source: hook.source, hash: hook.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
1622
- saveHookTrustStore(configDir, { records: next });
1623
- }
1624
- function untrustHook(configDir, hook) {
1625
- const store = loadHookTrustStore(configDir);
1626
- saveHookTrustStore(configDir, {
1627
- records: store.records.filter((r) => !(r.source === hook.source && r.event === hook.event && r.hash === hook.hash))
1628
- });
1629
- }
1630
- function getPendingHookTrust(config, configDir) {
1631
- return listHooks(config, configDir).filter((h) => h.source === "project" && !h.disabled && !h.trusted);
1632
- }
1633
- function normalizeDecision(value, hook) {
1634
- if (!value || typeof value !== "object") return null;
1635
- const obj = value;
1636
- const action = obj.action;
1637
- if (action !== "allow" && action !== "deny" && action !== "ask") return null;
1638
- return {
1639
- action,
1640
- reason: typeof obj.reason === "string" ? obj.reason : void 0,
1641
- prompt: typeof obj.prompt === "string" ? obj.prompt : void 0,
1642
- contextAppend: typeof obj.contextAppend === "string" ? obj.contextAppend : void 0,
1643
- warning: typeof obj.warning === "string" ? obj.warning : void 0,
1644
- warnings: Array.isArray(obj.warnings) ? obj.warnings.filter((x) => typeof x === "string") : void 0,
1645
- hook
1646
- };
1647
- }
1648
- function runStructuredHook(hook, descriptor, payload) {
1649
- if (hook.disabled === true) return null;
1650
- const timeout = Math.max(100, Math.min(hook.timeoutMs ?? DEFAULT_TIMEOUT_MS, 3e4));
1651
- try {
1652
- const stdout = execSync(hook.command, {
1653
- timeout,
1654
- stdio: ["pipe", "pipe", "pipe"],
1655
- encoding: "utf-8",
1656
- env: {
1657
- ...process.env,
1658
- AICLI_HOOK_EVENT: payload.event,
1659
- AICLI_HOOK_EVENT_JSON: JSON.stringify(payload)
1660
- }
1661
- }).trim();
1662
- if (!stdout) return null;
1663
- return normalizeDecision(JSON.parse(stdout), descriptor);
1664
- } catch (err) {
1665
- process.stderr.write(`\u26A0 Hook failed: ${hook.command.slice(0, 100)}
1666
- `);
1667
- if (hook.required) {
1668
- return { action: "deny", reason: err instanceof Error ? err.message : String(err), hook: descriptor };
1669
- }
1670
- return null;
1671
- }
1672
- }
1673
- function runLifecycleHooks(config, event, payload, opts) {
1674
- if (!config || config.enabled === false) return [];
1675
- const options = typeof opts === "string" ? { configDir: opts } : opts;
1676
- const store = loadHookTrustStore(options.configDir);
1677
- const hooks = asArray(config.events?.[event]);
1678
- const decisions = [];
1679
- for (let i = 0; i < hooks.length; i++) {
1680
- const hook = hooks[i];
1681
- if (!hook.command || hook.disabled) continue;
1682
- const source = hook.source ?? "user";
1683
- const hash = hashHook(event, hook.command);
1684
- const descriptor = {
1685
- id: `${event}:${i}`,
1686
- event,
1687
- command: hook.command,
1688
- source,
1689
- hash,
1690
- trusted: isTrusted(source, event, hash, store),
1691
- disabled: false,
1692
- description: hook.description
1693
- };
1694
- if (!descriptor.trusted) {
1695
- options.onSummary?.(`hook skipped: ${event} project hook requires trust (${hash.slice(0, 12)})`);
1696
- continue;
1697
- }
1698
- const decision = runStructuredHook(hook, descriptor, { event, ...payload });
1699
- if (decision) {
1700
- decisions.push(decision);
1701
- options.onSummary?.(`hook ${event}: ${decision.action}${decision.reason ? ` (${decision.reason})` : ""}`);
1702
- }
1703
- }
1704
- return decisions;
1705
- }
1706
- function rewriteTemplate(template, isWindows) {
1707
- const ref = (name) => isWindows ? `%${name}%` : `$${name}`;
1708
- 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"));
1709
- }
1710
- function runHook(template, vars) {
1711
- if (!template) return;
1712
- const isWindows = process.platform === "win32";
1713
- const cmd = rewriteTemplate(template, isWindows);
1714
- try {
1715
- execSync(cmd, {
1716
- timeout: DEFAULT_TIMEOUT_MS,
1717
- stdio: ["pipe", "pipe", "pipe"],
1718
- encoding: "utf-8",
1719
- env: {
1720
- ...process.env,
1721
- AICLI_HOOK_TOOL: vars.tool,
1722
- AICLI_HOOK_DANGER_LEVEL: vars.dangerLevel ?? "",
1723
- AICLI_HOOK_ARGS: vars.args ?? "",
1724
- AICLI_HOOK_STATUS: vars.status ?? ""
1725
- }
1726
- });
1727
- } catch {
1728
- process.stderr.write(`\u26A0 Hook failed: ${cmd.slice(0, 100)}
1729
- `);
1730
- }
1731
- }
1732
-
1733
1276
  // src/tools/permissions.ts
1734
- import { isAbsolute, resolve as resolve4 } from "path";
1277
+ import { isAbsolute, resolve as resolve3 } from "path";
1735
1278
  function checkPermission(toolName, args, dangerLevel, rules, defaultAction = "confirm") {
1736
1279
  for (const rule of rules) {
1737
1280
  if (rule.tool !== "*" && rule.tool !== toolName) continue;
@@ -1777,8 +1320,8 @@ function normalizePathForPermission(value) {
1777
1320
  return value.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
1778
1321
  }
1779
1322
  function isInsidePath(root, target) {
1780
- const absoluteTarget = isAbsolute(target) ? target : resolve4(root, target);
1781
- const r = normalizePathForPermission(resolve4(root));
1323
+ const absoluteTarget = isAbsolute(target) ? target : resolve3(root, target);
1324
+ const r = normalizePathForPermission(resolve3(root));
1782
1325
  const t = normalizePathForPermission(absoluteTarget);
1783
1326
  return t === r || t.startsWith(`${r}/`);
1784
1327
  }
@@ -2152,8 +1695,8 @@ var theme = new Proxy(DARK_THEME, {
2152
1695
  });
2153
1696
 
2154
1697
  // src/tools/action-classifier.ts
2155
- import { existsSync as existsSync6, readFileSync as readFileSync5 } from "fs";
2156
- import { isAbsolute as isAbsolute2, join as join3, resolve as resolve5 } from "path";
1698
+ import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
1699
+ import { isAbsolute as isAbsolute2, join, resolve as resolve4 } from "path";
2157
1700
  var RECENT_DENIED_LIMIT = 50;
2158
1701
  var recentlyDenied = [];
2159
1702
  function recordRecentlyDeniedAutoAction(call, classification) {
@@ -2176,8 +1719,8 @@ function normalizePath(value) {
2176
1719
  return value.replace(/\\/g, "/").replace(/\/+$/, "").toLowerCase();
2177
1720
  }
2178
1721
  function isInside(root, target) {
2179
- const absoluteRoot = resolve5(root);
2180
- const absoluteTarget = isAbsolute2(target) ? target : resolve5(root, target);
1722
+ const absoluteRoot = resolve4(root);
1723
+ const absoluteTarget = isAbsolute2(target) ? target : resolve4(root, target);
2181
1724
  const base = normalizePath(absoluteRoot);
2182
1725
  const t = normalizePath(absoluteTarget);
2183
1726
  return t === base || t.startsWith(base + "/");
@@ -2194,10 +1737,10 @@ function splitShellWords(command) {
2194
1737
  return out.filter(Boolean);
2195
1738
  }
2196
1739
  function readPackageManifest(root) {
2197
- const p = join3(root, "package.json");
2198
- if (!existsSync6(p)) return null;
1740
+ const p = join(root, "package.json");
1741
+ if (!existsSync4(p)) return null;
2199
1742
  try {
2200
- return JSON.parse(readFileSync5(p, "utf-8"));
1743
+ return JSON.parse(readFileSync3(p, "utf-8"));
2201
1744
  } catch {
2202
1745
  return null;
2203
1746
  }
@@ -2213,10 +1756,10 @@ function manifestHasDependency(root, name) {
2213
1756
  }
2214
1757
  function lockfileMentions(root, name) {
2215
1758
  for (const file of ["package-lock.json", "pnpm-lock.yaml", "yarn.lock"]) {
2216
- const p = join3(root, file);
2217
- if (!existsSync6(p)) continue;
1759
+ const p = join(root, file);
1760
+ if (!existsSync4(p)) continue;
2218
1761
  try {
2219
- if (readFileSync5(p, "utf-8").includes(name)) return true;
1762
+ if (readFileSync3(p, "utf-8").includes(name)) return true;
2220
1763
  } catch {
2221
1764
  }
2222
1765
  }
@@ -2703,7 +2246,7 @@ var ToolExecutor = class {
2703
2246
  rl.resume();
2704
2247
  process.stdout.write(prompt);
2705
2248
  this.confirming = true;
2706
- return new Promise((resolve9) => {
2249
+ return new Promise((resolve8) => {
2707
2250
  let completed = false;
2708
2251
  const cleanup = (result) => {
2709
2252
  if (completed) return;
@@ -2713,7 +2256,7 @@ var ToolExecutor = class {
2713
2256
  rl.pause();
2714
2257
  rlAny.output = savedOutput;
2715
2258
  this.confirming = false;
2716
- resolve9(result);
2259
+ resolve8(result);
2717
2260
  };
2718
2261
  const onLine = (line) => {
2719
2262
  const trimmed = line.trim();
@@ -2780,10 +2323,10 @@ var ToolExecutor = class {
2780
2323
  const filePath = String(call.arguments["path"] ?? "");
2781
2324
  const newContent = String(call.arguments["content"] ?? "");
2782
2325
  if (!filePath) return;
2783
- if (existsSync7(filePath)) {
2326
+ if (existsSync5(filePath)) {
2784
2327
  let oldContent;
2785
2328
  try {
2786
- oldContent = readFileSync6(filePath, "utf-8");
2329
+ oldContent = readFileSync4(filePath, "utf-8");
2787
2330
  } catch {
2788
2331
  return;
2789
2332
  }
@@ -2806,7 +2349,7 @@ var ToolExecutor = class {
2806
2349
  }
2807
2350
  } else if (call.name === "edit_file") {
2808
2351
  const filePath = String(call.arguments["path"] ?? "");
2809
- if (!filePath || !existsSync7(filePath)) return;
2352
+ if (!filePath || !existsSync5(filePath)) return;
2810
2353
  const oldStr = call.arguments["old_str"];
2811
2354
  const newStr = call.arguments["new_str"];
2812
2355
  if (oldStr !== void 0) {
@@ -2833,7 +2376,7 @@ var ToolExecutor = class {
2833
2376
  const to = Number(call.arguments["delete_to_line"] ?? from);
2834
2377
  let fileContent;
2835
2378
  try {
2836
- fileContent = readFileSync6(filePath, "utf-8");
2379
+ fileContent = readFileSync4(filePath, "utf-8");
2837
2380
  } catch {
2838
2381
  return;
2839
2382
  }
@@ -2887,7 +2430,7 @@ var ToolExecutor = class {
2887
2430
  rl.resume();
2888
2431
  process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
2889
2432
  this.confirming = true;
2890
- return new Promise((resolve9) => {
2433
+ return new Promise((resolve8) => {
2891
2434
  let completed = false;
2892
2435
  const cleanup = (answer) => {
2893
2436
  if (completed) return;
@@ -2897,7 +2440,7 @@ var ToolExecutor = class {
2897
2440
  rl.pause();
2898
2441
  rlAny.output = savedOutput;
2899
2442
  this.confirming = false;
2900
- resolve9(answer === "y");
2443
+ resolve8(answer === "y");
2901
2444
  };
2902
2445
  const onLine = (line) => {
2903
2446
  const trimmed = line.trim();
@@ -2925,11 +2468,11 @@ var ToolExecutor = class {
2925
2468
  };
2926
2469
 
2927
2470
  // src/tools/sensitive-paths.ts
2928
- import { resolve as resolve6, sep as sep2, basename as basename3 } from "path";
2471
+ import { resolve as resolve5, sep as sep2, basename as basename2 } from "path";
2929
2472
  import { homedir as homedir2 } from "os";
2930
2473
  var home = homedir2();
2931
2474
  function norm(p) {
2932
- const abs = resolve6(p);
2475
+ const abs = resolve5(p);
2933
2476
  return process.platform === "win32" ? abs.toLowerCase() : abs;
2934
2477
  }
2935
2478
  function homeRel(p) {
@@ -2944,7 +2487,7 @@ function homeRel(p) {
2944
2487
  function classifyWritePath(path3) {
2945
2488
  if (!path3) return { sensitive: false };
2946
2489
  const abs = norm(path3);
2947
- const base = basename3(abs);
2490
+ const base = basename2(abs);
2948
2491
  const rel = homeRel(path3);
2949
2492
  if (rel) {
2950
2493
  const shellRc = /* @__PURE__ */ new Set([
@@ -3068,7 +2611,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
3068
2611
  }
3069
2612
  undoStack.push(filePath, `write_file${appendMode ? " (append)" : ""}: ${filePath}`);
3070
2613
  fileCheckpoints.snapshot(filePath, ToolExecutor.currentMessageIndex);
3071
- mkdirSync3(dirname3(filePath), { recursive: true });
2614
+ mkdirSync(dirname2(filePath), { recursive: true });
3072
2615
  if (appendMode) {
3073
2616
  appendFileSync(filePath, content, encoding);
3074
2617
  } else {
@@ -3088,7 +2631,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
3088
2631
  };
3089
2632
 
3090
2633
  // src/tools/builtin/edit-file.ts
3091
- import { readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
2634
+ import { readFileSync as readFileSync5, existsSync as existsSync6 } from "fs";
3092
2635
 
3093
2636
  // src/tools/builtin/patch-apply.ts
3094
2637
  function parseUnifiedDiff(patch) {
@@ -3449,7 +2992,7 @@ Note: Path can be absolute or relative to cwd.`,
3449
2992
  const filePath = String(args["path"] ?? "");
3450
2993
  const encoding = args["encoding"] ?? "utf-8";
3451
2994
  if (!filePath) throw new ToolError("edit_file", "path is required");
3452
- if (!existsSync8(filePath)) throw new ToolError("edit_file", `File not found: ${filePath}`);
2995
+ if (!existsSync6(filePath)) throw new ToolError("edit_file", `File not found: ${filePath}`);
3453
2996
  const verdict = classifyWritePath(filePath);
3454
2997
  if (verdict.sensitive && subAgentGuard.active) {
3455
2998
  throw new ToolError(
@@ -3457,7 +3000,7 @@ Note: Path can be absolute or relative to cwd.`,
3457
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.`
3458
3001
  );
3459
3002
  }
3460
- const original = readFileSync7(filePath, encoding);
3003
+ const original = readFileSync5(filePath, encoding);
3461
3004
  if (args["patch"] !== void 0) {
3462
3005
  const patchText = String(args["patch"] ?? "");
3463
3006
  const stopOnError = args["stop_on_error"] !== false;
@@ -3615,8 +3158,8 @@ function truncatePreview(str, maxLen = 80) {
3615
3158
  }
3616
3159
 
3617
3160
  // src/tools/builtin/list-dir.ts
3618
- import { readdirSync as readdirSync4, statSync as statSync4, existsSync as existsSync9 } from "fs";
3619
- import { join as join4, basename as basename4 } 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";
3620
3163
  var listDirTool = {
3621
3164
  definition: {
3622
3165
  name: "list_dir",
@@ -3638,12 +3181,12 @@ var listDirTool = {
3638
3181
  async execute(args) {
3639
3182
  const dirPath = String(args["path"] ?? process.cwd());
3640
3183
  const recursive = Boolean(args["recursive"] ?? false);
3641
- if (!existsSync9(dirPath)) {
3642
- const targetName = basename4(dirPath).toLowerCase();
3184
+ if (!existsSync7(dirPath)) {
3185
+ const targetName = basename3(dirPath).toLowerCase();
3643
3186
  const cwd = process.cwd();
3644
3187
  const suggestions = [];
3645
3188
  try {
3646
- for (const entry of readdirSync4(cwd, { withFileTypes: true })) {
3189
+ for (const entry of readdirSync3(cwd, { withFileTypes: true })) {
3647
3190
  if (entry.isDirectory() && entry.name.toLowerCase() === targetName) {
3648
3191
  suggestions.push(entry.name);
3649
3192
  }
@@ -3676,7 +3219,7 @@ Please use list_dir (without path) to see the current directory structure first.
3676
3219
  function listRecursive(basePath, indent, recursive, lines) {
3677
3220
  let entries;
3678
3221
  try {
3679
- entries = readdirSync4(basePath, { withFileTypes: true });
3222
+ entries = readdirSync3(basePath, { withFileTypes: true });
3680
3223
  } catch {
3681
3224
  lines.push(`${indent}(permission denied)`);
3682
3225
  return;
@@ -3696,11 +3239,11 @@ function listRecursive(basePath, indent, recursive, lines) {
3696
3239
  if (entry.isDirectory()) {
3697
3240
  lines.push(`${indent}\u{1F4C1} ${entry.name}/`);
3698
3241
  if (recursive) {
3699
- listRecursive(join4(basePath, entry.name), indent + " ", true, lines);
3242
+ listRecursive(join2(basePath, entry.name), indent + " ", true, lines);
3700
3243
  }
3701
3244
  } else {
3702
3245
  try {
3703
- const stat = statSync4(join4(basePath, entry.name));
3246
+ const stat = statSync3(join2(basePath, entry.name));
3704
3247
  const size = formatSize(stat.size);
3705
3248
  lines.push(`${indent}\u{1F4C4} ${entry.name} (${size})`);
3706
3249
  } catch {
@@ -3716,9 +3259,9 @@ function formatSize(bytes) {
3716
3259
  }
3717
3260
 
3718
3261
  // src/tools/builtin/grep-files.ts
3719
- import { readdirSync as readdirSync5, readFileSync as readFileSync8, statSync as statSync5, existsSync as existsSync10 } from "fs";
3262
+ import { readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4, existsSync as existsSync8 } from "fs";
3720
3263
  import { readFile } from "fs/promises";
3721
- import { join as join5, relative } from "path";
3264
+ import { join as join3, relative } from "path";
3722
3265
  var grepFilesTool = {
3723
3266
  definition: {
3724
3267
  name: "grep_files",
@@ -3769,7 +3312,7 @@ Supports regex. Automatically skips node_modules, dist, .git directories.`,
3769
3312
  const contextLines = Math.max(0, Number(args["context_lines"] ?? 0));
3770
3313
  const maxResults = Math.max(1, Number(args["max_results"] ?? 50));
3771
3314
  if (!pattern) throw new ToolError("grep_files", "pattern is required");
3772
- if (!existsSync10(rootPath)) throw new ToolError("grep_files", `Path not found: ${rootPath}`);
3315
+ if (!existsSync8(rootPath)) throw new ToolError("grep_files", `Path not found: ${rootPath}`);
3773
3316
  const MAX_PATTERN_LENGTH = 1e3;
3774
3317
  if (pattern.length > MAX_PATTERN_LENGTH) {
3775
3318
  throw new ToolError("grep_files", `Pattern too long (${pattern.length} chars, max ${MAX_PATTERN_LENGTH}). Use a shorter pattern.`);
@@ -3782,7 +3325,7 @@ Supports regex. Automatically skips node_modules, dist, .git directories.`,
3782
3325
  regex = new RegExp(escaped, ignoreCase ? "gi" : "g");
3783
3326
  }
3784
3327
  const results = [];
3785
- const stat = statSync5(rootPath);
3328
+ const stat = statSync4(rootPath);
3786
3329
  if (stat.isFile()) {
3787
3330
  searchInFile(rootPath, rootPath, regex, contextLines, maxResults, results);
3788
3331
  } else {
@@ -3855,7 +3398,7 @@ function collectFilePaths(rootPath, filePattern, maxFiles) {
3855
3398
  if (paths.length >= maxFiles) return;
3856
3399
  let entries;
3857
3400
  try {
3858
- entries = readdirSync5(dirPath, { withFileTypes: true });
3401
+ entries = readdirSync4(dirPath, { withFileTypes: true });
3859
3402
  } catch {
3860
3403
  return;
3861
3404
  }
@@ -3863,13 +3406,13 @@ function collectFilePaths(rootPath, filePattern, maxFiles) {
3863
3406
  if (paths.length >= maxFiles) return;
3864
3407
  if (entry.isDirectory()) {
3865
3408
  if (SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
3866
- walk(join5(dirPath, entry.name));
3409
+ walk(join3(dirPath, entry.name));
3867
3410
  } else if (entry.isFile()) {
3868
3411
  if (isBinary(entry.name)) continue;
3869
3412
  if (filePattern && !matchesFilePattern(entry.name, filePattern)) continue;
3870
- const fullPath = join5(dirPath, entry.name);
3413
+ const fullPath = join3(dirPath, entry.name);
3871
3414
  try {
3872
- if (statSync5(fullPath).size > 1e6) continue;
3415
+ if (statSync4(fullPath).size > 1e6) continue;
3873
3416
  } catch {
3874
3417
  continue;
3875
3418
  }
@@ -3915,14 +3458,14 @@ async function searchInFileAsync(fullPath, displayPath, regex, contextLines, max
3915
3458
  }
3916
3459
  function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, results) {
3917
3460
  try {
3918
- const stat = statSync5(fullPath);
3461
+ const stat = statSync4(fullPath);
3919
3462
  if (stat.size > 1e6) return;
3920
3463
  } catch {
3921
3464
  return;
3922
3465
  }
3923
3466
  let content;
3924
3467
  try {
3925
- content = readFileSync8(fullPath, "utf-8");
3468
+ content = readFileSync6(fullPath, "utf-8");
3926
3469
  } catch {
3927
3470
  return;
3928
3471
  }
@@ -3953,8 +3496,8 @@ function searchInFile(fullPath, displayPath, regex, contextLines, maxResults, re
3953
3496
  }
3954
3497
 
3955
3498
  // src/tools/builtin/glob-files.ts
3956
- import { readdirSync as readdirSync6, statSync as statSync6, existsSync as existsSync11 } from "fs";
3957
- import { join as join6, relative as relative2, basename as basename5 } 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";
3958
3501
  var globFilesTool = {
3959
3502
  definition: {
3960
3503
  name: "glob_files",
@@ -3987,7 +3530,7 @@ Results sorted by most recent modification time. Automatically skips node_module
3987
3530
  const rootPath = String(args["path"] ?? process.cwd());
3988
3531
  const maxResults = Math.max(1, Number(args["max_results"] ?? 100));
3989
3532
  if (!pattern) throw new ToolError("glob_files", "pattern is required");
3990
- if (!existsSync11(rootPath)) throw new ToolError("glob_files", `Path not found: ${rootPath}`);
3533
+ if (!existsSync9(rootPath)) throw new ToolError("glob_files", `Path not found: ${rootPath}`);
3991
3534
  const regex = globToRegex(pattern);
3992
3535
  const matches = [];
3993
3536
  collectMatchingFiles(rootPath, rootPath, regex, matches, maxResults);
@@ -4058,21 +3601,21 @@ function collectMatchingFiles(dirPath, rootPath, regex, results, maxResults) {
4058
3601
  if (results.length >= maxResults) return;
4059
3602
  let entries;
4060
3603
  try {
4061
- entries = readdirSync6(dirPath, { withFileTypes: true });
3604
+ entries = readdirSync5(dirPath, { withFileTypes: true });
4062
3605
  } catch {
4063
3606
  return;
4064
3607
  }
4065
3608
  for (const entry of entries) {
4066
3609
  if (results.length >= maxResults) break;
4067
- const fullPath = join6(dirPath, entry.name);
3610
+ const fullPath = join4(dirPath, entry.name);
4068
3611
  if (entry.isDirectory()) {
4069
3612
  if (SKIP_DIRS2.has(entry.name) || entry.name.startsWith(".")) continue;
4070
3613
  collectMatchingFiles(fullPath, rootPath, regex, results, maxResults);
4071
3614
  } else if (entry.isFile()) {
4072
3615
  const relPath = relative2(rootPath, fullPath).replace(/\\/g, "/");
4073
- if (regex.test(relPath) || regex.test(basename5(relPath))) {
3616
+ if (regex.test(relPath) || regex.test(basename4(relPath))) {
4074
3617
  try {
4075
- const stat = statSync6(fullPath);
3618
+ const stat = statSync5(fullPath);
4076
3619
  results.push({ relPath, absPath: fullPath, mtime: stat.mtimeMs });
4077
3620
  } catch {
4078
3621
  results.push({ relPath, absPath: fullPath, mtime: 0 });
@@ -4146,7 +3689,7 @@ var runInteractiveTool = {
4146
3689
  PYTHONDONTWRITEBYTECODE: "1"
4147
3690
  };
4148
3691
  const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
4149
- return new Promise((resolve9) => {
3692
+ return new Promise((resolve8) => {
4150
3693
  const child = spawn2(executable, cmdArgs.map(String), {
4151
3694
  cwd: process.cwd(),
4152
3695
  env,
@@ -4179,22 +3722,22 @@ var runInteractiveTool = {
4179
3722
  setTimeout(writeNextLine, 400);
4180
3723
  const timer = setTimeout(() => {
4181
3724
  child.kill();
4182
- resolve9(`${prefixWarnings}[Timeout after ${timeout}ms]
3725
+ resolve8(`${prefixWarnings}[Timeout after ${timeout}ms]
4183
3726
  ${buildOutput(stdout, stderr)}`);
4184
3727
  }, timeout);
4185
3728
  child.on("close", (code) => {
4186
3729
  clearTimeout(timer);
4187
3730
  const output = buildOutput(stdout, stderr);
4188
3731
  if (code !== 0 && code !== null) {
4189
- resolve9(`${prefixWarnings}Exit code ${code}:
3732
+ resolve8(`${prefixWarnings}Exit code ${code}:
4190
3733
  ${output}`);
4191
3734
  } else {
4192
- resolve9(`${prefixWarnings}${output || "(no output)"}`);
3735
+ resolve8(`${prefixWarnings}${output || "(no output)"}`);
4193
3736
  }
4194
3737
  });
4195
3738
  child.on("error", (err) => {
4196
3739
  clearTimeout(timer);
4197
- resolve9(
3740
+ resolve8(
4198
3741
  `${prefixWarnings}Failed to start process "${executable}": ${err.message}
4199
3742
  Hint: On Windows, use the full path to the executable, e.g.:
4200
3743
  C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
@@ -4804,8 +4347,8 @@ ${preamble}`;
4804
4347
  }
4805
4348
 
4806
4349
  // src/tools/builtin/save-last-response.ts
4807
- import { mkdirSync as mkdirSync4, unlinkSync as unlinkSync2, rmdirSync as rmdirSync2 } from "fs";
4808
- import { dirname as dirname4 } from "path";
4350
+ import { mkdirSync as mkdirSync2, unlinkSync as unlinkSync2, rmdirSync as rmdirSync2 } from "fs";
4351
+ import { dirname as dirname3 } from "path";
4809
4352
  var lastResponseStore = { content: "" };
4810
4353
  function cleanupRejectedTeeFile(filePath) {
4811
4354
  try {
@@ -4813,7 +4356,7 @@ function cleanupRejectedTeeFile(filePath) {
4813
4356
  } catch {
4814
4357
  }
4815
4358
  try {
4816
- rmdirSync2(dirname4(filePath));
4359
+ rmdirSync2(dirname3(filePath));
4817
4360
  } catch {
4818
4361
  }
4819
4362
  }
@@ -4854,7 +4397,7 @@ Any of these triggers means use save_last_response, NOT write_file:
4854
4397
  throw new ToolError("save_last_response", "No content to save: AI has not produced any response yet, or the last response was empty.");
4855
4398
  }
4856
4399
  undoStack.push(filePath, `save_last_response: ${filePath}`);
4857
- mkdirSync4(dirname4(filePath), { recursive: true });
4400
+ mkdirSync2(dirname3(filePath), { recursive: true });
4858
4401
  atomicWriteFileSync(filePath, content);
4859
4402
  const lines = content.split("\n").length;
4860
4403
  return `File saved: ${filePath} (${lines} lines, ${content.length} bytes)`;
@@ -4862,21 +4405,21 @@ Any of these triggers means use save_last_response, NOT write_file:
4862
4405
  };
4863
4406
 
4864
4407
  // src/tools/builtin/save-memory.ts
4865
- import { join as join8 } from "path";
4408
+ import { join as join6 } from "path";
4866
4409
  import { homedir as homedir3 } from "os";
4867
4410
 
4868
4411
  // src/memory/persistent-memory.ts
4869
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync9 } from "fs";
4870
- import { randomUUID, createHash as createHash3 } from "crypto";
4871
- import { dirname as dirname5, join as join7, resolve as resolve7 } 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";
4872
4415
  function memoryStorePath(configDir) {
4873
- return join7(configDir, MEMORY_STORE_FILE_NAME);
4416
+ return join5(configDir, MEMORY_STORE_FILE_NAME);
4874
4417
  }
4875
4418
  function memoryMarkdownPath(configDir) {
4876
- return join7(configDir, MEMORY_FILE_NAME);
4419
+ return join5(configDir, MEMORY_FILE_NAME);
4877
4420
  }
4878
4421
  function getProjectKey(cwd = process.cwd()) {
4879
- return resolve7(getGitRoot(cwd) ?? cwd);
4422
+ return resolve6(getGitRoot(cwd) ?? cwd);
4880
4423
  }
4881
4424
  function nowIso() {
4882
4425
  return (/* @__PURE__ */ new Date()).toISOString();
@@ -4909,8 +4452,8 @@ function normalizeEntry(value) {
4909
4452
  }
4910
4453
  function legacyEntriesFromMarkdown(configDir) {
4911
4454
  const file = memoryMarkdownPath(configDir);
4912
- if (!existsSync12(file)) return [];
4913
- const content = readFileSync9(file, "utf-8").trim();
4455
+ if (!existsSync10(file)) return [];
4456
+ const content = readFileSync7(file, "utf-8").trim();
4914
4457
  if (!content) return [];
4915
4458
  const parts = content.split(/\n(?=##\s+\d{4}-\d{2}-\d{2})/g);
4916
4459
  const chunks = parts.length > 1 ? parts : [content];
@@ -4919,15 +4462,15 @@ function legacyEntriesFromMarkdown(configDir) {
4919
4462
  const body = (match ? match[2] : chunk).trim();
4920
4463
  const parsed = match ? Date.parse(match[1].replace(" ", "T")) : NaN;
4921
4464
  const createdAt = Number.isFinite(parsed) ? new Date(parsed).toISOString() : nowIso();
4922
- const id = "legacy-" + createHash3("sha1").update(`${index}
4465
+ const id = "legacy-" + createHash("sha1").update(`${index}
4923
4466
  ${chunk}`).digest("hex").slice(0, 12);
4924
4467
  return normalizeEntry({ id, content: body, scope: "personal", createdAt, updatedAt: createdAt, sensitivity: "low", approved: true });
4925
4468
  }).filter((entry) => Boolean(entry));
4926
4469
  }
4927
4470
  function loadMemoryEntries(configDir) {
4928
4471
  const file = memoryStorePath(configDir);
4929
- if (!existsSync12(file)) return legacyEntriesFromMarkdown(configDir);
4930
- const text = readFileSync9(file, "utf-8").trim();
4472
+ if (!existsSync10(file)) return legacyEntriesFromMarkdown(configDir);
4473
+ const text = readFileSync7(file, "utf-8").trim();
4931
4474
  if (!text) return [];
4932
4475
  const entries = [];
4933
4476
  for (const line of text.split("\n")) {
@@ -4942,7 +4485,7 @@ function loadMemoryEntries(configDir) {
4942
4485
  return entries;
4943
4486
  }
4944
4487
  function saveMemoryEntries(configDir, entries) {
4945
- mkdirSync5(configDir, { recursive: true });
4488
+ mkdirSync3(configDir, { recursive: true });
4946
4489
  const jsonl = entries.map((entry) => JSON.stringify(entry)).join("\n");
4947
4490
  atomicWriteFileSync(memoryStorePath(configDir), jsonl ? jsonl + "\n" : "");
4948
4491
  syncLegacyMarkdown(configDir, entries);
@@ -5017,7 +4560,7 @@ function findUnique(entries, idPrefix) {
5017
4560
  return matches[0];
5018
4561
  }
5019
4562
  function syncLegacyMarkdown(configDir, entries = loadMemoryEntries(configDir)) {
5020
- mkdirSync5(dirname5(memoryMarkdownPath(configDir)), { recursive: true });
4563
+ mkdirSync3(dirname4(memoryMarkdownPath(configDir)), { recursive: true });
5021
4564
  const active = entries.filter((entry) => entry.approved && !isMemoryExpired(entry));
5022
4565
  const markdown = active.map((entry) => {
5023
4566
  const date = entry.createdAt.replace("T", " ").slice(0, 19);
@@ -5060,7 +4603,7 @@ ${entry.content}`;
5060
4603
 
5061
4604
  // src/tools/builtin/save-memory.ts
5062
4605
  function getConfigDir() {
5063
- return join8(homedir3(), CONFIG_DIR_NAME);
4606
+ return join6(homedir3(), CONFIG_DIR_NAME);
5064
4607
  }
5065
4608
  function parseScope(value) {
5066
4609
  return value === "personal" || value === "project" || value === "session" || value === "team" ? value : void 0;
@@ -5152,7 +4695,7 @@ function promptUser(rl, question) {
5152
4695
  console.log();
5153
4696
  console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
5154
4697
  process.stdout.write(chalk4.cyan("> "));
5155
- return new Promise((resolve9) => {
4698
+ return new Promise((resolve8) => {
5156
4699
  let completed = false;
5157
4700
  const cleanup = (answer) => {
5158
4701
  if (completed) return;
@@ -5162,7 +4705,7 @@ function promptUser(rl, question) {
5162
4705
  rl.pause();
5163
4706
  rlAny.output = savedOutput;
5164
4707
  askUserContext.prompting = false;
5165
- resolve9(answer);
4708
+ resolve8(answer);
5166
4709
  };
5167
4710
  const onLine = (line) => {
5168
4711
  cleanup(line);
@@ -5394,8 +4937,8 @@ function formatResults2(query, data, _requested) {
5394
4937
  }
5395
4938
 
5396
4939
  // src/agents/agent-config.ts
5397
- import { existsSync as existsSync13, readdirSync as readdirSync7, readFileSync as readFileSync10 } from "fs";
5398
- import { join as join9 } from "path";
4940
+ import { existsSync as existsSync11, readdirSync as readdirSync6, readFileSync as readFileSync8 } from "fs";
4941
+ import { join as join7 } from "path";
5399
4942
  import { homedir as homedir4 } from "os";
5400
4943
  var READ_ONLY_TOOLS2 = /* @__PURE__ */ new Set([
5401
4944
  "read_file",
@@ -5490,13 +5033,13 @@ function parseAgentConfig(raw, source, path3) {
5490
5033
  return cfg;
5491
5034
  }
5492
5035
  function loadAgentDir(dir, source) {
5493
- if (!existsSync13(dir)) return [];
5036
+ if (!existsSync11(dir)) return [];
5494
5037
  const out = [];
5495
- for (const file of readdirSync7(dir)) {
5038
+ for (const file of readdirSync6(dir)) {
5496
5039
  if (!file.endsWith(".json")) continue;
5497
- const path3 = join9(dir, file);
5040
+ const path3 = join7(dir, file);
5498
5041
  try {
5499
- const parsed = JSON.parse(readFileSync10(path3, "utf-8"));
5042
+ const parsed = JSON.parse(readFileSync8(path3, "utf-8"));
5500
5043
  const cfg = parseAgentConfig(parsed, source, path3);
5501
5044
  if (cfg) out.push(cfg);
5502
5045
  } catch {
@@ -5506,8 +5049,8 @@ function loadAgentDir(dir, source) {
5506
5049
  }
5507
5050
  function getAgentDirs(configDir, cwd = process.cwd()) {
5508
5051
  return {
5509
- user: join9(configDir ?? join9(homedir4(), CONFIG_DIR_NAME), "agents"),
5510
- project: join9(cwd, CONFIG_DIR_NAME, "agents")
5052
+ user: join7(configDir ?? join7(homedir4(), CONFIG_DIR_NAME), "agents"),
5053
+ project: join7(cwd, CONFIG_DIR_NAME, "agents")
5511
5054
  };
5512
5055
  }
5513
5056
  function listAgentConfigs(configDir, cwd = process.cwd()) {
@@ -6222,14 +5765,14 @@ var taskStopTool = {
6222
5765
 
6223
5766
  // src/tools/builtin/git-tools.ts
6224
5767
  import { execFileSync as execFileSync2 } from "child_process";
6225
- import { existsSync as existsSync14 } from "fs";
6226
- import { join as join10 } from "path";
5768
+ import { existsSync as existsSync12 } from "fs";
5769
+ import { join as join8 } from "path";
6227
5770
  function assertGitRepo(cwd) {
6228
5771
  let dir = cwd;
6229
5772
  const root = dir.split(/[\\/]/)[0] + (dir.includes("\\") ? "\\" : "/");
6230
5773
  while (dir && dir !== root) {
6231
- if (existsSync14(join10(dir, ".git"))) return;
6232
- const parent = join10(dir, "..");
5774
+ if (existsSync12(join8(dir, ".git"))) return;
5775
+ const parent = join8(dir, "..");
6233
5776
  if (parent === dir) break;
6234
5777
  dir = parent;
6235
5778
  }
@@ -6494,9 +6037,9 @@ ${commitOutput.trim()}`;
6494
6037
  };
6495
6038
 
6496
6039
  // src/tools/builtin/notebook-edit.ts
6497
- import { readFileSync as readFileSync11, existsSync as existsSync15 } from "fs";
6040
+ import { readFileSync as readFileSync9, existsSync as existsSync13 } from "fs";
6498
6041
  import { writeFile } from "fs/promises";
6499
- import { resolve as resolve8, extname as extname2 } from "path";
6042
+ import { resolve as resolve7, extname as extname2 } from "path";
6500
6043
  var notebookEditTool = {
6501
6044
  definition: {
6502
6045
  name: "notebook_edit",
@@ -6545,14 +6088,14 @@ var notebookEditTool = {
6545
6088
  if (!Number.isInteger(cellIndexRaw) || cellIndexRaw < 1) {
6546
6089
  throw new ToolError("notebook_edit", "cell_index must be a positive integer (1-based)");
6547
6090
  }
6548
- const absPath = resolve8(filePath);
6091
+ const absPath = resolve7(filePath);
6549
6092
  if (extname2(absPath).toLowerCase() !== ".ipynb") {
6550
6093
  throw new ToolError("notebook_edit", "path must point to a .ipynb file");
6551
6094
  }
6552
- if (!existsSync15(absPath)) {
6095
+ if (!existsSync13(absPath)) {
6553
6096
  throw new ToolError("notebook_edit", `Notebook not found: ${filePath}`);
6554
6097
  }
6555
- const raw = readFileSync11(absPath, "utf-8");
6098
+ const raw = readFileSync9(absPath, "utf-8");
6556
6099
  const nb = parseNotebook(raw);
6557
6100
  const cellIdx0 = cellIndexRaw - 1;
6558
6101
  undoStack.push(absPath, `notebook_edit (${action}): ${filePath}`);
@@ -6969,8 +6512,8 @@ function estimateToolDefinitionTokens(def) {
6969
6512
 
6970
6513
  // src/tools/registry.ts
6971
6514
  import { pathToFileURL } from "url";
6972
- import { existsSync as existsSync16, mkdirSync as mkdirSync6, readdirSync as readdirSync8 } from "fs";
6973
- import { join as join11 } from "path";
6515
+ import { existsSync as existsSync14, mkdirSync as mkdirSync4, readdirSync as readdirSync7 } from "fs";
6516
+ import { join as join9 } from "path";
6974
6517
  var ToolRegistry = class {
6975
6518
  tools = /* @__PURE__ */ new Map();
6976
6519
  pluginToolNames = /* @__PURE__ */ new Set();
@@ -7131,16 +6674,16 @@ var ToolRegistry = class {
7131
6674
  * Returns the number of successfully loaded plugins.
7132
6675
  */
7133
6676
  async loadPlugins(pluginsDir, allowPlugins = false) {
7134
- if (!existsSync16(pluginsDir)) {
6677
+ if (!existsSync14(pluginsDir)) {
7135
6678
  try {
7136
- mkdirSync6(pluginsDir, { recursive: true });
6679
+ mkdirSync4(pluginsDir, { recursive: true });
7137
6680
  } catch {
7138
6681
  }
7139
6682
  return 0;
7140
6683
  }
7141
6684
  let files;
7142
6685
  try {
7143
- files = readdirSync8(pluginsDir).filter((f) => f.endsWith(".js"));
6686
+ files = readdirSync7(pluginsDir).filter((f) => f.endsWith(".js"));
7144
6687
  } catch {
7145
6688
  return 0;
7146
6689
  }
@@ -7157,12 +6700,12 @@ var ToolRegistry = class {
7157
6700
  process.stderr.write(
7158
6701
  `
7159
6702
  [plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
7160
- ` + files.map((f) => ` + ${join11(pluginsDir, f)}`).join("\n") + "\n\n"
6703
+ ` + files.map((f) => ` + ${join9(pluginsDir, f)}`).join("\n") + "\n\n"
7161
6704
  );
7162
6705
  let loaded = 0;
7163
6706
  for (const file of files) {
7164
6707
  try {
7165
- const fileUrl = pathToFileURL(join11(pluginsDir, file)).href;
6708
+ const fileUrl = pathToFileURL(join9(pluginsDir, file)).href;
7166
6709
  const mod = await import(fileUrl);
7167
6710
  const tool = mod.tool ?? mod.default?.tool ?? mod.default;
7168
6711
  if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
@@ -7194,25 +6737,10 @@ export {
7194
6737
  theme,
7195
6738
  undoStack,
7196
6739
  renderDiff,
7197
- listHooks,
7198
- trustHook,
7199
- untrustHook,
7200
- getPendingHookTrust,
7201
- runLifecycleHooks,
7202
- runHook,
7203
6740
  recordRecentlyDeniedAutoAction,
7204
6741
  getRecentlyDeniedAutoActions,
7205
6742
  clearRecentlyDeniedAutoActions,
7206
6743
  defaultActionClassifier,
7207
- pluginRoot,
7208
- installPlugin,
7209
- setPluginEnabled,
7210
- trustPlugin,
7211
- getInstalledPlugin,
7212
- listInstalledPlugins,
7213
- mergePluginHooks,
7214
- getActivePluginAssets,
7215
- describePlugin,
7216
6744
  memoryStorePath,
7217
6745
  memoryMarkdownPath,
7218
6746
  isMemoryExpired,