@clawos-dev/clawd 0.2.22 → 0.2.23-beta.33.3955675
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);
|
|
@@ -8686,8 +8686,8 @@ function getErrorMap() {
|
|
|
8686
8686
|
|
|
8687
8687
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
8688
8688
|
var makeIssue = (params) => {
|
|
8689
|
-
const { data, path:
|
|
8690
|
-
const fullPath = [...
|
|
8689
|
+
const { data, path: path18, errorMaps, issueData } = params;
|
|
8690
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
8691
8691
|
const fullIssue = {
|
|
8692
8692
|
...issueData,
|
|
8693
8693
|
path: fullPath
|
|
@@ -8803,11 +8803,11 @@ var errorUtil;
|
|
|
8803
8803
|
|
|
8804
8804
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
8805
8805
|
var ParseInputLazyPath = class {
|
|
8806
|
-
constructor(parent, value,
|
|
8806
|
+
constructor(parent, value, path18, key) {
|
|
8807
8807
|
this._cachedPath = [];
|
|
8808
8808
|
this.parent = parent;
|
|
8809
8809
|
this.data = value;
|
|
8810
|
-
this._path =
|
|
8810
|
+
this._path = path18;
|
|
8811
8811
|
this._key = key;
|
|
8812
8812
|
}
|
|
8813
8813
|
get path() {
|
|
@@ -12812,7 +12812,7 @@ var SessionStore = class {
|
|
|
12812
12812
|
};
|
|
12813
12813
|
|
|
12814
12814
|
// src/session/manager.ts
|
|
12815
|
-
var
|
|
12815
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
12816
12816
|
|
|
12817
12817
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
12818
12818
|
var byteToHex = [];
|
|
@@ -13401,6 +13401,58 @@ function reduceSession(state, input, deps) {
|
|
|
13401
13401
|
}
|
|
13402
13402
|
}
|
|
13403
13403
|
|
|
13404
|
+
// src/ipc-recorder.ts
|
|
13405
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
13406
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
13407
|
+
function tsForFilename(ms) {
|
|
13408
|
+
return new Date(ms).toISOString().replace(/[:.]/g, "-");
|
|
13409
|
+
}
|
|
13410
|
+
function startRecorder(opts) {
|
|
13411
|
+
if (opts.env.CLAWD_RECORD_IPC !== "1") return null;
|
|
13412
|
+
if (!opts.dataDir) return null;
|
|
13413
|
+
if (!opts.sessionId || opts.sessionId.includes("..") || opts.sessionId.includes("/") || opts.sessionId.includes("\\") || opts.sessionId.startsWith(".")) {
|
|
13414
|
+
return null;
|
|
13415
|
+
}
|
|
13416
|
+
const now = opts.now ?? Date.now;
|
|
13417
|
+
const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
|
|
13418
|
+
const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
|
|
13419
|
+
let stream = null;
|
|
13420
|
+
let closedResolve;
|
|
13421
|
+
const closed = new Promise((resolve) => {
|
|
13422
|
+
closedResolve = resolve;
|
|
13423
|
+
});
|
|
13424
|
+
let exited = false;
|
|
13425
|
+
const ensureStream = () => {
|
|
13426
|
+
if (stream) return stream;
|
|
13427
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
13428
|
+
stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
|
|
13429
|
+
stream.on("close", () => closedResolve());
|
|
13430
|
+
return stream;
|
|
13431
|
+
};
|
|
13432
|
+
const writeLine = (s, chunk) => {
|
|
13433
|
+
if (exited) return;
|
|
13434
|
+
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13435
|
+
const line = JSON.stringify({ ts: now(), stream: s, chunk: text }) + "\n";
|
|
13436
|
+
ensureStream().write(line);
|
|
13437
|
+
};
|
|
13438
|
+
opts.proc.stdout?.on("data", (chunk) => writeLine("stdout", chunk));
|
|
13439
|
+
opts.proc.stderr?.on("data", (chunk) => writeLine("stderr", chunk));
|
|
13440
|
+
opts.proc.on("exit", () => {
|
|
13441
|
+
exited = true;
|
|
13442
|
+
if (stream) {
|
|
13443
|
+
stream.end();
|
|
13444
|
+
} else {
|
|
13445
|
+
closedResolve();
|
|
13446
|
+
}
|
|
13447
|
+
});
|
|
13448
|
+
return {
|
|
13449
|
+
tapStdinWrite(chunk) {
|
|
13450
|
+
writeLine("stdin", chunk);
|
|
13451
|
+
},
|
|
13452
|
+
closed
|
|
13453
|
+
};
|
|
13454
|
+
}
|
|
13455
|
+
|
|
13404
13456
|
// src/session/runner.ts
|
|
13405
13457
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
13406
13458
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -13431,6 +13483,8 @@ var SessionRunner = class {
|
|
|
13431
13483
|
pendingControlRequests = /* @__PURE__ */ new Map();
|
|
13432
13484
|
// waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
|
|
13433
13485
|
stopWaiters = [];
|
|
13486
|
+
// IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
|
|
13487
|
+
recorder = null;
|
|
13434
13488
|
getState() {
|
|
13435
13489
|
return this.state;
|
|
13436
13490
|
}
|
|
@@ -13520,6 +13574,7 @@ var SessionRunner = class {
|
|
|
13520
13574
|
this.pendingControlRequests.set(requestId, { resolve, reject, timer });
|
|
13521
13575
|
try {
|
|
13522
13576
|
proc.stdin?.write(payload);
|
|
13577
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13523
13578
|
} catch (err) {
|
|
13524
13579
|
clearTimeout(timer);
|
|
13525
13580
|
this.pendingControlRequests.delete(requestId);
|
|
@@ -13575,10 +13630,14 @@ var SessionRunner = class {
|
|
|
13575
13630
|
break;
|
|
13576
13631
|
case "write-stdin":
|
|
13577
13632
|
this.proc?.stdin?.write(effect.payload);
|
|
13633
|
+
this.recorder?.tapStdinWrite(effect.payload);
|
|
13578
13634
|
break;
|
|
13579
|
-
case "send-control-response-allow-with-input":
|
|
13580
|
-
|
|
13635
|
+
case "send-control-response-allow-with-input": {
|
|
13636
|
+
const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
|
|
13637
|
+
this.proc?.stdin?.write(payload);
|
|
13638
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13581
13639
|
break;
|
|
13640
|
+
}
|
|
13582
13641
|
case "persist-file":
|
|
13583
13642
|
try {
|
|
13584
13643
|
this.hooks.store.write(effect.file);
|
|
@@ -13608,6 +13667,13 @@ var SessionRunner = class {
|
|
|
13608
13667
|
const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
|
|
13609
13668
|
this.proc = proc;
|
|
13610
13669
|
this.stdoutBuf = "";
|
|
13670
|
+
this.recorder = startRecorder({
|
|
13671
|
+
proc,
|
|
13672
|
+
sessionId: this.state.file.sessionId,
|
|
13673
|
+
dataDir: this.hooks.dataDir,
|
|
13674
|
+
env: this.hooks.recordEnv ?? process.env,
|
|
13675
|
+
now: this.hooks.now
|
|
13676
|
+
});
|
|
13611
13677
|
proc.stdout?.on("data", (chunk) => {
|
|
13612
13678
|
this.stdoutBuf += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13613
13679
|
let idx;
|
|
@@ -13624,6 +13690,7 @@ var SessionRunner = class {
|
|
|
13624
13690
|
});
|
|
13625
13691
|
proc.on("exit", (code) => {
|
|
13626
13692
|
this.proc = null;
|
|
13693
|
+
this.recorder = null;
|
|
13627
13694
|
this.rejectAllPending(new Error("session gone"));
|
|
13628
13695
|
this.input({ kind: "proc-exit", code });
|
|
13629
13696
|
});
|
|
@@ -13750,7 +13817,8 @@ var SessionManager = class {
|
|
|
13750
13817
|
now: this.deps.now,
|
|
13751
13818
|
bufferCap: this.deps.bufferCap,
|
|
13752
13819
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
13753
|
-
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
|
|
13820
|
+
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
13821
|
+
dataDir: this.deps.dataDir
|
|
13754
13822
|
});
|
|
13755
13823
|
return runner;
|
|
13756
13824
|
}
|
|
@@ -13781,7 +13849,7 @@ var SessionManager = class {
|
|
|
13781
13849
|
// ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
|
|
13782
13850
|
create(args) {
|
|
13783
13851
|
try {
|
|
13784
|
-
const stat =
|
|
13852
|
+
const stat = import_node_fs5.default.statSync(args.cwd);
|
|
13785
13853
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
13786
13854
|
} catch {
|
|
13787
13855
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
|
|
@@ -14227,14 +14295,14 @@ var SessionManager = class {
|
|
|
14227
14295
|
// src/tools/claude.ts
|
|
14228
14296
|
var import_node_child_process = require("child_process");
|
|
14229
14297
|
var import_node_child_process2 = require("child_process");
|
|
14230
|
-
var
|
|
14298
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
14231
14299
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
14232
|
-
var
|
|
14300
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
14233
14301
|
|
|
14234
14302
|
// src/tools/claude-history.ts
|
|
14235
|
-
var
|
|
14303
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
14236
14304
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
14237
|
-
var
|
|
14305
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
14238
14306
|
|
|
14239
14307
|
// ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
|
|
14240
14308
|
function Diff() {
|
|
@@ -14338,11 +14406,11 @@ Diff.prototype = {
|
|
|
14338
14406
|
}
|
|
14339
14407
|
}
|
|
14340
14408
|
},
|
|
14341
|
-
addToPath: function addToPath(
|
|
14342
|
-
var last =
|
|
14409
|
+
addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
|
|
14410
|
+
var last = path18.lastComponent;
|
|
14343
14411
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14344
14412
|
return {
|
|
14345
|
-
oldPos:
|
|
14413
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14346
14414
|
lastComponent: {
|
|
14347
14415
|
count: last.count + 1,
|
|
14348
14416
|
added,
|
|
@@ -14352,7 +14420,7 @@ Diff.prototype = {
|
|
|
14352
14420
|
};
|
|
14353
14421
|
} else {
|
|
14354
14422
|
return {
|
|
14355
|
-
oldPos:
|
|
14423
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14356
14424
|
lastComponent: {
|
|
14357
14425
|
count: 1,
|
|
14358
14426
|
added,
|
|
@@ -15011,7 +15079,7 @@ function hashDirToCwd(hash) {
|
|
|
15011
15079
|
}
|
|
15012
15080
|
function safeStatMtime(p) {
|
|
15013
15081
|
try {
|
|
15014
|
-
return
|
|
15082
|
+
return import_node_fs6.default.statSync(p).mtimeMs;
|
|
15015
15083
|
} catch {
|
|
15016
15084
|
return 0;
|
|
15017
15085
|
}
|
|
@@ -15019,7 +15087,7 @@ function safeStatMtime(p) {
|
|
|
15019
15087
|
function readJsonlLines(file) {
|
|
15020
15088
|
let raw;
|
|
15021
15089
|
try {
|
|
15022
|
-
raw =
|
|
15090
|
+
raw = import_node_fs6.default.readFileSync(file, "utf8");
|
|
15023
15091
|
} catch (err) {
|
|
15024
15092
|
if (err.code === "ENOENT") return [];
|
|
15025
15093
|
throw err;
|
|
@@ -15211,10 +15279,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15211
15279
|
const memories = raw.map((m) => {
|
|
15212
15280
|
if (!m || typeof m !== "object") return null;
|
|
15213
15281
|
const rec = m;
|
|
15214
|
-
const
|
|
15282
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15215
15283
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15216
|
-
if (!
|
|
15217
|
-
const entry = { path:
|
|
15284
|
+
if (!path18 || content == null) return null;
|
|
15285
|
+
const entry = { path: path18, content };
|
|
15218
15286
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
15219
15287
|
return entry;
|
|
15220
15288
|
}).filter((m) => m !== null);
|
|
@@ -15250,8 +15318,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
15250
15318
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
15251
15319
|
if (backupFileName === null) return null;
|
|
15252
15320
|
try {
|
|
15253
|
-
return
|
|
15254
|
-
|
|
15321
|
+
return import_node_fs6.default.readFileSync(
|
|
15322
|
+
import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
15255
15323
|
"utf8"
|
|
15256
15324
|
);
|
|
15257
15325
|
} catch {
|
|
@@ -15260,7 +15328,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
15260
15328
|
}
|
|
15261
15329
|
function readCurrentContent(filePath) {
|
|
15262
15330
|
try {
|
|
15263
|
-
return
|
|
15331
|
+
return import_node_fs6.default.readFileSync(filePath, "utf8");
|
|
15264
15332
|
} catch (err) {
|
|
15265
15333
|
if (err.code === "ENOENT") return null;
|
|
15266
15334
|
return null;
|
|
@@ -15272,14 +15340,14 @@ var ClaudeHistoryReader = class {
|
|
|
15272
15340
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
15273
15341
|
fileHistoryRoot;
|
|
15274
15342
|
constructor(opts = {}) {
|
|
15275
|
-
const base = opts.baseDir ??
|
|
15276
|
-
this.projectsRoot =
|
|
15277
|
-
this.fileHistoryRoot =
|
|
15343
|
+
const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
|
|
15344
|
+
this.projectsRoot = import_node_path5.default.join(base, "projects");
|
|
15345
|
+
this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
|
|
15278
15346
|
}
|
|
15279
15347
|
async listProjects() {
|
|
15280
15348
|
let entries;
|
|
15281
15349
|
try {
|
|
15282
|
-
entries =
|
|
15350
|
+
entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
15283
15351
|
} catch (err) {
|
|
15284
15352
|
if (err.code === "ENOENT") return [];
|
|
15285
15353
|
throw err;
|
|
@@ -15287,9 +15355,9 @@ var ClaudeHistoryReader = class {
|
|
|
15287
15355
|
const out = [];
|
|
15288
15356
|
for (const ent of entries) {
|
|
15289
15357
|
if (!ent.isDirectory()) continue;
|
|
15290
|
-
const dir =
|
|
15291
|
-
const files =
|
|
15292
|
-
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(
|
|
15358
|
+
const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
|
|
15359
|
+
const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15360
|
+
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
|
|
15293
15361
|
out.push({
|
|
15294
15362
|
projectPath: hashDirToCwd(ent.name),
|
|
15295
15363
|
hashDir: ent.name,
|
|
@@ -15301,17 +15369,17 @@ var ClaudeHistoryReader = class {
|
|
|
15301
15369
|
return out;
|
|
15302
15370
|
}
|
|
15303
15371
|
async listSessions(args) {
|
|
15304
|
-
const dir =
|
|
15372
|
+
const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
15305
15373
|
let files;
|
|
15306
15374
|
try {
|
|
15307
|
-
files =
|
|
15375
|
+
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15308
15376
|
} catch (err) {
|
|
15309
15377
|
if (err.code === "ENOENT") return [];
|
|
15310
15378
|
throw err;
|
|
15311
15379
|
}
|
|
15312
15380
|
const out = [];
|
|
15313
15381
|
for (const f of files) {
|
|
15314
|
-
const full =
|
|
15382
|
+
const full = import_node_path5.default.join(dir, f);
|
|
15315
15383
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
15316
15384
|
const lines = readJsonlLines(full);
|
|
15317
15385
|
let summary = "";
|
|
@@ -15366,7 +15434,7 @@ var ClaudeHistoryReader = class {
|
|
|
15366
15434
|
return out;
|
|
15367
15435
|
}
|
|
15368
15436
|
async read(args) {
|
|
15369
|
-
const file =
|
|
15437
|
+
const file = import_node_path5.default.join(
|
|
15370
15438
|
this.projectsRoot,
|
|
15371
15439
|
cwdToHashDir(args.cwd),
|
|
15372
15440
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15399,7 +15467,7 @@ var ClaudeHistoryReader = class {
|
|
|
15399
15467
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
15400
15468
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
15401
15469
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
15402
|
-
const dir =
|
|
15470
|
+
const dir = import_node_path5.default.join(
|
|
15403
15471
|
this.projectsRoot,
|
|
15404
15472
|
cwdToHashDir(cwd),
|
|
15405
15473
|
toolSessionId,
|
|
@@ -15407,7 +15475,7 @@ var ClaudeHistoryReader = class {
|
|
|
15407
15475
|
);
|
|
15408
15476
|
let entries;
|
|
15409
15477
|
try {
|
|
15410
|
-
entries =
|
|
15478
|
+
entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
|
|
15411
15479
|
} catch (err) {
|
|
15412
15480
|
if (err.code === "ENOENT") return null;
|
|
15413
15481
|
return null;
|
|
@@ -15417,7 +15485,7 @@ var ClaudeHistoryReader = class {
|
|
|
15417
15485
|
if (!e.isFile()) continue;
|
|
15418
15486
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
15419
15487
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
15420
|
-
const filePath =
|
|
15488
|
+
const filePath = import_node_path5.default.join(dir, e.name);
|
|
15421
15489
|
const lines = readJsonlLines(filePath);
|
|
15422
15490
|
let firstText = "";
|
|
15423
15491
|
let messageCount = 0;
|
|
@@ -15434,7 +15502,7 @@ var ClaudeHistoryReader = class {
|
|
|
15434
15502
|
return out;
|
|
15435
15503
|
}
|
|
15436
15504
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
15437
|
-
const file =
|
|
15505
|
+
const file = import_node_path5.default.join(
|
|
15438
15506
|
this.projectsRoot,
|
|
15439
15507
|
cwdToHashDir(cwd),
|
|
15440
15508
|
`${toolSessionId}.jsonl`
|
|
@@ -15469,7 +15537,7 @@ var ClaudeHistoryReader = class {
|
|
|
15469
15537
|
}
|
|
15470
15538
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
15471
15539
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
15472
|
-
const file =
|
|
15540
|
+
const file = import_node_path5.default.join(
|
|
15473
15541
|
this.projectsRoot,
|
|
15474
15542
|
cwdToHashDir(cwd),
|
|
15475
15543
|
toolSessionId,
|
|
@@ -15478,7 +15546,7 @@ var ClaudeHistoryReader = class {
|
|
|
15478
15546
|
);
|
|
15479
15547
|
let exists = false;
|
|
15480
15548
|
try {
|
|
15481
|
-
exists =
|
|
15549
|
+
exists = import_node_fs6.default.statSync(file).isFile();
|
|
15482
15550
|
} catch {
|
|
15483
15551
|
return null;
|
|
15484
15552
|
}
|
|
@@ -15497,7 +15565,7 @@ var ClaudeHistoryReader = class {
|
|
|
15497
15565
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
15498
15566
|
*/
|
|
15499
15567
|
readFileHistorySnapshots(args) {
|
|
15500
|
-
const file =
|
|
15568
|
+
const file = import_node_path5.default.join(
|
|
15501
15569
|
this.projectsRoot,
|
|
15502
15570
|
cwdToHashDir(args.cwd),
|
|
15503
15571
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15542,7 +15610,7 @@ var ClaudeHistoryReader = class {
|
|
|
15542
15610
|
for (const [anchorId, target] of snapshots) {
|
|
15543
15611
|
let hasAny = false;
|
|
15544
15612
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15545
|
-
const absPath =
|
|
15613
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15546
15614
|
const backupContent = readBackupContent(
|
|
15547
15615
|
this.fileHistoryRoot,
|
|
15548
15616
|
args.toolSessionId,
|
|
@@ -15582,7 +15650,7 @@ var ClaudeHistoryReader = class {
|
|
|
15582
15650
|
let totalInsertions = 0;
|
|
15583
15651
|
let totalDeletions = 0;
|
|
15584
15652
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15585
|
-
const absPath =
|
|
15653
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15586
15654
|
const backupContent = readBackupContent(
|
|
15587
15655
|
this.fileHistoryRoot,
|
|
15588
15656
|
args.toolSessionId,
|
|
@@ -15629,7 +15697,7 @@ var ClaudeHistoryReader = class {
|
|
|
15629
15697
|
};
|
|
15630
15698
|
}
|
|
15631
15699
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
15632
|
-
const file =
|
|
15700
|
+
const file = import_node_path5.default.join(
|
|
15633
15701
|
this.projectsRoot,
|
|
15634
15702
|
cwdToHashDir(cwd),
|
|
15635
15703
|
`${toolSessionId}.jsonl`
|
|
@@ -15651,27 +15719,27 @@ var ClaudeHistoryReader = class {
|
|
|
15651
15719
|
// src/tools/claude.ts
|
|
15652
15720
|
function macOSDesktopCandidates(home) {
|
|
15653
15721
|
return [
|
|
15654
|
-
|
|
15722
|
+
import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
15655
15723
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
15656
15724
|
];
|
|
15657
15725
|
}
|
|
15658
15726
|
function probeViaWhich() {
|
|
15659
15727
|
try {
|
|
15660
15728
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
15661
|
-
if (out &&
|
|
15729
|
+
if (out && import_node_fs7.default.existsSync(out)) return out;
|
|
15662
15730
|
} catch {
|
|
15663
15731
|
}
|
|
15664
15732
|
return null;
|
|
15665
15733
|
}
|
|
15666
15734
|
async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
|
|
15667
|
-
if (env.CLAUDE_BIN &&
|
|
15735
|
+
if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
|
|
15668
15736
|
return { available: true, path: env.CLAUDE_BIN };
|
|
15669
15737
|
}
|
|
15670
15738
|
const w = probeViaWhich();
|
|
15671
15739
|
if (w) return { available: true, path: w };
|
|
15672
15740
|
if (process.platform === "darwin") {
|
|
15673
15741
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
15674
|
-
if (
|
|
15742
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15675
15743
|
return { available: true, path: candidate };
|
|
15676
15744
|
}
|
|
15677
15745
|
}
|
|
@@ -15982,10 +16050,10 @@ function parseAttachment(obj) {
|
|
|
15982
16050
|
const memories = raw.map((m) => {
|
|
15983
16051
|
if (!m || typeof m !== "object") return null;
|
|
15984
16052
|
const rec = m;
|
|
15985
|
-
const
|
|
16053
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15986
16054
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15987
|
-
if (!
|
|
15988
|
-
const out = { path:
|
|
16055
|
+
if (!path18 || content == null) return null;
|
|
16056
|
+
const out = { path: path18, content };
|
|
15989
16057
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
15990
16058
|
return out;
|
|
15991
16059
|
}).filter((m) => m !== null);
|
|
@@ -16213,22 +16281,22 @@ var ClaudeAdapter = class {
|
|
|
16213
16281
|
};
|
|
16214
16282
|
|
|
16215
16283
|
// src/workspace/browser.ts
|
|
16216
|
-
var
|
|
16284
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
16217
16285
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
16218
|
-
var
|
|
16286
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
16219
16287
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
16220
16288
|
function resolveInsideCwd(cwd, subpath) {
|
|
16221
|
-
const absCwd =
|
|
16222
|
-
const joined =
|
|
16223
|
-
const rel =
|
|
16224
|
-
if (rel.startsWith("..") ||
|
|
16289
|
+
const absCwd = import_node_path7.default.resolve(cwd);
|
|
16290
|
+
const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
|
|
16291
|
+
const rel = import_node_path7.default.relative(absCwd, joined);
|
|
16292
|
+
if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
|
|
16225
16293
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
16226
16294
|
}
|
|
16227
16295
|
return joined;
|
|
16228
16296
|
}
|
|
16229
16297
|
function ensureCwd(cwd) {
|
|
16230
16298
|
try {
|
|
16231
|
-
const stat =
|
|
16299
|
+
const stat = import_node_fs8.default.statSync(cwd);
|
|
16232
16300
|
if (!stat.isDirectory()) {
|
|
16233
16301
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
16234
16302
|
}
|
|
@@ -16242,7 +16310,7 @@ var WorkspaceBrowser = class {
|
|
|
16242
16310
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
|
|
16243
16311
|
ensureCwd(cwd);
|
|
16244
16312
|
const full = resolveInsideCwd(cwd, args.path);
|
|
16245
|
-
const dirents =
|
|
16313
|
+
const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
|
|
16246
16314
|
const entries = [];
|
|
16247
16315
|
for (const d of dirents) {
|
|
16248
16316
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -16252,7 +16320,7 @@ var WorkspaceBrowser = class {
|
|
|
16252
16320
|
mtime: ""
|
|
16253
16321
|
};
|
|
16254
16322
|
try {
|
|
16255
|
-
const st =
|
|
16323
|
+
const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
|
|
16256
16324
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
16257
16325
|
if (d.isFile()) entry.size = st.size;
|
|
16258
16326
|
} catch {
|
|
@@ -16268,14 +16336,14 @@ var WorkspaceBrowser = class {
|
|
|
16268
16336
|
read(args) {
|
|
16269
16337
|
ensureCwd(args.cwd);
|
|
16270
16338
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
16271
|
-
const st =
|
|
16339
|
+
const st = import_node_fs8.default.statSync(full);
|
|
16272
16340
|
if (!st.isFile()) {
|
|
16273
16341
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
16274
16342
|
}
|
|
16275
16343
|
if (st.size > MAX_FILE_BYTES) {
|
|
16276
16344
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
16277
16345
|
}
|
|
16278
|
-
const buf =
|
|
16346
|
+
const buf = import_node_fs8.default.readFileSync(full);
|
|
16279
16347
|
const isBinary = buf.includes(0);
|
|
16280
16348
|
if (isBinary) {
|
|
16281
16349
|
return {
|
|
@@ -16297,9 +16365,9 @@ var WorkspaceBrowser = class {
|
|
|
16297
16365
|
};
|
|
16298
16366
|
|
|
16299
16367
|
// src/skills/scanner.ts
|
|
16300
|
-
var
|
|
16368
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
16301
16369
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
16302
|
-
var
|
|
16370
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
16303
16371
|
function parseFrontmatter(content) {
|
|
16304
16372
|
if (!content.startsWith("---")) return { name: "", description: "" };
|
|
16305
16373
|
const end = content.indexOf("---", 3);
|
|
@@ -16335,7 +16403,7 @@ function parseFrontmatter(content) {
|
|
|
16335
16403
|
}
|
|
16336
16404
|
function isDirLikeSync(p) {
|
|
16337
16405
|
try {
|
|
16338
|
-
return
|
|
16406
|
+
return import_node_fs9.default.statSync(p).isDirectory();
|
|
16339
16407
|
} catch {
|
|
16340
16408
|
return false;
|
|
16341
16409
|
}
|
|
@@ -16343,19 +16411,19 @@ function isDirLikeSync(p) {
|
|
|
16343
16411
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
16344
16412
|
let entries;
|
|
16345
16413
|
try {
|
|
16346
|
-
entries =
|
|
16414
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16347
16415
|
} catch {
|
|
16348
16416
|
return;
|
|
16349
16417
|
}
|
|
16350
16418
|
for (const ent of entries) {
|
|
16351
|
-
const entryPath =
|
|
16419
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16352
16420
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
16353
16421
|
let content;
|
|
16354
16422
|
try {
|
|
16355
|
-
content =
|
|
16423
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
16356
16424
|
} catch {
|
|
16357
16425
|
try {
|
|
16358
|
-
content =
|
|
16426
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
16359
16427
|
} catch {
|
|
16360
16428
|
continue;
|
|
16361
16429
|
}
|
|
@@ -16373,26 +16441,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
16373
16441
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
16374
16442
|
let entries;
|
|
16375
16443
|
try {
|
|
16376
|
-
entries =
|
|
16444
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16377
16445
|
} catch {
|
|
16378
16446
|
return;
|
|
16379
16447
|
}
|
|
16380
16448
|
for (const ent of entries) {
|
|
16381
|
-
const entryPath =
|
|
16449
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16382
16450
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
16383
16451
|
const ns = ent.name;
|
|
16384
16452
|
let subEntries;
|
|
16385
16453
|
try {
|
|
16386
|
-
subEntries =
|
|
16454
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
16387
16455
|
} catch {
|
|
16388
16456
|
continue;
|
|
16389
16457
|
}
|
|
16390
16458
|
for (const se of subEntries) {
|
|
16391
16459
|
if (!se.name.endsWith(".md")) continue;
|
|
16392
|
-
const sePath =
|
|
16460
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
16393
16461
|
let content;
|
|
16394
16462
|
try {
|
|
16395
|
-
content =
|
|
16463
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
16396
16464
|
} catch {
|
|
16397
16465
|
continue;
|
|
16398
16466
|
}
|
|
@@ -16409,7 +16477,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16409
16477
|
} else if (ent.name.endsWith(".md")) {
|
|
16410
16478
|
let content;
|
|
16411
16479
|
try {
|
|
16412
|
-
content =
|
|
16480
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
16413
16481
|
} catch {
|
|
16414
16482
|
continue;
|
|
16415
16483
|
}
|
|
@@ -16425,10 +16493,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16425
16493
|
}
|
|
16426
16494
|
}
|
|
16427
16495
|
function readInstalledPlugins(home) {
|
|
16428
|
-
const file =
|
|
16496
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
16429
16497
|
let raw;
|
|
16430
16498
|
try {
|
|
16431
|
-
raw =
|
|
16499
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
16432
16500
|
} catch {
|
|
16433
16501
|
return [];
|
|
16434
16502
|
}
|
|
@@ -16466,14 +16534,14 @@ var SkillsScanner = class {
|
|
|
16466
16534
|
list(args) {
|
|
16467
16535
|
const seen = /* @__PURE__ */ new Set();
|
|
16468
16536
|
const out = [];
|
|
16469
|
-
scanSkillDir(
|
|
16470
|
-
scanCommandDir(
|
|
16471
|
-
scanSkillDir(
|
|
16472
|
-
scanCommandDir(
|
|
16537
|
+
scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
|
|
16538
|
+
scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
|
|
16539
|
+
scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
|
|
16540
|
+
scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
|
|
16473
16541
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
16474
16542
|
for (const { name, root } of plugins) {
|
|
16475
|
-
scanSkillDir(
|
|
16476
|
-
scanCommandDir(
|
|
16543
|
+
scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
|
|
16544
|
+
scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
|
|
16477
16545
|
}
|
|
16478
16546
|
out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
16479
16547
|
return out;
|
|
@@ -16481,9 +16549,9 @@ var SkillsScanner = class {
|
|
|
16481
16549
|
};
|
|
16482
16550
|
|
|
16483
16551
|
// src/observer/session-observer.ts
|
|
16484
|
-
var
|
|
16552
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
16485
16553
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
16486
|
-
var
|
|
16554
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
16487
16555
|
var SessionObserver = class {
|
|
16488
16556
|
constructor(opts) {
|
|
16489
16557
|
this.opts = opts;
|
|
@@ -16494,14 +16562,14 @@ var SessionObserver = class {
|
|
|
16494
16562
|
watches = /* @__PURE__ */ new Map();
|
|
16495
16563
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
16496
16564
|
if (override) return override;
|
|
16497
|
-
return
|
|
16565
|
+
return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
16498
16566
|
}
|
|
16499
16567
|
start(args) {
|
|
16500
16568
|
this.stop(args.sessionId);
|
|
16501
16569
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
16502
16570
|
let size = 0;
|
|
16503
16571
|
try {
|
|
16504
|
-
size =
|
|
16572
|
+
size = import_node_fs10.default.statSync(filePath).size;
|
|
16505
16573
|
} catch {
|
|
16506
16574
|
}
|
|
16507
16575
|
const w = {
|
|
@@ -16514,10 +16582,10 @@ var SessionObserver = class {
|
|
|
16514
16582
|
adapter: args.adapter
|
|
16515
16583
|
};
|
|
16516
16584
|
try {
|
|
16517
|
-
|
|
16585
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
|
|
16518
16586
|
} catch {
|
|
16519
16587
|
}
|
|
16520
|
-
w.watcher =
|
|
16588
|
+
w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
16521
16589
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
16522
16590
|
this.poll(w);
|
|
16523
16591
|
});
|
|
@@ -16532,7 +16600,7 @@ var SessionObserver = class {
|
|
|
16532
16600
|
// reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
|
|
16533
16601
|
hydrateMetaTail(w, maxLines = 200) {
|
|
16534
16602
|
try {
|
|
16535
|
-
const raw =
|
|
16603
|
+
const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
|
|
16536
16604
|
if (!raw) return;
|
|
16537
16605
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
16538
16606
|
if (allLines.length === 0) return;
|
|
@@ -16553,7 +16621,7 @@ var SessionObserver = class {
|
|
|
16553
16621
|
poll(w) {
|
|
16554
16622
|
let size = 0;
|
|
16555
16623
|
try {
|
|
16556
|
-
size =
|
|
16624
|
+
size = import_node_fs10.default.statSync(w.filePath).size;
|
|
16557
16625
|
} catch {
|
|
16558
16626
|
return;
|
|
16559
16627
|
}
|
|
@@ -16562,11 +16630,11 @@ var SessionObserver = class {
|
|
|
16562
16630
|
w.buf = "";
|
|
16563
16631
|
}
|
|
16564
16632
|
if (size === w.lastSize) return;
|
|
16565
|
-
const fd =
|
|
16633
|
+
const fd = import_node_fs10.default.openSync(w.filePath, "r");
|
|
16566
16634
|
try {
|
|
16567
16635
|
const len = size - w.lastSize;
|
|
16568
16636
|
const buf = Buffer.alloc(len);
|
|
16569
|
-
|
|
16637
|
+
import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
|
|
16570
16638
|
w.lastSize = size;
|
|
16571
16639
|
w.buf += buf.toString("utf8");
|
|
16572
16640
|
let newlineIndex;
|
|
@@ -16580,7 +16648,7 @@ var SessionObserver = class {
|
|
|
16580
16648
|
this.maybeReportUserMessage(w.sessionId, line);
|
|
16581
16649
|
}
|
|
16582
16650
|
} finally {
|
|
16583
|
-
|
|
16651
|
+
import_node_fs10.default.closeSync(fd);
|
|
16584
16652
|
}
|
|
16585
16653
|
}
|
|
16586
16654
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -16995,10 +17063,10 @@ function isLocalhost(addr) {
|
|
|
16995
17063
|
}
|
|
16996
17064
|
|
|
16997
17065
|
// src/discovery/state-file.ts
|
|
16998
|
-
var
|
|
16999
|
-
var
|
|
17066
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
17067
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
17000
17068
|
function defaultStateFilePath(dataDir) {
|
|
17001
|
-
return
|
|
17069
|
+
return import_node_path10.default.join(dataDir, "state.json");
|
|
17002
17070
|
}
|
|
17003
17071
|
function isPidAlive(pid) {
|
|
17004
17072
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -17020,7 +17088,7 @@ var StateFileManager = class {
|
|
|
17020
17088
|
}
|
|
17021
17089
|
read() {
|
|
17022
17090
|
try {
|
|
17023
|
-
const raw =
|
|
17091
|
+
const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
|
|
17024
17092
|
const parsed = JSON.parse(raw);
|
|
17025
17093
|
return parsed;
|
|
17026
17094
|
} catch {
|
|
@@ -17034,34 +17102,34 @@ var StateFileManager = class {
|
|
|
17034
17102
|
return { status: "stale", existing };
|
|
17035
17103
|
}
|
|
17036
17104
|
write(state) {
|
|
17037
|
-
|
|
17105
|
+
import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
|
|
17038
17106
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
17039
|
-
|
|
17040
|
-
|
|
17107
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
17108
|
+
import_node_fs11.default.renameSync(tmp, this.file);
|
|
17041
17109
|
if (process.platform !== "win32") {
|
|
17042
17110
|
try {
|
|
17043
|
-
|
|
17111
|
+
import_node_fs11.default.chmodSync(this.file, 384);
|
|
17044
17112
|
} catch {
|
|
17045
17113
|
}
|
|
17046
17114
|
}
|
|
17047
17115
|
}
|
|
17048
17116
|
delete() {
|
|
17049
17117
|
try {
|
|
17050
|
-
|
|
17118
|
+
import_node_fs11.default.unlinkSync(this.file);
|
|
17051
17119
|
} catch {
|
|
17052
17120
|
}
|
|
17053
17121
|
}
|
|
17054
17122
|
};
|
|
17055
17123
|
|
|
17056
17124
|
// src/tunnel/tunnel-manager.ts
|
|
17057
|
-
var
|
|
17058
|
-
var
|
|
17125
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
17126
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
17059
17127
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
17060
17128
|
var import_node_child_process4 = require("child_process");
|
|
17061
17129
|
|
|
17062
17130
|
// src/tunnel/tunnel-store.ts
|
|
17063
|
-
var
|
|
17064
|
-
var
|
|
17131
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
17132
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
17065
17133
|
var TunnelStore = class {
|
|
17066
17134
|
constructor(filePath) {
|
|
17067
17135
|
this.filePath = filePath;
|
|
@@ -17069,7 +17137,7 @@ var TunnelStore = class {
|
|
|
17069
17137
|
filePath;
|
|
17070
17138
|
async get() {
|
|
17071
17139
|
try {
|
|
17072
|
-
const raw = await
|
|
17140
|
+
const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
|
|
17073
17141
|
const obj = JSON.parse(raw);
|
|
17074
17142
|
if (!isPersistedTunnel(obj)) return null;
|
|
17075
17143
|
return obj;
|
|
@@ -17080,22 +17148,22 @@ var TunnelStore = class {
|
|
|
17080
17148
|
}
|
|
17081
17149
|
}
|
|
17082
17150
|
async set(v) {
|
|
17083
|
-
const dir =
|
|
17084
|
-
await
|
|
17151
|
+
const dir = import_node_path11.default.dirname(this.filePath);
|
|
17152
|
+
await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
|
|
17085
17153
|
const data = JSON.stringify(v, null, 2);
|
|
17086
17154
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
17087
|
-
await
|
|
17155
|
+
await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
17088
17156
|
if (process.platform !== "win32") {
|
|
17089
17157
|
try {
|
|
17090
|
-
await
|
|
17158
|
+
await import_node_fs12.default.promises.chmod(tmp, 384);
|
|
17091
17159
|
} catch {
|
|
17092
17160
|
}
|
|
17093
17161
|
}
|
|
17094
|
-
await
|
|
17162
|
+
await import_node_fs12.default.promises.rename(tmp, this.filePath);
|
|
17095
17163
|
}
|
|
17096
17164
|
async clear() {
|
|
17097
17165
|
try {
|
|
17098
|
-
await
|
|
17166
|
+
await import_node_fs12.default.promises.unlink(this.filePath);
|
|
17099
17167
|
} catch (err) {
|
|
17100
17168
|
const code = err?.code;
|
|
17101
17169
|
if (code !== "ENOENT") throw err;
|
|
@@ -17190,9 +17258,9 @@ function escape(v) {
|
|
|
17190
17258
|
}
|
|
17191
17259
|
|
|
17192
17260
|
// src/tunnel/frpc-binary.ts
|
|
17193
|
-
var
|
|
17261
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
17194
17262
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
17195
|
-
var
|
|
17263
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
17196
17264
|
var import_node_child_process3 = require("child_process");
|
|
17197
17265
|
var import_node_stream = require("stream");
|
|
17198
17266
|
var import_promises = require("stream/promises");
|
|
@@ -17224,20 +17292,20 @@ function frpcDownloadUrl(version2, p) {
|
|
|
17224
17292
|
}
|
|
17225
17293
|
async function ensureFrpcBinary(opts) {
|
|
17226
17294
|
if (opts.override) {
|
|
17227
|
-
if (!
|
|
17295
|
+
if (!import_node_fs13.default.existsSync(opts.override)) {
|
|
17228
17296
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
17229
17297
|
}
|
|
17230
17298
|
return opts.override;
|
|
17231
17299
|
}
|
|
17232
17300
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
17233
17301
|
const platform = opts.platform ?? detectPlatform();
|
|
17234
|
-
const binDir =
|
|
17235
|
-
|
|
17302
|
+
const binDir = import_node_path12.default.join(opts.dataDir, "bin");
|
|
17303
|
+
import_node_fs13.default.mkdirSync(binDir, { recursive: true });
|
|
17236
17304
|
cleanupStaleArtifacts(binDir);
|
|
17237
|
-
const stableBin =
|
|
17238
|
-
if (
|
|
17305
|
+
const stableBin = import_node_path12.default.join(binDir, "frpc");
|
|
17306
|
+
if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
|
|
17239
17307
|
const partialBin = `${stableBin}.partial`;
|
|
17240
|
-
const tarballPath =
|
|
17308
|
+
const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
17241
17309
|
try {
|
|
17242
17310
|
const url = frpcDownloadUrl(version2, platform);
|
|
17243
17311
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -17246,8 +17314,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
17246
17314
|
} else {
|
|
17247
17315
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
17248
17316
|
}
|
|
17249
|
-
|
|
17250
|
-
|
|
17317
|
+
import_node_fs13.default.chmodSync(partialBin, 493);
|
|
17318
|
+
import_node_fs13.default.renameSync(partialBin, stableBin);
|
|
17251
17319
|
} finally {
|
|
17252
17320
|
safeUnlink(tarballPath);
|
|
17253
17321
|
safeUnlink(partialBin);
|
|
@@ -17257,15 +17325,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
17257
17325
|
function cleanupStaleArtifacts(binDir) {
|
|
17258
17326
|
let entries;
|
|
17259
17327
|
try {
|
|
17260
|
-
entries =
|
|
17328
|
+
entries = import_node_fs13.default.readdirSync(binDir);
|
|
17261
17329
|
} catch {
|
|
17262
17330
|
return;
|
|
17263
17331
|
}
|
|
17264
17332
|
for (const name of entries) {
|
|
17265
17333
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
17266
|
-
const full =
|
|
17334
|
+
const full = import_node_path12.default.join(binDir, name);
|
|
17267
17335
|
try {
|
|
17268
|
-
|
|
17336
|
+
import_node_fs13.default.rmSync(full, { recursive: true, force: true });
|
|
17269
17337
|
} catch {
|
|
17270
17338
|
}
|
|
17271
17339
|
}
|
|
@@ -17273,7 +17341,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
17273
17341
|
}
|
|
17274
17342
|
function safeUnlink(p) {
|
|
17275
17343
|
try {
|
|
17276
|
-
|
|
17344
|
+
import_node_fs13.default.unlinkSync(p);
|
|
17277
17345
|
} catch {
|
|
17278
17346
|
}
|
|
17279
17347
|
}
|
|
@@ -17284,13 +17352,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
17284
17352
|
if (!res.ok || !res.body) {
|
|
17285
17353
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
17286
17354
|
}
|
|
17287
|
-
const out =
|
|
17355
|
+
const out = import_node_fs13.default.createWriteStream(dest);
|
|
17288
17356
|
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
17289
17357
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
17290
17358
|
}
|
|
17291
17359
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
17292
|
-
const work =
|
|
17293
|
-
|
|
17360
|
+
const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
17361
|
+
import_node_fs13.default.mkdirSync(work, { recursive: true });
|
|
17294
17362
|
try {
|
|
17295
17363
|
await new Promise((resolve, reject) => {
|
|
17296
17364
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -17298,13 +17366,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
17298
17366
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
17299
17367
|
});
|
|
17300
17368
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
17301
|
-
const src =
|
|
17302
|
-
if (!
|
|
17369
|
+
const src = import_node_path12.default.join(work, dirName, "frpc");
|
|
17370
|
+
if (!import_node_fs13.default.existsSync(src)) {
|
|
17303
17371
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
17304
17372
|
}
|
|
17305
|
-
|
|
17373
|
+
import_node_fs13.default.copyFileSync(src, destBin);
|
|
17306
17374
|
} finally {
|
|
17307
|
-
|
|
17375
|
+
import_node_fs13.default.rmSync(work, { recursive: true, force: true });
|
|
17308
17376
|
}
|
|
17309
17377
|
}
|
|
17310
17378
|
|
|
@@ -17313,7 +17381,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
17313
17381
|
var TunnelManager = class {
|
|
17314
17382
|
constructor(deps) {
|
|
17315
17383
|
this.deps = deps;
|
|
17316
|
-
this.store = deps.store ?? new TunnelStore(
|
|
17384
|
+
this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
|
|
17317
17385
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
17318
17386
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
17319
17387
|
}
|
|
@@ -17430,7 +17498,7 @@ var TunnelManager = class {
|
|
|
17430
17498
|
dataDir: this.deps.dataDir,
|
|
17431
17499
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
17432
17500
|
});
|
|
17433
|
-
const tomlPath =
|
|
17501
|
+
const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
|
|
17434
17502
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
|
|
17435
17503
|
const toml = buildFrpcToml({
|
|
17436
17504
|
serverAddr: t.frpsHost,
|
|
@@ -17441,12 +17509,12 @@ var TunnelManager = class {
|
|
|
17441
17509
|
localPort,
|
|
17442
17510
|
logLevel: "info"
|
|
17443
17511
|
});
|
|
17444
|
-
await
|
|
17512
|
+
await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
17445
17513
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
17446
17514
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17447
17515
|
});
|
|
17448
|
-
const logFilePath =
|
|
17449
|
-
const logStream =
|
|
17516
|
+
const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
|
|
17517
|
+
const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
17450
17518
|
logStream.on("error", () => {
|
|
17451
17519
|
});
|
|
17452
17520
|
const tee = (chunk) => {
|
|
@@ -17538,12 +17606,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
17538
17606
|
}
|
|
17539
17607
|
|
|
17540
17608
|
// src/auth-store.ts
|
|
17541
|
-
var
|
|
17542
|
-
var
|
|
17609
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
17610
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
17543
17611
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
17544
17612
|
var AUTH_FILE_NAME = "auth.json";
|
|
17545
17613
|
function authFilePath(dataDir) {
|
|
17546
|
-
return
|
|
17614
|
+
return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
|
|
17547
17615
|
}
|
|
17548
17616
|
function loadOrCreateAuthToken(opts) {
|
|
17549
17617
|
const file = authFilePath(opts.dataDir);
|
|
@@ -17559,7 +17627,7 @@ function defaultGenerate() {
|
|
|
17559
17627
|
}
|
|
17560
17628
|
function readAuthFile(file) {
|
|
17561
17629
|
try {
|
|
17562
|
-
const raw =
|
|
17630
|
+
const raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
17563
17631
|
const parsed = JSON.parse(raw);
|
|
17564
17632
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
17565
17633
|
return {
|
|
@@ -17575,20 +17643,20 @@ function readAuthFile(file) {
|
|
|
17575
17643
|
}
|
|
17576
17644
|
}
|
|
17577
17645
|
function writeAuthFile(file, content) {
|
|
17578
|
-
|
|
17579
|
-
|
|
17646
|
+
import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
|
|
17647
|
+
import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
17580
17648
|
try {
|
|
17581
|
-
|
|
17649
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
17582
17650
|
} catch {
|
|
17583
17651
|
}
|
|
17584
17652
|
}
|
|
17585
17653
|
|
|
17586
17654
|
// src/session/fork.ts
|
|
17587
|
-
var
|
|
17655
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
17588
17656
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
17589
|
-
var
|
|
17657
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
17590
17658
|
function readJsonlEntries(file) {
|
|
17591
|
-
const raw =
|
|
17659
|
+
const raw = import_node_fs16.default.readFileSync(file, "utf8");
|
|
17592
17660
|
const out = [];
|
|
17593
17661
|
for (const line of raw.split("\n")) {
|
|
17594
17662
|
const t = line.trim();
|
|
@@ -17601,10 +17669,10 @@ function readJsonlEntries(file) {
|
|
|
17601
17669
|
return out;
|
|
17602
17670
|
}
|
|
17603
17671
|
function forkSession(input) {
|
|
17604
|
-
const baseDir = input.baseDir ??
|
|
17605
|
-
const projectDir =
|
|
17606
|
-
const sourceFile =
|
|
17607
|
-
if (!
|
|
17672
|
+
const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
|
|
17673
|
+
const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
17674
|
+
const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
17675
|
+
if (!import_node_fs16.default.existsSync(sourceFile)) {
|
|
17608
17676
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
17609
17677
|
}
|
|
17610
17678
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -17634,9 +17702,9 @@ function forkSession(input) {
|
|
|
17634
17702
|
}
|
|
17635
17703
|
forkedLines.push(JSON.stringify(forked));
|
|
17636
17704
|
}
|
|
17637
|
-
const forkedFilePath =
|
|
17638
|
-
|
|
17639
|
-
|
|
17705
|
+
const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
17706
|
+
import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
|
|
17707
|
+
import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
17640
17708
|
return { forkedToolSessionId, forkedFilePath };
|
|
17641
17709
|
}
|
|
17642
17710
|
|
|
@@ -17892,9 +17960,9 @@ function buildWorkspaceHandlers(deps) {
|
|
|
17892
17960
|
|
|
17893
17961
|
// src/workspace/git.ts
|
|
17894
17962
|
var import_node_child_process5 = require("child_process");
|
|
17895
|
-
var
|
|
17963
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
17896
17964
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
17897
|
-
var
|
|
17965
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
17898
17966
|
var import_node_util = require("util");
|
|
17899
17967
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
17900
17968
|
function formatChildProcessError(err) {
|
|
@@ -17909,9 +17977,9 @@ function formatChildProcessError(err) {
|
|
|
17909
17977
|
return e.message ?? "unknown error";
|
|
17910
17978
|
}
|
|
17911
17979
|
function normalizePath(p) {
|
|
17912
|
-
const resolved =
|
|
17980
|
+
const resolved = import_node_path16.default.resolve(p);
|
|
17913
17981
|
try {
|
|
17914
|
-
return
|
|
17982
|
+
return import_node_fs17.default.realpathSync(resolved);
|
|
17915
17983
|
} catch {
|
|
17916
17984
|
return resolved;
|
|
17917
17985
|
}
|
|
@@ -18012,13 +18080,13 @@ function flattenToDirName(branch) {
|
|
|
18012
18080
|
}
|
|
18013
18081
|
function encodeClaudeProjectDir(absPath) {
|
|
18014
18082
|
if (!absPath || typeof absPath !== "string") return "";
|
|
18015
|
-
let canonical =
|
|
18083
|
+
let canonical = import_node_path16.default.resolve(absPath);
|
|
18016
18084
|
try {
|
|
18017
|
-
canonical =
|
|
18085
|
+
canonical = import_node_fs17.default.realpathSync(canonical);
|
|
18018
18086
|
} catch {
|
|
18019
18087
|
try {
|
|
18020
|
-
const parent =
|
|
18021
|
-
canonical =
|
|
18088
|
+
const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
|
|
18089
|
+
canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
|
|
18022
18090
|
} catch {
|
|
18023
18091
|
}
|
|
18024
18092
|
}
|
|
@@ -18042,11 +18110,11 @@ async function createWorktree(input) {
|
|
|
18042
18110
|
if (!isGitRoot) {
|
|
18043
18111
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
18044
18112
|
}
|
|
18045
|
-
const parent =
|
|
18046
|
-
if (parent === "/" || parent ===
|
|
18113
|
+
const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
|
|
18114
|
+
if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
|
|
18047
18115
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
18048
18116
|
}
|
|
18049
|
-
const worktreeRoot =
|
|
18117
|
+
const worktreeRoot = import_node_path16.default.join(parent, dirName);
|
|
18050
18118
|
try {
|
|
18051
18119
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
|
|
18052
18120
|
timeout: 3e3
|
|
@@ -18063,7 +18131,7 @@ async function createWorktree(input) {
|
|
|
18063
18131
|
const msg = err.message;
|
|
18064
18132
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
18065
18133
|
}
|
|
18066
|
-
if (
|
|
18134
|
+
if (import_node_fs17.default.existsSync(worktreeRoot)) {
|
|
18067
18135
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
18068
18136
|
}
|
|
18069
18137
|
try {
|
|
@@ -18091,8 +18159,8 @@ async function removeWorktree(input) {
|
|
|
18091
18159
|
);
|
|
18092
18160
|
const gitCommonDir = stdout.trim();
|
|
18093
18161
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
18094
|
-
const absGitCommon =
|
|
18095
|
-
repoRoot =
|
|
18162
|
+
const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
|
|
18163
|
+
repoRoot = import_node_path16.default.dirname(absGitCommon);
|
|
18096
18164
|
} catch {
|
|
18097
18165
|
repoRoot = null;
|
|
18098
18166
|
}
|
|
@@ -18104,7 +18172,7 @@ async function removeWorktree(input) {
|
|
|
18104
18172
|
} catch (err) {
|
|
18105
18173
|
const stderr = err.stderr ?? "";
|
|
18106
18174
|
const lower = stderr.toLowerCase();
|
|
18107
|
-
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !
|
|
18175
|
+
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
|
|
18108
18176
|
if (!vanished) {
|
|
18109
18177
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
18110
18178
|
}
|
|
@@ -18123,10 +18191,10 @@ async function removeWorktree(input) {
|
|
|
18123
18191
|
try {
|
|
18124
18192
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
18125
18193
|
if (encoded) {
|
|
18126
|
-
const projectsRoot =
|
|
18127
|
-
const target =
|
|
18128
|
-
if (target.startsWith(projectsRoot +
|
|
18129
|
-
|
|
18194
|
+
const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
18195
|
+
const target = import_node_path16.default.resolve(projectsRoot, encoded);
|
|
18196
|
+
if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
|
|
18197
|
+
import_node_fs17.default.rmSync(target, { recursive: true, force: true });
|
|
18130
18198
|
}
|
|
18131
18199
|
}
|
|
18132
18200
|
} catch {
|
|
@@ -18253,7 +18321,7 @@ function buildMethodHandlers(deps) {
|
|
|
18253
18321
|
async function startDaemon(config) {
|
|
18254
18322
|
const logger = createLogger({
|
|
18255
18323
|
level: config.logLevel,
|
|
18256
|
-
file:
|
|
18324
|
+
file: import_node_path17.default.join(config.dataDir, "clawd.log")
|
|
18257
18325
|
});
|
|
18258
18326
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
18259
18327
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -18293,6 +18361,7 @@ async function startDaemon(config) {
|
|
|
18293
18361
|
logger,
|
|
18294
18362
|
getAdapter,
|
|
18295
18363
|
historyReader: history,
|
|
18364
|
+
dataDir: config.dataDir,
|
|
18296
18365
|
broadcastFrame: (frame, target) => {
|
|
18297
18366
|
if (target === "all") {
|
|
18298
18367
|
transport?.broadcastAll(frame);
|
|
@@ -18415,8 +18484,8 @@ async function startDaemon(config) {
|
|
|
18415
18484
|
const lines = [
|
|
18416
18485
|
`Tunnel: ${r.url}`,
|
|
18417
18486
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
18418
|
-
`Frpc config: ${
|
|
18419
|
-
`Frpc log: ${
|
|
18487
|
+
`Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
|
|
18488
|
+
`Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
|
|
18420
18489
|
];
|
|
18421
18490
|
const width = Math.max(...lines.map((l) => l.length));
|
|
18422
18491
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -18429,8 +18498,8 @@ ${bar}
|
|
|
18429
18498
|
|
|
18430
18499
|
`);
|
|
18431
18500
|
try {
|
|
18432
|
-
const connectPath =
|
|
18433
|
-
|
|
18501
|
+
const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
|
|
18502
|
+
import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
18434
18503
|
} catch {
|
|
18435
18504
|
}
|
|
18436
18505
|
} catch (err) {
|