@clawos-dev/clawd 0.2.203-beta.405.1ab6ff3 → 0.2.203-beta.407.bb42013

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 -370
  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
@@ -41735,7 +41812,7 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41735
41812
  fsv.denyWrite = unionArr((fsv.denyWrite ?? []).filter((p2) => p2 !== "~/"), [spawnCwd]);
41736
41813
  fsv.allowRead = unionArr(fsv.allowRead, [userWorkDir]);
41737
41814
  fsv.allowWrite = unionArr(fsv.allowWrite, [userWorkDir]);
41738
- fsv.allowRead = unionArr(fsv.allowRead, ["~/.clawd/contact-ssh-keys", "~/.clawd/contacts.json"]);
41815
+ fsv.allowRead = unionArr(fsv.allowRead, ["~/.clawd/contact-ssh-keys", "~/.clawd/bin"]);
41739
41816
  return s;
41740
41817
  }
41741
41818
 
@@ -41885,12 +41962,14 @@ var CONTACT_SSH_SYSTEM_PROMPT_HINT = `## \u8DE8\u8BBE\u5907\u6587\u4EF6\u8BBF\u9
41885
41962
  \uFF08\u6BCF\u4E2A \`<deviceId>.ed25519\` \u5C31\u662F\u4E00\u628A privkey\uFF0C\u53BB\u6389\u540E\u7F00\u5C31\u662F deviceId\uFF09
41886
41963
  2. \u7528 SSH \u62E8\u53F7\uFF08\u628A \`<A>\` \u6362\u6210\u5B9E\u9645 deviceId\uFF09\uFF1A
41887
41964
  \`\`\`bash
41888
- ssh -o ProxyCommand='clawd ssh-relay <A>' \\
41965
+ ssh -o ProxyCommand='~/.clawd/bin/clawd ssh-relay <A>' \\
41889
41966
  -i ~/.clawd/contact-ssh-keys/<A>.ed25519 \\
41890
41967
  -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \\
41891
41968
  $USER@127.0.0.1 <command>
41892
41969
  # \u4F8B\u5982\uFF1A... $USER@127.0.0.1 cat /Users/xxx/some/file.md
41893
41970
  # ... $USER@127.0.0.1 ls -la /Users/xxx/proj
41971
+ # \u8BF4\u660E\uFF1A\`~/.clawd/bin/clawd\` \u662F daemon \u542F\u52A8\u65F6 seed \u7684 shim\uFF0C\u786C\u7F16\u7801\u5F53\u524D daemon \u7684
41972
+ # 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
41894
41973
  \`\`\`
41895
41974
 
41896
41975
  **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
@@ -46560,8 +46639,8 @@ function turnStartInput(text) {
46560
46639
  const items = [];
46561
46640
  let leftover = text;
46562
46641
  for (const m2 of text.matchAll(SKILL_RE)) {
46563
- const [marker, name, path76] = m2;
46564
- items.push({ type: "skill", name, path: path76 });
46642
+ const [marker, name, path77] = m2;
46643
+ items.push({ type: "skill", name, path: path77 });
46565
46644
  leftover = leftover.replace(marker, "");
46566
46645
  }
46567
46646
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -49015,13 +49094,13 @@ function mapSkillsListResponse(res) {
49015
49094
  const r = s ?? {};
49016
49095
  const name = str3(r.name);
49017
49096
  if (!name) continue;
49018
- const path76 = str3(r.path);
49097
+ const path77 = str3(r.path);
49019
49098
  const description = str3(r.description);
49020
49099
  const isPlugin = name.includes(":");
49021
49100
  out.push({
49022
49101
  name,
49023
49102
  source: isPlugin ? "plugin" : "project",
49024
- ...path76 ? { path: path76 } : {},
49103
+ ...path77 ? { path: path77 } : {},
49025
49104
  ...description ? { description } : {},
49026
49105
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49027
49106
  });
@@ -52993,8 +53072,8 @@ async function waitForFrpcReady(proc, timeoutMs) {
52993
53072
  }
52994
53073
 
52995
53074
  // src/sshd/sshd-manager.ts
52996
- var import_node_fs36 = __toESM(require("fs"), 1);
52997
- var import_node_path37 = __toESM(require("path"), 1);
53075
+ var import_node_fs37 = __toESM(require("fs"), 1);
53076
+ var import_node_path38 = __toESM(require("path"), 1);
52998
53077
  var import_node_child_process11 = require("child_process");
52999
53078
 
53000
53079
  // src/sshd/sshd-config.ts
@@ -53277,11 +53356,35 @@ function ensureJailScript(dataDir) {
53277
53356
  return target;
53278
53357
  }
53279
53358
 
53359
+ // src/sshd/clawd-shim.ts
53360
+ var import_node_fs36 = __toESM(require("fs"), 1);
53361
+ var import_node_path37 = __toESM(require("path"), 1);
53362
+ function shellQuote(s) {
53363
+ return `'${s.replace(/'/g, "'\\''")}'`;
53364
+ }
53365
+ function buildClawdShim(execPath, cliPath) {
53366
+ return `#!/usr/bin/env bash
53367
+ # clawd shim (managed by clawd; do not edit)
53368
+ #
53369
+ # \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
53370
+ # guest CC \u7528 SSH ProxyCommand \u8D70 ~/.clawd/bin/clawd ssh-relay \u65F6\u4F1A\u547D\u4E2D\u672C shim\uFF0C\u4FDD\u8BC1
53371
+ # relay \u4E8C\u8FDB\u5236\u8DDF\u5F53\u524D\u8DD1\u7740\u7684 daemon \u540C\u6E90\u540C\u7248\u672C\u3002
53372
+ exec ${shellQuote(execPath)} ${shellQuote(cliPath)} "$@"
53373
+ `;
53374
+ }
53375
+ function ensureClawdShim(dataDir, execPath, cliPath) {
53376
+ const binDir = import_node_path37.default.join(dataDir, "bin");
53377
+ import_node_fs36.default.mkdirSync(binDir, { recursive: true, mode: 493 });
53378
+ const target = import_node_path37.default.join(binDir, "clawd");
53379
+ import_node_fs36.default.writeFileSync(target, buildClawdShim(execPath, cliPath), { mode: 493 });
53380
+ return target;
53381
+ }
53382
+
53280
53383
  // src/sshd/sshd-manager.ts
53281
53384
  var SshdManager = class {
53282
53385
  constructor(deps) {
53283
53386
  this.deps = deps;
53284
- this.sshdDir = import_node_path37.default.join(deps.dataDir, "sshd");
53387
+ this.sshdDir = import_node_path38.default.join(deps.dataDir, "sshd");
53285
53388
  this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
53286
53389
  }
53287
53390
  deps;
@@ -53300,31 +53403,32 @@ var SshdManager = class {
53300
53403
  ownPid: process.pid,
53301
53404
  logger
53302
53405
  });
