@clawos-dev/clawd 0.2.209-beta.415.57f6599 → 0.2.209

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -742,8 +742,8 @@ var init_parseUtil = __esm({
742
742
  init_errors2();
743
743
  init_en();
744
744
  makeIssue = (params) => {
745
- const { data, path: path77, errorMaps, issueData } = params;
746
- const fullPath = [...path77, ...issueData.path || []];
745
+ const { data, path: path78, errorMaps, issueData } = params;
746
+ const fullPath = [...path78, ...issueData.path || []];
747
747
  const fullIssue = {
748
748
  ...issueData,
749
749
  path: fullPath
@@ -1054,11 +1054,11 @@ var init_types = __esm({
1054
1054
  init_parseUtil();
1055
1055
  init_util();
1056
1056
  ParseInputLazyPath = class {
1057
- constructor(parent, value, path77, key) {
1057
+ constructor(parent, value, path78, key) {
1058
1058
  this._cachedPath = [];
1059
1059
  this.parent = parent;
1060
1060
  this.data = value;
1061
- this._path = path77;
1061
+ this._path = path78;
1062
1062
  this._key = key;
1063
1063
  }
1064
1064
  get path() {
@@ -6449,8 +6449,8 @@ var require_req = __commonJS({
6449
6449
  if (req.originalUrl) {
6450
6450
  _req.url = req.originalUrl;
6451
6451
  } else {
6452
- const path77 = req.path;
6453
- _req.url = typeof path77 === "string" ? path77 : req.url ? req.url.path || req.url : void 0;
6452
+ const path78 = req.path;
6453
+ _req.url = typeof path78 === "string" ? path78 : req.url ? req.url.path || req.url : void 0;
6454
6454
  }
6455
6455
  if (req.query) {
6456
6456
  _req.query = req.query;
@@ -6615,14 +6615,14 @@ var require_redact = __commonJS({
6615
6615
  }
6616
6616
  return obj;
6617
6617
  }
6618
- function parsePath(path77) {
6618
+ function parsePath(path78) {
6619
6619
  const parts = [];
6620
6620
  let current = "";
6621
6621
  let inBrackets = false;
6622
6622
  let inQuotes = false;
6623
6623
  let quoteChar = "";
6624
- for (let i = 0; i < path77.length; i++) {
6625
- const char = path77[i];
6624
+ for (let i = 0; i < path78.length; i++) {
6625
+ const char = path78[i];
6626
6626
  if (!inBrackets && char === ".") {
6627
6627
  if (current) {
6628
6628
  parts.push(current);
@@ -6753,10 +6753,10 @@ var require_redact = __commonJS({
6753
6753
  return current;
6754
6754
  }
6755
6755
  function redactPaths(obj, paths, censor, remove = false) {
6756
- for (const path77 of paths) {
6757
- const parts = parsePath(path77);
6756
+ for (const path78 of paths) {
6757
+ const parts = parsePath(path78);
6758
6758
  if (parts.includes("*")) {
6759
- redactWildcardPath(obj, parts, censor, path77, remove);
6759
+ redactWildcardPath(obj, parts, censor, path78, remove);
6760
6760
  } else {
6761
6761
  if (remove) {
6762
6762
  removeKey(obj, parts);
@@ -6841,8 +6841,8 @@ var require_redact = __commonJS({
6841
6841
  }
6842
6842
  } else {
6843
6843
  if (afterWildcard.includes("*")) {
6844
- const wrappedCensor = typeof censor === "function" ? (value, path77) => {
6845
- const fullPath = [...pathArray.slice(0, pathLength), ...path77];
6844
+ const wrappedCensor = typeof censor === "function" ? (value, path78) => {
6845
+ const fullPath = [...pathArray.slice(0, pathLength), ...path78];
6846
6846
  return censor(value, fullPath);
6847
6847
  } : censor;
6848
6848
  redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
@@ -6877,8 +6877,8 @@ var require_redact = __commonJS({
6877
6877
  return null;
6878
6878
  }
6879
6879
  const pathStructure = /* @__PURE__ */ new Map();
6880
- for (const path77 of pathsToClone) {
6881
- const parts = parsePath(path77);
6880
+ for (const path78 of pathsToClone) {
6881
+ const parts = parsePath(path78);
6882
6882
  let current = pathStructure;
6883
6883
  for (let i = 0; i < parts.length; i++) {
6884
6884
  const part = parts[i];
@@ -6930,24 +6930,24 @@ var require_redact = __commonJS({
6930
6930
  }
6931
6931
  return cloneSelectively(obj, pathStructure);
6932
6932
  }
6933
- function validatePath(path77) {
6934
- if (typeof path77 !== "string") {
6933
+ function validatePath(path78) {
6934
+ if (typeof path78 !== "string") {
6935
6935
  throw new Error("Paths must be (non-empty) strings");
6936
6936
  }
6937
- if (path77 === "") {
6937
+ if (path78 === "") {
6938
6938
  throw new Error("Invalid redaction path ()");
6939
6939
  }
6940
- if (path77.includes("..")) {
6941
- throw new Error(`Invalid redaction path (${path77})`);
6940
+ if (path78.includes("..")) {
6941
+ throw new Error(`Invalid redaction path (${path78})`);
6942
6942
  }
6943
- if (path77.includes(",")) {
6944
- throw new Error(`Invalid redaction path (${path77})`);
6943
+ if (path78.includes(",")) {
6944
+ throw new Error(`Invalid redaction path (${path78})`);
6945
6945
  }
6946
6946
  let bracketCount = 0;
6947
6947
  let inQuotes = false;
6948
6948
  let quoteChar = "";
6949
- for (let i = 0; i < path77.length; i++) {
6950
- const char = path77[i];
6949
+ for (let i = 0; i < path78.length; i++) {
6950
+ const char = path78[i];
6951
6951
  if ((char === '"' || char === "'") && bracketCount > 0) {
6952
6952
  if (!inQuotes) {
6953
6953
  inQuotes = true;
@@ -6961,20 +6961,20 @@ var require_redact = __commonJS({
6961
6961
  } else if (char === "]" && !inQuotes) {
6962
6962
  bracketCount--;
6963
6963
  if (bracketCount < 0) {
6964
- throw new Error(`Invalid redaction path (${path77})`);
6964
+ throw new Error(`Invalid redaction path (${path78})`);
6965
6965
  }
6966
6966
  }
6967
6967
  }
6968
6968
  if (bracketCount !== 0) {
6969
- throw new Error(`Invalid redaction path (${path77})`);
6969
+ throw new Error(`Invalid redaction path (${path78})`);
6970
6970
  }
6971
6971
  }
6972
6972
  function validatePaths(paths) {
6973
6973
  if (!Array.isArray(paths)) {
6974
6974
  throw new TypeError("paths must be an array");
6975
6975
  }
6976
- for (const path77 of paths) {
6977
- validatePath(path77);
6976
+ for (const path78 of paths) {
6977
+ validatePath(path78);
6978
6978
  }
6979
6979
  }
6980
6980
  function slowRedact(options = {}) {
@@ -7142,8 +7142,8 @@ var require_redaction = __commonJS({
7142
7142
  if (shape[k2] === null) {
7143
7143
  o[k2] = (value) => topCensor(value, [k2]);
7144
7144
  } else {
7145
- const wrappedCensor = typeof censor === "function" ? (value, path77) => {
7146
- return censor(value, [k2, ...path77]);
7145
+ const wrappedCensor = typeof censor === "function" ? (value, path78) => {
7146
+ return censor(value, [k2, ...path78]);
7147
7147
  } : censor;
7148
7148
  o[k2] = Redact({
7149
7149
  paths: shape[k2],
@@ -7361,10 +7361,10 @@ var require_atomic_sleep = __commonJS({
7361
7361
  var require_sonic_boom = __commonJS({
7362
7362
  "../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
7363
7363
  "use strict";
7364
- var fs70 = require("fs");
7364
+ var fs71 = require("fs");
7365
7365
  var EventEmitter3 = require("events");
7366
7366
  var inherits = require("util").inherits;
7367
- var path77 = require("path");
7367
+ var path78 = require("path");
7368
7368
  var sleep2 = require_atomic_sleep();
7369
7369
  var assert = require("assert");
7370
7370
  var BUSY_WRITE_TIMEOUT = 100;
@@ -7418,20 +7418,20 @@ var require_sonic_boom = __commonJS({
7418
7418
  const mode = sonic.mode;
7419
7419
  if (sonic.sync) {
7420
7420
  try {
7421
- if (sonic.mkdir) fs70.mkdirSync(path77.dirname(file), { recursive: true });
7422
- const fd = fs70.openSync(file, flags, mode);
7421
+ if (sonic.mkdir) fs71.mkdirSync(path78.dirname(file), { recursive: true });
7422
+ const fd = fs71.openSync(file, flags, mode);
7423
7423
  fileOpened(null, fd);
7424
7424
  } catch (err) {
7425
7425
  fileOpened(err);
7426
7426
  throw err;
7427
7427
  }
7428
7428
  } else if (sonic.mkdir) {
7429
- fs70.mkdir(path77.dirname(file), { recursive: true }, (err) => {
7429
+ fs71.mkdir(path78.dirname(file), { recursive: true }, (err) => {
7430
7430
  if (err) return fileOpened(err);
7431
- fs70.open(file, flags, mode, fileOpened);
7431
+ fs71.open(file, flags, mode, fileOpened);
7432
7432
  });
7433
7433
  } else {
7434
- fs70.open(file, flags, mode, fileOpened);
7434
+ fs71.open(file, flags, mode, fileOpened);
7435
7435
  }
7436
7436
  }
7437
7437
  function SonicBoom(opts) {
@@ -7472,8 +7472,8 @@ var require_sonic_boom = __commonJS({
7472
7472
  this.flush = flushBuffer;
7473
7473
  this.flushSync = flushBufferSync;
7474
7474
  this._actualWrite = actualWriteBuffer;
7475
- fsWriteSync = () => fs70.writeSync(this.fd, this._writingBuf);
7476
- fsWrite = () => fs70.write(this.fd, this._writingBuf, this.release);
7475
+ fsWriteSync = () => fs71.writeSync(this.fd, this._writingBuf);
7476
+ fsWrite = () => fs71.write(this.fd, this._writingBuf, this.release);
7477
7477
  } else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
7478
7478
  this._writingBuf = "";
7479
7479
  this.write = write;
@@ -7482,15 +7482,15 @@ var require_sonic_boom = __commonJS({
7482
7482
  this._actualWrite = actualWrite;
7483
7483
  fsWriteSync = () => {
7484
7484
  if (Buffer.isBuffer(this._writingBuf)) {
7485
- return fs70.writeSync(this.fd, this._writingBuf);
7485
+ return fs71.writeSync(this.fd, this._writingBuf);
7486
7486
  }
7487
- return fs70.writeSync(this.fd, this._writingBuf, "utf8");
7487
+ return fs71.writeSync(this.fd, this._writingBuf, "utf8");
7488
7488
  };
7489
7489
  fsWrite = () => {
7490
7490
  if (Buffer.isBuffer(this._writingBuf)) {
7491
- return fs70.write(this.fd, this._writingBuf, this.release);
7491
+ return fs71.write(this.fd, this._writingBuf, this.release);
7492
7492
  }
7493
- return fs70.write(this.fd, this._writingBuf, "utf8", this.release);
7493
+ return fs71.write(this.fd, this._writingBuf, "utf8", this.release);
7494
7494
  };
7495
7495
  } else {
7496
7496
  throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
@@ -7547,7 +7547,7 @@ var require_sonic_boom = __commonJS({
7547
7547
  }
7548
7548
  }
7549
7549
  if (this._fsync) {
7550
- fs70.fsyncSync(this.fd);
7550
+ fs71.fsyncSync(this.fd);
7551
7551
  }
7552
7552
  const len = this._len;
7553
7553
  if (this._reopening) {
@@ -7661,7 +7661,7 @@ var require_sonic_boom = __commonJS({
7661
7661
  const onDrain = () => {
7662
7662
  if (!this._fsync) {
7663
7663
  try {
7664
- fs70.fsync(this.fd, (err) => {
7664
+ fs71.fsync(this.fd, (err) => {
7665
7665
  this._flushPending = false;
7666
7666
  cb(err);
7667
7667
  });
@@ -7763,7 +7763,7 @@ var require_sonic_boom = __commonJS({
7763
7763
  const fd = this.fd;
7764
7764
  this.once("ready", () => {
7765
7765
  if (fd !== this.fd) {
7766
- fs70.close(fd, (err) => {
7766
+ fs71.close(fd, (err) => {
7767
7767
  if (err) {
7768
7768
  return this.emit("error", err);
7769
7769
  }
@@ -7812,7 +7812,7 @@ var require_sonic_boom = __commonJS({
7812
7812
  buf = this._bufs[0];
7813
7813
  }
7814
7814
  try {
7815
- const n = Buffer.isBuffer(buf) ? fs70.writeSync(this.fd, buf) : fs70.writeSync(this.fd, buf, "utf8");
7815
+ const n = Buffer.isBuffer(buf) ? fs71.writeSync(this.fd, buf) : fs71.writeSync(this.fd, buf, "utf8");
7816
7816
  const releasedBufObj = releaseWritingBuf(buf, this._len, n);
7817
7817
  buf = releasedBufObj.writingBuf;
7818
7818
  this._len = releasedBufObj.len;
@@ -7828,7 +7828,7 @@ var require_sonic_boom = __commonJS({
7828
7828
  }
7829
7829
  }
7830
7830
  try {
7831
- fs70.fsyncSync(this.fd);
7831
+ fs71.fsyncSync(this.fd);
7832
7832
  } catch {
7833
7833
  }
7834
7834
  }
@@ -7849,7 +7849,7 @@ var require_sonic_boom = __commonJS({
7849
7849
  buf = mergeBuf(this._bufs[0], this._lens[0]);
7850
7850
  }
7851
7851
  try {
7852
- const n = fs70.writeSync(this.fd, buf);
7852
+ const n = fs71.writeSync(this.fd, buf);
7853
7853
  buf = buf.subarray(n);
7854
7854
  this._len = Math.max(this._len - n, 0);
7855
7855
  if (buf.length <= 0) {
@@ -7877,13 +7877,13 @@ var require_sonic_boom = __commonJS({
7877
7877
  this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
7878
7878
  if (this.sync) {
7879
7879
  try {
7880
- const written = Buffer.isBuffer(this._writingBuf) ? fs70.writeSync(this.fd, this._writingBuf) : fs70.writeSync(this.fd, this._writingBuf, "utf8");
7880
+ const written = Buffer.isBuffer(this._writingBuf) ? fs71.writeSync(this.fd, this._writingBuf) : fs71.writeSync(this.fd, this._writingBuf, "utf8");
7881
7881
  release(null, written);
7882
7882
  } catch (err) {
7883
7883
  release(err);
7884
7884
  }
7885
7885
  } else {
7886
- fs70.write(this.fd, this._writingBuf, release);
7886
+ fs71.write(this.fd, this._writingBuf, release);
7887
7887
  }
7888
7888
  }
7889
7889
  function actualWriteBuffer() {
@@ -7892,7 +7892,7 @@ var require_sonic_boom = __commonJS({
7892
7892
  this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
7893
7893
  if (this.sync) {
7894
7894
  try {
7895
- const written = fs70.writeSync(this.fd, this._writingBuf);
7895
+ const written = fs71.writeSync(this.fd, this._writingBuf);
7896
7896
  release(null, written);
7897
7897
  } catch (err) {
7898
7898
  release(err);
@@ -7901,7 +7901,7 @@ var require_sonic_boom = __commonJS({
7901
7901
  if (kCopyBuffer) {
7902
7902
  this._writingBuf = Buffer.from(this._writingBuf);
7903
7903
  }
7904
- fs70.write(this.fd, this._writingBuf, release);
7904
+ fs71.write(this.fd, this._writingBuf, release);
7905
7905
  }
7906
7906
  }
7907
7907
  function actualClose(sonic) {
@@ -7917,12 +7917,12 @@ var require_sonic_boom = __commonJS({
7917
7917
  sonic._lens = [];
7918
7918
  assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
7919
7919
  try {
7920
- fs70.fsync(sonic.fd, closeWrapped);
7920
+ fs71.fsync(sonic.fd, closeWrapped);
7921
7921
  } catch {
7922
7922
  }
7923
7923
  function closeWrapped() {
7924
7924
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7925
- fs70.close(sonic.fd, done);
7925
+ fs71.close(sonic.fd, done);
7926
7926
  } else {
7927
7927
  done();
7928
7928
  }
@@ -11057,11 +11057,11 @@ var init_lib = __esm({
11057
11057
  }
11058
11058
  }
11059
11059
  },
11060
- addToPath: function addToPath(path77, added, removed, oldPosInc, options) {
11061
- var last = path77.lastComponent;
11060
+ addToPath: function addToPath(path78, added, removed, oldPosInc, options) {
11061
+ var last = path78.lastComponent;
11062
11062
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
11063
11063
  return {
11064
- oldPos: path77.oldPos + oldPosInc,
11064
+ oldPos: path78.oldPos + oldPosInc,
11065
11065
  lastComponent: {
11066
11066
  count: last.count + 1,
11067
11067
  added,
@@ -11071,7 +11071,7 @@ var init_lib = __esm({
11071
11071
  };
11072
11072
  } else {
11073
11073
  return {
11074
- oldPos: path77.oldPos + oldPosInc,
11074
+ oldPos: path78.oldPos + oldPosInc,
11075
11075
  lastComponent: {
11076
11076
  count: 1,
11077
11077
  added,
@@ -11312,10 +11312,10 @@ function cwdToHashDir(cwd) {
11312
11312
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
11313
11313
  }
11314
11314
  function newestSubagentMtimeMs(projectsRoot, cwd, toolSessionId) {
11315
- const dir = import_node_path4.default.join(projectsRoot, cwdToHashDir(cwd), toolSessionId, "subagents");
11315
+ const dir = import_node_path5.default.join(projectsRoot, cwdToHashDir(cwd), toolSessionId, "subagents");
11316
11316
  let entries;
11317
11317
  try {
11318
- entries = import_node_fs4.default.readdirSync(dir, { withFileTypes: true });
11318
+ entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
11319
11319
  } catch {
11320
11320
  return null;
11321
11321
  }
@@ -11324,7 +11324,7 @@ function newestSubagentMtimeMs(projectsRoot, cwd, toolSessionId) {
11324
11324
  if (!e.isFile()) continue;
11325
11325
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11326
11326
  try {
11327
- const m2 = import_node_fs4.default.statSync(import_node_path4.default.join(dir, e.name)).mtimeMs;
11327
+ const m2 = import_node_fs5.default.statSync(import_node_path5.default.join(dir, e.name)).mtimeMs;
11328
11328
  if (newest === null || m2 > newest) newest = m2;
11329
11329
  } catch {
11330
11330
  }
@@ -11337,7 +11337,7 @@ function hashDirToCwd(hash) {
11337
11337
  }
11338
11338
  function safeStatMtime(p2) {
11339
11339
  try {
11340
- return import_node_fs4.default.statSync(p2).mtimeMs;
11340
+ return import_node_fs5.default.statSync(p2).mtimeMs;
11341
11341
  } catch {
11342
11342
  return 0;
11343
11343
  }
@@ -11345,7 +11345,7 @@ function safeStatMtime(p2) {
11345
11345
  function readJsonlLines(file) {
11346
11346
  let raw;
11347
11347
  try {
11348
- raw = import_node_fs4.default.readFileSync(file, "utf8");
11348
+ raw = import_node_fs5.default.readFileSync(file, "utf8");
11349
11349
  } catch (err) {
11350
11350
  if (err.code === "ENOENT") return [];
11351
11351
  throw err;
@@ -11537,10 +11537,10 @@ function attachmentToHistoryMessage(o, ts) {
11537
11537
  const memories = raw.map((m2) => {
11538
11538
  if (!m2 || typeof m2 !== "object") return null;
11539
11539
  const rec3 = m2;
11540
- const path77 = typeof rec3.path === "string" ? rec3.path : null;
11540
+ const path78 = typeof rec3.path === "string" ? rec3.path : null;
11541
11541
  const content = typeof rec3.content === "string" ? rec3.content : null;
11542
- if (!path77 || content == null) return null;
11543
- const entry = { path: path77, content };
11542
+ if (!path78 || content == null) return null;
11543
+ const entry = { path: path78, content };
11544
11544
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11545
11545
  return entry;
11546
11546
  }).filter((m2) => m2 !== null);
@@ -11576,8 +11576,8 @@ function attachmentDeferredToolsText(a) {
11576
11576
  function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11577
11577
  if (backupFileName === null) return null;
11578
11578
  try {
11579
- return import_node_fs4.default.readFileSync(
11580
- import_node_path4.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11579
+ return import_node_fs5.default.readFileSync(
11580
+ import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
11581
11581
  "utf8"
11582
11582
  );
11583
11583
  } catch {
@@ -11586,19 +11586,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
11586
11586
  }
11587
11587
  function readCurrentContent(filePath) {
11588
11588
  try {
11589
- return import_node_fs4.default.readFileSync(filePath, "utf8");
11589
+ return import_node_fs5.default.readFileSync(filePath, "utf8");
11590
11590
  } catch (err) {
11591
11591
  if (err.code === "ENOENT") return null;
11592
11592
  return null;
11593
11593
  }
11594
11594
  }
11595
- var import_node_fs4, import_node_os3, import_node_path4, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11595
+ var import_node_fs5, import_node_os3, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
11596
11596
  var init_claude_history = __esm({
11597
11597
  "src/tools/claude-history.ts"() {
11598
11598
  "use strict";
11599
- import_node_fs4 = __toESM(require("fs"), 1);
11599
+ import_node_fs5 = __toESM(require("fs"), 1);
11600
11600
  import_node_os3 = __toESM(require("os"), 1);
11601
- import_node_path4 = __toESM(require("path"), 1);
11601
+ import_node_path5 = __toESM(require("path"), 1);
11602
11602
  init_lib();
11603
11603
  init_tool_result_extra();
11604
11604
  TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
@@ -11622,14 +11622,14 @@ var init_claude_history = __esm({
11622
11622
  // 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
11623
11623
  fileHistoryRoot;
11624
11624
  constructor(opts = {}) {
11625
- const base = opts.baseDir ?? import_node_path4.default.join(import_node_os3.default.homedir(), ".claude");
11626
- this.projectsRoot = import_node_path4.default.join(base, "projects");
11627
- this.fileHistoryRoot = import_node_path4.default.join(base, "file-history");
11625
+ const base = opts.baseDir ?? import_node_path5.default.join(import_node_os3.default.homedir(), ".claude");
11626
+ this.projectsRoot = import_node_path5.default.join(base, "projects");
11627
+ this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
11628
11628
  }
11629
11629
  async listProjects() {
11630
11630
  let entries;
11631
11631
  try {
11632
- entries = import_node_fs4.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11632
+ entries = import_node_fs5.default.readdirSync(this.projectsRoot, { withFileTypes: true });
11633
11633
  } catch (err) {
11634
11634
  if (err.code === "ENOENT") return [];
11635
11635
  throw err;
@@ -11637,9 +11637,9 @@ var init_claude_history = __esm({
11637
11637
  const out = [];
11638
11638
  for (const ent of entries) {
11639
11639
  if (!ent.isDirectory()) continue;
11640
- const dir = import_node_path4.default.join(this.projectsRoot, ent.name);
11641
- const files = import_node_fs4.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11642
- const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path4.default.join(dir, f))), 0);
11640
+ const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
11641
+ const files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11642
+ const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
11643
11643
  out.push({
11644
11644
  projectPath: hashDirToCwd(ent.name),
11645
11645
  hashDir: ent.name,
@@ -11651,17 +11651,17 @@ var init_claude_history = __esm({
11651
11651
  return out;
11652
11652
  }
11653
11653
  async listSessions(args) {
11654
- const dir = import_node_path4.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11654
+ const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
11655
11655
  let files;
11656
11656
  try {
11657
- files = import_node_fs4.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11657
+ files = import_node_fs5.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
11658
11658
  } catch (err) {
11659
11659
  if (err.code === "ENOENT") return [];
11660
11660
  throw err;
11661
11661
  }
11662
11662
  const out = [];
11663
11663
  for (const f of files) {
11664
- const full = import_node_path4.default.join(dir, f);
11664
+ const full = import_node_path5.default.join(dir, f);
11665
11665
  const toolSessionId = f.slice(0, -".jsonl".length);
11666
11666
  const lines = readJsonlLines(full);
11667
11667
  let summary = "";
@@ -11716,7 +11716,7 @@ var init_claude_history = __esm({
11716
11716
  return out;
11717
11717
  }
11718
11718
  async read(args) {
11719
- const file = import_node_path4.default.join(
11719
+ const file = import_node_path5.default.join(
11720
11720
  this.projectsRoot,
11721
11721
  cwdToHashDir(args.cwd),
11722
11722
  `${args.toolSessionId}.jsonl`
@@ -11753,7 +11753,7 @@ var init_claude_history = __esm({
11753
11753
  // 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
11754
11754
  // 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
11755
11755
  listSubagentsFromDirectory(cwd, toolSessionId) {
11756
- const dir = import_node_path4.default.join(
11756
+ const dir = import_node_path5.default.join(
11757
11757
  this.projectsRoot,
11758
11758
  cwdToHashDir(cwd),
11759
11759
  toolSessionId,
@@ -11761,7 +11761,7 @@ var init_claude_history = __esm({
11761
11761
  );
11762
11762
  let entries;
11763
11763
  try {
11764
- entries = import_node_fs4.default.readdirSync(dir, { withFileTypes: true });
11764
+ entries = import_node_fs5.default.readdirSync(dir, { withFileTypes: true });
11765
11765
  } catch (err) {
11766
11766
  if (err.code === "ENOENT") return null;
11767
11767
  return null;
@@ -11771,7 +11771,7 @@ var init_claude_history = __esm({
11771
11771
  if (!e.isFile()) continue;
11772
11772
  if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
11773
11773
  const subagentId = e.name.slice("agent-".length, -".jsonl".length);
11774
- const filePath = import_node_path4.default.join(dir, e.name);
11774
+ const filePath = import_node_path5.default.join(dir, e.name);
11775
11775
  const lines = readJsonlLines(filePath);
11776
11776
  let firstText = "";
11777
11777
  let messageCount = 0;
@@ -11788,7 +11788,7 @@ var init_claude_history = __esm({
11788
11788
  return out;
11789
11789
  }
11790
11790
  listSubagentsFromMainJsonl(cwd, toolSessionId) {
11791
- const file = import_node_path4.default.join(
11791
+ const file = import_node_path5.default.join(
11792
11792
  this.projectsRoot,
11793
11793
  cwdToHashDir(cwd),
11794
11794
  `${toolSessionId}.jsonl`
@@ -11823,7 +11823,7 @@ var init_claude_history = __esm({
11823
11823
  }
11824
11824
  // 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
11825
11825
  readSubagentFromFile(cwd, toolSessionId, subagentId) {
11826
- const file = import_node_path4.default.join(
11826
+ const file = import_node_path5.default.join(
11827
11827
  this.projectsRoot,
11828
11828
  cwdToHashDir(cwd),
11829
11829
  toolSessionId,
@@ -11832,7 +11832,7 @@ var init_claude_history = __esm({
11832
11832
  );
11833
11833
  let exists = false;
11834
11834
  try {
11835
- exists = import_node_fs4.default.statSync(file).isFile();
11835
+ exists = import_node_fs5.default.statSync(file).isFile();
11836
11836
  } catch {
11837
11837
  return null;
11838
11838
  }
@@ -11851,7 +11851,7 @@ var init_claude_history = __esm({
11851
11851
  * "那一刻每个 tracked 文件对应的 backup 文件名"
11852
11852
  */
11853
11853
  readFileHistorySnapshots(args) {
11854
- const file = import_node_path4.default.join(
11854
+ const file = import_node_path5.default.join(
11855
11855
  this.projectsRoot,
11856
11856
  cwdToHashDir(args.cwd),
11857
11857
  `${args.toolSessionId}.jsonl`
@@ -11896,7 +11896,7 @@ var init_claude_history = __esm({
11896
11896
  for (const [anchorId, target] of snapshots) {
11897
11897
  let hasAny = false;
11898
11898
  for (const [rawPath, backup] of Object.entries(target)) {
11899
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
11899
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
11900
11900
  const backupContent = readBackupContent(
11901
11901
  this.fileHistoryRoot,
11902
11902
  args.toolSessionId,
@@ -11936,7 +11936,7 @@ var init_claude_history = __esm({
11936
11936
  let totalInsertions = 0;
11937
11937
  let totalDeletions = 0;
11938
11938
  for (const [rawPath, backup] of Object.entries(target)) {
11939
- const absPath = import_node_path4.default.isAbsolute(rawPath) ? rawPath : import_node_path4.default.join(args.cwd, rawPath);
11939
+ const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
11940
11940
  const backupContent = readBackupContent(
11941
11941
  this.fileHistoryRoot,
11942
11942
  args.toolSessionId,
@@ -11983,7 +11983,7 @@ var init_claude_history = __esm({
11983
11983
  };
11984
11984
  }
11985
11985
  readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
11986
- const file = import_node_path4.default.join(
11986
+ const file = import_node_path5.default.join(
11987
11987
  this.projectsRoot,
11988
11988
  cwdToHashDir(cwd),
11989
11989
  `${toolSessionId}.jsonl`
@@ -12016,13 +12016,13 @@ var init_src = __esm({
12016
12016
  function probeViaWhich() {
12017
12017
  try {
12018
12018
  const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
12019
- if (out && import_node_fs14.default.existsSync(out)) return out;
12019
+ if (out && import_node_fs15.default.existsSync(out)) return out;
12020
12020
  } catch {
12021
12021
  }
12022
12022
  return null;
12023
12023
  }
12024
12024
  async function probeClaude(env = process.env) {
12025
- if (env.CLAUDE_BIN && import_node_fs14.default.existsSync(env.CLAUDE_BIN)) {
12025
+ if (env.CLAUDE_BIN && import_node_fs15.default.existsSync(env.CLAUDE_BIN)) {
12026
12026
  return { available: true, path: env.CLAUDE_BIN };
12027
12027
  }
12028
12028
  const w2 = probeViaWhich();
@@ -12360,10 +12360,10 @@ function parseAttachment(obj) {
12360
12360
  const memories = raw.map((m2) => {
12361
12361
  if (!m2 || typeof m2 !== "object") return null;
12362
12362
  const rec3 = m2;
12363
- const path77 = typeof rec3.path === "string" ? rec3.path : null;
12363
+ const path78 = typeof rec3.path === "string" ? rec3.path : null;
12364
12364
  const content = typeof rec3.content === "string" ? rec3.content : null;
12365
- if (!path77 || content == null) return null;
12366
- const out = { path: path77, content };
12365
+ if (!path78 || content == null) return null;
12366
+ const out = { path: path78, content };
12367
12367
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12368
12368
  return out;
12369
12369
  }).filter((m2) => m2 !== null);
@@ -12467,13 +12467,13 @@ function encodeClaudeStdin(text) {
12467
12467
  };
12468
12468
  return JSON.stringify(frame) + "\n";
12469
12469
  }
12470
- var import_node_child_process, import_node_child_process2, import_node_fs14, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12470
+ var import_node_child_process, import_node_child_process2, import_node_fs15, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
12471
12471
  var init_claude = __esm({
12472
12472
  "src/tools/claude.ts"() {
12473
12473
  "use strict";
12474
12474
  import_node_child_process = require("child_process");
12475
12475
  import_node_child_process2 = require("child_process");
12476
- import_node_fs14 = __toESM(require("fs"), 1);
12476
+ import_node_fs15 = __toESM(require("fs"), 1);
12477
12477
  init_protocol();
12478
12478
  init_claude_history();
12479
12479
  init_tool_result_extra();
@@ -33460,8 +33460,8 @@ var require_utils = __commonJS({
33460
33460
  var result = transform[inputType][outputType](input);
33461
33461
  return result;
33462
33462
  };
33463
- exports2.resolve = function(path77) {
33464
- var parts = path77.split("/");
33463
+ exports2.resolve = function(path78) {
33464
+ var parts = path78.split("/");
33465
33465
  var result = [];
33466
33466
  for (var index = 0; index < parts.length; index++) {
33467
33467
  var part = parts[index];
@@ -39314,18 +39314,18 @@ var require_object = __commonJS({
39314
39314
  var object = new ZipObject(name, zipObjectContent, o);
39315
39315
  this.files[name] = object;
39316
39316
  };
39317
- var parentFolder = function(path77) {
39318
- if (path77.slice(-1) === "/") {
39319
- path77 = path77.substring(0, path77.length - 1);
39317
+ var parentFolder = function(path78) {
39318
+ if (path78.slice(-1) === "/") {
39319
+ path78 = path78.substring(0, path78.length - 1);
39320
39320
  }
39321
- var lastSlash = path77.lastIndexOf("/");
39322
- return lastSlash > 0 ? path77.substring(0, lastSlash) : "";
39321
+ var lastSlash = path78.lastIndexOf("/");
39322
+ return lastSlash > 0 ? path78.substring(0, lastSlash) : "";
39323
39323
  };
39324
- var forceTrailingSlash = function(path77) {
39325
- if (path77.slice(-1) !== "/") {
39326
- path77 += "/";
39324
+ var forceTrailingSlash = function(path78) {
39325
+ if (path78.slice(-1) !== "/") {
39326
+ path78 += "/";
39327
39327
  }
39328
- return path77;
39328
+ return path78;
39329
39329
  };
39330
39330
  var folderAdd = function(name, createFolders) {
39331
39331
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -40326,7 +40326,7 @@ var require_lib3 = __commonJS({
40326
40326
 
40327
40327
  // src/sshd/contact-ssh-log.ts
40328
40328
  function createContactSshLog(dataDir) {
40329
- const file = import_node_path40.default.join(dataDir, "contact-ssh.log");
40329
+ const file = import_node_path41.default.join(dataDir, "contact-ssh.log");
40330
40330
  function append(level, tag, message, meta) {
40331
40331
  const time = (/* @__PURE__ */ new Date()).toISOString();
40332
40332
  let line = `[${time}] [${level}] [${tag}] ${message}`;
@@ -40339,8 +40339,8 @@ function createContactSshLog(dataDir) {
40339
40339
  }
40340
40340
  line += "\n";
40341
40341
  try {
40342
- import_node_fs39.default.mkdirSync(import_node_path40.default.dirname(file), { recursive: true });
40343
- import_node_fs39.default.appendFileSync(file, line, { mode: 384 });
40342
+ import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
40343
+ import_node_fs40.default.appendFileSync(file, line, { mode: 384 });
40344
40344
  } catch {
40345
40345
  }
40346
40346
  }
@@ -40350,12 +40350,12 @@ function createContactSshLog(dataDir) {
40350
40350
  error: (tag, message, meta) => append("ERROR", tag, message, meta)
40351
40351
  };
40352
40352
  }
40353
- var import_node_fs39, import_node_path40, nullContactSshLog;
40353
+ var import_node_fs40, import_node_path41, nullContactSshLog;
40354
40354
  var init_contact_ssh_log = __esm({
40355
40355
  "src/sshd/contact-ssh-log.ts"() {
40356
40356
  "use strict";
40357
- import_node_fs39 = __toESM(require("fs"), 1);
40358
- import_node_path40 = __toESM(require("path"), 1);
40357
+ import_node_fs40 = __toESM(require("fs"), 1);
40358
+ import_node_path41 = __toESM(require("path"), 1);
40359
40359
  nullContactSshLog = {
40360
40360
  info: () => {
40361
40361
  },
@@ -40370,7 +40370,7 @@ var init_contact_ssh_log = __esm({
40370
40370
  // src/run-case/recorder.ts
40371
40371
  function startRunCaseRecorder(opts) {
40372
40372
  const now = opts.now ?? Date.now;
40373
- const dir = import_node_path64.default.dirname(opts.recordPath);
40373
+ const dir = import_node_path65.default.dirname(opts.recordPath);
40374
40374
  let stream = null;
40375
40375
  let closing = false;
40376
40376
  let closedSettled = false;
@@ -40384,8 +40384,8 @@ function startRunCaseRecorder(opts) {
40384
40384
  });
40385
40385
  const ensureStream = () => {
40386
40386
  if (stream) return stream;
40387
- import_node_fs51.default.mkdirSync(dir, { recursive: true });
40388
- stream = import_node_fs51.default.createWriteStream(opts.recordPath, { flags: "a" });
40387
+ import_node_fs52.default.mkdirSync(dir, { recursive: true });
40388
+ stream = import_node_fs52.default.createWriteStream(opts.recordPath, { flags: "a" });
40389
40389
  stream.on("close", () => closedResolve());
40390
40390
  return stream;
40391
40391
  };
@@ -40410,12 +40410,12 @@ function startRunCaseRecorder(opts) {
40410
40410
  };
40411
40411
  return { tap, close, closed };
40412
40412
  }
40413
- var import_node_fs51, import_node_path64;
40413
+ var import_node_fs52, import_node_path65;
40414
40414
  var init_recorder = __esm({
40415
40415
  "src/run-case/recorder.ts"() {
40416
40416
  "use strict";
40417
- import_node_fs51 = __toESM(require("fs"), 1);
40418
- import_node_path64 = __toESM(require("path"), 1);
40417
+ import_node_fs52 = __toESM(require("fs"), 1);
40418
+ import_node_path65 = __toESM(require("path"), 1);
40419
40419
  }
40420
40420
  });
40421
40421
 
@@ -40458,7 +40458,7 @@ var init_wire = __esm({
40458
40458
  // src/run-case/controller.ts
40459
40459
  async function runController(opts) {
40460
40460
  const now = opts.now ?? Date.now;
40461
- const cwd = opts.cwd ?? (0, import_node_fs52.mkdtempSync)(import_node_path65.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40461
+ const cwd = opts.cwd ?? (0, import_node_fs53.mkdtempSync)(import_node_path66.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40462
40462
  const ownsCwd = opts.cwd === void 0;
40463
40463
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
40464
40464
  const spawnCtx = { cwd };
@@ -40619,19 +40619,19 @@ async function runController(opts) {
40619
40619
  if (sigintHandler) process.off("SIGINT", sigintHandler);
40620
40620
  if (ownsCwd) {
40621
40621
  try {
40622
- (0, import_node_fs52.rmSync)(cwd, { recursive: true, force: true });
40622
+ (0, import_node_fs53.rmSync)(cwd, { recursive: true, force: true });
40623
40623
  } catch {
40624
40624
  }
40625
40625
  }
40626
40626
  return exitCode ?? 0;
40627
40627
  }
40628
- var import_node_fs52, import_node_os22, import_node_path65;
40628
+ var import_node_fs53, import_node_os22, import_node_path66;
40629
40629
  var init_controller = __esm({
40630
40630
  "src/run-case/controller.ts"() {
40631
40631
  "use strict";
40632
- import_node_fs52 = require("fs");
40632
+ import_node_fs53 = require("fs");
40633
40633
  import_node_os22 = __toESM(require("os"), 1);
40634
- import_node_path65 = __toESM(require("path"), 1);
40634
+ import_node_path66 = __toESM(require("path"), 1);
40635
40635
  init_claude();
40636
40636
  init_stdout_splitter();
40637
40637
  init_permission_stdio();
@@ -40742,13 +40742,13 @@ async function sshRelay(argv) {
40742
40742
  process.stderr.write("clawd ssh-relay: missing <peer-device-id>\n" + SSH_RELAY_HELP);
40743
40743
  return 2;
40744
40744
  }
40745
- const dataDir = args.dataDir ?? import_node_path66.default.join(import_node_os23.default.homedir(), ".clawd");
40745
+ const dataDir = args.dataDir ?? import_node_path67.default.join(import_node_os23.default.homedir(), ".clawd");
40746
40746
  const sshLog = createContactSshLog(dataDir);
40747
40747
  const contact = findContact(dataDir, args.peerDeviceId);
40748
40748
  if (!contact) {
40749
40749
  sshLog.error("relay.contact-not-found", "ssh-relay \u627E\u4E0D\u5230 peer contact", {
40750
40750
  peerDeviceId: args.peerDeviceId,
40751
- contactsPath: import_node_path66.default.join(dataDir, "contacts.json")
40751
+ contactsPath: import_node_path67.default.join(dataDir, "contacts.json")
40752
40752
  });
40753
40753
  process.stderr.write(`clawd ssh-relay: contact ${args.peerDeviceId} not found in ${dataDir}/contacts.json
40754
40754
  `);
@@ -40869,10 +40869,10 @@ function parseSshRelayArgs(argv) {
40869
40869
  return out;
40870
40870
  }
40871
40871
  function findContact(dataDir, deviceId) {
40872
- const file = import_node_path66.default.join(dataDir, "contacts.json");
40872
+ const file = import_node_path67.default.join(dataDir, "contacts.json");
40873
40873
  let raw;
40874
40874
  try {
40875
- raw = import_node_fs53.default.readFileSync(file, "utf8");
40875
+ raw = import_node_fs54.default.readFileSync(file, "utf8");
40876
40876
  } catch {
40877
40877
  return null;
40878
40878
  }
@@ -40890,13 +40890,13 @@ function findContact(dataDir, deviceId) {
40890
40890
  }
40891
40891
  return null;
40892
40892
  }
40893
- var import_node_fs53, import_node_os23, import_node_path66, SSH_RELAY_HELP;
40893
+ var import_node_fs54, import_node_os23, import_node_path67, SSH_RELAY_HELP;
40894
40894
  var init_sshd_cli_relay = __esm({
40895
40895
  "src/sshd/sshd-cli-relay.ts"() {
40896
40896
  "use strict";
40897
- import_node_fs53 = __toESM(require("fs"), 1);
40897
+ import_node_fs54 = __toESM(require("fs"), 1);
40898
40898
  import_node_os23 = __toESM(require("os"), 1);
40899
- import_node_path66 = __toESM(require("path"), 1);
40899
+ import_node_path67 = __toESM(require("path"), 1);
40900
40900
  init_wrapper();
40901
40901
  init_src();
40902
40902
  init_peer_forward();
@@ -41100,8 +41100,8 @@ Env (advanced):
41100
41100
  `;
41101
41101
 
41102
41102
  // src/index.ts
41103
- var import_node_path63 = __toESM(require("path"), 1);
41104
- var import_node_fs50 = __toESM(require("fs"), 1);
41103
+ var import_node_path64 = __toESM(require("path"), 1);
41104
+ var import_node_fs51 = __toESM(require("fs"), 1);
41105
41105
  var import_node_os21 = __toESM(require("os"), 1);
41106
41106
 
41107
41107
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -41731,8 +41731,8 @@ var SessionStoreFactory = class {
41731
41731
  };
41732
41732
 
41733
41733
  // src/session/manager.ts
41734
- var import_node_fs7 = __toESM(require("fs"), 1);
41735
- var import_node_path8 = __toESM(require("path"), 1);
41734
+ var import_node_fs8 = __toESM(require("fs"), 1);
41735
+ var import_node_path9 = __toESM(require("path"), 1);
41736
41736
  var import_node_os5 = __toESM(require("os"), 1);
41737
41737
  init_protocol();
41738
41738
 
@@ -41825,6 +41825,60 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41825
41825
  return s;
41826
41826
  }
41827
41827
 
41828
+ // src/tools/owner-credentials.ts
41829
+ var import_node_fs4 = __toESM(require("fs"), 1);
41830
+ var import_node_path4 = __toESM(require("path"), 1);
41831
+ function readOwnerCredentials(homeDir, logger) {
41832
+ const settingsPath = import_node_path4.default.join(homeDir, ".claude", "settings.json");
41833
+ let raw;
41834
+ try {
41835
+ raw = import_node_fs4.default.readFileSync(settingsPath, "utf8");
41836
+ } catch (err) {
41837
+ const code = err.code;
41838
+ if (code === "ENOENT") return null;
41839
+ logger?.warn("owner ~/.claude/settings.json read failed", { code });
41840
+ return null;
41841
+ }
41842
+ let parsed;
41843
+ try {
41844
+ parsed = JSON.parse(raw);
41845
+ } catch {
41846
+ logger?.warn("owner ~/.claude/settings.json malformed JSON");
41847
+ return null;
41848
+ }
41849
+ if (!parsed || typeof parsed !== "object") return null;
41850
+ const obj = parsed;
41851
+ const bundle = {};
41852
+ const envRaw = obj.env;
41853
+ if (envRaw && typeof envRaw === "object" && !Array.isArray(envRaw)) {
41854
+ const filtered = {};
41855
+ for (const [k2, v2] of Object.entries(envRaw)) {
41856
+ if (k2.startsWith("ANTHROPIC_") && typeof v2 === "string") filtered[k2] = v2;
41857
+ }
41858
+ if (Object.keys(filtered).length > 0) bundle.env = filtered;
41859
+ }
41860
+ const helperRaw = obj.apiKeyHelper;
41861
+ if (typeof helperRaw === "string" && helperRaw.length > 0) {
41862
+ if (!import_node_path4.default.isAbsolute(helperRaw)) {
41863
+ logger?.warn(
41864
+ "owner apiKeyHelper is not absolute; cc will resolve against guest cwd (persona dir), likely EXEC not found",
41865
+ { basename: import_node_path4.default.basename(helperRaw) }
41866
+ );
41867
+ }
41868
+ bundle.apiKeyHelper = helperRaw;
41869
+ }
41870
+ if (!bundle.env && !bundle.apiKeyHelper) return null;
41871
+ return bundle;
41872
+ }
41873
+ function mergeOwnerCredentials(guestSandbox, bundle) {
41874
+ if (!bundle) return guestSandbox;
41875
+ return {
41876
+ ...guestSandbox,
41877
+ ...bundle.env ? { env: bundle.env } : {},
41878
+ ...bundle.apiKeyHelper ? { apiKeyHelper: bundle.apiKeyHelper } : {}
41879
+ };
41880
+ }
41881
+
41828
41882
  // src/shift/wrap.ts
41829
41883
  function wrapShiftFirePrompt(args) {
41830
41884
  return [
@@ -41843,7 +41897,7 @@ function escapeAttr(v2) {
41843
41897
 
41844
41898
  // src/session/runner.ts
41845
41899
  var import_node_os4 = __toESM(require("os"), 1);
41846
- var import_node_path6 = __toESM(require("path"), 1);
41900
+ var import_node_path7 = __toESM(require("path"), 1);
41847
41901
 
41848
41902
  // src/session/reducer.ts
41849
41903
  init_runtime();
@@ -42771,8 +42825,8 @@ init_permission_stdio();
42771
42825
  init_claude_history();
42772
42826
 
42773
42827
  // src/ipc-recorder.ts
42774
- var import_node_fs5 = __toESM(require("fs"), 1);
42775
- var import_node_path5 = __toESM(require("path"), 1);
42828
+ var import_node_fs6 = __toESM(require("fs"), 1);
42829
+ var import_node_path6 = __toESM(require("path"), 1);
42776
42830
  function tsForFilename(ms) {
42777
42831
  return new Date(ms).toISOString().replace(/[:.]/g, "-");
42778
42832
  }
@@ -42783,8 +42837,8 @@ function startRecorder(opts) {
42783
42837
  return null;
42784
42838
  }
42785
42839
  const now = opts.now ?? Date.now;
42786
- const dir = import_node_path5.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42787
- const filePath = import_node_path5.default.join(dir, `${tsForFilename(now())}.jsonl`);
42840
+ const dir = import_node_path6.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42841
+ const filePath = import_node_path6.default.join(dir, `${tsForFilename(now())}.jsonl`);
42788
42842
  let stream = null;
42789
42843
  let closedResolve;
42790
42844
  const closed = new Promise((resolve6) => {
@@ -42793,8 +42847,8 @@ function startRecorder(opts) {
42793
42847
  let exited = false;
42794
42848
  const ensureStream = () => {
42795
42849
  if (stream) return stream;
42796
- import_node_fs5.default.mkdirSync(dir, { recursive: true });
42797
- stream = import_node_fs5.default.createWriteStream(filePath, { flags: "a" });
42850
+ import_node_fs6.default.mkdirSync(dir, { recursive: true });
42851
+ stream = import_node_fs6.default.createWriteStream(filePath, { flags: "a" });
42798
42852
  stream.on("close", () => closedResolve());
42799
42853
  return stream;
42800
42854
  };
@@ -43174,7 +43228,7 @@ var SessionRunner = class {
43174
43228
  isSubagentActive() {
43175
43229
  const toolSessionId = this.state.file.toolSessionId;
43176
43230
  if (!toolSessionId) return false;
43177
- const projectsRoot = import_node_path6.default.join(this.hooks.home ?? import_node_os4.default.homedir(), ".claude", "projects");
43231
+ const projectsRoot = import_node_path7.default.join(this.hooks.home ?? import_node_os4.default.homedir(), ".claude", "projects");
43178
43232
  const mtime = newestSubagentMtimeMs(projectsRoot, this.state.file.cwd, toolSessionId);
43179
43233
  if (mtime === null) return false;
43180
43234
  const now = (this.hooks.now ?? Date.now)();
@@ -43262,15 +43316,15 @@ function extractEditPath(input) {
43262
43316
  }
43263
43317
 
43264
43318
  // src/debug/pty-probe.ts
43265
- var import_node_fs6 = __toESM(require("fs"), 1);
43266
- var import_node_path7 = __toESM(require("path"), 1);
43319
+ var import_node_fs7 = __toESM(require("fs"), 1);
43320
+ var import_node_path8 = __toESM(require("path"), 1);
43267
43321
  var PROBE_DIR = "/tmp/clawd-probe";
43268
- var EVENTS_FILE = import_node_path7.default.join(PROBE_DIR, "events.jsonl");
43322
+ var EVENTS_FILE = import_node_path8.default.join(PROBE_DIR, "events.jsonl");
43269
43323
  var inited = false;
43270
43324
  function ensureDir() {
43271
43325
  if (inited) return true;
43272
43326
  try {
43273
- import_node_fs6.default.mkdirSync(PROBE_DIR, { recursive: true });
43327
+ import_node_fs7.default.mkdirSync(PROBE_DIR, { recursive: true });
43274
43328
  inited = true;
43275
43329
  return true;
43276
43330
  } catch {
@@ -43281,15 +43335,15 @@ function probeEvent(event, data = {}) {
43281
43335
  try {
43282
43336
  if (!ensureDir()) return;
43283
43337
  const line = JSON.stringify({ ts: Date.now(), event, ...data }) + "\n";
43284
- import_node_fs6.default.appendFileSync(EVENTS_FILE, line);
43338
+ import_node_fs7.default.appendFileSync(EVENTS_FILE, line);
43285
43339
  } catch {
43286
43340
  }
43287
43341
  }
43288
43342
  function probeDumpReplay(sessionId, payload) {
43289
43343
  try {
43290
43344
  if (!ensureDir()) return "";
43291
- const file = import_node_path7.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
43292
- import_node_fs6.default.writeFileSync(file, payload, "utf8");
43345
+ const file = import_node_path8.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
43346
+ import_node_fs7.default.writeFileSync(file, payload, "utf8");
43293
43347
  return file;
43294
43348
  } catch {
43295
43349
  return "";
@@ -43398,7 +43452,7 @@ function derivePersonaSpawnCwd(file, personaRoot) {
43398
43452
  `derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${personaId})`
43399
43453
  );
43400
43454
  }
43401
- return import_node_path8.default.join(personaRoot, safeFileName(personaId));
43455
+ return import_node_path9.default.join(personaRoot, safeFileName(personaId));
43402
43456
  }
43403
43457
  function makeInitialState(file, subSessionMeta) {
43404
43458
  return {
@@ -43532,10 +43586,10 @@ var SessionManager = class {
43532
43586
  // <dataDir>/sessions/ 列子目录 (排除 'default').
43533
43587
  listPersonaIdsOnDisk() {
43534
43588
  if (!this.deps.dataDir) return [];
43535
- const root = this.deps.storeFactory ? import_node_path8.default.join(this.deps.dataDir, "personas") : import_node_path8.default.join(this.deps.dataDir, "sessions");
43589
+ const root = this.deps.storeFactory ? import_node_path9.default.join(this.deps.dataDir, "personas") : import_node_path9.default.join(this.deps.dataDir, "sessions");
43536
43590
  let entries;
43537
43591
  try {
43538
- entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
43592
+ entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43539
43593
  } catch (err) {
43540
43594
  const code = err?.code;
43541
43595
  if (code === "ENOENT") return [];
@@ -43548,7 +43602,7 @@ var SessionManager = class {
43548
43602
  // 只在 storeFactory 注入 (新布局) 下生效, 老布局无 guest 目录.
43549
43603
  listGuestCapIdsForPersona(personaId) {
43550
43604
  if (!this.deps.dataDir || !this.deps.storeFactory) return [];
43551
- const root = import_node_path8.default.join(
43605
+ const root = import_node_path9.default.join(
43552
43606
  this.deps.dataDir,
43553
43607
  "personas",
43554
43608
  personaId,
@@ -43558,7 +43612,7 @@ var SessionManager = class {
43558
43612
  );
43559
43613
  let entries;
43560
43614
  try {
43561
- entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
43615
+ entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43562
43616
  } catch (err) {
43563
43617
  const code = err?.code;
43564
43618
  if (code === "ENOENT") return [];
@@ -43677,7 +43731,7 @@ var SessionManager = class {
43677
43731
  callerDisplayName
43678
43732
  );
43679
43733
  if (subSessionMeta?.userWorkDir) {
43680
- import_node_fs7.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43734
+ import_node_fs8.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43681
43735
  }
43682
43736
  if (scope.kind === "persona" && scope.mode === "guest") {
43683
43737
  if (!this.deps.personaRoot || !subSessionMeta?.userWorkDir) {
@@ -43686,10 +43740,19 @@ var SessionManager = class {
43686
43740
  );
43687
43741
  }
43688
43742
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
43689
- const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43690
- subSessionMeta.extraSettings = JSON.stringify(settings);
43743
+ const sandboxSettings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43744
+ const ownerCreds = readOwnerCredentials(import_node_os5.default.homedir(), this.deps.logger);
43745
+ const merged = mergeOwnerCredentials(sandboxSettings, ownerCreds);
43746
+ if (ownerCreds) {
43747
+ this.deps.logger?.info("owner credentials injected into guest spawn", {
43748
+ sessionId: file.sessionId,
43749
+ envKeys: ownerCreds.env ? Object.keys(ownerCreds.env) : [],
43750
+ apiKeyHelper: ownerCreds.apiKeyHelper ? "present" : "absent"
43751
+ });
43752
+ }
43753
+ subSessionMeta.extraSettings = JSON.stringify(merged);
43691
43754
  const home = import_node_os5.default.homedir();
43692
- const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path8.default.join(home, p2.slice(2)) : p2;
43755
+ const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path9.default.join(home, p2.slice(2)) : p2;
43693
43756
  const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
43694
43757
  subSessionMeta.codexSandbox = {
43695
43758
  writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
@@ -43850,7 +43913,7 @@ var SessionManager = class {
43850
43913
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
43851
43914
  }
43852
43915
  try {
43853
- const stat = import_node_fs7.default.statSync(cwd);
43916
+ const stat = import_node_fs8.default.statSync(cwd);
43854
43917
  if (!stat.isDirectory()) throw new Error("not dir");
43855
43918
  } catch {
43856
43919
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
@@ -44384,7 +44447,7 @@ var SessionManager = class {
44384
44447
  */
44385
44448
  createForScope(args) {
44386
44449
  try {
44387
- const stat = import_node_fs7.default.statSync(args.cwd);
44450
+ const stat = import_node_fs8.default.statSync(args.cwd);
44388
44451
  if (!stat.isDirectory()) throw new Error("not dir");
44389
44452
  } catch {
44390
44453
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -44600,7 +44663,7 @@ var SessionManager = class {
44600
44663
  personaId: args.targetPersona,
44601
44664
  mode: "owner"
44602
44665
  };
44603
- const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44666
+ const cwd = import_node_path9.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44604
44667
  const now = (/* @__PURE__ */ new Date()).toISOString();
44605
44668
  const file = {
44606
44669
  sessionId,
@@ -44665,7 +44728,7 @@ var SessionManager = class {
44665
44728
  personaId: args.targetPersona,
44666
44729
  mode: "owner"
44667
44730
  };
44668
- const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44731
+ const cwd = import_node_path9.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44669
44732
  const now = (/* @__PURE__ */ new Date()).toISOString();
44670
44733
  const file = {
44671
44734
  sessionId,
@@ -45153,28 +45216,28 @@ var SessionManager = class {
45153
45216
  };
45154
45217
 
45155
45218
  // src/persona/store.ts
45156
- var fs8 = __toESM(require("fs"), 1);
45157
- var path11 = __toESM(require("path"), 1);
45219
+ var fs9 = __toESM(require("fs"), 1);
45220
+ var path12 = __toESM(require("path"), 1);
45158
45221
  init_protocol();
45159
45222
  var PersonaStore = class {
45160
45223
  constructor(root) {
45161
45224
  this.root = root;
45162
- fs8.mkdirSync(root, { recursive: true });
45225
+ fs9.mkdirSync(root, { recursive: true });
45163
45226
  }
45164
45227
  root;
45165
45228
  personaDir(personaId) {
45166
- return path11.join(this.root, safeFileName(personaId));
45229
+ return path12.join(this.root, safeFileName(personaId));
45167
45230
  }
45168
45231
  metaPath(personaId) {
45169
- return path11.join(this.personaDir(personaId), ".clawd", "persona.json");
45232
+ return path12.join(this.personaDir(personaId), ".clawd", "persona.json");
45170
45233
  }
45171
45234
  claudeMdPath(personaId) {
45172
- return path11.join(this.personaDir(personaId), "CLAUDE.md");
45235
+ return path12.join(this.personaDir(personaId), "CLAUDE.md");
45173
45236
  }
45174
45237
  // codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
45175
45238
  // 两份内容恒一致,persona 切 tool 零迁移。
45176
45239
  agentsMdPath(personaId) {
45177
- return path11.join(this.personaDir(personaId), "AGENTS.md");
45240
+ return path12.join(this.personaDir(personaId), "AGENTS.md");
45178
45241
  }
45179
45242
  /**
45180
45243
  * persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
@@ -45183,11 +45246,11 @@ var PersonaStore = class {
45183
45246
  * spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
45184
45247
  */
45185
45248
  sandboxSettingsPath(personaId) {
45186
- return path11.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
45249
+ return path12.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
45187
45250
  }
45188
45251
  write(persona, personality) {
45189
45252
  const dir = this.personaDir(persona.personaId);
45190
- fs8.mkdirSync(path11.join(dir, ".clawd"), { recursive: true });
45253
+ fs9.mkdirSync(path12.join(dir, ".clawd"), { recursive: true });
45191
45254
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
45192
45255
  this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
45193
45256
  this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
@@ -45206,9 +45269,9 @@ var PersonaStore = class {
45206
45269
  ensureAgentsMirror(personaId) {
45207
45270
  const claudeMd = this.claudeMdPath(personaId);
45208
45271
  const agentsMd = this.agentsMdPath(personaId);
45209
- if (!fs8.existsSync(claudeMd)) return false;
45210
- if (fs8.existsSync(agentsMd)) return false;
45211
- this.atomicWrite(agentsMd, fs8.readFileSync(claudeMd, "utf8"));
45272
+ if (!fs9.existsSync(claudeMd)) return false;
45273
+ if (fs9.existsSync(agentsMd)) return false;
45274
+ this.atomicWrite(agentsMd, fs9.readFileSync(claudeMd, "utf8"));
45212
45275
  return true;
45213
45276
  }
45214
45277
  /**
@@ -45232,22 +45295,22 @@ var PersonaStore = class {
45232
45295
  return { ...s, permissions: { ...s.permissions ?? {}, deny: [...prev, rule] } };
45233
45296
  }
45234
45297
  codexSandboxSettingsPath(personaId) {
45235
- return path11.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
45298
+ return path12.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
45236
45299
  }
45237
45300
  /** 读 codex-sandbox.json;不存在/损坏 → null。 */
45238
45301
  readCodexSandboxSettings(personaId) {
45239
45302
  const p2 = this.codexSandboxSettingsPath(personaId);
45240
- if (!fs8.existsSync(p2)) return null;
45303
+ if (!fs9.existsSync(p2)) return null;
45241
45304
  try {
45242
- return CodexSandboxSettingsSchema.parse(JSON.parse(fs8.readFileSync(p2, "utf8")));
45305
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs9.readFileSync(p2, "utf8")));
45243
45306
  } catch {
45244
45307
  return null;
45245
45308
  }
45246
45309
  }
45247
45310
  /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
45248
45311
  writeCodexSandboxSettings(personaId, settings) {
45249
- const dir = path11.join(this.personaDir(personaId), ".clawd");
45250
- fs8.mkdirSync(dir, { recursive: true });
45312
+ const dir = path12.join(this.personaDir(personaId), ".clawd");
45313
+ fs9.mkdirSync(dir, { recursive: true });
45251
45314
  this.atomicWrite(this.codexSandboxSettingsPath(personaId), JSON.stringify(settings, null, 2));
45252
45315
  }
45253
45316
  writeMeta(persona) {
@@ -45255,8 +45318,8 @@ var PersonaStore = class {
45255
45318
  }
45256
45319
  read(personaId) {
45257
45320
  const p2 = this.metaPath(personaId);
45258
- if (!fs8.existsSync(p2)) return null;
45259
- const raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
45321
+ if (!fs9.existsSync(p2)) return null;
45322
+ const raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45260
45323
  if (raw && typeof raw === "object" && "tokenMap" in raw) {
45261
45324
  delete raw.tokenMap;
45262
45325
  this.atomicWrite(p2, JSON.stringify(raw, null, 2));
@@ -45264,13 +45327,13 @@ var PersonaStore = class {
45264
45327
  return PersonaFileSchema.parse(raw);
45265
45328
  }
45266
45329
  has(personaId) {
45267
- return fs8.existsSync(this.metaPath(personaId));
45330
+ return fs9.existsSync(this.metaPath(personaId));
45268
45331
  }
45269
45332
  readPersonality(personaId) {
45270
45333
  const claudeMd = this.claudeMdPath(personaId);
45271
- if (fs8.existsSync(claudeMd)) return fs8.readFileSync(claudeMd, "utf8");
45334
+ if (fs9.existsSync(claudeMd)) return fs9.readFileSync(claudeMd, "utf8");
45272
45335
  const agentsMd = this.agentsMdPath(personaId);
45273
- if (fs8.existsSync(agentsMd)) return fs8.readFileSync(agentsMd, "utf8");
45336
+ if (fs9.existsSync(agentsMd)) return fs9.readFileSync(agentsMd, "utf8");
45274
45337
  return null;
45275
45338
  }
45276
45339
  /**
@@ -45279,23 +45342,23 @@ var PersonaStore = class {
45279
45342
  */
45280
45343
  readSandboxSettings(personaId) {
45281
45344
  const p2 = this.sandboxSettingsPath(personaId);
45282
- if (!fs8.existsSync(p2)) return null;
45345
+ if (!fs9.existsSync(p2)) return null;
45283
45346
  try {
45284
- return JSON.parse(fs8.readFileSync(p2, "utf8"));
45347
+ return JSON.parse(fs9.readFileSync(p2, "utf8"));
45285
45348
  } catch {
45286
45349
  return null;
45287
45350
  }
45288
45351
  }
45289
45352
  /** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
45290
45353
  skillsDir(personaId) {
45291
- return path11.join(this.personaDir(personaId), ".claude", "skills");
45354
+ return path12.join(this.personaDir(personaId), ".claude", "skills");
45292
45355
  }
45293
45356
  /**
45294
45357
  * Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
45295
45358
  * 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
45296
45359
  */
45297
45360
  claudeSettingsPath(personaId) {
45298
- return path11.join(this.personaDir(personaId), ".claude", "settings.json");
45361
+ return path12.join(this.personaDir(personaId), ".claude", "settings.json");
45299
45362
  }
45300
45363
  /**
45301
45364
  * 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
@@ -45310,10 +45373,10 @@ var PersonaStore = class {
45310
45373
  */
45311
45374
  readEnabledPlugins(personaId) {
45312
45375
  const p2 = this.claudeSettingsPath(personaId);
45313
- if (!fs8.existsSync(p2)) return [];
45376
+ if (!fs9.existsSync(p2)) return [];
45314
45377
  let raw;
45315
45378
  try {
45316
- raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
45379
+ raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45317
45380
  } catch {
45318
45381
  return [];
45319
45382
  }
@@ -45327,22 +45390,22 @@ var PersonaStore = class {
45327
45390
  return out;
45328
45391
  }
45329
45392
  list() {
45330
- if (!fs8.existsSync(this.root)) return [];
45331
- return fs8.readdirSync(this.root).filter((name) => {
45332
- return fs8.existsSync(path11.join(this.root, name, ".clawd", "persona.json"));
45393
+ if (!fs9.existsSync(this.root)) return [];
45394
+ return fs9.readdirSync(this.root).filter((name) => {
45395
+ return fs9.existsSync(path12.join(this.root, name, ".clawd", "persona.json"));
45333
45396
  });
45334
45397
  }
45335
45398
  remove(personaId) {
45336
45399
  const dir = this.personaDir(personaId);
45337
- if (fs8.existsSync(dir)) fs8.rmSync(dir, { recursive: true, force: true });
45400
+ if (fs9.existsSync(dir)) fs9.rmSync(dir, { recursive: true, force: true });
45338
45401
  }
45339
45402
  personaDirPath(personaId) {
45340
45403
  return this.personaDir(personaId);
45341
45404
  }
45342
45405
  atomicWrite(file, content) {
45343
45406
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
45344
- fs8.writeFileSync(tmp, content, { mode: 384 });
45345
- fs8.renameSync(tmp, file);
45407
+ fs9.writeFileSync(tmp, content, { mode: 384 });
45408
+ fs9.renameSync(tmp, file);
45346
45409
  }
45347
45410
  };
45348
45411
 
@@ -45388,9 +45451,9 @@ var PersonaRegistry = class {
45388
45451
  var import_node_crypto3 = __toESM(require("crypto"), 1);
45389
45452
 
45390
45453
  // src/skills/scanner.ts
45391
- var import_node_fs8 = __toESM(require("fs"), 1);
45454
+ var import_node_fs9 = __toESM(require("fs"), 1);
45392
45455
  var import_node_os6 = __toESM(require("os"), 1);
45393
- var import_node_path9 = __toESM(require("path"), 1);
45456
+ var import_node_path10 = __toESM(require("path"), 1);
45394
45457
 
45395
45458
  // src/skills/frontmatter.ts
45396
45459
  var STRIP_QUOTES = /^["']|["']$/g;
@@ -45499,7 +45562,7 @@ function parseDescription(content) {
45499
45562
  }
45500
45563
  function isDirLikeSync(p2) {
45501
45564
  try {
45502
- return import_node_fs8.default.statSync(p2).isDirectory();
45565
+ return import_node_fs9.default.statSync(p2).isDirectory();
45503
45566
  } catch {
45504
45567
  return false;
45505
45568
  }
@@ -45507,19 +45570,19 @@ function isDirLikeSync(p2) {
45507
45570
  function scanSkillDir(dir, source, seen, out, pluginName) {
45508
45571
  let entries;
45509
45572
  try {
45510
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
45573
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45511
45574
  } catch {
45512
45575
  return;
45513
45576
  }
45514
45577
  for (const ent of entries) {
45515
- const entryPath = import_node_path9.default.join(dir, ent.name);
45578
+ const entryPath = import_node_path10.default.join(dir, ent.name);
45516
45579
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
45517
45580
  let content;
45518
45581
  try {
45519
- content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
45582
+ content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
45520
45583
  } catch {
45521
45584
  try {
45522
- content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
45585
+ content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
45523
45586
  } catch {
45524
45587
  continue;
45525
45588
  }
@@ -45543,26 +45606,26 @@ function listSkillsForDir(dir, source) {
45543
45606
  function scanCommandDir(dir, source, seen, out, pluginName) {
45544
45607
  let entries;
45545
45608
  try {
45546
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
45609
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45547
45610
  } catch {
45548
45611
  return;
45549
45612
  }
45550
45613
  for (const ent of entries) {
45551
- const entryPath = import_node_path9.default.join(dir, ent.name);
45614
+ const entryPath = import_node_path10.default.join(dir, ent.name);
45552
45615
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
45553
45616
  const ns = ent.name;
45554
45617
  let subEntries;
45555
45618
  try {
45556
- subEntries = import_node_fs8.default.readdirSync(entryPath, { withFileTypes: true });
45619
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
45557
45620
  } catch {
45558
45621
  continue;
45559
45622
  }
45560
45623
  for (const se of subEntries) {
45561
45624
  if (!se.name.endsWith(".md")) continue;
45562
- const sePath = import_node_path9.default.join(entryPath, se.name);
45625
+ const sePath = import_node_path10.default.join(entryPath, se.name);
45563
45626
  let content;
45564
45627
  try {
45565
- content = import_node_fs8.default.readFileSync(sePath, "utf8");
45628
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
45566
45629
  } catch {
45567
45630
  continue;
45568
45631
  }
@@ -45579,7 +45642,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45579
45642
  } else if (ent.name.endsWith(".md")) {
45580
45643
  let content;
45581
45644
  try {
45582
- content = import_node_fs8.default.readFileSync(entryPath, "utf8");
45645
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
45583
45646
  } catch {
45584
45647
  continue;
45585
45648
  }
@@ -45595,10 +45658,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45595
45658
  }
45596
45659
  }
45597
45660
  function readInstalledPlugins(home) {
45598
- const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
45661
+ const file = import_node_path10.default.join(home, ".claude", "plugins", "installed_plugins.json");
45599
45662
  let raw;
45600
45663
  try {
45601
- raw = import_node_fs8.default.readFileSync(file, "utf8");
45664
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
45602
45665
  } catch {
45603
45666
  return [];
45604
45667
  }
@@ -45646,14 +45709,14 @@ var SkillsScanner = class {
45646
45709
  });
45647
45710
  }
45648
45711
  const fsBlock = [];
45649
- scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45650
- scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45651
- scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45652
- scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45712
+ scanSkillDir(import_node_path10.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45713
+ scanCommandDir(import_node_path10.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45714
+ scanSkillDir(import_node_path10.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45715
+ scanCommandDir(import_node_path10.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45653
45716
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
45654
45717
  for (const { name, root } of plugins) {
45655
- scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45656
- scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45718
+ scanSkillDir(import_node_path10.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45719
+ scanCommandDir(import_node_path10.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45657
45720
  }
45658
45721
  fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
45659
45722
  return [...builtinBlock, ...fsBlock];
@@ -45759,8 +45822,8 @@ var PersonaManager = class {
45759
45822
  };
45760
45823
 
45761
45824
  // src/persona/seed.ts
45762
- var fs10 = __toESM(require("fs"), 1);
45763
- var path13 = __toESM(require("path"), 1);
45825
+ var fs11 = __toESM(require("fs"), 1);
45826
+ var path14 = __toESM(require("path"), 1);
45764
45827
  var import_node_url = require("url");
45765
45828
  var import_meta = {};
45766
45829
  var DEFAULT_BYPASS_PROFILE = {
@@ -45930,24 +45993,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
45930
45993
  if (!argv1) return null;
45931
45994
  let real = argv1;
45932
45995
  try {
45933
- real = fs10.realpathSync(argv1);
45996
+ real = fs11.realpathSync(argv1);
45934
45997
  } catch {
45935
45998
  }
45936
- return path13.resolve(path13.dirname(real), sibling);
45999
+ return path14.resolve(path14.dirname(real), sibling);
45937
46000
  }
45938
46001
  function findDefaultsRoot(logger) {
45939
46002
  const candidates = [];
45940
46003
  try {
45941
- const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45942
- candidates.push(path13.resolve(here, "defaults"));
45943
- candidates.push(path13.resolve(here, "persona-defaults"));
46004
+ const here = path14.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46005
+ candidates.push(path14.resolve(here, "defaults"));
46006
+ candidates.push(path14.resolve(here, "persona-defaults"));
45944
46007
  } catch {
45945
46008
  }
45946
46009
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
45947
46010
  if (fromArgv) candidates.push(fromArgv);
45948
46011
  for (const c of candidates) {
45949
46012
  try {
45950
- if (fs10.statSync(c).isDirectory()) {
46013
+ if (fs11.statSync(c).isDirectory()) {
45951
46014
  logger?.info("persona.defaults-root.resolved", { root: c });
45952
46015
  return c;
45953
46016
  }
@@ -45964,8 +46027,8 @@ function seedDefaultPersonas(args) {
45964
46027
  args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
45965
46028
  continue;
45966
46029
  }
45967
- const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
45968
- if (!fs10.existsSync(bundleDir)) {
46030
+ const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
46031
+ if (!fs11.existsSync(bundleDir)) {
45969
46032
  args.logger.warn("persona.seed.skip", {
45970
46033
  personaId: entry.personaId,
45971
46034
  reason: "bundle-missing",
@@ -45973,8 +46036,8 @@ function seedDefaultPersonas(args) {
45973
46036
  });
45974
46037
  continue;
45975
46038
  }
45976
- const claudeMdPath = path13.join(bundleDir, "CLAUDE.md");
45977
- if (!fs10.existsSync(claudeMdPath)) {
46039
+ const claudeMdPath = path14.join(bundleDir, "CLAUDE.md");
46040
+ if (!fs11.existsSync(claudeMdPath)) {
45978
46041
  args.logger.warn("persona.seed.skip", {
45979
46042
  personaId: entry.personaId,
45980
46043
  reason: "no-CLAUDE.md",
@@ -45982,7 +46045,7 @@ function seedDefaultPersonas(args) {
45982
46045
  });
45983
46046
  continue;
45984
46047
  }
45985
- const personality = fs10.readFileSync(claudeMdPath, "utf8");
46048
+ const personality = fs11.readFileSync(claudeMdPath, "utf8");
45986
46049
  const now = Date.now();
45987
46050
  const persona = {
45988
46051
  personaId: entry.personaId,
@@ -46008,17 +46071,17 @@ function seedDefaultPersonas(args) {
46008
46071
  }
46009
46072
  }
46010
46073
  function skipNodeModulesUnder(srcRoot) {
46011
- return (src) => !path13.relative(srcRoot, src).split(path13.sep).includes("node_modules");
46074
+ return (src) => !path14.relative(srcRoot, src).split(path14.sep).includes("node_modules");
46012
46075
  }
46013
46076
  function copyBundleExtras(srcDir, dstDir) {
46014
- for (const entry of fs10.readdirSync(srcDir, { withFileTypes: true })) {
46077
+ for (const entry of fs11.readdirSync(srcDir, { withFileTypes: true })) {
46015
46078
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
46016
- const srcPath = path13.join(srcDir, entry.name);
46017
- const dstPath = path13.join(dstDir, entry.name);
46079
+ const srcPath = path14.join(srcDir, entry.name);
46080
+ const dstPath = path14.join(dstDir, entry.name);
46018
46081
  if (entry.isDirectory()) {
46019
- fs10.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46082
+ fs11.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46020
46083
  } else if (entry.isFile()) {
46021
- fs10.copyFileSync(srcPath, dstPath);
46084
+ fs11.copyFileSync(srcPath, dstPath);
46022
46085
  }
46023
46086
  }
46024
46087
  }
@@ -46026,16 +46089,16 @@ var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json"];
46026
46089
  function refreshDaemonManagedDirs(args) {
46027
46090
  const entries = args.entries ?? DEFAULT_PERSONAS;
46028
46091
  for (const entry of entries) {
46029
- const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
46030
- if (!fs10.existsSync(bundleDir)) continue;
46092
+ const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
46093
+ if (!fs11.existsSync(bundleDir)) continue;
46031
46094
  const personaDir = args.store.personaDirPath(entry.personaId);
46032
- if (!fs10.existsSync(personaDir)) continue;
46095
+ if (!fs11.existsSync(personaDir)) continue;
46033
46096
  for (const relPath of DAEMON_MANAGED_PATHS) {
46034
- const srcPath = path13.join(bundleDir, relPath);
46035
- if (!fs10.existsSync(srcPath)) continue;
46036
- const dstPath = path13.join(personaDir, relPath);
46097
+ const srcPath = path14.join(bundleDir, relPath);
46098
+ if (!fs11.existsSync(srcPath)) continue;
46099
+ const dstPath = path14.join(personaDir, relPath);
46037
46100
  try {
46038
- fs10.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46101
+ fs11.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46039
46102
  args.logger.info("persona.refresh.synced", {
46040
46103
  personaId: entry.personaId,
46041
46104
  path: relPath
@@ -46095,15 +46158,15 @@ function migrateCodexSandbox(args) {
46095
46158
  function findDeployKitRoot(logger) {
46096
46159
  const candidates = [];
46097
46160
  try {
46098
- const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46099
- candidates.push(path13.resolve(here, "..", "deploy-kit"));
46161
+ const here = path14.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46162
+ candidates.push(path14.resolve(here, "..", "deploy-kit"));
46100
46163
  } catch {
46101
46164
  }
46102
46165
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
46103
46166
  if (fromArgv) candidates.push(fromArgv);
46104
46167
  for (const c of candidates) {
46105
46168
  try {
46106
- if (fs10.statSync(c).isDirectory()) {
46169
+ if (fs11.statSync(c).isDirectory()) {
46107
46170
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
46108
46171
  return c;
46109
46172
  }
@@ -46114,8 +46177,8 @@ function findDeployKitRoot(logger) {
46114
46177
  return null;
46115
46178
  }
46116
46179
  function seedDeployKit(args) {
46117
- const dst = path13.join(args.dataDir, "deploy-kit");
46118
- fs10.cpSync(args.deployKitBundleRoot, dst, {
46180
+ const dst = path14.join(args.dataDir, "deploy-kit");
46181
+ fs11.cpSync(args.deployKitBundleRoot, dst, {
46119
46182
  recursive: true,
46120
46183
  dereference: true,
46121
46184
  force: false,
@@ -46124,35 +46187,35 @@ function seedDeployKit(args) {
46124
46187
  args.logger.info("deploy-kit.seed.done", { dst });
46125
46188
  }
46126
46189
  function refreshDeployKit(args) {
46127
- const dst = path13.join(args.dataDir, "deploy-kit");
46128
- if (!fs10.existsSync(dst)) {
46190
+ const dst = path14.join(args.dataDir, "deploy-kit");
46191
+ if (!fs11.existsSync(dst)) {
46129
46192
  seedDeployKit(args);
46130
46193
  return;
46131
46194
  }
46132
46195
  for (const sub of ["scripts", "contract"]) {
46133
- const s = path13.join(args.deployKitBundleRoot, sub);
46134
- if (fs10.existsSync(s)) {
46135
- fs10.cpSync(s, path13.join(dst, sub), { recursive: true, force: true, dereference: true });
46196
+ const s = path14.join(args.deployKitBundleRoot, sub);
46197
+ if (fs11.existsSync(s)) {
46198
+ fs11.cpSync(s, path14.join(dst, sub), { recursive: true, force: true, dereference: true });
46136
46199
  }
46137
46200
  }
46138
- const secretsSrc = path13.join(args.deployKitBundleRoot, ".secrets");
46139
- if (fs10.existsSync(secretsSrc)) {
46140
- fs10.mkdirSync(path13.join(dst, ".secrets"), { recursive: true });
46141
- for (const f of fs10.readdirSync(secretsSrc)) {
46142
- if (!f.endsWith(".example")) continue;
46143
- fs10.copyFileSync(path13.join(secretsSrc, f), path13.join(dst, ".secrets", f));
46201
+ const secretsSrc = path14.join(args.deployKitBundleRoot, ".secrets");
46202
+ if (fs11.existsSync(secretsSrc)) {
46203
+ fs11.mkdirSync(path14.join(dst, ".secrets"), { recursive: true });
46204
+ for (const f of fs11.readdirSync(secretsSrc)) {
46205
+ if (f.endsWith(".local")) continue;
46206
+ fs11.copyFileSync(path14.join(secretsSrc, f), path14.join(dst, ".secrets", f));
46144
46207
  }
46145
46208
  }
46146
46209
  args.logger.info("deploy-kit.refresh.done", { dst });
46147
46210
  }
46148
46211
 
46149
46212
  // src/share-md-viewer/load.ts
46150
- var import_node_fs10 = __toESM(require("fs"), 1);
46151
- var import_node_path10 = __toESM(require("path"), 1);
46213
+ var import_node_fs11 = __toESM(require("fs"), 1);
46214
+ var import_node_path11 = __toESM(require("path"), 1);
46152
46215
  var import_node_url2 = require("url");
46153
46216
 
46154
46217
  // src/share-md-viewer/asset-loader.ts
46155
- var import_node_fs9 = __toESM(require("fs"), 1);
46218
+ var import_node_fs10 = __toESM(require("fs"), 1);
46156
46219
  function htmlEscape(s) {
46157
46220
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
46158
46221
  }
@@ -46160,12 +46223,12 @@ function createViewerAssetLoader(opts) {
46160
46223
  let viewerTemplate;
46161
46224
  let errorTemplate;
46162
46225
  try {
46163
- viewerTemplate = import_node_fs9.default.readFileSync(opts.viewerHtmlPath, "utf8");
46226
+ viewerTemplate = import_node_fs10.default.readFileSync(opts.viewerHtmlPath, "utf8");
46164
46227
  } catch (err) {
46165
46228
  throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
46166
46229
  }
46167
46230
  try {
46168
- errorTemplate = import_node_fs9.default.readFileSync(opts.errorHtmlPath, "utf8");
46231
+ errorTemplate = import_node_fs10.default.readFileSync(opts.errorHtmlPath, "utf8");
46169
46232
  } catch (err) {
46170
46233
  throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
46171
46234
  }
@@ -46184,25 +46247,25 @@ var import_meta2 = {};
46184
46247
  function tryLoadViewerAssets(logger) {
46185
46248
  const candidates = [];
46186
46249
  try {
46187
- const here = import_node_path10.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
46250
+ const here = import_node_path11.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
46188
46251
  candidates.push(here);
46189
- candidates.push(import_node_path10.default.resolve(here, ".."));
46190
- candidates.push(import_node_path10.default.resolve(here, "..", "..", "dist"));
46252
+ candidates.push(import_node_path11.default.resolve(here, ".."));
46253
+ candidates.push(import_node_path11.default.resolve(here, "..", "..", "dist"));
46191
46254
  } catch {
46192
46255
  }
46193
46256
  if (process.argv[1]) {
46194
46257
  let real = process.argv[1];
46195
46258
  try {
46196
- real = import_node_fs10.default.realpathSync(process.argv[1]);
46259
+ real = import_node_fs11.default.realpathSync(process.argv[1]);
46197
46260
  } catch {
46198
46261
  }
46199
- candidates.push(import_node_path10.default.dirname(real));
46262
+ candidates.push(import_node_path11.default.dirname(real));
46200
46263
  }
46201
46264
  for (const root of candidates) {
46202
- const viewerHtmlPath = import_node_path10.default.join(root, "share-md-viewer.html");
46203
- const errorHtmlPath = import_node_path10.default.join(root, "share-md-viewer-error.html");
46265
+ const viewerHtmlPath = import_node_path11.default.join(root, "share-md-viewer.html");
46266
+ const errorHtmlPath = import_node_path11.default.join(root, "share-md-viewer-error.html");
46204
46267
  try {
46205
- if (import_node_fs10.default.statSync(viewerHtmlPath).isFile() && import_node_fs10.default.statSync(errorHtmlPath).isFile()) {
46268
+ if (import_node_fs11.default.statSync(viewerHtmlPath).isFile() && import_node_fs11.default.statSync(errorHtmlPath).isFile()) {
46206
46269
  logger?.info("share-md-viewer.assets-root.resolved", { root });
46207
46270
  return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
46208
46271
  }
@@ -46217,30 +46280,30 @@ function tryLoadViewerAssets(logger) {
46217
46280
  }
46218
46281
 
46219
46282
  // src/share-ui/load.ts
46220
- var import_node_fs12 = __toESM(require("fs"), 1);
46221
- var import_node_path12 = __toESM(require("path"), 1);
46283
+ var import_node_fs13 = __toESM(require("fs"), 1);
46284
+ var import_node_path13 = __toESM(require("path"), 1);
46222
46285
  var import_node_url3 = require("url");
46223
46286
 
46224
46287
  // src/share-ui/asset-loader.ts
46225
- var import_node_fs11 = __toESM(require("fs"), 1);
46226
- var import_node_path11 = __toESM(require("path"), 1);
46288
+ var import_node_fs12 = __toESM(require("fs"), 1);
46289
+ var import_node_path12 = __toESM(require("path"), 1);
46227
46290
  function createShareUiAssetLoader(opts) {
46228
46291
  let indexHtml;
46229
46292
  try {
46230
- indexHtml = import_node_fs11.default.readFileSync(opts.indexHtmlPath, "utf8");
46293
+ indexHtml = import_node_fs12.default.readFileSync(opts.indexHtmlPath, "utf8");
46231
46294
  } catch (err) {
46232
46295
  throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
46233
46296
  }
46234
- const assetsDir = import_node_path11.default.resolve(opts.assetsDir);
46297
+ const assetsDir = import_node_path12.default.resolve(opts.assetsDir);
46235
46298
  return {
46236
46299
  renderIndexHtml() {
46237
46300
  return indexHtml;
46238
46301
  },
46239
46302
  resolveAssetPath(rel) {
46240
- const resolved = import_node_path11.default.resolve(assetsDir, rel);
46241
- if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path11.default.sep)) return null;
46303
+ const resolved = import_node_path12.default.resolve(assetsDir, rel);
46304
+ if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path12.default.sep)) return null;
46242
46305
  try {
46243
- if (import_node_fs11.default.statSync(resolved).isFile()) return resolved;
46306
+ if (import_node_fs12.default.statSync(resolved).isFile()) return resolved;
46244
46307
  } catch {
46245
46308
  }
46246
46309
  return null;
@@ -46254,28 +46317,28 @@ function bundleDirFromArgv(argv1) {
46254
46317
  if (!argv1) return null;
46255
46318
  let real = argv1;
46256
46319
  try {
46257
- real = import_node_fs12.default.realpathSync(argv1);
46320
+ real = import_node_fs13.default.realpathSync(argv1);
46258
46321
  } catch {
46259
46322
  }
46260
- return import_node_path12.default.dirname(real);
46323
+ return import_node_path13.default.dirname(real);
46261
46324
  }
46262
46325
  function tryLoadShareUi(logger) {
46263
46326
  const candidates = [];
46264
46327
  try {
46265
- const here = import_node_path12.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
46328
+ const here = import_node_path13.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
46266
46329
  candidates.push(here);
46267
- candidates.push(import_node_path12.default.resolve(here, ".."));
46268
- candidates.push(import_node_path12.default.resolve(here, "..", "..", "dist"));
46330
+ candidates.push(import_node_path13.default.resolve(here, ".."));
46331
+ candidates.push(import_node_path13.default.resolve(here, "..", "..", "dist"));
46269
46332
  } catch {
46270
46333
  }
46271
46334
  const argvDir = bundleDirFromArgv(process.argv[1]);
46272
46335
  if (argvDir) candidates.push(argvDir);
46273
46336
  for (const root of candidates) {
46274
- const shareUiDir = import_node_path12.default.join(root, "share-ui");
46275
- const indexHtmlPath = import_node_path12.default.join(shareUiDir, "guest.html");
46276
- const assetsDir = import_node_path12.default.join(shareUiDir, "assets");
46337
+ const shareUiDir = import_node_path13.default.join(root, "share-ui");
46338
+ const indexHtmlPath = import_node_path13.default.join(shareUiDir, "guest.html");
46339
+ const assetsDir = import_node_path13.default.join(shareUiDir, "assets");
46277
46340
  try {
46278
- if (import_node_fs12.default.statSync(indexHtmlPath).isFile() && import_node_fs12.default.statSync(assetsDir).isDirectory()) {
46341
+ if (import_node_fs13.default.statSync(indexHtmlPath).isFile() && import_node_fs13.default.statSync(assetsDir).isDirectory()) {
46279
46342
  logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
46280
46343
  return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
46281
46344
  }
@@ -46353,20 +46416,20 @@ function buildVisitorLogin(deps) {
46353
46416
  }
46354
46417
 
46355
46418
  // src/visitor/visitor-store.ts
46356
- var import_node_fs13 = __toESM(require("fs"), 1);
46357
- var import_node_path13 = __toESM(require("path"), 1);
46419
+ var import_node_fs14 = __toESM(require("fs"), 1);
46420
+ var import_node_path14 = __toESM(require("path"), 1);
46358
46421
  function createVisitorStore(opts) {
46359
- const file = import_node_path13.default.join(opts.dir, "visitors.json");
46422
+ const file = import_node_path14.default.join(opts.dir, "visitors.json");
46360
46423
  const read = () => {
46361
46424
  try {
46362
- return JSON.parse(import_node_fs13.default.readFileSync(file, "utf8"));
46425
+ return JSON.parse(import_node_fs14.default.readFileSync(file, "utf8"));
46363
46426
  } catch {
46364
46427
  return [];
46365
46428
  }
46366
46429
  };
46367
46430
  const write = (rows) => {
46368
- import_node_fs13.default.mkdirSync(opts.dir, { recursive: true });
46369
- import_node_fs13.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46431
+ import_node_fs14.default.mkdirSync(opts.dir, { recursive: true });
46432
+ import_node_fs14.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46370
46433
  };
46371
46434
  return {
46372
46435
  upsert(r) {
@@ -46400,7 +46463,7 @@ init_claude();
46400
46463
 
46401
46464
  // src/tools/codex.ts
46402
46465
  var import_node_child_process4 = require("child_process");
46403
- var import_node_fs15 = __toESM(require("fs"), 1);
46466
+ var import_node_fs16 = __toESM(require("fs"), 1);
46404
46467
 
46405
46468
  // src/tools/codex-session.ts
46406
46469
  var import_node_child_process3 = require("child_process");
@@ -46648,8 +46711,8 @@ function turnStartInput(text) {
46648
46711
  const items = [];
46649
46712
  let leftover = text;
46650
46713
  for (const m2 of text.matchAll(SKILL_RE)) {
46651
- const [marker, name, path77] = m2;
46652
- items.push({ type: "skill", name, path: path77 });
46714
+ const [marker, name, path78] = m2;
46715
+ items.push({ type: "skill", name, path: path78 });
46653
46716
  leftover = leftover.replace(marker, "");
46654
46717
  }
46655
46718
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -46833,10 +46896,10 @@ function sanitizeCodexModel(model) {
46833
46896
  return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
46834
46897
  }
46835
46898
  async function probeCodex(env = process.env) {
46836
- if (env.CODEX_BIN && import_node_fs15.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46899
+ if (env.CODEX_BIN && import_node_fs16.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46837
46900
  try {
46838
46901
  const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
46839
- if (out && import_node_fs15.default.existsSync(out)) return { available: true, path: out };
46902
+ if (out && import_node_fs16.default.existsSync(out)) return { available: true, path: out };
46840
46903
  } catch {
46841
46904
  }
46842
46905
  return { available: false };
@@ -46882,9 +46945,9 @@ var CodexAdapter = class {
46882
46945
 
46883
46946
  // src/tools/claude-tui.ts
46884
46947
  var import_node_crypto5 = require("crypto");
46885
- var import_node_fs16 = __toESM(require("fs"), 1);
46948
+ var import_node_fs17 = __toESM(require("fs"), 1);
46886
46949
  var import_node_os7 = __toESM(require("os"), 1);
46887
- var import_node_path14 = __toESM(require("path"), 1);
46950
+ var import_node_path15 = __toESM(require("path"), 1);
46888
46951
  var import_headless = __toESM(require_xterm_headless(), 1);
46889
46952
 
46890
46953
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -48126,9 +48189,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
48126
48189
  function jsonlExistsForCtx(ctx) {
48127
48190
  if (!ctx.toolSessionId) return false;
48128
48191
  const home = import_node_os7.default.homedir();
48129
- const file = import_node_path14.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48192
+ const file = import_node_path15.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48130
48193
  try {
48131
- return import_node_fs16.default.statSync(file).isFile();
48194
+ return import_node_fs17.default.statSync(file).isFile();
48132
48195
  } catch {
48133
48196
  return false;
48134
48197
  }
@@ -48197,10 +48260,10 @@ var PersonaDispatchManager = class {
48197
48260
  };
48198
48261
 
48199
48262
  // src/dispatch/mcp-config.ts
48200
- var import_node_fs17 = __toESM(require("fs"), 1);
48201
- var import_node_path15 = __toESM(require("path"), 1);
48263
+ var import_node_fs18 = __toESM(require("fs"), 1);
48264
+ var import_node_path16 = __toESM(require("path"), 1);
48202
48265
  function dispatchMcpConfigPath(dataDir) {
48203
- return import_node_path15.default.join(dataDir, "dispatch.mcp.json");
48266
+ return import_node_path16.default.join(dataDir, "dispatch.mcp.json");
48204
48267
  }
48205
48268
  function writeDispatchMcpConfig(args) {
48206
48269
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -48215,16 +48278,16 @@ function writeDispatchMcpConfig(args) {
48215
48278
  }
48216
48279
  }
48217
48280
  };
48218
- import_node_fs17.default.mkdirSync(args.dataDir, { recursive: true });
48219
- import_node_fs17.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48281
+ import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
48282
+ import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48220
48283
  return cfgPath;
48221
48284
  }
48222
48285
 
48223
48286
  // src/ticket/mcp-config.ts
48224
- var import_node_fs18 = __toESM(require("fs"), 1);
48225
- var import_node_path16 = __toESM(require("path"), 1);
48287
+ var import_node_fs19 = __toESM(require("fs"), 1);
48288
+ var import_node_path17 = __toESM(require("path"), 1);
48226
48289
  function ticketMcpConfigPath(dataDir) {
48227
- return import_node_path16.default.join(dataDir, "ticket.mcp.json");
48290
+ return import_node_path17.default.join(dataDir, "ticket.mcp.json");
48228
48291
  }
48229
48292
  function writeTicketMcpConfig(args) {
48230
48293
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -48245,16 +48308,16 @@ function writeTicketMcpConfig(args) {
48245
48308
  }
48246
48309
  }
48247
48310
  };
48248
- import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
48249
- import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48311
+ import_node_fs19.default.mkdirSync(args.dataDir, { recursive: true });
48312
+ import_node_fs19.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48250
48313
  return cfgPath;
48251
48314
  }
48252
48315
 
48253
48316
  // src/shift/mcp-config.ts
48254
- var import_node_fs19 = __toESM(require("fs"), 1);
48255
- var import_node_path17 = __toESM(require("path"), 1);
48317
+ var import_node_fs20 = __toESM(require("fs"), 1);
48318
+ var import_node_path18 = __toESM(require("path"), 1);
48256
48319
  function shiftMcpConfigPath(dataDir) {
48257
- return import_node_path17.default.join(dataDir, "shift.mcp.json");
48320
+ return import_node_path18.default.join(dataDir, "shift.mcp.json");
48258
48321
  }
48259
48322
  async function writeShiftMcpConfig(args) {
48260
48323
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -48269,16 +48332,16 @@ async function writeShiftMcpConfig(args) {
48269
48332
  }
48270
48333
  }
48271
48334
  };
48272
- await import_node_fs19.default.promises.mkdir(args.dataDir, { recursive: true });
48273
- await import_node_fs19.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48335
+ await import_node_fs20.default.promises.mkdir(args.dataDir, { recursive: true });
48336
+ await import_node_fs20.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48274
48337
  return cfgPath;
48275
48338
  }
48276
48339
 
48277
48340
  // src/inbox/mcp-config.ts
48278
- var import_node_fs20 = __toESM(require("fs"), 1);
48279
- var import_node_path18 = __toESM(require("path"), 1);
48341
+ var import_node_fs21 = __toESM(require("fs"), 1);
48342
+ var import_node_path19 = __toESM(require("path"), 1);
48280
48343
  function inboxMcpConfigPath(dataDir) {
48281
- return import_node_path18.default.join(dataDir, "inbox.mcp.json");
48344
+ return import_node_path19.default.join(dataDir, "inbox.mcp.json");
48282
48345
  }
48283
48346
  async function writeInboxMcpConfig(args) {
48284
48347
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -48293,14 +48356,14 @@ async function writeInboxMcpConfig(args) {
48293
48356
  }
48294
48357
  }
48295
48358
  };
48296
- await import_node_fs20.default.promises.mkdir(args.dataDir, { recursive: true });
48297
- await import_node_fs20.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48359
+ await import_node_fs21.default.promises.mkdir(args.dataDir, { recursive: true });
48360
+ await import_node_fs21.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48298
48361
  return cfgPath;
48299
48362
  }
48300
48363
 
48301
48364
  // src/shift/store.ts
48302
48365
  var import_promises = __toESM(require("fs/promises"), 1);
48303
- var import_node_path19 = __toESM(require("path"), 1);
48366
+ var import_node_path20 = __toESM(require("path"), 1);
48304
48367
  var import_node_crypto6 = require("crypto");
48305
48368
 
48306
48369
  // src/shift/constants.ts
@@ -48369,7 +48432,7 @@ function createShiftStore(deps) {
48369
48432
  flushTimer = null;
48370
48433
  }
48371
48434
  const content = { version: 1, shifts };
48372
- await import_promises.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
48435
+ await import_promises.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
48373
48436
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
48374
48437
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
48375
48438
  await import_promises.default.rename(tmp, deps.filePath);
@@ -49103,13 +49166,13 @@ function mapSkillsListResponse(res) {
49103
49166
  const r = s ?? {};
49104
49167
  const name = str3(r.name);
49105
49168
  if (!name) continue;
49106
- const path77 = str3(r.path);
49169
+ const path78 = str3(r.path);
49107
49170
  const description = str3(r.description);
49108
49171
  const isPlugin = name.includes(":");
49109
49172
  out.push({
49110
49173
  name,
49111
49174
  source: isPlugin ? "plugin" : "project",
49112
- ...path77 ? { path: path77 } : {},
49175
+ ...path78 ? { path: path78 } : {},
49113
49176
  ...description ? { description } : {},
49114
49177
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49115
49178
  });
@@ -49148,23 +49211,23 @@ async function listCodexSkills(cwd, deps = {}) {
49148
49211
  }
49149
49212
 
49150
49213
  // src/workspace/browser.ts
49151
- var import_node_fs21 = __toESM(require("fs"), 1);
49214
+ var import_node_fs22 = __toESM(require("fs"), 1);
49152
49215
  var import_node_os8 = __toESM(require("os"), 1);
49153
- var import_node_path20 = __toESM(require("path"), 1);
49216
+ var import_node_path21 = __toESM(require("path"), 1);
49154
49217
  init_protocol();
49155
49218
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
49156
49219
  function resolveInsideCwd(cwd, subpath) {
49157
- const absCwd = import_node_path20.default.resolve(cwd);
49158
- const joined = import_node_path20.default.resolve(absCwd, subpath ?? ".");
49159
- const rel = import_node_path20.default.relative(absCwd, joined);
49160
- if (rel.startsWith("..") || import_node_path20.default.isAbsolute(rel)) {
49220
+ const absCwd = import_node_path21.default.resolve(cwd);
49221
+ const joined = import_node_path21.default.resolve(absCwd, subpath ?? ".");
49222
+ const rel = import_node_path21.default.relative(absCwd, joined);
49223
+ if (rel.startsWith("..") || import_node_path21.default.isAbsolute(rel)) {
49161
49224
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
49162
49225
  }
49163
49226
  return joined;
49164
49227
  }
49165
49228
  function ensureCwd(cwd) {
49166
49229
  try {
49167
- const stat = import_node_fs21.default.statSync(cwd);
49230
+ const stat = import_node_fs22.default.statSync(cwd);
49168
49231
  if (!stat.isDirectory()) {
49169
49232
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
49170
49233
  }
@@ -49178,7 +49241,7 @@ var WorkspaceBrowser = class {
49178
49241
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
49179
49242
  ensureCwd(cwd);
49180
49243
  const full = resolveInsideCwd(cwd, args.path);
49181
- const dirents = import_node_fs21.default.readdirSync(full, { withFileTypes: true });
49244
+ const dirents = import_node_fs22.default.readdirSync(full, { withFileTypes: true });
49182
49245
  const entries = [];
49183
49246
  for (const d of dirents) {
49184
49247
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -49188,7 +49251,7 @@ var WorkspaceBrowser = class {
49188
49251
  mtime: ""
49189
49252
  };
49190
49253
  try {
49191
- const st = import_node_fs21.default.statSync(import_node_path20.default.join(full, d.name));
49254
+ const st = import_node_fs22.default.statSync(import_node_path21.default.join(full, d.name));
49192
49255
  entry.mtime = new Date(st.mtimeMs).toISOString();
49193
49256
  if (d.isFile()) entry.size = st.size;
49194
49257
  } catch {
@@ -49204,14 +49267,14 @@ var WorkspaceBrowser = class {
49204
49267
  read(args) {
49205
49268
  ensureCwd(args.cwd);
49206
49269
  const full = resolveInsideCwd(args.cwd, args.path);
49207
- const st = import_node_fs21.default.statSync(full);
49270
+ const st = import_node_fs22.default.statSync(full);
49208
49271
  if (!st.isFile()) {
49209
49272
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
49210
49273
  }
49211
49274
  if (st.size > MAX_FILE_BYTES) {
49212
49275
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
49213
49276
  }
49214
- const buf = import_node_fs21.default.readFileSync(full);
49277
+ const buf = import_node_fs22.default.readFileSync(full);
49215
49278
  const isBinary = buf.includes(0);
49216
49279
  if (isBinary) {
49217
49280
  return {
@@ -49233,20 +49296,20 @@ var WorkspaceBrowser = class {
49233
49296
  };
49234
49297
 
49235
49298
  // src/skills/agents-scanner.ts
49236
- var import_node_fs22 = __toESM(require("fs"), 1);
49299
+ var import_node_fs23 = __toESM(require("fs"), 1);
49237
49300
  var import_node_os9 = __toESM(require("os"), 1);
49238
- var import_node_path21 = __toESM(require("path"), 1);
49301
+ var import_node_path22 = __toESM(require("path"), 1);
49239
49302
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
49240
49303
  function isDirLikeSync2(p2) {
49241
49304
  try {
49242
- return import_node_fs22.default.statSync(p2).isDirectory();
49305
+ return import_node_fs23.default.statSync(p2).isDirectory();
49243
49306
  } catch {
49244
49307
  return false;
49245
49308
  }
49246
49309
  }
49247
49310
  function fileExistsSync(p2) {
49248
49311
  try {
49249
- return import_node_fs22.default.statSync(p2).isFile();
49312
+ return import_node_fs23.default.statSync(p2).isFile();
49250
49313
  } catch {
49251
49314
  return false;
49252
49315
  }
@@ -49254,7 +49317,7 @@ function fileExistsSync(p2) {
49254
49317
  function parseAgentFile(filePath) {
49255
49318
  let content;
49256
49319
  try {
49257
- content = import_node_fs22.default.readFileSync(filePath, "utf8");
49320
+ content = import_node_fs23.default.readFileSync(filePath, "utf8");
49258
49321
  } catch {
49259
49322
  return {};
49260
49323
  }
@@ -49267,16 +49330,16 @@ function parseAgentFile(filePath) {
49267
49330
  function scanAgentsDir(dir, source, seen, out) {
49268
49331
  let entries;
49269
49332
  try {
49270
- entries = import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
49333
+ entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49271
49334
  } catch {
49272
49335
  return;
49273
49336
  }
49274
49337
  for (const ent of entries) {
49275
49338
  if (!ent.name.endsWith(".md")) continue;
49276
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path21.default.join(dir, ent.name)))) {
49339
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path22.default.join(dir, ent.name)))) {
49277
49340
  continue;
49278
49341
  }
49279
- const filePath = import_node_path21.default.join(dir, ent.name);
49342
+ const filePath = import_node_path22.default.join(dir, ent.name);
49280
49343
  const baseName = ent.name.replace(/\.md$/, "");
49281
49344
  if (seen.has(baseName)) continue;
49282
49345
  seen.add(baseName);
@@ -49294,12 +49357,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49294
49357
  function walk2(dir, namespaces) {
49295
49358
  let entries;
49296
49359
  try {
49297
- entries = import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
49360
+ entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49298
49361
  } catch {
49299
49362
  return;
49300
49363
  }
49301
49364
  for (const ent of entries) {
49302
- const childPath = import_node_path21.default.join(dir, ent.name);
49365
+ const childPath = import_node_path22.default.join(dir, ent.name);
49303
49366
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
49304
49367
  walk2(childPath, [...namespaces, ent.name]);
49305
49368
  continue;
@@ -49324,13 +49387,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49324
49387
  walk2(root, []);
49325
49388
  }
49326
49389
  function readInstalledPlugins2(home) {
49327
- const pluginsDir = import_node_path21.default.join(home, ".claude", "plugins");
49328
- const v2 = import_node_path21.default.join(pluginsDir, "installed_plugins_v2.json");
49329
- const v1 = import_node_path21.default.join(pluginsDir, "installed_plugins.json");
49390
+ const pluginsDir = import_node_path22.default.join(home, ".claude", "plugins");
49391
+ const v2 = import_node_path22.default.join(pluginsDir, "installed_plugins_v2.json");
49392
+ const v1 = import_node_path22.default.join(pluginsDir, "installed_plugins.json");
49330
49393
  let raw = null;
49331
49394
  for (const candidate of [v2, v1]) {
49332
49395
  try {
49333
- raw = import_node_fs22.default.readFileSync(candidate, "utf8");
49396
+ raw = import_node_fs23.default.readFileSync(candidate, "utf8");
49334
49397
  break;
49335
49398
  } catch {
49336
49399
  }
@@ -49355,19 +49418,19 @@ function readInstalledPlugins2(home) {
49355
49418
  return out;
49356
49419
  }
49357
49420
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
49358
- let cur = import_node_path21.default.resolve(startCwd);
49359
- const fsRoot = import_node_path21.default.parse(cur).root;
49421
+ let cur = import_node_path22.default.resolve(startCwd);
49422
+ const fsRoot = import_node_path22.default.parse(cur).root;
49360
49423
  while (true) {
49361
- scanAgentsDir(import_node_path21.default.join(cur, ".claude", "agents"), "project", seen, out);
49424
+ scanAgentsDir(import_node_path22.default.join(cur, ".claude", "agents"), "project", seen, out);
49362
49425
  let hasGit = false;
49363
49426
  try {
49364
- hasGit = import_node_fs22.default.existsSync(import_node_path21.default.join(cur, ".git"));
49427
+ hasGit = import_node_fs23.default.existsSync(import_node_path22.default.join(cur, ".git"));
49365
49428
  } catch {
49366
49429
  }
49367
49430
  if (hasGit) return;
49368
49431
  if (cur === home) return;
49369
49432
  if (cur === fsRoot) return;
49370
- const parent = import_node_path21.default.dirname(cur);
49433
+ const parent = import_node_path22.default.dirname(cur);
49371
49434
  if (parent === cur) return;
49372
49435
  cur = parent;
49373
49436
  }
@@ -49402,7 +49465,7 @@ var AgentsScanner = class {
49402
49465
  }
49403
49466
  const fsBlock = [];
49404
49467
  scanAgentsDir(
49405
- import_node_path21.default.join(this.home, ".claude", "agents"),
49468
+ import_node_path22.default.join(this.home, ".claude", "agents"),
49406
49469
  "global",
49407
49470
  seen,
49408
49471
  fsBlock
@@ -49416,7 +49479,7 @@ var AgentsScanner = class {
49416
49479
  ...this.extraPluginRoots
49417
49480
  ];
49418
49481
  for (const { name, root } of plugins) {
49419
- const agentsRoot = import_node_path21.default.join(root, "agents");
49482
+ const agentsRoot = import_node_path22.default.join(root, "agents");
49420
49483
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
49421
49484
  }
49422
49485
  return [...builtinBlock, ...fsBlock];
@@ -49424,15 +49487,15 @@ var AgentsScanner = class {
49424
49487
  };
49425
49488
 
49426
49489
  // src/observer/session-observer.ts
49427
- var import_node_fs24 = __toESM(require("fs"), 1);
49490
+ var import_node_fs25 = __toESM(require("fs"), 1);
49428
49491
  var import_node_os11 = __toESM(require("os"), 1);
49429
- var import_node_path23 = __toESM(require("path"), 1);
49492
+ var import_node_path24 = __toESM(require("path"), 1);
49430
49493
  init_claude_history();
49431
49494
 
49432
49495
  // src/observer/subagent-meta-observer.ts
49433
- var import_node_fs23 = __toESM(require("fs"), 1);
49496
+ var import_node_fs24 = __toESM(require("fs"), 1);
49434
49497
  var import_node_os10 = __toESM(require("os"), 1);
49435
- var import_node_path22 = __toESM(require("path"), 1);
49498
+ var import_node_path23 = __toESM(require("path"), 1);
49436
49499
  init_claude_history();
49437
49500
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
49438
49501
  var SubagentMetaObserver = class {
@@ -49445,7 +49508,7 @@ var SubagentMetaObserver = class {
49445
49508
  watches = /* @__PURE__ */ new Map();
49446
49509
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
49447
49510
  resolveSubagentDir(cwd, toolSessionId) {
49448
- return import_node_path22.default.join(
49511
+ return import_node_path23.default.join(
49449
49512
  this.home,
49450
49513
  ".claude",
49451
49514
  "projects",
@@ -49475,7 +49538,7 @@ var SubagentMetaObserver = class {
49475
49538
  attachWatcher(w2) {
49476
49539
  if (w2.watcher) return;
49477
49540
  try {
49478
- w2.watcher = import_node_fs23.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49541
+ w2.watcher = import_node_fs24.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49479
49542
  if (!name) return;
49480
49543
  const m2 = META_RE.exec(String(name));
49481
49544
  if (!m2) return;
@@ -49487,7 +49550,7 @@ var SubagentMetaObserver = class {
49487
49550
  scan(w2) {
49488
49551
  let entries;
49489
49552
  try {
49490
- entries = import_node_fs23.default.readdirSync(w2.dirPath);
49553
+ entries = import_node_fs24.default.readdirSync(w2.dirPath);
49491
49554
  } catch {
49492
49555
  return;
49493
49556
  }
@@ -49501,10 +49564,10 @@ var SubagentMetaObserver = class {
49501
49564
  if (!m2) return;
49502
49565
  const agentId = m2[1];
49503
49566
  if (w2.emitted.has(agentId)) return;
49504
- const file = import_node_path22.default.join(w2.dirPath, name);
49567
+ const file = import_node_path23.default.join(w2.dirPath, name);
49505
49568
  let raw;
49506
49569
  try {
49507
- raw = import_node_fs23.default.readFileSync(file, "utf8");
49570
+ raw = import_node_fs24.default.readFileSync(file, "utf8");
49508
49571
  } catch {
49509
49572
  return;
49510
49573
  }
@@ -49561,14 +49624,14 @@ var SessionObserver = class {
49561
49624
  metaObserver;
49562
49625
  resolveJsonlPath(cwd, toolSessionId, override) {
49563
49626
  if (override) return override;
49564
- return import_node_path23.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
49627
+ return import_node_path24.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
49565
49628
  }
49566
49629
  start(args) {
49567
49630
  this.stop(args.sessionId);
49568
49631
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
49569
49632
  let size = 0;
49570
49633
  try {
49571
- size = import_node_fs24.default.statSync(filePath).size;
49634
+ size = import_node_fs25.default.statSync(filePath).size;
49572
49635
  } catch {
49573
49636
  }
49574
49637
  const w2 = {
@@ -49582,10 +49645,10 @@ var SessionObserver = class {
49582
49645
  prevIsRejectSentinel: false
49583
49646
  };
49584
49647
  try {
49585
- import_node_fs24.default.mkdirSync(import_node_path23.default.dirname(filePath), { recursive: true });
49648
+ import_node_fs25.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
49586
49649
  } catch {
49587
49650
  }
49588
- w2.watcher = import_node_fs24.default.watch(import_node_path23.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49651
+ w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49589
49652
  if (!changedName || !filePath.endsWith(changedName)) return;
49590
49653
  this.poll(w2);
49591
49654
  });
@@ -49608,7 +49671,7 @@ var SessionObserver = class {
49608
49671
  // 异常静默吞,不阻塞 watcher 启动
49609
49672
  hydrateMetaTail(w2, maxLines = 200) {
49610
49673
  try {
49611
- const raw = import_node_fs24.default.readFileSync(w2.filePath, "utf8");
49674
+ const raw = import_node_fs25.default.readFileSync(w2.filePath, "utf8");
49612
49675
  if (!raw) return;
49613
49676
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
49614
49677
  if (allLines.length === 0) return;
@@ -49632,7 +49695,7 @@ var SessionObserver = class {
49632
49695
  poll(w2) {
49633
49696
  let size = 0;
49634
49697
  try {
49635
- size = import_node_fs24.default.statSync(w2.filePath).size;
49698
+ size = import_node_fs25.default.statSync(w2.filePath).size;
49636
49699
  } catch {
49637
49700
  return;
49638
49701
  }
@@ -49641,11 +49704,11 @@ var SessionObserver = class {
49641
49704
  w2.buf = "";
49642
49705
  }
49643
49706
  if (size === w2.lastSize) return;
49644
- const fd = import_node_fs24.default.openSync(w2.filePath, "r");
49707
+ const fd = import_node_fs25.default.openSync(w2.filePath, "r");
49645
49708
  try {
49646
49709
  const len = size - w2.lastSize;
49647
49710
  const buf = Buffer.alloc(len);
49648
- import_node_fs24.default.readSync(fd, buf, 0, len, w2.lastSize);
49711
+ import_node_fs25.default.readSync(fd, buf, 0, len, w2.lastSize);
49649
49712
  w2.lastSize = size;
49650
49713
  w2.buf += buf.toString("utf8");
49651
49714
  let newlineIndex;
@@ -49668,7 +49731,7 @@ var SessionObserver = class {
49668
49731
  }
49669
49732
  }
49670
49733
  } finally {
49671
- import_node_fs24.default.closeSync(fd);
49734
+ import_node_fs25.default.closeSync(fd);
49672
49735
  }
49673
49736
  }
49674
49737
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -50471,15 +50534,15 @@ async function authenticate(token, deps) {
50471
50534
  }
50472
50535
 
50473
50536
  // src/permission/capability-store.ts
50474
- var fs28 = __toESM(require("fs"), 1);
50475
- var path28 = __toESM(require("path"), 1);
50537
+ var fs29 = __toESM(require("fs"), 1);
50538
+ var path29 = __toESM(require("path"), 1);
50476
50539
  init_src();
50477
50540
  var CAPABILITIES_FILE_NAME = "capabilities.json";
50478
50541
  var FILE_VERSION = 1;
50479
50542
  var CapabilityStore = class {
50480
50543
  constructor(dataDir) {
50481
50544
  this.dataDir = dataDir;
50482
- fs28.mkdirSync(dataDir, { recursive: true });
50545
+ fs29.mkdirSync(dataDir, { recursive: true });
50483
50546
  this.cache = this.readFromDisk();
50484
50547
  }
50485
50548
  dataDir;
@@ -50503,13 +50566,13 @@ var CapabilityStore = class {
50503
50566
  this.flush();
50504
50567
  }
50505
50568
  filePath() {
50506
- return path28.join(this.dataDir, CAPABILITIES_FILE_NAME);
50569
+ return path29.join(this.dataDir, CAPABILITIES_FILE_NAME);
50507
50570
  }
50508
50571
  readFromDisk() {
50509
50572
  const file = this.filePath();
50510
50573
  let raw;
50511
50574
  try {
50512
- raw = fs28.readFileSync(file, "utf8");
50575
+ raw = fs29.readFileSync(file, "utf8");
50513
50576
  } catch (err) {
50514
50577
  if (err?.code === "ENOENT") return [];
50515
50578
  return [];
@@ -50537,10 +50600,10 @@ var CapabilityStore = class {
50537
50600
  }
50538
50601
  atomicWrite(file, content) {
50539
50602
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50540
- fs28.writeFileSync(tmp, content, { mode: 384 });
50541
- fs28.renameSync(tmp, file);
50603
+ fs29.writeFileSync(tmp, content, { mode: 384 });
50604
+ fs29.renameSync(tmp, file);
50542
50605
  try {
50543
- fs28.chmodSync(file, 384);
50606
+ fs29.chmodSync(file, 384);
50544
50607
  } catch {
50545
50608
  }
50546
50609
  }
@@ -50633,14 +50696,14 @@ var CapabilityManager = class {
50633
50696
  };
50634
50697
 
50635
50698
  // src/permission/cleanup.ts
50636
- var fs29 = __toESM(require("fs"), 1);
50699
+ var fs30 = __toESM(require("fs"), 1);
50637
50700
  function cleanupGuestSessionsForCapability(cap, factory) {
50638
50701
  const removed = [];
50639
50702
  for (const g2 of cap.grants) {
50640
50703
  if (g2.resource.type !== "persona") continue;
50641
50704
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
50642
50705
  try {
50643
- fs29.rmSync(dir, { recursive: true, force: true });
50706
+ fs30.rmSync(dir, { recursive: true, force: true });
50644
50707
  removed.push(dir);
50645
50708
  } catch {
50646
50709
  }
@@ -50649,14 +50712,14 @@ function cleanupGuestSessionsForCapability(cap, factory) {
50649
50712
  }
50650
50713
 
50651
50714
  // src/inbox/inbox-store.ts
50652
- var fs30 = __toESM(require("fs"), 1);
50653
- var path29 = __toESM(require("path"), 1);
50715
+ var fs31 = __toESM(require("fs"), 1);
50716
+ var path30 = __toESM(require("path"), 1);
50654
50717
  init_src();
50655
50718
  var INBOX_SUBDIR = "inbox";
50656
50719
  var InboxStore = class {
50657
50720
  constructor(dataDir) {
50658
50721
  this.dataDir = dataDir;
50659
- fs30.mkdirSync(this.dirPath(), { recursive: true });
50722
+ fs31.mkdirSync(this.dirPath(), { recursive: true });
50660
50723
  }
50661
50724
  dataDir;
50662
50725
  /**
@@ -50668,7 +50731,7 @@ var InboxStore = class {
50668
50731
  const file = this.filePath(peerDeviceId);
50669
50732
  let raw;
50670
50733
  try {
50671
- raw = fs30.readFileSync(file, "utf8");
50734
+ raw = fs31.readFileSync(file, "utf8");
50672
50735
  } catch (err) {
50673
50736
  if (err?.code === "ENOENT") return [];
50674
50737
  return [];
@@ -50684,7 +50747,7 @@ var InboxStore = class {
50684
50747
  const dir = this.dirPath();
50685
50748
  let entries;
50686
50749
  try {
50687
- entries = fs30.readdirSync(dir);
50750
+ entries = fs31.readdirSync(dir);
50688
50751
  } catch (err) {
50689
50752
  if (err?.code === "ENOENT") return [];
50690
50753
  return [];
@@ -50700,9 +50763,9 @@ var InboxStore = class {
50700
50763
  if (existing.some((m2) => m2.id === message.id)) return;
50701
50764
  const file = this.filePath(message.peerDeviceId);
50702
50765
  const line = JSON.stringify(message) + "\n";
50703
- fs30.appendFileSync(file, line, { mode: 384 });
50766
+ fs31.appendFileSync(file, line, { mode: 384 });
50704
50767
  try {
50705
- fs30.chmodSync(file, 384);
50768
+ fs31.chmodSync(file, 384);
50706
50769
  } catch {
50707
50770
  }
50708
50771
  }
@@ -50732,7 +50795,7 @@ var InboxStore = class {
50732
50795
  removeByPeerDeviceId(peerDeviceId) {
50733
50796
  const file = this.filePath(peerDeviceId);
50734
50797
  try {
50735
- fs30.unlinkSync(file);
50798
+ fs31.unlinkSync(file);
50736
50799
  } catch (err) {
50737
50800
  if (err?.code === "ENOENT") return;
50738
50801
  }
@@ -50741,18 +50804,18 @@ var InboxStore = class {
50741
50804
  const file = this.filePath(peerDeviceId);
50742
50805
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50743
50806
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
50744
- fs30.writeFileSync(tmp, content, { mode: 384 });
50745
- fs30.renameSync(tmp, file);
50807
+ fs31.writeFileSync(tmp, content, { mode: 384 });
50808
+ fs31.renameSync(tmp, file);
50746
50809
  try {
50747
- fs30.chmodSync(file, 384);
50810
+ fs31.chmodSync(file, 384);
50748
50811
  } catch {
50749
50812
  }
50750
50813
  }
50751
50814
  dirPath() {
50752
- return path29.join(this.dataDir, INBOX_SUBDIR);
50815
+ return path30.join(this.dataDir, INBOX_SUBDIR);
50753
50816
  }
50754
50817
  filePath(peerDeviceId) {
50755
- return path29.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50818
+ return path30.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50756
50819
  }
50757
50820
  };
50758
50821
  function parseAllLines(raw) {
@@ -50840,8 +50903,8 @@ var InboxManager = class {
50840
50903
  };
50841
50904
 
50842
50905
  // src/state/contact-store.ts
50843
- var fs31 = __toESM(require("fs"), 1);
50844
- var path30 = __toESM(require("path"), 1);
50906
+ var fs32 = __toESM(require("fs"), 1);
50907
+ var path31 = __toESM(require("path"), 1);
50845
50908
  init_src();
50846
50909
  var FILE_NAME = "contacts.json";
50847
50910
  var ContactStore = class {
@@ -50852,10 +50915,10 @@ var ContactStore = class {
50852
50915
  contacts = /* @__PURE__ */ new Map();
50853
50916
  load() {
50854
50917
  this.contacts.clear();
50855
- const file = path30.join(this.dataDir, FILE_NAME);
50918
+ const file = path31.join(this.dataDir, FILE_NAME);
50856
50919
  let raw;
50857
50920
  try {
50858
- raw = fs31.readFileSync(file, "utf8");
50921
+ raw = fs32.readFileSync(file, "utf8");
50859
50922
  } catch (err) {
50860
50923
  if (err?.code !== "ENOENT") this.renameBak(file);
50861
50924
  return;
@@ -50927,20 +50990,20 @@ var ContactStore = class {
50927
50990
  return true;
50928
50991
  }
50929
50992
  flush() {
50930
- const file = path30.join(this.dataDir, FILE_NAME);
50993
+ const file = path31.join(this.dataDir, FILE_NAME);
50931
50994
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
50932
50995
  const content = JSON.stringify(
50933
50996
  { contacts: Array.from(this.contacts.values()) },
50934
50997
  null,
50935
50998
  2
50936
50999
  );
50937
- fs31.mkdirSync(this.dataDir, { recursive: true });
50938
- fs31.writeFileSync(tmp, content, { mode: 384 });
50939
- fs31.renameSync(tmp, file);
51000
+ fs32.mkdirSync(this.dataDir, { recursive: true });
51001
+ fs32.writeFileSync(tmp, content, { mode: 384 });
51002
+ fs32.renameSync(tmp, file);
50940
51003
  }
50941
51004
  renameBak(file) {
50942
51005
  try {
50943
- fs31.renameSync(file, `${file}.bak`);
51006
+ fs32.renameSync(file, `${file}.bak`);
50944
51007
  } catch {
50945
51008
  }
50946
51009
  }
@@ -51097,61 +51160,61 @@ async function autoReverseContact(args) {
51097
51160
  init_src();
51098
51161
 
51099
51162
  // src/migrations/2026-05-20-flatten-sessions.ts
51100
- var fs32 = __toESM(require("fs"), 1);
51101
- var path31 = __toESM(require("path"), 1);
51163
+ var fs33 = __toESM(require("fs"), 1);
51164
+ var path32 = __toESM(require("path"), 1);
51102
51165
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
51103
51166
  function migrateFlattenSessions(opts) {
51104
51167
  const dataDir = opts.dataDir;
51105
51168
  const now = opts.now ?? Date.now;
51106
- const sessionsDir = path31.join(dataDir, "sessions");
51107
- const flagPath = path31.join(sessionsDir, MIGRATION_FLAG_NAME);
51169
+ const sessionsDir = path32.join(dataDir, "sessions");
51170
+ const flagPath = path32.join(sessionsDir, MIGRATION_FLAG_NAME);
51108
51171
  if (existsSync3(flagPath)) {
51109
51172
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
51110
51173
  }
51111
51174
  let movedBare = 0;
51112
51175
  let movedVmOwner = 0;
51113
51176
  let archivedListener = 0;
51114
- const defaultDir = path31.join(sessionsDir, "default");
51177
+ const defaultDir = path32.join(sessionsDir, "default");
51115
51178
  if (existsSync3(defaultDir)) {
51116
51179
  for (const entry of readdirSafe(defaultDir)) {
51117
51180
  if (!entry.endsWith(".json")) continue;
51118
- const src = path31.join(defaultDir, entry);
51119
- const dst = path31.join(sessionsDir, entry);
51120
- fs32.renameSync(src, dst);
51181
+ const src = path32.join(defaultDir, entry);
51182
+ const dst = path32.join(sessionsDir, entry);
51183
+ fs33.renameSync(src, dst);
51121
51184
  movedBare += 1;
51122
51185
  }
51123
51186
  rmdirIfEmpty(defaultDir);
51124
51187
  }
51125
51188
  for (const pid of readdirSafe(sessionsDir)) {
51126
- const personaDir = path31.join(sessionsDir, pid);
51189
+ const personaDir = path32.join(sessionsDir, pid);
51127
51190
  if (!isDir(personaDir)) continue;
51128
51191
  if (pid === "default") continue;
51129
- const ownerSrc = path31.join(personaDir, "owner");
51192
+ const ownerSrc = path32.join(personaDir, "owner");
51130
51193
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
51131
- const ownerDst = path31.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51132
- fs32.mkdirSync(ownerDst, { recursive: true });
51194
+ const ownerDst = path32.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51195
+ fs33.mkdirSync(ownerDst, { recursive: true });
51133
51196
  for (const file of readdirSafe(ownerSrc)) {
51134
51197
  if (!file.endsWith(".json")) continue;
51135
- fs32.renameSync(path31.join(ownerSrc, file), path31.join(ownerDst, file));
51198
+ fs33.renameSync(path32.join(ownerSrc, file), path32.join(ownerDst, file));
51136
51199
  movedVmOwner += 1;
51137
51200
  }
51138
51201
  rmdirIfEmpty(ownerSrc);
51139
51202
  }
51140
- const listenerSrc = path31.join(personaDir, "listener");
51203
+ const listenerSrc = path32.join(personaDir, "listener");
51141
51204
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
51142
- const archiveDst = path31.join(dataDir, ".legacy", `listener-${pid}`);
51143
- fs32.mkdirSync(archiveDst, { recursive: true });
51205
+ const archiveDst = path32.join(dataDir, ".legacy", `listener-${pid}`);
51206
+ fs33.mkdirSync(archiveDst, { recursive: true });
51144
51207
  for (const file of readdirSafe(listenerSrc)) {
51145
51208
  if (!file.endsWith(".json")) continue;
51146
- fs32.renameSync(path31.join(listenerSrc, file), path31.join(archiveDst, file));
51209
+ fs33.renameSync(path32.join(listenerSrc, file), path32.join(archiveDst, file));
51147
51210
  archivedListener += 1;
51148
51211
  }
51149
51212
  rmdirIfEmpty(listenerSrc);
51150
51213
  }
51151
51214
  rmdirIfEmpty(personaDir);
51152
51215
  }
51153
- fs32.mkdirSync(sessionsDir, { recursive: true });
51154
- fs32.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51216
+ fs33.mkdirSync(sessionsDir, { recursive: true });
51217
+ fs33.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51155
51218
  return {
51156
51219
  skipped: false,
51157
51220
  flagWritten: true,
@@ -51162,7 +51225,7 @@ function migrateFlattenSessions(opts) {
51162
51225
  }
51163
51226
  function existsSync3(p2) {
51164
51227
  try {
51165
- fs32.statSync(p2);
51228
+ fs33.statSync(p2);
51166
51229
  return true;
51167
51230
  } catch {
51168
51231
  return false;
@@ -51170,31 +51233,31 @@ function existsSync3(p2) {
51170
51233
  }
51171
51234
  function isDir(p2) {
51172
51235
  try {
51173
- return fs32.statSync(p2).isDirectory();
51236
+ return fs33.statSync(p2).isDirectory();
51174
51237
  } catch {
51175
51238
  return false;
51176
51239
  }
51177
51240
  }
51178
51241
  function readdirSafe(p2) {
51179
51242
  try {
51180
- return fs32.readdirSync(p2);
51243
+ return fs33.readdirSync(p2);
51181
51244
  } catch {
51182
51245
  return [];
51183
51246
  }
51184
51247
  }
51185
51248
  function rmdirIfEmpty(p2) {
51186
51249
  try {
51187
- fs32.rmdirSync(p2);
51250
+ fs33.rmdirSync(p2);
51188
51251
  } catch {
51189
51252
  }
51190
51253
  }
51191
51254
 
51192
51255
  // src/transport/http-router.ts
51193
- var import_node_fs26 = __toESM(require("fs"), 1);
51194
- var import_node_path27 = __toESM(require("path"), 1);
51256
+ var import_node_fs27 = __toESM(require("fs"), 1);
51257
+ var import_node_path28 = __toESM(require("path"), 1);
51195
51258
 
51196
51259
  // src/attachment/mime.ts
51197
- var import_node_path24 = __toESM(require("path"), 1);
51260
+ var import_node_path25 = __toESM(require("path"), 1);
51198
51261
  var TEXT_PLAIN = "text/plain; charset=utf-8";
51199
51262
  var EXT_TO_NATIVE_MIME = {
51200
51263
  // 图片
@@ -51301,7 +51364,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
51301
51364
  ".mk"
51302
51365
  ]);
51303
51366
  function lookupMime(filePathOrName) {
51304
- const ext = import_node_path24.default.extname(filePathOrName).toLowerCase();
51367
+ const ext = import_node_path25.default.extname(filePathOrName).toLowerCase();
51305
51368
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
51306
51369
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
51307
51370
  return "application/octet-stream";
@@ -51370,8 +51433,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
51370
51433
  }
51371
51434
 
51372
51435
  // src/attachment/upload.ts
51373
- var import_node_fs25 = __toESM(require("fs"), 1);
51374
- var import_node_path25 = __toESM(require("path"), 1);
51436
+ var import_node_fs26 = __toESM(require("fs"), 1);
51437
+ var import_node_path26 = __toESM(require("path"), 1);
51375
51438
  var import_node_crypto8 = __toESM(require("crypto"), 1);
51376
51439
  var import_promises2 = require("stream/promises");
51377
51440
  var UploadError = class extends Error {
@@ -51383,22 +51446,22 @@ var UploadError = class extends Error {
51383
51446
  code;
51384
51447
  };
51385
51448
  function assertValidFileName(fileName) {
51386
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path25.default.basename(fileName)) {
51449
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path26.default.basename(fileName)) {
51387
51450
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
51388
51451
  }
51389
51452
  }
51390
51453
  var HASH_PREFIX_LEN = 16;
51391
51454
  async function writeUploadedAttachment(args) {
51392
51455
  assertValidFileName(args.fileName);
51393
- const attachmentsRoot = import_node_path25.default.join(args.sessionDir, ".attachments");
51456
+ const attachmentsRoot = import_node_path26.default.join(args.sessionDir, ".attachments");
51394
51457
  try {
51395
- import_node_fs25.default.mkdirSync(attachmentsRoot, { recursive: true });
51458
+ import_node_fs26.default.mkdirSync(attachmentsRoot, { recursive: true });
51396
51459
  } catch (err) {
51397
51460
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
51398
51461
  }
51399
51462
  const hasher = import_node_crypto8.default.createHash("sha256");
51400
51463
  let actualSize = 0;
51401
- const tmpPath = import_node_path25.default.join(
51464
+ const tmpPath = import_node_path26.default.join(
51402
51465
  attachmentsRoot,
51403
51466
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
51404
51467
  );
@@ -51413,18 +51476,18 @@ async function writeUploadedAttachment(args) {
51413
51476
  yield buf;
51414
51477
  }
51415
51478
  },
51416
- import_node_fs25.default.createWriteStream(tmpPath, { mode: 384 })
51479
+ import_node_fs26.default.createWriteStream(tmpPath, { mode: 384 })
51417
51480
  );
51418
51481
  } catch (err) {
51419
51482
  try {
51420
- import_node_fs25.default.unlinkSync(tmpPath);
51483
+ import_node_fs26.default.unlinkSync(tmpPath);
51421
51484
  } catch {
51422
51485
  }
51423
51486
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
51424
51487
  }
51425
51488
  if (actualSize !== args.contentLength) {
51426
51489
  try {
51427
- import_node_fs25.default.unlinkSync(tmpPath);
51490
+ import_node_fs26.default.unlinkSync(tmpPath);
51428
51491
  } catch {
51429
51492
  }
51430
51493
  throw new UploadError(
@@ -51433,35 +51496,35 @@ async function writeUploadedAttachment(args) {
51433
51496
  );
51434
51497
  }
51435
51498
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
51436
- const hashDir = import_node_path25.default.join(attachmentsRoot, attachmentId);
51499
+ const hashDir = import_node_path26.default.join(attachmentsRoot, attachmentId);
51437
51500
  let finalFileName;
51438
51501
  let hashDirExists = false;
51439
51502
  try {
51440
- hashDirExists = import_node_fs25.default.statSync(hashDir).isDirectory();
51503
+ hashDirExists = import_node_fs26.default.statSync(hashDir).isDirectory();
51441
51504
  } catch {
51442
51505
  }
51443
51506
  if (hashDirExists) {
51444
- const existing = import_node_fs25.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51507
+ const existing = import_node_fs26.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51445
51508
  finalFileName = existing[0] ?? args.fileName;
51446
51509
  try {
51447
- import_node_fs25.default.unlinkSync(tmpPath);
51510
+ import_node_fs26.default.unlinkSync(tmpPath);
51448
51511
  } catch {
51449
51512
  }
51450
51513
  } else {
51451
51514
  try {
51452
- import_node_fs25.default.mkdirSync(hashDir, { recursive: true });
51515
+ import_node_fs26.default.mkdirSync(hashDir, { recursive: true });
51453
51516
  finalFileName = args.fileName;
51454
- import_node_fs25.default.renameSync(tmpPath, import_node_path25.default.join(hashDir, finalFileName));
51517
+ import_node_fs26.default.renameSync(tmpPath, import_node_path26.default.join(hashDir, finalFileName));
51455
51518
  } catch (err) {
51456
51519
  try {
51457
- import_node_fs25.default.unlinkSync(tmpPath);
51520
+ import_node_fs26.default.unlinkSync(tmpPath);
51458
51521
  } catch {
51459
51522
  }
51460
51523
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
51461
51524
  }
51462
51525
  }
51463
- const absPath = import_node_path25.default.join(hashDir, finalFileName);
51464
- const relPath = import_node_path25.default.relative(args.sessionDir, absPath);
51526
+ const absPath = import_node_path26.default.join(hashDir, finalFileName);
51527
+ const relPath = import_node_path26.default.relative(args.sessionDir, absPath);
51465
51528
  args.groupFileStore.upsert(args.scope, args.sessionId, {
51466
51529
  relPath: absPath,
51467
51530
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -51475,7 +51538,7 @@ async function writeUploadedAttachment(args) {
51475
51538
 
51476
51539
  // src/extension/import.ts
51477
51540
  var import_promises3 = __toESM(require("fs/promises"), 1);
51478
- var import_node_path26 = __toESM(require("path"), 1);
51541
+ var import_node_path27 = __toESM(require("path"), 1);
51479
51542
  var import_node_os12 = __toESM(require("os"), 1);
51480
51543
  var import_jszip = __toESM(require_lib3(), 1);
51481
51544
  init_src();
@@ -51494,7 +51557,7 @@ async function importZip(buf, root) {
51494
51557
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
51495
51558
  }
51496
51559
  for (const name of Object.keys(zip.files)) {
51497
- if (name.includes("..") || name.startsWith("/") || import_node_path26.default.isAbsolute(name)) {
51560
+ if (name.includes("..") || name.startsWith("/") || import_node_path27.default.isAbsolute(name)) {
51498
51561
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
51499
51562
  }
51500
51563
  }
@@ -51527,7 +51590,7 @@ async function importZip(buf, root) {
51527
51590
  );
51528
51591
  }
51529
51592
  }
51530
- const destDir = import_node_path26.default.join(root, manifest.id);
51593
+ const destDir = import_node_path27.default.join(root, manifest.id);
51531
51594
  let destExists = false;
51532
51595
  try {
51533
51596
  await import_promises3.default.access(destDir);
@@ -51537,15 +51600,15 @@ async function importZip(buf, root) {
51537
51600
  if (destExists) {
51538
51601
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
51539
51602
  }
51540
- const stage = await import_promises3.default.mkdtemp(import_node_path26.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
51603
+ const stage = await import_promises3.default.mkdtemp(import_node_path27.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
51541
51604
  try {
51542
51605
  for (const [name, entry] of Object.entries(zip.files)) {
51543
- const dest = import_node_path26.default.join(stage, name);
51606
+ const dest = import_node_path27.default.join(stage, name);
51544
51607
  if (entry.dir) {
51545
51608
  await import_promises3.default.mkdir(dest, { recursive: true });
51546
51609
  continue;
51547
51610
  }
51548
- await import_promises3.default.mkdir(import_node_path26.default.dirname(dest), { recursive: true });
51611
+ await import_promises3.default.mkdir(import_node_path27.default.dirname(dest), { recursive: true });
51549
51612
  const content = await entry.async("nodebuffer");
51550
51613
  await import_promises3.default.writeFile(dest, content);
51551
51614
  }
@@ -51576,7 +51639,7 @@ var SHARE_UI_ASSET_MIME = {
51576
51639
  ".wasm": "application/wasm"
51577
51640
  };
51578
51641
  function shareUiAssetMime(filePath) {
51579
- const ext = import_node_path27.default.extname(filePath).toLowerCase();
51642
+ const ext = import_node_path28.default.extname(filePath).toLowerCase();
51580
51643
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
51581
51644
  }
51582
51645
  var DISPATCH_HEARTBEAT_MS = 25e3;
@@ -51663,7 +51726,7 @@ function isValidUploadFileName(fileName) {
51663
51726
  if (fileName === "." || fileName === "..") return false;
51664
51727
  if (fileName.startsWith(".")) return false;
51665
51728
  if (fileName.includes("/") || fileName.includes("\\")) return false;
51666
- return fileName === import_node_path27.default.basename(fileName);
51729
+ return fileName === import_node_path28.default.basename(fileName);
51667
51730
  }
51668
51731
  function createHttpRouter(deps) {
51669
51732
  return async (req, res) => {
@@ -51735,7 +51798,7 @@ function createHttpRouter(deps) {
51735
51798
  }
51736
51799
  let buf;
51737
51800
  try {
51738
- buf = await import_node_fs26.default.promises.readFile(abs);
51801
+ buf = await import_node_fs27.default.promises.readFile(abs);
51739
51802
  } catch {
51740
51803
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
51741
51804
  return true;
@@ -51959,7 +52022,7 @@ function createHttpRouter(deps) {
51959
52022
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
51960
52023
  return true;
51961
52024
  }
51962
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path27.default.basename(r.absPath)));
52025
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path28.default.basename(r.absPath)));
51963
52026
  return true;
51964
52027
  }
51965
52028
  const ctx = deps.authResolver.resolveFromHeader(
@@ -52080,7 +52143,7 @@ function createHttpRouter(deps) {
52080
52143
  return true;
52081
52144
  }
52082
52145
  let absPath;
52083
- if (import_node_path27.default.isAbsolute(pathParam)) {
52146
+ if (import_node_path28.default.isAbsolute(pathParam)) {
52084
52147
  absPath = pathParam;
52085
52148
  } else if (deps.sessionStore) {
52086
52149
  const file = deps.sessionStore.read(sid);
@@ -52088,7 +52151,7 @@ function createHttpRouter(deps) {
52088
52151
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
52089
52152
  return true;
52090
52153
  }
52091
- absPath = import_node_path27.default.join(file.cwd, pathParam);
52154
+ absPath = import_node_path28.default.join(file.cwd, pathParam);
52092
52155
  } else {
52093
52156
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
52094
52157
  return true;
@@ -52175,7 +52238,7 @@ function withCtx(ctx, body) {
52175
52238
  function streamFile(res, absPath, logger) {
52176
52239
  let stat;
52177
52240
  try {
52178
- stat = import_node_fs26.default.statSync(absPath);
52241
+ stat = import_node_fs27.default.statSync(absPath);
52179
52242
  } catch (err) {
52180
52243
  const code = err?.code;
52181
52244
  if (code === "ENOENT") {
@@ -52190,7 +52253,7 @@ function streamFile(res, absPath, logger) {
52190
52253
  return;
52191
52254
  }
52192
52255
  const mime = lookupMime(absPath);
52193
- const basename = import_node_path27.default.basename(absPath);
52256
+ const basename = import_node_path28.default.basename(absPath);
52194
52257
  res.writeHead(200, {
52195
52258
  "Content-Type": mime,
52196
52259
  "Content-Length": String(stat.size),
@@ -52198,7 +52261,7 @@ function streamFile(res, absPath, logger) {
52198
52261
  // 防止浏览器把任意 mime 当 html 渲染
52199
52262
  "X-Content-Type-Options": "nosniff"
52200
52263
  });
52201
- const stream = import_node_fs26.default.createReadStream(absPath);
52264
+ const stream = import_node_fs27.default.createReadStream(absPath);
52202
52265
  stream.on("error", (err) => {
52203
52266
  logger?.warn("streamFile read error", { absPath, err: err.message });
52204
52267
  res.destroy();
@@ -52207,8 +52270,8 @@ function streamFile(res, absPath, logger) {
52207
52270
  }
52208
52271
 
52209
52272
  // src/attachment/gc.ts
52210
- var import_node_fs27 = __toESM(require("fs"), 1);
52211
- var import_node_path28 = __toESM(require("path"), 1);
52273
+ var import_node_fs28 = __toESM(require("fs"), 1);
52274
+ var import_node_path29 = __toESM(require("path"), 1);
52212
52275
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
52213
52276
  function runAttachmentGc(args) {
52214
52277
  const now = (args.now ?? Date.now)();
@@ -52217,38 +52280,38 @@ function runAttachmentGc(args) {
52217
52280
  for (const { scope, sessionId } of args.sessionScopes) {
52218
52281
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
52219
52282
  if (entry.stale) continue;
52220
- if (import_node_path28.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52283
+ if (import_node_path29.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52221
52284
  }
52222
52285
  }
52223
52286
  for (const { scope, sessionId } of args.sessionScopes) {
52224
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path28.default.join(
52287
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path29.default.join(
52225
52288
  args.dataDir,
52226
52289
  "sessions",
52227
52290
  ...scopeSubPath(scope).map(safeFileName),
52228
52291
  safeFileName(sessionId)
52229
52292
  );
52230
- const attRoot = import_node_path28.default.join(sessionDir, ".attachments");
52293
+ const attRoot = import_node_path29.default.join(sessionDir, ".attachments");
52231
52294
  let hashDirs;
52232
52295
  try {
52233
- hashDirs = import_node_fs27.default.readdirSync(attRoot);
52296
+ hashDirs = import_node_fs28.default.readdirSync(attRoot);
52234
52297
  } catch (err) {
52235
52298
  if (err.code === "ENOENT") continue;
52236
52299
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
52237
52300
  continue;
52238
52301
  }
52239
52302
  for (const hashDir of hashDirs) {
52240
- const hashDirAbs = import_node_path28.default.join(attRoot, hashDir);
52303
+ const hashDirAbs = import_node_path29.default.join(attRoot, hashDir);
52241
52304
  let files;
52242
52305
  try {
52243
- files = import_node_fs27.default.readdirSync(hashDirAbs);
52306
+ files = import_node_fs28.default.readdirSync(hashDirAbs);
52244
52307
  } catch {
52245
52308
  continue;
52246
52309
  }
52247
52310
  for (const name of files) {
52248
- const file = import_node_path28.default.join(hashDirAbs, name);
52311
+ const file = import_node_path29.default.join(hashDirAbs, name);
52249
52312
  let stat;
52250
52313
  try {
52251
- stat = import_node_fs27.default.statSync(file);
52314
+ stat = import_node_fs28.default.statSync(file);
52252
52315
  } catch {
52253
52316
  continue;
52254
52317
  }
@@ -52257,26 +52320,26 @@ function runAttachmentGc(args) {
52257
52320
  if (age < ttlMs) continue;
52258
52321
  if (liveAbs.has(file)) continue;
52259
52322
  try {
52260
- import_node_fs27.default.unlinkSync(file);
52323
+ import_node_fs28.default.unlinkSync(file);
52261
52324
  } catch (err) {
52262
52325
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
52263
52326
  }
52264
52327
  }
52265
52328
  try {
52266
- if (import_node_fs27.default.readdirSync(hashDirAbs).length === 0) import_node_fs27.default.rmdirSync(hashDirAbs);
52329
+ if (import_node_fs28.default.readdirSync(hashDirAbs).length === 0) import_node_fs28.default.rmdirSync(hashDirAbs);
52267
52330
  } catch {
52268
52331
  }
52269
52332
  }
52270
52333
  try {
52271
- if (import_node_fs27.default.readdirSync(attRoot).length === 0) import_node_fs27.default.rmdirSync(attRoot);
52334
+ if (import_node_fs28.default.readdirSync(attRoot).length === 0) import_node_fs28.default.rmdirSync(attRoot);
52272
52335
  } catch {
52273
52336
  }
52274
52337
  }
52275
52338
  }
52276
52339
 
52277
52340
  // src/attachment/group.ts
52278
- var import_node_fs28 = __toESM(require("fs"), 1);
52279
- var import_node_path29 = __toESM(require("path"), 1);
52341
+ var import_node_fs29 = __toESM(require("fs"), 1);
52342
+ var import_node_path30 = __toESM(require("path"), 1);
52280
52343
  var import_node_crypto9 = __toESM(require("crypto"), 1);
52281
52344
  init_protocol();
52282
52345
  var GroupFileStore = class {
@@ -52288,11 +52351,11 @@ var GroupFileStore = class {
52288
52351
  this.logger = opts.logger;
52289
52352
  }
52290
52353
  rootForScope(scope) {
52291
- return import_node_path29.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
52354
+ return import_node_path30.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
52292
52355
  }
52293
52356
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
52294
52357
  filePath(scope, sessionId) {
52295
- return import_node_path29.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
52358
+ return import_node_path30.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
52296
52359
  }
52297
52360
  cacheKey(scope, sessionId) {
52298
52361
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -52301,7 +52364,7 @@ var GroupFileStore = class {
52301
52364
  readFile(scope, sessionId) {
52302
52365
  const file = this.filePath(scope, sessionId);
52303
52366
  try {
52304
- const raw = import_node_fs28.default.readFileSync(file, "utf8");
52367
+ const raw = import_node_fs29.default.readFileSync(file, "utf8");
52305
52368
  const parsed = JSON.parse(raw);
52306
52369
  if (!Array.isArray(parsed)) {
52307
52370
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -52327,10 +52390,10 @@ var GroupFileStore = class {
52327
52390
  }
52328
52391
  writeFile(scope, sessionId, entries) {
52329
52392
  const file = this.filePath(scope, sessionId);
52330
- import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
52393
+ import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(file), { recursive: true });
52331
52394
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
52332
- import_node_fs28.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52333
- import_node_fs28.default.renameSync(tmp, file);
52395
+ import_node_fs29.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52396
+ import_node_fs29.default.renameSync(tmp, file);
52334
52397
  }
52335
52398
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
52336
52399
  list(scope, sessionId) {
@@ -52416,10 +52479,10 @@ var GroupFileStore = class {
52416
52479
  };
52417
52480
 
52418
52481
  // src/discovery/state-file.ts
52419
- var import_node_fs29 = __toESM(require("fs"), 1);
52420
- var import_node_path30 = __toESM(require("path"), 1);
52482
+ var import_node_fs30 = __toESM(require("fs"), 1);
52483
+ var import_node_path31 = __toESM(require("path"), 1);
52421
52484
  function defaultStateFilePath(dataDir) {
52422
- return import_node_path30.default.join(dataDir, "state.json");
52485
+ return import_node_path31.default.join(dataDir, "state.json");
52423
52486
  }
52424
52487
  function isPidAlive(pid) {
52425
52488
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -52441,7 +52504,7 @@ var StateFileManager = class {
52441
52504
  }
52442
52505
  read() {
52443
52506
  try {
52444
- const raw = import_node_fs29.default.readFileSync(this.file, "utf8");
52507
+ const raw = import_node_fs30.default.readFileSync(this.file, "utf8");
52445
52508
  const parsed = JSON.parse(raw);
52446
52509
  return parsed;
52447
52510
  } catch {
@@ -52455,20 +52518,20 @@ var StateFileManager = class {
52455
52518
  return { status: "stale", existing };
52456
52519
  }
52457
52520
  write(state) {
52458
- import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
52521
+ import_node_fs30.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
52459
52522
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
52460
- import_node_fs29.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52461
- import_node_fs29.default.renameSync(tmp, this.file);
52523
+ import_node_fs30.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52524
+ import_node_fs30.default.renameSync(tmp, this.file);
52462
52525
  if (process.platform !== "win32") {
52463
52526
  try {
52464
- import_node_fs29.default.chmodSync(this.file, 384);
52527
+ import_node_fs30.default.chmodSync(this.file, 384);
52465
52528
  } catch {
52466
52529
  }
52467
52530
  }
52468
52531
  }
52469
52532
  delete() {
52470
52533
  try {
52471
- import_node_fs29.default.unlinkSync(this.file);
52534
+ import_node_fs30.default.unlinkSync(this.file);
52472
52535
  } catch {
52473
52536
  }
52474
52537
  }
@@ -52483,14 +52546,14 @@ function readDaemonSourceFromEnv(env = process.env) {
52483
52546
  }
52484
52547
 
52485
52548
  // src/tunnel/tunnel-manager.ts
52486
- var import_node_fs33 = __toESM(require("fs"), 1);
52487
- var import_node_path34 = __toESM(require("path"), 1);
52549
+ var import_node_fs34 = __toESM(require("fs"), 1);
52550
+ var import_node_path35 = __toESM(require("path"), 1);
52488
52551
  var import_node_crypto10 = __toESM(require("crypto"), 1);
52489
52552
  var import_node_child_process9 = require("child_process");
52490
52553
 
52491
52554
  // src/tunnel/tunnel-store.ts
52492
- var import_node_fs30 = __toESM(require("fs"), 1);
52493
- var import_node_path31 = __toESM(require("path"), 1);
52555
+ var import_node_fs31 = __toESM(require("fs"), 1);
52556
+ var import_node_path32 = __toESM(require("path"), 1);
52494
52557
  var TunnelStore = class {
52495
52558
  constructor(filePath) {
52496
52559
  this.filePath = filePath;
@@ -52498,7 +52561,7 @@ var TunnelStore = class {
52498
52561
  filePath;
52499
52562
  async get() {
52500
52563
  try {
52501
- const raw = await import_node_fs30.default.promises.readFile(this.filePath, "utf8");
52564
+ const raw = await import_node_fs31.default.promises.readFile(this.filePath, "utf8");
52502
52565
  const obj = JSON.parse(raw);
52503
52566
  if (!isPersistedTunnel(obj)) return null;
52504
52567
  return obj;
@@ -52509,22 +52572,22 @@ var TunnelStore = class {
52509
52572
  }
52510
52573
  }
52511
52574
  async set(v2) {
52512
- const dir = import_node_path31.default.dirname(this.filePath);
52513
- await import_node_fs30.default.promises.mkdir(dir, { recursive: true });
52575
+ const dir = import_node_path32.default.dirname(this.filePath);
52576
+ await import_node_fs31.default.promises.mkdir(dir, { recursive: true });
52514
52577
  const data = JSON.stringify(v2, null, 2);
52515
52578
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
52516
- await import_node_fs30.default.promises.writeFile(tmp, data, { mode: 384 });
52579
+ await import_node_fs31.default.promises.writeFile(tmp, data, { mode: 384 });
52517
52580
  if (process.platform !== "win32") {
52518
52581
  try {
52519
- await import_node_fs30.default.promises.chmod(tmp, 384);
52582
+ await import_node_fs31.default.promises.chmod(tmp, 384);
52520
52583
  } catch {
52521
52584
  }
52522
52585
  }
52523
- await import_node_fs30.default.promises.rename(tmp, this.filePath);
52586
+ await import_node_fs31.default.promises.rename(tmp, this.filePath);
52524
52587
  }
52525
52588
  async clear() {
52526
52589
  try {
52527
- await import_node_fs30.default.promises.unlink(this.filePath);
52590
+ await import_node_fs31.default.promises.unlink(this.filePath);
52528
52591
  } catch (err) {
52529
52592
  const code = err?.code;
52530
52593
  if (code !== "ENOENT") throw err;
@@ -52619,9 +52682,9 @@ function escape(v2) {
52619
52682
  }
52620
52683
 
52621
52684
  // src/tunnel/frpc-binary.ts
52622
- var import_node_fs31 = __toESM(require("fs"), 1);
52685
+ var import_node_fs32 = __toESM(require("fs"), 1);
52623
52686
  var import_node_os13 = __toESM(require("os"), 1);
52624
- var import_node_path32 = __toESM(require("path"), 1);
52687
+ var import_node_path33 = __toESM(require("path"), 1);
52625
52688
  var import_node_child_process7 = require("child_process");
52626
52689
  var import_node_stream3 = require("stream");
52627
52690
  var import_promises4 = require("stream/promises");
@@ -52653,20 +52716,20 @@ function frpcDownloadUrl(version2, p2) {
52653
52716
  }
52654
52717
  async function ensureFrpcBinary(opts) {
52655
52718
  if (opts.override) {
52656
- if (!import_node_fs31.default.existsSync(opts.override)) {
52719
+ if (!import_node_fs32.default.existsSync(opts.override)) {
52657
52720
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
52658
52721
  }
52659
52722
  return opts.override;
52660
52723
  }
52661
52724
  const version2 = opts.version ?? FRPC_VERSION;
52662
52725
  const platform = opts.platform ?? detectPlatform();
52663
- const binDir = import_node_path32.default.join(opts.dataDir, "bin");
52664
- import_node_fs31.default.mkdirSync(binDir, { recursive: true });
52726
+ const binDir = import_node_path33.default.join(opts.dataDir, "bin");
52727
+ import_node_fs32.default.mkdirSync(binDir, { recursive: true });
52665
52728
  cleanupStaleArtifacts(binDir);
52666
- const stableBin = import_node_path32.default.join(binDir, "frpc");
52667
- if (import_node_fs31.default.existsSync(stableBin)) return stableBin;
52729
+ const stableBin = import_node_path33.default.join(binDir, "frpc");
52730
+ if (import_node_fs32.default.existsSync(stableBin)) return stableBin;
52668
52731
  const partialBin = `${stableBin}.partial`;
52669
- const tarballPath = import_node_path32.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52732
+ const tarballPath = import_node_path33.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52670
52733
  try {
52671
52734
  const url = frpcDownloadUrl(version2, platform);
52672
52735
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -52675,8 +52738,8 @@ async function ensureFrpcBinary(opts) {
52675
52738
  } else {
52676
52739
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
52677
52740
  }
52678
- import_node_fs31.default.chmodSync(partialBin, 493);
52679
- import_node_fs31.default.renameSync(partialBin, stableBin);
52741
+ import_node_fs32.default.chmodSync(partialBin, 493);
52742
+ import_node_fs32.default.renameSync(partialBin, stableBin);
52680
52743
  } finally {
52681
52744
  safeUnlink(tarballPath);
52682
52745
  safeUnlink(partialBin);
@@ -52686,15 +52749,15 @@ async function ensureFrpcBinary(opts) {
52686
52749
  function cleanupStaleArtifacts(binDir) {
52687
52750
  let entries;
52688
52751
  try {
52689
- entries = import_node_fs31.default.readdirSync(binDir);
52752
+ entries = import_node_fs32.default.readdirSync(binDir);
52690
52753
  } catch {
52691
52754
  return;
52692
52755
  }
52693
52756
  for (const name of entries) {
52694
52757
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
52695
- const full = import_node_path32.default.join(binDir, name);
52758
+ const full = import_node_path33.default.join(binDir, name);
52696
52759
  try {
52697
- import_node_fs31.default.rmSync(full, { recursive: true, force: true });
52760
+ import_node_fs32.default.rmSync(full, { recursive: true, force: true });
52698
52761
  } catch {
52699
52762
  }
52700
52763
  }
@@ -52702,7 +52765,7 @@ function cleanupStaleArtifacts(binDir) {
52702
52765
  }
52703
52766
  function safeUnlink(p2) {
52704
52767
  try {
52705
- import_node_fs31.default.unlinkSync(p2);
52768
+ import_node_fs32.default.unlinkSync(p2);
52706
52769
  } catch {
52707
52770
  }
52708
52771
  }
@@ -52713,13 +52776,13 @@ async function downloadToFile(url, dest, fetchImpl) {
52713
52776
  if (!res.ok || !res.body) {
52714
52777
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
52715
52778
  }
52716
- const out = import_node_fs31.default.createWriteStream(dest);
52779
+ const out = import_node_fs32.default.createWriteStream(dest);
52717
52780
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
52718
52781
  await (0, import_promises4.pipeline)(nodeStream, out);
52719
52782
  }
52720
52783
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
52721
- const work = import_node_path32.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52722
- import_node_fs31.default.mkdirSync(work, { recursive: true });
52784
+ const work = import_node_path33.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52785
+ import_node_fs32.default.mkdirSync(work, { recursive: true });
52723
52786
  try {
52724
52787
  await new Promise((resolve6, reject) => {
52725
52788
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -52727,32 +52790,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
52727
52790
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
52728
52791
  });
52729
52792
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
52730
- const src = import_node_path32.default.join(work, dirName, "frpc");
52731
- if (!import_node_fs31.default.existsSync(src)) {
52793
+ const src = import_node_path33.default.join(work, dirName, "frpc");
52794
+ if (!import_node_fs32.default.existsSync(src)) {
52732
52795
  throw new Error(`frpc not found inside tarball at ${src}`);
52733
52796
  }
52734
- import_node_fs31.default.copyFileSync(src, destBin);
52797
+ import_node_fs32.default.copyFileSync(src, destBin);
52735
52798
  } finally {
52736
- import_node_fs31.default.rmSync(work, { recursive: true, force: true });
52799
+ import_node_fs32.default.rmSync(work, { recursive: true, force: true });
52737
52800
  }
52738
52801
  }
52739
52802
 
52740
52803
  // src/tunnel/frpc-process.ts
52741
- var import_node_fs32 = __toESM(require("fs"), 1);
52742
- var import_node_path33 = __toESM(require("path"), 1);
52804
+ var import_node_fs33 = __toESM(require("fs"), 1);
52805
+ var import_node_path34 = __toESM(require("path"), 1);
52743
52806
  var import_node_child_process8 = require("child_process");
52744
52807
  function frpcPidFilePath(dataDir) {
52745
- return import_node_path33.default.join(dataDir, "frpc.pid");
52808
+ return import_node_path34.default.join(dataDir, "frpc.pid");
52746
52809
  }
52747
52810
  function writeFrpcPid(dataDir, pid) {
52748
52811
  try {
52749
- import_node_fs32.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
52812
+ import_node_fs33.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
52750
52813
  } catch {
52751
52814
  }
52752
52815
  }
52753
52816
  function clearFrpcPid(dataDir) {
52754
52817
  try {
52755
- import_node_fs32.default.unlinkSync(frpcPidFilePath(dataDir));
52818
+ import_node_fs33.default.unlinkSync(frpcPidFilePath(dataDir));
52756
52819
  } catch {
52757
52820
  }
52758
52821
  }
@@ -52768,7 +52831,7 @@ function defaultIsPidAlive(pid) {
52768
52831
  }
52769
52832
  function defaultReadPidFile(file) {
52770
52833
  try {
52771
- return import_node_fs32.default.readFileSync(file, "utf8");
52834
+ return import_node_fs33.default.readFileSync(file, "utf8");
52772
52835
  } catch {
52773
52836
  return null;
52774
52837
  }
@@ -52784,7 +52847,7 @@ function defaultSleep(ms) {
52784
52847
  }
52785
52848
  async function killStaleFrpc(deps) {
52786
52849
  const pidFile = frpcPidFilePath(deps.dataDir);
52787
- const tomlPath = import_node_path33.default.join(deps.dataDir, "frpc.toml");
52850
+ const tomlPath = import_node_path34.default.join(deps.dataDir, "frpc.toml");
52788
52851
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
52789
52852
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
52790
52853
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -52808,7 +52871,7 @@ async function killStaleFrpc(deps) {
52808
52871
  }
52809
52872
  if (victims.size === 0) {
52810
52873
  try {
52811
- import_node_fs32.default.unlinkSync(pidFile);
52874
+ import_node_fs33.default.unlinkSync(pidFile);
52812
52875
  } catch {
52813
52876
  }
52814
52877
  return;
@@ -52819,7 +52882,7 @@ async function killStaleFrpc(deps) {
52819
52882
  }
52820
52883
  await sleep2(deps.reapWaitMs ?? 300);
52821
52884
  try {
52822
- import_node_fs32.default.unlinkSync(pidFile);
52885
+ import_node_fs33.default.unlinkSync(pidFile);
52823
52886
  } catch {
52824
52887
  }
52825
52888
  }
@@ -52856,7 +52919,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
52856
52919
  var TunnelManager = class {
52857
52920
  constructor(deps) {
52858
52921
  this.deps = deps;
52859
- this.store = deps.store ?? new TunnelStore(import_node_path34.default.join(deps.dataDir, "tunnel.json"));
52922
+ this.store = deps.store ?? new TunnelStore(import_node_path35.default.join(deps.dataDir, "tunnel.json"));
52860
52923
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
52861
52924
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
52862
52925
  }
@@ -52983,7 +53046,7 @@ var TunnelManager = class {
52983
53046
  dataDir: this.deps.dataDir,
52984
53047
  override: this.deps.frpcBinaryOverride ?? void 0
52985
53048
  });
52986
- const tomlPath = import_node_path34.default.join(this.deps.dataDir, "frpc.toml");
53049
+ const tomlPath = import_node_path35.default.join(this.deps.dataDir, "frpc.toml");
52987
53050
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
52988
53051
  const toml = buildFrpcToml({
52989
53052
  serverAddr: t.frpsHost,
@@ -52994,12 +53057,12 @@ var TunnelManager = class {
52994
53057
  localPort,
52995
53058
  logLevel: "info"
52996
53059
  });
52997
- await import_node_fs33.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53060
+ await import_node_fs34.default.promises.writeFile(tomlPath, toml, { mode: 384 });
52998
53061
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
52999
53062
  stdio: ["ignore", "pipe", "pipe"]
53000
53063
  });
53001
- const logFilePath = import_node_path34.default.join(this.deps.dataDir, "frpc.log");
53002
- const logStream = import_node_fs33.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53064
+ const logFilePath = import_node_path35.default.join(this.deps.dataDir, "frpc.log");
53065
+ const logStream = import_node_fs34.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53003
53066
  logStream.on("error", () => {
53004
53067
  });
53005
53068
  const tee = (chunk) => {
@@ -53081,8 +53144,8 @@ async function waitForFrpcReady(proc, timeoutMs) {
53081
53144
  }
53082
53145
 
53083
53146
  // src/sshd/sshd-manager.ts
53084
- var import_node_fs37 = __toESM(require("fs"), 1);
53085
- var import_node_path38 = __toESM(require("path"), 1);
53147
+ var import_node_fs38 = __toESM(require("fs"), 1);
53148
+ var import_node_path39 = __toESM(require("path"), 1);
53086
53149
  var import_node_child_process11 = require("child_process");
53087
53150
 
53088
53151
  // src/sshd/sshd-config.ts
@@ -53107,23 +53170,23 @@ function buildSshdConfig(input) {
53107
53170
  }
53108
53171
 
53109
53172
  // src/sshd/sshd-process.ts
53110
- var import_node_fs34 = __toESM(require("fs"), 1);
53111
- var import_node_path35 = __toESM(require("path"), 1);
53173
+ var import_node_fs35 = __toESM(require("fs"), 1);
53174
+ var import_node_path36 = __toESM(require("path"), 1);
53112
53175
  var import_node_child_process10 = require("child_process");
53113
53176
  function sshdPidFilePath(dataDir) {
53114
- return import_node_path35.default.join(dataDir, "sshd", "sshd.pid");
53177
+ return import_node_path36.default.join(dataDir, "sshd", "sshd.pid");
53115
53178
  }
53116
53179
  function writeSshdPid(dataDir, pid) {
53117
53180
  try {
53118
53181
  const p2 = sshdPidFilePath(dataDir);
53119
- import_node_fs34.default.mkdirSync(import_node_path35.default.dirname(p2), { recursive: true, mode: 448 });
53120
- import_node_fs34.default.writeFileSync(p2, String(pid), { mode: 384 });
53182
+ import_node_fs35.default.mkdirSync(import_node_path36.default.dirname(p2), { recursive: true, mode: 448 });
53183
+ import_node_fs35.default.writeFileSync(p2, String(pid), { mode: 384 });
53121
53184
  } catch {
53122
53185
  }
53123
53186
  }
53124
53187
  function clearSshdPid(dataDir) {
53125
53188
  try {
53126
- import_node_fs34.default.unlinkSync(sshdPidFilePath(dataDir));
53189
+ import_node_fs35.default.unlinkSync(sshdPidFilePath(dataDir));
53127
53190
  } catch {
53128
53191
  }
53129
53192
  }
@@ -53139,7 +53202,7 @@ function defaultIsPidAlive2(pid) {
53139
53202
  }
53140
53203
  function defaultReadPidFile2(file) {
53141
53204
  try {
53142
- return import_node_fs34.default.readFileSync(file, "utf8");
53205
+ return import_node_fs35.default.readFileSync(file, "utf8");
53143
53206
  } catch {
53144
53207
  return null;
53145
53208
  }
@@ -53155,7 +53218,7 @@ function defaultSleep2(ms) {
53155
53218
  }
53156
53219
  async function killStaleSshd(deps) {
53157
53220
  const pidFile = sshdPidFilePath(deps.dataDir);
53158
- const configPath = import_node_path35.default.join(deps.dataDir, "sshd", "sshd_config");
53221
+ const configPath = import_node_path36.default.join(deps.dataDir, "sshd", "sshd_config");
53159
53222
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile2;
53160
53223
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive2;
53161
53224
  const killPid = deps.killPidImpl ?? defaultKillPid2;
@@ -53179,7 +53242,7 @@ async function killStaleSshd(deps) {
53179
53242
  }
53180
53243
  if (victims.size === 0) {
53181
53244
  try {
53182
- import_node_fs34.default.unlinkSync(pidFile);
53245
+ import_node_fs35.default.unlinkSync(pidFile);
53183
53246
  } catch {
53184
53247
  }
53185
53248
  return;
@@ -53190,7 +53253,7 @@ async function killStaleSshd(deps) {
53190
53253
  }
53191
53254
  await sleep2(deps.reapWaitMs ?? 300);
53192
53255
  try {
53193
- import_node_fs34.default.unlinkSync(pidFile);
53256
+ import_node_fs35.default.unlinkSync(pidFile);
53194
53257
  } catch {
53195
53258
  }
53196
53259
  }
@@ -53223,8 +53286,8 @@ async function defaultScanSshdPidsByCmdline(configPath, logger) {
53223
53286
  }
53224
53287
 
53225
53288
  // src/sshd/jail-script.ts
53226
- var import_node_fs35 = __toESM(require("fs"), 1);
53227
- var import_node_path36 = __toESM(require("path"), 1);
53289
+ var import_node_fs36 = __toESM(require("fs"), 1);
53290
+ var import_node_path37 = __toESM(require("path"), 1);
53228
53291
  var CLAWD_SSH_JAIL_SCRIPT = String.raw`#!/usr/bin/env bash
53229
53292
  # clawd-ssh-jail — SSH reverse access sandbox wrapper (managed by clawd; do not edit)
53230
53293
  #
@@ -53358,16 +53421,16 @@ case "$(uname -s)" in
53358
53421
  esac
53359
53422
  `;
53360
53423
  function ensureJailScript(dataDir) {
53361
- const binDir = import_node_path36.default.join(dataDir, "bin");
53362
- import_node_fs35.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53363
- const target = import_node_path36.default.join(binDir, "clawd-ssh-jail");
53364
- import_node_fs35.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53424
+ const binDir = import_node_path37.default.join(dataDir, "bin");
53425
+ import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53426
+ const target = import_node_path37.default.join(binDir, "clawd-ssh-jail");
53427
+ import_node_fs36.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53365
53428
  return target;
53366
53429
  }
53367
53430
 
53368
53431
  // src/sshd/clawd-shim.ts
53369
- var import_node_fs36 = __toESM(require("fs"), 1);
53370
- var import_node_path37 = __toESM(require("path"), 1);
53432
+ var import_node_fs37 = __toESM(require("fs"), 1);
53433
+ var import_node_path38 = __toESM(require("path"), 1);
53371
53434
  function shellQuote(s) {
53372
53435
  return `'${s.replace(/'/g, "'\\''")}'`;
53373
53436
  }
@@ -53382,10 +53445,10 @@ exec ${shellQuote(execPath)} ${shellQuote(cliPath)} "$@"
53382
53445
  `;
53383
53446
  }
53384
53447
  function ensureClawdShim(dataDir, execPath, cliPath) {
53385
- const binDir = import_node_path37.default.join(dataDir, "bin");
53386
- import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53387
- const target = import_node_path37.default.join(binDir, "clawd");
53388
- import_node_fs36.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53448
+ const binDir = import_node_path38.default.join(dataDir, "bin");
53449
+ import_node_fs37.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53450
+ const target = import_node_path38.default.join(binDir, "clawd");
53451
+ import_node_fs37.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53389
53452
  return target;
53390
53453
  }
53391
53454
 
@@ -53393,7 +53456,7 @@ function ensureClawdShim(dataDir, execPath, cliPath) {
53393
53456
  var SshdManager = class {
53394
53457
  constructor(deps) {
53395
53458
  this.deps = deps;
53396
- this.sshdDir = import_node_path38.default.join(deps.dataDir, "sshd");
53459
+ this.sshdDir = import_node_path39.default.join(deps.dataDir, "sshd");
53397
53460
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
53398
53461
  }
53399
53462
  deps;
@@ -53412,32 +53475,32 @@ var SshdManager = class {
53412
53475
  ownPid: process.pid,
53413
53476
  logger
53414
53477
  });
53415
- import_node_fs37.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53416
- import_node_fs37.default.mkdirSync(import_node_path38.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53478
+ import_node_fs38.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53479
+ import_node_fs38.default.mkdirSync(import_node_path39.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53417
53480
  ensureJailScript(this.deps.dataDir);
53418
53481
  ensureClawdShim(this.deps.dataDir, process.execPath, process.argv[1] ?? "");
53419
- const hostKeyPath = import_node_path38.default.join(this.sshdDir, "host_key");
53420
- if (!import_node_fs37.default.existsSync(hostKeyPath)) {
53482
+ const hostKeyPath = import_node_path39.default.join(this.sshdDir, "host_key");
53483
+ if (!import_node_fs38.default.existsSync(hostKeyPath)) {
53421
53484
  await this.generateHostKey(hostKeyPath);
53422
53485
  }
53423
- const akFile = import_node_path38.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53424
- if (!import_node_fs37.default.existsSync(akFile)) {
53425
- import_node_fs37.default.writeFileSync(akFile, "", { mode: 384 });
53486
+ const akFile = import_node_path39.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53487
+ if (!import_node_fs38.default.existsSync(akFile)) {
53488
+ import_node_fs38.default.writeFileSync(akFile, "", { mode: 384 });
53426
53489
  }
53427
- const configPath = import_node_path38.default.join(this.sshdDir, "sshd_config");
53490
+ const configPath = import_node_path39.default.join(this.sshdDir, "sshd_config");
53428
53491
  const config = buildSshdConfig({
53429
53492
  listenAddress: "127.0.0.1",
53430
53493
  port: this.deps.port,
53431
53494
  hostKeyPath,
53432
53495
  authorizedKeysFile: akFile,
53433
- pidFilePath: import_node_path38.default.join(this.sshdDir, "sshd.pid")
53496
+ pidFilePath: import_node_path39.default.join(this.sshdDir, "sshd.pid")
53434
53497
  });
53435
- import_node_fs37.default.writeFileSync(configPath, config, { mode: 384 });
53498
+ import_node_fs38.default.writeFileSync(configPath, config, { mode: 384 });
53436
53499
  const sshdBin = this.deps.sshdBin ?? "/usr/sbin/sshd";
53437
53500
  const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
53438
53501
  stdio: ["ignore", "pipe", "pipe"]
53439
53502
  });
53440
- const logStream = import_node_fs37.default.createWriteStream(import_node_path38.default.join(this.sshdDir, "sshd.log"), {
53503
+ const logStream = import_node_fs38.default.createWriteStream(import_node_path39.default.join(this.sshdDir, "sshd.log"), {
53441
53504
  flags: "a",
53442
53505
  mode: 384
53443
53506
  });
@@ -53530,7 +53593,7 @@ ${tail}` : ready.error;
53530
53593
  p2.on("error", reject);
53531
53594
  });
53532
53595
  try {
53533
- import_node_fs37.default.chmodSync(hostKeyPath, 384);
53596
+ import_node_fs38.default.chmodSync(hostKeyPath, 384);
53534
53597
  } catch {
53535
53598
  }
53536
53599
  }
@@ -53573,17 +53636,17 @@ async function waitForSshdReady(proc, timeoutMs) {
53573
53636
  }
53574
53637
 
53575
53638
  // src/sshd/authorized-keys.ts
53576
- var import_node_fs38 = __toESM(require("fs"), 1);
53577
- var import_node_path39 = __toESM(require("path"), 1);
53639
+ var import_node_fs39 = __toESM(require("fs"), 1);
53640
+ var import_node_path40 = __toESM(require("path"), 1);
53578
53641
  var JAIL_BIN_PATH_ENV = "CLAWD_JAIL_BIN_PATH";
53579
53642
  var AUTHORIZED_KEYS_FILE = "clawd-contacts";
53580
53643
  function jailBinPath() {
53581
- return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path39.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53644
+ return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path40.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53582
53645
  }
53583
53646
  function rebuildAuthorizedKeys(store, sshdDir) {
53584
- const akDir = import_node_path39.default.join(sshdDir, "authorized_keys.d");
53585
- const target = import_node_path39.default.join(akDir, AUTHORIZED_KEYS_FILE);
53586
- import_node_fs38.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53647
+ const akDir = import_node_path40.default.join(sshdDir, "authorized_keys.d");
53648
+ const target = import_node_path40.default.join(akDir, AUTHORIZED_KEYS_FILE);
53649
+ import_node_fs39.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53587
53650
  const lines = ["# managed by clawd; do not edit", ""];
53588
53651
  for (const c of store.list()) {
53589
53652
  if (!c.sshAllowed) continue;
@@ -53597,28 +53660,28 @@ function rebuildAuthorizedKeys(store, sshdDir) {
53597
53660
  }
53598
53661
  const body = lines.join("\n") + "\n";
53599
53662
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
53600
- import_node_fs38.default.writeFileSync(tmp, body, { mode: 384 });
53601
- import_node_fs38.default.renameSync(tmp, target);
53663
+ import_node_fs39.default.writeFileSync(tmp, body, { mode: 384 });
53664
+ import_node_fs39.default.renameSync(tmp, target);
53602
53665
  }
53603
53666
  function readIssuedPubkey(sshdDir, deviceId) {
53604
53667
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53605
- const p2 = import_node_path39.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53668
+ const p2 = import_node_path40.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53606
53669
  try {
53607
- return import_node_fs38.default.readFileSync(p2, "utf8");
53670
+ return import_node_fs39.default.readFileSync(p2, "utf8");
53608
53671
  } catch {
53609
53672
  return null;
53610
53673
  }
53611
53674
  }
53612
53675
 
53613
53676
  // src/sshd/contact-key-puller.ts
53614
- var import_node_fs40 = __toESM(require("fs"), 1);
53615
- var import_node_path41 = __toESM(require("path"), 1);
53677
+ var import_node_fs41 = __toESM(require("fs"), 1);
53678
+ var import_node_path42 = __toESM(require("path"), 1);
53616
53679
  init_peer_forward();
53617
53680
  init_contact_ssh_log();
53618
53681
  var CONTACT_KEYS_DIR = "contact-ssh-keys";
53619
53682
  function safeContactKeyPath(dataDir, deviceId) {
53620
53683
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53621
- return import_node_path41.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53684
+ return import_node_path42.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53622
53685
  }
53623
53686
  async function pullContactSshKeyOnce(deps) {
53624
53687
  const forward = deps.forwardImpl ?? ((c) => forwardContactSshKeyIssueToPeer({
@@ -53684,12 +53747,12 @@ async function pullContactSshKeyOnce(deps) {
53684
53747
  }
53685
53748
  function writeKeyFile(dataDir, deviceId, pem) {
53686
53749
  const p2 = safeContactKeyPath(dataDir, deviceId);
53687
- import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(p2), { recursive: true, mode: 448 });
53688
- import_node_fs40.default.writeFileSync(p2, pem, { mode: 384 });
53750
+ import_node_fs41.default.mkdirSync(import_node_path42.default.dirname(p2), { recursive: true, mode: 448 });
53751
+ import_node_fs41.default.writeFileSync(p2, pem, { mode: 384 });
53689
53752
  }
53690
53753
  function removeKeyFile(dataDir, deviceId) {
53691
53754
  try {
53692
- import_node_fs40.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53755
+ import_node_fs41.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53693
53756
  return true;
53694
53757
  } catch {
53695
53758
  return false;
@@ -53839,27 +53902,27 @@ init_contact_ssh_log();
53839
53902
 
53840
53903
  // src/tunnel/device-key.ts
53841
53904
  var import_node_os14 = __toESM(require("os"), 1);
53842
- var import_node_path42 = __toESM(require("path"), 1);
53905
+ var import_node_path43 = __toESM(require("path"), 1);
53843
53906
  var import_node_crypto11 = __toESM(require("crypto"), 1);
53844
53907
  var DERIVE_SALT = "clawd-tunnel-device-v1";
53845
53908
  function deriveStableDeviceKey(opts = {}) {
53846
53909
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
53847
53910
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
53848
53911
  const home = opts.home ?? import_node_os14.default.homedir();
53849
- const defaultDataDir = import_node_path42.default.resolve(import_node_path42.default.join(home, ".clawd"));
53850
- const normalizedDataDir = opts.dataDir ? import_node_path42.default.resolve(opts.dataDir) : null;
53912
+ const defaultDataDir = import_node_path43.default.resolve(import_node_path43.default.join(home, ".clawd"));
53913
+ const normalizedDataDir = opts.dataDir ? import_node_path43.default.resolve(opts.dataDir) : null;
53851
53914
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
53852
53915
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
53853
53916
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
53854
53917
  }
53855
53918
 
53856
53919
  // src/auth-store.ts
53857
- var import_node_fs41 = __toESM(require("fs"), 1);
53858
- var import_node_path43 = __toESM(require("path"), 1);
53920
+ var import_node_fs42 = __toESM(require("fs"), 1);
53921
+ var import_node_path44 = __toESM(require("path"), 1);
53859
53922
  var import_node_crypto12 = __toESM(require("crypto"), 1);
53860
53923
  var AUTH_FILE_NAME = "auth.json";
53861
53924
  function authFilePath(dataDir) {
53862
- return import_node_path43.default.join(dataDir, AUTH_FILE_NAME);
53925
+ return import_node_path44.default.join(dataDir, AUTH_FILE_NAME);
53863
53926
  }
53864
53927
  function loadOrCreateAuthFile(opts) {
53865
53928
  const file = authFilePath(opts.dataDir);
@@ -53895,7 +53958,7 @@ function defaultGenerateOwnerPrincipalId() {
53895
53958
  }
53896
53959
  function readAuthFile(file) {
53897
53960
  try {
53898
- const raw = import_node_fs41.default.readFileSync(file, "utf8");
53961
+ const raw = import_node_fs42.default.readFileSync(file, "utf8");
53899
53962
  const parsed = JSON.parse(raw);
53900
53963
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
53901
53964
  return null;
@@ -53915,25 +53978,25 @@ function readAuthFile(file) {
53915
53978
  }
53916
53979
  }
53917
53980
  function writeAuthFile(file, content) {
53918
- import_node_fs41.default.mkdirSync(import_node_path43.default.dirname(file), { recursive: true });
53919
- import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53981
+ import_node_fs42.default.mkdirSync(import_node_path44.default.dirname(file), { recursive: true });
53982
+ import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53920
53983
  try {
53921
- import_node_fs41.default.chmodSync(file, 384);
53984
+ import_node_fs42.default.chmodSync(file, 384);
53922
53985
  } catch {
53923
53986
  }
53924
53987
  }
53925
53988
 
53926
53989
  // src/owner-profile.ts
53927
- var import_node_fs42 = __toESM(require("fs"), 1);
53990
+ var import_node_fs43 = __toESM(require("fs"), 1);
53928
53991
  var import_node_os15 = __toESM(require("os"), 1);
53929
- var import_node_path44 = __toESM(require("path"), 1);
53992
+ var import_node_path45 = __toESM(require("path"), 1);
53930
53993
  var PROFILE_FILENAME = "profile.json";
53931
53994
  function loadOwnerDisplayName(dataDir) {
53932
53995
  const fallback = import_node_os15.default.userInfo().username;
53933
- const profilePath = import_node_path44.default.join(dataDir, PROFILE_FILENAME);
53996
+ const profilePath = import_node_path45.default.join(dataDir, PROFILE_FILENAME);
53934
53997
  let raw;
53935
53998
  try {
53936
- raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
53999
+ raw = import_node_fs43.default.readFileSync(profilePath, "utf8");
53937
54000
  } catch {
53938
54001
  return fallback;
53939
54002
  }
@@ -53956,18 +54019,18 @@ function loadOwnerDisplayName(dataDir) {
53956
54019
  }
53957
54020
 
53958
54021
  // src/feishu-auth/owner-identity-store.ts
53959
- var import_node_fs43 = __toESM(require("fs"), 1);
53960
- var import_node_path45 = __toESM(require("path"), 1);
54022
+ var import_node_fs44 = __toESM(require("fs"), 1);
54023
+ var import_node_path46 = __toESM(require("path"), 1);
53961
54024
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
53962
54025
  var OwnerIdentityStore = class {
53963
54026
  file;
53964
54027
  constructor(dataDir) {
53965
- this.file = import_node_path45.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
54028
+ this.file = import_node_path46.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53966
54029
  }
53967
54030
  read() {
53968
54031
  let raw;
53969
54032
  try {
53970
- raw = import_node_fs43.default.readFileSync(this.file, "utf8");
54033
+ raw = import_node_fs44.default.readFileSync(this.file, "utf8");
53971
54034
  } catch {
53972
54035
  return null;
53973
54036
  }
@@ -53995,16 +54058,16 @@ var OwnerIdentityStore = class {
53995
54058
  };
53996
54059
  }
53997
54060
  write(record) {
53998
- import_node_fs43.default.mkdirSync(import_node_path45.default.dirname(this.file), { recursive: true });
53999
- import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
54061
+ import_node_fs44.default.mkdirSync(import_node_path46.default.dirname(this.file), { recursive: true });
54062
+ import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
54000
54063
  try {
54001
- import_node_fs43.default.chmodSync(this.file, 384);
54064
+ import_node_fs44.default.chmodSync(this.file, 384);
54002
54065
  } catch {
54003
54066
  }
54004
54067
  }
54005
54068
  clear() {
54006
54069
  try {
54007
- import_node_fs43.default.unlinkSync(this.file);
54070
+ import_node_fs44.default.unlinkSync(this.file);
54008
54071
  } catch (err) {
54009
54072
  const code = err?.code;
54010
54073
  if (code !== "ENOENT") throw err;
@@ -54125,9 +54188,9 @@ var CentralClientError = class extends Error {
54125
54188
  code;
54126
54189
  cause;
54127
54190
  };
54128
- async function centralRequest(opts, path77, init) {
54191
+ async function centralRequest(opts, path78, init) {
54129
54192
  const f = opts.fetchImpl ?? globalThis.fetch;
54130
- const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
54193
+ const url = `${opts.api.replace(/\/+$/, "")}${path78}`;
54131
54194
  const ctrl = new AbortController();
54132
54195
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54133
54196
  let res;
@@ -54269,8 +54332,8 @@ function verifyConnectToken(args) {
54269
54332
  }
54270
54333
 
54271
54334
  // src/feishu-auth/server-key.ts
54272
- var fs53 = __toESM(require("fs"), 1);
54273
- var path54 = __toESM(require("path"), 1);
54335
+ var fs54 = __toESM(require("fs"), 1);
54336
+ var path55 = __toESM(require("path"), 1);
54274
54337
  var FILE_NAME2 = "server-signing-key.json";
54275
54338
  var ServerKeyStore = class {
54276
54339
  constructor(dataDir) {
@@ -54278,12 +54341,12 @@ var ServerKeyStore = class {
54278
54341
  }
54279
54342
  dataDir;
54280
54343
  filePath() {
54281
- return path54.join(this.dataDir, FILE_NAME2);
54344
+ return path55.join(this.dataDir, FILE_NAME2);
54282
54345
  }
54283
54346
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54284
54347
  read() {
54285
54348
  try {
54286
- const raw = fs53.readFileSync(this.filePath(), "utf8");
54349
+ const raw = fs54.readFileSync(this.filePath(), "utf8");
54287
54350
  const parsed = JSON.parse(raw);
54288
54351
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54289
54352
  return parsed.publicKeyPem;
@@ -54298,12 +54361,12 @@ var ServerKeyStore = class {
54298
54361
  publicKeyPem,
54299
54362
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54300
54363
  };
54301
- fs53.mkdirSync(this.dataDir, { recursive: true });
54302
- fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54364
+ fs54.mkdirSync(this.dataDir, { recursive: true });
54365
+ fs54.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54303
54366
  }
54304
54367
  clear() {
54305
54368
  try {
54306
- fs53.unlinkSync(this.filePath());
54369
+ fs54.unlinkSync(this.filePath());
54307
54370
  } catch {
54308
54371
  }
54309
54372
  }
@@ -54316,12 +54379,12 @@ init_protocol();
54316
54379
  init_protocol();
54317
54380
 
54318
54381
  // src/session/fork.ts
54319
- var import_node_fs44 = __toESM(require("fs"), 1);
54382
+ var import_node_fs45 = __toESM(require("fs"), 1);
54320
54383
  var import_node_os16 = __toESM(require("os"), 1);
54321
- var import_node_path46 = __toESM(require("path"), 1);
54384
+ var import_node_path47 = __toESM(require("path"), 1);
54322
54385
  init_claude_history();
54323
54386
  function readJsonlEntries(file) {
54324
- const raw = import_node_fs44.default.readFileSync(file, "utf8");
54387
+ const raw = import_node_fs45.default.readFileSync(file, "utf8");
54325
54388
  const out = [];
54326
54389
  for (const line of raw.split("\n")) {
54327
54390
  const t = line.trim();
@@ -54334,10 +54397,10 @@ function readJsonlEntries(file) {
54334
54397
  return out;
54335
54398
  }
54336
54399
  function forkSession(input) {
54337
- const baseDir = input.baseDir ?? import_node_path46.default.join(import_node_os16.default.homedir(), ".claude");
54338
- const projectDir = import_node_path46.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54339
- const sourceFile = import_node_path46.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54340
- if (!import_node_fs44.default.existsSync(sourceFile)) {
54400
+ const baseDir = input.baseDir ?? import_node_path47.default.join(import_node_os16.default.homedir(), ".claude");
54401
+ const projectDir = import_node_path47.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54402
+ const sourceFile = import_node_path47.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54403
+ if (!import_node_fs45.default.existsSync(sourceFile)) {
54341
54404
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
54342
54405
  }
54343
54406
  const entries = readJsonlEntries(sourceFile);
@@ -54367,9 +54430,9 @@ function forkSession(input) {
54367
54430
  }
54368
54431
  forkedLines.push(JSON.stringify(forked));
54369
54432
  }
54370
- const forkedFilePath = import_node_path46.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54371
- import_node_fs44.default.mkdirSync(projectDir, { recursive: true });
54372
- import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54433
+ const forkedFilePath = import_node_path47.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54434
+ import_node_fs45.default.mkdirSync(projectDir, { recursive: true });
54435
+ import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54373
54436
  return { forkedToolSessionId, forkedFilePath };
54374
54437
  }
54375
54438
 
@@ -54721,7 +54784,7 @@ function buildPermissionHandlers(deps) {
54721
54784
  }
54722
54785
 
54723
54786
  // src/handlers/history.ts
54724
- var path57 = __toESM(require("path"), 1);
54787
+ var path58 = __toESM(require("path"), 1);
54725
54788
  init_protocol();
54726
54789
 
54727
54790
  // src/session/recent-dirs.ts
@@ -54739,7 +54802,7 @@ function listRecentDirs(store, limit = 50) {
54739
54802
  }
54740
54803
 
54741
54804
  // src/permission/persona-paths.ts
54742
- var path56 = __toESM(require("path"), 1);
54805
+ var path57 = __toESM(require("path"), 1);
54743
54806
  function getAllowedPersonaIds(grants, action) {
54744
54807
  const ids = /* @__PURE__ */ new Set();
54745
54808
  for (const g2 of grants) {
@@ -54752,42 +54815,42 @@ function getAllowedPersonaIds(grants, action) {
54752
54815
  return ids;
54753
54816
  }
54754
54817
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
54755
- const target = path56.resolve(absPath);
54818
+ const target = path57.resolve(absPath);
54756
54819
  if (userWorkDir) {
54757
- const u = path56.resolve(userWorkDir);
54758
- const usep = u.endsWith(path56.sep) ? "" : path56.sep;
54820
+ const u = path57.resolve(userWorkDir);
54821
+ const usep = u.endsWith(path57.sep) ? "" : path57.sep;
54759
54822
  if (target === u || target.startsWith(u + usep)) return true;
54760
54823
  }
54761
- const root = path56.resolve(personaRoot);
54762
- const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54824
+ const root = path57.resolve(personaRoot);
54825
+ const sep3 = root.endsWith(path57.sep) ? "" : path57.sep;
54763
54826
  if (!target.startsWith(root + sep3)) return false;
54764
- const rel = path56.relative(root, target);
54827
+ const rel = path57.relative(root, target);
54765
54828
  if (!rel || rel.startsWith("..")) return false;
54766
- const personaId = rel.split(path56.sep)[0];
54829
+ const personaId = rel.split(path57.sep)[0];
54767
54830
  if (!personaId) return false;
54768
54831
  const allowed = getAllowedPersonaIds(grants, action);
54769
54832
  if (allowed === "*") return true;
54770
54833
  return allowed.has(personaId);
54771
54834
  }
54772
54835
  function personaIdFromPath(absPath, personaRoot) {
54773
- const root = path56.resolve(personaRoot);
54774
- const target = path56.resolve(absPath);
54775
- const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54836
+ const root = path57.resolve(personaRoot);
54837
+ const target = path57.resolve(absPath);
54838
+ const sep3 = root.endsWith(path57.sep) ? "" : path57.sep;
54776
54839
  if (!target.startsWith(root + sep3)) return null;
54777
- const rel = path56.relative(root, target);
54840
+ const rel = path57.relative(root, target);
54778
54841
  if (!rel || rel.startsWith("..")) return null;
54779
- const id = rel.split(path56.sep)[0];
54842
+ const id = rel.split(path57.sep)[0];
54780
54843
  return id || null;
54781
54844
  }
54782
54845
  function isPathWithin(dir, absPath) {
54783
- const d = path56.resolve(dir);
54784
- const t = path56.resolve(absPath);
54785
- const sep3 = d.endsWith(path56.sep) ? "" : path56.sep;
54846
+ const d = path57.resolve(dir);
54847
+ const t = path57.resolve(absPath);
54848
+ const sep3 = d.endsWith(path57.sep) ? "" : path57.sep;
54786
54849
  return t === d || t.startsWith(d + sep3);
54787
54850
  }
54788
54851
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
54789
54852
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
54790
- return personaIdFromPath(path56.resolve(absPath), personaRoot) === personaId;
54853
+ return personaIdFromPath(path57.resolve(absPath), personaRoot) === personaId;
54791
54854
  }
54792
54855
 
54793
54856
  // src/handlers/history.ts
@@ -54813,7 +54876,7 @@ function buildHistoryHandlers(deps) {
54813
54876
  if (!pid) return false;
54814
54877
  return isGuestPathAllowed(
54815
54878
  ctx.grants,
54816
- path57.join(personaRoot, pid),
54879
+ path58.join(personaRoot, pid),
54817
54880
  personaRoot,
54818
54881
  "read",
54819
54882
  userWorkDir
@@ -54825,7 +54888,7 @@ function buildHistoryHandlers(deps) {
54825
54888
  };
54826
54889
  const list = async (frame, _client, ctx) => {
54827
54890
  const args = HistoryListArgs.parse(frame);
54828
- assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list");
54891
+ assertGuestPath(ctx, path58.resolve(args.projectPath), personaRoot, "history:list");
54829
54892
  const sessions = await history.listSessions(args);
54830
54893
  return { response: { type: "history:list", sessions } };
54831
54894
  };
@@ -54857,13 +54920,13 @@ function buildHistoryHandlers(deps) {
54857
54920
  };
54858
54921
  const subagents = async (frame, _client, ctx) => {
54859
54922
  const args = HistorySubagentsArgs.parse(frame);
54860
- assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54923
+ assertGuestPath(ctx, path58.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54861
54924
  const subs = await history.listSubagents(args);
54862
54925
  return { response: { type: "history:subagents", subagents: subs } };
54863
54926
  };
54864
54927
  const subagentRead = async (frame, _client, ctx) => {
54865
54928
  const args = HistorySubagentReadArgs.parse(frame);
54866
- assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54929
+ assertGuestPath(ctx, path58.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54867
54930
  const res = await history.readSubagent(args);
54868
54931
  return { response: { type: "history:subagent-read", ...res } };
54869
54932
  };
@@ -54872,7 +54935,7 @@ function buildHistoryHandlers(deps) {
54872
54935
  if (ctx?.principal.kind === "guest" && personaRoot) {
54873
54936
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54874
54937
  const filtered = dirs.filter(
54875
- (d) => isGuestPathAllowed(ctx.grants, path57.resolve(d.cwd), personaRoot, "read", userWorkDir)
54938
+ (d) => isGuestPathAllowed(ctx.grants, path58.resolve(d.cwd), personaRoot, "read", userWorkDir)
54876
54939
  );
54877
54940
  return { response: { type: "history:recentDirs", dirs: filtered } };
54878
54941
  }
@@ -54889,7 +54952,7 @@ function buildHistoryHandlers(deps) {
54889
54952
  }
54890
54953
 
54891
54954
  // src/handlers/workspace.ts
54892
- var path58 = __toESM(require("path"), 1);
54955
+ var path59 = __toESM(require("path"), 1);
54893
54956
  var os16 = __toESM(require("os"), 1);
54894
54957
  init_protocol();
54895
54958
  init_protocol();
@@ -54931,22 +54994,22 @@ function buildWorkspaceHandlers(deps) {
54931
54994
  const args = WorkspaceListArgs.parse(frame);
54932
54995
  const isGuest = ctx?.principal.kind === "guest";
54933
54996
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
54934
- const resolvedCwd = path58.resolve(args.cwd ?? fallbackCwd);
54935
- const target = args.path ? path58.resolve(resolvedCwd, args.path) : resolvedCwd;
54997
+ const resolvedCwd = path59.resolve(args.cwd ?? fallbackCwd);
54998
+ const target = args.path ? path59.resolve(resolvedCwd, args.path) : resolvedCwd;
54936
54999
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
54937
55000
  const res = workspace.list({ ...args, cwd: resolvedCwd });
54938
55001
  return { response: { type: "workspace:list", ...res } };
54939
55002
  };
54940
55003
  const read = async (frame, _client, ctx) => {
54941
55004
  const args = WorkspaceReadArgs.parse(frame);
54942
- const target = path58.isAbsolute(args.path) ? path58.resolve(args.path) : path58.resolve(args.cwd, args.path);
55005
+ const target = path59.isAbsolute(args.path) ? path59.resolve(args.path) : path59.resolve(args.cwd, args.path);
54943
55006
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
54944
55007
  const res = workspace.read(args);
54945
55008
  return { response: { type: "workspace:read", ...res } };
54946
55009
  };
54947
55010
  const skillsList = async (frame, _client, ctx) => {
54948
55011
  const args = SkillsListArgs.parse(frame);
54949
- const cwdAbs = path58.resolve(args.cwd);
55012
+ const cwdAbs = path59.resolve(args.cwd);
54950
55013
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
54951
55014
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
54952
55015
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -54958,7 +55021,7 @@ function buildWorkspaceHandlers(deps) {
54958
55021
  };
54959
55022
  const agentsList = async (frame, _client, ctx) => {
54960
55023
  const args = AgentsListArgs.parse(frame);
54961
- const cwdAbs = path58.resolve(args.cwd);
55024
+ const cwdAbs = path59.resolve(args.cwd);
54962
55025
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
54963
55026
  if (args.tool === "codex") {
54964
55027
  return { response: { type: "agents:list", agents: [] } };
@@ -54980,20 +55043,20 @@ function buildWorkspaceHandlers(deps) {
54980
55043
  }
54981
55044
 
54982
55045
  // src/handlers/git.ts
54983
- var path60 = __toESM(require("path"), 1);
55046
+ var path61 = __toESM(require("path"), 1);
54984
55047
  init_protocol();
54985
55048
  init_protocol();
54986
55049
 
54987
55050
  // src/workspace/git.ts
54988
55051
  var import_node_child_process12 = require("child_process");
54989
- var import_node_fs45 = __toESM(require("fs"), 1);
54990
- var import_node_path47 = __toESM(require("path"), 1);
55052
+ var import_node_fs46 = __toESM(require("fs"), 1);
55053
+ var import_node_path48 = __toESM(require("path"), 1);
54991
55054
  var import_node_util = require("util");
54992
55055
  var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
54993
55056
  function normalizePath(p2) {
54994
- const resolved = import_node_path47.default.resolve(p2);
55057
+ const resolved = import_node_path48.default.resolve(p2);
54995
55058
  try {
54996
- return import_node_fs45.default.realpathSync(resolved);
55059
+ return import_node_fs46.default.realpathSync(resolved);
54997
55060
  } catch {
54998
55061
  return resolved;
54999
55062
  }
@@ -55067,7 +55130,7 @@ async function listGitBranches(cwd) {
55067
55130
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
55068
55131
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
55069
55132
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
55070
- if (!isGuestPathAllowed(ctx.grants, path60.resolve(cwd), personaRoot, "read", userWorkDir)) {
55133
+ if (!isGuestPathAllowed(ctx.grants, path61.resolve(cwd), personaRoot, "read", userWorkDir)) {
55071
55134
  throw new ClawdError(
55072
55135
  ERROR_CODES.UNAUTHORIZED,
55073
55136
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -55408,22 +55471,22 @@ init_src();
55408
55471
  init_protocol();
55409
55472
 
55410
55473
  // src/sshd/key-issue.ts
55411
- var import_node_fs46 = __toESM(require("fs"), 1);
55412
- var import_node_path48 = __toESM(require("path"), 1);
55474
+ var import_node_fs47 = __toESM(require("fs"), 1);
55475
+ var import_node_path49 = __toESM(require("path"), 1);
55413
55476
  var import_node_child_process13 = require("child_process");
55414
55477
  function safeDeviceId(deviceId) {
55415
55478
  return deviceId.replace(/[\/\\]/g, "_");
55416
55479
  }
55417
55480
  async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55418
55481
  const safeId = safeDeviceId(deviceId);
55419
- const keysDir = import_node_path48.default.join(sshdDir, "keys");
55420
- import_node_fs46.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55421
- const privPath = import_node_path48.default.join(keysDir, `${safeId}.ed25519`);
55482
+ const keysDir = import_node_path49.default.join(sshdDir, "keys");
55483
+ import_node_fs47.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55484
+ const privPath = import_node_path49.default.join(keysDir, `${safeId}.ed25519`);
55422
55485
  const pubPath = `${privPath}.pub`;
55423
- if (import_node_fs46.default.existsSync(privPath) && import_node_fs46.default.existsSync(pubPath)) {
55486
+ if (import_node_fs47.default.existsSync(privPath) && import_node_fs47.default.existsSync(pubPath)) {
55424
55487
  return {
55425
- privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55426
- publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55488
+ privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55489
+ publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
55427
55490
  };
55428
55491
  }
55429
55492
  const bin = opts.keygenBin ?? "/usr/bin/ssh-keygen";
@@ -55437,16 +55500,16 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55437
55500
  p2.on("error", reject);
55438
55501
  });
55439
55502
  try {
55440
- import_node_fs46.default.chmodSync(privPath, 384);
55503
+ import_node_fs47.default.chmodSync(privPath, 384);
55441
55504
  } catch {
55442
55505
  }
55443
55506
  try {
55444
- import_node_fs46.default.chmodSync(pubPath, 420);
55507
+ import_node_fs47.default.chmodSync(pubPath, 420);
55445
55508
  } catch {
55446
55509
  }
55447
55510
  return {
55448
- privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55449
- publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55511
+ privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55512
+ publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
55450
55513
  };
55451
55514
  }
55452
55515
 
@@ -55866,7 +55929,7 @@ function buildPersonaHandlers(deps) {
55866
55929
  }
55867
55930
 
55868
55931
  // src/handlers/attachment.ts
55869
- var import_node_path49 = __toESM(require("path"), 1);
55932
+ var import_node_path50 = __toESM(require("path"), 1);
55870
55933
  init_protocol();
55871
55934
  init_protocol();
55872
55935
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -55946,12 +56009,12 @@ function buildAttachmentHandlers(deps) {
55946
56009
  `session ${args.sessionId} scope unresolved`
55947
56010
  );
55948
56011
  }
55949
- const cwdAbs = import_node_path49.default.resolve(sessionFile.cwd);
55950
- const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
56012
+ const cwdAbs = import_node_path50.default.resolve(sessionFile.cwd);
56013
+ const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
55951
56014
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
55952
56015
  const entries = deps.groupFileStore.list(scope, args.sessionId);
55953
56016
  const entry = entries.find((e) => {
55954
- const storedAbs = import_node_path49.default.isAbsolute(e.relPath) ? import_node_path49.default.resolve(e.relPath) : import_node_path49.default.resolve(cwdAbs, e.relPath);
56017
+ const storedAbs = import_node_path50.default.isAbsolute(e.relPath) ? import_node_path50.default.resolve(e.relPath) : import_node_path50.default.resolve(cwdAbs, e.relPath);
55955
56018
  return storedAbs === candidateAbs && !e.stale;
55956
56019
  });
55957
56020
  if (!entry) {
@@ -55976,7 +56039,7 @@ function buildAttachmentHandlers(deps) {
55976
56039
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
55977
56040
  const f = deps.sessionStore.read(sessionId);
55978
56041
  if (!f) return;
55979
- assertGuestAttachmentPath(ctx, import_node_path49.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
56042
+ assertGuestAttachmentPath(ctx, import_node_path50.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55980
56043
  }
55981
56044
  const groupAdd = async (frame, _client, ctx) => {
55982
56045
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -55991,8 +56054,8 @@ function buildAttachmentHandlers(deps) {
55991
56054
  if (!scope) {
55992
56055
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
55993
56056
  }
55994
- const cwdAbs = import_node_path49.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55995
- const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
56057
+ const cwdAbs = import_node_path50.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
56058
+ const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
55996
56059
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
55997
56060
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
55998
56061
  const size = 0;
@@ -56051,20 +56114,20 @@ function buildAttachmentHandlers(deps) {
56051
56114
 
56052
56115
  // src/handlers/extension.ts
56053
56116
  var import_promises8 = __toESM(require("fs/promises"), 1);
56054
- var import_node_path54 = __toESM(require("path"), 1);
56117
+ var import_node_path55 = __toESM(require("path"), 1);
56055
56118
  init_protocol();
56056
56119
  init_src();
56057
56120
 
56058
56121
  // src/extension/bundle-zip.ts
56059
56122
  var import_promises5 = __toESM(require("fs/promises"), 1);
56060
- var import_node_path50 = __toESM(require("path"), 1);
56123
+ var import_node_path51 = __toESM(require("path"), 1);
56061
56124
  var import_node_crypto14 = __toESM(require("crypto"), 1);
56062
56125
  var import_jszip2 = __toESM(require_lib3(), 1);
56063
56126
  async function bundleExtensionDir(dir) {
56064
56127
  const entries = await listFilesSorted(dir);
56065
56128
  const zip = new import_jszip2.default();
56066
56129
  for (const rel of entries) {
56067
- const abs = import_node_path50.default.join(dir, rel);
56130
+ const abs = import_node_path51.default.join(dir, rel);
56068
56131
  const content = await import_promises5.default.readFile(abs);
56069
56132
  zip.file(rel, content, { date: FIXED_DATE });
56070
56133
  }
@@ -56085,7 +56148,7 @@ async function listFilesSorted(rootDir) {
56085
56148
  return out;
56086
56149
  }
56087
56150
  async function walk(absRoot, relPrefix, out) {
56088
- const dirAbs = import_node_path50.default.join(absRoot, relPrefix);
56151
+ const dirAbs = import_node_path51.default.join(absRoot, relPrefix);
56089
56152
  const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
56090
56153
  for (const e of entries) {
56091
56154
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -56141,7 +56204,7 @@ function computePublishCheck(args) {
56141
56204
 
56142
56205
  // src/extension/install-flow.ts
56143
56206
  var import_promises6 = __toESM(require("fs/promises"), 1);
56144
- var import_node_path52 = __toESM(require("path"), 1);
56207
+ var import_node_path53 = __toESM(require("path"), 1);
56145
56208
  var import_node_os19 = __toESM(require("os"), 1);
56146
56209
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56147
56210
  var import_jszip3 = __toESM(require_lib3(), 1);
@@ -56149,19 +56212,19 @@ init_src();
56149
56212
 
56150
56213
  // src/extension/paths.ts
56151
56214
  var import_node_os18 = __toESM(require("os"), 1);
56152
- var import_node_path51 = __toESM(require("path"), 1);
56215
+ var import_node_path52 = __toESM(require("path"), 1);
56153
56216
  init_src();
56154
56217
  function clawdHomeRoot(override) {
56155
- return override ?? process.env.CLAWD_HOME ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".clawd");
56218
+ return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
56156
56219
  }
56157
56220
  function extensionsRoot(override) {
56158
- return import_node_path51.default.join(clawdHomeRoot(override), "extensions");
56221
+ return import_node_path52.default.join(clawdHomeRoot(override), "extensions");
56159
56222
  }
56160
56223
  function publishedChannelsFile(override) {
56161
- return import_node_path51.default.join(clawdHomeRoot(override), "extensions-published.json");
56224
+ return import_node_path52.default.join(clawdHomeRoot(override), "extensions-published.json");
56162
56225
  }
56163
56226
  function bundleCacheRoot(override) {
56164
- return import_node_path51.default.join(clawdHomeRoot(override), "extension-bundles");
56227
+ return import_node_path52.default.join(clawdHomeRoot(override), "extension-bundles");
56165
56228
  }
56166
56229
 
56167
56230
  // src/extension/install-flow.ts
@@ -56188,7 +56251,7 @@ async function installFromChannel(args, deps) {
56188
56251
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56189
56252
  }
56190
56253
  for (const name of Object.keys(zip.files)) {
56191
- if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56254
+ if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56192
56255
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56193
56256
  }
56194
56257
  }
@@ -56220,7 +56283,7 @@ async function installFromChannel(args, deps) {
56220
56283
  );
56221
56284
  }
56222
56285
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
56223
- const destDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56286
+ const destDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56224
56287
  let destExists = false;
56225
56288
  try {
56226
56289
  await import_promises6.default.access(destDir);
@@ -56234,16 +56297,16 @@ async function installFromChannel(args, deps) {
56234
56297
  );
56235
56298
  }
56236
56299
  const stage = await import_promises6.default.mkdtemp(
56237
- import_node_path52.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56300
+ import_node_path53.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56238
56301
  );
56239
56302
  try {
56240
56303
  for (const [name, entry] of Object.entries(zip.files)) {
56241
- const dest = import_node_path52.default.join(stage, name);
56304
+ const dest = import_node_path53.default.join(stage, name);
56242
56305
  if (entry.dir) {
56243
56306
  await import_promises6.default.mkdir(dest, { recursive: true });
56244
56307
  continue;
56245
56308
  }
56246
- await import_promises6.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56309
+ await import_promises6.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56247
56310
  if (name === "manifest.json") {
56248
56311
  const rewritten = { ...parsed.data, id: localExtId };
56249
56312
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56264,7 +56327,7 @@ async function installFromChannel(args, deps) {
56264
56327
 
56265
56328
  // src/extension/update-flow.ts
56266
56329
  var import_promises7 = __toESM(require("fs/promises"), 1);
56267
- var import_node_path53 = __toESM(require("path"), 1);
56330
+ var import_node_path54 = __toESM(require("path"), 1);
56268
56331
  var import_node_os20 = __toESM(require("os"), 1);
56269
56332
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56270
56333
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -56282,11 +56345,11 @@ async function updateFromChannel(args, deps) {
56282
56345
  channelRef.extId,
56283
56346
  channelRef.ownerPrincipalId
56284
56347
  );
56285
- const liveDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56348
+ const liveDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
56286
56349
  const prevDir = `${liveDir}.prev`;
56287
56350
  let existingVersion;
56288
56351
  try {
56289
- const raw = await import_promises7.default.readFile(import_node_path53.default.join(liveDir, "manifest.json"), "utf8");
56352
+ const raw = await import_promises7.default.readFile(import_node_path54.default.join(liveDir, "manifest.json"), "utf8");
56290
56353
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
56291
56354
  if (!parsed2.success) {
56292
56355
  throw new UpdateError(
@@ -56319,7 +56382,7 @@ async function updateFromChannel(args, deps) {
56319
56382
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56320
56383
  }
56321
56384
  for (const name of Object.keys(zip.files)) {
56322
- if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56385
+ if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
56323
56386
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56324
56387
  }
56325
56388
  }
@@ -56354,16 +56417,16 @@ async function updateFromChannel(args, deps) {
56354
56417
  await import_promises7.default.rm(prevDir, { recursive: true, force: true });
56355
56418
  await import_promises7.default.rename(liveDir, prevDir);
56356
56419
  const stage = await import_promises7.default.mkdtemp(
56357
- import_node_path53.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56420
+ import_node_path54.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56358
56421
  );
56359
56422
  try {
56360
56423
  for (const [name, entry] of Object.entries(zip.files)) {
56361
- const dest = import_node_path53.default.join(stage, name);
56424
+ const dest = import_node_path54.default.join(stage, name);
56362
56425
  if (entry.dir) {
56363
56426
  await import_promises7.default.mkdir(dest, { recursive: true });
56364
56427
  continue;
56365
56428
  }
56366
- await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56429
+ await import_promises7.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
56367
56430
  if (name === "manifest.json") {
56368
56431
  const rewritten = { ...parsed.data, id: localExtId };
56369
56432
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56457,7 +56520,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56457
56520
  );
56458
56521
  }
56459
56522
  }
56460
- const manifestPath = import_node_path54.default.join(root, extId, "manifest.json");
56523
+ const manifestPath = import_node_path55.default.join(root, extId, "manifest.json");
56461
56524
  const manifest = await readManifest(root, extId);
56462
56525
  const next = { ...manifest, version: newVersion };
56463
56526
  const tmp = `${manifestPath}.tmp`;
@@ -56465,7 +56528,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56465
56528
  await import_promises8.default.rename(tmp, manifestPath);
56466
56529
  }
56467
56530
  async function readManifest(root, extId) {
56468
- const file = import_node_path54.default.join(root, extId, "manifest.json");
56531
+ const file = import_node_path55.default.join(root, extId, "manifest.json");
56469
56532
  let raw;
56470
56533
  try {
56471
56534
  raw = await import_promises8.default.readFile(file, "utf8");
@@ -56556,7 +56619,7 @@ function buildExtensionHandlers(deps) {
56556
56619
  };
56557
56620
  async function buildSnapshotMeta(extId) {
56558
56621
  const manifest = await readManifest(deps.root, extId);
56559
- const { sha256, buffer } = await bundleExtensionDir(import_node_path54.default.join(deps.root, extId));
56622
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path55.default.join(deps.root, extId));
56560
56623
  return { manifest, contentHash: sha256, buffer };
56561
56624
  }
56562
56625
  const publish = async (frame, _client, ctx) => {
@@ -56737,9 +56800,9 @@ function buildExtensionHandlers(deps) {
56737
56800
  }
56738
56801
 
56739
56802
  // src/app-builder/project-store.ts
56740
- var import_node_fs47 = require("fs");
56803
+ var import_node_fs48 = require("fs");
56741
56804
  var import_node_child_process14 = require("child_process");
56742
- var import_node_path55 = require("path");
56805
+ var import_node_path56 = require("path");
56743
56806
  init_protocol();
56744
56807
  var PROJECTS_DIR = "projects";
56745
56808
  var META_FILE = ".clawd-project.json";
@@ -56753,19 +56816,19 @@ var ProjectStore = class {
56753
56816
  root;
56754
56817
  /** projects/<name>/.clawd-project.json 路径 */
56755
56818
  metaPath(name) {
56756
- return (0, import_node_path55.join)(this.projectsRoot(), name, META_FILE);
56819
+ return (0, import_node_path56.join)(this.projectsRoot(), name, META_FILE);
56757
56820
  }
56758
56821
  /** projects/<name>/ 目录路径(cwd 用) */
56759
56822
  projectDir(name) {
56760
- return (0, import_node_path55.join)(this.projectsRoot(), name);
56823
+ return (0, import_node_path56.join)(this.projectsRoot(), name);
56761
56824
  }
56762
56825
  projectsRoot() {
56763
- return (0, import_node_path55.join)(this.root, PROJECTS_DIR);
56826
+ return (0, import_node_path56.join)(this.root, PROJECTS_DIR);
56764
56827
  }
56765
56828
  async list() {
56766
56829
  let entries;
56767
56830
  try {
56768
- entries = await import_node_fs47.promises.readdir(this.projectsRoot());
56831
+ entries = await import_node_fs48.promises.readdir(this.projectsRoot());
56769
56832
  } catch (err) {
56770
56833
  if (err.code === "ENOENT") return [];
56771
56834
  throw err;
@@ -56773,7 +56836,7 @@ var ProjectStore = class {
56773
56836
  const out = [];
56774
56837
  for (const name of entries) {
56775
56838
  try {
56776
- const raw = await import_node_fs47.promises.readFile(this.metaPath(name), "utf8");
56839
+ const raw = await import_node_fs48.promises.readFile(this.metaPath(name), "utf8");
56777
56840
  const json = JSON.parse(raw);
56778
56841
  let migrated = false;
56779
56842
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -56784,7 +56847,7 @@ var ProjectStore = class {
56784
56847
  if (parsed.success) {
56785
56848
  out.push(parsed.data);
56786
56849
  if (migrated) {
56787
- void import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56850
+ void import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56788
56851
  });
56789
56852
  }
56790
56853
  }
@@ -56828,8 +56891,8 @@ var ProjectStore = class {
56828
56891
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
56829
56892
  }
56830
56893
  const dir = this.projectDir(name);
56831
- await import_node_fs47.promises.mkdir(dir, { recursive: true });
56832
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56894
+ await import_node_fs48.promises.mkdir(dir, { recursive: true });
56895
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56833
56896
  return meta;
56834
56897
  }
56835
56898
  /**
@@ -56872,7 +56935,7 @@ var ProjectStore = class {
56872
56935
  }
56873
56936
  async delete(name) {
56874
56937
  const dir = this.projectDir(name);
56875
- await import_node_fs47.promises.rm(dir, { recursive: true, force: true });
56938
+ await import_node_fs48.promises.rm(dir, { recursive: true, force: true });
56876
56939
  }
56877
56940
  async updatePort(name, newPort) {
56878
56941
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -56888,7 +56951,7 @@ var ProjectStore = class {
56888
56951
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
56889
56952
  }
56890
56953
  const updated = { ...target, port: newPort };
56891
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56954
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56892
56955
  return updated;
56893
56956
  }
56894
56957
  /**
@@ -56905,7 +56968,7 @@ var ProjectStore = class {
56905
56968
  if (!validated.success) {
56906
56969
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
56907
56970
  }
56908
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56971
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56909
56972
  return validated.data;
56910
56973
  }
56911
56974
  /**
@@ -56926,7 +56989,7 @@ var ProjectStore = class {
56926
56989
  if (!validated.success) {
56927
56990
  throw new Error(`invalid publishJob: ${validated.error.message}`);
56928
56991
  }
56929
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56992
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56930
56993
  return validated.data;
56931
56994
  }
56932
56995
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -56941,7 +57004,7 @@ var ProjectStore = class {
56941
57004
  if (!validated.success) {
56942
57005
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
56943
57006
  }
56944
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57007
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56945
57008
  return validated.data;
56946
57009
  }
56947
57010
  };
@@ -57062,8 +57125,8 @@ var PublishJobRegistry = class {
57062
57125
 
57063
57126
  // src/app-builder/publish-job-runner.ts
57064
57127
  var import_node_child_process16 = require("child_process");
57065
- var import_node_fs48 = require("fs");
57066
- var import_node_path56 = require("path");
57128
+ var import_node_fs49 = require("fs");
57129
+ var import_node_path57 = require("path");
57067
57130
 
57068
57131
  // src/app-builder/publish-stage-parser.ts
57069
57132
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -57095,10 +57158,10 @@ async function startPublishJob(deps, args) {
57095
57158
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
57096
57159
  }
57097
57160
  const projDir = projectDir(args.name);
57098
- const logPath = (0, import_node_path56.join)(projDir, ".publish.log");
57161
+ const logPath = (0, import_node_path57.join)(projDir, ".publish.log");
57099
57162
  let logStream = null;
57100
57163
  try {
57101
- logStream = (0, import_node_fs48.createWriteStream)(logPath, { flags: "w" });
57164
+ logStream = (0, import_node_fs49.createWriteStream)(logPath, { flags: "w" });
57102
57165
  } catch {
57103
57166
  logStream = null;
57104
57167
  }
@@ -57355,8 +57418,8 @@ async function recoverInterruptedJobs(deps) {
57355
57418
 
57356
57419
  // src/handlers/app-builder.ts
57357
57420
  init_protocol();
57358
- var import_node_path57 = require("path");
57359
- var import_node_fs49 = require("fs");
57421
+ var import_node_path58 = require("path");
57422
+ var import_node_fs50 = require("fs");
57360
57423
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57361
57424
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57362
57425
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57437,7 +57500,7 @@ function buildAppBuilderHandlers(deps) {
57437
57500
  async function listAllUsersProjects() {
57438
57501
  if (!deps.usersRoot || !deps.getStore) return [];
57439
57502
  const getStore = deps.getStore;
57440
- const userIds = await import_node_fs49.promises.readdir(deps.usersRoot).catch(() => []);
57503
+ const userIds = await import_node_fs50.promises.readdir(deps.usersRoot).catch(() => []);
57441
57504
  const perUser = await Promise.all(
57442
57505
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57443
57506
  );
@@ -57513,8 +57576,8 @@ function buildAppBuilderHandlers(deps) {
57513
57576
  const project = await userStore.create(f.name, reservedPorts);
57514
57577
  try {
57515
57578
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
57516
- const templateSrcDir = (0, import_node_path57.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57517
- const scaffoldScript = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57579
+ const templateSrcDir = (0, import_node_path58.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57580
+ const scaffoldScript = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57518
57581
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
57519
57582
  deps.logger?.info("app-builder.scaffold.done", {
57520
57583
  name: project.name,
@@ -57735,7 +57798,7 @@ function buildAppBuilderHandlers(deps) {
57735
57798
  await userStore.clearPublishJob(args.name);
57736
57799
  }
57737
57800
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
57738
- const scriptPath = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "publish.sh");
57801
+ const scriptPath = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "publish.sh");
57739
57802
  deps.logger?.info("app-builder.publish.start", {
57740
57803
  name: args.name,
57741
57804
  sessionId: boundSession.sessionId,
@@ -57904,7 +57967,7 @@ function buildVisitorHandlers(deps) {
57904
57967
 
57905
57968
  // src/extension/registry.ts
57906
57969
  var import_promises9 = __toESM(require("fs/promises"), 1);
57907
- var import_node_path58 = __toESM(require("path"), 1);
57970
+ var import_node_path59 = __toESM(require("path"), 1);
57908
57971
  init_src();
57909
57972
  async function loadAll(root) {
57910
57973
  let entries;
@@ -57918,13 +57981,13 @@ async function loadAll(root) {
57918
57981
  for (const ent of entries) {
57919
57982
  if (!ent.isDirectory()) continue;
57920
57983
  if (ent.name.startsWith(".")) continue;
57921
- records.push(await loadOne(import_node_path58.default.join(root, ent.name), ent.name));
57984
+ records.push(await loadOne(import_node_path59.default.join(root, ent.name), ent.name));
57922
57985
  }
57923
57986
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
57924
57987
  return records;
57925
57988
  }
57926
57989
  async function loadOne(dir, dirName) {
57927
- const manifestPath = import_node_path58.default.join(dir, "manifest.json");
57990
+ const manifestPath = import_node_path59.default.join(dir, "manifest.json");
57928
57991
  let raw;
57929
57992
  try {
57930
57993
  raw = await import_promises9.default.readFile(manifestPath, "utf8");
@@ -57969,7 +58032,7 @@ async function loadOne(dir, dirName) {
57969
58032
 
57970
58033
  // src/extension/uninstall.ts
57971
58034
  var import_promises10 = __toESM(require("fs/promises"), 1);
57972
- var import_node_path59 = __toESM(require("path"), 1);
58035
+ var import_node_path60 = __toESM(require("path"), 1);
57973
58036
  var UninstallError = class extends Error {
57974
58037
  constructor(code, message) {
57975
58038
  super(message);
@@ -57978,7 +58041,7 @@ var UninstallError = class extends Error {
57978
58041
  code;
57979
58042
  };
57980
58043
  async function uninstall(deps) {
57981
- const dir = import_node_path59.default.join(deps.root, deps.extId);
58044
+ const dir = import_node_path60.default.join(deps.root, deps.extId);
57982
58045
  try {
57983
58046
  await import_promises10.default.access(dir);
57984
58047
  } catch {
@@ -58562,7 +58625,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58562
58625
 
58563
58626
  // src/extension/runtime.ts
58564
58627
  var import_node_child_process18 = require("child_process");
58565
- var import_node_path60 = __toESM(require("path"), 1);
58628
+ var import_node_path61 = __toESM(require("path"), 1);
58566
58629
  var import_promises11 = require("timers/promises");
58567
58630
  init_src();
58568
58631
 
@@ -58664,7 +58727,7 @@ var Runtime = class {
58664
58727
  /\$CLAWOS_EXT_PORT/g,
58665
58728
  String(port)
58666
58729
  );
58667
- const dir = import_node_path60.default.join(this.root, extId);
58730
+ const dir = import_node_path61.default.join(this.root, extId);
58668
58731
  const env = {
58669
58732
  ...process.env,
58670
58733
  CLAWOS_EXT_PORT: String(port),
@@ -58776,7 +58839,7 @@ ${handle.stderrTail}`
58776
58839
 
58777
58840
  // src/extension/published-channels.ts
58778
58841
  var import_promises12 = __toESM(require("fs/promises"), 1);
58779
- var import_node_path61 = __toESM(require("path"), 1);
58842
+ var import_node_path62 = __toESM(require("path"), 1);
58780
58843
  init_src();
58781
58844
  init_zod();
58782
58845
  var PublishedChannelsError = class extends Error {
@@ -58876,7 +58939,7 @@ var PublishedChannelStore = class {
58876
58939
  )
58877
58940
  };
58878
58941
  const tmp = `${this.filePath}.tmp`;
58879
- await import_promises12.default.mkdir(import_node_path61.default.dirname(this.filePath), { recursive: true });
58942
+ await import_promises12.default.mkdir(import_node_path62.default.dirname(this.filePath), { recursive: true });
58880
58943
  await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
58881
58944
  await import_promises12.default.rename(tmp, this.filePath);
58882
58945
  }
@@ -58884,7 +58947,7 @@ var PublishedChannelStore = class {
58884
58947
 
58885
58948
  // src/extension/bundle-cache.ts
58886
58949
  var import_promises13 = __toESM(require("fs/promises"), 1);
58887
- var import_node_path62 = __toESM(require("path"), 1);
58950
+ var import_node_path63 = __toESM(require("path"), 1);
58888
58951
  var BundleCache = class {
58889
58952
  constructor(rootDir) {
58890
58953
  this.rootDir = rootDir;
@@ -58893,14 +58956,14 @@ var BundleCache = class {
58893
58956
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
58894
58957
  async write(snapshotHash, buffer) {
58895
58958
  await import_promises13.default.mkdir(this.rootDir, { recursive: true });
58896
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58959
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58897
58960
  const tmp = `${file}.tmp`;
58898
58961
  await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
58899
58962
  await import_promises13.default.rename(tmp, file);
58900
58963
  }
58901
58964
  /** Returns the bundle bytes, or null when the file doesn't exist. */
58902
58965
  async read(snapshotHash) {
58903
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58966
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58904
58967
  try {
58905
58968
  return await import_promises13.default.readFile(file);
58906
58969
  } catch (e) {
@@ -58910,7 +58973,7 @@ var BundleCache = class {
58910
58973
  }
58911
58974
  /** Idempotent — missing file is not an error. */
58912
58975
  async delete(snapshotHash) {
58913
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58976
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58914
58977
  await import_promises13.default.rm(file, { force: true });
58915
58978
  }
58916
58979
  };
@@ -58935,16 +58998,16 @@ async function startDaemon(config) {
58935
58998
  });
58936
58999
  const logger = createLogger({
58937
59000
  level: config.logLevel,
58938
- file: import_node_path63.default.join(config.dataDir, "clawd.log"),
59001
+ file: import_node_path64.default.join(config.dataDir, "clawd.log"),
58939
59002
  logClient
58940
59003
  });
58941
59004
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
58942
59005
  const screenIdleProbeLogger = createFileOnlyLogger({
58943
- file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log"),
59006
+ file: import_node_path64.default.join(config.dataDir, "screen-idle-probe.log"),
58944
59007
  level: "debug"
58945
59008
  });
58946
59009
  logger.info("screen-idle probe logger enabled", {
58947
- file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log")
59010
+ file: import_node_path64.default.join(config.dataDir, "screen-idle-probe.log")
58948
59011
  });
58949
59012
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
58950
59013
  const pre = stateMgr.preflight();
@@ -59082,8 +59145,8 @@ async function startDaemon(config) {
59082
59145
  const agents = new AgentsScanner();
59083
59146
  const history = new ClaudeHistoryReader();
59084
59147
  let transport = null;
59085
- const personaStore = new PersonaStore(import_node_path63.default.join(config.dataDir, "personas"));
59086
- const usersRoot = import_node_path63.default.join(config.dataDir, "users");
59148
+ const personaStore = new PersonaStore(import_node_path64.default.join(config.dataDir, "personas"));
59149
+ const usersRoot = import_node_path64.default.join(config.dataDir, "users");
59087
59150
  const defaultsRoot = findDefaultsRoot(logger);
59088
59151
  if (defaultsRoot) {
59089
59152
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -59103,17 +59166,17 @@ async function startDaemon(config) {
59103
59166
  migrateCodexSandbox({ store: personaStore, logger });
59104
59167
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
59105
59168
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
59106
- const here = typeof __dirname === "string" ? __dirname : import_node_path63.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59169
+ const here = typeof __dirname === "string" ? __dirname : import_node_path64.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59107
59170
  const dispatchServerCandidates = [
59108
- import_node_path63.default.join(here, "dispatch", "mcp-server.cjs"),
59171
+ import_node_path64.default.join(here, "dispatch", "mcp-server.cjs"),
59109
59172
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
59110
- import_node_path63.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59173
+ import_node_path64.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59111
59174
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59112
59175
  ];
59113
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59176
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59114
59177
  let dispatchMcpConfigPath2;
59115
59178
  if (dispatchServerScriptPath) {
59116
- const dispatchLogPath = import_node_path63.default.join(config.dataDir, "dispatch-mcp-server.log");
59179
+ const dispatchLogPath = import_node_path64.default.join(config.dataDir, "dispatch-mcp-server.log");
59117
59180
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
59118
59181
  dataDir: config.dataDir,
59119
59182
  serverScriptPath: dispatchServerScriptPath,
@@ -59130,15 +59193,15 @@ async function startDaemon(config) {
59130
59193
  });
59131
59194
  }
59132
59195
  const ticketServerCandidates = [
59133
- import_node_path63.default.join(here, "ticket", "mcp-server.cjs"),
59134
- import_node_path63.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59196
+ import_node_path64.default.join(here, "ticket", "mcp-server.cjs"),
59197
+ import_node_path64.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59135
59198
  ];
59136
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59199
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59137
59200
  const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
59138
59201
  const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
59139
59202
  let ticketMcpConfigPath2;
59140
59203
  if (ticketServerScriptPath && ticketOwnerUnionId) {
59141
- const ticketLogPath = import_node_path63.default.join(config.dataDir, "ticket-mcp-server.log");
59204
+ const ticketLogPath = import_node_path64.default.join(config.dataDir, "ticket-mcp-server.log");
59142
59205
  ticketMcpConfigPath2 = writeTicketMcpConfig({
59143
59206
  dataDir: config.dataDir,
59144
59207
  serverScriptPath: ticketServerScriptPath,
@@ -59159,13 +59222,13 @@ async function startDaemon(config) {
59159
59222
  });
59160
59223
  }
59161
59224
  const shiftServerCandidates = [
59162
- import_node_path63.default.join(here, "shift", "mcp-server.cjs"),
59163
- import_node_path63.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59225
+ import_node_path64.default.join(here, "shift", "mcp-server.cjs"),
59226
+ import_node_path64.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59164
59227
  ];
59165
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59228
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59166
59229
  let shiftMcpConfigPath2;
59167
59230
  if (shiftServerScriptPath) {
59168
- const shiftLogPath = import_node_path63.default.join(config.dataDir, "shift-mcp-server.log");
59231
+ const shiftLogPath = import_node_path64.default.join(config.dataDir, "shift-mcp-server.log");
59169
59232
  shiftMcpConfigPath2 = await writeShiftMcpConfig({
59170
59233
  dataDir: config.dataDir,
59171
59234
  serverScriptPath: shiftServerScriptPath,
@@ -59183,13 +59246,13 @@ async function startDaemon(config) {
59183
59246
  );
59184
59247
  }
59185
59248
  const inboxServerCandidates = [
59186
- import_node_path63.default.join(here, "inbox", "mcp-server.cjs"),
59187
- import_node_path63.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59249
+ import_node_path64.default.join(here, "inbox", "mcp-server.cjs"),
59250
+ import_node_path64.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59188
59251
  ];
59189
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59252
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59190
59253
  let inboxMcpConfigPath2;
59191
59254
  if (inboxServerScriptPath) {
59192
- const inboxLogPath = import_node_path63.default.join(config.dataDir, "inbox-mcp-server.log");
59255
+ const inboxLogPath = import_node_path64.default.join(config.dataDir, "inbox-mcp-server.log");
59193
59256
  inboxMcpConfigPath2 = await writeInboxMcpConfig({
59194
59257
  dataDir: config.dataDir,
59195
59258
  serverScriptPath: inboxServerScriptPath,
@@ -59207,7 +59270,7 @@ async function startDaemon(config) {
59207
59270
  );
59208
59271
  }
59209
59272
  const shiftStore = createShiftStore({
59210
- filePath: import_node_path63.default.join(config.dataDir, "shift.json"),
59273
+ filePath: import_node_path64.default.join(config.dataDir, "shift.json"),
59211
59274
  ownerIdProvider: () => ownerPrincipalId,
59212
59275
  now: () => Date.now()
59213
59276
  });
@@ -59229,7 +59292,7 @@ async function startDaemon(config) {
59229
59292
  getAdapter,
59230
59293
  historyReader: history,
59231
59294
  dataDir: config.dataDir,
59232
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59295
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59233
59296
  usersRoot,
59234
59297
  personaStore,
59235
59298
  ownerDisplayName,
@@ -59272,10 +59335,10 @@ async function startDaemon(config) {
59272
59335
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
59273
59336
  attachmentGroup: {
59274
59337
  onFileEdit: (input) => {
59275
- const absPath = import_node_path63.default.isAbsolute(input.relPath) ? input.relPath : import_node_path63.default.join(input.cwd, input.relPath);
59338
+ const absPath = import_node_path64.default.isAbsolute(input.relPath) ? input.relPath : import_node_path64.default.join(input.cwd, input.relPath);
59276
59339
  let size = 0;
59277
59340
  try {
59278
- size = import_node_fs50.default.statSync(absPath).size;
59341
+ size = import_node_fs51.default.statSync(absPath).size;
59279
59342
  } catch (err) {
59280
59343
  logger.warn("attachment.onFileEdit stat failed", {
59281
59344
  sessionId: input.sessionId,
@@ -59474,11 +59537,11 @@ async function startDaemon(config) {
59474
59537
  // 'persona/<pid>/owner',default 走 'default'。
59475
59538
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
59476
59539
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
59477
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59540
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59478
59541
  usersRoot
59479
59542
  },
59480
59543
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
59481
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59544
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59482
59545
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
59483
59546
  usersRoot,
59484
59547
  // capability:list / delete handler 依赖
@@ -59500,7 +59563,7 @@ async function startDaemon(config) {
59500
59563
  contactStore,
59501
59564
  // <dataDir>/sshd 绝对路径 —— contact-ssh handlers 用它拼 authorized_keys / keys/ 子路径
59502
59565
  // Task 10 会加 SshdManager 起 sshd;handlers wire 提前挂 sshdDir 让 typecheck 过
59503
- sshdDir: import_node_path63.default.join(config.dataDir, "sshd"),
59566
+ sshdDir: import_node_path64.default.join(config.dataDir, "sshd"),
59504
59567
  contactSshLog: sshLog,
59505
59568
  // inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
59506
59569
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
@@ -59591,11 +59654,11 @@ async function startDaemon(config) {
59591
59654
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
59592
59655
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
59593
59656
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
59594
- appBuilderPersonaRoot: import_node_path63.default.join(config.dataDir, "personas", "persona-app-builder"),
59657
+ appBuilderPersonaRoot: import_node_path64.default.join(config.dataDir, "personas", "persona-app-builder"),
59595
59658
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
59596
- deployKitRoot: import_node_path63.default.join(config.dataDir, "deploy-kit"),
59659
+ deployKitRoot: import_node_path64.default.join(config.dataDir, "deploy-kit"),
59597
59660
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
59598
- resolvePersonaRoot: (personaId) => import_node_path63.default.join(config.dataDir, "personas", personaId),
59661
+ resolvePersonaRoot: (personaId) => import_node_path64.default.join(config.dataDir, "personas", personaId),
59599
59662
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
59600
59663
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
59601
59664
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -59638,7 +59701,7 @@ async function startDaemon(config) {
59638
59701
  }
59639
59702
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
59640
59703
  if (sourceFile && sourceFile.toolSessionId) {
59641
- sourceJsonlPath = import_node_path63.default.join(
59704
+ sourceJsonlPath = import_node_path64.default.join(
59642
59705
  import_node_os21.default.homedir(),
59643
59706
  ".claude",
59644
59707
  "projects",
@@ -59968,8 +60031,8 @@ async function startDaemon(config) {
59968
60031
  const lines = [
59969
60032
  `Tunnel: ${r.url}`,
59970
60033
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
59971
- `Frpc config: ${import_node_path63.default.join(config.dataDir, "frpc.toml")}`,
59972
- `Frpc log: ${import_node_path63.default.join(config.dataDir, "frpc.log")}`
60034
+ `Frpc config: ${import_node_path64.default.join(config.dataDir, "frpc.toml")}`,
60035
+ `Frpc log: ${import_node_path64.default.join(config.dataDir, "frpc.log")}`
59973
60036
  ];
59974
60037
  const width = Math.max(...lines.map((l) => l.length));
59975
60038
  const bar = "\u2550".repeat(width + 4);
@@ -59982,8 +60045,8 @@ ${bar}
59982
60045
 
59983
60046
  `);
59984
60047
  try {
59985
- const connectPath = import_node_path63.default.join(config.dataDir, "connect.txt");
59986
- import_node_fs50.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60048
+ const connectPath = import_node_path64.default.join(config.dataDir, "connect.txt");
60049
+ import_node_fs51.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
59987
60050
  } catch {
59988
60051
  }
59989
60052
  } catch (err) {
@@ -60017,7 +60080,7 @@ ${bar}
60017
60080
  });
60018
60081
  try {
60019
60082
  await sshdMgr.start();
60020
- rebuildAuthorizedKeys(contactStore, import_node_path63.default.join(config.dataDir, "sshd"));
60083
+ rebuildAuthorizedKeys(contactStore, import_node_path64.default.join(config.dataDir, "sshd"));
60021
60084
  logger.info("sshd: contact-ssh sandbox ready", { port: config.sshdPort });
60022
60085
  } catch (err) {
60023
60086
  logger.warn("sshd start failed; contact SSH grant will not work until fixed", {
@@ -60085,9 +60148,9 @@ ${bar}
60085
60148
  };
60086
60149
  }
60087
60150
  function migrateDropPersonsDir(dataDir) {
60088
- const dir = import_node_path63.default.join(dataDir, "persons");
60151
+ const dir = import_node_path64.default.join(dataDir, "persons");
60089
60152
  try {
60090
- import_node_fs50.default.rmSync(dir, { recursive: true, force: true });
60153
+ import_node_fs51.default.rmSync(dir, { recursive: true, force: true });
60091
60154
  } catch {
60092
60155
  }
60093
60156
  }