jinzd-ai-cli 0.4.242 → 0.4.244

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 (31) hide show
  1. package/dist/{batch-D3UHL432.js → batch-GLB7ES6K.js} +2 -2
  2. package/dist/{chunk-6ZWNXHNH.js → chunk-6IAVHU3I.js} +1 -1
  3. package/dist/{chunk-WMAXYDCB.js → chunk-ACU6T7B3.js} +1 -1
  4. package/dist/{chunk-Y4CMNXZH.js → chunk-B7KTFHK2.js} +1 -1
  5. package/dist/{chunk-D27TMEOV.js → chunk-BKTCOL5D.js} +107 -2
  6. package/dist/{chunk-J363BGOH.js → chunk-BO5UU3TY.js} +1 -1
  7. package/dist/{chunk-FRNWQIG6.js → chunk-HN4FU37T.js} +3 -3
  8. package/dist/{chunk-UWV2NBCO.js → chunk-M7XY5AK5.js} +107 -2
  9. package/dist/{chunk-MC2ZNPBC.js → chunk-MCC5BEZG.js} +1 -1
  10. package/dist/{chunk-PSP6UIKL.js → chunk-OYFDGRYD.js} +2 -2
  11. package/dist/{chunk-OO2PHOXD.js → chunk-P6AUULT2.js} +3 -3
  12. package/dist/{chunk-FEMPCNX3.js → chunk-WF7FD7WS.js} +49 -27
  13. package/dist/{chunk-LHINXQZF.js → chunk-XZI4ULXF.js} +1 -1
  14. package/dist/{chunk-MKLPAQT6.js → chunk-ZQGCX4QD.js} +1 -1
  15. package/dist/{ci-WSED3Z6V.js → ci-V7RGDIER.js} +4 -4
  16. package/dist/{ci-format-6AYL2X2J.js → ci-format-HSUEHAM2.js} +2 -2
  17. package/dist/{constants-FJ3L5GYO.js → constants-OQ6FVQ23.js} +1 -1
  18. package/dist/{doctor-cli-HCP56MKH.js → doctor-cli-LABZF3XG.js} +4 -4
  19. package/dist/electron-server.js +115 -93
  20. package/dist/{hub-K5MYSVEF.js → hub-RTFICY6M.js} +1 -1
  21. package/dist/index.js +91 -25
  22. package/dist/{persistent-memory-HWFNDQFQ.js → persistent-memory-OWXDBSZY.js} +12 -2
  23. package/dist/{persistent-memory-EYAKL2XA.js → persistent-memory-P6LU5KDG.js} +12 -2
  24. package/dist/{pr-OICMUN6R.js → pr-HXJ6ML6M.js} +4 -4
  25. package/dist/{run-tests-B3FSE5NV.js → run-tests-EFWAH43I.js} +2 -2
  26. package/dist/{run-tests-DSEW5HED.js → run-tests-XJ44FWIK.js} +2 -2
  27. package/dist/{server-2FS65CQZ.js → server-6OPGWJ7S.js} +11 -11
  28. package/dist/{server-EDCGPEGC.js → server-B6WJWV3T.js} +5 -5
  29. package/dist/{task-orchestrator-WCZYV3TE.js → task-orchestrator-KHJYQXWU.js} +5 -5
  30. package/dist/{usage-WVUYNLOD.js → usage-NW2ZXN6N.js} +2 -2
  31. package/package.json +1 -1
@@ -30,16 +30,18 @@ import {
30
30
  loadMemoryEntries,
31
31
  memoryStorePath,
32
32
  parseWritableScope,
33
+ searchPersistentMemories,
34
+ touchMemoryReferences,
33
35
  updateMemoryApproval,
34
36
  updateMemoryEntry
35
- } from "./chunk-UWV2NBCO.js";
37
+ } from "./chunk-M7XY5AK5.js";
36
38
  import {
37
39
  redactJson,
38
40
  scanString
39
41
  } from "./chunk-YVTASHS5.js";
