@clawos-dev/clawd 0.2.86-beta.161.3250922 → 0.2.86

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 +472 -337
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -643,8 +643,8 @@ var init_parseUtil = __esm({
643
643
  init_errors2();
644
644
  init_en();
645
645
  makeIssue = (params) => {
646
- const { data, path: path45, errorMaps, issueData } = params;
647
- const fullPath = [...path45, ...issueData.path || []];
646
+ const { data, path: path46, errorMaps, issueData } = params;
647
+ const fullPath = [...path46, ...issueData.path || []];
648
648
  const fullIssue = {
649
649
  ...issueData,
650
650
  path: fullPath
@@ -955,11 +955,11 @@ var init_types = __esm({
955
955
  init_parseUtil();
956
956
  init_util();
957
957
  ParseInputLazyPath = class {
958
- constructor(parent, value, path45, key) {
958
+ constructor(parent, value, path46, key) {
959
959
  this._cachedPath = [];
960
960
  this.parent = parent;
961
961
  this.data = value;
962
- this._path = path45;
962
+ this._path = path46;
963
963
  this._key = key;
964
964
  }
965
965
  get path() {
@@ -5590,8 +5590,8 @@ var require_req = __commonJS({
5590
5590
  if (req.originalUrl) {
5591
5591
  _req.url = req.originalUrl;
5592
5592
  } else {
5593
- const path45 = req.path;
5594
- _req.url = typeof path45 === "string" ? path45 : req.url ? req.url.path || req.url : void 0;
5593
+ const path46 = req.path;
5594
+ _req.url = typeof path46 === "string" ? path46 : req.url ? req.url.path || req.url : void 0;
5595
5595
  }
5596
5596
  if (req.query) {
5597
5597
  _req.query = req.query;
@@ -5756,14 +5756,14 @@ var require_redact = __commonJS({
5756
5756
  }
5757
5757
  return obj;
5758
5758
  }
5759
- function parsePath(path45) {
5759
+ function parsePath(path46) {
5760
5760
  const parts = [];
5761
5761
  let current = "";
5762
5762
  let inBrackets = false;
5763
5763
  let inQuotes = false;
5764
5764
  let quoteChar = "";
5765
- for (let i = 0; i < path45.length; i++) {
5766
- const char = path45[i];
5765
+ for (let i = 0; i < path46.length; i++) {
5766
+ const char = path46[i];
5767
5767
  if (!inBrackets && char === ".") {
5768
5768
  if (current) {
5769
5769
  parts.push(current);
@@ -5894,10 +5894,10 @@ var require_redact = __commonJS({
5894
5894
  return current;
5895
5895
  }
5896
5896
  function redactPaths(obj, paths, censor, remove = false) {
5897
- for (const path45 of paths) {
5898
- const parts = parsePath(path45);
5897
+ for (const path46 of paths) {
5898
+ const parts = parsePath(path46);
5899
5899
  if (parts.includes("*")) {
5900
- redactWildcardPath(obj, parts, censor, path45, remove);
5900
+ redactWildcardPath(obj, parts, censor, path46, remove);
5901
5901
  } else {
5902
5902
  if (remove) {
5903
5903
  removeKey(obj, parts);
@@ -5982,8 +5982,8 @@ var require_redact = __commonJS({
5982
5982
  }
5983
5983
  } else {
5984
5984
  if (afterWildcard.includes("*")) {
5985
- const wrappedCensor = typeof censor === "function" ? (value, path45) => {
5986
- const fullPath = [...pathArray.slice(0, pathLength), ...path45];
5985
+ const wrappedCensor = typeof censor === "function" ? (value, path46) => {
5986
+ const fullPath = [...pathArray.slice(0, pathLength), ...path46];
5987
5987
  return censor(value, fullPath);
5988
5988
  } : censor;
5989
5989
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6018,8 +6018,8 @@ var require_redact = __commonJS({
6018
6018
  return null;
6019
6019
  }
6020
6020
  const pathStructure = /* @__PURE__ */ new Map();
6021
- for (const path45 of pathsToClone) {
6022
- const parts = parsePath(path45);
6021
+ for (const path46 of pathsToClone) {
6022
+ const parts = parsePath(path46);
6023
6023
  let current = pathStructure;
6024
6024
  for (let i = 0; i < parts.length; i++) {
6025
6025
  const part = parts[i];
@@ -6071,24 +6071,24 @@ var require_redact = __commonJS({
6071
6071
  }
6072
6072
  return cloneSelectively(obj, pathStructure);
6073
6073
  }
6074
- function validatePath(path45) {
6075
- if (typeof path45 !== "string") {
6074
+ function validatePath(path46) {
6075
+ if (typeof path46 !== "string") {
6076
6076
  throw new Error("Paths must be (non-empty) strings");
6077
6077
  }
6078
- if (path45 === "") {
6078
+ if (path46 === "") {
6079
6079
  throw new Error("Invalid redaction path ()");
6080
6080
  }
6081
- if (path45.includes("..")) {
6082
- throw new Error(`Invalid redaction path (${path45})`);
6081
+ if (path46.includes("..")) {
6082
+ throw new Error(`Invalid redaction path (${path46})`);
6083
6083
  }
6084
- if (path45.includes(",")) {
6085
- throw new Error(`Invalid redaction path (${path45})`);
6084
+ if (path46.includes(",")) {
6085
+ throw new Error(`Invalid redaction path (${path46})`);
6086
6086
  }
6087
6087
  let bracketCount = 0;
6088
6088
  let inQuotes = false;
6089
6089
  let quoteChar = "";
6090
- for (let i = 0; i < path45.length; i++) {
6091
- const char = path45[i];
6090
+ for (let i = 0; i < path46.length; i++) {
6091
+ const char = path46[i];
6092
6092
  if ((char === '"' || char === "'") && bracketCount > 0) {
6093
6093
  if (!inQuotes) {
6094
6094
  inQuotes = true;
@@ -6102,20 +6102,20 @@ var require_redact = __commonJS({
6102
6102
  } else if (char === "]" && !inQuotes) {
6103
6103
  bracketCount--;
6104
6104
  if (bracketCount < 0) {
6105
- throw new Error(`Invalid redaction path (${path45})`);
6105
+ throw new Error(`Invalid redaction path (${path46})`);
6106
6106
  }
6107
6107
  }
6108
6108
  }
6109
6109
  if (bracketCount !== 0) {
6110
- throw new Error(`Invalid redaction path (${path45})`);
6110
+ throw new Error(`Invalid redaction path (${path46})`);
6111
6111
  }
6112
6112
  }
6113
6113
  function validatePaths(paths) {
6114
6114
  if (!Array.isArray(paths)) {
6115
6115
  throw new TypeError("paths must be an array");
6116
6116
  }
6117
- for (const path45 of paths) {
6118
- validatePath(path45);
6117
+ for (const path46 of paths) {
6118
+ validatePath(path46);
6119
6119
  }
6120
6120
  }
6121
6121
  function slowRedact(options = {}) {
@@ -6283,8 +6283,8 @@ var require_redaction = __commonJS({
6283
6283
  if (shape[k2] === null) {
6284
6284
  o[k2] = (value) => topCensor(value, [k2]);
6285
6285
  } else {
6286
- const wrappedCensor = typeof censor === "function" ? (value, path45) => {
6287
- return censor(value, [k2, ...path45]);
6286
+ const wrappedCensor = typeof censor === "function" ? (value, path46) => {
6287
+ return censor(value, [k2, ...path46]);
6288
6288
  } : censor;
6289
6289
  o[k2] = Redact({
6290
6290
  paths: shape[k2],
@@ -6502,10 +6502,10 @@ var require_atomic_sleep = __commonJS({
6502
6502
  var require_sonic_boom = __commonJS({
6503
6503
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
6504
6504
  "use strict";
6505
- var fs36 = require("fs");
6505
+ var fs37 = require("fs");
6506
6506
  var EventEmitter2 = require("events");
6507
6507
  var inherits = require("util").inherits;
6508
- var path45 = require("path");
6508
+ var path46 = require("path");
6509
6509
  var sleep = require_atomic_sleep();
6510
6510
  var assert = require("assert");
6511
6511
  var BUSY_WRITE_TIMEOUT = 100;
@@ -6559,20 +6559,20 @@ var require_sonic_boom = __commonJS({
6559
6559
  const mode = sonic.mode;
6560
6560
  if (sonic.sync) {
6561
6561
  try {
6562
- if (sonic.mkdir) fs36.mkdirSync(path45.dirname(file), { recursive: true });
6563
- const fd = fs36.openSync(file, flags, mode);
6562
+ if (sonic.mkdir) fs37.mkdirSync(path46.dirname(file), { recursive: true });
6563
+ const fd = fs37.openSync(file, flags, mode);
6564
6564
  fileOpened(null, fd);
6565
6565
  } catch (err) {
6566
6566
  fileOpened(err);
6567
6567
  throw err;
6568
6568
  }
6569
6569
  } else if (sonic.mkdir) {
6570
- fs36.mkdir(path45.dirname(file), { recursive: true }, (err) => {
6570
+ fs37.mkdir(path46.dirname(file), { recursive: true }, (err) => {
6571
6571
  if (err) return fileOpened(err);
6572
- fs36.open(file, flags, mode, fileOpened);
6572
+ fs37.open(file, flags, mode, fileOpened);
6573
6573
  });
6574
6574
  } else {
6575
- fs36.open(file, flags, mode, fileOpened);
6575
+ fs37.open(file, flags, mode, fileOpened);
6576
6576
  }
6577
6577
  }
6578
6578
  function SonicBoom(opts) {
@@ -6613,8 +6613,8 @@ var require_sonic_boom = __commonJS({
6613
6613
  this.flush = flushBuffer;
6614
6614
  this.flushSync = flushBufferSync;
6615
6615
  this._actualWrite = actualWriteBuffer;
6616
- fsWriteSync = () => fs36.writeSync(this.fd, this._writingBuf);
6617
- fsWrite = () => fs36.write(this.fd, this._writingBuf, this.release);
6616
+ fsWriteSync = () => fs37.writeSync(this.fd, this._writingBuf);
6617
+ fsWrite = () => fs37.write(this.fd, this._writingBuf, this.release);
6618
6618
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
6619
6619
  this._writingBuf = "";
6620
6620
  this.write = write;
@@ -6623,15 +6623,15 @@ var require_sonic_boom = __commonJS({
6623
6623
  this._actualWrite = actualWrite;
6624
6624
  fsWriteSync = () => {
6625
6625
  if (Buffer.isBuffer(this._writingBuf)) {
6626
- return fs36.writeSync(this.fd, this._writingBuf);
6626
+ return fs37.writeSync(this.fd, this._writingBuf);
6627
6627
  }
6628
- return fs36.writeSync(this.fd, this._writingBuf, "utf8");
6628
+ return fs37.writeSync(this.fd, this._writingBuf, "utf8");
6629
6629
  };
6630
6630
  fsWrite = () => {
6631
6631
  if (Buffer.isBuffer(this._writingBuf)) {
6632
- return fs36.write(this.fd, this._writingBuf, this.release);
6632
+ return fs37.write(this.fd, this._writingBuf, this.release);
6633
6633
  }
6634
- return fs36.write(this.fd, this._writingBuf, "utf8", this.release);
6634
+ return fs37.write(this.fd, this._writingBuf, "utf8", this.release);
6635
6635
  };
6636
6636
  } else {
6637
6637
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -6688,7 +6688,7 @@ var require_sonic_boom = __commonJS({
6688
6688
  }
6689
6689
  }
6690
6690
  if (this._fsync) {
6691
- fs36.fsyncSync(this.fd);
6691
+ fs37.fsyncSync(this.fd);
6692
6692
  }
6693
6693
  const len = this._len;
6694
6694
  if (this._reopening) {
@@ -6802,7 +6802,7 @@ var require_sonic_boom = __commonJS({
6802
6802
  const onDrain = () => {
6803
6803
  if (!this._fsync) {
6804
6804
  try {
6805
- fs36.fsync(this.fd, (err) => {
6805
+ fs37.fsync(this.fd, (err) => {
6806
6806
  this._flushPending = false;
6807
6807
  cb(err);
6808
6808
  });
@@ -6904,7 +6904,7 @@ var require_sonic_boom = __commonJS({
6904
6904
  const fd = this.fd;
6905
6905
  this.once("ready", () => {
6906
6906
  if (fd !== this.fd) {
6907
- fs36.close(fd, (err) => {
6907
+ fs37.close(fd, (err) => {
6908
6908
  if (err) {
6909
6909
  return this.emit("error", err);
6910
6910
  }
@@ -6953,7 +6953,7 @@ var require_sonic_boom = __commonJS({
6953
6953
  buf = this._bufs[0];
6954
6954
  }
6955
6955
  try {
6956
- const n = Buffer.isBuffer(buf) ? fs36.writeSync(this.fd, buf) : fs36.writeSync(this.fd, buf, "utf8");
6956
+ const n = Buffer.isBuffer(buf) ? fs37.writeSync(this.fd, buf) : fs37.writeSync(this.fd, buf, "utf8");
6957
6957
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
6958
6958
  buf = releasedBufObj.writingBuf;
6959
6959
  this._len = releasedBufObj.len;
@@ -6969,7 +6969,7 @@ var require_sonic_boom = __commonJS({
6969
6969
  }
6970
6970
  }
6971
6971
  try {
6972
- fs36.fsyncSync(this.fd);
6972
+ fs37.fsyncSync(this.fd);
6973
6973
  } catch {
6974
6974
  }
6975
6975
  }
@@ -6990,7 +6990,7 @@ var require_sonic_boom = __commonJS({
6990
6990
  buf = mergeBuf(this._bufs[0], this._lens[0]);
6991
6991
  }
6992
6992
  try {
6993
- const n = fs36.writeSync(this.fd, buf);
6993
+ const n = fs37.writeSync(this.fd, buf);
6994
6994
  buf = buf.subarray(n);
6995
6995
  this._len = Math.max(this._len - n, 0);
6996
6996
  if (buf.length <= 0) {
@@ -7018,13 +7018,13 @@ var require_sonic_boom = __commonJS({
7018
7018
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7019
7019
  if (this.sync) {
7020
7020
  try {
7021
- const written = Buffer.isBuffer(this._writingBuf) ? fs36.writeSync(this.fd, this._writingBuf) : fs36.writeSync(this.fd, this._writingBuf, "utf8");
7021
+ const written = Buffer.isBuffer(this._writingBuf) ? fs37.writeSync(this.fd, this._writingBuf) : fs37.writeSync(this.fd, this._writingBuf, "utf8");
7022
7022
  release(null, written);
7023
7023
  } catch (err) {
7024
7024
  release(err);
7025
7025
  }
7026
7026
  } else {
7027
- fs36.write(this.fd, this._writingBuf, release);
7027
+ fs37.write(this.fd, this._writingBuf, release);
7028
7028
  }
7029
7029
  }
7030
7030
  function actualWriteBuffer() {
@@ -7033,7 +7033,7 @@ var require_sonic_boom = __commonJS({
7033
7033
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7034
7034
  if (this.sync) {
7035
7035
  try {
7036
- const written = fs36.writeSync(this.fd, this._writingBuf);
7036
+ const written = fs37.writeSync(this.fd, this._writingBuf);
7037
7037
  release(null, written);
7038
7038
  } catch (err) {
7039
7039
  release(err);
@@ -7042,7 +7042,7 @@ var require_sonic_boom = __commonJS({
7042
7042
  if (kCopyBuffer) {
7043
7043
  this._writingBuf = Buffer.from(this._writingBuf);
7044
7044
  }
7045
- fs36.write(this.fd, this._writingBuf, release);
7045
+ fs37.write(this.fd, this._writingBuf, release);
7046
7046
  }
7047
7047
  }
7048
7048
  function actualClose(sonic) {
@@ -7058,12 +7058,12 @@ var require_sonic_boom = __commonJS({
7058
7058
  sonic._lens = [];
7059
7059
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7060
7060
  try {
7061
- fs36.fsync(sonic.fd, closeWrapped);
7061
+ fs37.fsync(sonic.fd, closeWrapped);
7062
7062
  } catch {
7063
7063
  }
7064
7064
  function closeWrapped() {
7065
7065
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7066
- fs36.close(sonic.fd, done);
7066
+ fs37.close(sonic.fd, done);
7067
7067
  } else {
7068
7068
  done();
7069
7069
  }
@@ -9427,7 +9427,7 @@ var require_multistream = __commonJS({
9427
9427
  var require_pino = __commonJS({
9428
9428
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
9429
9429
  "use strict";
9430
- var os16 = require("os");
9430
+ var os17 = require("os");
9431
9431
  var stdSerializers = require_pino_std_serializers();
9432
9432
  var caller = require_caller();
9433
9433
  var redaction = require_redaction();
@@ -9474,7 +9474,7 @@ var require_pino = __commonJS({
9474
9474
  } = symbols;
9475
9475
  var { epochTime, nullTime } = time;
9476
9476
  var { pid } = process;
9477
- var hostname = os16.hostname();
9477
+ var hostname = os17.hostname();
9478
9478
  var defaultErrorSerializer = stdSerializers.err;
9479
9479
  var defaultOptions = {
9480
9480
  level: "info",
@@ -10198,11 +10198,11 @@ var init_lib = __esm({
10198
10198
  }
10199
10199
  }
10200
10200
  },
10201
- addToPath: function addToPath(path45, added, removed, oldPosInc, options) {
10202
- var last = path45.lastComponent;
10201
+ addToPath: function addToPath(path46, added, removed, oldPosInc, options) {
10202
+ var last = path46.lastComponent;
10203
10203
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
10204
10204
  return {
10205
- oldPos: path45.oldPos + oldPosInc,
10205
+ oldPos: path46.oldPos + oldPosInc,
10206
10206
  lastComponent: {
10207
10207
  count: last.count + 1,
10208
10208
  added,
@@ -10212,7 +10212,7 @@ var init_lib = __esm({
10212
10212
  };
10213
10213
  } else {
10214
10214
  return {
10215
- oldPos: path45.oldPos + oldPosInc,
10215
+ oldPos: path46.oldPos + oldPosInc,
10216
10216
  lastComponent: {
10217
10217
  count: 1,
10218
10218
  added,
@@ -10643,10 +10643,10 @@ function attachmentToHistoryMessage(o, ts) {
10643
10643
  const memories = raw.map((m2) => {
10644
10644
  if (!m2 || typeof m2 !== "object") return null;
10645
10645
  const rec = m2;
10646
- const path45 = typeof rec.path === "string" ? rec.path : null;
10646
+ const path46 = typeof rec.path === "string" ? rec.path : null;
10647
10647
  const content = typeof rec.content === "string" ? rec.content : null;
10648
- if (!path45 || content == null) return null;
10649
- const entry = { path: path45, content };
10648
+ if (!path46 || content == null) return null;
10649
+ const entry = { path: path46, content };
10650
10650
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
10651
10651
  return entry;
10652
10652
  }).filter((m2) => m2 !== null);
@@ -11472,10 +11472,10 @@ function parseAttachment(obj) {
11472
11472
  const memories = raw.map((m2) => {
11473
11473
  if (!m2 || typeof m2 !== "object") return null;
11474
11474
  const rec = m2;
11475
- const path45 = typeof rec.path === "string" ? rec.path : null;
11475
+ const path46 = typeof rec.path === "string" ? rec.path : null;
11476
11476
  const content = typeof rec.content === "string" ? rec.content : null;
11477
- if (!path45 || content == null) return null;
11478
- const out = { path: path45, content };
11477
+ if (!path46 || content == null) return null;
11478
+ const out = { path: path46, content };
11479
11479
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
11480
11480
  return out;
11481
11481
  }).filter((m2) => m2 !== null);
@@ -20390,7 +20390,7 @@ var require_websocket_server = __commonJS({
20390
20390
  // src/run-case/recorder.ts
20391
20391
  function startRunCaseRecorder(opts) {
20392
20392
  const now = opts.now ?? Date.now;
20393
- const dir = import_node_path31.default.dirname(opts.recordPath);
20393
+ const dir = import_node_path32.default.dirname(opts.recordPath);
20394
20394
  let stream = null;
20395
20395
  let closing = false;
20396
20396
  let closedSettled = false;
@@ -20404,8 +20404,8 @@ function startRunCaseRecorder(opts) {
20404
20404
  });
20405
20405
  const ensureStream = () => {
20406
20406
  if (stream) return stream;
20407
- import_node_fs28.default.mkdirSync(dir, { recursive: true });
20408
- stream = import_node_fs28.default.createWriteStream(opts.recordPath, { flags: "a" });
20407
+ import_node_fs29.default.mkdirSync(dir, { recursive: true });
20408
+ stream = import_node_fs29.default.createWriteStream(opts.recordPath, { flags: "a" });
20409
20409
  stream.on("close", () => closedResolve());
20410
20410
  return stream;
20411
20411
  };
@@ -20430,12 +20430,12 @@ function startRunCaseRecorder(opts) {
20430
20430
  };
20431
20431
  return { tap, close, closed };
20432
20432
  }
20433
- var import_node_fs28, import_node_path31;
20433
+ var import_node_fs29, import_node_path32;
20434
20434
  var init_recorder = __esm({
20435
20435
  "src/run-case/recorder.ts"() {
20436
20436
  "use strict";
20437
- import_node_fs28 = __toESM(require("fs"), 1);
20438
- import_node_path31 = __toESM(require("path"), 1);
20437
+ import_node_fs29 = __toESM(require("fs"), 1);
20438
+ import_node_path32 = __toESM(require("path"), 1);
20439
20439
  }
20440
20440
  });
20441
20441
 
@@ -20478,7 +20478,7 @@ var init_wire = __esm({
20478
20478
  // src/run-case/controller.ts
20479
20479
  async function runController(opts) {
20480
20480
  const now = opts.now ?? Date.now;
20481
- const cwd = opts.cwd ?? (0, import_node_fs29.mkdtempSync)(import_node_path32.default.join(import_node_os14.default.tmpdir(), "clawd-runcase-"));
20481
+ const cwd = opts.cwd ?? (0, import_node_fs30.mkdtempSync)(import_node_path33.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
20482
20482
  const ownsCwd = opts.cwd === void 0;
20483
20483
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
20484
20484
  const spawnCtx = { cwd };
@@ -20639,19 +20639,19 @@ async function runController(opts) {
20639
20639
  if (sigintHandler) process.off("SIGINT", sigintHandler);
20640
20640
  if (ownsCwd) {
20641
20641
  try {
20642
- (0, import_node_fs29.rmSync)(cwd, { recursive: true, force: true });
20642
+ (0, import_node_fs30.rmSync)(cwd, { recursive: true, force: true });
20643
20643
  } catch {
20644
20644
  }
20645
20645
  }
20646
20646
  return exitCode ?? 0;
20647
20647
  }
20648
- var import_node_fs29, import_node_os14, import_node_path32;
20648
+ var import_node_fs30, import_node_os15, import_node_path33;
20649
20649
  var init_controller = __esm({
20650
20650
  "src/run-case/controller.ts"() {
20651
20651
  "use strict";
20652
- import_node_fs29 = require("fs");
20653
- import_node_os14 = __toESM(require("os"), 1);
20654
- import_node_path32 = __toESM(require("path"), 1);
20652
+ import_node_fs30 = require("fs");
20653
+ import_node_os15 = __toESM(require("os"), 1);
20654
+ import_node_path33 = __toESM(require("path"), 1);
20655
20655
  init_claude();
20656
20656
  init_stdout_splitter();
20657
20657
  init_permission_stdio();
@@ -20883,8 +20883,8 @@ Env (advanced):
20883
20883
  `;
20884
20884
 
20885
20885
  // src/index.ts
20886
- var import_node_path30 = __toESM(require("path"), 1);
20887
- var import_node_fs27 = __toESM(require("fs"), 1);
20886
+ var import_node_path31 = __toESM(require("path"), 1);
20887
+ var import_node_fs28 = __toESM(require("fs"), 1);
20888
20888
 
20889
20889
  // src/logger.ts
20890
20890
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -25531,11 +25531,18 @@ var AgentsScanner = class {
25531
25531
  };
25532
25532
 
25533
25533
  // src/observer/session-observer.ts
25534
+ var import_node_fs13 = __toESM(require("fs"), 1);
25535
+ var import_node_os9 = __toESM(require("os"), 1);
25536
+ var import_node_path14 = __toESM(require("path"), 1);
25537
+ init_claude_history();
25538
+
25539
+ // src/observer/subagent-meta-observer.ts
25534
25540
  var import_node_fs12 = __toESM(require("fs"), 1);
25535
25541
  var import_node_os8 = __toESM(require("os"), 1);
25536
25542
  var import_node_path13 = __toESM(require("path"), 1);
25537
25543
  init_claude_history();
25538
- var SessionObserver = class {
25544
+ var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
25545
+ var SubagentMetaObserver = class {
25539
25546
  constructor(opts) {
25540
25547
  this.opts = opts;
25541
25548
  this.home = opts.home ?? import_node_os8.default.homedir();
@@ -25543,16 +25550,132 @@ var SessionObserver = class {
25543
25550
  opts;
25544
25551
  home;
25545
25552
  watches = /* @__PURE__ */ new Map();
25553
+ // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
25554
+ resolveSubagentDir(cwd, toolSessionId) {
25555
+ return import_node_path13.default.join(
25556
+ this.home,
25557
+ ".claude",
25558
+ "projects",
25559
+ cwdToHashDir(cwd),
25560
+ toolSessionId,
25561
+ "subagents"
25562
+ );
25563
+ }
25564
+ start(args) {
25565
+ this.stop(args.sessionId);
25566
+ const dirPath = this.resolveSubagentDir(args.cwd, args.toolSessionId);
25567
+ const w2 = {
25568
+ sessionId: args.sessionId,
25569
+ dirPath,
25570
+ watcher: null,
25571
+ pollTimer: null,
25572
+ emitted: /* @__PURE__ */ new Set()
25573
+ };
25574
+ this.watches.set(args.sessionId, w2);
25575
+ this.scan(w2);
25576
+ this.attachWatcher(w2);
25577
+ w2.pollTimer = setInterval(() => this.scan(w2), 200);
25578
+ return { dirPath };
25579
+ }
25580
+ // fs.watch 必须在目录存在后调用;首次启动时 subagents/ 通常不存在 —— attachWatcher
25581
+ // 失败就交给 pollTimer 200ms 兜底,目录一出现就被下次 poll 捡起来,那时也尝试 attach
25582
+ attachWatcher(w2) {
25583
+ if (w2.watcher) return;
25584
+ try {
25585
+ w2.watcher = import_node_fs12.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
25586
+ if (!name) return;
25587
+ const m2 = META_RE.exec(String(name));
25588
+ if (!m2) return;
25589
+ this.scanOne(w2, String(name));
25590
+ });
25591
+ } catch {
25592
+ }
25593
+ }
25594
+ scan(w2) {
25595
+ let entries;
25596
+ try {
25597
+ entries = import_node_fs12.default.readdirSync(w2.dirPath);
25598
+ } catch {
25599
+ return;
25600
+ }
25601
+ if (!w2.watcher) this.attachWatcher(w2);
25602
+ for (const name of entries) {
25603
+ this.scanOne(w2, name);
25604
+ }
25605
+ }
25606
+ scanOne(w2, name) {
25607
+ const m2 = META_RE.exec(name);
25608
+ if (!m2) return;
25609
+ const agentId = m2[1];
25610
+ if (w2.emitted.has(agentId)) return;
25611
+ const file = import_node_path13.default.join(w2.dirPath, name);
25612
+ let raw;
25613
+ try {
25614
+ raw = import_node_fs12.default.readFileSync(file, "utf8");
25615
+ } catch {
25616
+ return;
25617
+ }
25618
+ let obj;
25619
+ try {
25620
+ obj = JSON.parse(raw);
25621
+ } catch {
25622
+ return;
25623
+ }
25624
+ const toolUseId = typeof obj.toolUseId === "string" ? obj.toolUseId : "";
25625
+ if (!toolUseId) return;
25626
+ w2.emitted.add(agentId);
25627
+ const ev = {
25628
+ kind: "subagent_progress",
25629
+ toolUseId,
25630
+ agentId,
25631
+ status: "started"
25632
+ };
25633
+ if (typeof obj.description === "string" && obj.description) ev.description = obj.description;
25634
+ this.opts.onEvent({ sessionId: w2.sessionId, events: [ev] });
25635
+ }
25636
+ isObserving(sessionId) {
25637
+ return this.watches.has(sessionId);
25638
+ }
25639
+ stop(sessionId) {
25640
+ const w2 = this.watches.get(sessionId);
25641
+ if (!w2) return false;
25642
+ try {
25643
+ w2.watcher?.close();
25644
+ } catch {
25645
+ }
25646
+ if (w2.pollTimer) clearInterval(w2.pollTimer);
25647
+ this.watches.delete(sessionId);
25648
+ return true;
25649
+ }
25650
+ stopAll() {
25651
+ for (const id of [...this.watches.keys()]) this.stop(id);
25652
+ }
25653
+ };
25654
+
25655
+ // src/observer/session-observer.ts
25656
+ var SessionObserver = class {
25657
+ constructor(opts) {
25658
+ this.opts = opts;
25659
+ this.home = opts.home ?? import_node_os9.default.homedir();
25660
+ this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
25661
+ }
25662
+ opts;
25663
+ home;
25664
+ watches = /* @__PURE__ */ new Map();
25665
+ // 子 observer:监听 <projectsRoot>/<hashDir>/<toolSessionId>/subagents/ 目录的 meta.json,
25666
+ // 仅 TUI 模式启用——SDK 模式靠 `system.task_started` 帧(claude.ts:466)emit subagent_progress
25667
+ // 已经能解锁 AgentCallLine 抽屉入口,再跑 meta watcher 会让 ring buffer 留双帧
25668
+ metaObserver;
25546
25669
  resolveJsonlPath(cwd, toolSessionId, override) {
25547
25670
  if (override) return override;
25548
- return import_node_path13.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
25671
+ return import_node_path14.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
25549
25672
  }
25550
25673
  start(args) {
25551
25674
  this.stop(args.sessionId);
25552
25675
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
25553
25676
  let size = 0;
25554
25677
  try {
25555
- size = import_node_fs12.default.statSync(filePath).size;
25678
+ size = import_node_fs13.default.statSync(filePath).size;
25556
25679
  } catch {
25557
25680
  }
25558
25681
  const w2 = {
@@ -25565,10 +25688,10 @@ var SessionObserver = class {
25565
25688
  adapter: args.adapter
25566
25689
  };
25567
25690
  try {
25568
- import_node_fs12.default.mkdirSync(import_node_path13.default.dirname(filePath), { recursive: true });
25691
+ import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
25569
25692
  } catch {
25570
25693
  }
25571
- w2.watcher = import_node_fs12.default.watch(import_node_path13.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
25694
+ w2.watcher = import_node_fs13.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
25572
25695
  if (!changedName || !filePath.endsWith(changedName)) return;
25573
25696
  this.poll(w2);
25574
25697
  });
@@ -25577,6 +25700,11 @@ var SessionObserver = class {
25577
25700
  this.opts.onStatus?.(args.sessionId, "observing");
25578
25701
  this.hydrateMetaTail(w2);
25579
25702
  this.poll(w2);
25703
+ this.metaObserver?.start({
25704
+ sessionId: args.sessionId,
25705
+ cwd: args.cwd,
25706
+ toolSessionId: args.toolSessionId
25707
+ });
25580
25708
  return { filePath };
25581
25709
  }
25582
25710
  // 读 JSONL 文件尾部 N 行,把每行的 meta_update 字段**合并成一个 patch** 喂给 reducer。
@@ -25586,7 +25714,7 @@ var SessionObserver = class {
25586
25714
  // 异常静默吞,不阻塞 watcher 启动
25587
25715
  hydrateMetaTail(w2, maxLines = 200) {
25588
25716
  try {
25589
- const raw = import_node_fs12.default.readFileSync(w2.filePath, "utf8");
25717
+ const raw = import_node_fs13.default.readFileSync(w2.filePath, "utf8");
25590
25718
  if (!raw) return;
25591
25719
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
25592
25720
  if (allLines.length === 0) return;
@@ -25610,7 +25738,7 @@ var SessionObserver = class {
25610
25738
  poll(w2) {
25611
25739
  let size = 0;
25612
25740
  try {
25613
- size = import_node_fs12.default.statSync(w2.filePath).size;
25741
+ size = import_node_fs13.default.statSync(w2.filePath).size;
25614
25742
  } catch {
25615
25743
  return;
25616
25744
  }
@@ -25619,11 +25747,11 @@ var SessionObserver = class {
25619
25747
  w2.buf = "";
25620
25748
  }
25621
25749
  if (size === w2.lastSize) return;
25622
- const fd = import_node_fs12.default.openSync(w2.filePath, "r");
25750
+ const fd = import_node_fs13.default.openSync(w2.filePath, "r");
25623
25751
  try {
25624
25752
  const len = size - w2.lastSize;
25625
25753
  const buf = Buffer.alloc(len);
25626
- import_node_fs12.default.readSync(fd, buf, 0, len, w2.lastSize);
25754
+ import_node_fs13.default.readSync(fd, buf, 0, len, w2.lastSize);
25627
25755
  w2.lastSize = size;
25628
25756
  w2.buf += buf.toString("utf8");
25629
25757
  let newlineIndex;
@@ -25637,7 +25765,7 @@ var SessionObserver = class {
25637
25765
  }
25638
25766
  }
25639
25767
  } finally {
25640
- import_node_fs12.default.closeSync(fd);
25768
+ import_node_fs13.default.closeSync(fd);
25641
25769
  }
25642
25770
  }
25643
25771
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -25690,11 +25818,13 @@ var SessionObserver = class {
25690
25818
  }
25691
25819
  if (w2.pollTimer) clearInterval(w2.pollTimer);
25692
25820
  this.watches.delete(sessionId);
25821
+ this.metaObserver?.stop(sessionId);
25693
25822
  this.opts.onStatus?.(sessionId, "stopped");
25694
25823
  return true;
25695
25824
  }
25696
25825
  stopAll() {
25697
25826
  for (const id of [...this.watches.keys()]) this.stop(id);
25827
+ this.metaObserver?.stopAll();
25698
25828
  }
25699
25829
  };
25700
25830
 
@@ -26295,14 +26425,14 @@ function authenticate(token, deps) {
26295
26425
  }
26296
26426
 
26297
26427
  // src/permission/capability-store.ts
26298
- var fs15 = __toESM(require("fs"), 1);
26299
- var path18 = __toESM(require("path"), 1);
26428
+ var fs16 = __toESM(require("fs"), 1);
26429
+ var path19 = __toESM(require("path"), 1);
26300
26430
  var CAPABILITIES_FILE_NAME = "capabilities.json";
26301
26431
  var FILE_VERSION = 1;
26302
26432
  var CapabilityStore = class {
26303
26433
  constructor(dataDir) {
26304
26434
  this.dataDir = dataDir;
26305
- fs15.mkdirSync(dataDir, { recursive: true });
26435
+ fs16.mkdirSync(dataDir, { recursive: true });
26306
26436
  this.cache = this.readFromDisk();
26307
26437
  }
26308
26438
  dataDir;
@@ -26326,13 +26456,13 @@ var CapabilityStore = class {
26326
26456
  this.flush();
26327
26457
  }
26328
26458
  filePath() {
26329
- return path18.join(this.dataDir, CAPABILITIES_FILE_NAME);
26459
+ return path19.join(this.dataDir, CAPABILITIES_FILE_NAME);
26330
26460
  }
26331
26461
  readFromDisk() {
26332
26462
  const file = this.filePath();
26333
26463
  let raw;
26334
26464
  try {
26335
- raw = fs15.readFileSync(file, "utf8");
26465
+ raw = fs16.readFileSync(file, "utf8");
26336
26466
  } catch (err) {
26337
26467
  if (err?.code === "ENOENT") return [];
26338
26468
  return [];
@@ -26360,10 +26490,10 @@ var CapabilityStore = class {
26360
26490
  }
26361
26491
  atomicWrite(file, content) {
26362
26492
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26363
- fs15.writeFileSync(tmp, content, { mode: 384 });
26364
- fs15.renameSync(tmp, file);
26493
+ fs16.writeFileSync(tmp, content, { mode: 384 });
26494
+ fs16.renameSync(tmp, file);
26365
26495
  try {
26366
- fs15.chmodSync(file, 384);
26496
+ fs16.chmodSync(file, 384);
26367
26497
  } catch {
26368
26498
  }
26369
26499
  }
@@ -26456,14 +26586,14 @@ var CapabilityManager = class {
26456
26586
  };
26457
26587
 
26458
26588
  // src/permission/cleanup.ts
26459
- var fs16 = __toESM(require("fs"), 1);
26589
+ var fs17 = __toESM(require("fs"), 1);
26460
26590
  function cleanupGuestSessionsForCapability(cap, factory) {
26461
26591
  const removed = [];
26462
26592
  for (const g2 of cap.grants) {
26463
26593
  if (g2.resource.type !== "persona") continue;
26464
26594
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
26465
26595
  try {
26466
- fs16.rmSync(dir, { recursive: true, force: true });
26596
+ fs17.rmSync(dir, { recursive: true, force: true });
26467
26597
  removed.push(dir);
26468
26598
  } catch {
26469
26599
  }
@@ -26472,13 +26602,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
26472
26602
  }
26473
26603
 
26474
26604
  // src/permission/personal-capability.ts
26475
- var import_node_fs13 = __toESM(require("fs"), 1);
26476
- var import_node_path14 = __toESM(require("path"), 1);
26605
+ var import_node_fs14 = __toESM(require("fs"), 1);
26606
+ var import_node_path15 = __toESM(require("path"), 1);
26477
26607
  var import_node_crypto4 = __toESM(require("crypto"), 1);
26478
26608
  var PERSONAL_CAP_FILE_NAME = "personal-capability.json";
26479
26609
  var PERSONAL_CAP_DISPLAY_NAME = "personal";
26480
26610
  function personalCapFilePath(dataDir) {
26481
- return import_node_path14.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
26611
+ return import_node_path15.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
26482
26612
  }
26483
26613
  function loadOrCreatePersonalCapability(opts) {
26484
26614
  const file = personalCapFilePath(opts.dataDir);
@@ -26508,7 +26638,7 @@ function loadOrCreatePersonalCapability(opts) {
26508
26638
  function readFile(file) {
26509
26639
  let raw;
26510
26640
  try {
26511
- raw = import_node_fs13.default.readFileSync(file, "utf8");
26641
+ raw = import_node_fs14.default.readFileSync(file, "utf8");
26512
26642
  } catch (err) {
26513
26643
  const code = err?.code;
26514
26644
  if (code === "ENOENT") return null;
@@ -26529,10 +26659,10 @@ function readFile(file) {
26529
26659
  return { token: obj.token, capability: capParsed.data };
26530
26660
  }
26531
26661
  function writeFile(file, content) {
26532
- import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
26533
- import_node_fs13.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
26662
+ import_node_fs14.default.mkdirSync(import_node_path15.default.dirname(file), { recursive: true });
26663
+ import_node_fs14.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
26534
26664
  try {
26535
- import_node_fs13.default.chmodSync(file, 384);
26665
+ import_node_fs14.default.chmodSync(file, 384);
26536
26666
  } catch {
26537
26667
  }
26538
26668
  }
@@ -26547,13 +26677,13 @@ function sha256Hex2(s) {
26547
26677
  }
26548
26678
 
26549
26679
  // src/inbox/inbox-store.ts
26550
- var fs18 = __toESM(require("fs"), 1);
26551
- var path20 = __toESM(require("path"), 1);
26680
+ var fs19 = __toESM(require("fs"), 1);
26681
+ var path21 = __toESM(require("path"), 1);
26552
26682
  var INBOX_SUBDIR = "inbox";
26553
26683
  var InboxStore = class {
26554
26684
  constructor(dataDir) {
26555
26685
  this.dataDir = dataDir;
26556
- fs18.mkdirSync(this.dirPath(), { recursive: true });
26686
+ fs19.mkdirSync(this.dirPath(), { recursive: true });
26557
26687
  }
26558
26688
  dataDir;
26559
26689
  /**
@@ -26565,7 +26695,7 @@ var InboxStore = class {
26565
26695
  const file = this.filePath(peerOwnerId);
26566
26696
  let raw;
26567
26697
  try {
26568
- raw = fs18.readFileSync(file, "utf8");
26698
+ raw = fs19.readFileSync(file, "utf8");
26569
26699
  } catch (err) {
26570
26700
  if (err?.code === "ENOENT") return [];
26571
26701
  return [];
@@ -26581,7 +26711,7 @@ var InboxStore = class {
26581
26711
  const dir = this.dirPath();
26582
26712
  let entries;
26583
26713
  try {
26584
- entries = fs18.readdirSync(dir);
26714
+ entries = fs19.readdirSync(dir);
26585
26715
  } catch (err) {
26586
26716
  if (err?.code === "ENOENT") return [];
26587
26717
  return [];
@@ -26597,9 +26727,9 @@ var InboxStore = class {
26597
26727
  if (existing.some((m2) => m2.id === message.id)) return;
26598
26728
  const file = this.filePath(message.peerOwnerId);
26599
26729
  const line = JSON.stringify(message) + "\n";
26600
- fs18.appendFileSync(file, line, { mode: 384 });
26730
+ fs19.appendFileSync(file, line, { mode: 384 });
26601
26731
  try {
26602
- fs18.chmodSync(file, 384);
26732
+ fs19.chmodSync(file, 384);
26603
26733
  } catch {
26604
26734
  }
26605
26735
  }
@@ -26629,7 +26759,7 @@ var InboxStore = class {
26629
26759
  removeByPeerOwnerId(peerOwnerId) {
26630
26760
  const file = this.filePath(peerOwnerId);
26631
26761
  try {
26632
- fs18.unlinkSync(file);
26762
+ fs19.unlinkSync(file);
26633
26763
  } catch (err) {
26634
26764
  if (err?.code === "ENOENT") return;
26635
26765
  }
@@ -26638,18 +26768,18 @@ var InboxStore = class {
26638
26768
  const file = this.filePath(peerOwnerId);
26639
26769
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
26640
26770
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
26641
- fs18.writeFileSync(tmp, content, { mode: 384 });
26642
- fs18.renameSync(tmp, file);
26771
+ fs19.writeFileSync(tmp, content, { mode: 384 });
26772
+ fs19.renameSync(tmp, file);
26643
26773
  try {
26644
- fs18.chmodSync(file, 384);
26774
+ fs19.chmodSync(file, 384);
26645
26775
  } catch {
26646
26776
  }
26647
26777
  }
26648
26778
  dirPath() {
26649
- return path20.join(this.dataDir, INBOX_SUBDIR);
26779
+ return path21.join(this.dataDir, INBOX_SUBDIR);
26650
26780
  }
26651
26781
  filePath(peerOwnerId) {
26652
- return path20.join(this.dirPath(), `${peerOwnerId}.jsonl`);
26782
+ return path21.join(this.dirPath(), `${peerOwnerId}.jsonl`);
26653
26783
  }
26654
26784
  };
26655
26785
  function parseAllLines(raw) {
@@ -26736,8 +26866,8 @@ var InboxManager = class {
26736
26866
  };
26737
26867
 
26738
26868
  // src/state/received-capability-store.ts
26739
- var fs19 = __toESM(require("fs"), 1);
26740
- var path21 = __toESM(require("path"), 1);
26869
+ var fs20 = __toESM(require("fs"), 1);
26870
+ var path22 = __toESM(require("path"), 1);
26741
26871
  var FILE_NAME = "received-capabilities.json";
26742
26872
  var ReceivedCapabilityStore = class {
26743
26873
  constructor(dataDir) {
@@ -26747,10 +26877,10 @@ var ReceivedCapabilityStore = class {
26747
26877
  caps = /* @__PURE__ */ new Map();
26748
26878
  load() {
26749
26879
  this.caps.clear();
26750
- const file = path21.join(this.dataDir, FILE_NAME);
26880
+ const file = path22.join(this.dataDir, FILE_NAME);
26751
26881
  let raw;
26752
26882
  try {
26753
- raw = fs19.readFileSync(file, "utf8");
26883
+ raw = fs20.readFileSync(file, "utf8");
26754
26884
  } catch (err) {
26755
26885
  if (err?.code !== "ENOENT") this.renameBak(file);
26756
26886
  return;
@@ -26787,20 +26917,20 @@ var ReceivedCapabilityStore = class {
26787
26917
  this.flush();
26788
26918
  }
26789
26919
  flush() {
26790
- const file = path21.join(this.dataDir, FILE_NAME);
26920
+ const file = path22.join(this.dataDir, FILE_NAME);
26791
26921
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
26792
26922
  const content = JSON.stringify(
26793
26923
  { receivedCaps: Array.from(this.caps.values()) },
26794
26924
  null,
26795
26925
  2
26796
26926
  );
26797
- fs19.mkdirSync(this.dataDir, { recursive: true });
26798
- fs19.writeFileSync(tmp, content, { mode: 384 });
26799
- fs19.renameSync(tmp, file);
26927
+ fs20.mkdirSync(this.dataDir, { recursive: true });
26928
+ fs20.writeFileSync(tmp, content, { mode: 384 });
26929
+ fs20.renameSync(tmp, file);
26800
26930
  }
26801
26931
  renameBak(file) {
26802
26932
  try {
26803
- fs19.renameSync(file, `${file}.bak`);
26933
+ fs20.renameSync(file, `${file}.bak`);
26804
26934
  } catch {
26805
26935
  }
26806
26936
  }
@@ -26898,61 +27028,61 @@ async function connectRemote(args) {
26898
27028
  }
26899
27029
 
26900
27030
  // src/migrations/2026-05-20-flatten-sessions.ts
26901
- var fs20 = __toESM(require("fs"), 1);
26902
- var path22 = __toESM(require("path"), 1);
27031
+ var fs21 = __toESM(require("fs"), 1);
27032
+ var path23 = __toESM(require("path"), 1);
26903
27033
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
26904
27034
  function migrateFlattenSessions(opts) {
26905
27035
  const dataDir = opts.dataDir;
26906
27036
  const now = opts.now ?? Date.now;
26907
- const sessionsDir = path22.join(dataDir, "sessions");
26908
- const flagPath = path22.join(sessionsDir, MIGRATION_FLAG_NAME);
27037
+ const sessionsDir = path23.join(dataDir, "sessions");
27038
+ const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
26909
27039
  if (existsSync3(flagPath)) {
26910
27040
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
26911
27041
  }
26912
27042
  let movedBare = 0;
26913
27043
  let movedVmOwner = 0;
26914
27044
  let archivedListener = 0;
26915
- const defaultDir = path22.join(sessionsDir, "default");
27045
+ const defaultDir = path23.join(sessionsDir, "default");
26916
27046
  if (existsSync3(defaultDir)) {
26917
27047
  for (const entry of readdirSafe(defaultDir)) {
26918
27048
  if (!entry.endsWith(".json")) continue;
26919
- const src = path22.join(defaultDir, entry);
26920
- const dst = path22.join(sessionsDir, entry);
26921
- fs20.renameSync(src, dst);
27049
+ const src = path23.join(defaultDir, entry);
27050
+ const dst = path23.join(sessionsDir, entry);
27051
+ fs21.renameSync(src, dst);
26922
27052
  movedBare += 1;
26923
27053
  }
26924
27054
  rmdirIfEmpty(defaultDir);
26925
27055
  }
26926
27056
  for (const pid of readdirSafe(sessionsDir)) {
26927
- const personaDir = path22.join(sessionsDir, pid);
27057
+ const personaDir = path23.join(sessionsDir, pid);
26928
27058
  if (!isDir(personaDir)) continue;
26929
27059
  if (pid === "default") continue;
26930
- const ownerSrc = path22.join(personaDir, "owner");
27060
+ const ownerSrc = path23.join(personaDir, "owner");
26931
27061
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
26932
- const ownerDst = path22.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
26933
- fs20.mkdirSync(ownerDst, { recursive: true });
27062
+ const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
27063
+ fs21.mkdirSync(ownerDst, { recursive: true });
26934
27064
  for (const file of readdirSafe(ownerSrc)) {
26935
27065
  if (!file.endsWith(".json")) continue;
26936
- fs20.renameSync(path22.join(ownerSrc, file), path22.join(ownerDst, file));
27066
+ fs21.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
26937
27067
  movedVmOwner += 1;
26938
27068
  }
26939
27069
  rmdirIfEmpty(ownerSrc);
26940
27070
  }
26941
- const listenerSrc = path22.join(personaDir, "listener");
27071
+ const listenerSrc = path23.join(personaDir, "listener");
26942
27072
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
26943
- const archiveDst = path22.join(dataDir, ".legacy", `listener-${pid}`);
26944
- fs20.mkdirSync(archiveDst, { recursive: true });
27073
+ const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
27074
+ fs21.mkdirSync(archiveDst, { recursive: true });
26945
27075
  for (const file of readdirSafe(listenerSrc)) {
26946
27076
  if (!file.endsWith(".json")) continue;
26947
- fs20.renameSync(path22.join(listenerSrc, file), path22.join(archiveDst, file));
27077
+ fs21.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
26948
27078
  archivedListener += 1;
26949
27079
  }
26950
27080
  rmdirIfEmpty(listenerSrc);
26951
27081
  }
26952
27082
  rmdirIfEmpty(personaDir);
26953
27083
  }
26954
- fs20.mkdirSync(sessionsDir, { recursive: true });
26955
- fs20.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
27084
+ fs21.mkdirSync(sessionsDir, { recursive: true });
27085
+ fs21.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
26956
27086
  return {
26957
27087
  skipped: false,
26958
27088
  flagWritten: true,
@@ -26963,7 +27093,7 @@ function migrateFlattenSessions(opts) {
26963
27093
  }
26964
27094
  function existsSync3(p2) {
26965
27095
  try {
26966
- fs20.statSync(p2);
27096
+ fs21.statSync(p2);
26967
27097
  return true;
26968
27098
  } catch {
26969
27099
  return false;
@@ -26971,31 +27101,31 @@ function existsSync3(p2) {
26971
27101
  }
26972
27102
  function isDir(p2) {
26973
27103
  try {
26974
- return fs20.statSync(p2).isDirectory();
27104
+ return fs21.statSync(p2).isDirectory();
26975
27105
  } catch {
26976
27106
  return false;
26977
27107
  }
26978
27108
  }
26979
27109
  function readdirSafe(p2) {
26980
27110
  try {
26981
- return fs20.readdirSync(p2);
27111
+ return fs21.readdirSync(p2);
26982
27112
  } catch {
26983
27113
  return [];
26984
27114
  }
26985
27115
  }
26986
27116
  function rmdirIfEmpty(p2) {
26987
27117
  try {
26988
- fs20.rmdirSync(p2);
27118
+ fs21.rmdirSync(p2);
26989
27119
  } catch {
26990
27120
  }
26991
27121
  }
26992
27122
 
26993
27123
  // src/transport/http-router.ts
26994
- var import_node_fs15 = __toESM(require("fs"), 1);
26995
- var import_node_path17 = __toESM(require("path"), 1);
27124
+ var import_node_fs16 = __toESM(require("fs"), 1);
27125
+ var import_node_path18 = __toESM(require("path"), 1);
26996
27126
 
26997
27127
  // src/attachment/mime.ts
26998
- var import_node_path15 = __toESM(require("path"), 1);
27128
+ var import_node_path16 = __toESM(require("path"), 1);
26999
27129
  var TEXT_PLAIN = "text/plain; charset=utf-8";
27000
27130
  var EXT_TO_NATIVE_MIME = {
27001
27131
  // 图片
@@ -27102,7 +27232,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
27102
27232
  ".mk"
27103
27233
  ]);
27104
27234
  function lookupMime(filePathOrName) {
27105
- const ext = import_node_path15.default.extname(filePathOrName).toLowerCase();
27235
+ const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
27106
27236
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
27107
27237
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
27108
27238
  return "application/octet-stream";
@@ -27171,8 +27301,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
27171
27301
  }
27172
27302
 
27173
27303
  // src/attachment/upload.ts
27174
- var import_node_fs14 = __toESM(require("fs"), 1);
27175
- var import_node_path16 = __toESM(require("path"), 1);
27304
+ var import_node_fs15 = __toESM(require("fs"), 1);
27305
+ var import_node_path17 = __toESM(require("path"), 1);
27176
27306
  var import_node_crypto6 = __toESM(require("crypto"), 1);
27177
27307
  var import_promises = require("stream/promises");
27178
27308
  var UploadError = class extends Error {
@@ -27184,22 +27314,22 @@ var UploadError = class extends Error {
27184
27314
  code;
27185
27315
  };
27186
27316
  function assertValidFileName(fileName) {
27187
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path16.default.basename(fileName)) {
27317
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path17.default.basename(fileName)) {
27188
27318
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
27189
27319
  }
27190
27320
  }
27191
27321
  var HASH_PREFIX_LEN = 16;
27192
27322
  async function writeUploadedAttachment(args) {
27193
27323
  assertValidFileName(args.fileName);
27194
- const attachmentsRoot = import_node_path16.default.join(args.sessionDir, ".attachments");
27324
+ const attachmentsRoot = import_node_path17.default.join(args.sessionDir, ".attachments");
27195
27325
  try {
27196
- import_node_fs14.default.mkdirSync(attachmentsRoot, { recursive: true });
27326
+ import_node_fs15.default.mkdirSync(attachmentsRoot, { recursive: true });
27197
27327
  } catch (err) {
27198
27328
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
27199
27329
  }
27200
27330
  const hasher = import_node_crypto6.default.createHash("sha256");
27201
27331
  let actualSize = 0;
27202
- const tmpPath = import_node_path16.default.join(
27332
+ const tmpPath = import_node_path17.default.join(
27203
27333
  attachmentsRoot,
27204
27334
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto6.default.randomBytes(4).toString("hex")}`
27205
27335
  );
@@ -27214,18 +27344,18 @@ async function writeUploadedAttachment(args) {
27214
27344
  yield buf;
27215
27345
  }
27216
27346
  },
27217
- import_node_fs14.default.createWriteStream(tmpPath, { mode: 384 })
27347
+ import_node_fs15.default.createWriteStream(tmpPath, { mode: 384 })
27218
27348
  );
27219
27349
  } catch (err) {
27220
27350
  try {
27221
- import_node_fs14.default.unlinkSync(tmpPath);
27351
+ import_node_fs15.default.unlinkSync(tmpPath);
27222
27352
  } catch {
27223
27353
  }
27224
27354
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
27225
27355
  }
27226
27356
  if (actualSize !== args.contentLength) {
27227
27357
  try {
27228
- import_node_fs14.default.unlinkSync(tmpPath);
27358
+ import_node_fs15.default.unlinkSync(tmpPath);
27229
27359
  } catch {
27230
27360
  }
27231
27361
  throw new UploadError(
@@ -27234,35 +27364,35 @@ async function writeUploadedAttachment(args) {
27234
27364
  );
27235
27365
  }
27236
27366
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
27237
- const hashDir = import_node_path16.default.join(attachmentsRoot, attachmentId);
27367
+ const hashDir = import_node_path17.default.join(attachmentsRoot, attachmentId);
27238
27368
  let finalFileName;
27239
27369
  let hashDirExists = false;
27240
27370
  try {
27241
- hashDirExists = import_node_fs14.default.statSync(hashDir).isDirectory();
27371
+ hashDirExists = import_node_fs15.default.statSync(hashDir).isDirectory();
27242
27372
  } catch {
27243
27373
  }
27244
27374
  if (hashDirExists) {
27245
- const existing = import_node_fs14.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
27375
+ const existing = import_node_fs15.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
27246
27376
  finalFileName = existing[0] ?? args.fileName;
27247
27377
  try {
27248
- import_node_fs14.default.unlinkSync(tmpPath);
27378
+ import_node_fs15.default.unlinkSync(tmpPath);
27249
27379
  } catch {
27250
27380
  }
27251
27381
  } else {
27252
27382
  try {
27253
- import_node_fs14.default.mkdirSync(hashDir, { recursive: true });
27383
+ import_node_fs15.default.mkdirSync(hashDir, { recursive: true });
27254
27384
  finalFileName = args.fileName;
27255
- import_node_fs14.default.renameSync(tmpPath, import_node_path16.default.join(hashDir, finalFileName));
27385
+ import_node_fs15.default.renameSync(tmpPath, import_node_path17.default.join(hashDir, finalFileName));
27256
27386
  } catch (err) {
27257
27387
  try {
27258
- import_node_fs14.default.unlinkSync(tmpPath);
27388
+ import_node_fs15.default.unlinkSync(tmpPath);
27259
27389
  } catch {
27260
27390
  }
27261
27391
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
27262
27392
  }
27263
27393
  }
27264
- const absPath = import_node_path16.default.join(hashDir, finalFileName);
27265
- const relPath = import_node_path16.default.relative(args.sessionDir, absPath);
27394
+ const absPath = import_node_path17.default.join(hashDir, finalFileName);
27395
+ const relPath = import_node_path17.default.relative(args.sessionDir, absPath);
27266
27396
  args.groupFileStore.upsert(args.scope, args.sessionId, {
27267
27397
  relPath: absPath,
27268
27398
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -27293,7 +27423,7 @@ function isValidUploadFileName(fileName) {
27293
27423
  if (fileName === "." || fileName === "..") return false;
27294
27424
  if (fileName.startsWith(".")) return false;
27295
27425
  if (fileName.includes("/") || fileName.includes("\\")) return false;
27296
- return fileName === import_node_path17.default.basename(fileName);
27426
+ return fileName === import_node_path18.default.basename(fileName);
27297
27427
  }
27298
27428
  function createHttpRouter(deps) {
27299
27429
  return async (req, res) => {
@@ -27457,7 +27587,7 @@ function createHttpRouter(deps) {
27457
27587
  return true;
27458
27588
  }
27459
27589
  let absPath;
27460
- if (import_node_path17.default.isAbsolute(pathParam)) {
27590
+ if (import_node_path18.default.isAbsolute(pathParam)) {
27461
27591
  absPath = pathParam;
27462
27592
  } else if (deps.sessionStore) {
27463
27593
  const file = deps.sessionStore.read(sid);
@@ -27465,7 +27595,7 @@ function createHttpRouter(deps) {
27465
27595
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
27466
27596
  return true;
27467
27597
  }
27468
- absPath = import_node_path17.default.join(file.cwd, pathParam);
27598
+ absPath = import_node_path18.default.join(file.cwd, pathParam);
27469
27599
  } else {
27470
27600
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
27471
27601
  return true;
@@ -27498,7 +27628,7 @@ function withCtx(ctx, body) {
27498
27628
  function streamFile(res, absPath, logger) {
27499
27629
  let stat;
27500
27630
  try {
27501
- stat = import_node_fs15.default.statSync(absPath);
27631
+ stat = import_node_fs16.default.statSync(absPath);
27502
27632
  } catch (err) {
27503
27633
  const code = err?.code;
27504
27634
  if (code === "ENOENT") {
@@ -27513,7 +27643,7 @@ function streamFile(res, absPath, logger) {
27513
27643
  return;
27514
27644
  }
27515
27645
  const mime = lookupMime(absPath);
27516
- const basename = import_node_path17.default.basename(absPath);
27646
+ const basename = import_node_path18.default.basename(absPath);
27517
27647
  res.writeHead(200, {
27518
27648
  "Content-Type": mime,
27519
27649
  "Content-Length": String(stat.size),
@@ -27521,7 +27651,7 @@ function streamFile(res, absPath, logger) {
27521
27651
  // 防止浏览器把任意 mime 当 html 渲染
27522
27652
  "X-Content-Type-Options": "nosniff"
27523
27653
  });
27524
- const stream = import_node_fs15.default.createReadStream(absPath);
27654
+ const stream = import_node_fs16.default.createReadStream(absPath);
27525
27655
  stream.on("error", (err) => {
27526
27656
  logger?.warn("streamFile read error", { absPath, err: err.message });
27527
27657
  res.destroy();
@@ -27530,8 +27660,8 @@ function streamFile(res, absPath, logger) {
27530
27660
  }
27531
27661
 
27532
27662
  // src/attachment/gc.ts
27533
- var import_node_fs16 = __toESM(require("fs"), 1);
27534
- var import_node_path18 = __toESM(require("path"), 1);
27663
+ var import_node_fs17 = __toESM(require("fs"), 1);
27664
+ var import_node_path19 = __toESM(require("path"), 1);
27535
27665
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
27536
27666
  function runAttachmentGc(args) {
27537
27667
  const now = (args.now ?? Date.now)();
@@ -27540,38 +27670,38 @@ function runAttachmentGc(args) {
27540
27670
  for (const { scope, sessionId } of args.sessionScopes) {
27541
27671
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
27542
27672
  if (entry.stale) continue;
27543
- if (import_node_path18.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
27673
+ if (import_node_path19.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
27544
27674
  }
27545
27675
  }
27546
27676
  for (const { scope, sessionId } of args.sessionScopes) {
27547
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path18.default.join(
27677
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path19.default.join(
27548
27678
  args.dataDir,
27549
27679
  "sessions",
27550
27680
  ...scopeSubPath(scope).map(safeFileName),
27551
27681
  safeFileName(sessionId)
27552
27682
  );
27553
- const attRoot = import_node_path18.default.join(sessionDir, ".attachments");
27683
+ const attRoot = import_node_path19.default.join(sessionDir, ".attachments");
27554
27684
  let hashDirs;
27555
27685
  try {
27556
- hashDirs = import_node_fs16.default.readdirSync(attRoot);
27686
+ hashDirs = import_node_fs17.default.readdirSync(attRoot);
27557
27687
  } catch (err) {
27558
27688
  if (err.code === "ENOENT") continue;
27559
27689
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
27560
27690
  continue;
27561
27691
  }
27562
27692
  for (const hashDir of hashDirs) {
27563
- const hashDirAbs = import_node_path18.default.join(attRoot, hashDir);
27693
+ const hashDirAbs = import_node_path19.default.join(attRoot, hashDir);
27564
27694
  let files;
27565
27695
  try {
27566
- files = import_node_fs16.default.readdirSync(hashDirAbs);
27696
+ files = import_node_fs17.default.readdirSync(hashDirAbs);
27567
27697
  } catch {
27568
27698
  continue;
27569
27699
  }
27570
27700
  for (const name of files) {
27571
- const file = import_node_path18.default.join(hashDirAbs, name);
27701
+ const file = import_node_path19.default.join(hashDirAbs, name);
27572
27702
  let stat;
27573
27703
  try {
27574
- stat = import_node_fs16.default.statSync(file);
27704
+ stat = import_node_fs17.default.statSync(file);
27575
27705
  } catch {
27576
27706
  continue;
27577
27707
  }
@@ -27580,26 +27710,26 @@ function runAttachmentGc(args) {
27580
27710
  if (age < ttlMs) continue;
27581
27711
  if (liveAbs.has(file)) continue;
27582
27712
  try {
27583
- import_node_fs16.default.unlinkSync(file);
27713
+ import_node_fs17.default.unlinkSync(file);
27584
27714
  } catch (err) {
27585
27715
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
27586
27716
  }
27587
27717
  }
27588
27718
  try {
27589
- if (import_node_fs16.default.readdirSync(hashDirAbs).length === 0) import_node_fs16.default.rmdirSync(hashDirAbs);
27719
+ if (import_node_fs17.default.readdirSync(hashDirAbs).length === 0) import_node_fs17.default.rmdirSync(hashDirAbs);
27590
27720
  } catch {
27591
27721
  }
27592
27722
  }
27593
27723
  try {
27594
- if (import_node_fs16.default.readdirSync(attRoot).length === 0) import_node_fs16.default.rmdirSync(attRoot);
27724
+ if (import_node_fs17.default.readdirSync(attRoot).length === 0) import_node_fs17.default.rmdirSync(attRoot);
27595
27725
  } catch {
27596
27726
  }
27597
27727
  }
27598
27728
  }
27599
27729
 
27600
27730
  // src/attachment/group.ts
27601
- var import_node_fs17 = __toESM(require("fs"), 1);
27602
- var import_node_path19 = __toESM(require("path"), 1);
27731
+ var import_node_fs18 = __toESM(require("fs"), 1);
27732
+ var import_node_path20 = __toESM(require("path"), 1);
27603
27733
  var import_node_crypto7 = __toESM(require("crypto"), 1);
27604
27734
  init_protocol();
27605
27735
  var GroupFileStore = class {
@@ -27611,11 +27741,11 @@ var GroupFileStore = class {
27611
27741
  this.logger = opts.logger;
27612
27742
  }
27613
27743
  rootForScope(scope) {
27614
- return import_node_path19.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
27744
+ return import_node_path20.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
27615
27745
  }
27616
27746
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
27617
27747
  filePath(scope, sessionId) {
27618
- return import_node_path19.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
27748
+ return import_node_path20.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
27619
27749
  }
27620
27750
  cacheKey(scope, sessionId) {
27621
27751
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -27624,7 +27754,7 @@ var GroupFileStore = class {
27624
27754
  readFile(scope, sessionId) {
27625
27755
  const file = this.filePath(scope, sessionId);
27626
27756
  try {
27627
- const raw = import_node_fs17.default.readFileSync(file, "utf8");
27757
+ const raw = import_node_fs18.default.readFileSync(file, "utf8");
27628
27758
  const parsed = JSON.parse(raw);
27629
27759
  if (!Array.isArray(parsed)) {
27630
27760
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -27650,10 +27780,10 @@ var GroupFileStore = class {
27650
27780
  }
27651
27781
  writeFile(scope, sessionId, entries) {
27652
27782
  const file = this.filePath(scope, sessionId);
27653
- import_node_fs17.default.mkdirSync(import_node_path19.default.dirname(file), { recursive: true });
27783
+ import_node_fs18.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
27654
27784
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
27655
- import_node_fs17.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
27656
- import_node_fs17.default.renameSync(tmp, file);
27785
+ import_node_fs18.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
27786
+ import_node_fs18.default.renameSync(tmp, file);
27657
27787
  }
27658
27788
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
27659
27789
  list(scope, sessionId) {
@@ -27739,10 +27869,10 @@ var GroupFileStore = class {
27739
27869
  };
27740
27870
 
27741
27871
  // src/discovery/state-file.ts
27742
- var import_node_fs18 = __toESM(require("fs"), 1);
27743
- var import_node_path20 = __toESM(require("path"), 1);
27872
+ var import_node_fs19 = __toESM(require("fs"), 1);
27873
+ var import_node_path21 = __toESM(require("path"), 1);
27744
27874
  function defaultStateFilePath(dataDir) {
27745
- return import_node_path20.default.join(dataDir, "state.json");
27875
+ return import_node_path21.default.join(dataDir, "state.json");
27746
27876
  }
27747
27877
  function isPidAlive(pid) {
27748
27878
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -27764,7 +27894,7 @@ var StateFileManager = class {
27764
27894
  }
27765
27895
  read() {
27766
27896
  try {
27767
- const raw = import_node_fs18.default.readFileSync(this.file, "utf8");
27897
+ const raw = import_node_fs19.default.readFileSync(this.file, "utf8");
27768
27898
  const parsed = JSON.parse(raw);
27769
27899
  return parsed;
27770
27900
  } catch {
@@ -27778,34 +27908,34 @@ var StateFileManager = class {
27778
27908
  return { status: "stale", existing };
27779
27909
  }
27780
27910
  write(state) {
27781
- import_node_fs18.default.mkdirSync(import_node_path20.default.dirname(this.file), { recursive: true });
27911
+ import_node_fs19.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
27782
27912
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
27783
- import_node_fs18.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27784
- import_node_fs18.default.renameSync(tmp, this.file);
27913
+ import_node_fs19.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
27914
+ import_node_fs19.default.renameSync(tmp, this.file);
27785
27915
  if (process.platform !== "win32") {
27786
27916
  try {
27787
- import_node_fs18.default.chmodSync(this.file, 384);
27917
+ import_node_fs19.default.chmodSync(this.file, 384);
27788
27918
  } catch {
27789
27919
  }
27790
27920
  }
27791
27921
  }
27792
27922
  delete() {
27793
27923
  try {
27794
- import_node_fs18.default.unlinkSync(this.file);
27924
+ import_node_fs19.default.unlinkSync(this.file);
27795
27925
  } catch {
27796
27926
  }
27797
27927
  }
27798
27928
  };
27799
27929
 
27800
27930
  // src/tunnel/tunnel-manager.ts
27801
- var import_node_fs22 = __toESM(require("fs"), 1);
27802
- var import_node_path24 = __toESM(require("path"), 1);
27931
+ var import_node_fs23 = __toESM(require("fs"), 1);
27932
+ var import_node_path25 = __toESM(require("path"), 1);
27803
27933
  var import_node_crypto8 = __toESM(require("crypto"), 1);
27804
27934
  var import_node_child_process5 = require("child_process");
27805
27935
 
27806
27936
  // src/tunnel/tunnel-store.ts
27807
- var import_node_fs19 = __toESM(require("fs"), 1);
27808
- var import_node_path21 = __toESM(require("path"), 1);
27937
+ var import_node_fs20 = __toESM(require("fs"), 1);
27938
+ var import_node_path22 = __toESM(require("path"), 1);
27809
27939
  var TunnelStore = class {
27810
27940
  constructor(filePath) {
27811
27941
  this.filePath = filePath;
@@ -27813,7 +27943,7 @@ var TunnelStore = class {
27813
27943
  filePath;
27814
27944
  async get() {
27815
27945
  try {
27816
- const raw = await import_node_fs19.default.promises.readFile(this.filePath, "utf8");
27946
+ const raw = await import_node_fs20.default.promises.readFile(this.filePath, "utf8");
27817
27947
  const obj = JSON.parse(raw);
27818
27948
  if (!isPersistedTunnel(obj)) return null;
27819
27949
  return obj;
@@ -27824,22 +27954,22 @@ var TunnelStore = class {
27824
27954
  }
27825
27955
  }
27826
27956
  async set(v2) {
27827
- const dir = import_node_path21.default.dirname(this.filePath);
27828
- await import_node_fs19.default.promises.mkdir(dir, { recursive: true });
27957
+ const dir = import_node_path22.default.dirname(this.filePath);
27958
+ await import_node_fs20.default.promises.mkdir(dir, { recursive: true });
27829
27959
  const data = JSON.stringify(v2, null, 2);
27830
27960
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
27831
- await import_node_fs19.default.promises.writeFile(tmp, data, { mode: 384 });
27961
+ await import_node_fs20.default.promises.writeFile(tmp, data, { mode: 384 });
27832
27962
  if (process.platform !== "win32") {
27833
27963
  try {
27834
- await import_node_fs19.default.promises.chmod(tmp, 384);
27964
+ await import_node_fs20.default.promises.chmod(tmp, 384);
27835
27965
  } catch {
27836
27966
  }
27837
27967
  }
27838
- await import_node_fs19.default.promises.rename(tmp, this.filePath);
27968
+ await import_node_fs20.default.promises.rename(tmp, this.filePath);
27839
27969
  }
27840
27970
  async clear() {
27841
27971
  try {
27842
- await import_node_fs19.default.promises.unlink(this.filePath);
27972
+ await import_node_fs20.default.promises.unlink(this.filePath);
27843
27973
  } catch (err) {
27844
27974
  const code = err?.code;
27845
27975
  if (code !== "ENOENT") throw err;
@@ -27934,9 +28064,9 @@ function escape(v2) {
27934
28064
  }
27935
28065
 
27936
28066
  // src/tunnel/frpc-binary.ts
27937
- var import_node_fs20 = __toESM(require("fs"), 1);
27938
- var import_node_os9 = __toESM(require("os"), 1);
27939
- var import_node_path22 = __toESM(require("path"), 1);
28067
+ var import_node_fs21 = __toESM(require("fs"), 1);
28068
+ var import_node_os10 = __toESM(require("os"), 1);
28069
+ var import_node_path23 = __toESM(require("path"), 1);
27940
28070
  var import_node_child_process3 = require("child_process");
27941
28071
  var import_node_stream2 = require("stream");
27942
28072
  var import_promises2 = require("stream/promises");
@@ -27968,20 +28098,20 @@ function frpcDownloadUrl(version2, p2) {
27968
28098
  }
27969
28099
  async function ensureFrpcBinary(opts) {
27970
28100
  if (opts.override) {
27971
- if (!import_node_fs20.default.existsSync(opts.override)) {
28101
+ if (!import_node_fs21.default.existsSync(opts.override)) {
27972
28102
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
27973
28103
  }
27974
28104
  return opts.override;
27975
28105
  }
27976
28106
  const version2 = opts.version ?? FRPC_VERSION;
27977
28107
  const platform = opts.platform ?? detectPlatform();
27978
- const binDir = import_node_path22.default.join(opts.dataDir, "bin");
27979
- import_node_fs20.default.mkdirSync(binDir, { recursive: true });
28108
+ const binDir = import_node_path23.default.join(opts.dataDir, "bin");
28109
+ import_node_fs21.default.mkdirSync(binDir, { recursive: true });
27980
28110
  cleanupStaleArtifacts(binDir);
27981
- const stableBin = import_node_path22.default.join(binDir, "frpc");
27982
- if (import_node_fs20.default.existsSync(stableBin)) return stableBin;
28111
+ const stableBin = import_node_path23.default.join(binDir, "frpc");
28112
+ if (import_node_fs21.default.existsSync(stableBin)) return stableBin;
27983
28113
  const partialBin = `${stableBin}.partial`;
27984
- const tarballPath = import_node_path22.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
28114
+ const tarballPath = import_node_path23.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
27985
28115
  try {
27986
28116
  const url = frpcDownloadUrl(version2, platform);
27987
28117
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -27990,8 +28120,8 @@ async function ensureFrpcBinary(opts) {
27990
28120
  } else {
27991
28121
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
27992
28122
  }
27993
- import_node_fs20.default.chmodSync(partialBin, 493);
27994
- import_node_fs20.default.renameSync(partialBin, stableBin);
28123
+ import_node_fs21.default.chmodSync(partialBin, 493);
28124
+ import_node_fs21.default.renameSync(partialBin, stableBin);
27995
28125
  } finally {
27996
28126
  safeUnlink(tarballPath);
27997
28127
  safeUnlink(partialBin);
@@ -28001,15 +28131,15 @@ async function ensureFrpcBinary(opts) {
28001
28131
  function cleanupStaleArtifacts(binDir) {
28002
28132
  let entries;
28003
28133
  try {
28004
- entries = import_node_fs20.default.readdirSync(binDir);
28134
+ entries = import_node_fs21.default.readdirSync(binDir);
28005
28135
  } catch {
28006
28136
  return;
28007
28137
  }
28008
28138
  for (const name of entries) {
28009
28139
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
28010
- const full = import_node_path22.default.join(binDir, name);
28140
+ const full = import_node_path23.default.join(binDir, name);
28011
28141
  try {
28012
- import_node_fs20.default.rmSync(full, { recursive: true, force: true });
28142
+ import_node_fs21.default.rmSync(full, { recursive: true, force: true });
28013
28143
  } catch {
28014
28144
  }
28015
28145
  }
@@ -28017,7 +28147,7 @@ function cleanupStaleArtifacts(binDir) {
28017
28147
  }
28018
28148
  function safeUnlink(p2) {
28019
28149
  try {
28020
- import_node_fs20.default.unlinkSync(p2);
28150
+ import_node_fs21.default.unlinkSync(p2);
28021
28151
  } catch {
28022
28152
  }
28023
28153
  }
@@ -28028,13 +28158,13 @@ async function downloadToFile(url, dest, fetchImpl) {
28028
28158
  if (!res.ok || !res.body) {
28029
28159
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
28030
28160
  }
28031
- const out = import_node_fs20.default.createWriteStream(dest);
28161
+ const out = import_node_fs21.default.createWriteStream(dest);
28032
28162
  const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
28033
28163
  await (0, import_promises2.pipeline)(nodeStream, out);
28034
28164
  }
28035
28165
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
28036
- const work = import_node_path22.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
28037
- import_node_fs20.default.mkdirSync(work, { recursive: true });
28166
+ const work = import_node_path23.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
28167
+ import_node_fs21.default.mkdirSync(work, { recursive: true });
28038
28168
  try {
28039
28169
  await new Promise((resolve6, reject) => {
28040
28170
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -28042,32 +28172,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
28042
28172
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
28043
28173
  });
28044
28174
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
28045
- const src = import_node_path22.default.join(work, dirName, "frpc");
28046
- if (!import_node_fs20.default.existsSync(src)) {
28175
+ const src = import_node_path23.default.join(work, dirName, "frpc");
28176
+ if (!import_node_fs21.default.existsSync(src)) {
28047
28177
  throw new Error(`frpc not found inside tarball at ${src}`);
28048
28178
  }
28049
- import_node_fs20.default.copyFileSync(src, destBin);
28179
+ import_node_fs21.default.copyFileSync(src, destBin);
28050
28180
  } finally {
28051
- import_node_fs20.default.rmSync(work, { recursive: true, force: true });
28181
+ import_node_fs21.default.rmSync(work, { recursive: true, force: true });
28052
28182
  }
28053
28183
  }
28054
28184
 
28055
28185
  // src/tunnel/frpc-process.ts
28056
- var import_node_fs21 = __toESM(require("fs"), 1);
28057
- var import_node_path23 = __toESM(require("path"), 1);
28186
+ var import_node_fs22 = __toESM(require("fs"), 1);
28187
+ var import_node_path24 = __toESM(require("path"), 1);
28058
28188
  var import_node_child_process4 = require("child_process");
28059
28189
  function frpcPidFilePath(dataDir) {
28060
- return import_node_path23.default.join(dataDir, "frpc.pid");
28190
+ return import_node_path24.default.join(dataDir, "frpc.pid");
28061
28191
  }
28062
28192
  function writeFrpcPid(dataDir, pid) {
28063
28193
  try {
28064
- import_node_fs21.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
28194
+ import_node_fs22.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
28065
28195
  } catch {
28066
28196
  }
28067
28197
  }
28068
28198
  function clearFrpcPid(dataDir) {
28069
28199
  try {
28070
- import_node_fs21.default.unlinkSync(frpcPidFilePath(dataDir));
28200
+ import_node_fs22.default.unlinkSync(frpcPidFilePath(dataDir));
28071
28201
  } catch {
28072
28202
  }
28073
28203
  }
@@ -28083,7 +28213,7 @@ function defaultIsPidAlive(pid) {
28083
28213
  }
28084
28214
  function defaultReadPidFile(file) {
28085
28215
  try {
28086
- return import_node_fs21.default.readFileSync(file, "utf8");
28216
+ return import_node_fs22.default.readFileSync(file, "utf8");
28087
28217
  } catch {
28088
28218
  return null;
28089
28219
  }
@@ -28099,7 +28229,7 @@ function defaultSleep(ms) {
28099
28229
  }
28100
28230
  async function killStaleFrpc(deps) {
28101
28231
  const pidFile = frpcPidFilePath(deps.dataDir);
28102
- const tomlPath = import_node_path23.default.join(deps.dataDir, "frpc.toml");
28232
+ const tomlPath = import_node_path24.default.join(deps.dataDir, "frpc.toml");
28103
28233
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
28104
28234
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
28105
28235
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -28123,7 +28253,7 @@ async function killStaleFrpc(deps) {
28123
28253
  }
28124
28254
  if (victims.size === 0) {
28125
28255
  try {
28126
- import_node_fs21.default.unlinkSync(pidFile);
28256
+ import_node_fs22.default.unlinkSync(pidFile);
28127
28257
  } catch {
28128
28258
  }
28129
28259
  return;
@@ -28134,7 +28264,7 @@ async function killStaleFrpc(deps) {
28134
28264
  }
28135
28265
  await sleep(deps.reapWaitMs ?? 300);
28136
28266
  try {
28137
- import_node_fs21.default.unlinkSync(pidFile);
28267
+ import_node_fs22.default.unlinkSync(pidFile);
28138
28268
  } catch {
28139
28269
  }
28140
28270
  }
@@ -28171,7 +28301,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
28171
28301
  var TunnelManager = class {
28172
28302
  constructor(deps) {
28173
28303
  this.deps = deps;
28174
- this.store = deps.store ?? new TunnelStore(import_node_path24.default.join(deps.dataDir, "tunnel.json"));
28304
+ this.store = deps.store ?? new TunnelStore(import_node_path25.default.join(deps.dataDir, "tunnel.json"));
28175
28305
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
28176
28306
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
28177
28307
  }
@@ -28298,7 +28428,7 @@ var TunnelManager = class {
28298
28428
  dataDir: this.deps.dataDir,
28299
28429
  override: this.deps.frpcBinaryOverride ?? void 0
28300
28430
  });
28301
- const tomlPath = import_node_path24.default.join(this.deps.dataDir, "frpc.toml");
28431
+ const tomlPath = import_node_path25.default.join(this.deps.dataDir, "frpc.toml");
28302
28432
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto8.default.randomBytes(3).toString("hex")}`;
28303
28433
  const toml = buildFrpcToml({
28304
28434
  serverAddr: t.frpsHost,
@@ -28309,12 +28439,12 @@ var TunnelManager = class {
28309
28439
  localPort,
28310
28440
  logLevel: "info"
28311
28441
  });
28312
- await import_node_fs22.default.promises.writeFile(tomlPath, toml, { mode: 384 });
28442
+ await import_node_fs23.default.promises.writeFile(tomlPath, toml, { mode: 384 });
28313
28443
  const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
28314
28444
  stdio: ["ignore", "pipe", "pipe"]
28315
28445
  });
28316
- const logFilePath = import_node_path24.default.join(this.deps.dataDir, "frpc.log");
28317
- const logStream = import_node_fs22.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
28446
+ const logFilePath = import_node_path25.default.join(this.deps.dataDir, "frpc.log");
28447
+ const logStream = import_node_fs23.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
28318
28448
  logStream.on("error", () => {
28319
28449
  });
28320
28450
  const tee = (chunk) => {
@@ -28396,23 +28526,23 @@ async function waitForFrpcReady(proc, timeoutMs) {
28396
28526
  }
28397
28527
 
28398
28528
  // src/tunnel/device-key.ts
28399
- var import_node_os10 = __toESM(require("os"), 1);
28529
+ var import_node_os11 = __toESM(require("os"), 1);
28400
28530
  var import_node_crypto9 = __toESM(require("crypto"), 1);
28401
28531
  var DERIVE_SALT = "clawd-tunnel-device-v1";
28402
28532
  function deriveStableDeviceKey(opts = {}) {
28403
- const hostname = opts.hostname ?? import_node_os10.default.hostname();
28404
- const uid = opts.uid ?? (typeof import_node_os10.default.userInfo === "function" ? import_node_os10.default.userInfo().uid : 0);
28533
+ const hostname = opts.hostname ?? import_node_os11.default.hostname();
28534
+ const uid = opts.uid ?? (typeof import_node_os11.default.userInfo === "function" ? import_node_os11.default.userInfo().uid : 0);
28405
28535
  const input = `${hostname}::${uid}`;
28406
28536
  return import_node_crypto9.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
28407
28537
  }
28408
28538
 
28409
28539
  // src/auth-store.ts
28410
- var import_node_fs23 = __toESM(require("fs"), 1);
28411
- var import_node_path25 = __toESM(require("path"), 1);
28540
+ var import_node_fs24 = __toESM(require("fs"), 1);
28541
+ var import_node_path26 = __toESM(require("path"), 1);
28412
28542
  var import_node_crypto10 = __toESM(require("crypto"), 1);
28413
28543
  var AUTH_FILE_NAME = "auth.json";
28414
28544
  function authFilePath(dataDir) {
28415
- return import_node_path25.default.join(dataDir, AUTH_FILE_NAME);
28545
+ return import_node_path26.default.join(dataDir, AUTH_FILE_NAME);
28416
28546
  }
28417
28547
  function loadOrCreateAuthFile(opts) {
28418
28548
  const file = authFilePath(opts.dataDir);
@@ -28444,7 +28574,7 @@ function defaultGenerateOwnerPrincipalId() {
28444
28574
  }
28445
28575
  function readAuthFile(file) {
28446
28576
  try {
28447
- const raw = import_node_fs23.default.readFileSync(file, "utf8");
28577
+ const raw = import_node_fs24.default.readFileSync(file, "utf8");
28448
28578
  const parsed = JSON.parse(raw);
28449
28579
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
28450
28580
  return null;
@@ -28462,25 +28592,25 @@ function readAuthFile(file) {
28462
28592
  }
28463
28593
  }
28464
28594
  function writeAuthFile(file, content) {
28465
- import_node_fs23.default.mkdirSync(import_node_path25.default.dirname(file), { recursive: true });
28466
- import_node_fs23.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
28595
+ import_node_fs24.default.mkdirSync(import_node_path26.default.dirname(file), { recursive: true });
28596
+ import_node_fs24.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
28467
28597
  try {
28468
- import_node_fs23.default.chmodSync(file, 384);
28598
+ import_node_fs24.default.chmodSync(file, 384);
28469
28599
  } catch {
28470
28600
  }
28471
28601
  }
28472
28602
 
28473
28603
  // src/owner-profile.ts
28474
- var import_node_fs24 = __toESM(require("fs"), 1);
28475
- var import_node_os11 = __toESM(require("os"), 1);
28476
- var import_node_path26 = __toESM(require("path"), 1);
28604
+ var import_node_fs25 = __toESM(require("fs"), 1);
28605
+ var import_node_os12 = __toESM(require("os"), 1);
28606
+ var import_node_path27 = __toESM(require("path"), 1);
28477
28607
  var PROFILE_FILENAME = "profile.json";
28478
28608
  function loadOwnerDisplayName(dataDir) {
28479
- const fallback = import_node_os11.default.userInfo().username;
28480
- const profilePath = import_node_path26.default.join(dataDir, PROFILE_FILENAME);
28609
+ const fallback = import_node_os12.default.userInfo().username;
28610
+ const profilePath = import_node_path27.default.join(dataDir, PROFILE_FILENAME);
28481
28611
  let raw;
28482
28612
  try {
28483
- raw = import_node_fs24.default.readFileSync(profilePath, "utf8");
28613
+ raw = import_node_fs25.default.readFileSync(profilePath, "utf8");
28484
28614
  } catch {
28485
28615
  return fallback;
28486
28616
  }
@@ -28509,12 +28639,12 @@ init_protocol();
28509
28639
  init_protocol();
28510
28640
 
28511
28641
  // src/session/fork.ts
28512
- var import_node_fs25 = __toESM(require("fs"), 1);
28513
- var import_node_os12 = __toESM(require("os"), 1);
28514
- var import_node_path27 = __toESM(require("path"), 1);
28642
+ var import_node_fs26 = __toESM(require("fs"), 1);
28643
+ var import_node_os13 = __toESM(require("os"), 1);
28644
+ var import_node_path28 = __toESM(require("path"), 1);
28515
28645
  init_claude_history();
28516
28646
  function readJsonlEntries(file) {
28517
- const raw = import_node_fs25.default.readFileSync(file, "utf8");
28647
+ const raw = import_node_fs26.default.readFileSync(file, "utf8");
28518
28648
  const out = [];
28519
28649
  for (const line of raw.split("\n")) {
28520
28650
  const t = line.trim();
@@ -28527,10 +28657,10 @@ function readJsonlEntries(file) {
28527
28657
  return out;
28528
28658
  }
28529
28659
  function forkSession(input) {
28530
- const baseDir = input.baseDir ?? import_node_path27.default.join(import_node_os12.default.homedir(), ".claude");
28531
- const projectDir = import_node_path27.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
28532
- const sourceFile = import_node_path27.default.join(projectDir, `${input.toolSessionId}.jsonl`);
28533
- if (!import_node_fs25.default.existsSync(sourceFile)) {
28660
+ const baseDir = input.baseDir ?? import_node_path28.default.join(import_node_os13.default.homedir(), ".claude");
28661
+ const projectDir = import_node_path28.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
28662
+ const sourceFile = import_node_path28.default.join(projectDir, `${input.toolSessionId}.jsonl`);
28663
+ if (!import_node_fs26.default.existsSync(sourceFile)) {
28534
28664
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
28535
28665
  }
28536
28666
  const entries = readJsonlEntries(sourceFile);
@@ -28560,9 +28690,9 @@ function forkSession(input) {
28560
28690
  }
28561
28691
  forkedLines.push(JSON.stringify(forked));
28562
28692
  }
28563
- const forkedFilePath = import_node_path27.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
28564
- import_node_fs25.default.mkdirSync(projectDir, { recursive: true });
28565
- import_node_fs25.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
28693
+ const forkedFilePath = import_node_path28.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
28694
+ import_node_fs26.default.mkdirSync(projectDir, { recursive: true });
28695
+ import_node_fs26.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
28566
28696
  return { forkedToolSessionId, forkedFilePath };
28567
28697
  }
28568
28698
 
@@ -28894,7 +29024,7 @@ function buildPermissionHandlers(deps) {
28894
29024
  }
28895
29025
 
28896
29026
  // src/handlers/history.ts
28897
- var path37 = __toESM(require("path"), 1);
29027
+ var path38 = __toESM(require("path"), 1);
28898
29028
  init_protocol();
28899
29029
 
28900
29030
  // src/session/recent-dirs.ts
@@ -28912,7 +29042,7 @@ function listRecentDirs(store, limit = 50) {
28912
29042
  }
28913
29043
 
28914
29044
  // src/permission/persona-paths.ts
28915
- var path36 = __toESM(require("path"), 1);
29045
+ var path37 = __toESM(require("path"), 1);
28916
29046
  function getAllowedPersonaIds(grants, action) {
28917
29047
  const ids = /* @__PURE__ */ new Set();
28918
29048
  for (const g2 of grants) {
@@ -28925,26 +29055,26 @@ function getAllowedPersonaIds(grants, action) {
28925
29055
  return ids;
28926
29056
  }
28927
29057
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read") {
28928
- const root = path36.resolve(personaRoot);
28929
- const target = path36.resolve(absPath);
28930
- const sep3 = root.endsWith(path36.sep) ? "" : path36.sep;
29058
+ const root = path37.resolve(personaRoot);
29059
+ const target = path37.resolve(absPath);
29060
+ const sep3 = root.endsWith(path37.sep) ? "" : path37.sep;
28931
29061
  if (!target.startsWith(root + sep3)) return false;
28932
- const rel = path36.relative(root, target);
29062
+ const rel = path37.relative(root, target);
28933
29063
  if (!rel || rel.startsWith("..")) return false;
28934
- const personaId = rel.split(path36.sep)[0];
29064
+ const personaId = rel.split(path37.sep)[0];
28935
29065
  if (!personaId) return false;
28936
29066
  const allowed = getAllowedPersonaIds(grants, action);
28937
29067
  if (allowed === "*") return true;
28938
29068
  return allowed.has(personaId);
28939
29069
  }
28940
29070
  function personaIdFromPath(absPath, personaRoot) {
28941
- const root = path36.resolve(personaRoot);
28942
- const target = path36.resolve(absPath);
28943
- const sep3 = root.endsWith(path36.sep) ? "" : path36.sep;
29071
+ const root = path37.resolve(personaRoot);
29072
+ const target = path37.resolve(absPath);
29073
+ const sep3 = root.endsWith(path37.sep) ? "" : path37.sep;
28944
29074
  if (!target.startsWith(root + sep3)) return null;
28945
- const rel = path36.relative(root, target);
29075
+ const rel = path37.relative(root, target);
28946
29076
  if (!rel || rel.startsWith("..")) return null;
28947
- const id = rel.split(path36.sep)[0];
29077
+ const id = rel.split(path37.sep)[0];
28948
29078
  return id || null;
28949
29079
  }
28950
29080
 
@@ -28969,7 +29099,7 @@ function buildHistoryHandlers(deps) {
28969
29099
  if (!pid) return false;
28970
29100
  return isGuestPathAllowed(
28971
29101
  ctx.grants,
28972
- path37.join(personaRoot, pid),
29102
+ path38.join(personaRoot, pid),
28973
29103
  personaRoot,
28974
29104
  "read"
28975
29105
  );
@@ -28980,7 +29110,7 @@ function buildHistoryHandlers(deps) {
28980
29110
  };
28981
29111
  const list = async (frame, _client, ctx) => {
28982
29112
  const args = HistoryListArgs.parse(frame);
28983
- assertGuestPath(ctx, path37.resolve(args.projectPath), personaRoot, "history:list");
29113
+ assertGuestPath(ctx, path38.resolve(args.projectPath), personaRoot, "history:list");
28984
29114
  const sessions = await history.listSessions(args);
28985
29115
  return { response: { type: "history:list", sessions } };
28986
29116
  };
@@ -29012,13 +29142,13 @@ function buildHistoryHandlers(deps) {
29012
29142
  };
29013
29143
  const subagents = async (frame, _client, ctx) => {
29014
29144
  const args = HistorySubagentsArgs.parse(frame);
29015
- assertGuestPath(ctx, path37.resolve(args.cwd), personaRoot, "history:subagents");
29145
+ assertGuestPath(ctx, path38.resolve(args.cwd), personaRoot, "history:subagents");
29016
29146
  const subs = await history.listSubagents(args);
29017
29147
  return { response: { type: "history:subagents", subagents: subs } };
29018
29148
  };
29019
29149
  const subagentRead = async (frame, _client, ctx) => {
29020
29150
  const args = HistorySubagentReadArgs.parse(frame);
29021
- assertGuestPath(ctx, path37.resolve(args.cwd), personaRoot, "history:subagent-read");
29151
+ assertGuestPath(ctx, path38.resolve(args.cwd), personaRoot, "history:subagent-read");
29022
29152
  const res = await history.readSubagent(args);
29023
29153
  return { response: { type: "history:subagent-read", ...res } };
29024
29154
  };
@@ -29026,7 +29156,7 @@ function buildHistoryHandlers(deps) {
29026
29156
  const dirs = listRecentDirs(store);
29027
29157
  if (ctx?.principal.kind === "guest" && personaRoot) {
29028
29158
  const filtered = dirs.filter(
29029
- (d) => isGuestPathAllowed(ctx.grants, path37.resolve(d.cwd), personaRoot, "read")
29159
+ (d) => isGuestPathAllowed(ctx.grants, path38.resolve(d.cwd), personaRoot, "read")
29030
29160
  );
29031
29161
  return { response: { type: "history:recentDirs", dirs: filtered } };
29032
29162
  }
@@ -29043,8 +29173,8 @@ function buildHistoryHandlers(deps) {
29043
29173
  }
29044
29174
 
29045
29175
  // src/handlers/workspace.ts
29046
- var path38 = __toESM(require("path"), 1);
29047
- var os13 = __toESM(require("os"), 1);
29176
+ var path39 = __toESM(require("path"), 1);
29177
+ var os14 = __toESM(require("os"), 1);
29048
29178
  init_protocol();
29049
29179
  init_protocol();
29050
29180
  function buildEnabledPluginNames(personaManager, personaId) {
@@ -29083,23 +29213,23 @@ function buildWorkspaceHandlers(deps) {
29083
29213
  const list = async (frame, _client, ctx) => {
29084
29214
  const args = WorkspaceListArgs.parse(frame);
29085
29215
  const isGuest = ctx?.principal.kind === "guest";
29086
- const fallbackCwd = isGuest && personaRoot ? personaRoot : os13.homedir();
29087
- const resolvedCwd = path38.resolve(args.cwd ?? fallbackCwd);
29088
- const target = args.path ? path38.resolve(resolvedCwd, args.path) : resolvedCwd;
29216
+ const fallbackCwd = isGuest && personaRoot ? personaRoot : os14.homedir();
29217
+ const resolvedCwd = path39.resolve(args.cwd ?? fallbackCwd);
29218
+ const target = args.path ? path39.resolve(resolvedCwd, args.path) : resolvedCwd;
29089
29219
  assertGuestPath2(ctx, target, personaRoot, "workspace:list");
29090
29220
  const res = workspace.list({ ...args, cwd: resolvedCwd });
29091
29221
  return { response: { type: "workspace:list", ...res } };
29092
29222
  };
29093
29223
  const read = async (frame, _client, ctx) => {
29094
29224
  const args = WorkspaceReadArgs.parse(frame);
29095
- const target = path38.isAbsolute(args.path) ? path38.resolve(args.path) : path38.resolve(args.cwd, args.path);
29225
+ const target = path39.isAbsolute(args.path) ? path39.resolve(args.path) : path39.resolve(args.cwd, args.path);
29096
29226
  assertGuestPath2(ctx, target, personaRoot, "workspace:read");
29097
29227
  const res = workspace.read(args);
29098
29228
  return { response: { type: "workspace:read", ...res } };
29099
29229
  };
29100
29230
  const skillsList = async (frame, _client, ctx) => {
29101
29231
  const args = SkillsListArgs.parse(frame);
29102
- const cwdAbs = path38.resolve(args.cwd);
29232
+ const cwdAbs = path39.resolve(args.cwd);
29103
29233
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list");
29104
29234
  const list2 = skills.list(args);
29105
29235
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -29111,7 +29241,7 @@ function buildWorkspaceHandlers(deps) {
29111
29241
  };
29112
29242
  const agentsList = async (frame, _client, ctx) => {
29113
29243
  const args = AgentsListArgs.parse(frame);
29114
- const cwdAbs = path38.resolve(args.cwd);
29244
+ const cwdAbs = path39.resolve(args.cwd);
29115
29245
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list");
29116
29246
  const list2 = agents.list(args);
29117
29247
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -29130,20 +29260,20 @@ function buildWorkspaceHandlers(deps) {
29130
29260
  }
29131
29261
 
29132
29262
  // src/handlers/git.ts
29133
- var path40 = __toESM(require("path"), 1);
29263
+ var path41 = __toESM(require("path"), 1);
29134
29264
  init_protocol();
29135
29265
  init_protocol();
29136
29266
 
29137
29267
  // src/workspace/git.ts
29138
29268
  var import_node_child_process6 = require("child_process");
29139
- var import_node_fs26 = __toESM(require("fs"), 1);
29140
- var import_node_path28 = __toESM(require("path"), 1);
29269
+ var import_node_fs27 = __toESM(require("fs"), 1);
29270
+ var import_node_path29 = __toESM(require("path"), 1);
29141
29271
  var import_node_util = require("util");
29142
29272
  var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
29143
29273
  function normalizePath(p2) {
29144
- const resolved = import_node_path28.default.resolve(p2);
29274
+ const resolved = import_node_path29.default.resolve(p2);
29145
29275
  try {
29146
- return import_node_fs26.default.realpathSync(resolved);
29276
+ return import_node_fs27.default.realpathSync(resolved);
29147
29277
  } catch {
29148
29278
  return resolved;
29149
29279
  }
@@ -29216,7 +29346,7 @@ async function listGitBranches(cwd) {
29216
29346
  // src/handlers/git.ts
29217
29347
  function assertGuestCwd(ctx, cwd, personaRoot, method) {
29218
29348
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
29219
- if (!isGuestPathAllowed(ctx.grants, path40.resolve(cwd), personaRoot, "read")) {
29349
+ if (!isGuestPathAllowed(ctx.grants, path41.resolve(cwd), personaRoot, "read")) {
29220
29350
  throw new ClawdError(
29221
29351
  ERROR_CODES.UNAUTHORIZED,
29222
29352
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -29579,7 +29709,7 @@ function buildWhoamiHandler(deps) {
29579
29709
  }
29580
29710
 
29581
29711
  // src/handlers/meta.ts
29582
- var import_node_os13 = __toESM(require("os"), 1);
29712
+ var import_node_os14 = __toESM(require("os"), 1);
29583
29713
  init_protocol();
29584
29714
 
29585
29715
  // src/version.ts
@@ -29609,7 +29739,7 @@ function buildReadyFrame(deps, client) {
29609
29739
  return {
29610
29740
  version,
29611
29741
  protocolVersion: PROTOCOL_VERSION,
29612
- hostname: import_node_os13.default.hostname(),
29742
+ hostname: import_node_os14.default.hostname(),
29613
29743
  os: process.platform,
29614
29744
  tools,
29615
29745
  runningSessions: info.runningSessions,
@@ -29703,7 +29833,7 @@ function buildPersonaHandlers(deps) {
29703
29833
  }
29704
29834
 
29705
29835
  // src/handlers/attachment.ts
29706
- var import_node_path29 = __toESM(require("path"), 1);
29836
+ var import_node_path30 = __toESM(require("path"), 1);
29707
29837
  init_protocol();
29708
29838
  init_protocol();
29709
29839
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -29757,12 +29887,12 @@ function buildAttachmentHandlers(deps) {
29757
29887
  `session ${args.sessionId} scope unresolved`
29758
29888
  );
29759
29889
  }
29760
- const cwdAbs = import_node_path29.default.resolve(sessionFile.cwd);
29761
- const candidateAbs = import_node_path29.default.isAbsolute(args.relPath) ? import_node_path29.default.resolve(args.relPath) : import_node_path29.default.resolve(cwdAbs, args.relPath);
29890
+ const cwdAbs = import_node_path30.default.resolve(sessionFile.cwd);
29891
+ const candidateAbs = import_node_path30.default.isAbsolute(args.relPath) ? import_node_path30.default.resolve(args.relPath) : import_node_path30.default.resolve(cwdAbs, args.relPath);
29762
29892
  assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
29763
29893
  const entries = deps.groupFileStore.list(scope, args.sessionId);
29764
29894
  const entry = entries.find((e) => {
29765
- const storedAbs = import_node_path29.default.isAbsolute(e.relPath) ? import_node_path29.default.resolve(e.relPath) : import_node_path29.default.resolve(cwdAbs, e.relPath);
29895
+ const storedAbs = import_node_path30.default.isAbsolute(e.relPath) ? import_node_path30.default.resolve(e.relPath) : import_node_path30.default.resolve(cwdAbs, e.relPath);
29766
29896
  return storedAbs === candidateAbs && !e.stale;
29767
29897
  });
29768
29898
  if (!entry) {
@@ -29786,7 +29916,7 @@ function buildAttachmentHandlers(deps) {
29786
29916
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
29787
29917
  const f = deps.sessionStore.read(sessionId);
29788
29918
  if (!f) return;
29789
- assertGuestAttachmentPath(ctx, import_node_path29.default.resolve(f.cwd), deps.personaRoot, method);
29919
+ assertGuestAttachmentPath(ctx, import_node_path30.default.resolve(f.cwd), deps.personaRoot, method);
29790
29920
  }
29791
29921
  const groupAdd = async (frame, _client, ctx) => {
29792
29922
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -30023,7 +30153,7 @@ function computeGrantForFrame(method, frame) {
30023
30153
  async function startDaemon(config) {
30024
30154
  const logger = createLogger({
30025
30155
  level: config.logLevel,
30026
- file: import_node_path30.default.join(config.dataDir, "clawd.log")
30156
+ file: import_node_path31.default.join(config.dataDir, "clawd.log")
30027
30157
  });
30028
30158
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
30029
30159
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -30110,7 +30240,7 @@ async function startDaemon(config) {
30110
30240
  const agents = new AgentsScanner();
30111
30241
  const history = new ClaudeHistoryReader();
30112
30242
  let transport = null;
30113
- const personaStore = new PersonaStore(import_node_path30.default.join(config.dataDir, "personas"));
30243
+ const personaStore = new PersonaStore(import_node_path31.default.join(config.dataDir, "personas"));
30114
30244
  const defaultsRoot = findDefaultsRoot();
30115
30245
  if (defaultsRoot) {
30116
30246
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -30127,7 +30257,7 @@ async function startDaemon(config) {
30127
30257
  getAdapter,
30128
30258
  historyReader: history,
30129
30259
  dataDir: config.dataDir,
30130
- personaRoot: import_node_path30.default.join(config.dataDir, "personas"),
30260
+ personaRoot: import_node_path31.default.join(config.dataDir, "personas"),
30131
30261
  personaStore,
30132
30262
  ownerDisplayName,
30133
30263
  ownerPrincipalId,
@@ -30151,10 +30281,10 @@ async function startDaemon(config) {
30151
30281
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
30152
30282
  attachmentGroup: {
30153
30283
  onFileEdit: (input) => {
30154
- const absPath = import_node_path30.default.isAbsolute(input.relPath) ? input.relPath : import_node_path30.default.join(input.cwd, input.relPath);
30284
+ const absPath = import_node_path31.default.isAbsolute(input.relPath) ? input.relPath : import_node_path31.default.join(input.cwd, input.relPath);
30155
30285
  let size = 0;
30156
30286
  try {
30157
- size = import_node_fs27.default.statSync(absPath).size;
30287
+ size = import_node_fs28.default.statSync(absPath).size;
30158
30288
  } catch (err) {
30159
30289
  logger.warn("attachment.onFileEdit stat failed", {
30160
30290
  sessionId: input.sessionId,
@@ -30180,6 +30310,11 @@ async function startDaemon(config) {
30180
30310
  }
30181
30311
  });
30182
30312
  const observer = new SessionObserver({
30313
+ // TUI 模式 pty 跑 CC 不发 SDK system.task_started 帧 → UI pending 期 progress.agentId
30314
+ // 永远 undefined,子 agent 调用过程没有抽屉入口。开 meta observer 后从 subagents 目录
30315
+ // 新出现的 agent-*.meta.json 派生 subagent_progress(started) 补这块缺口。SDK 模式仍走
30316
+ // task_started 路径,避免双 emit 让 ring buffer 双帧。
30317
+ enableSubagentMetaObserver: config.mode === "tui",
30183
30318
  onEvent: ({ sessionId, events }) => {
30184
30319
  manager.feedObserverEvents(sessionId, events);
30185
30320
  },
@@ -30267,10 +30402,10 @@ async function startDaemon(config) {
30267
30402
  // 'persona/<pid>/owner',default 走 'default'。
30268
30403
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
30269
30404
  // guest path guard:candidate 必须在 personaRoot 子树下
30270
- personaRoot: import_node_path30.default.join(config.dataDir, "personas")
30405
+ personaRoot: import_node_path31.default.join(config.dataDir, "personas")
30271
30406
  },
30272
30407
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
30273
- personaRoot: import_node_path30.default.join(config.dataDir, "personas"),
30408
+ personaRoot: import_node_path31.default.join(config.dataDir, "personas"),
30274
30409
  // capability:list / delete handler 依赖
30275
30410
  capabilityManager,
30276
30411
  // personal-cap:get 返回的 shareBaseUrl 用此 base URL:
@@ -30483,8 +30618,8 @@ async function startDaemon(config) {
30483
30618
  const lines = [
30484
30619
  `Tunnel: ${r.url}`,
30485
30620
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
30486
- `Frpc config: ${import_node_path30.default.join(config.dataDir, "frpc.toml")}`,
30487
- `Frpc log: ${import_node_path30.default.join(config.dataDir, "frpc.log")}`
30621
+ `Frpc config: ${import_node_path31.default.join(config.dataDir, "frpc.toml")}`,
30622
+ `Frpc log: ${import_node_path31.default.join(config.dataDir, "frpc.log")}`
30488
30623
  ];
30489
30624
  const width = Math.max(...lines.map((l) => l.length));
30490
30625
  const bar = "\u2550".repeat(width + 4);
@@ -30497,8 +30632,8 @@ ${bar}
30497
30632
 
30498
30633
  `);
30499
30634
  try {
30500
- const connectPath = import_node_path30.default.join(config.dataDir, "connect.txt");
30501
- import_node_fs27.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
30635
+ const connectPath = import_node_path31.default.join(config.dataDir, "connect.txt");
30636
+ import_node_fs28.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
30502
30637
  } catch {
30503
30638
  }
30504
30639
  } catch (err) {
@@ -30563,9 +30698,9 @@ ${bar}
30563
30698
  };
30564
30699
  }
30565
30700
  function migrateDropPersonsDir(dataDir) {
30566
- const dir = import_node_path30.default.join(dataDir, "persons");
30701
+ const dir = import_node_path31.default.join(dataDir, "persons");
30567
30702
  try {
30568
- import_node_fs27.default.rmSync(dir, { recursive: true, force: true });
30703
+ import_node_fs28.default.rmSync(dir, { recursive: true, force: true });
30569
30704
  } catch {
30570
30705
  }
30571
30706
  }