@clawos-dev/clawd 0.2.23-beta.34.136a698 → 0.2.24
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 +306 -237
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -293,8 +293,8 @@ var require_req = __commonJS({
|
|
|
293
293
|
if (req.originalUrl) {
|
|
294
294
|
_req.url = req.originalUrl;
|
|
295
295
|
} else {
|
|
296
|
-
const
|
|
297
|
-
_req.url = typeof
|
|
296
|
+
const path18 = req.path;
|
|
297
|
+
_req.url = typeof path18 === "string" ? path18 : req.url ? req.url.path || req.url : void 0;
|
|
298
298
|
}
|
|
299
299
|
if (req.query) {
|
|
300
300
|
_req.query = req.query;
|
|
@@ -459,14 +459,14 @@ var require_redact = __commonJS({
|
|
|
459
459
|
}
|
|
460
460
|
return obj;
|
|
461
461
|
}
|
|
462
|
-
function parsePath(
|
|
462
|
+
function parsePath(path18) {
|
|
463
463
|
const parts = [];
|
|
464
464
|
let current = "";
|
|
465
465
|
let inBrackets = false;
|
|
466
466
|
let inQuotes = false;
|
|
467
467
|
let quoteChar = "";
|
|
468
|
-
for (let i = 0; i <
|
|
469
|
-
const char =
|
|
468
|
+
for (let i = 0; i < path18.length; i++) {
|
|
469
|
+
const char = path18[i];
|
|
470
470
|
if (!inBrackets && char === ".") {
|
|
471
471
|
if (current) {
|
|
472
472
|
parts.push(current);
|
|
@@ -597,10 +597,10 @@ var require_redact = __commonJS({
|
|
|
597
597
|
return current;
|
|
598
598
|
}
|
|
599
599
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
600
|
-
for (const
|
|
601
|
-
const parts = parsePath(
|
|
600
|
+
for (const path18 of paths) {
|
|
601
|
+
const parts = parsePath(path18);
|
|
602
602
|
if (parts.includes("*")) {
|
|
603
|
-
redactWildcardPath(obj, parts, censor,
|
|
603
|
+
redactWildcardPath(obj, parts, censor, path18, remove);
|
|
604
604
|
} else {
|
|
605
605
|
if (remove) {
|
|
606
606
|
removeKey(obj, parts);
|
|
@@ -685,8 +685,8 @@ var require_redact = __commonJS({
|
|
|
685
685
|
}
|
|
686
686
|
} else {
|
|
687
687
|
if (afterWildcard.includes("*")) {
|
|
688
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
689
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
688
|
+
const wrappedCensor = typeof censor === "function" ? (value, path18) => {
|
|
689
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path18];
|
|
690
690
|
return censor(value, fullPath);
|
|
691
691
|
} : censor;
|
|
692
692
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -721,8 +721,8 @@ var require_redact = __commonJS({
|
|
|
721
721
|
return null;
|
|
722
722
|
}
|
|
723
723
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
724
|
-
for (const
|
|
725
|
-
const parts = parsePath(
|
|
724
|
+
for (const path18 of pathsToClone) {
|
|
725
|
+
const parts = parsePath(path18);
|
|
726
726
|
let current = pathStructure;
|
|
727
727
|
for (let i = 0; i < parts.length; i++) {
|
|
728
728
|
const part = parts[i];
|
|
@@ -774,24 +774,24 @@ var require_redact = __commonJS({
|
|
|
774
774
|
}
|
|
775
775
|
return cloneSelectively(obj, pathStructure);
|
|
776
776
|
}
|
|
777
|
-
function validatePath(
|
|
778
|
-
if (typeof
|
|
777
|
+
function validatePath(path18) {
|
|
778
|
+
if (typeof path18 !== "string") {
|
|
779
779
|
throw new Error("Paths must be (non-empty) strings");
|
|
780
780
|
}
|
|
781
|
-
if (
|
|
781
|
+
if (path18 === "") {
|
|
782
782
|
throw new Error("Invalid redaction path ()");
|
|
783
783
|
}
|
|
784
|
-
if (
|
|
785
|
-
throw new Error(`Invalid redaction path (${
|
|
784
|
+
if (path18.includes("..")) {
|
|
785
|
+
throw new Error(`Invalid redaction path (${path18})`);
|
|
786
786
|
}
|
|
787
|
-
if (
|
|
788
|
-
throw new Error(`Invalid redaction path (${
|
|
787
|
+
if (path18.includes(",")) {
|
|
788
|
+
throw new Error(`Invalid redaction path (${path18})`);
|
|
789
789
|
}
|
|
790
790
|
let bracketCount = 0;
|
|
791
791
|
let inQuotes = false;
|
|
792
792
|
let quoteChar = "";
|
|
793
|
-
for (let i = 0; i <
|
|
794
|
-
const char =
|
|
793
|
+
for (let i = 0; i < path18.length; i++) {
|
|
794
|
+
const char = path18[i];
|
|
795
795
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
796
796
|
if (!inQuotes) {
|
|
797
797
|
inQuotes = true;
|
|
@@ -805,20 +805,20 @@ var require_redact = __commonJS({
|
|
|
805
805
|
} else if (char === "]" && !inQuotes) {
|
|
806
806
|
bracketCount--;
|
|
807
807
|
if (bracketCount < 0) {
|
|
808
|
-
throw new Error(`Invalid redaction path (${
|
|
808
|
+
throw new Error(`Invalid redaction path (${path18})`);
|
|
809
809
|
}
|
|
810
810
|
}
|
|
811
811
|
}
|
|
812
812
|
if (bracketCount !== 0) {
|
|
813
|
-
throw new Error(`Invalid redaction path (${
|
|
813
|
+
throw new Error(`Invalid redaction path (${path18})`);
|
|
814
814
|
}
|
|
815
815
|
}
|
|
816
816
|
function validatePaths(paths) {
|
|
817
817
|
if (!Array.isArray(paths)) {
|
|
818
818
|
throw new TypeError("paths must be an array");
|
|
819
819
|
}
|
|
820
|
-
for (const
|
|
821
|
-
validatePath(
|
|
820
|
+
for (const path18 of paths) {
|
|
821
|
+
validatePath(path18);
|
|
822
822
|
}
|
|
823
823
|
}
|
|
824
824
|
function slowRedact(options = {}) {
|
|
@@ -986,8 +986,8 @@ var require_redaction = __commonJS({
|
|
|
986
986
|
if (shape[k] === null) {
|
|
987
987
|
o[k] = (value) => topCensor(value, [k]);
|
|
988
988
|
} else {
|
|
989
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
990
|
-
return censor(value, [k, ...
|
|
989
|
+
const wrappedCensor = typeof censor === "function" ? (value, path18) => {
|
|
990
|
+
return censor(value, [k, ...path18]);
|
|
991
991
|
} : censor;
|
|
992
992
|
o[k] = Redact({
|
|
993
993
|
paths: shape[k],
|
|
@@ -1205,10 +1205,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
1205
1205
|
var require_sonic_boom = __commonJS({
|
|
1206
1206
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
1207
1207
|
"use strict";
|
|
1208
|
-
var
|
|
1208
|
+
var fs19 = require("fs");
|
|
1209
1209
|
var EventEmitter = require("events");
|
|
1210
1210
|
var inherits = require("util").inherits;
|
|
1211
|
-
var
|
|
1211
|
+
var path18 = require("path");
|
|
1212
1212
|
var sleep = require_atomic_sleep();
|
|
1213
1213
|
var assert = require("assert");
|
|
1214
1214
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -1262,20 +1262,20 @@ var require_sonic_boom = __commonJS({
|
|
|
1262
1262
|
const mode = sonic.mode;
|
|
1263
1263
|
if (sonic.sync) {
|
|
1264
1264
|
try {
|
|
1265
|
-
if (sonic.mkdir)
|
|
1266
|
-
const fd =
|
|
1265
|
+
if (sonic.mkdir) fs19.mkdirSync(path18.dirname(file), { recursive: true });
|
|
1266
|
+
const fd = fs19.openSync(file, flags, mode);
|
|
1267
1267
|
fileOpened(null, fd);
|
|
1268
1268
|
} catch (err) {
|
|
1269
1269
|
fileOpened(err);
|
|
1270
1270
|
throw err;
|
|
1271
1271
|
}
|
|
1272
1272
|
} else if (sonic.mkdir) {
|
|
1273
|
-
|
|
1273
|
+
fs19.mkdir(path18.dirname(file), { recursive: true }, (err) => {
|
|
1274
1274
|
if (err) return fileOpened(err);
|
|
1275
|
-
|
|
1275
|
+
fs19.open(file, flags, mode, fileOpened);
|
|
1276
1276
|
});
|
|
1277
1277
|
} else {
|
|
1278
|
-
|
|
1278
|
+
fs19.open(file, flags, mode, fileOpened);
|
|
1279
1279
|
}
|
|
1280
1280
|
}
|
|
1281
1281
|
function SonicBoom(opts) {
|
|
@@ -1316,8 +1316,8 @@ var require_sonic_boom = __commonJS({
|
|
|
1316
1316
|
this.flush = flushBuffer;
|
|
1317
1317
|
this.flushSync = flushBufferSync;
|
|
1318
1318
|
this._actualWrite = actualWriteBuffer;
|
|
1319
|
-
fsWriteSync = () =>
|
|
1320
|
-
fsWrite = () =>
|
|
1319
|
+
fsWriteSync = () => fs19.writeSync(this.fd, this._writingBuf);
|
|
1320
|
+
fsWrite = () => fs19.write(this.fd, this._writingBuf, this.release);
|
|
1321
1321
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
1322
1322
|
this._writingBuf = "";
|
|
1323
1323
|
this.write = write;
|
|
@@ -1326,15 +1326,15 @@ var require_sonic_boom = __commonJS({
|
|
|
1326
1326
|
this._actualWrite = actualWrite;
|
|
1327
1327
|
fsWriteSync = () => {
|
|
1328
1328
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
1329
|
-
return
|
|
1329
|
+
return fs19.writeSync(this.fd, this._writingBuf);
|
|
1330
1330
|
}
|
|
1331
|
-
return
|
|
1331
|
+
return fs19.writeSync(this.fd, this._writingBuf, "utf8");
|
|
1332
1332
|
};
|
|
1333
1333
|
fsWrite = () => {
|
|
1334
1334
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
1335
|
-
return
|
|
1335
|
+
return fs19.write(this.fd, this._writingBuf, this.release);
|
|
1336
1336
|
}
|
|
1337
|
-
return
|
|
1337
|
+
return fs19.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
1338
1338
|
};
|
|
1339
1339
|
} else {
|
|
1340
1340
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -1391,7 +1391,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1391
1391
|
}
|
|
1392
1392
|
}
|
|
1393
1393
|
if (this._fsync) {
|
|
1394
|
-
|
|
1394
|
+
fs19.fsyncSync(this.fd);
|
|
1395
1395
|
}
|
|
1396
1396
|
const len = this._len;
|
|
1397
1397
|
if (this._reopening) {
|
|
@@ -1505,7 +1505,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1505
1505
|
const onDrain = () => {
|
|
1506
1506
|
if (!this._fsync) {
|
|
1507
1507
|
try {
|
|
1508
|
-
|
|
1508
|
+
fs19.fsync(this.fd, (err) => {
|
|
1509
1509
|
this._flushPending = false;
|
|
1510
1510
|
cb(err);
|
|
1511
1511
|
});
|
|
@@ -1607,7 +1607,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1607
1607
|
const fd = this.fd;
|
|
1608
1608
|
this.once("ready", () => {
|
|
1609
1609
|
if (fd !== this.fd) {
|
|
1610
|
-
|
|
1610
|
+
fs19.close(fd, (err) => {
|
|
1611
1611
|
if (err) {
|
|
1612
1612
|
return this.emit("error", err);
|
|
1613
1613
|
}
|
|
@@ -1656,7 +1656,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1656
1656
|
buf = this._bufs[0];
|
|
1657
1657
|
}
|
|
1658
1658
|
try {
|
|
1659
|
-
const n = Buffer.isBuffer(buf) ?
|
|
1659
|
+
const n = Buffer.isBuffer(buf) ? fs19.writeSync(this.fd, buf) : fs19.writeSync(this.fd, buf, "utf8");
|
|
1660
1660
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
1661
1661
|
buf = releasedBufObj.writingBuf;
|
|
1662
1662
|
this._len = releasedBufObj.len;
|
|
@@ -1672,7 +1672,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1672
1672
|
}
|
|
1673
1673
|
}
|
|
1674
1674
|
try {
|
|
1675
|
-
|
|
1675
|
+
fs19.fsyncSync(this.fd);
|
|
1676
1676
|
} catch {
|
|
1677
1677
|
}
|
|
1678
1678
|
}
|
|
@@ -1693,7 +1693,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1693
1693
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
1694
1694
|
}
|
|
1695
1695
|
try {
|
|
1696
|
-
const n =
|
|
1696
|
+
const n = fs19.writeSync(this.fd, buf);
|
|
1697
1697
|
buf = buf.subarray(n);
|
|
1698
1698
|
this._len = Math.max(this._len - n, 0);
|
|
1699
1699
|
if (buf.length <= 0) {
|
|
@@ -1721,13 +1721,13 @@ var require_sonic_boom = __commonJS({
|
|
|
1721
1721
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
1722
1722
|
if (this.sync) {
|
|
1723
1723
|
try {
|
|
1724
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
1724
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs19.writeSync(this.fd, this._writingBuf) : fs19.writeSync(this.fd, this._writingBuf, "utf8");
|
|
1725
1725
|
release(null, written);
|
|
1726
1726
|
} catch (err) {
|
|
1727
1727
|
release(err);
|
|
1728
1728
|
}
|
|
1729
1729
|
} else {
|
|
1730
|
-
|
|
1730
|
+
fs19.write(this.fd, this._writingBuf, release);
|
|
1731
1731
|
}
|
|
1732
1732
|
}
|
|
1733
1733
|
function actualWriteBuffer() {
|
|
@@ -1736,7 +1736,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1736
1736
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
1737
1737
|
if (this.sync) {
|
|
1738
1738
|
try {
|
|
1739
|
-
const written =
|
|
1739
|
+
const written = fs19.writeSync(this.fd, this._writingBuf);
|
|
1740
1740
|
release(null, written);
|
|
1741
1741
|
} catch (err) {
|
|
1742
1742
|
release(err);
|
|
@@ -1745,7 +1745,7 @@ var require_sonic_boom = __commonJS({
|
|
|
1745
1745
|
if (kCopyBuffer) {
|
|
1746
1746
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
1747
1747
|
}
|
|
1748
|
-
|
|
1748
|
+
fs19.write(this.fd, this._writingBuf, release);
|
|
1749
1749
|
}
|
|
1750
1750
|
}
|
|
1751
1751
|
function actualClose(sonic) {
|
|
@@ -1761,12 +1761,12 @@ var require_sonic_boom = __commonJS({
|
|
|
1761
1761
|
sonic._lens = [];
|
|
1762
1762
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
1763
1763
|
try {
|
|
1764
|
-
|
|
1764
|
+
fs19.fsync(sonic.fd, closeWrapped);
|
|
1765
1765
|
} catch {
|
|
1766
1766
|
}
|
|
1767
1767
|
function closeWrapped() {
|
|
1768
1768
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
1769
|
-
|
|
1769
|
+
fs19.close(sonic.fd, done);
|
|
1770
1770
|
} else {
|
|
1771
1771
|
done();
|
|
1772
1772
|
}
|
|
@@ -8075,8 +8075,8 @@ Env (advanced):
|
|
|
8075
8075
|
`;
|
|
8076
8076
|
|
|
8077
8077
|
// src/index.ts
|
|
8078
|
-
var
|
|
8079
|
-
var
|
|
8078
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
8079
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
8080
8080
|
|
|
8081
8081
|
// src/logger.ts
|
|
8082
8082
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -8687,8 +8687,8 @@ function getErrorMap() {
|
|
|
8687
8687
|
|
|
8688
8688
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
8689
8689
|
var makeIssue = (params) => {
|
|
8690
|
-
const { data, path:
|
|
8691
|
-
const fullPath = [...
|
|
8690
|
+
const { data, path: path18, errorMaps, issueData } = params;
|
|
8691
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
8692
8692
|
const fullIssue = {
|
|
8693
8693
|
...issueData,
|
|
8694
8694
|
path: fullPath
|
|
@@ -8804,11 +8804,11 @@ var errorUtil;
|
|
|
8804
8804
|
|
|
8805
8805
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
8806
8806
|
var ParseInputLazyPath = class {
|
|
8807
|
-
constructor(parent, value,
|
|
8807
|
+
constructor(parent, value, path18, key) {
|
|
8808
8808
|
this._cachedPath = [];
|
|
8809
8809
|
this.parent = parent;
|
|
8810
8810
|
this.data = value;
|
|
8811
|
-
this._path =
|
|
8811
|
+
this._path = path18;
|
|
8812
8812
|
this._key = key;
|
|
8813
8813
|
}
|
|
8814
8814
|
get path() {
|
|
@@ -12819,7 +12819,7 @@ var SessionStore = class {
|
|
|
12819
12819
|
};
|
|
12820
12820
|
|
|
12821
12821
|
// src/session/manager.ts
|
|
12822
|
-
var
|
|
12822
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
12823
12823
|
|
|
12824
12824
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
12825
12825
|
var byteToHex = [];
|
|
@@ -13408,6 +13408,58 @@ function reduceSession(state, input, deps) {
|
|
|
13408
13408
|
}
|
|
13409
13409
|
}
|
|
13410
13410
|
|
|
13411
|
+
// src/ipc-recorder.ts
|
|
13412
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
13413
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
13414
|
+
function tsForFilename(ms) {
|
|
13415
|
+
return new Date(ms).toISOString().replace(/[:.]/g, "-");
|
|
13416
|
+
}
|
|
13417
|
+
function startRecorder(opts) {
|
|
13418
|
+
if (opts.env.CLAWD_RECORD_IPC !== "1") return null;
|
|
13419
|
+
if (!opts.dataDir) return null;
|
|
13420
|
+
if (!opts.sessionId || opts.sessionId.includes("..") || opts.sessionId.includes("/") || opts.sessionId.includes("\\") || opts.sessionId.startsWith(".")) {
|
|
13421
|
+
return null;
|
|
13422
|
+
}
|
|
13423
|
+
const now = opts.now ?? Date.now;
|
|
13424
|
+
const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
|
|
13425
|
+
const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
|
|
13426
|
+
let stream = null;
|
|
13427
|
+
let closedResolve;
|
|
13428
|
+
const closed = new Promise((resolve) => {
|
|
13429
|
+
closedResolve = resolve;
|
|
13430
|
+
});
|
|
13431
|
+
let exited = false;
|
|
13432
|
+
const ensureStream = () => {
|
|
13433
|
+
if (stream) return stream;
|
|
13434
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
13435
|
+
stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
|
|
13436
|
+
stream.on("close", () => closedResolve());
|
|
13437
|
+
return stream;
|
|
13438
|
+
};
|
|
13439
|
+
const writeLine = (s, chunk) => {
|
|
13440
|
+
if (exited) return;
|
|
13441
|
+
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13442
|
+
const line = JSON.stringify({ ts: now(), stream: s, chunk: text }) + "\n";
|
|
13443
|
+
ensureStream().write(line);
|
|
13444
|
+
};
|
|
13445
|
+
opts.proc.stdout?.on("data", (chunk) => writeLine("stdout", chunk));
|
|
13446
|
+
opts.proc.stderr?.on("data", (chunk) => writeLine("stderr", chunk));
|
|
13447
|
+
opts.proc.on("exit", () => {
|
|
13448
|
+
exited = true;
|
|
13449
|
+
if (stream) {
|
|
13450
|
+
stream.end();
|
|
13451
|
+
} else {
|
|
13452
|
+
closedResolve();
|
|
13453
|
+
}
|
|
13454
|
+
});
|
|
13455
|
+
return {
|
|
13456
|
+
tapStdinWrite(chunk) {
|
|
13457
|
+
writeLine("stdin", chunk);
|
|
13458
|
+
},
|
|
13459
|
+
closed
|
|
13460
|
+
};
|
|
13461
|
+
}
|
|
13462
|
+
|
|
13411
13463
|
// src/session/runner.ts
|
|
13412
13464
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
13413
13465
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -13438,6 +13490,8 @@ var SessionRunner = class {
|
|
|
13438
13490
|
pendingControlRequests = /* @__PURE__ */ new Map();
|
|
13439
13491
|
// waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
|
|
13440
13492
|
stopWaiters = [];
|
|
13493
|
+
// IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
|
|
13494
|
+
recorder = null;
|
|
13441
13495
|
getState() {
|
|
13442
13496
|
return this.state;
|
|
13443
13497
|
}
|
|
@@ -13527,6 +13581,7 @@ var SessionRunner = class {
|
|
|
13527
13581
|
this.pendingControlRequests.set(requestId, { resolve, reject, timer });
|
|
13528
13582
|
try {
|
|
13529
13583
|
proc.stdin?.write(payload);
|
|
13584
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13530
13585
|
} catch (err) {
|
|
13531
13586
|
clearTimeout(timer);
|
|
13532
13587
|
this.pendingControlRequests.delete(requestId);
|
|
@@ -13582,10 +13637,14 @@ var SessionRunner = class {
|
|
|
13582
13637
|
break;
|
|
13583
13638
|
case "write-stdin":
|
|
13584
13639
|
this.proc?.stdin?.write(effect.payload);
|
|
13640
|
+
this.recorder?.tapStdinWrite(effect.payload);
|
|
13585
13641
|
break;
|
|
13586
|
-
case "send-control-response-allow-with-input":
|
|
13587
|
-
|
|
13642
|
+
case "send-control-response-allow-with-input": {
|
|
13643
|
+
const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
|
|
13644
|
+
this.proc?.stdin?.write(payload);
|
|
13645
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13588
13646
|
break;
|
|
13647
|
+
}
|
|
13589
13648
|
case "persist-file":
|
|
13590
13649
|
try {
|
|
13591
13650
|
this.hooks.store.write(effect.file);
|
|
@@ -13615,6 +13674,13 @@ var SessionRunner = class {
|
|
|
13615
13674
|
const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
|
|
13616
13675
|
this.proc = proc;
|
|
13617
13676
|
this.stdoutBuf = "";
|
|
13677
|
+
this.recorder = startRecorder({
|
|
13678
|
+
proc,
|
|
13679
|
+
sessionId: this.state.file.sessionId,
|
|
13680
|
+
dataDir: this.hooks.dataDir,
|
|
13681
|
+
env: this.hooks.recordEnv ?? process.env,
|
|
13682
|
+
now: this.hooks.now
|
|
13683
|
+
});
|
|
13618
13684
|
proc.stdout?.on("data", (chunk) => {
|
|
13619
13685
|
this.stdoutBuf += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13620
13686
|
let idx;
|
|
@@ -13631,6 +13697,7 @@ var SessionRunner = class {
|
|
|
13631
13697
|
});
|
|
13632
13698
|
proc.on("exit", (code) => {
|
|
13633
13699
|
this.proc = null;
|
|
13700
|
+
this.recorder = null;
|
|
13634
13701
|
this.rejectAllPending(new Error("session gone"));
|
|
13635
13702
|
this.input({ kind: "proc-exit", code });
|
|
13636
13703
|
});
|
|
@@ -13757,7 +13824,8 @@ var SessionManager = class {
|
|
|
13757
13824
|
now: this.deps.now,
|
|
13758
13825
|
bufferCap: this.deps.bufferCap,
|
|
13759
13826
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
13760
|
-
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
|
|
13827
|
+
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
13828
|
+
dataDir: this.deps.dataDir
|
|
13761
13829
|
});
|
|
13762
13830
|
return runner;
|
|
13763
13831
|
}
|
|
@@ -13788,7 +13856,7 @@ var SessionManager = class {
|
|
|
13788
13856
|
// ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
|
|
13789
13857
|
create(args) {
|
|
13790
13858
|
try {
|
|
13791
|
-
const stat =
|
|
13859
|
+
const stat = import_node_fs5.default.statSync(args.cwd);
|
|
13792
13860
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
13793
13861
|
} catch {
|
|
13794
13862
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
|
|
@@ -14277,14 +14345,14 @@ var SessionManager = class {
|
|
|
14277
14345
|
// src/tools/claude.ts
|
|
14278
14346
|
var import_node_child_process = require("child_process");
|
|
14279
14347
|
var import_node_child_process2 = require("child_process");
|
|
14280
|
-
var
|
|
14348
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
14281
14349
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
14282
|
-
var
|
|
14350
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
14283
14351
|
|
|
14284
14352
|
// src/tools/claude-history.ts
|
|
14285
|
-
var
|
|
14353
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
14286
14354
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
14287
|
-
var
|
|
14355
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
14288
14356
|
|
|
14289
14357
|
// ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
|
|
14290
14358
|
function Diff() {
|
|
@@ -14388,11 +14456,11 @@ Diff.prototype = {
|
|
|
14388
14456
|
}
|
|
14389
14457
|
}
|
|
14390
14458
|
},
|
|
14391
|
-
addToPath: function addToPath(
|
|
14392
|
-
var last =
|
|
14459
|
+
addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
|
|
14460
|
+
var last = path18.lastComponent;
|
|
14393
14461
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14394
14462
|
return {
|
|
14395
|
-
oldPos:
|
|
14463
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14396
14464
|
lastComponent: {
|
|
14397
14465
|
count: last.count + 1,
|
|
14398
14466
|
added,
|
|
@@ -14402,7 +14470,7 @@ Diff.prototype = {
|
|
|
14402
14470
|
};
|
|
14403
14471
|
} else {
|
|
14404
14472
|
return {
|
|
14405
|
-
oldPos:
|
|
14473
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14406
14474
|
lastComponent: {
|
|
14407
14475
|
count: 1,
|
|
14408
14476
|
added,
|
|
@@ -15061,7 +15129,7 @@ function hashDirToCwd(hash) {
|
|
|
15061
15129
|
}
|
|
15062
15130
|
function safeStatMtime(p) {
|
|
15063
15131
|
try {
|
|
15064
|
-
return
|
|
15132
|
+
return import_node_fs6.default.statSync(p).mtimeMs;
|
|
15065
15133
|
} catch {
|
|
15066
15134
|
return 0;
|
|
15067
15135
|
}
|
|
@@ -15069,7 +15137,7 @@ function safeStatMtime(p) {
|
|
|
15069
15137
|
function readJsonlLines(file) {
|
|
15070
15138
|
let raw;
|
|
15071
15139
|
try {
|
|
15072
|
-
raw =
|
|
15140
|
+
raw = import_node_fs6.default.readFileSync(file, "utf8");
|
|
15073
15141
|
} catch (err) {
|
|
15074
15142
|
if (err.code === "ENOENT") return [];
|
|
15075
15143
|
throw err;
|
|
@@ -15261,10 +15329,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15261
15329
|
const memories = raw.map((m) => {
|
|
15262
15330
|
if (!m || typeof m !== "object") return null;
|
|
15263
15331
|
const rec = m;
|
|
15264
|
-
const
|
|
15332
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15265
15333
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15266
|
-
if (!
|
|
15267
|
-
const entry = { path:
|
|
15334
|
+
if (!path18 || content == null) return null;
|
|
15335
|
+
const entry = { path: path18, content };
|
|
15268
15336
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
15269
15337
|
return entry;
|
|
15270
15338
|
}).filter((m) => m !== null);
|
|
@@ -15300,8 +15368,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
15300
15368
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
15301
15369
|
if (backupFileName === null) return null;
|
|
15302
15370
|
try {
|
|
15303
|
-
return
|
|
15304
|
-
|
|
15371
|
+
return import_node_fs6.default.readFileSync(
|
|
15372
|
+
import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
15305
15373
|
"utf8"
|
|
15306
15374
|
);
|
|
15307
15375
|
} catch {
|
|
@@ -15310,7 +15378,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
15310
15378
|
}
|
|
15311
15379
|
function readCurrentContent(filePath) {
|
|
15312
15380
|
try {
|
|
15313
|
-
return
|
|
15381
|
+
return import_node_fs6.default.readFileSync(filePath, "utf8");
|
|
15314
15382
|
} catch (err) {
|
|
15315
15383
|
if (err.code === "ENOENT") return null;
|
|
15316
15384
|
return null;
|
|
@@ -15322,14 +15390,14 @@ var ClaudeHistoryReader = class {
|
|
|
15322
15390
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
15323
15391
|
fileHistoryRoot;
|
|
15324
15392
|
constructor(opts = {}) {
|
|
15325
|
-
const base = opts.baseDir ??
|
|
15326
|
-
this.projectsRoot =
|
|
15327
|
-
this.fileHistoryRoot =
|
|
15393
|
+
const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
|
|
15394
|
+
this.projectsRoot = import_node_path5.default.join(base, "projects");
|
|
15395
|
+
this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
|
|
15328
15396
|
}
|
|
15329
15397
|
async listProjects() {
|
|
15330
15398
|
let entries;
|
|
15331
15399
|
try {
|
|
15332
|
-
entries =
|
|
15400
|
+
entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
15333
15401
|
} catch (err) {
|
|
15334
15402
|
if (err.code === "ENOENT") return [];
|
|
15335
15403
|
throw err;
|
|
@@ -15337,9 +15405,9 @@ var ClaudeHistoryReader = class {
|
|
|
15337
15405
|
const out = [];
|
|
15338
15406
|
for (const ent of entries) {
|
|
15339
15407
|
if (!ent.isDirectory()) continue;
|
|
15340
|
-
const dir =
|
|
15341
|
-
const files =
|
|
15342
|
-
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(
|
|
15408
|
+
const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
|
|
15409
|
+
const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15410
|
+
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
|
|
15343
15411
|
out.push({
|
|
15344
15412
|
projectPath: hashDirToCwd(ent.name),
|
|
15345
15413
|
hashDir: ent.name,
|
|
@@ -15351,17 +15419,17 @@ var ClaudeHistoryReader = class {
|
|
|
15351
15419
|
return out;
|
|
15352
15420
|
}
|
|
15353
15421
|
async listSessions(args) {
|
|
15354
|
-
const dir =
|
|
15422
|
+
const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
15355
15423
|
let files;
|
|
15356
15424
|
try {
|
|
15357
|
-
files =
|
|
15425
|
+
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15358
15426
|
} catch (err) {
|
|
15359
15427
|
if (err.code === "ENOENT") return [];
|
|
15360
15428
|
throw err;
|
|
15361
15429
|
}
|
|
15362
15430
|
const out = [];
|
|
15363
15431
|
for (const f of files) {
|
|
15364
|
-
const full =
|
|
15432
|
+
const full = import_node_path5.default.join(dir, f);
|
|
15365
15433
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
15366
15434
|
const lines = readJsonlLines(full);
|
|
15367
15435
|
let summary = "";
|
|
@@ -15416,7 +15484,7 @@ var ClaudeHistoryReader = class {
|
|
|
15416
15484
|
return out;
|
|
15417
15485
|
}
|
|
15418
15486
|
async read(args) {
|
|
15419
|
-
const file =
|
|
15487
|
+
const file = import_node_path5.default.join(
|
|
15420
15488
|
this.projectsRoot,
|
|
15421
15489
|
cwdToHashDir(args.cwd),
|
|
15422
15490
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15449,7 +15517,7 @@ var ClaudeHistoryReader = class {
|
|
|
15449
15517
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
15450
15518
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
15451
15519
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
15452
|
-
const dir =
|
|
15520
|
+
const dir = import_node_path5.default.join(
|
|
15453
15521
|
this.projectsRoot,
|
|
15454
15522
|
cwdToHashDir(cwd),
|
|
15455
15523
|
toolSessionId,
|
|
@@ -15457,7 +15525,7 @@ var ClaudeHistoryReader = class {
|
|
|
15457
15525
|
);
|
|
15458
15526
|
let entries;
|
|
15459
15527
|
try {
|
|
15460
|
-
entries =
|
|
15528
|
+
entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
|
|
15461
15529
|
} catch (err) {
|
|
15462
15530
|
if (err.code === "ENOENT") return null;
|
|
15463
15531
|
return null;
|
|
@@ -15467,7 +15535,7 @@ var ClaudeHistoryReader = class {
|
|
|
15467
15535
|
if (!e.isFile()) continue;
|
|
15468
15536
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
15469
15537
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
15470
|
-
const filePath =
|
|
15538
|
+
const filePath = import_node_path5.default.join(dir, e.name);
|
|
15471
15539
|
const lines = readJsonlLines(filePath);
|
|
15472
15540
|
let firstText = "";
|
|
15473
15541
|
let messageCount = 0;
|
|
@@ -15484,7 +15552,7 @@ var ClaudeHistoryReader = class {
|
|
|
15484
15552
|
return out;
|
|
15485
15553
|
}
|
|
15486
15554
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
15487
|
-
const file =
|
|
15555
|
+
const file = import_node_path5.default.join(
|
|
15488
15556
|
this.projectsRoot,
|
|
15489
15557
|
cwdToHashDir(cwd),
|
|
15490
15558
|
`${toolSessionId}.jsonl`
|
|
@@ -15519,7 +15587,7 @@ var ClaudeHistoryReader = class {
|
|
|
15519
15587
|
}
|
|
15520
15588
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
15521
15589
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
15522
|
-
const file =
|
|
15590
|
+
const file = import_node_path5.default.join(
|
|
15523
15591
|
this.projectsRoot,
|
|
15524
15592
|
cwdToHashDir(cwd),
|
|
15525
15593
|
toolSessionId,
|
|
@@ -15528,7 +15596,7 @@ var ClaudeHistoryReader = class {
|
|
|
15528
15596
|
);
|
|
15529
15597
|
let exists = false;
|
|
15530
15598
|
try {
|
|
15531
|
-
exists =
|
|
15599
|
+
exists = import_node_fs6.default.statSync(file).isFile();
|
|
15532
15600
|
} catch {
|
|
15533
15601
|
return null;
|
|
15534
15602
|
}
|
|
@@ -15547,7 +15615,7 @@ var ClaudeHistoryReader = class {
|
|
|
15547
15615
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
15548
15616
|
*/
|
|
15549
15617
|
readFileHistorySnapshots(args) {
|
|
15550
|
-
const file =
|
|
15618
|
+
const file = import_node_path5.default.join(
|
|
15551
15619
|
this.projectsRoot,
|
|
15552
15620
|
cwdToHashDir(args.cwd),
|
|
15553
15621
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15592,7 +15660,7 @@ var ClaudeHistoryReader = class {
|
|
|
15592
15660
|
for (const [anchorId, target] of snapshots) {
|
|
15593
15661
|
let hasAny = false;
|
|
15594
15662
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15595
|
-
const absPath =
|
|
15663
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15596
15664
|
const backupContent = readBackupContent(
|
|
15597
15665
|
this.fileHistoryRoot,
|
|
15598
15666
|
args.toolSessionId,
|
|
@@ -15632,7 +15700,7 @@ var ClaudeHistoryReader = class {
|
|
|
15632
15700
|
let totalInsertions = 0;
|
|
15633
15701
|
let totalDeletions = 0;
|
|
15634
15702
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15635
|
-
const absPath =
|
|
15703
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15636
15704
|
const backupContent = readBackupContent(
|
|
15637
15705
|
this.fileHistoryRoot,
|
|
15638
15706
|
args.toolSessionId,
|
|
@@ -15679,7 +15747,7 @@ var ClaudeHistoryReader = class {
|
|
|
15679
15747
|
};
|
|
15680
15748
|
}
|
|
15681
15749
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
15682
|
-
const file =
|
|
15750
|
+
const file = import_node_path5.default.join(
|
|
15683
15751
|
this.projectsRoot,
|
|
15684
15752
|
cwdToHashDir(cwd),
|
|
15685
15753
|
`${toolSessionId}.jsonl`
|
|
@@ -15701,27 +15769,27 @@ var ClaudeHistoryReader = class {
|
|
|
15701
15769
|
// src/tools/claude.ts
|
|
15702
15770
|
function macOSDesktopCandidates(home) {
|
|
15703
15771
|
return [
|
|
15704
|
-
|
|
15772
|
+
import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
15705
15773
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
15706
15774
|
];
|
|
15707
15775
|
}
|
|
15708
15776
|
function probeViaWhich() {
|
|
15709
15777
|
try {
|
|
15710
15778
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
15711
|
-
if (out &&
|
|
15779
|
+
if (out && import_node_fs7.default.existsSync(out)) return out;
|
|
15712
15780
|
} catch {
|
|
15713
15781
|
}
|
|
15714
15782
|
return null;
|
|
15715
15783
|
}
|
|
15716
15784
|
async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
|
|
15717
|
-
if (env.CLAUDE_BIN &&
|
|
15785
|
+
if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
|
|
15718
15786
|
return { available: true, path: env.CLAUDE_BIN };
|
|
15719
15787
|
}
|
|
15720
15788
|
const w = probeViaWhich();
|
|
15721
15789
|
if (w) return { available: true, path: w };
|
|
15722
15790
|
if (process.platform === "darwin") {
|
|
15723
15791
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
15724
|
-
if (
|
|
15792
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15725
15793
|
return { available: true, path: candidate };
|
|
15726
15794
|
}
|
|
15727
15795
|
}
|
|
@@ -16032,10 +16100,10 @@ function parseAttachment(obj) {
|
|
|
16032
16100
|
const memories = raw.map((m) => {
|
|
16033
16101
|
if (!m || typeof m !== "object") return null;
|
|
16034
16102
|
const rec = m;
|
|
16035
|
-
const
|
|
16103
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
16036
16104
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
16037
|
-
if (!
|
|
16038
|
-
const out = { path:
|
|
16105
|
+
if (!path18 || content == null) return null;
|
|
16106
|
+
const out = { path: path18, content };
|
|
16039
16107
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
16040
16108
|
return out;
|
|
16041
16109
|
}).filter((m) => m !== null);
|
|
@@ -16263,22 +16331,22 @@ var ClaudeAdapter = class {
|
|
|
16263
16331
|
};
|
|
16264
16332
|
|
|
16265
16333
|
// src/workspace/browser.ts
|
|
16266
|
-
var
|
|
16334
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
16267
16335
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
16268
|
-
var
|
|
16336
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
16269
16337
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
16270
16338
|
function resolveInsideCwd(cwd, subpath) {
|
|
16271
|
-
const absCwd =
|
|
16272
|
-
const joined =
|
|
16273
|
-
const rel =
|
|
16274
|
-
if (rel.startsWith("..") ||
|
|
16339
|
+
const absCwd = import_node_path7.default.resolve(cwd);
|
|
16340
|
+
const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
|
|
16341
|
+
const rel = import_node_path7.default.relative(absCwd, joined);
|
|
16342
|
+
if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
|
|
16275
16343
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
16276
16344
|
}
|
|
16277
16345
|
return joined;
|
|
16278
16346
|
}
|
|
16279
16347
|
function ensureCwd(cwd) {
|
|
16280
16348
|
try {
|
|
16281
|
-
const stat =
|
|
16349
|
+
const stat = import_node_fs8.default.statSync(cwd);
|
|
16282
16350
|
if (!stat.isDirectory()) {
|
|
16283
16351
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
16284
16352
|
}
|
|
@@ -16292,7 +16360,7 @@ var WorkspaceBrowser = class {
|
|
|
16292
16360
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
|
|
16293
16361
|
ensureCwd(cwd);
|
|
16294
16362
|
const full = resolveInsideCwd(cwd, args.path);
|
|
16295
|
-
const dirents =
|
|
16363
|
+
const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
|
|
16296
16364
|
const entries = [];
|
|
16297
16365
|
for (const d of dirents) {
|
|
16298
16366
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -16302,7 +16370,7 @@ var WorkspaceBrowser = class {
|
|
|
16302
16370
|
mtime: ""
|
|
16303
16371
|
};
|
|
16304
16372
|
try {
|
|
16305
|
-
const st =
|
|
16373
|
+
const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
|
|
16306
16374
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
16307
16375
|
if (d.isFile()) entry.size = st.size;
|
|
16308
16376
|
} catch {
|
|
@@ -16318,14 +16386,14 @@ var WorkspaceBrowser = class {
|
|
|
16318
16386
|
read(args) {
|
|
16319
16387
|
ensureCwd(args.cwd);
|
|
16320
16388
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
16321
|
-
const st =
|
|
16389
|
+
const st = import_node_fs8.default.statSync(full);
|
|
16322
16390
|
if (!st.isFile()) {
|
|
16323
16391
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
16324
16392
|
}
|
|
16325
16393
|
if (st.size > MAX_FILE_BYTES) {
|
|
16326
16394
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
16327
16395
|
}
|
|
16328
|
-
const buf =
|
|
16396
|
+
const buf = import_node_fs8.default.readFileSync(full);
|
|
16329
16397
|
const isBinary = buf.includes(0);
|
|
16330
16398
|
if (isBinary) {
|
|
16331
16399
|
return {
|
|
@@ -16347,9 +16415,9 @@ var WorkspaceBrowser = class {
|
|
|
16347
16415
|
};
|
|
16348
16416
|
|
|
16349
16417
|
// src/skills/scanner.ts
|
|
16350
|
-
var
|
|
16418
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
16351
16419
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
16352
|
-
var
|
|
16420
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
16353
16421
|
function parseFrontmatter(content) {
|
|
16354
16422
|
if (!content.startsWith("---")) return { name: "", description: "" };
|
|
16355
16423
|
const end = content.indexOf("---", 3);
|
|
@@ -16385,7 +16453,7 @@ function parseFrontmatter(content) {
|
|
|
16385
16453
|
}
|
|
16386
16454
|
function isDirLikeSync(p) {
|
|
16387
16455
|
try {
|
|
16388
|
-
return
|
|
16456
|
+
return import_node_fs9.default.statSync(p).isDirectory();
|
|
16389
16457
|
} catch {
|
|
16390
16458
|
return false;
|
|
16391
16459
|
}
|
|
@@ -16393,19 +16461,19 @@ function isDirLikeSync(p) {
|
|
|
16393
16461
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
16394
16462
|
let entries;
|
|
16395
16463
|
try {
|
|
16396
|
-
entries =
|
|
16464
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16397
16465
|
} catch {
|
|
16398
16466
|
return;
|
|
16399
16467
|
}
|
|
16400
16468
|
for (const ent of entries) {
|
|
16401
|
-
const entryPath =
|
|
16469
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16402
16470
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
16403
16471
|
let content;
|
|
16404
16472
|
try {
|
|
16405
|
-
content =
|
|
16473
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
16406
16474
|
} catch {
|
|
16407
16475
|
try {
|
|
16408
|
-
content =
|
|
16476
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
16409
16477
|
} catch {
|
|
16410
16478
|
continue;
|
|
16411
16479
|
}
|
|
@@ -16423,26 +16491,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
16423
16491
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
16424
16492
|
let entries;
|
|
16425
16493
|
try {
|
|
16426
|
-
entries =
|
|
16494
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16427
16495
|
} catch {
|
|
16428
16496
|
return;
|
|
16429
16497
|
}
|
|
16430
16498
|
for (const ent of entries) {
|
|
16431
|
-
const entryPath =
|
|
16499
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16432
16500
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
16433
16501
|
const ns = ent.name;
|
|
16434
16502
|
let subEntries;
|
|
16435
16503
|
try {
|
|
16436
|
-
subEntries =
|
|
16504
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
16437
16505
|
} catch {
|
|
16438
16506
|
continue;
|
|
16439
16507
|
}
|
|
16440
16508
|
for (const se of subEntries) {
|
|
16441
16509
|
if (!se.name.endsWith(".md")) continue;
|
|
16442
|
-
const sePath =
|
|
16510
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
16443
16511
|
let content;
|
|
16444
16512
|
try {
|
|
16445
|
-
content =
|
|
16513
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
16446
16514
|
} catch {
|
|
16447
16515
|
continue;
|
|
16448
16516
|
}
|
|
@@ -16459,7 +16527,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16459
16527
|
} else if (ent.name.endsWith(".md")) {
|
|
16460
16528
|
let content;
|
|
16461
16529
|
try {
|
|
16462
|
-
content =
|
|
16530
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
16463
16531
|
} catch {
|
|
16464
16532
|
continue;
|
|
16465
16533
|
}
|
|
@@ -16475,10 +16543,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16475
16543
|
}
|
|
16476
16544
|
}
|
|
16477
16545
|
function readInstalledPlugins(home) {
|
|
16478
|
-
const file =
|
|
16546
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
16479
16547
|
let raw;
|
|
16480
16548
|
try {
|
|
16481
|
-
raw =
|
|
16549
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
16482
16550
|
} catch {
|
|
16483
16551
|
return [];
|
|
16484
16552
|
}
|
|
@@ -16516,14 +16584,14 @@ var SkillsScanner = class {
|
|
|
16516
16584
|
list(args) {
|
|
16517
16585
|
const seen = /* @__PURE__ */ new Set();
|
|
16518
16586
|
const out = [];
|
|
16519
|
-
scanSkillDir(
|
|
16520
|
-
scanCommandDir(
|
|
16521
|
-
scanSkillDir(
|
|
16522
|
-
scanCommandDir(
|
|
16587
|
+
scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
|
|
16588
|
+
scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
|
|
16589
|
+
scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
|
|
16590
|
+
scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
|
|
16523
16591
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
16524
16592
|
for (const { name, root } of plugins) {
|
|
16525
|
-
scanSkillDir(
|
|
16526
|
-
scanCommandDir(
|
|
16593
|
+
scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
|
|
16594
|
+
scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
|
|
16527
16595
|
}
|
|
16528
16596
|
out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
16529
16597
|
return out;
|
|
@@ -16531,9 +16599,9 @@ var SkillsScanner = class {
|
|
|
16531
16599
|
};
|
|
16532
16600
|
|
|
16533
16601
|
// src/observer/session-observer.ts
|
|
16534
|
-
var
|
|
16602
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
16535
16603
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
16536
|
-
var
|
|
16604
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
16537
16605
|
var SessionObserver = class {
|
|
16538
16606
|
constructor(opts) {
|
|
16539
16607
|
this.opts = opts;
|
|
@@ -16544,14 +16612,14 @@ var SessionObserver = class {
|
|
|
16544
16612
|
watches = /* @__PURE__ */ new Map();
|
|
16545
16613
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
16546
16614
|
if (override) return override;
|
|
16547
|
-
return
|
|
16615
|
+
return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
16548
16616
|
}
|
|
16549
16617
|
start(args) {
|
|
16550
16618
|
this.stop(args.sessionId);
|
|
16551
16619
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
16552
16620
|
let size = 0;
|
|
16553
16621
|
try {
|
|
16554
|
-
size =
|
|
16622
|
+
size = import_node_fs10.default.statSync(filePath).size;
|
|
16555
16623
|
} catch {
|
|
16556
16624
|
}
|
|
16557
16625
|
const w = {
|
|
@@ -16564,10 +16632,10 @@ var SessionObserver = class {
|
|
|
16564
16632
|
adapter: args.adapter
|
|
16565
16633
|
};
|
|
16566
16634
|
try {
|
|
16567
|
-
|
|
16635
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
|
|
16568
16636
|
} catch {
|
|
16569
16637
|
}
|
|
16570
|
-
w.watcher =
|
|
16638
|
+
w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
16571
16639
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
16572
16640
|
this.poll(w);
|
|
16573
16641
|
});
|
|
@@ -16582,7 +16650,7 @@ var SessionObserver = class {
|
|
|
16582
16650
|
// reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
|
|
16583
16651
|
hydrateMetaTail(w, maxLines = 200) {
|
|
16584
16652
|
try {
|
|
16585
|
-
const raw =
|
|
16653
|
+
const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
|
|
16586
16654
|
if (!raw) return;
|
|
16587
16655
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
16588
16656
|
if (allLines.length === 0) return;
|
|
@@ -16603,7 +16671,7 @@ var SessionObserver = class {
|
|
|
16603
16671
|
poll(w) {
|
|
16604
16672
|
let size = 0;
|
|
16605
16673
|
try {
|
|
16606
|
-
size =
|
|
16674
|
+
size = import_node_fs10.default.statSync(w.filePath).size;
|
|
16607
16675
|
} catch {
|
|
16608
16676
|
return;
|
|
16609
16677
|
}
|
|
@@ -16612,11 +16680,11 @@ var SessionObserver = class {
|
|
|
16612
16680
|
w.buf = "";
|
|
16613
16681
|
}
|
|
16614
16682
|
if (size === w.lastSize) return;
|
|
16615
|
-
const fd =
|
|
16683
|
+
const fd = import_node_fs10.default.openSync(w.filePath, "r");
|
|
16616
16684
|
try {
|
|
16617
16685
|
const len = size - w.lastSize;
|
|
16618
16686
|
const buf = Buffer.alloc(len);
|
|
16619
|
-
|
|
16687
|
+
import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
|
|
16620
16688
|
w.lastSize = size;
|
|
16621
16689
|
w.buf += buf.toString("utf8");
|
|
16622
16690
|
let newlineIndex;
|
|
@@ -16630,7 +16698,7 @@ var SessionObserver = class {
|
|
|
16630
16698
|
this.maybeReportUserMessage(w.sessionId, line);
|
|
16631
16699
|
}
|
|
16632
16700
|
} finally {
|
|
16633
|
-
|
|
16701
|
+
import_node_fs10.default.closeSync(fd);
|
|
16634
16702
|
}
|
|
16635
16703
|
}
|
|
16636
16704
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -17045,10 +17113,10 @@ function isLocalhost(addr) {
|
|
|
17045
17113
|
}
|
|
17046
17114
|
|
|
17047
17115
|
// src/discovery/state-file.ts
|
|
17048
|
-
var
|
|
17049
|
-
var
|
|
17116
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
17117
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
17050
17118
|
function defaultStateFilePath(dataDir) {
|
|
17051
|
-
return
|
|
17119
|
+
return import_node_path10.default.join(dataDir, "state.json");
|
|
17052
17120
|
}
|
|
17053
17121
|
function isPidAlive(pid) {
|
|
17054
17122
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -17070,7 +17138,7 @@ var StateFileManager = class {
|
|
|
17070
17138
|
}
|
|
17071
17139
|
read() {
|
|
17072
17140
|
try {
|
|
17073
|
-
const raw =
|
|
17141
|
+
const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
|
|
17074
17142
|
const parsed = JSON.parse(raw);
|
|
17075
17143
|
return parsed;
|
|
17076
17144
|
} catch {
|
|
@@ -17084,34 +17152,34 @@ var StateFileManager = class {
|
|
|
17084
17152
|
return { status: "stale", existing };
|
|
17085
17153
|
}
|
|
17086
17154
|
write(state) {
|
|
17087
|
-
|
|
17155
|
+
import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
|
|
17088
17156
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
17089
|
-
|
|
17090
|
-
|
|
17157
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
17158
|
+
import_node_fs11.default.renameSync(tmp, this.file);
|
|
17091
17159
|
if (process.platform !== "win32") {
|
|
17092
17160
|
try {
|
|
17093
|
-
|
|
17161
|
+
import_node_fs11.default.chmodSync(this.file, 384);
|
|
17094
17162
|
} catch {
|
|
17095
17163
|
}
|
|
17096
17164
|
}
|
|
17097
17165
|
}
|
|
17098
17166
|
delete() {
|
|
17099
17167
|
try {
|
|
17100
|
-
|
|
17168
|
+
import_node_fs11.default.unlinkSync(this.file);
|
|
17101
17169
|
} catch {
|
|
17102
17170
|
}
|
|
17103
17171
|
}
|
|
17104
17172
|
};
|
|
17105
17173
|
|
|
17106
17174
|
// src/tunnel/tunnel-manager.ts
|
|
17107
|
-
var
|
|
17108
|
-
var
|
|
17175
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
17176
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
17109
17177
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
17110
17178
|
var import_node_child_process4 = require("child_process");
|
|
17111
17179
|
|
|
17112
17180
|
// src/tunnel/tunnel-store.ts
|
|
17113
|
-
var
|
|
17114
|
-
var
|
|
17181
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
17182
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
17115
17183
|
var TunnelStore = class {
|
|
17116
17184
|
constructor(filePath) {
|
|
17117
17185
|
this.filePath = filePath;
|
|
@@ -17119,7 +17187,7 @@ var TunnelStore = class {
|
|
|
17119
17187
|
filePath;
|
|
17120
17188
|
async get() {
|
|
17121
17189
|
try {
|
|
17122
|
-
const raw = await
|
|
17190
|
+
const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
|
|
17123
17191
|
const obj = JSON.parse(raw);
|
|
17124
17192
|
if (!isPersistedTunnel(obj)) return null;
|
|
17125
17193
|
return obj;
|
|
@@ -17130,22 +17198,22 @@ var TunnelStore = class {
|
|
|
17130
17198
|
}
|
|
17131
17199
|
}
|
|
17132
17200
|
async set(v) {
|
|
17133
|
-
const dir =
|
|
17134
|
-
await
|
|
17201
|
+
const dir = import_node_path11.default.dirname(this.filePath);
|
|
17202
|
+
await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
|
|
17135
17203
|
const data = JSON.stringify(v, null, 2);
|
|
17136
17204
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
17137
|
-
await
|
|
17205
|
+
await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
17138
17206
|
if (process.platform !== "win32") {
|
|
17139
17207
|
try {
|
|
17140
|
-
await
|
|
17208
|
+
await import_node_fs12.default.promises.chmod(tmp, 384);
|
|
17141
17209
|
} catch {
|
|
17142
17210
|
}
|
|
17143
17211
|
}
|
|
17144
|
-
await
|
|
17212
|
+
await import_node_fs12.default.promises.rename(tmp, this.filePath);
|
|
17145
17213
|
}
|
|
17146
17214
|
async clear() {
|
|
17147
17215
|
try {
|
|
17148
|
-
await
|
|
17216
|
+
await import_node_fs12.default.promises.unlink(this.filePath);
|
|
17149
17217
|
} catch (err) {
|
|
17150
17218
|
const code = err?.code;
|
|
17151
17219
|
if (code !== "ENOENT") throw err;
|
|
@@ -17240,9 +17308,9 @@ function escape(v) {
|
|
|
17240
17308
|
}
|
|
17241
17309
|
|
|
17242
17310
|
// src/tunnel/frpc-binary.ts
|
|
17243
|
-
var
|
|
17311
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
17244
17312
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
17245
|
-
var
|
|
17313
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
17246
17314
|
var import_node_child_process3 = require("child_process");
|
|
17247
17315
|
var import_node_stream = require("stream");
|
|
17248
17316
|
var import_promises = require("stream/promises");
|
|
@@ -17274,20 +17342,20 @@ function frpcDownloadUrl(version2, p) {
|
|
|
17274
17342
|
}
|
|
17275
17343
|
async function ensureFrpcBinary(opts) {
|
|
17276
17344
|
if (opts.override) {
|
|
17277
|
-
if (!
|
|
17345
|
+
if (!import_node_fs13.default.existsSync(opts.override)) {
|
|
17278
17346
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
17279
17347
|
}
|
|
17280
17348
|
return opts.override;
|
|
17281
17349
|
}
|
|
17282
17350
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
17283
17351
|
const platform = opts.platform ?? detectPlatform();
|
|
17284
|
-
const binDir =
|
|
17285
|
-
|
|
17352
|
+
const binDir = import_node_path12.default.join(opts.dataDir, "bin");
|
|
17353
|
+
import_node_fs13.default.mkdirSync(binDir, { recursive: true });
|
|
17286
17354
|
cleanupStaleArtifacts(binDir);
|
|
17287
|
-
const stableBin =
|
|
17288
|
-
if (
|
|
17355
|
+
const stableBin = import_node_path12.default.join(binDir, "frpc");
|
|
17356
|
+
if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
|
|
17289
17357
|
const partialBin = `${stableBin}.partial`;
|
|
17290
|
-
const tarballPath =
|
|
17358
|
+
const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
17291
17359
|
try {
|
|
17292
17360
|
const url = frpcDownloadUrl(version2, platform);
|
|
17293
17361
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -17296,8 +17364,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
17296
17364
|
} else {
|
|
17297
17365
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
17298
17366
|
}
|
|
17299
|
-
|
|
17300
|
-
|
|
17367
|
+
import_node_fs13.default.chmodSync(partialBin, 493);
|
|
17368
|
+
import_node_fs13.default.renameSync(partialBin, stableBin);
|
|
17301
17369
|
} finally {
|
|
17302
17370
|
safeUnlink(tarballPath);
|
|
17303
17371
|
safeUnlink(partialBin);
|
|
@@ -17307,15 +17375,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
17307
17375
|
function cleanupStaleArtifacts(binDir) {
|
|
17308
17376
|
let entries;
|
|
17309
17377
|
try {
|
|
17310
|
-
entries =
|
|
17378
|
+
entries = import_node_fs13.default.readdirSync(binDir);
|
|
17311
17379
|
} catch {
|
|
17312
17380
|
return;
|
|
17313
17381
|
}
|
|
17314
17382
|
for (const name of entries) {
|
|
17315
17383
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
17316
|
-
const full =
|
|
17384
|
+
const full = import_node_path12.default.join(binDir, name);
|
|
17317
17385
|
try {
|
|
17318
|
-
|
|
17386
|
+
import_node_fs13.default.rmSync(full, { recursive: true, force: true });
|
|
17319
17387
|
} catch {
|
|
17320
17388
|
}
|
|
17321
17389
|
}
|
|
@@ -17323,7 +17391,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
17323
17391
|
}
|
|
17324
17392
|
function safeUnlink(p) {
|
|
17325
17393
|
try {
|
|
17326
|
-
|
|
17394
|
+
import_node_fs13.default.unlinkSync(p);
|
|
17327
17395
|
} catch {
|
|
17328
17396
|
}
|
|
17329
17397
|
}
|
|
@@ -17334,13 +17402,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
17334
17402
|
if (!res.ok || !res.body) {
|
|
17335
17403
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
17336
17404
|
}
|
|
17337
|
-
const out =
|
|
17405
|
+
const out = import_node_fs13.default.createWriteStream(dest);
|
|
17338
17406
|
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
17339
17407
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
17340
17408
|
}
|
|
17341
17409
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
17342
|
-
const work =
|
|
17343
|
-
|
|
17410
|
+
const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
17411
|
+
import_node_fs13.default.mkdirSync(work, { recursive: true });
|
|
17344
17412
|
try {
|
|
17345
17413
|
await new Promise((resolve, reject) => {
|
|
17346
17414
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -17348,13 +17416,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
17348
17416
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
17349
17417
|
});
|
|
17350
17418
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
17351
|
-
const src =
|
|
17352
|
-
if (!
|
|
17419
|
+
const src = import_node_path12.default.join(work, dirName, "frpc");
|
|
17420
|
+
if (!import_node_fs13.default.existsSync(src)) {
|
|
17353
17421
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
17354
17422
|
}
|
|
17355
|
-
|
|
17423
|
+
import_node_fs13.default.copyFileSync(src, destBin);
|
|
17356
17424
|
} finally {
|
|
17357
|
-
|
|
17425
|
+
import_node_fs13.default.rmSync(work, { recursive: true, force: true });
|
|
17358
17426
|
}
|
|
17359
17427
|
}
|
|
17360
17428
|
|
|
@@ -17363,7 +17431,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
17363
17431
|
var TunnelManager = class {
|
|
17364
17432
|
constructor(deps) {
|
|
17365
17433
|
this.deps = deps;
|
|
17366
|
-
this.store = deps.store ?? new TunnelStore(
|
|
17434
|
+
this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
|
|
17367
17435
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
17368
17436
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
17369
17437
|
}
|
|
@@ -17480,7 +17548,7 @@ var TunnelManager = class {
|
|
|
17480
17548
|
dataDir: this.deps.dataDir,
|
|
17481
17549
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
17482
17550
|
});
|
|
17483
|
-
const tomlPath =
|
|
17551
|
+
const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
|
|
17484
17552
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
|
|
17485
17553
|
const toml = buildFrpcToml({
|
|
17486
17554
|
serverAddr: t.frpsHost,
|
|
@@ -17491,12 +17559,12 @@ var TunnelManager = class {
|
|
|
17491
17559
|
localPort,
|
|
17492
17560
|
logLevel: "info"
|
|
17493
17561
|
});
|
|
17494
|
-
await
|
|
17562
|
+
await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
17495
17563
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
17496
17564
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17497
17565
|
});
|
|
17498
|
-
const logFilePath =
|
|
17499
|
-
const logStream =
|
|
17566
|
+
const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
|
|
17567
|
+
const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
17500
17568
|
logStream.on("error", () => {
|
|
17501
17569
|
});
|
|
17502
17570
|
const tee = (chunk) => {
|
|
@@ -17588,12 +17656,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
17588
17656
|
}
|
|
17589
17657
|
|
|
17590
17658
|
// src/auth-store.ts
|
|
17591
|
-
var
|
|
17592
|
-
var
|
|
17659
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
17660
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
17593
17661
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
17594
17662
|
var AUTH_FILE_NAME = "auth.json";
|
|
17595
17663
|
function authFilePath(dataDir) {
|
|
17596
|
-
return
|
|
17664
|
+
return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
|
|
17597
17665
|
}
|
|
17598
17666
|
function loadOrCreateAuthToken(opts) {
|
|
17599
17667
|
const file = authFilePath(opts.dataDir);
|
|
@@ -17609,7 +17677,7 @@ function defaultGenerate() {
|
|
|
17609
17677
|
}
|
|
17610
17678
|
function readAuthFile(file) {
|
|
17611
17679
|
try {
|
|
17612
|
-
const raw =
|
|
17680
|
+
const raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
17613
17681
|
const parsed = JSON.parse(raw);
|
|
17614
17682
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
17615
17683
|
return {
|
|
@@ -17625,20 +17693,20 @@ function readAuthFile(file) {
|
|
|
17625
17693
|
}
|
|
17626
17694
|
}
|
|
17627
17695
|
function writeAuthFile(file, content) {
|
|
17628
|
-
|
|
17629
|
-
|
|
17696
|
+
import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
|
|
17697
|
+
import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
17630
17698
|
try {
|
|
17631
|
-
|
|
17699
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
17632
17700
|
} catch {
|
|
17633
17701
|
}
|
|
17634
17702
|
}
|
|
17635
17703
|
|
|
17636
17704
|
// src/session/fork.ts
|
|
17637
|
-
var
|
|
17705
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
17638
17706
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
17639
|
-
var
|
|
17707
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
17640
17708
|
function readJsonlEntries(file) {
|
|
17641
|
-
const raw =
|
|
17709
|
+
const raw = import_node_fs16.default.readFileSync(file, "utf8");
|
|
17642
17710
|
const out = [];
|
|
17643
17711
|
for (const line of raw.split("\n")) {
|
|
17644
17712
|
const t = line.trim();
|
|
@@ -17651,10 +17719,10 @@ function readJsonlEntries(file) {
|
|
|
17651
17719
|
return out;
|
|
17652
17720
|
}
|
|
17653
17721
|
function forkSession(input) {
|
|
17654
|
-
const baseDir = input.baseDir ??
|
|
17655
|
-
const projectDir =
|
|
17656
|
-
const sourceFile =
|
|
17657
|
-
if (!
|
|
17722
|
+
const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
|
|
17723
|
+
const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
17724
|
+
const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
17725
|
+
if (!import_node_fs16.default.existsSync(sourceFile)) {
|
|
17658
17726
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
17659
17727
|
}
|
|
17660
17728
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -17684,9 +17752,9 @@ function forkSession(input) {
|
|
|
17684
17752
|
}
|
|
17685
17753
|
forkedLines.push(JSON.stringify(forked));
|
|
17686
17754
|
}
|
|
17687
|
-
const forkedFilePath =
|
|
17688
|
-
|
|
17689
|
-
|
|
17755
|
+
const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
17756
|
+
import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
|
|
17757
|
+
import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
17690
17758
|
return { forkedToolSessionId, forkedFilePath };
|
|
17691
17759
|
}
|
|
17692
17760
|
|
|
@@ -17948,9 +18016,9 @@ function buildWorkspaceHandlers(deps) {
|
|
|
17948
18016
|
|
|
17949
18017
|
// src/workspace/git.ts
|
|
17950
18018
|
var import_node_child_process5 = require("child_process");
|
|
17951
|
-
var
|
|
18019
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
17952
18020
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
17953
|
-
var
|
|
18021
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
17954
18022
|
var import_node_util = require("util");
|
|
17955
18023
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
17956
18024
|
function formatChildProcessError(err) {
|
|
@@ -17965,9 +18033,9 @@ function formatChildProcessError(err) {
|
|
|
17965
18033
|
return e.message ?? "unknown error";
|
|
17966
18034
|
}
|
|
17967
18035
|
function normalizePath(p) {
|
|
17968
|
-
const resolved =
|
|
18036
|
+
const resolved = import_node_path16.default.resolve(p);
|
|
17969
18037
|
try {
|
|
17970
|
-
return
|
|
18038
|
+
return import_node_fs17.default.realpathSync(resolved);
|
|
17971
18039
|
} catch {
|
|
17972
18040
|
return resolved;
|
|
17973
18041
|
}
|
|
@@ -18068,13 +18136,13 @@ function flattenToDirName(branch) {
|
|
|
18068
18136
|
}
|
|
18069
18137
|
function encodeClaudeProjectDir(absPath) {
|
|
18070
18138
|
if (!absPath || typeof absPath !== "string") return "";
|
|
18071
|
-
let canonical =
|
|
18139
|
+
let canonical = import_node_path16.default.resolve(absPath);
|
|
18072
18140
|
try {
|
|
18073
|
-
canonical =
|
|
18141
|
+
canonical = import_node_fs17.default.realpathSync(canonical);
|
|
18074
18142
|
} catch {
|
|
18075
18143
|
try {
|
|
18076
|
-
const parent =
|
|
18077
|
-
canonical =
|
|
18144
|
+
const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
|
|
18145
|
+
canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
|
|
18078
18146
|
} catch {
|
|
18079
18147
|
}
|
|
18080
18148
|
}
|
|
@@ -18098,11 +18166,11 @@ async function createWorktree(input) {
|
|
|
18098
18166
|
if (!isGitRoot) {
|
|
18099
18167
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
18100
18168
|
}
|
|
18101
|
-
const parent =
|
|
18102
|
-
if (parent === "/" || parent ===
|
|
18169
|
+
const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
|
|
18170
|
+
if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
|
|
18103
18171
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
18104
18172
|
}
|
|
18105
|
-
const worktreeRoot =
|
|
18173
|
+
const worktreeRoot = import_node_path16.default.join(parent, dirName);
|
|
18106
18174
|
try {
|
|
18107
18175
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
|
|
18108
18176
|
timeout: 3e3
|
|
@@ -18119,7 +18187,7 @@ async function createWorktree(input) {
|
|
|
18119
18187
|
const msg = err.message;
|
|
18120
18188
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
18121
18189
|
}
|
|
18122
|
-
if (
|
|
18190
|
+
if (import_node_fs17.default.existsSync(worktreeRoot)) {
|
|
18123
18191
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
18124
18192
|
}
|
|
18125
18193
|
try {
|
|
@@ -18147,8 +18215,8 @@ async function removeWorktree(input) {
|
|
|
18147
18215
|
);
|
|
18148
18216
|
const gitCommonDir = stdout.trim();
|
|
18149
18217
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
18150
|
-
const absGitCommon =
|
|
18151
|
-
repoRoot =
|
|
18218
|
+
const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
|
|
18219
|
+
repoRoot = import_node_path16.default.dirname(absGitCommon);
|
|
18152
18220
|
} catch {
|
|
18153
18221
|
repoRoot = null;
|
|
18154
18222
|
}
|
|
@@ -18160,7 +18228,7 @@ async function removeWorktree(input) {
|
|
|
18160
18228
|
} catch (err) {
|
|
18161
18229
|
const stderr = err.stderr ?? "";
|
|
18162
18230
|
const lower = stderr.toLowerCase();
|
|
18163
|
-
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !
|
|
18231
|
+
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
|
|
18164
18232
|
if (!vanished) {
|
|
18165
18233
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
18166
18234
|
}
|
|
@@ -18179,10 +18247,10 @@ async function removeWorktree(input) {
|
|
|
18179
18247
|
try {
|
|
18180
18248
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
18181
18249
|
if (encoded) {
|
|
18182
|
-
const projectsRoot =
|
|
18183
|
-
const target =
|
|
18184
|
-
if (target.startsWith(projectsRoot +
|
|
18185
|
-
|
|
18250
|
+
const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
18251
|
+
const target = import_node_path16.default.resolve(projectsRoot, encoded);
|
|
18252
|
+
if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
|
|
18253
|
+
import_node_fs17.default.rmSync(target, { recursive: true, force: true });
|
|
18186
18254
|
}
|
|
18187
18255
|
}
|
|
18188
18256
|
} catch {
|
|
@@ -18309,7 +18377,7 @@ function buildMethodHandlers(deps) {
|
|
|
18309
18377
|
async function startDaemon(config) {
|
|
18310
18378
|
const logger = createLogger({
|
|
18311
18379
|
level: config.logLevel,
|
|
18312
|
-
file:
|
|
18380
|
+
file: import_node_path17.default.join(config.dataDir, "clawd.log")
|
|
18313
18381
|
});
|
|
18314
18382
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
18315
18383
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -18349,6 +18417,7 @@ async function startDaemon(config) {
|
|
|
18349
18417
|
logger,
|
|
18350
18418
|
getAdapter,
|
|
18351
18419
|
historyReader: history,
|
|
18420
|
+
dataDir: config.dataDir,
|
|
18352
18421
|
broadcastFrame: (frame, target) => {
|
|
18353
18422
|
if (target === "all") {
|
|
18354
18423
|
transport?.broadcastAll(frame);
|
|
@@ -18471,8 +18540,8 @@ async function startDaemon(config) {
|
|
|
18471
18540
|
const lines = [
|
|
18472
18541
|
`Tunnel: ${r.url}`,
|
|
18473
18542
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
18474
|
-
`Frpc config: ${
|
|
18475
|
-
`Frpc log: ${
|
|
18543
|
+
`Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
|
|
18544
|
+
`Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
|
|
18476
18545
|
];
|
|
18477
18546
|
const width = Math.max(...lines.map((l) => l.length));
|
|
18478
18547
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -18485,8 +18554,8 @@ ${bar}
|
|
|
18485
18554
|
|
|
18486
18555
|
`);
|
|
18487
18556
|
try {
|
|
18488
|
-
const connectPath =
|
|
18489
|
-
|
|
18557
|
+
const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
|
|
18558
|
+
import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
18490
18559
|
} catch {
|
|
18491
18560
|
}
|
|
18492
18561
|
} catch (err) {
|