@clawos-dev/clawd 0.2.205-beta.409.d6f7a21 → 0.2.205-beta.410.e49bc1f

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 +441 -369
  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: path76, errorMaps, issueData } = params;
746
- const fullPath = [...path76, ...issueData.path || []];
745
+ const { data, path: path77, errorMaps, issueData } = params;
746
+ const fullPath = [...path77, ...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, path76, key) {
1057
+ constructor(parent, value, path77, key) {
1058
1058
  this._cachedPath = [];
1059
1059
  this.parent = parent;
1060
1060
  this.data = value;
1061
- this._path = path76;
1061
+ this._path = path77;
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 path76 = req.path;
6453
- _req.url = typeof path76 === "string" ? path76 : req.url ? req.url.path || req.url : void 0;
6452
+ const path77 = req.path;
6453
+ _req.url = typeof path77 === "string" ? path77 : 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(path76) {
6618
+ function parsePath(path77) {
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 < path76.length; i++) {
6625
- const char = path76[i];
6624
+ for (let i = 0; i < path77.length; i++) {
6625
+ const char = path77[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 path76 of paths) {
6757
- const parts = parsePath(path76);
6756
+ for (const path77 of paths) {
6757
+ const parts = parsePath(path77);
6758
6758
  if (parts.includes("*")) {
6759
- redactWildcardPath(obj, parts, censor, path76, remove);
6759
+ redactWildcardPath(obj, parts, censor, path77, 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, path76) => {
6845
- const fullPath = [...pathArray.slice(0, pathLength), ...path76];
6844
+ const wrappedCensor = typeof censor === "function" ? (value, path77) => {
6845
+ const fullPath = [...pathArray.slice(0, pathLength), ...path77];
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 path76 of pathsToClone) {
6881
- const parts = parsePath(path76);
6880
+ for (const path77 of pathsToClone) {
6881
+ const parts = parsePath(path77);
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(path76) {
6934
- if (typeof path76 !== "string") {
6933
+ function validatePath(path77) {
6934
+ if (typeof path77 !== "string") {
6935
6935
  throw new Error("Paths must be (non-empty) strings");
6936
6936
  }
6937
- if (path76 === "") {
6937
+ if (path77 === "") {
6938
6938
  throw new Error("Invalid redaction path ()");
6939
6939
  }
6940
- if (path76.includes("..")) {
6941
- throw new Error(`Invalid redaction path (${path76})`);
6940
+ if (path77.includes("..")) {
6941
+ throw new Error(`Invalid redaction path (${path77})`);
6942
6942
  }
6943
- if (path76.includes(",")) {
6944
- throw new Error(`Invalid redaction path (${path76})`);
6943
+ if (path77.includes(",")) {
6944
+ throw new Error(`Invalid redaction path (${path77})`);
6945
6945
  }
6946
6946
  let bracketCount = 0;
6947
6947
  let inQuotes = false;
6948
6948
  let quoteChar = "";
6949
- for (let i = 0; i < path76.length; i++) {
6950
- const char = path76[i];
6949
+ for (let i = 0; i < path77.length; i++) {
6950
+ const char = path77[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 (${path76})`);
6964
+ throw new Error(`Invalid redaction path (${path77})`);
6965
6965
  }
6966
6966
  }
6967
6967
  }
6968
6968
  if (bracketCount !== 0) {
6969
- throw new Error(`Invalid redaction path (${path76})`);
6969
+ throw new Error(`Invalid redaction path (${path77})`);
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 path76 of paths) {
6977
- validatePath(path76);
6976
+ for (const path77 of paths) {
6977
+ validatePath(path77);
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, path76) => {
7146
- return censor(value, [k2, ...path76]);
7145
+ const wrappedCensor = typeof censor === "function" ? (value, path77) => {
7146
+ return censor(value, [k2, ...path77]);
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 fs69 = require("fs");
7364
+ var fs70 = require("fs");
7365
7365
  var EventEmitter3 = require("events");
7366
7366
  var inherits = require("util").inherits;
7367
- var path76 = require("path");
7367
+ var path77 = 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) fs69.mkdirSync(path76.dirname(file), { recursive: true });
7422
- const fd = fs69.openSync(file, flags, mode);
7421
+ if (sonic.mkdir) fs70.mkdirSync(path77.dirname(file), { recursive: true });
7422
+ const fd = fs70.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
- fs69.mkdir(path76.dirname(file), { recursive: true }, (err) => {
7429
+ fs70.mkdir(path77.dirname(file), { recursive: true }, (err) => {
7430
7430
  if (err) return fileOpened(err);
7431
- fs69.open(file, flags, mode, fileOpened);
7431
+ fs70.open(file, flags, mode, fileOpened);
7432
7432
  });
7433
7433
  } else {
7434
- fs69.open(file, flags, mode, fileOpened);
7434
+ fs70.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 = () => fs69.writeSync(this.fd, this._writingBuf);
7476
- fsWrite = () => fs69.write(this.fd, this._writingBuf, this.release);
7475
+ fsWriteSync = () => fs70.writeSync(this.fd, this._writingBuf);
7476
+ fsWrite = () => fs70.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 fs69.writeSync(this.fd, this._writingBuf);
7485
+ return fs70.writeSync(this.fd, this._writingBuf);
7486
7486
  }
7487
- return fs69.writeSync(this.fd, this._writingBuf, "utf8");
7487
+ return fs70.writeSync(this.fd, this._writingBuf, "utf8");
7488
7488
  };
7489
7489
  fsWrite = () => {
7490
7490
  if (Buffer.isBuffer(this._writingBuf)) {
7491
- return fs69.write(this.fd, this._writingBuf, this.release);
7491
+ return fs70.write(this.fd, this._writingBuf, this.release);
7492
7492
  }
7493
- return fs69.write(this.fd, this._writingBuf, "utf8", this.release);
7493
+ return fs70.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
- fs69.fsyncSync(this.fd);
7550
+ fs70.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
- fs69.fsync(this.fd, (err) => {
7664
+ fs70.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
- fs69.close(fd, (err) => {
7766
+ fs70.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) ? fs69.writeSync(this.fd, buf) : fs69.writeSync(this.fd, buf, "utf8");
7815
+ const n = Buffer.isBuffer(buf) ? fs70.writeSync(this.fd, buf) : fs70.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
- fs69.fsyncSync(this.fd);
7831
+ fs70.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 = fs69.writeSync(this.fd, buf);
7852
+ const n = fs70.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) ? fs69.writeSync(this.fd, this._writingBuf) : fs69.writeSync(this.fd, this._writingBuf, "utf8");
7880
+ const written = Buffer.isBuffer(this._writingBuf) ? fs70.writeSync(this.fd, this._writingBuf) : fs70.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
- fs69.write(this.fd, this._writingBuf, release);
7886
+ fs70.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 = fs69.writeSync(this.fd, this._writingBuf);
7895
+ const written = fs70.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
- fs69.write(this.fd, this._writingBuf, release);
7904
+ fs70.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
- fs69.fsync(sonic.fd, closeWrapped);
7920
+ fs70.fsync(sonic.fd, closeWrapped);
7921
7921
  } catch {
7922
7922
  }
7923
7923
  function closeWrapped() {
7924
7924
  if (sonic.fd !== 1 && sonic.fd !== 2) {
7925
- fs69.close(sonic.fd, done);
7925
+ fs70.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(path76, added, removed, oldPosInc, options) {
11061
- var last = path76.lastComponent;
11060
+ addToPath: function addToPath(path77, added, removed, oldPosInc, options) {
11061
+ var last = path77.lastComponent;
11062
11062
  if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
11063
11063
  return {
11064
- oldPos: path76.oldPos + oldPosInc,
11064
+ oldPos: path77.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: path76.oldPos + oldPosInc,
11074
+ oldPos: path77.oldPos + oldPosInc,
11075
11075
  lastComponent: {
11076
11076
  count: 1,
11077
11077
  added,
@@ -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 path76 = typeof rec3.path === "string" ? rec3.path : null;
11540
+ const path77 = typeof rec3.path === "string" ? rec3.path : null;
11541
11541
  const content = typeof rec3.content === "string" ? rec3.content : null;
11542
- if (!path76 || content == null) return null;
11543
- const entry = { path: path76, content };
11542
+ if (!path77 || content == null) return null;
11543
+ const entry = { path: path77, content };
11544
11544
  if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
11545
11545
  return entry;
11546
11546
  }).filter((m2) => m2 !== null);
@@ -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 path76 = typeof rec3.path === "string" ? rec3.path : null;
12363
+ const path77 = typeof rec3.path === "string" ? rec3.path : null;
12364
12364
  const content = typeof rec3.content === "string" ? rec3.content : null;
12365
- if (!path76 || content == null) return null;
12366
- const out = { path: path76, content };
12365
+ if (!path77 || content == null) return null;
12366
+ const out = { path: path77, content };
12367
12367
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12368
12368
  return out;
12369
12369
  }).filter((m2) => m2 !== null);
@@ -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(path76) {
33464
- var parts = path76.split("/");
33463
+ exports2.resolve = function(path77) {
33464
+ var parts = path77.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(path76) {
39318
- if (path76.slice(-1) === "/") {
39319
- path76 = path76.substring(0, path76.length - 1);
39317
+ var parentFolder = function(path77) {
39318
+ if (path77.slice(-1) === "/") {
39319
+ path77 = path77.substring(0, path77.length - 1);
39320
39320
  }
39321
- var lastSlash = path76.lastIndexOf("/");
39322
- return lastSlash > 0 ? path76.substring(0, lastSlash) : "";
39321
+ var lastSlash = path77.lastIndexOf("/");
39322
+ return lastSlash > 0 ? path77.substring(0, lastSlash) : "";
39323
39323
  };
39324
- var forceTrailingSlash = function(path76) {
39325
- if (path76.slice(-1) !== "/") {
39326
- path76 += "/";
39324
+ var forceTrailingSlash = function(path77) {
39325
+ if (path77.slice(-1) !== "/") {
39326
+ path77 += "/";
39327
39327
  }
39328
- return path76;
39328
+ return path77;
39329
39329
  };
39330
39330
  var folderAdd = function(name, createFolders) {
39331
39331
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -40324,10 +40324,53 @@ var require_lib3 = __commonJS({
40324
40324
  }
40325
40325
  });
40326
40326
 
40327
+ // src/sshd/contact-ssh-log.ts
40328
+ function createContactSshLog(dataDir) {
40329
+ const file = import_node_path40.default.join(dataDir, "contact-ssh.log");
40330
+ function append(level, tag, message, meta) {
40331
+ const time = (/* @__PURE__ */ new Date()).toISOString();
40332
+ let line = `[${time}] [${level}] [${tag}] ${message}`;
40333
+ if (meta && Object.keys(meta).length > 0) {
40334
+ try {
40335
+ line += " " + JSON.stringify(meta);
40336
+ } catch {
40337
+ line += " [meta-serialize-failed]";
40338
+ }
40339
+ }
40340
+ line += "\n";
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 });
40344
+ } catch {
40345
+ }
40346
+ }
40347
+ return {
40348
+ info: (tag, message, meta) => append("INFO", tag, message, meta),
40349
+ warn: (tag, message, meta) => append("WARN", tag, message, meta),
40350
+ error: (tag, message, meta) => append("ERROR", tag, message, meta)
40351
+ };
40352
+ }
40353
+ var import_node_fs39, import_node_path40, nullContactSshLog;
40354
+ var init_contact_ssh_log = __esm({
40355
+ "src/sshd/contact-ssh-log.ts"() {
40356
+ "use strict";
40357
+ import_node_fs39 = __toESM(require("fs"), 1);
40358
+ import_node_path40 = __toESM(require("path"), 1);
40359
+ nullContactSshLog = {
40360
+ info: () => {
40361
+ },
40362
+ warn: () => {
40363
+ },
40364
+ error: () => {
40365
+ }
40366
+ };
40367
+ }
40368
+ });
40369
+
40327
40370
  // src/run-case/recorder.ts
40328
40371
  function startRunCaseRecorder(opts) {
40329
40372
  const now = opts.now ?? Date.now;
40330
- const dir = import_node_path63.default.dirname(opts.recordPath);
40373
+ const dir = import_node_path64.default.dirname(opts.recordPath);
40331
40374
  let stream = null;
40332
40375
  let closing = false;
40333
40376
  let closedSettled = false;
@@ -40341,8 +40384,8 @@ function startRunCaseRecorder(opts) {
40341
40384
  });
40342
40385
  const ensureStream = () => {
40343
40386
  if (stream) return stream;
40344
- import_node_fs50.default.mkdirSync(dir, { recursive: true });
40345
- stream = import_node_fs50.default.createWriteStream(opts.recordPath, { flags: "a" });
40387
+ import_node_fs51.default.mkdirSync(dir, { recursive: true });
40388
+ stream = import_node_fs51.default.createWriteStream(opts.recordPath, { flags: "a" });
40346
40389
  stream.on("close", () => closedResolve());
40347
40390
  return stream;
40348
40391
  };
@@ -40367,12 +40410,12 @@ function startRunCaseRecorder(opts) {
40367
40410
  };
40368
40411
  return { tap, close, closed };
40369
40412
  }
40370
- var import_node_fs50, import_node_path63;
40413
+ var import_node_fs51, import_node_path64;
40371
40414
  var init_recorder = __esm({
40372
40415
  "src/run-case/recorder.ts"() {
40373
40416
  "use strict";
40374
- import_node_fs50 = __toESM(require("fs"), 1);
40375
- import_node_path63 = __toESM(require("path"), 1);
40417
+ import_node_fs51 = __toESM(require("fs"), 1);
40418
+ import_node_path64 = __toESM(require("path"), 1);
40376
40419
  }
40377
40420
  });
40378
40421
 
@@ -40415,7 +40458,7 @@ var init_wire = __esm({
40415
40458
  // src/run-case/controller.ts
40416
40459
  async function runController(opts) {
40417
40460
  const now = opts.now ?? Date.now;
40418
- const cwd = opts.cwd ?? (0, import_node_fs51.mkdtempSync)(import_node_path64.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40461
+ const cwd = opts.cwd ?? (0, import_node_fs52.mkdtempSync)(import_node_path65.default.join(import_node_os22.default.tmpdir(), "clawd-runcase-"));
40419
40462
  const ownsCwd = opts.cwd === void 0;
40420
40463
  const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
40421
40464
  const spawnCtx = { cwd };
@@ -40576,19 +40619,19 @@ async function runController(opts) {
40576
40619
  if (sigintHandler) process.off("SIGINT", sigintHandler);
40577
40620
  if (ownsCwd) {
40578
40621
  try {
40579
- (0, import_node_fs51.rmSync)(cwd, { recursive: true, force: true });
40622
+ (0, import_node_fs52.rmSync)(cwd, { recursive: true, force: true });
40580
40623
  } catch {
40581
40624
  }
40582
40625
  }
40583
40626
  return exitCode ?? 0;
40584
40627
  }
40585
- var import_node_fs51, import_node_os22, import_node_path64;
40628
+ var import_node_fs52, import_node_os22, import_node_path65;
40586
40629
  var init_controller = __esm({
40587
40630
  "src/run-case/controller.ts"() {
40588
40631
  "use strict";
40589
- import_node_fs51 = require("fs");
40632
+ import_node_fs52 = require("fs");
40590
40633
  import_node_os22 = __toESM(require("os"), 1);
40591
- import_node_path64 = __toESM(require("path"), 1);
40634
+ import_node_path65 = __toESM(require("path"), 1);
40592
40635
  init_claude();
40593
40636
  init_stdout_splitter();
40594
40637
  init_permission_stdio();
@@ -40699,14 +40742,23 @@ async function sshRelay(argv) {
40699
40742
  process.stderr.write("clawd ssh-relay: missing <peer-device-id>\n" + SSH_RELAY_HELP);
40700
40743
  return 2;
40701
40744
  }
40702
- const dataDir = args.dataDir ?? import_node_path65.default.join(import_node_os23.default.homedir(), ".clawd");
40745
+ const dataDir = args.dataDir ?? import_node_path66.default.join(import_node_os23.default.homedir(), ".clawd");
40746
+ const sshLog = createContactSshLog(dataDir);
40703
40747
  const contact = findContact(dataDir, args.peerDeviceId);
40704
40748
  if (!contact) {
40749
+ sshLog.error("relay.contact-not-found", "ssh-relay \u627E\u4E0D\u5230 peer contact", {
40750
+ peerDeviceId: args.peerDeviceId,
40751
+ contactsPath: import_node_path66.default.join(dataDir, "contacts.json")
40752
+ });
40705
40753
  process.stderr.write(`clawd ssh-relay: contact ${args.peerDeviceId} not found in ${dataDir}/contacts.json
40706
40754
  `);
40707
40755
  return 2;
40708
40756
  }
40709
40757
  if (!contact.connectToken) {
40758
+ sshLog.error("relay.token-missing", "contact \u6709\u8BB0\u5F55\u4F46\u7F3A connectToken\uFF08auto-reverse \u672A\u6362\u7968\uFF09", {
40759
+ peerDeviceId: args.peerDeviceId,
40760
+ peerDisplayName: contact.displayName
40761
+ });
40710
40762
  process.stderr.write(
40711
40763
  `clawd ssh-relay: contact ${args.peerDeviceId} has no connectToken (auto-reverse \u672A\u6362\u7968)
40712
40764
  `
@@ -40716,6 +40768,11 @@ async function sshRelay(argv) {
40716
40768
  const baseHttp = wsUrlToHttp(contact.remoteUrl).replace(/\/+$/, "");
40717
40769
  const wsBase = baseHttp.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
40718
40770
  const url = `${wsBase}/rpc/ssh-tunnel`;
40771
+ sshLog.info("relay.dial", "\u5F00\u59CB\u62E8 A \u4FA7 /rpc/ssh-tunnel", {
40772
+ peerDeviceId: args.peerDeviceId,
40773
+ peerDisplayName: contact.displayName,
40774
+ url
40775
+ });
40719
40776
  return new Promise((resolve6) => {
40720
40777
  const ws = new import_websocket.default(url, {
40721
40778
  headers: {
@@ -40735,6 +40792,9 @@ async function sshRelay(argv) {
40735
40792
  resolve6(exitCode);
40736
40793
  };
40737
40794
  ws.on("open", () => {
40795
+ sshLog.info("relay.dial-open", "ws open\uFF0C\u8FDB\u5165 stdio \u2194 ws \u4E2D\u7EE7", {
40796
+ peerDeviceId: args.peerDeviceId
40797
+ });
40738
40798
  process.stdin.on("data", (chunk) => {
40739
40799
  if (ws.readyState === ws.OPEN) {
40740
40800
  ws.send(chunk, { binary: true });
@@ -40759,9 +40819,25 @@ async function sshRelay(argv) {
40759
40819
  }
40760
40820
  });
40761
40821
  ws.on("close", (code) => {
40822
+ if (code === 1e3) {
40823
+ sshLog.info("relay.dial-close", "ws \u6B63\u5E38\u5173\u95ED", {
40824
+ peerDeviceId: args.peerDeviceId,
40825
+ code
40826
+ });
40827
+ } else {
40828
+ sshLog.warn("relay.dial-close-abnormal", "ws \u975E\u6B63\u5E38\u5173\u95ED\uFF08A \u4FA7\u62D2 auth / \u7F51\u7EDC\u65AD / peer \u5D29\uFF09", {
40829
+ peerDeviceId: args.peerDeviceId,
40830
+ code
40831
+ });
40832
+ }
40762
40833
  settle(code === 1e3 ? 0 : 1);
40763
40834
  });
40764
40835
  ws.on("error", (err) => {
40836
+ sshLog.error("relay.dial-error", "ws \u8FDE\u63A5\u9519\u8BEF\uFF08peer \u4E0D\u53EF\u8FBE / \u7AEF\u53E3\u4E0D\u901A / TLS \u5931\u8D25\uFF09", {
40837
+ peerDeviceId: args.peerDeviceId,
40838
+ url,
40839
+ message: err.message
40840
+ });
40765
40841
  process.stderr.write(`clawd ssh-relay: ws error ${err.message}
40766
40842
  `);
40767
40843
  settle(1);
@@ -40793,10 +40869,10 @@ function parseSshRelayArgs(argv) {
40793
40869
  return out;
40794
40870
  }
40795
40871
  function findContact(dataDir, deviceId) {
40796
- const file = import_node_path65.default.join(dataDir, "contacts.json");
40872
+ const file = import_node_path66.default.join(dataDir, "contacts.json");
40797
40873
  let raw;
40798
40874
  try {
40799
- raw = import_node_fs52.default.readFileSync(file, "utf8");
40875
+ raw = import_node_fs53.default.readFileSync(file, "utf8");
40800
40876
  } catch {
40801
40877
  return null;
40802
40878
  }
@@ -40814,16 +40890,17 @@ function findContact(dataDir, deviceId) {
40814
40890
  }
40815
40891
  return null;
40816
40892
  }
40817
- var import_node_fs52, import_node_os23, import_node_path65, SSH_RELAY_HELP;
40893
+ var import_node_fs53, import_node_os23, import_node_path66, SSH_RELAY_HELP;
40818
40894
  var init_sshd_cli_relay = __esm({
40819
40895
  "src/sshd/sshd-cli-relay.ts"() {
40820
40896
  "use strict";
40821
- import_node_fs52 = __toESM(require("fs"), 1);
40897
+ import_node_fs53 = __toESM(require("fs"), 1);
40822
40898
  import_node_os23 = __toESM(require("os"), 1);
40823
- import_node_path65 = __toESM(require("path"), 1);
40899
+ import_node_path66 = __toESM(require("path"), 1);
40824
40900
  init_wrapper();
40825
40901
  init_src();
40826
40902
  init_peer_forward();
40903
+ init_contact_ssh_log();
40827
40904
  SSH_RELAY_HELP = `clawd ssh-relay <peer-device-id> [options]
40828
40905
 
40829
40906
  WebSocket relay to a peer daemon's /rpc/ssh-tunnel, exposing raw SSH bytes on
@@ -41023,8 +41100,8 @@ Env (advanced):
41023
41100
  `;
41024
41101
 
41025
41102
  // src/index.ts
41026
- var import_node_path62 = __toESM(require("path"), 1);
41027
- var import_node_fs49 = __toESM(require("fs"), 1);
41103
+ var import_node_path63 = __toESM(require("path"), 1);
41104
+ var import_node_fs50 = __toESM(require("fs"), 1);
41028
41105
  var import_node_os21 = __toESM(require("os"), 1);
41029
41106
 
41030
41107
  // ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
@@ -41738,6 +41815,7 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41738
41815
  fsv.allowRead = unionArr(fsv.allowRead, [
41739
41816
  "~/.clawd/contact-ssh-keys",
41740
41817
  "~/.clawd/contacts.json",
41818
+ "~/.clawd/bin",
41741
41819
  "~/Library/Application Support/@clawos/clawd-desktop/ota-bundles",
41742
41820
  "~/.clawd/config.json",
41743
41821
  "~/.clawd/auth.json"
@@ -41891,12 +41969,14 @@ var CONTACT_SSH_SYSTEM_PROMPT_HINT = `## \u8DE8\u8BBE\u5907\u6587\u4EF6\u8BBF\u9
41891
41969
  \uFF08\u6BCF\u4E2A \`<deviceId>.ed25519\` \u5C31\u662F\u4E00\u628A privkey\uFF0C\u53BB\u6389\u540E\u7F00\u5C31\u662F deviceId\uFF09
41892
41970
  2. \u7528 SSH \u62E8\u53F7\uFF08\u628A \`<A>\` \u6362\u6210\u5B9E\u9645 deviceId\uFF09\uFF1A
41893
41971
  \`\`\`bash
41894
- ssh -o ProxyCommand='clawd ssh-relay <A>' \\
41972
+ ssh -o ProxyCommand='~/.clawd/bin/clawd ssh-relay <A>' \\
41895
41973
  -i ~/.clawd/contact-ssh-keys/<A>.ed25519 \\
41896
41974
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \\
41897
41975
  $USER@127.0.0.1 <command>
41898
41976
  # \u4F8B\u5982\uFF1A... $USER@127.0.0.1 cat /Users/xxx/some/file.md
41899
41977
  # ... $USER@127.0.0.1 ls -la /Users/xxx/proj
41978
+ # \u8BF4\u660E\uFF1A\`~/.clawd/bin/clawd\` \u662F daemon \u542F\u52A8\u65F6 seed \u7684 shim\uFF0C\u786C\u7F16\u7801\u5F53\u524D daemon \u7684
41979
+ # execPath+cliPath\uFF0C\u4FDD\u8BC1 relay \u8DDF daemon \u7248\u672C\u540C\u6B65\u3002\u4E0D\u8981\u7528\u88F8 \`clawd\`\uFF08\u8D70 $PATH \u4F1A\u6F02\uFF09\u3002
41900
41980
  \`\`\`
41901
41981
 
41902
41982
  **A \u6388\u6743\u54EA\u4E9B\u76EE\u5F55\u4E0D\u7528\u4F60\u63D0\u524D\u8BB0**\uFF1AA \u4FA7\u7684 sshd \u62E8\u53F7\u4F1A\u5F3A\u5236\u8D70 sandbox jail\uFF0C\u8FDB\u6C99\u7BB1\u524D\u4F1A\u628A\u6388\u6743\u76EE\u5F55\u5217\u8868\u5199\u5230 stderr\uFF08\u683C\u5F0F \`[clawd-ssh-jail] Access allowed to these directories: ...\`\uFF09\u3002\u4F60\u5373\u4F7F\u731C\u9519\u8DEF\u5F84\u4E5F\u4F1A\u88AB sandbox deny\uFF0C\u4F46 stderr \u91CC\u5C31\u81EA\u5E26\u7B54\u6848\uFF0C\u8BD5\u9519\u4E00\u6B21\u5C31\u5B66\u5230 A \u6388\u6743\u4E86\u54EA\u4E9B\u76EE\u5F55\uFF0C\u4E0B\u6B21\u76F4\u63A5\u7528\u5BF9\u7684\u8DEF\u5F84\u3002
@@ -46566,8 +46646,8 @@ function turnStartInput(text) {
46566
46646
  const items = [];
46567
46647
  let leftover = text;
46568
46648
  for (const m2 of text.matchAll(SKILL_RE)) {
46569
- const [marker, name, path76] = m2;
46570
- items.push({ type: "skill", name, path: path76 });
46649
+ const [marker, name, path77] = m2;
46650
+ items.push({ type: "skill", name, path: path77 });
46571
46651
  leftover = leftover.replace(marker, "");
46572
46652
  }
46573
46653
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -49021,13 +49101,13 @@ function mapSkillsListResponse(res) {
49021
49101
  const r = s ?? {};
49022
49102
  const name = str3(r.name);
49023
49103
  if (!name) continue;
49024
- const path76 = str3(r.path);
49104
+ const path77 = str3(r.path);
49025
49105
  const description = str3(r.description);
49026
49106
  const isPlugin = name.includes(":");
49027
49107
  out.push({
49028
49108
  name,
49029
49109
  source: isPlugin ? "plugin" : "project",
49030
- ...path76 ? { path: path76 } : {},
49110
+ ...path77 ? { path: path77 } : {},
49031
49111
  ...description ? { description } : {},
49032
49112
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49033
49113
  });
@@ -52999,8 +53079,8 @@ async function waitForFrpcReady(proc, timeoutMs) {
52999
53079
  }
53000
53080
 
53001
53081
  // src/sshd/sshd-manager.ts
53002
- var import_node_fs36 = __toESM(require("fs"), 1);
53003
- var import_node_path37 = __toESM(require("path"), 1);
53082
+ var import_node_fs37 = __toESM(require("fs"), 1);
53083
+ var import_node_path38 = __toESM(require("path"), 1);
53004
53084
  var import_node_child_process11 = require("child_process");
53005
53085
 
53006
53086
  // src/sshd/sshd-config.ts
@@ -53283,11 +53363,35 @@ function ensureJailScript(dataDir) {
53283
53363
  return target;
53284
53364
  }
53285
53365
 
53366
+ // src/sshd/clawd-shim.ts
53367
+ var import_node_fs36 = __toESM(require("fs"), 1);
53368
+ var import_node_path37 = __toESM(require("path"), 1);
53369
+ function shellQuote(s) {
53370
+ return `'${s.replace(/'/g, "'\\''")}'`;
53371
+ }
53372
+ function buildClawdShim(execPath, cliPath) {
53373
+ return `#!/usr/bin/env bash
53374
+ # clawd shim (managed by clawd; do not edit)
53375
+ #
53376
+ # \u786C\u7F16\u7801\u672C daemon \u542F\u52A8\u65F6\u7528\u7684 execPath + cliPath\uFF1Bdaemon \u91CD\u542F\u4F1A\u8986\u5199\u672C\u6587\u4EF6\uFF08\u5E42\u7B49 seed\uFF09\u3002
53377
+ # guest CC \u7528 SSH ProxyCommand \u8D70 ~/.clawd/bin/clawd ssh-relay \u65F6\u4F1A\u547D\u4E2D\u672C shim\uFF0C\u4FDD\u8BC1
53378
+ # relay \u4E8C\u8FDB\u5236\u8DDF\u5F53\u524D\u8DD1\u7740\u7684 daemon \u540C\u6E90\u540C\u7248\u672C\u3002
53379
+ exec ${shellQuote(execPath)} ${shellQuote(cliPath)} "$@"
53380
+ `;
53381
+ }
53382
+ 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 });
53387
+ return target;
53388
+ }
53389
+
53286
53390
  // src/sshd/sshd-manager.ts
53287
53391
  var SshdManager = class {
53288
53392
  constructor(deps) {
53289
53393
  this.deps = deps;
53290
- this.sshdDir = import_node_path37.default.join(deps.dataDir, "sshd");
53394
+ this.sshdDir = import_node_path38.default.join(deps.dataDir, "sshd");
53291
53395
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
53292
53396
  }
53293
53397
  deps;
@@ -53306,31 +53410,32 @@ var SshdManager = class {
53306
53410
  ownPid: process.pid,
53307
53411
  logger
53308
53412
  });
53309
- import_node_fs36.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53310
- import_node_fs36.default.mkdirSync(import_node_path37.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
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 });
53311
53415
  ensureJailScript(this.deps.dataDir);
53312
- const hostKeyPath = import_node_path37.default.join(this.sshdDir, "host_key");
53313
- if (!import_node_fs36.default.existsSync(hostKeyPath)) {
53416
+ 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)) {
53314
53419
  await this.generateHostKey(hostKeyPath);
53315
53420
  }
53316
- const akFile = import_node_path37.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53317
- if (!import_node_fs36.default.existsSync(akFile)) {
53318
- import_node_fs36.default.writeFileSync(akFile, "", { mode: 384 });
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 });
53319
53424
  }
53320
- const configPath = import_node_path37.default.join(this.sshdDir, "sshd_config");
53425
+ const configPath = import_node_path38.default.join(this.sshdDir, "sshd_config");
53321
53426
  const config = buildSshdConfig({
53322
53427
  listenAddress: "127.0.0.1",
53323
53428
  port: this.deps.port,
53324
53429
  hostKeyPath,
53325
53430
  authorizedKeysFile: akFile,
53326
- pidFilePath: import_node_path37.default.join(this.sshdDir, "sshd.pid")
53431
+ pidFilePath: import_node_path38.default.join(this.sshdDir, "sshd.pid")
53327
53432
  });
53328
- import_node_fs36.default.writeFileSync(configPath, config, { mode: 384 });
53433
+ import_node_fs37.default.writeFileSync(configPath, config, { mode: 384 });
53329
53434
  const sshdBin = this.deps.sshdBin ?? "/usr/sbin/sshd";
53330
53435
  const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
53331
53436
  stdio: ["ignore", "pipe", "pipe"]
53332
53437
  });
53333
- const logStream = import_node_fs36.default.createWriteStream(import_node_path37.default.join(this.sshdDir, "sshd.log"), {
53438
+ const logStream = import_node_fs37.default.createWriteStream(import_node_path38.default.join(this.sshdDir, "sshd.log"), {
53334
53439
  flags: "a",
53335
53440
  mode: 384
53336
53441
  });
@@ -53423,7 +53528,7 @@ ${tail}` : ready.error;
53423
53528
  p2.on("error", reject);
53424
53529
  });
53425
53530
  try {
53426
- import_node_fs36.default.chmodSync(hostKeyPath, 384);
53531
+ import_node_fs37.default.chmodSync(hostKeyPath, 384);
53427
53532
  } catch {
53428
53533
  }
53429
53534
  }
@@ -53466,17 +53571,17 @@ async function waitForSshdReady(proc, timeoutMs) {
53466
53571
  }
53467
53572
 
53468
53573
  // src/sshd/authorized-keys.ts
53469
- var import_node_fs37 = __toESM(require("fs"), 1);
53470
- var import_node_path38 = __toESM(require("path"), 1);
53574
+ var import_node_fs38 = __toESM(require("fs"), 1);
53575
+ var import_node_path39 = __toESM(require("path"), 1);
53471
53576
  var JAIL_BIN_PATH_ENV = "CLAWD_JAIL_BIN_PATH";
53472
53577
  var AUTHORIZED_KEYS_FILE = "clawd-contacts";
53473
53578
  function jailBinPath() {
53474
- return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path38.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53579
+ return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path39.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53475
53580
  }
53476
53581
  function rebuildAuthorizedKeys(store, sshdDir) {
53477
- const akDir = import_node_path38.default.join(sshdDir, "authorized_keys.d");
53478
- const target = import_node_path38.default.join(akDir, AUTHORIZED_KEYS_FILE);
53479
- import_node_fs37.default.mkdirSync(akDir, { recursive: true, mode: 448 });
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 });
53480
53585
  const lines = ["# managed by clawd; do not edit", ""];
53481
53586
  for (const c of store.list()) {
53482
53587
  if (!c.sshAllowed) continue;
@@ -53490,66 +53595,28 @@ function rebuildAuthorizedKeys(store, sshdDir) {
53490
53595
  }
53491
53596
  const body = lines.join("\n") + "\n";
53492
53597
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
53493
- import_node_fs37.default.writeFileSync(tmp, body, { mode: 384 });
53494
- import_node_fs37.default.renameSync(tmp, target);
53598
+ import_node_fs38.default.writeFileSync(tmp, body, { mode: 384 });
53599
+ import_node_fs38.default.renameSync(tmp, target);
53495
53600
  }
53496
53601
  function readIssuedPubkey(sshdDir, deviceId) {
53497
53602
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53498
- const p2 = import_node_path38.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53603
+ const p2 = import_node_path39.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53499
53604
  try {
53500
- return import_node_fs37.default.readFileSync(p2, "utf8");
53605
+ return import_node_fs38.default.readFileSync(p2, "utf8");
53501
53606
  } catch {
53502
53607
  return null;
53503
53608
  }
53504
53609
  }
53505
53610
 
53506
53611
  // src/sshd/contact-key-puller.ts
53507
- var import_node_fs39 = __toESM(require("fs"), 1);
53508
- var import_node_path40 = __toESM(require("path"), 1);
53612
+ var import_node_fs40 = __toESM(require("fs"), 1);
53613
+ var import_node_path41 = __toESM(require("path"), 1);
53509
53614
  init_peer_forward();
53510
-
53511
- // src/sshd/contact-ssh-log.ts
53512
- var import_node_fs38 = __toESM(require("fs"), 1);
53513
- var import_node_path39 = __toESM(require("path"), 1);
53514
- function createContactSshLog(dataDir) {
53515
- const file = import_node_path39.default.join(dataDir, "contact-ssh.log");
53516
- function append(level, tag, message, meta) {
53517
- const time = (/* @__PURE__ */ new Date()).toISOString();
53518
- let line = `[${time}] [${level}] [${tag}] ${message}`;
53519
- if (meta && Object.keys(meta).length > 0) {
53520
- try {
53521
- line += " " + JSON.stringify(meta);
53522
- } catch {
53523
- line += " [meta-serialize-failed]";
53524
- }
53525
- }
53526
- line += "\n";
53527
- try {
53528
- import_node_fs38.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
53529
- import_node_fs38.default.appendFileSync(file, line, { mode: 384 });
53530
- } catch {
53531
- }
53532
- }
53533
- return {
53534
- info: (tag, message, meta) => append("INFO", tag, message, meta),
53535
- warn: (tag, message, meta) => append("WARN", tag, message, meta),
53536
- error: (tag, message, meta) => append("ERROR", tag, message, meta)
53537
- };
53538
- }
53539
- var nullContactSshLog = {
53540
- info: () => {
53541
- },
53542
- warn: () => {
53543
- },
53544
- error: () => {
53545
- }
53546
- };
53547
-
53548
- // src/sshd/contact-key-puller.ts
53615
+ init_contact_ssh_log();
53549
53616
  var CONTACT_KEYS_DIR = "contact-ssh-keys";
53550
53617
  function safeContactKeyPath(dataDir, deviceId) {
53551
53618
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53552
- return import_node_path40.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53619
+ return import_node_path41.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53553
53620
  }
53554
53621
  async function pullContactSshKeyOnce(deps) {
53555
53622
  const forward = deps.forwardImpl ?? ((c) => forwardContactSshKeyIssueToPeer({
@@ -53615,12 +53682,12 @@ async function pullContactSshKeyOnce(deps) {
53615
53682
  }
53616
53683
  function writeKeyFile(dataDir, deviceId, pem) {
53617
53684
  const p2 = safeContactKeyPath(dataDir, deviceId);
53618
- import_node_fs39.default.mkdirSync(import_node_path40.default.dirname(p2), { recursive: true, mode: 448 });
53619
- import_node_fs39.default.writeFileSync(p2, pem, { mode: 384 });
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 });
53620
53687
  }
53621
53688
  function removeKeyFile(dataDir, deviceId) {
53622
53689
  try {
53623
- import_node_fs39.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53690
+ import_node_fs40.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53624
53691
  return true;
53625
53692
  } catch {
53626
53693
  return false;
@@ -53657,6 +53724,7 @@ var ContactKeyPuller = class {
53657
53724
 
53658
53725
  // src/sshd/ssh-tunnel-relay.ts
53659
53726
  var import_node_net2 = __toESM(require("net"), 1);
53727
+ init_contact_ssh_log();
53660
53728
  async function handleSshTunnelUpgrade(req, socket, head, deps) {
53661
53729
  const sshLog = deps.sshLog ?? nullContactSshLog;
53662
53730
  const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
@@ -53764,29 +53832,32 @@ function pumpWsToSshd(ws, deps, clientAddr) {
53764
53832
  });
53765
53833
  }
53766
53834
 
53835
+ // src/index.ts
53836
+ init_contact_ssh_log();
53837
+
53767
53838
  // src/tunnel/device-key.ts
53768
53839
  var import_node_os14 = __toESM(require("os"), 1);
53769
- var import_node_path41 = __toESM(require("path"), 1);
53840
+ var import_node_path42 = __toESM(require("path"), 1);
53770
53841
  var import_node_crypto11 = __toESM(require("crypto"), 1);
53771
53842
  var DERIVE_SALT = "clawd-tunnel-device-v1";
53772
53843
  function deriveStableDeviceKey(opts = {}) {
53773
53844
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
53774
53845
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
53775
53846
  const home = opts.home ?? import_node_os14.default.homedir();
53776
- const defaultDataDir = import_node_path41.default.resolve(import_node_path41.default.join(home, ".clawd"));
53777
- const normalizedDataDir = opts.dataDir ? import_node_path41.default.resolve(opts.dataDir) : null;
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;
53778
53849
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
53779
53850
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
53780
53851
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
53781
53852
  }
53782
53853
 
53783
53854
  // src/auth-store.ts
53784
- var import_node_fs40 = __toESM(require("fs"), 1);
53785
- var import_node_path42 = __toESM(require("path"), 1);
53855
+ var import_node_fs41 = __toESM(require("fs"), 1);
53856
+ var import_node_path43 = __toESM(require("path"), 1);
53786
53857
  var import_node_crypto12 = __toESM(require("crypto"), 1);
53787
53858
  var AUTH_FILE_NAME = "auth.json";
53788
53859
  function authFilePath(dataDir) {
53789
- return import_node_path42.default.join(dataDir, AUTH_FILE_NAME);
53860
+ return import_node_path43.default.join(dataDir, AUTH_FILE_NAME);
53790
53861
  }
53791
53862
  function loadOrCreateAuthFile(opts) {
53792
53863
  const file = authFilePath(opts.dataDir);
@@ -53822,7 +53893,7 @@ function defaultGenerateOwnerPrincipalId() {
53822
53893
  }
53823
53894
  function readAuthFile(file) {
53824
53895
  try {
53825
- const raw = import_node_fs40.default.readFileSync(file, "utf8");
53896
+ const raw = import_node_fs41.default.readFileSync(file, "utf8");
53826
53897
  const parsed = JSON.parse(raw);
53827
53898
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
53828
53899
  return null;
@@ -53842,25 +53913,25 @@ function readAuthFile(file) {
53842
53913
  }
53843
53914
  }
53844
53915
  function writeAuthFile(file, content) {
53845
- import_node_fs40.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
53846
- import_node_fs40.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
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 });
53847
53918
  try {
53848
- import_node_fs40.default.chmodSync(file, 384);
53919
+ import_node_fs41.default.chmodSync(file, 384);
53849
53920
  } catch {
53850
53921
  }
53851
53922
  }
53852
53923
 
53853
53924
  // src/owner-profile.ts
53854
- var import_node_fs41 = __toESM(require("fs"), 1);
53925
+ var import_node_fs42 = __toESM(require("fs"), 1);
53855
53926
  var import_node_os15 = __toESM(require("os"), 1);
53856
- var import_node_path43 = __toESM(require("path"), 1);
53927
+ var import_node_path44 = __toESM(require("path"), 1);
53857
53928
  var PROFILE_FILENAME = "profile.json";
53858
53929
  function loadOwnerDisplayName(dataDir) {
53859
53930
  const fallback = import_node_os15.default.userInfo().username;
53860
- const profilePath = import_node_path43.default.join(dataDir, PROFILE_FILENAME);
53931
+ const profilePath = import_node_path44.default.join(dataDir, PROFILE_FILENAME);
53861
53932
  let raw;
53862
53933
  try {
53863
- raw = import_node_fs41.default.readFileSync(profilePath, "utf8");
53934
+ raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
53864
53935
  } catch {
53865
53936
  return fallback;
53866
53937
  }
@@ -53883,18 +53954,18 @@ function loadOwnerDisplayName(dataDir) {
53883
53954
  }
53884
53955
 
53885
53956
  // src/feishu-auth/owner-identity-store.ts
53886
- var import_node_fs42 = __toESM(require("fs"), 1);
53887
- var import_node_path44 = __toESM(require("path"), 1);
53957
+ var import_node_fs43 = __toESM(require("fs"), 1);
53958
+ var import_node_path45 = __toESM(require("path"), 1);
53888
53959
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
53889
53960
  var OwnerIdentityStore = class {
53890
53961
  file;
53891
53962
  constructor(dataDir) {
53892
- this.file = import_node_path44.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53963
+ this.file = import_node_path45.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53893
53964
  }
53894
53965
  read() {
53895
53966
  let raw;
53896
53967
  try {
53897
- raw = import_node_fs42.default.readFileSync(this.file, "utf8");
53968
+ raw = import_node_fs43.default.readFileSync(this.file, "utf8");
53898
53969
  } catch {
53899
53970
  return null;
53900
53971
  }
@@ -53922,16 +53993,16 @@ var OwnerIdentityStore = class {
53922
53993
  };
53923
53994
  }
53924
53995
  write(record) {
53925
- import_node_fs42.default.mkdirSync(import_node_path44.default.dirname(this.file), { recursive: true });
53926
- import_node_fs42.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
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 });
53927
53998
  try {
53928
- import_node_fs42.default.chmodSync(this.file, 384);
53999
+ import_node_fs43.default.chmodSync(this.file, 384);
53929
54000
  } catch {
53930
54001
  }
53931
54002
  }
53932
54003
  clear() {
53933
54004
  try {
53934
- import_node_fs42.default.unlinkSync(this.file);
54005
+ import_node_fs43.default.unlinkSync(this.file);
53935
54006
  } catch (err) {
53936
54007
  const code = err?.code;
53937
54008
  if (code !== "ENOENT") throw err;
@@ -54052,9 +54123,9 @@ var CentralClientError = class extends Error {
54052
54123
  code;
54053
54124
  cause;
54054
54125
  };
54055
- async function centralRequest(opts, path76, init) {
54126
+ async function centralRequest(opts, path77, init) {
54056
54127
  const f = opts.fetchImpl ?? globalThis.fetch;
54057
- const url = `${opts.api.replace(/\/+$/, "")}${path76}`;
54128
+ const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
54058
54129
  const ctrl = new AbortController();
54059
54130
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54060
54131
  let res;
@@ -54196,8 +54267,8 @@ function verifyConnectToken(args) {
54196
54267
  }
54197
54268
 
54198
54269
  // src/feishu-auth/server-key.ts
54199
- var fs52 = __toESM(require("fs"), 1);
54200
- var path53 = __toESM(require("path"), 1);
54270
+ var fs53 = __toESM(require("fs"), 1);
54271
+ var path54 = __toESM(require("path"), 1);
54201
54272
  var FILE_NAME2 = "server-signing-key.json";
54202
54273
  var ServerKeyStore = class {
54203
54274
  constructor(dataDir) {
@@ -54205,12 +54276,12 @@ var ServerKeyStore = class {
54205
54276
  }
54206
54277
  dataDir;
54207
54278
  filePath() {
54208
- return path53.join(this.dataDir, FILE_NAME2);
54279
+ return path54.join(this.dataDir, FILE_NAME2);
54209
54280
  }
54210
54281
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54211
54282
  read() {
54212
54283
  try {
54213
- const raw = fs52.readFileSync(this.filePath(), "utf8");
54284
+ const raw = fs53.readFileSync(this.filePath(), "utf8");
54214
54285
  const parsed = JSON.parse(raw);
54215
54286
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54216
54287
  return parsed.publicKeyPem;
@@ -54225,12 +54296,12 @@ var ServerKeyStore = class {
54225
54296
  publicKeyPem,
54226
54297
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54227
54298
  };
54228
- fs52.mkdirSync(this.dataDir, { recursive: true });
54229
- fs52.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54299
+ fs53.mkdirSync(this.dataDir, { recursive: true });
54300
+ fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54230
54301
  }
54231
54302
  clear() {
54232
54303
  try {
54233
- fs52.unlinkSync(this.filePath());
54304
+ fs53.unlinkSync(this.filePath());
54234
54305
  } catch {
54235
54306
  }
54236
54307
  }
@@ -54243,12 +54314,12 @@ init_protocol();
54243
54314
  init_protocol();
54244
54315
 
54245
54316
  // src/session/fork.ts
54246
- var import_node_fs43 = __toESM(require("fs"), 1);
54317
+ var import_node_fs44 = __toESM(require("fs"), 1);
54247
54318
  var import_node_os16 = __toESM(require("os"), 1);
54248
- var import_node_path45 = __toESM(require("path"), 1);
54319
+ var import_node_path46 = __toESM(require("path"), 1);
54249
54320
  init_claude_history();
54250
54321
  function readJsonlEntries(file) {
54251
- const raw = import_node_fs43.default.readFileSync(file, "utf8");
54322
+ const raw = import_node_fs44.default.readFileSync(file, "utf8");
54252
54323
  const out = [];
54253
54324
  for (const line of raw.split("\n")) {
54254
54325
  const t = line.trim();
@@ -54261,10 +54332,10 @@ function readJsonlEntries(file) {
54261
54332
  return out;
54262
54333
  }
54263
54334
  function forkSession(input) {
54264
- const baseDir = input.baseDir ?? import_node_path45.default.join(import_node_os16.default.homedir(), ".claude");
54265
- const projectDir = import_node_path45.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54266
- const sourceFile = import_node_path45.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54267
- if (!import_node_fs43.default.existsSync(sourceFile)) {
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)) {
54268
54339
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
54269
54340
  }
54270
54341
  const entries = readJsonlEntries(sourceFile);
@@ -54294,9 +54365,9 @@ function forkSession(input) {
54294
54365
  }
54295
54366
  forkedLines.push(JSON.stringify(forked));
54296
54367
  }
54297
- const forkedFilePath = import_node_path45.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54298
- import_node_fs43.default.mkdirSync(projectDir, { recursive: true });
54299
- import_node_fs43.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
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 });
54300
54371
  return { forkedToolSessionId, forkedFilePath };
54301
54372
  }
54302
54373
 
@@ -54648,7 +54719,7 @@ function buildPermissionHandlers(deps) {
54648
54719
  }
54649
54720
 
54650
54721
  // src/handlers/history.ts
54651
- var path56 = __toESM(require("path"), 1);
54722
+ var path57 = __toESM(require("path"), 1);
54652
54723
  init_protocol();
54653
54724
 
54654
54725
  // src/session/recent-dirs.ts
@@ -54666,7 +54737,7 @@ function listRecentDirs(store, limit = 50) {
54666
54737
  }
54667
54738
 
54668
54739
  // src/permission/persona-paths.ts
54669
- var path55 = __toESM(require("path"), 1);
54740
+ var path56 = __toESM(require("path"), 1);
54670
54741
  function getAllowedPersonaIds(grants, action) {
54671
54742
  const ids = /* @__PURE__ */ new Set();
54672
54743
  for (const g2 of grants) {
@@ -54679,42 +54750,42 @@ function getAllowedPersonaIds(grants, action) {
54679
54750
  return ids;
54680
54751
  }
54681
54752
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
54682
- const target = path55.resolve(absPath);
54753
+ const target = path56.resolve(absPath);
54683
54754
  if (userWorkDir) {
54684
- const u = path55.resolve(userWorkDir);
54685
- const usep = u.endsWith(path55.sep) ? "" : path55.sep;
54755
+ const u = path56.resolve(userWorkDir);
54756
+ const usep = u.endsWith(path56.sep) ? "" : path56.sep;
54686
54757
  if (target === u || target.startsWith(u + usep)) return true;
54687
54758
  }
54688
- const root = path55.resolve(personaRoot);
54689
- const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54759
+ const root = path56.resolve(personaRoot);
54760
+ const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54690
54761
  if (!target.startsWith(root + sep3)) return false;
54691
- const rel = path55.relative(root, target);
54762
+ const rel = path56.relative(root, target);
54692
54763
  if (!rel || rel.startsWith("..")) return false;
54693
- const personaId = rel.split(path55.sep)[0];
54764
+ const personaId = rel.split(path56.sep)[0];
54694
54765
  if (!personaId) return false;
54695
54766
  const allowed = getAllowedPersonaIds(grants, action);
54696
54767
  if (allowed === "*") return true;
54697
54768
  return allowed.has(personaId);
54698
54769
  }
54699
54770
  function personaIdFromPath(absPath, personaRoot) {
54700
- const root = path55.resolve(personaRoot);
54701
- const target = path55.resolve(absPath);
54702
- const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54771
+ const root = path56.resolve(personaRoot);
54772
+ const target = path56.resolve(absPath);
54773
+ const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54703
54774
  if (!target.startsWith(root + sep3)) return null;
54704
- const rel = path55.relative(root, target);
54775
+ const rel = path56.relative(root, target);
54705
54776
  if (!rel || rel.startsWith("..")) return null;
54706
- const id = rel.split(path55.sep)[0];
54777
+ const id = rel.split(path56.sep)[0];
54707
54778
  return id || null;
54708
54779
  }
54709
54780
  function isPathWithin(dir, absPath) {
54710
- const d = path55.resolve(dir);
54711
- const t = path55.resolve(absPath);
54712
- const sep3 = d.endsWith(path55.sep) ? "" : path55.sep;
54781
+ const d = path56.resolve(dir);
54782
+ const t = path56.resolve(absPath);
54783
+ const sep3 = d.endsWith(path56.sep) ? "" : path56.sep;
54713
54784
  return t === d || t.startsWith(d + sep3);
54714
54785
  }
54715
54786
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
54716
54787
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
54717
- return personaIdFromPath(path55.resolve(absPath), personaRoot) === personaId;
54788
+ return personaIdFromPath(path56.resolve(absPath), personaRoot) === personaId;
54718
54789
  }
54719
54790
 
54720
54791
  // src/handlers/history.ts
@@ -54740,7 +54811,7 @@ function buildHistoryHandlers(deps) {
54740
54811
  if (!pid) return false;
54741
54812
  return isGuestPathAllowed(
54742
54813
  ctx.grants,
54743
- path56.join(personaRoot, pid),
54814
+ path57.join(personaRoot, pid),
54744
54815
  personaRoot,
54745
54816
  "read",
54746
54817
  userWorkDir
@@ -54752,7 +54823,7 @@ function buildHistoryHandlers(deps) {
54752
54823
  };
54753
54824
  const list = async (frame, _client, ctx) => {
54754
54825
  const args = HistoryListArgs.parse(frame);
54755
- assertGuestPath(ctx, path56.resolve(args.projectPath), personaRoot, "history:list");
54826
+ assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list");
54756
54827
  const sessions = await history.listSessions(args);
54757
54828
  return { response: { type: "history:list", sessions } };
54758
54829
  };
@@ -54784,13 +54855,13 @@ function buildHistoryHandlers(deps) {
54784
54855
  };
54785
54856
  const subagents = async (frame, _client, ctx) => {
54786
54857
  const args = HistorySubagentsArgs.parse(frame);
54787
- assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54858
+ assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54788
54859
  const subs = await history.listSubagents(args);
54789
54860
  return { response: { type: "history:subagents", subagents: subs } };
54790
54861
  };
54791
54862
  const subagentRead = async (frame, _client, ctx) => {
54792
54863
  const args = HistorySubagentReadArgs.parse(frame);
54793
- assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54864
+ assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54794
54865
  const res = await history.readSubagent(args);
54795
54866
  return { response: { type: "history:subagent-read", ...res } };
54796
54867
  };
@@ -54799,7 +54870,7 @@ function buildHistoryHandlers(deps) {
54799
54870
  if (ctx?.principal.kind === "guest" && personaRoot) {
54800
54871
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54801
54872
  const filtered = dirs.filter(
54802
- (d) => isGuestPathAllowed(ctx.grants, path56.resolve(d.cwd), personaRoot, "read", userWorkDir)
54873
+ (d) => isGuestPathAllowed(ctx.grants, path57.resolve(d.cwd), personaRoot, "read", userWorkDir)
54803
54874
  );
54804
54875
  return { response: { type: "history:recentDirs", dirs: filtered } };
54805
54876
  }
@@ -54816,7 +54887,7 @@ function buildHistoryHandlers(deps) {
54816
54887
  }
54817
54888
 
54818
54889
  // src/handlers/workspace.ts
54819
- var path57 = __toESM(require("path"), 1);
54890
+ var path58 = __toESM(require("path"), 1);
54820
54891
  var os16 = __toESM(require("os"), 1);
54821
54892
  init_protocol();
54822
54893
  init_protocol();
@@ -54858,22 +54929,22 @@ function buildWorkspaceHandlers(deps) {
54858
54929
  const args = WorkspaceListArgs.parse(frame);
54859
54930
  const isGuest = ctx?.principal.kind === "guest";
54860
54931
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
54861
- const resolvedCwd = path57.resolve(args.cwd ?? fallbackCwd);
54862
- const target = args.path ? path57.resolve(resolvedCwd, args.path) : resolvedCwd;
54932
+ const resolvedCwd = path58.resolve(args.cwd ?? fallbackCwd);
54933
+ const target = args.path ? path58.resolve(resolvedCwd, args.path) : resolvedCwd;
54863
54934
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
54864
54935
  const res = workspace.list({ ...args, cwd: resolvedCwd });
54865
54936
  return { response: { type: "workspace:list", ...res } };
54866
54937
  };
54867
54938
  const read = async (frame, _client, ctx) => {
54868
54939
  const args = WorkspaceReadArgs.parse(frame);
54869
- const target = path57.isAbsolute(args.path) ? path57.resolve(args.path) : path57.resolve(args.cwd, args.path);
54940
+ const target = path58.isAbsolute(args.path) ? path58.resolve(args.path) : path58.resolve(args.cwd, args.path);
54870
54941
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
54871
54942
  const res = workspace.read(args);
54872
54943
  return { response: { type: "workspace:read", ...res } };
54873
54944
  };
54874
54945
  const skillsList = async (frame, _client, ctx) => {
54875
54946
  const args = SkillsListArgs.parse(frame);
54876
- const cwdAbs = path57.resolve(args.cwd);
54947
+ const cwdAbs = path58.resolve(args.cwd);
54877
54948
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
54878
54949
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
54879
54950
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -54885,7 +54956,7 @@ function buildWorkspaceHandlers(deps) {
54885
54956
  };
54886
54957
  const agentsList = async (frame, _client, ctx) => {
54887
54958
  const args = AgentsListArgs.parse(frame);
54888
- const cwdAbs = path57.resolve(args.cwd);
54959
+ const cwdAbs = path58.resolve(args.cwd);
54889
54960
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
54890
54961
  if (args.tool === "codex") {
54891
54962
  return { response: { type: "agents:list", agents: [] } };
@@ -54907,20 +54978,20 @@ function buildWorkspaceHandlers(deps) {
54907
54978
  }
54908
54979
 
54909
54980
  // src/handlers/git.ts
54910
- var path59 = __toESM(require("path"), 1);
54981
+ var path60 = __toESM(require("path"), 1);
54911
54982
  init_protocol();
54912
54983
  init_protocol();
54913
54984
 
54914
54985
  // src/workspace/git.ts
54915
54986
  var import_node_child_process12 = require("child_process");
54916
- var import_node_fs44 = __toESM(require("fs"), 1);
54917
- var import_node_path46 = __toESM(require("path"), 1);
54987
+ var import_node_fs45 = __toESM(require("fs"), 1);
54988
+ var import_node_path47 = __toESM(require("path"), 1);
54918
54989
  var import_node_util = require("util");
54919
54990
  var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
54920
54991
  function normalizePath(p2) {
54921
- const resolved = import_node_path46.default.resolve(p2);
54992
+ const resolved = import_node_path47.default.resolve(p2);
54922
54993
  try {
54923
- return import_node_fs44.default.realpathSync(resolved);
54994
+ return import_node_fs45.default.realpathSync(resolved);
54924
54995
  } catch {
54925
54996
  return resolved;
54926
54997
  }
@@ -54994,7 +55065,7 @@ async function listGitBranches(cwd) {
54994
55065
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
54995
55066
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
54996
55067
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54997
- if (!isGuestPathAllowed(ctx.grants, path59.resolve(cwd), personaRoot, "read", userWorkDir)) {
55068
+ if (!isGuestPathAllowed(ctx.grants, path60.resolve(cwd), personaRoot, "read", userWorkDir)) {
54998
55069
  throw new ClawdError(
54999
55070
  ERROR_CODES.UNAUTHORIZED,
55000
55071
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -55335,22 +55406,22 @@ init_src();
55335
55406
  init_protocol();
55336
55407
 
55337
55408
  // src/sshd/key-issue.ts
55338
- var import_node_fs45 = __toESM(require("fs"), 1);
55339
- var import_node_path47 = __toESM(require("path"), 1);
55409
+ var import_node_fs46 = __toESM(require("fs"), 1);
55410
+ var import_node_path48 = __toESM(require("path"), 1);
55340
55411
  var import_node_child_process13 = require("child_process");
55341
55412
  function safeDeviceId(deviceId) {
55342
55413
  return deviceId.replace(/[\/\\]/g, "_");
55343
55414
  }
55344
55415
  async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55345
55416
  const safeId = safeDeviceId(deviceId);
55346
- const keysDir = import_node_path47.default.join(sshdDir, "keys");
55347
- import_node_fs45.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55348
- const privPath = import_node_path47.default.join(keysDir, `${safeId}.ed25519`);
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`);
55349
55420
  const pubPath = `${privPath}.pub`;
55350
- if (import_node_fs45.default.existsSync(privPath) && import_node_fs45.default.existsSync(pubPath)) {
55421
+ if (import_node_fs46.default.existsSync(privPath) && import_node_fs46.default.existsSync(pubPath)) {
55351
55422
  return {
55352
- privateKeyPem: import_node_fs45.default.readFileSync(privPath, "utf8"),
55353
- publicKeyLine: import_node_fs45.default.readFileSync(pubPath, "utf8").trim()
55423
+ privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55424
+ publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55354
55425
  };
55355
55426
  }
55356
55427
  const bin = opts.keygenBin ?? "/usr/bin/ssh-keygen";
@@ -55364,20 +55435,21 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55364
55435
  p2.on("error", reject);
55365
55436
  });
55366
55437
  try {
55367
- import_node_fs45.default.chmodSync(privPath, 384);
55438
+ import_node_fs46.default.chmodSync(privPath, 384);
55368
55439
  } catch {
55369
55440
  }
55370
55441
  try {
55371
- import_node_fs45.default.chmodSync(pubPath, 420);
55442
+ import_node_fs46.default.chmodSync(pubPath, 420);
55372
55443
  } catch {
55373
55444
  }
55374
55445
  return {
55375
- privateKeyPem: import_node_fs45.default.readFileSync(privPath, "utf8"),
55376
- publicKeyLine: import_node_fs45.default.readFileSync(pubPath, "utf8").trim()
55446
+ privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55447
+ publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55377
55448
  };
55378
55449
  }
55379
55450
 
55380
55451
  // src/handlers/contact-ssh.ts
55452
+ init_contact_ssh_log();
55381
55453
  function ensureOwner2(ctx) {
55382
55454
  if (!ctx || ctx.principal.kind !== "owner") {
55383
55455
  throw new ClawdError(
@@ -55792,7 +55864,7 @@ function buildPersonaHandlers(deps) {
55792
55864
  }
55793
55865
 
55794
55866
  // src/handlers/attachment.ts
55795
- var import_node_path48 = __toESM(require("path"), 1);
55867
+ var import_node_path49 = __toESM(require("path"), 1);
55796
55868
  init_protocol();
55797
55869
  init_protocol();
55798
55870
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -55872,12 +55944,12 @@ function buildAttachmentHandlers(deps) {
55872
55944
  `session ${args.sessionId} scope unresolved`
55873
55945
  );
55874
55946
  }
55875
- const cwdAbs = import_node_path48.default.resolve(sessionFile.cwd);
55876
- const candidateAbs = import_node_path48.default.isAbsolute(args.relPath) ? import_node_path48.default.resolve(args.relPath) : import_node_path48.default.resolve(cwdAbs, args.relPath);
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);
55877
55949
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
55878
55950
  const entries = deps.groupFileStore.list(scope, args.sessionId);
55879
55951
  const entry = entries.find((e) => {
55880
- const storedAbs = import_node_path48.default.isAbsolute(e.relPath) ? import_node_path48.default.resolve(e.relPath) : import_node_path48.default.resolve(cwdAbs, e.relPath);
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);
55881
55953
  return storedAbs === candidateAbs && !e.stale;
55882
55954
  });
55883
55955
  if (!entry) {
@@ -55902,7 +55974,7 @@ function buildAttachmentHandlers(deps) {
55902
55974
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
55903
55975
  const f = deps.sessionStore.read(sessionId);
55904
55976
  if (!f) return;
55905
- assertGuestAttachmentPath(ctx, import_node_path48.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55977
+ assertGuestAttachmentPath(ctx, import_node_path49.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55906
55978
  }
55907
55979
  const groupAdd = async (frame, _client, ctx) => {
55908
55980
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -55917,8 +55989,8 @@ function buildAttachmentHandlers(deps) {
55917
55989
  if (!scope) {
55918
55990
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
55919
55991
  }
55920
- const cwdAbs = import_node_path48.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55921
- const candidateAbs = import_node_path48.default.isAbsolute(args.relPath) ? import_node_path48.default.resolve(args.relPath) : import_node_path48.default.resolve(cwdAbs, args.relPath);
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);
55922
55994
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
55923
55995
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
55924
55996
  const size = 0;
@@ -55977,20 +56049,20 @@ function buildAttachmentHandlers(deps) {
55977
56049
 
55978
56050
  // src/handlers/extension.ts
55979
56051
  var import_promises8 = __toESM(require("fs/promises"), 1);
55980
- var import_node_path53 = __toESM(require("path"), 1);
56052
+ var import_node_path54 = __toESM(require("path"), 1);
55981
56053
  init_protocol();
55982
56054
  init_src();
55983
56055
 
55984
56056
  // src/extension/bundle-zip.ts
55985
56057
  var import_promises5 = __toESM(require("fs/promises"), 1);
55986
- var import_node_path49 = __toESM(require("path"), 1);
56058
+ var import_node_path50 = __toESM(require("path"), 1);
55987
56059
  var import_node_crypto14 = __toESM(require("crypto"), 1);
55988
56060
  var import_jszip2 = __toESM(require_lib3(), 1);
55989
56061
  async function bundleExtensionDir(dir) {
55990
56062
  const entries = await listFilesSorted(dir);
55991
56063
  const zip = new import_jszip2.default();
55992
56064
  for (const rel of entries) {
55993
- const abs = import_node_path49.default.join(dir, rel);
56065
+ const abs = import_node_path50.default.join(dir, rel);
55994
56066
  const content = await import_promises5.default.readFile(abs);
55995
56067
  zip.file(rel, content, { date: FIXED_DATE });
55996
56068
  }
@@ -56011,7 +56083,7 @@ async function listFilesSorted(rootDir) {
56011
56083
  return out;
56012
56084
  }
56013
56085
  async function walk(absRoot, relPrefix, out) {
56014
- const dirAbs = import_node_path49.default.join(absRoot, relPrefix);
56086
+ const dirAbs = import_node_path50.default.join(absRoot, relPrefix);
56015
56087
  const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
56016
56088
  for (const e of entries) {
56017
56089
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -56067,7 +56139,7 @@ function computePublishCheck(args) {
56067
56139
 
56068
56140
  // src/extension/install-flow.ts
56069
56141
  var import_promises6 = __toESM(require("fs/promises"), 1);
56070
- var import_node_path51 = __toESM(require("path"), 1);
56142
+ var import_node_path52 = __toESM(require("path"), 1);
56071
56143
  var import_node_os19 = __toESM(require("os"), 1);
56072
56144
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56073
56145
  var import_jszip3 = __toESM(require_lib3(), 1);
@@ -56075,19 +56147,19 @@ init_src();
56075
56147
 
56076
56148
  // src/extension/paths.ts
56077
56149
  var import_node_os18 = __toESM(require("os"), 1);
56078
- var import_node_path50 = __toESM(require("path"), 1);
56150
+ var import_node_path51 = __toESM(require("path"), 1);
56079
56151
  init_src();
56080
56152
  function clawdHomeRoot(override) {
56081
- return override ?? process.env.CLAWD_HOME ?? import_node_path50.default.join(import_node_os18.default.homedir(), ".clawd");
56153
+ return override ?? process.env.CLAWD_HOME ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".clawd");
56082
56154
  }
56083
56155
  function extensionsRoot(override) {
56084
- return import_node_path50.default.join(clawdHomeRoot(override), "extensions");
56156
+ return import_node_path51.default.join(clawdHomeRoot(override), "extensions");
56085
56157
  }
56086
56158
  function publishedChannelsFile(override) {
56087
- return import_node_path50.default.join(clawdHomeRoot(override), "extensions-published.json");
56159
+ return import_node_path51.default.join(clawdHomeRoot(override), "extensions-published.json");
56088
56160
  }
56089
56161
  function bundleCacheRoot(override) {
56090
- return import_node_path50.default.join(clawdHomeRoot(override), "extension-bundles");
56162
+ return import_node_path51.default.join(clawdHomeRoot(override), "extension-bundles");
56091
56163
  }
56092
56164
 
56093
56165
  // src/extension/install-flow.ts
@@ -56114,7 +56186,7 @@ async function installFromChannel(args, deps) {
56114
56186
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56115
56187
  }
56116
56188
  for (const name of Object.keys(zip.files)) {
56117
- if (name.includes("..") || name.startsWith("/") || import_node_path51.default.isAbsolute(name)) {
56189
+ if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56118
56190
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56119
56191
  }
56120
56192
  }
@@ -56146,7 +56218,7 @@ async function installFromChannel(args, deps) {
56146
56218
  );
56147
56219
  }
56148
56220
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
56149
- const destDir = import_node_path51.default.join(deps.extensionsRoot, localExtId);
56221
+ const destDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56150
56222
  let destExists = false;
56151
56223
  try {
56152
56224
  await import_promises6.default.access(destDir);
@@ -56160,16 +56232,16 @@ async function installFromChannel(args, deps) {
56160
56232
  );
56161
56233
  }
56162
56234
  const stage = await import_promises6.default.mkdtemp(
56163
- import_node_path51.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56235
+ import_node_path52.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56164
56236
  );
56165
56237
  try {
56166
56238
  for (const [name, entry] of Object.entries(zip.files)) {
56167
- const dest = import_node_path51.default.join(stage, name);
56239
+ const dest = import_node_path52.default.join(stage, name);
56168
56240
  if (entry.dir) {
56169
56241
  await import_promises6.default.mkdir(dest, { recursive: true });
56170
56242
  continue;
56171
56243
  }
56172
- await import_promises6.default.mkdir(import_node_path51.default.dirname(dest), { recursive: true });
56244
+ await import_promises6.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56173
56245
  if (name === "manifest.json") {
56174
56246
  const rewritten = { ...parsed.data, id: localExtId };
56175
56247
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56190,7 +56262,7 @@ async function installFromChannel(args, deps) {
56190
56262
 
56191
56263
  // src/extension/update-flow.ts
56192
56264
  var import_promises7 = __toESM(require("fs/promises"), 1);
56193
- var import_node_path52 = __toESM(require("path"), 1);
56265
+ var import_node_path53 = __toESM(require("path"), 1);
56194
56266
  var import_node_os20 = __toESM(require("os"), 1);
56195
56267
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56196
56268
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -56208,11 +56280,11 @@ async function updateFromChannel(args, deps) {
56208
56280
  channelRef.extId,
56209
56281
  channelRef.ownerPrincipalId
56210
56282
  );
56211
- const liveDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56283
+ const liveDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56212
56284
  const prevDir = `${liveDir}.prev`;
56213
56285
  let existingVersion;
56214
56286
  try {
56215
- const raw = await import_promises7.default.readFile(import_node_path52.default.join(liveDir, "manifest.json"), "utf8");
56287
+ const raw = await import_promises7.default.readFile(import_node_path53.default.join(liveDir, "manifest.json"), "utf8");
56216
56288
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
56217
56289
  if (!parsed2.success) {
56218
56290
  throw new UpdateError(
@@ -56245,7 +56317,7 @@ async function updateFromChannel(args, deps) {
56245
56317
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56246
56318
  }
56247
56319
  for (const name of Object.keys(zip.files)) {
56248
- if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56320
+ if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56249
56321
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56250
56322
  }
56251
56323
  }
@@ -56280,16 +56352,16 @@ async function updateFromChannel(args, deps) {
56280
56352
  await import_promises7.default.rm(prevDir, { recursive: true, force: true });
56281
56353
  await import_promises7.default.rename(liveDir, prevDir);
56282
56354
  const stage = await import_promises7.default.mkdtemp(
56283
- import_node_path52.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56355
+ import_node_path53.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56284
56356
  );
56285
56357
  try {
56286
56358
  for (const [name, entry] of Object.entries(zip.files)) {
56287
- const dest = import_node_path52.default.join(stage, name);
56359
+ const dest = import_node_path53.default.join(stage, name);
56288
56360
  if (entry.dir) {
56289
56361
  await import_promises7.default.mkdir(dest, { recursive: true });
56290
56362
  continue;
56291
56363
  }
56292
- await import_promises7.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56364
+ await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56293
56365
  if (name === "manifest.json") {
56294
56366
  const rewritten = { ...parsed.data, id: localExtId };
56295
56367
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56383,7 +56455,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56383
56455
  );
56384
56456
  }
56385
56457
  }
56386
- const manifestPath = import_node_path53.default.join(root, extId, "manifest.json");
56458
+ const manifestPath = import_node_path54.default.join(root, extId, "manifest.json");
56387
56459
  const manifest = await readManifest(root, extId);
56388
56460
  const next = { ...manifest, version: newVersion };
56389
56461
  const tmp = `${manifestPath}.tmp`;
@@ -56391,7 +56463,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56391
56463
  await import_promises8.default.rename(tmp, manifestPath);
56392
56464
  }
56393
56465
  async function readManifest(root, extId) {
56394
- const file = import_node_path53.default.join(root, extId, "manifest.json");
56466
+ const file = import_node_path54.default.join(root, extId, "manifest.json");
56395
56467
  let raw;
56396
56468
  try {
56397
56469
  raw = await import_promises8.default.readFile(file, "utf8");
@@ -56482,7 +56554,7 @@ function buildExtensionHandlers(deps) {
56482
56554
  };
56483
56555
  async function buildSnapshotMeta(extId) {
56484
56556
  const manifest = await readManifest(deps.root, extId);
56485
- const { sha256, buffer } = await bundleExtensionDir(import_node_path53.default.join(deps.root, extId));
56557
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path54.default.join(deps.root, extId));
56486
56558
  return { manifest, contentHash: sha256, buffer };
56487
56559
  }
56488
56560
  const publish = async (frame, _client, ctx) => {
@@ -56663,9 +56735,9 @@ function buildExtensionHandlers(deps) {
56663
56735
  }
56664
56736
 
56665
56737
  // src/app-builder/project-store.ts
56666
- var import_node_fs46 = require("fs");
56738
+ var import_node_fs47 = require("fs");
56667
56739
  var import_node_child_process14 = require("child_process");
56668
- var import_node_path54 = require("path");
56740
+ var import_node_path55 = require("path");
56669
56741
  init_protocol();
56670
56742
  var PROJECTS_DIR = "projects";
56671
56743
  var META_FILE = ".clawd-project.json";
@@ -56679,19 +56751,19 @@ var ProjectStore = class {
56679
56751
  root;
56680
56752
  /** projects/<name>/.clawd-project.json 路径 */
56681
56753
  metaPath(name) {
56682
- return (0, import_node_path54.join)(this.projectsRoot(), name, META_FILE);
56754
+ return (0, import_node_path55.join)(this.projectsRoot(), name, META_FILE);
56683
56755
  }
56684
56756
  /** projects/<name>/ 目录路径(cwd 用) */
56685
56757
  projectDir(name) {
56686
- return (0, import_node_path54.join)(this.projectsRoot(), name);
56758
+ return (0, import_node_path55.join)(this.projectsRoot(), name);
56687
56759
  }
56688
56760
  projectsRoot() {
56689
- return (0, import_node_path54.join)(this.root, PROJECTS_DIR);
56761
+ return (0, import_node_path55.join)(this.root, PROJECTS_DIR);
56690
56762
  }
56691
56763
  async list() {
56692
56764
  let entries;
56693
56765
  try {
56694
- entries = await import_node_fs46.promises.readdir(this.projectsRoot());
56766
+ entries = await import_node_fs47.promises.readdir(this.projectsRoot());
56695
56767
  } catch (err) {
56696
56768
  if (err.code === "ENOENT") return [];
56697
56769
  throw err;
@@ -56699,7 +56771,7 @@ var ProjectStore = class {
56699
56771
  const out = [];
56700
56772
  for (const name of entries) {
56701
56773
  try {
56702
- const raw = await import_node_fs46.promises.readFile(this.metaPath(name), "utf8");
56774
+ const raw = await import_node_fs47.promises.readFile(this.metaPath(name), "utf8");
56703
56775
  const json = JSON.parse(raw);
56704
56776
  let migrated = false;
56705
56777
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -56710,7 +56782,7 @@ var ProjectStore = class {
56710
56782
  if (parsed.success) {
56711
56783
  out.push(parsed.data);
56712
56784
  if (migrated) {
56713
- void import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56785
+ void import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56714
56786
  });
56715
56787
  }
56716
56788
  }
@@ -56754,8 +56826,8 @@ var ProjectStore = class {
56754
56826
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
56755
56827
  }
56756
56828
  const dir = this.projectDir(name);
56757
- await import_node_fs46.promises.mkdir(dir, { recursive: true });
56758
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
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");
56759
56831
  return meta;
56760
56832
  }
56761
56833
  /**
@@ -56798,7 +56870,7 @@ var ProjectStore = class {
56798
56870
  }
56799
56871
  async delete(name) {
56800
56872
  const dir = this.projectDir(name);
56801
- await import_node_fs46.promises.rm(dir, { recursive: true, force: true });
56873
+ await import_node_fs47.promises.rm(dir, { recursive: true, force: true });
56802
56874
  }
56803
56875
  async updatePort(name, newPort) {
56804
56876
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -56814,7 +56886,7 @@ var ProjectStore = class {
56814
56886
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
56815
56887
  }
56816
56888
  const updated = { ...target, port: newPort };
56817
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56889
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56818
56890
  return updated;
56819
56891
  }
56820
56892
  /**
@@ -56831,7 +56903,7 @@ var ProjectStore = class {
56831
56903
  if (!validated.success) {
56832
56904
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
56833
56905
  }
56834
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56906
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56835
56907
  return validated.data;
56836
56908
  }
56837
56909
  /**
@@ -56852,7 +56924,7 @@ var ProjectStore = class {
56852
56924
  if (!validated.success) {
56853
56925
  throw new Error(`invalid publishJob: ${validated.error.message}`);
56854
56926
  }
56855
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56927
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56856
56928
  return validated.data;
56857
56929
  }
56858
56930
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -56867,7 +56939,7 @@ var ProjectStore = class {
56867
56939
  if (!validated.success) {
56868
56940
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
56869
56941
  }
56870
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56942
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56871
56943
  return validated.data;
56872
56944
  }
56873
56945
  };
@@ -56988,8 +57060,8 @@ var PublishJobRegistry = class {
56988
57060
 
56989
57061
  // src/app-builder/publish-job-runner.ts
56990
57062
  var import_node_child_process16 = require("child_process");
56991
- var import_node_fs47 = require("fs");
56992
- var import_node_path55 = require("path");
57063
+ var import_node_fs48 = require("fs");
57064
+ var import_node_path56 = require("path");
56993
57065
 
56994
57066
  // src/app-builder/publish-stage-parser.ts
56995
57067
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -57021,10 +57093,10 @@ async function startPublishJob(deps, args) {
57021
57093
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
57022
57094
  }
57023
57095
  const projDir = projectDir(args.name);
57024
- const logPath = (0, import_node_path55.join)(projDir, ".publish.log");
57096
+ const logPath = (0, import_node_path56.join)(projDir, ".publish.log");
57025
57097
  let logStream = null;
57026
57098
  try {
57027
- logStream = (0, import_node_fs47.createWriteStream)(logPath, { flags: "w" });
57099
+ logStream = (0, import_node_fs48.createWriteStream)(logPath, { flags: "w" });
57028
57100
  } catch {
57029
57101
  logStream = null;
57030
57102
  }
@@ -57281,8 +57353,8 @@ async function recoverInterruptedJobs(deps) {
57281
57353
 
57282
57354
  // src/handlers/app-builder.ts
57283
57355
  init_protocol();
57284
- var import_node_path56 = require("path");
57285
- var import_node_fs48 = require("fs");
57356
+ var import_node_path57 = require("path");
57357
+ var import_node_fs49 = require("fs");
57286
57358
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57287
57359
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57288
57360
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57363,7 +57435,7 @@ function buildAppBuilderHandlers(deps) {
57363
57435
  async function listAllUsersProjects() {
57364
57436
  if (!deps.usersRoot || !deps.getStore) return [];
57365
57437
  const getStore = deps.getStore;
57366
- const userIds = await import_node_fs48.promises.readdir(deps.usersRoot).catch(() => []);
57438
+ const userIds = await import_node_fs49.promises.readdir(deps.usersRoot).catch(() => []);
57367
57439
  const perUser = await Promise.all(
57368
57440
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57369
57441
  );
@@ -57439,8 +57511,8 @@ function buildAppBuilderHandlers(deps) {
57439
57511
  const project = await userStore.create(f.name, reservedPorts);
57440
57512
  try {
57441
57513
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
57442
- const templateSrcDir = (0, import_node_path56.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57443
- const scaffoldScript = (0, import_node_path56.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
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");
57444
57516
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
57445
57517
  deps.logger?.info("app-builder.scaffold.done", {
57446
57518
  name: project.name,
@@ -57661,7 +57733,7 @@ function buildAppBuilderHandlers(deps) {
57661
57733
  await userStore.clearPublishJob(args.name);
57662
57734
  }
57663
57735
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
57664
- const scriptPath = (0, import_node_path56.join)(deps.deployKitRoot, "scripts", "publish.sh");
57736
+ const scriptPath = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "publish.sh");
57665
57737
  deps.logger?.info("app-builder.publish.start", {
57666
57738
  name: args.name,
57667
57739
  sessionId: boundSession.sessionId,
@@ -57830,7 +57902,7 @@ function buildVisitorHandlers(deps) {
57830
57902
 
57831
57903
  // src/extension/registry.ts
57832
57904
  var import_promises9 = __toESM(require("fs/promises"), 1);
57833
- var import_node_path57 = __toESM(require("path"), 1);
57905
+ var import_node_path58 = __toESM(require("path"), 1);
57834
57906
  init_src();
57835
57907
  async function loadAll(root) {
57836
57908
  let entries;
@@ -57844,13 +57916,13 @@ async function loadAll(root) {
57844
57916
  for (const ent of entries) {
57845
57917
  if (!ent.isDirectory()) continue;
57846
57918
  if (ent.name.startsWith(".")) continue;
57847
- records.push(await loadOne(import_node_path57.default.join(root, ent.name), ent.name));
57919
+ records.push(await loadOne(import_node_path58.default.join(root, ent.name), ent.name));
57848
57920
  }
57849
57921
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
57850
57922
  return records;
57851
57923
  }
57852
57924
  async function loadOne(dir, dirName) {
57853
- const manifestPath = import_node_path57.default.join(dir, "manifest.json");
57925
+ const manifestPath = import_node_path58.default.join(dir, "manifest.json");
57854
57926
  let raw;
57855
57927
  try {
57856
57928
  raw = await import_promises9.default.readFile(manifestPath, "utf8");
@@ -57895,7 +57967,7 @@ async function loadOne(dir, dirName) {
57895
57967
 
57896
57968
  // src/extension/uninstall.ts
57897
57969
  var import_promises10 = __toESM(require("fs/promises"), 1);
57898
- var import_node_path58 = __toESM(require("path"), 1);
57970
+ var import_node_path59 = __toESM(require("path"), 1);
57899
57971
  var UninstallError = class extends Error {
57900
57972
  constructor(code, message) {
57901
57973
  super(message);
@@ -57904,7 +57976,7 @@ var UninstallError = class extends Error {
57904
57976
  code;
57905
57977
  };
57906
57978
  async function uninstall(deps) {
57907
- const dir = import_node_path58.default.join(deps.root, deps.extId);
57979
+ const dir = import_node_path59.default.join(deps.root, deps.extId);
57908
57980
  try {
57909
57981
  await import_promises10.default.access(dir);
57910
57982
  } catch {
@@ -58488,7 +58560,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58488
58560
 
58489
58561
  // src/extension/runtime.ts
58490
58562
  var import_node_child_process18 = require("child_process");
58491
- var import_node_path59 = __toESM(require("path"), 1);
58563
+ var import_node_path60 = __toESM(require("path"), 1);
58492
58564
  var import_promises11 = require("timers/promises");
58493
58565
  init_src();
58494
58566
 
@@ -58590,7 +58662,7 @@ var Runtime = class {
58590
58662
  /\$CLAWOS_EXT_PORT/g,
58591
58663
  String(port)
58592
58664
  );
58593
- const dir = import_node_path59.default.join(this.root, extId);
58665
+ const dir = import_node_path60.default.join(this.root, extId);
58594
58666
  const env = {
58595
58667
  ...process.env,
58596
58668
  CLAWOS_EXT_PORT: String(port),
@@ -58702,7 +58774,7 @@ ${handle.stderrTail}`
58702
58774
 
58703
58775
  // src/extension/published-channels.ts
58704
58776
  var import_promises12 = __toESM(require("fs/promises"), 1);
58705
- var import_node_path60 = __toESM(require("path"), 1);
58777
+ var import_node_path61 = __toESM(require("path"), 1);
58706
58778
  init_src();
58707
58779
  init_zod();
58708
58780
  var PublishedChannelsError = class extends Error {
@@ -58802,7 +58874,7 @@ var PublishedChannelStore = class {
58802
58874
  )
58803
58875
  };
58804
58876
  const tmp = `${this.filePath}.tmp`;
58805
- await import_promises12.default.mkdir(import_node_path60.default.dirname(this.filePath), { recursive: true });
58877
+ await import_promises12.default.mkdir(import_node_path61.default.dirname(this.filePath), { recursive: true });
58806
58878
  await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
58807
58879
  await import_promises12.default.rename(tmp, this.filePath);
58808
58880
  }
@@ -58810,7 +58882,7 @@ var PublishedChannelStore = class {
58810
58882
 
58811
58883
  // src/extension/bundle-cache.ts
58812
58884
  var import_promises13 = __toESM(require("fs/promises"), 1);
58813
- var import_node_path61 = __toESM(require("path"), 1);
58885
+ var import_node_path62 = __toESM(require("path"), 1);
58814
58886
  var BundleCache = class {
58815
58887
  constructor(rootDir) {
58816
58888
  this.rootDir = rootDir;
@@ -58819,14 +58891,14 @@ var BundleCache = class {
58819
58891
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
58820
58892
  async write(snapshotHash, buffer) {
58821
58893
  await import_promises13.default.mkdir(this.rootDir, { recursive: true });
58822
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58894
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58823
58895
  const tmp = `${file}.tmp`;
58824
58896
  await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
58825
58897
  await import_promises13.default.rename(tmp, file);
58826
58898
  }
58827
58899
  /** Returns the bundle bytes, or null when the file doesn't exist. */
58828
58900
  async read(snapshotHash) {
58829
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58901
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58830
58902
  try {
58831
58903
  return await import_promises13.default.readFile(file);
58832
58904
  } catch (e) {
@@ -58836,7 +58908,7 @@ var BundleCache = class {
58836
58908
  }
58837
58909
  /** Idempotent — missing file is not an error. */
58838
58910
  async delete(snapshotHash) {
58839
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58911
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58840
58912
  await import_promises13.default.rm(file, { force: true });
58841
58913
  }
58842
58914
  };
@@ -58861,16 +58933,16 @@ async function startDaemon(config) {
58861
58933
  });
58862
58934
  const logger = createLogger({
58863
58935
  level: config.logLevel,
58864
- file: import_node_path62.default.join(config.dataDir, "clawd.log"),
58936
+ file: import_node_path63.default.join(config.dataDir, "clawd.log"),
58865
58937
  logClient
58866
58938
  });
58867
58939
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
58868
58940
  const screenIdleProbeLogger = createFileOnlyLogger({
58869
- file: import_node_path62.default.join(config.dataDir, "screen-idle-probe.log"),
58941
+ file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log"),
58870
58942
  level: "debug"
58871
58943
  });
58872
58944
  logger.info("screen-idle probe logger enabled", {
58873
- file: import_node_path62.default.join(config.dataDir, "screen-idle-probe.log")
58945
+ file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log")
58874
58946
  });
58875
58947
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
58876
58948
  const pre = stateMgr.preflight();
@@ -59008,8 +59080,8 @@ async function startDaemon(config) {
59008
59080
  const agents = new AgentsScanner();
59009
59081
  const history = new ClaudeHistoryReader();
59010
59082
  let transport = null;
59011
- const personaStore = new PersonaStore(import_node_path62.default.join(config.dataDir, "personas"));
59012
- const usersRoot = import_node_path62.default.join(config.dataDir, "users");
59083
+ const personaStore = new PersonaStore(import_node_path63.default.join(config.dataDir, "personas"));
59084
+ const usersRoot = import_node_path63.default.join(config.dataDir, "users");
59013
59085
  const defaultsRoot = findDefaultsRoot(logger);
59014
59086
  if (defaultsRoot) {
59015
59087
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -59029,17 +59101,17 @@ async function startDaemon(config) {
59029
59101
  migrateCodexSandbox({ store: personaStore, logger });
59030
59102
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
59031
59103
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
59032
- const here = typeof __dirname === "string" ? __dirname : import_node_path62.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59104
+ const here = typeof __dirname === "string" ? __dirname : import_node_path63.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59033
59105
  const dispatchServerCandidates = [
59034
- import_node_path62.default.join(here, "dispatch", "mcp-server.cjs"),
59106
+ import_node_path63.default.join(here, "dispatch", "mcp-server.cjs"),
59035
59107
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
59036
- import_node_path62.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59108
+ import_node_path63.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59037
59109
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59038
59110
  ];
59039
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59111
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59040
59112
  let dispatchMcpConfigPath2;
59041
59113
  if (dispatchServerScriptPath) {
59042
- const dispatchLogPath = import_node_path62.default.join(config.dataDir, "dispatch-mcp-server.log");
59114
+ const dispatchLogPath = import_node_path63.default.join(config.dataDir, "dispatch-mcp-server.log");
59043
59115
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
59044
59116
  dataDir: config.dataDir,
59045
59117
  serverScriptPath: dispatchServerScriptPath,
@@ -59056,15 +59128,15 @@ async function startDaemon(config) {
59056
59128
  });
59057
59129
  }
59058
59130
  const ticketServerCandidates = [
59059
- import_node_path62.default.join(here, "ticket", "mcp-server.cjs"),
59060
- import_node_path62.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59131
+ import_node_path63.default.join(here, "ticket", "mcp-server.cjs"),
59132
+ import_node_path63.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59061
59133
  ];
59062
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59134
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59063
59135
  const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
59064
59136
  const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
59065
59137
  let ticketMcpConfigPath2;
59066
59138
  if (ticketServerScriptPath && ticketOwnerUnionId) {
59067
- const ticketLogPath = import_node_path62.default.join(config.dataDir, "ticket-mcp-server.log");
59139
+ const ticketLogPath = import_node_path63.default.join(config.dataDir, "ticket-mcp-server.log");
59068
59140
  ticketMcpConfigPath2 = writeTicketMcpConfig({
59069
59141
  dataDir: config.dataDir,
59070
59142
  serverScriptPath: ticketServerScriptPath,
@@ -59085,13 +59157,13 @@ async function startDaemon(config) {
59085
59157
  });
59086
59158
  }
59087
59159
  const shiftServerCandidates = [
59088
- import_node_path62.default.join(here, "shift", "mcp-server.cjs"),
59089
- import_node_path62.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59160
+ import_node_path63.default.join(here, "shift", "mcp-server.cjs"),
59161
+ import_node_path63.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59090
59162
  ];
59091
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59163
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59092
59164
  let shiftMcpConfigPath2;
59093
59165
  if (shiftServerScriptPath) {
59094
- const shiftLogPath = import_node_path62.default.join(config.dataDir, "shift-mcp-server.log");
59166
+ const shiftLogPath = import_node_path63.default.join(config.dataDir, "shift-mcp-server.log");
59095
59167
  shiftMcpConfigPath2 = await writeShiftMcpConfig({
59096
59168
  dataDir: config.dataDir,
59097
59169
  serverScriptPath: shiftServerScriptPath,
@@ -59109,13 +59181,13 @@ async function startDaemon(config) {
59109
59181
  );
59110
59182
  }
59111
59183
  const inboxServerCandidates = [
59112
- import_node_path62.default.join(here, "inbox", "mcp-server.cjs"),
59113
- import_node_path62.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59184
+ import_node_path63.default.join(here, "inbox", "mcp-server.cjs"),
59185
+ import_node_path63.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59114
59186
  ];
59115
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59187
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59116
59188
  let inboxMcpConfigPath2;
59117
59189
  if (inboxServerScriptPath) {
59118
- const inboxLogPath = import_node_path62.default.join(config.dataDir, "inbox-mcp-server.log");
59190
+ const inboxLogPath = import_node_path63.default.join(config.dataDir, "inbox-mcp-server.log");
59119
59191
  inboxMcpConfigPath2 = await writeInboxMcpConfig({
59120
59192
  dataDir: config.dataDir,
59121
59193
  serverScriptPath: inboxServerScriptPath,
@@ -59133,7 +59205,7 @@ async function startDaemon(config) {
59133
59205
  );
59134
59206
  }
59135
59207
  const shiftStore = createShiftStore({
59136
- filePath: import_node_path62.default.join(config.dataDir, "shift.json"),
59208
+ filePath: import_node_path63.default.join(config.dataDir, "shift.json"),
59137
59209
  ownerIdProvider: () => ownerPrincipalId,
59138
59210
  now: () => Date.now()
59139
59211
  });
@@ -59155,7 +59227,7 @@ async function startDaemon(config) {
59155
59227
  getAdapter,
59156
59228
  historyReader: history,
59157
59229
  dataDir: config.dataDir,
59158
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59230
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59159
59231
  usersRoot,
59160
59232
  personaStore,
59161
59233
  ownerDisplayName,
@@ -59198,10 +59270,10 @@ async function startDaemon(config) {
59198
59270
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
59199
59271
  attachmentGroup: {
59200
59272
  onFileEdit: (input) => {
59201
- const absPath = import_node_path62.default.isAbsolute(input.relPath) ? input.relPath : import_node_path62.default.join(input.cwd, input.relPath);
59273
+ const absPath = import_node_path63.default.isAbsolute(input.relPath) ? input.relPath : import_node_path63.default.join(input.cwd, input.relPath);
59202
59274
  let size = 0;
59203
59275
  try {
59204
- size = import_node_fs49.default.statSync(absPath).size;
59276
+ size = import_node_fs50.default.statSync(absPath).size;
59205
59277
  } catch (err) {
59206
59278
  logger.warn("attachment.onFileEdit stat failed", {
59207
59279
  sessionId: input.sessionId,
@@ -59400,11 +59472,11 @@ async function startDaemon(config) {
59400
59472
  // 'persona/<pid>/owner',default 走 'default'。
59401
59473
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
59402
59474
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
59403
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59475
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59404
59476
  usersRoot
59405
59477
  },
59406
59478
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
59407
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59479
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59408
59480
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
59409
59481
  usersRoot,
59410
59482
  // capability:list / delete handler 依赖
@@ -59426,7 +59498,7 @@ async function startDaemon(config) {
59426
59498
  contactStore,
59427
59499
  // <dataDir>/sshd 绝对路径 —— contact-ssh handlers 用它拼 authorized_keys / keys/ 子路径
59428
59500
  // Task 10 会加 SshdManager 起 sshd;handlers wire 提前挂 sshdDir 让 typecheck 过
59429
- sshdDir: import_node_path62.default.join(config.dataDir, "sshd"),
59501
+ sshdDir: import_node_path63.default.join(config.dataDir, "sshd"),
59430
59502
  contactSshLog: sshLog,
59431
59503
  // inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
59432
59504
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
@@ -59517,11 +59589,11 @@ async function startDaemon(config) {
59517
59589
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
59518
59590
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
59519
59591
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
59520
- appBuilderPersonaRoot: import_node_path62.default.join(config.dataDir, "personas", "persona-app-builder"),
59592
+ appBuilderPersonaRoot: import_node_path63.default.join(config.dataDir, "personas", "persona-app-builder"),
59521
59593
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
59522
- deployKitRoot: import_node_path62.default.join(config.dataDir, "deploy-kit"),
59594
+ deployKitRoot: import_node_path63.default.join(config.dataDir, "deploy-kit"),
59523
59595
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
59524
- resolvePersonaRoot: (personaId) => import_node_path62.default.join(config.dataDir, "personas", personaId),
59596
+ resolvePersonaRoot: (personaId) => import_node_path63.default.join(config.dataDir, "personas", personaId),
59525
59597
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
59526
59598
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
59527
59599
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -59564,7 +59636,7 @@ async function startDaemon(config) {
59564
59636
  }
59565
59637
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
59566
59638
  if (sourceFile && sourceFile.toolSessionId) {
59567
- sourceJsonlPath = import_node_path62.default.join(
59639
+ sourceJsonlPath = import_node_path63.default.join(
59568
59640
  import_node_os21.default.homedir(),
59569
59641
  ".claude",
59570
59642
  "projects",
@@ -59894,8 +59966,8 @@ async function startDaemon(config) {
59894
59966
  const lines = [
59895
59967
  `Tunnel: ${r.url}`,
59896
59968
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
59897
- `Frpc config: ${import_node_path62.default.join(config.dataDir, "frpc.toml")}`,
59898
- `Frpc log: ${import_node_path62.default.join(config.dataDir, "frpc.log")}`
59969
+ `Frpc config: ${import_node_path63.default.join(config.dataDir, "frpc.toml")}`,
59970
+ `Frpc log: ${import_node_path63.default.join(config.dataDir, "frpc.log")}`
59899
59971
  ];
59900
59972
  const width = Math.max(...lines.map((l) => l.length));
59901
59973
  const bar = "\u2550".repeat(width + 4);
@@ -59908,8 +59980,8 @@ ${bar}
59908
59980
 
59909
59981
  `);
59910
59982
  try {
59911
- const connectPath = import_node_path62.default.join(config.dataDir, "connect.txt");
59912
- import_node_fs49.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
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 });
59913
59985
  } catch {
59914
59986
  }
59915
59987
  } catch (err) {
@@ -59943,7 +60015,7 @@ ${bar}
59943
60015
  });
59944
60016
  try {
59945
60017
  await sshdMgr.start();
59946
- rebuildAuthorizedKeys(contactStore, import_node_path62.default.join(config.dataDir, "sshd"));
60018
+ rebuildAuthorizedKeys(contactStore, import_node_path63.default.join(config.dataDir, "sshd"));
59947
60019
  logger.info("sshd: contact-ssh sandbox ready", { port: config.sshdPort });
59948
60020
  } catch (err) {
59949
60021
  logger.warn("sshd start failed; contact SSH grant will not work until fixed", {
@@ -60011,9 +60083,9 @@ ${bar}
60011
60083
  };
60012
60084
  }
60013
60085
  function migrateDropPersonsDir(dataDir) {
60014
- const dir = import_node_path62.default.join(dataDir, "persons");
60086
+ const dir = import_node_path63.default.join(dataDir, "persons");
60015
60087
  try {
60016
- import_node_fs49.default.rmSync(dir, { recursive: true, force: true });
60088
+ import_node_fs50.default.rmSync(dir, { recursive: true, force: true });
60017
60089
  } catch {
60018
60090
  }
60019
60091
  }