@clawos-dev/clawd 0.2.28 → 0.2.29

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 (2) hide show
  1. package/dist/cli.cjs +451 -509
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -296,8 +296,8 @@ var require_req = __commonJS({
296
296
  if (req.originalUrl) {
297
297
  _req.url = req.originalUrl;
298
298
  } else {
299
- const path23 = req.path;
300
- _req.url = typeof path23 === "string" ? path23 : req.url ? req.url.path || req.url : void 0;
299
+ const path21 = req.path;
300
+ _req.url = typeof path21 === "string" ? path21 : req.url ? req.url.path || req.url : void 0;
301
301
  }
302
302
  if (req.query) {
303
303
  _req.query = req.query;
@@ -462,14 +462,14 @@ var require_redact = __commonJS({
462
462
  }
463
463
  return obj;
464
464
  }
465
- function parsePath(path23) {
465
+ function parsePath(path21) {
466
466
  const parts = [];
467
467
  let current = "";
468
468
  let inBrackets = false;
469
469
  let inQuotes = false;
470
470
  let quoteChar = "";
471
- for (let i = 0; i < path23.length; i++) {
472
- const char = path23[i];
471
+ for (let i = 0; i < path21.length; i++) {
472
+ const char = path21[i];
473
473
  if (!inBrackets && char === ".") {
474
474
  if (current) {
475
475
  parts.push(current);
@@ -600,10 +600,10 @@ var require_redact = __commonJS({
600
600
  return current;
601
601
  }
602
602
  function redactPaths(obj, paths, censor, remove = false) {
603
- for (const path23 of paths) {
604
- const parts = parsePath(path23);
603
+ for (const path21 of paths) {
604
+ const parts = parsePath(path21);
605
605
  if (parts.includes("*")) {
606
- redactWildcardPath(obj, parts, censor, path23, remove);
606
+ redactWildcardPath(obj, parts, censor, path21, remove);
607
607
  } else {
608
608
  if (remove) {
609
609
  removeKey(obj, parts);
@@ -688,8 +688,8 @@ var require_redact = __commonJS({
688
688
  }
689
689
  } else {
690
690
  if (afterWildcard.includes("*")) {
691
- const wrappedCensor = typeof censor === "function" ? (value, path23) => {
692
- const fullPath = [...pathArray.slice(0, pathLength), ...path23];
691
+ const wrappedCensor = typeof censor === "function" ? (value, path21) => {
692
+ const fullPath = [...pathArray.slice(0, pathLength), ...path21];
693
693
  return censor(value, fullPath);
694
694
  } : censor;
695
695
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -724,8 +724,8 @@ var require_redact = __commonJS({
724
724
  return null;
725
725
  }
726
726
  const pathStructure = /* @__PURE__ */ new Map();
727
- for (const path23 of pathsToClone) {
728
- const parts = parsePath(path23);
727
+ for (const path21 of pathsToClone) {
728
+ const parts = parsePath(path21);
729
729
  let current = pathStructure;
730
730
  for (let i = 0; i < parts.length; i++) {
731
731
  const part = parts[i];
@@ -777,24 +777,24 @@ var require_redact = __commonJS({
777
777
  }
778
778
  return cloneSelectively(obj, pathStructure);
779
779
  }
780
- function validatePath(path23) {
781
- if (typeof path23 !== "string") {
780
+ function validatePath(path21) {
781
+ if (typeof path21 !== "string") {
782
782
  throw new Error("Paths must be (non-empty) strings");
783
783
  }
784
- if (path23 === "") {
784
+ if (path21 === "") {
785
785
  throw new Error("Invalid redaction path ()");
786
786
  }
787
- if (path23.includes("..")) {
788
- throw new Error(`Invalid redaction path (${path23})`);
787
+ if (path21.includes("..")) {
788
+ throw new Error(`Invalid redaction path (${path21})`);
789
789
  }
790
- if (path23.includes(",")) {
791
- throw new Error(`Invalid redaction path (${path23})`);
790
+ if (path21.includes(",")) {
791
+ throw new Error(`Invalid redaction path (${path21})`);
792
792
  }
793
793
  let bracketCount = 0;
794
794
  let inQuotes = false;
795
795
  let quoteChar = "";
796
- for (let i = 0; i < path23.length; i++) {
797
- const char = path23[i];
796
+ for (let i = 0; i < path21.length; i++) {
797
+ const char = path21[i];
798
798
  if ((char === '"' || char === "'") && bracketCount > 0) {
799
799
  if (!inQuotes) {
800
800
  inQuotes = true;
@@ -808,20 +808,20 @@ var require_redact = __commonJS({
808
808
  } else if (char === "]" && !inQuotes) {
809
809
  bracketCount--;
810
810
  if (bracketCount < 0) {
811
- throw new Error(`Invalid redaction path (${path23})`);
811
+ throw new Error(`Invalid redaction path (${path21})`);
812
812
  }
813
813
  }
814
814
  }
815
815
  if (bracketCount !== 0) {
816
- throw new Error(`Invalid redaction path (${path23})`);
816
+ throw new Error(`Invalid redaction path (${path21})`);
817
817
  }
818
818
  }
819
819
  function validatePaths(paths) {
820
820
  if (!Array.isArray(paths)) {
821
821
  throw new TypeError("paths must be an array");
822
822
  }
823
- for (const path23 of paths) {
824
- validatePath(path23);
823
+ for (const path21 of paths) {
824
+ validatePath(path21);
825
825
  }
826
826
  }
827
827
  function slowRedact(options = {}) {
@@ -989,8 +989,8 @@ var require_redaction = __commonJS({
989
989
  if (shape[k] === null) {
990
990
  o[k] = (value) => topCensor(value, [k]);
991
991
  } else {
992
- const wrappedCensor = typeof censor === "function" ? (value, path23) => {
993
- return censor(value, [k, ...path23]);
992
+ const wrappedCensor = typeof censor === "function" ? (value, path21) => {
993
+ return censor(value, [k, ...path21]);
994
994
  } : censor;
995
995
  o[k] = Redact({
996
996
  paths: shape[k],
@@ -1208,10 +1208,10 @@ var require_atomic_sleep = __commonJS({
1208
1208
  var require_sonic_boom = __commonJS({
1209
1209
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
1210
1210
  "use strict";
1211
- var fs22 = require("fs");
1211
+ var fs21 = require("fs");
1212
1212
  var EventEmitter = require("events");
1213
1213
  var inherits = require("util").inherits;
1214
- var path23 = require("path");
1214
+ var path21 = require("path");
1215
1215
  var sleep = require_atomic_sleep();
1216
1216
  var assert = require("assert");
1217
1217
  var BUSY_WRITE_TIMEOUT = 100;
@@ -1265,20 +1265,20 @@ var require_sonic_boom = __commonJS({
1265
1265
  const mode = sonic.mode;
1266
1266
  if (sonic.sync) {
1267
1267
  try {
1268
- if (sonic.mkdir) fs22.mkdirSync(path23.dirname(file), { recursive: true });
1269
- const fd = fs22.openSync(file, flags, mode);
1268
+ if (sonic.mkdir) fs21.mkdirSync(path21.dirname(file), { recursive: true });
1269
+ const fd = fs21.openSync(file, flags, mode);
1270
1270
  fileOpened(null, fd);
1271
1271
  } catch (err) {
1272
1272
  fileOpened(err);
1273
1273
  throw err;
1274
1274
  }
1275
1275
  } else if (sonic.mkdir) {
1276
- fs22.mkdir(path23.dirname(file), { recursive: true }, (err) => {
1276
+ fs21.mkdir(path21.dirname(file), { recursive: true }, (err) => {
1277
1277
  if (err) return fileOpened(err);
1278
- fs22.open(file, flags, mode, fileOpened);
1278
+ fs21.open(file, flags, mode, fileOpened);
1279
1279
  });
1280
1280
  } else {
1281
- fs22.open(file, flags, mode, fileOpened);
1281
+ fs21.open(file, flags, mode, fileOpened);
1282
1282
  }
1283
1283
  }
1284
1284
  function SonicBoom(opts) {
@@ -1319,8 +1319,8 @@ var require_sonic_boom = __commonJS({
1319
1319
  this.flush = flushBuffer;
1320
1320
  this.flushSync = flushBufferSync;
1321
1321
  this._actualWrite = actualWriteBuffer;
1322
- fsWriteSync = () => fs22.writeSync(this.fd, this._writingBuf);
1323
- fsWrite = () => fs22.write(this.fd, this._writingBuf, this.release);
1322
+ fsWriteSync = () => fs21.writeSync(this.fd, this._writingBuf);
1323
+ fsWrite = () => fs21.write(this.fd, this._writingBuf, this.release);
1324
1324
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
1325
1325
  this._writingBuf = "";
1326
1326
  this.write = write;
@@ -1329,15 +1329,15 @@ var require_sonic_boom = __commonJS({
1329
1329
  this._actualWrite = actualWrite;
1330
1330
  fsWriteSync = () => {
1331
1331
  if (Buffer.isBuffer(this._writingBuf)) {
1332
- return fs22.writeSync(this.fd, this._writingBuf);
1332
+ return fs21.writeSync(this.fd, this._writingBuf);
1333
1333
  }
1334
- return fs22.writeSync(this.fd, this._writingBuf, "utf8");
1334
+ return fs21.writeSync(this.fd, this._writingBuf, "utf8");
1335
1335
  };
1336
1336
  fsWrite = () => {
1337
1337
  if (Buffer.isBuffer(this._writingBuf)) {
1338
- return fs22.write(this.fd, this._writingBuf, this.release);
1338
+ return fs21.write(this.fd, this._writingBuf, this.release);
1339
1339
  }
1340
- return fs22.write(this.fd, this._writingBuf, "utf8", this.release);
1340
+ return fs21.write(this.fd, this._writingBuf, "utf8", this.release);
1341
1341
  };
1342
1342
  } else {
1343
1343
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -1394,7 +1394,7 @@ var require_sonic_boom = __commonJS({
1394
1394
  }
1395
1395
  }
1396
1396
  if (this._fsync) {
1397
- fs22.fsyncSync(this.fd);
1397
+ fs21.fsyncSync(this.fd);
1398
1398
  }
1399
1399
  const len = this._len;
1400
1400
  if (this._reopening) {
@@ -1508,7 +1508,7 @@ var require_sonic_boom = __commonJS({
1508
1508
  const onDrain = () => {
1509
1509
  if (!this._fsync) {
1510
1510
  try {
1511
- fs22.fsync(this.fd, (err) => {
1511
+ fs21.fsync(this.fd, (err) => {
1512
1512
  this._flushPending = false;
1513
1513
  cb(err);
1514
1514
  });
@@ -1610,7 +1610,7 @@ var require_sonic_boom = __commonJS({
1610
1610
  const fd = this.fd;
1611
1611
  this.once("ready", () => {
1612
1612
  if (fd !== this.fd) {
1613
- fs22.close(fd, (err) => {
1613
+ fs21.close(fd, (err) => {
1614
1614
  if (err) {
1615
1615
  return this.emit("error", err);
1616
1616
  }
@@ -1659,7 +1659,7 @@ var require_sonic_boom = __commonJS({
1659
1659
  buf = this._bufs[0];
1660
1660
  }
1661
1661
  try {
1662
- const n = Buffer.isBuffer(buf) ? fs22.writeSync(this.fd, buf) : fs22.writeSync(this.fd, buf, "utf8");
1662
+ const n = Buffer.isBuffer(buf) ? fs21.writeSync(this.fd, buf) : fs21.writeSync(this.fd, buf, "utf8");
1663
1663
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
1664
1664
  buf = releasedBufObj.writingBuf;
1665
1665
  this._len = releasedBufObj.len;
@@ -1675,7 +1675,7 @@ var require_sonic_boom = __commonJS({
1675
1675
  }
1676
1676
  }
1677
1677
  try {
1678
- fs22.fsyncSync(this.fd);
1678
+ fs21.fsyncSync(this.fd);
1679
1679
  } catch {
1680
1680
  }
1681
1681
  }
@@ -1696,7 +1696,7 @@ var require_sonic_boom = __commonJS({
1696
1696
  buf = mergeBuf(this._bufs[0], this._lens[0]);
1697
1697
  }
1698
1698
  try {
1699
- const n = fs22.writeSync(this.fd, buf);
1699
+ const n = fs21.writeSync(this.fd, buf);
1700
1700
  buf = buf.subarray(n);
1701
1701
  this._len = Math.max(this._len - n, 0);
1702
1702
  if (buf.length <= 0) {
@@ -1724,13 +1724,13 @@ var require_sonic_boom = __commonJS({
1724
1724
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
1725
1725
  if (this.sync) {
1726
1726
  try {
1727
- const written = Buffer.isBuffer(this._writingBuf) ? fs22.writeSync(this.fd, this._writingBuf) : fs22.writeSync(this.fd, this._writingBuf, "utf8");
1727
+ const written = Buffer.isBuffer(this._writingBuf) ? fs21.writeSync(this.fd, this._writingBuf) : fs21.writeSync(this.fd, this._writingBuf, "utf8");
1728
1728
  release(null, written);
1729
1729
  } catch (err) {
1730
1730
  release(err);
1731
1731
  }
1732
1732
  } else {
1733
- fs22.write(this.fd, this._writingBuf, release);
1733
+ fs21.write(this.fd, this._writingBuf, release);
1734
1734
  }
1735
1735
  }
1736
1736
  function actualWriteBuffer() {
@@ -1739,7 +1739,7 @@ var require_sonic_boom = __commonJS({
1739
1739
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
1740
1740
  if (this.sync) {
1741
1741
  try {
1742
- const written = fs22.writeSync(this.fd, this._writingBuf);
1742
+ const written = fs21.writeSync(this.fd, this._writingBuf);
1743
1743
  release(null, written);
1744
1744
  } catch (err) {
1745
1745
  release(err);
@@ -1748,7 +1748,7 @@ var require_sonic_boom = __commonJS({
1748
1748
  if (kCopyBuffer) {
1749
1749
  this._writingBuf = Buffer.from(this._writingBuf);
1750
1750
  }
1751
- fs22.write(this.fd, this._writingBuf, release);
1751
+ fs21.write(this.fd, this._writingBuf, release);
1752
1752
  }
1753
1753
  }
1754
1754
  function actualClose(sonic) {
@@ -1764,12 +1764,12 @@ var require_sonic_boom = __commonJS({
1764
1764
  sonic._lens = [];
1765
1765
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
1766
1766
  try {
1767
- fs22.fsync(sonic.fd, closeWrapped);
1767
+ fs21.fsync(sonic.fd, closeWrapped);
1768
1768
  } catch {
1769
1769
  }
1770
1770
  function closeWrapped() {
1771
1771
  if (sonic.fd !== 1 && sonic.fd !== 2) {
1772
- fs22.close(sonic.fd, done);
1772
+ fs21.close(sonic.fd, done);
1773
1773
  } else {
1774
1774
  done();
1775
1775
  }
@@ -2026,7 +2026,7 @@ var require_thread_stream = __commonJS({
2026
2026
  var { version: version2 } = require_package();
2027
2027
  var { EventEmitter } = require("events");
2028
2028
  var { Worker } = require("worker_threads");
2029
- var { join: join2 } = require("path");
2029
+ var { join: join3 } = require("path");
2030
2030
  var { pathToFileURL } = require("url");
2031
2031
  var { wait } = require_wait();
2032
2032
  var {
@@ -2062,7 +2062,7 @@ var require_thread_stream = __commonJS({
2062
2062
  function createWorker(stream, opts) {
2063
2063
  const { filename, workerData } = opts;
2064
2064
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
2065
- const toExecute = bundlerOverrides["thread-stream-worker"] || join2(__dirname, "lib", "worker.js");
2065
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join3(__dirname, "lib", "worker.js");
2066
2066
  const worker = new Worker(toExecute, {
2067
2067
  ...opts.workerOpts,
2068
2068
  trackUnmanagedFds: false,
@@ -2448,7 +2448,7 @@ var require_transport = __commonJS({
2448
2448
  "use strict";
2449
2449
  var { createRequire } = require("module");
2450
2450
  var getCallers = require_caller();
2451
- var { join: join2, isAbsolute, sep } = require("path");
2451
+ var { join: join3, isAbsolute, sep } = require("path");
2452
2452
  var sleep = require_atomic_sleep();
2453
2453
  var onExit = require_on_exit_leak_free();
2454
2454
  var ThreadStream = require_thread_stream();
@@ -2511,7 +2511,7 @@ var require_transport = __commonJS({
2511
2511
  throw new Error("only one of target or targets can be specified");
2512
2512
  }
2513
2513
  if (targets) {
2514
- target = bundlerOverrides["pino-worker"] || join2(__dirname, "worker.js");
2514
+ target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
2515
2515
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
2516
2516
  return {
2517
2517
  ...dest,
@@ -2529,7 +2529,7 @@ var require_transport = __commonJS({
2529
2529
  });
2530
2530
  });
2531
2531
  } else if (pipeline2) {
2532
- target = bundlerOverrides["pino-worker"] || join2(__dirname, "worker.js");
2532
+ target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
2533
2533
  options.pipelines = [pipeline2.map((dest) => {
2534
2534
  return {
2535
2535
  ...dest,
@@ -2551,7 +2551,7 @@ var require_transport = __commonJS({
2551
2551
  return origin;
2552
2552
  }
2553
2553
  if (origin === "pino/file") {
2554
- return join2(__dirname, "..", "file.js");
2554
+ return join3(__dirname, "..", "file.js");
2555
2555
  }
2556
2556
  let fixTarget2;
2557
2557
  for (const filePath of callers) {
@@ -3541,7 +3541,7 @@ var require_safe_stable_stringify = __commonJS({
3541
3541
  return circularValue;
3542
3542
  }
3543
3543
  let res = "";
3544
- let join2 = ",";
3544
+ let join3 = ",";
3545
3545
  const originalIndentation = indentation;
3546
3546
  if (Array.isArray(value)) {
3547
3547
  if (value.length === 0) {
@@ -3555,7 +3555,7 @@ var require_safe_stable_stringify = __commonJS({
3555
3555
  indentation += spacer;
3556
3556
  res += `
3557
3557
  ${indentation}`;
3558
- join2 = `,
3558
+ join3 = `,
3559
3559
  ${indentation}`;
3560
3560
  }
3561
3561
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3563,13 +3563,13 @@ ${indentation}`;
3563
3563
  for (; i < maximumValuesToStringify - 1; i++) {
3564
3564
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3565
3565
  res += tmp2 !== void 0 ? tmp2 : "null";
3566
- res += join2;
3566
+ res += join3;
3567
3567
  }
3568
3568
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3569
3569
  res += tmp !== void 0 ? tmp : "null";
3570
3570
  if (value.length - 1 > maximumBreadth) {
3571
3571
  const removedKeys = value.length - maximumBreadth - 1;
3572
- res += `${join2}"... ${getItemCount(removedKeys)} not stringified"`;
3572
+ res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
3573
3573
  }
3574
3574
  if (spacer !== "") {
3575
3575
  res += `
@@ -3590,7 +3590,7 @@ ${originalIndentation}`;
3590
3590
  let separator = "";
3591
3591
  if (spacer !== "") {
3592
3592
  indentation += spacer;
3593
- join2 = `,
3593
+ join3 = `,
3594
3594
  ${indentation}`;
3595
3595
  whitespace = " ";
3596
3596
  }
@@ -3604,13 +3604,13 @@ ${indentation}`;
3604
3604
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
3605
3605
  if (tmp !== void 0) {
3606
3606
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3607
- separator = join2;
3607
+ separator = join3;
3608
3608
  }
3609
3609
  }
3610
3610
  if (keyLength > maximumBreadth) {
3611
3611
  const removedKeys = keyLength - maximumBreadth;
3612
3612
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
3613
- separator = join2;
3613
+ separator = join3;
3614
3614
  }
3615
3615
  if (spacer !== "" && separator.length > 1) {
3616
3616
  res = `
@@ -3651,7 +3651,7 @@ ${originalIndentation}`;
3651
3651
  }
3652
3652
  const originalIndentation = indentation;
3653
3653
  let res = "";
3654
- let join2 = ",";
3654
+ let join3 = ",";
3655
3655
  if (Array.isArray(value)) {
3656
3656
  if (value.length === 0) {
3657
3657
  return "[]";
@@ -3664,7 +3664,7 @@ ${originalIndentation}`;
3664
3664
  indentation += spacer;
3665
3665
  res += `
3666
3666
  ${indentation}`;
3667
- join2 = `,
3667
+ join3 = `,
3668
3668
  ${indentation}`;
3669
3669
  }
3670
3670
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3672,13 +3672,13 @@ ${indentation}`;
3672
3672
  for (; i < maximumValuesToStringify - 1; i++) {
3673
3673
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3674
3674
  res += tmp2 !== void 0 ? tmp2 : "null";
3675
- res += join2;
3675
+ res += join3;
3676
3676
  }
3677
3677
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3678
3678
  res += tmp !== void 0 ? tmp : "null";
3679
3679
  if (value.length - 1 > maximumBreadth) {
3680
3680
  const removedKeys = value.length - maximumBreadth - 1;
3681
- res += `${join2}"... ${getItemCount(removedKeys)} not stringified"`;
3681
+ res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
3682
3682
  }
3683
3683
  if (spacer !== "") {
3684
3684
  res += `
@@ -3691,7 +3691,7 @@ ${originalIndentation}`;
3691
3691
  let whitespace = "";
3692
3692
  if (spacer !== "") {
3693
3693
  indentation += spacer;
3694
- join2 = `,
3694
+ join3 = `,
3695
3695
  ${indentation}`;
3696
3696
  whitespace = " ";
3697
3697
  }
@@ -3700,7 +3700,7 @@ ${indentation}`;
3700
3700
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
3701
3701
  if (tmp !== void 0) {
3702
3702
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3703
- separator = join2;
3703
+ separator = join3;
3704
3704
  }
3705
3705
  }
3706
3706
  if (spacer !== "" && separator.length > 1) {
@@ -3758,20 +3758,20 @@ ${originalIndentation}`;
3758
3758
  indentation += spacer;
3759
3759
  let res2 = `
3760
3760
  ${indentation}`;
3761
- const join3 = `,
3761
+ const join4 = `,
3762
3762
  ${indentation}`;
3763
3763
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
3764
3764
  let i = 0;
3765
3765
  for (; i < maximumValuesToStringify - 1; i++) {
3766
3766
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3767
3767
  res2 += tmp2 !== void 0 ? tmp2 : "null";
3768
- res2 += join3;
3768
+ res2 += join4;
3769
3769
  }
3770
3770
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3771
3771
  res2 += tmp !== void 0 ? tmp : "null";
3772
3772
  if (value.length - 1 > maximumBreadth) {
3773
3773
  const removedKeys = value.length - maximumBreadth - 1;
3774
- res2 += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
3774
+ res2 += `${join4}"... ${getItemCount(removedKeys)} not stringified"`;
3775
3775
  }
3776
3776
  res2 += `
3777
3777
  ${originalIndentation}`;
@@ -3787,16 +3787,16 @@ ${originalIndentation}`;
3787
3787
  return '"[Object]"';
3788
3788
  }
3789
3789
  indentation += spacer;
3790
- const join2 = `,
3790
+ const join3 = `,
3791
3791
  ${indentation}`;
3792
3792
  let res = "";
3793
3793
  let separator = "";
3794
3794
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
3795
3795
  if (isTypedArrayWithEntries(value)) {
3796
- res += stringifyTypedArray(value, join2, maximumBreadth);
3796
+ res += stringifyTypedArray(value, join3, maximumBreadth);
3797
3797
  keys = keys.slice(value.length);
3798
3798
  maximumPropertiesToStringify -= value.length;
3799
- separator = join2;
3799
+ separator = join3;
3800
3800
  }
3801
3801
  if (deterministic) {
3802
3802
  keys = sort(keys, comparator);
@@ -3807,13 +3807,13 @@ ${indentation}`;
3807
3807
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
3808
3808
  if (tmp !== void 0) {
3809
3809
  res += `${separator}${strEscape(key2)}: ${tmp}`;
3810
- separator = join2;
3810
+ separator = join3;
3811
3811
  }
3812
3812
  }
3813
3813
  if (keyLength > maximumBreadth) {
3814
3814
  const removedKeys = keyLength - maximumBreadth;
3815
3815
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
3816
- separator = join2;
3816
+ separator = join3;
3817
3817
  }
3818
3818
  if (separator !== "") {
3819
3819
  res = `
@@ -4883,8 +4883,8 @@ var init_parseUtil = __esm({
4883
4883
  init_errors2();
4884
4884
  init_en();
4885
4885
  makeIssue = (params) => {
4886
- const { data, path: path23, errorMaps, issueData } = params;
4887
- const fullPath = [...path23, ...issueData.path || []];
4886
+ const { data, path: path21, errorMaps, issueData } = params;
4887
+ const fullPath = [...path21, ...issueData.path || []];
4888
4888
  const fullIssue = {
4889
4889
  ...issueData,
4890
4890
  path: fullPath
@@ -5195,11 +5195,11 @@ var init_types = __esm({
5195
5195
  init_parseUtil();
5196
5196
  init_util();
5197
5197
  ParseInputLazyPath = class {
5198
- constructor(parent, value, path23, key) {
5198
+ constructor(parent, value, path21, key) {
5199
5199
  this._cachedPath = [];
5200
5200
  this.parent = parent;
5201
5201
  this.data = value;
5202
- this._path = path23;
5202
+ this._path = path21;
5203
5203
  this._key = key;
5204
5204
  }
5205
5205
  get path() {
@@ -8583,32 +8583,25 @@ var init_zod = __esm({
8583
8583
  });
8584
8584
 
8585
8585
  // ../protocol/src/persona-schemas.ts
8586
- var ALLOWED_PERSONA_TOOLS, PersonaTokenEntrySchema, PersonaFileSchema, PersonaHelloFrameSchema, PersonaSendFrameSchema, PersonaResetFrameSchema, PersonaPingFrameSchema, PersonaReadyFrameSchema, PersonaHistoryEventFrameSchema, PersonaHistoryDoneFrameSchema, PersonaEventFrameSchema, PersonaErrorFrameSchema, PersonaPongFrameSchema, PersonaClientFrameSchema, PersonaServerFrameSchema, PersonaCreateArgs, PersonaIdArgs, PersonaUpdateArgs, PersonaIssueTokenArgs, PersonaRevokeTokenArgs, PersonaAppendOwnerMessageArgs;
8586
+ var PersonaTokenEntrySchema, PersonaFileSchema, PersonaHelloFrameSchema, PersonaSendFrameSchema, PersonaResetFrameSchema, PersonaPingFrameSchema, PersonaReadyFrameSchema, PersonaHistoryEventFrameSchema, PersonaHistoryDoneFrameSchema, PersonaEventFrameSchema, PersonaErrorFrameSchema, PersonaPongFrameSchema, PersonaClientFrameSchema, PersonaServerFrameSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema, PersonaIssueTokenArgsSchema, PersonaRevokeTokenArgsSchema, PersonaAppendOwnerMessageArgsSchema;
8587
8587
  var init_persona_schemas = __esm({
8588
8588
  "../protocol/src/persona-schemas.ts"() {
8589
8589
  "use strict";
8590
8590
  init_zod();
8591
- ALLOWED_PERSONA_TOOLS = ["Read", "Grep", "Glob"];
8592
8591
  PersonaTokenEntrySchema = external_exports.object({
8593
- label: external_exports.string().min(1),
8594
- issuedAt: external_exports.string(),
8595
- revoked: external_exports.boolean().optional()
8592
+ label: external_exports.string(),
8593
+ issuedAt: external_exports.number(),
8594
+ revoked: external_exports.boolean()
8596
8595
  });
8597
8596
  PersonaFileSchema = external_exports.object({
8598
- personaId: external_exports.string().min(1),
8599
- label: external_exports.string().min(1),
8600
- // cwd 必须是绝对路径;老板侧创建时 daemon 校验
8601
- cwd: external_exports.string().refine((p) => p.startsWith("/"), { message: "cwd must be absolute" }),
8597
+ personaId: external_exports.string(),
8598
+ label: external_exports.string(),
8602
8599
  model: external_exports.string().optional(),
8603
- systemPromptAppend: external_exports.string().optional(),
8604
- // L1 锁死:permissionMode 只能是 'plan',toolAllowlist 只能是 ALLOWED_PERSONA_TOOLS 子集
8605
- permissionMode: external_exports.literal("plan"),
8606
- toolAllowlist: external_exports.array(external_exports.enum(ALLOWED_PERSONA_TOOLS)),
8607
8600
  public: external_exports.boolean(),
8608
8601
  tokenMap: external_exports.record(external_exports.string(), PersonaTokenEntrySchema),
8609
- createdAt: external_exports.string(),
8610
- updatedAt: external_exports.string()
8611
- });
8602
+ createdAt: external_exports.number(),
8603
+ updatedAt: external_exports.number()
8604
+ }).strict();
8612
8605
  PersonaHelloFrameSchema = external_exports.object({
8613
8606
  kind: external_exports.literal("persona-hello"),
8614
8607
  token: external_exports.string().min(1)
@@ -8669,34 +8662,33 @@ var init_persona_schemas = __esm({
8669
8662
  PersonaErrorFrameSchema,
8670
8663
  PersonaPongFrameSchema
8671
8664
  ]);
8672
- PersonaCreateArgs = external_exports.object({
8665
+ PersonaCreateArgsSchema = external_exports.object({
8673
8666
  label: external_exports.string().min(1),
8674
- cwd: external_exports.string().min(1),
8667
+ personality: external_exports.string(),
8675
8668
  model: external_exports.string().optional(),
8676
- systemPromptAppend: external_exports.string().optional()
8677
- });
8678
- PersonaIdArgs = external_exports.object({
8669
+ public: external_exports.boolean().optional()
8670
+ }).strict();
8671
+ PersonaIdArgsSchema = external_exports.object({
8679
8672
  personaId: external_exports.string().min(1)
8680
8673
  });
8681
- PersonaUpdateArgs = external_exports.object({
8674
+ PersonaUpdateArgsSchema = external_exports.object({
8682
8675
  personaId: external_exports.string().min(1),
8683
8676
  patch: external_exports.object({
8684
8677
  label: external_exports.string().min(1).optional(),
8685
- cwd: external_exports.string().min(1).optional(),
8686
8678
  model: external_exports.string().optional(),
8687
- systemPromptAppend: external_exports.string().optional(),
8679
+ personality: external_exports.string().optional(),
8688
8680
  public: external_exports.boolean().optional()
8689
8681
  }).strict()
8690
- });
8691
- PersonaIssueTokenArgs = external_exports.object({
8682
+ }).strict();
8683
+ PersonaIssueTokenArgsSchema = external_exports.object({
8692
8684
  personaId: external_exports.string().min(1),
8693
8685
  label: external_exports.string().min(1)
8694
8686
  });
8695
- PersonaRevokeTokenArgs = external_exports.object({
8687
+ PersonaRevokeTokenArgsSchema = external_exports.object({
8696
8688
  personaId: external_exports.string().min(1),
8697
8689
  token: external_exports.string().min(1)
8698
8690
  });
8699
- PersonaAppendOwnerMessageArgs = external_exports.object({
8691
+ PersonaAppendOwnerMessageArgsSchema = external_exports.object({
8700
8692
  personaId: external_exports.string().min(1),
8701
8693
  subSessionId: external_exports.string().min(1),
8702
8694
  text: external_exports.string().min(1)
@@ -9828,11 +9820,11 @@ var init_lib = __esm({
9828
9820
  }
9829
9821
  }
9830
9822
  },
9831
- addToPath: function addToPath(path23, added, removed, oldPosInc, options) {
9832
- var last = path23.lastComponent;
9823
+ addToPath: function addToPath(path21, added, removed, oldPosInc, options) {
9824
+ var last = path21.lastComponent;
9833
9825
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
9834
9826
  return {
9835
- oldPos: path23.oldPos + oldPosInc,
9827
+ oldPos: path21.oldPos + oldPosInc,
9836
9828
  lastComponent: {
9837
9829
  count: last.count + 1,
9838
9830
  added,
@@ -9842,7 +9834,7 @@ var init_lib = __esm({
9842
9834
  };
9843
9835
  } else {
9844
9836
  return {
9845
- oldPos: path23.oldPos + oldPosInc,
9837
+ oldPos: path21.oldPos + oldPosInc,
9846
9838
  lastComponent: {
9847
9839
  count: 1,
9848
9840
  added,
@@ -9900,7 +9892,7 @@ var init_lib = __esm({
9900
9892
  tokenize: function tokenize(value) {
9901
9893
  return Array.from(value);
9902
9894
  },
9903
- join: function join(chars) {
9895
+ join: function join2(chars) {
9904
9896
  return chars.join("");
9905
9897
  },
9906
9898
  postProcess: function postProcess(changeObjects) {
@@ -10088,7 +10080,7 @@ function hashDirToCwd(hash) {
10088
10080
  }
10089
10081
  function safeStatMtime(p) {
10090
10082
  try {
10091
- return import_node_fs8.default.statSync(p).mtimeMs;
10083
+ return import_node_fs6.default.statSync(p).mtimeMs;
10092
10084
  } catch {
10093
10085
  return 0;
10094
10086
  }
@@ -10096,7 +10088,7 @@ function safeStatMtime(p) {
10096
10088
  function readJsonlLines(file) {
10097
10089
  let raw;
10098
10090
  try {
10099
- raw = import_node_fs8.default.readFileSync(file, "utf8");
10091
+ raw = import_node_fs6.default.readFileSync(file, "utf8");
10100
10092
  } catch (err) {
10101
10093
  if (err.code === "ENOENT") return [];
10102
10094
  throw err;
@@ -10273,10 +10265,10 @@ function attachmentToHistoryMessage(o, ts) {
10273
10265
  const memories = raw.map((m) => {
10274
10266
  if (!m || typeof m !== "object") return null;
10275
10267
  const rec = m;
10276
- const path23 = typeof rec.path === "string" ? rec.path : null;
10268
+ const path21 = typeof rec.path === "string" ? rec.path : null;
10277
10269
  const content = typeof rec.content === "string" ? rec.content : null;
10278
- if (!path23 || content == null) return null;
10279
- const entry = { path: path23, content };
10270
+ if (!path21 || content == null) return null;
10271
+ const entry = { path: path21, content };
10280
10272
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10281
10273
  return entry;
10282
10274
  }).filter((m) => m !== null);
@@ -10312,8 +10304,8 @@ function attachmentDeferredToolsText(a) {
10312
10304
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
10313
10305
  if (backupFileName === null) return null;
10314
10306
  try {
10315
- return import_node_fs8.default.readFileSync(
10316
- import_node_path8.default.join(fileHistoryRoot, toolSessionId, backupFileName),
10307
+ return import_node_fs6.default.readFileSync(
10308
+ import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
10317
10309
  "utf8"
10318
10310
  );
10319
10311
  } catch {
@@ -10322,19 +10314,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
10322
10314
  }
10323
10315
  function readCurrentContent(filePath) {
10324
10316
  try {
10325
- return import_node_fs8.default.readFileSync(filePath, "utf8");
10317
+ return import_node_fs6.default.readFileSync(filePath, "utf8");
10326
10318
  } catch (err) {
10327
10319
  if (err.code === "ENOENT") return null;
10328
10320
  return null;
10329
10321
  }
10330
10322
  }
10331
- var import_node_fs8, import_node_os2, import_node_path8, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
10323
+ var import_node_fs6, import_node_os2, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
10332
10324
  var init_claude_history = __esm({
10333
10325
  "src/tools/claude-history.ts"() {
10334
10326
  "use strict";
10335
- import_node_fs8 = __toESM(require("fs"), 1);
10327
+ import_node_fs6 = __toESM(require("fs"), 1);
10336
10328
  import_node_os2 = __toESM(require("os"), 1);
10337
- import_node_path8 = __toESM(require("path"), 1);
10329
+ import_node_path5 = __toESM(require("path"), 1);
10338
10330
  init_lib();
10339
10331
  init_tool_result_extra();
10340
10332
  TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
@@ -10358,14 +10350,14 @@ var init_claude_history = __esm({
10358
10350
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
10359
10351
  fileHistoryRoot;
10360
10352
  constructor(opts = {}) {
10361
- const base = opts.baseDir ?? import_node_path8.default.join(import_node_os2.default.homedir(), ".claude");
10362
- this.projectsRoot = import_node_path8.default.join(base, "projects");
10363
- this.fileHistoryRoot = import_node_path8.default.join(base, "file-history");
10353
+ const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
10354
+ this.projectsRoot = import_node_path5.default.join(base, "projects");
10355
+ this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
10364
10356
  }
10365
10357
  async listProjects() {
10366
10358
  let entries;
10367
10359
  try {
10368
- entries = import_node_fs8.default.readdirSync(this.projectsRoot, { withFileTypes: true });
10360
+ entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
10369
10361
  } catch (err) {
10370
10362
  if (err.code === "ENOENT") return [];
10371
10363
  throw err;
@@ -10373,9 +10365,9 @@ var init_claude_history = __esm({
10373
10365
  const out = [];
10374
10366
  for (const ent of entries) {
10375
10367
  if (!ent.isDirectory()) continue;
10376
- const dir = import_node_path8.default.join(this.projectsRoot, ent.name);
10377
- const files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
10378
- const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path8.default.join(dir, f))), 0);
10368
+ const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
10369
+ const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
10370
+ const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
10379
10371
  out.push({
10380
10372
  projectPath: hashDirToCwd(ent.name),
10381
10373
  hashDir: ent.name,
@@ -10387,17 +10379,17 @@ var init_claude_history = __esm({
10387
10379
  return out;
10388
10380
  }
10389
10381
  async listSessions(args) {
10390
- const dir = import_node_path8.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
10382
+ const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
10391
10383
  let files;
10392
10384
  try {
10393
- files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
10385
+ files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
10394
10386
  } catch (err) {
10395
10387
  if (err.code === "ENOENT") return [];
10396
10388
  throw err;
10397
10389
  }
10398
10390
  const out = [];
10399
10391
  for (const f of files) {
10400
- const full = import_node_path8.default.join(dir, f);
10392
+ const full = import_node_path5.default.join(dir, f);
10401
10393
  const toolSessionId = f.slice(0, -".jsonl".length);
10402
10394
  const lines = readJsonlLines(full);
10403
10395
  let summary = "";
@@ -10452,7 +10444,7 @@ var init_claude_history = __esm({
10452
10444
  return out;
10453
10445
  }
10454
10446
  async read(args) {
10455
- const file = import_node_path8.default.join(
10447
+ const file = import_node_path5.default.join(
10456
10448
  this.projectsRoot,
10457
10449
  cwdToHashDir(args.cwd),
10458
10450
  `${args.toolSessionId}.jsonl`
@@ -10485,7 +10477,7 @@ var init_claude_history = __esm({
10485
10477
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
10486
10478
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
10487
10479
  listSubagentsFromDirectory(cwd, toolSessionId) {
10488
- const dir = import_node_path8.default.join(
10480
+ const dir = import_node_path5.default.join(
10489
10481
  this.projectsRoot,
10490
10482
  cwdToHashDir(cwd),
10491
10483
  toolSessionId,
@@ -10493,7 +10485,7 @@ var init_claude_history = __esm({
10493
10485
  );
10494
10486
  let entries;
10495
10487
  try {
10496
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
10488
+ entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
10497
10489
  } catch (err) {
10498
10490
  if (err.code === "ENOENT") return null;
10499
10491
  return null;
@@ -10503,7 +10495,7 @@ var init_claude_history = __esm({
10503
10495
  if (!e.isFile()) continue;
10504
10496
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
10505
10497
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
10506
- const filePath = import_node_path8.default.join(dir, e.name);
10498
+ const filePath = import_node_path5.default.join(dir, e.name);
10507
10499
  const lines = readJsonlLines(filePath);
10508
10500
  let firstText = "";
10509
10501
  let messageCount = 0;
@@ -10520,7 +10512,7 @@ var init_claude_history = __esm({
10520
10512
  return out;
10521
10513
  }
10522
10514
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
10523
- const file = import_node_path8.default.join(
10515
+ const file = import_node_path5.default.join(
10524
10516
  this.projectsRoot,
10525
10517
  cwdToHashDir(cwd),
10526
10518
  `${toolSessionId}.jsonl`
@@ -10555,7 +10547,7 @@ var init_claude_history = __esm({
10555
10547
  }
10556
10548
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
10557
10549
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
10558
- const file = import_node_path8.default.join(
10550
+ const file = import_node_path5.default.join(
10559
10551
  this.projectsRoot,
10560
10552
  cwdToHashDir(cwd),
10561
10553
  toolSessionId,
@@ -10564,7 +10556,7 @@ var init_claude_history = __esm({
10564
10556
  );
10565
10557
  let exists = false;
10566
10558
  try {
10567
- exists = import_node_fs8.default.statSync(file).isFile();
10559
+ exists = import_node_fs6.default.statSync(file).isFile();
10568
10560
  } catch {
10569
10561
  return null;
10570
10562
  }
@@ -10583,7 +10575,7 @@ var init_claude_history = __esm({
10583
10575
  * "那一刻每个 tracked 文件对应的 backup 文件名"
10584
10576
  */
10585
10577
  readFileHistorySnapshots(args) {
10586
- const file = import_node_path8.default.join(
10578
+ const file = import_node_path5.default.join(
10587
10579
  this.projectsRoot,
10588
10580
  cwdToHashDir(args.cwd),
10589
10581
  `${args.toolSessionId}.jsonl`
@@ -10628,7 +10620,7 @@ var init_claude_history = __esm({
10628
10620
  for (const [anchorId, target] of snapshots) {
10629
10621
  let hasAny = false;
10630
10622
  for (const [rawPath, backup] of Object.entries(target)) {
10631
- const absPath = import_node_path8.default.isAbsolute(rawPath) ? rawPath : import_node_path8.default.join(args.cwd, rawPath);
10623
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
10632
10624
  const backupContent = readBackupContent(
10633
10625
  this.fileHistoryRoot,
10634
10626
  args.toolSessionId,
@@ -10668,7 +10660,7 @@ var init_claude_history = __esm({
10668
10660
  let totalInsertions = 0;
10669
10661
  let totalDeletions = 0;
10670
10662
  for (const [rawPath, backup] of Object.entries(target)) {
10671
- const absPath = import_node_path8.default.isAbsolute(rawPath) ? rawPath : import_node_path8.default.join(args.cwd, rawPath);
10663
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
10672
10664
  const backupContent = readBackupContent(
10673
10665
  this.fileHistoryRoot,
10674
10666
  args.toolSessionId,
@@ -10715,7 +10707,7 @@ var init_claude_history = __esm({
10715
10707
  };
10716
10708
  }
10717
10709
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
10718
- const file = import_node_path8.default.join(
10710
+ const file = import_node_path5.default.join(
10719
10711
  this.projectsRoot,
10720
10712
  cwdToHashDir(cwd),
10721
10713
  `${toolSessionId}.jsonl`
@@ -10739,27 +10731,27 @@ var init_claude_history = __esm({
10739
10731
  // src/tools/claude.ts
10740
10732
  function macOSDesktopCandidates(home) {
10741
10733
  return [
10742
- import_node_path9.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
10734
+ import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
10743
10735
  "/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
10744
10736
  ];
10745
10737
  }
10746
10738
  function probeViaWhich() {
10747
10739
  try {
10748
10740
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
10749
- if (out && import_node_fs9.default.existsSync(out)) return out;
10741
+ if (out && import_node_fs7.default.existsSync(out)) return out;
10750
10742
  } catch {
10751
10743
  }
10752
10744
  return null;
10753
10745
  }
10754
10746
  async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
10755
- if (env.CLAUDE_BIN && import_node_fs9.default.existsSync(env.CLAUDE_BIN)) {
10747
+ if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
10756
10748
  return { available: true, path: env.CLAUDE_BIN };
10757
10749
  }
10758
10750
  const w = probeViaWhich();
10759
10751
  if (w) return { available: true, path: w };
10760
10752
  if (process.platform === "darwin") {
10761
10753
  for (const candidate of macOSDesktopCandidates(home)) {
10762
- if (import_node_fs9.default.existsSync(candidate)) {
10754
+ if (import_node_fs7.default.existsSync(candidate)) {
10763
10755
  return { available: true, path: candidate };
10764
10756
  }
10765
10757
  }
@@ -10784,11 +10776,8 @@ function buildSpawnArgs(ctx) {
10784
10776
  "--verbose"
10785
10777
  ];
10786
10778
  if (ctx.model) args.push("--model", ctx.model);
10787
- const hardcoded = ctx.hardcodedToolAllowlist && ctx.hardcodedToolAllowlist.length > 0;
10788
- if (hardcoded) {
10789
- args.push("--permission-mode", ctx.hardcodedPermissionMode ?? "plan");
10790
- args.push("--add-dir", ctx.cwd);
10791
- args.push("--disallowed-tools", HARDCODED_DISALLOWED_TOOLS.join(" "));
10779
+ if (ctx.personaMode) {
10780
+ args.push("--setting-sources", "project,local");
10792
10781
  } else if (ctx.permissionMode) {
10793
10782
  args.push("--permission-mode", ctx.permissionMode);
10794
10783
  }
@@ -11070,10 +11059,10 @@ function parseAttachment(obj) {
11070
11059
  const memories = raw.map((m) => {
11071
11060
  if (!m || typeof m !== "object") return null;
11072
11061
  const rec = m;
11073
- const path23 = typeof rec.path === "string" ? rec.path : null;
11062
+ const path21 = typeof rec.path === "string" ? rec.path : null;
11074
11063
  const content = typeof rec.content === "string" ? rec.content : null;
11075
- if (!path23 || content == null) return null;
11076
- const out = { path: path23, content };
11064
+ if (!path21 || content == null) return null;
11065
+ const out = { path: path21, content };
11077
11066
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11078
11067
  return out;
11079
11068
  }).filter((m) => m !== null);
@@ -11177,19 +11166,18 @@ function encodeClaudeStdin(text) {
11177
11166
  };
11178
11167
  return JSON.stringify(frame) + "\n";
11179
11168
  }
11180
- var import_node_child_process, import_node_child_process2, import_node_fs9, import_node_os3, import_node_path9, HARDCODED_DISALLOWED_TOOLS, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
11169
+ var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3, import_node_path6, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
11181
11170
  var init_claude = __esm({
11182
11171
  "src/tools/claude.ts"() {
11183
11172
  "use strict";
11184
11173
  import_node_child_process = require("child_process");
11185
11174
  import_node_child_process2 = require("child_process");
11186
- import_node_fs9 = __toESM(require("fs"), 1);
11175
+ import_node_fs7 = __toESM(require("fs"), 1);
11187
11176
  import_node_os3 = __toESM(require("os"), 1);
11188
- import_node_path9 = __toESM(require("path"), 1);
11177
+ import_node_path6 = __toESM(require("path"), 1);
11189
11178
  init_protocol();
11190
11179
  init_claude_history();
11191
11180
  init_tool_result_extra();
11192
- HARDCODED_DISALLOWED_TOOLS = ["Bash", "Edit", "Write", "WebFetch", "WebSearch", "Task"];
11193
11181
  ATTACHMENT_SILENT_SUBTYPES2 = /* @__PURE__ */ new Set([
11194
11182
  "hook_additional_context",
11195
11183
  "hook_success",
@@ -14941,7 +14929,7 @@ var require_websocket_server = __commonJS({
14941
14929
  // src/run-case/recorder.ts
14942
14930
  function startRunCaseRecorder(opts) {
14943
14931
  const now = opts.now ?? Date.now;
14944
- const dir = import_node_path21.default.dirname(opts.recordPath);
14932
+ const dir = import_node_path18.default.dirname(opts.recordPath);
14945
14933
  let stream = null;
14946
14934
  let closing = false;
14947
14935
  let closedSettled = false;
@@ -14955,8 +14943,8 @@ function startRunCaseRecorder(opts) {
14955
14943
  });
14956
14944
  const ensureStream = () => {
14957
14945
  if (stream) return stream;
14958
- import_node_fs21.default.mkdirSync(dir, { recursive: true });
14959
- stream = import_node_fs21.default.createWriteStream(opts.recordPath, { flags: "a" });
14946
+ import_node_fs19.default.mkdirSync(dir, { recursive: true });
14947
+ stream = import_node_fs19.default.createWriteStream(opts.recordPath, { flags: "a" });
14960
14948
  stream.on("close", () => closedResolve());
14961
14949
  return stream;
14962
14950
  };
@@ -14981,12 +14969,12 @@ function startRunCaseRecorder(opts) {
14981
14969
  };
14982
14970
  return { tap, close, closed };
14983
14971
  }
14984
- var import_node_fs21, import_node_path21;
14972
+ var import_node_fs19, import_node_path18;
14985
14973
  var init_recorder = __esm({
14986
14974
  "src/run-case/recorder.ts"() {
14987
14975
  "use strict";
14988
- import_node_fs21 = __toESM(require("fs"), 1);
14989
- import_node_path21 = __toESM(require("path"), 1);
14976
+ import_node_fs19 = __toESM(require("fs"), 1);
14977
+ import_node_path18 = __toESM(require("path"), 1);
14990
14978
  }
14991
14979
  });
14992
14980
 
@@ -15029,7 +15017,7 @@ var init_wire = __esm({
15029
15017
  // src/run-case/controller.ts
15030
15018
  async function runController(opts) {
15031
15019
  const now = opts.now ?? Date.now;
15032
- const cwd = opts.cwd ?? (0, import_node_fs22.mkdtempSync)(import_node_path22.default.join(import_node_os12.default.tmpdir(), "clawd-runcase-"));
15020
+ const cwd = opts.cwd ?? (0, import_node_fs20.mkdtempSync)(import_node_path19.default.join(import_node_os12.default.tmpdir(), "clawd-runcase-"));
15033
15021
  const ownsCwd = opts.cwd === void 0;
15034
15022
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
15035
15023
  const spawnCtx = { cwd };
@@ -15190,19 +15178,19 @@ async function runController(opts) {
15190
15178
  if (sigintHandler) process.off("SIGINT", sigintHandler);
15191
15179
  if (ownsCwd) {
15192
15180
  try {
15193
- (0, import_node_fs22.rmSync)(cwd, { recursive: true, force: true });
15181
+ (0, import_node_fs20.rmSync)(cwd, { recursive: true, force: true });
15194
15182
  } catch {
15195
15183
  }
15196
15184
  }
15197
15185
  return exitCode ?? 0;
15198
15186
  }
15199
- var import_node_fs22, import_node_os12, import_node_path22;
15187
+ var import_node_fs20, import_node_os12, import_node_path19;
15200
15188
  var init_controller = __esm({
15201
15189
  "src/run-case/controller.ts"() {
15202
15190
  "use strict";
15203
- import_node_fs22 = require("fs");
15191
+ import_node_fs20 = require("fs");
15204
15192
  import_node_os12 = __toESM(require("os"), 1);
15205
- import_node_path22 = __toESM(require("path"), 1);
15193
+ import_node_path19 = __toESM(require("path"), 1);
15206
15194
  init_claude();
15207
15195
  init_stdout_splitter();
15208
15196
  init_permission_stdio();
@@ -15427,8 +15415,8 @@ Env (advanced):
15427
15415
  `;
15428
15416
 
15429
15417
  // src/index.ts
15430
- var import_node_path20 = __toESM(require("path"), 1);
15431
- var import_node_fs20 = __toESM(require("fs"), 1);
15418
+ var import_node_path17 = __toESM(require("path"), 1);
15419
+ var import_node_fs18 = __toESM(require("fs"), 1);
15432
15420
 
15433
15421
  // src/logger.ts
15434
15422
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -15482,7 +15470,16 @@ var SessionStore = class {
15482
15470
  root;
15483
15471
  constructor(opts) {
15484
15472
  const agentId = opts.agentId ?? DEFAULT_AGENT_ID;
15485
- this.root = import_node_path3.default.join(opts.dataDir, "sessions", agentId);
15473
+ if (agentId !== DEFAULT_AGENT_ID) {
15474
+ if (!opts.personaRoot) {
15475
+ throw new Error(
15476
+ `SessionStore: personaRoot is required for non-default agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionStore for persona agents.`
15477
+ );
15478
+ }
15479
+ this.root = import_node_path3.default.join(opts.personaRoot, safeFileName(agentId), ".clawd", "sub-sessions");
15480
+ } else {
15481
+ this.root = import_node_path3.default.join(opts.dataDir, "sessions", agentId);
15482
+ }
15486
15483
  }
15487
15484
  filePath(sessionId) {
15488
15485
  return import_node_path3.default.join(this.root, `${safeFileName(sessionId)}.json`);
@@ -15694,9 +15691,8 @@ function buildSpawnContext(state) {
15694
15691
  effort: file.effort
15695
15692
  };
15696
15693
  const meta = state.subSessionMeta;
15697
- if (meta?.toolAllowlist && meta.toolAllowlist.length > 0) {
15698
- ctx.hardcodedToolAllowlist = meta.toolAllowlist;
15699
- ctx.hardcodedPermissionMode = meta.permissionMode ?? "plan";
15694
+ if (meta?.personaMode) {
15695
+ ctx.personaMode = true;
15700
15696
  }
15701
15697
  return ctx;
15702
15698
  }
@@ -16266,19 +16262,6 @@ function startRecorder(opts) {
16266
16262
  };
16267
16263
  }
16268
16264
 
16269
- // src/tools/cwd-boundary.ts
16270
- var import_node_path5 = __toESM(require("path"), 1);
16271
- function isPathInsideCwd(cwd, target) {
16272
- if (!import_node_path5.default.isAbsolute(target)) return false;
16273
- const cwdNorm = import_node_path5.default.resolve(cwd);
16274
- const targetNorm = import_node_path5.default.resolve(target);
16275
- if (cwdNorm === targetNorm) return true;
16276
- const rel = import_node_path5.default.relative(cwdNorm, targetNorm);
16277
- if (rel.startsWith("..")) return false;
16278
- if (import_node_path5.default.isAbsolute(rel)) return false;
16279
- return true;
16280
- }
16281
-
16282
16265
  // src/session/runner.ts
16283
16266
  var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
16284
16267
  function encodeAllowWithInputControlResponse(requestId, updatedInput) {
@@ -16296,15 +16279,6 @@ function encodeAllowWithInputControlResponse(requestId, updatedInput) {
16296
16279
  return JSON.stringify(payload) + "\n";
16297
16280
  }
16298
16281
  var DEFAULT_WAIT_STOP_TIMEOUT_MS = 3e3;
16299
- function extractToolPath(ev) {
16300
- const input = ev.input;
16301
- if (!input || typeof input !== "object") return void 0;
16302
- const inp = input;
16303
- if (ev.tool === "Read" && typeof inp.file_path === "string") return inp.file_path;
16304
- if (ev.tool === "Grep" && typeof inp.path === "string") return inp.path;
16305
- if (ev.tool === "Glob" && typeof inp.path === "string") return inp.path;
16306
- return void 0;
16307
- }
16308
16282
  var SessionRunner = class {
16309
16283
  constructor(initial, hooks) {
16310
16284
  this.hooks = hooks;
@@ -16420,62 +16394,6 @@ var SessionRunner = class {
16420
16394
  }
16421
16395
  });
16422
16396
  }
16423
- // L1 锁定(task 14)拦截:仅 sub-session(state.subSessionMeta.toolAllowlist 非空)启用。
16424
- // 1. 解析 line 为 ParsedEvent[],扫 'tool_call' kind
16425
- // 2. tool 名不在白名单 → emit session:event(kind='error') + SIGKILL,丢弃本行
16426
- // 3. tool input 里带 path 字段(Read.file_path / Grep.path / Glob.path)越出 cwd 子树 → 同上处理
16427
- // 命中返回 true,调用方不再喂 reducer;命中即 SIGKILL,CC 进程会触发 proc.on('exit')
16428
- // 走正常的 stop / proc-exit 流程。本拦截层与 buildSpawnArgs 的 --disallowed-tools / --add-dir
16429
- // 共同构成 L1 第二 / 第三层防御(schema 层 + manager 层 + claude CLI 层 + runner 拦截层)
16430
- tryInterceptL1Violation(line) {
16431
- const meta = this.state.subSessionMeta;
16432
- if (!meta?.toolAllowlist || meta.toolAllowlist.length === 0) return false;
16433
- const allowed = new Set(meta.toolAllowlist);
16434
- let events;
16435
- try {
16436
- events = this.hooks.adapter.parseLine(line);
16437
- } catch {
16438
- return false;
16439
- }
16440
- if (events.length === 0) return false;
16441
- const cwd = this.state.file.cwd;
16442
- for (const ev of events) {
16443
- if (ev.kind !== "tool_call") continue;
16444
- if (typeof ev.tool === "string" && ev.tool && !allowed.has(ev.tool)) {
16445
- this.emitL1Error(`tool ${ev.tool} blocked by L1 lockdown`, "TOOL_NOT_ALLOWED");
16446
- this.doKill("SIGKILL");
16447
- return true;
16448
- }
16449
- const argPath = extractToolPath(ev);
16450
- if (argPath && !isPathInsideCwd(cwd, argPath)) {
16451
- this.emitL1Error(
16452
- `path ${argPath} outside cwd ${cwd}`,
16453
- "PATH_OUT_OF_BOUND"
16454
- );
16455
- this.doKill("SIGKILL");
16456
- return true;
16457
- }
16458
- }
16459
- return false;
16460
- }
16461
- // L1 违规错误帧:走 session:event 通道,code 编码进 ParsedEvent.error message。
16462
- // 不引入新的 wire 帧 type(避免 protocol 改动),现有 error kind 已经走 broadcast 路径
16463
- emitL1Error(message, code) {
16464
- const errEvent = {
16465
- kind: "error",
16466
- message: `[${code}] ${message}`
16467
- };
16468
- const frame = {
16469
- type: "session:event",
16470
- sessionId: this.state.file.sessionId,
16471
- event: errEvent
16472
- };
16473
- try {
16474
- this.hooks.broadcastFrame(frame, "broadcast");
16475
- } catch {
16476
- }
16477
- this.hooks.logger?.warn("clawd-l1-violation", { code, message, sessionId: this.state.file.sessionId });
16478
- }
16479
16397
  // 尝试把一行 stdout 解析成 `type:"control_response"` 帧并 resolve 匹配的 pending。
16480
16398
  // 命中返回 true —— 调用方不再把该行喂给 reducer(control_response 不是会话事件)。
16481
16399
  tryHandleControlResponse(line) {
@@ -16598,7 +16516,6 @@ var SessionRunner = class {
16598
16516
  this.stdoutBuf = newBuf;
16599
16517
  for (const line of lines) {
16600
16518
  if (this.tryHandleControlResponse(line)) continue;
16601
- if (this.tryInterceptL1Violation(line)) continue;
16602
16519
  this.input({ kind: "stdout-line", line });
16603
16520
  }
16604
16521
  });
@@ -16730,15 +16647,21 @@ var SessionManager = class {
16730
16647
  // 仅推 reducer 产出的 'session:event' 帧里的 ParsedEvent,其他帧(status / info / cleared)
16731
16648
  // 由调用方按需自行处理(persona-bound 简化协议只暴露 event 流,不需要这些)
16732
16649
  eventSubscribers = /* @__PURE__ */ new Map();
16733
- // 按 agentId 拿对应的 SessionStore;persona sub-session 走这条路径写到
16734
- // sessions/<personaId>/<sessionId>.json。需要 deps.dataDir 同源,否则脑裂
16650
+ // 按 agentId 拿对应的 SessionStore;persona-* agentId 使用 personaRoot 路径。
16651
+ // 'default' 直接复用 deps.store;其它 agentId 第一次访问时按需创建并缓存。
16652
+ // personaRoot 必须与 PersonaStore 同源,两者共享相同的 persona 目录层级
16735
16653
  storeFor(agentId) {
16736
16654
  const cached = this.storesByAgent.get(agentId);
16737
16655
  if (cached) return cached;
16738
16656
  if (!this.deps.dataDir) {
16739
16657
  throw new Error(`SessionManager: dataDir required to route agentId='${agentId}'`);
16740
16658
  }
16741
- const st = new SessionStore({ dataDir: this.deps.dataDir, agentId });
16659
+ if (!this.deps.personaRoot) {
16660
+ throw new Error(
16661
+ `SessionManager: personaRoot is required to route agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionManager for persona sub-sessions.`
16662
+ );
16663
+ }
16664
+ const st = new SessionStore({ dataDir: this.deps.dataDir, agentId, personaRoot: this.deps.personaRoot });
16742
16665
  this.storesByAgent.set(agentId, st);
16743
16666
  return st;
16744
16667
  }
@@ -17243,7 +17166,7 @@ var SessionManager = class {
17243
17166
  //
17244
17167
  // PersonaManager 是 SessionManager 之上的薄编排层,sub-session 的持久化(SessionFile)
17245
17168
  // 仍由 SessionManager 持有。区别于普通 session:
17246
- // - SessionFile 落到 sessions/<personaId>/ 而非 sessions/default/
17169
+ // - SessionFile 落到 <personaRoot>/<personaId>/.clawd/sub-sessions/ 而非 sessions/default/
17247
17170
  // - reducer state.subSessionMeta.idleKillEnabled = true(turn_end 自动 idle-kill)
17248
17171
  // - sessionId 由 PersonaManager 派生(personaId-<tokenHash>),不走自动 newSessionId
17249
17172
  /** 按 agentId 读取 SessionFile;不存在返回 null */
@@ -17287,15 +17210,8 @@ var SessionManager = class {
17287
17210
  updatedAt: iso
17288
17211
  };
17289
17212
  const written = store.write(file);
17290
- if (args.subSessionMeta || args.hardcodedToolAllowlist) {
17291
- const meta = {
17292
- idleKillEnabled: args.subSessionMeta?.idleKillEnabled ?? false,
17293
- ...args.hardcodedToolAllowlist && args.hardcodedToolAllowlist.length > 0 ? {
17294
- toolAllowlist: args.hardcodedToolAllowlist,
17295
- permissionMode: args.permissionMode
17296
- } : {}
17297
- };
17298
- this.subSessionMetaBySid.set(args.sessionId, meta);
17213
+ if (args.subSessionMeta) {
17214
+ this.subSessionMetaBySid.set(args.sessionId, args.subSessionMeta);
17299
17215
  }
17300
17216
  return written;
17301
17217
  }
@@ -17482,59 +17398,89 @@ var SessionManager = class {
17482
17398
  };
17483
17399
 
17484
17400
  // src/persona/store.ts
17485
- var import_node_fs6 = __toESM(require("fs"), 1);
17486
- var import_node_path6 = __toESM(require("path"), 1);
17401
+ var fs6 = __toESM(require("fs"), 1);
17402
+ var path5 = __toESM(require("path"), 1);
17487
17403
  init_protocol();
17404
+ var DEFAULT_SETTINGS = {
17405
+ permissions: {
17406
+ // silent-deny for tools accessing outside cwd — no permission prompt shown to persona
17407
+ defaultMode: "dontAsk"
17408
+ },
17409
+ sandbox: {
17410
+ enabled: true,
17411
+ // sandboxed Bash auto-runs without prompting the user
17412
+ autoAllowBashIfSandboxed: true,
17413
+ // prevents CC from retrying denied commands with dangerouslyDisableSandbox: true
17414
+ allowUnsandboxedCommands: false,
17415
+ filesystem: {
17416
+ // deny home dir explicitly; default sandbox allows all reads, only limits writes to cwd
17417
+ denyRead: ["~/"],
17418
+ allowRead: ["."],
17419
+ denyWrite: ["~/"],
17420
+ allowWrite: ["."]
17421
+ }
17422
+ }
17423
+ };
17488
17424
  var PersonaStore = class {
17425
+ constructor(root) {
17426
+ this.root = root;
17427
+ fs6.mkdirSync(root, { recursive: true });
17428
+ }
17489
17429
  root;
17490
- constructor(opts) {
17491
- this.root = import_node_path6.default.join(opts.dataDir, "personas");
17430
+ personaDir(personaId) {
17431
+ return path5.join(this.root, safeFileName(personaId));
17492
17432
  }
17493
- filePath(personaId) {
17494
- return import_node_path6.default.join(this.root, `${safeFileName(personaId)}.json`);
17433
+ metaPath(personaId) {
17434
+ return path5.join(this.personaDir(personaId), ".clawd", "persona.json");
17495
17435
  }
17496
- ensureDir() {
17497
- import_node_fs6.default.mkdirSync(this.root, { recursive: true });
17436
+ claudeMdPath(personaId) {
17437
+ return path5.join(this.personaDir(personaId), "CLAUDE.md");
17498
17438
  }
17499
- read(personaId) {
17500
- try {
17501
- const raw = import_node_fs6.default.readFileSync(this.filePath(personaId), "utf8");
17502
- return PersonaFileSchema.parse(JSON.parse(raw));
17503
- } catch (err) {
17504
- const code = err?.code;
17505
- if (code === "ENOENT") return null;
17506
- return null;
17507
- }
17439
+ settingsPath(personaId) {
17440
+ return path5.join(this.personaDir(personaId), ".claude", "settings.json");
17508
17441
  }
17509
- write(file) {
17510
- const validated = PersonaFileSchema.parse(file);
17511
- this.ensureDir();
17512
- const target = this.filePath(validated.personaId);
17513
- const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
17514
- import_node_fs6.default.writeFileSync(tmp, JSON.stringify(validated, null, 2), { encoding: "utf8", mode: 384 });
17515
- import_node_fs6.default.renameSync(tmp, target);
17516
- return validated;
17442
+ write(persona, personality) {
17443
+ const dir = this.personaDir(persona.personaId);
17444
+ fs6.mkdirSync(path5.join(dir, ".claude"), { recursive: true });
17445
+ fs6.mkdirSync(path5.join(dir, ".clawd"), { recursive: true });
17446
+ this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
17447
+ this.atomicWrite(this.settingsPath(persona.personaId), JSON.stringify(DEFAULT_SETTINGS, null, 2));
17448
+ this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
17517
17449
  }
17518
- delete(personaId) {
17519
- try {
17520
- import_node_fs6.default.unlinkSync(this.filePath(personaId));
17521
- } catch (err) {
17522
- const code = err?.code;
17523
- if (code !== "ENOENT") throw err;
17524
- }
17450
+ writePersonality(personaId, personality) {
17451
+ this.atomicWrite(this.claudeMdPath(personaId), personality);
17452
+ }
17453
+ writeMeta(persona) {
17454
+ this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
17455
+ }
17456
+ read(personaId) {
17457
+ const p = this.metaPath(personaId);
17458
+ if (!fs6.existsSync(p)) return null;
17459
+ const raw = JSON.parse(fs6.readFileSync(p, "utf8"));
17460
+ return PersonaFileSchema.parse(raw);
17461
+ }
17462
+ readPersonality(personaId) {
17463
+ const p = this.claudeMdPath(personaId);
17464
+ if (!fs6.existsSync(p)) return null;
17465
+ return fs6.readFileSync(p, "utf8");
17525
17466
  }
17526
17467
  list() {
17527
- if (!import_node_fs6.default.existsSync(this.root)) return [];
17528
- const files = import_node_fs6.default.readdirSync(this.root).filter((f) => f.endsWith(".json") && !f.includes(".tmp"));
17529
- const items = [];
17530
- for (const f of files) {
17531
- try {
17532
- const raw = import_node_fs6.default.readFileSync(import_node_path6.default.join(this.root, f), "utf8");
17533
- items.push(PersonaFileSchema.parse(JSON.parse(raw)));
17534
- } catch {
17535
- }
17536
- }
17537
- return items.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
17468
+ if (!fs6.existsSync(this.root)) return [];
17469
+ return fs6.readdirSync(this.root).filter((name) => {
17470
+ return fs6.existsSync(path5.join(this.root, name, ".clawd", "persona.json"));
17471
+ });
17472
+ }
17473
+ remove(personaId) {
17474
+ const dir = this.personaDir(personaId);
17475
+ if (fs6.existsSync(dir)) fs6.rmSync(dir, { recursive: true, force: true });
17476
+ }
17477
+ personaDirPath(personaId) {
17478
+ return this.personaDir(personaId);
17479
+ }
17480
+ atomicWrite(file, content) {
17481
+ const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
17482
+ fs6.writeFileSync(tmp, content, { mode: 384 });
17483
+ fs6.renameSync(tmp, file);
17538
17484
  }
17539
17485
  };
17540
17486
 
@@ -17549,7 +17495,10 @@ var PersonaRegistry = class {
17549
17495
  /** 从 store 全量重建缓存(boot 时 + 测试 setup 时) */
17550
17496
  reload() {
17551
17497
  this.cache.clear();
17552
- for (const p of this.store.list()) this.cache.set(p.personaId, p);
17498
+ for (const id of this.store.list()) {
17499
+ const p = this.store.read(id);
17500
+ if (p) this.cache.set(p.personaId, p);
17501
+ }
17553
17502
  }
17554
17503
  get(personaId) {
17555
17504
  return this.cache.get(personaId);
@@ -17577,8 +17526,6 @@ var PersonaRegistry = class {
17577
17526
 
17578
17527
  // src/persona/manager.ts
17579
17528
  var import_node_crypto3 = __toESM(require("crypto"), 1);
17580
- var import_node_fs7 = __toESM(require("fs"), 1);
17581
- var import_node_path7 = __toESM(require("path"), 1);
17582
17529
  var PersonaManager = class {
17583
17530
  constructor(deps) {
17584
17531
  this.deps = deps;
@@ -17586,49 +17533,45 @@ var PersonaManager = class {
17586
17533
  deps;
17587
17534
  create(args) {
17588
17535
  const personaId = this.generatePersonaId(args.label);
17589
- const iso = this.deps.now().toISOString();
17590
- const file = {
17536
+ const now = Date.now();
17537
+ const persona = {
17591
17538
  personaId,
17592
17539
  label: args.label,
17593
- cwd: args.cwd,
17594
17540
  model: args.model,
17595
- systemPromptAppend: args.systemPromptAppend,
17596
- // L1 锁死:plan 模式 + 只读三件套
17597
- permissionMode: "plan",
17598
- toolAllowlist: ["Read", "Grep", "Glob"],
17599
- public: true,
17541
+ public: args.public ?? false,
17600
17542
  tokenMap: {},
17601
- createdAt: iso,
17602
- updatedAt: iso
17543
+ createdAt: now,
17544
+ updatedAt: now
17603
17545
  };
17604
- const written = this.deps.store.write(file);
17605
- this.deps.registry.set(written);
17606
- return written;
17546
+ this.deps.store.write(persona, args.personality);
17547
+ this.deps.registry.set(persona);
17548
+ return persona;
17607
17549
  }
17608
- update(personaId, patch) {
17550
+ update(personaId, patch, personality) {
17609
17551
  const existing = this.deps.registry.get(personaId);
17610
17552
  if (!existing) throw new Error(`persona not found: ${personaId}`);
17611
17553
  const updated = {
17612
17554
  ...existing,
17613
17555
  ...patch,
17614
- updatedAt: this.deps.now().toISOString()
17556
+ updatedAt: Date.now()
17615
17557
  };
17616
- const written = this.deps.store.write(updated);
17617
- this.deps.registry.set(written);
17618
- return written;
17558
+ if (personality !== void 0) {
17559
+ this.deps.store.write(updated, personality);
17560
+ } else {
17561
+ this.deps.store.writeMeta(updated);
17562
+ }
17563
+ this.deps.registry.set(updated);
17564
+ return updated;
17619
17565
  }
17620
- /** 删除 persona + 级联清掉 sessions/<personaId>/ 目录 */
17566
+ /**
17567
+ * 删除 persona。
17568
+ * PersonaStore.remove(personaId) 已级联删除整个 <personaRoot>/<personaId>/ 目录,
17569
+ * 其中包含 .clawd/sub-sessions/——无需额外清理。
17570
+ * 旧的 <dataDir>/sessions/<personaId>/ 路径已废弃,不再维护。
17571
+ */
17621
17572
  delete(personaId) {
17622
- this.deps.store.delete(personaId);
17573
+ this.deps.store.remove(personaId);
17623
17574
  this.deps.registry.remove(personaId);
17624
- const dir = import_node_path7.default.join(this.deps.dataDir, "sessions", personaId);
17625
- try {
17626
- import_node_fs7.default.rmSync(dir, { recursive: true, force: true });
17627
- } catch (err) {
17628
- this.deps.logger.warn(`PersonaManager.delete: cleanup ${dir} failed`, {
17629
- err: err.message
17630
- });
17631
- }
17632
17575
  }
17633
17576
  /** 生成 32-char base64url token(24 bytes 随机),label 必填 */
17634
17577
  issueToken(personaId, label) {
@@ -17637,16 +17580,17 @@ var PersonaManager = class {
17637
17580
  const token = import_node_crypto3.default.randomBytes(24).toString("base64url");
17638
17581
  const entry = {
17639
17582
  label,
17640
- issuedAt: this.deps.now().toISOString()
17583
+ issuedAt: Date.now(),
17584
+ revoked: false
17641
17585
  };
17642
17586
  const updated = {
17643
17587
  ...existing,
17644
17588
  tokenMap: { ...existing.tokenMap, [token]: entry },
17645
- updatedAt: this.deps.now().toISOString()
17589
+ updatedAt: Date.now()
17646
17590
  };
17647
- const written = this.deps.store.write(updated);
17648
- this.deps.registry.set(written);
17649
- return { token, persona: written };
17591
+ this.deps.store.writeMeta(updated);
17592
+ this.deps.registry.set(updated);
17593
+ return { token, persona: updated };
17650
17594
  }
17651
17595
  revokeToken(personaId, token) {
17652
17596
  const existing = this.deps.registry.get(personaId);
@@ -17659,16 +17603,17 @@ var PersonaManager = class {
17659
17603
  ...existing.tokenMap,
17660
17604
  [token]: { ...tokenEntry, revoked: true }
17661
17605
  },
17662
- updatedAt: this.deps.now().toISOString()
17606
+ updatedAt: Date.now()
17663
17607
  };
17664
- const written = this.deps.store.write(updated);
17665
- this.deps.registry.set(written);
17666
- return written;
17608
+ this.deps.store.writeMeta(updated);
17609
+ this.deps.registry.set(updated);
17610
+ return updated;
17667
17611
  }
17668
17612
  /**
17669
17613
  * 拿到(或按需创建)该 token 对应的 sub-session。subSessionId 由 personaId + token 哈希派生
17670
17614
  * 保证 idempotent:同一 token 永远复用同一个 sub-session。
17671
- * 创建路径:开启 idleKillEnabled,cwd / model / tool 等字段从 PersonaFile 模板复制
17615
+ * 创建路径:开启 idleKillEnabled,cwd persona 目录,不再硬编码 permission mode / tool allowlist
17616
+ * (sandbox 约束移到 persona dir 下的 .claude/settings.json,由 OS-level Seatbelt 执行)
17672
17617
  */
17673
17618
  getOrCreateSubSession(personaId, token) {
17674
17619
  const persona = this.deps.registry.get(personaId);
@@ -17683,16 +17628,11 @@ var PersonaManager = class {
17683
17628
  const sessionFile = this.deps.sessionManager.createForAgent({
17684
17629
  sessionId: subSessionId,
17685
17630
  agentId: personaId,
17686
- cwd: persona.cwd,
17631
+ cwd: this.deps.store.personaDirPath(personaId),
17687
17632
  tool: "claude",
17688
17633
  label: subLabel,
17689
17634
  model: persona.model,
17690
- permissionMode: "plan",
17691
- // L1 锁定(task 14):把 PersonaFile.toolAllowlist 透传到 SessionManager,
17692
- // 最终在 buildSpawnArgs 拼成 --add-dir + --disallowed-tools,runner stdout 拦截层
17693
- // 也读 SubSessionMeta.toolAllowlist 做工具名 / cwd 越界拦截
17694
- hardcodedToolAllowlist: persona.toolAllowlist,
17695
- subSessionMeta: { idleKillEnabled: true }
17635
+ subSessionMeta: { idleKillEnabled: true, personaMode: true }
17696
17636
  });
17697
17637
  return { sessionFile, isNew: true };
17698
17638
  }
@@ -17726,23 +17666,23 @@ init_claude();
17726
17666
  init_claude_history();
17727
17667
 
17728
17668
  // src/workspace/browser.ts
17729
- var import_node_fs10 = __toESM(require("fs"), 1);
17669
+ var import_node_fs8 = __toESM(require("fs"), 1);
17730
17670
  var import_node_os4 = __toESM(require("os"), 1);
17731
- var import_node_path10 = __toESM(require("path"), 1);
17671
+ var import_node_path7 = __toESM(require("path"), 1);
17732
17672
  init_protocol();
17733
17673
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
17734
17674
  function resolveInsideCwd(cwd, subpath) {
17735
- const absCwd = import_node_path10.default.resolve(cwd);
17736
- const joined = import_node_path10.default.resolve(absCwd, subpath ?? ".");
17737
- const rel = import_node_path10.default.relative(absCwd, joined);
17738
- if (rel.startsWith("..") || import_node_path10.default.isAbsolute(rel)) {
17675
+ const absCwd = import_node_path7.default.resolve(cwd);
17676
+ const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
17677
+ const rel = import_node_path7.default.relative(absCwd, joined);
17678
+ if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
17739
17679
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
17740
17680
  }
17741
17681
  return joined;
17742
17682
  }
17743
17683
  function ensureCwd(cwd) {
17744
17684
  try {
17745
- const stat = import_node_fs10.default.statSync(cwd);
17685
+ const stat = import_node_fs8.default.statSync(cwd);
17746
17686
  if (!stat.isDirectory()) {
17747
17687
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
17748
17688
  }
@@ -17756,7 +17696,7 @@ var WorkspaceBrowser = class {
17756
17696
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
17757
17697
  ensureCwd(cwd);
17758
17698
  const full = resolveInsideCwd(cwd, args.path);
17759
- const dirents = import_node_fs10.default.readdirSync(full, { withFileTypes: true });
17699
+ const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
17760
17700
  const entries = [];
17761
17701
  for (const d of dirents) {
17762
17702
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -17766,7 +17706,7 @@ var WorkspaceBrowser = class {
17766
17706
  mtime: ""
17767
17707
  };
17768
17708
  try {
17769
- const st = import_node_fs10.default.statSync(import_node_path10.default.join(full, d.name));
17709
+ const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
17770
17710
  entry.mtime = new Date(st.mtimeMs).toISOString();
17771
17711
  if (d.isFile()) entry.size = st.size;
17772
17712
  } catch {
@@ -17782,14 +17722,14 @@ var WorkspaceBrowser = class {
17782
17722
  read(args) {
17783
17723
  ensureCwd(args.cwd);
17784
17724
  const full = resolveInsideCwd(args.cwd, args.path);
17785
- const st = import_node_fs10.default.statSync(full);
17725
+ const st = import_node_fs8.default.statSync(full);
17786
17726
  if (!st.isFile()) {
17787
17727
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
17788
17728
  }
17789
17729
  if (st.size > MAX_FILE_BYTES) {
17790
17730
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
17791
17731
  }
17792
- const buf = import_node_fs10.default.readFileSync(full);
17732
+ const buf = import_node_fs8.default.readFileSync(full);
17793
17733
  const isBinary = buf.includes(0);
17794
17734
  if (isBinary) {
17795
17735
  return {
@@ -17811,9 +17751,9 @@ var WorkspaceBrowser = class {
17811
17751
  };
17812
17752
 
17813
17753
  // src/skills/scanner.ts
17814
- var import_node_fs11 = __toESM(require("fs"), 1);
17754
+ var import_node_fs9 = __toESM(require("fs"), 1);
17815
17755
  var import_node_os5 = __toESM(require("os"), 1);
17816
- var import_node_path11 = __toESM(require("path"), 1);
17756
+ var import_node_path8 = __toESM(require("path"), 1);
17817
17757
  function parseFrontmatter(content) {
17818
17758
  if (!content.startsWith("---")) return { name: "", description: "" };
17819
17759
  const end = content.indexOf("---", 3);
@@ -17849,7 +17789,7 @@ function parseFrontmatter(content) {
17849
17789
  }
17850
17790
  function isDirLikeSync(p) {
17851
17791
  try {
17852
- return import_node_fs11.default.statSync(p).isDirectory();
17792
+ return import_node_fs9.default.statSync(p).isDirectory();
17853
17793
  } catch {
17854
17794
  return false;
17855
17795
  }
@@ -17857,19 +17797,19 @@ function isDirLikeSync(p) {
17857
17797
  function scanSkillDir(dir, source, seen, out, pluginName) {
17858
17798
  let entries;
17859
17799
  try {
17860
- entries = import_node_fs11.default.readdirSync(dir, { withFileTypes: true });
17800
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
17861
17801
  } catch {
17862
17802
  return;
17863
17803
  }
17864
17804
  for (const ent of entries) {
17865
- const entryPath = import_node_path11.default.join(dir, ent.name);
17805
+ const entryPath = import_node_path8.default.join(dir, ent.name);
17866
17806
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
17867
17807
  let content;
17868
17808
  try {
17869
- content = import_node_fs11.default.readFileSync(import_node_path11.default.join(entryPath, "SKILL.md"), "utf8");
17809
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
17870
17810
  } catch {
17871
17811
  try {
17872
- content = import_node_fs11.default.readFileSync(import_node_path11.default.join(entryPath, "skill.md"), "utf8");
17812
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
17873
17813
  } catch {
17874
17814
  continue;
17875
17815
  }
@@ -17887,26 +17827,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
17887
17827
  function scanCommandDir(dir, source, seen, out, pluginName) {
17888
17828
  let entries;
17889
17829
  try {
17890
- entries = import_node_fs11.default.readdirSync(dir, { withFileTypes: true });
17830
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
17891
17831
  } catch {
17892
17832
  return;
17893
17833
  }
17894
17834
  for (const ent of entries) {
17895
- const entryPath = import_node_path11.default.join(dir, ent.name);
17835
+ const entryPath = import_node_path8.default.join(dir, ent.name);
17896
17836
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
17897
17837
  const ns = ent.name;
17898
17838
  let subEntries;
17899
17839
  try {
17900
- subEntries = import_node_fs11.default.readdirSync(entryPath, { withFileTypes: true });
17840
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
17901
17841
  } catch {
17902
17842
  continue;
17903
17843
  }
17904
17844
  for (const se of subEntries) {
17905
17845
  if (!se.name.endsWith(".md")) continue;
17906
- const sePath = import_node_path11.default.join(entryPath, se.name);
17846
+ const sePath = import_node_path8.default.join(entryPath, se.name);
17907
17847
  let content;
17908
17848
  try {
17909
- content = import_node_fs11.default.readFileSync(sePath, "utf8");
17849
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
17910
17850
  } catch {
17911
17851
  continue;
17912
17852
  }
@@ -17923,7 +17863,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
17923
17863
  } else if (ent.name.endsWith(".md")) {
17924
17864
  let content;
17925
17865
  try {
17926
- content = import_node_fs11.default.readFileSync(entryPath, "utf8");
17866
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
17927
17867
  } catch {
17928
17868
  continue;
17929
17869
  }
@@ -17939,10 +17879,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
17939
17879
  }
17940
17880
  }
17941
17881
  function readInstalledPlugins(home) {
17942
- const file = import_node_path11.default.join(home, ".claude", "plugins", "installed_plugins.json");
17882
+ const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
17943
17883
  let raw;
17944
17884
  try {
17945
- raw = import_node_fs11.default.readFileSync(file, "utf8");
17885
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
17946
17886
  } catch {
17947
17887
  return [];
17948
17888
  }
@@ -17980,14 +17920,14 @@ var SkillsScanner = class {
17980
17920
  list(args) {
17981
17921
  const seen = /* @__PURE__ */ new Set();
17982
17922
  const out = [];
17983
- scanSkillDir(import_node_path11.default.join(this.home, ".claude", "skills"), "global", seen, out);
17984
- scanCommandDir(import_node_path11.default.join(this.home, ".claude", "commands"), "global", seen, out);
17985
- scanSkillDir(import_node_path11.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
17986
- scanCommandDir(import_node_path11.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
17923
+ scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
17924
+ scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
17925
+ scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
17926
+ scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
17987
17927
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
17988
17928
  for (const { name, root } of plugins) {
17989
- scanSkillDir(import_node_path11.default.join(root, "skills"), "plugin", seen, out, name);
17990
- scanCommandDir(import_node_path11.default.join(root, "commands"), "plugin", seen, out, name);
17929
+ scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
17930
+ scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
17991
17931
  }
17992
17932
  out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
17993
17933
  return out;
@@ -17995,9 +17935,9 @@ var SkillsScanner = class {
17995
17935
  };
17996
17936
 
17997
17937
  // src/observer/session-observer.ts
17998
- var import_node_fs12 = __toESM(require("fs"), 1);
17938
+ var import_node_fs10 = __toESM(require("fs"), 1);
17999
17939
  var import_node_os6 = __toESM(require("os"), 1);
18000
- var import_node_path12 = __toESM(require("path"), 1);
17940
+ var import_node_path9 = __toESM(require("path"), 1);
18001
17941
  init_claude_history();
18002
17942
  var SessionObserver = class {
18003
17943
  constructor(opts) {
@@ -18009,14 +17949,14 @@ var SessionObserver = class {
18009
17949
  watches = /* @__PURE__ */ new Map();
18010
17950
  resolveJsonlPath(cwd, toolSessionId, override) {
18011
17951
  if (override) return override;
18012
- return import_node_path12.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
17952
+ return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
18013
17953
  }
18014
17954
  start(args) {
18015
17955
  this.stop(args.sessionId);
18016
17956
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
18017
17957
  let size = 0;
18018
17958
  try {
18019
- size = import_node_fs12.default.statSync(filePath).size;
17959
+ size = import_node_fs10.default.statSync(filePath).size;
18020
17960
  } catch {
18021
17961
  }
18022
17962
  const w = {
@@ -18029,10 +17969,10 @@ var SessionObserver = class {
18029
17969
  adapter: args.adapter
18030
17970
  };
18031
17971
  try {
18032
- import_node_fs12.default.mkdirSync(import_node_path12.default.dirname(filePath), { recursive: true });
17972
+ import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
18033
17973
  } catch {
18034
17974
  }
18035
- w.watcher = import_node_fs12.default.watch(import_node_path12.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
17975
+ w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
18036
17976
  if (!changedName || !filePath.endsWith(changedName)) return;
18037
17977
  this.poll(w);
18038
17978
  });
@@ -18047,7 +17987,7 @@ var SessionObserver = class {
18047
17987
  // reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
18048
17988
  hydrateMetaTail(w, maxLines = 200) {
18049
17989
  try {
18050
- const raw = import_node_fs12.default.readFileSync(w.filePath, "utf8");
17990
+ const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
18051
17991
  if (!raw) return;
18052
17992
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
18053
17993
  if (allLines.length === 0) return;
@@ -18068,7 +18008,7 @@ var SessionObserver = class {
18068
18008
  poll(w) {
18069
18009
  let size = 0;
18070
18010
  try {
18071
- size = import_node_fs12.default.statSync(w.filePath).size;
18011
+ size = import_node_fs10.default.statSync(w.filePath).size;
18072
18012
  } catch {
18073
18013
  return;
18074
18014
  }
@@ -18077,11 +18017,11 @@ var SessionObserver = class {
18077
18017
  w.buf = "";
18078
18018
  }
18079
18019
  if (size === w.lastSize) return;
18080
- const fd = import_node_fs12.default.openSync(w.filePath, "r");
18020
+ const fd = import_node_fs10.default.openSync(w.filePath, "r");
18081
18021
  try {
18082
18022
  const len = size - w.lastSize;
18083
18023
  const buf = Buffer.alloc(len);
18084
- import_node_fs12.default.readSync(fd, buf, 0, len, w.lastSize);
18024
+ import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
18085
18025
  w.lastSize = size;
18086
18026
  w.buf += buf.toString("utf8");
18087
18027
  let newlineIndex;
@@ -18095,7 +18035,7 @@ var SessionObserver = class {
18095
18035
  this.maybeReportUserMessage(w.sessionId, line);
18096
18036
  }
18097
18037
  } finally {
18098
- import_node_fs12.default.closeSync(fd);
18038
+ import_node_fs10.default.closeSync(fd);
18099
18039
  }
18100
18040
  }
18101
18041
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -18519,7 +18459,7 @@ var PersonaBoundHandler = class {
18519
18459
  kind: "persona-ready",
18520
18460
  subSessionId: subSessionFile.sessionId,
18521
18461
  personaLabel: persona.label,
18522
- cwd: persona.cwd,
18462
+ cwd: this.deps.personaStore.personaDirPath(personaId),
18523
18463
  model: persona.model
18524
18464
  });
18525
18465
  unsubscribe = this.deps.sessionManager.subscribe(
@@ -18683,10 +18623,10 @@ function isLocalhost(addr) {
18683
18623
  }
18684
18624
 
18685
18625
  // src/discovery/state-file.ts
18686
- var import_node_fs13 = __toESM(require("fs"), 1);
18687
- var import_node_path13 = __toESM(require("path"), 1);
18626
+ var import_node_fs11 = __toESM(require("fs"), 1);
18627
+ var import_node_path10 = __toESM(require("path"), 1);
18688
18628
  function defaultStateFilePath(dataDir) {
18689
- return import_node_path13.default.join(dataDir, "state.json");
18629
+ return import_node_path10.default.join(dataDir, "state.json");
18690
18630
  }
18691
18631
  function isPidAlive(pid) {
18692
18632
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -18708,7 +18648,7 @@ var StateFileManager = class {
18708
18648
  }
18709
18649
  read() {
18710
18650
  try {
18711
- const raw = import_node_fs13.default.readFileSync(this.file, "utf8");
18651
+ const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
18712
18652
  const parsed = JSON.parse(raw);
18713
18653
  return parsed;
18714
18654
  } catch {
@@ -18722,34 +18662,34 @@ var StateFileManager = class {
18722
18662
  return { status: "stale", existing };
18723
18663
  }
18724
18664
  write(state) {
18725
- import_node_fs13.default.mkdirSync(import_node_path13.default.dirname(this.file), { recursive: true });
18665
+ import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
18726
18666
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
18727
- import_node_fs13.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
18728
- import_node_fs13.default.renameSync(tmp, this.file);
18667
+ import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
18668
+ import_node_fs11.default.renameSync(tmp, this.file);
18729
18669
  if (process.platform !== "win32") {
18730
18670
  try {
18731
- import_node_fs13.default.chmodSync(this.file, 384);
18671
+ import_node_fs11.default.chmodSync(this.file, 384);
18732
18672
  } catch {
18733
18673
  }
18734
18674
  }
18735
18675
  }
18736
18676
  delete() {
18737
18677
  try {
18738
- import_node_fs13.default.unlinkSync(this.file);
18678
+ import_node_fs11.default.unlinkSync(this.file);
18739
18679
  } catch {
18740
18680
  }
18741
18681
  }
18742
18682
  };
18743
18683
 
18744
18684
  // src/tunnel/tunnel-manager.ts
18745
- var import_node_fs16 = __toESM(require("fs"), 1);
18746
- var import_node_path16 = __toESM(require("path"), 1);
18685
+ var import_node_fs14 = __toESM(require("fs"), 1);
18686
+ var import_node_path13 = __toESM(require("path"), 1);
18747
18687
  var import_node_crypto4 = __toESM(require("crypto"), 1);
18748
18688
  var import_node_child_process4 = require("child_process");
18749
18689
 
18750
18690
  // src/tunnel/tunnel-store.ts
18751
- var import_node_fs14 = __toESM(require("fs"), 1);
18752
- var import_node_path14 = __toESM(require("path"), 1);
18691
+ var import_node_fs12 = __toESM(require("fs"), 1);
18692
+ var import_node_path11 = __toESM(require("path"), 1);
18753
18693
  var TunnelStore = class {
18754
18694
  constructor(filePath) {
18755
18695
  this.filePath = filePath;
@@ -18757,7 +18697,7 @@ var TunnelStore = class {
18757
18697
  filePath;
18758
18698
  async get() {
18759
18699
  try {
18760
- const raw = await import_node_fs14.default.promises.readFile(this.filePath, "utf8");
18700
+ const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
18761
18701
  const obj = JSON.parse(raw);
18762
18702
  if (!isPersistedTunnel(obj)) return null;
18763
18703
  return obj;
@@ -18768,22 +18708,22 @@ var TunnelStore = class {
18768
18708
  }
18769
18709
  }
18770
18710
  async set(v) {
18771
- const dir = import_node_path14.default.dirname(this.filePath);
18772
- await import_node_fs14.default.promises.mkdir(dir, { recursive: true });
18711
+ const dir = import_node_path11.default.dirname(this.filePath);
18712
+ await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
18773
18713
  const data = JSON.stringify(v, null, 2);
18774
18714
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
18775
- await import_node_fs14.default.promises.writeFile(tmp, data, { mode: 384 });
18715
+ await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
18776
18716
  if (process.platform !== "win32") {
18777
18717
  try {
18778
- await import_node_fs14.default.promises.chmod(tmp, 384);
18718
+ await import_node_fs12.default.promises.chmod(tmp, 384);
18779
18719
  } catch {
18780
18720
  }
18781
18721
  }
18782
- await import_node_fs14.default.promises.rename(tmp, this.filePath);
18722
+ await import_node_fs12.default.promises.rename(tmp, this.filePath);
18783
18723
  }
18784
18724
  async clear() {
18785
18725
  try {
18786
- await import_node_fs14.default.promises.unlink(this.filePath);
18726
+ await import_node_fs12.default.promises.unlink(this.filePath);
18787
18727
  } catch (err) {
18788
18728
  const code = err?.code;
18789
18729
  if (code !== "ENOENT") throw err;
@@ -18878,9 +18818,9 @@ function escape(v) {
18878
18818
  }
18879
18819
 
18880
18820
  // src/tunnel/frpc-binary.ts
18881
- var import_node_fs15 = __toESM(require("fs"), 1);
18821
+ var import_node_fs13 = __toESM(require("fs"), 1);
18882
18822
  var import_node_os7 = __toESM(require("os"), 1);
18883
- var import_node_path15 = __toESM(require("path"), 1);
18823
+ var import_node_path12 = __toESM(require("path"), 1);
18884
18824
  var import_node_child_process3 = require("child_process");
18885
18825
  var import_node_stream = require("stream");
18886
18826
  var import_promises = require("stream/promises");
@@ -18912,20 +18852,20 @@ function frpcDownloadUrl(version2, p) {
18912
18852
  }
18913
18853
  async function ensureFrpcBinary(opts) {
18914
18854
  if (opts.override) {
18915
- if (!import_node_fs15.default.existsSync(opts.override)) {
18855
+ if (!import_node_fs13.default.existsSync(opts.override)) {
18916
18856
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
18917
18857
  }
18918
18858
  return opts.override;
18919
18859
  }
18920
18860
  const version2 = opts.version ?? FRPC_VERSION;
18921
18861
  const platform = opts.platform ?? detectPlatform();
18922
- const binDir = import_node_path15.default.join(opts.dataDir, "bin");
18923
- import_node_fs15.default.mkdirSync(binDir, { recursive: true });
18862
+ const binDir = import_node_path12.default.join(opts.dataDir, "bin");
18863
+ import_node_fs13.default.mkdirSync(binDir, { recursive: true });
18924
18864
  cleanupStaleArtifacts(binDir);
18925
- const stableBin = import_node_path15.default.join(binDir, "frpc");
18926
- if (import_node_fs15.default.existsSync(stableBin)) return stableBin;
18865
+ const stableBin = import_node_path12.default.join(binDir, "frpc");
18866
+ if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
18927
18867
  const partialBin = `${stableBin}.partial`;
18928
- const tarballPath = import_node_path15.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
18868
+ const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
18929
18869
  try {
18930
18870
  const url = frpcDownloadUrl(version2, platform);
18931
18871
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -18934,8 +18874,8 @@ async function ensureFrpcBinary(opts) {
18934
18874
  } else {
18935
18875
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
18936
18876
  }
18937
- import_node_fs15.default.chmodSync(partialBin, 493);
18938
- import_node_fs15.default.renameSync(partialBin, stableBin);
18877
+ import_node_fs13.default.chmodSync(partialBin, 493);
18878
+ import_node_fs13.default.renameSync(partialBin, stableBin);
18939
18879
  } finally {
18940
18880
  safeUnlink(tarballPath);
18941
18881
  safeUnlink(partialBin);
@@ -18945,15 +18885,15 @@ async function ensureFrpcBinary(opts) {
18945
18885
  function cleanupStaleArtifacts(binDir) {
18946
18886
  let entries;
18947
18887
  try {
18948
- entries = import_node_fs15.default.readdirSync(binDir);
18888
+ entries = import_node_fs13.default.readdirSync(binDir);
18949
18889
  } catch {
18950
18890
  return;
18951
18891
  }
18952
18892
  for (const name of entries) {
18953
18893
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
18954
- const full = import_node_path15.default.join(binDir, name);
18894
+ const full = import_node_path12.default.join(binDir, name);
18955
18895
  try {
18956
- import_node_fs15.default.rmSync(full, { recursive: true, force: true });
18896
+ import_node_fs13.default.rmSync(full, { recursive: true, force: true });
18957
18897
  } catch {
18958
18898
  }
18959
18899
  }
@@ -18961,7 +18901,7 @@ function cleanupStaleArtifacts(binDir) {
18961
18901
  }
18962
18902
  function safeUnlink(p) {
18963
18903
  try {
18964
- import_node_fs15.default.unlinkSync(p);
18904
+ import_node_fs13.default.unlinkSync(p);
18965
18905
  } catch {
18966
18906
  }
18967
18907
  }
@@ -18972,13 +18912,13 @@ async function downloadToFile(url, dest, fetchImpl) {
18972
18912
  if (!res.ok || !res.body) {
18973
18913
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
18974
18914
  }
18975
- const out = import_node_fs15.default.createWriteStream(dest);
18915
+ const out = import_node_fs13.default.createWriteStream(dest);
18976
18916
  const nodeStream = import_node_stream.Readable.fromWeb(res.body);
18977
18917
  await (0, import_promises.pipeline)(nodeStream, out);
18978
18918
  }
18979
18919
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
18980
- const work = import_node_path15.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
18981
- import_node_fs15.default.mkdirSync(work, { recursive: true });
18920
+ const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
18921
+ import_node_fs13.default.mkdirSync(work, { recursive: true });
18982
18922
  try {
18983
18923
  await new Promise((resolve, reject) => {
18984
18924
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -18986,13 +18926,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
18986
18926
  proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
18987
18927
  });
18988
18928
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
18989
- const src = import_node_path15.default.join(work, dirName, "frpc");
18990
- if (!import_node_fs15.default.existsSync(src)) {
18929
+ const src = import_node_path12.default.join(work, dirName, "frpc");
18930
+ if (!import_node_fs13.default.existsSync(src)) {
18991
18931
  throw new Error(`frpc not found inside tarball at ${src}`);
18992
18932
  }
18993
- import_node_fs15.default.copyFileSync(src, destBin);
18933
+ import_node_fs13.default.copyFileSync(src, destBin);
18994
18934
  } finally {
18995
- import_node_fs15.default.rmSync(work, { recursive: true, force: true });
18935
+ import_node_fs13.default.rmSync(work, { recursive: true, force: true });
18996
18936
  }
18997
18937
  }
18998
18938
 
@@ -19001,7 +18941,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
19001
18941
  var TunnelManager = class {
19002
18942
  constructor(deps) {
19003
18943
  this.deps = deps;
19004
- this.store = deps.store ?? new TunnelStore(import_node_path16.default.join(deps.dataDir, "tunnel.json"));
18944
+ this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
19005
18945
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
19006
18946
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
19007
18947
  }
@@ -19118,7 +19058,7 @@ var TunnelManager = class {
19118
19058
  dataDir: this.deps.dataDir,
19119
19059
  override: this.deps.frpcBinaryOverride ?? void 0
19120
19060
  });
19121
- const tomlPath = import_node_path16.default.join(this.deps.dataDir, "frpc.toml");
19061
+ const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
19122
19062
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto4.default.randomBytes(3).toString("hex")}`;
19123
19063
  const toml = buildFrpcToml({
19124
19064
  serverAddr: t.frpsHost,
@@ -19129,12 +19069,12 @@ var TunnelManager = class {
19129
19069
  localPort,
19130
19070
  logLevel: "info"
19131
19071
  });
19132
- await import_node_fs16.default.promises.writeFile(tomlPath, toml, { mode: 384 });
19072
+ await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
19133
19073
  const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
19134
19074
  stdio: ["ignore", "pipe", "pipe"]
19135
19075
  });
19136
- const logFilePath = import_node_path16.default.join(this.deps.dataDir, "frpc.log");
19137
- const logStream = import_node_fs16.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
19076
+ const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
19077
+ const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
19138
19078
  logStream.on("error", () => {
19139
19079
  });
19140
19080
  const tee = (chunk) => {
@@ -19226,12 +19166,12 @@ function deriveStableDeviceKey(opts = {}) {
19226
19166
  }
19227
19167
 
19228
19168
  // src/auth-store.ts
19229
- var import_node_fs17 = __toESM(require("fs"), 1);
19230
- var import_node_path17 = __toESM(require("path"), 1);
19169
+ var import_node_fs15 = __toESM(require("fs"), 1);
19170
+ var import_node_path14 = __toESM(require("path"), 1);
19231
19171
  var import_node_crypto6 = __toESM(require("crypto"), 1);
19232
19172
  var AUTH_FILE_NAME = "auth.json";
19233
19173
  function authFilePath(dataDir) {
19234
- return import_node_path17.default.join(dataDir, AUTH_FILE_NAME);
19174
+ return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
19235
19175
  }
19236
19176
  function loadOrCreateAuthToken(opts) {
19237
19177
  const file = authFilePath(opts.dataDir);
@@ -19247,7 +19187,7 @@ function defaultGenerate() {
19247
19187
  }
19248
19188
  function readAuthFile(file) {
19249
19189
  try {
19250
- const raw = import_node_fs17.default.readFileSync(file, "utf8");
19190
+ const raw = import_node_fs15.default.readFileSync(file, "utf8");
19251
19191
  const parsed = JSON.parse(raw);
19252
19192
  if (typeof parsed?.token === "string" && parsed.token.length > 0) {
19253
19193
  return {
@@ -19263,10 +19203,10 @@ function readAuthFile(file) {
19263
19203
  }
19264
19204
  }
19265
19205
  function writeAuthFile(file, content) {
19266
- import_node_fs17.default.mkdirSync(import_node_path17.default.dirname(file), { recursive: true });
19267
- import_node_fs17.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
19206
+ import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
19207
+ import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
19268
19208
  try {
19269
- import_node_fs17.default.chmodSync(file, 384);
19209
+ import_node_fs15.default.chmodSync(file, 384);
19270
19210
  } catch {
19271
19211
  }
19272
19212
  }
@@ -19278,12 +19218,12 @@ init_protocol();
19278
19218
  init_protocol();
19279
19219
 
19280
19220
  // src/session/fork.ts
19281
- var import_node_fs18 = __toESM(require("fs"), 1);
19221
+ var import_node_fs16 = __toESM(require("fs"), 1);
19282
19222
  var import_node_os9 = __toESM(require("os"), 1);
19283
- var import_node_path18 = __toESM(require("path"), 1);
19223
+ var import_node_path15 = __toESM(require("path"), 1);
19284
19224
  init_claude_history();
19285
19225
  function readJsonlEntries(file) {
19286
- const raw = import_node_fs18.default.readFileSync(file, "utf8");
19226
+ const raw = import_node_fs16.default.readFileSync(file, "utf8");
19287
19227
  const out = [];
19288
19228
  for (const line of raw.split("\n")) {
19289
19229
  const t = line.trim();
@@ -19296,10 +19236,10 @@ function readJsonlEntries(file) {
19296
19236
  return out;
19297
19237
  }
19298
19238
  function forkSession(input) {
19299
- const baseDir = input.baseDir ?? import_node_path18.default.join(import_node_os9.default.homedir(), ".claude");
19300
- const projectDir = import_node_path18.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
19301
- const sourceFile = import_node_path18.default.join(projectDir, `${input.toolSessionId}.jsonl`);
19302
- if (!import_node_fs18.default.existsSync(sourceFile)) {
19239
+ const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
19240
+ const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
19241
+ const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
19242
+ if (!import_node_fs16.default.existsSync(sourceFile)) {
19303
19243
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
19304
19244
  }
19305
19245
  const entries = readJsonlEntries(sourceFile);
@@ -19329,9 +19269,9 @@ function forkSession(input) {
19329
19269
  }
19330
19270
  forkedLines.push(JSON.stringify(forked));
19331
19271
  }
19332
- const forkedFilePath = import_node_path18.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
19333
- import_node_fs18.default.mkdirSync(projectDir, { recursive: true });
19334
- import_node_fs18.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
19272
+ const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
19273
+ import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
19274
+ import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
19335
19275
  return { forkedToolSessionId, forkedFilePath };
19336
19276
  }
19337
19277
 
@@ -19601,9 +19541,9 @@ init_protocol();
19601
19541
 
19602
19542
  // src/workspace/git.ts
19603
19543
  var import_node_child_process5 = require("child_process");
19604
- var import_node_fs19 = __toESM(require("fs"), 1);
19544
+ var import_node_fs17 = __toESM(require("fs"), 1);
19605
19545
  var import_node_os10 = __toESM(require("os"), 1);
19606
- var import_node_path19 = __toESM(require("path"), 1);
19546
+ var import_node_path16 = __toESM(require("path"), 1);
19607
19547
  var import_node_util = require("util");
19608
19548
  var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
19609
19549
  function formatChildProcessError(err) {
@@ -19618,9 +19558,9 @@ function formatChildProcessError(err) {
19618
19558
  return e.message ?? "unknown error";
19619
19559
  }
19620
19560
  function normalizePath(p) {
19621
- const resolved = import_node_path19.default.resolve(p);
19561
+ const resolved = import_node_path16.default.resolve(p);
19622
19562
  try {
19623
- return import_node_fs19.default.realpathSync(resolved);
19563
+ return import_node_fs17.default.realpathSync(resolved);
19624
19564
  } catch {
19625
19565
  return resolved;
19626
19566
  }
@@ -19721,13 +19661,13 @@ function flattenToDirName(branch) {
19721
19661
  }
19722
19662
  function encodeClaudeProjectDir(absPath) {
19723
19663
  if (!absPath || typeof absPath !== "string") return "";
19724
- let canonical = import_node_path19.default.resolve(absPath);
19664
+ let canonical = import_node_path16.default.resolve(absPath);
19725
19665
  try {
19726
- canonical = import_node_fs19.default.realpathSync(canonical);
19666
+ canonical = import_node_fs17.default.realpathSync(canonical);
19727
19667
  } catch {
19728
19668
  try {
19729
- const parent = import_node_fs19.default.realpathSync(import_node_path19.default.dirname(canonical));
19730
- canonical = import_node_path19.default.join(parent, import_node_path19.default.basename(canonical));
19669
+ const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
19670
+ canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
19731
19671
  } catch {
19732
19672
  }
19733
19673
  }
@@ -19751,11 +19691,11 @@ async function createWorktree(input) {
19751
19691
  if (!isGitRoot) {
19752
19692
  throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
19753
19693
  }
19754
- const parent = import_node_path19.default.dirname(import_node_path19.default.resolve(cwd));
19755
- if (parent === "/" || parent === import_node_path19.default.resolve(cwd)) {
19694
+ const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
19695
+ if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
19756
19696
  throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
19757
19697
  }
19758
- const worktreeRoot = import_node_path19.default.join(parent, dirName);
19698
+ const worktreeRoot = import_node_path16.default.join(parent, dirName);
19759
19699
  try {
19760
19700
  await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
19761
19701
  timeout: 3e3
@@ -19772,7 +19712,7 @@ async function createWorktree(input) {
19772
19712
  const msg = err.message;
19773
19713
  if (msg.startsWith("\u5206\u652F ")) throw err;
19774
19714
  }
19775
- if (import_node_fs19.default.existsSync(worktreeRoot)) {
19715
+ if (import_node_fs17.default.existsSync(worktreeRoot)) {
19776
19716
  throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
19777
19717
  }
19778
19718
  try {
@@ -19800,8 +19740,8 @@ async function removeWorktree(input) {
19800
19740
  );
19801
19741
  const gitCommonDir = stdout.trim();
19802
19742
  if (!gitCommonDir) throw new Error("empty git-common-dir");
19803
- const absGitCommon = import_node_path19.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path19.default.resolve(worktreeRoot, gitCommonDir);
19804
- repoRoot = import_node_path19.default.dirname(absGitCommon);
19743
+ const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
19744
+ repoRoot = import_node_path16.default.dirname(absGitCommon);
19805
19745
  } catch {
19806
19746
  repoRoot = null;
19807
19747
  }
@@ -19813,7 +19753,7 @@ async function removeWorktree(input) {
19813
19753
  } catch (err) {
19814
19754
  const stderr = err.stderr ?? "";
19815
19755
  const lower = stderr.toLowerCase();
19816
- const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs19.default.existsSync(worktreeRoot);
19756
+ const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
19817
19757
  if (!vanished) {
19818
19758
  throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
19819
19759
  }
@@ -19832,10 +19772,10 @@ async function removeWorktree(input) {
19832
19772
  try {
19833
19773
  const encoded = encodeClaudeProjectDir(worktreeRoot);
19834
19774
  if (encoded) {
19835
- const projectsRoot = import_node_path19.default.join(import_node_os10.default.homedir(), ".claude", "projects");
19836
- const target = import_node_path19.default.resolve(projectsRoot, encoded);
19837
- if (target.startsWith(projectsRoot + import_node_path19.default.sep) && target !== projectsRoot) {
19838
- import_node_fs19.default.rmSync(target, { recursive: true, force: true });
19775
+ const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
19776
+ const target = import_node_path16.default.resolve(projectsRoot, encoded);
19777
+ if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
19778
+ import_node_fs17.default.rmSync(target, { recursive: true, force: true });
19839
19779
  }
19840
19780
  }
19841
19781
  } catch {
@@ -19954,7 +19894,8 @@ init_protocol();
19954
19894
  function buildPersonaHandlers(deps) {
19955
19895
  const { personaManager, personaRegistry, sessionManager } = deps;
19956
19896
  const create = async (frame) => {
19957
- const args = PersonaCreateArgs.parse(frame);
19897
+ const { type: _type, requestId: _requestId, ...rest } = frame;
19898
+ const args = PersonaCreateArgsSchema.parse(rest);
19958
19899
  const persona = personaManager.create(args);
19959
19900
  return { response: { type: "persona:info", ...persona } };
19960
19901
  };
@@ -19964,7 +19905,7 @@ function buildPersonaHandlers(deps) {
19964
19905
  };
19965
19906
  };
19966
19907
  const get = async (frame) => {
19967
- const args = PersonaIdArgs.parse(frame);
19908
+ const args = PersonaIdArgsSchema.parse(frame);
19968
19909
  const persona = personaRegistry.get(args.personaId) ?? null;
19969
19910
  if (!persona) {
19970
19911
  return { response: { type: "persona:info", persona: null } };
@@ -19972,38 +19913,40 @@ function buildPersonaHandlers(deps) {
19972
19913
  return { response: { type: "persona:info", ...persona } };
19973
19914
  };
19974
19915
  const update = async (frame) => {
19975
- const args = PersonaUpdateArgs.parse(frame);
19976
- const persona = personaManager.update(args.personaId, args.patch);
19916
+ const { type: _type, requestId: _requestId, ...rest } = frame;
19917
+ const args = PersonaUpdateArgsSchema.parse(rest);
19918
+ const { personality, ...metaPatch } = args.patch;
19919
+ const persona = personaManager.update(args.personaId, metaPatch, personality);
19977
19920
  return { response: { type: "persona:info", ...persona } };
19978
19921
  };
19979
19922
  const del = async (frame) => {
19980
- const args = PersonaIdArgs.parse(frame);
19923
+ const args = PersonaIdArgsSchema.parse(frame);
19981
19924
  personaManager.delete(args.personaId);
19982
19925
  return {
19983
19926
  response: { type: "persona:deleted", personaId: args.personaId }
19984
19927
  };
19985
19928
  };
19986
19929
  const issueToken = async (frame) => {
19987
- const args = PersonaIssueTokenArgs.parse(frame);
19930
+ const args = PersonaIssueTokenArgsSchema.parse(frame);
19988
19931
  const { token, persona } = personaManager.issueToken(args.personaId, args.label);
19989
19932
  return {
19990
19933
  response: { type: "persona:tokenIssued", token, persona }
19991
19934
  };
19992
19935
  };
19993
19936
  const revokeToken = async (frame) => {
19994
- const args = PersonaRevokeTokenArgs.parse(frame);
19937
+ const args = PersonaRevokeTokenArgsSchema.parse(frame);
19995
19938
  const persona = personaManager.revokeToken(args.personaId, args.token);
19996
19939
  return { response: { type: "persona:info", ...persona } };
19997
19940
  };
19998
19941
  const listSubSessions = async (frame) => {
19999
- const args = PersonaIdArgs.parse(frame);
19942
+ const args = PersonaIdArgsSchema.parse(frame);
20000
19943
  const sessions = sessionManager.listForAgent(args.personaId);
20001
19944
  return {
20002
19945
  response: { type: "persona:subSessions", sessions }
20003
19946
  };
20004
19947
  };
20005
19948
  const appendOwnerMessage = async (frame) => {
20006
- const args = PersonaAppendOwnerMessageArgs.parse(frame);
19949
+ const args = PersonaAppendOwnerMessageArgsSchema.parse(frame);
20007
19950
  personaManager.appendOwnerMessage(args.personaId, args.subSessionId, args.text);
20008
19951
  return {
20009
19952
  response: { type: "persona:appendOwnerMessage", ok: true }
@@ -20044,7 +19987,7 @@ function buildMethodHandlers(deps) {
20044
19987
  async function startDaemon(config) {
20045
19988
  const logger = createLogger({
20046
19989
  level: config.logLevel,
20047
- file: import_node_path20.default.join(config.dataDir, "clawd.log")
19990
+ file: import_node_path17.default.join(config.dataDir, "clawd.log")
20048
19991
  });
20049
19992
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
20050
19993
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -20085,6 +20028,7 @@ async function startDaemon(config) {
20085
20028
  getAdapter,
20086
20029
  historyReader: history,
20087
20030
  dataDir: config.dataDir,
20031
+ personaRoot: import_node_path17.default.join(config.dataDir, "personas"),
20088
20032
  broadcastFrame: (frame, target) => {
20089
20033
  if (target === "all") {
20090
20034
  transport?.broadcastAll(frame);
@@ -20124,15 +20068,12 @@ async function startDaemon(config) {
20124
20068
  manager.recordRealUserUuid({ sessionId, realUuid, text });
20125
20069
  }
20126
20070
  });
20127
- const personaStore = new PersonaStore({ dataDir: config.dataDir });
20071
+ const personaStore = new PersonaStore(import_node_path17.default.join(config.dataDir, "personas"));
20128
20072
  const personaRegistry = new PersonaRegistry(personaStore);
20129
20073
  const personaManager = new PersonaManager({
20130
20074
  store: personaStore,
20131
20075
  registry: personaRegistry,
20132
- sessionManager: manager,
20133
- dataDir: config.dataDir,
20134
- now: () => /* @__PURE__ */ new Date(),
20135
- logger
20076
+ sessionManager: manager
20136
20077
  });
20137
20078
  let currentTunnelUrl = null;
20138
20079
  const handlers = buildMethodHandlers({
@@ -20150,6 +20091,7 @@ async function startDaemon(config) {
20150
20091
  const personaBoundHandler = new PersonaBoundHandler({
20151
20092
  registry: personaRegistry,
20152
20093
  personaManager,
20094
+ personaStore,
20153
20095
  sessionManager: manager,
20154
20096
  logger
20155
20097
  });
@@ -20258,8 +20200,8 @@ async function startDaemon(config) {
20258
20200
  const lines = [
20259
20201
  `Tunnel: ${r.url}`,
20260
20202
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
20261
- `Frpc config: ${import_node_path20.default.join(config.dataDir, "frpc.toml")}`,
20262
- `Frpc log: ${import_node_path20.default.join(config.dataDir, "frpc.log")}`
20203
+ `Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
20204
+ `Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
20263
20205
  ];
20264
20206
  const width = Math.max(...lines.map((l) => l.length));
20265
20207
  const bar = "\u2550".repeat(width + 4);
@@ -20272,8 +20214,8 @@ ${bar}
20272
20214
 
20273
20215
  `);
20274
20216
  try {
20275
- const connectPath = import_node_path20.default.join(config.dataDir, "connect.txt");
20276
- import_node_fs20.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
20217
+ const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
20218
+ import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
20277
20219
  } catch {
20278
20220
  }
20279
20221
  } catch (err) {