@clawos-dev/clawd 0.2.25-beta.35.0347a17 → 0.2.25
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 +362 -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);
|
|
@@ -8144,6 +8144,7 @@ var METHOD_NAMES = [
|
|
|
8144
8144
|
"session:subscribe",
|
|
8145
8145
|
"session:unsubscribe",
|
|
8146
8146
|
"session:pin",
|
|
8147
|
+
"session:reorderPins",
|
|
8147
8148
|
"permission:respond",
|
|
8148
8149
|
// AskUserQuestion 表单回写:UI 答完所有 question 后调用,daemon 把答案合并进 updated_input
|
|
8149
8150
|
// 写一条 control_response 到 CC stdin(详见 events.ts session:question JSDoc)
|
|
@@ -8686,8 +8687,8 @@ function getErrorMap() {
|
|
|
8686
8687
|
|
|
8687
8688
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
8688
8689
|
var makeIssue = (params) => {
|
|
8689
|
-
const { data, path:
|
|
8690
|
-
const fullPath = [...
|
|
8690
|
+
const { data, path: path18, errorMaps, issueData } = params;
|
|
8691
|
+
const fullPath = [...path18, ...issueData.path || []];
|
|
8691
8692
|
const fullIssue = {
|
|
8692
8693
|
...issueData,
|
|
8693
8694
|
path: fullPath
|
|
@@ -8803,11 +8804,11 @@ var errorUtil;
|
|
|
8803
8804
|
|
|
8804
8805
|
// ../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
8805
8806
|
var ParseInputLazyPath = class {
|
|
8806
|
-
constructor(parent, value,
|
|
8807
|
+
constructor(parent, value, path18, key) {
|
|
8807
8808
|
this._cachedPath = [];
|
|
8808
8809
|
this.parent = parent;
|
|
8809
8810
|
this.data = value;
|
|
8810
|
-
this._path =
|
|
8811
|
+
this._path = path18;
|
|
8811
8812
|
this._key = key;
|
|
8812
8813
|
}
|
|
8813
8814
|
get path() {
|
|
@@ -12326,6 +12327,9 @@ var SessionFileSchema = external_exports.object({
|
|
|
12326
12327
|
permissionRules: external_exports.array(AllowRuleSchema).optional(),
|
|
12327
12328
|
// Sidebar 置顶时间戳;null/undefined 表示未置顶
|
|
12328
12329
|
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(),
|
|
12329
12333
|
// 用户在 NewSessionDialog 或 Edit modal 选择的 icon 标识;UI 端做 enum 兜底
|
|
12330
12334
|
iconKey: external_exports.string().optional(),
|
|
12331
12335
|
// NewSessionDialog 勾选 worktree 创建的 session 才会持久化这两个字段
|
|
@@ -12657,6 +12661,9 @@ var SessionPinArgs = external_exports.object({
|
|
|
12657
12661
|
sessionId: external_exports.string().min(1),
|
|
12658
12662
|
pinned: external_exports.boolean()
|
|
12659
12663
|
});
|
|
12664
|
+
var SessionReorderPinsArgs = external_exports.object({
|
|
12665
|
+
orderedIds: external_exports.array(external_exports.string().min(1)).min(1)
|
|
12666
|
+
});
|
|
12660
12667
|
var GitRootArgs = external_exports.object({ cwd: external_exports.string().min(1) });
|
|
12661
12668
|
var GitRootResponseSchema = external_exports.object({
|
|
12662
12669
|
isGitRoot: external_exports.boolean(),
|
|
@@ -12812,7 +12819,7 @@ var SessionStore = class {
|
|
|
12812
12819
|
};
|
|
12813
12820
|
|
|
12814
12821
|
// src/session/manager.ts
|
|
12815
|
-
var
|
|
12822
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
12816
12823
|
|
|
12817
12824
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
12818
12825
|
var byteToHex = [];
|
|
@@ -13413,6 +13420,58 @@ function splitStdoutChunk(buf, chunk) {
|
|
|
13413
13420
|
return { newBuf: next, lines };
|
|
13414
13421
|
}
|
|
13415
13422
|
|
|
13423
|
+
// src/ipc-recorder.ts
|
|
13424
|
+
var import_node_fs4 = __toESM(require("fs"), 1);
|
|
13425
|
+
var import_node_path4 = __toESM(require("path"), 1);
|
|
13426
|
+
function tsForFilename(ms) {
|
|
13427
|
+
return new Date(ms).toISOString().replace(/[:.]/g, "-");
|
|
13428
|
+
}
|
|
13429
|
+
function startRecorder(opts) {
|
|
13430
|
+
if (opts.env.CLAWD_RECORD_IPC !== "1") return null;
|
|
13431
|
+
if (!opts.dataDir) return null;
|
|
13432
|
+
if (!opts.sessionId || opts.sessionId.includes("..") || opts.sessionId.includes("/") || opts.sessionId.includes("\\") || opts.sessionId.startsWith(".")) {
|
|
13433
|
+
return null;
|
|
13434
|
+
}
|
|
13435
|
+
const now = opts.now ?? Date.now;
|
|
13436
|
+
const dir = import_node_path4.default.join(opts.dataDir, "ipc-recordings", opts.sessionId);
|
|
13437
|
+
const filePath = import_node_path4.default.join(dir, `${tsForFilename(now())}.jsonl`);
|
|
13438
|
+
let stream = null;
|
|
13439
|
+
let closedResolve;
|
|
13440
|
+
const closed = new Promise((resolve) => {
|
|
13441
|
+
closedResolve = resolve;
|
|
13442
|
+
});
|
|
13443
|
+
let exited = false;
|
|
13444
|
+
const ensureStream = () => {
|
|
13445
|
+
if (stream) return stream;
|
|
13446
|
+
import_node_fs4.default.mkdirSync(dir, { recursive: true });
|
|
13447
|
+
stream = import_node_fs4.default.createWriteStream(filePath, { flags: "a" });
|
|
13448
|
+
stream.on("close", () => closedResolve());
|
|
13449
|
+
return stream;
|
|
13450
|
+
};
|
|
13451
|
+
const writeLine = (s, chunk) => {
|
|
13452
|
+
if (exited) return;
|
|
13453
|
+
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
13454
|
+
const line = JSON.stringify({ ts: now(), stream: s, chunk: text }) + "\n";
|
|
13455
|
+
ensureStream().write(line);
|
|
13456
|
+
};
|
|
13457
|
+
opts.proc.stdout?.on("data", (chunk) => writeLine("stdout", chunk));
|
|
13458
|
+
opts.proc.stderr?.on("data", (chunk) => writeLine("stderr", chunk));
|
|
13459
|
+
opts.proc.on("exit", () => {
|
|
13460
|
+
exited = true;
|
|
13461
|
+
if (stream) {
|
|
13462
|
+
stream.end();
|
|
13463
|
+
} else {
|
|
13464
|
+
closedResolve();
|
|
13465
|
+
}
|
|
13466
|
+
});
|
|
13467
|
+
return {
|
|
13468
|
+
tapStdinWrite(chunk) {
|
|
13469
|
+
writeLine("stdin", chunk);
|
|
13470
|
+
},
|
|
13471
|
+
closed
|
|
13472
|
+
};
|
|
13473
|
+
}
|
|
13474
|
+
|
|
13416
13475
|
// src/session/runner.ts
|
|
13417
13476
|
var DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 1e4;
|
|
13418
13477
|
function encodeAllowWithInputControlResponse(requestId, updatedInput) {
|
|
@@ -13443,6 +13502,8 @@ var SessionRunner = class {
|
|
|
13443
13502
|
pendingControlRequests = /* @__PURE__ */ new Map();
|
|
13444
13503
|
// waitUntilStopped 排队的 resolve 回调;reducer 把 procAlive 翻成 false 后批量触发
|
|
13445
13504
|
stopWaiters = [];
|
|
13505
|
+
// IPC recorder(CLAWD_RECORD_IPC=1 时启用);null 表示当前 spawn 未启用 / 已退出
|
|
13506
|
+
recorder = null;
|
|
13446
13507
|
getState() {
|
|
13447
13508
|
return this.state;
|
|
13448
13509
|
}
|
|
@@ -13532,6 +13593,7 @@ var SessionRunner = class {
|
|
|
13532
13593
|
this.pendingControlRequests.set(requestId, { resolve, reject, timer });
|
|
13533
13594
|
try {
|
|
13534
13595
|
proc.stdin?.write(payload);
|
|
13596
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13535
13597
|
} catch (err) {
|
|
13536
13598
|
clearTimeout(timer);
|
|
13537
13599
|
this.pendingControlRequests.delete(requestId);
|
|
@@ -13587,10 +13649,14 @@ var SessionRunner = class {
|
|
|
13587
13649
|
break;
|
|
13588
13650
|
case "write-stdin":
|
|
13589
13651
|
this.proc?.stdin?.write(effect.payload);
|
|
13652
|
+
this.recorder?.tapStdinWrite(effect.payload);
|
|
13590
13653
|
break;
|
|
13591
|
-
case "send-control-response-allow-with-input":
|
|
13592
|
-
|
|
13654
|
+
case "send-control-response-allow-with-input": {
|
|
13655
|
+
const payload = encodeAllowWithInputControlResponse(effect.requestId, effect.updatedInput);
|
|
13656
|
+
this.proc?.stdin?.write(payload);
|
|
13657
|
+
this.recorder?.tapStdinWrite(payload);
|
|
13593
13658
|
break;
|
|
13659
|
+
}
|
|
13594
13660
|
case "persist-file":
|
|
13595
13661
|
try {
|
|
13596
13662
|
this.hooks.store.write(effect.file);
|
|
@@ -13620,6 +13686,13 @@ var SessionRunner = class {
|
|
|
13620
13686
|
const proc = this.hooks.spawnOverride ? this.hooks.spawnOverride(ctx) : this.hooks.adapter.spawn(ctx);
|
|
13621
13687
|
this.proc = proc;
|
|
13622
13688
|
this.stdoutBuf = "";
|
|
13689
|
+
this.recorder = startRecorder({
|
|
13690
|
+
proc,
|
|
13691
|
+
sessionId: this.state.file.sessionId,
|
|
13692
|
+
dataDir: this.hooks.dataDir,
|
|
13693
|
+
env: this.hooks.recordEnv ?? process.env,
|
|
13694
|
+
now: this.hooks.now
|
|
13695
|
+
});
|
|
13623
13696
|
proc.stdout?.on("data", (chunk) => {
|
|
13624
13697
|
const { newBuf, lines } = splitStdoutChunk(this.stdoutBuf, chunk);
|
|
13625
13698
|
this.stdoutBuf = newBuf;
|
|
@@ -13634,6 +13707,7 @@ var SessionRunner = class {
|
|
|
13634
13707
|
});
|
|
13635
13708
|
proc.on("exit", (code) => {
|
|
13636
13709
|
this.proc = null;
|
|
13710
|
+
this.recorder = null;
|
|
13637
13711
|
this.rejectAllPending(new Error("session gone"));
|
|
13638
13712
|
this.input({ kind: "proc-exit", code });
|
|
13639
13713
|
});
|
|
@@ -13760,7 +13834,8 @@ var SessionManager = class {
|
|
|
13760
13834
|
now: this.deps.now,
|
|
13761
13835
|
bufferCap: this.deps.bufferCap,
|
|
13762
13836
|
// adapter 自己持有模型表 + 兜底逻辑(contains / opus-1M / [1m] 等),manager 不再 cache 转发
|
|
13763
|
-
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId)
|
|
13837
|
+
resolveContextWindow: (tool, modelId) => this.deps.getAdapter(tool).resolveContextWindow(modelId),
|
|
13838
|
+
dataDir: this.deps.dataDir
|
|
13764
13839
|
});
|
|
13765
13840
|
return runner;
|
|
13766
13841
|
}
|
|
@@ -13791,7 +13866,7 @@ var SessionManager = class {
|
|
|
13791
13866
|
// ---- 命令方法:均返回 { response, broadcast[] },由 dispatcher 聚合 ----
|
|
13792
13867
|
create(args) {
|
|
13793
13868
|
try {
|
|
13794
|
-
const stat =
|
|
13869
|
+
const stat = import_node_fs5.default.statSync(args.cwd);
|
|
13795
13870
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
13796
13871
|
} catch {
|
|
13797
13872
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
|
|
@@ -13832,6 +13907,49 @@ var SessionManager = class {
|
|
|
13832
13907
|
this.deps.store.write(updated);
|
|
13833
13908
|
return { response: updated, broadcast: [] };
|
|
13834
13909
|
}
|
|
13910
|
+
// sidebar 拖拽完成 → 整体重写 pinned root 的 pinSortOrder(按 orderedIds 下标 0,1,2...)
|
|
13911
|
+
// orderedIds 必须正好覆盖所有当前 pinned root(既不能漏,也不能含 unpinned id)
|
|
13912
|
+
reorderPins(args) {
|
|
13913
|
+
const all = this.deps.store.list();
|
|
13914
|
+
const currentPinnedIds = new Set(
|
|
13915
|
+
all.filter((f) => typeof f.pinnedAt === "number").map((f) => f.sessionId)
|
|
13916
|
+
);
|
|
13917
|
+
const incoming = new Set(args.orderedIds);
|
|
13918
|
+
if (incoming.size !== args.orderedIds.length) {
|
|
13919
|
+
throw new Error("reorderPins: orderedIds contains duplicate ids");
|
|
13920
|
+
}
|
|
13921
|
+
if (currentPinnedIds.size !== incoming.size || [...currentPinnedIds].some((id) => !incoming.has(id))) {
|
|
13922
|
+
throw new Error(
|
|
13923
|
+
"reorderPins: orderedIds must cover exactly the current pinned root set"
|
|
13924
|
+
);
|
|
13925
|
+
}
|
|
13926
|
+
const broadcast = [];
|
|
13927
|
+
const updatedFiles = [];
|
|
13928
|
+
args.orderedIds.forEach((sessionId, index) => {
|
|
13929
|
+
const runner = this.runners.get(sessionId);
|
|
13930
|
+
if (runner) {
|
|
13931
|
+
const { value, broadcast: b } = this.withCollector(() => {
|
|
13932
|
+
runner.input({
|
|
13933
|
+
kind: "command",
|
|
13934
|
+
command: { kind: "update", patch: { pinSortOrder: index } }
|
|
13935
|
+
});
|
|
13936
|
+
return runner.getState().file;
|
|
13937
|
+
});
|
|
13938
|
+
updatedFiles.push(value);
|
|
13939
|
+
broadcast.push(...b);
|
|
13940
|
+
} else {
|
|
13941
|
+
const existing = this.getFile(sessionId);
|
|
13942
|
+
const updated = {
|
|
13943
|
+
...existing,
|
|
13944
|
+
pinSortOrder: index,
|
|
13945
|
+
updatedAt: nowIso2(this.deps)
|
|
13946
|
+
};
|
|
13947
|
+
this.deps.store.write(updated);
|
|
13948
|
+
updatedFiles.push(updated);
|
|
13949
|
+
}
|
|
13950
|
+
});
|
|
13951
|
+
return { response: { sessions: updatedFiles }, broadcast };
|
|
13952
|
+
}
|
|
13835
13953
|
list() {
|
|
13836
13954
|
return { response: { sessions: this.deps.store.list() }, broadcast: [] };
|
|
13837
13955
|
}
|
|
@@ -14237,14 +14355,14 @@ var SessionManager = class {
|
|
|
14237
14355
|
// src/tools/claude.ts
|
|
14238
14356
|
var import_node_child_process = require("child_process");
|
|
14239
14357
|
var import_node_child_process2 = require("child_process");
|
|
14240
|
-
var
|
|
14358
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
14241
14359
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
14242
|
-
var
|
|
14360
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
14243
14361
|
|
|
14244
14362
|
// src/tools/claude-history.ts
|
|
14245
|
-
var
|
|
14363
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
14246
14364
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
14247
|
-
var
|
|
14365
|
+
var import_node_path5 = __toESM(require("path"), 1);
|
|
14248
14366
|
|
|
14249
14367
|
// ../node_modules/.pnpm/diff@7.0.0/node_modules/diff/lib/index.mjs
|
|
14250
14368
|
function Diff() {
|
|
@@ -14348,11 +14466,11 @@ Diff.prototype = {
|
|
|
14348
14466
|
}
|
|
14349
14467
|
}
|
|
14350
14468
|
},
|
|
14351
|
-
addToPath: function addToPath(
|
|
14352
|
-
var last =
|
|
14469
|
+
addToPath: function addToPath(path18, added, removed, oldPosInc, options) {
|
|
14470
|
+
var last = path18.lastComponent;
|
|
14353
14471
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14354
14472
|
return {
|
|
14355
|
-
oldPos:
|
|
14473
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14356
14474
|
lastComponent: {
|
|
14357
14475
|
count: last.count + 1,
|
|
14358
14476
|
added,
|
|
@@ -14362,7 +14480,7 @@ Diff.prototype = {
|
|
|
14362
14480
|
};
|
|
14363
14481
|
} else {
|
|
14364
14482
|
return {
|
|
14365
|
-
oldPos:
|
|
14483
|
+
oldPos: path18.oldPos + oldPosInc,
|
|
14366
14484
|
lastComponent: {
|
|
14367
14485
|
count: 1,
|
|
14368
14486
|
added,
|
|
@@ -15021,7 +15139,7 @@ function hashDirToCwd(hash) {
|
|
|
15021
15139
|
}
|
|
15022
15140
|
function safeStatMtime(p) {
|
|
15023
15141
|
try {
|
|
15024
|
-
return
|
|
15142
|
+
return import_node_fs6.default.statSync(p).mtimeMs;
|
|
15025
15143
|
} catch {
|
|
15026
15144
|
return 0;
|
|
15027
15145
|
}
|
|
@@ -15029,7 +15147,7 @@ function safeStatMtime(p) {
|
|
|
15029
15147
|
function readJsonlLines(file) {
|
|
15030
15148
|
let raw;
|
|
15031
15149
|
try {
|
|
15032
|
-
raw =
|
|
15150
|
+
raw = import_node_fs6.default.readFileSync(file, "utf8");
|
|
15033
15151
|
} catch (err) {
|
|
15034
15152
|
if (err.code === "ENOENT") return [];
|
|
15035
15153
|
throw err;
|
|
@@ -15221,10 +15339,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
15221
15339
|
const memories = raw.map((m) => {
|
|
15222
15340
|
if (!m || typeof m !== "object") return null;
|
|
15223
15341
|
const rec = m;
|
|
15224
|
-
const
|
|
15342
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15225
15343
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15226
|
-
if (!
|
|
15227
|
-
const entry = { path:
|
|
15344
|
+
if (!path18 || content == null) return null;
|
|
15345
|
+
const entry = { path: path18, content };
|
|
15228
15346
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
15229
15347
|
return entry;
|
|
15230
15348
|
}).filter((m) => m !== null);
|
|
@@ -15260,8 +15378,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
15260
15378
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
15261
15379
|
if (backupFileName === null) return null;
|
|
15262
15380
|
try {
|
|
15263
|
-
return
|
|
15264
|
-
|
|
15381
|
+
return import_node_fs6.default.readFileSync(
|
|
15382
|
+
import_node_path5.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
15265
15383
|
"utf8"
|
|
15266
15384
|
);
|
|
15267
15385
|
} catch {
|
|
@@ -15270,7 +15388,7 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
15270
15388
|
}
|
|
15271
15389
|
function readCurrentContent(filePath) {
|
|
15272
15390
|
try {
|
|
15273
|
-
return
|
|
15391
|
+
return import_node_fs6.default.readFileSync(filePath, "utf8");
|
|
15274
15392
|
} catch (err) {
|
|
15275
15393
|
if (err.code === "ENOENT") return null;
|
|
15276
15394
|
return null;
|
|
@@ -15282,14 +15400,14 @@ var ClaudeHistoryReader = class {
|
|
|
15282
15400
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
15283
15401
|
fileHistoryRoot;
|
|
15284
15402
|
constructor(opts = {}) {
|
|
15285
|
-
const base = opts.baseDir ??
|
|
15286
|
-
this.projectsRoot =
|
|
15287
|
-
this.fileHistoryRoot =
|
|
15403
|
+
const base = opts.baseDir ?? import_node_path5.default.join(import_node_os2.default.homedir(), ".claude");
|
|
15404
|
+
this.projectsRoot = import_node_path5.default.join(base, "projects");
|
|
15405
|
+
this.fileHistoryRoot = import_node_path5.default.join(base, "file-history");
|
|
15288
15406
|
}
|
|
15289
15407
|
async listProjects() {
|
|
15290
15408
|
let entries;
|
|
15291
15409
|
try {
|
|
15292
|
-
entries =
|
|
15410
|
+
entries = import_node_fs6.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
15293
15411
|
} catch (err) {
|
|
15294
15412
|
if (err.code === "ENOENT") return [];
|
|
15295
15413
|
throw err;
|
|
@@ -15297,9 +15415,9 @@ var ClaudeHistoryReader = class {
|
|
|
15297
15415
|
const out = [];
|
|
15298
15416
|
for (const ent of entries) {
|
|
15299
15417
|
if (!ent.isDirectory()) continue;
|
|
15300
|
-
const dir =
|
|
15301
|
-
const files =
|
|
15302
|
-
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(
|
|
15418
|
+
const dir = import_node_path5.default.join(this.projectsRoot, ent.name);
|
|
15419
|
+
const files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15420
|
+
const updatedAtMs = files.reduce((m, f) => Math.max(m, safeStatMtime(import_node_path5.default.join(dir, f))), 0);
|
|
15303
15421
|
out.push({
|
|
15304
15422
|
projectPath: hashDirToCwd(ent.name),
|
|
15305
15423
|
hashDir: ent.name,
|
|
@@ -15311,17 +15429,17 @@ var ClaudeHistoryReader = class {
|
|
|
15311
15429
|
return out;
|
|
15312
15430
|
}
|
|
15313
15431
|
async listSessions(args) {
|
|
15314
|
-
const dir =
|
|
15432
|
+
const dir = import_node_path5.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
15315
15433
|
let files;
|
|
15316
15434
|
try {
|
|
15317
|
-
files =
|
|
15435
|
+
files = import_node_fs6.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
15318
15436
|
} catch (err) {
|
|
15319
15437
|
if (err.code === "ENOENT") return [];
|
|
15320
15438
|
throw err;
|
|
15321
15439
|
}
|
|
15322
15440
|
const out = [];
|
|
15323
15441
|
for (const f of files) {
|
|
15324
|
-
const full =
|
|
15442
|
+
const full = import_node_path5.default.join(dir, f);
|
|
15325
15443
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
15326
15444
|
const lines = readJsonlLines(full);
|
|
15327
15445
|
let summary = "";
|
|
@@ -15376,7 +15494,7 @@ var ClaudeHistoryReader = class {
|
|
|
15376
15494
|
return out;
|
|
15377
15495
|
}
|
|
15378
15496
|
async read(args) {
|
|
15379
|
-
const file =
|
|
15497
|
+
const file = import_node_path5.default.join(
|
|
15380
15498
|
this.projectsRoot,
|
|
15381
15499
|
cwdToHashDir(args.cwd),
|
|
15382
15500
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15409,7 +15527,7 @@ var ClaudeHistoryReader = class {
|
|
|
15409
15527
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
15410
15528
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
15411
15529
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
15412
|
-
const dir =
|
|
15530
|
+
const dir = import_node_path5.default.join(
|
|
15413
15531
|
this.projectsRoot,
|
|
15414
15532
|
cwdToHashDir(cwd),
|
|
15415
15533
|
toolSessionId,
|
|
@@ -15417,7 +15535,7 @@ var ClaudeHistoryReader = class {
|
|
|
15417
15535
|
);
|
|
15418
15536
|
let entries;
|
|
15419
15537
|
try {
|
|
15420
|
-
entries =
|
|
15538
|
+
entries = import_node_fs6.default.readdirSync(dir, { withFileTypes: true });
|
|
15421
15539
|
} catch (err) {
|
|
15422
15540
|
if (err.code === "ENOENT") return null;
|
|
15423
15541
|
return null;
|
|
@@ -15427,7 +15545,7 @@ var ClaudeHistoryReader = class {
|
|
|
15427
15545
|
if (!e.isFile()) continue;
|
|
15428
15546
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
15429
15547
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
15430
|
-
const filePath =
|
|
15548
|
+
const filePath = import_node_path5.default.join(dir, e.name);
|
|
15431
15549
|
const lines = readJsonlLines(filePath);
|
|
15432
15550
|
let firstText = "";
|
|
15433
15551
|
let messageCount = 0;
|
|
@@ -15444,7 +15562,7 @@ var ClaudeHistoryReader = class {
|
|
|
15444
15562
|
return out;
|
|
15445
15563
|
}
|
|
15446
15564
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
15447
|
-
const file =
|
|
15565
|
+
const file = import_node_path5.default.join(
|
|
15448
15566
|
this.projectsRoot,
|
|
15449
15567
|
cwdToHashDir(cwd),
|
|
15450
15568
|
`${toolSessionId}.jsonl`
|
|
@@ -15479,7 +15597,7 @@ var ClaudeHistoryReader = class {
|
|
|
15479
15597
|
}
|
|
15480
15598
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
15481
15599
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
15482
|
-
const file =
|
|
15600
|
+
const file = import_node_path5.default.join(
|
|
15483
15601
|
this.projectsRoot,
|
|
15484
15602
|
cwdToHashDir(cwd),
|
|
15485
15603
|
toolSessionId,
|
|
@@ -15488,7 +15606,7 @@ var ClaudeHistoryReader = class {
|
|
|
15488
15606
|
);
|
|
15489
15607
|
let exists = false;
|
|
15490
15608
|
try {
|
|
15491
|
-
exists =
|
|
15609
|
+
exists = import_node_fs6.default.statSync(file).isFile();
|
|
15492
15610
|
} catch {
|
|
15493
15611
|
return null;
|
|
15494
15612
|
}
|
|
@@ -15507,7 +15625,7 @@ var ClaudeHistoryReader = class {
|
|
|
15507
15625
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
15508
15626
|
*/
|
|
15509
15627
|
readFileHistorySnapshots(args) {
|
|
15510
|
-
const file =
|
|
15628
|
+
const file = import_node_path5.default.join(
|
|
15511
15629
|
this.projectsRoot,
|
|
15512
15630
|
cwdToHashDir(args.cwd),
|
|
15513
15631
|
`${args.toolSessionId}.jsonl`
|
|
@@ -15552,7 +15670,7 @@ var ClaudeHistoryReader = class {
|
|
|
15552
15670
|
for (const [anchorId, target] of snapshots) {
|
|
15553
15671
|
let hasAny = false;
|
|
15554
15672
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15555
|
-
const absPath =
|
|
15673
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15556
15674
|
const backupContent = readBackupContent(
|
|
15557
15675
|
this.fileHistoryRoot,
|
|
15558
15676
|
args.toolSessionId,
|
|
@@ -15592,7 +15710,7 @@ var ClaudeHistoryReader = class {
|
|
|
15592
15710
|
let totalInsertions = 0;
|
|
15593
15711
|
let totalDeletions = 0;
|
|
15594
15712
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
15595
|
-
const absPath =
|
|
15713
|
+
const absPath = import_node_path5.default.isAbsolute(rawPath) ? rawPath : import_node_path5.default.join(args.cwd, rawPath);
|
|
15596
15714
|
const backupContent = readBackupContent(
|
|
15597
15715
|
this.fileHistoryRoot,
|
|
15598
15716
|
args.toolSessionId,
|
|
@@ -15639,7 +15757,7 @@ var ClaudeHistoryReader = class {
|
|
|
15639
15757
|
};
|
|
15640
15758
|
}
|
|
15641
15759
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
15642
|
-
const file =
|
|
15760
|
+
const file = import_node_path5.default.join(
|
|
15643
15761
|
this.projectsRoot,
|
|
15644
15762
|
cwdToHashDir(cwd),
|
|
15645
15763
|
`${toolSessionId}.jsonl`
|
|
@@ -15661,27 +15779,27 @@ var ClaudeHistoryReader = class {
|
|
|
15661
15779
|
// src/tools/claude.ts
|
|
15662
15780
|
function macOSDesktopCandidates(home) {
|
|
15663
15781
|
return [
|
|
15664
|
-
|
|
15782
|
+
import_node_path6.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
15665
15783
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
15666
15784
|
];
|
|
15667
15785
|
}
|
|
15668
15786
|
function probeViaWhich() {
|
|
15669
15787
|
try {
|
|
15670
15788
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
15671
|
-
if (out &&
|
|
15789
|
+
if (out && import_node_fs7.default.existsSync(out)) return out;
|
|
15672
15790
|
} catch {
|
|
15673
15791
|
}
|
|
15674
15792
|
return null;
|
|
15675
15793
|
}
|
|
15676
15794
|
async function probeClaude(env = process.env, home = import_node_os3.default.homedir()) {
|
|
15677
|
-
if (env.CLAUDE_BIN &&
|
|
15795
|
+
if (env.CLAUDE_BIN && import_node_fs7.default.existsSync(env.CLAUDE_BIN)) {
|
|
15678
15796
|
return { available: true, path: env.CLAUDE_BIN };
|
|
15679
15797
|
}
|
|
15680
15798
|
const w = probeViaWhich();
|
|
15681
15799
|
if (w) return { available: true, path: w };
|
|
15682
15800
|
if (process.platform === "darwin") {
|
|
15683
15801
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
15684
|
-
if (
|
|
15802
|
+
if (import_node_fs7.default.existsSync(candidate)) {
|
|
15685
15803
|
return { available: true, path: candidate };
|
|
15686
15804
|
}
|
|
15687
15805
|
}
|
|
@@ -15992,10 +16110,10 @@ function parseAttachment(obj) {
|
|
|
15992
16110
|
const memories = raw.map((m) => {
|
|
15993
16111
|
if (!m || typeof m !== "object") return null;
|
|
15994
16112
|
const rec = m;
|
|
15995
|
-
const
|
|
16113
|
+
const path18 = typeof rec.path === "string" ? rec.path : null;
|
|
15996
16114
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
15997
|
-
if (!
|
|
15998
|
-
const out = { path:
|
|
16115
|
+
if (!path18 || content == null) return null;
|
|
16116
|
+
const out = { path: path18, content };
|
|
15999
16117
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
16000
16118
|
return out;
|
|
16001
16119
|
}).filter((m) => m !== null);
|
|
@@ -16223,22 +16341,22 @@ var ClaudeAdapter = class {
|
|
|
16223
16341
|
};
|
|
16224
16342
|
|
|
16225
16343
|
// src/workspace/browser.ts
|
|
16226
|
-
var
|
|
16344
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
16227
16345
|
var import_node_os4 = __toESM(require("os"), 1);
|
|
16228
|
-
var
|
|
16346
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
16229
16347
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
16230
16348
|
function resolveInsideCwd(cwd, subpath) {
|
|
16231
|
-
const absCwd =
|
|
16232
|
-
const joined =
|
|
16233
|
-
const rel =
|
|
16234
|
-
if (rel.startsWith("..") ||
|
|
16349
|
+
const absCwd = import_node_path7.default.resolve(cwd);
|
|
16350
|
+
const joined = import_node_path7.default.resolve(absCwd, subpath ?? ".");
|
|
16351
|
+
const rel = import_node_path7.default.relative(absCwd, joined);
|
|
16352
|
+
if (rel.startsWith("..") || import_node_path7.default.isAbsolute(rel)) {
|
|
16235
16353
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
16236
16354
|
}
|
|
16237
16355
|
return joined;
|
|
16238
16356
|
}
|
|
16239
16357
|
function ensureCwd(cwd) {
|
|
16240
16358
|
try {
|
|
16241
|
-
const stat =
|
|
16359
|
+
const stat = import_node_fs8.default.statSync(cwd);
|
|
16242
16360
|
if (!stat.isDirectory()) {
|
|
16243
16361
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
16244
16362
|
}
|
|
@@ -16252,7 +16370,7 @@ var WorkspaceBrowser = class {
|
|
|
16252
16370
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os4.default.homedir();
|
|
16253
16371
|
ensureCwd(cwd);
|
|
16254
16372
|
const full = resolveInsideCwd(cwd, args.path);
|
|
16255
|
-
const dirents =
|
|
16373
|
+
const dirents = import_node_fs8.default.readdirSync(full, { withFileTypes: true });
|
|
16256
16374
|
const entries = [];
|
|
16257
16375
|
for (const d of dirents) {
|
|
16258
16376
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -16262,7 +16380,7 @@ var WorkspaceBrowser = class {
|
|
|
16262
16380
|
mtime: ""
|
|
16263
16381
|
};
|
|
16264
16382
|
try {
|
|
16265
|
-
const st =
|
|
16383
|
+
const st = import_node_fs8.default.statSync(import_node_path7.default.join(full, d.name));
|
|
16266
16384
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
16267
16385
|
if (d.isFile()) entry.size = st.size;
|
|
16268
16386
|
} catch {
|
|
@@ -16278,14 +16396,14 @@ var WorkspaceBrowser = class {
|
|
|
16278
16396
|
read(args) {
|
|
16279
16397
|
ensureCwd(args.cwd);
|
|
16280
16398
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
16281
|
-
const st =
|
|
16399
|
+
const st = import_node_fs8.default.statSync(full);
|
|
16282
16400
|
if (!st.isFile()) {
|
|
16283
16401
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
16284
16402
|
}
|
|
16285
16403
|
if (st.size > MAX_FILE_BYTES) {
|
|
16286
16404
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
16287
16405
|
}
|
|
16288
|
-
const buf =
|
|
16406
|
+
const buf = import_node_fs8.default.readFileSync(full);
|
|
16289
16407
|
const isBinary = buf.includes(0);
|
|
16290
16408
|
if (isBinary) {
|
|
16291
16409
|
return {
|
|
@@ -16307,9 +16425,9 @@ var WorkspaceBrowser = class {
|
|
|
16307
16425
|
};
|
|
16308
16426
|
|
|
16309
16427
|
// src/skills/scanner.ts
|
|
16310
|
-
var
|
|
16428
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
16311
16429
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
16312
|
-
var
|
|
16430
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
16313
16431
|
function parseFrontmatter(content) {
|
|
16314
16432
|
if (!content.startsWith("---")) return { name: "", description: "" };
|
|
16315
16433
|
const end = content.indexOf("---", 3);
|
|
@@ -16345,7 +16463,7 @@ function parseFrontmatter(content) {
|
|
|
16345
16463
|
}
|
|
16346
16464
|
function isDirLikeSync(p) {
|
|
16347
16465
|
try {
|
|
16348
|
-
return
|
|
16466
|
+
return import_node_fs9.default.statSync(p).isDirectory();
|
|
16349
16467
|
} catch {
|
|
16350
16468
|
return false;
|
|
16351
16469
|
}
|
|
@@ -16353,19 +16471,19 @@ function isDirLikeSync(p) {
|
|
|
16353
16471
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
16354
16472
|
let entries;
|
|
16355
16473
|
try {
|
|
16356
|
-
entries =
|
|
16474
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16357
16475
|
} catch {
|
|
16358
16476
|
return;
|
|
16359
16477
|
}
|
|
16360
16478
|
for (const ent of entries) {
|
|
16361
|
-
const entryPath =
|
|
16479
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16362
16480
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
16363
16481
|
let content;
|
|
16364
16482
|
try {
|
|
16365
|
-
content =
|
|
16483
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
16366
16484
|
} catch {
|
|
16367
16485
|
try {
|
|
16368
|
-
content =
|
|
16486
|
+
content = import_node_fs9.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
16369
16487
|
} catch {
|
|
16370
16488
|
continue;
|
|
16371
16489
|
}
|
|
@@ -16383,26 +16501,26 @@ function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
|
16383
16501
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
16384
16502
|
let entries;
|
|
16385
16503
|
try {
|
|
16386
|
-
entries =
|
|
16504
|
+
entries = import_node_fs9.default.readdirSync(dir, { withFileTypes: true });
|
|
16387
16505
|
} catch {
|
|
16388
16506
|
return;
|
|
16389
16507
|
}
|
|
16390
16508
|
for (const ent of entries) {
|
|
16391
|
-
const entryPath =
|
|
16509
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
16392
16510
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
16393
16511
|
const ns = ent.name;
|
|
16394
16512
|
let subEntries;
|
|
16395
16513
|
try {
|
|
16396
|
-
subEntries =
|
|
16514
|
+
subEntries = import_node_fs9.default.readdirSync(entryPath, { withFileTypes: true });
|
|
16397
16515
|
} catch {
|
|
16398
16516
|
continue;
|
|
16399
16517
|
}
|
|
16400
16518
|
for (const se of subEntries) {
|
|
16401
16519
|
if (!se.name.endsWith(".md")) continue;
|
|
16402
|
-
const sePath =
|
|
16520
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
16403
16521
|
let content;
|
|
16404
16522
|
try {
|
|
16405
|
-
content =
|
|
16523
|
+
content = import_node_fs9.default.readFileSync(sePath, "utf8");
|
|
16406
16524
|
} catch {
|
|
16407
16525
|
continue;
|
|
16408
16526
|
}
|
|
@@ -16419,7 +16537,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16419
16537
|
} else if (ent.name.endsWith(".md")) {
|
|
16420
16538
|
let content;
|
|
16421
16539
|
try {
|
|
16422
|
-
content =
|
|
16540
|
+
content = import_node_fs9.default.readFileSync(entryPath, "utf8");
|
|
16423
16541
|
} catch {
|
|
16424
16542
|
continue;
|
|
16425
16543
|
}
|
|
@@ -16435,10 +16553,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
16435
16553
|
}
|
|
16436
16554
|
}
|
|
16437
16555
|
function readInstalledPlugins(home) {
|
|
16438
|
-
const file =
|
|
16556
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
16439
16557
|
let raw;
|
|
16440
16558
|
try {
|
|
16441
|
-
raw =
|
|
16559
|
+
raw = import_node_fs9.default.readFileSync(file, "utf8");
|
|
16442
16560
|
} catch {
|
|
16443
16561
|
return [];
|
|
16444
16562
|
}
|
|
@@ -16476,14 +16594,14 @@ var SkillsScanner = class {
|
|
|
16476
16594
|
list(args) {
|
|
16477
16595
|
const seen = /* @__PURE__ */ new Set();
|
|
16478
16596
|
const out = [];
|
|
16479
|
-
scanSkillDir(
|
|
16480
|
-
scanCommandDir(
|
|
16481
|
-
scanSkillDir(
|
|
16482
|
-
scanCommandDir(
|
|
16597
|
+
scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, out);
|
|
16598
|
+
scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, out);
|
|
16599
|
+
scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, out);
|
|
16600
|
+
scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, out);
|
|
16483
16601
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
16484
16602
|
for (const { name, root } of plugins) {
|
|
16485
|
-
scanSkillDir(
|
|
16486
|
-
scanCommandDir(
|
|
16603
|
+
scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, out, name);
|
|
16604
|
+
scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, out, name);
|
|
16487
16605
|
}
|
|
16488
16606
|
out.sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
|
|
16489
16607
|
return out;
|
|
@@ -16491,9 +16609,9 @@ var SkillsScanner = class {
|
|
|
16491
16609
|
};
|
|
16492
16610
|
|
|
16493
16611
|
// src/observer/session-observer.ts
|
|
16494
|
-
var
|
|
16612
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
16495
16613
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
16496
|
-
var
|
|
16614
|
+
var import_node_path9 = __toESM(require("path"), 1);
|
|
16497
16615
|
var SessionObserver = class {
|
|
16498
16616
|
constructor(opts) {
|
|
16499
16617
|
this.opts = opts;
|
|
@@ -16504,14 +16622,14 @@ var SessionObserver = class {
|
|
|
16504
16622
|
watches = /* @__PURE__ */ new Map();
|
|
16505
16623
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
16506
16624
|
if (override) return override;
|
|
16507
|
-
return
|
|
16625
|
+
return import_node_path9.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
16508
16626
|
}
|
|
16509
16627
|
start(args) {
|
|
16510
16628
|
this.stop(args.sessionId);
|
|
16511
16629
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
16512
16630
|
let size = 0;
|
|
16513
16631
|
try {
|
|
16514
|
-
size =
|
|
16632
|
+
size = import_node_fs10.default.statSync(filePath).size;
|
|
16515
16633
|
} catch {
|
|
16516
16634
|
}
|
|
16517
16635
|
const w = {
|
|
@@ -16524,10 +16642,10 @@ var SessionObserver = class {
|
|
|
16524
16642
|
adapter: args.adapter
|
|
16525
16643
|
};
|
|
16526
16644
|
try {
|
|
16527
|
-
|
|
16645
|
+
import_node_fs10.default.mkdirSync(import_node_path9.default.dirname(filePath), { recursive: true });
|
|
16528
16646
|
} catch {
|
|
16529
16647
|
}
|
|
16530
|
-
w.watcher =
|
|
16648
|
+
w.watcher = import_node_fs10.default.watch(import_node_path9.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
16531
16649
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
16532
16650
|
this.poll(w);
|
|
16533
16651
|
});
|
|
@@ -16542,7 +16660,7 @@ var SessionObserver = class {
|
|
|
16542
16660
|
// reducer.shallowEqMeta diff 让重复 patch 静默吞掉;异常静默吞,不阻塞 watcher 启动
|
|
16543
16661
|
hydrateMetaTail(w, maxLines = 200) {
|
|
16544
16662
|
try {
|
|
16545
|
-
const raw =
|
|
16663
|
+
const raw = import_node_fs10.default.readFileSync(w.filePath, "utf8");
|
|
16546
16664
|
if (!raw) return;
|
|
16547
16665
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
16548
16666
|
if (allLines.length === 0) return;
|
|
@@ -16563,7 +16681,7 @@ var SessionObserver = class {
|
|
|
16563
16681
|
poll(w) {
|
|
16564
16682
|
let size = 0;
|
|
16565
16683
|
try {
|
|
16566
|
-
size =
|
|
16684
|
+
size = import_node_fs10.default.statSync(w.filePath).size;
|
|
16567
16685
|
} catch {
|
|
16568
16686
|
return;
|
|
16569
16687
|
}
|
|
@@ -16572,11 +16690,11 @@ var SessionObserver = class {
|
|
|
16572
16690
|
w.buf = "";
|
|
16573
16691
|
}
|
|
16574
16692
|
if (size === w.lastSize) return;
|
|
16575
|
-
const fd =
|
|
16693
|
+
const fd = import_node_fs10.default.openSync(w.filePath, "r");
|
|
16576
16694
|
try {
|
|
16577
16695
|
const len = size - w.lastSize;
|
|
16578
16696
|
const buf = Buffer.alloc(len);
|
|
16579
|
-
|
|
16697
|
+
import_node_fs10.default.readSync(fd, buf, 0, len, w.lastSize);
|
|
16580
16698
|
w.lastSize = size;
|
|
16581
16699
|
w.buf += buf.toString("utf8");
|
|
16582
16700
|
let newlineIndex;
|
|
@@ -16590,7 +16708,7 @@ var SessionObserver = class {
|
|
|
16590
16708
|
this.maybeReportUserMessage(w.sessionId, line);
|
|
16591
16709
|
}
|
|
16592
16710
|
} finally {
|
|
16593
|
-
|
|
16711
|
+
import_node_fs10.default.closeSync(fd);
|
|
16594
16712
|
}
|
|
16595
16713
|
}
|
|
16596
16714
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -17005,10 +17123,10 @@ function isLocalhost(addr) {
|
|
|
17005
17123
|
}
|
|
17006
17124
|
|
|
17007
17125
|
// src/discovery/state-file.ts
|
|
17008
|
-
var
|
|
17009
|
-
var
|
|
17126
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
17127
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
17010
17128
|
function defaultStateFilePath(dataDir) {
|
|
17011
|
-
return
|
|
17129
|
+
return import_node_path10.default.join(dataDir, "state.json");
|
|
17012
17130
|
}
|
|
17013
17131
|
function isPidAlive(pid) {
|
|
17014
17132
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -17030,7 +17148,7 @@ var StateFileManager = class {
|
|
|
17030
17148
|
}
|
|
17031
17149
|
read() {
|
|
17032
17150
|
try {
|
|
17033
|
-
const raw =
|
|
17151
|
+
const raw = import_node_fs11.default.readFileSync(this.file, "utf8");
|
|
17034
17152
|
const parsed = JSON.parse(raw);
|
|
17035
17153
|
return parsed;
|
|
17036
17154
|
} catch {
|
|
@@ -17044,34 +17162,34 @@ var StateFileManager = class {
|
|
|
17044
17162
|
return { status: "stale", existing };
|
|
17045
17163
|
}
|
|
17046
17164
|
write(state) {
|
|
17047
|
-
|
|
17165
|
+
import_node_fs11.default.mkdirSync(import_node_path10.default.dirname(this.file), { recursive: true });
|
|
17048
17166
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
17049
|
-
|
|
17050
|
-
|
|
17167
|
+
import_node_fs11.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
17168
|
+
import_node_fs11.default.renameSync(tmp, this.file);
|
|
17051
17169
|
if (process.platform !== "win32") {
|
|
17052
17170
|
try {
|
|
17053
|
-
|
|
17171
|
+
import_node_fs11.default.chmodSync(this.file, 384);
|
|
17054
17172
|
} catch {
|
|
17055
17173
|
}
|
|
17056
17174
|
}
|
|
17057
17175
|
}
|
|
17058
17176
|
delete() {
|
|
17059
17177
|
try {
|
|
17060
|
-
|
|
17178
|
+
import_node_fs11.default.unlinkSync(this.file);
|
|
17061
17179
|
} catch {
|
|
17062
17180
|
}
|
|
17063
17181
|
}
|
|
17064
17182
|
};
|
|
17065
17183
|
|
|
17066
17184
|
// src/tunnel/tunnel-manager.ts
|
|
17067
|
-
var
|
|
17068
|
-
var
|
|
17185
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
17186
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
17069
17187
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
17070
17188
|
var import_node_child_process4 = require("child_process");
|
|
17071
17189
|
|
|
17072
17190
|
// src/tunnel/tunnel-store.ts
|
|
17073
|
-
var
|
|
17074
|
-
var
|
|
17191
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
17192
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
17075
17193
|
var TunnelStore = class {
|
|
17076
17194
|
constructor(filePath) {
|
|
17077
17195
|
this.filePath = filePath;
|
|
@@ -17079,7 +17197,7 @@ var TunnelStore = class {
|
|
|
17079
17197
|
filePath;
|
|
17080
17198
|
async get() {
|
|
17081
17199
|
try {
|
|
17082
|
-
const raw = await
|
|
17200
|
+
const raw = await import_node_fs12.default.promises.readFile(this.filePath, "utf8");
|
|
17083
17201
|
const obj = JSON.parse(raw);
|
|
17084
17202
|
if (!isPersistedTunnel(obj)) return null;
|
|
17085
17203
|
return obj;
|
|
@@ -17090,22 +17208,22 @@ var TunnelStore = class {
|
|
|
17090
17208
|
}
|
|
17091
17209
|
}
|
|
17092
17210
|
async set(v) {
|
|
17093
|
-
const dir =
|
|
17094
|
-
await
|
|
17211
|
+
const dir = import_node_path11.default.dirname(this.filePath);
|
|
17212
|
+
await import_node_fs12.default.promises.mkdir(dir, { recursive: true });
|
|
17095
17213
|
const data = JSON.stringify(v, null, 2);
|
|
17096
17214
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
17097
|
-
await
|
|
17215
|
+
await import_node_fs12.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
17098
17216
|
if (process.platform !== "win32") {
|
|
17099
17217
|
try {
|
|
17100
|
-
await
|
|
17218
|
+
await import_node_fs12.default.promises.chmod(tmp, 384);
|
|
17101
17219
|
} catch {
|
|
17102
17220
|
}
|
|
17103
17221
|
}
|
|
17104
|
-
await
|
|
17222
|
+
await import_node_fs12.default.promises.rename(tmp, this.filePath);
|
|
17105
17223
|
}
|
|
17106
17224
|
async clear() {
|
|
17107
17225
|
try {
|
|
17108
|
-
await
|
|
17226
|
+
await import_node_fs12.default.promises.unlink(this.filePath);
|
|
17109
17227
|
} catch (err) {
|
|
17110
17228
|
const code = err?.code;
|
|
17111
17229
|
if (code !== "ENOENT") throw err;
|
|
@@ -17200,9 +17318,9 @@ function escape(v) {
|
|
|
17200
17318
|
}
|
|
17201
17319
|
|
|
17202
17320
|
// src/tunnel/frpc-binary.ts
|
|
17203
|
-
var
|
|
17321
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
17204
17322
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
17205
|
-
var
|
|
17323
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
17206
17324
|
var import_node_child_process3 = require("child_process");
|
|
17207
17325
|
var import_node_stream = require("stream");
|
|
17208
17326
|
var import_promises = require("stream/promises");
|
|
@@ -17234,20 +17352,20 @@ function frpcDownloadUrl(version2, p) {
|
|
|
17234
17352
|
}
|
|
17235
17353
|
async function ensureFrpcBinary(opts) {
|
|
17236
17354
|
if (opts.override) {
|
|
17237
|
-
if (!
|
|
17355
|
+
if (!import_node_fs13.default.existsSync(opts.override)) {
|
|
17238
17356
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
17239
17357
|
}
|
|
17240
17358
|
return opts.override;
|
|
17241
17359
|
}
|
|
17242
17360
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
17243
17361
|
const platform = opts.platform ?? detectPlatform();
|
|
17244
|
-
const binDir =
|
|
17245
|
-
|
|
17362
|
+
const binDir = import_node_path12.default.join(opts.dataDir, "bin");
|
|
17363
|
+
import_node_fs13.default.mkdirSync(binDir, { recursive: true });
|
|
17246
17364
|
cleanupStaleArtifacts(binDir);
|
|
17247
|
-
const stableBin =
|
|
17248
|
-
if (
|
|
17365
|
+
const stableBin = import_node_path12.default.join(binDir, "frpc");
|
|
17366
|
+
if (import_node_fs13.default.existsSync(stableBin)) return stableBin;
|
|
17249
17367
|
const partialBin = `${stableBin}.partial`;
|
|
17250
|
-
const tarballPath =
|
|
17368
|
+
const tarballPath = import_node_path12.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
17251
17369
|
try {
|
|
17252
17370
|
const url = frpcDownloadUrl(version2, platform);
|
|
17253
17371
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -17256,8 +17374,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
17256
17374
|
} else {
|
|
17257
17375
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
17258
17376
|
}
|
|
17259
|
-
|
|
17260
|
-
|
|
17377
|
+
import_node_fs13.default.chmodSync(partialBin, 493);
|
|
17378
|
+
import_node_fs13.default.renameSync(partialBin, stableBin);
|
|
17261
17379
|
} finally {
|
|
17262
17380
|
safeUnlink(tarballPath);
|
|
17263
17381
|
safeUnlink(partialBin);
|
|
@@ -17267,15 +17385,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
17267
17385
|
function cleanupStaleArtifacts(binDir) {
|
|
17268
17386
|
let entries;
|
|
17269
17387
|
try {
|
|
17270
|
-
entries =
|
|
17388
|
+
entries = import_node_fs13.default.readdirSync(binDir);
|
|
17271
17389
|
} catch {
|
|
17272
17390
|
return;
|
|
17273
17391
|
}
|
|
17274
17392
|
for (const name of entries) {
|
|
17275
17393
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
17276
|
-
const full =
|
|
17394
|
+
const full = import_node_path12.default.join(binDir, name);
|
|
17277
17395
|
try {
|
|
17278
|
-
|
|
17396
|
+
import_node_fs13.default.rmSync(full, { recursive: true, force: true });
|
|
17279
17397
|
} catch {
|
|
17280
17398
|
}
|
|
17281
17399
|
}
|
|
@@ -17283,7 +17401,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
17283
17401
|
}
|
|
17284
17402
|
function safeUnlink(p) {
|
|
17285
17403
|
try {
|
|
17286
|
-
|
|
17404
|
+
import_node_fs13.default.unlinkSync(p);
|
|
17287
17405
|
} catch {
|
|
17288
17406
|
}
|
|
17289
17407
|
}
|
|
@@ -17294,13 +17412,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
17294
17412
|
if (!res.ok || !res.body) {
|
|
17295
17413
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
17296
17414
|
}
|
|
17297
|
-
const out =
|
|
17415
|
+
const out = import_node_fs13.default.createWriteStream(dest);
|
|
17298
17416
|
const nodeStream = import_node_stream.Readable.fromWeb(res.body);
|
|
17299
17417
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
17300
17418
|
}
|
|
17301
17419
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
17302
|
-
const work =
|
|
17303
|
-
|
|
17420
|
+
const work = import_node_path12.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
17421
|
+
import_node_fs13.default.mkdirSync(work, { recursive: true });
|
|
17304
17422
|
try {
|
|
17305
17423
|
await new Promise((resolve, reject) => {
|
|
17306
17424
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -17308,13 +17426,13 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
17308
17426
|
proc.on("exit", (code) => code === 0 ? resolve() : reject(new Error(`tar exited ${code}`)));
|
|
17309
17427
|
});
|
|
17310
17428
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
17311
|
-
const src =
|
|
17312
|
-
if (!
|
|
17429
|
+
const src = import_node_path12.default.join(work, dirName, "frpc");
|
|
17430
|
+
if (!import_node_fs13.default.existsSync(src)) {
|
|
17313
17431
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
17314
17432
|
}
|
|
17315
|
-
|
|
17433
|
+
import_node_fs13.default.copyFileSync(src, destBin);
|
|
17316
17434
|
} finally {
|
|
17317
|
-
|
|
17435
|
+
import_node_fs13.default.rmSync(work, { recursive: true, force: true });
|
|
17318
17436
|
}
|
|
17319
17437
|
}
|
|
17320
17438
|
|
|
@@ -17323,7 +17441,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
17323
17441
|
var TunnelManager = class {
|
|
17324
17442
|
constructor(deps) {
|
|
17325
17443
|
this.deps = deps;
|
|
17326
|
-
this.store = deps.store ?? new TunnelStore(
|
|
17444
|
+
this.store = deps.store ?? new TunnelStore(import_node_path13.default.join(deps.dataDir, "tunnel.json"));
|
|
17327
17445
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
17328
17446
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
17329
17447
|
}
|
|
@@ -17440,7 +17558,7 @@ var TunnelManager = class {
|
|
|
17440
17558
|
dataDir: this.deps.dataDir,
|
|
17441
17559
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
17442
17560
|
});
|
|
17443
|
-
const tomlPath =
|
|
17561
|
+
const tomlPath = import_node_path13.default.join(this.deps.dataDir, "frpc.toml");
|
|
17444
17562
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto3.default.randomBytes(3).toString("hex")}`;
|
|
17445
17563
|
const toml = buildFrpcToml({
|
|
17446
17564
|
serverAddr: t.frpsHost,
|
|
@@ -17451,12 +17569,12 @@ var TunnelManager = class {
|
|
|
17451
17569
|
localPort,
|
|
17452
17570
|
logLevel: "info"
|
|
17453
17571
|
});
|
|
17454
|
-
await
|
|
17572
|
+
await import_node_fs14.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
17455
17573
|
const proc = (this.deps.spawnImpl ?? import_node_child_process4.spawn)(frpcBin, ["-c", tomlPath], {
|
|
17456
17574
|
stdio: ["ignore", "pipe", "pipe"]
|
|
17457
17575
|
});
|
|
17458
|
-
const logFilePath =
|
|
17459
|
-
const logStream =
|
|
17576
|
+
const logFilePath = import_node_path13.default.join(this.deps.dataDir, "frpc.log");
|
|
17577
|
+
const logStream = import_node_fs14.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
17460
17578
|
logStream.on("error", () => {
|
|
17461
17579
|
});
|
|
17462
17580
|
const tee = (chunk) => {
|
|
@@ -17548,12 +17666,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
17548
17666
|
}
|
|
17549
17667
|
|
|
17550
17668
|
// src/auth-store.ts
|
|
17551
|
-
var
|
|
17552
|
-
var
|
|
17669
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
17670
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
17553
17671
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
17554
17672
|
var AUTH_FILE_NAME = "auth.json";
|
|
17555
17673
|
function authFilePath(dataDir) {
|
|
17556
|
-
return
|
|
17674
|
+
return import_node_path14.default.join(dataDir, AUTH_FILE_NAME);
|
|
17557
17675
|
}
|
|
17558
17676
|
function loadOrCreateAuthToken(opts) {
|
|
17559
17677
|
const file = authFilePath(opts.dataDir);
|
|
@@ -17569,7 +17687,7 @@ function defaultGenerate() {
|
|
|
17569
17687
|
}
|
|
17570
17688
|
function readAuthFile(file) {
|
|
17571
17689
|
try {
|
|
17572
|
-
const raw =
|
|
17690
|
+
const raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
17573
17691
|
const parsed = JSON.parse(raw);
|
|
17574
17692
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
17575
17693
|
return {
|
|
@@ -17585,20 +17703,20 @@ function readAuthFile(file) {
|
|
|
17585
17703
|
}
|
|
17586
17704
|
}
|
|
17587
17705
|
function writeAuthFile(file, content) {
|
|
17588
|
-
|
|
17589
|
-
|
|
17706
|
+
import_node_fs15.default.mkdirSync(import_node_path14.default.dirname(file), { recursive: true });
|
|
17707
|
+
import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
17590
17708
|
try {
|
|
17591
|
-
|
|
17709
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
17592
17710
|
} catch {
|
|
17593
17711
|
}
|
|
17594
17712
|
}
|
|
17595
17713
|
|
|
17596
17714
|
// src/session/fork.ts
|
|
17597
|
-
var
|
|
17715
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
17598
17716
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
17599
|
-
var
|
|
17717
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
17600
17718
|
function readJsonlEntries(file) {
|
|
17601
|
-
const raw =
|
|
17719
|
+
const raw = import_node_fs16.default.readFileSync(file, "utf8");
|
|
17602
17720
|
const out = [];
|
|
17603
17721
|
for (const line of raw.split("\n")) {
|
|
17604
17722
|
const t = line.trim();
|
|
@@ -17611,10 +17729,10 @@ function readJsonlEntries(file) {
|
|
|
17611
17729
|
return out;
|
|
17612
17730
|
}
|
|
17613
17731
|
function forkSession(input) {
|
|
17614
|
-
const baseDir = input.baseDir ??
|
|
17615
|
-
const projectDir =
|
|
17616
|
-
const sourceFile =
|
|
17617
|
-
if (!
|
|
17732
|
+
const baseDir = input.baseDir ?? import_node_path15.default.join(import_node_os9.default.homedir(), ".claude");
|
|
17733
|
+
const projectDir = import_node_path15.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
17734
|
+
const sourceFile = import_node_path15.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
17735
|
+
if (!import_node_fs16.default.existsSync(sourceFile)) {
|
|
17618
17736
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
17619
17737
|
}
|
|
17620
17738
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -17644,9 +17762,9 @@ function forkSession(input) {
|
|
|
17644
17762
|
}
|
|
17645
17763
|
forkedLines.push(JSON.stringify(forked));
|
|
17646
17764
|
}
|
|
17647
|
-
const forkedFilePath =
|
|
17648
|
-
|
|
17649
|
-
|
|
17765
|
+
const forkedFilePath = import_node_path15.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
17766
|
+
import_node_fs16.default.mkdirSync(projectDir, { recursive: true });
|
|
17767
|
+
import_node_fs16.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
17650
17768
|
return { forkedToolSessionId, forkedFilePath };
|
|
17651
17769
|
}
|
|
17652
17770
|
|
|
@@ -17767,6 +17885,11 @@ function buildSessionHandlers(deps) {
|
|
|
17767
17885
|
const { response, broadcast } = manager.pin(args);
|
|
17768
17886
|
return { response: { type: "session:info", ...response }, broadcast };
|
|
17769
17887
|
};
|
|
17888
|
+
const reorderPins = async (frame) => {
|
|
17889
|
+
const args = SessionReorderPinsArgs.parse(frame);
|
|
17890
|
+
const { response, broadcast } = manager.reorderPins(args);
|
|
17891
|
+
return { response: { type: "session:reorderPins", ...response }, broadcast };
|
|
17892
|
+
};
|
|
17770
17893
|
const answerQuestion = async (frame) => {
|
|
17771
17894
|
const args = AnswerQuestionArgs.parse(frame);
|
|
17772
17895
|
const { response, broadcast } = manager.answerQuestion(args);
|
|
@@ -17792,6 +17915,7 @@ function buildSessionHandlers(deps) {
|
|
|
17792
17915
|
"session:subscribe": subscribe,
|
|
17793
17916
|
"session:unsubscribe": unsubscribe,
|
|
17794
17917
|
"session:pin": pin,
|
|
17918
|
+
"session:reorderPins": reorderPins,
|
|
17795
17919
|
"session:answerQuestion": answerQuestion
|
|
17796
17920
|
};
|
|
17797
17921
|
}
|
|
@@ -17902,9 +18026,9 @@ function buildWorkspaceHandlers(deps) {
|
|
|
17902
18026
|
|
|
17903
18027
|
// src/workspace/git.ts
|
|
17904
18028
|
var import_node_child_process5 = require("child_process");
|
|
17905
|
-
var
|
|
18029
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
17906
18030
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
17907
|
-
var
|
|
18031
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
17908
18032
|
var import_node_util = require("util");
|
|
17909
18033
|
var pexec = (0, import_node_util.promisify)(import_node_child_process5.execFile);
|
|
17910
18034
|
function formatChildProcessError(err) {
|
|
@@ -17919,9 +18043,9 @@ function formatChildProcessError(err) {
|
|
|
17919
18043
|
return e.message ?? "unknown error";
|
|
17920
18044
|
}
|
|
17921
18045
|
function normalizePath(p) {
|
|
17922
|
-
const resolved =
|
|
18046
|
+
const resolved = import_node_path16.default.resolve(p);
|
|
17923
18047
|
try {
|
|
17924
|
-
return
|
|
18048
|
+
return import_node_fs17.default.realpathSync(resolved);
|
|
17925
18049
|
} catch {
|
|
17926
18050
|
return resolved;
|
|
17927
18051
|
}
|
|
@@ -18022,13 +18146,13 @@ function flattenToDirName(branch) {
|
|
|
18022
18146
|
}
|
|
18023
18147
|
function encodeClaudeProjectDir(absPath) {
|
|
18024
18148
|
if (!absPath || typeof absPath !== "string") return "";
|
|
18025
|
-
let canonical =
|
|
18149
|
+
let canonical = import_node_path16.default.resolve(absPath);
|
|
18026
18150
|
try {
|
|
18027
|
-
canonical =
|
|
18151
|
+
canonical = import_node_fs17.default.realpathSync(canonical);
|
|
18028
18152
|
} catch {
|
|
18029
18153
|
try {
|
|
18030
|
-
const parent =
|
|
18031
|
-
canonical =
|
|
18154
|
+
const parent = import_node_fs17.default.realpathSync(import_node_path16.default.dirname(canonical));
|
|
18155
|
+
canonical = import_node_path16.default.join(parent, import_node_path16.default.basename(canonical));
|
|
18032
18156
|
} catch {
|
|
18033
18157
|
}
|
|
18034
18158
|
}
|
|
@@ -18052,11 +18176,11 @@ async function createWorktree(input) {
|
|
|
18052
18176
|
if (!isGitRoot) {
|
|
18053
18177
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
18054
18178
|
}
|
|
18055
|
-
const parent =
|
|
18056
|
-
if (parent === "/" || parent ===
|
|
18179
|
+
const parent = import_node_path16.default.dirname(import_node_path16.default.resolve(cwd));
|
|
18180
|
+
if (parent === "/" || parent === import_node_path16.default.resolve(cwd)) {
|
|
18057
18181
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
18058
18182
|
}
|
|
18059
|
-
const worktreeRoot =
|
|
18183
|
+
const worktreeRoot = import_node_path16.default.join(parent, dirName);
|
|
18060
18184
|
try {
|
|
18061
18185
|
await pexec("git", ["-C", cwd, "rev-parse", "--verify", `refs/heads/${baseBranch}`], {
|
|
18062
18186
|
timeout: 3e3
|
|
@@ -18073,7 +18197,7 @@ async function createWorktree(input) {
|
|
|
18073
18197
|
const msg = err.message;
|
|
18074
18198
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
18075
18199
|
}
|
|
18076
|
-
if (
|
|
18200
|
+
if (import_node_fs17.default.existsSync(worktreeRoot)) {
|
|
18077
18201
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
18078
18202
|
}
|
|
18079
18203
|
try {
|
|
@@ -18101,8 +18225,8 @@ async function removeWorktree(input) {
|
|
|
18101
18225
|
);
|
|
18102
18226
|
const gitCommonDir = stdout.trim();
|
|
18103
18227
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
18104
|
-
const absGitCommon =
|
|
18105
|
-
repoRoot =
|
|
18228
|
+
const absGitCommon = import_node_path16.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path16.default.resolve(worktreeRoot, gitCommonDir);
|
|
18229
|
+
repoRoot = import_node_path16.default.dirname(absGitCommon);
|
|
18106
18230
|
} catch {
|
|
18107
18231
|
repoRoot = null;
|
|
18108
18232
|
}
|
|
@@ -18114,7 +18238,7 @@ async function removeWorktree(input) {
|
|
|
18114
18238
|
} catch (err) {
|
|
18115
18239
|
const stderr = err.stderr ?? "";
|
|
18116
18240
|
const lower = stderr.toLowerCase();
|
|
18117
|
-
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !
|
|
18241
|
+
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs17.default.existsSync(worktreeRoot);
|
|
18118
18242
|
if (!vanished) {
|
|
18119
18243
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
18120
18244
|
}
|
|
@@ -18133,10 +18257,10 @@ async function removeWorktree(input) {
|
|
|
18133
18257
|
try {
|
|
18134
18258
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
18135
18259
|
if (encoded) {
|
|
18136
|
-
const projectsRoot =
|
|
18137
|
-
const target =
|
|
18138
|
-
if (target.startsWith(projectsRoot +
|
|
18139
|
-
|
|
18260
|
+
const projectsRoot = import_node_path16.default.join(import_node_os10.default.homedir(), ".claude", "projects");
|
|
18261
|
+
const target = import_node_path16.default.resolve(projectsRoot, encoded);
|
|
18262
|
+
if (target.startsWith(projectsRoot + import_node_path16.default.sep) && target !== projectsRoot) {
|
|
18263
|
+
import_node_fs17.default.rmSync(target, { recursive: true, force: true });
|
|
18140
18264
|
}
|
|
18141
18265
|
}
|
|
18142
18266
|
} catch {
|
|
@@ -18263,7 +18387,7 @@ function buildMethodHandlers(deps) {
|
|
|
18263
18387
|
async function startDaemon(config) {
|
|
18264
18388
|
const logger = createLogger({
|
|
18265
18389
|
level: config.logLevel,
|
|
18266
|
-
file:
|
|
18390
|
+
file: import_node_path17.default.join(config.dataDir, "clawd.log")
|
|
18267
18391
|
});
|
|
18268
18392
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
18269
18393
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -18303,6 +18427,7 @@ async function startDaemon(config) {
|
|
|
18303
18427
|
logger,
|
|
18304
18428
|
getAdapter,
|
|
18305
18429
|
historyReader: history,
|
|
18430
|
+
dataDir: config.dataDir,
|
|
18306
18431
|
broadcastFrame: (frame, target) => {
|
|
18307
18432
|
if (target === "all") {
|
|
18308
18433
|
transport?.broadcastAll(frame);
|
|
@@ -18425,8 +18550,8 @@ async function startDaemon(config) {
|
|
|
18425
18550
|
const lines = [
|
|
18426
18551
|
`Tunnel: ${r.url}`,
|
|
18427
18552
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
18428
|
-
`Frpc config: ${
|
|
18429
|
-
`Frpc log: ${
|
|
18553
|
+
`Frpc config: ${import_node_path17.default.join(config.dataDir, "frpc.toml")}`,
|
|
18554
|
+
`Frpc log: ${import_node_path17.default.join(config.dataDir, "frpc.log")}`
|
|
18430
18555
|
];
|
|
18431
18556
|
const width = Math.max(...lines.map((l) => l.length));
|
|
18432
18557
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -18439,8 +18564,8 @@ ${bar}
|
|
|
18439
18564
|
|
|
18440
18565
|
`);
|
|
18441
18566
|
try {
|
|
18442
|
-
const connectPath =
|
|
18443
|
-
|
|
18567
|
+
const connectPath = import_node_path17.default.join(config.dataDir, "connect.txt");
|
|
18568
|
+
import_node_fs18.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
18444
18569
|
} catch {
|
|
18445
18570
|
}
|
|
18446
18571
|
} catch (err) {
|