jinzd-ai-cli 0.4.235 → 0.4.236

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-HZI7QAE7.js} +2 -2
  3. package/dist/{chunk-Q5GVANMH.js → chunk-7VAE3I3D.js} +1 -1
  4. package/dist/{chunk-GDXKFWFL.js → chunk-CGQARJMP.js} +1 -1
  5. package/dist/{chunk-HHYMSEWS.js → chunk-MFWAL5S2.js} +1 -1
  6. package/dist/{chunk-CDOQNIVV.js → chunk-O4QYY6SF.js} +3 -3
  7. package/dist/{chunk-7D5EJBHO.js → chunk-QDP3NUPX.js} +3 -3
  8. package/dist/{chunk-FYJGVFXL.js → chunk-SBSWH2EG.js} +7 -7
  9. package/dist/{chunk-WXFQ6LYN.js → chunk-SCFGLRB3.js} +1 -1
  10. package/dist/{chunk-GFDRC2JZ.js → chunk-T6EIBUKW.js} +115 -18
  11. package/dist/{chunk-DHNYGJYB.js → chunk-TT7YURG3.js} +3 -3
  12. package/dist/{chunk-BFTTW5LS.js → chunk-VBAW4ZPY.js} +1 -1
  13. package/dist/{ci-OAFNH3MA.js → ci-FYLCHRN3.js} +4 -4
  14. package/dist/{ci-format-4LSXJNND.js → ci-format-TH2ZTFKU.js} +2 -2
  15. package/dist/{constants-ERIAS7GV.js → constants-BF6YNKRW.js} +1 -1
  16. package/dist/{doctor-cli-VFSVWZU6.js → doctor-cli-B6GE4BYJ.js} +4 -4
  17. package/dist/electron-server.js +164 -67
  18. package/dist/{hub-X4EUYRIN.js → hub-QBQCKEPE.js} +1 -1
  19. package/dist/index.js +2438 -2436
  20. package/dist/{pr-2CZN5JLE.js → pr-KV2WK7SU.js} +4 -4
  21. package/dist/{run-tests-YSRET52H.js → run-tests-DI6WEYHX.js} +1 -1
  22. package/dist/{run-tests-DXRJDPFF.js → run-tests-MEHC73SQ.js} +2 -2
  23. package/dist/{server-FGJGXHZD.js → server-ETIGAZX5.js} +4 -4
  24. package/dist/{server-5ZAXMKRI.js → server-KZAP5JN3.js} +28 -28
  25. package/dist/{task-orchestrator-QMERCD77.js → task-orchestrator-WS724BUX.js} +4 -4
  26. package/dist/{usage-633DUDNT.js → usage-DHZR5PG7.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-MFWAL5S2.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
@@ -10146,8 +10146,8 @@ import { join as join14 } from "path";
10146
10146
  import { homedir as homedir6 } from "os";
10147
10147
 
10148
10148
  // 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";
10149
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readdirSync as readdirSync7, readFileSync as readFileSync13, realpathSync as realpathSync2, cpSync, rmSync, statSync as statSync7 } from "fs";
10150
+ import { basename as basename6, dirname as dirname8, join as join13, relative as relative3, resolve as resolve7, sep as sep3 } from "path";
10151
10151
  import { createHash as createHash3 } from "crypto";
10152
10152
  import { z as z2 } from "zod";
10153
10153
  var MANIFEST_RELATIVE = ".aicli-plugin/plugin.json";
@@ -10217,20 +10217,117 @@ function statePath(configDir) {
10217
10217
  }
10218
10218
  function loadState(configDir) {
10219
10219
  const file = statePath(configDir);
10220
- if (!existsSync18(file)) return { version: 1, plugins: [] };
10220
+ if (!existsSync18(file)) return { version: 2, plugins: [] };
10221
10221
  try {
10222
10222
  const parsed = JSON.parse(readFileSync13(file, "utf-8"));
10223
- return { version: 1, plugins: Array.isArray(parsed.plugins) ? parsed.plugins : [] };
10223
+ const rawPlugins = Array.isArray(parsed.plugins) ? parsed.plugins : [];
10224
+ return { version: 2, plugins: rawPlugins.map((p) => migrateEntry(p)) };
10224
10225
  } catch {
10225
- return { version: 1, plugins: [] };
10226
+ return { version: 2, plugins: [] };
10226
10227
  }
10227
10228
  }
