jinzd-ai-cli 0.4.242 → 0.4.243

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-CUVZUPRK.js} +2 -2
  2. package/dist/{chunk-Y4CMNXZH.js → chunk-66CE3E6X.js} +1 -1
  3. package/dist/{chunk-LHINXQZF.js → chunk-DJGCG7SF.js} +1 -1
  4. package/dist/{chunk-J363BGOH.js → chunk-EMFCHE2B.js} +1 -1
  5. package/dist/{chunk-MKLPAQT6.js → chunk-GEWPLNKA.js} +1 -1
  6. package/dist/{chunk-PSP6UIKL.js → chunk-H3ARWBYR.js} +2 -2
  7. package/dist/{chunk-FRNWQIG6.js → chunk-HNJX3N2V.js} +3 -3
  8. package/dist/{chunk-FEMPCNX3.js → chunk-KILKF2VN.js} +28 -12
  9. package/dist/{chunk-6ZWNXHNH.js → chunk-L5IRDRWG.js} +1 -1
  10. package/dist/{chunk-MC2ZNPBC.js → chunk-PLEXBFCR.js} +1 -1
  11. package/dist/{chunk-UWV2NBCO.js → chunk-PNNZRJ67.js} +107 -2
  12. package/dist/{chunk-OO2PHOXD.js → chunk-QNK7GUUB.js} +3 -3
  13. package/dist/{chunk-D27TMEOV.js → chunk-TY4FSEZS.js} +107 -2
  14. package/dist/{chunk-WMAXYDCB.js → chunk-X73Y4JZI.js} +1 -1
  15. package/dist/{ci-WSED3Z6V.js → ci-3O3JR6FX.js} +4 -4
  16. package/dist/{ci-format-6AYL2X2J.js → ci-format-KGWF6KOU.js} +2 -2
  17. package/dist/{constants-FJ3L5GYO.js → constants-NMFRZ5LW.js} +1 -1
  18. package/dist/{doctor-cli-HCP56MKH.js → doctor-cli-4QUHTJZ4.js} +4 -4
  19. package/dist/electron-server.js +94 -78
  20. package/dist/{hub-K5MYSVEF.js → hub-2GXFPWOR.js} +1 -1
  21. package/dist/index.js +91 -25
  22. package/dist/{persistent-memory-EYAKL2XA.js → persistent-memory-VFBRMKGG.js} +12 -2
  23. package/dist/{persistent-memory-HWFNDQFQ.js → persistent-memory-ZCQKLIC5.js} +12 -2
  24. package/dist/{pr-OICMUN6R.js → pr-GIDFO4KP.js} +4 -4
  25. package/dist/{run-tests-DSEW5HED.js → run-tests-BMH6QJN2.js} +2 -2
  26. package/dist/{run-tests-B3FSE5NV.js → run-tests-WCZBWQFS.js} +2 -2
  27. package/dist/{server-2FS65CQZ.js → server-A5NGGDMP.js} +11 -11
  28. package/dist/{server-EDCGPEGC.js → server-FEFIFJDA.js} +5 -5
  29. package/dist/{task-orchestrator-WCZYV3TE.js → task-orchestrator-J2H6OV6R.js} +5 -5
  30. package/dist/{usage-WVUYNLOD.js → usage-7WJC234G.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-PNNZRJ67.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-PLEXBFCR.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-GEWPLNKA.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
 
@@ -11828,6 +11830,8 @@ ${lines.join("\n")}`;
11828
11830
  };
11829
11831
 
11830
11832
  // src/tools/builtin/recall-memory.ts
11833
+ import { join as join14 } from "path";
11834
+ import { homedir as homedir7 } from "os";
11831
11835
  function formatHit(h, i) {
11832
11836
  const ts = h.chunk.timestamp.slice(0, 16).replace("T", " ");
11833
11837
  const title = h.chunk.sessionTitle ? ` \xB7 ${h.chunk.sessionTitle}` : "";
@@ -11840,7 +11844,7 @@ function formatHit(h, i) {
11840
11844
  var recallMemoryTool = {
11841
11845
  definition: {
11842
11846
  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".',
11847
+ 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
11848
  parameters: {
11845
11849
  query: {
11846
11850
  type: "string",
@@ -11877,9 +11881,21 @@ var recallMemoryTool = {
11877
11881
  const excludeCurrent = Boolean(args["excludeCurrentSession"]);
11878
11882
  const currentId = args["currentSessionId"] ? String(args["currentSessionId"]) : void 0;
11879
11883
  const minScore = args["minScore"] !== void 0 ? Number(args["minScore"]) : 0.25;
11884
+ const configDir = join14(homedir7(), CONFIG_DIR_NAME);
11885
+ let persistentSection = "";
11886
+ try {
11887
+ const persistentHits = searchPersistentMemories(configDir, query, process.cwd(), 3);
11888
+ if (persistentHits.length > 0) {
11889
+ touchMemoryReferences(configDir, persistentHits.map((h) => h.entry.id));
11890
+ persistentSection = `\u2500\u2500 Persistent memory (${persistentHits.length} hit(s)) \u2500\u2500
11891
+ ` + persistentHits.map((h) => `[id ${h.entry.id.slice(0, 8)} \xB7 ${h.entry.scope} \xB7 coverage ${h.score.toFixed(2)}]
11892
+ ${h.entry.content}`).join("\n\n") + "\n\n";
11893
+ }
11894
+ } catch {
11895
+ }
11880
11896
  const status = loadChatIndex();
11881
11897
  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.";
11898
+ 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
11899
  }
11884
11900
  const hits = await searchChatMemory(query, {
11885
11901
  topK,
@@ -11887,11 +11903,11 @@ var recallMemoryTool = {
11887
11903
  excludeSessionId: excludeCurrent ? currentId : void 0
11888
11904
  });
11889
11905
  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.`;
11906
+ 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
11907
  }
11892
- const header = `Found ${hits.length} memory hit(s) for "${query}" (min-score ${minScore}):
11908
+ const header = `Found ${hits.length} chat-history hit(s) for "${query}" (min-score ${minScore}):
11893
11909
  `;
11894
- return header + "\n" + hits.map(formatHit).join("\n\n");
11910
+ return persistentSection + header + "\n" + hits.map(formatHit).join("\n\n");
11895
11911
  }
11896
11912
  };
11897
11913
 
@@ -11920,7 +11936,7 @@ function estimateToolDefinitionTokens(def) {
11920
11936
  // src/tools/registry.ts
11921
11937
  import { pathToFileURL } from "url";
11922
11938
  import { existsSync as existsSync20, mkdirSync as mkdirSync9, readdirSync as readdirSync9 } from "fs";
11923
- import { join as join14 } from "path";
11939
+ import { join as join15 } from "path";
11924
11940
  var ToolRegistry = class {
11925
11941
  tools = /* @__PURE__ */ new Map();
11926
11942
  pluginToolNames = /* @__PURE__ */ new Set();
@@ -12107,12 +12123,12 @@ var ToolRegistry = class {
12107
12123
  process.stderr.write(
12108
12124
  `
12109
12125
  [plugins] \u26A0 Loading ${files.length} plugin(s) with FULL system privileges:
12110
- ` + files.map((f) => ` + ${join14(pluginsDir, f)}`).join("\n") + "\n\n"
12126
+ ` + files.map((f) => ` + ${join15(pluginsDir, f)}`).join("\n") + "\n\n"
12111
12127
  );
12112
12128
  let loaded = 0;