53303
- import_node_fs36.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53304
- import_node_fs36.default.mkdirSync(import_node_path37.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53406
+ import_node_fs37.default.mkdirSync(this.sshdDir, { recursive: true, mode: 448 });
53407
+ import_node_fs37.default.mkdirSync(import_node_path38.default.join(this.sshdDir, "authorized_keys.d"), { recursive: true, mode: 448 });
53305
53408
  ensureJailScript(this.deps.dataDir);
53306
- const hostKeyPath = import_node_path37.default.join(this.sshdDir, "host_key");
53307
- if (!import_node_fs36.default.existsSync(hostKeyPath)) {
53409
+ ensureClawdShim(this.deps.dataDir, process.execPath, process.argv[1] ?? "");
53410
+ const hostKeyPath = import_node_path38.default.join(this.sshdDir, "host_key");
53411
+ if (!import_node_fs37.default.existsSync(hostKeyPath)) {
53308
53412
  await this.generateHostKey(hostKeyPath);
53309
53413
  }
53310
- const akFile = import_node_path37.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53311
- if (!import_node_fs36.default.existsSync(akFile)) {
53312
- import_node_fs36.default.writeFileSync(akFile, "", { mode: 384 });
53414
+ const akFile = import_node_path38.default.join(this.sshdDir, "authorized_keys.d", "clawd-contacts");
53415
+ if (!import_node_fs37.default.existsSync(akFile)) {
53416
+ import_node_fs37.default.writeFileSync(akFile, "", { mode: 384 });
53313
53417
  }
53314
- const configPath = import_node_path37.default.join(this.sshdDir, "sshd_config");
53418
+ const configPath = import_node_path38.default.join(this.sshdDir, "sshd_config");
53315
53419
  const config = buildSshdConfig({
53316
53420
  listenAddress: "127.0.0.1",
53317
53421
  port: this.deps.port,
53318
53422
  hostKeyPath,
53319
53423
  authorizedKeysFile: akFile,
53320
- pidFilePath: import_node_path37.default.join(this.sshdDir, "sshd.pid")
53424
+ pidFilePath: import_node_path38.default.join(this.sshdDir, "sshd.pid")
53321
53425
  });
53322
- import_node_fs36.default.writeFileSync(configPath, config, { mode: 384 });
53426
+ import_node_fs37.default.writeFileSync(configPath, config, { mode: 384 });
53323
53427
  const sshdBin = this.deps.sshdBin ?? "/usr/sbin/sshd";
53324
53428
  const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(sshdBin, ["-D", "-e", "-f", configPath], {
53325
53429
  stdio: ["ignore", "pipe", "pipe"]
53326
53430
  });
53327
- const logStream = import_node_fs36.default.createWriteStream(import_node_path37.default.join(this.sshdDir, "sshd.log"), {
53431
+ const logStream = import_node_fs37.default.createWriteStream(import_node_path38.default.join(this.sshdDir, "sshd.log"), {
53328
53432
  flags: "a",
53329
53433
  mode: 384
53330
53434
  });
@@ -53417,7 +53521,7 @@ ${tail}` : ready.error;
53417
53521
  p2.on("error", reject);
53418
53522
  });
53419
53523
  try {
53420
- import_node_fs36.default.chmodSync(hostKeyPath, 384);
53524
+ import_node_fs37.default.chmodSync(hostKeyPath, 384);
53421
53525
  } catch {
53422
53526
  }
53423
53527
  }
@@ -53460,17 +53564,17 @@ async function waitForSshdReady(proc, timeoutMs) {
53460
53564
  }
53461
53565
 
53462
53566
  // src/sshd/authorized-keys.ts
53463
- var import_node_fs37 = __toESM(require("fs"), 1);
53464
- var import_node_path38 = __toESM(require("path"), 1);
53567
+ var import_node_fs38 = __toESM(require("fs"), 1);
53568
+ var import_node_path39 = __toESM(require("path"), 1);
53465
53569
  var JAIL_BIN_PATH_ENV = "CLAWD_JAIL_BIN_PATH";
53466
53570
  var AUTHORIZED_KEYS_FILE = "clawd-contacts";
53467
53571
  function jailBinPath() {
53468
- return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path38.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53572
+ return process.env[JAIL_BIN_PATH_ENV] ?? import_node_path39.default.join(process.env.HOME ?? "", ".clawd", "bin", "clawd-ssh-jail");
53469
53573
  }
53470
53574
  function rebuildAuthorizedKeys(store, sshdDir) {
53471
- const akDir = import_node_path38.default.join(sshdDir, "authorized_keys.d");
53472
- const target = import_node_path38.default.join(akDir, AUTHORIZED_KEYS_FILE);
53473
- import_node_fs37.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53575
+ const akDir = import_node_path39.default.join(sshdDir, "authorized_keys.d");
53576
+ const target = import_node_path39.default.join(akDir, AUTHORIZED_KEYS_FILE);
53577
+ import_node_fs38.default.mkdirSync(akDir, { recursive: true, mode: 448 });
53474
53578
  const lines = ["# managed by clawd; do not edit", ""];
53475
53579
  for (const c of store.list()) {
53476
53580
  if (!c.sshAllowed) continue;
@@ -53484,66 +53588,28 @@ function rebuildAuthorizedKeys(store, sshdDir) {
53484
53588
  }
53485
53589
  const body = lines.join("\n") + "\n";
53486
53590
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
53487
- import_node_fs37.default.writeFileSync(tmp, body, { mode: 384 });
53488
- import_node_fs37.default.renameSync(tmp, target);
53591
+ import_node_fs38.default.writeFileSync(tmp, body, { mode: 384 });
53592
+ import_node_fs38.default.renameSync(tmp, target);
53489
53593
  }
53490
53594
  function readIssuedPubkey(sshdDir, deviceId) {
53491
53595
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53492
- const p2 = import_node_path38.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53596
+ const p2 = import_node_path39.default.join(sshdDir, "keys", `${safeId}.ed25519.pub`);
53493
53597
  try {
53494
- return import_node_fs37.default.readFileSync(p2, "utf8");
53598
+ return import_node_fs38.default.readFileSync(p2, "utf8");
53495
53599
  } catch {
53496
53600
  return null;
53497
53601
  }
53498
53602
  }
53499
53603
 
53500
53604
  // src/sshd/contact-key-puller.ts
53501
- var import_node_fs39 = __toESM(require("fs"), 1);
53502
- var import_node_path40 = __toESM(require("path"), 1);
53605
+ var import_node_fs40 = __toESM(require("fs"), 1);
53606
+ var import_node_path41 = __toESM(require("path"), 1);
53503
53607
  init_peer_forward();
53504
-
53505
- // src/sshd/contact-ssh-log.ts
53506
- var import_node_fs38 = __toESM(require("fs"), 1);
53507
- var import_node_path39 = __toESM(require("path"), 1);
53508
- function createContactSshLog(dataDir) {
53509
- const file = import_node_path39.default.join(dataDir, "contact-ssh.log");
53510
- function append(level, tag, message, meta) {
53511
- const time = (/* @__PURE__ */ new Date()).toISOString();
53512
- let line = `[${time}] [${level}] [${tag}] ${message}`;
53513
- if (meta && Object.keys(meta).length > 0) {
53514
- try {
53515
- line += " " + JSON.stringify(meta);
53516
- } catch {
53517
- line += " [meta-serialize-failed]";
53518
- }
53519
- }
53520
- line += "\n";
53521
- try {
53522
- import_node_fs38.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
53523
- import_node_fs38.default.appendFileSync(file, line, { mode: 384 });
53524
- } catch {
53525
- }
53526
- }
53527
- return {
53528
- info: (tag, message, meta) => append("INFO", tag, message, meta),
53529
- warn: (tag, message, meta) => append("WARN", tag, message, meta),
53530
- error: (tag, message, meta) => append("ERROR", tag, message, meta)
53531
- };
53532
- }
53533
- var nullContactSshLog = {
53534
- info: () => {
53535
- },
53536
- warn: () => {
53537
- },
53538
- error: () => {
53539
- }
53540
- };
53541
-
53542
- // src/sshd/contact-key-puller.ts
53608
+ init_contact_ssh_log();
53543
53609
  var CONTACT_KEYS_DIR = "contact-ssh-keys";
53544
53610
  function safeContactKeyPath(dataDir, deviceId) {
53545
53611
  const safeId = deviceId.replace(/[\/\\]/g, "_");
53546
- return import_node_path40.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53612
+ return import_node_path41.default.join(dataDir, CONTACT_KEYS_DIR, `${safeId}.ed25519`);
53547
53613
  }
53548
53614
  async function pullContactSshKeyOnce(deps) {
53549
53615
  const forward = deps.forwardImpl ?? ((c) => forwardContactSshKeyIssueToPeer({
@@ -53609,12 +53675,12 @@ async function pullContactSshKeyOnce(deps) {
53609
53675
  }
53610
53676
  function writeKeyFile(dataDir, deviceId, pem) {
53611
53677
  const p2 = safeContactKeyPath(dataDir, deviceId);
53612
- import_node_fs39.default.mkdirSync(import_node_path40.default.dirname(p2), { recursive: true, mode: 448 });
53613
- import_node_fs39.default.writeFileSync(p2, pem, { mode: 384 });
53678
+ import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(p2), { recursive: true, mode: 448 });
53679
+ import_node_fs40.default.writeFileSync(p2, pem, { mode: 384 });
53614
53680
  }
53615
53681
  function removeKeyFile(dataDir, deviceId) {
53616
53682
  try {
53617
- import_node_fs39.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53683
+ import_node_fs40.default.unlinkSync(safeContactKeyPath(dataDir, deviceId));
53618
53684
  return true;
53619
53685
  } catch {
53620
53686
  return false;
@@ -53651,6 +53717,7 @@ var ContactKeyPuller = class {
53651
53717
 
53652
53718
  // src/sshd/ssh-tunnel-relay.ts
53653
53719
  var import_node_net2 = __toESM(require("net"), 1);
53720
+ init_contact_ssh_log();
53654
53721
  async function handleSshTunnelUpgrade(req, socket, head, deps) {
53655
53722
  const sshLog = deps.sshLog ?? nullContactSshLog;
53656
53723
  const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
@@ -53758,29 +53825,32 @@ function pumpWsToSshd(ws, deps, clientAddr) {
53758
53825
  });
53759
53826
  }
53760
53827
 
53828
+ // src/index.ts
53829
+ init_contact_ssh_log();
53830
+
53761
53831
  // src/tunnel/device-key.ts
53762
53832
  var import_node_os14 = __toESM(require("os"), 1);
53763
- var import_node_path41 = __toESM(require("path"), 1);
53833
+ var import_node_path42 = __toESM(require("path"), 1);
53764
53834
  var import_node_crypto11 = __toESM(require("crypto"), 1);
53765
53835
  var DERIVE_SALT = "clawd-tunnel-device-v1";
53766
53836
  function deriveStableDeviceKey(opts = {}) {
53767
53837
  const hostname = opts.hostname ?? import_node_os14.default.hostname();
53768
53838
  const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
53769
53839
  const home = opts.home ?? import_node_os14.default.homedir();
53770
- const defaultDataDir = import_node_path41.default.resolve(import_node_path41.default.join(home, ".clawd"));
53771
- const normalizedDataDir = opts.dataDir ? import_node_path41.default.resolve(opts.dataDir) : null;
53840
+ const defaultDataDir = import_node_path42.default.resolve(import_node_path42.default.join(home, ".clawd"));
53841
+ const normalizedDataDir = opts.dataDir ? import_node_path42.default.resolve(opts.dataDir) : null;
53772
53842
  const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
53773
53843
  const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
53774
53844
  return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
53775
53845
  }
53776
53846
 
53777
53847
  // src/auth-store.ts
53778
- var import_node_fs40 = __toESM(require("fs"), 1);
53779
- var import_node_path42 = __toESM(require("path"), 1);
53848
+ var import_node_fs41 = __toESM(require("fs"), 1);
53849
+ var import_node_path43 = __toESM(require("path"), 1);
53780
53850
  var import_node_crypto12 = __toESM(require("crypto"), 1);
53781
53851
  var AUTH_FILE_NAME = "auth.json";
53782
53852
  function authFilePath(dataDir) {
53783
- return import_node_path42.default.join(dataDir, AUTH_FILE_NAME);
53853
+ return import_node_path43.default.join(dataDir, AUTH_FILE_NAME);
53784
53854
  }
53785
53855
  function loadOrCreateAuthFile(opts) {
53786
53856
  const file = authFilePath(opts.dataDir);
@@ -53816,7 +53886,7 @@ function defaultGenerateOwnerPrincipalId() {
53816
53886
  }
53817
53887
  function readAuthFile(file) {
53818
53888
  try {
53819
- const raw = import_node_fs40.default.readFileSync(file, "utf8");
53889
+ const raw = import_node_fs41.default.readFileSync(file, "utf8");
53820
53890
  const parsed = JSON.parse(raw);
53821
53891
  if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
53822
53892
  return null;
@@ -53836,25 +53906,25 @@ function readAuthFile(file) {
53836
53906
  }
53837
53907
  }
53838
53908
  function writeAuthFile(file, content) {
53839
- import_node_fs40.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
53840
- import_node_fs40.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53909
+ import_node_fs41.default.mkdirSync(import_node_path43.default.dirname(file), { recursive: true });
53910
+ import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
53841
53911
  try {
53842
- import_node_fs40.default.chmodSync(file, 384);
53912
+ import_node_fs41.default.chmodSync(file, 384);
53843
53913
  } catch {
53844
53914
  }
53845
53915
  }
53846
53916
 
53847
53917
  // src/owner-profile.ts
53848
- var import_node_fs41 = __toESM(require("fs"), 1);
53918
+ var import_node_fs42 = __toESM(require("fs"), 1);
53849
53919
  var import_node_os15 = __toESM(require("os"), 1);
53850
- var import_node_path43 = __toESM(require("path"), 1);
53920
+ var import_node_path44 = __toESM(require("path"), 1);
53851
53921
  var PROFILE_FILENAME = "profile.json";
53852
53922
  function loadOwnerDisplayName(dataDir) {
53853
53923
  const fallback = import_node_os15.default.userInfo().username;
53854
- const profilePath = import_node_path43.default.join(dataDir, PROFILE_FILENAME);
53924
+ const profilePath = import_node_path44.default.join(dataDir, PROFILE_FILENAME);
53855
53925
  let raw;
53856
53926
  try {
53857
- raw = import_node_fs41.default.readFileSync(profilePath, "utf8");
53927
+ raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
53858
53928
  } catch {
53859
53929
  return fallback;
53860
53930
  }
@@ -53877,18 +53947,18 @@ function loadOwnerDisplayName(dataDir) {
53877
53947
  }
53878
53948
 
53879
53949
  // src/feishu-auth/owner-identity-store.ts
53880
- var import_node_fs42 = __toESM(require("fs"), 1);
53881
- var import_node_path44 = __toESM(require("path"), 1);
53950
+ var import_node_fs43 = __toESM(require("fs"), 1);
53951
+ var import_node_path45 = __toESM(require("path"), 1);
53882
53952
  var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
53883
53953
  var OwnerIdentityStore = class {
53884
53954
  file;
53885
53955
  constructor(dataDir) {
53886
- this.file = import_node_path44.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53956
+ this.file = import_node_path45.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
53887
53957
  }
53888
53958
  read() {
53889
53959
  let raw;
53890
53960
  try {
53891
- raw = import_node_fs42.default.readFileSync(this.file, "utf8");
53961
+ raw = import_node_fs43.default.readFileSync(this.file, "utf8");
53892
53962
  } catch {
53893
53963
  return null;
53894
53964
  }
@@ -53916,16 +53986,16 @@ var OwnerIdentityStore = class {
53916
53986
  };
53917
53987
  }
53918
53988
  write(record) {
53919
- import_node_fs42.default.mkdirSync(import_node_path44.default.dirname(this.file), { recursive: true });
53920
- import_node_fs42.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
53989
+ import_node_fs43.default.mkdirSync(import_node_path45.default.dirname(this.file), { recursive: true });
53990
+ import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
53921
53991
  try {
53922
- import_node_fs42.default.chmodSync(this.file, 384);
53992
+ import_node_fs43.default.chmodSync(this.file, 384);
53923
53993
  } catch {
53924
53994
  }
53925
53995
  }
53926
53996
  clear() {
53927
53997
  try {
53928
- import_node_fs42.default.unlinkSync(this.file);
53998
+ import_node_fs43.default.unlinkSync(this.file);
53929
53999
  } catch (err) {
53930
54000
  const code = err?.code;
53931
54001
  if (code !== "ENOENT") throw err;
@@ -54046,9 +54116,9 @@ var CentralClientError = class extends Error {
54046
54116
  code;
54047
54117
  cause;
54048
54118
  };
54049
- async function centralRequest(opts, path76, init) {
54119
+ async function centralRequest(opts, path77, init) {
54050
54120
  const f = opts.fetchImpl ?? globalThis.fetch;
54051
- const url = `${opts.api.replace(/\/+$/, "")}${path76}`;
54121
+ const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
54052
54122
  const ctrl = new AbortController();
54053
54123
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54054
54124
  let res;
@@ -54190,8 +54260,8 @@ function verifyConnectToken(args) {
54190
54260
  }
54191
54261
 
54192
54262
  // src/feishu-auth/server-key.ts
54193
- var fs52 = __toESM(require("fs"), 1);
54194
- var path53 = __toESM(require("path"), 1);
54263
+ var fs53 = __toESM(require("fs"), 1);
54264
+ var path54 = __toESM(require("path"), 1);
54195
54265
  var FILE_NAME2 = "server-signing-key.json";
54196
54266
  var ServerKeyStore = class {
54197
54267
  constructor(dataDir) {
@@ -54199,12 +54269,12 @@ var ServerKeyStore = class {
54199
54269
  }
54200
54270
  dataDir;
54201
54271
  filePath() {
54202
- return path53.join(this.dataDir, FILE_NAME2);
54272
+ return path54.join(this.dataDir, FILE_NAME2);
54203
54273
  }
54204
54274
  /** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
54205
54275
  read() {
54206
54276
  try {
54207
- const raw = fs52.readFileSync(this.filePath(), "utf8");
54277
+ const raw = fs53.readFileSync(this.filePath(), "utf8");
54208
54278
  const parsed = JSON.parse(raw);
54209
54279
  if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
54210
54280
  return parsed.publicKeyPem;
@@ -54219,12 +54289,12 @@ var ServerKeyStore = class {
54219
54289
  publicKeyPem,
54220
54290
  fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
54221
54291
  };
54222
- fs52.mkdirSync(this.dataDir, { recursive: true });
54223
- fs52.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54292
+ fs53.mkdirSync(this.dataDir, { recursive: true });
54293
+ fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
54224
54294
  }
54225
54295
  clear() {
54226
54296
  try {
54227
- fs52.unlinkSync(this.filePath());
54297
+ fs53.unlinkSync(this.filePath());
54228
54298
  } catch {
54229
54299
  }
54230
54300
  }
@@ -54237,12 +54307,12 @@ init_protocol();
54237
54307
  init_protocol();
54238
54308
 
54239
54309
  // src/session/fork.ts
54240
- var import_node_fs43 = __toESM(require("fs"), 1);
54310
+ var import_node_fs44 = __toESM(require("fs"), 1);
54241
54311
  var import_node_os16 = __toESM(require("os"), 1);
54242
- var import_node_path45 = __toESM(require("path"), 1);
54312
+ var import_node_path46 = __toESM(require("path"), 1);
54243
54313
  init_claude_history();
54244
54314
  function readJsonlEntries(file) {
54245
- const raw = import_node_fs43.default.readFileSync(file, "utf8");
54315
+ const raw = import_node_fs44.default.readFileSync(file, "utf8");
54246
54316
  const out = [];
54247
54317
  for (const line of raw.split("\n")) {
54248
54318
  const t = line.trim();
@@ -54255,10 +54325,10 @@ function readJsonlEntries(file) {
54255
54325
  return out;
54256
54326
  }
54257
54327
  function forkSession(input) {
54258
- const baseDir = input.baseDir ?? import_node_path45.default.join(import_node_os16.default.homedir(), ".claude");
54259
- const projectDir = import_node_path45.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54260
- const sourceFile = import_node_path45.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54261
- if (!import_node_fs43.default.existsSync(sourceFile)) {
54328
+ const baseDir = input.baseDir ?? import_node_path46.default.join(import_node_os16.default.homedir(), ".claude");
54329
+ const projectDir = import_node_path46.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
54330
+ const sourceFile = import_node_path46.default.join(projectDir, `${input.toolSessionId}.jsonl`);
54331
+ if (!import_node_fs44.default.existsSync(sourceFile)) {
54262
54332
  throw new Error(`fork: source transcript not found: ${sourceFile}`);
54263
54333
  }
54264
54334
  const entries = readJsonlEntries(sourceFile);
@@ -54288,9 +54358,9 @@ function forkSession(input) {
54288
54358
  }
54289
54359
  forkedLines.push(JSON.stringify(forked));
54290
54360
  }
54291
- const forkedFilePath = import_node_path45.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54292
- import_node_fs43.default.mkdirSync(projectDir, { recursive: true });
54293
- import_node_fs43.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54361
+ const forkedFilePath = import_node_path46.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
54362
+ import_node_fs44.default.mkdirSync(projectDir, { recursive: true });
54363
+ import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
54294
54364
  return { forkedToolSessionId, forkedFilePath };
54295
54365
  }
54296
54366
 
@@ -54642,7 +54712,7 @@ function buildPermissionHandlers(deps) {
54642
54712
  }
54643
54713
 
54644
54714
  // src/handlers/history.ts
54645
- var path56 = __toESM(require("path"), 1);
54715
+ var path57 = __toESM(require("path"), 1);
54646
54716
  init_protocol();
54647
54717
 
54648
54718
  // src/session/recent-dirs.ts
@@ -54660,7 +54730,7 @@ function listRecentDirs(store, limit = 50) {
54660
54730
  }
54661
54731
 
54662
54732
  // src/permission/persona-paths.ts
54663
- var path55 = __toESM(require("path"), 1);
54733
+ var path56 = __toESM(require("path"), 1);
54664
54734
  function getAllowedPersonaIds(grants, action) {
54665
54735
  const ids = /* @__PURE__ */ new Set();
54666
54736
  for (const g2 of grants) {
@@ -54673,42 +54743,42 @@ function getAllowedPersonaIds(grants, action) {
54673
54743
  return ids;
54674
54744
  }
54675
54745
  function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
54676
- const target = path55.resolve(absPath);
54746
+ const target = path56.resolve(absPath);
54677
54747
  if (userWorkDir) {
54678
- const u = path55.resolve(userWorkDir);
54679
- const usep = u.endsWith(path55.sep) ? "" : path55.sep;
54748
+ const u = path56.resolve(userWorkDir);
54749
+ const usep = u.endsWith(path56.sep) ? "" : path56.sep;
54680
54750
  if (target === u || target.startsWith(u + usep)) return true;
54681
54751
  }
54682
- const root = path55.resolve(personaRoot);
54683
- const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54752
+ const root = path56.resolve(personaRoot);
54753
+ const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54684
54754
  if (!target.startsWith(root + sep3)) return false;
54685
- const rel = path55.relative(root, target);
54755
+ const rel = path56.relative(root, target);
54686
54756
  if (!rel || rel.startsWith("..")) return false;
54687
- const personaId = rel.split(path55.sep)[0];
54757
+ const personaId = rel.split(path56.sep)[0];
54688
54758
  if (!personaId) return false;
54689
54759
  const allowed = getAllowedPersonaIds(grants, action);
54690
54760
  if (allowed === "*") return true;
54691
54761
  return allowed.has(personaId);
54692
54762
  }
54693
54763
  function personaIdFromPath(absPath, personaRoot) {
54694
- const root = path55.resolve(personaRoot);
54695
- const target = path55.resolve(absPath);
54696
- const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
54764
+ const root = path56.resolve(personaRoot);
54765
+ const target = path56.resolve(absPath);
54766
+ const sep3 = root.endsWith(path56.sep) ? "" : path56.sep;
54697
54767
  if (!target.startsWith(root + sep3)) return null;
54698
- const rel = path55.relative(root, target);
54768
+ const rel = path56.relative(root, target);
54699
54769
  if (!rel || rel.startsWith("..")) return null;
54700
- const id = rel.split(path55.sep)[0];
54770
+ const id = rel.split(path56.sep)[0];
54701
54771
  return id || null;
54702
54772
  }
54703
54773
  function isPathWithin(dir, absPath) {
54704
- const d = path55.resolve(dir);
54705
- const t = path55.resolve(absPath);
54706
- const sep3 = d.endsWith(path55.sep) ? "" : path55.sep;
54774
+ const d = path56.resolve(dir);
54775
+ const t = path56.resolve(absPath);
54776
+ const sep3 = d.endsWith(path56.sep) ? "" : path56.sep;
54707
54777
  return t === d || t.startsWith(d + sep3);
54708
54778
  }
54709
54779
  function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
54710
54780
  if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
54711
- return personaIdFromPath(path55.resolve(absPath), personaRoot) === personaId;
54781
+ return personaIdFromPath(path56.resolve(absPath), personaRoot) === personaId;
54712
54782
  }
54713
54783
 
54714
54784
  // src/handlers/history.ts
@@ -54734,7 +54804,7 @@ function buildHistoryHandlers(deps) {
54734
54804
  if (!pid) return false;
54735
54805
  return isGuestPathAllowed(
54736
54806
  ctx.grants,
54737
- path56.join(personaRoot, pid),
54807
+ path57.join(personaRoot, pid),
54738
54808
  personaRoot,
54739
54809
  "read",
54740
54810
  userWorkDir
@@ -54746,7 +54816,7 @@ function buildHistoryHandlers(deps) {
54746
54816
  };
54747
54817
  const list = async (frame, _client, ctx) => {
54748
54818
  const args = HistoryListArgs.parse(frame);
54749
- assertGuestPath(ctx, path56.resolve(args.projectPath), personaRoot, "history:list");
54819
+ assertGuestPath(ctx, path57.resolve(args.projectPath), personaRoot, "history:list");
54750
54820
  const sessions = await history.listSessions(args);
54751
54821
  return { response: { type: "history:list", sessions } };
54752
54822
  };
@@ -54778,13 +54848,13 @@ function buildHistoryHandlers(deps) {
54778
54848
  };
54779
54849
  const subagents = async (frame, _client, ctx) => {
54780
54850
  const args = HistorySubagentsArgs.parse(frame);
54781
- assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54851
+ assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
54782
54852
  const subs = await history.listSubagents(args);
54783
54853
  return { response: { type: "history:subagents", subagents: subs } };
54784
54854
  };
54785
54855
  const subagentRead = async (frame, _client, ctx) => {
54786
54856
  const args = HistorySubagentReadArgs.parse(frame);
54787
- assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54857
+ assertGuestPath(ctx, path57.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
54788
54858
  const res = await history.readSubagent(args);
54789
54859
  return { response: { type: "history:subagent-read", ...res } };
54790
54860
  };
@@ -54793,7 +54863,7 @@ function buildHistoryHandlers(deps) {
54793
54863
  if (ctx?.principal.kind === "guest" && personaRoot) {
54794
54864
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54795
54865
  const filtered = dirs.filter(
54796
- (d) => isGuestPathAllowed(ctx.grants, path56.resolve(d.cwd), personaRoot, "read", userWorkDir)
54866
+ (d) => isGuestPathAllowed(ctx.grants, path57.resolve(d.cwd), personaRoot, "read", userWorkDir)
54797
54867
  );
54798
54868
  return { response: { type: "history:recentDirs", dirs: filtered } };
54799
54869
  }
@@ -54810,7 +54880,7 @@ function buildHistoryHandlers(deps) {
54810
54880
  }
54811
54881
 
54812
54882
  // src/handlers/workspace.ts
54813
- var path57 = __toESM(require("path"), 1);
54883
+ var path58 = __toESM(require("path"), 1);
54814
54884
  var os16 = __toESM(require("os"), 1);
54815
54885
  init_protocol();
54816
54886
  init_protocol();
@@ -54852,22 +54922,22 @@ function buildWorkspaceHandlers(deps) {
54852
54922
  const args = WorkspaceListArgs.parse(frame);
54853
54923
  const isGuest = ctx?.principal.kind === "guest";
54854
54924
  const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
54855
- const resolvedCwd = path57.resolve(args.cwd ?? fallbackCwd);
54856
- const target = args.path ? path57.resolve(resolvedCwd, args.path) : resolvedCwd;
54925
+ const resolvedCwd = path58.resolve(args.cwd ?? fallbackCwd);
54926
+ const target = args.path ? path58.resolve(resolvedCwd, args.path) : resolvedCwd;
54857
54927
  assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
54858
54928
  const res = workspace.list({ ...args, cwd: resolvedCwd });
54859
54929
  return { response: { type: "workspace:list", ...res } };
54860
54930
  };
54861
54931
  const read = async (frame, _client, ctx) => {
54862
54932
  const args = WorkspaceReadArgs.parse(frame);
54863
- const target = path57.isAbsolute(args.path) ? path57.resolve(args.path) : path57.resolve(args.cwd, args.path);
54933
+ const target = path58.isAbsolute(args.path) ? path58.resolve(args.path) : path58.resolve(args.cwd, args.path);
54864
54934
  assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
54865
54935
  const res = workspace.read(args);
54866
54936
  return { response: { type: "workspace:read", ...res } };
54867
54937
  };
54868
54938
  const skillsList = async (frame, _client, ctx) => {
54869
54939
  const args = SkillsListArgs.parse(frame);
54870
- const cwdAbs = path57.resolve(args.cwd);
54940
+ const cwdAbs = path58.resolve(args.cwd);
54871
54941
  assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
54872
54942
  const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
54873
54943
  if (ctx?.principal.kind === "guest" && personaRoot) {
@@ -54879,7 +54949,7 @@ function buildWorkspaceHandlers(deps) {
54879
54949
  };
54880
54950
  const agentsList = async (frame, _client, ctx) => {
54881
54951
  const args = AgentsListArgs.parse(frame);
54882
- const cwdAbs = path57.resolve(args.cwd);
54952
+ const cwdAbs = path58.resolve(args.cwd);
54883
54953
  assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
54884
54954
  if (args.tool === "codex") {
54885
54955
  return { response: { type: "agents:list", agents: [] } };
@@ -54901,20 +54971,20 @@ function buildWorkspaceHandlers(deps) {
54901
54971
  }
54902
54972
 
54903
54973
  // src/handlers/git.ts
54904
- var path59 = __toESM(require("path"), 1);
54974
+ var path60 = __toESM(require("path"), 1);
54905
54975
  init_protocol();
54906
54976
  init_protocol();
54907
54977
 
54908
54978
  // src/workspace/git.ts
54909
54979
  var import_node_child_process12 = require("child_process");
54910
- var import_node_fs44 = __toESM(require("fs"), 1);
54911
- var import_node_path46 = __toESM(require("path"), 1);
54980
+ var import_node_fs45 = __toESM(require("fs"), 1);
54981
+ var import_node_path47 = __toESM(require("path"), 1);
54912
54982
  var import_node_util = require("util");
54913
54983
  var pexec = (0, import_node_util.promisify)(import_node_child_process12.execFile);
54914
54984
  function normalizePath(p2) {
54915
- const resolved = import_node_path46.default.resolve(p2);
54985
+ const resolved = import_node_path47.default.resolve(p2);
54916
54986
  try {
54917
- return import_node_fs44.default.realpathSync(resolved);
54987
+ return import_node_fs45.default.realpathSync(resolved);
54918
54988
  } catch {
54919
54989
  return resolved;
54920
54990
  }
@@ -54988,7 +55058,7 @@ async function listGitBranches(cwd) {
54988
55058
  function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
54989
55059
  if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
54990
55060
  const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
54991
- if (!isGuestPathAllowed(ctx.grants, path59.resolve(cwd), personaRoot, "read", userWorkDir)) {
55061
+ if (!isGuestPathAllowed(ctx.grants, path60.resolve(cwd), personaRoot, "read", userWorkDir)) {
54992
55062
  throw new ClawdError(
54993
55063
  ERROR_CODES.UNAUTHORIZED,
54994
55064
  `guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
@@ -55329,22 +55399,22 @@ init_src();
55329
55399
  init_protocol();
55330
55400
 
55331
55401
  // src/sshd/key-issue.ts
55332
- var import_node_fs45 = __toESM(require("fs"), 1);
55333
- var import_node_path47 = __toESM(require("path"), 1);
55402
+ var import_node_fs46 = __toESM(require("fs"), 1);
55403
+ var import_node_path48 = __toESM(require("path"), 1);
55334
55404
  var import_node_child_process13 = require("child_process");
55335
55405
  function safeDeviceId(deviceId) {
55336
55406
  return deviceId.replace(/[\/\\]/g, "_");
55337
55407
  }
55338
55408
  async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55339
55409
  const safeId = safeDeviceId(deviceId);
55340
- const keysDir = import_node_path47.default.join(sshdDir, "keys");
55341
- import_node_fs45.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55342
- const privPath = import_node_path47.default.join(keysDir, `${safeId}.ed25519`);
55410
+ const keysDir = import_node_path48.default.join(sshdDir, "keys");
55411
+ import_node_fs46.default.mkdirSync(keysDir, { recursive: true, mode: 448 });
55412
+ const privPath = import_node_path48.default.join(keysDir, `${safeId}.ed25519`);
55343
55413
  const pubPath = `${privPath}.pub`;
55344
- if (import_node_fs45.default.existsSync(privPath) && import_node_fs45.default.existsSync(pubPath)) {
55414
+ if (import_node_fs46.default.existsSync(privPath) && import_node_fs46.default.existsSync(pubPath)) {
55345
55415
  return {
55346
- privateKeyPem: import_node_fs45.default.readFileSync(privPath, "utf8"),
55347
- publicKeyLine: import_node_fs45.default.readFileSync(pubPath, "utf8").trim()
55416
+ privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55417
+ publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55348
55418
  };
55349
55419
  }
55350
55420
  const bin = opts.keygenBin ?? "/usr/bin/ssh-keygen";
@@ -55358,20 +55428,21 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55358
55428
  p2.on("error", reject);
55359
55429
  });
55360
55430
  try {
55361
- import_node_fs45.default.chmodSync(privPath, 384);
55431
+ import_node_fs46.default.chmodSync(privPath, 384);
55362
55432
  } catch {
55363
55433
  }
55364
55434
  try {
55365
- import_node_fs45.default.chmodSync(pubPath, 420);
55435
+ import_node_fs46.default.chmodSync(pubPath, 420);
55366
55436
  } catch {
55367
55437
  }
55368
55438
  return {
55369
- privateKeyPem: import_node_fs45.default.readFileSync(privPath, "utf8"),
55370
- publicKeyLine: import_node_fs45.default.readFileSync(pubPath, "utf8").trim()
55439
+ privateKeyPem: import_node_fs46.default.readFileSync(privPath, "utf8"),
55440
+ publicKeyLine: import_node_fs46.default.readFileSync(pubPath, "utf8").trim()
55371
55441
  };
55372
55442
  }
55373
55443
 
55374
55444
  // src/handlers/contact-ssh.ts
55445
+ init_contact_ssh_log();
55375
55446
  function ensureOwner2(ctx) {
55376
55447
  if (!ctx || ctx.principal.kind !== "owner") {
55377
55448
  throw new ClawdError(
@@ -55786,7 +55857,7 @@ function buildPersonaHandlers(deps) {
55786
55857
  }
55787
55858
 
55788
55859
  // src/handlers/attachment.ts
55789
- var import_node_path48 = __toESM(require("path"), 1);
55860
+ var import_node_path49 = __toESM(require("path"), 1);
55790
55861
  init_protocol();
55791
55862
  init_protocol();
55792
55863
  var DEFAULT_TTL_SECONDS = 24 * 3600;
@@ -55866,12 +55937,12 @@ function buildAttachmentHandlers(deps) {
55866
55937
  `session ${args.sessionId} scope unresolved`
55867
55938
  );
55868
55939
  }
55869
- const cwdAbs = import_node_path48.default.resolve(sessionFile.cwd);
55870
- const candidateAbs = import_node_path48.default.isAbsolute(args.relPath) ? import_node_path48.default.resolve(args.relPath) : import_node_path48.default.resolve(cwdAbs, args.relPath);
55940
+ const cwdAbs = import_node_path49.default.resolve(sessionFile.cwd);
55941
+ const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
55871
55942
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
55872
55943
  const entries = deps.groupFileStore.list(scope, args.sessionId);
55873
55944
  const entry = entries.find((e) => {
55874
- const storedAbs = import_node_path48.default.isAbsolute(e.relPath) ? import_node_path48.default.resolve(e.relPath) : import_node_path48.default.resolve(cwdAbs, e.relPath);
55945
+ const storedAbs = import_node_path49.default.isAbsolute(e.relPath) ? import_node_path49.default.resolve(e.relPath) : import_node_path49.default.resolve(cwdAbs, e.relPath);
55875
55946
  return storedAbs === candidateAbs && !e.stale;
55876
55947
  });
55877
55948
  if (!entry) {
@@ -55896,7 +55967,7 @@ function buildAttachmentHandlers(deps) {
55896
55967
  if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
55897
55968
  const f = deps.sessionStore.read(sessionId);
55898
55969
  if (!f) return;
55899
- assertGuestAttachmentPath(ctx, import_node_path48.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55970
+ assertGuestAttachmentPath(ctx, import_node_path49.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
55900
55971
  }
55901
55972
  const groupAdd = async (frame, _client, ctx) => {
55902
55973
  if (!deps.groupFileStore || !deps.getSessionScope) {
@@ -55911,8 +55982,8 @@ function buildAttachmentHandlers(deps) {
55911
55982
  if (!scope) {
55912
55983
  throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
55913
55984
  }
55914
- const cwdAbs = import_node_path48.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55915
- const candidateAbs = import_node_path48.default.isAbsolute(args.relPath) ? import_node_path48.default.resolve(args.relPath) : import_node_path48.default.resolve(cwdAbs, args.relPath);
55985
+ const cwdAbs = import_node_path49.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
55986
+ const candidateAbs = import_node_path49.default.isAbsolute(args.relPath) ? import_node_path49.default.resolve(args.relPath) : import_node_path49.default.resolve(cwdAbs, args.relPath);
55916
55987
  guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
55917
55988
  const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
55918
55989
  const size = 0;
@@ -55971,20 +56042,20 @@ function buildAttachmentHandlers(deps) {
55971
56042
 
55972
56043
  // src/handlers/extension.ts
55973
56044
  var import_promises8 = __toESM(require("fs/promises"), 1);
55974
- var import_node_path53 = __toESM(require("path"), 1);
56045
+ var import_node_path54 = __toESM(require("path"), 1);
55975
56046
  init_protocol();
55976
56047
  init_src();
55977
56048
 
55978
56049
  // src/extension/bundle-zip.ts
55979
56050
  var import_promises5 = __toESM(require("fs/promises"), 1);
55980
- var import_node_path49 = __toESM(require("path"), 1);
56051
+ var import_node_path50 = __toESM(require("path"), 1);
55981
56052
  var import_node_crypto14 = __toESM(require("crypto"), 1);
55982
56053
  var import_jszip2 = __toESM(require_lib3(), 1);
55983
56054
  async function bundleExtensionDir(dir) {
55984
56055
  const entries = await listFilesSorted(dir);
55985
56056
  const zip = new import_jszip2.default();
55986
56057
  for (const rel of entries) {
55987
- const abs = import_node_path49.default.join(dir, rel);
56058
+ const abs = import_node_path50.default.join(dir, rel);
55988
56059
  const content = await import_promises5.default.readFile(abs);
55989
56060
  zip.file(rel, content, { date: FIXED_DATE });
55990
56061
  }
@@ -56005,7 +56076,7 @@ async function listFilesSorted(rootDir) {
56005
56076
  return out;
56006
56077
  }
56007
56078
  async function walk(absRoot, relPrefix, out) {
56008
- const dirAbs = import_node_path49.default.join(absRoot, relPrefix);
56079
+ const dirAbs = import_node_path50.default.join(absRoot, relPrefix);
56009
56080
  const entries = await import_promises5.default.readdir(dirAbs, { withFileTypes: true });
56010
56081
  for (const e of entries) {
56011
56082
  if (IGNORE_BASENAMES.has(e.name)) continue;
@@ -56061,7 +56132,7 @@ function computePublishCheck(args) {
56061
56132
 
56062
56133
  // src/extension/install-flow.ts
56063
56134
  var import_promises6 = __toESM(require("fs/promises"), 1);
56064
- var import_node_path51 = __toESM(require("path"), 1);
56135
+ var import_node_path52 = __toESM(require("path"), 1);
56065
56136
  var import_node_os19 = __toESM(require("os"), 1);
56066
56137
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56067
56138
  var import_jszip3 = __toESM(require_lib3(), 1);
@@ -56069,19 +56140,19 @@ init_src();
56069
56140
 
56070
56141
  // src/extension/paths.ts
56071
56142
  var import_node_os18 = __toESM(require("os"), 1);
56072
- var import_node_path50 = __toESM(require("path"), 1);
56143
+ var import_node_path51 = __toESM(require("path"), 1);
56073
56144
  init_src();
56074
56145
  function clawdHomeRoot(override) {
56075
- return override ?? process.env.CLAWD_HOME ?? import_node_path50.default.join(import_node_os18.default.homedir(), ".clawd");
56146
+ return override ?? process.env.CLAWD_HOME ?? import_node_path51.default.join(import_node_os18.default.homedir(), ".clawd");
56076
56147
  }
56077
56148
  function extensionsRoot(override) {
56078
- return import_node_path50.default.join(clawdHomeRoot(override), "extensions");
56149
+ return import_node_path51.default.join(clawdHomeRoot(override), "extensions");
56079
56150
  }
56080
56151
  function publishedChannelsFile(override) {
56081
- return import_node_path50.default.join(clawdHomeRoot(override), "extensions-published.json");
56152
+ return import_node_path51.default.join(clawdHomeRoot(override), "extensions-published.json");
56082
56153
  }
56083
56154
  function bundleCacheRoot(override) {
56084
- return import_node_path50.default.join(clawdHomeRoot(override), "extension-bundles");
56155
+ return import_node_path51.default.join(clawdHomeRoot(override), "extension-bundles");
56085
56156
  }
56086
56157
 
56087
56158
  // src/extension/install-flow.ts
@@ -56108,7 +56179,7 @@ async function installFromChannel(args, deps) {
56108
56179
  throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56109
56180
  }
56110
56181
  for (const name of Object.keys(zip.files)) {
56111
- if (name.includes("..") || name.startsWith("/") || import_node_path51.default.isAbsolute(name)) {
56182
+ if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56112
56183
  throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56113
56184
  }
56114
56185
  }
@@ -56140,7 +56211,7 @@ async function installFromChannel(args, deps) {
56140
56211
  );
56141
56212
  }
56142
56213
  const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
56143
- const destDir = import_node_path51.default.join(deps.extensionsRoot, localExtId);
56214
+ const destDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56144
56215
  let destExists = false;
56145
56216
  try {
56146
56217
  await import_promises6.default.access(destDir);
@@ -56154,16 +56225,16 @@ async function installFromChannel(args, deps) {
56154
56225
  );
56155
56226
  }
56156
56227
  const stage = await import_promises6.default.mkdtemp(
56157
- import_node_path51.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56228
+ import_node_path52.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
56158
56229
  );
56159
56230
  try {
56160
56231
  for (const [name, entry] of Object.entries(zip.files)) {
56161
- const dest = import_node_path51.default.join(stage, name);
56232
+ const dest = import_node_path52.default.join(stage, name);
56162
56233
  if (entry.dir) {
56163
56234
  await import_promises6.default.mkdir(dest, { recursive: true });
56164
56235
  continue;
56165
56236
  }
56166
- await import_promises6.default.mkdir(import_node_path51.default.dirname(dest), { recursive: true });
56237
+ await import_promises6.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56167
56238
  if (name === "manifest.json") {
56168
56239
  const rewritten = { ...parsed.data, id: localExtId };
56169
56240
  await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56184,7 +56255,7 @@ async function installFromChannel(args, deps) {
56184
56255
 
56185
56256
  // src/extension/update-flow.ts
56186
56257
  var import_promises7 = __toESM(require("fs/promises"), 1);
56187
- var import_node_path52 = __toESM(require("path"), 1);
56258
+ var import_node_path53 = __toESM(require("path"), 1);
56188
56259
  var import_node_os20 = __toESM(require("os"), 1);
56189
56260
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56190
56261
  var import_jszip4 = __toESM(require_lib3(), 1);
@@ -56202,11 +56273,11 @@ async function updateFromChannel(args, deps) {
56202
56273
  channelRef.extId,
56203
56274
  channelRef.ownerPrincipalId
56204
56275
  );
56205
- const liveDir = import_node_path52.default.join(deps.extensionsRoot, localExtId);
56276
+ const liveDir = import_node_path53.default.join(deps.extensionsRoot, localExtId);
56206
56277
  const prevDir = `${liveDir}.prev`;
56207
56278
  let existingVersion;
56208
56279
  try {
56209
- const raw = await import_promises7.default.readFile(import_node_path52.default.join(liveDir, "manifest.json"), "utf8");
56280
+ const raw = await import_promises7.default.readFile(import_node_path53.default.join(liveDir, "manifest.json"), "utf8");
56210
56281
  const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
56211
56282
  if (!parsed2.success) {
56212
56283
  throw new UpdateError(
@@ -56239,7 +56310,7 @@ async function updateFromChannel(args, deps) {
56239
56310
  throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
56240
56311
  }
56241
56312
  for (const name of Object.keys(zip.files)) {
56242
- if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
56313
+ if (name.includes("..") || name.startsWith("/") || import_node_path53.default.isAbsolute(name)) {
56243
56314
  throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
56244
56315
  }
56245
56316
  }
@@ -56274,16 +56345,16 @@ async function updateFromChannel(args, deps) {
56274
56345
  await import_promises7.default.rm(prevDir, { recursive: true, force: true });
56275
56346
  await import_promises7.default.rename(liveDir, prevDir);
56276
56347
  const stage = await import_promises7.default.mkdtemp(
56277
- import_node_path52.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56348
+ import_node_path53.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
56278
56349
  );
56279
56350
  try {
56280
56351
  for (const [name, entry] of Object.entries(zip.files)) {
56281
- const dest = import_node_path52.default.join(stage, name);
56352
+ const dest = import_node_path53.default.join(stage, name);
56282
56353
  if (entry.dir) {
56283
56354
  await import_promises7.default.mkdir(dest, { recursive: true });
56284
56355
  continue;
56285
56356
  }
56286
- await import_promises7.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
56357
+ await import_promises7.default.mkdir(import_node_path53.default.dirname(dest), { recursive: true });
56287
56358
  if (name === "manifest.json") {
56288
56359
  const rewritten = { ...parsed.data, id: localExtId };
56289
56360
  await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
@@ -56377,7 +56448,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56377
56448
  );
56378
56449
  }
56379
56450
  }
56380
- const manifestPath = import_node_path53.default.join(root, extId, "manifest.json");
56451
+ const manifestPath = import_node_path54.default.join(root, extId, "manifest.json");
56381
56452
  const manifest = await readManifest(root, extId);
56382
56453
  const next = { ...manifest, version: newVersion };
56383
56454
  const tmp = `${manifestPath}.tmp`;
@@ -56385,7 +56456,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
56385
56456
  await import_promises8.default.rename(tmp, manifestPath);
56386
56457
  }
56387
56458
  async function readManifest(root, extId) {
56388
- const file = import_node_path53.default.join(root, extId, "manifest.json");
56459
+ const file = import_node_path54.default.join(root, extId, "manifest.json");
56389
56460
  let raw;
56390
56461
  try {
56391
56462
  raw = await import_promises8.default.readFile(file, "utf8");
@@ -56476,7 +56547,7 @@ function buildExtensionHandlers(deps) {
56476
56547
  };
56477
56548
  async function buildSnapshotMeta(extId) {
56478
56549
  const manifest = await readManifest(deps.root, extId);
56479
- const { sha256, buffer } = await bundleExtensionDir(import_node_path53.default.join(deps.root, extId));
56550
+ const { sha256, buffer } = await bundleExtensionDir(import_node_path54.default.join(deps.root, extId));
56480
56551
  return { manifest, contentHash: sha256, buffer };
56481
56552
  }
56482
56553
  const publish = async (frame, _client, ctx) => {
@@ -56657,9 +56728,9 @@ function buildExtensionHandlers(deps) {
56657
56728
  }
56658
56729
 
56659
56730
  // src/app-builder/project-store.ts
56660
- var import_node_fs46 = require("fs");
56731
+ var import_node_fs47 = require("fs");
56661
56732
  var import_node_child_process14 = require("child_process");
56662
- var import_node_path54 = require("path");
56733
+ var import_node_path55 = require("path");
56663
56734
  init_protocol();
56664
56735
  var PROJECTS_DIR = "projects";
56665
56736
  var META_FILE = ".clawd-project.json";
@@ -56673,19 +56744,19 @@ var ProjectStore = class {
56673
56744
  root;
56674
56745
  /** projects/<name>/.clawd-project.json 路径 */
56675
56746
  metaPath(name) {
56676
- return (0, import_node_path54.join)(this.projectsRoot(), name, META_FILE);
56747
+ return (0, import_node_path55.join)(this.projectsRoot(), name, META_FILE);
56677
56748
  }
56678
56749
  /** projects/<name>/ 目录路径(cwd 用) */
56679
56750
  projectDir(name) {
56680
- return (0, import_node_path54.join)(this.projectsRoot(), name);
56751
+ return (0, import_node_path55.join)(this.projectsRoot(), name);
56681
56752
  }
56682
56753
  projectsRoot() {
56683
- return (0, import_node_path54.join)(this.root, PROJECTS_DIR);
56754
+ return (0, import_node_path55.join)(this.root, PROJECTS_DIR);
56684
56755
  }
56685
56756
  async list() {
56686
56757
  let entries;
56687
56758
  try {
56688
- entries = await import_node_fs46.promises.readdir(this.projectsRoot());
56759
+ entries = await import_node_fs47.promises.readdir(this.projectsRoot());
56689
56760
  } catch (err) {
56690
56761
  if (err.code === "ENOENT") return [];
56691
56762
  throw err;
@@ -56693,7 +56764,7 @@ var ProjectStore = class {
56693
56764
  const out = [];
56694
56765
  for (const name of entries) {
56695
56766
  try {
56696
- const raw = await import_node_fs46.promises.readFile(this.metaPath(name), "utf8");
56767
+ const raw = await import_node_fs47.promises.readFile(this.metaPath(name), "utf8");
56697
56768
  const json = JSON.parse(raw);
56698
56769
  let migrated = false;
56699
56770
  if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
@@ -56704,7 +56775,7 @@ var ProjectStore = class {
56704
56775
  if (parsed.success) {
56705
56776
  out.push(parsed.data);
56706
56777
  if (migrated) {
56707
- void import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56778
+ void import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
56708
56779
  });
56709
56780
  }
56710
56781
  }
@@ -56748,8 +56819,8 @@ var ProjectStore = class {
56748
56819
  throw new Error(`invalid name "${name}": ${validated.error.message}`);
56749
56820
  }
56750
56821
  const dir = this.projectDir(name);
56751
- await import_node_fs46.promises.mkdir(dir, { recursive: true });
56752
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56822
+ await import_node_fs47.promises.mkdir(dir, { recursive: true });
56823
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
56753
56824
  return meta;
56754
56825
  }
56755
56826
  /**
@@ -56792,7 +56863,7 @@ var ProjectStore = class {
56792
56863
  }
56793
56864
  async delete(name) {
56794
56865
  const dir = this.projectDir(name);
56795
- await import_node_fs46.promises.rm(dir, { recursive: true, force: true });
56866
+ await import_node_fs47.promises.rm(dir, { recursive: true, force: true });
56796
56867
  }
56797
56868
  async updatePort(name, newPort) {
56798
56869
  if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
@@ -56808,7 +56879,7 @@ var ProjectStore = class {
56808
56879
  throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
56809
56880
  }
56810
56881
  const updated = { ...target, port: newPort };
56811
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56882
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
56812
56883
  return updated;
56813
56884
  }
56814
56885
  /**
@@ -56825,7 +56896,7 @@ var ProjectStore = class {
56825
56896
  if (!validated.success) {
56826
56897
  throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
56827
56898
  }
56828
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56899
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56829
56900
  return validated.data;
56830
56901
  }
56831
56902
  /**
@@ -56846,7 +56917,7 @@ var ProjectStore = class {
56846
56917
  if (!validated.success) {
56847
56918
  throw new Error(`invalid publishJob: ${validated.error.message}`);
56848
56919
  }
56849
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56920
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56850
56921
  return validated.data;
56851
56922
  }
56852
56923
  /** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
@@ -56861,7 +56932,7 @@ var ProjectStore = class {
56861
56932
  if (!validated.success) {
56862
56933
  throw new Error(`failed to clear publishJob: ${validated.error.message}`);
56863
56934
  }
56864
- await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56935
+ await import_node_fs47.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
56865
56936
  return validated.data;
56866
56937
  }
56867
56938
  };
@@ -56982,8 +57053,8 @@ var PublishJobRegistry = class {
56982
57053
 
56983
57054
  // src/app-builder/publish-job-runner.ts
56984
57055
  var import_node_child_process16 = require("child_process");
56985
- var import_node_fs47 = require("fs");
56986
- var import_node_path55 = require("path");
57056
+ var import_node_fs48 = require("fs");
57057
+ var import_node_path56 = require("path");
56987
57058
 
56988
57059
  // src/app-builder/publish-stage-parser.ts
56989
57060
  var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
@@ -57015,10 +57086,10 @@ async function startPublishJob(deps, args) {
57015
57086
  return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
57016
57087
  }
57017
57088
  const projDir = projectDir(args.name);
57018
- const logPath = (0, import_node_path55.join)(projDir, ".publish.log");
57089
+ const logPath = (0, import_node_path56.join)(projDir, ".publish.log");
57019
57090
  let logStream = null;
57020
57091
  try {
57021
- logStream = (0, import_node_fs47.createWriteStream)(logPath, { flags: "w" });
57092
+ logStream = (0, import_node_fs48.createWriteStream)(logPath, { flags: "w" });
57022
57093
  } catch {
57023
57094
  logStream = null;
57024
57095
  }
@@ -57275,8 +57346,8 @@ async function recoverInterruptedJobs(deps) {
57275
57346
 
57276
57347
  // src/handlers/app-builder.ts
57277
57348
  init_protocol();
57278
- var import_node_path56 = require("path");
57279
- var import_node_fs48 = require("fs");
57349
+ var import_node_path57 = require("path");
57350
+ var import_node_fs49 = require("fs");
57280
57351
  var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
57281
57352
  var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
57282
57353
  async function recoverInterruptedPublishJobs(store, logger) {
@@ -57357,7 +57428,7 @@ function buildAppBuilderHandlers(deps) {
57357
57428
  async function listAllUsersProjects() {
57358
57429
  if (!deps.usersRoot || !deps.getStore) return [];
57359
57430
  const getStore = deps.getStore;
57360
- const userIds = await import_node_fs48.promises.readdir(deps.usersRoot).catch(() => []);
57431
+ const userIds = await import_node_fs49.promises.readdir(deps.usersRoot).catch(() => []);
57361
57432
  const perUser = await Promise.all(
57362
57433
  userIds.map((uid) => getStore(uid).list().catch(() => []))
57363
57434
  );
@@ -57433,8 +57504,8 @@ function buildAppBuilderHandlers(deps) {
57433
57504
  const project = await userStore.create(f.name, reservedPorts);
57434
57505
  try {
57435
57506
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
57436
- const templateSrcDir = (0, import_node_path56.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57437
- const scaffoldScript = (0, import_node_path56.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57507
+ const templateSrcDir = (0, import_node_path57.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
57508
+ const scaffoldScript = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
57438
57509
  const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
57439
57510
  deps.logger?.info("app-builder.scaffold.done", {
57440
57511
  name: project.name,
@@ -57655,7 +57726,7 @@ function buildAppBuilderHandlers(deps) {
57655
57726
  await userStore.clearPublishJob(args.name);
57656
57727
  }
57657
57728
  const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
57658
- const scriptPath = (0, import_node_path56.join)(deps.deployKitRoot, "scripts", "publish.sh");
57729
+ const scriptPath = (0, import_node_path57.join)(deps.deployKitRoot, "scripts", "publish.sh");
57659
57730
  deps.logger?.info("app-builder.publish.start", {
57660
57731
  name: args.name,
57661
57732
  sessionId: boundSession.sessionId,
@@ -57824,7 +57895,7 @@ function buildVisitorHandlers(deps) {
57824
57895
 
57825
57896
  // src/extension/registry.ts
57826
57897
  var import_promises9 = __toESM(require("fs/promises"), 1);
57827
- var import_node_path57 = __toESM(require("path"), 1);
57898
+ var import_node_path58 = __toESM(require("path"), 1);
57828
57899
  init_src();
57829
57900
  async function loadAll(root) {
57830
57901
  let entries;
@@ -57838,13 +57909,13 @@ async function loadAll(root) {
57838
57909
  for (const ent of entries) {
57839
57910
  if (!ent.isDirectory()) continue;
57840
57911
  if (ent.name.startsWith(".")) continue;
57841
- records.push(await loadOne(import_node_path57.default.join(root, ent.name), ent.name));
57912
+ records.push(await loadOne(import_node_path58.default.join(root, ent.name), ent.name));
57842
57913
  }
57843
57914
  records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
57844
57915
  return records;
57845
57916
  }
57846
57917
  async function loadOne(dir, dirName) {
57847
- const manifestPath = import_node_path57.default.join(dir, "manifest.json");
57918
+ const manifestPath = import_node_path58.default.join(dir, "manifest.json");
57848
57919
  let raw;
57849
57920
  try {
57850
57921
  raw = await import_promises9.default.readFile(manifestPath, "utf8");
@@ -57889,7 +57960,7 @@ async function loadOne(dir, dirName) {
57889
57960
 
57890
57961
  // src/extension/uninstall.ts
57891
57962
  var import_promises10 = __toESM(require("fs/promises"), 1);
57892
- var import_node_path58 = __toESM(require("path"), 1);
57963
+ var import_node_path59 = __toESM(require("path"), 1);
57893
57964
  var UninstallError = class extends Error {
57894
57965
  constructor(code, message) {
57895
57966
  super(message);
@@ -57898,7 +57969,7 @@ var UninstallError = class extends Error {
57898
57969
  code;
57899
57970
  };
57900
57971
  async function uninstall(deps) {
57901
- const dir = import_node_path58.default.join(deps.root, deps.extId);
57972
+ const dir = import_node_path59.default.join(deps.root, deps.extId);
57902
57973
  try {
57903
57974
  await import_promises10.default.access(dir);
57904
57975
  } catch {
@@ -58482,7 +58553,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58482
58553
 
58483
58554
  // src/extension/runtime.ts
58484
58555
  var import_node_child_process18 = require("child_process");
58485
- var import_node_path59 = __toESM(require("path"), 1);
58556
+ var import_node_path60 = __toESM(require("path"), 1);
58486
58557
  var import_promises11 = require("timers/promises");
58487
58558
  init_src();
58488
58559
 
@@ -58584,7 +58655,7 @@ var Runtime = class {
58584
58655
  /\$CLAWOS_EXT_PORT/g,
58585
58656
  String(port)
58586
58657
  );
58587
- const dir = import_node_path59.default.join(this.root, extId);
58658
+ const dir = import_node_path60.default.join(this.root, extId);
58588
58659
  const env = {
58589
58660
  ...process.env,
58590
58661
  CLAWOS_EXT_PORT: String(port),
@@ -58696,7 +58767,7 @@ ${handle.stderrTail}`
58696
58767
 
58697
58768
  // src/extension/published-channels.ts
58698
58769
  var import_promises12 = __toESM(require("fs/promises"), 1);
58699
- var import_node_path60 = __toESM(require("path"), 1);
58770
+ var import_node_path61 = __toESM(require("path"), 1);
58700
58771
  init_src();
58701
58772
  init_zod();
58702
58773
  var PublishedChannelsError = class extends Error {
@@ -58796,7 +58867,7 @@ var PublishedChannelStore = class {
58796
58867
  )
58797
58868
  };
58798
58869
  const tmp = `${this.filePath}.tmp`;
58799
- await import_promises12.default.mkdir(import_node_path60.default.dirname(this.filePath), { recursive: true });
58870
+ await import_promises12.default.mkdir(import_node_path61.default.dirname(this.filePath), { recursive: true });
58800
58871
  await import_promises12.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
58801
58872
  await import_promises12.default.rename(tmp, this.filePath);
58802
58873
  }
@@ -58804,7 +58875,7 @@ var PublishedChannelStore = class {
58804
58875
 
58805
58876
  // src/extension/bundle-cache.ts
58806
58877
  var import_promises13 = __toESM(require("fs/promises"), 1);
58807
- var import_node_path61 = __toESM(require("path"), 1);
58878
+ var import_node_path62 = __toESM(require("path"), 1);
58808
58879
  var BundleCache = class {
58809
58880
  constructor(rootDir) {
58810
58881
  this.rootDir = rootDir;
@@ -58813,14 +58884,14 @@ var BundleCache = class {
58813
58884
  /** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
58814
58885
  async write(snapshotHash, buffer) {
58815
58886
  await import_promises13.default.mkdir(this.rootDir, { recursive: true });
58816
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58887
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58817
58888
  const tmp = `${file}.tmp`;
58818
58889
  await import_promises13.default.writeFile(tmp, buffer, { mode: 384 });
58819
58890
  await import_promises13.default.rename(tmp, file);
58820
58891
  }
58821
58892
  /** Returns the bundle bytes, or null when the file doesn't exist. */
58822
58893
  async read(snapshotHash) {
58823
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58894
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58824
58895
  try {
58825
58896
  return await import_promises13.default.readFile(file);
58826
58897
  } catch (e) {
@@ -58830,7 +58901,7 @@ var BundleCache = class {
58830
58901
  }
58831
58902
  /** Idempotent — missing file is not an error. */
58832
58903
  async delete(snapshotHash) {
58833
- const file = import_node_path61.default.join(this.rootDir, `${snapshotHash}.zip`);
58904
+ const file = import_node_path62.default.join(this.rootDir, `${snapshotHash}.zip`);
58834
58905
  await import_promises13.default.rm(file, { force: true });
58835
58906
  }
58836
58907
  };
@@ -58855,16 +58926,16 @@ async function startDaemon(config) {
58855
58926
  });
58856
58927
  const logger = createLogger({
58857
58928
  level: config.logLevel,
58858
- file: import_node_path62.default.join(config.dataDir, "clawd.log"),
58929
+ file: import_node_path63.default.join(config.dataDir, "clawd.log"),
58859
58930
  logClient
58860
58931
  });
58861
58932
  logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
58862
58933
  const screenIdleProbeLogger = createFileOnlyLogger({
58863
- file: import_node_path62.default.join(config.dataDir, "screen-idle-probe.log"),
58934
+ file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log"),
58864
58935
  level: "debug"
58865
58936
  });
58866
58937
  logger.info("screen-idle probe logger enabled", {
58867
- file: import_node_path62.default.join(config.dataDir, "screen-idle-probe.log")
58938
+ file: import_node_path63.default.join(config.dataDir, "screen-idle-probe.log")
58868
58939
  });
58869
58940
  const stateMgr = new StateFileManager({ dataDir: config.dataDir });
58870
58941
  const pre = stateMgr.preflight();
@@ -59002,8 +59073,8 @@ async function startDaemon(config) {
59002
59073
  const agents = new AgentsScanner();
59003
59074
  const history = new ClaudeHistoryReader();
59004
59075
  let transport = null;
59005
- const personaStore = new PersonaStore(import_node_path62.default.join(config.dataDir, "personas"));
59006
- const usersRoot = import_node_path62.default.join(config.dataDir, "users");
59076
+ const personaStore = new PersonaStore(import_node_path63.default.join(config.dataDir, "personas"));
59077
+ const usersRoot = import_node_path63.default.join(config.dataDir, "users");
59007
59078
  const defaultsRoot = findDefaultsRoot(logger);
59008
59079
  if (defaultsRoot) {
59009
59080
  seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
@@ -59023,17 +59094,17 @@ async function startDaemon(config) {
59023
59094
  migrateCodexSandbox({ store: personaStore, logger });
59024
59095
  const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
59025
59096
  const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
59026
- const here = typeof __dirname === "string" ? __dirname : import_node_path62.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59097
+ const here = typeof __dirname === "string" ? __dirname : import_node_path63.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
59027
59098
  const dispatchServerCandidates = [
59028
- import_node_path62.default.join(here, "dispatch", "mcp-server.cjs"),
59099
+ import_node_path63.default.join(here, "dispatch", "mcp-server.cjs"),
59029
59100
  // 生产 dist/index → dist/dispatch/mcp-server.cjs
59030
- import_node_path62.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59101
+ import_node_path63.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
59031
59102
  // dev tsx src/index → ../dist/dispatch/mcp-server.cjs
59032
59103
  ];
59033
- const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59104
+ const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59034
59105
  let dispatchMcpConfigPath2;
59035
59106
  if (dispatchServerScriptPath) {
59036
- const dispatchLogPath = import_node_path62.default.join(config.dataDir, "dispatch-mcp-server.log");
59107
+ const dispatchLogPath = import_node_path63.default.join(config.dataDir, "dispatch-mcp-server.log");
59037
59108
  dispatchMcpConfigPath2 = writeDispatchMcpConfig({
59038
59109
  dataDir: config.dataDir,
59039
59110
  serverScriptPath: dispatchServerScriptPath,
@@ -59050,15 +59121,15 @@ async function startDaemon(config) {
59050
59121
  });
59051
59122
  }
59052
59123
  const ticketServerCandidates = [
59053
- import_node_path62.default.join(here, "ticket", "mcp-server.cjs"),
59054
- import_node_path62.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59124
+ import_node_path63.default.join(here, "ticket", "mcp-server.cjs"),
59125
+ import_node_path63.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
59055
59126
  ];
59056
- const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59127
+ const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59057
59128
  const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
59058
59129
  const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
59059
59130
  let ticketMcpConfigPath2;
59060
59131
  if (ticketServerScriptPath && ticketOwnerUnionId) {
59061
- const ticketLogPath = import_node_path62.default.join(config.dataDir, "ticket-mcp-server.log");
59132
+ const ticketLogPath = import_node_path63.default.join(config.dataDir, "ticket-mcp-server.log");
59062
59133
  ticketMcpConfigPath2 = writeTicketMcpConfig({
59063
59134
  dataDir: config.dataDir,
59064
59135
  serverScriptPath: ticketServerScriptPath,
@@ -59079,13 +59150,13 @@ async function startDaemon(config) {
59079
59150
  });
59080
59151
  }
59081
59152
  const shiftServerCandidates = [
59082
- import_node_path62.default.join(here, "shift", "mcp-server.cjs"),
59083
- import_node_path62.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59153
+ import_node_path63.default.join(here, "shift", "mcp-server.cjs"),
59154
+ import_node_path63.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
59084
59155
  ];
59085
- const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59156
+ const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59086
59157
  let shiftMcpConfigPath2;
59087
59158
  if (shiftServerScriptPath) {
59088
- const shiftLogPath = import_node_path62.default.join(config.dataDir, "shift-mcp-server.log");
59159
+ const shiftLogPath = import_node_path63.default.join(config.dataDir, "shift-mcp-server.log");
59089
59160
  shiftMcpConfigPath2 = await writeShiftMcpConfig({
59090
59161
  dataDir: config.dataDir,
59091
59162
  serverScriptPath: shiftServerScriptPath,
@@ -59103,13 +59174,13 @@ async function startDaemon(config) {
59103
59174
  );
59104
59175
  }
59105
59176
  const inboxServerCandidates = [
59106
- import_node_path62.default.join(here, "inbox", "mcp-server.cjs"),
59107
- import_node_path62.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59177
+ import_node_path63.default.join(here, "inbox", "mcp-server.cjs"),
59178
+ import_node_path63.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
59108
59179
  ];
59109
- const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
59180
+ const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs50.default.existsSync(p2));
59110
59181
  let inboxMcpConfigPath2;
59111
59182
  if (inboxServerScriptPath) {
59112
- const inboxLogPath = import_node_path62.default.join(config.dataDir, "inbox-mcp-server.log");
59183
+ const inboxLogPath = import_node_path63.default.join(config.dataDir, "inbox-mcp-server.log");
59113
59184
  inboxMcpConfigPath2 = await writeInboxMcpConfig({
59114
59185
  dataDir: config.dataDir,
59115
59186
  serverScriptPath: inboxServerScriptPath,
@@ -59127,7 +59198,7 @@ async function startDaemon(config) {
59127
59198
  );
59128
59199
  }
59129
59200
  const shiftStore = createShiftStore({
59130
- filePath: import_node_path62.default.join(config.dataDir, "shift.json"),
59201
+ filePath: import_node_path63.default.join(config.dataDir, "shift.json"),
59131
59202
  ownerIdProvider: () => ownerPrincipalId,
59132
59203
  now: () => Date.now()
59133
59204
  });
@@ -59149,7 +59220,7 @@ async function startDaemon(config) {
59149
59220
  getAdapter,
59150
59221
  historyReader: history,
59151
59222
  dataDir: config.dataDir,
59152
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59223
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59153
59224
  usersRoot,
59154
59225
  personaStore,
59155
59226
  ownerDisplayName,
@@ -59192,10 +59263,10 @@ async function startDaemon(config) {
59192
59263
  // 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
59193
59264
  attachmentGroup: {
59194
59265
  onFileEdit: (input) => {
59195
- const absPath = import_node_path62.default.isAbsolute(input.relPath) ? input.relPath : import_node_path62.default.join(input.cwd, input.relPath);
59266
+ const absPath = import_node_path63.default.isAbsolute(input.relPath) ? input.relPath : import_node_path63.default.join(input.cwd, input.relPath);
59196
59267
  let size = 0;
59197
59268
  try {
59198
- size = import_node_fs49.default.statSync(absPath).size;
59269
+ size = import_node_fs50.default.statSync(absPath).size;
59199
59270
  } catch (err) {
59200
59271
  logger.warn("attachment.onFileEdit stat failed", {
59201
59272
  sessionId: input.sessionId,
@@ -59394,11 +59465,11 @@ async function startDaemon(config) {
59394
59465
  // 'persona/<pid>/owner',default 走 'default'。
59395
59466
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
59396
59467
  // guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
59397
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59468
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59398
59469
  usersRoot
59399
59470
  },
59400
59471
  // workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
59401
- personaRoot: import_node_path62.default.join(config.dataDir, "personas"),
59472
+ personaRoot: import_node_path63.default.join(config.dataDir, "personas"),
59402
59473
  // v2 多人 persona 隔离:handler 派生 guest user-dir 放行
59403
59474
  usersRoot,
59404
59475
  // capability:list / delete handler 依赖
@@ -59420,7 +59491,7 @@ async function startDaemon(config) {
59420
59491
  contactStore,
59421
59492
  // <dataDir>/sshd 绝对路径 —— contact-ssh handlers 用它拼 authorized_keys / keys/ 子路径
59422
59493
  // Task 10 会加 SshdManager 起 sshd;handlers wire 提前挂 sshdDir 让 typecheck 过
59423
- sshdDir: import_node_path62.default.join(config.dataDir, "sshd"),
59494
+ sshdDir: import_node_path63.default.join(config.dataDir, "sshd"),
59424
59495
  contactSshLog: sshLog,
59425
59496
  // inbox:sendDm 用:sessionId → session 出身(复用 attachment 同款 findOwnedSessionScope)
59426
59497
  getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
@@ -59511,11 +59582,11 @@ async function startDaemon(config) {
59511
59582
  // 发布上线脚手架化 (spec 2026-06-03 §5.2):
59512
59583
  // appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
59513
59584
  // dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
59514
- appBuilderPersonaRoot: import_node_path62.default.join(config.dataDir, "personas", "persona-app-builder"),
59585
+ appBuilderPersonaRoot: import_node_path63.default.join(config.dataDir, "personas", "persona-app-builder"),
59515
59586
  // 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
59516
- deployKitRoot: import_node_path62.default.join(config.dataDir, "deploy-kit"),
59587
+ deployKitRoot: import_node_path63.default.join(config.dataDir, "deploy-kit"),
59517
59588
  // scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
59518
- resolvePersonaRoot: (personaId) => import_node_path62.default.join(config.dataDir, "personas", personaId),
59589
+ resolvePersonaRoot: (personaId) => import_node_path63.default.join(config.dataDir, "personas", personaId),
59519
59590
  // 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
59520
59591
  // 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
59521
59592
  // 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
@@ -59558,7 +59629,7 @@ async function startDaemon(config) {
59558
59629
  }
59559
59630
  let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
59560
59631
  if (sourceFile && sourceFile.toolSessionId) {
59561
- sourceJsonlPath = import_node_path62.default.join(
59632
+ sourceJsonlPath = import_node_path63.default.join(
59562
59633
  import_node_os21.default.homedir(),
59563
59634
  ".claude",
59564
59635
  "projects",
@@ -59888,8 +59959,8 @@ async function startDaemon(config) {
59888
59959
  const lines = [
59889
59960
  `Tunnel: ${r.url}`,
59890
59961
  ...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
59891
- `Frpc config: ${import_node_path62.default.join(config.dataDir, "frpc.toml")}`,
59892
- `Frpc log: ${import_node_path62.default.join(config.dataDir, "frpc.log")}`
59962
+ `Frpc config: ${import_node_path63.default.join(config.dataDir, "frpc.toml")}`,
59963
+ `Frpc log: ${import_node_path63.default.join(config.dataDir, "frpc.log")}`
59893
59964
  ];
59894
59965
  const width = Math.max(...lines.map((l) => l.length));
59895
59966
  const bar = "\u2550".repeat(width + 4);
@@ -59902,8 +59973,8 @@ ${bar}
59902
59973
 
59903
59974
  `);
59904
59975
  try {
59905
- const connectPath = import_node_path62.default.join(config.dataDir, "connect.txt");
59906
- import_node_fs49.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
59976
+ const connectPath = import_node_path63.default.join(config.dataDir, "connect.txt");
59977
+ import_node_fs50.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
59907
59978
  } catch {
59908
59979
  }
59909
59980
  } catch (err) {
@@ -59937,7 +60008,7 @@ ${bar}
59937
60008
  });
59938
60009
  try {
59939
60010
  await sshdMgr.start();
59940
- rebuildAuthorizedKeys(contactStore, import_node_path62.default.join(config.dataDir, "sshd"));
60011
+ rebuildAuthorizedKeys(contactStore, import_node_path63.default.join(config.dataDir, "sshd"));
59941
60012
  logger.info("sshd: contact-ssh sandbox ready", { port: config.sshdPort });
59942
60013
  } catch (err) {
59943
60014
  logger.warn("sshd start failed; contact SSH grant will not work until fixed", {
@@ -60005,9 +60076,9 @@ ${bar}
60005
60076
  };
60006
60077
  }
60007
60078
  function migrateDropPersonsDir(dataDir) {
60008
- const dir = import_node_path62.default.join(dataDir, "persons");
60079
+ const dir = import_node_path63.default.join(dataDir, "persons");
60009
60080
  try {
60010
- import_node_fs49.default.rmSync(dir, { recursive: true, force: true });
60081
+ import_node_fs50.default.rmSync(dir, { recursive: true, force: true });
60011
60082
  } catch {
60012
60083
  }
60013
60084
  }