jinzd-ai-cli 0.4.235 → 0.4.237

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 (27) hide show
  1. package/README.md +5 -5
  2. package/dist/{batch-Y7MHXVR7.js → batch-S2NUD45K.js} +2 -2
  3. package/dist/{chunk-GDXKFWFL.js → chunk-25FKQO3A.js} +1 -1
  4. package/dist/{chunk-CDOQNIVV.js → chunk-45TJA46E.js} +3 -3
  5. package/dist/{chunk-Q5GVANMH.js → chunk-6RU5AKXB.js} +1 -1
  6. package/dist/{chunk-BFTTW5LS.js → chunk-CSATDZ3Z.js} +1 -1
  7. package/dist/{chunk-HHYMSEWS.js → chunk-EG5P3AMC.js} +1 -1
  8. package/dist/{chunk-WXFQ6LYN.js → chunk-J2M4GOFE.js} +1 -1
  9. package/dist/{chunk-DHNYGJYB.js → chunk-KQJ55BTD.js} +3 -3
  10. package/dist/{chunk-GFDRC2JZ.js → chunk-MSK2BAKT.js} +115 -18
  11. package/dist/{chunk-7D5EJBHO.js → chunk-NAPAMAFY.js} +3 -3
  12. package/dist/{chunk-FYJGVFXL.js → chunk-WI4DN5FN.js} +51 -7
  13. package/dist/{ci-OAFNH3MA.js → ci-HDGRBALH.js} +4 -4
  14. package/dist/{ci-format-4LSXJNND.js → ci-format-W6DDOFS7.js} +2 -2
  15. package/dist/{constants-ERIAS7GV.js → constants-3KMOIJNP.js} +1 -1
  16. package/dist/{doctor-cli-VFSVWZU6.js → doctor-cli-E5MBY7CZ.js} +4 -4
  17. package/dist/electron-server.js +208 -67
  18. package/dist/{hub-X4EUYRIN.js → hub-2WPMT242.js} +1 -1
  19. package/dist/index.js +2438 -2436
  20. package/dist/{pr-2CZN5JLE.js → pr-RRHV7P7D.js} +4 -4
  21. package/dist/{run-tests-DXRJDPFF.js → run-tests-GP7ZMSAX.js} +2 -2
  22. package/dist/{run-tests-YSRET52H.js → run-tests-K36VNQ5W.js} +1 -1
  23. package/dist/{server-5ZAXMKRI.js → server-J36CY5EU.js} +28 -28
  24. package/dist/{server-FGJGXHZD.js → server-JEVAHG53.js} +4 -4
  25. package/dist/{task-orchestrator-QMERCD77.js → task-orchestrator-D66BJZKU.js} +4 -4
  26. package/dist/{usage-633DUDNT.js → usage-5QO5AFYC.js} +2 -2
  27. package/package.json +1 -1
