@clawos-dev/clawd 0.2.23-beta.34.136a698 → 0.2.23
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 -293
- 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);
|
|
@@ -8144,7 +8144,6 @@ var METHOD_NAMES = [
|
|
|
8144
8144
|
"session:subscribe",
|
|
8145
8145
|
"session:unsubscribe",
|
|
8146
8146
|
"session:pin",
|
|
8147
|
-
"session:reorderPins",
|
|
8148
8147
|
"permission:respond",
|
|
8149
8148
|
// AskUserQuestion 表单回写:UI 答完所有 question 后调用,daemon 把答案合并进 updated_input
|
|
8150
8149
|
// 写一条 control_response 到 CC stdin(详见 events.ts session:question JSDoc)
|
|
@@ -8687,8 +8686,8 @@ function getErrorMap() {
|
|
|
8687
8686
|
|
|
8688
8687
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
8689
8688
|
var makeIssue = (params) => {
|
|
8690
|
-
const { data, path:
|
|
8691
|
-
const fullPath = [...
|
|
8689
|
+
const { data, path: path18, errorMaps, issueData } = params;
|
|
8690
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
8692
8691
|
const fullIssue = {
|
|
8693
8692
|
...issueData,
|
|
8694
8693
|
path: fullPath
|
|
@@ -8804,11 +8803,11 @@ var errorUtil;
|
|
|
8804
8803
|
|
|
8805
8804
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
8806
8805
|
var ParseInputLazyPath = class {
|
|
8807
|
-
constructor(parent, value,
|
|
8806
|
+
constructor(parent, value, path18, key) {
|
|
8808
8807
|
this._cachedPath = [];
|
|
8809
8808
|
this.parent = parent;
|
|
8810
8809
|
this.data = value;
|
|
8811
|
-
this._path =
|
|
8810
|
+
this._path = path18;
|
|
8812
8811
|
this._key = key;
|
|
8813
8812
|
}
|
|
8814
8813
|
get path() {
|
|
@@ -12327,9 +12326,6 @@ var SessionFileSchema = external_exports.object({
|
|
|
12327
12326
|
permissionRules: external_exports.array(AllowRuleSchema).optional(),
|
|
12328
12327
|
// Sidebar 置顶时间戳;null/undefined 表示未置顶
|
|
12329
12328
|
pinnedAt: external_exports.number().int().nonnegative().nullable().optional(),
|
|
12330
|
-
// pinned 行手动拖拽顺序;越小越靠前。session:reorderPins 整体重写所有 pinned 的此字段。
|
|
12331
|
-
// 缺失时 view-state 排序回退到 pinnedAt desc(旧数据兼容)
|
|
12332
|
-
pinSortOrder: external_exports.number().int().nullable().optional(),
|
|
12333
12329
|
// 用户在 NewSessionDialog 或 Edit modal 选择的 icon 标识;UI 端做 enum 兜底
|
|
12334
12330
|
iconKey: external_exports.string().optional(),
|
|
12335
12331
|
// NewSessionDialog 勾选 worktree 创建的 session 才会持久化这两个字段
|
|
@@ -12661,9 +12657,6 @@ var SessionPinArgs = external_exports.object({
|
|
|
12661
12657
|
sessionId: external_exports.string().min(1),
|
|
12662
12658
|
pinned: external_exports.boolean()
|
|
12663
12659
|
});
|
|
12664
|
-
var SessionReorderPinsArgs = external_exports.object({
|
|
12665
|
-
orderedIds: external_exports.array(external_exports.string().min(1)).min(1)
|
|
12666
|
-
});
|
|
12667
12660
|
var GitRootArgs = external_exports.object({ cwd: external_exports.string().min(1) });
|
|
12668
12661
|
var GitRootResponseSchema = external_exports.object({
|
|
12669
12662
|
isGitRoot: external_exports.boolean(),
|
|
@@ -12819,7 +12812,7 @@ var SessionStore = class {
|
|
|
12819
12812
|
};
|
|
12820
12813
|
|
|
12821
12814
|
// src/session/manager.ts
|
|
12822
|
-
var
|
|
12815
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
12823
12816
|
|
|
12824
12817
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
12825
12818
|
var byteToHex = [];
|
|
@@ -13408,6 +13401,58 @@ function reduceSession(state, input, deps) {
|
|
|
13408
13401
|
}
|
|
13409
13402
|
}
|
|
13410
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
|
+
|
|
13411
13456
|
// src/session/runner.ts
|
|
13412
13457
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
13413
13458
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -13438,6 +13483,8 @@ var SessionRunner = class {
|
|
|
13438
13483
|
pendingControlRequests = /* @__PURE__ */ new Map();
|
|
13439
13484
|
// waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
|
|
13440
13485
|
stopWaiters = [];
|
|
13486
|
+
// IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
|
|
13487
|
+
recorder = null;
|
|
13441
13488
|
getState() {
|
|
13442
13489
|
return this.state;
|
|
13443
13490
|
}
|
|
@@ -13527,6 +13574,7 @@ var SessionRunner = class {
|
|
|
13527
13574
|
this.pendingControlRequests.set(requestId, { resolve, reject, timer });
|
|
13528
13575
|
try {
|
|
13529
13576
|
proc.stdin?.write(payload);
|
|
13577
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13530
13578
|
} catch (err) {
|
|
13531
13579
|
clearTimeout(timer);
|
|
13532
13580
|
this.pendingControlRequests.delete(requestId);
|
|
@@ -13582,10 +13630,14 @@ var SessionRunner = class {
|
|
|
13582
13630
|
break;
|
|
13583
13631
|
case "write-stdin":
|
|
13584
13632
|
this.proc?.stdin?.write(effect.payload);
|
|
13633
|
+
this.recorder?.tapStdinWrite(effect.payload);
|
|
13585
13634
|
break;
|
|
13586
|
-
case "send-control-response-allow-with-input":
|
|
13587
|
-
|
|
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);
|
|
13588
13639
|
break;
|
|
13640
|
+
}
|
|
13589
13641
|
case "persist-file":
|
|
13590
13642
|
try {
|
|
13591
13643
|
this.hooks.store.write(effect.file);
|
|
@@ -13615,6 +13667,13 @@ var SessionRunner = class {
|
|
|
13615
13667
|
const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
|
|
13616
13668
|
this.proc = proc;
|
|
13617
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
|
+
});
|
|
13618
13677
|
proc.stdout?.on("data", (chunk) => {
|
|
13619
13678
|
this.stdoutBuf += typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13620
13679
|
let idx;
|
|
@@ -13631,6 +13690,7 @@ var SessionRunner = class {
|
|
|
13631
13690
|
});
|
|
13632
13691
|
proc.on("exit", (code) => {
|
|
13633
13692
|
this.proc = null;
|
|
13693
|
+
this.recorder = null;
|
|
13634
13694
|
this.rejectAllPending(new Error("session gone"));
|
|
13635
13695
|
this.input({ kind: "proc-exit", code });
|
|
13636
13696
|
});
|
|
@@ -13757,7 +13817,8 @@ var SessionManager = class {
|
|
|
13757
13817
|
now: this.deps.now,
|
|
13758
13818
|
bufferCap: this.deps.bufferCap,
|
|
13759
13819
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
13760
|
-
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
|
|
13820
|
+
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
13821
|
+
dataDir: this.deps.dataDir
|
|
13761
13822
|
});
|
|
13762
13823
|
return runner;
|
|
13763
13824
|
}
|
|
@@ -13788,7 +13849,7 @@ var SessionManager = class {
|
|
|
13788
13849
|
// ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
|
|
13789
13850
|
create(args) {
|
|
13790
13851
|
try {
|
|
13791
|
-
const stat =
|
|
13852
|
+
const stat = import_node_fs5.default.statSync(args.cwd);
|
|
13792
13853
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
13793
13854
|
} catch {
|
|
13794
13855
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
|
|
@@ -13829,49 +13890,6 @@ var SessionManager = class {
|
|
|
13829
13890
|
this.deps.store.write(updated);
|
|
13830
13891
|
return { response: updated, broadcast: [] };
|
|
13831
13892
|
}
|
|
13832
|
-
// sidebar 拖拽完成 → 整体重写 pinned root 的 pinSortOrder(按 orderedIds 下标 0,1,2...)
|
|
13833
|
-
// orderedIds 必须正好覆盖所有当前 pinned root(既不能漏,也不能含 unpinned id)
|
|
13834
|
-
reorderPins(args) {
|
|
13835
|
-
const all = this.deps.store.list();
|
|
13836
|
-
const currentPinnedIds = new Set(
|
|
13837
|
-
all.filter((f) => typeof f.pinnedAt === "number").map((f) => f.sessionId)
|
|
13838
|
-
);
|
|
13839
|
-
const incoming = new Set(args.orderedIds);
|
|
13840
|
-
if (incoming.size !== args.orderedIds.length) {
|
|
13841
|
-
throw new Error("reorderPins: orderedIds contains duplicate ids");
|
|
13842
|
-
}
|
|
13843
|
-
if (currentPinnedIds.size !== incoming.size || [...currentPinnedIds].some((id) => !incoming.has(id))) {
|
|
13844
|
-
throw new Error(
|
|
13845
|
-
"reorderPins: orderedIds must cover exactly the current pinned root set"
|
|
13846
|
-
);
|
|
13847
|
-
}
|
|
13848
|
-
const broadcast = [];
|
|
13849
|
-
const updatedFiles = [];
|
|
13850
|
-
args.orderedIds.forEach((sessionId, index) => {
|
|
13851
|
-
const runner = this.runners.get(sessionId);
|
|
13852
|
-
if (runner) {
|
|
13853
|
-
const { value, broadcast: b } = this.withCollector(() => {
|
|
13854
|
-
runner.input({
|
|
13855
|
-
kind: "command",
|
|
13856
|
-
command: { kind: "update", patch: { pinSortOrder: index } }
|
|
13857
|
-
});
|
|
13858
|
-
return runner.getState().file;
|
|
13859
|
-
});
|
|
13860
|
-
updatedFiles.push(value);
|
|
13861
|
-
broadcast.push(...b);
|
|
13862
|
-
} else {
|
|
13863
|
-
const existing = this.getFile(sessionId);
|
|
13864
|
-
const updated = {
|
|
13865
|
-
...existing,
|
|
13866
|
-
pinSortOrder: index,
|
|
13867
|
-
updatedAt: nowIso2(this.deps)
|
|
13868
|
-
};
|
|
13869
|
-
this.deps.store.write(updated);
|
|
13870
|
-
updatedFiles.push(updated);
|
|
13871
|
-
}
|
|
13872
|
-
});
|
|
13873
|
-
return { response: { sessions: updatedFiles }, broadcast };
|
|
13874
|
-
}
|
|
13875
13893
|
list() {
|
|
13876
13894
|
return { response: { sessions: this.deps.store.list() }, broadcast: [] };
|
|
13877
13895
|
}
|
|
@@ -14277,14 +14295,14 @@ var SessionManager = class {
|
|
|
14277
14295
|
// src/tools/claude.ts
|
|
14278
14296
|
var import_node_child_process = require("child_process");
|
|
14279
14297
|
var import_node_child_process2 = require("child_process");
|
|
14280
|
-
var
|
|
14298
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
14281
14299
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
14282
|
-
var
|
|
14300
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
14283
14301
|
|
|
14284
14302
|
// src/tools/claude-history.ts
|
|
14285
|
-
var
|
|
14303
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
14286
14304
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
14287
|
-
var
|
|
14305
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
14288
14306
|
|
|
14289
14307
|
// ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
|
|
14290
14308
|
function Diff() {
|
|
@@ -14388,11 +14406,11 @@ Diff.prototype = {
|
|
|
14388
14406
|
}
|
|
14389
14407
|
}
|
|
14390
14408
|
},
|
|
14391
|
-
addToPath: function addToPath(
|
|
14392
|
-
var last =
|
|
14409
|
+
addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
|
|
14410
|
+
var last = path18.lastComponent;
|
|
14393
14411
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14394
14412
|
return {
|
|
14395
|
-
oldPos:
|
|
14413
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14396
14414
|
lastComponent: {
|
|
14397
14415
|
count: last.count + 1,
|
|
14398
14416
|
added,
|
|
@@ -14402,7 +14420,7 @@ Diff.prototype = {
|
|
|
14402
14420
|
};
|
|
14403
14421
|
} else {
|
|
14404
14422
|
return {
|
|
14405
|
-
oldPos:
|
|
14423
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14406
14424
|
lastComponent: {
|
|
14407
14425
|
count: 1,
|
|
14408
14426
|
added,
|
|
@@ -15061,7 +15079,7 @@ function hashDirToCwd(hash) {
|
|
|
15061
15079
|
}
|
|
15062
15080
|
function safeStatMtime(p) {
|
|
15063
15081
|
try {
|
|
15064
|
-
return
|
|
15082
|
+
return import_node_fs6.default.statSync(p).mtimeMs;
|
|
15065
15083
|
} catch {
|
|
15066
15084
|
return 0;
|
|
15067
15085
|
}
|
|
@@ -15069,7 +15087,7 @@ function safeStatMtime(p) {
|
|
|
15069
15087
|
function readJsonlLines(file) {
|
|
15070
15088
|
let raw;
|
|
15071
15089
|
try {
|
|
15072
|
-
raw =
|
|
15090
|
+
raw = import_node_fs6.default.readFileSync(file, "utf8");
|
|
15073
15091
|
} catch (err) {
|
|
15074
15092
|
if (err.code === "ENOENT") return [];
|
|
15075
15093
|
throw err;
|
|
@@ -15261,10 +15279,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15261
15279
|
const memories = raw.map((m) => {
|
|
15262
15280
|
if (!m || typeof m !== "object") return null;
|
|
15263
15281
|
const rec = m;
|
|
15264
|
-
const
|
|
15282
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15265
15283
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15266
|
-
if (!
|
|
15267
|
-
const entry = { path:
|
|
15284
|
+
if (!path18 || content == null) return null;
|
|
15285
|
+
const entry = { path: path18, content };
|
|
15268
15286
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
15269
15287
|
return entry;
|
|
15270
15288
|
}).filter((m) => m !== null);
|
|
@@ -15300,8 +15318,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
15300
15318
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
15301
15319
|
if (backupFileName === null) return null;
|
|
15302
15320
|
try {
|
|
15303
|
-
return
|
|
15304
|
-
|
|
15321
|
+
return import_node_fs6.default.readFileSync(
|
|
15322
|
+
import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
15305
15323
|
"utf8"
|
|
15306
15324
|
);
|
|
15307
15325
|
} catch {
|
|
@@ -15310,7 +15328,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
15310
15328
|
}
|
|
15311
15329
|
function readCurrentContent(filePath) {
|
|
15312
15330
|
try {
|
|
15313
|
-
return
|
|
15331
|
+
return import_node_fs6.default.readFileSync(filePath, "utf8");
|
|
15314
15332
|
} catch (err) {
|
|
15315
15333
|
if (err.code === "ENOENT") return null;
|
|
15316
15334
|
return null;
|
|
@@ -15322,14 +15340,14 @@ var ClaudeHistoryReader = class {
|
|
|
15322
15340
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
15323
15341
|
fileHistoryRoot;
|
|
15324
15342
|
constructor(opts = {}) {
|
|
15325
|
-
const base = opts.baseDir ??
|
|
15326
|
-
this.projectsRoot =
|
|
15327
|
-
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");
|
|
15328
15346
|
}
|
|
15329
15347
|
async listProjects() {
|
|
15330
15348
|
let entries;
|
|
15331
15349
|
try {
|
|
15332
|
-
entries =
|
|
15350
|
+
entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
15333
15351
|
} catch (err) {
|
|
15334
15352
|
if (err.code === "ENOENT") return [];
|
|
15335
15353
|
throw err;
|
|
@@ -15337,9 +15355,9 @@ var ClaudeHistoryReader = class {
|
|
|
15337
15355
|
const out = [];
|
|
15338
15356
|
for (const ent of entries) {
|
|
15339
15357
|
if (!ent.isDirectory()) continue;
|
|
15340
|
-
const dir =
|
|
15341
|
-
const files =
|
|
15342
|
-
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);
|
|
15343
15361
|
out.push({
|
|
15344
15362
|
projectPath: hashDirToCwd(ent.name),
|
|
15345
15363
|
hashDir: ent.name,
|
|
@@ -15351,17 +15369,17 @@ var ClaudeHistoryReader = class {
|
|
|
15351
15369
|
return out;
|
|
15352
15370
|
}
|
|
15353
15371
|
async listSessions(args) {
|
|
15354
|
-
const dir =
|
|
15372
|
+
const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
15355
15373
|
let files;
|
|
15356
15374
|
try {
|
|
15357
|
-
files =
|
|
15375
|
+
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15358
15376
|
} catch (err) {
|
|
15359
15377
|
if (err.code === "ENOENT") return [];
|
|
15360
15378
|
throw err;
|
|
15361
15379
|
}
|
|
15362
15380
|
const out = [];
|
|
15363
15381
|
for (const f of files) {
|
|
15364
|
-
const full =
|
|
15382
|
+
const full = import_node_path5.default.join(dir, f);
|
|
15365
15383
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
15366
15384
|
const lines = readJsonlLines(full);
|
|
15367
15385
|
let summary = "";
|
|
@@ -15416,7 +15434,7 @@ var ClaudeHistoryReader = class {
|
|
|
15416
15434
|
return out;
|
|
15417
15435
|
}
|
|
15418
15436
|
async read(args) {
|
|
15419
|
-
const file =
|
|
15437
|
+
const file = import_node_path5.default.join(
|
|
15420
15438
|
this.projectsRoot,
|
|
15421
15439
|
cwdToHashDir(args.cwd),
|
|
15422
15440
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15449,7 +15467,7 @@ var ClaudeHistoryReader = class {
|
|
|
15449
15467
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
15450
15468
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
15451
15469
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
15452
|
-
const dir =
|
|
15470
|
+
const dir = import_node_path5.default.join(
|
|
15453
15471
|
this.projectsRoot,
|
|
15454
15472
|
cwdToHashDir(cwd),
|
|
15455
15473
|
toolSessionId,
|
|
@@ -15457,7 +15475,7 @@ var ClaudeHistoryReader = class {
|
|
|
15457
15475
|
);
|
|
15458
15476
|
let entries;
|
|
15459
15477
|
try {
|
|
15460
|
-
entries =
|
|
15478
|
+
entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
|
|
15461
15479
|
} catch (err) {
|
|
15462
15480
|
if (err.code === "ENOENT") return null;
|
|
15463
15481
|
return null;
|
|
@@ -15467,7 +15485,7 @@ var ClaudeHistoryReader = class {
|
|
|
15467
15485
|
if (!e.isFile()) continue;
|
|
15468
15486
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
15469
15487
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
15470
|
-
const filePath =
|
|
15488
|
+
const filePath = import_node_path5.default.join(dir, e.name);
|
|
15471
15489
|
const lines = readJsonlLines(filePath);
|
|
15472
15490
|
let firstText = "";
|
|
15473
15491
|
let messageCount = 0;
|
|
@@ -15484,7 +15502,7 @@ var ClaudeHistoryReader = class {
|
|
|
15484
15502
|
return out;
|
|
15485
15503
|
}
|
|
15486
15504
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
15487
|
-
const file =
|
|
15505
|
+
const file = import_node_path5.default.join(
|
|
15488
15506
|
this.projectsRoot,
|
|
15489
15507
|
cwdToHashDir(cwd),
|
|
15490
15508
|
`${toolSessionId}.jsonl`
|
|
@@ -15519,7 +15537,7 @@ var ClaudeHistoryReader = class {
|
|
|
15519
15537
|
}
|
|
15520
15538
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
15521
15539
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
15522
|
-
const file =
|
|
15540
|
+
const file = import_node_path5.default.join(
|
|
15523
15541
|
this.projectsRoot,
|
|
15524
15542
|
cwdToHashDir(cwd),
|
|
15525
15543
|
toolSessionId,
|
|
@@ -15528,7 +15546,7 @@ var ClaudeHistoryReader = class {
|
|
|
15528
15546
|
);
|
|
15529
15547
|
let exists = false;
|
|
15530
15548
|
try {
|
|
15531
|
-
exists =
|
|
15549
|
+
exists = import_node_fs6.default.statSync(file).isFile();
|
|
15532
15550
|
} catch {
|
|
15533
15551
|
return null;
|
|
15534
15552
|
}
|
|
@@ -15547,7 +15565,7 @@ var ClaudeHistoryReader = class {
|
|
|
15547
15565
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
15548
15566
|
*/
|
|
15549
15567
|
readFileHistorySnapshots(args) {
|
|
15550
|
-
const file =
|
|
15568
|
+
const file = import_node_path5.default.join(
|
|
15551
15569
|
this.projectsRoot,
|
|
15552
15570
|
cwdToHashDir(args.cwd),
|
|
15553
15571
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15592,7 +15610,7 @@ var ClaudeHistoryReader = class {
|
|
|
15592
15610
|
for (const [anchorId, target] of snapshots) {
|
|
15593
15611
|
let hasAny = false;
|
|
15594
15612
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15595
|
-
const absPath =
|
|
15613
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15596
15614
|
const backupContent = readBackupContent(
|
|
15597
15615
|
this.fileHistoryRoot,
|
|
15598
15616
|
args.toolSessionId,
|
|
@@ -15632,7 +15650,7 @@ var ClaudeHistoryReader = class {
|
|
|
15632
15650
|
let totalInsertions = 0;
|
|
15633
15651
|
let totalDeletions = 0;
|
|
15634
15652
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15635
|
-
const absPath =
|
|
15653
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15636
15654
|
const backupContent = readBackupContent(
|
|
15637
15655
|
this.fileHistoryRoot,
|
|
15638
15656
|
args.toolSessionId,
|
|
@@ -15679,7 +15697,7 @@ var ClaudeHistoryReader = class {
|
|
|
15679
15697
|
};
|
|
15680
15698
|
}
|
|
15681
15699
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
15682
|
-
const file =
|
|
15700
|
+
const file = import_node_path5.default.join(
|
|
15683
15701
|
this.projectsRoot,
|
|
15684
15702
|
cwdToHashDir(cwd),
|
|
15685
15703
|
`${toolSessionId}.jsonl`
|
|
@@ -15701,27 +15719,27 @@ var ClaudeHistoryReader = class {
|
|
|
15701
15719
|
// src/tools/claude.ts
|
|
15702
15720
|
function macOSDesktopCandidates(home) {
|
|
15703
15721
|
return [
|
|
15704
|
-
|
|
15722
|
+
import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
15705
15723
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
15706
15724
|
];
|
|
15707
15725
|
}
|
|
15708
15726
|
function probeViaWhich() {
|
|
15709
15727
|
try {
|
|
15710
15728
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
15711
|
-
if (out &&
|
|
15729
|
+
if (out && import_node_fs7.default.existsSync(out)) return out;
|
|
15712
15730
|
} catch {
|
|
15713
15731
|
}
|
|
15714
15732
|
return null;
|
|
15715
15733
|
}
|
|
15716
15734
|
async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
|
|
15717
|
-
if (env.CLAUDE_BIN &&
|
|
15735
|
+
if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
|
|
15718
15736
|
return { available: true, path: env.CLAUDE_BIN };
|
|
15719
15737
|
}
|
|
15720
15738
|
const w = probeViaWhich();
|
|
15721
15739
|
if (w) return { available: true, path: w };
|
|
15722
15740
|
if (process.platform === "darwin") {
|
|
15723
15741
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
15724
|
-
if (
|
|
15742
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15725
15743
|
return { available: true, path: candidate };
|
|
15726
15744
|
}
|
|
15727
15745
|
}
|
|
@@ -16032,10 +16050,10 @@ function parseAttachment(obj) {
|
|
|
16032
16050
|
const memories = raw.map((m) => {
|
|
16033
16051
|
if (!m || typeof m !== "object") return null;
|
|
16034
16052
|
const rec = m;
|
|
16035
|
-
const
|
|
16053
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
16036
16054
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
16037
|
-
if (!
|
|
16038
|
-
const out = { path:
|
|
16055
|
+
if (!path18 || content == null) return null;
|
|
16056
|
+
const out = { path: path18, content };
|
|
16039
16057
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
16040
16058
|
return out;
|
|
16041
16059
|
}).filter((m) => m !== null);
|
|
@@ -16263,22 +16281,22 @@ var ClaudeAdapter = class {
|
|
|
16263
16281
|
};
|
|
16264
16282
|
|
|
16265
16283
|
// src/workspace/browser.ts
|
|
16266
|
-
var
|
|
16284
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
16267
16285
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
16268
|
-
var
|
|
16286
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
16269
16287
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
16270
16288
|
function resolveInsideCwd(cwd, subpath) {
|
|
16271
|
-
const absCwd =
|
|
16272
|
-
const joined =
|
|
16273
|
-
const rel =
|
|
16274
|
-
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)) {
|
|
16275
16293
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
16276
16294
|
}
|
|
16277
16295
|
return joined;
|
|
16278
16296
|
}
|
|
16279
16297
|
function ensureCwd(cwd) {
|
|
16280
16298
|
try {
|
|
16281
|
-
const stat =
|
|
16299
|
+
const stat = import_node_fs8.default.statSync(cwd);
|
|
16282
16300
|
if (!stat.isDirectory()) {
|
|
16283
16301
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
16284
16302
|
}
|
|
@@ -16292,7 +16310,7 @@ var WorkspaceBrowser = class {
|
|
|
16292
16310
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
|
|
16293
16311
|
ensureCwd(cwd);
|
|
16294
16312
|
const full = resolveInsideCwd(cwd, args.path);
|
|
16295
|
-
const dirents =
|
|
16313
|
+
const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
|
|
16296
16314
|
const entries = [];
|
|
16297
16315
|
for (const d of dirents) {
|
|
16298
16316
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -16302,7 +16320,7 @@ var WorkspaceBrowser = class {
|
|
|
16302
16320
|
mtime: ""
|
|
16303
16321
|
};
|
|
16304
16322
|
try {
|
|
16305
|
-
const st =
|
|
16323
|
+
const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
|
|
16306
16324
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
16307
16325
|
if (d.isFile()) entry.size = st.size;
|
|
16308
16326
|
} catch {
|
|
@@ -16318,14 +16336,14 @@ var WorkspaceBrowser = class {
|
|
|
16318
16336
|
read(args) {
|
|
16319
16337
|
ensureCwd(args.cwd);
|
|
16320
16338
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
16321
|
-
const st =
|
|
16339
|
+
const st = import_node_fs8.default.statSync(full);
|
|
16322
16340
|
if (!st.isFile()) {
|
|
16323
16341
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
16324
16342
|
}
|
|
16325
16343
|
if (st.size > MAX_FILE_BYTES) {
|
|
16326
16344
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
16327
16345
|
}
|
|
16328
|
-
const buf =
|
|
16346
|
+
const buf = import_node_fs8.default.readFileSync(full);
|
|
16329
16347
|
const isBinary = buf.includes(0);
|
|
16330
16348
|
if (isBinary) {
|
|
16331
16349
|
return {
|
|
@@ -16347,9 +16365,9 @@ var WorkspaceBrowser = class {
|
|
|
16347
16365
|
};
|
|
16348
16366
|
|
|
16349
16367
|
// src/skills/scanner.ts
|
|
16350
|
-
var
|
|
16368
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
16351
16369
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
16352
|
-
var
|
|
16370
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
16353
16371
|
function parseFrontmatter(content) {
|
|
16354
16372
|
if (!content.startsWith("---")) return { name: "", description: "" };
|
|
16355
16373
|
const end = content.indexOf("---", 3);
|
|
@@ -16385,7 +16403,7 @@ function parseFrontmatter(content) {
|
|
|
16385
16403
|
}
|
|
16386
16404
|
function isDirLikeSync(p) {
|
|
16387
16405
|
try {
|
|
16388
|
-
return
|
|
16406
|
+
return import_node_fs9.default.statSync(p).isDirectory();
|
|
16389
16407
|
} catch {
|
|
16390
16408
|
return false;
|
|
16391
16409
|
}
|
|
@@ -16393,19 +16411,19 @@ function isDirLikeSync(p) {
|
|
|
16393
16411
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
16394
16412
|
let entries;
|
|
16395
16413
|
try {
|
|
16396
|
-
entries =
|
|
16414
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16397
16415
|
} catch {
|
|
16398
16416
|
return;
|
|
16399
16417
|
}
|
|
16400
16418
|
for (const ent of entries) {
|
|
16401
|
-
const entryPath =
|
|
16419
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16402
16420
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
16403
16421
|
let content;
|
|
16404
16422
|
try {
|
|
16405
|
-
content =
|
|
16423
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
16406
16424
|
} catch {
|
|
16407
16425
|
try {
|
|
16408
|
-
content =
|
|
16426
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
16409
16427
|
} catch {
|
|
16410
16428
|
continue;
|
|
16411
16429
|
}
|
|
@@ -16423,26 +16441,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
16423
16441
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
16424
16442
|
let entries;
|
|
16425
16443
|
try {
|
|
16426
|
-
entries =
|
|
16444
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16427
16445
|
} catch {
|
|
16428
16446
|
return;
|
|
16429
16447
|
}
|
|
16430
16448
|
for (const ent of entries) {
|
|
16431
|
-
const entryPath =
|
|
16449
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16432
16450
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
16433
16451
|
const ns = ent.name;
|
|
16434
16452
|
let subEntries;
|
|
16435
16453
|
try {
|
|
16436
|
-
subEntries =
|
|
16454
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
16437
16455
|
} catch {
|
|
16438
16456
|
continue;
|
|
16439
16457
|
}
|
|
16440
16458
|
for (const se of subEntries) {
|
|
16441
16459
|
if (!se.name.endsWith(".md")) continue;
|
|
16442
|
-
const sePath =
|
|
16460
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
16443
16461
|
let content;
|
|
16444
16462
|
try {
|
|
16445
|
-
content =
|
|
16463
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
16446
16464
|
} catch {
|
|
16447
16465
|
continue;
|
|
16448
16466
|
}
|
|
@@ -16459,7 +16477,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16459
16477
|
} else if (ent.name.endsWith(".md")) {
|
|
16460
16478
|
let content;
|
|
16461
16479
|
try {
|
|
16462
|
-
content =
|
|
16480
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
16463
16481
|
} catch {
|
|
16464
16482
|
continue;
|
|
16465
16483
|
}
|
|
@@ -16475,10 +16493,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16475
16493
|
}
|
|
16476
16494
|
}
|
|
16477
16495
|
function readInstalledPlugins(home) {
|
|
16478
|
-
const file =
|
|
16496
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
16479
16497
|
let raw;
|
|
16480
16498
|
try {
|
|
16481
|
-
raw =
|
|
16499
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
16482
16500
|
} catch {
|
|
16483
16501
|
return [];
|
|
16484
16502
|
}
|
|
@@ -16516,14 +16534,14 @@ var SkillsScanner = class {
|
|
|
16516
16534
|
list(args) {
|
|
16517
16535
|
const seen = /* @__PURE__ */ new Set();
|
|
16518
16536
|
const out = [];
|
|
16519
|
-
scanSkillDir(
|
|
16520
|
-
scanCommandDir(
|
|
16521
|
-
scanSkillDir(
|
|
16522
|
-
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);
|
|
16523
16541
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
16524
16542
|
for (const { name, root } of plugins) {
|
|
16525
|
-
scanSkillDir(
|
|
16526
|
-
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);
|
|
16527
16545
|
}
|
|
16528
16546
|
out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
16529
16547
|
return out;
|
|
@@ -16531,9 +16549,9 @@ var SkillsScanner = class {
|
|
|
16531
16549
|
};
|
|
16532
16550
|
|
|
16533
16551
|
// src/observer/session-observer.ts
|
|
16534
|
-
var
|
|
16552
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
16535
16553
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
16536
|
-
var
|
|
16554
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
16537
16555
|
var SessionObserver = class {
|
|
16538
16556
|
constructor(opts) {
|
|
16539
16557
|
this.opts = opts;
|
|
@@ -16544,14 +16562,14 @@ var SessionObserver = class {
|
|
|
16544
16562
|
watches = /* @__PURE__ */ new Map();
|
|
16545
16563
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
16546
16564
|
if (override) return override;
|
|
16547
|
-
return
|
|
16565
|
+
return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
16548
16566
|
}
|
|
16549
16567
|
start(args) {
|
|
16550
16568
|
this.stop(args.sessionId);
|
|
16551
16569
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
16552
16570
|
let size = 0;
|
|
16553
16571
|
try {
|
|
16554
|
-
size =
|
|
16572
|
+
size = import_node_fs10.default.statSync(filePath).size;
|
|
16555
16573
|
} catch {
|
|
16556
16574
|
}
|
|
16557
16575
|
const w = {
|
|
@@ -16564,10 +16582,10 @@ var SessionObserver = class {
|
|
|
16564
16582
|
adapter: args.adapter
|
|
16565
16583
|
};
|
|
16566
16584
|
try {
|
|
16567
|
-
|
|
16585
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
|
|
16568
16586
|
} catch {
|
|
16569
16587
|
}
|
|
16570
|
-
w.watcher =
|
|
16588
|
+
w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
16571
16589
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
16572
16590
|
this.poll(w);
|
|
16573
16591
|
});
|
|
@@ -16582,7 +16600,7 @@ var SessionObserver = class {
|
|
|
16582
16600
|
// reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
|
|
16583
16601
|
hydrateMetaTail(w, maxLines = 200) {
|
|
16584
16602
|
try {
|
|
16585
|
-
const raw =
|
|
16603
|
+
const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
|
|
16586
16604
|
if (!raw) return;
|
|
16587
16605
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
16588
16606
|
if (allLines.length === 0) return;
|
|
@@ -16603,7 +16621,7 @@ var SessionObserver = class {
|
|
|
16603
16621
|
poll(w) {
|
|
16604
16622
|
let size = 0;
|
|
16605
16623
|
try {
|
|
16606
|
-
size =
|
|
16624
|
+
size = import_node_fs10.default.statSync(w.filePath).size;
|
|
16607
16625
|
} catch {
|
|
16608
16626
|
return;
|
|
16609
16627
|
}
|
|
@@ -16612,11 +16630,11 @@ var SessionObserver = class {
|
|
|
16612
16630
|
w.buf = "";
|
|
16613
16631
|
}
|
|
16614
16632
|
if (size === w.lastSize) return;
|
|
16615
|
-
const fd =
|
|
16633
|
+
const fd = import_node_fs10.default.openSync(w.filePath, "r");
|
|
16616
16634
|
try {
|
|
16617
16635
|
const len = size - w.lastSize;
|
|
16618
16636
|
const buf = Buffer.alloc(len);
|
|
16619
|
-
|
|
16637
|
+
import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
|
|
16620
16638
|
w.lastSize = size;
|
|
16621
16639
|
w.buf += buf.toString("utf8");
|
|
16622
16640
|
let newlineIndex;
|
|
@@ -16630,7 +16648,7 @@ var SessionObserver = class {
|
|
|
16630
16648
|
this.maybeReportUserMessage(w.sessionId, line);
|
|
16631
16649
|
}
|
|
16632
16650
|
} finally {
|
|
16633
|
-
|
|
16651
|
+
import_node_fs10.default.closeSync(fd);
|
|
16634
16652
|
}
|
|
16635
16653
|
}
|
|
16636
16654
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -17045,10 +17063,10 @@ function isLocalhost(addr) {
|
|
|
17045
17063
|
}
|
|
17046
17064
|
|
|
17047
17065
|
// src/discovery/state-file.ts
|
|
17048
|
-
var
|
|
17049
|
-
var
|
|
17066
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
17067
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
17050
17068
|
function defaultStateFilePath(dataDir) {
|
|
17051
|
-
return
|
|
17069
|
+
return import_node_path10.default.join(dataDir, "state.json");
|
|
17052
17070
|
}
|
|
17053
17071
|
function isPidAlive(pid) {
|
|
17054
17072
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -17070,7 +17088,7 @@ var StateFileManager = class {
|
|
|
17070
17088
|
}
|
|
17071
17089
|
read() {
|
|
17072
17090
|
try {
|
|
17073
|
-
const raw =
|
|
17091
|
+
const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
|
|
17074
17092
|
const parsed = JSON.parse(raw);
|
|
17075
17093
|
return parsed;
|
|
17076
17094
|
} catch {
|
|
@@ -17084,34 +17102,34 @@ var StateFileManager = class {
|
|
|
17084
17102
|
return { status: "stale", existing };
|
|
17085
17103
|
}
|
|
17086
17104
|
write(state) {
|
|
17087
|
-
|
|
17105
|
+
import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
|
|
17088
17106
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
17089
|
-
|
|
17090
|
-
|
|
17107
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
17108
|
+
import_node_fs11.default.renameSync(tmp, this.file);
|
|
17091
17109
|
if (process.platform !== "win32") {
|
|
17092
17110
|
try {
|
|
17093
|
-
|
|
17111
|
+
import_node_fs11.default.chmodSync(this.file, 384);
|
|
17094
17112
|
} catch {
|
|
17095
17113
|
}
|
|
17096
17114
|
}
|
|
17097
17115
|
}
|
|
17098
17116
|
delete() {
|
|
17099
17117
|
try {
|
|
17100
|
-
|
|
17118
|
+
import_node_fs11.default.unlinkSync(this.file);
|
|
17101
17119
|
} catch {
|
|
17102
17120
|
}
|
|
17103
17121
|
}
|
|
17104
17122
|
};
|
|
17105
17123
|
|
|
17106
17124
|
// src/tunnel/tunnel-manager.ts
|
|
17107
|
-
var
|
|
17108
|
-
var
|
|
17125
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
17126
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
17109
17127
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
17110
17128
|
var import_node_child_process4 = require("child_process");
|
|
17111
17129
|
|
|
17112
17130
|
// src/tunnel/tunnel-store.ts
|
|
17113
|
-
var
|
|
17114
|
-
var
|
|
17131
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
17132
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
17115
17133
|
var TunnelStore = class {
|
|
17116
17134
|
constructor(filePath) {
|
|
17117
17135
|
this.filePath = filePath;
|
|
@@ -17119,7 +17137,7 @@ var TunnelStore = class {
|
|
|
17119
17137
|
filePath;
|
|
17120
17138
|
async get() {
|
|
17121
17139
|
try {
|
|
17122
|
-
const raw = await
|
|
17140
|
+
const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
|
|
17123
17141
|
const obj = JSON.parse(raw);
|
|
17124
17142
|
if (!isPersistedTunnel(obj)) return null;
|
|
17125
17143
|
return obj;
|
|
@@ -17130,22 +17148,22 @@ var TunnelStore = class {
|
|
|
17130
17148
|
}
|
|
17131
17149
|
}
|
|
17132
17150
|
async set(v) {
|
|
17133
|
-
const dir =
|
|
17134
|
-
await
|
|
17151
|
+
const dir = import_node_path11.default.dirname(this.filePath);
|
|
17152
|
+
await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
|
|
17135
17153
|
const data = JSON.stringify(v, null, 2);
|
|
17136
17154
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
17137
|
-
await
|
|
17155
|
+
await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
17138
17156
|
if (process.platform !== "win32") {
|
|
17139
17157
|
try {
|
|
17140
|
-
await
|
|
17158
|
+
await import_node_fs12.default.promises.chmod(tmp, 384);
|
|
17141
17159
|
} catch {
|
|
17142
17160
|
}
|
|
17143
17161
|
}
|
|
17144
|
-
await
|
|
17162
|
+
await import_node_fs12.default.promises.rename(tmp, this.filePath);
|
|
17145
17163
|
}
|
|
17146
17164
|
async clear() {
|
|
17147
17165
|
try {
|
|
17148
|
-
await
|
|
17166
|
+
await import_node_fs12.default.promises.unlink(this.filePath);
|
|
17149
17167
|
} catch (err) {
|
|
17150
17168
|
const code = err?.code;
|
|
17151
17169
|
if (code !== "ENOENT") throw err;
|
|
@@ -17240,9 +17258,9 @@ function escape(v) {
|
|
|
17240
17258
|
}
|
|
17241
17259
|
|
|
17242
17260
|
// src/tunnel/frpc-binary.ts
|
|
17243
|
-
var
|
|
17261
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
17244
17262
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
17245
|
-
var
|
|
17263
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
17246
17264
|
var import_node_child_process3 = require("child_process");
|
|
17247
17265
|
var import_node_stream = require("stream");
|
|
17248
17266
|
var import_promises = require("stream/promises");
|
|
@@ -17274,20 +17292,20 @@ function frpcDownloadUrl(version2, p) {
|
|
|
17274
17292
|
}
|
|
17275
17293
|
async function ensureFrpcBinary(opts) {
|
|
17276
17294
|
if (opts.override) {
|
|
17277
|
-
if (!
|
|
17295
|
+
if (!import_node_fs13.default.existsSync(opts.override)) {
|
|
17278
17296
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
17279
17297
|
}
|
|
17280
17298
|
return opts.override;
|
|
17281
17299
|
}
|
|
17282
17300
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
17283
17301
|
const platform = opts.platform ?? detectPlatform();
|
|
17284
|
-
const binDir =
|
|
17285
|
-
|
|
17302
|
+
const binDir = import_node_path12.default.join(opts.dataDir, "bin");
|
|
17303
|
+
import_node_fs13.default.mkdirSync(binDir, { recursive: true });
|
|
17286
17304
|
cleanupStaleArtifacts(binDir);
|
|
17287
|
-
const stableBin =
|
|
17288
|
-
if (
|
|
17305
|
+
const stableBin = import_node_path12.default.join(binDir, "frpc");
|
|
17306
|
+
if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
|
|
17289
17307
|
const partialBin = `${stableBin}.partial`;
|
|
17290
|
-
const tarballPath =
|
|
17308
|
+
const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
17291
17309
|
try {
|
|
17292
17310
|
const url = frpcDownloadUrl(version2, platform);
|
|
17293
17311
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -17296,8 +17314,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
17296
17314
|
} else {
|
|
17297
17315
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
17298
17316
|
}
|
|
17299
|
-
|
|
17300
|
-
|
|
17317
|
+
import_node_fs13.default.chmodSync(partialBin, 493);
|
|
17318
|
+
import_node_fs13.default.renameSync(partialBin, stableBin);
|
|
17301
17319
|
} finally {
|
|
17302
17320
|
safeUnlink(tarballPath);
|
|
17303
17321
|
safeUnlink(partialBin);
|
|
@@ -17307,15 +17325,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
17307
17325
|
function cleanupStaleArtifacts(binDir) {
|
|
17308
17326
|
let entries;
|
|
17309
17327
|
try {
|
|
17310
|
-
entries =
|
|
17328
|
+
entries = import_node_fs13.default.readdirSync(binDir);
|
|
17311
17329
|
} catch {
|
|
17312
17330
|
return;
|
|
17313
17331
|
}
|
|
17314
17332
|
for (const name of entries) {
|
|
17315
17333
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
17316
|
-
const full =
|
|
17334
|
+
const full = import_node_path12.default.join(binDir, name);
|
|
17317
17335
|
try {
|
|
17318
|
-
|
|
17336
|
+
import_node_fs13.default.rmSync(full, { recursive: true, force: true });
|
|
17319
17337
|
} catch {
|
|
17320
17338
|
}
|
|
17321
17339
|
}
|
|
@@ -17323,7 +17341,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
17323
17341
|
}
|
|
17324
17342
|
function safeUnlink(p) {
|
|
17325
17343
|
try {
|
|
17326
|
-
|
|
17344
|
+
import_node_fs13.default.unlinkSync(p);
|
|
17327
17345
|
} catch {
|
|
17328
17346
|
}
|
|
17329
17347
|
}
|
|
@@ -17334,13 +17352,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
17334
17352
|
if (!res.ok || !res.body) {
|
|
17335
17353
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
17336
17354
|
}
|
|
17337
|
-
const out =
|
|
17355
|
+
const out = import_node_fs13.default.createWriteStream(dest);
|
|
17338
17356
|
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
17339
17357
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
17340
17358
|
}
|
|
17341
17359
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
17342
|
-
const work =
|
|
17343
|
-
|
|
17360
|
+
const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
17361
|
+
import_node_fs13.default.mkdirSync(work, { recursive: true });
|
|
17344
17362
|
try {
|
|
17345
17363
|
await new Promise((resolve, reject) => {
|
|
17346
17364
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -17348,13 +17366,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
17348
17366
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
17349
17367
|
});
|
|
17350
17368
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
17351
|
-
const src =
|
|
17352
|
-
if (!
|
|
17369
|
+
const src = import_node_path12.default.join(work, dirName, "frpc");
|
|
17370
|
+
if (!import_node_fs13.default.existsSync(src)) {
|
|
17353
17371
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
17354
17372
|
}
|
|
17355
|
-
|
|
17373
|
+
import_node_fs13.default.copyFileSync(src, destBin);
|
|
17356
17374
|
} finally {
|
|
17357
|
-
|
|
17375
|
+
import_node_fs13.default.rmSync(work, { recursive: true, force: true });
|
|
17358
17376
|
}
|
|
17359
17377
|
}
|
|
17360
17378
|
|
|
@@ -17363,7 +17381,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
17363
17381
|
var TunnelManager = class {
|
|
17364
17382
|
constructor(deps) {
|
|
17365
17383
|
this.deps = deps;
|
|
17366
|
-
this.store = deps.store ?? new TunnelStore(
|
|
17384
|
+
this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
|
|
17367
17385
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
17368
17386
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
17369
17387
|
}
|
|
@@ -17480,7 +17498,7 @@ var TunnelManager = class {
|
|
|
17480
17498
|
dataDir: this.deps.dataDir,
|
|
17481
17499
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
17482
17500
|
});
|
|
17483
|
-
const tomlPath =
|
|
17501
|
+
const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
|
|
17484
17502
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
|
|
17485
17503
|
const toml = buildFrpcToml({
|
|
17486
17504
|
serverAddr: t.frpsHost,
|
|
@@ -17491,12 +17509,12 @@ var TunnelManager = class {
|
|
|
17491
17509
|
localPort,
|
|
17492
17510
|
logLevel: "info"
|
|
17493
17511
|
});
|
|
17494
|
-
await
|
|
17512
|
+
await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
17495
17513
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
17496
17514
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17497
17515
|
});
|
|
17498
|
-
const logFilePath =
|
|
17499
|
-
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 });
|
|
17500
17518
|
logStream.on("error", () => {
|
|
17501
17519
|
});
|
|
17502
17520
|
const tee = (chunk) => {
|
|
@@ -17588,12 +17606,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
17588
17606
|
}
|
|
17589
17607
|
|
|
17590
17608
|
// src/auth-store.ts
|
|
17591
|
-
var
|
|
17592
|
-
var
|
|
17609
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
17610
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
17593
17611
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
17594
17612
|
var AUTH_FILE_NAME = "auth.json";
|
|
17595
17613
|
function authFilePath(dataDir) {
|
|
17596
|
-
return
|
|
17614
|
+
return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
|
|
17597
17615
|
}
|
|
17598
17616
|
function loadOrCreateAuthToken(opts) {
|
|
17599
17617
|
const file = authFilePath(opts.dataDir);
|
|
@@ -17609,7 +17627,7 @@ function defaultGenerate() {
|
|
|
17609
17627
|
}
|
|
17610
17628
|
function readAuthFile(file) {
|
|
17611
17629
|
try {
|
|
17612
|
-
const raw =
|
|
17630
|
+
const raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
17613
17631
|
const parsed = JSON.parse(raw);
|
|
17614
17632
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
17615
17633
|
return {
|
|
@@ -17625,20 +17643,20 @@ function readAuthFile(file) {
|
|
|
17625
17643
|
}
|
|
17626
17644
|
}
|
|
17627
17645
|
function writeAuthFile(file, content) {
|
|
17628
|
-
|
|
17629
|
-
|
|
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 });
|
|
17630
17648
|
try {
|
|
17631
|
-
|
|
17649
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
17632
17650
|
} catch {
|
|
17633
17651
|
}
|
|
17634
17652
|
}
|
|
17635
17653
|
|
|
17636
17654
|
// src/session/fork.ts
|
|
17637
|
-
var
|
|
17655
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
17638
17656
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
17639
|
-
var
|
|
17657
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
17640
17658
|
function readJsonlEntries(file) {
|
|
17641
|
-
const raw =
|
|
17659
|
+
const raw = import_node_fs16.default.readFileSync(file, "utf8");
|
|
17642
17660
|
const out = [];
|
|
17643
17661
|
for (const line of raw.split("\n")) {
|
|
17644
17662
|
const t = line.trim();
|
|
@@ -17651,10 +17669,10 @@ function readJsonlEntries(file) {
|
|
|
17651
17669
|
return out;
|
|
17652
17670
|
}
|
|
17653
17671
|
function forkSession(input) {
|
|
17654
|
-
const baseDir = input.baseDir ??
|
|
17655
|
-
const projectDir =
|
|
17656
|
-
const sourceFile =
|
|
17657
|
-
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)) {
|
|
17658
17676
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
17659
17677
|
}
|
|
17660
17678
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -17684,9 +17702,9 @@ function forkSession(input) {
|
|
|
17684
17702
|
}
|
|
17685
17703
|
forkedLines.push(JSON.stringify(forked));
|
|
17686
17704
|
}
|
|
17687
|
-
const forkedFilePath =
|
|
17688
|
-
|
|
17689
|
-
|
|
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 });
|
|
17690
17708
|
return { forkedToolSessionId, forkedFilePath };
|
|
17691
17709
|
}
|
|
17692
17710
|
|
|
@@ -17807,11 +17825,6 @@ function buildSessionHandlers(deps) {
|
|
|
17807
17825
|
const { response, broadcast } = manager.pin(args);
|
|
17808
17826
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
17809
17827
|
};
|
|
17810
|
-
const reorderPins = async (frame) => {
|
|
17811
|
-
const args = SessionReorderPinsArgs.parse(frame);
|
|
17812
|
-
const { response, broadcast } = manager.reorderPins(args);
|
|
17813
|
-
return { response: { type: "session:reorderPins", ...response }, broadcast };
|
|
17814
|
-
};
|
|
17815
17828
|
const answerQuestion = async (frame) => {
|
|
17816
17829
|
const args = AnswerQuestionArgs.parse(frame);
|
|
17817
17830
|
const { response, broadcast } = manager.answerQuestion(args);
|
|
@@ -17837,7 +17850,6 @@ function buildSessionHandlers(deps) {
|
|
|
17837
17850
|
"session:subscribe": subscribe,
|
|
17838
17851
|
"session:unsubscribe": unsubscribe,
|
|
17839
17852
|
"session:pin": pin,
|
|
17840
|
-
"session:reorderPins": reorderPins,
|
|
17841
17853
|
"session:answerQuestion": answerQuestion
|
|
17842
17854
|
};
|
|
17843
17855
|
}
|
|
@@ -17948,9 +17960,9 @@ function buildWorkspaceHandlers(deps) {
|
|
|
17948
17960
|
|
|
17949
17961
|
// src/workspace/git.ts
|
|
17950
17962
|
var import_node_child_process5 = require("child_process");
|
|
17951
|
-
var
|
|
17963
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
17952
17964
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
17953
|
-
var
|
|
17965
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
17954
17966
|
var import_node_util = require("util");
|
|
17955
17967
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
17956
17968
|
function formatChildProcessError(err) {
|
|
@@ -17965,9 +17977,9 @@ function formatChildProcessError(err) {
|
|
|
17965
17977
|
return e.message ?? "unknown error";
|
|
17966
17978
|
}
|
|
17967
17979
|
function normalizePath(p) {
|
|
17968
|
-
const resolved =
|
|
17980
|
+
const resolved = import_node_path16.default.resolve(p);
|
|
17969
17981
|
try {
|
|
17970
|
-
return
|
|
17982
|
+
return import_node_fs17.default.realpathSync(resolved);
|
|
17971
17983
|
} catch {
|
|
17972
17984
|
return resolved;
|
|
17973
17985
|
}
|
|
@@ -18068,13 +18080,13 @@ function flattenToDirName(branch) {
|
|
|
18068
18080
|
}
|
|
18069
18081
|
function encodeClaudeProjectDir(absPath) {
|
|
18070
18082
|
if (!absPath || typeof absPath !== "string") return "";
|
|
18071
|
-
let canonical =
|
|
18083
|
+
let canonical = import_node_path16.default.resolve(absPath);
|
|
18072
18084
|
try {
|
|
18073
|
-
canonical =
|
|
18085
|
+
canonical = import_node_fs17.default.realpathSync(canonical);
|
|
18074
18086
|
} catch {
|
|
18075
18087
|
try {
|
|
18076
|
-
const parent =
|
|
18077
|
-
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));
|
|
18078
18090
|
} catch {
|
|
18079
18091
|
}
|
|
18080
18092
|
}
|
|
@@ -18098,11 +18110,11 @@ async function createWorktree(input) {
|
|
|
18098
18110
|
if (!isGitRoot) {
|
|
18099
18111
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
18100
18112
|
}
|
|
18101
|
-
const parent =
|
|
18102
|
-
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)) {
|
|
18103
18115
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
18104
18116
|
}
|
|
18105
|
-
const worktreeRoot =
|
|
18117
|
+
const worktreeRoot = import_node_path16.default.join(parent, dirName);
|
|
18106
18118
|
try {
|
|
18107
18119
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
|
|
18108
18120
|
timeout: 3e3
|
|
@@ -18119,7 +18131,7 @@ async function createWorktree(input) {
|
|
|
18119
18131
|
const msg = err.message;
|
|
18120
18132
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
18121
18133
|
}
|
|
18122
|
-
if (
|
|
18134
|
+
if (import_node_fs17.default.existsSync(worktreeRoot)) {
|
|
18123
18135
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
18124
18136
|
}
|
|
18125
18137
|
try {
|
|
@@ -18147,8 +18159,8 @@ async function removeWorktree(input) {
|
|
|
18147
18159
|
);
|
|
18148
18160
|
const gitCommonDir = stdout.trim();
|
|
18149
18161
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
18150
|
-
const absGitCommon =
|
|
18151
|
-
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);
|
|
18152
18164
|
} catch {
|
|
18153
18165
|
repoRoot = null;
|
|
18154
18166
|
}
|
|
@@ -18160,7 +18172,7 @@ async function removeWorktree(input) {
|
|
|
18160
18172
|
} catch (err) {
|
|
18161
18173
|
const stderr = err.stderr ?? "";
|
|
18162
18174
|
const lower = stderr.toLowerCase();
|
|
18163
|
-
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);
|
|
18164
18176
|
if (!vanished) {
|
|
18165
18177
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
18166
18178
|
}
|
|
@@ -18179,10 +18191,10 @@ async function removeWorktree(input) {
|
|
|
18179
18191
|
try {
|
|
18180
18192
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
18181
18193
|
if (encoded) {
|
|
18182
|
-
const projectsRoot =
|
|
18183
|
-
const target =
|
|
18184
|
-
if (target.startsWith(projectsRoot +
|
|
18185
|
-
|
|
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 });
|
|
18186
18198
|
}
|
|
18187
18199
|
}
|
|
18188
18200
|
} catch {
|
|
@@ -18309,7 +18321,7 @@ function buildMethodHandlers(deps) {
|
|
|
18309
18321
|
async function startDaemon(config) {
|
|
18310
18322
|
const logger = createLogger({
|
|
18311
18323
|
level: config.logLevel,
|
|
18312
|
-
file:
|
|
18324
|
+
file: import_node_path17.default.join(config.dataDir, "clawd.log")
|
|
18313
18325
|
});
|
|
18314
18326
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
18315
18327
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -18349,6 +18361,7 @@ async function startDaemon(config) {
|
|
|
18349
18361
|
logger,
|
|
18350
18362
|
getAdapter,
|
|
18351
18363
|
historyReader: history,
|
|
18364
|
+
dataDir: config.dataDir,
|
|
18352
18365
|
broadcastFrame: (frame, target) => {
|
|
18353
18366
|
if (target === "all") {
|
|
18354
18367
|
transport?.broadcastAll(frame);
|
|
@@ -18471,8 +18484,8 @@ async function startDaemon(config) {
|
|
|
18471
18484
|
const lines = [
|
|
18472
18485
|
`Tunnel: ${r.url}`,
|
|
18473
18486
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
18474
|
-
`Frpc config: ${
|
|
18475
|
-
`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")}`
|
|
18476
18489
|
];
|
|
18477
18490
|
const width = Math.max(...lines.map((l) => l.length));
|
|
18478
18491
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -18485,8 +18498,8 @@ ${bar}
|
|
|
18485
18498
|
|
|
18486
18499
|
`);
|
|
18487
18500
|
try {
|
|
18488
|
-
const connectPath =
|
|
18489
|
-
|
|
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 });
|
|
18490
18503
|
} catch {
|
|
18491
18504
|
}
|
|
18492
18505
|
} catch (err) {
|