jinzd-ai-cli 0.4.271 → 0.4.273

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 (40) hide show
  1. package/dist/{batch-FPDT2USZ.js → batch-LOW3GM26.js} +2 -2
  2. package/dist/{chat-index-7MMTGQNA.js → chat-index-2D5GK2DB.js} +2 -2
  3. package/dist/{chat-index-Q6BKWWAM.js → chat-index-TDU3S2MG.js} +2 -2
  4. package/dist/{chunk-B5TYJO7V.js → chunk-3FEZSLGI.js} +51 -6
  5. package/dist/{chunk-BFPF3JF2.js → chunk-4FIDMC2K.js} +3 -3
  6. package/dist/{chunk-OBULDJSU.js → chunk-CGDYO52A.js} +1 -1
  7. package/dist/{chunk-FT3WS5PG.js → chunk-EDAUDILT.js} +1 -1
  8. package/dist/{chunk-PDRAOFGI.js → chunk-FHXLAJJG.js} +1 -1
  9. package/dist/{chunk-RNDHIERN.js → chunk-FN7DE4HA.js} +3 -3
  10. package/dist/{chunk-RLAUMACS.js → chunk-FNLWPYP5.js} +1 -1
  11. package/dist/{chunk-YVTASHS5.js → chunk-FSC6KEWU.js} +51 -6
  12. package/dist/{chunk-6RPGQ5CG.js → chunk-GHWZVPUV.js} +1 -1
  13. package/dist/{chunk-5JFRM47R.js → chunk-LEK5WGKV.js} +1 -1
  14. package/dist/{chunk-VPXNLE7E.js → chunk-M3NXF4GD.js} +2 -2
  15. package/dist/{chunk-PG7O7N7D.js → chunk-MTQBSOZW.js} +3 -3
  16. package/dist/{chunk-JQXXPTWL.js → chunk-MX75TNE5.js} +1 -1
  17. package/dist/{chunk-V26ZMB3D.js → chunk-R4YGDJPL.js} +5 -5
  18. package/dist/{chunk-PMRU2CAF.js → chunk-T65VFCID.js} +1 -1
  19. package/dist/{chunk-OSYK6D4G.js → chunk-WSCZRQDR.js} +1 -1
  20. package/dist/{chunk-ZWEZNKDW.js → chunk-YOVHMQEJ.js} +1 -1
  21. package/dist/{chunk-4UNRDXZV.js → chunk-Z3UXZ5EI.js} +2 -2
  22. package/dist/{chunk-2RN4T4XD.js → chunk-ZWCQQZT5.js} +1 -1
  23. package/dist/{ci-VPN5RWCO.js → ci-C5YMQXCS.js} +4 -4
  24. package/dist/{ci-format-GKXVCVME.js → ci-format-R6EMNOGZ.js} +2 -2
  25. package/dist/{constants-Y43DJFGV.js → constants-QJCNMBPJ.js} +1 -1
  26. package/dist/{doctor-cli-RZGZB2TF.js → doctor-cli-5CM2I6OF.js} +4 -4
  27. package/dist/electron-server.js +162 -80
  28. package/dist/{hub-FJWP6SDG.js → hub-7JBSZOSD.js} +2 -2
  29. package/dist/index.js +23 -23
  30. package/dist/{persist-A2QSXYFY.js → persist-PQM4BRI4.js} +3 -3
  31. package/dist/{persistent-memory-IR47JCTF.js → persistent-memory-4E53HW3U.js} +3 -3
  32. package/dist/{persistent-memory-KX2R67AT.js → persistent-memory-KYRY56PG.js} +3 -3
  33. package/dist/{pr-NTQ3N4B4.js → pr-NPUGZSXB.js} +4 -4
  34. package/dist/{run-tests-25CNXJ4N.js → run-tests-5FHQ5IBX.js} +2 -2
  35. package/dist/{run-tests-UTES6HCT.js → run-tests-SU5CDQKF.js} +2 -2
  36. package/dist/{server-IGCCSX4B.js → server-77YS5NNN.js} +7 -7
  37. package/dist/{server-R56CVHCM.js → server-ER36M7TR.js} +149 -67
  38. package/dist/{task-orchestrator-MFYEKR2I.js → task-orchestrator-56PQ7LGV.js} +7 -7
  39. package/dist/{usage-FHX7PQQH.js → usage-3YATXRFZ.js} +2 -2
  40. package/package.json +1 -1
@@ -7,7 +7,7 @@ import {
7
7
  searchCandidates,
8
8
  searchChatMemory,
9
9
  updateSessionInIndex
10
- } from "./chunk-ZWEZNKDW.js";
10
+ } from "./chunk-YOVHMQEJ.js";
11
11
  import {
12
12
  fileCheckpoints
13
13
  } from "./chunk-SKET65WZ.js";
@@ -16,7 +16,9 @@ import {
16
16
  } from "./chunk-QCG6UU2S.js";
