@clawos-dev/clawd 0.2.210-beta.417.a3be9b3 → 0.2.210-beta.419.6484399

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 +461 -403
  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: path78, errorMaps, issueData } = params;
746
- const fullPath = [...path78, ...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, path78, key) {
1057
+ constructor(parent, value, path77, key) {
1058
1058
  this._cachedPath = [];
1059
1059
  this.parent = parent;
1060
1060
  this.data = value;
1061
- this._path = path78;
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 path78 = req.path;
6453
- _req.url = typeof path78 === "string" ? path78 : 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(path78) {
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 < path78.length; i++) {
6625
- const char = path78[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 path78 of paths) {
6757
- const parts = parsePath(path78);
6756
+ for (const path77 of paths) {
6757
+ const parts = parsePath(path77);
6758
6758
  if (parts.includes("*")) {
6759
- redactWildcardPath(obj, parts, censor, path78, 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, path78) => {
6845
- const fullPath = [...pathArray.slice(0, pathLength), ...path78];
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 path78 of pathsToClone) {
6881
- const parts = parsePath(path78);
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(path78) {
6934
- if (typeof path78 !== "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 (path78 === "") {
6937
+ if (path77 === "") {
6938
6938
  throw new Error("Invalid redaction path ()");
6939
6939
  }
6940
- if (path78.includes("..")) {
6941
- throw new Error(`Invalid redaction path (${path78})`);
6940
+ if (path77.includes("..")) {
6941
+ throw new Error(`Invalid redaction path (${path77})`);
6942
6942
  }
6943
- if (path78.includes(",")) {
6944
- throw new Error(`Invalid redaction path (${path78})`);
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 < path78.length; i++) {
6950
- const char = path78[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 (${path78})`);
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 (${path78})`);
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 path78 of paths) {
6977
- validatePath(path78);
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, path78) => {
7146
- return censor(value, [k2, ...path78]);
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 fs71 = require("fs");
7364
+ var fs70 = require("fs");
7365
7365
  var EventEmitter3 = require("events");
7366
7366
  var inherits = require("util").inherits;
7367
- var path78 = 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) fs71.mkdirSync(path78.dirname(file), { recursive: true });
7422
- const fd = fs71.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
- fs71.mkdir(path78.dirname(file), { recursive: true }, (err) => {
7429
+ fs70.mkdir(path77.dirname(file), { recursive: true }, (err) => {
7430
7430
  if (err) return fileOpened(err);
7431
- fs71.open(file, flags, mode, fileOpened);
7431
+ fs70.open(file, flags, mode, fileOpened);
7432
7432
  });
7433
7433
  } else {
7434
- fs71.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 = () => fs71.writeSync(this.fd, this._writingBuf);
7476
- fsWrite = () => fs71.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 fs71.writeSync(this.fd, this._writingBuf);
7485
+ return fs70.writeSync(this.fd, this._writingBuf);
7486
7486
  }
7487
- return fs71.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 fs71.write(this.fd, this._writingBuf, this.release);
7491
+ return fs70.write(this.fd, this._writingBuf, this.release);
7492
7492
  }
7493
- return fs71.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
- fs71.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
- fs71.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
- fs71.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) ? fs71.writeSync(this.fd, buf) : fs71.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
- fs71.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 = fs71.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) ? fs71.writeSync(this.fd, this._writingBuf) : fs71.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
- fs71.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 = fs71.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
- fs71.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
- fs71.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
- fs71.close(sonic.fd, done);
7925
+ fs70.close(sonic.fd, done);
7926
7926
  } else {
7927
7927
  done();
7928
7928
  }
@@ -10286,7 +10286,7 @@ var require_multistream = __commonJS({
10286
10286
  var require_pino = __commonJS({
10287
10287
  "../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
10288
10288
  "use strict";
10289
- var os24 = require("os");
10289
+ var os23 = require("os");
10290
10290
  var stdSerializers = require_pino_std_serializers();
10291
10291
  var caller = require_caller();
10292
10292
  var redaction = require_redaction();
@@ -10333,7 +10333,7 @@ var require_pino = __commonJS({
10333
10333
  } = symbols;
10334
10334
  var { epochTime, nullTime } = time;
10335
10335
  var { pid } = process;
10336
- var hostname = os24.hostname();
10336
+ var hostname = os23.hostname();
10337
10337
  var defaultErrorSerializer = stdSerializers.err;
10338
10338
  var defaultOptions = {
10339
10339
  level: "info",
@@ -11057,11 +11057,11 @@ var init_lib = __esm({
11057
11057
  }
11058
11058
  }
11059
11059
  },
11060
- addToPath: function addToPath(path78, added, removed, oldPosInc, options) {
11061
- var last = path78.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: path78.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: path78.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 path78 = 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 (!path78 || content == null) return null;
11543
- const entry = { path: path78, 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);
@@ -12004,14 +12004,6 @@ var init_claude_history = __esm({
12004
12004
  }
12005
12005
  });
12006
12006
 
12007
- // ../protocol/src/index.ts
12008
- var init_src = __esm({
12009
- "../protocol/src/index.ts"() {
12010
- "use strict";
12011
- init_runtime();
12012
- }
12013
- });
12014
-
12015
12007
  // src/tools/claude.ts
12016
12008
  function probeViaWhich() {
12017
12009
  try {
@@ -12360,10 +12352,10 @@ function parseAttachment(obj) {
12360
12352
  const memories = raw.map((m2) => {
12361
12353
  if (!m2 || typeof m2 !== "object") return null;
12362
12354
  const rec3 = m2;
12363
- const path78 = typeof rec3.path === "string" ? rec3.path : null;
12355
+ const path77 = typeof rec3.path === "string" ? rec3.path : null;
12364
12356
  const content = typeof rec3.content === "string" ? rec3.content : null;
12365
- if (!path78 || content == null) return null;
12366
- const out = { path: path78, content };
12357
+ if (!path77 || content == null) return null;
12358
+ const out = { path: path77, content };
12367
12359
  if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
12368
12360
  return out;
12369
12361
  }).filter((m2) => m2 !== null);
@@ -26835,121 +26827,6 @@ var require_dist = __commonJS({
26835
26827
  }
26836
26828
  });
26837
26829
 
26838
- // src/dispatch/peer-forward.ts
26839
- function wsUrlToHttp(url) {
26840
- if (url.startsWith("wss://")) return "https://" + url.slice("wss://".length);
26841
- if (url.startsWith("ws://")) return "http://" + url.slice("ws://".length);
26842
- return url;
26843
- }
26844
- async function forwardDispatchToPeer(args) {
26845
- const f = args.fetchImpl ?? fetch;
26846
- const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
26847
- const url = `${base}/rpc/personaDispatch:run`;
26848
- let res;
26849
- try {
26850
- res = await f(url, {
26851
- method: "POST",
26852
- headers: {
26853
- "content-type": "application/json",
26854
- authorization: `Bearer ${args.contact.connectToken}`
26855
- },
26856
- // 注意:不带 targetDeviceId —— B 端据此判定为本地执行(B 角色)。
26857
- body: JSON.stringify({ targetPersona: args.targetPersona, prompt: args.prompt })
26858
- });
26859
- } catch (err) {
26860
- const msg = err instanceof Error ? err.message : String(err);
26861
- return { kind: "failure", reason: `forward to peer failed: ${msg}` };
26862
- }
26863
- let json;
26864
- try {
26865
- json = await res.json();
26866
- } catch {
26867
- return {
26868
- kind: "failure",
26869
- reason: `peer returned non-JSON response (HTTP ${res.status})`
26870
- };
26871
- }
26872
- if (json.ok === false) {
26873
- return { kind: "failure", reason: `peer rejected: ${json.error}: ${json.message}` };
26874
- }
26875
- return json.result.outcome;
26876
- }
26877
- async function forwardInboxPostToPeer(args) {
26878
- const f = args.fetchImpl ?? fetch;
26879
- const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
26880
- const url = `${base}/rpc/inbox:postMessage`;
26881
- let res;
26882
- try {
26883
- res = await f(url, {
26884
- method: "POST",
26885
- headers: {
26886
- "content-type": "application/json",
26887
- authorization: `Bearer ${args.contact.connectToken}`
26888
- },
26889
- body: JSON.stringify({
26890
- id: args.id,
26891
- text: args.text,
26892
- createdAt: args.createdAt,
26893
- ...args.origin ? { origin: args.origin } : {}
26894
- })
26895
- });
26896
- } catch (err) {
26897
- return { ok: false, error: err instanceof Error ? err.message : String(err) };
26898
- }
26899
- let json = null;
26900
- try {
26901
- json = await res.json();
26902
- } catch {
26903
- return { ok: false, error: `peer non-JSON (HTTP ${res.status})` };
26904
- }
26905
- if (res.status < 200 || res.status >= 300 || json?.ok === false) {
26906
- return { ok: false, error: json?.error ?? `HTTP ${res.status}` };
26907
- }
26908
- return { ok: true };
26909
- }
26910
- async function forwardContactSshKeyIssueToPeer(args) {
26911
- const f = args.fetchImpl ?? fetch;
26912
- const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
26913
- const url = `${base}/rpc/contact:sshKey:issue`;
26914
- let res;
26915
- try {
26916
- res = await f(url, {
26917
- method: "POST",
26918
- headers: {
26919
- "content-type": "application/json",
26920
- authorization: `Bearer ${args.contact.connectToken}`
26921
- },
26922
- body: JSON.stringify({ deviceId: args.selfDeviceIdForRequest })
26923
- });
26924
- } catch (err) {
26925
- return {
26926
- ok: false,
26927
- code: "NETWORK",
26928
- message: err instanceof Error ? err.message : String(err)
26929
- };
26930
- }
26931
- let json = null;
26932
- try {
26933
- json = await res.json();
26934
- } catch {
26935
- return { ok: false, code: "PROTOCOL", message: `peer non-JSON (HTTP ${res.status})` };
26936
- }
26937
- if (!json) {
26938
- return { ok: false, code: "PROTOCOL", message: `peer returned null (HTTP ${res.status})` };
26939
- }
26940
- if (json.ok === false) {
26941
- const j = json;
26942
- return { ok: false, code: j.error ?? "UNKNOWN", message: j.message ?? "" };
26943
- }
26944
- const r = json.result;
26945
- return { ok: true, privateKeyPem: r.privateKeyPem, publicKeyLine: r.publicKeyLine };
26946
- }
26947
- var init_peer_forward = __esm({
26948
- "src/dispatch/peer-forward.ts"() {
26949
- "use strict";
26950
- }
26951
- });
26952
-
26953
26830
  // ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/constants.js
26954
26831
  var require_constants2 = __commonJS({
26955
26832
  "../node_modules/.pnpm/ws@8.20.0/node_modules/ws/lib/constants.js"(exports2, module2) {
@@ -27010,8 +26887,8 @@ var require_buffer_util = __commonJS({
27010
26887
  }
27011
26888
  return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.length);
27012
26889
  }
27013
- function toBuffer(data) {
27014
- toBuffer.readOnly = true;
26890
+ function toBuffer2(data) {
26891
+ toBuffer2.readOnly = true;
27015
26892
  if (Buffer.isBuffer(data)) return data;
27016
26893
  let buf;
27017
26894
  if (data instanceof ArrayBuffer) {
@@ -27020,7 +26897,7 @@ var require_buffer_util = __commonJS({
27020
26897
  buf = new FastBuffer(data.buffer, data.byteOffset, data.byteLength);
27021
26898
  } else {
27022
26899
  buf = Buffer.from(data);
27023
- toBuffer.readOnly = false;
26900
+ toBuffer2.readOnly = false;
27024
26901
  }
27025
26902
  return buf;
27026
26903
  }
@@ -27028,7 +26905,7 @@ var require_buffer_util = __commonJS({
27028
26905
  concat,
27029
26906
  mask: _mask,
27030
26907
  toArrayBuffer,
27031
- toBuffer,
26908
+ toBuffer: toBuffer2,
27032
26909
  unmask: _unmask
27033
26910
  };
27034
26911
  if (!process.env.WS_NO_BUFFER_UTIL) {
@@ -28283,7 +28160,7 @@ var require_sender = __commonJS({
28283
28160
  var PerMessageDeflate2 = require_permessage_deflate();
28284
28161
  var { EMPTY_BUFFER, kWebSocket, NOOP } = require_constants2();
28285
28162
  var { isBlob, isValidStatusCode } = require_validation();
28286
- var { mask: applyMask, toBuffer } = require_buffer_util();
28163
+ var { mask: applyMask, toBuffer: toBuffer2 } = require_buffer_util();
28287
28164
  var kByteLength = /* @__PURE__ */ Symbol("kByteLength");
28288
28165
  var maskBuffer = Buffer.alloc(4);
28289
28166
  var RANDOM_POOL_SIZE = 8 * 1024;
@@ -28471,9 +28348,9 @@ var require_sender = __commonJS({
28471
28348
  byteLength = data.size;
28472
28349
  readOnly = false;
28473
28350
  } else {
28474
- data = toBuffer(data);
28351
+ data = toBuffer2(data);
28475
28352
  byteLength = data.length;
28476
- readOnly = toBuffer.readOnly;
28353
+ readOnly = toBuffer2.readOnly;
28477
28354
  }
28478
28355
  if (byteLength > 125) {
28479
28356
  throw new RangeError("The data size must not be greater than 125 bytes");
@@ -28518,9 +28395,9 @@ var require_sender = __commonJS({
28518
28395
  byteLength = data.size;
28519
28396
  readOnly = false;
28520
28397
  } else {
28521
- data = toBuffer(data);
28398
+ data = toBuffer2(data);
28522
28399
  byteLength = data.length;
28523
- readOnly = toBuffer.readOnly;
28400
+ readOnly = toBuffer2.readOnly;
28524
28401
  }
28525
28402
  if (byteLength > 125) {
28526
28403
  throw new RangeError("The data size must not be greater than 125 bytes");
@@ -28576,9 +28453,9 @@ var require_sender = __commonJS({
28576
28453
  byteLength = data.size;
28577
28454
  readOnly = false;
28578
28455
  } else {
28579
- data = toBuffer(data);
28456
+ data = toBuffer2(data);
28580
28457
  byteLength = data.length;
28581
- readOnly = toBuffer.readOnly;
28458
+ readOnly = toBuffer2.readOnly;
28582
28459
  }
28583
28460
  if (this._firstFragment) {
28584
28461
  this._firstFragment = false;
@@ -28648,7 +28525,7 @@ var require_sender = __commonJS({
28648
28525
  return;
28649
28526
  }
28650
28527
  this._bufferedBytes -= options[kByteLength];
28651
- const data = toBuffer(arrayBuffer);
28528
+ const data = toBuffer2(arrayBuffer);
28652
28529
  if (!compress) {
28653
28530
  this._state = DEFAULT;
28654
28531
  this.sendFrame(_Sender.frame(data, options), cb);
@@ -29175,7 +29052,7 @@ var require_websocket = __commonJS({
29175
29052
  EventTarget: { addEventListener, removeEventListener }
29176
29053
  } = require_event_target();
29177
29054
  var { format, parse } = require_extension();
29178
- var { toBuffer } = require_buffer_util();
29055
+ var { toBuffer: toBuffer2 } = require_buffer_util();
29179
29056
  var kAborted = /* @__PURE__ */ Symbol("kAborted");
29180
29057
  var protocolVersions = [8, 13];
29181
29058
  var readyStates = ["CONNECTING", "OPEN", "CLOSING", "CLOSED"];
@@ -29913,7 +29790,7 @@ var require_websocket = __commonJS({
29913
29790
  }
29914
29791
  function sendAfterClose(websocket, data, cb) {
29915
29792
  if (data) {
29916
- const length = isBlob(data) ? data.size : toBuffer(data).length;
29793
+ const length = isBlob(data) ? data.size : toBuffer2(data).length;
29917
29794
  if (websocket._socket) websocket._sender._bufferedBytes += length;
29918
29795
  else websocket._bufferedAmount += length;
29919
29796
  }
@@ -33460,8 +33337,8 @@ var require_utils = __commonJS({
33460
33337
  var result = transform[inputType][outputType](input);
33461
33338
  return result;
33462
33339
  };
33463
- exports2.resolve = function(path78) {
33464
- var parts = path78.split("/");
33340
+ exports2.resolve = function(path77) {
33341
+ var parts = path77.split("/");
33465
33342
  var result = [];
33466
33343
  for (var index = 0; index < parts.length; index++) {
33467
33344
  var part = parts[index];
@@ -39314,18 +39191,18 @@ var require_object = __commonJS({
39314
39191
  var object = new ZipObject(name, zipObjectContent, o);
39315
39192
  this.files[name] = object;
39316
39193
  };
39317
- var parentFolder = function(path78) {
39318
- if (path78.slice(-1) === "/") {
39319
- path78 = path78.substring(0, path78.length - 1);
39194
+ var parentFolder = function(path77) {
39195
+ if (path77.slice(-1) === "/") {
39196
+ path77 = path77.substring(0, path77.length - 1);
39320
39197
  }
39321
- var lastSlash = path78.lastIndexOf("/");
39322
- return lastSlash > 0 ? path78.substring(0, lastSlash) : "";
39198
+ var lastSlash = path77.lastIndexOf("/");
39199
+ return lastSlash > 0 ? path77.substring(0, lastSlash) : "";
39323
39200
  };
39324
- var forceTrailingSlash = function(path78) {
39325
- if (path78.slice(-1) !== "/") {
39326
- path78 += "/";
39201
+ var forceTrailingSlash = function(path77) {
39202
+ if (path77.slice(-1) !== "/") {
39203
+ path77 += "/";
39327
39204
  }
39328
- return path78;
39205
+ return path77;
39329
39206
  };
39330
39207
  var folderAdd = function(name, createFolders) {
39331
39208
  createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
@@ -40324,49 +40201,6 @@ var require_lib3 = __commonJS({
40324
40201
  }
40325
40202
  });
40326
40203
 
40327
- // src/sshd/contact-ssh-log.ts
40328
- function createContactSshLog(dataDir) {
40329
- const file = import_node_path41.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_fs40.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
40343
- import_node_fs40.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_fs40, import_node_path41, nullContactSshLog;
40354
- var init_contact_ssh_log = __esm({
40355
- "src/sshd/contact-ssh-log.ts"() {
40356
- "use strict";
40357
- import_node_fs40 = __toESM(require("fs"), 1);
40358
- import_node_path41 = __toESM(require("path"), 1);
40359
- nullContactSshLog = {
40360
- info: () => {
40361
- },
40362
- warn: () => {
40363
- },
40364
- error: () => {
40365
- }
40366
- };
40367
- }
40368
- });
40369
-
40370
40204
  // src/run-case/recorder.ts
40371
40205
  function startRunCaseRecorder(opts) {
40372
40206
  const now = opts.now ?? Date.now;
@@ -40742,63 +40576,39 @@ async function sshRelay(argv) {
40742
40576
  process.stderr.write("clawd ssh-relay: missing <peer-device-id>\n" + SSH_RELAY_HELP);
40743
40577
  return 2;
40744
40578
  }
40745
- const dataDir = args.dataDir ?? import_node_path67.default.join(import_node_os23.default.homedir(), ".clawd");
40746
- const sshLog = createContactSshLog(dataDir);
40747
- const contact = findContact(dataDir, args.peerDeviceId);
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_path67.default.join(dataDir, "contacts.json")
40752
- });
40753
- process.stderr.write(`clawd ssh-relay: contact ${args.peerDeviceId} not found in ${dataDir}/contacts.json
40754
- `);
40579
+ const daemonUrl = process.env.CLAWD_DAEMON_URL;
40580
+ const sessionId = process.env.CLAWD_SESSION_ID;
40581
+ if (!daemonUrl) {
40582
+ process.stderr.write(
40583
+ "clawd ssh-relay: CLAWD_DAEMON_URL env not set (relay must run inside a clawd CC session)\n"
40584
+ );
40755
40585
  return 2;
40756
40586
  }
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
- });
40587
+ if (!sessionId) {
40762
40588
  process.stderr.write(
40763
- `clawd ssh-relay: contact ${args.peerDeviceId} has no connectToken (auto-reverse \u672A\u6362\u7968)
40764
- `
40589
+ "clawd ssh-relay: CLAWD_SESSION_ID env not set (relay must run inside a clawd CC session)\n"
40765
40590
  );
40766
40591
  return 2;
40767
40592
  }
40768
- const baseHttp = wsUrlToHttp(contact.remoteUrl).replace(/\/+$/, "");
40769
- const wsBase = baseHttp.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
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
- });
40593
+ const wsBase = daemonUrl.replace(/^http/, "ws").replace(/\/+$/, "");
40594
+ const url = `${wsBase}/rpc/ssh-tunnel-local?peerDeviceId=${encodeURIComponent(args.peerDeviceId)}`;
40776
40595
  return new Promise((resolve6) => {
40777
40596
  const ws = new import_websocket.default(url, {
40778
- headers: {
40779
- Authorization: `Bearer ${contact.connectToken}`
40780
- }
40597
+ headers: { "X-Clawd-Session-Id": sessionId }
40781
40598
  });
40782
- let exitCode = 0;
40783
40599
  let settled = false;
40784
40600
  const settle = (code) => {
40785
40601
  if (settled) return;
40786
40602
  settled = true;
40787
- exitCode = code;
40788
40603
  try {
40789
40604
  ws.close();
40790
40605
  } catch {
40791
40606
  }
40792
- resolve6(exitCode);
40607
+ resolve6(code);
40793
40608
  };
40794
40609
  ws.on("open", () => {
40795
- sshLog.info("relay.dial-open", "ws open\uFF0C\u8FDB\u5165 stdio \u2194 ws \u4E2D\u7EE7", {
40796
- peerDeviceId: args.peerDeviceId
40797
- });
40798
40610
  process.stdin.on("data", (chunk) => {
40799
- if (ws.readyState === ws.OPEN) {
40800
- ws.send(chunk, { binary: true });
40801
- }
40611
+ if (ws.readyState === ws.OPEN) ws.send(chunk, { binary: true });
40802
40612
  });
40803
40613
  process.stdin.on("end", () => {
40804
40614
  try {
@@ -40808,36 +40618,15 @@ async function sshRelay(argv) {
40808
40618
  });
40809
40619
  process.stdin.on("error", () => settle(1));
40810
40620
  });
40811
- ws.on("message", (data, isBinary) => {
40812
- void isBinary;
40813
- if (Buffer.isBuffer(data)) {
40814
- process.stdout.write(data);
40815
- } else if (Array.isArray(data)) {
40816
- process.stdout.write(Buffer.concat(data));
40817
- } else if (data instanceof ArrayBuffer) {
40818
- process.stdout.write(Buffer.from(data));
40819
- }
40621
+ ws.on("message", (data) => {
40622
+ if (Buffer.isBuffer(data)) process.stdout.write(data);
40623
+ else if (Array.isArray(data)) process.stdout.write(Buffer.concat(data));
40624
+ else if (data instanceof ArrayBuffer) process.stdout.write(Buffer.from(data));
40820
40625
  });
40821
40626
  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
- }
40833
40627
  settle(code === 1e3 ? 0 : 1);
40834
40628
  });
40835
40629
  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
- });
40841
40630
  process.stderr.write(`clawd ssh-relay: ws error ${err.message}
40842
40631
  `);
40843
40632
  settle(1);
@@ -40855,10 +40644,6 @@ function parseSshRelayArgs(argv) {
40855
40644
  out.help = true;
40856
40645
  continue;
40857
40646
  }
40858
- if (a === "--data-dir") {
40859
- out.dataDir = argv[++i];
40860
- continue;
40861
- }
40862
40647
  if (a.startsWith("--")) {
40863
40648
  throw new Error(`unknown flag: ${a}`);
40864
40649
  }
@@ -40868,50 +40653,22 @@ function parseSshRelayArgs(argv) {
40868
40653
  }
40869
40654
  return out;
40870
40655
  }
40871
- function findContact(dataDir, deviceId) {
40872
- const file = import_node_path67.default.join(dataDir, "contacts.json");
40873
- let raw;
40874
- try {
40875
- raw = import_node_fs54.default.readFileSync(file, "utf8");
40876
- } catch {
40877
- return null;
40878
- }
40879
- let json;
40880
- try {
40881
- json = JSON.parse(raw);
40882
- } catch {
40883
- return null;
40884
- }
40885
- const arr = json?.contacts;
40886
- if (!Array.isArray(arr)) return null;
40887
- for (const entry of arr) {
40888
- const r = ContactSchema.safeParse(entry);
40889
- if (r.success && r.data.deviceId === deviceId) return r.data;
40890
- }
40891
- return null;
40892
- }
40893
- var import_node_fs54, import_node_os23, import_node_path67, SSH_RELAY_HELP;
40656
+ var SSH_RELAY_HELP;
40894
40657
  var init_sshd_cli_relay = __esm({
40895
40658
  "src/sshd/sshd-cli-relay.ts"() {
40896
40659
  "use strict";
40897
- import_node_fs54 = __toESM(require("fs"), 1);
40898
- import_node_os23 = __toESM(require("os"), 1);
40899
- import_node_path67 = __toESM(require("path"), 1);
40900
40660
  init_wrapper();
40901
- init_src();
40902
- init_peer_forward();
40903
- init_contact_ssh_log();
40904
- SSH_RELAY_HELP = `clawd ssh-relay <peer-device-id> [options]
40661
+ SSH_RELAY_HELP = `clawd ssh-relay <peer-device-id>
40905
40662
 
40906
- WebSocket relay to a peer daemon's /rpc/ssh-tunnel, exposing raw SSH bytes on
40907
- stdio. Meant to be used as SSH ProxyCommand.
40663
+ WebSocket relay to a peer daemon's /rpc/ssh-tunnel via the local daemon
40664
+ (reads CLAWD_DAEMON_URL + CLAWD_SESSION_ID from env). Meant to be used as
40665
+ SSH ProxyCommand from inside a clawd CC session.
40908
40666
 
40909
40667
  Options:
40910
- --data-dir <path> \u6570\u636E\u76EE\u5F55\uFF08\u9ED8\u8BA4 ~/.clawd\uFF09
40911
40668
  --help / -h \u663E\u793A\u5E2E\u52A9
40912
40669
 
40913
40670
  Example:
40914
- ssh -o ProxyCommand='clawd ssh-relay <peer-device-id>' \\
40671
+ ssh -o ProxyCommand='~/.clawd/bin/clawd ssh-relay <peer-device-id>' \\
40915
40672
  -i ~/.clawd/contact-ssh-keys/<peer-device-id>.ed25519 \\
40916
40673
  $USER@127.0.0.1
40917
40674
  `;
@@ -41086,9 +40843,11 @@ Subcommands:
41086
40843
  \u72EC\u7ACB CC \u63A7\u5236\u5668\u8FDB\u7A0B\uFF1A\u5916\u90E8 AI \u901A\u8FC7 stdin/stdout \u884C JSON \u534F\u8BAE
41087
40844
  \u9A71\u52A8 CC \u591A\u8F6E\u5BF9\u8BDD\u4E0E\u6743\u9650\u51B3\u7B56\uFF0CIPC \u5168\u7A0B\u5F55\u5230 --record JSONL\u3002
41088
40845
  \u8BE6\u89C1 'clawd run-case --help'
41089
- ssh-relay <peer-device-id> [--data-dir <path>]
41090
- WebSocket relay to peer daemon's /rpc/ssh-tunnel\uFF0C\u4F5C\u4E3A SSH
41091
- ProxyCommand \u4F7F\u7528\uFF08Contact SSH tunnel\uFF0CPR#2\uFF09\u3002
40846
+ ssh-relay <peer-device-id>
40847
+ WebSocket relay via local daemon (reads
40848
+ CLAWD_DAEMON_URL + CLAWD_SESSION_ID from env)
40849
+ to peer /rpc/ssh-tunnel\uFF0C\u4F5C\u4E3A SSH ProxyCommand
40850
+ \u4F7F\u7528\uFF08Contact SSH tunnel v2\uFF09\u3002
41092
40851
  \u8BE6\u89C1 'clawd ssh-relay --help'
41093
40852
 
41094
40853
  Env (advanced):
@@ -41814,12 +41573,13 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
41814
41573
  fsv.allowWrite = unionArr(fsv.allowWrite, [userWorkDir]);
41815
41574
  fsv.allowRead = unionArr(fsv.allowRead, [
41816
41575
  "~/.clawd/contact-ssh-keys",
41817
- "~/.clawd/contacts.json",
41818
41576
  "~/.clawd/bin",
41819
41577
  "~/Library/Application Support/@clawos/clawd-desktop/ota-bundles",
41820
41578
  "~/.clawd/config.json",
41821
41579
  "~/.clawd/auth.json"
41822
41580
  ]);
41581
+ const netv = s.sandbox.network ?? (s.sandbox.network = {});
41582
+ netv.allowedDomains = unionArr(netv.allowedDomains, ["*.tunnel.clawos.chat"]);
41823
41583
  return s;
41824
41584
  }
41825
41585
 
@@ -46352,7 +46112,11 @@ function tryLoadShareUi(logger) {
46352
46112
 
46353
46113
  // src/visitor/visitor-token.ts
46354
46114
  var import_node_crypto4 = __toESM(require("crypto"), 1);
46355
- init_src();
46115
+
46116
+ // ../protocol/src/index.ts
46117
+ init_runtime();
46118
+
46119
+ // src/visitor/visitor-token.ts
46356
46120
  function hmac(secret, body) {
46357
46121
  return import_node_crypto4.default.createHmac("sha256", secret).update(body).digest("base64url");
46358
46122
  }
@@ -46709,8 +46473,8 @@ function turnStartInput(text) {
46709
46473
  const items = [];
46710
46474
  let leftover = text;
46711
46475
  for (const m2 of text.matchAll(SKILL_RE)) {
46712
- const [marker, name, path78] = m2;
46713
- items.push({ type: "skill", name, path: path78 });
46476
+ const [marker, name, path77] = m2;
46477
+ items.push({ type: "skill", name, path: path77 });
46714
46478
  leftover = leftover.replace(marker, "");
46715
46479
  }
46716
46480
  for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
@@ -48975,8 +48739,115 @@ function buildPersonaDispatchHandlers(deps) {
48975
48739
  };
48976
48740
  }
48977
48741
 
48978
- // src/index.ts
48979
- init_peer_forward();
48742
+ // src/dispatch/peer-forward.ts
48743
+ function wsUrlToHttp(url) {
48744
+ if (url.startsWith("wss://")) return "https://" + url.slice("wss://".length);
48745
+ if (url.startsWith("ws://")) return "http://" + url.slice("ws://".length);
48746
+ return url;
48747
+ }
48748
+ async function forwardDispatchToPeer(args) {
48749
+ const f = args.fetchImpl ?? fetch;
48750
+ const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
48751
+ const url = `${base}/rpc/personaDispatch:run`;
48752
+ let res;
48753
+ try {
48754
+ res = await f(url, {
48755
+ method: "POST",
48756
+ headers: {
48757
+ "content-type": "application/json",
48758
+ authorization: `Bearer ${args.contact.connectToken}`
48759
+ },
48760
+ // 注意:不带 targetDeviceId —— B 端据此判定为本地执行(B 角色)。
48761
+ body: JSON.stringify({ targetPersona: args.targetPersona, prompt: args.prompt })
48762
+ });
48763
+ } catch (err) {
48764
+ const msg = err instanceof Error ? err.message : String(err);
48765
+ return { kind: "failure", reason: `forward to peer failed: ${msg}` };
48766
+ }
48767
+ let json;
48768
+ try {
48769
+ json = await res.json();
48770
+ } catch {
48771
+ return {
48772
+ kind: "failure",
48773
+ reason: `peer returned non-JSON response (HTTP ${res.status})`
48774
+ };
48775
+ }
48776
+ if (json.ok === false) {
48777
+ return { kind: "failure", reason: `peer rejected: ${json.error}: ${json.message}` };
48778
+ }
48779
+ return json.result.outcome;
48780
+ }
48781
+ async function forwardInboxPostToPeer(args) {
48782
+ const f = args.fetchImpl ?? fetch;
48783
+ const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
48784
+ const url = `${base}/rpc/inbox:postMessage`;
48785
+ let res;
48786
+ try {
48787
+ res = await f(url, {
48788
+ method: "POST",
48789
+ headers: {
48790
+ "content-type": "application/json",
48791
+ authorization: `Bearer ${args.contact.connectToken}`
48792
+ },
48793
+ body: JSON.stringify({
48794
+ id: args.id,
48795
+ text: args.text,
48796
+ createdAt: args.createdAt,
48797
+ ...args.origin ? { origin: args.origin } : {}
48798
+ })
48799
+ });
48800
+ } catch (err) {
48801
+ return { ok: false, error: err instanceof Error ? err.message : String(err) };
48802
+ }
48803
+ let json = null;
48804
+ try {
48805
+ json = await res.json();
48806
+ } catch {
48807
+ return { ok: false, error: `peer non-JSON (HTTP ${res.status})` };
48808
+ }
48809
+ if (res.status < 200 || res.status >= 300 || json?.ok === false) {
48810
+ return { ok: false, error: json?.error ?? `HTTP ${res.status}` };
48811
+ }
48812
+ return { ok: true };
48813
+ }
48814
+ async function forwardContactSshKeyIssueToPeer(args) {
48815
+ const f = args.fetchImpl ?? fetch;
48816
+ const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
48817
+ const url = `${base}/rpc/contact:sshKey:issue`;
48818
+ let res;
48819
+ try {
48820
+ res = await f(url, {
48821
+ method: "POST",
48822
+ headers: {
48823
+ "content-type": "application/json",
48824
+ authorization: `Bearer ${args.contact.connectToken}`
48825
+ },
48826
+ body: JSON.stringify({ deviceId: args.selfDeviceIdForRequest })
48827
+ });
48828
+ } catch (err) {
48829
+ return {
48830
+ ok: false,
48831
+ code: "NETWORK",
48832
+ message: err instanceof Error ? err.message : String(err)
48833
+ };
48834
+ }
48835
+ let json = null;
48836
+ try {
48837
+ json = await res.json();
48838
+ } catch {
48839
+ return { ok: false, code: "PROTOCOL", message: `peer non-JSON (HTTP ${res.status})` };
48840
+ }
48841
+ if (!json) {
48842
+ return { ok: false, code: "PROTOCOL", message: `peer returned null (HTTP ${res.status})` };
48843
+ }
48844
+ if (json.ok === false) {
48845
+ const j = json;
48846
+ return { ok: false, code: j.error ?? "UNKNOWN", message: j.message ?? "" };
48847
+ }
48848
+ const r = json.result;
48849
+ return { ok: true, privateKeyPem: r.privateKeyPem, publicKeyLine: r.publicKeyLine };
48850
+ }
48980
48851
 
48981
48852
  // src/tools/codex-history.ts
48982
48853
  var import_node_child_process5 = require("child_process");
@@ -49164,13 +49035,13 @@ function mapSkillsListResponse(res) {
49164
49035
  const r = s ?? {};
49165
49036
  const name = str3(r.name);
49166
49037
  if (!name) continue;
49167
- const path78 = str3(r.path);
49038
+ const path77 = str3(r.path);
49168
49039
  const description = str3(r.description);
49169
49040
  const isPlugin = name.includes(":");
49170
49041
  out.push({
49171
49042
  name,
49172
49043
  source: isPlugin ? "plugin" : "project",
49173
- ...path78 ? { path: path78 } : {},
49044
+ ...path77 ? { path: path77 } : {},
49174
49045
  ...description ? { description } : {},
49175
49046
  ...isPlugin ? { plugin: name.split(":")[0] } : {}
49176
49047
  });
@@ -49908,6 +49779,18 @@ var LocalWsServer = class {
49908
49779
  return;
49909
49780
  }
49910
49781
  }
49782
+ if (this.opts.sshTunnelLocalUpgradeHandler) {
49783
+ const [urlPath] = (req.url ?? "").split("?");
49784
+ if (urlPath === "/rpc/ssh-tunnel-local") {
49785
+ void this.opts.sshTunnelLocalUpgradeHandler(
49786
+ req,
49787
+ socket,
49788
+ head,
49789
+ wss
49790
+ );
49791
+ return;
49792
+ }
49793
+ }
49911
49794
  if (req.url?.startsWith("/preview/")) {
49912
49795
  const pathname = (() => {
49913
49796
  try {
@@ -50480,7 +50363,6 @@ function constantTimeEqual2(a, b2) {
50480
50363
  }
50481
50364
 
50482
50365
  // src/transport/connection-context.ts
50483
- init_src();
50484
50366
  function ownerContext(ownerPrincipalId, displayName) {
50485
50367
  return {
50486
50368
  principal: makeOwnerPrincipal(ownerPrincipalId, displayName),
@@ -50534,7 +50416,6 @@ async function authenticate(token, deps) {
50534
50416
  // src/permission/capability-store.ts
50535
50417
  var fs29 = __toESM(require("fs"), 1);
50536
50418
  var path29 = __toESM(require("path"), 1);
50537
- init_src();
50538
50419
  var CAPABILITIES_FILE_NAME = "capabilities.json";
50539
50420
  var FILE_VERSION = 1;
50540
50421
  var CapabilityStore = class {
@@ -50712,7 +50593,6 @@ function cleanupGuestSessionsForCapability(cap, factory) {
50712
50593
  // src/inbox/inbox-store.ts
50713
50594
  var fs31 = __toESM(require("fs"), 1);
50714
50595
  var path30 = __toESM(require("path"), 1);
50715
- init_src();
50716
50596
  var INBOX_SUBDIR = "inbox";
50717
50597
  var InboxStore = class {
50718
50598
  constructor(dataDir) {
@@ -50903,7 +50783,6 @@ var InboxManager = class {
50903
50783
  // src/state/contact-store.ts
50904
50784
  var fs32 = __toESM(require("fs"), 1);
50905
50785
  var path31 = __toESM(require("path"), 1);
50906
- init_src();
50907
50786
  var FILE_NAME = "contacts.json";
50908
50787
  var ContactStore = class {
50909
50788
  constructor(dataDir) {
@@ -51154,9 +51033,6 @@ async function autoReverseContact(args) {
51154
51033
  args.broadcast({ type: "contact:added", contact: upgraded });
51155
51034
  }
51156
51035
 
51157
- // src/index.ts
51158
- init_src();
51159
-
51160
51036
  // src/migrations/2026-05-20-flatten-sessions.ts
51161
51037
  var fs33 = __toESM(require("fs"), 1);
51162
51038
  var path32 = __toESM(require("path"), 1);
@@ -51539,7 +51415,6 @@ var import_promises3 = __toESM(require("fs/promises"), 1);
51539
51415
  var import_node_path27 = __toESM(require("path"), 1);
51540
51416
  var import_node_os12 = __toESM(require("os"), 1);
51541
51417
  var import_jszip = __toESM(require_lib3(), 1);
51542
- init_src();
51543
51418
  var ImportError = class extends Error {
51544
51419
  constructor(code, message) {
51545
51420
  super(message);
@@ -53674,8 +53549,45 @@ function readIssuedPubkey(sshdDir, deviceId) {
53674
53549
  // src/sshd/contact-key-puller.ts
53675
53550
  var import_node_fs41 = __toESM(require("fs"), 1);
53676
53551
  var import_node_path42 = __toESM(require("path"), 1);
53677
- init_peer_forward();
53678
- init_contact_ssh_log();
53552
+
53553
+ // src/sshd/contact-ssh-log.ts
53554
+ var import_node_fs40 = __toESM(require("fs"), 1);
53555
+ var import_node_path41 = __toESM(require("path"), 1);
53556
+ function createContactSshLog(dataDir) {
53557
+ const file = import_node_path41.default.join(dataDir, "contact-ssh.log");
53558
+ function append(level, tag, message, meta) {
53559
+ const time = (/* @__PURE__ */ new Date()).toISOString();
53560
+ let line = `[${time}] [${level}] [${tag}] ${message}`;
53561
+ if (meta && Object.keys(meta).length > 0) {
53562
+ try {
53563
+ line += " " + JSON.stringify(meta);
53564
+ } catch {
53565
+ line += " [meta-serialize-failed]";
53566
+ }
53567
+ }
53568
+ line += "\n";
53569
+ try {
53570
+ import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
53571
+ import_node_fs40.default.appendFileSync(file, line, { mode: 384 });
53572
+ } catch {
53573
+ }
53574
+ }
53575
+ return {
53576
+ info: (tag, message, meta) => append("INFO", tag, message, meta),
53577
+ warn: (tag, message, meta) => append("WARN", tag, message, meta),
53578
+ error: (tag, message, meta) => append("ERROR", tag, message, meta)
53579
+ };
53580
+ }
53581
+ var nullContactSshLog = {
53582
+ info: () => {
53583
+ },
53584
+ warn: () => {
53585
+ },
53586
+ error: () => {
53587
+ }
53588
+ };
53589
+
53590
+ // src/sshd/contact-key-puller.ts
53679
53591
  var CONTACT_KEYS_DIR = "contact-ssh-keys";
53680
53592
  function safeContactKeyPath(dataDir, deviceId) {
53681
53593
  const safeId = deviceId.replace(/[\/\\]/g, "_");
@@ -53787,7 +53699,6 @@ var ContactKeyPuller = class {
53787
53699
 
53788
53700
  // src/sshd/ssh-tunnel-relay.ts
53789
53701
  var import_node_net2 = __toESM(require("net"), 1);
53790
- init_contact_ssh_log();
53791
53702
  async function handleSshTunnelUpgrade(req, socket, head, deps) {
53792
53703
  const sshLog = deps.sshLog ?? nullContactSshLog;
53793
53704
  const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
@@ -53895,8 +53806,161 @@ function pumpWsToSshd(ws, deps, clientAddr) {
53895
53806
  });
53896
53807
  }
53897
53808
 
53898
- // src/index.ts
53899
- init_contact_ssh_log();
53809
+ // src/sshd/ssh-tunnel-local-relay.ts
53810
+ init_wrapper();
53811
+ function parsePeerDeviceId(rawUrl) {
53812
+ if (!rawUrl) return null;
53813
+ try {
53814
+ const u = new URL(rawUrl, "http://127.0.0.1");
53815
+ const v2 = u.searchParams.get("peerDeviceId");
53816
+ return v2 && v2.length > 0 ? v2 : null;
53817
+ } catch {
53818
+ return null;
53819
+ }
53820
+ }
53821
+ async function handleSshTunnelLocalUpgrade(req, socket, head, deps) {
53822
+ const sshLog = deps.sshLog ?? nullContactSshLog;
53823
+ const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
53824
+ const sessionId = req.headers["x-clawd-session-id"] ?? "";
53825
+ if (!sessionId) {
53826
+ sshLog.warn("relay.auth-failed", "/rpc/ssh-tunnel-local \u7F3A X-Clawd-Session-Id header", {
53827
+ clientAddr
53828
+ });
53829
+ respond401(socket);
53830
+ return;
53831
+ }
53832
+ const peerDeviceId = parsePeerDeviceId(req.url);
53833
+ if (!peerDeviceId) {
53834
+ sshLog.warn("relay.auth-failed", "/rpc/ssh-tunnel-local \u7F3A peerDeviceId query", { clientAddr });
53835
+ respond400(socket);
53836
+ return;
53837
+ }
53838
+ const contact = deps.store.get(peerDeviceId);
53839
+ if (!contact) {
53840
+ sshLog.error("relay.contact-not-found", "ssh-tunnel-local \u627E\u4E0D\u5230 peer contact", {
53841
+ peerDeviceId
53842
+ });
53843
+ respond404(socket);
53844
+ return;
53845
+ }
53846
+ if (!contact.connectToken) {
53847
+ sshLog.error(
53848
+ "relay.token-missing",
53849
+ "contact \u6709\u8BB0\u5F55\u4F46\u7F3A connectToken\uFF08auto-reverse \u672A\u6362\u7968\uFF09",
53850
+ { peerDeviceId, peerDisplayName: contact.displayName }
53851
+ );
53852
+ respond403(socket);
53853
+ return;
53854
+ }
53855
+ const baseHttp = wsUrlToHttp(contact.remoteUrl).replace(/\/+$/, "");
53856
+ const wsBase = baseHttp.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
53857
+ const outboundUrl = `${wsBase}/rpc/ssh-tunnel`;
53858
+ sshLog.info("relay.dial", "\u5F00\u59CB\u62E8 A \u4FA7 /rpc/ssh-tunnel", {
53859
+ peerDeviceId,
53860
+ peerDisplayName: contact.displayName,
53861
+ url: outboundUrl
53862
+ });
53863
+ deps.wss.handleUpgrade(req, socket, head, (clientWs) => {
53864
+ const makeOut = deps.makeOutboundWs ?? ((u, o) => new import_websocket.default(u, o));
53865
+ const outbound = makeOut(outboundUrl, {
53866
+ headers: { Authorization: `Bearer ${contact.connectToken}` }
53867
+ });
53868
+ pumpClientToOutbound(clientWs, outbound, peerDeviceId, contact.displayName, deps);
53869
+ });
53870
+ }
53871
+ function pumpClientToOutbound(client, outbound, peerDeviceId, peerDisplayName, deps) {
53872
+ const sshLog = deps.sshLog ?? nullContactSshLog;
53873
+ const startedAt = Date.now();
53874
+ let outboundOpened = false;
53875
+ let bytesClientToOutbound = 0;
53876
+ let bytesOutboundToClient = 0;
53877
+ let settled = false;
53878
+ const cleanup = (reason, code = 1e3) => {
53879
+ if (settled) return;
53880
+ settled = true;
53881
+ try {
53882
+ client.close(code, reason);
53883
+ } catch {
53884
+ }
53885
+ try {
53886
+ outbound.close();
53887
+ } catch {
53888
+ }
53889
+ const level = code === 1e3 ? "info" : "warn";
53890
+ sshLog[level](
53891
+ code === 1e3 ? "relay.dial-close" : "relay.dial-close-abnormal",
53892
+ code === 1e3 ? "tunnel \u4F1A\u8BDD\u6B63\u5E38\u7ED3\u675F" : "tunnel \u4F1A\u8BDD\u975E\u6B63\u5E38\u5173\u95ED",
53893
+ {
53894
+ peerDeviceId,
53895
+ peerDisplayName,
53896
+ reason,
53897
+ code,
53898
+ outboundOpened,
53899
+ bytesClientToOutbound,
53900
+ bytesOutboundToClient,
53901
+ durationMs: Date.now() - startedAt
53902
+ }
53903
+ );
53904
+ };
53905
+ outbound.on("open", () => {
53906
+ outboundOpened = true;
53907
+ sshLog.info("relay.dial-open", "outbound ws open\uFF0C\u8FDB\u5165\u53CC\u5411 pipe", {
53908
+ peerDeviceId,
53909
+ peerDisplayName
53910
+ });
53911
+ });
53912
+ outbound.on("message", (data) => {
53913
+ const buf = toBuffer(data);
53914
+ if (!buf) return;
53915
+ bytesOutboundToClient += buf.length;
53916
+ if (client.readyState === client.OPEN) client.send(buf, { binary: true });
53917
+ });
53918
+ outbound.on("error", (err) => {
53919
+ deps.logger?.warn("ssh-tunnel-local: outbound ws error", { err: err.message });
53920
+ sshLog.error("relay.dial-error", "outbound ws \u8FDE\u63A5\u9519\u8BEF\uFF08peer \u4E0D\u53EF\u8FBE / TLS \u5931\u8D25\uFF09", {
53921
+ peerDeviceId,
53922
+ peerDisplayName,
53923
+ message: err.message
53924
+ });
53925
+ cleanup("outbound error", 1011);
53926
+ });
53927
+ outbound.on("close", (code) => {
53928
+ if (!settled) cleanup(`outbound close ${code}`, code === 1e3 ? 1e3 : 1011);
53929
+ });
53930
+ client.on("message", (data) => {
53931
+ const buf = toBuffer(data);
53932
+ if (!buf) return;
53933
+ bytesClientToOutbound += buf.length;
53934
+ if (outbound.readyState === outbound.OPEN) outbound.send(buf, { binary: true });
53935
+ });
53936
+ client.on("close", () => cleanup("client close", 1e3));
53937
+ client.on("error", (err) => {
53938
+ deps.logger?.warn("ssh-tunnel-local: client ws error", { err: err.message });
53939
+ cleanup("client error", 1011);
53940
+ });
53941
+ }
53942
+ function toBuffer(data) {
53943
+ if (Buffer.isBuffer(data)) return data;
53944
+ if (Array.isArray(data)) return Buffer.concat(data);
53945
+ if (data instanceof ArrayBuffer) return Buffer.from(data);
53946
+ return null;
53947
+ }
53948
+ function respond401(socket) {
53949
+ socket.write("HTTP/1.1 401 Unauthorized\r\nContent-Length: 0\r\n\r\n");
53950
+ socket.destroy();
53951
+ }
53952
+ function respond400(socket) {
53953
+ socket.write("HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
53954
+ socket.destroy();
53955
+ }
53956
+ function respond403(socket) {
53957
+ socket.write("HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n");
53958
+ socket.destroy();
53959
+ }
53960
+ function respond404(socket) {
53961
+ socket.write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
53962
+ socket.destroy();
53963
+ }
53900
53964
 
53901
53965
  // src/tunnel/device-key.ts
53902
53966
  var import_node_os14 = __toESM(require("os"), 1);
@@ -54186,9 +54250,9 @@ var CentralClientError = class extends Error {
54186
54250
  code;
54187
54251
  cause;
54188
54252
  };
54189
- async function centralRequest(opts, path78, init) {
54253
+ async function centralRequest(opts, path77, init) {
54190
54254
  const f = opts.fetchImpl ?? globalThis.fetch;
54191
- const url = `${opts.api.replace(/\/+$/, "")}${path78}`;
54255
+ const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
54192
54256
  const ctrl = new AbortController();
54193
54257
  const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
54194
54258
  let res;
@@ -55178,7 +55242,6 @@ function buildCapabilitiesHandlers(deps) {
55178
55242
 
55179
55243
  // src/handlers/capability.ts
55180
55244
  init_zod();
55181
- init_src();
55182
55245
  init_protocol();
55183
55246
  var DeleteArgsSchema = external_exports.object({
55184
55247
  capabilityId: external_exports.string().min(1)
@@ -55217,7 +55280,6 @@ function buildCapabilityHandlers(deps) {
55217
55280
  }
55218
55281
 
55219
55282
  // src/handlers/inbox.ts
55220
- init_src();
55221
55283
  init_protocol();
55222
55284
  function resolvePeerDeviceId(ctx, argsPeerDeviceId) {
55223
55285
  if (ctx.principal.kind === "owner") {
@@ -55396,7 +55458,6 @@ function buildInboxHandlers(deps) {
55396
55458
  }
55397
55459
 
55398
55460
  // src/handlers/contact.ts
55399
- init_src();
55400
55461
  init_protocol();
55401
55462
  function ensureOwner(ctx) {
55402
55463
  if (!ctx || ctx.principal.kind !== "owner") {
@@ -55465,7 +55526,6 @@ function buildContactHandlers(deps) {
55465
55526
  }
55466
55527
 
55467
55528
  // src/handlers/contact-ssh.ts
55468
- init_src();
55469
55529
  init_protocol();
55470
55530
 
55471
55531
  // src/sshd/key-issue.ts
@@ -55512,7 +55572,6 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
55512
55572
  }
55513
55573
 
55514
55574
  // src/handlers/contact-ssh.ts
55515
- init_contact_ssh_log();
55516
55575
  function ensureOwner2(ctx) {
55517
55576
  if (!ctx || ctx.principal.kind !== "owner") {
55518
55577
  throw new ClawdError(
@@ -55615,7 +55674,6 @@ function buildContactSshHandlers(deps) {
55615
55674
  }
55616
55675
 
55617
55676
  // src/handlers/whoami.ts
55618
- init_src();
55619
55677
  init_protocol();
55620
55678
  function buildWhoamiHandler(deps) {
55621
55679
  return async (_frame, _client, ctx) => {
@@ -55709,7 +55767,6 @@ function buildFeishuAuthHandlers(deps) {
55709
55767
  }
55710
55768
 
55711
55769
  // src/handlers/device.ts
55712
- init_src();
55713
55770
  init_protocol();
55714
55771
  function ensureOwner3(ctx) {
55715
55772
  if (!ctx || ctx.principal.kind !== "owner") {
@@ -56114,7 +56171,6 @@ function buildAttachmentHandlers(deps) {
56114
56171
  var import_promises8 = __toESM(require("fs/promises"), 1);
56115
56172
  var import_node_path55 = __toESM(require("path"), 1);
56116
56173
  init_protocol();
56117
- init_src();
56118
56174
 
56119
56175
  // src/extension/bundle-zip.ts
56120
56176
  var import_promises5 = __toESM(require("fs/promises"), 1);
@@ -56160,8 +56216,6 @@ async function walk(absRoot, relPrefix, out) {
56160
56216
  }
56161
56217
 
56162
56218
  // src/extension/publish-check.ts
56163
- init_src();
56164
- init_src();
56165
56219
  function computePublishCheck(args) {
56166
56220
  const { localHash, localVersion, head } = args;
56167
56221
  if (head === null) {
@@ -56206,12 +56260,10 @@ var import_node_path53 = __toESM(require("path"), 1);
56206
56260
  var import_node_os19 = __toESM(require("os"), 1);
56207
56261
  var import_node_crypto15 = __toESM(require("crypto"), 1);
56208
56262
  var import_jszip3 = __toESM(require_lib3(), 1);
56209
- init_src();
56210
56263
 
56211
56264
  // src/extension/paths.ts
56212
56265
  var import_node_os18 = __toESM(require("os"), 1);
56213
56266
  var import_node_path52 = __toESM(require("path"), 1);
56214
- init_src();
56215
56267
  function clawdHomeRoot(override) {
56216
56268
  return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
56217
56269
  }
@@ -56329,7 +56381,6 @@ var import_node_path54 = __toESM(require("path"), 1);
56329
56381
  var import_node_os20 = __toESM(require("os"), 1);
56330
56382
  var import_node_crypto16 = __toESM(require("crypto"), 1);
56331
56383
  var import_jszip4 = __toESM(require_lib3(), 1);
56332
- init_src();
56333
56384
  var UpdateError = class extends Error {
56334
56385
  constructor(code, message) {
56335
56386
  super(message);
@@ -56475,7 +56526,6 @@ async function rollback(deps, localExtId, liveDir, prevDir) {
56475
56526
  }
56476
56527
 
56477
56528
  // src/handlers/extension.ts
56478
- init_src();
56479
56529
  function pickChannelRef(frame) {
56480
56530
  const ref = frame.channelRef;
56481
56531
  const parsed = ChannelRefSchema.safeParse(ref);
@@ -57966,7 +58016,6 @@ function buildVisitorHandlers(deps) {
57966
58016
  // src/extension/registry.ts
57967
58017
  var import_promises9 = __toESM(require("fs/promises"), 1);
57968
58018
  var import_node_path59 = __toESM(require("path"), 1);
57969
- init_src();
57970
58019
  async function loadAll(root) {
57971
58020
  let entries;
57972
58021
  try {
@@ -58051,7 +58100,6 @@ async function uninstall(deps) {
58051
58100
 
58052
58101
  // src/handlers/index.ts
58053
58102
  var import_node_crypto18 = require("crypto");
58054
- init_peer_forward();
58055
58103
  function buildMethodHandlers(deps) {
58056
58104
  return {
58057
58105
  ...buildSessionHandlers({
@@ -58625,7 +58673,6 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
58625
58673
  var import_node_child_process18 = require("child_process");
58626
58674
  var import_node_path61 = __toESM(require("path"), 1);
58627
58675
  var import_promises11 = require("timers/promises");
58628
- init_src();
58629
58676
 
58630
58677
  // src/extension/port-allocator.ts
58631
58678
  var import_node_net3 = __toESM(require("net"), 1);
@@ -58838,7 +58885,6 @@ ${handle.stderrTail}`
58838
58885
  // src/extension/published-channels.ts
58839
58886
  var import_promises12 = __toESM(require("fs/promises"), 1);
58840
58887
  var import_node_path62 = __toESM(require("path"), 1);
58841
- init_src();
58842
58888
  init_zod();
58843
58889
  var PublishedChannelsError = class extends Error {
58844
58890
  constructor(code, message) {
@@ -59918,6 +59964,18 @@ async function startDaemon(config) {
59918
59964
  });
59919
59965
  return true;
59920
59966
  },
59967
+ // Contact SSH relay v2 (spec 2026-07-06-contact-ssh-relay-via-local-daemon-tunnel):
59968
+ // /rpc/ssh-tunnel-local WS 前置拦截。guest CC 沙箱从 localhost 连本地 daemon,daemon
59969
+ // 代理起 outbound wss 到 peer /rpc/ssh-tunnel。findContact / connectToken 处理下沉到
59970
+ // 本 handler;relay CLI 变纯粹的 stdio ↔ local WS pump(不再读 contacts.json / 持 token)。
59971
+ sshTunnelLocalUpgradeHandler: async (req, socket, head, wss2) => {
59972
+ await handleSshTunnelLocalUpgrade(req, socket, head, {
59973
+ wss: wss2,
59974
+ store: contactStore,
59975
+ logger,
59976
+ sshLog
59977
+ });
59978
+ },
59921
59979
  // 订阅成功后给该 client 重放 in-flight pendingQuestions(plan: clawd-question-server-truth)。
59922
59980
  // daemon 是 pendingQuestions 的唯一 source of truth;新 client 接入 / 刷新页面时
59923
59981
  // 把当前所有未决 question 以 session:question 帧定向回放,让 UI 不再误显示 Ended。