40
42
  import {
41
43
  runTestsTool
42
- } from "./chunk-MC2ZNPBC.js";
44
+ } from "./chunk-MCC5BEZG.js";
43
45
  import {
44
46
  AGENTIC_BEHAVIOR_GUIDELINE,
45
47
  APP_NAME,
@@ -71,7 +73,7 @@ import {
71
73
  SUBAGENT_MAX_ROUNDS_LIMIT,
72
74
  VERSION,
73
75
  buildUserIdentityPrompt
74
- } from "./chunk-MKLPAQT6.js";
76
+ } from "./chunk-ZQGCX4QD.js";
75
77
  import {
76
78
  hasSemanticIndex,
77
79
  semanticSearch
@@ -89,7 +91,7 @@ import {
89
91
  import express from "express";
90
92
  import { createServer } from "http";
91
93
  import { WebSocketServer } from "ws";
92
- import { join as join26, dirname as dirname10, resolve as resolve12, relative as relative6, sep as sep4 } from "path";
94
+ import { join as join27, dirname as dirname10, resolve as resolve12, relative as relative6, sep as sep4 } from "path";
93
95
  import { existsSync as existsSync31, readFileSync as readFileSync24, readdirSync as readdirSync16, statSync as statSync14, realpathSync as realpathSync3 } from "fs";
94
96
  import { networkInterfaces } from "os";
95
97
 
@@ -5203,6 +5205,10 @@ Important rules:
5203
5205
  [The user pressed Ctrl+C while this command was running. Stop the current task, summarize what was done so far, and wait for the user's next instruction. Do NOT retry this command or continue with further tool calls unless explicitly asked.]`
5204
5206
  );
5205
5207
  }
5208
+ if (timedOut) {
5209
+ pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
5210
+ throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
5211
+ }
5206
5212
  if (status !== 0 || timedOut) {
5207
5213
  const poolStdout = (stdout ?? "").trim();
5208
5214
  const poolStderr = (stderr ?? "").trim();
@@ -5264,21 +5270,7 @@ ${combined || formatFailureFallback(status)}
5264
5270
  const execErr = err;
5265
5271
  const isTimeout = execErr.code === "ETIMEDOUT" || execErr.status == null && execErr.signal === "SIGTERM" || /ETIMEDOUT/i.test(execErr.message ?? "");
5266
5272
  if (isTimeout) {
5267
- const seconds = Math.round(timeout / 1e3);
5268
- throw new ToolError(
5269
- "bash",
5270
- `Command timed out after ${seconds}s.
5271
-
5272
- The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.
5273
-
5274
- How to recover (pick ONE \u2014 do NOT retry the same command):
5275
- 1. Pass an explicit longer timeout, e.g. timeout: ${Math.min(timeout * 2, MAX_TIMEOUT)}
5276
- 2. Use a non-recursive / narrower alternative (e.g. 'Get-ChildItem -File' without -Recurse, or limit depth with -Depth 1)
5277
- 3. Split the work into smaller batches (process subdirectories one at a time)
5278
- 4. For size/count queries, use '(Get-ChildItem X).Count' per directory instead of one giant pipeline
5279
-
5280
- [Do NOT retry the identical command \u2014 it will time out again.]`
5281
- );
5273
+ throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
5282
5274
  }
5283
5275
  if ("status" in execErr && execErr.status !== void 0) {
5284
5276
  const stderr = IS_WINDOWS3 && Buffer.isBuffer(execErr.stderr) ? decodeWindowsBuffer(execErr.stderr).trim() : execErr.stderr?.toString().trim() ?? "";
@@ -5303,6 +5295,22 @@ ${combined || execErr.message || formatFailureFallback(execErr.status)}
5303
5295
  function formatFailureHeader(status) {
5304
5296
  return typeof status === "number" ? `Exit code ${status}:` : "Command failed before exit code could be determined:";
5305
5297
  }
5298
+ function formatTimeoutMessage(timeout, maxTimeout) {
5299
+ const seconds = Math.round(timeout / 1e3);
5300
+ return [
5301
+ `Command timed out after ${seconds}s.`,
5302
+ "",
5303
+ "The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.",
5304
+ "",
5305
+ "How to recover (pick ONE \u2014 do NOT retry the same command):",
5306
+ ` 1. Pass an explicit longer timeout, e.g. timeout: ${Math.min(timeout * 2, maxTimeout)}`,
5307
+ " 2. Use a non-recursive / narrower alternative (e.g. 'Get-ChildItem -File' without -Recurse, or limit depth with -Depth 1)",
5308
+ " 3. Split the work into smaller batches (process subdirectories one at a time)",
5309
+ " 4. For size/count queries, use '(Get-ChildItem X).Count' per directory instead of one giant pipeline",
5310
+ "",
5311
+ "[Do NOT retry the identical command \u2014 it will time out again.]"
5312
+ ].join(String.fromCharCode(10));
5313
+ }
5306
5314
  function formatFailureFallback(status) {
5307
5315
  return typeof status === "number" ? `exit ${status}` : "The shell process ended before reporting a numeric exit code.";
5308
5316
  }
@@ -11828,6 +11836,8 @@ ${lines.join("\n")}`;
11828
11836
  };
11829
11837
 
11830
11838
  // src/tools/builtin/recall-memory.ts
11839
+ import { join as join14 } from "path";
11840
+ import { homedir as homedir7 } from "os";
11831
11841
  function formatHit(h, i) {
11832
11842
  const ts = h.chunk.timestamp.slice(0, 16).replace("T", " ");
11833
11843
  const title = h.chunk.sessionTitle ? ` \xB7 ${h.chunk.sessionTitle}` : "";
@@ -11840,7 +11850,7 @@ function formatHit(h, i) {
11840
11850
  var recallMemoryTool = {
11841
11851
  definition: {
11842
11852
  name: "recall_memory",
11843
- description: 'Semantic search over past chat sessions. Call this whenever the user references something that may have been discussed before ("last time", "remember", "\u4E4B\u524D", "\u4E0A\u6B21"), when context is ambiguous and continuity matters, or when you want to check what decisions or preferences have been established across prior conversations. Returns up to `topK` relevant snippets with session id, timestamp, and cosine similarity score. Prefer this over asking the user "can you remind me".',
11853
+ description: 'Search long-term memory: governed persistent memory entries (keyword match) plus semantic search over past chat sessions. Call this whenever the user references something that may have been discussed before ("last time", "remember", "\u4E4B\u524D", "\u4E0A\u6B21"), when context is ambiguous and continuity matters, or when you want to check what decisions or preferences have been established across prior conversations \u2014 including memories that were dropped from the injected system prompt by the size budget. Returns persistent-memory hits first, then up to `topK` chat snippets with session id, timestamp, and cosine similarity score. Prefer this over asking the user "can you remind me".',
11844
11854
  parameters: {
11845
11855
  query: {
11846
11856
  type: "string",
@@ -11877,9 +11887,21 @@ var recallMemoryTool = {
11877
11887
  const excludeCurrent = Boolean(args["excludeCurrentSession"]);
11878
11888
  const currentId = args["currentSessionId"] ? String(args["currentSessionId"]) : void 0;
11879
11889
  const minScore = args["minScore"] !== void 0 ? Number(args["minScore"]) : 0.25;
11890
+ const configDir = join14(homedir7(), CONFIG_DIR_NAME);
11891
+ let persistentSection = "";
11892
+ try {
11893
+ const persistentHits = searchPersistentMemories(configDir, query, process.cwd(), 3);
11894
+ if (persistentHits.length > 0) {
11895
+ touchMemoryReferences(configDir, persistentHits.map((h) => h.entry.id));
11896
+ persistentSection = `\u2500\u2500 Persistent memory (${persistentHits.length} hit(s)) \u2500\u2500
11897
+ ` + persistentHits.map((h) => `[id ${h.entry.id.slice(0, 8)} \xB7 ${h.entry.scope} \xB7 coverage ${h.score.toFixed(2)}]
11898
+ ${h.entry.content}`).join("\n\n") + "\n\n";
11899
+ }
11900
+ } catch {
11901
+ }
11880
11902
  const status = loadChatIndex();
11881
11903
  if (!status) {
11882
- return "No chat memory index found. The index is built on REPL startup, or run `/memory rebuild` manually. If you have no past sessions yet, this is expected.";
11904
+ return persistentSection + "No chat memory index found. The index is built on REPL startup, or run `/memory rebuild` manually. If you have no past sessions yet, this is expected.";
11883
11905
  }
11884
11906
  const hits = await searchChatMemory(query, {
11885
11907
  topK,
@@ -11887,11 +11909,11 @@ var recallMemoryTool = {
11887
11909
  excludeSessionId: excludeCurrent ? currentId : void 0
11888
11910
  });
11889
11911
  if (hits.length === 0) {
11890
- return `No memories matched "${query}" above score ${minScore}. Index has ${status.idx.chunks.length} chunks across ${Object.keys(status.idx.sessionMtimes).length} sessions. Consider lowering minScore to 0.15 or rephrasing the query.`;
11912
+ return persistentSection + `No chat-history memories matched "${query}" above score ${minScore}. Index has ${status.idx.chunks.length} chunks across ${Object.keys(status.idx.sessionMtimes).length} sessions. Consider lowering minScore to 0.15 or rephrasing the query.`;
11891
11913
  }
11892
- const header = `Found ${hits.length} memory hit(s) for "${query}" (min-score ${minScore}):
11914
+ const header = `Found ${hits.length} chat-history hit(s) for "${query}" (min-score ${minScore}):
11893
11915
  `;
11894
- return header + "\n" + hits.map(formatHit).join("\n\n");
11916
+ return persistentSection + header + "\n" + hits.map(formatHit).join("\n\n");
11895
11917
  }
11896
11918
  };
11897
11919
 
@@ -11920,7 +11942,7 @@ function estimateToolDefinitionTokens(def) {
11920
11942
  // src/tools/registry.ts
11921
11943
  import { pathToFileURL } from "url";
11922
11944
  import { existsSync as existsSync20, mkdirSync as mkdirSync9, readdirSync as readdirSync9 } from "fs";
11923
- import { join as join14 } from "path";
11945
+ import { join as join15 } from "path";
11924
11946
  var ToolRegistry = class {
11925
11947
  tools = /* @__PURE__ */ new Map();
11926
11948
  pluginToolNames = /* @__PURE__ */ new Set();
@@ -12107,12 +12129,12 @@ var ToolRegistry = class {
12107
12129
  process.stderr.write(
12108
12130
  `
12109
12131
  [plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
12110
- ` + files.map((f) => ` + ${join14(pluginsDir, f)}`).join("\n") + "\n\n"
12132
+ ` + files.map((f) => ` + ${join15(pluginsDir, f)}`).join("\n") + "\n\n"
12111
12133
  );
12112
12134
  let loaded = 0;
12113
12135
  for (const file of files) {
12114
12136
  try {
12115
- const fileUrl = pathToFileURL(join14(pluginsDir, file)).href;
12137
+ const fileUrl = pathToFileURL(join15(pluginsDir, file)).href;
12116
12138
  const mod = await import(fileUrl);
12117
12139
  const tool = mod.tool ?? mod.default?.tool ?? mod.default;
12118
12140
  if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
@@ -12659,7 +12681,7 @@ var McpManager = class {
12659
12681
 
12660
12682
  // src/skills/manager.ts
12661
12683
  import { existsSync as existsSync21, readdirSync as readdirSync10, mkdirSync as mkdirSync10, statSync as statSync8 } from "fs";
12662
- import { join as join15 } from "path";
12684
+ import { join as join16 } from "path";
12663
12685
 
12664
12686
  // src/skills/types.ts
12665
12687
  import { readFileSync as readFileSync15 } from "fs";
@@ -12749,13 +12771,13 @@ var SkillManager = class {
12749
12771
  }
12750
12772
  for (const entry of entries) {
12751
12773
  let filePath;
12752
- const fullPath = join15(dir, entry);
12774
+ const fullPath = join16(dir, entry);
12753
12775
  if (entry.endsWith(".md")) {
12754
12776
  filePath = fullPath;
12755
12777
  } else {
12756
12778
  try {
12757
12779
  if (statSync8(fullPath).isDirectory()) {
12758
- const skillMd = join15(fullPath, "SKILL.md");
12780
+ const skillMd = join16(fullPath, "SKILL.md");
12759
12781
  if (existsSync21(skillMd)) filePath = skillMd;
12760
12782
  else continue;
12761
12783
  } else {
@@ -13261,10 +13283,10 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13261
13283
 
13262
13284
  // src/repl/dev-state.ts
13263
13285
  import { existsSync as existsSync23, readFileSync as readFileSync17, unlinkSync as unlinkSync5, mkdirSync as mkdirSync11 } from "fs";
13264
- import { join as join16 } from "path";
13265
- import { homedir as homedir7 } from "os";
13286
+ import { join as join17 } from "path";
13287
+ import { homedir as homedir8 } from "os";
13266
13288
  function getDevStatePath() {
13267
- return join16(homedir7(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
13289
+ return join17(homedir8(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
13268
13290
  }
13269
13291
  function loadDevState() {
13270
13292
  const path3 = getDevStatePath();
@@ -13527,7 +13549,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13527
13549
 
13528
13550
  // src/core/context-files.ts
13529
13551
  import { existsSync as existsSync24, readFileSync as readFileSync18 } from "fs";
13530
- import { join as join17, relative as relative4, resolve as resolve8 } from "path";
13552
+ import { join as join18, relative as relative4, resolve as resolve8 } from "path";
13531
13553
  function uniqueNonEmpty(values) {
13532
13554
  const seen = /* @__PURE__ */ new Set();
13533
13555
  const out = [];
@@ -13604,7 +13626,7 @@ function readContextFile(level, filePath, cwd, maxBytes) {
13604
13626
  function findFirstContextFile(level, dir, cwd, candidates, maxBytes) {
13605
13627
  const skipped = [];
13606
13628
  for (const candidate of candidates) {
13607
- const filePath = join17(dir, candidate);
13629
+ const filePath = join18(dir, candidate);
13608
13630
  if (!existsSync24(filePath)) continue;
13609
13631
  const result = readContextFile(level, filePath, cwd, maxBytes);
13610
13632
  if (result.skipped) skipped.push(result.skipped);
@@ -13688,7 +13710,7 @@ import { dirname as dirname9 } from "path";
13688
13710
 
13689
13711
  // src/repl/commands/project-init.ts
13690
13712
  import { existsSync as existsSync25, readFileSync as readFileSync19, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
13691
- import { join as join18 } from "path";
13713
+ import { join as join19 } from "path";
13692
13714
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
13693
13715
  "node_modules",
13694
13716
  ".git",
@@ -13732,11 +13754,11 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13732
13754
  const sorted = filtered.sort((a, b) => {
13733
13755
  let aIsDir = false, bIsDir = false;
13734
13756
  try {
13735
- aIsDir = statSync9(join18(d, a)).isDirectory();
13757
+ aIsDir = statSync9(join19(d, a)).isDirectory();
13736
13758
  } catch {
13737
13759
  }
13738
13760
  try {
13739
- bIsDir = statSync9(join18(d, b)).isDirectory();
13761
+ bIsDir = statSync9(join19(d, b)).isDirectory();
13740
13762
  } catch {
13741
13763
  }
13742
13764
  if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
@@ -13744,7 +13766,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13744
13766
  });
13745
13767
  for (let i = 0; i < sorted.length && count < maxEntries; i++) {
13746
13768
  const name = sorted[i];
13747
- const fullPath = join18(d, name);
13769
+ const fullPath = join19(d, name);
13748
13770
  const isLast = i === sorted.length - 1;
13749
13771
  const connector = isLast ? "+-- " : "|-- ";
13750
13772
  let isDir;
@@ -13771,7 +13793,7 @@ function scanProject(cwd) {
13771
13793
  configFiles: [],
13772
13794
  directoryStructure: ""
13773
13795
  };
13774
- const check = (file) => existsSync25(join18(cwd, file));
13796
+ const check = (file) => existsSync25(join19(cwd, file));
13775
13797
  const configCandidates = [
13776
13798
  "package.json",
13777
13799
  "tsconfig.json",
@@ -13798,7 +13820,7 @@ function scanProject(cwd) {
13798
13820
  info.type = "node";
13799
13821
  info.language = check("tsconfig.json") ? "TypeScript" : "JavaScript";
13800
13822
  try {
13801
- const pkg = JSON.parse(readFileSync19(join18(cwd, "package.json"), "utf-8"));
13823
+ const pkg = JSON.parse(readFileSync19(join19(cwd, "package.json"), "utf-8"));
13802
13824
  const scripts = pkg.scripts ?? {};
13803
13825
  info.buildCommand = scripts.build ? "npm run build" : void 0;
13804
13826
  info.testCommand = scripts.test ? "npm test" : void 0;
@@ -14447,7 +14469,7 @@ function resolveRoleProviders(roles, lookup, defaultProvider, defaultModel, avai
14447
14469
  }
14448
14470
 
14449
14471
  // src/hub/persist.ts
14450
- import { join as join19 } from "path";
14472
+ import { join as join20 } from "path";
14451
14473
  function discussionToMessages(state2) {
14452
14474
  const out = [];
14453
14475
  const t0 = state2.messages[0]?.timestamp ?? /* @__PURE__ */ new Date();
@@ -14485,7 +14507,7 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
14485
14507
  session.title = `[Hub] ${state2.topic.slice(0, 48)}`.replace(/\n/g, " ");
14486
14508
  session.titleAiGenerated = true;
14487
14509
  await sm.save();
14488
- return { id: session.id, path: join19(config.getHistoryDir(), `${session.id}.json`) };
14510
+ return { id: session.id, path: join20(config.getHistoryDir(), `${session.id}.json`) };
14489
14511
  }
14490
14512
 
14491
14513
  // src/web/commands/provider-commands.ts
@@ -14574,7 +14596,7 @@ async function handlePlan(args, ctx) {
14574
14596
 
14575
14597
  // src/web/commands/_shared.ts
14576
14598
  import { existsSync as existsSync28, readFileSync as readFileSync21, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync13, statSync as statSync12, createWriteStream } from "fs";
14577
- import { join as join22, resolve as resolve9, dirname as dirname8 } from "path";
14599
+ import { join as join23, resolve as resolve9, dirname as dirname8 } from "path";
14578
14600
 
14579
14601
  // src/cli/review-prompts.ts
14580
14602
  function buildReviewPrompt(diff, gitContextStr, detailed) {
@@ -14647,7 +14669,7 @@ function readGitDiff(options = {}) {
14647
14669
 
14648
14670
  // src/diagnostics/doctor-report.ts
14649
14671
  import { existsSync as existsSync27, statSync as statSync11 } from "fs";
14650
- import { join as join21 } from "path";
14672
+ import { join as join22 } from "path";
14651
14673
  import { arch as arch2, platform as platform7, release as release2 } from "os";
14652
14674
 
14653
14675
  // src/diagnostics/crash-log.ts
@@ -14660,13 +14682,13 @@ import {
14660
14682
  unlinkSync as unlinkSync6,
14661
14683
  writeFileSync as writeFileSync2
14662
14684
  } from "fs";
14663
- import { join as join20 } from "path";
14664
- import { homedir as homedir8, platform as platform6, release, arch } from "os";
14685
+ import { join as join21 } from "path";
14686
+ import { homedir as homedir9, platform as platform6, release, arch } from "os";
14665
14687
  var LOGS_DIR_NAME = "logs";
14666
14688
  var CRASH_LOG_PREFIX = "crash-";
14667
14689
  function getLogsDir(configDir) {
14668
- const base = configDir ?? join20(homedir8(), CONFIG_DIR_NAME);
14669
- return join20(base, LOGS_DIR_NAME);
14690
+ const base = configDir ?? join21(homedir9(), CONFIG_DIR_NAME);
14691
+ return join21(base, LOGS_DIR_NAME);
14670
14692
  }
14671
14693
  function truncate(s, n) {
14672
14694
  return s.length <= n ? s : s.slice(0, n) + "\u2026";
@@ -14683,7 +14705,7 @@ function listRecentCrashes(limit = 10, configDir) {
14683
14705
  }
14684
14706
  for (const name of names) {
14685
14707
  if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
14686
- const full = join20(dir, name);
14708
+ const full = join21(dir, name);
14687
14709
  try {
14688
14710
  const st = statSync10(full);
14689
14711
  const head = readFileSync20(full, "utf-8").split("\n").slice(0, 20);
@@ -14705,7 +14727,7 @@ function listRecentCrashes(limit = 10, configDir) {
14705
14727
  return files.slice(0, limit);
14706
14728
  }
14707
14729
  function getConfigDirUsage(configDir) {
14708
- const base = configDir ?? join20(homedir8(), CONFIG_DIR_NAME);
14730
+ const base = configDir ?? join21(homedir9(), CONFIG_DIR_NAME);
14709
14731
  if (!existsSync26(base)) return { totalBytes: 0, entries: [] };
14710
14732
  const entries = [];
14711
14733
  let total = 0;
@@ -14716,7 +14738,7 @@ function getConfigDirUsage(configDir) {
14716
14738
  return { totalBytes: 0, entries: [] };
14717
14739
  }
14718
14740
  for (const name of names) {
14719
- const full = join20(base, name);
14741
+ const full = join21(base, name);
14720
14742
  const bytes = dirSize(full);
14721
14743
  entries.push({ name, bytes });
14722
14744
  total += bytes;
@@ -14731,7 +14753,7 @@ function dirSize(path3) {
14731
14753
  if (!st.isDirectory()) return 0;
14732
14754
  let sum = 0;
14733
14755
  for (const name of readdirSync12(path3)) {
14734
- sum += dirSize(join20(path3, name));
14756
+ sum += dirSize(join21(path3, name));
14735
14757
  }
14736
14758
  return sum;
14737
14759
  } catch {
@@ -14784,12 +14806,12 @@ function buildDoctorReport(options) {
14784
14806
  configDir,
14785
14807
  providers: options.providers.listAll().map((p) => ({ id: p.id, displayName: p.displayName, configured: p.configured })),
14786
14808
  files: [
14787
- checkFile("config.json", join21(configDir, "config.json")),
14788
- checkFile("memory.md", join21(configDir, MEMORY_FILE_NAME)),
14789
- checkFile("memory.jsonl", join21(configDir, "memory.jsonl")),
14790
- checkFile("dev-state.md", join21(configDir, DEV_STATE_FILE_NAME)),
14791
- checkFile("hooks-trust.json", join21(configDir, "hooks-trust.json")),
14792
- checkFile("plugin-state.json", join21(configDir, "plugins", "plugin-state.json"))
14809
+ checkFile("config.json", join22(configDir, "config.json")),
14810
+ checkFile("memory.md", join22(configDir, MEMORY_FILE_NAME)),
14811
+ checkFile("memory.jsonl", join22(configDir, "memory.jsonl")),
14812
+ checkFile("dev-state.md", join22(configDir, DEV_STATE_FILE_NAME)),
14813
+ checkFile("hooks-trust.json", join22(configDir, "hooks-trust.json")),
14814
+ checkFile("plugin-state.json", join22(configDir, "plugins", "plugin-state.json"))
14793
14815
  ],
14794
14816
  context: {
14795
14817
  enabled: contextSetting !== false,
@@ -14824,7 +14846,7 @@ function buildDoctorReport(options) {
14824
14846
  disabled: hooks.filter((h) => h.disabled).length
14825
14847
  },
14826
14848
  plugins: {
14827
- root: join21(configDir, "plugins"),
14849
+ root: join22(configDir, "plugins"),
14828
14850
  installed: plugins.length,
14829
14851
  active: activeAssets.plugins.length,
14830
14852
  invalid: plugins.filter((p) => !p.valid).length,
@@ -14839,7 +14861,7 @@ function buildDoctorReport(options) {
14839
14861
  mcp: {
14840
14862
  enabled: config.get("mcpEnabled"),
14841
14863
  configured: Object.keys(mcpServers).length,
14842
- projectConfigExists: existsSync27(join21(projectRoot, MCP_PROJECT_CONFIG_NAME)),
14864
+ projectConfigExists: existsSync27(join22(projectRoot, MCP_PROJECT_CONFIG_NAME)),
14843
14865
  statuses: options.mcpStatuses ?? []
14844
14866
  },
14845
14867
  recentCrashes: listRecentCrashes(5, configDir),
@@ -15067,7 +15089,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15067
15089
  Cost: ${formatCost(cost)}` : "";
15068
15090
  let memoryLine = "";
15069
15091
  try {
15070
- const { countPendingMemories } = await import("./persistent-memory-HWFNDQFQ.js");
15092
+ const { countPendingMemories } = await import("./persistent-memory-OWXDBSZY.js");
15071
15093
  const pending = countPendingMemories(ctx.config.getConfigDir());
15072
15094
  if (pending > 0) memoryLine = `
15073
15095
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -15651,7 +15673,7 @@ async function handlePlugin(args, ctx) {
15651
15673
  lines.push("");
15652
15674
  }
15653
15675
  if (pluginTools.length > 0) {
15654
- const legacyDir = join22(configDir, PLUGINS_DIR_NAME);
15676
+ const legacyDir = join23(configDir, PLUGINS_DIR_NAME);
15655
15677
  lines.push(`**Legacy JS tools** (${pluginTools.length}):`);
15656
15678
  lines.push(`Dir: ${legacyDir}`);
15657
15679
  for (const t of pluginTools) lines.push(` \u2022 ${t.definition.name} \u2014 ${t.definition.description}`);
@@ -15775,7 +15797,7 @@ ${activated.meta.description || ""}` });
15775
15797
  }
15776
15798
  async function handleCommands(_args, ctx) {
15777
15799
  const configDir = ctx.config.getConfigDir();
15778
- const commandsDir = join22(configDir, CUSTOM_COMMANDS_DIR_NAME);
15800
+ const commandsDir = join23(configDir, CUSTOM_COMMANDS_DIR_NAME);
15779
15801
  if (!existsSync28(commandsDir)) {
15780
15802
  ctx.send({ type: "info", message: `No custom commands directory.
15781
15803
  Create: ${commandsDir}/ with .md files.` });
@@ -15876,7 +15898,7 @@ async function handleSecurityReview(args, ctx) {
15876
15898
  async function handleTest(args, ctx) {
15877
15899
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
15878
15900
  try {
15879
- const { executeTests } = await import("./run-tests-B3FSE5NV.js");
15901
+ const { executeTests } = await import("./run-tests-EFWAH43I.js");
15880
15902
  const argStr = args.join(" ").trim();
15881
15903
  let testArgs = {};
15882
15904
  if (argStr) {
@@ -15943,7 +15965,7 @@ async function handleDiff(args, ctx) {
15943
15965
  }
15944
15966
  async function handleInit(args, ctx) {
15945
15967
  const cwd = process.cwd();
15946
- const targetPath = join22(cwd, "AICLI.md");
15968
+ const targetPath = join23(cwd, "AICLI.md");
15947
15969
  const force = args.includes("--force");
15948
15970
  if (existsSync28(targetPath) && !force) {
15949
15971
  ctx.send({ type: "info", message: `AICLI.md already exists at ${targetPath}
@@ -16140,7 +16162,7 @@ async function handleMemory(args, ctx) {
16140
16162
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16141
16163
  } else if (sub === "export") {
16142
16164
  if (args[1] === "md") {
16143
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-HWFNDQFQ.js");
16165
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-OWXDBSZY.js");
16144
16166
  ctx.send({
16145
16167
  type: "export_data",
16146
16168
  format: "md",
@@ -18038,7 +18060,7 @@ async function setupProxy(configProxy) {
18038
18060
 
18039
18061
  // src/web/auth.ts
18040
18062
  import { existsSync as existsSync30, readFileSync as readFileSync23, writeFileSync as writeFileSync5, mkdirSync as mkdirSync15, readdirSync as readdirSync15, copyFileSync } from "fs";
18041
- import { isAbsolute as isAbsolute3, join as join25, relative as relative5 } from "path";
18063
+ import { isAbsolute as isAbsolute3, join as join26, relative as relative5 } from "path";
18042
18064
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
18043
18065
  var USERS_FILE = "users.json";
18044
18066
  var TOKEN_EXPIRY_HOURS = 24;
@@ -18053,7 +18075,7 @@ var AuthManager = class {
18053
18075
  db;
18054
18076
  constructor(baseDir) {
18055
18077
  this.baseDir = baseDir;
18056
- this.usersFile = join25(baseDir, USERS_FILE);
18078
+ this.usersFile = join26(baseDir, USERS_FILE);
18057
18079
  this.db = this.loadOrCreate();
18058
18080
  }
18059
18081
  // ── Public API ─────────────────────────────────────────────────
@@ -18082,9 +18104,9 @@ var AuthManager = class {
18082
18104
  }
18083
18105
  const salt = randomBytes(16).toString("hex");
18084
18106
  const passwordHash = this.hashPassword(password, salt);
18085
- const dataDir = join25(USERS_DIR, username);
18086
- const fullDataDir = join25(this.baseDir, dataDir);
18087
- mkdirSync15(join25(fullDataDir, "history"), { recursive: true });
18107
+ const dataDir = join26(USERS_DIR, username);
18108
+ const fullDataDir = join26(this.baseDir, dataDir);
18109
+ mkdirSync15(join26(fullDataDir, "history"), { recursive: true });
18088
18110
  const user = {
18089
18111
  username,
18090
18112
  passwordHash,
@@ -18199,7 +18221,7 @@ var AuthManager = class {
18199
18221
  getUserDataDir(username) {
18200
18222
  const user = this.db.users.find((u) => u.username === username);
18201
18223
  if (!user) throw new Error(`User not found: ${username}`);
18202
- return join25(this.baseDir, user.dataDir);
18224
+ return join26(this.baseDir, user.dataDir);
18203
18225
  }
18204
18226
  /** List all usernames */
18205
18227
  listUsers() {
@@ -18235,30 +18257,30 @@ var AuthManager = class {
18235
18257
  const err = this.register(username, password);
18236
18258
  if (err) return err;
18237
18259
  const userDir = this.getUserDataDir(username);
18238
- const globalConfig = join25(this.baseDir, "config.json");
18260
+ const globalConfig = join26(this.baseDir, "config.json");
18239
18261
  if (existsSync30(globalConfig)) {
18240
18262
  try {
18241
18263
  const content = readFileSync23(globalConfig, "utf-8");
18242
- writeFileSync5(join25(userDir, "config.json"), content, "utf-8");
18264
+ writeFileSync5(join26(userDir, "config.json"), content, "utf-8");
18243
18265
  } catch {
18244
18266
  }
18245
18267
  }
18246
- const globalMemory = join25(this.baseDir, "memory.md");
18268
+ const globalMemory = join26(this.baseDir, "memory.md");
18247
18269
  if (existsSync30(globalMemory)) {
18248
18270
  try {
18249
18271
  const content = readFileSync23(globalMemory, "utf-8");
18250
- writeFileSync5(join25(userDir, "memory.md"), content, "utf-8");
18272
+ writeFileSync5(join26(userDir, "memory.md"), content, "utf-8");
18251
18273
  } catch {
18252
18274
  }
18253
18275
  }
18254
- const globalHistory = join25(this.baseDir, "history");
18276
+ const globalHistory = join26(this.baseDir, "history");
18255
18277
  if (existsSync30(globalHistory)) {
18256
18278
  try {
18257
18279
  const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
18258
- const userHistory = join25(userDir, "history");
18280
+ const userHistory = join26(userDir, "history");
18259
18281
  for (const f of files) {
18260
18282
  try {
18261
- copyFileSync(join25(globalHistory, f), join25(userHistory, f));
18283
+ copyFileSync(join26(globalHistory, f), join26(userHistory, f));
18262
18284
  } catch {
18263
18285
  }
18264
18286
  }
@@ -18305,7 +18327,7 @@ var AuthManager = class {
18305
18327
  if (typeof record.username !== "string" || !/^[a-z0-9_-]{2,32}$/.test(record.username) || usernames.has(record.username) || typeof record.passwordHash !== "string" || record.passwordHash.length === 0 || typeof record.salt !== "string" || record.salt.length === 0 || typeof record.createdAt !== "string" || typeof record.dataDir !== "string" || record.dataDir.length === 0 || isAbsolute3(record.dataDir)) {
18306
18328
  return false;
18307
18329
  }
18308
- const dataDirFromBase = relative5(this.baseDir, join25(this.baseDir, record.dataDir));
18330
+ const dataDirFromBase = relative5(this.baseDir, join26(this.baseDir, record.dataDir));
18309
18331
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
18310
18332
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
18311
18333
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -18421,7 +18443,7 @@ async function startWebServer(options = {}) {
18421
18443
  }
18422
18444
  }
18423
18445
  let skillManager = null;
18424
- const skillsDir = join26(config.getConfigDir(), SKILLS_DIR_NAME);
18446
+ const skillsDir = join27(config.getConfigDir(), SKILLS_DIR_NAME);
18425
18447
  if (existsSync31(skillsDir)) {
18426
18448
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
18427
18449
  skillManager.loadSkills(pluginAssets.skillDirs);
@@ -18493,18 +18515,18 @@ async function startWebServer(options = {}) {
18493
18515
  next();
18494
18516
  };
18495
18517
  const moduleDir = getModuleDir();
18496
- let clientDir = join26(moduleDir, "web", "client");
18518
+ let clientDir = join27(moduleDir, "web", "client");
18497
18519
  if (!existsSync31(clientDir)) {
18498
- clientDir = join26(moduleDir, "client");
18520
+ clientDir = join27(moduleDir, "client");
18499
18521
  }
18500
18522
  if (!existsSync31(clientDir)) {
18501
- clientDir = join26(moduleDir, "..", "..", "src", "web", "client");
18523
+ clientDir = join27(moduleDir, "..", "..", "src", "web", "client");
18502
18524
  }
18503
18525
  if (!existsSync31(clientDir)) {
18504
- clientDir = join26(process.cwd(), "src", "web", "client");
18526
+ clientDir = join27(process.cwd(), "src", "web", "client");
18505
18527
  }
18506
18528
  console.log(` Static files: ${clientDir}`);
18507
- app.use("/vendor", express.static(join26(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18529
+ app.use("/vendor", express.static(join27(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18508
18530
  app.use(express.static(clientDir));
18509
18531
  app.get("/api/status", (_req, res) => {
18510
18532
  res.json({
@@ -18571,7 +18593,7 @@ async function startWebServer(options = {}) {
18571
18593
  app.get("/api/files", requireAuth, (req, res) => {
18572
18594
  const cwd = process.cwd();
18573
18595
  const prefix = req.query.prefix || "";
18574
- const targetDir = join26(cwd, prefix);
18596
+ const targetDir = join27(cwd, prefix);
18575
18597
  try {
18576
18598
  const canonicalTarget = realpathSync3(resolve12(targetDir));
18577
18599
  const canonicalCwd = realpathSync3(resolve12(cwd));
@@ -18588,7 +18610,7 @@ async function startWebServer(options = {}) {
18588
18610
  const entries = readdirSync16(targetDir, { withFileTypes: true });
18589
18611
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
18590
18612
  name: e.name,
18591
- path: relative6(cwd, join26(targetDir, e.name)).replace(/\\/g, "/"),
18613
+ path: relative6(cwd, join27(targetDir, e.name)).replace(/\\/g, "/"),
18592
18614
  isDir: e.isDirectory()
18593
18615
  }));
18594
18616
  res.json({ files });
@@ -18628,7 +18650,7 @@ async function startWebServer(options = {}) {
18628
18650
  try {
18629
18651
  const authUser = req._authUser;
18630
18652
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
18631
- const filePath = join26(histDir, `${id}.json`);
18653
+ const filePath = join27(histDir, `${id}.json`);
18632
18654
  if (!existsSync31(filePath)) {
18633
18655
  res.status(404).json({ error: "Session not found" });
18634
18656
  return;
@@ -18657,7 +18679,7 @@ async function startWebServer(options = {}) {
18657
18679
  return;
18658
18680
  }
18659
18681
  const cwd = process.cwd();
18660
- const fullPath = resolve12(join26(cwd, filePath));
18682
+ const fullPath = resolve12(join27(cwd, filePath));
18661
18683
  try {
18662
18684
  const canonicalFull = realpathSync3(fullPath);
18663
18685
  const canonicalCwd = realpathSync3(resolve12(cwd));
@@ -18930,14 +18952,14 @@ function resolveProjectMcpPath() {
18930
18952
  const cwd = process.cwd();
18931
18953
  const gitRoot = getGitRoot(cwd);
18932
18954
  const projectRoot = gitRoot ?? cwd;
18933
- const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
18955
+ const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18934
18956
  return existsSync31(configPath) ? configPath : null;
18935
18957
  }
18936
18958
  function loadProjectMcpConfig() {
18937
18959
  const cwd = process.cwd();
18938
18960
  const gitRoot = getGitRoot(cwd);
18939
18961
  const projectRoot = gitRoot ?? cwd;
18940
- const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
18962
+ const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18941
18963
  if (!existsSync31(configPath)) return null;
18942
18964
  try {
18943
18965
  const raw = JSON.parse(readFileSync24(configPath, "utf-8"));
@@ -154,7 +154,7 @@ ${content}`);
154
154
  }
155
155
  }
156
156
  async function runTaskMode(config, providers, configManager, topic) {
157
- const { TaskOrchestrator } = await import("./task-orchestrator-WCZYV3TE.js");
157
+ const { TaskOrchestrator } = await import("./task-orchestrator-KHJYQXWU.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {