jinzd-ai-cli 0.4.330 → 0.4.331

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 (41) hide show
  1. package/dist/{batch-GXITPLER.js → batch-OOHC5POO.js} +2 -2
  2. package/dist/{chunk-DX2U6QK4.js → chunk-56ME7PB2.js} +1 -1
  3. package/dist/{chunk-GWEBO4RF.js → chunk-6BGW25LG.js} +1 -1
  4. package/dist/{chunk-E2W2MI6H.js → chunk-C6GA7H5D.js} +1 -72
  5. package/dist/{chunk-QU74ONFF.js → chunk-CM5C7ZSM.js} +1 -1
  6. package/dist/{chunk-3YVZJHTF.js → chunk-DTVN2LDU.js} +1 -1
  7. package/dist/{chunk-265M6ZLH.js → chunk-EWARNWJ4.js} +4 -4
  8. package/dist/{chunk-CCFCPAKN.js → chunk-IJNDIOOQ.js} +1 -1
  9. package/dist/{chunk-LLXHA2LA.js → chunk-L3FDFFD2.js} +8 -8
  10. package/dist/{chunk-LUJ4JVMI.js → chunk-MJSK6ZYR.js} +4 -4
  11. package/dist/{chunk-C2Z77RTU.js → chunk-MN25ELTF.js} +15 -4
  12. package/dist/{chunk-72AR23R2.js → chunk-NOLK5C4U.js} +54 -2
  13. package/dist/{chunk-HMQA2R3O.js → chunk-Q26V2PNA.js} +1 -1
  14. package/dist/{chunk-GEC3MEVQ.js → chunk-QFF2PTI3.js} +6 -4
  15. package/dist/{chunk-2SYDIWRU.js → chunk-R3XIU7NS.js} +1 -1
  16. package/dist/{chunk-M5B6G6AY.js → chunk-RZDRBFAB.js} +9 -7
  17. package/dist/{chunk-DU44SD6A.js → chunk-TF2FNRDZ.js} +1 -1
  18. package/dist/chunk-W4P2KJZN.js +75 -0
  19. package/dist/{chunk-AJITHMRE.js → chunk-YCDF6FNR.js} +1 -1
  20. package/dist/{ci-6K3JNHB4.js → ci-HNYUXJUE.js} +7 -6
  21. package/dist/{ci-format-2L3RFJVH.js → ci-format-ZLBEAU7Z.js} +2 -2
  22. package/dist/{constants-DLJECTGQ.js → constants-4EH6Y6VI.js} +1 -1
  23. package/dist/{constants-J5SJ232X.js → constants-JM6MK5SS.js} +1 -1
  24. package/dist/{doctor-cli-BHS7G2XY.js → doctor-cli-VCNERMX5.js} +7 -6
  25. package/dist/electron-server.js +193 -130
  26. package/dist/{hub-PPG4N6QQ.js → hub-3OXLWTEP.js} +8 -18
  27. package/dist/{hub-server-JLC7CNP7.js → hub-server-LJWXNEWK.js} +2 -1
  28. package/dist/index.js +20 -19
  29. package/dist/{persistent-memory-3XTSZ3QR.js → persistent-memory-LMVWIHMX.js} +2 -2
  30. package/dist/{persistent-memory-O4T2OTVV.js → persistent-memory-PAS7NAPQ.js} +2 -2
  31. package/dist/{pr-M6ZY4CEK.js → pr-IMR62OHN.js} +7 -6
  32. package/dist/{run-tests-H3DIUCDB.js → run-tests-2TVEWCQI.js} +2 -2
  33. package/dist/{run-tests-WQE3XTUL.js → run-tests-MQVGE6FK.js} +2 -2
  34. package/dist/{server-J2B26DZK.js → server-55X6MCGX.js} +7 -6
  35. package/dist/{server-5NQSYQ2T.js → server-6MS2NGEJ.js} +29 -19
  36. package/dist/{task-orchestrator-CI7EDT25.js → task-orchestrator-KIDJB7NP.js} +9 -7
  37. package/dist/{usage-AJYZ5A7P.js → usage-X2CQYAUA.js} +2 -2
  38. package/dist/web/client/app.js +19 -0
  39. package/dist/web/client/app.js.br +0 -0
  40. package/dist/web/client/app.js.gz +0 -0
  41. package/package.json +1 -1
@@ -55,7 +55,7 @@ import {
55
55
  touchMemoryReferences,
56
56
  updateMemoryApproval,
57
57
  updateMemoryEntry
58
- } from "./chunk-2SYDIWRU.js";
58
+ } from "./chunk-R3XIU7NS.js";
59
59
  import {
60
60
  DEFAULT_PATTERNS,
61
61
  redactJson,
@@ -81,7 +81,7 @@ import {
81
81
  recoverGbkMojibake,
82
82
  runTestsTool,
83
83
  shellInvocation
84
- } from "./chunk-DU44SD6A.js";
84
+ } from "./chunk-TF2FNRDZ.js";
85
85
  import {
86
86
  getCurrentSessionKey,
87
87
  getExecutionConfigDir,
@@ -123,7 +123,7 @@ import {
123
123
  SUBAGENT_MAX_ROUNDS_LIMIT,
124
124
  VERSION,
125
125
  buildUserIdentityPrompt
126
- } from "./chunk-3YVZJHTF.js";
126
+ } from "./chunk-DTVN2LDU.js";
127
127
 
128
128
  // src/web/access.ts
129
129
  import { randomBytes, timingSafeEqual } from "crypto";
@@ -205,8 +205,8 @@ function imageValidationError(images) {
205
205
  }
206
206
 
207
207
  // src/web/server.ts
208
- import { join as join25, dirname as dirname12, resolve as resolve12, relative as relative6, sep as sep5, extname as extname3, resolve as resolvePath } from "path";
209
- import { existsSync as existsSync31, readFileSync as readFileSync22, readdirSync as readdirSync15, statSync as statSync16, realpathSync as realpathSync3, createReadStream } from "fs";
208
+ import { join as join26, dirname as dirname12, resolve as resolve12, relative as relative6, sep as sep5, extname as extname3, resolve as resolvePath } from "path";
209
+ import { existsSync as existsSync32, readFileSync as readFileSync23, readdirSync as readdirSync16, statSync as statSync16, realpathSync as realpathSync3, createReadStream } from "fs";
210
210
  import { networkInterfaces as networkInterfaces2 } from "os";
211
211
 
212
212
  // src/config/config-manager.ts
