@clawos-dev/clawd 0.2.64-beta.104.6f4b611 → 0.2.64-beta.106.42f5a70

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.cjs +252 -499
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -617,8 +617,8 @@ var init_parseUtil = __esm({
617
617
  init_errors2();
618
618
  init_en();
619
619
  makeIssue = (params) => {
620
- const { data, path: path34, errorMaps, issueData } = params;
621
- const fullPath = [...path34, ...issueData.path || []];
620
+ const { data, path: path33, errorMaps, issueData } = params;
621
+ const fullPath = [...path33, ...issueData.path || []];
622
622
  const fullIssue = {
623
623
  ...issueData,
624
624
  path: fullPath
@@ -929,11 +929,11 @@ var init_types = __esm({
929
929
  init_parseUtil();
930
930
  init_util();
931
931
  ParseInputLazyPath = class {
932
- constructor(parent, value, path34, key) {
932
+ constructor(parent, value, path33, key) {
933
933
  this._cachedPath = [];
934
934
  this.parent = parent;
935
935
  this.data = value;
936
- this._path = path34;
936
+ this._path = path33;
937
937
  this._key = key;
938
938
  }
939
939
  get path() {
@@ -4323,7 +4323,7 @@ var init_attachment_schemas = __esm({
4323
4323
  "use strict";
4324
4324
  init_zod();
4325
4325
  TOKEN_ROLES = ["owner", "personal"];
4326
- GROUP_FILE_SOURCES = ["agent", "user", "owner"];
4326
+ GROUP_FILE_SOURCES = ["agent", "owner"];
4327
4327
  MOUNT_MODES = ["link", "copy"];
4328
4328
  GroupFileEntrySchema = external_exports.object({
4329
4329
  /** daemon 派发的稳定 id(用于 RPC remove / UI key) */
@@ -4331,8 +4331,6 @@ var init_attachment_schemas = __esm({
4331
4331
  /** 相对 personaDir / sessionCwd 的路径 */
4332
4332
  relPath: external_exports.string().min(1),
4333
4333
  from: external_exports.enum(GROUP_FILE_SOURCES),
4334
- /** user 上传时的客户端标识(personal label / hostname),from='user' 才有 */
4335
- addedBy: external_exports.string().optional(),
4336
4334
  /** owner 手动加群时的可选备注 */
4337
4335
  label: external_exports.string().optional(),
4338
4336
  /** 文件字节数(stat 时拍) */
@@ -4428,7 +4426,7 @@ var init_attachment_schemas = __esm({
4428
4426
  AttachmentGroupAddArgs = external_exports.object({
4429
4427
  sessionId: external_exports.string().min(1),
4430
4428
  relPath: external_exports.string().min(1),
4431
- /** owner 手动加群时可选备注;agent / inbox 自动入清单不走此 RPC */
4429
+ /** owner 手动加群时可选备注;agent 自动入清单不走此 RPC */
4432
4430
  label: external_exports.string().optional()
4433
4431
  });
4434
4432
  AttachmentGroupAddResponseSchema = external_exports.object({
@@ -5545,8 +5543,8 @@ var require_req = __commonJS({
5545
5543
  if (req.originalUrl) {
5546
5544
  _req.url = req.originalUrl;
5547
5545
  } else {
5548
- const path34 = req.path;
5549
- _req.url = typeof path34 === "string" ? path34 : req.url ? req.url.path || req.url : void 0;
5546
+ const path33 = req.path;
5547
+ _req.url = typeof path33 === "string" ? path33 : req.url ? req.url.path || req.url : void 0;
5550
5548
  }
5551
5549
  if (req.query) {
5552
5550
  _req.query = req.query;
@@ -5711,14 +5709,14 @@ var require_redact = __commonJS({
5711
5709
  }
5712
5710
  return obj;
5713
5711
  }
5714
- function parsePath(path34) {
5712
+ function parsePath(path33) {
5715
5713
  const parts = [];
5716
5714
  let current = "";
5717
5715
  let inBrackets = false;
5718
5716
  let inQuotes = false;
5719
5717
  let quoteChar = "";
5720
- for (let i = 0; i < path34.length; i++) {
5721
- const char = path34[i];
5718
+ for (let i = 0; i < path33.length; i++) {
5719
+ const char = path33[i];
5722
5720
  if (!inBrackets && char === ".") {
5723
5721
  if (current) {
5724
5722
  parts.push(current);
@@ -5849,10 +5847,10 @@ var require_redact = __commonJS({
5849
5847
  return current;
5850
5848
  }
5851
5849
  function redactPaths(obj, paths, censor, remove = false) {
5852
- for (const path34 of paths) {
5853
- const parts = parsePath(path34);
5850
+ for (const path33 of paths) {
5851
+ const parts = parsePath(path33);
5854
5852
  if (parts.includes("*")) {
5855
- redactWildcardPath(obj, parts, censor, path34, remove);
5853
+ redactWildcardPath(obj, parts, censor, path33, remove);
5856
5854
  } else {
5857
5855
  if (remove) {
5858
5856
  removeKey(obj, parts);
@@ -5937,8 +5935,8 @@ var require_redact = __commonJS({
5937
5935
  }
5938
5936
  } else {
5939
5937
  if (afterWildcard.includes("*")) {
5940
- const wrappedCensor = typeof censor === "function" ? (value, path34) => {
5941
- const fullPath = [...pathArray.slice(0, pathLength), ...path34];
5938
+ const wrappedCensor = typeof censor === "function" ? (value, path33) => {
5939
+ const fullPath = [...pathArray.slice(0, pathLength), ...path33];
5942
5940
  return censor(value, fullPath);
5943
5941
  } : censor;
5944
5942
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -5973,8 +5971,8 @@ var require_redact = __commonJS({
5973
5971
  return null;
5974
5972
  }
5975
5973
  const pathStructure = /* @__PURE__ */ new Map();
5976
- for (const path34 of pathsToClone) {
5977
- const parts = parsePath(path34);
5974
+ for (const path33 of pathsToClone) {
5975
+ const parts = parsePath(path33);
5978
5976
  let current = pathStructure;
5979
5977
  for (let i = 0; i < parts.length; i++) {
5980
5978
  const part = parts[i];
@@ -6026,24 +6024,24 @@ var require_redact = __commonJS({
6026
6024
  }
6027
6025
  return cloneSelectively(obj, pathStructure);
6028
6026
  }
6029
- function validatePath(path34) {
6030
- if (typeof path34 !== "string") {
6027
+ function validatePath(path33) {
6028
+ if (typeof path33 !== "string") {
6031
6029
  throw new Error("Paths must be (non-empty) strings");
6032
6030
  }
6033
- if (path34 === "") {
6031
+ if (path33 === "") {
6034
6032
  throw new Error("Invalid redaction path ()");
6035
6033
  }
6036
- if (path34.includes("..")) {
6037
- throw new Error(`Invalid redaction path (${path34})`);
6034
+ if (path33.includes("..")) {
6035
+ throw new Error(`Invalid redaction path (${path33})`);
6038
6036
  }
6039
- if (path34.includes(",")) {
6040
- throw new Error(`Invalid redaction path (${path34})`);
6037
+ if (path33.includes(",")) {
6038
+ throw new Error(`Invalid redaction path (${path33})`);
6041
6039
  }
6042
6040
  let bracketCount = 0;
6043
6041
  let inQuotes = false;
6044
6042
  let quoteChar = "";
6045
- for (let i = 0; i < path34.length; i++) {
6046
- const char = path34[i];
6043
+ for (let i = 0; i < path33.length; i++) {
6044
+ const char = path33[i];
6047
6045
  if ((char === '"' || char === "'") && bracketCount > 0) {
6048
6046
  if (!inQuotes) {
6049
6047
  inQuotes = true;
@@ -6057,20 +6055,20 @@ var require_redact = __commonJS({
6057
6055
  } else if (char === "]" && !inQuotes) {
6058
6056
  bracketCount--;
6059
6057
  if (bracketCount < 0) {
6060
- throw new Error(`Invalid redaction path (${path34})`);
6058
+ throw new Error(`Invalid redaction path (${path33})`);
6061
6059
  }
6062
6060
  }
6063
6061
  }
6064
6062
  if (bracketCount !== 0) {
6065
- throw new Error(`Invalid redaction path (${path34})`);
6063
+ throw new Error(`Invalid redaction path (${path33})`);
6066
6064
  }
6067
6065
  }
6068
6066
  function validatePaths(paths) {
6069
6067
  if (!Array.isArray(paths)) {
6070
6068
  throw new TypeError("paths must be an array");
6071
6069
  }
6072
- for (const path34 of paths) {
6073
- validatePath(path34);
6070
+ for (const path33 of paths) {
6071
+ validatePath(path33);
6074
6072
  }
6075
6073
  }
6076
6074
  function slowRedact(options = {}) {
@@ -6238,8 +6236,8 @@ var require_redaction = __commonJS({
6238
6236
  if (shape[k2] === null) {
6239
6237
  o[k2] = (value) => topCensor(value, [k2]);
6240
6238
  } else {
6241
- const wrappedCensor = typeof censor === "function" ? (value, path34) => {
6242
- return censor(value, [k2, ...path34]);
6239
+ const wrappedCensor = typeof censor === "function" ? (value, path33) => {
6240
+ return censor(value, [k2, ...path33]);
6243
6241
  } : censor;
6244
6242
  o[k2] = Redact({
6245
6243
  paths: shape[k2],
@@ -6457,10 +6455,10 @@ var require_atomic_sleep = __commonJS({
6457
6455
  var require_sonic_boom = __commonJS({
6458
6456
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6459
6457
  "use strict";
6460
- var fs31 = require("fs");
6458
+ var fs30 = require("fs");
6461
6459
  var EventEmitter2 = require("events");
6462
6460
  var inherits = require("util").inherits;
6463
- var path34 = require("path");
6461
+ var path33 = require("path");
6464
6462
  var sleep = require_atomic_sleep();
6465
6463
  var assert = require("assert");
6466
6464
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6514,20 +6512,20 @@ var require_sonic_boom = __commonJS({
6514
6512
  const mode = sonic.mode;
6515
6513
  if (sonic.sync) {
6516
6514
  try {
6517
- if (sonic.mkdir) fs31.mkdirSync(path34.dirname(file), { recursive: true });
6518
- const fd = fs31.openSync(file, flags, mode);
6515
+ if (sonic.mkdir) fs30.mkdirSync(path33.dirname(file), { recursive: true });
6516
+ const fd = fs30.openSync(file, flags, mode);
6519
6517
  fileOpened(null, fd);
6520
6518
  } catch (err) {
6521
6519
  fileOpened(err);
6522
6520
  throw err;
6523
6521
  }
6524
6522
  } else if (sonic.mkdir) {
6525
- fs31.mkdir(path34.dirname(file), { recursive: true }, (err) => {
6523
+ fs30.mkdir(path33.dirname(file), { recursive: true }, (err) => {
6526
6524
  if (err) return fileOpened(err);
6527
- fs31.open(file, flags, mode, fileOpened);
6525
+ fs30.open(file, flags, mode, fileOpened);
6528
6526
  });
6529
6527
  } else {
6530
- fs31.open(file, flags, mode, fileOpened);
6528
+ fs30.open(file, flags, mode, fileOpened);
6531
6529
  }
6532
6530
  }
6533
6531
  function SonicBoom(opts) {
@@ -6568,8 +6566,8 @@ var require_sonic_boom = __commonJS({
6568
6566
  this.flush = flushBuffer;
6569
6567
  this.flushSync = flushBufferSync;
6570
6568
  this._actualWrite = actualWriteBuffer;
6571
- fsWriteSync = () => fs31.writeSync(this.fd, this._writingBuf);
6572
- fsWrite = () => fs31.write(this.fd, this._writingBuf, this.release);
6569
+ fsWriteSync = () => fs30.writeSync(this.fd, this._writingBuf);
6570
+ fsWrite = () => fs30.write(this.fd, this._writingBuf, this.release);
6573
6571
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6574
6572
  this._writingBuf = "";
6575
6573
  this.write = write;
@@ -6578,15 +6576,15 @@ var require_sonic_boom = __commonJS({
6578
6576
  this._actualWrite = actualWrite;
6579
6577
  fsWriteSync = () => {
6580
6578
  if (Buffer.isBuffer(this._writingBuf)) {
6581
- return fs31.writeSync(this.fd, this._writingBuf);
6579
+ return fs30.writeSync(this.fd, this._writingBuf);
6582
6580
  }
6583
- return fs31.writeSync(this.fd, this._writingBuf, "utf8");
6581
+ return fs30.writeSync(this.fd, this._writingBuf, "utf8");
6584
6582
  };
6585
6583
  fsWrite = () => {
6586
6584
  if (Buffer.isBuffer(this._writingBuf)) {
6587
- return fs31.write(this.fd, this._writingBuf, this.release);
6585
+ return fs30.write(this.fd, this._writingBuf, this.release);
6588
6586
  }
6589
- return fs31.write(this.fd, this._writingBuf, "utf8", this.release);
6587
+ return fs30.write(this.fd, this._writingBuf, "utf8", this.release);
6590
6588
  };
6591
6589
  } else {
6592
6590
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6643,7 +6641,7 @@ var require_sonic_boom = __commonJS({
6643
6641
  }
6644
6642
  }
6645
6643
  if (this._fsync) {
6646
- fs31.fsyncSync(this.fd);
6644
+ fs30.fsyncSync(this.fd);
6647
6645
  }
6648
6646
  const len = this._len;
6649
6647
  if (this._reopening) {
@@ -6757,7 +6755,7 @@ var require_sonic_boom = __commonJS({
6757
6755
  const onDrain = () => {
6758
6756
  if (!this._fsync) {
6759
6757
  try {
6760
- fs31.fsync(this.fd, (err) => {
6758
+ fs30.fsync(this.fd, (err) => {
6761
6759
  this._flushPending = false;
6762
6760
  cb(err);
6763
6761
  });
@@ -6859,7 +6857,7 @@ var require_sonic_boom = __commonJS({
6859
6857
  const fd = this.fd;
6860
6858
  this.once("ready", () => {
6861
6859
  if (fd !== this.fd) {
6862
- fs31.close(fd, (err) => {
6860
+ fs30.close(fd, (err) => {
6863
6861
  if (err) {
6864
6862
  return this.emit("error", err);
6865
6863
  }
@@ -6908,7 +6906,7 @@ var require_sonic_boom = __commonJS({
6908
6906
  buf = this._bufs[0];
6909
6907
  }
6910
6908
  try {
6911
- const n = Buffer.isBuffer(buf) ? fs31.writeSync(this.fd, buf) : fs31.writeSync(this.fd, buf, "utf8");
6909
+ const n = Buffer.isBuffer(buf) ? fs30.writeSync(this.fd, buf) : fs30.writeSync(this.fd, buf, "utf8");
6912
6910
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6913
6911
  buf = releasedBufObj.writingBuf;
6914
6912
  this._len = releasedBufObj.len;
@@ -6924,7 +6922,7 @@ var require_sonic_boom = __commonJS({
6924
6922
  }
6925
6923
  }
6926
6924
  try {
6927
- fs31.fsyncSync(this.fd);
6925
+ fs30.fsyncSync(this.fd);
6928
6926
  } catch {
6929
6927
  }
6930
6928
  }
@@ -6945,7 +6943,7 @@ var require_sonic_boom = __commonJS({
6945
6943
  buf = mergeBuf(this._bufs[0], this._lens[0]);
6946
6944
  }
6947
6945
  try {
6948
- const n = fs31.writeSync(this.fd, buf);
6946
+ const n = fs30.writeSync(this.fd, buf);
6949
6947
  buf = buf.subarray(n);
6950
6948
  this._len = Math.max(this._len - n, 0);
6951
6949
  if (buf.length <= 0) {
@@ -6973,13 +6971,13 @@ var require_sonic_boom = __commonJS({
6973
6971
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
6974
6972
  if (this.sync) {
6975
6973
  try {
6976
- const written = Buffer.isBuffer(this._writingBuf) ? fs31.writeSync(this.fd, this._writingBuf) : fs31.writeSync(this.fd, this._writingBuf, "utf8");
6974
+ const written = Buffer.isBuffer(this._writingBuf) ? fs30.writeSync(this.fd, this._writingBuf) : fs30.writeSync(this.fd, this._writingBuf, "utf8");
6977
6975
  release(null, written);
6978
6976
  } catch (err) {
6979
6977
  release(err);
6980
6978
  }
6981
6979
  } else {
6982
- fs31.write(this.fd, this._writingBuf, release);
6980
+ fs30.write(this.fd, this._writingBuf, release);
6983
6981
  }
6984
6982
  }
6985
6983
  function actualWriteBuffer() {
@@ -6988,7 +6986,7 @@ var require_sonic_boom = __commonJS({
6988
6986
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
6989
6987
  if (this.sync) {
6990
6988
  try {
6991
- const written = fs31.writeSync(this.fd, this._writingBuf);
6989
+ const written = fs30.writeSync(this.fd, this._writingBuf);
6992
6990
  release(null, written);
6993
6991
  } catch (err) {
6994
6992
  release(err);
@@ -6997,7 +6995,7 @@ var require_sonic_boom = __commonJS({
6997
6995
  if (kCopyBuffer) {
6998
6996
  this._writingBuf = Buffer.from(this._writingBuf);
6999
6997
  }
7000
- fs31.write(this.fd, this._writingBuf, release);
6998
+ fs30.write(this.fd, this._writingBuf, release);
7001
6999
  }
7002
7000
  }
7003
7001
  function actualClose(sonic) {
@@ -7013,12 +7011,12 @@ var require_sonic_boom = __commonJS({
7013
7011
  sonic._lens = [];
7014
7012
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7015
7013
  try {
7016
- fs31.fsync(sonic.fd, closeWrapped);
7014
+ fs30.fsync(sonic.fd, closeWrapped);
7017
7015
  } catch {
7018
7016
  }
7019
7017
  function closeWrapped() {
7020
7018
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7021
- fs31.close(sonic.fd, done);
7019
+ fs30.close(sonic.fd, done);
7022
7020
  } else {
7023
7021
  done();
7024
7022
  }
@@ -10153,11 +10151,11 @@ var init_lib = __esm({
10153
10151
  }
10154
10152
  }
10155
10153
  },
10156
- addToPath: function addToPath(path34, added, removed, oldPosInc, options) {
10157
- var last = path34.lastComponent;
10154
+ addToPath: function addToPath(path33, added, removed, oldPosInc, options) {
10155
+ var last = path33.lastComponent;
10158
10156
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10159
10157
  return {
10160
- oldPos: path34.oldPos + oldPosInc,
10158
+ oldPos: path33.oldPos + oldPosInc,
10161
10159
  lastComponent: {
10162
10160
  count: last.count + 1,
10163
10161
  added,
@@ -10167,7 +10165,7 @@ var init_lib = __esm({
10167
10165
  };
10168
10166
  } else {
10169
10167
  return {
10170
- oldPos: path34.oldPos + oldPosInc,
10168
+ oldPos: path33.oldPos + oldPosInc,
10171
10169
  lastComponent: {
10172
10170
  count: 1,
10173
10171
  added,
@@ -10598,10 +10596,10 @@ function attachmentToHistoryMessage(o, ts) {
10598
10596
  const memories = raw.map((m2) => {
10599
10597
  if (!m2 || typeof m2 !== "object") return null;
10600
10598
  const rec = m2;
10601
- const path34 = typeof rec.path === "string" ? rec.path : null;
10599
+ const path33 = typeof rec.path === "string" ? rec.path : null;
10602
10600
  const content = typeof rec.content === "string" ? rec.content : null;
10603
- if (!path34 || content == null) return null;
10604
- const entry = { path: path34, content };
10601
+ if (!path33 || content == null) return null;
10602
+ const entry = { path: path33, content };
10605
10603
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10606
10604
  return entry;
10607
10605
  }).filter((m2) => m2 !== null);
@@ -11405,10 +11403,10 @@ function parseAttachment(obj) {
11405
11403
  const memories = raw.map((m2) => {
11406
11404
  if (!m2 || typeof m2 !== "object") return null;
11407
11405
  const rec = m2;
11408
- const path34 = typeof rec.path === "string" ? rec.path : null;
11406
+ const path33 = typeof rec.path === "string" ? rec.path : null;
11409
11407
  const content = typeof rec.content === "string" ? rec.content : null;
11410
- if (!path34 || content == null) return null;
11411
- const out = { path: path34, content };
11408
+ if (!path33 || content == null) return null;
11409
+ const out = { path: path33, content };
11412
11410
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11413
11411
  return out;
11414
11412
  }).filter((m2) => m2 !== null);
@@ -20322,7 +20320,7 @@ var require_websocket_server = __commonJS({
20322
20320
  // src/run-case/recorder.ts
20323
20321
  function startRunCaseRecorder(opts) {
20324
20322
  const now = opts.now ?? Date.now;
20325
- const dir = import_node_path30.default.dirname(opts.recordPath);
20323
+ const dir = import_node_path29.default.dirname(opts.recordPath);
20326
20324
  let stream = null;
20327
20325
  let closing = false;
20328
20326
  let closedSettled = false;
@@ -20336,8 +20334,8 @@ function startRunCaseRecorder(opts) {
20336
20334
  });
20337
20335
  const ensureStream = () => {
20338
20336
  if (stream) return stream;
20339
- import_node_fs28.default.mkdirSync(dir, { recursive: true });
20340
- stream = import_node_fs28.default.createWriteStream(opts.recordPath, { flags: "a" });
20337
+ import_node_fs27.default.mkdirSync(dir, { recursive: true });
20338
+ stream = import_node_fs27.default.createWriteStream(opts.recordPath, { flags: "a" });
20341
20339
  stream.on("close", () => closedResolve());
20342
20340
  return stream;
20343
20341
  };
@@ -20362,12 +20360,12 @@ function startRunCaseRecorder(opts) {
20362
20360
  };
20363
20361
  return { tap, close, closed };
20364
20362
  }
20365
- var import_node_fs28, import_node_path30;
20363
+ var import_node_fs27, import_node_path29;
20366
20364
  var init_recorder = __esm({
20367
20365
  "src/run-case/recorder.ts"() {
20368
20366
  "use strict";
20369
- import_node_fs28 = __toESM(require("fs"), 1);
20370
- import_node_path30 = __toESM(require("path"), 1);
20367
+ import_node_fs27 = __toESM(require("fs"), 1);
20368
+ import_node_path29 = __toESM(require("path"), 1);
20371
20369
  }
20372
20370
  });
20373
20371
 
@@ -20410,7 +20408,7 @@ var init_wire = __esm({
20410
20408
  // src/run-case/controller.ts
20411
20409
  async function runController(opts) {
20412
20410
  const now = opts.now ?? Date.now;
20413
- const cwd = opts.cwd ?? (0, import_node_fs29.mkdtempSync)(import_node_path31.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
20411
+ const cwd = opts.cwd ?? (0, import_node_fs28.mkdtempSync)(import_node_path30.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
20414
20412
  const ownsCwd = opts.cwd === void 0;
20415
20413
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
20416
20414
  const spawnCtx = { cwd };
@@ -20571,19 +20569,19 @@ async function runController(opts) {
20571
20569
  if (sigintHandler) process.off("SIGINT", sigintHandler);
20572
20570
  if (ownsCwd) {
20573
20571
  try {
20574
- (0, import_node_fs29.rmSync)(cwd, { recursive: true, force: true });
20572
+ (0, import_node_fs28.rmSync)(cwd, { recursive: true, force: true });
20575
20573
  } catch {
20576
20574
  }
20577
20575
  }
20578
20576
  return exitCode ?? 0;
20579
20577
  }
20580
- var import_node_fs29, import_node_os15, import_node_path31;
20578
+ var import_node_fs28, import_node_os15, import_node_path30;
20581
20579
  var init_controller = __esm({
20582
20580
  "src/run-case/controller.ts"() {
20583
20581
  "use strict";
20584
- import_node_fs29 = require("fs");
20582
+ import_node_fs28 = require("fs");
20585
20583
  import_node_os15 = __toESM(require("os"), 1);
20586
- import_node_path31 = __toESM(require("path"), 1);
20584
+ import_node_path30 = __toESM(require("path"), 1);
20587
20585
  init_claude();
20588
20586
  init_stdout_splitter();
20589
20587
  init_permission_stdio();
@@ -20815,8 +20813,8 @@ Env (advanced):
20815
20813
  `;
20816
20814
 
20817
20815
  // src/index.ts
20818
- var import_node_path29 = __toESM(require("path"), 1);
20819
- var import_node_fs27 = __toESM(require("fs"), 1);
20816
+ var import_node_path28 = __toESM(require("path"), 1);
20817
+ var import_node_fs26 = __toESM(require("fs"), 1);
20820
20818
 
20821
20819
  // src/logger.ts
20822
20820
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -26343,8 +26341,8 @@ function constantTimeEqual2(a, b2) {
26343
26341
  }
26344
26342
 
26345
26343
  // src/transport/http-router.ts
26346
- var import_node_fs15 = __toESM(require("fs"), 1);
26347
- var import_node_path17 = __toESM(require("path"), 1);
26344
+ var import_node_fs14 = __toESM(require("fs"), 1);
26345
+ var import_node_path16 = __toESM(require("path"), 1);
26348
26346
 
26349
26347
  // src/attachment/group.ts
26350
26348
  var import_node_fs13 = __toESM(require("fs"), 1);
@@ -26433,7 +26431,7 @@ var GroupFileStore = class {
26433
26431
  mime: input.mime,
26434
26432
  lastEditedAt: now,
26435
26433
  stale: false
26436
- // addedBy / label 不在 upsert 路径覆盖(owner +Add 走另一条路径)
26434
+ // label 不在 upsert 路径覆盖(owner +Add 走另一条路径)
26437
26435
  };
26438
26436
  entries[idx] = next;
26439
26437
  } else {
@@ -26441,12 +26439,11 @@ var GroupFileStore = class {
26441
26439
  id: `gf-${import_node_crypto4.default.randomBytes(6).toString("base64url")}`,
26442
26440
  relPath: input.relPath,
26443
26441
  from: input.from,
26444
- addedBy: input.addedBy,
26445
26442
  label: input.label,
26446
26443
  size: input.size,
26447
26444
  mime: input.mime,
26448
26445
  addedAt: now
26449
- // agent / inbox 第一次 upsert 时不写 lastEditedAt(语义上 = 首次"编辑" = addedAt)
26446
+ // agent 第一次 upsert 时不写 lastEditedAt(语义上 = 首次"编辑" = addedAt)
26450
26447
  };
26451
26448
  entries.push(next);
26452
26449
  }
@@ -26472,7 +26469,7 @@ var GroupFileStore = class {
26472
26469
  }
26473
26470
  /**
26474
26471
  * 真删一条群文件条目(用于 owner 撤销自己 +Add 的入群操作)。
26475
- * agent / inbox 自动入群的不应走这条 —— 用 markStale 表达"文件不在了"语义;
26472
+ * agent 自动入群的不应走这条 —— 用 markStale 表达"文件不在了"语义;
26476
26473
  * owner 手动加错了,应该能彻底从列表移除而不是留个 stale 占位。
26477
26474
  *
26478
26475
  * 返回值:true=命中并删除;false=relPath 不在群里。
@@ -26579,207 +26576,16 @@ function lookupMime(filePathOrName) {
26579
26576
  return EXT_TO_MIME[ext] ?? "application/octet-stream";
26580
26577
  }
26581
26578
 
26582
- // src/attachment/inbox.ts
26583
- var import_node_fs14 = __toESM(require("fs"), 1);
26584
- var import_node_path16 = __toESM(require("path"), 1);
26585
- var import_node_crypto5 = __toESM(require("crypto"), 1);
26586
- var DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
26587
- async function handlePersonaInbox(req, args, deps) {
26588
- const filename = readFilenameFromUrl(req.url);
26589
- if (!filename) throw httpErr(400, "INVALID_PARAM", "missing ?name= query");
26590
- const safeName = sanitizeFilename(filename);
26591
- const mime = lookupMime(safeName);
26592
- if (deps.isAllowedMime && !deps.isAllowedMime(mime)) {
26593
- throw httpErr(415, "UNSUPPORTED_MEDIA", `mime ${mime} not allowed`);
26594
- }
26595
- const inboxDir = import_node_path16.default.join(args.personaDir, "_inbox");
26596
- import_node_fs14.default.mkdirSync(inboxDir, { recursive: true });
26597
- const sha = import_node_crypto5.default.randomBytes(6).toString("hex");
26598
- const fileName = `${sha}-${safeName}`;
26599
- const absPath = import_node_path16.default.join(inboxDir, fileName);
26600
- const size = await streamBodyToFile(req, absPath, deps.maxBytes ?? DEFAULT_MAX_BYTES);
26601
- const relPath = `_inbox/${fileName}`;
26602
- deps.groupFileStore.upsert(args.scope, args.sessionId, {
26603
- relPath,
26604
- from: args.from,
26605
- addedBy: args.addedBy,
26606
- size,
26607
- mime
26608
- });
26609
- return { relPath, size, mime };
26610
- }
26611
- async function handleSessionInbox(req, args, deps) {
26612
- const filename = readFilenameFromUrl(req.url);
26613
- if (!filename) throw httpErr(400, "INVALID_PARAM", "missing ?name= query");
26614
- const safeName = sanitizeFilename(filename);
26615
- const mime = lookupMime(safeName);
26616
- if (deps.isAllowedMime && !deps.isAllowedMime(mime)) {
26617
- throw httpErr(415, "UNSUPPORTED_MEDIA", `mime ${mime} not allowed`);
26618
- }
26619
- const inboxDir = import_node_path16.default.join(args.sessionCwd, "_inbox");
26620
- import_node_fs14.default.mkdirSync(inboxDir, { recursive: true });
26621
- const sha = import_node_crypto5.default.randomBytes(6).toString("hex");
26622
- const fileName = `${sha}-${safeName}`;
26623
- const absPath = import_node_path16.default.join(inboxDir, fileName);
26624
- const size = await streamBodyToFile(req, absPath, deps.maxBytes ?? DEFAULT_MAX_BYTES);
26625
- const relPath = `_inbox/${fileName}`;
26626
- deps.groupFileStore.upsert(args.scope, args.sessionId, {
26627
- relPath,
26628
- from: "owner",
26629
- size,
26630
- mime
26631
- });
26632
- return { relPath, size, mime };
26633
- }
26634
- function streamBodyToFile(req, absPath, maxBytes) {
26635
- return new Promise((resolve2, reject) => {
26636
- let received = 0;
26637
- const tmp = `${absPath}.tmp-${process.pid}-${Date.now()}`;
26638
- const stream = import_node_fs14.default.createWriteStream(tmp, { mode: 384 });
26639
- req.on("data", (chunk) => {
26640
- received += chunk.length;
26641
- if (received > maxBytes) {
26642
- stream.destroy();
26643
- try {
26644
- import_node_fs14.default.unlinkSync(tmp);
26645
- } catch {
26646
- }
26647
- reject(httpErr(413, "TOO_LARGE", `upload exceeds ${maxBytes} bytes`));
26648
- req.destroy();
26649
- return;
26650
- }
26651
- stream.write(chunk);
26652
- });
26653
- req.on("end", () => {
26654
- stream.end();
26655
- stream.on("finish", () => {
26656
- try {
26657
- import_node_fs14.default.renameSync(tmp, absPath);
26658
- resolve2(received);
26659
- } catch (err) {
26660
- reject(err);
26661
- }
26662
- });
26663
- });
26664
- req.on("error", reject);
26665
- stream.on("error", reject);
26666
- });
26667
- }
26668
- function readFilenameFromUrl(rawUrl) {
26669
- if (!rawUrl) return null;
26670
- try {
26671
- const u = new URL(rawUrl, "http://placeholder");
26672
- return u.searchParams.get("name");
26673
- } catch {
26674
- return null;
26675
- }
26676
- }
26677
- function sanitizeFilename(name) {
26678
- const trimmed = name.replace(/[\x00-\x1f]/g, "").replace(/\//g, "_").replace(/\\/g, "_");
26679
- const dotsOnly = trimmed.replace(/^\.+/, (m2) => "_".repeat(m2.length));
26680
- if (!dotsOnly) return "unnamed";
26681
- return dotsOnly.slice(0, 200);
26682
- }
26683
- function httpErr(status, code, message) {
26684
- const err = new Error(message);
26685
- err.httpStatus = status;
26686
- err.code = code;
26687
- return err;
26688
- }
26689
- function isHttpError(err) {
26690
- return err instanceof Error && typeof err.httpStatus === "number" && typeof err.code === "string";
26691
- }
26692
- async function handleInboxRequest(req, res, ctxRouter, deps) {
26693
- const personaMatch = ctxRouter.pathname.match(/^\/persona\/([^/]+)\/inbox$/);
26694
- if (personaMatch && req.method === "POST") {
26695
- if (!deps.getPersonaDir || !deps.getPersonaScope) {
26696
- sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "inbox not wired" });
26697
- return true;
26698
- }
26699
- const pid = personaMatch[1];
26700
- const personaDir = deps.getPersonaDir(pid);
26701
- if (!personaDir) {
26702
- sendJson(res, 404, { code: "NOT_FOUND", message: `persona ${pid} not found` });
26703
- return true;
26704
- }
26705
- const sessionId = new URL(req.url ?? "", "http://placeholder").searchParams.get("session") || pid;
26706
- try {
26707
- const result = await handlePersonaInbox(
26708
- req,
26709
- {
26710
- personaId: pid,
26711
- personaDir,
26712
- sessionId,
26713
- scope: deps.getPersonaScope(pid),
26714
- addedBy: deps.addedBy,
26715
- from: ctxRouter.isOwner ? "owner" : "user"
26716
- },
26717
- deps.inboxOpts ?? { groupFileStore: deps.groupFileStore }
26718
- );
26719
- sendJson(res, 200, result);
26720
- } catch (err) {
26721
- handleInboxError(err, res);
26722
- }
26723
- return true;
26724
- }
26725
- const sessionMatch = ctxRouter.pathname.match(/^\/session\/([^/]+)\/inbox$/);
26726
- if (sessionMatch && req.method === "POST") {
26727
- if (!ctxRouter.isOwner) {
26728
- sendJson(res, 403, { code: "FORBIDDEN", message: "direct session inbox is owner-only" });
26729
- return true;
26730
- }
26731
- if (!deps.getSessionCwd) {
26732
- sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "inbox not wired" });
26733
- return true;
26734
- }
26735
- const sid = sessionMatch[1];
26736
- const sessionCwd = deps.getSessionCwd(sid);
26737
- if (!sessionCwd) {
26738
- sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
26739
- return true;
26740
- }
26741
- try {
26742
- const result = await handleSessionInbox(
26743
- req,
26744
- {
26745
- sessionId: sid,
26746
- sessionCwd: sessionCwd.cwd,
26747
- scope: sessionCwd.scope,
26748
- from: "owner"
26749
- },
26750
- deps.inboxOpts ?? { groupFileStore: deps.groupFileStore }
26751
- );
26752
- sendJson(res, 200, result);
26753
- } catch (err) {
26754
- handleInboxError(err, res);
26755
- }
26756
- return true;
26757
- }
26758
- return false;
26759
- }
26760
- function handleInboxError(err, res) {
26761
- if (isHttpError(err)) {
26762
- sendJson(res, err.httpStatus, { code: err.code, message: err.message });
26763
- return;
26764
- }
26765
- sendJson(res, 500, { code: "INTERNAL", message: err.message });
26766
- }
26767
- function sendJson(res, status, body) {
26768
- if (res.headersSent) return;
26769
- res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
26770
- res.end(JSON.stringify(body));
26771
- }
26772
-
26773
26579
  // src/transport/http-router.ts
26774
26580
  function createHttpRouter(deps) {
26775
26581
  return async (req, res) => {
26776
26582
  const url = parseUrl(req.url);
26777
26583
  if (!url) {
26778
- sendJson2(res, 400, { code: "INVALID_URL", message: "malformed request URL" });
26584
+ sendJson(res, 400, { code: "INVALID_URL", message: "malformed request URL" });
26779
26585
  return true;
26780
26586
  }
26781
26587
  if (url.pathname === "/healthz" && req.method === "GET") {
26782
- sendJson2(res, 200, { ok: true, version: deps.daemonVersion });
26588
+ sendJson(res, 200, { ok: true, version: deps.daemonVersion });
26783
26589
  return true;
26784
26590
  }
26785
26591
  if (!url.pathname.startsWith("/persona/") && !url.pathname.startsWith("/session/") && url.pathname !== "/outbox" && !url.pathname.startsWith("/outbox/")) {
@@ -26790,7 +26596,7 @@ function createHttpRouter(deps) {
26790
26596
  const personaMatch = url.pathname.match(/^\/persona\/([^/]+)\/outbox\/([^/]+)$/);
26791
26597
  if (directMatch || personaMatch) {
26792
26598
  if (!deps.outboxStore) {
26793
- sendJson2(res, 501, { code: "NOT_IMPLEMENTED", message: "outbox store not wired" });
26599
+ sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "outbox store not wired" });
26794
26600
  return true;
26795
26601
  }
26796
26602
  const capToken = directMatch ? directMatch[1] : personaMatch[2];
@@ -26801,7 +26607,7 @@ function createHttpRouter(deps) {
26801
26607
  EXPIRED: 410,
26802
26608
  REVOKED: 410
26803
26609
  };
26804
- sendJson2(res, statusByCode[lookup.code], { code: lookup.code, message: "outbox cap not usable" });
26610
+ sendJson(res, statusByCode[lookup.code], { code: lookup.code, message: "outbox cap not usable" });
26805
26611
  return true;
26806
26612
  }
26807
26613
  const { entry } = lookup;
@@ -26811,7 +26617,7 @@ function createHttpRouter(deps) {
26811
26617
  req.socket.remoteAddress ?? void 0
26812
26618
  );
26813
26619
  if (!ctx2 || ctx2.role !== "personal" || ctx2.personaId !== entry.scope.personalId) {
26814
- sendJson2(res, 403, { code: "FORBIDDEN", message: "personal-scoped cap requires matching token" });
26620
+ sendJson(res, 403, { code: "FORBIDDEN", message: "personal-scoped cap requires matching token" });
26815
26621
  return true;
26816
26622
  }
26817
26623
  }
@@ -26825,7 +26631,7 @@ function createHttpRouter(deps) {
26825
26631
  req.socket.remoteAddress ?? void 0
26826
26632
  );
26827
26633
  if (!ctx) {
26828
- sendJson2(res, 401, { code: "UNAUTHORIZED", message: "missing or invalid bearer token" });
26634
+ sendJson(res, 401, { code: "UNAUTHORIZED", message: "missing or invalid bearer token" });
26829
26635
  return true;
26830
26636
  }
26831
26637
  const personaFilesMatch = url.pathname.match(/^\/persona\/([^/]+)\/files$/);
@@ -26833,26 +26639,26 @@ function createHttpRouter(deps) {
26833
26639
  const pid = personaFilesMatch[1];
26834
26640
  const pathParam = url.searchParams.get("path");
26835
26641
  if (!pathParam) {
26836
- sendJson2(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
26642
+ sendJson(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
26837
26643
  return true;
26838
26644
  }
26839
26645
  if (!deps.personaStore || !deps.groupFileStore) {
26840
- sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "files endpoint not wired" }));
26646
+ sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "files endpoint not wired" }));
26841
26647
  return true;
26842
26648
  }
26843
26649
  const personaDir = deps.personaStore.personaDirPath(pid);
26844
- const absPath = import_node_path17.default.isAbsolute(pathParam) ? pathParam : import_node_path17.default.join(personaDir, pathParam);
26845
- if (!import_node_path17.default.isAbsolute(pathParam) && !isContainedIn(absPath, personaDir)) {
26846
- sendJson2(res, 400, { code: "PATH_TRAVERSAL", message: "rel path escapes personaDir" });
26650
+ const absPath = import_node_path16.default.isAbsolute(pathParam) ? pathParam : import_node_path16.default.join(personaDir, pathParam);
26651
+ if (!import_node_path16.default.isAbsolute(pathParam) && !isContainedIn(absPath, personaDir)) {
26652
+ sendJson(res, 400, { code: "PATH_TRAVERSAL", message: "rel path escapes personaDir" });
26847
26653
  return true;
26848
26654
  }
26849
26655
  if (ctx.role === "personal") {
26850
26656
  if (ctx.personaId !== pid) {
26851
- sendJson2(res, 403, { code: "FORBIDDEN", message: "personal token bound to other persona" });
26657
+ sendJson(res, 403, { code: "FORBIDDEN", message: "personal token bound to other persona" });
26852
26658
  return true;
26853
26659
  }
26854
26660
  if (!personalViewable(deps.groupFileStore, personaDir, pid, absPath)) {
26855
- sendJson2(res, 403, { code: "FORBIDDEN", message: "path not in personal viewable scope" });
26661
+ sendJson(res, 403, { code: "FORBIDDEN", message: "path not in personal viewable scope" });
26856
26662
  return true;
26857
26663
  }
26858
26664
  }
@@ -26862,90 +26668,37 @@ function createHttpRouter(deps) {
26862
26668
  const sessionFilesMatch = url.pathname.match(/^\/session\/([^/]+)\/files$/);
26863
26669
  if (sessionFilesMatch && req.method === "GET") {
26864
26670
  if (ctx.role !== "owner") {
26865
- sendJson2(res, 403, { code: "FORBIDDEN", message: "direct session files are owner-only" });
26671
+ sendJson(res, 403, { code: "FORBIDDEN", message: "direct session files are owner-only" });
26866
26672
  return true;
26867
26673
  }
26868
26674
  const sid = sessionFilesMatch[1];
26869
26675
  const pathParam = url.searchParams.get("path");
26870
26676
  if (!pathParam) {
26871
- sendJson2(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
26677
+ sendJson(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
26872
26678
  return true;
26873
26679
  }
26874
26680
  let absPath;
26875
- if (import_node_path17.default.isAbsolute(pathParam)) {
26681
+ if (import_node_path16.default.isAbsolute(pathParam)) {
26876
26682
  absPath = pathParam;
26877
26683
  } else if (deps.sessionStore) {
26878
26684
  const file = deps.sessionStore.read(sid);
26879
26685
  if (!file) {
26880
- sendJson2(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
26686
+ sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
26881
26687
  return true;
26882
26688
  }
26883
- absPath = import_node_path17.default.join(file.cwd, pathParam);
26689
+ absPath = import_node_path16.default.join(file.cwd, pathParam);
26884
26690
  } else {
26885
- sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
26691
+ sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
26886
26692
  return true;
26887
26693
  }
26888
26694
  streamFile(res, absPath, deps.logger);
26889
26695
  return true;
26890
26696
  }
26891
- if (/^\/persona\/[^/]+\/inbox$/.test(url.pathname) && req.method === "POST") {
26892
- if (!deps.groupFileStore || !deps.personaStore) {
26893
- sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "inbox not wired" }));
26894
- return true;
26895
- }
26896
- const handled = await handleInboxRequest(
26897
- req,
26898
- res,
26899
- {
26900
- pathname: url.pathname,
26901
- isOwner: ctx.role === "owner",
26902
- personaId: ctx.personaId
26903
- },
26904
- {
26905
- groupFileStore: deps.groupFileStore,
26906
- getPersonaDir: (pid) => deps.personaStore.personaDirPath(pid),
26907
- // PR 7:persona inbox 默认走 owner-mode scope;UI 端如果用 personal listener
26908
- // 也归到 owner scope(session 维度)—— PR 9 完善时再走 listener scope。
26909
- getPersonaScope: (pid) => ({
26910
- kind: "persona",
26911
- personaId: pid,
26912
- mode: "owner"
26913
- }),
26914
- addedBy: ctx.label ?? (ctx.role === "owner" ? "owner" : "unknown")
26915
- }
26916
- );
26917
- if (handled) return true;
26918
- }
26919
- if (/^\/session\/[^/]+\/inbox$/.test(url.pathname) && req.method === "POST") {
26920
- if (!deps.groupFileStore || !deps.sessionStore) {
26921
- sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "inbox not wired" }));
26922
- return true;
26923
- }
26924
- const handled = await handleInboxRequest(
26925
- req,
26926
- res,
26927
- {
26928
- pathname: url.pathname,
26929
- isOwner: ctx.role === "owner"
26930
- },
26931
- {
26932
- groupFileStore: deps.groupFileStore,
26933
- getSessionCwd: (sid) => {
26934
- const f = deps.sessionStore.read(sid);
26935
- if (!f) return null;
26936
- const scope = f.ownerPersonaId ? { kind: "persona", personaId: f.ownerPersonaId, mode: "owner" } : { kind: "default" };
26937
- return { cwd: f.cwd, scope };
26938
- },
26939
- addedBy: ctx.role === "owner" ? "owner" : "unknown"
26940
- }
26941
- );
26942
- if (handled) return true;
26943
- }
26944
26697
  if (/^\/persona\/[^/]+\/attachment-meta$/.test(url.pathname) && req.method === "GET") {
26945
- sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "attachment-meta \u2014 PR 6" }));
26698
+ sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "attachment-meta \u2014 PR 6" }));
26946
26699
  return true;
26947
26700
  }
26948
- sendJson2(res, 404, { code: "NOT_FOUND", message: `no route for ${req.method} ${url.pathname}` });
26701
+ sendJson(res, 404, { code: "NOT_FOUND", message: `no route for ${req.method} ${url.pathname}` });
26949
26702
  return true;
26950
26703
  };
26951
26704
  }
@@ -26957,7 +26710,7 @@ function parseUrl(rawUrl) {
26957
26710
  return null;
26958
26711
  }
26959
26712
  }
26960
- function sendJson2(res, status, body) {
26713
+ function sendJson(res, status, body) {
26961
26714
  res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
26962
26715
  res.end(JSON.stringify(body));
26963
26716
  }
@@ -26965,26 +26718,26 @@ function withCtx(ctx, body) {
26965
26718
  return { ...body, role: ctx.role, personaId: ctx.personaId };
26966
26719
  }
26967
26720
  function isContainedIn(abs, root) {
26968
- const normalized = import_node_path17.default.resolve(abs);
26969
- const normalizedRoot = import_node_path17.default.resolve(root);
26721
+ const normalized = import_node_path16.default.resolve(abs);
26722
+ const normalizedRoot = import_node_path16.default.resolve(root);
26970
26723
  if (normalized === normalizedRoot) return true;
26971
- return normalized.startsWith(normalizedRoot + import_node_path17.default.sep);
26724
+ return normalized.startsWith(normalizedRoot + import_node_path16.default.sep);
26972
26725
  }
26973
26726
  function streamFile(res, absPath, logger, onComplete) {
26974
26727
  let stat;
26975
26728
  try {
26976
- stat = import_node_fs15.default.statSync(absPath);
26729
+ stat = import_node_fs14.default.statSync(absPath);
26977
26730
  } catch (err) {
26978
26731
  const code = err?.code;
26979
26732
  if (code === "ENOENT") {
26980
- sendJson2(res, 404, { code: "NOT_FOUND", message: "file not found" });
26733
+ sendJson(res, 404, { code: "NOT_FOUND", message: "file not found" });
26981
26734
  } else {
26982
- sendJson2(res, 500, { code: "STAT_FAILED", message: err.message });
26735
+ sendJson(res, 500, { code: "STAT_FAILED", message: err.message });
26983
26736
  }
26984
26737
  return;
26985
26738
  }
26986
26739
  if (!stat.isFile()) {
26987
- sendJson2(res, 400, { code: "NOT_A_FILE", message: "path is not a regular file" });
26740
+ sendJson(res, 400, { code: "NOT_A_FILE", message: "path is not a regular file" });
26988
26741
  return;
26989
26742
  }
26990
26743
  const mime = lookupMime(absPath);
@@ -26994,7 +26747,7 @@ function streamFile(res, absPath, logger, onComplete) {
26994
26747
  // 防止浏览器把任意 mime 当 html 渲染(spec §11 #8 安全心智)
26995
26748
  "X-Content-Type-Options": "nosniff"
26996
26749
  });
26997
- const stream = import_node_fs15.default.createReadStream(absPath);
26750
+ const stream = import_node_fs14.default.createReadStream(absPath);
26998
26751
  stream.on("error", (err) => {
26999
26752
  logger?.warn("streamFile read error", { absPath, err: err.message });
27000
26753
  res.destroy();
@@ -27006,9 +26759,9 @@ function streamFile(res, absPath, logger, onComplete) {
27006
26759
  }
27007
26760
 
27008
26761
  // src/attachment/outbox.ts
27009
- var import_node_fs16 = __toESM(require("fs"), 1);
27010
- var import_node_path18 = __toESM(require("path"), 1);
27011
- var import_node_crypto6 = __toESM(require("crypto"), 1);
26762
+ var import_node_fs15 = __toESM(require("fs"), 1);
26763
+ var import_node_path17 = __toESM(require("path"), 1);
26764
+ var import_node_crypto5 = __toESM(require("crypto"), 1);
27012
26765
  init_protocol();
27013
26766
  var FILE_NAME = "outbox-caps.json";
27014
26767
  var OutboxStore = class {
@@ -27017,14 +26770,14 @@ var OutboxStore = class {
27017
26770
  logger;
27018
26771
  cache = [];
27019
26772
  constructor(opts) {
27020
- this.file = import_node_path18.default.join(opts.dataDir, FILE_NAME);
26773
+ this.file = import_node_path17.default.join(opts.dataDir, FILE_NAME);
27021
26774
  this.now = opts.now ?? Date.now;
27022
26775
  this.logger = opts.logger;
27023
26776
  this.reload();
27024
26777
  }
27025
26778
  reload() {
27026
26779
  try {
27027
- const raw = import_node_fs16.default.readFileSync(this.file, "utf8");
26780
+ const raw = import_node_fs15.default.readFileSync(this.file, "utf8");
27028
26781
  const parsed = JSON.parse(raw);
27029
26782
  if (!Array.isArray(parsed)) {
27030
26783
  this.logger?.warn("OutboxStore.reload: outbox-caps.json is not an array; resetting", {
@@ -27051,10 +26804,10 @@ var OutboxStore = class {
27051
26804
  }
27052
26805
  }
27053
26806
  persist() {
27054
- import_node_fs16.default.mkdirSync(import_node_path18.default.dirname(this.file), { recursive: true });
26807
+ import_node_fs15.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
27055
26808
  const tmp = `${this.file}.tmp-${process.pid}-${Date.now()}`;
27056
- import_node_fs16.default.writeFileSync(tmp, JSON.stringify(this.cache, null, 2), { mode: 384 });
27057
- import_node_fs16.default.renameSync(tmp, this.file);
26809
+ import_node_fs15.default.writeFileSync(tmp, JSON.stringify(this.cache, null, 2), { mode: 384 });
26810
+ import_node_fs15.default.renameSync(tmp, this.file);
27058
26811
  }
27059
26812
  /** 列出当前缓存(含 revoked / 过期,UI Drawer 显灰;过滤靠调用方) */
27060
26813
  list() {
@@ -27076,7 +26829,7 @@ var OutboxStore = class {
27076
26829
  const ts = this.now();
27077
26830
  const ttl = input.ttlSeconds === null ? null : input.ttlSeconds ?? 24 * 3600;
27078
26831
  const entry = {
27079
- capToken: import_node_crypto6.default.randomBytes(32).toString("base64url"),
26832
+ capToken: import_node_crypto5.default.randomBytes(32).toString("base64url"),
27080
26833
  scopeRef: input.scopeRef,
27081
26834
  absPath: input.absPath,
27082
26835
  name: input.name,
@@ -27132,8 +26885,8 @@ var OutboxStore = class {
27132
26885
  };
27133
26886
 
27134
26887
  // src/attachment/mount.ts
27135
- var import_node_fs17 = __toESM(require("fs"), 1);
27136
- var import_node_path19 = __toESM(require("path"), 1);
26888
+ var import_node_fs16 = __toESM(require("fs"), 1);
26889
+ var import_node_path18 = __toESM(require("path"), 1);
27137
26890
  init_protocol();
27138
26891
  var MountStore = class {
27139
26892
  constructor(opts) {
@@ -27141,11 +26894,11 @@ var MountStore = class {
27141
26894
  }
27142
26895
  opts;
27143
26896
  filePath(personaId) {
27144
- return import_node_path19.default.join(this.opts.personaDirPath(personaId), ".clawd", "shared-files.json");
26897
+ return import_node_path18.default.join(this.opts.personaDirPath(personaId), ".clawd", "shared-files.json");
27145
26898
  }
27146
26899
  list(personaId) {
27147
26900
  try {
27148
- const raw = import_node_fs17.default.readFileSync(this.filePath(personaId), "utf8");
26901
+ const raw = import_node_fs16.default.readFileSync(this.filePath(personaId), "utf8");
27149
26902
  const parsed = JSON.parse(raw);
27150
26903
  if (!Array.isArray(parsed)) return [];
27151
26904
  const out = [];
@@ -27164,22 +26917,22 @@ var MountStore = class {
27164
26917
  */
27165
26918
  add(personaId, input) {
27166
26919
  const personaDir = this.opts.personaDirPath(personaId);
27167
- if (!import_node_fs17.default.existsSync(personaDir)) {
26920
+ if (!import_node_fs16.default.existsSync(personaDir)) {
27168
26921
  throw new Error(`personaDir not found: ${personaDir}`);
27169
26922
  }
27170
- const source = import_node_path19.default.resolve(input.absPath);
27171
- if (!import_node_fs17.default.existsSync(source)) {
26923
+ const source = import_node_path18.default.resolve(input.absPath);
26924
+ if (!import_node_fs16.default.existsSync(source)) {
27172
26925
  throw new Error(`source path not found: ${source}`);
27173
26926
  }
27174
- const basename = import_node_path19.default.basename(source);
27175
- const dest = import_node_path19.default.join(personaDir, basename);
27176
- if (import_node_fs17.default.existsSync(dest)) {
26927
+ const basename = import_node_path18.default.basename(source);
26928
+ const dest = import_node_path18.default.join(personaDir, basename);
26929
+ if (import_node_fs16.default.existsSync(dest)) {
27177
26930
  throw new Error(`destination already exists: ${dest}`);
27178
26931
  }
27179
26932
  if (input.mode === "link") {
27180
- import_node_fs17.default.symlinkSync(source, dest);
26933
+ import_node_fs16.default.symlinkSync(source, dest);
27181
26934
  } else {
27182
- import_node_fs17.default.copyFileSync(source, dest);
26935
+ import_node_fs16.default.copyFileSync(source, dest);
27183
26936
  }
27184
26937
  const entry = {
27185
26938
  basename,
@@ -27196,9 +26949,9 @@ var MountStore = class {
27196
26949
  if (idx < 0) return false;
27197
26950
  const entry = entries[idx];
27198
26951
  const personaDir = this.opts.personaDirPath(personaId);
27199
- const dest = import_node_path19.default.join(personaDir, basename);
26952
+ const dest = import_node_path18.default.join(personaDir, basename);
27200
26953
  try {
27201
- import_node_fs17.default.unlinkSync(dest);
26954
+ import_node_fs16.default.unlinkSync(dest);
27202
26955
  } catch {
27203
26956
  }
27204
26957
  const next = entries.slice();
@@ -27209,18 +26962,18 @@ var MountStore = class {
27209
26962
  }
27210
26963
  writeManifest(personaId, entries) {
27211
26964
  const file = this.filePath(personaId);
27212
- import_node_fs17.default.mkdirSync(import_node_path19.default.dirname(file), { recursive: true });
26965
+ import_node_fs16.default.mkdirSync(import_node_path18.default.dirname(file), { recursive: true });
27213
26966
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
27214
- import_node_fs17.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
27215
- import_node_fs17.default.renameSync(tmp, file);
26967
+ import_node_fs16.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
26968
+ import_node_fs16.default.renameSync(tmp, file);
27216
26969
  }
27217
26970
  };
27218
26971
 
27219
26972
  // src/discovery/state-file.ts
27220
- var import_node_fs18 = __toESM(require("fs"), 1);
27221
- var import_node_path20 = __toESM(require("path"), 1);
26973
+ var import_node_fs17 = __toESM(require("fs"), 1);
26974
+ var import_node_path19 = __toESM(require("path"), 1);
27222
26975
  function defaultStateFilePath(dataDir) {
27223
- return import_node_path20.default.join(dataDir, "state.json");
26976
+ return import_node_path19.default.join(dataDir, "state.json");
27224
26977
  }
27225
26978
  function isPidAlive(pid) {
27226
26979
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -27242,7 +26995,7 @@ var StateFileManager = class {
27242
26995
  }
27243
26996
  read() {
27244
26997
  try {
27245
- const raw = import_node_fs18.default.readFileSync(this.file, "utf8");
26998
+ const raw = import_node_fs17.default.readFileSync(this.file, "utf8");
27246
26999
  const parsed = JSON.parse(raw);
27247
27000
  return parsed;
27248
27001
  } catch {
@@ -27256,34 +27009,34 @@ var StateFileManager = class {
27256
27009
  return { status: "stale", existing };
27257
27010
  }
27258
27011
  write(state) {
27259
- import_node_fs18.default.mkdirSync(import_node_path20.default.dirname(this.file), { recursive: true });
27012
+ import_node_fs17.default.mkdirSync(import_node_path19.default.dirname(this.file), { recursive: true });
27260
27013
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
27261
- import_node_fs18.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27262
- import_node_fs18.default.renameSync(tmp, this.file);
27014
+ import_node_fs17.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27015
+ import_node_fs17.default.renameSync(tmp, this.file);
27263
27016
  if (process.platform !== "win32") {
27264
27017
  try {
27265
- import_node_fs18.default.chmodSync(this.file, 384);
27018
+ import_node_fs17.default.chmodSync(this.file, 384);
27266
27019
  } catch {
27267
27020
  }
27268
27021
  }
27269
27022
  }
27270
27023
  delete() {
27271
27024
  try {
27272
- import_node_fs18.default.unlinkSync(this.file);
27025
+ import_node_fs17.default.unlinkSync(this.file);
27273
27026
  } catch {
27274
27027
  }
27275
27028
  }
27276
27029
  };
27277
27030
 
27278
27031
  // src/tunnel/tunnel-manager.ts
27279
- var import_node_fs22 = __toESM(require("fs"), 1);
27280
- var import_node_path24 = __toESM(require("path"), 1);
27281
- var import_node_crypto7 = __toESM(require("crypto"), 1);
27032
+ var import_node_fs21 = __toESM(require("fs"), 1);
27033
+ var import_node_path23 = __toESM(require("path"), 1);
27034
+ var import_node_crypto6 = __toESM(require("crypto"), 1);
27282
27035
  var import_node_child_process5 = require("child_process");
27283
27036
 
27284
27037
  // src/tunnel/tunnel-store.ts
27285
- var import_node_fs19 = __toESM(require("fs"), 1);
27286
- var import_node_path21 = __toESM(require("path"), 1);
27038
+ var import_node_fs18 = __toESM(require("fs"), 1);
27039
+ var import_node_path20 = __toESM(require("path"), 1);
27287
27040
  var TunnelStore = class {
27288
27041
  constructor(filePath) {
27289
27042
  this.filePath = filePath;
@@ -27291,7 +27044,7 @@ var TunnelStore = class {
27291
27044
  filePath;
27292
27045
  async get() {
27293
27046
  try {
27294
- const raw = await import_node_fs19.default.promises.readFile(this.filePath, "utf8");
27047
+ const raw = await import_node_fs18.default.promises.readFile(this.filePath, "utf8");
27295
27048
  const obj = JSON.parse(raw);
27296
27049
  if (!isPersistedTunnel(obj)) return null;
27297
27050
  return obj;
@@ -27302,22 +27055,22 @@ var TunnelStore = class {
27302
27055
  }
27303
27056
  }
27304
27057
  async set(v2) {
27305
- const dir = import_node_path21.default.dirname(this.filePath);
27306
- await import_node_fs19.default.promises.mkdir(dir, { recursive: true });
27058
+ const dir = import_node_path20.default.dirname(this.filePath);
27059
+ await import_node_fs18.default.promises.mkdir(dir, { recursive: true });
27307
27060
  const data = JSON.stringify(v2, null, 2);
27308
27061
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
27309
- await import_node_fs19.default.promises.writeFile(tmp, data, { mode: 384 });
27062
+ await import_node_fs18.default.promises.writeFile(tmp, data, { mode: 384 });
27310
27063
  if (process.platform !== "win32") {
27311
27064
  try {
27312
- await import_node_fs19.default.promises.chmod(tmp, 384);
27065
+ await import_node_fs18.default.promises.chmod(tmp, 384);
27313
27066
  } catch {
27314
27067
  }
27315
27068
  }
27316
- await import_node_fs19.default.promises.rename(tmp, this.filePath);
27069
+ await import_node_fs18.default.promises.rename(tmp, this.filePath);
27317
27070
  }
27318
27071
  async clear() {
27319
27072
  try {
27320
- await import_node_fs19.default.promises.unlink(this.filePath);
27073
+ await import_node_fs18.default.promises.unlink(this.filePath);
27321
27074
  } catch (err) {
27322
27075
  const code = err?.code;
27323
27076
  if (code !== "ENOENT") throw err;
@@ -27412,9 +27165,9 @@ function escape(v2) {
27412
27165
  }
27413
27166
 
27414
27167
  // src/tunnel/frpc-binary.ts
27415
- var import_node_fs20 = __toESM(require("fs"), 1);
27168
+ var import_node_fs19 = __toESM(require("fs"), 1);
27416
27169
  var import_node_os9 = __toESM(require("os"), 1);
27417
- var import_node_path22 = __toESM(require("path"), 1);
27170
+ var import_node_path21 = __toESM(require("path"), 1);
27418
27171
  var import_node_child_process3 = require("child_process");
27419
27172
  var import_node_stream2 = require("stream");
27420
27173
  var import_promises = require("stream/promises");
@@ -27446,20 +27199,20 @@ function frpcDownloadUrl(version2, p2) {
27446
27199
  }
27447
27200
  async function ensureFrpcBinary(opts) {
27448
27201
  if (opts.override) {
27449
- if (!import_node_fs20.default.existsSync(opts.override)) {
27202
+ if (!import_node_fs19.default.existsSync(opts.override)) {
27450
27203
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
27451
27204
  }
27452
27205
  return opts.override;
27453
27206
  }
27454
27207
  const version2 = opts.version ?? FRPC_VERSION;
27455
27208
  const platform = opts.platform ?? detectPlatform();
27456
- const binDir = import_node_path22.default.join(opts.dataDir, "bin");
27457
- import_node_fs20.default.mkdirSync(binDir, { recursive: true });
27209
+ const binDir = import_node_path21.default.join(opts.dataDir, "bin");
27210
+ import_node_fs19.default.mkdirSync(binDir, { recursive: true });
27458
27211
  cleanupStaleArtifacts(binDir);
27459
- const stableBin = import_node_path22.default.join(binDir, "frpc");
27460
- if (import_node_fs20.default.existsSync(stableBin)) return stableBin;
27212
+ const stableBin = import_node_path21.default.join(binDir, "frpc");
27213
+ if (import_node_fs19.default.existsSync(stableBin)) return stableBin;
27461
27214
  const partialBin = `${stableBin}.partial`;
27462
- const tarballPath = import_node_path22.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
27215
+ const tarballPath = import_node_path21.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
27463
27216
  try {
27464
27217
  const url = frpcDownloadUrl(version2, platform);
27465
27218
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -27468,8 +27221,8 @@ async function ensureFrpcBinary(opts) {
27468
27221
  } else {
27469
27222
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
27470
27223
  }
27471
- import_node_fs20.default.chmodSync(partialBin, 493);
27472
- import_node_fs20.default.renameSync(partialBin, stableBin);
27224
+ import_node_fs19.default.chmodSync(partialBin, 493);
27225
+ import_node_fs19.default.renameSync(partialBin, stableBin);
27473
27226
  } finally {
27474
27227
  safeUnlink(tarballPath);
27475
27228
  safeUnlink(partialBin);
@@ -27479,15 +27232,15 @@ async function ensureFrpcBinary(opts) {
27479
27232
  function cleanupStaleArtifacts(binDir) {
27480
27233
  let entries;
27481
27234
  try {
27482
- entries = import_node_fs20.default.readdirSync(binDir);
27235
+ entries = import_node_fs19.default.readdirSync(binDir);
27483
27236
  } catch {
27484
27237
  return;
27485
27238
  }
27486
27239
  for (const name of entries) {
27487
27240
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
27488
- const full = import_node_path22.default.join(binDir, name);
27241
+ const full = import_node_path21.default.join(binDir, name);
27489
27242
  try {
27490
- import_node_fs20.default.rmSync(full, { recursive: true, force: true });
27243
+ import_node_fs19.default.rmSync(full, { recursive: true, force: true });
27491
27244
  } catch {
27492
27245
  }
27493
27246
  }
@@ -27495,7 +27248,7 @@ function cleanupStaleArtifacts(binDir) {
27495
27248
  }
27496
27249
  function safeUnlink(p2) {
27497
27250
  try {
27498
- import_node_fs20.default.unlinkSync(p2);
27251
+ import_node_fs19.default.unlinkSync(p2);
27499
27252
  } catch {
27500
27253
  }
27501
27254
  }
@@ -27506,13 +27259,13 @@ async function downloadToFile(url, dest, fetchImpl) {
27506
27259
  if (!res.ok || !res.body) {
27507
27260
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
27508
27261
  }
27509
- const out = import_node_fs20.default.createWriteStream(dest);
27262
+ const out = import_node_fs19.default.createWriteStream(dest);
27510
27263
  const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
27511
27264
  await (0, import_promises.pipeline)(nodeStream, out);
27512
27265
  }
27513
27266
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
27514
- const work = import_node_path22.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
27515
- import_node_fs20.default.mkdirSync(work, { recursive: true });
27267
+ const work = import_node_path21.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
27268
+ import_node_fs19.default.mkdirSync(work, { recursive: true });
27516
27269
  try {
27517
27270
  await new Promise((resolve2, reject) => {
27518
27271
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -27520,32 +27273,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
27520
27273
  proc.on("exit", (code) => code === 0 ? resolve2() : reject(new Error(`tar exited ${code}`)));
27521
27274
  });
27522
27275
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
27523
- const src = import_node_path22.default.join(work, dirName, "frpc");
27524
- if (!import_node_fs20.default.existsSync(src)) {
27276
+ const src = import_node_path21.default.join(work, dirName, "frpc");
27277
+ if (!import_node_fs19.default.existsSync(src)) {
27525
27278
  throw new Error(`frpc not found inside tarball at ${src}`);
27526
27279
  }
27527
- import_node_fs20.default.copyFileSync(src, destBin);
27280
+ import_node_fs19.default.copyFileSync(src, destBin);
27528
27281
  } finally {
27529
- import_node_fs20.default.rmSync(work, { recursive: true, force: true });
27282
+ import_node_fs19.default.rmSync(work, { recursive: true, force: true });
27530
27283
  }
27531
27284
  }
27532
27285
 
27533
27286
  // src/tunnel/frpc-process.ts
27534
- var import_node_fs21 = __toESM(require("fs"), 1);
27535
- var import_node_path23 = __toESM(require("path"), 1);
27287
+ var import_node_fs20 = __toESM(require("fs"), 1);
27288
+ var import_node_path22 = __toESM(require("path"), 1);
27536
27289
  var import_node_child_process4 = require("child_process");
27537
27290
  function frpcPidFilePath(dataDir) {
27538
- return import_node_path23.default.join(dataDir, "frpc.pid");
27291
+ return import_node_path22.default.join(dataDir, "frpc.pid");
27539
27292
  }
27540
27293
  function writeFrpcPid(dataDir, pid) {
27541
27294
  try {
27542
- import_node_fs21.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
27295
+ import_node_fs20.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
27543
27296
  } catch {
27544
27297
  }
27545
27298
  }
27546
27299
  function clearFrpcPid(dataDir) {
27547
27300
  try {
27548
- import_node_fs21.default.unlinkSync(frpcPidFilePath(dataDir));
27301
+ import_node_fs20.default.unlinkSync(frpcPidFilePath(dataDir));
27549
27302
  } catch {
27550
27303
  }
27551
27304
  }
@@ -27561,7 +27314,7 @@ function defaultIsPidAlive(pid) {
27561
27314
  }
27562
27315
  function defaultReadPidFile(file) {
27563
27316
  try {
27564
- return import_node_fs21.default.readFileSync(file, "utf8");
27317
+ return import_node_fs20.default.readFileSync(file, "utf8");
27565
27318
  } catch {
27566
27319
  return null;
27567
27320
  }
@@ -27577,7 +27330,7 @@ function defaultSleep(ms) {
27577
27330
  }
27578
27331
  async function killStaleFrpc(deps) {
27579
27332
  const pidFile = frpcPidFilePath(deps.dataDir);
27580
- const tomlPath = import_node_path23.default.join(deps.dataDir, "frpc.toml");
27333
+ const tomlPath = import_node_path22.default.join(deps.dataDir, "frpc.toml");
27581
27334
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
27582
27335
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
27583
27336
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -27601,7 +27354,7 @@ async function killStaleFrpc(deps) {
27601
27354
  }
27602
27355
  if (victims.size === 0) {
27603
27356
  try {
27604
- import_node_fs21.default.unlinkSync(pidFile);
27357
+ import_node_fs20.default.unlinkSync(pidFile);
27605
27358
  } catch {
27606
27359
  }
27607
27360
  return;
@@ -27612,7 +27365,7 @@ async function killStaleFrpc(deps) {
27612
27365
  }
27613
27366
  await sleep(deps.reapWaitMs ?? 300);
27614
27367
  try {
27615
- import_node_fs21.default.unlinkSync(pidFile);
27368
+ import_node_fs20.default.unlinkSync(pidFile);
27616
27369
  } catch {
27617
27370
  }
27618
27371
  }
@@ -27649,7 +27402,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
27649
27402
  var TunnelManager = class {
27650
27403
  constructor(deps) {
27651
27404
  this.deps = deps;
27652
- this.store = deps.store ?? new TunnelStore(import_node_path24.default.join(deps.dataDir, "tunnel.json"));
27405
+ this.store = deps.store ?? new TunnelStore(import_node_path23.default.join(deps.dataDir, "tunnel.json"));
27653
27406
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
27654
27407
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
27655
27408
  }
@@ -27776,8 +27529,8 @@ var TunnelManager = class {
27776
27529
  dataDir: this.deps.dataDir,
27777
27530
  override: this.deps.frpcBinaryOverride ?? void 0
27778
27531
  });
27779
- const tomlPath = import_node_path24.default.join(this.deps.dataDir, "frpc.toml");
27780
- const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
27532
+ const tomlPath = import_node_path23.default.join(this.deps.dataDir, "frpc.toml");
27533
+ const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto6.default.randomBytes(3).toString("hex")}`;
27781
27534
  const toml = buildFrpcToml({
27782
27535
  serverAddr: t.frpsHost,
27783
27536
  serverPort: t.frpsPort,
@@ -27787,12 +27540,12 @@ var TunnelManager = class {
27787
27540
  localPort,
27788
27541
  logLevel: "info"
27789
27542
  });
27790
- await import_node_fs22.default.promises.writeFile(tomlPath, toml, { mode: 384 });
27543
+ await import_node_fs21.default.promises.writeFile(tomlPath, toml, { mode: 384 });
27791
27544
  const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
27792
27545
  stdio: ["ignore", "pipe", "pipe"]
27793
27546
  });
27794
- const logFilePath = import_node_path24.default.join(this.deps.dataDir, "frpc.log");
27795
- const logStream = import_node_fs22.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
27547
+ const logFilePath = import_node_path23.default.join(this.deps.dataDir, "frpc.log");
27548
+ const logStream = import_node_fs21.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
27796
27549
  logStream.on("error", () => {
27797
27550
  });
27798
27551
  const tee = (chunk) => {
@@ -27875,22 +27628,22 @@ async function waitForFrpcReady(proc, timeoutMs) {
27875
27628
 
27876
27629
  // src/tunnel/device-key.ts
27877
27630
  var import_node_os10 = __toESM(require("os"), 1);
27878
- var import_node_crypto8 = __toESM(require("crypto"), 1);
27631
+ var import_node_crypto7 = __toESM(require("crypto"), 1);
27879
27632
  var DERIVE_SALT = "clawd-tunnel-device-v1";
27880
27633
  function deriveStableDeviceKey(opts = {}) {
27881
27634
  const hostname = opts.hostname ?? import_node_os10.default.hostname();
27882
27635
  const uid = opts.uid ?? (typeof import_node_os10.default.userInfo === "function" ? import_node_os10.default.userInfo().uid : 0);
27883
27636
  const input = `${hostname}::${uid}`;
27884
- return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
27637
+ return import_node_crypto7.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
27885
27638
  }
27886
27639
 
27887
27640
  // src/auth-store.ts
27888
- var import_node_fs23 = __toESM(require("fs"), 1);
27889
- var import_node_path25 = __toESM(require("path"), 1);
27890
- var import_node_crypto9 = __toESM(require("crypto"), 1);
27641
+ var import_node_fs22 = __toESM(require("fs"), 1);
27642
+ var import_node_path24 = __toESM(require("path"), 1);
27643
+ var import_node_crypto8 = __toESM(require("crypto"), 1);
27891
27644
  var AUTH_FILE_NAME = "auth.json";
27892
27645
  function authFilePath(dataDir) {
27893
- return import_node_path25.default.join(dataDir, AUTH_FILE_NAME);
27646
+ return import_node_path24.default.join(dataDir, AUTH_FILE_NAME);
27894
27647
  }
27895
27648
  function loadOrCreateAuthToken(opts) {
27896
27649
  const file = authFilePath(opts.dataDir);
@@ -27902,11 +27655,11 @@ function loadOrCreateAuthToken(opts) {
27902
27655
  return token;
27903
27656
  }
27904
27657
  function defaultGenerate() {
27905
- return import_node_crypto9.default.randomBytes(32).toString("base64url");
27658
+ return import_node_crypto8.default.randomBytes(32).toString("base64url");
27906
27659
  }
27907
27660
  function readAuthFile(file) {
27908
27661
  try {
27909
- const raw = import_node_fs23.default.readFileSync(file, "utf8");
27662
+ const raw = import_node_fs22.default.readFileSync(file, "utf8");
27910
27663
  const parsed = JSON.parse(raw);
27911
27664
  if (typeof parsed?.token === "string" && parsed.token.length > 0) {
27912
27665
  return {
@@ -27922,25 +27675,25 @@ function readAuthFile(file) {
27922
27675
  }
27923
27676
  }
27924
27677
  function writeAuthFile(file, content) {
27925
- import_node_fs23.default.mkdirSync(import_node_path25.default.dirname(file), { recursive: true });
27926
- import_node_fs23.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
27678
+ import_node_fs22.default.mkdirSync(import_node_path24.default.dirname(file), { recursive: true });
27679
+ import_node_fs22.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
27927
27680
  try {
27928
- import_node_fs23.default.chmodSync(file, 384);
27681
+ import_node_fs22.default.chmodSync(file, 384);
27929
27682
  } catch {
27930
27683
  }
27931
27684
  }
27932
27685
 
27933
27686
  // src/owner-profile.ts
27934
- var import_node_fs24 = __toESM(require("fs"), 1);
27687
+ var import_node_fs23 = __toESM(require("fs"), 1);
27935
27688
  var import_node_os11 = __toESM(require("os"), 1);
27936
- var import_node_path26 = __toESM(require("path"), 1);
27689
+ var import_node_path25 = __toESM(require("path"), 1);
27937
27690
  var PROFILE_FILENAME = "profile.json";
27938
27691
  function loadOwnerDisplayName(dataDir) {
27939
27692
  const fallback = import_node_os11.default.userInfo().username;
27940
- const profilePath = import_node_path26.default.join(dataDir, PROFILE_FILENAME);
27693
+ const profilePath = import_node_path25.default.join(dataDir, PROFILE_FILENAME);
27941
27694
  let raw;
27942
27695
  try {
27943
- raw = import_node_fs24.default.readFileSync(profilePath, "utf8");
27696
+ raw = import_node_fs23.default.readFileSync(profilePath, "utf8");
27944
27697
  } catch {
27945
27698
  return fallback;
27946
27699
  }
@@ -27969,12 +27722,12 @@ init_protocol();
27969
27722
  init_protocol();
27970
27723
 
27971
27724
  // src/session/fork.ts
27972
- var import_node_fs25 = __toESM(require("fs"), 1);
27725
+ var import_node_fs24 = __toESM(require("fs"), 1);
27973
27726
  var import_node_os12 = __toESM(require("os"), 1);
27974
- var import_node_path27 = __toESM(require("path"), 1);
27727
+ var import_node_path26 = __toESM(require("path"), 1);
27975
27728
  init_claude_history();
27976
27729
  function readJsonlEntries(file) {
27977
- const raw = import_node_fs25.default.readFileSync(file, "utf8");
27730
+ const raw = import_node_fs24.default.readFileSync(file, "utf8");
27978
27731
  const out = [];
27979
27732
  for (const line of raw.split("\n")) {
27980
27733
  const t = line.trim();
@@ -27987,10 +27740,10 @@ function readJsonlEntries(file) {
27987
27740
  return out;
27988
27741
  }
27989
27742
  function forkSession(input) {
27990
- const baseDir = input.baseDir ?? import_node_path27.default.join(import_node_os12.default.homedir(), ".claude");
27991
- const projectDir = import_node_path27.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
27992
- const sourceFile = import_node_path27.default.join(projectDir, `${input.toolSessionId}.jsonl`);
27993
- if (!import_node_fs25.default.existsSync(sourceFile)) {
27743
+ const baseDir = input.baseDir ?? import_node_path26.default.join(import_node_os12.default.homedir(), ".claude");
27744
+ const projectDir = import_node_path26.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
27745
+ const sourceFile = import_node_path26.default.join(projectDir, `${input.toolSessionId}.jsonl`);
27746
+ if (!import_node_fs24.default.existsSync(sourceFile)) {
27994
27747
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
27995
27748
  }
27996
27749
  const entries = readJsonlEntries(sourceFile);
@@ -28020,9 +27773,9 @@ function forkSession(input) {
28020
27773
  }
28021
27774
  forkedLines.push(JSON.stringify(forked));
28022
27775
  }
28023
- const forkedFilePath = import_node_path27.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
28024
- import_node_fs25.default.mkdirSync(projectDir, { recursive: true });
28025
- import_node_fs25.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
27776
+ const forkedFilePath = import_node_path26.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
27777
+ import_node_fs24.default.mkdirSync(projectDir, { recursive: true });
27778
+ import_node_fs24.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
28026
27779
  return { forkedToolSessionId, forkedFilePath };
28027
27780
  }
28028
27781
 
@@ -28343,9 +28096,9 @@ init_protocol();
28343
28096
 
28344
28097
  // src/workspace/git.ts
28345
28098
  var import_node_child_process6 = require("child_process");
28346
- var import_node_fs26 = __toESM(require("fs"), 1);
28099
+ var import_node_fs25 = __toESM(require("fs"), 1);
28347
28100
  var import_node_os13 = __toESM(require("os"), 1);
28348
- var import_node_path28 = __toESM(require("path"), 1);
28101
+ var import_node_path27 = __toESM(require("path"), 1);
28349
28102
  var import_node_util = require("util");
28350
28103
  var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
28351
28104
  function formatChildProcessError(err) {
@@ -28360,9 +28113,9 @@ function formatChildProcessError(err) {
28360
28113
  return e.message ?? "unknown error";
28361
28114
  }
28362
28115
  function normalizePath(p2) {
28363
- const resolved = import_node_path28.default.resolve(p2);
28116
+ const resolved = import_node_path27.default.resolve(p2);
28364
28117
  try {
28365
- return import_node_fs26.default.realpathSync(resolved);
28118
+ return import_node_fs25.default.realpathSync(resolved);
28366
28119
  } catch {
28367
28120
  return resolved;
28368
28121
  }
@@ -28463,13 +28216,13 @@ function flattenToDirName(branch) {
28463
28216
  }
28464
28217
  function encodeClaudeProjectDir(absPath) {
28465
28218
  if (!absPath || typeof absPath !== "string") return "";
28466
- let canonical = import_node_path28.default.resolve(absPath);
28219
+ let canonical = import_node_path27.default.resolve(absPath);
28467
28220
  try {
28468
- canonical = import_node_fs26.default.realpathSync(canonical);
28221
+ canonical = import_node_fs25.default.realpathSync(canonical);
28469
28222
  } catch {
28470
28223
  try {
28471
- const parent = import_node_fs26.default.realpathSync(import_node_path28.default.dirname(canonical));
28472
- canonical = import_node_path28.default.join(parent, import_node_path28.default.basename(canonical));
28224
+ const parent = import_node_fs25.default.realpathSync(import_node_path27.default.dirname(canonical));
28225
+ canonical = import_node_path27.default.join(parent, import_node_path27.default.basename(canonical));
28473
28226
  } catch {
28474
28227
  }
28475
28228
  }
@@ -28493,11 +28246,11 @@ async function createWorktree(input) {
28493
28246
  if (!isGitRoot) {
28494
28247
  throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
28495
28248
  }
28496
- const parent = import_node_path28.default.dirname(import_node_path28.default.resolve(cwd));
28497
- if (parent === "/" || parent === import_node_path28.default.resolve(cwd)) {
28249
+ const parent = import_node_path27.default.dirname(import_node_path27.default.resolve(cwd));
28250
+ if (parent === "/" || parent === import_node_path27.default.resolve(cwd)) {
28498
28251
  throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
28499
28252
  }
28500
- const worktreeRoot = import_node_path28.default.join(parent, dirName);
28253
+ const worktreeRoot = import_node_path27.default.join(parent, dirName);
28501
28254
  try {
28502
28255
  await pexec("git", ["-C", cwd, "fetch", "origin", baseBranch, "--no-tags"], {
28503
28256
  timeout: 3e4
@@ -28516,7 +28269,7 @@ async function createWorktree(input) {
28516
28269
  const msg = err.message;
28517
28270
  if (msg.startsWith("\u5206\u652F ")) throw err;
28518
28271
  }
28519
- if (import_node_fs26.default.existsSync(worktreeRoot)) {
28272
+ if (import_node_fs25.default.existsSync(worktreeRoot)) {
28520
28273
  throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
28521
28274
  }
28522
28275
  try {
@@ -28544,8 +28297,8 @@ async function removeWorktree(input) {
28544
28297
  );
28545
28298
  const gitCommonDir = stdout.trim();
28546
28299
  if (!gitCommonDir) throw new Error("empty git-common-dir");
28547
- const absGitCommon = import_node_path28.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path28.default.resolve(worktreeRoot, gitCommonDir);
28548
- repoRoot = import_node_path28.default.dirname(absGitCommon);
28300
+ const absGitCommon = import_node_path27.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path27.default.resolve(worktreeRoot, gitCommonDir);
28301
+ repoRoot = import_node_path27.default.dirname(absGitCommon);
28549
28302
  } catch {
28550
28303
  repoRoot = null;
28551
28304
  }
@@ -28557,7 +28310,7 @@ async function removeWorktree(input) {
28557
28310
  } catch (err) {
28558
28311
  const stderr = err.stderr ?? "";
28559
28312
  const lower = stderr.toLowerCase();
28560
- const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs26.default.existsSync(worktreeRoot);
28313
+ const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs25.default.existsSync(worktreeRoot);
28561
28314
  if (!vanished) {
28562
28315
  throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
28563
28316
  }
@@ -28576,10 +28329,10 @@ async function removeWorktree(input) {
28576
28329
  try {
28577
28330
  const encoded = encodeClaudeProjectDir(worktreeRoot);
28578
28331
  if (encoded) {
28579
- const projectsRoot = import_node_path28.default.join(import_node_os13.default.homedir(), ".claude", "projects");
28580
- const target = import_node_path28.default.resolve(projectsRoot, encoded);
28581
- if (target.startsWith(projectsRoot + import_node_path28.default.sep) && target !== projectsRoot) {
28582
- import_node_fs26.default.rmSync(target, { recursive: true, force: true });
28332
+ const projectsRoot = import_node_path27.default.join(import_node_os13.default.homedir(), ".claude", "projects");
28333
+ const target = import_node_path27.default.resolve(projectsRoot, encoded);
28334
+ if (target.startsWith(projectsRoot + import_node_path27.default.sep) && target !== projectsRoot) {
28335
+ import_node_fs25.default.rmSync(target, { recursive: true, force: true });
28583
28336
  }
28584
28337
  }
28585
28338
  } catch {
@@ -29016,7 +28769,7 @@ function buildMethodHandlers(deps) {
29016
28769
  async function startDaemon(config) {
29017
28770
  const logger = createLogger({
29018
28771
  level: config.logLevel,
29019
- file: import_node_path29.default.join(config.dataDir, "clawd.log")
28772
+ file: import_node_path28.default.join(config.dataDir, "clawd.log")
29020
28773
  });
29021
28774
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
29022
28775
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -29048,7 +28801,7 @@ async function startDaemon(config) {
29048
28801
  const agents = new AgentsScanner();
29049
28802
  const history = new ClaudeHistoryReader();
29050
28803
  let transport = null;
29051
- const personaStore = new PersonaStore(import_node_path29.default.join(config.dataDir, "personas"));
28804
+ const personaStore = new PersonaStore(import_node_path28.default.join(config.dataDir, "personas"));
29052
28805
  const defaultsRoot = findDefaultsRoot();
29053
28806
  if (defaultsRoot) {
29054
28807
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -29067,7 +28820,7 @@ async function startDaemon(config) {
29067
28820
  getAdapter,
29068
28821
  historyReader: history,
29069
28822
  dataDir: config.dataDir,
29070
- personaRoot: import_node_path29.default.join(config.dataDir, "personas"),
28823
+ personaRoot: import_node_path28.default.join(config.dataDir, "personas"),
29071
28824
  personaStore,
29072
28825
  ownerDisplayName,
29073
28826
  mode: config.mode,
@@ -29090,10 +28843,10 @@ async function startDaemon(config) {
29090
28843
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
29091
28844
  attachmentGroup: {
29092
28845
  onFileEdit: (input) => {
29093
- const absPath = import_node_path29.default.isAbsolute(input.relPath) ? input.relPath : import_node_path29.default.join(input.cwd, input.relPath);
28846
+ const absPath = import_node_path28.default.isAbsolute(input.relPath) ? input.relPath : import_node_path28.default.join(input.cwd, input.relPath);
29094
28847
  let size = 0;
29095
28848
  try {
29096
- size = import_node_fs27.default.statSync(absPath).size;
28849
+ size = import_node_fs26.default.statSync(absPath).size;
29097
28850
  } catch (err) {
29098
28851
  logger.warn("attachment.onFileEdit stat failed", {
29099
28852
  sessionId: input.sessionId,
@@ -29374,8 +29127,8 @@ async function startDaemon(config) {
29374
29127
  const lines = [
29375
29128
  `Tunnel: ${r.url}`,
29376
29129
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
29377
- `Frpc config: ${import_node_path29.default.join(config.dataDir, "frpc.toml")}`,
29378
- `Frpc log: ${import_node_path29.default.join(config.dataDir, "frpc.log")}`
29130
+ `Frpc config: ${import_node_path28.default.join(config.dataDir, "frpc.toml")}`,
29131
+ `Frpc log: ${import_node_path28.default.join(config.dataDir, "frpc.log")}`
29379
29132
  ];
29380
29133
  const width = Math.max(...lines.map((l) => l.length));
29381
29134
  const bar = "\u2550".repeat(width + 4);
@@ -29388,8 +29141,8 @@ ${bar}
29388
29141
 
29389
29142
  `);
29390
29143
  try {
29391
- const connectPath = import_node_path29.default.join(config.dataDir, "connect.txt");
29392
- import_node_fs27.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
29144
+ const connectPath = import_node_path28.default.join(config.dataDir, "connect.txt");
29145
+ import_node_fs26.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
29393
29146
  } catch {
29394
29147
  }
29395
29148
  } catch (err) {