@@ -38,7 +38,7 @@ import {
38
38
  VERSION,
39
39
  buildUserIdentityPrompt,
40
40
  runTestsTool
41
- } from "./chunk-HHYMSEWS.js";
41
+ } from "./chunk-EG5P3AMC.js";
42
42
  import {
43
43
  hasSemanticIndex,
44
44
  semanticSearch
@@ -70,8 +70,8 @@ import {
70
70
  import express from "express";
71
71
  import { createServer } from "http";
72
72
  import { WebSocketServer } from "ws";
73
- import { join as join28, dirname as dirname12, resolve as resolve13, relative as relative5, sep as sep3 } from "path";
74
- import { existsSync as existsSync34, readFileSync as readFileSync26, readdirSync as readdirSync17, statSync as statSync15, realpathSync as realpathSync2 } from "fs";
73
+ import { join as join28, dirname as dirname11, resolve as resolve13, relative as relative6, sep as sep4 } from "path";
74
+ import { existsSync as existsSync33, readFileSync as readFileSync25, readdirSync as readdirSync16, statSync as statSync14, realpathSync as realpathSync3 } from "fs";
75
75
  import { networkInterfaces } from "os";
76
76
 
77
77
  // src/config/config-manager.ts
@@ -9153,6 +9153,14 @@ var webFetchTool = {
9153
9153
  }
9154
9154
  const cause = err.cause;
9155
9155
  if (cause?.message?.startsWith("Blocked:")) throw new NetworkError(cause.message);
9156
+ if (err instanceof Error && err.message === "fetch failed") {
9157
+ const detail = cause?.message ? ` (${cause.message})` : "";
9158
+ throw new NetworkError(
9159
+ `Connection failed for ${url}${detail}. The domain may be unreachable from the current network (some sites require a proxy \u2014 see config.proxy) or temporarily down. Do not retry the same URL; try an alternative source.`,
9160
+ void 0,
9161
+ err
9162
+ );
9163
+ }
9156
9164
  throw err;
9157
9165
  } finally {
9158
9166
  void dispatcher.close().catch(() => {
@@ -9301,8 +9309,44 @@ function classifyBingWeakness(query, results) {
9301
9309
  if (homepageCount / results.length >= 0.6) {
9302
9310
  return `${homepageCount}/${results.length} results are bare site homepages (popular-sites fallback)`;
9303
9311
  }
9312
+ if (!hasDefinitionIntent(query) && countAsciiWords(query) >= 4) {
9313
+ const dictHits = results.filter(isDictionaryResult).length;
9314
+ if (dictHits >= 2 || isDictionaryResult(results[0])) {
9315
+ return `${dictHits}/${results.length} dictionary word-lookup results for a multi-word query (word-match fallback)`;
9316
+ }
9317
+ }
9318
+ if (!hasDefinitionIntent(query)) {
9319
+ const { total, best } = tokenCoverage(query, results);
9320
+ if (total >= 4 && best < 2) {
9321
+ return `low query-token coverage (best result matches only ${best}/${total} query terms)`;
9322
+ }
9323
+ }
9304
9324
  return null;
9305
9325
  }
9326
+ function tokenCoverage(query, results) {
9327
+ const tokens = extractQueryTokens(query);
9328
+ let best = 0;
9329
+ for (const r of results) {
9330
+ const haystack = (r.title + " " + r.snippet).toLowerCase();
9331
+ let matched = 0;
9332
+ for (const t of tokens) {
9333
+ if (haystack.includes(t.toLowerCase())) matched++;
9334
+ }
9335
+ if (matched > best) best = matched;
9336
+ }
9337
+ return { total: tokens.size, best };
9338
+ }
9339
+ var DICT_DOMAIN_RE = /\b(iciba\.com|dict\.youdao\.com|youdao\.com\/w\/|dict\.cn|dict\.baidu\.com|dictionary\.cambridge\.org|merriam-webster\.com|vocabulary\.com|bing\.com\/dict)/i;
9340
+ var DICT_TITLE_RE = /(是什么意思|的翻译|_音标_|权威在线词典|剑桥词典|Definition\s*&\s*Meaning)/i;
9341
+ function isDictionaryResult(r) {
9342
+ return DICT_DOMAIN_RE.test(r.url) || DICT_TITLE_RE.test(r.title);
9343
+ }
9344
+ function hasDefinitionIntent(query) {
9345
+ return /(meaning|definition|define\b|translat|pronounc|是什么意思|什么意思|翻译|词典|发音|读音|用法)/i.test(query);
9346
+ }
9347
+ function countAsciiWords(query) {
9348
+ return (query.match(/[a-zA-Z]{3,}/g) ?? []).length;
9349
+ }
9306
9350
  function isBareHomepage(url) {
9307
9351
  try {
9308
9352
  return new URL(url).pathname.replace(/\/+$/, "") === "";
@@ -10146,8 +10190,8 @@ import { join as join14 } from "path";
10146
10190
  import { homedir as homedir6 } from "os";
10147
10191
 
10148
10192
  // src/plugins/plugin-manager.ts
10149
- import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync7, readFileSync as readFileSync13, cpSync, rmSync, statSync as statSync7 } from "fs";
10150
- import { basename as basename6, dirname as dirname8, join as join13, resolve as resolve7 } from "path";
10193
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync7, readFileSync as readFileSync13, realpathSync as realpathSync2, cpSync, rmSync, statSync as statSync7 } from "fs";
10194
+ import { basename as basename6, dirname as dirname8, join as join13, relative as relative3, resolve as resolve7, sep as sep3 } from "path";
10151
10195
  import { createHash as createHash3 } from "crypto";
10152
10196
  import { z as z2 } from "zod";
10153
10197
  var MANIFEST_RELATIVE = ".aicli-plugin/plugin.json";
@@ -10217,20 +10261,117 @@ function statePath(configDir) {
10217
10261
  }
10218
10262
  function loadState(configDir) {
10219
10263
  const file = statePath(configDir);
10220
- if (!existsSync18(file)) return { version: 1, plugins: [] };
10264
+ if (!existsSync18(file)) return { version: 2, plugins: [] };
10221
10265
  try {
10222
10266
  const parsed = JSON.parse(readFileSync13(file, "utf-8"));
10223
- return { version: 1, plugins: Array.isArray(parsed.plugins) ? parsed.plugins : [] };
10267
+ const rawPlugins = Array.isArray(parsed.plugins) ? parsed.plugins : [];
10268
+ return { version: 2, plugins: rawPlugins.map((p) => migrateEntry(p)) };
10224
10269
  } catch {
10225
- return { version: 1, plugins: [] };
10270
+ return { version: 2, plugins: [] };
10226
10271
  }
10227
10272
  }
10273
+ function migrateEntry(entry) {
10274
+ const name = String(entry.name ?? "");
10275
+ const contentHash = typeof entry.contentHash === "string" ? entry.contentHash : void 0;
10276
+ const legacyHash = typeof entry.hash === "string" ? entry.hash : void 0;
10277
+ const trusted = contentHash ? entry.trusted === true : false;
10278
+ return {
10279
+ name,
10280
+ enabled: entry.enabled === true,
10281
+ trusted,
10282
+ contentHash: contentHash ?? legacyHash,
10283
+ installedAt: String(entry.installedAt ?? (/* @__PURE__ */ new Date(0)).toISOString()),
10284
+ trustedAt: trusted && entry.trustedAt ? String(entry.trustedAt) : void 0,
10285
+ enabledAt: entry.enabledAt ? String(entry.enabledAt) : void 0
10286
+ };
10287
+ }
10228
10288
  function saveState(configDir, state2) {
10229
10289
  mkdirSync9(pluginRoot(configDir), { recursive: true });
10230
10290
  atomicWriteFileSync(statePath(configDir), JSON.stringify(state2, null, 2));
10231
10291
  }
10232
- function hashPluginManifest(manifestPath) {
10233
- return createHash3("sha256").update(readFileSync13(manifestPath)).digest("hex");
10292
+ function normalizeForHash(buf) {
10293
+ const str = buf.toString("utf-8").replaceAll("\r\n", "\n");
10294
+ return Buffer.from(str, "utf-8");
10295
+ }
10296
+ function extractCommandPaths(command, pluginDir) {
10297
+ const resolvedDir = resolve7(pluginDir);
10298
+ const refs = [];
10299
+ for (const m of command.matchAll(/\$PLUGIN_DIR[\\/]([^"'\s]+)/g)) {
10300
+ refs.push(m[1]);
10301
+ }
10302
+ for (const m of command.matchAll(/\$\{pluginDir\}[\\/]([^"'\s}]+)/g)) {
10303
+ refs.push(m[1]);
10304
+ }
10305
+ for (const m of command.matchAll(/(?<=["'\s])(\.?[.\\/][^"'\s]+)/g)) {
10306
+ refs.push(m[0]);
10307
+ }
10308
+ const seen = /* @__PURE__ */ new Set();
10309
+ const valid = [];
10310
+ for (const ref of refs) {
10311
+ if (seen.has(ref)) continue;
10312
+ seen.add(ref);
10313
+ try {
10314
+ const abs = resolve7(resolvedDir, ref);
10315
+ if (!abs.startsWith(resolvedDir + sep3)) continue;
10316
+ if (existsSync18(abs)) {
10317
+ const real = realpathSync2(abs);
10318
+ if (!real.startsWith(resolvedDir + sep3)) continue;
10319
+ valid.push(relative3(resolvedDir, real));
10320
+ }
10321
+ } catch {
10322
+ }
10323
+ }
10324
+ return valid;
10325
+ }
10326
+ function hashPluginContent(pluginDir, manifest) {
10327
+ const resolvedDir = resolve7(pluginDir);
10328
+ const assetRels = /* @__PURE__ */ new Set(
10329
+ [...manifest.skills, ...manifest.commands, ...manifest.agents]
10330
+ );
10331
+ for (const raw of Object.values(manifest.hooks?.events ?? {})) {
10332
+ const items = Array.isArray(raw) ? raw : [raw];
10333
+ for (const item of items) {
10334
+ const cmd = typeof item === "string" ? item : item.command;
10335
+ if (cmd) {
10336
+ for (const p of extractCommandPaths(cmd, pluginDir)) assetRels.add(p);
10337
+ }
10338
+ }
10339
+ }
10340
+ for (const server of Object.values(manifest.mcpServers ?? {})) {
10341
+ for (const p of extractCommandPaths(server.command, pluginDir)) assetRels.add(p);
10342
+ for (const arg of server.args ?? []) {
10343
+ for (const p of extractCommandPaths(arg, pluginDir)) assetRels.add(p);
10344
+ }
10345
+ }
10346
+ const sorted = [...assetRels].sort();
10347
+ const hasher = createHash3("sha256");
10348
+ const manifestPath = join13(resolvedDir, MANIFEST_RELATIVE);
10349
+ hasher.update(normalizeForHash(readFileSync13(manifestPath)));
10350
+ for (const rel of sorted) {
10351
+ const abs = resolve7(resolvedDir, rel);
10352
+ if (!abs.startsWith(resolvedDir + sep3)) {
10353
+ throw new Error(`plugin asset escapes plugin dir: ${rel}`);
10354
+ }
10355
+ let realPath;
10356
+ try {
10357
+ realPath = realpathSync2(abs);
10358
+ } catch {
10359
+ continue;
10360
+ }
10361
+ try {
10362
+ if (statSync7(realPath).isDirectory()) continue;
10363
+ } catch {
10364
+ continue;
10365
+ }
10366
+ if (!realPath.startsWith(resolvedDir + sep3)) {
10367
+ throw new Error(`plugin asset symlink escapes plugin dir: ${rel} \u2192 ${realPath}`);
10368
+ }
10369
+ hasher.update(normalizeForHash(readFileSync13(abs)));
10370
+ }
10371
+ return hasher.digest("hex");
10372
+ }
10373
+ function effectiveHash(entry) {
10374
+ return entry.contentHash ?? entry.hash ?? "";
10234
10375
  }
10235
10376
  function readPluginManifest(manifestPath) {
10236
10377
  return PluginManifestSchema.parse(JSON.parse(readFileSync13(manifestPath, "utf-8")));
@@ -10251,19 +10392,19 @@ function installPlugin(configDir, inputPath) {
10251
10392
  if (existsSync18(targetDir)) rmSync(targetDir, { recursive: true, force: true });
10252
10393
  cpSync(sourceDir, targetDir, { recursive: true });
10253
10394
  const manifestPath = pluginManifestPath(targetDir);
10254
- const hash = hashPluginManifest(manifestPath);
10395
+ const contentHash = hashPluginContent(targetDir, manifest);
10255
10396
  const state2 = loadState(configDir);
10256
10397
  const previous = state2.plugins.find((p) => p.name === manifest.name);
10257
10398
  const next = {
10258
10399
  name: manifest.name,
10259
10400
  enabled: previous?.enabled ?? false,
10260
10401
  trusted: false,
10261
- hash,
10402
+ contentHash,
10262
10403
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10263
10404
  };
10264
10405
  state2.plugins = [...state2.plugins.filter((p) => p.name !== manifest.name), next];
10265
10406
  saveState(configDir, state2);
10266
- return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash, enabled: next.enabled, trusted: false, valid: true };
10407
+ return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash: contentHash, enabled: next.enabled, trusted: false, valid: true };
10267
10408
  }
10268
10409
  function setPluginEnabled(configDir, name, enabled) {
10269
10410
  const plugin = getInstalledPlugin(configDir, name);
@@ -10273,10 +10414,10 @@ function setPluginEnabled(configDir, name, enabled) {
10273
10414
  name: plugin.name,
10274
10415
  enabled: false,
10275
10416
  trusted: false,
10276
- hash: plugin.hash,
10417
+ contentHash: plugin.hash,
10277
10418
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10278
10419
  };
10279
- const next = { ...current, enabled, hash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
10420
+ const next = { ...current, enabled, contentHash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
10280
10421
  state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
10281
10422
  saveState(configDir, state2);
10282
10423
  return next;
@@ -10289,10 +10430,10 @@ function trustPlugin(configDir, name) {
10289
10430
  name: plugin.name,
10290
10431
  enabled: false,
10291
10432
  trusted: false,
10292
- hash: plugin.hash,
10433
+ contentHash: plugin.hash,
10293
10434
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10294
10435
  };
10295
- const next = { ...current, trusted: true, hash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
10436
+ const next = { ...current, trusted: true, contentHash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
10296
10437
  state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
10297
10438
  saveState(configDir, state2);
10298
10439
  return next;
@@ -10320,15 +10461,15 @@ function listInstalledPlugins(configDir) {
10320
10461
  if (!existsSync18(manifestPath)) continue;
10321
10462
  try {
10322
10463
  const manifest = readPluginManifest(manifestPath);
10323
- const hash = hashPluginManifest(manifestPath);
10464
+ const contentHash = hashPluginContent(dir, manifest);
10324
10465
  const st = state2.plugins.find((p) => p.name === manifest.name);
10325
- const trusted = st?.trusted === true && st.hash === hash;
10466
+ const trusted = st?.trusted === true && effectiveHash(st) === contentHash;
10326
10467
  out.push({
10327
10468
  name: manifest.name,
10328
10469
  dir,
10329
10470
  manifestPath,
10330
10471
  manifest,
10331
- hash,
10472
+ hash: contentHash,
10332
10473
  enabled: st?.enabled === true,
10333
10474
  trusted,
10334
10475
  valid: true
@@ -13607,7 +13748,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13607
13748
 
13608
13749
  // src/core/context-files.ts
13609
13750
  import { existsSync as existsSync26, readFileSync as readFileSync19 } from "fs";
13610
- import { join as join19, relative as relative3, resolve as resolve9 } from "path";
13751
+ import { join as join19, relative as relative4, resolve as resolve9 } from "path";
13611
13752
  function uniqueNonEmpty(values) {
13612
13753
  const seen = /* @__PURE__ */ new Set();
13613
13754
  const out = [];
@@ -13623,14 +13764,14 @@ function buildContextFileCandidates(fallbackFilenames = []) {
13623
13764
  return uniqueNonEmpty([...CONTEXT_FILE_CANDIDATES, ...fallbackFilenames]);
13624
13765
  }
13625
13766
  function displayPath(filePath, cwd) {
13626
- const rel = relative3(cwd, filePath);
13767
+ const rel = relative4(cwd, filePath);
13627
13768
  if (rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\")) {
13628
13769
  return rel;
13629
13770
  }
13630
13771
  return filePath;
13631
13772
  }
13632
13773
  function isInsideOrEqual(parent, child) {
13633
- const rel = relative3(resolve9(parent), resolve9(child));
13774
+ const rel = relative4(resolve9(parent), resolve9(child));
13634
13775
  return rel === "" || !!rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\");
13635
13776
  }
13636
13777
  function readContextFile(level, filePath, cwd, maxBytes) {
@@ -13763,8 +13904,8 @@ function loadContextFiles(options) {
13763
13904
  }
13764
13905
 
13765
13906
  // src/web/session-handler.ts
13766
- import { mkdirSync as mkdirSync16, createWriteStream as createWriteStream3 } from "fs";
13767
- import { join as join26, dirname as dirname11 } from "path";
13907
+ import { mkdirSync as mkdirSync15, createWriteStream as createWriteStream2 } from "fs";
13908
+ import { join as join26, dirname as dirname10 } from "path";
13768
13909
 
13769
13910
  // src/repl/commands/project-init.ts
13770
13911
  import { existsSync as existsSync27, readFileSync as readFileSync20, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
@@ -15889,7 +16030,7 @@ async function handleSecurityReview(args, ctx) {
15889
16030
  async function handleTest(args, ctx) {
15890
16031
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
15891
16032
  try {
15892
- const { executeTests } = await import("./run-tests-YSRET52H.js");
16033
+ const { executeTests } = await import("./run-tests-K36VNQ5W.js");
15893
16034
  const argStr = args.join(" ").trim();
15894
16035
  let testArgs = {};
15895
16036
  if (argStr) {
@@ -17217,7 +17358,7 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
17217
17358
  this.send({ type: "response_done", content, usage });
17218
17359
  if (pendingTeeSave && isCleanDocumentBody(content)) {
17219
17360
  try {
17220
- mkdirSync16(dirname11(pendingTeeSave), { recursive: true });
17361
+ mkdirSync15(dirname10(pendingTeeSave), { recursive: true });
17221
17362
  const bodyToSave = stripOuterCodeFence(content);
17222
17363
  atomicWriteFileSync(pendingTeeSave, bodyToSave);
17223
17364
  undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
@@ -17393,8 +17534,8 @@ ${summaryContent}`,
17393
17534
  let isError = false;
17394
17535
  let summary;
17395
17536
  try {
17396
- mkdirSync16(dirname11(saveToFile), { recursive: true });
17397
- fileStream = createWriteStream3(saveToFile);
17537
+ mkdirSync15(dirname10(saveToFile), { recursive: true });
17538
+ fileStream = createWriteStream2(saveToFile);
17398
17539
  const teeSystemPrompt = stripToolCallReminder(systemPrompt ?? "") + CONTENT_ONLY_STREAM_REMINDER;
17399
17540
  const teeExtraMessages = extraMessages.length > 0 ? [...extraMessages, { role: "user", content: TEE_FINAL_USER_NUDGE }] : [{ role: "user", content: TEE_FINAL_USER_NUDGE }];
17400
17541
  const chatRequest = {
@@ -17968,8 +18109,8 @@ async function setupProxy(configProxy) {
17968
18109
  }
17969
18110
 
17970
18111
  // src/web/auth.ts
17971
- import { existsSync as existsSync33, readFileSync as readFileSync25, writeFileSync as writeFileSync6, mkdirSync as mkdirSync17, readdirSync as readdirSync16, copyFileSync } from "fs";
17972
- import { isAbsolute as isAbsolute3, join as join27, relative as relative4 } from "path";
18112
+ import { existsSync as existsSync32, readFileSync as readFileSync24, writeFileSync as writeFileSync5, mkdirSync as mkdirSync16, readdirSync as readdirSync15, copyFileSync } from "fs";
18113
+ import { isAbsolute as isAbsolute3, join as join27, relative as relative5 } from "path";
17973
18114
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
17974
18115
  var USERS_FILE = "users.json";
17975
18116
  var TOKEN_EXPIRY_HOURS = 24;
@@ -18015,7 +18156,7 @@ var AuthManager = class {
18015
18156
  const passwordHash = this.hashPassword(password, salt);
18016
18157
  const dataDir = join27(USERS_DIR, username);
18017
18158
  const fullDataDir = join27(this.baseDir, dataDir);
18018
- mkdirSync17(join27(fullDataDir, "history"), { recursive: true });
18159
+ mkdirSync16(join27(fullDataDir, "history"), { recursive: true });
18019
18160
  const user = {
18020
18161
  username,
18021
18162
  passwordHash,
@@ -18167,25 +18308,25 @@ var AuthManager = class {
18167
18308
  if (err) return err;
18168
18309
  const userDir = this.getUserDataDir(username);
18169
18310
  const globalConfig = join27(this.baseDir, "config.json");
18170
- if (existsSync33(globalConfig)) {
18311
+ if (existsSync32(globalConfig)) {
18171
18312
  try {
18172
- const content = readFileSync25(globalConfig, "utf-8");
18173
- writeFileSync6(join27(userDir, "config.json"), content, "utf-8");
18313
+ const content = readFileSync24(globalConfig, "utf-8");
18314
+ writeFileSync5(join27(userDir, "config.json"), content, "utf-8");
18174
18315
  } catch {
18175
18316
  }
18176
18317
  }
18177
18318
  const globalMemory = join27(this.baseDir, "memory.md");
18178
- if (existsSync33(globalMemory)) {
18319
+ if (existsSync32(globalMemory)) {
18179
18320
  try {
18180
- const content = readFileSync25(globalMemory, "utf-8");
18181
- writeFileSync6(join27(userDir, "memory.md"), content, "utf-8");
18321
+ const content = readFileSync24(globalMemory, "utf-8");
18322
+ writeFileSync5(join27(userDir, "memory.md"), content, "utf-8");
18182
18323
  } catch {
18183
18324
  }
18184
18325
  }
18185
18326
  const globalHistory = join27(this.baseDir, "history");
18186
- if (existsSync33(globalHistory)) {
18327
+ if (existsSync32(globalHistory)) {
18187
18328
  try {
18188
- const files = readdirSync16(globalHistory).filter((f) => f.endsWith(".json"));
18329
+ const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
18189
18330
  const userHistory = join27(userDir, "history");
18190
18331
  for (const f of files) {
18191
18332
  try {
@@ -18200,9 +18341,9 @@ var AuthManager = class {
18200
18341
  }
18201
18342
  // ── Private methods ────────────────────────────────────────────
18202
18343
  loadOrCreate() {
18203
- if (existsSync33(this.usersFile)) {
18344
+ if (existsSync32(this.usersFile)) {
18204
18345
  try {
18205
- const parsed = JSON.parse(readFileSync25(this.usersFile, "utf-8"));
18346
+ const parsed = JSON.parse(readFileSync24(this.usersFile, "utf-8"));
18206
18347
  if (!this.isValidUsersDB(parsed)) {
18207
18348
  throw new Error("database structure is invalid");
18208
18349
  }
@@ -18236,7 +18377,7 @@ var AuthManager = class {
18236
18377
  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)) {
18237
18378
  return false;
18238
18379
  }
18239
- const dataDirFromBase = relative4(this.baseDir, join27(this.baseDir, record.dataDir));
18380
+ const dataDirFromBase = relative5(this.baseDir, join27(this.baseDir, record.dataDir));
18240
18381
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
18241
18382
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
18242
18383
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -18248,7 +18389,7 @@ var AuthManager = class {
18248
18389
  this.saveDB(this.db);
18249
18390
  }
18250
18391
  saveDB(db) {
18251
- mkdirSync17(this.baseDir, { recursive: true });
18392
+ mkdirSync16(this.baseDir, { recursive: true });
18252
18393
  atomicWriteFileSync(this.usersFile, JSON.stringify(db, null, 2));
18253
18394
  }
18254
18395
  /** Legacy hash — kept only for migrating old users (v0.2.x) */
@@ -18280,7 +18421,7 @@ function getModuleDir() {
18280
18421
  if (typeof import.meta?.url === "string") {
18281
18422
  const url = new URL(import.meta.url);
18282
18423
  const filePath = url.pathname.replace(/^\/([A-Z]:)/i, "$1");
18283
- return dirname12(filePath);
18424
+ return dirname11(filePath);
18284
18425
  }
18285
18426
  } catch {
18286
18427
  }
@@ -18353,7 +18494,7 @@ async function startWebServer(options = {}) {
18353
18494
  }
18354
18495
  let skillManager = null;
18355
18496
  const skillsDir = join28(config.getConfigDir(), SKILLS_DIR_NAME);
18356
- if (existsSync34(skillsDir)) {
18497
+ if (existsSync33(skillsDir)) {
18357
18498
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
18358
18499
  skillManager.loadSkills(pluginAssets.skillDirs);
18359
18500
  const count = skillManager.listSkills().length;
@@ -18425,13 +18566,13 @@ async function startWebServer(options = {}) {
18425
18566
  };
18426
18567
  const moduleDir = getModuleDir();
18427
18568
  let clientDir = join28(moduleDir, "web", "client");
18428
- if (!existsSync34(clientDir)) {
18569
+ if (!existsSync33(clientDir)) {
18429
18570
  clientDir = join28(moduleDir, "client");
18430
18571
  }
18431
- if (!existsSync34(clientDir)) {
18572
+ if (!existsSync33(clientDir)) {
18432
18573
  clientDir = join28(moduleDir, "..", "..", "src", "web", "client");
18433
18574
  }
18434
- if (!existsSync34(clientDir)) {
18575
+ if (!existsSync33(clientDir)) {
18435
18576
  clientDir = join28(process.cwd(), "src", "web", "client");
18436
18577
  }
18437
18578
  console.log(` Static files: ${clientDir}`);
@@ -18504,9 +18645,9 @@ async function startWebServer(options = {}) {
18504
18645
  const prefix = req.query.prefix || "";
18505
18646
  const targetDir = join28(cwd, prefix);
18506
18647
  try {
18507
- const canonicalTarget = realpathSync2(resolve13(targetDir));
18508
- const canonicalCwd = realpathSync2(resolve13(cwd));
18509
- if (!canonicalTarget.startsWith(canonicalCwd + sep3) && canonicalTarget !== canonicalCwd) {
18648
+ const canonicalTarget = realpathSync3(resolve13(targetDir));
18649
+ const canonicalCwd = realpathSync3(resolve13(cwd));
18650
+ if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
18510
18651
  res.json({ files: [] });
18511
18652
  return;
18512
18653
  }
@@ -18516,10 +18657,10 @@ async function startWebServer(options = {}) {
18516
18657
  }
18517
18658
  try {
18518
18659
  const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
18519
- const entries = readdirSync17(targetDir, { withFileTypes: true });
18660
+ const entries = readdirSync16(targetDir, { withFileTypes: true });
18520
18661
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
18521
18662
  name: e.name,
18522
- path: relative5(cwd, join28(targetDir, e.name)).replace(/\\/g, "/"),
18663
+ path: relative6(cwd, join28(targetDir, e.name)).replace(/\\/g, "/"),
18523
18664
  isDir: e.isDirectory()
18524
18665
  }));
18525
18666
  res.json({ files });
@@ -18560,14 +18701,14 @@ async function startWebServer(options = {}) {
18560
18701
  const authUser = req._authUser;
18561
18702
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
18562
18703
  const filePath = join28(histDir, `${id}.json`);
18563
- if (!existsSync34(filePath)) {
18704
+ if (!existsSync33(filePath)) {
18564
18705
  res.status(404).json({ error: "Session not found" });
18565
18706
  return;
18566
18707
  }
18567
18708
  try {
18568
- const canonicalFile = realpathSync2(filePath);
18569
- const canonicalDir = realpathSync2(histDir);
18570
- if (!canonicalFile.startsWith(canonicalDir + sep3)) {
18709
+ const canonicalFile = realpathSync3(filePath);
18710
+ const canonicalDir = realpathSync3(histDir);
18711
+ if (!canonicalFile.startsWith(canonicalDir + sep4)) {
18571
18712
  res.status(404).json({ error: "Session not found" });
18572
18713
  return;
18573
18714
  }
@@ -18575,7 +18716,7 @@ async function startWebServer(options = {}) {
18575
18716
  res.status(404).json({ error: "Session not found" });
18576
18717
  return;
18577
18718
  }
18578
- const data = JSON.parse(readFileSync26(filePath, "utf-8"));
18719
+ const data = JSON.parse(readFileSync25(filePath, "utf-8"));
18579
18720
  res.json({ session: data });
18580
18721
  } catch (err) {
18581
18722
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
@@ -18590,9 +18731,9 @@ async function startWebServer(options = {}) {
18590
18731
  const cwd = process.cwd();
18591
18732
  const fullPath = resolve13(join28(cwd, filePath));
18592
18733
  try {
18593
- const canonicalFull = realpathSync2(fullPath);
18594
- const canonicalCwd = realpathSync2(resolve13(cwd));
18595
- if (!canonicalFull.startsWith(canonicalCwd + sep3) && canonicalFull !== canonicalCwd) {
18734
+ const canonicalFull = realpathSync3(fullPath);
18735
+ const canonicalCwd = realpathSync3(resolve13(cwd));
18736
+ if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
18596
18737
  res.json({ error: "Access denied" });
18597
18738
  return;
18598
18739
  }
@@ -18601,12 +18742,12 @@ async function startWebServer(options = {}) {
18601
18742
  return;
18602
18743
  }
18603
18744
  try {
18604
- const stat = statSync15(fullPath);
18745
+ const stat = statSync14(fullPath);
18605
18746
  if (stat.size > 512 * 1024) {
18606
18747
  res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
18607
18748
  return;
18608
18749
  }
18609
- const content = readFileSync26(fullPath, "utf-8");
18750
+ const content = readFileSync25(fullPath, "utf-8");
18610
18751
  res.json({ content, size: stat.size });
18611
18752
  } catch {
18612
18753
  res.json({ error: "Cannot read file" });
@@ -18862,16 +19003,16 @@ function resolveProjectMcpPath() {
18862
19003
  const gitRoot = getGitRoot(cwd);
18863
19004
  const projectRoot = gitRoot ?? cwd;
18864
19005
  const configPath = join28(projectRoot, MCP_PROJECT_CONFIG_NAME);
18865
- return existsSync34(configPath) ? configPath : null;
19006
+ return existsSync33(configPath) ? configPath : null;
18866
19007
  }
18867
19008
  function loadProjectMcpConfig() {
18868
19009
  const cwd = process.cwd();
18869
19010
  const gitRoot = getGitRoot(cwd);
18870
19011
  const projectRoot = gitRoot ?? cwd;
18871
19012
  const configPath = join28(projectRoot, MCP_PROJECT_CONFIG_NAME);
18872
- if (!existsSync34(configPath)) return null;
19013
+ if (!existsSync33(configPath)) return null;
18873
19014
  try {
18874
- const raw = JSON.parse(readFileSync26(configPath, "utf-8"));
19015
+ const raw = JSON.parse(readFileSync25(configPath, "utf-8"));
18875
19016
  return raw.mcpServers ?? raw;
18876
19017
  } catch {
18877
19018
  return null;
@@ -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-QMERCD77.js");
157
+ const { TaskOrchestrator } = await import("./task-orchestrator-D66BJZKU.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {