@clawos-dev/clawd 0.2.206 → 0.2.207-beta.414.456f239

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.cjs +867 -804
  2. package/package.json +1 -1
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
 
@@ -41823,6 +41823,60 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41823
41823
  return s;
41824
41824
  }
41825
41825
 
41826
+ // src/tools/owner-credentials.ts
41827
+ var import_node_fs4 = __toESM(require("fs"), 1);
41828
+ var import_node_path4 = __toESM(require("path"), 1);
41829
+ function readOwnerCredentials(homeDir, logger) {
41830
+ const settingsPath = import_node_path4.default.join(homeDir, ".claude", "settings.json");
41831
+ let raw;
41832
+ try {
41833
+ raw = import_node_fs4.default.readFileSync(settingsPath, "utf8");
41834
+ } catch (err) {
41835
+ const code = err.code;
41836
+ if (code === "ENOENT") return null;
41837
+ logger?.warn("owner ~/.claude/settings.json read failed", { code });
41838
+ return null;
41839
+ }
41840
+ let parsed;
41841
+ try {
41842
+ parsed = JSON.parse(raw);
41843
+ } catch {
41844
+ logger?.warn("owner ~/.claude/settings.json malformed JSON");
41845
+ return null;
41846
+ }
41847
+ if (!parsed || typeof parsed !== "object") return null;
41848
+ const obj = parsed;
41849
+ const bundle = {};
41850
+ const envRaw = obj.env;
41851
+ if (envRaw && typeof envRaw === "object" && !Array.isArray(envRaw)) {
41852
+ const filtered = {};
41853
+ for (const [k2, v2] of Object.entries(envRaw)) {
41854
+ if (k2.startsWith("ANTHROPIC_") && typeof v2 === "string") filtered[k2] = v2;
41855
+ }
41856
+ if (Object.keys(filtered).length > 0) bundle.env = filtered;
41857
+ }
41858
+ const helperRaw = obj.apiKeyHelper;
41859
+ if (typeof helperRaw === "string" && helperRaw.length > 0) {
41860
+ if (!import_node_path4.default.isAbsolute(helperRaw)) {
41861
+ logger?.warn(
41862
+ "owner apiKeyHelper is not absolute; cc will resolve against guest cwd (persona dir), likely EXEC not found",
41863
+ { basename: import_node_path4.default.basename(helperRaw) }
41864
+ );
41865
+ }
41866
+ bundle.apiKeyHelper = helperRaw;
41867
+ }
41868
+ if (!bundle.env && !bundle.apiKeyHelper) return null;
41869
+ return bundle;
41870
+ }
41871
+ function mergeOwnerCredentials(guestSandbox, bundle) {
41872
+ if (!bundle) return guestSandbox;
41873
+ return {
41874
+ ...guestSandbox,
41875
+ ...bundle.env ? { env: bundle.env } : {},
41876
+ ...bundle.apiKeyHelper ? { apiKeyHelper: bundle.apiKeyHelper } : {}
41877
+ };
41878
+ }
41879
+
41826
41880
  // src/shift/wrap.ts