17
17
  import {
18
18
  addMemoryEntry,
19
+ backupMemoryStore,
19
20
  clearMemoryEntries,
21
+ countPendingMemories,
20
22
  deleteMemoryEntry,
21
23
  expireMemoryEntry,
22
24
  exportMemoryEntries,
@@ -32,18 +34,20 @@ import {
32
34
  loadMemoryEntries,
33
35
  memoryStorePath,
34
36
  parseWritableScope,
37
+ rebindMemoryProject,
38
+ restoreMemoryEntries,
35
39
  searchPersistentMemories,
36
40
  touchMemoryReferences,
37
41
  updateMemoryApproval,
38
42
  updateMemoryEntry
39
- } from "./chunk-VPXNLE7E.js";
43
+ } from "./chunk-M3NXF4GD.js";
40
44
  import {
41
45
  redactJson,
42
46
  scanString
43
- } from "./chunk-YVTASHS5.js";
47
+ } from "./chunk-FSC6KEWU.js";
44
48
  import {
45
49
  runTestsTool
46
- } from "./chunk-RLAUMACS.js";
50
+ } from "./chunk-FNLWPYP5.js";
47
51
  import {
48
52
  AGENTIC_BEHAVIOR_GUIDELINE,
49
53
  APP_NAME,
@@ -76,7 +80,7 @@ import {
76
80
  SUBAGENT_MAX_ROUNDS_LIMIT,
77
81
  VERSION,
78
82
  buildUserIdentityPrompt
79
- } from "./chunk-5JFRM47R.js";
83
+ } from "./chunk-LEK5WGKV.js";
80
84
  import {
81
85
  hasSemanticIndex,
82
86
  semanticSearch
@@ -94,7 +98,7 @@ import {
94
98
  import express from "express";
95
99
  import { createServer } from "http";
96
100
  import { WebSocketServer } from "ws";
97
- import { join as join26, dirname as dirname10, resolve as resolve10, relative as relative6, sep as sep4, extname as extname3, resolve as resolvePath } from "path";
101
+ import { join as join26, dirname as dirname10, resolve as resolve11, relative as relative6, sep as sep5, extname as extname3, resolve as resolvePath } from "path";
98
102
  import { existsSync as existsSync31, readFileSync as readFileSync25, readdirSync as readdirSync15, statSync as statSync14, realpathSync as realpathSync3, createReadStream } from "fs";
99
103
  import { networkInterfaces } from "os";
100
104
 
@@ -5598,7 +5602,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5598
5602
  startEvictionTimer();
5599
5603
  const id = `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
5600
5604
  const wrappedCmd = buildWrappedCommand(command, id, IS_WINDOWS2);
5601
- return new Promise((resolve11) => {
5605
+ return new Promise((resolve12) => {
5602
5606
  let stdout = "";
5603
5607
  let stderr = "";
5604
5608
  let timedOut = false;
@@ -5615,7 +5619,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5615
5619
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5616
5620
  resolved = true;
5617
5621
  cleanup();
5618
- resolve11({ stdout, stderr, exitCode, timedOut, aborted });
5622
+ resolve12({ stdout, stderr, exitCode, timedOut, aborted });
5619
5623
  }
5620
5624
  };
5621
5625
  const onErr = (chunk) => {
@@ -5628,7 +5632,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5628
5632
  stderr += `${stderr ? "\n" : ""}[pool terminated] ${message}`;
5629
5633
  cleanup();
5630
5634
  pool.delete(sessionKey);
5631
- resolve11({ stdout, stderr, exitCode: exitCode === 0 ? null : exitCode, timedOut, aborted });
5635
+ resolve12({ stdout, stderr, exitCode: exitCode === 0 ? null : exitCode, timedOut, aborted });
5632
5636
  };
5633
5637
  const onClose = (code, signal) => {
5634
5638
  const detail = signal ? `signal ${signal}` : `exit code ${code ?? "unknown"}`;
@@ -5647,7 +5651,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5647
5651
  resolved = true;
5648
5652
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5649
5653
  cleanup();
5650
- resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
5654
+ resolve12({ stdout, stderr, exitCode: null, timedOut, aborted });
5651
5655
  killProcessTree(proc);
5652
5656
  pool.delete(sessionKey);
5653
5657
  }, timeout);
@@ -5657,7 +5661,7 @@ async function execInPool(sessionKey, command, timeout, cwd, abortSignal) {
5657
5661
  resolved = true;
5658
5662
  cleanup();
5659
5663
  stdout = stripMarkerOutput(stdout, markerStartPattern, markerEndPattern);
5660
- resolve11({ stdout, stderr, exitCode: null, timedOut, aborted });
5664
+ resolve12({ stdout, stderr, exitCode: null, timedOut, aborted });
5661
5665
  killProcessTree(proc);
5662
5666
  pool.delete(sessionKey);
5663
5667
  };
@@ -8099,7 +8103,7 @@ var ToolExecutor = class {
8099
8103
  rl.resume();
8100
8104
  process.stdout.write(prompt);
8101
8105
  this.confirming = true;
8102
- return new Promise((resolve11) => {
8106
+ return new Promise((resolve12) => {
8103
8107
  let completed = false;
8104
8108
  const cleanup = (result) => {
8105
8109
  if (completed) return;
@@ -8109,7 +8113,7 @@ var ToolExecutor = class {
8109
8113
  rl.pause();
8110
8114
  rlAny.output = savedOutput;
8111
8115
  this.confirming = false;
8112
- resolve11(result);
8116
+ resolve12(result);
8113
8117
  };
8114
8118
  const onLine = (line) => {
8115
8119
  const trimmed = line.trim();
@@ -8283,7 +8287,7 @@ var ToolExecutor = class {
8283
8287
  rl.resume();
8284
8288
  process.stdout.write(color("Proceed? [y/N] (type y + Enter to confirm) "));
8285
8289
  this.confirming = true;
8286
- return new Promise((resolve11) => {
8290
+ return new Promise((resolve12) => {
8287
8291
  let completed = false;
8288
8292
  const cleanup = (answer) => {
8289
8293
  if (completed) return;
@@ -8293,7 +8297,7 @@ var ToolExecutor = class {
8293
8297
  rl.pause();
8294
8298
  rlAny.output = savedOutput;
8295
8299
  this.confirming = false;
8296
- resolve11(answer === "y");
8300
+ resolve12(answer === "y");
8297
8301
  };
8298
8302
  const onLine = (line) => {
8299
8303
  const trimmed = line.trim();
@@ -9576,7 +9580,7 @@ var runInteractiveTool = {
9576
9580
  PYTHONDONTWRITEBYTECODE: "1"
9577
9581
  };
9578
9582
  const prefixWarnings = [argsTypeWarning, stdinTypeWarning].filter(Boolean).join("");
9579
- return new Promise((resolve11) => {
9583
+ return new Promise((resolve12) => {
9580
9584
  const child = spawn4(executable, cmdArgs.map(String), {
9581
9585
  cwd: process.cwd(),
9582
9586
  env,
@@ -9609,22 +9613,22 @@ var runInteractiveTool = {
9609
9613
  setTimeout(writeNextLine, 400);
9610
9614
  const timer = setTimeout(() => {
9611
9615
  child.kill();
9612
- resolve11(`${prefixWarnings}[Timeout after ${timeout}ms]
9616
+ resolve12(`${prefixWarnings}[Timeout after ${timeout}ms]
9613
9617
  ${buildOutput(stdout, stderr)}`);
9614
9618
  }, timeout);
