@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.
- package/dist/cli.cjs +461 -403
- 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:
|
|
746
|
-
const fullPath = [...
|
|
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,
|
|
1057
|
+
constructor(parent, value, path77, key) {
|
|
1058
1058
|
this._cachedPath = [];
|
|
1059
1059
|
this.parent = parent;
|
|
1060
1060
|
this.data = value;
|
|
1061
|
-
this._path =
|
|
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
|
|
6453
|
-
_req.url = typeof
|
|
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(
|
|
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 <
|
|
6625
|
-
const char =
|
|
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
|
|
6757
|
-
const parts = parsePath(
|
|
6756
|
+
for (const path77 of paths) {
|
|
6757
|
+
const parts = parsePath(path77);
|
|
6758
6758
|
if (parts.includes("*")) {
|
|
6759
|
-
redactWildcardPath(obj, parts, censor,
|
|
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,
|
|
6845
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
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
|
|
6881
|
-
const parts = parsePath(
|
|
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(
|
|
6934
|
-
if (typeof
|
|
6933
|
+
function validatePath(path77) {
|
|
6934
|
+
if (typeof path77 !== "string") {
|
|
6935
6935
|
throw new Error("Paths must be (non-empty) strings");
|
|
6936
6936
|
}
|
|
6937
|
-
if (
|
|
6937
|
+
if (path77 === "") {
|
|
6938
6938
|
throw new Error("Invalid redaction path ()");
|
|
6939
6939
|
}
|
|
6940
|
-
if (
|
|
6941
|
-
throw new Error(`Invalid redaction path (${
|
|
6940
|
+
if (path77.includes("..")) {
|
|
6941
|
+
throw new Error(`Invalid redaction path (${path77})`);
|
|
6942
6942
|
}
|
|
6943
|
-
if (
|
|
6944
|
-
throw new Error(`Invalid redaction path (${
|
|
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 <
|
|
6950
|
-
const char =
|
|
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 (${
|
|
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 (${
|
|
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
|
|
6977
|
-
validatePath(
|
|
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,
|
|
7146
|
-
return censor(value, [k2, ...
|
|
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
|
|
7364
|
+
var fs70 = require("fs");
|
|
7365
7365
|
var EventEmitter3 = require("events");
|
|
7366
7366
|
var inherits = require("util").inherits;
|
|
7367
|
-
var
|
|
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)
|
|
7422
|
-
const fd =
|
|
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
|
-
|
|
7429
|
+
fs70.mkdir(path77.dirname(file), { recursive: true }, (err) => {
|
|
7430
7430
|
if (err) return fileOpened(err);
|
|
7431
|
-
|
|
7431
|
+
fs70.open(file, flags, mode, fileOpened);
|
|
7432
7432
|
});
|
|
7433
7433
|
} else {
|
|
7434
|
-
|
|
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 = () =>
|
|
7476
|
-
fsWrite = () =>
|
|
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
|
|
7485
|
+
return fs70.writeSync(this.fd, this._writingBuf);
|
|
7486
7486
|
}
|
|
7487
|
-
return
|
|
7487
|
+
return fs70.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7488
7488
|
};
|
|
7489
7489
|
fsWrite = () => {
|
|
7490
7490
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7491
|
-
return
|
|
7491
|
+
return fs70.write(this.fd, this._writingBuf, this.release);
|
|
7492
7492
|
}
|
|
7493
|
-
return
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) ?
|
|
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
|
-
|
|
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 =
|
|
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) ?
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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(
|
|
11061
|
-
var last =
|
|
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:
|
|
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:
|
|
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
|
|
11540
|
+
const path77 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11541
11541
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11542
|
-
if (!
|
|
11543
|
-
const entry = { path:
|
|
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
|
|
12355
|
+
const path77 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12364
12356
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12365
|
-
if (!
|
|
12366
|
-
const out = { path:
|
|
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
|
|
27014
|
-
|
|
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
|
-
|
|
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 =
|
|
28351
|
+
data = toBuffer2(data);
|
|
28475
28352
|
byteLength = data.length;
|
|
28476
|
-
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 =
|
|
28398
|
+
data = toBuffer2(data);
|
|
28522
28399
|
byteLength = data.length;
|
|
28523
|
-
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 =
|
|
28456
|
+
data = toBuffer2(data);
|
|
28580
28457
|
byteLength = data.length;
|
|
28581
|
-
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 =
|
|
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 :
|
|
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(
|
|
33464
|
-
var parts =
|
|
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(
|
|
39318
|
-
if (
|
|
39319
|
-
|
|
39194
|
+
var parentFolder = function(path77) {
|
|
39195
|
+
if (path77.slice(-1) === "/") {
|
|
39196
|
+
path77 = path77.substring(0, path77.length - 1);
|
|
39320
39197
|
}
|
|
39321
|
-
var lastSlash =
|
|
39322
|
-
return lastSlash > 0 ?
|
|
39198
|
+
var lastSlash = path77.lastIndexOf("/");
|
|
39199
|
+
return lastSlash > 0 ? path77.substring(0, lastSlash) : "";
|
|
39323
39200
|
};
|
|
39324
|
-
var forceTrailingSlash = function(
|
|
39325
|
-
if (
|
|
39326
|
-
|
|
39201
|
+
var forceTrailingSlash = function(path77) {
|
|
39202
|
+
if (path77.slice(-1) !== "/") {
|
|
39203
|
+
path77 += "/";
|
|
39327
39204
|
}
|
|
39328
|
-
return
|
|
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
|
|
40746
|
-
const
|
|
40747
|
-
|
|
40748
|
-
|
|
40749
|
-
|
|
40750
|
-
|
|
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 (!
|
|
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
|
-
|
|
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
|
|
40769
|
-
const
|
|
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(
|
|
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
|
|
40812
|
-
|
|
40813
|
-
if (Buffer.
|
|
40814
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
40907
|
-
|
|
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>
|
|
41090
|
-
WebSocket relay
|
|
41091
|
-
|
|
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
|
-
|
|
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,
|
|
46713
|
-
items.push({ type: "skill", name, path:
|
|
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/
|
|
48979
|
-
|
|
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
|
|
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
|
-
...
|
|
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
|
-
|
|
53678
|
-
|
|
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/
|
|
53899
|
-
|
|
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,
|
|
54253
|
+
async function centralRequest(opts, path77, init) {
|
|
54190
54254
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
54191
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
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。
|