41827
41881
  function wrapShiftFirePrompt(args) {
41828
41882
  return [
@@ -41841,7 +41895,7 @@ function escapeAttr(v2) {
41841
41895
 
41842
41896
  // src/session/runner.ts
41843
41897
  var import_node_os4 = __toESM(require("os"), 1);
41844
- var import_node_path6 = __toESM(require("path"), 1);
41898
+ var import_node_path7 = __toESM(require("path"), 1);
41845
41899
 
41846
41900
  // src/session/reducer.ts
41847
41901
  init_runtime();
@@ -42769,8 +42823,8 @@ init_permission_stdio();
42769
42823
  init_claude_history();
42770
42824
 
42771
42825
  // src/ipc-recorder.ts
42772
- var import_node_fs5 = __toESM(require("fs"), 1);
42773
- var import_node_path5 = __toESM(require("path"), 1);
42826
+ var import_node_fs6 = __toESM(require("fs"), 1);
42827
+ var import_node_path6 = __toESM(require("path"), 1);
42774
42828
  function tsForFilename(ms) {
42775
42829
  return new Date(ms).toISOString().replace(/[:.]/g, "-");
42776
42830
  }
@@ -42781,8 +42835,8 @@ function startRecorder(opts) {
42781
42835
  return null;
42782
42836
  }
42783
42837
  const now = opts.now ?? Date.now;
42784
- const dir = import_node_path5.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42785
- const filePath = import_node_path5.default.join(dir, `${tsForFilename(now())}.jsonl`);
42838
+ const dir = import_node_path6.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
42839
+ const filePath = import_node_path6.default.join(dir, `${tsForFilename(now())}.jsonl`);
42786
42840
  let stream = null;
42787
42841
  let closedResolve;
42788
42842
  const closed = new Promise((resolve6) => {
@@ -42791,8 +42845,8 @@ function startRecorder(opts) {
42791
42845
  let exited = false;
42792
42846
  const ensureStream = () => {
42793
42847
  if (stream) return stream;
42794
- import_node_fs5.default.mkdirSync(dir, { recursive: true });
42795
- stream = import_node_fs5.default.createWriteStream(filePath, { flags: "a" });
42848
+ import_node_fs6.default.mkdirSync(dir, { recursive: true });
42849
+ stream = import_node_fs6.default.createWriteStream(filePath, { flags: "a" });
42796
42850
  stream.on("close", () => closedResolve());
42797
42851
  return stream;
42798
42852
  };
@@ -43172,7 +43226,7 @@ var SessionRunner = class {
43172
43226
  isSubagentActive() {
43173
43227
  const toolSessionId = this.state.file.toolSessionId;
43174
43228
  if (!toolSessionId) return false;
43175
- const projectsRoot = import_node_path6.default.join(this.hooks.home ?? import_node_os4.default.homedir(), ".claude", "projects");
43229
+ const projectsRoot = import_node_path7.default.join(this.hooks.home ?? import_node_os4.default.homedir(), ".claude", "projects");
43176
43230
  const mtime = newestSubagentMtimeMs(projectsRoot, this.state.file.cwd, toolSessionId);
43177
43231
  if (mtime === null) return false;
43178
43232
  const now = (this.hooks.now ?? Date.now)();
@@ -43260,15 +43314,15 @@ function extractEditPath(input) {
43260
43314
  }
43261
43315
 
43262
43316
  // src/debug/pty-probe.ts
43263
- var import_node_fs6 = __toESM(require("fs"), 1);
43264
- var import_node_path7 = __toESM(require("path"), 1);
43317
+ var import_node_fs7 = __toESM(require("fs"), 1);
43318
+ var import_node_path8 = __toESM(require("path"), 1);
43265
43319
  var PROBE_DIR = "/tmp/clawd-probe";
43266
- var EVENTS_FILE = import_node_path7.default.join(PROBE_DIR, "events.jsonl");
43320
+ var EVENTS_FILE = import_node_path8.default.join(PROBE_DIR, "events.jsonl");
43267
43321
  var inited = false;
43268
43322
  function ensureDir() {
43269
43323
  if (inited) return true;
43270
43324
  try {
43271
- import_node_fs6.default.mkdirSync(PROBE_DIR, { recursive: true });
43325
+ import_node_fs7.default.mkdirSync(PROBE_DIR, { recursive: true });
43272
43326
  inited = true;
43273
43327
  return true;
43274
43328
  } catch {
@@ -43279,15 +43333,15 @@ function probeEvent(event, data = {}) {
43279
43333
  try {
43280
43334
  if (!ensureDir()) return;
43281
43335
  const line = JSON.stringify({ ts: Date.now(), event, ...data }) + "\n";
43282
- import_node_fs6.default.appendFileSync(EVENTS_FILE, line);
43336
+ import_node_fs7.default.appendFileSync(EVENTS_FILE, line);
43283
43337
  } catch {
43284
43338
  }
43285
43339
  }
43286
43340
  function probeDumpReplay(sessionId, payload) {
43287
43341
  try {
43288
43342
  if (!ensureDir()) return "";
43289
- const file = import_node_path7.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
43290
- import_node_fs6.default.writeFileSync(file, payload, "utf8");
43343
+ const file = import_node_path8.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
43344
+ import_node_fs7.default.writeFileSync(file, payload, "utf8");
43291
43345
  return file;
43292
43346
  } catch {
43293
43347
  return "";
@@ -43396,7 +43450,7 @@ function derivePersonaSpawnCwd(file, personaRoot) {
43396
43450
  `derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${personaId})`
43397
43451
  );
43398
43452
  }
43399
- return import_node_path8.default.join(personaRoot, safeFileName(personaId));
43453
+ return import_node_path9.default.join(personaRoot, safeFileName(personaId));
43400
43454
  }
43401
43455
  function makeInitialState(file, subSessionMeta) {
43402
43456
  return {
@@ -43530,10 +43584,10 @@ var SessionManager = class {
43530
43584
  // <dataDir>/sessions/ 列子目录 (排除 'default').
43531
43585
  listPersonaIdsOnDisk() {
43532
43586
  if (!this.deps.dataDir) return [];
43533
- const root = this.deps.storeFactory ? import_node_path8.default.join(this.deps.dataDir, "personas") : import_node_path8.default.join(this.deps.dataDir, "sessions");
43587
+ const root = this.deps.storeFactory ? import_node_path9.default.join(this.deps.dataDir, "personas") : import_node_path9.default.join(this.deps.dataDir, "sessions");
43534
43588
  let entries;
43535
43589
  try {
43536
- entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
43590
+ entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43537
43591
  } catch (err) {
43538
43592
  const code = err?.code;
43539
43593
  if (code === "ENOENT") return [];
@@ -43546,7 +43600,7 @@ var SessionManager = class {
43546
43600
  // 只在 storeFactory 注入 (新布局) 下生效, 老布局无 guest 目录.
43547
43601
  listGuestCapIdsForPersona(personaId) {
43548
43602
  if (!this.deps.dataDir || !this.deps.storeFactory) return [];
43549
- const root = import_node_path8.default.join(
43603
+ const root = import_node_path9.default.join(
43550
43604
  this.deps.dataDir,
43551
43605
  "personas",
43552
43606
  personaId,
@@ -43556,7 +43610,7 @@ var SessionManager = class {
43556
43610
  );
43557
43611
  let entries;
43558
43612
  try {
43559
- entries = import_node_fs7.default.readdirSync(root, { withFileTypes: true });
43613
+ entries = import_node_fs8.default.readdirSync(root, { withFileTypes: true });
43560
43614
  } catch (err) {
43561
43615
  const code = err?.code;
43562
43616
  if (code === "ENOENT") return [];
@@ -43675,7 +43729,7 @@ var SessionManager = class {
43675
43729
  callerDisplayName
43676
43730
  );
43677
43731
  if (subSessionMeta?.userWorkDir) {
43678
- import_node_fs7.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43732
+ import_node_fs8.default.mkdirSync(subSessionMeta.userWorkDir, { recursive: true });
43679
43733
  }
43680
43734
  if (scope.kind === "persona" && scope.mode === "guest") {
43681
43735
  if (!this.deps.personaRoot || !subSessionMeta?.userWorkDir) {
@@ -43684,10 +43738,19 @@ var SessionManager = class {
43684
43738
  );
43685
43739
  }
43686
43740
  const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
43687
- const settings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43688
- subSessionMeta.extraSettings = JSON.stringify(settings);
43741
+ const sandboxSettings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
43742
+ const ownerCreds = readOwnerCredentials(import_node_os5.default.homedir(), this.deps.logger);
43743
+ const merged = mergeOwnerCredentials(sandboxSettings, ownerCreds);
43744
+ if (ownerCreds) {
43745
+ this.deps.logger?.info("owner credentials injected into guest spawn", {
43746
+ sessionId: file.sessionId,
43747
+ envKeys: ownerCreds.env ? Object.keys(ownerCreds.env) : [],
43748
+ apiKeyHelper: ownerCreds.apiKeyHelper ? "present" : "absent"
43749
+ });
43750
+ }
43751
+ subSessionMeta.extraSettings = JSON.stringify(merged);
43689
43752
  const home = import_node_os5.default.homedir();
43690
- const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path8.default.join(home, p2.slice(2)) : p2;
43753
+ const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path9.default.join(home, p2.slice(2)) : p2;
43691
43754
  const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
43692
43755
  subSessionMeta.codexSandbox = {
43693
43756
  writableRoots: [subSessionMeta.userWorkDir, ...(codexCfg?.writableRoots ?? []).map(expand)],
@@ -43848,7 +43911,7 @@ var SessionManager = class {
43848
43911
  throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
43849
43912
  }
43850
43913
  try {
43851
- const stat = import_node_fs7.default.statSync(cwd);
43914
+ const stat = import_node_fs8.default.statSync(cwd);
43852
43915
  if (!stat.isDirectory()) throw new Error("not dir");
43853
43916
  } catch {
43854
43917
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
@@ -44382,7 +44445,7 @@ var SessionManager = class {
44382
44445
  */
44383
44446
  createForScope(args) {
44384
44447
  try {
44385
- const stat = import_node_fs7.default.statSync(args.cwd);
44448
+ const stat = import_node_fs8.default.statSync(args.cwd);
44386
44449
  if (!stat.isDirectory()) throw new Error("not dir");
44387
44450
  } catch {
44388
44451
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
@@ -44598,7 +44661,7 @@ var SessionManager = class {
44598
44661
  personaId: args.targetPersona,
44599
44662
  mode: "owner"
44600
44663
  };
44601
- const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44664
+ const cwd = import_node_path9.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44602
44665
  const now = (/* @__PURE__ */ new Date()).toISOString();
44603
44666
  const file = {
44604
44667
  sessionId,
@@ -44663,7 +44726,7 @@ var SessionManager = class {
44663
44726
  personaId: args.targetPersona,
44664
44727
  mode: "owner"
44665
44728
  };
44666
- const cwd = import_node_path8.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44729
+ const cwd = import_node_path9.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
44667
44730
  const now = (/* @__PURE__ */ new Date()).toISOString();
44668
44731
  const file = {
44669
44732
  sessionId,
@@ -45151,28 +45214,28 @@ var SessionManager = class {
45151
45214
  };
45152
45215
 
45153
45216
  // src/persona/store.ts
45154
- var fs8 = __toESM(require("fs"), 1);
45155
- var path11 = __toESM(require("path"), 1);
45217
+ var fs9 = __toESM(require("fs"), 1);
45218
+ var path12 = __toESM(require("path"), 1);
45156
45219
  init_protocol();
45157
45220
  var PersonaStore = class {
45158
45221
  constructor(root) {
45159
45222
  this.root = root;
45160
- fs8.mkdirSync(root, { recursive: true });
45223
+ fs9.mkdirSync(root, { recursive: true });
45161
45224
  }
45162
45225
  root;
45163
45226
  personaDir(personaId) {
45164
- return path11.join(this.root, safeFileName(personaId));
45227
+ return path12.join(this.root, safeFileName(personaId));
45165
45228
  }
45166
45229
  metaPath(personaId) {
45167
- return path11.join(this.personaDir(personaId), ".clawd", "persona.json");
45230
+ return path12.join(this.personaDir(personaId), ".clawd", "persona.json");
45168
45231
  }
45169
45232
  claudeMdPath(personaId) {
45170
- return path11.join(this.personaDir(personaId), "CLAUDE.md");
45233
+ return path12.join(this.personaDir(personaId), "CLAUDE.md");
45171
45234
  }
45172
45235
  // codex 原生读 cwd 的 AGENTS.md。人格双写镜像:claude 读 CLAUDE.md、codex 读 AGENTS.md,
45173
45236
  // 两份内容恒一致,persona 切 tool 零迁移。
45174
45237
  agentsMdPath(personaId) {
45175
- return path11.join(this.personaDir(personaId), "AGENTS.md");
45238
+ return path12.join(this.personaDir(personaId), "AGENTS.md");
45176
45239
  }
45177
45240
  /**
45178
45241
  * persona 级 sandbox base 落盘路径 —— 故意放 `.clawd/` 而非 `.claude/`,让 CC 的 project
@@ -45181,11 +45244,11 @@ var PersonaStore = class {
45181
45244
  * spawn 前 per-guest 动态拼到各自 session 目录的那份(base + 强制底座 + 本 guest userWorkDir carve)。
45182
45245
  */
45183
45246
  sandboxSettingsPath(personaId) {
45184
- return path11.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
45247
+ return path12.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
45185
45248
  }
45186
45249
  write(persona, personality) {
45187
45250
  const dir = this.personaDir(persona.personaId);
45188
- fs8.mkdirSync(path11.join(dir, ".clawd"), { recursive: true });
45251
+ fs9.mkdirSync(path12.join(dir, ".clawd"), { recursive: true });
45189
45252
  this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
45190
45253
  this.atomicWrite(this.agentsMdPath(persona.personaId), personality);
45191
45254
  this.writeSandboxSettings(persona.personaId, buildGuestSettingsV1());
@@ -45204,9 +45267,9 @@ var PersonaStore = class {
45204
45267
  ensureAgentsMirror(personaId) {
45205
45268
  const claudeMd = this.claudeMdPath(personaId);
45206
45269
  const agentsMd = this.agentsMdPath(personaId);
45207
- if (!fs8.existsSync(claudeMd)) return false;
45208
- if (fs8.existsSync(agentsMd)) return false;
45209
- this.atomicWrite(agentsMd, fs8.readFileSync(claudeMd, "utf8"));
45270
+ if (!fs9.existsSync(claudeMd)) return false;
45271
+ if (fs9.existsSync(agentsMd)) return false;
45272
+ this.atomicWrite(agentsMd, fs9.readFileSync(claudeMd, "utf8"));
45210
45273
  return true;
45211
45274
  }
45212
45275
  /**
@@ -45230,22 +45293,22 @@ var PersonaStore = class {
45230
45293
  return { ...s, permissions: { ...s.permissions ?? {}, deny: [...prev, rule] } };
45231
45294
  }
45232
45295
  codexSandboxSettingsPath(personaId) {
45233
- return path11.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
45296
+ return path12.join(this.personaDir(personaId), ".clawd", "codex-sandbox.json");
45234
45297
  }
45235
45298
  /** 读 codex-sandbox.json;不存在/损坏 → null。 */
45236
45299
  readCodexSandboxSettings(personaId) {
45237
45300
  const p2 = this.codexSandboxSettingsPath(personaId);
45238
- if (!fs8.existsSync(p2)) return null;
45301
+ if (!fs9.existsSync(p2)) return null;
45239
45302
  try {
45240
- return CodexSandboxSettingsSchema.parse(JSON.parse(fs8.readFileSync(p2, "utf8")));
45303
+ return CodexSandboxSettingsSchema.parse(JSON.parse(fs9.readFileSync(p2, "utf8")));
45241
45304
  } catch {
45242
45305
  return null;
45243
45306
  }
45244
45307
  }
45245
45308
  /** 覆盖写 codex-sandbox.json(seed/migrate 用)。 */
45246
45309
  writeCodexSandboxSettings(personaId, settings) {
45247
- const dir = path11.join(this.personaDir(personaId), ".clawd");
45248
- fs8.mkdirSync(dir, { recursive: true });
45310
+ const dir = path12.join(this.personaDir(personaId), ".clawd");
45311
+ fs9.mkdirSync(dir, { recursive: true });
45249
45312
  this.atomicWrite(this.codexSandboxSettingsPath(personaId), JSON.stringify(settings, null, 2));
45250
45313
  }
45251
45314
  writeMeta(persona) {
@@ -45253,8 +45316,8 @@ var PersonaStore = class {
45253
45316
  }
45254
45317
  read(personaId) {
45255
45318
  const p2 = this.metaPath(personaId);
45256
- if (!fs8.existsSync(p2)) return null;
45257
- const raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
45319
+ if (!fs9.existsSync(p2)) return null;
45320
+ const raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45258
45321
  if (raw && typeof raw === "object" && "tokenMap" in raw) {
45259
45322
  delete raw.tokenMap;
45260
45323
  this.atomicWrite(p2, JSON.stringify(raw, null, 2));
@@ -45262,13 +45325,13 @@ var PersonaStore = class {
45262
45325
  return PersonaFileSchema.parse(raw);
45263
45326
  }
45264
45327
  has(personaId) {
45265
- return fs8.existsSync(this.metaPath(personaId));
45328
+ return fs9.existsSync(this.metaPath(personaId));
45266
45329
  }
45267
45330
  readPersonality(personaId) {
45268
45331
  const claudeMd = this.claudeMdPath(personaId);
45269
- if (fs8.existsSync(claudeMd)) return fs8.readFileSync(claudeMd, "utf8");
45332
+ if (fs9.existsSync(claudeMd)) return fs9.readFileSync(claudeMd, "utf8");
45270
45333
  const agentsMd = this.agentsMdPath(personaId);
45271
- if (fs8.existsSync(agentsMd)) return fs8.readFileSync(agentsMd, "utf8");
45334
+ if (fs9.existsSync(agentsMd)) return fs9.readFileSync(agentsMd, "utf8");
45272
45335
  return null;
45273
45336
  }
45274
45337
  /**
@@ -45277,23 +45340,23 @@ var PersonaStore = class {
45277
45340
  */
45278
45341
  readSandboxSettings(personaId) {
45279
45342
  const p2 = this.sandboxSettingsPath(personaId);
45280
- if (!fs8.existsSync(p2)) return null;
45343
+ if (!fs9.existsSync(p2)) return null;
45281
45344
  try {
45282
- return JSON.parse(fs8.readFileSync(p2, "utf8"));
45345
+ return JSON.parse(fs9.readFileSync(p2, "utf8"));
45283
45346
  } catch {
45284
45347
  return null;
45285
45348
  }
45286
45349
  }
45287
45350
  /** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
45288
45351
  skillsDir(personaId) {
45289
- return path11.join(this.personaDir(personaId), ".claude", "skills");
45352
+ return path12.join(this.personaDir(personaId), ".claude", "skills");
45290
45353
  }
45291
45354
  /**
45292
45355
  * Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
45293
45356
  * 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
45294
45357
  */
45295
45358
  claudeSettingsPath(personaId) {
45296
- return path11.join(this.personaDir(personaId), ".claude", "settings.json");
45359
+ return path12.join(this.personaDir(personaId), ".claude", "settings.json");
45297
45360
  }
45298
45361
  /**
45299
45362
  * 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
@@ -45308,10 +45371,10 @@ var PersonaStore = class {
45308
45371
  */
45309
45372
  readEnabledPlugins(personaId) {
45310
45373
  const p2 = this.claudeSettingsPath(personaId);
45311
- if (!fs8.existsSync(p2)) return [];
45374
+ if (!fs9.existsSync(p2)) return [];
45312
45375
  let raw;
45313
45376
  try {
45314
- raw = JSON.parse(fs8.readFileSync(p2, "utf8"));
45377
+ raw = JSON.parse(fs9.readFileSync(p2, "utf8"));
45315
45378
  } catch {
45316
45379
  return [];
45317
45380
  }
@@ -45325,22 +45388,22 @@ var PersonaStore = class {
45325
45388
  return out;
45326
45389
  }
45327
45390
  list() {
45328
- if (!fs8.existsSync(this.root)) return [];
45329
- return fs8.readdirSync(this.root).filter((name) => {
45330
- return fs8.existsSync(path11.join(this.root, name, ".clawd", "persona.json"));
45391
+ if (!fs9.existsSync(this.root)) return [];
45392
+ return fs9.readdirSync(this.root).filter((name) => {
45393
+ return fs9.existsSync(path12.join(this.root, name, ".clawd", "persona.json"));
45331
45394
  });
45332
45395
  }
45333
45396
  remove(personaId) {
45334
45397
  const dir = this.personaDir(personaId);
45335
- if (fs8.existsSync(dir)) fs8.rmSync(dir, { recursive: true, force: true });
45398
+ if (fs9.existsSync(dir)) fs9.rmSync(dir, { recursive: true, force: true });
45336
45399
  }
45337
45400
  personaDirPath(personaId) {
45338
45401
  return this.personaDir(personaId);
45339
45402
  }
45340
45403
  atomicWrite(file, content) {
45341
45404
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
45342
- fs8.writeFileSync(tmp, content, { mode: 384 });
45343
- fs8.renameSync(tmp, file);
45405
+ fs9.writeFileSync(tmp, content, { mode: 384 });
45406
+ fs9.renameSync(tmp, file);
45344
45407
  }
45345
45408
  };
45346
45409
 
@@ -45386,9 +45449,9 @@ var PersonaRegistry = class {
45386
45449
  var import_node_crypto3 = __toESM(require("crypto"), 1);
45387
45450
 
45388
45451
  // src/skills/scanner.ts
45389
- var import_node_fs8 = __toESM(require("fs"), 1);
45452
+ var import_node_fs9 = __toESM(require("fs"), 1);
45390
45453
  var import_node_os6 = __toESM(require("os"), 1);
45391
- var import_node_path9 = __toESM(require("path"), 1);
45454
+ var import_node_path10 = __toESM(require("path"), 1);
45392
45455
 
45393
45456
  // src/skills/frontmatter.ts
45394
45457
  var STRIP_QUOTES = /^["']|["']$/g;
@@ -45497,7 +45560,7 @@ function parseDescription(content) {
45497
45560
  }
45498
45561
  function isDirLikeSync(p2) {
45499
45562
  try {
45500
- return import_node_fs8.default.statSync(p2).isDirectory();
45563
+ return import_node_fs9.default.statSync(p2).isDirectory();
45501
45564
  } catch {
45502
45565
  return false;
45503
45566
  }
@@ -45505,19 +45568,19 @@ function isDirLikeSync(p2) {
45505
45568
  function scanSkillDir(dir, source, seen, out, pluginName) {
45506
45569
  let entries;
45507
45570
  try {
45508
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
45571
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45509
45572
  } catch {
45510
45573
  return;
45511
45574
  }
45512
45575
  for (const ent of entries) {
45513
- const entryPath = import_node_path9.default.join(dir, ent.name);
45576
+ const entryPath = import_node_path10.default.join(dir, ent.name);
45514
45577
  if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
45515
45578
  let content;
45516
45579
  try {
45517
- content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "SKILL.md"), "utf8");
45580
+ content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "SKILL.md"), "utf8");
45518
45581
  } catch {
45519
45582
  try {
45520
- content = import_node_fs8.default.readFileSync(import_node_path9.default.join(entryPath, "skill.md"), "utf8");
45583
+ content = import_node_fs9.default.readFileSync(import_node_path10.default.join(entryPath, "skill.md"), "utf8");
45521
45584
  } catch {
45522
45585
  continue;
45523
45586
  }
@@ -45541,26 +45604,26 @@ function listSkillsForDir(dir, source) {
45541
45604
  function scanCommandDir(dir, source, seen, out, pluginName) {
45542
45605
  let entries;
45543
45606
  try {
45544
- entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
45607
+ entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
45545
45608
  } catch {
45546
45609
  return;
45547
45610
  }
45548
45611
  for (const ent of entries) {
45549
- const entryPath = import_node_path9.default.join(dir, ent.name);
45612
+ const entryPath = import_node_path10.default.join(dir, ent.name);
45550
45613
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
45551
45614
  const ns = ent.name;
45552
45615
  let subEntries;
45553
45616
  try {
45554
- subEntries = import_node_fs8.default.readdirSync(entryPath, { withFileTypes: true });
45617
+ subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
45555
45618
  } catch {
45556
45619
  continue;
45557
45620
  }
45558
45621
  for (const se of subEntries) {
45559
45622
  if (!se.name.endsWith(".md")) continue;
45560
- const sePath = import_node_path9.default.join(entryPath, se.name);
45623
+ const sePath = import_node_path10.default.join(entryPath, se.name);
45561
45624
  let content;
45562
45625
  try {
45563
- content = import_node_fs8.default.readFileSync(sePath, "utf8");
45626
+ content = import_node_fs9.default.readFileSync(sePath, "utf8");
45564
45627
  } catch {
45565
45628
  continue;
45566
45629
  }
@@ -45577,7 +45640,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45577
45640
  } else if (ent.name.endsWith(".md")) {
45578
45641
  let content;
45579
45642
  try {
45580
- content = import_node_fs8.default.readFileSync(entryPath, "utf8");
45643
+ content = import_node_fs9.default.readFileSync(entryPath, "utf8");
45581
45644
  } catch {
45582
45645
  continue;
45583
45646
  }
@@ -45593,10 +45656,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
45593
45656
  }
45594
45657
  }
45595
45658
  function readInstalledPlugins(home) {
45596
- const file = import_node_path9.default.join(home, ".claude", "plugins", "installed_plugins.json");
45659
+ const file = import_node_path10.default.join(home, ".claude", "plugins", "installed_plugins.json");
45597
45660
  let raw;
45598
45661
  try {
45599
- raw = import_node_fs8.default.readFileSync(file, "utf8");
45662
+ raw = import_node_fs9.default.readFileSync(file, "utf8");
45600
45663
  } catch {
45601
45664
  return [];
45602
45665
  }
@@ -45644,14 +45707,14 @@ var SkillsScanner = class {
45644
45707
  });
45645
45708
  }
45646
45709
  const fsBlock = [];
45647
- scanSkillDir(import_node_path9.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45648
- scanCommandDir(import_node_path9.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45649
- scanSkillDir(import_node_path9.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45650
- scanCommandDir(import_node_path9.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45710
+ scanSkillDir(import_node_path10.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
45711
+ scanCommandDir(import_node_path10.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
45712
+ scanSkillDir(import_node_path10.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
45713
+ scanCommandDir(import_node_path10.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
45651
45714
  const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
45652
45715
  for (const { name, root } of plugins) {
45653
- scanSkillDir(import_node_path9.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45654
- scanCommandDir(import_node_path9.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45716
+ scanSkillDir(import_node_path10.default.join(root, "skills"), "plugin", seen, fsBlock, name);
45717
+ scanCommandDir(import_node_path10.default.join(root, "commands"), "plugin", seen, fsBlock, name);
45655
45718
  }
45656
45719
  fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
45657
45720
  return [...builtinBlock, ...fsBlock];
@@ -45757,8 +45820,8 @@ var PersonaManager = class {
45757
45820
  };
45758
45821
 
45759
45822
  // src/persona/seed.ts
45760
- var fs10 = __toESM(require("fs"), 1);
45761
- var path13 = __toESM(require("path"), 1);
45823
+ var fs11 = __toESM(require("fs"), 1);
45824
+ var path14 = __toESM(require("path"), 1);
45762
45825
  var import_node_url = require("url");
45763
45826
  var import_meta = {};
45764
45827
  var DEFAULT_BYPASS_PROFILE = {
@@ -45928,24 +45991,24 @@ function bundleSiblingFromArgv(argv1, sibling) {
45928
45991
  if (!argv1) return null;
45929
45992
  let real = argv1;
45930
45993
  try {
45931
- real = fs10.realpathSync(argv1);
45994
+ real = fs11.realpathSync(argv1);
45932
45995
  } catch {
45933
45996
  }
45934
- return path13.resolve(path13.dirname(real), sibling);
45997
+ return path14.resolve(path14.dirname(real), sibling);
45935
45998
  }
45936
45999
  function findDefaultsRoot(logger) {
45937
46000
  const candidates = [];
45938
46001
  try {
45939
- const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
45940
- candidates.push(path13.resolve(here, "defaults"));
45941
- candidates.push(path13.resolve(here, "persona-defaults"));
46002
+ const here = path14.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46003
+ candidates.push(path14.resolve(here, "defaults"));
46004
+ candidates.push(path14.resolve(here, "persona-defaults"));
45942
46005
  } catch {
45943
46006
  }
45944
46007
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "persona-defaults");
45945
46008
  if (fromArgv) candidates.push(fromArgv);
45946
46009
  for (const c of candidates) {
45947
46010
  try {
45948
- if (fs10.statSync(c).isDirectory()) {
46011
+ if (fs11.statSync(c).isDirectory()) {
45949
46012
  logger?.info("persona.defaults-root.resolved", { root: c });
45950
46013
  return c;
45951
46014
  }
@@ -45962,8 +46025,8 @@ function seedDefaultPersonas(args) {
45962
46025
  args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
45963
46026
  continue;
45964
46027
  }
45965
- const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
45966
- if (!fs10.existsSync(bundleDir)) {
46028
+ const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
46029
+ if (!fs11.existsSync(bundleDir)) {
45967
46030
  args.logger.warn("persona.seed.skip", {
45968
46031
  personaId: entry.personaId,
45969
46032
  reason: "bundle-missing",
@@ -45971,8 +46034,8 @@ function seedDefaultPersonas(args) {
45971
46034
  });
45972
46035
  continue;
45973
46036
  }
45974
- const claudeMdPath = path13.join(bundleDir, "CLAUDE.md");
45975
- if (!fs10.existsSync(claudeMdPath)) {
46037
+ const claudeMdPath = path14.join(bundleDir, "CLAUDE.md");
46038
+ if (!fs11.existsSync(claudeMdPath)) {
45976
46039
  args.logger.warn("persona.seed.skip", {
45977
46040
  personaId: entry.personaId,
45978
46041
  reason: "no-CLAUDE.md",
@@ -45980,7 +46043,7 @@ function seedDefaultPersonas(args) {
45980
46043
  });
45981
46044
  continue;
45982
46045
  }
45983
- const personality = fs10.readFileSync(claudeMdPath, "utf8");
46046
+ const personality = fs11.readFileSync(claudeMdPath, "utf8");
45984
46047
  const now = Date.now();
45985
46048
  const persona = {
45986
46049
  personaId: entry.personaId,
@@ -46006,17 +46069,17 @@ function seedDefaultPersonas(args) {
46006
46069
  }
46007
46070
  }
46008
46071
  function skipNodeModulesUnder(srcRoot) {
46009
- return (src) => !path13.relative(srcRoot, src).split(path13.sep).includes("node_modules");
46072
+ return (src) => !path14.relative(srcRoot, src).split(path14.sep).includes("node_modules");
46010
46073
  }
46011
46074
  function copyBundleExtras(srcDir, dstDir) {
46012
- for (const entry of fs10.readdirSync(srcDir, { withFileTypes: true })) {
46075
+ for (const entry of fs11.readdirSync(srcDir, { withFileTypes: true })) {
46013
46076
  if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
46014
- const srcPath = path13.join(srcDir, entry.name);
46015
- const dstPath = path13.join(dstDir, entry.name);
46077
+ const srcPath = path14.join(srcDir, entry.name);
46078
+ const dstPath = path14.join(dstDir, entry.name);
46016
46079
  if (entry.isDirectory()) {
46017
- fs10.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46080
+ fs11.cpSync(srcPath, dstPath, { recursive: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46018
46081
  } else if (entry.isFile()) {
46019
- fs10.copyFileSync(srcPath, dstPath);
46082
+ fs11.copyFileSync(srcPath, dstPath);
46020
46083
  }
46021
46084
  }
46022
46085
  }
@@ -46024,16 +46087,16 @@ var DAEMON_MANAGED_PATHS = ["extension-kit", "CLAUDE.md", ".mcp.json"];
46024
46087
  function refreshDaemonManagedDirs(args) {
46025
46088
  const entries = args.entries ?? DEFAULT_PERSONAS;
46026
46089
  for (const entry of entries) {
46027
- const bundleDir = path13.join(args.defaultsRoot, entry.personaId);
46028
- if (!fs10.existsSync(bundleDir)) continue;
46090
+ const bundleDir = path14.join(args.defaultsRoot, entry.personaId);
46091
+ if (!fs11.existsSync(bundleDir)) continue;
46029
46092
  const personaDir = args.store.personaDirPath(entry.personaId);
46030
- if (!fs10.existsSync(personaDir)) continue;
46093
+ if (!fs11.existsSync(personaDir)) continue;
46031
46094
  for (const relPath of DAEMON_MANAGED_PATHS) {
46032
- const srcPath = path13.join(bundleDir, relPath);
46033
- if (!fs10.existsSync(srcPath)) continue;
46034
- const dstPath = path13.join(personaDir, relPath);
46095
+ const srcPath = path14.join(bundleDir, relPath);
46096
+ if (!fs11.existsSync(srcPath)) continue;
46097
+ const dstPath = path14.join(personaDir, relPath);
46035
46098
  try {
46036
- fs10.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46099
+ fs11.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
46037
46100
  args.logger.info("persona.refresh.synced", {
46038
46101
  personaId: entry.personaId,
46039
46102
  path: relPath
@@ -46093,15 +46156,15 @@ function migrateCodexSandbox(args) {
46093
46156
  function findDeployKitRoot(logger) {
46094
46157
  const candidates = [];
46095
46158
  try {
46096
- const here = path13.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46097
- candidates.push(path13.resolve(here, "..", "deploy-kit"));
46159
+ const here = path14.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
46160
+ candidates.push(path14.resolve(here, "..", "deploy-kit"));
46098
46161
  } catch {
46099
46162
  }
46100
46163
  const fromArgv = bundleSiblingFromArgv(process.argv[1], "deploy-kit");
46101
46164
  if (fromArgv) candidates.push(fromArgv);
46102
46165
  for (const c of candidates) {
46103
46166
  try {
46104
- if (fs10.statSync(c).isDirectory()) {
46167
+ if (fs11.statSync(c).isDirectory()) {
46105
46168
  logger?.info("persona.deploy-kit-root.resolved", { root: c });
46106
46169
  return c;
46107
46170
  }
@@ -46112,8 +46175,8 @@ function findDeployKitRoot(logger) {
46112
46175
  return null;
46113
46176
  }
46114
46177
  function seedDeployKit(args) {
46115
- const dst = path13.join(args.dataDir, "deploy-kit");
46116
- fs10.cpSync(args.deployKitBundleRoot, dst, {
46178
+ const dst = path14.join(args.dataDir, "deploy-kit");
46179
+ fs11.cpSync(args.deployKitBundleRoot, dst, {
46117
46180
  recursive: true,
46118
46181
  dereference: true,
46119
46182
  force: false,
@@ -46122,35 +46185,35 @@ function seedDeployKit(args) {
46122
46185
  args.logger.info("deploy-kit.seed.done", { dst });
46123
46186
  }
46124
46187
  function refreshDeployKit(args) {
46125
- const dst = path13.join(args.dataDir, "deploy-kit");
46126
- if (!fs10.existsSync(dst)) {
46188
+ const dst = path14.join(args.dataDir, "deploy-kit");
46189
+ if (!fs11.existsSync(dst)) {
46127
46190
  seedDeployKit(args);
46128
46191
  return;
46129
46192
  }
46130
46193
  for (const sub of ["scripts", "contract"]) {
46131
- const s = path13.join(args.deployKitBundleRoot, sub);
46132
- if (fs10.existsSync(s)) {
46133
- fs10.cpSync(s, path13.join(dst, sub), { recursive: true, force: true, dereference: true });
46194
+ const s = path14.join(args.deployKitBundleRoot, sub);
46195
+ if (fs11.existsSync(s)) {
46196
+ fs11.cpSync(s, path14.join(dst, sub), { recursive: true, force: true, dereference: true });
46134
46197
  }
46135
46198
  }
46136
- const secretsSrc = path13.join(args.deployKitBundleRoot, ".secrets");
46137
- if (fs10.existsSync(secretsSrc)) {
46138
- fs10.mkdirSync(path13.join(dst, ".secrets"), { recursive: true });
46139
- for (const f of fs10.readdirSync(secretsSrc)) {
46199
+ const secretsSrc = path14.join(args.deployKitBundleRoot, ".secrets");
46200
+ if (fs11.existsSync(secretsSrc)) {
46201
+ fs11.mkdirSync(path14.join(dst, ".secrets"), { recursive: true });
46202
+ for (const f of fs11.readdirSync(secretsSrc)) {
46140
46203
  if (!f.endsWith(".example")) continue;
46141
- fs10.copyFileSync(path13.join(secretsSrc, f), path13.join(dst, ".secrets", f));
46204
+ fs11.copyFileSync(path14.join(secretsSrc, f), path14.join(dst, ".secrets", f));
46142
46205
  }
46143
46206
  }
46144
46207
  args.logger.info("deploy-kit.refresh.done", { dst });
46145
46208
  }
46146
46209
 
46147
46210
  // src/share-md-viewer/load.ts
46148
- var import_node_fs10 = __toESM(require("fs"), 1);
46149
- var import_node_path10 = __toESM(require("path"), 1);
46211
+ var import_node_fs11 = __toESM(require("fs"), 1);
46212
+ var import_node_path11 = __toESM(require("path"), 1);
46150
46213
  var import_node_url2 = require("url");
46151
46214
 
46152
46215
  // src/share-md-viewer/asset-loader.ts
46153
- var import_node_fs9 = __toESM(require("fs"), 1);
46216
+ var import_node_fs10 = __toESM(require("fs"), 1);
46154
46217
  function htmlEscape(s) {
46155
46218
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
46156
46219
  }
@@ -46158,12 +46221,12 @@ function createViewerAssetLoader(opts) {
46158
46221
  let viewerTemplate;
46159
46222
  let errorTemplate;
46160
46223
  try {
46161
- viewerTemplate = import_node_fs9.default.readFileSync(opts.viewerHtmlPath, "utf8");
46224
+ viewerTemplate = import_node_fs10.default.readFileSync(opts.viewerHtmlPath, "utf8");
46162
46225
  } catch (err) {
46163
46226
  throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
46164
46227
  }
46165
46228
  try {
46166
- errorTemplate = import_node_fs9.default.readFileSync(opts.errorHtmlPath, "utf8");
46229
+ errorTemplate = import_node_fs10.default.readFileSync(opts.errorHtmlPath, "utf8");
46167
46230
  } catch (err) {
46168
46231
  throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
46169
46232
  }
@@ -46182,25 +46245,25 @@ var import_meta2 = {};
46182
46245
  function tryLoadViewerAssets(logger) {
46183
46246
  const candidates = [];
46184
46247
  try {
46185
- const here = import_node_path10.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
46248
+ const here = import_node_path11.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
46186
46249
  candidates.push(here);
46187
- candidates.push(import_node_path10.default.resolve(here, ".."));
46188
- candidates.push(import_node_path10.default.resolve(here, "..", "..", "dist"));
46250
+ candidates.push(import_node_path11.default.resolve(here, ".."));
46251
+ candidates.push(import_node_path11.default.resolve(here, "..", "..", "dist"));
46189
46252
  } catch {
46190
46253
  }
46191
46254
  if (process.argv[1]) {
46192
46255
  let real = process.argv[1];
46193
46256
  try {
46194
- real = import_node_fs10.default.realpathSync(process.argv[1]);
46257
+ real = import_node_fs11.default.realpathSync(process.argv[1]);
46195
46258
  } catch {
46196
46259
  }
46197
- candidates.push(import_node_path10.default.dirname(real));
46260
+ candidates.push(import_node_path11.default.dirname(real));
46198
46261
  }
46199
46262
  for (const root of candidates) {
46200
- const viewerHtmlPath = import_node_path10.default.join(root, "share-md-viewer.html");
46201
- const errorHtmlPath = import_node_path10.default.join(root, "share-md-viewer-error.html");
46263
+ const viewerHtmlPath = import_node_path11.default.join(root, "share-md-viewer.html");
46264
+ const errorHtmlPath = import_node_path11.default.join(root, "share-md-viewer-error.html");
46202
46265
  try {
46203
- if (import_node_fs10.default.statSync(viewerHtmlPath).isFile() && import_node_fs10.default.statSync(errorHtmlPath).isFile()) {
46266
+ if (import_node_fs11.default.statSync(viewerHtmlPath).isFile() && import_node_fs11.default.statSync(errorHtmlPath).isFile()) {
46204
46267
  logger?.info("share-md-viewer.assets-root.resolved", { root });
46205
46268
  return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
46206
46269
  }
@@ -46215,30 +46278,30 @@ function tryLoadViewerAssets(logger) {
46215
46278
  }
46216
46279
 
46217
46280
  // src/share-ui/load.ts
46218
- var import_node_fs12 = __toESM(require("fs"), 1);
46219
- var import_node_path12 = __toESM(require("path"), 1);
46281
+ var import_node_fs13 = __toESM(require("fs"), 1);
46282
+ var import_node_path13 = __toESM(require("path"), 1);
46220
46283
  var import_node_url3 = require("url");
46221
46284
 
46222
46285
  // src/share-ui/asset-loader.ts
46223
- var import_node_fs11 = __toESM(require("fs"), 1);
46224
- var import_node_path11 = __toESM(require("path"), 1);
46286
+ var import_node_fs12 = __toESM(require("fs"), 1);
46287
+ var import_node_path12 = __toESM(require("path"), 1);
46225
46288
  function createShareUiAssetLoader(opts) {
46226
46289
  let indexHtml;
46227
46290
  try {
46228
- indexHtml = import_node_fs11.default.readFileSync(opts.indexHtmlPath, "utf8");
46291
+ indexHtml = import_node_fs12.default.readFileSync(opts.indexHtmlPath, "utf8");
46229
46292
  } catch (err) {
46230
46293
  throw new Error(`share-ui index.html not found at ${opts.indexHtmlPath}: ${err.message}`);
46231
46294
  }
46232
- const assetsDir = import_node_path11.default.resolve(opts.assetsDir);
46295
+ const assetsDir = import_node_path12.default.resolve(opts.assetsDir);
46233
46296
  return {
46234
46297
  renderIndexHtml() {
46235
46298
  return indexHtml;
46236
46299
  },
46237
46300
  resolveAssetPath(rel) {
46238
- const resolved = import_node_path11.default.resolve(assetsDir, rel);
46239
- if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path11.default.sep)) return null;
46301
+ const resolved = import_node_path12.default.resolve(assetsDir, rel);
46302
+ if (resolved !== assetsDir && !resolved.startsWith(assetsDir + import_node_path12.default.sep)) return null;
46240
46303
  try {
46241
- if (import_node_fs11.default.statSync(resolved).isFile()) return resolved;
46304
+ if (import_node_fs12.default.statSync(resolved).isFile()) return resolved;
46242
46305
  } catch {
46243
46306
  }
46244
46307
  return null;
@@ -46252,28 +46315,28 @@ function bundleDirFromArgv(argv1) {
46252
46315
  if (!argv1) return null;
46253
46316
  let real = argv1;
46254
46317
  try {
46255
- real = import_node_fs12.default.realpathSync(argv1);
46318
+ real = import_node_fs13.default.realpathSync(argv1);
46256
46319
  } catch {
46257
46320
  }
46258
- return import_node_path12.default.dirname(real);
46321
+ return import_node_path13.default.dirname(real);
46259
46322
  }
46260
46323
  function tryLoadShareUi(logger) {
46261
46324
  const candidates = [];
46262
46325
  try {
46263
- const here = import_node_path12.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
46326
+ const here = import_node_path13.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url));
46264
46327
  candidates.push(here);
46265
- candidates.push(import_node_path12.default.resolve(here, ".."));
46266
- candidates.push(import_node_path12.default.resolve(here, "..", "..", "dist"));
46328
+ candidates.push(import_node_path13.default.resolve(here, ".."));
46329
+ candidates.push(import_node_path13.default.resolve(here, "..", "..", "dist"));
46267
46330
  } catch {
46268
46331
  }
46269
46332
  const argvDir = bundleDirFromArgv(process.argv[1]);
46270
46333
  if (argvDir) candidates.push(argvDir);
46271
46334
  for (const root of candidates) {
46272
- const shareUiDir = import_node_path12.default.join(root, "share-ui");
46273
- const indexHtmlPath = import_node_path12.default.join(shareUiDir, "guest.html");
46274
- const assetsDir = import_node_path12.default.join(shareUiDir, "assets");
46335
+ const shareUiDir = import_node_path13.default.join(root, "share-ui");
46336
+ const indexHtmlPath = import_node_path13.default.join(shareUiDir, "guest.html");
46337
+ const assetsDir = import_node_path13.default.join(shareUiDir, "assets");
46275
46338
  try {
46276
- if (import_node_fs12.default.statSync(indexHtmlPath).isFile() && import_node_fs12.default.statSync(assetsDir).isDirectory()) {
46339
+ if (import_node_fs13.default.statSync(indexHtmlPath).isFile() && import_node_fs13.default.statSync(assetsDir).isDirectory()) {
46277
46340
  logger?.info("share-ui.assets-root.resolved", { root: shareUiDir });
46278
46341
  return createShareUiAssetLoader({ indexHtmlPath, assetsDir });
46279
46342
  }
@@ -46351,20 +46414,20 @@ function buildVisitorLogin(deps) {
46351
46414
  }
46352
46415
 
46353
46416
  // src/visitor/visitor-store.ts
46354
- var import_node_fs13 = __toESM(require("fs"), 1);
46355
- var import_node_path13 = __toESM(require("path"), 1);
46417
+ var import_node_fs14 = __toESM(require("fs"), 1);
46418
+ var import_node_path14 = __toESM(require("path"), 1);
46356
46419
  function createVisitorStore(opts) {
46357
- const file = import_node_path13.default.join(opts.dir, "visitors.json");
46420
+ const file = import_node_path14.default.join(opts.dir, "visitors.json");
46358
46421
  const read = () => {
46359
46422
  try {
46360
- return JSON.parse(import_node_fs13.default.readFileSync(file, "utf8"));
46423
+ return JSON.parse(import_node_fs14.default.readFileSync(file, "utf8"));
46361
46424
  } catch {
46362
46425
  return [];
46363
46426
  }
46364
46427
  };
46365
46428
  const write = (rows) => {
46366
- import_node_fs13.default.mkdirSync(opts.dir, { recursive: true });
46367
- import_node_fs13.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46429
+ import_node_fs14.default.mkdirSync(opts.dir, { recursive: true });
46430
+ import_node_fs14.default.writeFileSync(file, JSON.stringify(rows, null, 2));
46368
46431
  };
46369
46432
  return {
46370
46433
  upsert(r) {
@@ -46398,7 +46461,7 @@ init_claude();
46398
46461
 
46399
46462
  // src/tools/codex.ts
46400
46463
  var import_node_child_process4 = require("child_process");
46401
- var import_node_fs15 = __toESM(require("fs"), 1);
46464
+ var import_node_fs16 = __toESM(require("fs"), 1);
46402
46465
 
46403
46466
  // src/tools/codex-session.ts
46404
46467
  var import_node_child_process3 = require("child_process");
@@ -46646,8 +46709,8 @@ function turnStartInput(text) {
46646
46709
  const items = [];
46647
46710
  let leftover = text;
46648
46711
  for (const m2 of text.matchAll(SKILL_RE)) {
46649
- const [marker, name, path77] = m2;
46650
- items.push({ type: "skill", name, path: path77 });
46712
+ const [marker, name, path78] = m2;
46713
+ items.push({ type: "skill", name, path: path78 });
46651
46714
  leftover = leftover.replace(marker, "");
46652
46715
  }
46653
46716
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -46831,10 +46894,10 @@ function sanitizeCodexModel(model) {
46831
46894
  return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
46832
46895
  }
46833
46896
  async function probeCodex(env = process.env) {
46834
- if (env.CODEX_BIN && import_node_fs15.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46897
+ if (env.CODEX_BIN && import_node_fs16.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
46835
46898
  try {
46836
46899
  const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
46837
- if (out && import_node_fs15.default.existsSync(out)) return { available: true, path: out };
46900
+ if (out && import_node_fs16.default.existsSync(out)) return { available: true, path: out };
46838
46901
  } catch {
46839
46902
  }
46840
46903
  return { available: false };
@@ -46880,9 +46943,9 @@ var CodexAdapter = class {
46880
46943
 
46881
46944
  // src/tools/claude-tui.ts
46882
46945
  var import_node_crypto5 = require("crypto");
46883
- var import_node_fs16 = __toESM(require("fs"), 1);
46946
+ var import_node_fs17 = __toESM(require("fs"), 1);
46884
46947
  var import_node_os7 = __toESM(require("os"), 1);
46885
- var import_node_path14 = __toESM(require("path"), 1);
46948
+ var import_node_path15 = __toESM(require("path"), 1);
46886
46949
  var import_headless = __toESM(require_xterm_headless(), 1);
46887
46950
 
46888
46951
  // ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
@@ -48124,9 +48187,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
48124
48187
  function jsonlExistsForCtx(ctx) {
48125
48188
  if (!ctx.toolSessionId) return false;
48126
48189
  const home = import_node_os7.default.homedir();
48127
- const file = import_node_path14.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48190
+ const file = import_node_path15.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
48128
48191
  try {
48129
- return import_node_fs16.default.statSync(file).isFile();
48192
+ return import_node_fs17.default.statSync(file).isFile();
48130
48193
  } catch {
48131
48194
  return false;
48132
48195
  }
@@ -48195,10 +48258,10 @@ var PersonaDispatchManager = class {
48195
48258
  };
48196
48259
 
48197
48260
  // src/dispatch/mcp-config.ts
48198
- var import_node_fs17 = __toESM(require("fs"), 1);
48199
- var import_node_path15 = __toESM(require("path"), 1);
48261
+ var import_node_fs18 = __toESM(require("fs"), 1);
48262
+ var import_node_path16 = __toESM(require("path"), 1);
48200
48263
  function dispatchMcpConfigPath(dataDir) {
48201
- return import_node_path15.default.join(dataDir, "dispatch.mcp.json");
48264
+ return import_node_path16.default.join(dataDir, "dispatch.mcp.json");
48202
48265
  }
48203
48266
  function writeDispatchMcpConfig(args) {
48204
48267
  const cfgPath = dispatchMcpConfigPath(args.dataDir);
@@ -48213,16 +48276,16 @@ function writeDispatchMcpConfig(args) {
48213
48276
  }
48214
48277
  }
48215
48278
  };
48216
- import_node_fs17.default.mkdirSync(args.dataDir, { recursive: true });
48217
- import_node_fs17.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48279
+ import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
48280
+ import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48218
48281
  return cfgPath;
48219
48282
  }
48220
48283
 
48221
48284
  // src/ticket/mcp-config.ts
48222
- var import_node_fs18 = __toESM(require("fs"), 1);
48223
- var import_node_path16 = __toESM(require("path"), 1);
48285
+ var import_node_fs19 = __toESM(require("fs"), 1);
48286
+ var import_node_path17 = __toESM(require("path"), 1);
48224
48287
  function ticketMcpConfigPath(dataDir) {
48225
- return import_node_path16.default.join(dataDir, "ticket.mcp.json");
48288
+ return import_node_path17.default.join(dataDir, "ticket.mcp.json");
48226
48289
  }
48227
48290
  function writeTicketMcpConfig(args) {
48228
48291
  const cfgPath = ticketMcpConfigPath(args.dataDir);
@@ -48243,16 +48306,16 @@ function writeTicketMcpConfig(args) {
48243
48306
  }
48244
48307
  }
48245
48308
  };
48246
- import_node_fs18.default.mkdirSync(args.dataDir, { recursive: true });
48247
- import_node_fs18.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48309
+ import_node_fs19.default.mkdirSync(args.dataDir, { recursive: true });
48310
+ import_node_fs19.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
48248
48311
  return cfgPath;
48249
48312
  }
48250
48313
 
48251
48314
  // src/shift/mcp-config.ts
48252
- var import_node_fs19 = __toESM(require("fs"), 1);
48253
- var import_node_path17 = __toESM(require("path"), 1);
48315
+ var import_node_fs20 = __toESM(require("fs"), 1);
48316
+ var import_node_path18 = __toESM(require("path"), 1);
48254
48317
  function shiftMcpConfigPath(dataDir) {
48255
- return import_node_path17.default.join(dataDir, "shift.mcp.json");
48318
+ return import_node_path18.default.join(dataDir, "shift.mcp.json");
48256
48319
  }
48257
48320
  async function writeShiftMcpConfig(args) {
48258
48321
  const cfgPath = shiftMcpConfigPath(args.dataDir);
@@ -48267,16 +48330,16 @@ async function writeShiftMcpConfig(args) {
48267
48330
  }
48268
48331
  }
48269
48332
  };
48270
- await import_node_fs19.default.promises.mkdir(args.dataDir, { recursive: true });
48271
- await import_node_fs19.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48333
+ await import_node_fs20.default.promises.mkdir(args.dataDir, { recursive: true });
48334
+ await import_node_fs20.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48272
48335
  return cfgPath;
48273
48336
  }
48274
48337
 
48275
48338
  // src/inbox/mcp-config.ts
48276
- var import_node_fs20 = __toESM(require("fs"), 1);
48277
- var import_node_path18 = __toESM(require("path"), 1);
48339
+ var import_node_fs21 = __toESM(require("fs"), 1);
48340
+ var import_node_path19 = __toESM(require("path"), 1);
48278
48341
  function inboxMcpConfigPath(dataDir) {
48279
- return import_node_path18.default.join(dataDir, "inbox.mcp.json");
48342
+ return import_node_path19.default.join(dataDir, "inbox.mcp.json");
48280
48343
  }
48281
48344
  async function writeInboxMcpConfig(args) {
48282
48345
  const cfgPath = inboxMcpConfigPath(args.dataDir);
@@ -48291,14 +48354,14 @@ async function writeInboxMcpConfig(args) {
48291
48354
  }
48292
48355
  }
48293
48356
  };
48294
- await import_node_fs20.default.promises.mkdir(args.dataDir, { recursive: true });
48295
- await import_node_fs20.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48357
+ await import_node_fs21.default.promises.mkdir(args.dataDir, { recursive: true });
48358
+ await import_node_fs21.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
48296
48359
  return cfgPath;
48297
48360
  }
48298
48361
 
48299
48362
  // src/shift/store.ts
48300
48363
  var import_promises = __toESM(require("fs/promises"), 1);
48301
- var import_node_path19 = __toESM(require("path"), 1);
48364
+ var import_node_path20 = __toESM(require("path"), 1);
48302
48365
  var import_node_crypto6 = require("crypto");
48303
48366
 
48304
48367
  // src/shift/constants.ts
@@ -48367,7 +48430,7 @@ function createShiftStore(deps) {
48367
48430
  flushTimer = null;
48368
48431
  }
48369
48432
  const content = { version: 1, shifts };
48370
- await import_promises.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
48433
+ await import_promises.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
48371
48434
  const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
48372
48435
  await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
48373
48436
  await import_promises.default.rename(tmp, deps.filePath);
@@ -49101,13 +49164,13 @@ function mapSkillsListResponse(res) {
49101
49164
  const r = s ?? {};
49102
49165
  const name = str3(r.name);
49103
49166
  if (!name) continue;
49104
- const path77 = str3(r.path);
49167
+ const path78 = str3(r.path);
49105
49168
  const description = str3(r.description);
49106
49169
  const isPlugin = name.includes(":");
49107
49170
  out.push({
49108
49171
  name,
49109
49172
  source: isPlugin ? "plugin" : "project",
49110
- ...path77 ? { path: path77 } : {},
49173
+ ...path78 ? { path: path78 } : {},
49111
49174
  ...description ? { description } : {},
49112
49175
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49113
49176
  });
@@ -49146,23 +49209,23 @@ async function listCodexSkills(cwd, deps = {}) {
49146
49209
  }
49147
49210
 
49148
49211
  // src/workspace/browser.ts
49149
- var import_node_fs21 = __toESM(require("fs"), 1);
49212
+ var import_node_fs22 = __toESM(require("fs"), 1);
49150
49213
  var import_node_os8 = __toESM(require("os"), 1);
49151
- var import_node_path20 = __toESM(require("path"), 1);
49214
+ var import_node_path21 = __toESM(require("path"), 1);
49152
49215
  init_protocol();
49153
49216
  var MAX_FILE_BYTES = 2 * 1024 * 1024;
49154
49217
  function resolveInsideCwd(cwd, subpath) {
49155
- const absCwd = import_node_path20.default.resolve(cwd);
49156
- const joined = import_node_path20.default.resolve(absCwd, subpath ?? ".");
49157
- const rel = import_node_path20.default.relative(absCwd, joined);
49158
- if (rel.startsWith("..") || import_node_path20.default.isAbsolute(rel)) {
49218
+ const absCwd = import_node_path21.default.resolve(cwd);
49219
+ const joined = import_node_path21.default.resolve(absCwd, subpath ?? ".");
49220
+ const rel = import_node_path21.default.relative(absCwd, joined);
49221
+ if (rel.startsWith("..") || import_node_path21.default.isAbsolute(rel)) {
49159
49222
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
49160
49223
  }
49161
49224
  return joined;
49162
49225
  }
49163
49226
  function ensureCwd(cwd) {
49164
49227
  try {
49165
- const stat = import_node_fs21.default.statSync(cwd);
49228
+ const stat = import_node_fs22.default.statSync(cwd);
49166
49229
  if (!stat.isDirectory()) {
49167
49230
  throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
49168
49231
  }
@@ -49176,7 +49239,7 @@ var WorkspaceBrowser = class {
49176
49239
  const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
49177
49240
  ensureCwd(cwd);
49178
49241
  const full = resolveInsideCwd(cwd, args.path);
49179
- const dirents = import_node_fs21.default.readdirSync(full, { withFileTypes: true });
49242
+ const dirents = import_node_fs22.default.readdirSync(full, { withFileTypes: true });
49180
49243
  const entries = [];
49181
49244
  for (const d of dirents) {
49182
49245
  if (!args.showHidden && d.name.startsWith(".")) continue;
@@ -49186,7 +49249,7 @@ var WorkspaceBrowser = class {
49186
49249
  mtime: ""
49187
49250
  };
49188
49251
  try {
49189
- const st = import_node_fs21.default.statSync(import_node_path20.default.join(full, d.name));
49252
+ const st = import_node_fs22.default.statSync(import_node_path21.default.join(full, d.name));
49190
49253
  entry.mtime = new Date(st.mtimeMs).toISOString();
49191
49254
  if (d.isFile()) entry.size = st.size;
49192
49255
  } catch {
@@ -49202,14 +49265,14 @@ var WorkspaceBrowser = class {
49202
49265
  read(args) {
49203
49266
  ensureCwd(args.cwd);
49204
49267
  const full = resolveInsideCwd(args.cwd, args.path);
49205
- const st = import_node_fs21.default.statSync(full);
49268
+ const st = import_node_fs22.default.statSync(full);
49206
49269
  if (!st.isFile()) {
49207
49270
  throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
49208
49271
  }
49209
49272
  if (st.size > MAX_FILE_BYTES) {
49210
49273
  throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
49211
49274
  }
49212
- const buf = import_node_fs21.default.readFileSync(full);
49275
+ const buf = import_node_fs22.default.readFileSync(full);
49213
49276
  const isBinary = buf.includes(0);
49214
49277
  if (isBinary) {
49215
49278
  return {
@@ -49231,20 +49294,20 @@ var WorkspaceBrowser = class {
49231
49294
  };
49232
49295
 
49233
49296
  // src/skills/agents-scanner.ts
49234
- var import_node_fs22 = __toESM(require("fs"), 1);
49297
+ var import_node_fs23 = __toESM(require("fs"), 1);
49235
49298
  var import_node_os9 = __toESM(require("os"), 1);
49236
- var import_node_path21 = __toESM(require("path"), 1);
49299
+ var import_node_path22 = __toESM(require("path"), 1);
49237
49300
  var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
49238
49301
  function isDirLikeSync2(p2) {
49239
49302
  try {
49240
- return import_node_fs22.default.statSync(p2).isDirectory();
49303
+ return import_node_fs23.default.statSync(p2).isDirectory();
49241
49304
  } catch {
49242
49305
  return false;
49243
49306
  }
49244
49307
  }
49245
49308
  function fileExistsSync(p2) {
49246
49309
  try {
49247
- return import_node_fs22.default.statSync(p2).isFile();
49310
+ return import_node_fs23.default.statSync(p2).isFile();
49248
49311
  } catch {
49249
49312
  return false;
49250
49313
  }
@@ -49252,7 +49315,7 @@ function fileExistsSync(p2) {
49252
49315
  function parseAgentFile(filePath) {
49253
49316
  let content;
49254
49317
  try {
49255
- content = import_node_fs22.default.readFileSync(filePath, "utf8");
49318
+ content = import_node_fs23.default.readFileSync(filePath, "utf8");
49256
49319
  } catch {
49257
49320
  return {};
49258
49321
  }
@@ -49265,16 +49328,16 @@ function parseAgentFile(filePath) {
49265
49328
  function scanAgentsDir(dir, source, seen, out) {
49266
49329
  let entries;
49267
49330
  try {
49268
- entries = import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
49331
+ entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49269
49332
  } catch {
49270
49333
  return;
49271
49334
  }
49272
49335
  for (const ent of entries) {
49273
49336
  if (!ent.name.endsWith(".md")) continue;
49274
- if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path21.default.join(dir, ent.name)))) {
49337
+ if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path22.default.join(dir, ent.name)))) {
49275
49338
  continue;
49276
49339
  }
49277
- const filePath = import_node_path21.default.join(dir, ent.name);
49340
+ const filePath = import_node_path22.default.join(dir, ent.name);
49278
49341
  const baseName = ent.name.replace(/\.md$/, "");
49279
49342
  if (seen.has(baseName)) continue;
49280
49343
  seen.add(baseName);
@@ -49292,12 +49355,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49292
49355
  function walk2(dir, namespaces) {
49293
49356
  let entries;
49294
49357
  try {
49295
- entries = import_node_fs22.default.readdirSync(dir, { withFileTypes: true });
49358
+ entries = import_node_fs23.default.readdirSync(dir, { withFileTypes: true });
49296
49359
  } catch {
49297
49360
  return;
49298
49361
  }
49299
49362
  for (const ent of entries) {
49300
- const childPath = import_node_path21.default.join(dir, ent.name);
49363
+ const childPath = import_node_path22.default.join(dir, ent.name);
49301
49364
  if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
49302
49365
  walk2(childPath, [...namespaces, ent.name]);
49303
49366
  continue;
@@ -49322,13 +49385,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
49322
49385
  walk2(root, []);
49323
49386
  }
49324
49387
  function readInstalledPlugins2(home) {
49325
- const pluginsDir = import_node_path21.default.join(home, ".claude", "plugins");
49326
- const v2 = import_node_path21.default.join(pluginsDir, "installed_plugins_v2.json");
49327
- const v1 = import_node_path21.default.join(pluginsDir, "installed_plugins.json");
49388
+ const pluginsDir = import_node_path22.default.join(home, ".claude", "plugins");
49389
+ const v2 = import_node_path22.default.join(pluginsDir, "installed_plugins_v2.json");
49390
+ const v1 = import_node_path22.default.join(pluginsDir, "installed_plugins.json");
49328
49391
  let raw = null;
49329
49392
  for (const candidate of [v2, v1]) {
49330
49393
  try {
49331
- raw = import_node_fs22.default.readFileSync(candidate, "utf8");
49394
+ raw = import_node_fs23.default.readFileSync(candidate, "utf8");
49332
49395
  break;
49333
49396
  } catch {
49334
49397
  }
@@ -49353,19 +49416,19 @@ function readInstalledPlugins2(home) {
49353
49416
  return out;
49354
49417
  }
49355
49418
  function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
49356
- let cur = import_node_path21.default.resolve(startCwd);
49357
- const fsRoot = import_node_path21.default.parse(cur).root;
49419
+ let cur = import_node_path22.default.resolve(startCwd);
49420
+ const fsRoot = import_node_path22.default.parse(cur).root;
49358
49421
  while (true) {
49359
- scanAgentsDir(import_node_path21.default.join(cur, ".claude", "agents"), "project", seen, out);
49422
+ scanAgentsDir(import_node_path22.default.join(cur, ".claude", "agents"), "project", seen, out);
49360
49423
  let hasGit = false;
49361
49424
  try {
49362
- hasGit = import_node_fs22.default.existsSync(import_node_path21.default.join(cur, ".git"));
49425
+ hasGit = import_node_fs23.default.existsSync(import_node_path22.default.join(cur, ".git"));
49363
49426
  } catch {
49364
49427
  }
49365
49428
  if (hasGit) return;
49366
49429
  if (cur === home) return;
49367
49430
  if (cur === fsRoot) return;
49368
- const parent = import_node_path21.default.dirname(cur);
49431
+ const parent = import_node_path22.default.dirname(cur);
49369
49432
  if (parent === cur) return;
49370
49433
  cur = parent;
49371
49434
  }
@@ -49400,7 +49463,7 @@ var AgentsScanner = class {
49400
49463
  }
49401
49464
  const fsBlock = [];
49402
49465
  scanAgentsDir(
49403
- import_node_path21.default.join(this.home, ".claude", "agents"),
49466
+ import_node_path22.default.join(this.home, ".claude", "agents"),
49404
49467
  "global",
49405
49468
  seen,
49406
49469
  fsBlock
@@ -49414,7 +49477,7 @@ var AgentsScanner = class {
49414
49477
  ...this.extraPluginRoots
49415
49478
  ];
49416
49479
  for (const { name, root } of plugins) {
49417
- const agentsRoot = import_node_path21.default.join(root, "agents");
49480
+ const agentsRoot = import_node_path22.default.join(root, "agents");
49418
49481
  scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
49419
49482
  }
49420
49483
  return [...builtinBlock, ...fsBlock];
@@ -49422,15 +49485,15 @@ var AgentsScanner = class {
49422
49485
  };
49423
49486
 
49424
49487
  // src/observer/session-observer.ts
49425
- var import_node_fs24 = __toESM(require("fs"), 1);
49488
+ var import_node_fs25 = __toESM(require("fs"), 1);
49426
49489
  var import_node_os11 = __toESM(require("os"), 1);
49427
- var import_node_path23 = __toESM(require("path"), 1);
49490
+ var import_node_path24 = __toESM(require("path"), 1);
49428
49491
  init_claude_history();
49429
49492
 
49430
49493
  // src/observer/subagent-meta-observer.ts
49431
- var import_node_fs23 = __toESM(require("fs"), 1);
49494
+ var import_node_fs24 = __toESM(require("fs"), 1);
49432
49495
  var import_node_os10 = __toESM(require("os"), 1);
49433
- var import_node_path22 = __toESM(require("path"), 1);
49496
+ var import_node_path23 = __toESM(require("path"), 1);
49434
49497
  init_claude_history();
49435
49498
  var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
49436
49499
  var SubagentMetaObserver = class {
@@ -49443,7 +49506,7 @@ var SubagentMetaObserver = class {
49443
49506
  watches = /* @__PURE__ */ new Map();
49444
49507
  // public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
49445
49508
  resolveSubagentDir(cwd, toolSessionId) {
49446
- return import_node_path22.default.join(
49509
+ return import_node_path23.default.join(
49447
49510
  this.home,
49448
49511
  ".claude",
49449
49512
  "projects",
@@ -49473,7 +49536,7 @@ var SubagentMetaObserver = class {
49473
49536
  attachWatcher(w2) {
49474
49537
  if (w2.watcher) return;
49475
49538
  try {
49476
- w2.watcher = import_node_fs23.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49539
+ w2.watcher = import_node_fs24.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
49477
49540
  if (!name) return;
49478
49541
  const m2 = META_RE.exec(String(name));
49479
49542
  if (!m2) return;
@@ -49485,7 +49548,7 @@ var SubagentMetaObserver = class {
49485
49548
  scan(w2) {
49486
49549
  let entries;
49487
49550
  try {
49488
- entries = import_node_fs23.default.readdirSync(w2.dirPath);
49551
+ entries = import_node_fs24.default.readdirSync(w2.dirPath);
49489
49552
  } catch {
49490
49553
  return;
49491
49554
  }
@@ -49499,10 +49562,10 @@ var SubagentMetaObserver = class {
49499
49562
  if (!m2) return;
49500
49563
  const agentId = m2[1];
49501
49564
  if (w2.emitted.has(agentId)) return;
49502
- const file = import_node_path22.default.join(w2.dirPath, name);
49565
+ const file = import_node_path23.default.join(w2.dirPath, name);
49503
49566
  let raw;
49504
49567
  try {
49505
- raw = import_node_fs23.default.readFileSync(file, "utf8");
49568
+ raw = import_node_fs24.default.readFileSync(file, "utf8");
49506
49569
  } catch {
49507
49570
  return;
49508
49571
  }
@@ -49559,14 +49622,14 @@ var SessionObserver = class {
49559
49622
  metaObserver;
49560
49623
  resolveJsonlPath(cwd, toolSessionId, override) {
49561
49624
  if (override) return override;
49562
- return import_node_path23.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
49625
+ return import_node_path24.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
49563
49626
  }
49564
49627
  start(args) {
49565
49628
  this.stop(args.sessionId);
49566
49629
  const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
49567
49630
  let size = 0;
49568
49631
  try {
49569
- size = import_node_fs24.default.statSync(filePath).size;
49632
+ size = import_node_fs25.default.statSync(filePath).size;
49570
49633
  } catch {
49571
49634
  }
49572
49635
  const w2 = {
@@ -49580,10 +49643,10 @@ var SessionObserver = class {
49580
49643
  prevIsRejectSentinel: false
49581
49644
  };
49582
49645
  try {
49583
- import_node_fs24.default.mkdirSync(import_node_path23.default.dirname(filePath), { recursive: true });
49646
+ import_node_fs25.default.mkdirSync(import_node_path24.default.dirname(filePath), { recursive: true });
49584
49647
  } catch {
49585
49648
  }
49586
- w2.watcher = import_node_fs24.default.watch(import_node_path23.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49649
+ w2.watcher = import_node_fs25.default.watch(import_node_path24.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
49587
49650
  if (!changedName || !filePath.endsWith(changedName)) return;
49588
49651
  this.poll(w2);
49589
49652
  });
@@ -49606,7 +49669,7 @@ var SessionObserver = class {
49606
49669
  // 异常静默吞,不阻塞 watcher 启动
49607
49670
  hydrateMetaTail(w2, maxLines = 200) {
49608
49671
  try {
49609
- const raw = import_node_fs24.default.readFileSync(w2.filePath, "utf8");
49672
+ const raw = import_node_fs25.default.readFileSync(w2.filePath, "utf8");
49610
49673
  if (!raw) return;
49611
49674
  const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
49612
49675
  if (allLines.length === 0) return;
@@ -49630,7 +49693,7 @@ var SessionObserver = class {
49630
49693
  poll(w2) {
49631
49694
  let size = 0;
49632
49695
  try {
49633
- size = import_node_fs24.default.statSync(w2.filePath).size;
49696
+ size = import_node_fs25.default.statSync(w2.filePath).size;
49634
49697
  } catch {
49635
49698
  return;
49636
49699
  }
@@ -49639,11 +49702,11 @@ var SessionObserver = class {
49639
49702
  w2.buf = "";
49640
49703
  }
49641
49704
  if (size === w2.lastSize) return;
49642
- const fd = import_node_fs24.default.openSync(w2.filePath, "r");
49705
+ const fd = import_node_fs25.default.openSync(w2.filePath, "r");
49643
49706
  try {
49644
49707
  const len = size - w2.lastSize;
49645
49708
  const buf = Buffer.alloc(len);
49646
- import_node_fs24.default.readSync(fd, buf, 0, len, w2.lastSize);
49709
+ import_node_fs25.default.readSync(fd, buf, 0, len, w2.lastSize);
49647
49710
  w2.lastSize = size;
49648
49711
  w2.buf += buf.toString("utf8");
49649
49712
  let newlineIndex;
@@ -49666,7 +49729,7 @@ var SessionObserver = class {
49666
49729
  }
49667
49730
  }
49668
49731
  } finally {
49669
- import_node_fs24.default.closeSync(fd);
49732
+ import_node_fs25.default.closeSync(fd);
49670
49733
  }
49671
49734
  }
49672
49735
  // 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
@@ -50469,15 +50532,15 @@ async function authenticate(token, deps) {
50469
50532
  }
50470
50533
 
50471
50534
  // src/permission/capability-store.ts
50472
- var fs28 = __toESM(require("fs"), 1);
50473
- var path28 = __toESM(require("path"), 1);
50535
+ var fs29 = __toESM(require("fs"), 1);
50536
+ var path29 = __toESM(require("path"), 1);
50474
50537
  init_src();
50475
50538
  var CAPABILITIES_FILE_NAME = "capabilities.json";
50476
50539
  var FILE_VERSION = 1;
50477
50540
  var CapabilityStore = class {
50478
50541
  constructor(dataDir) {
50479
50542
  this.dataDir = dataDir;
50480
- fs28.mkdirSync(dataDir, { recursive: true });
50543
+ fs29.mkdirSync(dataDir, { recursive: true });
50481
50544
  this.cache = this.readFromDisk();
50482
50545
  }
50483
50546
  dataDir;
@@ -50501,13 +50564,13 @@ var CapabilityStore = class {
50501
50564
  this.flush();
50502
50565
  }
50503
50566
  filePath() {
50504
- return path28.join(this.dataDir, CAPABILITIES_FILE_NAME);
50567
+ return path29.join(this.dataDir, CAPABILITIES_FILE_NAME);
50505
50568
  }
50506
50569
  readFromDisk() {
50507
50570
  const file = this.filePath();
50508
50571
  let raw;
50509
50572
  try {
50510
- raw = fs28.readFileSync(file, "utf8");
50573
+ raw = fs29.readFileSync(file, "utf8");
50511
50574
  } catch (err) {
50512
50575
  if (err?.code === "ENOENT") return [];
50513
50576
  return [];
@@ -50535,10 +50598,10 @@ var CapabilityStore = class {
50535
50598
  }
50536
50599
  atomicWrite(file, content) {
50537
50600
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50538
- fs28.writeFileSync(tmp, content, { mode: 384 });
50539
- fs28.renameSync(tmp, file);
50601
+ fs29.writeFileSync(tmp, content, { mode: 384 });
50602
+ fs29.renameSync(tmp, file);
50540
50603
  try {
50541
- fs28.chmodSync(file, 384);
50604
+ fs29.chmodSync(file, 384);
50542
50605
  } catch {
50543
50606
  }
50544
50607
  }
@@ -50631,14 +50694,14 @@ var CapabilityManager = class {
50631
50694
  };
50632
50695
 
50633
50696
  // src/permission/cleanup.ts
50634
- var fs29 = __toESM(require("fs"), 1);
50697
+ var fs30 = __toESM(require("fs"), 1);
50635
50698
  function cleanupGuestSessionsForCapability(cap, factory) {
50636
50699
  const removed = [];
50637
50700
  for (const g2 of cap.grants) {
50638
50701
  if (g2.resource.type !== "persona") continue;
50639
50702
  const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
50640
50703
  try {
50641
- fs29.rmSync(dir, { recursive: true, force: true });
50704
+ fs30.rmSync(dir, { recursive: true, force: true });
50642
50705
  removed.push(dir);
50643
50706
  } catch {
50644
50707
  }
@@ -50647,14 +50710,14 @@ function cleanupGuestSessionsForCapability(cap, factory) {
50647
50710
  }
50648
50711
 
50649
50712
  // src/inbox/inbox-store.ts
50650
- var fs30 = __toESM(require("fs"), 1);
50651
- var path29 = __toESM(require("path"), 1);
50713
+ var fs31 = __toESM(require("fs"), 1);
50714
+ var path30 = __toESM(require("path"), 1);
50652
50715
  init_src();
50653
50716
  var INBOX_SUBDIR = "inbox";
50654
50717
  var InboxStore = class {
50655
50718
  constructor(dataDir) {
50656
50719
  this.dataDir = dataDir;
50657
- fs30.mkdirSync(this.dirPath(), { recursive: true });
50720
+ fs31.mkdirSync(this.dirPath(), { recursive: true });
50658
50721
  }
50659
50722
  dataDir;
50660
50723
  /**
@@ -50666,7 +50729,7 @@ var InboxStore = class {
50666
50729
  const file = this.filePath(peerDeviceId);
50667
50730
  let raw;
50668
50731
  try {
50669
- raw = fs30.readFileSync(file, "utf8");
50732
+ raw = fs31.readFileSync(file, "utf8");
50670
50733
  } catch (err) {
50671
50734
  if (err?.code === "ENOENT") return [];
50672
50735
  return [];
@@ -50682,7 +50745,7 @@ var InboxStore = class {
50682
50745
  const dir = this.dirPath();
50683
50746
  let entries;
50684
50747
  try {
50685
- entries = fs30.readdirSync(dir);
50748
+ entries = fs31.readdirSync(dir);
50686
50749
  } catch (err) {
50687
50750
  if (err?.code === "ENOENT") return [];
50688
50751
  return [];
@@ -50698,9 +50761,9 @@ var InboxStore = class {
50698
50761
  if (existing.some((m2) => m2.id === message.id)) return;
50699
50762
  const file = this.filePath(message.peerDeviceId);
50700
50763
  const line = JSON.stringify(message) + "\n";
50701
- fs30.appendFileSync(file, line, { mode: 384 });
50764
+ fs31.appendFileSync(file, line, { mode: 384 });
50702
50765
  try {
50703
- fs30.chmodSync(file, 384);
50766
+ fs31.chmodSync(file, 384);
50704
50767
  } catch {
50705
50768
  }
50706
50769
  }
@@ -50730,7 +50793,7 @@ var InboxStore = class {
50730
50793
  removeByPeerDeviceId(peerDeviceId) {
50731
50794
  const file = this.filePath(peerDeviceId);
50732
50795
  try {
50733
- fs30.unlinkSync(file);
50796
+ fs31.unlinkSync(file);
50734
50797
  } catch (err) {
50735
50798
  if (err?.code === "ENOENT") return;
50736
50799
  }
@@ -50739,18 +50802,18 @@ var InboxStore = class {
50739
50802
  const file = this.filePath(peerDeviceId);
50740
50803
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
50741
50804
  const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
50742
- fs30.writeFileSync(tmp, content, { mode: 384 });
50743
- fs30.renameSync(tmp, file);
50805
+ fs31.writeFileSync(tmp, content, { mode: 384 });
50806
+ fs31.renameSync(tmp, file);
50744
50807
  try {
50745
- fs30.chmodSync(file, 384);
50808
+ fs31.chmodSync(file, 384);
50746
50809
  } catch {
50747
50810
  }
50748
50811
  }
50749
50812
  dirPath() {
50750
- return path29.join(this.dataDir, INBOX_SUBDIR);
50813
+ return path30.join(this.dataDir, INBOX_SUBDIR);
50751
50814
  }
50752
50815
  filePath(peerDeviceId) {
50753
- return path29.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50816
+ return path30.join(this.dirPath(), `${peerDeviceId}.jsonl`);
50754
50817
  }
50755
50818
  };
50756
50819
  function parseAllLines(raw) {
@@ -50838,8 +50901,8 @@ var InboxManager = class {
50838
50901
  };
50839
50902
 
50840
50903
  // src/state/contact-store.ts
50841
- var fs31 = __toESM(require("fs"), 1);
50842
- var path30 = __toESM(require("path"), 1);
50904
+ var fs32 = __toESM(require("fs"), 1);
50905
+ var path31 = __toESM(require("path"), 1);
50843
50906
  init_src();
50844
50907
  var FILE_NAME = "contacts.json";
50845
50908
  var ContactStore = class {
@@ -50850,10 +50913,10 @@ var ContactStore = class {
50850
50913
  contacts = /* @__PURE__ */ new Map();
50851
50914
  load() {
50852
50915
  this.contacts.clear();
50853
- const file = path30.join(this.dataDir, FILE_NAME);
50916
+ const file = path31.join(this.dataDir, FILE_NAME);
50854
50917
  let raw;
50855
50918
  try {
50856
- raw = fs31.readFileSync(file, "utf8");
50919
+ raw = fs32.readFileSync(file, "utf8");
50857
50920
  } catch (err) {
50858
50921
  if (err?.code !== "ENOENT") this.renameBak(file);
50859
50922
  return;
@@ -50925,20 +50988,20 @@ var ContactStore = class {
50925
50988
  return true;
50926
50989
  }
50927
50990
  flush() {
50928
- const file = path30.join(this.dataDir, FILE_NAME);
50991
+ const file = path31.join(this.dataDir, FILE_NAME);
50929
50992
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
50930
50993
  const content = JSON.stringify(
50931
50994
  { contacts: Array.from(this.contacts.values()) },
50932
50995
  null,
50933
50996
  2
50934
50997
  );
50935
- fs31.mkdirSync(this.dataDir, { recursive: true });
50936
- fs31.writeFileSync(tmp, content, { mode: 384 });
50937
- fs31.renameSync(tmp, file);
50998
+ fs32.mkdirSync(this.dataDir, { recursive: true });
50999
+ fs32.writeFileSync(tmp, content, { mode: 384 });
51000
+ fs32.renameSync(tmp, file);
50938
51001
  }
50939
51002
  renameBak(file) {
50940
51003
  try {
50941
- fs31.renameSync(file, `${file}.bak`);
51004
+ fs32.renameSync(file, `${file}.bak`);
50942
51005
  } catch {
50943
51006
  }
50944
51007
  }
@@ -51095,61 +51158,61 @@ async function autoReverseContact(args) {
51095
51158
  init_src();
51096
51159
 
51097
51160
  // src/migrations/2026-05-20-flatten-sessions.ts
51098
- var fs32 = __toESM(require("fs"), 1);
51099
- var path31 = __toESM(require("path"), 1);
51161
+ var fs33 = __toESM(require("fs"), 1);
51162
+ var path32 = __toESM(require("path"), 1);
51100
51163
  var MIGRATION_FLAG_NAME = ".migration.v1.done";
51101
51164
  function migrateFlattenSessions(opts) {
51102
51165
  const dataDir = opts.dataDir;
51103
51166
  const now = opts.now ?? Date.now;
51104
- const sessionsDir = path31.join(dataDir, "sessions");
51105
- const flagPath = path31.join(sessionsDir, MIGRATION_FLAG_NAME);
51167
+ const sessionsDir = path32.join(dataDir, "sessions");
51168
+ const flagPath = path32.join(sessionsDir, MIGRATION_FLAG_NAME);
51106
51169
  if (existsSync3(flagPath)) {
51107
51170
  return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
51108
51171
  }
51109
51172
  let movedBare = 0;
51110
51173
  let movedVmOwner = 0;
51111
51174
  let archivedListener = 0;
51112
- const defaultDir = path31.join(sessionsDir, "default");
51175
+ const defaultDir = path32.join(sessionsDir, "default");
51113
51176
  if (existsSync3(defaultDir)) {
51114
51177
  for (const entry of readdirSafe(defaultDir)) {
51115
51178
  if (!entry.endsWith(".json")) continue;
51116
- const src = path31.join(defaultDir, entry);
51117
- const dst = path31.join(sessionsDir, entry);
51118
- fs32.renameSync(src, dst);
51179
+ const src = path32.join(defaultDir, entry);
51180
+ const dst = path32.join(sessionsDir, entry);
51181
+ fs33.renameSync(src, dst);
51119
51182
  movedBare += 1;
51120
51183
  }
51121
51184
  rmdirIfEmpty(defaultDir);
51122
51185
  }
51123
51186
  for (const pid of readdirSafe(sessionsDir)) {
51124
- const personaDir = path31.join(sessionsDir, pid);
51187
+ const personaDir = path32.join(sessionsDir, pid);
51125
51188
  if (!isDir(personaDir)) continue;
51126
51189
  if (pid === "default") continue;
51127
- const ownerSrc = path31.join(personaDir, "owner");
51190
+ const ownerSrc = path32.join(personaDir, "owner");
51128
51191
  if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
51129
- const ownerDst = path31.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51130
- fs32.mkdirSync(ownerDst, { recursive: true });
51192
+ const ownerDst = path32.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
51193
+ fs33.mkdirSync(ownerDst, { recursive: true });
51131
51194
  for (const file of readdirSafe(ownerSrc)) {
51132
51195
  if (!file.endsWith(".json")) continue;
51133
- fs32.renameSync(path31.join(ownerSrc, file), path31.join(ownerDst, file));
51196
+ fs33.renameSync(path32.join(ownerSrc, file), path32.join(ownerDst, file));
51134
51197
  movedVmOwner += 1;
51135
51198
  }
51136
51199
  rmdirIfEmpty(ownerSrc);
51137
51200
  }
51138
- const listenerSrc = path31.join(personaDir, "listener");
51201
+ const listenerSrc = path32.join(personaDir, "listener");
51139
51202
  if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
51140
- const archiveDst = path31.join(dataDir, ".legacy", `listener-${pid}`);
51141
- fs32.mkdirSync(archiveDst, { recursive: true });
51203
+ const archiveDst = path32.join(dataDir, ".legacy", `listener-${pid}`);
51204
+ fs33.mkdirSync(archiveDst, { recursive: true });
51142
51205
  for (const file of readdirSafe(listenerSrc)) {
51143
51206
  if (!file.endsWith(".json")) continue;
51144
- fs32.renameSync(path31.join(listenerSrc, file), path31.join(archiveDst, file));
51207
+ fs33.renameSync(path32.join(listenerSrc, file), path32.join(archiveDst, file));
51145
51208
  archivedListener += 1;
51146
51209
  }
51147
51210
  rmdirIfEmpty(listenerSrc);
51148
51211
  }
51149
51212
  rmdirIfEmpty(personaDir);
51150
51213
  }
51151
- fs32.mkdirSync(sessionsDir, { recursive: true });
51152
- fs32.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51214
+ fs33.mkdirSync(sessionsDir, { recursive: true });
51215
+ fs33.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
51153
51216
  return {
51154
51217
  skipped: false,
51155
51218
  flagWritten: true,
@@ -51160,7 +51223,7 @@ function migrateFlattenSessions(opts) {
51160
51223
  }
51161
51224
  function existsSync3(p2) {
51162
51225
  try {
51163
- fs32.statSync(p2);
51226
+ fs33.statSync(p2);
51164
51227
  return true;
51165
51228
  } catch {
51166
51229
  return false;
@@ -51168,31 +51231,31 @@ function existsSync3(p2) {
51168
51231
  }
51169
51232
  function isDir(p2) {
51170
51233
  try {
51171
- return fs32.statSync(p2).isDirectory();
51234
+ return fs33.statSync(p2).isDirectory();
51172
51235
  } catch {
51173
51236
  return false;
51174
51237
  }
51175
51238
  }
51176
51239
  function readdirSafe(p2) {
51177
51240
  try {
51178
- return fs32.readdirSync(p2);
51241
+ return fs33.readdirSync(p2);
51179
51242
  } catch {
51180
51243
  return [];
51181
51244
  }
51182
51245
  }
51183
51246
  function rmdirIfEmpty(p2) {
51184
51247
  try {
51185
- fs32.rmdirSync(p2);
51248
+ fs33.rmdirSync(p2);
51186
51249
  } catch {
51187
51250
  }
51188
51251
  }
51189
51252
 
51190
51253
  // src/transport/http-router.ts
51191
- var import_node_fs26 = __toESM(require("fs"), 1);
51192
- var import_node_path27 = __toESM(require("path"), 1);
51254
+ var import_node_fs27 = __toESM(require("fs"), 1);
51255
+ var import_node_path28 = __toESM(require("path"), 1);
51193
51256
 
51194
51257
  // src/attachment/mime.ts
51195
- var import_node_path24 = __toESM(require("path"), 1);
51258
+ var import_node_path25 = __toESM(require("path"), 1);
51196
51259
  var TEXT_PLAIN = "text/plain; charset=utf-8";
51197
51260
  var EXT_TO_NATIVE_MIME = {
51198
51261
  // 图片
@@ -51299,7 +51362,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
51299
51362
  ".mk"
51300
51363
  ]);
51301
51364
  function lookupMime(filePathOrName) {
51302
- const ext = import_node_path24.default.extname(filePathOrName).toLowerCase();
51365
+ const ext = import_node_path25.default.extname(filePathOrName).toLowerCase();
51303
51366
  if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
51304
51367
  if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
51305
51368
  return "application/octet-stream";
@@ -51368,8 +51431,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
51368
51431
  }
51369
51432
 
51370
51433
  // src/attachment/upload.ts
51371
- var import_node_fs25 = __toESM(require("fs"), 1);
51372
- var import_node_path25 = __toESM(require("path"), 1);
51434
+ var import_node_fs26 = __toESM(require("fs"), 1);
51435
+ var import_node_path26 = __toESM(require("path"), 1);
51373
51436
  var import_node_crypto8 = __toESM(require("crypto"), 1);
51374
51437
  var import_promises2 = require("stream/promises");
51375
51438
  var UploadError = class extends Error {
@@ -51381,22 +51444,22 @@ var UploadError = class extends Error {
51381
51444
  code;
51382
51445
  };
51383
51446
  function assertValidFileName(fileName) {
51384
- if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path25.default.basename(fileName)) {
51447
+ if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path26.default.basename(fileName)) {
51385
51448
  throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
51386
51449
  }
51387
51450
  }
51388
51451
  var HASH_PREFIX_LEN = 16;
51389
51452
  async function writeUploadedAttachment(args) {
51390
51453
  assertValidFileName(args.fileName);
51391
- const attachmentsRoot = import_node_path25.default.join(args.sessionDir, ".attachments");
51454
+ const attachmentsRoot = import_node_path26.default.join(args.sessionDir, ".attachments");
51392
51455
  try {
51393
- import_node_fs25.default.mkdirSync(attachmentsRoot, { recursive: true });
51456
+ import_node_fs26.default.mkdirSync(attachmentsRoot, { recursive: true });
51394
51457
  } catch (err) {
51395
51458
  throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
51396
51459
  }
51397
51460
  const hasher = import_node_crypto8.default.createHash("sha256");
51398
51461
  let actualSize = 0;
51399
- const tmpPath = import_node_path25.default.join(
51462
+ const tmpPath = import_node_path26.default.join(
51400
51463
  attachmentsRoot,
51401
51464
  `.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
51402
51465
  );
@@ -51411,18 +51474,18 @@ async function writeUploadedAttachment(args) {
51411
51474
  yield buf;
51412
51475
  }
51413
51476
  },
51414
- import_node_fs25.default.createWriteStream(tmpPath, { mode: 384 })
51477
+ import_node_fs26.default.createWriteStream(tmpPath, { mode: 384 })
51415
51478
  );
51416
51479
  } catch (err) {
51417
51480
  try {
51418
- import_node_fs25.default.unlinkSync(tmpPath);
51481
+ import_node_fs26.default.unlinkSync(tmpPath);
51419
51482
  } catch {
51420
51483
  }
51421
51484
  throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
51422
51485
  }
51423
51486
  if (actualSize !== args.contentLength) {
51424
51487
  try {
51425
- import_node_fs25.default.unlinkSync(tmpPath);
51488
+ import_node_fs26.default.unlinkSync(tmpPath);
51426
51489
  } catch {
51427
51490
  }
51428
51491
  throw new UploadError(
@@ -51431,35 +51494,35 @@ async function writeUploadedAttachment(args) {
51431
51494
  );
51432
51495
  }
51433
51496
  const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
51434
- const hashDir = import_node_path25.default.join(attachmentsRoot, attachmentId);
51497
+ const hashDir = import_node_path26.default.join(attachmentsRoot, attachmentId);
51435
51498
  let finalFileName;
51436
51499
  let hashDirExists = false;
51437
51500
  try {
51438
- hashDirExists = import_node_fs25.default.statSync(hashDir).isDirectory();
51501
+ hashDirExists = import_node_fs26.default.statSync(hashDir).isDirectory();
51439
51502
  } catch {
51440
51503
  }
51441
51504
  if (hashDirExists) {
51442
- const existing = import_node_fs25.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51505
+ const existing = import_node_fs26.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
51443
51506
  finalFileName = existing[0] ?? args.fileName;
51444
51507
  try {
51445
- import_node_fs25.default.unlinkSync(tmpPath);
51508
+ import_node_fs26.default.unlinkSync(tmpPath);
51446
51509
  } catch {
51447
51510
  }
51448
51511
  } else {
51449
51512
  try {
51450
- import_node_fs25.default.mkdirSync(hashDir, { recursive: true });
51513
+ import_node_fs26.default.mkdirSync(hashDir, { recursive: true });
51451
51514
  finalFileName = args.fileName;
51452
- import_node_fs25.default.renameSync(tmpPath, import_node_path25.default.join(hashDir, finalFileName));
51515
+ import_node_fs26.default.renameSync(tmpPath, import_node_path26.default.join(hashDir, finalFileName));
51453
51516
  } catch (err) {
51454
51517
  try {
51455
- import_node_fs25.default.unlinkSync(tmpPath);
51518
+ import_node_fs26.default.unlinkSync(tmpPath);
51456
51519
  } catch {
51457
51520
  }
51458
51521
  throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
51459
51522
  }
51460
51523
  }
51461
- const absPath = import_node_path25.default.join(hashDir, finalFileName);
51462
- const relPath = import_node_path25.default.relative(args.sessionDir, absPath);
51524
+ const absPath = import_node_path26.default.join(hashDir, finalFileName);
51525
+ const relPath = import_node_path26.default.relative(args.sessionDir, absPath);
51463
51526
  args.groupFileStore.upsert(args.scope, args.sessionId, {
51464
51527
  relPath: absPath,
51465
51528
  // 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
@@ -51473,7 +51536,7 @@ async function writeUploadedAttachment(args) {
51473
51536
 
51474
51537
  // src/extension/import.ts
51475
51538
  var import_promises3 = __toESM(require("fs/promises"), 1);
51476
- var import_node_path26 = __toESM(require("path"), 1);
51539
+ var import_node_path27 = __toESM(require("path"), 1);
51477
51540
  var import_node_os12 = __toESM(require("os"), 1);
51478
51541
  var import_jszip = __toESM(require_lib3(), 1);
51479
51542
  init_src();
@@ -51492,7 +51555,7 @@ async function importZip(buf, root) {
51492
51555
  throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
51493
51556
  }
51494
51557
  for (const name of Object.keys(zip.files)) {
51495
- if (name.includes("..") || name.startsWith("/") || import_node_path26.default.isAbsolute(name)) {
51558
+ if (name.includes("..") || name.startsWith("/") || import_node_path27.default.isAbsolute(name)) {
51496
51559
  throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
51497
51560
  }
51498
51561
  }
@@ -51525,7 +51588,7 @@ async function importZip(buf, root) {
51525
51588
  );
51526
51589
  }
51527
51590
  }
51528
- const destDir = import_node_path26.default.join(root, manifest.id);
51591
+ const destDir = import_node_path27.default.join(root, manifest.id);
51529
51592
  let destExists = false;
51530
51593
  try {
51531
51594
  await import_promises3.default.access(destDir);
@@ -51535,15 +51598,15 @@ async function importZip(buf, root) {
51535
51598
  if (destExists) {
51536
51599
  throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
51537
51600
  }
51538
- const stage = await import_promises3.default.mkdtemp(import_node_path26.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
51601
+ const stage = await import_promises3.default.mkdtemp(import_node_path27.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
51539
51602
  try {
51540
51603
  for (const [name, entry] of Object.entries(zip.files)) {
51541
- const dest = import_node_path26.default.join(stage, name);
51604
+ const dest = import_node_path27.default.join(stage, name);
51542
51605
  if (entry.dir) {
51543
51606
  await import_promises3.default.mkdir(dest, { recursive: true });
51544
51607
  continue;
51545
51608
  }
51546
- await import_promises3.default.mkdir(import_node_path26.default.dirname(dest), { recursive: true });
51609
+ await import_promises3.default.mkdir(import_node_path27.default.dirname(dest), { recursive: true });
51547
51610
  const content = await entry.async("nodebuffer");
51548
51611
  await import_promises3.default.writeFile(dest, content);
51549
51612
  }
@@ -51574,7 +51637,7 @@ var SHARE_UI_ASSET_MIME = {
51574
51637
  ".wasm": "application/wasm"
51575
51638
  };
51576
51639
  function shareUiAssetMime(filePath) {
51577
- const ext = import_node_path27.default.extname(filePath).toLowerCase();
51640
+ const ext = import_node_path28.default.extname(filePath).toLowerCase();
51578
51641
  return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
51579
51642
  }
51580
51643
  var DISPATCH_HEARTBEAT_MS = 25e3;
@@ -51661,7 +51724,7 @@ function isValidUploadFileName(fileName) {
51661
51724
  if (fileName === "." || fileName === "..") return false;
51662
51725
  if (fileName.startsWith(".")) return false;
51663
51726
  if (fileName.includes("/") || fileName.includes("\\")) return false;
51664
- return fileName === import_node_path27.default.basename(fileName);
51727
+ return fileName === import_node_path28.default.basename(fileName);
51665
51728
  }
51666
51729
  function createHttpRouter(deps) {
51667
51730
  return async (req, res) => {
@@ -51733,7 +51796,7 @@ function createHttpRouter(deps) {
51733
51796
  }
51734
51797
  let buf;
51735
51798
  try {
51736
- buf = await import_node_fs26.default.promises.readFile(abs);
51799
+ buf = await import_node_fs27.default.promises.readFile(abs);
51737
51800
  } catch {
51738
51801
  sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
51739
51802
  return true;
@@ -51957,7 +52020,7 @@ function createHttpRouter(deps) {
51957
52020
  sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
51958
52021
  return true;
51959
52022
  }
51960
- sendHtml(res, 200, loader.renderViewerHtml(import_node_path27.default.basename(r.absPath)));
52023
+ sendHtml(res, 200, loader.renderViewerHtml(import_node_path28.default.basename(r.absPath)));
51961
52024
  return true;
51962
52025
  }
51963
52026
  const ctx = deps.authResolver.resolveFromHeader(
@@ -52078,7 +52141,7 @@ function createHttpRouter(deps) {
52078
52141
  return true;
52079
52142
  }
52080
52143
  let absPath;
52081
- if (import_node_path27.default.isAbsolute(pathParam)) {
52144
+ if (import_node_path28.default.isAbsolute(pathParam)) {
52082
52145
  absPath = pathParam;
52083
52146
  } else if (deps.sessionStore) {
52084
52147
  const file = deps.sessionStore.read(sid);
@@ -52086,7 +52149,7 @@ function createHttpRouter(deps) {
52086
52149
  sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
52087
52150
  return true;
52088
52151
  }
52089
- absPath = import_node_path27.default.join(file.cwd, pathParam);
52152
+ absPath = import_node_path28.default.join(file.cwd, pathParam);
52090
52153
  } else {
52091
52154
  sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
52092
52155
  return true;
@@ -52173,7 +52236,7 @@ function withCtx(ctx, body) {
52173
52236
  function streamFile(res, absPath, logger) {
52174
52237
  let stat;
52175
52238
  try {
52176
- stat = import_node_fs26.default.statSync(absPath);
52239
+ stat = import_node_fs27.default.statSync(absPath);
52177
52240
  } catch (err) {
52178
52241
  const code = err?.code;
52179
52242
  if (code === "ENOENT") {
@@ -52188,7 +52251,7 @@ function streamFile(res, absPath, logger) {
52188
52251
  return;
52189
52252
  }
52190
52253
  const mime = lookupMime(absPath);
52191
- const basename = import_node_path27.default.basename(absPath);
52254
+ const basename = import_node_path28.default.basename(absPath);
52192
52255
  res.writeHead(200, {
52193
52256
  "Content-Type": mime,
52194
52257
  "Content-Length": String(stat.size),
@@ -52196,7 +52259,7 @@ function streamFile(res, absPath, logger) {
52196
52259
  // 防止浏览器把任意 mime 当 html 渲染
52197
52260
  "X-Content-Type-Options": "nosniff"
52198
52261
  });
52199
- const stream = import_node_fs26.default.createReadStream(absPath);
52262
+ const stream = import_node_fs27.default.createReadStream(absPath);
52200
52263
  stream.on("error", (err) => {
52201
52264
  logger?.warn("streamFile read error", { absPath, err: err.message });
52202
52265
  res.destroy();
@@ -52205,8 +52268,8 @@ function streamFile(res, absPath, logger) {
52205
52268
  }
52206
52269
 
52207
52270
  // src/attachment/gc.ts
52208
- var import_node_fs27 = __toESM(require("fs"), 1);
52209
- var import_node_path28 = __toESM(require("path"), 1);
52271
+ var import_node_fs28 = __toESM(require("fs"), 1);
52272
+ var import_node_path29 = __toESM(require("path"), 1);
52210
52273
  var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
52211
52274
  function runAttachmentGc(args) {
52212
52275
  const now = (args.now ?? Date.now)();
@@ -52215,38 +52278,38 @@ function runAttachmentGc(args) {
52215
52278
  for (const { scope, sessionId } of args.sessionScopes) {
52216
52279
  for (const entry of args.groupFileStore.list(scope, sessionId)) {
52217
52280
  if (entry.stale) continue;
52218
- if (import_node_path28.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52281
+ if (import_node_path29.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
52219
52282
  }
52220
52283
  }
52221
52284
  for (const { scope, sessionId } of args.sessionScopes) {
52222
- const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path28.default.join(
52285
+ const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path29.default.join(
52223
52286
  args.dataDir,
52224
52287
  "sessions",
52225
52288
  ...scopeSubPath(scope).map(safeFileName),
52226
52289
  safeFileName(sessionId)
52227
52290
  );
52228
- const attRoot = import_node_path28.default.join(sessionDir, ".attachments");
52291
+ const attRoot = import_node_path29.default.join(sessionDir, ".attachments");
52229
52292
  let hashDirs;
52230
52293
  try {
52231
- hashDirs = import_node_fs27.default.readdirSync(attRoot);
52294
+ hashDirs = import_node_fs28.default.readdirSync(attRoot);
52232
52295
  } catch (err) {
52233
52296
  if (err.code === "ENOENT") continue;
52234
52297
  args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
52235
52298
  continue;
52236
52299
  }
52237
52300
  for (const hashDir of hashDirs) {
52238
- const hashDirAbs = import_node_path28.default.join(attRoot, hashDir);
52301
+ const hashDirAbs = import_node_path29.default.join(attRoot, hashDir);
52239
52302
  let files;
52240
52303
  try {
52241
- files = import_node_fs27.default.readdirSync(hashDirAbs);
52304
+ files = import_node_fs28.default.readdirSync(hashDirAbs);
52242
52305
  } catch {
52243
52306
  continue;
52244
52307
  }
52245
52308
  for (const name of files) {
52246
- const file = import_node_path28.default.join(hashDirAbs, name);
52309
+ const file = import_node_path29.default.join(hashDirAbs, name);
52247
52310
  let stat;
52248
52311
  try {
52249
- stat = import_node_fs27.default.statSync(file);
52312
+ stat = import_node_fs28.default.statSync(file);
52250
52313
  } catch {
52251
52314
  continue;
52252
52315
  }
@@ -52255,26 +52318,26 @@ function runAttachmentGc(args) {
52255
52318
  if (age < ttlMs) continue;
52256
52319
  if (liveAbs.has(file)) continue;
52257
52320
  try {
52258
- import_node_fs27.default.unlinkSync(file);
52321
+ import_node_fs28.default.unlinkSync(file);
52259
52322
  } catch (err) {
52260
52323
  args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
52261
52324
  }
52262
52325
  }
52263
52326
  try {
52264
- if (import_node_fs27.default.readdirSync(hashDirAbs).length === 0) import_node_fs27.default.rmdirSync(hashDirAbs);
52327
+ if (import_node_fs28.default.readdirSync(hashDirAbs).length === 0) import_node_fs28.default.rmdirSync(hashDirAbs);
52265
52328
  } catch {
52266
52329
  }
52267
52330
  }
52268
52331
  try {
52269
- if (import_node_fs27.default.readdirSync(attRoot).length === 0) import_node_fs27.default.rmdirSync(attRoot);
52332
+ if (import_node_fs28.default.readdirSync(attRoot).length === 0) import_node_fs28.default.rmdirSync(attRoot);
52270
52333
  } catch {
52271
52334
  }
52272
52335
  }
52273
52336
  }
52274
52337
 
52275
52338
  // src/attachment/group.ts
52276
- var import_node_fs28 = __toESM(require("fs"), 1);
52277
- var import_node_path29 = __toESM(require("path"), 1);
52339
+ var import_node_fs29 = __toESM(require("fs"), 1);
52340
+ var import_node_path30 = __toESM(require("path"), 1);
52278
52341
  var import_node_crypto9 = __toESM(require("crypto"), 1);
52279
52342
  init_protocol();
52280
52343
  var GroupFileStore = class {
@@ -52286,11 +52349,11 @@ var GroupFileStore = class {
52286
52349
  this.logger = opts.logger;
52287
52350
  }
52288
52351
  rootForScope(scope) {
52289
- return import_node_path29.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
52352
+ return import_node_path30.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
52290
52353
  }
52291
52354
  /** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
52292
52355
  filePath(scope, sessionId) {
52293
- return import_node_path29.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
52356
+ return import_node_path30.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
52294
52357
  }
52295
52358
  cacheKey(scope, sessionId) {
52296
52359
  return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
@@ -52299,7 +52362,7 @@ var GroupFileStore = class {
52299
52362
  readFile(scope, sessionId) {
52300
52363
  const file = this.filePath(scope, sessionId);
52301
52364
  try {
52302
- const raw = import_node_fs28.default.readFileSync(file, "utf8");
52365
+ const raw = import_node_fs29.default.readFileSync(file, "utf8");
52303
52366
  const parsed = JSON.parse(raw);
52304
52367
  if (!Array.isArray(parsed)) {
52305
52368
  this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
@@ -52325,10 +52388,10 @@ var GroupFileStore = class {
52325
52388
  }
52326
52389
  writeFile(scope, sessionId, entries) {
52327
52390
  const file = this.filePath(scope, sessionId);
52328
- import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
52391
+ import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(file), { recursive: true });
52329
52392
  const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
52330
- import_node_fs28.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52331
- import_node_fs28.default.renameSync(tmp, file);
52393
+ import_node_fs29.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
52394
+ import_node_fs29.default.renameSync(tmp, file);
52332
52395
  }
52333
52396
  /** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
52334
52397
  list(scope, sessionId) {
@@ -52414,10 +52477,10 @@ var GroupFileStore = class {
52414
52477
  };
52415
52478
 
52416
52479
  // src/discovery/state-file.ts
52417
- var import_node_fs29 = __toESM(require("fs"), 1);
52418
- var import_node_path30 = __toESM(require("path"), 1);
52480
+ var import_node_fs30 = __toESM(require("fs"), 1);
52481
+ var import_node_path31 = __toESM(require("path"), 1);
52419
52482
  function defaultStateFilePath(dataDir) {
52420
- return import_node_path30.default.join(dataDir, "state.json");
52483
+ return import_node_path31.default.join(dataDir, "state.json");
52421
52484
  }
52422
52485
  function isPidAlive(pid) {
52423
52486
  if (!Number.isFinite(pid) || pid <= 0) return false;
@@ -52439,7 +52502,7 @@ var StateFileManager = class {
52439
52502
  }
52440
52503
  read() {
52441
52504
  try {
52442
- const raw = import_node_fs29.default.readFileSync(this.file, "utf8");
52505
+ const raw = import_node_fs30.default.readFileSync(this.file, "utf8");
52443
52506
  const parsed = JSON.parse(raw);
52444
52507
  return parsed;
52445
52508
  } catch {
@@ -52453,20 +52516,20 @@ var StateFileManager = class {
52453
52516
  return { status: "stale", existing };
52454
52517
  }
52455
52518
  write(state) {
52456
- import_node_fs29.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
52519
+ import_node_fs30.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
52457
52520
  const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
52458
- import_node_fs29.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52459
- import_node_fs29.default.renameSync(tmp, this.file);
52521
+ import_node_fs30.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
52522
+ import_node_fs30.default.renameSync(tmp, this.file);
52460
52523
  if (process.platform !== "win32") {
52461
52524
  try {
52462
- import_node_fs29.default.chmodSync(this.file, 384);
52525
+ import_node_fs30.default.chmodSync(this.file, 384);
52463
52526
  } catch {
52464
52527
  }
52465
52528
  }
52466
52529
  }
52467
52530
  delete() {
52468
52531
  try {
52469
- import_node_fs29.default.unlinkSync(this.file);
52532
+ import_node_fs30.default.unlinkSync(this.file);
52470
52533
  } catch {
52471
52534
  }
52472
52535
  }
@@ -52481,14 +52544,14 @@ function readDaemonSourceFromEnv(env = process.env) {
52481
52544
  }
52482
52545
 
52483
52546
  // src/tunnel/tunnel-manager.ts
52484
- var import_node_fs33 = __toESM(require("fs"), 1);
52485
- var import_node_path34 = __toESM(require("path"), 1);
52547
+ var import_node_fs34 = __toESM(require("fs"), 1);
52548
+ var import_node_path35 = __toESM(require("path"), 1);
52486
52549
  var import_node_crypto10 = __toESM(require("crypto"), 1);
52487
52550
  var import_node_child_process9 = require("child_process");
52488
52551
 
52489
52552
  // src/tunnel/tunnel-store.ts
52490
- var import_node_fs30 = __toESM(require("fs"), 1);
52491
- var import_node_path31 = __toESM(require("path"), 1);
52553
+ var import_node_fs31 = __toESM(require("fs"), 1);
52554
+ var import_node_path32 = __toESM(require("path"), 1);
52492
52555
  var TunnelStore = class {
52493
52556
  constructor(filePath) {
52494
52557
  this.filePath = filePath;
@@ -52496,7 +52559,7 @@ var TunnelStore = class {
52496
52559
  filePath;
52497
52560
  async get() {
52498
52561
  try {
52499
- const raw = await import_node_fs30.default.promises.readFile(this.filePath, "utf8");
52562
+ const raw = await import_node_fs31.default.promises.readFile(this.filePath, "utf8");
52500
52563
  const obj = JSON.parse(raw);
52501
52564
  if (!isPersistedTunnel(obj)) return null;
52502
52565
  return obj;
@@ -52507,22 +52570,22 @@ var TunnelStore = class {
52507
52570
  }
52508
52571
  }
52509
52572
  async set(v2) {
52510
- const dir = import_node_path31.default.dirname(this.filePath);
52511
- await import_node_fs30.default.promises.mkdir(dir, { recursive: true });
52573
+ const dir = import_node_path32.default.dirname(this.filePath);
52574
+ await import_node_fs31.default.promises.mkdir(dir, { recursive: true });
52512
52575
  const data = JSON.stringify(v2, null, 2);
52513
52576
  const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
52514
- await import_node_fs30.default.promises.writeFile(tmp, data, { mode: 384 });
52577
+ await import_node_fs31.default.promises.writeFile(tmp, data, { mode: 384 });
52515
52578
  if (process.platform !== "win32") {
52516
52579
  try {
52517
- await import_node_fs30.default.promises.chmod(tmp, 384);
52580
+ await import_node_fs31.default.promises.chmod(tmp, 384);
52518
52581
  } catch {
52519
52582
  }
52520
52583
  }
52521
- await import_node_fs30.default.promises.rename(tmp, this.filePath);
52584
+ await import_node_fs31.default.promises.rename(tmp, this.filePath);
52522
52585
  }
52523
52586
  async clear() {
52524
52587
  try {
52525
- await import_node_fs30.default.promises.unlink(this.filePath);
52588
+ await import_node_fs31.default.promises.unlink(this.filePath);
52526
52589
  } catch (err) {
52527
52590
  const code = err?.code;
52528
52591
  if (code !== "ENOENT") throw err;
@@ -52617,9 +52680,9 @@ function escape(v2) {
52617
52680
  }
52618
52681
 
52619
52682
  // src/tunnel/frpc-binary.ts
52620
- var import_node_fs31 = __toESM(require("fs"), 1);
52683
+ var import_node_fs32 = __toESM(require("fs"), 1);
52621
52684
  var import_node_os13 = __toESM(require("os"), 1);
52622
- var import_node_path32 = __toESM(require("path"), 1);
52685
+ var import_node_path33 = __toESM(require("path"), 1);
52623
52686
  var import_node_child_process7 = require("child_process");
52624
52687
  var import_node_stream3 = require("stream");
52625
52688
  var import_promises4 = require("stream/promises");
@@ -52651,20 +52714,20 @@ function frpcDownloadUrl(version2, p2) {
52651
52714
  }
52652
52715
  async function ensureFrpcBinary(opts) {
52653
52716
  if (opts.override) {
52654
- if (!import_node_fs31.default.existsSync(opts.override)) {
52717
+ if (!import_node_fs32.default.existsSync(opts.override)) {
52655
52718
  throw new Error(`frpc binary not found at override path: ${opts.override}`);
52656
52719
  }
52657
52720
  return opts.override;
52658
52721
  }
52659
52722
  const version2 = opts.version ?? FRPC_VERSION;
52660
52723
  const platform = opts.platform ?? detectPlatform();
52661
- const binDir = import_node_path32.default.join(opts.dataDir, "bin");
52662
- import_node_fs31.default.mkdirSync(binDir, { recursive: true });
52724
+ const binDir = import_node_path33.default.join(opts.dataDir, "bin");
52725
+ import_node_fs32.default.mkdirSync(binDir, { recursive: true });
52663
52726
  cleanupStaleArtifacts(binDir);
52664
- const stableBin = import_node_path32.default.join(binDir, "frpc");
52665
- if (import_node_fs31.default.existsSync(stableBin)) return stableBin;
52727
+ const stableBin = import_node_path33.default.join(binDir, "frpc");
52728
+ if (import_node_fs32.default.existsSync(stableBin)) return stableBin;
52666
52729
  const partialBin = `${stableBin}.partial`;
52667
- const tarballPath = import_node_path32.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52730
+ const tarballPath = import_node_path33.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
52668
52731
  try {
52669
52732
  const url = frpcDownloadUrl(version2, platform);
52670
52733
  await downloadToFile(url, tarballPath, opts.fetchImpl);
@@ -52673,8 +52736,8 @@ async function ensureFrpcBinary(opts) {
52673
52736
  } else {
52674
52737
  await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
52675
52738
  }
52676
- import_node_fs31.default.chmodSync(partialBin, 493);
52677
- import_node_fs31.default.renameSync(partialBin, stableBin);
52739
+ import_node_fs32.default.chmodSync(partialBin, 493);
52740
+ import_node_fs32.default.renameSync(partialBin, stableBin);
52678
52741
  } finally {
52679
52742
  safeUnlink(tarballPath);
52680
52743
  safeUnlink(partialBin);
@@ -52684,15 +52747,15 @@ async function ensureFrpcBinary(opts) {
52684
52747
  function cleanupStaleArtifacts(binDir) {
52685
52748
  let entries;
52686
52749
  try {
52687
- entries = import_node_fs31.default.readdirSync(binDir);
52750
+ entries = import_node_fs32.default.readdirSync(binDir);
52688
52751
  } catch {
52689
52752
  return;
52690
52753
  }
52691
52754
  for (const name of entries) {
52692
52755
  if (name.endsWith(".partial") || name.startsWith("extract-")) {
52693
- const full = import_node_path32.default.join(binDir, name);
52756
+ const full = import_node_path33.default.join(binDir, name);
52694
52757
  try {
52695
- import_node_fs31.default.rmSync(full, { recursive: true, force: true });
52758
+ import_node_fs32.default.rmSync(full, { recursive: true, force: true });
52696
52759
  } catch {
52697
52760
  }
52698
52761
  }
@@ -52700,7 +52763,7 @@ function cleanupStaleArtifacts(binDir) {
52700
52763
  }
52701
52764
  function safeUnlink(p2) {
52702
52765
  try {
52703
- import_node_fs31.default.unlinkSync(p2);
52766
+ import_node_fs32.default.unlinkSync(p2);
52704
52767
  } catch {
52705
52768
  }
52706
52769
  }
@@ -52711,13 +52774,13 @@ async function downloadToFile(url, dest, fetchImpl) {
52711
52774
  if (!res.ok || !res.body) {
52712
52775
  throw new Error(`download failed: ${res.status} ${res.statusText}`);
52713
52776
  }
52714
- const out = import_node_fs31.default.createWriteStream(dest);
52777
+ const out = import_node_fs32.default.createWriteStream(dest);
52715
52778
  const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
52716
52779
  await (0, import_promises4.pipeline)(nodeStream, out);
52717
52780
  }
52718
52781
  async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
52719
- const work = import_node_path32.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52720
- import_node_fs31.default.mkdirSync(work, { recursive: true });
52782
+ const work = import_node_path33.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
52783
+ import_node_fs32.default.mkdirSync(work, { recursive: true });
52721
52784
  try {
52722
52785
  await new Promise((resolve6, reject) => {
52723
52786
  const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
@@ -52725,32 +52788,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
52725
52788
  proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
52726
52789
  });
52727
52790
  const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
52728
- const src = import_node_path32.default.join(work, dirName, "frpc");
52729
- if (!import_node_fs31.default.existsSync(src)) {
52791
+ const src = import_node_path33.default.join(work, dirName, "frpc");
52792
+ if (!import_node_fs32.default.existsSync(src)) {
52730
52793
  throw new Error(`frpc not found inside tarball at ${src}`);
52731
52794
  }
52732
- import_node_fs31.default.copyFileSync(src, destBin);
52795
+ import_node_fs32.default.copyFileSync(src, destBin);
52733
52796
  } finally {
52734
- import_node_fs31.default.rmSync(work, { recursive: true, force: true });
52797
+ import_node_fs32.default.rmSync(work, { recursive: true, force: true });
52735
52798
  }
52736
52799
  }
52737
52800
 
52738
52801
  // src/tunnel/frpc-process.ts
52739
- var import_node_fs32 = __toESM(require("fs"), 1);
52740
- var import_node_path33 = __toESM(require("path"), 1);
52802
+ var import_node_fs33 = __toESM(require("fs"), 1);
52803
+ var import_node_path34 = __toESM(require("path"), 1);
52741
52804
  var import_node_child_process8 = require("child_process");
52742
52805
  function frpcPidFilePath(dataDir) {
52743
- return import_node_path33.default.join(dataDir, "frpc.pid");
52806
+ return import_node_path34.default.join(dataDir, "frpc.pid");
52744
52807
  }
52745
52808
  function writeFrpcPid(dataDir, pid) {
52746
52809
  try {
52747
- import_node_fs32.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
52810
+ import_node_fs33.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
52748
52811
  } catch {
52749
52812
  }
52750
52813
  }
52751
52814
  function clearFrpcPid(dataDir) {
52752
52815
  try {
52753
- import_node_fs32.default.unlinkSync(frpcPidFilePath(dataDir));
52816
+ import_node_fs33.default.unlinkSync(frpcPidFilePath(dataDir));
52754
52817
  } catch {
52755
52818
  }
52756
52819
  }
@@ -52766,7 +52829,7 @@ function defaultIsPidAlive(pid) {
52766
52829
  }
52767
52830
  function defaultReadPidFile(file) {
52768
52831
  try {
52769
- return import_node_fs32.default.readFileSync(file, "utf8");
52832
+ return import_node_fs33.default.readFileSync(file, "utf8");
52770
52833
  } catch {
52771
52834
  return null;
52772
52835
  }
@@ -52782,7 +52845,7 @@ function defaultSleep(ms) {
52782
52845
  }
52783
52846
  async function killStaleFrpc(deps) {
52784
52847
  const pidFile = frpcPidFilePath(deps.dataDir);
52785
- const tomlPath = import_node_path33.default.join(deps.dataDir, "frpc.toml");
52848
+ const tomlPath = import_node_path34.default.join(deps.dataDir, "frpc.toml");
52786
52849
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
52787
52850
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
52788
52851
  const killPid = deps.killPidImpl ?? defaultKillPid;
@@ -52806,7 +52869,7 @@ async function killStaleFrpc(deps) {
52806
52869
  }
52807
52870
  if (victims.size === 0) {
52808
52871
  try {
52809
- import_node_fs32.default.unlinkSync(pidFile);
52872
+ import_node_fs33.default.unlinkSync(pidFile);
52810
52873
  } catch {
52811
52874
  }
52812
52875
  return;
@@ -52817,7 +52880,7 @@ async function killStaleFrpc(deps) {
52817
52880
  }
52818
52881
  await sleep2(deps.reapWaitMs ?? 300);
52819
52882
  try {
52820
- import_node_fs32.default.unlinkSync(pidFile);
52883
+ import_node_fs33.default.unlinkSync(pidFile);
52821
52884
  } catch {
52822
52885
  }
52823
52886
  }
@@ -52854,7 +52917,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
52854
52917
  var TunnelManager = class {
52855
52918
  constructor(deps) {
52856
52919
  this.deps = deps;
52857
- this.store = deps.store ?? new TunnelStore(import_node_path34.default.join(deps.dataDir, "tunnel.json"));
52920
+ this.store = deps.store ?? new TunnelStore(import_node_path35.default.join(deps.dataDir, "tunnel.json"));
52858
52921
  this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
52859
52922
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
52860
52923
  }
@@ -52981,7 +53044,7 @@ var TunnelManager = class {
52981
53044
  dataDir: this.deps.dataDir,
52982
53045
  override: this.deps.frpcBinaryOverride ?? void 0
52983
53046
  });
52984
- const tomlPath = import_node_path34.default.join(this.deps.dataDir, "frpc.toml");
53047
+ const tomlPath = import_node_path35.default.join(this.deps.dataDir, "frpc.toml");
52985
53048
  const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
52986
53049
  const toml = buildFrpcToml({
52987
53050
  serverAddr: t.frpsHost,
@@ -52992,12 +53055,12 @@ var TunnelManager = class {
52992
53055
  localPort,
52993
53056
  logLevel: "info"
52994
53057
  });
52995
- await import_node_fs33.default.promises.writeFile(tomlPath, toml, { mode: 384 });
53058
+ await import_node_fs34.default.promises.writeFile(tomlPath, toml, { mode: 384 });
52996
53059
  const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
52997
53060
  stdio: ["ignore", "pipe", "pipe"]
52998
53061
  });
52999
- const logFilePath = import_node_path34.default.join(this.deps.dataDir, "frpc.log");
53000
- const logStream = import_node_fs33.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53062
+ const logFilePath = import_node_path35.default.join(this.deps.dataDir, "frpc.log");
53063
+ const logStream = import_node_fs34.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
53001
53064
  logStream.on("error", () => {
53002
53065
  });
53003
53066
  const tee = (chunk) => {
@@ -53079,8 +53142,8 @@ async function waitForFrpcReady(proc, timeoutMs) {
53079
53142
  }
53080
53143
 
53081
53144
  // src/sshd/sshd-manager.ts
53082
- var import_node_fs37 = __toESM(require("fs"), 1);
53083
- var import_node_path38 = __toESM(require("path"), 1);
53145
+ var import_node_fs38 = __toESM(require("fs"), 1);
53146
+ var import_node_path39 = __toESM(require("path"), 1);
53084
53147
  var import_node_child_process11 = require("child_process");
53085
53148
 
53086
53149
  // src/sshd/sshd-config.ts
@@ -53105,23 +53168,23 @@ function buildSshdConfig(input) {
53105
53168
  }
53106
53169
 
53107
53170
  // src/sshd/sshd-process.ts
53108
- var import_node_fs34 = __toESM(require("fs"), 1);
53109
- var import_node_path35 = __toESM(require("path"), 1);
53171
+ var import_node_fs35 = __toESM(require("fs"), 1);
53172
+ var import_node_path36 = __toESM(require("path"), 1);
53110
53173
  var import_node_child_process10 = require("child_process");
53111
53174
  function sshdPidFilePath(dataDir) {
53112
- return import_node_path35.default.join(dataDir, "sshd", "sshd.pid");
53175
+ return import_node_path36.default.join(dataDir, "sshd", "sshd.pid");
53113
53176
  }
53114
53177
  function writeSshdPid(dataDir, pid) {
53115
53178
  try {
53116
53179
  const p2 = sshdPidFilePath(dataDir);
53117
- import_node_fs34.default.mkdirSync(import_node_path35.default.dirname(p2), { recursive: true, mode: 448 });
53118
- import_node_fs34.default.writeFileSync(p2, String(pid), { mode: 384 });
53180
+ import_node_fs35.default.mkdirSync(import_node_path36.default.dirname(p2), { recursive: true, mode: 448 });
53181
+ import_node_fs35.default.writeFileSync(p2, String(pid), { mode: 384 });
53119
53182
  } catch {
53120
53183
  }
53121
53184
  }
53122
53185
  function clearSshdPid(dataDir) {
53123
53186
  try {
53124
- import_node_fs34.default.unlinkSync(sshdPidFilePath(dataDir));
53187
+ import_node_fs35.default.unlinkSync(sshdPidFilePath(dataDir));
53125
53188
  } catch {
53126
53189
  }
53127
53190
  }
@@ -53137,7 +53200,7 @@ function defaultIsPidAlive2(pid) {
53137
53200
  }
53138
53201
  function defaultReadPidFile2(file) {
53139
53202
  try {
53140
- return import_node_fs34.default.readFileSync(file, "utf8");
53203
+ return import_node_fs35.default.readFileSync(file, "utf8");
53141
53204
  } catch {
53142
53205
  return null;
53143
53206
  }
@@ -53153,7 +53216,7 @@ function defaultSleep2(ms) {
53153
53216
  }
53154
53217
  async function killStaleSshd(deps) {
53155
53218
  const pidFile = sshdPidFilePath(deps.dataDir);
53156
- const configPath = import_node_path35.default.join(deps.dataDir, "sshd", "sshd_config");
53219
+ const configPath = import_node_path36.default.join(deps.dataDir, "sshd", "sshd_config");
53157
53220
  const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile2;
53158
53221
  const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive2;
53159
53222
  const killPid = deps.killPidImpl ?? defaultKillPid2;
@@ -53177,7 +53240,7 @@ async function killStaleSshd(deps) {
53177
53240
  }
53178
53241
  if (victims.size === 0) {
53179
53242
  try {
53180
- import_node_fs34.default.unlinkSync(pidFile);
53243
+ import_node_fs35.default.unlinkSync(pidFile);
53181
53244
  } catch {
53182
53245
  }
53183
53246
  return;
@@ -53188,7 +53251,7 @@ async function killStaleSshd(deps) {
53188
53251
  }
53189
53252
  await sleep2(deps.reapWaitMs ?? 300);
53190
53253
  try {
53191
- import_node_fs34.default.unlinkSync(pidFile);
53254
+ import_node_fs35.default.unlinkSync(pidFile);
53192
53255
  } catch {
53193
53256
  }
53194
53257
  }
@@ -53221,8 +53284,8 @@ async function defaultScanSshdPidsByCmdline(configPath, logger) {
53221
53284
  }
53222
53285
 
53223
53286
  // src/sshd/jail-script.ts
53224
- var import_node_fs35 = __toESM(require("fs"), 1);
53225
- var import_node_path36 = __toESM(require("path"), 1);
53287
+ var import_node_fs36 = __toESM(require("fs"), 1);
53288
+ var import_node_path37 = __toESM(require("path"), 1);
53226
53289
  var CLAWD_SSH_JAIL_SCRIPT = String.raw`#!/usr/bin/env bash
53227
53290
  # clawd-ssh-jail — SSH reverse access sandbox wrapper (managed by clawd; do not edit)
53228
53291
  #
@@ -53356,16 +53419,16 @@ case "$(uname -s)" in
53356
53419
  esac
53357
53420
  `;
53358
53421
  function ensureJailScript(dataDir) {
53359
- const binDir = import_node_path36.default.join(dataDir, "bin");
53360
- import_node_fs35.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53361
- const target = import_node_path36.default.join(binDir, "clawd-ssh-jail");
53362
- import_node_fs35.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53422
+ const binDir = import_node_path37.default.join(dataDir, "bin");
53423
+ import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53424
+ const target = import_node_path37.default.join(binDir, "clawd-ssh-jail");
53425
+ import_node_fs36.default.writeFileSync(target, CLAWD_SSH_JAIL_SCRIPT, { mode: 493 });
53363
53426
  return target;
53364
53427
  }
53365
53428
 
53366
53429
  // src/sshd/clawd-shim.ts
53367
- var import_node_fs36 = __toESM(require("fs"), 1);
53368
- var import_node_path37 = __toESM(require("path"), 1);
53430
+ var import_node_fs37 = __toESM(require("fs"), 1);
53431
+ var import_node_path38 = __toESM(require("path"), 1);
53369
53432
  function shellQuote(s) {
53370
53433
  return `'${s.replace(/'/g, "'\\''")}'`;
53371
53434
  }
@@ -53380,10 +53443,10 @@ exec ${shellQuote(execPath)} ${shellQuote(cliPath)} "$@"
53380
53443
  `;
53381
53444
  }
53382
53445
  function ensureClawdShim(dataDir, execPath, cliPath) {
53383
- const binDir = import_node_path37.default.join(dataDir, "bin");
53384
- import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53385
- const target = import_node_path37.default.join(binDir, "clawd");
53386
- import_node_fs36.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53446
+ const binDir = import_node_path38.default.join(dataDir, "bin");
53447
+ import_node_fs37.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53448
+ const target = import_node_path38.default.join(binDir, "clawd");
53449
+ import_node_fs37.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53387
53450
  return target;
53388
53451
  }
53389
53452
 
@@ -53391,7 +53454,7 @@ function ensureClawdShim(dataDir, execPath, cliPath) {
53391
53454
  var SshdManager = class {
53392
53455
  constructor(deps) {
53393
53456
  this.deps = deps;
53394
- this.sshdDir = import_node_path38.default.join(deps.dataDir, "sshd");
53457
+ this.sshdDir = import_node_path39.default.join(deps.dataDir, "sshd");
53395
53458
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
53396
53459
  }
53397
53460
  deps;
@@ -53410,32 +53473,32 @@ var SshdManager = class {
53410
53473
  ownPid: process.pid,
53411
53474
  logger
53412
53475
  });
53413
- import_node_fs37.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53414
- import_node_fs37.default.mkdirSync(import_node_path38.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53476
+ import_node_fs38.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53477
+ import_node_fs38.default.mkdirSync(import_node_path39.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53415
53478
  ensureJailScript(this.deps.dataDir);
53416
53479
  ensureClawdShim(this.deps.dataDir, process.execPath, process.argv[1] ?? "");
53417
- const hostKeyPath = import_node_path38.default.join(this.sshdDir, "host_key");
53418
- if (!import_node_fs37.default.existsSync(hostKeyPath)) {
53480
+ const hostKeyPath = import_node_path39.default.join(this.sshdDir, "host_key");
53481
+ if (!import_node_fs38.default.existsSync(hostKeyPath)) {
53419
53482
  await this.generateHostKey(hostKeyPath);
53420
53483
  }
53421
- const akFile = import_node_path38.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53422
- if (!import_node_fs37.default.existsSync(akFile)) {
53423
- import_node_fs37.default.writeFileSync(akFile, "", { mode: 384 });
53484
+ const akFile = import_node_path39.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53485
+ if (!import_node_fs38.default.existsSync(akFile)) {
53486
+ import_node_fs38.default.writeFileSync(akFile, "", { mode: 384 });
53424
53487
  }
53425
- const configPath = import_node_path38.default.join(this.sshdDir, "sshd_config");
53488
+ const configPath = import_node_path39.default.join(this.sshdDir, "sshd_config");
53426
53489
  const config = buildSshdConfig({
53427
53490
  listenAddress: "127.0.0.1",
53428
53491
  port: this.deps.port,
53429
53492
  hostKeyPath,
53430
53493
  authorizedKeysFile: akFile,
53431
- pidFilePath: import_node_path38.default.join(this.sshdDir, "sshd.pid")
53494
+ pidFilePath: import_node_path39.default.join(this.sshdDir, "sshd.pid")
53432
53495
  });
53433
- import_node_fs37.default.writeFileSync(configPath, config, { mode: 384 });
53496
+ import_node_fs38.default.writeFileSync(configPath, config, { mode: 384 });
53434
53497
  const sshdBin = this.deps.sshdBin ?? "/usr/sbin/sshd";
53435
53498
  const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
53436
53499
  stdio: ["ignore", "pipe", "pipe"]
53437
53500
  });
53438
- const logStream = import_node_fs37.default.createWriteStream(import_node_path38.default.join(this.sshdDir, "sshd.log"), {
53501
+ const logStream = import_node_fs38.default.createWriteStream(import_node_path39.default.join(this.sshdDir, "sshd.log"), {
53439
53502
  flags: "a",
53440
53503
  mode: 384
53441
53504
  });
@@ -53528,7 +53591,7 @@ ${tail}` : ready.error;
53528
53591
  p2.on("error", reject);
53529
53592
  });
53530
53593
  try {
53531
- import_node_fs37.default.chmodSync(hostKeyPath, 384);
53594
+ import_node_fs38.default.chmodSync(hostKeyPath, 384);
53532
53595
  } catch {
53533
53596
  }
53534
53597
  }
@@ -53571,17 +53634,17 @@ async function waitForSshdReady(proc, timeoutMs) {
53571
53634
  }
53572
53635
 
53573
53636
  // src/sshd/authorized-keys.ts
53574
- var import_node_fs38 = __toESM(require("fs"), 1);
53575
- var import_node_path39 = __toESM(require("path"), 1);
53637
+ var import_node_fs39 = __toESM(require("fs"), 1);
53638
+ var import_node_path40 = __toESM(require("path"), 1);
53576
53639
  var JAIL_BIN_PATH_ENV = "CLAWD_JAIL_BIN_PATH";
53577
53640
  var AUTHORIZED_KEYS_FILE = "clawd-contacts";
53578
53641
  function jailBinPath() {
53579
- return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path39.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53642
+ return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path40.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53580
53643
  }
53581
53644
  function rebuildAuthorizedKeys(store, sshdDir) {
53582
- const akDir = import_node_path39.default.join(sshdDir, "authorized_keys.d");
53583
- const target = import_node_path39.default.join(akDir, AUTHORIZED_KEYS_FILE);
53584
- import_node_fs38.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53645
+ const akDir = import_node_path40.default.join(sshdDir, "authorized_keys.d");
53646
+ const target = import_node_path40.default.join(akDir, AUTHORIZED_KEYS_FILE);
53647
+ import_node_fs39.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53585
53648
  const lines = ["# managed by clawd; do not edit", ""];
53586
53649
  for (const c of store.list()) {
53587
53650
  if (!c.sshAllowed) continue;
@@ -53595,28 +53658,28 @@ function rebuildAuthorizedKeys(store, sshdDir) {
53595
53658
  }
53596
53659
  const body = lines.join("\n") + "\n";
53597
53660
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
53598
- import_node_fs38.default.writeFileSync(tmp, body, { mode: 384 });
53599
- import_node_fs38.default.renameSync(tmp, target);
53661
+ import_node_fs39.default.writeFileSync(tmp, body, { mode: 384 });
53662
+ import_node_fs39.default.renameSync(tmp, target);
53600
53663
  }
53601
53664
  function readIssuedPubkey(sshdDir, deviceId) {
53602
53665
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53603
- const p2 = import_node_path39.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53666
+ const p2 = import_node_path40.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53604
53667
  try {
53605
- return import_node_fs38.default.readFileSync(p2, "utf8");
53668
+ return import_node_fs39.default.readFileSync(p2, "utf8");
53606
53669
  } catch {
53607
53670
  return null;
53608
53671
  }
53609
53672
  }
53610
53673
 
53611
53674
  // src/sshd/contact-key-puller.ts
53612
- var import_node_fs40 = __toESM(require("fs"), 1);
53613
- var import_node_path41 = __toESM(require("path"), 1);
53675
+ var import_node_fs41 = __toESM(require("fs"), 1);
53676
+ var import_node_path42 = __toESM(require("path"), 1);
53614
53677
  init_peer_forward();
53615
53678
  init_contact_ssh_log();
53616
53679
  var CONTACT_KEYS_DIR = "contact-ssh-keys";
53617
53680
  function safeContactKeyPath(dataDir, deviceId) {
53618
53681
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53619
- return import_node_path41.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53682
+ return import_node_path42.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53620
53683
  }
53621
53684
  async function pullContactSshKeyOnce(deps) {
53622
53685
  const forward = deps.forwardImpl ?? ((c) => forwardContactSshKeyIssueToPeer({
@@ -53682,12 +53745,12 @@ async function pullContactSshKeyOnce(deps) {
53682
53745
  }
53683
53746
  function writeKeyFile(dataDir, deviceId, pem) {
53684
53747
  const p2 = safeContactKeyPath(dataDir, deviceId);
53685
- import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(p2), { recursive: true, mode: 448 });
53686
- import_node_fs40.default.writeFileSync(p2, pem, { mode: 384 });
53748
+ import_node_fs41.default.mkdirSync(import_node_path42.default.dirname(p2), { recursive: true, mode: 448 });
53749
+ import_node_fs41.default.writeFileSync(p2, pem, { mode: 384 });
53687
53750
  }
53688
53751
  function removeKeyFile(dataDir, deviceId) {
53689
53752
  try {
53690
- import_node_fs40.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53753
+ import_node_fs41.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53691
53754
  return true;
53692
53755
  } catch {
53693
53756
  return false;
@@ -53837,27 +53900,27 @@ init_contact_ssh_log();
53837
53900
 
53838
53901
  // src/tunnel/device-key.ts
53839
53902
  var import_node_os14 = __toESM(require("os"), 1);
53840
- var import_node_path42 = __toESM(require("path"), 1);
53903
+ var import_node_path43 = __toESM(require("path"), 1);
53841
53904
  var import_node_crypto11 = __toESM(require("crypto"), 1);
53842
53905
  var DERIVE_SALT = "clawd-tunnel-device-v1";
53843
53906
  function deriveStableDeviceKey(opts = {}) {
53844
53907
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
53845
53908
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
53846
53909
  const home = opts.home ?? import_node_os14.default.homedir();
53847
- const defaultDataDir = import_node_path42.default.resolve(import_node_path42.default.join(home, ".clawd"));
53848
- const normalizedDataDir = opts.dataDir ? import_node_path42.default.resolve(opts.dataDir) : null;
53910
+ const defaultDataDir = import_node_path43.default.resolve(import_node_path43.default.join(home, ".clawd"));
53911
+ const normalizedDataDir = opts.dataDir ? import_node_path43.default.resolve(opts.dataDir) : null;
53849
53912
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
53850
53913
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
53851
53914
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
53852
53915
  }
53853
53916
 
53854
53917
  // src/auth-store.ts
53855
- var import_node_fs41 = __toESM(require("fs"), 1);
53856
- var import_node_path43 = __toESM(require("path"), 1);
53918
+ var import_node_fs42 = __toESM(require("fs"), 1);
53919
+ var import_node_path44 = __toESM(require("path"), 1);
53857
53920
  var import_node_crypto12 = __toESM(require("crypto"), 1);
53858
53921
  var AUTH_FILE_NAME = "auth.json";
53859
53922
  function authFilePath(dataDir) {
53860
- return import_node_path43.default.join(dataDir, AUTH_FILE_NAME);
53923
+ return import_node_path44.default.join(dataDir, AUTH_FILE_NAME);
53861
53924
  }
53862
53925
  function loadOrCreateAuthFile(opts) {
53863
53926
  const file = authFilePath(opts.dataDir);
@@ -53893,7 +53956,7 @@ function defaultGenerateOwnerPrincipalId() {
53893
53956
  }
53894
53957
  function readAuthFile(file) {
53895
53958
  try {
53896
- const raw = import_node_fs41.default.readFileSync(file, "utf8");
53959
+ const raw = import_node_fs42.default.readFileSync(file, "utf8");
53897
53960
  const parsed = JSON.parse(raw);
53898
53961
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
53899
53962
  return null;
@@ -53913,25 +53976,25 @@ function readAuthFile(file) {
53913
53976
  }
53914
53977
  }
53915
53978
  function writeAuthFile(file, content) {
53916
- import_node_fs41.default.mkdirSync(import_node_path43.default.dirname(file), { recursive: true });
53917
- import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53979
+ import_node_fs42.default.mkdirSync(import_node_path44.default.dirname(file), { recursive: true });
53980
+ import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53918
53981
  try {
53919
- import_node_fs41.default.chmodSync(file, 384);
53982
+ import_node_fs42.default.chmodSync(file, 384);
53920
53983
  } catch {
53921
53984
  }
53922
53985
  }
53923
53986
 
53924
53987
  // src/owner-profile.ts
53925
- var import_node_fs42 = __toESM(require("fs"), 1);
53988
+ var import_node_fs43 = __toESM(require("fs"), 1);
53926
53989
  var import_node_os15 = __toESM(require("os"), 1);
53927
- var import_node_path44 = __toESM(require("path"), 1);
53990
+ var import_node_path45 = __toESM(require("path"), 1);
53928
53991
  var PROFILE_FILENAME = "profile.json";
53929
53992
  function loadOwnerDisplayName(dataDir) {
53930
53993
  const fallback = import_node_os15.default.userInfo().username;
53931
- const profilePath = import_node_path44.default.join(dataDir, PROFILE_FILENAME);
53994
+ const profilePath = import_node_path45.default.join(dataDir, PROFILE_FILENAME);
53932
53995
  let raw;
53933
53996
  try {
53934
- raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
53997
+ raw = import_node_fs43.default.readFileSync(profilePath, "utf8");
53935
53998
  } catch {
53936
53999
  return fallback;
53937
54000
  }
@@ -53954,18 +54017,18 @@ function loadOwnerDisplayName(dataDir) {
53954
54017
  }
53955
54018
 
53956
54019
  // src/feishu-auth/owner-identity-store.ts
53957
- var import_node_fs43 = __toESM(require("fs"), 1);
53958
- var import_node_path45 = __toESM(require("path"), 1);
54020
+ var import_node_fs44 = __toESM(require("fs"), 1);
54021
+ var import_node_path46 = __toESM(require("path"), 1);
53959
54022
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
53960
54023
  var OwnerIdentityStore = class {
53961
54024
  file;
53962
54025
  constructor(dataDir) {
53963
- this.file = import_node_path45.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
54026
+ this.file = import_node_path46.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53964
54027
  }
53965
54028
  read() {
53966
54029
  let raw;
53967
54030
  try {
53968
- raw = import_node_fs43.default.readFileSync(this.file, "utf8");
54031
+ raw = import_node_fs44.default.readFileSync(this.file, "utf8");
53969
54032
  } catch {
53970
54033
  return null;
53971
54034
  }
@@ -53993,16 +54056,16 @@ var OwnerIdentityStore = class {
53993
54056
  };
53994
54057
  }
53995
54058
  write(record) {
53996
- import_node_fs43.default.mkdirSync(import_node_path45.default.dirname(this.file), { recursive: true });
53997
- import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
54059
+ import_node_fs44.default.mkdirSync(import_node_path46.default.dirname(this.file), { recursive: true });
54060
+ import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
53998
54061
  try {
53999
- import_node_fs43.default.chmodSync(this.file, 384);
54062
+ import_node_fs44.default.chmodSync(this.file, 384);
54000
54063
  } catch {
54001
54064
  }
54002
54065
  }
54003
54066
  clear() {
54004
54067
  try {
54005
- import_node_fs43.default.unlinkSync(this.file);
54068
+ import_node_fs44.default.unlinkSync(this.file);
54006
54069
  } catch (err) {
54007
54070
  const code = err?.code;
54008
54071
  if (code !== "ENOENT") throw err;
@@ -54123,9 +54186,9 @@ var CentralClientError = class extends Error {
54123
54186
  code;
54124
54187
  cause;
54125
54188
  };
54126
- async function centralRequest(opts, path77, init) {
54189
+ async function centralRequest(opts, path78, init) {
54127
54190
  const f = opts.fetchImpl ?? globalThis.fetch;
54128
- const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
54191
+ const url = `${opts.api.replace(/\/+$/, "")}${path78}`;
54129
54192
  const ctrl = new AbortController();
54130
54193
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54131
54194
  let res;
@@ -54267,8 +54330,8 @@ function verifyConnectToken(args) {
54267
54330
  }
54268
54331
 
54269
54332
  // src/feishu-auth/server-key.ts
54270
- var fs53 = __toESM(require("fs"), 1);
54271
- var path54 = __toESM(require("path"), 1);
54333
+ var fs54 = __toESM(require("fs"), 1);
54334
+ var path55 = __toESM(require("path"), 1);
54272
54335
  var FILE_NAME2 = "server-signing-key.json";
54273
54336
  var ServerKeyStore = class {
54274
54337
  constructor(dataDir) {
@@ -54276,12 +54339,12 @@ var ServerKeyStore = class {
54276
54339
  }
54277
54340
  dataDir;
54278
54341
  filePath() {
54279
- return path54.join(this.dataDir, FILE_NAME2);
54342
+ return path55.join(this.dataDir, FILE_NAME2);
54280
54343
  }
54281
54344
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54282
54345
  read() {
54283
54346
  try {
54284
- const raw = fs53.readFileSync(this.filePath(), "utf8");
54347
+ const raw = fs54.readFileSync(this.filePath(), "utf8");
54285
54348
  const parsed = JSON.parse(raw);
54286
54349
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54287
54350
  return parsed.publicKeyPem;
@@ -54296,12 +54359,12 @@ var ServerKeyStore = class {
54296
54359
  publicKeyPem,
54297
54360
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54298
54361
  };
54299
- fs53.mkdirSync(this.dataDir, { recursive: true });
54300
- fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54362
+ fs54.mkdirSync(this.dataDir, { recursive: true });
54363
+ fs54.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54301
54364
  }
54302
54365
  clear() {
54303
54366
  try {
54304
- fs53.unlinkSync(this.filePath());
54367
+ fs54.unlinkSync(this.filePath());
54305
54368
  } catch {
54306
54369
  }
54307
54370
  }
@@ -54314,12 +54377,12 @@ init_protocol();
54314
54377
  init_protocol();
54315
54378
 
54316
54379
  // src/session/fork.ts
54317
- var import_node_fs44 = __toESM(require("fs"), 1);
54380
+ var import_node_fs45 = __toESM(require("fs"), 1);
54318
54381
  var import_node_os16 = __toESM(require("os"), 1);
54319
- var import_node_path46 = __toESM(require("path"), 1);
54382
+ var import_node_path47 = __toESM(require("path"), 1);
54320
54383
  init_claude_history();
54321
54384
  function readJsonlEntries(file) {
54322
- const raw = import_node_fs44.default.readFileSync(file, "utf8");
54385
+ const raw = import_node_fs45.default.readFileSync(file, "utf8");
54323
54386
  const out = [];
54324
54387
  for (const line of raw.split("\n")) {
54325
54388
  const t = line.trim();
@@ -54332,10 +54395,10 @@ function readJsonlEntries(file) {
54332
54395
  return out;
54333
54396
  }
54334
54397
  function forkSession(input) {
54335
- const baseDir = input.baseDir ?? import_node_path46.default.join(import_node_os16.default.homedir(), ".claude");
54336
- const projectDir = import_node_path46.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54337
- const sourceFile = import_node_path46.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54338
- if (!import_node_fs44.default.existsSync(sourceFile)) {
54398
+ const baseDir = input.baseDir ?? import_node_path47.default.join(import_node_os16.default.homedir(), ".claude");
54399
+ const projectDir = import_node_path47.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54400
+ const sourceFile = import_node_path47.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54401
+ if (!import_node_fs45.default.existsSync(sourceFile)) {
54339
54402
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
54340
54403
  }
54341
54404
  const entries = readJsonlEntries(sourceFile);
@@ -54365,9 +54428,9 @@ function forkSession(input) {
54365
54428
  }
54366
54429
  forkedLines.push(JSON.stringify(forked));
54367
54430
  }
54368
- const forkedFilePath = import_node_path46.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54369
- import_node_fs44.default.mkdirSync(projectDir, { recursive: true });
54370
- import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54431
+ const forkedFilePath = import_node_path47.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54432
+ import_node_fs45.default.mkdirSync(projectDir, { recursive: true });
54433
+ import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54371
54434
  return { forkedToolSessionId, forkedFilePath };
54372
54435
  }
54373
54436
 
@@ -54719,7 +54782,7 @@ function buildPermissionHandlers(deps) {
54719
54782
  }
54720
54783
 
54721
54784
  // src/handlers/history.ts
54722
- var path57 = __toESM(require("path"), 1);
54785
+ var path58 = __toESM(require("path"), 1);
54723
54786
  init_protocol();
54724
54787
 
54725
54788
  // src/session/recent-dirs.ts
@@ -54737,7 +54800,7 @@ function listRecentDirs(store, limit = 50) {
54737
54800
  }
54738
54801
 
54739
54802
  // src/permission/persona-paths.ts
54740
- var path56 = __toESM(require("path"), 1);
54803
+ var path57 = __toESM(require("path"), 1);
54741
54804
  function getAllowedPersonaIds(grants, action) {
54742
54805
  const ids = /* @__PURE__ */ new Set();
54743
54806
  for (const g2 of grants) {
@@ -54750,42 +54813,42 @@ function getAllowedPersonaIds(grants, action) {
54750
54813
  return ids;
54751
54814
  }
54752
54815
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
54753
- const target = path56.resolve(absPath);
54816
+ const target = path57.resolve(absPath);
54754
54817
  if (userWorkDir) {
54755
- const u = path56.resolve(userWorkDir);
54756
- const usep = u.endsWith(path56.sep) ? "" : path56.sep;
54818
+ const u = path57.resolve(userWorkDir);
54819
+ const usep = u.endsWith(path57.sep) ? "" : path57.sep;
54757
54820
  if (target === u || target.startsWith(u + usep)) return true;
54758
54821
  }
54759
- const root = path56.resolve(personaRoot);
54760
- const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54822
+ const root = path57.resolve(personaRoot);
54823
+ const sep3 = root.endsWith(path57.sep) ? "" : path57.sep;
54761
54824
  if (!target.startsWith(root + sep3)) return false;
54762
- const rel = path56.relative(root, target);
54825
+ const rel = path57.relative(root, target);
54763
54826
  if (!rel || rel.startsWith("..")) return false;
54764
- const personaId = rel.split(path56.sep)[0];
54827
+ const personaId = rel.split(path57.sep)[0];
54765
54828
  if (!personaId) return false;
54766
54829
  const allowed = getAllowedPersonaIds(grants, action);
54767
54830
  if (allowed === "*") return true;
54768
54831
  return allowed.has(personaId);
54769
54832
  }
54770
54833
  function personaIdFromPath(absPath, personaRoot) {
54771
- const root = path56.resolve(personaRoot);
54772
- const target = path56.resolve(absPath);
54773
- const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54834
+ const root = path57.resolve(personaRoot);
54835
+ const target = path57.resolve(absPath);
54836
+ const sep3 = root.endsWith(path57.sep) ? "" : path57.sep;
54774
54837
  if (!target.startsWith(root + sep3)) return null;
54775
- const rel = path56.relative(root, target);
54838
+ const rel = path57.relative(root, target);
54776
54839
  if (!rel || rel.startsWith("..")) return null;
54777
- const id = rel.split(path56.sep)[0];
54840
+ const id = rel.split(path57.sep)[0];
54778
54841
  return id || null;
54779
54842
  }
54780
54843
  function isPathWithin(dir, absPath) {
54781
- const d = path56.resolve(dir);
54782
- const t = path56.resolve(absPath);
54783
- const sep3 = d.endsWith(path56.sep) ? "" : path56.sep;
54844
+ const d = path57.resolve(dir);
54845
+ const t = path57.resolve(absPath);
54846
+ const sep3 = d.endsWith(path57.sep) ? "" : path57.sep;
54784
54847
  return t === d || t.startsWith(d + sep3);
54785
54848
  }
54786
54849
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
54787
54850
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
54788
- return personaIdFromPath(path56.resolve(absPath), personaRoot) === personaId;
54851
+ return personaIdFromPath(path57.resolve(absPath), personaRoot) === personaId;
54789
54852
  }
54790
54853
 
54791
54854
  // src/handlers/history.ts
@@ -54811,7 +54874,7 @@ function buildHistoryHandlers(deps) {
54811
54874
  if (!pid) return false;
54812
54875
  return isGuestPathAllowed(
54813
54876
  ctx.grants,
54814
- path57.join(personaRoot, pid),
54877
+ path58.join(personaRoot, pid),
54815
54878
  personaRoot,
54816
54879
  "read",
54817
54880
  userWorkDir
@@ -54823,7 +54886,7 @@ function buildHistoryHandlers(deps) {
54823
54886
  };
54824
54887
  const list = async (frame, _client, ctx) => {
54825
54888
  const args = HistoryListArgs.parse(frame);
54826
- assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list");
54889
+ assertGuestPath(ctx, path58.resolve(args.projectPath), personaRoot, "history:list");
54827
54890
  const sessions = await history.listSessions(args);
54828
54891
  return { response: { type: "history:list", sessions } };
54829
54892
  };
@@ -54855,13 +54918,13 @@ function buildHistoryHandlers(deps) {
54855
54918
  };
54856
54919
  const subagents = async (frame, _client, ctx) => {
54857
54920
  const args = HistorySubagentsArgs.parse(frame);
54858
- assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54921
+ assertGuestPath(ctx, path58.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54859
54922
  const subs = await history.listSubagents(args);
54860
54923
  return { response: { type: "history:subagents", subagents: subs } };
54861
54924
  };
54862
54925
  const subagentRead = async (frame, _client, ctx) => {
54863
54926
  const args = HistorySubagentReadArgs.parse(frame);
54864
- assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54927
+ assertGuestPath(ctx, path58.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54865
54928
  const res = await history.readSubagent(args);
54866
54929
  return { response: { type: "history:subagent-read", ...res } };
54867
54930
  };
@@ -54870,7 +54933,7 @@ function buildHistoryHandlers(deps) {
54870
54933
  if (ctx?.principal.kind === "guest" && personaRoot) {
54871
54934
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54872
54935
  const filtered = dirs.filter(
54873
- (d) => isGuestPathAllowed(ctx.grants, path57.resolve(d.cwd), personaRoot, "read", userWorkDir)
54936
+ (d) => isGuestPathAllowed(ctx.grants, path58.resolve(d.cwd), personaRoot, "read", userWorkDir)
54874
54937
  );
54875
54938
  return { response: { type: "history:recentDirs", dirs: filtered } };
54876
54939
  }
@@ -54887,7 +54950,7 @@ function buildHistoryHandlers(deps) {
54887
54950
  }
54888
54951
 
54889
54952
  // src/handlers/workspace.ts
54890
- var path58 = __toESM(require("path"), 1);
54953
+ var path59 = __toESM(require("path"), 1);
54891
54954
  var os16 = __toESM(require("os"), 1);
54892
54955
  init_protocol();
54893
54956
  init_protocol();
@@ -54929,22 +54992,22 @@ function buildWorkspaceHandlers(deps) {
54929
54992
  const args = WorkspaceListArgs.parse(frame);
54930
54993
  const isGuest = ctx?.principal.kind === "guest";
54931
54994
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
54932
- const resolvedCwd = path58.resolve(args.cwd ?? fallbackCwd);
54933
- const target = args.path ? path58.resolve(resolvedCwd, args.path) : resolvedCwd;
54995
+ const resolvedCwd = path59.resolve(args.cwd ?? fallbackCwd);
54996
+ const target = args.path ? path59.resolve(resolvedCwd, args.path) : resolvedCwd;
54934
54997
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
54935
54998
  const res = workspace.list({ ...args, cwd: resolvedCwd });
54936
54999
  return { response: { type: "workspace:list", ...res } };
54937
55000
  };
54938
55001
  const read = async (frame, _client, ctx) => {
54939
55002
  const args = WorkspaceReadArgs.parse(frame);
54940
- const target = path58.isAbsolute(args.path) ? path58.resolve(args.path) : path58.resolve(args.cwd, args.path);
55003
+ const target = path59.isAbsolute(args.path) ? path59.resolve(args.path) : path59.resolve(args.cwd, args.path);
54941
55004
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
54942
55005
  const res = workspace.read(args);
54943
55006
  return { response: { type: "workspace:read", ...res } };
54944
55007
  };
54945
55008
  const skillsList = async (frame, _client, ctx) => {
54946
55009
  const args = SkillsListArgs.parse(frame);
54947
- const cwdAbs = path58.resolve(args.cwd);
55010
+ const cwdAbs = path59.resolve(args.cwd);
54948
55011
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
54949
55012
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
54950
55013
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -54956,7 +55019,7 @@ function buildWorkspaceHandlers(deps) {
54956
55019
  };
54957
55020
  const agentsList = async (frame, _client, ctx) => {
54958
55021
  const args = AgentsListArgs.parse(frame);
54959
- const cwdAbs = path58.resolve(args.cwd);
55022
+ const cwdAbs = path59.resolve(args.cwd);
54960
55023
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
54961
55024
  if (args.tool === "codex") {
54962
55025
  return { response: { type: "agents:list", agents: [] } };
@@ -54978,20 +55041,20 @@ function buildWorkspaceHandlers(deps) {
54978
55041
  }
54979
55042
 
54980
55043
  // src/handlers/git.ts
54981
- var path60 = __toESM(require("path"), 1);
55044
+ var path61 = __toESM(require("path"), 1);
54982
55045
  init_protocol();
54983
55046
  init_protocol();
54984
55047
 
54985
55048
  // src/workspace/git.ts
54986
55049
  var import_node_child_process12 = require("child_process");
54987
- var import_node_fs45 = __toESM(require("fs"), 1);
54988
- var import_node_path47 = __toESM(require("path"), 1);
55050
+ var import_node_fs46 = __toESM(require("fs"), 1);
55051
+ var import_node_path48 = __toESM(require("path"), 1);
54989
55052
  var import_node_util = require("util");
54990
55053
  var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
54991
55054
  function normalizePath(p2) {
54992
- const resolved = import_node_path47.default.resolve(p2);
55055
+ const resolved = import_node_path48.default.resolve(p2);
54993
55056
  try {
54994
- return import_node_fs45.default.realpathSync(resolved);
55057
+ return import_node_fs46.default.realpathSync(resolved);
54995
55058
  } catch {
54996
55059
  return resolved;
54997
55060
  }
@@ -55065,7 +55128,7 @@ async function listGitBranches(cwd) {
55065
55128
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
55066
55129
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
55067
55130
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
55068
- if (!isGuestPathAllowed(ctx.grants, path60.resolve(cwd), personaRoot, "read", userWorkDir)) {
55131
+ if (!isGuestPathAllowed(ctx.grants, path61.resolve(cwd), personaRoot, "read", userWorkDir)) {
55069
55132
  throw new ClawdError(
55070
55133
  ERROR_CODES.UNAUTHORIZED,
55071
55134
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -55406,22 +55469,22 @@ init_src();
55406
55469
  init_protocol();
55407
55470
 
55408
55471
  // src/sshd/key-issue.ts
55409
- var import_node_fs46 = __toESM(require("fs"), 1);
55410
- var import_node_path48 = __toESM(require("path"), 1);
55472
+ var import_node_fs47 = __toESM(require("fs"), 1);
55473
+ var import_node_path49 = __toESM(require("path"), 1);
55411
55474
  var import_node_child_process13 = require("child_process");
55412
55475
  function safeDeviceId(deviceId) {
55413
55476
  return deviceId.replace(/[\/\\]/g, "_");
55414
55477
  }
55415
55478
  async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55416
55479
  const safeId = safeDeviceId(deviceId);
55417
- const keysDir = import_node_path48.default.join(sshdDir, "keys");
55418
- import_node_fs46.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55419
- const privPath = import_node_path48.default.join(keysDir, `${safeId}.ed25519`);
55480
+ const keysDir = import_node_path49.default.join(sshdDir, "keys");
55481
+ import_node_fs47.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55482
+ const privPath = import_node_path49.default.join(keysDir, `${safeId}.ed25519`);
55420
55483
  const pubPath = `${privPath}.pub`;
55421
- if (import_node_fs46.default.existsSync(privPath) && import_node_fs46.default.existsSync(pubPath)) {
55484
+ if (import_node_fs47.default.existsSync(privPath) && import_node_fs47.default.existsSync(pubPath)) {
55422
55485
  return {
55423
- privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55424
- publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55486
+ privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55487
+ publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
55425
55488
  };
55426
55489
  }
55427
55490
  const bin = opts.keygenBin ?? "/usr/bin/ssh-keygen";
@@ -55435,16 +55498,16 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55435
55498
  p2.on("error", reject);
55436
55499
  });
55437
55500
  try {
55438
- import_node_fs46.default.chmodSync(privPath, 384);
55501
+ import_node_fs47.default.chmodSync(privPath, 384);
55439
55502
  } catch {
55440
55503
  }
55441
55504
  try {
55442
- import_node_fs46.default.chmodSync(pubPath, 420);
55505
+ import_node_fs47.default.chmodSync(pubPath, 420);
55443
55506
  } catch {
55444
55507
  }
55445
55508
  return {
55446
- privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55447
- publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55509
+ privateKeyPem: import_node_fs47.default.readFileSync(privPath, "utf8"),
55510
+ publicKeyLine: import_node_fs47.default.readFileSync(pubPath, "utf8").trim()
55448
55511
  };
55449
55512
  }
55450
55513
 
@@ -55864,7 +55927,7 @@ function buildPersonaHandlers(deps) {
55864
55927
  }
55865
55928
 
55866
55929
  // src/handlers/attachment.ts
55867
- var import_node_path49 = __toESM(require("path"), 1);
55930
+ var import_node_path50 = __toESM(require("path"), 1);
55868
55931
  init_protocol();
55869
55932
  init_protocol();
55870
55933
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -55944,12 +56007,12 @@ function buildAttachmentHandlers(deps) {
55944
56007
  `session ${args.sessionId} scope unresolved`
55945
56008
  );
55946
56009
  }
55947
- const cwdAbs = import_node_path49.default.resolve(sessionFile.cwd);
55948
- const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
56010
+ const cwdAbs = import_node_path50.default.resolve(sessionFile.cwd);
56011
+ const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
55949
56012
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
55950
56013
  const entries = deps.groupFileStore.list(scope, args.sessionId);
55951
56014
  const entry = entries.find((e) => {
55952
- const storedAbs = import_node_path49.default.isAbsolute(e.relPath) ? import_node_path49.default.resolve(e.relPath) : import_node_path49.default.resolve(cwdAbs, e.relPath);
56015
+ const storedAbs = import_node_path50.default.isAbsolute(e.relPath) ? import_node_path50.default.resolve(e.relPath) : import_node_path50.default.resolve(cwdAbs, e.relPath);
55953
56016
  return storedAbs === candidateAbs && !e.stale;
55954
56017
  });
55955
56018
  if (!entry) {
@@ -55974,7 +56037,7 @@ function buildAttachmentHandlers(deps) {
55974
56037
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
55975
56038
  const f = deps.sessionStore.read(sessionId);
55976
56039
  if (!f) return;
55977
- assertGuestAttachmentPath(ctx, import_node_path49.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
56040
+ assertGuestAttachmentPath(ctx, import_node_path50.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55978
56041
  }
55979
56042
  const groupAdd = async (frame, _client, ctx) => {
55980
56043
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -55989,8 +56052,8 @@ function buildAttachmentHandlers(deps) {
55989
56052
  if (!scope) {
55990
56053
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
55991
56054
  }
55992
- const cwdAbs = import_node_path49.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55993
- const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
56055
+ const cwdAbs = import_node_path50.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
56056
+ const candidateAbs = import_node_path50.default.isAbsolute(args.relPath) ? import_node_path50.default.resolve(args.relPath) : import_node_path50.default.resolve(cwdAbs, args.relPath);
55994
56057
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
55995
56058
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
55996
56059
  const size = 0;
@@ -56049,20 +56112,20 @@ function buildAttachmentHandlers(deps) {
56049
56112
 
56050
56113
  // src/handlers/extension.ts
56051
56114
  var import_promises8 = __toESM(require("fs/promises"), 1);
56052
- var import_node_path54 = __toESM(require("path"), 1);
56115
+ var import_node_path55 = __toESM(require("path"), 1);
56053
56116
  init_protocol();
56054
56117
  init_src();
56055
56118
 
56056
56119
  // src/extension/bundle-zip.ts
56057
56120
  var import_promises5 = __toESM(require("fs/promises"), 1);
56058
- var import_node_path50 = __toESM(require("path"), 1);
56121
+ var import_node_path51 = __toESM(require("path"), 1);
56059
56122
  var import_node_crypto14 = __toESM(require("crypto"), 1);
56060
56123
  var import_jszip2 = __toESM(require_lib3(), 1);
56061
56124
  async function bundleExtensionDir(dir) {
56062
56125
  const entries = await listFilesSorted(dir);
56063
56126
  const zip = new import_jszip2.default();
56064
56127
  for (const rel of entries) {
56065
- const abs = import_node_path50.default.join(dir, rel);
56128
+ const abs = import_node_path51.default.join(dir, rel);
56066
56129
  const content = await import_promises5.default.readFile(abs);
56067
56130
  zip.file(rel, content, { date: FIXED_DATE });
56068
56131
  }
@@ -56083,7 +56146,7 @@ async function listFilesSorted(rootDir) {
56083
56146
  return out;
56084
56147
  }
56085
56148
  async function walk(absRoot, relPrefix, out) {
56086
- const dirAbs = import_node_path50.default.join(absRoot, relPrefix);
56149
+ const dirAbs = import_node_path51.default.join(absRoot, relPrefix);
56087
56150
  const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
56088
56151
  for (const e of entries) {
56089
56152
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -56139,7 +56202,7 @@ function computePublishCheck(args) {
56139
56202
 
56140
56203
  // src/extension/install-flow.ts
56141
56204
  var import_promises6 = __toESM(require("fs/promises"), 1);
56142
- var import_node_path52 = __toESM(require("path"), 1);
56205
+ var import_node_path53 = __toESM(require("path"), 1);
56143
56206
  var import_node_os19 = __toESM(require("os"), 1);
56144
56207
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56145
56208
  var import_jszip3 = __toESM(require_lib3(), 1);
@@ -56147,19 +56210,19 @@ init_src();
56147
56210
 
56148
56211
  // src/extension/paths.ts
56149
56212
  var import_node_os18 = __toESM(require("os"), 1);
56150
- var import_node_path51 = __toESM(require("path"), 1);
56213
+ var import_node_path52 = __toESM(require("path"), 1);
56151
56214
  init_src();
56152
56215
  function clawdHomeRoot(override) {
56153
- return override ?? process.env.CLAWD_HOME ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".clawd");
56216
+ return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
56154
56217
  }
56155
56218
  function extensionsRoot(override) {
56156
- return import_node_path51.default.join(clawdHomeRoot(override), "extensions");
56219
+ return import_node_path52.default.join(clawdHomeRoot(override), "extensions");
56157
56220
  }
56158
56221
  function publishedChannelsFile(override) {
56159
- return import_node_path51.default.join(clawdHomeRoot(override), "extensions-published.json");
56222
+ return import_node_path52.default.join(clawdHomeRoot(override), "extensions-published.json");
56160
56223
  }
56161
56224
  function bundleCacheRoot(override) {
56162
- return import_node_path51.default.join(clawdHomeRoot(override), "extension-bundles");
56225
+ return import_node_path52.default.join(clawdHomeRoot(override), "extension-bundles");
56163
56226
  }
56164
56227
 
56165
56228
  // src/extension/install-flow.ts
@@ -56186,7 +56249,7 @@ async function installFromChannel(args, deps) {
56186
56249
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56187
56250
  }
56188
56251
  for (const name of Object.keys(zip.files)) {
56189
- if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56252
+ if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56190
56253
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56191
56254
  }
56192
56255
  }
@@ -56218,7 +56281,7 @@ async function installFromChannel(args, deps) {
56218
56281
  );
56219
56282
  }
56220
56283
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
56221
- const destDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56284
+ const destDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56222
56285
  let destExists = false;
56223
56286
  try {
56224
56287
  await import_promises6.default.access(destDir);
@@ -56232,16 +56295,16 @@ async function installFromChannel(args, deps) {
56232
56295
  );
56233
56296
  }
56234
56297
  const stage = await import_promises6.default.mkdtemp(
56235
- import_node_path52.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56298
+ import_node_path53.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56236
56299
  );
56237
56300
  try {
56238
56301
  for (const [name, entry] of Object.entries(zip.files)) {
56239
- const dest = import_node_path52.default.join(stage, name);
56302
+ const dest = import_node_path53.default.join(stage, name);
56240
56303
  if (entry.dir) {
56241
56304
  await import_promises6.default.mkdir(dest, { recursive: true });
56242
56305
  continue;
56243
56306
  }
56244
- await import_promises6.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56307
+ await import_promises6.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56245
56308
  if (name === "manifest.json") {
56246
56309
  const rewritten = { ...parsed.data, id: localExtId };
56247
56310
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56262,7 +56325,7 @@ async function installFromChannel(args, deps) {
56262
56325
 
56263
56326
  // src/extension/update-flow.ts
56264
56327
  var import_promises7 = __toESM(require("fs/promises"), 1);
56265
- var import_node_path53 = __toESM(require("path"), 1);
56328
+ var import_node_path54 = __toESM(require("path"), 1);
56266
56329
  var import_node_os20 = __toESM(require("os"), 1);
56267
56330
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56268
56331
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -56280,11 +56343,11 @@ async function updateFromChannel(args, deps) {
56280
56343
  channelRef.extId,
56281
56344
  channelRef.ownerPrincipalId
56282
56345
  );
56283
- const liveDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56346
+ const liveDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
56284
56347
  const prevDir = `${liveDir}.prev`;
56285
56348
  let existingVersion;
56286
56349
  try {
56287
- const raw = await import_promises7.default.readFile(import_node_path53.default.join(liveDir, "manifest.json"), "utf8");
56350
+ const raw = await import_promises7.default.readFile(import_node_path54.default.join(liveDir, "manifest.json"), "utf8");
56288
56351
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
56289
56352
  if (!parsed2.success) {
56290
56353
  throw new UpdateError(
@@ -56317,7 +56380,7 @@ async function updateFromChannel(args, deps) {
56317
56380
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56318
56381
  }
56319
56382
  for (const name of Object.keys(zip.files)) {
56320
- if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56383
+ if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
56321
56384
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56322
56385
  }
56323
56386
  }
@@ -56352,16 +56415,16 @@ async function updateFromChannel(args, deps) {
56352
56415
  await import_promises7.default.rm(prevDir, { recursive: true, force: true });
56353
56416
  await import_promises7.default.rename(liveDir, prevDir);
56354
56417
  const stage = await import_promises7.default.mkdtemp(
56355
- import_node_path53.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56418
+ import_node_path54.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56356
56419
  );
56357
56420
  try {
56358
56421
  for (const [name, entry] of Object.entries(zip.files)) {
56359
- const dest = import_node_path53.default.join(stage, name);
56422
+ const dest = import_node_path54.default.join(stage, name);
56360
56423
  if (entry.dir) {
56361
56424
  await import_promises7.default.mkdir(dest, { recursive: true });
56362
56425
  continue;
56363
56426
  }
56364
- await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56427
+ await import_promises7.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
56365
56428
  if (name === "manifest.json") {
56366
56429
  const rewritten = { ...parsed.data, id: localExtId };
56367
56430
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56455,7 +56518,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56455
56518
  );
56456
56519
  }
56457
56520
  }
56458
- const manifestPath = import_node_path54.default.join(root, extId, "manifest.json");
56521
+ const manifestPath = import_node_path55.default.join(root, extId, "manifest.json");
56459
56522
  const manifest = await readManifest(root, extId);
56460
56523
  const next = { ...manifest, version: newVersion };
56461
56524
  const tmp = `${manifestPath}.tmp`;
@@ -56463,7 +56526,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56463
56526
  await import_promises8.default.rename(tmp, manifestPath);
56464
56527
  }
56465
56528
  async function readManifest(root, extId) {
56466
- const file = import_node_path54.default.join(root, extId, "manifest.json");
56529
+ const file = import_node_path55.default.join(root, extId, "manifest.json");
56467
56530
  let raw;
56468
56531
  try {
56469
56532
  raw = await import_promises8.default.readFile(file, "utf8");
@@ -56554,7 +56617,7 @@ function buildExtensionHandlers(deps) {
56554
56617
  };
56555
56618
  async function buildSnapshotMeta(extId) {
56556
56619
  const manifest = await readManifest(deps.root, extId);
56557
- const { sha256, buffer } = await bundleExtensionDir(import_node_path54.default.join(deps.root, extId));
56620
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path55.default.join(deps.root, extId));
56558
56621
  return { manifest, contentHash: sha256, buffer };
56559
56622
  }
56560
56623
  const publish = async (frame, _client, ctx) => {
@@ -56735,9 +56798,9 @@ function buildExtensionHandlers(deps) {
56735
56798
  }
56736
56799
 
56737
56800
  // src/app-builder/project-store.ts
56738
- var import_node_fs47 = require("fs");
56801
+ var import_node_fs48 = require("fs");
56739
56802
  var import_node_child_process14 = require("child_process");
56740
- var import_node_path55 = require("path");
56803
+ var import_node_path56 = require("path");
56741
56804
  init_protocol();
56742
56805
  var PROJECTS_DIR = "projects";
56743
56806
  var META_FILE = ".clawd-project.json";
@@ -56751,19 +56814,19 @@ var ProjectStore = class {
56751
56814
  root;
56752
56815
  /** projects/<name>/.clawd-project.json 路径 */
56753
56816
  metaPath(name) {
56754
- return (0, import_node_path55.join)(this.projectsRoot(), name, META_FILE);
56817
+ return (0, import_node_path56.join)(this.projectsRoot(), name, META_FILE);
56755
56818
  }
56756
56819
  /** projects/<name>/ 目录路径(cwd 用) */
56757
56820
  projectDir(name) {
56758
- return (0, import_node_path55.join)(this.projectsRoot(), name);
56821
+ return (0, import_node_path56.join)(this.projectsRoot(), name);
56759
56822
  }
56760
56823
  projectsRoot() {
56761
- return (0, import_node_path55.join)(this.root, PROJECTS_DIR);
56824
+ return (0, import_node_path56.join)(this.root, PROJECTS_DIR);
56762
56825
  }
56763
56826
  async list() {
56764
56827
  let entries;
56765
56828
  try {
56766
- entries = await import_node_fs47.promises.readdir(this.projectsRoot());
56829
+ entries = await import_node_fs48.promises.readdir(this.projectsRoot());
56767
56830
  } catch (err) {
56768
56831
  if (err.code === "ENOENT") return [];
56769
56832
  throw err;
@@ -56771,7 +56834,7 @@ var ProjectStore = class {
56771
56834
  const out = [];
56772
56835
  for (const name of entries) {
56773
56836
  try {
56774
- const raw = await import_node_fs47.promises.readFile(this.metaPath(name), "utf8");
56837
+ const raw = await import_node_fs48.promises.readFile(this.metaPath(name), "utf8");
56775
56838
  const json = JSON.parse(raw);
56776
56839
  let migrated = false;
56777
56840
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -56782,7 +56845,7 @@ var ProjectStore = class {
56782
56845
  if (parsed.success) {
56783
56846
  out.push(parsed.data);
56784
56847
  if (migrated) {
56785
- void import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56848
+ void import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56786
56849
  });
56787
56850
  }
56788
56851
  }
@@ -56826,8 +56889,8 @@ var ProjectStore = class {
56826
56889
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
56827
56890
  }
56828
56891
  const dir = this.projectDir(name);
56829
- await import_node_fs47.promises.mkdir(dir, { recursive: true });
56830
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56892
+ await import_node_fs48.promises.mkdir(dir, { recursive: true });
56893
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56831
56894
  return meta;
56832
56895
  }
56833
56896
  /**
@@ -56870,7 +56933,7 @@ var ProjectStore = class {
56870
56933
  }
56871
56934
  async delete(name) {
56872
56935
  const dir = this.projectDir(name);
56873
- await import_node_fs47.promises.rm(dir, { recursive: true, force: true });
56936
+ await import_node_fs48.promises.rm(dir, { recursive: true, force: true });
56874
56937
  }
56875
56938
  async updatePort(name, newPort) {
56876
56939
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -56886,7 +56949,7 @@ var ProjectStore = class {
56886
56949
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
56887
56950
  }
56888
56951
  const updated = { ...target, port: newPort };
56889
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56952
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56890
56953
  return updated;
56891
56954
  }
56892
56955
  /**
@@ -56903,7 +56966,7 @@ var ProjectStore = class {
56903
56966
  if (!validated.success) {
56904
56967
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
56905
56968
  }
56906
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56969
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56907
56970
  return validated.data;
56908
56971
  }
56909
56972
  /**
@@ -56924,7 +56987,7 @@ var ProjectStore = class {
56924
56987
  if (!validated.success) {
56925
56988
  throw new Error(`invalid publishJob: ${validated.error.message}`);
56926
56989
  }
56927
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56990
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56928
56991
  return validated.data;
56929
56992
  }
56930
56993
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -56939,7 +57002,7 @@ var ProjectStore = class {
56939
57002
  if (!validated.success) {
56940
57003
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
56941
57004
  }
56942
- await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
57005
+ await import_node_fs48.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56943
57006
  return validated.data;
56944
57007
  }
56945
57008
  };
@@ -57060,8 +57123,8 @@ var PublishJobRegistry = class {
57060
57123
 
57061
57124
  // src/app-builder/publish-job-runner.ts
57062
57125
  var import_node_child_process16 = require("child_process");
57063
- var import_node_fs48 = require("fs");
57064
- var import_node_path56 = require("path");
57126
+ var import_node_fs49 = require("fs");
57127
+ var import_node_path57 = require("path");
57065
57128
 
57066
57129
  // src/app-builder/publish-stage-parser.ts
57067
57130
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -57093,10 +57156,10 @@ async function startPublishJob(deps, args) {
57093
57156
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
57094
57157
  }
57095
57158
  const projDir = projectDir(args.name);
57096
- const logPath = (0, import_node_path56.join)(projDir, ".publish.log");
57159
+ const logPath = (0, import_node_path57.join)(projDir, ".publish.log");
57097
57160
  let logStream = null;
57098
57161
  try {
57099
- logStream = (0, import_node_fs48.createWriteStream)(logPath, { flags: "w" });
57162
+ logStream = (0, import_node_fs49.createWriteStream)(logPath, { flags: "w" });
57100
57163
  } catch {
57101
57164
  logStream = null;
57102
57165
  }
@@ -57353,8 +57416,8 @@ async function recoverInterruptedJobs(deps) {
57353
57416
 
57354
57417
  // src/handlers/app-builder.ts
57355
57418
  init_protocol();
57356
- var import_node_path57 = require("path");
57357
- var import_node_fs49 = require("fs");
57419
+ var import_node_path58 = require("path");
57420
+ var import_node_fs50 = require("fs");
57358
57421
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57359
57422
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57360
57423
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57435,7 +57498,7 @@ function buildAppBuilderHandlers(deps) {
57435
57498
  async function listAllUsersProjects() {
57436
57499
  if (!deps.usersRoot || !deps.getStore) return [];
57437
57500
  const getStore = deps.getStore;
57438
- const userIds = await import_node_fs49.promises.readdir(deps.usersRoot).catch(() => []);
57501
+ const userIds = await import_node_fs50.promises.readdir(deps.usersRoot).catch(() => []);
57439
57502
  const perUser = await Promise.all(
57440
57503
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57441
57504
  );
@@ -57511,8 +57574,8 @@ function buildAppBuilderHandlers(deps) {
57511
57574
  const project = await userStore.create(f.name, reservedPorts);
57512
57575
  try {
57513
57576
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
57514
- const templateSrcDir = (0, import_node_path57.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57515
- const scaffoldScript = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57577
+ const templateSrcDir = (0, import_node_path58.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57578
+ const scaffoldScript = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57516
57579
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
57517
57580
  deps.logger?.info("app-builder.scaffold.done", {
57518
57581
  name: project.name,
@@ -57733,7 +57796,7 @@ function buildAppBuilderHandlers(deps) {
57733
57796
  await userStore.clearPublishJob(args.name);
57734
57797
  }
57735
57798
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
57736
- const scriptPath = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "publish.sh");
57799
+ const scriptPath = (0, import_node_path58.join)(deps.deployKitRoot, "scripts", "publish.sh");
57737
57800
  deps.logger?.info("app-builder.publish.start", {
57738
57801
  name: args.name,
57739
57802
  sessionId: boundSession.sessionId,
@@ -57902,7 +57965,7 @@ function buildVisitorHandlers(deps) {
57902
57965
 
57903
57966
  // src/extension/registry.ts
57904
57967
  var import_promises9 = __toESM(require("fs/promises"), 1);
57905
- var import_node_path58 = __toESM(require("path"), 1);
57968
+ var import_node_path59 = __toESM(require("path"), 1);
57906
57969
  init_src();
57907
57970
  async function loadAll(root) {
57908
57971
  let entries;
@@ -57916,13 +57979,13 @@ async function loadAll(root) {
57916
57979
  for (const ent of entries) {
57917
57980
  if (!ent.isDirectory()) continue;
57918
57981
  if (ent.name.startsWith(".")) continue;
57919
- records.push(await loadOne(import_node_path58.default.join(root, ent.name), ent.name));
57982
+ records.push(await loadOne(import_node_path59.default.join(root, ent.name), ent.name));
57920
57983
  }
57921
57984
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
57922
57985
  return records;
57923
57986
  }
57924
57987
  async function loadOne(dir, dirName) {
57925
- const manifestPath = import_node_path58.default.join(dir, "manifest.json");
57988
+ const manifestPath = import_node_path59.default.join(dir, "manifest.json");
57926
57989
  let raw;
57927
57990
  try {
57928
57991
  raw = await import_promises9.default.readFile(manifestPath, "utf8");
@@ -57967,7 +58030,7 @@ async function loadOne(dir, dirName) {
57967
58030
 
57968
58031
  // src/extension/uninstall.ts
57969
58032
  var import_promises10 = __toESM(require("fs/promises"), 1);
57970
- var import_node_path59 = __toESM(require("path"), 1);
58033
+ var import_node_path60 = __toESM(require("path"), 1);
57971
58034
  var UninstallError = class extends Error {
57972
58035
  constructor(code, message) {
57973
58036
  super(message);
@@ -57976,7 +58039,7 @@ var UninstallError = class extends Error {
57976
58039
  code;
57977
58040
  };
57978
58041
  async function uninstall(deps) {
57979
- const dir = import_node_path59.default.join(deps.root, deps.extId);
58042
+ const dir = import_node_path60.default.join(deps.root, deps.extId);
57980
58043
  try {
57981
58044
  await import_promises10.default.access(dir);
57982
58045
  } catch {
@@ -58560,7 +58623,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58560
58623
 
58561
58624
  // src/extension/runtime.ts
58562
58625
  var import_node_child_process18 = require("child_process");
58563
- var import_node_path60 = __toESM(require("path"), 1);
58626
+ var import_node_path61 = __toESM(require("path"), 1);
58564
58627
  var import_promises11 = require("timers/promises");
58565
58628
  init_src();
58566
58629
 
@@ -58662,7 +58725,7 @@ var Runtime = class {
58662
58725
  /\$CLAWOS_EXT_PORT/g,
58663
58726
  String(port)
58664
58727
  );
58665
- const dir = import_node_path60.default.join(this.root, extId);
58728
+ const dir = import_node_path61.default.join(this.root, extId);
58666
58729
  const env = {
58667
58730
  ...process.env,
58668
58731
  CLAWOS_EXT_PORT: String(port),
@@ -58774,7 +58837,7 @@ ${handle.stderrTail}`
58774
58837
 
58775
58838
  // src/extension/published-channels.ts
58776
58839
  var import_promises12 = __toESM(require("fs/promises"), 1);
58777
- var import_node_path61 = __toESM(require("path"), 1);
58840
+ var import_node_path62 = __toESM(require("path"), 1);
58778
58841
  init_src();
58779
58842
  init_zod();
58780
58843
  var PublishedChannelsError = class extends Error {
@@ -58874,7 +58937,7 @@ var PublishedChannelStore = class {
58874
58937
  )
58875
58938
  };
58876
58939
  const tmp = `${this.filePath}.tmp`;
58877
- await import_promises12.default.mkdir(import_node_path61.default.dirname(this.filePath), { recursive: true });
58940
+ await import_promises12.default.mkdir(import_node_path62.default.dirname(this.filePath), { recursive: true });
58878
58941
  await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
58879
58942
  await import_promises12.default.rename(tmp, this.filePath);
58880
58943
  }
@@ -58882,7 +58945,7 @@ var PublishedChannelStore = class {
58882
58945
 
58883
58946
  // src/extension/bundle-cache.ts
58884
58947
  var import_promises13 = __toESM(require("fs/promises"), 1);
58885
- var import_node_path62 = __toESM(require("path"), 1);
58948
+ var import_node_path63 = __toESM(require("path"), 1);
58886
58949
  var BundleCache = class {
58887
58950
  constructor(rootDir) {
58888
58951
  this.rootDir = rootDir;
@@ -58891,14 +58954,14 @@ var BundleCache = class {
58891
58954
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
58892
58955
  async write(snapshotHash, buffer) {
58893
58956
  await import_promises13.default.mkdir(this.rootDir, { recursive: true });
58894
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58957
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58895
58958
  const tmp = `${file}.tmp`;
58896
58959
  await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
58897
58960
  await import_promises13.default.rename(tmp, file);
58898
58961
  }
58899
58962
  /** Returns the bundle bytes, or null when the file doesn't exist. */
58900
58963
  async read(snapshotHash) {
58901
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58964
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58902
58965
  try {
58903
58966
  return await import_promises13.default.readFile(file);
58904
58967
  } catch (e) {
@@ -58908,7 +58971,7 @@ var BundleCache = class {
58908
58971
  }
58909
58972
  /** Idempotent — missing file is not an error. */
58910
58973
  async delete(snapshotHash) {
58911
- const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58974
+ const file = import_node_path63.default.join(this.rootDir, `${snapshotHash}.zip`);
58912
58975
  await import_promises13.default.rm(file, { force: true });
58913
58976
  }
58914
58977
  };
@@ -58933,16 +58996,16 @@ async function startDaemon(config) {
58933
58996
  });
58934
58997
  const logger = createLogger({
58935
58998
  level: config.logLevel,
58936
- file: import_node_path63.default.join(config.dataDir, "clawd.log"),
58999
+ file: import_node_path64.default.join(config.dataDir, "clawd.log"),
58937
59000
  logClient
58938
59001
  });
58939
59002
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
58940
59003
  const screenIdleProbeLogger = createFileOnlyLogger({
58941
- file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log"),
59004
+ file: import_node_path64.default.join(config.dataDir, "screen-idle-probe.log"),
58942
59005
  level: "debug"
58943
59006
  });
58944
59007
  logger.info("screen-idle probe logger enabled", {
58945
- file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log")
59008
+ file: import_node_path64.default.join(config.dataDir, "screen-idle-probe.log")
58946
59009
  });
58947
59010
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
58948
59011
  const pre = stateMgr.preflight();
@@ -59080,8 +59143,8 @@ async function startDaemon(config) {
59080
59143
  const agents = new AgentsScanner();
59081
59144
  const history = new ClaudeHistoryReader();
59082
59145
  let transport = null;
59083
- const personaStore = new PersonaStore(import_node_path63.default.join(config.dataDir, "personas"));
59084
- const usersRoot = import_node_path63.default.join(config.dataDir, "users");
59146
+ const personaStore = new PersonaStore(import_node_path64.default.join(config.dataDir, "personas"));
59147
+ const usersRoot = import_node_path64.default.join(config.dataDir, "users");
59085
59148
  const defaultsRoot = findDefaultsRoot(logger);
59086
59149
  if (defaultsRoot) {
59087
59150
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -59101,17 +59164,17 @@ async function startDaemon(config) {
59101
59164
  migrateCodexSandbox({ store: personaStore, logger });
59102
59165
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
59103
59166
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
59104
- const here = typeof __dirname === "string" ? __dirname : import_node_path63.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59167
+ const here = typeof __dirname === "string" ? __dirname : import_node_path64.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59105
59168
  const dispatchServerCandidates = [
59106
- import_node_path63.default.join(here, "dispatch", "mcp-server.cjs"),
59169
+ import_node_path64.default.join(here, "dispatch", "mcp-server.cjs"),
59107
59170
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
59108
- import_node_path63.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59171
+ import_node_path64.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59109
59172
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59110
59173
  ];
59111
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59174
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59112
59175
  let dispatchMcpConfigPath2;
59113
59176
  if (dispatchServerScriptPath) {
59114
- const dispatchLogPath = import_node_path63.default.join(config.dataDir, "dispatch-mcp-server.log");
59177
+ const dispatchLogPath = import_node_path64.default.join(config.dataDir, "dispatch-mcp-server.log");
59115
59178
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
59116
59179
  dataDir: config.dataDir,
59117
59180
  serverScriptPath: dispatchServerScriptPath,
@@ -59128,15 +59191,15 @@ async function startDaemon(config) {
59128
59191
  });
59129
59192
  }
59130
59193
  const ticketServerCandidates = [
59131
- import_node_path63.default.join(here, "ticket", "mcp-server.cjs"),
59132
- import_node_path63.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59194
+ import_node_path64.default.join(here, "ticket", "mcp-server.cjs"),
59195
+ import_node_path64.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59133
59196
  ];
59134
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59197
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59135
59198
  const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
59136
59199
  const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
59137
59200
  let ticketMcpConfigPath2;
59138
59201
  if (ticketServerScriptPath && ticketOwnerUnionId) {
59139
- const ticketLogPath = import_node_path63.default.join(config.dataDir, "ticket-mcp-server.log");
59202
+ const ticketLogPath = import_node_path64.default.join(config.dataDir, "ticket-mcp-server.log");
59140
59203
  ticketMcpConfigPath2 = writeTicketMcpConfig({
59141
59204
  dataDir: config.dataDir,
59142
59205
  serverScriptPath: ticketServerScriptPath,
@@ -59157,13 +59220,13 @@ async function startDaemon(config) {
59157
59220
  });
59158
59221
  }
59159
59222
  const shiftServerCandidates = [
59160
- import_node_path63.default.join(here, "shift", "mcp-server.cjs"),
59161
- import_node_path63.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59223
+ import_node_path64.default.join(here, "shift", "mcp-server.cjs"),
59224
+ import_node_path64.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59162
59225
  ];
59163
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59226
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59164
59227
  let shiftMcpConfigPath2;
59165
59228
  if (shiftServerScriptPath) {
59166
- const shiftLogPath = import_node_path63.default.join(config.dataDir, "shift-mcp-server.log");
59229
+ const shiftLogPath = import_node_path64.default.join(config.dataDir, "shift-mcp-server.log");
59167
59230
  shiftMcpConfigPath2 = await writeShiftMcpConfig({
59168
59231
  dataDir: config.dataDir,
59169
59232
  serverScriptPath: shiftServerScriptPath,
@@ -59181,13 +59244,13 @@ async function startDaemon(config) {
59181
59244
  );
59182
59245
  }
59183
59246
  const inboxServerCandidates = [
59184
- import_node_path63.default.join(here, "inbox", "mcp-server.cjs"),
59185
- import_node_path63.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59247
+ import_node_path64.default.join(here, "inbox", "mcp-server.cjs"),
59248
+ import_node_path64.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59186
59249
  ];
59187
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59250
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs51.default.existsSync(p2));
59188
59251
  let inboxMcpConfigPath2;
59189
59252
  if (inboxServerScriptPath) {
59190
- const inboxLogPath = import_node_path63.default.join(config.dataDir, "inbox-mcp-server.log");
59253
+ const inboxLogPath = import_node_path64.default.join(config.dataDir, "inbox-mcp-server.log");
59191
59254
  inboxMcpConfigPath2 = await writeInboxMcpConfig({
59192
59255
  dataDir: config.dataDir,
59193
59256
  serverScriptPath: inboxServerScriptPath,
@@ -59205,7 +59268,7 @@ async function startDaemon(config) {
59205
59268
  );
59206
59269
  }
59207
59270
  const shiftStore = createShiftStore({
59208
- filePath: import_node_path63.default.join(config.dataDir, "shift.json"),
59271
+ filePath: import_node_path64.default.join(config.dataDir, "shift.json"),
59209
59272
  ownerIdProvider: () => ownerPrincipalId,
59210
59273
  now: () => Date.now()
59211
59274
  });
@@ -59227,7 +59290,7 @@ async function startDaemon(config) {
59227
59290
  getAdapter,
59228
59291
  historyReader: history,
59229
59292
  dataDir: config.dataDir,
59230
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59293
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59231
59294
  usersRoot,
59232
59295
  personaStore,
59233
59296
  ownerDisplayName,
@@ -59270,10 +59333,10 @@ async function startDaemon(config) {
59270
59333
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
59271
59334
  attachmentGroup: {
59272
59335
  onFileEdit: (input) => {
59273
- const absPath = import_node_path63.default.isAbsolute(input.relPath) ? input.relPath : import_node_path63.default.join(input.cwd, input.relPath);
59336
+ const absPath = import_node_path64.default.isAbsolute(input.relPath) ? input.relPath : import_node_path64.default.join(input.cwd, input.relPath);
59274
59337
  let size = 0;
59275
59338
  try {
59276
- size = import_node_fs50.default.statSync(absPath).size;
59339
+ size = import_node_fs51.default.statSync(absPath).size;
59277
59340
  } catch (err) {
59278
59341
  logger.warn("attachment.onFileEdit stat failed", {
59279
59342
  sessionId: input.sessionId,
@@ -59472,11 +59535,11 @@ async function startDaemon(config) {
59472
59535
  // 'persona/<pid>/owner',default 走 'default'。
59473
59536
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
59474
59537
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
59475
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59538
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59476
59539
  usersRoot
59477
59540
  },
59478
59541
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
59479
- personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59542
+ personaRoot: import_node_path64.default.join(config.dataDir, "personas"),
59480
59543
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
59481
59544
  usersRoot,
59482
59545
  // capability:list / delete handler 依赖
@@ -59498,7 +59561,7 @@ async function startDaemon(config) {
59498
59561
  contactStore,
59499
59562
  // <dataDir>/sshd 绝对路径 —— contact-ssh handlers 用它拼 authorized_keys / keys/ 子路径
59500
59563
  // Task 10 会加 SshdManager 起 sshd;handlers wire 提前挂 sshdDir 让 typecheck 过
59501
- sshdDir: import_node_path63.default.join(config.dataDir, "sshd"),
59564
+ sshdDir: import_node_path64.default.join(config.dataDir, "sshd"),
59502
59565
  contactSshLog: sshLog,
59503
59566
  // inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
59504
59567
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
@@ -59589,11 +59652,11 @@ async function startDaemon(config) {
59589
59652
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
59590
59653
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
59591
59654
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
59592
- appBuilderPersonaRoot: import_node_path63.default.join(config.dataDir, "personas", "persona-app-builder"),
59655
+ appBuilderPersonaRoot: import_node_path64.default.join(config.dataDir, "personas", "persona-app-builder"),
59593
59656
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
59594
- deployKitRoot: import_node_path63.default.join(config.dataDir, "deploy-kit"),
59657
+ deployKitRoot: import_node_path64.default.join(config.dataDir, "deploy-kit"),
59595
59658
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
59596
- resolvePersonaRoot: (personaId) => import_node_path63.default.join(config.dataDir, "personas", personaId),
59659
+ resolvePersonaRoot: (personaId) => import_node_path64.default.join(config.dataDir, "personas", personaId),
59597
59660
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
59598
59661
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
59599
59662
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -59636,7 +59699,7 @@ async function startDaemon(config) {
59636
59699
  }
59637
59700
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
59638
59701
  if (sourceFile && sourceFile.toolSessionId) {
59639
- sourceJsonlPath = import_node_path63.default.join(
59702
+ sourceJsonlPath = import_node_path64.default.join(
59640
59703
  import_node_os21.default.homedir(),
59641
59704
  ".claude",
59642
59705
  "projects",
@@ -59966,8 +60029,8 @@ async function startDaemon(config) {
59966
60029
  const lines = [
59967
60030
  `Tunnel: ${r.url}`,
59968
60031
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
59969
- `Frpc config: ${import_node_path63.default.join(config.dataDir, "frpc.toml")}`,
59970
- `Frpc log: ${import_node_path63.default.join(config.dataDir, "frpc.log")}`
60032
+ `Frpc config: ${import_node_path64.default.join(config.dataDir, "frpc.toml")}`,
60033
+ `Frpc log: ${import_node_path64.default.join(config.dataDir, "frpc.log")}`
59971
60034
  ];
59972
60035
  const width = Math.max(...lines.map((l) => l.length));
59973
60036
  const bar = "\u2550".repeat(width + 4);
@@ -59980,8 +60043,8 @@ ${bar}
59980
60043
 
59981
60044
  `);
59982
60045
  try {
59983
- const connectPath = import_node_path63.default.join(config.dataDir, "connect.txt");
59984
- import_node_fs50.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
60046
+ const connectPath = import_node_path64.default.join(config.dataDir, "connect.txt");
60047
+ import_node_fs51.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
59985
60048
  } catch {
59986
60049
  }
59987
60050
  } catch (err) {
@@ -60015,7 +60078,7 @@ ${bar}
60015
60078
  });
60016
60079
  try {
60017
60080
  await sshdMgr.start();
60018
- rebuildAuthorizedKeys(contactStore, import_node_path63.default.join(config.dataDir, "sshd"));
60081
+ rebuildAuthorizedKeys(contactStore, import_node_path64.default.join(config.dataDir, "sshd"));
60019
60082
  logger.info("sshd: contact-ssh sandbox ready", { port: config.sshdPort });
60020
60083
  } catch (err) {
60021
60084
  logger.warn("sshd start failed; contact SSH grant will not work until fixed", {
@@ -60083,9 +60146,9 @@ ${bar}
60083
60146
  };
60084
60147
  }
60085
60148
  function migrateDropPersonsDir(dataDir) {
60086
- const dir = import_node_path63.default.join(dataDir, "persons");
60149
+ const dir = import_node_path64.default.join(dataDir, "persons");
60087
60150
  try {
60088
- import_node_fs50.default.rmSync(dir, { recursive: true, force: true });
60151
+ import_node_fs51.default.rmSync(dir, { recursive: true, force: true });
60089
60152
  } catch {
60090
60153
  }
60091
60154
  }