9615
9619
  child.on("close", (code) => {
9616
9620
  clearTimeout(timer);
9617
9621
  const output = buildOutput(stdout, stderr);
9618
9622
  if (code !== 0 && code !== null) {
9619
- resolve11(`${prefixWarnings}Exit code ${code}:
9623
+ resolve12(`${prefixWarnings}Exit code ${code}:
9620
9624
  ${output}`);
9621
9625
  } else {
9622
- resolve11(`${prefixWarnings}${output || "(no output)"}`);
9626
+ resolve12(`${prefixWarnings}${output || "(no output)"}`);
9623
9627
  }
9624
9628
  });
9625
9629
  child.on("error", (err) => {
9626
9630
  clearTimeout(timer);
9627
- resolve11(
9631
+ resolve12(
9628
9632
  `${prefixWarnings}Failed to start process "${executable}": ${err.message}
9629
9633
  Hint: On Windows, use the full path to the executable, e.g.:
9630
9634
  C:\\Users\\Jinzd\\anaconda3\\envs\\python312\\python.exe`
@@ -10446,7 +10450,7 @@ function promptUser(rl, question) {
10446
10450
  console.log();
10447
10451
  console.log(chalk4.cyan("\u2753 ") + chalk4.bold(question));
10448
10452
  process.stdout.write(chalk4.cyan("> "));
10449
- return new Promise((resolve11) => {
10453
+ return new Promise((resolve12) => {
10450
10454
  let completed = false;
10451
10455
  const cleanup = (answer) => {
10452
10456
  if (completed) return;
@@ -10456,7 +10460,7 @@ function promptUser(rl, question) {
10456
10460
  rl.pause();
10457
10461
  rlAny.output = savedOutput;
10458
10462
  askUserContext.prompting = false;
10459
- resolve11(answer);
10463
+ resolve12(answer);
10460
10464
  };
10461
10465
  const onLine = (line) => {
10462
10466
  cleanup(line);
@@ -13023,7 +13027,7 @@ var McpClient = class {
13023
13027
  // 内部方法:JSON-RPC 通信
13024
13028
  // ══════════════════════════════════════════════════════════════════
13025
13029
  sendRequest(method, params) {
13026
- return new Promise((resolve11, reject) => {
13030
+ return new Promise((resolve12, reject) => {
13027
13031
  if (!this.process?.stdin?.writable) {
13028
13032
  return reject(new Error(`MCP server [${this.serverId}] stdin not writable`));
13029
13033
  }
@@ -13046,7 +13050,7 @@ var McpClient = class {
13046
13050
  this.pendingRequests.set(id, {
13047
13051
  resolve: (result) => {
13048
13052
  cleanup();
13049
- resolve11(result);
13053
+ resolve12(result);
13050
13054
  },
13051
13055
  reject: (error) => {
13052
13056
  cleanup();
@@ -13123,13 +13127,13 @@ var McpClient = class {
13123
13127
  }
13124
13128
  /** Promise 超时包装 */
13125
13129
  withTimeout(promise, ms, label) {
13126
- return new Promise((resolve11, reject) => {
13130
+ return new Promise((resolve12, reject) => {
13127
13131
  const timer = setTimeout(() => {
13128
13132
  reject(new Error(`MCP [${this.serverId}] ${label} timed out after ${ms}ms`));
13129
13133
  }, ms);
13130
13134
  promise.then((val) => {
13131
13135
  clearTimeout(timer);
13132
- resolve11(val);
13136
+ resolve12(val);
13133
13137
  }).catch((err) => {
13134
13138
  clearTimeout(timer);
13135
13139
  reject(err);
@@ -13635,33 +13639,33 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13635
13639
  }
13636
13640
  /** Resolve a pending confirm from client response */
13637
13641
  resolveConfirm(requestId, approved) {
13638
- const resolve11 = this.pendingConfirms.get(requestId);
13639
- if (resolve11) {
13642
+ const resolve12 = this.pendingConfirms.get(requestId);
13643
+ if (resolve12) {
13640
13644
  this.clearPendingTimer(requestId);
13641
13645
  this.pendingConfirms.delete(requestId);
13642
13646
  this.confirming = false;
13643
- resolve11(approved);
13647
+ resolve12(approved);
13644
13648
  }
13645
13649
  }
13646
13650
  /** Resolve a pending batch confirm from client response */
13647
13651
  resolveBatchConfirm(requestId, decision) {
13648
- const resolve11 = this.pendingBatchConfirms.get(requestId);
13649
- if (resolve11) {
13652
+ const resolve12 = this.pendingBatchConfirms.get(requestId);
13653
+ if (resolve12) {
13650
13654
  this.clearPendingTimer(requestId);
13651
13655
  this.pendingBatchConfirms.delete(requestId);
13652
13656
  this.confirming = false;
13653
13657
  if (decision === "all" || decision === "none") {
13654
- resolve11(decision);
13658
+ resolve12(decision);
13655
13659
  } else {
13656
- resolve11(new Set(decision));
13660
+ resolve12(new Set(decision));
13657
13661
  }
13658
13662
  }
13659
13663
  }
13660
13664
  /** Cancel all pending confirms (e.g., on disconnect) */
13661
13665
  cancelAll() {
13662
- for (const resolve11 of this.pendingConfirms.values()) resolve11(false);
13666
+ for (const resolve12 of this.pendingConfirms.values()) resolve12(false);
13663
13667
  this.pendingConfirms.clear();
13664
- for (const resolve11 of this.pendingBatchConfirms.values()) resolve11("none");
13668
+ for (const resolve12 of this.pendingBatchConfirms.values()) resolve12("none");
13665
13669
  this.pendingBatchConfirms.clear();
13666
13670
  this.confirming = false;
13667
13671
  }
@@ -13736,8 +13740,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13736
13740
  diff: this.getDiffPreview(call)
13737
13741
  };
13738
13742
  this.send(msg);
13739
- return new Promise((resolve11) => {
13740
- this.pendingConfirms.set(requestId, resolve11);
13743
+ return new Promise((resolve12) => {
13744
+ this.pendingConfirms.set(requestId, resolve12);
13741
13745
  this.pendingTimers.set(requestId, setTimeout(() => {
13742
13746
  if (this.pendingConfirms.has(requestId)) {
13743
13747
  this.resolveConfirm(requestId, false);
@@ -13761,8 +13765,8 @@ var ToolExecutorWeb = class _ToolExecutorWeb {
13761
13765
  files
13762
13766
  };
13763
13767
  this.send(msg);
13764
- return new Promise((resolve11) => {
13765
- this.pendingBatchConfirms.set(requestId, resolve11);
13768
+ return new Promise((resolve12) => {
13769
+ this.pendingBatchConfirms.set(requestId, resolve12);
13766
13770
  this.pendingTimers.set(requestId, setTimeout(() => {
13767
13771
  if (this.pendingBatchConfirms.has(requestId)) {
13768
13772
  this.resolveBatchConfirm(requestId, "none");
@@ -16039,8 +16043,8 @@ Cache: write=${cacheCreate} read=${cacheRead}` : "";
16039
16043
  Cost: ${formatCost(cost)}` : "";
16040
16044
  let memoryLine = "";
16041
16045
  try {
16042
- const { countPendingMemories } = await import("./persistent-memory-KX2R67AT.js");
16043
- const pending = countPendingMemories(ctx.config.getConfigDir());
16046
+ const { countPendingMemories: countPendingMemories2 } = await import("./persistent-memory-KYRY56PG.js");
16047
+ const pending = countPendingMemories2(ctx.config.getConfigDir());
16044
16048
  if (pending > 0) memoryLine = `
16045
16049
  Memory: \u26A0 ${pending} pending approval \u2014 see the Memory panel or /memory`;
16046
16050
  } catch {
@@ -16344,7 +16348,7 @@ async function handleBranch(args, ctx) {
16344
16348
  return;
16345
16349
  }
16346
16350
  const sub = args[0]?.toLowerCase();
16347
- const resolve11 = (ref) => {
16351
+ const resolve12 = (ref) => {
16348
16352
  const r = session.resolveBranchRef(ref);
16349
16353
  if (r.ok) return r.id;
16350
16354
  if (r.reason === "ambiguous") {
@@ -16398,7 +16402,7 @@ async function handleBranch(args, ctx) {
16398
16402
  ctx.send({ type: "error", message: "Usage: /branch switch <id|title>" });
16399
16403
  return;
16400
16404
  }
16401
- const id = resolve11(ref);
16405
+ const id = resolve12(ref);
16402
16406
  if (!id) return;
16403
16407
  const ok = session.switchBranch(id);
16404
16408
  if (ok) {
@@ -16418,7 +16422,7 @@ async function handleBranch(args, ctx) {
16418
16422
  ctx.send({ type: "error", message: "Usage: /branch delete <id|title>" });
16419
16423
  return;
16420
16424
  }
16421
- const id = resolve11(ref);
16425
+ const id = resolve12(ref);
16422
16426
  if (!id) return;
16423
16427
  const ok = session.deleteBranch(id);
16424
16428
  if (ok) {
@@ -16437,7 +16441,7 @@ async function handleBranch(args, ctx) {
16437
16441
  ctx.send({ type: "error", message: "Usage: /branch rename <id|title> <new title>" });
16438
16442
  return;
16439
16443
  }
16440
- const id = resolve11(ref);
16444
+ const id = resolve12(ref);
16441
16445
  if (!id) return;
16442
16446
  const ok = session.renameBranch(id, title);
16443
16447
  if (ok) {
@@ -16455,7 +16459,7 @@ async function handleBranch(args, ctx) {
16455
16459
  ctx.send({ type: "error", message: "Usage: /branch diff <id|title>" });
16456
16460
  return;
16457
16461
  }
16458
- const id = resolve11(ref);
16462
+ const id = resolve12(ref);
16459
16463
  if (!id) return;
16460
16464
  const d = session.diffBranches(id);
16461
16465
  if (!d) {
@@ -16497,7 +16501,7 @@ async function handleBranch(args, ctx) {
16497
16501
  ctx.send({ type: "error", message: "Usage: /branch cherry-pick <source-id|title> <msg-index>" });
16498
16502
  return;
16499
16503
  }
16500
- const id = resolve11(ref);
16504
+ const id = resolve12(ref);
16501
16505
  if (!id) return;
16502
16506
  const idx = parseInt(idxStr, 10);
16503
16507
  if (Number.isNaN(idx)) {
@@ -16852,7 +16856,7 @@ async function handleTest(args, ctx) {
16852
16856
  const isCommand = argStr.includes(" ") || /^(mvn|gradle|npm|pytest|cargo|go)\b/.test(argStr);
16853
16857
  testArgs = isCommand ? { command: argStr } : { filter: argStr };
16854
16858
  }
16855
- const runTests = ctx.runTests ?? (await import("./run-tests-25CNXJ4N.js")).executeTests;
16859
+ const runTests = ctx.runTests ?? (await import("./run-tests-5FHQ5IBX.js")).executeTests;
16856
16860
  const report = await runTests(testArgs);
16857
16861
  ctx.send({ type: "info", message: report });
16858
16862
  } catch (err) {
@@ -16945,6 +16949,33 @@ Create the necessary files and directory structure. Use write_file and bash tool
16945
16949
  await ctx.handleChat(scaffoldPrompt);
16946
16950
  }
16947
16951
 
16952
+ // src/core/memory-admin.ts
16953
+ import { resolve as resolve10, sep as sep4 } from "path";
16954
+ function isWithinDir(base, target) {
16955
+ const b = resolve10(base);
16956
+ const t = resolve10(base, target);
16957
+ return t === b || t.startsWith(b.endsWith(sep4) ? b : b + sep4);
16958
+ }
16959
+ function checkWebRestorePath(configDir, file) {
16960
+ const trimmed = file?.trim();
16961
+ if (!trimmed) {
16962
+ return { ok: false, reason: "Usage: /memory restore <file> (a backup inside the config directory)" };
16963
+ }
16964
+ if (!isWithinDir(configDir, trimmed)) {
16965
+ return {
16966
+ ok: false,
16967
+ reason: `For safety the Web UI can only restore from inside the config directory (${configDir}). Slash commands bypass tool permission checks, so an arbitrary server-side path would be a read channel around them. Run /memory backup first, or use the terminal REPL for files elsewhere.`
16968
+ };
16969
+ }
16970
+ return { ok: true, resolved: resolve10(configDir, trimmed) };
16971
+ }
16972
+ function parseOutFlag(args) {
16973
+ const i = args.indexOf("--out");
16974
+ if (i < 0) return void 0;
16975
+ const v = args[i + 1];
16976
+ return v && !v.startsWith("--") ? v : void 0;
16977
+ }
16978
+
16948
16979
  // src/web/commands/memory-commands.ts
16949
16980
  async function handleSystem(args, ctx) {
16950
16981
  const text = args.join(" ").trim();
@@ -17076,6 +17107,57 @@ async function handleIndex(args, ctx) {
17076
17107
  }
17077
17108
  async function handleMemory(args, ctx) {
17078
17109
  const sub = args[0];
17110
+ if (sub === "backup") {
17111
+ try {
17112
+ const result = backupMemoryStore(ctx.config.getConfigDir(), parseOutFlag(args.slice(1)));
17113
+ ctx.send({ type: "info", message: `\u2713 Backed up ${result.count} entr${result.count === 1 ? "y" : "ies"} to ${result.backupPath}` });
17114
+ } catch (err) {
17115
+ ctx.send({ type: "error", message: err instanceof Error ? err.message : String(err) });
17116
+ }
17117
+ return;
17118
+ }
17119
+ if (sub === "restore") {
17120
+ const configDir = ctx.config.getConfigDir();
17121
+ const verdict = checkWebRestorePath(configDir, args[1]);
17122
+ if (!verdict.ok) {
17123
+ ctx.send({ type: "error", message: verdict.reason });
17124
+ return;
17125
+ }
17126
+ try {
17127
+ const result = restoreMemoryEntries(configDir, verdict.resolved);
17128
+ const lines = [
17129
+ `\u2713 Restored ${result.imported} entr${result.imported === 1 ? "y" : "ies"} (${result.skipped} duplicate${result.skipped === 1 ? "" : "s"} skipped)`
17130
+ ];
17131
+ if (result.backupPath) lines.push(`Pre-restore backup: ${result.backupPath}`);
17132
+ const pending = countPendingMemories(configDir);
17133
+ if (pending > 0) lines.push(`${pending} entr${pending === 1 ? "y" : "ies"} pending approval \u2014 /memory show --pending`);
17134
+ ctx.send({ type: "info", message: lines.join("\n") });
17135
+ ctx.sendMemoryEntries();
17136
+ } catch (err) {
17137
+ ctx.send({ type: "error", message: err instanceof Error ? err.message : String(err) });
17138
+ }
17139
+ return;
17140
+ }
17141
+ if (sub === "rebind") {
17142
+ const id = args[1];
17143
+ const newPath = args.slice(2).join(" ").trim();
17144
+ if (!id || !newPath) {
17145
+ ctx.send({ type: "error", message: "Usage: /memory rebind <id> <new project path> (find orphans with /memory show --orphaned)" });
17146
+ return;
17147
+ }
17148
+ try {
17149
+ const entry = rebindMemoryProject(ctx.config.getConfigDir(), id, newPath);
17150
+ ctx.send({ type: "info", message: `\u2713 Rebound memory ${entry.id.slice(0, 8)} to project ${entry.sourceProject}` });
17151
+ ctx.sendMemoryEntries();
17152
+ } catch (err) {
17153
+ ctx.send({ type: "error", message: err instanceof Error ? err.message : String(err) });
17154
+ }
17155
+ return;
17156
+ }
17157
+ if (sub === "path") {
17158
+ ctx.send({ type: "info", message: memoryStorePath(ctx.config.getConfigDir()) });
17159
+ return;
17160
+ }
17079
17161
  if (sub === "add" && args.length > 1) {
17080
17162
  const rest = args.slice(1);
17081
17163
  const opts = {};
@@ -17110,7 +17192,7 @@ async function handleMemory(args, ctx) {
17110
17192
  ctx.handleMemoryManage(sub, args[1], sub === "expire" ? args[2] : void 0);
17111
17193
  } else if (sub === "export") {
17112
17194
  if (args[1] === "md") {
17113
- const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-KX2R67AT.js");
17195
+ const { exportMemoryEntries: exportMemoryEntries2 } = await import("./persistent-memory-KYRY56PG.js");
17114
17196
  ctx.send({
17115
17197
  type: "export_data",
17116
17198
  format: "md",
@@ -17950,10 +18032,10 @@ var SessionHandler = class {
17950
18032
  return;
17951
18033
  }
17952
18034
  case "ask_user_response": {
17953
- const resolve11 = this.pendingAskUser.get(msg.requestId);
17954
- if (resolve11) {
18035
+ const resolve12 = this.pendingAskUser.get(msg.requestId);
18036
+ if (resolve12) {
17955
18037
  this.pendingAskUser.delete(msg.requestId);
17956
- resolve11(msg.answer);
18038
+ resolve12(msg.answer);
17957
18039
  }
17958
18040
  return;
17959
18041
  }
@@ -17966,10 +18048,10 @@ var SessionHandler = class {
17966
18048
  case "memory_manage":
17967
18049
  return this.handleMemoryManage(msg.action, msg.id, msg.expiresAt);
17968
18050
  case "auto_pause_response": {
17969
- const resolve11 = this.pendingAutoPause.get(msg.requestId);
17970
- if (resolve11) {
18051
+ const resolve12 = this.pendingAutoPause.get(msg.requestId);
18052
+ if (resolve12) {
17971
18053
  this.pendingAutoPause.delete(msg.requestId);
17972
- resolve11({ action: msg.action, message: msg.message });
18054
+ resolve12({ action: msg.action, message: msg.message });
17973
18055
  }
17974
18056
  return;
17975
18057
  }
@@ -17984,10 +18066,10 @@ var SessionHandler = class {
17984
18066
  this.hubOrchestrator?.abort();
17985
18067
  return;
17986
18068
  case "hub_steer": {
17987
- const resolve11 = this.pendingHubReview.get(msg.requestId);
17988
- if (resolve11) {
18069
+ const resolve12 = this.pendingHubReview.get(msg.requestId);
18070
+ if (resolve12) {
17989
18071
  this.pendingHubReview.delete(msg.requestId);
17990
- resolve11({ action: msg.action, message: msg.message });
18072
+ resolve12({ action: msg.action, message: msg.message });
17991
18073
  }
17992
18074
  return;
17993
18075
  }
@@ -18000,9 +18082,9 @@ var SessionHandler = class {
18000
18082
  runLifecycleHooks(mergePluginHooks(this.config.get("hooks") ?? void 0, this.config.getConfigDir()), "Stop", { sessionId: this.sessions.current?.id }, { configDir: this.config.getConfigDir() });
18001
18083
  this.toolExecutor.cancelAll();
18002
18084
  if (this.abortController) this.abortController.abort();
18003
- for (const resolve11 of this.pendingAskUser.values()) resolve11(null);
18085
+ for (const resolve12 of this.pendingAskUser.values()) resolve12(null);
18004
18086
  this.pendingAskUser.clear();
18005
- for (const resolve11 of this.pendingAutoPause.values()) resolve11({ action: "stop" });
18087
+ for (const resolve12 of this.pendingAutoPause.values()) resolve12({ action: "stop" });
18006
18088
  this.pendingAutoPause.clear();
18007
18089
  this.saveIfNeeded();
18008
18090
  if (this._bashSessionKey) clearBashSession(this._bashSessionKey);
@@ -18138,9 +18220,9 @@ var SessionHandler = class {
18138
18220
  this.hubOrchestrator = orchestrator;
18139
18221
  orchestrator.onEvent = (event) => this.send({ type: "hub_event", event });
18140
18222
  if (config.humanSteer) {
18141
- orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve11) => {
18223
+ orchestrator.onRoundReview = ({ round, maxRounds }) => new Promise((resolve12) => {
18142
18224
  const requestId = `hubrev_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
18143
- this.pendingHubReview.set(requestId, resolve11);
18225
+ this.pendingHubReview.set(requestId, resolve12);
18144
18226
  this.send({ type: "hub_review", requestId, round, maxRounds });
18145
18227
  });
18146
18228
  }
@@ -18515,8 +18597,8 @@ Try: /compact to reduce context, /clear to reset, or switch to a larger-context
18515
18597
  onMcpToolUsed: (name) => this.usedMcpToolNames.add(name),
18516
18598
  requestAutoPause: async ({ effectiveRound, maxToolRounds: totalRounds, toolSummary }) => {
18517
18599
  const requestId = `pause_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
18518
- const pauseResp = await new Promise((resolve11) => {
18519
- this.pendingAutoPause.set(requestId, resolve11);
18600
+ const pauseResp = await new Promise((resolve12) => {
18601
+ this.pendingAutoPause.set(requestId, resolve12);
18520
18602
  this.send({
18521
18603
  type: "auto_pause_request",
18522
18604
  requestId,
@@ -18696,8 +18778,8 @@ ${summaryContent}`,
18696
18778
  }
18697
18779
  if (chunk.done) break;
18698
18780
  }
