@clawos-dev/clawd 0.2.23-beta.34.136a698 → 0.2.24

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 +306 -237
  2. package/package.json +1 -1
package/dist/cli.cjs CHANGED
@@ -293,8 +293,8 @@ var require_req = __commonJS({
293
293
  if (req.originalUrl) {
294
294
  _req.url = req.originalUrl;
295
295
  } else {
296
- const path17 = req.path;
297
- _req.url = typeof path17 === "string" ? path17 : req.url ? req.url.path || req.url : void 0;
296
+ const path18 = req.path;
297
+ _req.url = typeof path18 === "string" ? path18 : req.url ? req.url.path || req.url : void 0;
298
298
  }
299
299
  if (req.query) {
300
300
  _req.query = req.query;
@@ -459,14 +459,14 @@ var require_redact = __commonJS({
459
459
  }
460
460
  return obj;
461
461
  }
462
- function parsePath(path17) {
462
+ function parsePath(path18) {
463
463
  const parts = [];
464
464
  let current = "";
465
465
  let inBrackets = false;
466
466
  let inQuotes = false;
467
467
  let quoteChar = "";
468
- for (let i = 0; i < path17.length; i++) {
469
- const char = path17[i];
468
+ for (let i = 0; i < path18.length; i++) {
469
+ const char = path18[i];
470
470
  if (!inBrackets && char === ".") {
471
471
  if (current) {
472
472
  parts.push(current);
@@ -597,10 +597,10 @@ var require_redact = __commonJS({
597
597
  return current;
598
598
  }
599
599
  function redactPaths(obj, paths, censor, remove = false) {
600
- for (const path17 of paths) {
601
- const parts = parsePath(path17);
600
+ for (const path18 of paths) {
601
+ const parts = parsePath(path18);
602
602
  if (parts.includes("*")) {
603
- redactWildcardPath(obj, parts, censor, path17, remove);
603
+ redactWildcardPath(obj, parts, censor, path18, remove);
604
604
  } else {
605
605
  if (remove) {
606
606
  removeKey(obj, parts);
@@ -685,8 +685,8 @@ var require_redact = __commonJS({
685
685
  }
686
686
  } else {
687
687
  if (afterWildcard.includes("*")) {
688
- const wrappedCensor = typeof censor === "function" ? (value, path17) => {
689
- const fullPath = [...pathArray.slice(0, pathLength), ...path17];
688
+ const wrappedCensor = typeof censor === "function" ? (value, path18) => {
689
+ const fullPath = [...pathArray.slice(0, pathLength), ...path18];
690
690
  return censor(value, fullPath);
691
691
  } : censor;
692
692
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -721,8 +721,8 @@ var require_redact = __commonJS({
721
721
  return null;
722
722
  }
723
723
  const pathStructure = /* @__PURE__ */ new Map();
724
- for (const path17 of pathsToClone) {
725
- const parts = parsePath(path17);
724
+ for (const path18 of pathsToClone) {
725
+ const parts = parsePath(path18);
726
726
  let current = pathStructure;
727
727
  for (let i = 0; i < parts.length; i++) {
728
728
  const part = parts[i];
@@ -774,24 +774,24 @@ var require_redact = __commonJS({
774
774
  }
775
775
  return cloneSelectively(obj, pathStructure);
776
776
  }
777
- function validatePath(path17) {
778
- if (typeof path17 !== "string") {
777
+ function validatePath(path18) {
778
+ if (typeof path18 !== "string") {
779
779
  throw new Error("Paths must be (non-empty) strings");
780
780
  }
781
- if (path17 === "") {
781
+ if (path18 === "") {
782
782
  throw new Error("Invalid redaction path ()");
783
783
  }
784
- if (path17.includes("..")) {
785
- throw new Error(`Invalid redaction path (${path17})`);
784
+ if (path18.includes("..")) {
785
+ throw new Error(`Invalid redaction path (${path18})`);
786
786
  }
787
- if (path17.includes(",")) {
788
- throw new Error(`Invalid redaction path (${path17})`);
787
+ if (path18.includes(",")) {
788
+ throw new Error(`Invalid redaction path (${path18})`);
789
789
  }
790
790
  let bracketCount = 0;
791
791
  let inQuotes = false;
792
792
  let quoteChar = "";
793
- for (let i = 0; i < path17.length; i++) {
794
- const char = path17[i];
793
+ for (let i = 0; i < path18.length; i++) {
794
+ const char = path18[i];
795
795
  if ((char === '"' || char === "'") && bracketCount > 0) {
796
796
  if (!inQuotes) {
797
797
  inQuotes = true;
@@ -805,20 +805,20 @@ var require_redact = __commonJS({
805
805
  } else if (char === "]" && !inQuotes) {
806
806
  bracketCount--;
807
807
  if (bracketCount < 0) {
808
- throw new Error(`Invalid redaction path (${path17})`);
808
+ throw new Error(`Invalid redaction path (${path18})`);
809
809
  }
810
810
  }
811
811
  }
812
812
  if (bracketCount !== 0) {
813
- throw new Error(`Invalid redaction path (${path17})`);
813
+ throw new Error(`Invalid redaction path (${path18})`);
814
814
  }
815
815
  }
816
816
  function validatePaths(paths) {
817
817
  if (!Array.isArray(paths)) {
818
818
  throw new TypeError("paths must be an array");
819
819
  }
820
- for (const path17 of paths) {
821
- validatePath(path17);
820
+ for (const path18 of paths) {
821
+ validatePath(path18);
822
822
  }
823
823
  }
824
824
  function slowRedact(options = {}) {
@@ -986,8 +986,8 @@ var require_redaction = __commonJS({
986
986
  if (shape[k] === null) {
987
987
  o[k] = (value) => topCensor(value, [k]);
988
988
  } else {
989
- const wrappedCensor = typeof censor === "function" ? (value, path17) => {
990
- return censor(value, [k, ...path17]);
989
+ const wrappedCensor = typeof censor === "function" ? (value, path18) => {
990
+ return censor(value, [k, ...path18]);
991
991
  } : censor;
992
992
  o[k] = Redact({
993
993
  paths: shape[k],
@@ -1205,10 +1205,10 @@ var require_atomic_sleep = __commonJS({
1205
1205
  var require_sonic_boom = __commonJS({
1206
1206
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
1207
1207
  "use strict";
1208
- var fs18 = require("fs");
1208
+ var fs19 = require("fs");
1209
1209
  var EventEmitter = require("events");
1210
1210
  var inherits = require("util").inherits;
1211
- var path17 = require("path");
1211
+ var path18 = require("path");
1212
1212
  var sleep = require_atomic_sleep();
1213
1213
  var assert = require("assert");
1214
1214
  var BUSY_WRITE_TIMEOUT = 100;
@@ -1262,20 +1262,20 @@ var require_sonic_boom = __commonJS({
1262
1262
  const mode = sonic.mode;
1263
1263
  if (sonic.sync) {
1264
1264
  try {
1265
- if (sonic.mkdir) fs18.mkdirSync(path17.dirname(file), { recursive: true });
1266
- const fd = fs18.openSync(file, flags, mode);
1265
+ if (sonic.mkdir) fs19.mkdirSync(path18.dirname(file), { recursive: true });
1266
+ const fd = fs19.openSync(file, flags, mode);
1267
1267
  fileOpened(null, fd);
1268
1268
  } catch (err) {
1269
1269
  fileOpened(err);
1270
1270
  throw err;
1271
1271
  }
1272
1272
  } else if (sonic.mkdir) {
1273
- fs18.mkdir(path17.dirname(file), { recursive: true }, (err) => {
1273
+ fs19.mkdir(path18.dirname(file), { recursive: true }, (err) => {
1274
1274
  if (err) return fileOpened(err);
1275
- fs18.open(file, flags, mode, fileOpened);
1275
+ fs19.open(file, flags, mode, fileOpened);
1276
1276
  });
1277
1277
  } else {
1278
- fs18.open(file, flags, mode, fileOpened);
1278
+ fs19.open(file, flags, mode, fileOpened);
1279
1279
  }
1280
1280
  }
1281
1281
  function SonicBoom(opts) {
@@ -1316,8 +1316,8 @@ var require_sonic_boom = __commonJS({
1316
1316
  this.flush = flushBuffer;
1317
1317
  this.flushSync = flushBufferSync;
1318
1318
  this._actualWrite = actualWriteBuffer;
1319
- fsWriteSync = () => fs18.writeSync(this.fd, this._writingBuf);
1320
- fsWrite = () => fs18.write(this.fd, this._writingBuf, this.release);
1319
+ fsWriteSync = () => fs19.writeSync(this.fd, this._writingBuf);
1320
+ fsWrite = () => fs19.write(this.fd, this._writingBuf, this.release);
1321
1321
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
1322
1322
  this._writingBuf = "";
1323
1323
  this.write = write;
@@ -1326,15 +1326,15 @@ var require_sonic_boom = __commonJS({
1326
1326
  this._actualWrite = actualWrite;
1327
1327
  fsWriteSync = () => {
1328
1328
  if (Buffer.isBuffer(this._writingBuf)) {
1329
- return fs18.writeSync(this.fd, this._writingBuf);
1329
+ return fs19.writeSync(this.fd, this._writingBuf);
1330
1330
  }
1331
- return fs18.writeSync(this.fd, this._writingBuf, "utf8");
1331
+ return fs19.writeSync(this.fd, this._writingBuf, "utf8");
1332
1332
  };
1333
1333
  fsWrite = () => {
1334
1334
  if (Buffer.isBuffer(this._writingBuf)) {
1335
- return fs18.write(this.fd, this._writingBuf, this.release);
1335
+ return fs19.write(this.fd, this._writingBuf, this.release);
1336
1336
  }
1337
- return fs18.write(this.fd, this._writingBuf, "utf8", this.release);
1337
+ return fs19.write(this.fd, this._writingBuf, "utf8", this.release);
1338
1338
  };
1339
1339
  } else {
1340
1340
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -1391,7 +1391,7 @@ var require_sonic_boom = __commonJS({
1391
1391
  }
1392
1392
  }
1393
1393
  if (this._fsync) {
1394
- fs18.fsyncSync(this.fd);
1394
+ fs19.fsyncSync(this.fd);
1395
1395
  }
1396
1396
  const len = this._len;
1397
1397
  if (this._reopening) {
@@ -1505,7 +1505,7 @@ var require_sonic_boom = __commonJS({
1505
1505
  const onDrain = () => {
1506
1506
  if (!this._fsync) {
1507
1507
  try {
1508
- fs18.fsync(this.fd, (err) => {
1508
+ fs19.fsync(this.fd, (err) => {
1509
1509
  this._flushPending = false;
1510
1510
  cb(err);
1511
1511
  });
@@ -1607,7 +1607,7 @@ var require_sonic_boom = __commonJS({
1607
1607
  const fd = this.fd;
1608
1608
  this.once("ready", () => {
1609
1609
  if (fd !== this.fd) {
1610
- fs18.close(fd, (err) => {
1610
+ fs19.close(fd, (err) => {
1611
1611
  if (err) {
1612
1612
  return this.emit("error", err);
1613
1613
  }
@@ -1656,7 +1656,7 @@ var require_sonic_boom = __commonJS({
1656
1656
  buf = this._bufs[0];
1657
1657
  }
1658
1658
  try {
1659
- const n = Buffer.isBuffer(buf) ? fs18.writeSync(this.fd, buf) : fs18.writeSync(this.fd, buf, "utf8");
1659
+ const n = Buffer.isBuffer(buf) ? fs19.writeSync(this.fd, buf) : fs19.writeSync(this.fd, buf, "utf8");
1660
1660
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
1661
1661
  buf = releasedBufObj.writingBuf;
1662
1662
  this._len = releasedBufObj.len;
@@ -1672,7 +1672,7 @@ var require_sonic_boom = __commonJS({
1672
1672
  }
1673
1673
  }
1674
1674
  try {
1675
- fs18.fsyncSync(this.fd);
1675
+ fs19.fsyncSync(this.fd);
1676
1676
  } catch {
1677
1677
  }
1678
1678
  }
@@ -1693,7 +1693,7 @@ var require_sonic_boom = __commonJS({
1693
1693
  buf = mergeBuf(this._bufs[0], this._lens[0]);
1694
1694
  }
1695
1695
  try {
1696
- const n = fs18.writeSync(this.fd, buf);
1696
+ const n = fs19.writeSync(this.fd, buf);
1697
1697
  buf = buf.subarray(n);
1698
1698
  this._len = Math.max(this._len - n, 0);
1699
1699
  if (buf.length <= 0) {
@@ -1721,13 +1721,13 @@ var require_sonic_boom = __commonJS({
1721
1721
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
1722
1722
  if (this.sync) {
1723
1723
  try {
1724
- const written = Buffer.isBuffer(this._writingBuf) ? fs18.writeSync(this.fd, this._writingBuf) : fs18.writeSync(this.fd, this._writingBuf, "utf8");
1724
+ const written = Buffer.isBuffer(this._writingBuf) ? fs19.writeSync(this.fd, this._writingBuf) : fs19.writeSync(this.fd, this._writingBuf, "utf8");
1725
1725
  release(null, written);
1726
1726
  } catch (err) {
1727
1727
  release(err);
1728
1728
  }
1729
1729
  } else {
1730
- fs18.write(this.fd, this._writingBuf, release);
1730
+ fs19.write(this.fd, this._writingBuf, release);
1731
1731
  }
1732
1732
  }
1733
1733
  function actualWriteBuffer() {
@@ -1736,7 +1736,7 @@ var require_sonic_boom = __commonJS({
1736
1736
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
1737
1737
  if (this.sync) {
1738
1738
  try {
1739
- const written = fs18.writeSync(this.fd, this._writingBuf);
1739
+ const written = fs19.writeSync(this.fd, this._writingBuf);
1740
1740
  release(null, written);
1741
1741
  } catch (err) {
1742
1742
  release(err);
@@ -1745,7 +1745,7 @@ var require_sonic_boom = __commonJS({
1745
1745
  if (kCopyBuffer) {
1746
1746
  this._writingBuf = Buffer.from(this._writingBuf);
1747
1747
  }
1748
- fs18.write(this.fd, this._writingBuf, release);
1748
+ fs19.write(this.fd, this._writingBuf, release);
1749
1749
  }
1750
1750
  }
1751
1751
  function actualClose(sonic) {
@@ -1761,12 +1761,12 @@ var require_sonic_boom = __commonJS({
1761
1761
  sonic._lens = [];
1762
1762
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
1763
1763
  try {
1764
- fs18.fsync(sonic.fd, closeWrapped);
1764
+ fs19.fsync(sonic.fd, closeWrapped);
1765
1765
  } catch {
1766
1766
  }
1767
1767
  function closeWrapped() {
1768
1768
  if (sonic.fd !== 1 && sonic.fd !== 2) {
1769
- fs18.close(sonic.fd, done);
1769
+ fs19.close(sonic.fd, done);
1770
1770
  } else {
1771
1771
  done();
1772
1772
  }
@@ -8075,8 +8075,8 @@ Env (advanced):
8075
8075
  `;
8076
8076
 
8077
8077
  // src/index.ts
8078
- var import_node_path16 = __toESM(require("path"), 1);
8079
- var import_node_fs17 = __toESM(require("fs"), 1);
8078
+ var import_node_path17 = __toESM(require("path"), 1);
8079
+ var import_node_fs18 = __toESM(require("fs"), 1);
8080
8080
 
8081
8081
  // src/logger.ts
8082
8082
  var import_node_fs2 = __toESM(require("fs"), 1);
@@ -8687,8 +8687,8 @@ function getErrorMap() {
8687
8687
 
8688
8688
  // ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
8689
8689
  var makeIssue = (params) => {
8690
- const { data, path: path17, errorMaps, issueData } = params;
8691
- const fullPath = [...path17, ...issueData.path || []];
8690
+ const { data, path: path18, errorMaps, issueData } = params;
8691
+ const fullPath = [...path18, ...issueData.path || []];
8692
8692
  const fullIssue = {
8693
8693
  ...issueData,
8694
8694
  path: fullPath
@@ -8804,11 +8804,11 @@ var errorUtil;
8804
8804
 
8805
8805
  // ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
8806
8806
  var ParseInputLazyPath = class {
8807
- constructor(parent, value, path17, key) {
8807
+ constructor(parent, value, path18, key) {
8808
8808
  this._cachedPath = [];
8809
8809
  this.parent = parent;
8810
8810
  this.data = value;
8811
- this._path = path17;
8811
+ this._path = path18;
8812
8812
  this._key = key;
8813
8813
  }
8814
8814
  get path() {
@@ -12819,7 +12819,7 @@ var SessionStore = class {
12819
12819
  };
12820
12820
 
12821
12821
  // src/session/manager.ts
12822
- var import_node_fs4 = __toESM(require("fs"), 1);
12822
+ var import_node_fs5 = __toESM(require("fs"), 1);
12823
12823
 
12824
12824
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
12825
12825
  var byteToHex = [];
@@ -13408,6 +13408,58 @@ function reduceSession(state, input, deps) {
13408
13408
  }
13409
13409
  }
13410
13410
 
13411
+ // src/ipc-recorder.ts
13412
+ var import_node_fs4 = __toESM(require("fs"), 1);
13413
+ var import_node_path4 = __toESM(require("path"), 1);
13414
+ function tsForFilename(ms) {
13415
+ return new Date(ms).toISOString().replace(/[:.]/g, "-");
13416
+ }
13417
+ function startRecorder(opts) {
13418
+ if (opts.env.CLAWD_RECORD_IPC !== "1") return null;
13419
+ if (!opts.dataDir) return null;
13420
+ if (!opts.sessionId || opts.sessionId.includes("..") || opts.sessionId.includes("/") || opts.sessionId.includes("\\") || opts.sessionId.startsWith(".")) {
13421
+ return null;
13422
+ }
13423
+ const now = opts.now ?? Date.now;
13424
+ const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
13425
+ const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
13426
+ let stream = null;
13427
+ let closedResolve;
13428
+ const closed = new Promise((resolve) => {
13429
+ closedResolve = resolve;
13430
+ });
13431
+ let exited = false;
13432
+ const ensureStream = () => {
13433
+ if (stream) return stream;
13434
+ import_node_fs4.default.mkdirSync(dir, { recursive: true });
13435
+ stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
13436
+ stream.on("close", () => closedResolve());
13437
+ return stream;
13438
+ };
13439
+ const writeLine = (s, chunk) => {
13440
+ if (exited) return;
13441
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
13442
+ const line = JSON.stringify({ ts: now(), stream: s, chunk: text }) + "\n";
13443
+ ensureStream().write(line);
13444
+ };
13445
+ opts.proc.stdout?.on("data", (chunk) => writeLine("stdout", chunk));
13446
+ opts.proc.stderr?.on("data", (chunk) => writeLine("stderr", chunk));
13447
+ opts.proc.on("exit", () => {
13448
+ exited = true;
13449
+ if (stream) {
13450
+ stream.end();
13451
+ } else {
13452
+ closedResolve();
13453
+ }
13454
+ });
13455
+ return {
13456
+ tapStdinWrite(chunk) {
13457
+ writeLine("stdin", chunk);
13458
+ },
13459
+ closed
13460
+ };
13461
+ }
13462
+
13411
13463
  // src/session/runner.ts
13412
13464
  var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
13413
13465
  function encodeAllowWithInputControlResponse(requestId, updatedInput) {
@@ -13438,6 +13490,8 @@ var SessionRunner = class {
13438
13490
  pendingControlRequests = /* @__PURE__ */ new Map();
13439
13491
  // waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
13440
13492
  stopWaiters = [];
13493
+ // IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
13494
+ recorder = null;
13441
13495
  getState() {
13442
13496
  return this.state;
13443
13497
  }
@@ -13527,6 +13581,7 @@ var SessionRunner = class {
13527
13581
  this.pendingControlRequests.set(requestId, { resolve, reject, timer });
13528
13582
  try {
13529
13583
  proc.stdin?.write(payload);
13584
+ this.recorder?.tapStdinWrite(payload);
13530
13585
  } catch (err) {
13531
13586
  clearTimeout(timer);
13532
13587
  this.pendingControlRequests.delete(requestId);
@@ -13582,10 +13637,14 @@ var SessionRunner = class {
13582
13637
  break;
13583
13638
  case "write-stdin":
13584
13639
  this.proc?.stdin?.write(effect.payload);
13640
+ this.recorder?.tapStdinWrite(effect.payload);
13585
13641
  break;
13586
- case "send-control-response-allow-with-input":
13587
- this.proc?.stdin?.write(encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput));
13642
+ case "send-control-response-allow-with-input": {
13643
+ const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
13644
+ this.proc?.stdin?.write(payload);
13645
+ this.recorder?.tapStdinWrite(payload);
13588
13646
  break;
13647
+ }
13589
13648
  case "persist-file":
13590
13649
  try {
13591
13650
  this.hooks.store.write(effect.file);
@@ -13615,6 +13674,13 @@ var SessionRunner = class {
13615
13674
  const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
13616
13675
  this.proc = proc;
13617
13676
  this.stdoutBuf = "";
13677
+ this.recorder = startRecorder({
13678
+ proc,
13679
+ sessionId: this.state.file.sessionId,
13680
+ dataDir: this.hooks.dataDir,
13681
+ env: this.hooks.recordEnv ?? process.env,
13682
+ now: this.hooks.now
13683
+ });
13618
13684
  proc.stdout?.on("data", (chunk) => {
13619
13685
  this.stdoutBuf += typeof chunk === "string" ? chunk : chunk.toString("utf8");
13620
13686
  let idx;
@@ -13631,6 +13697,7 @@ var SessionRunner = class {
13631
13697
  });
13632
13698
  proc.on("exit", (code) => {
13633
13699
  this.proc = null;
13700
+ this.recorder = null;
13634
13701
  this.rejectAllPending(new Error("session gone"));
13635
13702
  this.input({ kind: "proc-exit", code });
13636
13703
  });
@@ -13757,7 +13824,8 @@ var SessionManager = class {
13757
13824
  now: this.deps.now,
13758
13825
  bufferCap: this.deps.bufferCap,
13759
13826
  // adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
13760
- resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
13827
+ resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
13828
+ dataDir: this.deps.dataDir
13761
13829
  });
13762
13830
  return runner;
13763
13831
  }
@@ -13788,7 +13856,7 @@ var SessionManager = class {
13788
13856
  // ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
13789
13857
  create(args) {
13790
13858
  try {
13791
- const stat = import_node_fs4.default.statSync(args.cwd);
13859
+ const stat = import_node_fs5.default.statSync(args.cwd);
13792
13860
  if (!stat.isDirectory()) throw new Error("not dir");
13793
13861
  } catch {
13794
13862
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -14277,14 +14345,14 @@ var SessionManager = class {
14277
14345
  // src/tools/claude.ts
14278
14346
  var import_node_child_process = require("child_process");
14279
14347
  var import_node_child_process2 = require("child_process");
14280
- var import_node_fs6 = __toESM(require("fs"), 1);
14348
+ var import_node_fs7 = __toESM(require("fs"), 1);
14281
14349
  var import_node_os3 = __toESM(require("os"), 1);
14282
- var import_node_path5 = __toESM(require("path"), 1);
14350
+ var import_node_path6 = __toESM(require("path"), 1);
14283
14351
 
14284
14352
  // src/tools/claude-history.ts
14285
- var import_node_fs5 = __toESM(require("fs"), 1);
14353
+ var import_node_fs6 = __toESM(require("fs"), 1);
14286
14354
  var import_node_os2 = __toESM(require("os"), 1);
14287
- var import_node_path4 = __toESM(require("path"), 1);
14355
+ var import_node_path5 = __toESM(require("path"), 1);
14288
14356
 
14289
14357
  // ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
14290
14358
  function Diff() {
@@ -14388,11 +14456,11 @@ Diff.prototype = {
14388
14456
  }
14389
14457
  }
14390
14458
  },
14391
- addToPath: function addToPath(path17, added, removed, oldPosInc, options) {
14392
- var last = path17.lastComponent;
14459
+ addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
14460
+ var last = path18.lastComponent;
14393
14461
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14394
14462
  return {
14395
- oldPos: path17.oldPos + oldPosInc,
14463
+ oldPos: path18.oldPos + oldPosInc,
14396
14464
  lastComponent: {
14397
14465
  count: last.count + 1,
14398
14466
  added,
@@ -14402,7 +14470,7 @@ Diff.prototype = {
14402
14470
  };
14403
14471
  } else {
14404
14472
  return {
14405
- oldPos: path17.oldPos + oldPosInc,
14473
+ oldPos: path18.oldPos + oldPosInc,
14406
14474
  lastComponent: {
14407
14475
  count: 1,
14408
14476
  added,
@@ -15061,7 +15129,7 @@ function hashDirToCwd(hash) {
15061
15129
  }
15062
15130
  function safeStatMtime(p) {
15063
15131
  try {
15064
- return import_node_fs5.default.statSync(p).mtimeMs;
15132
+ return import_node_fs6.default.statSync(p).mtimeMs;
15065
15133
  } catch {
15066
15134
  return 0;
15067
15135
  }
@@ -15069,7 +15137,7 @@ function safeStatMtime(p) {
15069
15137
  function readJsonlLines(file) {
15070
15138
  let raw;
15071
15139
  try {
15072
- raw = import_node_fs5.default.readFileSync(file, "utf8");
15140
+ raw = import_node_fs6.default.readFileSync(file, "utf8");
15073
15141
  } catch (err) {
15074
15142
  if (err.code === "ENOENT") return [];
15075
15143
  throw err;
@@ -15261,10 +15329,10 @@ function attachmentToHistoryMessage(o, ts) {
15261
15329
  const memories = raw.map((m) => {
15262
15330
  if (!m || typeof m !== "object") return null;
15263
15331
  const rec = m;
15264
- const path17 = typeof rec.path === "string" ? rec.path : null;
15332
+ const path18 = typeof rec.path === "string" ? rec.path : null;
15265
15333
  const content = typeof rec.content === "string" ? rec.content : null;
15266
- if (!path17 || content == null) return null;
15267
- const entry = { path: path17, content };
15334
+ if (!path18 || content == null) return null;
15335
+ const entry = { path: path18, content };
15268
15336
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
15269
15337
  return entry;
15270
15338
  }).filter((m) => m !== null);
@@ -15300,8 +15368,8 @@ function attachmentDeferredToolsText(a) {
15300
15368
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
15301
15369
  if (backupFileName === null) return null;
15302
15370
  try {
15303
- return import_node_fs5.default.readFileSync(
15304
- import_node_path4.default.join(fileHistoryRoot, toolSessionId, backupFileName),
15371
+ return import_node_fs6.default.readFileSync(
15372
+ import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
15305
15373
  "utf8"
15306
15374
  );
15307
15375
  } catch {
@@ -15310,7 +15378,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
15310
15378
  }
15311
15379
  function readCurrentContent(filePath) {
15312
15380
  try {
15313
- return import_node_fs5.default.readFileSync(filePath, "utf8");
15381
+ return import_node_fs6.default.readFileSync(filePath, "utf8");
15314
15382
  } catch (err) {
15315
15383
  if (err.code === "ENOENT") return null;
15316
15384
  return null;
@@ -15322,14 +15390,14 @@ var ClaudeHistoryReader = class {
15322
15390
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
15323
15391
  fileHistoryRoot;
15324
15392
  constructor(opts = {}) {
15325
- const base = opts.baseDir ?? import_node_path4.default.join(import_node_os2.default.homedir(), ".claude");
15326
- this.projectsRoot = import_node_path4.default.join(base, "projects");
15327
- this.fileHistoryRoot = import_node_path4.default.join(base, "file-history");
15393
+ const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
15394
+ this.projectsRoot = import_node_path5.default.join(base, "projects");
15395
+ this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
15328
15396
  }
15329
15397
  async listProjects() {
15330
15398
  let entries;
15331
15399
  try {
15332
- entries = import_node_fs5.default.readdirSync(this.projectsRoot, { withFileTypes: true });
15400
+ entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
15333
15401
  } catch (err) {
15334
15402
  if (err.code === "ENOENT") return [];
15335
15403
  throw err;
@@ -15337,9 +15405,9 @@ var ClaudeHistoryReader = class {
15337
15405
  const out = [];
15338
15406
  for (const ent of entries) {
15339
15407
  if (!ent.isDirectory()) continue;
15340
- const dir = import_node_path4.default.join(this.projectsRoot, ent.name);
15341
- const files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15342
- const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path4.default.join(dir, f))), 0);
15408
+ const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
15409
+ const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15410
+ const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
15343
15411
  out.push({
15344
15412
  projectPath: hashDirToCwd(ent.name),
15345
15413
  hashDir: ent.name,
@@ -15351,17 +15419,17 @@ var ClaudeHistoryReader = class {
15351
15419
  return out;
15352
15420
  }
15353
15421
  async listSessions(args) {
15354
- const dir = import_node_path4.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
15422
+ const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
15355
15423
  let files;
15356
15424
  try {
15357
- files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15425
+ files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15358
15426
  } catch (err) {
15359
15427
  if (err.code === "ENOENT") return [];
15360
15428
  throw err;
15361
15429
  }
15362
15430
  const out = [];
15363
15431
  for (const f of files) {
15364
- const full = import_node_path4.default.join(dir, f);
15432
+ const full = import_node_path5.default.join(dir, f);
15365
15433
  const toolSessionId = f.slice(0, -".jsonl".length);
15366
15434
  const lines = readJsonlLines(full);
15367
15435
  let summary = "";
@@ -15416,7 +15484,7 @@ var ClaudeHistoryReader = class {
15416
15484
  return out;
15417
15485
  }
15418
15486
  async read(args) {
15419
- const file = import_node_path4.default.join(
15487
+ const file = import_node_path5.default.join(
15420
15488
  this.projectsRoot,
15421
15489
  cwdToHashDir(args.cwd),
15422
15490
  `${args.toolSessionId}.jsonl`
@@ -15449,7 +15517,7 @@ var ClaudeHistoryReader = class {
15449
15517
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
15450
15518
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
15451
15519
  listSubagentsFromDirectory(cwd, toolSessionId) {
15452
- const dir = import_node_path4.default.join(
15520
+ const dir = import_node_path5.default.join(
15453
15521
  this.projectsRoot,
15454
15522
  cwdToHashDir(cwd),
15455
15523
  toolSessionId,
@@ -15457,7 +15525,7 @@ var ClaudeHistoryReader = class {
15457
15525
  );
15458
15526
  let entries;
15459
15527
  try {
15460
- entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
15528
+ entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
15461
15529
  } catch (err) {
15462
15530
  if (err.code === "ENOENT") return null;
15463
15531
  return null;
@@ -15467,7 +15535,7 @@ var ClaudeHistoryReader = class {
15467
15535
  if (!e.isFile()) continue;
15468
15536
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
15469
15537
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
15470
- const filePath = import_node_path4.default.join(dir, e.name);
15538
+ const filePath = import_node_path5.default.join(dir, e.name);
15471
15539
  const lines = readJsonlLines(filePath);
15472
15540
  let firstText = "";
15473
15541
  let messageCount = 0;
@@ -15484,7 +15552,7 @@ var ClaudeHistoryReader = class {
15484
15552
  return out;
15485
15553
  }
15486
15554
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
15487
- const file = import_node_path4.default.join(
15555
+ const file = import_node_path5.default.join(
15488
15556
  this.projectsRoot,
15489
15557
  cwdToHashDir(cwd),
15490
15558
  `${toolSessionId}.jsonl`
@@ -15519,7 +15587,7 @@ var ClaudeHistoryReader = class {
15519
15587
  }
15520
15588
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
15521
15589
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
15522
- const file = import_node_path4.default.join(
15590
+ const file = import_node_path5.default.join(
15523
15591
  this.projectsRoot,
15524
15592
  cwdToHashDir(cwd),
15525
15593
  toolSessionId,
@@ -15528,7 +15596,7 @@ var ClaudeHistoryReader = class {
15528
15596
  );
15529
15597
  let exists = false;
15530
15598
  try {
15531
- exists = import_node_fs5.default.statSync(file).isFile();
15599
+ exists = import_node_fs6.default.statSync(file).isFile();
15532
15600
  } catch {
15533
15601
  return null;
15534
15602
  }
@@ -15547,7 +15615,7 @@ var ClaudeHistoryReader = class {
15547
15615
  * "那一刻每个 tracked 文件对应的 backup 文件名"
15548
15616
  */
15549
15617
  readFileHistorySnapshots(args) {
15550
- const file = import_node_path4.default.join(
15618
+ const file = import_node_path5.default.join(
15551
15619
  this.projectsRoot,
15552
15620
  cwdToHashDir(args.cwd),
15553
15621
  `${args.toolSessionId}.jsonl`
@@ -15592,7 +15660,7 @@ var ClaudeHistoryReader = class {
15592
15660
  for (const [anchorId, target] of snapshots) {
15593
15661
  let hasAny = false;
15594
15662
  for (const [rawPath, backup] of Object.entries(target)) {
15595
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
15663
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
15596
15664
  const backupContent = readBackupContent(
15597
15665
  this.fileHistoryRoot,
15598
15666
  args.toolSessionId,
@@ -15632,7 +15700,7 @@ var ClaudeHistoryReader = class {
15632
15700
  let totalInsertions = 0;
15633
15701
  let totalDeletions = 0;
15634
15702
  for (const [rawPath, backup] of Object.entries(target)) {
15635
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
15703
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
15636
15704
  const backupContent = readBackupContent(
15637
15705
  this.fileHistoryRoot,
15638
15706
  args.toolSessionId,
@@ -15679,7 +15747,7 @@ var ClaudeHistoryReader = class {
15679
15747
  };
15680
15748
  }
15681
15749
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
15682
- const file = import_node_path4.default.join(
15750
+ const file = import_node_path5.default.join(
15683
15751
  this.projectsRoot,
15684
15752
  cwdToHashDir(cwd),
15685
15753
  `${toolSessionId}.jsonl`
@@ -15701,27 +15769,27 @@ var ClaudeHistoryReader = class {
15701
15769
  // src/tools/claude.ts
15702
15770
  function macOSDesktopCandidates(home) {
15703
15771
  return [
15704
- import_node_path5.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
15772
+ import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
15705
15773
  "/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
15706
15774
  ];
15707
15775
  }
15708
15776
  function probeViaWhich() {
15709
15777
  try {
15710
15778
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
15711
- if (out && import_node_fs6.default.existsSync(out)) return out;
15779
+ if (out && import_node_fs7.default.existsSync(out)) return out;
15712
15780
  } catch {
15713
15781
  }
15714
15782
  return null;
15715
15783
  }
15716
15784
  async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
15717
- if (env.CLAUDE_BIN && import_node_fs6.default.existsSync(env.CLAUDE_BIN)) {
15785
+ if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
15718
15786
  return { available: true, path: env.CLAUDE_BIN };
15719
15787
  }
15720
15788
  const w = probeViaWhich();
15721
15789
  if (w) return { available: true, path: w };
15722
15790
  if (process.platform === "darwin") {
15723
15791
  for (const candidate of macOSDesktopCandidates(home)) {
15724
- if (import_node_fs6.default.existsSync(candidate)) {
15792
+ if (import_node_fs7.default.existsSync(candidate)) {
15725
15793
  return { available: true, path: candidate };
15726
15794
  }
15727
15795
  }
@@ -16032,10 +16100,10 @@ function parseAttachment(obj) {
16032
16100
  const memories = raw.map((m) => {
16033
16101
  if (!m || typeof m !== "object") return null;
16034
16102
  const rec = m;
16035
- const path17 = typeof rec.path === "string" ? rec.path : null;
16103
+ const path18 = typeof rec.path === "string" ? rec.path : null;
16036
16104
  const content = typeof rec.content === "string" ? rec.content : null;
16037
- if (!path17 || content == null) return null;
16038
- const out = { path: path17, content };
16105
+ if (!path18 || content == null) return null;
16106
+ const out = { path: path18, content };
16039
16107
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
16040
16108
  return out;
16041
16109
  }).filter((m) => m !== null);
@@ -16263,22 +16331,22 @@ var ClaudeAdapter = class {
16263
16331
  };
16264
16332
 
16265
16333
  // src/workspace/browser.ts
16266
- var import_node_fs7 = __toESM(require("fs"), 1);
16334
+ var import_node_fs8 = __toESM(require("fs"), 1);
16267
16335
  var import_node_os4 = __toESM(require("os"), 1);
16268
- var import_node_path6 = __toESM(require("path"), 1);
16336
+ var import_node_path7 = __toESM(require("path"), 1);
16269
16337
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
16270
16338
  function resolveInsideCwd(cwd, subpath) {
16271
- const absCwd = import_node_path6.default.resolve(cwd);
16272
- const joined = import_node_path6.default.resolve(absCwd, subpath ?? ".");
16273
- const rel = import_node_path6.default.relative(absCwd, joined);
16274
- if (rel.startsWith("..") || import_node_path6.default.isAbsolute(rel)) {
16339
+ const absCwd = import_node_path7.default.resolve(cwd);
16340
+ const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
16341
+ const rel = import_node_path7.default.relative(absCwd, joined);
16342
+ if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
16275
16343
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
16276
16344
  }
16277
16345
  return joined;
16278
16346
  }
16279
16347
  function ensureCwd(cwd) {
16280
16348
  try {
16281
- const stat = import_node_fs7.default.statSync(cwd);
16349
+ const stat = import_node_fs8.default.statSync(cwd);
16282
16350
  if (!stat.isDirectory()) {
16283
16351
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
16284
16352
  }
@@ -16292,7 +16360,7 @@ var WorkspaceBrowser = class {
16292
16360
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
16293
16361
  ensureCwd(cwd);
16294
16362
  const full = resolveInsideCwd(cwd, args.path);
16295
- const dirents = import_node_fs7.default.readdirSync(full, { withFileTypes: true });
16363
+ const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
16296
16364
  const entries = [];
16297
16365
  for (const d of dirents) {
16298
16366
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -16302,7 +16370,7 @@ var WorkspaceBrowser = class {
16302
16370
  mtime: ""
16303
16371
  };
16304
16372
  try {
16305
- const st = import_node_fs7.default.statSync(import_node_path6.default.join(full, d.name));
16373
+ const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
16306
16374
  entry.mtime = new Date(st.mtimeMs).toISOString();
16307
16375
  if (d.isFile()) entry.size = st.size;
16308
16376
  } catch {
@@ -16318,14 +16386,14 @@ var WorkspaceBrowser = class {
16318
16386
  read(args) {
16319
16387
  ensureCwd(args.cwd);
16320
16388
  const full = resolveInsideCwd(args.cwd, args.path);
16321
- const st = import_node_fs7.default.statSync(full);
16389
+ const st = import_node_fs8.default.statSync(full);
16322
16390
  if (!st.isFile()) {
16323
16391
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
16324
16392
  }
16325
16393
  if (st.size > MAX_FILE_BYTES) {
16326
16394
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
16327
16395
  }
16328
- const buf = import_node_fs7.default.readFileSync(full);
16396
+ const buf = import_node_fs8.default.readFileSync(full);
16329
16397
  const isBinary = buf.includes(0);
16330
16398
  if (isBinary) {
16331
16399
  return {
@@ -16347,9 +16415,9 @@ var WorkspaceBrowser = class {
16347
16415
  };
16348
16416
 
16349
16417
  // src/skills/scanner.ts
16350
- var import_node_fs8 = __toESM(require("fs"), 1);
16418
+ var import_node_fs9 = __toESM(require("fs"), 1);
16351
16419
  var import_node_os5 = __toESM(require("os"), 1);
16352
- var import_node_path7 = __toESM(require("path"), 1);
16420
+ var import_node_path8 = __toESM(require("path"), 1);
16353
16421
  function parseFrontmatter(content) {
16354
16422
  if (!content.startsWith("---")) return { name: "", description: "" };
16355
16423
  const end = content.indexOf("---", 3);
@@ -16385,7 +16453,7 @@ function parseFrontmatter(content) {
16385
16453
  }
16386
16454
  function isDirLikeSync(p) {
16387
16455
  try {
16388
- return import_node_fs8.default.statSync(p).isDirectory();
16456
+ return import_node_fs9.default.statSync(p).isDirectory();
16389
16457
  } catch {
16390
16458
  return false;
16391
16459
  }
@@ -16393,19 +16461,19 @@ function isDirLikeSync(p) {
16393
16461
  function scanSkillDir(dir, source, seen, out, pluginName) {
16394
16462
  let entries;
16395
16463
  try {
16396
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
16464
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
16397
16465
  } catch {
16398
16466
  return;
16399
16467
  }
16400
16468
  for (const ent of entries) {
16401
- const entryPath = import_node_path7.default.join(dir, ent.name);
16469
+ const entryPath = import_node_path8.default.join(dir, ent.name);
16402
16470
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
16403
16471
  let content;
16404
16472
  try {
16405
- content = import_node_fs8.default.readFileSync(import_node_path7.default.join(entryPath, "SKILL.md"), "utf8");
16473
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
16406
16474
  } catch {
16407
16475
  try {
16408
- content = import_node_fs8.default.readFileSync(import_node_path7.default.join(entryPath, "skill.md"), "utf8");
16476
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
16409
16477
  } catch {
16410
16478
  continue;
16411
16479
  }
@@ -16423,26 +16491,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
16423
16491
  function scanCommandDir(dir, source, seen, out, pluginName) {
16424
16492
  let entries;
16425
16493
  try {
16426
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
16494
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
16427
16495
  } catch {
16428
16496
  return;
16429
16497
  }
16430
16498
  for (const ent of entries) {
16431
- const entryPath = import_node_path7.default.join(dir, ent.name);
16499
+ const entryPath = import_node_path8.default.join(dir, ent.name);
16432
16500
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
16433
16501
  const ns = ent.name;
16434
16502
  let subEntries;
16435
16503
  try {
16436
- subEntries = import_node_fs8.default.readdirSync(entryPath, { withFileTypes: true });
16504
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
16437
16505
  } catch {
16438
16506
  continue;
16439
16507
  }
16440
16508
  for (const se of subEntries) {
16441
16509
  if (!se.name.endsWith(".md")) continue;
16442
- const sePath = import_node_path7.default.join(entryPath, se.name);
16510
+ const sePath = import_node_path8.default.join(entryPath, se.name);
16443
16511
  let content;
16444
16512
  try {
16445
- content = import_node_fs8.default.readFileSync(sePath, "utf8");
16513
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
16446
16514
  } catch {
16447
16515
  continue;
16448
16516
  }
@@ -16459,7 +16527,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
16459
16527
  } else if (ent.name.endsWith(".md")) {
16460
16528
  let content;
16461
16529
  try {
16462
- content = import_node_fs8.default.readFileSync(entryPath, "utf8");
16530
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
16463
16531
  } catch {
16464
16532
  continue;
16465
16533
  }
@@ -16475,10 +16543,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
16475
16543
  }
16476
16544
  }
16477
16545
  function readInstalledPlugins(home) {
16478
- const file = import_node_path7.default.join(home, ".claude", "plugins", "installed_plugins.json");
16546
+ const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
16479
16547
  let raw;
16480
16548
  try {
16481
- raw = import_node_fs8.default.readFileSync(file, "utf8");
16549
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
16482
16550
  } catch {
16483
16551
  return [];
16484
16552
  }
@@ -16516,14 +16584,14 @@ var SkillsScanner = class {
16516
16584
  list(args) {
16517
16585
  const seen = /* @__PURE__ */ new Set();
16518
16586
  const out = [];
16519
- scanSkillDir(import_node_path7.default.join(this.home, ".claude", "skills"), "global", seen, out);
16520
- scanCommandDir(import_node_path7.default.join(this.home, ".claude", "commands"), "global", seen, out);
16521
- scanSkillDir(import_node_path7.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
16522
- scanCommandDir(import_node_path7.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
16587
+ scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
16588
+ scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
16589
+ scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
16590
+ scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
16523
16591
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
16524
16592
  for (const { name, root } of plugins) {
16525
- scanSkillDir(import_node_path7.default.join(root, "skills"), "plugin", seen, out, name);
16526
- scanCommandDir(import_node_path7.default.join(root, "commands"), "plugin", seen, out, name);
16593
+ scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
16594
+ scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
16527
16595
  }
16528
16596
  out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
16529
16597
  return out;
@@ -16531,9 +16599,9 @@ var SkillsScanner = class {
16531
16599
  };
16532
16600
 
16533
16601
  // src/observer/session-observer.ts
16534
- var import_node_fs9 = __toESM(require("fs"), 1);
16602
+ var import_node_fs10 = __toESM(require("fs"), 1);
16535
16603
  var import_node_os6 = __toESM(require("os"), 1);
16536
- var import_node_path8 = __toESM(require("path"), 1);
16604
+ var import_node_path9 = __toESM(require("path"), 1);
16537
16605
  var SessionObserver = class {
16538
16606
  constructor(opts) {
16539
16607
  this.opts = opts;
@@ -16544,14 +16612,14 @@ var SessionObserver = class {
16544
16612
  watches = /* @__PURE__ */ new Map();
16545
16613
  resolveJsonlPath(cwd, toolSessionId, override) {
16546
16614
  if (override) return override;
16547
- return import_node_path8.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
16615
+ return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
16548
16616
  }
16549
16617
  start(args) {
16550
16618
  this.stop(args.sessionId);
16551
16619
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
16552
16620
  let size = 0;
16553
16621
  try {
16554
- size = import_node_fs9.default.statSync(filePath).size;
16622
+ size = import_node_fs10.default.statSync(filePath).size;
16555
16623
  } catch {
16556
16624
  }
16557
16625
  const w = {
@@ -16564,10 +16632,10 @@ var SessionObserver = class {
16564
16632
  adapter: args.adapter
16565
16633
  };
16566
16634
  try {
16567
- import_node_fs9.default.mkdirSync(import_node_path8.default.dirname(filePath), { recursive: true });
16635
+ import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
16568
16636
  } catch {
16569
16637
  }
16570
- w.watcher = import_node_fs9.default.watch(import_node_path8.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
16638
+ w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
16571
16639
  if (!changedName || !filePath.endsWith(changedName)) return;
16572
16640
  this.poll(w);
16573
16641
  });
@@ -16582,7 +16650,7 @@ var SessionObserver = class {
16582
16650
  // reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
16583
16651
  hydrateMetaTail(w, maxLines = 200) {
16584
16652
  try {
16585
- const raw = import_node_fs9.default.readFileSync(w.filePath, "utf8");
16653
+ const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
16586
16654
  if (!raw) return;
16587
16655
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
16588
16656
  if (allLines.length === 0) return;
@@ -16603,7 +16671,7 @@ var SessionObserver = class {
16603
16671
  poll(w) {
16604
16672
  let size = 0;
16605
16673
  try {
16606
- size = import_node_fs9.default.statSync(w.filePath).size;
16674
+ size = import_node_fs10.default.statSync(w.filePath).size;
16607
16675
  } catch {
16608
16676
  return;
16609
16677
  }
@@ -16612,11 +16680,11 @@ var SessionObserver = class {
16612
16680
  w.buf = "";
16613
16681
  }
16614
16682
  if (size === w.lastSize) return;
16615
- const fd = import_node_fs9.default.openSync(w.filePath, "r");
16683
+ const fd = import_node_fs10.default.openSync(w.filePath, "r");
16616
16684
  try {
16617
16685
  const len = size - w.lastSize;
16618
16686
  const buf = Buffer.alloc(len);
16619
- import_node_fs9.default.readSync(fd, buf, 0, len, w.lastSize);
16687
+ import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
16620
16688
  w.lastSize = size;
16621
16689
  w.buf += buf.toString("utf8");
16622
16690
  let newlineIndex;
@@ -16630,7 +16698,7 @@ var SessionObserver = class {
16630
16698
  this.maybeReportUserMessage(w.sessionId, line);
16631
16699
  }
16632
16700
  } finally {
16633
- import_node_fs9.default.closeSync(fd);
16701
+ import_node_fs10.default.closeSync(fd);
16634
16702
  }
16635
16703
  }
16636
16704
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -17045,10 +17113,10 @@ function isLocalhost(addr) {
17045
17113
  }
17046
17114
 
17047
17115
  // src/discovery/state-file.ts
17048
- var import_node_fs10 = __toESM(require("fs"), 1);
17049
- var import_node_path9 = __toESM(require("path"), 1);
17116
+ var import_node_fs11 = __toESM(require("fs"), 1);
17117
+ var import_node_path10 = __toESM(require("path"), 1);
17050
17118
  function defaultStateFilePath(dataDir) {
17051
- return import_node_path9.default.join(dataDir, "state.json");
17119
+ return import_node_path10.default.join(dataDir, "state.json");
17052
17120
  }
17053
17121
  function isPidAlive(pid) {
17054
17122
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -17070,7 +17138,7 @@ var StateFileManager = class {
17070
17138
  }
17071
17139
  read() {
17072
17140
  try {
17073
- const raw = import_node_fs10.default.readFileSync(this.file, "utf8");
17141
+ const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
17074
17142
  const parsed = JSON.parse(raw);
17075
17143
  return parsed;
17076
17144
  } catch {
@@ -17084,34 +17152,34 @@ var StateFileManager = class {
17084
17152
  return { status: "stale", existing };
17085
17153
  }
17086
17154
  write(state) {
17087
- import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(this.file), { recursive: true });
17155
+ import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
17088
17156
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
17089
- import_node_fs10.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
17090
- import_node_fs10.default.renameSync(tmp, this.file);
17157
+ import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
17158
+ import_node_fs11.default.renameSync(tmp, this.file);
17091
17159
  if (process.platform !== "win32") {
17092
17160
  try {
17093
- import_node_fs10.default.chmodSync(this.file, 384);
17161
+ import_node_fs11.default.chmodSync(this.file, 384);
17094
17162
  } catch {
17095
17163
  }
17096
17164
  }
17097
17165
  }
17098
17166
  delete() {
17099
17167
  try {
17100
- import_node_fs10.default.unlinkSync(this.file);
17168
+ import_node_fs11.default.unlinkSync(this.file);
17101
17169
  } catch {
17102
17170
  }
17103
17171
  }
17104
17172
  };
17105
17173
 
17106
17174
  // src/tunnel/tunnel-manager.ts
17107
- var import_node_fs13 = __toESM(require("fs"), 1);
17108
- var import_node_path12 = __toESM(require("path"), 1);
17175
+ var import_node_fs14 = __toESM(require("fs"), 1);
17176
+ var import_node_path13 = __toESM(require("path"), 1);
17109
17177
  var import_node_crypto3 = __toESM(require("crypto"), 1);
17110
17178
  var import_node_child_process4 = require("child_process");
17111
17179
 
17112
17180
  // src/tunnel/tunnel-store.ts
17113
- var import_node_fs11 = __toESM(require("fs"), 1);
17114
- var import_node_path10 = __toESM(require("path"), 1);
17181
+ var import_node_fs12 = __toESM(require("fs"), 1);
17182
+ var import_node_path11 = __toESM(require("path"), 1);
17115
17183
  var TunnelStore = class {
17116
17184
  constructor(filePath) {
17117
17185
  this.filePath = filePath;
@@ -17119,7 +17187,7 @@ var TunnelStore = class {
17119
17187
  filePath;
17120
17188
  async get() {
17121
17189
  try {
17122
- const raw = await import_node_fs11.default.promises.readFile(this.filePath, "utf8");
17190
+ const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
17123
17191
  const obj = JSON.parse(raw);
17124
17192
  if (!isPersistedTunnel(obj)) return null;
17125
17193
  return obj;
@@ -17130,22 +17198,22 @@ var TunnelStore = class {
17130
17198
  }
17131
17199
  }
17132
17200
  async set(v) {
17133
- const dir = import_node_path10.default.dirname(this.filePath);
17134
- await import_node_fs11.default.promises.mkdir(dir, { recursive: true });
17201
+ const dir = import_node_path11.default.dirname(this.filePath);
17202
+ await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
17135
17203
  const data = JSON.stringify(v, null, 2);
17136
17204
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
17137
- await import_node_fs11.default.promises.writeFile(tmp, data, { mode: 384 });
17205
+ await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
17138
17206
  if (process.platform !== "win32") {
17139
17207
  try {
17140
- await import_node_fs11.default.promises.chmod(tmp, 384);
17208
+ await import_node_fs12.default.promises.chmod(tmp, 384);
17141
17209
  } catch {
17142
17210
  }
17143
17211
  }
17144
- await import_node_fs11.default.promises.rename(tmp, this.filePath);
17212
+ await import_node_fs12.default.promises.rename(tmp, this.filePath);
17145
17213
  }
17146
17214
  async clear() {
17147
17215
  try {
17148
- await import_node_fs11.default.promises.unlink(this.filePath);
17216
+ await import_node_fs12.default.promises.unlink(this.filePath);
17149
17217
  } catch (err) {
17150
17218
  const code = err?.code;
17151
17219
  if (code !== "ENOENT") throw err;
@@ -17240,9 +17308,9 @@ function escape(v) {
17240
17308
  }
17241
17309
 
17242
17310
  // src/tunnel/frpc-binary.ts
17243
- var import_node_fs12 = __toESM(require("fs"), 1);
17311
+ var import_node_fs13 = __toESM(require("fs"), 1);
17244
17312
  var import_node_os7 = __toESM(require("os"), 1);
17245
- var import_node_path11 = __toESM(require("path"), 1);
17313
+ var import_node_path12 = __toESM(require("path"), 1);
17246
17314
  var import_node_child_process3 = require("child_process");
17247
17315
  var import_node_stream = require("stream");
17248
17316
  var import_promises = require("stream/promises");
@@ -17274,20 +17342,20 @@ function frpcDownloadUrl(version2, p) {
17274
17342
  }
17275
17343
  async function ensureFrpcBinary(opts) {
17276
17344
  if (opts.override) {
17277
- if (!import_node_fs12.default.existsSync(opts.override)) {
17345
+ if (!import_node_fs13.default.existsSync(opts.override)) {
17278
17346
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
17279
17347
  }
17280
17348
  return opts.override;
17281
17349
  }
17282
17350
  const version2 = opts.version ?? FRPC_VERSION;
17283
17351
  const platform = opts.platform ?? detectPlatform();
17284
- const binDir = import_node_path11.default.join(opts.dataDir, "bin");
17285
- import_node_fs12.default.mkdirSync(binDir, { recursive: true });
17352
+ const binDir = import_node_path12.default.join(opts.dataDir, "bin");
17353
+ import_node_fs13.default.mkdirSync(binDir, { recursive: true });
17286
17354
  cleanupStaleArtifacts(binDir);
17287
- const stableBin = import_node_path11.default.join(binDir, "frpc");
17288
- if (import_node_fs12.default.existsSync(stableBin)) return stableBin;
17355
+ const stableBin = import_node_path12.default.join(binDir, "frpc");
17356
+ if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
17289
17357
  const partialBin = `${stableBin}.partial`;
17290
- const tarballPath = import_node_path11.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
17358
+ const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
17291
17359
  try {
17292
17360
  const url = frpcDownloadUrl(version2, platform);
17293
17361
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -17296,8 +17364,8 @@ async function ensureFrpcBinary(opts) {
17296
17364
  } else {
17297
17365
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
17298
17366
  }
17299
- import_node_fs12.default.chmodSync(partialBin, 493);
17300
- import_node_fs12.default.renameSync(partialBin, stableBin);
17367
+ import_node_fs13.default.chmodSync(partialBin, 493);
17368
+ import_node_fs13.default.renameSync(partialBin, stableBin);
17301
17369
  } finally {
17302
17370
  safeUnlink(tarballPath);
17303
17371
  safeUnlink(partialBin);
@@ -17307,15 +17375,15 @@ async function ensureFrpcBinary(opts) {
17307
17375
  function cleanupStaleArtifacts(binDir) {
17308
17376
  let entries;
17309
17377
  try {
17310
- entries = import_node_fs12.default.readdirSync(binDir);
17378
+ entries = import_node_fs13.default.readdirSync(binDir);
17311
17379
  } catch {
17312
17380
  return;
17313
17381
  }
17314
17382
  for (const name of entries) {
17315
17383
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
17316
- const full = import_node_path11.default.join(binDir, name);
17384
+ const full = import_node_path12.default.join(binDir, name);
17317
17385
  try {
17318
- import_node_fs12.default.rmSync(full, { recursive: true, force: true });
17386
+ import_node_fs13.default.rmSync(full, { recursive: true, force: true });
17319
17387
  } catch {
17320
17388
  }
17321
17389
  }
@@ -17323,7 +17391,7 @@ function cleanupStaleArtifacts(binDir) {
17323
17391
  }
17324
17392
  function safeUnlink(p) {
17325
17393
  try {
17326
- import_node_fs12.default.unlinkSync(p);
17394
+ import_node_fs13.default.unlinkSync(p);
17327
17395
  } catch {
17328
17396
  }
17329
17397
  }
@@ -17334,13 +17402,13 @@ async function downloadToFile(url, dest, fetchImpl) {
17334
17402
  if (!res.ok || !res.body) {
17335
17403
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
17336
17404
  }
17337
- const out = import_node_fs12.default.createWriteStream(dest);
17405
+ const out = import_node_fs13.default.createWriteStream(dest);
17338
17406
  const nodeStream = import_node_stream.Readable.fromWeb(res.body);
17339
17407
  await (0, import_promises.pipeline)(nodeStream, out);
17340
17408
  }
17341
17409
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
17342
- const work = import_node_path11.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
17343
- import_node_fs12.default.mkdirSync(work, { recursive: true });
17410
+ const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
17411
+ import_node_fs13.default.mkdirSync(work, { recursive: true });
17344
17412
  try {
17345
17413
  await new Promise((resolve, reject) => {
17346
17414
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -17348,13 +17416,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
17348
17416
  proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
17349
17417
  });
17350
17418
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
17351
- const src = import_node_path11.default.join(work, dirName, "frpc");
17352
- if (!import_node_fs12.default.existsSync(src)) {
17419
+ const src = import_node_path12.default.join(work, dirName, "frpc");
17420
+ if (!import_node_fs13.default.existsSync(src)) {
17353
17421
  throw new Error(`frpc not found inside tarball at ${src}`);
17354
17422
  }
17355
- import_node_fs12.default.copyFileSync(src, destBin);
17423
+ import_node_fs13.default.copyFileSync(src, destBin);
17356
17424
  } finally {
17357
- import_node_fs12.default.rmSync(work, { recursive: true, force: true });
17425
+ import_node_fs13.default.rmSync(work, { recursive: true, force: true });
17358
17426
  }
17359
17427
  }
17360
17428
 
@@ -17363,7 +17431,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
17363
17431
  var TunnelManager = class {
17364
17432
  constructor(deps) {
17365
17433
  this.deps = deps;
17366
- this.store = deps.store ?? new TunnelStore(import_node_path12.default.join(deps.dataDir, "tunnel.json"));
17434
+ this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
17367
17435
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
17368
17436
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
17369
17437
  }
@@ -17480,7 +17548,7 @@ var TunnelManager = class {
17480
17548
  dataDir: this.deps.dataDir,
17481
17549
  override: this.deps.frpcBinaryOverride ?? void 0
17482
17550
  });
17483
- const tomlPath = import_node_path12.default.join(this.deps.dataDir, "frpc.toml");
17551
+ const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
17484
17552
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
17485
17553
  const toml = buildFrpcToml({
17486
17554
  serverAddr: t.frpsHost,
@@ -17491,12 +17559,12 @@ var TunnelManager = class {
17491
17559
  localPort,
17492
17560
  logLevel: "info"
17493
17561
  });
17494
- await import_node_fs13.default.promises.writeFile(tomlPath, toml, { mode: 384 });
17562
+ await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
17495
17563
  const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
17496
17564
  stdio: ["ignore", "pipe", "pipe"]
17497
17565
  });
17498
- const logFilePath = import_node_path12.default.join(this.deps.dataDir, "frpc.log");
17499
- const logStream = import_node_fs13.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
17566
+ const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
17567
+ const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
17500
17568
  logStream.on("error", () => {
17501
17569
  });
17502
17570
  const tee = (chunk) => {
@@ -17588,12 +17656,12 @@ function deriveStableDeviceKey(opts = {}) {
17588
17656
  }
17589
17657
 
17590
17658
  // src/auth-store.ts
17591
- var import_node_fs14 = __toESM(require("fs"), 1);
17592
- var import_node_path13 = __toESM(require("path"), 1);
17659
+ var import_node_fs15 = __toESM(require("fs"), 1);
17660
+ var import_node_path14 = __toESM(require("path"), 1);
17593
17661
  var import_node_crypto5 = __toESM(require("crypto"), 1);
17594
17662
  var AUTH_FILE_NAME = "auth.json";
17595
17663
  function authFilePath(dataDir) {
17596
- return import_node_path13.default.join(dataDir, AUTH_FILE_NAME);
17664
+ return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
17597
17665
  }
17598
17666
  function loadOrCreateAuthToken(opts) {
17599
17667
  const file = authFilePath(opts.dataDir);
@@ -17609,7 +17677,7 @@ function defaultGenerate() {
17609
17677
  }
17610
17678
  function readAuthFile(file) {
17611
17679
  try {
17612
- const raw = import_node_fs14.default.readFileSync(file, "utf8");
17680
+ const raw = import_node_fs15.default.readFileSync(file, "utf8");
17613
17681
  const parsed = JSON.parse(raw);
17614
17682
  if (typeof parsed?.token === "string" && parsed.token.length > 0) {
17615
17683
  return {
@@ -17625,20 +17693,20 @@ function readAuthFile(file) {
17625
17693
  }
17626
17694
  }
17627
17695
  function writeAuthFile(file, content) {
17628
- import_node_fs14.default.mkdirSync(import_node_path13.default.dirname(file), { recursive: true });
17629
- import_node_fs14.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
17696
+ import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
17697
+ import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
17630
17698
  try {
17631
- import_node_fs14.default.chmodSync(file, 384);
17699
+ import_node_fs15.default.chmodSync(file, 384);
17632
17700
  } catch {
17633
17701
  }
17634
17702
  }
17635
17703
 
17636
17704
  // src/session/fork.ts
17637
- var import_node_fs15 = __toESM(require("fs"), 1);
17705
+ var import_node_fs16 = __toESM(require("fs"), 1);
17638
17706
  var import_node_os9 = __toESM(require("os"), 1);
17639
- var import_node_path14 = __toESM(require("path"), 1);
17707
+ var import_node_path15 = __toESM(require("path"), 1);
17640
17708
  function readJsonlEntries(file) {
17641
- const raw = import_node_fs15.default.readFileSync(file, "utf8");
17709
+ const raw = import_node_fs16.default.readFileSync(file, "utf8");
17642
17710
  const out = [];
17643
17711
  for (const line of raw.split("\n")) {
17644
17712
  const t = line.trim();
@@ -17651,10 +17719,10 @@ function readJsonlEntries(file) {
17651
17719
  return out;
17652
17720
  }
17653
17721
  function forkSession(input) {
17654
- const baseDir = input.baseDir ?? import_node_path14.default.join(import_node_os9.default.homedir(), ".claude");
17655
- const projectDir = import_node_path14.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
17656
- const sourceFile = import_node_path14.default.join(projectDir, `${input.toolSessionId}.jsonl`);
17657
- if (!import_node_fs15.default.existsSync(sourceFile)) {
17722
+ const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
17723
+ const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
17724
+ const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
17725
+ if (!import_node_fs16.default.existsSync(sourceFile)) {
17658
17726
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
17659
17727
  }
17660
17728
  const entries = readJsonlEntries(sourceFile);
@@ -17684,9 +17752,9 @@ function forkSession(input) {
17684
17752
  }
17685
17753
  forkedLines.push(JSON.stringify(forked));
17686
17754
  }
17687
- const forkedFilePath = import_node_path14.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
17688
- import_node_fs15.default.mkdirSync(projectDir, { recursive: true });
17689
- import_node_fs15.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
17755
+ const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
17756
+ import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
17757
+ import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
17690
17758
  return { forkedToolSessionId, forkedFilePath };
17691
17759
  }
17692
17760
 
@@ -17948,9 +18016,9 @@ function buildWorkspaceHandlers(deps) {
17948
18016
 
17949
18017
  // src/workspace/git.ts
17950
18018
  var import_node_child_process5 = require("child_process");
17951
- var import_node_fs16 = __toESM(require("fs"), 1);
18019
+ var import_node_fs17 = __toESM(require("fs"), 1);
17952
18020
  var import_node_os10 = __toESM(require("os"), 1);
17953
- var import_node_path15 = __toESM(require("path"), 1);
18021
+ var import_node_path16 = __toESM(require("path"), 1);
17954
18022
  var import_node_util = require("util");
17955
18023
  var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
17956
18024
  function formatChildProcessError(err) {
@@ -17965,9 +18033,9 @@ function formatChildProcessError(err) {
17965
18033
  return e.message ?? "unknown error";
17966
18034
  }
17967
18035
  function normalizePath(p) {
17968
- const resolved = import_node_path15.default.resolve(p);
18036
+ const resolved = import_node_path16.default.resolve(p);
17969
18037
  try {
17970
- return import_node_fs16.default.realpathSync(resolved);
18038
+ return import_node_fs17.default.realpathSync(resolved);
17971
18039
  } catch {
17972
18040
  return resolved;
17973
18041
  }
@@ -18068,13 +18136,13 @@ function flattenToDirName(branch) {
18068
18136
  }
18069
18137
  function encodeClaudeProjectDir(absPath) {
18070
18138
  if (!absPath || typeof absPath !== "string") return "";
18071
- let canonical = import_node_path15.default.resolve(absPath);
18139
+ let canonical = import_node_path16.default.resolve(absPath);
18072
18140
  try {
18073
- canonical = import_node_fs16.default.realpathSync(canonical);
18141
+ canonical = import_node_fs17.default.realpathSync(canonical);
18074
18142
  } catch {
18075
18143
  try {
18076
- const parent = import_node_fs16.default.realpathSync(import_node_path15.default.dirname(canonical));
18077
- canonical = import_node_path15.default.join(parent, import_node_path15.default.basename(canonical));
18144
+ const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
18145
+ canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
18078
18146
  } catch {
18079
18147
  }
18080
18148
  }
@@ -18098,11 +18166,11 @@ async function createWorktree(input) {
18098
18166
  if (!isGitRoot) {
18099
18167
  throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
18100
18168
  }
18101
- const parent = import_node_path15.default.dirname(import_node_path15.default.resolve(cwd));
18102
- if (parent === "/" || parent === import_node_path15.default.resolve(cwd)) {
18169
+ const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
18170
+ if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
18103
18171
  throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
18104
18172
  }
18105
- const worktreeRoot = import_node_path15.default.join(parent, dirName);
18173
+ const worktreeRoot = import_node_path16.default.join(parent, dirName);
18106
18174
  try {
18107
18175
  await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
18108
18176
  timeout: 3e3
@@ -18119,7 +18187,7 @@ async function createWorktree(input) {
18119
18187
  const msg = err.message;
18120
18188
  if (msg.startsWith("\u5206\u652F ")) throw err;
18121
18189
  }
18122
- if (import_node_fs16.default.existsSync(worktreeRoot)) {
18190
+ if (import_node_fs17.default.existsSync(worktreeRoot)) {
18123
18191
  throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
18124
18192
  }
18125
18193
  try {
@@ -18147,8 +18215,8 @@ async function removeWorktree(input) {
18147
18215
  );
18148
18216
  const gitCommonDir = stdout.trim();
18149
18217
  if (!gitCommonDir) throw new Error("empty git-common-dir");
18150
- const absGitCommon = import_node_path15.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path15.default.resolve(worktreeRoot, gitCommonDir);
18151
- repoRoot = import_node_path15.default.dirname(absGitCommon);
18218
+ const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
18219
+ repoRoot = import_node_path16.default.dirname(absGitCommon);
18152
18220
  } catch {
18153
18221
  repoRoot = null;
18154
18222
  }
@@ -18160,7 +18228,7 @@ async function removeWorktree(input) {
18160
18228
  } catch (err) {
18161
18229
  const stderr = err.stderr ?? "";
18162
18230
  const lower = stderr.toLowerCase();
18163
- const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs16.default.existsSync(worktreeRoot);
18231
+ const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
18164
18232
  if (!vanished) {
18165
18233
  throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
18166
18234
  }
@@ -18179,10 +18247,10 @@ async function removeWorktree(input) {
18179
18247
  try {
18180
18248
  const encoded = encodeClaudeProjectDir(worktreeRoot);
18181
18249
  if (encoded) {
18182
- const projectsRoot = import_node_path15.default.join(import_node_os10.default.homedir(), ".claude", "projects");
18183
- const target = import_node_path15.default.resolve(projectsRoot, encoded);
18184
- if (target.startsWith(projectsRoot + import_node_path15.default.sep) && target !== projectsRoot) {
18185
- import_node_fs16.default.rmSync(target, { recursive: true, force: true });
18250
+ const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
18251
+ const target = import_node_path16.default.resolve(projectsRoot, encoded);
18252
+ if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
18253
+ import_node_fs17.default.rmSync(target, { recursive: true, force: true });
18186
18254
  }
18187
18255
  }
18188
18256
  } catch {
@@ -18309,7 +18377,7 @@ function buildMethodHandlers(deps) {
18309
18377
  async function startDaemon(config) {
18310
18378
  const logger = createLogger({
18311
18379
  level: config.logLevel,
18312
- file: import_node_path16.default.join(config.dataDir, "clawd.log")
18380
+ file: import_node_path17.default.join(config.dataDir, "clawd.log")
18313
18381
  });
18314
18382
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
18315
18383
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -18349,6 +18417,7 @@ async function startDaemon(config) {
18349
18417
  logger,
18350
18418
  getAdapter,
18351
18419
  historyReader: history,
18420
+ dataDir: config.dataDir,
18352
18421
  broadcastFrame: (frame, target) => {
18353
18422
  if (target === "all") {
18354
18423
  transport?.broadcastAll(frame);
@@ -18471,8 +18540,8 @@ async function startDaemon(config) {
18471
18540
  const lines = [
18472
18541
  `Tunnel: ${r.url}`,
18473
18542
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
18474
- `Frpc config: ${import_node_path16.default.join(config.dataDir, "frpc.toml")}`,
18475
- `Frpc log: ${import_node_path16.default.join(config.dataDir, "frpc.log")}`
18543
+ `Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
18544
+ `Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
18476
18545
  ];
18477
18546
  const width = Math.max(...lines.map((l) => l.length));
18478
18547
  const bar = "\u2550".repeat(width + 4);
@@ -18485,8 +18554,8 @@ ${bar}
18485
18554
 
18486
18555
  `);
18487
18556
  try {
18488
- const connectPath = import_node_path16.default.join(config.dataDir, "connect.txt");
18489
- import_node_fs17.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
18557
+ const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
18558
+ import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
18490
18559
  } catch {
18491
18560
  }
18492
18561
  } catch (err) {