@clawos-dev/clawd 0.2.64-beta.104.6f4b611 → 0.2.64-beta.106.42f5a70
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 +252 -499
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -617,8 +617,8 @@ var init_parseUtil = __esm({
|
|
|
617
617
|
init_errors2();
|
|
618
618
|
init_en();
|
|
619
619
|
makeIssue = (params) => {
|
|
620
|
-
const { data, path:
|
|
621
|
-
const fullPath = [...
|
|
620
|
+
const { data, path: path33, errorMaps, issueData } = params;
|
|
621
|
+
const fullPath = [...path33, ...issueData.path || []];
|
|
622
622
|
const fullIssue = {
|
|
623
623
|
...issueData,
|
|
624
624
|
path: fullPath
|
|
@@ -929,11 +929,11 @@ var init_types = __esm({
|
|
|
929
929
|
init_parseUtil();
|
|
930
930
|
init_util();
|
|
931
931
|
ParseInputLazyPath = class {
|
|
932
|
-
constructor(parent, value,
|
|
932
|
+
constructor(parent, value, path33, key) {
|
|
933
933
|
this._cachedPath = [];
|
|
934
934
|
this.parent = parent;
|
|
935
935
|
this.data = value;
|
|
936
|
-
this._path =
|
|
936
|
+
this._path = path33;
|
|
937
937
|
this._key = key;
|
|
938
938
|
}
|
|
939
939
|
get path() {
|
|
@@ -4323,7 +4323,7 @@ var init_attachment_schemas = __esm({
|
|
|
4323
4323
|
"use strict";
|
|
4324
4324
|
init_zod();
|
|
4325
4325
|
TOKEN_ROLES = ["owner", "personal"];
|
|
4326
|
-
GROUP_FILE_SOURCES = ["agent", "
|
|
4326
|
+
GROUP_FILE_SOURCES = ["agent", "owner"];
|
|
4327
4327
|
MOUNT_MODES = ["link", "copy"];
|
|
4328
4328
|
GroupFileEntrySchema = external_exports.object({
|
|
4329
4329
|
/** daemon 派发的稳定 id(用于 RPC remove / UI key) */
|
|
@@ -4331,8 +4331,6 @@ var init_attachment_schemas = __esm({
|
|
|
4331
4331
|
/** 相对 personaDir / sessionCwd 的路径 */
|
|
4332
4332
|
relPath: external_exports.string().min(1),
|
|
4333
4333
|
from: external_exports.enum(GROUP_FILE_SOURCES),
|
|
4334
|
-
/** user 上传时的客户端标识(personal label / hostname),from='user' 才有 */
|
|
4335
|
-
addedBy: external_exports.string().optional(),
|
|
4336
4334
|
/** owner 手动加群时的可选备注 */
|
|
4337
4335
|
label: external_exports.string().optional(),
|
|
4338
4336
|
/** 文件字节数(stat 时拍) */
|
|
@@ -4428,7 +4426,7 @@ var init_attachment_schemas = __esm({
|
|
|
4428
4426
|
AttachmentGroupAddArgs = external_exports.object({
|
|
4429
4427
|
sessionId: external_exports.string().min(1),
|
|
4430
4428
|
relPath: external_exports.string().min(1),
|
|
4431
|
-
/** owner 手动加群时可选备注;agent
|
|
4429
|
+
/** owner 手动加群时可选备注;agent 自动入清单不走此 RPC */
|
|
4432
4430
|
label: external_exports.string().optional()
|
|
4433
4431
|
});
|
|
4434
4432
|
AttachmentGroupAddResponseSchema = external_exports.object({
|
|
@@ -5545,8 +5543,8 @@ var require_req = __commonJS({
|
|
|
5545
5543
|
if (req.originalUrl) {
|
|
5546
5544
|
_req.url = req.originalUrl;
|
|
5547
5545
|
} else {
|
|
5548
|
-
const
|
|
5549
|
-
_req.url = typeof
|
|
5546
|
+
const path33 = req.path;
|
|
5547
|
+
_req.url = typeof path33 === "string" ? path33 : req.url ? req.url.path || req.url : void 0;
|
|
5550
5548
|
}
|
|
5551
5549
|
if (req.query) {
|
|
5552
5550
|
_req.query = req.query;
|
|
@@ -5711,14 +5709,14 @@ var require_redact = __commonJS({
|
|
|
5711
5709
|
}
|
|
5712
5710
|
return obj;
|
|
5713
5711
|
}
|
|
5714
|
-
function parsePath(
|
|
5712
|
+
function parsePath(path33) {
|
|
5715
5713
|
const parts = [];
|
|
5716
5714
|
let current = "";
|
|
5717
5715
|
let inBrackets = false;
|
|
5718
5716
|
let inQuotes = false;
|
|
5719
5717
|
let quoteChar = "";
|
|
5720
|
-
for (let i = 0; i <
|
|
5721
|
-
const char =
|
|
5718
|
+
for (let i = 0; i < path33.length; i++) {
|
|
5719
|
+
const char = path33[i];
|
|
5722
5720
|
if (!inBrackets && char === ".") {
|
|
5723
5721
|
if (current) {
|
|
5724
5722
|
parts.push(current);
|
|
@@ -5849,10 +5847,10 @@ var require_redact = __commonJS({
|
|
|
5849
5847
|
return current;
|
|
5850
5848
|
}
|
|
5851
5849
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
5852
|
-
for (const
|
|
5853
|
-
const parts = parsePath(
|
|
5850
|
+
for (const path33 of paths) {
|
|
5851
|
+
const parts = parsePath(path33);
|
|
5854
5852
|
if (parts.includes("*")) {
|
|
5855
|
-
redactWildcardPath(obj, parts, censor,
|
|
5853
|
+
redactWildcardPath(obj, parts, censor, path33, remove);
|
|
5856
5854
|
} else {
|
|
5857
5855
|
if (remove) {
|
|
5858
5856
|
removeKey(obj, parts);
|
|
@@ -5937,8 +5935,8 @@ var require_redact = __commonJS({
|
|
|
5937
5935
|
}
|
|
5938
5936
|
} else {
|
|
5939
5937
|
if (afterWildcard.includes("*")) {
|
|
5940
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
5941
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
5938
|
+
const wrappedCensor = typeof censor === "function" ? (value, path33) => {
|
|
5939
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path33];
|
|
5942
5940
|
return censor(value, fullPath);
|
|
5943
5941
|
} : censor;
|
|
5944
5942
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -5973,8 +5971,8 @@ var require_redact = __commonJS({
|
|
|
5973
5971
|
return null;
|
|
5974
5972
|
}
|
|
5975
5973
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
5976
|
-
for (const
|
|
5977
|
-
const parts = parsePath(
|
|
5974
|
+
for (const path33 of pathsToClone) {
|
|
5975
|
+
const parts = parsePath(path33);
|
|
5978
5976
|
let current = pathStructure;
|
|
5979
5977
|
for (let i = 0; i < parts.length; i++) {
|
|
5980
5978
|
const part = parts[i];
|
|
@@ -6026,24 +6024,24 @@ var require_redact = __commonJS({
|
|
|
6026
6024
|
}
|
|
6027
6025
|
return cloneSelectively(obj, pathStructure);
|
|
6028
6026
|
}
|
|
6029
|
-
function validatePath(
|
|
6030
|
-
if (typeof
|
|
6027
|
+
function validatePath(path33) {
|
|
6028
|
+
if (typeof path33 !== "string") {
|
|
6031
6029
|
throw new Error("Paths must be (non-empty) strings");
|
|
6032
6030
|
}
|
|
6033
|
-
if (
|
|
6031
|
+
if (path33 === "") {
|
|
6034
6032
|
throw new Error("Invalid redaction path ()");
|
|
6035
6033
|
}
|
|
6036
|
-
if (
|
|
6037
|
-
throw new Error(`Invalid redaction path (${
|
|
6034
|
+
if (path33.includes("..")) {
|
|
6035
|
+
throw new Error(`Invalid redaction path (${path33})`);
|
|
6038
6036
|
}
|
|
6039
|
-
if (
|
|
6040
|
-
throw new Error(`Invalid redaction path (${
|
|
6037
|
+
if (path33.includes(",")) {
|
|
6038
|
+
throw new Error(`Invalid redaction path (${path33})`);
|
|
6041
6039
|
}
|
|
6042
6040
|
let bracketCount = 0;
|
|
6043
6041
|
let inQuotes = false;
|
|
6044
6042
|
let quoteChar = "";
|
|
6045
|
-
for (let i = 0; i <
|
|
6046
|
-
const char =
|
|
6043
|
+
for (let i = 0; i < path33.length; i++) {
|
|
6044
|
+
const char = path33[i];
|
|
6047
6045
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6048
6046
|
if (!inQuotes) {
|
|
6049
6047
|
inQuotes = true;
|
|
@@ -6057,20 +6055,20 @@ var require_redact = __commonJS({
|
|
|
6057
6055
|
} else if (char === "]" && !inQuotes) {
|
|
6058
6056
|
bracketCount--;
|
|
6059
6057
|
if (bracketCount < 0) {
|
|
6060
|
-
throw new Error(`Invalid redaction path (${
|
|
6058
|
+
throw new Error(`Invalid redaction path (${path33})`);
|
|
6061
6059
|
}
|
|
6062
6060
|
}
|
|
6063
6061
|
}
|
|
6064
6062
|
if (bracketCount !== 0) {
|
|
6065
|
-
throw new Error(`Invalid redaction path (${
|
|
6063
|
+
throw new Error(`Invalid redaction path (${path33})`);
|
|
6066
6064
|
}
|
|
6067
6065
|
}
|
|
6068
6066
|
function validatePaths(paths) {
|
|
6069
6067
|
if (!Array.isArray(paths)) {
|
|
6070
6068
|
throw new TypeError("paths must be an array");
|
|
6071
6069
|
}
|
|
6072
|
-
for (const
|
|
6073
|
-
validatePath(
|
|
6070
|
+
for (const path33 of paths) {
|
|
6071
|
+
validatePath(path33);
|
|
6074
6072
|
}
|
|
6075
6073
|
}
|
|
6076
6074
|
function slowRedact(options = {}) {
|
|
@@ -6238,8 +6236,8 @@ var require_redaction = __commonJS({
|
|
|
6238
6236
|
if (shape[k2] === null) {
|
|
6239
6237
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6240
6238
|
} else {
|
|
6241
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6242
|
-
return censor(value, [k2, ...
|
|
6239
|
+
const wrappedCensor = typeof censor === "function" ? (value, path33) => {
|
|
6240
|
+
return censor(value, [k2, ...path33]);
|
|
6243
6241
|
} : censor;
|
|
6244
6242
|
o[k2] = Redact({
|
|
6245
6243
|
paths: shape[k2],
|
|
@@ -6457,10 +6455,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
6457
6455
|
var require_sonic_boom = __commonJS({
|
|
6458
6456
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
6459
6457
|
"use strict";
|
|
6460
|
-
var
|
|
6458
|
+
var fs30 = require("fs");
|
|
6461
6459
|
var EventEmitter2 = require("events");
|
|
6462
6460
|
var inherits = require("util").inherits;
|
|
6463
|
-
var
|
|
6461
|
+
var path33 = require("path");
|
|
6464
6462
|
var sleep = require_atomic_sleep();
|
|
6465
6463
|
var assert = require("assert");
|
|
6466
6464
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -6514,20 +6512,20 @@ var require_sonic_boom = __commonJS({
|
|
|
6514
6512
|
const mode = sonic.mode;
|
|
6515
6513
|
if (sonic.sync) {
|
|
6516
6514
|
try {
|
|
6517
|
-
if (sonic.mkdir)
|
|
6518
|
-
const fd =
|
|
6515
|
+
if (sonic.mkdir) fs30.mkdirSync(path33.dirname(file), { recursive: true });
|
|
6516
|
+
const fd = fs30.openSync(file, flags, mode);
|
|
6519
6517
|
fileOpened(null, fd);
|
|
6520
6518
|
} catch (err) {
|
|
6521
6519
|
fileOpened(err);
|
|
6522
6520
|
throw err;
|
|
6523
6521
|
}
|
|
6524
6522
|
} else if (sonic.mkdir) {
|
|
6525
|
-
|
|
6523
|
+
fs30.mkdir(path33.dirname(file), { recursive: true }, (err) => {
|
|
6526
6524
|
if (err) return fileOpened(err);
|
|
6527
|
-
|
|
6525
|
+
fs30.open(file, flags, mode, fileOpened);
|
|
6528
6526
|
});
|
|
6529
6527
|
} else {
|
|
6530
|
-
|
|
6528
|
+
fs30.open(file, flags, mode, fileOpened);
|
|
6531
6529
|
}
|
|
6532
6530
|
}
|
|
6533
6531
|
function SonicBoom(opts) {
|
|
@@ -6568,8 +6566,8 @@ var require_sonic_boom = __commonJS({
|
|
|
6568
6566
|
this.flush = flushBuffer;
|
|
6569
6567
|
this.flushSync = flushBufferSync;
|
|
6570
6568
|
this._actualWrite = actualWriteBuffer;
|
|
6571
|
-
fsWriteSync = () =>
|
|
6572
|
-
fsWrite = () =>
|
|
6569
|
+
fsWriteSync = () => fs30.writeSync(this.fd, this._writingBuf);
|
|
6570
|
+
fsWrite = () => fs30.write(this.fd, this._writingBuf, this.release);
|
|
6573
6571
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
6574
6572
|
this._writingBuf = "";
|
|
6575
6573
|
this.write = write;
|
|
@@ -6578,15 +6576,15 @@ var require_sonic_boom = __commonJS({
|
|
|
6578
6576
|
this._actualWrite = actualWrite;
|
|
6579
6577
|
fsWriteSync = () => {
|
|
6580
6578
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6581
|
-
return
|
|
6579
|
+
return fs30.writeSync(this.fd, this._writingBuf);
|
|
6582
6580
|
}
|
|
6583
|
-
return
|
|
6581
|
+
return fs30.writeSync(this.fd, this._writingBuf, "utf8");
|
|
6584
6582
|
};
|
|
6585
6583
|
fsWrite = () => {
|
|
6586
6584
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
6587
|
-
return
|
|
6585
|
+
return fs30.write(this.fd, this._writingBuf, this.release);
|
|
6588
6586
|
}
|
|
6589
|
-
return
|
|
6587
|
+
return fs30.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
6590
6588
|
};
|
|
6591
6589
|
} else {
|
|
6592
6590
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -6643,7 +6641,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6643
6641
|
}
|
|
6644
6642
|
}
|
|
6645
6643
|
if (this._fsync) {
|
|
6646
|
-
|
|
6644
|
+
fs30.fsyncSync(this.fd);
|
|
6647
6645
|
}
|
|
6648
6646
|
const len = this._len;
|
|
6649
6647
|
if (this._reopening) {
|
|
@@ -6757,7 +6755,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6757
6755
|
const onDrain = () => {
|
|
6758
6756
|
if (!this._fsync) {
|
|
6759
6757
|
try {
|
|
6760
|
-
|
|
6758
|
+
fs30.fsync(this.fd, (err) => {
|
|
6761
6759
|
this._flushPending = false;
|
|
6762
6760
|
cb(err);
|
|
6763
6761
|
});
|
|
@@ -6859,7 +6857,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6859
6857
|
const fd = this.fd;
|
|
6860
6858
|
this.once("ready", () => {
|
|
6861
6859
|
if (fd !== this.fd) {
|
|
6862
|
-
|
|
6860
|
+
fs30.close(fd, (err) => {
|
|
6863
6861
|
if (err) {
|
|
6864
6862
|
return this.emit("error", err);
|
|
6865
6863
|
}
|
|
@@ -6908,7 +6906,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6908
6906
|
buf = this._bufs[0];
|
|
6909
6907
|
}
|
|
6910
6908
|
try {
|
|
6911
|
-
const n = Buffer.isBuffer(buf) ?
|
|
6909
|
+
const n = Buffer.isBuffer(buf) ? fs30.writeSync(this.fd, buf) : fs30.writeSync(this.fd, buf, "utf8");
|
|
6912
6910
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
6913
6911
|
buf = releasedBufObj.writingBuf;
|
|
6914
6912
|
this._len = releasedBufObj.len;
|
|
@@ -6924,7 +6922,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6924
6922
|
}
|
|
6925
6923
|
}
|
|
6926
6924
|
try {
|
|
6927
|
-
|
|
6925
|
+
fs30.fsyncSync(this.fd);
|
|
6928
6926
|
} catch {
|
|
6929
6927
|
}
|
|
6930
6928
|
}
|
|
@@ -6945,7 +6943,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6945
6943
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
6946
6944
|
}
|
|
6947
6945
|
try {
|
|
6948
|
-
const n =
|
|
6946
|
+
const n = fs30.writeSync(this.fd, buf);
|
|
6949
6947
|
buf = buf.subarray(n);
|
|
6950
6948
|
this._len = Math.max(this._len - n, 0);
|
|
6951
6949
|
if (buf.length <= 0) {
|
|
@@ -6973,13 +6971,13 @@ var require_sonic_boom = __commonJS({
|
|
|
6973
6971
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
6974
6972
|
if (this.sync) {
|
|
6975
6973
|
try {
|
|
6976
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
6974
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs30.writeSync(this.fd, this._writingBuf) : fs30.writeSync(this.fd, this._writingBuf, "utf8");
|
|
6977
6975
|
release(null, written);
|
|
6978
6976
|
} catch (err) {
|
|
6979
6977
|
release(err);
|
|
6980
6978
|
}
|
|
6981
6979
|
} else {
|
|
6982
|
-
|
|
6980
|
+
fs30.write(this.fd, this._writingBuf, release);
|
|
6983
6981
|
}
|
|
6984
6982
|
}
|
|
6985
6983
|
function actualWriteBuffer() {
|
|
@@ -6988,7 +6986,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6988
6986
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
6989
6987
|
if (this.sync) {
|
|
6990
6988
|
try {
|
|
6991
|
-
const written =
|
|
6989
|
+
const written = fs30.writeSync(this.fd, this._writingBuf);
|
|
6992
6990
|
release(null, written);
|
|
6993
6991
|
} catch (err) {
|
|
6994
6992
|
release(err);
|
|
@@ -6997,7 +6995,7 @@ var require_sonic_boom = __commonJS({
|
|
|
6997
6995
|
if (kCopyBuffer) {
|
|
6998
6996
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
6999
6997
|
}
|
|
7000
|
-
|
|
6998
|
+
fs30.write(this.fd, this._writingBuf, release);
|
|
7001
6999
|
}
|
|
7002
7000
|
}
|
|
7003
7001
|
function actualClose(sonic) {
|
|
@@ -7013,12 +7011,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7013
7011
|
sonic._lens = [];
|
|
7014
7012
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7015
7013
|
try {
|
|
7016
|
-
|
|
7014
|
+
fs30.fsync(sonic.fd, closeWrapped);
|
|
7017
7015
|
} catch {
|
|
7018
7016
|
}
|
|
7019
7017
|
function closeWrapped() {
|
|
7020
7018
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7021
|
-
|
|
7019
|
+
fs30.close(sonic.fd, done);
|
|
7022
7020
|
} else {
|
|
7023
7021
|
done();
|
|
7024
7022
|
}
|
|
@@ -10153,11 +10151,11 @@ var init_lib = __esm({
|
|
|
10153
10151
|
}
|
|
10154
10152
|
}
|
|
10155
10153
|
},
|
|
10156
|
-
addToPath: function addToPath(
|
|
10157
|
-
var last =
|
|
10154
|
+
addToPath: function addToPath(path33, added, removed, oldPosInc, options) {
|
|
10155
|
+
var last = path33.lastComponent;
|
|
10158
10156
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10159
10157
|
return {
|
|
10160
|
-
oldPos:
|
|
10158
|
+
oldPos: path33.oldPos + oldPosInc,
|
|
10161
10159
|
lastComponent: {
|
|
10162
10160
|
count: last.count + 1,
|
|
10163
10161
|
added,
|
|
@@ -10167,7 +10165,7 @@ var init_lib = __esm({
|
|
|
10167
10165
|
};
|
|
10168
10166
|
} else {
|
|
10169
10167
|
return {
|
|
10170
|
-
oldPos:
|
|
10168
|
+
oldPos: path33.oldPos + oldPosInc,
|
|
10171
10169
|
lastComponent: {
|
|
10172
10170
|
count: 1,
|
|
10173
10171
|
added,
|
|
@@ -10598,10 +10596,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
10598
10596
|
const memories = raw.map((m2) => {
|
|
10599
10597
|
if (!m2 || typeof m2 !== "object") return null;
|
|
10600
10598
|
const rec = m2;
|
|
10601
|
-
const
|
|
10599
|
+
const path33 = typeof rec.path === "string" ? rec.path : null;
|
|
10602
10600
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
10603
|
-
if (!
|
|
10604
|
-
const entry = { path:
|
|
10601
|
+
if (!path33 || content == null) return null;
|
|
10602
|
+
const entry = { path: path33, content };
|
|
10605
10603
|
if (typeof rec.mtimeMs === "number") entry.mtimeMs = rec.mtimeMs;
|
|
10606
10604
|
return entry;
|
|
10607
10605
|
}).filter((m2) => m2 !== null);
|
|
@@ -11405,10 +11403,10 @@ function parseAttachment(obj) {
|
|
|
11405
11403
|
const memories = raw.map((m2) => {
|
|
11406
11404
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11407
11405
|
const rec = m2;
|
|
11408
|
-
const
|
|
11406
|
+
const path33 = typeof rec.path === "string" ? rec.path : null;
|
|
11409
11407
|
const content = typeof rec.content === "string" ? rec.content : null;
|
|
11410
|
-
if (!
|
|
11411
|
-
const out = { path:
|
|
11408
|
+
if (!path33 || content == null) return null;
|
|
11409
|
+
const out = { path: path33, content };
|
|
11412
11410
|
if (typeof rec.mtimeMs === "number") out.mtimeMs = rec.mtimeMs;
|
|
11413
11411
|
return out;
|
|
11414
11412
|
}).filter((m2) => m2 !== null);
|
|
@@ -20322,7 +20320,7 @@ var require_websocket_server = __commonJS({
|
|
|
20322
20320
|
// src/run-case/recorder.ts
|
|
20323
20321
|
function startRunCaseRecorder(opts) {
|
|
20324
20322
|
const now = opts.now ?? Date.now;
|
|
20325
|
-
const dir =
|
|
20323
|
+
const dir = import_node_path29.default.dirname(opts.recordPath);
|
|
20326
20324
|
let stream = null;
|
|
20327
20325
|
let closing = false;
|
|
20328
20326
|
let closedSettled = false;
|
|
@@ -20336,8 +20334,8 @@ function startRunCaseRecorder(opts) {
|
|
|
20336
20334
|
});
|
|
20337
20335
|
const ensureStream = () => {
|
|
20338
20336
|
if (stream) return stream;
|
|
20339
|
-
|
|
20340
|
-
stream =
|
|
20337
|
+
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
20338
|
+
stream = import_node_fs27.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
20341
20339
|
stream.on("close", () => closedResolve());
|
|
20342
20340
|
return stream;
|
|
20343
20341
|
};
|
|
@@ -20362,12 +20360,12 @@ function startRunCaseRecorder(opts) {
|
|
|
20362
20360
|
};
|
|
20363
20361
|
return { tap, close, closed };
|
|
20364
20362
|
}
|
|
20365
|
-
var
|
|
20363
|
+
var import_node_fs27, import_node_path29;
|
|
20366
20364
|
var init_recorder = __esm({
|
|
20367
20365
|
"src/run-case/recorder.ts"() {
|
|
20368
20366
|
"use strict";
|
|
20369
|
-
|
|
20370
|
-
|
|
20367
|
+
import_node_fs27 = __toESM(require("fs"), 1);
|
|
20368
|
+
import_node_path29 = __toESM(require("path"), 1);
|
|
20371
20369
|
}
|
|
20372
20370
|
});
|
|
20373
20371
|
|
|
@@ -20410,7 +20408,7 @@ var init_wire = __esm({
|
|
|
20410
20408
|
// src/run-case/controller.ts
|
|
20411
20409
|
async function runController(opts) {
|
|
20412
20410
|
const now = opts.now ?? Date.now;
|
|
20413
|
-
const cwd = opts.cwd ?? (0,
|
|
20411
|
+
const cwd = opts.cwd ?? (0, import_node_fs28.mkdtempSync)(import_node_path30.default.join(import_node_os15.default.tmpdir(), "clawd-runcase-"));
|
|
20414
20412
|
const ownsCwd = opts.cwd === void 0;
|
|
20415
20413
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
20416
20414
|
const spawnCtx = { cwd };
|
|
@@ -20571,19 +20569,19 @@ async function runController(opts) {
|
|
|
20571
20569
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
20572
20570
|
if (ownsCwd) {
|
|
20573
20571
|
try {
|
|
20574
|
-
(0,
|
|
20572
|
+
(0, import_node_fs28.rmSync)(cwd, { recursive: true, force: true });
|
|
20575
20573
|
} catch {
|
|
20576
20574
|
}
|
|
20577
20575
|
}
|
|
20578
20576
|
return exitCode ?? 0;
|
|
20579
20577
|
}
|
|
20580
|
-
var
|
|
20578
|
+
var import_node_fs28, import_node_os15, import_node_path30;
|
|
20581
20579
|
var init_controller = __esm({
|
|
20582
20580
|
"src/run-case/controller.ts"() {
|
|
20583
20581
|
"use strict";
|
|
20584
|
-
|
|
20582
|
+
import_node_fs28 = require("fs");
|
|
20585
20583
|
import_node_os15 = __toESM(require("os"), 1);
|
|
20586
|
-
|
|
20584
|
+
import_node_path30 = __toESM(require("path"), 1);
|
|
20587
20585
|
init_claude();
|
|
20588
20586
|
init_stdout_splitter();
|
|
20589
20587
|
init_permission_stdio();
|
|
@@ -20815,8 +20813,8 @@ Env (advanced):
|
|
|
20815
20813
|
`;
|
|
20816
20814
|
|
|
20817
20815
|
// src/index.ts
|
|
20818
|
-
var
|
|
20819
|
-
var
|
|
20816
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
20817
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
20820
20818
|
|
|
20821
20819
|
// src/logger.ts
|
|
20822
20820
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
@@ -26343,8 +26341,8 @@ function constantTimeEqual2(a, b2) {
|
|
|
26343
26341
|
}
|
|
26344
26342
|
|
|
26345
26343
|
// src/transport/http-router.ts
|
|
26346
|
-
var
|
|
26347
|
-
var
|
|
26344
|
+
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
26345
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
26348
26346
|
|
|
26349
26347
|
// src/attachment/group.ts
|
|
26350
26348
|
var import_node_fs13 = __toESM(require("fs"), 1);
|
|
@@ -26433,7 +26431,7 @@ var GroupFileStore = class {
|
|
|
26433
26431
|
mime: input.mime,
|
|
26434
26432
|
lastEditedAt: now,
|
|
26435
26433
|
stale: false
|
|
26436
|
-
//
|
|
26434
|
+
// label 不在 upsert 路径覆盖(owner +Add 走另一条路径)
|
|
26437
26435
|
};
|
|
26438
26436
|
entries[idx] = next;
|
|
26439
26437
|
} else {
|
|
@@ -26441,12 +26439,11 @@ var GroupFileStore = class {
|
|
|
26441
26439
|
id: `gf-${import_node_crypto4.default.randomBytes(6).toString("base64url")}`,
|
|
26442
26440
|
relPath: input.relPath,
|
|
26443
26441
|
from: input.from,
|
|
26444
|
-
addedBy: input.addedBy,
|
|
26445
26442
|
label: input.label,
|
|
26446
26443
|
size: input.size,
|
|
26447
26444
|
mime: input.mime,
|
|
26448
26445
|
addedAt: now
|
|
26449
|
-
// agent
|
|
26446
|
+
// agent 第一次 upsert 时不写 lastEditedAt(语义上 = 首次"编辑" = addedAt)
|
|
26450
26447
|
};
|
|
26451
26448
|
entries.push(next);
|
|
26452
26449
|
}
|
|
@@ -26472,7 +26469,7 @@ var GroupFileStore = class {
|
|
|
26472
26469
|
}
|
|
26473
26470
|
/**
|
|
26474
26471
|
* 真删一条群文件条目(用于 owner 撤销自己 +Add 的入群操作)。
|
|
26475
|
-
* agent
|
|
26472
|
+
* agent 自动入群的不应走这条 —— 用 markStale 表达"文件不在了"语义;
|
|
26476
26473
|
* owner 手动加错了,应该能彻底从列表移除而不是留个 stale 占位。
|
|
26477
26474
|
*
|
|
26478
26475
|
* 返回值:true=命中并删除;false=relPath 不在群里。
|
|
@@ -26579,207 +26576,16 @@ function lookupMime(filePathOrName) {
|
|
|
26579
26576
|
return EXT_TO_MIME[ext] ?? "application/octet-stream";
|
|
26580
26577
|
}
|
|
26581
26578
|
|
|
26582
|
-
// src/attachment/inbox.ts
|
|
26583
|
-
var import_node_fs14 = __toESM(require("fs"), 1);
|
|
26584
|
-
var import_node_path16 = __toESM(require("path"), 1);
|
|
26585
|
-
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
26586
|
-
var DEFAULT_MAX_BYTES = 10 * 1024 * 1024;
|
|
26587
|
-
async function handlePersonaInbox(req, args, deps) {
|
|
26588
|
-
const filename = readFilenameFromUrl(req.url);
|
|
26589
|
-
if (!filename) throw httpErr(400, "INVALID_PARAM", "missing ?name= query");
|
|
26590
|
-
const safeName = sanitizeFilename(filename);
|
|
26591
|
-
const mime = lookupMime(safeName);
|
|
26592
|
-
if (deps.isAllowedMime && !deps.isAllowedMime(mime)) {
|
|
26593
|
-
throw httpErr(415, "UNSUPPORTED_MEDIA", `mime ${mime} not allowed`);
|
|
26594
|
-
}
|
|
26595
|
-
const inboxDir = import_node_path16.default.join(args.personaDir, "_inbox");
|
|
26596
|
-
import_node_fs14.default.mkdirSync(inboxDir, { recursive: true });
|
|
26597
|
-
const sha = import_node_crypto5.default.randomBytes(6).toString("hex");
|
|
26598
|
-
const fileName = `${sha}-${safeName}`;
|
|
26599
|
-
const absPath = import_node_path16.default.join(inboxDir, fileName);
|
|
26600
|
-
const size = await streamBodyToFile(req, absPath, deps.maxBytes ?? DEFAULT_MAX_BYTES);
|
|
26601
|
-
const relPath = `_inbox/${fileName}`;
|
|
26602
|
-
deps.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
26603
|
-
relPath,
|
|
26604
|
-
from: args.from,
|
|
26605
|
-
addedBy: args.addedBy,
|
|
26606
|
-
size,
|
|
26607
|
-
mime
|
|
26608
|
-
});
|
|
26609
|
-
return { relPath, size, mime };
|
|
26610
|
-
}
|
|
26611
|
-
async function handleSessionInbox(req, args, deps) {
|
|
26612
|
-
const filename = readFilenameFromUrl(req.url);
|
|
26613
|
-
if (!filename) throw httpErr(400, "INVALID_PARAM", "missing ?name= query");
|
|
26614
|
-
const safeName = sanitizeFilename(filename);
|
|
26615
|
-
const mime = lookupMime(safeName);
|
|
26616
|
-
if (deps.isAllowedMime && !deps.isAllowedMime(mime)) {
|
|
26617
|
-
throw httpErr(415, "UNSUPPORTED_MEDIA", `mime ${mime} not allowed`);
|
|
26618
|
-
}
|
|
26619
|
-
const inboxDir = import_node_path16.default.join(args.sessionCwd, "_inbox");
|
|
26620
|
-
import_node_fs14.default.mkdirSync(inboxDir, { recursive: true });
|
|
26621
|
-
const sha = import_node_crypto5.default.randomBytes(6).toString("hex");
|
|
26622
|
-
const fileName = `${sha}-${safeName}`;
|
|
26623
|
-
const absPath = import_node_path16.default.join(inboxDir, fileName);
|
|
26624
|
-
const size = await streamBodyToFile(req, absPath, deps.maxBytes ?? DEFAULT_MAX_BYTES);
|
|
26625
|
-
const relPath = `_inbox/${fileName}`;
|
|
26626
|
-
deps.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
26627
|
-
relPath,
|
|
26628
|
-
from: "owner",
|
|
26629
|
-
size,
|
|
26630
|
-
mime
|
|
26631
|
-
});
|
|
26632
|
-
return { relPath, size, mime };
|
|
26633
|
-
}
|
|
26634
|
-
function streamBodyToFile(req, absPath, maxBytes) {
|
|
26635
|
-
return new Promise((resolve2, reject) => {
|
|
26636
|
-
let received = 0;
|
|
26637
|
-
const tmp = `${absPath}.tmp-${process.pid}-${Date.now()}`;
|
|
26638
|
-
const stream = import_node_fs14.default.createWriteStream(tmp, { mode: 384 });
|
|
26639
|
-
req.on("data", (chunk) => {
|
|
26640
|
-
received += chunk.length;
|
|
26641
|
-
if (received > maxBytes) {
|
|
26642
|
-
stream.destroy();
|
|
26643
|
-
try {
|
|
26644
|
-
import_node_fs14.default.unlinkSync(tmp);
|
|
26645
|
-
} catch {
|
|
26646
|
-
}
|
|
26647
|
-
reject(httpErr(413, "TOO_LARGE", `upload exceeds ${maxBytes} bytes`));
|
|
26648
|
-
req.destroy();
|
|
26649
|
-
return;
|
|
26650
|
-
}
|
|
26651
|
-
stream.write(chunk);
|
|
26652
|
-
});
|
|
26653
|
-
req.on("end", () => {
|
|
26654
|
-
stream.end();
|
|
26655
|
-
stream.on("finish", () => {
|
|
26656
|
-
try {
|
|
26657
|
-
import_node_fs14.default.renameSync(tmp, absPath);
|
|
26658
|
-
resolve2(received);
|
|
26659
|
-
} catch (err) {
|
|
26660
|
-
reject(err);
|
|
26661
|
-
}
|
|
26662
|
-
});
|
|
26663
|
-
});
|
|
26664
|
-
req.on("error", reject);
|
|
26665
|
-
stream.on("error", reject);
|
|
26666
|
-
});
|
|
26667
|
-
}
|
|
26668
|
-
function readFilenameFromUrl(rawUrl) {
|
|
26669
|
-
if (!rawUrl) return null;
|
|
26670
|
-
try {
|
|
26671
|
-
const u = new URL(rawUrl, "http://placeholder");
|
|
26672
|
-
return u.searchParams.get("name");
|
|
26673
|
-
} catch {
|
|
26674
|
-
return null;
|
|
26675
|
-
}
|
|
26676
|
-
}
|
|
26677
|
-
function sanitizeFilename(name) {
|
|
26678
|
-
const trimmed = name.replace(/[\x00-\x1f]/g, "").replace(/\//g, "_").replace(/\\/g, "_");
|
|
26679
|
-
const dotsOnly = trimmed.replace(/^\.+/, (m2) => "_".repeat(m2.length));
|
|
26680
|
-
if (!dotsOnly) return "unnamed";
|
|
26681
|
-
return dotsOnly.slice(0, 200);
|
|
26682
|
-
}
|
|
26683
|
-
function httpErr(status, code, message) {
|
|
26684
|
-
const err = new Error(message);
|
|
26685
|
-
err.httpStatus = status;
|
|
26686
|
-
err.code = code;
|
|
26687
|
-
return err;
|
|
26688
|
-
}
|
|
26689
|
-
function isHttpError(err) {
|
|
26690
|
-
return err instanceof Error && typeof err.httpStatus === "number" && typeof err.code === "string";
|
|
26691
|
-
}
|
|
26692
|
-
async function handleInboxRequest(req, res, ctxRouter, deps) {
|
|
26693
|
-
const personaMatch = ctxRouter.pathname.match(/^\/persona\/([^/]+)\/inbox$/);
|
|
26694
|
-
if (personaMatch && req.method === "POST") {
|
|
26695
|
-
if (!deps.getPersonaDir || !deps.getPersonaScope) {
|
|
26696
|
-
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "inbox not wired" });
|
|
26697
|
-
return true;
|
|
26698
|
-
}
|
|
26699
|
-
const pid = personaMatch[1];
|
|
26700
|
-
const personaDir = deps.getPersonaDir(pid);
|
|
26701
|
-
if (!personaDir) {
|
|
26702
|
-
sendJson(res, 404, { code: "NOT_FOUND", message: `persona ${pid} not found` });
|
|
26703
|
-
return true;
|
|
26704
|
-
}
|
|
26705
|
-
const sessionId = new URL(req.url ?? "", "http://placeholder").searchParams.get("session") || pid;
|
|
26706
|
-
try {
|
|
26707
|
-
const result = await handlePersonaInbox(
|
|
26708
|
-
req,
|
|
26709
|
-
{
|
|
26710
|
-
personaId: pid,
|
|
26711
|
-
personaDir,
|
|
26712
|
-
sessionId,
|
|
26713
|
-
scope: deps.getPersonaScope(pid),
|
|
26714
|
-
addedBy: deps.addedBy,
|
|
26715
|
-
from: ctxRouter.isOwner ? "owner" : "user"
|
|
26716
|
-
},
|
|
26717
|
-
deps.inboxOpts ?? { groupFileStore: deps.groupFileStore }
|
|
26718
|
-
);
|
|
26719
|
-
sendJson(res, 200, result);
|
|
26720
|
-
} catch (err) {
|
|
26721
|
-
handleInboxError(err, res);
|
|
26722
|
-
}
|
|
26723
|
-
return true;
|
|
26724
|
-
}
|
|
26725
|
-
const sessionMatch = ctxRouter.pathname.match(/^\/session\/([^/]+)\/inbox$/);
|
|
26726
|
-
if (sessionMatch && req.method === "POST") {
|
|
26727
|
-
if (!ctxRouter.isOwner) {
|
|
26728
|
-
sendJson(res, 403, { code: "FORBIDDEN", message: "direct session inbox is owner-only" });
|
|
26729
|
-
return true;
|
|
26730
|
-
}
|
|
26731
|
-
if (!deps.getSessionCwd) {
|
|
26732
|
-
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "inbox not wired" });
|
|
26733
|
-
return true;
|
|
26734
|
-
}
|
|
26735
|
-
const sid = sessionMatch[1];
|
|
26736
|
-
const sessionCwd = deps.getSessionCwd(sid);
|
|
26737
|
-
if (!sessionCwd) {
|
|
26738
|
-
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
26739
|
-
return true;
|
|
26740
|
-
}
|
|
26741
|
-
try {
|
|
26742
|
-
const result = await handleSessionInbox(
|
|
26743
|
-
req,
|
|
26744
|
-
{
|
|
26745
|
-
sessionId: sid,
|
|
26746
|
-
sessionCwd: sessionCwd.cwd,
|
|
26747
|
-
scope: sessionCwd.scope,
|
|
26748
|
-
from: "owner"
|
|
26749
|
-
},
|
|
26750
|
-
deps.inboxOpts ?? { groupFileStore: deps.groupFileStore }
|
|
26751
|
-
);
|
|
26752
|
-
sendJson(res, 200, result);
|
|
26753
|
-
} catch (err) {
|
|
26754
|
-
handleInboxError(err, res);
|
|
26755
|
-
}
|
|
26756
|
-
return true;
|
|
26757
|
-
}
|
|
26758
|
-
return false;
|
|
26759
|
-
}
|
|
26760
|
-
function handleInboxError(err, res) {
|
|
26761
|
-
if (isHttpError(err)) {
|
|
26762
|
-
sendJson(res, err.httpStatus, { code: err.code, message: err.message });
|
|
26763
|
-
return;
|
|
26764
|
-
}
|
|
26765
|
-
sendJson(res, 500, { code: "INTERNAL", message: err.message });
|
|
26766
|
-
}
|
|
26767
|
-
function sendJson(res, status, body) {
|
|
26768
|
-
if (res.headersSent) return;
|
|
26769
|
-
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
|
|
26770
|
-
res.end(JSON.stringify(body));
|
|
26771
|
-
}
|
|
26772
|
-
|
|
26773
26579
|
// src/transport/http-router.ts
|
|
26774
26580
|
function createHttpRouter(deps) {
|
|
26775
26581
|
return async (req, res) => {
|
|
26776
26582
|
const url = parseUrl(req.url);
|
|
26777
26583
|
if (!url) {
|
|
26778
|
-
|
|
26584
|
+
sendJson(res, 400, { code: "INVALID_URL", message: "malformed request URL" });
|
|
26779
26585
|
return true;
|
|
26780
26586
|
}
|
|
26781
26587
|
if (url.pathname === "/healthz" && req.method === "GET") {
|
|
26782
|
-
|
|
26588
|
+
sendJson(res, 200, { ok: true, version: deps.daemonVersion });
|
|
26783
26589
|
return true;
|
|
26784
26590
|
}
|
|
26785
26591
|
if (!url.pathname.startsWith("/persona/") && !url.pathname.startsWith("/session/") && url.pathname !== "/outbox" && !url.pathname.startsWith("/outbox/")) {
|
|
@@ -26790,7 +26596,7 @@ function createHttpRouter(deps) {
|
|
|
26790
26596
|
const personaMatch = url.pathname.match(/^\/persona\/([^/]+)\/outbox\/([^/]+)$/);
|
|
26791
26597
|
if (directMatch || personaMatch) {
|
|
26792
26598
|
if (!deps.outboxStore) {
|
|
26793
|
-
|
|
26599
|
+
sendJson(res, 501, { code: "NOT_IMPLEMENTED", message: "outbox store not wired" });
|
|
26794
26600
|
return true;
|
|
26795
26601
|
}
|
|
26796
26602
|
const capToken = directMatch ? directMatch[1] : personaMatch[2];
|
|
@@ -26801,7 +26607,7 @@ function createHttpRouter(deps) {
|
|
|
26801
26607
|
EXPIRED: 410,
|
|
26802
26608
|
REVOKED: 410
|
|
26803
26609
|
};
|
|
26804
|
-
|
|
26610
|
+
sendJson(res, statusByCode[lookup.code], { code: lookup.code, message: "outbox cap not usable" });
|
|
26805
26611
|
return true;
|
|
26806
26612
|
}
|
|
26807
26613
|
const { entry } = lookup;
|
|
@@ -26811,7 +26617,7 @@ function createHttpRouter(deps) {
|
|
|
26811
26617
|
req.socket.remoteAddress ?? void 0
|
|
26812
26618
|
);
|
|
26813
26619
|
if (!ctx2 || ctx2.role !== "personal" || ctx2.personaId !== entry.scope.personalId) {
|
|
26814
|
-
|
|
26620
|
+
sendJson(res, 403, { code: "FORBIDDEN", message: "personal-scoped cap requires matching token" });
|
|
26815
26621
|
return true;
|
|
26816
26622
|
}
|
|
26817
26623
|
}
|
|
@@ -26825,7 +26631,7 @@ function createHttpRouter(deps) {
|
|
|
26825
26631
|
req.socket.remoteAddress ?? void 0
|
|
26826
26632
|
);
|
|
26827
26633
|
if (!ctx) {
|
|
26828
|
-
|
|
26634
|
+
sendJson(res, 401, { code: "UNAUTHORIZED", message: "missing or invalid bearer token" });
|
|
26829
26635
|
return true;
|
|
26830
26636
|
}
|
|
26831
26637
|
const personaFilesMatch = url.pathname.match(/^\/persona\/([^/]+)\/files$/);
|
|
@@ -26833,26 +26639,26 @@ function createHttpRouter(deps) {
|
|
|
26833
26639
|
const pid = personaFilesMatch[1];
|
|
26834
26640
|
const pathParam = url.searchParams.get("path");
|
|
26835
26641
|
if (!pathParam) {
|
|
26836
|
-
|
|
26642
|
+
sendJson(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
|
|
26837
26643
|
return true;
|
|
26838
26644
|
}
|
|
26839
26645
|
if (!deps.personaStore || !deps.groupFileStore) {
|
|
26840
|
-
|
|
26646
|
+
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "files endpoint not wired" }));
|
|
26841
26647
|
return true;
|
|
26842
26648
|
}
|
|
26843
26649
|
const personaDir = deps.personaStore.personaDirPath(pid);
|
|
26844
|
-
const absPath =
|
|
26845
|
-
if (!
|
|
26846
|
-
|
|
26650
|
+
const absPath = import_node_path16.default.isAbsolute(pathParam) ? pathParam : import_node_path16.default.join(personaDir, pathParam);
|
|
26651
|
+
if (!import_node_path16.default.isAbsolute(pathParam) && !isContainedIn(absPath, personaDir)) {
|
|
26652
|
+
sendJson(res, 400, { code: "PATH_TRAVERSAL", message: "rel path escapes personaDir" });
|
|
26847
26653
|
return true;
|
|
26848
26654
|
}
|
|
26849
26655
|
if (ctx.role === "personal") {
|
|
26850
26656
|
if (ctx.personaId !== pid) {
|
|
26851
|
-
|
|
26657
|
+
sendJson(res, 403, { code: "FORBIDDEN", message: "personal token bound to other persona" });
|
|
26852
26658
|
return true;
|
|
26853
26659
|
}
|
|
26854
26660
|
if (!personalViewable(deps.groupFileStore, personaDir, pid, absPath)) {
|
|
26855
|
-
|
|
26661
|
+
sendJson(res, 403, { code: "FORBIDDEN", message: "path not in personal viewable scope" });
|
|
26856
26662
|
return true;
|
|
26857
26663
|
}
|
|
26858
26664
|
}
|
|
@@ -26862,90 +26668,37 @@ function createHttpRouter(deps) {
|
|
|
26862
26668
|
const sessionFilesMatch = url.pathname.match(/^\/session\/([^/]+)\/files$/);
|
|
26863
26669
|
if (sessionFilesMatch && req.method === "GET") {
|
|
26864
26670
|
if (ctx.role !== "owner") {
|
|
26865
|
-
|
|
26671
|
+
sendJson(res, 403, { code: "FORBIDDEN", message: "direct session files are owner-only" });
|
|
26866
26672
|
return true;
|
|
26867
26673
|
}
|
|
26868
26674
|
const sid = sessionFilesMatch[1];
|
|
26869
26675
|
const pathParam = url.searchParams.get("path");
|
|
26870
26676
|
if (!pathParam) {
|
|
26871
|
-
|
|
26677
|
+
sendJson(res, 400, { code: "INVALID_PARAM", message: "missing `path` query" });
|
|
26872
26678
|
return true;
|
|
26873
26679
|
}
|
|
26874
26680
|
let absPath;
|
|
26875
|
-
if (
|
|
26681
|
+
if (import_node_path16.default.isAbsolute(pathParam)) {
|
|
26876
26682
|
absPath = pathParam;
|
|
26877
26683
|
} else if (deps.sessionStore) {
|
|
26878
26684
|
const file = deps.sessionStore.read(sid);
|
|
26879
26685
|
if (!file) {
|
|
26880
|
-
|
|
26686
|
+
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
26881
26687
|
return true;
|
|
26882
26688
|
}
|
|
26883
|
-
absPath =
|
|
26689
|
+
absPath = import_node_path16.default.join(file.cwd, pathParam);
|
|
26884
26690
|
} else {
|
|
26885
|
-
|
|
26691
|
+
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
26886
26692
|
return true;
|
|
26887
26693
|
}
|
|
26888
26694
|
streamFile(res, absPath, deps.logger);
|
|
26889
26695
|
return true;
|
|
26890
26696
|
}
|
|
26891
|
-
if (/^\/persona\/[^/]+\/inbox$/.test(url.pathname) && req.method === "POST") {
|
|
26892
|
-
if (!deps.groupFileStore || !deps.personaStore) {
|
|
26893
|
-
sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "inbox not wired" }));
|
|
26894
|
-
return true;
|
|
26895
|
-
}
|
|
26896
|
-
const handled = await handleInboxRequest(
|
|
26897
|
-
req,
|
|
26898
|
-
res,
|
|
26899
|
-
{
|
|
26900
|
-
pathname: url.pathname,
|
|
26901
|
-
isOwner: ctx.role === "owner",
|
|
26902
|
-
personaId: ctx.personaId
|
|
26903
|
-
},
|
|
26904
|
-
{
|
|
26905
|
-
groupFileStore: deps.groupFileStore,
|
|
26906
|
-
getPersonaDir: (pid) => deps.personaStore.personaDirPath(pid),
|
|
26907
|
-
// PR 7:persona inbox 默认走 owner-mode scope;UI 端如果用 personal listener
|
|
26908
|
-
// 也归到 owner scope(session 维度)—— PR 9 完善时再走 listener scope。
|
|
26909
|
-
getPersonaScope: (pid) => ({
|
|
26910
|
-
kind: "persona",
|
|
26911
|
-
personaId: pid,
|
|
26912
|
-
mode: "owner"
|
|
26913
|
-
}),
|
|
26914
|
-
addedBy: ctx.label ?? (ctx.role === "owner" ? "owner" : "unknown")
|
|
26915
|
-
}
|
|
26916
|
-
);
|
|
26917
|
-
if (handled) return true;
|
|
26918
|
-
}
|
|
26919
|
-
if (/^\/session\/[^/]+\/inbox$/.test(url.pathname) && req.method === "POST") {
|
|
26920
|
-
if (!deps.groupFileStore || !deps.sessionStore) {
|
|
26921
|
-
sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "inbox not wired" }));
|
|
26922
|
-
return true;
|
|
26923
|
-
}
|
|
26924
|
-
const handled = await handleInboxRequest(
|
|
26925
|
-
req,
|
|
26926
|
-
res,
|
|
26927
|
-
{
|
|
26928
|
-
pathname: url.pathname,
|
|
26929
|
-
isOwner: ctx.role === "owner"
|
|
26930
|
-
},
|
|
26931
|
-
{
|
|
26932
|
-
groupFileStore: deps.groupFileStore,
|
|
26933
|
-
getSessionCwd: (sid) => {
|
|
26934
|
-
const f = deps.sessionStore.read(sid);
|
|
26935
|
-
if (!f) return null;
|
|
26936
|
-
const scope = f.ownerPersonaId ? { kind: "persona", personaId: f.ownerPersonaId, mode: "owner" } : { kind: "default" };
|
|
26937
|
-
return { cwd: f.cwd, scope };
|
|
26938
|
-
},
|
|
26939
|
-
addedBy: ctx.role === "owner" ? "owner" : "unknown"
|
|
26940
|
-
}
|
|
26941
|
-
);
|
|
26942
|
-
if (handled) return true;
|
|
26943
|
-
}
|
|
26944
26697
|
if (/^\/persona\/[^/]+\/attachment-meta$/.test(url.pathname) && req.method === "GET") {
|
|
26945
|
-
|
|
26698
|
+
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "attachment-meta \u2014 PR 6" }));
|
|
26946
26699
|
return true;
|
|
26947
26700
|
}
|
|
26948
|
-
|
|
26701
|
+
sendJson(res, 404, { code: "NOT_FOUND", message: `no route for ${req.method} ${url.pathname}` });
|
|
26949
26702
|
return true;
|
|
26950
26703
|
};
|
|
26951
26704
|
}
|
|
@@ -26957,7 +26710,7 @@ function parseUrl(rawUrl) {
|
|
|
26957
26710
|
return null;
|
|
26958
26711
|
}
|
|
26959
26712
|
}
|
|
26960
|
-
function
|
|
26713
|
+
function sendJson(res, status, body) {
|
|
26961
26714
|
res.writeHead(status, { "Content-Type": "application/json; charset=utf-8" });
|
|
26962
26715
|
res.end(JSON.stringify(body));
|
|
26963
26716
|
}
|
|
@@ -26965,26 +26718,26 @@ function withCtx(ctx, body) {
|
|
|
26965
26718
|
return { ...body, role: ctx.role, personaId: ctx.personaId };
|
|
26966
26719
|
}
|
|
26967
26720
|
function isContainedIn(abs, root) {
|
|
26968
|
-
const normalized =
|
|
26969
|
-
const normalizedRoot =
|
|
26721
|
+
const normalized = import_node_path16.default.resolve(abs);
|
|
26722
|
+
const normalizedRoot = import_node_path16.default.resolve(root);
|
|
26970
26723
|
if (normalized === normalizedRoot) return true;
|
|
26971
|
-
return normalized.startsWith(normalizedRoot +
|
|
26724
|
+
return normalized.startsWith(normalizedRoot + import_node_path16.default.sep);
|
|
26972
26725
|
}
|
|
26973
26726
|
function streamFile(res, absPath, logger, onComplete) {
|
|
26974
26727
|
let stat;
|
|
26975
26728
|
try {
|
|
26976
|
-
stat =
|
|
26729
|
+
stat = import_node_fs14.default.statSync(absPath);
|
|
26977
26730
|
} catch (err) {
|
|
26978
26731
|
const code = err?.code;
|
|
26979
26732
|
if (code === "ENOENT") {
|
|
26980
|
-
|
|
26733
|
+
sendJson(res, 404, { code: "NOT_FOUND", message: "file not found" });
|
|
26981
26734
|
} else {
|
|
26982
|
-
|
|
26735
|
+
sendJson(res, 500, { code: "STAT_FAILED", message: err.message });
|
|
26983
26736
|
}
|
|
26984
26737
|
return;
|
|
26985
26738
|
}
|
|
26986
26739
|
if (!stat.isFile()) {
|
|
26987
|
-
|
|
26740
|
+
sendJson(res, 400, { code: "NOT_A_FILE", message: "path is not a regular file" });
|
|
26988
26741
|
return;
|
|
26989
26742
|
}
|
|
26990
26743
|
const mime = lookupMime(absPath);
|
|
@@ -26994,7 +26747,7 @@ function streamFile(res, absPath, logger, onComplete) {
|
|
|
26994
26747
|
// 防止浏览器把任意 mime 当 html 渲染(spec §11 #8 安全心智)
|
|
26995
26748
|
"X-Content-Type-Options": "nosniff"
|
|
26996
26749
|
});
|
|
26997
|
-
const stream =
|
|
26750
|
+
const stream = import_node_fs14.default.createReadStream(absPath);
|
|
26998
26751
|
stream.on("error", (err) => {
|
|
26999
26752
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
27000
26753
|
res.destroy();
|
|
@@ -27006,9 +26759,9 @@ function streamFile(res, absPath, logger, onComplete) {
|
|
|
27006
26759
|
}
|
|
27007
26760
|
|
|
27008
26761
|
// src/attachment/outbox.ts
|
|
27009
|
-
var
|
|
27010
|
-
var
|
|
27011
|
-
var
|
|
26762
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
26763
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
26764
|
+
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
27012
26765
|
init_protocol();
|
|
27013
26766
|
var FILE_NAME = "outbox-caps.json";
|
|
27014
26767
|
var OutboxStore = class {
|
|
@@ -27017,14 +26770,14 @@ var OutboxStore = class {
|
|
|
27017
26770
|
logger;
|
|
27018
26771
|
cache = [];
|
|
27019
26772
|
constructor(opts) {
|
|
27020
|
-
this.file =
|
|
26773
|
+
this.file = import_node_path17.default.join(opts.dataDir, FILE_NAME);
|
|
27021
26774
|
this.now = opts.now ?? Date.now;
|
|
27022
26775
|
this.logger = opts.logger;
|
|
27023
26776
|
this.reload();
|
|
27024
26777
|
}
|
|
27025
26778
|
reload() {
|
|
27026
26779
|
try {
|
|
27027
|
-
const raw =
|
|
26780
|
+
const raw = import_node_fs15.default.readFileSync(this.file, "utf8");
|
|
27028
26781
|
const parsed = JSON.parse(raw);
|
|
27029
26782
|
if (!Array.isArray(parsed)) {
|
|
27030
26783
|
this.logger?.warn("OutboxStore.reload: outbox-caps.json is not an array; resetting", {
|
|
@@ -27051,10 +26804,10 @@ var OutboxStore = class {
|
|
|
27051
26804
|
}
|
|
27052
26805
|
}
|
|
27053
26806
|
persist() {
|
|
27054
|
-
|
|
26807
|
+
import_node_fs15.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
|
|
27055
26808
|
const tmp = `${this.file}.tmp-${process.pid}-${Date.now()}`;
|
|
27056
|
-
|
|
27057
|
-
|
|
26809
|
+
import_node_fs15.default.writeFileSync(tmp, JSON.stringify(this.cache, null, 2), { mode: 384 });
|
|
26810
|
+
import_node_fs15.default.renameSync(tmp, this.file);
|
|
27058
26811
|
}
|
|
27059
26812
|
/** 列出当前缓存(含 revoked / 过期,UI Drawer 显灰;过滤靠调用方) */
|
|
27060
26813
|
list() {
|
|
@@ -27076,7 +26829,7 @@ var OutboxStore = class {
|
|
|
27076
26829
|
const ts = this.now();
|
|
27077
26830
|
const ttl = input.ttlSeconds === null ? null : input.ttlSeconds ?? 24 * 3600;
|
|
27078
26831
|
const entry = {
|
|
27079
|
-
capToken:
|
|
26832
|
+
capToken: import_node_crypto5.default.randomBytes(32).toString("base64url"),
|
|
27080
26833
|
scopeRef: input.scopeRef,
|
|
27081
26834
|
absPath: input.absPath,
|
|
27082
26835
|
name: input.name,
|
|
@@ -27132,8 +26885,8 @@ var OutboxStore = class {
|
|
|
27132
26885
|
};
|
|
27133
26886
|
|
|
27134
26887
|
// src/attachment/mount.ts
|
|
27135
|
-
var
|
|
27136
|
-
var
|
|
26888
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
26889
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
27137
26890
|
init_protocol();
|
|
27138
26891
|
var MountStore = class {
|
|
27139
26892
|
constructor(opts) {
|
|
@@ -27141,11 +26894,11 @@ var MountStore = class {
|
|
|
27141
26894
|
}
|
|
27142
26895
|
opts;
|
|
27143
26896
|
filePath(personaId) {
|
|
27144
|
-
return
|
|
26897
|
+
return import_node_path18.default.join(this.opts.personaDirPath(personaId), ".clawd", "shared-files.json");
|
|
27145
26898
|
}
|
|
27146
26899
|
list(personaId) {
|
|
27147
26900
|
try {
|
|
27148
|
-
const raw =
|
|
26901
|
+
const raw = import_node_fs16.default.readFileSync(this.filePath(personaId), "utf8");
|
|
27149
26902
|
const parsed = JSON.parse(raw);
|
|
27150
26903
|
if (!Array.isArray(parsed)) return [];
|
|
27151
26904
|
const out = [];
|
|
@@ -27164,22 +26917,22 @@ var MountStore = class {
|
|
|
27164
26917
|
*/
|
|
27165
26918
|
add(personaId, input) {
|
|
27166
26919
|
const personaDir = this.opts.personaDirPath(personaId);
|
|
27167
|
-
if (!
|
|
26920
|
+
if (!import_node_fs16.default.existsSync(personaDir)) {
|
|
27168
26921
|
throw new Error(`personaDir not found: ${personaDir}`);
|
|
27169
26922
|
}
|
|
27170
|
-
const source =
|
|
27171
|
-
if (!
|
|
26923
|
+
const source = import_node_path18.default.resolve(input.absPath);
|
|
26924
|
+
if (!import_node_fs16.default.existsSync(source)) {
|
|
27172
26925
|
throw new Error(`source path not found: ${source}`);
|
|
27173
26926
|
}
|
|
27174
|
-
const basename =
|
|
27175
|
-
const dest =
|
|
27176
|
-
if (
|
|
26927
|
+
const basename = import_node_path18.default.basename(source);
|
|
26928
|
+
const dest = import_node_path18.default.join(personaDir, basename);
|
|
26929
|
+
if (import_node_fs16.default.existsSync(dest)) {
|
|
27177
26930
|
throw new Error(`destination already exists: ${dest}`);
|
|
27178
26931
|
}
|
|
27179
26932
|
if (input.mode === "link") {
|
|
27180
|
-
|
|
26933
|
+
import_node_fs16.default.symlinkSync(source, dest);
|
|
27181
26934
|
} else {
|
|
27182
|
-
|
|
26935
|
+
import_node_fs16.default.copyFileSync(source, dest);
|
|
27183
26936
|
}
|
|
27184
26937
|
const entry = {
|
|
27185
26938
|
basename,
|
|
@@ -27196,9 +26949,9 @@ var MountStore = class {
|
|
|
27196
26949
|
if (idx < 0) return false;
|
|
27197
26950
|
const entry = entries[idx];
|
|
27198
26951
|
const personaDir = this.opts.personaDirPath(personaId);
|
|
27199
|
-
const dest =
|
|
26952
|
+
const dest = import_node_path18.default.join(personaDir, basename);
|
|
27200
26953
|
try {
|
|
27201
|
-
|
|
26954
|
+
import_node_fs16.default.unlinkSync(dest);
|
|
27202
26955
|
} catch {
|
|
27203
26956
|
}
|
|
27204
26957
|
const next = entries.slice();
|
|
@@ -27209,18 +26962,18 @@ var MountStore = class {
|
|
|
27209
26962
|
}
|
|
27210
26963
|
writeManifest(personaId, entries) {
|
|
27211
26964
|
const file = this.filePath(personaId);
|
|
27212
|
-
|
|
26965
|
+
import_node_fs16.default.mkdirSync(import_node_path18.default.dirname(file), { recursive: true });
|
|
27213
26966
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
27214
|
-
|
|
27215
|
-
|
|
26967
|
+
import_node_fs16.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
26968
|
+
import_node_fs16.default.renameSync(tmp, file);
|
|
27216
26969
|
}
|
|
27217
26970
|
};
|
|
27218
26971
|
|
|
27219
26972
|
// src/discovery/state-file.ts
|
|
27220
|
-
var
|
|
27221
|
-
var
|
|
26973
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
26974
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
27222
26975
|
function defaultStateFilePath(dataDir) {
|
|
27223
|
-
return
|
|
26976
|
+
return import_node_path19.default.join(dataDir, "state.json");
|
|
27224
26977
|
}
|
|
27225
26978
|
function isPidAlive(pid) {
|
|
27226
26979
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -27242,7 +26995,7 @@ var StateFileManager = class {
|
|
|
27242
26995
|
}
|
|
27243
26996
|
read() {
|
|
27244
26997
|
try {
|
|
27245
|
-
const raw =
|
|
26998
|
+
const raw = import_node_fs17.default.readFileSync(this.file, "utf8");
|
|
27246
26999
|
const parsed = JSON.parse(raw);
|
|
27247
27000
|
return parsed;
|
|
27248
27001
|
} catch {
|
|
@@ -27256,34 +27009,34 @@ var StateFileManager = class {
|
|
|
27256
27009
|
return { status: "stale", existing };
|
|
27257
27010
|
}
|
|
27258
27011
|
write(state) {
|
|
27259
|
-
|
|
27012
|
+
import_node_fs17.default.mkdirSync(import_node_path19.default.dirname(this.file), { recursive: true });
|
|
27260
27013
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
27261
|
-
|
|
27262
|
-
|
|
27014
|
+
import_node_fs17.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
27015
|
+
import_node_fs17.default.renameSync(tmp, this.file);
|
|
27263
27016
|
if (process.platform !== "win32") {
|
|
27264
27017
|
try {
|
|
27265
|
-
|
|
27018
|
+
import_node_fs17.default.chmodSync(this.file, 384);
|
|
27266
27019
|
} catch {
|
|
27267
27020
|
}
|
|
27268
27021
|
}
|
|
27269
27022
|
}
|
|
27270
27023
|
delete() {
|
|
27271
27024
|
try {
|
|
27272
|
-
|
|
27025
|
+
import_node_fs17.default.unlinkSync(this.file);
|
|
27273
27026
|
} catch {
|
|
27274
27027
|
}
|
|
27275
27028
|
}
|
|
27276
27029
|
};
|
|
27277
27030
|
|
|
27278
27031
|
// src/tunnel/tunnel-manager.ts
|
|
27279
|
-
var
|
|
27280
|
-
var
|
|
27281
|
-
var
|
|
27032
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
27033
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
27034
|
+
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
27282
27035
|
var import_node_child_process5 = require("child_process");
|
|
27283
27036
|
|
|
27284
27037
|
// src/tunnel/tunnel-store.ts
|
|
27285
|
-
var
|
|
27286
|
-
var
|
|
27038
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
27039
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
27287
27040
|
var TunnelStore = class {
|
|
27288
27041
|
constructor(filePath) {
|
|
27289
27042
|
this.filePath = filePath;
|
|
@@ -27291,7 +27044,7 @@ var TunnelStore = class {
|
|
|
27291
27044
|
filePath;
|
|
27292
27045
|
async get() {
|
|
27293
27046
|
try {
|
|
27294
|
-
const raw = await
|
|
27047
|
+
const raw = await import_node_fs18.default.promises.readFile(this.filePath, "utf8");
|
|
27295
27048
|
const obj = JSON.parse(raw);
|
|
27296
27049
|
if (!isPersistedTunnel(obj)) return null;
|
|
27297
27050
|
return obj;
|
|
@@ -27302,22 +27055,22 @@ var TunnelStore = class {
|
|
|
27302
27055
|
}
|
|
27303
27056
|
}
|
|
27304
27057
|
async set(v2) {
|
|
27305
|
-
const dir =
|
|
27306
|
-
await
|
|
27058
|
+
const dir = import_node_path20.default.dirname(this.filePath);
|
|
27059
|
+
await import_node_fs18.default.promises.mkdir(dir, { recursive: true });
|
|
27307
27060
|
const data = JSON.stringify(v2, null, 2);
|
|
27308
27061
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
27309
|
-
await
|
|
27062
|
+
await import_node_fs18.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
27310
27063
|
if (process.platform !== "win32") {
|
|
27311
27064
|
try {
|
|
27312
|
-
await
|
|
27065
|
+
await import_node_fs18.default.promises.chmod(tmp, 384);
|
|
27313
27066
|
} catch {
|
|
27314
27067
|
}
|
|
27315
27068
|
}
|
|
27316
|
-
await
|
|
27069
|
+
await import_node_fs18.default.promises.rename(tmp, this.filePath);
|
|
27317
27070
|
}
|
|
27318
27071
|
async clear() {
|
|
27319
27072
|
try {
|
|
27320
|
-
await
|
|
27073
|
+
await import_node_fs18.default.promises.unlink(this.filePath);
|
|
27321
27074
|
} catch (err) {
|
|
27322
27075
|
const code = err?.code;
|
|
27323
27076
|
if (code !== "ENOENT") throw err;
|
|
@@ -27412,9 +27165,9 @@ function escape(v2) {
|
|
|
27412
27165
|
}
|
|
27413
27166
|
|
|
27414
27167
|
// src/tunnel/frpc-binary.ts
|
|
27415
|
-
var
|
|
27168
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
27416
27169
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
27417
|
-
var
|
|
27170
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
27418
27171
|
var import_node_child_process3 = require("child_process");
|
|
27419
27172
|
var import_node_stream2 = require("stream");
|
|
27420
27173
|
var import_promises = require("stream/promises");
|
|
@@ -27446,20 +27199,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
27446
27199
|
}
|
|
27447
27200
|
async function ensureFrpcBinary(opts) {
|
|
27448
27201
|
if (opts.override) {
|
|
27449
|
-
if (!
|
|
27202
|
+
if (!import_node_fs19.default.existsSync(opts.override)) {
|
|
27450
27203
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
27451
27204
|
}
|
|
27452
27205
|
return opts.override;
|
|
27453
27206
|
}
|
|
27454
27207
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
27455
27208
|
const platform = opts.platform ?? detectPlatform();
|
|
27456
|
-
const binDir =
|
|
27457
|
-
|
|
27209
|
+
const binDir = import_node_path21.default.join(opts.dataDir, "bin");
|
|
27210
|
+
import_node_fs19.default.mkdirSync(binDir, { recursive: true });
|
|
27458
27211
|
cleanupStaleArtifacts(binDir);
|
|
27459
|
-
const stableBin =
|
|
27460
|
-
if (
|
|
27212
|
+
const stableBin = import_node_path21.default.join(binDir, "frpc");
|
|
27213
|
+
if (import_node_fs19.default.existsSync(stableBin)) return stableBin;
|
|
27461
27214
|
const partialBin = `${stableBin}.partial`;
|
|
27462
|
-
const tarballPath =
|
|
27215
|
+
const tarballPath = import_node_path21.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
27463
27216
|
try {
|
|
27464
27217
|
const url = frpcDownloadUrl(version2, platform);
|
|
27465
27218
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -27468,8 +27221,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
27468
27221
|
} else {
|
|
27469
27222
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
27470
27223
|
}
|
|
27471
|
-
|
|
27472
|
-
|
|
27224
|
+
import_node_fs19.default.chmodSync(partialBin, 493);
|
|
27225
|
+
import_node_fs19.default.renameSync(partialBin, stableBin);
|
|
27473
27226
|
} finally {
|
|
27474
27227
|
safeUnlink(tarballPath);
|
|
27475
27228
|
safeUnlink(partialBin);
|
|
@@ -27479,15 +27232,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
27479
27232
|
function cleanupStaleArtifacts(binDir) {
|
|
27480
27233
|
let entries;
|
|
27481
27234
|
try {
|
|
27482
|
-
entries =
|
|
27235
|
+
entries = import_node_fs19.default.readdirSync(binDir);
|
|
27483
27236
|
} catch {
|
|
27484
27237
|
return;
|
|
27485
27238
|
}
|
|
27486
27239
|
for (const name of entries) {
|
|
27487
27240
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
27488
|
-
const full =
|
|
27241
|
+
const full = import_node_path21.default.join(binDir, name);
|
|
27489
27242
|
try {
|
|
27490
|
-
|
|
27243
|
+
import_node_fs19.default.rmSync(full, { recursive: true, force: true });
|
|
27491
27244
|
} catch {
|
|
27492
27245
|
}
|
|
27493
27246
|
}
|
|
@@ -27495,7 +27248,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
27495
27248
|
}
|
|
27496
27249
|
function safeUnlink(p2) {
|
|
27497
27250
|
try {
|
|
27498
|
-
|
|
27251
|
+
import_node_fs19.default.unlinkSync(p2);
|
|
27499
27252
|
} catch {
|
|
27500
27253
|
}
|
|
27501
27254
|
}
|
|
@@ -27506,13 +27259,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
27506
27259
|
if (!res.ok || !res.body) {
|
|
27507
27260
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
27508
27261
|
}
|
|
27509
|
-
const out =
|
|
27262
|
+
const out = import_node_fs19.default.createWriteStream(dest);
|
|
27510
27263
|
const nodeStream = import_node_stream2.Readable.fromWeb(res.body);
|
|
27511
27264
|
await (0, import_promises.pipeline)(nodeStream, out);
|
|
27512
27265
|
}
|
|
27513
27266
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
27514
|
-
const work =
|
|
27515
|
-
|
|
27267
|
+
const work = import_node_path21.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
27268
|
+
import_node_fs19.default.mkdirSync(work, { recursive: true });
|
|
27516
27269
|
try {
|
|
27517
27270
|
await new Promise((resolve2, reject) => {
|
|
27518
27271
|
const proc = (0, import_node_child_process3.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -27520,32 +27273,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
27520
27273
|
proc.on("exit", (code) => code === 0 ? resolve2() : reject(new Error(`tar exited ${code}`)));
|
|
27521
27274
|
});
|
|
27522
27275
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
27523
|
-
const src =
|
|
27524
|
-
if (!
|
|
27276
|
+
const src = import_node_path21.default.join(work, dirName, "frpc");
|
|
27277
|
+
if (!import_node_fs19.default.existsSync(src)) {
|
|
27525
27278
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
27526
27279
|
}
|
|
27527
|
-
|
|
27280
|
+
import_node_fs19.default.copyFileSync(src, destBin);
|
|
27528
27281
|
} finally {
|
|
27529
|
-
|
|
27282
|
+
import_node_fs19.default.rmSync(work, { recursive: true, force: true });
|
|
27530
27283
|
}
|
|
27531
27284
|
}
|
|
27532
27285
|
|
|
27533
27286
|
// src/tunnel/frpc-process.ts
|
|
27534
|
-
var
|
|
27535
|
-
var
|
|
27287
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
27288
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
27536
27289
|
var import_node_child_process4 = require("child_process");
|
|
27537
27290
|
function frpcPidFilePath(dataDir) {
|
|
27538
|
-
return
|
|
27291
|
+
return import_node_path22.default.join(dataDir, "frpc.pid");
|
|
27539
27292
|
}
|
|
27540
27293
|
function writeFrpcPid(dataDir, pid) {
|
|
27541
27294
|
try {
|
|
27542
|
-
|
|
27295
|
+
import_node_fs20.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
27543
27296
|
} catch {
|
|
27544
27297
|
}
|
|
27545
27298
|
}
|
|
27546
27299
|
function clearFrpcPid(dataDir) {
|
|
27547
27300
|
try {
|
|
27548
|
-
|
|
27301
|
+
import_node_fs20.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
27549
27302
|
} catch {
|
|
27550
27303
|
}
|
|
27551
27304
|
}
|
|
@@ -27561,7 +27314,7 @@ function defaultIsPidAlive(pid) {
|
|
|
27561
27314
|
}
|
|
27562
27315
|
function defaultReadPidFile(file) {
|
|
27563
27316
|
try {
|
|
27564
|
-
return
|
|
27317
|
+
return import_node_fs20.default.readFileSync(file, "utf8");
|
|
27565
27318
|
} catch {
|
|
27566
27319
|
return null;
|
|
27567
27320
|
}
|
|
@@ -27577,7 +27330,7 @@ function defaultSleep(ms) {
|
|
|
27577
27330
|
}
|
|
27578
27331
|
async function killStaleFrpc(deps) {
|
|
27579
27332
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
27580
|
-
const tomlPath =
|
|
27333
|
+
const tomlPath = import_node_path22.default.join(deps.dataDir, "frpc.toml");
|
|
27581
27334
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
27582
27335
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
27583
27336
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -27601,7 +27354,7 @@ async function killStaleFrpc(deps) {
|
|
|
27601
27354
|
}
|
|
27602
27355
|
if (victims.size === 0) {
|
|
27603
27356
|
try {
|
|
27604
|
-
|
|
27357
|
+
import_node_fs20.default.unlinkSync(pidFile);
|
|
27605
27358
|
} catch {
|
|
27606
27359
|
}
|
|
27607
27360
|
return;
|
|
@@ -27612,7 +27365,7 @@ async function killStaleFrpc(deps) {
|
|
|
27612
27365
|
}
|
|
27613
27366
|
await sleep(deps.reapWaitMs ?? 300);
|
|
27614
27367
|
try {
|
|
27615
|
-
|
|
27368
|
+
import_node_fs20.default.unlinkSync(pidFile);
|
|
27616
27369
|
} catch {
|
|
27617
27370
|
}
|
|
27618
27371
|
}
|
|
@@ -27649,7 +27402,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
27649
27402
|
var TunnelManager = class {
|
|
27650
27403
|
constructor(deps) {
|
|
27651
27404
|
this.deps = deps;
|
|
27652
|
-
this.store = deps.store ?? new TunnelStore(
|
|
27405
|
+
this.store = deps.store ?? new TunnelStore(import_node_path23.default.join(deps.dataDir, "tunnel.json"));
|
|
27653
27406
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
27654
27407
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
27655
27408
|
}
|
|
@@ -27776,8 +27529,8 @@ var TunnelManager = class {
|
|
|
27776
27529
|
dataDir: this.deps.dataDir,
|
|
27777
27530
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
27778
27531
|
});
|
|
27779
|
-
const tomlPath =
|
|
27780
|
-
const proxyName = `clawd-${t.subdomain}-${localPort}-${
|
|
27532
|
+
const tomlPath = import_node_path23.default.join(this.deps.dataDir, "frpc.toml");
|
|
27533
|
+
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto6.default.randomBytes(3).toString("hex")}`;
|
|
27781
27534
|
const toml = buildFrpcToml({
|
|
27782
27535
|
serverAddr: t.frpsHost,
|
|
27783
27536
|
serverPort: t.frpsPort,
|
|
@@ -27787,12 +27540,12 @@ var TunnelManager = class {
|
|
|
27787
27540
|
localPort,
|
|
27788
27541
|
logLevel: "info"
|
|
27789
27542
|
});
|
|
27790
|
-
await
|
|
27543
|
+
await import_node_fs21.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
27791
27544
|
const proc = (this.deps.spawnImpl ?? import_node_child_process5.spawn)(frpcBin, ["-c", tomlPath], {
|
|
27792
27545
|
stdio: ["ignore", "pipe", "pipe"]
|
|
27793
27546
|
});
|
|
27794
|
-
const logFilePath =
|
|
27795
|
-
const logStream =
|
|
27547
|
+
const logFilePath = import_node_path23.default.join(this.deps.dataDir, "frpc.log");
|
|
27548
|
+
const logStream = import_node_fs21.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
27796
27549
|
logStream.on("error", () => {
|
|
27797
27550
|
});
|
|
27798
27551
|
const tee = (chunk) => {
|
|
@@ -27875,22 +27628,22 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
27875
27628
|
|
|
27876
27629
|
// src/tunnel/device-key.ts
|
|
27877
27630
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
27878
|
-
var
|
|
27631
|
+
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
27879
27632
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
27880
27633
|
function deriveStableDeviceKey(opts = {}) {
|
|
27881
27634
|
const hostname = opts.hostname ?? import_node_os10.default.hostname();
|
|
27882
27635
|
const uid = opts.uid ?? (typeof import_node_os10.default.userInfo === "function" ? import_node_os10.default.userInfo().uid : 0);
|
|
27883
27636
|
const input = `${hostname}::${uid}`;
|
|
27884
|
-
return
|
|
27637
|
+
return import_node_crypto7.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
27885
27638
|
}
|
|
27886
27639
|
|
|
27887
27640
|
// src/auth-store.ts
|
|
27888
|
-
var
|
|
27889
|
-
var
|
|
27890
|
-
var
|
|
27641
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
27642
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
27643
|
+
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
27891
27644
|
var AUTH_FILE_NAME = "auth.json";
|
|
27892
27645
|
function authFilePath(dataDir) {
|
|
27893
|
-
return
|
|
27646
|
+
return import_node_path24.default.join(dataDir, AUTH_FILE_NAME);
|
|
27894
27647
|
}
|
|
27895
27648
|
function loadOrCreateAuthToken(opts) {
|
|
27896
27649
|
const file = authFilePath(opts.dataDir);
|
|
@@ -27902,11 +27655,11 @@ function loadOrCreateAuthToken(opts) {
|
|
|
27902
27655
|
return token;
|
|
27903
27656
|
}
|
|
27904
27657
|
function defaultGenerate() {
|
|
27905
|
-
return
|
|
27658
|
+
return import_node_crypto8.default.randomBytes(32).toString("base64url");
|
|
27906
27659
|
}
|
|
27907
27660
|
function readAuthFile(file) {
|
|
27908
27661
|
try {
|
|
27909
|
-
const raw =
|
|
27662
|
+
const raw = import_node_fs22.default.readFileSync(file, "utf8");
|
|
27910
27663
|
const parsed = JSON.parse(raw);
|
|
27911
27664
|
if (typeof parsed?.token === "string" && parsed.token.length > 0) {
|
|
27912
27665
|
return {
|
|
@@ -27922,25 +27675,25 @@ function readAuthFile(file) {
|
|
|
27922
27675
|
}
|
|
27923
27676
|
}
|
|
27924
27677
|
function writeAuthFile(file, content) {
|
|
27925
|
-
|
|
27926
|
-
|
|
27678
|
+
import_node_fs22.default.mkdirSync(import_node_path24.default.dirname(file), { recursive: true });
|
|
27679
|
+
import_node_fs22.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
27927
27680
|
try {
|
|
27928
|
-
|
|
27681
|
+
import_node_fs22.default.chmodSync(file, 384);
|
|
27929
27682
|
} catch {
|
|
27930
27683
|
}
|
|
27931
27684
|
}
|
|
27932
27685
|
|
|
27933
27686
|
// src/owner-profile.ts
|
|
27934
|
-
var
|
|
27687
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
27935
27688
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
27936
|
-
var
|
|
27689
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
27937
27690
|
var PROFILE_FILENAME = "profile.json";
|
|
27938
27691
|
function loadOwnerDisplayName(dataDir) {
|
|
27939
27692
|
const fallback = import_node_os11.default.userInfo().username;
|
|
27940
|
-
const profilePath =
|
|
27693
|
+
const profilePath = import_node_path25.default.join(dataDir, PROFILE_FILENAME);
|
|
27941
27694
|
let raw;
|
|
27942
27695
|
try {
|
|
27943
|
-
raw =
|
|
27696
|
+
raw = import_node_fs23.default.readFileSync(profilePath, "utf8");
|
|
27944
27697
|
} catch {
|
|
27945
27698
|
return fallback;
|
|
27946
27699
|
}
|
|
@@ -27969,12 +27722,12 @@ init_protocol();
|
|
|
27969
27722
|
init_protocol();
|
|
27970
27723
|
|
|
27971
27724
|
// src/session/fork.ts
|
|
27972
|
-
var
|
|
27725
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
27973
27726
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
27974
|
-
var
|
|
27727
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
27975
27728
|
init_claude_history();
|
|
27976
27729
|
function readJsonlEntries(file) {
|
|
27977
|
-
const raw =
|
|
27730
|
+
const raw = import_node_fs24.default.readFileSync(file, "utf8");
|
|
27978
27731
|
const out = [];
|
|
27979
27732
|
for (const line of raw.split("\n")) {
|
|
27980
27733
|
const t = line.trim();
|
|
@@ -27987,10 +27740,10 @@ function readJsonlEntries(file) {
|
|
|
27987
27740
|
return out;
|
|
27988
27741
|
}
|
|
27989
27742
|
function forkSession(input) {
|
|
27990
|
-
const baseDir = input.baseDir ??
|
|
27991
|
-
const projectDir =
|
|
27992
|
-
const sourceFile =
|
|
27993
|
-
if (!
|
|
27743
|
+
const baseDir = input.baseDir ?? import_node_path26.default.join(import_node_os12.default.homedir(), ".claude");
|
|
27744
|
+
const projectDir = import_node_path26.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
27745
|
+
const sourceFile = import_node_path26.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
27746
|
+
if (!import_node_fs24.default.existsSync(sourceFile)) {
|
|
27994
27747
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
27995
27748
|
}
|
|
27996
27749
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -28020,9 +27773,9 @@ function forkSession(input) {
|
|
|
28020
27773
|
}
|
|
28021
27774
|
forkedLines.push(JSON.stringify(forked));
|
|
28022
27775
|
}
|
|
28023
|
-
const forkedFilePath =
|
|
28024
|
-
|
|
28025
|
-
|
|
27776
|
+
const forkedFilePath = import_node_path26.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
27777
|
+
import_node_fs24.default.mkdirSync(projectDir, { recursive: true });
|
|
27778
|
+
import_node_fs24.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
28026
27779
|
return { forkedToolSessionId, forkedFilePath };
|
|
28027
27780
|
}
|
|
28028
27781
|
|
|
@@ -28343,9 +28096,9 @@ init_protocol();
|
|
|
28343
28096
|
|
|
28344
28097
|
// src/workspace/git.ts
|
|
28345
28098
|
var import_node_child_process6 = require("child_process");
|
|
28346
|
-
var
|
|
28099
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
28347
28100
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
28348
|
-
var
|
|
28101
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
28349
28102
|
var import_node_util = require("util");
|
|
28350
28103
|
var pexec = (0, import_node_util.promisify)(import_node_child_process6.execFile);
|
|
28351
28104
|
function formatChildProcessError(err) {
|
|
@@ -28360,9 +28113,9 @@ function formatChildProcessError(err) {
|
|
|
28360
28113
|
return e.message ?? "unknown error";
|
|
28361
28114
|
}
|
|
28362
28115
|
function normalizePath(p2) {
|
|
28363
|
-
const resolved =
|
|
28116
|
+
const resolved = import_node_path27.default.resolve(p2);
|
|
28364
28117
|
try {
|
|
28365
|
-
return
|
|
28118
|
+
return import_node_fs25.default.realpathSync(resolved);
|
|
28366
28119
|
} catch {
|
|
28367
28120
|
return resolved;
|
|
28368
28121
|
}
|
|
@@ -28463,13 +28216,13 @@ function flattenToDirName(branch) {
|
|
|
28463
28216
|
}
|
|
28464
28217
|
function encodeClaudeProjectDir(absPath) {
|
|
28465
28218
|
if (!absPath || typeof absPath !== "string") return "";
|
|
28466
|
-
let canonical =
|
|
28219
|
+
let canonical = import_node_path27.default.resolve(absPath);
|
|
28467
28220
|
try {
|
|
28468
|
-
canonical =
|
|
28221
|
+
canonical = import_node_fs25.default.realpathSync(canonical);
|
|
28469
28222
|
} catch {
|
|
28470
28223
|
try {
|
|
28471
|
-
const parent =
|
|
28472
|
-
canonical =
|
|
28224
|
+
const parent = import_node_fs25.default.realpathSync(import_node_path27.default.dirname(canonical));
|
|
28225
|
+
canonical = import_node_path27.default.join(parent, import_node_path27.default.basename(canonical));
|
|
28473
28226
|
} catch {
|
|
28474
28227
|
}
|
|
28475
28228
|
}
|
|
@@ -28493,11 +28246,11 @@ async function createWorktree(input) {
|
|
|
28493
28246
|
if (!isGitRoot) {
|
|
28494
28247
|
throw new Error(`\u76EE\u5F55 ${cwd} \u4E0D\u662F git repo \u6839`);
|
|
28495
28248
|
}
|
|
28496
|
-
const parent =
|
|
28497
|
-
if (parent === "/" || parent ===
|
|
28249
|
+
const parent = import_node_path27.default.dirname(import_node_path27.default.resolve(cwd));
|
|
28250
|
+
if (parent === "/" || parent === import_node_path27.default.resolve(cwd)) {
|
|
28498
28251
|
throw new Error("repo \u5728\u78C1\u76D8\u6839\u76EE\u5F55\uFF0C\u65E0\u6CD5\u5728\u540C\u7EA7\u521B\u5EFA worktree");
|
|
28499
28252
|
}
|
|
28500
|
-
const worktreeRoot =
|
|
28253
|
+
const worktreeRoot = import_node_path27.default.join(parent, dirName);
|
|
28501
28254
|
try {
|
|
28502
28255
|
await pexec("git", ["-C", cwd, "fetch", "origin", baseBranch, "--no-tags"], {
|
|
28503
28256
|
timeout: 3e4
|
|
@@ -28516,7 +28269,7 @@ async function createWorktree(input) {
|
|
|
28516
28269
|
const msg = err.message;
|
|
28517
28270
|
if (msg.startsWith("\u5206\u652F ")) throw err;
|
|
28518
28271
|
}
|
|
28519
|
-
if (
|
|
28272
|
+
if (import_node_fs25.default.existsSync(worktreeRoot)) {
|
|
28520
28273
|
throw new Error(`\u76EE\u5F55 ${worktreeRoot} \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A label \u6216\u6E05\u7406\u540E\u91CD\u8BD5`);
|
|
28521
28274
|
}
|
|
28522
28275
|
try {
|
|
@@ -28544,8 +28297,8 @@ async function removeWorktree(input) {
|
|
|
28544
28297
|
);
|
|
28545
28298
|
const gitCommonDir = stdout.trim();
|
|
28546
28299
|
if (!gitCommonDir) throw new Error("empty git-common-dir");
|
|
28547
|
-
const absGitCommon =
|
|
28548
|
-
repoRoot =
|
|
28300
|
+
const absGitCommon = import_node_path27.default.isAbsolute(gitCommonDir) ? gitCommonDir : import_node_path27.default.resolve(worktreeRoot, gitCommonDir);
|
|
28301
|
+
repoRoot = import_node_path27.default.dirname(absGitCommon);
|
|
28549
28302
|
} catch {
|
|
28550
28303
|
repoRoot = null;
|
|
28551
28304
|
}
|
|
@@ -28557,7 +28310,7 @@ async function removeWorktree(input) {
|
|
|
28557
28310
|
} catch (err) {
|
|
28558
28311
|
const stderr = err.stderr ?? "";
|
|
28559
28312
|
const lower = stderr.toLowerCase();
|
|
28560
|
-
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !
|
|
28313
|
+
const vanished = lower.includes("not a working tree") || lower.includes("is not a working tree") || !import_node_fs25.default.existsSync(worktreeRoot);
|
|
28561
28314
|
if (!vanished) {
|
|
28562
28315
|
throw new Error(`\u6E05\u7406 worktree \u5931\u8D25\uFF1A${formatChildProcessError(err)}`);
|
|
28563
28316
|
}
|
|
@@ -28576,10 +28329,10 @@ async function removeWorktree(input) {
|
|
|
28576
28329
|
try {
|
|
28577
28330
|
const encoded = encodeClaudeProjectDir(worktreeRoot);
|
|
28578
28331
|
if (encoded) {
|
|
28579
|
-
const projectsRoot =
|
|
28580
|
-
const target =
|
|
28581
|
-
if (target.startsWith(projectsRoot +
|
|
28582
|
-
|
|
28332
|
+
const projectsRoot = import_node_path27.default.join(import_node_os13.default.homedir(), ".claude", "projects");
|
|
28333
|
+
const target = import_node_path27.default.resolve(projectsRoot, encoded);
|
|
28334
|
+
if (target.startsWith(projectsRoot + import_node_path27.default.sep) && target !== projectsRoot) {
|
|
28335
|
+
import_node_fs25.default.rmSync(target, { recursive: true, force: true });
|
|
28583
28336
|
}
|
|
28584
28337
|
}
|
|
28585
28338
|
} catch {
|
|
@@ -29016,7 +28769,7 @@ function buildMethodHandlers(deps) {
|
|
|
29016
28769
|
async function startDaemon(config) {
|
|
29017
28770
|
const logger = createLogger({
|
|
29018
28771
|
level: config.logLevel,
|
|
29019
|
-
file:
|
|
28772
|
+
file: import_node_path28.default.join(config.dataDir, "clawd.log")
|
|
29020
28773
|
});
|
|
29021
28774
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
29022
28775
|
const stateMgr = new StateFileManager({ dataDir: config.dataDir });
|
|
@@ -29048,7 +28801,7 @@ async function startDaemon(config) {
|
|
|
29048
28801
|
const agents = new AgentsScanner();
|
|
29049
28802
|
const history = new ClaudeHistoryReader();
|
|
29050
28803
|
let transport = null;
|
|
29051
|
-
const personaStore = new PersonaStore(
|
|
28804
|
+
const personaStore = new PersonaStore(import_node_path28.default.join(config.dataDir, "personas"));
|
|
29052
28805
|
const defaultsRoot = findDefaultsRoot();
|
|
29053
28806
|
if (defaultsRoot) {
|
|
29054
28807
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -29067,7 +28820,7 @@ async function startDaemon(config) {
|
|
|
29067
28820
|
getAdapter,
|
|
29068
28821
|
historyReader: history,
|
|
29069
28822
|
dataDir: config.dataDir,
|
|
29070
|
-
personaRoot:
|
|
28823
|
+
personaRoot: import_node_path28.default.join(config.dataDir, "personas"),
|
|
29071
28824
|
personaStore,
|
|
29072
28825
|
ownerDisplayName,
|
|
29073
28826
|
mode: config.mode,
|
|
@@ -29090,10 +28843,10 @@ async function startDaemon(config) {
|
|
|
29090
28843
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
29091
28844
|
attachmentGroup: {
|
|
29092
28845
|
onFileEdit: (input) => {
|
|
29093
|
-
const absPath =
|
|
28846
|
+
const absPath = import_node_path28.default.isAbsolute(input.relPath) ? input.relPath : import_node_path28.default.join(input.cwd, input.relPath);
|
|
29094
28847
|
let size = 0;
|
|
29095
28848
|
try {
|
|
29096
|
-
size =
|
|
28849
|
+
size = import_node_fs26.default.statSync(absPath).size;
|
|
29097
28850
|
} catch (err) {
|
|
29098
28851
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
29099
28852
|
sessionId: input.sessionId,
|
|
@@ -29374,8 +29127,8 @@ async function startDaemon(config) {
|
|
|
29374
29127
|
const lines = [
|
|
29375
29128
|
`Tunnel: ${r.url}`,
|
|
29376
29129
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
29377
|
-
`Frpc config: ${
|
|
29378
|
-
`Frpc log: ${
|
|
29130
|
+
`Frpc config: ${import_node_path28.default.join(config.dataDir, "frpc.toml")}`,
|
|
29131
|
+
`Frpc log: ${import_node_path28.default.join(config.dataDir, "frpc.log")}`
|
|
29379
29132
|
];
|
|
29380
29133
|
const width = Math.max(...lines.map((l) => l.length));
|
|
29381
29134
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -29388,8 +29141,8 @@ ${bar}
|
|
|
29388
29141
|
|
|
29389
29142
|
`);
|
|
29390
29143
|
try {
|
|
29391
|
-
const connectPath =
|
|
29392
|
-
|
|
29144
|
+
const connectPath = import_node_path28.default.join(config.dataDir, "connect.txt");
|
|
29145
|
+
import_node_fs26.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
29393
29146
|
} catch {
|
|
29394
29147
|
}
|
|
29395
29148
|
} catch (err) {
|