@clawos-dev/clawd 0.2.209 → 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 +454 -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,7 +41571,6 @@ 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",
|
|
@@ -46354,7 +46110,11 @@ function tryLoadShareUi(logger) {
|
|
|
46354
46110
|
|
|
46355
46111
|
// src/visitor/visitor-token.ts
|
|
46356
46112
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
46357
|
-
|
|
46113
|
+
|
|
46114
|
+
// ../protocol/src/index.ts
|
|
46115
|
+
init_runtime();
|
|
46116
|
+
|
|
46117
|
+
// src/visitor/visitor-token.ts
|
|
46358
46118
|
function hmac(secret, body) {
|
|
46359
46119
|
return import_node_crypto4.default.createHmac("sha256", secret).update(body).digest("base64url");
|
|
46360
46120
|
}
|
|
@@ -46711,8 +46471,8 @@ function turnStartInput(text) {
|
|
|
46711
46471
|
const items = [];
|
|
46712
46472
|
let leftover = text;
|
|
46713
46473
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
46714
|
-
const [marker, name,
|
|
46715
|
-
items.push({ type: "skill", name, path:
|
|
46474
|
+
const [marker, name, path77] = m2;
|
|
46475
|
+
items.push({ type: "skill", name, path: path77 });
|
|
46716
46476
|
leftover = leftover.replace(marker, "");
|
|
46717
46477
|
}
|
|
46718
46478
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -48977,8 +48737,115 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
48977
48737
|
};
|
|
48978
48738
|
}
|
|
48979
48739
|
|
|
48980
|
-
// src/
|
|
48981
|
-
|
|
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
|
+
}
|
|
48982
48849
|
|
|
48983
48850
|
// src/tools/codex-history.ts
|
|
48984
48851
|
var import_node_child_process5 = require("child_process");
|
|
@@ -49166,13 +49033,13 @@ function mapSkillsListResponse(res) {
|
|
|
49166
49033
|
const r = s ?? {};
|
|
49167
49034
|
const name = str3(r.name);
|
|
49168
49035
|
if (!name) continue;
|
|
49169
|
-
const
|
|
49036
|
+
const path77 = str3(r.path);
|
|
49170
49037
|
const description = str3(r.description);
|
|
49171
49038
|
const isPlugin = name.includes(":");
|
|
49172
49039
|
out.push({
|
|
49173
49040
|
name,
|
|
49174
49041
|
source: isPlugin ? "plugin" : "project",
|
|
49175
|
-
...
|
|
49042
|
+
...path77 ? { path: path77 } : {},
|
|
49176
49043
|
...description ? { description } : {},
|
|
49177
49044
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
49178
49045
|
});
|
|
@@ -49910,6 +49777,18 @@ var LocalWsServer = class {
|
|
|
49910
49777
|
return;
|
|
49911
49778
|
}
|
|
49912
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
|
+
}
|
|
49913
49792
|
if (req.url?.startsWith("/preview/")) {
|
|
49914
49793
|
const pathname = (() => {
|
|
49915
49794
|
try {
|
|
@@ -50482,7 +50361,6 @@ function constantTimeEqual2(a, b2) {
|
|
|
50482
50361
|
}
|
|
50483
50362
|
|
|
50484
50363
|
// src/transport/connection-context.ts
|
|
50485
|
-
init_src();
|
|
50486
50364
|
function ownerContext(ownerPrincipalId, displayName) {
|
|
50487
50365
|
return {
|
|
50488
50366
|
principal: makeOwnerPrincipal(ownerPrincipalId, displayName),
|
|
@@ -50536,7 +50414,6 @@ async function authenticate(token, deps) {
|
|
|
50536
50414
|
// src/permission/capability-store.ts
|
|
50537
50415
|
var fs29 = __toESM(require("fs"), 1);
|
|
50538
50416
|
var path29 = __toESM(require("path"), 1);
|
|
50539
|
-
init_src();
|
|
50540
50417
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
50541
50418
|
var FILE_VERSION = 1;
|
|
50542
50419
|
var CapabilityStore = class {
|
|
@@ -50714,7 +50591,6 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
50714
50591
|
// src/inbox/inbox-store.ts
|
|
50715
50592
|
var fs31 = __toESM(require("fs"), 1);
|
|
50716
50593
|
var path30 = __toESM(require("path"), 1);
|
|
50717
|
-
init_src();
|
|
50718
50594
|
var INBOX_SUBDIR = "inbox";
|
|
50719
50595
|
var InboxStore = class {
|
|
50720
50596
|
constructor(dataDir) {
|
|
@@ -50905,7 +50781,6 @@ var InboxManager = class {
|
|
|
50905
50781
|
// src/state/contact-store.ts
|
|
50906
50782
|
var fs32 = __toESM(require("fs"), 1);
|
|
50907
50783
|
var path31 = __toESM(require("path"), 1);
|
|
50908
|
-
init_src();
|
|
50909
50784
|
var FILE_NAME = "contacts.json";
|
|
50910
50785
|
var ContactStore = class {
|
|
50911
50786
|
constructor(dataDir) {
|
|
@@ -51156,9 +51031,6 @@ async function autoReverseContact(args) {
|
|
|
51156
51031
|
args.broadcast({ type: "contact:added", contact: upgraded });
|
|
51157
51032
|
}
|
|
51158
51033
|
|
|
51159
|
-
// src/index.ts
|
|
51160
|
-
init_src();
|
|
51161
|
-
|
|
51162
51034
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
51163
51035
|
var fs33 = __toESM(require("fs"), 1);
|
|
51164
51036
|
var path32 = __toESM(require("path"), 1);
|
|
@@ -51541,7 +51413,6 @@ var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
|
51541
51413
|
var import_node_path27 = __toESM(require("path"), 1);
|
|
51542
51414
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
51543
51415
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
51544
|
-
init_src();
|
|
51545
51416
|
var ImportError = class extends Error {
|
|
51546
51417
|
constructor(code, message) {
|
|
51547
51418
|
super(message);
|
|
@@ -53676,8 +53547,45 @@ function readIssuedPubkey(sshdDir, deviceId) {
|
|
|
53676
53547
|
// src/sshd/contact-key-puller.ts
|
|
53677
53548
|
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
53678
53549
|
var import_node_path42 = __toESM(require("path"), 1);
|
|
53679
|
-
|
|
53680
|
-
|
|
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
|
|
53681
53589
|
var CONTACT_KEYS_DIR = "contact-ssh-keys";
|
|
53682
53590
|
function safeContactKeyPath(dataDir, deviceId) {
|
|
53683
53591
|
const safeId = deviceId.replace(/[\/\\]/g, "_");
|
|
@@ -53789,7 +53697,6 @@ var ContactKeyPuller = class {
|
|
|
53789
53697
|
|
|
53790
53698
|
// src/sshd/ssh-tunnel-relay.ts
|
|
53791
53699
|
var import_node_net2 = __toESM(require("net"), 1);
|
|
53792
|
-
init_contact_ssh_log();
|
|
53793
53700
|
async function handleSshTunnelUpgrade(req, socket, head, deps) {
|
|
53794
53701
|
const sshLog = deps.sshLog ?? nullContactSshLog;
|
|
53795
53702
|
const clientAddr = (req.socket && "remoteAddress" in req.socket ? req.socket.remoteAddress : null) ?? "unknown";
|
|
@@ -53897,8 +53804,161 @@ function pumpWsToSshd(ws, deps, clientAddr) {
|
|
|
53897
53804
|
});
|
|
53898
53805
|
}
|
|
53899
53806
|
|
|
53900
|
-
// src/
|
|
53901
|
-
|
|
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
|
+
}
|
|
53902
53962
|
|
|
53903
53963
|
// src/tunnel/device-key.ts
|
|
53904
53964
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
@@ -54188,9 +54248,9 @@ var CentralClientError = class extends Error {
|
|
|
54188
54248
|
code;
|
|
54189
54249
|
cause;
|
|
54190
54250
|
};
|
|
54191
|
-
async function centralRequest(opts,
|
|
54251
|
+
async function centralRequest(opts, path77, init) {
|
|
54192
54252
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
54193
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
54253
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path77}`;
|
|
54194
54254
|
const ctrl = new AbortController();
|
|
54195
54255
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
54196
54256
|
let res;
|
|
@@ -55180,7 +55240,6 @@ function buildCapabilitiesHandlers(deps) {
|
|
|
55180
55240
|
|
|
55181
55241
|
// src/handlers/capability.ts
|
|
55182
55242
|
init_zod();
|
|
55183
|
-
init_src();
|
|
55184
55243
|
init_protocol();
|
|
55185
55244
|
var DeleteArgsSchema = external_exports.object({
|
|
55186
55245
|
capabilityId: external_exports.string().min(1)
|
|
@@ -55219,7 +55278,6 @@ function buildCapabilityHandlers(deps) {
|
|
|
55219
55278
|
}
|
|
55220
55279
|
|
|
55221
55280
|
// src/handlers/inbox.ts
|
|
55222
|
-
init_src();
|
|
55223
55281
|
init_protocol();
|
|
55224
55282
|
function resolvePeerDeviceId(ctx, argsPeerDeviceId) {
|
|
55225
55283
|
if (ctx.principal.kind === "owner") {
|
|
@@ -55398,7 +55456,6 @@ function buildInboxHandlers(deps) {
|
|
|
55398
55456
|
}
|
|
55399
55457
|
|
|
55400
55458
|
// src/handlers/contact.ts
|
|
55401
|
-
init_src();
|
|
55402
55459
|
init_protocol();
|
|
55403
55460
|
function ensureOwner(ctx) {
|
|
55404
55461
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -55467,7 +55524,6 @@ function buildContactHandlers(deps) {
|
|
|
55467
55524
|
}
|
|
55468
55525
|
|
|
55469
55526
|
// src/handlers/contact-ssh.ts
|
|
55470
|
-
init_src();
|
|
55471
55527
|
init_protocol();
|
|
55472
55528
|
|
|
55473
55529
|
// src/sshd/key-issue.ts
|
|
@@ -55514,7 +55570,6 @@ async function issueContactSshKey(deviceId, sshdDir, opts = {}) {
|
|
|
55514
55570
|
}
|
|
55515
55571
|
|
|
55516
55572
|
// src/handlers/contact-ssh.ts
|
|
55517
|
-
init_contact_ssh_log();
|
|
55518
55573
|
function ensureOwner2(ctx) {
|
|
55519
55574
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
55520
55575
|
throw new ClawdError(
|
|
@@ -55617,7 +55672,6 @@ function buildContactSshHandlers(deps) {
|
|
|
55617
55672
|
}
|
|
55618
55673
|
|
|
55619
55674
|
// src/handlers/whoami.ts
|
|
55620
|
-
init_src();
|
|
55621
55675
|
init_protocol();
|
|
55622
55676
|
function buildWhoamiHandler(deps) {
|
|
55623
55677
|
return async (_frame, _client, ctx) => {
|
|
@@ -55711,7 +55765,6 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
55711
55765
|
}
|
|
55712
55766
|
|
|
55713
55767
|
// src/handlers/device.ts
|
|
55714
|
-
init_src();
|
|
55715
55768
|
init_protocol();
|
|
55716
55769
|
function ensureOwner3(ctx) {
|
|
55717
55770
|
if (!ctx || ctx.principal.kind !== "owner") {
|
|
@@ -56116,7 +56169,6 @@ function buildAttachmentHandlers(deps) {
|
|
|
56116
56169
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
56117
56170
|
var import_node_path55 = __toESM(require("path"), 1);
|
|
56118
56171
|
init_protocol();
|
|
56119
|
-
init_src();
|
|
56120
56172
|
|
|
56121
56173
|
// src/extension/bundle-zip.ts
|
|
56122
56174
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
@@ -56162,8 +56214,6 @@ async function walk(absRoot, relPrefix, out) {
|
|
|
56162
56214
|
}
|
|
56163
56215
|
|
|
56164
56216
|
// src/extension/publish-check.ts
|
|
56165
|
-
init_src();
|
|
56166
|
-
init_src();
|
|
56167
56217
|
function computePublishCheck(args) {
|
|
56168
56218
|
const { localHash, localVersion, head } = args;
|
|
56169
56219
|
if (head === null) {
|
|
@@ -56208,12 +56258,10 @@ var import_node_path53 = __toESM(require("path"), 1);
|
|
|
56208
56258
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
56209
56259
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
56210
56260
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
56211
|
-
init_src();
|
|
56212
56261
|
|
|
56213
56262
|
// src/extension/paths.ts
|
|
56214
56263
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
56215
56264
|
var import_node_path52 = __toESM(require("path"), 1);
|
|
56216
|
-
init_src();
|
|
56217
56265
|
function clawdHomeRoot(override) {
|
|
56218
56266
|
return override ?? process.env.CLAWD_HOME ?? import_node_path52.default.join(import_node_os18.default.homedir(), ".clawd");
|
|
56219
56267
|
}
|
|
@@ -56331,7 +56379,6 @@ var import_node_path54 = __toESM(require("path"), 1);
|
|
|
56331
56379
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
56332
56380
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
56333
56381
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
56334
|
-
init_src();
|
|
56335
56382
|
var UpdateError = class extends Error {
|
|
56336
56383
|
constructor(code, message) {
|
|
56337
56384
|
super(message);
|
|
@@ -56477,7 +56524,6 @@ async function rollback(deps, localExtId, liveDir, prevDir) {
|
|
|
56477
56524
|
}
|
|
56478
56525
|
|
|
56479
56526
|
// src/handlers/extension.ts
|
|
56480
|
-
init_src();
|
|
56481
56527
|
function pickChannelRef(frame) {
|
|
56482
56528
|
const ref = frame.channelRef;
|
|
56483
56529
|
const parsed = ChannelRefSchema.safeParse(ref);
|
|
@@ -57968,7 +58014,6 @@ function buildVisitorHandlers(deps) {
|
|
|
57968
58014
|
// src/extension/registry.ts
|
|
57969
58015
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
57970
58016
|
var import_node_path59 = __toESM(require("path"), 1);
|
|
57971
|
-
init_src();
|
|
57972
58017
|
async function loadAll(root) {
|
|
57973
58018
|
let entries;
|
|
57974
58019
|
try {
|
|
@@ -58053,7 +58098,6 @@ async function uninstall(deps) {
|
|
|
58053
58098
|
|
|
58054
58099
|
// src/handlers/index.ts
|
|
58055
58100
|
var import_node_crypto18 = require("crypto");
|
|
58056
|
-
init_peer_forward();
|
|
58057
58101
|
function buildMethodHandlers(deps) {
|
|
58058
58102
|
return {
|
|
58059
58103
|
...buildSessionHandlers({
|
|
@@ -58627,7 +58671,6 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
58627
58671
|
var import_node_child_process18 = require("child_process");
|
|
58628
58672
|
var import_node_path61 = __toESM(require("path"), 1);
|
|
58629
58673
|
var import_promises11 = require("timers/promises");
|
|
58630
|
-
init_src();
|
|
58631
58674
|
|
|
58632
58675
|
// src/extension/port-allocator.ts
|
|
58633
58676
|
var import_node_net3 = __toESM(require("net"), 1);
|
|
@@ -58840,7 +58883,6 @@ ${handle.stderrTail}`
|
|
|
58840
58883
|
// src/extension/published-channels.ts
|
|
58841
58884
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
58842
58885
|
var import_node_path62 = __toESM(require("path"), 1);
|
|
58843
|
-
init_src();
|
|
58844
58886
|
init_zod();
|
|
58845
58887
|
var PublishedChannelsError = class extends Error {
|
|
58846
58888
|
constructor(code, message) {
|
|
@@ -59920,6 +59962,18 @@ async function startDaemon(config) {
|
|
|
59920
59962
|
});
|
|
59921
59963
|
return true;
|
|
59922
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
|
+
},
|
|
59923
59977
|
// 订阅成功后给该 client 重放 in-flight pendingQuestions(plan: clawd-question-server-truth)。
|
|
59924
59978
|
// daemon 是 pendingQuestions 的唯一 source of truth;新 client 接入 / 刷新页面时
|
|
59925
59979
|
// 把当前所有未决 question 以 session:question 帧定向回放,让 UI 不再误显示 Ended。
|