@clawos-dev/clawd 0.2.210-beta.417.a3be9b3 → 0.2.210-beta.418.4af4e12
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 +456 -400
- 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
|
`;
|
|
@@ -41814,12 +41571,13 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
|
|
|
41814
41571
|
fsv.allowWrite = unionArr(fsv.allowWrite, [userWorkDir]);
|
|
41815
41572
|
fsv.allowRead = unionArr(fsv.allowRead, [
|
|
41816
41573
|
"~/.clawd/contact-ssh-keys",
|
|
41817
|
-
"~/.clawd/contacts.json",
|
|
41818
41574
|
"~/.clawd/bin",
|
|
41819
41575
|
"~/Library/Application Support/@clawos/clawd-desktop/ota-bundles",
|
|
41820
41576
|
"~/.clawd/config.json",
|
|
41821
41577
|
"~/.clawd/auth.json"
|
|
41822
41578
|
]);
|
|
41579
|
+
const netv = s.sandbox.network ?? (s.sandbox.network = {});
|
|
41580
|
+
netv.allowedDomains = unionArr(netv.allowedDomains, ["*.tunnel.clawos.chat"]);
|
|
41823
41581
|
return s;
|
|
41824
41582
|
}
|
|
41825
41583
|
|
|
@@ -46352,7 +46110,11 @@ function tryLoadShareUi(logger) {
|
|
|
46352
46110
|
|
|
46353
46111
|
// src/visitor/visitor-token.ts
|
|
46354
46112
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
46355
|
-
|
|
46113
|
+
|
|
46114
|
+
// ../protocol/src/index.ts
|
|
46115
|
+
init_runtime();
|
|
46116
|
+
|
|
46117
|
+
// src/visitor/visitor-token.ts
|
|
46356
46118
|
function hmac(secret, body) {
|
|
46357
46119
|
return import_node_crypto4.default.createHmac("sha256", secret).update(body).digest("base64url");
|
|
46358
46120
|
}
|
|
@@ -46709,8 +46471,8 @@ function turnStartInput(text) {
|
|
|
46709
46471
|
const items = [];
|
|
46710
46472
|
let leftover = text;
|
|
46711
46473
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
46712
|
-
const [marker, name,
|
|
46713
|
-
items.push({ type: "skill", name, path:
|
|
46474
|
+
const [marker, name, path77] = m2;
|
|
46475
|
+
items.push({ type: "skill", name, path: path77 });
|
|
46714
46476
|
leftover = leftover.replace(marker, "");
|
|
46715
46477
|
}
|
|
46716
46478
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -48975,8 +48737,115 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
48975
48737
|
};
|
|
48976
48738
|
}
|
|
48977
48739
|
|
|
48978
|
-
// src/
|
|
48979
|
-
|
|
48740
|
+
// src/dispatch/peer-forward.ts
|
|
48741
|
+
function wsUrlToHttp(url) {
|
|
48742
|
+
if (url.startsWith("wss://")) return "https://" + url.slice("wss://".length);
|
|
48743
|
+
if (url.startsWith("ws://")) return "http://" + url.slice("ws://".length);
|
|
48744
|
+
return url;
|
|
48745
|
+
}
|
|
48746
|
+
async function forwardDispatchToPeer(args) {
|
|
48747
|
+
const f = args.fetchImpl ?? fetch;
|
|
48748
|
+
const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
|
|
48749
|
+
const url = `${base}/rpc/personaDispatch:run`;
|
|
48750
|
+
let res;
|
|
48751
|
+
try {
|
|
48752
|
+
res = await f(url, {
|
|
48753
|
+
method: "POST",
|
|
48754
|
+
headers: {
|
|
48755
|
+
"content-type": "application/json",
|
|
48756
|
+
authorization: `Bearer ${args.contact.connectToken}`
|
|
48757
|
+
},
|
|
48758
|
+
// 注意:不带 targetDeviceId —— B 端据此判定为本地执行(B 角色)。
|
|
48759
|
+
body: JSON.stringify({ targetPersona: args.targetPersona, prompt: args.prompt })
|
|
48760
|
+
});
|
|
48761
|
+
} catch (err) {
|
|
48762
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
48763
|
+
return { kind: "failure", reason: `forward to peer failed: ${msg}` };
|
|
48764
|
+
}
|
|
48765
|
+
let json;
|
|
48766
|
+
try {
|
|
48767
|
+
json = await res.json();
|
|
48768
|
+
} catch {
|
|
48769
|
+
return {
|
|
48770
|
+
kind: "failure",
|
|
48771
|
+
reason: `peer returned non-JSON response (HTTP ${res.status})`
|
|
48772
|
+
};
|
|
48773
|
+
}
|
|
48774
|
+
if (json.ok === false) {
|
|
48775
|
+
return { kind: "failure", reason: `peer rejected: ${json.error}: ${json.message}` };
|
|
48776
|
+
}
|
|
48777
|
+
return json.result.outcome;
|
|
48778
|
+
}
|
|
48779
|
+
async function forwardInboxPostToPeer(args) {
|
|
48780
|
+
const f = args.fetchImpl ?? fetch;
|
|
48781
|
+
const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
|
|
48782
|
+
const url = `${base}/rpc/inbox:postMessage`;
|
|
48783
|
+
let res;
|
|
48784
|
+
try {
|
|
48785
|
+
res = await f(url, {
|
|
48786
|
+
method: "POST",
|
|
48787
|
+
headers: {
|
|
48788
|
+
"content-type": "application/json",
|
|
48789
|
+
authorization: `Bearer ${args.contact.connectToken}`
|
|
48790
|
+
},
|
|
48791
|
+
body: JSON.stringify({
|
|
48792
|
+
id: args.id,
|
|
48793
|
+
text: args.text,
|
|
48794
|
+
createdAt: args.createdAt,
|
|
48795
|
+
...args.origin ? { origin: args.origin } : {}
|
|
48796
|
+
})
|
|
48797
|
+
});
|
|
48798
|
+
} catch (err) {
|
|
48799
|
+
return { ok: false, error: err instanceof Error ? err.message : String(err) };
|
|
48800
|
+
}
|
|
48801
|
+
let json = null;
|
|
48802
|
+
try {
|
|
48803
|
+
json = await res.json();
|
|
48804
|
+
} catch {
|
|
48805
|
+
return { ok: false, error: `peer non-JSON (HTTP ${res.status})` };
|
|
48806
|
+
}
|
|
48807
|
+
if (res.status < 200 || res.status >= 300 || json?.ok === false) {
|
|
48808
|
+
return { ok: false, error: json?.error ?? `HTTP ${res.status}` };
|
|
48809
|
+
}
|
|
48810
|
+
return { ok: true };
|
|
48811
|
+
}
|
|
48812
|
+
async function forwardContactSshKeyIssueToPeer(args) {
|
|
48813
|
+
const f = args.fetchImpl ?? fetch;
|
|
48814
|
+
const base = wsUrlToHttp(args.contact.remoteUrl).replace(/\/+$/, "");
|
|
48815
|
+
const url = `${base}/rpc/contact:sshKey:issue`;
|
|
48816
|
+
let res;
|
|
48817
|
+
try {
|
|
48818
|
+
res = await f(url, {
|
|
48819
|
+
method: "POST",
|
|
48820
|
+
headers: {
|
|
48821
|
+
"content-type": "application/json",
|
|
48822
|
+
authorization: `Bearer ${args.contact.connectToken}`
|
|
48823
|
+
},
|
|
48824
|
+
body: JSON.stringify({ deviceId: args.selfDeviceIdForRequest })
|
|
48825
|
+
});
|
|
48826
|
+
} catch (err) {
|
|
48827
|
+
return {
|
|
48828
|
+
ok: false,
|
|
48829
|
+
code: "NETWORK",
|
|
48830
|
+
message: err instanceof Error ? err.message : String(err)
|
|
48831
|
+
};
|
|
48832
|
+
}
|
|
48833
|
+
let json = null;
|
|
48834
|
+
try {
|
|
48835
|
+
json = await res.json();
|
|
48836
|
+
} catch {
|
|
48837
|
+
return { ok: false, code: "PROTOCOL", message: `peer non-JSON (HTTP ${res.status})` };
|
|
48838
|
+
}
|
|
48839
|
+
if (!json) {
|
|
48840
|
+
return { ok: false, code: "PROTOCOL", message: `peer returned null (HTTP ${res.status})` };
|
|
48841
|
+
}
|
|
48842
|
+
if (json.ok === false) {
|
|
48843
|
+
const j = json;
|
|
48844
|
+
return { ok: false, code: j.error ?? "UNKNOWN", message: j.message ?? "" };
|
|
48845
|
+
}
|
|
48846
|
+
const r = json.result;
|
|
48847
|
+
return { ok: true, privateKeyPem: r.privateKeyPem, publicKeyLine: r.publicKeyLine };
|
|
48848
|
+
}
|
|
48980
48849
|
|
|
48981
48850
|
// src/tools/codex-history.ts
|
|
48982
48851
|
var import_node_child_process5 = require("child_process");
|
|
@@ -49164,13 +49033,13 @@ function mapSkillsListResponse(res) {
|
|
|
49164
49033
|
const r = s ?? {};
|
|
49165
49034
|
const name = str3(r.name);
|
|
49166
49035
|
if (!name) continue;
|
|
49167
|
-
const
|
|
49036
|
+
const path77 = str3(r.path);
|
|
49168
49037
|
const description = str3(r.description);
|
|
49169
49038
|
const isPlugin = name.includes(":");
|
|
49170
49039
|
out.push({
|
|
49171
49040
|
name,
|
|
49172
49041
|
source: isPlugin ? "plugin" : "project",
|
|
49173
|
-
...
|
|
49042
|
+
...path77 ? { path: path77 } : {},
|
|
49174
49043
|
...description ? { description } : {},
|
|
49175
49044
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
49176
49045
|
});
|
|
@@ -49908,6 +49777,18 @@ var LocalWsServer = class {
|
|
|
49908
49777
|
return;
|
|
49909
49778
|
}
|
|
49910
49779
|
}
|
|
49780
|
+
if (this.opts.sshTunnelLocalUpgradeHandler) {
|
|
49781
|
+
const [urlPath] = (req.url ?? "").split("?");
|
|
49782
|
+
if (urlPath === "/rpc/ssh-tunnel-local") {
|
|
49783
|
+
void this.opts.sshTunnelLocalUpgradeHandler(
|
|
49784
|
+
req,
|
|
49785
|
+
socket,
|
|
49786
|
+
head,
|
|
49787
|
+
wss
|
|
49788
|
+
);
|
|
49789
|
+
return;
|
|
49790
|
+
}
|
|
49791
|
+
}
|
|
49911
49792
|
if (req.url?.startsWith("/preview/")) {
|
|
49912
49793
|
const pathname = (() => {
|
|
49913
49794
|
try {
|
|
@@ -50480,7 +50361,6 @@ function constantTimeEqual2(a, b2) {
|
|
|
50480
50361
|
}
|
|
50481
50362
|
|
|
50482
50363
|
// src/transport/connection-context.ts
|
|
50483
|
-
init_src();
|
|
50484
50364
|
function ownerContext(ownerPrincipalId, displayName) {
|
|
50485
50365
|
return {
|
|
50486
50366
|
principal: makeOwnerPrincipal(ownerPrincipalId, displayName),
|
|
@@ -50534,7 +50414,6 @@ async function authenticate(token, deps) {
|
|
|
50534
50414
|
// src/permission/capability-store.ts
|
|
50535
50415
|
var fs29 = __toESM(require("fs"), 1);
|
|
50536
50416
|
var path29 = __toESM(require("path"), 1);
|
|
50537
|
-
init_src();
|
|
50538
50417
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
50539
50418
|
var FILE_VERSION = 1;
|
|
50540
50419
|
var CapabilityStore = class {
|
|
@@ -50712,7 +50591,6 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
50712
50591
|
// src/inbox/inbox-store.ts
|
|
50713
50592
|
var fs31 = __toESM(require("fs"), 1);
|
|
50714
50593
|
var path30 = __toESM(require("path"), 1);
|
|
50715
|
-
init_src();
|
|
50716
50594
|
var INBOX_SUBDIR = "inbox";
|
|
50717
50595
|
var InboxStore = class {
|
|
50718
50596
|
constructor(dataDir) {
|
|
@@ -50903,7 +50781,6 @@ var InboxManager = class {
|
|
|
50903
50781
|
// src/state/contact-store.ts
|
|
50904
50782
|
var fs32 = __toESM(require("fs"), 1);
|
|
50905
50783
|
var path31 = __toESM(require("path"), 1);
|
|
50906
|
-
init_src();
|
|
50907
50784
|
var FILE_NAME = "contacts.json";
|
|
50908
50785
|
var ContactStore = class {
|
|
50909
50786
|
constructor(dataDir) {
|
|
@@ -51154,9 +51031,6 @@ async function autoReverseContact(args) {
|
|
|
51154
51031
|
args.broadcast({ type: "contact:added", contact: upgraded });
|
|
51155
51032
|
}
|
|
51156
51033
|
|
|
51157
|
-
// src/index.ts
|
|
51158
|
-
init_src();
|
|
51159
|
-
|
|
51160
51034
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
51161
51035
|
var fs33 = __toESM(require("fs"), 1);
|
|
51162
51036
|
var path32 = __toESM(require("path"), 1);
|
|
@@ -51539,7 +51413,6 @@ var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
|
51539
51413
|
var import_node_path27 = __toESM(require("path"), 1);
|
|
51540
51414
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
51541
51415
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
51542
|
-
init_src();
|
|
51543
51416
|
var ImportError = class extends Error {
|
|
51544
51417
|
constructor(code, message) {
|
|
51545
51418
|
super(message);
|
|
@@ -53674,8 +53547,45 @@ function readIssuedPubkey(sshdDir, deviceId) {
|
|
|
53674
53547
|
// src/sshd/contact-key-puller.ts
|
|
53675
53548
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
53676
53549
|
var import_node_path42 = __toESM(require("path"), 1);
|
|
53677
|
-
|
|
53678
|
-
|
|
53550
|
+
|
|
53551
|
+
// src/sshd/contact-ssh-log.ts
|
|
53552
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
53553
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
53554
|
+
function createContactSshLog(dataDir) {
|
|
53555
|
+
const file = import_node_path41.default.join(dataDir, "contact-ssh.log");
|
|
53556
|
+
function append(level, tag, message, meta) {
|
|
53557
|
+
const time = (/* @__PURE__ */ new Date()).toISOString();
|
|
53558
|
+
let line = `[${time}] [${level}] [${tag}] ${message}`;
|
|
53559
|
+
if (meta && Object.keys(meta).length > 0) {
|
|
53560
|
+
try {
|
|
53561
|
+
line += " " + JSON.stringify(meta);
|
|
53562
|
+
} catch {
|
|
53563
|
+
line += " [meta-serialize-failed]";
|
|
53564
|
+
}
|
|
53565
|
+
}
|
|
53566
|
+
line += "\n";
|
|
53567
|
+
try {
|
|
53568
|
+
import_node_fs40.default.mkdirSync(import_node_path41.default.dirname(file), { recursive: true });
|
|
53569
|
+
import_node_fs40.default.appendFileSync(file, line, { mode: 384 });
|
|
53570
|
+
} catch {
|
|
53571
|
+
}
|
|
53572
|
+
}
|
|
53573
|
+
return {
|
|
53574
|
+
info: (tag, message, meta) => append("INFO", tag, message, meta),
|
|
53575
|
+
warn: (tag, message, meta) => append("WARN", tag, message, meta),
|
|
53576
|
+
error: (tag, message, meta) => append("ERROR", tag, message, meta)
|
|
53577
|
+
};
|
|
53578
|
+
}
|
|
53579
|
+
var nullContactSshLog = {
|
|
53580
|
+
info: () => {
|
|
53581
|
+
},
|
|
53582
|
+
warn: () => {
|
|
53583
|
+
},
|
|
53584
|
+
error: () => {
|
|
53585
|
+
}
|
|
53586
|
+
};
|
|
53587
|
+
|
|
53588
|
+
// src/sshd/contact-key-puller.ts
|
|
53679
53589
|
var CONTACT_KEYS_DIR = "contact-ssh-keys";
|
|
53680
53590
|
function safeContactKeyPath(dataDir, deviceId) {
|
|
53681
53591
|
const safeId = deviceId.replace(/[\/\\]/g, "_");
|
|
@@ -53787,7 +53697,6 @@ var ContactKeyPuller = class {
|
|
|
53787
53697
|
|
|
53788
53698
|
// src/sshd/ssh-tunnel-relay.ts
|
|
53789
53699
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
53790
|
-
init_contact_ssh_log();
|
|
53791
53700
|
async function handleSshTunnelUpgrade(req, socket, head, deps) {
|
|
53792
53701
|
const sshLog = deps.sshLog ?? nullContactSshLog;
|
|
53793
53702
|
const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
|
|
@@ -53895,8 +53804,161 @@ function pumpWsToSshd(ws, deps, clientAddr) {
|
|
|
53895
53804
|
});
|
|
53896
53805
|
}
|
|
53897
53806
|
|
|
53898
|
-
// src/
|
|
53899
|
-
|
|
53807
|
+
// src/sshd/ssh-tunnel-local-relay.ts
|
|
53808
|
+
init_wrapper();
|
|
53809
|
+
function parsePeerDeviceId(rawUrl) {
|
|
53810
|
+
if (!rawUrl) return null;
|
|
53811
|
+
try {
|
|
53812
|
+
const u = new URL(rawUrl, "http://127.0.0.1");
|
|
53813
|
+
const v2 = u.searchParams.get("peerDeviceId");
|
|
53814
|
+
return v2 && v2.length > 0 ? v2 : null;
|
|
53815
|
+
} catch {
|
|
53816
|
+
return null;
|
|
53817
|
+
}
|
|
53818
|
+
}
|
|
53819
|
+
async function handleSshTunnelLocalUpgrade(req, socket, head, deps) {
|
|
53820
|
+
const sshLog = deps.sshLog ?? nullContactSshLog;
|
|
53821
|
+
const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
|
|
53822
|
+
const sessionId = req.headers["x-clawd-session-id"] ?? "";
|
|
53823
|
+
if (!sessionId) {
|
|
53824
|
+
sshLog.warn("relay.auth-failed", "/rpc/ssh-tunnel-local \u7F3A X-Clawd-Session-Id header", {
|
|
53825
|
+
clientAddr
|
|
53826
|
+
});
|
|
53827
|
+
respond401(socket);
|
|
53828
|
+
return;
|
|
53829
|
+
}
|
|
53830
|
+
const peerDeviceId = parsePeerDeviceId(req.url);
|
|
53831
|
+
if (!peerDeviceId) {
|
|
53832
|
+
sshLog.warn("relay.auth-failed", "/rpc/ssh-tunnel-local \u7F3A peerDeviceId query", { clientAddr });
|
|
53833
|
+
respond400(socket);
|
|
53834
|
+
return;
|
|
53835
|
+
}
|
|
53836
|
+
const contact = deps.store.get(peerDeviceId);
|
|
53837
|
+
if (!contact) {
|
|
53838
|
+
sshLog.error("relay.contact-not-found", "ssh-tunnel-local \u627E\u4E0D\u5230 peer contact", {
|
|
53839
|
+
peerDeviceId
|
|
53840
|
+
});
|
|
53841
|
+
respond404(socket);
|
|
53842
|
+
return;
|
|
53843
|
+
}
|
|
53844
|
+
if (!contact.connectToken) {
|
|
53845
|
+
sshLog.error(
|
|
53846
|
+
"relay.token-missing",
|
|
53847
|
+
"contact \u6709\u8BB0\u5F55\u4F46\u7F3A connectToken\uFF08auto-reverse \u672A\u6362\u7968\uFF09",
|
|
53848
|
+
{ peerDeviceId, peerDisplayName: contact.displayName }
|
|
53849
|
+
);
|
|
53850
|
+
respond403(socket);
|
|
53851
|
+
return;
|
|
53852
|
+
}
|
|
53853
|
+
const baseHttp = wsUrlToHttp(contact.remoteUrl).replace(/\/+$/, "");
|
|
53854
|
+
const wsBase = baseHttp.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
|
|
53855
|
+
const outboundUrl = `${wsBase}/rpc/ssh-tunnel`;
|
|
53856
|
+
sshLog.info("relay.dial", "\u5F00\u59CB\u62E8 A \u4FA7 /rpc/ssh-tunnel", {
|
|
53857
|
+
peerDeviceId,
|
|
53858
|
+
peerDisplayName: contact.displayName,
|
|
53859
|
+
url: outboundUrl
|
|
53860
|
+
});
|
|
53861
|
+
deps.wss.handleUpgrade(req, socket, head, (clientWs) => {
|
|
53862
|
+
const makeOut = deps.makeOutboundWs ?? ((u, o) => new import_websocket.default(u, o));
|
|
53863
|
+
const outbound = makeOut(outboundUrl, {
|
|
53864
|
+
headers: { Authorization: `Bearer ${contact.connectToken}` }
|
|
53865
|
+
});
|
|
53866
|
+
pumpClientToOutbound(clientWs, outbound, peerDeviceId, contact.displayName, deps);
|
|
53867
|
+
});
|
|
53868
|
+
}
|
|
53869
|
+
function pumpClientToOutbound(client, outbound, peerDeviceId, peerDisplayName, deps) {
|
|
53870
|
+
const sshLog = deps.sshLog ?? nullContactSshLog;
|
|
53871
|
+
const startedAt = Date.now();
|
|
53872
|
+
let outboundOpened = false;
|
|
53873
|
+
let bytesClientToOutbound = 0;
|
|
53874
|
+
let bytesOutboundToClient = 0;
|
|
53875
|
+
let settled = false;
|
|
53876
|
+
const cleanup = (reason, code = 1e3) => {
|
|
53877
|
+
if (settled) return;
|
|
53878
|
+
settled = true;
|
|
53879
|
+
try {
|
|
53880
|
+
client.close(code, reason);
|
|
53881
|
+
} catch {
|
|
53882
|
+
}
|
|
53883
|
+
try {
|
|
53884
|
+
outbound.close();
|
|
53885
|
+
} catch {
|
|
53886
|
+
}
|
|
53887
|
+
const level = code === 1e3 ? "info" : "warn";
|
|
53888
|
+
sshLog[level](
|
|
53889
|
+
code === 1e3 ? "relay.dial-close" : "relay.dial-close-abnormal",
|
|
53890
|
+
code === 1e3 ? "tunnel \u4F1A\u8BDD\u6B63\u5E38\u7ED3\u675F" : "tunnel \u4F1A\u8BDD\u975E\u6B63\u5E38\u5173\u95ED",
|
|
53891
|
+
{
|
|
53892
|
+
peerDeviceId,
|
|
53893
|
+
peerDisplayName,
|
|
53894
|
+
reason,
|
|
53895
|
+
code,
|
|
53896
|
+
outboundOpened,
|
|
53897
|
+
bytesClientToOutbound,
|
|
53898
|
+
bytesOutboundToClient,
|
|
53899
|
+
durationMs: Date.now() - startedAt
|
|
53900
|
+
}
|
|
53901
|
+
);
|
|
53902
|
+
};
|
|
53903
|
+
outbound.on("open", () => {
|
|
53904
|
+
outboundOpened = true;
|
|
53905
|
+
sshLog.info("relay.dial-open", "outbound ws open\uFF0C\u8FDB\u5165\u53CC\u5411 pipe", {
|
|
53906
|
+
peerDeviceId,
|
|
53907
|
+
peerDisplayName
|
|
53908
|
+
});
|
|
53909
|
+
});
|
|
53910
|
+
outbound.on("message", (data) => {
|
|
53911
|
+
const buf = toBuffer(data);
|
|
53912
|
+
if (!buf) return;
|
|
53913
|
+
bytesOutboundToClient += buf.length;
|
|
53914
|
+
if (client.readyState === client.OPEN) client.send(buf, { binary: true });
|
|
53915
|
+
});
|
|
53916
|
+
outbound.on("error", (err) => {
|
|
53917
|
+
deps.logger?.warn("ssh-tunnel-local: outbound ws error", { err: err.message });
|
|
53918
|
+
sshLog.error("relay.dial-error", "outbound ws \u8FDE\u63A5\u9519\u8BEF\uFF08peer \u4E0D\u53EF\u8FBE / TLS \u5931\u8D25\uFF09", {
|
|
53919
|
+
peerDeviceId,
|
|
53920
|
+
peerDisplayName,
|
|
53921
|
+
message: err.message
|
|
53922
|
+
});
|
|
53923
|
+
cleanup("outbound error", 1011);
|
|
53924
|
+
});
|
|
53925
|
+
outbound.on("close", (code) => {
|
|
53926
|
+
if (!settled) cleanup(`outbound close ${code}`, code === 1e3 ? 1e3 : 1011);
|
|
53927
|
+
});
|
|
53928
|
+
client.on("message", (data) => {
|
|
53929
|
+
const buf = toBuffer(data);
|
|
53930
|
+
if (!buf) return;
|
|
53931
|
+
bytesClientToOutbound += buf.length;
|
|
53932
|
+
if (outbound.readyState === outbound.OPEN) outbound.send(buf, { binary: true });
|
|
53933
|
+
});
|
|
53934
|
+
client.on("close", () => cleanup("client close", 1e3));
|
|
53935
|
+
client.on("error", (err) => {
|
|
53936
|
+
deps.logger?.warn("ssh-tunnel-local: client ws error", { err: err.message });
|
|
53937
|
+
cleanup("client error", 1011);
|
|
53938
|
+
});
|
|
53939
|
+
}
|
|
53940
|
+
function toBuffer(data) {
|
|
53941
|
+
if (Buffer.isBuffer(data)) return data;
|
|
53942
|
+
if (Array.isArray(data)) return Buffer.concat(data);
|
|
53943
|
+
if (data instanceof ArrayBuffer) return Buffer.from(data);
|
|
53944
|
+
return null;
|
|
53945
|
+
}
|
|
53946
|
+
function respond401(socket) {
|
|
53947
|
+
socket.write("HTTP/1.1 401 Unauthorized\r\nContent-Length: 0\r\n\r\n");
|
|
53948
|
+
socket.destroy();
|
|
53949
|
+
}
|
|
53950
|
+
function respond400(socket) {
|
|
53951
|
+
socket.write("HTTP/1.1 400 Bad Request\r\nContent-Length: 0\r\n\r\n");
|
|
53952
|
+
socket.destroy();
|
|
53953
|
+
}
|
|
53954
|
+
function respond403(socket) {
|
|
53955
|
+
socket.write("HTTP/1.1 403 Forbidden\r\nContent-Length: 0\r\n\r\n");
|
|
53956
|
+
socket.destroy();
|
|
53957
|
+
}
|
|
53958
|
+
function respond404(socket) {
|
|
53959
|
+
socket.write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n");
|
|
53960
|
+
socket.destroy();
|
|
53961
|
+
}
|
|
53900
53962
|
|
|
53901
53963
|
// src/tunnel/device-key.ts
|
|
53902
53964
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
@@ -54186,9 +54248,9 @@ var CentralClientError = class extends Error {
|
|
|
54186
54248
|
code;
|
|
54187
54249
|
cause;
|
|
54188
54250
|
};
|
|
54189
|
-
async function centralRequest(opts,
|
|
54251
|
+
async function centralRequest(opts, path77, init) {
|
|
54190
54252
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
54191
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
54253
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
|
|
54192
54254
|
const ctrl = new AbortController();
|
|
54193
54255
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
54194
54256
|
let res;
|
|
@@ -55178,7 +55240,6 @@ function buildCapabilitiesHandlers(deps) {
|
|
|
55178
55240
|
|
|
55179
55241
|
// src/handlers/capability.ts
|
|
55180
55242
|
init_zod();
|
|
55181
|
-
init_src();
|
|
55182
55243
|
init_protocol();
|
|
55183
55244
|
var DeleteArgsSchema = external_exports.object({
|
|
55184
55245
|
capabilityId: external_exports.string().min(1)
|
|
@@ -55217,7 +55278,6 @@ function buildCapabilityHandlers(deps) {
|
|
|
55217
55278
|
}
|
|
55218
55279
|
|
|
55219
55280
|
// src/handlers/inbox.ts
|
|
55220
|
-
init_src();
|
|
55221
55281
|
init_protocol();
|
|
55222
55282
|
function resolvePeerDeviceId(ctx, argsPeerDeviceId) {
|
|
55223
55283
|
if (ctx.principal.kind === "owner") {
|
|
@@ -55396,7 +55456,6 @@ function buildInboxHandlers(deps) {
|
|
|
55396
55456
|
}
|
|
55397
55457
|
|
|
55398
55458
|
// src/handlers/contact.ts
|
|
55399
|
-
init_src();
|
|
55400
55459
|
init_protocol();
|
|
55401
55460
|
function ensureOwner(ctx) {
|
|
55402
55461
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -55465,7 +55524,6 @@ function buildContactHandlers(deps) {
|
|
|
55465
55524
|
}
|
|
55466
55525
|
|
|
55467
55526
|
// src/handlers/contact-ssh.ts
|
|
55468
|
-
init_src();
|
|
55469
55527
|
init_protocol();
|
|
55470
55528
|
|
|
55471
55529
|
// src/sshd/key-issue.ts
|
|
@@ -55512,7 +55570,6 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
|
|
|
55512
55570
|
}
|
|
55513
55571
|
|
|
55514
55572
|
// src/handlers/contact-ssh.ts
|
|
55515
|
-
init_contact_ssh_log();
|
|
55516
55573
|
function ensureOwner2(ctx) {
|
|
55517
55574
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
55518
55575
|
throw new ClawdError(
|
|
@@ -55615,7 +55672,6 @@ function buildContactSshHandlers(deps) {
|
|
|
55615
55672
|
}
|
|
55616
55673
|
|
|
55617
55674
|
// src/handlers/whoami.ts
|
|
55618
|
-
init_src();
|
|
55619
55675
|
init_protocol();
|
|
55620
55676
|
function buildWhoamiHandler(deps) {
|
|
55621
55677
|
return async (_frame, _client, ctx) => {
|
|
@@ -55709,7 +55765,6 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
55709
55765
|
}
|
|
55710
55766
|
|
|
55711
55767
|
// src/handlers/device.ts
|
|
55712
|
-
init_src();
|
|
55713
55768
|
init_protocol();
|
|
55714
55769
|
function ensureOwner3(ctx) {
|
|
55715
55770
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -56114,7 +56169,6 @@ function buildAttachmentHandlers(deps) {
|
|
|
56114
56169
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
56115
56170
|
var import_node_path55 = __toESM(require("path"), 1);
|
|
56116
56171
|
init_protocol();
|
|
56117
|
-
init_src();
|
|
56118
56172
|
|
|
56119
56173
|
// src/extension/bundle-zip.ts
|
|
56120
56174
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
@@ -56160,8 +56214,6 @@ async function walk(absRoot, relPrefix, out) {
|
|
|
56160
56214
|
}
|
|
56161
56215
|
|
|
56162
56216
|
// src/extension/publish-check.ts
|
|
56163
|
-
init_src();
|
|
56164
|
-
init_src();
|
|
56165
56217
|
function computePublishCheck(args) {
|
|
56166
56218
|
const { localHash, localVersion, head } = args;
|
|
56167
56219
|
if (head === null) {
|
|
@@ -56206,12 +56258,10 @@ var import_node_path53 = __toESM(require("path"), 1);
|
|
|
56206
56258
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
56207
56259
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
56208
56260
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
56209
|
-
init_src();
|
|
56210
56261
|
|
|
56211
56262
|
// src/extension/paths.ts
|
|
56212
56263
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
56213
56264
|
var import_node_path52 = __toESM(require("path"), 1);
|
|
56214
|
-
init_src();
|
|
56215
56265
|
function clawdHomeRoot(override) {
|
|
56216
56266
|
return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
|
|
56217
56267
|
}
|
|
@@ -56329,7 +56379,6 @@ var import_node_path54 = __toESM(require("path"), 1);
|
|
|
56329
56379
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
56330
56380
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
56331
56381
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
56332
|
-
init_src();
|
|
56333
56382
|
var UpdateError = class extends Error {
|
|
56334
56383
|
constructor(code, message) {
|
|
56335
56384
|
super(message);
|
|
@@ -56475,7 +56524,6 @@ async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
|
56475
56524
|
}
|
|
56476
56525
|
|
|
56477
56526
|
// src/handlers/extension.ts
|
|
56478
|
-
init_src();
|
|
56479
56527
|
function pickChannelRef(frame) {
|
|
56480
56528
|
const ref = frame.channelRef;
|
|
56481
56529
|
const parsed = ChannelRefSchema.safeParse(ref);
|
|
@@ -57966,7 +58014,6 @@ function buildVisitorHandlers(deps) {
|
|
|
57966
58014
|
// src/extension/registry.ts
|
|
57967
58015
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
57968
58016
|
var import_node_path59 = __toESM(require("path"), 1);
|
|
57969
|
-
init_src();
|
|
57970
58017
|
async function loadAll(root) {
|
|
57971
58018
|
let entries;
|
|
57972
58019
|
try {
|
|
@@ -58051,7 +58098,6 @@ async function uninstall(deps) {
|
|
|
58051
58098
|
|
|
58052
58099
|
// src/handlers/index.ts
|
|
58053
58100
|
var import_node_crypto18 = require("crypto");
|
|
58054
|
-
init_peer_forward();
|
|
58055
58101
|
function buildMethodHandlers(deps) {
|
|
58056
58102
|
return {
|
|
58057
58103
|
...buildSessionHandlers({
|
|
@@ -58625,7 +58671,6 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
58625
58671
|
var import_node_child_process18 = require("child_process");
|
|
58626
58672
|
var import_node_path61 = __toESM(require("path"), 1);
|
|
58627
58673
|
var import_promises11 = require("timers/promises");
|
|
58628
|
-
init_src();
|
|
58629
58674
|
|
|
58630
58675
|
// src/extension/port-allocator.ts
|
|
58631
58676
|
var import_node_net3 = __toESM(require("net"), 1);
|
|
@@ -58838,7 +58883,6 @@ ${handle.stderrTail}`
|
|
|
58838
58883
|
// src/extension/published-channels.ts
|
|
58839
58884
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
58840
58885
|
var import_node_path62 = __toESM(require("path"), 1);
|
|
58841
|
-
init_src();
|
|
58842
58886
|
init_zod();
|
|
58843
58887
|
var PublishedChannelsError = class extends Error {
|
|
58844
58888
|
constructor(code, message) {
|
|
@@ -59918,6 +59962,18 @@ async function startDaemon(config) {
|
|
|
59918
59962
|
});
|
|
59919
59963
|
return true;
|
|
59920
59964
|
},
|
|
59965
|
+
// Contact SSH relay v2 (spec 2026-07-06-contact-ssh-relay-via-local-daemon-tunnel):
|
|
59966
|
+
// /rpc/ssh-tunnel-local WS 前置拦截。guest CC 沙箱从 localhost 连本地 daemon,daemon
|
|
59967
|
+
// 代理起 outbound wss 到 peer /rpc/ssh-tunnel。findContact / connectToken 处理下沉到
|
|
59968
|
+
// 本 handler;relay CLI 变纯粹的 stdio ↔ local WS pump(不再读 contacts.json / 持 token)。
|
|
59969
|
+
sshTunnelLocalUpgradeHandler: async (req, socket, head, wss2) => {
|
|
59970
|
+
await handleSshTunnelLocalUpgrade(req, socket, head, {
|
|
59971
|
+
wss: wss2,
|
|
59972
|
+
store: contactStore,
|
|
59973
|
+
logger,
|
|
59974
|
+
sshLog
|
|
59975
|
+
});
|
|
59976
|
+
},
|
|
59921
59977
|
// 订阅成功后给该 client 重放 in-flight pendingQuestions(plan: clawd-question-server-truth)。
|
|
59922
59978
|
// daemon 是 pendingQuestions 的唯一 source of truth;新 client 接入 / 刷新页面时
|
|
59923
59979
|
// 把当前所有未决 question 以 session:question 帧定向回放,让 UI 不再误显示 Ended。
|