@clawos-dev/clawd 0.2.28 → 0.2.29
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 +451 -509
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -296,8 +296,8 @@ var require_req = __commonJS({
|
|
|
296
296
|
if (req.originalUrl) {
|
|
297
297
|
_req.url = req.originalUrl;
|
|
298
298
|
} else {
|
|
299
|
-
const
|
|
300
|
-
_req.url = typeof
|
|
299
|
+
const path21 = req.path;
|
|
300
|
+
_req.url = typeof path21 === "string" ? path21 : req.url ? req.url.path || req.url : void 0;
|
|
301
301
|
}
|
|
302
302
|
if (req.query) {
|
|
303
303
|
_req.query = req.query;
|
|
@@ -462,14 +462,14 @@ var require_redact = __commonJS({
|
|
|
462
462
|
}
|
|
463
463
|
return obj;
|
|
464
464
|
}
|
|
465
|
-
function parsePath(
|
|
465
|
+
function parsePath(path21) {
|
|
466
466
|
const parts = [];
|
|
467
467
|
let current = "";
|
|
468
468
|
let inBrackets = false;
|
|
469
469
|
let inQuotes = false;
|
|
470
470
|
let quoteChar = "";
|
|
471
|
-
for (let i = 0; i <
|
|
472
|
-
const char =
|
|
471
|
+
for (let i = 0; i < path21.length; i++) {
|
|
472
|
+
const char = path21[i];
|
|
473
473
|
if (!inBrackets && char === ".") {
|
|
474
474
|
if (current) {
|
|
475
475
|
parts.push(current);
|
|
@@ -600,10 +600,10 @@ var require_redact = __commonJS({
|
|
|
600
600
|
return current;
|
|
601
601
|
}
|
|
602
602
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
603
|
-
for (const
|
|
604
|
-
const parts = parsePath(
|
|
603
|
+
for (const path21 of paths) {
|
|
604
|
+
const parts = parsePath(path21);
|
|
605
605
|
if (parts.includes("*")) {
|
|
606
|
-
redactWildcardPath(obj, parts, censor,
|
|
606
|
+
redactWildcardPath(obj, parts, censor, path21, remove);
|
|
607
607
|
} else {
|
|
608
608
|
if (remove) {
|
|
609
609
|
removeKey(obj, parts);
|
|
@@ -688,8 +688,8 @@ var require_redact = __commonJS({
|
|
|
688
688
|
}
|
|
689
689
|
} else {
|
|
690
690
|
if (afterWildcard.includes("*")) {
|
|
691
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
692
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
691
|
+
const wrappedCensor = typeof censor === "function" ? (value, path21) => {
|
|
692
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path21];
|
|
693
693
|
return censor(value, fullPath);
|
|
694
694
|
} : censor;
|
|
695
695
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -724,8 +724,8 @@ var require_redact = __commonJS({
|
|
|
724
724
|
return null;
|
|
725
725
|
}
|
|
726
726
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
727
|
-
for (const
|
|
728
|
-
const parts = parsePath(
|
|
727
|
+
for (const path21 of pathsToClone) {
|
|
728
|
+
const parts = parsePath(path21);
|
|
729
729
|
let current = pathStructure;
|
|
730
730
|
for (let i = 0; i < parts.length; i++) {
|
|
731
731
|
const part = parts[i];
|
|
@@ -777,24 +777,24 @@ var require_redact = __commonJS({
|
|
|
777
777
|
}
|
|
778
778
|
return cloneSelectively(obj, pathStructure);
|
|
779
779
|
}
|
|
780
|
-
function validatePath(
|
|
781
|
-
if (typeof
|
|
780
|
+
function validatePath(path21) {
|
|
781
|
+
if (typeof path21 !== "string") {
|
|
782
782
|
throw new Error("Paths must be (non-empty) strings");
|
|
783
783
|
}
|
|
784
|
-
if (
|
|
784
|
+
if (path21 === "") {
|
|
785
785
|
throw new Error("Invalid redaction path ()");
|
|
786
786
|
}
|
|
787
|
-
if (
|
|
788
|
-
throw new Error(`Invalid redaction path (${
|
|
787
|
+
if (path21.includes("..")) {
|
|
788
|
+
throw new Error(`Invalid redaction path (${path21})`);
|
|
789
789
|
}
|
|
790
|
-
if (
|
|
791
|
-
throw new Error(`Invalid redaction path (${
|
|
790
|
+
if (path21.includes(",")) {
|
|
791
|
+
throw new Error(`Invalid redaction path (${path21})`);
|
|
792
792
|
}
|
|
793
793
|
let bracketCount = 0;
|
|
794
794
|
let inQuotes = false;
|
|
795
795
|
let quoteChar = "";
|
|
796
|
-
for (let i = 0; i <
|
|
797
|
-
const char =
|
|
796
|
+
for (let i = 0; i < path21.length; i++) {
|
|
797
|
+
const char = path21[i];
|
|
798
798
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
799
799
|
if (!inQuotes) {
|
|
800
800
|
inQuotes = true;
|
|
@@ -808,20 +808,20 @@ var require_redact = __commonJS({
|
|
|
808
808
|
} else if (char === "]" && !inQuotes) {
|
|
809
809
|
bracketCount--;
|
|
810
810
|
if (bracketCount < 0) {
|
|
811
|
-
throw new Error(`Invalid redaction path (${
|
|
811
|
+
throw new Error(`Invalid redaction path (${path21})`);
|
|
812
812
|
}
|
|
813
813
|
}
|
|
814
814
|
}
|
|
815
815
|
if (bracketCount !== 0) {
|
|
816
|
-
throw new Error(`Invalid redaction path (${
|
|
816
|
+
throw new Error(`Invalid redaction path (${path21})`);
|
|
817
817
|
}
|
|
818
818
|
}
|
|
819
819
|
function validatePaths(paths) {
|
|
820
820
|
if (!Array.isArray(paths)) {
|
|
821
821
|
throw new TypeError("paths must be an array");
|
|
822
822
|
}
|
|
823
|
-
for (const
|
|
824
|
-
validatePath(
|
|
823
|
+
for (const path21 of paths) {
|
|
824
|
+
validatePath(path21);
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
function slowRedact(options = {}) {
|
|
@@ -989,8 +989,8 @@ var require_redaction = __commonJS({
|
|
|
989
989
|
if (shape[k] === null) {
|
|
990
990
|
o[k] = (value) => topCensor(value, [k]);
|
|
991
991
|
} else {
|
|
992
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
993
|
-
return censor(value, [k, ...
|
|
992
|
+
const wrappedCensor = typeof censor === "function" ? (value, path21) => {
|
|
993
|
+
return censor(value, [k, ...path21]);
|
|
994
994
|
} : censor;
|
|
995
995
|
o[k] = Redact({
|
|
996
996
|
paths: shape[k],
|
|
@@ -1208,10 +1208,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
1208
1208
|
var require_sonic_boom = __commonJS({
|
|
1209
1209
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
1210
1210
|
"use strict";
|
|
1211
|
-
var
|
|
1211
|
+
var fs21 = require("fs");
|
|
1212
1212
|
var EventEmitter = require("events");
|
|
1213
1213
|
var inherits = require("util").inherits;
|
|
1214
|
-
var
|
|
1214
|
+
var path21 = require("path");
|
|
1215
1215
|
var sleep = require_atomic_sleep();
|
|
1216
1216
|
var assert = require("assert");
|
|
1217
1217
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -1265,20 +1265,20 @@ var require_sonic_boom = __commonJS({
|
|
|
1265
1265
|
const mode = sonic.mode;
|
|
1266
1266
|
if (sonic.sync) {
|
|
1267
1267
|
try {
|
|
1268
|
-
if (sonic.mkdir)
|
|
1269
|
-
const fd =
|
|
1268
|
+
if (sonic.mkdir) fs21.mkdirSync(path21.dirname(file), { recursive: true });
|
|
1269
|
+
const fd = fs21.openSync(file, flags, mode);
|
|
1270
1270
|
fileOpened(null, fd);
|
|
1271
1271
|
} catch (err) {
|
|
1272
1272
|
fileOpened(err);
|
|
1273
1273
|
throw err;
|
|
1274
1274
|
}
|
|
1275
1275
|
} else if (sonic.mkdir) {
|
|
1276
|
-
|
|
1276
|
+
fs21.mkdir(path21.dirname(file), { recursive: true }, (err) => {
|
|
1277
1277
|
if (err) return fileOpened(err);
|
|
1278
|
-
|
|
1278
|
+
fs21.open(file, flags, mode, fileOpened);
|
|
1279
1279
|
});
|
|
1280
1280
|
} else {
|
|
1281
|
-
|
|
1281
|
+
fs21.open(file, flags, mode, fileOpened);
|
|
1282
1282
|
}
|
|
1283
1283
|
}
|
|
1284
1284
|
function SonicBoom(opts) {
|
|
@@ -1319,8 +1319,8 @@ var require_sonic_boom = __commonJS({
|
|
|
1319
1319
|
this.flush = flushBuffer;
|
|
1320
1320
|
this.flushSync = flushBufferSync;
|
|
1321
1321
|
this._actualWrite = actualWriteBuffer;
|
|
1322
|
-
fsWriteSync = () =>
|
|
1323
|
-
fsWrite = () =>
|
|
1322
|
+
fsWriteSync = () => fs21.writeSync(this.fd, this._writingBuf);
|
|
1323
|
+
fsWrite = () => fs21.write(this.fd, this._writingBuf, this.release);
|
|
1324
1324
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
1325
1325
|
this._writingBuf = "";
|
|
1326
1326
|
this.write = write;
|
|
@@ -1329,15 +1329,15 @@ var require_sonic_boom = __commonJS({
|
|
|
1329
1329
|
this._actualWrite = actualWrite;
|
|
1330
1330
|
fsWriteSync = () => {
|
|
1331
1331
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
1332
|
-
return
|
|
1332
|
+
return fs21.writeSync(this.fd, this._writingBuf);
|
|
1333
1333
|
}
|
|
1334
|
-
return
|
|
1334
|
+
return fs21.writeSync(this.fd, this._writingBuf, "utf8");
|
|
1335
1335
|
};
|
|
1336
1336
|
fsWrite = () => {
|
|
1337
1337
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
1338
|
-
return
|
|
1338
|
+
return fs21.write(this.fd, this._writingBuf, this.release);
|
|
1339
1339
|
}
|
|
1340
|
-
return
|
|
1340
|
+
return fs21.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
1341
1341
|
};
|
|
1342
1342
|
} else {
|
|
1343
1343
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -1394,7 +1394,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1394
1394
|
}
|
|
1395
1395
|
}
|
|
1396
1396
|
if (this._fsync) {
|
|
1397
|
-
|
|
1397
|
+
fs21.fsyncSync(this.fd);
|
|
1398
1398
|
}
|
|
1399
1399
|
const len = this._len;
|
|
1400
1400
|
if (this._reopening) {
|
|
@@ -1508,7 +1508,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1508
1508
|
const onDrain = () => {
|
|
1509
1509
|
if (!this._fsync) {
|
|
1510
1510
|
try {
|
|
1511
|
-
|
|
1511
|
+
fs21.fsync(this.fd, (err) => {
|
|
1512
1512
|
this._flushPending = false;
|
|
1513
1513
|
cb(err);
|
|
1514
1514
|
});
|
|
@@ -1610,7 +1610,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1610
1610
|
const fd = this.fd;
|
|
1611
1611
|
this.once("ready", () => {
|
|
1612
1612
|
if (fd !== this.fd) {
|
|
1613
|
-
|
|
1613
|
+
fs21.close(fd, (err) => {
|
|
1614
1614
|
if (err) {
|
|
1615
1615
|
return this.emit("error", err);
|
|
1616
1616
|
}
|
|
@@ -1659,7 +1659,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1659
1659
|
buf = this._bufs[0];
|
|
1660
1660
|
}
|
|
1661
1661
|
try {
|
|
1662
|
-
const n = Buffer.isBuffer(buf) ?
|
|
1662
|
+
const n = Buffer.isBuffer(buf) ? fs21.writeSync(this.fd, buf) : fs21.writeSync(this.fd, buf, "utf8");
|
|
1663
1663
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
1664
1664
|
buf = releasedBufObj.writingBuf;
|
|
1665
1665
|
this._len = releasedBufObj.len;
|
|
@@ -1675,7 +1675,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1675
1675
|
}
|
|
1676
1676
|
}
|
|
1677
1677
|
try {
|
|
1678
|
-
|
|
1678
|
+
fs21.fsyncSync(this.fd);
|
|
1679
1679
|
} catch {
|
|
1680
1680
|
}
|
|
1681
1681
|
}
|
|
@@ -1696,7 +1696,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1696
1696
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
1697
1697
|
}
|
|
1698
1698
|
try {
|
|
1699
|
-
const n =
|
|
1699
|
+
const n = fs21.writeSync(this.fd, buf);
|
|
1700
1700
|
buf = buf.subarray(n);
|
|
1701
1701
|
this._len = Math.max(this._len - n, 0);
|
|
1702
1702
|
if (buf.length <= 0) {
|
|
@@ -1724,13 +1724,13 @@ var require_sonic_boom = __commonJS({
|
|
|
1724
1724
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
1725
1725
|
if (this.sync) {
|
|
1726
1726
|
try {
|
|
1727
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
1727
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs21.writeSync(this.fd, this._writingBuf) : fs21.writeSync(this.fd, this._writingBuf, "utf8");
|
|
1728
1728
|
release(null, written);
|
|
1729
1729
|
} catch (err) {
|
|
1730
1730
|
release(err);
|
|
1731
1731
|
}
|
|
1732
1732
|
} else {
|
|
1733
|
-
|
|
1733
|
+
fs21.write(this.fd, this._writingBuf, release);
|
|
1734
1734
|
}
|
|
1735
1735
|
}
|
|
1736
1736
|
function actualWriteBuffer() {
|
|
@@ -1739,7 +1739,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1739
1739
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
1740
1740
|
if (this.sync) {
|
|
1741
1741
|
try {
|
|
1742
|
-
const written =
|
|
1742
|
+
const written = fs21.writeSync(this.fd, this._writingBuf);
|
|
1743
1743
|
release(null, written);
|
|
1744
1744
|
} catch (err) {
|
|
1745
1745
|
release(err);
|
|
@@ -1748,7 +1748,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1748
1748
|
if (kCopyBuffer) {
|
|
1749
1749
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
1750
1750
|
}
|
|
1751
|
-
|
|
1751
|
+
fs21.write(this.fd, this._writingBuf, release);
|
|
1752
1752
|
}
|
|
1753
1753
|
}
|
|
1754
1754
|
function actualClose(sonic) {
|
|
@@ -1764,12 +1764,12 @@ var require_sonic_boom = __commonJS({
|
|
|
1764
1764
|
sonic._lens = [];
|
|
1765
1765
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
1766
1766
|
try {
|
|
1767
|
-
|
|
1767
|
+
fs21.fsync(sonic.fd, closeWrapped);
|
|
1768
1768
|
} catch {
|
|
1769
1769
|
}
|
|
1770
1770
|
function closeWrapped() {
|
|
1771
1771
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
1772
|
-
|
|
1772
|
+
fs21.close(sonic.fd, done);
|
|
1773
1773
|
} else {
|
|
1774
1774
|
done();
|
|
1775
1775
|
}
|
|
@@ -2026,7 +2026,7 @@ var require_thread_stream = __commonJS({
|
|
|
2026
2026
|
var { version: version2 } = require_package();
|
|
2027
2027
|
var { EventEmitter } = require("events");
|
|
2028
2028
|
var { Worker } = require("worker_threads");
|
|
2029
|
-
var { join:
|
|
2029
|
+
var { join: join3 } = require("path");
|
|
2030
2030
|
var { pathToFileURL } = require("url");
|
|
2031
2031
|
var { wait } = require_wait();
|
|
2032
2032
|
var {
|
|
@@ -2062,7 +2062,7 @@ var require_thread_stream = __commonJS({
|
|
|
2062
2062
|
function createWorker(stream, opts) {
|
|
2063
2063
|
const { filename, workerData } = opts;
|
|
2064
2064
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
2065
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
2065
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join3(__dirname, "lib", "worker.js");
|
|
2066
2066
|
const worker = new Worker(toExecute, {
|
|
2067
2067
|
...opts.workerOpts,
|
|
2068
2068
|
trackUnmanagedFds: false,
|
|
@@ -2448,7 +2448,7 @@ var require_transport = __commonJS({
|
|
|
2448
2448
|
"use strict";
|
|
2449
2449
|
var { createRequire } = require("module");
|
|
2450
2450
|
var getCallers = require_caller();
|
|
2451
|
-
var { join:
|
|
2451
|
+
var { join: join3, isAbsolute, sep } = require("path");
|
|
2452
2452
|
var sleep = require_atomic_sleep();
|
|
2453
2453
|
var onExit = require_on_exit_leak_free();
|
|
2454
2454
|
var ThreadStream = require_thread_stream();
|
|
@@ -2511,7 +2511,7 @@ var require_transport = __commonJS({
|
|
|
2511
2511
|
throw new Error("only one of target or targets can be specified");
|
|
2512
2512
|
}
|
|
2513
2513
|
if (targets) {
|
|
2514
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2514
|
+
target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
|
|
2515
2515
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
2516
2516
|
return {
|
|
2517
2517
|
...dest,
|
|
@@ -2529,7 +2529,7 @@ var require_transport = __commonJS({
|
|
|
2529
2529
|
});
|
|
2530
2530
|
});
|
|
2531
2531
|
} else if (pipeline2) {
|
|
2532
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2532
|
+
target = bundlerOverrides["pino-worker"] || join3(__dirname, "worker.js");
|
|
2533
2533
|
options.pipelines = [pipeline2.map((dest) => {
|
|
2534
2534
|
return {
|
|
2535
2535
|
...dest,
|
|
@@ -2551,7 +2551,7 @@ var require_transport = __commonJS({
|
|
|
2551
2551
|
return origin;
|
|
2552
2552
|
}
|
|
2553
2553
|
if (origin === "pino/file") {
|
|
2554
|
-
return
|
|
2554
|
+
return join3(__dirname, "..", "file.js");
|
|
2555
2555
|
}
|
|
2556
2556
|
let fixTarget2;
|
|
2557
2557
|
for (const filePath of callers) {
|
|
@@ -3541,7 +3541,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3541
3541
|
return circularValue;
|
|
3542
3542
|
}
|
|
3543
3543
|
let res = "";
|
|
3544
|
-
let
|
|
3544
|
+
let join3 = ",";
|
|
3545
3545
|
const originalIndentation = indentation;
|
|
3546
3546
|
if (Array.isArray(value)) {
|
|
3547
3547
|
if (value.length === 0) {
|
|
@@ -3555,7 +3555,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3555
3555
|
indentation += spacer;
|
|
3556
3556
|
res += `
|
|
3557
3557
|
${indentation}`;
|
|
3558
|
-
|
|
3558
|
+
join3 = `,
|
|
3559
3559
|
${indentation}`;
|
|
3560
3560
|
}
|
|
3561
3561
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3563,13 +3563,13 @@ ${indentation}`;
|
|
|
3563
3563
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3564
3564
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3565
3565
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3566
|
-
res +=
|
|
3566
|
+
res += join3;
|
|
3567
3567
|
}
|
|
3568
3568
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3569
3569
|
res += tmp !== void 0 ? tmp : "null";
|
|
3570
3570
|
if (value.length - 1 > maximumBreadth) {
|
|
3571
3571
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3572
|
-
res += `${
|
|
3572
|
+
res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3573
3573
|
}
|
|
3574
3574
|
if (spacer !== "") {
|
|
3575
3575
|
res += `
|
|
@@ -3590,7 +3590,7 @@ ${originalIndentation}`;
|
|
|
3590
3590
|
let separator = "";
|
|
3591
3591
|
if (spacer !== "") {
|
|
3592
3592
|
indentation += spacer;
|
|
3593
|
-
|
|
3593
|
+
join3 = `,
|
|
3594
3594
|
${indentation}`;
|
|
3595
3595
|
whitespace = " ";
|
|
3596
3596
|
}
|
|
@@ -3604,13 +3604,13 @@ ${indentation}`;
|
|
|
3604
3604
|
const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
|
|
3605
3605
|
if (tmp !== void 0) {
|
|
3606
3606
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
3607
|
-
separator =
|
|
3607
|
+
separator = join3;
|
|
3608
3608
|
}
|
|
3609
3609
|
}
|
|
3610
3610
|
if (keyLength > maximumBreadth) {
|
|
3611
3611
|
const removedKeys = keyLength - maximumBreadth;
|
|
3612
3612
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
3613
|
-
separator =
|
|
3613
|
+
separator = join3;
|
|
3614
3614
|
}
|
|
3615
3615
|
if (spacer !== "" && separator.length > 1) {
|
|
3616
3616
|
res = `
|
|
@@ -3651,7 +3651,7 @@ ${originalIndentation}`;
|
|
|
3651
3651
|
}
|
|
3652
3652
|
const originalIndentation = indentation;
|
|
3653
3653
|
let res = "";
|
|
3654
|
-
let
|
|
3654
|
+
let join3 = ",";
|
|
3655
3655
|
if (Array.isArray(value)) {
|
|
3656
3656
|
if (value.length === 0) {
|
|
3657
3657
|
return "[]";
|
|
@@ -3664,7 +3664,7 @@ ${originalIndentation}`;
|
|
|
3664
3664
|
indentation += spacer;
|
|
3665
3665
|
res += `
|
|
3666
3666
|
${indentation}`;
|
|
3667
|
-
|
|
3667
|
+
join3 = `,
|
|
3668
3668
|
${indentation}`;
|
|
3669
3669
|
}
|
|
3670
3670
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3672,13 +3672,13 @@ ${indentation}`;
|
|
|
3672
3672
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3673
3673
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3674
3674
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3675
|
-
res +=
|
|
3675
|
+
res += join3;
|
|
3676
3676
|
}
|
|
3677
3677
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3678
3678
|
res += tmp !== void 0 ? tmp : "null";
|
|
3679
3679
|
if (value.length - 1 > maximumBreadth) {
|
|
3680
3680
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3681
|
-
res += `${
|
|
3681
|
+
res += `${join3}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3682
3682
|
}
|
|
3683
3683
|
if (spacer !== "") {
|
|
3684
3684
|
res += `
|
|
@@ -3691,7 +3691,7 @@ ${originalIndentation}`;
|
|
|
3691
3691
|
let whitespace = "";
|
|
3692
3692
|
if (spacer !== "") {
|
|
3693
3693
|
indentation += spacer;
|
|
3694
|
-
|
|
3694
|
+
join3 = `,
|
|
3695
3695
|
${indentation}`;
|
|
3696
3696
|
whitespace = " ";
|
|
3697
3697
|
}
|
|
@@ -3700,7 +3700,7 @@ ${indentation}`;
|
|
|
3700
3700
|
const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
|
|
3701
3701
|
if (tmp !== void 0) {
|
|
3702
3702
|
res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
|
|
3703
|
-
separator =
|
|
3703
|
+
separator = join3;
|
|
3704
3704
|
}
|
|
3705
3705
|
}
|
|
3706
3706
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -3758,20 +3758,20 @@ ${originalIndentation}`;
|
|
|
3758
3758
|
indentation += spacer;
|
|
3759
3759
|
let res2 = `
|
|
3760
3760
|
${indentation}`;
|
|
3761
|
-
const
|
|
3761
|
+
const join4 = `,
|
|
3762
3762
|
${indentation}`;
|
|
3763
3763
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
3764
3764
|
let i = 0;
|
|
3765
3765
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3766
3766
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3767
3767
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
3768
|
-
res2 +=
|
|
3768
|
+
res2 += join4;
|
|
3769
3769
|
}
|
|
3770
3770
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3771
3771
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
3772
3772
|
if (value.length - 1 > maximumBreadth) {
|
|
3773
3773
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3774
|
-
res2 += `${
|
|
3774
|
+
res2 += `${join4}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3775
3775
|
}
|
|
3776
3776
|
res2 += `
|
|
3777
3777
|
${originalIndentation}`;
|
|
@@ -3787,16 +3787,16 @@ ${originalIndentation}`;
|
|
|
3787
3787
|
return '"[Object]"';
|
|
3788
3788
|
}
|
|
3789
3789
|
indentation += spacer;
|
|
3790
|
-
const
|
|
3790
|
+
const join3 = `,
|
|
3791
3791
|
${indentation}`;
|
|
3792
3792
|
let res = "";
|
|
3793
3793
|
let separator = "";
|
|
3794
3794
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
3795
3795
|
if (isTypedArrayWithEntries(value)) {
|
|
3796
|
-
res += stringifyTypedArray(value,
|
|
3796
|
+
res += stringifyTypedArray(value, join3, maximumBreadth);
|
|
3797
3797
|
keys = keys.slice(value.length);
|
|
3798
3798
|
maximumPropertiesToStringify -= value.length;
|
|
3799
|
-
separator =
|
|
3799
|
+
separator = join3;
|
|
3800
3800
|
}
|
|
3801
3801
|
if (deterministic) {
|
|
3802
3802
|
keys = sort(keys, comparator);
|
|
@@ -3807,13 +3807,13 @@ ${indentation}`;
|
|
|
3807
3807
|
const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
|
|
3808
3808
|
if (tmp !== void 0) {
|
|
3809
3809
|
res += `${separator}${strEscape(key2)}: ${tmp}`;
|
|
3810
|
-
separator =
|
|
3810
|
+
separator = join3;
|
|
3811
3811
|
}
|
|
3812
3812
|
}
|
|
3813
3813
|
if (keyLength > maximumBreadth) {
|
|
3814
3814
|
const removedKeys = keyLength - maximumBreadth;
|
|
3815
3815
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
3816
|
-
separator =
|
|
3816
|
+
separator = join3;
|
|
3817
3817
|
}
|
|
3818
3818
|
if (separator !== "") {
|
|
3819
3819
|
res = `
|
|
@@ -4883,8 +4883,8 @@ var init_parseUtil = __esm({
|
|
|
4883
4883
|
init_errors2();
|
|
4884
4884
|
init_en();
|
|
4885
4885
|
makeIssue = (params) => {
|
|
4886
|
-
const { data, path:
|
|
4887
|
-
const fullPath = [...
|
|
4886
|
+
const { data, path: path21, errorMaps, issueData } = params;
|
|
4887
|
+
const fullPath = [...path21, ...issueData.path || []];
|
|
4888
4888
|
const fullIssue = {
|
|
4889
4889
|
...issueData,
|
|
4890
4890
|
path: fullPath
|
|
@@ -5195,11 +5195,11 @@ var init_types = __esm({
|
|
|
5195
5195
|
init_parseUtil();
|
|
5196
5196
|
init_util();
|
|
5197
5197
|
ParseInputLazyPath = class {
|
|
5198
|
-
constructor(parent, value,
|
|
5198
|
+
constructor(parent, value, path21, key) {
|
|
5199
5199
|
this._cachedPath = [];
|
|
5200
5200
|
this.parent = parent;
|
|
5201
5201
|
this.data = value;
|
|
5202
|
-
this._path =
|
|
5202
|
+
this._path = path21;
|
|
5203
5203
|
this._key = key;
|
|
5204
5204
|
}
|
|
5205
5205
|
get path() {
|
|
@@ -8583,32 +8583,25 @@ var init_zod = __esm({
|
|
|
8583
8583
|
});
|
|
8584
8584
|
|
|
8585
8585
|
// ../protocol/src/persona-schemas.ts
|
|
8586
|
-
var
|
|
8586
|
+
var PersonaTokenEntrySchema, PersonaFileSchema, PersonaHelloFrameSchema, PersonaSendFrameSchema, PersonaResetFrameSchema, PersonaPingFrameSchema, PersonaReadyFrameSchema, PersonaHistoryEventFrameSchema, PersonaHistoryDoneFrameSchema, PersonaEventFrameSchema, PersonaErrorFrameSchema, PersonaPongFrameSchema, PersonaClientFrameSchema, PersonaServerFrameSchema, PersonaCreateArgsSchema, PersonaIdArgsSchema, PersonaUpdateArgsSchema, PersonaIssueTokenArgsSchema, PersonaRevokeTokenArgsSchema, PersonaAppendOwnerMessageArgsSchema;
|
|
8587
8587
|
var init_persona_schemas = __esm({
|
|
8588
8588
|
"../protocol/src/persona-schemas.ts"() {
|
|
8589
8589
|
"use strict";
|
|
8590
8590
|
init_zod();
|
|
8591
|
-
ALLOWED_PERSONA_TOOLS = ["Read", "Grep", "Glob"];
|
|
8592
8591
|
PersonaTokenEntrySchema = external_exports.object({
|
|
8593
|
-
label: external_exports.string()
|
|
8594
|
-
issuedAt: external_exports.
|
|
8595
|
-
revoked: external_exports.boolean()
|
|
8592
|
+
label: external_exports.string(),
|
|
8593
|
+
issuedAt: external_exports.number(),
|
|
8594
|
+
revoked: external_exports.boolean()
|
|
8596
8595
|
});
|
|
8597
8596
|
PersonaFileSchema = external_exports.object({
|
|
8598
|
-
personaId: external_exports.string()
|
|
8599
|
-
label: external_exports.string()
|
|
8600
|
-
// cwd 必须是绝对路径;老板侧创建时 daemon 校验
|
|
8601
|
-
cwd: external_exports.string().refine((p) => p.startsWith("/"), { message: "cwd must be absolute" }),
|
|
8597
|
+
personaId: external_exports.string(),
|
|
8598
|
+
label: external_exports.string(),
|
|
8602
8599
|
model: external_exports.string().optional(),
|
|
8603
|
-
systemPromptAppend: external_exports.string().optional(),
|
|
8604
|
-
// L1 锁死:permissionMode 只能是 'plan',toolAllowlist 只能是 ALLOWED_PERSONA_TOOLS 子集
|
|
8605
|
-
permissionMode: external_exports.literal("plan"),
|
|
8606
|
-
toolAllowlist: external_exports.array(external_exports.enum(ALLOWED_PERSONA_TOOLS)),
|
|
8607
8600
|
public: external_exports.boolean(),
|
|
8608
8601
|
tokenMap: external_exports.record(external_exports.string(), PersonaTokenEntrySchema),
|
|
8609
|
-
createdAt: external_exports.
|
|
8610
|
-
updatedAt: external_exports.
|
|
8611
|
-
});
|
|
8602
|
+
createdAt: external_exports.number(),
|
|
8603
|
+
updatedAt: external_exports.number()
|
|
8604
|
+
}).strict();
|
|
8612
8605
|
PersonaHelloFrameSchema = external_exports.object({
|
|
8613
8606
|
kind: external_exports.literal("persona-hello"),
|
|
8614
8607
|
token: external_exports.string().min(1)
|
|
@@ -8669,34 +8662,33 @@ var init_persona_schemas = __esm({
|
|
|
8669
8662
|
PersonaErrorFrameSchema,
|
|
8670
8663
|
PersonaPongFrameSchema
|
|
8671
8664
|
]);
|
|
8672
|
-
|
|
8665
|
+
PersonaCreateArgsSchema = external_exports.object({
|
|
8673
8666
|
label: external_exports.string().min(1),
|
|
8674
|
-
|
|
8667
|
+
personality: external_exports.string(),
|
|
8675
8668
|
model: external_exports.string().optional(),
|
|
8676
|
-
|
|
8677
|
-
});
|
|
8678
|
-
|
|
8669
|
+
public: external_exports.boolean().optional()
|
|
8670
|
+
}).strict();
|
|
8671
|
+
PersonaIdArgsSchema = external_exports.object({
|
|
8679
8672
|
personaId: external_exports.string().min(1)
|
|
8680
8673
|
});
|
|
8681
|
-
|
|
8674
|
+
PersonaUpdateArgsSchema = external_exports.object({
|
|
8682
8675
|
personaId: external_exports.string().min(1),
|
|
8683
8676
|
patch: external_exports.object({
|
|
8684
8677
|
label: external_exports.string().min(1).optional(),
|
|
8685
|
-
cwd: external_exports.string().min(1).optional(),
|
|
8686
8678
|
model: external_exports.string().optional(),
|
|
8687
|
-
|
|
8679
|
+
personality: external_exports.string().optional(),
|
|
8688
8680
|
public: external_exports.boolean().optional()
|
|
8689
8681
|
}).strict()
|
|
8690
|
-
});
|
|
8691
|
-
|
|
8682
|
+
}).strict();
|
|
8683
|
+
PersonaIssueTokenArgsSchema = external_exports.object({
|
|
8692
8684
|
personaId: external_exports.string().min(1),
|
|
8693
8685
|
label: external_exports.string().min(1)
|
|
8694
8686
|
});
|
|
8695
|
-
|
|
8687
|
+
PersonaRevokeTokenArgsSchema = external_exports.object({
|
|
8696
8688
|
personaId: external_exports.string().min(1),
|
|
8697
8689
|
token: external_exports.string().min(1)
|
|
8698
8690
|
});
|
|
8699
|
-
|
|
8691
|
+
PersonaAppendOwnerMessageArgsSchema = external_exports.object({
|
|
8700
8692
|
personaId: external_exports.string().min(1),
|
|
8701
8693
|
subSessionId: external_exports.string().min(1),
|
|
8702
8694
|
text: external_exports.string().min(1)
|
|
@@ -9828,11 +9820,11 @@ var init_lib = __esm({
|
|
|
9828
9820
|
}
|
|
9829
9821
|
}
|
|
9830
9822
|
},
|
|
9831
|
-
addToPath: function addToPath(
|
|
9832
|
-
var last =
|
|
9823
|
+
addToPath: function addToPath(path21, added, removed, oldPosInc, options) {
|
|
9824
|
+
var last = path21.lastComponent;
|
|
9833
9825
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
9834
9826
|
return {
|
|
9835
|
-
oldPos:
|
|
9827
|
+
oldPos: path21.oldPos + oldPosInc,
|
|
9836
9828
|
lastComponent: {
|
|
9837
9829
|
count: last.count + 1,
|
|
9838
9830
|
added,
|
|
@@ -9842,7 +9834,7 @@ var init_lib = __esm({
|
|
|
9842
9834
|
};
|
|
9843
9835
|
} else {
|
|
9844
9836
|
return {
|
|
9845
|
-
oldPos:
|
|
9837
|
+
oldPos: path21.oldPos + oldPosInc,
|
|
9846
9838
|
lastComponent: {
|
|
9847
9839
|
count: 1,
|
|
9848
9840
|
added,
|
|
@@ -9900,7 +9892,7 @@ var init_lib = __esm({
|
|
|
9900
9892
|
tokenize: function tokenize(value) {
|
|
9901
9893
|
return Array.from(value);
|
|
9902
9894
|
},
|
|
9903
|
-
join: function
|
|
9895
|
+
join: function join2(chars) {
|
|
9904
9896
|
return chars.join("");
|
|
9905
9897
|
},
|
|
9906
9898
|
postProcess: function postProcess(changeObjects) {
|
|
@@ -10088,7 +10080,7 @@ function hashDirToCwd(hash) {
|
|
|
10088
10080
|
}
|
|
10089
10081
|
function safeStatMtime(p) {
|
|
10090
10082
|
try {
|
|
10091
|
-
return
|
|
10083
|
+
return import_node_fs6.default.statSync(p).mtimeMs;
|
|
10092
10084
|
} catch {
|
|
10093
10085
|
return 0;
|
|
10094
10086
|
}
|
|
@@ -10096,7 +10088,7 @@ function safeStatMtime(p) {
|
|
|
10096
10088
|
function readJsonlLines(file) {
|
|
10097
10089
|
let raw;
|
|
10098
10090
|
try {
|
|
10099
|
-
raw =
|
|
10091
|
+
raw = import_node_fs6.default.readFileSync(file, "utf8");
|
|
10100
10092
|
} catch (err) {
|
|
10101
10093
|
if (err.code === "ENOENT") return [];
|
|
10102
10094
|
throw err;
|
|
@@ -10273,10 +10265,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
10273
10265
|
const memories = raw.map((m) => {
|
|
10274
10266
|
if (!m || typeof m !== "object") return null;
|
|
10275
10267
|
const rec = m;
|
|
10276
|
-
const
|
|
10268
|
+
const path21 = typeof rec.path === "string" ? rec.path : null;
|
|
10277
10269
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10278
|
-
if (!
|
|
10279
|
-
const entry = { path:
|
|
10270
|
+
if (!path21 || content == null) return null;
|
|
10271
|
+
const entry = { path: path21, content };
|
|
10280
10272
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
10281
10273
|
return entry;
|
|
10282
10274
|
}).filter((m) => m !== null);
|
|
@@ -10312,8 +10304,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
10312
10304
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
10313
10305
|
if (backupFileName === null) return null;
|
|
10314
10306
|
try {
|
|
10315
|
-
return
|
|
10316
|
-
|
|
10307
|
+
return import_node_fs6.default.readFileSync(
|
|
10308
|
+
import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
10317
10309
|
"utf8"
|
|
10318
10310
|
);
|
|
10319
10311
|
} catch {
|
|
@@ -10322,19 +10314,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
10322
10314
|
}
|
|
10323
10315
|
function readCurrentContent(filePath) {
|
|
10324
10316
|
try {
|
|
10325
|
-
return
|
|
10317
|
+
return import_node_fs6.default.readFileSync(filePath, "utf8");
|
|
10326
10318
|
} catch (err) {
|
|
10327
10319
|
if (err.code === "ENOENT") return null;
|
|
10328
10320
|
return null;
|
|
10329
10321
|
}
|
|
10330
10322
|
}
|
|
10331
|
-
var
|
|
10323
|
+
var import_node_fs6, import_node_os2, import_node_path5, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
10332
10324
|
var init_claude_history = __esm({
|
|
10333
10325
|
"src/tools/claude-history.ts"() {
|
|
10334
10326
|
"use strict";
|
|
10335
|
-
|
|
10327
|
+
import_node_fs6 = __toESM(require("fs"), 1);
|
|
10336
10328
|
import_node_os2 = __toESM(require("os"), 1);
|
|
10337
|
-
|
|
10329
|
+
import_node_path5 = __toESM(require("path"), 1);
|
|
10338
10330
|
init_lib();
|
|
10339
10331
|
init_tool_result_extra();
|
|
10340
10332
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -10358,14 +10350,14 @@ var init_claude_history = __esm({
|
|
|
10358
10350
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
10359
10351
|
fileHistoryRoot;
|
|
10360
10352
|
constructor(opts = {}) {
|
|
10361
|
-
const base = opts.baseDir ??
|
|
10362
|
-
this.projectsRoot =
|
|
10363
|
-
this.fileHistoryRoot =
|
|
10353
|
+
const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
|
|
10354
|
+
this.projectsRoot = import_node_path5.default.join(base, "projects");
|
|
10355
|
+
this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
|
|
10364
10356
|
}
|
|
10365
10357
|
async listProjects() {
|
|
10366
10358
|
let entries;
|
|
10367
10359
|
try {
|
|
10368
|
-
entries =
|
|
10360
|
+
entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
10369
10361
|
} catch (err) {
|
|
10370
10362
|
if (err.code === "ENOENT") return [];
|
|
10371
10363
|
throw err;
|
|
@@ -10373,9 +10365,9 @@ var init_claude_history = __esm({
|
|
|
10373
10365
|
const out = [];
|
|
10374
10366
|
for (const ent of entries) {
|
|
10375
10367
|
if (!ent.isDirectory()) continue;
|
|
10376
|
-
const dir =
|
|
10377
|
-
const files =
|
|
10378
|
-
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(
|
|
10368
|
+
const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
|
|
10369
|
+
const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
10370
|
+
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
|
|
10379
10371
|
out.push({
|
|
10380
10372
|
projectPath: hashDirToCwd(ent.name),
|
|
10381
10373
|
hashDir: ent.name,
|
|
@@ -10387,17 +10379,17 @@ var init_claude_history = __esm({
|
|
|
10387
10379
|
return out;
|
|
10388
10380
|
}
|
|
10389
10381
|
async listSessions(args) {
|
|
10390
|
-
const dir =
|
|
10382
|
+
const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
10391
10383
|
let files;
|
|
10392
10384
|
try {
|
|
10393
|
-
files =
|
|
10385
|
+
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
10394
10386
|
} catch (err) {
|
|
10395
10387
|
if (err.code === "ENOENT") return [];
|
|
10396
10388
|
throw err;
|
|
10397
10389
|
}
|
|
10398
10390
|
const out = [];
|
|
10399
10391
|
for (const f of files) {
|
|
10400
|
-
const full =
|
|
10392
|
+
const full = import_node_path5.default.join(dir, f);
|
|
10401
10393
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
10402
10394
|
const lines = readJsonlLines(full);
|
|
10403
10395
|
let summary = "";
|
|
@@ -10452,7 +10444,7 @@ var init_claude_history = __esm({
|
|
|
10452
10444
|
return out;
|
|
10453
10445
|
}
|
|
10454
10446
|
async read(args) {
|
|
10455
|
-
const file =
|
|
10447
|
+
const file = import_node_path5.default.join(
|
|
10456
10448
|
this.projectsRoot,
|
|
10457
10449
|
cwdToHashDir(args.cwd),
|
|
10458
10450
|
`${args.toolSessionId}.jsonl`
|
|
@@ -10485,7 +10477,7 @@ var init_claude_history = __esm({
|
|
|
10485
10477
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
10486
10478
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
10487
10479
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
10488
|
-
const dir =
|
|
10480
|
+
const dir = import_node_path5.default.join(
|
|
10489
10481
|
this.projectsRoot,
|
|
10490
10482
|
cwdToHashDir(cwd),
|
|
10491
10483
|
toolSessionId,
|
|
@@ -10493,7 +10485,7 @@ var init_claude_history = __esm({
|
|
|
10493
10485
|
);
|
|
10494
10486
|
let entries;
|
|
10495
10487
|
try {
|
|
10496
|
-
entries =
|
|
10488
|
+
entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
|
|
10497
10489
|
} catch (err) {
|
|
10498
10490
|
if (err.code === "ENOENT") return null;
|
|
10499
10491
|
return null;
|
|
@@ -10503,7 +10495,7 @@ var init_claude_history = __esm({
|
|
|
10503
10495
|
if (!e.isFile()) continue;
|
|
10504
10496
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
10505
10497
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
10506
|
-
const filePath =
|
|
10498
|
+
const filePath = import_node_path5.default.join(dir, e.name);
|
|
10507
10499
|
const lines = readJsonlLines(filePath);
|
|
10508
10500
|
let firstText = "";
|
|
10509
10501
|
let messageCount = 0;
|
|
@@ -10520,7 +10512,7 @@ var init_claude_history = __esm({
|
|
|
10520
10512
|
return out;
|
|
10521
10513
|
}
|
|
10522
10514
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
10523
|
-
const file =
|
|
10515
|
+
const file = import_node_path5.default.join(
|
|
10524
10516
|
this.projectsRoot,
|
|
10525
10517
|
cwdToHashDir(cwd),
|
|
10526
10518
|
`${toolSessionId}.jsonl`
|
|
@@ -10555,7 +10547,7 @@ var init_claude_history = __esm({
|
|
|
10555
10547
|
}
|
|
10556
10548
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
10557
10549
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
10558
|
-
const file =
|
|
10550
|
+
const file = import_node_path5.default.join(
|
|
10559
10551
|
this.projectsRoot,
|
|
10560
10552
|
cwdToHashDir(cwd),
|
|
10561
10553
|
toolSessionId,
|
|
@@ -10564,7 +10556,7 @@ var init_claude_history = __esm({
|
|
|
10564
10556
|
);
|
|
10565
10557
|
let exists = false;
|
|
10566
10558
|
try {
|
|
10567
|
-
exists =
|
|
10559
|
+
exists = import_node_fs6.default.statSync(file).isFile();
|
|
10568
10560
|
} catch {
|
|
10569
10561
|
return null;
|
|
10570
10562
|
}
|
|
@@ -10583,7 +10575,7 @@ var init_claude_history = __esm({
|
|
|
10583
10575
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
10584
10576
|
*/
|
|
10585
10577
|
readFileHistorySnapshots(args) {
|
|
10586
|
-
const file =
|
|
10578
|
+
const file = import_node_path5.default.join(
|
|
10587
10579
|
this.projectsRoot,
|
|
10588
10580
|
cwdToHashDir(args.cwd),
|
|
10589
10581
|
`${args.toolSessionId}.jsonl`
|
|
@@ -10628,7 +10620,7 @@ var init_claude_history = __esm({
|
|
|
10628
10620
|
for (const [anchorId, target] of snapshots) {
|
|
10629
10621
|
let hasAny = false;
|
|
10630
10622
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
10631
|
-
const absPath =
|
|
10623
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
10632
10624
|
const backupContent = readBackupContent(
|
|
10633
10625
|
this.fileHistoryRoot,
|
|
10634
10626
|
args.toolSessionId,
|
|
@@ -10668,7 +10660,7 @@ var init_claude_history = __esm({
|
|
|
10668
10660
|
let totalInsertions = 0;
|
|
10669
10661
|
let totalDeletions = 0;
|
|
10670
10662
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
10671
|
-
const absPath =
|
|
10663
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
10672
10664
|
const backupContent = readBackupContent(
|
|
10673
10665
|
this.fileHistoryRoot,
|
|
10674
10666
|
args.toolSessionId,
|
|
@@ -10715,7 +10707,7 @@ var init_claude_history = __esm({
|
|
|
10715
10707
|
};
|
|
10716
10708
|
}
|
|
10717
10709
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
10718
|
-
const file =
|
|
10710
|
+
const file = import_node_path5.default.join(
|
|
10719
10711
|
this.projectsRoot,
|
|
10720
10712
|
cwdToHashDir(cwd),
|
|
10721
10713
|
`${toolSessionId}.jsonl`
|
|
@@ -10739,27 +10731,27 @@ var init_claude_history = __esm({
|
|
|
10739
10731
|
// src/tools/claude.ts
|
|
10740
10732
|
function macOSDesktopCandidates(home) {
|
|
10741
10733
|
return [
|
|
10742
|
-
|
|
10734
|
+
import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
10743
10735
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
10744
10736
|
];
|
|
10745
10737
|
}
|
|
10746
10738
|
function probeViaWhich() {
|
|
10747
10739
|
try {
|
|
10748
10740
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
10749
|
-
if (out &&
|
|
10741
|
+
if (out && import_node_fs7.default.existsSync(out)) return out;
|
|
10750
10742
|
} catch {
|
|
10751
10743
|
}
|
|
10752
10744
|
return null;
|
|
10753
10745
|
}
|
|
10754
10746
|
async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
|
|
10755
|
-
if (env.CLAUDE_BIN &&
|
|
10747
|
+
if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
|
|
10756
10748
|
return { available: true, path: env.CLAUDE_BIN };
|
|
10757
10749
|
}
|
|
10758
10750
|
const w = probeViaWhich();
|
|
10759
10751
|
if (w) return { available: true, path: w };
|
|
10760
10752
|
if (process.platform === "darwin") {
|
|
10761
10753
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
10762
|
-
if (
|
|
10754
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
10763
10755
|
return { available: true, path: candidate };
|
|
10764
10756
|
}
|
|
10765
10757
|
}
|
|
@@ -10784,11 +10776,8 @@ function buildSpawnArgs(ctx) {
|
|
|
10784
10776
|
"--verbose"
|
|
10785
10777
|
];
|
|
10786
10778
|
if (ctx.model) args.push("--model", ctx.model);
|
|
10787
|
-
|
|
10788
|
-
|
|
10789
|
-
args.push("--permission-mode", ctx.hardcodedPermissionMode ?? "plan");
|
|
10790
|
-
args.push("--add-dir", ctx.cwd);
|
|
10791
|
-
args.push("--disallowed-tools", HARDCODED_DISALLOWED_TOOLS.join(" "));
|
|
10779
|
+
if (ctx.personaMode) {
|
|
10780
|
+
args.push("--setting-sources", "project,local");
|
|
10792
10781
|
} else if (ctx.permissionMode) {
|
|
10793
10782
|
args.push("--permission-mode", ctx.permissionMode);
|
|
10794
10783
|
}
|
|
@@ -11070,10 +11059,10 @@ function parseAttachment(obj) {
|
|
|
11070
11059
|
const memories = raw.map((m) => {
|
|
11071
11060
|
if (!m || typeof m !== "object") return null;
|
|
11072
11061
|
const rec = m;
|
|
11073
|
-
const
|
|
11062
|
+
const path21 = typeof rec.path === "string" ? rec.path : null;
|
|
11074
11063
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11075
|
-
if (!
|
|
11076
|
-
const out = { path:
|
|
11064
|
+
if (!path21 || content == null) return null;
|
|
11065
|
+
const out = { path: path21, content };
|
|
11077
11066
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
11078
11067
|
return out;
|
|
11079
11068
|
}).filter((m) => m !== null);
|
|
@@ -11177,19 +11166,18 @@ function encodeClaudeStdin(text) {
|
|
|
11177
11166
|
};
|
|
11178
11167
|
return JSON.stringify(frame) + "\n";
|
|
11179
11168
|
}
|
|
11180
|
-
var import_node_child_process, import_node_child_process2,
|
|
11169
|
+
var import_node_child_process, import_node_child_process2, import_node_fs7, import_node_os3, import_node_path6, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
11181
11170
|
var init_claude = __esm({
|
|
11182
11171
|
"src/tools/claude.ts"() {
|
|
11183
11172
|
"use strict";
|
|
11184
11173
|
import_node_child_process = require("child_process");
|
|
11185
11174
|
import_node_child_process2 = require("child_process");
|
|
11186
|
-
|
|
11175
|
+
import_node_fs7 = __toESM(require("fs"), 1);
|
|
11187
11176
|
import_node_os3 = __toESM(require("os"), 1);
|
|
11188
|
-
|
|
11177
|
+
import_node_path6 = __toESM(require("path"), 1);
|
|
11189
11178
|
init_protocol();
|
|
11190
11179
|
init_claude_history();
|
|
11191
11180
|
init_tool_result_extra();
|
|
11192
|
-
HARDCODED_DISALLOWED_TOOLS = ["Bash", "Edit", "Write", "WebFetch", "WebSearch", "Task"];
|
|
11193
11181
|
ATTACHMENT_SILENT_SUBTYPES2 = /* @__PURE__ */ new Set([
|
|
11194
11182
|
"hook_additional_context",
|
|
11195
11183
|
"hook_success",
|
|
@@ -14941,7 +14929,7 @@ var require_websocket_server = __commonJS({
|
|
|
14941
14929
|
// src/run-case/recorder.ts
|
|
14942
14930
|
function startRunCaseRecorder(opts) {
|
|
14943
14931
|
const now = opts.now ?? Date.now;
|
|
14944
|
-
const dir =
|
|
14932
|
+
const dir = import_node_path18.default.dirname(opts.recordPath);
|
|
14945
14933
|
let stream = null;
|
|
14946
14934
|
let closing = false;
|
|
14947
14935
|
let closedSettled = false;
|
|
@@ -14955,8 +14943,8 @@ function startRunCaseRecorder(opts) {
|
|
|
14955
14943
|
});
|
|
14956
14944
|
const ensureStream = () => {
|
|
14957
14945
|
if (stream) return stream;
|
|
14958
|
-
|
|
14959
|
-
stream =
|
|
14946
|
+
import_node_fs19.default.mkdirSync(dir, { recursive: true });
|
|
14947
|
+
stream = import_node_fs19.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
14960
14948
|
stream.on("close", () => closedResolve());
|
|
14961
14949
|
return stream;
|
|
14962
14950
|
};
|
|
@@ -14981,12 +14969,12 @@ function startRunCaseRecorder(opts) {
|
|
|
14981
14969
|
};
|
|
14982
14970
|
return { tap, close, closed };
|
|
14983
14971
|
}
|
|
14984
|
-
var
|
|
14972
|
+
var import_node_fs19, import_node_path18;
|
|
14985
14973
|
var init_recorder = __esm({
|
|
14986
14974
|
"src/run-case/recorder.ts"() {
|
|
14987
14975
|
"use strict";
|
|
14988
|
-
|
|
14989
|
-
|
|
14976
|
+
import_node_fs19 = __toESM(require("fs"), 1);
|
|
14977
|
+
import_node_path18 = __toESM(require("path"), 1);
|
|
14990
14978
|
}
|
|
14991
14979
|
});
|
|
14992
14980
|
|
|
@@ -15029,7 +15017,7 @@ var init_wire = __esm({
|
|
|
15029
15017
|
// src/run-case/controller.ts
|
|
15030
15018
|
async function runController(opts) {
|
|
15031
15019
|
const now = opts.now ?? Date.now;
|
|
15032
|
-
const cwd = opts.cwd ?? (0,
|
|
15020
|
+
const cwd = opts.cwd ?? (0, import_node_fs20.mkdtempSync)(import_node_path19.default.join(import_node_os12.default.tmpdir(), "clawd-runcase-"));
|
|
15033
15021
|
const ownsCwd = opts.cwd === void 0;
|
|
15034
15022
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
15035
15023
|
const spawnCtx = { cwd };
|
|
@@ -15190,19 +15178,19 @@ async function runController(opts) {
|
|
|
15190
15178
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
15191
15179
|
if (ownsCwd) {
|
|
15192
15180
|
try {
|
|
15193
|
-
(0,
|
|
15181
|
+
(0, import_node_fs20.rmSync)(cwd, { recursive: true, force: true });
|
|
15194
15182
|
} catch {
|
|
15195
15183
|
}
|
|
15196
15184
|
}
|
|
15197
15185
|
return exitCode ?? 0;
|
|
15198
15186
|
}
|
|
15199
|
-
var
|
|
15187
|
+
var import_node_fs20, import_node_os12, import_node_path19;
|
|
15200
15188
|
var init_controller = __esm({
|
|
15201
15189
|
"src/run-case/controller.ts"() {
|
|
15202
15190
|
"use strict";
|
|
15203
|
-
|
|
15191
|
+
import_node_fs20 = require("fs");
|
|
15204
15192
|
import_node_os12 = __toESM(require("os"), 1);
|
|
15205
|
-
|
|
15193
|
+
import_node_path19 = __toESM(require("path"), 1);
|
|
15206
15194
|
init_claude();
|
|
15207
15195
|
init_stdout_splitter();
|
|
15208
15196
|
init_permission_stdio();
|
|
@@ -15427,8 +15415,8 @@ Env (advanced):
|
|
|
15427
15415
|
`;
|
|
15428
15416
|
|
|
15429
15417
|
// src/index.ts
|
|
15430
|
-
var
|
|
15431
|
-
var
|
|
15418
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
15419
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
15432
15420
|
|
|
15433
15421
|
// src/logger.ts
|
|
15434
15422
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -15482,7 +15470,16 @@ var SessionStore = class {
|
|
|
15482
15470
|
root;
|
|
15483
15471
|
constructor(opts) {
|
|
15484
15472
|
const agentId = opts.agentId ?? DEFAULT_AGENT_ID;
|
|
15485
|
-
|
|
15473
|
+
if (agentId !== DEFAULT_AGENT_ID) {
|
|
15474
|
+
if (!opts.personaRoot) {
|
|
15475
|
+
throw new Error(
|
|
15476
|
+
`SessionStore: personaRoot is required for non-default agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionStore for persona agents.`
|
|
15477
|
+
);
|
|
15478
|
+
}
|
|
15479
|
+
this.root = import_node_path3.default.join(opts.personaRoot, safeFileName(agentId), ".clawd", "sub-sessions");
|
|
15480
|
+
} else {
|
|
15481
|
+
this.root = import_node_path3.default.join(opts.dataDir, "sessions", agentId);
|
|
15482
|
+
}
|
|
15486
15483
|
}
|
|
15487
15484
|
filePath(sessionId) {
|
|
15488
15485
|
return import_node_path3.default.join(this.root, `${safeFileName(sessionId)}.json`);
|
|
@@ -15694,9 +15691,8 @@ function buildSpawnContext(state) {
|
|
|
15694
15691
|
effort: file.effort
|
|
15695
15692
|
};
|
|
15696
15693
|
const meta = state.subSessionMeta;
|
|
15697
|
-
if (meta?.
|
|
15698
|
-
ctx.
|
|
15699
|
-
ctx.hardcodedPermissionMode = meta.permissionMode ?? "plan";
|
|
15694
|
+
if (meta?.personaMode) {
|
|
15695
|
+
ctx.personaMode = true;
|
|
15700
15696
|
}
|
|
15701
15697
|
return ctx;
|
|
15702
15698
|
}
|
|
@@ -16266,19 +16262,6 @@ function startRecorder(opts) {
|
|
|
16266
16262
|
};
|
|
16267
16263
|
}
|
|
16268
16264
|
|
|
16269
|
-
// src/tools/cwd-boundary.ts
|
|
16270
|
-
var import_node_path5 = __toESM(require("path"), 1);
|
|
16271
|
-
function isPathInsideCwd(cwd, target) {
|
|
16272
|
-
if (!import_node_path5.default.isAbsolute(target)) return false;
|
|
16273
|
-
const cwdNorm = import_node_path5.default.resolve(cwd);
|
|
16274
|
-
const targetNorm = import_node_path5.default.resolve(target);
|
|
16275
|
-
if (cwdNorm === targetNorm) return true;
|
|
16276
|
-
const rel = import_node_path5.default.relative(cwdNorm, targetNorm);
|
|
16277
|
-
if (rel.startsWith("..")) return false;
|
|
16278
|
-
if (import_node_path5.default.isAbsolute(rel)) return false;
|
|
16279
|
-
return true;
|
|
16280
|
-
}
|
|
16281
|
-
|
|
16282
16265
|
// src/session/runner.ts
|
|
16283
16266
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
16284
16267
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -16296,15 +16279,6 @@ function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
|
16296
16279
|
return JSON.stringify(payload) + "\n";
|
|
16297
16280
|
}
|
|
16298
16281
|
var DEFAULT_WAIT_STOP_TIMEOUT_MS = 3e3;
|
|
16299
|
-
function extractToolPath(ev) {
|
|
16300
|
-
const input = ev.input;
|
|
16301
|
-
if (!input || typeof input !== "object") return void 0;
|
|
16302
|
-
const inp = input;
|
|
16303
|
-
if (ev.tool === "Read" && typeof inp.file_path === "string") return inp.file_path;
|
|
16304
|
-
if (ev.tool === "Grep" && typeof inp.path === "string") return inp.path;
|
|
16305
|
-
if (ev.tool === "Glob" && typeof inp.path === "string") return inp.path;
|
|
16306
|
-
return void 0;
|
|
16307
|
-
}
|
|
16308
16282
|
var SessionRunner = class {
|
|
16309
16283
|
constructor(initial, hooks) {
|
|
16310
16284
|
this.hooks = hooks;
|
|
@@ -16420,62 +16394,6 @@ var SessionRunner = class {
|
|
|
16420
16394
|
}
|
|
16421
16395
|
});
|
|
16422
16396
|
}
|
|
16423
|
-
// L1 锁定(task 14)拦截:仅 sub-session(state.subSessionMeta.toolAllowlist 非空)启用。
|
|
16424
|
-
// 1. 解析 line 为 ParsedEvent[],扫 'tool_call' kind
|
|
16425
|
-
// 2. tool 名不在白名单 → emit session:event(kind='error') + SIGKILL,丢弃本行
|
|
16426
|
-
// 3. tool input 里带 path 字段(Read.file_path / Grep.path / Glob.path)越出 cwd 子树 → 同上处理
|
|
16427
|
-
// 命中返回 true,调用方不再喂 reducer;命中即 SIGKILL,CC 进程会触发 proc.on('exit')
|
|
16428
|
-
// 走正常的 stop / proc-exit 流程。本拦截层与 buildSpawnArgs 的 --disallowed-tools / --add-dir
|
|
16429
|
-
// 共同构成 L1 第二 / 第三层防御(schema 层 + manager 层 + claude CLI 层 + runner 拦截层)
|
|
16430
|
-
tryInterceptL1Violation(line) {
|
|
16431
|
-
const meta = this.state.subSessionMeta;
|
|
16432
|
-
if (!meta?.toolAllowlist || meta.toolAllowlist.length === 0) return false;
|
|
16433
|
-
const allowed = new Set(meta.toolAllowlist);
|
|
16434
|
-
let events;
|
|
16435
|
-
try {
|
|
16436
|
-
events = this.hooks.adapter.parseLine(line);
|
|
16437
|
-
} catch {
|
|
16438
|
-
return false;
|
|
16439
|
-
}
|
|
16440
|
-
if (events.length === 0) return false;
|
|
16441
|
-
const cwd = this.state.file.cwd;
|
|
16442
|
-
for (const ev of events) {
|
|
16443
|
-
if (ev.kind !== "tool_call") continue;
|
|
16444
|
-
if (typeof ev.tool === "string" && ev.tool && !allowed.has(ev.tool)) {
|
|
16445
|
-
this.emitL1Error(`tool ${ev.tool} blocked by L1 lockdown`, "TOOL_NOT_ALLOWED");
|
|
16446
|
-
this.doKill("SIGKILL");
|
|
16447
|
-
return true;
|
|
16448
|
-
}
|
|
16449
|
-
const argPath = extractToolPath(ev);
|
|
16450
|
-
if (argPath && !isPathInsideCwd(cwd, argPath)) {
|
|
16451
|
-
this.emitL1Error(
|
|
16452
|
-
`path ${argPath} outside cwd ${cwd}`,
|
|
16453
|
-
"PATH_OUT_OF_BOUND"
|
|
16454
|
-
);
|
|
16455
|
-
this.doKill("SIGKILL");
|
|
16456
|
-
return true;
|
|
16457
|
-
}
|
|
16458
|
-
}
|
|
16459
|
-
return false;
|
|
16460
|
-
}
|
|
16461
|
-
// L1 违规错误帧:走 session:event 通道,code 编码进 ParsedEvent.error message。
|
|
16462
|
-
// 不引入新的 wire 帧 type(避免 protocol 改动),现有 error kind 已经走 broadcast 路径
|
|
16463
|
-
emitL1Error(message, code) {
|
|
16464
|
-
const errEvent = {
|
|
16465
|
-
kind: "error",
|
|
16466
|
-
message: `[${code}] ${message}`
|
|
16467
|
-
};
|
|
16468
|
-
const frame = {
|
|
16469
|
-
type: "session:event",
|
|
16470
|
-
sessionId: this.state.file.sessionId,
|
|
16471
|
-
event: errEvent
|
|
16472
|
-
};
|
|
16473
|
-
try {
|
|
16474
|
-
this.hooks.broadcastFrame(frame, "broadcast");
|
|
16475
|
-
} catch {
|
|
16476
|
-
}
|
|
16477
|
-
this.hooks.logger?.warn("clawd-l1-violation", { code, message, sessionId: this.state.file.sessionId });
|
|
16478
|
-
}
|
|
16479
16397
|
// 尝试把一行 stdout 解析成 `type:"control_response"` 帧并 resolve 匹配的 pending。
|
|
16480
16398
|
// 命中返回 true —— 调用方不再把该行喂给 reducer(control_response 不是会话事件)。
|
|
16481
16399
|
tryHandleControlResponse(line) {
|
|
@@ -16598,7 +16516,6 @@ var SessionRunner = class {
|
|
|
16598
16516
|
this.stdoutBuf = newBuf;
|
|
16599
16517
|
for (const line of lines) {
|
|
16600
16518
|
if (this.tryHandleControlResponse(line)) continue;
|
|
16601
|
-
if (this.tryInterceptL1Violation(line)) continue;
|
|
16602
16519
|
this.input({ kind: "stdout-line", line });
|
|
16603
16520
|
}
|
|
16604
16521
|
});
|
|
@@ -16730,15 +16647,21 @@ var SessionManager = class {
|
|
|
16730
16647
|
// 仅推 reducer 产出的 'session:event' 帧里的 ParsedEvent,其他帧(status / info / cleared)
|
|
16731
16648
|
// 由调用方按需自行处理(persona-bound 简化协议只暴露 event 流,不需要这些)
|
|
16732
16649
|
eventSubscribers = /* @__PURE__ */ new Map();
|
|
16733
|
-
// 按 agentId 拿对应的 SessionStore;persona
|
|
16734
|
-
//
|
|
16650
|
+
// 按 agentId 拿对应的 SessionStore;persona-* agentId 使用 personaRoot 路径。
|
|
16651
|
+
// 'default' 直接复用 deps.store;其它 agentId 第一次访问时按需创建并缓存。
|
|
16652
|
+
// personaRoot 必须与 PersonaStore 同源,两者共享相同的 persona 目录层级
|
|
16735
16653
|
storeFor(agentId) {
|
|
16736
16654
|
const cached = this.storesByAgent.get(agentId);
|
|
16737
16655
|
if (cached) return cached;
|
|
16738
16656
|
if (!this.deps.dataDir) {
|
|
16739
16657
|
throw new Error(`SessionManager: dataDir required to route agentId='${agentId}'`);
|
|
16740
16658
|
}
|
|
16741
|
-
|
|
16659
|
+
if (!this.deps.personaRoot) {
|
|
16660
|
+
throw new Error(
|
|
16661
|
+
`SessionManager: personaRoot is required to route agentId='${agentId}'. Bootstrap must wire personaRoot when constructing SessionManager for persona sub-sessions.`
|
|
16662
|
+
);
|
|
16663
|
+
}
|
|
16664
|
+
const st = new SessionStore({ dataDir: this.deps.dataDir, agentId, personaRoot: this.deps.personaRoot });
|
|
16742
16665
|
this.storesByAgent.set(agentId, st);
|
|
16743
16666
|
return st;
|
|
16744
16667
|
}
|
|
@@ -17243,7 +17166,7 @@ var SessionManager = class {
|
|
|
17243
17166
|
//
|
|
17244
17167
|
// PersonaManager 是 SessionManager 之上的薄编排层,sub-session 的持久化(SessionFile)
|
|
17245
17168
|
// 仍由 SessionManager 持有。区别于普通 session:
|
|
17246
|
-
// - SessionFile 落到 sessions
|
|
17169
|
+
// - SessionFile 落到 <personaRoot>/<personaId>/.clawd/sub-sessions/ 而非 sessions/default/
|
|
17247
17170
|
// - reducer state.subSessionMeta.idleKillEnabled = true(turn_end 自动 idle-kill)
|
|
17248
17171
|
// - sessionId 由 PersonaManager 派生(personaId-<tokenHash>),不走自动 newSessionId
|
|
17249
17172
|
/** 按 agentId 读取 SessionFile;不存在返回 null */
|
|
@@ -17287,15 +17210,8 @@ var SessionManager = class {
|
|
|
17287
17210
|
updatedAt: iso
|
|
17288
17211
|
};
|
|
17289
17212
|
const written = store.write(file);
|
|
17290
|
-
if (args.subSessionMeta
|
|
17291
|
-
|
|
17292
|
-
idleKillEnabled: args.subSessionMeta?.idleKillEnabled ?? false,
|
|
17293
|
-
...args.hardcodedToolAllowlist && args.hardcodedToolAllowlist.length > 0 ? {
|
|
17294
|
-
toolAllowlist: args.hardcodedToolAllowlist,
|
|
17295
|
-
permissionMode: args.permissionMode
|
|
17296
|
-
} : {}
|
|
17297
|
-
};
|
|
17298
|
-
this.subSessionMetaBySid.set(args.sessionId, meta);
|
|
17213
|
+
if (args.subSessionMeta) {
|
|
17214
|
+
this.subSessionMetaBySid.set(args.sessionId, args.subSessionMeta);
|
|
17299
17215
|
}
|
|
17300
17216
|
return written;
|
|
17301
17217
|
}
|
|
@@ -17482,59 +17398,89 @@ var SessionManager = class {
|
|
|
17482
17398
|
};
|
|
17483
17399
|
|
|
17484
17400
|
// src/persona/store.ts
|
|
17485
|
-
var
|
|
17486
|
-
var
|
|
17401
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
17402
|
+
var path5 = __toESM(require("path"), 1);
|
|
17487
17403
|
init_protocol();
|
|
17404
|
+
var DEFAULT_SETTINGS = {
|
|
17405
|
+
permissions: {
|
|
17406
|
+
// silent-deny for tools accessing outside cwd — no permission prompt shown to persona
|
|
17407
|
+
defaultMode: "dontAsk"
|
|
17408
|
+
},
|
|
17409
|
+
sandbox: {
|
|
17410
|
+
enabled: true,
|
|
17411
|
+
// sandboxed Bash auto-runs without prompting the user
|
|
17412
|
+
autoAllowBashIfSandboxed: true,
|
|
17413
|
+
// prevents CC from retrying denied commands with dangerouslyDisableSandbox: true
|
|
17414
|
+
allowUnsandboxedCommands: false,
|
|
17415
|
+
filesystem: {
|
|
17416
|
+
// deny home dir explicitly; default sandbox allows all reads, only limits writes to cwd
|
|
17417
|
+
denyRead: ["~/"],
|
|
17418
|
+
allowRead: ["."],
|
|
17419
|
+
denyWrite: ["~/"],
|
|
17420
|
+
allowWrite: ["."]
|
|
17421
|
+
}
|
|
17422
|
+
}
|
|
17423
|
+
};
|
|
17488
17424
|
var PersonaStore = class {
|
|
17425
|
+
constructor(root) {
|
|
17426
|
+
this.root = root;
|
|
17427
|
+
fs6.mkdirSync(root, { recursive: true });
|
|
17428
|
+
}
|
|
17489
17429
|
root;
|
|
17490
|
-
|
|
17491
|
-
|
|
17430
|
+
personaDir(personaId) {
|
|
17431
|
+
return path5.join(this.root, safeFileName(personaId));
|
|
17492
17432
|
}
|
|
17493
|
-
|
|
17494
|
-
return
|
|
17433
|
+
metaPath(personaId) {
|
|
17434
|
+
return path5.join(this.personaDir(personaId), ".clawd", "persona.json");
|
|
17495
17435
|
}
|
|
17496
|
-
|
|
17497
|
-
|
|
17436
|
+
claudeMdPath(personaId) {
|
|
17437
|
+
return path5.join(this.personaDir(personaId), "CLAUDE.md");
|
|
17498
17438
|
}
|
|
17499
|
-
|
|
17500
|
-
|
|
17501
|
-
const raw = import_node_fs6.default.readFileSync(this.filePath(personaId), "utf8");
|
|
17502
|
-
return PersonaFileSchema.parse(JSON.parse(raw));
|
|
17503
|
-
} catch (err) {
|
|
17504
|
-
const code = err?.code;
|
|
17505
|
-
if (code === "ENOENT") return null;
|
|
17506
|
-
return null;
|
|
17507
|
-
}
|
|
17439
|
+
settingsPath(personaId) {
|
|
17440
|
+
return path5.join(this.personaDir(personaId), ".claude", "settings.json");
|
|
17508
17441
|
}
|
|
17509
|
-
write(
|
|
17510
|
-
const
|
|
17511
|
-
|
|
17512
|
-
|
|
17513
|
-
|
|
17514
|
-
|
|
17515
|
-
|
|
17516
|
-
return validated;
|
|
17442
|
+
write(persona, personality) {
|
|
17443
|
+
const dir = this.personaDir(persona.personaId);
|
|
17444
|
+
fs6.mkdirSync(path5.join(dir, ".claude"), { recursive: true });
|
|
17445
|
+
fs6.mkdirSync(path5.join(dir, ".clawd"), { recursive: true });
|
|
17446
|
+
this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
|
|
17447
|
+
this.atomicWrite(this.settingsPath(persona.personaId), JSON.stringify(DEFAULT_SETTINGS, null, 2));
|
|
17448
|
+
this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
|
|
17517
17449
|
}
|
|
17518
|
-
|
|
17519
|
-
|
|
17520
|
-
|
|
17521
|
-
|
|
17522
|
-
|
|
17523
|
-
|
|
17524
|
-
|
|
17450
|
+
writePersonality(personaId, personality) {
|
|
17451
|
+
this.atomicWrite(this.claudeMdPath(personaId), personality);
|
|
17452
|
+
}
|
|
17453
|
+
writeMeta(persona) {
|
|
17454
|
+
this.atomicWrite(this.metaPath(persona.personaId), JSON.stringify(persona, null, 2));
|
|
17455
|
+
}
|
|
17456
|
+
read(personaId) {
|
|
17457
|
+
const p = this.metaPath(personaId);
|
|
17458
|
+
if (!fs6.existsSync(p)) return null;
|
|
17459
|
+
const raw = JSON.parse(fs6.readFileSync(p, "utf8"));
|
|
17460
|
+
return PersonaFileSchema.parse(raw);
|
|
17461
|
+
}
|
|
17462
|
+
readPersonality(personaId) {
|
|
17463
|
+
const p = this.claudeMdPath(personaId);
|
|
17464
|
+
if (!fs6.existsSync(p)) return null;
|
|
17465
|
+
return fs6.readFileSync(p, "utf8");
|
|
17525
17466
|
}
|
|
17526
17467
|
list() {
|
|
17527
|
-
if (!
|
|
17528
|
-
|
|
17529
|
-
|
|
17530
|
-
|
|
17531
|
-
|
|
17532
|
-
|
|
17533
|
-
|
|
17534
|
-
|
|
17535
|
-
|
|
17536
|
-
|
|
17537
|
-
return
|
|
17468
|
+
if (!fs6.existsSync(this.root)) return [];
|
|
17469
|
+
return fs6.readdirSync(this.root).filter((name) => {
|
|
17470
|
+
return fs6.existsSync(path5.join(this.root, name, ".clawd", "persona.json"));
|
|
17471
|
+
});
|
|
17472
|
+
}
|
|
17473
|
+
remove(personaId) {
|
|
17474
|
+
const dir = this.personaDir(personaId);
|
|
17475
|
+
if (fs6.existsSync(dir)) fs6.rmSync(dir, { recursive: true, force: true });
|
|
17476
|
+
}
|
|
17477
|
+
personaDirPath(personaId) {
|
|
17478
|
+
return this.personaDir(personaId);
|
|
17479
|
+
}
|
|
17480
|
+
atomicWrite(file, content) {
|
|
17481
|
+
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
17482
|
+
fs6.writeFileSync(tmp, content, { mode: 384 });
|
|
17483
|
+
fs6.renameSync(tmp, file);
|
|
17538
17484
|
}
|
|
17539
17485
|
};
|
|
17540
17486
|
|
|
@@ -17549,7 +17495,10 @@ var PersonaRegistry = class {
|
|
|
17549
17495
|
/** 从 store 全量重建缓存(boot 时 + 测试 setup 时) */
|
|
17550
17496
|
reload() {
|
|
17551
17497
|
this.cache.clear();
|
|
17552
|
-
for (const
|
|
17498
|
+
for (const id of this.store.list()) {
|
|
17499
|
+
const p = this.store.read(id);
|
|
17500
|
+
if (p) this.cache.set(p.personaId, p);
|
|
17501
|
+
}
|
|
17553
17502
|
}
|
|
17554
17503
|
get(personaId) {
|
|
17555
17504
|
return this.cache.get(personaId);
|
|
@@ -17577,8 +17526,6 @@ var PersonaRegistry = class {
|
|
|
17577
17526
|
|
|
17578
17527
|
// src/persona/manager.ts
|
|
17579
17528
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
17580
|
-
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
17581
|
-
var import_node_path7 = __toESM(require("path"), 1);
|
|
17582
17529
|
var PersonaManager = class {
|
|
17583
17530
|
constructor(deps) {
|
|
17584
17531
|
this.deps = deps;
|
|
@@ -17586,49 +17533,45 @@ var PersonaManager = class {
|
|
|
17586
17533
|
deps;
|
|
17587
17534
|
create(args) {
|
|
17588
17535
|
const personaId = this.generatePersonaId(args.label);
|
|
17589
|
-
const
|
|
17590
|
-
const
|
|
17536
|
+
const now = Date.now();
|
|
17537
|
+
const persona = {
|
|
17591
17538
|
personaId,
|
|
17592
17539
|
label: args.label,
|
|
17593
|
-
cwd: args.cwd,
|
|
17594
17540
|
model: args.model,
|
|
17595
|
-
|
|
17596
|
-
// L1 锁死:plan 模式 + 只读三件套
|
|
17597
|
-
permissionMode: "plan",
|
|
17598
|
-
toolAllowlist: ["Read", "Grep", "Glob"],
|
|
17599
|
-
public: true,
|
|
17541
|
+
public: args.public ?? false,
|
|
17600
17542
|
tokenMap: {},
|
|
17601
|
-
createdAt:
|
|
17602
|
-
updatedAt:
|
|
17543
|
+
createdAt: now,
|
|
17544
|
+
updatedAt: now
|
|
17603
17545
|
};
|
|
17604
|
-
|
|
17605
|
-
this.deps.registry.set(
|
|
17606
|
-
return
|
|
17546
|
+
this.deps.store.write(persona, args.personality);
|
|
17547
|
+
this.deps.registry.set(persona);
|
|
17548
|
+
return persona;
|
|
17607
17549
|
}
|
|
17608
|
-
update(personaId, patch) {
|
|
17550
|
+
update(personaId, patch, personality) {
|
|
17609
17551
|
const existing = this.deps.registry.get(personaId);
|
|
17610
17552
|
if (!existing) throw new Error(`persona not found: ${personaId}`);
|
|
17611
17553
|
const updated = {
|
|
17612
17554
|
...existing,
|
|
17613
17555
|
...patch,
|
|
17614
|
-
updatedAt:
|
|
17556
|
+
updatedAt: Date.now()
|
|
17615
17557
|
};
|
|
17616
|
-
|
|
17617
|
-
|
|
17618
|
-
|
|
17558
|
+
if (personality !== void 0) {
|
|
17559
|
+
this.deps.store.write(updated, personality);
|
|
17560
|
+
} else {
|
|
17561
|
+
this.deps.store.writeMeta(updated);
|
|
17562
|
+
}
|
|
17563
|
+
this.deps.registry.set(updated);
|
|
17564
|
+
return updated;
|
|
17619
17565
|
}
|
|
17620
|
-
/**
|
|
17566
|
+
/**
|
|
17567
|
+
* 删除 persona。
|
|
17568
|
+
* PersonaStore.remove(personaId) 已级联删除整个 <personaRoot>/<personaId>/ 目录,
|
|
17569
|
+
* 其中包含 .clawd/sub-sessions/——无需额外清理。
|
|
17570
|
+
* 旧的 <dataDir>/sessions/<personaId>/ 路径已废弃,不再维护。
|
|
17571
|
+
*/
|
|
17621
17572
|
delete(personaId) {
|
|
17622
|
-
this.deps.store.
|
|
17573
|
+
this.deps.store.remove(personaId);
|
|
17623
17574
|
this.deps.registry.remove(personaId);
|
|
17624
|
-
const dir = import_node_path7.default.join(this.deps.dataDir, "sessions", personaId);
|
|
17625
|
-
try {
|
|
17626
|
-
import_node_fs7.default.rmSync(dir, { recursive: true, force: true });
|
|
17627
|
-
} catch (err) {
|
|
17628
|
-
this.deps.logger.warn(`PersonaManager.delete: cleanup ${dir} failed`, {
|
|
17629
|
-
err: err.message
|
|
17630
|
-
});
|
|
17631
|
-
}
|
|
17632
17575
|
}
|
|
17633
17576
|
/** 生成 32-char base64url token(24 bytes 随机),label 必填 */
|
|
17634
17577
|
issueToken(personaId, label) {
|
|
@@ -17637,16 +17580,17 @@ var PersonaManager = class {
|
|
|
17637
17580
|
const token = import_node_crypto3.default.randomBytes(24).toString("base64url");
|
|
17638
17581
|
const entry = {
|
|
17639
17582
|
label,
|
|
17640
|
-
issuedAt:
|
|
17583
|
+
issuedAt: Date.now(),
|
|
17584
|
+
revoked: false
|
|
17641
17585
|
};
|
|
17642
17586
|
const updated = {
|
|
17643
17587
|
...existing,
|
|
17644
17588
|
tokenMap: { ...existing.tokenMap, [token]: entry },
|
|
17645
|
-
updatedAt:
|
|
17589
|
+
updatedAt: Date.now()
|
|
17646
17590
|
};
|
|
17647
|
-
|
|
17648
|
-
this.deps.registry.set(
|
|
17649
|
-
return { token, persona:
|
|
17591
|
+
this.deps.store.writeMeta(updated);
|
|
17592
|
+
this.deps.registry.set(updated);
|
|
17593
|
+
return { token, persona: updated };
|
|
17650
17594
|
}
|
|
17651
17595
|
revokeToken(personaId, token) {
|
|
17652
17596
|
const existing = this.deps.registry.get(personaId);
|
|
@@ -17659,16 +17603,17 @@ var PersonaManager = class {
|
|
|
17659
17603
|
...existing.tokenMap,
|
|
17660
17604
|
[token]: { ...tokenEntry, revoked: true }
|
|
17661
17605
|
},
|
|
17662
|
-
updatedAt:
|
|
17606
|
+
updatedAt: Date.now()
|
|
17663
17607
|
};
|
|
17664
|
-
|
|
17665
|
-
this.deps.registry.set(
|
|
17666
|
-
return
|
|
17608
|
+
this.deps.store.writeMeta(updated);
|
|
17609
|
+
this.deps.registry.set(updated);
|
|
17610
|
+
return updated;
|
|
17667
17611
|
}
|
|
17668
17612
|
/**
|
|
17669
17613
|
* 拿到(或按需创建)该 token 对应的 sub-session。subSessionId 由 personaId + token 哈希派生
|
|
17670
17614
|
* 保证 idempotent:同一 token 永远复用同一个 sub-session。
|
|
17671
|
-
* 创建路径:开启 idleKillEnabled,cwd
|
|
17615
|
+
* 创建路径:开启 idleKillEnabled,cwd 取 persona 目录,不再硬编码 permission mode / tool allowlist
|
|
17616
|
+
* (sandbox 约束移到 persona dir 下的 .claude/settings.json,由 OS-level Seatbelt 执行)
|
|
17672
17617
|
*/
|
|
17673
17618
|
getOrCreateSubSession(personaId, token) {
|
|
17674
17619
|
const persona = this.deps.registry.get(personaId);
|
|
@@ -17683,16 +17628,11 @@ var PersonaManager = class {
|
|
|
17683
17628
|
const sessionFile = this.deps.sessionManager.createForAgent({
|
|
17684
17629
|
sessionId: subSessionId,
|
|
17685
17630
|
agentId: personaId,
|
|
17686
|
-
cwd:
|
|
17631
|
+
cwd: this.deps.store.personaDirPath(personaId),
|
|
17687
17632
|
tool: "claude",
|
|
17688
17633
|
label: subLabel,
|
|
17689
17634
|
model: persona.model,
|
|
17690
|
-
|
|
17691
|
-
// L1 锁定(task 14):把 PersonaFile.toolAllowlist 透传到 SessionManager,
|
|
17692
|
-
// 最终在 buildSpawnArgs 拼成 --add-dir + --disallowed-tools,runner stdout 拦截层
|
|
17693
|
-
// 也读 SubSessionMeta.toolAllowlist 做工具名 / cwd 越界拦截
|
|
17694
|
-
hardcodedToolAllowlist: persona.toolAllowlist,
|
|
17695
|
-
subSessionMeta: { idleKillEnabled: true }
|
|
17635
|
+
subSessionMeta: { idleKillEnabled: true, personaMode: true }
|
|
17696
17636
|
});
|
|
17697
17637
|
return { sessionFile, isNew: true };
|
|
17698
17638
|
}
|
|
@@ -17726,23 +17666,23 @@ init_claude();
|
|
|
17726
17666
|
init_claude_history();
|
|
17727
17667
|
|
|
17728
17668
|
// src/workspace/browser.ts
|
|
17729
|
-
var
|
|
17669
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
17730
17670
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
17731
|
-
var
|
|
17671
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
17732
17672
|
init_protocol();
|
|
17733
17673
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
17734
17674
|
function resolveInsideCwd(cwd, subpath) {
|
|
17735
|
-
const absCwd =
|
|
17736
|
-
const joined =
|
|
17737
|
-
const rel =
|
|
17738
|
-
if (rel.startsWith("..") ||
|
|
17675
|
+
const absCwd = import_node_path7.default.resolve(cwd);
|
|
17676
|
+
const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
|
|
17677
|
+
const rel = import_node_path7.default.relative(absCwd, joined);
|
|
17678
|
+
if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
|
|
17739
17679
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
17740
17680
|
}
|
|
17741
17681
|
return joined;
|
|
17742
17682
|
}
|
|
17743
17683
|
function ensureCwd(cwd) {
|
|
17744
17684
|
try {
|
|
17745
|
-
const stat =
|
|
17685
|
+
const stat = import_node_fs8.default.statSync(cwd);
|
|
17746
17686
|
if (!stat.isDirectory()) {
|
|
17747
17687
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
17748
17688
|
}
|
|
@@ -17756,7 +17696,7 @@ var WorkspaceBrowser = class {
|
|
|
17756
17696
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
|
|
17757
17697
|
ensureCwd(cwd);
|
|
17758
17698
|
const full = resolveInsideCwd(cwd, args.path);
|
|
17759
|
-
const dirents =
|
|
17699
|
+
const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
|
|
17760
17700
|
const entries = [];
|
|
17761
17701
|
for (const d of dirents) {
|
|
17762
17702
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -17766,7 +17706,7 @@ var WorkspaceBrowser = class {
|
|
|
17766
17706
|
mtime: ""
|
|
17767
17707
|
};
|
|
17768
17708
|
try {
|
|
17769
|
-
const st =
|
|
17709
|
+
const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
|
|
17770
17710
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
17771
17711
|
if (d.isFile()) entry.size = st.size;
|
|
17772
17712
|
} catch {
|
|
@@ -17782,14 +17722,14 @@ var WorkspaceBrowser = class {
|
|
|
17782
17722
|
read(args) {
|
|
17783
17723
|
ensureCwd(args.cwd);
|
|
17784
17724
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
17785
|
-
const st =
|
|
17725
|
+
const st = import_node_fs8.default.statSync(full);
|
|
17786
17726
|
if (!st.isFile()) {
|
|
17787
17727
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
17788
17728
|
}
|
|
17789
17729
|
if (st.size > MAX_FILE_BYTES) {
|
|
17790
17730
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
17791
17731
|
}
|
|
17792
|
-
const buf =
|
|
17732
|
+
const buf = import_node_fs8.default.readFileSync(full);
|
|
17793
17733
|
const isBinary = buf.includes(0);
|
|
17794
17734
|
if (isBinary) {
|
|
17795
17735
|
return {
|
|
@@ -17811,9 +17751,9 @@ var WorkspaceBrowser = class {
|
|
|
17811
17751
|
};
|
|
17812
17752
|
|
|
17813
17753
|
// src/skills/scanner.ts
|
|
17814
|
-
var
|
|
17754
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
17815
17755
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
17816
|
-
var
|
|
17756
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
17817
17757
|
function parseFrontmatter(content) {
|
|
17818
17758
|
if (!content.startsWith("---")) return { name: "", description: "" };
|
|
17819
17759
|
const end = content.indexOf("---", 3);
|
|
@@ -17849,7 +17789,7 @@ function parseFrontmatter(content) {
|
|
|
17849
17789
|
}
|
|
17850
17790
|
function isDirLikeSync(p) {
|
|
17851
17791
|
try {
|
|
17852
|
-
return
|
|
17792
|
+
return import_node_fs9.default.statSync(p).isDirectory();
|
|
17853
17793
|
} catch {
|
|
17854
17794
|
return false;
|
|
17855
17795
|
}
|
|
@@ -17857,19 +17797,19 @@ function isDirLikeSync(p) {
|
|
|
17857
17797
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
17858
17798
|
let entries;
|
|
17859
17799
|
try {
|
|
17860
|
-
entries =
|
|
17800
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
17861
17801
|
} catch {
|
|
17862
17802
|
return;
|
|
17863
17803
|
}
|
|
17864
17804
|
for (const ent of entries) {
|
|
17865
|
-
const entryPath =
|
|
17805
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
17866
17806
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
17867
17807
|
let content;
|
|
17868
17808
|
try {
|
|
17869
|
-
content =
|
|
17809
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
17870
17810
|
} catch {
|
|
17871
17811
|
try {
|
|
17872
|
-
content =
|
|
17812
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
17873
17813
|
} catch {
|
|
17874
17814
|
continue;
|
|
17875
17815
|
}
|
|
@@ -17887,26 +17827,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
17887
17827
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
17888
17828
|
let entries;
|
|
17889
17829
|
try {
|
|
17890
|
-
entries =
|
|
17830
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
17891
17831
|
} catch {
|
|
17892
17832
|
return;
|
|
17893
17833
|
}
|
|
17894
17834
|
for (const ent of entries) {
|
|
17895
|
-
const entryPath =
|
|
17835
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
17896
17836
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
17897
17837
|
const ns = ent.name;
|
|
17898
17838
|
let subEntries;
|
|
17899
17839
|
try {
|
|
17900
|
-
subEntries =
|
|
17840
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
17901
17841
|
} catch {
|
|
17902
17842
|
continue;
|
|
17903
17843
|
}
|
|
17904
17844
|
for (const se of subEntries) {
|
|
17905
17845
|
if (!se.name.endsWith(".md")) continue;
|
|
17906
|
-
const sePath =
|
|
17846
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
17907
17847
|
let content;
|
|
17908
17848
|
try {
|
|
17909
|
-
content =
|
|
17849
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
17910
17850
|
} catch {
|
|
17911
17851
|
continue;
|
|
17912
17852
|
}
|
|
@@ -17923,7 +17863,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
17923
17863
|
} else if (ent.name.endsWith(".md")) {
|
|
17924
17864
|
let content;
|
|
17925
17865
|
try {
|
|
17926
|
-
content =
|
|
17866
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
17927
17867
|
} catch {
|
|
17928
17868
|
continue;
|
|
17929
17869
|
}
|
|
@@ -17939,10 +17879,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
17939
17879
|
}
|
|
17940
17880
|
}
|
|
17941
17881
|
function readInstalledPlugins(home) {
|
|
17942
|
-
const file =
|
|
17882
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
17943
17883
|
let raw;
|
|
17944
17884
|
try {
|
|
17945
|
-
raw =
|
|
17885
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
17946
17886
|
} catch {
|
|
17947
17887
|
return [];
|
|
17948
17888
|
}
|
|
@@ -17980,14 +17920,14 @@ var SkillsScanner = class {
|
|
|
17980
17920
|
list(args) {
|
|
17981
17921
|
const seen = /* @__PURE__ */ new Set();
|
|
17982
17922
|
const out = [];
|
|
17983
|
-
scanSkillDir(
|
|
17984
|
-
scanCommandDir(
|
|
17985
|
-
scanSkillDir(
|
|
17986
|
-
scanCommandDir(
|
|
17923
|
+
scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
|
|
17924
|
+
scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
|
|
17925
|
+
scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
|
|
17926
|
+
scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
|
|
17987
17927
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
17988
17928
|
for (const { name, root } of plugins) {
|
|
17989
|
-
scanSkillDir(
|
|
17990
|
-
scanCommandDir(
|
|
17929
|
+
scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
|
|
17930
|
+
scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
|
|
17991
17931
|
}
|
|
17992
17932
|
out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
17993
17933
|
return out;
|
|
@@ -17995,9 +17935,9 @@ var SkillsScanner = class {
|
|
|
17995
17935
|
};
|
|
17996
17936
|
|
|
17997
17937
|
// src/observer/session-observer.ts
|
|
17998
|
-
var
|
|
17938
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
17999
17939
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
18000
|
-
var
|
|
17940
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
18001
17941
|
init_claude_history();
|
|
18002
17942
|
var SessionObserver = class {
|
|
18003
17943
|
constructor(opts) {
|
|
@@ -18009,14 +17949,14 @@ var SessionObserver = class {
|
|
|
18009
17949
|
watches = /* @__PURE__ */ new Map();
|
|
18010
17950
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
18011
17951
|
if (override) return override;
|
|
18012
|
-
return
|
|
17952
|
+
return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
18013
17953
|
}
|
|
18014
17954
|
start(args) {
|
|
18015
17955
|
this.stop(args.sessionId);
|
|
18016
17956
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
18017
17957
|
let size = 0;
|
|
18018
17958
|
try {
|
|
18019
|
-
size =
|
|
17959
|
+
size = import_node_fs10.default.statSync(filePath).size;
|
|
18020
17960
|
} catch {
|
|
18021
17961
|
}
|
|
18022
17962
|
const w = {
|
|
@@ -18029,10 +17969,10 @@ var SessionObserver = class {
|
|
|
18029
17969
|
adapter: args.adapter
|
|
18030
17970
|
};
|
|
18031
17971
|
try {
|
|
18032
|
-
|
|
17972
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
|
|
18033
17973
|
} catch {
|
|
18034
17974
|
}
|
|
18035
|
-
w.watcher =
|
|
17975
|
+
w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
18036
17976
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
18037
17977
|
this.poll(w);
|
|
18038
17978
|
});
|
|
@@ -18047,7 +17987,7 @@ var SessionObserver = class {
|
|
|
18047
17987
|
// reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
|
|
18048
17988
|
hydrateMetaTail(w, maxLines = 200) {
|
|
18049
17989
|
try {
|
|
18050
|
-
const raw =
|
|
17990
|
+
const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
|
|
18051
17991
|
if (!raw) return;
|
|
18052
17992
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
18053
17993
|
if (allLines.length === 0) return;
|
|
@@ -18068,7 +18008,7 @@ var SessionObserver = class {
|
|
|
18068
18008
|
poll(w) {
|
|
18069
18009
|
let size = 0;
|
|
18070
18010
|
try {
|
|
18071
|
-
size =
|
|
18011
|
+
size = import_node_fs10.default.statSync(w.filePath).size;
|
|
18072
18012
|
} catch {
|
|
18073
18013
|
return;
|
|
18074
18014
|
}
|
|
@@ -18077,11 +18017,11 @@ var SessionObserver = class {
|
|
|
18077
18017
|
w.buf = "";
|
|
18078
18018
|
}
|
|
18079
18019
|
if (size === w.lastSize) return;
|
|
18080
|
-
const fd =
|
|
18020
|
+
const fd = import_node_fs10.default.openSync(w.filePath, "r");
|
|
18081
18021
|
try {
|
|
18082
18022
|
const len = size - w.lastSize;
|
|
18083
18023
|
const buf = Buffer.alloc(len);
|
|
18084
|
-
|
|
18024
|
+
import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
|
|
18085
18025
|
w.lastSize = size;
|
|
18086
18026
|
w.buf += buf.toString("utf8");
|
|
18087
18027
|
let newlineIndex;
|
|
@@ -18095,7 +18035,7 @@ var SessionObserver = class {
|
|
|
18095
18035
|
this.maybeReportUserMessage(w.sessionId, line);
|
|
18096
18036
|
}
|
|
18097
18037
|
} finally {
|
|
18098
|
-
|
|
18038
|
+
import_node_fs10.default.closeSync(fd);
|
|
18099
18039
|
}
|
|
18100
18040
|
}
|
|
18101
18041
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -18519,7 +18459,7 @@ var PersonaBoundHandler = class {
|
|
|
18519
18459
|
kind: "persona-ready",
|
|
18520
18460
|
subSessionId: subSessionFile.sessionId,
|
|
18521
18461
|
personaLabel: persona.label,
|
|
18522
|
-
cwd:
|
|
18462
|
+
cwd: this.deps.personaStore.personaDirPath(personaId),
|
|
18523
18463
|
model: persona.model
|
|
18524
18464
|
});
|
|
18525
18465
|
unsubscribe = this.deps.sessionManager.subscribe(
|
|
@@ -18683,10 +18623,10 @@ function isLocalhost(addr) {
|
|
|
18683
18623
|
}
|
|
18684
18624
|
|
|
18685
18625
|
// src/discovery/state-file.ts
|
|
18686
|
-
var
|
|
18687
|
-
var
|
|
18626
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
18627
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
18688
18628
|
function defaultStateFilePath(dataDir) {
|
|
18689
|
-
return
|
|
18629
|
+
return import_node_path10.default.join(dataDir, "state.json");
|
|
18690
18630
|
}
|
|
18691
18631
|
function isPidAlive(pid) {
|
|
18692
18632
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -18708,7 +18648,7 @@ var StateFileManager = class {
|
|
|
18708
18648
|
}
|
|
18709
18649
|
read() {
|
|
18710
18650
|
try {
|
|
18711
|
-
const raw =
|
|
18651
|
+
const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
|
|
18712
18652
|
const parsed = JSON.parse(raw);
|
|
18713
18653
|
return parsed;
|
|
18714
18654
|
} catch {
|
|
@@ -18722,34 +18662,34 @@ var StateFileManager = class {
|
|
|
18722
18662
|
return { status: "stale", existing };
|
|
18723
18663
|
}
|
|
18724
18664
|
write(state) {
|
|
18725
|
-
|
|
18665
|
+
import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
|
|
18726
18666
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
18727
|
-
|
|
18728
|
-
|
|
18667
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
18668
|
+
import_node_fs11.default.renameSync(tmp, this.file);
|
|
18729
18669
|
if (process.platform !== "win32") {
|
|
18730
18670
|
try {
|
|
18731
|
-
|
|
18671
|
+
import_node_fs11.default.chmodSync(this.file, 384);
|
|
18732
18672
|
} catch {
|
|
18733
18673
|
}
|
|
18734
18674
|
}
|
|
18735
18675
|
}
|
|
18736
18676
|
delete() {
|
|
18737
18677
|
try {
|
|
18738
|
-
|
|
18678
|
+
import_node_fs11.default.unlinkSync(this.file);
|
|
18739
18679
|
} catch {
|
|
18740
18680
|
}
|
|
18741
18681
|
}
|
|
18742
18682
|
};
|
|
18743
18683
|
|
|
18744
18684
|
// src/tunnel/tunnel-manager.ts
|
|
18745
|
-
var
|
|
18746
|
-
var
|
|
18685
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
18686
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
18747
18687
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
18748
18688
|
var import_node_child_process4 = require("child_process");
|
|
18749
18689
|
|
|
18750
18690
|
// src/tunnel/tunnel-store.ts
|
|
18751
|
-
var
|
|
18752
|
-
var
|
|
18691
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
18692
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
18753
18693
|
var TunnelStore = class {
|
|
18754
18694
|
constructor(filePath) {
|
|
18755
18695
|
this.filePath = filePath;
|
|
@@ -18757,7 +18697,7 @@ var TunnelStore = class {
|
|
|
18757
18697
|
filePath;
|
|
18758
18698
|
async get() {
|
|
18759
18699
|
try {
|
|
18760
|
-
const raw = await
|
|
18700
|
+
const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
|
|
18761
18701
|
const obj = JSON.parse(raw);
|
|
18762
18702
|
if (!isPersistedTunnel(obj)) return null;
|
|
18763
18703
|
return obj;
|
|
@@ -18768,22 +18708,22 @@ var TunnelStore = class {
|
|
|
18768
18708
|
}
|
|
18769
18709
|
}
|
|
18770
18710
|
async set(v) {
|
|
18771
|
-
const dir =
|
|
18772
|
-
await
|
|
18711
|
+
const dir = import_node_path11.default.dirname(this.filePath);
|
|
18712
|
+
await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
|
|
18773
18713
|
const data = JSON.stringify(v, null, 2);
|
|
18774
18714
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
18775
|
-
await
|
|
18715
|
+
await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
18776
18716
|
if (process.platform !== "win32") {
|
|
18777
18717
|
try {
|
|
18778
|
-
await
|
|
18718
|
+
await import_node_fs12.default.promises.chmod(tmp, 384);
|
|
18779
18719
|
} catch {
|
|
18780
18720
|
}
|
|
18781
18721
|
}
|
|
18782
|
-
await
|
|
18722
|
+
await import_node_fs12.default.promises.rename(tmp, this.filePath);
|
|
18783
18723
|
}
|
|
18784
18724
|
async clear() {
|
|
18785
18725
|
try {
|
|
18786
|
-
await
|
|
18726
|
+
await import_node_fs12.default.promises.unlink(this.filePath);
|
|
18787
18727
|
} catch (err) {
|
|
18788
18728
|
const code = err?.code;
|
|
18789
18729
|
if (code !== "ENOENT") throw err;
|
|
@@ -18878,9 +18818,9 @@ function escape(v) {
|
|
|
18878
18818
|
}
|
|
18879
18819
|
|
|
18880
18820
|
// src/tunnel/frpc-binary.ts
|
|
18881
|
-
var
|
|
18821
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
18882
18822
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
18883
|
-
var
|
|
18823
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
18884
18824
|
var import_node_child_process3 = require("child_process");
|
|
18885
18825
|
var import_node_stream = require("stream");
|
|
18886
18826
|
var import_promises = require("stream/promises");
|
|
@@ -18912,20 +18852,20 @@ function frpcDownloadUrl(version2, p) {
|
|
|
18912
18852
|
}
|
|
18913
18853
|
async function ensureFrpcBinary(opts) {
|
|
18914
18854
|
if (opts.override) {
|
|
18915
|
-
if (!
|
|
18855
|
+
if (!import_node_fs13.default.existsSync(opts.override)) {
|
|
18916
18856
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
18917
18857
|
}
|
|
18918
18858
|
return opts.override;
|
|
18919
18859
|
}
|
|
18920
18860
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
18921
18861
|
const platform = opts.platform ?? detectPlatform();
|
|
18922
|
-
const binDir =
|
|
18923
|
-
|
|
18862
|
+
const binDir = import_node_path12.default.join(opts.dataDir, "bin");
|
|
18863
|
+
import_node_fs13.default.mkdirSync(binDir, { recursive: true });
|
|
18924
18864
|
cleanupStaleArtifacts(binDir);
|
|
18925
|
-
const stableBin =
|
|
18926
|
-
if (
|
|
18865
|
+
const stableBin = import_node_path12.default.join(binDir, "frpc");
|
|
18866
|
+
if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
|
|
18927
18867
|
const partialBin = `${stableBin}.partial`;
|
|
18928
|
-
const tarballPath =
|
|
18868
|
+
const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
18929
18869
|
try {
|
|
18930
18870
|
const url = frpcDownloadUrl(version2, platform);
|
|
18931
18871
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -18934,8 +18874,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
18934
18874
|
} else {
|
|
18935
18875
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
18936
18876
|
}
|
|
18937
|
-
|
|
18938
|
-
|
|
18877
|
+
import_node_fs13.default.chmodSync(partialBin, 493);
|
|
18878
|
+
import_node_fs13.default.renameSync(partialBin, stableBin);
|
|
18939
18879
|
} finally {
|
|
18940
18880
|
safeUnlink(tarballPath);
|
|
18941
18881
|
safeUnlink(partialBin);
|
|
@@ -18945,15 +18885,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
18945
18885
|
function cleanupStaleArtifacts(binDir) {
|
|
18946
18886
|
let entries;
|
|
18947
18887
|
try {
|
|
18948
|
-
entries =
|
|
18888
|
+
entries = import_node_fs13.default.readdirSync(binDir);
|
|
18949
18889
|
} catch {
|
|
18950
18890
|
return;
|
|
18951
18891
|
}
|
|
18952
18892
|
for (const name of entries) {
|
|
18953
18893
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
18954
|
-
const full =
|
|
18894
|
+
const full = import_node_path12.default.join(binDir, name);
|
|
18955
18895
|
try {
|
|
18956
|
-
|
|
18896
|
+
import_node_fs13.default.rmSync(full, { recursive: true, force: true });
|
|
18957
18897
|
} catch {
|
|
18958
18898
|
}
|
|
18959
18899
|
}
|
|
@@ -18961,7 +18901,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
18961
18901
|
}
|
|
18962
18902
|
function safeUnlink(p) {
|
|
18963
18903
|
try {
|
|
18964
|
-
|
|
18904
|
+
import_node_fs13.default.unlinkSync(p);
|
|
18965
18905
|
} catch {
|
|
18966
18906
|
}
|
|
18967
18907
|
}
|
|
@@ -18972,13 +18912,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
18972
18912
|
if (!res.ok || !res.body) {
|
|
18973
18913
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
18974
18914
|
}
|
|
18975
|
-
const out =
|
|
18915
|
+
const out = import_node_fs13.default.createWriteStream(dest);
|
|
18976
18916
|
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
18977
18917
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
18978
18918
|
}
|
|
18979
18919
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
18980
|
-
const work =
|
|
18981
|
-
|
|
18920
|
+
const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
18921
|
+
import_node_fs13.default.mkdirSync(work, { recursive: true });
|
|
18982
18922
|
try {
|
|
18983
18923
|
await new Promise((resolve, reject) => {
|
|
18984
18924
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -18986,13 +18926,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
18986
18926
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
18987
18927
|
});
|
|
18988
18928
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
18989
|
-
const src =
|
|
18990
|
-
if (!
|
|
18929
|
+
const src = import_node_path12.default.join(work, dirName, "frpc");
|
|
18930
|
+
if (!import_node_fs13.default.existsSync(src)) {
|
|
18991
18931
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
18992
18932
|
}
|
|
18993
|
-
|
|
18933
|
+
import_node_fs13.default.copyFileSync(src, destBin);
|
|
18994
18934
|
} finally {
|
|
18995
|
-
|
|
18935
|
+
import_node_fs13.default.rmSync(work, { recursive: true, force: true });
|
|
18996
18936
|
}
|
|
18997
18937
|
}
|
|
18998
18938
|
|
|
@@ -19001,7 +18941,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
19001
18941
|
var TunnelManager = class {
|
|
19002
18942
|
constructor(deps) {
|
|
19003
18943
|
this.deps = deps;
|
|
19004
|
-
this.store = deps.store ?? new TunnelStore(
|
|
18944
|
+
this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
|
|
19005
18945
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
19006
18946
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
19007
18947
|
}
|
|
@@ -19118,7 +19058,7 @@ var TunnelManager = class {
|
|
|
19118
19058
|
dataDir: this.deps.dataDir,
|
|
19119
19059
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
19120
19060
|
});
|
|
19121
|
-
const tomlPath =
|
|
19061
|
+
const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
|
|
19122
19062
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto4.default.randomBytes(3).toString("hex")}`;
|
|
19123
19063
|
const toml = buildFrpcToml({
|
|
19124
19064
|
serverAddr: t.frpsHost,
|
|
@@ -19129,12 +19069,12 @@ var TunnelManager = class {
|
|
|
19129
19069
|
localPort,
|
|
19130
19070
|
logLevel: "info"
|
|
19131
19071
|
});
|
|
19132
|
-
await
|
|
19072
|
+
await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
19133
19073
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
19134
19074
|
stdio: ["ignore", "pipe", "pipe"]
|
|
19135
19075
|
});
|
|
19136
|
-
const logFilePath =
|
|
19137
|
-
const logStream =
|
|
19076
|
+
const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
|
|
19077
|
+
const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
19138
19078
|
logStream.on("error", () => {
|
|
19139
19079
|
});
|
|
19140
19080
|
const tee = (chunk) => {
|
|
@@ -19226,12 +19166,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
19226
19166
|
}
|
|
19227
19167
|
|
|
19228
19168
|
// src/auth-store.ts
|
|
19229
|
-
var
|
|
19230
|
-
var
|
|
19169
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
19170
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
19231
19171
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
19232
19172
|
var AUTH_FILE_NAME = "auth.json";
|
|
19233
19173
|
function authFilePath(dataDir) {
|
|
19234
|
-
return
|
|
19174
|
+
return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
|
|
19235
19175
|
}
|
|
19236
19176
|
function loadOrCreateAuthToken(opts) {
|
|
19237
19177
|
const file = authFilePath(opts.dataDir);
|
|
@@ -19247,7 +19187,7 @@ function defaultGenerate() {
|
|
|
19247
19187
|
}
|
|
19248
19188
|
function readAuthFile(file) {
|
|
19249
19189
|
try {
|
|
19250
|
-
const raw =
|
|
19190
|
+
const raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
19251
19191
|
const parsed = JSON.parse(raw);
|
|
19252
19192
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
19253
19193
|
return {
|
|
@@ -19263,10 +19203,10 @@ function readAuthFile(file) {
|
|
|
19263
19203
|
}
|
|
19264
19204
|
}
|
|
19265
19205
|
function writeAuthFile(file, content) {
|
|
19266
|
-
|
|
19267
|
-
|
|
19206
|
+
import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
|
|
19207
|
+
import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
19268
19208
|
try {
|
|
19269
|
-
|
|
19209
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
19270
19210
|
} catch {
|
|
19271
19211
|
}
|
|
19272
19212
|
}
|
|
@@ -19278,12 +19218,12 @@ init_protocol();
|
|
|
19278
19218
|
init_protocol();
|
|
19279
19219
|
|
|
19280
19220
|
// src/session/fork.ts
|
|
19281
|
-
var
|
|
19221
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
19282
19222
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
19283
|
-
var
|
|
19223
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
19284
19224
|
init_claude_history();
|
|
19285
19225
|
function readJsonlEntries(file) {
|
|
19286
|
-
const raw =
|
|
19226
|
+
const raw = import_node_fs16.default.readFileSync(file, "utf8");
|
|
19287
19227
|
const out = [];
|
|
19288
19228
|
for (const line of raw.split("\n")) {
|
|
19289
19229
|
const t = line.trim();
|
|
@@ -19296,10 +19236,10 @@ function readJsonlEntries(file) {
|
|
|
19296
19236
|
return out;
|
|
19297
19237
|
}
|
|
19298
19238
|
function forkSession(input) {
|
|
19299
|
-
const baseDir = input.baseDir ??
|
|
19300
|
-
const projectDir =
|
|
19301
|
-
const sourceFile =
|
|
19302
|
-
if (!
|
|
19239
|
+
const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
|
|
19240
|
+
const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
19241
|
+
const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
19242
|
+
if (!import_node_fs16.default.existsSync(sourceFile)) {
|
|
19303
19243
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
19304
19244
|
}
|
|
19305
19245
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -19329,9 +19269,9 @@ function forkSession(input) {
|
|
|
19329
19269
|
}
|
|
19330
19270
|
forkedLines.push(JSON.stringify(forked));
|
|
19331
19271
|
}
|
|
19332
|
-
const forkedFilePath =
|
|
19333
|
-
|
|
19334
|
-
|
|
19272
|
+
const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
19273
|
+
import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
|
|
19274
|
+
import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
19335
19275
|
return { forkedToolSessionId, forkedFilePath };
|
|
19336
19276
|
}
|
|
19337
19277
|
|
|
@@ -19601,9 +19541,9 @@ init_protocol();
|
|
|
19601
19541
|
|
|
19602
19542
|
// src/workspace/git.ts
|
|
19603
19543
|
var import_node_child_process5 = require("child_process");
|
|
19604
|
-
var
|
|
19544
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
19605
19545
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
19606
|
-
var
|
|
19546
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
19607
19547
|
var import_node_util = require("util");
|
|
19608
19548
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
19609
19549
|
function formatChildProcessError(err) {
|
|
@@ -19618,9 +19558,9 @@ function formatChildProcessError(err) {
|
|
|
19618
19558
|
return e.message ?? "unknown error";
|
|
19619
19559
|
}
|
|
19620
19560
|
function normalizePath(p) {
|
|
19621
|
-
const resolved =
|
|
19561
|
+
const resolved = import_node_path16.default.resolve(p);
|
|
19622
19562
|
try {
|
|
19623
|
-
return
|
|
19563
|
+
return import_node_fs17.default.realpathSync(resolved);
|
|
19624
19564
|
} catch {
|
|
19625
19565
|
return resolved;
|
|
19626
19566
|
}
|
|
@@ -19721,13 +19661,13 @@ function flattenToDirName(branch) {
|
|
|
19721
19661
|
}
|
|
19722
19662
|
function encodeClaudeProjectDir(absPath) {
|
|
19723
19663
|
if (!absPath || typeof absPath !== "string") return "";
|
|
19724
|
-
let canonical =
|
|
19664
|
+
let canonical = import_node_path16.default.resolve(absPath);
|
|
19725
19665
|
try {
|
|
19726
|
-
canonical =
|
|
19666
|
+
canonical = import_node_fs17.default.realpathSync(canonical);
|
|
19727
19667
|
} catch {
|
|
19728
19668
|
try {
|
|
19729
|
-
const parent =
|
|
19730
|
-
canonical =
|
|
19669
|
+
const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
|
|
19670
|
+
canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
|
|
19731
19671
|
} catch {
|
|
19732
19672
|
}
|
|
19733
19673
|
}
|
|
@@ -19751,11 +19691,11 @@ async function createWorktree(input) {
|
|
|
19751
19691
|
if (!isGitRoot) {
|
|
19752
19692
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
19753
19693
|
}
|
|
19754
|
-
const parent =
|
|
19755
|
-
if (parent === "/" || parent ===
|
|
19694
|
+
const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
|
|
19695
|
+
if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
|
|
19756
19696
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
19757
19697
|
}
|
|
19758
|
-
const worktreeRoot =
|
|
19698
|
+
const worktreeRoot = import_node_path16.default.join(parent, dirName);
|
|
19759
19699
|
try {
|
|
19760
19700
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
|
|
19761
19701
|
timeout: 3e3
|
|
@@ -19772,7 +19712,7 @@ async function createWorktree(input) {
|
|
|
19772
19712
|
const msg = err.message;
|
|
19773
19713
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
19774
19714
|
}
|
|
19775
|
-
if (
|
|
19715
|
+
if (import_node_fs17.default.existsSync(worktreeRoot)) {
|
|
19776
19716
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
19777
19717
|
}
|
|
19778
19718
|
try {
|
|
@@ -19800,8 +19740,8 @@ async function removeWorktree(input) {
|
|
|
19800
19740
|
);
|
|
19801
19741
|
const gitCommonDir = stdout.trim();
|
|
19802
19742
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
19803
|
-
const absGitCommon =
|
|
19804
|
-
repoRoot =
|
|
19743
|
+
const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
|
|
19744
|
+
repoRoot = import_node_path16.default.dirname(absGitCommon);
|
|
19805
19745
|
} catch {
|
|
19806
19746
|
repoRoot = null;
|
|
19807
19747
|
}
|
|
@@ -19813,7 +19753,7 @@ async function removeWorktree(input) {
|
|
|
19813
19753
|
} catch (err) {
|
|
19814
19754
|
const stderr = err.stderr ?? "";
|
|
19815
19755
|
const lower = stderr.toLowerCase();
|
|
19816
|
-
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !
|
|
19756
|
+
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
|
|
19817
19757
|
if (!vanished) {
|
|
19818
19758
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
19819
19759
|
}
|
|
@@ -19832,10 +19772,10 @@ async function removeWorktree(input) {
|
|
|
19832
19772
|
try {
|
|
19833
19773
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
19834
19774
|
if (encoded) {
|
|
19835
|
-
const projectsRoot =
|
|
19836
|
-
const target =
|
|
19837
|
-
if (target.startsWith(projectsRoot +
|
|
19838
|
-
|
|
19775
|
+
const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
19776
|
+
const target = import_node_path16.default.resolve(projectsRoot, encoded);
|
|
19777
|
+
if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
|
|
19778
|
+
import_node_fs17.default.rmSync(target, { recursive: true, force: true });
|
|
19839
19779
|
}
|
|
19840
19780
|
}
|
|
19841
19781
|
} catch {
|
|
@@ -19954,7 +19894,8 @@ init_protocol();
|
|
|
19954
19894
|
function buildPersonaHandlers(deps) {
|
|
19955
19895
|
const { personaManager, personaRegistry, sessionManager } = deps;
|
|
19956
19896
|
const create = async (frame) => {
|
|
19957
|
-
const
|
|
19897
|
+
const { type: _type, requestId: _requestId, ...rest } = frame;
|
|
19898
|
+
const args = PersonaCreateArgsSchema.parse(rest);
|
|
19958
19899
|
const persona = personaManager.create(args);
|
|
19959
19900
|
return { response: { type: "persona:info", ...persona } };
|
|
19960
19901
|
};
|
|
@@ -19964,7 +19905,7 @@ function buildPersonaHandlers(deps) {
|
|
|
19964
19905
|
};
|
|
19965
19906
|
};
|
|
19966
19907
|
const get = async (frame) => {
|
|
19967
|
-
const args =
|
|
19908
|
+
const args = PersonaIdArgsSchema.parse(frame);
|
|
19968
19909
|
const persona = personaRegistry.get(args.personaId) ?? null;
|
|
19969
19910
|
if (!persona) {
|
|
19970
19911
|
return { response: { type: "persona:info", persona: null } };
|
|
@@ -19972,38 +19913,40 @@ function buildPersonaHandlers(deps) {
|
|
|
19972
19913
|
return { response: { type: "persona:info", ...persona } };
|
|
19973
19914
|
};
|
|
19974
19915
|
const update = async (frame) => {
|
|
19975
|
-
const
|
|
19976
|
-
const
|
|
19916
|
+
const { type: _type, requestId: _requestId, ...rest } = frame;
|
|
19917
|
+
const args = PersonaUpdateArgsSchema.parse(rest);
|
|
19918
|
+
const { personality, ...metaPatch } = args.patch;
|
|
19919
|
+
const persona = personaManager.update(args.personaId, metaPatch, personality);
|
|
19977
19920
|
return { response: { type: "persona:info", ...persona } };
|
|
19978
19921
|
};
|
|
19979
19922
|
const del = async (frame) => {
|
|
19980
|
-
const args =
|
|
19923
|
+
const args = PersonaIdArgsSchema.parse(frame);
|
|
19981
19924
|
personaManager.delete(args.personaId);
|
|
19982
19925
|
return {
|
|
19983
19926
|
response: { type: "persona:deleted", personaId: args.personaId }
|
|
19984
19927
|
};
|
|
19985
19928
|
};
|
|
19986
19929
|
const issueToken = async (frame) => {
|
|
19987
|
-
const args =
|
|
19930
|
+
const args = PersonaIssueTokenArgsSchema.parse(frame);
|
|
19988
19931
|
const { token, persona } = personaManager.issueToken(args.personaId, args.label);
|
|
19989
19932
|
return {
|
|
19990
19933
|
response: { type: "persona:tokenIssued", token, persona }
|
|
19991
19934
|
};
|
|
19992
19935
|
};
|
|
19993
19936
|
const revokeToken = async (frame) => {
|
|
19994
|
-
const args =
|
|
19937
|
+
const args = PersonaRevokeTokenArgsSchema.parse(frame);
|
|
19995
19938
|
const persona = personaManager.revokeToken(args.personaId, args.token);
|
|
19996
19939
|
return { response: { type: "persona:info", ...persona } };
|
|
19997
19940
|
};
|
|
19998
19941
|
const listSubSessions = async (frame) => {
|
|
19999
|
-
const args =
|
|
19942
|
+
const args = PersonaIdArgsSchema.parse(frame);
|
|
20000
19943
|
const sessions = sessionManager.listForAgent(args.personaId);
|
|
20001
19944
|
return {
|
|
20002
19945
|
response: { type: "persona:subSessions", sessions }
|
|
20003
19946
|
};
|
|
20004
19947
|
};
|
|
20005
19948
|
const appendOwnerMessage = async (frame) => {
|
|
20006
|
-
const args =
|
|
19949
|
+
const args = PersonaAppendOwnerMessageArgsSchema.parse(frame);
|
|
20007
19950
|
personaManager.appendOwnerMessage(args.personaId, args.subSessionId, args.text);
|
|
20008
19951
|
return {
|
|
20009
19952
|
response: { type: "persona:appendOwnerMessage", ok: true }
|
|
@@ -20044,7 +19987,7 @@ function buildMethodHandlers(deps) {
|
|
|
20044
19987
|
async function startDaemon(config) {
|
|
20045
19988
|
const logger = createLogger({
|
|
20046
19989
|
level: config.logLevel,
|
|
20047
|
-
file:
|
|
19990
|
+
file: import_node_path17.default.join(config.dataDir, "clawd.log")
|
|
20048
19991
|
});
|
|
20049
19992
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
20050
19993
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -20085,6 +20028,7 @@ async function startDaemon(config) {
|
|
|
20085
20028
|
getAdapter,
|
|
20086
20029
|
historyReader: history,
|
|
20087
20030
|
dataDir: config.dataDir,
|
|
20031
|
+
personaRoot: import_node_path17.default.join(config.dataDir, "personas"),
|
|
20088
20032
|
broadcastFrame: (frame, target) => {
|
|
20089
20033
|
if (target === "all") {
|
|
20090
20034
|
transport?.broadcastAll(frame);
|
|
@@ -20124,15 +20068,12 @@ async function startDaemon(config) {
|
|
|
20124
20068
|
manager.recordRealUserUuid({ sessionId, realUuid, text });
|
|
20125
20069
|
}
|
|
20126
20070
|
});
|
|
20127
|
-
const personaStore = new PersonaStore(
|
|
20071
|
+
const personaStore = new PersonaStore(import_node_path17.default.join(config.dataDir, "personas"));
|
|
20128
20072
|
const personaRegistry = new PersonaRegistry(personaStore);
|
|
20129
20073
|
const personaManager = new PersonaManager({
|
|
20130
20074
|
store: personaStore,
|
|
20131
20075
|
registry: personaRegistry,
|
|
20132
|
-
sessionManager: manager
|
|
20133
|
-
dataDir: config.dataDir,
|
|
20134
|
-
now: () => /* @__PURE__ */ new Date(),
|
|
20135
|
-
logger
|
|
20076
|
+
sessionManager: manager
|
|
20136
20077
|
});
|
|
20137
20078
|
let currentTunnelUrl = null;
|
|
20138
20079
|
const handlers = buildMethodHandlers({
|
|
@@ -20150,6 +20091,7 @@ async function startDaemon(config) {
|
|
|
20150
20091
|
const personaBoundHandler = new PersonaBoundHandler({
|
|
20151
20092
|
registry: personaRegistry,
|
|
20152
20093
|
personaManager,
|
|
20094
|
+
personaStore,
|
|
20153
20095
|
sessionManager: manager,
|
|
20154
20096
|
logger
|
|
20155
20097
|
});
|
|
@@ -20258,8 +20200,8 @@ async function startDaemon(config) {
|
|
|
20258
20200
|
const lines = [
|
|
20259
20201
|
`Tunnel: ${r.url}`,
|
|
20260
20202
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
20261
|
-
`Frpc config: ${
|
|
20262
|
-
`Frpc log: ${
|
|
20203
|
+
`Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
|
|
20204
|
+
`Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
|
|
20263
20205
|
];
|
|
20264
20206
|
const width = Math.max(...lines.map((l) => l.length));
|
|
20265
20207
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -20272,8 +20214,8 @@ ${bar}
|
|
|
20272
20214
|
|
|
20273
20215
|
`);
|
|
20274
20216
|
try {
|
|
20275
|
-
const connectPath =
|
|
20276
|
-
|
|
20217
|
+
const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
|
|
20218
|
+
import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
20277
20219
|
} catch {
|
|
20278
20220
|
}
|
|
20279
20221
|
} catch (err) {
|