@@ -2859,12 +2859,12 @@ function findPhantomClaims(content, extraMessages) {
2859
2859
  const claimed = extractClaimedFilePaths(content);
2860
2860
  if (claimed.length === 0) return [];
2861
2861
  const normalize = (p) => p.replace(/\\/g, "/").toLowerCase().replace(/^\.\//, "");
2862
- const basename11 = (p) => {
2862
+ const basename12 = (p) => {
2863
2863
  const parts = normalize(p).split("/");
2864
2864
  return parts[parts.length - 1] ?? "";
2865
2865
  };
2866
2866
  const written = extractWrittenFilePaths(extraMessages).map(normalize);
2867
- const writtenBases = new Set(written.map(basename11));
2867
+ const writtenBases = new Set(written.map(basename12));
2868
2868
  const writtenFull = new Set(written);
2869
2869
  const bashText = extractBashCommands(extraMessages).map((c) => c.replace(/\\/g, "/").toLowerCase()).join("\n");
2870
2870
  return claimed.filter((raw) => {
@@ -2873,8 +2873,8 @@ function findPhantomClaims(content, extraMessages) {
2873
2873
  for (const w of writtenFull) {
2874
2874
  if (w.endsWith("/" + norm2) || norm2.endsWith("/" + w)) return false;
2875
2875
  }
2876
- if (writtenBases.has(basename11(norm2))) return false;
2877
- const base = basename11(norm2);
2876
+ if (writtenBases.has(basename12(norm2))) return false;
2877
+ const base = basename12(norm2);
2878
2878
  if (base && bashText.includes(base)) return false;
2879
2879
  return true;
2880
2880
  });
@@ -16004,8 +16004,12 @@ function stripConvergedMarker(content) {
16004
16004
 
16005
16005
  // src/hub/agent.ts
16006
16006
  var PASS_MARKER = "[PASS]";
16007
+ function stripThinkBlocks(raw) {
16008
+ const filter = new ThinkTagFilter();
16009
+ return filter.push(raw) + filter.flush();
16010
+ }
16007
16011
  function parseTurn(raw) {
16008
- const trimmed = raw.trim();
16012
+ const trimmed = stripThinkBlocks(raw).trim();
16009
16013
  const upper = trimmed.toUpperCase();
16010
16014
  if (upper.startsWith(PASS_MARKER) || upper === PASS_MARKER) {
16011
16015
  return { content: "", passed: true, converged: false };
@@ -16085,6 +16089,7 @@ var HubAgent = class {
16085
16089
  const systemPrompt = this.buildSystemPrompt(topic, round, maxRounds, opts?.voteConverge);
16086
16090
  const messages = this.buildMessages(history);
16087
16091
  let raw = "";
16092
+ const thinkFilter = new ThinkTagFilter();
16088
16093
  const stream = provider.chatStream({
16089
16094
  messages,
16090
16095
  model: this.modelId,
@@ -16099,13 +16104,16 @@ var HubAgent = class {
16099
16104
  for await (const chunk of stream) {
16100
16105
  if (chunk.delta) {
16101
16106
  raw += chunk.delta;
16102
- onToken?.(chunk.delta);
16107
+ const visible = thinkFilter.push(chunk.delta);
16108
+ if (visible) onToken?.(visible);
16103
16109
  }
16104
16110
  if (opts?.signal?.aborted) break;
16105
16111
  }
16106
16112
  } catch (error) {
16107
16113
  if (!opts?.signal?.aborted) throw error;
16108
16114
  }
16115
+ const tail = thinkFilter.flush();
16116
+ if (tail) onToken?.(tail);
16109
16117
  const { content, passed, converged } = parseTurn(raw);
16110
16118
  return {
16111
16119
  speaker: this.role.id,
@@ -16140,7 +16148,7 @@ var HubAgent = class {
16140
16148
  maxTokens: 4096,
16141
16149
  ...this.thinking ?? {}
16142
16150
  });
16143
- return response.content.trim();
16151
+ return stripThinkBlocks(response.content).trim();
16144
16152
  }
16145
16153
  // ── Private ──────────────────────────────────────────────────────
16146
16154
  buildSystemPrompt(topic, round, maxRounds, voteConverge) {
@@ -16221,7 +16229,7 @@ Produce a structured, decision-oriented synthesis with these exact sections:
16221
16229
  4. **Action Items** \u2014 concrete next steps as a checklist. For each, suggest which role/expertise should own it, e.g. "- [ ] (\u67B6\u6784\u5E08) \u8BC4\u4F30\u670D\u52A1\u62C6\u5206\u8FB9\u754C".
16222
16230
  5. **Risks & Open Questions** \u2014 unresolved issues and what to watch.
16223
16231
 
16224
- Keep it tight (within ~600 words). Use the same language as the discussion.`;
16232
+ Keep it tight (within ~600 words). Use the same language as the discussion \u2014 including the section headings (translate them, e.g. \u51B3\u7B56 / \u5EFA\u8BAE\u3001\u5173\u952E\u5171\u8BC6\u3001\u5206\u6B67\u70B9\u3001\u884C\u52A8\u9879\u3001\u98CE\u9669\u4E0E\u5F00\u653E\u95EE\u9898 for a Chinese discussion).`;
16225
16233
  }
16226
16234
  };
16227
16235
 
@@ -16597,8 +16605,57 @@ function resolveRoleProviders(roles, lookup, defaultProvider, defaultModel, avai
16597
16605
  return { roles: outRoles, assignments, warnings };
16598
16606
  }
16599
16607
 
16608
+ // src/hub/custom-presets.ts
16609
+ import { existsSync as existsSync25, readdirSync as readdirSync12, readFileSync as readFileSync18 } from "fs";
16610
+ import { join as join18, basename as basename10 } from "path";
16611
+ var CUSTOM_PRESET_PREFIX = "custom:";
16612
+ var HUB_ROLES_DIRNAME = "hub-roles";
16613
+ function parseRolesJson(parsed) {
16614
+ const rawRoles = Array.isArray(parsed) ? parsed : parsed?.roles;
16615
+ if (!Array.isArray(rawRoles) || rawRoles.length === 0) {
16616
+ throw new Error("roles must be a non-empty array");
16617
+ }
16618
+ return rawRoles.map((r) => ({
16619
+ id: r.id ?? r.name?.toLowerCase().replace(/\s+/g, "-") ?? "agent",
16620
+ name: r.name ?? r.id ?? "Agent",
16621
+ persona: r.persona ?? r.description ?? `You are ${r.name ?? "an AI assistant"}.`,
16622
+ ...r.provider && { provider: r.provider },
16623
+ ...r.model && { model: r.model },
16624
+ ...r.color && { color: r.color }
16625
+ }));
16626
+ }
16627
+ function loadCustomPresets(configDir) {
16628
+ const dir = join18(configDir, HUB_ROLES_DIRNAME);
16629
+ const presets = [];
16630
+ const warnings = [];
16631
+ if (!existsSync25(dir)) return { presets, warnings };
16632
+ let files;
16633
+ try {
16634
+ files = readdirSync12(dir).filter((f) => f.toLowerCase().endsWith(".json")).sort();
16635
+ } catch (err) {
16636
+ return { presets, warnings: [`${dir}: ${err.message}`] };
16637
+ }
16638
+ for (const file of files) {
16639
+ const stem = basename10(file, file.slice(file.lastIndexOf(".")));
16640
+ try {
16641
+ const parsed = JSON.parse(readFileSync18(join18(dir, file), "utf-8").replace(/^/, ""));
16642
+ const roles = parseRolesJson(parsed);
16643
+ const meta = Array.isArray(parsed) ? {} : parsed;
16644
+ presets.push({
16645
+ id: `${CUSTOM_PRESET_PREFIX}${stem}`,
16646
+ name: typeof meta.name === "string" && meta.name.trim() ? meta.name.trim() : stem,
16647
+ description: typeof meta.description === "string" && meta.description.trim() ? meta.description.trim() : roles.map((r) => r.name).join("\xB7"),
16648
+ roles
16649
+ });
16650
+ } catch (err) {
16651
+ warnings.push(`${HUB_ROLES_DIRNAME}/${file}: ${err.message}`);
16652
+ }
16653
+ }
16654
+ return { presets, warnings };
16655
+ }
16656
+
16600
16657
  // src/hub/persist.ts
16601
- import { join as join18 } from "path";
16658
+ import { join as join19 } from "path";
16602
16659
  function discussionToMessages(state2) {
16603
16660
  const out = [];
16604
16661
  const t0 = state2.messages[0]?.timestamp ?? /* @__PURE__ */ new Date();
@@ -16636,7 +16693,7 @@ async function persistDiscussion(state2, config, defaultProvider, defaultModel)
16636
16693
  session.title = `[Hub] ${state2.topic.slice(0, 48)}`.replace(/\n/g, " ");
16637
16694
  session.titleAiGenerated = true;
16638
16695
  await sm.save();
16639
- return { id: session.id, path: join18(config.getHistoryDir(), `${session.id}.json`) };
16696
+ return { id: session.id, path: join19(config.getHistoryDir(), `${session.id}.json`) };
16640
16697
  }
16641
16698
 
16642
16699
  // src/core/think-command.ts
@@ -17097,8 +17154,8 @@ function costSourceNote(source2) {
17097
17154
  }
17098
17155
 
17099
17156
  // src/web/commands/_shared.ts
17100
- import { existsSync as existsSync27, readFileSync as readFileSync19, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync13, statSync as statSync14, createWriteStream } from "fs";
17101
- import { join as join21, resolve as resolve9, dirname as dirname9 } from "path";
17157
+ import { existsSync as existsSync28, readFileSync as readFileSync20, writeFileSync as writeFileSync3, mkdirSync as mkdirSync13, readdirSync as readdirSync14, statSync as statSync14, createWriteStream } from "fs";
17158
+ import { join as join22, resolve as resolve9, dirname as dirname9 } from "path";
17102
17159
 
17103
17160
  // src/cli/review-prompts.ts
17104
17161
  function buildReviewPrompt(diff, gitContextStr, detailed) {
@@ -17170,47 +17227,47 @@ function readGitDiff(options = {}) {
17170
17227
  }
17171
17228
 
17172
17229
  // src/diagnostics/doctor-report.ts
17173
- import { existsSync as existsSync26, statSync as statSync13 } from "fs";
17174
- import { join as join20 } from "path";
17230
+ import { existsSync as existsSync27, statSync as statSync13 } from "fs";
17231
+ import { join as join21 } from "path";
17175
17232
  import { arch as arch2, platform as platform5, release as release2 } from "os";
17176
17233
 
17177
17234
  // src/diagnostics/crash-log.ts
17178
17235
  import {
17179
- existsSync as existsSync25,
17236
+ existsSync as existsSync26,
17180
17237
  mkdirSync as mkdirSync12,
17181
- readdirSync as readdirSync12,
17182
- readFileSync as readFileSync18,
17238
+ readdirSync as readdirSync13,
17239
+ readFileSync as readFileSync19,
17183
17240
  statSync as statSync12,
17184
17241
  unlinkSync as unlinkSync6,
17185
17242
  writeFileSync as writeFileSync2
17186
17243
  } from "fs";
17187
- import { join as join19 } from "path";
17244
+ import { join as join20 } from "path";
17188
17245
  import { homedir as homedir7, platform as platform4, release, arch } from "os";
17189
17246
  var LOGS_DIR_NAME = "logs";
17190
17247
  var CRASH_LOG_PREFIX = "crash-";
17191
17248
  function getLogsDir(configDir) {
17192
- const base = configDir ?? join19(homedir7(), CONFIG_DIR_NAME);
17193
- return join19(base, LOGS_DIR_NAME);
17249
+ const base = configDir ?? join20(homedir7(), CONFIG_DIR_NAME);
17250
+ return join20(base, LOGS_DIR_NAME);
17194
17251
  }
17195
17252
  function truncate(s, n) {
17196
17253
  return s.length <= n ? s : s.slice(0, n) + "\u2026";
17197
17254
  }
17198
17255
  function listRecentCrashes(limit = 10, configDir) {
17199
17256
  const dir = getLogsDir(configDir);
17200
- if (!existsSync25(dir)) return [];
17257
+ if (!existsSync26(dir)) return [];
17201
17258
  const files = [];
17202
17259
  let names;
17203
17260
  try {
17204
- names = readdirSync12(dir);
17261
+ names = readdirSync13(dir);
17205
17262
  } catch {
17206
17263
  return [];
17207
17264
  }
17208
17265
  for (const name of names) {
17209
17266
  if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
17210
- const full = join19(dir, name);
17267
+ const full = join20(dir, name);
17211
17268
  try {
17212
17269
  const st = statSync12(full);
17213
- const head = readFileSync18(full, "utf-8").split("\n").slice(0, 20);
17270
+ const head = readFileSync19(full, "utf-8").split("\n").slice(0, 20);
17214
17271
  const tsLine = head.find((l) => l.startsWith("timestamp:"));
17215
17272
  const kindLine = head.find((l) => l.startsWith("kind:"));
17216
17273
  const msgIdx = head.findIndex((l) => l.trim() === "## message");
@@ -17229,18 +17286,18 @@ function listRecentCrashes(limit = 10, configDir) {
17229
17286
  return files.slice(0, limit);
17230
17287
  }
17231
17288
  function getConfigDirUsage(configDir) {
17232
- const base = configDir ?? join19(homedir7(), CONFIG_DIR_NAME);
17233
- if (!existsSync25(base)) return { totalBytes: 0, entries: [] };
17289
+ const base = configDir ?? join20(homedir7(), CONFIG_DIR_NAME);
17290
+ if (!existsSync26(base)) return { totalBytes: 0, entries: [] };
17234
17291
  const entries = [];
17235
17292
  let total = 0;
17236
17293
  let names;
17237
17294
  try {
17238
- names = readdirSync12(base);
17295
+ names = readdirSync13(base);
17239
17296
  } catch {
17240
17297
  return { totalBytes: 0, entries: [] };
17241
17298
  }
17242
17299
  for (const name of names) {
17243
- const full = join19(base, name);
17300
+ const full = join20(base, name);
17244
17301
  const bytes = dirSize(full);
17245
17302
  entries.push({ name, bytes });
17246
17303
  total += bytes;
@@ -17254,8 +17311,8 @@ function dirSize(path3) {
17254
17311
  if (st.isFile()) return st.size;
17255
17312
  if (!st.isDirectory()) return 0;
17256
17313
  let sum = 0;
17257
- for (const name of readdirSync12(path3)) {
17258
- sum += dirSize(join19(path3, name));
17314
+ for (const name of readdirSync13(path3)) {
17315
+ sum += dirSize(join20(path3, name));
17259
17316
  }
17260
17317
  return sum;
17261
17318
  } catch {
@@ -17265,7 +17322,7 @@ function dirSize(path3) {
17265
17322
 
17266
17323
  // src/diagnostics/doctor-report.ts
17267
17324
  function checkFile(label, path3) {
17268
- const exists = existsSync26(path3);
17325
+ const exists = existsSync27(path3);
17269
17326
  let sizeBytes = null;
17270
17327
  if (exists) {
17271
17328
  try {
@@ -17308,12 +17365,12 @@ function buildDoctorReport(options) {
17308
17365
  configDir,
17309
17366
  providers: options.providers.listAll().map((p) => ({ id: p.id, displayName: p.displayName, configured: p.configured })),
17310
17367
  files: [
17311
- checkFile("config.json", join20(configDir, "config.json")),
17312
- checkFile("memory.md", join20(configDir, MEMORY_FILE_NAME)),
17313
- checkFile("memory.jsonl", join20(configDir, "memory.jsonl")),
17314
- checkFile("dev-state.md", join20(configDir, DEV_STATE_FILE_NAME)),
17315
- checkFile("hooks-trust.json", join20(configDir, "hooks-trust.json")),
17316
- checkFile("plugin-state.json", join20(configDir, "plugins", "plugin-state.json"))
17368
+ checkFile("config.json", join21(configDir, "config.json")),
17369
+ checkFile("memory.md", join21(configDir, MEMORY_FILE_NAME)),
17370
+ checkFile("memory.jsonl", join21(configDir, "memory.jsonl")),
17371
+ checkFile("dev-state.md", join21(configDir, DEV_STATE_FILE_NAME)),
17372
+ checkFile("hooks-trust.json", join21(configDir, "hooks-trust.json")),
17373
+ checkFile("plugin-state.json", join21(configDir, "plugins", "plugin-state.json"))
17317
17374
  ],
17318
17375
  context: {
17319
17376
  enabled: contextSetting !== false,
@@ -17348,7 +17405,7 @@ function buildDoctorReport(options) {
17348
17405
  disabled: hooks.filter((h) => h.disabled).length
17349
17406
  },
17350
17407
  plugins: {
17351
- root: join20(configDir, "plugins"),
17408
+ root: join21(configDir, "plugins"),
17352
17409
  installed: plugins.length,
17353
17410
  active: activeAssets.plugins.length,
17354
17411
  invalid: plugins.filter((p) => !p.valid).length,
@@ -17363,7 +17420,7 @@ function buildDoctorReport(options) {
17363
17420
  mcp: {
17364
17421
  enabled: config.get("mcpEnabled"),
17365
17422
  configured: Object.keys(mcpServers).length,
17366
- projectConfigExists: existsSync26(join20(projectRoot, MCP_PROJECT_CONFIG_NAME)),
17423
+ projectConfigExists: existsSync27(join21(projectRoot, MCP_PROJECT_CONFIG_NAME)),
17367
17424
  statuses: options.mcpStatuses ?? []
17368
17425
  },
17369
17426
  recentCrashes: listRecentCrashes(5, configDir),
@@ -17885,7 +17942,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
17885
17942
  Cost: ${formatCost(cost)}` : "";
17886
17943
  let memoryLine = "";
17887
17944
  try {
17888
- const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-3XTSZ3QR.js");
17945
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-LMVWIHMX.js");
17889
17946
  const pending = countPendingMemories2(ctx.config.getConfigDir());
17890
17947
  if (pending > 0) memoryLine = `
17891
17948
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -18626,7 +18683,7 @@ async function handlePlugin(args, ctx) {
18626
18683
  lines.push("");
18627
18684
  }
18628
18685
  if (pluginTools.length > 0) {
18629
- const legacyDir = join21(configDir, PLUGINS_DIR_NAME);
18686
+ const legacyDir = join22(configDir, PLUGINS_DIR_NAME);
18630
18687
  lines.push(`**Legacy JS tools** (${pluginTools.length}):`);
18631
18688
  lines.push(`Dir: ${legacyDir}`);
18632
18689
  for (const t of pluginTools) lines.push(` \u2022 ${t.definition.name} \u2014 ${t.definition.description}`);
@@ -18766,14 +18823,14 @@ ${note}` : head });
18766
18823
  }
18767
18824
  async function handleCommands(_args, ctx) {
18768
18825
  const configDir = ctx.config.getConfigDir();
18769
- const commandsDir = join21(configDir, CUSTOM_COMMANDS_DIR_NAME);
18770
- if (!existsSync27(commandsDir)) {
18826
+ const commandsDir = join22(configDir, CUSTOM_COMMANDS_DIR_NAME);
18827
+ if (!existsSync28(commandsDir)) {
18771
18828
  ctx.send({ type: "info", message: `No custom commands directory.
18772
18829
  Create: ${commandsDir}/ with .md files.` });
18773
18830
  return;
18774
18831
  }
18775
18832
  try {
18776
- const files = readdirSync13(commandsDir).filter((f) => f.endsWith(".md"));
18833
+ const files = readdirSync14(commandsDir).filter((f) => f.endsWith(".md"));
18777
18834
  if (files.length === 0) {
18778
18835
  ctx.send({ type: "info", message: `No custom commands found in ${commandsDir}
18779
18836
  Add .md files to create commands.` });
@@ -18873,7 +18930,7 @@ async function handleTest(args, ctx) {
18873
18930
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
18874
18931
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
18875
18932
  }
18876
- const runTests = ctx.runTests ?? (await import("./run-tests-WQE3XTUL.js")).executeTests;
18933
+ const runTests = ctx.runTests ?? (await import("./run-tests-MQVGE6FK.js")).executeTests;
18877
18934
  const report = await runTests(testArgs);
18878
18935
  ctx.send({ type: "info", message: report });
18879
18936
  } catch (err) {
@@ -18897,9 +18954,9 @@ async function handleDiff(args, ctx) {
18897
18954
  let modifiedFiles = 0;
18898
18955
  const diffLines2 = [];
18899
18956
  for (const [filePath, { earliest }] of fileMap) {
18900
- const currentContent = existsSync27(filePath) ? (() => {
18957
+ const currentContent = existsSync28(filePath) ? (() => {
18901
18958
  try {
18902
- return readFileSync19(filePath, "utf-8");
18959
+ return readFileSync20(filePath, "utf-8");
18903
18960
  } catch {
18904
18961
  return null;
18905
18962
  }
@@ -18934,9 +18991,9 @@ async function handleDiff(args, ctx) {
18934
18991
  }
18935
18992
  async function handleInit(args, ctx) {
18936
18993
  const cwd = process.cwd();
18937
- const targetPath = join21(cwd, "AICLI.md");
18994
+ const targetPath = join22(cwd, "AICLI.md");
18938
18995
  const force = args.includes("--force");
18939
- if (existsSync27(targetPath) && !force) {
18996
+ if (existsSync28(targetPath) && !force) {
18940
18997
  ctx.send({ type: "info", message: `AICLI.md already exists at ${targetPath}
18941
18998
  Use /init --force to overwrite.` });
18942
18999
  return;
@@ -19264,7 +19321,7 @@ async function handleMemory(args, ctx) {
19264
19321
  }
19265
19322
  if (intent.kind === "status") {
19266
19323
  const { getChatIndexStatus: getChatIndexStatus2 } = await import("./chat-index-RLVLQRRC.js");
19267
- const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-3XTSZ3QR.js");
19324
+ const { listMemoryEntries: listMemoryEntries2, isMemoryExpired: isMemoryExpired2, formatMemoryForPrompt: formatMemoryForPrompt2 } = await import("./persistent-memory-LMVWIHMX.js");
19268
19325
  const memories = listMemoryEntries2(configDir, { includeExpired: true, includeRejected: true });
19269
19326
  const injected = formatMemoryForPrompt2(configDir, process.cwd(), ctx.config.get("memory")?.maxChars);
19270
19327
  const view = buildMemoryStatusView({
@@ -19287,7 +19344,7 @@ async function handleMemory(args, ctx) {
19287
19344
  return;
19288
19345
  }
19289
19346
  if (intent.kind === "recall") {
19290
- const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-3XTSZ3QR.js");
19347
+ const { searchPersistentMemories: searchPersistentMemories2, touchMemoryReferences: touchMemoryReferences2 } = await import("./persistent-memory-LMVWIHMX.js");
19291
19348
  const { searchChatMemory: searchChatMemory2 } = await import("./chat-index-RLVLQRRC.js");
19292
19349
  const persistentHits = searchPersistentMemories2(configDir, intent.query, process.cwd(), 3);
19293
19350
  if (persistentHits.length > 0) {
@@ -19408,7 +19465,7 @@ async function handleMemory(args, ctx) {
19408
19465
  ctx.handleMemoryManage(intent.action, args[1], intent.action === "expire" ? args[2] : void 0);
19409
19466
  } else if (intent.kind === "export") {
19410
19467
  if (args[1] === "md") {
19411
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-3XTSZ3QR.js");
19468
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-LMVWIHMX.js");
19412
19469
  ctx.send({
19413
19470
  type: "export_data",
19414
19471
  format: "md",
@@ -19446,7 +19503,7 @@ Use /add-dir remove to clear.` : "No directories added.\nUsage: /add-dir <path>
19446
19503
  return;
19447
19504
  }
19448
19505
  const dirPath = resolve9(sub);
19449
- if (!existsSync27(dirPath)) {
19506
+ if (!existsSync28(dirPath)) {
19450
19507
  ctx.send({ type: "error", message: `Directory not found: ${dirPath}` });
19451
19508
  return;
19452
19509
  }
@@ -20411,16 +20468,16 @@ No tools match "${filter}".
20411
20468
  usage: "/mcp [reconnect [serverId] | trust-project]",
20412
20469
  async execute(args, ctx) {
20413
20470
  if (args[0] === "trust-project") {
20414
- const { join: join26 } = await import("path");
20415
- const { existsSync: existsSync32 } = await import("fs");
20471
+ const { join: join27 } = await import("path");
20472
+ const { existsSync: existsSync33 } = await import("fs");
20416
20473
  const { getGitRoot: getGitRoot2 } = await import("./git-context-VNCA2GU7.js");
20417
- const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-J5SJ232X.js");
20474
+ const { MCP_PROJECT_CONFIG_NAME: MCP_PROJECT_CONFIG_NAME2 } = await import("./constants-JM6MK5SS.js");
20418
20475
  const { approveProject, hashMcpFile } = await import("./project-trust-6CJB5ZMX.js");
20419
20476
  const cwd = process.cwd();
20420
20477
  const projectRoot = getGitRoot2(cwd) ?? cwd;
20421
- const mcpPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME2);
20478
+ const mcpPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME2);
20422
20479
  console.log();
20423
- if (!existsSync32(mcpPath)) {
20480
+ if (!existsSync33(mcpPath)) {
20424
20481
  console.log(theme.dim(` No .mcp.json in ${projectRoot}.`));
20425
20482
  console.log();
20426
20483
  return;
@@ -20855,12 +20912,12 @@ ${outcome.summary}
20855
20912
  if (scanAll) {
20856
20913
  const metas = ctx.sessions.listSessions();
20857
20914
  console.log(theme.info(` Scanning ${metas.length} session(s)\u2026`));
20858
- const { readFileSync: readFileSync23 } = await import("fs");
20859
- const { join: join26 } = await import("path");
20915
+ const { readFileSync: readFileSync24 } = await import("fs");
20916
+ const { join: join27 } = await import("path");
20860
20917
  const historyDir = ctx.config.getHistoryDir();
20861
20918
  for (const m of metas) {
20862
20919
  try {
20863
- const content = readFileSync23(join26(historyDir, `${m.id}.json`), "utf-8");
20920
+ const content = readFileSync24(join27(historyDir, `${m.id}.json`), "utf-8");
20864
20921
  const hits2 = scanString(content, opts);
20865
20922
  if (hits2.length) {
20866
20923
  filesWithHits++;
@@ -20907,8 +20964,8 @@ ${outcome.summary}
20907
20964
  }
20908
20965
 
20909
20966
  // src/repl/commands/review-commands.ts
20910
- import { existsSync as existsSync28, readFileSync as readFileSync20, writeFileSync as writeFileSync4 } from "fs";
20911
- import { join as join22 } from "path";
20967
+ import { existsSync as existsSync29, readFileSync as readFileSync21, writeFileSync as writeFileSync4 } from "fs";
20968
+ import { join as join23 } from "path";
20912
20969
  function createReviewCommands() {
20913
20970
  return [
20914
20971
  {
@@ -21267,9 +21324,9 @@ function createReviewCommands() {
21267
21324
  usage: "/init [--force]",
21268
21325
  async execute(args, ctx) {
21269
21326
  const cwd = process.cwd();
21270
- const targetPath = join22(cwd, "AICLI.md");
21327
+ const targetPath = join23(cwd, "AICLI.md");
21271
21328
  const force = args.includes("--force");
21272
- if (existsSync28(targetPath) && !force) {
21329
+ if (existsSync29(targetPath) && !force) {
21273
21330
  ctx.renderer.printInfo(`AICLI.md already exists at ${targetPath}`);
21274
21331
  ctx.renderer.printInfo("Use /init --force to overwrite, or edit it manually.");
21275
21332
  return;
@@ -21333,7 +21390,7 @@ function createReviewCommands() {
21333
21390
  usage: "/test [command|filter]",
21334
21391
  async execute(args, ctx) {
21335
21392
  try {
21336
- const { executeTests } = await import("./run-tests-WQE3XTUL.js");
21393
+ const { executeTests } = await import("./run-tests-MQVGE6FK.js");
21337
21394
  const argStr = args.join(" ").trim();
21338
21395
  let testArgs = {};
21339
21396
  if (argStr) {
@@ -21368,9 +21425,9 @@ function createReviewCommands() {
21368
21425
  let newFiles = 0;
21369
21426
  let modifiedFiles = 0;
21370
21427
  for (const [filePath, { earliest }] of fileMap) {
21371
- const currentContent = existsSync28(filePath) ? (() => {
21428
+ const currentContent = existsSync29(filePath) ? (() => {
21372
21429
  try {
21373
- return readFileSync20(filePath, "utf-8");
21430
+ return readFileSync21(filePath, "utf-8");
21374
21431
  } catch {
21375
21432
  return null;
21376
21433
  }
@@ -22532,17 +22589,17 @@ function createSessionCommands() {
22532
22589
  }
22533
22590
 
22534
22591
  // src/repl/commands/misc-commands.ts
22535
- import { basename as basename10 } from "path";
22592
+ import { basename as basename11 } from "path";
22536
22593
  import { platform as platform8 } from "os";
22537
22594
 
22538
22595
  // src/repl/clipboard.ts
22539
22596
  import { execSync as execSync3 } from "child_process";
22540
- import { existsSync as existsSync29, statSync as statSync15, unlinkSync as unlinkSync7 } from "fs";
22597
+ import { existsSync as existsSync30, statSync as statSync15, unlinkSync as unlinkSync7 } from "fs";
22541
22598
  import { tmpdir as tmpdir3 } from "os";
22542
- import { join as join23 } from "path";
22599
+ import { join as join24 } from "path";
22543
22600
  var CLIPBOARD_TIMEOUT = 5e3;
22544
22601
  function readClipboardImage() {
22545
- const outPath = join23(tmpdir3(), `aicli-paste-${Date.now()}.png`);
22602
+ const outPath = join24(tmpdir3(), `aicli-paste-${Date.now()}.png`);
22546
22603
  try {
22547
22604
  if (process.platform === "win32") {
22548
22605
  _readWin32(outPath);
@@ -22555,7 +22612,7 @@ function readClipboardImage() {
22555
22612
  _cleanup(outPath);
22556
22613
  return null;
22557
22614
  }
22558
- if (!existsSync29(outPath) || statSync15(outPath).size === 0) {
22615
+ if (!existsSync30(outPath) || statSync15(outPath).size === 0) {
22559
22616
  _cleanup(outPath);
22560
22617
  return null;
22561
22618
  }
@@ -22608,7 +22665,7 @@ function _readLinux(outPath) {
22608
22665
  }
22609
22666
  function _cleanup(path3) {
22610
22667
  try {
22611
- if (existsSync29(path3)) unlinkSync7(path3);
22668
+ if (existsSync30(path3)) unlinkSync7(path3);
22612
22669
  } catch {
22613
22670
  }
22614
22671
  }
@@ -22878,7 +22935,7 @@ ${hint}` : "")
22878
22935
  return;
22879
22936
  }
22880
22937
  const description = args.join(" ").trim() || "Please describe this image";
22881
- ctx.renderer.printSuccess(`\u{1F4CB} Image loaded: ${basename10(imgPath)}`);
22938
+ ctx.renderer.printSuccess(`\u{1F4CB} Image loaded: ${basename11(imgPath)}`);
22882
22939
  await ctx.sendAsChat(`@${imgPath} ${description}`);
22883
22940
  }
22884
22941
  },
@@ -23434,6 +23491,11 @@ var SessionHandler = class _SessionHandler {
23434
23491
  costCnyPerUsd: CNY_PER_USD,
23435
23492
  costPricingUnknown,
23436
23493
  providers: providerList,
23494
+ hubPresets: loadCustomPresets(this.config.getConfigDir()).presets.map((p) => ({
23495
+ id: p.id,
23496
+ name: p.name,
23497
+ description: p.description
23498
+ })),
23437
23499
  branches,
23438
23500
  activeBranchId: sess?.activeBranchId ?? "main",
23439
23501
  agents: listAgentRuns().slice(0, 20).map((run) => ({
@@ -23687,7 +23749,8 @@ var SessionHandler = class _SessionHandler {
23687
23749
  this.send({ type: "error", message: "Hub topic is required." });
23688
23750
  return;
23689
23751
  }
23690
- const preset = getPreset(msg.preset ?? "brainstorm");
23752
+ const presetId = msg.preset ?? "brainstorm";
23753
+ const preset = presetId.startsWith(CUSTOM_PRESET_PREFIX) ? loadCustomPresets(this.config.getConfigDir()).presets.find((p) => p.id === presetId) : getPreset(presetId);
23691
23754
  if (!preset) {
23692
23755
  this.send({ type: "error", message: `Unknown preset "${msg.preset}".` });
23693
23756
  return;
@@ -24890,8 +24953,8 @@ async function setupProxy(configProxy) {
24890
24953
  }
24891
24954
 
24892
24955
  // src/web/auth.ts
24893
- import { existsSync as existsSync30, readFileSync as readFileSync21, mkdirSync as mkdirSync16, readdirSync as readdirSync14, openSync, closeSync, unlinkSync as unlinkSync8 } from "fs";
24894
- import { isAbsolute as isAbsolute3, join as join24, relative as relative5 } from "path";
24956
+ import { existsSync as existsSync31, readFileSync as readFileSync22, mkdirSync as mkdirSync16, readdirSync as readdirSync15, openSync, closeSync, unlinkSync as unlinkSync8 } from "fs";
24957
+ import { isAbsolute as isAbsolute3, join as join25, relative as relative5 } from "path";
24895
24958
  import { createHmac, randomBytes as randomBytes2, timingSafeEqual as timingSafeEqual2, pbkdf2Sync, pbkdf2 } from "crypto";
24896
24959
  var USERS_FILE = "users.json";
24897
24960
  var TOKEN_EXPIRY_HOURS = 24;
@@ -24907,7 +24970,7 @@ var AuthManager = class {
24907
24970
  loadedRaw;
24908
24971
  constructor(baseDir) {
24909
24972
  this.baseDir = baseDir;
24910
- this.usersFile = join24(baseDir, USERS_FILE);
24973
+ this.usersFile = join25(baseDir, USERS_FILE);
24911
24974
  this.db = this.loadOrCreate();
24912
24975
  }
24913
24976
  // ── Public API ─────────────────────────────────────────────────
@@ -24949,10 +25012,10 @@ var AuthManager = class {
24949
25012
  }
24950
25013
  const salt = prepared?.salt ?? randomBytes2(16).toString("hex");
24951
25014
  const passwordHash = prepared?.hash ?? this.hashPassword(password, salt);
24952
- const dataDir = join24(USERS_DIR, username);
24953
- const fullDataDir = join24(this.baseDir, dataDir);
25015
+ const dataDir = join25(USERS_DIR, username);
25016
+ const fullDataDir = join25(this.baseDir, dataDir);
24954
25017
  mkdirSync16(fullDataDir, { recursive: true, mode: 448 });
24955
- mkdirSync16(join24(fullDataDir, "history"), { recursive: true, mode: 448 });
25018
+ mkdirSync16(join25(fullDataDir, "history"), { recursive: true, mode: 448 });
24956
25019
  const user = {
24957
25020
  username,
24958
25021
  passwordHash,
@@ -25112,7 +25175,7 @@ var AuthManager = class {
25112
25175
  this.refresh();
25113
25176
  const user = this.db.users.find((u) => u.username === username);
25114
25177
  if (!user) throw new Error(`User not found: ${username}`);
25115
- return join24(this.baseDir, user.dataDir);
25178
+ return join25(this.baseDir, user.dataDir);
25116
25179
  }
25117
25180
  /** List all usernames */
25118
25181
  listUsers() {
@@ -25151,30 +25214,30 @@ var AuthManager = class {
25151
25214
  const err = this.register(username, password);
25152
25215
  if (err) return err;
25153
25216
  const userDir = this.getUserDataDir(username);
25154
- const globalConfig = join24(this.baseDir, "config.json");
25155
- if (existsSync30(globalConfig)) {
25217
+ const globalConfig = join25(this.baseDir, "config.json");
25218
+ if (existsSync31(globalConfig)) {
25156
25219
  try {
25157
- const content = readFileSync21(globalConfig, "utf-8");
25158
- atomicWriteFileSync(join24(userDir, "config.json"), content, { mode: 384 });
25220
+ const content = readFileSync22(globalConfig, "utf-8");
25221
+ atomicWriteFileSync(join25(userDir, "config.json"), content, { mode: 384 });
25159
25222
  } catch {
25160
25223
  }
25161
25224
  }
25162
- const globalMemory = join24(this.baseDir, "memory.md");
25163
- if (existsSync30(globalMemory)) {
25225
+ const globalMemory = join25(this.baseDir, "memory.md");
25226
+ if (existsSync31(globalMemory)) {
25164
25227
  try {
25165
- const content = readFileSync21(globalMemory, "utf-8");
25166
- atomicWriteFileSync(join24(userDir, "memory.md"), content, { mode: 384 });
25228
+ const content = readFileSync22(globalMemory, "utf-8");
25229
+ atomicWriteFileSync(join25(userDir, "memory.md"), content, { mode: 384 });
25167
25230
  } catch {
25168
25231
  }
25169
25232
  }
25170
- const globalHistory = join24(this.baseDir, "history");
25171
- if (existsSync30(globalHistory)) {
25233
+ const globalHistory = join25(this.baseDir, "history");
25234
+ if (existsSync31(globalHistory)) {
25172
25235
  try {
25173
- const files = readdirSync14(globalHistory).filter((f) => f.endsWith(".json"));
25174
- const userHistory = join24(userDir, "history");
25236
+ const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
25237
+ const userHistory = join25(userDir, "history");
25175
25238
  for (const f of files) {
25176
25239
  try {
25177
- atomicWriteFileSync(join24(userHistory, f), readFileSync21(join24(globalHistory, f), "utf8"), { mode: 384 });
25240
+ atomicWriteFileSync(join25(userHistory, f), readFileSync22(join25(globalHistory, f), "utf8"), { mode: 384 });
25178
25241
  } catch {
25179
25242
  }
25180
25243
  }
@@ -25185,16 +25248,16 @@ var AuthManager = class {
25185
25248
  }
25186
25249
  // ── Private methods ────────────────────────────────────────────
25187
25250
  refresh() {
25188
- const raw = readFileSync21(this.usersFile, "utf8");
25251
+ const raw = readFileSync22(this.usersFile, "utf8");
25189
25252
  const parsed = JSON.parse(raw);
25190
25253
  if (!this.isValidUsersDB(parsed)) throw new Error("Authentication database is invalid; access refused");
25191
25254
  this.db = parsed;
25192
25255
  this.loadedRaw = raw;
25193
25256
  }
25194
25257
  loadOrCreate() {
25195
- if (existsSync30(this.usersFile)) {
25258
+ if (existsSync31(this.usersFile)) {
25196
25259
  try {
25197
- const raw = readFileSync21(this.usersFile, "utf-8");
25260
+ const raw = readFileSync22(this.usersFile, "utf-8");
25198
25261
  const parsed = JSON.parse(raw);
25199
25262
  if (!this.isValidUsersDB(parsed)) {
25200
25263
  throw new Error("database structure is invalid");
@@ -25230,7 +25293,7 @@ var AuthManager = class {
25230
25293
  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)) {
25231
25294
  return false;
25232
25295
  }
25233
- const dataDirFromBase = relative5(this.baseDir, join24(this.baseDir, record.dataDir));
25296
+ const dataDirFromBase = relative5(this.baseDir, join25(this.baseDir, record.dataDir));
25234
25297
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
25235
25298
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
25236
25299
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -25246,7 +25309,7 @@ var AuthManager = class {
25246
25309
  const lock = this.usersFile + ".lock";
25247
25310
  const fd = openSync(lock, "wx", 384);
25248
25311
  try {
25249
- const current = existsSync30(this.usersFile) ? readFileSync21(this.usersFile, "utf8") : void 0;
25312
+ const current = existsSync31(this.usersFile) ? readFileSync22(this.usersFile, "utf8") : void 0;
25250
25313
  if (current !== this.loadedRaw) throw new Error("Authentication database changed concurrently; retry the operation");
25251
25314
  const raw = JSON.stringify(db, null, 2);
25252
25315
  atomicWriteFileSync(this.usersFile, raw, { mode: 384 });
@@ -25380,8 +25443,8 @@ async function startWebServer(options = {}) {
25380
25443
  }
25381
25444
  }
25382
25445
  let skillManager = null;
25383
- const skillsDir = join25(config.getConfigDir(), SKILLS_DIR_NAME);
25384
- if (existsSync31(skillsDir)) {
25446
+ const skillsDir = join26(config.getConfigDir(), SKILLS_DIR_NAME);
25447
+ if (existsSync32(skillsDir)) {
25385
25448
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
25386
25449
  skillManager.loadSkills(pluginAssets.skillDirs);
25387
25450
  const count = skillManager.listSkills().length;
@@ -25474,15 +25537,15 @@ async function startWebServer(options = {}) {
25474
25537
  next();
25475
25538
  };
25476
25539
  const moduleDir = getModuleDir();
25477
- let clientDir = join25(moduleDir, "web", "client");
25478
- if (!existsSync31(clientDir)) {
25479
- clientDir = join25(moduleDir, "client");
25540
+ let clientDir = join26(moduleDir, "web", "client");
25541
+ if (!existsSync32(clientDir)) {
25542
+ clientDir = join26(moduleDir, "client");
25480
25543
  }
25481
- if (!existsSync31(clientDir)) {
25482
- clientDir = join25(moduleDir, "..", "..", "src", "web", "client");
25544
+ if (!existsSync32(clientDir)) {
25545
+ clientDir = join26(moduleDir, "..", "..", "src", "web", "client");
25483
25546
  }
25484
- if (!existsSync31(clientDir)) {
25485
- clientDir = join25(process.cwd(), "src", "web", "client");
25547
+ if (!existsSync32(clientDir)) {
25548
+ clientDir = join26(process.cwd(), "src", "web", "client");
25486
25549
  }
25487
25550
  console.log(` Static files: ${clientDir}`);
25488
25551
  const PRECOMPRESSED_TYPES = {
@@ -25502,14 +25565,14 @@ async function startWebServer(options = {}) {
25502
25565
  const encoding = /\bbr\b/.test(accept) ? "br" : /\bgzip\b/.test(accept) ? "gzip" : null;
25503
25566
  if (!encoding) return next();
25504
25567
  const target = resolvePath(clientDir, `.${req.path}`) + (encoding === "br" ? ".br" : ".gz");
25505
- if (!target.startsWith(clientDir) || !existsSync31(target)) return next();
25568
+ if (!target.startsWith(clientDir) || !existsSync32(target)) return next();
25506
25569
  res.setHeader("Content-Type", contentType);
25507
25570
  res.setHeader("Content-Encoding", encoding);
25508
25571
  res.setHeader("Vary", "Accept-Encoding");
25509
25572
  if (req.path.startsWith("/vendor/")) res.setHeader("Cache-Control", "public, max-age=31536000, immutable");
25510
25573
  createReadStream(target).pipe(res);
25511
25574
  });
25512
- app.use("/vendor", express.static(join25(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
25575
+ app.use("/vendor", express.static(join26(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
25513
25576
  app.use(express.static(clientDir));
25514
25577
  app.get("/api/status", (_req, res) => {
25515
25578
  res.json({
@@ -25600,7 +25663,7 @@ async function startWebServer(options = {}) {
25600
25663
  app.get("/api/files", requireAuth, (req, res) => {
25601
25664
  const cwd = process.cwd();
25602
25665
  const prefix = req.query.prefix || "";
25603
- const targetDir = join25(cwd, prefix);
25666
+ const targetDir = join26(cwd, prefix);
25604
25667
  try {
25605
25668
  const canonicalTarget = realpathSync3(resolve12(targetDir));
25606
25669
  const canonicalCwd = realpathSync3(resolve12(cwd));
@@ -25614,10 +25677,10 @@ async function startWebServer(options = {}) {
25614
25677
  }
25615
25678
  try {
25616
25679
  const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
25617
- const entries = readdirSync15(targetDir, { withFileTypes: true });
25680
+ const entries = readdirSync16(targetDir, { withFileTypes: true });
25618
25681
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
25619
25682
  name: e.name,
25620
- path: relative6(cwd, join25(targetDir, e.name)).replace(/\\/g, "/"),
25683
+ path: relative6(cwd, join26(targetDir, e.name)).replace(/\\/g, "/"),
25621
25684
  isDir: e.isDirectory()
25622
25685
  }));
25623
25686
  res.json({ files });
@@ -25657,8 +25720,8 @@ async function startWebServer(options = {}) {
25657
25720
  try {
25658
25721
  const authUser = req._authUser;
25659
25722
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
25660
- const filePath = join25(histDir, `${id}.json`);
25661
- if (!existsSync31(filePath)) {
25723
+ const filePath = join26(histDir, `${id}.json`);
25724
+ if (!existsSync32(filePath)) {
25662
25725
  res.status(404).json({ error: "Session not found" });
25663
25726
  return;
25664
25727
  }
@@ -25673,7 +25736,7 @@ async function startWebServer(options = {}) {
25673
25736
  res.status(404).json({ error: "Session not found" });
25674
25737
  return;
25675
25738
  }
25676
- const data = JSON.parse(readFileSync22(filePath, "utf-8"));
25739
+ const data = JSON.parse(readFileSync23(filePath, "utf-8"));
25677
25740
  res.json({ session: data });
25678
25741
  } catch (err) {
25679
25742
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
@@ -25686,7 +25749,7 @@ async function startWebServer(options = {}) {
25686
25749
  return;
25687
25750
  }
25688
25751
  const cwd = process.cwd();
25689
- const fullPath = resolve12(join25(cwd, filePath));
25752
+ const fullPath = resolve12(join26(cwd, filePath));
25690
25753
  try {
25691
25754
  const canonicalFull = realpathSync3(fullPath);
25692
25755
  assertReadablePath(canonicalFull);
@@ -25705,7 +25768,7 @@ async function startWebServer(options = {}) {
25705
25768
  res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
25706
25769
  return;
25707
25770
  }
25708
- const content = readFileSync22(fullPath, "utf-8");
25771
+ const content = readFileSync23(fullPath, "utf-8");
25709
25772
  res.json({ content, size: stat.size });
25710
25773
  } catch {
25711
25774
  res.json({ error: "Cannot read file" });
@@ -26042,17 +26105,17 @@ function resolveProjectMcpPath() {
26042
26105
  const cwd = process.cwd();
26043
26106
  const gitRoot = getGitRoot(cwd);
26044
26107
  const projectRoot = gitRoot ?? cwd;
26045
- const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
26046
- return existsSync31(configPath) ? configPath : null;
26108
+ const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
26109
+ return existsSync32(configPath) ? configPath : null;
26047
26110
  }
26048
26111
  function loadProjectMcpConfig() {
26049
26112
  const cwd = process.cwd();
26050
26113
  const gitRoot = getGitRoot(cwd);
26051
26114
  const projectRoot = gitRoot ?? cwd;
26052
- const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
26053
- if (!existsSync31(configPath)) return null;
26115
+ const configPath = join26(projectRoot, MCP_PROJECT_CONFIG_NAME);
26116
+ if (!existsSync32(configPath)) return null;
26054
26117
  try {
26055
- const raw = JSON.parse(readFileSync22(configPath, "utf-8"));
26118
+ const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
26056
26119
  return raw.mcpServers ?? raw;
26057
26120
  } catch {
26058
26121
  return null;