@clawos-dev/clawd 0.2.250 → 0.2.251

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.
package/dist/cli.cjs CHANGED
@@ -751,8 +751,8 @@ var init_parseUtil = __esm({
751
751
  init_errors2();
752
752
  init_en();
753
753
  makeIssue = (params) => {
754
- const { data, path: path71, errorMaps, issueData } = params;
755
- const fullPath = [...path71, ...issueData.path || []];
754
+ const { data, path: path74, errorMaps, issueData } = params;
755
+ const fullPath = [...path74, ...issueData.path || []];
756
756
  const fullIssue = {
757
757
  ...issueData,
758
758
  path: fullPath
@@ -1063,11 +1063,11 @@ var init_types = __esm({
1063
1063
  init_parseUtil();
1064
1064
  init_util();
1065
1065
  ParseInputLazyPath = class {
1066
- constructor(parent, value, path71, key) {
1066
+ constructor(parent, value, path74, key) {
1067
1067
  this._cachedPath = [];
1068
1068
  this.parent = parent;
1069
1069
  this.data = value;
1070
- this._path = path71;
1070
+ this._path = path74;
1071
1071
  this._key = key;
1072
1072
  }
1073
1073
  get path() {
@@ -6615,8 +6615,8 @@ var require_req = __commonJS({
6615
6615
  if (req.originalUrl) {
6616
6616
  _req.url = req.originalUrl;
6617
6617
  } else {
6618
- const path71 = req.path;
6619
- _req.url = typeof path71 === "string" ? path71 : req.url ? req.url.path || req.url : void 0;
6618
+ const path74 = req.path;
6619
+ _req.url = typeof path74 === "string" ? path74 : req.url ? req.url.path || req.url : void 0;
6620
6620
  }
6621
6621
  if (req.query) {
6622
6622
  _req.query = req.query;
@@ -6781,14 +6781,14 @@ var require_redact = __commonJS({
6781
6781
  }
6782
6782
  return obj;
6783
6783
  }
6784
- function parsePath(path71) {
6784
+ function parsePath(path74) {
6785
6785
  const parts = [];
6786
6786
  let current = "";
6787
6787
  let inBrackets = false;
6788
6788
  let inQuotes = false;
6789
6789
  let quoteChar = "";
6790
- for (let i = 0; i < path71.length; i++) {
6791
- const char = path71[i];
6790
+ for (let i = 0; i < path74.length; i++) {
6791
+ const char = path74[i];
6792
6792
  if (!inBrackets && char === ".") {
6793
6793
  if (current) {
6794
6794
  parts.push(current);
@@ -6919,10 +6919,10 @@ var require_redact = __commonJS({
6919
6919
  return current;
6920
6920
  }
6921
6921
  function redactPaths(obj, paths, censor, remove = false) {
6922
- for (const path71 of paths) {
6923
- const parts = parsePath(path71);
6922
+ for (const path74 of paths) {
6923
+ const parts = parsePath(path74);
6924
6924
  if (parts.includes("*")) {
6925
- redactWildcardPath(obj, parts, censor, path71, remove);
6925
+ redactWildcardPath(obj, parts, censor, path74, remove);
6926
6926
  } else {
6927
6927
  if (remove) {
6928
6928
  removeKey(obj, parts);
@@ -7007,8 +7007,8 @@ var require_redact = __commonJS({
7007
7007
  }
7008
7008
  } else {
7009
7009
  if (afterWildcard.includes("*")) {
7010
- const wrappedCensor = typeof censor === "function" ? (value, path71) => {
7011
- const fullPath = [...pathArray.slice(0, pathLength), ...path71];
7010
+ const wrappedCensor = typeof censor === "function" ? (value, path74) => {
7011
+ const fullPath = [...pathArray.slice(0, pathLength), ...path74];
7012
7012
  return censor(value, fullPath);
7013
7013
  } : censor;
7014
7014
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -7043,8 +7043,8 @@ var require_redact = __commonJS({
7043
7043
  return null;
7044
7044
  }
7045
7045
  const pathStructure = /* @__PURE__ */ new Map();
7046
- for (const path71 of pathsToClone) {
7047
- const parts = parsePath(path71);
7046
+ for (const path74 of pathsToClone) {
7047
+ const parts = parsePath(path74);
7048
7048
  let current = pathStructure;
7049
7049
  for (let i = 0; i < parts.length; i++) {
7050
7050
  const part = parts[i];
@@ -7096,24 +7096,24 @@ var require_redact = __commonJS({
7096
7096
  }
7097
7097
  return cloneSelectively(obj, pathStructure);
7098
7098
  }
7099
- function validatePath(path71) {
7100
- if (typeof path71 !== "string") {
7099
+ function validatePath(path74) {
7100
+ if (typeof path74 !== "string") {
7101
7101
  throw new Error("Paths must be (non-empty) strings");
7102
7102
  }
7103
- if (path71 === "") {
7103
+ if (path74 === "") {
7104
7104
  throw new Error("Invalid redaction path ()");
7105
7105
  }
7106
- if (path71.includes("..")) {
7107
- throw new Error(`Invalid redaction path (${path71})`);
7106
+ if (path74.includes("..")) {
7107
+ throw new Error(`Invalid redaction path (${path74})`);
7108
7108
  }
7109
- if (path71.includes(",")) {
7110
- throw new Error(`Invalid redaction path (${path71})`);
7109
+ if (path74.includes(",")) {
7110
+ throw new Error(`Invalid redaction path (${path74})`);
7111
7111
  }
7112
7112
  let bracketCount = 0;
7113
7113
  let inQuotes = false;
7114
7114
  let quoteChar = "";
7115
- for (let i = 0; i < path71.length; i++) {
7116
- const char = path71[i];
7115
+ for (let i = 0; i < path74.length; i++) {
7116
+ const char = path74[i];
7117
7117
  if ((char === '"' || char === "'") && bracketCount > 0) {
7118
7118
  if (!inQuotes) {
7119
7119
  inQuotes = true;
@@ -7127,20 +7127,20 @@ var require_redact = __commonJS({
7127
7127
  } else if (char === "]" && !inQuotes) {
7128
7128
  bracketCount--;
7129
7129
  if (bracketCount < 0) {
7130
- throw new Error(`Invalid redaction path (${path71})`);
7130
+ throw new Error(`Invalid redaction path (${path74})`);
7131
7131
  }
7132
7132
  }
7133
7133
  }
7134
7134
  if (bracketCount !== 0) {
7135
- throw new Error(`Invalid redaction path (${path71})`);
7135
+ throw new Error(`Invalid redaction path (${path74})`);
7136
7136
  }
7137
7137
  }
7138
7138
  function validatePaths(paths) {
7139
7139
  if (!Array.isArray(paths)) {
7140
7140
  throw new TypeError("paths must be an array");
7141
7141
  }
7142
- for (const path71 of paths) {
7143
- validatePath(path71);
7142
+ for (const path74 of paths) {
7143
+ validatePath(path74);
7144
7144
  }
7145
7145
  }
7146
7146
  function slowRedact(options = {}) {
@@ -7308,8 +7308,8 @@ var require_redaction = __commonJS({
7308
7308
  if (shape[k2] === null) {
7309
7309
  o[k2] = (value) => topCensor(value, [k2]);
7310
7310
  } else {
7311
- const wrappedCensor = typeof censor === "function" ? (value, path71) => {
7312
- return censor(value, [k2, ...path71]);
7311
+ const wrappedCensor = typeof censor === "function" ? (value, path74) => {
7312
+ return censor(value, [k2, ...path74]);
7313
7313
  } : censor;
7314
7314
  o[k2] = Redact({
7315
7315
  paths: shape[k2],
@@ -7527,10 +7527,10 @@ var require_atomic_sleep = __commonJS({
7527
7527
  var require_sonic_boom = __commonJS({
7528
7528
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7529
7529
  "use strict";
7530
- var fs65 = require("fs");
7530
+ var fs66 = require("fs");
7531
7531
  var EventEmitter3 = require("events");
7532
7532
  var inherits = require("util").inherits;
7533
- var path71 = require("path");
7533
+ var path74 = require("path");
7534
7534
  var sleep2 = require_atomic_sleep();
7535
7535
  var assert = require("assert");
7536
7536
  var BUSY_WRITE_TIMEOUT = 100;
@@ -7584,20 +7584,20 @@ var require_sonic_boom = __commonJS({
7584
7584
  const mode = sonic.mode;
7585
7585
  if (sonic.sync) {
7586
7586
  try {
7587
- if (sonic.mkdir) fs65.mkdirSync(path71.dirname(file), { recursive: true });
7588
- const fd = fs65.openSync(file, flags, mode);
7587
+ if (sonic.mkdir) fs66.mkdirSync(path74.dirname(file), { recursive: true });
7588
+ const fd = fs66.openSync(file, flags, mode);
7589
7589
  fileOpened(null, fd);
7590
7590
  } catch (err) {
7591
7591
  fileOpened(err);
7592
7592
  throw err;
7593
7593
  }
7594
7594
  } else if (sonic.mkdir) {
7595
- fs65.mkdir(path71.dirname(file), { recursive: true }, (err) => {
7595
+ fs66.mkdir(path74.dirname(file), { recursive: true }, (err) => {
7596
7596
  if (err) return fileOpened(err);
7597
- fs65.open(file, flags, mode, fileOpened);
7597
+ fs66.open(file, flags, mode, fileOpened);
7598
7598
  });
7599
7599
  } else {
7600
- fs65.open(file, flags, mode, fileOpened);
7600
+ fs66.open(file, flags, mode, fileOpened);
7601
7601
  }
7602
7602
  }
7603
7603
  function SonicBoom(opts) {
@@ -7638,8 +7638,8 @@ var require_sonic_boom = __commonJS({
7638
7638
  this.flush = flushBuffer;
7639
7639
  this.flushSync = flushBufferSync;
7640
7640
  this._actualWrite = actualWriteBuffer;
7641
- fsWriteSync = () => fs65.writeSync(this.fd, this._writingBuf);
7642
- fsWrite = () => fs65.write(this.fd, this._writingBuf, this.release);
7641
+ fsWriteSync = () => fs66.writeSync(this.fd, this._writingBuf);
7642
+ fsWrite = () => fs66.write(this.fd, this._writingBuf, this.release);
7643
7643
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7644
7644
  this._writingBuf = "";
7645
7645
  this.write = write;
@@ -7648,15 +7648,15 @@ var require_sonic_boom = __commonJS({
7648
7648
  this._actualWrite = actualWrite;
7649
7649
  fsWriteSync = () => {
7650
7650
  if (Buffer.isBuffer(this._writingBuf)) {
7651
- return fs65.writeSync(this.fd, this._writingBuf);
7651
+ return fs66.writeSync(this.fd, this._writingBuf);
7652
7652
  }
7653
- return fs65.writeSync(this.fd, this._writingBuf, "utf8");
7653
+ return fs66.writeSync(this.fd, this._writingBuf, "utf8");
7654
7654
  };
7655
7655
  fsWrite = () => {
7656
7656
  if (Buffer.isBuffer(this._writingBuf)) {
7657
- return fs65.write(this.fd, this._writingBuf, this.release);
7657
+ return fs66.write(this.fd, this._writingBuf, this.release);
7658
7658
  }
7659
- return fs65.write(this.fd, this._writingBuf, "utf8", this.release);
7659
+ return fs66.write(this.fd, this._writingBuf, "utf8", this.release);
7660
7660
  };
7661
7661
  } else {
7662
7662
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7713,7 +7713,7 @@ var require_sonic_boom = __commonJS({
7713
7713
  }
7714
7714
  }
7715
7715
  if (this._fsync) {
7716
- fs65.fsyncSync(this.fd);
7716
+ fs66.fsyncSync(this.fd);
7717
7717
  }
7718
7718
  const len = this._len;
7719
7719
  if (this._reopening) {
@@ -7827,7 +7827,7 @@ var require_sonic_boom = __commonJS({
7827
7827
  const onDrain = () => {
7828
7828
  if (!this._fsync) {
7829
7829
  try {
7830
- fs65.fsync(this.fd, (err) => {
7830
+ fs66.fsync(this.fd, (err) => {
7831
7831
  this._flushPending = false;
7832
7832
  cb(err);
7833
7833
  });
@@ -7929,7 +7929,7 @@ var require_sonic_boom = __commonJS({
7929
7929
  const fd = this.fd;
7930
7930
  this.once("ready", () => {
7931
7931
  if (fd !== this.fd) {
7932
- fs65.close(fd, (err) => {
7932
+ fs66.close(fd, (err) => {
7933
7933
  if (err) {
7934
7934
  return this.emit("error", err);
7935
7935
  }
@@ -7978,7 +7978,7 @@ var require_sonic_boom = __commonJS({
7978
7978
  buf = this._bufs[0];
7979
7979
  }
7980
7980
  try {
7981
- const n = Buffer.isBuffer(buf) ? fs65.writeSync(this.fd, buf) : fs65.writeSync(this.fd, buf, "utf8");
7981
+ const n = Buffer.isBuffer(buf) ? fs66.writeSync(this.fd, buf) : fs66.writeSync(this.fd, buf, "utf8");
7982
7982
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7983
7983
  buf = releasedBufObj.writingBuf;
7984
7984
  this._len = releasedBufObj.len;
@@ -7994,7 +7994,7 @@ var require_sonic_boom = __commonJS({
7994
7994
  }
7995
7995
  }
7996
7996
  try {
7997
- fs65.fsyncSync(this.fd);
7997
+ fs66.fsyncSync(this.fd);
7998
7998
  } catch {
7999
7999
  }
8000
8000
  }
@@ -8015,7 +8015,7 @@ var require_sonic_boom = __commonJS({
8015
8015
  buf = mergeBuf(this._bufs[0], this._lens[0]);
8016
8016
  }
8017
8017
  try {
8018
- const n = fs65.writeSync(this.fd, buf);
8018
+ const n = fs66.writeSync(this.fd, buf);
8019
8019
  buf = buf.subarray(n);
8020
8020
  this._len = Math.max(this._len - n, 0);
8021
8021
  if (buf.length <= 0) {
@@ -8043,13 +8043,13 @@ var require_sonic_boom = __commonJS({
8043
8043
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
8044
8044
  if (this.sync) {
8045
8045
  try {
8046
- const written = Buffer.isBuffer(this._writingBuf) ? fs65.writeSync(this.fd, this._writingBuf) : fs65.writeSync(this.fd, this._writingBuf, "utf8");
8046
+ const written = Buffer.isBuffer(this._writingBuf) ? fs66.writeSync(this.fd, this._writingBuf) : fs66.writeSync(this.fd, this._writingBuf, "utf8");
8047
8047
  release(null, written);
8048
8048
  } catch (err) {
8049
8049
  release(err);
8050
8050
  }
8051
8051
  } else {
8052
- fs65.write(this.fd, this._writingBuf, release);
8052
+ fs66.write(this.fd, this._writingBuf, release);
8053
8053
  }
8054
8054
  }
8055
8055
  function actualWriteBuffer() {
@@ -8058,7 +8058,7 @@ var require_sonic_boom = __commonJS({
8058
8058
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
8059
8059
  if (this.sync) {
8060
8060
  try {
8061
- const written = fs65.writeSync(this.fd, this._writingBuf);
8061
+ const written = fs66.writeSync(this.fd, this._writingBuf);
8062
8062
  release(null, written);
8063
8063
  } catch (err) {
8064
8064
  release(err);
@@ -8067,7 +8067,7 @@ var require_sonic_boom = __commonJS({
8067
8067
  if (kCopyBuffer) {
8068
8068
  this._writingBuf = Buffer.from(this._writingBuf);
8069
8069
  }
8070
- fs65.write(this.fd, this._writingBuf, release);
8070
+ fs66.write(this.fd, this._writingBuf, release);
8071
8071
  }
8072
8072
  }
8073
8073
  function actualClose(sonic) {
@@ -8083,12 +8083,12 @@ var require_sonic_boom = __commonJS({
8083
8083
  sonic._lens = [];
8084
8084
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
8085
8085
  try {
8086
- fs65.fsync(sonic.fd, closeWrapped);
8086
+ fs66.fsync(sonic.fd, closeWrapped);
8087
8087
  } catch {
8088
8088
  }
8089
8089
  function closeWrapped() {
8090
8090
  if (sonic.fd !== 1 && sonic.fd !== 2) {
8091
- fs65.close(sonic.fd, done);
8091
+ fs66.close(sonic.fd, done);
8092
8092
  } else {
8093
8093
  done();
8094
8094
  }
@@ -11223,11 +11223,11 @@ var init_lib = __esm({
11223
11223
  }
11224
11224
  }
11225
11225
  },
11226
- addToPath: function addToPath(path71, added, removed, oldPosInc, options) {
11227
- var last = path71.lastComponent;
11226
+ addToPath: function addToPath(path74, added, removed, oldPosInc, options) {
11227
+ var last = path74.lastComponent;
11228
11228
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
11229
11229
  return {
11230
- oldPos: path71.oldPos + oldPosInc,
11230
+ oldPos: path74.oldPos + oldPosInc,
11231
11231
  lastComponent: {
11232
11232
  count: last.count + 1,
11233
11233
  added,
@@ -11237,7 +11237,7 @@ var init_lib = __esm({
11237
11237
  };
11238
11238
  } else {
11239
11239
  return {
11240
- oldPos: path71.oldPos + oldPosInc,
11240
+ oldPos: path74.oldPos + oldPosInc,
11241
11241
  lastComponent: {
11242
11242
  count: 1,
11243
11243
  added,
@@ -11746,10 +11746,10 @@ function attachmentToHistoryMessage(o, ts) {
11746
11746
  const memories = raw.map((m2) => {
11747
11747
  if (!m2 || typeof m2 !== "object") return null;
11748
11748
  const rec3 = m2;
11749
- const path71 = typeof rec3.path === "string" ? rec3.path : null;
11749
+ const path74 = typeof rec3.path === "string" ? rec3.path : null;
11750
11750
  const content = typeof rec3.content === "string" ? rec3.content : null;
11751
- if (!path71 || content == null) return null;
11752
- const entry = { path: path71, content };
11751
+ if (!path74 || content == null) return null;
11752
+ const entry = { path: path74, content };
11753
11753
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11754
11754
  return entry;
11755
11755
  }).filter((m2) => m2 !== null);
@@ -12552,10 +12552,10 @@ function parseAttachment(obj) {
12552
12552
  const memories = raw.map((m2) => {
12553
12553
  if (!m2 || typeof m2 !== "object") return null;
12554
12554
  const rec3 = m2;
12555
- const path71 = typeof rec3.path === "string" ? rec3.path : null;
12555
+ const path74 = typeof rec3.path === "string" ? rec3.path : null;
12556
12556
  const content = typeof rec3.content === "string" ? rec3.content : null;
12557
- if (!path71 || content == null) return null;
12558
- const out = { path: path71, content };
12557
+ if (!path74 || content == null) return null;
12558
+ const out = { path: path74, content };
12559
12559
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12560
12560
  return out;
12561
12561
  }).filter((m2) => m2 !== null);
@@ -33524,8 +33524,8 @@ var require_utils = __commonJS({
33524
33524
  var result = transform[inputType][outputType](input);
33525
33525
  return result;
33526
33526
  };
33527
- exports2.resolve = function(path71) {
33528
- var parts = path71.split("/");
33527
+ exports2.resolve = function(path74) {
33528
+ var parts = path74.split("/");
33529
33529
  var result = [];
33530
33530
  for (var index = 0; index < parts.length; index++) {
33531
33531
  var part = parts[index];
@@ -39378,18 +39378,18 @@ var require_object = __commonJS({
39378
39378
  var object = new ZipObject(name, zipObjectContent, o);
39379
39379
  this.files[name] = object;
39380
39380
  };
39381
- var parentFolder = function(path71) {
39382
- if (path71.slice(-1) === "/") {
39383
- path71 = path71.substring(0, path71.length - 1);
39381
+ var parentFolder = function(path74) {
39382
+ if (path74.slice(-1) === "/") {
39383
+ path74 = path74.substring(0, path74.length - 1);
39384
39384
  }
39385
- var lastSlash = path71.lastIndexOf("/");
39386
- return lastSlash > 0 ? path71.substring(0, lastSlash) : "";
39385
+ var lastSlash = path74.lastIndexOf("/");
39386
+ return lastSlash > 0 ? path74.substring(0, lastSlash) : "";
39387
39387
  };
39388
- var forceTrailingSlash = function(path71) {
39389
- if (path71.slice(-1) !== "/") {
39390
- path71 += "/";
39388
+ var forceTrailingSlash = function(path74) {
39389
+ if (path74.slice(-1) !== "/") {
39390
+ path74 += "/";
39391
39391
  }
39392
- return path71;
39392
+ return path74;
39393
39393
  };
39394
39394
  var folderAdd = function(name, createFolders) {
39395
39395
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -40391,7 +40391,7 @@ var require_lib3 = __commonJS({
40391
40391
  // src/run-case/recorder.ts
40392
40392
  function startRunCaseRecorder(opts) {
40393
40393
  const now = opts.now ?? Date.now;
40394
- const dir = import_node_path59.default.dirname(opts.recordPath);
40394
+ const dir = import_node_path62.default.dirname(opts.recordPath);
40395
40395
  let stream = null;
40396
40396
  let closing = false;
40397
40397
  let closedSettled = false;
@@ -40405,8 +40405,8 @@ function startRunCaseRecorder(opts) {
40405
40405
  });
40406
40406
  const ensureStream = () => {
40407
40407
  if (stream) return stream;
40408
- import_node_fs46.default.mkdirSync(dir, { recursive: true });
40409
- stream = import_node_fs46.default.createWriteStream(opts.recordPath, { flags: "a" });
40408
+ import_node_fs47.default.mkdirSync(dir, { recursive: true });
40409
+ stream = import_node_fs47.default.createWriteStream(opts.recordPath, { flags: "a" });
40410
40410
  stream.on("close", () => closedResolve());
40411
40411
  return stream;
40412
40412
  };
@@ -40431,12 +40431,12 @@ function startRunCaseRecorder(opts) {
40431
40431
  };
40432
40432
  return { tap, close, closed };
40433
40433
  }
40434
- var import_node_fs46, import_node_path59;
40434
+ var import_node_fs47, import_node_path62;
40435
40435
  var init_recorder = __esm({
40436
40436
  "src/run-case/recorder.ts"() {
40437
40437
  "use strict";
40438
- import_node_fs46 = __toESM(require("fs"), 1);
40439
- import_node_path59 = __toESM(require("path"), 1);
40438
+ import_node_fs47 = __toESM(require("fs"), 1);
40439
+ import_node_path62 = __toESM(require("path"), 1);
40440
40440
  }
40441
40441
  });
40442
40442
 
@@ -40479,7 +40479,7 @@ var init_wire = __esm({
40479
40479
  // src/run-case/controller.ts
40480
40480
  async function runController(opts) {
40481
40481
  const now = opts.now ?? Date.now;
40482
- const cwd = opts.cwd ?? (0, import_node_fs47.mkdtempSync)(import_node_path60.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
40482
+ const cwd = opts.cwd ?? (0, import_node_fs48.mkdtempSync)(import_node_path63.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
40483
40483
  const ownsCwd = opts.cwd === void 0;
40484
40484
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
40485
40485
  const spawnCtx = { cwd };
@@ -40640,19 +40640,19 @@ async function runController(opts) {
40640
40640
  if (sigintHandler) process.off("SIGINT", sigintHandler);
40641
40641
  if (ownsCwd) {
40642
40642
  try {
40643
- (0, import_node_fs47.rmSync)(cwd, { recursive: true, force: true });
40643
+ (0, import_node_fs48.rmSync)(cwd, { recursive: true, force: true });
40644
40644
  } catch {
40645
40645
  }
40646
40646
  }
40647
40647
  return exitCode ?? 0;
40648
40648
  }
40649
- var import_node_fs47, import_node_os23, import_node_path60;
40649
+ var import_node_fs48, import_node_os23, import_node_path63;
40650
40650
  var init_controller = __esm({
40651
40651
  "src/run-case/controller.ts"() {
40652
40652
  "use strict";
40653
- import_node_fs47 = require("fs");
40653
+ import_node_fs48 = require("fs");
40654
40654
  import_node_os23 = __toESM(require("os"), 1);
40655
- import_node_path60 = __toESM(require("path"), 1);
40655
+ import_node_path63 = __toESM(require("path"), 1);
40656
40656
  init_claude();
40657
40657
  init_stdout_splitter();
40658
40658
  init_permission_stdio();
@@ -40914,8 +40914,8 @@ Env (advanced):
40914
40914
  `;
40915
40915
 
40916
40916
  // src/index.ts
40917
- var import_node_path58 = __toESM(require("path"), 1);
40918
- var import_node_fs45 = __toESM(require("fs"), 1);
40917
+ var import_node_path61 = __toESM(require("path"), 1);
40918
+ var import_node_fs46 = __toESM(require("fs"), 1);
40919
40919
  var import_node_os22 = __toESM(require("os"), 1);
40920
40920
 
40921
40921
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -41918,17 +41918,17 @@ var ATTACHMENT_SHARING_HINT = `## \u628A\u4EA7\u51FA\u6587\u4EF6\u5206\u4EAB\u7E
41918
41918
 
41919
41919
  - \`relPath\` \u5FC5\u987B\u4F20**\u7EDD\u5BF9\u8DEF\u5F84**\uFF08\u4F60\u4EA7\u51FA\u6587\u4EF6\u7684\u771F\u5B9E\u8DEF\u5F84\uFF09\uFF0C\u4E0D\u8981\u4F20\u76F8\u5BF9\u8DEF\u5F84\u3002
41920
41920
  - \u53EA\u80FD\u5206\u4EAB\u4F60\u81EA\u5DF1\u5DE5\u4F5C\u76EE\u5F55\u5185\u7684\u6587\u4EF6\uFF0C\u8D8A\u754C\u4F1A\u88AB\u62D2\u3002
41921
- - \u88AB dispatch \u63A5\u5230\u4EFB\u52A1\u3001\u8981\u56DE\u4F20\u4EA7\u7269\u65F6\uFF1A\u628A\u7B7E\u540D URL \u5199\u8FDB \`personaDispatchComplete\` \u7684 \`text\` \u91CC\uFF08\`filePaths\` \u53EA\u662F\u4F60\u672C\u673A\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u8DE8\u8BBE\u5907\u5BF9\u65B9\u6253\u4E0D\u5F00\uFF0CURL \u624D\u80FD\u6253\u5F00\uFF09\u3002`;
41921
+ - \u88AB dispatch \u63A5\u5230\u4EFB\u52A1\u3001\u8981\u56DE\u4F20\u4EA7\u7269\u65F6\uFF1A\u628A\u7B7E\u540D URL \u5199\u8FDB \`personaDispatchComplete\` tool\uFF08\`clawd-dispatch\` MCP\uFF09\u7684 \`text\` \u91CC\uFF08\`filePaths\` \u53EA\u662F\u4F60\u672C\u673A\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u8DE8\u8BBE\u5907\u5BF9\u65B9\u6253\u4E0D\u5F00\uFF0CURL \u624D\u80FD\u6253\u5F00\uFF09\u3002`;
41922
41922
 
41923
41923
  // src/dispatch/system-prompt.ts
41924
41924
  var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
41925
41925
 
41926
- \u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-app-builder\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 MCP tool \`mcp__clawd-dispatch__personaDispatch\` \u59D4\u6D3E\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
41926
+ \u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-app-builder\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 \`clawd-dispatch\` MCP server \u7684 \`personaDispatch\` tool \u59D4\u6D3E\uFF08\u5404 agent \u5BF9 MCP tool \u7684\u5C55\u793A\u540D\u4E0D\u540C\uFF0C\u5982 claude \u663E\u793A\u4E3A \`mcp__clawd-dispatch__personaDispatch\`\uFF1B\u6309\u4F60\u73AF\u5883\u91CC\u5B9E\u9645\u5217\u51FA\u7684\u540D\u5B57\u8C03\u7528\uFF09\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
41927
41927
 
41928
41928
  - \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
41929
41929
  - \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
41930
41930
 
41931
- tool \u4F1A**\u7ACB\u5373\u8FD4\u56DE** dispatchId\uFF08\u5F02\u6B65\u59D4\u6D3E\uFF09\uFF0C\u5BF9\u65B9\u4EBA\u683C\u5728\u540E\u53F0\u5E72\u6D3B\u3002\u4F60\u544A\u8BC9\u7528\u6237"\u4EFB\u52A1\u5DF2\u4EA4\u529E"\u5373\u53EF\u7ED3\u675F\u672C\u8F6E\u2014\u2014**\u4E0D\u8981\u7B49\u5F85\u3001\u4E0D\u8981\u8F6E\u8BE2**\u3002\u5BF9\u65B9\u5E72\u5B8C\u540E\uFF0C\u7ED3\u679C\u4F1A\u4F5C\u4E3A\u4E00\u6761\u65B0\u6D88\u606F\u81EA\u52A8\u6CE8\u5165\u56DE\u4F60\u7684 session\uFF0C\u4F60\u5C4A\u65F6\u518D\u7EFC\u5408\u8F6C\u8FBE\u7ED9\u7528\u6237\u3002\u60F3\u67E5\u8FDB\u5C55\u65F6\uFF08\u7528\u6237\u95EE\u8D77\uFF09\u8C03 \`mcp__clawd-dispatch__personaDispatchList\`\u3002
41931
+ tool \u4F1A**\u7ACB\u5373\u8FD4\u56DE** dispatchId\uFF08\u5F02\u6B65\u59D4\u6D3E\uFF09\uFF0C\u5BF9\u65B9\u4EBA\u683C\u5728\u540E\u53F0\u5E72\u6D3B\u3002\u4F60\u544A\u8BC9\u7528\u6237"\u4EFB\u52A1\u5DF2\u4EA4\u529E"\u5373\u53EF\u7ED3\u675F\u672C\u8F6E\u2014\u2014**\u4E0D\u8981\u7B49\u5F85\u3001\u4E0D\u8981\u8F6E\u8BE2**\u3002\u5BF9\u65B9\u5E72\u5B8C\u540E\uFF0C\u7ED3\u679C\u4F1A\u4F5C\u4E3A\u4E00\u6761\u65B0\u6D88\u606F\u81EA\u52A8\u6CE8\u5165\u56DE\u4F60\u7684 session\uFF0C\u4F60\u5C4A\u65F6\u518D\u7EFC\u5408\u8F6C\u8FBE\u7ED9\u7528\u6237\u3002\u60F3\u67E5\u8FDB\u5C55\u65F6\uFF08\u7528\u6237\u95EE\u8D77\uFF09\u8C03\u540C\u4E00 MCP \u7684 \`personaDispatchList\`\u3002
41932
41932
 
41933
41933
  - **\u4E0D\u8981**\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF08\u4F60\u4E0D\u662F\u90A3\u4E2A persona\uFF09
41934
41934
  - **\u4E0D\u8981** in-place \u6A21\u4EFF\u5BF9\u65B9\u4EBA\u683C \u2014\u2014 dispatch \u662F\u771F\u5207\u5230\u53E6\u4E00\u4E2A\u72EC\u7ACB session
@@ -41953,7 +41953,7 @@ deviceId \u76F4\u63A5\u53D6\u81EA token\uFF0C\u4E0D\u8981\u6539\u5199\u6216\u731
41953
41953
 
41954
41954
  - \u4EFB\u52A1\u5728 \`Task:\` \u6BB5
41955
41955
  - \u539F\u4F1A\u8BDD\u7684\u5BF9\u8BDD\u5386\u53F2\u5728 \`Source conversation\` \u6BB5\u7ED9\u7684 jsonl \u8DEF\u5F84\u4E0B\uFF1B\u6309\u9700 Read \u5B83\u4E86\u89E3\u4E0A\u4E0B\u6587\uFF08\u4E0D\u5FC5\u8BFB\u5B8C\uFF09
41956
- - \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`mcp__clawd-dispatch__personaDispatchComplete\` \u62A5\u544A\u7ED3\u679C\uFF1A
41956
+ - \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`clawd-dispatch\` MCP \u7684 \`personaDispatchComplete\` tool \u62A5\u544A\u7ED3\u679C\uFF1A
41957
41957
  - \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
41958
41958
  - \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "..." }\`
41959
41959
  - \u62A5\u544A\u5B8C\u540E\u4F60\u7684 session \u5C31\u7ED3\u675F\u4E86\uFF0C\u4E0D\u8981\u7EE7\u7EED\u8F93\u51FA`;
@@ -43353,7 +43353,8 @@ Source conversation (jsonl, CC stream-json format, one message per line):
43353
43353
  ${args.sourceJsonlPath}
43354
43354
  You may read this file with your Read tool to understand context. You do not have to read it all.
43355
43355
 
43356
- When done, call the MCP tool \`mcp__clawd-dispatch__personaDispatchComplete\` with your result:
43356
+ When done, call the \`personaDispatchComplete\` tool from the \`clawd-dispatch\` MCP server with your result
43357
+ (tool display name varies by agent, e.g. \`mcp__clawd-dispatch__personaDispatchComplete\` in claude):
43357
43358
  - Success: { text: "...", filePaths?: ["abs/path", ...] }
43358
43359
  - Failure: { isFailure: true, reason: "..." }
43359
43360
 
@@ -43658,18 +43659,20 @@ var SessionManager = class {
43658
43659
  `newRunner: guest session ${file.sessionId} \u7F3A personaRoot/userWorkDir\uFF0C\u65E0\u6CD5\u7269\u5316 OS \u6C99\u7BB1\uFF08\u62D2\u7EDD\u521B\u5EFA\u65E0\u6C99\u7BB1 guest\uFF09`
43659
43660
  );
43660
43661
  }
43661
- const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
43662
- const sandboxSettings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43663
- const ownerCreds = readOwnerCredentials(import_node_os5.default.homedir(), this.deps.logger);
43664
- const merged = mergeOwnerCredentials(sandboxSettings, ownerCreds);
43665
- if (ownerCreds) {
43666
- this.deps.logger?.info("owner credentials injected into guest spawn", {
43667
- sessionId: file.sessionId,
43668
- envKeys: ownerCreds.env ? Object.keys(ownerCreds.env) : [],
43669
- apiKeyHelper: ownerCreds.apiKeyHelper ? "present" : "absent"
43670
- });
43662
+ if ((file.tool ?? "claude") === "claude") {
43663
+ const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
43664
+ const sandboxSettings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43665
+ const ownerCreds = readOwnerCredentials(import_node_os5.default.homedir(), this.deps.logger);
43666
+ const merged = mergeOwnerCredentials(sandboxSettings, ownerCreds);
43667
+ if (ownerCreds) {
43668
+ this.deps.logger?.info("owner credentials injected into guest spawn", {
43669
+ sessionId: file.sessionId,
43670
+ envKeys: ownerCreds.env ? Object.keys(ownerCreds.env) : [],
43671
+ apiKeyHelper: ownerCreds.apiKeyHelper ? "present" : "absent"
43672
+ });
43673
+ }
43674
+ subSessionMeta.extraSettings = JSON.stringify(merged);
43671
43675
  }
43672
- subSessionMeta.extraSettings = JSON.stringify(merged);
43673
43676
  const home = import_node_os5.default.homedir();
43674
43677
  const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path9.default.join(home, p2.slice(2)) : p2;
43675
43678
  const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
@@ -44719,7 +44722,9 @@ var SessionManager = class {
44719
44722
  const file = {
44720
44723
  sessionId,
44721
44724
  cwd,
44722
- tool: "claude",
44725
+ // dispatch B session 跟随 persona 绑定的 tool(codex persona 用 codex spawn),
44726
+ // 与 UI 手建路径(handlers/session.ts create 的 persona.tool 优先)同语义
44727
+ tool: this.deps.getPersonaTool?.(args.targetPersona) ?? "claude",
44723
44728
  ownerPersonaId: args.targetPersona,
44724
44729
  dispatchedFromSessionId: args.sourceSessionId,
44725
44730
  // 跨设备显示关键(spec §8):creatorPrincipalId = A 的 deviceId,让 A 的
@@ -44809,7 +44814,8 @@ var SessionManager = class {
44809
44814
  const file = {
44810
44815
  sessionId,
44811
44816
  cwd,
44812
- tool: "claude",
44817
+ // shift 定时 spawn 同样跟随 persona 绑定 tool(对齐 dispatch B session)
44818
+ tool: this.deps.getPersonaTool?.(args.targetPersona) ?? "claude",
44813
44819
  ownerPersonaId: args.targetPersona,
44814
44820
  ...args.sourceSessionId ? { shiftFiredFromSessionId: args.sourceSessionId } : {},
44815
44821
  createdAt: now,
@@ -46185,6 +46191,9 @@ function refreshDaemonManagedDirs(args) {
46185
46191
  const dstPath = path14.join(personaDir, relPath);
46186
46192
  try {
46187
46193
  fs12.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46194
+ if (relPath === "CLAUDE.md") {
46195
+ fs12.cpSync(srcPath, path14.join(personaDir, "AGENTS.md"), { force: true, dereference: true });
46196
+ }
46188
46197
  args.logger.info("persona.refresh.synced", {
46189
46198
  personaId: entry.personaId,
46190
46199
  path: relPath
@@ -46552,11 +46561,12 @@ function createVisitorStore(opts) {
46552
46561
  init_claude();
46553
46562
 
46554
46563
  // src/tools/codex.ts
46555
- var import_node_child_process4 = require("child_process");
46556
- var import_node_fs17 = __toESM(require("fs"), 1);
46564
+ var import_node_child_process5 = require("child_process");
46565
+ var import_node_fs18 = __toESM(require("fs"), 1);
46557
46566
 
46558
46567
  // src/tools/codex-session.ts
46559
- var import_node_child_process3 = require("child_process");
46568
+ var import_node_child_process4 = require("child_process");
46569
+ var import_node_path16 = __toESM(require("path"), 1);
46560
46570
 
46561
46571
  // src/tools/codex-app-server-client.ts
46562
46572
  var import_node_readline = require("readline");
@@ -46739,7 +46749,7 @@ function resolveApprovalPolicy(ctx) {
46739
46749
  if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
46740
46750
  return "on-request";
46741
46751
  }
46742
- function buildCodexGuestConfig(cs) {
46752
+ function buildCodexGuestConfig(cs, opts = {}) {
46743
46753
  const filesystem = {};
46744
46754
  for (const w2 of cs.writableRoots ?? []) filesystem[w2] = "write";
46745
46755
  const deny = cs.denyRead ?? [];
@@ -46754,7 +46764,7 @@ function buildCodexGuestConfig(cs) {
46754
46764
  clawos_guest: {
46755
46765
  extends: ":workspace",
46756
46766
  filesystem,
46757
- network: cs.network ? { enabled: true, domains: { "*": "allow" } } : { enabled: false }
46767
+ network: cs.network ? { enabled: true, domains: { "*": "allow" } } : opts.loopbackDaemonAccess ? { enabled: true, allowed_domains: [], allow_local_binding: true } : { enabled: false }
46758
46768
  }
46759
46769
  }
46760
46770
  };
@@ -46768,15 +46778,32 @@ function tomlValue(v2) {
46768
46778
  }
46769
46779
  return JSON.stringify(v2);
46770
46780
  }
46771
- function codexGuestCliArgs(cs) {
46772
- const cfg = buildCodexGuestConfig(cs);
46781
+ function codexGuestCliArgs(cs, opts = {}) {
46782
+ const cfg = buildCodexGuestConfig(cs, opts);
46773
46783
  const profile = cfg.permissions.clawos_guest;
46774
- return [
46784
+ const args = [
46775
46785
  "-c",
46776
46786
  `default_permissions=${tomlValue("clawos_guest")}`,
46777
46787
  "-c",
46778
46788
  `permissions.clawos_guest=${tomlValue(profile)}`
46779
46789
  ];
46790
+ if (!cs.network && opts.loopbackDaemonAccess) {
46791
+ args.push("-c", "features.network_proxy=true");
46792
+ }
46793
+ return args;
46794
+ }
46795
+ function codexMcpCliArgs(defs) {
46796
+ const out = [];
46797
+ for (const d of defs) {
46798
+ const cfg = {
46799
+ command: d.command,
46800
+ ...d.args && d.args.length > 0 ? { args: d.args } : {},
46801
+ ...d.env && Object.keys(d.env).length > 0 ? { env: d.env } : {}
46802
+ };
46803
+ const key = /^[A-Za-z0-9_-]+$/.test(d.name) ? d.name : JSON.stringify(d.name);
46804
+ out.push("-c", `mcp_servers.${key}=${tomlValue(cfg)}`);
46805
+ }
46806
+ return out;
46780
46807
  }
46781
46808
  function threadStartParams(ctx) {
46782
46809
  const params = {
@@ -46801,8 +46828,8 @@ function turnStartInput(text) {
46801
46828
  const items = [];
46802
46829
  let leftover = text;
46803
46830
  for (const m2 of text.matchAll(SKILL_RE)) {
46804
- const [marker, name, path71] = m2;
46805
- items.push({ type: "skill", name, path: path71 });
46831
+ const [marker, name, path74] = m2;
46832
+ items.push({ type: "skill", name, path: path74 });
46806
46833
  leftover = leftover.replace(marker, "");
46807
46834
  }
46808
46835
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -46817,15 +46844,122 @@ function turnStartInput(text) {
46817
46844
  return items;
46818
46845
  }
46819
46846
 
46847
+ // src/tools/codex-mcp-config.ts
46848
+ var import_node_fs17 = __toESM(require("fs"), 1);
46849
+ var import_node_path15 = __toESM(require("path"), 1);
46850
+ function loadCodexMcpServerDefs(args) {
46851
+ const out = [];
46852
+ const seen = /* @__PURE__ */ new Set();
46853
+ const sources = [...args.mcpConfigPaths, import_node_path15.default.join(args.cwd, ".mcp.json")];
46854
+ for (const file of sources) {
46855
+ let parsed;
46856
+ try {
46857
+ parsed = JSON.parse(import_node_fs17.default.readFileSync(file, "utf8"));
46858
+ } catch (e) {
46859
+ const code = e.code;
46860
+ if (code !== "ENOENT") {
46861
+ args.logger?.warn("codex mcp config unreadable, skipped", { file, code: code ?? "parse-error" });
46862
+ }
46863
+ continue;
46864
+ }
46865
+ const servers = parsed?.mcpServers;
46866
+ if (!servers || typeof servers !== "object") continue;
46867
+ for (const [name, raw] of Object.entries(servers)) {
46868
+ const def = raw ?? {};
46869
+ const type = typeof def.type === "string" ? def.type : "stdio";
46870
+ if (type !== "stdio") {
46871
+ args.logger?.warn("codex mcp server type unsupported, skipped", { file, name, type });
46872
+ continue;
46873
+ }
46874
+ if (typeof def.command !== "string" || !def.command) {
46875
+ args.logger?.warn("codex mcp server missing command, skipped", { file, name });
46876
+ continue;
46877
+ }
46878
+ if (seen.has(name)) {
46879
+ args.logger?.warn("codex mcp server name collision, first-wins", { file, name });
46880
+ continue;
46881
+ }
46882
+ seen.add(name);
46883
+ const fileEnv = def.env && typeof def.env === "object" ? Object.fromEntries(
46884
+ Object.entries(def.env).filter(
46885
+ (kv) => typeof kv[1] === "string"
46886
+ )
46887
+ ) : {};
46888
+ const env = { ...args.baseEnv ?? {}, ...fileEnv };
46889
+ out.push({
46890
+ name,
46891
+ command: def.command,
46892
+ ...Array.isArray(def.args) && def.args.every((a) => typeof a === "string") ? { args: def.args } : {},
46893
+ ...Object.keys(env).length > 0 ? { env } : {}
46894
+ });
46895
+ }
46896
+ }
46897
+ return out;
46898
+ }
46899
+
46900
+ // src/tools/codex-features.ts
46901
+ var import_node_child_process3 = require("child_process");
46902
+ var cachedNetworkProxy;
46903
+ function hasNetworkProxyFeature(deps = {}) {
46904
+ if (cachedNetworkProxy !== void 0) return cachedNetworkProxy;
46905
+ try {
46906
+ const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process3.execFileSync)(process.env.CODEX_BIN ?? "codex", ["features", "list"], {
46907
+ encoding: "utf8",
46908
+ timeout: 3e3
46909
+ });
46910
+ const m2 = /^network_proxy\s+(.+?)\s+(?:true|false)\s*$/m.exec(out);
46911
+ cachedNetworkProxy = m2 !== null && m2[1].trim() !== "removed";
46912
+ } catch {
46913
+ cachedNetworkProxy = false;
46914
+ }
46915
+ return cachedNetworkProxy;
46916
+ }
46917
+ var warming = false;
46918
+ function warmCodexFeatureCache() {
46919
+ if (cachedNetworkProxy !== void 0 || warming) return;
46920
+ warming = true;
46921
+ (0, import_node_child_process3.execFile)(
46922
+ process.env.CODEX_BIN ?? "codex",
46923
+ ["features", "list"],
46924
+ { encoding: "utf8", timeout: 3e3 },
46925
+ (err, stdout) => {
46926
+ warming = false;
46927
+ if (cachedNetworkProxy !== void 0) return;
46928
+ if (err) {
46929
+ cachedNetworkProxy = false;
46930
+ return;
46931
+ }
46932
+ const m2 = /^network_proxy\s+(.+?)\s+(?:true|false)\s*$/m.exec(stdout);
46933
+ cachedNetworkProxy = m2 !== null && m2[1].trim() !== "removed";
46934
+ }
46935
+ );
46936
+ }
46937
+
46820
46938
  // src/tools/codex-session.ts
46821
46939
  function createCodexSession(ctx, sink, deps = {}) {
46822
46940
  const cmd = process.env.CODEX_BIN ?? "codex";
46823
46941
  const args = ["app-server", "--listen", "stdio://"];
46824
46942
  if (ctx.personaMode === "guest" && ctx.codexSandbox) {
46825
- args.push(...codexGuestCliArgs(ctx.codexSandbox));
46943
+ const loopbackDaemonAccess = deps.hasNetworkProxyOverride ? deps.hasNetworkProxyOverride() : hasNetworkProxyFeature();
46944
+ args.push(...codexGuestCliArgs(ctx.codexSandbox, { loopbackDaemonAccess }));
46826
46945
  }
46946
+ const clawdEnv = Object.fromEntries(
46947
+ Object.entries(ctx.env ?? {}).filter(
46948
+ (kv) => kv[0].startsWith("CLAWD_") && typeof kv[1] === "string"
46949
+ )
46950
+ );
46951
+ args.push(
46952
+ ...codexMcpCliArgs(
46953
+ loadCodexMcpServerDefs({
46954
+ mcpConfigPaths: (ctx.mcpConfigs ?? []).map((m2) => m2.path),
46955
+ cwd: ctx.cwd,
46956
+ baseEnv: clawdEnv,
46957
+ logger: deps.logger
46958
+ })
46959
+ )
46960
+ );
46827
46961
  const env = { ...process.env, ...ctx.env };
46828
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process3.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
46962
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process4.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
46829
46963
  let threadId = ctx.toolSessionId;
46830
46964
  let turnId;
46831
46965
  const approvalIds = /* @__PURE__ */ new Map();
@@ -46882,6 +47016,7 @@ function createCodexSession(ctx, sink, deps = {}) {
46882
47016
  capabilities: null
46883
47017
  });
46884
47018
  client.notify("initialized", {});
47019
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path16.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
46885
47020
  if (threadId) {
46886
47021
  await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
46887
47022
  } else {
@@ -46928,6 +47063,7 @@ function createCodexSession(ctx, sink, deps = {}) {
46928
47063
  }
46929
47064
 
46930
47065
  // src/tools/codex.ts
47066
+ var CODEX_MODEL_IDS = ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
46931
47067
  var CODEX_MODELS = [
46932
47068
  { id: "", label: "Default", description: "codex config.toml \u9ED8\u8BA4", contextWindowSize: 258400, default: true },
46933
47069
  { id: "gpt-5.5", label: "GPT-5.5", description: "Frontier model for complex coding", contextWindowSize: 258400 },
@@ -46986,10 +47122,10 @@ function sanitizeCodexModel(model) {
46986
47122
  return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
46987
47123
  }
46988
47124
  async function probeCodex(env = process.env) {
46989
- if (env.CODEX_BIN && import_node_fs17.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
47125
+ if (env.CODEX_BIN && import_node_fs18.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46990
47126
  try {
46991
- const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
46992
- if (out && import_node_fs17.default.existsSync(out)) return { available: true, path: out };
47127
+ const out = (0, import_node_child_process5.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
47128
+ if (out && import_node_fs18.default.existsSync(out)) return { available: true, path: out };
46993
47129
  } catch {
46994
47130
  }
46995
47131
  return { available: false };
@@ -47035,9 +47171,9 @@ var CodexAdapter = class {
47035
47171
 
47036
47172
  // src/tools/claude-tui.ts
47037
47173
  var import_node_crypto5 = require("crypto");
47038
- var import_node_fs18 = __toESM(require("fs"), 1);
47174
+ var import_node_fs19 = __toESM(require("fs"), 1);
47039
47175
  var import_node_os7 = __toESM(require("os"), 1);
47040
- var import_node_path15 = __toESM(require("path"), 1);
47176
+ var import_node_path17 = __toESM(require("path"), 1);
47041
47177
  var import_headless = __toESM(require_xterm_headless(), 1);
47042
47178
 
47043
47179
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -48270,9 +48406,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
48270
48406
  function jsonlExistsForCtx(ctx) {
48271
48407
  if (!ctx.toolSessionId) return false;
48272
48408
  const home = import_node_os7.default.homedir();
48273
- const file = import_node_path15.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48409
+ const file = import_node_path17.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48274
48410
  try {
48275
- return import_node_fs18.default.statSync(file).isFile();
48411
+ return import_node_fs19.default.statSync(file).isFile();
48276
48412
  } catch {
48277
48413
  return false;
48278
48414
  }
@@ -48382,7 +48518,7 @@ var PersonaDispatchManager = class {
48382
48518
 
48383
48519
  // src/dispatch/store.ts
48384
48520
  var import_promises = __toESM(require("fs/promises"), 1);
48385
- var import_node_path16 = __toESM(require("path"), 1);
48521
+ var import_node_path18 = __toESM(require("path"), 1);
48386
48522
 
48387
48523
  // src/shift/constants.ts
48388
48524
  var MAX_RUNS_PER_SHIFT = 30;
@@ -48420,7 +48556,7 @@ function createDispatchStore(deps) {
48420
48556
  flushTimer = null;
48421
48557
  }
48422
48558
  const content = { version: 1, records };
48423
- await import_promises.default.mkdir(import_node_path16.default.dirname(deps.filePath), { recursive: true });
48559
+ await import_promises.default.mkdir(import_node_path18.default.dirname(deps.filePath), { recursive: true });
48424
48560
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
48425
48561
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
48426
48562
  await import_promises.default.rename(tmp, deps.filePath);
@@ -48482,10 +48618,10 @@ function createDispatchStore(deps) {
48482
48618
  }
48483
48619
 
48484
48620
  // src/dispatch/mcp-config.ts
48485
- var import_node_fs19 = __toESM(require("fs"), 1);
48486
- var import_node_path17 = __toESM(require("path"), 1);
48621
+ var import_node_fs20 = __toESM(require("fs"), 1);
48622
+ var import_node_path19 = __toESM(require("path"), 1);
48487
48623
  function dispatchMcpConfigPath(dataDir) {
48488
- return import_node_path17.default.join(dataDir, "dispatch.mcp.json");
48624
+ return import_node_path19.default.join(dataDir, "dispatch.mcp.json");
48489
48625
  }
48490
48626
  function writeDispatchMcpConfig(args) {
48491
48627
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -48500,16 +48636,16 @@ function writeDispatchMcpConfig(args) {
48500
48636
  }
48501
48637
  }
48502
48638
  };
48503
- import_node_fs19.default.mkdirSync(args.dataDir, { recursive: true });
48504
- import_node_fs19.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48639
+ import_node_fs20.default.mkdirSync(args.dataDir, { recursive: true });
48640
+ import_node_fs20.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48505
48641
  return cfgPath;
48506
48642
  }
48507
48643
 
48508
48644
  // src/ticket/mcp-config.ts
48509
- var import_node_fs20 = __toESM(require("fs"), 1);
48510
- var import_node_path18 = __toESM(require("path"), 1);
48645
+ var import_node_fs21 = __toESM(require("fs"), 1);
48646
+ var import_node_path20 = __toESM(require("path"), 1);
48511
48647
  function ticketMcpConfigPath(dataDir) {
48512
- return import_node_path18.default.join(dataDir, "ticket.mcp.json");
48648
+ return import_node_path20.default.join(dataDir, "ticket.mcp.json");
48513
48649
  }
48514
48650
  function writeTicketMcpConfig(args) {
48515
48651
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -48529,16 +48665,16 @@ function writeTicketMcpConfig(args) {
48529
48665
  }
48530
48666
  }
48531
48667
  };
48532
- import_node_fs20.default.mkdirSync(args.dataDir, { recursive: true });
48533
- import_node_fs20.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48668
+ import_node_fs21.default.mkdirSync(args.dataDir, { recursive: true });
48669
+ import_node_fs21.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48534
48670
  return cfgPath;
48535
48671
  }
48536
48672
 
48537
48673
  // src/shift/mcp-config.ts
48538
- var import_node_fs21 = __toESM(require("fs"), 1);
48539
- var import_node_path19 = __toESM(require("path"), 1);
48674
+ var import_node_fs22 = __toESM(require("fs"), 1);
48675
+ var import_node_path21 = __toESM(require("path"), 1);
48540
48676
  function shiftMcpConfigPath(dataDir) {
48541
- return import_node_path19.default.join(dataDir, "shift.mcp.json");
48677
+ return import_node_path21.default.join(dataDir, "shift.mcp.json");
48542
48678
  }
48543
48679
  async function writeShiftMcpConfig(args) {
48544
48680
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -48553,16 +48689,16 @@ async function writeShiftMcpConfig(args) {
48553
48689
  }
48554
48690
  }
48555
48691
  };
48556
- await import_node_fs21.default.promises.mkdir(args.dataDir, { recursive: true });
48557
- await import_node_fs21.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48692
+ await import_node_fs22.default.promises.mkdir(args.dataDir, { recursive: true });
48693
+ await import_node_fs22.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48558
48694
  return cfgPath;
48559
48695
  }
48560
48696
 
48561
48697
  // src/inbox/mcp-config.ts
48562
- var import_node_fs22 = __toESM(require("fs"), 1);
48563
- var import_node_path20 = __toESM(require("path"), 1);
48698
+ var import_node_fs23 = __toESM(require("fs"), 1);
48699
+ var import_node_path22 = __toESM(require("path"), 1);
48564
48700
  function inboxMcpConfigPath(dataDir) {
48565
- return import_node_path20.default.join(dataDir, "inbox.mcp.json");
48701
+ return import_node_path22.default.join(dataDir, "inbox.mcp.json");
48566
48702
  }
48567
48703
  async function writeInboxMcpConfig(args) {
48568
48704
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -48577,16 +48713,16 @@ async function writeInboxMcpConfig(args) {
48577
48713
  }
48578
48714
  }
48579
48715
  };
48580
- await import_node_fs22.default.promises.mkdir(args.dataDir, { recursive: true });
48581
- await import_node_fs22.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48716
+ await import_node_fs23.default.promises.mkdir(args.dataDir, { recursive: true });
48717
+ await import_node_fs23.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48582
48718
  return cfgPath;
48583
48719
  }
48584
48720
 
48585
48721
  // src/peer-ops/mcp-config.ts
48586
- var import_node_fs23 = __toESM(require("fs"), 1);
48587
- var import_node_path21 = __toESM(require("path"), 1);
48722
+ var import_node_fs24 = __toESM(require("fs"), 1);
48723
+ var import_node_path23 = __toESM(require("path"), 1);
48588
48724
  function peerOpsMcpConfigPath(dataDir) {
48589
- return import_node_path21.default.join(dataDir, "peer-ops.mcp.json");
48725
+ return import_node_path23.default.join(dataDir, "peer-ops.mcp.json");
48590
48726
  }
48591
48727
  function writePeerOpsMcpConfig(args) {
48592
48728
  const cfgPath = peerOpsMcpConfigPath(args.dataDir);
@@ -48599,14 +48735,14 @@ function writePeerOpsMcpConfig(args) {
48599
48735
  }
48600
48736
  }
48601
48737
  };
48602
- import_node_fs23.default.mkdirSync(args.dataDir, { recursive: true });
48603
- import_node_fs23.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
48738
+ import_node_fs24.default.mkdirSync(args.dataDir, { recursive: true });
48739
+ import_node_fs24.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
48604
48740
  return cfgPath;
48605
48741
  }
48606
48742
 
48607
48743
  // src/shift/store.ts
48608
48744
  var import_promises2 = __toESM(require("fs/promises"), 1);
48609
- var import_node_path22 = __toESM(require("path"), 1);
48745
+ var import_node_path24 = __toESM(require("path"), 1);
48610
48746
  var import_node_crypto6 = require("crypto");
48611
48747
 
48612
48748
  // src/shift/schedule.ts
@@ -48681,7 +48817,7 @@ function createShiftStore(deps) {
48681
48817
  flushTimer = null;
48682
48818
  }
48683
48819
  const content = { version: 1, shifts };
48684
- await import_promises2.default.mkdir(import_node_path22.default.dirname(deps.filePath), { recursive: true });
48820
+ await import_promises2.default.mkdir(import_node_path24.default.dirname(deps.filePath), { recursive: true });
48685
48821
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
48686
48822
  await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
48687
48823
  await import_promises2.default.rename(tmp, deps.filePath);
@@ -49114,11 +49250,16 @@ function buildPersonaDispatchHandlers(deps) {
49114
49250
  const { type: _t, requestId: _r, ...rest } = frame;
49115
49251
  const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
49116
49252
  const args = DispatchRunArgsSchema.parse(rest);
49117
- if (args.model !== void 0 && !CLAUDE_MODEL_IDS.includes(args.model)) {
49118
- throw new ClawdError(
49119
- ERROR_CODES.INVALID_PARAM,
49120
- `model '${args.model}' not supported; allowed: ${CLAUDE_MODEL_IDS.join(", ")}`
49121
- );
49253
+ if (args.model !== void 0) {
49254
+ const targetPersona2 = args.targetPersona ?? (args.dispatchId ? deps.store.get(args.dispatchId)?.targetPersonaId : void 0);
49255
+ const targetTool = (targetPersona2 ? deps.getPersonaTool?.(targetPersona2) : void 0) ?? "claude";
49256
+ const allowed = targetTool === "codex" ? CODEX_MODEL_IDS : CLAUDE_MODEL_IDS;
49257
+ if (!allowed.includes(args.model)) {
49258
+ throw new ClawdError(
49259
+ ERROR_CODES.INVALID_PARAM,
49260
+ `model '${args.model}' not supported for tool '${targetTool}'; allowed: ${allowed.join(", ")}`
49261
+ );
49262
+ }
49122
49263
  }
49123
49264
  if (args.dispatchId) {
49124
49265
  if (ctx?.principal.kind === "guest") {
@@ -49453,7 +49594,7 @@ async function forwardPeerExecToPeer(args) {
49453
49594
  }
49454
49595
 
49455
49596
  // src/tools/codex-history.ts
49456
- var import_node_child_process5 = require("child_process");
49597
+ var import_node_child_process6 = require("child_process");
49457
49598
  var DEFAULT_TIMEOUT_MS2 = 8e3;
49458
49599
  function rec2(v2) {
49459
49600
  return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
@@ -49516,7 +49657,7 @@ function threadItemToHistoryMessages(item) {
49516
49657
  async function queryCodexAppServer(cwd, method, params, deps) {
49517
49658
  const cmd = process.env.CODEX_BIN ?? "codex";
49518
49659
  const args = ["app-server", "--listen", "stdio://"];
49519
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process5.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
49660
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
49520
49661
  const client = new CodexAppServerClient(proc, {});
49521
49662
  const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
49522
49663
  let timer;
@@ -49622,7 +49763,8 @@ var CodexHistoryReader = class {
49622
49763
  };
49623
49764
 
49624
49765
  // src/tools/codex-skills.ts
49625
- var import_node_child_process6 = require("child_process");
49766
+ var import_node_child_process7 = require("child_process");
49767
+ var import_node_path25 = __toESM(require("path"), 1);
49626
49768
  var DEFAULT_TIMEOUT_MS3 = 8e3;
49627
49769
  function str3(v2) {
49628
49770
  return typeof v2 === "string" ? v2 : void 0;
@@ -49638,13 +49780,13 @@ function mapSkillsListResponse(res) {
49638
49780
  const r = s ?? {};
49639
49781
  const name = str3(r.name);
49640
49782
  if (!name) continue;
49641
- const path71 = str3(r.path);
49783
+ const path74 = str3(r.path);
49642
49784
  const description = str3(r.description);
49643
49785
  const isPlugin = name.includes(":");
49644
49786
  out.push({
49645
49787
  name,
49646
49788
  source: isPlugin ? "plugin" : "project",
49647
- ...path71 ? { path: path71 } : {},
49789
+ ...path74 ? { path: path74 } : {},
49648
49790
  ...description ? { description } : {},
49649
49791
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49650
49792
  });
@@ -49655,7 +49797,7 @@ function mapSkillsListResponse(res) {
49655
49797
  async function listCodexSkills(cwd, deps = {}) {
49656
49798
  const cmd = process.env.CODEX_BIN ?? "codex";
49657
49799
  const args = ["app-server", "--listen", "stdio://"];
49658
- const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
49800
+ const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
49659
49801
  const client = new CodexAppServerClient(proc, {});
49660
49802
  const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
49661
49803
  let timer;
@@ -49674,6 +49816,7 @@ async function listCodexSkills(cwd, deps = {}) {
49674
49816
  })(),
49675
49817
  timeout
49676
49818
  ]);
49819
+ void client.request("skills/extraRoots/set", { extraRoots: [import_node_path25.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
49677
49820
  const res = await Promise.race([client.request("skills/list", { cwds: [cwd] }), timeout]);
49678
49821
  return mapSkillsListResponse(res);
49679
49822
  } finally {
@@ -49683,23 +49826,23 @@ async function listCodexSkills(cwd, deps = {}) {
49683
49826
  }
49684
49827
 
49685
49828
  // src/workspace/browser.ts
49686
- var import_node_fs24 = __toESM(require("fs"), 1);
49829
+ var import_node_fs25 = __toESM(require("fs"), 1);
49687
49830
  var import_node_os8 = __toESM(require("os"), 1);
49688
- var import_node_path23 = __toESM(require("path"), 1);
49831
+ var import_node_path26 = __toESM(require("path"), 1);
49689
49832
  init_protocol();
49690
49833
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
49691
49834
  function resolveInsideCwd(cwd, subpath) {
49692
- const absCwd = import_node_path23.default.resolve(cwd);
49693
- const joined = import_node_path23.default.resolve(absCwd, subpath ?? ".");
49694
- const rel = import_node_path23.default.relative(absCwd, joined);
49695
- if (rel.startsWith("..") || import_node_path23.default.isAbsolute(rel)) {
49835
+ const absCwd = import_node_path26.default.resolve(cwd);
49836
+ const joined = import_node_path26.default.resolve(absCwd, subpath ?? ".");
49837
+ const rel = import_node_path26.default.relative(absCwd, joined);
49838
+ if (rel.startsWith("..") || import_node_path26.default.isAbsolute(rel)) {
49696
49839
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
49697
49840
  }
49698
49841
  return joined;
49699
49842
  }
49700
49843
  function ensureCwd(cwd) {
49701
49844
  try {
49702
- const stat = import_node_fs24.default.statSync(cwd);
49845
+ const stat = import_node_fs25.default.statSync(cwd);
49703
49846
  if (!stat.isDirectory()) {
49704
49847
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
49705
49848
  }
@@ -49713,7 +49856,7 @@ var WorkspaceBrowser = class {
49713
49856
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
49714
49857
  ensureCwd(cwd);
49715
49858
  const full = resolveInsideCwd(cwd, args.path);
49716
- const dirents = import_node_fs24.default.readdirSync(full, { withFileTypes: true });
49859
+ const dirents = import_node_fs25.default.readdirSync(full, { withFileTypes: true });
49717
49860
  const entries = [];
49718
49861
  for (const d of dirents) {
49719
49862
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -49723,7 +49866,7 @@ var WorkspaceBrowser = class {
49723
49866
  mtime: ""
49724
49867
  };
49725
49868
  try {
49726
- const st = import_node_fs24.default.statSync(import_node_path23.default.join(full, d.name));
49869
+ const st = import_node_fs25.default.statSync(import_node_path26.default.join(full, d.name));
49727
49870
  entry.mtime = new Date(st.mtimeMs).toISOString();
49728
49871
  if (d.isFile()) entry.size = st.size;
49729
49872
  } catch {
@@ -49739,14 +49882,14 @@ var WorkspaceBrowser = class {
49739
49882
  read(args) {
49740
49883
  ensureCwd(args.cwd);
49741
49884
  const full = resolveInsideCwd(args.cwd, args.path);
49742
- const st = import_node_fs24.default.statSync(full);
49885
+ const st = import_node_fs25.default.statSync(full);
49743
49886
  if (!st.isFile()) {
49744
49887
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
49745
49888
  }
49746
49889
  if (st.size > MAX_FILE_BYTES) {
49747
49890
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
49748
49891
  }
49749
- const buf = import_node_fs24.default.readFileSync(full);
49892
+ const buf = import_node_fs25.default.readFileSync(full);
49750
49893
  const isBinary = buf.includes(0);
49751
49894
  if (isBinary) {
49752
49895
  return {
@@ -49768,20 +49911,20 @@ var WorkspaceBrowser = class {
49768
49911
  };
49769
49912
 
49770
49913
  // src/skills/agents-scanner.ts
49771
- var import_node_fs25 = __toESM(require("fs"), 1);
49914
+ var import_node_fs26 = __toESM(require("fs"), 1);
49772
49915
  var import_node_os9 = __toESM(require("os"), 1);
49773
- var import_node_path24 = __toESM(require("path"), 1);
49916
+ var import_node_path27 = __toESM(require("path"), 1);
49774
49917
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
49775
49918
  function isDirLikeSync2(p2) {
49776
49919
  try {
49777
- return import_node_fs25.default.statSync(p2).isDirectory();
49920
+ return import_node_fs26.default.statSync(p2).isDirectory();
49778
49921
  } catch {
49779
49922
  return false;
49780
49923
  }
49781
49924
  }
49782
49925
  function fileExistsSync(p2) {
49783
49926
  try {
49784
- return import_node_fs25.default.statSync(p2).isFile();
49927
+ return import_node_fs26.default.statSync(p2).isFile();
49785
49928
  } catch {
49786
49929
  return false;
49787
49930
  }
@@ -49789,7 +49932,7 @@ function fileExistsSync(p2) {
49789
49932
  function parseAgentFile(filePath) {
49790
49933
  let content;
49791
49934
  try {
49792
- content = import_node_fs25.default.readFileSync(filePath, "utf8");
49935
+ content = import_node_fs26.default.readFileSync(filePath, "utf8");
49793
49936
  } catch {
49794
49937
  return {};
49795
49938
  }
@@ -49802,16 +49945,16 @@ function parseAgentFile(filePath) {
49802
49945
  function scanAgentsDir(dir, source, seen, out) {
49803
49946
  let entries;
49804
49947
  try {
49805
- entries = import_node_fs25.default.readdirSync(dir, { withFileTypes: true });
49948
+ entries = import_node_fs26.default.readdirSync(dir, { withFileTypes: true });
49806
49949
  } catch {
49807
49950
  return;
49808
49951
  }
49809
49952
  for (const ent of entries) {
49810
49953
  if (!ent.name.endsWith(".md")) continue;
49811
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path24.default.join(dir, ent.name)))) {
49954
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path27.default.join(dir, ent.name)))) {
49812
49955
  continue;
49813
49956
  }
49814
- const filePath = import_node_path24.default.join(dir, ent.name);
49957
+ const filePath = import_node_path27.default.join(dir, ent.name);
49815
49958
  const baseName = ent.name.replace(/\.md$/, "");
49816
49959
  if (seen.has(baseName)) continue;
49817
49960
  seen.add(baseName);
@@ -49829,12 +49972,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49829
49972
  function walk2(dir, namespaces) {
49830
49973
  let entries;
49831
49974
  try {
49832
- entries = import_node_fs25.default.readdirSync(dir, { withFileTypes: true });
49975
+ entries = import_node_fs26.default.readdirSync(dir, { withFileTypes: true });
49833
49976
  } catch {
49834
49977
  return;
49835
49978
  }
49836
49979
  for (const ent of entries) {
49837
- const childPath = import_node_path24.default.join(dir, ent.name);
49980
+ const childPath = import_node_path27.default.join(dir, ent.name);
49838
49981
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
49839
49982
  walk2(childPath, [...namespaces, ent.name]);
49840
49983
  continue;
@@ -49859,13 +50002,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49859
50002
  walk2(root, []);
49860
50003
  }
49861
50004
  function readInstalledPlugins2(home) {
49862
- const pluginsDir = import_node_path24.default.join(home, ".claude", "plugins");
49863
- const v2 = import_node_path24.default.join(pluginsDir, "installed_plugins_v2.json");
49864
- const v1 = import_node_path24.default.join(pluginsDir, "installed_plugins.json");
50005
+ const pluginsDir = import_node_path27.default.join(home, ".claude", "plugins");
50006
+ const v2 = import_node_path27.default.join(pluginsDir, "installed_plugins_v2.json");
50007
+ const v1 = import_node_path27.default.join(pluginsDir, "installed_plugins.json");
49865
50008
  let raw = null;
49866
50009
  for (const candidate of [v2, v1]) {
49867
50010
  try {
49868
- raw = import_node_fs25.default.readFileSync(candidate, "utf8");
50011
+ raw = import_node_fs26.default.readFileSync(candidate, "utf8");
49869
50012
  break;
49870
50013
  } catch {
49871
50014
  }
@@ -49890,19 +50033,19 @@ function readInstalledPlugins2(home) {
49890
50033
  return out;
49891
50034
  }
49892
50035
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
49893
- let cur = import_node_path24.default.resolve(startCwd);
49894
- const fsRoot = import_node_path24.default.parse(cur).root;
50036
+ let cur = import_node_path27.default.resolve(startCwd);
50037
+ const fsRoot = import_node_path27.default.parse(cur).root;
49895
50038
  while (true) {
49896
- scanAgentsDir(import_node_path24.default.join(cur, ".claude", "agents"), "project", seen, out);
50039
+ scanAgentsDir(import_node_path27.default.join(cur, ".claude", "agents"), "project", seen, out);
49897
50040
  let hasGit = false;
49898
50041
  try {
49899
- hasGit = import_node_fs25.default.existsSync(import_node_path24.default.join(cur, ".git"));
50042
+ hasGit = import_node_fs26.default.existsSync(import_node_path27.default.join(cur, ".git"));
49900
50043
  } catch {
49901
50044
  }
49902
50045
  if (hasGit) return;
49903
50046
  if (cur === home) return;
49904
50047
  if (cur === fsRoot) return;
49905
- const parent = import_node_path24.default.dirname(cur);
50048
+ const parent = import_node_path27.default.dirname(cur);
49906
50049
  if (parent === cur) return;
49907
50050
  cur = parent;
49908
50051
  }
@@ -49937,7 +50080,7 @@ var AgentsScanner = class {
49937
50080
  }
49938
50081
  const fsBlock = [];
49939
50082
  scanAgentsDir(
49940
- import_node_path24.default.join(this.home, ".claude", "agents"),
50083
+ import_node_path27.default.join(this.home, ".claude", "agents"),
49941
50084
  "global",
49942
50085
  seen,
49943
50086
  fsBlock
@@ -49951,7 +50094,7 @@ var AgentsScanner = class {
49951
50094
  ...this.extraPluginRoots
49952
50095
  ];
49953
50096
  for (const { name, root } of plugins) {
49954
- const agentsRoot = import_node_path24.default.join(root, "agents");
50097
+ const agentsRoot = import_node_path27.default.join(root, "agents");
49955
50098
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
49956
50099
  }
49957
50100
  return [...builtinBlock, ...fsBlock];
@@ -49959,15 +50102,15 @@ var AgentsScanner = class {
49959
50102
  };
49960
50103
 
49961
50104
  // src/observer/session-observer.ts
49962
- var import_node_fs27 = __toESM(require("fs"), 1);
50105
+ var import_node_fs28 = __toESM(require("fs"), 1);
49963
50106
  var import_node_os11 = __toESM(require("os"), 1);
49964
- var import_node_path26 = __toESM(require("path"), 1);
50107
+ var import_node_path29 = __toESM(require("path"), 1);
49965
50108
  init_claude_history();
49966
50109
 
49967
50110
  // src/observer/subagent-meta-observer.ts
49968
- var import_node_fs26 = __toESM(require("fs"), 1);
50111
+ var import_node_fs27 = __toESM(require("fs"), 1);
49969
50112
  var import_node_os10 = __toESM(require("os"), 1);
49970
- var import_node_path25 = __toESM(require("path"), 1);
50113
+ var import_node_path28 = __toESM(require("path"), 1);
49971
50114
  init_claude_history();
49972
50115
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
49973
50116
  var SubagentMetaObserver = class {
@@ -49980,7 +50123,7 @@ var SubagentMetaObserver = class {
49980
50123
  watches = /* @__PURE__ */ new Map();
49981
50124
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
49982
50125
  resolveSubagentDir(cwd, toolSessionId) {
49983
- return import_node_path25.default.join(
50126
+ return import_node_path28.default.join(
49984
50127
  this.home,
49985
50128
  ".claude",
49986
50129
  "projects",
@@ -50010,7 +50153,7 @@ var SubagentMetaObserver = class {
50010
50153
  attachWatcher(w2) {
50011
50154
  if (w2.watcher) return;
50012
50155
  try {
50013
- w2.watcher = import_node_fs26.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
50156
+ w2.watcher = import_node_fs27.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
50014
50157
  if (!name) return;
50015
50158
  const m2 = META_RE.exec(String(name));
50016
50159
  if (!m2) return;
@@ -50022,7 +50165,7 @@ var SubagentMetaObserver = class {
50022
50165
  scan(w2) {
50023
50166
  let entries;
50024
50167
  try {
50025
- entries = import_node_fs26.default.readdirSync(w2.dirPath);
50168
+ entries = import_node_fs27.default.readdirSync(w2.dirPath);
50026
50169
  } catch {
50027
50170
  return;
50028
50171
  }
@@ -50036,10 +50179,10 @@ var SubagentMetaObserver = class {
50036
50179
  if (!m2) return;
50037
50180
  const agentId = m2[1];
50038
50181
  if (w2.emitted.has(agentId)) return;
50039
- const file = import_node_path25.default.join(w2.dirPath, name);
50182
+ const file = import_node_path28.default.join(w2.dirPath, name);
50040
50183
  let raw;
50041
50184
  try {
50042
- raw = import_node_fs26.default.readFileSync(file, "utf8");
50185
+ raw = import_node_fs27.default.readFileSync(file, "utf8");
50043
50186
  } catch {
50044
50187
  return;
50045
50188
  }
@@ -50096,14 +50239,14 @@ var SessionObserver = class {
50096
50239
  metaObserver;
50097
50240
  resolveJsonlPath(cwd, toolSessionId, override) {
50098
50241
  if (override) return override;
50099
- return import_node_path26.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
50242
+ return import_node_path29.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
50100
50243
  }
50101
50244
  start(args) {
50102
50245
  this.stop(args.sessionId);
50103
50246
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
50104
50247
  let size = 0;
50105
50248
  try {
50106
- size = import_node_fs27.default.statSync(filePath).size;
50249
+ size = import_node_fs28.default.statSync(filePath).size;
50107
50250
  } catch {
50108
50251
  }
50109
50252
  const w2 = {
@@ -50116,16 +50259,16 @@ var SessionObserver = class {
50116
50259
  adapter: args.adapter,
50117
50260
  prevIsRejectSentinel: false,
50118
50261
  toolSessionId: args.toolSessionId,
50119
- sawFile: import_node_fs27.default.existsSync(filePath),
50262
+ sawFile: import_node_fs28.default.existsSync(filePath),
50120
50263
  lastRelocateScanMs: 0,
50121
50264
  pendingCwdDerive: false,
50122
50265
  lastDeriveMs: 0
50123
50266
  };
50124
50267
  try {
50125
- import_node_fs27.default.mkdirSync(import_node_path26.default.dirname(filePath), { recursive: true });
50268
+ import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(filePath), { recursive: true });
50126
50269
  } catch {
50127
50270
  }
50128
- w2.watcher = import_node_fs27.default.watch(import_node_path26.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
50271
+ w2.watcher = import_node_fs28.default.watch(import_node_path29.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
50129
50272
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
50130
50273
  this.poll(w2);
50131
50274
  });
@@ -50148,7 +50291,7 @@ var SessionObserver = class {
50148
50291
  // 异常静默吞,不阻塞 watcher 启动
50149
50292
  hydrateMetaTail(w2, maxLines = 200) {
50150
50293
  try {
50151
- const raw = import_node_fs27.default.readFileSync(w2.filePath, "utf8");
50294
+ const raw = import_node_fs28.default.readFileSync(w2.filePath, "utf8");
50152
50295
  if (!raw) return;
50153
50296
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
50154
50297
  if (allLines.length === 0) return;
@@ -50172,7 +50315,7 @@ var SessionObserver = class {
50172
50315
  poll(w2) {
50173
50316
  let size = 0;
50174
50317
  try {
50175
- size = import_node_fs27.default.statSync(w2.filePath).size;
50318
+ size = import_node_fs28.default.statSync(w2.filePath).size;
50176
50319
  } catch {
50177
50320
  if (w2.sawFile) this.maybeRelocate(w2);
50178
50321
  return;
@@ -50183,11 +50326,11 @@ var SessionObserver = class {
50183
50326
  w2.buf = "";
50184
50327
  }
50185
50328
  if (size === w2.lastSize) return;
50186
- const fd = import_node_fs27.default.openSync(w2.filePath, "r");
50329
+ const fd = import_node_fs28.default.openSync(w2.filePath, "r");
50187
50330
  try {
50188
50331
  const len = size - w2.lastSize;
50189
50332
  const buf = Buffer.alloc(len);
50190
- import_node_fs27.default.readSync(fd, buf, 0, len, w2.lastSize);
50333
+ import_node_fs28.default.readSync(fd, buf, 0, len, w2.lastSize);
50191
50334
  w2.lastSize = size;
50192
50335
  w2.buf += buf.toString("utf8");
50193
50336
  let newlineIndex;
@@ -50210,7 +50353,7 @@ var SessionObserver = class {
50210
50353
  }
50211
50354
  }
50212
50355
  } finally {
50213
- import_node_fs27.default.closeSync(fd);
50356
+ import_node_fs28.default.closeSync(fd);
50214
50357
  }
50215
50358
  if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
50216
50359
  }
@@ -50222,7 +50365,7 @@ var SessionObserver = class {
50222
50365
  const now = Date.now();
50223
50366
  if (now - w2.lastRelocateScanMs < 1e3) return;
50224
50367
  w2.lastRelocateScanMs = now;
50225
- const projectsRoot = import_node_path26.default.join(this.home, ".claude", "projects");
50368
+ const projectsRoot = import_node_path29.default.join(this.home, ".claude", "projects");
50226
50369
  const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
50227
50370
  if (!found || found === w2.filePath) return;
50228
50371
  try {
@@ -50231,7 +50374,7 @@ var SessionObserver = class {
50231
50374
  }
50232
50375
  w2.filePath = found;
50233
50376
  try {
50234
- w2.watcher = import_node_fs27.default.watch(import_node_path26.default.dirname(found), { persistent: false }, (_event, changedName) => {
50377
+ w2.watcher = import_node_fs28.default.watch(import_node_path29.default.dirname(found), { persistent: false }, (_event, changedName) => {
50235
50378
  if (!changedName || !w2.filePath.endsWith(changedName)) return;
50236
50379
  this.poll(w2);
50237
50380
  });
@@ -51089,14 +51232,14 @@ async function authenticate(token, deps) {
51089
51232
  }
51090
51233
 
51091
51234
  // src/permission/capability-store.ts
51092
- var fs32 = __toESM(require("fs"), 1);
51093
- var path31 = __toESM(require("path"), 1);
51235
+ var fs33 = __toESM(require("fs"), 1);
51236
+ var path34 = __toESM(require("path"), 1);
51094
51237
  var CAPABILITIES_FILE_NAME = "capabilities.json";
51095
51238
  var FILE_VERSION = 1;
51096
51239
  var CapabilityStore = class {
51097
51240
  constructor(dataDir) {
51098
51241
  this.dataDir = dataDir;
51099
- fs32.mkdirSync(dataDir, { recursive: true });
51242
+ fs33.mkdirSync(dataDir, { recursive: true });
51100
51243
  this.cache = this.readFromDisk();
51101
51244
  }
51102
51245
  dataDir;
@@ -51120,13 +51263,13 @@ var CapabilityStore = class {
51120
51263
  this.flush();
51121
51264
  }
51122
51265
  filePath() {
51123
- return path31.join(this.dataDir, CAPABILITIES_FILE_NAME);
51266
+ return path34.join(this.dataDir, CAPABILITIES_FILE_NAME);
51124
51267
  }
51125
51268
  readFromDisk() {
51126
51269
  const file = this.filePath();
51127
51270
  let raw;
51128
51271
  try {
51129
- raw = fs32.readFileSync(file, "utf8");
51272
+ raw = fs33.readFileSync(file, "utf8");
51130
51273
  } catch (err) {
51131
51274
  if (err?.code === "ENOENT") return [];
51132
51275
  return [];
@@ -51154,10 +51297,10 @@ var CapabilityStore = class {
51154
51297
  }
51155
51298
  atomicWrite(file, content) {
51156
51299
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
51157
- fs32.writeFileSync(tmp, content, { mode: 384 });
51158
- fs32.renameSync(tmp, file);
51300
+ fs33.writeFileSync(tmp, content, { mode: 384 });
51301
+ fs33.renameSync(tmp, file);
51159
51302
  try {
51160
- fs32.chmodSync(file, 384);
51303
+ fs33.chmodSync(file, 384);
51161
51304
  } catch {
51162
51305
  }
51163
51306
  }
@@ -51250,14 +51393,14 @@ var CapabilityManager = class {
51250
51393
  };
51251
51394
 
51252
51395
  // src/permission/cleanup.ts
51253
- var fs33 = __toESM(require("fs"), 1);
51396
+ var fs34 = __toESM(require("fs"), 1);
51254
51397
  function cleanupGuestSessionsForCapability(cap, factory) {
51255
51398
  const removed = [];
51256
51399
  for (const g2 of cap.grants) {
51257
51400
  if (g2.resource.type !== "persona") continue;
51258
51401
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
51259
51402
  try {
51260
- fs33.rmSync(dir, { recursive: true, force: true });
51403
+ fs34.rmSync(dir, { recursive: true, force: true });
51261
51404
  removed.push(dir);
51262
51405
  } catch {
51263
51406
  }
@@ -51266,13 +51409,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
51266
51409
  }
51267
51410
 
51268
51411
  // src/inbox/inbox-store.ts
51269
- var fs34 = __toESM(require("fs"), 1);
51270
- var path32 = __toESM(require("path"), 1);
51412
+ var fs35 = __toESM(require("fs"), 1);
51413
+ var path35 = __toESM(require("path"), 1);
51271
51414
  var INBOX_SUBDIR = "inbox";
51272
51415
  var InboxStore = class {
51273
51416
  constructor(dataDir) {
51274
51417
  this.dataDir = dataDir;
51275
- fs34.mkdirSync(this.dirPath(), { recursive: true });
51418
+ fs35.mkdirSync(this.dirPath(), { recursive: true });
51276
51419
  }
51277
51420
  dataDir;
51278
51421
  /**
@@ -51284,7 +51427,7 @@ var InboxStore = class {
51284
51427
  const file = this.filePath(peerDeviceId);
51285
51428
  let raw;
51286
51429
  try {
51287
- raw = fs34.readFileSync(file, "utf8");
51430
+ raw = fs35.readFileSync(file, "utf8");
51288
51431
  } catch (err) {
51289
51432
  if (err?.code === "ENOENT") return [];
51290
51433
  return [];
@@ -51300,7 +51443,7 @@ var InboxStore = class {
51300
51443
  const dir = this.dirPath();
51301
51444
  let entries;
51302
51445
  try {
51303
- entries = fs34.readdirSync(dir);
51446
+ entries = fs35.readdirSync(dir);
51304
51447
  } catch (err) {
51305
51448
  if (err?.code === "ENOENT") return [];
51306
51449
  return [];
@@ -51316,9 +51459,9 @@ var InboxStore = class {
51316
51459
  if (existing.some((m2) => m2.id === message.id)) return;
51317
51460
  const file = this.filePath(message.peerDeviceId);
51318
51461
  const line = JSON.stringify(message) + "\n";
51319
- fs34.appendFileSync(file, line, { mode: 384 });
51462
+ fs35.appendFileSync(file, line, { mode: 384 });
51320
51463
  try {
51321
- fs34.chmodSync(file, 384);
51464
+ fs35.chmodSync(file, 384);
51322
51465
  } catch {
51323
51466
  }
51324
51467
  }
@@ -51348,7 +51491,7 @@ var InboxStore = class {
51348
51491
  removeByPeerDeviceId(peerDeviceId) {
51349
51492
  const file = this.filePath(peerDeviceId);
51350
51493
  try {
51351
- fs34.unlinkSync(file);
51494
+ fs35.unlinkSync(file);
51352
51495
  } catch (err) {
51353
51496
  if (err?.code === "ENOENT") return;
51354
51497
  }
@@ -51357,18 +51500,18 @@ var InboxStore = class {
51357
51500
  const file = this.filePath(peerDeviceId);
51358
51501
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
51359
51502
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
51360
- fs34.writeFileSync(tmp, content, { mode: 384 });
51361
- fs34.renameSync(tmp, file);
51503
+ fs35.writeFileSync(tmp, content, { mode: 384 });
51504
+ fs35.renameSync(tmp, file);
51362
51505
  try {
51363
- fs34.chmodSync(file, 384);
51506
+ fs35.chmodSync(file, 384);
51364
51507
  } catch {
51365
51508
  }
51366
51509
  }
51367
51510
  dirPath() {
51368
- return path32.join(this.dataDir, INBOX_SUBDIR);
51511
+ return path35.join(this.dataDir, INBOX_SUBDIR);
51369
51512
  }
51370
51513
  filePath(peerDeviceId) {
51371
- return path32.join(this.dirPath(), `${peerDeviceId}.jsonl`);
51514
+ return path35.join(this.dirPath(), `${peerDeviceId}.jsonl`);
51372
51515
  }
51373
51516
  };
51374
51517
  function parseAllLines(raw) {
@@ -51456,8 +51599,8 @@ var InboxManager = class {
51456
51599
  };
51457
51600
 
51458
51601
  // src/state/contact-store.ts
51459
- var fs35 = __toESM(require("fs"), 1);
51460
- var path33 = __toESM(require("path"), 1);
51602
+ var fs36 = __toESM(require("fs"), 1);
51603
+ var path36 = __toESM(require("path"), 1);
51461
51604
  var FILE_NAME = "contacts.json";
51462
51605
  var ContactStore = class {
51463
51606
  constructor(dataDir) {
@@ -51467,10 +51610,10 @@ var ContactStore = class {
51467
51610
  contacts = /* @__PURE__ */ new Map();
51468
51611
  load() {
51469
51612
  this.contacts.clear();
51470
- const file = path33.join(this.dataDir, FILE_NAME);
51613
+ const file = path36.join(this.dataDir, FILE_NAME);
51471
51614
  let raw;
51472
51615
  try {
51473
- raw = fs35.readFileSync(file, "utf8");
51616
+ raw = fs36.readFileSync(file, "utf8");
51474
51617
  } catch (err) {
51475
51618
  if (err?.code !== "ENOENT") this.renameBak(file);
51476
51619
  return;
@@ -51539,20 +51682,20 @@ var ContactStore = class {
51539
51682
  return true;
51540
51683
  }
51541
51684
  flush() {
51542
- const file = path33.join(this.dataDir, FILE_NAME);
51685
+ const file = path36.join(this.dataDir, FILE_NAME);
51543
51686
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
51544
51687
  const content = JSON.stringify(
51545
51688
  { contacts: Array.from(this.contacts.values()) },
51546
51689
  null,
51547
51690
  2
51548
51691
  );
51549
- fs35.mkdirSync(this.dataDir, { recursive: true });
51550
- fs35.writeFileSync(tmp, content, { mode: 384 });
51551
- fs35.renameSync(tmp, file);
51692
+ fs36.mkdirSync(this.dataDir, { recursive: true });
51693
+ fs36.writeFileSync(tmp, content, { mode: 384 });
51694
+ fs36.renameSync(tmp, file);
51552
51695
  }
51553
51696
  renameBak(file) {
51554
51697
  try {
51555
- fs35.renameSync(file, `${file}.bak`);
51698
+ fs36.renameSync(file, `${file}.bak`);
51556
51699
  } catch {
51557
51700
  }
51558
51701
  }
@@ -51705,61 +51848,61 @@ async function autoReverseContact(args) {
51705
51848
  }
51706
51849
 
51707
51850
  // src/migrations/2026-05-20-flatten-sessions.ts
51708
- var fs36 = __toESM(require("fs"), 1);
51709
- var path34 = __toESM(require("path"), 1);
51851
+ var fs37 = __toESM(require("fs"), 1);
51852
+ var path37 = __toESM(require("path"), 1);
51710
51853
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
51711
51854
  function migrateFlattenSessions(opts) {
51712
51855
  const dataDir = opts.dataDir;
51713
51856
  const now = opts.now ?? Date.now;
51714
- const sessionsDir = path34.join(dataDir, "sessions");
51715
- const flagPath = path34.join(sessionsDir, MIGRATION_FLAG_NAME);
51857
+ const sessionsDir = path37.join(dataDir, "sessions");
51858
+ const flagPath = path37.join(sessionsDir, MIGRATION_FLAG_NAME);
51716
51859
  if (existsSync3(flagPath)) {
51717
51860
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
51718
51861
  }
51719
51862
  let movedBare = 0;
51720
51863
  let movedVmOwner = 0;
51721
51864
  let archivedListener = 0;
51722
- const defaultDir = path34.join(sessionsDir, "default");
51865
+ const defaultDir = path37.join(sessionsDir, "default");
51723
51866
  if (existsSync3(defaultDir)) {
51724
51867
  for (const entry of readdirSafe(defaultDir)) {
51725
51868
  if (!entry.endsWith(".json")) continue;
51726
- const src = path34.join(defaultDir, entry);
51727
- const dst = path34.join(sessionsDir, entry);
51728
- fs36.renameSync(src, dst);
51869
+ const src = path37.join(defaultDir, entry);
51870
+ const dst = path37.join(sessionsDir, entry);
51871
+ fs37.renameSync(src, dst);
51729
51872
  movedBare += 1;
51730
51873
  }
51731
51874
  rmdirIfEmpty(defaultDir);
51732
51875
  }
51733
51876
  for (const pid of readdirSafe(sessionsDir)) {
51734
- const personaDir = path34.join(sessionsDir, pid);
51877
+ const personaDir = path37.join(sessionsDir, pid);
51735
51878
  if (!isDir(personaDir)) continue;
51736
51879
  if (pid === "default") continue;
51737
- const ownerSrc = path34.join(personaDir, "owner");
51880
+ const ownerSrc = path37.join(personaDir, "owner");
51738
51881
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
51739
- const ownerDst = path34.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51740
- fs36.mkdirSync(ownerDst, { recursive: true });
51882
+ const ownerDst = path37.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51883
+ fs37.mkdirSync(ownerDst, { recursive: true });
51741
51884
  for (const file of readdirSafe(ownerSrc)) {
51742
51885
  if (!file.endsWith(".json")) continue;
51743
- fs36.renameSync(path34.join(ownerSrc, file), path34.join(ownerDst, file));
51886
+ fs37.renameSync(path37.join(ownerSrc, file), path37.join(ownerDst, file));
51744
51887
  movedVmOwner += 1;
51745
51888
  }
51746
51889
  rmdirIfEmpty(ownerSrc);
51747
51890
  }
51748
- const listenerSrc = path34.join(personaDir, "listener");
51891
+ const listenerSrc = path37.join(personaDir, "listener");
51749
51892
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
51750
- const archiveDst = path34.join(dataDir, ".legacy", `listener-${pid}`);
51751
- fs36.mkdirSync(archiveDst, { recursive: true });
51893
+ const archiveDst = path37.join(dataDir, ".legacy", `listener-${pid}`);
51894
+ fs37.mkdirSync(archiveDst, { recursive: true });
51752
51895
  for (const file of readdirSafe(listenerSrc)) {
51753
51896
  if (!file.endsWith(".json")) continue;
51754
- fs36.renameSync(path34.join(listenerSrc, file), path34.join(archiveDst, file));
51897
+ fs37.renameSync(path37.join(listenerSrc, file), path37.join(archiveDst, file));
51755
51898
  archivedListener += 1;
51756
51899
  }
51757
51900
  rmdirIfEmpty(listenerSrc);
51758
51901
  }
51759
51902
  rmdirIfEmpty(personaDir);
51760
51903
  }
51761
- fs36.mkdirSync(sessionsDir, { recursive: true });
51762
- fs36.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51904
+ fs37.mkdirSync(sessionsDir, { recursive: true });
51905
+ fs37.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51763
51906
  return {
51764
51907
  skipped: false,
51765
51908
  flagWritten: true,
@@ -51770,7 +51913,7 @@ function migrateFlattenSessions(opts) {
51770
51913
  }
51771
51914
  function existsSync3(p2) {
51772
51915
  try {
51773
- fs36.statSync(p2);
51916
+ fs37.statSync(p2);
51774
51917
  return true;
51775
51918
  } catch {
51776
51919
  return false;
@@ -51778,31 +51921,31 @@ function existsSync3(p2) {
51778
51921
  }
51779
51922
  function isDir(p2) {
51780
51923
  try {
51781
- return fs36.statSync(p2).isDirectory();
51924
+ return fs37.statSync(p2).isDirectory();
51782
51925
  } catch {
51783
51926
  return false;
51784
51927
  }
51785
51928
  }
51786
51929
  function readdirSafe(p2) {
51787
51930
  try {
51788
- return fs36.readdirSync(p2);
51931
+ return fs37.readdirSync(p2);
51789
51932
  } catch {
51790
51933
  return [];
51791
51934
  }
51792
51935
  }
51793
51936
  function rmdirIfEmpty(p2) {
51794
51937
  try {
51795
- fs36.rmdirSync(p2);
51938
+ fs37.rmdirSync(p2);
51796
51939
  } catch {
51797
51940
  }
51798
51941
  }
51799
51942
 
51800
51943
  // src/transport/http-router.ts
51801
- var import_node_fs29 = __toESM(require("fs"), 1);
51802
- var import_node_path30 = __toESM(require("path"), 1);
51944
+ var import_node_fs30 = __toESM(require("fs"), 1);
51945
+ var import_node_path33 = __toESM(require("path"), 1);
51803
51946
 
51804
51947
  // src/attachment/mime.ts
51805
- var import_node_path27 = __toESM(require("path"), 1);
51948
+ var import_node_path30 = __toESM(require("path"), 1);
51806
51949
  var TEXT_PLAIN = "text/plain; charset=utf-8";
51807
51950
  var EXT_TO_NATIVE_MIME = {
51808
51951
  // 图片
@@ -51909,7 +52052,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
51909
52052
  ".mk"
51910
52053
  ]);
51911
52054
  function lookupMime(filePathOrName) {
51912
- const ext = import_node_path27.default.extname(filePathOrName).toLowerCase();
52055
+ const ext = import_node_path30.default.extname(filePathOrName).toLowerCase();
51913
52056
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
51914
52057
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
51915
52058
  return "application/octet-stream";
@@ -51978,8 +52121,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
51978
52121
  }
51979
52122
 
51980
52123
  // src/attachment/upload.ts
51981
- var import_node_fs28 = __toESM(require("fs"), 1);
51982
- var import_node_path28 = __toESM(require("path"), 1);
52124
+ var import_node_fs29 = __toESM(require("fs"), 1);
52125
+ var import_node_path31 = __toESM(require("path"), 1);
51983
52126
  var import_node_crypto8 = __toESM(require("crypto"), 1);
51984
52127
  var import_promises3 = require("stream/promises");
51985
52128
  var UploadError = class extends Error {
@@ -51991,22 +52134,22 @@ var UploadError = class extends Error {
51991
52134
  code;
51992
52135
  };
51993
52136
  function assertValidFileName(fileName) {
51994
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path28.default.basename(fileName)) {
52137
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path31.default.basename(fileName)) {
51995
52138
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
51996
52139
  }
51997
52140
  }
51998
52141
  var HASH_PREFIX_LEN = 16;
51999
52142
  async function writeUploadedAttachment(args) {
52000
52143
  assertValidFileName(args.fileName);
52001
- const attachmentsRoot = import_node_path28.default.join(args.sessionDir, ".attachments");
52144
+ const attachmentsRoot = import_node_path31.default.join(args.sessionDir, ".attachments");
52002
52145
  try {
52003
- import_node_fs28.default.mkdirSync(attachmentsRoot, { recursive: true });
52146
+ import_node_fs29.default.mkdirSync(attachmentsRoot, { recursive: true });
52004
52147
  } catch (err) {
52005
52148
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
52006
52149
  }
52007
52150
  const hasher = import_node_crypto8.default.createHash("sha256");
52008
52151
  let actualSize = 0;
52009
- const tmpPath = import_node_path28.default.join(
52152
+ const tmpPath = import_node_path31.default.join(
52010
52153
  attachmentsRoot,
52011
52154
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
52012
52155
  );
@@ -52021,18 +52164,18 @@ async function writeUploadedAttachment(args) {
52021
52164
  yield buf;
52022
52165
  }
52023
52166
  },
52024
- import_node_fs28.default.createWriteStream(tmpPath, { mode: 384 })
52167
+ import_node_fs29.default.createWriteStream(tmpPath, { mode: 384 })
52025
52168
  );
52026
52169
  } catch (err) {
52027
52170
  try {
52028
- import_node_fs28.default.unlinkSync(tmpPath);
52171
+ import_node_fs29.default.unlinkSync(tmpPath);
52029
52172
  } catch {
52030
52173
  }
52031
52174
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
52032
52175
  }
52033
52176
  if (actualSize !== args.contentLength) {
52034
52177
  try {
52035
- import_node_fs28.default.unlinkSync(tmpPath);
52178
+ import_node_fs29.default.unlinkSync(tmpPath);
52036
52179
  } catch {
52037
52180
  }
52038
52181
  throw new UploadError(
@@ -52041,35 +52184,35 @@ async function writeUploadedAttachment(args) {
52041
52184
  );
52042
52185
  }
52043
52186
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
52044
- const hashDir = import_node_path28.default.join(attachmentsRoot, attachmentId);
52187
+ const hashDir = import_node_path31.default.join(attachmentsRoot, attachmentId);
52045
52188
  let finalFileName;
52046
52189
  let hashDirExists = false;
52047
52190
  try {
52048
- hashDirExists = import_node_fs28.default.statSync(hashDir).isDirectory();
52191
+ hashDirExists = import_node_fs29.default.statSync(hashDir).isDirectory();
52049
52192
  } catch {
52050
52193
  }
52051
52194
  if (hashDirExists) {
52052
- const existing = import_node_fs28.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
52195
+ const existing = import_node_fs29.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
52053
52196
  finalFileName = existing[0] ?? args.fileName;
52054
52197
  try {
52055
- import_node_fs28.default.unlinkSync(tmpPath);
52198
+ import_node_fs29.default.unlinkSync(tmpPath);
52056
52199
  } catch {
52057
52200
  }
52058
52201
  } else {
52059
52202
  try {
52060
- import_node_fs28.default.mkdirSync(hashDir, { recursive: true });
52203
+ import_node_fs29.default.mkdirSync(hashDir, { recursive: true });
52061
52204
  finalFileName = args.fileName;
52062
- import_node_fs28.default.renameSync(tmpPath, import_node_path28.default.join(hashDir, finalFileName));
52205
+ import_node_fs29.default.renameSync(tmpPath, import_node_path31.default.join(hashDir, finalFileName));
52063
52206
  } catch (err) {
52064
52207
  try {
52065
- import_node_fs28.default.unlinkSync(tmpPath);
52208
+ import_node_fs29.default.unlinkSync(tmpPath);
52066
52209
  } catch {
52067
52210
  }
52068
52211
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
52069
52212
  }
52070
52213
  }
52071
- const absPath = import_node_path28.default.join(hashDir, finalFileName);
52072
- const relPath = import_node_path28.default.relative(args.sessionDir, absPath);
52214
+ const absPath = import_node_path31.default.join(hashDir, finalFileName);
52215
+ const relPath = import_node_path31.default.relative(args.sessionDir, absPath);
52073
52216
  args.groupFileStore.upsert(args.scope, args.sessionId, {
52074
52217
  relPath: absPath,
52075
52218
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -52083,7 +52226,7 @@ async function writeUploadedAttachment(args) {
52083
52226
 
52084
52227
  // src/extension/import.ts
52085
52228
  var import_promises4 = __toESM(require("fs/promises"), 1);
52086
- var import_node_path29 = __toESM(require("path"), 1);
52229
+ var import_node_path32 = __toESM(require("path"), 1);
52087
52230
  var import_node_os12 = __toESM(require("os"), 1);
52088
52231
  var import_jszip = __toESM(require_lib3(), 1);
52089
52232
  var ImportError = class extends Error {
@@ -52101,7 +52244,7 @@ async function importZip(buf, root) {
52101
52244
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
52102
52245
  }
52103
52246
  for (const name of Object.keys(zip.files)) {
52104
- if (name.includes("..") || name.startsWith("/") || import_node_path29.default.isAbsolute(name)) {
52247
+ if (name.includes("..") || name.startsWith("/") || import_node_path32.default.isAbsolute(name)) {
52105
52248
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
52106
52249
  }
52107
52250
  }
@@ -52134,7 +52277,7 @@ async function importZip(buf, root) {
52134
52277
  );
52135
52278
  }
52136
52279
  }
52137
- const destDir = import_node_path29.default.join(root, manifest.id);
52280
+ const destDir = import_node_path32.default.join(root, manifest.id);
52138
52281
  let destExists = false;
52139
52282
  try {
52140
52283
  await import_promises4.default.access(destDir);
@@ -52144,15 +52287,15 @@ async function importZip(buf, root) {
52144
52287
  if (destExists) {
52145
52288
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
52146
52289
  }
52147
- const stage = await import_promises4.default.mkdtemp(import_node_path29.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
52290
+ const stage = await import_promises4.default.mkdtemp(import_node_path32.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
52148
52291
  try {
52149
52292
  for (const [name, entry] of Object.entries(zip.files)) {
52150
- const dest = import_node_path29.default.join(stage, name);
52293
+ const dest = import_node_path32.default.join(stage, name);
52151
52294
  if (entry.dir) {
52152
52295
  await import_promises4.default.mkdir(dest, { recursive: true });
52153
52296
  continue;
52154
52297
  }
52155
- await import_promises4.default.mkdir(import_node_path29.default.dirname(dest), { recursive: true });
52298
+ await import_promises4.default.mkdir(import_node_path32.default.dirname(dest), { recursive: true });
52156
52299
  const content = await entry.async("nodebuffer");
52157
52300
  await import_promises4.default.writeFile(dest, content);
52158
52301
  }
@@ -52183,7 +52326,7 @@ var SHARE_UI_ASSET_MIME = {
52183
52326
  ".wasm": "application/wasm"
52184
52327
  };
52185
52328
  function shareUiAssetMime(filePath) {
52186
- const ext = import_node_path30.default.extname(filePath).toLowerCase();
52329
+ const ext = import_node_path33.default.extname(filePath).toLowerCase();
52187
52330
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
52188
52331
  }
52189
52332
  var DISPATCH_HEARTBEAT_MS = 25e3;
@@ -52270,7 +52413,7 @@ function isValidUploadFileName(fileName) {
52270
52413
  if (fileName === "." || fileName === "..") return false;
52271
52414
  if (fileName.startsWith(".")) return false;
52272
52415
  if (fileName.includes("/") || fileName.includes("\\")) return false;
52273
- return fileName === import_node_path30.default.basename(fileName);
52416
+ return fileName === import_node_path33.default.basename(fileName);
52274
52417
  }
52275
52418
  function createHttpRouter(deps) {
52276
52419
  return async (req, res) => {
@@ -52342,7 +52485,7 @@ function createHttpRouter(deps) {
52342
52485
  }
52343
52486
  let buf;
52344
52487
  try {
52345
- buf = await import_node_fs29.default.promises.readFile(abs);
52488
+ buf = await import_node_fs30.default.promises.readFile(abs);
52346
52489
  } catch {
52347
52490
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
52348
52491
  return true;
@@ -52566,7 +52709,7 @@ function createHttpRouter(deps) {
52566
52709
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
52567
52710
  return true;
52568
52711
  }
52569
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path30.default.basename(r.absPath)));
52712
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path33.default.basename(r.absPath)));
52570
52713
  return true;
52571
52714
  }
52572
52715
  const ctx = deps.authResolver.resolveFromHeader(
@@ -52687,7 +52830,7 @@ function createHttpRouter(deps) {
52687
52830
  return true;
52688
52831
  }
52689
52832
  let absPath;
52690
- if (import_node_path30.default.isAbsolute(pathParam)) {
52833
+ if (import_node_path33.default.isAbsolute(pathParam)) {
52691
52834
  absPath = pathParam;
52692
52835
  } else if (deps.sessionStore) {
52693
52836
  const file = deps.sessionStore.read(sid);
@@ -52695,7 +52838,7 @@ function createHttpRouter(deps) {
52695
52838
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
52696
52839
  return true;
52697
52840
  }
52698
- absPath = import_node_path30.default.join(file.cwd, pathParam);
52841
+ absPath = import_node_path33.default.join(file.cwd, pathParam);
52699
52842
  } else {
52700
52843
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
52701
52844
  return true;
@@ -52782,7 +52925,7 @@ function withCtx(ctx, body) {
52782
52925
  function streamFile(res, absPath, logger) {
52783
52926
  let stat;
52784
52927
  try {
52785
- stat = import_node_fs29.default.statSync(absPath);
52928
+ stat = import_node_fs30.default.statSync(absPath);
52786
52929
  } catch (err) {
52787
52930
  const code = err?.code;
52788
52931
  if (code === "ENOENT") {
@@ -52797,7 +52940,7 @@ function streamFile(res, absPath, logger) {
52797
52940
  return;
52798
52941
  }
52799
52942
  const mime = lookupMime(absPath);
52800
- const basename = import_node_path30.default.basename(absPath);
52943
+ const basename = import_node_path33.default.basename(absPath);
52801
52944
  res.writeHead(200, {
52802
52945
  "Content-Type": mime,
52803
52946
  "Content-Length": String(stat.size),
@@ -52805,7 +52948,7 @@ function streamFile(res, absPath, logger) {
52805
52948
  // 防止浏览器把任意 mime 当 html 渲染
52806
52949
  "X-Content-Type-Options": "nosniff"
52807
52950
  });
52808
- const stream = import_node_fs29.default.createReadStream(absPath);
52951
+ const stream = import_node_fs30.default.createReadStream(absPath);
52809
52952
  stream.on("error", (err) => {
52810
52953
  logger?.warn("streamFile read error", { absPath, err: err.message });
52811
52954
  res.destroy();
@@ -52814,8 +52957,8 @@ function streamFile(res, absPath, logger) {
52814
52957
  }
52815
52958
 
52816
52959
  // src/attachment/gc.ts
52817
- var import_node_fs30 = __toESM(require("fs"), 1);
52818
- var import_node_path31 = __toESM(require("path"), 1);
52960
+ var import_node_fs31 = __toESM(require("fs"), 1);
52961
+ var import_node_path34 = __toESM(require("path"), 1);
52819
52962
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
52820
52963
  function runAttachmentGc(args) {
52821
52964
  const now = (args.now ?? Date.now)();
@@ -52824,38 +52967,38 @@ function runAttachmentGc(args) {
52824
52967
  for (const { scope, sessionId } of args.sessionScopes) {
52825
52968
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
52826
52969
  if (entry.stale) continue;
52827
- if (import_node_path31.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52970
+ if (import_node_path34.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52828
52971
  }
52829
52972
  }
52830
52973
  for (const { scope, sessionId } of args.sessionScopes) {
52831
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path31.default.join(
52974
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path34.default.join(
52832
52975
  args.dataDir,
52833
52976
  "sessions",
52834
52977
  ...scopeSubPath(scope).map(safeFileName),
52835
52978
  safeFileName(sessionId)
52836
52979
  );
52837
- const attRoot = import_node_path31.default.join(sessionDir, ".attachments");
52980
+ const attRoot = import_node_path34.default.join(sessionDir, ".attachments");
52838
52981
  let hashDirs;
52839
52982
  try {
52840
- hashDirs = import_node_fs30.default.readdirSync(attRoot);
52983
+ hashDirs = import_node_fs31.default.readdirSync(attRoot);
52841
52984
  } catch (err) {
52842
52985
  if (err.code === "ENOENT") continue;
52843
52986
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
52844
52987
  continue;
52845
52988
  }
52846
52989
  for (const hashDir of hashDirs) {
52847
- const hashDirAbs = import_node_path31.default.join(attRoot, hashDir);
52990
+ const hashDirAbs = import_node_path34.default.join(attRoot, hashDir);
52848
52991
  let files;
52849
52992
  try {
52850
- files = import_node_fs30.default.readdirSync(hashDirAbs);
52993
+ files = import_node_fs31.default.readdirSync(hashDirAbs);
52851
52994
  } catch {
52852
52995
  continue;
52853
52996
  }
52854
52997
  for (const name of files) {
52855
- const file = import_node_path31.default.join(hashDirAbs, name);
52998
+ const file = import_node_path34.default.join(hashDirAbs, name);
52856
52999
  let stat;
52857
53000
  try {
52858
- stat = import_node_fs30.default.statSync(file);
53001
+ stat = import_node_fs31.default.statSync(file);
52859
53002
  } catch {
52860
53003
  continue;
52861
53004
  }
@@ -52864,26 +53007,26 @@ function runAttachmentGc(args) {
52864
53007
  if (age < ttlMs) continue;
52865
53008
  if (liveAbs.has(file)) continue;
52866
53009
  try {
52867
- import_node_fs30.default.unlinkSync(file);
53010
+ import_node_fs31.default.unlinkSync(file);
52868
53011
  } catch (err) {
52869
53012
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
52870
53013
  }
52871
53014
  }
52872
53015
  try {
52873
- if (import_node_fs30.default.readdirSync(hashDirAbs).length === 0) import_node_fs30.default.rmdirSync(hashDirAbs);
53016
+ if (import_node_fs31.default.readdirSync(hashDirAbs).length === 0) import_node_fs31.default.rmdirSync(hashDirAbs);
52874
53017
  } catch {
52875
53018
  }
52876
53019
  }
52877
53020
  try {
52878
- if (import_node_fs30.default.readdirSync(attRoot).length === 0) import_node_fs30.default.rmdirSync(attRoot);
53021
+ if (import_node_fs31.default.readdirSync(attRoot).length === 0) import_node_fs31.default.rmdirSync(attRoot);
52879
53022
  } catch {
52880
53023
  }
52881
53024
  }
52882
53025
  }
52883
53026
 
52884
53027
  // src/attachment/group.ts
52885
- var import_node_fs31 = __toESM(require("fs"), 1);
52886
- var import_node_path32 = __toESM(require("path"), 1);
53028
+ var import_node_fs32 = __toESM(require("fs"), 1);
53029
+ var import_node_path35 = __toESM(require("path"), 1);
52887
53030
  var import_node_crypto9 = __toESM(require("crypto"), 1);
52888
53031
  init_protocol();
52889
53032
  var GroupFileStore = class {
@@ -52895,11 +53038,11 @@ var GroupFileStore = class {
52895
53038
  this.logger = opts.logger;
52896
53039
  }
52897
53040
  rootForScope(scope) {
52898
- return import_node_path32.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
53041
+ return import_node_path35.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
52899
53042
  }
52900
53043
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
52901
53044
  filePath(scope, sessionId) {
52902
- return import_node_path32.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
53045
+ return import_node_path35.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
52903
53046
  }
52904
53047
  cacheKey(scope, sessionId) {
52905
53048
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -52908,7 +53051,7 @@ var GroupFileStore = class {
52908
53051
  readFile(scope, sessionId) {
52909
53052
  const file = this.filePath(scope, sessionId);
52910
53053
  try {
52911
- const raw = import_node_fs31.default.readFileSync(file, "utf8");
53054
+ const raw = import_node_fs32.default.readFileSync(file, "utf8");
52912
53055
  const parsed = JSON.parse(raw);
52913
53056
  if (!Array.isArray(parsed)) {
52914
53057
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -52934,10 +53077,10 @@ var GroupFileStore = class {
52934
53077
  }
52935
53078
  writeFile(scope, sessionId, entries) {
52936
53079
  const file = this.filePath(scope, sessionId);
52937
- import_node_fs31.default.mkdirSync(import_node_path32.default.dirname(file), { recursive: true });
53080
+ import_node_fs32.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
52938
53081
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
52939
- import_node_fs31.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52940
- import_node_fs31.default.renameSync(tmp, file);
53082
+ import_node_fs32.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
53083
+ import_node_fs32.default.renameSync(tmp, file);
52941
53084
  }
52942
53085
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
52943
53086
  list(scope, sessionId) {
@@ -53023,10 +53166,10 @@ var GroupFileStore = class {
53023
53166
  };
53024
53167
 
53025
53168
  // src/discovery/state-file.ts
53026
- var import_node_fs32 = __toESM(require("fs"), 1);
53027
- var import_node_path33 = __toESM(require("path"), 1);
53169
+ var import_node_fs33 = __toESM(require("fs"), 1);
53170
+ var import_node_path36 = __toESM(require("path"), 1);
53028
53171
  function defaultStateFilePath(dataDir) {
53029
- return import_node_path33.default.join(dataDir, "state.json");
53172
+ return import_node_path36.default.join(dataDir, "state.json");
53030
53173
  }
53031
53174
  function isPidAlive(pid) {
53032
53175
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -53048,7 +53191,7 @@ var StateFileManager = class {
53048
53191
  }
53049
53192
  read() {
53050
53193
  try {
53051
- const raw = import_node_fs32.default.readFileSync(this.file, "utf8");
53194
+ const raw = import_node_fs33.default.readFileSync(this.file, "utf8");
53052
53195
  const parsed = JSON.parse(raw);
53053
53196
  return parsed;
53054
53197
  } catch {
@@ -53062,20 +53205,20 @@ var StateFileManager = class {
53062
53205
  return { status: "stale", existing };
53063
53206
  }
53064
53207
  write(state) {
53065
- import_node_fs32.default.mkdirSync(import_node_path33.default.dirname(this.file), { recursive: true });
53208
+ import_node_fs33.default.mkdirSync(import_node_path36.default.dirname(this.file), { recursive: true });
53066
53209
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
53067
- import_node_fs32.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
53068
- import_node_fs32.default.renameSync(tmp, this.file);
53210
+ import_node_fs33.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
53211
+ import_node_fs33.default.renameSync(tmp, this.file);
53069
53212
  if (process.platform !== "win32") {
53070
53213
  try {
53071
- import_node_fs32.default.chmodSync(this.file, 384);
53214
+ import_node_fs33.default.chmodSync(this.file, 384);
53072
53215
  } catch {
53073
53216
  }
53074
53217
  }
53075
53218
  }
53076
53219
  delete() {
53077
53220
  try {
53078
- import_node_fs32.default.unlinkSync(this.file);
53221
+ import_node_fs33.default.unlinkSync(this.file);
53079
53222
  } catch {
53080
53223
  }
53081
53224
  }
@@ -53089,14 +53232,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
53089
53232
  }
53090
53233
 
53091
53234
  // src/tunnel/tunnel-manager.ts
53092
- var import_node_fs36 = __toESM(require("fs"), 1);
53093
- var import_node_path37 = __toESM(require("path"), 1);
53235
+ var import_node_fs37 = __toESM(require("fs"), 1);
53236
+ var import_node_path40 = __toESM(require("path"), 1);
53094
53237
  var import_node_crypto10 = __toESM(require("crypto"), 1);
53095
- var import_node_child_process9 = require("child_process");
53238
+ var import_node_child_process10 = require("child_process");
53096
53239
 
53097
53240
  // src/tunnel/tunnel-store.ts
53098
- var import_node_fs33 = __toESM(require("fs"), 1);
53099
- var import_node_path34 = __toESM(require("path"), 1);
53241
+ var import_node_fs34 = __toESM(require("fs"), 1);
53242
+ var import_node_path37 = __toESM(require("path"), 1);
53100
53243
  var TunnelStore = class {
53101
53244
  constructor(filePath) {
53102
53245
  this.filePath = filePath;
@@ -53104,7 +53247,7 @@ var TunnelStore = class {
53104
53247
  filePath;
53105
53248
  async get() {
53106
53249
  try {
53107
- const raw = await import_node_fs33.default.promises.readFile(this.filePath, "utf8");
53250
+ const raw = await import_node_fs34.default.promises.readFile(this.filePath, "utf8");
53108
53251
  const obj = JSON.parse(raw);
53109
53252
  if (!isPersistedTunnel(obj)) return null;
53110
53253
  return obj;
@@ -53115,22 +53258,22 @@ var TunnelStore = class {
53115
53258
  }
53116
53259
  }
53117
53260
  async set(v2) {
53118
- const dir = import_node_path34.default.dirname(this.filePath);
53119
- await import_node_fs33.default.promises.mkdir(dir, { recursive: true });
53261
+ const dir = import_node_path37.default.dirname(this.filePath);
53262
+ await import_node_fs34.default.promises.mkdir(dir, { recursive: true });
53120
53263
  const data = JSON.stringify(v2, null, 2);
53121
53264
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
53122
- await import_node_fs33.default.promises.writeFile(tmp, data, { mode: 384 });
53265
+ await import_node_fs34.default.promises.writeFile(tmp, data, { mode: 384 });
53123
53266
  if (process.platform !== "win32") {
53124
53267
  try {
53125
- await import_node_fs33.default.promises.chmod(tmp, 384);
53268
+ await import_node_fs34.default.promises.chmod(tmp, 384);
53126
53269
  } catch {
53127
53270
  }
53128
53271
  }
53129
- await import_node_fs33.default.promises.rename(tmp, this.filePath);
53272
+ await import_node_fs34.default.promises.rename(tmp, this.filePath);
53130
53273
  }
53131
53274
  async clear() {
53132
53275
  try {
53133
- await import_node_fs33.default.promises.unlink(this.filePath);
53276
+ await import_node_fs34.default.promises.unlink(this.filePath);
53134
53277
  } catch (err) {
53135
53278
  const code = err?.code;
53136
53279
  if (code !== "ENOENT") throw err;
@@ -53225,10 +53368,10 @@ function escape(v2) {
53225
53368
  }
53226
53369
 
53227
53370
  // src/tunnel/frpc-binary.ts
53228
- var import_node_fs34 = __toESM(require("fs"), 1);
53371
+ var import_node_fs35 = __toESM(require("fs"), 1);
53229
53372
  var import_node_os13 = __toESM(require("os"), 1);
53230
- var import_node_path35 = __toESM(require("path"), 1);
53231
- var import_node_child_process7 = require("child_process");
53373
+ var import_node_path38 = __toESM(require("path"), 1);
53374
+ var import_node_child_process8 = require("child_process");
53232
53375
  var import_node_stream3 = require("stream");
53233
53376
  var import_promises5 = require("stream/promises");
53234
53377
  var FRPC_VERSION = "0.68.0";
@@ -53259,20 +53402,20 @@ function frpcDownloadUrl(version2, p2) {
53259
53402
  }
53260
53403
  async function ensureFrpcBinary(opts) {
53261
53404
  if (opts.override) {
53262
- if (!import_node_fs34.default.existsSync(opts.override)) {
53405
+ if (!import_node_fs35.default.existsSync(opts.override)) {
53263
53406
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
53264
53407
  }
53265
53408
  return opts.override;
53266
53409
  }
53267
53410
  const version2 = opts.version ?? FRPC_VERSION;
53268
53411
  const platform = opts.platform ?? detectPlatform();
53269
- const binDir = import_node_path35.default.join(opts.dataDir, "bin");
53270
- import_node_fs34.default.mkdirSync(binDir, { recursive: true });
53412
+ const binDir = import_node_path38.default.join(opts.dataDir, "bin");
53413
+ import_node_fs35.default.mkdirSync(binDir, { recursive: true });
53271
53414
  cleanupStaleArtifacts(binDir);
53272
- const stableBin = import_node_path35.default.join(binDir, "frpc");
53273
- if (import_node_fs34.default.existsSync(stableBin)) return stableBin;
53415
+ const stableBin = import_node_path38.default.join(binDir, "frpc");
53416
+ if (import_node_fs35.default.existsSync(stableBin)) return stableBin;
53274
53417
  const partialBin = `${stableBin}.partial`;
53275
- const tarballPath = import_node_path35.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
53418
+ const tarballPath = import_node_path38.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
53276
53419
  try {
53277
53420
  const url = frpcDownloadUrl(version2, platform);
53278
53421
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -53281,8 +53424,8 @@ async function ensureFrpcBinary(opts) {
53281
53424
  } else {
53282
53425
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
53283
53426
  }
53284
- import_node_fs34.default.chmodSync(partialBin, 493);
53285
- import_node_fs34.default.renameSync(partialBin, stableBin);
53427
+ import_node_fs35.default.chmodSync(partialBin, 493);
53428
+ import_node_fs35.default.renameSync(partialBin, stableBin);
53286
53429
  } finally {
53287
53430
  safeUnlink(tarballPath);
53288
53431
  safeUnlink(partialBin);
@@ -53292,15 +53435,15 @@ async function ensureFrpcBinary(opts) {
53292
53435
  function cleanupStaleArtifacts(binDir) {
53293
53436
  let entries;
53294
53437
  try {
53295
- entries = import_node_fs34.default.readdirSync(binDir);
53438
+ entries = import_node_fs35.default.readdirSync(binDir);
53296
53439
  } catch {
53297
53440
  return;
53298
53441
  }
53299
53442
  for (const name of entries) {
53300
53443
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
53301
- const full = import_node_path35.default.join(binDir, name);
53444
+ const full = import_node_path38.default.join(binDir, name);
53302
53445
  try {
53303
- import_node_fs34.default.rmSync(full, { recursive: true, force: true });
53446
+ import_node_fs35.default.rmSync(full, { recursive: true, force: true });
53304
53447
  } catch {
53305
53448
  }
53306
53449
  }
@@ -53308,7 +53451,7 @@ function cleanupStaleArtifacts(binDir) {
53308
53451
  }
53309
53452
  function safeUnlink(p2) {
53310
53453
  try {
53311
- import_node_fs34.default.unlinkSync(p2);
53454
+ import_node_fs35.default.unlinkSync(p2);
53312
53455
  } catch {
53313
53456
  }
53314
53457
  }
@@ -53319,46 +53462,46 @@ async function downloadToFile(url, dest, fetchImpl) {
53319
53462
  if (!res.ok || !res.body) {
53320
53463
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
53321
53464
  }
53322
- const out = import_node_fs34.default.createWriteStream(dest);
53465
+ const out = import_node_fs35.default.createWriteStream(dest);
53323
53466
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
53324
53467
  await (0, import_promises5.pipeline)(nodeStream, out);
53325
53468
  }
53326
53469
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
53327
- const work = import_node_path35.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
53328
- import_node_fs34.default.mkdirSync(work, { recursive: true });
53470
+ const work = import_node_path38.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
53471
+ import_node_fs35.default.mkdirSync(work, { recursive: true });
53329
53472
  try {
53330
53473
  await new Promise((resolve6, reject) => {
53331
- const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
53474
+ const proc = (0, import_node_child_process8.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
53332
53475
  proc.on("error", reject);
53333
53476
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
53334
53477
  });
53335
53478
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
53336
- const src = import_node_path35.default.join(work, dirName, "frpc");
53337
- if (!import_node_fs34.default.existsSync(src)) {
53479
+ const src = import_node_path38.default.join(work, dirName, "frpc");
53480
+ if (!import_node_fs35.default.existsSync(src)) {
53338
53481
  throw new Error(`frpc not found inside tarball at ${src}`);
53339
53482
  }
53340
- import_node_fs34.default.copyFileSync(src, destBin);
53483
+ import_node_fs35.default.copyFileSync(src, destBin);
53341
53484
  } finally {
53342
- import_node_fs34.default.rmSync(work, { recursive: true, force: true });
53485
+ import_node_fs35.default.rmSync(work, { recursive: true, force: true });
53343
53486
  }
53344
53487
  }
53345
53488
 
53346
53489
  // src/tunnel/frpc-process.ts
53347
- var import_node_fs35 = __toESM(require("fs"), 1);
53348
- var import_node_path36 = __toESM(require("path"), 1);
53349
- var import_node_child_process8 = require("child_process");
53490
+ var import_node_fs36 = __toESM(require("fs"), 1);
53491
+ var import_node_path39 = __toESM(require("path"), 1);
53492
+ var import_node_child_process9 = require("child_process");
53350
53493
  function frpcPidFilePath(dataDir) {
53351
- return import_node_path36.default.join(dataDir, "frpc.pid");
53494
+ return import_node_path39.default.join(dataDir, "frpc.pid");
53352
53495
  }
53353
53496
  function writeFrpcPid(dataDir, pid) {
53354
53497
  try {
53355
- import_node_fs35.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
53498
+ import_node_fs36.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
53356
53499
  } catch {
53357
53500
  }
53358
53501
  }
53359
53502
  function clearFrpcPid(dataDir) {
53360
53503
  try {
53361
- import_node_fs35.default.unlinkSync(frpcPidFilePath(dataDir));
53504
+ import_node_fs36.default.unlinkSync(frpcPidFilePath(dataDir));
53362
53505
  } catch {
53363
53506
  }
53364
53507
  }
@@ -53374,7 +53517,7 @@ function defaultIsPidAlive(pid) {
53374
53517
  }
53375
53518
  function defaultReadPidFile(file) {
53376
53519
  try {
53377
- return import_node_fs35.default.readFileSync(file, "utf8");
53520
+ return import_node_fs36.default.readFileSync(file, "utf8");
53378
53521
  } catch {
53379
53522
  return null;
53380
53523
  }
@@ -53390,7 +53533,7 @@ function defaultSleep(ms) {
53390
53533
  }
53391
53534
  async function killStaleFrpc(deps) {
53392
53535
  const pidFile = frpcPidFilePath(deps.dataDir);
53393
- const tomlPath = import_node_path36.default.join(deps.dataDir, "frpc.toml");
53536
+ const tomlPath = import_node_path39.default.join(deps.dataDir, "frpc.toml");
53394
53537
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
53395
53538
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
53396
53539
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -53414,7 +53557,7 @@ async function killStaleFrpc(deps) {
53414
53557
  }
53415
53558
  if (victims.size === 0) {
53416
53559
  try {
53417
- import_node_fs35.default.unlinkSync(pidFile);
53560
+ import_node_fs36.default.unlinkSync(pidFile);
53418
53561
  } catch {
53419
53562
  }
53420
53563
  return;
@@ -53425,14 +53568,14 @@ async function killStaleFrpc(deps) {
53425
53568
  }
53426
53569
  await sleep2(deps.reapWaitMs ?? 300);
53427
53570
  try {
53428
- import_node_fs35.default.unlinkSync(pidFile);
53571
+ import_node_fs36.default.unlinkSync(pidFile);
53429
53572
  } catch {
53430
53573
  }
53431
53574
  }
53432
53575
  async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
53433
53576
  if (process.platform === "win32") return [];
53434
53577
  return new Promise((resolve6) => {
53435
- const ps = (0, import_node_child_process8.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
53578
+ const ps = (0, import_node_child_process9.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
53436
53579
  let buf = "";
53437
53580
  ps.stdout.on("data", (c) => {
53438
53581
  buf += c.toString();
@@ -53462,7 +53605,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
53462
53605
  var TunnelManager = class {
53463
53606
  constructor(deps) {
53464
53607
  this.deps = deps;
53465
- this.store = deps.store ?? new TunnelStore(import_node_path37.default.join(deps.dataDir, "tunnel.json"));
53608
+ this.store = deps.store ?? new TunnelStore(import_node_path40.default.join(deps.dataDir, "tunnel.json"));
53466
53609
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
53467
53610
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
53468
53611
  }
@@ -53589,7 +53732,7 @@ var TunnelManager = class {
53589
53732
  dataDir: this.deps.dataDir,
53590
53733
  override: this.deps.frpcBinaryOverride ?? void 0
53591
53734
  });
53592
- const tomlPath = import_node_path37.default.join(this.deps.dataDir, "frpc.toml");
53735
+ const tomlPath = import_node_path40.default.join(this.deps.dataDir, "frpc.toml");
53593
53736
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
53594
53737
  const toml = buildFrpcToml({
53595
53738
  serverAddr: t.frpsHost,
@@ -53600,14 +53743,14 @@ var TunnelManager = class {
53600
53743
  localPort,
53601
53744
  logLevel: "info"
53602
53745
  });
53603
- await import_node_fs36.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53604
- const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
53746
+ await import_node_fs37.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53747
+ const proc = (this.deps.spawnImpl ?? import_node_child_process10.spawn)(frpcBin, ["-c", tomlPath], {
53605
53748
  stdio: ["ignore", "pipe", "pipe"]
53606
53749
  });
53607
- const logDir = import_node_path37.default.join(this.deps.dataDir, "log");
53608
- import_node_fs36.default.mkdirSync(logDir, { recursive: true });
53609
- const logFilePath = import_node_path37.default.join(logDir, "frpc.log");
53610
- const logStream = import_node_fs36.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53750
+ const logDir = import_node_path40.default.join(this.deps.dataDir, "log");
53751
+ import_node_fs37.default.mkdirSync(logDir, { recursive: true });
53752
+ const logFilePath = import_node_path40.default.join(logDir, "frpc.log");
53753
+ const logStream = import_node_fs37.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53611
53754
  logStream.on("error", () => {
53612
53755
  });
53613
53756
  const tee = (chunk) => {
@@ -53690,27 +53833,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
53690
53833
 
53691
53834
  // src/tunnel/device-key.ts
53692
53835
  var import_node_os14 = __toESM(require("os"), 1);
53693
- var import_node_path38 = __toESM(require("path"), 1);
53836
+ var import_node_path41 = __toESM(require("path"), 1);
53694
53837
  var import_node_crypto11 = __toESM(require("crypto"), 1);
53695
53838
  var DERIVE_SALT = "clawd-tunnel-device-v1";
53696
53839
  function deriveStableDeviceKey(opts = {}) {
53697
53840
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
53698
53841
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
53699
53842
  const home = opts.home ?? import_node_os14.default.homedir();
53700
- const defaultDataDir = import_node_path38.default.resolve(import_node_path38.default.join(home, ".clawd"));
53701
- const normalizedDataDir = opts.dataDir ? import_node_path38.default.resolve(opts.dataDir) : null;
53843
+ const defaultDataDir = import_node_path41.default.resolve(import_node_path41.default.join(home, ".clawd"));
53844
+ const normalizedDataDir = opts.dataDir ? import_node_path41.default.resolve(opts.dataDir) : null;
53702
53845
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
53703
53846
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
53704
53847
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
53705
53848
  }
53706
53849
 
53707
53850
  // src/auth-store.ts
53708
- var import_node_fs37 = __toESM(require("fs"), 1);
53709
- var import_node_path39 = __toESM(require("path"), 1);
53851
+ var import_node_fs38 = __toESM(require("fs"), 1);
53852
+ var import_node_path42 = __toESM(require("path"), 1);
53710
53853
  var import_node_crypto12 = __toESM(require("crypto"), 1);
53711
53854
  var AUTH_FILE_NAME = "auth.json";
53712
53855
  function authFilePath(dataDir) {
53713
- return import_node_path39.default.join(dataDir, AUTH_FILE_NAME);
53856
+ return import_node_path42.default.join(dataDir, AUTH_FILE_NAME);
53714
53857
  }
53715
53858
  function loadOrCreateAuthFile(opts) {
53716
53859
  const file = authFilePath(opts.dataDir);
@@ -53746,7 +53889,7 @@ function defaultGenerateOwnerPrincipalId() {
53746
53889
  }
53747
53890
  function readAuthFile(file) {
53748
53891
  try {
53749
- const raw = import_node_fs37.default.readFileSync(file, "utf8");
53892
+ const raw = import_node_fs38.default.readFileSync(file, "utf8");
53750
53893
  const parsed = JSON.parse(raw);
53751
53894
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
53752
53895
  return null;
@@ -53766,25 +53909,25 @@ function readAuthFile(file) {
53766
53909
  }
53767
53910
  }
53768
53911
  function writeAuthFile(file, content) {
53769
- import_node_fs37.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
53770
- import_node_fs37.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53912
+ import_node_fs38.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
53913
+ import_node_fs38.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53771
53914
  try {
53772
- import_node_fs37.default.chmodSync(file, 384);
53915
+ import_node_fs38.default.chmodSync(file, 384);
53773
53916
  } catch {
53774
53917
  }
53775
53918
  }
53776
53919
 
53777
53920
  // src/owner-profile.ts
53778
- var import_node_fs38 = __toESM(require("fs"), 1);
53921
+ var import_node_fs39 = __toESM(require("fs"), 1);
53779
53922
  var import_node_os15 = __toESM(require("os"), 1);
53780
- var import_node_path40 = __toESM(require("path"), 1);
53923
+ var import_node_path43 = __toESM(require("path"), 1);
53781
53924
  var PROFILE_FILENAME = "profile.json";
53782
53925
  function loadOwnerDisplayName(dataDir) {
53783
53926
  const fallback = import_node_os15.default.userInfo().username;
53784
- const profilePath = import_node_path40.default.join(dataDir, PROFILE_FILENAME);
53927
+ const profilePath = import_node_path43.default.join(dataDir, PROFILE_FILENAME);
53785
53928
  let raw;
53786
53929
  try {
53787
- raw = import_node_fs38.default.readFileSync(profilePath, "utf8");
53930
+ raw = import_node_fs39.default.readFileSync(profilePath, "utf8");
53788
53931
  } catch {
53789
53932
  return fallback;
53790
53933
  }
@@ -53807,18 +53950,18 @@ function loadOwnerDisplayName(dataDir) {
53807
53950
  }
53808
53951
 
53809
53952
  // src/feishu-auth/owner-identity-store.ts
53810
- var import_node_fs39 = __toESM(require("fs"), 1);
53811
- var import_node_path41 = __toESM(require("path"), 1);
53953
+ var import_node_fs40 = __toESM(require("fs"), 1);
53954
+ var import_node_path44 = __toESM(require("path"), 1);
53812
53955
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
53813
53956
  var OwnerIdentityStore = class {
53814
53957
  file;
53815
53958
  constructor(dataDir) {
53816
- this.file = import_node_path41.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53959
+ this.file = import_node_path44.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53817
53960
  }
53818
53961
  read() {
53819
53962
  let raw;
53820
53963
  try {
53821
- raw = import_node_fs39.default.readFileSync(this.file, "utf8");
53964
+ raw = import_node_fs40.default.readFileSync(this.file, "utf8");
53822
53965
  } catch {
53823
53966
  return null;
53824
53967
  }
@@ -53846,16 +53989,16 @@ var OwnerIdentityStore = class {
53846
53989
  };
53847
53990
  }
53848
53991
  write(record) {
53849
- import_node_fs39.default.mkdirSync(import_node_path41.default.dirname(this.file), { recursive: true });
53850
- import_node_fs39.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
53992
+ import_node_fs40.default.mkdirSync(import_node_path44.default.dirname(this.file), { recursive: true });
53993
+ import_node_fs40.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
53851
53994
  try {
53852
- import_node_fs39.default.chmodSync(this.file, 384);
53995
+ import_node_fs40.default.chmodSync(this.file, 384);
53853
53996
  } catch {
53854
53997
  }
53855
53998
  }
53856
53999
  clear() {
53857
54000
  try {
53858
- import_node_fs39.default.unlinkSync(this.file);
54001
+ import_node_fs40.default.unlinkSync(this.file);
53859
54002
  } catch (err) {
53860
54003
  const code = err?.code;
53861
54004
  if (code !== "ENOENT") throw err;
@@ -53992,9 +54135,9 @@ var CentralClientError = class extends Error {
53992
54135
  code;
53993
54136
  cause;
53994
54137
  };
53995
- async function centralRequest(opts, path71, init) {
54138
+ async function centralRequest(opts, path74, init) {
53996
54139
  const f = opts.fetchImpl ?? globalThis.fetch;
53997
- const url = `${opts.api.replace(/\/+$/, "")}${path71}`;
54140
+ const url = `${opts.api.replace(/\/+$/, "")}${path74}`;
53998
54141
  const ctrl = new AbortController();
53999
54142
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54000
54143
  let res;
@@ -54188,8 +54331,8 @@ function verifyConnectToken(args) {
54188
54331
  }
54189
54332
 
54190
54333
  // src/feishu-auth/server-key.ts
54191
- var fs50 = __toESM(require("fs"), 1);
54192
- var path50 = __toESM(require("path"), 1);
54334
+ var fs51 = __toESM(require("fs"), 1);
54335
+ var path53 = __toESM(require("path"), 1);
54193
54336
  var FILE_NAME2 = "server-signing-key.json";
54194
54337
  var ServerKeyStore = class {
54195
54338
  constructor(dataDir) {
@@ -54197,12 +54340,12 @@ var ServerKeyStore = class {
54197
54340
  }
54198
54341
  dataDir;
54199
54342
  filePath() {
54200
- return path50.join(this.dataDir, FILE_NAME2);
54343
+ return path53.join(this.dataDir, FILE_NAME2);
54201
54344
  }
54202
54345
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54203
54346
  read() {
54204
54347
  try {
54205
- const raw = fs50.readFileSync(this.filePath(), "utf8");
54348
+ const raw = fs51.readFileSync(this.filePath(), "utf8");
54206
54349
  const parsed = JSON.parse(raw);
54207
54350
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54208
54351
  return parsed.publicKeyPem;
@@ -54217,12 +54360,12 @@ var ServerKeyStore = class {
54217
54360
  publicKeyPem,
54218
54361
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54219
54362
  };
54220
- fs50.mkdirSync(this.dataDir, { recursive: true });
54221
- fs50.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54363
+ fs51.mkdirSync(this.dataDir, { recursive: true });
54364
+ fs51.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54222
54365
  }
54223
54366
  clear() {
54224
54367
  try {
54225
- fs50.unlinkSync(this.filePath());
54368
+ fs51.unlinkSync(this.filePath());
54226
54369
  } catch {
54227
54370
  }
54228
54371
  }
@@ -54235,12 +54378,12 @@ init_protocol();
54235
54378
  init_protocol();
54236
54379
 
54237
54380
  // src/session/fork.ts
54238
- var import_node_fs40 = __toESM(require("fs"), 1);
54381
+ var import_node_fs41 = __toESM(require("fs"), 1);
54239
54382
  var import_node_os16 = __toESM(require("os"), 1);
54240
- var import_node_path42 = __toESM(require("path"), 1);
54383
+ var import_node_path45 = __toESM(require("path"), 1);
54241
54384
  init_claude_history();
54242
54385
  function readJsonlEntries(file) {
54243
- const raw = import_node_fs40.default.readFileSync(file, "utf8");
54386
+ const raw = import_node_fs41.default.readFileSync(file, "utf8");
54244
54387
  const out = [];
54245
54388
  for (const line of raw.split("\n")) {
54246
54389
  const t = line.trim();
@@ -54253,19 +54396,19 @@ function readJsonlEntries(file) {
54253
54396
  return out;
54254
54397
  }
54255
54398
  function forkSession(input) {
54256
- const baseDir = input.baseDir ?? import_node_path42.default.join(import_node_os16.default.homedir(), ".claude");
54257
- let projectDir = import_node_path42.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54258
- let sourceFile = import_node_path42.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54259
- if (!import_node_fs40.default.existsSync(sourceFile)) {
54399
+ const baseDir = input.baseDir ?? import_node_path45.default.join(import_node_os16.default.homedir(), ".claude");
54400
+ let projectDir = import_node_path45.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54401
+ let sourceFile = import_node_path45.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54402
+ if (!import_node_fs41.default.existsSync(sourceFile)) {
54260
54403
  const found = findTranscriptByToolSessionId(
54261
- import_node_path42.default.join(baseDir, "projects"),
54404
+ import_node_path45.default.join(baseDir, "projects"),
54262
54405
  input.toolSessionId
54263
54406
  );
54264
54407
  if (!found) {
54265
54408
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
54266
54409
  }
54267
54410
  sourceFile = found;
54268
- projectDir = import_node_path42.default.dirname(found);
54411
+ projectDir = import_node_path45.default.dirname(found);
54269
54412
  }
54270
54413
  const entries = readJsonlEntries(sourceFile);
54271
54414
  const mainEntries = entries.filter((e) => e.isSidechain !== true);
@@ -54294,9 +54437,9 @@ function forkSession(input) {
54294
54437
  }
54295
54438
  forkedLines.push(JSON.stringify(forked));
54296
54439
  }
54297
- const forkedFilePath = import_node_path42.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54298
- import_node_fs40.default.mkdirSync(projectDir, { recursive: true });
54299
- import_node_fs40.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54440
+ const forkedFilePath = import_node_path45.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54441
+ import_node_fs41.default.mkdirSync(projectDir, { recursive: true });
54442
+ import_node_fs41.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54300
54443
  return { forkedToolSessionId, forkedFilePath };
54301
54444
  }
54302
54445
 
@@ -54458,21 +54601,34 @@ function buildSessionHandlers(deps) {
54458
54601
  const { broadcast } = await manager.interrupt(args);
54459
54602
  return { response: { type: "session:interrupt", ok: true }, broadcast };
54460
54603
  };
54604
+ const ensureRewindSupported = async (sessionId) => {
54605
+ const file = manager.get({ sessionId }).response;
54606
+ const caps = await getAdapter2(file.tool ?? "claude").capabilities();
54607
+ if (caps.features.rewind === false) {
54608
+ throw new ClawdError(
54609
+ ERROR_CODES.TOOL_NOT_SUPPORTED,
54610
+ `tool ${file.tool ?? "claude"} does not support rewind`
54611
+ );
54612
+ }
54613
+ };
54461
54614
  const rewind = async (frame, _client, ctx) => {
54462
54615
  const args = SessionRewindArgs.parse(frame);
54463
54616
  ensureSessionAccess(ctx, args.sessionId, "send");
54617
+ await ensureRewindSupported(args.sessionId);
54464
54618
  const { response, broadcast } = await manager.rewind(args);
54465
54619
  return { response: { type: "session:rewind", ...response }, broadcast };
54466
54620
  };
54467
54621
  const rewindDiff = async (frame, _client, ctx) => {
54468
54622
  const args = SessionRewindDiffArgs.parse(frame);
54469
54623
  ensureSessionAccess(ctx, args.sessionId, "read");
54624
+ await ensureRewindSupported(args.sessionId);
54470
54625
  const { response } = await manager.rewindDiff(args);
54471
54626
  return { response: { type: "session:rewind-diff", ...response } };
54472
54627
  };
54473
54628
  const rewindableMessageIds = async (frame, _client, ctx) => {
54474
54629
  const args = SessionRewindableMessageIdsArgs.parse(frame);
54475
54630
  ensureSessionAccess(ctx, args.sessionId, "read");
54631
+ await ensureRewindSupported(args.sessionId);
54476
54632
  const { response } = manager.rewindableMessageIds(args);
54477
54633
  return {
54478
54634
  response: { type: "session:rewindable-message-ids", ...response }
@@ -54695,7 +54851,7 @@ function buildPermissionHandlers(deps) {
54695
54851
  }
54696
54852
 
54697
54853
  // src/handlers/history.ts
54698
- var path53 = __toESM(require("path"), 1);
54854
+ var path56 = __toESM(require("path"), 1);
54699
54855
  init_protocol();
54700
54856
 
54701
54857
  // src/session/recent-dirs.ts
@@ -54713,7 +54869,7 @@ function listRecentDirs(store, limit = 50) {
54713
54869
  }
54714
54870
 
54715
54871
  // src/permission/persona-paths.ts
54716
- var path52 = __toESM(require("path"), 1);
54872
+ var path55 = __toESM(require("path"), 1);
54717
54873
  function getAllowedPersonaIds(grants, action) {
54718
54874
  const ids = /* @__PURE__ */ new Set();
54719
54875
  for (const g2 of grants) {
@@ -54726,42 +54882,42 @@ function getAllowedPersonaIds(grants, action) {
54726
54882
  return ids;
54727
54883
  }
54728
54884
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
54729
- const target = path52.resolve(absPath);
54885
+ const target = path55.resolve(absPath);
54730
54886
  if (userWorkDir) {
54731
- const u = path52.resolve(userWorkDir);
54732
- const usep = u.endsWith(path52.sep) ? "" : path52.sep;
54887
+ const u = path55.resolve(userWorkDir);
54888
+ const usep = u.endsWith(path55.sep) ? "" : path55.sep;
54733
54889
  if (target === u || target.startsWith(u + usep)) return true;
54734
54890
  }
54735
- const root = path52.resolve(personaRoot);
54736
- const sep3 = root.endsWith(path52.sep) ? "" : path52.sep;
54891
+ const root = path55.resolve(personaRoot);
54892
+ const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54737
54893
  if (!target.startsWith(root + sep3)) return false;
54738
- const rel = path52.relative(root, target);
54894
+ const rel = path55.relative(root, target);
54739
54895
  if (!rel || rel.startsWith("..")) return false;
54740
- const personaId = rel.split(path52.sep)[0];
54896
+ const personaId = rel.split(path55.sep)[0];
54741
54897
  if (!personaId) return false;
54742
54898
  const allowed = getAllowedPersonaIds(grants, action);
54743
54899
  if (allowed === "*") return true;
54744
54900
  return allowed.has(personaId);
54745
54901
  }
54746
54902
  function personaIdFromPath(absPath, personaRoot) {
54747
- const root = path52.resolve(personaRoot);
54748
- const target = path52.resolve(absPath);
54749
- const sep3 = root.endsWith(path52.sep) ? "" : path52.sep;
54903
+ const root = path55.resolve(personaRoot);
54904
+ const target = path55.resolve(absPath);
54905
+ const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54750
54906
  if (!target.startsWith(root + sep3)) return null;
54751
- const rel = path52.relative(root, target);
54907
+ const rel = path55.relative(root, target);
54752
54908
  if (!rel || rel.startsWith("..")) return null;
54753
- const id = rel.split(path52.sep)[0];
54909
+ const id = rel.split(path55.sep)[0];
54754
54910
  return id || null;
54755
54911
  }
54756
54912
  function isPathWithin(dir, absPath) {
54757
- const d = path52.resolve(dir);
54758
- const t = path52.resolve(absPath);
54759
- const sep3 = d.endsWith(path52.sep) ? "" : path52.sep;
54913
+ const d = path55.resolve(dir);
54914
+ const t = path55.resolve(absPath);
54915
+ const sep3 = d.endsWith(path55.sep) ? "" : path55.sep;
54760
54916
  return t === d || t.startsWith(d + sep3);
54761
54917
  }
54762
54918
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
54763
54919
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
54764
- return personaIdFromPath(path52.resolve(absPath), personaRoot) === personaId;
54920
+ return personaIdFromPath(path55.resolve(absPath), personaRoot) === personaId;
54765
54921
  }
54766
54922
 
54767
54923
  // src/handlers/history.ts
@@ -54813,7 +54969,7 @@ function buildHistoryHandlers(deps) {
54813
54969
  if (!pid) return false;
54814
54970
  return isGuestPathAllowed(
54815
54971
  ctx.grants,
54816
- path53.join(personaRoot, pid),
54972
+ path56.join(personaRoot, pid),
54817
54973
  personaRoot,
54818
54974
  "read",
54819
54975
  userWorkDir
@@ -54825,7 +54981,7 @@ function buildHistoryHandlers(deps) {
54825
54981
  };
54826
54982
  const list = async (frame, _client, ctx) => {
54827
54983
  const args = HistoryListArgs.parse(frame);
54828
- assertGuestPath(ctx, path53.resolve(args.projectPath), personaRoot, "history:list");
54984
+ assertGuestPath(ctx, path56.resolve(args.projectPath), personaRoot, "history:list");
54829
54985
  const sessions = await history.listSessions(args);
54830
54986
  return { response: { type: "history:list", sessions } };
54831
54987
  };
@@ -54858,13 +55014,13 @@ function buildHistoryHandlers(deps) {
54858
55014
  };
54859
55015
  const subagents = async (frame, _client, ctx) => {
54860
55016
  const args = HistorySubagentsArgs.parse(frame);
54861
- assertGuestPath(ctx, path53.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
55017
+ assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54862
55018
  const subs = await history.listSubagents(args);
54863
55019
  return { response: { type: "history:subagents", subagents: subs } };
54864
55020
  };
54865
55021
  const subagentRead = async (frame, _client, ctx) => {
54866
55022
  const args = HistorySubagentReadArgs.parse(frame);
54867
- assertGuestPath(ctx, path53.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
55023
+ assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54868
55024
  const res = await history.readSubagent(args);
54869
55025
  return { response: { type: "history:subagent-read", ...res } };
54870
55026
  };
@@ -54873,7 +55029,7 @@ function buildHistoryHandlers(deps) {
54873
55029
  if (ctx?.principal.kind === "guest" && personaRoot) {
54874
55030
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54875
55031
  const filtered = dirs.filter(
54876
- (d) => isGuestPathAllowed(ctx.grants, path53.resolve(d.cwd), personaRoot, "read", userWorkDir)
55032
+ (d) => isGuestPathAllowed(ctx.grants, path56.resolve(d.cwd), personaRoot, "read", userWorkDir)
54877
55033
  );
54878
55034
  return { response: { type: "history:recentDirs", dirs: filtered } };
54879
55035
  }
@@ -54890,7 +55046,7 @@ function buildHistoryHandlers(deps) {
54890
55046
  }
54891
55047
 
54892
55048
  // src/handlers/workspace.ts
54893
- var path54 = __toESM(require("path"), 1);
55049
+ var path57 = __toESM(require("path"), 1);
54894
55050
  var os16 = __toESM(require("os"), 1);
54895
55051
  init_protocol();
54896
55052
  init_protocol();
@@ -54932,22 +55088,22 @@ function buildWorkspaceHandlers(deps) {
54932
55088
  const args = WorkspaceListArgs.parse(frame);
54933
55089
  const isGuest = ctx?.principal.kind === "guest";
54934
55090
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
54935
- const resolvedCwd = path54.resolve(args.cwd ?? fallbackCwd);
54936
- const target = args.path ? path54.resolve(resolvedCwd, args.path) : resolvedCwd;
55091
+ const resolvedCwd = path57.resolve(args.cwd ?? fallbackCwd);
55092
+ const target = args.path ? path57.resolve(resolvedCwd, args.path) : resolvedCwd;
54937
55093
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
54938
55094
  const res = workspace.list({ ...args, cwd: resolvedCwd });
54939
55095
  return { response: { type: "workspace:list", ...res } };
54940
55096
  };
54941
55097
  const read = async (frame, _client, ctx) => {
54942
55098
  const args = WorkspaceReadArgs.parse(frame);
54943
- const target = path54.isAbsolute(args.path) ? path54.resolve(args.path) : path54.resolve(args.cwd, args.path);
55099
+ const target = path57.isAbsolute(args.path) ? path57.resolve(args.path) : path57.resolve(args.cwd, args.path);
54944
55100
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
54945
55101
  const res = workspace.read(args);
54946
55102
  return { response: { type: "workspace:read", ...res } };
54947
55103
  };
54948
55104
  const skillsList = async (frame, _client, ctx) => {
54949
55105
  const args = SkillsListArgs.parse(frame);
54950
- const cwdAbs = path54.resolve(args.cwd);
55106
+ const cwdAbs = path57.resolve(args.cwd);
54951
55107
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
54952
55108
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
54953
55109
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -54959,7 +55115,7 @@ function buildWorkspaceHandlers(deps) {
54959
55115
  };
54960
55116
  const agentsList = async (frame, _client, ctx) => {
54961
55117
  const args = AgentsListArgs.parse(frame);
54962
- const cwdAbs = path54.resolve(args.cwd);
55118
+ const cwdAbs = path57.resolve(args.cwd);
54963
55119
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
54964
55120
  if (args.tool === "codex") {
54965
55121
  return { response: { type: "agents:list", agents: [] } };
@@ -54981,20 +55137,20 @@ function buildWorkspaceHandlers(deps) {
54981
55137
  }
54982
55138
 
54983
55139
  // src/handlers/git.ts
54984
- var path56 = __toESM(require("path"), 1);
55140
+ var path59 = __toESM(require("path"), 1);
54985
55141
  init_protocol();
54986
55142
  init_protocol();
54987
55143
 
54988
55144
  // src/workspace/git.ts
54989
- var import_node_child_process10 = require("child_process");
54990
- var import_node_fs41 = __toESM(require("fs"), 1);
54991
- var import_node_path43 = __toESM(require("path"), 1);
55145
+ var import_node_child_process11 = require("child_process");
55146
+ var import_node_fs42 = __toESM(require("fs"), 1);
55147
+ var import_node_path46 = __toESM(require("path"), 1);
54992
55148
  var import_node_util = require("util");
54993
- var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
55149
+ var pexec = (0, import_node_util.promisify)(import_node_child_process11.execFile);
54994
55150
  function normalizePath(p2) {
54995
- const resolved = import_node_path43.default.resolve(p2);
55151
+ const resolved = import_node_path46.default.resolve(p2);
54996
55152
  try {
54997
- return import_node_fs41.default.realpathSync(resolved);
55153
+ return import_node_fs42.default.realpathSync(resolved);
54998
55154
  } catch {
54999
55155
  return resolved;
55000
55156
  }
@@ -55068,7 +55224,7 @@ async function listGitBranches(cwd) {
55068
55224
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
55069
55225
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
55070
55226
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
55071
- if (!isGuestPathAllowed(ctx.grants, path56.resolve(cwd), personaRoot, "read", userWorkDir)) {
55227
+ if (!isGuestPathAllowed(ctx.grants, path59.resolve(cwd), personaRoot, "read", userWorkDir)) {
55072
55228
  throw new ClawdError(
55073
55229
  ERROR_CODES.UNAUTHORIZED,
55074
55230
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -55754,7 +55910,7 @@ function buildPersonaHandlers(deps) {
55754
55910
  }
55755
55911
 
55756
55912
  // src/handlers/attachment.ts
55757
- var import_node_path44 = __toESM(require("path"), 1);
55913
+ var import_node_path47 = __toESM(require("path"), 1);
55758
55914
  init_protocol();
55759
55915
  init_protocol();
55760
55916
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -55834,12 +55990,12 @@ function buildAttachmentHandlers(deps) {
55834
55990
  `session ${args.sessionId} scope unresolved`
55835
55991
  );
55836
55992
  }
55837
- const cwdAbs = import_node_path44.default.resolve(sessionFile.cwd);
55838
- const candidateAbs = import_node_path44.default.isAbsolute(args.relPath) ? import_node_path44.default.resolve(args.relPath) : import_node_path44.default.resolve(cwdAbs, args.relPath);
55993
+ const cwdAbs = import_node_path47.default.resolve(sessionFile.cwd);
55994
+ const candidateAbs = import_node_path47.default.isAbsolute(args.relPath) ? import_node_path47.default.resolve(args.relPath) : import_node_path47.default.resolve(cwdAbs, args.relPath);
55839
55995
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
55840
55996
  const entries = deps.groupFileStore.list(scope, args.sessionId);
55841
55997
  const entry = entries.find((e) => {
55842
- const storedAbs = import_node_path44.default.isAbsolute(e.relPath) ? import_node_path44.default.resolve(e.relPath) : import_node_path44.default.resolve(cwdAbs, e.relPath);
55998
+ const storedAbs = import_node_path47.default.isAbsolute(e.relPath) ? import_node_path47.default.resolve(e.relPath) : import_node_path47.default.resolve(cwdAbs, e.relPath);
55843
55999
  return storedAbs === candidateAbs && !e.stale;
55844
56000
  });
55845
56001
  if (!entry) {
@@ -55864,7 +56020,7 @@ function buildAttachmentHandlers(deps) {
55864
56020
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
55865
56021
  const f = deps.sessionStore.read(sessionId);
55866
56022
  if (!f) return;
55867
- assertGuestAttachmentPath(ctx, import_node_path44.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
56023
+ assertGuestAttachmentPath(ctx, import_node_path47.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55868
56024
  }
55869
56025
  const groupAdd = async (frame, _client, ctx) => {
55870
56026
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -55879,8 +56035,8 @@ function buildAttachmentHandlers(deps) {
55879
56035
  if (!scope) {
55880
56036
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
55881
56037
  }
55882
- const cwdAbs = import_node_path44.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55883
- const candidateAbs = import_node_path44.default.isAbsolute(args.relPath) ? import_node_path44.default.resolve(args.relPath) : import_node_path44.default.resolve(cwdAbs, args.relPath);
56038
+ const cwdAbs = import_node_path47.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
56039
+ const candidateAbs = import_node_path47.default.isAbsolute(args.relPath) ? import_node_path47.default.resolve(args.relPath) : import_node_path47.default.resolve(cwdAbs, args.relPath);
55884
56040
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
55885
56041
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
55886
56042
  const size = 0;
@@ -55939,19 +56095,19 @@ function buildAttachmentHandlers(deps) {
55939
56095
 
55940
56096
  // src/handlers/extension.ts
55941
56097
  var import_promises9 = __toESM(require("fs/promises"), 1);
55942
- var import_node_path49 = __toESM(require("path"), 1);
56098
+ var import_node_path52 = __toESM(require("path"), 1);
55943
56099
  init_protocol();
55944
56100
 
55945
56101
  // src/extension/bundle-zip.ts
55946
56102
  var import_promises6 = __toESM(require("fs/promises"), 1);
55947
- var import_node_path45 = __toESM(require("path"), 1);
56103
+ var import_node_path48 = __toESM(require("path"), 1);
55948
56104
  var import_node_crypto14 = __toESM(require("crypto"), 1);
55949
56105
  var import_jszip2 = __toESM(require_lib3(), 1);
55950
56106
  async function bundleExtensionDir(dir) {
55951
56107
  const entries = await listFilesSorted(dir);
55952
56108
  const zip = new import_jszip2.default();
55953
56109
  for (const rel of entries) {
55954
- const abs = import_node_path45.default.join(dir, rel);
56110
+ const abs = import_node_path48.default.join(dir, rel);
55955
56111
  const content = await import_promises6.default.readFile(abs);
55956
56112
  zip.file(rel, content, { date: FIXED_DATE });
55957
56113
  }
@@ -55972,7 +56128,7 @@ async function listFilesSorted(rootDir) {
55972
56128
  return out;
55973
56129
  }
55974
56130
  async function walk(absRoot, relPrefix, out) {
55975
- const dirAbs = import_node_path45.default.join(absRoot, relPrefix);
56131
+ const dirAbs = import_node_path48.default.join(absRoot, relPrefix);
55976
56132
  const entries = await import_promises6.default.readdir(dirAbs, { withFileTypes: true });
55977
56133
  for (const e of entries) {
55978
56134
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -56026,25 +56182,25 @@ function computePublishCheck(args) {
56026
56182
 
56027
56183
  // src/extension/install-flow.ts
56028
56184
  var import_promises7 = __toESM(require("fs/promises"), 1);
56029
- var import_node_path47 = __toESM(require("path"), 1);
56185
+ var import_node_path50 = __toESM(require("path"), 1);
56030
56186
  var import_node_os19 = __toESM(require("os"), 1);
56031
56187
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56032
56188
  var import_jszip3 = __toESM(require_lib3(), 1);
56033
56189
 
56034
56190
  // src/extension/paths.ts
56035
56191
  var import_node_os18 = __toESM(require("os"), 1);
56036
- var import_node_path46 = __toESM(require("path"), 1);
56192
+ var import_node_path49 = __toESM(require("path"), 1);
56037
56193
  function clawdHomeRoot(override) {
56038
- return override ?? process.env.CLAWD_HOME ?? import_node_path46.default.join(import_node_os18.default.homedir(), ".clawd");
56194
+ return override ?? process.env.CLAWD_HOME ?? import_node_path49.default.join(import_node_os18.default.homedir(), ".clawd");
56039
56195
  }
56040
56196
  function extensionsRoot(override) {
56041
- return import_node_path46.default.join(clawdHomeRoot(override), "extensions");
56197
+ return import_node_path49.default.join(clawdHomeRoot(override), "extensions");
56042
56198
  }
56043
56199
  function publishedChannelsFile(override) {
56044
- return import_node_path46.default.join(clawdHomeRoot(override), "extensions-published.json");
56200
+ return import_node_path49.default.join(clawdHomeRoot(override), "extensions-published.json");
56045
56201
  }
56046
56202
  function bundleCacheRoot(override) {
56047
- return import_node_path46.default.join(clawdHomeRoot(override), "extension-bundles");
56203
+ return import_node_path49.default.join(clawdHomeRoot(override), "extension-bundles");
56048
56204
  }
56049
56205
 
56050
56206
  // src/extension/install-flow.ts
@@ -56071,7 +56227,7 @@ async function installFromChannel(args, deps) {
56071
56227
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56072
56228
  }
56073
56229
  for (const name of Object.keys(zip.files)) {
56074
- if (name.includes("..") || name.startsWith("/") || import_node_path47.default.isAbsolute(name)) {
56230
+ if (name.includes("..") || name.startsWith("/") || import_node_path50.default.isAbsolute(name)) {
56075
56231
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56076
56232
  }
56077
56233
  }
@@ -56103,7 +56259,7 @@ async function installFromChannel(args, deps) {
56103
56259
  );
56104
56260
  }
56105
56261
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
56106
- const destDir = import_node_path47.default.join(deps.extensionsRoot, localExtId);
56262
+ const destDir = import_node_path50.default.join(deps.extensionsRoot, localExtId);
56107
56263
  let destExists = false;
56108
56264
  try {
56109
56265
  await import_promises7.default.access(destDir);
@@ -56117,16 +56273,16 @@ async function installFromChannel(args, deps) {
56117
56273
  );
56118
56274
  }
56119
56275
  const stage = await import_promises7.default.mkdtemp(
56120
- import_node_path47.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56276
+ import_node_path50.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56121
56277
  );
56122
56278
  try {
56123
56279
  for (const [name, entry] of Object.entries(zip.files)) {
56124
- const dest = import_node_path47.default.join(stage, name);
56280
+ const dest = import_node_path50.default.join(stage, name);
56125
56281
  if (entry.dir) {
56126
56282
  await import_promises7.default.mkdir(dest, { recursive: true });
56127
56283
  continue;
56128
56284
  }
56129
- await import_promises7.default.mkdir(import_node_path47.default.dirname(dest), { recursive: true });
56285
+ await import_promises7.default.mkdir(import_node_path50.default.dirname(dest), { recursive: true });
56130
56286
  if (name === "manifest.json") {
56131
56287
  const rewritten = { ...parsed.data, id: localExtId };
56132
56288
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56147,7 +56303,7 @@ async function installFromChannel(args, deps) {
56147
56303
 
56148
56304
  // src/extension/update-flow.ts
56149
56305
  var import_promises8 = __toESM(require("fs/promises"), 1);
56150
- var import_node_path48 = __toESM(require("path"), 1);
56306
+ var import_node_path51 = __toESM(require("path"), 1);
56151
56307
  var import_node_os20 = __toESM(require("os"), 1);
56152
56308
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56153
56309
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -56164,11 +56320,11 @@ async function updateFromChannel(args, deps) {
56164
56320
  channelRef.extId,
56165
56321
  channelRef.ownerPrincipalId
56166
56322
  );
56167
- const liveDir = import_node_path48.default.join(deps.extensionsRoot, localExtId);
56323
+ const liveDir = import_node_path51.default.join(deps.extensionsRoot, localExtId);
56168
56324
  const prevDir = `${liveDir}.prev`;
56169
56325
  let existingVersion;
56170
56326
  try {
56171
- const raw = await import_promises8.default.readFile(import_node_path48.default.join(liveDir, "manifest.json"), "utf8");
56327
+ const raw = await import_promises8.default.readFile(import_node_path51.default.join(liveDir, "manifest.json"), "utf8");
56172
56328
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
56173
56329
  if (!parsed2.success) {
56174
56330
  throw new UpdateError(
@@ -56201,7 +56357,7 @@ async function updateFromChannel(args, deps) {
56201
56357
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56202
56358
  }
56203
56359
  for (const name of Object.keys(zip.files)) {
56204
- if (name.includes("..") || name.startsWith("/") || import_node_path48.default.isAbsolute(name)) {
56360
+ if (name.includes("..") || name.startsWith("/") || import_node_path51.default.isAbsolute(name)) {
56205
56361
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56206
56362
  }
56207
56363
  }
@@ -56236,16 +56392,16 @@ async function updateFromChannel(args, deps) {
56236
56392
  await import_promises8.default.rm(prevDir, { recursive: true, force: true });
56237
56393
  await import_promises8.default.rename(liveDir, prevDir);
56238
56394
  const stage = await import_promises8.default.mkdtemp(
56239
- import_node_path48.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56395
+ import_node_path51.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56240
56396
  );
56241
56397
  try {
56242
56398
  for (const [name, entry] of Object.entries(zip.files)) {
56243
- const dest = import_node_path48.default.join(stage, name);
56399
+ const dest = import_node_path51.default.join(stage, name);
56244
56400
  if (entry.dir) {
56245
56401
  await import_promises8.default.mkdir(dest, { recursive: true });
56246
56402
  continue;
56247
56403
  }
56248
- await import_promises8.default.mkdir(import_node_path48.default.dirname(dest), { recursive: true });
56404
+ await import_promises8.default.mkdir(import_node_path51.default.dirname(dest), { recursive: true });
56249
56405
  if (name === "manifest.json") {
56250
56406
  const rewritten = { ...parsed.data, id: localExtId };
56251
56407
  await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56338,7 +56494,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56338
56494
  );
56339
56495
  }
56340
56496
  }
56341
- const manifestPath = import_node_path49.default.join(root, extId, "manifest.json");
56497
+ const manifestPath = import_node_path52.default.join(root, extId, "manifest.json");
56342
56498
  const manifest = await readManifest(root, extId);
56343
56499
  const next = { ...manifest, version: newVersion };
56344
56500
  const tmp = `${manifestPath}.tmp`;
@@ -56346,7 +56502,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56346
56502
  await import_promises9.default.rename(tmp, manifestPath);
56347
56503
  }
56348
56504
  async function readManifest(root, extId) {
56349
- const file = import_node_path49.default.join(root, extId, "manifest.json");
56505
+ const file = import_node_path52.default.join(root, extId, "manifest.json");
56350
56506
  let raw;
56351
56507
  try {
56352
56508
  raw = await import_promises9.default.readFile(file, "utf8");
@@ -56437,7 +56593,7 @@ function buildExtensionHandlers(deps) {
56437
56593
  };
56438
56594
  async function buildSnapshotMeta(extId) {
56439
56595
  const manifest = await readManifest(deps.root, extId);
56440
- const { sha256, buffer } = await bundleExtensionDir(import_node_path49.default.join(deps.root, extId));
56596
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path52.default.join(deps.root, extId));
56441
56597
  return { manifest, contentHash: sha256, buffer };
56442
56598
  }
56443
56599
  const publish = async (frame, _client, ctx) => {
@@ -56618,9 +56774,9 @@ function buildExtensionHandlers(deps) {
56618
56774
  }
56619
56775
 
56620
56776
  // src/app-builder/project-store.ts
56621
- var import_node_fs42 = require("fs");
56622
- var import_node_child_process11 = require("child_process");
56623
- var import_node_path50 = require("path");
56777
+ var import_node_fs43 = require("fs");
56778
+ var import_node_child_process12 = require("child_process");
56779
+ var import_node_path53 = require("path");
56624
56780
  init_protocol();
56625
56781
  var PROJECTS_DIR = "projects";
56626
56782
  var META_FILE = ".clawd-project.json";
@@ -56634,19 +56790,19 @@ var ProjectStore = class {
56634
56790
  root;
56635
56791
  /** projects/<name>/.clawd-project.json 路径 */
56636
56792
  metaPath(name) {
56637
- return (0, import_node_path50.join)(this.projectsRoot(), name, META_FILE);
56793
+ return (0, import_node_path53.join)(this.projectsRoot(), name, META_FILE);
56638
56794
  }
56639
56795
  /** projects/<name>/ 目录路径(cwd 用) */
56640
56796
  projectDir(name) {
56641
- return (0, import_node_path50.join)(this.projectsRoot(), name);
56797
+ return (0, import_node_path53.join)(this.projectsRoot(), name);
56642
56798
  }
56643
56799
  projectsRoot() {
56644
- return (0, import_node_path50.join)(this.root, PROJECTS_DIR);
56800
+ return (0, import_node_path53.join)(this.root, PROJECTS_DIR);
56645
56801
  }
56646
56802
  async list() {
56647
56803
  let entries;
56648
56804
  try {
56649
- entries = await import_node_fs42.promises.readdir(this.projectsRoot());
56805
+ entries = await import_node_fs43.promises.readdir(this.projectsRoot());
56650
56806
  } catch (err) {
56651
56807
  if (err.code === "ENOENT") return [];
56652
56808
  throw err;
@@ -56654,7 +56810,7 @@ var ProjectStore = class {
56654
56810
  const out = [];
56655
56811
  for (const name of entries) {
56656
56812
  try {
56657
- const raw = await import_node_fs42.promises.readFile(this.metaPath(name), "utf8");
56813
+ const raw = await import_node_fs43.promises.readFile(this.metaPath(name), "utf8");
56658
56814
  const json = JSON.parse(raw);
56659
56815
  let migrated = false;
56660
56816
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -56665,7 +56821,7 @@ var ProjectStore = class {
56665
56821
  if (parsed.success) {
56666
56822
  out.push(parsed.data);
56667
56823
  if (migrated) {
56668
- void import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56824
+ void import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56669
56825
  });
56670
56826
  }
56671
56827
  }
@@ -56709,8 +56865,8 @@ var ProjectStore = class {
56709
56865
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
56710
56866
  }
56711
56867
  const dir = this.projectDir(name);
56712
- await import_node_fs42.promises.mkdir(dir, { recursive: true });
56713
- await import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56868
+ await import_node_fs43.promises.mkdir(dir, { recursive: true });
56869
+ await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56714
56870
  return meta;
56715
56871
  }
56716
56872
  /**
@@ -56724,7 +56880,7 @@ var ProjectStore = class {
56724
56880
  async scaffold(name, templateSrcDir, scaffoldScriptPath) {
56725
56881
  const destDir = this.projectDir(name);
56726
56882
  return await new Promise((resolve6, reject) => {
56727
- const child = (0, import_node_child_process11.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
56883
+ const child = (0, import_node_child_process12.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
56728
56884
  env: { ...process.env, PATH: process.env.PATH ?? "" },
56729
56885
  stdio: ["ignore", "pipe", "pipe"]
56730
56886
  });
@@ -56753,7 +56909,7 @@ var ProjectStore = class {
56753
56909
  }
56754
56910
  async delete(name) {
56755
56911
  const dir = this.projectDir(name);
56756
- await import_node_fs42.promises.rm(dir, { recursive: true, force: true });
56912
+ await import_node_fs43.promises.rm(dir, { recursive: true, force: true });
56757
56913
  }
56758
56914
  async updatePort(name, newPort) {
56759
56915
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -56769,7 +56925,7 @@ var ProjectStore = class {
56769
56925
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
56770
56926
  }
56771
56927
  const updated = { ...target, port: newPort };
56772
- await import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56928
+ await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56773
56929
  return updated;
56774
56930
  }
56775
56931
  /**
@@ -56786,7 +56942,7 @@ var ProjectStore = class {
56786
56942
  if (!validated.success) {
56787
56943
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
56788
56944
  }
56789
- await import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56945
+ await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56790
56946
  return validated.data;
56791
56947
  }
56792
56948
  /**
@@ -56807,7 +56963,7 @@ var ProjectStore = class {
56807
56963
  if (!validated.success) {
56808
56964
  throw new Error(`invalid publishJob: ${validated.error.message}`);
56809
56965
  }
56810
- await import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56966
+ await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56811
56967
  return validated.data;
56812
56968
  }
56813
56969
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -56822,13 +56978,13 @@ var ProjectStore = class {
56822
56978
  if (!validated.success) {
56823
56979
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
56824
56980
  }
56825
- await import_node_fs42.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56981
+ await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56826
56982
  return validated.data;
56827
56983
  }
56828
56984
  };
56829
56985
 
56830
56986
  // src/app-builder/kill-port.ts
56831
- var import_node_child_process12 = require("child_process");
56987
+ var import_node_child_process13 = require("child_process");
56832
56988
  async function killPortOccupants(port, ownedPids, logger) {
56833
56989
  let pids;
56834
56990
  try {
@@ -56870,7 +57026,7 @@ async function killPortOccupants(port, ownedPids, logger) {
56870
57026
  }
56871
57027
  function listPidsOnPort(port) {
56872
57028
  return new Promise((resolve6, reject) => {
56873
- (0, import_node_child_process12.execFile)(
57029
+ (0, import_node_child_process13.execFile)(
56874
57030
  "lsof",
56875
57031
  ["-ti", `:${port}`],
56876
57032
  { timeout: 3e3 },
@@ -56942,9 +57098,9 @@ var PublishJobRegistry = class {
56942
57098
  };
56943
57099
 
56944
57100
  // src/app-builder/publish-job-runner.ts
56945
- var import_node_child_process13 = require("child_process");
56946
- var import_node_fs43 = require("fs");
56947
- var import_node_path51 = require("path");
57101
+ var import_node_child_process14 = require("child_process");
57102
+ var import_node_fs44 = require("fs");
57103
+ var import_node_path54 = require("path");
56948
57104
 
56949
57105
  // src/app-builder/publish-stage-parser.ts
56950
57106
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -56971,15 +57127,15 @@ function tailStderrLines(buf, n) {
56971
57127
  // src/app-builder/publish-job-runner.ts
56972
57128
  async function startPublishJob(deps, args) {
56973
57129
  const { registry: registry2, projectDir } = deps;
56974
- const spawn13 = deps.spawnImpl ?? import_node_child_process13.spawn;
57130
+ const spawn13 = deps.spawnImpl ?? import_node_child_process14.spawn;
56975
57131
  if (registry2.has(args.name)) {
56976
57132
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
56977
57133
  }
56978
57134
  const projDir = projectDir(args.name);
56979
- const logPath = (0, import_node_path51.join)(projDir, ".publish.log");
57135
+ const logPath = (0, import_node_path54.join)(projDir, ".publish.log");
56980
57136
  let logStream = null;
56981
57137
  try {
56982
- logStream = (0, import_node_fs43.createWriteStream)(logPath, { flags: "w" });
57138
+ logStream = (0, import_node_fs44.createWriteStream)(logPath, { flags: "w" });
56983
57139
  } catch {
56984
57140
  logStream = null;
56985
57141
  }
@@ -57236,8 +57392,8 @@ async function recoverInterruptedJobs(deps) {
57236
57392
 
57237
57393
  // src/handlers/app-builder.ts
57238
57394
  init_protocol();
57239
- var import_node_path52 = require("path");
57240
- var import_node_fs44 = require("fs");
57395
+ var import_node_path55 = require("path");
57396
+ var import_node_fs45 = require("fs");
57241
57397
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57242
57398
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57243
57399
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57318,7 +57474,7 @@ function buildAppBuilderHandlers(deps) {
57318
57474
  async function listAllUsersProjects() {
57319
57475
  if (!deps.usersRoot || !deps.getStore) return [];
57320
57476
  const getStore = deps.getStore;
57321
- const userIds = await import_node_fs44.promises.readdir(deps.usersRoot).catch(() => []);
57477
+ const userIds = await import_node_fs45.promises.readdir(deps.usersRoot).catch(() => []);
57322
57478
  const perUser = await Promise.all(
57323
57479
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57324
57480
  );
@@ -57394,8 +57550,8 @@ function buildAppBuilderHandlers(deps) {
57394
57550
  const project = await userStore.create(f.name, reservedPorts);
57395
57551
  try {
57396
57552
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
57397
- const templateSrcDir = (0, import_node_path52.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57398
- const scaffoldScript = (0, import_node_path52.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57553
+ const templateSrcDir = (0, import_node_path55.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57554
+ const scaffoldScript = (0, import_node_path55.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57399
57555
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
57400
57556
  deps.logger?.info("app-builder.scaffold.done", {
57401
57557
  name: project.name,
@@ -57616,7 +57772,7 @@ function buildAppBuilderHandlers(deps) {
57616
57772
  await userStore.clearPublishJob(args.name);
57617
57773
  }
57618
57774
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
57619
- const scriptPath = (0, import_node_path52.join)(deps.deployKitRoot, "scripts", "publish.sh");
57775
+ const scriptPath = (0, import_node_path55.join)(deps.deployKitRoot, "scripts", "publish.sh");
57620
57776
  deps.logger?.info("app-builder.publish.start", {
57621
57777
  name: args.name,
57622
57778
  sessionId: boundSession.sessionId,
@@ -57792,7 +57948,7 @@ function buildVisitorHandlers(deps) {
57792
57948
 
57793
57949
  // src/extension/registry.ts
57794
57950
  var import_promises10 = __toESM(require("fs/promises"), 1);
57795
- var import_node_path53 = __toESM(require("path"), 1);
57951
+ var import_node_path56 = __toESM(require("path"), 1);
57796
57952
  async function loadAll(root) {
57797
57953
  let entries;
57798
57954
  try {
@@ -57805,13 +57961,13 @@ async function loadAll(root) {
57805
57961
  for (const ent of entries) {
57806
57962
  if (!ent.isDirectory()) continue;
57807
57963
  if (ent.name.startsWith(".")) continue;
57808
- records.push(await loadOne(import_node_path53.default.join(root, ent.name), ent.name));
57964
+ records.push(await loadOne(import_node_path56.default.join(root, ent.name), ent.name));
57809
57965
  }
57810
57966
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
57811
57967
  return records;
57812
57968
  }
57813
57969
  async function loadOne(dir, dirName) {
57814
- const manifestPath = import_node_path53.default.join(dir, "manifest.json");
57970
+ const manifestPath = import_node_path56.default.join(dir, "manifest.json");
57815
57971
  let raw;
57816
57972
  try {
57817
57973
  raw = await import_promises10.default.readFile(manifestPath, "utf8");
@@ -57856,7 +58012,7 @@ async function loadOne(dir, dirName) {
57856
58012
 
57857
58013
  // src/extension/uninstall.ts
57858
58014
  var import_promises11 = __toESM(require("fs/promises"), 1);
57859
- var import_node_path54 = __toESM(require("path"), 1);
58015
+ var import_node_path57 = __toESM(require("path"), 1);
57860
58016
  var UninstallError = class extends Error {
57861
58017
  constructor(code, message) {
57862
58018
  super(message);
@@ -57865,7 +58021,7 @@ var UninstallError = class extends Error {
57865
58021
  code;
57866
58022
  };
57867
58023
  async function uninstall(deps) {
57868
- const dir = import_node_path54.default.join(deps.root, deps.extId);
58024
+ const dir = import_node_path57.default.join(deps.root, deps.extId);
57869
58025
  try {
57870
58026
  await import_promises11.default.access(dir);
57871
58027
  } catch {
@@ -57882,7 +58038,7 @@ var import_node_crypto18 = require("crypto");
57882
58038
  init_protocol();
57883
58039
 
57884
58040
  // src/peer-ops/run-command.ts
57885
- var import_node_child_process14 = require("child_process");
58041
+ var import_node_child_process15 = require("child_process");
57886
58042
  var import_node_os21 = __toESM(require("os"), 1);
57887
58043
  var DEFAULT_TIMEOUT_MS5 = 3e4;
57888
58044
  var MAX_TIMEOUT_MS = 3e5;
@@ -57890,7 +58046,7 @@ var MAX_OUTPUT_BYTES = 1048576;
57890
58046
  function runCommand(command, opts = {}) {
57891
58047
  const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
57892
58048
  return new Promise((resolve6) => {
57893
- const child = (0, import_node_child_process14.spawn)("bash", ["-c", command], { cwd: import_node_os21.default.homedir() });
58049
+ const child = (0, import_node_child_process15.spawn)("bash", ["-c", command], { cwd: import_node_os21.default.homedir() });
57894
58050
  const out = [];
57895
58051
  const err = [];
57896
58052
  let outBytes = 0;
@@ -58104,7 +58260,7 @@ function buildMethodHandlers(deps) {
58104
58260
  }
58105
58261
 
58106
58262
  // src/app-builder/dev-server-supervisor.ts
58107
- var import_node_child_process15 = require("child_process");
58263
+ var import_node_child_process16 = require("child_process");
58108
58264
  var import_node_events2 = require("events");
58109
58265
  var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
58110
58266
  var DevServerSupervisor = class extends import_node_events2.EventEmitter {
@@ -58141,7 +58297,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
58141
58297
  tunnelHost: args.tunnelHost,
58142
58298
  devCommand: cmd
58143
58299
  });
58144
- const child = (0, import_node_child_process15.spawn)("sh", ["-c", cmd], {
58300
+ const child = (0, import_node_child_process16.spawn)("sh", ["-c", cmd], {
58145
58301
  cwd: args.cwd,
58146
58302
  env,
58147
58303
  stdio: "pipe",
@@ -58584,8 +58740,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58584
58740
  }
58585
58741
 
58586
58742
  // src/extension/runtime.ts
58587
- var import_node_child_process16 = require("child_process");
58588
- var import_node_path55 = __toESM(require("path"), 1);
58743
+ var import_node_child_process17 = require("child_process");
58744
+ var import_node_path58 = __toESM(require("path"), 1);
58589
58745
  var import_promises12 = require("timers/promises");
58590
58746
 
58591
58747
  // src/extension/port-allocator.ts
@@ -58686,13 +58842,13 @@ var Runtime = class {
58686
58842
  /\$CLAWOS_EXT_PORT/g,
58687
58843
  String(port)
58688
58844
  );
58689
- const dir = import_node_path55.default.join(this.root, extId);
58845
+ const dir = import_node_path58.default.join(this.root, extId);
58690
58846
  const env = {
58691
58847
  ...process.env,
58692
58848
  CLAWOS_EXT_PORT: String(port),
58693
58849
  CLAWOS_EXT_ID: extId
58694
58850
  };
58695
- const child = (0, import_node_child_process16.spawn)("sh", ["-c", cmd], {
58851
+ const child = (0, import_node_child_process17.spawn)("sh", ["-c", cmd], {
58696
58852
  cwd: dir,
58697
58853
  env,
58698
58854
  stdio: ["ignore", "pipe", "pipe"],
@@ -58798,7 +58954,7 @@ ${handle.stderrTail}`
58798
58954
 
58799
58955
  // src/extension/published-channels.ts
58800
58956
  var import_promises13 = __toESM(require("fs/promises"), 1);
58801
- var import_node_path56 = __toESM(require("path"), 1);
58957
+ var import_node_path59 = __toESM(require("path"), 1);
58802
58958
  init_zod();
58803
58959
  var PublishedChannelsError = class extends Error {
58804
58960
  constructor(code, message) {
@@ -58897,7 +59053,7 @@ var PublishedChannelStore = class {
58897
59053
  )
58898
59054
  };
58899
59055
  const tmp = `${this.filePath}.tmp`;
58900
- await import_promises13.default.mkdir(import_node_path56.default.dirname(this.filePath), { recursive: true });
59056
+ await import_promises13.default.mkdir(import_node_path59.default.dirname(this.filePath), { recursive: true });
58901
59057
  await import_promises13.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
58902
59058
  await import_promises13.default.rename(tmp, this.filePath);
58903
59059
  }
@@ -58905,7 +59061,7 @@ var PublishedChannelStore = class {
58905
59061
 
58906
59062
  // src/extension/bundle-cache.ts
58907
59063
  var import_promises14 = __toESM(require("fs/promises"), 1);
58908
- var import_node_path57 = __toESM(require("path"), 1);
59064
+ var import_node_path60 = __toESM(require("path"), 1);
58909
59065
  var BundleCache = class {
58910
59066
  constructor(rootDir) {
58911
59067
  this.rootDir = rootDir;
@@ -58914,14 +59070,14 @@ var BundleCache = class {
58914
59070
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
58915
59071
  async write(snapshotHash, buffer) {
58916
59072
  await import_promises14.default.mkdir(this.rootDir, { recursive: true });
58917
- const file = import_node_path57.default.join(this.rootDir, `${snapshotHash}.zip`);
59073
+ const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
58918
59074
  const tmp = `${file}.tmp`;
58919
59075
  await import_promises14.default.writeFile(tmp, buffer, { mode: 384 });
58920
59076
  await import_promises14.default.rename(tmp, file);
58921
59077
  }
58922
59078
  /** Returns the bundle bytes, or null when the file doesn't exist. */
58923
59079
  async read(snapshotHash) {
58924
- const file = import_node_path57.default.join(this.rootDir, `${snapshotHash}.zip`);
59080
+ const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
58925
59081
  try {
58926
59082
  return await import_promises14.default.readFile(file);
58927
59083
  } catch (e) {
@@ -58931,7 +59087,7 @@ var BundleCache = class {
58931
59087
  }
58932
59088
  /** Idempotent — missing file is not an error. */
58933
59089
  async delete(snapshotHash) {
58934
- const file = import_node_path57.default.join(this.rootDir, `${snapshotHash}.zip`);
59090
+ const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
58935
59091
  await import_promises14.default.rm(file, { force: true });
58936
59092
  }
58937
59093
  };
@@ -58954,24 +59110,24 @@ async function startDaemon(config) {
58954
59110
  sampling: logShippingCfg.sampling,
58955
59111
  homeDir: import_node_os22.default.homedir()
58956
59112
  });
58957
- const logDir = import_node_path58.default.join(config.dataDir, "log");
58958
- import_node_fs45.default.mkdirSync(logDir, { recursive: true });
59113
+ const logDir = import_node_path61.default.join(config.dataDir, "log");
59114
+ import_node_fs46.default.mkdirSync(logDir, { recursive: true });
58959
59115
  const logger = createLogger({
58960
59116
  level: config.logLevel,
58961
- file: import_node_path58.default.join(logDir, "clawd.log"),
59117
+ file: import_node_path61.default.join(logDir, "clawd.log"),
58962
59118
  logClient
58963
59119
  });
58964
59120
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
58965
59121
  const screenIdleProbeLogger = createFileOnlyLogger({
58966
- file: import_node_path58.default.join(logDir, "screen-idle-probe.log"),
59122
+ file: import_node_path61.default.join(logDir, "screen-idle-probe.log"),
58967
59123
  level: "debug"
58968
59124
  });
58969
59125
  logger.info("screen-idle probe logger enabled", {
58970
- file: import_node_path58.default.join(logDir, "screen-idle-probe.log")
59126
+ file: import_node_path61.default.join(logDir, "screen-idle-probe.log")
58971
59127
  });
58972
59128
  const CAP_TARGETS = [
58973
- import_node_path58.default.join(logDir, "clawd.log"),
58974
- import_node_path58.default.join(logDir, "screen-idle-probe.log")
59129
+ import_node_path61.default.join(logDir, "clawd.log"),
59130
+ import_node_path61.default.join(logDir, "screen-idle-probe.log")
58975
59131
  ];
58976
59132
  const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
58977
59133
  const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
@@ -59125,8 +59281,8 @@ async function startDaemon(config) {
59125
59281
  const agents = new AgentsScanner();
59126
59282
  const history = new ClaudeHistoryReader();
59127
59283
  let transport = null;
59128
- const personaStore = new PersonaStore(import_node_path58.default.join(config.dataDir, "personas"));
59129
- const usersRoot = import_node_path58.default.join(config.dataDir, "users");
59284
+ const personaStore = new PersonaStore(import_node_path61.default.join(config.dataDir, "personas"));
59285
+ const usersRoot = import_node_path61.default.join(config.dataDir, "users");
59130
59286
  const defaultsRoot = findDefaultsRoot(logger);
59131
59287
  if (defaultsRoot) {
59132
59288
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -59146,7 +59302,7 @@ async function startDaemon(config) {
59146
59302
  migrateCodexSandbox({ store: personaStore, logger });
59147
59303
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
59148
59304
  const dispatchStore = createDispatchStore({
59149
- filePath: import_node_path58.default.join(config.dataDir, "dispatch.json"),
59305
+ filePath: import_node_path61.default.join(config.dataDir, "dispatch.json"),
59150
59306
  now: () => Date.now(),
59151
59307
  onFlushError: (err) => logger.error("dispatch store flush failed", {
59152
59308
  reason: err instanceof Error ? err.message : String(err)
@@ -59161,17 +59317,17 @@ async function startDaemon(config) {
59161
59317
  now: () => Date.now(),
59162
59318
  onCompleted: (sid) => deliverPendingRef?.(sid)
59163
59319
  });
59164
- const here = typeof __dirname === "string" ? __dirname : import_node_path58.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59320
+ const here = typeof __dirname === "string" ? __dirname : import_node_path61.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59165
59321
  const mcpConfigs = [];
59166
59322
  const dispatchServerCandidates = [
59167
- import_node_path58.default.join(here, "dispatch", "mcp-server.cjs"),
59323
+ import_node_path61.default.join(here, "dispatch", "mcp-server.cjs"),
59168
59324
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
59169
- import_node_path58.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59325
+ import_node_path61.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59170
59326
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59171
59327
  ];
59172
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs45.default.existsSync(p2));
59328
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
59173
59329
  if (dispatchServerScriptPath) {
59174
- const dispatchLogPath = import_node_path58.default.join(logDir, "dispatch-mcp-server.log");
59330
+ const dispatchLogPath = import_node_path61.default.join(logDir, "dispatch-mcp-server.log");
59175
59331
  const dispatchCfgPath = writeDispatchMcpConfig({
59176
59332
  dataDir: config.dataDir,
59177
59333
  serverScriptPath: dispatchServerScriptPath,
@@ -59189,12 +59345,12 @@ async function startDaemon(config) {
59189
59345
  });
59190
59346
  }
59191
59347
  const ticketServerCandidates = [
59192
- import_node_path58.default.join(here, "ticket", "mcp-server.cjs"),
59193
- import_node_path58.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59348
+ import_node_path61.default.join(here, "ticket", "mcp-server.cjs"),
59349
+ import_node_path61.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59194
59350
  ];
59195
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs45.default.existsSync(p2));
59351
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
59196
59352
  if (ticketServerScriptPath) {
59197
- const ticketLogPath = import_node_path58.default.join(logDir, "ticket-mcp-server.log");
59353
+ const ticketLogPath = import_node_path61.default.join(logDir, "ticket-mcp-server.log");
59198
59354
  const ticketCfgPath = writeTicketMcpConfig({
59199
59355
  dataDir: config.dataDir,
59200
59356
  serverScriptPath: ticketServerScriptPath,
@@ -59214,12 +59370,12 @@ async function startDaemon(config) {
59214
59370
  });
59215
59371
  }
59216
59372
  const shiftServerCandidates = [
59217
- import_node_path58.default.join(here, "shift", "mcp-server.cjs"),
59218
- import_node_path58.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59373
+ import_node_path61.default.join(here, "shift", "mcp-server.cjs"),
59374
+ import_node_path61.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59219
59375
  ];
59220
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs45.default.existsSync(p2));
59376
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
59221
59377
  if (shiftServerScriptPath) {
59222
- const shiftLogPath = import_node_path58.default.join(logDir, "shift-mcp-server.log");
59378
+ const shiftLogPath = import_node_path61.default.join(logDir, "shift-mcp-server.log");
59223
59379
  const shiftCfgPath = await writeShiftMcpConfig({
59224
59380
  dataDir: config.dataDir,
59225
59381
  serverScriptPath: shiftServerScriptPath,
@@ -59238,12 +59394,12 @@ async function startDaemon(config) {
59238
59394
  );
59239
59395
  }
59240
59396
  const inboxServerCandidates = [
59241
- import_node_path58.default.join(here, "inbox", "mcp-server.cjs"),
59242
- import_node_path58.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59397
+ import_node_path61.default.join(here, "inbox", "mcp-server.cjs"),
59398
+ import_node_path61.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59243
59399
  ];
59244
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs45.default.existsSync(p2));
59400
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
59245
59401
  if (inboxServerScriptPath) {
59246
- const inboxLogPath = import_node_path58.default.join(logDir, "inbox-mcp-server.log");
59402
+ const inboxLogPath = import_node_path61.default.join(logDir, "inbox-mcp-server.log");
59247
59403
  const inboxCfgPath = await writeInboxMcpConfig({
59248
59404
  dataDir: config.dataDir,
59249
59405
  serverScriptPath: inboxServerScriptPath,
@@ -59262,10 +59418,10 @@ async function startDaemon(config) {
59262
59418
  );
59263
59419
  }
59264
59420
  const peerOpsServerCandidates = [
59265
- import_node_path58.default.join(here, "peer-ops", "mcp-server.cjs"),
59266
- import_node_path58.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
59421
+ import_node_path61.default.join(here, "peer-ops", "mcp-server.cjs"),
59422
+ import_node_path61.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
59267
59423
  ];
59268
- const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs45.default.existsSync(p2));
59424
+ const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
59269
59425
  if (peerOpsServerScriptPath) {
59270
59426
  const peerOpsCfgPath = writePeerOpsMcpConfig({
59271
59427
  dataDir: config.dataDir,
@@ -59283,7 +59439,7 @@ async function startDaemon(config) {
59283
59439
  );
59284
59440
  }
59285
59441
  const shiftStore = createShiftStore({
59286
- filePath: import_node_path58.default.join(config.dataDir, "shift.json"),
59442
+ filePath: import_node_path61.default.join(config.dataDir, "shift.json"),
59287
59443
  ownerIdProvider: () => ownerPrincipalId,
59288
59444
  now: () => Date.now()
59289
59445
  });
@@ -59305,7 +59461,10 @@ async function startDaemon(config) {
59305
59461
  getAdapter,
59306
59462
  historyReader: history,
59307
59463
  dataDir: config.dataDir,
59308
- personaRoot: import_node_path58.default.join(config.dataDir, "personas"),
59464
+ personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
59465
+ // dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
59466
+ // personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
59467
+ getPersonaTool: (personaId) => personaRegistry.get(personaId)?.tool,
59309
59468
  usersRoot,
59310
59469
  personaStore,
59311
59470
  ownerDisplayName,
@@ -59345,10 +59504,10 @@ async function startDaemon(config) {
59345
59504
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
59346
59505
  attachmentGroup: {
59347
59506
  onFileEdit: (input) => {
59348
- const absPath = import_node_path58.default.isAbsolute(input.relPath) ? input.relPath : import_node_path58.default.join(input.cwd, input.relPath);
59507
+ const absPath = import_node_path61.default.isAbsolute(input.relPath) ? input.relPath : import_node_path61.default.join(input.cwd, input.relPath);
59349
59508
  let size = 0;
59350
59509
  try {
59351
- size = import_node_fs45.default.statSync(absPath).size;
59510
+ size = import_node_fs46.default.statSync(absPath).size;
59352
59511
  } catch (err) {
59353
59512
  logger.warn("attachment.onFileEdit stat failed", {
59354
59513
  sessionId: input.sessionId,
@@ -59431,6 +59590,7 @@ async function startDaemon(config) {
59431
59590
  }) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
59432
59591
  registerAdapter("claude", claudeAdapter);
59433
59592
  registerAdapter("codex", new CodexAdapter({ logger, historyReader: new CodexHistoryReader() }));
59593
+ warmCodexFeatureCache();
59434
59594
  const personaRegistry = new PersonaRegistry(personaStore);
59435
59595
  const personaManager = new PersonaManager({
59436
59596
  store: personaStore,
@@ -59578,11 +59738,11 @@ async function startDaemon(config) {
59578
59738
  // 'persona/<pid>/owner',default 走 'default'。
59579
59739
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
59580
59740
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
59581
- personaRoot: import_node_path58.default.join(config.dataDir, "personas"),
59741
+ personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
59582
59742
  usersRoot
59583
59743
  },
59584
59744
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
59585
- personaRoot: import_node_path58.default.join(config.dataDir, "personas"),
59745
+ personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
59586
59746
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
59587
59747
  usersRoot,
59588
59748
  // capability:list / delete handler 依赖
@@ -59693,11 +59853,11 @@ async function startDaemon(config) {
59693
59853
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
59694
59854
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
59695
59855
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
59696
- appBuilderPersonaRoot: import_node_path58.default.join(config.dataDir, "personas", "persona-app-builder"),
59856
+ appBuilderPersonaRoot: import_node_path61.default.join(config.dataDir, "personas", "persona-app-builder"),
59697
59857
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
59698
- deployKitRoot: import_node_path58.default.join(config.dataDir, "deploy-kit"),
59858
+ deployKitRoot: import_node_path61.default.join(config.dataDir, "deploy-kit"),
59699
59859
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
59700
- resolvePersonaRoot: (personaId) => import_node_path58.default.join(config.dataDir, "personas", personaId),
59860
+ resolvePersonaRoot: (personaId) => import_node_path61.default.join(config.dataDir, "personas", personaId),
59701
59861
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
59702
59862
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
59703
59863
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -59743,7 +59903,7 @@ async function startDaemon(config) {
59743
59903
  }
59744
59904
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
59745
59905
  if (sourceFile && sourceFile.toolSessionId) {
59746
- sourceJsonlPath = import_node_path58.default.join(
59906
+ sourceJsonlPath = import_node_path61.default.join(
59747
59907
  import_node_os22.default.homedir(),
59748
59908
  ".claude",
59749
59909
  "projects",
@@ -59789,7 +59949,9 @@ async function startDaemon(config) {
59789
59949
  });
59790
59950
  },
59791
59951
  // B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。
59792
- getPersonaPublic: (personaId) => personaRegistry.get(personaId)?.public ?? false
59952
+ getPersonaPublic: (personaId) => personaRegistry.get(personaId)?.public ?? false,
59953
+ // model 校验按 target persona 绑定 tool 选表(claude / codex 模型集不同)
59954
+ getPersonaTool: (personaId) => personaRegistry.get(personaId)?.tool
59793
59955
  });
59794
59956
  handlers = { ...handlers, ...dispatchHandlers };
59795
59957
  const shiftHandlers = buildShiftInternalHandlers({
@@ -60061,8 +60223,8 @@ async function startDaemon(config) {
60061
60223
  const lines = [
60062
60224
  `Tunnel: ${r.url}`,
60063
60225
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
60064
- `Frpc config: ${import_node_path58.default.join(config.dataDir, "frpc.toml")}`,
60065
- `Frpc log: ${import_node_path58.default.join(logDir, "frpc.log")}`
60226
+ `Frpc config: ${import_node_path61.default.join(config.dataDir, "frpc.toml")}`,
60227
+ `Frpc log: ${import_node_path61.default.join(logDir, "frpc.log")}`
60066
60228
  ];
60067
60229
  const width = Math.max(...lines.map((l) => l.length));
60068
60230
  const bar = "\u2550".repeat(width + 4);
@@ -60075,8 +60237,8 @@ ${bar}
60075
60237
 
60076
60238
  `);
60077
60239
  try {
60078
- const connectPath = import_node_path58.default.join(config.dataDir, "connect.txt");
60079
- import_node_fs45.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60240
+ const connectPath = import_node_path61.default.join(config.dataDir, "connect.txt");
60241
+ import_node_fs46.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60080
60242
  } catch {
60081
60243
  }
60082
60244
  } catch (err) {
@@ -60148,9 +60310,9 @@ ${bar}
60148
60310
  };
60149
60311
  }
60150
60312
  function migrateDropPersonsDir(dataDir) {
60151
- const dir = import_node_path58.default.join(dataDir, "persons");
60313
+ const dir = import_node_path61.default.join(dataDir, "persons");
60152
60314
  try {
60153
- import_node_fs45.default.rmSync(dir, { recursive: true, force: true });
60315
+ import_node_fs46.default.rmSync(dir, { recursive: true, force: true });
60154
60316
  } catch {
60155
60317
  }
60156
60318
  }