jinzd-ai-cli 0.4.245 → 0.4.247

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 (46) hide show
  1. package/README.md +8 -3
  2. package/README.zh-CN.md +8 -3
  3. package/dist/{batch-MRP2KUFC.js → batch-UE7XQMQB.js} +2 -2
  4. package/dist/{chat-index-ALUHFJKI.js → chat-index-7MMTGQNA.js} +2 -2
  5. package/dist/{chat-index-ML5FF5L6.js → chat-index-Q6BKWWAM.js} +1 -1
  6. package/dist/{chunk-JM2DX7OY.js → chunk-3IIKIWT2.js} +1 -1
  7. package/dist/{chunk-H3PEWUFY.js → chunk-3IM53IFO.js} +1 -1
  8. package/dist/{chunk-UM2OVVLP.js → chunk-4EZWVX7G.js} +1 -1
  9. package/dist/{chunk-WKXADWWK.js → chunk-4GKWLTU3.js} +4 -4
  10. package/dist/{chunk-KEAUVMKS.js → chunk-6Q2XAWKP.js} +1 -1
  11. package/dist/{chunk-IGPFYNZA.js → chunk-6RPGQ5CG.js} +1 -1
  12. package/dist/{chunk-K3CF65QH.js → chunk-GLSR2NR3.js} +1 -1
  13. package/dist/{chunk-WWHTQHIN.js → chunk-IP7LPVRW.js} +1 -1
  14. package/dist/{chunk-DT77O33T.js → chunk-JQXXPTWL.js} +1 -1
  15. package/dist/{chunk-XYXVTHOB.js → chunk-KPRU6QY3.js} +4 -5
  16. package/dist/{chunk-PJ3ONBWZ.js → chunk-NYNSYLFY.js} +1 -1
  17. package/dist/{chunk-KWQKQVPH.js → chunk-OBULDJSU.js} +1 -1
  18. package/dist/{chunk-A4MLBB4H.js → chunk-Q2OMGJIQ.js} +28 -15
  19. package/dist/{chunk-BNERFXVO.js → chunk-QCG6UU2S.js} +1 -1
  20. package/dist/{chunk-O357YW7E.js → chunk-REBKFMF3.js} +1 -1
  21. package/dist/{chunk-4UIVLJAP.js → chunk-RZV6WSER.js} +1 -1
  22. package/dist/{chunk-QYQI7ZWK.js → chunk-S7ZS7X23.js} +0 -1
  23. package/dist/{chunk-XH4JPEIZ.js → chunk-TBXMRJHS.js} +1 -1
  24. package/dist/{chunk-Y6KDBGY7.js → chunk-VN6OGMSV.js} +1 -1
  25. package/dist/{chunk-M7BQVFMF.js → chunk-VPM5WRJ2.js} +4 -4
  26. package/dist/{chunk-NV63EYFL.js → chunk-ZWEZNKDW.js} +1 -1
  27. package/dist/{ci-Q3LQQT7K.js → ci-EY6USUO7.js} +5 -5
  28. package/dist/{ci-format-L2WPVFFC.js → ci-format-CZNUUWEV.js} +2 -2
  29. package/dist/{constants-DTPJHB6W.js → constants-UDRMWAPN.js} +1 -1
  30. package/dist/{doctor-cli-AEVPW6VY.js → doctor-cli-GY654USP.js} +5 -5
  31. package/dist/electron-server.js +170 -139
  32. package/dist/{hub-PPNKIMPG.js → hub-L2WX4255.js} +2 -2
  33. package/dist/index.js +29 -30
  34. package/dist/{indexer-4WWS3VIL.js → indexer-M2LJGTY2.js} +1 -1
  35. package/dist/{indexer-2AG4G6B5.js → indexer-VZETNE4H.js} +1 -1
  36. package/dist/{persist-WGIJ6RXY.js → persist-A2QSXYFY.js} +3 -3
  37. package/dist/{persistent-memory-YLB2ZSB2.js → persistent-memory-G24RJ5LA.js} +2 -2
  38. package/dist/{persistent-memory-ZIC4UA2W.js → persistent-memory-JCX3P2CF.js} +2 -2
  39. package/dist/{pr-Z3NX3SG5.js → pr-B5P2M6DV.js} +5 -5
  40. package/dist/{run-tests-WW6VCT23.js → run-tests-N2JQGL4C.js} +2 -2
  41. package/dist/{run-tests-42DWRQAR.js → run-tests-QEIR322E.js} +2 -2
  42. package/dist/{server-KX6WKW6V.js → server-4OAE6OEK.js} +8 -8
  43. package/dist/{server-NNDBF3SH.js → server-QDMMCD3O.js} +112 -92
  44. package/dist/{task-orchestrator-DEDL6YAZ.js → task-orchestrator-VZXU2HK3.js} +8 -9
  45. package/dist/{usage-QAMWSX52.js → usage-LH3LNYAS.js} +2 -2
  46. package/package.json +5 -4
@@ -7,13 +7,13 @@ import {
7
7
  searchCandidates,
8
8
  searchChatMemory,
9
9
  updateSessionInIndex
10
- } from "./chunk-NV63EYFL.js";
10
+ } from "./chunk-ZWEZNKDW.js";
11
11
  import {
12
12
  fileCheckpoints
13
13
  } from "./chunk-SKET65WZ.js";
14
14
  import {
15
15
  indexProject
16
- } from "./chunk-BNERFXVO.js";
16
+ } from "./chunk-QCG6UU2S.js";
17
17
  import {
18
18
  addMemoryEntry,
19
19
  clearMemoryEntries,
@@ -34,14 +34,14 @@ import {
34
34
  touchMemoryReferences,
35
35
  updateMemoryApproval,
36
36
  updateMemoryEntry
37
- } from "./chunk-O357YW7E.js";
37
+ } from "./chunk-REBKFMF3.js";
38
38
  import {
39
39
  redactJson,
40
40
  scanString
41
41
  } from "./chunk-YVTASHS5.js";
