@clawos-dev/clawd 0.2.87-beta.163.de7e74a → 0.2.87
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 +472 -337
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -643,8 +643,8 @@ var init_parseUtil = __esm({
|
|
|
643
643
|
init_errors2();
|
|
644
644
|
init_en();
|
|
645
645
|
makeIssue = (params) => {
|
|
646
|
-
const { data, path:
|
|
647
|
-
const fullPath = [...
|
|
646
|
+
const { data, path: path46, errorMaps, issueData } = params;
|
|
647
|
+
const fullPath = [...path46, ...issueData.path || []];
|
|
648
648
|
const fullIssue = {
|
|
649
649
|
...issueData,
|
|
650
650
|
path: fullPath
|
|
@@ -955,11 +955,11 @@ var init_types = __esm({
|
|
|
955
955
|
init_parseUtil();
|
|
956
956
|
init_util();
|
|
957
957
|
ParseInputLazyPath = class {
|
|
958
|
-
constructor(parent, value,
|
|
958
|
+
constructor(parent, value, path46, key) {
|
|
959
959
|
this._cachedPath = [];
|
|
960
960
|
this.parent = parent;
|
|
961
961
|
this.data = value;
|
|
962
|
-
this._path =
|
|
962
|
+
this._path = path46;
|
|
963
963
|
this._key = key;
|
|
964
964
|
}
|
|
965
965
|
get path() {
|
|
@@ -5590,8 +5590,8 @@ var require_req = __commonJS({
|
|
|
5590
5590
|
if (req.originalUrl) {
|
|
5591
5591
|
_req.url = req.originalUrl;
|
|
5592
5592
|
} else {
|
|
5593
|
-
const
|
|
5594
|
-
_req.url = typeof
|
|
5593
|
+
const path46 = req.path;
|
|
5594
|
+
_req.url = typeof path46 === "string" ? path46 : req.url ? req.url.path || req.url : void 0;
|
|
5595
5595
|
}
|
|
5596
5596
|
if (req.query) {
|
|
5597
5597
|
_req.query = req.query;
|
|
@@ -5756,14 +5756,14 @@ var require_redact = __commonJS({
|
|
|
5756
5756
|
}
|
|
5757
5757
|
return obj;
|
|
5758
5758
|
}
|
|
5759
|
-
function parsePath(
|
|
5759
|
+
function parsePath(path46) {
|
|
5760
5760
|
const parts = [];
|
|
5761
5761
|
let current = "";
|
|
5762
5762
|
let inBrackets = false;
|
|
5763
5763
|
let inQuotes = false;
|
|
5764
5764
|
let quoteChar = "";
|
|
5765
|
-
for (let i = 0; i <
|
|
5766
|
-
const char =
|
|
5765
|
+
for (let i = 0; i < path46.length; i++) {
|
|
5766
|
+
const char = path46[i];
|
|
5767
5767
|
if (!inBrackets && char === ".") {
|
|
5768
5768
|
if (current) {
|
|
5769
5769
|
parts.push(current);
|
|
@@ -5894,10 +5894,10 @@ var require_redact = __commonJS({
|
|
|
5894
5894
|
return current;
|
|
5895
5895
|
}
|
|
5896
5896
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
5897
|
-
for (const
|
|
5898
|
-
const parts = parsePath(
|
|
5897
|
+
for (const path46 of paths) {
|
|
5898
|
+
const parts = parsePath(path46);
|
|
5899
5899
|
if (parts.includes("*")) {
|
|
5900
|
-
redactWildcardPath(obj, parts, censor,
|
|
5900
|
+
redactWildcardPath(obj, parts, censor, path46, remove);
|
|
5901
5901
|
} else {
|
|
5902
5902
|
if (remove) {
|
|
5903
5903
|
removeKey(obj, parts);
|
|
@@ -5982,8 +5982,8 @@ var require_redact = __commonJS({
|
|
|
5982
5982
|
}
|
|
5983
5983
|
} else {
|
|
5984
5984
|
if (afterWildcard.includes("*")) {
|
|
5985
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
5986
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
5985
|
+
const wrappedCensor = typeof censor === "function" ? (value, path46) => {
|
|
5986
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path46];
|
|
5987
5987
|
return censor(value, fullPath);
|
|
5988
5988
|
} : censor;
|
|
5989
5989
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6018,8 +6018,8 @@ var require_redact = __commonJS({
|
|
|
6018
6018
|
return null;
|
|
6019
6019
|
}
|
|
6020
6020
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6021
|
-
for (const
|
|
6022
|
-
const parts = parsePath(
|
|
6021
|
+
for (const path46 of pathsToClone) {
|
|
6022
|
+
const parts = parsePath(path46);
|
|
6023
6023
|
let current = pathStructure;
|
|
6024
6024
|
for (let i = 0; i < parts.length; i++) {
|
|
6025
6025
|
const part = parts[i];
|
|
@@ -6071,24 +6071,24 @@ var require_redact = __commonJS({
|
|
|
6071
6071
|
}
|
|
6072
6072
|
return cloneSelectively(obj, pathStructure);
|
|
6073
6073
|
}
|
|
6074
|
-
function validatePath(
|
|
6075
|
-
if (typeof
|
|
6074
|
+
function validatePath(path46) {
|
|
6075
|
+
if (typeof path46 !== "string") {
|
|
6076
6076
|
throw new Error("Paths must be (non-empty) strings");
|
|
6077
6077
|
}
|
|
6078
|
-
if (
|
|
6078
|
+
if (path46 === "") {
|
|
6079
6079
|
throw new Error("Invalid redaction path ()");
|
|
6080
6080
|
}
|
|
6081
|
-
if (
|
|
6082
|
-
throw new Error(`Invalid redaction path (${
|
|
6081
|
+
if (path46.includes("..")) {
|
|
6082
|
+
throw new Error(`Invalid redaction path (${path46})`);
|
|
6083
6083
|
}
|
|
6084
|
-
if (
|
|
6085
|
-
throw new Error(`Invalid redaction path (${
|
|
6084
|
+
if (path46.includes(",")) {
|
|
6085
|
+
throw new Error(`Invalid redaction path (${path46})`);
|
|
6086
6086
|
}
|
|
6087
6087
|
let bracketCount = 0;
|
|
6088
6088
|
let inQuotes = false;
|
|
6089
6089
|
let quoteChar = "";
|
|
6090
|
-
for (let i = 0; i <
|
|
6091
|
-
const char =
|
|
6090
|
+
for (let i = 0; i < path46.length; i++) {
|
|
6091
|
+
const char = path46[i];
|
|
6092
6092
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6093
6093
|
if (!inQuotes) {
|
|
6094
6094
|
inQuotes = true;
|
|
@@ -6102,20 +6102,20 @@ var require_redact = __commonJS({
|
|
|
6102
6102
|
} else if (char === "]" && !inQuotes) {
|
|
6103
6103
|
bracketCount--;
|
|
6104
6104
|
if (bracketCount < 0) {
|
|
6105
|
-
throw new Error(`Invalid redaction path (${
|
|
6105
|
+
throw new Error(`Invalid redaction path (${path46})`);
|
|
6106
6106
|
}
|
|
6107
6107
|
}
|
|
6108
6108
|
}
|
|
6109
6109
|
if (bracketCount !== 0) {
|
|
6110
|
-
throw new Error(`Invalid redaction path (${
|
|
6110
|
+
throw new Error(`Invalid redaction path (${path46})`);
|
|
6111
6111
|
}
|
|
6112
6112
|
}
|
|
6113
6113
|
function validatePaths(paths) {
|
|
6114
6114
|
if (!Array.isArray(paths)) {
|
|
6115
6115
|
throw new TypeError("paths must be an array");
|
|
6116
6116
|
}
|
|
6117
|
-
for (const
|
|
6118
|
-
validatePath(
|
|
6117
|
+
for (const path46 of paths) {
|
|
6118
|
+
validatePath(path46);
|
|
6119
6119
|
}
|
|
6120
6120
|
}
|
|
6121
6121
|
function slowRedact(options = {}) {
|
|
@@ -6283,8 +6283,8 @@ var require_redaction = __commonJS({
|
|
|
6283
6283
|
if (shape[k2] === null) {
|
|
6284
6284
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6285
6285
|
} else {
|
|
6286
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6287
|
-
return censor(value, [k2, ...
|
|
6286
|
+
const wrappedCensor = typeof censor === "function" ? (value, path46) => {
|
|
6287
|
+
return censor(value, [k2, ...path46]);
|
|
6288
6288
|
} : censor;
|
|
6289
6289
|
o[k2] = Redact({
|
|
6290
6290
|
paths: shape[k2],
|
|
@@ -6502,10 +6502,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
6502
6502
|
var require_sonic_boom = __commonJS({
|
|
6503
6503
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
6504
6504
|
"use strict";
|
|
6505
|
-
var
|
|
6505
|
+
var fs37 = require("fs");
|
|
6506
6506
|
var EventEmitter2 = require("events");
|
|
6507
6507
|
var inherits = require("util").inherits;
|
|
6508
|
-
var
|
|
6508
|
+
var path46 = require("path");
|
|
6509
6509
|
var sleep = require_atomic_sleep();
|
|
6510
6510
|
var assert = require("assert");
|
|
6511
6511
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -6559,20 +6559,20 @@ var require_sonic_boom = __commonJS({
|
|
|
6559
6559
|
const mode = sonic.mode;
|
|
6560
6560
|
if (sonic.sync) {
|
|
6561
6561
|
try {
|
|
6562
|
-
if (sonic.mkdir)
|
|
6563
|
-
const fd =
|
|
6562
|
+
if (sonic.mkdir) fs37.mkdirSync(path46.dirname(file), { recursive: true });
|
|
6563
|
+
const fd = fs37.openSync(file, flags, mode);
|
|
6564
6564
|
fileOpened(null, fd);
|
|
6565
6565
|
} catch (err) {
|
|
6566
6566
|
fileOpened(err);
|
|
6567
6567
|
throw err;
|
|
6568
6568
|
}
|
|
6569
6569
|
} else if (sonic.mkdir) {
|
|
6570
|
-
|
|
6570
|
+
fs37.mkdir(path46.dirname(file), { recursive: true }, (err) => {
|
|
6571
6571
|
if (err) return fileOpened(err);
|
|
6572
|
-
|
|
6572
|
+
fs37.open(file, flags, mode, fileOpened);
|
|
6573
6573
|
});
|
|
6574
6574
|
} else {
|
|
6575
|
-
|
|
6575
|
+
fs37.open(file, flags, mode, fileOpened);
|
|
6576
6576
|
}
|
|
6577
6577
|
}
|
|
6578
6578
|
function SonicBoom(opts) {
|
|
@@ -6613,8 +6613,8 @@ var require_sonic_boom = __commonJS({
|
|
|
6613
6613
|
this.flush = flushBuffer;
|
|
6614
6614
|
this.flushSync = flushBufferSync;
|
|
6615
6615
|
this._actualWrite = actualWriteBuffer;
|
|
6616
|
-
fsWriteSync = () =>
|
|
6617
|
-
fsWrite = () =>
|
|
6616
|
+
fsWriteSync = () => fs37.writeSync(this.fd, this._writingBuf);
|
|
6617
|
+
fsWrite = () => fs37.write(this.fd, this._writingBuf, this.release);
|
|
6618
6618
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
6619
6619
|
this._writingBuf = "";
|
|
6620
6620
|
this.write = write;
|
|
@@ -6623,15 +6623,15 @@ var require_sonic_boom = __commonJS({
|
|
|
6623
6623
|
this._actualWrite = actualWrite;
|
|
6624
6624
|
fsWriteSync = () => {
|
|
6625
6625
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6626
|
-
return
|
|
6626
|
+
return fs37.writeSync(this.fd, this._writingBuf);
|
|
6627
6627
|
}
|
|
6628
|
-
return
|
|
6628
|
+
return fs37.writeSync(this.fd, this._writingBuf, "utf8");
|
|
6629
6629
|
};
|
|
6630
6630
|
fsWrite = () => {
|
|
6631
6631
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6632
|
-
return
|
|
6632
|
+
return fs37.write(this.fd, this._writingBuf, this.release);
|
|
6633
6633
|
}
|
|
6634
|
-
return
|
|
6634
|
+
return fs37.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
6635
6635
|
};
|
|
6636
6636
|
} else {
|
|
6637
6637
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -6688,7 +6688,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6688
6688
|
}
|
|
6689
6689
|
}
|
|
6690
6690
|
if (this._fsync) {
|
|
6691
|
-
|
|
6691
|
+
fs37.fsyncSync(this.fd);
|
|
6692
6692
|
}
|
|
6693
6693
|
const len = this._len;
|
|
6694
6694
|
if (this._reopening) {
|
|
@@ -6802,7 +6802,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6802
6802
|
const onDrain = () => {
|
|
6803
6803
|
if (!this._fsync) {
|
|
6804
6804
|
try {
|
|
6805
|
-
|
|
6805
|
+
fs37.fsync(this.fd, (err) => {
|
|
6806
6806
|
this._flushPending = false;
|
|
6807
6807
|
cb(err);
|
|
6808
6808
|
});
|
|
@@ -6904,7 +6904,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6904
6904
|
const fd = this.fd;
|
|
6905
6905
|
this.once("ready", () => {
|
|
6906
6906
|
if (fd !== this.fd) {
|
|
6907
|
-
|
|
6907
|
+
fs37.close(fd, (err) => {
|
|
6908
6908
|
if (err) {
|
|
6909
6909
|
return this.emit("error", err);
|
|
6910
6910
|
}
|
|
@@ -6953,7 +6953,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6953
6953
|
buf = this._bufs[0];
|
|
6954
6954
|
}
|
|
6955
6955
|
try {
|
|
6956
|
-
const n = Buffer.isBuffer(buf) ?
|
|
6956
|
+
const n = Buffer.isBuffer(buf) ? fs37.writeSync(this.fd, buf) : fs37.writeSync(this.fd, buf, "utf8");
|
|
6957
6957
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
6958
6958
|
buf = releasedBufObj.writingBuf;
|
|
6959
6959
|
this._len = releasedBufObj.len;
|
|
@@ -6969,7 +6969,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6969
6969
|
}
|
|
6970
6970
|
}
|
|
6971
6971
|
try {
|
|
6972
|
-
|
|
6972
|
+
fs37.fsyncSync(this.fd);
|
|
6973
6973
|
} catch {
|
|
6974
6974
|
}
|
|
6975
6975
|
}
|
|
@@ -6990,7 +6990,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6990
6990
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
6991
6991
|
}
|
|
6992
6992
|
try {
|
|
6993
|
-
const n =
|
|
6993
|
+
const n = fs37.writeSync(this.fd, buf);
|
|
6994
6994
|
buf = buf.subarray(n);
|
|
6995
6995
|
this._len = Math.max(this._len - n, 0);
|
|
6996
6996
|
if (buf.length <= 0) {
|
|
@@ -7018,13 +7018,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7018
7018
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7019
7019
|
if (this.sync) {
|
|
7020
7020
|
try {
|
|
7021
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7021
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs37.writeSync(this.fd, this._writingBuf) : fs37.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7022
7022
|
release(null, written);
|
|
7023
7023
|
} catch (err) {
|
|
7024
7024
|
release(err);
|
|
7025
7025
|
}
|
|
7026
7026
|
} else {
|
|
7027
|
-
|
|
7027
|
+
fs37.write(this.fd, this._writingBuf, release);
|
|
7028
7028
|
}
|
|
7029
7029
|
}
|
|
7030
7030
|
function actualWriteBuffer() {
|
|
@@ -7033,7 +7033,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7033
7033
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7034
7034
|
if (this.sync) {
|
|
7035
7035
|
try {
|
|
7036
|
-
const written =
|
|
7036
|
+
const written = fs37.writeSync(this.fd, this._writingBuf);
|
|
7037
7037
|
release(null, written);
|
|
7038
7038
|
} catch (err) {
|
|
7039
7039
|
release(err);
|
|
@@ -7042,7 +7042,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7042
7042
|
if (kCopyBuffer) {
|
|
7043
7043
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7044
7044
|
}
|
|
7045
|
-
|
|
7045
|
+
fs37.write(this.fd, this._writingBuf, release);
|
|
7046
7046
|
}
|
|
7047
7047
|
}
|
|
7048
7048
|
function actualClose(sonic) {
|
|
@@ -7058,12 +7058,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7058
7058
|
sonic._lens = [];
|
|
7059
7059
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7060
7060
|
try {
|
|
7061
|
-
|
|
7061
|
+
fs37.fsync(sonic.fd, closeWrapped);
|
|
7062
7062
|
} catch {
|
|
7063
7063
|
}
|
|
7064
7064
|
function closeWrapped() {
|
|
7065
7065
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7066
|
-
|
|
7066
|
+
fs37.close(sonic.fd, done);
|
|
7067
7067
|
} else {
|
|
7068
7068
|
done();
|
|
7069
7069
|
}
|
|
@@ -9427,7 +9427,7 @@ var require_multistream = __commonJS({
|
|
|
9427
9427
|
var require_pino = __commonJS({
|
|
9428
9428
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
9429
9429
|
"use strict";
|
|
9430
|
-
var
|
|
9430
|
+
var os17 = require("os");
|
|
9431
9431
|
var stdSerializers = require_pino_std_serializers();
|
|
9432
9432
|
var caller = require_caller();
|
|
9433
9433
|
var redaction = require_redaction();
|
|
@@ -9474,7 +9474,7 @@ var require_pino = __commonJS({
|
|
|
9474
9474
|
} = symbols;
|
|
9475
9475
|
var { epochTime, nullTime } = time;
|
|
9476
9476
|
var { pid } = process;
|
|
9477
|
-
var hostname =
|
|
9477
|
+
var hostname = os17.hostname();
|
|
9478
9478
|
var defaultErrorSerializer = stdSerializers.err;
|
|
9479
9479
|
var defaultOptions = {
|
|
9480
9480
|
level: "info",
|
|
@@ -10198,11 +10198,11 @@ var init_lib = __esm({
|
|
|
10198
10198
|
}
|
|
10199
10199
|
}
|
|
10200
10200
|
},
|
|
10201
|
-
addToPath: function addToPath(
|
|
10202
|
-
var last =
|
|
10201
|
+
addToPath: function addToPath(path46, added, removed, oldPosInc, options) {
|
|
10202
|
+
var last = path46.lastComponent;
|
|
10203
10203
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10204
10204
|
return {
|
|
10205
|
-
oldPos:
|
|
10205
|
+
oldPos: path46.oldPos + oldPosInc,
|
|
10206
10206
|
lastComponent: {
|
|
10207
10207
|
count: last.count + 1,
|
|
10208
10208
|
added,
|
|
@@ -10212,7 +10212,7 @@ var init_lib = __esm({
|
|
|
10212
10212
|
};
|
|
10213
10213
|
} else {
|
|
10214
10214
|
return {
|
|
10215
|
-
oldPos:
|
|
10215
|
+
oldPos: path46.oldPos + oldPosInc,
|
|
10216
10216
|
lastComponent: {
|
|
10217
10217
|
count: 1,
|
|
10218
10218
|
added,
|
|
@@ -10643,10 +10643,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
10643
10643
|
const memories = raw.map((m2) => {
|
|
10644
10644
|
if (!m2 || typeof m2 !== "object") return null;
|
|
10645
10645
|
const rec = m2;
|
|
10646
|
-
const
|
|
10646
|
+
const path46 = typeof rec.path === "string" ? rec.path : null;
|
|
10647
10647
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10648
|
-
if (!
|
|
10649
|
-
const entry = { path:
|
|
10648
|
+
if (!path46 || content == null) return null;
|
|
10649
|
+
const entry = { path: path46, content };
|
|
10650
10650
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
10651
10651
|
return entry;
|
|
10652
10652
|
}).filter((m2) => m2 !== null);
|
|
@@ -11472,10 +11472,10 @@ function parseAttachment(obj) {
|
|
|
11472
11472
|
const memories = raw.map((m2) => {
|
|
11473
11473
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11474
11474
|
const rec = m2;
|
|
11475
|
-
const
|
|
11475
|
+
const path46 = typeof rec.path === "string" ? rec.path : null;
|
|
11476
11476
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11477
|
-
if (!
|
|
11478
|
-
const out = { path:
|
|
11477
|
+
if (!path46 || content == null) return null;
|
|
11478
|
+
const out = { path: path46, content };
|
|
11479
11479
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
11480
11480
|
return out;
|
|
11481
11481
|
}).filter((m2) => m2 !== null);
|
|
@@ -20390,7 +20390,7 @@ var require_websocket_server = __commonJS({
|
|
|
20390
20390
|
// src/run-case/recorder.ts
|
|
20391
20391
|
function startRunCaseRecorder(opts) {
|
|
20392
20392
|
const now = opts.now ?? Date.now;
|
|
20393
|
-
const dir =
|
|
20393
|
+
const dir = import_node_path32.default.dirname(opts.recordPath);
|
|
20394
20394
|
let stream = null;
|
|
20395
20395
|
let closing = false;
|
|
20396
20396
|
let closedSettled = false;
|
|
@@ -20404,8 +20404,8 @@ function startRunCaseRecorder(opts) {
|
|
|
20404
20404
|
});
|
|
20405
20405
|
const ensureStream = () => {
|
|
20406
20406
|
if (stream) return stream;
|
|
20407
|
-
|
|
20408
|
-
stream =
|
|
20407
|
+
import_node_fs29.default.mkdirSync(dir, { recursive: true });
|
|
20408
|
+
stream = import_node_fs29.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
20409
20409
|
stream.on("close", () => closedResolve());
|
|
20410
20410
|
return stream;
|
|
20411
20411
|
};
|
|
@@ -20430,12 +20430,12 @@ function startRunCaseRecorder(opts) {
|
|
|
20430
20430
|
};
|
|
20431
20431
|
return { tap, close, closed };
|
|
20432
20432
|
}
|
|
20433
|
-
var
|
|
20433
|
+
var import_node_fs29, import_node_path32;
|
|
20434
20434
|
var init_recorder = __esm({
|
|
20435
20435
|
"src/run-case/recorder.ts"() {
|
|
20436
20436
|
"use strict";
|
|
20437
|
-
|
|
20438
|
-
|
|
20437
|
+
import_node_fs29 = __toESM(require("fs"), 1);
|
|
20438
|
+
import_node_path32 = __toESM(require("path"), 1);
|
|
20439
20439
|
}
|
|
20440
20440
|
});
|
|
20441
20441
|
|
|
@@ -20478,7 +20478,7 @@ var init_wire = __esm({
|
|
|
20478
20478
|
// src/run-case/controller.ts
|
|
20479
20479
|
async function runController(opts) {
|
|
20480
20480
|
const now = opts.now ?? Date.now;
|
|
20481
|
-
const cwd = opts.cwd ?? (0,
|
|
20481
|
+
const cwd = opts.cwd ?? (0, import_node_fs30.mkdtempSync)(import_node_path33.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
|
|
20482
20482
|
const ownsCwd = opts.cwd === void 0;
|
|
20483
20483
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
20484
20484
|
const spawnCtx = { cwd };
|
|
@@ -20639,19 +20639,19 @@ async function runController(opts) {
|
|
|
20639
20639
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
20640
20640
|
if (ownsCwd) {
|
|
20641
20641
|
try {
|
|
20642
|
-
(0,
|
|
20642
|
+
(0, import_node_fs30.rmSync)(cwd, { recursive: true, force: true });
|
|
20643
20643
|
} catch {
|
|
20644
20644
|
}
|
|
20645
20645
|
}
|
|
20646
20646
|
return exitCode ?? 0;
|
|
20647
20647
|
}
|
|
20648
|
-
var
|
|
20648
|
+
var import_node_fs30, import_node_os15, import_node_path33;
|
|
20649
20649
|
var init_controller = __esm({
|
|
20650
20650
|
"src/run-case/controller.ts"() {
|
|
20651
20651
|
"use strict";
|
|
20652
|
-
|
|
20653
|
-
|
|
20654
|
-
|
|
20652
|
+
import_node_fs30 = require("fs");
|
|
20653
|
+
import_node_os15 = __toESM(require("os"), 1);
|
|
20654
|
+
import_node_path33 = __toESM(require("path"), 1);
|
|
20655
20655
|
init_claude();
|
|
20656
20656
|
init_stdout_splitter();
|
|
20657
20657
|
init_permission_stdio();
|
|
@@ -20883,8 +20883,8 @@ Env (advanced):
|
|
|
20883
20883
|
`;
|
|
20884
20884
|
|
|
20885
20885
|
// src/index.ts
|
|
20886
|
-
var
|
|
20887
|
-
var
|
|
20886
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
20887
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
20888
20888
|
|
|
20889
20889
|
// src/logger.ts
|
|
20890
20890
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -25531,11 +25531,18 @@ var AgentsScanner = class {
|
|
|
25531
25531
|
};
|
|
25532
25532
|
|
|
25533
25533
|
// src/observer/session-observer.ts
|
|
25534
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
25535
|
+
var import_node_os9 = __toESM(require("os"), 1);
|
|
25536
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
25537
|
+
init_claude_history();
|
|
25538
|
+
|
|
25539
|
+
// src/observer/subagent-meta-observer.ts
|
|
25534
25540
|
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
25535
25541
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
25536
25542
|
var import_node_path13 = __toESM(require("path"), 1);
|
|
25537
25543
|
init_claude_history();
|
|
25538
|
-
var
|
|
25544
|
+
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
25545
|
+
var SubagentMetaObserver = class {
|
|
25539
25546
|
constructor(opts) {
|
|
25540
25547
|
this.opts = opts;
|
|
25541
25548
|
this.home = opts.home ?? import_node_os8.default.homedir();
|
|
@@ -25543,16 +25550,132 @@ var SessionObserver = class {
|
|
|
25543
25550
|
opts;
|
|
25544
25551
|
home;
|
|
25545
25552
|
watches = /* @__PURE__ */ new Map();
|
|
25553
|
+
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
25554
|
+
resolveSubagentDir(cwd, toolSessionId) {
|
|
25555
|
+
return import_node_path13.default.join(
|
|
25556
|
+
this.home,
|
|
25557
|
+
".claude",
|
|
25558
|
+
"projects",
|
|
25559
|
+
cwdToHashDir(cwd),
|
|
25560
|
+
toolSessionId,
|
|
25561
|
+
"subagents"
|
|
25562
|
+
);
|
|
25563
|
+
}
|
|
25564
|
+
start(args) {
|
|
25565
|
+
this.stop(args.sessionId);
|
|
25566
|
+
const dirPath = this.resolveSubagentDir(args.cwd, args.toolSessionId);
|
|
25567
|
+
const w2 = {
|
|
25568
|
+
sessionId: args.sessionId,
|
|
25569
|
+
dirPath,
|
|
25570
|
+
watcher: null,
|
|
25571
|
+
pollTimer: null,
|
|
25572
|
+
emitted: /* @__PURE__ */ new Set()
|
|
25573
|
+
};
|
|
25574
|
+
this.watches.set(args.sessionId, w2);
|
|
25575
|
+
this.scan(w2);
|
|
25576
|
+
this.attachWatcher(w2);
|
|
25577
|
+
w2.pollTimer = setInterval(() => this.scan(w2), 200);
|
|
25578
|
+
return { dirPath };
|
|
25579
|
+
}
|
|
25580
|
+
// fs.watch 必须在目录存在后调用;首次启动时 subagents/ 通常不存在 —— attachWatcher
|
|
25581
|
+
// 失败就交给 pollTimer 200ms 兜底,目录一出现就被下次 poll 捡起来,那时也尝试 attach
|
|
25582
|
+
attachWatcher(w2) {
|
|
25583
|
+
if (w2.watcher) return;
|
|
25584
|
+
try {
|
|
25585
|
+
w2.watcher = import_node_fs12.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
25586
|
+
if (!name) return;
|
|
25587
|
+
const m2 = META_RE.exec(String(name));
|
|
25588
|
+
if (!m2) return;
|
|
25589
|
+
this.scanOne(w2, String(name));
|
|
25590
|
+
});
|
|
25591
|
+
} catch {
|
|
25592
|
+
}
|
|
25593
|
+
}
|
|
25594
|
+
scan(w2) {
|
|
25595
|
+
let entries;
|
|
25596
|
+
try {
|
|
25597
|
+
entries = import_node_fs12.default.readdirSync(w2.dirPath);
|
|
25598
|
+
} catch {
|
|
25599
|
+
return;
|
|
25600
|
+
}
|
|
25601
|
+
if (!w2.watcher) this.attachWatcher(w2);
|
|
25602
|
+
for (const name of entries) {
|
|
25603
|
+
this.scanOne(w2, name);
|
|
25604
|
+
}
|
|
25605
|
+
}
|
|
25606
|
+
scanOne(w2, name) {
|
|
25607
|
+
const m2 = META_RE.exec(name);
|
|
25608
|
+
if (!m2) return;
|
|
25609
|
+
const agentId = m2[1];
|
|
25610
|
+
if (w2.emitted.has(agentId)) return;
|
|
25611
|
+
const file = import_node_path13.default.join(w2.dirPath, name);
|
|
25612
|
+
let raw;
|
|
25613
|
+
try {
|
|
25614
|
+
raw = import_node_fs12.default.readFileSync(file, "utf8");
|
|
25615
|
+
} catch {
|
|
25616
|
+
return;
|
|
25617
|
+
}
|
|
25618
|
+
let obj;
|
|
25619
|
+
try {
|
|
25620
|
+
obj = JSON.parse(raw);
|
|
25621
|
+
} catch {
|
|
25622
|
+
return;
|
|
25623
|
+
}
|
|
25624
|
+
const toolUseId = typeof obj.toolUseId === "string" ? obj.toolUseId : "";
|
|
25625
|
+
if (!toolUseId) return;
|
|
25626
|
+
w2.emitted.add(agentId);
|
|
25627
|
+
const ev = {
|
|
25628
|
+
kind: "subagent_progress",
|
|
25629
|
+
toolUseId,
|
|
25630
|
+
agentId,
|
|
25631
|
+
status: "started"
|
|
25632
|
+
};
|
|
25633
|
+
if (typeof obj.description === "string" && obj.description) ev.description = obj.description;
|
|
25634
|
+
this.opts.onEvent({ sessionId: w2.sessionId, events: [ev] });
|
|
25635
|
+
}
|
|
25636
|
+
isObserving(sessionId) {
|
|
25637
|
+
return this.watches.has(sessionId);
|
|
25638
|
+
}
|
|
25639
|
+
stop(sessionId) {
|
|
25640
|
+
const w2 = this.watches.get(sessionId);
|
|
25641
|
+
if (!w2) return false;
|
|
25642
|
+
try {
|
|
25643
|
+
w2.watcher?.close();
|
|
25644
|
+
} catch {
|
|
25645
|
+
}
|
|
25646
|
+
if (w2.pollTimer) clearInterval(w2.pollTimer);
|
|
25647
|
+
this.watches.delete(sessionId);
|
|
25648
|
+
return true;
|
|
25649
|
+
}
|
|
25650
|
+
stopAll() {
|
|
25651
|
+
for (const id of [...this.watches.keys()]) this.stop(id);
|
|
25652
|
+
}
|
|
25653
|
+
};
|
|
25654
|
+
|
|
25655
|
+
// src/observer/session-observer.ts
|
|
25656
|
+
var SessionObserver = class {
|
|
25657
|
+
constructor(opts) {
|
|
25658
|
+
this.opts = opts;
|
|
25659
|
+
this.home = opts.home ?? import_node_os9.default.homedir();
|
|
25660
|
+
this.metaObserver = opts.enableSubagentMetaObserver ? new SubagentMetaObserver({ home: this.home, onEvent: opts.onEvent }) : null;
|
|
25661
|
+
}
|
|
25662
|
+
opts;
|
|
25663
|
+
home;
|
|
25664
|
+
watches = /* @__PURE__ */ new Map();
|
|
25665
|
+
// 子 observer:监听 <projectsRoot>/<hashDir>/<toolSessionId>/subagents/ 目录的 meta.json,
|
|
25666
|
+
// 仅 TUI 模式启用——SDK 模式靠 `system.task_started` 帧(claude.ts:466)emit subagent_progress
|
|
25667
|
+
// 已经能解锁 AgentCallLine 抽屉入口,再跑 meta watcher 会让 ring buffer 留双帧
|
|
25668
|
+
metaObserver;
|
|
25546
25669
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
25547
25670
|
if (override) return override;
|
|
25548
|
-
return
|
|
25671
|
+
return import_node_path14.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
25549
25672
|
}
|
|
25550
25673
|
start(args) {
|
|
25551
25674
|
this.stop(args.sessionId);
|
|
25552
25675
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
25553
25676
|
let size = 0;
|
|
25554
25677
|
try {
|
|
25555
|
-
size =
|
|
25678
|
+
size = import_node_fs13.default.statSync(filePath).size;
|
|
25556
25679
|
} catch {
|
|
25557
25680
|
}
|
|
25558
25681
|
const w2 = {
|
|
@@ -25565,10 +25688,10 @@ var SessionObserver = class {
|
|
|
25565
25688
|
adapter: args.adapter
|
|
25566
25689
|
};
|
|
25567
25690
|
try {
|
|
25568
|
-
|
|
25691
|
+
import_node_fs13.default.mkdirSync(import_node_path14.default.dirname(filePath), { recursive: true });
|
|
25569
25692
|
} catch {
|
|
25570
25693
|
}
|
|
25571
|
-
w2.watcher =
|
|
25694
|
+
w2.watcher = import_node_fs13.default.watch(import_node_path14.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
25572
25695
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
25573
25696
|
this.poll(w2);
|
|
25574
25697
|
});
|
|
@@ -25577,6 +25700,11 @@ var SessionObserver = class {
|
|
|
25577
25700
|
this.opts.onStatus?.(args.sessionId, "observing");
|
|
25578
25701
|
this.hydrateMetaTail(w2);
|
|
25579
25702
|
this.poll(w2);
|
|
25703
|
+
this.metaObserver?.start({
|
|
25704
|
+
sessionId: args.sessionId,
|
|
25705
|
+
cwd: args.cwd,
|
|
25706
|
+
toolSessionId: args.toolSessionId
|
|
25707
|
+
});
|
|
25580
25708
|
return { filePath };
|
|
25581
25709
|
}
|
|
25582
25710
|
// 读 JSONL 文件尾部 N 行,把每行的 meta_update 字段**合并成一个 patch** 喂给 reducer。
|
|
@@ -25586,7 +25714,7 @@ var SessionObserver = class {
|
|
|
25586
25714
|
// 异常静默吞,不阻塞 watcher 启动
|
|
25587
25715
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
25588
25716
|
try {
|
|
25589
|
-
const raw =
|
|
25717
|
+
const raw = import_node_fs13.default.readFileSync(w2.filePath, "utf8");
|
|
25590
25718
|
if (!raw) return;
|
|
25591
25719
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
25592
25720
|
if (allLines.length === 0) return;
|
|
@@ -25610,7 +25738,7 @@ var SessionObserver = class {
|
|
|
25610
25738
|
poll(w2) {
|
|
25611
25739
|
let size = 0;
|
|
25612
25740
|
try {
|
|
25613
|
-
size =
|
|
25741
|
+
size = import_node_fs13.default.statSync(w2.filePath).size;
|
|
25614
25742
|
} catch {
|
|
25615
25743
|
return;
|
|
25616
25744
|
}
|
|
@@ -25619,11 +25747,11 @@ var SessionObserver = class {
|
|
|
25619
25747
|
w2.buf = "";
|
|
25620
25748
|
}
|
|
25621
25749
|
if (size === w2.lastSize) return;
|
|
25622
|
-
const fd =
|
|
25750
|
+
const fd = import_node_fs13.default.openSync(w2.filePath, "r");
|
|
25623
25751
|
try {
|
|
25624
25752
|
const len = size - w2.lastSize;
|
|
25625
25753
|
const buf = Buffer.alloc(len);
|
|
25626
|
-
|
|
25754
|
+
import_node_fs13.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
25627
25755
|
w2.lastSize = size;
|
|
25628
25756
|
w2.buf += buf.toString("utf8");
|
|
25629
25757
|
let newlineIndex;
|
|
@@ -25637,7 +25765,7 @@ var SessionObserver = class {
|
|
|
25637
25765
|
}
|
|
25638
25766
|
}
|
|
25639
25767
|
} finally {
|
|
25640
|
-
|
|
25768
|
+
import_node_fs13.default.closeSync(fd);
|
|
25641
25769
|
}
|
|
25642
25770
|
}
|
|
25643
25771
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -25690,11 +25818,13 @@ var SessionObserver = class {
|
|
|
25690
25818
|
}
|
|
25691
25819
|
if (w2.pollTimer) clearInterval(w2.pollTimer);
|
|
25692
25820
|
this.watches.delete(sessionId);
|
|
25821
|
+
this.metaObserver?.stop(sessionId);
|
|
25693
25822
|
this.opts.onStatus?.(sessionId, "stopped");
|
|
25694
25823
|
return true;
|
|
25695
25824
|
}
|
|
25696
25825
|
stopAll() {
|
|
25697
25826
|
for (const id of [...this.watches.keys()]) this.stop(id);
|
|
25827
|
+
this.metaObserver?.stopAll();
|
|
25698
25828
|
}
|
|
25699
25829
|
};
|
|
25700
25830
|
|
|
@@ -26295,14 +26425,14 @@ function authenticate(token, deps) {
|
|
|
26295
26425
|
}
|
|
26296
26426
|
|
|
26297
26427
|
// src/permission/capability-store.ts
|
|
26298
|
-
var
|
|
26299
|
-
var
|
|
26428
|
+
var fs16 = __toESM(require("fs"), 1);
|
|
26429
|
+
var path19 = __toESM(require("path"), 1);
|
|
26300
26430
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
26301
26431
|
var FILE_VERSION = 1;
|
|
26302
26432
|
var CapabilityStore = class {
|
|
26303
26433
|
constructor(dataDir) {
|
|
26304
26434
|
this.dataDir = dataDir;
|
|
26305
|
-
|
|
26435
|
+
fs16.mkdirSync(dataDir, { recursive: true });
|
|
26306
26436
|
this.cache = this.readFromDisk();
|
|
26307
26437
|
}
|
|
26308
26438
|
dataDir;
|
|
@@ -26326,13 +26456,13 @@ var CapabilityStore = class {
|
|
|
26326
26456
|
this.flush();
|
|
26327
26457
|
}
|
|
26328
26458
|
filePath() {
|
|
26329
|
-
return
|
|
26459
|
+
return path19.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
26330
26460
|
}
|
|
26331
26461
|
readFromDisk() {
|
|
26332
26462
|
const file = this.filePath();
|
|
26333
26463
|
let raw;
|
|
26334
26464
|
try {
|
|
26335
|
-
raw =
|
|
26465
|
+
raw = fs16.readFileSync(file, "utf8");
|
|
26336
26466
|
} catch (err) {
|
|
26337
26467
|
if (err?.code === "ENOENT") return [];
|
|
26338
26468
|
return [];
|
|
@@ -26360,10 +26490,10 @@ var CapabilityStore = class {
|
|
|
26360
26490
|
}
|
|
26361
26491
|
atomicWrite(file, content) {
|
|
26362
26492
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26363
|
-
|
|
26364
|
-
|
|
26493
|
+
fs16.writeFileSync(tmp, content, { mode: 384 });
|
|
26494
|
+
fs16.renameSync(tmp, file);
|
|
26365
26495
|
try {
|
|
26366
|
-
|
|
26496
|
+
fs16.chmodSync(file, 384);
|
|
26367
26497
|
} catch {
|
|
26368
26498
|
}
|
|
26369
26499
|
}
|
|
@@ -26456,14 +26586,14 @@ var CapabilityManager = class {
|
|
|
26456
26586
|
};
|
|
26457
26587
|
|
|
26458
26588
|
// src/permission/cleanup.ts
|
|
26459
|
-
var
|
|
26589
|
+
var fs17 = __toESM(require("fs"), 1);
|
|
26460
26590
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
26461
26591
|
const removed = [];
|
|
26462
26592
|
for (const g2 of cap.grants) {
|
|
26463
26593
|
if (g2.resource.type !== "persona") continue;
|
|
26464
26594
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
26465
26595
|
try {
|
|
26466
|
-
|
|
26596
|
+
fs17.rmSync(dir, { recursive: true, force: true });
|
|
26467
26597
|
removed.push(dir);
|
|
26468
26598
|
} catch {
|
|
26469
26599
|
}
|
|
@@ -26472,13 +26602,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
26472
26602
|
}
|
|
26473
26603
|
|
|
26474
26604
|
// src/permission/personal-capability.ts
|
|
26475
|
-
var
|
|
26476
|
-
var
|
|
26605
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
26606
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
26477
26607
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
26478
26608
|
var PERSONAL_CAP_FILE_NAME = "personal-capability.json";
|
|
26479
26609
|
var PERSONAL_CAP_DISPLAY_NAME = "personal";
|
|
26480
26610
|
function personalCapFilePath(dataDir) {
|
|
26481
|
-
return
|
|
26611
|
+
return import_node_path15.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
|
|
26482
26612
|
}
|
|
26483
26613
|
function loadOrCreatePersonalCapability(opts) {
|
|
26484
26614
|
const file = personalCapFilePath(opts.dataDir);
|
|
@@ -26508,7 +26638,7 @@ function loadOrCreatePersonalCapability(opts) {
|
|
|
26508
26638
|
function readFile(file) {
|
|
26509
26639
|
let raw;
|
|
26510
26640
|
try {
|
|
26511
|
-
raw =
|
|
26641
|
+
raw = import_node_fs14.default.readFileSync(file, "utf8");
|
|
26512
26642
|
} catch (err) {
|
|
26513
26643
|
const code = err?.code;
|
|
26514
26644
|
if (code === "ENOENT") return null;
|
|
@@ -26529,10 +26659,10 @@ function readFile(file) {
|
|
|
26529
26659
|
return { token: obj.token, capability: capParsed.data };
|
|
26530
26660
|
}
|
|
26531
26661
|
function writeFile(file, content) {
|
|
26532
|
-
|
|
26533
|
-
|
|
26662
|
+
import_node_fs14.default.mkdirSync(import_node_path15.default.dirname(file), { recursive: true });
|
|
26663
|
+
import_node_fs14.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
26534
26664
|
try {
|
|
26535
|
-
|
|
26665
|
+
import_node_fs14.default.chmodSync(file, 384);
|
|
26536
26666
|
} catch {
|
|
26537
26667
|
}
|
|
26538
26668
|
}
|
|
@@ -26547,13 +26677,13 @@ function sha256Hex2(s) {
|
|
|
26547
26677
|
}
|
|
26548
26678
|
|
|
26549
26679
|
// src/inbox/inbox-store.ts
|
|
26550
|
-
var
|
|
26551
|
-
var
|
|
26680
|
+
var fs19 = __toESM(require("fs"), 1);
|
|
26681
|
+
var path21 = __toESM(require("path"), 1);
|
|
26552
26682
|
var INBOX_SUBDIR = "inbox";
|
|
26553
26683
|
var InboxStore = class {
|
|
26554
26684
|
constructor(dataDir) {
|
|
26555
26685
|
this.dataDir = dataDir;
|
|
26556
|
-
|
|
26686
|
+
fs19.mkdirSync(this.dirPath(), { recursive: true });
|
|
26557
26687
|
}
|
|
26558
26688
|
dataDir;
|
|
26559
26689
|
/**
|
|
@@ -26565,7 +26695,7 @@ var InboxStore = class {
|
|
|
26565
26695
|
const file = this.filePath(peerOwnerId);
|
|
26566
26696
|
let raw;
|
|
26567
26697
|
try {
|
|
26568
|
-
raw =
|
|
26698
|
+
raw = fs19.readFileSync(file, "utf8");
|
|
26569
26699
|
} catch (err) {
|
|
26570
26700
|
if (err?.code === "ENOENT") return [];
|
|
26571
26701
|
return [];
|
|
@@ -26581,7 +26711,7 @@ var InboxStore = class {
|
|
|
26581
26711
|
const dir = this.dirPath();
|
|
26582
26712
|
let entries;
|
|
26583
26713
|
try {
|
|
26584
|
-
entries =
|
|
26714
|
+
entries = fs19.readdirSync(dir);
|
|
26585
26715
|
} catch (err) {
|
|
26586
26716
|
if (err?.code === "ENOENT") return [];
|
|
26587
26717
|
return [];
|
|
@@ -26597,9 +26727,9 @@ var InboxStore = class {
|
|
|
26597
26727
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
26598
26728
|
const file = this.filePath(message.peerOwnerId);
|
|
26599
26729
|
const line = JSON.stringify(message) + "\n";
|
|
26600
|
-
|
|
26730
|
+
fs19.appendFileSync(file, line, { mode: 384 });
|
|
26601
26731
|
try {
|
|
26602
|
-
|
|
26732
|
+
fs19.chmodSync(file, 384);
|
|
26603
26733
|
} catch {
|
|
26604
26734
|
}
|
|
26605
26735
|
}
|
|
@@ -26629,7 +26759,7 @@ var InboxStore = class {
|
|
|
26629
26759
|
removeByPeerOwnerId(peerOwnerId) {
|
|
26630
26760
|
const file = this.filePath(peerOwnerId);
|
|
26631
26761
|
try {
|
|
26632
|
-
|
|
26762
|
+
fs19.unlinkSync(file);
|
|
26633
26763
|
} catch (err) {
|
|
26634
26764
|
if (err?.code === "ENOENT") return;
|
|
26635
26765
|
}
|
|
@@ -26638,18 +26768,18 @@ var InboxStore = class {
|
|
|
26638
26768
|
const file = this.filePath(peerOwnerId);
|
|
26639
26769
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26640
26770
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
26641
|
-
|
|
26642
|
-
|
|
26771
|
+
fs19.writeFileSync(tmp, content, { mode: 384 });
|
|
26772
|
+
fs19.renameSync(tmp, file);
|
|
26643
26773
|
try {
|
|
26644
|
-
|
|
26774
|
+
fs19.chmodSync(file, 384);
|
|
26645
26775
|
} catch {
|
|
26646
26776
|
}
|
|
26647
26777
|
}
|
|
26648
26778
|
dirPath() {
|
|
26649
|
-
return
|
|
26779
|
+
return path21.join(this.dataDir, INBOX_SUBDIR);
|
|
26650
26780
|
}
|
|
26651
26781
|
filePath(peerOwnerId) {
|
|
26652
|
-
return
|
|
26782
|
+
return path21.join(this.dirPath(), `${peerOwnerId}.jsonl`);
|
|
26653
26783
|
}
|
|
26654
26784
|
};
|
|
26655
26785
|
function parseAllLines(raw) {
|
|
@@ -26736,8 +26866,8 @@ var InboxManager = class {
|
|
|
26736
26866
|
};
|
|
26737
26867
|
|
|
26738
26868
|
// src/state/received-capability-store.ts
|
|
26739
|
-
var
|
|
26740
|
-
var
|
|
26869
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
26870
|
+
var path22 = __toESM(require("path"), 1);
|
|
26741
26871
|
var FILE_NAME = "received-capabilities.json";
|
|
26742
26872
|
var ReceivedCapabilityStore = class {
|
|
26743
26873
|
constructor(dataDir) {
|
|
@@ -26747,10 +26877,10 @@ var ReceivedCapabilityStore = class {
|
|
|
26747
26877
|
caps = /* @__PURE__ */ new Map();
|
|
26748
26878
|
load() {
|
|
26749
26879
|
this.caps.clear();
|
|
26750
|
-
const file =
|
|
26880
|
+
const file = path22.join(this.dataDir, FILE_NAME);
|
|
26751
26881
|
let raw;
|
|
26752
26882
|
try {
|
|
26753
|
-
raw =
|
|
26883
|
+
raw = fs20.readFileSync(file, "utf8");
|
|
26754
26884
|
} catch (err) {
|
|
26755
26885
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
26756
26886
|
return;
|
|
@@ -26787,20 +26917,20 @@ var ReceivedCapabilityStore = class {
|
|
|
26787
26917
|
this.flush();
|
|
26788
26918
|
}
|
|
26789
26919
|
flush() {
|
|
26790
|
-
const file =
|
|
26920
|
+
const file = path22.join(this.dataDir, FILE_NAME);
|
|
26791
26921
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
26792
26922
|
const content = JSON.stringify(
|
|
26793
26923
|
{ receivedCaps: Array.from(this.caps.values()) },
|
|
26794
26924
|
null,
|
|
26795
26925
|
2
|
|
26796
26926
|
);
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
26927
|
+
fs20.mkdirSync(this.dataDir, { recursive: true });
|
|
26928
|
+
fs20.writeFileSync(tmp, content, { mode: 384 });
|
|
26929
|
+
fs20.renameSync(tmp, file);
|
|
26800
26930
|
}
|
|
26801
26931
|
renameBak(file) {
|
|
26802
26932
|
try {
|
|
26803
|
-
|
|
26933
|
+
fs20.renameSync(file, `${file}.bak`);
|
|
26804
26934
|
} catch {
|
|
26805
26935
|
}
|
|
26806
26936
|
}
|
|
@@ -26898,61 +27028,61 @@ async function connectRemote(args) {
|
|
|
26898
27028
|
}
|
|
26899
27029
|
|
|
26900
27030
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
26901
|
-
var
|
|
26902
|
-
var
|
|
27031
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
27032
|
+
var path23 = __toESM(require("path"), 1);
|
|
26903
27033
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
26904
27034
|
function migrateFlattenSessions(opts) {
|
|
26905
27035
|
const dataDir = opts.dataDir;
|
|
26906
27036
|
const now = opts.now ?? Date.now;
|
|
26907
|
-
const sessionsDir =
|
|
26908
|
-
const flagPath =
|
|
27037
|
+
const sessionsDir = path23.join(dataDir, "sessions");
|
|
27038
|
+
const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
26909
27039
|
if (existsSync3(flagPath)) {
|
|
26910
27040
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
26911
27041
|
}
|
|
26912
27042
|
let movedBare = 0;
|
|
26913
27043
|
let movedVmOwner = 0;
|
|
26914
27044
|
let archivedListener = 0;
|
|
26915
|
-
const defaultDir =
|
|
27045
|
+
const defaultDir = path23.join(sessionsDir, "default");
|
|
26916
27046
|
if (existsSync3(defaultDir)) {
|
|
26917
27047
|
for (const entry of readdirSafe(defaultDir)) {
|
|
26918
27048
|
if (!entry.endsWith(".json")) continue;
|
|
26919
|
-
const src =
|
|
26920
|
-
const dst =
|
|
26921
|
-
|
|
27049
|
+
const src = path23.join(defaultDir, entry);
|
|
27050
|
+
const dst = path23.join(sessionsDir, entry);
|
|
27051
|
+
fs21.renameSync(src, dst);
|
|
26922
27052
|
movedBare += 1;
|
|
26923
27053
|
}
|
|
26924
27054
|
rmdirIfEmpty(defaultDir);
|
|
26925
27055
|
}
|
|
26926
27056
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
26927
|
-
const personaDir =
|
|
27057
|
+
const personaDir = path23.join(sessionsDir, pid);
|
|
26928
27058
|
if (!isDir(personaDir)) continue;
|
|
26929
27059
|
if (pid === "default") continue;
|
|
26930
|
-
const ownerSrc =
|
|
27060
|
+
const ownerSrc = path23.join(personaDir, "owner");
|
|
26931
27061
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
26932
|
-
const ownerDst =
|
|
26933
|
-
|
|
27062
|
+
const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
27063
|
+
fs21.mkdirSync(ownerDst, { recursive: true });
|
|
26934
27064
|
for (const file of readdirSafe(ownerSrc)) {
|
|
26935
27065
|
if (!file.endsWith(".json")) continue;
|
|
26936
|
-
|
|
27066
|
+
fs21.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
|
|
26937
27067
|
movedVmOwner += 1;
|
|
26938
27068
|
}
|
|
26939
27069
|
rmdirIfEmpty(ownerSrc);
|
|
26940
27070
|
}
|
|
26941
|
-
const listenerSrc =
|
|
27071
|
+
const listenerSrc = path23.join(personaDir, "listener");
|
|
26942
27072
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
26943
|
-
const archiveDst =
|
|
26944
|
-
|
|
27073
|
+
const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
|
|
27074
|
+
fs21.mkdirSync(archiveDst, { recursive: true });
|
|
26945
27075
|
for (const file of readdirSafe(listenerSrc)) {
|
|
26946
27076
|
if (!file.endsWith(".json")) continue;
|
|
26947
|
-
|
|
27077
|
+
fs21.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
|
|
26948
27078
|
archivedListener += 1;
|
|
26949
27079
|
}
|
|
26950
27080
|
rmdirIfEmpty(listenerSrc);
|
|
26951
27081
|
}
|
|
26952
27082
|
rmdirIfEmpty(personaDir);
|
|
26953
27083
|
}
|
|
26954
|
-
|
|
26955
|
-
|
|
27084
|
+
fs21.mkdirSync(sessionsDir, { recursive: true });
|
|
27085
|
+
fs21.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
26956
27086
|
return {
|
|
26957
27087
|
skipped: false,
|
|
26958
27088
|
flagWritten: true,
|
|
@@ -26963,7 +27093,7 @@ function migrateFlattenSessions(opts) {
|
|
|
26963
27093
|
}
|
|
26964
27094
|
function existsSync3(p2) {
|
|
26965
27095
|
try {
|
|
26966
|
-
|
|
27096
|
+
fs21.statSync(p2);
|
|
26967
27097
|
return true;
|
|
26968
27098
|
} catch {
|
|
26969
27099
|
return false;
|
|
@@ -26971,31 +27101,31 @@ function existsSync3(p2) {
|
|
|
26971
27101
|
}
|
|
26972
27102
|
function isDir(p2) {
|
|
26973
27103
|
try {
|
|
26974
|
-
return
|
|
27104
|
+
return fs21.statSync(p2).isDirectory();
|
|
26975
27105
|
} catch {
|
|
26976
27106
|
return false;
|
|
26977
27107
|
}
|
|
26978
27108
|
}
|
|
26979
27109
|
function readdirSafe(p2) {
|
|
26980
27110
|
try {
|
|
26981
|
-
return
|
|
27111
|
+
return fs21.readdirSync(p2);
|
|
26982
27112
|
} catch {
|
|
26983
27113
|
return [];
|
|
26984
27114
|
}
|
|
26985
27115
|
}
|
|
26986
27116
|
function rmdirIfEmpty(p2) {
|
|
26987
27117
|
try {
|
|
26988
|
-
|
|
27118
|
+
fs21.rmdirSync(p2);
|
|
26989
27119
|
} catch {
|
|
26990
27120
|
}
|
|
26991
27121
|
}
|
|
26992
27122
|
|
|
26993
27123
|
// src/transport/http-router.ts
|
|
26994
|
-
var
|
|
26995
|
-
var
|
|
27124
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
27125
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
26996
27126
|
|
|
26997
27127
|
// src/attachment/mime.ts
|
|
26998
|
-
var
|
|
27128
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
26999
27129
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
27000
27130
|
var EXT_TO_NATIVE_MIME = {
|
|
27001
27131
|
// 图片
|
|
@@ -27102,7 +27232,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
27102
27232
|
".mk"
|
|
27103
27233
|
]);
|
|
27104
27234
|
function lookupMime(filePathOrName) {
|
|
27105
|
-
const ext =
|
|
27235
|
+
const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
|
|
27106
27236
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
27107
27237
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
27108
27238
|
return "application/octet-stream";
|
|
@@ -27171,8 +27301,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
27171
27301
|
}
|
|
27172
27302
|
|
|
27173
27303
|
// src/attachment/upload.ts
|
|
27174
|
-
var
|
|
27175
|
-
var
|
|
27304
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
27305
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
27176
27306
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
27177
27307
|
var import_promises = require("stream/promises");
|
|
27178
27308
|
var UploadError = class extends Error {
|
|
@@ -27184,22 +27314,22 @@ var UploadError = class extends Error {
|
|
|
27184
27314
|
code;
|
|
27185
27315
|
};
|
|
27186
27316
|
function assertValidFileName(fileName) {
|
|
27187
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
27317
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path17.default.basename(fileName)) {
|
|
27188
27318
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
27189
27319
|
}
|
|
27190
27320
|
}
|
|
27191
27321
|
var HASH_PREFIX_LEN = 16;
|
|
27192
27322
|
async function writeUploadedAttachment(args) {
|
|
27193
27323
|
assertValidFileName(args.fileName);
|
|
27194
|
-
const attachmentsRoot =
|
|
27324
|
+
const attachmentsRoot = import_node_path17.default.join(args.sessionDir, ".attachments");
|
|
27195
27325
|
try {
|
|
27196
|
-
|
|
27326
|
+
import_node_fs15.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
27197
27327
|
} catch (err) {
|
|
27198
27328
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
27199
27329
|
}
|
|
27200
27330
|
const hasher = import_node_crypto6.default.createHash("sha256");
|
|
27201
27331
|
let actualSize = 0;
|
|
27202
|
-
const tmpPath =
|
|
27332
|
+
const tmpPath = import_node_path17.default.join(
|
|
27203
27333
|
attachmentsRoot,
|
|
27204
27334
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto6.default.randomBytes(4).toString("hex")}`
|
|
27205
27335
|
);
|
|
@@ -27214,18 +27344,18 @@ async function writeUploadedAttachment(args) {
|
|
|
27214
27344
|
yield buf;
|
|
27215
27345
|
}
|
|
27216
27346
|
},
|
|
27217
|
-
|
|
27347
|
+
import_node_fs15.default.createWriteStream(tmpPath, { mode: 384 })
|
|
27218
27348
|
);
|
|
27219
27349
|
} catch (err) {
|
|
27220
27350
|
try {
|
|
27221
|
-
|
|
27351
|
+
import_node_fs15.default.unlinkSync(tmpPath);
|
|
27222
27352
|
} catch {
|
|
27223
27353
|
}
|
|
27224
27354
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
27225
27355
|
}
|
|
27226
27356
|
if (actualSize !== args.contentLength) {
|
|
27227
27357
|
try {
|
|
27228
|
-
|
|
27358
|
+
import_node_fs15.default.unlinkSync(tmpPath);
|
|
27229
27359
|
} catch {
|
|
27230
27360
|
}
|
|
27231
27361
|
throw new UploadError(
|
|
@@ -27234,35 +27364,35 @@ async function writeUploadedAttachment(args) {
|
|
|
27234
27364
|
);
|
|
27235
27365
|
}
|
|
27236
27366
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
27237
|
-
const hashDir =
|
|
27367
|
+
const hashDir = import_node_path17.default.join(attachmentsRoot, attachmentId);
|
|
27238
27368
|
let finalFileName;
|
|
27239
27369
|
let hashDirExists = false;
|
|
27240
27370
|
try {
|
|
27241
|
-
hashDirExists =
|
|
27371
|
+
hashDirExists = import_node_fs15.default.statSync(hashDir).isDirectory();
|
|
27242
27372
|
} catch {
|
|
27243
27373
|
}
|
|
27244
27374
|
if (hashDirExists) {
|
|
27245
|
-
const existing =
|
|
27375
|
+
const existing = import_node_fs15.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
27246
27376
|
finalFileName = existing[0] ?? args.fileName;
|
|
27247
27377
|
try {
|
|
27248
|
-
|
|
27378
|
+
import_node_fs15.default.unlinkSync(tmpPath);
|
|
27249
27379
|
} catch {
|
|
27250
27380
|
}
|
|
27251
27381
|
} else {
|
|
27252
27382
|
try {
|
|
27253
|
-
|
|
27383
|
+
import_node_fs15.default.mkdirSync(hashDir, { recursive: true });
|
|
27254
27384
|
finalFileName = args.fileName;
|
|
27255
|
-
|
|
27385
|
+
import_node_fs15.default.renameSync(tmpPath, import_node_path17.default.join(hashDir, finalFileName));
|
|
27256
27386
|
} catch (err) {
|
|
27257
27387
|
try {
|
|
27258
|
-
|
|
27388
|
+
import_node_fs15.default.unlinkSync(tmpPath);
|
|
27259
27389
|
} catch {
|
|
27260
27390
|
}
|
|
27261
27391
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
27262
27392
|
}
|
|
27263
27393
|
}
|
|
27264
|
-
const absPath =
|
|
27265
|
-
const relPath =
|
|
27394
|
+
const absPath = import_node_path17.default.join(hashDir, finalFileName);
|
|
27395
|
+
const relPath = import_node_path17.default.relative(args.sessionDir, absPath);
|
|
27266
27396
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
27267
27397
|
relPath: absPath,
|
|
27268
27398
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -27299,7 +27429,7 @@ function isValidUploadFileName(fileName) {
|
|
|
27299
27429
|
if (fileName === "." || fileName === "..") return false;
|
|
27300
27430
|
if (fileName.startsWith(".")) return false;
|
|
27301
27431
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
27302
|
-
return fileName ===
|
|
27432
|
+
return fileName === import_node_path18.default.basename(fileName);
|
|
27303
27433
|
}
|
|
27304
27434
|
function createHttpRouter(deps) {
|
|
27305
27435
|
return async (req, res) => {
|
|
@@ -27469,7 +27599,7 @@ function createHttpRouter(deps) {
|
|
|
27469
27599
|
return true;
|
|
27470
27600
|
}
|
|
27471
27601
|
let absPath;
|
|
27472
|
-
if (
|
|
27602
|
+
if (import_node_path18.default.isAbsolute(pathParam)) {
|
|
27473
27603
|
absPath = pathParam;
|
|
27474
27604
|
} else if (deps.sessionStore) {
|
|
27475
27605
|
const file = deps.sessionStore.read(sid);
|
|
@@ -27477,7 +27607,7 @@ function createHttpRouter(deps) {
|
|
|
27477
27607
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
27478
27608
|
return true;
|
|
27479
27609
|
}
|
|
27480
|
-
absPath =
|
|
27610
|
+
absPath = import_node_path18.default.join(file.cwd, pathParam);
|
|
27481
27611
|
} else {
|
|
27482
27612
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
27483
27613
|
return true;
|
|
@@ -27510,7 +27640,7 @@ function withCtx(ctx, body) {
|
|
|
27510
27640
|
function streamFile(res, absPath, logger) {
|
|
27511
27641
|
let stat;
|
|
27512
27642
|
try {
|
|
27513
|
-
stat =
|
|
27643
|
+
stat = import_node_fs16.default.statSync(absPath);
|
|
27514
27644
|
} catch (err) {
|
|
27515
27645
|
const code = err?.code;
|
|
27516
27646
|
if (code === "ENOENT") {
|
|
@@ -27525,7 +27655,7 @@ function streamFile(res, absPath, logger) {
|
|
|
27525
27655
|
return;
|
|
27526
27656
|
}
|
|
27527
27657
|
const mime = lookupMime(absPath);
|
|
27528
|
-
const basename =
|
|
27658
|
+
const basename = import_node_path18.default.basename(absPath);
|
|
27529
27659
|
res.writeHead(200, {
|
|
27530
27660
|
"Content-Type": mime,
|
|
27531
27661
|
"Content-Length": String(stat.size),
|
|
@@ -27533,7 +27663,7 @@ function streamFile(res, absPath, logger) {
|
|
|
27533
27663
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
27534
27664
|
"X-Content-Type-Options": "nosniff"
|
|
27535
27665
|
});
|
|
27536
|
-
const stream =
|
|
27666
|
+
const stream = import_node_fs16.default.createReadStream(absPath);
|
|
27537
27667
|
stream.on("error", (err) => {
|
|
27538
27668
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
27539
27669
|
res.destroy();
|
|
@@ -27542,8 +27672,8 @@ function streamFile(res, absPath, logger) {
|
|
|
27542
27672
|
}
|
|
27543
27673
|
|
|
27544
27674
|
// src/attachment/gc.ts
|
|
27545
|
-
var
|
|
27546
|
-
var
|
|
27675
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
27676
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
27547
27677
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
27548
27678
|
function runAttachmentGc(args) {
|
|
27549
27679
|
const now = (args.now ?? Date.now)();
|
|
@@ -27552,38 +27682,38 @@ function runAttachmentGc(args) {
|
|
|
27552
27682
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
27553
27683
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
27554
27684
|
if (entry.stale) continue;
|
|
27555
|
-
if (
|
|
27685
|
+
if (import_node_path19.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
27556
27686
|
}
|
|
27557
27687
|
}
|
|
27558
27688
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
27559
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
27689
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path19.default.join(
|
|
27560
27690
|
args.dataDir,
|
|
27561
27691
|
"sessions",
|
|
27562
27692
|
...scopeSubPath(scope).map(safeFileName),
|
|
27563
27693
|
safeFileName(sessionId)
|
|
27564
27694
|
);
|
|
27565
|
-
const attRoot =
|
|
27695
|
+
const attRoot = import_node_path19.default.join(sessionDir, ".attachments");
|
|
27566
27696
|
let hashDirs;
|
|
27567
27697
|
try {
|
|
27568
|
-
hashDirs =
|
|
27698
|
+
hashDirs = import_node_fs17.default.readdirSync(attRoot);
|
|
27569
27699
|
} catch (err) {
|
|
27570
27700
|
if (err.code === "ENOENT") continue;
|
|
27571
27701
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
27572
27702
|
continue;
|
|
27573
27703
|
}
|
|
27574
27704
|
for (const hashDir of hashDirs) {
|
|
27575
|
-
const hashDirAbs =
|
|
27705
|
+
const hashDirAbs = import_node_path19.default.join(attRoot, hashDir);
|
|
27576
27706
|
let files;
|
|
27577
27707
|
try {
|
|
27578
|
-
files =
|
|
27708
|
+
files = import_node_fs17.default.readdirSync(hashDirAbs);
|
|
27579
27709
|
} catch {
|
|
27580
27710
|
continue;
|
|
27581
27711
|
}
|
|
27582
27712
|
for (const name of files) {
|
|
27583
|
-
const file =
|
|
27713
|
+
const file = import_node_path19.default.join(hashDirAbs, name);
|
|
27584
27714
|
let stat;
|
|
27585
27715
|
try {
|
|
27586
|
-
stat =
|
|
27716
|
+
stat = import_node_fs17.default.statSync(file);
|
|
27587
27717
|
} catch {
|
|
27588
27718
|
continue;
|
|
27589
27719
|
}
|
|
@@ -27592,26 +27722,26 @@ function runAttachmentGc(args) {
|
|
|
27592
27722
|
if (age < ttlMs) continue;
|
|
27593
27723
|
if (liveAbs.has(file)) continue;
|
|
27594
27724
|
try {
|
|
27595
|
-
|
|
27725
|
+
import_node_fs17.default.unlinkSync(file);
|
|
27596
27726
|
} catch (err) {
|
|
27597
27727
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
27598
27728
|
}
|
|
27599
27729
|
}
|
|
27600
27730
|
try {
|
|
27601
|
-
if (
|
|
27731
|
+
if (import_node_fs17.default.readdirSync(hashDirAbs).length === 0) import_node_fs17.default.rmdirSync(hashDirAbs);
|
|
27602
27732
|
} catch {
|
|
27603
27733
|
}
|
|
27604
27734
|
}
|
|
27605
27735
|
try {
|
|
27606
|
-
if (
|
|
27736
|
+
if (import_node_fs17.default.readdirSync(attRoot).length === 0) import_node_fs17.default.rmdirSync(attRoot);
|
|
27607
27737
|
} catch {
|
|
27608
27738
|
}
|
|
27609
27739
|
}
|
|
27610
27740
|
}
|
|
27611
27741
|
|
|
27612
27742
|
// src/attachment/group.ts
|
|
27613
|
-
var
|
|
27614
|
-
var
|
|
27743
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
27744
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
27615
27745
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
27616
27746
|
init_protocol();
|
|
27617
27747
|
var GroupFileStore = class {
|
|
@@ -27623,11 +27753,11 @@ var GroupFileStore = class {
|
|
|
27623
27753
|
this.logger = opts.logger;
|
|
27624
27754
|
}
|
|
27625
27755
|
rootForScope(scope) {
|
|
27626
|
-
return
|
|
27756
|
+
return import_node_path20.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
27627
27757
|
}
|
|
27628
27758
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
27629
27759
|
filePath(scope, sessionId) {
|
|
27630
|
-
return
|
|
27760
|
+
return import_node_path20.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
27631
27761
|
}
|
|
27632
27762
|
cacheKey(scope, sessionId) {
|
|
27633
27763
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -27636,7 +27766,7 @@ var GroupFileStore = class {
|
|
|
27636
27766
|
readFile(scope, sessionId) {
|
|
27637
27767
|
const file = this.filePath(scope, sessionId);
|
|
27638
27768
|
try {
|
|
27639
|
-
const raw =
|
|
27769
|
+
const raw = import_node_fs18.default.readFileSync(file, "utf8");
|
|
27640
27770
|
const parsed = JSON.parse(raw);
|
|
27641
27771
|
if (!Array.isArray(parsed)) {
|
|
27642
27772
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -27662,10 +27792,10 @@ var GroupFileStore = class {
|
|
|
27662
27792
|
}
|
|
27663
27793
|
writeFile(scope, sessionId, entries) {
|
|
27664
27794
|
const file = this.filePath(scope, sessionId);
|
|
27665
|
-
|
|
27795
|
+
import_node_fs18.default.mkdirSync(import_node_path20.default.dirname(file), { recursive: true });
|
|
27666
27796
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
27667
|
-
|
|
27668
|
-
|
|
27797
|
+
import_node_fs18.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
27798
|
+
import_node_fs18.default.renameSync(tmp, file);
|
|
27669
27799
|
}
|
|
27670
27800
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
27671
27801
|
list(scope, sessionId) {
|
|
@@ -27751,10 +27881,10 @@ var GroupFileStore = class {
|
|
|
27751
27881
|
};
|
|
27752
27882
|
|
|
27753
27883
|
// src/discovery/state-file.ts
|
|
27754
|
-
var
|
|
27755
|
-
var
|
|
27884
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
27885
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
27756
27886
|
function defaultStateFilePath(dataDir) {
|
|
27757
|
-
return
|
|
27887
|
+
return import_node_path21.default.join(dataDir, "state.json");
|
|
27758
27888
|
}
|
|
27759
27889
|
function isPidAlive(pid) {
|
|
27760
27890
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -27776,7 +27906,7 @@ var StateFileManager = class {
|
|
|
27776
27906
|
}
|
|
27777
27907
|
read() {
|
|
27778
27908
|
try {
|
|
27779
|
-
const raw =
|
|
27909
|
+
const raw = import_node_fs19.default.readFileSync(this.file, "utf8");
|
|
27780
27910
|
const parsed = JSON.parse(raw);
|
|
27781
27911
|
return parsed;
|
|
27782
27912
|
} catch {
|
|
@@ -27790,34 +27920,34 @@ var StateFileManager = class {
|
|
|
27790
27920
|
return { status: "stale", existing };
|
|
27791
27921
|
}
|
|
27792
27922
|
write(state) {
|
|
27793
|
-
|
|
27923
|
+
import_node_fs19.default.mkdirSync(import_node_path21.default.dirname(this.file), { recursive: true });
|
|
27794
27924
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
27795
|
-
|
|
27796
|
-
|
|
27925
|
+
import_node_fs19.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
27926
|
+
import_node_fs19.default.renameSync(tmp, this.file);
|
|
27797
27927
|
if (process.platform !== "win32") {
|
|
27798
27928
|
try {
|
|
27799
|
-
|
|
27929
|
+
import_node_fs19.default.chmodSync(this.file, 384);
|
|
27800
27930
|
} catch {
|
|
27801
27931
|
}
|
|
27802
27932
|
}
|
|
27803
27933
|
}
|
|
27804
27934
|
delete() {
|
|
27805
27935
|
try {
|
|
27806
|
-
|
|
27936
|
+
import_node_fs19.default.unlinkSync(this.file);
|
|
27807
27937
|
} catch {
|
|
27808
27938
|
}
|
|
27809
27939
|
}
|
|
27810
27940
|
};
|
|
27811
27941
|
|
|
27812
27942
|
// src/tunnel/tunnel-manager.ts
|
|
27813
|
-
var
|
|
27814
|
-
var
|
|
27943
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
27944
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
27815
27945
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
27816
27946
|
var import_node_child_process5 = require("child_process");
|
|
27817
27947
|
|
|
27818
27948
|
// src/tunnel/tunnel-store.ts
|
|
27819
|
-
var
|
|
27820
|
-
var
|
|
27949
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
27950
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
27821
27951
|
var TunnelStore = class {
|
|
27822
27952
|
constructor(filePath) {
|
|
27823
27953
|
this.filePath = filePath;
|
|
@@ -27825,7 +27955,7 @@ var TunnelStore = class {
|
|
|
27825
27955
|
filePath;
|
|
27826
27956
|
async get() {
|
|
27827
27957
|
try {
|
|
27828
|
-
const raw = await
|
|
27958
|
+
const raw = await import_node_fs20.default.promises.readFile(this.filePath, "utf8");
|
|
27829
27959
|
const obj = JSON.parse(raw);
|
|
27830
27960
|
if (!isPersistedTunnel(obj)) return null;
|
|
27831
27961
|
return obj;
|
|
@@ -27836,22 +27966,22 @@ var TunnelStore = class {
|
|
|
27836
27966
|
}
|
|
27837
27967
|
}
|
|
27838
27968
|
async set(v2) {
|
|
27839
|
-
const dir =
|
|
27840
|
-
await
|
|
27969
|
+
const dir = import_node_path22.default.dirname(this.filePath);
|
|
27970
|
+
await import_node_fs20.default.promises.mkdir(dir, { recursive: true });
|
|
27841
27971
|
const data = JSON.stringify(v2, null, 2);
|
|
27842
27972
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
27843
|
-
await
|
|
27973
|
+
await import_node_fs20.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
27844
27974
|
if (process.platform !== "win32") {
|
|
27845
27975
|
try {
|
|
27846
|
-
await
|
|
27976
|
+
await import_node_fs20.default.promises.chmod(tmp, 384);
|
|
27847
27977
|
} catch {
|
|
27848
27978
|
}
|
|
27849
27979
|
}
|
|
27850
|
-
await
|
|
27980
|
+
await import_node_fs20.default.promises.rename(tmp, this.filePath);
|
|
27851
27981
|
}
|
|
27852
27982
|
async clear() {
|
|
27853
27983
|
try {
|
|
27854
|
-
await
|
|
27984
|
+
await import_node_fs20.default.promises.unlink(this.filePath);
|
|
27855
27985
|
} catch (err) {
|
|
27856
27986
|
const code = err?.code;
|
|
27857
27987
|
if (code !== "ENOENT") throw err;
|
|
@@ -27946,9 +28076,9 @@ function escape(v2) {
|
|
|
27946
28076
|
}
|
|
27947
28077
|
|
|
27948
28078
|
// src/tunnel/frpc-binary.ts
|
|
27949
|
-
var
|
|
27950
|
-
var
|
|
27951
|
-
var
|
|
28079
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
28080
|
+
var import_node_os10 = __toESM(require("os"), 1);
|
|
28081
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
27952
28082
|
var import_node_child_process3 = require("child_process");
|
|
27953
28083
|
var import_node_stream2 = require("stream");
|
|
27954
28084
|
var import_promises2 = require("stream/promises");
|
|
@@ -27980,20 +28110,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
27980
28110
|
}
|
|
27981
28111
|
async function ensureFrpcBinary(opts) {
|
|
27982
28112
|
if (opts.override) {
|
|
27983
|
-
if (!
|
|
28113
|
+
if (!import_node_fs21.default.existsSync(opts.override)) {
|
|
27984
28114
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
27985
28115
|
}
|
|
27986
28116
|
return opts.override;
|
|
27987
28117
|
}
|
|
27988
28118
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
27989
28119
|
const platform = opts.platform ?? detectPlatform();
|
|
27990
|
-
const binDir =
|
|
27991
|
-
|
|
28120
|
+
const binDir = import_node_path23.default.join(opts.dataDir, "bin");
|
|
28121
|
+
import_node_fs21.default.mkdirSync(binDir, { recursive: true });
|
|
27992
28122
|
cleanupStaleArtifacts(binDir);
|
|
27993
|
-
const stableBin =
|
|
27994
|
-
if (
|
|
28123
|
+
const stableBin = import_node_path23.default.join(binDir, "frpc");
|
|
28124
|
+
if (import_node_fs21.default.existsSync(stableBin)) return stableBin;
|
|
27995
28125
|
const partialBin = `${stableBin}.partial`;
|
|
27996
|
-
const tarballPath =
|
|
28126
|
+
const tarballPath = import_node_path23.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
27997
28127
|
try {
|
|
27998
28128
|
const url = frpcDownloadUrl(version2, platform);
|
|
27999
28129
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -28002,8 +28132,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
28002
28132
|
} else {
|
|
28003
28133
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
28004
28134
|
}
|
|
28005
|
-
|
|
28006
|
-
|
|
28135
|
+
import_node_fs21.default.chmodSync(partialBin, 493);
|
|
28136
|
+
import_node_fs21.default.renameSync(partialBin, stableBin);
|
|
28007
28137
|
} finally {
|
|
28008
28138
|
safeUnlink(tarballPath);
|
|
28009
28139
|
safeUnlink(partialBin);
|
|
@@ -28013,15 +28143,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
28013
28143
|
function cleanupStaleArtifacts(binDir) {
|
|
28014
28144
|
let entries;
|
|
28015
28145
|
try {
|
|
28016
|
-
entries =
|
|
28146
|
+
entries = import_node_fs21.default.readdirSync(binDir);
|
|
28017
28147
|
} catch {
|
|
28018
28148
|
return;
|
|
28019
28149
|
}
|
|
28020
28150
|
for (const name of entries) {
|
|
28021
28151
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
28022
|
-
const full =
|
|
28152
|
+
const full = import_node_path23.default.join(binDir, name);
|
|
28023
28153
|
try {
|
|
28024
|
-
|
|
28154
|
+
import_node_fs21.default.rmSync(full, { recursive: true, force: true });
|
|
28025
28155
|
} catch {
|
|
28026
28156
|
}
|
|
28027
28157
|
}
|
|
@@ -28029,7 +28159,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
28029
28159
|
}
|
|
28030
28160
|
function safeUnlink(p2) {
|
|
28031
28161
|
try {
|
|
28032
|
-
|
|
28162
|
+
import_node_fs21.default.unlinkSync(p2);
|
|
28033
28163
|
} catch {
|
|
28034
28164
|
}
|
|
28035
28165
|
}
|
|
@@ -28040,13 +28170,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
28040
28170
|
if (!res.ok || !res.body) {
|
|
28041
28171
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
28042
28172
|
}
|
|
28043
|
-
const out =
|
|
28173
|
+
const out = import_node_fs21.default.createWriteStream(dest);
|
|
28044
28174
|
const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
|
|
28045
28175
|
await (0, import_promises2.pipeline)(nodeStream, out);
|
|
28046
28176
|
}
|
|
28047
28177
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
28048
|
-
const work =
|
|
28049
|
-
|
|
28178
|
+
const work = import_node_path23.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
28179
|
+
import_node_fs21.default.mkdirSync(work, { recursive: true });
|
|
28050
28180
|
try {
|
|
28051
28181
|
await new Promise((resolve6, reject) => {
|
|
28052
28182
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -28054,32 +28184,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
28054
28184
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
28055
28185
|
});
|
|
28056
28186
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
28057
|
-
const src =
|
|
28058
|
-
if (!
|
|
28187
|
+
const src = import_node_path23.default.join(work, dirName, "frpc");
|
|
28188
|
+
if (!import_node_fs21.default.existsSync(src)) {
|
|
28059
28189
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
28060
28190
|
}
|
|
28061
|
-
|
|
28191
|
+
import_node_fs21.default.copyFileSync(src, destBin);
|
|
28062
28192
|
} finally {
|
|
28063
|
-
|
|
28193
|
+
import_node_fs21.default.rmSync(work, { recursive: true, force: true });
|
|
28064
28194
|
}
|
|
28065
28195
|
}
|
|
28066
28196
|
|
|
28067
28197
|
// src/tunnel/frpc-process.ts
|
|
28068
|
-
var
|
|
28069
|
-
var
|
|
28198
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
28199
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
28070
28200
|
var import_node_child_process4 = require("child_process");
|
|
28071
28201
|
function frpcPidFilePath(dataDir) {
|
|
28072
|
-
return
|
|
28202
|
+
return import_node_path24.default.join(dataDir, "frpc.pid");
|
|
28073
28203
|
}
|
|
28074
28204
|
function writeFrpcPid(dataDir, pid) {
|
|
28075
28205
|
try {
|
|
28076
|
-
|
|
28206
|
+
import_node_fs22.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
28077
28207
|
} catch {
|
|
28078
28208
|
}
|
|
28079
28209
|
}
|
|
28080
28210
|
function clearFrpcPid(dataDir) {
|
|
28081
28211
|
try {
|
|
28082
|
-
|
|
28212
|
+
import_node_fs22.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
28083
28213
|
} catch {
|
|
28084
28214
|
}
|
|
28085
28215
|
}
|
|
@@ -28095,7 +28225,7 @@ function defaultIsPidAlive(pid) {
|
|
|
28095
28225
|
}
|
|
28096
28226
|
function defaultReadPidFile(file) {
|
|
28097
28227
|
try {
|
|
28098
|
-
return
|
|
28228
|
+
return import_node_fs22.default.readFileSync(file, "utf8");
|
|
28099
28229
|
} catch {
|
|
28100
28230
|
return null;
|
|
28101
28231
|
}
|
|
@@ -28111,7 +28241,7 @@ function defaultSleep(ms) {
|
|
|
28111
28241
|
}
|
|
28112
28242
|
async function killStaleFrpc(deps) {
|
|
28113
28243
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
28114
|
-
const tomlPath =
|
|
28244
|
+
const tomlPath = import_node_path24.default.join(deps.dataDir, "frpc.toml");
|
|
28115
28245
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
28116
28246
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
28117
28247
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -28135,7 +28265,7 @@ async function killStaleFrpc(deps) {
|
|
|
28135
28265
|
}
|
|
28136
28266
|
if (victims.size === 0) {
|
|
28137
28267
|
try {
|
|
28138
|
-
|
|
28268
|
+
import_node_fs22.default.unlinkSync(pidFile);
|
|
28139
28269
|
} catch {
|
|
28140
28270
|
}
|
|
28141
28271
|
return;
|
|
@@ -28146,7 +28276,7 @@ async function killStaleFrpc(deps) {
|
|
|
28146
28276
|
}
|
|
28147
28277
|
await sleep(deps.reapWaitMs ?? 300);
|
|
28148
28278
|
try {
|
|
28149
|
-
|
|
28279
|
+
import_node_fs22.default.unlinkSync(pidFile);
|
|
28150
28280
|
} catch {
|
|
28151
28281
|
}
|
|
28152
28282
|
}
|
|
@@ -28183,7 +28313,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
28183
28313
|
var TunnelManager = class {
|
|
28184
28314
|
constructor(deps) {
|
|
28185
28315
|
this.deps = deps;
|
|
28186
|
-
this.store = deps.store ?? new TunnelStore(
|
|
28316
|
+
this.store = deps.store ?? new TunnelStore(import_node_path25.default.join(deps.dataDir, "tunnel.json"));
|
|
28187
28317
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
28188
28318
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
28189
28319
|
}
|
|
@@ -28310,7 +28440,7 @@ var TunnelManager = class {
|
|
|
28310
28440
|
dataDir: this.deps.dataDir,
|
|
28311
28441
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
28312
28442
|
});
|
|
28313
|
-
const tomlPath =
|
|
28443
|
+
const tomlPath = import_node_path25.default.join(this.deps.dataDir, "frpc.toml");
|
|
28314
28444
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto8.default.randomBytes(3).toString("hex")}`;
|
|
28315
28445
|
const toml = buildFrpcToml({
|
|
28316
28446
|
serverAddr: t.frpsHost,
|
|
@@ -28321,12 +28451,12 @@ var TunnelManager = class {
|
|
|
28321
28451
|
localPort,
|
|
28322
28452
|
logLevel: "info"
|
|
28323
28453
|
});
|
|
28324
|
-
await
|
|
28454
|
+
await import_node_fs23.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
28325
28455
|
const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
|
|
28326
28456
|
stdio: ["ignore", "pipe", "pipe"]
|
|
28327
28457
|
});
|
|
28328
|
-
const logFilePath =
|
|
28329
|
-
const logStream =
|
|
28458
|
+
const logFilePath = import_node_path25.default.join(this.deps.dataDir, "frpc.log");
|
|
28459
|
+
const logStream = import_node_fs23.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
28330
28460
|
logStream.on("error", () => {
|
|
28331
28461
|
});
|
|
28332
28462
|
const tee = (chunk) => {
|
|
@@ -28408,23 +28538,23 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
28408
28538
|
}
|
|
28409
28539
|
|
|
28410
28540
|
// src/tunnel/device-key.ts
|
|
28411
|
-
var
|
|
28541
|
+
var import_node_os11 = __toESM(require("os"), 1);
|
|
28412
28542
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
28413
28543
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
28414
28544
|
function deriveStableDeviceKey(opts = {}) {
|
|
28415
|
-
const hostname = opts.hostname ??
|
|
28416
|
-
const uid = opts.uid ?? (typeof
|
|
28545
|
+
const hostname = opts.hostname ?? import_node_os11.default.hostname();
|
|
28546
|
+
const uid = opts.uid ?? (typeof import_node_os11.default.userInfo === "function" ? import_node_os11.default.userInfo().uid : 0);
|
|
28417
28547
|
const input = `${hostname}::${uid}`;
|
|
28418
28548
|
return import_node_crypto9.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
28419
28549
|
}
|
|
28420
28550
|
|
|
28421
28551
|
// src/auth-store.ts
|
|
28422
|
-
var
|
|
28423
|
-
var
|
|
28552
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
28553
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
28424
28554
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
28425
28555
|
var AUTH_FILE_NAME = "auth.json";
|
|
28426
28556
|
function authFilePath(dataDir) {
|
|
28427
|
-
return
|
|
28557
|
+
return import_node_path26.default.join(dataDir, AUTH_FILE_NAME);
|
|
28428
28558
|
}
|
|
28429
28559
|
function loadOrCreateAuthFile(opts) {
|
|
28430
28560
|
const file = authFilePath(opts.dataDir);
|
|
@@ -28456,7 +28586,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
28456
28586
|
}
|
|
28457
28587
|
function readAuthFile(file) {
|
|
28458
28588
|
try {
|
|
28459
|
-
const raw =
|
|
28589
|
+
const raw = import_node_fs24.default.readFileSync(file, "utf8");
|
|
28460
28590
|
const parsed = JSON.parse(raw);
|
|
28461
28591
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
28462
28592
|
return null;
|
|
@@ -28474,25 +28604,25 @@ function readAuthFile(file) {
|
|
|
28474
28604
|
}
|
|
28475
28605
|
}
|
|
28476
28606
|
function writeAuthFile(file, content) {
|
|
28477
|
-
|
|
28478
|
-
|
|
28607
|
+
import_node_fs24.default.mkdirSync(import_node_path26.default.dirname(file), { recursive: true });
|
|
28608
|
+
import_node_fs24.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
28479
28609
|
try {
|
|
28480
|
-
|
|
28610
|
+
import_node_fs24.default.chmodSync(file, 384);
|
|
28481
28611
|
} catch {
|
|
28482
28612
|
}
|
|
28483
28613
|
}
|
|
28484
28614
|
|
|
28485
28615
|
// src/owner-profile.ts
|
|
28486
|
-
var
|
|
28487
|
-
var
|
|
28488
|
-
var
|
|
28616
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
28617
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
28618
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
28489
28619
|
var PROFILE_FILENAME = "profile.json";
|
|
28490
28620
|
function loadOwnerDisplayName(dataDir) {
|
|
28491
|
-
const fallback =
|
|
28492
|
-
const profilePath =
|
|
28621
|
+
const fallback = import_node_os12.default.userInfo().username;
|
|
28622
|
+
const profilePath = import_node_path27.default.join(dataDir, PROFILE_FILENAME);
|
|
28493
28623
|
let raw;
|
|
28494
28624
|
try {
|
|
28495
|
-
raw =
|
|
28625
|
+
raw = import_node_fs25.default.readFileSync(profilePath, "utf8");
|
|
28496
28626
|
} catch {
|
|
28497
28627
|
return fallback;
|
|
28498
28628
|
}
|
|
@@ -28521,12 +28651,12 @@ init_protocol();
|
|
|
28521
28651
|
init_protocol();
|
|
28522
28652
|
|
|
28523
28653
|
// src/session/fork.ts
|
|
28524
|
-
var
|
|
28525
|
-
var
|
|
28526
|
-
var
|
|
28654
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
28655
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
28656
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
28527
28657
|
init_claude_history();
|
|
28528
28658
|
function readJsonlEntries(file) {
|
|
28529
|
-
const raw =
|
|
28659
|
+
const raw = import_node_fs26.default.readFileSync(file, "utf8");
|
|
28530
28660
|
const out = [];
|
|
28531
28661
|
for (const line of raw.split("\n")) {
|
|
28532
28662
|
const t = line.trim();
|
|
@@ -28539,10 +28669,10 @@ function readJsonlEntries(file) {
|
|
|
28539
28669
|
return out;
|
|
28540
28670
|
}
|
|
28541
28671
|
function forkSession(input) {
|
|
28542
|
-
const baseDir = input.baseDir ??
|
|
28543
|
-
const projectDir =
|
|
28544
|
-
const sourceFile =
|
|
28545
|
-
if (!
|
|
28672
|
+
const baseDir = input.baseDir ?? import_node_path28.default.join(import_node_os13.default.homedir(), ".claude");
|
|
28673
|
+
const projectDir = import_node_path28.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
28674
|
+
const sourceFile = import_node_path28.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
28675
|
+
if (!import_node_fs26.default.existsSync(sourceFile)) {
|
|
28546
28676
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
28547
28677
|
}
|
|
28548
28678
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -28572,9 +28702,9 @@ function forkSession(input) {
|
|
|
28572
28702
|
}
|
|
28573
28703
|
forkedLines.push(JSON.stringify(forked));
|
|
28574
28704
|
}
|
|
28575
|
-
const forkedFilePath =
|
|
28576
|
-
|
|
28577
|
-
|
|
28705
|
+
const forkedFilePath = import_node_path28.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
28706
|
+
import_node_fs26.default.mkdirSync(projectDir, { recursive: true });
|
|
28707
|
+
import_node_fs26.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
28578
28708
|
return { forkedToolSessionId, forkedFilePath };
|
|
28579
28709
|
}
|
|
28580
28710
|
|
|
@@ -28906,7 +29036,7 @@ function buildPermissionHandlers(deps) {
|
|
|
28906
29036
|
}
|
|
28907
29037
|
|
|
28908
29038
|
// src/handlers/history.ts
|
|
28909
|
-
var
|
|
29039
|
+
var path38 = __toESM(require("path"), 1);
|
|
28910
29040
|
init_protocol();
|
|
28911
29041
|
|
|
28912
29042
|
// src/session/recent-dirs.ts
|
|
@@ -28924,7 +29054,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
28924
29054
|
}
|
|
28925
29055
|
|
|
28926
29056
|
// src/permission/persona-paths.ts
|
|
28927
|
-
var
|
|
29057
|
+
var path37 = __toESM(require("path"), 1);
|
|
28928
29058
|
function getAllowedPersonaIds(grants, action) {
|
|
28929
29059
|
const ids = /* @__PURE__ */ new Set();
|
|
28930
29060
|
for (const g2 of grants) {
|
|
@@ -28937,26 +29067,26 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
28937
29067
|
return ids;
|
|
28938
29068
|
}
|
|
28939
29069
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read") {
|
|
28940
|
-
const root =
|
|
28941
|
-
const target =
|
|
28942
|
-
const sep3 = root.endsWith(
|
|
29070
|
+
const root = path37.resolve(personaRoot);
|
|
29071
|
+
const target = path37.resolve(absPath);
|
|
29072
|
+
const sep3 = root.endsWith(path37.sep) ? "" : path37.sep;
|
|
28943
29073
|
if (!target.startsWith(root + sep3)) return false;
|
|
28944
|
-
const rel =
|
|
29074
|
+
const rel = path37.relative(root, target);
|
|
28945
29075
|
if (!rel || rel.startsWith("..")) return false;
|
|
28946
|
-
const personaId = rel.split(
|
|
29076
|
+
const personaId = rel.split(path37.sep)[0];
|
|
28947
29077
|
if (!personaId) return false;
|
|
28948
29078
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
28949
29079
|
if (allowed === "*") return true;
|
|
28950
29080
|
return allowed.has(personaId);
|
|
28951
29081
|
}
|
|
28952
29082
|
function personaIdFromPath(absPath, personaRoot) {
|
|
28953
|
-
const root =
|
|
28954
|
-
const target =
|
|
28955
|
-
const sep3 = root.endsWith(
|
|
29083
|
+
const root = path37.resolve(personaRoot);
|
|
29084
|
+
const target = path37.resolve(absPath);
|
|
29085
|
+
const sep3 = root.endsWith(path37.sep) ? "" : path37.sep;
|
|
28956
29086
|
if (!target.startsWith(root + sep3)) return null;
|
|
28957
|
-
const rel =
|
|
29087
|
+
const rel = path37.relative(root, target);
|
|
28958
29088
|
if (!rel || rel.startsWith("..")) return null;
|
|
28959
|
-
const id = rel.split(
|
|
29089
|
+
const id = rel.split(path37.sep)[0];
|
|
28960
29090
|
return id || null;
|
|
28961
29091
|
}
|
|
28962
29092
|
|
|
@@ -28981,7 +29111,7 @@ function buildHistoryHandlers(deps) {
|
|
|
28981
29111
|
if (!pid) return false;
|
|
28982
29112
|
return isGuestPathAllowed(
|
|
28983
29113
|
ctx.grants,
|
|
28984
|
-
|
|
29114
|
+
path38.join(personaRoot, pid),
|
|
28985
29115
|
personaRoot,
|
|
28986
29116
|
"read"
|
|
28987
29117
|
);
|
|
@@ -28992,7 +29122,7 @@ function buildHistoryHandlers(deps) {
|
|
|
28992
29122
|
};
|
|
28993
29123
|
const list = async (frame, _client, ctx) => {
|
|
28994
29124
|
const args = HistoryListArgs.parse(frame);
|
|
28995
|
-
assertGuestPath(ctx,
|
|
29125
|
+
assertGuestPath(ctx, path38.resolve(args.projectPath), personaRoot, "history:list");
|
|
28996
29126
|
const sessions = await history.listSessions(args);
|
|
28997
29127
|
return { response: { type: "history:list", sessions } };
|
|
28998
29128
|
};
|
|
@@ -29024,13 +29154,13 @@ function buildHistoryHandlers(deps) {
|
|
|
29024
29154
|
};
|
|
29025
29155
|
const subagents = async (frame, _client, ctx) => {
|
|
29026
29156
|
const args = HistorySubagentsArgs.parse(frame);
|
|
29027
|
-
assertGuestPath(ctx,
|
|
29157
|
+
assertGuestPath(ctx, path38.resolve(args.cwd), personaRoot, "history:subagents");
|
|
29028
29158
|
const subs = await history.listSubagents(args);
|
|
29029
29159
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
29030
29160
|
};
|
|
29031
29161
|
const subagentRead = async (frame, _client, ctx) => {
|
|
29032
29162
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
29033
|
-
assertGuestPath(ctx,
|
|
29163
|
+
assertGuestPath(ctx, path38.resolve(args.cwd), personaRoot, "history:subagent-read");
|
|
29034
29164
|
const res = await history.readSubagent(args);
|
|
29035
29165
|
return { response: { type: "history:subagent-read", ...res } };
|
|
29036
29166
|
};
|
|
@@ -29038,7 +29168,7 @@ function buildHistoryHandlers(deps) {
|
|
|
29038
29168
|
const dirs = listRecentDirs(store);
|
|
29039
29169
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
29040
29170
|
const filtered = dirs.filter(
|
|
29041
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
29171
|
+
(d) => isGuestPathAllowed(ctx.grants, path38.resolve(d.cwd), personaRoot, "read")
|
|
29042
29172
|
);
|
|
29043
29173
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
29044
29174
|
}
|
|
@@ -29055,8 +29185,8 @@ function buildHistoryHandlers(deps) {
|
|
|
29055
29185
|
}
|
|
29056
29186
|
|
|
29057
29187
|
// src/handlers/workspace.ts
|
|
29058
|
-
var
|
|
29059
|
-
var
|
|
29188
|
+
var path39 = __toESM(require("path"), 1);
|
|
29189
|
+
var os14 = __toESM(require("os"), 1);
|
|
29060
29190
|
init_protocol();
|
|
29061
29191
|
init_protocol();
|
|
29062
29192
|
function buildEnabledPluginNames(personaManager, personaId) {
|
|
@@ -29095,23 +29225,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29095
29225
|
const list = async (frame, _client, ctx) => {
|
|
29096
29226
|
const args = WorkspaceListArgs.parse(frame);
|
|
29097
29227
|
const isGuest = ctx?.principal.kind === "guest";
|
|
29098
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
29099
|
-
const resolvedCwd =
|
|
29100
|
-
const target = args.path ?
|
|
29228
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os14.homedir();
|
|
29229
|
+
const resolvedCwd = path39.resolve(args.cwd ?? fallbackCwd);
|
|
29230
|
+
const target = args.path ? path39.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
29101
29231
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list");
|
|
29102
29232
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
29103
29233
|
return { response: { type: "workspace:list", ...res } };
|
|
29104
29234
|
};
|
|
29105
29235
|
const read = async (frame, _client, ctx) => {
|
|
29106
29236
|
const args = WorkspaceReadArgs.parse(frame);
|
|
29107
|
-
const target =
|
|
29237
|
+
const target = path39.isAbsolute(args.path) ? path39.resolve(args.path) : path39.resolve(args.cwd, args.path);
|
|
29108
29238
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read");
|
|
29109
29239
|
const res = workspace.read(args);
|
|
29110
29240
|
return { response: { type: "workspace:read", ...res } };
|
|
29111
29241
|
};
|
|
29112
29242
|
const skillsList = async (frame, _client, ctx) => {
|
|
29113
29243
|
const args = SkillsListArgs.parse(frame);
|
|
29114
|
-
const cwdAbs =
|
|
29244
|
+
const cwdAbs = path39.resolve(args.cwd);
|
|
29115
29245
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list");
|
|
29116
29246
|
const list2 = skills.list(args);
|
|
29117
29247
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -29123,7 +29253,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29123
29253
|
};
|
|
29124
29254
|
const agentsList = async (frame, _client, ctx) => {
|
|
29125
29255
|
const args = AgentsListArgs.parse(frame);
|
|
29126
|
-
const cwdAbs =
|
|
29256
|
+
const cwdAbs = path39.resolve(args.cwd);
|
|
29127
29257
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list");
|
|
29128
29258
|
const list2 = agents.list(args);
|
|
29129
29259
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -29142,20 +29272,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29142
29272
|
}
|
|
29143
29273
|
|
|
29144
29274
|
// src/handlers/git.ts
|
|
29145
|
-
var
|
|
29275
|
+
var path41 = __toESM(require("path"), 1);
|
|
29146
29276
|
init_protocol();
|
|
29147
29277
|
init_protocol();
|
|
29148
29278
|
|
|
29149
29279
|
// src/workspace/git.ts
|
|
29150
29280
|
var import_node_child_process6 = require("child_process");
|
|
29151
|
-
var
|
|
29152
|
-
var
|
|
29281
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
29282
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
29153
29283
|
var import_node_util = require("util");
|
|
29154
29284
|
var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
|
|
29155
29285
|
function normalizePath(p2) {
|
|
29156
|
-
const resolved =
|
|
29286
|
+
const resolved = import_node_path29.default.resolve(p2);
|
|
29157
29287
|
try {
|
|
29158
|
-
return
|
|
29288
|
+
return import_node_fs27.default.realpathSync(resolved);
|
|
29159
29289
|
} catch {
|
|
29160
29290
|
return resolved;
|
|
29161
29291
|
}
|
|
@@ -29228,7 +29358,7 @@ async function listGitBranches(cwd) {
|
|
|
29228
29358
|
// src/handlers/git.ts
|
|
29229
29359
|
function assertGuestCwd(ctx, cwd, personaRoot, method) {
|
|
29230
29360
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
29231
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
29361
|
+
if (!isGuestPathAllowed(ctx.grants, path41.resolve(cwd), personaRoot, "read")) {
|
|
29232
29362
|
throw new ClawdError(
|
|
29233
29363
|
ERROR_CODES.UNAUTHORIZED,
|
|
29234
29364
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -29591,7 +29721,7 @@ function buildWhoamiHandler(deps) {
|
|
|
29591
29721
|
}
|
|
29592
29722
|
|
|
29593
29723
|
// src/handlers/meta.ts
|
|
29594
|
-
var
|
|
29724
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
29595
29725
|
init_protocol();
|
|
29596
29726
|
|
|
29597
29727
|
// src/version.ts
|
|
@@ -29621,7 +29751,7 @@ function buildReadyFrame(deps, client) {
|
|
|
29621
29751
|
return {
|
|
29622
29752
|
version,
|
|
29623
29753
|
protocolVersion: PROTOCOL_VERSION,
|
|
29624
|
-
hostname:
|
|
29754
|
+
hostname: import_node_os14.default.hostname(),
|
|
29625
29755
|
os: process.platform,
|
|
29626
29756
|
tools,
|
|
29627
29757
|
runningSessions: info.runningSessions,
|
|
@@ -29715,7 +29845,7 @@ function buildPersonaHandlers(deps) {
|
|
|
29715
29845
|
}
|
|
29716
29846
|
|
|
29717
29847
|
// src/handlers/attachment.ts
|
|
29718
|
-
var
|
|
29848
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
29719
29849
|
init_protocol();
|
|
29720
29850
|
init_protocol();
|
|
29721
29851
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -29769,12 +29899,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
29769
29899
|
`session ${args.sessionId} scope unresolved`
|
|
29770
29900
|
);
|
|
29771
29901
|
}
|
|
29772
|
-
const cwdAbs =
|
|
29773
|
-
const candidateAbs =
|
|
29902
|
+
const cwdAbs = import_node_path30.default.resolve(sessionFile.cwd);
|
|
29903
|
+
const candidateAbs = import_node_path30.default.isAbsolute(args.relPath) ? import_node_path30.default.resolve(args.relPath) : import_node_path30.default.resolve(cwdAbs, args.relPath);
|
|
29774
29904
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
|
|
29775
29905
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
29776
29906
|
const entry = entries.find((e) => {
|
|
29777
|
-
const storedAbs =
|
|
29907
|
+
const storedAbs = import_node_path30.default.isAbsolute(e.relPath) ? import_node_path30.default.resolve(e.relPath) : import_node_path30.default.resolve(cwdAbs, e.relPath);
|
|
29778
29908
|
return storedAbs === candidateAbs && !e.stale;
|
|
29779
29909
|
});
|
|
29780
29910
|
if (!entry) {
|
|
@@ -29798,7 +29928,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
29798
29928
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
29799
29929
|
const f = deps.sessionStore.read(sessionId);
|
|
29800
29930
|
if (!f) return;
|
|
29801
|
-
assertGuestAttachmentPath(ctx,
|
|
29931
|
+
assertGuestAttachmentPath(ctx, import_node_path30.default.resolve(f.cwd), deps.personaRoot, method);
|
|
29802
29932
|
}
|
|
29803
29933
|
const groupAdd = async (frame, _client, ctx) => {
|
|
29804
29934
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -30035,7 +30165,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
30035
30165
|
async function startDaemon(config) {
|
|
30036
30166
|
const logger = createLogger({
|
|
30037
30167
|
level: config.logLevel,
|
|
30038
|
-
file:
|
|
30168
|
+
file: import_node_path31.default.join(config.dataDir, "clawd.log")
|
|
30039
30169
|
});
|
|
30040
30170
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
30041
30171
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -30122,7 +30252,7 @@ async function startDaemon(config) {
|
|
|
30122
30252
|
const agents = new AgentsScanner();
|
|
30123
30253
|
const history = new ClaudeHistoryReader();
|
|
30124
30254
|
let transport = null;
|
|
30125
|
-
const personaStore = new PersonaStore(
|
|
30255
|
+
const personaStore = new PersonaStore(import_node_path31.default.join(config.dataDir, "personas"));
|
|
30126
30256
|
const defaultsRoot = findDefaultsRoot();
|
|
30127
30257
|
if (defaultsRoot) {
|
|
30128
30258
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -30139,7 +30269,7 @@ async function startDaemon(config) {
|
|
|
30139
30269
|
getAdapter,
|
|
30140
30270
|
historyReader: history,
|
|
30141
30271
|
dataDir: config.dataDir,
|
|
30142
|
-
personaRoot:
|
|
30272
|
+
personaRoot: import_node_path31.default.join(config.dataDir, "personas"),
|
|
30143
30273
|
personaStore,
|
|
30144
30274
|
ownerDisplayName,
|
|
30145
30275
|
ownerPrincipalId,
|
|
@@ -30163,10 +30293,10 @@ async function startDaemon(config) {
|
|
|
30163
30293
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
30164
30294
|
attachmentGroup: {
|
|
30165
30295
|
onFileEdit: (input) => {
|
|
30166
|
-
const absPath =
|
|
30296
|
+
const absPath = import_node_path31.default.isAbsolute(input.relPath) ? input.relPath : import_node_path31.default.join(input.cwd, input.relPath);
|
|
30167
30297
|
let size = 0;
|
|
30168
30298
|
try {
|
|
30169
|
-
size =
|
|
30299
|
+
size = import_node_fs28.default.statSync(absPath).size;
|
|
30170
30300
|
} catch (err) {
|
|
30171
30301
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
30172
30302
|
sessionId: input.sessionId,
|
|
@@ -30192,6 +30322,11 @@ async function startDaemon(config) {
|
|
|
30192
30322
|
}
|
|
30193
30323
|
});
|
|
30194
30324
|
const observer = new SessionObserver({
|
|
30325
|
+
// TUI 模式 pty 跑 CC 不发 SDK system.task_started 帧 → UI pending 期 progress.agentId
|
|
30326
|
+
// 永远 undefined,子 agent 调用过程没有抽屉入口。开 meta observer 后从 subagents 目录
|
|
30327
|
+
// 新出现的 agent-*.meta.json 派生 subagent_progress(started) 补这块缺口。SDK 模式仍走
|
|
30328
|
+
// task_started 路径,避免双 emit 让 ring buffer 双帧。
|
|
30329
|
+
enableSubagentMetaObserver: config.mode === "tui",
|
|
30195
30330
|
onEvent: ({ sessionId, events }) => {
|
|
30196
30331
|
manager.feedObserverEvents(sessionId, events);
|
|
30197
30332
|
},
|
|
@@ -30279,10 +30414,10 @@ async function startDaemon(config) {
|
|
|
30279
30414
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
30280
30415
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
30281
30416
|
// guest path guard:candidate 必须在 personaRoot 子树下
|
|
30282
|
-
personaRoot:
|
|
30417
|
+
personaRoot: import_node_path31.default.join(config.dataDir, "personas")
|
|
30283
30418
|
},
|
|
30284
30419
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
30285
|
-
personaRoot:
|
|
30420
|
+
personaRoot: import_node_path31.default.join(config.dataDir, "personas"),
|
|
30286
30421
|
// capability:list / delete handler 依赖
|
|
30287
30422
|
capabilityManager,
|
|
30288
30423
|
// personal-cap:get 返回的 shareBaseUrl 用此 base URL:
|
|
@@ -30495,8 +30630,8 @@ async function startDaemon(config) {
|
|
|
30495
30630
|
const lines = [
|
|
30496
30631
|
`Tunnel: ${r.url}`,
|
|
30497
30632
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
30498
|
-
`Frpc config: ${
|
|
30499
|
-
`Frpc log: ${
|
|
30633
|
+
`Frpc config: ${import_node_path31.default.join(config.dataDir, "frpc.toml")}`,
|
|
30634
|
+
`Frpc log: ${import_node_path31.default.join(config.dataDir, "frpc.log")}`
|
|
30500
30635
|
];
|
|
30501
30636
|
const width = Math.max(...lines.map((l) => l.length));
|
|
30502
30637
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -30509,8 +30644,8 @@ ${bar}
|
|
|
30509
30644
|
|
|
30510
30645
|
`);
|
|
30511
30646
|
try {
|
|
30512
|
-
const connectPath =
|
|
30513
|
-
|
|
30647
|
+
const connectPath = import_node_path31.default.join(config.dataDir, "connect.txt");
|
|
30648
|
+
import_node_fs28.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
30514
30649
|
} catch {
|
|
30515
30650
|
}
|
|
30516
30651
|
} catch (err) {
|
|
@@ -30575,9 +30710,9 @@ ${bar}
|
|
|
30575
30710
|
};
|
|
30576
30711
|
}
|
|
30577
30712
|
function migrateDropPersonsDir(dataDir) {
|
|
30578
|
-
const dir =
|
|
30713
|
+
const dir = import_node_path31.default.join(dataDir, "persons");
|
|
30579
30714
|
try {
|
|
30580
|
-
|
|
30715
|
+
import_node_fs28.default.rmSync(dir, { recursive: true, force: true });
|
|
30581
30716
|
} catch {
|
|
30582
30717
|
}
|
|
30583
30718
|
}
|