@clawos-dev/clawd 0.2.153-beta.322.6a8336d → 0.2.154-beta.324.8c794f9
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 +639 -524
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -720,8 +720,8 @@ var init_parseUtil = __esm({
|
|
|
720
720
|
init_errors2();
|
|
721
721
|
init_en();
|
|
722
722
|
makeIssue = (params) => {
|
|
723
|
-
const { data, path:
|
|
724
|
-
const fullPath = [...
|
|
723
|
+
const { data, path: path60, errorMaps, issueData } = params;
|
|
724
|
+
const fullPath = [...path60, ...issueData.path || []];
|
|
725
725
|
const fullIssue = {
|
|
726
726
|
...issueData,
|
|
727
727
|
path: fullPath
|
|
@@ -1032,11 +1032,11 @@ var init_types = __esm({
|
|
|
1032
1032
|
init_parseUtil();
|
|
1033
1033
|
init_util();
|
|
1034
1034
|
ParseInputLazyPath = class {
|
|
1035
|
-
constructor(parent, value,
|
|
1035
|
+
constructor(parent, value, path60, key) {
|
|
1036
1036
|
this._cachedPath = [];
|
|
1037
1037
|
this.parent = parent;
|
|
1038
1038
|
this.data = value;
|
|
1039
|
-
this._path =
|
|
1039
|
+
this._path = path60;
|
|
1040
1040
|
this._key = key;
|
|
1041
1041
|
}
|
|
1042
1042
|
get path() {
|
|
@@ -4451,7 +4451,11 @@ var init_attachment_schemas = __esm({
|
|
|
4451
4451
|
/** 相对 session.cwd 的路径;允许传绝对路径,daemon 端会归一化(必须在 cwd 内) */
|
|
4452
4452
|
relPath: external_exports.string().min(1),
|
|
4453
4453
|
/** TTL 秒数;缺省 24h;null 走永久 URL(不带 exp 字段) */
|
|
4454
|
-
ttlSeconds: external_exports.number().int().positive().nullable().optional()
|
|
4454
|
+
ttlSeconds: external_exports.number().int().positive().nullable().optional(),
|
|
4455
|
+
/** 视图模式:缺省 'raw' 返 /files/... 裸文件 URL;'md-rendered' 返
|
|
4456
|
+
* /share/md/... viewer URL(同一签名,daemon 端换前缀),外人浏览器打开就是
|
|
4457
|
+
* drawer 同款 ReactMarkdown 渲染。FilesDrawer 等不关心渲染的 caller 不传。 */
|
|
4458
|
+
view: external_exports.enum(["raw", "md-rendered"]).optional()
|
|
4455
4459
|
});
|
|
4456
4460
|
AttachmentSignUrlResponseSchema = external_exports.object({
|
|
4457
4461
|
/** 完整 URL(含 httpBaseUrl 前缀),UI 直接 window.open / 复制到剪贴板 */
|
|
@@ -6286,8 +6290,8 @@ var require_req = __commonJS({
|
|
|
6286
6290
|
if (req.originalUrl) {
|
|
6287
6291
|
_req.url = req.originalUrl;
|
|
6288
6292
|
} else {
|
|
6289
|
-
const
|
|
6290
|
-
_req.url = typeof
|
|
6293
|
+
const path60 = req.path;
|
|
6294
|
+
_req.url = typeof path60 === "string" ? path60 : req.url ? req.url.path || req.url : void 0;
|
|
6291
6295
|
}
|
|
6292
6296
|
if (req.query) {
|
|
6293
6297
|
_req.query = req.query;
|
|
@@ -6452,14 +6456,14 @@ var require_redact = __commonJS({
|
|
|
6452
6456
|
}
|
|
6453
6457
|
return obj;
|
|
6454
6458
|
}
|
|
6455
|
-
function parsePath(
|
|
6459
|
+
function parsePath(path60) {
|
|
6456
6460
|
const parts = [];
|
|
6457
6461
|
let current = "";
|
|
6458
6462
|
let inBrackets = false;
|
|
6459
6463
|
let inQuotes = false;
|
|
6460
6464
|
let quoteChar = "";
|
|
6461
|
-
for (let i = 0; i <
|
|
6462
|
-
const char =
|
|
6465
|
+
for (let i = 0; i < path60.length; i++) {
|
|
6466
|
+
const char = path60[i];
|
|
6463
6467
|
if (!inBrackets && char === ".") {
|
|
6464
6468
|
if (current) {
|
|
6465
6469
|
parts.push(current);
|
|
@@ -6590,10 +6594,10 @@ var require_redact = __commonJS({
|
|
|
6590
6594
|
return current;
|
|
6591
6595
|
}
|
|
6592
6596
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6593
|
-
for (const
|
|
6594
|
-
const parts = parsePath(
|
|
6597
|
+
for (const path60 of paths) {
|
|
6598
|
+
const parts = parsePath(path60);
|
|
6595
6599
|
if (parts.includes("*")) {
|
|
6596
|
-
redactWildcardPath(obj, parts, censor,
|
|
6600
|
+
redactWildcardPath(obj, parts, censor, path60, remove);
|
|
6597
6601
|
} else {
|
|
6598
6602
|
if (remove) {
|
|
6599
6603
|
removeKey(obj, parts);
|
|
@@ -6678,8 +6682,8 @@ var require_redact = __commonJS({
|
|
|
6678
6682
|
}
|
|
6679
6683
|
} else {
|
|
6680
6684
|
if (afterWildcard.includes("*")) {
|
|
6681
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6682
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6685
|
+
const wrappedCensor = typeof censor === "function" ? (value, path60) => {
|
|
6686
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path60];
|
|
6683
6687
|
return censor(value, fullPath);
|
|
6684
6688
|
} : censor;
|
|
6685
6689
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6714,8 +6718,8 @@ var require_redact = __commonJS({
|
|
|
6714
6718
|
return null;
|
|
6715
6719
|
}
|
|
6716
6720
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6717
|
-
for (const
|
|
6718
|
-
const parts = parsePath(
|
|
6721
|
+
for (const path60 of pathsToClone) {
|
|
6722
|
+
const parts = parsePath(path60);
|
|
6719
6723
|
let current = pathStructure;
|
|
6720
6724
|
for (let i = 0; i < parts.length; i++) {
|
|
6721
6725
|
const part = parts[i];
|
|
@@ -6767,24 +6771,24 @@ var require_redact = __commonJS({
|
|
|
6767
6771
|
}
|
|
6768
6772
|
return cloneSelectively(obj, pathStructure);
|
|
6769
6773
|
}
|
|
6770
|
-
function validatePath(
|
|
6771
|
-
if (typeof
|
|
6774
|
+
function validatePath(path60) {
|
|
6775
|
+
if (typeof path60 !== "string") {
|
|
6772
6776
|
throw new Error("Paths must be (non-empty) strings");
|
|
6773
6777
|
}
|
|
6774
|
-
if (
|
|
6778
|
+
if (path60 === "") {
|
|
6775
6779
|
throw new Error("Invalid redaction path ()");
|
|
6776
6780
|
}
|
|
6777
|
-
if (
|
|
6778
|
-
throw new Error(`Invalid redaction path (${
|
|
6781
|
+
if (path60.includes("..")) {
|
|
6782
|
+
throw new Error(`Invalid redaction path (${path60})`);
|
|
6779
6783
|
}
|
|
6780
|
-
if (
|
|
6781
|
-
throw new Error(`Invalid redaction path (${
|
|
6784
|
+
if (path60.includes(",")) {
|
|
6785
|
+
throw new Error(`Invalid redaction path (${path60})`);
|
|
6782
6786
|
}
|
|
6783
6787
|
let bracketCount = 0;
|
|
6784
6788
|
let inQuotes = false;
|
|
6785
6789
|
let quoteChar = "";
|
|
6786
|
-
for (let i = 0; i <
|
|
6787
|
-
const char =
|
|
6790
|
+
for (let i = 0; i < path60.length; i++) {
|
|
6791
|
+
const char = path60[i];
|
|
6788
6792
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6789
6793
|
if (!inQuotes) {
|
|
6790
6794
|
inQuotes = true;
|
|
@@ -6798,20 +6802,20 @@ var require_redact = __commonJS({
|
|
|
6798
6802
|
} else if (char === "]" && !inQuotes) {
|
|
6799
6803
|
bracketCount--;
|
|
6800
6804
|
if (bracketCount < 0) {
|
|
6801
|
-
throw new Error(`Invalid redaction path (${
|
|
6805
|
+
throw new Error(`Invalid redaction path (${path60})`);
|
|
6802
6806
|
}
|
|
6803
6807
|
}
|
|
6804
6808
|
}
|
|
6805
6809
|
if (bracketCount !== 0) {
|
|
6806
|
-
throw new Error(`Invalid redaction path (${
|
|
6810
|
+
throw new Error(`Invalid redaction path (${path60})`);
|
|
6807
6811
|
}
|
|
6808
6812
|
}
|
|
6809
6813
|
function validatePaths(paths) {
|
|
6810
6814
|
if (!Array.isArray(paths)) {
|
|
6811
6815
|
throw new TypeError("paths must be an array");
|
|
6812
6816
|
}
|
|
6813
|
-
for (const
|
|
6814
|
-
validatePath(
|
|
6817
|
+
for (const path60 of paths) {
|
|
6818
|
+
validatePath(path60);
|
|
6815
6819
|
}
|
|
6816
6820
|
}
|
|
6817
6821
|
function slowRedact(options = {}) {
|
|
@@ -6979,8 +6983,8 @@ var require_redaction = __commonJS({
|
|
|
6979
6983
|
if (shape[k2] === null) {
|
|
6980
6984
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6981
6985
|
} else {
|
|
6982
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6983
|
-
return censor(value, [k2, ...
|
|
6986
|
+
const wrappedCensor = typeof censor === "function" ? (value, path60) => {
|
|
6987
|
+
return censor(value, [k2, ...path60]);
|
|
6984
6988
|
} : censor;
|
|
6985
6989
|
o[k2] = Redact({
|
|
6986
6990
|
paths: shape[k2],
|
|
@@ -7198,10 +7202,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
7198
7202
|
var require_sonic_boom = __commonJS({
|
|
7199
7203
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7200
7204
|
"use strict";
|
|
7201
|
-
var
|
|
7205
|
+
var fs54 = require("fs");
|
|
7202
7206
|
var EventEmitter3 = require("events");
|
|
7203
7207
|
var inherits = require("util").inherits;
|
|
7204
|
-
var
|
|
7208
|
+
var path60 = require("path");
|
|
7205
7209
|
var sleep2 = require_atomic_sleep();
|
|
7206
7210
|
var assert = require("assert");
|
|
7207
7211
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -7255,20 +7259,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7255
7259
|
const mode = sonic.mode;
|
|
7256
7260
|
if (sonic.sync) {
|
|
7257
7261
|
try {
|
|
7258
|
-
if (sonic.mkdir)
|
|
7259
|
-
const fd =
|
|
7262
|
+
if (sonic.mkdir) fs54.mkdirSync(path60.dirname(file), { recursive: true });
|
|
7263
|
+
const fd = fs54.openSync(file, flags, mode);
|
|
7260
7264
|
fileOpened(null, fd);
|
|
7261
7265
|
} catch (err) {
|
|
7262
7266
|
fileOpened(err);
|
|
7263
7267
|
throw err;
|
|
7264
7268
|
}
|
|
7265
7269
|
} else if (sonic.mkdir) {
|
|
7266
|
-
|
|
7270
|
+
fs54.mkdir(path60.dirname(file), { recursive: true }, (err) => {
|
|
7267
7271
|
if (err) return fileOpened(err);
|
|
7268
|
-
|
|
7272
|
+
fs54.open(file, flags, mode, fileOpened);
|
|
7269
7273
|
});
|
|
7270
7274
|
} else {
|
|
7271
|
-
|
|
7275
|
+
fs54.open(file, flags, mode, fileOpened);
|
|
7272
7276
|
}
|
|
7273
7277
|
}
|
|
7274
7278
|
function SonicBoom(opts) {
|
|
@@ -7309,8 +7313,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7309
7313
|
this.flush = flushBuffer;
|
|
7310
7314
|
this.flushSync = flushBufferSync;
|
|
7311
7315
|
this._actualWrite = actualWriteBuffer;
|
|
7312
|
-
fsWriteSync = () =>
|
|
7313
|
-
fsWrite = () =>
|
|
7316
|
+
fsWriteSync = () => fs54.writeSync(this.fd, this._writingBuf);
|
|
7317
|
+
fsWrite = () => fs54.write(this.fd, this._writingBuf, this.release);
|
|
7314
7318
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7315
7319
|
this._writingBuf = "";
|
|
7316
7320
|
this.write = write;
|
|
@@ -7319,15 +7323,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7319
7323
|
this._actualWrite = actualWrite;
|
|
7320
7324
|
fsWriteSync = () => {
|
|
7321
7325
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7322
|
-
return
|
|
7326
|
+
return fs54.writeSync(this.fd, this._writingBuf);
|
|
7323
7327
|
}
|
|
7324
|
-
return
|
|
7328
|
+
return fs54.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7325
7329
|
};
|
|
7326
7330
|
fsWrite = () => {
|
|
7327
7331
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7328
|
-
return
|
|
7332
|
+
return fs54.write(this.fd, this._writingBuf, this.release);
|
|
7329
7333
|
}
|
|
7330
|
-
return
|
|
7334
|
+
return fs54.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7331
7335
|
};
|
|
7332
7336
|
} else {
|
|
7333
7337
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7384,7 +7388,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7384
7388
|
}
|
|
7385
7389
|
}
|
|
7386
7390
|
if (this._fsync) {
|
|
7387
|
-
|
|
7391
|
+
fs54.fsyncSync(this.fd);
|
|
7388
7392
|
}
|
|
7389
7393
|
const len = this._len;
|
|
7390
7394
|
if (this._reopening) {
|
|
@@ -7498,7 +7502,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7498
7502
|
const onDrain = () => {
|
|
7499
7503
|
if (!this._fsync) {
|
|
7500
7504
|
try {
|
|
7501
|
-
|
|
7505
|
+
fs54.fsync(this.fd, (err) => {
|
|
7502
7506
|
this._flushPending = false;
|
|
7503
7507
|
cb(err);
|
|
7504
7508
|
});
|
|
@@ -7600,7 +7604,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7600
7604
|
const fd = this.fd;
|
|
7601
7605
|
this.once("ready", () => {
|
|
7602
7606
|
if (fd !== this.fd) {
|
|
7603
|
-
|
|
7607
|
+
fs54.close(fd, (err) => {
|
|
7604
7608
|
if (err) {
|
|
7605
7609
|
return this.emit("error", err);
|
|
7606
7610
|
}
|
|
@@ -7649,7 +7653,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7649
7653
|
buf = this._bufs[0];
|
|
7650
7654
|
}
|
|
7651
7655
|
try {
|
|
7652
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7656
|
+
const n = Buffer.isBuffer(buf) ? fs54.writeSync(this.fd, buf) : fs54.writeSync(this.fd, buf, "utf8");
|
|
7653
7657
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7654
7658
|
buf = releasedBufObj.writingBuf;
|
|
7655
7659
|
this._len = releasedBufObj.len;
|
|
@@ -7665,7 +7669,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7665
7669
|
}
|
|
7666
7670
|
}
|
|
7667
7671
|
try {
|
|
7668
|
-
|
|
7672
|
+
fs54.fsyncSync(this.fd);
|
|
7669
7673
|
} catch {
|
|
7670
7674
|
}
|
|
7671
7675
|
}
|
|
@@ -7686,7 +7690,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7686
7690
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7687
7691
|
}
|
|
7688
7692
|
try {
|
|
7689
|
-
const n =
|
|
7693
|
+
const n = fs54.writeSync(this.fd, buf);
|
|
7690
7694
|
buf = buf.subarray(n);
|
|
7691
7695
|
this._len = Math.max(this._len - n, 0);
|
|
7692
7696
|
if (buf.length <= 0) {
|
|
@@ -7714,13 +7718,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7714
7718
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7715
7719
|
if (this.sync) {
|
|
7716
7720
|
try {
|
|
7717
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7721
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs54.writeSync(this.fd, this._writingBuf) : fs54.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7718
7722
|
release(null, written);
|
|
7719
7723
|
} catch (err) {
|
|
7720
7724
|
release(err);
|
|
7721
7725
|
}
|
|
7722
7726
|
} else {
|
|
7723
|
-
|
|
7727
|
+
fs54.write(this.fd, this._writingBuf, release);
|
|
7724
7728
|
}
|
|
7725
7729
|
}
|
|
7726
7730
|
function actualWriteBuffer() {
|
|
@@ -7729,7 +7733,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7729
7733
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7730
7734
|
if (this.sync) {
|
|
7731
7735
|
try {
|
|
7732
|
-
const written =
|
|
7736
|
+
const written = fs54.writeSync(this.fd, this._writingBuf);
|
|
7733
7737
|
release(null, written);
|
|
7734
7738
|
} catch (err) {
|
|
7735
7739
|
release(err);
|
|
@@ -7738,7 +7742,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7738
7742
|
if (kCopyBuffer) {
|
|
7739
7743
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7740
7744
|
}
|
|
7741
|
-
|
|
7745
|
+
fs54.write(this.fd, this._writingBuf, release);
|
|
7742
7746
|
}
|
|
7743
7747
|
}
|
|
7744
7748
|
function actualClose(sonic) {
|
|
@@ -7754,12 +7758,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7754
7758
|
sonic._lens = [];
|
|
7755
7759
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7756
7760
|
try {
|
|
7757
|
-
|
|
7761
|
+
fs54.fsync(sonic.fd, closeWrapped);
|
|
7758
7762
|
} catch {
|
|
7759
7763
|
}
|
|
7760
7764
|
function closeWrapped() {
|
|
7761
7765
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7762
|
-
|
|
7766
|
+
fs54.close(sonic.fd, done);
|
|
7763
7767
|
} else {
|
|
7764
7768
|
done();
|
|
7765
7769
|
}
|
|
@@ -10894,11 +10898,11 @@ var init_lib = __esm({
|
|
|
10894
10898
|
}
|
|
10895
10899
|
}
|
|
10896
10900
|
},
|
|
10897
|
-
addToPath: function addToPath(
|
|
10898
|
-
var last =
|
|
10901
|
+
addToPath: function addToPath(path60, added, removed, oldPosInc, options) {
|
|
10902
|
+
var last = path60.lastComponent;
|
|
10899
10903
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10900
10904
|
return {
|
|
10901
|
-
oldPos:
|
|
10905
|
+
oldPos: path60.oldPos + oldPosInc,
|
|
10902
10906
|
lastComponent: {
|
|
10903
10907
|
count: last.count + 1,
|
|
10904
10908
|
added,
|
|
@@ -10908,7 +10912,7 @@ var init_lib = __esm({
|
|
|
10908
10912
|
};
|
|
10909
10913
|
} else {
|
|
10910
10914
|
return {
|
|
10911
|
-
oldPos:
|
|
10915
|
+
oldPos: path60.oldPos + oldPosInc,
|
|
10912
10916
|
lastComponent: {
|
|
10913
10917
|
count: 1,
|
|
10914
10918
|
added,
|
|
@@ -11154,7 +11158,7 @@ function hashDirToCwd(hash) {
|
|
|
11154
11158
|
}
|
|
11155
11159
|
function safeStatMtime(p2) {
|
|
11156
11160
|
try {
|
|
11157
|
-
return
|
|
11161
|
+
return import_node_fs10.default.statSync(p2).mtimeMs;
|
|
11158
11162
|
} catch {
|
|
11159
11163
|
return 0;
|
|
11160
11164
|
}
|
|
@@ -11162,7 +11166,7 @@ function safeStatMtime(p2) {
|
|
|
11162
11166
|
function readJsonlLines(file) {
|
|
11163
11167
|
let raw;
|
|
11164
11168
|
try {
|
|
11165
|
-
raw =
|
|
11169
|
+
raw = import_node_fs10.default.readFileSync(file, "utf8");
|
|
11166
11170
|
} catch (err) {
|
|
11167
11171
|
if (err.code === "ENOENT") return [];
|
|
11168
11172
|
throw err;
|
|
@@ -11354,10 +11358,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11354
11358
|
const memories = raw.map((m2) => {
|
|
11355
11359
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11356
11360
|
const rec3 = m2;
|
|
11357
|
-
const
|
|
11361
|
+
const path60 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11358
11362
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11359
|
-
if (!
|
|
11360
|
-
const entry = { path:
|
|
11363
|
+
if (!path60 || content == null) return null;
|
|
11364
|
+
const entry = { path: path60, content };
|
|
11361
11365
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11362
11366
|
return entry;
|
|
11363
11367
|
}).filter((m2) => m2 !== null);
|
|
@@ -11393,8 +11397,8 @@ function attachmentDeferredToolsText(a) {
|
|
|
11393
11397
|
function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
11394
11398
|
if (backupFileName === null) return null;
|
|
11395
11399
|
try {
|
|
11396
|
-
return
|
|
11397
|
-
|
|
11400
|
+
return import_node_fs10.default.readFileSync(
|
|
11401
|
+
import_node_path9.default.join(fileHistoryRoot, toolSessionId, backupFileName),
|
|
11398
11402
|
"utf8"
|
|
11399
11403
|
);
|
|
11400
11404
|
} catch {
|
|
@@ -11403,19 +11407,19 @@ function readBackupContent(fileHistoryRoot, toolSessionId, backupFileName) {
|
|
|
11403
11407
|
}
|
|
11404
11408
|
function readCurrentContent(filePath) {
|
|
11405
11409
|
try {
|
|
11406
|
-
return
|
|
11410
|
+
return import_node_fs10.default.readFileSync(filePath, "utf8");
|
|
11407
11411
|
} catch (err) {
|
|
11408
11412
|
if (err.code === "ENOENT") return null;
|
|
11409
11413
|
return null;
|
|
11410
11414
|
}
|
|
11411
11415
|
}
|
|
11412
|
-
var
|
|
11416
|
+
var import_node_fs10, import_node_os5, 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;
|
|
11413
11417
|
var init_claude_history = __esm({
|
|
11414
11418
|
"src/tools/claude-history.ts"() {
|
|
11415
11419
|
"use strict";
|
|
11416
|
-
|
|
11420
|
+
import_node_fs10 = __toESM(require("fs"), 1);
|
|
11417
11421
|
import_node_os5 = __toESM(require("os"), 1);
|
|
11418
|
-
|
|
11422
|
+
import_node_path9 = __toESM(require("path"), 1);
|
|
11419
11423
|
init_lib();
|
|
11420
11424
|
init_tool_result_extra();
|
|
11421
11425
|
TASK_NOTIFICATION_RE = /<task-notification\b[\s\S]*?<\/task-notification>/i;
|
|
@@ -11439,14 +11443,14 @@ var init_claude_history = __esm({
|
|
|
11439
11443
|
// 每次 user 提交前 trackEdit 拷一份,作为 rewind 回退目标
|
|
11440
11444
|
fileHistoryRoot;
|
|
11441
11445
|
constructor(opts = {}) {
|
|
11442
|
-
const base = opts.baseDir ??
|
|
11443
|
-
this.projectsRoot =
|
|
11444
|
-
this.fileHistoryRoot =
|
|
11446
|
+
const base = opts.baseDir ?? import_node_path9.default.join(import_node_os5.default.homedir(), ".claude");
|
|
11447
|
+
this.projectsRoot = import_node_path9.default.join(base, "projects");
|
|
11448
|
+
this.fileHistoryRoot = import_node_path9.default.join(base, "file-history");
|
|
11445
11449
|
}
|
|
11446
11450
|
async listProjects() {
|
|
11447
11451
|
let entries;
|
|
11448
11452
|
try {
|
|
11449
|
-
entries =
|
|
11453
|
+
entries = import_node_fs10.default.readdirSync(this.projectsRoot, { withFileTypes: true });
|
|
11450
11454
|
} catch (err) {
|
|
11451
11455
|
if (err.code === "ENOENT") return [];
|
|
11452
11456
|
throw err;
|
|
@@ -11454,9 +11458,9 @@ var init_claude_history = __esm({
|
|
|
11454
11458
|
const out = [];
|
|
11455
11459
|
for (const ent of entries) {
|
|
11456
11460
|
if (!ent.isDirectory()) continue;
|
|
11457
|
-
const dir =
|
|
11458
|
-
const files =
|
|
11459
|
-
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(
|
|
11461
|
+
const dir = import_node_path9.default.join(this.projectsRoot, ent.name);
|
|
11462
|
+
const files = import_node_fs10.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
11463
|
+
const updatedAtMs = files.reduce((m2, f) => Math.max(m2, safeStatMtime(import_node_path9.default.join(dir, f))), 0);
|
|
11460
11464
|
out.push({
|
|
11461
11465
|
projectPath: hashDirToCwd(ent.name),
|
|
11462
11466
|
hashDir: ent.name,
|
|
@@ -11468,17 +11472,17 @@ var init_claude_history = __esm({
|
|
|
11468
11472
|
return out;
|
|
11469
11473
|
}
|
|
11470
11474
|
async listSessions(args) {
|
|
11471
|
-
const dir =
|
|
11475
|
+
const dir = import_node_path9.default.join(this.projectsRoot, cwdToHashDir(args.projectPath));
|
|
11472
11476
|
let files;
|
|
11473
11477
|
try {
|
|
11474
|
-
files =
|
|
11478
|
+
files = import_node_fs10.default.readdirSync(dir).filter((f) => f.endsWith(".jsonl"));
|
|
11475
11479
|
} catch (err) {
|
|
11476
11480
|
if (err.code === "ENOENT") return [];
|
|
11477
11481
|
throw err;
|
|
11478
11482
|
}
|
|
11479
11483
|
const out = [];
|
|
11480
11484
|
for (const f of files) {
|
|
11481
|
-
const full =
|
|
11485
|
+
const full = import_node_path9.default.join(dir, f);
|
|
11482
11486
|
const toolSessionId = f.slice(0, -".jsonl".length);
|
|
11483
11487
|
const lines = readJsonlLines(full);
|
|
11484
11488
|
let summary = "";
|
|
@@ -11533,7 +11537,7 @@ var init_claude_history = __esm({
|
|
|
11533
11537
|
return out;
|
|
11534
11538
|
}
|
|
11535
11539
|
async read(args) {
|
|
11536
|
-
const file =
|
|
11540
|
+
const file = import_node_path9.default.join(
|
|
11537
11541
|
this.projectsRoot,
|
|
11538
11542
|
cwdToHashDir(args.cwd),
|
|
11539
11543
|
`${args.toolSessionId}.jsonl`
|
|
@@ -11570,7 +11574,7 @@ var init_claude_history = __esm({
|
|
|
11570
11574
|
// 独立目录路径:<projectsRoot>/<cwdHash>/<toolSessionId>/subagents/*.jsonl
|
|
11571
11575
|
// 返回 null 表示目录不存在(调用方回退旧实现);返回空数组表示目录存在但无 jsonl
|
|
11572
11576
|
listSubagentsFromDirectory(cwd, toolSessionId) {
|
|
11573
|
-
const dir =
|
|
11577
|
+
const dir = import_node_path9.default.join(
|
|
11574
11578
|
this.projectsRoot,
|
|
11575
11579
|
cwdToHashDir(cwd),
|
|
11576
11580
|
toolSessionId,
|
|
@@ -11578,7 +11582,7 @@ var init_claude_history = __esm({
|
|
|
11578
11582
|
);
|
|
11579
11583
|
let entries;
|
|
11580
11584
|
try {
|
|
11581
|
-
entries =
|
|
11585
|
+
entries = import_node_fs10.default.readdirSync(dir, { withFileTypes: true });
|
|
11582
11586
|
} catch (err) {
|
|
11583
11587
|
if (err.code === "ENOENT") return null;
|
|
11584
11588
|
return null;
|
|
@@ -11588,7 +11592,7 @@ var init_claude_history = __esm({
|
|
|
11588
11592
|
if (!e.isFile()) continue;
|
|
11589
11593
|
if (!e.name.startsWith("agent-") || !e.name.endsWith(".jsonl")) continue;
|
|
11590
11594
|
const subagentId = e.name.slice("agent-".length, -".jsonl".length);
|
|
11591
|
-
const filePath =
|
|
11595
|
+
const filePath = import_node_path9.default.join(dir, e.name);
|
|
11592
11596
|
const lines = readJsonlLines(filePath);
|
|
11593
11597
|
let firstText = "";
|
|
11594
11598
|
let messageCount = 0;
|
|
@@ -11605,7 +11609,7 @@ var init_claude_history = __esm({
|
|
|
11605
11609
|
return out;
|
|
11606
11610
|
}
|
|
11607
11611
|
listSubagentsFromMainJsonl(cwd, toolSessionId) {
|
|
11608
|
-
const file =
|
|
11612
|
+
const file = import_node_path9.default.join(
|
|
11609
11613
|
this.projectsRoot,
|
|
11610
11614
|
cwdToHashDir(cwd),
|
|
11611
11615
|
`${toolSessionId}.jsonl`
|
|
@@ -11640,7 +11644,7 @@ var init_claude_history = __esm({
|
|
|
11640
11644
|
}
|
|
11641
11645
|
// 独立文件路径:agent-<subagentId>.jsonl;文件不存在返回 null 让调用方回退旧实现
|
|
11642
11646
|
readSubagentFromFile(cwd, toolSessionId, subagentId) {
|
|
11643
|
-
const file =
|
|
11647
|
+
const file = import_node_path9.default.join(
|
|
11644
11648
|
this.projectsRoot,
|
|
11645
11649
|
cwdToHashDir(cwd),
|
|
11646
11650
|
toolSessionId,
|
|
@@ -11649,7 +11653,7 @@ var init_claude_history = __esm({
|
|
|
11649
11653
|
);
|
|
11650
11654
|
let exists = false;
|
|
11651
11655
|
try {
|
|
11652
|
-
exists =
|
|
11656
|
+
exists = import_node_fs10.default.statSync(file).isFile();
|
|
11653
11657
|
} catch {
|
|
11654
11658
|
return null;
|
|
11655
11659
|
}
|
|
@@ -11668,7 +11672,7 @@ var init_claude_history = __esm({
|
|
|
11668
11672
|
* "那一刻每个 tracked 文件对应的 backup 文件名"
|
|
11669
11673
|
*/
|
|
11670
11674
|
readFileHistorySnapshots(args) {
|
|
11671
|
-
const file =
|
|
11675
|
+
const file = import_node_path9.default.join(
|
|
11672
11676
|
this.projectsRoot,
|
|
11673
11677
|
cwdToHashDir(args.cwd),
|
|
11674
11678
|
`${args.toolSessionId}.jsonl`
|
|
@@ -11713,7 +11717,7 @@ var init_claude_history = __esm({
|
|
|
11713
11717
|
for (const [anchorId, target] of snapshots) {
|
|
11714
11718
|
let hasAny = false;
|
|
11715
11719
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11716
|
-
const absPath =
|
|
11720
|
+
const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
|
|
11717
11721
|
const backupContent = readBackupContent(
|
|
11718
11722
|
this.fileHistoryRoot,
|
|
11719
11723
|
args.toolSessionId,
|
|
@@ -11753,7 +11757,7 @@ var init_claude_history = __esm({
|
|
|
11753
11757
|
let totalInsertions = 0;
|
|
11754
11758
|
let totalDeletions = 0;
|
|
11755
11759
|
for (const [rawPath, backup] of Object.entries(target)) {
|
|
11756
|
-
const absPath =
|
|
11760
|
+
const absPath = import_node_path9.default.isAbsolute(rawPath) ? rawPath : import_node_path9.default.join(args.cwd, rawPath);
|
|
11757
11761
|
const backupContent = readBackupContent(
|
|
11758
11762
|
this.fileHistoryRoot,
|
|
11759
11763
|
args.toolSessionId,
|
|
@@ -11800,7 +11804,7 @@ var init_claude_history = __esm({
|
|
|
11800
11804
|
};
|
|
11801
11805
|
}
|
|
11802
11806
|
readSubagentFromMainJsonl(cwd, toolSessionId, subagentId) {
|
|
11803
|
-
const file =
|
|
11807
|
+
const file = import_node_path9.default.join(
|
|
11804
11808
|
this.projectsRoot,
|
|
11805
11809
|
cwdToHashDir(cwd),
|
|
11806
11810
|
`${toolSessionId}.jsonl`
|
|
@@ -11825,13 +11829,13 @@ var init_claude_history = __esm({
|
|
|
11825
11829
|
function probeViaWhich() {
|
|
11826
11830
|
try {
|
|
11827
11831
|
const out = (0, import_node_child_process2.execFileSync)("which", ["claude"], { encoding: "utf8" }).trim();
|
|
11828
|
-
if (out &&
|
|
11832
|
+
if (out && import_node_fs11.default.existsSync(out)) return out;
|
|
11829
11833
|
} catch {
|
|
11830
11834
|
}
|
|
11831
11835
|
return null;
|
|
11832
11836
|
}
|
|
11833
11837
|
async function probeClaude(env = process.env) {
|
|
11834
|
-
if (env.CLAUDE_BIN &&
|
|
11838
|
+
if (env.CLAUDE_BIN && import_node_fs11.default.existsSync(env.CLAUDE_BIN)) {
|
|
11835
11839
|
return { available: true, path: env.CLAUDE_BIN };
|
|
11836
11840
|
}
|
|
11837
11841
|
const w2 = probeViaWhich();
|
|
@@ -12159,10 +12163,10 @@ function parseAttachment(obj) {
|
|
|
12159
12163
|
const memories = raw.map((m2) => {
|
|
12160
12164
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12161
12165
|
const rec3 = m2;
|
|
12162
|
-
const
|
|
12166
|
+
const path60 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12163
12167
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12164
|
-
if (!
|
|
12165
|
-
const out = { path:
|
|
12168
|
+
if (!path60 || content == null) return null;
|
|
12169
|
+
const out = { path: path60, content };
|
|
12166
12170
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12167
12171
|
return out;
|
|
12168
12172
|
}).filter((m2) => m2 !== null);
|
|
@@ -12266,13 +12270,13 @@ function encodeClaudeStdin(text) {
|
|
|
12266
12270
|
};
|
|
12267
12271
|
return JSON.stringify(frame) + "\n";
|
|
12268
12272
|
}
|
|
12269
|
-
var import_node_child_process, import_node_child_process2,
|
|
12273
|
+
var import_node_child_process, import_node_child_process2, import_node_fs11, ATTACHMENT_SILENT_SUBTYPES2, unknownTypeHandler, ATTACHMENT_RE, IMAGE_EXT_MIME, CLAUDE_MODELS, CLAUDE_PERMISSION_MODES, CLAUDE_CAPABILITIES, ClaudeAdapter;
|
|
12270
12274
|
var init_claude = __esm({
|
|
12271
12275
|
"src/tools/claude.ts"() {
|
|
12272
12276
|
"use strict";
|
|
12273
12277
|
import_node_child_process = require("child_process");
|
|
12274
12278
|
import_node_child_process2 = require("child_process");
|
|
12275
|
-
|
|
12279
|
+
import_node_fs11 = __toESM(require("fs"), 1);
|
|
12276
12280
|
init_protocol();
|
|
12277
12281
|
init_claude_history();
|
|
12278
12282
|
init_tool_result_extra();
|
|
@@ -23949,8 +23953,8 @@ var require_utils = __commonJS({
|
|
|
23949
23953
|
var result = transform[inputType][outputType](input);
|
|
23950
23954
|
return result;
|
|
23951
23955
|
};
|
|
23952
|
-
exports2.resolve = function(
|
|
23953
|
-
var parts =
|
|
23956
|
+
exports2.resolve = function(path60) {
|
|
23957
|
+
var parts = path60.split("/");
|
|
23954
23958
|
var result = [];
|
|
23955
23959
|
for (var index = 0; index < parts.length; index++) {
|
|
23956
23960
|
var part = parts[index];
|
|
@@ -29803,18 +29807,18 @@ var require_object = __commonJS({
|
|
|
29803
29807
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
29804
29808
|
this.files[name] = object;
|
|
29805
29809
|
};
|
|
29806
|
-
var parentFolder = function(
|
|
29807
|
-
if (
|
|
29808
|
-
|
|
29810
|
+
var parentFolder = function(path60) {
|
|
29811
|
+
if (path60.slice(-1) === "/") {
|
|
29812
|
+
path60 = path60.substring(0, path60.length - 1);
|
|
29809
29813
|
}
|
|
29810
|
-
var lastSlash =
|
|
29811
|
-
return lastSlash > 0 ?
|
|
29814
|
+
var lastSlash = path60.lastIndexOf("/");
|
|
29815
|
+
return lastSlash > 0 ? path60.substring(0, lastSlash) : "";
|
|
29812
29816
|
};
|
|
29813
|
-
var forceTrailingSlash = function(
|
|
29814
|
-
if (
|
|
29815
|
-
|
|
29817
|
+
var forceTrailingSlash = function(path60) {
|
|
29818
|
+
if (path60.slice(-1) !== "/") {
|
|
29819
|
+
path60 += "/";
|
|
29816
29820
|
}
|
|
29817
|
-
return
|
|
29821
|
+
return path60;
|
|
29818
29822
|
};
|
|
29819
29823
|
var folderAdd = function(name, createFolders) {
|
|
29820
29824
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -30816,7 +30820,7 @@ var require_lib3 = __commonJS({
|
|
|
30816
30820
|
// src/run-case/recorder.ts
|
|
30817
30821
|
function startRunCaseRecorder(opts) {
|
|
30818
30822
|
const now = opts.now ?? Date.now;
|
|
30819
|
-
const dir =
|
|
30823
|
+
const dir = import_node_path48.default.dirname(opts.recordPath);
|
|
30820
30824
|
let stream = null;
|
|
30821
30825
|
let closing = false;
|
|
30822
30826
|
let closedSettled = false;
|
|
@@ -30830,8 +30834,8 @@ function startRunCaseRecorder(opts) {
|
|
|
30830
30834
|
});
|
|
30831
30835
|
const ensureStream = () => {
|
|
30832
30836
|
if (stream) return stream;
|
|
30833
|
-
|
|
30834
|
-
stream =
|
|
30837
|
+
import_node_fs37.default.mkdirSync(dir, { recursive: true });
|
|
30838
|
+
stream = import_node_fs37.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
30835
30839
|
stream.on("close", () => closedResolve());
|
|
30836
30840
|
return stream;
|
|
30837
30841
|
};
|
|
@@ -30856,12 +30860,12 @@ function startRunCaseRecorder(opts) {
|
|
|
30856
30860
|
};
|
|
30857
30861
|
return { tap, close, closed };
|
|
30858
30862
|
}
|
|
30859
|
-
var
|
|
30863
|
+
var import_node_fs37, import_node_path48;
|
|
30860
30864
|
var init_recorder = __esm({
|
|
30861
30865
|
"src/run-case/recorder.ts"() {
|
|
30862
30866
|
"use strict";
|
|
30863
|
-
|
|
30864
|
-
|
|
30867
|
+
import_node_fs37 = __toESM(require("fs"), 1);
|
|
30868
|
+
import_node_path48 = __toESM(require("path"), 1);
|
|
30865
30869
|
}
|
|
30866
30870
|
});
|
|
30867
30871
|
|
|
@@ -30904,7 +30908,7 @@ var init_wire = __esm({
|
|
|
30904
30908
|
// src/run-case/controller.ts
|
|
30905
30909
|
async function runController(opts) {
|
|
30906
30910
|
const now = opts.now ?? Date.now;
|
|
30907
|
-
const cwd = opts.cwd ?? (0,
|
|
30911
|
+
const cwd = opts.cwd ?? (0, import_node_fs38.mkdtempSync)(import_node_path49.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
|
|
30908
30912
|
const ownsCwd = opts.cwd === void 0;
|
|
30909
30913
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
30910
30914
|
const spawnCtx = { cwd };
|
|
@@ -31065,19 +31069,19 @@ async function runController(opts) {
|
|
|
31065
31069
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
31066
31070
|
if (ownsCwd) {
|
|
31067
31071
|
try {
|
|
31068
|
-
(0,
|
|
31072
|
+
(0, import_node_fs38.rmSync)(cwd, { recursive: true, force: true });
|
|
31069
31073
|
} catch {
|
|
31070
31074
|
}
|
|
31071
31075
|
}
|
|
31072
31076
|
return exitCode ?? 0;
|
|
31073
31077
|
}
|
|
31074
|
-
var
|
|
31078
|
+
var import_node_fs38, import_node_os21, import_node_path49;
|
|
31075
31079
|
var init_controller = __esm({
|
|
31076
31080
|
"src/run-case/controller.ts"() {
|
|
31077
31081
|
"use strict";
|
|
31078
|
-
|
|
31082
|
+
import_node_fs38 = require("fs");
|
|
31079
31083
|
import_node_os21 = __toESM(require("os"), 1);
|
|
31080
|
-
|
|
31084
|
+
import_node_path49 = __toESM(require("path"), 1);
|
|
31081
31085
|
init_claude();
|
|
31082
31086
|
init_stdout_splitter();
|
|
31083
31087
|
init_permission_stdio();
|
|
@@ -31339,8 +31343,8 @@ Env (advanced):
|
|
|
31339
31343
|
`;
|
|
31340
31344
|
|
|
31341
31345
|
// src/index.ts
|
|
31342
|
-
var
|
|
31343
|
-
var
|
|
31346
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
31347
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
31344
31348
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
31345
31349
|
|
|
31346
31350
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -31391,7 +31395,7 @@ function v4(options, buf, offset) {
|
|
|
31391
31395
|
var v4_default = v4;
|
|
31392
31396
|
|
|
31393
31397
|
// src/index.ts
|
|
31394
|
-
var
|
|
31398
|
+
var import_node_url3 = require("url");
|
|
31395
31399
|
|
|
31396
31400
|
// src/logger.ts
|
|
31397
31401
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -35955,12 +35959,77 @@ function refreshDeployKit(args) {
|
|
|
35955
35959
|
args.logger.info("deploy-kit.refresh.done", { dst });
|
|
35956
35960
|
}
|
|
35957
35961
|
|
|
35962
|
+
// src/share-md-viewer/load.ts
|
|
35963
|
+
var import_node_fs9 = __toESM(require("fs"), 1);
|
|
35964
|
+
var import_node_path8 = __toESM(require("path"), 1);
|
|
35965
|
+
var import_node_url2 = require("url");
|
|
35966
|
+
|
|
35967
|
+
// src/share-md-viewer/asset-loader.ts
|
|
35968
|
+
var import_node_fs8 = __toESM(require("fs"), 1);
|
|
35969
|
+
function htmlEscape(s) {
|
|
35970
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
35971
|
+
}
|
|
35972
|
+
function createViewerAssetLoader(opts) {
|
|
35973
|
+
let viewerTemplate;
|
|
35974
|
+
let errorTemplate;
|
|
35975
|
+
try {
|
|
35976
|
+
viewerTemplate = import_node_fs8.default.readFileSync(opts.viewerHtmlPath, "utf8");
|
|
35977
|
+
} catch (err) {
|
|
35978
|
+
throw new Error(`viewer asset not found at ${opts.viewerHtmlPath}: ${err.message}`);
|
|
35979
|
+
}
|
|
35980
|
+
try {
|
|
35981
|
+
errorTemplate = import_node_fs8.default.readFileSync(opts.errorHtmlPath, "utf8");
|
|
35982
|
+
} catch (err) {
|
|
35983
|
+
throw new Error(`viewer error asset not found at ${opts.errorHtmlPath}: ${err.message}`);
|
|
35984
|
+
}
|
|
35985
|
+
return {
|
|
35986
|
+
renderViewerHtml(basename) {
|
|
35987
|
+
return viewerTemplate.replace(/\{\{TITLE\}\}/g, htmlEscape(basename));
|
|
35988
|
+
},
|
|
35989
|
+
renderErrorHtml(code, message) {
|
|
35990
|
+
return errorTemplate.replace(/\{\{ERROR_CODE\}\}/g, htmlEscape(code)).replace(/\{\{ERROR_MESSAGE\}\}/g, htmlEscape(message));
|
|
35991
|
+
}
|
|
35992
|
+
};
|
|
35993
|
+
}
|
|
35994
|
+
|
|
35995
|
+
// src/share-md-viewer/load.ts
|
|
35996
|
+
var import_meta2 = {};
|
|
35997
|
+
function tryLoadViewerAssets(logger) {
|
|
35998
|
+
const candidates = [];
|
|
35999
|
+
try {
|
|
36000
|
+
const here = import_node_path8.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
|
|
36001
|
+
candidates.push(here);
|
|
36002
|
+
candidates.push(import_node_path8.default.resolve(here, ".."));
|
|
36003
|
+
candidates.push(import_node_path8.default.resolve(here, "..", "..", "dist"));
|
|
36004
|
+
} catch {
|
|
36005
|
+
}
|
|
36006
|
+
if (process.argv[1]) {
|
|
36007
|
+
candidates.push(import_node_path8.default.dirname(process.argv[1]));
|
|
36008
|
+
}
|
|
36009
|
+
for (const root of candidates) {
|
|
36010
|
+
const viewerHtmlPath = import_node_path8.default.join(root, "share-md-viewer.html");
|
|
36011
|
+
const errorHtmlPath = import_node_path8.default.join(root, "share-md-viewer-error.html");
|
|
36012
|
+
try {
|
|
36013
|
+
if (import_node_fs9.default.statSync(viewerHtmlPath).isFile() && import_node_fs9.default.statSync(errorHtmlPath).isFile()) {
|
|
36014
|
+
logger?.info("share-md-viewer.assets-root.resolved", { root });
|
|
36015
|
+
return createViewerAssetLoader({ viewerHtmlPath, errorHtmlPath });
|
|
36016
|
+
}
|
|
36017
|
+
} catch {
|
|
36018
|
+
}
|
|
36019
|
+
}
|
|
36020
|
+
logger?.warn("share-md-viewer.assets-not-found", {
|
|
36021
|
+
candidates,
|
|
36022
|
+
hint: "run `pnpm -F @clawos/ext-clawd-ui build && pnpm -F @clawos-dev/clawd build`"
|
|
36023
|
+
});
|
|
36024
|
+
return null;
|
|
36025
|
+
}
|
|
36026
|
+
|
|
35958
36027
|
// src/index.ts
|
|
35959
36028
|
init_claude();
|
|
35960
36029
|
|
|
35961
36030
|
// src/tools/codex.ts
|
|
35962
36031
|
var import_node_child_process4 = require("child_process");
|
|
35963
|
-
var
|
|
36032
|
+
var import_node_fs12 = __toESM(require("fs"), 1);
|
|
35964
36033
|
|
|
35965
36034
|
// src/tools/codex-session.ts
|
|
35966
36035
|
var import_node_child_process3 = require("child_process");
|
|
@@ -36208,8 +36277,8 @@ function turnStartInput(text) {
|
|
|
36208
36277
|
const items = [];
|
|
36209
36278
|
let leftover = text;
|
|
36210
36279
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
36211
|
-
const [marker, name,
|
|
36212
|
-
items.push({ type: "skill", name, path:
|
|
36280
|
+
const [marker, name, path60] = m2;
|
|
36281
|
+
items.push({ type: "skill", name, path: path60 });
|
|
36213
36282
|
leftover = leftover.replace(marker, "");
|
|
36214
36283
|
}
|
|
36215
36284
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -36393,10 +36462,10 @@ function sanitizeCodexModel(model) {
|
|
|
36393
36462
|
return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
|
|
36394
36463
|
}
|
|
36395
36464
|
async function probeCodex(env = process.env) {
|
|
36396
|
-
if (env.CODEX_BIN &&
|
|
36465
|
+
if (env.CODEX_BIN && import_node_fs12.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
36397
36466
|
try {
|
|
36398
36467
|
const out = (0, import_node_child_process4.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
|
|
36399
|
-
if (out &&
|
|
36468
|
+
if (out && import_node_fs12.default.existsSync(out)) return { available: true, path: out };
|
|
36400
36469
|
} catch {
|
|
36401
36470
|
}
|
|
36402
36471
|
return { available: false };
|
|
@@ -36441,9 +36510,9 @@ var CodexAdapter = class {
|
|
|
36441
36510
|
};
|
|
36442
36511
|
|
|
36443
36512
|
// src/tools/claude-tui.ts
|
|
36444
|
-
var
|
|
36513
|
+
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
36445
36514
|
var import_node_os6 = __toESM(require("os"), 1);
|
|
36446
|
-
var
|
|
36515
|
+
var import_node_path10 = __toESM(require("path"), 1);
|
|
36447
36516
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
36448
36517
|
|
|
36449
36518
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -37509,9 +37578,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
37509
37578
|
function jsonlExistsForCtx(ctx) {
|
|
37510
37579
|
if (!ctx.toolSessionId) return false;
|
|
37511
37580
|
const home = import_node_os6.default.homedir();
|
|
37512
|
-
const file =
|
|
37581
|
+
const file = import_node_path10.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
37513
37582
|
try {
|
|
37514
|
-
return
|
|
37583
|
+
return import_node_fs13.default.statSync(file).isFile();
|
|
37515
37584
|
} catch {
|
|
37516
37585
|
return false;
|
|
37517
37586
|
}
|
|
@@ -37580,10 +37649,10 @@ var PersonaDispatchManager = class {
|
|
|
37580
37649
|
};
|
|
37581
37650
|
|
|
37582
37651
|
// src/dispatch/mcp-config.ts
|
|
37583
|
-
var
|
|
37584
|
-
var
|
|
37652
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
37653
|
+
var import_node_path11 = __toESM(require("path"), 1);
|
|
37585
37654
|
function dispatchMcpConfigPath(dataDir) {
|
|
37586
|
-
return
|
|
37655
|
+
return import_node_path11.default.join(dataDir, "dispatch.mcp.json");
|
|
37587
37656
|
}
|
|
37588
37657
|
function writeDispatchMcpConfig(args) {
|
|
37589
37658
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -37598,8 +37667,8 @@ function writeDispatchMcpConfig(args) {
|
|
|
37598
37667
|
}
|
|
37599
37668
|
}
|
|
37600
37669
|
};
|
|
37601
|
-
|
|
37602
|
-
|
|
37670
|
+
import_node_fs14.default.mkdirSync(args.dataDir, { recursive: true });
|
|
37671
|
+
import_node_fs14.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
37603
37672
|
return cfgPath;
|
|
37604
37673
|
}
|
|
37605
37674
|
|
|
@@ -37855,13 +37924,13 @@ function mapSkillsListResponse(res) {
|
|
|
37855
37924
|
const r = s ?? {};
|
|
37856
37925
|
const name = str3(r.name);
|
|
37857
37926
|
if (!name) continue;
|
|
37858
|
-
const
|
|
37927
|
+
const path60 = str3(r.path);
|
|
37859
37928
|
const description = str3(r.description);
|
|
37860
37929
|
const isPlugin = name.includes(":");
|
|
37861
37930
|
out.push({
|
|
37862
37931
|
name,
|
|
37863
37932
|
source: isPlugin ? "plugin" : "project",
|
|
37864
|
-
...
|
|
37933
|
+
...path60 ? { path: path60 } : {},
|
|
37865
37934
|
...description ? { description } : {},
|
|
37866
37935
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
37867
37936
|
});
|
|
@@ -37900,23 +37969,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
37900
37969
|
}
|
|
37901
37970
|
|
|
37902
37971
|
// src/workspace/browser.ts
|
|
37903
|
-
var
|
|
37972
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37904
37973
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
37905
|
-
var
|
|
37974
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37906
37975
|
init_protocol();
|
|
37907
37976
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
37908
37977
|
function resolveInsideCwd(cwd, subpath) {
|
|
37909
|
-
const absCwd =
|
|
37910
|
-
const joined =
|
|
37911
|
-
const rel =
|
|
37912
|
-
if (rel.startsWith("..") ||
|
|
37978
|
+
const absCwd = import_node_path12.default.resolve(cwd);
|
|
37979
|
+
const joined = import_node_path12.default.resolve(absCwd, subpath ?? ".");
|
|
37980
|
+
const rel = import_node_path12.default.relative(absCwd, joined);
|
|
37981
|
+
if (rel.startsWith("..") || import_node_path12.default.isAbsolute(rel)) {
|
|
37913
37982
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
37914
37983
|
}
|
|
37915
37984
|
return joined;
|
|
37916
37985
|
}
|
|
37917
37986
|
function ensureCwd(cwd) {
|
|
37918
37987
|
try {
|
|
37919
|
-
const stat =
|
|
37988
|
+
const stat = import_node_fs15.default.statSync(cwd);
|
|
37920
37989
|
if (!stat.isDirectory()) {
|
|
37921
37990
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
37922
37991
|
}
|
|
@@ -37930,7 +37999,7 @@ var WorkspaceBrowser = class {
|
|
|
37930
37999
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
|
|
37931
38000
|
ensureCwd(cwd);
|
|
37932
38001
|
const full = resolveInsideCwd(cwd, args.path);
|
|
37933
|
-
const dirents =
|
|
38002
|
+
const dirents = import_node_fs15.default.readdirSync(full, { withFileTypes: true });
|
|
37934
38003
|
const entries = [];
|
|
37935
38004
|
for (const d of dirents) {
|
|
37936
38005
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -37940,7 +38009,7 @@ var WorkspaceBrowser = class {
|
|
|
37940
38009
|
mtime: ""
|
|
37941
38010
|
};
|
|
37942
38011
|
try {
|
|
37943
|
-
const st =
|
|
38012
|
+
const st = import_node_fs15.default.statSync(import_node_path12.default.join(full, d.name));
|
|
37944
38013
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
37945
38014
|
if (d.isFile()) entry.size = st.size;
|
|
37946
38015
|
} catch {
|
|
@@ -37956,14 +38025,14 @@ var WorkspaceBrowser = class {
|
|
|
37956
38025
|
read(args) {
|
|
37957
38026
|
ensureCwd(args.cwd);
|
|
37958
38027
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
37959
|
-
const st =
|
|
38028
|
+
const st = import_node_fs15.default.statSync(full);
|
|
37960
38029
|
if (!st.isFile()) {
|
|
37961
38030
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
37962
38031
|
}
|
|
37963
38032
|
if (st.size > MAX_FILE_BYTES) {
|
|
37964
38033
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
37965
38034
|
}
|
|
37966
|
-
const buf =
|
|
38035
|
+
const buf = import_node_fs15.default.readFileSync(full);
|
|
37967
38036
|
const isBinary = buf.includes(0);
|
|
37968
38037
|
if (isBinary) {
|
|
37969
38038
|
return {
|
|
@@ -37985,20 +38054,20 @@ var WorkspaceBrowser = class {
|
|
|
37985
38054
|
};
|
|
37986
38055
|
|
|
37987
38056
|
// src/skills/agents-scanner.ts
|
|
37988
|
-
var
|
|
38057
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
37989
38058
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
37990
|
-
var
|
|
38059
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
37991
38060
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
37992
38061
|
function isDirLikeSync2(p2) {
|
|
37993
38062
|
try {
|
|
37994
|
-
return
|
|
38063
|
+
return import_node_fs16.default.statSync(p2).isDirectory();
|
|
37995
38064
|
} catch {
|
|
37996
38065
|
return false;
|
|
37997
38066
|
}
|
|
37998
38067
|
}
|
|
37999
38068
|
function fileExistsSync(p2) {
|
|
38000
38069
|
try {
|
|
38001
|
-
return
|
|
38070
|
+
return import_node_fs16.default.statSync(p2).isFile();
|
|
38002
38071
|
} catch {
|
|
38003
38072
|
return false;
|
|
38004
38073
|
}
|
|
@@ -38006,7 +38075,7 @@ function fileExistsSync(p2) {
|
|
|
38006
38075
|
function parseAgentFile(filePath) {
|
|
38007
38076
|
let content;
|
|
38008
38077
|
try {
|
|
38009
|
-
content =
|
|
38078
|
+
content = import_node_fs16.default.readFileSync(filePath, "utf8");
|
|
38010
38079
|
} catch {
|
|
38011
38080
|
return {};
|
|
38012
38081
|
}
|
|
@@ -38019,16 +38088,16 @@ function parseAgentFile(filePath) {
|
|
|
38019
38088
|
function scanAgentsDir(dir, source, seen, out) {
|
|
38020
38089
|
let entries;
|
|
38021
38090
|
try {
|
|
38022
|
-
entries =
|
|
38091
|
+
entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
|
|
38023
38092
|
} catch {
|
|
38024
38093
|
return;
|
|
38025
38094
|
}
|
|
38026
38095
|
for (const ent of entries) {
|
|
38027
38096
|
if (!ent.name.endsWith(".md")) continue;
|
|
38028
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
38097
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path13.default.join(dir, ent.name)))) {
|
|
38029
38098
|
continue;
|
|
38030
38099
|
}
|
|
38031
|
-
const filePath =
|
|
38100
|
+
const filePath = import_node_path13.default.join(dir, ent.name);
|
|
38032
38101
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
38033
38102
|
if (seen.has(baseName)) continue;
|
|
38034
38103
|
seen.add(baseName);
|
|
@@ -38046,12 +38115,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
38046
38115
|
function walk2(dir, namespaces) {
|
|
38047
38116
|
let entries;
|
|
38048
38117
|
try {
|
|
38049
|
-
entries =
|
|
38118
|
+
entries = import_node_fs16.default.readdirSync(dir, { withFileTypes: true });
|
|
38050
38119
|
} catch {
|
|
38051
38120
|
return;
|
|
38052
38121
|
}
|
|
38053
38122
|
for (const ent of entries) {
|
|
38054
|
-
const childPath =
|
|
38123
|
+
const childPath = import_node_path13.default.join(dir, ent.name);
|
|
38055
38124
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
38056
38125
|
walk2(childPath, [...namespaces, ent.name]);
|
|
38057
38126
|
continue;
|
|
@@ -38076,13 +38145,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
38076
38145
|
walk2(root, []);
|
|
38077
38146
|
}
|
|
38078
38147
|
function readInstalledPlugins2(home) {
|
|
38079
|
-
const pluginsDir =
|
|
38080
|
-
const v2 =
|
|
38081
|
-
const v1 =
|
|
38148
|
+
const pluginsDir = import_node_path13.default.join(home, ".claude", "plugins");
|
|
38149
|
+
const v2 = import_node_path13.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
38150
|
+
const v1 = import_node_path13.default.join(pluginsDir, "installed_plugins.json");
|
|
38082
38151
|
let raw = null;
|
|
38083
38152
|
for (const candidate of [v2, v1]) {
|
|
38084
38153
|
try {
|
|
38085
|
-
raw =
|
|
38154
|
+
raw = import_node_fs16.default.readFileSync(candidate, "utf8");
|
|
38086
38155
|
break;
|
|
38087
38156
|
} catch {
|
|
38088
38157
|
}
|
|
@@ -38107,19 +38176,19 @@ function readInstalledPlugins2(home) {
|
|
|
38107
38176
|
return out;
|
|
38108
38177
|
}
|
|
38109
38178
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
38110
|
-
let cur =
|
|
38111
|
-
const fsRoot =
|
|
38179
|
+
let cur = import_node_path13.default.resolve(startCwd);
|
|
38180
|
+
const fsRoot = import_node_path13.default.parse(cur).root;
|
|
38112
38181
|
while (true) {
|
|
38113
|
-
scanAgentsDir(
|
|
38182
|
+
scanAgentsDir(import_node_path13.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
38114
38183
|
let hasGit = false;
|
|
38115
38184
|
try {
|
|
38116
|
-
hasGit =
|
|
38185
|
+
hasGit = import_node_fs16.default.existsSync(import_node_path13.default.join(cur, ".git"));
|
|
38117
38186
|
} catch {
|
|
38118
38187
|
}
|
|
38119
38188
|
if (hasGit) return;
|
|
38120
38189
|
if (cur === home) return;
|
|
38121
38190
|
if (cur === fsRoot) return;
|
|
38122
|
-
const parent =
|
|
38191
|
+
const parent = import_node_path13.default.dirname(cur);
|
|
38123
38192
|
if (parent === cur) return;
|
|
38124
38193
|
cur = parent;
|
|
38125
38194
|
}
|
|
@@ -38154,7 +38223,7 @@ var AgentsScanner = class {
|
|
|
38154
38223
|
}
|
|
38155
38224
|
const fsBlock = [];
|
|
38156
38225
|
scanAgentsDir(
|
|
38157
|
-
|
|
38226
|
+
import_node_path13.default.join(this.home, ".claude", "agents"),
|
|
38158
38227
|
"global",
|
|
38159
38228
|
seen,
|
|
38160
38229
|
fsBlock
|
|
@@ -38168,7 +38237,7 @@ var AgentsScanner = class {
|
|
|
38168
38237
|
...this.extraPluginRoots
|
|
38169
38238
|
];
|
|
38170
38239
|
for (const { name, root } of plugins) {
|
|
38171
|
-
const agentsRoot =
|
|
38240
|
+
const agentsRoot = import_node_path13.default.join(root, "agents");
|
|
38172
38241
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
38173
38242
|
}
|
|
38174
38243
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -38176,15 +38245,15 @@ var AgentsScanner = class {
|
|
|
38176
38245
|
};
|
|
38177
38246
|
|
|
38178
38247
|
// src/observer/session-observer.ts
|
|
38179
|
-
var
|
|
38248
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
38180
38249
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
38181
|
-
var
|
|
38250
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
38182
38251
|
init_claude_history();
|
|
38183
38252
|
|
|
38184
38253
|
// src/observer/subagent-meta-observer.ts
|
|
38185
|
-
var
|
|
38254
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
38186
38255
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
38187
|
-
var
|
|
38256
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
38188
38257
|
init_claude_history();
|
|
38189
38258
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
38190
38259
|
var SubagentMetaObserver = class {
|
|
@@ -38197,7 +38266,7 @@ var SubagentMetaObserver = class {
|
|
|
38197
38266
|
watches = /* @__PURE__ */ new Map();
|
|
38198
38267
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
38199
38268
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
38200
|
-
return
|
|
38269
|
+
return import_node_path14.default.join(
|
|
38201
38270
|
this.home,
|
|
38202
38271
|
".claude",
|
|
38203
38272
|
"projects",
|
|
@@ -38227,7 +38296,7 @@ var SubagentMetaObserver = class {
|
|
|
38227
38296
|
attachWatcher(w2) {
|
|
38228
38297
|
if (w2.watcher) return;
|
|
38229
38298
|
try {
|
|
38230
|
-
w2.watcher =
|
|
38299
|
+
w2.watcher = import_node_fs17.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
38231
38300
|
if (!name) return;
|
|
38232
38301
|
const m2 = META_RE.exec(String(name));
|
|
38233
38302
|
if (!m2) return;
|
|
@@ -38239,7 +38308,7 @@ var SubagentMetaObserver = class {
|
|
|
38239
38308
|
scan(w2) {
|
|
38240
38309
|
let entries;
|
|
38241
38310
|
try {
|
|
38242
|
-
entries =
|
|
38311
|
+
entries = import_node_fs17.default.readdirSync(w2.dirPath);
|
|
38243
38312
|
} catch {
|
|
38244
38313
|
return;
|
|
38245
38314
|
}
|
|
@@ -38253,10 +38322,10 @@ var SubagentMetaObserver = class {
|
|
|
38253
38322
|
if (!m2) return;
|
|
38254
38323
|
const agentId = m2[1];
|
|
38255
38324
|
if (w2.emitted.has(agentId)) return;
|
|
38256
|
-
const file =
|
|
38325
|
+
const file = import_node_path14.default.join(w2.dirPath, name);
|
|
38257
38326
|
let raw;
|
|
38258
38327
|
try {
|
|
38259
|
-
raw =
|
|
38328
|
+
raw = import_node_fs17.default.readFileSync(file, "utf8");
|
|
38260
38329
|
} catch {
|
|
38261
38330
|
return;
|
|
38262
38331
|
}
|
|
@@ -38313,14 +38382,14 @@ var SessionObserver = class {
|
|
|
38313
38382
|
metaObserver;
|
|
38314
38383
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
38315
38384
|
if (override) return override;
|
|
38316
|
-
return
|
|
38385
|
+
return import_node_path15.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
38317
38386
|
}
|
|
38318
38387
|
start(args) {
|
|
38319
38388
|
this.stop(args.sessionId);
|
|
38320
38389
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
38321
38390
|
let size = 0;
|
|
38322
38391
|
try {
|
|
38323
|
-
size =
|
|
38392
|
+
size = import_node_fs18.default.statSync(filePath).size;
|
|
38324
38393
|
} catch {
|
|
38325
38394
|
}
|
|
38326
38395
|
const w2 = {
|
|
@@ -38334,10 +38403,10 @@ var SessionObserver = class {
|
|
|
38334
38403
|
prevIsRejectSentinel: false
|
|
38335
38404
|
};
|
|
38336
38405
|
try {
|
|
38337
|
-
|
|
38406
|
+
import_node_fs18.default.mkdirSync(import_node_path15.default.dirname(filePath), { recursive: true });
|
|
38338
38407
|
} catch {
|
|
38339
38408
|
}
|
|
38340
|
-
w2.watcher =
|
|
38409
|
+
w2.watcher = import_node_fs18.default.watch(import_node_path15.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
38341
38410
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
38342
38411
|
this.poll(w2);
|
|
38343
38412
|
});
|
|
@@ -38360,7 +38429,7 @@ var SessionObserver = class {
|
|
|
38360
38429
|
// 异常静默吞,不阻塞 watcher 启动
|
|
38361
38430
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
38362
38431
|
try {
|
|
38363
|
-
const raw =
|
|
38432
|
+
const raw = import_node_fs18.default.readFileSync(w2.filePath, "utf8");
|
|
38364
38433
|
if (!raw) return;
|
|
38365
38434
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
38366
38435
|
if (allLines.length === 0) return;
|
|
@@ -38384,7 +38453,7 @@ var SessionObserver = class {
|
|
|
38384
38453
|
poll(w2) {
|
|
38385
38454
|
let size = 0;
|
|
38386
38455
|
try {
|
|
38387
|
-
size =
|
|
38456
|
+
size = import_node_fs18.default.statSync(w2.filePath).size;
|
|
38388
38457
|
} catch {
|
|
38389
38458
|
return;
|
|
38390
38459
|
}
|
|
@@ -38393,11 +38462,11 @@ var SessionObserver = class {
|
|
|
38393
38462
|
w2.buf = "";
|
|
38394
38463
|
}
|
|
38395
38464
|
if (size === w2.lastSize) return;
|
|
38396
|
-
const fd =
|
|
38465
|
+
const fd = import_node_fs18.default.openSync(w2.filePath, "r");
|
|
38397
38466
|
try {
|
|
38398
38467
|
const len = size - w2.lastSize;
|
|
38399
38468
|
const buf = Buffer.alloc(len);
|
|
38400
|
-
|
|
38469
|
+
import_node_fs18.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
38401
38470
|
w2.lastSize = size;
|
|
38402
38471
|
w2.buf += buf.toString("utf8");
|
|
38403
38472
|
let newlineIndex;
|
|
@@ -38420,7 +38489,7 @@ var SessionObserver = class {
|
|
|
38420
38489
|
}
|
|
38421
38490
|
}
|
|
38422
38491
|
} finally {
|
|
38423
|
-
|
|
38492
|
+
import_node_fs18.default.closeSync(fd);
|
|
38424
38493
|
}
|
|
38425
38494
|
}
|
|
38426
38495
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -39143,14 +39212,14 @@ async function authenticate(token, deps) {
|
|
|
39143
39212
|
}
|
|
39144
39213
|
|
|
39145
39214
|
// src/permission/capability-store.ts
|
|
39146
|
-
var
|
|
39147
|
-
var
|
|
39215
|
+
var fs21 = __toESM(require("fs"), 1);
|
|
39216
|
+
var path20 = __toESM(require("path"), 1);
|
|
39148
39217
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
39149
39218
|
var FILE_VERSION = 1;
|
|
39150
39219
|
var CapabilityStore = class {
|
|
39151
39220
|
constructor(dataDir) {
|
|
39152
39221
|
this.dataDir = dataDir;
|
|
39153
|
-
|
|
39222
|
+
fs21.mkdirSync(dataDir, { recursive: true });
|
|
39154
39223
|
this.cache = this.readFromDisk();
|
|
39155
39224
|
}
|
|
39156
39225
|
dataDir;
|
|
@@ -39174,13 +39243,13 @@ var CapabilityStore = class {
|
|
|
39174
39243
|
this.flush();
|
|
39175
39244
|
}
|
|
39176
39245
|
filePath() {
|
|
39177
|
-
return
|
|
39246
|
+
return path20.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
39178
39247
|
}
|
|
39179
39248
|
readFromDisk() {
|
|
39180
39249
|
const file = this.filePath();
|
|
39181
39250
|
let raw;
|
|
39182
39251
|
try {
|
|
39183
|
-
raw =
|
|
39252
|
+
raw = fs21.readFileSync(file, "utf8");
|
|
39184
39253
|
} catch (err) {
|
|
39185
39254
|
if (err?.code === "ENOENT") return [];
|
|
39186
39255
|
return [];
|
|
@@ -39208,10 +39277,10 @@ var CapabilityStore = class {
|
|
|
39208
39277
|
}
|
|
39209
39278
|
atomicWrite(file, content) {
|
|
39210
39279
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39211
|
-
|
|
39212
|
-
|
|
39280
|
+
fs21.writeFileSync(tmp, content, { mode: 384 });
|
|
39281
|
+
fs21.renameSync(tmp, file);
|
|
39213
39282
|
try {
|
|
39214
|
-
|
|
39283
|
+
fs21.chmodSync(file, 384);
|
|
39215
39284
|
} catch {
|
|
39216
39285
|
}
|
|
39217
39286
|
}
|
|
@@ -39304,14 +39373,14 @@ var CapabilityManager = class {
|
|
|
39304
39373
|
};
|
|
39305
39374
|
|
|
39306
39375
|
// src/permission/cleanup.ts
|
|
39307
|
-
var
|
|
39376
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
39308
39377
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
39309
39378
|
const removed = [];
|
|
39310
39379
|
for (const g2 of cap.grants) {
|
|
39311
39380
|
if (g2.resource.type !== "persona") continue;
|
|
39312
39381
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
39313
39382
|
try {
|
|
39314
|
-
|
|
39383
|
+
fs22.rmSync(dir, { recursive: true, force: true });
|
|
39315
39384
|
removed.push(dir);
|
|
39316
39385
|
} catch {
|
|
39317
39386
|
}
|
|
@@ -39320,13 +39389,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
39320
39389
|
}
|
|
39321
39390
|
|
|
39322
39391
|
// src/inbox/inbox-store.ts
|
|
39323
|
-
var
|
|
39324
|
-
var
|
|
39392
|
+
var fs23 = __toESM(require("fs"), 1);
|
|
39393
|
+
var path21 = __toESM(require("path"), 1);
|
|
39325
39394
|
var INBOX_SUBDIR = "inbox";
|
|
39326
39395
|
var InboxStore = class {
|
|
39327
39396
|
constructor(dataDir) {
|
|
39328
39397
|
this.dataDir = dataDir;
|
|
39329
|
-
|
|
39398
|
+
fs23.mkdirSync(this.dirPath(), { recursive: true });
|
|
39330
39399
|
}
|
|
39331
39400
|
dataDir;
|
|
39332
39401
|
/**
|
|
@@ -39338,7 +39407,7 @@ var InboxStore = class {
|
|
|
39338
39407
|
const file = this.filePath(peerDeviceId);
|
|
39339
39408
|
let raw;
|
|
39340
39409
|
try {
|
|
39341
|
-
raw =
|
|
39410
|
+
raw = fs23.readFileSync(file, "utf8");
|
|
39342
39411
|
} catch (err) {
|
|
39343
39412
|
if (err?.code === "ENOENT") return [];
|
|
39344
39413
|
return [];
|
|
@@ -39354,7 +39423,7 @@ var InboxStore = class {
|
|
|
39354
39423
|
const dir = this.dirPath();
|
|
39355
39424
|
let entries;
|
|
39356
39425
|
try {
|
|
39357
|
-
entries =
|
|
39426
|
+
entries = fs23.readdirSync(dir);
|
|
39358
39427
|
} catch (err) {
|
|
39359
39428
|
if (err?.code === "ENOENT") return [];
|
|
39360
39429
|
return [];
|
|
@@ -39370,9 +39439,9 @@ var InboxStore = class {
|
|
|
39370
39439
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
39371
39440
|
const file = this.filePath(message.peerDeviceId);
|
|
39372
39441
|
const line = JSON.stringify(message) + "\n";
|
|
39373
|
-
|
|
39442
|
+
fs23.appendFileSync(file, line, { mode: 384 });
|
|
39374
39443
|
try {
|
|
39375
|
-
|
|
39444
|
+
fs23.chmodSync(file, 384);
|
|
39376
39445
|
} catch {
|
|
39377
39446
|
}
|
|
39378
39447
|
}
|
|
@@ -39402,7 +39471,7 @@ var InboxStore = class {
|
|
|
39402
39471
|
removeByPeerDeviceId(peerDeviceId) {
|
|
39403
39472
|
const file = this.filePath(peerDeviceId);
|
|
39404
39473
|
try {
|
|
39405
|
-
|
|
39474
|
+
fs23.unlinkSync(file);
|
|
39406
39475
|
} catch (err) {
|
|
39407
39476
|
if (err?.code === "ENOENT") return;
|
|
39408
39477
|
}
|
|
@@ -39411,18 +39480,18 @@ var InboxStore = class {
|
|
|
39411
39480
|
const file = this.filePath(peerDeviceId);
|
|
39412
39481
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39413
39482
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
39414
|
-
|
|
39415
|
-
|
|
39483
|
+
fs23.writeFileSync(tmp, content, { mode: 384 });
|
|
39484
|
+
fs23.renameSync(tmp, file);
|
|
39416
39485
|
try {
|
|
39417
|
-
|
|
39486
|
+
fs23.chmodSync(file, 384);
|
|
39418
39487
|
} catch {
|
|
39419
39488
|
}
|
|
39420
39489
|
}
|
|
39421
39490
|
dirPath() {
|
|
39422
|
-
return
|
|
39491
|
+
return path21.join(this.dataDir, INBOX_SUBDIR);
|
|
39423
39492
|
}
|
|
39424
39493
|
filePath(peerDeviceId) {
|
|
39425
|
-
return
|
|
39494
|
+
return path21.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
39426
39495
|
}
|
|
39427
39496
|
};
|
|
39428
39497
|
function parseAllLines(raw) {
|
|
@@ -39509,8 +39578,8 @@ var InboxManager = class {
|
|
|
39509
39578
|
};
|
|
39510
39579
|
|
|
39511
39580
|
// src/state/contact-store.ts
|
|
39512
|
-
var
|
|
39513
|
-
var
|
|
39581
|
+
var fs24 = __toESM(require("fs"), 1);
|
|
39582
|
+
var path22 = __toESM(require("path"), 1);
|
|
39514
39583
|
var FILE_NAME = "contacts.json";
|
|
39515
39584
|
var ContactStore = class {
|
|
39516
39585
|
constructor(dataDir) {
|
|
@@ -39520,10 +39589,10 @@ var ContactStore = class {
|
|
|
39520
39589
|
contacts = /* @__PURE__ */ new Map();
|
|
39521
39590
|
load() {
|
|
39522
39591
|
this.contacts.clear();
|
|
39523
|
-
const file =
|
|
39592
|
+
const file = path22.join(this.dataDir, FILE_NAME);
|
|
39524
39593
|
let raw;
|
|
39525
39594
|
try {
|
|
39526
|
-
raw =
|
|
39595
|
+
raw = fs24.readFileSync(file, "utf8");
|
|
39527
39596
|
} catch (err) {
|
|
39528
39597
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
39529
39598
|
return;
|
|
@@ -39566,20 +39635,20 @@ var ContactStore = class {
|
|
|
39566
39635
|
return existed;
|
|
39567
39636
|
}
|
|
39568
39637
|
flush() {
|
|
39569
|
-
const file =
|
|
39638
|
+
const file = path22.join(this.dataDir, FILE_NAME);
|
|
39570
39639
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39571
39640
|
const content = JSON.stringify(
|
|
39572
39641
|
{ contacts: Array.from(this.contacts.values()) },
|
|
39573
39642
|
null,
|
|
39574
39643
|
2
|
|
39575
39644
|
);
|
|
39576
|
-
|
|
39577
|
-
|
|
39578
|
-
|
|
39645
|
+
fs24.mkdirSync(this.dataDir, { recursive: true });
|
|
39646
|
+
fs24.writeFileSync(tmp, content, { mode: 384 });
|
|
39647
|
+
fs24.renameSync(tmp, file);
|
|
39579
39648
|
}
|
|
39580
39649
|
renameBak(file) {
|
|
39581
39650
|
try {
|
|
39582
|
-
|
|
39651
|
+
fs24.renameSync(file, `${file}.bak`);
|
|
39583
39652
|
} catch {
|
|
39584
39653
|
}
|
|
39585
39654
|
}
|
|
@@ -39729,61 +39798,61 @@ async function autoReverseContact(args) {
|
|
|
39729
39798
|
}
|
|
39730
39799
|
|
|
39731
39800
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
39732
|
-
var
|
|
39733
|
-
var
|
|
39801
|
+
var fs25 = __toESM(require("fs"), 1);
|
|
39802
|
+
var path23 = __toESM(require("path"), 1);
|
|
39734
39803
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
39735
39804
|
function migrateFlattenSessions(opts) {
|
|
39736
39805
|
const dataDir = opts.dataDir;
|
|
39737
39806
|
const now = opts.now ?? Date.now;
|
|
39738
|
-
const sessionsDir =
|
|
39739
|
-
const flagPath =
|
|
39807
|
+
const sessionsDir = path23.join(dataDir, "sessions");
|
|
39808
|
+
const flagPath = path23.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
39740
39809
|
if (existsSync3(flagPath)) {
|
|
39741
39810
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
39742
39811
|
}
|
|
39743
39812
|
let movedBare = 0;
|
|
39744
39813
|
let movedVmOwner = 0;
|
|
39745
39814
|
let archivedListener = 0;
|
|
39746
|
-
const defaultDir =
|
|
39815
|
+
const defaultDir = path23.join(sessionsDir, "default");
|
|
39747
39816
|
if (existsSync3(defaultDir)) {
|
|
39748
39817
|
for (const entry of readdirSafe(defaultDir)) {
|
|
39749
39818
|
if (!entry.endsWith(".json")) continue;
|
|
39750
|
-
const src =
|
|
39751
|
-
const dst =
|
|
39752
|
-
|
|
39819
|
+
const src = path23.join(defaultDir, entry);
|
|
39820
|
+
const dst = path23.join(sessionsDir, entry);
|
|
39821
|
+
fs25.renameSync(src, dst);
|
|
39753
39822
|
movedBare += 1;
|
|
39754
39823
|
}
|
|
39755
39824
|
rmdirIfEmpty(defaultDir);
|
|
39756
39825
|
}
|
|
39757
39826
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
39758
|
-
const personaDir =
|
|
39827
|
+
const personaDir = path23.join(sessionsDir, pid);
|
|
39759
39828
|
if (!isDir(personaDir)) continue;
|
|
39760
39829
|
if (pid === "default") continue;
|
|
39761
|
-
const ownerSrc =
|
|
39830
|
+
const ownerSrc = path23.join(personaDir, "owner");
|
|
39762
39831
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
39763
|
-
const ownerDst =
|
|
39764
|
-
|
|
39832
|
+
const ownerDst = path23.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
39833
|
+
fs25.mkdirSync(ownerDst, { recursive: true });
|
|
39765
39834
|
for (const file of readdirSafe(ownerSrc)) {
|
|
39766
39835
|
if (!file.endsWith(".json")) continue;
|
|
39767
|
-
|
|
39836
|
+
fs25.renameSync(path23.join(ownerSrc, file), path23.join(ownerDst, file));
|
|
39768
39837
|
movedVmOwner += 1;
|
|
39769
39838
|
}
|
|
39770
39839
|
rmdirIfEmpty(ownerSrc);
|
|
39771
39840
|
}
|
|
39772
|
-
const listenerSrc =
|
|
39841
|
+
const listenerSrc = path23.join(personaDir, "listener");
|
|
39773
39842
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
39774
|
-
const archiveDst =
|
|
39775
|
-
|
|
39843
|
+
const archiveDst = path23.join(dataDir, ".legacy", `listener-${pid}`);
|
|
39844
|
+
fs25.mkdirSync(archiveDst, { recursive: true });
|
|
39776
39845
|
for (const file of readdirSafe(listenerSrc)) {
|
|
39777
39846
|
if (!file.endsWith(".json")) continue;
|
|
39778
|
-
|
|
39847
|
+
fs25.renameSync(path23.join(listenerSrc, file), path23.join(archiveDst, file));
|
|
39779
39848
|
archivedListener += 1;
|
|
39780
39849
|
}
|
|
39781
39850
|
rmdirIfEmpty(listenerSrc);
|
|
39782
39851
|
}
|
|
39783
39852
|
rmdirIfEmpty(personaDir);
|
|
39784
39853
|
}
|
|
39785
|
-
|
|
39786
|
-
|
|
39854
|
+
fs25.mkdirSync(sessionsDir, { recursive: true });
|
|
39855
|
+
fs25.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
39787
39856
|
return {
|
|
39788
39857
|
skipped: false,
|
|
39789
39858
|
flagWritten: true,
|
|
@@ -39794,7 +39863,7 @@ function migrateFlattenSessions(opts) {
|
|
|
39794
39863
|
}
|
|
39795
39864
|
function existsSync3(p2) {
|
|
39796
39865
|
try {
|
|
39797
|
-
|
|
39866
|
+
fs25.statSync(p2);
|
|
39798
39867
|
return true;
|
|
39799
39868
|
} catch {
|
|
39800
39869
|
return false;
|
|
@@ -39802,31 +39871,31 @@ function existsSync3(p2) {
|
|
|
39802
39871
|
}
|
|
39803
39872
|
function isDir(p2) {
|
|
39804
39873
|
try {
|
|
39805
|
-
return
|
|
39874
|
+
return fs25.statSync(p2).isDirectory();
|
|
39806
39875
|
} catch {
|
|
39807
39876
|
return false;
|
|
39808
39877
|
}
|
|
39809
39878
|
}
|
|
39810
39879
|
function readdirSafe(p2) {
|
|
39811
39880
|
try {
|
|
39812
|
-
return
|
|
39881
|
+
return fs25.readdirSync(p2);
|
|
39813
39882
|
} catch {
|
|
39814
39883
|
return [];
|
|
39815
39884
|
}
|
|
39816
39885
|
}
|
|
39817
39886
|
function rmdirIfEmpty(p2) {
|
|
39818
39887
|
try {
|
|
39819
|
-
|
|
39888
|
+
fs25.rmdirSync(p2);
|
|
39820
39889
|
} catch {
|
|
39821
39890
|
}
|
|
39822
39891
|
}
|
|
39823
39892
|
|
|
39824
39893
|
// src/transport/http-router.ts
|
|
39825
|
-
var
|
|
39826
|
-
var
|
|
39894
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
39895
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
39827
39896
|
|
|
39828
39897
|
// src/attachment/mime.ts
|
|
39829
|
-
var
|
|
39898
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
39830
39899
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
39831
39900
|
var EXT_TO_NATIVE_MIME = {
|
|
39832
39901
|
// 图片
|
|
@@ -39933,7 +40002,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
39933
40002
|
".mk"
|
|
39934
40003
|
]);
|
|
39935
40004
|
function lookupMime(filePathOrName) {
|
|
39936
|
-
const ext =
|
|
40005
|
+
const ext = import_node_path16.default.extname(filePathOrName).toLowerCase();
|
|
39937
40006
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
39938
40007
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
39939
40008
|
return "application/octet-stream";
|
|
@@ -39964,11 +40033,11 @@ function signUrlParts(secret, absPath, ttlSeconds, now = Date.now) {
|
|
|
39964
40033
|
const s = base64urlEncode(computeSig(secret, absPath, e));
|
|
39965
40034
|
return { absPath, e, s };
|
|
39966
40035
|
}
|
|
39967
|
-
function buildSignedFileUrl(httpBaseUrl, parts) {
|
|
40036
|
+
function buildSignedFileUrl(httpBaseUrl, parts, prefix = "/files") {
|
|
39968
40037
|
const encodedPath = encodeAbsPathForUrl(parts.absPath);
|
|
39969
40038
|
const query = parts.e === null ? `s=${encodeURIComponent(parts.s)}` : `e=${parts.e}&s=${encodeURIComponent(parts.s)}`;
|
|
39970
40039
|
const base = httpBaseUrl.endsWith("/") ? httpBaseUrl.slice(0, -1) : httpBaseUrl;
|
|
39971
|
-
return `${base}
|
|
40040
|
+
return `${base}${prefix}${encodedPath}?${query}`;
|
|
39972
40041
|
}
|
|
39973
40042
|
function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
39974
40043
|
let e;
|
|
@@ -40002,8 +40071,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
40002
40071
|
}
|
|
40003
40072
|
|
|
40004
40073
|
// src/attachment/upload.ts
|
|
40005
|
-
var
|
|
40006
|
-
var
|
|
40074
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
40075
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
40007
40076
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
40008
40077
|
var import_promises = require("stream/promises");
|
|
40009
40078
|
var UploadError = class extends Error {
|
|
@@ -40015,22 +40084,22 @@ var UploadError = class extends Error {
|
|
|
40015
40084
|
code;
|
|
40016
40085
|
};
|
|
40017
40086
|
function assertValidFileName(fileName) {
|
|
40018
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
40087
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path17.default.basename(fileName)) {
|
|
40019
40088
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
40020
40089
|
}
|
|
40021
40090
|
}
|
|
40022
40091
|
var HASH_PREFIX_LEN = 16;
|
|
40023
40092
|
async function writeUploadedAttachment(args) {
|
|
40024
40093
|
assertValidFileName(args.fileName);
|
|
40025
|
-
const attachmentsRoot =
|
|
40094
|
+
const attachmentsRoot = import_node_path17.default.join(args.sessionDir, ".attachments");
|
|
40026
40095
|
try {
|
|
40027
|
-
|
|
40096
|
+
import_node_fs19.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
40028
40097
|
} catch (err) {
|
|
40029
40098
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
40030
40099
|
}
|
|
40031
40100
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
40032
40101
|
let actualSize = 0;
|
|
40033
|
-
const tmpPath =
|
|
40102
|
+
const tmpPath = import_node_path17.default.join(
|
|
40034
40103
|
attachmentsRoot,
|
|
40035
40104
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
40036
40105
|
);
|
|
@@ -40045,18 +40114,18 @@ async function writeUploadedAttachment(args) {
|
|
|
40045
40114
|
yield buf;
|
|
40046
40115
|
}
|
|
40047
40116
|
},
|
|
40048
|
-
|
|
40117
|
+
import_node_fs19.default.createWriteStream(tmpPath, { mode: 384 })
|
|
40049
40118
|
);
|
|
40050
40119
|
} catch (err) {
|
|
40051
40120
|
try {
|
|
40052
|
-
|
|
40121
|
+
import_node_fs19.default.unlinkSync(tmpPath);
|
|
40053
40122
|
} catch {
|
|
40054
40123
|
}
|
|
40055
40124
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
40056
40125
|
}
|
|
40057
40126
|
if (actualSize !== args.contentLength) {
|
|
40058
40127
|
try {
|
|
40059
|
-
|
|
40128
|
+
import_node_fs19.default.unlinkSync(tmpPath);
|
|
40060
40129
|
} catch {
|
|
40061
40130
|
}
|
|
40062
40131
|
throw new UploadError(
|
|
@@ -40065,35 +40134,35 @@ async function writeUploadedAttachment(args) {
|
|
|
40065
40134
|
);
|
|
40066
40135
|
}
|
|
40067
40136
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
40068
|
-
const hashDir =
|
|
40137
|
+
const hashDir = import_node_path17.default.join(attachmentsRoot, attachmentId);
|
|
40069
40138
|
let finalFileName;
|
|
40070
40139
|
let hashDirExists = false;
|
|
40071
40140
|
try {
|
|
40072
|
-
hashDirExists =
|
|
40141
|
+
hashDirExists = import_node_fs19.default.statSync(hashDir).isDirectory();
|
|
40073
40142
|
} catch {
|
|
40074
40143
|
}
|
|
40075
40144
|
if (hashDirExists) {
|
|
40076
|
-
const existing =
|
|
40145
|
+
const existing = import_node_fs19.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
40077
40146
|
finalFileName = existing[0] ?? args.fileName;
|
|
40078
40147
|
try {
|
|
40079
|
-
|
|
40148
|
+
import_node_fs19.default.unlinkSync(tmpPath);
|
|
40080
40149
|
} catch {
|
|
40081
40150
|
}
|
|
40082
40151
|
} else {
|
|
40083
40152
|
try {
|
|
40084
|
-
|
|
40153
|
+
import_node_fs19.default.mkdirSync(hashDir, { recursive: true });
|
|
40085
40154
|
finalFileName = args.fileName;
|
|
40086
|
-
|
|
40155
|
+
import_node_fs19.default.renameSync(tmpPath, import_node_path17.default.join(hashDir, finalFileName));
|
|
40087
40156
|
} catch (err) {
|
|
40088
40157
|
try {
|
|
40089
|
-
|
|
40158
|
+
import_node_fs19.default.unlinkSync(tmpPath);
|
|
40090
40159
|
} catch {
|
|
40091
40160
|
}
|
|
40092
40161
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
40093
40162
|
}
|
|
40094
40163
|
}
|
|
40095
|
-
const absPath =
|
|
40096
|
-
const relPath =
|
|
40164
|
+
const absPath = import_node_path17.default.join(hashDir, finalFileName);
|
|
40165
|
+
const relPath = import_node_path17.default.relative(args.sessionDir, absPath);
|
|
40097
40166
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
40098
40167
|
relPath: absPath,
|
|
40099
40168
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -40107,7 +40176,7 @@ async function writeUploadedAttachment(args) {
|
|
|
40107
40176
|
|
|
40108
40177
|
// src/extension/import.ts
|
|
40109
40178
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
40110
|
-
var
|
|
40179
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
40111
40180
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
40112
40181
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
40113
40182
|
var ImportError = class extends Error {
|
|
@@ -40125,7 +40194,7 @@ async function importZip(buf, root) {
|
|
|
40125
40194
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
40126
40195
|
}
|
|
40127
40196
|
for (const name of Object.keys(zip.files)) {
|
|
40128
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
40197
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path18.default.isAbsolute(name)) {
|
|
40129
40198
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
40130
40199
|
}
|
|
40131
40200
|
}
|
|
@@ -40158,7 +40227,7 @@ async function importZip(buf, root) {
|
|
|
40158
40227
|
);
|
|
40159
40228
|
}
|
|
40160
40229
|
}
|
|
40161
|
-
const destDir =
|
|
40230
|
+
const destDir = import_node_path18.default.join(root, manifest.id);
|
|
40162
40231
|
let destExists = false;
|
|
40163
40232
|
try {
|
|
40164
40233
|
await import_promises2.default.access(destDir);
|
|
@@ -40168,15 +40237,15 @@ async function importZip(buf, root) {
|
|
|
40168
40237
|
if (destExists) {
|
|
40169
40238
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
40170
40239
|
}
|
|
40171
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
40240
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path18.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
40172
40241
|
try {
|
|
40173
40242
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
40174
|
-
const dest =
|
|
40243
|
+
const dest = import_node_path18.default.join(stage, name);
|
|
40175
40244
|
if (entry.dir) {
|
|
40176
40245
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
40177
40246
|
continue;
|
|
40178
40247
|
}
|
|
40179
|
-
await import_promises2.default.mkdir(
|
|
40248
|
+
await import_promises2.default.mkdir(import_node_path18.default.dirname(dest), { recursive: true });
|
|
40180
40249
|
const content = await entry.async("nodebuffer");
|
|
40181
40250
|
await import_promises2.default.writeFile(dest, content);
|
|
40182
40251
|
}
|
|
@@ -40298,7 +40367,7 @@ function isValidUploadFileName(fileName) {
|
|
|
40298
40367
|
if (fileName === "." || fileName === "..") return false;
|
|
40299
40368
|
if (fileName.startsWith(".")) return false;
|
|
40300
40369
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
40301
|
-
return fileName ===
|
|
40370
|
+
return fileName === import_node_path19.default.basename(fileName);
|
|
40302
40371
|
}
|
|
40303
40372
|
function createHttpRouter(deps) {
|
|
40304
40373
|
return async (req, res) => {
|
|
@@ -40369,7 +40438,7 @@ function createHttpRouter(deps) {
|
|
|
40369
40438
|
sendJson(res, 403, { code: "PREVIEW_PORT_FORBIDDEN", message: "preview port not allowed" });
|
|
40370
40439
|
return true;
|
|
40371
40440
|
}
|
|
40372
|
-
if (!url.pathname.startsWith("/session/") && !url.pathname.startsWith("/files/") && url.pathname !== "/attachments/upload" && url.pathname !== "/extensions/import") {
|
|
40441
|
+
if (!url.pathname.startsWith("/session/") && !url.pathname.startsWith("/files/") && !url.pathname.startsWith("/share/md/") && url.pathname !== "/attachments/upload" && url.pathname !== "/extensions/import") {
|
|
40373
40442
|
return false;
|
|
40374
40443
|
}
|
|
40375
40444
|
if (url.pathname === "/attachments/upload" && req.method === "OPTIONS") {
|
|
@@ -40411,6 +40480,45 @@ function createHttpRouter(deps) {
|
|
|
40411
40480
|
streamFile(res, r.absPath, deps.logger);
|
|
40412
40481
|
return true;
|
|
40413
40482
|
}
|
|
40483
|
+
if (url.pathname.startsWith("/share/md/") && req.method === "GET") {
|
|
40484
|
+
const loader = deps.viewerAssetLoader;
|
|
40485
|
+
if (!loader) {
|
|
40486
|
+
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "viewer asset not loaded" });
|
|
40487
|
+
return true;
|
|
40488
|
+
}
|
|
40489
|
+
const secret = deps.getSignSecret?.();
|
|
40490
|
+
if (!secret) {
|
|
40491
|
+
sendHtml(res, 501, loader.renderErrorHtml("NOT_IMPLEMENTED", "\u5206\u4EAB\u529F\u80FD\u672A\u542F\u7528\uFF08daemon noAuth \u6A21\u5F0F\uFF09"));
|
|
40492
|
+
return true;
|
|
40493
|
+
}
|
|
40494
|
+
const encodedPath = url.pathname.slice("/share/md".length);
|
|
40495
|
+
let absPath;
|
|
40496
|
+
try {
|
|
40497
|
+
absPath = decodeAbsPathFromUrl(encodedPath);
|
|
40498
|
+
} catch {
|
|
40499
|
+
sendHtml(res, 400, loader.renderErrorHtml("MALFORMED", "\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF"));
|
|
40500
|
+
return true;
|
|
40501
|
+
}
|
|
40502
|
+
const e = url.searchParams.get("e");
|
|
40503
|
+
const s = url.searchParams.get("s") ?? "";
|
|
40504
|
+
const r = verifySignedUrl(secret, absPath, e, s);
|
|
40505
|
+
if (!r.ok) {
|
|
40506
|
+
const statusByCode = {
|
|
40507
|
+
BAD_SIG: 403,
|
|
40508
|
+
EXPIRED: 410,
|
|
40509
|
+
MALFORMED: 400
|
|
40510
|
+
};
|
|
40511
|
+
const msgByCode = {
|
|
40512
|
+
BAD_SIG: "\u94FE\u63A5\u7B7E\u540D\u65E0\u6548\uFF0C\u8BF7\u8054\u7CFB\u5206\u4EAB\u8005\u91CD\u65B0\u751F\u6210",
|
|
40513
|
+
EXPIRED: "\u94FE\u63A5\u5DF2\u8FC7\u671F\uFF0824h \u6709\u6548\u671F\u5DF2\u5230\uFF09\uFF0C\u8BF7\u8054\u7CFB\u5206\u4EAB\u8005\u91CD\u65B0\u751F\u6210",
|
|
40514
|
+
MALFORMED: "\u94FE\u63A5\u683C\u5F0F\u9519\u8BEF"
|
|
40515
|
+
};
|
|
40516
|
+
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
40517
|
+
return true;
|
|
40518
|
+
}
|
|
40519
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path19.default.basename(r.absPath)));
|
|
40520
|
+
return true;
|
|
40521
|
+
}
|
|
40414
40522
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
40415
40523
|
req.headers.authorization,
|
|
40416
40524
|
req.socket.remoteAddress ?? void 0
|
|
@@ -40529,7 +40637,7 @@ function createHttpRouter(deps) {
|
|
|
40529
40637
|
return true;
|
|
40530
40638
|
}
|
|
40531
40639
|
let absPath;
|
|
40532
|
-
if (
|
|
40640
|
+
if (import_node_path19.default.isAbsolute(pathParam)) {
|
|
40533
40641
|
absPath = pathParam;
|
|
40534
40642
|
} else if (deps.sessionStore) {
|
|
40535
40643
|
const file = deps.sessionStore.read(sid);
|
|
@@ -40537,7 +40645,7 @@ function createHttpRouter(deps) {
|
|
|
40537
40645
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
40538
40646
|
return true;
|
|
40539
40647
|
}
|
|
40540
|
-
absPath =
|
|
40648
|
+
absPath = import_node_path19.default.join(file.cwd, pathParam);
|
|
40541
40649
|
} else {
|
|
40542
40650
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
40543
40651
|
return true;
|
|
@@ -40614,13 +40722,17 @@ function sendJson(res, status, body, extraHeaders) {
|
|
|
40614
40722
|
});
|
|
40615
40723
|
res.end(JSON.stringify(body));
|
|
40616
40724
|
}
|
|
40725
|
+
function sendHtml(res, status, body) {
|
|
40726
|
+
res.writeHead(status, { "Content-Type": "text/html; charset=utf-8" });
|
|
40727
|
+
res.end(body);
|
|
40728
|
+
}
|
|
40617
40729
|
function withCtx(ctx, body) {
|
|
40618
40730
|
return { ...body, role: ctx.role };
|
|
40619
40731
|
}
|
|
40620
40732
|
function streamFile(res, absPath, logger) {
|
|
40621
40733
|
let stat;
|
|
40622
40734
|
try {
|
|
40623
|
-
stat =
|
|
40735
|
+
stat = import_node_fs20.default.statSync(absPath);
|
|
40624
40736
|
} catch (err) {
|
|
40625
40737
|
const code = err?.code;
|
|
40626
40738
|
if (code === "ENOENT") {
|
|
@@ -40635,7 +40747,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40635
40747
|
return;
|
|
40636
40748
|
}
|
|
40637
40749
|
const mime = lookupMime(absPath);
|
|
40638
|
-
const basename =
|
|
40750
|
+
const basename = import_node_path19.default.basename(absPath);
|
|
40639
40751
|
res.writeHead(200, {
|
|
40640
40752
|
"Content-Type": mime,
|
|
40641
40753
|
"Content-Length": String(stat.size),
|
|
@@ -40643,7 +40755,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40643
40755
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
40644
40756
|
"X-Content-Type-Options": "nosniff"
|
|
40645
40757
|
});
|
|
40646
|
-
const stream =
|
|
40758
|
+
const stream = import_node_fs20.default.createReadStream(absPath);
|
|
40647
40759
|
stream.on("error", (err) => {
|
|
40648
40760
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
40649
40761
|
res.destroy();
|
|
@@ -40652,8 +40764,8 @@ function streamFile(res, absPath, logger) {
|
|
|
40652
40764
|
}
|
|
40653
40765
|
|
|
40654
40766
|
// src/attachment/gc.ts
|
|
40655
|
-
var
|
|
40656
|
-
var
|
|
40767
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
40768
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
40657
40769
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
40658
40770
|
function runAttachmentGc(args) {
|
|
40659
40771
|
const now = (args.now ?? Date.now)();
|
|
@@ -40662,38 +40774,38 @@ function runAttachmentGc(args) {
|
|
|
40662
40774
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40663
40775
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
40664
40776
|
if (entry.stale) continue;
|
|
40665
|
-
if (
|
|
40777
|
+
if (import_node_path20.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
40666
40778
|
}
|
|
40667
40779
|
}
|
|
40668
40780
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40669
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
40781
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path20.default.join(
|
|
40670
40782
|
args.dataDir,
|
|
40671
40783
|
"sessions",
|
|
40672
40784
|
...scopeSubPath(scope).map(safeFileName),
|
|
40673
40785
|
safeFileName(sessionId)
|
|
40674
40786
|
);
|
|
40675
|
-
const attRoot =
|
|
40787
|
+
const attRoot = import_node_path20.default.join(sessionDir, ".attachments");
|
|
40676
40788
|
let hashDirs;
|
|
40677
40789
|
try {
|
|
40678
|
-
hashDirs =
|
|
40790
|
+
hashDirs = import_node_fs21.default.readdirSync(attRoot);
|
|
40679
40791
|
} catch (err) {
|
|
40680
40792
|
if (err.code === "ENOENT") continue;
|
|
40681
40793
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
40682
40794
|
continue;
|
|
40683
40795
|
}
|
|
40684
40796
|
for (const hashDir of hashDirs) {
|
|
40685
|
-
const hashDirAbs =
|
|
40797
|
+
const hashDirAbs = import_node_path20.default.join(attRoot, hashDir);
|
|
40686
40798
|
let files;
|
|
40687
40799
|
try {
|
|
40688
|
-
files =
|
|
40800
|
+
files = import_node_fs21.default.readdirSync(hashDirAbs);
|
|
40689
40801
|
} catch {
|
|
40690
40802
|
continue;
|
|
40691
40803
|
}
|
|
40692
40804
|
for (const name of files) {
|
|
40693
|
-
const file =
|
|
40805
|
+
const file = import_node_path20.default.join(hashDirAbs, name);
|
|
40694
40806
|
let stat;
|
|
40695
40807
|
try {
|
|
40696
|
-
stat =
|
|
40808
|
+
stat = import_node_fs21.default.statSync(file);
|
|
40697
40809
|
} catch {
|
|
40698
40810
|
continue;
|
|
40699
40811
|
}
|
|
@@ -40702,26 +40814,26 @@ function runAttachmentGc(args) {
|
|
|
40702
40814
|
if (age < ttlMs) continue;
|
|
40703
40815
|
if (liveAbs.has(file)) continue;
|
|
40704
40816
|
try {
|
|
40705
|
-
|
|
40817
|
+
import_node_fs21.default.unlinkSync(file);
|
|
40706
40818
|
} catch (err) {
|
|
40707
40819
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
40708
40820
|
}
|
|
40709
40821
|
}
|
|
40710
40822
|
try {
|
|
40711
|
-
if (
|
|
40823
|
+
if (import_node_fs21.default.readdirSync(hashDirAbs).length === 0) import_node_fs21.default.rmdirSync(hashDirAbs);
|
|
40712
40824
|
} catch {
|
|
40713
40825
|
}
|
|
40714
40826
|
}
|
|
40715
40827
|
try {
|
|
40716
|
-
if (
|
|
40828
|
+
if (import_node_fs21.default.readdirSync(attRoot).length === 0) import_node_fs21.default.rmdirSync(attRoot);
|
|
40717
40829
|
} catch {
|
|
40718
40830
|
}
|
|
40719
40831
|
}
|
|
40720
40832
|
}
|
|
40721
40833
|
|
|
40722
40834
|
// src/attachment/group.ts
|
|
40723
|
-
var
|
|
40724
|
-
var
|
|
40835
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40836
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40725
40837
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
40726
40838
|
init_protocol();
|
|
40727
40839
|
var GroupFileStore = class {
|
|
@@ -40733,11 +40845,11 @@ var GroupFileStore = class {
|
|
|
40733
40845
|
this.logger = opts.logger;
|
|
40734
40846
|
}
|
|
40735
40847
|
rootForScope(scope) {
|
|
40736
|
-
return
|
|
40848
|
+
return import_node_path21.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
40737
40849
|
}
|
|
40738
40850
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
40739
40851
|
filePath(scope, sessionId) {
|
|
40740
|
-
return
|
|
40852
|
+
return import_node_path21.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
40741
40853
|
}
|
|
40742
40854
|
cacheKey(scope, sessionId) {
|
|
40743
40855
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -40746,7 +40858,7 @@ var GroupFileStore = class {
|
|
|
40746
40858
|
readFile(scope, sessionId) {
|
|
40747
40859
|
const file = this.filePath(scope, sessionId);
|
|
40748
40860
|
try {
|
|
40749
|
-
const raw =
|
|
40861
|
+
const raw = import_node_fs22.default.readFileSync(file, "utf8");
|
|
40750
40862
|
const parsed = JSON.parse(raw);
|
|
40751
40863
|
if (!Array.isArray(parsed)) {
|
|
40752
40864
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -40772,10 +40884,10 @@ var GroupFileStore = class {
|
|
|
40772
40884
|
}
|
|
40773
40885
|
writeFile(scope, sessionId, entries) {
|
|
40774
40886
|
const file = this.filePath(scope, sessionId);
|
|
40775
|
-
|
|
40887
|
+
import_node_fs22.default.mkdirSync(import_node_path21.default.dirname(file), { recursive: true });
|
|
40776
40888
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
40777
|
-
|
|
40778
|
-
|
|
40889
|
+
import_node_fs22.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
40890
|
+
import_node_fs22.default.renameSync(tmp, file);
|
|
40779
40891
|
}
|
|
40780
40892
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
40781
40893
|
list(scope, sessionId) {
|
|
@@ -40861,10 +40973,10 @@ var GroupFileStore = class {
|
|
|
40861
40973
|
};
|
|
40862
40974
|
|
|
40863
40975
|
// src/discovery/state-file.ts
|
|
40864
|
-
var
|
|
40865
|
-
var
|
|
40976
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40977
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40866
40978
|
function defaultStateFilePath(dataDir) {
|
|
40867
|
-
return
|
|
40979
|
+
return import_node_path22.default.join(dataDir, "state.json");
|
|
40868
40980
|
}
|
|
40869
40981
|
function isPidAlive(pid) {
|
|
40870
40982
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -40886,7 +40998,7 @@ var StateFileManager = class {
|
|
|
40886
40998
|
}
|
|
40887
40999
|
read() {
|
|
40888
41000
|
try {
|
|
40889
|
-
const raw =
|
|
41001
|
+
const raw = import_node_fs23.default.readFileSync(this.file, "utf8");
|
|
40890
41002
|
const parsed = JSON.parse(raw);
|
|
40891
41003
|
return parsed;
|
|
40892
41004
|
} catch {
|
|
@@ -40900,20 +41012,20 @@ var StateFileManager = class {
|
|
|
40900
41012
|
return { status: "stale", existing };
|
|
40901
41013
|
}
|
|
40902
41014
|
write(state) {
|
|
40903
|
-
|
|
41015
|
+
import_node_fs23.default.mkdirSync(import_node_path22.default.dirname(this.file), { recursive: true });
|
|
40904
41016
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
40905
|
-
|
|
40906
|
-
|
|
41017
|
+
import_node_fs23.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
41018
|
+
import_node_fs23.default.renameSync(tmp, this.file);
|
|
40907
41019
|
if (process.platform !== "win32") {
|
|
40908
41020
|
try {
|
|
40909
|
-
|
|
41021
|
+
import_node_fs23.default.chmodSync(this.file, 384);
|
|
40910
41022
|
} catch {
|
|
40911
41023
|
}
|
|
40912
41024
|
}
|
|
40913
41025
|
}
|
|
40914
41026
|
delete() {
|
|
40915
41027
|
try {
|
|
40916
|
-
|
|
41028
|
+
import_node_fs23.default.unlinkSync(this.file);
|
|
40917
41029
|
} catch {
|
|
40918
41030
|
}
|
|
40919
41031
|
}
|
|
@@ -40928,14 +41040,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
40928
41040
|
}
|
|
40929
41041
|
|
|
40930
41042
|
// src/tunnel/tunnel-manager.ts
|
|
40931
|
-
var
|
|
40932
|
-
var
|
|
41043
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
41044
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
40933
41045
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
40934
41046
|
var import_node_child_process9 = require("child_process");
|
|
40935
41047
|
|
|
40936
41048
|
// src/tunnel/tunnel-store.ts
|
|
40937
|
-
var
|
|
40938
|
-
var
|
|
41049
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
41050
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
40939
41051
|
var TunnelStore = class {
|
|
40940
41052
|
constructor(filePath) {
|
|
40941
41053
|
this.filePath = filePath;
|
|
@@ -40943,7 +41055,7 @@ var TunnelStore = class {
|
|
|
40943
41055
|
filePath;
|
|
40944
41056
|
async get() {
|
|
40945
41057
|
try {
|
|
40946
|
-
const raw = await
|
|
41058
|
+
const raw = await import_node_fs24.default.promises.readFile(this.filePath, "utf8");
|
|
40947
41059
|
const obj = JSON.parse(raw);
|
|
40948
41060
|
if (!isPersistedTunnel(obj)) return null;
|
|
40949
41061
|
return obj;
|
|
@@ -40954,22 +41066,22 @@ var TunnelStore = class {
|
|
|
40954
41066
|
}
|
|
40955
41067
|
}
|
|
40956
41068
|
async set(v2) {
|
|
40957
|
-
const dir =
|
|
40958
|
-
await
|
|
41069
|
+
const dir = import_node_path23.default.dirname(this.filePath);
|
|
41070
|
+
await import_node_fs24.default.promises.mkdir(dir, { recursive: true });
|
|
40959
41071
|
const data = JSON.stringify(v2, null, 2);
|
|
40960
41072
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
40961
|
-
await
|
|
41073
|
+
await import_node_fs24.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
40962
41074
|
if (process.platform !== "win32") {
|
|
40963
41075
|
try {
|
|
40964
|
-
await
|
|
41076
|
+
await import_node_fs24.default.promises.chmod(tmp, 384);
|
|
40965
41077
|
} catch {
|
|
40966
41078
|
}
|
|
40967
41079
|
}
|
|
40968
|
-
await
|
|
41080
|
+
await import_node_fs24.default.promises.rename(tmp, this.filePath);
|
|
40969
41081
|
}
|
|
40970
41082
|
async clear() {
|
|
40971
41083
|
try {
|
|
40972
|
-
await
|
|
41084
|
+
await import_node_fs24.default.promises.unlink(this.filePath);
|
|
40973
41085
|
} catch (err) {
|
|
40974
41086
|
const code = err?.code;
|
|
40975
41087
|
if (code !== "ENOENT") throw err;
|
|
@@ -41064,9 +41176,9 @@ function escape(v2) {
|
|
|
41064
41176
|
}
|
|
41065
41177
|
|
|
41066
41178
|
// src/tunnel/frpc-binary.ts
|
|
41067
|
-
var
|
|
41179
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
41068
41180
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
41069
|
-
var
|
|
41181
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
41070
41182
|
var import_node_child_process7 = require("child_process");
|
|
41071
41183
|
var import_node_stream3 = require("stream");
|
|
41072
41184
|
var import_promises3 = require("stream/promises");
|
|
@@ -41098,20 +41210,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
41098
41210
|
}
|
|
41099
41211
|
async function ensureFrpcBinary(opts) {
|
|
41100
41212
|
if (opts.override) {
|
|
41101
|
-
if (!
|
|
41213
|
+
if (!import_node_fs25.default.existsSync(opts.override)) {
|
|
41102
41214
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
41103
41215
|
}
|
|
41104
41216
|
return opts.override;
|
|
41105
41217
|
}
|
|
41106
41218
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
41107
41219
|
const platform = opts.platform ?? detectPlatform();
|
|
41108
|
-
const binDir =
|
|
41109
|
-
|
|
41220
|
+
const binDir = import_node_path24.default.join(opts.dataDir, "bin");
|
|
41221
|
+
import_node_fs25.default.mkdirSync(binDir, { recursive: true });
|
|
41110
41222
|
cleanupStaleArtifacts(binDir);
|
|
41111
|
-
const stableBin =
|
|
41112
|
-
if (
|
|
41223
|
+
const stableBin = import_node_path24.default.join(binDir, "frpc");
|
|
41224
|
+
if (import_node_fs25.default.existsSync(stableBin)) return stableBin;
|
|
41113
41225
|
const partialBin = `${stableBin}.partial`;
|
|
41114
|
-
const tarballPath =
|
|
41226
|
+
const tarballPath = import_node_path24.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
41115
41227
|
try {
|
|
41116
41228
|
const url = frpcDownloadUrl(version2, platform);
|
|
41117
41229
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -41120,8 +41232,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
41120
41232
|
} else {
|
|
41121
41233
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
41122
41234
|
}
|
|
41123
|
-
|
|
41124
|
-
|
|
41235
|
+
import_node_fs25.default.chmodSync(partialBin, 493);
|
|
41236
|
+
import_node_fs25.default.renameSync(partialBin, stableBin);
|
|
41125
41237
|
} finally {
|
|
41126
41238
|
safeUnlink(tarballPath);
|
|
41127
41239
|
safeUnlink(partialBin);
|
|
@@ -41131,15 +41243,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
41131
41243
|
function cleanupStaleArtifacts(binDir) {
|
|
41132
41244
|
let entries;
|
|
41133
41245
|
try {
|
|
41134
|
-
entries =
|
|
41246
|
+
entries = import_node_fs25.default.readdirSync(binDir);
|
|
41135
41247
|
} catch {
|
|
41136
41248
|
return;
|
|
41137
41249
|
}
|
|
41138
41250
|
for (const name of entries) {
|
|
41139
41251
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
41140
|
-
const full =
|
|
41252
|
+
const full = import_node_path24.default.join(binDir, name);
|
|
41141
41253
|
try {
|
|
41142
|
-
|
|
41254
|
+
import_node_fs25.default.rmSync(full, { recursive: true, force: true });
|
|
41143
41255
|
} catch {
|
|
41144
41256
|
}
|
|
41145
41257
|
}
|
|
@@ -41147,7 +41259,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
41147
41259
|
}
|
|
41148
41260
|
function safeUnlink(p2) {
|
|
41149
41261
|
try {
|
|
41150
|
-
|
|
41262
|
+
import_node_fs25.default.unlinkSync(p2);
|
|
41151
41263
|
} catch {
|
|
41152
41264
|
}
|
|
41153
41265
|
}
|
|
@@ -41158,13 +41270,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
41158
41270
|
if (!res.ok || !res.body) {
|
|
41159
41271
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
41160
41272
|
}
|
|
41161
|
-
const out =
|
|
41273
|
+
const out = import_node_fs25.default.createWriteStream(dest);
|
|
41162
41274
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
41163
41275
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
41164
41276
|
}
|
|
41165
41277
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
41166
|
-
const work =
|
|
41167
|
-
|
|
41278
|
+
const work = import_node_path24.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
41279
|
+
import_node_fs25.default.mkdirSync(work, { recursive: true });
|
|
41168
41280
|
try {
|
|
41169
41281
|
await new Promise((resolve6, reject) => {
|
|
41170
41282
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -41172,32 +41284,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
41172
41284
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
41173
41285
|
});
|
|
41174
41286
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
41175
|
-
const src =
|
|
41176
|
-
if (!
|
|
41287
|
+
const src = import_node_path24.default.join(work, dirName, "frpc");
|
|
41288
|
+
if (!import_node_fs25.default.existsSync(src)) {
|
|
41177
41289
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
41178
41290
|
}
|
|
41179
|
-
|
|
41291
|
+
import_node_fs25.default.copyFileSync(src, destBin);
|
|
41180
41292
|
} finally {
|
|
41181
|
-
|
|
41293
|
+
import_node_fs25.default.rmSync(work, { recursive: true, force: true });
|
|
41182
41294
|
}
|
|
41183
41295
|
}
|
|
41184
41296
|
|
|
41185
41297
|
// src/tunnel/frpc-process.ts
|
|
41186
|
-
var
|
|
41187
|
-
var
|
|
41298
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
41299
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
41188
41300
|
var import_node_child_process8 = require("child_process");
|
|
41189
41301
|
function frpcPidFilePath(dataDir) {
|
|
41190
|
-
return
|
|
41302
|
+
return import_node_path25.default.join(dataDir, "frpc.pid");
|
|
41191
41303
|
}
|
|
41192
41304
|
function writeFrpcPid(dataDir, pid) {
|
|
41193
41305
|
try {
|
|
41194
|
-
|
|
41306
|
+
import_node_fs26.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
41195
41307
|
} catch {
|
|
41196
41308
|
}
|
|
41197
41309
|
}
|
|
41198
41310
|
function clearFrpcPid(dataDir) {
|
|
41199
41311
|
try {
|
|
41200
|
-
|
|
41312
|
+
import_node_fs26.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
41201
41313
|
} catch {
|
|
41202
41314
|
}
|
|
41203
41315
|
}
|
|
@@ -41213,7 +41325,7 @@ function defaultIsPidAlive(pid) {
|
|
|
41213
41325
|
}
|
|
41214
41326
|
function defaultReadPidFile(file) {
|
|
41215
41327
|
try {
|
|
41216
|
-
return
|
|
41328
|
+
return import_node_fs26.default.readFileSync(file, "utf8");
|
|
41217
41329
|
} catch {
|
|
41218
41330
|
return null;
|
|
41219
41331
|
}
|
|
@@ -41229,7 +41341,7 @@ function defaultSleep(ms) {
|
|
|
41229
41341
|
}
|
|
41230
41342
|
async function killStaleFrpc(deps) {
|
|
41231
41343
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
41232
|
-
const tomlPath =
|
|
41344
|
+
const tomlPath = import_node_path25.default.join(deps.dataDir, "frpc.toml");
|
|
41233
41345
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
41234
41346
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
41235
41347
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -41253,7 +41365,7 @@ async function killStaleFrpc(deps) {
|
|
|
41253
41365
|
}
|
|
41254
41366
|
if (victims.size === 0) {
|
|
41255
41367
|
try {
|
|
41256
|
-
|
|
41368
|
+
import_node_fs26.default.unlinkSync(pidFile);
|
|
41257
41369
|
} catch {
|
|
41258
41370
|
}
|
|
41259
41371
|
return;
|
|
@@ -41264,7 +41376,7 @@ async function killStaleFrpc(deps) {
|
|
|
41264
41376
|
}
|
|
41265
41377
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
41266
41378
|
try {
|
|
41267
|
-
|
|
41379
|
+
import_node_fs26.default.unlinkSync(pidFile);
|
|
41268
41380
|
} catch {
|
|
41269
41381
|
}
|
|
41270
41382
|
}
|
|
@@ -41301,7 +41413,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
41301
41413
|
var TunnelManager = class {
|
|
41302
41414
|
constructor(deps) {
|
|
41303
41415
|
this.deps = deps;
|
|
41304
|
-
this.store = deps.store ?? new TunnelStore(
|
|
41416
|
+
this.store = deps.store ?? new TunnelStore(import_node_path26.default.join(deps.dataDir, "tunnel.json"));
|
|
41305
41417
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
41306
41418
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
41307
41419
|
}
|
|
@@ -41428,7 +41540,7 @@ var TunnelManager = class {
|
|
|
41428
41540
|
dataDir: this.deps.dataDir,
|
|
41429
41541
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
41430
41542
|
});
|
|
41431
|
-
const tomlPath =
|
|
41543
|
+
const tomlPath = import_node_path26.default.join(this.deps.dataDir, "frpc.toml");
|
|
41432
41544
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
41433
41545
|
const toml = buildFrpcToml({
|
|
41434
41546
|
serverAddr: t.frpsHost,
|
|
@@ -41439,12 +41551,12 @@ var TunnelManager = class {
|
|
|
41439
41551
|
localPort,
|
|
41440
41552
|
logLevel: "info"
|
|
41441
41553
|
});
|
|
41442
|
-
await
|
|
41554
|
+
await import_node_fs27.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
41443
41555
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
41444
41556
|
stdio: ["ignore", "pipe", "pipe"]
|
|
41445
41557
|
});
|
|
41446
|
-
const logFilePath =
|
|
41447
|
-
const logStream =
|
|
41558
|
+
const logFilePath = import_node_path26.default.join(this.deps.dataDir, "frpc.log");
|
|
41559
|
+
const logStream = import_node_fs27.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
41448
41560
|
logStream.on("error", () => {
|
|
41449
41561
|
});
|
|
41450
41562
|
const tee = (chunk) => {
|
|
@@ -41527,27 +41639,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
41527
41639
|
|
|
41528
41640
|
// src/tunnel/device-key.ts
|
|
41529
41641
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
41530
|
-
var
|
|
41642
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
41531
41643
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
41532
41644
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
41533
41645
|
function deriveStableDeviceKey(opts = {}) {
|
|
41534
41646
|
const hostname = opts.hostname ?? import_node_os13.default.hostname();
|
|
41535
41647
|
const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
|
|
41536
41648
|
const home = opts.home ?? import_node_os13.default.homedir();
|
|
41537
|
-
const defaultDataDir =
|
|
41538
|
-
const normalizedDataDir = opts.dataDir ?
|
|
41649
|
+
const defaultDataDir = import_node_path27.default.resolve(import_node_path27.default.join(home, ".clawd"));
|
|
41650
|
+
const normalizedDataDir = opts.dataDir ? import_node_path27.default.resolve(opts.dataDir) : null;
|
|
41539
41651
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
41540
41652
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
41541
41653
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
41542
41654
|
}
|
|
41543
41655
|
|
|
41544
41656
|
// src/auth-store.ts
|
|
41545
|
-
var
|
|
41546
|
-
var
|
|
41657
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41658
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
41547
41659
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
41548
41660
|
var AUTH_FILE_NAME = "auth.json";
|
|
41549
41661
|
function authFilePath(dataDir) {
|
|
41550
|
-
return
|
|
41662
|
+
return import_node_path28.default.join(dataDir, AUTH_FILE_NAME);
|
|
41551
41663
|
}
|
|
41552
41664
|
function loadOrCreateAuthFile(opts) {
|
|
41553
41665
|
const file = authFilePath(opts.dataDir);
|
|
@@ -41581,7 +41693,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
41581
41693
|
}
|
|
41582
41694
|
function readAuthFile(file) {
|
|
41583
41695
|
try {
|
|
41584
|
-
const raw =
|
|
41696
|
+
const raw = import_node_fs28.default.readFileSync(file, "utf8");
|
|
41585
41697
|
const parsed = JSON.parse(raw);
|
|
41586
41698
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
41587
41699
|
return null;
|
|
@@ -41600,25 +41712,25 @@ function readAuthFile(file) {
|
|
|
41600
41712
|
}
|
|
41601
41713
|
}
|
|
41602
41714
|
function writeAuthFile(file, content) {
|
|
41603
|
-
|
|
41604
|
-
|
|
41715
|
+
import_node_fs28.default.mkdirSync(import_node_path28.default.dirname(file), { recursive: true });
|
|
41716
|
+
import_node_fs28.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
41605
41717
|
try {
|
|
41606
|
-
|
|
41718
|
+
import_node_fs28.default.chmodSync(file, 384);
|
|
41607
41719
|
} catch {
|
|
41608
41720
|
}
|
|
41609
41721
|
}
|
|
41610
41722
|
|
|
41611
41723
|
// src/owner-profile.ts
|
|
41612
|
-
var
|
|
41724
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41613
41725
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
41614
|
-
var
|
|
41726
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
41615
41727
|
var PROFILE_FILENAME = "profile.json";
|
|
41616
41728
|
function loadOwnerDisplayName(dataDir) {
|
|
41617
41729
|
const fallback = import_node_os14.default.userInfo().username;
|
|
41618
|
-
const profilePath =
|
|
41730
|
+
const profilePath = import_node_path29.default.join(dataDir, PROFILE_FILENAME);
|
|
41619
41731
|
let raw;
|
|
41620
41732
|
try {
|
|
41621
|
-
raw =
|
|
41733
|
+
raw = import_node_fs29.default.readFileSync(profilePath, "utf8");
|
|
41622
41734
|
} catch {
|
|
41623
41735
|
return fallback;
|
|
41624
41736
|
}
|
|
@@ -41641,18 +41753,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
41641
41753
|
}
|
|
41642
41754
|
|
|
41643
41755
|
// src/feishu-auth/owner-identity-store.ts
|
|
41644
|
-
var
|
|
41645
|
-
var
|
|
41756
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
41757
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
41646
41758
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
41647
41759
|
var OwnerIdentityStore = class {
|
|
41648
41760
|
file;
|
|
41649
41761
|
constructor(dataDir) {
|
|
41650
|
-
this.file =
|
|
41762
|
+
this.file = import_node_path30.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
41651
41763
|
}
|
|
41652
41764
|
read() {
|
|
41653
41765
|
let raw;
|
|
41654
41766
|
try {
|
|
41655
|
-
raw =
|
|
41767
|
+
raw = import_node_fs30.default.readFileSync(this.file, "utf8");
|
|
41656
41768
|
} catch {
|
|
41657
41769
|
return null;
|
|
41658
41770
|
}
|
|
@@ -41680,16 +41792,16 @@ var OwnerIdentityStore = class {
|
|
|
41680
41792
|
};
|
|
41681
41793
|
}
|
|
41682
41794
|
write(record) {
|
|
41683
|
-
|
|
41684
|
-
|
|
41795
|
+
import_node_fs30.default.mkdirSync(import_node_path30.default.dirname(this.file), { recursive: true });
|
|
41796
|
+
import_node_fs30.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
41685
41797
|
try {
|
|
41686
|
-
|
|
41798
|
+
import_node_fs30.default.chmodSync(this.file, 384);
|
|
41687
41799
|
} catch {
|
|
41688
41800
|
}
|
|
41689
41801
|
}
|
|
41690
41802
|
clear() {
|
|
41691
41803
|
try {
|
|
41692
|
-
|
|
41804
|
+
import_node_fs30.default.unlinkSync(this.file);
|
|
41693
41805
|
} catch (err) {
|
|
41694
41806
|
const code = err?.code;
|
|
41695
41807
|
if (code !== "ENOENT") throw err;
|
|
@@ -41810,9 +41922,9 @@ var CentralClientError = class extends Error {
|
|
|
41810
41922
|
code;
|
|
41811
41923
|
cause;
|
|
41812
41924
|
};
|
|
41813
|
-
async function centralRequest(opts,
|
|
41925
|
+
async function centralRequest(opts, path60, init) {
|
|
41814
41926
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
41815
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
41927
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path60}`;
|
|
41816
41928
|
const ctrl = new AbortController();
|
|
41817
41929
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
41818
41930
|
let res;
|
|
@@ -41954,8 +42066,8 @@ function verifyConnectToken(args) {
|
|
|
41954
42066
|
}
|
|
41955
42067
|
|
|
41956
42068
|
// src/feishu-auth/server-key.ts
|
|
41957
|
-
var
|
|
41958
|
-
var
|
|
42069
|
+
var fs39 = __toESM(require("fs"), 1);
|
|
42070
|
+
var path39 = __toESM(require("path"), 1);
|
|
41959
42071
|
var FILE_NAME2 = "server-signing-key.json";
|
|
41960
42072
|
var ServerKeyStore = class {
|
|
41961
42073
|
constructor(dataDir) {
|
|
@@ -41963,12 +42075,12 @@ var ServerKeyStore = class {
|
|
|
41963
42075
|
}
|
|
41964
42076
|
dataDir;
|
|
41965
42077
|
filePath() {
|
|
41966
|
-
return
|
|
42078
|
+
return path39.join(this.dataDir, FILE_NAME2);
|
|
41967
42079
|
}
|
|
41968
42080
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
41969
42081
|
read() {
|
|
41970
42082
|
try {
|
|
41971
|
-
const raw =
|
|
42083
|
+
const raw = fs39.readFileSync(this.filePath(), "utf8");
|
|
41972
42084
|
const parsed = JSON.parse(raw);
|
|
41973
42085
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
41974
42086
|
return parsed.publicKeyPem;
|
|
@@ -41983,12 +42095,12 @@ var ServerKeyStore = class {
|
|
|
41983
42095
|
publicKeyPem,
|
|
41984
42096
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
41985
42097
|
};
|
|
41986
|
-
|
|
41987
|
-
|
|
42098
|
+
fs39.mkdirSync(this.dataDir, { recursive: true });
|
|
42099
|
+
fs39.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
41988
42100
|
}
|
|
41989
42101
|
clear() {
|
|
41990
42102
|
try {
|
|
41991
|
-
|
|
42103
|
+
fs39.unlinkSync(this.filePath());
|
|
41992
42104
|
} catch {
|
|
41993
42105
|
}
|
|
41994
42106
|
}
|
|
@@ -42001,12 +42113,12 @@ init_protocol();
|
|
|
42001
42113
|
init_protocol();
|
|
42002
42114
|
|
|
42003
42115
|
// src/session/fork.ts
|
|
42004
|
-
var
|
|
42116
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
42005
42117
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
42006
|
-
var
|
|
42118
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
42007
42119
|
init_claude_history();
|
|
42008
42120
|
function readJsonlEntries(file) {
|
|
42009
|
-
const raw =
|
|
42121
|
+
const raw = import_node_fs31.default.readFileSync(file, "utf8");
|
|
42010
42122
|
const out = [];
|
|
42011
42123
|
for (const line of raw.split("\n")) {
|
|
42012
42124
|
const t = line.trim();
|
|
@@ -42019,10 +42131,10 @@ function readJsonlEntries(file) {
|
|
|
42019
42131
|
return out;
|
|
42020
42132
|
}
|
|
42021
42133
|
function forkSession(input) {
|
|
42022
|
-
const baseDir = input.baseDir ??
|
|
42023
|
-
const projectDir =
|
|
42024
|
-
const sourceFile =
|
|
42025
|
-
if (!
|
|
42134
|
+
const baseDir = input.baseDir ?? import_node_path31.default.join(import_node_os15.default.homedir(), ".claude");
|
|
42135
|
+
const projectDir = import_node_path31.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
42136
|
+
const sourceFile = import_node_path31.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
42137
|
+
if (!import_node_fs31.default.existsSync(sourceFile)) {
|
|
42026
42138
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
42027
42139
|
}
|
|
42028
42140
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -42052,9 +42164,9 @@ function forkSession(input) {
|
|
|
42052
42164
|
}
|
|
42053
42165
|
forkedLines.push(JSON.stringify(forked));
|
|
42054
42166
|
}
|
|
42055
|
-
const forkedFilePath =
|
|
42056
|
-
|
|
42057
|
-
|
|
42167
|
+
const forkedFilePath = import_node_path31.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
42168
|
+
import_node_fs31.default.mkdirSync(projectDir, { recursive: true });
|
|
42169
|
+
import_node_fs31.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
42058
42170
|
return { forkedToolSessionId, forkedFilePath };
|
|
42059
42171
|
}
|
|
42060
42172
|
|
|
@@ -42430,7 +42542,7 @@ function buildPermissionHandlers(deps) {
|
|
|
42430
42542
|
}
|
|
42431
42543
|
|
|
42432
42544
|
// src/handlers/history.ts
|
|
42433
|
-
var
|
|
42545
|
+
var path42 = __toESM(require("path"), 1);
|
|
42434
42546
|
init_protocol();
|
|
42435
42547
|
|
|
42436
42548
|
// src/session/recent-dirs.ts
|
|
@@ -42448,7 +42560,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
42448
42560
|
}
|
|
42449
42561
|
|
|
42450
42562
|
// src/permission/persona-paths.ts
|
|
42451
|
-
var
|
|
42563
|
+
var path41 = __toESM(require("path"), 1);
|
|
42452
42564
|
function getAllowedPersonaIds(grants, action) {
|
|
42453
42565
|
const ids = /* @__PURE__ */ new Set();
|
|
42454
42566
|
for (const g2 of grants) {
|
|
@@ -42461,31 +42573,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
42461
42573
|
return ids;
|
|
42462
42574
|
}
|
|
42463
42575
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
42464
|
-
const target =
|
|
42576
|
+
const target = path41.resolve(absPath);
|
|
42465
42577
|
if (userWorkDir) {
|
|
42466
|
-
const u =
|
|
42467
|
-
const usep = u.endsWith(
|
|
42578
|
+
const u = path41.resolve(userWorkDir);
|
|
42579
|
+
const usep = u.endsWith(path41.sep) ? "" : path41.sep;
|
|
42468
42580
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
42469
42581
|
}
|
|
42470
|
-
const root =
|
|
42471
|
-
const sep3 = root.endsWith(
|
|
42582
|
+
const root = path41.resolve(personaRoot);
|
|
42583
|
+
const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
|
|
42472
42584
|
if (!target.startsWith(root + sep3)) return false;
|
|
42473
|
-
const rel =
|
|
42585
|
+
const rel = path41.relative(root, target);
|
|
42474
42586
|
if (!rel || rel.startsWith("..")) return false;
|
|
42475
|
-
const personaId = rel.split(
|
|
42587
|
+
const personaId = rel.split(path41.sep)[0];
|
|
42476
42588
|
if (!personaId) return false;
|
|
42477
42589
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
42478
42590
|
if (allowed === "*") return true;
|
|
42479
42591
|
return allowed.has(personaId);
|
|
42480
42592
|
}
|
|
42481
42593
|
function personaIdFromPath(absPath, personaRoot) {
|
|
42482
|
-
const root =
|
|
42483
|
-
const target =
|
|
42484
|
-
const sep3 = root.endsWith(
|
|
42594
|
+
const root = path41.resolve(personaRoot);
|
|
42595
|
+
const target = path41.resolve(absPath);
|
|
42596
|
+
const sep3 = root.endsWith(path41.sep) ? "" : path41.sep;
|
|
42485
42597
|
if (!target.startsWith(root + sep3)) return null;
|
|
42486
|
-
const rel =
|
|
42598
|
+
const rel = path41.relative(root, target);
|
|
42487
42599
|
if (!rel || rel.startsWith("..")) return null;
|
|
42488
|
-
const id = rel.split(
|
|
42600
|
+
const id = rel.split(path41.sep)[0];
|
|
42489
42601
|
return id || null;
|
|
42490
42602
|
}
|
|
42491
42603
|
|
|
@@ -42512,7 +42624,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42512
42624
|
if (!pid) return false;
|
|
42513
42625
|
return isGuestPathAllowed(
|
|
42514
42626
|
ctx.grants,
|
|
42515
|
-
|
|
42627
|
+
path42.join(personaRoot, pid),
|
|
42516
42628
|
personaRoot,
|
|
42517
42629
|
"read",
|
|
42518
42630
|
userWorkDir
|
|
@@ -42524,7 +42636,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42524
42636
|
};
|
|
42525
42637
|
const list = async (frame, _client, ctx) => {
|
|
42526
42638
|
const args = HistoryListArgs.parse(frame);
|
|
42527
|
-
assertGuestPath(ctx,
|
|
42639
|
+
assertGuestPath(ctx, path42.resolve(args.projectPath), personaRoot, "history:list");
|
|
42528
42640
|
const sessions = await history.listSessions(args);
|
|
42529
42641
|
return { response: { type: "history:list", sessions } };
|
|
42530
42642
|
};
|
|
@@ -42556,13 +42668,13 @@ function buildHistoryHandlers(deps) {
|
|
|
42556
42668
|
};
|
|
42557
42669
|
const subagents = async (frame, _client, ctx) => {
|
|
42558
42670
|
const args = HistorySubagentsArgs.parse(frame);
|
|
42559
|
-
assertGuestPath(ctx,
|
|
42671
|
+
assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
42560
42672
|
const subs = await history.listSubagents(args);
|
|
42561
42673
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
42562
42674
|
};
|
|
42563
42675
|
const subagentRead = async (frame, _client, ctx) => {
|
|
42564
42676
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
42565
|
-
assertGuestPath(ctx,
|
|
42677
|
+
assertGuestPath(ctx, path42.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
42566
42678
|
const res = await history.readSubagent(args);
|
|
42567
42679
|
return { response: { type: "history:subagent-read", ...res } };
|
|
42568
42680
|
};
|
|
@@ -42571,7 +42683,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42571
42683
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
42572
42684
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42573
42685
|
const filtered = dirs.filter(
|
|
42574
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
42686
|
+
(d) => isGuestPathAllowed(ctx.grants, path42.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
42575
42687
|
);
|
|
42576
42688
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
42577
42689
|
}
|
|
@@ -42588,7 +42700,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42588
42700
|
}
|
|
42589
42701
|
|
|
42590
42702
|
// src/handlers/workspace.ts
|
|
42591
|
-
var
|
|
42703
|
+
var path43 = __toESM(require("path"), 1);
|
|
42592
42704
|
var os15 = __toESM(require("os"), 1);
|
|
42593
42705
|
init_protocol();
|
|
42594
42706
|
init_protocol();
|
|
@@ -42630,22 +42742,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42630
42742
|
const args = WorkspaceListArgs.parse(frame);
|
|
42631
42743
|
const isGuest = ctx?.principal.kind === "guest";
|
|
42632
42744
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
42633
|
-
const resolvedCwd =
|
|
42634
|
-
const target = args.path ?
|
|
42745
|
+
const resolvedCwd = path43.resolve(args.cwd ?? fallbackCwd);
|
|
42746
|
+
const target = args.path ? path43.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
42635
42747
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
42636
42748
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
42637
42749
|
return { response: { type: "workspace:list", ...res } };
|
|
42638
42750
|
};
|
|
42639
42751
|
const read = async (frame, _client, ctx) => {
|
|
42640
42752
|
const args = WorkspaceReadArgs.parse(frame);
|
|
42641
|
-
const target =
|
|
42753
|
+
const target = path43.isAbsolute(args.path) ? path43.resolve(args.path) : path43.resolve(args.cwd, args.path);
|
|
42642
42754
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
42643
42755
|
const res = workspace.read(args);
|
|
42644
42756
|
return { response: { type: "workspace:read", ...res } };
|
|
42645
42757
|
};
|
|
42646
42758
|
const skillsList = async (frame, _client, ctx) => {
|
|
42647
42759
|
const args = SkillsListArgs.parse(frame);
|
|
42648
|
-
const cwdAbs =
|
|
42760
|
+
const cwdAbs = path43.resolve(args.cwd);
|
|
42649
42761
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
42650
42762
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
42651
42763
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -42657,7 +42769,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42657
42769
|
};
|
|
42658
42770
|
const agentsList = async (frame, _client, ctx) => {
|
|
42659
42771
|
const args = AgentsListArgs.parse(frame);
|
|
42660
|
-
const cwdAbs =
|
|
42772
|
+
const cwdAbs = path43.resolve(args.cwd);
|
|
42661
42773
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
42662
42774
|
if (args.tool === "codex") {
|
|
42663
42775
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -42679,20 +42791,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42679
42791
|
}
|
|
42680
42792
|
|
|
42681
42793
|
// src/handlers/git.ts
|
|
42682
|
-
var
|
|
42794
|
+
var path45 = __toESM(require("path"), 1);
|
|
42683
42795
|
init_protocol();
|
|
42684
42796
|
init_protocol();
|
|
42685
42797
|
|
|
42686
42798
|
// src/workspace/git.ts
|
|
42687
42799
|
var import_node_child_process10 = require("child_process");
|
|
42688
|
-
var
|
|
42689
|
-
var
|
|
42800
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
42801
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
42690
42802
|
var import_node_util = require("util");
|
|
42691
42803
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
42692
42804
|
function normalizePath(p2) {
|
|
42693
|
-
const resolved =
|
|
42805
|
+
const resolved = import_node_path32.default.resolve(p2);
|
|
42694
42806
|
try {
|
|
42695
|
-
return
|
|
42807
|
+
return import_node_fs32.default.realpathSync(resolved);
|
|
42696
42808
|
} catch {
|
|
42697
42809
|
return resolved;
|
|
42698
42810
|
}
|
|
@@ -42766,7 +42878,7 @@ async function listGitBranches(cwd) {
|
|
|
42766
42878
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
42767
42879
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
42768
42880
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42769
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
42881
|
+
if (!isGuestPathAllowed(ctx.grants, path45.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
42770
42882
|
throw new ClawdError(
|
|
42771
42883
|
ERROR_CODES.UNAUTHORIZED,
|
|
42772
42884
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -43283,7 +43395,7 @@ function buildPersonaHandlers(deps) {
|
|
|
43283
43395
|
}
|
|
43284
43396
|
|
|
43285
43397
|
// src/handlers/attachment.ts
|
|
43286
|
-
var
|
|
43398
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
43287
43399
|
init_protocol();
|
|
43288
43400
|
init_protocol();
|
|
43289
43401
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -43338,12 +43450,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
43338
43450
|
`session ${args.sessionId} scope unresolved`
|
|
43339
43451
|
);
|
|
43340
43452
|
}
|
|
43341
|
-
const cwdAbs =
|
|
43342
|
-
const candidateAbs =
|
|
43453
|
+
const cwdAbs = import_node_path33.default.resolve(sessionFile.cwd);
|
|
43454
|
+
const candidateAbs = import_node_path33.default.isAbsolute(args.relPath) ? import_node_path33.default.resolve(args.relPath) : import_node_path33.default.resolve(cwdAbs, args.relPath);
|
|
43343
43455
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
43344
43456
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
43345
43457
|
const entry = entries.find((e) => {
|
|
43346
|
-
const storedAbs =
|
|
43458
|
+
const storedAbs = import_node_path33.default.isAbsolute(e.relPath) ? import_node_path33.default.resolve(e.relPath) : import_node_path33.default.resolve(cwdAbs, e.relPath);
|
|
43347
43459
|
return storedAbs === candidateAbs && !e.stale;
|
|
43348
43460
|
});
|
|
43349
43461
|
if (!entry) {
|
|
@@ -43354,7 +43466,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
43354
43466
|
}
|
|
43355
43467
|
const ttl = args.ttlSeconds === null ? null : args.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
43356
43468
|
const parts = signUrlParts(secret, candidateAbs, ttl);
|
|
43357
|
-
const
|
|
43469
|
+
const prefix = args.view === "md-rendered" ? "/share/md" : "/files";
|
|
43470
|
+
const url = buildSignedFileUrl(httpBaseUrl, parts, prefix);
|
|
43358
43471
|
return {
|
|
43359
43472
|
response: {
|
|
43360
43473
|
type: "attachment.signUrl",
|
|
@@ -43367,7 +43480,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
43367
43480
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
43368
43481
|
const f = deps.sessionStore.read(sessionId);
|
|
43369
43482
|
if (!f) return;
|
|
43370
|
-
assertGuestAttachmentPath(ctx,
|
|
43483
|
+
assertGuestAttachmentPath(ctx, import_node_path33.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
43371
43484
|
}
|
|
43372
43485
|
const groupAdd = async (frame, _client, ctx) => {
|
|
43373
43486
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -43439,19 +43552,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
43439
43552
|
|
|
43440
43553
|
// src/handlers/extension.ts
|
|
43441
43554
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
43442
|
-
var
|
|
43555
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
43443
43556
|
init_protocol();
|
|
43444
43557
|
|
|
43445
43558
|
// src/extension/bundle-zip.ts
|
|
43446
43559
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
43447
|
-
var
|
|
43560
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
43448
43561
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
43449
43562
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
43450
43563
|
async function bundleExtensionDir(dir) {
|
|
43451
43564
|
const entries = await listFilesSorted(dir);
|
|
43452
43565
|
const zip = new import_jszip2.default();
|
|
43453
43566
|
for (const rel of entries) {
|
|
43454
|
-
const abs =
|
|
43567
|
+
const abs = import_node_path34.default.join(dir, rel);
|
|
43455
43568
|
const content = await import_promises4.default.readFile(abs);
|
|
43456
43569
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
43457
43570
|
}
|
|
@@ -43472,7 +43585,7 @@ async function listFilesSorted(rootDir) {
|
|
|
43472
43585
|
return out;
|
|
43473
43586
|
}
|
|
43474
43587
|
async function walk(absRoot, relPrefix, out) {
|
|
43475
|
-
const dirAbs =
|
|
43588
|
+
const dirAbs = import_node_path34.default.join(absRoot, relPrefix);
|
|
43476
43589
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
43477
43590
|
for (const e of entries) {
|
|
43478
43591
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -43526,25 +43639,25 @@ function computePublishCheck(args) {
|
|
|
43526
43639
|
|
|
43527
43640
|
// src/extension/install-flow.ts
|
|
43528
43641
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
43529
|
-
var
|
|
43642
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
43530
43643
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
43531
43644
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
43532
43645
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
43533
43646
|
|
|
43534
43647
|
// src/extension/paths.ts
|
|
43535
43648
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
43536
|
-
var
|
|
43649
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
43537
43650
|
function clawdHomeRoot(override) {
|
|
43538
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
43651
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path35.default.join(import_node_os17.default.homedir(), ".clawd");
|
|
43539
43652
|
}
|
|
43540
43653
|
function extensionsRoot(override) {
|
|
43541
|
-
return
|
|
43654
|
+
return import_node_path35.default.join(clawdHomeRoot(override), "extensions");
|
|
43542
43655
|
}
|
|
43543
43656
|
function publishedChannelsFile(override) {
|
|
43544
|
-
return
|
|
43657
|
+
return import_node_path35.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
43545
43658
|
}
|
|
43546
43659
|
function bundleCacheRoot(override) {
|
|
43547
|
-
return
|
|
43660
|
+
return import_node_path35.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
43548
43661
|
}
|
|
43549
43662
|
|
|
43550
43663
|
// src/extension/install-flow.ts
|
|
@@ -43571,7 +43684,7 @@ async function installFromChannel(args, deps) {
|
|
|
43571
43684
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43572
43685
|
}
|
|
43573
43686
|
for (const name of Object.keys(zip.files)) {
|
|
43574
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43687
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
|
|
43575
43688
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43576
43689
|
}
|
|
43577
43690
|
}
|
|
@@ -43603,7 +43716,7 @@ async function installFromChannel(args, deps) {
|
|
|
43603
43716
|
);
|
|
43604
43717
|
}
|
|
43605
43718
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
43606
|
-
const destDir =
|
|
43719
|
+
const destDir = import_node_path36.default.join(deps.extensionsRoot, localExtId);
|
|
43607
43720
|
let destExists = false;
|
|
43608
43721
|
try {
|
|
43609
43722
|
await import_promises5.default.access(destDir);
|
|
@@ -43617,16 +43730,16 @@ async function installFromChannel(args, deps) {
|
|
|
43617
43730
|
);
|
|
43618
43731
|
}
|
|
43619
43732
|
const stage = await import_promises5.default.mkdtemp(
|
|
43620
|
-
|
|
43733
|
+
import_node_path36.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
43621
43734
|
);
|
|
43622
43735
|
try {
|
|
43623
43736
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43624
|
-
const dest =
|
|
43737
|
+
const dest = import_node_path36.default.join(stage, name);
|
|
43625
43738
|
if (entry.dir) {
|
|
43626
43739
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
43627
43740
|
continue;
|
|
43628
43741
|
}
|
|
43629
|
-
await import_promises5.default.mkdir(
|
|
43742
|
+
await import_promises5.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
|
|
43630
43743
|
if (name === "manifest.json") {
|
|
43631
43744
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43632
43745
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43647,7 +43760,7 @@ async function installFromChannel(args, deps) {
|
|
|
43647
43760
|
|
|
43648
43761
|
// src/extension/update-flow.ts
|
|
43649
43762
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
43650
|
-
var
|
|
43763
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
43651
43764
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
43652
43765
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
43653
43766
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -43664,11 +43777,11 @@ async function updateFromChannel(args, deps) {
|
|
|
43664
43777
|
channelRef.extId,
|
|
43665
43778
|
channelRef.ownerPrincipalId
|
|
43666
43779
|
);
|
|
43667
|
-
const liveDir =
|
|
43780
|
+
const liveDir = import_node_path37.default.join(deps.extensionsRoot, localExtId);
|
|
43668
43781
|
const prevDir = `${liveDir}.prev`;
|
|
43669
43782
|
let existingVersion;
|
|
43670
43783
|
try {
|
|
43671
|
-
const raw = await import_promises6.default.readFile(
|
|
43784
|
+
const raw = await import_promises6.default.readFile(import_node_path37.default.join(liveDir, "manifest.json"), "utf8");
|
|
43672
43785
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
43673
43786
|
if (!parsed2.success) {
|
|
43674
43787
|
throw new UpdateError(
|
|
@@ -43701,7 +43814,7 @@ async function updateFromChannel(args, deps) {
|
|
|
43701
43814
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43702
43815
|
}
|
|
43703
43816
|
for (const name of Object.keys(zip.files)) {
|
|
43704
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43817
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
|
|
43705
43818
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43706
43819
|
}
|
|
43707
43820
|
}
|
|
@@ -43736,16 +43849,16 @@ async function updateFromChannel(args, deps) {
|
|
|
43736
43849
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
43737
43850
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
43738
43851
|
const stage = await import_promises6.default.mkdtemp(
|
|
43739
|
-
|
|
43852
|
+
import_node_path37.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
43740
43853
|
);
|
|
43741
43854
|
try {
|
|
43742
43855
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43743
|
-
const dest =
|
|
43856
|
+
const dest = import_node_path37.default.join(stage, name);
|
|
43744
43857
|
if (entry.dir) {
|
|
43745
43858
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
43746
43859
|
continue;
|
|
43747
43860
|
}
|
|
43748
|
-
await import_promises6.default.mkdir(
|
|
43861
|
+
await import_promises6.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
|
|
43749
43862
|
if (name === "manifest.json") {
|
|
43750
43863
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43751
43864
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43838,7 +43951,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43838
43951
|
);
|
|
43839
43952
|
}
|
|
43840
43953
|
}
|
|
43841
|
-
const manifestPath =
|
|
43954
|
+
const manifestPath = import_node_path38.default.join(root, extId, "manifest.json");
|
|
43842
43955
|
const manifest = await readManifest(root, extId);
|
|
43843
43956
|
const next = { ...manifest, version: newVersion };
|
|
43844
43957
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -43846,7 +43959,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
43846
43959
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
43847
43960
|
}
|
|
43848
43961
|
async function readManifest(root, extId) {
|
|
43849
|
-
const file =
|
|
43962
|
+
const file = import_node_path38.default.join(root, extId, "manifest.json");
|
|
43850
43963
|
let raw;
|
|
43851
43964
|
try {
|
|
43852
43965
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -43937,7 +44050,7 @@ function buildExtensionHandlers(deps) {
|
|
|
43937
44050
|
};
|
|
43938
44051
|
async function buildSnapshotMeta(extId) {
|
|
43939
44052
|
const manifest = await readManifest(deps.root, extId);
|
|
43940
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
44053
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path38.default.join(deps.root, extId));
|
|
43941
44054
|
return { manifest, contentHash: sha256, buffer };
|
|
43942
44055
|
}
|
|
43943
44056
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -44118,9 +44231,9 @@ function buildExtensionHandlers(deps) {
|
|
|
44118
44231
|
}
|
|
44119
44232
|
|
|
44120
44233
|
// src/app-builder/project-store.ts
|
|
44121
|
-
var
|
|
44234
|
+
var import_node_fs33 = require("fs");
|
|
44122
44235
|
var import_node_child_process11 = require("child_process");
|
|
44123
|
-
var
|
|
44236
|
+
var import_node_path39 = require("path");
|
|
44124
44237
|
init_protocol();
|
|
44125
44238
|
var PROJECTS_DIR = "projects";
|
|
44126
44239
|
var META_FILE = ".clawd-project.json";
|
|
@@ -44134,19 +44247,19 @@ var ProjectStore = class {
|
|
|
44134
44247
|
root;
|
|
44135
44248
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
44136
44249
|
metaPath(name) {
|
|
44137
|
-
return (0,
|
|
44250
|
+
return (0, import_node_path39.join)(this.projectsRoot(), name, META_FILE);
|
|
44138
44251
|
}
|
|
44139
44252
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
44140
44253
|
projectDir(name) {
|
|
44141
|
-
return (0,
|
|
44254
|
+
return (0, import_node_path39.join)(this.projectsRoot(), name);
|
|
44142
44255
|
}
|
|
44143
44256
|
projectsRoot() {
|
|
44144
|
-
return (0,
|
|
44257
|
+
return (0, import_node_path39.join)(this.root, PROJECTS_DIR);
|
|
44145
44258
|
}
|
|
44146
44259
|
async list() {
|
|
44147
44260
|
let entries;
|
|
44148
44261
|
try {
|
|
44149
|
-
entries = await
|
|
44262
|
+
entries = await import_node_fs33.promises.readdir(this.projectsRoot());
|
|
44150
44263
|
} catch (err) {
|
|
44151
44264
|
if (err.code === "ENOENT") return [];
|
|
44152
44265
|
throw err;
|
|
@@ -44154,7 +44267,7 @@ var ProjectStore = class {
|
|
|
44154
44267
|
const out = [];
|
|
44155
44268
|
for (const name of entries) {
|
|
44156
44269
|
try {
|
|
44157
|
-
const raw = await
|
|
44270
|
+
const raw = await import_node_fs33.promises.readFile(this.metaPath(name), "utf8");
|
|
44158
44271
|
const json = JSON.parse(raw);
|
|
44159
44272
|
let migrated = false;
|
|
44160
44273
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -44165,7 +44278,7 @@ var ProjectStore = class {
|
|
|
44165
44278
|
if (parsed.success) {
|
|
44166
44279
|
out.push(parsed.data);
|
|
44167
44280
|
if (migrated) {
|
|
44168
|
-
void
|
|
44281
|
+
void import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
44169
44282
|
});
|
|
44170
44283
|
}
|
|
44171
44284
|
}
|
|
@@ -44209,8 +44322,8 @@ var ProjectStore = class {
|
|
|
44209
44322
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
44210
44323
|
}
|
|
44211
44324
|
const dir = this.projectDir(name);
|
|
44212
|
-
await
|
|
44213
|
-
await
|
|
44325
|
+
await import_node_fs33.promises.mkdir(dir, { recursive: true });
|
|
44326
|
+
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
44214
44327
|
return meta;
|
|
44215
44328
|
}
|
|
44216
44329
|
/**
|
|
@@ -44253,7 +44366,7 @@ var ProjectStore = class {
|
|
|
44253
44366
|
}
|
|
44254
44367
|
async delete(name) {
|
|
44255
44368
|
const dir = this.projectDir(name);
|
|
44256
|
-
await
|
|
44369
|
+
await import_node_fs33.promises.rm(dir, { recursive: true, force: true });
|
|
44257
44370
|
}
|
|
44258
44371
|
async updatePort(name, newPort) {
|
|
44259
44372
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -44269,7 +44382,7 @@ var ProjectStore = class {
|
|
|
44269
44382
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
44270
44383
|
}
|
|
44271
44384
|
const updated = { ...target, port: newPort };
|
|
44272
|
-
await
|
|
44385
|
+
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
44273
44386
|
return updated;
|
|
44274
44387
|
}
|
|
44275
44388
|
/**
|
|
@@ -44286,7 +44399,7 @@ var ProjectStore = class {
|
|
|
44286
44399
|
if (!validated.success) {
|
|
44287
44400
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
44288
44401
|
}
|
|
44289
|
-
await
|
|
44402
|
+
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44290
44403
|
return validated.data;
|
|
44291
44404
|
}
|
|
44292
44405
|
/**
|
|
@@ -44307,7 +44420,7 @@ var ProjectStore = class {
|
|
|
44307
44420
|
if (!validated.success) {
|
|
44308
44421
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
44309
44422
|
}
|
|
44310
|
-
await
|
|
44423
|
+
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44311
44424
|
return validated.data;
|
|
44312
44425
|
}
|
|
44313
44426
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -44322,7 +44435,7 @@ var ProjectStore = class {
|
|
|
44322
44435
|
if (!validated.success) {
|
|
44323
44436
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
44324
44437
|
}
|
|
44325
|
-
await
|
|
44438
|
+
await import_node_fs33.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44326
44439
|
return validated.data;
|
|
44327
44440
|
}
|
|
44328
44441
|
};
|
|
@@ -44443,8 +44556,8 @@ var PublishJobRegistry = class {
|
|
|
44443
44556
|
|
|
44444
44557
|
// src/app-builder/publish-job-runner.ts
|
|
44445
44558
|
var import_node_child_process13 = require("child_process");
|
|
44446
|
-
var
|
|
44447
|
-
var
|
|
44559
|
+
var import_node_fs34 = require("fs");
|
|
44560
|
+
var import_node_path40 = require("path");
|
|
44448
44561
|
|
|
44449
44562
|
// src/app-builder/publish-stage-parser.ts
|
|
44450
44563
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -44476,10 +44589,10 @@ async function startPublishJob(deps, args) {
|
|
|
44476
44589
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
44477
44590
|
}
|
|
44478
44591
|
const projDir = projectDir(args.name);
|
|
44479
|
-
const logPath = (0,
|
|
44592
|
+
const logPath = (0, import_node_path40.join)(projDir, ".publish.log");
|
|
44480
44593
|
let logStream = null;
|
|
44481
44594
|
try {
|
|
44482
|
-
logStream = (0,
|
|
44595
|
+
logStream = (0, import_node_fs34.createWriteStream)(logPath, { flags: "w" });
|
|
44483
44596
|
} catch {
|
|
44484
44597
|
logStream = null;
|
|
44485
44598
|
}
|
|
@@ -44736,8 +44849,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
44736
44849
|
|
|
44737
44850
|
// src/handlers/app-builder.ts
|
|
44738
44851
|
init_protocol();
|
|
44739
|
-
var
|
|
44740
|
-
var
|
|
44852
|
+
var import_node_path41 = require("path");
|
|
44853
|
+
var import_node_fs35 = require("fs");
|
|
44741
44854
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
44742
44855
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
44743
44856
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -44818,7 +44931,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44818
44931
|
async function listAllUsersProjects() {
|
|
44819
44932
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
44820
44933
|
const getStore = deps.getStore;
|
|
44821
|
-
const userIds = await
|
|
44934
|
+
const userIds = await import_node_fs35.promises.readdir(deps.usersRoot).catch(() => []);
|
|
44822
44935
|
const perUser = await Promise.all(
|
|
44823
44936
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
44824
44937
|
);
|
|
@@ -44894,8 +45007,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44894
45007
|
const project = await userStore.create(f.name, reservedPorts);
|
|
44895
45008
|
try {
|
|
44896
45009
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
44897
|
-
const templateSrcDir = (0,
|
|
44898
|
-
const scaffoldScript = (0,
|
|
45010
|
+
const templateSrcDir = (0, import_node_path41.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
45011
|
+
const scaffoldScript = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
44899
45012
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
44900
45013
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
44901
45014
|
name: project.name,
|
|
@@ -45116,7 +45229,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
45116
45229
|
await userStore.clearPublishJob(args.name);
|
|
45117
45230
|
}
|
|
45118
45231
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
45119
|
-
const scriptPath = (0,
|
|
45232
|
+
const scriptPath = (0, import_node_path41.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
45120
45233
|
deps.logger?.info("app-builder.publish.start", {
|
|
45121
45234
|
name: args.name,
|
|
45122
45235
|
sessionId: boundSession.sessionId,
|
|
@@ -45212,7 +45325,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
45212
45325
|
|
|
45213
45326
|
// src/extension/registry.ts
|
|
45214
45327
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
45215
|
-
var
|
|
45328
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
45216
45329
|
async function loadAll(root) {
|
|
45217
45330
|
let entries;
|
|
45218
45331
|
try {
|
|
@@ -45225,13 +45338,13 @@ async function loadAll(root) {
|
|
|
45225
45338
|
for (const ent of entries) {
|
|
45226
45339
|
if (!ent.isDirectory()) continue;
|
|
45227
45340
|
if (ent.name.startsWith(".")) continue;
|
|
45228
|
-
records.push(await loadOne(
|
|
45341
|
+
records.push(await loadOne(import_node_path42.default.join(root, ent.name), ent.name));
|
|
45229
45342
|
}
|
|
45230
45343
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
45231
45344
|
return records;
|
|
45232
45345
|
}
|
|
45233
45346
|
async function loadOne(dir, dirName) {
|
|
45234
|
-
const manifestPath =
|
|
45347
|
+
const manifestPath = import_node_path42.default.join(dir, "manifest.json");
|
|
45235
45348
|
let raw;
|
|
45236
45349
|
try {
|
|
45237
45350
|
raw = await import_promises8.default.readFile(manifestPath, "utf8");
|
|
@@ -45276,7 +45389,7 @@ async function loadOne(dir, dirName) {
|
|
|
45276
45389
|
|
|
45277
45390
|
// src/extension/uninstall.ts
|
|
45278
45391
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
45279
|
-
var
|
|
45392
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
45280
45393
|
var UninstallError = class extends Error {
|
|
45281
45394
|
constructor(code, message) {
|
|
45282
45395
|
super(message);
|
|
@@ -45285,7 +45398,7 @@ var UninstallError = class extends Error {
|
|
|
45285
45398
|
code;
|
|
45286
45399
|
};
|
|
45287
45400
|
async function uninstall(deps) {
|
|
45288
|
-
const dir =
|
|
45401
|
+
const dir = import_node_path43.default.join(deps.root, deps.extId);
|
|
45289
45402
|
try {
|
|
45290
45403
|
await import_promises9.default.access(dir);
|
|
45291
45404
|
} catch {
|
|
@@ -45796,7 +45909,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
45796
45909
|
|
|
45797
45910
|
// src/extension/runtime.ts
|
|
45798
45911
|
var import_node_child_process15 = require("child_process");
|
|
45799
|
-
var
|
|
45912
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45800
45913
|
var import_promises10 = require("timers/promises");
|
|
45801
45914
|
|
|
45802
45915
|
// src/extension/port-allocator.ts
|
|
@@ -45897,7 +46010,7 @@ var Runtime = class {
|
|
|
45897
46010
|
/\$CLAWOS_EXT_PORT/g,
|
|
45898
46011
|
String(port)
|
|
45899
46012
|
);
|
|
45900
|
-
const dir =
|
|
46013
|
+
const dir = import_node_path44.default.join(this.root, extId);
|
|
45901
46014
|
const env = {
|
|
45902
46015
|
...process.env,
|
|
45903
46016
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -46009,7 +46122,7 @@ ${handle.stderrTail}`
|
|
|
46009
46122
|
|
|
46010
46123
|
// src/extension/published-channels.ts
|
|
46011
46124
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
46012
|
-
var
|
|
46125
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
46013
46126
|
init_zod();
|
|
46014
46127
|
var PublishedChannelsError = class extends Error {
|
|
46015
46128
|
constructor(code, message) {
|
|
@@ -46108,7 +46221,7 @@ var PublishedChannelStore = class {
|
|
|
46108
46221
|
)
|
|
46109
46222
|
};
|
|
46110
46223
|
const tmp = `${this.filePath}.tmp`;
|
|
46111
|
-
await import_promises11.default.mkdir(
|
|
46224
|
+
await import_promises11.default.mkdir(import_node_path45.default.dirname(this.filePath), { recursive: true });
|
|
46112
46225
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
46113
46226
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
46114
46227
|
}
|
|
@@ -46116,7 +46229,7 @@ var PublishedChannelStore = class {
|
|
|
46116
46229
|
|
|
46117
46230
|
// src/extension/bundle-cache.ts
|
|
46118
46231
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
46119
|
-
var
|
|
46232
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
46120
46233
|
var BundleCache = class {
|
|
46121
46234
|
constructor(rootDir) {
|
|
46122
46235
|
this.rootDir = rootDir;
|
|
@@ -46125,14 +46238,14 @@ var BundleCache = class {
|
|
|
46125
46238
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
46126
46239
|
async write(snapshotHash, buffer) {
|
|
46127
46240
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
46128
|
-
const file =
|
|
46241
|
+
const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46129
46242
|
const tmp = `${file}.tmp`;
|
|
46130
46243
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
46131
46244
|
await import_promises12.default.rename(tmp, file);
|
|
46132
46245
|
}
|
|
46133
46246
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
46134
46247
|
async read(snapshotHash) {
|
|
46135
|
-
const file =
|
|
46248
|
+
const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46136
46249
|
try {
|
|
46137
46250
|
return await import_promises12.default.readFile(file);
|
|
46138
46251
|
} catch (e) {
|
|
@@ -46142,13 +46255,13 @@ var BundleCache = class {
|
|
|
46142
46255
|
}
|
|
46143
46256
|
/** Idempotent — missing file is not an error. */
|
|
46144
46257
|
async delete(snapshotHash) {
|
|
46145
|
-
const file =
|
|
46258
|
+
const file = import_node_path46.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46146
46259
|
await import_promises12.default.rm(file, { force: true });
|
|
46147
46260
|
}
|
|
46148
46261
|
};
|
|
46149
46262
|
|
|
46150
46263
|
// src/index.ts
|
|
46151
|
-
var
|
|
46264
|
+
var import_meta5 = {};
|
|
46152
46265
|
async function startDaemon(config) {
|
|
46153
46266
|
const authFile = loadOrCreateAuthFile({ dataDir: config.dataDir });
|
|
46154
46267
|
const logShippingCfg = config.logShipping ?? { endpoint: null, sampling: {}, mode: "off" };
|
|
@@ -46167,7 +46280,7 @@ async function startDaemon(config) {
|
|
|
46167
46280
|
});
|
|
46168
46281
|
const logger = createLogger({
|
|
46169
46282
|
level: config.logLevel,
|
|
46170
|
-
file:
|
|
46283
|
+
file: import_node_path47.default.join(config.dataDir, "clawd.log"),
|
|
46171
46284
|
logClient
|
|
46172
46285
|
});
|
|
46173
46286
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
@@ -46303,8 +46416,8 @@ async function startDaemon(config) {
|
|
|
46303
46416
|
const agents = new AgentsScanner();
|
|
46304
46417
|
const history = new ClaudeHistoryReader();
|
|
46305
46418
|
let transport = null;
|
|
46306
|
-
const personaStore = new PersonaStore(
|
|
46307
|
-
const usersRoot =
|
|
46419
|
+
const personaStore = new PersonaStore(import_node_path47.default.join(config.dataDir, "personas"));
|
|
46420
|
+
const usersRoot = import_node_path47.default.join(config.dataDir, "users");
|
|
46308
46421
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
46309
46422
|
if (defaultsRoot) {
|
|
46310
46423
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -46324,17 +46437,17 @@ async function startDaemon(config) {
|
|
|
46324
46437
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
46325
46438
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
46326
46439
|
const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
|
|
46327
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
46440
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path47.default.dirname((0, import_node_url3.fileURLToPath)(import_meta5.url));
|
|
46328
46441
|
const dispatchServerCandidates = [
|
|
46329
|
-
|
|
46442
|
+
import_node_path47.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
46330
46443
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
46331
|
-
|
|
46444
|
+
import_node_path47.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
46332
46445
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
46333
46446
|
];
|
|
46334
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
46447
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs36.default.existsSync(p2));
|
|
46335
46448
|
let dispatchMcpConfigPath2;
|
|
46336
46449
|
if (dispatchServerScriptPath) {
|
|
46337
|
-
const dispatchLogPath =
|
|
46450
|
+
const dispatchLogPath = import_node_path47.default.join(config.dataDir, "dispatch-mcp-server.log");
|
|
46338
46451
|
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
46339
46452
|
dataDir: config.dataDir,
|
|
46340
46453
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -46359,7 +46472,7 @@ async function startDaemon(config) {
|
|
|
46359
46472
|
getAdapter,
|
|
46360
46473
|
historyReader: history,
|
|
46361
46474
|
dataDir: config.dataDir,
|
|
46362
|
-
personaRoot:
|
|
46475
|
+
personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
|
|
46363
46476
|
usersRoot,
|
|
46364
46477
|
personaStore,
|
|
46365
46478
|
ownerDisplayName,
|
|
@@ -46395,10 +46508,10 @@ async function startDaemon(config) {
|
|
|
46395
46508
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
46396
46509
|
attachmentGroup: {
|
|
46397
46510
|
onFileEdit: (input) => {
|
|
46398
|
-
const absPath =
|
|
46511
|
+
const absPath = import_node_path47.default.isAbsolute(input.relPath) ? input.relPath : import_node_path47.default.join(input.cwd, input.relPath);
|
|
46399
46512
|
let size = 0;
|
|
46400
46513
|
try {
|
|
46401
|
-
size =
|
|
46514
|
+
size = import_node_fs36.default.statSync(absPath).size;
|
|
46402
46515
|
} catch (err) {
|
|
46403
46516
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
46404
46517
|
sessionId: input.sessionId,
|
|
@@ -46584,11 +46697,11 @@ async function startDaemon(config) {
|
|
|
46584
46697
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
46585
46698
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
46586
46699
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
46587
|
-
personaRoot:
|
|
46700
|
+
personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
|
|
46588
46701
|
usersRoot
|
|
46589
46702
|
},
|
|
46590
46703
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
46591
|
-
personaRoot:
|
|
46704
|
+
personaRoot: import_node_path47.default.join(config.dataDir, "personas"),
|
|
46592
46705
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
46593
46706
|
usersRoot,
|
|
46594
46707
|
// capability:list / delete handler 依赖
|
|
@@ -46695,11 +46808,11 @@ async function startDaemon(config) {
|
|
|
46695
46808
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
46696
46809
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
46697
46810
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
46698
|
-
appBuilderPersonaRoot:
|
|
46811
|
+
appBuilderPersonaRoot: import_node_path47.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
46699
46812
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
46700
|
-
deployKitRoot:
|
|
46813
|
+
deployKitRoot: import_node_path47.default.join(config.dataDir, "deploy-kit"),
|
|
46701
46814
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
46702
|
-
resolvePersonaRoot: (personaId) =>
|
|
46815
|
+
resolvePersonaRoot: (personaId) => import_node_path47.default.join(config.dataDir, "personas", personaId),
|
|
46703
46816
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
46704
46817
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
46705
46818
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -46733,7 +46846,7 @@ async function startDaemon(config) {
|
|
|
46733
46846
|
if (!sourceFile) {
|
|
46734
46847
|
throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
|
|
46735
46848
|
}
|
|
46736
|
-
const sourceJsonlPath = sourceFile.toolSessionId ?
|
|
46849
|
+
const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path47.default.join(
|
|
46737
46850
|
import_node_os20.default.homedir(),
|
|
46738
46851
|
".claude",
|
|
46739
46852
|
"projects",
|
|
@@ -46769,12 +46882,14 @@ async function startDaemon(config) {
|
|
|
46769
46882
|
return result.response;
|
|
46770
46883
|
}
|
|
46771
46884
|
};
|
|
46885
|
+
const viewerAssetLoader = tryLoadViewerAssets(logger);
|
|
46772
46886
|
const httpRouter = createHttpRouter({
|
|
46773
46887
|
authResolver,
|
|
46774
46888
|
daemonVersion: version,
|
|
46775
46889
|
logger,
|
|
46776
46890
|
sessionStore: store,
|
|
46777
46891
|
rpcDispatcher,
|
|
46892
|
+
...viewerAssetLoader ? { viewerAssetLoader } : {},
|
|
46778
46893
|
// /files HMAC verify 用 auth.json 的 signSecret 字段(与 attachment.signUrl 同源)。
|
|
46779
46894
|
// --auth-token CLI 模式没 signSecret → 路由返 501,sign URL 功能整体禁用。
|
|
46780
46895
|
getSignSecret: () => authFile?.signSecret ?? null,
|
|
@@ -46987,8 +47102,8 @@ async function startDaemon(config) {
|
|
|
46987
47102
|
const lines = [
|
|
46988
47103
|
`Tunnel: ${r.url}`,
|
|
46989
47104
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
46990
|
-
`Frpc config: ${
|
|
46991
|
-
`Frpc log: ${
|
|
47105
|
+
`Frpc config: ${import_node_path47.default.join(config.dataDir, "frpc.toml")}`,
|
|
47106
|
+
`Frpc log: ${import_node_path47.default.join(config.dataDir, "frpc.log")}`
|
|
46992
47107
|
];
|
|
46993
47108
|
const width = Math.max(...lines.map((l) => l.length));
|
|
46994
47109
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -47001,8 +47116,8 @@ ${bar}
|
|
|
47001
47116
|
|
|
47002
47117
|
`);
|
|
47003
47118
|
try {
|
|
47004
|
-
const connectPath =
|
|
47005
|
-
|
|
47119
|
+
const connectPath = import_node_path47.default.join(config.dataDir, "connect.txt");
|
|
47120
|
+
import_node_fs36.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
47006
47121
|
} catch {
|
|
47007
47122
|
}
|
|
47008
47123
|
} catch (err) {
|
|
@@ -47074,9 +47189,9 @@ ${bar}
|
|
|
47074
47189
|
};
|
|
47075
47190
|
}
|
|
47076
47191
|
function migrateDropPersonsDir(dataDir) {
|
|
47077
|
-
const dir =
|
|
47192
|
+
const dir = import_node_path47.default.join(dataDir, "persons");
|
|
47078
47193
|
try {
|
|
47079
|
-
|
|
47194
|
+
import_node_fs36.default.rmSync(dir, { recursive: true, force: true });
|
|
47080
47195
|
} catch {
|
|
47081
47196
|
}
|
|
47082
47197
|
}
|