12113
12129
  for (const file of files) {
12114
12130
  try {
12115
- const fileUrl = pathToFileURL(join14(pluginsDir, file)).href;
12131
+ const fileUrl = pathToFileURL(join15(pluginsDir, file)).href;
12116
12132
  const mod = await import(fileUrl);
12117
12133
  const tool = mod.tool ?? mod.default?.tool ?? mod.default;
12118
12134
  if (!tool || typeof tool.execute !== "function" || !tool.definition?.name) {
@@ -12659,7 +12675,7 @@ var McpManager = class {
12659
12675
 
12660
12676
  // src/skills/manager.ts
12661
12677
  import { existsSync as existsSync21, readdirSync as readdirSync10, mkdirSync as mkdirSync10, statSync as statSync8 } from "fs";
12662
- import { join as join15 } from "path";
12678
+ import { join as join16 } from "path";
12663
12679
 
12664
12680
  // src/skills/types.ts
12665
12681
  import { readFileSync as readFileSync15 } from "fs";
@@ -12749,13 +12765,13 @@ var SkillManager = class {
12749
12765
  }
12750
12766
  for (const entry of entries) {
12751
12767
  let filePath;
12752
- const fullPath = join15(dir, entry);
12768
+ const fullPath = join16(dir, entry);
12753
12769
  if (entry.endsWith(".md")) {
12754
12770
  filePath = fullPath;
12755
12771
  } else {
12756
12772
  try {
12757
12773
  if (statSync8(fullPath).isDirectory()) {
12758
- const skillMd = join15(fullPath, "SKILL.md");
12774
+ const skillMd = join16(fullPath, "SKILL.md");
12759
12775
  if (existsSync21(skillMd)) filePath = skillMd;
12760
12776
  else continue;
12761
12777
  } else {
@@ -13261,10 +13277,10 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13261
13277
 
13262
13278
  // src/repl/dev-state.ts
13263
13279
  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";
13280
+ import { join as join17 } from "path";
13281
+ import { homedir as homedir8 } from "os";
13266
13282
  function getDevStatePath() {
13267
- return join16(homedir7(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
13283
+ return join17(homedir8(), CONFIG_DIR_NAME, DEV_STATE_FILE_NAME);
13268
13284
  }
13269
13285
  function loadDevState() {
13270
13286
  const path3 = getDevStatePath();
@@ -13527,7 +13543,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13527
13543
 
13528
13544
  // src/core/context-files.ts
13529
13545
  import { existsSync as existsSync24, readFileSync as readFileSync18 } from "fs";
13530
- import { join as join17, relative as relative4, resolve as resolve8 } from "path";
13546
+ import { join as join18, relative as relative4, resolve as resolve8 } from "path";
13531
13547
  function uniqueNonEmpty(values) {
13532
13548
  const seen = /* @__PURE__ */ new Set();
13533
13549
  const out = [];
@@ -13604,7 +13620,7 @@ function readContextFile(level, filePath, cwd, maxBytes) {
13604
13620
  function findFirstContextFile(level, dir, cwd, candidates, maxBytes) {
13605
13621
  const skipped = [];
13606
13622
  for (const candidate of candidates) {
13607
- const filePath = join17(dir, candidate);
13623
+ const filePath = join18(dir, candidate);
13608
13624
  if (!existsSync24(filePath)) continue;
13609
13625
  const result = readContextFile(level, filePath, cwd, maxBytes);
13610
13626
  if (result.skipped) skipped.push(result.skipped);
@@ -13688,7 +13704,7 @@ import { dirname as dirname9 } from "path";
13688
13704
 
13689
13705
  // src/repl/commands/project-init.ts
13690
13706
  import { existsSync as existsSync25, readFileSync as readFileSync19, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
13691
- import { join as join18 } from "path";
13707
+ import { join as join19 } from "path";
13692
13708
  var SCAN_SKIP_DIRS = /* @__PURE__ */ new Set([
13693
13709
  "node_modules",
13694
13710
  ".git",
@@ -13732,11 +13748,11 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13732
13748
  const sorted = filtered.sort((a, b) => {
13733
13749
  let aIsDir = false, bIsDir = false;
13734
13750
  try {
13735
- aIsDir = statSync9(join18(d, a)).isDirectory();
13751
+ aIsDir = statSync9(join19(d, a)).isDirectory();
13736
13752
  } catch {
13737
13753
  }
13738
13754
  try {
13739
- bIsDir = statSync9(join18(d, b)).isDirectory();
13755
+ bIsDir = statSync9(join19(d, b)).isDirectory();
13740
13756
  } catch {
13741
13757
  }
13742
13758
  if (aIsDir !== bIsDir) return aIsDir ? -1 : 1;
@@ -13744,7 +13760,7 @@ function scanDirTree(dir, maxDepth = 2, maxEntries = 80) {
13744
13760
  });
13745
13761
  for (let i = 0; i < sorted.length && count < maxEntries; i++) {
13746
13762
  const name = sorted[i];
13747
- const fullPath = join18(d, name);
13763
+ const fullPath = join19(d, name);
13748
13764
  const isLast = i === sorted.length - 1;
13749
13765
  const connector = isLast ? "+-- " : "|-- ";
13750
13766
  let isDir;
@@ -13771,7 +13787,7 @@ function scanProject(cwd) {
13771
13787
  configFiles: [],
13772
13788
  directoryStructure: ""
13773
13789
  };
13774
- const check = (file) => existsSync25(join18(cwd, file));
13790
+ const check = (file) => existsSync25(join19(cwd, file));
13775
13791
  const configCandidates = [
13776
13792
  "package.json",
13777
13793
  "tsconfig.json",
@@ -13798,7 +13814,7 @@ function scanProject(cwd) {
13798
13814
  info.type = "node";
13799
13815
  info.language = check("tsconfig.json") ? "TypeScript" : "JavaScript";
13800
13816
  try {
13801
- const pkg = JSON.parse(readFileSync19(join18(cwd, "package.json"), "utf-8"));
13817
+ const pkg = JSON.parse(readFileSync19(join19(cwd, "package.json"), "utf-8"));
13802
13818
  const scripts = pkg.scripts ?? {};
13803
13819
  info.buildCommand = scripts.build ? "npm run build" : void 0;
13804
13820
  info.testCommand = scripts.test ? "npm test" : void 0;
@@ -14447,7 +14463,7 @@ function resolveRoleProviders(roles, lookup, defaultProvider, defaultModel, avai
14447
14463
  }
14448
14464
 
14449
14465
  // src/hub/persist.ts
14450
- import { join as join19 } from "path";
14466
+ import { join as join20 } from "path";
14451
14467
  function discussionToMessages(state2) {
14452
14468
  const out = [];
14453
14469
  const t0 = state2.messages[0]?.timestamp ?? /* @__PURE__ */ new Date();
@@ -14485,7 +14501,7 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
14485
14501
  session.title = `[Hub] ${state2.topic.slice(0, 48)}`.replace(/\n/g, " ");
14486
14502
  session.titleAiGenerated = true;
14487
14503
  await sm.save();
14488
- return { id: session.id, path: join19(config.getHistoryDir(), `${session.id}.json`) };
14504
+ return { id: session.id, path: join20(config.getHistoryDir(), `${session.id}.json`) };
14489
14505
  }
14490
14506
 
14491
14507
  // src/web/commands/provider-commands.ts
@@ -14574,7 +14590,7 @@ async function handlePlan(args, ctx) {
14574
14590
 
14575
14591
  // src/web/commands/_shared.ts
14576
14592
  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";
14593
+ import { join as join23, resolve as resolve9, dirname as dirname8 } from "path";
14578
14594
 
14579
14595
  // src/cli/review-prompts.ts
14580
14596
  function buildReviewPrompt(diff, gitContextStr, detailed) {
@@ -14647,7 +14663,7 @@ function readGitDiff(options = {}) {
14647
14663
 
14648
14664
  // src/diagnostics/doctor-report.ts
14649
14665
  import { existsSync as existsSync27, statSync as statSync11 } from "fs";
14650
- import { join as join21 } from "path";
14666
+ import { join as join22 } from "path";
14651
14667
  import { arch as arch2, platform as platform7, release as release2 } from "os";
14652
14668
 
14653
14669
  // src/diagnostics/crash-log.ts
@@ -14660,13 +14676,13 @@ import {
14660
14676
  unlinkSync as unlinkSync6,
14661
14677
  writeFileSync as writeFileSync2
14662
14678
  } from "fs";
14663
- import { join as join20 } from "path";
14664
- import { homedir as homedir8, platform as platform6, release, arch } from "os";
14679
+ import { join as join21 } from "path";
14680
+ import { homedir as homedir9, platform as platform6, release, arch } from "os";
14665
14681
  var LOGS_DIR_NAME = "logs";
14666
14682
  var CRASH_LOG_PREFIX = "crash-";
14667
14683
  function getLogsDir(configDir) {
14668
- const base = configDir ?? join20(homedir8(), CONFIG_DIR_NAME);
14669
- return join20(base, LOGS_DIR_NAME);
14684
+ const base = configDir ?? join21(homedir9(), CONFIG_DIR_NAME);
14685
+ return join21(base, LOGS_DIR_NAME);
14670
14686
  }
14671
14687
  function truncate(s, n) {
14672
14688
  return s.length <= n ? s : s.slice(0, n) + "\u2026";
@@ -14683,7 +14699,7 @@ function listRecentCrashes(limit = 10, configDir) {
14683
14699
  }
14684
14700
  for (const name of names) {
14685
14701
  if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
14686
- const full = join20(dir, name);
14702
+ const full = join21(dir, name);
14687
14703
  try {
14688
14704
  const st = statSync10(full);
14689
14705
  const head = readFileSync20(full, "utf-8").split("\n").slice(0, 20);
@@ -14705,7 +14721,7 @@ function listRecentCrashes(limit = 10, configDir) {
14705
14721
  return files.slice(0, limit);
14706
14722
  }
14707
14723
  function getConfigDirUsage(configDir) {
14708
- const base = configDir ?? join20(homedir8(), CONFIG_DIR_NAME);
14724
+ const base = configDir ?? join21(homedir9(), CONFIG_DIR_NAME);
14709
14725
  if (!existsSync26(base)) return { totalBytes: 0, entries: [] };
14710
14726
  const entries = [];
14711
14727
  let total = 0;
@@ -14716,7 +14732,7 @@ function getConfigDirUsage(configDir) {
14716
14732
  return { totalBytes: 0, entries: [] };
14717
14733
  }
14718
14734
  for (const name of names) {
14719
- const full = join20(base, name);
14735
+ const full = join21(base, name);
14720
14736
  const bytes = dirSize(full);
14721
14737
  entries.push({ name, bytes });
14722
14738
  total += bytes;
@@ -14731,7 +14747,7 @@ function dirSize(path3) {
14731
14747
  if (!st.isDirectory()) return 0;
14732
14748
  let sum = 0;
14733
14749
  for (const name of readdirSync12(path3)) {
14734
- sum += dirSize(join20(path3, name));
14750
+ sum += dirSize(join21(path3, name));
14735
14751
  }
14736
14752
  return sum;
14737
14753
  } catch {
@@ -14784,12 +14800,12 @@ function buildDoctorReport(options) {
14784
14800
  configDir,
14785
14801
  providers: options.providers.listAll().map((p) => ({ id: p.id, displayName: p.displayName, configured: p.configured })),
14786
14802
  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"))
14803
+ checkFile("config.json", join22(configDir, "config.json")),
14804
+ checkFile("memory.md", join22(configDir, MEMORY_FILE_NAME)),
14805
+ checkFile("memory.jsonl", join22(configDir, "memory.jsonl")),
14806
+ checkFile("dev-state.md", join22(configDir, DEV_STATE_FILE_NAME)),
14807
+ checkFile("hooks-trust.json", join22(configDir, "hooks-trust.json")),
14808
+ checkFile("plugin-state.json", join22(configDir, "plugins", "plugin-state.json"))
14793
14809
  ],
14794
14810
  context: {
14795
14811
  enabled: contextSetting !== false,
@@ -14824,7 +14840,7 @@ function buildDoctorReport(options) {
14824
14840
  disabled: hooks.filter((h) => h.disabled).length
14825
14841
  },
14826
14842
  plugins: {
14827
- root: join21(configDir, "plugins"),
14843
+ root: join22(configDir, "plugins"),
14828
14844
  installed: plugins.length,
14829
14845
  active: activeAssets.plugins.length,
14830
14846
  invalid: plugins.filter((p) => !p.valid).length,
@@ -14839,7 +14855,7 @@ function buildDoctorReport(options) {
14839
14855
  mcp: {
14840
14856
  enabled: config.get("mcpEnabled"),
14841
14857
  configured: Object.keys(mcpServers).length,
14842
- projectConfigExists: existsSync27(join21(projectRoot, MCP_PROJECT_CONFIG_NAME)),
14858
+ projectConfigExists: existsSync27(join22(projectRoot, MCP_PROJECT_CONFIG_NAME)),
14843
14859
  statuses: options.mcpStatuses ?? []
14844
14860
  },
14845
14861
  recentCrashes: listRecentCrashes(5, configDir),
@@ -15067,7 +15083,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15067
15083
  Cost: ${formatCost(cost)}` : "";
15068
15084
  let memoryLine = "";
15069
15085
  try {
15070
- const { countPendingMemories } = await import("./persistent-memory-HWFNDQFQ.js");
15086
+ const { countPendingMemories } = await import("./persistent-memory-ZCQKLIC5.js");
15071
15087
  const pending = countPendingMemories(ctx.config.getConfigDir());
15072
15088
  if (pending > 0) memoryLine = `
15073
15089
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -15651,7 +15667,7 @@ async function handlePlugin(args, ctx) {
15651
15667
  lines.push("");
15652
15668
  }
15653
15669
  if (pluginTools.length > 0) {
15654
- const legacyDir = join22(configDir, PLUGINS_DIR_NAME);
15670
+ const legacyDir = join23(configDir, PLUGINS_DIR_NAME);
15655
15671
  lines.push(`**Legacy JS tools** (${pluginTools.length}):`);
15656
15672
  lines.push(`Dir: ${legacyDir}`);
15657
15673
  for (const t of pluginTools) lines.push(` \u2022 ${t.definition.name} \u2014 ${t.definition.description}`);
@@ -15775,7 +15791,7 @@ ${activated.meta.description || ""}` });
15775
15791
  }
15776
15792
  async function handleCommands(_args, ctx) {
15777
15793
  const configDir = ctx.config.getConfigDir();
15778
- const commandsDir = join22(configDir, CUSTOM_COMMANDS_DIR_NAME);
15794
+ const commandsDir = join23(configDir, CUSTOM_COMMANDS_DIR_NAME);
15779
15795
  if (!existsSync28(commandsDir)) {
15780
15796
  ctx.send({ type: "info", message: `No custom commands directory.
15781
15797
  Create: ${commandsDir}/ with .md files.` });
@@ -15876,7 +15892,7 @@ async function handleSecurityReview(args, ctx) {
15876
15892
  async function handleTest(args, ctx) {
15877
15893
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
15878
15894
  try {
15879
- const { executeTests } = await import("./run-tests-B3FSE5NV.js");
15895
+ const { executeTests } = await import("./run-tests-WCZBWQFS.js");
15880
15896
  const argStr = args.join(" ").trim();
15881
15897
  let testArgs = {};
15882
15898
  if (argStr) {
@@ -15943,7 +15959,7 @@ async function handleDiff(args, ctx) {
15943
15959
  }
15944
15960
  async function handleInit(args, ctx) {
15945
15961
  const cwd = process.cwd();
15946
- const targetPath = join22(cwd, "AICLI.md");
15962
+ const targetPath = join23(cwd, "AICLI.md");
15947
15963
  const force = args.includes("--force");
15948
15964
  if (existsSync28(targetPath) && !force) {
15949
15965
  ctx.send({ type: "info", message: `AICLI.md already exists at ${targetPath}
@@ -16140,7 +16156,7 @@ async function handleMemory(args, ctx) {
16140
16156
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16141
16157
  } else if (sub === "export") {
16142
16158
  if (args[1] === "md") {
16143
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-HWFNDQFQ.js");
16159
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-ZCQKLIC5.js");
16144
16160
  ctx.send({
16145
16161
  type: "export_data",
16146
16162
  format: "md",
@@ -18038,7 +18054,7 @@ async function setupProxy(configProxy) {
18038
18054
 
18039
18055
  // src/web/auth.ts
18040
18056
  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";
18057
+ import { isAbsolute as isAbsolute3, join as join26, relative as relative5 } from "path";
18042
18058
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
18043
18059
  var USERS_FILE = "users.json";
18044
18060
  var TOKEN_EXPIRY_HOURS = 24;
@@ -18053,7 +18069,7 @@ var AuthManager = class {
18053
18069
  db;
18054
18070
  constructor(baseDir) {
18055
18071
  this.baseDir = baseDir;
18056
- this.usersFile = join25(baseDir, USERS_FILE);
18072
+ this.usersFile = join26(baseDir, USERS_FILE);
18057
18073
  this.db = this.loadOrCreate();
18058
18074
  }
18059
18075
  // ── Public API ─────────────────────────────────────────────────
@@ -18082,9 +18098,9 @@ var AuthManager = class {
18082
18098
  }
18083
18099
  const salt = randomBytes(16).toString("hex");
18084
18100
  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 });
18101
+ const dataDir = join26(USERS_DIR, username);
18102
+ const fullDataDir = join26(this.baseDir, dataDir);
18103
+ mkdirSync15(join26(fullDataDir, "history"), { recursive: true });
18088
18104
  const user = {
18089
18105
  username,
18090
18106
  passwordHash,
@@ -18199,7 +18215,7 @@ var AuthManager = class {
18199
18215
  getUserDataDir(username) {
18200
18216
  const user = this.db.users.find((u) => u.username === username);
18201
18217
  if (!user) throw new Error(`User not found: ${username}`);
18202
- return join25(this.baseDir, user.dataDir);
18218
+ return join26(this.baseDir, user.dataDir);
18203
18219
  }
18204
18220
  /** List all usernames */
18205
18221
  listUsers() {
@@ -18235,30 +18251,30 @@ var AuthManager = class {
18235
18251
  const err = this.register(username, password);
18236
18252
  if (err) return err;
18237
18253
  const userDir = this.getUserDataDir(username);
18238
- const globalConfig = join25(this.baseDir, "config.json");
18254
+ const globalConfig = join26(this.baseDir, "config.json");
18239
18255
  if (existsSync30(globalConfig)) {
18240
18256
  try {
18241
18257
  const content = readFileSync23(globalConfig, "utf-8");
18242
- writeFileSync5(join25(userDir, "config.json"), content, "utf-8");
18258
+ writeFileSync5(join26(userDir, "config.json"), content, "utf-8");
18243
18259
  } catch {
18244
18260
  }
18245
18261
  }
18246
- const globalMemory = join25(this.baseDir, "memory.md");
18262
+ const globalMemory = join26(this.baseDir, "memory.md");
18247
18263
  if (existsSync30(globalMemory)) {
18248
18264
  try {
18249
18265
  const content = readFileSync23(globalMemory, "utf-8");
18250
- writeFileSync5(join25(userDir, "memory.md"), content, "utf-8");
18266
+ writeFileSync5(join26(userDir, "memory.md"), content, "utf-8");
18251
18267
  } catch {
18252
18268
  }
18253
18269
  }
18254
- const globalHistory = join25(this.baseDir, "history");
18270
+ const globalHistory = join26(this.baseDir, "history");
18255
18271
  if (existsSync30(globalHistory)) {
18256
18272
  try {
18257
18273
  const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
18258
- const userHistory = join25(userDir, "history");
18274
+ const userHistory = join26(userDir, "history");
18259
18275
  for (const f of files) {
18260
18276
  try {
18261
- copyFileSync(join25(globalHistory, f), join25(userHistory, f));
18277
+ copyFileSync(join26(globalHistory, f), join26(userHistory, f));
18262
18278
  } catch {
18263
18279
  }
18264
18280
  }
@@ -18305,7 +18321,7 @@ var AuthManager = class {
18305
18321
  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
18322
  return false;
18307
18323
  }
18308
- const dataDirFromBase = relative5(this.baseDir, join25(this.baseDir, record.dataDir));
18324
+ const dataDirFromBase = relative5(this.baseDir, join26(this.baseDir, record.dataDir));
18309
18325
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
18310
18326
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
18311
18327
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -18421,7 +18437,7 @@ async function startWebServer(options = {}) {
18421
18437
  }
18422
18438
  }
18423
18439
  let skillManager = null;
18424
- const skillsDir = join26(config.getConfigDir(), SKILLS_DIR_NAME);
18440
+ const skillsDir = join27(config.getConfigDir(), SKILLS_DIR_NAME);
18425
18441
  if (existsSync31(skillsDir)) {
18426
18442
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
18427
18443
  skillManager.loadSkills(pluginAssets.skillDirs);
@@ -18493,18 +18509,18 @@ async function startWebServer(options = {}) {
18493
18509
  next();
18494
18510
  };
18495
18511
  const moduleDir = getModuleDir();
18496
- let clientDir = join26(moduleDir, "web", "client");
18512
+ let clientDir = join27(moduleDir, "web", "client");
18497
18513
  if (!existsSync31(clientDir)) {
18498
- clientDir = join26(moduleDir, "client");
18514
+ clientDir = join27(moduleDir, "client");
18499
18515
  }
18500
18516
  if (!existsSync31(clientDir)) {
18501
- clientDir = join26(moduleDir, "..", "..", "src", "web", "client");
18517
+ clientDir = join27(moduleDir, "..", "..", "src", "web", "client");
18502
18518
  }
18503
18519
  if (!existsSync31(clientDir)) {
18504
- clientDir = join26(process.cwd(), "src", "web", "client");
18520
+ clientDir = join27(process.cwd(), "src", "web", "client");
18505
18521
  }
18506
18522
  console.log(` Static files: ${clientDir}`);
18507
- app.use("/vendor", express.static(join26(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18523
+ app.use("/vendor", express.static(join27(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18508
18524
  app.use(express.static(clientDir));
18509
18525
  app.get("/api/status", (_req, res) => {
18510
18526
  res.json({
@@ -18571,7 +18587,7 @@ async function startWebServer(options = {}) {
18571
18587
  app.get("/api/files", requireAuth, (req, res) => {
18572
18588
  const cwd = process.cwd();
18573
18589
  const prefix = req.query.prefix || "";
18574
- const targetDir = join26(cwd, prefix);
18590
+ const targetDir = join27(cwd, prefix);
18575
18591
  try {
18576
18592
  const canonicalTarget = realpathSync3(resolve12(targetDir));
18577
18593
  const canonicalCwd = realpathSync3(resolve12(cwd));
@@ -18588,7 +18604,7 @@ async function startWebServer(options = {}) {
18588
18604
  const entries = readdirSync16(targetDir, { withFileTypes: true });
18589
18605
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
18590
18606
  name: e.name,
18591
- path: relative6(cwd, join26(targetDir, e.name)).replace(/\\/g, "/"),
18607
+ path: relative6(cwd, join27(targetDir, e.name)).replace(/\\/g, "/"),
18592
18608
  isDir: e.isDirectory()
18593
18609
  }));
18594
18610
  res.json({ files });
@@ -18628,7 +18644,7 @@ async function startWebServer(options = {}) {
18628
18644
  try {
18629
18645
  const authUser = req._authUser;
18630
18646
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
18631
- const filePath = join26(histDir, `${id}.json`);
18647
+ const filePath = join27(histDir, `${id}.json`);
18632
18648
  if (!existsSync31(filePath)) {
18633
18649
  res.status(404).json({ error: "Session not found" });
18634
18650
  return;
@@ -18657,7 +18673,7 @@ async function startWebServer(options = {}) {
18657
18673
  return;
18658
18674
  }
18659
18675
  const cwd = process.cwd();
18660
- const fullPath = resolve12(join26(cwd, filePath));
18676
+ const fullPath = resolve12(join27(cwd, filePath));
18661
18677
  try {
18662
18678
  const canonicalFull = realpathSync3(fullPath);
18663
18679
  const canonicalCwd = realpathSync3(resolve12(cwd));
@@ -18930,14 +18946,14 @@ function resolveProjectMcpPath() {
18930
18946
  const cwd = process.cwd();
18931
18947
  const gitRoot = getGitRoot(cwd);
18932
18948
  const projectRoot = gitRoot ?? cwd;
18933
- const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
18949
+ const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18934
18950
  return existsSync31(configPath) ? configPath : null;
18935
18951
  }
18936
18952
  function loadProjectMcpConfig() {
18937
18953
  const cwd = process.cwd();
18938
18954
  const gitRoot = getGitRoot(cwd);
18939
18955
  const projectRoot = gitRoot ?? cwd;
18940
- const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
18956
+ const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18941
18957
  if (!existsSync31(configPath)) return null;
18942
18958
  try {
18943
18959
  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-J2H6OV6R.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {