@clawos-dev/clawd 0.2.352 → 0.2.353
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
CHANGED
|
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
|
|
|
450
450
|
init_errors();
|
|
451
451
|
init_en();
|
|
452
452
|
makeIssue = (params) => {
|
|
453
|
-
const { data, path:
|
|
454
|
-
const fullPath = [...
|
|
453
|
+
const { data, path: path82, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path82, ...issueData.path || []];
|
|
455
455
|
const fullIssue = {
|
|
456
456
|
...issueData,
|
|
457
457
|
path: fullPath
|
|
@@ -762,11 +762,11 @@ var init_types = __esm({
|
|
|
762
762
|
init_parseUtil();
|
|
763
763
|
init_util();
|
|
764
764
|
ParseInputLazyPath = class {
|
|
765
|
-
constructor(parent, value,
|
|
765
|
+
constructor(parent, value, path82, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path82;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -7018,6 +7018,10 @@ var init_schemas = __esm({
|
|
|
7018
7018
|
effort: external_exports.string().optional(),
|
|
7019
7019
|
// 归一化运行时观测字段(daemon 独立计算,session:update 不接受;meta_update 事件投递)
|
|
7020
7020
|
...sessionMetaShape,
|
|
7021
|
+
// daemon 生成智能标题的防重标记:reducer 在 meta_update.aiLabel 真变化时自动盖章
|
|
7022
|
+
// (observer ai-title 回灌与 daemon 自产两个生产者同路)。为空 = 还没生成过 →
|
|
7023
|
+
// manager.send 首条消息触发生成。session:update(外部 RPC)zod strip 不接受此字段。
|
|
7024
|
+
aiLabelGeneratedAt: external_exports.string().optional(),
|
|
7021
7025
|
permissionRules: external_exports.array(AllowRuleSchema).optional(),
|
|
7022
7026
|
// Sidebar 置顶时间戳;null/undefined 表示未置顶
|
|
7023
7027
|
pinnedAt: external_exports.number().int().nonnegative().nullable().optional(),
|
|
@@ -8960,8 +8964,8 @@ var require_req = __commonJS({
|
|
|
8960
8964
|
if (req.originalUrl) {
|
|
8961
8965
|
_req.url = req.originalUrl;
|
|
8962
8966
|
} else {
|
|
8963
|
-
const
|
|
8964
|
-
_req.url = typeof
|
|
8967
|
+
const path82 = req.path;
|
|
8968
|
+
_req.url = typeof path82 === "string" ? path82 : req.url ? req.url.path || req.url : void 0;
|
|
8965
8969
|
}
|
|
8966
8970
|
if (req.query) {
|
|
8967
8971
|
_req.query = req.query;
|
|
@@ -9126,14 +9130,14 @@ var require_redact = __commonJS({
|
|
|
9126
9130
|
}
|
|
9127
9131
|
return obj;
|
|
9128
9132
|
}
|
|
9129
|
-
function parsePath(
|
|
9133
|
+
function parsePath(path82) {
|
|
9130
9134
|
const parts = [];
|
|
9131
9135
|
let current = "";
|
|
9132
9136
|
let inBrackets = false;
|
|
9133
9137
|
let inQuotes = false;
|
|
9134
9138
|
let quoteChar = "";
|
|
9135
|
-
for (let i = 0; i <
|
|
9136
|
-
const char =
|
|
9139
|
+
for (let i = 0; i < path82.length; i++) {
|
|
9140
|
+
const char = path82[i];
|
|
9137
9141
|
if (!inBrackets && char === ".") {
|
|
9138
9142
|
if (current) {
|
|
9139
9143
|
parts.push(current);
|
|
@@ -9264,10 +9268,10 @@ var require_redact = __commonJS({
|
|
|
9264
9268
|
return current;
|
|
9265
9269
|
}
|
|
9266
9270
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9267
|
-
for (const
|
|
9268
|
-
const parts = parsePath(
|
|
9271
|
+
for (const path82 of paths) {
|
|
9272
|
+
const parts = parsePath(path82);
|
|
9269
9273
|
if (parts.includes("*")) {
|
|
9270
|
-
redactWildcardPath(obj, parts, censor,
|
|
9274
|
+
redactWildcardPath(obj, parts, censor, path82, remove);
|
|
9271
9275
|
} else {
|
|
9272
9276
|
if (remove) {
|
|
9273
9277
|
removeKey(obj, parts);
|
|
@@ -9352,8 +9356,8 @@ var require_redact = __commonJS({
|
|
|
9352
9356
|
}
|
|
9353
9357
|
} else {
|
|
9354
9358
|
if (afterWildcard.includes("*")) {
|
|
9355
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9356
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9359
|
+
const wrappedCensor = typeof censor === "function" ? (value, path82) => {
|
|
9360
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path82];
|
|
9357
9361
|
return censor(value, fullPath);
|
|
9358
9362
|
} : censor;
|
|
9359
9363
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9388,8 +9392,8 @@ var require_redact = __commonJS({
|
|
|
9388
9392
|
return null;
|
|
9389
9393
|
}
|
|
9390
9394
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9391
|
-
for (const
|
|
9392
|
-
const parts = parsePath(
|
|
9395
|
+
for (const path82 of pathsToClone) {
|
|
9396
|
+
const parts = parsePath(path82);
|
|
9393
9397
|
let current = pathStructure;
|
|
9394
9398
|
for (let i = 0; i < parts.length; i++) {
|
|
9395
9399
|
const part = parts[i];
|
|
@@ -9441,24 +9445,24 @@ var require_redact = __commonJS({
|
|
|
9441
9445
|
}
|
|
9442
9446
|
return cloneSelectively(obj, pathStructure);
|
|
9443
9447
|
}
|
|
9444
|
-
function validatePath(
|
|
9445
|
-
if (typeof
|
|
9448
|
+
function validatePath(path82) {
|
|
9449
|
+
if (typeof path82 !== "string") {
|
|
9446
9450
|
throw new Error("Paths must be (non-empty) strings");
|
|
9447
9451
|
}
|
|
9448
|
-
if (
|
|
9452
|
+
if (path82 === "") {
|
|
9449
9453
|
throw new Error("Invalid redaction path ()");
|
|
9450
9454
|
}
|
|
9451
|
-
if (
|
|
9452
|
-
throw new Error(`Invalid redaction path (${
|
|
9455
|
+
if (path82.includes("..")) {
|
|
9456
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9453
9457
|
}
|
|
9454
|
-
if (
|
|
9455
|
-
throw new Error(`Invalid redaction path (${
|
|
9458
|
+
if (path82.includes(",")) {
|
|
9459
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9456
9460
|
}
|
|
9457
9461
|
let bracketCount = 0;
|
|
9458
9462
|
let inQuotes = false;
|
|
9459
9463
|
let quoteChar = "";
|
|
9460
|
-
for (let i = 0; i <
|
|
9461
|
-
const char =
|
|
9464
|
+
for (let i = 0; i < path82.length; i++) {
|
|
9465
|
+
const char = path82[i];
|
|
9462
9466
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9463
9467
|
if (!inQuotes) {
|
|
9464
9468
|
inQuotes = true;
|
|
@@ -9472,20 +9476,20 @@ var require_redact = __commonJS({
|
|
|
9472
9476
|
} else if (char === "]" && !inQuotes) {
|
|
9473
9477
|
bracketCount--;
|
|
9474
9478
|
if (bracketCount < 0) {
|
|
9475
|
-
throw new Error(`Invalid redaction path (${
|
|
9479
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9476
9480
|
}
|
|
9477
9481
|
}
|
|
9478
9482
|
}
|
|
9479
9483
|
if (bracketCount !== 0) {
|
|
9480
|
-
throw new Error(`Invalid redaction path (${
|
|
9484
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9481
9485
|
}
|
|
9482
9486
|
}
|
|
9483
9487
|
function validatePaths(paths) {
|
|
9484
9488
|
if (!Array.isArray(paths)) {
|
|
9485
9489
|
throw new TypeError("paths must be an array");
|
|
9486
9490
|
}
|
|
9487
|
-
for (const
|
|
9488
|
-
validatePath(
|
|
9491
|
+
for (const path82 of paths) {
|
|
9492
|
+
validatePath(path82);
|
|
9489
9493
|
}
|
|
9490
9494
|
}
|
|
9491
9495
|
function slowRedact(options = {}) {
|
|
@@ -9653,8 +9657,8 @@ var require_redaction = __commonJS({
|
|
|
9653
9657
|
if (shape[k2] === null) {
|
|
9654
9658
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9655
9659
|
} else {
|
|
9656
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9657
|
-
return censor(value, [k2, ...
|
|
9660
|
+
const wrappedCensor = typeof censor === "function" ? (value, path82) => {
|
|
9661
|
+
return censor(value, [k2, ...path82]);
|
|
9658
9662
|
} : censor;
|
|
9659
9663
|
o[k2] = Redact({
|
|
9660
9664
|
paths: shape[k2],
|
|
@@ -9872,10 +9876,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
9872
9876
|
var require_sonic_boom = __commonJS({
|
|
9873
9877
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
9874
9878
|
"use strict";
|
|
9875
|
-
var
|
|
9879
|
+
var fs73 = require("fs");
|
|
9876
9880
|
var EventEmitter3 = require("events");
|
|
9877
9881
|
var inherits = require("util").inherits;
|
|
9878
|
-
var
|
|
9882
|
+
var path82 = require("path");
|
|
9879
9883
|
var sleep2 = require_atomic_sleep();
|
|
9880
9884
|
var assert = require("assert");
|
|
9881
9885
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -9929,20 +9933,20 @@ var require_sonic_boom = __commonJS({
|
|
|
9929
9933
|
const mode = sonic.mode;
|
|
9930
9934
|
if (sonic.sync) {
|
|
9931
9935
|
try {
|
|
9932
|
-
if (sonic.mkdir)
|
|
9933
|
-
const fd =
|
|
9936
|
+
if (sonic.mkdir) fs73.mkdirSync(path82.dirname(file), { recursive: true });
|
|
9937
|
+
const fd = fs73.openSync(file, flags, mode);
|
|
9934
9938
|
fileOpened(null, fd);
|
|
9935
9939
|
} catch (err) {
|
|
9936
9940
|
fileOpened(err);
|
|
9937
9941
|
throw err;
|
|
9938
9942
|
}
|
|
9939
9943
|
} else if (sonic.mkdir) {
|
|
9940
|
-
|
|
9944
|
+
fs73.mkdir(path82.dirname(file), { recursive: true }, (err) => {
|
|
9941
9945
|
if (err) return fileOpened(err);
|
|
9942
|
-
|
|
9946
|
+
fs73.open(file, flags, mode, fileOpened);
|
|
9943
9947
|
});
|
|
9944
9948
|
} else {
|
|
9945
|
-
|
|
9949
|
+
fs73.open(file, flags, mode, fileOpened);
|
|
9946
9950
|
}
|
|
9947
9951
|
}
|
|
9948
9952
|
function SonicBoom(opts) {
|
|
@@ -9983,8 +9987,8 @@ var require_sonic_boom = __commonJS({
|
|
|
9983
9987
|
this.flush = flushBuffer;
|
|
9984
9988
|
this.flushSync = flushBufferSync;
|
|
9985
9989
|
this._actualWrite = actualWriteBuffer;
|
|
9986
|
-
fsWriteSync = () =>
|
|
9987
|
-
fsWrite = () =>
|
|
9990
|
+
fsWriteSync = () => fs73.writeSync(this.fd, this._writingBuf);
|
|
9991
|
+
fsWrite = () => fs73.write(this.fd, this._writingBuf, this.release);
|
|
9988
9992
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
9989
9993
|
this._writingBuf = "";
|
|
9990
9994
|
this.write = write;
|
|
@@ -9993,15 +9997,15 @@ var require_sonic_boom = __commonJS({
|
|
|
9993
9997
|
this._actualWrite = actualWrite;
|
|
9994
9998
|
fsWriteSync = () => {
|
|
9995
9999
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9996
|
-
return
|
|
10000
|
+
return fs73.writeSync(this.fd, this._writingBuf);
|
|
9997
10001
|
}
|
|
9998
|
-
return
|
|
10002
|
+
return fs73.writeSync(this.fd, this._writingBuf, "utf8");
|
|
9999
10003
|
};
|
|
10000
10004
|
fsWrite = () => {
|
|
10001
10005
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10002
|
-
return
|
|
10006
|
+
return fs73.write(this.fd, this._writingBuf, this.release);
|
|
10003
10007
|
}
|
|
10004
|
-
return
|
|
10008
|
+
return fs73.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10005
10009
|
};
|
|
10006
10010
|
} else {
|
|
10007
10011
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10058,7 +10062,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10058
10062
|
}
|
|
10059
10063
|
}
|
|
10060
10064
|
if (this._fsync) {
|
|
10061
|
-
|
|
10065
|
+
fs73.fsyncSync(this.fd);
|
|
10062
10066
|
}
|
|
10063
10067
|
const len = this._len;
|
|
10064
10068
|
if (this._reopening) {
|
|
@@ -10172,7 +10176,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10172
10176
|
const onDrain = () => {
|
|
10173
10177
|
if (!this._fsync) {
|
|
10174
10178
|
try {
|
|
10175
|
-
|
|
10179
|
+
fs73.fsync(this.fd, (err) => {
|
|
10176
10180
|
this._flushPending = false;
|
|
10177
10181
|
cb(err);
|
|
10178
10182
|
});
|
|
@@ -10274,7 +10278,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10274
10278
|
const fd = this.fd;
|
|
10275
10279
|
this.once("ready", () => {
|
|
10276
10280
|
if (fd !== this.fd) {
|
|
10277
|
-
|
|
10281
|
+
fs73.close(fd, (err) => {
|
|
10278
10282
|
if (err) {
|
|
10279
10283
|
return this.emit("error", err);
|
|
10280
10284
|
}
|
|
@@ -10323,7 +10327,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10323
10327
|
buf = this._bufs[0];
|
|
10324
10328
|
}
|
|
10325
10329
|
try {
|
|
10326
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10330
|
+
const n = Buffer.isBuffer(buf) ? fs73.writeSync(this.fd, buf) : fs73.writeSync(this.fd, buf, "utf8");
|
|
10327
10331
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10328
10332
|
buf = releasedBufObj.writingBuf;
|
|
10329
10333
|
this._len = releasedBufObj.len;
|
|
@@ -10339,7 +10343,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10339
10343
|
}
|
|
10340
10344
|
}
|
|
10341
10345
|
try {
|
|
10342
|
-
|
|
10346
|
+
fs73.fsyncSync(this.fd);
|
|
10343
10347
|
} catch {
|
|
10344
10348
|
}
|
|
10345
10349
|
}
|
|
@@ -10360,7 +10364,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10360
10364
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10361
10365
|
}
|
|
10362
10366
|
try {
|
|
10363
|
-
const n =
|
|
10367
|
+
const n = fs73.writeSync(this.fd, buf);
|
|
10364
10368
|
buf = buf.subarray(n);
|
|
10365
10369
|
this._len = Math.max(this._len - n, 0);
|
|
10366
10370
|
if (buf.length <= 0) {
|
|
@@ -10388,13 +10392,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10388
10392
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10389
10393
|
if (this.sync) {
|
|
10390
10394
|
try {
|
|
10391
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
10395
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs73.writeSync(this.fd, this._writingBuf) : fs73.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10392
10396
|
release(null, written);
|
|
10393
10397
|
} catch (err) {
|
|
10394
10398
|
release(err);
|
|
10395
10399
|
}
|
|
10396
10400
|
} else {
|
|
10397
|
-
|
|
10401
|
+
fs73.write(this.fd, this._writingBuf, release);
|
|
10398
10402
|
}
|
|
10399
10403
|
}
|
|
10400
10404
|
function actualWriteBuffer() {
|
|
@@ -10403,7 +10407,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10403
10407
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10404
10408
|
if (this.sync) {
|
|
10405
10409
|
try {
|
|
10406
|
-
const written =
|
|
10410
|
+
const written = fs73.writeSync(this.fd, this._writingBuf);
|
|
10407
10411
|
release(null, written);
|
|
10408
10412
|
} catch (err) {
|
|
10409
10413
|
release(err);
|
|
@@ -10412,7 +10416,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10412
10416
|
if (kCopyBuffer) {
|
|
10413
10417
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10414
10418
|
}
|
|
10415
|
-
|
|
10419
|
+
fs73.write(this.fd, this._writingBuf, release);
|
|
10416
10420
|
}
|
|
10417
10421
|
}
|
|
10418
10422
|
function actualClose(sonic) {
|
|
@@ -10428,12 +10432,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10428
10432
|
sonic._lens = [];
|
|
10429
10433
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10430
10434
|
try {
|
|
10431
|
-
|
|
10435
|
+
fs73.fsync(sonic.fd, closeWrapped);
|
|
10432
10436
|
} catch {
|
|
10433
10437
|
}
|
|
10434
10438
|
function closeWrapped() {
|
|
10435
10439
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10436
|
-
|
|
10440
|
+
fs73.close(sonic.fd, done);
|
|
10437
10441
|
} else {
|
|
10438
10442
|
done();
|
|
10439
10443
|
}
|
|
@@ -12797,7 +12801,7 @@ var require_multistream = __commonJS({
|
|
|
12797
12801
|
var require_pino = __commonJS({
|
|
12798
12802
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
12799
12803
|
"use strict";
|
|
12800
|
-
var
|
|
12804
|
+
var os26 = require("os");
|
|
12801
12805
|
var stdSerializers = require_pino_std_serializers();
|
|
12802
12806
|
var caller = require_caller();
|
|
12803
12807
|
var redaction = require_redaction();
|
|
@@ -12844,7 +12848,7 @@ var require_pino = __commonJS({
|
|
|
12844
12848
|
} = symbols;
|
|
12845
12849
|
var { epochTime, nullTime } = time;
|
|
12846
12850
|
var { pid } = process;
|
|
12847
|
-
var hostname =
|
|
12851
|
+
var hostname = os26.hostname();
|
|
12848
12852
|
var defaultErrorSerializer = stdSerializers.err;
|
|
12849
12853
|
var defaultOptions2 = {
|
|
12850
12854
|
level: "info",
|
|
@@ -13568,11 +13572,11 @@ var init_lib = __esm({
|
|
|
13568
13572
|
}
|
|
13569
13573
|
}
|
|
13570
13574
|
},
|
|
13571
|
-
addToPath: function addToPath(
|
|
13572
|
-
var last =
|
|
13575
|
+
addToPath: function addToPath(path82, added, removed, oldPosInc, options) {
|
|
13576
|
+
var last = path82.lastComponent;
|
|
13573
13577
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13574
13578
|
return {
|
|
13575
|
-
oldPos:
|
|
13579
|
+
oldPos: path82.oldPos + oldPosInc,
|
|
13576
13580
|
lastComponent: {
|
|
13577
13581
|
count: last.count + 1,
|
|
13578
13582
|
added,
|
|
@@ -13582,7 +13586,7 @@ var init_lib = __esm({
|
|
|
13582
13586
|
};
|
|
13583
13587
|
} else {
|
|
13584
13588
|
return {
|
|
13585
|
-
oldPos:
|
|
13589
|
+
oldPos: path82.oldPos + oldPosInc,
|
|
13586
13590
|
lastComponent: {
|
|
13587
13591
|
count: 1,
|
|
13588
13592
|
added,
|
|
@@ -14114,10 +14118,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14114
14118
|
const memories = raw.map((m2) => {
|
|
14115
14119
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14116
14120
|
const rec4 = m2;
|
|
14117
|
-
const
|
|
14121
|
+
const path82 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14118
14122
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14119
|
-
if (!
|
|
14120
|
-
const entry = { path:
|
|
14123
|
+
if (!path82 || content == null) return null;
|
|
14124
|
+
const entry = { path: path82, content };
|
|
14121
14125
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14122
14126
|
return entry;
|
|
14123
14127
|
}).filter((m2) => m2 !== null);
|
|
@@ -14951,10 +14955,10 @@ function parseAttachment(obj) {
|
|
|
14951
14955
|
const memories = raw.map((m2) => {
|
|
14952
14956
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14953
14957
|
const rec4 = m2;
|
|
14954
|
-
const
|
|
14958
|
+
const path82 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14955
14959
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14956
|
-
if (!
|
|
14957
|
-
const out = { path:
|
|
14960
|
+
if (!path82 || content == null) return null;
|
|
14961
|
+
const out = { path: path82, content };
|
|
14958
14962
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
14959
14963
|
return out;
|
|
14960
14964
|
}).filter((m2) => m2 !== null);
|
|
@@ -35928,8 +35932,8 @@ var require_utils = __commonJS({
|
|
|
35928
35932
|
var result = transform[inputType][outputType](input);
|
|
35929
35933
|
return result;
|
|
35930
35934
|
};
|
|
35931
|
-
exports2.resolve = function(
|
|
35932
|
-
var parts =
|
|
35935
|
+
exports2.resolve = function(path82) {
|
|
35936
|
+
var parts = path82.split("/");
|
|
35933
35937
|
var result = [];
|
|
35934
35938
|
for (var index = 0; index < parts.length; index++) {
|
|
35935
35939
|
var part = parts[index];
|
|
@@ -41782,18 +41786,18 @@ var require_object = __commonJS({
|
|
|
41782
41786
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
41783
41787
|
this.files[name] = object;
|
|
41784
41788
|
};
|
|
41785
|
-
var parentFolder = function(
|
|
41786
|
-
if (
|
|
41787
|
-
|
|
41789
|
+
var parentFolder = function(path82) {
|
|
41790
|
+
if (path82.slice(-1) === "/") {
|
|
41791
|
+
path82 = path82.substring(0, path82.length - 1);
|
|
41788
41792
|
}
|
|
41789
|
-
var lastSlash =
|
|
41790
|
-
return lastSlash > 0 ?
|
|
41793
|
+
var lastSlash = path82.lastIndexOf("/");
|
|
41794
|
+
return lastSlash > 0 ? path82.substring(0, lastSlash) : "";
|
|
41791
41795
|
};
|
|
41792
|
-
var forceTrailingSlash = function(
|
|
41793
|
-
if (
|
|
41794
|
-
|
|
41796
|
+
var forceTrailingSlash = function(path82) {
|
|
41797
|
+
if (path82.slice(-1) !== "/") {
|
|
41798
|
+
path82 += "/";
|
|
41795
41799
|
}
|
|
41796
|
-
return
|
|
41800
|
+
return path82;
|
|
41797
41801
|
};
|
|
41798
41802
|
var folderAdd = function(name, createFolders) {
|
|
41799
41803
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -42795,7 +42799,7 @@ var require_lib3 = __commonJS({
|
|
|
42795
42799
|
// src/run-case/recorder.ts
|
|
42796
42800
|
function startRunCaseRecorder(opts) {
|
|
42797
42801
|
const now = opts.now ?? Date.now;
|
|
42798
|
-
const dir =
|
|
42802
|
+
const dir = import_node_path69.default.dirname(opts.recordPath);
|
|
42799
42803
|
let stream = null;
|
|
42800
42804
|
let closing = false;
|
|
42801
42805
|
let closedSettled = false;
|
|
@@ -42809,8 +42813,8 @@ function startRunCaseRecorder(opts) {
|
|
|
42809
42813
|
});
|
|
42810
42814
|
const ensureStream = () => {
|
|
42811
42815
|
if (stream) return stream;
|
|
42812
|
-
|
|
42813
|
-
stream =
|
|
42816
|
+
import_node_fs53.default.mkdirSync(dir, { recursive: true });
|
|
42817
|
+
stream = import_node_fs53.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
42814
42818
|
stream.on("close", () => closedResolve());
|
|
42815
42819
|
return stream;
|
|
42816
42820
|
};
|
|
@@ -42835,12 +42839,12 @@ function startRunCaseRecorder(opts) {
|
|
|
42835
42839
|
};
|
|
42836
42840
|
return { tap, close, closed };
|
|
42837
42841
|
}
|
|
42838
|
-
var
|
|
42842
|
+
var import_node_fs53, import_node_path69;
|
|
42839
42843
|
var init_recorder = __esm({
|
|
42840
42844
|
"src/run-case/recorder.ts"() {
|
|
42841
42845
|
"use strict";
|
|
42842
|
-
|
|
42843
|
-
|
|
42846
|
+
import_node_fs53 = __toESM(require("fs"), 1);
|
|
42847
|
+
import_node_path69 = __toESM(require("path"), 1);
|
|
42844
42848
|
}
|
|
42845
42849
|
});
|
|
42846
42850
|
|
|
@@ -42883,7 +42887,7 @@ var init_wire = __esm({
|
|
|
42883
42887
|
// src/run-case/controller.ts
|
|
42884
42888
|
async function runController(opts) {
|
|
42885
42889
|
const now = opts.now ?? Date.now;
|
|
42886
|
-
const cwd = opts.cwd ?? (0,
|
|
42890
|
+
const cwd = opts.cwd ?? (0, import_node_fs54.mkdtempSync)(import_node_path70.default.join(import_node_os25.default.tmpdir(), "clawd-runcase-"));
|
|
42887
42891
|
const ownsCwd = opts.cwd === void 0;
|
|
42888
42892
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
42889
42893
|
const spawnCtx = { cwd };
|
|
@@ -43044,19 +43048,19 @@ async function runController(opts) {
|
|
|
43044
43048
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
43045
43049
|
if (ownsCwd) {
|
|
43046
43050
|
try {
|
|
43047
|
-
(0,
|
|
43051
|
+
(0, import_node_fs54.rmSync)(cwd, { recursive: true, force: true });
|
|
43048
43052
|
} catch {
|
|
43049
43053
|
}
|
|
43050
43054
|
}
|
|
43051
43055
|
return exitCode ?? 0;
|
|
43052
43056
|
}
|
|
43053
|
-
var
|
|
43057
|
+
var import_node_fs54, import_node_os25, import_node_path70;
|
|
43054
43058
|
var init_controller = __esm({
|
|
43055
43059
|
"src/run-case/controller.ts"() {
|
|
43056
43060
|
"use strict";
|
|
43057
|
-
|
|
43058
|
-
|
|
43059
|
-
|
|
43061
|
+
import_node_fs54 = require("fs");
|
|
43062
|
+
import_node_os25 = __toESM(require("os"), 1);
|
|
43063
|
+
import_node_path70 = __toESM(require("path"), 1);
|
|
43060
43064
|
init_claude();
|
|
43061
43065
|
init_stdout_splitter();
|
|
43062
43066
|
init_permission_stdio();
|
|
@@ -43331,9 +43335,9 @@ Env (advanced):
|
|
|
43331
43335
|
`;
|
|
43332
43336
|
|
|
43333
43337
|
// src/index.ts
|
|
43334
|
-
var
|
|
43335
|
-
var
|
|
43336
|
-
var
|
|
43338
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
43339
|
+
var import_node_fs52 = __toESM(require("fs"), 1);
|
|
43340
|
+
var import_node_os24 = __toESM(require("os"), 1);
|
|
43337
43341
|
|
|
43338
43342
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
43339
43343
|
var byteToHex = [];
|
|
@@ -44619,9 +44623,13 @@ function applyMetaUpdate(state, patch, deps) {
|
|
|
44619
44623
|
const w2 = deps.resolveContextWindow?.(next.file.tool, patch.resolvedModel);
|
|
44620
44624
|
if (w2 !== void 0) merged.contextWindowSize = w2;
|
|
44621
44625
|
}
|
|
44622
|
-
|
|
44626
|
+
const aiLabelArrived = patch.aiLabel !== void 0 && (patch.aiLabel !== next.file.aiLabel || !next.file.aiLabelGeneratedAt);
|
|
44627
|
+
if (shallowEqMeta(next.file, merged) && !aiLabelArrived) {
|
|
44623
44628
|
return { state: next, effects: [] };
|
|
44624
44629
|
}
|
|
44630
|
+
if (aiLabelArrived) {
|
|
44631
|
+
merged.aiLabelGeneratedAt = nowIso(deps);
|
|
44632
|
+
}
|
|
44625
44633
|
next.file = merged;
|
|
44626
44634
|
return {
|
|
44627
44635
|
state: next,
|
|
@@ -45950,6 +45958,8 @@ var SessionManager = class {
|
|
|
45950
45958
|
deps;
|
|
45951
45959
|
// sessionId → SessionRunner;在 send / ensureSession 时按需创建
|
|
45952
45960
|
runners = /* @__PURE__ */ new Map();
|
|
45961
|
+
// 标题生成 in-flight 防重(进程内);跨重启防重靠 SessionFile.aiLabelGeneratedAt
|
|
45962
|
+
titleGenPending = /* @__PURE__ */ new Set();
|
|
45953
45963
|
// 当同步命令执行期间,runner 的 emit-frame 临时 push 到这里;
|
|
45954
45964
|
// null 表示当前是异步路径(stdout 'data' / proc 'exit' 等),走 deps.broadcastFrame
|
|
45955
45965
|
currentCollector = null;
|
|
@@ -46775,8 +46785,38 @@ var SessionManager = class {
|
|
|
46775
46785
|
command: { kind: "send", text: args.text, senderPrincipal }
|
|
46776
46786
|
});
|
|
46777
46787
|
});
|
|
46788
|
+
this.maybeGenerateTitle(existing, args.text);
|
|
46778
46789
|
return { response: { ok: true }, broadcast };
|
|
46779
46790
|
}
|
|
46791
|
+
/**
|
|
46792
|
+
* 首条 send 触发的智能标题自产(spec:PR #1196 追加拍板 2026-08-17)。
|
|
46793
|
+
* 背景见 tools/title-generator.ts 头注释——CC/codex 两条上游标题数据源都等不来
|
|
46794
|
+
* 「首轮即有」,daemon 用会话同家族小模型自己生成,与主 turn 并行,几秒后经
|
|
46795
|
+
* manager.update 内部通道写 aiLabel(marker patch:不刷 updatedAt、广播 session:info)。
|
|
46796
|
+
*
|
|
46797
|
+
* 跳过条件:
|
|
46798
|
+
* - aiLabelGeneratedAt 已盖章(成功过;失败不盖章 → 下次 send 自然重试)
|
|
46799
|
+
* - label 非空(用户手输/dispatch 显式命名,显示优先级下 aiLabel 永远不可见,纯浪费)
|
|
46800
|
+
* - larkChatId 非空(lark 群会话显示群名是产品语义,AI 标题反而会遮住群名)
|
|
46801
|
+
* - 进程内已有同 session 的 in-flight 调用
|
|
46802
|
+
*/
|
|
46803
|
+
maybeGenerateTitle(file, text) {
|
|
46804
|
+
const generate = this.deps.generateTitle;
|
|
46805
|
+
if (!generate) return;
|
|
46806
|
+
const sessionId = file.sessionId;
|
|
46807
|
+
if (file.aiLabelGeneratedAt || file.label || file.larkChatId) return;
|
|
46808
|
+
if (this.titleGenPending.has(sessionId)) return;
|
|
46809
|
+
this.titleGenPending.add(sessionId);
|
|
46810
|
+
void generate(file.tool ?? "claude", text).then((title) => {
|
|
46811
|
+
if (!title) return;
|
|
46812
|
+
this.applyResolvedMeta(sessionId, { aiLabel: title });
|
|
46813
|
+
this.deps.logger?.info("title-gen ok", { sessionId, tool: file.tool, title });
|
|
46814
|
+
}).catch((err) => {
|
|
46815
|
+
this.deps.logger?.warn("title-gen failed", { sessionId, message: err.message });
|
|
46816
|
+
}).finally(() => {
|
|
46817
|
+
this.titleGenPending.delete(sessionId);
|
|
46818
|
+
});
|
|
46819
|
+
}
|
|
46780
46820
|
/**
|
|
46781
46821
|
* Dispatch 结果投递(spec 2026-07-20 §5):查台账里该 source session 名下已完成
|
|
46782
46822
|
* 且未投递的行,合并成一段 plain text 结果包注入回 source session。
|
|
@@ -49771,8 +49811,8 @@ function turnStartInput(text) {
|
|
|
49771
49811
|
const items = [];
|
|
49772
49812
|
let leftover = text;
|
|
49773
49813
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
49774
|
-
const [marker, name,
|
|
49775
|
-
items.push({ type: "skill", name, path:
|
|
49814
|
+
const [marker, name, path82] = m2;
|
|
49815
|
+
items.push({ type: "skill", name, path: path82 });
|
|
49776
49816
|
leftover = leftover.replace(marker, "");
|
|
49777
49817
|
}
|
|
49778
49818
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -53728,13 +53768,13 @@ function mapSkillsListResponse(res) {
|
|
|
53728
53768
|
const r = s ?? {};
|
|
53729
53769
|
const name = str3(r.name);
|
|
53730
53770
|
if (!name) continue;
|
|
53731
|
-
const
|
|
53771
|
+
const path82 = str3(r.path);
|
|
53732
53772
|
const description = str3(r.description);
|
|
53733
53773
|
const isPlugin = name.includes(":");
|
|
53734
53774
|
out.push({
|
|
53735
53775
|
name,
|
|
53736
53776
|
source: isPlugin ? "plugin" : "project",
|
|
53737
|
-
...
|
|
53777
|
+
...path82 ? { path: path82 } : {},
|
|
53738
53778
|
...description ? { description } : {},
|
|
53739
53779
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
53740
53780
|
});
|
|
@@ -54502,6 +54542,149 @@ function listRegistered() {
|
|
|
54502
54542
|
return [...registry.keys()];
|
|
54503
54543
|
}
|
|
54504
54544
|
|
|
54545
|
+
// src/tools/title-generator.ts
|
|
54546
|
+
var import_node_child_process8 = require("child_process");
|
|
54547
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
54548
|
+
var import_node_os12 = __toESM(require("os"), 1);
|
|
54549
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
54550
|
+
var TITLE_GEN_DIR_NAME = "clawd-title-gen";
|
|
54551
|
+
var TITLE_MODEL_BY_TOOL = {
|
|
54552
|
+
claude: "haiku",
|
|
54553
|
+
codex: "gpt-5.4-mini"
|
|
54554
|
+
};
|
|
54555
|
+
var TITLE_INPUT_MAX_CHARS = 400;
|
|
54556
|
+
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
54557
|
+
var outFileSeq = 0;
|
|
54558
|
+
function buildTitlePrompt(firstMessage) {
|
|
54559
|
+
const text = firstMessage.slice(0, TITLE_INPUT_MAX_CHARS);
|
|
54560
|
+
return `\u4E3A\u4E0B\u9762\u8FD9\u6761\u7528\u6237\u6D88\u606F\u751F\u6210\u4E00\u4E2A\u7B80\u6D01\u7684\u4F1A\u8BDD\u6807\u9898\uFF1A\u4E0D\u8D85\u8FC7 20 \u4E2A\u5B57\uFF08\u82F1\u6587\u5219\u4E0D\u8D85\u8FC7 6 \u4E2A\u5355\u8BCD\uFF09\uFF0C\u4F7F\u7528\u4E0E\u6D88\u606F\u76F8\u540C\u7684\u8BED\u8A00\uFF0C\u53EA\u6982\u62EC\u6D88\u606F\u4E3B\u9898\u3002
|
|
54561
|
+
|
|
54562
|
+
\u7528\u6237\u6D88\u606F\uFF1A
|
|
54563
|
+
${text}`;
|
|
54564
|
+
}
|
|
54565
|
+
function buildClaudeTitlePrompt(firstMessage) {
|
|
54566
|
+
return buildTitlePrompt(firstMessage) + '\n\n\u53EA\u8F93\u51FA\u4E00\u4E2A JSON \u5BF9\u8C61\uFF0C\u683C\u5F0F\uFF1A{"greeting":"\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC","title":"\u4F1A\u8BDD\u6807\u9898"}\uFF0C\u4E0D\u8981\u8F93\u51FA JSON \u4EE5\u5916\u7684\u4EFB\u4F55\u5185\u5BB9\u3002';
|
|
54567
|
+
}
|
|
54568
|
+
function sanitizeTitle(raw) {
|
|
54569
|
+
const line = raw.split("\n").map((l) => l.trim()).find((l) => l.length > 0);
|
|
54570
|
+
if (!line) return null;
|
|
54571
|
+
const stripped = line.replace(/^["'“”‘’「」《》\[\((]+/, "").replace(/["'“”‘’「」《》\]\))]+$/, "").replace(/[。..!!??]+$/, "").replace(/\s+/g, " ").trim();
|
|
54572
|
+
if (!stripped) return null;
|
|
54573
|
+
return stripped.slice(0, 60);
|
|
54574
|
+
}
|
|
54575
|
+
function buildClaudeTitleArgs(prompt) {
|
|
54576
|
+
return ["-p", "--model", TITLE_MODEL_BY_TOOL.claude, prompt];
|
|
54577
|
+
}
|
|
54578
|
+
var CODEX_TITLE_SCHEMA = JSON.stringify({
|
|
54579
|
+
type: "object",
|
|
54580
|
+
properties: {
|
|
54581
|
+
greeting: { type: "string", description: "\u4F60\u7684\u89C4\u5219\u8981\u6C42\u7684\u79F0\u547C/\u95EE\u5019\u653E\u8FD9\u91CC" },
|
|
54582
|
+
title: { type: "string", description: "\u4F1A\u8BDD\u6807\u9898\uFF1A\u53EA\u542B\u6D88\u606F\u4E3B\u9898" }
|
|
54583
|
+
},
|
|
54584
|
+
required: ["greeting", "title"],
|
|
54585
|
+
additionalProperties: false
|
|
54586
|
+
});
|
|
54587
|
+
function parseTitleJson(raw) {
|
|
54588
|
+
const text = raw.trim().replace(/^```[a-zA-Z]*\s*/, "").replace(/```\s*$/, "").trim();
|
|
54589
|
+
try {
|
|
54590
|
+
const obj = JSON.parse(text);
|
|
54591
|
+
if (typeof obj.title === "string") return sanitizeTitle(obj.title);
|
|
54592
|
+
} catch {
|
|
54593
|
+
}
|
|
54594
|
+
return sanitizeTitle(text);
|
|
54595
|
+
}
|
|
54596
|
+
function buildCodexTitleArgs(prompt, outFile, schemaFile) {
|
|
54597
|
+
return [
|
|
54598
|
+
"exec",
|
|
54599
|
+
"--ephemeral",
|
|
54600
|
+
"--skip-git-repo-check",
|
|
54601
|
+
"--output-schema",
|
|
54602
|
+
schemaFile,
|
|
54603
|
+
"-s",
|
|
54604
|
+
"read-only",
|
|
54605
|
+
"-m",
|
|
54606
|
+
TITLE_MODEL_BY_TOOL.codex,
|
|
54607
|
+
"--color",
|
|
54608
|
+
"never",
|
|
54609
|
+
"-o",
|
|
54610
|
+
outFile,
|
|
54611
|
+
prompt
|
|
54612
|
+
];
|
|
54613
|
+
}
|
|
54614
|
+
async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
54615
|
+
if (tool !== "claude" && tool !== "codex") return null;
|
|
54616
|
+
const text = firstMessage.trim();
|
|
54617
|
+
if (!text) return null;
|
|
54618
|
+
const workDir = import_node_path34.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_NAME);
|
|
54619
|
+
try {
|
|
54620
|
+
import_node_fs32.default.mkdirSync(workDir, { recursive: true });
|
|
54621
|
+
} catch {
|
|
54622
|
+
return null;
|
|
54623
|
+
}
|
|
54624
|
+
const outFile = import_node_path34.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
54625
|
+
const schemaFile = import_node_path34.default.join(workDir, "title-schema.json");
|
|
54626
|
+
if (tool === "codex") {
|
|
54627
|
+
try {
|
|
54628
|
+
import_node_fs32.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA, { flag: "wx" });
|
|
54629
|
+
} catch (err) {
|
|
54630
|
+
if (err.code !== "EEXIST") return null;
|
|
54631
|
+
}
|
|
54632
|
+
}
|
|
54633
|
+
const cmd = tool === "claude" ? process.env.CLAUDE_BIN ?? "claude" : process.env.CODEX_BIN ?? "codex";
|
|
54634
|
+
const args = tool === "claude" ? buildClaudeTitleArgs(buildClaudeTitlePrompt(text)) : buildCodexTitleArgs(buildTitlePrompt(text), outFile, schemaFile);
|
|
54635
|
+
const doSpawn = deps.spawnOverride ?? ((c, a, o) => (0, import_node_child_process8.spawn)(c, a, { ...o, stdio: ["ignore", "pipe", "pipe"] }));
|
|
54636
|
+
const timeoutMs = deps.timeoutMs ?? DEFAULT_TITLE_GEN_TIMEOUT_MS;
|
|
54637
|
+
return await new Promise((resolve6) => {
|
|
54638
|
+
let proc;
|
|
54639
|
+
try {
|
|
54640
|
+
proc = doSpawn(cmd, args, { cwd: workDir });
|
|
54641
|
+
} catch (err) {
|
|
54642
|
+
deps.logger?.warn("title-gen spawn failed", { tool, message: err.message });
|
|
54643
|
+
return resolve6(null);
|
|
54644
|
+
}
|
|
54645
|
+
let stdout = "";
|
|
54646
|
+
let settled = false;
|
|
54647
|
+
const finish = (title) => {
|
|
54648
|
+
if (settled) return;
|
|
54649
|
+
settled = true;
|
|
54650
|
+
clearTimeout(timer);
|
|
54651
|
+
if (proc.exitCode === null && proc.signalCode === null) proc.kill("SIGKILL");
|
|
54652
|
+
try {
|
|
54653
|
+
import_node_fs32.default.rmSync(outFile, { force: true });
|
|
54654
|
+
} catch {
|
|
54655
|
+
}
|
|
54656
|
+
resolve6(title);
|
|
54657
|
+
};
|
|
54658
|
+
const timer = setTimeout(() => {
|
|
54659
|
+
deps.logger?.warn("title-gen timed out", { tool, timeoutMs });
|
|
54660
|
+
finish(null);
|
|
54661
|
+
}, timeoutMs);
|
|
54662
|
+
proc.stdout?.on("data", (c) => {
|
|
54663
|
+
stdout += c.toString();
|
|
54664
|
+
});
|
|
54665
|
+
proc.stderr?.on("data", () => {
|
|
54666
|
+
});
|
|
54667
|
+
proc.on("error", (err) => {
|
|
54668
|
+
deps.logger?.warn("title-gen proc error", { tool, message: err.message });
|
|
54669
|
+
finish(null);
|
|
54670
|
+
});
|
|
54671
|
+
proc.on("close", (code) => {
|
|
54672
|
+
if (code !== 0) {
|
|
54673
|
+
deps.logger?.warn("title-gen exited non-zero", { tool, code });
|
|
54674
|
+
return finish(null);
|
|
54675
|
+
}
|
|
54676
|
+
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
54677
|
+
let fileText = "";
|
|
54678
|
+
try {
|
|
54679
|
+
fileText = import_node_fs32.default.readFileSync(outFile, "utf8");
|
|
54680
|
+
} catch {
|
|
54681
|
+
return finish(null);
|
|
54682
|
+
}
|
|
54683
|
+
finish(parseTitleJson(fileText));
|
|
54684
|
+
});
|
|
54685
|
+
});
|
|
54686
|
+
}
|
|
54687
|
+
|
|
54505
54688
|
// ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
54506
54689
|
var import_stream = __toESM(require_stream(), 1);
|
|
54507
54690
|
var import_extension2 = __toESM(require_extension(), 1);
|
|
@@ -55178,8 +55361,8 @@ async function authenticate(token, deps) {
|
|
|
55178
55361
|
}
|
|
55179
55362
|
|
|
55180
55363
|
// src/legacy-cleanup.ts
|
|
55181
|
-
var
|
|
55182
|
-
var
|
|
55364
|
+
var fs38 = __toESM(require("fs/promises"), 1);
|
|
55365
|
+
var path39 = __toESM(require("path"), 1);
|
|
55183
55366
|
var LEGACY_FILES = [
|
|
55184
55367
|
"personal-capability.json",
|
|
55185
55368
|
"received-capabilities.json",
|
|
@@ -55188,9 +55371,9 @@ var LEGACY_FILES = [
|
|
|
55188
55371
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
55189
55372
|
const removed = [];
|
|
55190
55373
|
for (const name of LEGACY_FILES) {
|
|
55191
|
-
const p2 =
|
|
55374
|
+
const p2 = path39.join(dataDir, name);
|
|
55192
55375
|
try {
|
|
55193
|
-
await
|
|
55376
|
+
await fs38.unlink(p2);
|
|
55194
55377
|
removed.push(name);
|
|
55195
55378
|
logger.debug("legacy capability file removed", { file: name });
|
|
55196
55379
|
} catch (err) {
|
|
@@ -55202,13 +55385,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
55202
55385
|
}
|
|
55203
55386
|
|
|
55204
55387
|
// src/inbox/inbox-store.ts
|
|
55205
|
-
var
|
|
55206
|
-
var
|
|
55388
|
+
var fs39 = __toESM(require("fs"), 1);
|
|
55389
|
+
var path40 = __toESM(require("path"), 1);
|
|
55207
55390
|
var INBOX_SUBDIR = "inbox";
|
|
55208
55391
|
var InboxStore = class {
|
|
55209
55392
|
constructor(dataDir) {
|
|
55210
55393
|
this.dataDir = dataDir;
|
|
55211
|
-
|
|
55394
|
+
fs39.mkdirSync(this.dirPath(), { recursive: true });
|
|
55212
55395
|
}
|
|
55213
55396
|
dataDir;
|
|
55214
55397
|
/**
|
|
@@ -55220,7 +55403,7 @@ var InboxStore = class {
|
|
|
55220
55403
|
const file = this.filePath(peerDeviceId);
|
|
55221
55404
|
let raw;
|
|
55222
55405
|
try {
|
|
55223
|
-
raw =
|
|
55406
|
+
raw = fs39.readFileSync(file, "utf8");
|
|
55224
55407
|
} catch (err) {
|
|
55225
55408
|
if (err?.code === "ENOENT") return [];
|
|
55226
55409
|
return [];
|
|
@@ -55236,7 +55419,7 @@ var InboxStore = class {
|
|
|
55236
55419
|
const dir = this.dirPath();
|
|
55237
55420
|
let entries;
|
|
55238
55421
|
try {
|
|
55239
|
-
entries =
|
|
55422
|
+
entries = fs39.readdirSync(dir);
|
|
55240
55423
|
} catch (err) {
|
|
55241
55424
|
if (err?.code === "ENOENT") return [];
|
|
55242
55425
|
return [];
|
|
@@ -55252,9 +55435,9 @@ var InboxStore = class {
|
|
|
55252
55435
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
55253
55436
|
const file = this.filePath(message.peerDeviceId);
|
|
55254
55437
|
const line = JSON.stringify(message) + "\n";
|
|
55255
|
-
|
|
55438
|
+
fs39.appendFileSync(file, line, { mode: 384 });
|
|
55256
55439
|
try {
|
|
55257
|
-
|
|
55440
|
+
fs39.chmodSync(file, 384);
|
|
55258
55441
|
} catch {
|
|
55259
55442
|
}
|
|
55260
55443
|
}
|
|
@@ -55284,7 +55467,7 @@ var InboxStore = class {
|
|
|
55284
55467
|
removeByPeerDeviceId(peerDeviceId) {
|
|
55285
55468
|
const file = this.filePath(peerDeviceId);
|
|
55286
55469
|
try {
|
|
55287
|
-
|
|
55470
|
+
fs39.unlinkSync(file);
|
|
55288
55471
|
} catch (err) {
|
|
55289
55472
|
if (err?.code === "ENOENT") return;
|
|
55290
55473
|
}
|
|
@@ -55293,18 +55476,18 @@ var InboxStore = class {
|
|
|
55293
55476
|
const file = this.filePath(peerDeviceId);
|
|
55294
55477
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
55295
55478
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
55296
|
-
|
|
55297
|
-
|
|
55479
|
+
fs39.writeFileSync(tmp, content, { mode: 384 });
|
|
55480
|
+
fs39.renameSync(tmp, file);
|
|
55298
55481
|
try {
|
|
55299
|
-
|
|
55482
|
+
fs39.chmodSync(file, 384);
|
|
55300
55483
|
} catch {
|
|
55301
55484
|
}
|
|
55302
55485
|
}
|
|
55303
55486
|
dirPath() {
|
|
55304
|
-
return
|
|
55487
|
+
return path40.join(this.dataDir, INBOX_SUBDIR);
|
|
55305
55488
|
}
|
|
55306
55489
|
filePath(peerDeviceId) {
|
|
55307
|
-
return
|
|
55490
|
+
return path40.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
55308
55491
|
}
|
|
55309
55492
|
};
|
|
55310
55493
|
function parseAllLines(raw) {
|
|
@@ -55392,8 +55575,8 @@ var InboxManager = class {
|
|
|
55392
55575
|
};
|
|
55393
55576
|
|
|
55394
55577
|
// src/state/contact-store.ts
|
|
55395
|
-
var
|
|
55396
|
-
var
|
|
55578
|
+
var fs40 = __toESM(require("fs"), 1);
|
|
55579
|
+
var path41 = __toESM(require("path"), 1);
|
|
55397
55580
|
var FILE_NAME = "contacts.json";
|
|
55398
55581
|
var ContactStore = class {
|
|
55399
55582
|
constructor(dataDir) {
|
|
@@ -55403,10 +55586,10 @@ var ContactStore = class {
|
|
|
55403
55586
|
contacts = /* @__PURE__ */ new Map();
|
|
55404
55587
|
load() {
|
|
55405
55588
|
this.contacts.clear();
|
|
55406
|
-
const file =
|
|
55589
|
+
const file = path41.join(this.dataDir, FILE_NAME);
|
|
55407
55590
|
let raw;
|
|
55408
55591
|
try {
|
|
55409
|
-
raw =
|
|
55592
|
+
raw = fs40.readFileSync(file, "utf8");
|
|
55410
55593
|
} catch (err) {
|
|
55411
55594
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
55412
55595
|
return;
|
|
@@ -55475,20 +55658,20 @@ var ContactStore = class {
|
|
|
55475
55658
|
return true;
|
|
55476
55659
|
}
|
|
55477
55660
|
flush() {
|
|
55478
|
-
const file =
|
|
55661
|
+
const file = path41.join(this.dataDir, FILE_NAME);
|
|
55479
55662
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
55480
55663
|
const content = JSON.stringify(
|
|
55481
55664
|
{ contacts: Array.from(this.contacts.values()) },
|
|
55482
55665
|
null,
|
|
55483
55666
|
2
|
|
55484
55667
|
);
|
|
55485
|
-
|
|
55486
|
-
|
|
55487
|
-
|
|
55668
|
+
fs40.mkdirSync(this.dataDir, { recursive: true });
|
|
55669
|
+
fs40.writeFileSync(tmp, content, { mode: 384 });
|
|
55670
|
+
fs40.renameSync(tmp, file);
|
|
55488
55671
|
}
|
|
55489
55672
|
renameBak(file) {
|
|
55490
55673
|
try {
|
|
55491
|
-
|
|
55674
|
+
fs40.renameSync(file, `${file}.bak`);
|
|
55492
55675
|
} catch {
|
|
55493
55676
|
}
|
|
55494
55677
|
}
|
|
@@ -55596,61 +55779,61 @@ async function connectRemote(args) {
|
|
|
55596
55779
|
}
|
|
55597
55780
|
|
|
55598
55781
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
55599
|
-
var
|
|
55600
|
-
var
|
|
55782
|
+
var fs41 = __toESM(require("fs"), 1);
|
|
55783
|
+
var path42 = __toESM(require("path"), 1);
|
|
55601
55784
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
55602
55785
|
function migrateFlattenSessions(opts) {
|
|
55603
55786
|
const dataDir = opts.dataDir;
|
|
55604
55787
|
const now = opts.now ?? Date.now;
|
|
55605
|
-
const sessionsDir =
|
|
55606
|
-
const flagPath =
|
|
55788
|
+
const sessionsDir = path42.join(dataDir, "sessions");
|
|
55789
|
+
const flagPath = path42.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
55607
55790
|
if (existsSync3(flagPath)) {
|
|
55608
55791
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
55609
55792
|
}
|
|
55610
55793
|
let movedBare = 0;
|
|
55611
55794
|
let movedVmOwner = 0;
|
|
55612
55795
|
let archivedListener = 0;
|
|
55613
|
-
const defaultDir =
|
|
55796
|
+
const defaultDir = path42.join(sessionsDir, "default");
|
|
55614
55797
|
if (existsSync3(defaultDir)) {
|
|
55615
55798
|
for (const entry of readdirSafe(defaultDir)) {
|
|
55616
55799
|
if (!entry.endsWith(".json")) continue;
|
|
55617
|
-
const src =
|
|
55618
|
-
const dst =
|
|
55619
|
-
|
|
55800
|
+
const src = path42.join(defaultDir, entry);
|
|
55801
|
+
const dst = path42.join(sessionsDir, entry);
|
|
55802
|
+
fs41.renameSync(src, dst);
|
|
55620
55803
|
movedBare += 1;
|
|
55621
55804
|
}
|
|
55622
55805
|
rmdirIfEmpty(defaultDir);
|
|
55623
55806
|
}
|
|
55624
55807
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
55625
|
-
const personaDir =
|
|
55808
|
+
const personaDir = path42.join(sessionsDir, pid);
|
|
55626
55809
|
if (!isDir(personaDir)) continue;
|
|
55627
55810
|
if (pid === "default") continue;
|
|
55628
|
-
const ownerSrc =
|
|
55811
|
+
const ownerSrc = path42.join(personaDir, "owner");
|
|
55629
55812
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
55630
|
-
const ownerDst =
|
|
55631
|
-
|
|
55813
|
+
const ownerDst = path42.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
55814
|
+
fs41.mkdirSync(ownerDst, { recursive: true });
|
|
55632
55815
|
for (const file of readdirSafe(ownerSrc)) {
|
|
55633
55816
|
if (!file.endsWith(".json")) continue;
|
|
55634
|
-
|
|
55817
|
+
fs41.renameSync(path42.join(ownerSrc, file), path42.join(ownerDst, file));
|
|
55635
55818
|
movedVmOwner += 1;
|
|
55636
55819
|
}
|
|
55637
55820
|
rmdirIfEmpty(ownerSrc);
|
|
55638
55821
|
}
|
|
55639
|
-
const listenerSrc =
|
|
55822
|
+
const listenerSrc = path42.join(personaDir, "listener");
|
|
55640
55823
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
55641
|
-
const archiveDst =
|
|
55642
|
-
|
|
55824
|
+
const archiveDst = path42.join(dataDir, ".legacy", `listener-${pid}`);
|
|
55825
|
+
fs41.mkdirSync(archiveDst, { recursive: true });
|
|
55643
55826
|
for (const file of readdirSafe(listenerSrc)) {
|
|
55644
55827
|
if (!file.endsWith(".json")) continue;
|
|
55645
|
-
|
|
55828
|
+
fs41.renameSync(path42.join(listenerSrc, file), path42.join(archiveDst, file));
|
|
55646
55829
|
archivedListener += 1;
|
|
55647
55830
|
}
|
|
55648
55831
|
rmdirIfEmpty(listenerSrc);
|
|
55649
55832
|
}
|
|
55650
55833
|
rmdirIfEmpty(personaDir);
|
|
55651
55834
|
}
|
|
55652
|
-
|
|
55653
|
-
|
|
55835
|
+
fs41.mkdirSync(sessionsDir, { recursive: true });
|
|
55836
|
+
fs41.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
55654
55837
|
return {
|
|
55655
55838
|
skipped: false,
|
|
55656
55839
|
flagWritten: true,
|
|
@@ -55661,7 +55844,7 @@ function migrateFlattenSessions(opts) {
|
|
|
55661
55844
|
}
|
|
55662
55845
|
function existsSync3(p2) {
|
|
55663
55846
|
try {
|
|
55664
|
-
|
|
55847
|
+
fs41.statSync(p2);
|
|
55665
55848
|
return true;
|
|
55666
55849
|
} catch {
|
|
55667
55850
|
return false;
|
|
@@ -55669,31 +55852,31 @@ function existsSync3(p2) {
|
|
|
55669
55852
|
}
|
|
55670
55853
|
function isDir(p2) {
|
|
55671
55854
|
try {
|
|
55672
|
-
return
|
|
55855
|
+
return fs41.statSync(p2).isDirectory();
|
|
55673
55856
|
} catch {
|
|
55674
55857
|
return false;
|
|
55675
55858
|
}
|
|
55676
55859
|
}
|
|
55677
55860
|
function readdirSafe(p2) {
|
|
55678
55861
|
try {
|
|
55679
|
-
return
|
|
55862
|
+
return fs41.readdirSync(p2);
|
|
55680
55863
|
} catch {
|
|
55681
55864
|
return [];
|
|
55682
55865
|
}
|
|
55683
55866
|
}
|
|
55684
55867
|
function rmdirIfEmpty(p2) {
|
|
55685
55868
|
try {
|
|
55686
|
-
|
|
55869
|
+
fs41.rmdirSync(p2);
|
|
55687
55870
|
} catch {
|
|
55688
55871
|
}
|
|
55689
55872
|
}
|
|
55690
55873
|
|
|
55691
55874
|
// src/transport/http-router.ts
|
|
55692
|
-
var
|
|
55693
|
-
var
|
|
55875
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
55876
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
55694
55877
|
|
|
55695
55878
|
// src/attachment/mime.ts
|
|
55696
|
-
var
|
|
55879
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55697
55880
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
55698
55881
|
var EXT_TO_NATIVE_MIME = {
|
|
55699
55882
|
// 图片
|
|
@@ -55800,7 +55983,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
55800
55983
|
".mk"
|
|
55801
55984
|
]);
|
|
55802
55985
|
function lookupMime(filePathOrName) {
|
|
55803
|
-
const ext =
|
|
55986
|
+
const ext = import_node_path35.default.extname(filePathOrName).toLowerCase();
|
|
55804
55987
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
55805
55988
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
55806
55989
|
return "application/octet-stream";
|
|
@@ -55870,8 +56053,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
55870
56053
|
}
|
|
55871
56054
|
|
|
55872
56055
|
// src/attachment/upload.ts
|
|
55873
|
-
var
|
|
55874
|
-
var
|
|
56056
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
56057
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
55875
56058
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
55876
56059
|
var import_promises4 = require("stream/promises");
|
|
55877
56060
|
var UploadError = class extends Error {
|
|
@@ -55883,22 +56066,22 @@ var UploadError = class extends Error {
|
|
|
55883
56066
|
code;
|
|
55884
56067
|
};
|
|
55885
56068
|
function assertValidFileName(fileName) {
|
|
55886
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
56069
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path36.default.basename(fileName)) {
|
|
55887
56070
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
55888
56071
|
}
|
|
55889
56072
|
}
|
|
55890
56073
|
var HASH_PREFIX_LEN = 16;
|
|
55891
56074
|
async function writeUploadedAttachment(args) {
|
|
55892
56075
|
assertValidFileName(args.fileName);
|
|
55893
|
-
const attachmentsRoot =
|
|
56076
|
+
const attachmentsRoot = import_node_path36.default.join(args.baseDir, ".attachments");
|
|
55894
56077
|
try {
|
|
55895
|
-
|
|
56078
|
+
import_node_fs33.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
55896
56079
|
} catch (err) {
|
|
55897
56080
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
55898
56081
|
}
|
|
55899
56082
|
const hasher = import_node_crypto9.default.createHash("sha256");
|
|
55900
56083
|
let actualSize = 0;
|
|
55901
|
-
const tmpPath =
|
|
56084
|
+
const tmpPath = import_node_path36.default.join(
|
|
55902
56085
|
attachmentsRoot,
|
|
55903
56086
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
|
|
55904
56087
|
);
|
|
@@ -55913,18 +56096,18 @@ async function writeUploadedAttachment(args) {
|
|
|
55913
56096
|
yield buf;
|
|
55914
56097
|
}
|
|
55915
56098
|
},
|
|
55916
|
-
|
|
56099
|
+
import_node_fs33.default.createWriteStream(tmpPath, { mode: 384 })
|
|
55917
56100
|
);
|
|
55918
56101
|
} catch (err) {
|
|
55919
56102
|
try {
|
|
55920
|
-
|
|
56103
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55921
56104
|
} catch {
|
|
55922
56105
|
}
|
|
55923
56106
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
55924
56107
|
}
|
|
55925
56108
|
if (actualSize !== args.contentLength) {
|
|
55926
56109
|
try {
|
|
55927
|
-
|
|
56110
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55928
56111
|
} catch {
|
|
55929
56112
|
}
|
|
55930
56113
|
throw new UploadError(
|
|
@@ -55933,34 +56116,34 @@ async function writeUploadedAttachment(args) {
|
|
|
55933
56116
|
);
|
|
55934
56117
|
}
|
|
55935
56118
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
55936
|
-
const hashDir =
|
|
56119
|
+
const hashDir = import_node_path36.default.join(attachmentsRoot, attachmentId);
|
|
55937
56120
|
let finalFileName;
|
|
55938
56121
|
let hashDirExists = false;
|
|
55939
56122
|
try {
|
|
55940
|
-
hashDirExists =
|
|
56123
|
+
hashDirExists = import_node_fs33.default.statSync(hashDir).isDirectory();
|
|
55941
56124
|
} catch {
|
|
55942
56125
|
}
|
|
55943
56126
|
if (hashDirExists) {
|
|
55944
|
-
const existing =
|
|
56127
|
+
const existing = import_node_fs33.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
55945
56128
|
finalFileName = existing[0] ?? args.fileName;
|
|
55946
56129
|
try {
|
|
55947
|
-
|
|
56130
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55948
56131
|
} catch {
|
|
55949
56132
|
}
|
|
55950
56133
|
} else {
|
|
55951
56134
|
try {
|
|
55952
|
-
|
|
56135
|
+
import_node_fs33.default.mkdirSync(hashDir, { recursive: true });
|
|
55953
56136
|
finalFileName = args.fileName;
|
|
55954
|
-
|
|
56137
|
+
import_node_fs33.default.renameSync(tmpPath, import_node_path36.default.join(hashDir, finalFileName));
|
|
55955
56138
|
} catch (err) {
|
|
55956
56139
|
try {
|
|
55957
|
-
|
|
56140
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55958
56141
|
} catch {
|
|
55959
56142
|
}
|
|
55960
56143
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
55961
56144
|
}
|
|
55962
56145
|
}
|
|
55963
|
-
const absPath =
|
|
56146
|
+
const absPath = import_node_path36.default.join(hashDir, finalFileName);
|
|
55964
56147
|
const relPath = absPath;
|
|
55965
56148
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
55966
56149
|
relPath: absPath,
|
|
@@ -55975,8 +56158,8 @@ async function writeUploadedAttachment(args) {
|
|
|
55975
56158
|
|
|
55976
56159
|
// src/extension/import.ts
|
|
55977
56160
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
55978
|
-
var
|
|
55979
|
-
var
|
|
56161
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56162
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
55980
56163
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
55981
56164
|
var ImportError = class extends Error {
|
|
55982
56165
|
constructor(code, message) {
|
|
@@ -55993,7 +56176,7 @@ async function importZip(buf, root) {
|
|
|
55993
56176
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
55994
56177
|
}
|
|
55995
56178
|
for (const name of Object.keys(zip.files)) {
|
|
55996
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
56179
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
|
|
55997
56180
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
55998
56181
|
}
|
|
55999
56182
|
}
|
|
@@ -56026,7 +56209,7 @@ async function importZip(buf, root) {
|
|
|
56026
56209
|
);
|
|
56027
56210
|
}
|
|
56028
56211
|
}
|
|
56029
|
-
const destDir =
|
|
56212
|
+
const destDir = import_node_path37.default.join(root, manifest.id);
|
|
56030
56213
|
let destExists = false;
|
|
56031
56214
|
try {
|
|
56032
56215
|
await import_promises5.default.access(destDir);
|
|
@@ -56036,15 +56219,15 @@ async function importZip(buf, root) {
|
|
|
56036
56219
|
if (destExists) {
|
|
56037
56220
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
56038
56221
|
}
|
|
56039
|
-
const stage = await import_promises5.default.mkdtemp(
|
|
56222
|
+
const stage = await import_promises5.default.mkdtemp(import_node_path37.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
56040
56223
|
try {
|
|
56041
56224
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56042
|
-
const dest =
|
|
56225
|
+
const dest = import_node_path37.default.join(stage, name);
|
|
56043
56226
|
if (entry.dir) {
|
|
56044
56227
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
56045
56228
|
continue;
|
|
56046
56229
|
}
|
|
56047
|
-
await import_promises5.default.mkdir(
|
|
56230
|
+
await import_promises5.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
|
|
56048
56231
|
const content = await entry.async("nodebuffer");
|
|
56049
56232
|
await import_promises5.default.writeFile(dest, content);
|
|
56050
56233
|
}
|
|
@@ -56074,7 +56257,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
56074
56257
|
".wasm": "application/wasm"
|
|
56075
56258
|
};
|
|
56076
56259
|
function shareUiAssetMime(filePath) {
|
|
56077
|
-
const ext =
|
|
56260
|
+
const ext = import_node_path38.default.extname(filePath).toLowerCase();
|
|
56078
56261
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
56079
56262
|
}
|
|
56080
56263
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -56173,7 +56356,7 @@ function isValidUploadFileName(fileName) {
|
|
|
56173
56356
|
if (fileName === "." || fileName === "..") return false;
|
|
56174
56357
|
if (fileName.startsWith(".")) return false;
|
|
56175
56358
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
56176
|
-
return fileName ===
|
|
56359
|
+
return fileName === import_node_path38.default.basename(fileName);
|
|
56177
56360
|
}
|
|
56178
56361
|
function createHttpRouter(deps) {
|
|
56179
56362
|
return async (req, res) => {
|
|
@@ -56261,7 +56444,7 @@ function createHttpRouter(deps) {
|
|
|
56261
56444
|
}
|
|
56262
56445
|
let buf;
|
|
56263
56446
|
try {
|
|
56264
|
-
buf = await
|
|
56447
|
+
buf = await import_node_fs34.default.promises.readFile(abs);
|
|
56265
56448
|
} catch {
|
|
56266
56449
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
56267
56450
|
return true;
|
|
@@ -56409,7 +56592,7 @@ function createHttpRouter(deps) {
|
|
|
56409
56592
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
56410
56593
|
return true;
|
|
56411
56594
|
}
|
|
56412
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
56595
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path38.default.basename(r.absPath)));
|
|
56413
56596
|
return true;
|
|
56414
56597
|
}
|
|
56415
56598
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -56530,7 +56713,7 @@ function createHttpRouter(deps) {
|
|
|
56530
56713
|
return true;
|
|
56531
56714
|
}
|
|
56532
56715
|
let absPath;
|
|
56533
|
-
if (
|
|
56716
|
+
if (import_node_path38.default.isAbsolute(pathParam)) {
|
|
56534
56717
|
absPath = pathParam;
|
|
56535
56718
|
} else if (deps.sessionStore) {
|
|
56536
56719
|
const file = deps.sessionStore.read(sid);
|
|
@@ -56538,7 +56721,7 @@ function createHttpRouter(deps) {
|
|
|
56538
56721
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
56539
56722
|
return true;
|
|
56540
56723
|
}
|
|
56541
|
-
absPath =
|
|
56724
|
+
absPath = import_node_path38.default.join(file.cwd, pathParam);
|
|
56542
56725
|
} else {
|
|
56543
56726
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
56544
56727
|
return true;
|
|
@@ -56625,7 +56808,7 @@ function withCtx(ctx, body) {
|
|
|
56625
56808
|
function streamFile(res, absPath, logger) {
|
|
56626
56809
|
let stat;
|
|
56627
56810
|
try {
|
|
56628
|
-
stat =
|
|
56811
|
+
stat = import_node_fs34.default.statSync(absPath);
|
|
56629
56812
|
} catch (err) {
|
|
56630
56813
|
const code = err?.code;
|
|
56631
56814
|
if (code === "ENOENT") {
|
|
@@ -56640,7 +56823,7 @@ function streamFile(res, absPath, logger) {
|
|
|
56640
56823
|
return;
|
|
56641
56824
|
}
|
|
56642
56825
|
const mime = lookupMime(absPath);
|
|
56643
|
-
const basename =
|
|
56826
|
+
const basename = import_node_path38.default.basename(absPath);
|
|
56644
56827
|
res.writeHead(200, {
|
|
56645
56828
|
"Content-Type": mime,
|
|
56646
56829
|
"Content-Length": String(stat.size),
|
|
@@ -56648,7 +56831,7 @@ function streamFile(res, absPath, logger) {
|
|
|
56648
56831
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
56649
56832
|
"X-Content-Type-Options": "nosniff"
|
|
56650
56833
|
});
|
|
56651
|
-
const stream =
|
|
56834
|
+
const stream = import_node_fs34.default.createReadStream(absPath);
|
|
56652
56835
|
stream.on("error", (err) => {
|
|
56653
56836
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
56654
56837
|
res.destroy();
|
|
@@ -56657,8 +56840,8 @@ function streamFile(res, absPath, logger) {
|
|
|
56657
56840
|
}
|
|
56658
56841
|
|
|
56659
56842
|
// src/attachment/gc.ts
|
|
56660
|
-
var
|
|
56661
|
-
var
|
|
56843
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
56844
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
56662
56845
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
56663
56846
|
function runAttachmentGc(args) {
|
|
56664
56847
|
const now = (args.now ?? Date.now)();
|
|
@@ -56667,12 +56850,12 @@ function runAttachmentGc(args) {
|
|
|
56667
56850
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
56668
56851
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
56669
56852
|
if (entry.stale) continue;
|
|
56670
|
-
if (
|
|
56853
|
+
if (import_node_path39.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
56671
56854
|
}
|
|
56672
56855
|
}
|
|
56673
56856
|
const visited = /* @__PURE__ */ new Set();
|
|
56674
56857
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
56675
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
56858
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path39.default.join(
|
|
56676
56859
|
args.dataDir,
|
|
56677
56860
|
"sessions",
|
|
56678
56861
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -56685,28 +56868,28 @@ function runAttachmentGc(args) {
|
|
|
56685
56868
|
return true;
|
|
56686
56869
|
});
|
|
56687
56870
|
for (const rootDir of roots) {
|
|
56688
|
-
const attRoot =
|
|
56871
|
+
const attRoot = import_node_path39.default.join(rootDir, ".attachments");
|
|
56689
56872
|
let hashDirs;
|
|
56690
56873
|
try {
|
|
56691
|
-
hashDirs =
|
|
56874
|
+
hashDirs = import_node_fs35.default.readdirSync(attRoot);
|
|
56692
56875
|
} catch (err) {
|
|
56693
56876
|
if (err.code === "ENOENT") continue;
|
|
56694
56877
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
56695
56878
|
continue;
|
|
56696
56879
|
}
|
|
56697
56880
|
for (const hashDir of hashDirs) {
|
|
56698
|
-
const hashDirAbs =
|
|
56881
|
+
const hashDirAbs = import_node_path39.default.join(attRoot, hashDir);
|
|
56699
56882
|
let files;
|
|
56700
56883
|
try {
|
|
56701
|
-
files =
|
|
56884
|
+
files = import_node_fs35.default.readdirSync(hashDirAbs);
|
|
56702
56885
|
} catch {
|
|
56703
56886
|
continue;
|
|
56704
56887
|
}
|
|
56705
56888
|
for (const name of files) {
|
|
56706
|
-
const file =
|
|
56889
|
+
const file = import_node_path39.default.join(hashDirAbs, name);
|
|
56707
56890
|
let stat;
|
|
56708
56891
|
try {
|
|
56709
|
-
stat =
|
|
56892
|
+
stat = import_node_fs35.default.statSync(file);
|
|
56710
56893
|
} catch {
|
|
56711
56894
|
continue;
|
|
56712
56895
|
}
|
|
@@ -56715,18 +56898,18 @@ function runAttachmentGc(args) {
|
|
|
56715
56898
|
if (age < ttlMs) continue;
|
|
56716
56899
|
if (liveAbs.has(file)) continue;
|
|
56717
56900
|
try {
|
|
56718
|
-
|
|
56901
|
+
import_node_fs35.default.unlinkSync(file);
|
|
56719
56902
|
} catch (err) {
|
|
56720
56903
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
56721
56904
|
}
|
|
56722
56905
|
}
|
|
56723
56906
|
try {
|
|
56724
|
-
if (
|
|
56907
|
+
if (import_node_fs35.default.readdirSync(hashDirAbs).length === 0) import_node_fs35.default.rmdirSync(hashDirAbs);
|
|
56725
56908
|
} catch {
|
|
56726
56909
|
}
|
|
56727
56910
|
}
|
|
56728
56911
|
try {
|
|
56729
|
-
if (
|
|
56912
|
+
if (import_node_fs35.default.readdirSync(attRoot).length === 0) import_node_fs35.default.rmdirSync(attRoot);
|
|
56730
56913
|
} catch {
|
|
56731
56914
|
}
|
|
56732
56915
|
}
|
|
@@ -56734,8 +56917,8 @@ function runAttachmentGc(args) {
|
|
|
56734
56917
|
}
|
|
56735
56918
|
|
|
56736
56919
|
// src/attachment/group.ts
|
|
56737
|
-
var
|
|
56738
|
-
var
|
|
56920
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
56921
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
56739
56922
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
56740
56923
|
init_protocol();
|
|
56741
56924
|
var GroupFileStore = class {
|
|
@@ -56747,11 +56930,11 @@ var GroupFileStore = class {
|
|
|
56747
56930
|
this.logger = opts.logger;
|
|
56748
56931
|
}
|
|
56749
56932
|
rootForScope(scope) {
|
|
56750
|
-
return
|
|
56933
|
+
return import_node_path40.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
56751
56934
|
}
|
|
56752
56935
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
56753
56936
|
filePath(scope, sessionId) {
|
|
56754
|
-
return
|
|
56937
|
+
return import_node_path40.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
56755
56938
|
}
|
|
56756
56939
|
cacheKey(scope, sessionId) {
|
|
56757
56940
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -56760,7 +56943,7 @@ var GroupFileStore = class {
|
|
|
56760
56943
|
readFile(scope, sessionId) {
|
|
56761
56944
|
const file = this.filePath(scope, sessionId);
|
|
56762
56945
|
try {
|
|
56763
|
-
const raw =
|
|
56946
|
+
const raw = import_node_fs36.default.readFileSync(file, "utf8");
|
|
56764
56947
|
const parsed = JSON.parse(raw);
|
|
56765
56948
|
if (!Array.isArray(parsed)) {
|
|
56766
56949
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -56786,10 +56969,10 @@ var GroupFileStore = class {
|
|
|
56786
56969
|
}
|
|
56787
56970
|
writeFile(scope, sessionId, entries) {
|
|
56788
56971
|
const file = this.filePath(scope, sessionId);
|
|
56789
|
-
|
|
56972
|
+
import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(file), { recursive: true });
|
|
56790
56973
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
56791
|
-
|
|
56792
|
-
|
|
56974
|
+
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
56975
|
+
import_node_fs36.default.renameSync(tmp, file);
|
|
56793
56976
|
}
|
|
56794
56977
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
56795
56978
|
list(scope, sessionId) {
|
|
@@ -56875,10 +57058,10 @@ var GroupFileStore = class {
|
|
|
56875
57058
|
};
|
|
56876
57059
|
|
|
56877
57060
|
// src/discovery/state-file.ts
|
|
56878
|
-
var
|
|
56879
|
-
var
|
|
57061
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
57062
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
56880
57063
|
function defaultStateFilePath(dataDir) {
|
|
56881
|
-
return
|
|
57064
|
+
return import_node_path41.default.join(dataDir, "state.json");
|
|
56882
57065
|
}
|
|
56883
57066
|
function isPidAlive(pid) {
|
|
56884
57067
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -56900,7 +57083,7 @@ var StateFileManager = class {
|
|
|
56900
57083
|
}
|
|
56901
57084
|
read() {
|
|
56902
57085
|
try {
|
|
56903
|
-
const raw =
|
|
57086
|
+
const raw = import_node_fs37.default.readFileSync(this.file, "utf8");
|
|
56904
57087
|
const parsed = JSON.parse(raw);
|
|
56905
57088
|
return parsed;
|
|
56906
57089
|
} catch {
|
|
@@ -56914,20 +57097,20 @@ var StateFileManager = class {
|
|
|
56914
57097
|
return { status: "stale", existing };
|
|
56915
57098
|
}
|
|
56916
57099
|
write(state) {
|
|
56917
|
-
|
|
57100
|
+
import_node_fs37.default.mkdirSync(import_node_path41.default.dirname(this.file), { recursive: true });
|
|
56918
57101
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
56919
|
-
|
|
56920
|
-
|
|
57102
|
+
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
57103
|
+
import_node_fs37.default.renameSync(tmp, this.file);
|
|
56921
57104
|
if (process.platform !== "win32") {
|
|
56922
57105
|
try {
|
|
56923
|
-
|
|
57106
|
+
import_node_fs37.default.chmodSync(this.file, 384);
|
|
56924
57107
|
} catch {
|
|
56925
57108
|
}
|
|
56926
57109
|
}
|
|
56927
57110
|
}
|
|
56928
57111
|
delete() {
|
|
56929
57112
|
try {
|
|
56930
|
-
|
|
57113
|
+
import_node_fs37.default.unlinkSync(this.file);
|
|
56931
57114
|
} catch {
|
|
56932
57115
|
}
|
|
56933
57116
|
}
|
|
@@ -56941,14 +57124,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
56941
57124
|
}
|
|
56942
57125
|
|
|
56943
57126
|
// src/tunnel/tunnel-manager.ts
|
|
56944
|
-
var
|
|
56945
|
-
var
|
|
57127
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
57128
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
56946
57129
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
56947
|
-
var
|
|
57130
|
+
var import_node_child_process11 = require("child_process");
|
|
56948
57131
|
|
|
56949
57132
|
// src/tunnel/tunnel-store.ts
|
|
56950
|
-
var
|
|
56951
|
-
var
|
|
57133
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
57134
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
56952
57135
|
var TunnelStore = class {
|
|
56953
57136
|
constructor(filePath) {
|
|
56954
57137
|
this.filePath = filePath;
|
|
@@ -56956,7 +57139,7 @@ var TunnelStore = class {
|
|
|
56956
57139
|
filePath;
|
|
56957
57140
|
async get() {
|
|
56958
57141
|
try {
|
|
56959
|
-
const raw = await
|
|
57142
|
+
const raw = await import_node_fs38.default.promises.readFile(this.filePath, "utf8");
|
|
56960
57143
|
const obj = JSON.parse(raw);
|
|
56961
57144
|
if (!isPersistedTunnel(obj)) return null;
|
|
56962
57145
|
return obj;
|
|
@@ -56967,22 +57150,22 @@ var TunnelStore = class {
|
|
|
56967
57150
|
}
|
|
56968
57151
|
}
|
|
56969
57152
|
async set(v2) {
|
|
56970
|
-
const dir =
|
|
56971
|
-
await
|
|
57153
|
+
const dir = import_node_path42.default.dirname(this.filePath);
|
|
57154
|
+
await import_node_fs38.default.promises.mkdir(dir, { recursive: true });
|
|
56972
57155
|
const data = JSON.stringify(v2, null, 2);
|
|
56973
57156
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
56974
|
-
await
|
|
57157
|
+
await import_node_fs38.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
56975
57158
|
if (process.platform !== "win32") {
|
|
56976
57159
|
try {
|
|
56977
|
-
await
|
|
57160
|
+
await import_node_fs38.default.promises.chmod(tmp, 384);
|
|
56978
57161
|
} catch {
|
|
56979
57162
|
}
|
|
56980
57163
|
}
|
|
56981
|
-
await
|
|
57164
|
+
await import_node_fs38.default.promises.rename(tmp, this.filePath);
|
|
56982
57165
|
}
|
|
56983
57166
|
async clear() {
|
|
56984
57167
|
try {
|
|
56985
|
-
await
|
|
57168
|
+
await import_node_fs38.default.promises.unlink(this.filePath);
|
|
56986
57169
|
} catch (err) {
|
|
56987
57170
|
const code = err?.code;
|
|
56988
57171
|
if (code !== "ENOENT") throw err;
|
|
@@ -57077,10 +57260,10 @@ function escape(v2) {
|
|
|
57077
57260
|
}
|
|
57078
57261
|
|
|
57079
57262
|
// src/tunnel/frpc-binary.ts
|
|
57080
|
-
var
|
|
57081
|
-
var
|
|
57082
|
-
var
|
|
57083
|
-
var
|
|
57263
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
57264
|
+
var import_node_os14 = __toESM(require("os"), 1);
|
|
57265
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
57266
|
+
var import_node_child_process9 = require("child_process");
|
|
57084
57267
|
var import_node_stream3 = require("stream");
|
|
57085
57268
|
var import_promises6 = require("stream/promises");
|
|
57086
57269
|
var FRPC_VERSION = "0.68.0";
|
|
@@ -57111,20 +57294,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
57111
57294
|
}
|
|
57112
57295
|
async function ensureFrpcBinary(opts) {
|
|
57113
57296
|
if (opts.override) {
|
|
57114
|
-
if (!
|
|
57297
|
+
if (!import_node_fs39.default.existsSync(opts.override)) {
|
|
57115
57298
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
57116
57299
|
}
|
|
57117
57300
|
return opts.override;
|
|
57118
57301
|
}
|
|
57119
57302
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
57120
57303
|
const platform = opts.platform ?? detectPlatform();
|
|
57121
|
-
const binDir =
|
|
57122
|
-
|
|
57304
|
+
const binDir = import_node_path43.default.join(opts.dataDir, "bin");
|
|
57305
|
+
import_node_fs39.default.mkdirSync(binDir, { recursive: true });
|
|
57123
57306
|
cleanupStaleArtifacts(binDir);
|
|
57124
|
-
const stableBin =
|
|
57125
|
-
if (
|
|
57307
|
+
const stableBin = import_node_path43.default.join(binDir, "frpc");
|
|
57308
|
+
if (import_node_fs39.default.existsSync(stableBin)) return stableBin;
|
|
57126
57309
|
const partialBin = `${stableBin}.partial`;
|
|
57127
|
-
const tarballPath =
|
|
57310
|
+
const tarballPath = import_node_path43.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
57128
57311
|
try {
|
|
57129
57312
|
const url = frpcDownloadUrl(version2, platform);
|
|
57130
57313
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -57133,8 +57316,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
57133
57316
|
} else {
|
|
57134
57317
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
57135
57318
|
}
|
|
57136
|
-
|
|
57137
|
-
|
|
57319
|
+
import_node_fs39.default.chmodSync(partialBin, 493);
|
|
57320
|
+
import_node_fs39.default.renameSync(partialBin, stableBin);
|
|
57138
57321
|
} finally {
|
|
57139
57322
|
safeUnlink(tarballPath);
|
|
57140
57323
|
safeUnlink(partialBin);
|
|
@@ -57144,15 +57327,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
57144
57327
|
function cleanupStaleArtifacts(binDir) {
|
|
57145
57328
|
let entries;
|
|
57146
57329
|
try {
|
|
57147
|
-
entries =
|
|
57330
|
+
entries = import_node_fs39.default.readdirSync(binDir);
|
|
57148
57331
|
} catch {
|
|
57149
57332
|
return;
|
|
57150
57333
|
}
|
|
57151
57334
|
for (const name of entries) {
|
|
57152
57335
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
57153
|
-
const full =
|
|
57336
|
+
const full = import_node_path43.default.join(binDir, name);
|
|
57154
57337
|
try {
|
|
57155
|
-
|
|
57338
|
+
import_node_fs39.default.rmSync(full, { recursive: true, force: true });
|
|
57156
57339
|
} catch {
|
|
57157
57340
|
}
|
|
57158
57341
|
}
|
|
@@ -57160,7 +57343,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
57160
57343
|
}
|
|
57161
57344
|
function safeUnlink(p2) {
|
|
57162
57345
|
try {
|
|
57163
|
-
|
|
57346
|
+
import_node_fs39.default.unlinkSync(p2);
|
|
57164
57347
|
} catch {
|
|
57165
57348
|
}
|
|
57166
57349
|
}
|
|
@@ -57171,46 +57354,46 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
57171
57354
|
if (!res.ok || !res.body) {
|
|
57172
57355
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
57173
57356
|
}
|
|
57174
|
-
const out =
|
|
57357
|
+
const out = import_node_fs39.default.createWriteStream(dest);
|
|
57175
57358
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
57176
57359
|
await (0, import_promises6.pipeline)(nodeStream, out);
|
|
57177
57360
|
}
|
|
57178
57361
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
57179
|
-
const work =
|
|
57180
|
-
|
|
57362
|
+
const work = import_node_path43.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
57363
|
+
import_node_fs39.default.mkdirSync(work, { recursive: true });
|
|
57181
57364
|
try {
|
|
57182
57365
|
await new Promise((resolve6, reject) => {
|
|
57183
|
-
const proc = (0,
|
|
57366
|
+
const proc = (0, import_node_child_process9.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
57184
57367
|
proc.on("error", reject);
|
|
57185
57368
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
57186
57369
|
});
|
|
57187
57370
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
57188
|
-
const src =
|
|
57189
|
-
if (!
|
|
57371
|
+
const src = import_node_path43.default.join(work, dirName, "frpc");
|
|
57372
|
+
if (!import_node_fs39.default.existsSync(src)) {
|
|
57190
57373
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
57191
57374
|
}
|
|
57192
|
-
|
|
57375
|
+
import_node_fs39.default.copyFileSync(src, destBin);
|
|
57193
57376
|
} finally {
|
|
57194
|
-
|
|
57377
|
+
import_node_fs39.default.rmSync(work, { recursive: true, force: true });
|
|
57195
57378
|
}
|
|
57196
57379
|
}
|
|
57197
57380
|
|
|
57198
57381
|
// src/tunnel/frpc-process.ts
|
|
57199
|
-
var
|
|
57200
|
-
var
|
|
57201
|
-
var
|
|
57382
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
57383
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
57384
|
+
var import_node_child_process10 = require("child_process");
|
|
57202
57385
|
function frpcPidFilePath(dataDir) {
|
|
57203
|
-
return
|
|
57386
|
+
return import_node_path44.default.join(dataDir, "frpc.pid");
|
|
57204
57387
|
}
|
|
57205
57388
|
function writeFrpcPid(dataDir, pid) {
|
|
57206
57389
|
try {
|
|
57207
|
-
|
|
57390
|
+
import_node_fs40.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
57208
57391
|
} catch {
|
|
57209
57392
|
}
|
|
57210
57393
|
}
|
|
57211
57394
|
function clearFrpcPid(dataDir) {
|
|
57212
57395
|
try {
|
|
57213
|
-
|
|
57396
|
+
import_node_fs40.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
57214
57397
|
} catch {
|
|
57215
57398
|
}
|
|
57216
57399
|
}
|
|
@@ -57226,7 +57409,7 @@ function defaultIsPidAlive(pid) {
|
|
|
57226
57409
|
}
|
|
57227
57410
|
function defaultReadPidFile(file) {
|
|
57228
57411
|
try {
|
|
57229
|
-
return
|
|
57412
|
+
return import_node_fs40.default.readFileSync(file, "utf8");
|
|
57230
57413
|
} catch {
|
|
57231
57414
|
return null;
|
|
57232
57415
|
}
|
|
@@ -57242,7 +57425,7 @@ function defaultSleep2(ms) {
|
|
|
57242
57425
|
}
|
|
57243
57426
|
async function killStaleFrpc(deps) {
|
|
57244
57427
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
57245
|
-
const tomlPath =
|
|
57428
|
+
const tomlPath = import_node_path44.default.join(deps.dataDir, "frpc.toml");
|
|
57246
57429
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
57247
57430
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
57248
57431
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -57266,7 +57449,7 @@ async function killStaleFrpc(deps) {
|
|
|
57266
57449
|
}
|
|
57267
57450
|
if (victims.size === 0) {
|
|
57268
57451
|
try {
|
|
57269
|
-
|
|
57452
|
+
import_node_fs40.default.unlinkSync(pidFile);
|
|
57270
57453
|
} catch {
|
|
57271
57454
|
}
|
|
57272
57455
|
return;
|
|
@@ -57277,14 +57460,14 @@ async function killStaleFrpc(deps) {
|
|
|
57277
57460
|
}
|
|
57278
57461
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
57279
57462
|
try {
|
|
57280
|
-
|
|
57463
|
+
import_node_fs40.default.unlinkSync(pidFile);
|
|
57281
57464
|
} catch {
|
|
57282
57465
|
}
|
|
57283
57466
|
}
|
|
57284
57467
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
57285
57468
|
if (process.platform === "win32") return [];
|
|
57286
57469
|
return new Promise((resolve6) => {
|
|
57287
|
-
const ps = (0,
|
|
57470
|
+
const ps = (0, import_node_child_process10.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
57288
57471
|
let buf = "";
|
|
57289
57472
|
ps.stdout.on("data", (c) => {
|
|
57290
57473
|
buf += c.toString();
|
|
@@ -57314,7 +57497,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
57314
57497
|
var TunnelManager = class {
|
|
57315
57498
|
constructor(deps) {
|
|
57316
57499
|
this.deps = deps;
|
|
57317
|
-
this.store = deps.store ?? new TunnelStore(
|
|
57500
|
+
this.store = deps.store ?? new TunnelStore(import_node_path45.default.join(deps.dataDir, "tunnel.json"));
|
|
57318
57501
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
57319
57502
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
57320
57503
|
}
|
|
@@ -57441,7 +57624,7 @@ var TunnelManager = class {
|
|
|
57441
57624
|
dataDir: this.deps.dataDir,
|
|
57442
57625
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
57443
57626
|
});
|
|
57444
|
-
const tomlPath =
|
|
57627
|
+
const tomlPath = import_node_path45.default.join(this.deps.dataDir, "frpc.toml");
|
|
57445
57628
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
|
|
57446
57629
|
const toml = buildFrpcToml({
|
|
57447
57630
|
serverAddr: t.frpsHost,
|
|
@@ -57452,14 +57635,14 @@ var TunnelManager = class {
|
|
|
57452
57635
|
localPort,
|
|
57453
57636
|
logLevel: "info"
|
|
57454
57637
|
});
|
|
57455
|
-
await
|
|
57456
|
-
const proc = (this.deps.spawnImpl ??
|
|
57638
|
+
await import_node_fs41.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
57639
|
+
const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(frpcBin, ["-c", tomlPath], {
|
|
57457
57640
|
stdio: ["ignore", "pipe", "pipe"]
|
|
57458
57641
|
});
|
|
57459
|
-
const logDir =
|
|
57460
|
-
|
|
57461
|
-
const logFilePath =
|
|
57462
|
-
const logStream =
|
|
57642
|
+
const logDir = import_node_path45.default.join(this.deps.dataDir, "log");
|
|
57643
|
+
import_node_fs41.default.mkdirSync(logDir, { recursive: true });
|
|
57644
|
+
const logFilePath = import_node_path45.default.join(logDir, "frpc.log");
|
|
57645
|
+
const logStream = import_node_fs41.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
57463
57646
|
logStream.on("error", () => {
|
|
57464
57647
|
});
|
|
57465
57648
|
const tee = (chunk) => {
|
|
@@ -57541,28 +57724,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
57541
57724
|
}
|
|
57542
57725
|
|
|
57543
57726
|
// src/tunnel/device-key.ts
|
|
57544
|
-
var
|
|
57545
|
-
var
|
|
57727
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
57728
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
57546
57729
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
57547
57730
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
57548
57731
|
function deriveStableDeviceKey(opts = {}) {
|
|
57549
|
-
const hostname = opts.hostname ??
|
|
57550
|
-
const uid = opts.uid ?? (typeof
|
|
57551
|
-
const home = opts.home ??
|
|
57552
|
-
const defaultDataDir =
|
|
57553
|
-
const normalizedDataDir = opts.dataDir ?
|
|
57732
|
+
const hostname = opts.hostname ?? import_node_os15.default.hostname();
|
|
57733
|
+
const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
|
|
57734
|
+
const home = opts.home ?? import_node_os15.default.homedir();
|
|
57735
|
+
const defaultDataDir = import_node_path46.default.resolve(import_node_path46.default.join(home, ".clawd"));
|
|
57736
|
+
const normalizedDataDir = opts.dataDir ? import_node_path46.default.resolve(opts.dataDir) : null;
|
|
57554
57737
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
57555
57738
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
57556
57739
|
return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
57557
57740
|
}
|
|
57558
57741
|
|
|
57559
57742
|
// src/auth-store.ts
|
|
57560
|
-
var
|
|
57561
|
-
var
|
|
57743
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
57744
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
57562
57745
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
57563
57746
|
var AUTH_FILE_NAME = "auth.json";
|
|
57564
57747
|
function authFilePath(dataDir) {
|
|
57565
|
-
return
|
|
57748
|
+
return import_node_path47.default.join(dataDir, AUTH_FILE_NAME);
|
|
57566
57749
|
}
|
|
57567
57750
|
function loadOrCreateAuthFile(opts) {
|
|
57568
57751
|
const file = authFilePath(opts.dataDir);
|
|
@@ -57594,7 +57777,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
57594
57777
|
}
|
|
57595
57778
|
function readAuthFile(file) {
|
|
57596
57779
|
try {
|
|
57597
|
-
const raw =
|
|
57780
|
+
const raw = import_node_fs42.default.readFileSync(file, "utf8");
|
|
57598
57781
|
const parsed = JSON.parse(raw);
|
|
57599
57782
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
57600
57783
|
return null;
|
|
@@ -57614,26 +57797,26 @@ function readAuthFile(file) {
|
|
|
57614
57797
|
}
|
|
57615
57798
|
}
|
|
57616
57799
|
function writeAuthFile(file, content) {
|
|
57617
|
-
|
|
57618
|
-
|
|
57800
|
+
import_node_fs42.default.mkdirSync(import_node_path47.default.dirname(file), { recursive: true });
|
|
57801
|
+
import_node_fs42.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
57619
57802
|
try {
|
|
57620
|
-
|
|
57803
|
+
import_node_fs42.default.chmodSync(file, 384);
|
|
57621
57804
|
} catch {
|
|
57622
57805
|
}
|
|
57623
57806
|
}
|
|
57624
57807
|
|
|
57625
57808
|
// src/owner-profile.ts
|
|
57626
|
-
var
|
|
57627
|
-
var
|
|
57628
|
-
var
|
|
57809
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
57810
|
+
var import_node_os16 = __toESM(require("os"), 1);
|
|
57811
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
57629
57812
|
var PROFILE_FILENAME = "profile.json";
|
|
57630
57813
|
function profilePath(dataDir) {
|
|
57631
|
-
return
|
|
57814
|
+
return import_node_path48.default.join(dataDir, PROFILE_FILENAME);
|
|
57632
57815
|
}
|
|
57633
57816
|
function loadOwnerProfile(dataDir) {
|
|
57634
57817
|
let raw;
|
|
57635
57818
|
try {
|
|
57636
|
-
raw =
|
|
57819
|
+
raw = import_node_fs43.default.readFileSync(profilePath(dataDir), "utf8");
|
|
57637
57820
|
} catch {
|
|
57638
57821
|
return {};
|
|
57639
57822
|
}
|
|
@@ -57649,11 +57832,11 @@ function loadOwnerProfile(dataDir) {
|
|
|
57649
57832
|
}
|
|
57650
57833
|
function patchOwnerProfile(dataDir, patch) {
|
|
57651
57834
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
57652
|
-
|
|
57835
|
+
import_node_fs43.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
57653
57836
|
return merged;
|
|
57654
57837
|
}
|
|
57655
57838
|
function loadOwnerDisplayName(dataDir) {
|
|
57656
|
-
const fallback =
|
|
57839
|
+
const fallback = import_node_os16.default.userInfo().username;
|
|
57657
57840
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
57658
57841
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
57659
57842
|
if (displayName !== void 0) {
|
|
@@ -57665,18 +57848,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
57665
57848
|
}
|
|
57666
57849
|
|
|
57667
57850
|
// src/feishu-auth/owner-identity-store.ts
|
|
57668
|
-
var
|
|
57669
|
-
var
|
|
57851
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
57852
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
57670
57853
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
57671
57854
|
var OwnerIdentityStore = class {
|
|
57672
57855
|
file;
|
|
57673
57856
|
constructor(dataDir) {
|
|
57674
|
-
this.file =
|
|
57857
|
+
this.file = import_node_path49.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
57675
57858
|
}
|
|
57676
57859
|
read() {
|
|
57677
57860
|
let raw;
|
|
57678
57861
|
try {
|
|
57679
|
-
raw =
|
|
57862
|
+
raw = import_node_fs44.default.readFileSync(this.file, "utf8");
|
|
57680
57863
|
} catch {
|
|
57681
57864
|
return null;
|
|
57682
57865
|
}
|
|
@@ -57704,16 +57887,16 @@ var OwnerIdentityStore = class {
|
|
|
57704
57887
|
};
|
|
57705
57888
|
}
|
|
57706
57889
|
write(record) {
|
|
57707
|
-
|
|
57708
|
-
|
|
57890
|
+
import_node_fs44.default.mkdirSync(import_node_path49.default.dirname(this.file), { recursive: true });
|
|
57891
|
+
import_node_fs44.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
57709
57892
|
try {
|
|
57710
|
-
|
|
57893
|
+
import_node_fs44.default.chmodSync(this.file, 384);
|
|
57711
57894
|
} catch {
|
|
57712
57895
|
}
|
|
57713
57896
|
}
|
|
57714
57897
|
clear() {
|
|
57715
57898
|
try {
|
|
57716
|
-
|
|
57899
|
+
import_node_fs44.default.unlinkSync(this.file);
|
|
57717
57900
|
} catch (err) {
|
|
57718
57901
|
const code = err?.code;
|
|
57719
57902
|
if (code !== "ENOENT") throw err;
|
|
@@ -57850,9 +58033,9 @@ var CentralClientError = class extends Error {
|
|
|
57850
58033
|
code;
|
|
57851
58034
|
cause;
|
|
57852
58035
|
};
|
|
57853
|
-
async function centralRequest(opts,
|
|
58036
|
+
async function centralRequest(opts, path82, init) {
|
|
57854
58037
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
57855
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
58038
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path82}`;
|
|
57856
58039
|
const ctrl = new AbortController();
|
|
57857
58040
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
57858
58041
|
let res;
|
|
@@ -58046,8 +58229,8 @@ function verifyConnectToken(args) {
|
|
|
58046
58229
|
}
|
|
58047
58230
|
|
|
58048
58231
|
// src/feishu-auth/server-key.ts
|
|
58049
|
-
var
|
|
58050
|
-
var
|
|
58232
|
+
var fs55 = __toESM(require("fs"), 1);
|
|
58233
|
+
var path58 = __toESM(require("path"), 1);
|
|
58051
58234
|
var FILE_NAME2 = "server-signing-key.json";
|
|
58052
58235
|
var ServerKeyStore = class {
|
|
58053
58236
|
constructor(dataDir) {
|
|
@@ -58055,12 +58238,12 @@ var ServerKeyStore = class {
|
|
|
58055
58238
|
}
|
|
58056
58239
|
dataDir;
|
|
58057
58240
|
filePath() {
|
|
58058
|
-
return
|
|
58241
|
+
return path58.join(this.dataDir, FILE_NAME2);
|
|
58059
58242
|
}
|
|
58060
58243
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
58061
58244
|
read() {
|
|
58062
58245
|
try {
|
|
58063
|
-
const raw =
|
|
58246
|
+
const raw = fs55.readFileSync(this.filePath(), "utf8");
|
|
58064
58247
|
const parsed = JSON.parse(raw);
|
|
58065
58248
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
58066
58249
|
return parsed.publicKeyPem;
|
|
@@ -58075,12 +58258,12 @@ var ServerKeyStore = class {
|
|
|
58075
58258
|
publicKeyPem,
|
|
58076
58259
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
58077
58260
|
};
|
|
58078
|
-
|
|
58079
|
-
|
|
58261
|
+
fs55.mkdirSync(this.dataDir, { recursive: true });
|
|
58262
|
+
fs55.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
58080
58263
|
}
|
|
58081
58264
|
clear() {
|
|
58082
58265
|
try {
|
|
58083
|
-
|
|
58266
|
+
fs55.unlinkSync(this.filePath());
|
|
58084
58267
|
} catch {
|
|
58085
58268
|
}
|
|
58086
58269
|
}
|
|
@@ -58093,12 +58276,12 @@ init_protocol();
|
|
|
58093
58276
|
init_protocol();
|
|
58094
58277
|
|
|
58095
58278
|
// src/session/fork.ts
|
|
58096
|
-
var
|
|
58097
|
-
var
|
|
58098
|
-
var
|
|
58279
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
58280
|
+
var import_node_os17 = __toESM(require("os"), 1);
|
|
58281
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
58099
58282
|
init_claude_history();
|
|
58100
58283
|
function readJsonlEntries(file) {
|
|
58101
|
-
const raw =
|
|
58284
|
+
const raw = import_node_fs45.default.readFileSync(file, "utf8");
|
|
58102
58285
|
const out = [];
|
|
58103
58286
|
for (const line of raw.split("\n")) {
|
|
58104
58287
|
const t = line.trim();
|
|
@@ -58111,19 +58294,19 @@ function readJsonlEntries(file) {
|
|
|
58111
58294
|
return out;
|
|
58112
58295
|
}
|
|
58113
58296
|
function forkSession(input) {
|
|
58114
|
-
const baseDir = input.baseDir ??
|
|
58115
|
-
let projectDir =
|
|
58116
|
-
let sourceFile =
|
|
58117
|
-
if (!
|
|
58297
|
+
const baseDir = input.baseDir ?? import_node_path50.default.join(import_node_os17.default.homedir(), ".claude");
|
|
58298
|
+
let projectDir = import_node_path50.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
58299
|
+
let sourceFile = import_node_path50.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
58300
|
+
if (!import_node_fs45.default.existsSync(sourceFile)) {
|
|
58118
58301
|
const found = findTranscriptByToolSessionId(
|
|
58119
|
-
|
|
58302
|
+
import_node_path50.default.join(baseDir, "projects"),
|
|
58120
58303
|
input.toolSessionId
|
|
58121
58304
|
);
|
|
58122
58305
|
if (!found) {
|
|
58123
58306
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
58124
58307
|
}
|
|
58125
58308
|
sourceFile = found;
|
|
58126
|
-
projectDir =
|
|
58309
|
+
projectDir = import_node_path50.default.dirname(found);
|
|
58127
58310
|
}
|
|
58128
58311
|
const entries = readJsonlEntries(sourceFile);
|
|
58129
58312
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -58152,27 +58335,27 @@ function forkSession(input) {
|
|
|
58152
58335
|
}
|
|
58153
58336
|
forkedLines.push(JSON.stringify(forked));
|
|
58154
58337
|
}
|
|
58155
|
-
const outDir = input.targetCwd ?
|
|
58156
|
-
const forkedFilePath =
|
|
58157
|
-
|
|
58158
|
-
|
|
58338
|
+
const outDir = input.targetCwd ? import_node_path50.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
58339
|
+
const forkedFilePath = import_node_path50.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
58340
|
+
import_node_fs45.default.mkdirSync(outDir, { recursive: true });
|
|
58341
|
+
import_node_fs45.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
58159
58342
|
return { forkedToolSessionId, forkedFilePath };
|
|
58160
58343
|
}
|
|
58161
58344
|
|
|
58162
58345
|
// src/session/external-scan.ts
|
|
58163
|
-
var
|
|
58346
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
58164
58347
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
58165
|
-
var
|
|
58166
|
-
var
|
|
58348
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
58349
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58167
58350
|
var import_node_module = require("module");
|
|
58168
|
-
var
|
|
58351
|
+
var import_node_child_process12 = require("child_process");
|
|
58169
58352
|
var import_meta4 = {};
|
|
58170
58353
|
function defaultRoots() {
|
|
58171
|
-
const home =
|
|
58354
|
+
const home = import_node_os18.default.homedir();
|
|
58172
58355
|
return {
|
|
58173
|
-
claudeProjectsDir:
|
|
58174
|
-
codexDir:
|
|
58175
|
-
clawdDir:
|
|
58356
|
+
claudeProjectsDir: import_node_path51.default.join(home, ".claude", "projects"),
|
|
58357
|
+
codexDir: import_node_path51.default.join(home, ".codex"),
|
|
58358
|
+
clawdDir: import_node_path51.default.join(home, ".clawd")
|
|
58176
58359
|
};
|
|
58177
58360
|
}
|
|
58178
58361
|
function width(s) {
|
|
@@ -58200,12 +58383,12 @@ function toMs(v2) {
|
|
|
58200
58383
|
function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
|
|
58201
58384
|
let entries;
|
|
58202
58385
|
try {
|
|
58203
|
-
entries =
|
|
58386
|
+
entries = import_node_fs46.default.readdirSync(dir, { withFileTypes: true });
|
|
58204
58387
|
} catch {
|
|
58205
58388
|
return out;
|
|
58206
58389
|
}
|
|
58207
58390
|
for (const e of entries) {
|
|
58208
|
-
const full =
|
|
58391
|
+
const full = import_node_path51.default.join(dir, e.name);
|
|
58209
58392
|
if (e.isDirectory()) {
|
|
58210
58393
|
if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
|
|
58211
58394
|
} else if (e.isFile()) {
|
|
@@ -58240,7 +58423,7 @@ function userText(msg) {
|
|
|
58240
58423
|
}
|
|
58241
58424
|
function isDir2(p2) {
|
|
58242
58425
|
try {
|
|
58243
|
-
return
|
|
58426
|
+
return import_node_fs46.default.statSync(p2).isDirectory();
|
|
58244
58427
|
} catch {
|
|
58245
58428
|
return false;
|
|
58246
58429
|
}
|
|
@@ -58249,7 +58432,7 @@ async function scanClaude(roots) {
|
|
|
58249
58432
|
const out = [];
|
|
58250
58433
|
let dirs;
|
|
58251
58434
|
try {
|
|
58252
|
-
dirs =
|
|
58435
|
+
dirs = import_node_fs46.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
58253
58436
|
} catch {
|
|
58254
58437
|
return out;
|
|
58255
58438
|
}
|
|
@@ -58257,16 +58440,16 @@ async function scanClaude(roots) {
|
|
|
58257
58440
|
if (!d.isDirectory()) continue;
|
|
58258
58441
|
let files;
|
|
58259
58442
|
try {
|
|
58260
|
-
files =
|
|
58443
|
+
files = import_node_fs46.default.readdirSync(import_node_path51.default.join(roots.claudeProjectsDir, d.name));
|
|
58261
58444
|
} catch {
|
|
58262
58445
|
continue;
|
|
58263
58446
|
}
|
|
58264
58447
|
for (const name of files) {
|
|
58265
58448
|
if (!name.endsWith(".jsonl")) continue;
|
|
58266
|
-
const file =
|
|
58449
|
+
const file = import_node_path51.default.join(roots.claudeProjectsDir, d.name, name);
|
|
58267
58450
|
let st;
|
|
58268
58451
|
try {
|
|
58269
|
-
st =
|
|
58452
|
+
st = import_node_fs46.default.statSync(file);
|
|
58270
58453
|
} catch {
|
|
58271
58454
|
continue;
|
|
58272
58455
|
}
|
|
@@ -58310,13 +58493,14 @@ async function scanClaude(roots) {
|
|
|
58310
58493
|
};
|
|
58311
58494
|
if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
|
|
58312
58495
|
else if (!cwd) cand.skip = "\u65E0 cwd";
|
|
58496
|
+
else if (cwd.includes("clawd-title-gen")) cand.skip = "\u6807\u9898\u751F\u6210\u4E34\u65F6\u4F1A\u8BDD";
|
|
58313
58497
|
out.push(cand);
|
|
58314
58498
|
}
|
|
58315
58499
|
}
|
|
58316
58500
|
return out;
|
|
58317
58501
|
}
|
|
58318
58502
|
async function countCodexTurns(rolloutPath) {
|
|
58319
|
-
if (!rolloutPath || !
|
|
58503
|
+
if (!rolloutPath || !import_node_fs46.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
58320
58504
|
let turns = 0;
|
|
58321
58505
|
let first = "";
|
|
58322
58506
|
for await (const rec4 of jsonLines(rolloutPath)) {
|
|
@@ -58347,14 +58531,14 @@ function readCodexThreads(db) {
|
|
|
58347
58531
|
} catch {
|
|
58348
58532
|
}
|
|
58349
58533
|
try {
|
|
58350
|
-
const info = (0,
|
|
58534
|
+
const info = (0, import_node_child_process12.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
58351
58535
|
if (info.status !== 0) return null;
|
|
58352
58536
|
const have = new Set(
|
|
58353
58537
|
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
58354
58538
|
);
|
|
58355
58539
|
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
58356
58540
|
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
58357
|
-
const res = (0,
|
|
58541
|
+
const res = (0, import_node_child_process12.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
58358
58542
|
encoding: "utf8",
|
|
58359
58543
|
maxBuffer: 64 * 1024 * 1024
|
|
58360
58544
|
});
|
|
@@ -58388,11 +58572,11 @@ async function codexFromRows(rows) {
|
|
|
58388
58572
|
}
|
|
58389
58573
|
async function scanCodexRollouts(roots) {
|
|
58390
58574
|
const out = [];
|
|
58391
|
-
for (const file of listFiles(
|
|
58575
|
+
for (const file of listFiles(import_node_path51.default.join(roots.codexDir, "sessions"))) {
|
|
58392
58576
|
if (!file.endsWith(".jsonl")) continue;
|
|
58393
58577
|
let st;
|
|
58394
58578
|
try {
|
|
58395
|
-
st =
|
|
58579
|
+
st = import_node_fs46.default.statSync(file);
|
|
58396
58580
|
} catch {
|
|
58397
58581
|
continue;
|
|
58398
58582
|
}
|
|
@@ -58424,7 +58608,7 @@ async function scanCodexRollouts(roots) {
|
|
|
58424
58608
|
async function scanCodex(roots) {
|
|
58425
58609
|
let dbs = [];
|
|
58426
58610
|
try {
|
|
58427
|
-
dbs =
|
|
58611
|
+
dbs = import_node_fs46.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path51.default.join(roots.codexDir, n));
|
|
58428
58612
|
} catch {
|
|
58429
58613
|
}
|
|
58430
58614
|
if (dbs.length) {
|
|
@@ -58435,14 +58619,14 @@ async function scanCodex(roots) {
|
|
|
58435
58619
|
}
|
|
58436
58620
|
async function scanExternalSessions(rootsIn) {
|
|
58437
58621
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
58438
|
-
const personaRoot =
|
|
58622
|
+
const personaRoot = import_node_path51.default.join(roots.clawdDir, "personas");
|
|
58439
58623
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
58440
58624
|
const out = [];
|
|
58441
58625
|
for (const c of all) {
|
|
58442
58626
|
if (c.skip) continue;
|
|
58443
58627
|
if (c.turns < 1) continue;
|
|
58444
58628
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
58445
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
58629
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path51.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path51.default.sep)) {
|
|
58446
58630
|
continue;
|
|
58447
58631
|
}
|
|
58448
58632
|
out.push({
|
|
@@ -58459,19 +58643,19 @@ async function scanExternalSessions(rootsIn) {
|
|
|
58459
58643
|
}
|
|
58460
58644
|
|
|
58461
58645
|
// src/session/import-ledger.ts
|
|
58462
|
-
var
|
|
58463
|
-
var
|
|
58646
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
58647
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
58464
58648
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
58465
58649
|
function appendImportLedger(dataDir, entry) {
|
|
58466
|
-
const file =
|
|
58650
|
+
const file = import_node_path52.default.join(dataDir, LEDGER_FILENAME);
|
|
58467
58651
|
let entries = [];
|
|
58468
58652
|
try {
|
|
58469
|
-
const parsed = JSON.parse(
|
|
58653
|
+
const parsed = JSON.parse(import_node_fs47.default.readFileSync(file, "utf8"));
|
|
58470
58654
|
if (Array.isArray(parsed)) entries = parsed;
|
|
58471
58655
|
} catch {
|
|
58472
58656
|
}
|
|
58473
58657
|
entries.push(entry);
|
|
58474
|
-
|
|
58658
|
+
import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
58475
58659
|
}
|
|
58476
58660
|
|
|
58477
58661
|
// src/handlers/session.ts
|
|
@@ -58964,7 +59148,7 @@ function buildPermissionHandlers(deps) {
|
|
|
58964
59148
|
}
|
|
58965
59149
|
|
|
58966
59150
|
// src/handlers/history.ts
|
|
58967
|
-
var
|
|
59151
|
+
var path63 = __toESM(require("path"), 1);
|
|
58968
59152
|
init_protocol();
|
|
58969
59153
|
|
|
58970
59154
|
// src/session/recent-dirs.ts
|
|
@@ -58982,7 +59166,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
58982
59166
|
}
|
|
58983
59167
|
|
|
58984
59168
|
// src/permission/persona-paths.ts
|
|
58985
|
-
var
|
|
59169
|
+
var path62 = __toESM(require("path"), 1);
|
|
58986
59170
|
function getAllowedPersonaIds(grants, action) {
|
|
58987
59171
|
const ids = /* @__PURE__ */ new Set();
|
|
58988
59172
|
for (const g2 of grants) {
|
|
@@ -58995,42 +59179,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
58995
59179
|
return ids;
|
|
58996
59180
|
}
|
|
58997
59181
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
58998
|
-
const target =
|
|
59182
|
+
const target = path62.resolve(absPath);
|
|
58999
59183
|
if (userWorkDir) {
|
|
59000
|
-
const u =
|
|
59001
|
-
const usep = u.endsWith(
|
|
59184
|
+
const u = path62.resolve(userWorkDir);
|
|
59185
|
+
const usep = u.endsWith(path62.sep) ? "" : path62.sep;
|
|
59002
59186
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
59003
59187
|
}
|
|
59004
|
-
const root =
|
|
59005
|
-
const sep3 = root.endsWith(
|
|
59188
|
+
const root = path62.resolve(personaRoot);
|
|
59189
|
+
const sep3 = root.endsWith(path62.sep) ? "" : path62.sep;
|
|
59006
59190
|
if (!target.startsWith(root + sep3)) return false;
|
|
59007
|
-
const rel =
|
|
59191
|
+
const rel = path62.relative(root, target);
|
|
59008
59192
|
if (!rel || rel.startsWith("..")) return false;
|
|
59009
|
-
const personaId2 = rel.split(
|
|
59193
|
+
const personaId2 = rel.split(path62.sep)[0];
|
|
59010
59194
|
if (!personaId2) return false;
|
|
59011
59195
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
59012
59196
|
if (allowed === "*") return true;
|
|
59013
59197
|
return allowed.has(personaId2);
|
|
59014
59198
|
}
|
|
59015
59199
|
function personaIdFromPath(absPath, personaRoot) {
|
|
59016
|
-
const root =
|
|
59017
|
-
const target =
|
|
59018
|
-
const sep3 = root.endsWith(
|
|
59200
|
+
const root = path62.resolve(personaRoot);
|
|
59201
|
+
const target = path62.resolve(absPath);
|
|
59202
|
+
const sep3 = root.endsWith(path62.sep) ? "" : path62.sep;
|
|
59019
59203
|
if (!target.startsWith(root + sep3)) return null;
|
|
59020
|
-
const rel =
|
|
59204
|
+
const rel = path62.relative(root, target);
|
|
59021
59205
|
if (!rel || rel.startsWith("..")) return null;
|
|
59022
|
-
const id = rel.split(
|
|
59206
|
+
const id = rel.split(path62.sep)[0];
|
|
59023
59207
|
return id || null;
|
|
59024
59208
|
}
|
|
59025
59209
|
function isPathWithin(dir, absPath) {
|
|
59026
|
-
const d =
|
|
59027
|
-
const t =
|
|
59028
|
-
const sep3 = d.endsWith(
|
|
59210
|
+
const d = path62.resolve(dir);
|
|
59211
|
+
const t = path62.resolve(absPath);
|
|
59212
|
+
const sep3 = d.endsWith(path62.sep) ? "" : path62.sep;
|
|
59029
59213
|
return t === d || t.startsWith(d + sep3);
|
|
59030
59214
|
}
|
|
59031
59215
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
59032
59216
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
59033
|
-
return personaIdFromPath(
|
|
59217
|
+
return personaIdFromPath(path62.resolve(absPath), personaRoot) === personaId2;
|
|
59034
59218
|
}
|
|
59035
59219
|
|
|
59036
59220
|
// src/handlers/history.ts
|
|
@@ -59083,7 +59267,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59083
59267
|
if (!pid) return false;
|
|
59084
59268
|
return isGuestPathAllowed(
|
|
59085
59269
|
ctx.grants,
|
|
59086
|
-
|
|
59270
|
+
path63.join(personaRoot, pid),
|
|
59087
59271
|
personaRoot,
|
|
59088
59272
|
"read",
|
|
59089
59273
|
userWorkDir
|
|
@@ -59095,7 +59279,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59095
59279
|
};
|
|
59096
59280
|
const list = async (frame, _client, ctx) => {
|
|
59097
59281
|
const args = HistoryListArgs.parse(frame);
|
|
59098
|
-
assertGuestPath(ctx,
|
|
59282
|
+
assertGuestPath(ctx, path63.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
59099
59283
|
const sessions = await history.listSessions(args);
|
|
59100
59284
|
return { response: { type: "history:list", sessions } };
|
|
59101
59285
|
};
|
|
@@ -59139,14 +59323,14 @@ function buildHistoryHandlers(deps) {
|
|
|
59139
59323
|
};
|
|
59140
59324
|
const subagents = async (frame, _client, ctx) => {
|
|
59141
59325
|
const args = HistorySubagentsArgs.parse(frame);
|
|
59142
|
-
assertGuestPath(ctx,
|
|
59326
|
+
assertGuestPath(ctx, path63.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
59143
59327
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
59144
59328
|
const subs = await history.listSubagents(args);
|
|
59145
59329
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
59146
59330
|
};
|
|
59147
59331
|
const subagentRead = async (frame, _client, ctx) => {
|
|
59148
59332
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
59149
|
-
assertGuestPath(ctx,
|
|
59333
|
+
assertGuestPath(ctx, path63.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
59150
59334
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
59151
59335
|
const res = await history.readSubagent(args);
|
|
59152
59336
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -59156,7 +59340,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59156
59340
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
59157
59341
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
59158
59342
|
const filtered = dirs.filter(
|
|
59159
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
59343
|
+
(d) => isGuestPathAllowed(ctx.grants, path63.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
59160
59344
|
);
|
|
59161
59345
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
59162
59346
|
}
|
|
@@ -59173,8 +59357,8 @@ function buildHistoryHandlers(deps) {
|
|
|
59173
59357
|
}
|
|
59174
59358
|
|
|
59175
59359
|
// src/handlers/workspace.ts
|
|
59176
|
-
var
|
|
59177
|
-
var
|
|
59360
|
+
var path64 = __toESM(require("path"), 1);
|
|
59361
|
+
var os18 = __toESM(require("os"), 1);
|
|
59178
59362
|
init_protocol();
|
|
59179
59363
|
init_protocol();
|
|
59180
59364
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -59214,23 +59398,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59214
59398
|
const list = async (frame, _client, ctx) => {
|
|
59215
59399
|
const args = WorkspaceListArgs.parse(frame);
|
|
59216
59400
|
const isGuest = ctx?.principal.kind === "guest";
|
|
59217
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
59218
|
-
const resolvedCwd =
|
|
59219
|
-
const target = args.path ?
|
|
59401
|
+
const fallbackCwd = isGuest && personaRoot ? personaRoot : os18.homedir();
|
|
59402
|
+
const resolvedCwd = path64.resolve(args.cwd ?? fallbackCwd);
|
|
59403
|
+
const target = args.path ? path64.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
59220
59404
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
59221
59405
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
59222
59406
|
return { response: { type: "workspace:list", ...res } };
|
|
59223
59407
|
};
|
|
59224
59408
|
const read = async (frame, _client, ctx) => {
|
|
59225
59409
|
const args = WorkspaceReadArgs.parse(frame);
|
|
59226
|
-
const target =
|
|
59410
|
+
const target = path64.isAbsolute(args.path) ? path64.resolve(args.path) : path64.resolve(args.cwd, args.path);
|
|
59227
59411
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
59228
59412
|
const res = workspace.read(args);
|
|
59229
59413
|
return { response: { type: "workspace:read", ...res } };
|
|
59230
59414
|
};
|
|
59231
59415
|
const skillsList = async (frame, _client, ctx) => {
|
|
59232
59416
|
const args = SkillsListArgs.parse(frame);
|
|
59233
|
-
const cwdAbs =
|
|
59417
|
+
const cwdAbs = path64.resolve(args.cwd);
|
|
59234
59418
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
59235
59419
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
59236
59420
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -59242,7 +59426,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59242
59426
|
};
|
|
59243
59427
|
const agentsList = async (frame, _client, ctx) => {
|
|
59244
59428
|
const args = AgentsListArgs.parse(frame);
|
|
59245
|
-
const cwdAbs =
|
|
59429
|
+
const cwdAbs = path64.resolve(args.cwd);
|
|
59246
59430
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
59247
59431
|
if (args.tool === "codex") {
|
|
59248
59432
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -59264,20 +59448,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59264
59448
|
}
|
|
59265
59449
|
|
|
59266
59450
|
// src/handlers/git.ts
|
|
59267
|
-
var
|
|
59451
|
+
var path66 = __toESM(require("path"), 1);
|
|
59268
59452
|
init_protocol();
|
|
59269
59453
|
init_protocol();
|
|
59270
59454
|
|
|
59271
59455
|
// src/workspace/git.ts
|
|
59272
|
-
var
|
|
59273
|
-
var
|
|
59274
|
-
var
|
|
59456
|
+
var import_node_child_process13 = require("child_process");
|
|
59457
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
59458
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
59275
59459
|
var import_node_util = require("util");
|
|
59276
|
-
var pexec = (0, import_node_util.promisify)(
|
|
59460
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process13.execFile);
|
|
59277
59461
|
function normalizePath(p2) {
|
|
59278
|
-
const resolved =
|
|
59462
|
+
const resolved = import_node_path53.default.resolve(p2);
|
|
59279
59463
|
try {
|
|
59280
|
-
return
|
|
59464
|
+
return import_node_fs48.default.realpathSync(resolved);
|
|
59281
59465
|
} catch {
|
|
59282
59466
|
return resolved;
|
|
59283
59467
|
}
|
|
@@ -59351,7 +59535,7 @@ async function listGitBranches(cwd) {
|
|
|
59351
59535
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
59352
59536
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
59353
59537
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
59354
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
59538
|
+
if (!isGuestPathAllowed(ctx.grants, path66.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
59355
59539
|
throw new ClawdError(
|
|
59356
59540
|
ERROR_CODES.UNAUTHORIZED,
|
|
59357
59541
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -59984,7 +60168,7 @@ function buildDeviceHandlers(deps) {
|
|
|
59984
60168
|
}
|
|
59985
60169
|
|
|
59986
60170
|
// src/handlers/meta.ts
|
|
59987
|
-
var
|
|
60171
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
59988
60172
|
init_protocol();
|
|
59989
60173
|
|
|
59990
60174
|
// src/handlers/method-grants.ts
|
|
@@ -60244,21 +60428,21 @@ function computeMethodAccess(args) {
|
|
|
60244
60428
|
}
|
|
60245
60429
|
|
|
60246
60430
|
// src/version.ts
|
|
60247
|
-
var version = "0.2.
|
|
60431
|
+
var version = "0.2.353".length > 0 ? "0.2.353" : "dev";
|
|
60248
60432
|
|
|
60249
60433
|
// src/cli-probe/probe.ts
|
|
60250
|
-
var
|
|
60251
|
-
var
|
|
60434
|
+
var fs60 = __toESM(require("fs"), 1);
|
|
60435
|
+
var path67 = __toESM(require("path"), 1);
|
|
60252
60436
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
60253
60437
|
var BIN_NAME = "clawd";
|
|
60254
60438
|
var MAX_PARENT_HOPS = 5;
|
|
60255
60439
|
function probeGlobalCli(pathEnv) {
|
|
60256
60440
|
if (!pathEnv) return null;
|
|
60257
|
-
for (const dir of pathEnv.split(
|
|
60441
|
+
for (const dir of pathEnv.split(path67.delimiter)) {
|
|
60258
60442
|
if (!dir) continue;
|
|
60259
60443
|
let real;
|
|
60260
60444
|
try {
|
|
60261
|
-
real =
|
|
60445
|
+
real = fs60.realpathSync(path67.join(dir, BIN_NAME));
|
|
60262
60446
|
} catch {
|
|
60263
60447
|
continue;
|
|
60264
60448
|
}
|
|
@@ -60268,15 +60452,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
60268
60452
|
return null;
|
|
60269
60453
|
}
|
|
60270
60454
|
function readOwnPackageVersion(entryPath) {
|
|
60271
|
-
let dir =
|
|
60455
|
+
let dir = path67.dirname(entryPath);
|
|
60272
60456
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
60273
60457
|
try {
|
|
60274
|
-
const raw =
|
|
60458
|
+
const raw = fs60.readFileSync(path67.join(dir, "package.json"), "utf8");
|
|
60275
60459
|
const pkg = JSON.parse(raw);
|
|
60276
60460
|
if (pkg.name !== PKG_NAME) return null;
|
|
60277
60461
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
60278
60462
|
} catch {
|
|
60279
|
-
const parent =
|
|
60463
|
+
const parent = path67.dirname(dir);
|
|
60280
60464
|
if (parent === dir) return null;
|
|
60281
60465
|
dir = parent;
|
|
60282
60466
|
}
|
|
@@ -60312,7 +60496,7 @@ function buildReadyFrame(deps, client) {
|
|
|
60312
60496
|
return {
|
|
60313
60497
|
version,
|
|
60314
60498
|
protocolVersion: PROTOCOL_VERSION,
|
|
60315
|
-
hostname:
|
|
60499
|
+
hostname: import_node_os19.default.hostname(),
|
|
60316
60500
|
os: process.platform,
|
|
60317
60501
|
tools,
|
|
60318
60502
|
runningSessions: info.runningSessions,
|
|
@@ -60439,7 +60623,7 @@ function buildPersonaHandlers(deps) {
|
|
|
60439
60623
|
}
|
|
60440
60624
|
|
|
60441
60625
|
// src/handlers/attachment.ts
|
|
60442
|
-
var
|
|
60626
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60443
60627
|
init_protocol();
|
|
60444
60628
|
init_protocol();
|
|
60445
60629
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -60519,12 +60703,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
60519
60703
|
`session ${args.sessionId} scope unresolved`
|
|
60520
60704
|
);
|
|
60521
60705
|
}
|
|
60522
|
-
const cwdAbs =
|
|
60523
|
-
const candidateAbs =
|
|
60706
|
+
const cwdAbs = import_node_path54.default.resolve(sessionFile.cwd);
|
|
60707
|
+
const candidateAbs = import_node_path54.default.isAbsolute(args.relPath) ? import_node_path54.default.resolve(args.relPath) : import_node_path54.default.resolve(cwdAbs, args.relPath);
|
|
60524
60708
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
60525
60709
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
60526
60710
|
const entry = entries.find((e) => {
|
|
60527
|
-
const storedAbs =
|
|
60711
|
+
const storedAbs = import_node_path54.default.isAbsolute(e.relPath) ? import_node_path54.default.resolve(e.relPath) : import_node_path54.default.resolve(cwdAbs, e.relPath);
|
|
60528
60712
|
return storedAbs === candidateAbs && !e.stale;
|
|
60529
60713
|
});
|
|
60530
60714
|
if (!entry) {
|
|
@@ -60549,7 +60733,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
60549
60733
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
60550
60734
|
const f = deps.sessionStore.read(sessionId);
|
|
60551
60735
|
if (!f) return;
|
|
60552
|
-
assertGuestAttachmentPath(ctx,
|
|
60736
|
+
assertGuestAttachmentPath(ctx, import_node_path54.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
60553
60737
|
}
|
|
60554
60738
|
const groupAdd = async (frame, _client, ctx) => {
|
|
60555
60739
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -60564,8 +60748,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
60564
60748
|
if (!scope) {
|
|
60565
60749
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
60566
60750
|
}
|
|
60567
|
-
const cwdAbs =
|
|
60568
|
-
const candidateAbs =
|
|
60751
|
+
const cwdAbs = import_node_path54.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
60752
|
+
const candidateAbs = import_node_path54.default.isAbsolute(args.relPath) ? import_node_path54.default.resolve(args.relPath) : import_node_path54.default.resolve(cwdAbs, args.relPath);
|
|
60569
60753
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
60570
60754
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
60571
60755
|
const size = 0;
|
|
@@ -60624,19 +60808,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
60624
60808
|
|
|
60625
60809
|
// src/handlers/extension.ts
|
|
60626
60810
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
60627
|
-
var
|
|
60811
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
60628
60812
|
init_protocol();
|
|
60629
60813
|
|
|
60630
60814
|
// src/extension/bundle-zip.ts
|
|
60631
60815
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
60632
|
-
var
|
|
60816
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
60633
60817
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
60634
60818
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
60635
60819
|
async function bundleExtensionDir(dir) {
|
|
60636
60820
|
const entries = await listFilesSorted(dir);
|
|
60637
60821
|
const zip = new import_jszip2.default();
|
|
60638
60822
|
for (const rel of entries) {
|
|
60639
|
-
const abs =
|
|
60823
|
+
const abs = import_node_path55.default.join(dir, rel);
|
|
60640
60824
|
const content = await import_promises8.default.readFile(abs);
|
|
60641
60825
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
60642
60826
|
}
|
|
@@ -60657,7 +60841,7 @@ async function listFilesSorted(rootDir) {
|
|
|
60657
60841
|
return out;
|
|
60658
60842
|
}
|
|
60659
60843
|
async function walk(absRoot, relPrefix, out) {
|
|
60660
|
-
const dirAbs =
|
|
60844
|
+
const dirAbs = import_node_path55.default.join(absRoot, relPrefix);
|
|
60661
60845
|
const entries = await import_promises8.default.readdir(dirAbs, { withFileTypes: true });
|
|
60662
60846
|
for (const e of entries) {
|
|
60663
60847
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -60711,25 +60895,25 @@ function computePublishCheck(args) {
|
|
|
60711
60895
|
|
|
60712
60896
|
// src/extension/install-flow.ts
|
|
60713
60897
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
60714
|
-
var
|
|
60715
|
-
var
|
|
60898
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
60899
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
60716
60900
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
60717
60901
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
60718
60902
|
|
|
60719
60903
|
// src/extension/paths.ts
|
|
60720
|
-
var
|
|
60721
|
-
var
|
|
60904
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
60905
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
60722
60906
|
function clawdHomeRoot(override) {
|
|
60723
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
60907
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path56.default.join(import_node_os20.default.homedir(), ".clawd");
|
|
60724
60908
|
}
|
|
60725
60909
|
function extensionsRoot(override) {
|
|
60726
|
-
return
|
|
60910
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extensions");
|
|
60727
60911
|
}
|
|
60728
60912
|
function publishedChannelsFile(override) {
|
|
60729
|
-
return
|
|
60913
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
60730
60914
|
}
|
|
60731
60915
|
function bundleCacheRoot(override) {
|
|
60732
|
-
return
|
|
60916
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
60733
60917
|
}
|
|
60734
60918
|
|
|
60735
60919
|
// src/extension/install-flow.ts
|
|
@@ -60756,7 +60940,7 @@ async function installFromChannel(args, deps) {
|
|
|
60756
60940
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60757
60941
|
}
|
|
60758
60942
|
for (const name of Object.keys(zip.files)) {
|
|
60759
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
60943
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path57.default.isAbsolute(name)) {
|
|
60760
60944
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
60761
60945
|
}
|
|
60762
60946
|
}
|
|
@@ -60788,7 +60972,7 @@ async function installFromChannel(args, deps) {
|
|
|
60788
60972
|
);
|
|
60789
60973
|
}
|
|
60790
60974
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
60791
|
-
const destDir =
|
|
60975
|
+
const destDir = import_node_path57.default.join(deps.extensionsRoot, localExtId);
|
|
60792
60976
|
let destExists = false;
|
|
60793
60977
|
try {
|
|
60794
60978
|
await import_promises9.default.access(destDir);
|
|
@@ -60802,16 +60986,16 @@ async function installFromChannel(args, deps) {
|
|
|
60802
60986
|
);
|
|
60803
60987
|
}
|
|
60804
60988
|
const stage = await import_promises9.default.mkdtemp(
|
|
60805
|
-
|
|
60989
|
+
import_node_path57.default.join(import_node_os21.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
60806
60990
|
);
|
|
60807
60991
|
try {
|
|
60808
60992
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60809
|
-
const dest =
|
|
60993
|
+
const dest = import_node_path57.default.join(stage, name);
|
|
60810
60994
|
if (entry.dir) {
|
|
60811
60995
|
await import_promises9.default.mkdir(dest, { recursive: true });
|
|
60812
60996
|
continue;
|
|
60813
60997
|
}
|
|
60814
|
-
await import_promises9.default.mkdir(
|
|
60998
|
+
await import_promises9.default.mkdir(import_node_path57.default.dirname(dest), { recursive: true });
|
|
60815
60999
|
if (name === "manifest.json") {
|
|
60816
61000
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60817
61001
|
await import_promises9.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -60832,8 +61016,8 @@ async function installFromChannel(args, deps) {
|
|
|
60832
61016
|
|
|
60833
61017
|
// src/extension/update-flow.ts
|
|
60834
61018
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
60835
|
-
var
|
|
60836
|
-
var
|
|
61019
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
61020
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
60837
61021
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
60838
61022
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
60839
61023
|
var UpdateError = class extends Error {
|
|
@@ -60849,11 +61033,11 @@ async function updateFromChannel(args, deps) {
|
|
|
60849
61033
|
channelRef.extId,
|
|
60850
61034
|
channelRef.ownerPrincipalId
|
|
60851
61035
|
);
|
|
60852
|
-
const liveDir =
|
|
61036
|
+
const liveDir = import_node_path58.default.join(deps.extensionsRoot, localExtId);
|
|
60853
61037
|
const prevDir = `${liveDir}.prev`;
|
|
60854
61038
|
let existingVersion;
|
|
60855
61039
|
try {
|
|
60856
|
-
const raw = await import_promises10.default.readFile(
|
|
61040
|
+
const raw = await import_promises10.default.readFile(import_node_path58.default.join(liveDir, "manifest.json"), "utf8");
|
|
60857
61041
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
60858
61042
|
if (!parsed2.success) {
|
|
60859
61043
|
throw new UpdateError(
|
|
@@ -60886,7 +61070,7 @@ async function updateFromChannel(args, deps) {
|
|
|
60886
61070
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60887
61071
|
}
|
|
60888
61072
|
for (const name of Object.keys(zip.files)) {
|
|
60889
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
61073
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path58.default.isAbsolute(name)) {
|
|
60890
61074
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
60891
61075
|
}
|
|
60892
61076
|
}
|
|
@@ -60921,16 +61105,16 @@ async function updateFromChannel(args, deps) {
|
|
|
60921
61105
|
await import_promises10.default.rm(prevDir, { recursive: true, force: true });
|
|
60922
61106
|
await import_promises10.default.rename(liveDir, prevDir);
|
|
60923
61107
|
const stage = await import_promises10.default.mkdtemp(
|
|
60924
|
-
|
|
61108
|
+
import_node_path58.default.join(import_node_os22.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
60925
61109
|
);
|
|
60926
61110
|
try {
|
|
60927
61111
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60928
|
-
const dest =
|
|
61112
|
+
const dest = import_node_path58.default.join(stage, name);
|
|
60929
61113
|
if (entry.dir) {
|
|
60930
61114
|
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
60931
61115
|
continue;
|
|
60932
61116
|
}
|
|
60933
|
-
await import_promises10.default.mkdir(
|
|
61117
|
+
await import_promises10.default.mkdir(import_node_path58.default.dirname(dest), { recursive: true });
|
|
60934
61118
|
if (name === "manifest.json") {
|
|
60935
61119
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60936
61120
|
await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -60997,7 +61181,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
60997
61181
|
);
|
|
60998
61182
|
}
|
|
60999
61183
|
}
|
|
61000
|
-
const manifestPath =
|
|
61184
|
+
const manifestPath = import_node_path59.default.join(root, extId, "manifest.json");
|
|
61001
61185
|
const manifest = await readManifest(root, extId);
|
|
61002
61186
|
const next = { ...manifest, version: newVersion };
|
|
61003
61187
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -61005,7 +61189,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
61005
61189
|
await import_promises11.default.rename(tmp, manifestPath);
|
|
61006
61190
|
}
|
|
61007
61191
|
async function readManifest(root, extId) {
|
|
61008
|
-
const file =
|
|
61192
|
+
const file = import_node_path59.default.join(root, extId, "manifest.json");
|
|
61009
61193
|
let raw;
|
|
61010
61194
|
try {
|
|
61011
61195
|
raw = await import_promises11.default.readFile(file, "utf8");
|
|
@@ -61089,7 +61273,7 @@ function buildExtensionHandlers(deps) {
|
|
|
61089
61273
|
};
|
|
61090
61274
|
async function buildSnapshotMeta(extId) {
|
|
61091
61275
|
const manifest = await readManifest(deps.root, extId);
|
|
61092
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
61276
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path59.default.join(deps.root, extId));
|
|
61093
61277
|
return { manifest, contentHash: sha256, buffer };
|
|
61094
61278
|
}
|
|
61095
61279
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -61264,9 +61448,9 @@ function buildExtensionHandlers(deps) {
|
|
|
61264
61448
|
}
|
|
61265
61449
|
|
|
61266
61450
|
// src/app-builder/project-store.ts
|
|
61267
|
-
var
|
|
61268
|
-
var
|
|
61269
|
-
var
|
|
61451
|
+
var import_node_fs49 = require("fs");
|
|
61452
|
+
var import_node_child_process14 = require("child_process");
|
|
61453
|
+
var import_node_path60 = require("path");
|
|
61270
61454
|
init_protocol();
|
|
61271
61455
|
var PROJECTS_DIR = "projects";
|
|
61272
61456
|
var META_FILE = ".clawd-project.json";
|
|
@@ -61280,19 +61464,19 @@ var ProjectStore = class {
|
|
|
61280
61464
|
root;
|
|
61281
61465
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
61282
61466
|
metaPath(name) {
|
|
61283
|
-
return (0,
|
|
61467
|
+
return (0, import_node_path60.join)(this.projectsRoot(), name, META_FILE);
|
|
61284
61468
|
}
|
|
61285
61469
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
61286
61470
|
projectDir(name) {
|
|
61287
|
-
return (0,
|
|
61471
|
+
return (0, import_node_path60.join)(this.projectsRoot(), name);
|
|
61288
61472
|
}
|
|
61289
61473
|
projectsRoot() {
|
|
61290
|
-
return (0,
|
|
61474
|
+
return (0, import_node_path60.join)(this.root, PROJECTS_DIR);
|
|
61291
61475
|
}
|
|
61292
61476
|
async list() {
|
|
61293
61477
|
let entries;
|
|
61294
61478
|
try {
|
|
61295
|
-
entries = await
|
|
61479
|
+
entries = await import_node_fs49.promises.readdir(this.projectsRoot());
|
|
61296
61480
|
} catch (err) {
|
|
61297
61481
|
if (err.code === "ENOENT") return [];
|
|
61298
61482
|
throw err;
|
|
@@ -61300,7 +61484,7 @@ var ProjectStore = class {
|
|
|
61300
61484
|
const out = [];
|
|
61301
61485
|
for (const name of entries) {
|
|
61302
61486
|
try {
|
|
61303
|
-
const raw = await
|
|
61487
|
+
const raw = await import_node_fs49.promises.readFile(this.metaPath(name), "utf8");
|
|
61304
61488
|
const json = JSON.parse(raw);
|
|
61305
61489
|
let migrated = false;
|
|
61306
61490
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -61311,7 +61495,7 @@ var ProjectStore = class {
|
|
|
61311
61495
|
if (parsed.success) {
|
|
61312
61496
|
out.push(parsed.data);
|
|
61313
61497
|
if (migrated) {
|
|
61314
|
-
void
|
|
61498
|
+
void import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
61315
61499
|
});
|
|
61316
61500
|
}
|
|
61317
61501
|
}
|
|
@@ -61355,8 +61539,8 @@ var ProjectStore = class {
|
|
|
61355
61539
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
61356
61540
|
}
|
|
61357
61541
|
const dir = this.projectDir(name);
|
|
61358
|
-
await
|
|
61359
|
-
await
|
|
61542
|
+
await import_node_fs49.promises.mkdir(dir, { recursive: true });
|
|
61543
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
61360
61544
|
return meta;
|
|
61361
61545
|
}
|
|
61362
61546
|
/**
|
|
@@ -61370,7 +61554,7 @@ var ProjectStore = class {
|
|
|
61370
61554
|
async scaffold(name, templateSrcDir, scaffoldScriptPath) {
|
|
61371
61555
|
const destDir = this.projectDir(name);
|
|
61372
61556
|
return await new Promise((resolve6, reject) => {
|
|
61373
|
-
const child = (0,
|
|
61557
|
+
const child = (0, import_node_child_process14.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
61374
61558
|
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
61375
61559
|
stdio: ["ignore", "pipe", "pipe"]
|
|
61376
61560
|
});
|
|
@@ -61399,7 +61583,7 @@ var ProjectStore = class {
|
|
|
61399
61583
|
}
|
|
61400
61584
|
async delete(name) {
|
|
61401
61585
|
const dir = this.projectDir(name);
|
|
61402
|
-
await
|
|
61586
|
+
await import_node_fs49.promises.rm(dir, { recursive: true, force: true });
|
|
61403
61587
|
}
|
|
61404
61588
|
async updatePort(name, newPort) {
|
|
61405
61589
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -61415,7 +61599,7 @@ var ProjectStore = class {
|
|
|
61415
61599
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
61416
61600
|
}
|
|
61417
61601
|
const updated = { ...target, port: newPort };
|
|
61418
|
-
await
|
|
61602
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
61419
61603
|
return updated;
|
|
61420
61604
|
}
|
|
61421
61605
|
/**
|
|
@@ -61432,7 +61616,7 @@ var ProjectStore = class {
|
|
|
61432
61616
|
if (!validated.success) {
|
|
61433
61617
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
61434
61618
|
}
|
|
61435
|
-
await
|
|
61619
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61436
61620
|
return validated.data;
|
|
61437
61621
|
}
|
|
61438
61622
|
/**
|
|
@@ -61453,7 +61637,7 @@ var ProjectStore = class {
|
|
|
61453
61637
|
if (!validated.success) {
|
|
61454
61638
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
61455
61639
|
}
|
|
61456
|
-
await
|
|
61640
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61457
61641
|
return validated.data;
|
|
61458
61642
|
}
|
|
61459
61643
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -61468,13 +61652,13 @@ var ProjectStore = class {
|
|
|
61468
61652
|
if (!validated.success) {
|
|
61469
61653
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
61470
61654
|
}
|
|
61471
|
-
await
|
|
61655
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61472
61656
|
return validated.data;
|
|
61473
61657
|
}
|
|
61474
61658
|
};
|
|
61475
61659
|
|
|
61476
61660
|
// src/app-builder/kill-port.ts
|
|
61477
|
-
var
|
|
61661
|
+
var import_node_child_process15 = require("child_process");
|
|
61478
61662
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
61479
61663
|
let pids;
|
|
61480
61664
|
try {
|
|
@@ -61516,7 +61700,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
61516
61700
|
}
|
|
61517
61701
|
function listPidsOnPort(port) {
|
|
61518
61702
|
return new Promise((resolve6, reject) => {
|
|
61519
|
-
(0,
|
|
61703
|
+
(0, import_node_child_process15.execFile)(
|
|
61520
61704
|
"lsof",
|
|
61521
61705
|
["-ti", `:${port}`],
|
|
61522
61706
|
{ timeout: 3e3 },
|
|
@@ -61588,9 +61772,9 @@ var PublishJobRegistry = class {
|
|
|
61588
61772
|
};
|
|
61589
61773
|
|
|
61590
61774
|
// src/app-builder/publish-job-runner.ts
|
|
61591
|
-
var
|
|
61592
|
-
var
|
|
61593
|
-
var
|
|
61775
|
+
var import_node_child_process16 = require("child_process");
|
|
61776
|
+
var import_node_fs50 = require("fs");
|
|
61777
|
+
var import_node_path61 = require("path");
|
|
61594
61778
|
|
|
61595
61779
|
// src/app-builder/publish-stage-parser.ts
|
|
61596
61780
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -61617,19 +61801,19 @@ function tailStderrLines(buf, n) {
|
|
|
61617
61801
|
// src/app-builder/publish-job-runner.ts
|
|
61618
61802
|
async function startPublishJob(deps, args) {
|
|
61619
61803
|
const { registry: registry2, projectDir } = deps;
|
|
61620
|
-
const
|
|
61804
|
+
const spawn13 = deps.spawnImpl ?? import_node_child_process16.spawn;
|
|
61621
61805
|
if (registry2.has(args.name)) {
|
|
61622
61806
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
61623
61807
|
}
|
|
61624
61808
|
const projDir = projectDir(args.name);
|
|
61625
|
-
const logPath = (0,
|
|
61809
|
+
const logPath = (0, import_node_path61.join)(projDir, ".publish.log");
|
|
61626
61810
|
let logStream = null;
|
|
61627
61811
|
try {
|
|
61628
|
-
logStream = (0,
|
|
61812
|
+
logStream = (0, import_node_fs50.createWriteStream)(logPath, { flags: "w" });
|
|
61629
61813
|
} catch {
|
|
61630
61814
|
logStream = null;
|
|
61631
61815
|
}
|
|
61632
|
-
const child =
|
|
61816
|
+
const child = spawn13("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
|
|
61633
61817
|
cwd: projDir,
|
|
61634
61818
|
env: process.env,
|
|
61635
61819
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -61882,8 +62066,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
61882
62066
|
|
|
61883
62067
|
// src/handlers/app-builder.ts
|
|
61884
62068
|
init_protocol();
|
|
61885
|
-
var
|
|
61886
|
-
var
|
|
62069
|
+
var import_node_path62 = require("path");
|
|
62070
|
+
var import_node_fs51 = require("fs");
|
|
61887
62071
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
61888
62072
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
61889
62073
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -61964,7 +62148,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
61964
62148
|
async function listAllUsersProjects() {
|
|
61965
62149
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
61966
62150
|
const getStore = deps.getStore;
|
|
61967
|
-
const userIds = await
|
|
62151
|
+
const userIds = await import_node_fs51.promises.readdir(deps.usersRoot).catch(() => []);
|
|
61968
62152
|
const perUser = await Promise.all(
|
|
61969
62153
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
61970
62154
|
);
|
|
@@ -62033,8 +62217,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
62033
62217
|
const project = await userStore.create(f.name, reservedPorts);
|
|
62034
62218
|
try {
|
|
62035
62219
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
62036
|
-
const templateSrcDir = (0,
|
|
62037
|
-
const scaffoldScript = (0,
|
|
62220
|
+
const templateSrcDir = (0, import_node_path62.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
62221
|
+
const scaffoldScript = (0, import_node_path62.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
62038
62222
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
62039
62223
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
62040
62224
|
name: project.name,
|
|
@@ -62238,7 +62422,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
62238
62422
|
await userStore.clearPublishJob(args.name);
|
|
62239
62423
|
}
|
|
62240
62424
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
62241
|
-
const scriptPath = (0,
|
|
62425
|
+
const scriptPath = (0, import_node_path62.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
62242
62426
|
deps.logger?.info("app-builder.publish.start", {
|
|
62243
62427
|
name: args.name,
|
|
62244
62428
|
sessionId: boundSession.sessionId,
|
|
@@ -62658,7 +62842,7 @@ function buildVisitorHandlers(deps) {
|
|
|
62658
62842
|
|
|
62659
62843
|
// src/extension/registry.ts
|
|
62660
62844
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62661
|
-
var
|
|
62845
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
62662
62846
|
async function loadAll(root) {
|
|
62663
62847
|
let entries;
|
|
62664
62848
|
try {
|
|
@@ -62671,13 +62855,13 @@ async function loadAll(root) {
|
|
|
62671
62855
|
for (const ent of entries) {
|
|
62672
62856
|
if (!ent.isDirectory()) continue;
|
|
62673
62857
|
if (ent.name.startsWith(".")) continue;
|
|
62674
|
-
records.push(await loadOne(
|
|
62858
|
+
records.push(await loadOne(import_node_path63.default.join(root, ent.name), ent.name));
|
|
62675
62859
|
}
|
|
62676
62860
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
62677
62861
|
return records;
|
|
62678
62862
|
}
|
|
62679
62863
|
async function loadOne(dir, dirName) {
|
|
62680
|
-
const manifestPath =
|
|
62864
|
+
const manifestPath = import_node_path63.default.join(dir, "manifest.json");
|
|
62681
62865
|
let raw;
|
|
62682
62866
|
try {
|
|
62683
62867
|
raw = await import_promises12.default.readFile(manifestPath, "utf8");
|
|
@@ -62722,7 +62906,7 @@ async function loadOne(dir, dirName) {
|
|
|
62722
62906
|
|
|
62723
62907
|
// src/extension/uninstall.ts
|
|
62724
62908
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
62725
|
-
var
|
|
62909
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
62726
62910
|
var UninstallError = class extends Error {
|
|
62727
62911
|
constructor(code, message) {
|
|
62728
62912
|
super(message);
|
|
@@ -62731,7 +62915,7 @@ var UninstallError = class extends Error {
|
|
|
62731
62915
|
code;
|
|
62732
62916
|
};
|
|
62733
62917
|
async function uninstall(deps) {
|
|
62734
|
-
const dir =
|
|
62918
|
+
const dir = import_node_path64.default.join(deps.root, deps.extId);
|
|
62735
62919
|
try {
|
|
62736
62920
|
await import_promises13.default.access(dir);
|
|
62737
62921
|
} catch {
|
|
@@ -62748,15 +62932,15 @@ var import_node_crypto19 = require("crypto");
|
|
|
62748
62932
|
init_protocol();
|
|
62749
62933
|
|
|
62750
62934
|
// src/peer-ops/run-command.ts
|
|
62751
|
-
var
|
|
62752
|
-
var
|
|
62935
|
+
var import_node_child_process17 = require("child_process");
|
|
62936
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
62753
62937
|
var DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
62754
62938
|
var MAX_TIMEOUT_MS = 3e5;
|
|
62755
62939
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
62756
62940
|
function runCommand(command, opts = {}) {
|
|
62757
62941
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4, MAX_TIMEOUT_MS);
|
|
62758
62942
|
return new Promise((resolve6) => {
|
|
62759
|
-
const child = (0,
|
|
62943
|
+
const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os23.default.homedir() });
|
|
62760
62944
|
const out = [];
|
|
62761
62945
|
const err = [];
|
|
62762
62946
|
let outBytes = 0;
|
|
@@ -62975,14 +63159,14 @@ function buildMethodHandlers(deps) {
|
|
|
62975
63159
|
init_protocol();
|
|
62976
63160
|
|
|
62977
63161
|
// src/tools/version-probe.ts
|
|
62978
|
-
var
|
|
63162
|
+
var import_node_child_process18 = require("child_process");
|
|
62979
63163
|
init_claude();
|
|
62980
63164
|
function parseVersionOutput(out) {
|
|
62981
63165
|
return /(\d+\.\d+\.\d+)/.exec(out)?.[1];
|
|
62982
63166
|
}
|
|
62983
63167
|
function execVersion(bin) {
|
|
62984
63168
|
return new Promise((resolve6, reject) => {
|
|
62985
|
-
(0,
|
|
63169
|
+
(0, import_node_child_process18.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
|
|
62986
63170
|
if (err) reject(err);
|
|
62987
63171
|
else resolve6(String(stdout));
|
|
62988
63172
|
});
|
|
@@ -63093,7 +63277,7 @@ function buildOnboardingHandlers(deps) {
|
|
|
63093
63277
|
}
|
|
63094
63278
|
|
|
63095
63279
|
// src/app-builder/dev-server-supervisor.ts
|
|
63096
|
-
var
|
|
63280
|
+
var import_node_child_process19 = require("child_process");
|
|
63097
63281
|
var import_node_events2 = require("events");
|
|
63098
63282
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
63099
63283
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -63130,7 +63314,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
63130
63314
|
tunnelHost: args.tunnelHost,
|
|
63131
63315
|
devCommand: cmd
|
|
63132
63316
|
});
|
|
63133
|
-
const child = (0,
|
|
63317
|
+
const child = (0, import_node_child_process19.spawn)("sh", ["-c", cmd], {
|
|
63134
63318
|
cwd: args.cwd,
|
|
63135
63319
|
env,
|
|
63136
63320
|
stdio: "pipe",
|
|
@@ -63382,8 +63566,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
63382
63566
|
}
|
|
63383
63567
|
|
|
63384
63568
|
// src/extension/runtime.ts
|
|
63385
|
-
var
|
|
63386
|
-
var
|
|
63569
|
+
var import_node_child_process20 = require("child_process");
|
|
63570
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
63387
63571
|
var import_promises14 = require("timers/promises");
|
|
63388
63572
|
|
|
63389
63573
|
// src/extension/port-allocator.ts
|
|
@@ -63484,13 +63668,13 @@ var Runtime = class {
|
|
|
63484
63668
|
/\$CLAWOS_EXT_PORT/g,
|
|
63485
63669
|
String(port)
|
|
63486
63670
|
);
|
|
63487
|
-
const dir =
|
|
63671
|
+
const dir = import_node_path65.default.join(this.root, extId);
|
|
63488
63672
|
const env = {
|
|
63489
63673
|
...process.env,
|
|
63490
63674
|
CLAWOS_EXT_PORT: String(port),
|
|
63491
63675
|
CLAWOS_EXT_ID: extId
|
|
63492
63676
|
};
|
|
63493
|
-
const child = (0,
|
|
63677
|
+
const child = (0, import_node_child_process20.spawn)("sh", ["-c", cmd], {
|
|
63494
63678
|
cwd: dir,
|
|
63495
63679
|
env,
|
|
63496
63680
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -63596,7 +63780,7 @@ ${handle.stderrTail}`
|
|
|
63596
63780
|
|
|
63597
63781
|
// src/extension/published-channels.ts
|
|
63598
63782
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
63599
|
-
var
|
|
63783
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
63600
63784
|
init_zod();
|
|
63601
63785
|
var PublishedChannelsError = class extends Error {
|
|
63602
63786
|
constructor(code, message) {
|
|
@@ -63695,7 +63879,7 @@ var PublishedChannelStore = class {
|
|
|
63695
63879
|
)
|
|
63696
63880
|
};
|
|
63697
63881
|
const tmp = `${this.filePath}.tmp`;
|
|
63698
|
-
await import_promises15.default.mkdir(
|
|
63882
|
+
await import_promises15.default.mkdir(import_node_path66.default.dirname(this.filePath), { recursive: true });
|
|
63699
63883
|
await import_promises15.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
63700
63884
|
await import_promises15.default.rename(tmp, this.filePath);
|
|
63701
63885
|
}
|
|
@@ -63703,7 +63887,7 @@ var PublishedChannelStore = class {
|
|
|
63703
63887
|
|
|
63704
63888
|
// src/extension/bundle-cache.ts
|
|
63705
63889
|
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
63706
|
-
var
|
|
63890
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
63707
63891
|
var BundleCache = class {
|
|
63708
63892
|
constructor(rootDir) {
|
|
63709
63893
|
this.rootDir = rootDir;
|
|
@@ -63712,14 +63896,14 @@ var BundleCache = class {
|
|
|
63712
63896
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
63713
63897
|
async write(snapshotHash, buffer) {
|
|
63714
63898
|
await import_promises16.default.mkdir(this.rootDir, { recursive: true });
|
|
63715
|
-
const file =
|
|
63899
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63716
63900
|
const tmp = `${file}.tmp`;
|
|
63717
63901
|
await import_promises16.default.writeFile(tmp, buffer, { mode: 384 });
|
|
63718
63902
|
await import_promises16.default.rename(tmp, file);
|
|
63719
63903
|
}
|
|
63720
63904
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
63721
63905
|
async read(snapshotHash) {
|
|
63722
|
-
const file =
|
|
63906
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63723
63907
|
try {
|
|
63724
63908
|
return await import_promises16.default.readFile(file);
|
|
63725
63909
|
} catch (e) {
|
|
@@ -63729,7 +63913,7 @@ var BundleCache = class {
|
|
|
63729
63913
|
}
|
|
63730
63914
|
/** Idempotent — missing file is not an error. */
|
|
63731
63915
|
async delete(snapshotHash) {
|
|
63732
|
-
const file =
|
|
63916
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63733
63917
|
await import_promises16.default.rm(file, { force: true });
|
|
63734
63918
|
}
|
|
63735
63919
|
};
|
|
@@ -63750,26 +63934,26 @@ async function startDaemon(config) {
|
|
|
63750
63934
|
},
|
|
63751
63935
|
source: "daemon",
|
|
63752
63936
|
sampling: logShippingCfg.sampling,
|
|
63753
|
-
homeDir:
|
|
63937
|
+
homeDir: import_node_os24.default.homedir()
|
|
63754
63938
|
});
|
|
63755
|
-
const logDir =
|
|
63756
|
-
|
|
63939
|
+
const logDir = import_node_path68.default.join(config.dataDir, "log");
|
|
63940
|
+
import_node_fs52.default.mkdirSync(logDir, { recursive: true });
|
|
63757
63941
|
const logger = createLogger({
|
|
63758
63942
|
level: config.logLevel,
|
|
63759
|
-
file:
|
|
63943
|
+
file: import_node_path68.default.join(logDir, "clawd.log"),
|
|
63760
63944
|
logClient
|
|
63761
63945
|
});
|
|
63762
63946
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
63763
63947
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
63764
|
-
file:
|
|
63948
|
+
file: import_node_path68.default.join(logDir, "screen-idle-probe.log"),
|
|
63765
63949
|
level: "debug"
|
|
63766
63950
|
});
|
|
63767
63951
|
logger.info("screen-idle probe logger enabled", {
|
|
63768
|
-
file:
|
|
63952
|
+
file: import_node_path68.default.join(logDir, "screen-idle-probe.log")
|
|
63769
63953
|
});
|
|
63770
63954
|
const CAP_TARGETS = [
|
|
63771
|
-
|
|
63772
|
-
|
|
63955
|
+
import_node_path68.default.join(logDir, "clawd.log"),
|
|
63956
|
+
import_node_path68.default.join(logDir, "screen-idle-probe.log")
|
|
63773
63957
|
];
|
|
63774
63958
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
63775
63959
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -63865,8 +64049,8 @@ async function startDaemon(config) {
|
|
|
63865
64049
|
const agents = new AgentsScanner();
|
|
63866
64050
|
const history = new ClaudeHistoryReader();
|
|
63867
64051
|
let transport = null;
|
|
63868
|
-
const personaStore = new PersonaStore(
|
|
63869
|
-
const usersRoot =
|
|
64052
|
+
const personaStore = new PersonaStore(import_node_path68.default.join(config.dataDir, "personas"));
|
|
64053
|
+
const usersRoot = import_node_path68.default.join(config.dataDir, "users");
|
|
63870
64054
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
63871
64055
|
if (defaultsRoot) {
|
|
63872
64056
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -63889,7 +64073,7 @@ async function startDaemon(config) {
|
|
|
63889
64073
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
63890
64074
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
63891
64075
|
const dispatchStore = createDispatchStore({
|
|
63892
|
-
filePath:
|
|
64076
|
+
filePath: import_node_path68.default.join(config.dataDir, "dispatch.json"),
|
|
63893
64077
|
now: () => Date.now(),
|
|
63894
64078
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
63895
64079
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -63904,18 +64088,18 @@ async function startDaemon(config) {
|
|
|
63904
64088
|
now: () => Date.now(),
|
|
63905
64089
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
63906
64090
|
});
|
|
63907
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
64091
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path68.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
63908
64092
|
const mcpConfigs = [];
|
|
63909
64093
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
63910
64094
|
const dispatchServerCandidates = [
|
|
63911
|
-
|
|
64095
|
+
import_node_path68.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
63912
64096
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
63913
|
-
|
|
64097
|
+
import_node_path68.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
63914
64098
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
63915
64099
|
];
|
|
63916
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
64100
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63917
64101
|
if (dispatchServerScriptPath) {
|
|
63918
|
-
const dispatchLogPath =
|
|
64102
|
+
const dispatchLogPath = import_node_path68.default.join(logDir, "dispatch-mcp-server.log");
|
|
63919
64103
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
63920
64104
|
dataDir: config.dataDir,
|
|
63921
64105
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -63935,12 +64119,12 @@ async function startDaemon(config) {
|
|
|
63935
64119
|
});
|
|
63936
64120
|
}
|
|
63937
64121
|
const ticketServerCandidates = [
|
|
63938
|
-
|
|
63939
|
-
|
|
64122
|
+
import_node_path68.default.join(here, "ticket", "mcp-server.cjs"),
|
|
64123
|
+
import_node_path68.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
63940
64124
|
];
|
|
63941
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
64125
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63942
64126
|
if (ticketServerScriptPath) {
|
|
63943
|
-
const ticketLogPath =
|
|
64127
|
+
const ticketLogPath = import_node_path68.default.join(logDir, "ticket-mcp-server.log");
|
|
63944
64128
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
63945
64129
|
dataDir: config.dataDir,
|
|
63946
64130
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -63962,12 +64146,12 @@ async function startDaemon(config) {
|
|
|
63962
64146
|
});
|
|
63963
64147
|
}
|
|
63964
64148
|
const shiftServerCandidates = [
|
|
63965
|
-
|
|
63966
|
-
|
|
64149
|
+
import_node_path68.default.join(here, "shift", "mcp-server.cjs"),
|
|
64150
|
+
import_node_path68.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
63967
64151
|
];
|
|
63968
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
64152
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63969
64153
|
if (shiftServerScriptPath) {
|
|
63970
|
-
const shiftLogPath =
|
|
64154
|
+
const shiftLogPath = import_node_path68.default.join(logDir, "shift-mcp-server.log");
|
|
63971
64155
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
63972
64156
|
dataDir: config.dataDir,
|
|
63973
64157
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -63988,12 +64172,12 @@ async function startDaemon(config) {
|
|
|
63988
64172
|
);
|
|
63989
64173
|
}
|
|
63990
64174
|
const inboxServerCandidates = [
|
|
63991
|
-
|
|
63992
|
-
|
|
64175
|
+
import_node_path68.default.join(here, "inbox", "mcp-server.cjs"),
|
|
64176
|
+
import_node_path68.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
63993
64177
|
];
|
|
63994
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
64178
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63995
64179
|
if (inboxServerScriptPath) {
|
|
63996
|
-
const inboxLogPath =
|
|
64180
|
+
const inboxLogPath = import_node_path68.default.join(logDir, "inbox-mcp-server.log");
|
|
63997
64181
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
63998
64182
|
dataDir: config.dataDir,
|
|
63999
64183
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -64014,10 +64198,10 @@ async function startDaemon(config) {
|
|
|
64014
64198
|
);
|
|
64015
64199
|
}
|
|
64016
64200
|
const peerOpsServerCandidates = [
|
|
64017
|
-
|
|
64018
|
-
|
|
64201
|
+
import_node_path68.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
64202
|
+
import_node_path68.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
64019
64203
|
];
|
|
64020
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
64204
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64021
64205
|
if (peerOpsServerScriptPath) {
|
|
64022
64206
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
64023
64207
|
dataDir: config.dataDir,
|
|
@@ -64037,12 +64221,12 @@ async function startDaemon(config) {
|
|
|
64037
64221
|
);
|
|
64038
64222
|
}
|
|
64039
64223
|
const rpcToolServerCandidates = [
|
|
64040
|
-
|
|
64041
|
-
|
|
64224
|
+
import_node_path68.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
64225
|
+
import_node_path68.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
64042
64226
|
];
|
|
64043
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
64227
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64044
64228
|
if (rpcToolServerScriptPath) {
|
|
64045
|
-
const rpcToolLogPath =
|
|
64229
|
+
const rpcToolLogPath = import_node_path68.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
64046
64230
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
64047
64231
|
dataDir: config.dataDir,
|
|
64048
64232
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -64063,7 +64247,7 @@ async function startDaemon(config) {
|
|
|
64063
64247
|
);
|
|
64064
64248
|
}
|
|
64065
64249
|
const shiftStore = createShiftStore({
|
|
64066
|
-
filePath:
|
|
64250
|
+
filePath: import_node_path68.default.join(config.dataDir, "shift.json"),
|
|
64067
64251
|
ownerIdProvider: () => ownerPrincipalId,
|
|
64068
64252
|
now: () => Date.now()
|
|
64069
64253
|
});
|
|
@@ -64085,7 +64269,7 @@ async function startDaemon(config) {
|
|
|
64085
64269
|
getAdapter,
|
|
64086
64270
|
historyReader: history,
|
|
64087
64271
|
dataDir: config.dataDir,
|
|
64088
|
-
personaRoot:
|
|
64272
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64089
64273
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
64090
64274
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
64091
64275
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -64117,6 +64301,9 @@ async function startDaemon(config) {
|
|
|
64117
64301
|
// daemon 级 MCP server 登记表(dispatch / ticket / shift / inbox / ...,上方各 writer
|
|
64118
64302
|
// 块写盘成功即登记);reducer 透传到 SpawnContext.mcpConfigs,cc spawn 逐项 --mcp-config。
|
|
64119
64303
|
mcpConfigs,
|
|
64304
|
+
// 会话标题自产(首条 send 并行 fire,claude→haiku / codex→gpt-5.4-mini)。
|
|
64305
|
+
// 不注入 = 功能关(manager 测试默认关闭防烧真调用),这里是唯一的生产装配点。
|
|
64306
|
+
generateTitle: (tool, firstMessage) => generateSessionTitle(tool, firstMessage, { logger }),
|
|
64120
64307
|
broadcastFrame: (frame, target) => {
|
|
64121
64308
|
if (target === "all") {
|
|
64122
64309
|
transport?.broadcastAll(frame);
|
|
@@ -64136,10 +64323,10 @@ async function startDaemon(config) {
|
|
|
64136
64323
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
64137
64324
|
attachmentGroup: {
|
|
64138
64325
|
onFileEdit: (input) => {
|
|
64139
|
-
const absPath =
|
|
64326
|
+
const absPath = import_node_path68.default.isAbsolute(input.relPath) ? input.relPath : import_node_path68.default.join(input.cwd, input.relPath);
|
|
64140
64327
|
let size = 0;
|
|
64141
64328
|
try {
|
|
64142
|
-
size =
|
|
64329
|
+
size = import_node_fs52.default.statSync(absPath).size;
|
|
64143
64330
|
} catch (err) {
|
|
64144
64331
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
64145
64332
|
sessionId: input.sessionId,
|
|
@@ -64407,11 +64594,11 @@ async function startDaemon(config) {
|
|
|
64407
64594
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
64408
64595
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
64409
64596
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
64410
|
-
personaRoot:
|
|
64597
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64411
64598
|
usersRoot
|
|
64412
64599
|
},
|
|
64413
64600
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
64414
|
-
personaRoot:
|
|
64601
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64415
64602
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
64416
64603
|
usersRoot,
|
|
64417
64604
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -64537,11 +64724,11 @@ async function startDaemon(config) {
|
|
|
64537
64724
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
64538
64725
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
64539
64726
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
64540
|
-
appBuilderPersonaRoot:
|
|
64727
|
+
appBuilderPersonaRoot: import_node_path68.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
64541
64728
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
64542
|
-
deployKitRoot:
|
|
64729
|
+
deployKitRoot: import_node_path68.default.join(config.dataDir, "deploy-kit"),
|
|
64543
64730
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
64544
|
-
resolvePersonaRoot: (personaId2) =>
|
|
64731
|
+
resolvePersonaRoot: (personaId2) => import_node_path68.default.join(config.dataDir, "personas", personaId2),
|
|
64545
64732
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
64546
64733
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
64547
64734
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -64584,7 +64771,7 @@ async function startDaemon(config) {
|
|
|
64584
64771
|
sourceSessionId: args.sourceSessionId
|
|
64585
64772
|
});
|
|
64586
64773
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
64587
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
64774
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os24.default.homedir());
|
|
64588
64775
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
64589
64776
|
dispatchId: args.dispatchId,
|
|
64590
64777
|
sourceJsonlPath,
|
|
@@ -64646,7 +64833,7 @@ async function startDaemon(config) {
|
|
|
64646
64833
|
});
|
|
64647
64834
|
shiftScheduler.start();
|
|
64648
64835
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
64649
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
64836
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path68.default.join(config.dataDir, "personas"));
|
|
64650
64837
|
const larkBotCloud = createLarkBotCloudClient({
|
|
64651
64838
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
64652
64839
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -64660,7 +64847,7 @@ async function startDaemon(config) {
|
|
|
64660
64847
|
store: larkBotStore,
|
|
64661
64848
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
64662
64849
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
64663
|
-
mediaRootFor: (chatId) =>
|
|
64850
|
+
mediaRootFor: (chatId) => import_node_path68.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
64664
64851
|
isShuttingDown: () => larkDraining,
|
|
64665
64852
|
logger: {
|
|
64666
64853
|
warn: (msg) => logger.warn(msg),
|
|
@@ -64964,8 +65151,8 @@ async function startDaemon(config) {
|
|
|
64964
65151
|
const lines = [
|
|
64965
65152
|
`Tunnel: ${r.url}`,
|
|
64966
65153
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
64967
|
-
`Frpc config: ${
|
|
64968
|
-
`Frpc log: ${
|
|
65154
|
+
`Frpc config: ${import_node_path68.default.join(config.dataDir, "frpc.toml")}`,
|
|
65155
|
+
`Frpc log: ${import_node_path68.default.join(logDir, "frpc.log")}`
|
|
64969
65156
|
];
|
|
64970
65157
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
64971
65158
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -64978,8 +65165,8 @@ ${bar}
|
|
|
64978
65165
|
|
|
64979
65166
|
`);
|
|
64980
65167
|
try {
|
|
64981
|
-
const connectPath =
|
|
64982
|
-
|
|
65168
|
+
const connectPath = import_node_path68.default.join(config.dataDir, "connect.txt");
|
|
65169
|
+
import_node_fs52.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
64983
65170
|
} catch {
|
|
64984
65171
|
}
|
|
64985
65172
|
} catch (err) {
|
|
@@ -65054,9 +65241,9 @@ ${bar}
|
|
|
65054
65241
|
};
|
|
65055
65242
|
}
|
|
65056
65243
|
function migrateDropPersonsDir(dataDir) {
|
|
65057
|
-
const dir =
|
|
65244
|
+
const dir = import_node_path68.default.join(dataDir, "persons");
|
|
65058
65245
|
try {
|
|
65059
|
-
|
|
65246
|
+
import_node_fs52.default.rmSync(dir, { recursive: true, force: true });
|
|
65060
65247
|
} catch {
|
|
65061
65248
|
}
|
|
65062
65249
|
}
|