18699
- await new Promise((resolve11, reject) => {
18700
- fileStream.end((err) => err ? reject(err) : resolve11());
18781
+ await new Promise((resolve12, reject) => {
18782
+ fileStream.end((err) => err ? reject(err) : resolve12());
18701
18783
  });
18702
18784
  const verdict = evaluateTeeContent(fullContent, saveToFile, priorContent);
18703
18785
  if (verdict.kind === "reject") {
@@ -18723,7 +18805,7 @@ ${summaryContent}`,
18723
18805
  } catch (err) {
18724
18806
  if (fileStream) {
18725
18807
  try {
18726
- await new Promise((resolve11) => fileStream.end(() => resolve11()));
18808
+ await new Promise((resolve12) => fileStream.end(() => resolve12()));
18727
18809
  } catch {
18728
18810
  }
18729
18811
  }
@@ -19100,7 +19182,7 @@ Backup saved: ${result.backupPath}` : "";
19100
19182
  return;
19101
19183
  }
19102
19184
  try {
19103
- const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-Q6BKWWAM.js");
19185
+ const { searchChatMemory: searchChatMemory2, loadChatIndex: loadChatIndex2 } = await import("./chat-index-TDU3S2MG.js");
19104
19186
  const loaded = loadChatIndex2();
19105
19187
  if (!loaded || loaded.idx.chunks.length === 0) {
19106
19188
  this.send({ type: "memory_hits", query: q, hits: [], indexMissing: true });
@@ -19136,7 +19218,7 @@ Backup saved: ${result.backupPath}` : "";
19136
19218
  }
19137
19219
  async handleMemoryStatus() {
19138
19220
  try {
19139
- const { getChatIndexStatus } = await import("./chat-index-Q6BKWWAM.js");
19221
+ const { getChatIndexStatus } = await import("./chat-index-TDU3S2MG.js");
19140
19222
  const s = getChatIndexStatus();
19141
19223
  this.send({
19142
19224
  type: "memory_status",
@@ -19161,7 +19243,7 @@ Backup saved: ${result.backupPath}` : "";
19161
19243
  type: "info",
19162
19244
  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"
19163
19245
  });
19164
- const { buildChatIndex } = await import("./chat-index-Q6BKWWAM.js");
19246
+ const { buildChatIndex } = await import("./chat-index-TDU3S2MG.js");
19165
19247
  const stats = await buildChatIndex({
19166
19248
  full,
19167
19249
  onProgress: (p) => {
@@ -19634,7 +19716,7 @@ function getModuleDir() {
19634
19716
  }
19635
19717
  } catch {
19636
19718
  }
19637
- return resolve10(".");
19719
+ return resolve11(".");
19638
19720
  }
19639
19721
  async function startWebServer(options = {}) {
19640
19722
  const port = options.port ?? 3e3;
@@ -19883,9 +19965,9 @@ async function startWebServer(options = {}) {
19883
19965
  const prefix = req.query.prefix || "";
19884
19966
  const targetDir = join26(cwd, prefix);
19885
19967
  try {
19886
- const canonicalTarget = realpathSync3(resolve10(targetDir));
19887
- const canonicalCwd = realpathSync3(resolve10(cwd));
19888
- if (!canonicalTarget.startsWith(canonicalCwd + sep4) && canonicalTarget !== canonicalCwd) {
19968
+ const canonicalTarget = realpathSync3(resolve11(targetDir));
19969
+ const canonicalCwd = realpathSync3(resolve11(cwd));
19970
+ if (!canonicalTarget.startsWith(canonicalCwd + sep5) && canonicalTarget !== canonicalCwd) {
19889
19971
  res.json({ files: [] });
19890
19972
  return;
19891
19973
  }
@@ -19946,7 +20028,7 @@ async function startWebServer(options = {}) {
19946
20028
  try {
19947
20029
  const canonicalFile = realpathSync3(filePath);
19948
20030
  const canonicalDir = realpathSync3(histDir);
19949
- if (!canonicalFile.startsWith(canonicalDir + sep4)) {
20031
+ if (!canonicalFile.startsWith(canonicalDir + sep5)) {
19950
20032
  res.status(404).json({ error: "Session not found" });
19951
20033
  return;
19952
20034
  }
@@ -19967,11 +20049,11 @@ async function startWebServer(options = {}) {
19967
20049
  return;
19968
20050
  }
19969
20051
  const cwd = process.cwd();
19970
- const fullPath = resolve10(join26(cwd, filePath));
20052
+ const fullPath = resolve11(join26(cwd, filePath));
19971
20053
  try {
19972
20054
  const canonicalFull = realpathSync3(fullPath);
19973
- const canonicalCwd = realpathSync3(resolve10(cwd));
19974
- if (!canonicalFull.startsWith(canonicalCwd + sep4) && canonicalFull !== canonicalCwd) {
20055
+ const canonicalCwd = realpathSync3(resolve11(cwd));
20056
+ if (!canonicalFull.startsWith(canonicalCwd + sep5) && canonicalFull !== canonicalCwd) {
19975
20057
  res.json({ error: "Access denied" });
19976
20058
  return;
19977
20059
  }
@@ -20191,7 +20273,7 @@ async function startWebServer(options = {}) {
20191
20273
  });
20192
20274
  const MAX_PORT_ATTEMPTS = 10;
20193
20275
  let actualPort = port;
20194
- const result = await new Promise((resolve11, reject) => {
20276
+ const result = await new Promise((resolve12, reject) => {
20195
20277
  const tryListen = (attempt) => {
20196
20278
  server.once("error", (err) => {
20197
20279
  if (err.code === "EADDRINUSE" && attempt < MAX_PORT_ATTEMPTS) {
@@ -20222,7 +20304,7 @@ async function startWebServer(options = {}) {
20222
20304
  }
20223
20305
  console.log(` Press Ctrl+C to stop
20224
20306
  `);
20225
- resolve11({ port: actualPort, host, url });
20307
+ resolve12({ port: actualPort, host, url });
20226
20308
  });
20227
20309
  };
20228
20310
  tryListen(1);
@@ -143,7 +143,7 @@ ${content}`);
143
143
  const state = await runDiscussion(config, providers, options.topic);
144
144
  if (options.save !== false && state.messages.length > 0) {
145
145
  try {
146
- const { persistDiscussion } = await import("./persist-A2QSXYFY.js");
146
+ const { persistDiscussion } = await import("./persist-PQM4BRI4.js");
147
147
  const { path } = await persistDiscussion(state, configManager, defaultProvider, defaultModel);
148
148
  console.log(chalk.dim(`
149
149
  \u{1F4BE} Saved to history \u2014 open it in the Web UI and hit \u{1F3AC} to replay.
@@ -158,7 +158,7 @@ ${content}`);
158
158
  }
159
159
  }
160
160
  async function runTaskMode(config, providers, configManager, topic) {
161
- const { TaskOrchestrator } = await import("./task-orchestrator-MFYEKR2I.js");
161
+ const { TaskOrchestrator } = await import("./task-orchestrator-56PQ7LGV.js");
162
162
  const orchestrator = new TaskOrchestrator(config, providers, configManager);
163
163
  let interrupted = false;
164
164
  const onSigint = () => {