@clawos-dev/clawd 0.2.89 → 0.2.90
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 +598 -487
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -651,8 +651,8 @@ var init_parseUtil = __esm({
|
|
|
651
651
|
init_errors2();
|
|
652
652
|
init_en();
|
|
653
653
|
makeIssue = (params) => {
|
|
654
|
-
const { data, path:
|
|
655
|
-
const fullPath = [...
|
|
654
|
+
const { data, path: path47, errorMaps, issueData } = params;
|
|
655
|
+
const fullPath = [...path47, ...issueData.path || []];
|
|
656
656
|
const fullIssue = {
|
|
657
657
|
...issueData,
|
|
658
658
|
path: fullPath
|
|
@@ -963,11 +963,11 @@ var init_types = __esm({
|
|
|
963
963
|
init_parseUtil();
|
|
964
964
|
init_util();
|
|
965
965
|
ParseInputLazyPath = class {
|
|
966
|
-
constructor(parent, value,
|
|
966
|
+
constructor(parent, value, path47, key) {
|
|
967
967
|
this._cachedPath = [];
|
|
968
968
|
this.parent = parent;
|
|
969
969
|
this.data = value;
|
|
970
|
-
this._path =
|
|
970
|
+
this._path = path47;
|
|
971
971
|
this._key = key;
|
|
972
972
|
}
|
|
973
973
|
get path() {
|
|
@@ -5635,8 +5635,8 @@ var require_req = __commonJS({
|
|
|
5635
5635
|
if (req.originalUrl) {
|
|
5636
5636
|
_req.url = req.originalUrl;
|
|
5637
5637
|
} else {
|
|
5638
|
-
const
|
|
5639
|
-
_req.url = typeof
|
|
5638
|
+
const path47 = req.path;
|
|
5639
|
+
_req.url = typeof path47 === "string" ? path47 : req.url ? req.url.path || req.url : void 0;
|
|
5640
5640
|
}
|
|
5641
5641
|
if (req.query) {
|
|
5642
5642
|
_req.query = req.query;
|
|
@@ -5801,14 +5801,14 @@ var require_redact = __commonJS({
|
|
|
5801
5801
|
}
|
|
5802
5802
|
return obj;
|
|
5803
5803
|
}
|
|
5804
|
-
function parsePath(
|
|
5804
|
+
function parsePath(path47) {
|
|
5805
5805
|
const parts = [];
|
|
5806
5806
|
let current = "";
|
|
5807
5807
|
let inBrackets = false;
|
|
5808
5808
|
let inQuotes = false;
|
|
5809
5809
|
let quoteChar = "";
|
|
5810
|
-
for (let i = 0; i <
|
|
5811
|
-
const char =
|
|
5810
|
+
for (let i = 0; i < path47.length; i++) {
|
|
5811
|
+
const char = path47[i];
|
|
5812
5812
|
if (!inBrackets && char === ".") {
|
|
5813
5813
|
if (current) {
|
|
5814
5814
|
parts.push(current);
|
|
@@ -5939,10 +5939,10 @@ var require_redact = __commonJS({
|
|
|
5939
5939
|
return current;
|
|
5940
5940
|
}
|
|
5941
5941
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
5942
|
-
for (const
|
|
5943
|
-
const parts = parsePath(
|
|
5942
|
+
for (const path47 of paths) {
|
|
5943
|
+
const parts = parsePath(path47);
|
|
5944
5944
|
if (parts.includes("*")) {
|
|
5945
|
-
redactWildcardPath(obj, parts, censor,
|
|
5945
|
+
redactWildcardPath(obj, parts, censor, path47, remove);
|
|
5946
5946
|
} else {
|
|
5947
5947
|
if (remove) {
|
|
5948
5948
|
removeKey(obj, parts);
|
|
@@ -6027,8 +6027,8 @@ var require_redact = __commonJS({
|
|
|
6027
6027
|
}
|
|
6028
6028
|
} else {
|
|
6029
6029
|
if (afterWildcard.includes("*")) {
|
|
6030
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6031
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6030
|
+
const wrappedCensor = typeof censor === "function" ? (value, path47) => {
|
|
6031
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path47];
|
|
6032
6032
|
return censor(value, fullPath);
|
|
6033
6033
|
} : censor;
|
|
6034
6034
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6063,8 +6063,8 @@ var require_redact = __commonJS({
|
|
|
6063
6063
|
return null;
|
|
6064
6064
|
}
|
|
6065
6065
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6066
|
-
for (const
|
|
6067
|
-
const parts = parsePath(
|
|
6066
|
+
for (const path47 of pathsToClone) {
|
|
6067
|
+
const parts = parsePath(path47);
|
|
6068
6068
|
let current = pathStructure;
|
|
6069
6069
|
for (let i = 0; i < parts.length; i++) {
|
|
6070
6070
|
const part = parts[i];
|
|
@@ -6116,24 +6116,24 @@ var require_redact = __commonJS({
|
|
|
6116
6116
|
}
|
|
6117
6117
|
return cloneSelectively(obj, pathStructure);
|
|
6118
6118
|
}
|
|
6119
|
-
function validatePath(
|
|
6120
|
-
if (typeof
|
|
6119
|
+
function validatePath(path47) {
|
|
6120
|
+
if (typeof path47 !== "string") {
|
|
6121
6121
|
throw new Error("Paths must be (non-empty) strings");
|
|
6122
6122
|
}
|
|
6123
|
-
if (
|
|
6123
|
+
if (path47 === "") {
|
|
6124
6124
|
throw new Error("Invalid redaction path ()");
|
|
6125
6125
|
}
|
|
6126
|
-
if (
|
|
6127
|
-
throw new Error(`Invalid redaction path (${
|
|
6126
|
+
if (path47.includes("..")) {
|
|
6127
|
+
throw new Error(`Invalid redaction path (${path47})`);
|
|
6128
6128
|
}
|
|
6129
|
-
if (
|
|
6130
|
-
throw new Error(`Invalid redaction path (${
|
|
6129
|
+
if (path47.includes(",")) {
|
|
6130
|
+
throw new Error(`Invalid redaction path (${path47})`);
|
|
6131
6131
|
}
|
|
6132
6132
|
let bracketCount = 0;
|
|
6133
6133
|
let inQuotes = false;
|
|
6134
6134
|
let quoteChar = "";
|
|
6135
|
-
for (let i = 0; i <
|
|
6136
|
-
const char =
|
|
6135
|
+
for (let i = 0; i < path47.length; i++) {
|
|
6136
|
+
const char = path47[i];
|
|
6137
6137
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6138
6138
|
if (!inQuotes) {
|
|
6139
6139
|
inQuotes = true;
|
|
@@ -6147,20 +6147,20 @@ var require_redact = __commonJS({
|
|
|
6147
6147
|
} else if (char === "]" && !inQuotes) {
|
|
6148
6148
|
bracketCount--;
|
|
6149
6149
|
if (bracketCount < 0) {
|
|
6150
|
-
throw new Error(`Invalid redaction path (${
|
|
6150
|
+
throw new Error(`Invalid redaction path (${path47})`);
|
|
6151
6151
|
}
|
|
6152
6152
|
}
|
|
6153
6153
|
}
|
|
6154
6154
|
if (bracketCount !== 0) {
|
|
6155
|
-
throw new Error(`Invalid redaction path (${
|
|
6155
|
+
throw new Error(`Invalid redaction path (${path47})`);
|
|
6156
6156
|
}
|
|
6157
6157
|
}
|
|
6158
6158
|
function validatePaths(paths) {
|
|
6159
6159
|
if (!Array.isArray(paths)) {
|
|
6160
6160
|
throw new TypeError("paths must be an array");
|
|
6161
6161
|
}
|
|
6162
|
-
for (const
|
|
6163
|
-
validatePath(
|
|
6162
|
+
for (const path47 of paths) {
|
|
6163
|
+
validatePath(path47);
|
|
6164
6164
|
}
|
|
6165
6165
|
}
|
|
6166
6166
|
function slowRedact(options = {}) {
|
|
@@ -6328,8 +6328,8 @@ var require_redaction = __commonJS({
|
|
|
6328
6328
|
if (shape[k2] === null) {
|
|
6329
6329
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6330
6330
|
} else {
|
|
6331
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6332
|
-
return censor(value, [k2, ...
|
|
6331
|
+
const wrappedCensor = typeof censor === "function" ? (value, path47) => {
|
|
6332
|
+
return censor(value, [k2, ...path47]);
|
|
6333
6333
|
} : censor;
|
|
6334
6334
|
o[k2] = Redact({
|
|
6335
6335
|
paths: shape[k2],
|
|
@@ -6547,10 +6547,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
6547
6547
|
var require_sonic_boom = __commonJS({
|
|
6548
6548
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
6549
6549
|
"use strict";
|
|
6550
|
-
var
|
|
6550
|
+
var fs38 = require("fs");
|
|
6551
6551
|
var EventEmitter2 = require("events");
|
|
6552
6552
|
var inherits = require("util").inherits;
|
|
6553
|
-
var
|
|
6553
|
+
var path47 = require("path");
|
|
6554
6554
|
var sleep = require_atomic_sleep();
|
|
6555
6555
|
var assert = require("assert");
|
|
6556
6556
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -6604,20 +6604,20 @@ var require_sonic_boom = __commonJS({
|
|
|
6604
6604
|
const mode = sonic.mode;
|
|
6605
6605
|
if (sonic.sync) {
|
|
6606
6606
|
try {
|
|
6607
|
-
if (sonic.mkdir)
|
|
6608
|
-
const fd =
|
|
6607
|
+
if (sonic.mkdir) fs38.mkdirSync(path47.dirname(file), { recursive: true });
|
|
6608
|
+
const fd = fs38.openSync(file, flags, mode);
|
|
6609
6609
|
fileOpened(null, fd);
|
|
6610
6610
|
} catch (err) {
|
|
6611
6611
|
fileOpened(err);
|
|
6612
6612
|
throw err;
|
|
6613
6613
|
}
|
|
6614
6614
|
} else if (sonic.mkdir) {
|
|
6615
|
-
|
|
6615
|
+
fs38.mkdir(path47.dirname(file), { recursive: true }, (err) => {
|
|
6616
6616
|
if (err) return fileOpened(err);
|
|
6617
|
-
|
|
6617
|
+
fs38.open(file, flags, mode, fileOpened);
|
|
6618
6618
|
});
|
|
6619
6619
|
} else {
|
|
6620
|
-
|
|
6620
|
+
fs38.open(file, flags, mode, fileOpened);
|
|
6621
6621
|
}
|
|
6622
6622
|
}
|
|
6623
6623
|
function SonicBoom(opts) {
|
|
@@ -6658,8 +6658,8 @@ var require_sonic_boom = __commonJS({
|
|
|
6658
6658
|
this.flush = flushBuffer;
|
|
6659
6659
|
this.flushSync = flushBufferSync;
|
|
6660
6660
|
this._actualWrite = actualWriteBuffer;
|
|
6661
|
-
fsWriteSync = () =>
|
|
6662
|
-
fsWrite = () =>
|
|
6661
|
+
fsWriteSync = () => fs38.writeSync(this.fd, this._writingBuf);
|
|
6662
|
+
fsWrite = () => fs38.write(this.fd, this._writingBuf, this.release);
|
|
6663
6663
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
6664
6664
|
this._writingBuf = "";
|
|
6665
6665
|
this.write = write;
|
|
@@ -6668,15 +6668,15 @@ var require_sonic_boom = __commonJS({
|
|
|
6668
6668
|
this._actualWrite = actualWrite;
|
|
6669
6669
|
fsWriteSync = () => {
|
|
6670
6670
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6671
|
-
return
|
|
6671
|
+
return fs38.writeSync(this.fd, this._writingBuf);
|
|
6672
6672
|
}
|
|
6673
|
-
return
|
|
6673
|
+
return fs38.writeSync(this.fd, this._writingBuf, "utf8");
|
|
6674
6674
|
};
|
|
6675
6675
|
fsWrite = () => {
|
|
6676
6676
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6677
|
-
return
|
|
6677
|
+
return fs38.write(this.fd, this._writingBuf, this.release);
|
|
6678
6678
|
}
|
|
6679
|
-
return
|
|
6679
|
+
return fs38.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
6680
6680
|
};
|
|
6681
6681
|
} else {
|
|
6682
6682
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -6733,7 +6733,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6733
6733
|
}
|
|
6734
6734
|
}
|
|
6735
6735
|
if (this._fsync) {
|
|
6736
|
-
|
|
6736
|
+
fs38.fsyncSync(this.fd);
|
|
6737
6737
|
}
|
|
6738
6738
|
const len = this._len;
|
|
6739
6739
|
if (this._reopening) {
|
|
@@ -6847,7 +6847,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6847
6847
|
const onDrain = () => {
|
|
6848
6848
|
if (!this._fsync) {
|
|
6849
6849
|
try {
|
|
6850
|
-
|
|
6850
|
+
fs38.fsync(this.fd, (err) => {
|
|
6851
6851
|
this._flushPending = false;
|
|
6852
6852
|
cb(err);
|
|
6853
6853
|
});
|
|
@@ -6949,7 +6949,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6949
6949
|
const fd = this.fd;
|
|
6950
6950
|
this.once("ready", () => {
|
|
6951
6951
|
if (fd !== this.fd) {
|
|
6952
|
-
|
|
6952
|
+
fs38.close(fd, (err) => {
|
|
6953
6953
|
if (err) {
|
|
6954
6954
|
return this.emit("error", err);
|
|
6955
6955
|
}
|
|
@@ -6998,7 +6998,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6998
6998
|
buf = this._bufs[0];
|
|
6999
6999
|
}
|
|
7000
7000
|
try {
|
|
7001
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7001
|
+
const n = Buffer.isBuffer(buf) ? fs38.writeSync(this.fd, buf) : fs38.writeSync(this.fd, buf, "utf8");
|
|
7002
7002
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7003
7003
|
buf = releasedBufObj.writingBuf;
|
|
7004
7004
|
this._len = releasedBufObj.len;
|
|
@@ -7014,7 +7014,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7014
7014
|
}
|
|
7015
7015
|
}
|
|
7016
7016
|
try {
|
|
7017
|
-
|
|
7017
|
+
fs38.fsyncSync(this.fd);
|
|
7018
7018
|
} catch {
|
|
7019
7019
|
}
|
|
7020
7020
|
}
|
|
@@ -7035,7 +7035,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7035
7035
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7036
7036
|
}
|
|
7037
7037
|
try {
|
|
7038
|
-
const n =
|
|
7038
|
+
const n = fs38.writeSync(this.fd, buf);
|
|
7039
7039
|
buf = buf.subarray(n);
|
|
7040
7040
|
this._len = Math.max(this._len - n, 0);
|
|
7041
7041
|
if (buf.length <= 0) {
|
|
@@ -7063,13 +7063,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7063
7063
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7064
7064
|
if (this.sync) {
|
|
7065
7065
|
try {
|
|
7066
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7066
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs38.writeSync(this.fd, this._writingBuf) : fs38.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7067
7067
|
release(null, written);
|
|
7068
7068
|
} catch (err) {
|
|
7069
7069
|
release(err);
|
|
7070
7070
|
}
|
|
7071
7071
|
} else {
|
|
7072
|
-
|
|
7072
|
+
fs38.write(this.fd, this._writingBuf, release);
|
|
7073
7073
|
}
|
|
7074
7074
|
}
|
|
7075
7075
|
function actualWriteBuffer() {
|
|
@@ -7078,7 +7078,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7078
7078
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7079
7079
|
if (this.sync) {
|
|
7080
7080
|
try {
|
|
7081
|
-
const written =
|
|
7081
|
+
const written = fs38.writeSync(this.fd, this._writingBuf);
|
|
7082
7082
|
release(null, written);
|
|
7083
7083
|
} catch (err) {
|
|
7084
7084
|
release(err);
|
|
@@ -7087,7 +7087,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7087
7087
|
if (kCopyBuffer) {
|
|
7088
7088
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7089
7089
|
}
|
|
7090
|
-
|
|
7090
|
+
fs38.write(this.fd, this._writingBuf, release);
|
|
7091
7091
|
}
|
|
7092
7092
|
}
|
|
7093
7093
|
function actualClose(sonic) {
|
|
@@ -7103,12 +7103,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7103
7103
|
sonic._lens = [];
|
|
7104
7104
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7105
7105
|
try {
|
|
7106
|
-
|
|
7106
|
+
fs38.fsync(sonic.fd, closeWrapped);
|
|
7107
7107
|
} catch {
|
|
7108
7108
|
}
|
|
7109
7109
|
function closeWrapped() {
|
|
7110
7110
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7111
|
-
|
|
7111
|
+
fs38.close(sonic.fd, done);
|
|
7112
7112
|
} else {
|
|
7113
7113
|
done();
|
|
7114
7114
|
}
|
|
@@ -10243,11 +10243,11 @@ var init_lib = __esm({
|
|
|
10243
10243
|
}
|
|
10244
10244
|
}
|
|
10245
10245
|
},
|
|
10246
|
-
addToPath: function addToPath(
|
|
10247
|
-
var last =
|
|
10246
|
+
addToPath: function addToPath(path47, added, removed, oldPosInc, options) {
|
|
10247
|
+
var last = path47.lastComponent;
|
|
10248
10248
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10249
10249
|
return {
|
|
10250
|
-
oldPos:
|
|
10250
|
+
oldPos: path47.oldPos + oldPosInc,
|
|
10251
10251
|
lastComponent: {
|
|
10252
10252
|
count: last.count + 1,
|
|
10253
10253
|
added,
|
|
@@ -10257,7 +10257,7 @@ var init_lib = __esm({
|
|
|
10257
10257
|
};
|
|
10258
10258
|
} else {
|
|
10259
10259
|
return {
|
|
10260
|
-
oldPos:
|
|
10260
|
+
oldPos: path47.oldPos + oldPosInc,
|
|
10261
10261
|
lastComponent: {
|
|
10262
10262
|
count: 1,
|
|
10263
10263
|
added,
|
|
@@ -10503,7 +10503,7 @@ function hashDirToCwd(hash) {
|
|
|
10503
10503
|
}
|
|
10504
10504
|
function safeStatMtime(p2) {
|
|
10505
10505
|
try {
|
|
10506
|
-
return
|
|
10506
|
+
return import_node_fs8.default.statSync(p2).mtimeMs;
|
|
10507
10507
|
} catch {
|
|
10508
10508
|
return 0;
|
|
10509
10509
|
}
|
|
@@ -10511,7 +10511,7 @@ function safeStatMtime(p2) {
|
|
|
10511
10511
|
function readJsonlLines(file) {
|
|
10512
10512
|
let raw;
|
|
10513
10513
|
try {
|
|
10514
|
-
raw =
|
|
10514
|
+
raw = import_node_fs8.default.readFileSync(file, "utf8");
|
|
10515
10515
|
} catch (err) {
|
|
10516
10516
|
if (err.code === "ENOENT") return [];
|
|
10517
10517
|
throw err;
|
|
@@ -10688,10 +10688,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
10688
10688
|
const memories = raw.map((m2) => {
|
|
10689
10689
|
if (!m2 || typeof m2 !== "object") return null;
|
|
10690
10690
|
const rec = m2;
|
|
10691
|
-
const
|
|
10691
|
+
const path47 = typeof rec.path === "string" ? rec.path : null;
|
|
10692
10692
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10693
|
-
if (!
|
|
10694
|
-
const entry = { path:
|
|
10693
|
+
if (!path47 || content == null) return null;
|
|
10694
|
+
const entry = { path: path47, content };
|
|
10695
10695
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
10696
10696
|
return entry;
|
|
10697
10697
|
}).filter((m2) => m2 !== null);
|
|
@@ -10727,8 +10727,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
10727
10727
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
10728
10728
|
if (backupFileName === null) return null;
|
|
10729
10729
|
try {
|
|
10730
|
-
return
|
|
10731
|
-
|
|
10730
|
+
return import_node_fs8.default.readFileSync(
|
|
10731
|
+
import_node_path9.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
10732
10732
|
"utf8"
|
|
10733
10733
|
);
|
|
10734
10734
|
} catch {
|
|
@@ -10737,19 +10737,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
10737
10737
|
}
|
|
10738
10738
|
function readCurrentContent(filePath) {
|
|
10739
10739
|
try {
|
|
10740
|
-
return
|
|
10740
|
+
return import_node_fs8.default.readFileSync(filePath, "utf8");
|
|
10741
10741
|
} catch (err) {
|
|
10742
10742
|
if (err.code === "ENOENT") return null;
|
|
10743
10743
|
return null;
|
|
10744
10744
|
}
|
|
10745
10745
|
}
|
|
10746
|
-
var
|
|
10746
|
+
var import_node_fs8, import_node_os3, import_node_path9, TASK_NOTIFICATION_RE, TASK_ID_RE, TOOL_USE_ID_RE, SLASH_COMMAND_RE, LOCAL_COMMAND_RE, SYSTEM_REMINDER_RE, OPENSPEC_BLOCK_RE, SKILL_HINT_RE, ATTACHMENT_SILENT_SUBTYPES, ClaudeHistoryReader;
|
|
10747
10747
|
var init_claude_history = __esm({
|
|
10748
10748
|
"src/tools/claude-history.ts"() {
|
|
10749
10749
|
"use strict";
|
|
10750
|
-
|
|
10750
|
+
import_node_fs8 = __toESM(require("fs"), 1);
|
|
10751
10751
|
import_node_os3 = __toESM(require("os"), 1);
|
|
10752
|
-
|
|
10752
|
+
import_node_path9 = __toESM(require("path"), 1);
|
|
10753
10753
|
init_lib();
|
|
10754
10754
|
init_tool_result_extra();
|
|
10755
10755
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -10773,14 +10773,14 @@ var init_claude_history = __esm({
|
|
|
10773
10773
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
10774
10774
|
fileHistoryRoot;
|
|
10775
10775
|
constructor(opts = {}) {
|
|
10776
|
-
const base = opts.baseDir ??
|
|
10777
|
-
this.projectsRoot =
|
|
10778
|
-
this.fileHistoryRoot =
|
|
10776
|
+
const base = opts.baseDir ?? import_node_path9.default.join(import_node_os3.default.homedir(), ".claude");
|
|
10777
|
+
this.projectsRoot = import_node_path9.default.join(base, "projects");
|
|
10778
|
+
this.fileHistoryRoot = import_node_path9.default.join(base, "file-history");
|
|
10779
10779
|
}
|
|
10780
10780
|
async listProjects() {
|
|
10781
10781
|
let entries;
|
|
10782
10782
|
try {
|
|
10783
|
-
entries =
|
|
10783
|
+
entries = import_node_fs8.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
10784
10784
|
} catch (err) {
|
|
10785
10785
|
if (err.code === "ENOENT") return [];
|
|
10786
10786
|
throw err;
|
|
@@ -10788,9 +10788,9 @@ var init_claude_history = __esm({
|
|
|
10788
10788
|
const out = [];
|
|
10789
10789
|
for (const ent of entries) {
|
|
10790
10790
|
if (!ent.isDirectory()) continue;
|
|
10791
|
-
const dir =
|
|
10792
|
-
const files =
|
|
10793
|
-
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(
|
|
10791
|
+
const dir = import_node_path9.default.join(this.projectsRoot, ent.name);
|
|
10792
|
+
const files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
10793
|
+
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path9.default.join(dir, f))), 0);
|
|
10794
10794
|
out.push({
|
|
10795
10795
|
projectPath: hashDirToCwd(ent.name),
|
|
10796
10796
|
hashDir: ent.name,
|
|
@@ -10802,17 +10802,17 @@ var init_claude_history = __esm({
|
|
|
10802
10802
|
return out;
|
|
10803
10803
|
}
|
|
10804
10804
|
async listSessions(args) {
|
|
10805
|
-
const dir =
|
|
10805
|
+
const dir = import_node_path9.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
10806
10806
|
let files;
|
|
10807
10807
|
try {
|
|
10808
|
-
files =
|
|
10808
|
+
files = import_node_fs8.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
10809
10809
|
} catch (err) {
|
|
10810
10810
|
if (err.code === "ENOENT") return [];
|
|
10811
10811
|
throw err;
|
|
10812
10812
|
}
|
|
10813
10813
|
const out = [];
|
|
10814
10814
|
for (const f of files) {
|
|
10815
|
-
const full =
|
|
10815
|
+
const full = import_node_path9.default.join(dir, f);
|
|
10816
10816
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
10817
10817
|
const lines = readJsonlLines(full);
|
|
10818
10818
|
let summary = "";
|
|
@@ -10867,7 +10867,7 @@ var init_claude_history = __esm({
|
|
|
10867
10867
|
return out;
|
|
10868
10868
|
}
|
|
10869
10869
|
async read(args) {
|
|
10870
|
-
const file =
|
|
10870
|
+
const file = import_node_path9.default.join(
|
|
10871
10871
|
this.projectsRoot,
|
|
10872
10872
|
cwdToHashDir(args.cwd),
|
|
10873
10873
|
`${args.toolSessionId}.jsonl`
|
|
@@ -10900,7 +10900,7 @@ var init_claude_history = __esm({
|
|
|
10900
10900
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
10901
10901
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
10902
10902
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
10903
|
-
const dir =
|
|
10903
|
+
const dir = import_node_path9.default.join(
|
|
10904
10904
|
this.projectsRoot,
|
|
10905
10905
|
cwdToHashDir(cwd),
|
|
10906
10906
|
toolSessionId,
|
|
@@ -10908,7 +10908,7 @@ var init_claude_history = __esm({
|
|
|
10908
10908
|
);
|
|
10909
10909
|
let entries;
|
|
10910
10910
|
try {
|
|
10911
|
-
entries =
|
|
10911
|
+
entries = import_node_fs8.default.readdirSync(dir, { withFileTypes: true });
|
|
10912
10912
|
} catch (err) {
|
|
10913
10913
|
if (err.code === "ENOENT") return null;
|
|
10914
10914
|
return null;
|
|
@@ -10918,7 +10918,7 @@ var init_claude_history = __esm({
|
|
|
10918
10918
|
if (!e.isFile()) continue;
|
|
10919
10919
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
10920
10920
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
10921
|
-
const filePath =
|
|
10921
|
+
const filePath = import_node_path9.default.join(dir, e.name);
|
|
10922
10922
|
const lines = readJsonlLines(filePath);
|
|
10923
10923
|
let firstText = "";
|
|
10924
10924
|
let messageCount = 0;
|
|
@@ -10935,7 +10935,7 @@ var init_claude_history = __esm({
|
|
|
10935
10935
|
return out;
|
|
10936
10936
|
}
|
|
10937
10937
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
10938
|
-
const file =
|
|
10938
|
+
const file = import_node_path9.default.join(
|
|
10939
10939
|
this.projectsRoot,
|
|
10940
10940
|
cwdToHashDir(cwd),
|
|
10941
10941
|
`${toolSessionId}.jsonl`
|
|
@@ -10970,7 +10970,7 @@ var init_claude_history = __esm({
|
|
|
10970
10970
|
}
|
|
10971
10971
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
10972
10972
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
10973
|
-
const file =
|
|
10973
|
+
const file = import_node_path9.default.join(
|
|
10974
10974
|
this.projectsRoot,
|
|
10975
10975
|
cwdToHashDir(cwd),
|
|
10976
10976
|
toolSessionId,
|
|
@@ -10979,7 +10979,7 @@ var init_claude_history = __esm({
|
|
|
10979
10979
|
);
|
|
10980
10980
|
let exists = false;
|
|
10981
10981
|
try {
|
|
10982
|
-
exists =
|
|
10982
|
+
exists = import_node_fs8.default.statSync(file).isFile();
|
|
10983
10983
|
} catch {
|
|
10984
10984
|
return null;
|
|
10985
10985
|
}
|
|
@@ -10998,7 +10998,7 @@ var init_claude_history = __esm({
|
|
|
10998
10998
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
10999
10999
|
*/
|
|
11000
11000
|
readFileHistorySnapshots(args) {
|
|
11001
|
-
const file =
|
|
11001
|
+
const file = import_node_path9.default.join(
|
|
11002
11002
|
this.projectsRoot,
|
|
11003
11003
|
cwdToHashDir(args.cwd),
|
|
11004
11004
|
`${args.toolSessionId}.jsonl`
|
|
@@ -11043,7 +11043,7 @@ var init_claude_history = __esm({
|
|
|
11043
11043
|
for (const [anchorId, target] of snapshots) {
|
|
11044
11044
|
let hasAny = false;
|
|
11045
11045
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11046
|
-
const absPath =
|
|
11046
|
+
const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
|
|
11047
11047
|
const backupContent = readBackupContent(
|
|
11048
11048
|
this.fileHistoryRoot,
|
|
11049
11049
|
args.toolSessionId,
|
|
@@ -11083,7 +11083,7 @@ var init_claude_history = __esm({
|
|
|
11083
11083
|
let totalInsertions = 0;
|
|
11084
11084
|
let totalDeletions = 0;
|
|
11085
11085
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11086
|
-
const absPath =
|
|
11086
|
+
const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
|
|
11087
11087
|
const backupContent = readBackupContent(
|
|
11088
11088
|
this.fileHistoryRoot,
|
|
11089
11089
|
args.toolSessionId,
|
|
@@ -11130,7 +11130,7 @@ var init_claude_history = __esm({
|
|
|
11130
11130
|
};
|
|
11131
11131
|
}
|
|
11132
11132
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
11133
|
-
const file =
|
|
11133
|
+
const file = import_node_path9.default.join(
|
|
11134
11134
|
this.projectsRoot,
|
|
11135
11135
|
cwdToHashDir(cwd),
|
|
11136
11136
|
`${toolSessionId}.jsonl`
|
|
@@ -11154,48 +11154,48 @@ var init_claude_history = __esm({
|
|
|
11154
11154
|
// src/tools/sandbox.ts
|
|
11155
11155
|
function shouldSandbox(cwd, personaRoot) {
|
|
11156
11156
|
if (!personaRoot) return false;
|
|
11157
|
-
const sep3 = personaRoot.endsWith(
|
|
11157
|
+
const sep3 = personaRoot.endsWith(path13.sep) ? "" : path13.sep;
|
|
11158
11158
|
return cwd.startsWith(personaRoot + sep3) && cwd !== personaRoot;
|
|
11159
11159
|
}
|
|
11160
11160
|
function inferSandboxSettingsPath(cwd, personaRoot) {
|
|
11161
11161
|
if (!shouldSandbox(cwd, personaRoot)) return null;
|
|
11162
|
-
const rel =
|
|
11163
|
-
const personaId = rel.split(
|
|
11162
|
+
const rel = path13.relative(personaRoot, cwd);
|
|
11163
|
+
const personaId = rel.split(path13.sep)[0];
|
|
11164
11164
|
if (!personaId) return null;
|
|
11165
|
-
return
|
|
11165
|
+
return path13.join(personaRoot, personaId, ".clawd", "sandbox-settings.json");
|
|
11166
11166
|
}
|
|
11167
|
-
var
|
|
11167
|
+
var path13;
|
|
11168
11168
|
var init_sandbox = __esm({
|
|
11169
11169
|
"src/tools/sandbox.ts"() {
|
|
11170
11170
|
"use strict";
|
|
11171
|
-
|
|
11171
|
+
path13 = __toESM(require("path"), 1);
|
|
11172
11172
|
}
|
|
11173
11173
|
});
|
|
11174
11174
|
|
|
11175
11175
|
// src/tools/claude.ts
|
|
11176
11176
|
function macOSDesktopCandidates(home) {
|
|
11177
11177
|
return [
|
|
11178
|
-
|
|
11178
|
+
import_node_path10.default.join(home, "Applications", "Claude.app", "Contents", "Resources", "app.asar.unpacked", "node_modules", "@anthropic-ai", "claude-code", "cli.js"),
|
|
11179
11179
|
"/Applications/Claude.app/Contents/Resources/app.asar.unpacked/node_modules/@anthropic-ai/claude-code/cli.js"
|
|
11180
11180
|
];
|
|
11181
11181
|
}
|
|
11182
11182
|
function probeViaWhich() {
|
|
11183
11183
|
try {
|
|
11184
11184
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
11185
|
-
if (out &&
|
|
11185
|
+
if (out && import_node_fs9.default.existsSync(out)) return out;
|
|
11186
11186
|
} catch {
|
|
11187
11187
|
}
|
|
11188
11188
|
return null;
|
|
11189
11189
|
}
|
|
11190
11190
|
async function probeClaude(env = process.env, home = import_node_os4.default.homedir()) {
|
|
11191
|
-
if (env.CLAUDE_BIN &&
|
|
11191
|
+
if (env.CLAUDE_BIN && import_node_fs9.default.existsSync(env.CLAUDE_BIN)) {
|
|
11192
11192
|
return { available: true, path: env.CLAUDE_BIN };
|
|
11193
11193
|
}
|
|
11194
11194
|
const w2 = probeViaWhich();
|
|
11195
11195
|
if (w2) return { available: true, path: w2 };
|
|
11196
11196
|
if (process.platform === "darwin") {
|
|
11197
11197
|
for (const candidate of macOSDesktopCandidates(home)) {
|
|
11198
|
-
if (
|
|
11198
|
+
if (import_node_fs9.default.existsSync(candidate)) {
|
|
11199
11199
|
return { available: true, path: candidate };
|
|
11200
11200
|
}
|
|
11201
11201
|
}
|
|
@@ -11517,10 +11517,10 @@ function parseAttachment(obj) {
|
|
|
11517
11517
|
const memories = raw.map((m2) => {
|
|
11518
11518
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11519
11519
|
const rec = m2;
|
|
11520
|
-
const
|
|
11520
|
+
const path47 = typeof rec.path === "string" ? rec.path : null;
|
|
11521
11521
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11522
|
-
if (!
|
|
11523
|
-
const out = { path:
|
|
11522
|
+
if (!path47 || content == null) return null;
|
|
11523
|
+
const out = { path: path47, content };
|
|
11524
11524
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
11525
11525
|
return out;
|
|
11526
11526
|
}).filter((m2) => m2 !== null);
|
|
@@ -11624,15 +11624,15 @@ function encodeClaudeStdin(text) {
|
|
|
11624
11624
|
};
|
|
11625
11625
|
return JSON.stringify(frame) + "\n";
|
|
11626
11626
|
}
|
|
11627
|
-
var import_node_child_process, import_node_child_process2,
|
|
11627
|
+
var import_node_child_process, import_node_child_process2, import_node_fs9, import_node_os4, import_node_path10, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
11628
11628
|
var init_claude = __esm({
|
|
11629
11629
|
"src/tools/claude.ts"() {
|
|
11630
11630
|
"use strict";
|
|
11631
11631
|
import_node_child_process = require("child_process");
|
|
11632
11632
|
import_node_child_process2 = require("child_process");
|
|
11633
|
-
|
|
11633
|
+
import_node_fs9 = __toESM(require("fs"), 1);
|
|
11634
11634
|
import_node_os4 = __toESM(require("os"), 1);
|
|
11635
|
-
|
|
11635
|
+
import_node_path10 = __toESM(require("path"), 1);
|
|
11636
11636
|
init_protocol();
|
|
11637
11637
|
init_claude_history();
|
|
11638
11638
|
init_tool_result_extra();
|
|
@@ -20435,7 +20435,7 @@ var require_websocket_server = __commonJS({
|
|
|
20435
20435
|
// src/run-case/recorder.ts
|
|
20436
20436
|
function startRunCaseRecorder(opts) {
|
|
20437
20437
|
const now = opts.now ?? Date.now;
|
|
20438
|
-
const dir =
|
|
20438
|
+
const dir = import_node_path33.default.dirname(opts.recordPath);
|
|
20439
20439
|
let stream = null;
|
|
20440
20440
|
let closing = false;
|
|
20441
20441
|
let closedSettled = false;
|
|
@@ -20449,8 +20449,8 @@ function startRunCaseRecorder(opts) {
|
|
|
20449
20449
|
});
|
|
20450
20450
|
const ensureStream = () => {
|
|
20451
20451
|
if (stream) return stream;
|
|
20452
|
-
|
|
20453
|
-
stream =
|
|
20452
|
+
import_node_fs30.default.mkdirSync(dir, { recursive: true });
|
|
20453
|
+
stream = import_node_fs30.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
20454
20454
|
stream.on("close", () => closedResolve());
|
|
20455
20455
|
return stream;
|
|
20456
20456
|
};
|
|
@@ -20475,12 +20475,12 @@ function startRunCaseRecorder(opts) {
|
|
|
20475
20475
|
};
|
|
20476
20476
|
return { tap, close, closed };
|
|
20477
20477
|
}
|
|
20478
|
-
var
|
|
20478
|
+
var import_node_fs30, import_node_path33;
|
|
20479
20479
|
var init_recorder = __esm({
|
|
20480
20480
|
"src/run-case/recorder.ts"() {
|
|
20481
20481
|
"use strict";
|
|
20482
|
-
|
|
20483
|
-
|
|
20482
|
+
import_node_fs30 = __toESM(require("fs"), 1);
|
|
20483
|
+
import_node_path33 = __toESM(require("path"), 1);
|
|
20484
20484
|
}
|
|
20485
20485
|
});
|
|
20486
20486
|
|
|
@@ -20523,7 +20523,7 @@ var init_wire = __esm({
|
|
|
20523
20523
|
// src/run-case/controller.ts
|
|
20524
20524
|
async function runController(opts) {
|
|
20525
20525
|
const now = opts.now ?? Date.now;
|
|
20526
|
-
const cwd = opts.cwd ?? (0,
|
|
20526
|
+
const cwd = opts.cwd ?? (0, import_node_fs31.mkdtempSync)(import_node_path34.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
|
|
20527
20527
|
const ownsCwd = opts.cwd === void 0;
|
|
20528
20528
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
20529
20529
|
const spawnCtx = { cwd };
|
|
@@ -20684,19 +20684,19 @@ async function runController(opts) {
|
|
|
20684
20684
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
20685
20685
|
if (ownsCwd) {
|
|
20686
20686
|
try {
|
|
20687
|
-
(0,
|
|
20687
|
+
(0, import_node_fs31.rmSync)(cwd, { recursive: true, force: true });
|
|
20688
20688
|
} catch {
|
|
20689
20689
|
}
|
|
20690
20690
|
}
|
|
20691
20691
|
return exitCode ?? 0;
|
|
20692
20692
|
}
|
|
20693
|
-
var
|
|
20693
|
+
var import_node_fs31, import_node_os15, import_node_path34;
|
|
20694
20694
|
var init_controller = __esm({
|
|
20695
20695
|
"src/run-case/controller.ts"() {
|
|
20696
20696
|
"use strict";
|
|
20697
|
-
|
|
20697
|
+
import_node_fs31 = require("fs");
|
|
20698
20698
|
import_node_os15 = __toESM(require("os"), 1);
|
|
20699
|
-
|
|
20699
|
+
import_node_path34 = __toESM(require("path"), 1);
|
|
20700
20700
|
init_claude();
|
|
20701
20701
|
init_stdout_splitter();
|
|
20702
20702
|
init_permission_stdio();
|
|
@@ -20928,8 +20928,8 @@ Env (advanced):
|
|
|
20928
20928
|
`;
|
|
20929
20929
|
|
|
20930
20930
|
// src/index.ts
|
|
20931
|
-
var
|
|
20932
|
-
var
|
|
20931
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
20932
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
20933
20933
|
|
|
20934
20934
|
// src/logger.ts
|
|
20935
20935
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -21153,8 +21153,8 @@ var SessionStoreFactory = class {
|
|
|
21153
21153
|
};
|
|
21154
21154
|
|
|
21155
21155
|
// src/session/manager.ts
|
|
21156
|
-
var
|
|
21157
|
-
var
|
|
21156
|
+
var import_node_fs6 = __toESM(require("fs"), 1);
|
|
21157
|
+
var import_node_path7 = __toESM(require("path"), 1);
|
|
21158
21158
|
|
|
21159
21159
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
21160
21160
|
var byteToHex = [];
|
|
@@ -22398,6 +22398,62 @@ function extractEditPath(input) {
|
|
|
22398
22398
|
return candidate || null;
|
|
22399
22399
|
}
|
|
22400
22400
|
|
|
22401
|
+
// src/debug/pty-probe.ts
|
|
22402
|
+
var import_node_fs5 = __toESM(require("fs"), 1);
|
|
22403
|
+
var import_node_path6 = __toESM(require("path"), 1);
|
|
22404
|
+
var PROBE_DIR = "/tmp/clawd-probe";
|
|
22405
|
+
var EVENTS_FILE = import_node_path6.default.join(PROBE_DIR, "events.jsonl");
|
|
22406
|
+
var inited = false;
|
|
22407
|
+
function ensureDir() {
|
|
22408
|
+
if (inited) return true;
|
|
22409
|
+
try {
|
|
22410
|
+
import_node_fs5.default.mkdirSync(PROBE_DIR, { recursive: true });
|
|
22411
|
+
inited = true;
|
|
22412
|
+
return true;
|
|
22413
|
+
} catch {
|
|
22414
|
+
return false;
|
|
22415
|
+
}
|
|
22416
|
+
}
|
|
22417
|
+
function probeEvent(event, data = {}) {
|
|
22418
|
+
try {
|
|
22419
|
+
if (!ensureDir()) return;
|
|
22420
|
+
const line = JSON.stringify({ ts: Date.now(), event, ...data }) + "\n";
|
|
22421
|
+
import_node_fs5.default.appendFileSync(EVENTS_FILE, line);
|
|
22422
|
+
} catch {
|
|
22423
|
+
}
|
|
22424
|
+
}
|
|
22425
|
+
function probeDumpReplay(sessionId, payload) {
|
|
22426
|
+
try {
|
|
22427
|
+
if (!ensureDir()) return "";
|
|
22428
|
+
const file = import_node_path6.default.join(PROBE_DIR, `replay-${sessionId}-${Date.now()}.ans`);
|
|
22429
|
+
import_node_fs5.default.writeFileSync(file, payload, "utf8");
|
|
22430
|
+
return file;
|
|
22431
|
+
} catch {
|
|
22432
|
+
return "";
|
|
22433
|
+
}
|
|
22434
|
+
}
|
|
22435
|
+
var _throttle = /* @__PURE__ */ new Map();
|
|
22436
|
+
function probePtyDataThrottled(tsid, len, tail) {
|
|
22437
|
+
const now = Date.now();
|
|
22438
|
+
let s = _throttle.get(tsid);
|
|
22439
|
+
if (!s) {
|
|
22440
|
+
s = { last: 0, bytes: 0, chunks: 0 };
|
|
22441
|
+
_throttle.set(tsid, s);
|
|
22442
|
+
}
|
|
22443
|
+
s.bytes += len;
|
|
22444
|
+
s.chunks += 1;
|
|
22445
|
+
if (now - s.last >= 1e3) {
|
|
22446
|
+
probeEvent("pty.data", {
|
|
22447
|
+
tsid,
|
|
22448
|
+
chunks: s.chunks,
|
|
22449
|
+
accumBytes: s.bytes,
|
|
22450
|
+
lastChunkLen: len,
|
|
22451
|
+
tailHex: tail.subarray(Math.max(0, tail.length - 32)).toString("hex")
|
|
22452
|
+
});
|
|
22453
|
+
s.last = now;
|
|
22454
|
+
}
|
|
22455
|
+
}
|
|
22456
|
+
|
|
22401
22457
|
// src/session/manager.ts
|
|
22402
22458
|
function compressFrameForWire(frame) {
|
|
22403
22459
|
if (frame.type !== "session:status") return frame;
|
|
@@ -22461,7 +22517,7 @@ function derivePersonaSpawnCwd(file, personaRoot) {
|
|
|
22461
22517
|
`derivePersonaSpawnCwd: personaRoot missing for owner session ${file.sessionId} (ownerPersonaId=${personaId})`
|
|
22462
22518
|
);
|
|
22463
22519
|
}
|
|
22464
|
-
return
|
|
22520
|
+
return import_node_path7.default.join(personaRoot, safeFileName(personaId));
|
|
22465
22521
|
}
|
|
22466
22522
|
function makeInitialState(file, subSessionMeta) {
|
|
22467
22523
|
return {
|
|
@@ -22575,10 +22631,10 @@ var SessionManager = class {
|
|
|
22575
22631
|
// <dataDir>/sessions/ 列子目录 (排除 'default').
|
|
22576
22632
|
listPersonaIdsOnDisk() {
|
|
22577
22633
|
if (!this.deps.dataDir) return [];
|
|
22578
|
-
const root = this.deps.storeFactory ?
|
|
22634
|
+
const root = this.deps.storeFactory ? import_node_path7.default.join(this.deps.dataDir, "personas") : import_node_path7.default.join(this.deps.dataDir, "sessions");
|
|
22579
22635
|
let entries;
|
|
22580
22636
|
try {
|
|
22581
|
-
entries =
|
|
22637
|
+
entries = import_node_fs6.default.readdirSync(root, { withFileTypes: true });
|
|
22582
22638
|
} catch (err) {
|
|
22583
22639
|
const code = err?.code;
|
|
22584
22640
|
if (code === "ENOENT") return [];
|
|
@@ -22591,7 +22647,7 @@ var SessionManager = class {
|
|
|
22591
22647
|
// 只在 storeFactory 注入 (新布局) 下生效, 老布局无 guest 目录.
|
|
22592
22648
|
listGuestCapIdsForPersona(personaId) {
|
|
22593
22649
|
if (!this.deps.dataDir || !this.deps.storeFactory) return [];
|
|
22594
|
-
const root =
|
|
22650
|
+
const root = import_node_path7.default.join(
|
|
22595
22651
|
this.deps.dataDir,
|
|
22596
22652
|
"personas",
|
|
22597
22653
|
personaId,
|
|
@@ -22601,7 +22657,7 @@ var SessionManager = class {
|
|
|
22601
22657
|
);
|
|
22602
22658
|
let entries;
|
|
22603
22659
|
try {
|
|
22604
|
-
entries =
|
|
22660
|
+
entries = import_node_fs6.default.readdirSync(root, { withFileTypes: true });
|
|
22605
22661
|
} catch (err) {
|
|
22606
22662
|
const code = err?.code;
|
|
22607
22663
|
if (code === "ENOENT") return [];
|
|
@@ -22838,7 +22894,7 @@ var SessionManager = class {
|
|
|
22838
22894
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "cwd required when ownerPersonaId is absent");
|
|
22839
22895
|
}
|
|
22840
22896
|
try {
|
|
22841
|
-
const stat =
|
|
22897
|
+
const stat = import_node_fs6.default.statSync(cwd);
|
|
22842
22898
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
22843
22899
|
} catch {
|
|
22844
22900
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${cwd}`);
|
|
@@ -23374,7 +23430,7 @@ var SessionManager = class {
|
|
|
23374
23430
|
*/
|
|
23375
23431
|
createForScope(args) {
|
|
23376
23432
|
try {
|
|
23377
|
-
const stat =
|
|
23433
|
+
const stat = import_node_fs6.default.statSync(args.cwd);
|
|
23378
23434
|
if (!stat.isDirectory()) throw new Error("not dir");
|
|
23379
23435
|
} catch {
|
|
23380
23436
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `cwd not a directory: ${args.cwd}`);
|
|
@@ -23709,15 +23765,27 @@ var SessionManager = class {
|
|
|
23709
23765
|
}
|
|
23710
23766
|
/** spawn 进程 exit 时调用,清理映射防止后续 input 写到已死 pty + 释放 replay 闭包 */
|
|
23711
23767
|
unregisterPty(toolSessionId) {
|
|
23768
|
+
const hadReplay = this.ptyReplaysByToolSid.has(toolSessionId);
|
|
23712
23769
|
this.ptyTransports.delete(toolSessionId);
|
|
23713
23770
|
this.ptyReplaysByToolSid.delete(toolSessionId);
|
|
23771
|
+
probeEvent("pty.unregister", {
|
|
23772
|
+
tsid: toolSessionId,
|
|
23773
|
+
hadReplay,
|
|
23774
|
+
replayMapKeys: Array.from(this.ptyReplaysByToolSid.keys())
|
|
23775
|
+
});
|
|
23714
23776
|
}
|
|
23715
23777
|
/**
|
|
23716
23778
|
* ClaudeTuiAdapter.spawn 创建 detector 后调用,注册当前屏幕快照闭包。
|
|
23717
23779
|
* 同一 toolSessionId 重 spawn 会覆盖;unregisterPty 时一并删除。
|
|
23718
23780
|
*/
|
|
23719
23781
|
registerPtyReplay(toolSessionId, replay) {
|
|
23782
|
+
const overwrite = this.ptyReplaysByToolSid.has(toolSessionId);
|
|
23720
23783
|
this.ptyReplaysByToolSid.set(toolSessionId, replay);
|
|
23784
|
+
probeEvent("pty.register", {
|
|
23785
|
+
tsid: toolSessionId,
|
|
23786
|
+
overwrite,
|
|
23787
|
+
replayMapKeys: Array.from(this.ptyReplaysByToolSid.keys())
|
|
23788
|
+
});
|
|
23721
23789
|
}
|
|
23722
23790
|
/**
|
|
23723
23791
|
* 新 client subscribe 时拉当前屏幕快照。返回 null 表示无可重放数据:
|
|
@@ -23726,14 +23794,47 @@ var SessionManager = class {
|
|
|
23726
23794
|
* 调用方(onSubscribe hook)按返回值非空时构造 session:pty + session:control 帧定向回放
|
|
23727
23795
|
*/
|
|
23728
23796
|
getPtyReplay(sessionId) {
|
|
23729
|
-
if (this.deps.mode !== "tui")
|
|
23797
|
+
if (this.deps.mode !== "tui") {
|
|
23798
|
+
probeEvent("replay.request", { sid: sessionId, result: "not-tui-mode" });
|
|
23799
|
+
return null;
|
|
23800
|
+
}
|
|
23730
23801
|
const runner = this.runners.get(sessionId);
|
|
23731
|
-
if (!runner)
|
|
23802
|
+
if (!runner) {
|
|
23803
|
+
probeEvent("replay.request", {
|
|
23804
|
+
sid: sessionId,
|
|
23805
|
+
result: "no-runner",
|
|
23806
|
+
runnerKeys: Array.from(this.runners.keys())
|
|
23807
|
+
});
|
|
23808
|
+
return null;
|
|
23809
|
+
}
|
|
23732
23810
|
const tsid = runner.getState().file.toolSessionId;
|
|
23733
|
-
if (!tsid)
|
|
23811
|
+
if (!tsid) {
|
|
23812
|
+
probeEvent("replay.request", { sid: sessionId, result: "no-tsid" });
|
|
23813
|
+
return null;
|
|
23814
|
+
}
|
|
23734
23815
|
const replay = this.ptyReplaysByToolSid.get(tsid);
|
|
23735
|
-
if (!replay)
|
|
23736
|
-
|
|
23816
|
+
if (!replay) {
|
|
23817
|
+
probeEvent("replay.request", {
|
|
23818
|
+
sid: sessionId,
|
|
23819
|
+
tsid,
|
|
23820
|
+
result: "no-replay-closure",
|
|
23821
|
+
replayMapKeys: Array.from(this.ptyReplaysByToolSid.keys())
|
|
23822
|
+
});
|
|
23823
|
+
return null;
|
|
23824
|
+
}
|
|
23825
|
+
const snap = replay();
|
|
23826
|
+
const dumpFile = probeDumpReplay(sessionId, snap.data);
|
|
23827
|
+
probeEvent("replay.dump", {
|
|
23828
|
+
sid: sessionId,
|
|
23829
|
+
tsid,
|
|
23830
|
+
bytes: snap.data.length,
|
|
23831
|
+
popupKind: snap.popupKind,
|
|
23832
|
+
headHex: Buffer.from(snap.data, "utf8").subarray(0, 32).toString("hex"),
|
|
23833
|
+
dumpFile,
|
|
23834
|
+
runnerKeys: Array.from(this.runners.keys()),
|
|
23835
|
+
replayMapKeys: Array.from(this.ptyReplaysByToolSid.keys())
|
|
23836
|
+
});
|
|
23837
|
+
return snap;
|
|
23737
23838
|
}
|
|
23738
23839
|
/**
|
|
23739
23840
|
* handler tui:pty:input / tui:pty:resize 入口:传 wire 层 sessionId(16 字符),
|
|
@@ -23796,8 +23897,8 @@ var SessionManager = class {
|
|
|
23796
23897
|
};
|
|
23797
23898
|
|
|
23798
23899
|
// src/persona/store.ts
|
|
23799
|
-
var
|
|
23800
|
-
var
|
|
23900
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
23901
|
+
var path9 = __toESM(require("path"), 1);
|
|
23801
23902
|
init_protocol();
|
|
23802
23903
|
var DEFAULT_SETTINGS = {
|
|
23803
23904
|
permissions: {
|
|
@@ -23822,17 +23923,17 @@ var DEFAULT_SETTINGS = {
|
|
|
23822
23923
|
var PersonaStore = class {
|
|
23823
23924
|
constructor(root) {
|
|
23824
23925
|
this.root = root;
|
|
23825
|
-
|
|
23926
|
+
fs7.mkdirSync(root, { recursive: true });
|
|
23826
23927
|
}
|
|
23827
23928
|
root;
|
|
23828
23929
|
personaDir(personaId) {
|
|
23829
|
-
return
|
|
23930
|
+
return path9.join(this.root, safeFileName(personaId));
|
|
23830
23931
|
}
|
|
23831
23932
|
metaPath(personaId) {
|
|
23832
|
-
return
|
|
23933
|
+
return path9.join(this.personaDir(personaId), ".clawd", "persona.json");
|
|
23833
23934
|
}
|
|
23834
23935
|
claudeMdPath(personaId) {
|
|
23835
|
-
return
|
|
23936
|
+
return path9.join(this.personaDir(personaId), "CLAUDE.md");
|
|
23836
23937
|
}
|
|
23837
23938
|
/**
|
|
23838
23939
|
* Sandbox settings 落盘路径 —— 故意放在 `.clawd/` 而不是 `.claude/`,让 CC 的
|
|
@@ -23842,11 +23943,11 @@ var PersonaStore = class {
|
|
|
23842
23943
|
* 加载 persona 人格,只有 listener 多一层 OS sandbox。
|
|
23843
23944
|
*/
|
|
23844
23945
|
sandboxSettingsPath(personaId) {
|
|
23845
|
-
return
|
|
23946
|
+
return path9.join(this.personaDir(personaId), ".clawd", "sandbox-settings.json");
|
|
23846
23947
|
}
|
|
23847
23948
|
write(persona, personality) {
|
|
23848
23949
|
const dir = this.personaDir(persona.personaId);
|
|
23849
|
-
|
|
23950
|
+
fs7.mkdirSync(path9.join(dir, ".clawd"), { recursive: true });
|
|
23850
23951
|
this.atomicWrite(this.claudeMdPath(persona.personaId), personality);
|
|
23851
23952
|
this.atomicWrite(
|
|
23852
23953
|
this.sandboxSettingsPath(persona.personaId),
|
|
@@ -23862,8 +23963,8 @@ var PersonaStore = class {
|
|
|
23862
23963
|
}
|
|
23863
23964
|
read(personaId) {
|
|
23864
23965
|
const p2 = this.metaPath(personaId);
|
|
23865
|
-
if (!
|
|
23866
|
-
const raw = JSON.parse(
|
|
23966
|
+
if (!fs7.existsSync(p2)) return null;
|
|
23967
|
+
const raw = JSON.parse(fs7.readFileSync(p2, "utf8"));
|
|
23867
23968
|
if (raw && typeof raw === "object" && "tokenMap" in raw) {
|
|
23868
23969
|
delete raw.tokenMap;
|
|
23869
23970
|
this.atomicWrite(p2, JSON.stringify(raw, null, 2));
|
|
@@ -23871,12 +23972,12 @@ var PersonaStore = class {
|
|
|
23871
23972
|
return PersonaFileSchema.parse(raw);
|
|
23872
23973
|
}
|
|
23873
23974
|
has(personaId) {
|
|
23874
|
-
return
|
|
23975
|
+
return fs7.existsSync(this.metaPath(personaId));
|
|
23875
23976
|
}
|
|
23876
23977
|
readPersonality(personaId) {
|
|
23877
23978
|
const p2 = this.claudeMdPath(personaId);
|
|
23878
|
-
if (!
|
|
23879
|
-
return
|
|
23979
|
+
if (!fs7.existsSync(p2)) return null;
|
|
23980
|
+
return fs7.readFileSync(p2, "utf8");
|
|
23880
23981
|
}
|
|
23881
23982
|
/**
|
|
23882
23983
|
* 读 sandbox-settings.json 当前内容;文件不存在 / JSON 解析失败均返回 null。
|
|
@@ -23884,23 +23985,23 @@ var PersonaStore = class {
|
|
|
23884
23985
|
*/
|
|
23885
23986
|
readSandboxSettings(personaId) {
|
|
23886
23987
|
const p2 = this.sandboxSettingsPath(personaId);
|
|
23887
|
-
if (!
|
|
23988
|
+
if (!fs7.existsSync(p2)) return null;
|
|
23888
23989
|
try {
|
|
23889
|
-
return JSON.parse(
|
|
23990
|
+
return JSON.parse(fs7.readFileSync(p2, "utf8"));
|
|
23890
23991
|
} catch {
|
|
23891
23992
|
return null;
|
|
23892
23993
|
}
|
|
23893
23994
|
}
|
|
23894
23995
|
/** Persona 私有 skills 目录路径:<personaDir>/.claude/skills */
|
|
23895
23996
|
skillsDir(personaId) {
|
|
23896
|
-
return
|
|
23997
|
+
return path9.join(this.personaDir(personaId), ".claude", "skills");
|
|
23897
23998
|
}
|
|
23898
23999
|
/**
|
|
23899
24000
|
* Claude Code 项目级 settings 路径:`<personaDir>/.claude/settings.json`。
|
|
23900
24001
|
* 这里只读 `enabledPlugins` 字段,由 owner 通过 CC `/plugin` 之类命令维护,daemon 不写。
|
|
23901
24002
|
*/
|
|
23902
24003
|
claudeSettingsPath(personaId) {
|
|
23903
|
-
return
|
|
24004
|
+
return path9.join(this.personaDir(personaId), ".claude", "settings.json");
|
|
23904
24005
|
}
|
|
23905
24006
|
/**
|
|
23906
24007
|
* 读取 persona 的 `.claude/settings.json` 中 `enabledPlugins` map,把 value === true
|
|
@@ -23915,10 +24016,10 @@ var PersonaStore = class {
|
|
|
23915
24016
|
*/
|
|
23916
24017
|
readEnabledPlugins(personaId) {
|
|
23917
24018
|
const p2 = this.claudeSettingsPath(personaId);
|
|
23918
|
-
if (!
|
|
24019
|
+
if (!fs7.existsSync(p2)) return [];
|
|
23919
24020
|
let raw;
|
|
23920
24021
|
try {
|
|
23921
|
-
raw = JSON.parse(
|
|
24022
|
+
raw = JSON.parse(fs7.readFileSync(p2, "utf8"));
|
|
23922
24023
|
} catch {
|
|
23923
24024
|
return [];
|
|
23924
24025
|
}
|
|
@@ -23932,22 +24033,22 @@ var PersonaStore = class {
|
|
|
23932
24033
|
return out;
|
|
23933
24034
|
}
|
|
23934
24035
|
list() {
|
|
23935
|
-
if (!
|
|
23936
|
-
return
|
|
23937
|
-
return
|
|
24036
|
+
if (!fs7.existsSync(this.root)) return [];
|
|
24037
|
+
return fs7.readdirSync(this.root).filter((name) => {
|
|
24038
|
+
return fs7.existsSync(path9.join(this.root, name, ".clawd", "persona.json"));
|
|
23938
24039
|
});
|
|
23939
24040
|
}
|
|
23940
24041
|
remove(personaId) {
|
|
23941
24042
|
const dir = this.personaDir(personaId);
|
|
23942
|
-
if (
|
|
24043
|
+
if (fs7.existsSync(dir)) fs7.rmSync(dir, { recursive: true, force: true });
|
|
23943
24044
|
}
|
|
23944
24045
|
personaDirPath(personaId) {
|
|
23945
24046
|
return this.personaDir(personaId);
|
|
23946
24047
|
}
|
|
23947
24048
|
atomicWrite(file, content) {
|
|
23948
24049
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
23949
|
-
|
|
23950
|
-
|
|
24050
|
+
fs7.writeFileSync(tmp, content, { mode: 384 });
|
|
24051
|
+
fs7.renameSync(tmp, file);
|
|
23951
24052
|
}
|
|
23952
24053
|
};
|
|
23953
24054
|
|
|
@@ -23993,9 +24094,9 @@ var PersonaRegistry = class {
|
|
|
23993
24094
|
var import_node_crypto3 = __toESM(require("crypto"), 1);
|
|
23994
24095
|
|
|
23995
24096
|
// src/skills/scanner.ts
|
|
23996
|
-
var
|
|
24097
|
+
var import_node_fs7 = __toESM(require("fs"), 1);
|
|
23997
24098
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
23998
|
-
var
|
|
24099
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
23999
24100
|
|
|
24000
24101
|
// src/skills/frontmatter.ts
|
|
24001
24102
|
var STRIP_QUOTES = /^["']|["']$/g;
|
|
@@ -24104,7 +24205,7 @@ function parseDescription(content) {
|
|
|
24104
24205
|
}
|
|
24105
24206
|
function isDirLikeSync(p2) {
|
|
24106
24207
|
try {
|
|
24107
|
-
return
|
|
24208
|
+
return import_node_fs7.default.statSync(p2).isDirectory();
|
|
24108
24209
|
} catch {
|
|
24109
24210
|
return false;
|
|
24110
24211
|
}
|
|
@@ -24112,19 +24213,19 @@ function isDirLikeSync(p2) {
|
|
|
24112
24213
|
function scanSkillDir(dir, source, seen, out, pluginName) {
|
|
24113
24214
|
let entries;
|
|
24114
24215
|
try {
|
|
24115
|
-
entries =
|
|
24216
|
+
entries = import_node_fs7.default.readdirSync(dir, { withFileTypes: true });
|
|
24116
24217
|
} catch {
|
|
24117
24218
|
return;
|
|
24118
24219
|
}
|
|
24119
24220
|
for (const ent of entries) {
|
|
24120
|
-
const entryPath =
|
|
24221
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
24121
24222
|
if (!ent.isDirectory() && !(ent.isSymbolicLink() && isDirLikeSync(entryPath))) continue;
|
|
24122
24223
|
let content;
|
|
24123
24224
|
try {
|
|
24124
|
-
content =
|
|
24225
|
+
content = import_node_fs7.default.readFileSync(import_node_path8.default.join(entryPath, "SKILL.md"), "utf8");
|
|
24125
24226
|
} catch {
|
|
24126
24227
|
try {
|
|
24127
|
-
content =
|
|
24228
|
+
content = import_node_fs7.default.readFileSync(import_node_path8.default.join(entryPath, "skill.md"), "utf8");
|
|
24128
24229
|
} catch {
|
|
24129
24230
|
continue;
|
|
24130
24231
|
}
|
|
@@ -24148,26 +24249,26 @@ function listSkillsForDir(dir, source) {
|
|
|
24148
24249
|
function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
24149
24250
|
let entries;
|
|
24150
24251
|
try {
|
|
24151
|
-
entries =
|
|
24252
|
+
entries = import_node_fs7.default.readdirSync(dir, { withFileTypes: true });
|
|
24152
24253
|
} catch {
|
|
24153
24254
|
return;
|
|
24154
24255
|
}
|
|
24155
24256
|
for (const ent of entries) {
|
|
24156
|
-
const entryPath =
|
|
24257
|
+
const entryPath = import_node_path8.default.join(dir, ent.name);
|
|
24157
24258
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync(entryPath)) {
|
|
24158
24259
|
const ns = ent.name;
|
|
24159
24260
|
let subEntries;
|
|
24160
24261
|
try {
|
|
24161
|
-
subEntries =
|
|
24262
|
+
subEntries = import_node_fs7.default.readdirSync(entryPath, { withFileTypes: true });
|
|
24162
24263
|
} catch {
|
|
24163
24264
|
continue;
|
|
24164
24265
|
}
|
|
24165
24266
|
for (const se of subEntries) {
|
|
24166
24267
|
if (!se.name.endsWith(".md")) continue;
|
|
24167
|
-
const sePath =
|
|
24268
|
+
const sePath = import_node_path8.default.join(entryPath, se.name);
|
|
24168
24269
|
let content;
|
|
24169
24270
|
try {
|
|
24170
|
-
content =
|
|
24271
|
+
content = import_node_fs7.default.readFileSync(sePath, "utf8");
|
|
24171
24272
|
} catch {
|
|
24172
24273
|
continue;
|
|
24173
24274
|
}
|
|
@@ -24184,7 +24285,7 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
24184
24285
|
} else if (ent.name.endsWith(".md")) {
|
|
24185
24286
|
let content;
|
|
24186
24287
|
try {
|
|
24187
|
-
content =
|
|
24288
|
+
content = import_node_fs7.default.readFileSync(entryPath, "utf8");
|
|
24188
24289
|
} catch {
|
|
24189
24290
|
continue;
|
|
24190
24291
|
}
|
|
@@ -24200,10 +24301,10 @@ function scanCommandDir(dir, source, seen, out, pluginName) {
|
|
|
24200
24301
|
}
|
|
24201
24302
|
}
|
|
24202
24303
|
function readInstalledPlugins(home) {
|
|
24203
|
-
const file =
|
|
24304
|
+
const file = import_node_path8.default.join(home, ".claude", "plugins", "installed_plugins.json");
|
|
24204
24305
|
let raw;
|
|
24205
24306
|
try {
|
|
24206
|
-
raw =
|
|
24307
|
+
raw = import_node_fs7.default.readFileSync(file, "utf8");
|
|
24207
24308
|
} catch {
|
|
24208
24309
|
return [];
|
|
24209
24310
|
}
|
|
@@ -24251,14 +24352,14 @@ var SkillsScanner = class {
|
|
|
24251
24352
|
});
|
|
24252
24353
|
}
|
|
24253
24354
|
const fsBlock = [];
|
|
24254
|
-
scanSkillDir(
|
|
24255
|
-
scanCommandDir(
|
|
24256
|
-
scanSkillDir(
|
|
24257
|
-
scanCommandDir(
|
|
24355
|
+
scanSkillDir(import_node_path8.default.join(this.home, ".claude", "skills"), "global", seen, fsBlock);
|
|
24356
|
+
scanCommandDir(import_node_path8.default.join(this.home, ".claude", "commands"), "global", seen, fsBlock);
|
|
24357
|
+
scanSkillDir(import_node_path8.default.join(args.cwd, ".claude", "skills"), "project", seen, fsBlock);
|
|
24358
|
+
scanCommandDir(import_node_path8.default.join(args.cwd, ".claude", "commands"), "project", seen, fsBlock);
|
|
24258
24359
|
const plugins = [...readInstalledPlugins(this.home), ...this.extraPluginRoots];
|
|
24259
24360
|
for (const { name, root } of plugins) {
|
|
24260
|
-
scanSkillDir(
|
|
24261
|
-
scanCommandDir(
|
|
24361
|
+
scanSkillDir(import_node_path8.default.join(root, "skills"), "plugin", seen, fsBlock, name);
|
|
24362
|
+
scanCommandDir(import_node_path8.default.join(root, "commands"), "plugin", seen, fsBlock, name);
|
|
24262
24363
|
}
|
|
24263
24364
|
fsBlock.sort((a, b2) => a.name < b2.name ? -1 : a.name > b2.name ? 1 : 0);
|
|
24264
24365
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -24363,8 +24464,8 @@ var PersonaManager = class {
|
|
|
24363
24464
|
};
|
|
24364
24465
|
|
|
24365
24466
|
// src/persona/seed.ts
|
|
24366
|
-
var
|
|
24367
|
-
var
|
|
24467
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
24468
|
+
var path11 = __toESM(require("path"), 1);
|
|
24368
24469
|
var import_node_url = require("url");
|
|
24369
24470
|
var import_meta = {};
|
|
24370
24471
|
var DEFAULT_PERSONAS = [
|
|
@@ -24400,18 +24501,18 @@ var DEFAULT_PERSONAS = [
|
|
|
24400
24501
|
function findDefaultsRoot() {
|
|
24401
24502
|
const candidates = [];
|
|
24402
24503
|
try {
|
|
24403
|
-
const here =
|
|
24404
|
-
candidates.push(
|
|
24405
|
-
candidates.push(
|
|
24504
|
+
const here = path11.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
|
|
24505
|
+
candidates.push(path11.resolve(here, "defaults"));
|
|
24506
|
+
candidates.push(path11.resolve(here, "persona-defaults"));
|
|
24406
24507
|
} catch {
|
|
24407
24508
|
}
|
|
24408
24509
|
if (process.argv[1]) {
|
|
24409
|
-
const argvDir =
|
|
24410
|
-
candidates.push(
|
|
24510
|
+
const argvDir = path11.dirname(process.argv[1]);
|
|
24511
|
+
candidates.push(path11.resolve(argvDir, "persona-defaults"));
|
|
24411
24512
|
}
|
|
24412
24513
|
for (const c of candidates) {
|
|
24413
24514
|
try {
|
|
24414
|
-
if (
|
|
24515
|
+
if (fs9.statSync(c).isDirectory()) return c;
|
|
24415
24516
|
} catch {
|
|
24416
24517
|
}
|
|
24417
24518
|
}
|
|
@@ -24424,8 +24525,8 @@ function seedDefaultPersonas(args) {
|
|
|
24424
24525
|
args.logger.info("persona.seed.skip", { personaId: entry.personaId, reason: "exists" });
|
|
24425
24526
|
continue;
|
|
24426
24527
|
}
|
|
24427
|
-
const bundleDir =
|
|
24428
|
-
if (!
|
|
24528
|
+
const bundleDir = path11.join(args.defaultsRoot, entry.personaId);
|
|
24529
|
+
if (!fs9.existsSync(bundleDir)) {
|
|
24429
24530
|
args.logger.warn("persona.seed.skip", {
|
|
24430
24531
|
personaId: entry.personaId,
|
|
24431
24532
|
reason: "bundle-missing",
|
|
@@ -24433,8 +24534,8 @@ function seedDefaultPersonas(args) {
|
|
|
24433
24534
|
});
|
|
24434
24535
|
continue;
|
|
24435
24536
|
}
|
|
24436
|
-
const claudeMdPath =
|
|
24437
|
-
if (!
|
|
24537
|
+
const claudeMdPath = path11.join(bundleDir, "CLAUDE.md");
|
|
24538
|
+
if (!fs9.existsSync(claudeMdPath)) {
|
|
24438
24539
|
args.logger.warn("persona.seed.skip", {
|
|
24439
24540
|
personaId: entry.personaId,
|
|
24440
24541
|
reason: "no-CLAUDE.md",
|
|
@@ -24442,7 +24543,7 @@ function seedDefaultPersonas(args) {
|
|
|
24442
24543
|
});
|
|
24443
24544
|
continue;
|
|
24444
24545
|
}
|
|
24445
|
-
const personality =
|
|
24546
|
+
const personality = fs9.readFileSync(claudeMdPath, "utf8");
|
|
24446
24547
|
const now = Date.now();
|
|
24447
24548
|
const persona = {
|
|
24448
24549
|
personaId: entry.personaId,
|
|
@@ -24459,14 +24560,14 @@ function seedDefaultPersonas(args) {
|
|
|
24459
24560
|
}
|
|
24460
24561
|
}
|
|
24461
24562
|
function copyBundleExtras(srcDir, dstDir) {
|
|
24462
|
-
for (const entry of
|
|
24563
|
+
for (const entry of fs9.readdirSync(srcDir, { withFileTypes: true })) {
|
|
24463
24564
|
if (entry.name === "CLAUDE.md" || entry.name === ".clawd") continue;
|
|
24464
|
-
const srcPath =
|
|
24465
|
-
const dstPath =
|
|
24565
|
+
const srcPath = path11.join(srcDir, entry.name);
|
|
24566
|
+
const dstPath = path11.join(dstDir, entry.name);
|
|
24466
24567
|
if (entry.isDirectory()) {
|
|
24467
|
-
|
|
24568
|
+
fs9.cpSync(srcPath, dstPath, { recursive: true, dereference: true });
|
|
24468
24569
|
} else if (entry.isFile()) {
|
|
24469
|
-
|
|
24570
|
+
fs9.copyFileSync(srcPath, dstPath);
|
|
24470
24571
|
}
|
|
24471
24572
|
}
|
|
24472
24573
|
}
|
|
@@ -24475,9 +24576,9 @@ function copyBundleExtras(srcDir, dstDir) {
|
|
|
24475
24576
|
init_claude();
|
|
24476
24577
|
|
|
24477
24578
|
// src/tools/claude-tui.ts
|
|
24478
|
-
var
|
|
24579
|
+
var import_node_fs10 = __toESM(require("fs"), 1);
|
|
24479
24580
|
var import_node_os5 = __toESM(require("os"), 1);
|
|
24480
|
-
var
|
|
24581
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
24481
24582
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
24482
24583
|
|
|
24483
24584
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -25197,6 +25298,11 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
25197
25298
|
cwd: ctx.cwd,
|
|
25198
25299
|
toolSessionId: ctx.toolSessionId
|
|
25199
25300
|
});
|
|
25301
|
+
probeEvent("pty.spawn", {
|
|
25302
|
+
tsid: ctx.toolSessionId,
|
|
25303
|
+
isResume: jsonlExistsForCtx(ctx),
|
|
25304
|
+
cwd: ctx.cwd
|
|
25305
|
+
});
|
|
25200
25306
|
const pty = spawnPty({
|
|
25201
25307
|
command: cmd,
|
|
25202
25308
|
args,
|
|
@@ -25238,8 +25344,12 @@ var ClaudeTuiAdapter = class extends ClaudeAdapter {
|
|
|
25238
25344
|
this.tuiOpts.onPtyData(ctx.toolSessionId, data.toString("base64"));
|
|
25239
25345
|
}
|
|
25240
25346
|
void detector.writeBytes(data.toString("utf8"));
|
|
25347
|
+
if (ctx.toolSessionId) {
|
|
25348
|
+
probePtyDataThrottled(ctx.toolSessionId, data.length, data);
|
|
25349
|
+
}
|
|
25241
25350
|
});
|
|
25242
25351
|
ptyChild.on("exit", () => {
|
|
25352
|
+
probeEvent("pty.exit", { tsid: ctx.toolSessionId });
|
|
25243
25353
|
if (ctx.toolSessionId && this.tuiOpts.onPtyUnregister) {
|
|
25244
25354
|
this.tuiOpts.onPtyUnregister(ctx.toolSessionId);
|
|
25245
25355
|
}
|
|
@@ -25312,9 +25422,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
25312
25422
|
function jsonlExistsForCtx(ctx) {
|
|
25313
25423
|
if (!ctx.toolSessionId) return false;
|
|
25314
25424
|
const home = import_node_os5.default.homedir();
|
|
25315
|
-
const file =
|
|
25425
|
+
const file = import_node_path11.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
25316
25426
|
try {
|
|
25317
|
-
return
|
|
25427
|
+
return import_node_fs10.default.statSync(file).isFile();
|
|
25318
25428
|
} catch {
|
|
25319
25429
|
return false;
|
|
25320
25430
|
}
|
|
@@ -25324,23 +25434,23 @@ function jsonlExistsForCtx(ctx) {
|
|
|
25324
25434
|
init_claude_history();
|
|
25325
25435
|
|
|
25326
25436
|
// src/workspace/browser.ts
|
|
25327
|
-
var
|
|
25437
|
+
var import_node_fs11 = __toESM(require("fs"), 1);
|
|
25328
25438
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
25329
|
-
var
|
|
25439
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
25330
25440
|
init_protocol();
|
|
25331
25441
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
25332
25442
|
function resolveInsideCwd(cwd, subpath) {
|
|
25333
|
-
const absCwd =
|
|
25334
|
-
const joined =
|
|
25335
|
-
const rel =
|
|
25336
|
-
if (rel.startsWith("..") ||
|
|
25443
|
+
const absCwd = import_node_path12.default.resolve(cwd);
|
|
25444
|
+
const joined = import_node_path12.default.resolve(absCwd, subpath ?? ".");
|
|
25445
|
+
const rel = import_node_path12.default.relative(absCwd, joined);
|
|
25446
|
+
if (rel.startsWith("..") || import_node_path12.default.isAbsolute(rel)) {
|
|
25337
25447
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
25338
25448
|
}
|
|
25339
25449
|
return joined;
|
|
25340
25450
|
}
|
|
25341
25451
|
function ensureCwd(cwd) {
|
|
25342
25452
|
try {
|
|
25343
|
-
const stat =
|
|
25453
|
+
const stat = import_node_fs11.default.statSync(cwd);
|
|
25344
25454
|
if (!stat.isDirectory()) {
|
|
25345
25455
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
25346
25456
|
}
|
|
@@ -25354,7 +25464,7 @@ var WorkspaceBrowser = class {
|
|
|
25354
25464
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os6.default.homedir();
|
|
25355
25465
|
ensureCwd(cwd);
|
|
25356
25466
|
const full = resolveInsideCwd(cwd, args.path);
|
|
25357
|
-
const dirents =
|
|
25467
|
+
const dirents = import_node_fs11.default.readdirSync(full, { withFileTypes: true });
|
|
25358
25468
|
const entries = [];
|
|
25359
25469
|
for (const d of dirents) {
|
|
25360
25470
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -25364,7 +25474,7 @@ var WorkspaceBrowser = class {
|
|
|
25364
25474
|
mtime: ""
|
|
25365
25475
|
};
|
|
25366
25476
|
try {
|
|
25367
|
-
const st =
|
|
25477
|
+
const st = import_node_fs11.default.statSync(import_node_path12.default.join(full, d.name));
|
|
25368
25478
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
25369
25479
|
if (d.isFile()) entry.size = st.size;
|
|
25370
25480
|
} catch {
|
|
@@ -25380,14 +25490,14 @@ var WorkspaceBrowser = class {
|
|
|
25380
25490
|
read(args) {
|
|
25381
25491
|
ensureCwd(args.cwd);
|
|
25382
25492
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
25383
|
-
const st =
|
|
25493
|
+
const st = import_node_fs11.default.statSync(full);
|
|
25384
25494
|
if (!st.isFile()) {
|
|
25385
25495
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
25386
25496
|
}
|
|
25387
25497
|
if (st.size > MAX_FILE_BYTES) {
|
|
25388
25498
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
25389
25499
|
}
|
|
25390
|
-
const buf =
|
|
25500
|
+
const buf = import_node_fs11.default.readFileSync(full);
|
|
25391
25501
|
const isBinary = buf.includes(0);
|
|
25392
25502
|
if (isBinary) {
|
|
25393
25503
|
return {
|
|
@@ -25409,20 +25519,20 @@ var WorkspaceBrowser = class {
|
|
|
25409
25519
|
};
|
|
25410
25520
|
|
|
25411
25521
|
// src/skills/agents-scanner.ts
|
|
25412
|
-
var
|
|
25522
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
25413
25523
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
25414
|
-
var
|
|
25524
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
25415
25525
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
25416
25526
|
function isDirLikeSync2(p2) {
|
|
25417
25527
|
try {
|
|
25418
|
-
return
|
|
25528
|
+
return import_node_fs12.default.statSync(p2).isDirectory();
|
|
25419
25529
|
} catch {
|
|
25420
25530
|
return false;
|
|
25421
25531
|
}
|
|
25422
25532
|
}
|
|
25423
25533
|
function fileExistsSync(p2) {
|
|
25424
25534
|
try {
|
|
25425
|
-
return
|
|
25535
|
+
return import_node_fs12.default.statSync(p2).isFile();
|
|
25426
25536
|
} catch {
|
|
25427
25537
|
return false;
|
|
25428
25538
|
}
|
|
@@ -25430,7 +25540,7 @@ function fileExistsSync(p2) {
|
|
|
25430
25540
|
function parseAgentFile(filePath) {
|
|
25431
25541
|
let content;
|
|
25432
25542
|
try {
|
|
25433
|
-
content =
|
|
25543
|
+
content = import_node_fs12.default.readFileSync(filePath, "utf8");
|
|
25434
25544
|
} catch {
|
|
25435
25545
|
return {};
|
|
25436
25546
|
}
|
|
@@ -25443,16 +25553,16 @@ function parseAgentFile(filePath) {
|
|
|
25443
25553
|
function scanAgentsDir(dir, source, seen, out) {
|
|
25444
25554
|
let entries;
|
|
25445
25555
|
try {
|
|
25446
|
-
entries =
|
|
25556
|
+
entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
|
|
25447
25557
|
} catch {
|
|
25448
25558
|
return;
|
|
25449
25559
|
}
|
|
25450
25560
|
for (const ent of entries) {
|
|
25451
25561
|
if (!ent.name.endsWith(".md")) continue;
|
|
25452
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
25562
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path13.default.join(dir, ent.name)))) {
|
|
25453
25563
|
continue;
|
|
25454
25564
|
}
|
|
25455
|
-
const filePath =
|
|
25565
|
+
const filePath = import_node_path13.default.join(dir, ent.name);
|
|
25456
25566
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
25457
25567
|
if (seen.has(baseName)) continue;
|
|
25458
25568
|
seen.add(baseName);
|
|
@@ -25470,12 +25580,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
25470
25580
|
function walk(dir, namespaces) {
|
|
25471
25581
|
let entries;
|
|
25472
25582
|
try {
|
|
25473
|
-
entries =
|
|
25583
|
+
entries = import_node_fs12.default.readdirSync(dir, { withFileTypes: true });
|
|
25474
25584
|
} catch {
|
|
25475
25585
|
return;
|
|
25476
25586
|
}
|
|
25477
25587
|
for (const ent of entries) {
|
|
25478
|
-
const childPath =
|
|
25588
|
+
const childPath = import_node_path13.default.join(dir, ent.name);
|
|
25479
25589
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
25480
25590
|
walk(childPath, [...namespaces, ent.name]);
|
|
25481
25591
|
continue;
|
|
@@ -25500,13 +25610,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
25500
25610
|
walk(root, []);
|
|
25501
25611
|
}
|
|
25502
25612
|
function readInstalledPlugins2(home) {
|
|
25503
|
-
const pluginsDir =
|
|
25504
|
-
const v2 =
|
|
25505
|
-
const v1 =
|
|
25613
|
+
const pluginsDir = import_node_path13.default.join(home, ".claude", "plugins");
|
|
25614
|
+
const v2 = import_node_path13.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
25615
|
+
const v1 = import_node_path13.default.join(pluginsDir, "installed_plugins.json");
|
|
25506
25616
|
let raw = null;
|
|
25507
25617
|
for (const candidate of [v2, v1]) {
|
|
25508
25618
|
try {
|
|
25509
|
-
raw =
|
|
25619
|
+
raw = import_node_fs12.default.readFileSync(candidate, "utf8");
|
|
25510
25620
|
break;
|
|
25511
25621
|
} catch {
|
|
25512
25622
|
}
|
|
@@ -25531,19 +25641,19 @@ function readInstalledPlugins2(home) {
|
|
|
25531
25641
|
return out;
|
|
25532
25642
|
}
|
|
25533
25643
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
25534
|
-
let cur =
|
|
25535
|
-
const fsRoot =
|
|
25644
|
+
let cur = import_node_path13.default.resolve(startCwd);
|
|
25645
|
+
const fsRoot = import_node_path13.default.parse(cur).root;
|
|
25536
25646
|
while (true) {
|
|
25537
|
-
scanAgentsDir(
|
|
25647
|
+
scanAgentsDir(import_node_path13.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
25538
25648
|
let hasGit = false;
|
|
25539
25649
|
try {
|
|
25540
|
-
hasGit =
|
|
25650
|
+
hasGit = import_node_fs12.default.existsSync(import_node_path13.default.join(cur, ".git"));
|
|
25541
25651
|
} catch {
|
|
25542
25652
|
}
|
|
25543
25653
|
if (hasGit) return;
|
|
25544
25654
|
if (cur === home) return;
|
|
25545
25655
|
if (cur === fsRoot) return;
|
|
25546
|
-
const parent =
|
|
25656
|
+
const parent = import_node_path13.default.dirname(cur);
|
|
25547
25657
|
if (parent === cur) return;
|
|
25548
25658
|
cur = parent;
|
|
25549
25659
|
}
|
|
@@ -25578,7 +25688,7 @@ var AgentsScanner = class {
|
|
|
25578
25688
|
}
|
|
25579
25689
|
const fsBlock = [];
|
|
25580
25690
|
scanAgentsDir(
|
|
25581
|
-
|
|
25691
|
+
import_node_path13.default.join(this.home, ".claude", "agents"),
|
|
25582
25692
|
"global",
|
|
25583
25693
|
seen,
|
|
25584
25694
|
fsBlock
|
|
@@ -25592,7 +25702,7 @@ var AgentsScanner = class {
|
|
|
25592
25702
|
...this.extraPluginRoots
|
|
25593
25703
|
];
|
|
25594
25704
|
for (const { name, root } of plugins) {
|
|
25595
|
-
const agentsRoot =
|
|
25705
|
+
const agentsRoot = import_node_path13.default.join(root, "agents");
|
|
25596
25706
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
25597
25707
|
}
|
|
25598
25708
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -25600,15 +25710,15 @@ var AgentsScanner = class {
|
|
|
25600
25710
|
};
|
|
25601
25711
|
|
|
25602
25712
|
// src/observer/session-observer.ts
|
|
25603
|
-
var
|
|
25713
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
25604
25714
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
25605
|
-
var
|
|
25715
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
25606
25716
|
init_claude_history();
|
|
25607
25717
|
|
|
25608
25718
|
// src/observer/subagent-meta-observer.ts
|
|
25609
|
-
var
|
|
25719
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
25610
25720
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
25611
|
-
var
|
|
25721
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
25612
25722
|
init_claude_history();
|
|
25613
25723
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
25614
25724
|
var SubagentMetaObserver = class {
|
|
@@ -25621,7 +25731,7 @@ var SubagentMetaObserver = class {
|
|
|
25621
25731
|
watches = /* @__PURE__ */ new Map();
|
|
25622
25732
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
25623
25733
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
25624
|
-
return
|
|
25734
|
+
return import_node_path14.default.join(
|
|
25625
25735
|
this.home,
|
|
25626
25736
|
".claude",
|
|
25627
25737
|
"projects",
|
|
@@ -25651,7 +25761,7 @@ var SubagentMetaObserver = class {
|
|
|
25651
25761
|
attachWatcher(w2) {
|
|
25652
25762
|
if (w2.watcher) return;
|
|
25653
25763
|
try {
|
|
25654
|
-
w2.watcher =
|
|
25764
|
+
w2.watcher = import_node_fs13.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
25655
25765
|
if (!name) return;
|
|
25656
25766
|
const m2 = META_RE.exec(String(name));
|
|
25657
25767
|
if (!m2) return;
|
|
@@ -25663,7 +25773,7 @@ var SubagentMetaObserver = class {
|
|
|
25663
25773
|
scan(w2) {
|
|
25664
25774
|
let entries;
|
|
25665
25775
|
try {
|
|
25666
|
-
entries =
|
|
25776
|
+
entries = import_node_fs13.default.readdirSync(w2.dirPath);
|
|
25667
25777
|
} catch {
|
|
25668
25778
|
return;
|
|
25669
25779
|
}
|
|
@@ -25677,10 +25787,10 @@ var SubagentMetaObserver = class {
|
|
|
25677
25787
|
if (!m2) return;
|
|
25678
25788
|
const agentId = m2[1];
|
|
25679
25789
|
if (w2.emitted.has(agentId)) return;
|
|
25680
|
-
const file =
|
|
25790
|
+
const file = import_node_path14.default.join(w2.dirPath, name);
|
|
25681
25791
|
let raw;
|
|
25682
25792
|
try {
|
|
25683
|
-
raw =
|
|
25793
|
+
raw = import_node_fs13.default.readFileSync(file, "utf8");
|
|
25684
25794
|
} catch {
|
|
25685
25795
|
return;
|
|
25686
25796
|
}
|
|
@@ -25737,14 +25847,14 @@ var SessionObserver = class {
|
|
|
25737
25847
|
metaObserver;
|
|
25738
25848
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
25739
25849
|
if (override) return override;
|
|
25740
|
-
return
|
|
25850
|
+
return import_node_path15.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
25741
25851
|
}
|
|
25742
25852
|
start(args) {
|
|
25743
25853
|
this.stop(args.sessionId);
|
|
25744
25854
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
25745
25855
|
let size = 0;
|
|
25746
25856
|
try {
|
|
25747
|
-
size =
|
|
25857
|
+
size = import_node_fs14.default.statSync(filePath).size;
|
|
25748
25858
|
} catch {
|
|
25749
25859
|
}
|
|
25750
25860
|
const w2 = {
|
|
@@ -25757,10 +25867,10 @@ var SessionObserver = class {
|
|
|
25757
25867
|
adapter: args.adapter
|
|
25758
25868
|
};
|
|
25759
25869
|
try {
|
|
25760
|
-
|
|
25870
|
+
import_node_fs14.default.mkdirSync(import_node_path15.default.dirname(filePath), { recursive: true });
|
|
25761
25871
|
} catch {
|
|
25762
25872
|
}
|
|
25763
|
-
w2.watcher =
|
|
25873
|
+
w2.watcher = import_node_fs14.default.watch(import_node_path15.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
25764
25874
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
25765
25875
|
this.poll(w2);
|
|
25766
25876
|
});
|
|
@@ -25783,7 +25893,7 @@ var SessionObserver = class {
|
|
|
25783
25893
|
// 异常静默吞,不阻塞 watcher 启动
|
|
25784
25894
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
25785
25895
|
try {
|
|
25786
|
-
const raw =
|
|
25896
|
+
const raw = import_node_fs14.default.readFileSync(w2.filePath, "utf8");
|
|
25787
25897
|
if (!raw) return;
|
|
25788
25898
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
25789
25899
|
if (allLines.length === 0) return;
|
|
@@ -25807,7 +25917,7 @@ var SessionObserver = class {
|
|
|
25807
25917
|
poll(w2) {
|
|
25808
25918
|
let size = 0;
|
|
25809
25919
|
try {
|
|
25810
|
-
size =
|
|
25920
|
+
size = import_node_fs14.default.statSync(w2.filePath).size;
|
|
25811
25921
|
} catch {
|
|
25812
25922
|
return;
|
|
25813
25923
|
}
|
|
@@ -25816,11 +25926,11 @@ var SessionObserver = class {
|
|
|
25816
25926
|
w2.buf = "";
|
|
25817
25927
|
}
|
|
25818
25928
|
if (size === w2.lastSize) return;
|
|
25819
|
-
const fd =
|
|
25929
|
+
const fd = import_node_fs14.default.openSync(w2.filePath, "r");
|
|
25820
25930
|
try {
|
|
25821
25931
|
const len = size - w2.lastSize;
|
|
25822
25932
|
const buf = Buffer.alloc(len);
|
|
25823
|
-
|
|
25933
|
+
import_node_fs14.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
25824
25934
|
w2.lastSize = size;
|
|
25825
25935
|
w2.buf += buf.toString("utf8");
|
|
25826
25936
|
let newlineIndex;
|
|
@@ -25834,7 +25944,7 @@ var SessionObserver = class {
|
|
|
25834
25944
|
}
|
|
25835
25945
|
}
|
|
25836
25946
|
} finally {
|
|
25837
|
-
|
|
25947
|
+
import_node_fs14.default.closeSync(fd);
|
|
25838
25948
|
}
|
|
25839
25949
|
}
|
|
25840
25950
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -26494,14 +26604,14 @@ function authenticate(token, deps) {
|
|
|
26494
26604
|
}
|
|
26495
26605
|
|
|
26496
26606
|
// src/permission/capability-store.ts
|
|
26497
|
-
var
|
|
26498
|
-
var
|
|
26607
|
+
var fs17 = __toESM(require("fs"), 1);
|
|
26608
|
+
var path20 = __toESM(require("path"), 1);
|
|
26499
26609
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
26500
26610
|
var FILE_VERSION = 1;
|
|
26501
26611
|
var CapabilityStore = class {
|
|
26502
26612
|
constructor(dataDir) {
|
|
26503
26613
|
this.dataDir = dataDir;
|
|
26504
|
-
|
|
26614
|
+
fs17.mkdirSync(dataDir, { recursive: true });
|
|
26505
26615
|
this.cache = this.readFromDisk();
|
|
26506
26616
|
}
|
|
26507
26617
|
dataDir;
|
|
@@ -26525,13 +26635,13 @@ var CapabilityStore = class {
|
|
|
26525
26635
|
this.flush();
|
|
26526
26636
|
}
|
|
26527
26637
|
filePath() {
|
|
26528
|
-
return
|
|
26638
|
+
return path20.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
26529
26639
|
}
|
|
26530
26640
|
readFromDisk() {
|
|
26531
26641
|
const file = this.filePath();
|
|
26532
26642
|
let raw;
|
|
26533
26643
|
try {
|
|
26534
|
-
raw =
|
|
26644
|
+
raw = fs17.readFileSync(file, "utf8");
|
|
26535
26645
|
} catch (err) {
|
|
26536
26646
|
if (err?.code === "ENOENT") return [];
|
|
26537
26647
|
return [];
|
|
@@ -26559,10 +26669,10 @@ var CapabilityStore = class {
|
|
|
26559
26669
|
}
|
|
26560
26670
|
atomicWrite(file, content) {
|
|
26561
26671
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26562
|
-
|
|
26563
|
-
|
|
26672
|
+
fs17.writeFileSync(tmp, content, { mode: 384 });
|
|
26673
|
+
fs17.renameSync(tmp, file);
|
|
26564
26674
|
try {
|
|
26565
|
-
|
|
26675
|
+
fs17.chmodSync(file, 384);
|
|
26566
26676
|
} catch {
|
|
26567
26677
|
}
|
|
26568
26678
|
}
|
|
@@ -26655,14 +26765,14 @@ var CapabilityManager = class {
|
|
|
26655
26765
|
};
|
|
26656
26766
|
|
|
26657
26767
|
// src/permission/cleanup.ts
|
|
26658
|
-
var
|
|
26768
|
+
var fs18 = __toESM(require("fs"), 1);
|
|
26659
26769
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
26660
26770
|
const removed = [];
|
|
26661
26771
|
for (const g2 of cap.grants) {
|
|
26662
26772
|
if (g2.resource.type !== "persona") continue;
|
|
26663
26773
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
26664
26774
|
try {
|
|
26665
|
-
|
|
26775
|
+
fs18.rmSync(dir, { recursive: true, force: true });
|
|
26666
26776
|
removed.push(dir);
|
|
26667
26777
|
} catch {
|
|
26668
26778
|
}
|
|
@@ -26671,13 +26781,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
26671
26781
|
}
|
|
26672
26782
|
|
|
26673
26783
|
// src/permission/personal-capability.ts
|
|
26674
|
-
var
|
|
26675
|
-
var
|
|
26784
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
26785
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
26676
26786
|
var import_node_crypto4 = __toESM(require("crypto"), 1);
|
|
26677
26787
|
var PERSONAL_CAP_FILE_NAME = "personal-capability.json";
|
|
26678
26788
|
var PERSONAL_CAP_DISPLAY_NAME = "personal";
|
|
26679
26789
|
function personalCapFilePath(dataDir) {
|
|
26680
|
-
return
|
|
26790
|
+
return import_node_path16.default.join(dataDir, PERSONAL_CAP_FILE_NAME);
|
|
26681
26791
|
}
|
|
26682
26792
|
function loadOrCreatePersonalCapability(opts) {
|
|
26683
26793
|
const file = personalCapFilePath(opts.dataDir);
|
|
@@ -26707,7 +26817,7 @@ function loadOrCreatePersonalCapability(opts) {
|
|
|
26707
26817
|
function readFile(file) {
|
|
26708
26818
|
let raw;
|
|
26709
26819
|
try {
|
|
26710
|
-
raw =
|
|
26820
|
+
raw = import_node_fs15.default.readFileSync(file, "utf8");
|
|
26711
26821
|
} catch (err) {
|
|
26712
26822
|
const code = err?.code;
|
|
26713
26823
|
if (code === "ENOENT") return null;
|
|
@@ -26728,10 +26838,10 @@ function readFile(file) {
|
|
|
26728
26838
|
return { token: obj.token, capability: capParsed.data };
|
|
26729
26839
|
}
|
|
26730
26840
|
function writeFile(file, content) {
|
|
26731
|
-
|
|
26732
|
-
|
|
26841
|
+
import_node_fs15.default.mkdirSync(import_node_path16.default.dirname(file), { recursive: true });
|
|
26842
|
+
import_node_fs15.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
26733
26843
|
try {
|
|
26734
|
-
|
|
26844
|
+
import_node_fs15.default.chmodSync(file, 384);
|
|
26735
26845
|
} catch {
|
|
26736
26846
|
}
|
|
26737
26847
|
}
|
|
@@ -26746,13 +26856,13 @@ function sha256Hex2(s) {
|
|
|
26746
26856
|
}
|
|
26747
26857
|
|
|
26748
26858
|
// src/inbox/inbox-store.ts
|
|
26749
|
-
var
|
|
26750
|
-
var
|
|
26859
|
+
var fs20 = __toESM(require("fs"), 1);
|
|
26860
|
+
var path22 = __toESM(require("path"), 1);
|
|
26751
26861
|
var INBOX_SUBDIR = "inbox";
|
|
26752
26862
|
var InboxStore = class {
|
|
26753
26863
|
constructor(dataDir) {
|
|
26754
26864
|
this.dataDir = dataDir;
|
|
26755
|
-
|
|
26865
|
+
fs20.mkdirSync(this.dirPath(), { recursive: true });
|
|
26756
26866
|
}
|
|
26757
26867
|
dataDir;
|
|
26758
26868
|
/**
|
|
@@ -26764,7 +26874,7 @@ var InboxStore = class {
|
|
|
26764
26874
|
const file = this.filePath(peerOwnerId);
|
|
26765
26875
|
let raw;
|
|
26766
26876
|
try {
|
|
26767
|
-
raw =
|
|
26877
|
+
raw = fs20.readFileSync(file, "utf8");
|
|
26768
26878
|
} catch (err) {
|
|
26769
26879
|
if (err?.code === "ENOENT") return [];
|
|
26770
26880
|
return [];
|
|
@@ -26780,7 +26890,7 @@ var InboxStore = class {
|
|
|
26780
26890
|
const dir = this.dirPath();
|
|
26781
26891
|
let entries;
|
|
26782
26892
|
try {
|
|
26783
|
-
entries =
|
|
26893
|
+
entries = fs20.readdirSync(dir);
|
|
26784
26894
|
} catch (err) {
|
|
26785
26895
|
if (err?.code === "ENOENT") return [];
|
|
26786
26896
|
return [];
|
|
@@ -26796,9 +26906,9 @@ var InboxStore = class {
|
|
|
26796
26906
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
26797
26907
|
const file = this.filePath(message.peerOwnerId);
|
|
26798
26908
|
const line = JSON.stringify(message) + "\n";
|
|
26799
|
-
|
|
26909
|
+
fs20.appendFileSync(file, line, { mode: 384 });
|
|
26800
26910
|
try {
|
|
26801
|
-
|
|
26911
|
+
fs20.chmodSync(file, 384);
|
|
26802
26912
|
} catch {
|
|
26803
26913
|
}
|
|
26804
26914
|
}
|
|
@@ -26828,7 +26938,7 @@ var InboxStore = class {
|
|
|
26828
26938
|
removeByPeerOwnerId(peerOwnerId) {
|
|
26829
26939
|
const file = this.filePath(peerOwnerId);
|
|
26830
26940
|
try {
|
|
26831
|
-
|
|
26941
|
+
fs20.unlinkSync(file);
|
|
26832
26942
|
} catch (err) {
|
|
26833
26943
|
if (err?.code === "ENOENT") return;
|
|
26834
26944
|
}
|
|
@@ -26837,18 +26947,18 @@ var InboxStore = class {
|
|
|
26837
26947
|
const file = this.filePath(peerOwnerId);
|
|
26838
26948
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
26839
26949
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
26840
|
-
|
|
26841
|
-
|
|
26950
|
+
fs20.writeFileSync(tmp, content, { mode: 384 });
|
|
26951
|
+
fs20.renameSync(tmp, file);
|
|
26842
26952
|
try {
|
|
26843
|
-
|
|
26953
|
+
fs20.chmodSync(file, 384);
|
|
26844
26954
|
} catch {
|
|
26845
26955
|
}
|
|
26846
26956
|
}
|
|
26847
26957
|
dirPath() {
|
|
26848
|
-
return
|
|
26958
|
+
return path22.join(this.dataDir, INBOX_SUBDIR);
|
|
26849
26959
|
}
|
|
26850
26960
|
filePath(peerOwnerId) {
|
|
26851
|
-
return
|
|
26961
|
+
return path22.join(this.dirPath(), `${peerOwnerId}.jsonl`);
|
|
26852
26962
|
}
|
|
26853
26963
|
};
|
|
26854
26964
|
function parseAllLines(raw) {
|
|
@@ -26935,8 +27045,8 @@ var InboxManager = class {
|
|
|
26935
27045
|
};
|
|
26936
27046
|
|
|
26937
27047
|
// src/state/received-capability-store.ts
|
|
26938
|
-
var
|
|
26939
|
-
var
|
|
27048
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
27049
|
+
var path23 = __toESM(require("path"), 1);
|
|
26940
27050
|
var FILE_NAME = "received-capabilities.json";
|
|
26941
27051
|
var ReceivedCapabilityStore = class {
|
|
26942
27052
|
constructor(dataDir) {
|
|
@@ -26946,10 +27056,10 @@ var ReceivedCapabilityStore = class {
|
|
|
26946
27056
|
caps = /* @__PURE__ */ new Map();
|
|
26947
27057
|
load() {
|
|
26948
27058
|
this.caps.clear();
|
|
26949
|
-
const file =
|
|
27059
|
+
const file = path23.join(this.dataDir, FILE_NAME);
|
|
26950
27060
|
let raw;
|
|
26951
27061
|
try {
|
|
26952
|
-
raw =
|
|
27062
|
+
raw = fs21.readFileSync(file, "utf8");
|
|
26953
27063
|
} catch (err) {
|
|
26954
27064
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
26955
27065
|
return;
|
|
@@ -26986,20 +27096,20 @@ var ReceivedCapabilityStore = class {
|
|
|
26986
27096
|
this.flush();
|
|
26987
27097
|
}
|
|
26988
27098
|
flush() {
|
|
26989
|
-
const file =
|
|
27099
|
+
const file = path23.join(this.dataDir, FILE_NAME);
|
|
26990
27100
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
26991
27101
|
const content = JSON.stringify(
|
|
26992
27102
|
{ receivedCaps: Array.from(this.caps.values()) },
|
|
26993
27103
|
null,
|
|
26994
27104
|
2
|
|
26995
27105
|
);
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
|
|
27106
|
+
fs21.mkdirSync(this.dataDir, { recursive: true });
|
|
27107
|
+
fs21.writeFileSync(tmp, content, { mode: 384 });
|
|
27108
|
+
fs21.renameSync(tmp, file);
|
|
26999
27109
|
}
|
|
27000
27110
|
renameBak(file) {
|
|
27001
27111
|
try {
|
|
27002
|
-
|
|
27112
|
+
fs21.renameSync(file, `${file}.bak`);
|
|
27003
27113
|
} catch {
|
|
27004
27114
|
}
|
|
27005
27115
|
}
|
|
@@ -27097,61 +27207,61 @@ async function connectRemote(args) {
|
|
|
27097
27207
|
}
|
|
27098
27208
|
|
|
27099
27209
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
27100
|
-
var
|
|
27101
|
-
var
|
|
27210
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
27211
|
+
var path24 = __toESM(require("path"), 1);
|
|
27102
27212
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
27103
27213
|
function migrateFlattenSessions(opts) {
|
|
27104
27214
|
const dataDir = opts.dataDir;
|
|
27105
27215
|
const now = opts.now ?? Date.now;
|
|
27106
|
-
const sessionsDir =
|
|
27107
|
-
const flagPath =
|
|
27216
|
+
const sessionsDir = path24.join(dataDir, "sessions");
|
|
27217
|
+
const flagPath = path24.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
27108
27218
|
if (existsSync3(flagPath)) {
|
|
27109
27219
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
27110
27220
|
}
|
|
27111
27221
|
let movedBare = 0;
|
|
27112
27222
|
let movedVmOwner = 0;
|
|
27113
27223
|
let archivedListener = 0;
|
|
27114
|
-
const defaultDir =
|
|
27224
|
+
const defaultDir = path24.join(sessionsDir, "default");
|
|
27115
27225
|
if (existsSync3(defaultDir)) {
|
|
27116
27226
|
for (const entry of readdirSafe(defaultDir)) {
|
|
27117
27227
|
if (!entry.endsWith(".json")) continue;
|
|
27118
|
-
const src =
|
|
27119
|
-
const dst =
|
|
27120
|
-
|
|
27228
|
+
const src = path24.join(defaultDir, entry);
|
|
27229
|
+
const dst = path24.join(sessionsDir, entry);
|
|
27230
|
+
fs22.renameSync(src, dst);
|
|
27121
27231
|
movedBare += 1;
|
|
27122
27232
|
}
|
|
27123
27233
|
rmdirIfEmpty(defaultDir);
|
|
27124
27234
|
}
|
|
27125
27235
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
27126
|
-
const personaDir =
|
|
27236
|
+
const personaDir = path24.join(sessionsDir, pid);
|
|
27127
27237
|
if (!isDir(personaDir)) continue;
|
|
27128
27238
|
if (pid === "default") continue;
|
|
27129
|
-
const ownerSrc =
|
|
27239
|
+
const ownerSrc = path24.join(personaDir, "owner");
|
|
27130
27240
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
27131
|
-
const ownerDst =
|
|
27132
|
-
|
|
27241
|
+
const ownerDst = path24.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
27242
|
+
fs22.mkdirSync(ownerDst, { recursive: true });
|
|
27133
27243
|
for (const file of readdirSafe(ownerSrc)) {
|
|
27134
27244
|
if (!file.endsWith(".json")) continue;
|
|
27135
|
-
|
|
27245
|
+
fs22.renameSync(path24.join(ownerSrc, file), path24.join(ownerDst, file));
|
|
27136
27246
|
movedVmOwner += 1;
|
|
27137
27247
|
}
|
|
27138
27248
|
rmdirIfEmpty(ownerSrc);
|
|
27139
27249
|
}
|
|
27140
|
-
const listenerSrc =
|
|
27250
|
+
const listenerSrc = path24.join(personaDir, "listener");
|
|
27141
27251
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
27142
|
-
const archiveDst =
|
|
27143
|
-
|
|
27252
|
+
const archiveDst = path24.join(dataDir, ".legacy", `listener-${pid}`);
|
|
27253
|
+
fs22.mkdirSync(archiveDst, { recursive: true });
|
|
27144
27254
|
for (const file of readdirSafe(listenerSrc)) {
|
|
27145
27255
|
if (!file.endsWith(".json")) continue;
|
|
27146
|
-
|
|
27256
|
+
fs22.renameSync(path24.join(listenerSrc, file), path24.join(archiveDst, file));
|
|
27147
27257
|
archivedListener += 1;
|
|
27148
27258
|
}
|
|
27149
27259
|
rmdirIfEmpty(listenerSrc);
|
|
27150
27260
|
}
|
|
27151
27261
|
rmdirIfEmpty(personaDir);
|
|
27152
27262
|
}
|
|
27153
|
-
|
|
27154
|
-
|
|
27263
|
+
fs22.mkdirSync(sessionsDir, { recursive: true });
|
|
27264
|
+
fs22.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
27155
27265
|
return {
|
|
27156
27266
|
skipped: false,
|
|
27157
27267
|
flagWritten: true,
|
|
@@ -27162,7 +27272,7 @@ function migrateFlattenSessions(opts) {
|
|
|
27162
27272
|
}
|
|
27163
27273
|
function existsSync3(p2) {
|
|
27164
27274
|
try {
|
|
27165
|
-
|
|
27275
|
+
fs22.statSync(p2);
|
|
27166
27276
|
return true;
|
|
27167
27277
|
} catch {
|
|
27168
27278
|
return false;
|
|
@@ -27170,31 +27280,31 @@ function existsSync3(p2) {
|
|
|
27170
27280
|
}
|
|
27171
27281
|
function isDir(p2) {
|
|
27172
27282
|
try {
|
|
27173
|
-
return
|
|
27283
|
+
return fs22.statSync(p2).isDirectory();
|
|
27174
27284
|
} catch {
|
|
27175
27285
|
return false;
|
|
27176
27286
|
}
|
|
27177
27287
|
}
|
|
27178
27288
|
function readdirSafe(p2) {
|
|
27179
27289
|
try {
|
|
27180
|
-
return
|
|
27290
|
+
return fs22.readdirSync(p2);
|
|
27181
27291
|
} catch {
|
|
27182
27292
|
return [];
|
|
27183
27293
|
}
|
|
27184
27294
|
}
|
|
27185
27295
|
function rmdirIfEmpty(p2) {
|
|
27186
27296
|
try {
|
|
27187
|
-
|
|
27297
|
+
fs22.rmdirSync(p2);
|
|
27188
27298
|
} catch {
|
|
27189
27299
|
}
|
|
27190
27300
|
}
|
|
27191
27301
|
|
|
27192
27302
|
// src/transport/http-router.ts
|
|
27193
|
-
var
|
|
27194
|
-
var
|
|
27303
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
27304
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
27195
27305
|
|
|
27196
27306
|
// src/attachment/mime.ts
|
|
27197
|
-
var
|
|
27307
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
27198
27308
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
27199
27309
|
var EXT_TO_NATIVE_MIME = {
|
|
27200
27310
|
// 图片
|
|
@@ -27301,7 +27411,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
27301
27411
|
".mk"
|
|
27302
27412
|
]);
|
|
27303
27413
|
function lookupMime(filePathOrName) {
|
|
27304
|
-
const ext =
|
|
27414
|
+
const ext = import_node_path17.default.extname(filePathOrName).toLowerCase();
|
|
27305
27415
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
27306
27416
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
27307
27417
|
return "application/octet-stream";
|
|
@@ -27370,8 +27480,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
27370
27480
|
}
|
|
27371
27481
|
|
|
27372
27482
|
// src/attachment/upload.ts
|
|
27373
|
-
var
|
|
27374
|
-
var
|
|
27483
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
27484
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
27375
27485
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
27376
27486
|
var import_promises = require("stream/promises");
|
|
27377
27487
|
var UploadError = class extends Error {
|
|
@@ -27383,22 +27493,22 @@ var UploadError = class extends Error {
|
|
|
27383
27493
|
code;
|
|
27384
27494
|
};
|
|
27385
27495
|
function assertValidFileName(fileName) {
|
|
27386
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
27496
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path18.default.basename(fileName)) {
|
|
27387
27497
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
27388
27498
|
}
|
|
27389
27499
|
}
|
|
27390
27500
|
var HASH_PREFIX_LEN = 16;
|
|
27391
27501
|
async function writeUploadedAttachment(args) {
|
|
27392
27502
|
assertValidFileName(args.fileName);
|
|
27393
|
-
const attachmentsRoot =
|
|
27503
|
+
const attachmentsRoot = import_node_path18.default.join(args.sessionDir, ".attachments");
|
|
27394
27504
|
try {
|
|
27395
|
-
|
|
27505
|
+
import_node_fs16.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
27396
27506
|
} catch (err) {
|
|
27397
27507
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
27398
27508
|
}
|
|
27399
27509
|
const hasher = import_node_crypto6.default.createHash("sha256");
|
|
27400
27510
|
let actualSize = 0;
|
|
27401
|
-
const tmpPath =
|
|
27511
|
+
const tmpPath = import_node_path18.default.join(
|
|
27402
27512
|
attachmentsRoot,
|
|
27403
27513
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto6.default.randomBytes(4).toString("hex")}`
|
|
27404
27514
|
);
|
|
@@ -27413,18 +27523,18 @@ async function writeUploadedAttachment(args) {
|
|
|
27413
27523
|
yield buf;
|
|
27414
27524
|
}
|
|
27415
27525
|
},
|
|
27416
|
-
|
|
27526
|
+
import_node_fs16.default.createWriteStream(tmpPath, { mode: 384 })
|
|
27417
27527
|
);
|
|
27418
27528
|
} catch (err) {
|
|
27419
27529
|
try {
|
|
27420
|
-
|
|
27530
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
27421
27531
|
} catch {
|
|
27422
27532
|
}
|
|
27423
27533
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
27424
27534
|
}
|
|
27425
27535
|
if (actualSize !== args.contentLength) {
|
|
27426
27536
|
try {
|
|
27427
|
-
|
|
27537
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
27428
27538
|
} catch {
|
|
27429
27539
|
}
|
|
27430
27540
|
throw new UploadError(
|
|
@@ -27433,35 +27543,35 @@ async function writeUploadedAttachment(args) {
|
|
|
27433
27543
|
);
|
|
27434
27544
|
}
|
|
27435
27545
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
27436
|
-
const hashDir =
|
|
27546
|
+
const hashDir = import_node_path18.default.join(attachmentsRoot, attachmentId);
|
|
27437
27547
|
let finalFileName;
|
|
27438
27548
|
let hashDirExists = false;
|
|
27439
27549
|
try {
|
|
27440
|
-
hashDirExists =
|
|
27550
|
+
hashDirExists = import_node_fs16.default.statSync(hashDir).isDirectory();
|
|
27441
27551
|
} catch {
|
|
27442
27552
|
}
|
|
27443
27553
|
if (hashDirExists) {
|
|
27444
|
-
const existing =
|
|
27554
|
+
const existing = import_node_fs16.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
27445
27555
|
finalFileName = existing[0] ?? args.fileName;
|
|
27446
27556
|
try {
|
|
27447
|
-
|
|
27557
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
27448
27558
|
} catch {
|
|
27449
27559
|
}
|
|
27450
27560
|
} else {
|
|
27451
27561
|
try {
|
|
27452
|
-
|
|
27562
|
+
import_node_fs16.default.mkdirSync(hashDir, { recursive: true });
|
|
27453
27563
|
finalFileName = args.fileName;
|
|
27454
|
-
|
|
27564
|
+
import_node_fs16.default.renameSync(tmpPath, import_node_path18.default.join(hashDir, finalFileName));
|
|
27455
27565
|
} catch (err) {
|
|
27456
27566
|
try {
|
|
27457
|
-
|
|
27567
|
+
import_node_fs16.default.unlinkSync(tmpPath);
|
|
27458
27568
|
} catch {
|
|
27459
27569
|
}
|
|
27460
27570
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
27461
27571
|
}
|
|
27462
27572
|
}
|
|
27463
|
-
const absPath =
|
|
27464
|
-
const relPath =
|
|
27573
|
+
const absPath = import_node_path18.default.join(hashDir, finalFileName);
|
|
27574
|
+
const relPath = import_node_path18.default.relative(args.sessionDir, absPath);
|
|
27465
27575
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
27466
27576
|
relPath: absPath,
|
|
27467
27577
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -27498,7 +27608,7 @@ function isValidUploadFileName(fileName) {
|
|
|
27498
27608
|
if (fileName === "." || fileName === "..") return false;
|
|
27499
27609
|
if (fileName.startsWith(".")) return false;
|
|
27500
27610
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
27501
|
-
return fileName ===
|
|
27611
|
+
return fileName === import_node_path19.default.basename(fileName);
|
|
27502
27612
|
}
|
|
27503
27613
|
function createHttpRouter(deps) {
|
|
27504
27614
|
return async (req, res) => {
|
|
@@ -27668,7 +27778,7 @@ function createHttpRouter(deps) {
|
|
|
27668
27778
|
return true;
|
|
27669
27779
|
}
|
|
27670
27780
|
let absPath;
|
|
27671
|
-
if (
|
|
27781
|
+
if (import_node_path19.default.isAbsolute(pathParam)) {
|
|
27672
27782
|
absPath = pathParam;
|
|
27673
27783
|
} else if (deps.sessionStore) {
|
|
27674
27784
|
const file = deps.sessionStore.read(sid);
|
|
@@ -27676,7 +27786,7 @@ function createHttpRouter(deps) {
|
|
|
27676
27786
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
27677
27787
|
return true;
|
|
27678
27788
|
}
|
|
27679
|
-
absPath =
|
|
27789
|
+
absPath = import_node_path19.default.join(file.cwd, pathParam);
|
|
27680
27790
|
} else {
|
|
27681
27791
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
27682
27792
|
return true;
|
|
@@ -27709,7 +27819,7 @@ function withCtx(ctx, body) {
|
|
|
27709
27819
|
function streamFile(res, absPath, logger) {
|
|
27710
27820
|
let stat;
|
|
27711
27821
|
try {
|
|
27712
|
-
stat =
|
|
27822
|
+
stat = import_node_fs17.default.statSync(absPath);
|
|
27713
27823
|
} catch (err) {
|
|
27714
27824
|
const code = err?.code;
|
|
27715
27825
|
if (code === "ENOENT") {
|
|
@@ -27724,7 +27834,7 @@ function streamFile(res, absPath, logger) {
|
|
|
27724
27834
|
return;
|
|
27725
27835
|
}
|
|
27726
27836
|
const mime = lookupMime(absPath);
|
|
27727
|
-
const basename =
|
|
27837
|
+
const basename = import_node_path19.default.basename(absPath);
|
|
27728
27838
|
res.writeHead(200, {
|
|
27729
27839
|
"Content-Type": mime,
|
|
27730
27840
|
"Content-Length": String(stat.size),
|
|
@@ -27732,7 +27842,7 @@ function streamFile(res, absPath, logger) {
|
|
|
27732
27842
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
27733
27843
|
"X-Content-Type-Options": "nosniff"
|
|
27734
27844
|
});
|
|
27735
|
-
const stream =
|
|
27845
|
+
const stream = import_node_fs17.default.createReadStream(absPath);
|
|
27736
27846
|
stream.on("error", (err) => {
|
|
27737
27847
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
27738
27848
|
res.destroy();
|
|
@@ -27741,8 +27851,8 @@ function streamFile(res, absPath, logger) {
|
|
|
27741
27851
|
}
|
|
27742
27852
|
|
|
27743
27853
|
// src/attachment/gc.ts
|
|
27744
|
-
var
|
|
27745
|
-
var
|
|
27854
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
27855
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
27746
27856
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
27747
27857
|
function runAttachmentGc(args) {
|
|
27748
27858
|
const now = (args.now ?? Date.now)();
|
|
@@ -27751,38 +27861,38 @@ function runAttachmentGc(args) {
|
|
|
27751
27861
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
27752
27862
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
27753
27863
|
if (entry.stale) continue;
|
|
27754
|
-
if (
|
|
27864
|
+
if (import_node_path20.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
27755
27865
|
}
|
|
27756
27866
|
}
|
|
27757
27867
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
27758
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
27868
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path20.default.join(
|
|
27759
27869
|
args.dataDir,
|
|
27760
27870
|
"sessions",
|
|
27761
27871
|
...scopeSubPath(scope).map(safeFileName),
|
|
27762
27872
|
safeFileName(sessionId)
|
|
27763
27873
|
);
|
|
27764
|
-
const attRoot =
|
|
27874
|
+
const attRoot = import_node_path20.default.join(sessionDir, ".attachments");
|
|
27765
27875
|
let hashDirs;
|
|
27766
27876
|
try {
|
|
27767
|
-
hashDirs =
|
|
27877
|
+
hashDirs = import_node_fs18.default.readdirSync(attRoot);
|
|
27768
27878
|
} catch (err) {
|
|
27769
27879
|
if (err.code === "ENOENT") continue;
|
|
27770
27880
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
27771
27881
|
continue;
|
|
27772
27882
|
}
|
|
27773
27883
|
for (const hashDir of hashDirs) {
|
|
27774
|
-
const hashDirAbs =
|
|
27884
|
+
const hashDirAbs = import_node_path20.default.join(attRoot, hashDir);
|
|
27775
27885
|
let files;
|
|
27776
27886
|
try {
|
|
27777
|
-
files =
|
|
27887
|
+
files = import_node_fs18.default.readdirSync(hashDirAbs);
|
|
27778
27888
|
} catch {
|
|
27779
27889
|
continue;
|
|
27780
27890
|
}
|
|
27781
27891
|
for (const name of files) {
|
|
27782
|
-
const file =
|
|
27892
|
+
const file = import_node_path20.default.join(hashDirAbs, name);
|
|
27783
27893
|
let stat;
|
|
27784
27894
|
try {
|
|
27785
|
-
stat =
|
|
27895
|
+
stat = import_node_fs18.default.statSync(file);
|
|
27786
27896
|
} catch {
|
|
27787
27897
|
continue;
|
|
27788
27898
|
}
|
|
@@ -27791,26 +27901,26 @@ function runAttachmentGc(args) {
|
|
|
27791
27901
|
if (age < ttlMs) continue;
|
|
27792
27902
|
if (liveAbs.has(file)) continue;
|
|
27793
27903
|
try {
|
|
27794
|
-
|
|
27904
|
+
import_node_fs18.default.unlinkSync(file);
|
|
27795
27905
|
} catch (err) {
|
|
27796
27906
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
27797
27907
|
}
|
|
27798
27908
|
}
|
|
27799
27909
|
try {
|
|
27800
|
-
if (
|
|
27910
|
+
if (import_node_fs18.default.readdirSync(hashDirAbs).length === 0) import_node_fs18.default.rmdirSync(hashDirAbs);
|
|
27801
27911
|
} catch {
|
|
27802
27912
|
}
|
|
27803
27913
|
}
|
|
27804
27914
|
try {
|
|
27805
|
-
if (
|
|
27915
|
+
if (import_node_fs18.default.readdirSync(attRoot).length === 0) import_node_fs18.default.rmdirSync(attRoot);
|
|
27806
27916
|
} catch {
|
|
27807
27917
|
}
|
|
27808
27918
|
}
|
|
27809
27919
|
}
|
|
27810
27920
|
|
|
27811
27921
|
// src/attachment/group.ts
|
|
27812
|
-
var
|
|
27813
|
-
var
|
|
27922
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
27923
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
27814
27924
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
27815
27925
|
init_protocol();
|
|
27816
27926
|
var GroupFileStore = class {
|
|
@@ -27822,11 +27932,11 @@ var GroupFileStore = class {
|
|
|
27822
27932
|
this.logger = opts.logger;
|
|
27823
27933
|
}
|
|
27824
27934
|
rootForScope(scope) {
|
|
27825
|
-
return
|
|
27935
|
+
return import_node_path21.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
27826
27936
|
}
|
|
27827
27937
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
27828
27938
|
filePath(scope, sessionId) {
|
|
27829
|
-
return
|
|
27939
|
+
return import_node_path21.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
27830
27940
|
}
|
|
27831
27941
|
cacheKey(scope, sessionId) {
|
|
27832
27942
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -27835,7 +27945,7 @@ var GroupFileStore = class {
|
|
|
27835
27945
|
readFile(scope, sessionId) {
|
|
27836
27946
|
const file = this.filePath(scope, sessionId);
|
|
27837
27947
|
try {
|
|
27838
|
-
const raw =
|
|
27948
|
+
const raw = import_node_fs19.default.readFileSync(file, "utf8");
|
|
27839
27949
|
const parsed = JSON.parse(raw);
|
|
27840
27950
|
if (!Array.isArray(parsed)) {
|
|
27841
27951
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -27861,10 +27971,10 @@ var GroupFileStore = class {
|
|
|
27861
27971
|
}
|
|
27862
27972
|
writeFile(scope, sessionId, entries) {
|
|
27863
27973
|
const file = this.filePath(scope, sessionId);
|
|
27864
|
-
|
|
27974
|
+
import_node_fs19.default.mkdirSync(import_node_path21.default.dirname(file), { recursive: true });
|
|
27865
27975
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
27866
|
-
|
|
27867
|
-
|
|
27976
|
+
import_node_fs19.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
27977
|
+
import_node_fs19.default.renameSync(tmp, file);
|
|
27868
27978
|
}
|
|
27869
27979
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
27870
27980
|
list(scope, sessionId) {
|
|
@@ -27950,10 +28060,10 @@ var GroupFileStore = class {
|
|
|
27950
28060
|
};
|
|
27951
28061
|
|
|
27952
28062
|
// src/discovery/state-file.ts
|
|
27953
|
-
var
|
|
27954
|
-
var
|
|
28063
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
28064
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
27955
28065
|
function defaultStateFilePath(dataDir) {
|
|
27956
|
-
return
|
|
28066
|
+
return import_node_path22.default.join(dataDir, "state.json");
|
|
27957
28067
|
}
|
|
27958
28068
|
function isPidAlive(pid) {
|
|
27959
28069
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -27975,7 +28085,7 @@ var StateFileManager = class {
|
|
|
27975
28085
|
}
|
|
27976
28086
|
read() {
|
|
27977
28087
|
try {
|
|
27978
|
-
const raw =
|
|
28088
|
+
const raw = import_node_fs20.default.readFileSync(this.file, "utf8");
|
|
27979
28089
|
const parsed = JSON.parse(raw);
|
|
27980
28090
|
return parsed;
|
|
27981
28091
|
} catch {
|
|
@@ -27989,34 +28099,34 @@ var StateFileManager = class {
|
|
|
27989
28099
|
return { status: "stale", existing };
|
|
27990
28100
|
}
|
|
27991
28101
|
write(state) {
|
|
27992
|
-
|
|
28102
|
+
import_node_fs20.default.mkdirSync(import_node_path22.default.dirname(this.file), { recursive: true });
|
|
27993
28103
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
27994
|
-
|
|
27995
|
-
|
|
28104
|
+
import_node_fs20.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
28105
|
+
import_node_fs20.default.renameSync(tmp, this.file);
|
|
27996
28106
|
if (process.platform !== "win32") {
|
|
27997
28107
|
try {
|
|
27998
|
-
|
|
28108
|
+
import_node_fs20.default.chmodSync(this.file, 384);
|
|
27999
28109
|
} catch {
|
|
28000
28110
|
}
|
|
28001
28111
|
}
|
|
28002
28112
|
}
|
|
28003
28113
|
delete() {
|
|
28004
28114
|
try {
|
|
28005
|
-
|
|
28115
|
+
import_node_fs20.default.unlinkSync(this.file);
|
|
28006
28116
|
} catch {
|
|
28007
28117
|
}
|
|
28008
28118
|
}
|
|
28009
28119
|
};
|
|
28010
28120
|
|
|
28011
28121
|
// src/tunnel/tunnel-manager.ts
|
|
28012
|
-
var
|
|
28013
|
-
var
|
|
28122
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
28123
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
28014
28124
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
28015
28125
|
var import_node_child_process5 = require("child_process");
|
|
28016
28126
|
|
|
28017
28127
|
// src/tunnel/tunnel-store.ts
|
|
28018
|
-
var
|
|
28019
|
-
var
|
|
28128
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
28129
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
28020
28130
|
var TunnelStore = class {
|
|
28021
28131
|
constructor(filePath) {
|
|
28022
28132
|
this.filePath = filePath;
|
|
@@ -28024,7 +28134,7 @@ var TunnelStore = class {
|
|
|
28024
28134
|
filePath;
|
|
28025
28135
|
async get() {
|
|
28026
28136
|
try {
|
|
28027
|
-
const raw = await
|
|
28137
|
+
const raw = await import_node_fs21.default.promises.readFile(this.filePath, "utf8");
|
|
28028
28138
|
const obj = JSON.parse(raw);
|
|
28029
28139
|
if (!isPersistedTunnel(obj)) return null;
|
|
28030
28140
|
return obj;
|
|
@@ -28035,22 +28145,22 @@ var TunnelStore = class {
|
|
|
28035
28145
|
}
|
|
28036
28146
|
}
|
|
28037
28147
|
async set(v2) {
|
|
28038
|
-
const dir =
|
|
28039
|
-
await
|
|
28148
|
+
const dir = import_node_path23.default.dirname(this.filePath);
|
|
28149
|
+
await import_node_fs21.default.promises.mkdir(dir, { recursive: true });
|
|
28040
28150
|
const data = JSON.stringify(v2, null, 2);
|
|
28041
28151
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
28042
|
-
await
|
|
28152
|
+
await import_node_fs21.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
28043
28153
|
if (process.platform !== "win32") {
|
|
28044
28154
|
try {
|
|
28045
|
-
await
|
|
28155
|
+
await import_node_fs21.default.promises.chmod(tmp, 384);
|
|
28046
28156
|
} catch {
|
|
28047
28157
|
}
|
|
28048
28158
|
}
|
|
28049
|
-
await
|
|
28159
|
+
await import_node_fs21.default.promises.rename(tmp, this.filePath);
|
|
28050
28160
|
}
|
|
28051
28161
|
async clear() {
|
|
28052
28162
|
try {
|
|
28053
|
-
await
|
|
28163
|
+
await import_node_fs21.default.promises.unlink(this.filePath);
|
|
28054
28164
|
} catch (err) {
|
|
28055
28165
|
const code = err?.code;
|
|
28056
28166
|
if (code !== "ENOENT") throw err;
|
|
@@ -28145,9 +28255,9 @@ function escape(v2) {
|
|
|
28145
28255
|
}
|
|
28146
28256
|
|
|
28147
28257
|
// src/tunnel/frpc-binary.ts
|
|
28148
|
-
var
|
|
28258
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
28149
28259
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
28150
|
-
var
|
|
28260
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
28151
28261
|
var import_node_child_process3 = require("child_process");
|
|
28152
28262
|
var import_node_stream2 = require("stream");
|
|
28153
28263
|
var import_promises2 = require("stream/promises");
|
|
@@ -28179,20 +28289,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
28179
28289
|
}
|
|
28180
28290
|
async function ensureFrpcBinary(opts) {
|
|
28181
28291
|
if (opts.override) {
|
|
28182
|
-
if (!
|
|
28292
|
+
if (!import_node_fs22.default.existsSync(opts.override)) {
|
|
28183
28293
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
28184
28294
|
}
|
|
28185
28295
|
return opts.override;
|
|
28186
28296
|
}
|
|
28187
28297
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
28188
28298
|
const platform = opts.platform ?? detectPlatform();
|
|
28189
|
-
const binDir =
|
|
28190
|
-
|
|
28299
|
+
const binDir = import_node_path24.default.join(opts.dataDir, "bin");
|
|
28300
|
+
import_node_fs22.default.mkdirSync(binDir, { recursive: true });
|
|
28191
28301
|
cleanupStaleArtifacts(binDir);
|
|
28192
|
-
const stableBin =
|
|
28193
|
-
if (
|
|
28302
|
+
const stableBin = import_node_path24.default.join(binDir, "frpc");
|
|
28303
|
+
if (import_node_fs22.default.existsSync(stableBin)) return stableBin;
|
|
28194
28304
|
const partialBin = `${stableBin}.partial`;
|
|
28195
|
-
const tarballPath =
|
|
28305
|
+
const tarballPath = import_node_path24.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
28196
28306
|
try {
|
|
28197
28307
|
const url = frpcDownloadUrl(version2, platform);
|
|
28198
28308
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -28201,8 +28311,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
28201
28311
|
} else {
|
|
28202
28312
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
28203
28313
|
}
|
|
28204
|
-
|
|
28205
|
-
|
|
28314
|
+
import_node_fs22.default.chmodSync(partialBin, 493);
|
|
28315
|
+
import_node_fs22.default.renameSync(partialBin, stableBin);
|
|
28206
28316
|
} finally {
|
|
28207
28317
|
safeUnlink(tarballPath);
|
|
28208
28318
|
safeUnlink(partialBin);
|
|
@@ -28212,15 +28322,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
28212
28322
|
function cleanupStaleArtifacts(binDir) {
|
|
28213
28323
|
let entries;
|
|
28214
28324
|
try {
|
|
28215
|
-
entries =
|
|
28325
|
+
entries = import_node_fs22.default.readdirSync(binDir);
|
|
28216
28326
|
} catch {
|
|
28217
28327
|
return;
|
|
28218
28328
|
}
|
|
28219
28329
|
for (const name of entries) {
|
|
28220
28330
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
28221
|
-
const full =
|
|
28331
|
+
const full = import_node_path24.default.join(binDir, name);
|
|
28222
28332
|
try {
|
|
28223
|
-
|
|
28333
|
+
import_node_fs22.default.rmSync(full, { recursive: true, force: true });
|
|
28224
28334
|
} catch {
|
|
28225
28335
|
}
|
|
28226
28336
|
}
|
|
@@ -28228,7 +28338,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
28228
28338
|
}
|
|
28229
28339
|
function safeUnlink(p2) {
|
|
28230
28340
|
try {
|
|
28231
|
-
|
|
28341
|
+
import_node_fs22.default.unlinkSync(p2);
|
|
28232
28342
|
} catch {
|
|
28233
28343
|
}
|
|
28234
28344
|
}
|
|
@@ -28239,13 +28349,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
28239
28349
|
if (!res.ok || !res.body) {
|
|
28240
28350
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
28241
28351
|
}
|
|
28242
|
-
const out =
|
|
28352
|
+
const out = import_node_fs22.default.createWriteStream(dest);
|
|
28243
28353
|
const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
|
|
28244
28354
|
await (0, import_promises2.pipeline)(nodeStream, out);
|
|
28245
28355
|
}
|
|
28246
28356
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
28247
|
-
const work =
|
|
28248
|
-
|
|
28357
|
+
const work = import_node_path24.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
28358
|
+
import_node_fs22.default.mkdirSync(work, { recursive: true });
|
|
28249
28359
|
try {
|
|
28250
28360
|
await new Promise((resolve6, reject) => {
|
|
28251
28361
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -28253,32 +28363,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
28253
28363
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
28254
28364
|
});
|
|
28255
28365
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
28256
|
-
const src =
|
|
28257
|
-
if (!
|
|
28366
|
+
const src = import_node_path24.default.join(work, dirName, "frpc");
|
|
28367
|
+
if (!import_node_fs22.default.existsSync(src)) {
|
|
28258
28368
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
28259
28369
|
}
|
|
28260
|
-
|
|
28370
|
+
import_node_fs22.default.copyFileSync(src, destBin);
|
|
28261
28371
|
} finally {
|
|
28262
|
-
|
|
28372
|
+
import_node_fs22.default.rmSync(work, { recursive: true, force: true });
|
|
28263
28373
|
}
|
|
28264
28374
|
}
|
|
28265
28375
|
|
|
28266
28376
|
// src/tunnel/frpc-process.ts
|
|
28267
|
-
var
|
|
28268
|
-
var
|
|
28377
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
28378
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
28269
28379
|
var import_node_child_process4 = require("child_process");
|
|
28270
28380
|
function frpcPidFilePath(dataDir) {
|
|
28271
|
-
return
|
|
28381
|
+
return import_node_path25.default.join(dataDir, "frpc.pid");
|
|
28272
28382
|
}
|
|
28273
28383
|
function writeFrpcPid(dataDir, pid) {
|
|
28274
28384
|
try {
|
|
28275
|
-
|
|
28385
|
+
import_node_fs23.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
28276
28386
|
} catch {
|
|
28277
28387
|
}
|
|
28278
28388
|
}
|
|
28279
28389
|
function clearFrpcPid(dataDir) {
|
|
28280
28390
|
try {
|
|
28281
|
-
|
|
28391
|
+
import_node_fs23.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
28282
28392
|
} catch {
|
|
28283
28393
|
}
|
|
28284
28394
|
}
|
|
@@ -28294,7 +28404,7 @@ function defaultIsPidAlive(pid) {
|
|
|
28294
28404
|
}
|
|
28295
28405
|
function defaultReadPidFile(file) {
|
|
28296
28406
|
try {
|
|
28297
|
-
return
|
|
28407
|
+
return import_node_fs23.default.readFileSync(file, "utf8");
|
|
28298
28408
|
} catch {
|
|
28299
28409
|
return null;
|
|
28300
28410
|
}
|
|
@@ -28310,7 +28420,7 @@ function defaultSleep(ms) {
|
|
|
28310
28420
|
}
|
|
28311
28421
|
async function killStaleFrpc(deps) {
|
|
28312
28422
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
28313
|
-
const tomlPath =
|
|
28423
|
+
const tomlPath = import_node_path25.default.join(deps.dataDir, "frpc.toml");
|
|
28314
28424
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
28315
28425
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
28316
28426
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -28334,7 +28444,7 @@ async function killStaleFrpc(deps) {
|
|
|
28334
28444
|
}
|
|
28335
28445
|
if (victims.size === 0) {
|
|
28336
28446
|
try {
|
|
28337
|
-
|
|
28447
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
28338
28448
|
} catch {
|
|
28339
28449
|
}
|
|
28340
28450
|
return;
|
|
@@ -28345,7 +28455,7 @@ async function killStaleFrpc(deps) {
|
|
|
28345
28455
|
}
|
|
28346
28456
|
await sleep(deps.reapWaitMs ?? 300);
|
|
28347
28457
|
try {
|
|
28348
|
-
|
|
28458
|
+
import_node_fs23.default.unlinkSync(pidFile);
|
|
28349
28459
|
} catch {
|
|
28350
28460
|
}
|
|
28351
28461
|
}
|
|
@@ -28382,7 +28492,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
28382
28492
|
var TunnelManager = class {
|
|
28383
28493
|
constructor(deps) {
|
|
28384
28494
|
this.deps = deps;
|
|
28385
|
-
this.store = deps.store ?? new TunnelStore(
|
|
28495
|
+
this.store = deps.store ?? new TunnelStore(import_node_path26.default.join(deps.dataDir, "tunnel.json"));
|
|
28386
28496
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
28387
28497
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
28388
28498
|
}
|
|
@@ -28509,7 +28619,7 @@ var TunnelManager = class {
|
|
|
28509
28619
|
dataDir: this.deps.dataDir,
|
|
28510
28620
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
28511
28621
|
});
|
|
28512
|
-
const tomlPath =
|
|
28622
|
+
const tomlPath = import_node_path26.default.join(this.deps.dataDir, "frpc.toml");
|
|
28513
28623
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto8.default.randomBytes(3).toString("hex")}`;
|
|
28514
28624
|
const toml = buildFrpcToml({
|
|
28515
28625
|
serverAddr: t.frpsHost,
|
|
@@ -28520,12 +28630,12 @@ var TunnelManager = class {
|
|
|
28520
28630
|
localPort,
|
|
28521
28631
|
logLevel: "info"
|
|
28522
28632
|
});
|
|
28523
|
-
await
|
|
28633
|
+
await import_node_fs24.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
28524
28634
|
const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
|
|
28525
28635
|
stdio: ["ignore", "pipe", "pipe"]
|
|
28526
28636
|
});
|
|
28527
|
-
const logFilePath =
|
|
28528
|
-
const logStream =
|
|
28637
|
+
const logFilePath = import_node_path26.default.join(this.deps.dataDir, "frpc.log");
|
|
28638
|
+
const logStream = import_node_fs24.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
28529
28639
|
logStream.on("error", () => {
|
|
28530
28640
|
});
|
|
28531
28641
|
const tee = (chunk) => {
|
|
@@ -28618,12 +28728,12 @@ function deriveStableDeviceKey(opts = {}) {
|
|
|
28618
28728
|
}
|
|
28619
28729
|
|
|
28620
28730
|
// src/auth-store.ts
|
|
28621
|
-
var
|
|
28622
|
-
var
|
|
28731
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
28732
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
28623
28733
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
28624
28734
|
var AUTH_FILE_NAME = "auth.json";
|
|
28625
28735
|
function authFilePath(dataDir) {
|
|
28626
|
-
return
|
|
28736
|
+
return import_node_path27.default.join(dataDir, AUTH_FILE_NAME);
|
|
28627
28737
|
}
|
|
28628
28738
|
function loadOrCreateAuthFile(opts) {
|
|
28629
28739
|
const file = authFilePath(opts.dataDir);
|
|
@@ -28655,7 +28765,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
28655
28765
|
}
|
|
28656
28766
|
function readAuthFile(file) {
|
|
28657
28767
|
try {
|
|
28658
|
-
const raw =
|
|
28768
|
+
const raw = import_node_fs25.default.readFileSync(file, "utf8");
|
|
28659
28769
|
const parsed = JSON.parse(raw);
|
|
28660
28770
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
28661
28771
|
return null;
|
|
@@ -28673,25 +28783,25 @@ function readAuthFile(file) {
|
|
|
28673
28783
|
}
|
|
28674
28784
|
}
|
|
28675
28785
|
function writeAuthFile(file, content) {
|
|
28676
|
-
|
|
28677
|
-
|
|
28786
|
+
import_node_fs25.default.mkdirSync(import_node_path27.default.dirname(file), { recursive: true });
|
|
28787
|
+
import_node_fs25.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
28678
28788
|
try {
|
|
28679
|
-
|
|
28789
|
+
import_node_fs25.default.chmodSync(file, 384);
|
|
28680
28790
|
} catch {
|
|
28681
28791
|
}
|
|
28682
28792
|
}
|
|
28683
28793
|
|
|
28684
28794
|
// src/owner-profile.ts
|
|
28685
|
-
var
|
|
28795
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
28686
28796
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
28687
|
-
var
|
|
28797
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
28688
28798
|
var PROFILE_FILENAME = "profile.json";
|
|
28689
28799
|
function loadOwnerDisplayName(dataDir) {
|
|
28690
28800
|
const fallback = import_node_os12.default.userInfo().username;
|
|
28691
|
-
const profilePath =
|
|
28801
|
+
const profilePath = import_node_path28.default.join(dataDir, PROFILE_FILENAME);
|
|
28692
28802
|
let raw;
|
|
28693
28803
|
try {
|
|
28694
|
-
raw =
|
|
28804
|
+
raw = import_node_fs26.default.readFileSync(profilePath, "utf8");
|
|
28695
28805
|
} catch {
|
|
28696
28806
|
return fallback;
|
|
28697
28807
|
}
|
|
@@ -28720,12 +28830,12 @@ init_protocol();
|
|
|
28720
28830
|
init_protocol();
|
|
28721
28831
|
|
|
28722
28832
|
// src/session/fork.ts
|
|
28723
|
-
var
|
|
28833
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
28724
28834
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
28725
|
-
var
|
|
28835
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
28726
28836
|
init_claude_history();
|
|
28727
28837
|
function readJsonlEntries(file) {
|
|
28728
|
-
const raw =
|
|
28838
|
+
const raw = import_node_fs27.default.readFileSync(file, "utf8");
|
|
28729
28839
|
const out = [];
|
|
28730
28840
|
for (const line of raw.split("\n")) {
|
|
28731
28841
|
const t = line.trim();
|
|
@@ -28738,10 +28848,10 @@ function readJsonlEntries(file) {
|
|
|
28738
28848
|
return out;
|
|
28739
28849
|
}
|
|
28740
28850
|
function forkSession(input) {
|
|
28741
|
-
const baseDir = input.baseDir ??
|
|
28742
|
-
const projectDir =
|
|
28743
|
-
const sourceFile =
|
|
28744
|
-
if (!
|
|
28851
|
+
const baseDir = input.baseDir ?? import_node_path29.default.join(import_node_os13.default.homedir(), ".claude");
|
|
28852
|
+
const projectDir = import_node_path29.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
28853
|
+
const sourceFile = import_node_path29.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
28854
|
+
if (!import_node_fs27.default.existsSync(sourceFile)) {
|
|
28745
28855
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
28746
28856
|
}
|
|
28747
28857
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -28771,9 +28881,9 @@ function forkSession(input) {
|
|
|
28771
28881
|
}
|
|
28772
28882
|
forkedLines.push(JSON.stringify(forked));
|
|
28773
28883
|
}
|
|
28774
|
-
const forkedFilePath =
|
|
28775
|
-
|
|
28776
|
-
|
|
28884
|
+
const forkedFilePath = import_node_path29.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
28885
|
+
import_node_fs27.default.mkdirSync(projectDir, { recursive: true });
|
|
28886
|
+
import_node_fs27.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
28777
28887
|
return { forkedToolSessionId, forkedFilePath };
|
|
28778
28888
|
}
|
|
28779
28889
|
|
|
@@ -29129,7 +29239,7 @@ function buildPermissionHandlers(deps) {
|
|
|
29129
29239
|
}
|
|
29130
29240
|
|
|
29131
29241
|
// src/handlers/history.ts
|
|
29132
|
-
var
|
|
29242
|
+
var path39 = __toESM(require("path"), 1);
|
|
29133
29243
|
init_protocol();
|
|
29134
29244
|
|
|
29135
29245
|
// src/session/recent-dirs.ts
|
|
@@ -29147,7 +29257,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
29147
29257
|
}
|
|
29148
29258
|
|
|
29149
29259
|
// src/permission/persona-paths.ts
|
|
29150
|
-
var
|
|
29260
|
+
var path38 = __toESM(require("path"), 1);
|
|
29151
29261
|
function getAllowedPersonaIds(grants, action) {
|
|
29152
29262
|
const ids = /* @__PURE__ */ new Set();
|
|
29153
29263
|
for (const g2 of grants) {
|
|
@@ -29160,26 +29270,26 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
29160
29270
|
return ids;
|
|
29161
29271
|
}
|
|
29162
29272
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read") {
|
|
29163
|
-
const root =
|
|
29164
|
-
const target =
|
|
29165
|
-
const sep3 = root.endsWith(
|
|
29273
|
+
const root = path38.resolve(personaRoot);
|
|
29274
|
+
const target = path38.resolve(absPath);
|
|
29275
|
+
const sep3 = root.endsWith(path38.sep) ? "" : path38.sep;
|
|
29166
29276
|
if (!target.startsWith(root + sep3)) return false;
|
|
29167
|
-
const rel =
|
|
29277
|
+
const rel = path38.relative(root, target);
|
|
29168
29278
|
if (!rel || rel.startsWith("..")) return false;
|
|
29169
|
-
const personaId = rel.split(
|
|
29279
|
+
const personaId = rel.split(path38.sep)[0];
|
|
29170
29280
|
if (!personaId) return false;
|
|
29171
29281
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
29172
29282
|
if (allowed === "*") return true;
|
|
29173
29283
|
return allowed.has(personaId);
|
|
29174
29284
|
}
|
|
29175
29285
|
function personaIdFromPath(absPath, personaRoot) {
|
|
29176
|
-
const root =
|
|
29177
|
-
const target =
|
|
29178
|
-
const sep3 = root.endsWith(
|
|
29286
|
+
const root = path38.resolve(personaRoot);
|
|
29287
|
+
const target = path38.resolve(absPath);
|
|
29288
|
+
const sep3 = root.endsWith(path38.sep) ? "" : path38.sep;
|
|
29179
29289
|
if (!target.startsWith(root + sep3)) return null;
|
|
29180
|
-
const rel =
|
|
29290
|
+
const rel = path38.relative(root, target);
|
|
29181
29291
|
if (!rel || rel.startsWith("..")) return null;
|
|
29182
|
-
const id = rel.split(
|
|
29292
|
+
const id = rel.split(path38.sep)[0];
|
|
29183
29293
|
return id || null;
|
|
29184
29294
|
}
|
|
29185
29295
|
|
|
@@ -29204,7 +29314,7 @@ function buildHistoryHandlers(deps) {
|
|
|
29204
29314
|
if (!pid) return false;
|
|
29205
29315
|
return isGuestPathAllowed(
|
|
29206
29316
|
ctx.grants,
|
|
29207
|
-
|
|
29317
|
+
path39.join(personaRoot, pid),
|
|
29208
29318
|
personaRoot,
|
|
29209
29319
|
"read"
|
|
29210
29320
|
);
|
|
@@ -29215,7 +29325,7 @@ function buildHistoryHandlers(deps) {
|
|
|
29215
29325
|
};
|
|
29216
29326
|
const list = async (frame, _client, ctx) => {
|
|
29217
29327
|
const args = HistoryListArgs.parse(frame);
|
|
29218
|
-
assertGuestPath(ctx,
|
|
29328
|
+
assertGuestPath(ctx, path39.resolve(args.projectPath), personaRoot, "history:list");
|
|
29219
29329
|
const sessions = await history.listSessions(args);
|
|
29220
29330
|
return { response: { type: "history:list", sessions } };
|
|
29221
29331
|
};
|
|
@@ -29247,13 +29357,13 @@ function buildHistoryHandlers(deps) {
|
|
|
29247
29357
|
};
|
|
29248
29358
|
const subagents = async (frame, _client, ctx) => {
|
|
29249
29359
|
const args = HistorySubagentsArgs.parse(frame);
|
|
29250
|
-
assertGuestPath(ctx,
|
|
29360
|
+
assertGuestPath(ctx, path39.resolve(args.cwd), personaRoot, "history:subagents");
|
|
29251
29361
|
const subs = await history.listSubagents(args);
|
|
29252
29362
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
29253
29363
|
};
|
|
29254
29364
|
const subagentRead = async (frame, _client, ctx) => {
|
|
29255
29365
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
29256
|
-
assertGuestPath(ctx,
|
|
29366
|
+
assertGuestPath(ctx, path39.resolve(args.cwd), personaRoot, "history:subagent-read");
|
|
29257
29367
|
const res = await history.readSubagent(args);
|
|
29258
29368
|
return { response: { type: "history:subagent-read", ...res } };
|
|
29259
29369
|
};
|
|
@@ -29261,7 +29371,7 @@ function buildHistoryHandlers(deps) {
|
|
|
29261
29371
|
const dirs = listRecentDirs(store);
|
|
29262
29372
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
29263
29373
|
const filtered = dirs.filter(
|
|
29264
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
29374
|
+
(d) => isGuestPathAllowed(ctx.grants, path39.resolve(d.cwd), personaRoot, "read")
|
|
29265
29375
|
);
|
|
29266
29376
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
29267
29377
|
}
|
|
@@ -29278,7 +29388,7 @@ function buildHistoryHandlers(deps) {
|
|
|
29278
29388
|
}
|
|
29279
29389
|
|
|
29280
29390
|
// src/handlers/workspace.ts
|
|
29281
|
-
var
|
|
29391
|
+
var path40 = __toESM(require("path"), 1);
|
|
29282
29392
|
var os14 = __toESM(require("os"), 1);
|
|
29283
29393
|
init_protocol();
|
|
29284
29394
|
init_protocol();
|
|
@@ -29319,22 +29429,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29319
29429
|
const args = WorkspaceListArgs.parse(frame);
|
|
29320
29430
|
const isGuest = ctx?.principal.kind === "guest";
|
|
29321
29431
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os14.homedir();
|
|
29322
|
-
const resolvedCwd =
|
|
29323
|
-
const target = args.path ?
|
|
29432
|
+
const resolvedCwd = path40.resolve(args.cwd ?? fallbackCwd);
|
|
29433
|
+
const target = args.path ? path40.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
29324
29434
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list");
|
|
29325
29435
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
29326
29436
|
return { response: { type: "workspace:list", ...res } };
|
|
29327
29437
|
};
|
|
29328
29438
|
const read = async (frame, _client, ctx) => {
|
|
29329
29439
|
const args = WorkspaceReadArgs.parse(frame);
|
|
29330
|
-
const target =
|
|
29440
|
+
const target = path40.isAbsolute(args.path) ? path40.resolve(args.path) : path40.resolve(args.cwd, args.path);
|
|
29331
29441
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read");
|
|
29332
29442
|
const res = workspace.read(args);
|
|
29333
29443
|
return { response: { type: "workspace:read", ...res } };
|
|
29334
29444
|
};
|
|
29335
29445
|
const skillsList = async (frame, _client, ctx) => {
|
|
29336
29446
|
const args = SkillsListArgs.parse(frame);
|
|
29337
|
-
const cwdAbs =
|
|
29447
|
+
const cwdAbs = path40.resolve(args.cwd);
|
|
29338
29448
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list");
|
|
29339
29449
|
const list2 = skills.list(args);
|
|
29340
29450
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -29346,7 +29456,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29346
29456
|
};
|
|
29347
29457
|
const agentsList = async (frame, _client, ctx) => {
|
|
29348
29458
|
const args = AgentsListArgs.parse(frame);
|
|
29349
|
-
const cwdAbs =
|
|
29459
|
+
const cwdAbs = path40.resolve(args.cwd);
|
|
29350
29460
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list");
|
|
29351
29461
|
const list2 = agents.list(args);
|
|
29352
29462
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -29365,20 +29475,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
29365
29475
|
}
|
|
29366
29476
|
|
|
29367
29477
|
// src/handlers/git.ts
|
|
29368
|
-
var
|
|
29478
|
+
var path42 = __toESM(require("path"), 1);
|
|
29369
29479
|
init_protocol();
|
|
29370
29480
|
init_protocol();
|
|
29371
29481
|
|
|
29372
29482
|
// src/workspace/git.ts
|
|
29373
29483
|
var import_node_child_process6 = require("child_process");
|
|
29374
|
-
var
|
|
29375
|
-
var
|
|
29484
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
29485
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
29376
29486
|
var import_node_util = require("util");
|
|
29377
29487
|
var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
|
|
29378
29488
|
function normalizePath(p2) {
|
|
29379
|
-
const resolved =
|
|
29489
|
+
const resolved = import_node_path30.default.resolve(p2);
|
|
29380
29490
|
try {
|
|
29381
|
-
return
|
|
29491
|
+
return import_node_fs28.default.realpathSync(resolved);
|
|
29382
29492
|
} catch {
|
|
29383
29493
|
return resolved;
|
|
29384
29494
|
}
|
|
@@ -29451,7 +29561,7 @@ async function listGitBranches(cwd) {
|
|
|
29451
29561
|
// src/handlers/git.ts
|
|
29452
29562
|
function assertGuestCwd(ctx, cwd, personaRoot, method) {
|
|
29453
29563
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
29454
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
29564
|
+
if (!isGuestPathAllowed(ctx.grants, path42.resolve(cwd), personaRoot, "read")) {
|
|
29455
29565
|
throw new ClawdError(
|
|
29456
29566
|
ERROR_CODES.UNAUTHORIZED,
|
|
29457
29567
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -29938,7 +30048,7 @@ function buildPersonaHandlers(deps) {
|
|
|
29938
30048
|
}
|
|
29939
30049
|
|
|
29940
30050
|
// src/handlers/attachment.ts
|
|
29941
|
-
var
|
|
30051
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
29942
30052
|
init_protocol();
|
|
29943
30053
|
init_protocol();
|
|
29944
30054
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -29992,12 +30102,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
29992
30102
|
`session ${args.sessionId} scope unresolved`
|
|
29993
30103
|
);
|
|
29994
30104
|
}
|
|
29995
|
-
const cwdAbs =
|
|
29996
|
-
const candidateAbs =
|
|
30105
|
+
const cwdAbs = import_node_path31.default.resolve(sessionFile.cwd);
|
|
30106
|
+
const candidateAbs = import_node_path31.default.isAbsolute(args.relPath) ? import_node_path31.default.resolve(args.relPath) : import_node_path31.default.resolve(cwdAbs, args.relPath);
|
|
29997
30107
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl");
|
|
29998
30108
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
29999
30109
|
const entry = entries.find((e) => {
|
|
30000
|
-
const storedAbs =
|
|
30110
|
+
const storedAbs = import_node_path31.default.isAbsolute(e.relPath) ? import_node_path31.default.resolve(e.relPath) : import_node_path31.default.resolve(cwdAbs, e.relPath);
|
|
30001
30111
|
return storedAbs === candidateAbs && !e.stale;
|
|
30002
30112
|
});
|
|
30003
30113
|
if (!entry) {
|
|
@@ -30021,7 +30131,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
30021
30131
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
30022
30132
|
const f = deps.sessionStore.read(sessionId);
|
|
30023
30133
|
if (!f) return;
|
|
30024
|
-
assertGuestAttachmentPath(ctx,
|
|
30134
|
+
assertGuestAttachmentPath(ctx, import_node_path31.default.resolve(f.cwd), deps.personaRoot, method);
|
|
30025
30135
|
}
|
|
30026
30136
|
const groupAdd = async (frame, _client, ctx) => {
|
|
30027
30137
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -30263,7 +30373,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
30263
30373
|
async function startDaemon(config) {
|
|
30264
30374
|
const logger = createLogger({
|
|
30265
30375
|
level: config.logLevel,
|
|
30266
|
-
file:
|
|
30376
|
+
file: import_node_path32.default.join(config.dataDir, "clawd.log")
|
|
30267
30377
|
});
|
|
30268
30378
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
30269
30379
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -30350,7 +30460,7 @@ async function startDaemon(config) {
|
|
|
30350
30460
|
const agents = new AgentsScanner();
|
|
30351
30461
|
const history = new ClaudeHistoryReader();
|
|
30352
30462
|
let transport = null;
|
|
30353
|
-
const personaStore = new PersonaStore(
|
|
30463
|
+
const personaStore = new PersonaStore(import_node_path32.default.join(config.dataDir, "personas"));
|
|
30354
30464
|
const defaultsRoot = findDefaultsRoot();
|
|
30355
30465
|
if (defaultsRoot) {
|
|
30356
30466
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -30367,7 +30477,7 @@ async function startDaemon(config) {
|
|
|
30367
30477
|
getAdapter,
|
|
30368
30478
|
historyReader: history,
|
|
30369
30479
|
dataDir: config.dataDir,
|
|
30370
|
-
personaRoot:
|
|
30480
|
+
personaRoot: import_node_path32.default.join(config.dataDir, "personas"),
|
|
30371
30481
|
personaStore,
|
|
30372
30482
|
ownerDisplayName,
|
|
30373
30483
|
ownerPrincipalId,
|
|
@@ -30391,10 +30501,10 @@ async function startDaemon(config) {
|
|
|
30391
30501
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
30392
30502
|
attachmentGroup: {
|
|
30393
30503
|
onFileEdit: (input) => {
|
|
30394
|
-
const absPath =
|
|
30504
|
+
const absPath = import_node_path32.default.isAbsolute(input.relPath) ? input.relPath : import_node_path32.default.join(input.cwd, input.relPath);
|
|
30395
30505
|
let size = 0;
|
|
30396
30506
|
try {
|
|
30397
|
-
size =
|
|
30507
|
+
size = import_node_fs29.default.statSync(absPath).size;
|
|
30398
30508
|
} catch (err) {
|
|
30399
30509
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
30400
30510
|
sessionId: input.sessionId,
|
|
@@ -30512,10 +30622,10 @@ async function startDaemon(config) {
|
|
|
30512
30622
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
30513
30623
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
30514
30624
|
// guest path guard:candidate 必须在 personaRoot 子树下
|
|
30515
|
-
personaRoot:
|
|
30625
|
+
personaRoot: import_node_path32.default.join(config.dataDir, "personas")
|
|
30516
30626
|
},
|
|
30517
30627
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
30518
|
-
personaRoot:
|
|
30628
|
+
personaRoot: import_node_path32.default.join(config.dataDir, "personas"),
|
|
30519
30629
|
// capability:list / delete handler 依赖
|
|
30520
30630
|
capabilityManager,
|
|
30521
30631
|
// personal-cap:get 返回的 shareBaseUrl 用此 base URL:
|
|
@@ -30608,6 +30718,7 @@ async function startDaemon(config) {
|
|
|
30608
30718
|
// 形状与 reducer permission_request 分支构造的 session:question 帧一致;UI 不区分
|
|
30609
30719
|
// 首播 vs 重放(last-write-wins,详见 protocol/events.ts JSDoc)。
|
|
30610
30720
|
onSubscribe: (client, sessionId) => {
|
|
30721
|
+
probeEvent("subscribe", { sid: sessionId });
|
|
30611
30722
|
const runner = manager.getActive(sessionId);
|
|
30612
30723
|
if (!runner) return;
|
|
30613
30724
|
const pendingQuestions = runner.getState().pendingQuestions ?? {};
|
|
@@ -30728,8 +30839,8 @@ async function startDaemon(config) {
|
|
|
30728
30839
|
const lines = [
|
|
30729
30840
|
`Tunnel: ${r.url}`,
|
|
30730
30841
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
30731
|
-
`Frpc config: ${
|
|
30732
|
-
`Frpc log: ${
|
|
30842
|
+
`Frpc config: ${import_node_path32.default.join(config.dataDir, "frpc.toml")}`,
|
|
30843
|
+
`Frpc log: ${import_node_path32.default.join(config.dataDir, "frpc.log")}`
|
|
30733
30844
|
];
|
|
30734
30845
|
const width = Math.max(...lines.map((l) => l.length));
|
|
30735
30846
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -30742,8 +30853,8 @@ ${bar}
|
|
|
30742
30853
|
|
|
30743
30854
|
`);
|
|
30744
30855
|
try {
|
|
30745
|
-
const connectPath =
|
|
30746
|
-
|
|
30856
|
+
const connectPath = import_node_path32.default.join(config.dataDir, "connect.txt");
|
|
30857
|
+
import_node_fs29.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
30747
30858
|
} catch {
|
|
30748
30859
|
}
|
|
30749
30860
|
} catch (err) {
|
|
@@ -30808,9 +30919,9 @@ ${bar}
|
|
|
30808
30919
|
};
|
|
30809
30920
|
}
|
|
30810
30921
|
function migrateDropPersonsDir(dataDir) {
|
|
30811
|
-
const dir =
|
|
30922
|
+
const dir = import_node_path32.default.join(dataDir, "persons");
|
|
30812
30923
|
try {
|
|
30813
|
-
|
|
30924
|
+
import_node_fs29.default.rmSync(dir, { recursive: true, force: true });
|
|
30814
30925
|
} catch {
|
|
30815
30926
|
}
|
|
30816
30927
|
}
|