@clawos-dev/clawd 0.2.23-beta.32.62648eb → 0.2.23-beta.33.3955675

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);
@@ -8686,8 +8686,8 @@ function getErrorMap() {
8686
8686
 
8687
8687
  // ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
8688
8688
  var makeIssue = (params) => {
8689
- const { data, path: path17, errorMaps, issueData } = params;
8690
- const fullPath = [...path17, ...issueData.path || []];
8689
+ const { data, path: path18, errorMaps, issueData } = params;
8690
+ const fullPath = [...path18, ...issueData.path || []];
8691
8691
  const fullIssue = {
8692
8692
  ...issueData,
8693
8693
  path: fullPath
@@ -8803,11 +8803,11 @@ var errorUtil;
8803
8803
 
8804
8804
  // ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
8805
8805
  var ParseInputLazyPath = class {
8806
- constructor(parent, value, path17, key) {
8806
+ constructor(parent, value, path18, key) {
8807
8807
  this._cachedPath = [];
8808
8808
  this.parent = parent;
8809
8809
  this.data = value;
8810
- this._path = path17;
8810
+ this._path = path18;
8811
8811
  this._key = key;
8812
8812
  }
8813
8813
  get path() {
@@ -12812,7 +12812,7 @@ var SessionStore = class {
12812
12812
  };
12813
12813
 
12814
12814
  // src/session/manager.ts
12815
- var import_node_fs4 = __toESM(require("fs"), 1);
12815
+ var import_node_fs5 = __toESM(require("fs"), 1);
12816
12816
 
12817
12817
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
12818
12818
  var byteToHex = [];
@@ -13401,6 +13401,58 @@ function reduceSession(state, input, deps) {
13401
13401
  }
13402
13402
  }
13403
13403
 
13404
+ // src/ipc-recorder.ts
13405
+ var import_node_fs4 = __toESM(require("fs"), 1);
13406
+ var import_node_path4 = __toESM(require("path"), 1);
13407
+ function tsForFilename(ms) {
13408
+ return new Date(ms).toISOString().replace(/[:.]/g, "-");
13409
+ }
13410
+ function startRecorder(opts) {
13411
+ if (opts.env.CLAWD_RECORD_IPC !== "1") return null;
13412
+ if (!opts.dataDir) return null;
13413
+ if (!opts.sessionId || opts.sessionId.includes("..") || opts.sessionId.includes("/") || opts.sessionId.includes("\\") || opts.sessionId.startsWith(".")) {
13414
+ return null;
13415
+ }
13416
+ const now = opts.now ?? Date.now;
13417
+ const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
13418
+ const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
13419
+ let stream = null;
13420
+ let closedResolve;
13421
+ const closed = new Promise((resolve) => {
13422
+ closedResolve = resolve;
13423
+ });
13424
+ let exited = false;
13425
+ const ensureStream = () => {
13426
+ if (stream) return stream;
13427
+ import_node_fs4.default.mkdirSync(dir, { recursive: true });
13428
+ stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
13429
+ stream.on("close", () => closedResolve());
13430
+ return stream;
13431
+ };
13432
+ const writeLine = (s, chunk) => {
13433
+ if (exited) return;
13434
+ const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
13435
+ const line = JSON.stringify({ ts: now(), stream: s, chunk: text }) + "\n";
13436
+ ensureStream().write(line);
13437
+ };
13438
+ opts.proc.stdout?.on("data", (chunk) => writeLine("stdout", chunk));
13439
+ opts.proc.stderr?.on("data", (chunk) => writeLine("stderr", chunk));
13440
+ opts.proc.on("exit", () => {
13441
+ exited = true;
13442
+ if (stream) {
13443
+ stream.end();
13444
+ } else {
13445
+ closedResolve();
13446
+ }
13447
+ });
13448
+ return {
13449
+ tapStdinWrite(chunk) {
13450
+ writeLine("stdin", chunk);
13451
+ },
13452
+ closed
13453
+ };
13454
+ }
13455
+
13404
13456
  // src/session/runner.ts
13405
13457
  var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
13406
13458
  function encodeAllowWithInputControlResponse(requestId, updatedInput) {
@@ -13431,6 +13483,8 @@ var SessionRunner = class {
13431
13483
  pendingControlRequests = /* @__PURE__ */ new Map();
13432
13484
  // waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
13433
13485
  stopWaiters = [];
13486
+ // IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
13487
+ recorder = null;
13434
13488
  getState() {
13435
13489
  return this.state;
13436
13490
  }
@@ -13520,6 +13574,7 @@ var SessionRunner = class {
13520
13574
  this.pendingControlRequests.set(requestId, { resolve, reject, timer });
13521
13575
  try {
13522
13576
  proc.stdin?.write(payload);
13577
+ this.recorder?.tapStdinWrite(payload);
13523
13578
  } catch (err) {
13524
13579
  clearTimeout(timer);
13525
13580
  this.pendingControlRequests.delete(requestId);
@@ -13575,10 +13630,14 @@ var SessionRunner = class {
13575
13630
  break;
13576
13631
  case "write-stdin":
13577
13632
  this.proc?.stdin?.write(effect.payload);
13633
+ this.recorder?.tapStdinWrite(effect.payload);
13578
13634
  break;
13579
- case "send-control-response-allow-with-input":
13580
- this.proc?.stdin?.write(encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput));
13635
+ case "send-control-response-allow-with-input": {
13636
+ const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
13637
+ this.proc?.stdin?.write(payload);
13638
+ this.recorder?.tapStdinWrite(payload);
13581
13639
  break;
13640
+ }
13582
13641
  case "persist-file":
13583
13642
  try {
13584
13643
  this.hooks.store.write(effect.file);
@@ -13608,6 +13667,13 @@ var SessionRunner = class {
13608
13667
  const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
13609
13668
  this.proc = proc;
13610
13669
  this.stdoutBuf = "";
13670
+ this.recorder = startRecorder({
13671
+ proc,
13672
+ sessionId: this.state.file.sessionId,
13673
+ dataDir: this.hooks.dataDir,
13674
+ env: this.hooks.recordEnv ?? process.env,
13675
+ now: this.hooks.now
13676
+ });
13611
13677
  proc.stdout?.on("data", (chunk) => {
13612
13678
  this.stdoutBuf += typeof chunk === "string" ? chunk : chunk.toString("utf8");
13613
13679
  let idx;
@@ -13624,6 +13690,7 @@ var SessionRunner = class {
13624
13690
  });
13625
13691
  proc.on("exit", (code) => {
13626
13692
  this.proc = null;
13693
+ this.recorder = null;
13627
13694
  this.rejectAllPending(new Error("session gone"));
13628
13695
  this.input({ kind: "proc-exit", code });
13629
13696
  });
@@ -13750,7 +13817,8 @@ var SessionManager = class {
13750
13817
  now: this.deps.now,
13751
13818
  bufferCap: this.deps.bufferCap,
13752
13819
  // adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
13753
- resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
13820
+ resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
13821
+ dataDir: this.deps.dataDir
13754
13822
  });
13755
13823
  return runner;
13756
13824
  }
@@ -13781,7 +13849,7 @@ var SessionManager = class {
13781
13849
  // ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
13782
13850
  create(args) {
13783
13851
  try {
13784
- const stat = import_node_fs4.default.statSync(args.cwd);
13852
+ const stat = import_node_fs5.default.statSync(args.cwd);
13785
13853
  if (!stat.isDirectory()) throw new Error("not dir");
13786
13854
  } catch {
13787
13855
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -14227,14 +14295,14 @@ var SessionManager = class {
14227
14295
  // src/tools/claude.ts
14228
14296
  var import_node_child_process = require("child_process");
14229
14297
  var import_node_child_process2 = require("child_process");
14230
- var import_node_fs6 = __toESM(require("fs"), 1);
14298
+ var import_node_fs7 = __toESM(require("fs"), 1);
14231
14299
  var import_node_os3 = __toESM(require("os"), 1);
14232
- var import_node_path5 = __toESM(require("path"), 1);
14300
+ var import_node_path6 = __toESM(require("path"), 1);
14233
14301
 
14234
14302
  // src/tools/claude-history.ts
14235
- var import_node_fs5 = __toESM(require("fs"), 1);
14303
+ var import_node_fs6 = __toESM(require("fs"), 1);
14236
14304
  var import_node_os2 = __toESM(require("os"), 1);
14237
- var import_node_path4 = __toESM(require("path"), 1);
14305
+ var import_node_path5 = __toESM(require("path"), 1);
14238
14306
 
14239
14307
  // ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
14240
14308
  function Diff() {
@@ -14338,11 +14406,11 @@ Diff.prototype = {
14338
14406
  }
14339
14407
  }
14340
14408
  },
14341
- addToPath: function addToPath(path17, added, removed, oldPosInc, options) {
14342
- var last = path17.lastComponent;
14409
+ addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
14410
+ var last = path18.lastComponent;
14343
14411
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
14344
14412
  return {
14345
- oldPos: path17.oldPos + oldPosInc,
14413
+ oldPos: path18.oldPos + oldPosInc,
14346
14414
  lastComponent: {
14347
14415
  count: last.count + 1,
14348
14416
  added,
@@ -14352,7 +14420,7 @@ Diff.prototype = {
14352
14420
  };
14353
14421
  } else {
14354
14422
  return {
14355
- oldPos: path17.oldPos + oldPosInc,
14423
+ oldPos: path18.oldPos + oldPosInc,
14356
14424
  lastComponent: {
14357
14425
  count: 1,
14358
14426
  added,
@@ -15011,7 +15079,7 @@ function hashDirToCwd(hash) {
15011
15079
  }
15012
15080
  function safeStatMtime(p) {
15013
15081
  try {
15014
- return import_node_fs5.default.statSync(p).mtimeMs;
15082
+ return import_node_fs6.default.statSync(p).mtimeMs;
15015
15083
  } catch {
15016
15084
  return 0;
15017
15085
  }
@@ -15019,7 +15087,7 @@ function safeStatMtime(p) {
15019
15087
  function readJsonlLines(file) {
15020
15088
  let raw;
15021
15089
  try {
15022
- raw = import_node_fs5.default.readFileSync(file, "utf8");
15090
+ raw = import_node_fs6.default.readFileSync(file, "utf8");
15023
15091
  } catch (err) {
15024
15092
  if (err.code === "ENOENT") return [];
15025
15093
  throw err;
@@ -15211,10 +15279,10 @@ function attachmentToHistoryMessage(o, ts) {
15211
15279
  const memories = raw.map((m) => {
15212
15280
  if (!m || typeof m !== "object") return null;
15213
15281
  const rec = m;
15214
- const path17 = typeof rec.path === "string" ? rec.path : null;
15282
+ const path18 = typeof rec.path === "string" ? rec.path : null;
15215
15283
  const content = typeof rec.content === "string" ? rec.content : null;
15216
- if (!path17 || content == null) return null;
15217
- const entry = { path: path17, content };
15284
+ if (!path18 || content == null) return null;
15285
+ const entry = { path: path18, content };
15218
15286
  if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
15219
15287
  return entry;
15220
15288
  }).filter((m) => m !== null);
@@ -15250,8 +15318,8 @@ function attachmentDeferredToolsText(a) {
15250
15318
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
15251
15319
  if (backupFileName === null) return null;
15252
15320
  try {
15253
- return import_node_fs5.default.readFileSync(
15254
- import_node_path4.default.join(fileHistoryRoot, toolSessionId, backupFileName),
15321
+ return import_node_fs6.default.readFileSync(
15322
+ import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
15255
15323
  "utf8"
15256
15324
  );
15257
15325
  } catch {
@@ -15260,7 +15328,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
15260
15328
  }
15261
15329
  function readCurrentContent(filePath) {
15262
15330
  try {
15263
- return import_node_fs5.default.readFileSync(filePath, "utf8");
15331
+ return import_node_fs6.default.readFileSync(filePath, "utf8");
15264
15332
  } catch (err) {
15265
15333
  if (err.code === "ENOENT") return null;
15266
15334
  return null;
@@ -15272,14 +15340,14 @@ var ClaudeHistoryReader = class {
15272
15340
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
15273
15341
  fileHistoryRoot;
15274
15342
  constructor(opts = {}) {
15275
- const base = opts.baseDir ?? import_node_path4.default.join(import_node_os2.default.homedir(), ".claude");
15276
- this.projectsRoot = import_node_path4.default.join(base, "projects");
15277
- this.fileHistoryRoot = import_node_path4.default.join(base, "file-history");
15343
+ const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
15344
+ this.projectsRoot = import_node_path5.default.join(base, "projects");
15345
+ this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
15278
15346
  }
15279
15347
  async listProjects() {
15280
15348
  let entries;
15281
15349
  try {
15282
- entries = import_node_fs5.default.readdirSync(this.projectsRoot, { withFileTypes: true });
15350
+ entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
15283
15351
  } catch (err) {
15284
15352
  if (err.code === "ENOENT") return [];
15285
15353
  throw err;
@@ -15287,9 +15355,9 @@ var ClaudeHistoryReader = class {
15287
15355
  const out = [];
15288
15356
  for (const ent of entries) {
15289
15357
  if (!ent.isDirectory()) continue;
15290
- const dir = import_node_path4.default.join(this.projectsRoot, ent.name);
15291
- const files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15292
- const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path4.default.join(dir, f))), 0);
15358
+ const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
15359
+ const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15360
+ const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
15293
15361
  out.push({
15294
15362
  projectPath: hashDirToCwd(ent.name),
15295
15363
  hashDir: ent.name,
@@ -15301,17 +15369,17 @@ var ClaudeHistoryReader = class {
15301
15369
  return out;
15302
15370
  }
15303
15371
  async listSessions(args) {
15304
- const dir = import_node_path4.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
15372
+ const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
15305
15373
  let files;
15306
15374
  try {
15307
- files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15375
+ files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
15308
15376
  } catch (err) {
15309
15377
  if (err.code === "ENOENT") return [];
15310
15378
  throw err;
15311
15379
  }
15312
15380
  const out = [];
15313
15381
  for (const f of files) {
15314
- const full = import_node_path4.default.join(dir, f);
15382
+ const full = import_node_path5.default.join(dir, f);
15315
15383
  const toolSessionId = f.slice(0, -".jsonl".length);
15316
15384
  const lines = readJsonlLines(full);
15317
15385
  let summary = "";
@@ -15366,7 +15434,7 @@ var ClaudeHistoryReader = class {
15366
15434
  return out;
15367
15435
  }
15368
15436
  async read(args) {
15369
- const file = import_node_path4.default.join(
15437
+ const file = import_node_path5.default.join(
15370
15438
  this.projectsRoot,
15371
15439
  cwdToHashDir(args.cwd),
15372
15440
  `${args.toolSessionId}.jsonl`
@@ -15399,7 +15467,7 @@ var ClaudeHistoryReader = class {
15399
15467
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
15400
15468
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
15401
15469
  listSubagentsFromDirectory(cwd, toolSessionId) {
15402
- const dir = import_node_path4.default.join(
15470
+ const dir = import_node_path5.default.join(
15403
15471
  this.projectsRoot,
15404
15472
  cwdToHashDir(cwd),
15405
15473
  toolSessionId,
@@ -15407,7 +15475,7 @@ var ClaudeHistoryReader = class {
15407
15475
  );
15408
15476
  let entries;
15409
15477
  try {
15410
- entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
15478
+ entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
15411
15479
  } catch (err) {
15412
15480
  if (err.code === "ENOENT") return null;
15413
15481
  return null;
@@ -15417,7 +15485,7 @@ var ClaudeHistoryReader = class {
15417
15485
  if (!e.isFile()) continue;
15418
15486
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
15419
15487
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
15420
- const filePath = import_node_path4.default.join(dir, e.name);
15488
+ const filePath = import_node_path5.default.join(dir, e.name);
15421
15489
  const lines = readJsonlLines(filePath);
15422
15490
  let firstText = "";
15423
15491
  let messageCount = 0;
@@ -15434,7 +15502,7 @@ var ClaudeHistoryReader = class {
15434
15502
  return out;
15435
15503
  }
15436
15504
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
15437
- const file = import_node_path4.default.join(
15505
+ const file = import_node_path5.default.join(
15438
15506
  this.projectsRoot,
15439
15507
  cwdToHashDir(cwd),
15440
15508
  `${toolSessionId}.jsonl`
@@ -15469,7 +15537,7 @@ var ClaudeHistoryReader = class {
15469
15537
  }
15470
15538
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
15471
15539
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
15472
- const file = import_node_path4.default.join(
15540
+ const file = import_node_path5.default.join(
15473
15541
  this.projectsRoot,
15474
15542
  cwdToHashDir(cwd),
15475
15543
  toolSessionId,
@@ -15478,7 +15546,7 @@ var ClaudeHistoryReader = class {
15478
15546
  );
15479
15547
  let exists = false;
15480
15548
  try {
15481
- exists = import_node_fs5.default.statSync(file).isFile();
15549
+ exists = import_node_fs6.default.statSync(file).isFile();
15482
15550
  } catch {
15483
15551
  return null;
15484
15552
  }
@@ -15497,7 +15565,7 @@ var ClaudeHistoryReader = class {
15497
15565
  * "那一刻每个 tracked 文件对应的 backup 文件名"
15498
15566
  */
15499
15567
  readFileHistorySnapshots(args) {
15500
- const file = import_node_path4.default.join(
15568
+ const file = import_node_path5.default.join(
15501
15569
  this.projectsRoot,
15502
15570
  cwdToHashDir(args.cwd),
15503
15571
  `${args.toolSessionId}.jsonl`
@@ -15542,7 +15610,7 @@ var ClaudeHistoryReader = class {
15542
15610
  for (const [anchorId, target] of snapshots) {
15543
15611
  let hasAny = false;
15544
15612
  for (const [rawPath, backup] of Object.entries(target)) {
15545
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
15613
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
15546
15614
  const backupContent = readBackupContent(
15547
15615
  this.fileHistoryRoot,
15548
15616
  args.toolSessionId,
@@ -15582,7 +15650,7 @@ var ClaudeHistoryReader = class {
15582
15650
  let totalInsertions = 0;
15583
15651
  let totalDeletions = 0;
15584
15652
  for (const [rawPath, backup] of Object.entries(target)) {
15585
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
15653
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
15586
15654
  const backupContent = readBackupContent(
15587
15655
  this.fileHistoryRoot,
15588
15656
  args.toolSessionId,
@@ -15629,7 +15697,7 @@ var ClaudeHistoryReader = class {
15629
15697
  };
15630
15698
  }
15631
15699
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
15632
- const file = import_node_path4.default.join(
15700
+ const file = import_node_path5.default.join(
15633
15701
  this.projectsRoot,
15634
15702
  cwdToHashDir(cwd),
15635
15703
  `${toolSessionId}.jsonl`
@@ -15651,27 +15719,27 @@ var ClaudeHistoryReader = class {
15651
15719
  // src/tools/claude.ts
15652
15720
  function macOSDesktopCandidates(home) {
15653
15721
  return [
15654
- import_node_path5.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
15722
+ import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
15655
15723
  "/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
15656
15724
  ];
15657
15725
  }
15658
15726
  function probeViaWhich() {
15659
15727
  try {
15660
15728
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
15661
- if (out && import_node_fs6.default.existsSync(out)) return out;
15729
+ if (out && import_node_fs7.default.existsSync(out)) return out;
15662
15730
  } catch {
15663
15731
  }
15664
15732
  return null;
15665
15733
  }
15666
15734
  async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
15667
- if (env.CLAUDE_BIN && import_node_fs6.default.existsSync(env.CLAUDE_BIN)) {
15735
+ if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
15668
15736
  return { available: true, path: env.CLAUDE_BIN };
15669
15737
  }
15670
15738
  const w = probeViaWhich();
15671
15739
  if (w) return { available: true, path: w };
15672
15740
  if (process.platform === "darwin") {
15673
15741
  for (const candidate of macOSDesktopCandidates(home)) {
15674
- if (import_node_fs6.default.existsSync(candidate)) {
15742
+ if (import_node_fs7.default.existsSync(candidate)) {
15675
15743
  return { available: true, path: candidate };
15676
15744
  }
15677
15745
  }
@@ -15982,10 +16050,10 @@ function parseAttachment(obj) {
15982
16050
  const memories = raw.map((m) => {
15983
16051
  if (!m || typeof m !== "object") return null;
15984
16052
  const rec = m;
15985
- const path17 = typeof rec.path === "string" ? rec.path : null;
16053
+ const path18 = typeof rec.path === "string" ? rec.path : null;
15986
16054
  const content = typeof rec.content === "string" ? rec.content : null;
15987
- if (!path17 || content == null) return null;
15988
- const out = { path: path17, content };
16055
+ if (!path18 || content == null) return null;
16056
+ const out = { path: path18, content };
15989
16057
  if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
15990
16058
  return out;
15991
16059
  }).filter((m) => m !== null);
@@ -16213,22 +16281,22 @@ var ClaudeAdapter = class {
16213
16281
  };
16214
16282
 
16215
16283
  // src/workspace/browser.ts
16216
- var import_node_fs7 = __toESM(require("fs"), 1);
16284
+ var import_node_fs8 = __toESM(require("fs"), 1);
16217
16285
  var import_node_os4 = __toESM(require("os"), 1);
16218
- var import_node_path6 = __toESM(require("path"), 1);
16286
+ var import_node_path7 = __toESM(require("path"), 1);
16219
16287
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
16220
16288
  function resolveInsideCwd(cwd, subpath) {
16221
- const absCwd = import_node_path6.default.resolve(cwd);
16222
- const joined = import_node_path6.default.resolve(absCwd, subpath ?? ".");
16223
- const rel = import_node_path6.default.relative(absCwd, joined);
16224
- if (rel.startsWith("..") || import_node_path6.default.isAbsolute(rel)) {
16289
+ const absCwd = import_node_path7.default.resolve(cwd);
16290
+ const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
16291
+ const rel = import_node_path7.default.relative(absCwd, joined);
16292
+ if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
16225
16293
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
16226
16294
  }
16227
16295
  return joined;
16228
16296
  }
16229
16297
  function ensureCwd(cwd) {
16230
16298
  try {
16231
- const stat = import_node_fs7.default.statSync(cwd);
16299
+ const stat = import_node_fs8.default.statSync(cwd);
16232
16300
  if (!stat.isDirectory()) {
16233
16301
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
16234
16302
  }
@@ -16242,7 +16310,7 @@ var WorkspaceBrowser = class {
16242
16310
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
16243
16311
  ensureCwd(cwd);
16244
16312
  const full = resolveInsideCwd(cwd, args.path);
16245
- const dirents = import_node_fs7.default.readdirSync(full, { withFileTypes: true });
16313
+ const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
16246
16314
  const entries = [];
16247
16315
  for (const d of dirents) {
16248
16316
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -16252,7 +16320,7 @@ var WorkspaceBrowser = class {
16252
16320
  mtime: ""
16253
16321
  };
16254
16322
  try {
16255
- const st = import_node_fs7.default.statSync(import_node_path6.default.join(full, d.name));
16323
+ const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
16256
16324
  entry.mtime = new Date(st.mtimeMs).toISOString();
16257
16325
  if (d.isFile()) entry.size = st.size;
16258
16326
  } catch {
@@ -16268,14 +16336,14 @@ var WorkspaceBrowser = class {
16268
16336
  read(args) {
16269
16337
  ensureCwd(args.cwd);
16270
16338
  const full = resolveInsideCwd(args.cwd, args.path);
16271
- const st = import_node_fs7.default.statSync(full);
16339
+ const st = import_node_fs8.default.statSync(full);
16272
16340
  if (!st.isFile()) {
16273
16341
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
16274
16342
  }
16275
16343
  if (st.size > MAX_FILE_BYTES) {
16276
16344
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
16277
16345
  }
16278
- const buf = import_node_fs7.default.readFileSync(full);
16346
+ const buf = import_node_fs8.default.readFileSync(full);
16279
16347
  const isBinary = buf.includes(0);
16280
16348
  if (isBinary) {
16281
16349
  return {
@@ -16297,9 +16365,9 @@ var WorkspaceBrowser = class {
16297
16365
  };
16298
16366
 
16299
16367
  // src/skills/scanner.ts
16300
- var import_node_fs8 = __toESM(require("fs"), 1);
16368
+ var import_node_fs9 = __toESM(require("fs"), 1);
16301
16369
  var import_node_os5 = __toESM(require("os"), 1);
16302
- var import_node_path7 = __toESM(require("path"), 1);
16370
+ var import_node_path8 = __toESM(require("path"), 1);
16303
16371
  function parseFrontmatter(content) {
16304
16372
  if (!content.startsWith("---")) return { name: "", description: "" };
16305
16373
  const end = content.indexOf("---", 3);
@@ -16335,7 +16403,7 @@ function parseFrontmatter(content) {
16335
16403
  }
16336
16404
  function isDirLikeSync(p) {
16337
16405
  try {
16338
- return import_node_fs8.default.statSync(p).isDirectory();
16406
+ return import_node_fs9.default.statSync(p).isDirectory();
16339
16407
  } catch {
16340
16408
  return false;
16341
16409
  }
@@ -16343,19 +16411,19 @@ function isDirLikeSync(p) {
16343
16411
  function scanSkillDir(dir, source, seen, out, pluginName) {
16344
16412
  let entries;
16345
16413
  try {
16346
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
16414
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
16347
16415
  } catch {
16348
16416
  return;
16349
16417
  }
16350
16418
  for (const ent of entries) {
16351
- const entryPath = import_node_path7.default.join(dir, ent.name);
16419
+ const entryPath = import_node_path8.default.join(dir, ent.name);
16352
16420
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
16353
16421
  let content;
16354
16422
  try {
16355
- content = import_node_fs8.default.readFileSync(import_node_path7.default.join(entryPath, "SKILL.md"), "utf8");
16423
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
16356
16424
  } catch {
16357
16425
  try {
16358
- content = import_node_fs8.default.readFileSync(import_node_path7.default.join(entryPath, "skill.md"), "utf8");
16426
+ content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
16359
16427
  } catch {
16360
16428
  continue;
16361
16429
  }
@@ -16373,26 +16441,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
16373
16441
  function scanCommandDir(dir, source, seen, out, pluginName) {
16374
16442
  let entries;
16375
16443
  try {
16376
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
16444
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
16377
16445
  } catch {
16378
16446
  return;
16379
16447
  }
16380
16448
  for (const ent of entries) {
16381
- const entryPath = import_node_path7.default.join(dir, ent.name);
16449
+ const entryPath = import_node_path8.default.join(dir, ent.name);
16382
16450
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
16383
16451
  const ns = ent.name;
16384
16452
  let subEntries;
16385
16453
  try {
16386
- subEntries = import_node_fs8.default.readdirSync(entryPath, { withFileTypes: true });
16454
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
16387
16455
  } catch {
16388
16456
  continue;
16389
16457
  }
16390
16458
  for (const se of subEntries) {
16391
16459
  if (!se.name.endsWith(".md")) continue;
16392
- const sePath = import_node_path7.default.join(entryPath, se.name);
16460
+ const sePath = import_node_path8.default.join(entryPath, se.name);
16393
16461
  let content;
16394
16462
  try {
16395
- content = import_node_fs8.default.readFileSync(sePath, "utf8");
16463
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
16396
16464
  } catch {
16397
16465
  continue;
16398
16466
  }
@@ -16409,7 +16477,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
16409
16477
  } else if (ent.name.endsWith(".md")) {
16410
16478
  let content;
16411
16479
  try {
16412
- content = import_node_fs8.default.readFileSync(entryPath, "utf8");
16480
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
16413
16481
  } catch {
16414
16482
  continue;
16415
16483
  }
@@ -16425,10 +16493,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
16425
16493
  }
16426
16494
  }
16427
16495
  function readInstalledPlugins(home) {
16428
- const file = import_node_path7.default.join(home, ".claude", "plugins", "installed_plugins.json");
16496
+ const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
16429
16497
  let raw;
16430
16498
  try {
16431
- raw = import_node_fs8.default.readFileSync(file, "utf8");
16499
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
16432
16500
  } catch {
16433
16501
  return [];
16434
16502
  }
@@ -16466,14 +16534,14 @@ var SkillsScanner = class {
16466
16534
  list(args) {
16467
16535
  const seen = /* @__PURE__ */ new Set();
16468
16536
  const out = [];
16469
- scanSkillDir(import_node_path7.default.join(this.home, ".claude", "skills"), "global", seen, out);
16470
- scanCommandDir(import_node_path7.default.join(this.home, ".claude", "commands"), "global", seen, out);
16471
- scanSkillDir(import_node_path7.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
16472
- scanCommandDir(import_node_path7.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
16537
+ scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
16538
+ scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
16539
+ scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
16540
+ scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
16473
16541
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
16474
16542
  for (const { name, root } of plugins) {
16475
- scanSkillDir(import_node_path7.default.join(root, "skills"), "plugin", seen, out, name);
16476
- scanCommandDir(import_node_path7.default.join(root, "commands"), "plugin", seen, out, name);
16543
+ scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
16544
+ scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
16477
16545
  }
16478
16546
  out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
16479
16547
  return out;
@@ -16481,9 +16549,9 @@ var SkillsScanner = class {
16481
16549
  };
16482
16550
 
16483
16551
  // src/observer/session-observer.ts
16484
- var import_node_fs9 = __toESM(require("fs"), 1);
16552
+ var import_node_fs10 = __toESM(require("fs"), 1);
16485
16553
  var import_node_os6 = __toESM(require("os"), 1);
16486
- var import_node_path8 = __toESM(require("path"), 1);
16554
+ var import_node_path9 = __toESM(require("path"), 1);
16487
16555
  var SessionObserver = class {
16488
16556
  constructor(opts) {
16489
16557
  this.opts = opts;
@@ -16494,14 +16562,14 @@ var SessionObserver = class {
16494
16562
  watches = /* @__PURE__ */ new Map();
16495
16563
  resolveJsonlPath(cwd, toolSessionId, override) {
16496
16564
  if (override) return override;
16497
- return import_node_path8.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
16565
+ return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
16498
16566
  }
16499
16567
  start(args) {
16500
16568
  this.stop(args.sessionId);
16501
16569
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
16502
16570
  let size = 0;
16503
16571
  try {
16504
- size = import_node_fs9.default.statSync(filePath).size;
16572
+ size = import_node_fs10.default.statSync(filePath).size;
16505
16573
  } catch {
16506
16574
  }
16507
16575
  const w = {
@@ -16514,10 +16582,10 @@ var SessionObserver = class {
16514
16582
  adapter: args.adapter
16515
16583
  };
16516
16584
  try {
16517
- import_node_fs9.default.mkdirSync(import_node_path8.default.dirname(filePath), { recursive: true });
16585
+ import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
16518
16586
  } catch {
16519
16587
  }
16520
- w.watcher = import_node_fs9.default.watch(import_node_path8.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
16588
+ w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
16521
16589
  if (!changedName || !filePath.endsWith(changedName)) return;
16522
16590
  this.poll(w);
16523
16591
  });
@@ -16532,7 +16600,7 @@ var SessionObserver = class {
16532
16600
  // reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
16533
16601
  hydrateMetaTail(w, maxLines = 200) {
16534
16602
  try {
16535
- const raw = import_node_fs9.default.readFileSync(w.filePath, "utf8");
16603
+ const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
16536
16604
  if (!raw) return;
16537
16605
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
16538
16606
  if (allLines.length === 0) return;
@@ -16553,7 +16621,7 @@ var SessionObserver = class {
16553
16621
  poll(w) {
16554
16622
  let size = 0;
16555
16623
  try {
16556
- size = import_node_fs9.default.statSync(w.filePath).size;
16624
+ size = import_node_fs10.default.statSync(w.filePath).size;
16557
16625
  } catch {
16558
16626
  return;
16559
16627
  }
@@ -16562,11 +16630,11 @@ var SessionObserver = class {
16562
16630
  w.buf = "";
16563
16631
  }
16564
16632
  if (size === w.lastSize) return;
16565
- const fd = import_node_fs9.default.openSync(w.filePath, "r");
16633
+ const fd = import_node_fs10.default.openSync(w.filePath, "r");
16566
16634
  try {
16567
16635
  const len = size - w.lastSize;
16568
16636
  const buf = Buffer.alloc(len);
16569
- import_node_fs9.default.readSync(fd, buf, 0, len, w.lastSize);
16637
+ import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
16570
16638
  w.lastSize = size;
16571
16639
  w.buf += buf.toString("utf8");
16572
16640
  let newlineIndex;
@@ -16580,7 +16648,7 @@ var SessionObserver = class {
16580
16648
  this.maybeReportUserMessage(w.sessionId, line);
16581
16649
  }
16582
16650
  } finally {
16583
- import_node_fs9.default.closeSync(fd);
16651
+ import_node_fs10.default.closeSync(fd);
16584
16652
  }
16585
16653
  }
16586
16654
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -16995,10 +17063,10 @@ function isLocalhost(addr) {
16995
17063
  }
16996
17064
 
16997
17065
  // src/discovery/state-file.ts
16998
- var import_node_fs10 = __toESM(require("fs"), 1);
16999
- var import_node_path9 = __toESM(require("path"), 1);
17066
+ var import_node_fs11 = __toESM(require("fs"), 1);
17067
+ var import_node_path10 = __toESM(require("path"), 1);
17000
17068
  function defaultStateFilePath(dataDir) {
17001
- return import_node_path9.default.join(dataDir, "state.json");
17069
+ return import_node_path10.default.join(dataDir, "state.json");
17002
17070
  }
17003
17071
  function isPidAlive(pid) {
17004
17072
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -17020,7 +17088,7 @@ var StateFileManager = class {
17020
17088
  }
17021
17089
  read() {
17022
17090
  try {
17023
- const raw = import_node_fs10.default.readFileSync(this.file, "utf8");
17091
+ const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
17024
17092
  const parsed = JSON.parse(raw);
17025
17093
  return parsed;
17026
17094
  } catch {
@@ -17034,34 +17102,34 @@ var StateFileManager = class {
17034
17102
  return { status: "stale", existing };
17035
17103
  }
17036
17104
  write(state) {
17037
- import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(this.file), { recursive: true });
17105
+ import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
17038
17106
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
17039
- import_node_fs10.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
17040
- import_node_fs10.default.renameSync(tmp, this.file);
17107
+ import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
17108
+ import_node_fs11.default.renameSync(tmp, this.file);
17041
17109
  if (process.platform !== "win32") {
17042
17110
  try {
17043
- import_node_fs10.default.chmodSync(this.file, 384);
17111
+ import_node_fs11.default.chmodSync(this.file, 384);
17044
17112
  } catch {
17045
17113
  }
17046
17114
  }
17047
17115
  }
17048
17116
  delete() {
17049
17117
  try {
17050
- import_node_fs10.default.unlinkSync(this.file);
17118
+ import_node_fs11.default.unlinkSync(this.file);
17051
17119
  } catch {
17052
17120
  }
17053
17121
  }
17054
17122
  };
17055
17123
 
17056
17124
  // src/tunnel/tunnel-manager.ts
17057
- var import_node_fs13 = __toESM(require("fs"), 1);
17058
- var import_node_path12 = __toESM(require("path"), 1);
17125
+ var import_node_fs14 = __toESM(require("fs"), 1);
17126
+ var import_node_path13 = __toESM(require("path"), 1);
17059
17127
  var import_node_crypto3 = __toESM(require("crypto"), 1);
17060
17128
  var import_node_child_process4 = require("child_process");
17061
17129
 
17062
17130
  // src/tunnel/tunnel-store.ts
17063
- var import_node_fs11 = __toESM(require("fs"), 1);
17064
- var import_node_path10 = __toESM(require("path"), 1);
17131
+ var import_node_fs12 = __toESM(require("fs"), 1);
17132
+ var import_node_path11 = __toESM(require("path"), 1);
17065
17133
  var TunnelStore = class {
17066
17134
  constructor(filePath) {
17067
17135
  this.filePath = filePath;
@@ -17069,7 +17137,7 @@ var TunnelStore = class {
17069
17137
  filePath;
17070
17138
  async get() {
17071
17139
  try {
17072
- const raw = await import_node_fs11.default.promises.readFile(this.filePath, "utf8");
17140
+ const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
17073
17141
  const obj = JSON.parse(raw);
17074
17142
  if (!isPersistedTunnel(obj)) return null;
17075
17143
  return obj;
@@ -17080,22 +17148,22 @@ var TunnelStore = class {
17080
17148
  }
17081
17149
  }
17082
17150
  async set(v) {
17083
- const dir = import_node_path10.default.dirname(this.filePath);
17084
- await import_node_fs11.default.promises.mkdir(dir, { recursive: true });
17151
+ const dir = import_node_path11.default.dirname(this.filePath);
17152
+ await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
17085
17153
  const data = JSON.stringify(v, null, 2);
17086
17154
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
17087
- await import_node_fs11.default.promises.writeFile(tmp, data, { mode: 384 });
17155
+ await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
17088
17156
  if (process.platform !== "win32") {
17089
17157
  try {
17090
- await import_node_fs11.default.promises.chmod(tmp, 384);
17158
+ await import_node_fs12.default.promises.chmod(tmp, 384);
17091
17159
  } catch {
17092
17160
  }
17093
17161
  }
17094
- await import_node_fs11.default.promises.rename(tmp, this.filePath);
17162
+ await import_node_fs12.default.promises.rename(tmp, this.filePath);
17095
17163
  }
17096
17164
  async clear() {
17097
17165
  try {
17098
- await import_node_fs11.default.promises.unlink(this.filePath);
17166
+ await import_node_fs12.default.promises.unlink(this.filePath);
17099
17167
  } catch (err) {
17100
17168
  const code = err?.code;
17101
17169
  if (code !== "ENOENT") throw err;
@@ -17190,9 +17258,9 @@ function escape(v) {
17190
17258
  }
17191
17259
 
17192
17260
  // src/tunnel/frpc-binary.ts
17193
- var import_node_fs12 = __toESM(require("fs"), 1);
17261
+ var import_node_fs13 = __toESM(require("fs"), 1);
17194
17262
  var import_node_os7 = __toESM(require("os"), 1);
17195
- var import_node_path11 = __toESM(require("path"), 1);
17263
+ var import_node_path12 = __toESM(require("path"), 1);
17196
17264
  var import_node_child_process3 = require("child_process");
17197
17265
  var import_node_stream = require("stream");
17198
17266
  var import_promises = require("stream/promises");
@@ -17224,20 +17292,20 @@ function frpcDownloadUrl(version2, p) {
17224
17292
  }
17225
17293
  async function ensureFrpcBinary(opts) {
17226
17294
  if (opts.override) {
17227
- if (!import_node_fs12.default.existsSync(opts.override)) {
17295
+ if (!import_node_fs13.default.existsSync(opts.override)) {
17228
17296
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
17229
17297
  }
17230
17298
  return opts.override;
17231
17299
  }
17232
17300
  const version2 = opts.version ?? FRPC_VERSION;
17233
17301
  const platform = opts.platform ?? detectPlatform();
17234
- const binDir = import_node_path11.default.join(opts.dataDir, "bin");
17235
- import_node_fs12.default.mkdirSync(binDir, { recursive: true });
17302
+ const binDir = import_node_path12.default.join(opts.dataDir, "bin");
17303
+ import_node_fs13.default.mkdirSync(binDir, { recursive: true });
17236
17304
  cleanupStaleArtifacts(binDir);
17237
- const stableBin = import_node_path11.default.join(binDir, "frpc");
17238
- if (import_node_fs12.default.existsSync(stableBin)) return stableBin;
17305
+ const stableBin = import_node_path12.default.join(binDir, "frpc");
17306
+ if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
17239
17307
  const partialBin = `${stableBin}.partial`;
17240
- const tarballPath = import_node_path11.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
17308
+ const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
17241
17309
  try {
17242
17310
  const url = frpcDownloadUrl(version2, platform);
17243
17311
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -17246,8 +17314,8 @@ async function ensureFrpcBinary(opts) {
17246
17314
  } else {
17247
17315
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
17248
17316
  }
17249
- import_node_fs12.default.chmodSync(partialBin, 493);
17250
- import_node_fs12.default.renameSync(partialBin, stableBin);
17317
+ import_node_fs13.default.chmodSync(partialBin, 493);
17318
+ import_node_fs13.default.renameSync(partialBin, stableBin);
17251
17319
  } finally {
17252
17320
  safeUnlink(tarballPath);
17253
17321
  safeUnlink(partialBin);
@@ -17257,15 +17325,15 @@ async function ensureFrpcBinary(opts) {
17257
17325
  function cleanupStaleArtifacts(binDir) {
17258
17326
  let entries;
17259
17327
  try {
17260
- entries = import_node_fs12.default.readdirSync(binDir);
17328
+ entries = import_node_fs13.default.readdirSync(binDir);
17261
17329
  } catch {
17262
17330
  return;
17263
17331
  }
17264
17332
  for (const name of entries) {
17265
17333
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
17266
- const full = import_node_path11.default.join(binDir, name);
17334
+ const full = import_node_path12.default.join(binDir, name);
17267
17335
  try {
17268
- import_node_fs12.default.rmSync(full, { recursive: true, force: true });
17336
+ import_node_fs13.default.rmSync(full, { recursive: true, force: true });
17269
17337
  } catch {
17270
17338
  }
17271
17339
  }
@@ -17273,7 +17341,7 @@ function cleanupStaleArtifacts(binDir) {
17273
17341
  }
17274
17342
  function safeUnlink(p) {
17275
17343
  try {
17276
- import_node_fs12.default.unlinkSync(p);
17344
+ import_node_fs13.default.unlinkSync(p);
17277
17345
  } catch {
17278
17346
  }
17279
17347
  }
@@ -17284,13 +17352,13 @@ async function downloadToFile(url, dest, fetchImpl) {
17284
17352
  if (!res.ok || !res.body) {
17285
17353
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
17286
17354
  }
17287
- const out = import_node_fs12.default.createWriteStream(dest);
17355
+ const out = import_node_fs13.default.createWriteStream(dest);
17288
17356
  const nodeStream = import_node_stream.Readable.fromWeb(res.body);
17289
17357
  await (0, import_promises.pipeline)(nodeStream, out);
17290
17358
  }
17291
17359
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
17292
- const work = import_node_path11.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
17293
- import_node_fs12.default.mkdirSync(work, { recursive: true });
17360
+ const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
17361
+ import_node_fs13.default.mkdirSync(work, { recursive: true });
17294
17362
  try {
17295
17363
  await new Promise((resolve, reject) => {
17296
17364
  const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -17298,13 +17366,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
17298
17366
  proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
17299
17367
  });
17300
17368
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
17301
- const src = import_node_path11.default.join(work, dirName, "frpc");
17302
- if (!import_node_fs12.default.existsSync(src)) {
17369
+ const src = import_node_path12.default.join(work, dirName, "frpc");
17370
+ if (!import_node_fs13.default.existsSync(src)) {
17303
17371
  throw new Error(`frpc not found inside tarball at ${src}`);
17304
17372
  }
17305
- import_node_fs12.default.copyFileSync(src, destBin);
17373
+ import_node_fs13.default.copyFileSync(src, destBin);
17306
17374
  } finally {
17307
- import_node_fs12.default.rmSync(work, { recursive: true, force: true });
17375
+ import_node_fs13.default.rmSync(work, { recursive: true, force: true });
17308
17376
  }
17309
17377
  }
17310
17378
 
@@ -17313,7 +17381,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
17313
17381
  var TunnelManager = class {
17314
17382
  constructor(deps) {
17315
17383
  this.deps = deps;
17316
- this.store = deps.store ?? new TunnelStore(import_node_path12.default.join(deps.dataDir, "tunnel.json"));
17384
+ this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
17317
17385
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
17318
17386
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
17319
17387
  }
@@ -17430,7 +17498,7 @@ var TunnelManager = class {
17430
17498
  dataDir: this.deps.dataDir,
17431
17499
  override: this.deps.frpcBinaryOverride ?? void 0
17432
17500
  });
17433
- const tomlPath = import_node_path12.default.join(this.deps.dataDir, "frpc.toml");
17501
+ const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
17434
17502
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
17435
17503
  const toml = buildFrpcToml({
17436
17504
  serverAddr: t.frpsHost,
@@ -17441,12 +17509,12 @@ var TunnelManager = class {
17441
17509
  localPort,
17442
17510
  logLevel: "info"
17443
17511
  });
17444
- await import_node_fs13.default.promises.writeFile(tomlPath, toml, { mode: 384 });
17512
+ await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
17445
17513
  const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
17446
17514
  stdio: ["ignore", "pipe", "pipe"]
17447
17515
  });
17448
- const logFilePath = import_node_path12.default.join(this.deps.dataDir, "frpc.log");
17449
- const logStream = import_node_fs13.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
17516
+ const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
17517
+ const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
17450
17518
  logStream.on("error", () => {
17451
17519
  });
17452
17520
  const tee = (chunk) => {
@@ -17538,12 +17606,12 @@ function deriveStableDeviceKey(opts = {}) {
17538
17606
  }
17539
17607
 
17540
17608
  // src/auth-store.ts
17541
- var import_node_fs14 = __toESM(require("fs"), 1);
17542
- var import_node_path13 = __toESM(require("path"), 1);
17609
+ var import_node_fs15 = __toESM(require("fs"), 1);
17610
+ var import_node_path14 = __toESM(require("path"), 1);
17543
17611
  var import_node_crypto5 = __toESM(require("crypto"), 1);
17544
17612
  var AUTH_FILE_NAME = "auth.json";
17545
17613
  function authFilePath(dataDir) {
17546
- return import_node_path13.default.join(dataDir, AUTH_FILE_NAME);
17614
+ return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
17547
17615
  }
17548
17616
  function loadOrCreateAuthToken(opts) {
17549
17617
  const file = authFilePath(opts.dataDir);
@@ -17559,7 +17627,7 @@ function defaultGenerate() {
17559
17627
  }
17560
17628
  function readAuthFile(file) {
17561
17629
  try {
17562
- const raw = import_node_fs14.default.readFileSync(file, "utf8");
17630
+ const raw = import_node_fs15.default.readFileSync(file, "utf8");
17563
17631
  const parsed = JSON.parse(raw);
17564
17632
  if (typeof parsed?.token === "string" && parsed.token.length > 0) {
17565
17633
  return {
@@ -17575,20 +17643,20 @@ function readAuthFile(file) {
17575
17643
  }
17576
17644
  }
17577
17645
  function writeAuthFile(file, content) {
17578
- import_node_fs14.default.mkdirSync(import_node_path13.default.dirname(file), { recursive: true });
17579
- import_node_fs14.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
17646
+ import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
17647
+ import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
17580
17648
  try {
17581
- import_node_fs14.default.chmodSync(file, 384);
17649
+ import_node_fs15.default.chmodSync(file, 384);
17582
17650
  } catch {
17583
17651
  }
17584
17652
  }
17585
17653
 
17586
17654
  // src/session/fork.ts
17587
- var import_node_fs15 = __toESM(require("fs"), 1);
17655
+ var import_node_fs16 = __toESM(require("fs"), 1);
17588
17656
  var import_node_os9 = __toESM(require("os"), 1);
17589
- var import_node_path14 = __toESM(require("path"), 1);
17657
+ var import_node_path15 = __toESM(require("path"), 1);
17590
17658
  function readJsonlEntries(file) {
17591
- const raw = import_node_fs15.default.readFileSync(file, "utf8");
17659
+ const raw = import_node_fs16.default.readFileSync(file, "utf8");
17592
17660
  const out = [];
17593
17661
  for (const line of raw.split("\n")) {
17594
17662
  const t = line.trim();
@@ -17601,10 +17669,10 @@ function readJsonlEntries(file) {
17601
17669
  return out;
17602
17670
  }
17603
17671
  function forkSession(input) {
17604
- const baseDir = input.baseDir ?? import_node_path14.default.join(import_node_os9.default.homedir(), ".claude");
17605
- const projectDir = import_node_path14.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
17606
- const sourceFile = import_node_path14.default.join(projectDir, `${input.toolSessionId}.jsonl`);
17607
- if (!import_node_fs15.default.existsSync(sourceFile)) {
17672
+ const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
17673
+ const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
17674
+ const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
17675
+ if (!import_node_fs16.default.existsSync(sourceFile)) {
17608
17676
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
17609
17677
  }
17610
17678
  const entries = readJsonlEntries(sourceFile);
@@ -17634,9 +17702,9 @@ function forkSession(input) {
17634
17702
  }
17635
17703
  forkedLines.push(JSON.stringify(forked));
17636
17704
  }
17637
- const forkedFilePath = import_node_path14.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
17638
- import_node_fs15.default.mkdirSync(projectDir, { recursive: true });
17639
- import_node_fs15.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
17705
+ const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
17706
+ import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
17707
+ import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
17640
17708
  return { forkedToolSessionId, forkedFilePath };
17641
17709
  }
17642
17710
 
@@ -17892,9 +17960,9 @@ function buildWorkspaceHandlers(deps) {
17892
17960
 
17893
17961
  // src/workspace/git.ts
17894
17962
  var import_node_child_process5 = require("child_process");
17895
- var import_node_fs16 = __toESM(require("fs"), 1);
17963
+ var import_node_fs17 = __toESM(require("fs"), 1);
17896
17964
  var import_node_os10 = __toESM(require("os"), 1);
17897
- var import_node_path15 = __toESM(require("path"), 1);
17965
+ var import_node_path16 = __toESM(require("path"), 1);
17898
17966
  var import_node_util = require("util");
17899
17967
  var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
17900
17968
  function formatChildProcessError(err) {
@@ -17909,9 +17977,9 @@ function formatChildProcessError(err) {
17909
17977
  return e.message ?? "unknown error";
17910
17978
  }
17911
17979
  function normalizePath(p) {
17912
- const resolved = import_node_path15.default.resolve(p);
17980
+ const resolved = import_node_path16.default.resolve(p);
17913
17981
  try {
17914
- return import_node_fs16.default.realpathSync(resolved);
17982
+ return import_node_fs17.default.realpathSync(resolved);
17915
17983
  } catch {
17916
17984
  return resolved;
17917
17985
  }
@@ -18012,13 +18080,13 @@ function flattenToDirName(branch) {
18012
18080
  }
18013
18081
  function encodeClaudeProjectDir(absPath) {
18014
18082
  if (!absPath || typeof absPath !== "string") return "";
18015
- let canonical = import_node_path15.default.resolve(absPath);
18083
+ let canonical = import_node_path16.default.resolve(absPath);
18016
18084
  try {
18017
- canonical = import_node_fs16.default.realpathSync(canonical);
18085
+ canonical = import_node_fs17.default.realpathSync(canonical);
18018
18086
  } catch {
18019
18087
  try {
18020
- const parent = import_node_fs16.default.realpathSync(import_node_path15.default.dirname(canonical));
18021
- canonical = import_node_path15.default.join(parent, import_node_path15.default.basename(canonical));
18088
+ const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
18089
+ canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
18022
18090
  } catch {
18023
18091
  }
18024
18092
  }
@@ -18042,11 +18110,11 @@ async function createWorktree(input) {
18042
18110
  if (!isGitRoot) {
18043
18111
  throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
18044
18112
  }
18045
- const parent = import_node_path15.default.dirname(import_node_path15.default.resolve(cwd));
18046
- if (parent === "/" || parent === import_node_path15.default.resolve(cwd)) {
18113
+ const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
18114
+ if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
18047
18115
  throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
18048
18116
  }
18049
- const worktreeRoot = import_node_path15.default.join(parent, dirName);
18117
+ const worktreeRoot = import_node_path16.default.join(parent, dirName);
18050
18118
  try {
18051
18119
  await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
18052
18120
  timeout: 3e3
@@ -18063,7 +18131,7 @@ async function createWorktree(input) {
18063
18131
  const msg = err.message;
18064
18132
  if (msg.startsWith("\u5206\u652F ")) throw err;
18065
18133
  }
18066
- if (import_node_fs16.default.existsSync(worktreeRoot)) {
18134
+ if (import_node_fs17.default.existsSync(worktreeRoot)) {
18067
18135
  throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
18068
18136
  }
18069
18137
  try {
@@ -18091,8 +18159,8 @@ async function removeWorktree(input) {
18091
18159
  );
18092
18160
  const gitCommonDir = stdout.trim();
18093
18161
  if (!gitCommonDir) throw new Error("empty git-common-dir");
18094
- const absGitCommon = import_node_path15.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path15.default.resolve(worktreeRoot, gitCommonDir);
18095
- repoRoot = import_node_path15.default.dirname(absGitCommon);
18162
+ const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
18163
+ repoRoot = import_node_path16.default.dirname(absGitCommon);
18096
18164
  } catch {
18097
18165
  repoRoot = null;
18098
18166
  }
@@ -18104,7 +18172,7 @@ async function removeWorktree(input) {
18104
18172
  } catch (err) {
18105
18173
  const stderr = err.stderr ?? "";
18106
18174
  const lower = stderr.toLowerCase();
18107
- const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs16.default.existsSync(worktreeRoot);
18175
+ const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
18108
18176
  if (!vanished) {
18109
18177
  throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
18110
18178
  }
@@ -18123,10 +18191,10 @@ async function removeWorktree(input) {
18123
18191
  try {
18124
18192
  const encoded = encodeClaudeProjectDir(worktreeRoot);
18125
18193
  if (encoded) {
18126
- const projectsRoot = import_node_path15.default.join(import_node_os10.default.homedir(), ".claude", "projects");
18127
- const target = import_node_path15.default.resolve(projectsRoot, encoded);
18128
- if (target.startsWith(projectsRoot + import_node_path15.default.sep) && target !== projectsRoot) {
18129
- import_node_fs16.default.rmSync(target, { recursive: true, force: true });
18194
+ const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
18195
+ const target = import_node_path16.default.resolve(projectsRoot, encoded);
18196
+ if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
18197
+ import_node_fs17.default.rmSync(target, { recursive: true, force: true });
18130
18198
  }
18131
18199
  }
18132
18200
  } catch {
@@ -18253,7 +18321,7 @@ function buildMethodHandlers(deps) {
18253
18321
  async function startDaemon(config) {
18254
18322
  const logger = createLogger({
18255
18323
  level: config.logLevel,
18256
- file: import_node_path16.default.join(config.dataDir, "clawd.log")
18324
+ file: import_node_path17.default.join(config.dataDir, "clawd.log")
18257
18325
  });
18258
18326
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
18259
18327
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
@@ -18293,6 +18361,7 @@ async function startDaemon(config) {
18293
18361
  logger,
18294
18362
  getAdapter,
18295
18363
  historyReader: history,
18364
+ dataDir: config.dataDir,
18296
18365
  broadcastFrame: (frame, target) => {
18297
18366
  if (target === "all") {
18298
18367
  transport?.broadcastAll(frame);
@@ -18415,8 +18484,8 @@ async function startDaemon(config) {
18415
18484
  const lines = [
18416
18485
  `Tunnel: ${r.url}`,
18417
18486
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
18418
- `Frpc config: ${import_node_path16.default.join(config.dataDir, "frpc.toml")}`,
18419
- `Frpc log: ${import_node_path16.default.join(config.dataDir, "frpc.log")}`
18487
+ `Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
18488
+ `Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
18420
18489
  ];
18421
18490
  const width = Math.max(...lines.map((l) => l.length));
18422
18491
  const bar = "\u2550".repeat(width + 4);
@@ -18429,8 +18498,8 @@ ${bar}
18429
18498
 
18430
18499
  `);
18431
18500
  try {
18432
- const connectPath = import_node_path16.default.join(config.dataDir, "connect.txt");
18433
- import_node_fs17.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
18501
+ const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
18502
+ import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
18434
18503
  } catch {
18435
18504
  }
18436
18505
  } catch (err) {