10229
+ function migrateEntry(entry) {
10230
+ const name = String(entry.name ?? "");
10231
+ const contentHash = typeof entry.contentHash === "string" ? entry.contentHash : void 0;
10232
+ const legacyHash = typeof entry.hash === "string" ? entry.hash : void 0;
10233
+ const trusted = contentHash ? entry.trusted === true : false;
10234
+ return {
10235
+ name,
10236
+ enabled: entry.enabled === true,
10237
+ trusted,
10238
+ contentHash: contentHash ?? legacyHash,
10239
+ installedAt: String(entry.installedAt ?? (/* @__PURE__ */ new Date(0)).toISOString()),
10240
+ trustedAt: trusted && entry.trustedAt ? String(entry.trustedAt) : void 0,
10241
+ enabledAt: entry.enabledAt ? String(entry.enabledAt) : void 0
10242
+ };
10243
+ }
10228
10244
  function saveState(configDir, state2) {
10229
10245
  mkdirSync9(pluginRoot(configDir), { recursive: true });
10230
10246
  atomicWriteFileSync(statePath(configDir), JSON.stringify(state2, null, 2));
10231
10247
  }
10232
- function hashPluginManifest(manifestPath) {
10233
- return createHash3("sha256").update(readFileSync13(manifestPath)).digest("hex");
10248
+ function normalizeForHash(buf) {
10249
+ const str = buf.toString("utf-8").replaceAll("\r\n", "\n");
10250
+ return Buffer.from(str, "utf-8");
10251
+ }
10252
+ function extractCommandPaths(command, pluginDir) {
10253
+ const resolvedDir = resolve7(pluginDir);
10254
+ const refs = [];
10255
+ for (const m of command.matchAll(/\$PLUGIN_DIR[\\/]([^"'\s]+)/g)) {
10256
+ refs.push(m[1]);
10257
+ }
10258
+ for (const m of command.matchAll(/\$\{pluginDir\}[\\/]([^"'\s}]+)/g)) {
10259
+ refs.push(m[1]);
10260
+ }
10261
+ for (const m of command.matchAll(/(?<=["'\s])(\.?[.\\/][^"'\s]+)/g)) {
10262
+ refs.push(m[0]);
10263
+ }
10264
+ const seen = /* @__PURE__ */ new Set();
10265
+ const valid = [];
10266
+ for (const ref of refs) {
10267
+ if (seen.has(ref)) continue;
10268
+ seen.add(ref);
10269
+ try {
10270
+ const abs = resolve7(resolvedDir, ref);
10271
+ if (!abs.startsWith(resolvedDir + sep3)) continue;
10272
+ if (existsSync18(abs)) {
10273
+ const real = realpathSync2(abs);
10274
+ if (!real.startsWith(resolvedDir + sep3)) continue;
10275
+ valid.push(relative3(resolvedDir, real));
10276
+ }
10277
+ } catch {
10278
+ }
10279
+ }
10280
+ return valid;
10281
+ }
10282
+ function hashPluginContent(pluginDir, manifest) {
10283
+ const resolvedDir = resolve7(pluginDir);
10284
+ const assetRels = /* @__PURE__ */ new Set(
10285
+ [...manifest.skills, ...manifest.commands, ...manifest.agents]
10286
+ );
10287
+ for (const raw of Object.values(manifest.hooks?.events ?? {})) {
10288
+ const items = Array.isArray(raw) ? raw : [raw];
10289
+ for (const item of items) {
10290
+ const cmd = typeof item === "string" ? item : item.command;
10291
+ if (cmd) {
10292
+ for (const p of extractCommandPaths(cmd, pluginDir)) assetRels.add(p);
10293
+ }
10294
+ }
10295
+ }
10296
+ for (const server of Object.values(manifest.mcpServers ?? {})) {
10297
+ for (const p of extractCommandPaths(server.command, pluginDir)) assetRels.add(p);
10298
+ for (const arg of server.args ?? []) {
10299
+ for (const p of extractCommandPaths(arg, pluginDir)) assetRels.add(p);
10300
+ }
10301
+ }
10302
+ const sorted = [...assetRels].sort();
10303
+ const hasher = createHash3("sha256");
10304
+ const manifestPath = join13(resolvedDir, MANIFEST_RELATIVE);
10305
+ hasher.update(normalizeForHash(readFileSync13(manifestPath)));
10306
+ for (const rel of sorted) {
10307
+ const abs = resolve7(resolvedDir, rel);
10308
+ if (!abs.startsWith(resolvedDir + sep3)) {
10309
+ throw new Error(`plugin asset escapes plugin dir: ${rel}`);
10310
+ }
10311
+ let realPath;
10312
+ try {
10313
+ realPath = realpathSync2(abs);
10314
+ } catch {
10315
+ continue;
10316
+ }
10317
+ try {
10318
+ if (statSync7(realPath).isDirectory()) continue;
10319
+ } catch {
10320
+ continue;
10321
+ }
10322
+ if (!realPath.startsWith(resolvedDir + sep3)) {
10323
+ throw new Error(`plugin asset symlink escapes plugin dir: ${rel} \u2192 ${realPath}`);
10324
+ }
10325
+ hasher.update(normalizeForHash(readFileSync13(abs)));
10326
+ }
10327
+ return hasher.digest("hex");
10328
+ }
10329
+ function effectiveHash(entry) {
10330
+ return entry.contentHash ?? entry.hash ?? "";
10234
10331
  }
10235
10332
  function readPluginManifest(manifestPath) {
10236
10333
  return PluginManifestSchema.parse(JSON.parse(readFileSync13(manifestPath, "utf-8")));
@@ -10251,19 +10348,19 @@ function installPlugin(configDir, inputPath) {
10251
10348
  if (existsSync18(targetDir)) rmSync(targetDir, { recursive: true, force: true });
10252
10349
  cpSync(sourceDir, targetDir, { recursive: true });
10253
10350
  const manifestPath = pluginManifestPath(targetDir);
10254
- const hash = hashPluginManifest(manifestPath);
10351
+ const contentHash = hashPluginContent(targetDir, manifest);
10255
10352
  const state2 = loadState(configDir);
10256
10353
  const previous = state2.plugins.find((p) => p.name === manifest.name);
10257
10354
  const next = {
10258
10355
  name: manifest.name,
10259
10356
  enabled: previous?.enabled ?? false,
10260
10357
  trusted: false,
10261
- hash,
10358
+ contentHash,
10262
10359
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10263
10360
  };
10264
10361
  state2.plugins = [...state2.plugins.filter((p) => p.name !== manifest.name), next];
10265
10362
  saveState(configDir, state2);
10266
- return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash, enabled: next.enabled, trusted: false, valid: true };
10363
+ return { name: manifest.name, dir: targetDir, manifestPath, manifest, hash: contentHash, enabled: next.enabled, trusted: false, valid: true };
10267
10364
  }
10268
10365
  function setPluginEnabled(configDir, name, enabled) {
10269
10366
  const plugin = getInstalledPlugin(configDir, name);
@@ -10273,10 +10370,10 @@ function setPluginEnabled(configDir, name, enabled) {
10273
10370
  name: plugin.name,
10274
10371
  enabled: false,
10275
10372
  trusted: false,
10276
- hash: plugin.hash,
10373
+ contentHash: plugin.hash,
10277
10374
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10278
10375
  };
10279
- const next = { ...current, enabled, hash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
10376
+ const next = { ...current, enabled, contentHash: plugin.hash, enabledAt: enabled ? (/* @__PURE__ */ new Date()).toISOString() : current.enabledAt };
10280
10377
  state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
10281
10378
  saveState(configDir, state2);
10282
10379
  return next;
@@ -10289,10 +10386,10 @@ function trustPlugin(configDir, name) {
10289
10386
  name: plugin.name,
10290
10387
  enabled: false,
10291
10388
  trusted: false,
10292
- hash: plugin.hash,
10389
+ contentHash: plugin.hash,
10293
10390
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
10294
10391
  };
10295
- const next = { ...current, trusted: true, hash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
10392
+ const next = { ...current, trusted: true, contentHash: plugin.hash, trustedAt: (/* @__PURE__ */ new Date()).toISOString() };
10296
10393
  state2.plugins = [...state2.plugins.filter((p) => p.name !== plugin.name), next];
10297
10394
  saveState(configDir, state2);
10298
10395
  return next;
@@ -10320,15 +10417,15 @@ function listInstalledPlugins(configDir) {
10320
10417
  if (!existsSync18(manifestPath)) continue;
10321
10418
  try {
10322
10419
  const manifest = readPluginManifest(manifestPath);
10323
- const hash = hashPluginManifest(manifestPath);
10420
+ const contentHash = hashPluginContent(dir, manifest);
10324
10421
  const st = state2.plugins.find((p) => p.name === manifest.name);
10325
- const trusted = st?.trusted === true && st.hash === hash;
10422
+ const trusted = st?.trusted === true && effectiveHash(st) === contentHash;
10326
10423
  out.push({
10327
10424
  name: manifest.name,
10328
10425
  dir,
10329
10426
  manifestPath,
10330
10427
  manifest,
10331
- hash,
10428
+ hash: contentHash,
10332
10429
  enabled: st?.enabled === true,
10333
10430
  trusted,
10334
10431
  valid: true
@@ -13607,7 +13704,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13607
13704
 
13608
13705
  // src/core/context-files.ts
13609
13706
  import { existsSync as existsSync26, readFileSync as readFileSync19 } from "fs";
13610
- import { join as join19, relative as relative3, resolve as resolve9 } from "path";
13707
+ import { join as join19, relative as relative4, resolve as resolve9 } from "path";
13611
13708
  function uniqueNonEmpty(values) {
13612
13709
  const seen = /* @__PURE__ */ new Set();
13613
13710
  const out = [];
@@ -13623,14 +13720,14 @@ function buildContextFileCandidates(fallbackFilenames = []) {
13623
13720
  return uniqueNonEmpty([...CONTEXT_FILE_CANDIDATES, ...fallbackFilenames]);
13624
13721
  }
13625
13722
  function displayPath(filePath, cwd) {
13626
- const rel = relative3(cwd, filePath);
13723
+ const rel = relative4(cwd, filePath);
13627
13724
  if (rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\")) {
13628
13725
  return rel;
13629
13726
  }
13630
13727
  return filePath;
13631
13728
  }
13632
13729
  function isInsideOrEqual(parent, child) {
13633
- const rel = relative3(resolve9(parent), resolve9(child));
13730
+ const rel = relative4(resolve9(parent), resolve9(child));
13634
13731
  return rel === "" || !!rel && !rel.startsWith("..") && !rel.startsWith("/") && !rel.startsWith("\\");
13635
13732
  }
13636
13733
  function readContextFile(level, filePath, cwd, maxBytes) {
@@ -13763,8 +13860,8 @@ function loadContextFiles(options) {
13763
13860
  }
13764
13861
 
13765
13862
  // 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";
13863
+ import { mkdirSync as mkdirSync15, createWriteStream as createWriteStream2 } from "fs";
13864
+ import { join as join26, dirname as dirname10 } from "path";
13768
13865
 
13769
13866
  // src/repl/commands/project-init.ts
13770
13867
  import { existsSync as existsSync27, readFileSync as readFileSync20, readdirSync as readdirSync11, statSync as statSync9 } from "fs";
@@ -15889,7 +15986,7 @@ async function handleSecurityReview(args, ctx) {
15889
15986
  async function handleTest(args, ctx) {
15890
15987
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
15891
15988
  try {
15892
- const { executeTests } = await import("./run-tests-YSRET52H.js");
15989
+ const { executeTests } = await import("./run-tests-DI6WEYHX.js");
15893
15990
  const argStr = args.join(" ").trim();
15894
15991
  let testArgs = {};
15895
15992
  if (argStr) {
@@ -17217,7 +17314,7 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
17217
17314
  this.send({ type: "response_done", content, usage });
17218
17315
  if (pendingTeeSave && isCleanDocumentBody(content)) {
17219
17316
  try {
17220
- mkdirSync16(dirname11(pendingTeeSave), { recursive: true });
17317
+ mkdirSync15(dirname10(pendingTeeSave), { recursive: true });
17221
17318
  const bodyToSave = stripOuterCodeFence(content);
17222
17319
  atomicWriteFileSync(pendingTeeSave, bodyToSave);
17223
17320
  undoStack.push(pendingTeeSave, `save_last_response (deferred): ${pendingTeeSave}`);
@@ -17393,8 +17490,8 @@ ${summaryContent}`,
17393
17490
  let isError = false;
17394
17491
  let summary;
17395
17492
  try {
17396
- mkdirSync16(dirname11(saveToFile), { recursive: true });
17397
- fileStream = createWriteStream3(saveToFile);
17493
+ mkdirSync15(dirname10(saveToFile), { recursive: true });
17494
+ fileStream = createWriteStream2(saveToFile);
17398
17495
  const teeSystemPrompt = stripToolCallReminder(systemPrompt ?? "") + CONTENT_ONLY_STREAM_REMINDER;
17399
17496
  const teeExtraMessages = extraMessages.length > 0 ? [...extraMessages, { role: "user", content: TEE_FINAL_USER_NUDGE }] : [{ role: "user", content: TEE_FINAL_USER_NUDGE }];
17400
17497
  const chatRequest = {
@@ -17968,8 +18065,8 @@ async function setupProxy(configProxy) {
17968
18065
  }
17969
18066
 
17970
18067
  // 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";
18068
+ import { existsSync as existsSync32, readFileSync as readFileSync24, writeFileSync as writeFileSync5, mkdirSync as mkdirSync16, readdirSync as readdirSync15, copyFileSync } from "fs";
18069
+ import { isAbsolute as isAbsolute3, join as join27, relative as relative5 } from "path";
17973
18070
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
17974
18071
  var USERS_FILE = "users.json";
17975
18072
  var TOKEN_EXPIRY_HOURS = 24;
@@ -18015,7 +18112,7 @@ var AuthManager = class {
18015
18112
  const passwordHash = this.hashPassword(password, salt);
18016
18113
  const dataDir = join27(USERS_DIR, username);
18017
18114
  const fullDataDir = join27(this.baseDir, dataDir);
18018
- mkdirSync17(join27(fullDataDir, "history"), { recursive: true });
18115
+ mkdirSync16(join27(fullDataDir, "history"), { recursive: true });
18019
18116
  const user = {
18020
18117
  username,
18021
18118
  passwordHash,
@@ -18167,25 +18264,25 @@ var AuthManager = class {
18167
18264
  if (err) return err;
18168
18265
  const userDir = this.getUserDataDir(username);
18169
18266
  const globalConfig = join27(this.baseDir, "config.json");
18170
- if (existsSync33(globalConfig)) {
18267
+ if (existsSync32(globalConfig)) {
18171
18268
  try {
18172
- const content = readFileSync25(globalConfig, "utf-8");
18173
- writeFileSync6(join27(userDir, "config.json"), content, "utf-8");
18269
+ const content = readFileSync24(globalConfig, "utf-8");
18270
+ writeFileSync5(join27(userDir, "config.json"), content, "utf-8");
18174
18271
  } catch {
18175
18272
  }
18176
18273
  }
18177
18274
  const globalMemory = join27(this.baseDir, "memory.md");
18178
- if (existsSync33(globalMemory)) {
18275
+ if (existsSync32(globalMemory)) {
18179
18276
  try {
18180
- const content = readFileSync25(globalMemory, "utf-8");
18181
- writeFileSync6(join27(userDir, "memory.md"), content, "utf-8");
18277
+ const content = readFileSync24(globalMemory, "utf-8");
18278
+ writeFileSync5(join27(userDir, "memory.md"), content, "utf-8");
18182
18279
  } catch {
18183
18280
  }
18184
18281
  }
18185
18282
  const globalHistory = join27(this.baseDir, "history");
18186
- if (existsSync33(globalHistory)) {
18283
+ if (existsSync32(globalHistory)) {
18187
18284
  try {
18188
- const files = readdirSync16(globalHistory).filter((f) => f.endsWith(".json"));
18285
+ const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
18189
18286
  const userHistory = join27(userDir, "history");
18190
18287
  for (const f of files) {
18191
18288
  try {
@@ -18200,9 +18297,9 @@ var AuthManager = class {
18200
18297
  }
18201
18298
  // ── Private methods ────────────────────────────────────────────
18202
18299
  loadOrCreate() {
18203
- if (existsSync33(this.usersFile)) {
18300
+ if (existsSync32(this.usersFile)) {
18204
18301
  try {
18205
- const parsed = JSON.parse(readFileSync25(this.usersFile, "utf-8"));
18302
+ const parsed = JSON.parse(readFileSync24(this.usersFile, "utf-8"));
18206
18303
  if (!this.isValidUsersDB(parsed)) {
18207
18304
  throw new Error("database structure is invalid");
18208
18305
  }
@@ -18236,7 +18333,7 @@ var AuthManager = class {
18236
18333
  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
18334
  return false;
18238
18335
  }
18239
- const dataDirFromBase = relative4(this.baseDir, join27(this.baseDir, record.dataDir));
18336
+ const dataDirFromBase = relative5(this.baseDir, join27(this.baseDir, record.dataDir));
18240
18337
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
18241
18338
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
18242
18339
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -18248,7 +18345,7 @@ var AuthManager = class {
18248
18345
  this.saveDB(this.db);
18249
18346
  }
18250
18347
  saveDB(db) {
18251
- mkdirSync17(this.baseDir, { recursive: true });
18348
+ mkdirSync16(this.baseDir, { recursive: true });
18252
18349
  atomicWriteFileSync(this.usersFile, JSON.stringify(db, null, 2));
18253
18350
  }
18254
18351
  /** Legacy hash — kept only for migrating old users (v0.2.x) */
@@ -18280,7 +18377,7 @@ function getModuleDir() {
18280
18377
  if (typeof import.meta?.url === "string") {
18281
18378
  const url = new URL(import.meta.url);
18282
18379
  const filePath = url.pathname.replace(/^\/([A-Z]:)/i, "$1");
18283
- return dirname12(filePath);
18380
+ return dirname11(filePath);
18284
18381
  }
18285
18382
  } catch {
18286
18383
  }
@@ -18353,7 +18450,7 @@ async function startWebServer(options = {}) {
18353
18450
  }
18354
18451
  let skillManager = null;
18355
18452
  const skillsDir = join28(config.getConfigDir(), SKILLS_DIR_NAME);
18356
- if (existsSync34(skillsDir)) {
18453
+ if (existsSync33(skillsDir)) {
18357
18454
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
18358
18455
  skillManager.loadSkills(pluginAssets.skillDirs);
18359
18456
  const count = skillManager.listSkills().length;
@@ -18425,13 +18522,13 @@ async function startWebServer(options = {}) {
18425
18522
  };
18426
18523
  const moduleDir = getModuleDir();
18427
18524
  let clientDir = join28(moduleDir, "web", "client");
18428
- if (!existsSync34(clientDir)) {
18525
+ if (!existsSync33(clientDir)) {
18429
18526
  clientDir = join28(moduleDir, "client");
18430
18527
  }
18431
- if (!existsSync34(clientDir)) {
18528
+ if (!existsSync33(clientDir)) {
18432
18529
  clientDir = join28(moduleDir, "..", "..", "src", "web", "client");
18433
18530
  }
18434
- if (!existsSync34(clientDir)) {
18531
+ if (!existsSync33(clientDir)) {
18435
18532
  clientDir = join28(process.cwd(), "src", "web", "client");
18436
18533
  }
18437
18534
  console.log(` Static files: ${clientDir}`);
@@ -18504,9 +18601,9 @@ async function startWebServer(options = {}) {
18504
18601
  const prefix = req.query.prefix || "";
18505
18602
  const targetDir = join28(cwd, prefix);
18506
18603
  try {
18507
- const canonicalTarget = realpathSync2(resolve13(targetDir));
18508
- const canonicalCwd = realpathSync2(resolve13(cwd));
18509
- if (!canonicalTarget.startsWith(canonicalCwd + sep3) && canonicalTarget !== canonicalCwd) {
18604
+ const canonicalTarget = realpathSync3(resolve13(targetDir));
18605
+ const canonicalCwd = realpathSync3(resolve13(cwd));
18606
+ if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
18510
18607
  res.json({ files: [] });
18511
18608
  return;
18512
18609
  }
@@ -18516,10 +18613,10 @@ async function startWebServer(options = {}) {
18516
18613
  }
18517
18614
  try {
18518
18615
  const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
18519
- const entries = readdirSync17(targetDir, { withFileTypes: true });
18616
+ const entries = readdirSync16(targetDir, { withFileTypes: true });
18520
18617
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
18521
18618
  name: e.name,
18522
- path: relative5(cwd, join28(targetDir, e.name)).replace(/\\/g, "/"),
18619
+ path: relative6(cwd, join28(targetDir, e.name)).replace(/\\/g, "/"),
18523
18620
  isDir: e.isDirectory()
18524
18621
  }));
18525
18622
  res.json({ files });
@@ -18560,14 +18657,14 @@ async function startWebServer(options = {}) {
18560
18657
  const authUser = req._authUser;
18561
18658
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
18562
18659
  const filePath = join28(histDir, `${id}.json`);
18563
- if (!existsSync34(filePath)) {
18660
+ if (!existsSync33(filePath)) {
18564
18661
  res.status(404).json({ error: "Session not found" });
18565
18662
  return;
18566
18663
  }
18567
18664
  try {
18568
- const canonicalFile = realpathSync2(filePath);
18569
- const canonicalDir = realpathSync2(histDir);
18570
- if (!canonicalFile.startsWith(canonicalDir + sep3)) {
18665
+ const canonicalFile = realpathSync3(filePath);
18666
+ const canonicalDir = realpathSync3(histDir);
18667
+ if (!canonicalFile.startsWith(canonicalDir + sep4)) {
18571
18668
  res.status(404).json({ error: "Session not found" });
18572
18669
  return;
18573
18670
  }
@@ -18575,7 +18672,7 @@ async function startWebServer(options = {}) {
18575
18672
  res.status(404).json({ error: "Session not found" });
18576
18673
  return;
18577
18674
  }
18578
- const data = JSON.parse(readFileSync26(filePath, "utf-8"));
18675
+ const data = JSON.parse(readFileSync25(filePath, "utf-8"));
18579
18676
  res.json({ session: data });
18580
18677
  } catch (err) {
18581
18678
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
@@ -18590,9 +18687,9 @@ async function startWebServer(options = {}) {
18590
18687
  const cwd = process.cwd();
18591
18688
  const fullPath = resolve13(join28(cwd, filePath));
18592
18689
  try {
18593
- const canonicalFull = realpathSync2(fullPath);
18594
- const canonicalCwd = realpathSync2(resolve13(cwd));
18595
- if (!canonicalFull.startsWith(canonicalCwd + sep3) && canonicalFull !== canonicalCwd) {
18690
+ const canonicalFull = realpathSync3(fullPath);
18691
+ const canonicalCwd = realpathSync3(resolve13(cwd));
18692
+ if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
18596
18693
  res.json({ error: "Access denied" });
18597
18694
  return;
18598
18695
  }
@@ -18601,12 +18698,12 @@ async function startWebServer(options = {}) {
18601
18698
  return;
18602
18699
  }
18603
18700
  try {
18604
- const stat = statSync15(fullPath);
18701
+ const stat = statSync14(fullPath);
18605
18702
  if (stat.size > 512 * 1024) {
18606
18703
  res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
18607
18704
  return;
18608
18705
  }
18609
- const content = readFileSync26(fullPath, "utf-8");
18706
+ const content = readFileSync25(fullPath, "utf-8");
18610
18707
  res.json({ content, size: stat.size });
18611
18708
  } catch {
18612
18709
  res.json({ error: "Cannot read file" });
@@ -18862,16 +18959,16 @@ function resolveProjectMcpPath() {
18862
18959
  const gitRoot = getGitRoot(cwd);
18863
18960
  const projectRoot = gitRoot ?? cwd;
18864
18961
  const configPath = join28(projectRoot, MCP_PROJECT_CONFIG_NAME);
18865
- return existsSync34(configPath) ? configPath : null;
18962
+ return existsSync33(configPath) ? configPath : null;
18866
18963
  }
18867
18964
  function loadProjectMcpConfig() {
18868
18965
  const cwd = process.cwd();
18869
18966
  const gitRoot = getGitRoot(cwd);
18870
18967
  const projectRoot = gitRoot ?? cwd;
18871
18968
  const configPath = join28(projectRoot, MCP_PROJECT_CONFIG_NAME);
18872
- if (!existsSync34(configPath)) return null;
18969
+ if (!existsSync33(configPath)) return null;
18873
18970
  try {
18874
- const raw = JSON.parse(readFileSync26(configPath, "utf-8"));
18971
+ const raw = JSON.parse(readFileSync25(configPath, "utf-8"));
18875
18972
  return raw.mcpServers ?? raw;
18876
18973
  } catch {
18877
18974
  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-WS724BUX.js");
158
158
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
159
159
  let interrupted = false;
160
160
  const onSigint = () => {