42
42
  import {
43
43
  runTestsTool
44
- } from "./chunk-WWHTQHIN.js";
44
+ } from "./chunk-IP7LPVRW.js";
45
45
  import {
46
46
  AGENTIC_BEHAVIOR_GUIDELINE,
47
47
  APP_NAME,
@@ -73,7 +73,7 @@ import {
73
73
  SUBAGENT_MAX_ROUNDS_LIMIT,
74
74
  VERSION,
75
75
  buildUserIdentityPrompt
76
- } from "./chunk-UM2OVVLP.js";
76
+ } from "./chunk-4EZWVX7G.js";
77
77
  import {
78
78
  hasSemanticIndex,
79
79
  semanticSearch
@@ -91,8 +91,8 @@ import {
91
91
  import express from "express";
92
92
  import { createServer } from "http";
93
93
  import { WebSocketServer } from "ws";
94
- import { join as join27, dirname as dirname10, resolve as resolve12, relative as relative6, sep as sep4 } from "path";
95
- import { existsSync as existsSync31, readFileSync as readFileSync24, readdirSync as readdirSync16, statSync as statSync14, realpathSync as realpathSync3 } from "fs";
94
+ import { join as join25, dirname as dirname10, resolve as resolve10, relative as relative6, sep as sep4 } from "path";
95
+ import { existsSync as existsSync30, readFileSync as readFileSync23, readdirSync as readdirSync15, statSync as statSync13, realpathSync as realpathSync3 } from "fs";
96
96
  import { networkInterfaces } from "os";
97
97
 
98
98
  // src/config/config-manager.ts
@@ -2982,7 +2982,6 @@ var OpenAICompatibleProvider = class extends BaseProvider {
2982
2982
  const message = firstChoice.message;
2983
2983
  const finishReason = firstChoice.finish_reason;
2984
2984
  const usage = toUsage(response.usage);
2985
- const contentStr = typeof message.content === "string" ? message.content : "";
2986
2985
  const hasToolCalls = !!(message.tool_calls && message.tool_calls.length > 0);
2987
2986
  const reasoningContent = message.reasoning_content;
2988
2987
  if (message.tool_calls && message.tool_calls.length > 0) {
@@ -4996,7 +4995,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
4996
4995
  const markerStart = `AICLI_MARKER_START:${id}`;
4997
4996
  const markerEnd = `AICLI_MARKER_END:${id}`;
4998
4997
  const wrappedCmd = IS_WINDOWS2 ? `${WIN_UTF8_PREAMBLE} echo "${markerStart}"; ${command}; echo "${markerEnd}:0"` : `echo "${markerStart}"; ${command}; echo "${markerEnd}:$?"`;
4999
- return new Promise((resolve13) => {
4998
+ return new Promise((resolve11) => {
5000
4999
  let stdout = "";
5001
5000
  let stderr = "";
5002
5001
  let timedOut = false;
@@ -5008,11 +5007,11 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5008
5007
  stdout += IS_WINDOWS2 ? decodeWindowsBuffer(chunk) : chunk.toString("utf-8");
5009
5008
  if (!resolved && stdout.includes(markerEndPattern)) {
5010
5009
  const endLine = stdout.split("\n").find((l) => l.includes(markerEndPattern));
5011
- const exitCode = endLine ? parseEndMarker(endLine, markerEndPattern) : null;
5010
+ const exitCode = endLine ? parseEndMarker(endLine) : null;
5012
5011
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5013
5012
  resolved = true;
5014
5013
  cleanup();
5015
- resolve13({ stdout, stderr, exitCode, timedOut, aborted });
5014
+ resolve11({ stdout, stderr, exitCode, timedOut, aborted });
5016
5015
  }
5017
5016
  };
5018
5017
  const onErr = (chunk) => {
@@ -5027,7 +5026,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5027
5026
  resolved = true;
5028
5027
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5029
5028
  cleanup();
5030
- resolve13({ stdout, stderr, exitCode: null, timedOut, aborted });
5029
+ resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
5031
5030
  killProcessTree(proc);
5032
5031
  pool.delete(sessionKey);
5033
5032
  }, timeout);
@@ -5037,7 +5036,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5037
5036
  resolved = true;
5038
5037
  cleanup();
5039
5038
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5040
- resolve13({ stdout, stderr, exitCode: null, timedOut, aborted });
5039
+ resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
5041
5040
  killProcessTree(proc);
5042
5041
  pool.delete(sessionKey);
5043
5042
  };
@@ -5052,7 +5051,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5052
5051
  stderr += `
5053
5052
  [pool error] ${err.message}`;
5054
5053
  cleanup();
5055
- resolve13({ stdout, stderr, exitCode: null, timedOut, aborted });
5054
+ resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
5056
5055
  pool.delete(sessionKey);
5057
5056
  };
5058
5057
  proc.on("error", onError);
@@ -5065,7 +5064,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5065
5064
  }
5066
5065
  try {
5067
5066
  proc.stdin?.write(wrappedCmd + "\n");
5068
- } catch (err) {
5067
+ } catch {
5069
5068
  if (!resolved) {
5070
5069
  cleanup();
5071
5070
  pool.delete(sessionKey);
@@ -5073,7 +5072,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5073
5072
  }
5074
5073
  });
5075
5074
  }
5076
- function parseEndMarker(line, markerEndPattern) {
5075
+ function parseEndMarker(line) {
5077
5076
  const idx = line.lastIndexOf(":");
5078
5077
  if (idx < 0) return null;
5079
5078
  const code = line.slice(idx + 1).trim();
@@ -5243,7 +5242,7 @@ Important rules:
5243
5242
  }
5244
5243
  if (timedOut) {
5245
5244
  pushBashUndoEntries(beforeSnapshot, parsedTargetsBefore, effectiveCwd);
5246
- throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
5245
+ throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT, command));
5247
5246
  }
5248
5247
  if (status !== 0 || timedOut) {
5249
5248
  const poolStdout = (stdout ?? "").trim();
@@ -5306,7 +5305,7 @@ ${combined || formatFailureFallback(status)}
5306
5305
  const execErr = err;
5307
5306
  const isTimeout = execErr.code === "ETIMEDOUT" || execErr.status == null && execErr.signal === "SIGTERM" || /ETIMEDOUT/i.test(execErr.message ?? "");
5308
5307
  if (isTimeout) {
5309
- throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT));
5308
+ throw new ToolError("bash", formatTimeoutMessage(timeout, MAX_TIMEOUT, command));
5310
5309
  }
5311
5310
  if ("status" in execErr && execErr.status !== void 0) {
5312
5311
  const stderr = IS_WINDOWS3 && Buffer.isBuffer(execErr.stderr) ? decodeWindowsBuffer(execErr.stderr).trim() : execErr.stderr?.toString().trim() ?? "";
@@ -5331,11 +5330,24 @@ ${combined || execErr.message || formatFailureFallback(execErr.status)}
5331
5330
  function formatFailureHeader(status) {
5332
5331
  return typeof status === "number" ? `Exit code ${status}:` : "Command failed before exit code could be determined:";
5333
5332
  }
5334
- function formatTimeoutMessage(timeout, maxTimeout) {
5333
+ function looksLikeTestCommand(command) {
5334
+ return (
5335
+ // jest / vitest / mocha / pytest(可带 npx/yarn/pnpm 前缀,或跟在 cd xxx; 之后)
5336
+ /(?:^|[;&|(\s])(?:npx\s+|yarn\s+(?:run\s+)?|pnpm\s+(?:run\s+|exec\s+)?)?(?:jest|vitest|mocha|pytest)\b/.test(command) || // npm test / npm run test:xxx / yarn test / pnpm test
5337
+ /(?:^|[;&|(\s])(?:npm|yarn|pnpm)\s+(?:run\s+)?test\b/.test(command) || // go test / cargo test
5338
+ /(?:^|[;&|(\s])(?:go|cargo)\s+test\b/.test(command)
5339
+ );
5340
+ }
5341
+ function formatTimeoutMessage(timeout, maxTimeout, command) {
5335
5342
  const seconds = Math.round(timeout / 1e3);
5343
+ const testRunnerHint = command !== void 0 && looksLikeTestCommand(command) ? [
5344
+ "This looks like a TEST run. Prefer the 'run_tests' tool instead of running the test runner through bash: it has a 5-minute timeout, auto-detects the framework, and returns a structured summary (no findstr/grep filtering needed).",
5345
+ ""
5346
+ ] : [];
5336
5347
  return [
5337
5348
  `Command timed out after ${seconds}s.`,
5338
5349
  "",
5350
+ ...testRunnerHint,
5339
5351
  "The previous command ran for longer than the timeout limit and was killed. This usually means it is scanning a large filesystem tree (recursive Get-ChildItem / find), compressing a big archive, or waiting on a network request.",
5340
5352
  "",
5341
5353
  "How to recover (pick ONE \u2014 do NOT retry the same command):",
@@ -7197,7 +7209,7 @@ var ToolExecutor = class {
7197
7209
  };
7198
7210
  }
7199
7211
  if (permission.action === "auto-approve" && networkPermission?.action !== "confirm") {
7200
- this.printToolCall(call);
7212
+ if (!toolCallAlreadyPrinted) this.printToolCall(call);
7201
7213
  try {
7202
7214
  const rawContent = await runTool(tool, call.arguments, call.name);
7203
7215
  const content = truncateOutput(rawContent, call.name);
@@ -7428,7 +7440,7 @@ var ToolExecutor = class {
7428
7440
  rl.resume();
7429
7441
  process.stdout.write(prompt);
7430
7442
  this.confirming = true;
7431
- return new Promise((resolve13) => {
7443
+ return new Promise((resolve11) => {
7432
7444
  let completed = false;
7433
7445
  const cleanup = (result) => {
7434
7446
  if (completed) return;
@@ -7438,7 +7450,7 @@ var ToolExecutor = class {
7438
7450
  rl.pause();
7439
7451
  rlAny.output = savedOutput;
7440
7452
  this.confirming = false;
7441
- resolve13(result);
7453
+ resolve11(result);
7442
7454
  };
7443
7455
  const onLine = (line) => {
7444
7456
  const trimmed = line.trim();
@@ -7612,7 +7624,7 @@ var ToolExecutor = class {
7612
7624
  rl.resume();
7613
7625
  process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
7614
7626
  this.confirming = true;
7615
- return new Promise((resolve13) => {
7627
+ return new Promise((resolve11) => {
7616
7628
  let completed = false;
7617
7629
  const cleanup = (answer) => {
7618
7630
  if (completed) return;
@@ -7622,7 +7634,7 @@ var ToolExecutor = class {
7622
7634
  rl.pause();
7623
7635
  rlAny.output = savedOutput;
7624
7636
  this.confirming = false;
7625
- resolve13(answer === "y");
7637
+ resolve11(answer === "y");
7626
7638
  };
7627
7639
  const onLine = (line) => {
7628
7640
  const trimmed = line.trim();
@@ -7803,7 +7815,7 @@ Do NOT split a long document into many write_file(append=true) calls. That patte
7803
7815
  const mode = appendMode ? "appended" : "written";
7804
7816
  void (async () => {
7805
7817
  try {
7806
- const { updateFile } = await import("./indexer-4WWS3VIL.js");
7818
+ const { updateFile } = await import("./indexer-M2LJGTY2.js");
7807
7819
  await updateFile(process.cwd(), filePath);
7808
7820
  } catch {
7809
7821
  }
@@ -8871,7 +8883,7 @@ var runInteractiveTool = {
8871
8883
  PYTHONDONTWRITEBYTECODE: "1"
8872
8884
  };
8873
8885
  const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
8874
- return new Promise((resolve13) => {
8886
+ return new Promise((resolve11) => {
8875
8887
  const child = spawn4(executable, cmdArgs.map(String), {
8876
8888
  cwd: process.cwd(),
8877
8889
  env,
@@ -8904,22 +8916,22 @@ var runInteractiveTool = {
8904
8916
  setTimeout(writeNextLine, 400);
8905
8917
  const timer = setTimeout(() => {
8906
8918
  child.kill();
8907
- resolve13(`${prefixWarnings}[Timeout after ${timeout}ms]
8919
+ resolve11(`${prefixWarnings}[Timeout after ${timeout}ms]
8908
8920
  ${buildOutput(stdout, stderr)}`);
8909
8921
  }, timeout);
8910
8922
  child.on("close", (code) => {
8911
8923
  clearTimeout(timer);
8912
8924
  const output = buildOutput(stdout, stderr);
8913
8925
  if (code !== 0 && code !== null) {
8914
- resolve13(`${prefixWarnings}Exit code ${code}:
8926
+ resolve11(`${prefixWarnings}Exit code ${code}:
8915
8927
  ${output}`);
8916
8928
  } else {
8917
- resolve13(`${prefixWarnings}${output || "(no output)"}`);
8929
+ resolve11(`${prefixWarnings}${output || "(no output)"}`);
8918
8930
  }
8919
8931
  });
8920
8932
  child.on("error", (err) => {
8921
8933
  clearTimeout(timer);
8922
- resolve13(
8934
+ resolve11(
8923
8935
  `${prefixWarnings}Failed to start process "${executable}": ${err.message}
8924
8936
  Hint: On Windows, use the full path to the executable, e.g.:
8925
8937
  C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
@@ -9222,7 +9234,7 @@ var webFetchTool = {
9222
9234
  } else {
9223
9235
  const title = extractTitle(rawHtml);
9224
9236
  const desc = extractDescription(rawHtml);
9225
- let body = htmlToText(rawHtml);
9237
+ const body = htmlToText(rawHtml);
9226
9238
  const header = [
9227
9239
  title ? `# ${title}` : "",
9228
9240
  desc ? `> ${desc}` : "",
@@ -9741,7 +9753,7 @@ function promptUser(rl, question) {
9741
9753
  console.log();
9742
9754
  console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
9743
9755
  process.stdout.write(chalk4.cyan("> "));
9744
- return new Promise((resolve13) => {
9756
+ return new Promise((resolve11) => {
9745
9757
  let completed = false;
9746
9758
  const cleanup = (answer) => {
9747
9759
  if (completed) return;
@@ -9751,7 +9763,7 @@ function promptUser(rl, question) {
9751
9763
  rl.pause();
9752
9764
  rlAny.output = savedOutput;
9753
9765
  askUserContext.prompting = false;
9754
- resolve13(answer);
9766
+ resolve11(answer);
9755
9767
  };
9756
9768
  const onLine = (line) => {
9757
9769
  cleanup(line);
@@ -12307,7 +12319,7 @@ var McpClient = class {
12307
12319
  // 内部方法:JSON-RPC 通信
12308
12320
  // ══════════════════════════════════════════════════════════════════
12309
12321
  sendRequest(method, params) {
12310
- return new Promise((resolve13, reject) => {
12322
+ return new Promise((resolve11, reject) => {
12311
12323
  if (!this.process?.stdin?.writable) {
12312
12324
  return reject(new Error(`MCP server [${this.serverId}] stdin not writable`));
12313
12325
  }
@@ -12319,19 +12331,18 @@ var McpClient = class {
12319
12331
  method,
12320
12332
  ...params !== void 0 ? { params } : {}
12321
12333
  };
12322
- let timer;
12323
12334
  const cleanup = () => {
12324
12335
  this.pendingRequests.delete(id);
12325
12336
  clearTimeout(timer);
12326
12337
  };
12327
- timer = setTimeout(() => {
12338
+ const timer = setTimeout(() => {
12328
12339
  cleanup();
12329
12340
  reject(new Error(`MCP request [${method}] timed out (internal)`));
12330
12341
  }, MCP_CALL_TIMEOUT * 2);
12331
12342
  this.pendingRequests.set(id, {
12332
12343
  resolve: (result) => {
12333
12344
  cleanup();
12334
- resolve13(result);
12345
+ resolve11(result);
12335
12346
  },
12336
12347
  reject: (error) => {
12337
12348
  cleanup();
@@ -12408,13 +12419,13 @@ var McpClient = class {
12408
12419
  }
12409
12420
  /** Promise 超时包装 */
12410
12421
  withTimeout(promise, ms, label) {
12411
- return new Promise((resolve13, reject) => {
12422
+ return new Promise((resolve11, reject) => {
12412
12423
  const timer = setTimeout(() => {
12413
12424
  reject(new Error(`MCP [${this.serverId}] ${label} timed out after ${ms}ms`));
12414
12425
  }, ms);
12415
12426
  promise.then((val) => {
12416
12427
  clearTimeout(timer);
12417
- resolve13(val);
12428
+ resolve11(val);
12418
12429
  }).catch((err) => {
12419
12430
  clearTimeout(timer);
12420
12431
  reject(err);
@@ -12918,33 +12929,33 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
12918
12929
  }
12919
12930
  /** Resolve a pending confirm from client response */
12920
12931
  resolveConfirm(requestId, approved) {
12921
- const resolve13 = this.pendingConfirms.get(requestId);
12922
- if (resolve13) {
12932
+ const resolve11 = this.pendingConfirms.get(requestId);
12933
+ if (resolve11) {
12923
12934
  this.clearPendingTimer(requestId);
12924
12935
  this.pendingConfirms.delete(requestId);
12925
12936
  this.confirming = false;
12926
- resolve13(approved);
12937
+ resolve11(approved);
12927
12938
  }
12928
12939
  }
12929
12940
  /** Resolve a pending batch confirm from client response */
12930
12941
  resolveBatchConfirm(requestId, decision) {
12931
- const resolve13 = this.pendingBatchConfirms.get(requestId);
12932
- if (resolve13) {
12942
+ const resolve11 = this.pendingBatchConfirms.get(requestId);
12943
+ if (resolve11) {
12933
12944
  this.clearPendingTimer(requestId);
12934
12945
  this.pendingBatchConfirms.delete(requestId);
12935
12946
  this.confirming = false;
12936
12947
  if (decision === "all" || decision === "none") {
12937
- resolve13(decision);
12948
+ resolve11(decision);
12938
12949
  } else {
12939
- resolve13(new Set(decision));
12950
+ resolve11(new Set(decision));
12940
12951
  }
12941
12952
  }
12942
12953
  }
12943
12954
  /** Cancel all pending confirms (e.g., on disconnect) */
12944
12955
  cancelAll() {
12945
- for (const resolve13 of this.pendingConfirms.values()) resolve13(false);
12956
+ for (const resolve11 of this.pendingConfirms.values()) resolve11(false);
12946
12957
  this.pendingConfirms.clear();
12947
- for (const resolve13 of this.pendingBatchConfirms.values()) resolve13("none");
12958
+ for (const resolve11 of this.pendingBatchConfirms.values()) resolve11("none");
12948
12959
  this.pendingBatchConfirms.clear();
12949
12960
  this.confirming = false;
12950
12961
  }
@@ -13020,8 +13031,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13020
13031
  diff: this.getDiffPreview(call)
13021
13032
  };
13022
13033
  this.send(msg);
13023
- return new Promise((resolve13) => {
13024
- this.pendingConfirms.set(requestId, resolve13);
13034
+ return new Promise((resolve11) => {
13035
+ this.pendingConfirms.set(requestId, resolve11);
13025
13036
  this.pendingTimers.set(requestId, setTimeout(() => {
13026
13037
  if (this.pendingConfirms.has(requestId)) {
13027
13038
  this.resolveConfirm(requestId, false);
@@ -13045,8 +13056,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13045
13056
  files
13046
13057
  };
13047
13058
  this.send(msg);
13048
- return new Promise((resolve13) => {
13049
- this.pendingBatchConfirms.set(requestId, resolve13);
13059
+ return new Promise((resolve11) => {
13060
+ this.pendingBatchConfirms.set(requestId, resolve11);
13050
13061
  this.pendingTimers.set(requestId, setTimeout(() => {
13051
13062
  if (this.pendingBatchConfirms.has(requestId)) {
13052
13063
  this.resolveBatchConfirm(requestId, "none");
@@ -13156,7 +13167,7 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13156
13167
  return { callId: call.id, content: rejectionMsg, isError: true };
13157
13168
  }
13158
13169
  }
13159
- this.sendToolCallStart(call);
13170
+ if (!toolCallStarted) this.sendToolCallStart(call);
13160
13171
  if (this.sessionAutoMode && networkPermission?.action !== "confirm") {
13161
13172
  const classification = defaultActionClassifier.classify(call, dangerLevel, {
13162
13173
  workspaceRoot: this.workspaceRoot,
@@ -13535,7 +13546,7 @@ function autoTrimSessionIfNeeded(session, sizeLimit = SESSION_SIZE_LIMIT) {
13535
13546
  const originalSize = JSON.stringify(session.toJSON()).length;
13536
13547
  if (originalSize <= sizeLimit) return false;
13537
13548
  const snapshotLen = session.messages.length;
13538
- let working = cloneMessages(session.messages.slice(0, snapshotLen));
13549
+ const working = cloneMessages(session.messages.slice(0, snapshotLen));
13539
13550
  let committedSize = originalSize;
13540
13551
  let anyTrim = false;
13541
13552
  let keepRecent = 10;
@@ -15100,7 +15111,7 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
15100
15111
  Cost: ${formatCost(cost)}` : "";
15101
15112
  let memoryLine = "";
15102
15113
  try {
15103
- const { countPendingMemories } = await import("./persistent-memory-YLB2ZSB2.js");
15114
+ const { countPendingMemories } = await import("./persistent-memory-G24RJ5LA.js");
15104
15115
  const pending = countPendingMemories(ctx.config.getConfigDir());
15105
15116
  if (pending > 0) memoryLine = `
15106
15117
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
@@ -15407,7 +15418,7 @@ async function handleBranch(args, ctx) {
15407
15418
  return;
15408
15419
  }
15409
15420
  const sub = args[0]?.toLowerCase();
15410
- const resolve13 = (ref) => {
15421
+ const resolve11 = (ref) => {
15411
15422
  const r = session.resolveBranchRef(ref);
15412
15423
  if (r.ok) return r.id;
15413
15424
  if (r.reason === "ambiguous") {
@@ -15461,7 +15472,7 @@ async function handleBranch(args, ctx) {
15461
15472
  ctx.send({ type: "error", message: "Usage: /branch switch <id|title>" });
15462
15473
  return;
15463
15474
  }
15464
- const id = resolve13(ref);
15475
+ const id = resolve11(ref);
15465
15476
  if (!id) return;
15466
15477
  const ok = session.switchBranch(id);
15467
15478
  if (ok) {
@@ -15481,7 +15492,7 @@ async function handleBranch(args, ctx) {
15481
15492
  ctx.send({ type: "error", message: "Usage: /branch delete <id|title>" });
15482
15493
  return;
15483
15494
  }
15484
- const id = resolve13(ref);
15495
+ const id = resolve11(ref);
15485
15496
  if (!id) return;
15486
15497
  const ok = session.deleteBranch(id);
15487
15498
  if (ok) {
@@ -15500,7 +15511,7 @@ async function handleBranch(args, ctx) {
15500
15511
  ctx.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
15501
15512
  return;
15502
15513
  }
15503
- const id = resolve13(ref);
15514
+ const id = resolve11(ref);
15504
15515
  if (!id) return;
15505
15516
  const ok = session.renameBranch(id, title);
15506
15517
  if (ok) {
@@ -15518,7 +15529,7 @@ async function handleBranch(args, ctx) {
15518
15529
  ctx.send({ type: "error", message: "Usage: /branch diff <id|title>" });
15519
15530
  return;
15520
15531
  }
15521
- const id = resolve13(ref);
15532
+ const id = resolve11(ref);
15522
15533
  if (!id) return;
15523
15534
  const d = session.diffBranches(id);
15524
15535
  if (!d) {
@@ -15560,7 +15571,7 @@ async function handleBranch(args, ctx) {
15560
15571
  ctx.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
15561
15572
  return;
15562
15573
  }
15563
- const id = resolve13(ref);
15574
+ const id = resolve11(ref);
15564
15575
  if (!id) return;
15565
15576
  const idx = parseInt(idxStr, 10);
15566
15577
  if (Number.isNaN(idx)) {
@@ -15909,7 +15920,7 @@ async function handleSecurityReview(args, ctx) {
15909
15920
  async function handleTest(args, ctx) {
15910
15921
  ctx.send({ type: "info", message: "\u{1F9EA} Running tests..." });
15911
15922
  try {
15912
- const { executeTests } = await import("./run-tests-42DWRQAR.js");
15923
+ const { executeTests } = await import("./run-tests-QEIR322E.js");
15913
15924
  const argStr = args.join(" ").trim();
15914
15925
  let testArgs = {};
15915
15926
  if (argStr) {
@@ -16066,7 +16077,7 @@ async function handleIndex(args, ctx) {
16066
16077
  const sub = (args[0] ?? "status").toLowerCase();
16067
16078
  const root = process.cwd();
16068
16079
  const { loadIndex: loadIndex2, clearIndex } = await import("./store-VO37H6LS.js");
16069
- const { indexProject: indexProject2 } = await import("./indexer-4WWS3VIL.js");
16080
+ const { indexProject: indexProject2 } = await import("./indexer-M2LJGTY2.js");
16070
16081
  const { loadVectorStore, clearVectorStore } = await import("./vector-store-JBAE6PS4.js");
16071
16082
  if (sub === "status") {
16072
16083
  const idx = loadIndex2(root);
@@ -16173,7 +16184,7 @@ async function handleMemory(args, ctx) {
16173
16184
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
16174
16185
  } else if (sub === "export") {
16175
16186
  if (args[1] === "md") {
16176
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-YLB2ZSB2.js");
16187
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-G24RJ5LA.js");
16177
16188
  ctx.send({
16178
16189
  type: "export_data",
16179
16190
  format: "md",
@@ -16539,6 +16550,15 @@ ${undoResults.map((r) => ` \u2022 ${r}`).join("\n")}` });
16539
16550
  }
16540
16551
 
16541
16552
  // src/web/session-handler.ts
16553
+ var CLI_ONLY_WEB_COMMANDS = /* @__PURE__ */ new Set([
16554
+ "copy",
16555
+ "paste",
16556
+ "exit",
16557
+ "quit",
16558
+ "snapshot",
16559
+ "hooks",
16560
+ "hook"
16561
+ ]);
16542
16562
  var webCommandHandlers = {
16543
16563
  provider: handleProvider,
16544
16564
  model: handleModel,
@@ -16776,10 +16796,10 @@ var SessionHandler = class {
16776
16796
  return;
16777
16797
  }
16778
16798
  case "ask_user_response": {
16779
- const resolve13 = this.pendingAskUser.get(msg.requestId);
16780
- if (resolve13) {
16799
+ const resolve11 = this.pendingAskUser.get(msg.requestId);
16800
+ if (resolve11) {
16781
16801
  this.pendingAskUser.delete(msg.requestId);
16782
- resolve13(msg.answer);
16802
+ resolve11(msg.answer);
16783
16803
  }
16784
16804
  return;
16785
16805
  }
@@ -16792,10 +16812,10 @@ var SessionHandler = class {
16792
16812
  case "memory_manage":
16793
16813
  return this.handleMemoryManage(msg.action, msg.id, msg.expiresAt);
16794
16814
  case "auto_pause_response": {
16795
- const resolve13 = this.pendingAutoPause.get(msg.requestId);
16796
- if (resolve13) {
16815
+ const resolve11 = this.pendingAutoPause.get(msg.requestId);
16816
+ if (resolve11) {
16797
16817
  this.pendingAutoPause.delete(msg.requestId);
16798
- resolve13({ action: msg.action, message: msg.message });
16818
+ resolve11({ action: msg.action, message: msg.message });
16799
16819
  }
16800
16820
  return;
16801
16821
  }
@@ -16810,10 +16830,10 @@ var SessionHandler = class {
16810
16830
  this.hubOrchestrator?.abort();
16811
16831
  return;
16812
16832
  case "hub_steer": {
16813
- const resolve13 = this.pendingHubReview.get(msg.requestId);
16814
- if (resolve13) {
16833
+ const resolve11 = this.pendingHubReview.get(msg.requestId);
16834
+ if (resolve11) {
16815
16835
  this.pendingHubReview.delete(msg.requestId);
16816
- resolve13({ action: msg.action, message: msg.message });
16836
+ resolve11({ action: msg.action, message: msg.message });
16817
16837
  }
16818
16838
  return;
16819
16839
  }
@@ -16826,9 +16846,9 @@ var SessionHandler = class {
16826
16846
  runLifecycleHooks(mergePluginHooks(this.config.get("hooks") ?? void 0, this.config.getConfigDir()), "Stop", { sessionId: this.sessions.current?.id }, { configDir: this.config.getConfigDir() });
16827
16847
  this.toolExecutor.cancelAll();
16828
16848
  if (this.abortController) this.abortController.abort();
16829
- for (const resolve13 of this.pendingAskUser.values()) resolve13(null);
16849
+ for (const resolve11 of this.pendingAskUser.values()) resolve11(null);
16830
16850
  this.pendingAskUser.clear();
16831
- for (const resolve13 of this.pendingAutoPause.values()) resolve13({ action: "stop" });
16851
+ for (const resolve11 of this.pendingAutoPause.values()) resolve11({ action: "stop" });
16832
16852
  this.pendingAutoPause.clear();
16833
16853
  this.saveIfNeeded();
16834
16854
  if (this._bashSessionKey) clearBashSession(this._bashSessionKey);
@@ -16963,9 +16983,9 @@ var SessionHandler = class {
16963
16983
  this.hubOrchestrator = orchestrator;
16964
16984
  orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
16965
16985
  if (config.humanSteer) {
16966
- orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve13) => {
16986
+ orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve11) => {
16967
16987
  const requestId = `hubrev_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
16968
- this.pendingHubReview.set(requestId, resolve13);
16988
+ this.pendingHubReview.set(requestId, resolve11);
16969
16989
  this.send({ type: "hub_review", requestId, round, maxRounds });
16970
16990
  });
16971
16991
  }
@@ -17323,8 +17343,8 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
17323
17343
  onMcpToolUsed: (name) => this.usedMcpToolNames.add(name),
17324
17344
  requestAutoPause: async ({ effectiveRound, maxToolRounds: totalRounds, toolSummary }) => {
17325
17345
  const requestId = `pause_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
17326
- const pauseResp = await new Promise((resolve13) => {
17327
- this.pendingAutoPause.set(requestId, resolve13);
17346
+ const pauseResp = await new Promise((resolve11) => {
17347
+ this.pendingAutoPause.set(requestId, resolve11);
17328
17348
  this.send({
17329
17349
  type: "auto_pause_request",
17330
17350
  requestId,
@@ -17503,8 +17523,8 @@ ${summaryContent}`,
17503
17523
  }
17504
17524
  if (chunk.done) break;
17505
17525
  }
17506
- await new Promise((resolve13, reject) => {
17507
- fileStream.end((err) => err ? reject(err) : resolve13());
17526
+ await new Promise((resolve11, reject) => {
17527
+ fileStream.end((err) => err ? reject(err) : resolve11());
17508
17528
  });
17509
17529
  const verdict = evaluateTeeContent(fullContent, saveToFile, priorContent);
17510
17530
  if (verdict.kind === "reject") {
@@ -17530,7 +17550,7 @@ ${summaryContent}`,
17530
17550
  } catch (err) {
17531
17551
  if (fileStream) {
17532
17552
  try {
17533
- await new Promise((resolve13) => fileStream.end(() => resolve13()));
17553
+ await new Promise((resolve11) => fileStream.end(() => resolve11()));
17534
17554
  } catch {
17535
17555
  }
17536
17556
  }
@@ -17578,6 +17598,13 @@ ${summaryContent}`,
17578
17598
  }
17579
17599
  // ── Commands ─────────────────────────────────────────────────────
17580
17600
  async handleCommand(name, args) {
17601
+ if (CLI_ONLY_WEB_COMMANDS.has(name)) {
17602
+ this.send({
17603
+ type: "error",
17604
+ message: `/${name} is only available in the terminal REPL. Run \`aicli\` in a terminal and use /${name} there.`
17605
+ });
17606
+ return;
17607
+ }
17581
17608
  const handler = webCommandHandlers[name];
17582
17609
  if (handler) {
17583
17610
  await handler(args, this);
@@ -17853,7 +17880,7 @@ Backup saved: ${result.backupPath}` : "";
17853
17880
  return;
17854
17881
  }
17855
17882
  try {
17856
- const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-ML5FF5L6.js");
17883
+ const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-Q6BKWWAM.js");
17857
17884
  const loaded = loadChatIndex2();
17858
17885
  if (!loaded || loaded.idx.chunks.length === 0) {
17859
17886
  this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
@@ -17889,7 +17916,7 @@ Backup saved: ${result.backupPath}` : "";
17889
17916
  }
17890
17917
  async handleMemoryStatus() {
17891
17918
  try {
17892
- const { getChatIndexStatus } = await import("./chat-index-ML5FF5L6.js");
17919
+ const { getChatIndexStatus } = await import("./chat-index-Q6BKWWAM.js");
17893
17920
  const s = getChatIndexStatus();
17894
17921
  this.send({
17895
17922
  type: "memory_status",
@@ -17914,7 +17941,7 @@ Backup saved: ${result.backupPath}` : "";
17914
17941
  type: "info",
17915
17942
  message: full ? "\u{1F9E0} Rebuilding chat memory index (this may take a while on first run \u2014 ~117 MB embedder)." : "\u{1F9E0} Refreshing chat memory index (incremental)\u2026"
17916
17943
  });
17917
- const { buildChatIndex } = await import("./chat-index-ML5FF5L6.js");
17944
+ const { buildChatIndex } = await import("./chat-index-Q6BKWWAM.js");
17918
17945
  const stats = await buildChatIndex({
17919
17946
  full,
17920
17947
  onProgress: (p) => {
@@ -18070,8 +18097,8 @@ async function setupProxy(configProxy) {
18070
18097
  }
18071
18098
 
18072
18099
  // src/web/auth.ts
18073
- import { existsSync as existsSync30, readFileSync as readFileSync23, writeFileSync as writeFileSync5, mkdirSync as mkdirSync15, readdirSync as readdirSync15, copyFileSync } from "fs";
18074
- import { isAbsolute as isAbsolute3, join as join26, relative as relative5 } from "path";
18100
+ import { existsSync as existsSync29, readFileSync as readFileSync22, writeFileSync as writeFileSync4, mkdirSync as mkdirSync15, readdirSync as readdirSync14, copyFileSync } from "fs";
18101
+ import { isAbsolute as isAbsolute3, join as join24, relative as relative5 } from "path";
18075
18102
  import { createHmac, randomBytes, timingSafeEqual, pbkdf2Sync } from "crypto";
18076
18103
  var USERS_FILE = "users.json";
18077
18104
  var TOKEN_EXPIRY_HOURS = 24;
@@ -18086,7 +18113,7 @@ var AuthManager = class {
18086
18113
  db;
18087
18114
  constructor(baseDir) {
18088
18115
  this.baseDir = baseDir;
18089
- this.usersFile = join26(baseDir, USERS_FILE);
18116
+ this.usersFile = join24(baseDir, USERS_FILE);
18090
18117
  this.db = this.loadOrCreate();
18091
18118
  }
18092
18119
  // ── Public API ─────────────────────────────────────────────────
@@ -18115,9 +18142,9 @@ var AuthManager = class {
18115
18142
  }
18116
18143
  const salt = randomBytes(16).toString("hex");
18117
18144
  const passwordHash = this.hashPassword(password, salt);
18118
- const dataDir = join26(USERS_DIR, username);
18119
- const fullDataDir = join26(this.baseDir, dataDir);
18120
- mkdirSync15(join26(fullDataDir, "history"), { recursive: true });
18145
+ const dataDir = join24(USERS_DIR, username);
18146
+ const fullDataDir = join24(this.baseDir, dataDir);
18147
+ mkdirSync15(join24(fullDataDir, "history"), { recursive: true });
18121
18148
  const user = {
18122
18149
  username,
18123
18150
  passwordHash,
@@ -18232,7 +18259,7 @@ var AuthManager = class {
18232
18259
  getUserDataDir(username) {
18233
18260
  const user = this.db.users.find((u) => u.username === username);
18234
18261
  if (!user) throw new Error(`User not found: ${username}`);
18235
- return join26(this.baseDir, user.dataDir);
18262
+ return join24(this.baseDir, user.dataDir);
18236
18263
  }
18237
18264
  /** List all usernames */
18238
18265
  listUsers() {
@@ -18268,30 +18295,30 @@ var AuthManager = class {
18268
18295
  const err = this.register(username, password);
18269
18296
  if (err) return err;
18270
18297
  const userDir = this.getUserDataDir(username);
18271
- const globalConfig = join26(this.baseDir, "config.json");
18272
- if (existsSync30(globalConfig)) {
18298
+ const globalConfig = join24(this.baseDir, "config.json");
18299
+ if (existsSync29(globalConfig)) {
18273
18300
  try {
18274
- const content = readFileSync23(globalConfig, "utf-8");
18275
- writeFileSync5(join26(userDir, "config.json"), content, "utf-8");
18301
+ const content = readFileSync22(globalConfig, "utf-8");
18302
+ writeFileSync4(join24(userDir, "config.json"), content, "utf-8");
18276
18303
  } catch {
18277
18304
  }
18278
18305
  }
18279
- const globalMemory = join26(this.baseDir, "memory.md");
18280
- if (existsSync30(globalMemory)) {
18306
+ const globalMemory = join24(this.baseDir, "memory.md");
18307
+ if (existsSync29(globalMemory)) {
18281
18308
  try {
18282
- const content = readFileSync23(globalMemory, "utf-8");
18283
- writeFileSync5(join26(userDir, "memory.md"), content, "utf-8");
18309
+ const content = readFileSync22(globalMemory, "utf-8");
18310
+ writeFileSync4(join24(userDir, "memory.md"), content, "utf-8");
18284
18311
  } catch {
18285
18312
  }
18286
18313
  }
18287
- const globalHistory = join26(this.baseDir, "history");
18288
- if (existsSync30(globalHistory)) {
18314
+ const globalHistory = join24(this.baseDir, "history");
18315
+ if (existsSync29(globalHistory)) {
18289
18316
  try {
18290
- const files = readdirSync15(globalHistory).filter((f) => f.endsWith(".json"));
18291
- const userHistory = join26(userDir, "history");
18317
+ const files = readdirSync14(globalHistory).filter((f) => f.endsWith(".json"));
18318
+ const userHistory = join24(userDir, "history");
18292
18319
  for (const f of files) {
18293
18320
  try {
18294
- copyFileSync(join26(globalHistory, f), join26(userHistory, f));
18321
+ copyFileSync(join24(globalHistory, f), join24(userHistory, f));
18295
18322
  } catch {
18296
18323
  }
18297
18324
  }
@@ -18302,9 +18329,9 @@ var AuthManager = class {
18302
18329
  }
18303
18330
  // ── Private methods ────────────────────────────────────────────
18304
18331
  loadOrCreate() {
18305
- if (existsSync30(this.usersFile)) {
18332
+ if (existsSync29(this.usersFile)) {
18306
18333
  try {
18307
- const parsed = JSON.parse(readFileSync23(this.usersFile, "utf-8"));
18334
+ const parsed = JSON.parse(readFileSync22(this.usersFile, "utf-8"));
18308
18335
  if (!this.isValidUsersDB(parsed)) {
18309
18336
  throw new Error("database structure is invalid");
18310
18337
  }
@@ -18338,7 +18365,7 @@ var AuthManager = class {
18338
18365
  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)) {
18339
18366
  return false;
18340
18367
  }
18341
- const dataDirFromBase = relative5(this.baseDir, join26(this.baseDir, record.dataDir));
18368
+ const dataDirFromBase = relative5(this.baseDir, join24(this.baseDir, record.dataDir));
18342
18369
  if (dataDirFromBase.startsWith("..") || isAbsolute3(dataDirFromBase)) return false;
18343
18370
  if (record.hashVersion !== void 0 && record.hashVersion !== 1 && record.hashVersion !== 2) return false;
18344
18371
  if (record.tokensRevokedBefore !== void 0 && !Number.isFinite(record.tokensRevokedBefore)) return false;
@@ -18386,7 +18413,7 @@ function getModuleDir() {
18386
18413
  }
18387
18414
  } catch {
18388
18415
  }
18389
- return resolve12(".");
18416
+ return resolve10(".");
18390
18417
  }
18391
18418
  async function startWebServer(options = {}) {
18392
18419
  const port = options.port ?? 3e3;
@@ -18454,8 +18481,8 @@ async function startWebServer(options = {}) {
18454
18481
  }
18455
18482
  }
18456
18483
  let skillManager = null;
18457
- const skillsDir = join27(config.getConfigDir(), SKILLS_DIR_NAME);
18458
- if (existsSync31(skillsDir)) {
18484
+ const skillsDir = join25(config.getConfigDir(), SKILLS_DIR_NAME);
18485
+ if (existsSync30(skillsDir)) {
18459
18486
  skillManager = new SkillManager(skillsDir, config.get("ui").skillSizeWarn);
18460
18487
  skillManager.loadSkills(pluginAssets.skillDirs);
18461
18488
  const count = skillManager.listSkills().length;
@@ -18506,6 +18533,10 @@ async function startWebServer(options = {}) {
18506
18533
  console.log(` Auth: ${authManager.listUsers().length} user(s) registered`);
18507
18534
  } else {
18508
18535
  console.log(` Auth: disabled (no users registered)`);
18536
+ if (host === "0.0.0.0" || host === "::") {
18537
+ console.log(" WARNING: Web UI is reachable from the network without authentication.");
18538
+ console.log(" Create a user first for LAN/team use: aicli user create <name>");
18539
+ }
18509
18540
  }
18510
18541
  const requireAuth = (req, res, next) => {
18511
18542
  if (!authManager.isEnabled()) return next();
@@ -18526,18 +18557,18 @@ async function startWebServer(options = {}) {
18526
18557
  next();
18527
18558
  };
18528
18559
  const moduleDir = getModuleDir();
18529
- let clientDir = join27(moduleDir, "web", "client");
18530
- if (!existsSync31(clientDir)) {
18531
- clientDir = join27(moduleDir, "client");
18560
+ let clientDir = join25(moduleDir, "web", "client");
18561
+ if (!existsSync30(clientDir)) {
18562
+ clientDir = join25(moduleDir, "client");
18532
18563
  }
18533
- if (!existsSync31(clientDir)) {
18534
- clientDir = join27(moduleDir, "..", "..", "src", "web", "client");
18564
+ if (!existsSync30(clientDir)) {
18565
+ clientDir = join25(moduleDir, "..", "..", "src", "web", "client");
18535
18566
  }
18536
- if (!existsSync31(clientDir)) {
18537
- clientDir = join27(process.cwd(), "src", "web", "client");
18567
+ if (!existsSync30(clientDir)) {
18568
+ clientDir = join25(process.cwd(), "src", "web", "client");
18538
18569
  }
18539
18570
  console.log(` Static files: ${clientDir}`);
18540
- app.use("/vendor", express.static(join27(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18571
+ app.use("/vendor", express.static(join25(clientDir, "vendor"), { maxAge: "1y", immutable: true }));
18541
18572
  app.use(express.static(clientDir));
18542
18573
  app.get("/api/status", (_req, res) => {
18543
18574
  res.json({
@@ -18604,10 +18635,10 @@ async function startWebServer(options = {}) {
18604
18635
  app.get("/api/files", requireAuth, (req, res) => {
18605
18636
  const cwd = process.cwd();
18606
18637
  const prefix = req.query.prefix || "";
18607
- const targetDir = join27(cwd, prefix);
18638
+ const targetDir = join25(cwd, prefix);
18608
18639
  try {
18609
- const canonicalTarget = realpathSync3(resolve12(targetDir));
18610
- const canonicalCwd = realpathSync3(resolve12(cwd));
18640
+ const canonicalTarget = realpathSync3(resolve10(targetDir));
18641
+ const canonicalCwd = realpathSync3(resolve10(cwd));
18611
18642
  if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
18612
18643
  res.json({ files: [] });
18613
18644
  return;
@@ -18618,10 +18649,10 @@ async function startWebServer(options = {}) {
18618
18649
  }
18619
18650
  try {
18620
18651
  const SKIP = /* @__PURE__ */ new Set(["node_modules", ".git", "dist", "dist-cjs", "release", "__pycache__", ".next", ".nuxt", "coverage", ".cache"]);
18621
- const entries = readdirSync16(targetDir, { withFileTypes: true });
18652
+ const entries = readdirSync15(targetDir, { withFileTypes: true });
18622
18653
  const files = entries.filter((e) => !SKIP.has(e.name) && !e.name.startsWith(".")).slice(0, 50).map((e) => ({
18623
18654
  name: e.name,
18624
- path: relative6(cwd, join27(targetDir, e.name)).replace(/\\/g, "/"),
18655
+ path: relative6(cwd, join25(targetDir, e.name)).replace(/\\/g, "/"),
18625
18656
  isDir: e.isDirectory()
18626
18657
  }));
18627
18658
  res.json({ files });
@@ -18661,8 +18692,8 @@ async function startWebServer(options = {}) {
18661
18692
  try {
18662
18693
  const authUser = req._authUser;
18663
18694
  const histDir = authUser ? getUserShared(authUser).config.getHistoryDir() : config.getHistoryDir();
18664
- const filePath = join27(histDir, `${id}.json`);
18665
- if (!existsSync31(filePath)) {
18695
+ const filePath = join25(histDir, `${id}.json`);
18696
+ if (!existsSync30(filePath)) {
18666
18697
  res.status(404).json({ error: "Session not found" });
18667
18698
  return;
18668
18699
  }
@@ -18677,7 +18708,7 @@ async function startWebServer(options = {}) {
18677
18708
  res.status(404).json({ error: "Session not found" });
18678
18709
  return;
18679
18710
  }
18680
- const data = JSON.parse(readFileSync24(filePath, "utf-8"));
18711
+ const data = JSON.parse(readFileSync23(filePath, "utf-8"));
18681
18712
  res.json({ session: data });
18682
18713
  } catch (err) {
18683
18714
  res.status(500).json({ error: err instanceof Error ? err.message : String(err) });
@@ -18690,10 +18721,10 @@ async function startWebServer(options = {}) {
18690
18721
  return;
18691
18722
  }
18692
18723
  const cwd = process.cwd();
18693
- const fullPath = resolve12(join27(cwd, filePath));
18724
+ const fullPath = resolve10(join25(cwd, filePath));
18694
18725
  try {
18695
18726
  const canonicalFull = realpathSync3(fullPath);
18696
- const canonicalCwd = realpathSync3(resolve12(cwd));
18727
+ const canonicalCwd = realpathSync3(resolve10(cwd));
18697
18728
  if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
18698
18729
  res.json({ error: "Access denied" });
18699
18730
  return;
@@ -18703,12 +18734,12 @@ async function startWebServer(options = {}) {
18703
18734
  return;
18704
18735
  }
18705
18736
  try {
18706
- const stat = statSync14(fullPath);
18737
+ const stat = statSync13(fullPath);
18707
18738
  if (stat.size > 512 * 1024) {
18708
18739
  res.json({ error: `File too large (${(stat.size / 1024).toFixed(0)} KB, max 512 KB)` });
18709
18740
  return;
18710
18741
  }
18711
- const content = readFileSync24(fullPath, "utf-8");
18742
+ const content = readFileSync23(fullPath, "utf-8");
18712
18743
  res.json({ content, size: stat.size });
18713
18744
  } catch {
18714
18745
  res.json({ error: "Cannot read file" });
@@ -18837,7 +18868,7 @@ async function startWebServer(options = {}) {
18837
18868
  ws.send(JSON.stringify({ type: "auth_result", success: false, error: err }));
18838
18869
  return;
18839
18870
  }
18840
- const newToken = authManager.login(username, password);
18871
+ authManager.login(username, password);
18841
18872
  authenticatedUser = username;
18842
18873
  const userShared = getUserShared(username);
18843
18874
  handler = new SessionHandler(ws, userShared);
@@ -18912,7 +18943,7 @@ async function startWebServer(options = {}) {
18912
18943
  });
18913
18944
  const MAX_PORT_ATTEMPTS = 10;
18914
18945
  let actualPort = port;
18915
- const result = await new Promise((resolve13, reject) => {
18946
+ const result = await new Promise((resolve11, reject) => {
18916
18947
  const tryListen = (attempt) => {
18917
18948
  server.once("error", (err) => {
18918
18949
  if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
@@ -18943,7 +18974,7 @@ async function startWebServer(options = {}) {
18943
18974
  }
18944
18975
  console.log(` Press Ctrl+C to stop
18945
18976
  `);
18946
- resolve13({ port: actualPort, host, url });
18977
+ resolve11({ port: actualPort, host, url });
18947
18978
  });
18948
18979
  };
18949
18980
  tryListen(1);
@@ -18963,17 +18994,17 @@ function resolveProjectMcpPath() {
18963
18994
  const cwd = process.cwd();
18964
18995
  const gitRoot = getGitRoot(cwd);
18965
18996
  const projectRoot = gitRoot ?? cwd;
18966
- const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18967
- return existsSync31(configPath) ? configPath : null;
18997
+ const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
18998
+ return existsSync30(configPath) ? configPath : null;
18968
18999
  }
18969
19000
  function loadProjectMcpConfig() {
18970
19001
  const cwd = process.cwd();
18971
19002
  const gitRoot = getGitRoot(cwd);
18972
19003
  const projectRoot = gitRoot ?? cwd;
18973
- const configPath = join27(projectRoot, MCP_PROJECT_CONFIG_NAME);
18974
- if (!existsSync31(configPath)) return null;
19004
+ const configPath = join25(projectRoot, MCP_PROJECT_CONFIG_NAME);
19005
+ if (!existsSync30(configPath)) return null;
18975
19006
  try {
18976
- const raw = JSON.parse(readFileSync24(configPath, "utf-8"));
19007
+ const raw = JSON.parse(readFileSync23(configPath, "utf-8"));
18977
19008
  return raw.mcpServers ?? raw;
18978
19009
  } catch {
18979
19010
  return null;