@clawos-dev/clawd 0.2.351 → 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() {
|
|
@@ -6139,7 +6139,13 @@ var init_feishu_auth = __esm({
|
|
|
6139
6139
|
* 设备属性,与登录态无关、登录登出不变。UI"我的设备标识"用它拼
|
|
6140
6140
|
* clawos://device/<deviceId>(替代旧的 unionId——不再向外暴露人的身份标识)。
|
|
6141
6141
|
*/
|
|
6142
|
-
deviceId: external_exports.string().min(1)
|
|
6142
|
+
deviceId: external_exports.string().min(1),
|
|
6143
|
+
/**
|
|
6144
|
+
* TTC JWT 过期时间(unix ms)。null = 登录回调未携带 expires_at;字段缺省 = 老 daemon。
|
|
6145
|
+
* 仅时间戳——token 本体永不出 ws(spec §9 不变)。UI 据此派生 过期/临期 提示
|
|
6146
|
+
* (见 spec 2026-08-17-ttc-jwt-expiry-ux-design §2)。
|
|
6147
|
+
*/
|
|
6148
|
+
ttcTokenExpiresAt: external_exports.number().nullable().optional()
|
|
6143
6149
|
});
|
|
6144
6150
|
AuthLogoutResponseSchema = external_exports.object({
|
|
6145
6151
|
type: external_exports.literal("auth:logout:ok")
|
|
@@ -7012,6 +7018,10 @@ var init_schemas = __esm({
|
|
|
7012
7018
|
effort: external_exports.string().optional(),
|
|
7013
7019
|
// 归一化运行时观测字段(daemon 独立计算,session:update 不接受;meta_update 事件投递)
|
|
7014
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(),
|
|
7015
7025
|
permissionRules: external_exports.array(AllowRuleSchema).optional(),
|
|
7016
7026
|
// Sidebar 置顶时间戳;null/undefined 表示未置顶
|
|
7017
7027
|
pinnedAt: external_exports.number().int().nonnegative().nullable().optional(),
|
|
@@ -8954,8 +8964,8 @@ var require_req = __commonJS({
|
|
|
8954
8964
|
if (req.originalUrl) {
|
|
8955
8965
|
_req.url = req.originalUrl;
|
|
8956
8966
|
} else {
|
|
8957
|
-
const
|
|
8958
|
-
_req.url = typeof
|
|
8967
|
+
const path82 = req.path;
|
|
8968
|
+
_req.url = typeof path82 === "string" ? path82 : req.url ? req.url.path || req.url : void 0;
|
|
8959
8969
|
}
|
|
8960
8970
|
if (req.query) {
|
|
8961
8971
|
_req.query = req.query;
|
|
@@ -9120,14 +9130,14 @@ var require_redact = __commonJS({
|
|
|
9120
9130
|
}
|
|
9121
9131
|
return obj;
|
|
9122
9132
|
}
|
|
9123
|
-
function parsePath(
|
|
9133
|
+
function parsePath(path82) {
|
|
9124
9134
|
const parts = [];
|
|
9125
9135
|
let current = "";
|
|
9126
9136
|
let inBrackets = false;
|
|
9127
9137
|
let inQuotes = false;
|
|
9128
9138
|
let quoteChar = "";
|
|
9129
|
-
for (let i = 0; i <
|
|
9130
|
-
const char =
|
|
9139
|
+
for (let i = 0; i < path82.length; i++) {
|
|
9140
|
+
const char = path82[i];
|
|
9131
9141
|
if (!inBrackets && char === ".") {
|
|
9132
9142
|
if (current) {
|
|
9133
9143
|
parts.push(current);
|
|
@@ -9258,10 +9268,10 @@ var require_redact = __commonJS({
|
|
|
9258
9268
|
return current;
|
|
9259
9269
|
}
|
|
9260
9270
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9261
|
-
for (const
|
|
9262
|
-
const parts = parsePath(
|
|
9271
|
+
for (const path82 of paths) {
|
|
9272
|
+
const parts = parsePath(path82);
|
|
9263
9273
|
if (parts.includes("*")) {
|
|
9264
|
-
redactWildcardPath(obj, parts, censor,
|
|
9274
|
+
redactWildcardPath(obj, parts, censor, path82, remove);
|
|
9265
9275
|
} else {
|
|
9266
9276
|
if (remove) {
|
|
9267
9277
|
removeKey(obj, parts);
|
|
@@ -9346,8 +9356,8 @@ var require_redact = __commonJS({
|
|
|
9346
9356
|
}
|
|
9347
9357
|
} else {
|
|
9348
9358
|
if (afterWildcard.includes("*")) {
|
|
9349
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9350
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9359
|
+
const wrappedCensor = typeof censor === "function" ? (value, path82) => {
|
|
9360
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path82];
|
|
9351
9361
|
return censor(value, fullPath);
|
|
9352
9362
|
} : censor;
|
|
9353
9363
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9382,8 +9392,8 @@ var require_redact = __commonJS({
|
|
|
9382
9392
|
return null;
|
|
9383
9393
|
}
|
|
9384
9394
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9385
|
-
for (const
|
|
9386
|
-
const parts = parsePath(
|
|
9395
|
+
for (const path82 of pathsToClone) {
|
|
9396
|
+
const parts = parsePath(path82);
|
|
9387
9397
|
let current = pathStructure;
|
|
9388
9398
|
for (let i = 0; i < parts.length; i++) {
|
|
9389
9399
|
const part = parts[i];
|
|
@@ -9435,24 +9445,24 @@ var require_redact = __commonJS({
|
|
|
9435
9445
|
}
|
|
9436
9446
|
return cloneSelectively(obj, pathStructure);
|
|
9437
9447
|
}
|
|
9438
|
-
function validatePath(
|
|
9439
|
-
if (typeof
|
|
9448
|
+
function validatePath(path82) {
|
|
9449
|
+
if (typeof path82 !== "string") {
|
|
9440
9450
|
throw new Error("Paths must be (non-empty) strings");
|
|
9441
9451
|
}
|
|
9442
|
-
if (
|
|
9452
|
+
if (path82 === "") {
|
|
9443
9453
|
throw new Error("Invalid redaction path ()");
|
|
9444
9454
|
}
|
|
9445
|
-
if (
|
|
9446
|
-
throw new Error(`Invalid redaction path (${
|
|
9455
|
+
if (path82.includes("..")) {
|
|
9456
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9447
9457
|
}
|
|
9448
|
-
if (
|
|
9449
|
-
throw new Error(`Invalid redaction path (${
|
|
9458
|
+
if (path82.includes(",")) {
|
|
9459
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9450
9460
|
}
|
|
9451
9461
|
let bracketCount = 0;
|
|
9452
9462
|
let inQuotes = false;
|
|
9453
9463
|
let quoteChar = "";
|
|
9454
|
-
for (let i = 0; i <
|
|
9455
|
-
const char =
|
|
9464
|
+
for (let i = 0; i < path82.length; i++) {
|
|
9465
|
+
const char = path82[i];
|
|
9456
9466
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9457
9467
|
if (!inQuotes) {
|
|
9458
9468
|
inQuotes = true;
|
|
@@ -9466,20 +9476,20 @@ var require_redact = __commonJS({
|
|
|
9466
9476
|
} else if (char === "]" && !inQuotes) {
|
|
9467
9477
|
bracketCount--;
|
|
9468
9478
|
if (bracketCount < 0) {
|
|
9469
|
-
throw new Error(`Invalid redaction path (${
|
|
9479
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9470
9480
|
}
|
|
9471
9481
|
}
|
|
9472
9482
|
}
|
|
9473
9483
|
if (bracketCount !== 0) {
|
|
9474
|
-
throw new Error(`Invalid redaction path (${
|
|
9484
|
+
throw new Error(`Invalid redaction path (${path82})`);
|
|
9475
9485
|
}
|
|
9476
9486
|
}
|
|
9477
9487
|
function validatePaths(paths) {
|
|
9478
9488
|
if (!Array.isArray(paths)) {
|
|
9479
9489
|
throw new TypeError("paths must be an array");
|
|
9480
9490
|
}
|
|
9481
|
-
for (const
|
|
9482
|
-
validatePath(
|
|
9491
|
+
for (const path82 of paths) {
|
|
9492
|
+
validatePath(path82);
|
|
9483
9493
|
}
|
|
9484
9494
|
}
|
|
9485
9495
|
function slowRedact(options = {}) {
|
|
@@ -9647,8 +9657,8 @@ var require_redaction = __commonJS({
|
|
|
9647
9657
|
if (shape[k2] === null) {
|
|
9648
9658
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9649
9659
|
} else {
|
|
9650
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9651
|
-
return censor(value, [k2, ...
|
|
9660
|
+
const wrappedCensor = typeof censor === "function" ? (value, path82) => {
|
|
9661
|
+
return censor(value, [k2, ...path82]);
|
|
9652
9662
|
} : censor;
|
|
9653
9663
|
o[k2] = Redact({
|
|
9654
9664
|
paths: shape[k2],
|
|
@@ -9866,10 +9876,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
9866
9876
|
var require_sonic_boom = __commonJS({
|
|
9867
9877
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
9868
9878
|
"use strict";
|
|
9869
|
-
var
|
|
9879
|
+
var fs73 = require("fs");
|
|
9870
9880
|
var EventEmitter3 = require("events");
|
|
9871
9881
|
var inherits = require("util").inherits;
|
|
9872
|
-
var
|
|
9882
|
+
var path82 = require("path");
|
|
9873
9883
|
var sleep2 = require_atomic_sleep();
|
|
9874
9884
|
var assert = require("assert");
|
|
9875
9885
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -9923,20 +9933,20 @@ var require_sonic_boom = __commonJS({
|
|
|
9923
9933
|
const mode = sonic.mode;
|
|
9924
9934
|
if (sonic.sync) {
|
|
9925
9935
|
try {
|
|
9926
|
-
if (sonic.mkdir)
|
|
9927
|
-
const fd =
|
|
9936
|
+
if (sonic.mkdir) fs73.mkdirSync(path82.dirname(file), { recursive: true });
|
|
9937
|
+
const fd = fs73.openSync(file, flags, mode);
|
|
9928
9938
|
fileOpened(null, fd);
|
|
9929
9939
|
} catch (err) {
|
|
9930
9940
|
fileOpened(err);
|
|
9931
9941
|
throw err;
|
|
9932
9942
|
}
|
|
9933
9943
|
} else if (sonic.mkdir) {
|
|
9934
|
-
|
|
9944
|
+
fs73.mkdir(path82.dirname(file), { recursive: true }, (err) => {
|
|
9935
9945
|
if (err) return fileOpened(err);
|
|
9936
|
-
|
|
9946
|
+
fs73.open(file, flags, mode, fileOpened);
|
|
9937
9947
|
});
|
|
9938
9948
|
} else {
|
|
9939
|
-
|
|
9949
|
+
fs73.open(file, flags, mode, fileOpened);
|
|
9940
9950
|
}
|
|
9941
9951
|
}
|
|
9942
9952
|
function SonicBoom(opts) {
|
|
@@ -9977,8 +9987,8 @@ var require_sonic_boom = __commonJS({
|
|
|
9977
9987
|
this.flush = flushBuffer;
|
|
9978
9988
|
this.flushSync = flushBufferSync;
|
|
9979
9989
|
this._actualWrite = actualWriteBuffer;
|
|
9980
|
-
fsWriteSync = () =>
|
|
9981
|
-
fsWrite = () =>
|
|
9990
|
+
fsWriteSync = () => fs73.writeSync(this.fd, this._writingBuf);
|
|
9991
|
+
fsWrite = () => fs73.write(this.fd, this._writingBuf, this.release);
|
|
9982
9992
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
9983
9993
|
this._writingBuf = "";
|
|
9984
9994
|
this.write = write;
|
|
@@ -9987,15 +9997,15 @@ var require_sonic_boom = __commonJS({
|
|
|
9987
9997
|
this._actualWrite = actualWrite;
|
|
9988
9998
|
fsWriteSync = () => {
|
|
9989
9999
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9990
|
-
return
|
|
10000
|
+
return fs73.writeSync(this.fd, this._writingBuf);
|
|
9991
10001
|
}
|
|
9992
|
-
return
|
|
10002
|
+
return fs73.writeSync(this.fd, this._writingBuf, "utf8");
|
|
9993
10003
|
};
|
|
9994
10004
|
fsWrite = () => {
|
|
9995
10005
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9996
|
-
return
|
|
10006
|
+
return fs73.write(this.fd, this._writingBuf, this.release);
|
|
9997
10007
|
}
|
|
9998
|
-
return
|
|
10008
|
+
return fs73.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
9999
10009
|
};
|
|
10000
10010
|
} else {
|
|
10001
10011
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10052,7 +10062,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10052
10062
|
}
|
|
10053
10063
|
}
|
|
10054
10064
|
if (this._fsync) {
|
|
10055
|
-
|
|
10065
|
+
fs73.fsyncSync(this.fd);
|
|
10056
10066
|
}
|
|
10057
10067
|
const len = this._len;
|
|
10058
10068
|
if (this._reopening) {
|
|
@@ -10166,7 +10176,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10166
10176
|
const onDrain = () => {
|
|
10167
10177
|
if (!this._fsync) {
|
|
10168
10178
|
try {
|
|
10169
|
-
|
|
10179
|
+
fs73.fsync(this.fd, (err) => {
|
|
10170
10180
|
this._flushPending = false;
|
|
10171
10181
|
cb(err);
|
|
10172
10182
|
});
|
|
@@ -10268,7 +10278,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10268
10278
|
const fd = this.fd;
|
|
10269
10279
|
this.once("ready", () => {
|
|
10270
10280
|
if (fd !== this.fd) {
|
|
10271
|
-
|
|
10281
|
+
fs73.close(fd, (err) => {
|
|
10272
10282
|
if (err) {
|
|
10273
10283
|
return this.emit("error", err);
|
|
10274
10284
|
}
|
|
@@ -10317,7 +10327,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10317
10327
|
buf = this._bufs[0];
|
|
10318
10328
|
}
|
|
10319
10329
|
try {
|
|
10320
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10330
|
+
const n = Buffer.isBuffer(buf) ? fs73.writeSync(this.fd, buf) : fs73.writeSync(this.fd, buf, "utf8");
|
|
10321
10331
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10322
10332
|
buf = releasedBufObj.writingBuf;
|
|
10323
10333
|
this._len = releasedBufObj.len;
|
|
@@ -10333,7 +10343,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10333
10343
|
}
|
|
10334
10344
|
}
|
|
10335
10345
|
try {
|
|
10336
|
-
|
|
10346
|
+
fs73.fsyncSync(this.fd);
|
|
10337
10347
|
} catch {
|
|
10338
10348
|
}
|
|
10339
10349
|
}
|
|
@@ -10354,7 +10364,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10354
10364
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10355
10365
|
}
|
|
10356
10366
|
try {
|
|
10357
|
-
const n =
|
|
10367
|
+
const n = fs73.writeSync(this.fd, buf);
|
|
10358
10368
|
buf = buf.subarray(n);
|
|
10359
10369
|
this._len = Math.max(this._len - n, 0);
|
|
10360
10370
|
if (buf.length <= 0) {
|
|
@@ -10382,13 +10392,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10382
10392
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10383
10393
|
if (this.sync) {
|
|
10384
10394
|
try {
|
|
10385
|
-
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");
|
|
10386
10396
|
release(null, written);
|
|
10387
10397
|
} catch (err) {
|
|
10388
10398
|
release(err);
|
|
10389
10399
|
}
|
|
10390
10400
|
} else {
|
|
10391
|
-
|
|
10401
|
+
fs73.write(this.fd, this._writingBuf, release);
|
|
10392
10402
|
}
|
|
10393
10403
|
}
|
|
10394
10404
|
function actualWriteBuffer() {
|
|
@@ -10397,7 +10407,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10397
10407
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10398
10408
|
if (this.sync) {
|
|
10399
10409
|
try {
|
|
10400
|
-
const written =
|
|
10410
|
+
const written = fs73.writeSync(this.fd, this._writingBuf);
|
|
10401
10411
|
release(null, written);
|
|
10402
10412
|
} catch (err) {
|
|
10403
10413
|
release(err);
|
|
@@ -10406,7 +10416,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10406
10416
|
if (kCopyBuffer) {
|
|
10407
10417
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10408
10418
|
}
|
|
10409
|
-
|
|
10419
|
+
fs73.write(this.fd, this._writingBuf, release);
|
|
10410
10420
|
}
|
|
10411
10421
|
}
|
|
10412
10422
|
function actualClose(sonic) {
|
|
@@ -10422,12 +10432,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10422
10432
|
sonic._lens = [];
|
|
10423
10433
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10424
10434
|
try {
|
|
10425
|
-
|
|
10435
|
+
fs73.fsync(sonic.fd, closeWrapped);
|
|
10426
10436
|
} catch {
|
|
10427
10437
|
}
|
|
10428
10438
|
function closeWrapped() {
|
|
10429
10439
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10430
|
-
|
|
10440
|
+
fs73.close(sonic.fd, done);
|
|
10431
10441
|
} else {
|
|
10432
10442
|
done();
|
|
10433
10443
|
}
|
|
@@ -12791,7 +12801,7 @@ var require_multistream = __commonJS({
|
|
|
12791
12801
|
var require_pino = __commonJS({
|
|
12792
12802
|
"../node_modules/.pnpm/pino@9.14.0/node_modules/pino/pino.js"(exports2, module2) {
|
|
12793
12803
|
"use strict";
|
|
12794
|
-
var
|
|
12804
|
+
var os26 = require("os");
|
|
12795
12805
|
var stdSerializers = require_pino_std_serializers();
|
|
12796
12806
|
var caller = require_caller();
|
|
12797
12807
|
var redaction = require_redaction();
|
|
@@ -12838,7 +12848,7 @@ var require_pino = __commonJS({
|
|
|
12838
12848
|
} = symbols;
|
|
12839
12849
|
var { epochTime, nullTime } = time;
|
|
12840
12850
|
var { pid } = process;
|
|
12841
|
-
var hostname =
|
|
12851
|
+
var hostname = os26.hostname();
|
|
12842
12852
|
var defaultErrorSerializer = stdSerializers.err;
|
|
12843
12853
|
var defaultOptions2 = {
|
|
12844
12854
|
level: "info",
|
|
@@ -13562,11 +13572,11 @@ var init_lib = __esm({
|
|
|
13562
13572
|
}
|
|
13563
13573
|
}
|
|
13564
13574
|
},
|
|
13565
|
-
addToPath: function addToPath(
|
|
13566
|
-
var last =
|
|
13575
|
+
addToPath: function addToPath(path82, added, removed, oldPosInc, options) {
|
|
13576
|
+
var last = path82.lastComponent;
|
|
13567
13577
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13568
13578
|
return {
|
|
13569
|
-
oldPos:
|
|
13579
|
+
oldPos: path82.oldPos + oldPosInc,
|
|
13570
13580
|
lastComponent: {
|
|
13571
13581
|
count: last.count + 1,
|
|
13572
13582
|
added,
|
|
@@ -13576,7 +13586,7 @@ var init_lib = __esm({
|
|
|
13576
13586
|
};
|
|
13577
13587
|
} else {
|
|
13578
13588
|
return {
|
|
13579
|
-
oldPos:
|
|
13589
|
+
oldPos: path82.oldPos + oldPosInc,
|
|
13580
13590
|
lastComponent: {
|
|
13581
13591
|
count: 1,
|
|
13582
13592
|
added,
|
|
@@ -14108,10 +14118,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14108
14118
|
const memories = raw.map((m2) => {
|
|
14109
14119
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14110
14120
|
const rec4 = m2;
|
|
14111
|
-
const
|
|
14121
|
+
const path82 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14112
14122
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14113
|
-
if (!
|
|
14114
|
-
const entry = { path:
|
|
14123
|
+
if (!path82 || content == null) return null;
|
|
14124
|
+
const entry = { path: path82, content };
|
|
14115
14125
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14116
14126
|
return entry;
|
|
14117
14127
|
}).filter((m2) => m2 !== null);
|
|
@@ -14945,10 +14955,10 @@ function parseAttachment(obj) {
|
|
|
14945
14955
|
const memories = raw.map((m2) => {
|
|
14946
14956
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14947
14957
|
const rec4 = m2;
|
|
14948
|
-
const
|
|
14958
|
+
const path82 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14949
14959
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14950
|
-
if (!
|
|
14951
|
-
const out = { path:
|
|
14960
|
+
if (!path82 || content == null) return null;
|
|
14961
|
+
const out = { path: path82, content };
|
|
14952
14962
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
14953
14963
|
return out;
|
|
14954
14964
|
}).filter((m2) => m2 !== null);
|
|
@@ -35922,8 +35932,8 @@ var require_utils = __commonJS({
|
|
|
35922
35932
|
var result = transform[inputType][outputType](input);
|
|
35923
35933
|
return result;
|
|
35924
35934
|
};
|
|
35925
|
-
exports2.resolve = function(
|
|
35926
|
-
var parts =
|
|
35935
|
+
exports2.resolve = function(path82) {
|
|
35936
|
+
var parts = path82.split("/");
|
|
35927
35937
|
var result = [];
|
|
35928
35938
|
for (var index = 0; index < parts.length; index++) {
|
|
35929
35939
|
var part = parts[index];
|
|
@@ -41776,18 +41786,18 @@ var require_object = __commonJS({
|
|
|
41776
41786
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
41777
41787
|
this.files[name] = object;
|
|
41778
41788
|
};
|
|
41779
|
-
var parentFolder = function(
|
|
41780
|
-
if (
|
|
41781
|
-
|
|
41789
|
+
var parentFolder = function(path82) {
|
|
41790
|
+
if (path82.slice(-1) === "/") {
|
|
41791
|
+
path82 = path82.substring(0, path82.length - 1);
|
|
41782
41792
|
}
|
|
41783
|
-
var lastSlash =
|
|
41784
|
-
return lastSlash > 0 ?
|
|
41793
|
+
var lastSlash = path82.lastIndexOf("/");
|
|
41794
|
+
return lastSlash > 0 ? path82.substring(0, lastSlash) : "";
|
|
41785
41795
|
};
|
|
41786
|
-
var forceTrailingSlash = function(
|
|
41787
|
-
if (
|
|
41788
|
-
|
|
41796
|
+
var forceTrailingSlash = function(path82) {
|
|
41797
|
+
if (path82.slice(-1) !== "/") {
|
|
41798
|
+
path82 += "/";
|
|
41789
41799
|
}
|
|
41790
|
-
return
|
|
41800
|
+
return path82;
|
|
41791
41801
|
};
|
|
41792
41802
|
var folderAdd = function(name, createFolders) {
|
|
41793
41803
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -42789,7 +42799,7 @@ var require_lib3 = __commonJS({
|
|
|
42789
42799
|
// src/run-case/recorder.ts
|
|
42790
42800
|
function startRunCaseRecorder(opts) {
|
|
42791
42801
|
const now = opts.now ?? Date.now;
|
|
42792
|
-
const dir =
|
|
42802
|
+
const dir = import_node_path69.default.dirname(opts.recordPath);
|
|
42793
42803
|
let stream = null;
|
|
42794
42804
|
let closing = false;
|
|
42795
42805
|
let closedSettled = false;
|
|
@@ -42803,8 +42813,8 @@ function startRunCaseRecorder(opts) {
|
|
|
42803
42813
|
});
|
|
42804
42814
|
const ensureStream = () => {
|
|
42805
42815
|
if (stream) return stream;
|
|
42806
|
-
|
|
42807
|
-
stream =
|
|
42816
|
+
import_node_fs53.default.mkdirSync(dir, { recursive: true });
|
|
42817
|
+
stream = import_node_fs53.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
42808
42818
|
stream.on("close", () => closedResolve());
|
|
42809
42819
|
return stream;
|
|
42810
42820
|
};
|
|
@@ -42829,12 +42839,12 @@ function startRunCaseRecorder(opts) {
|
|
|
42829
42839
|
};
|
|
42830
42840
|
return { tap, close, closed };
|
|
42831
42841
|
}
|
|
42832
|
-
var
|
|
42842
|
+
var import_node_fs53, import_node_path69;
|
|
42833
42843
|
var init_recorder = __esm({
|
|
42834
42844
|
"src/run-case/recorder.ts"() {
|
|
42835
42845
|
"use strict";
|
|
42836
|
-
|
|
42837
|
-
|
|
42846
|
+
import_node_fs53 = __toESM(require("fs"), 1);
|
|
42847
|
+
import_node_path69 = __toESM(require("path"), 1);
|
|
42838
42848
|
}
|
|
42839
42849
|
});
|
|
42840
42850
|
|
|
@@ -42877,7 +42887,7 @@ var init_wire = __esm({
|
|
|
42877
42887
|
// src/run-case/controller.ts
|
|
42878
42888
|
async function runController(opts) {
|
|
42879
42889
|
const now = opts.now ?? Date.now;
|
|
42880
|
-
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-"));
|
|
42881
42891
|
const ownsCwd = opts.cwd === void 0;
|
|
42882
42892
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
42883
42893
|
const spawnCtx = { cwd };
|
|
@@ -43038,19 +43048,19 @@ async function runController(opts) {
|
|
|
43038
43048
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
43039
43049
|
if (ownsCwd) {
|
|
43040
43050
|
try {
|
|
43041
|
-
(0,
|
|
43051
|
+
(0, import_node_fs54.rmSync)(cwd, { recursive: true, force: true });
|
|
43042
43052
|
} catch {
|
|
43043
43053
|
}
|
|
43044
43054
|
}
|
|
43045
43055
|
return exitCode ?? 0;
|
|
43046
43056
|
}
|
|
43047
|
-
var
|
|
43057
|
+
var import_node_fs54, import_node_os25, import_node_path70;
|
|
43048
43058
|
var init_controller = __esm({
|
|
43049
43059
|
"src/run-case/controller.ts"() {
|
|
43050
43060
|
"use strict";
|
|
43051
|
-
|
|
43052
|
-
|
|
43053
|
-
|
|
43061
|
+
import_node_fs54 = require("fs");
|
|
43062
|
+
import_node_os25 = __toESM(require("os"), 1);
|
|
43063
|
+
import_node_path70 = __toESM(require("path"), 1);
|
|
43054
43064
|
init_claude();
|
|
43055
43065
|
init_stdout_splitter();
|
|
43056
43066
|
init_permission_stdio();
|
|
@@ -43325,9 +43335,9 @@ Env (advanced):
|
|
|
43325
43335
|
`;
|
|
43326
43336
|
|
|
43327
43337
|
// src/index.ts
|
|
43328
|
-
var
|
|
43329
|
-
var
|
|
43330
|
-
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);
|
|
43331
43341
|
|
|
43332
43342
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
43333
43343
|
var byteToHex = [];
|
|
@@ -44613,9 +44623,13 @@ function applyMetaUpdate(state, patch, deps) {
|
|
|
44613
44623
|
const w2 = deps.resolveContextWindow?.(next.file.tool, patch.resolvedModel);
|
|
44614
44624
|
if (w2 !== void 0) merged.contextWindowSize = w2;
|
|
44615
44625
|
}
|
|
44616
|
-
|
|
44626
|
+
const aiLabelArrived = patch.aiLabel !== void 0 && (patch.aiLabel !== next.file.aiLabel || !next.file.aiLabelGeneratedAt);
|
|
44627
|
+
if (shallowEqMeta(next.file, merged) && !aiLabelArrived) {
|
|
44617
44628
|
return { state: next, effects: [] };
|
|
44618
44629
|
}
|
|
44630
|
+
if (aiLabelArrived) {
|
|
44631
|
+
merged.aiLabelGeneratedAt = nowIso(deps);
|
|
44632
|
+
}
|
|
44619
44633
|
next.file = merged;
|
|
44620
44634
|
return {
|
|
44621
44635
|
state: next,
|
|
@@ -45944,6 +45958,8 @@ var SessionManager = class {
|
|
|
45944
45958
|
deps;
|
|
45945
45959
|
// sessionId → SessionRunner;在 send / ensureSession 时按需创建
|
|
45946
45960
|
runners = /* @__PURE__ */ new Map();
|
|
45961
|
+
// 标题生成 in-flight 防重(进程内);跨重启防重靠 SessionFile.aiLabelGeneratedAt
|
|
45962
|
+
titleGenPending = /* @__PURE__ */ new Set();
|
|
45947
45963
|
// 当同步命令执行期间,runner 的 emit-frame 临时 push 到这里;
|
|
45948
45964
|
// null 表示当前是异步路径(stdout 'data' / proc 'exit' 等),走 deps.broadcastFrame
|
|
45949
45965
|
currentCollector = null;
|
|
@@ -46769,8 +46785,38 @@ var SessionManager = class {
|
|
|
46769
46785
|
command: { kind: "send", text: args.text, senderPrincipal }
|
|
46770
46786
|
});
|
|
46771
46787
|
});
|
|
46788
|
+
this.maybeGenerateTitle(existing, args.text);
|
|
46772
46789
|
return { response: { ok: true }, broadcast };
|
|
46773
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
|
+
}
|
|
46774
46820
|
/**
|
|
46775
46821
|
* Dispatch 结果投递(spec 2026-07-20 §5):查台账里该 source session 名下已完成
|
|
46776
46822
|
* 且未投递的行,合并成一段 plain text 结果包注入回 source session。
|
|
@@ -49765,8 +49811,8 @@ function turnStartInput(text) {
|
|
|
49765
49811
|
const items = [];
|
|
49766
49812
|
let leftover = text;
|
|
49767
49813
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
49768
|
-
const [marker, name,
|
|
49769
|
-
items.push({ type: "skill", name, path:
|
|
49814
|
+
const [marker, name, path82] = m2;
|
|
49815
|
+
items.push({ type: "skill", name, path: path82 });
|
|
49770
49816
|
leftover = leftover.replace(marker, "");
|
|
49771
49817
|
}
|
|
49772
49818
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -53722,13 +53768,13 @@ function mapSkillsListResponse(res) {
|
|
|
53722
53768
|
const r = s ?? {};
|
|
53723
53769
|
const name = str3(r.name);
|
|
53724
53770
|
if (!name) continue;
|
|
53725
|
-
const
|
|
53771
|
+
const path82 = str3(r.path);
|
|
53726
53772
|
const description = str3(r.description);
|
|
53727
53773
|
const isPlugin = name.includes(":");
|
|
53728
53774
|
out.push({
|
|
53729
53775
|
name,
|
|
53730
53776
|
source: isPlugin ? "plugin" : "project",
|
|
53731
|
-
...
|
|
53777
|
+
...path82 ? { path: path82 } : {},
|
|
53732
53778
|
...description ? { description } : {},
|
|
53733
53779
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
53734
53780
|
});
|
|
@@ -54496,6 +54542,149 @@ function listRegistered() {
|
|
|
54496
54542
|
return [...registry.keys()];
|
|
54497
54543
|
}
|
|
54498
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
|
+
|
|
54499
54688
|
// ../node_modules/.pnpm/ws@8.20.0/node_modules/ws/wrapper.mjs
|
|
54500
54689
|
var import_stream = __toESM(require_stream(), 1);
|
|
54501
54690
|
var import_extension2 = __toESM(require_extension(), 1);
|
|
@@ -55172,8 +55361,8 @@ async function authenticate(token, deps) {
|
|
|
55172
55361
|
}
|
|
55173
55362
|
|
|
55174
55363
|
// src/legacy-cleanup.ts
|
|
55175
|
-
var
|
|
55176
|
-
var
|
|
55364
|
+
var fs38 = __toESM(require("fs/promises"), 1);
|
|
55365
|
+
var path39 = __toESM(require("path"), 1);
|
|
55177
55366
|
var LEGACY_FILES = [
|
|
55178
55367
|
"personal-capability.json",
|
|
55179
55368
|
"received-capabilities.json",
|
|
@@ -55182,9 +55371,9 @@ var LEGACY_FILES = [
|
|
|
55182
55371
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
55183
55372
|
const removed = [];
|
|
55184
55373
|
for (const name of LEGACY_FILES) {
|
|
55185
|
-
const p2 =
|
|
55374
|
+
const p2 = path39.join(dataDir, name);
|
|
55186
55375
|
try {
|
|
55187
|
-
await
|
|
55376
|
+
await fs38.unlink(p2);
|
|
55188
55377
|
removed.push(name);
|
|
55189
55378
|
logger.debug("legacy capability file removed", { file: name });
|
|
55190
55379
|
} catch (err) {
|
|
@@ -55196,13 +55385,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
55196
55385
|
}
|
|
55197
55386
|
|
|
55198
55387
|
// src/inbox/inbox-store.ts
|
|
55199
|
-
var
|
|
55200
|
-
var
|
|
55388
|
+
var fs39 = __toESM(require("fs"), 1);
|
|
55389
|
+
var path40 = __toESM(require("path"), 1);
|
|
55201
55390
|
var INBOX_SUBDIR = "inbox";
|
|
55202
55391
|
var InboxStore = class {
|
|
55203
55392
|
constructor(dataDir) {
|
|
55204
55393
|
this.dataDir = dataDir;
|
|
55205
|
-
|
|
55394
|
+
fs39.mkdirSync(this.dirPath(), { recursive: true });
|
|
55206
55395
|
}
|
|
55207
55396
|
dataDir;
|
|
55208
55397
|
/**
|
|
@@ -55214,7 +55403,7 @@ var InboxStore = class {
|
|
|
55214
55403
|
const file = this.filePath(peerDeviceId);
|
|
55215
55404
|
let raw;
|
|
55216
55405
|
try {
|
|
55217
|
-
raw =
|
|
55406
|
+
raw = fs39.readFileSync(file, "utf8");
|
|
55218
55407
|
} catch (err) {
|
|
55219
55408
|
if (err?.code === "ENOENT") return [];
|
|
55220
55409
|
return [];
|
|
@@ -55230,7 +55419,7 @@ var InboxStore = class {
|
|
|
55230
55419
|
const dir = this.dirPath();
|
|
55231
55420
|
let entries;
|
|
55232
55421
|
try {
|
|
55233
|
-
entries =
|
|
55422
|
+
entries = fs39.readdirSync(dir);
|
|
55234
55423
|
} catch (err) {
|
|
55235
55424
|
if (err?.code === "ENOENT") return [];
|
|
55236
55425
|
return [];
|
|
@@ -55246,9 +55435,9 @@ var InboxStore = class {
|
|
|
55246
55435
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
55247
55436
|
const file = this.filePath(message.peerDeviceId);
|
|
55248
55437
|
const line = JSON.stringify(message) + "\n";
|
|
55249
|
-
|
|
55438
|
+
fs39.appendFileSync(file, line, { mode: 384 });
|
|
55250
55439
|
try {
|
|
55251
|
-
|
|
55440
|
+
fs39.chmodSync(file, 384);
|
|
55252
55441
|
} catch {
|
|
55253
55442
|
}
|
|
55254
55443
|
}
|
|
@@ -55278,7 +55467,7 @@ var InboxStore = class {
|
|
|
55278
55467
|
removeByPeerDeviceId(peerDeviceId) {
|
|
55279
55468
|
const file = this.filePath(peerDeviceId);
|
|
55280
55469
|
try {
|
|
55281
|
-
|
|
55470
|
+
fs39.unlinkSync(file);
|
|
55282
55471
|
} catch (err) {
|
|
55283
55472
|
if (err?.code === "ENOENT") return;
|
|
55284
55473
|
}
|
|
@@ -55287,18 +55476,18 @@ var InboxStore = class {
|
|
|
55287
55476
|
const file = this.filePath(peerDeviceId);
|
|
55288
55477
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
55289
55478
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
55290
|
-
|
|
55291
|
-
|
|
55479
|
+
fs39.writeFileSync(tmp, content, { mode: 384 });
|
|
55480
|
+
fs39.renameSync(tmp, file);
|
|
55292
55481
|
try {
|
|
55293
|
-
|
|
55482
|
+
fs39.chmodSync(file, 384);
|
|
55294
55483
|
} catch {
|
|
55295
55484
|
}
|
|
55296
55485
|
}
|
|
55297
55486
|
dirPath() {
|
|
55298
|
-
return
|
|
55487
|
+
return path40.join(this.dataDir, INBOX_SUBDIR);
|
|
55299
55488
|
}
|
|
55300
55489
|
filePath(peerDeviceId) {
|
|
55301
|
-
return
|
|
55490
|
+
return path40.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
55302
55491
|
}
|
|
55303
55492
|
};
|
|
55304
55493
|
function parseAllLines(raw) {
|
|
@@ -55386,8 +55575,8 @@ var InboxManager = class {
|
|
|
55386
55575
|
};
|
|
55387
55576
|
|
|
55388
55577
|
// src/state/contact-store.ts
|
|
55389
|
-
var
|
|
55390
|
-
var
|
|
55578
|
+
var fs40 = __toESM(require("fs"), 1);
|
|
55579
|
+
var path41 = __toESM(require("path"), 1);
|
|
55391
55580
|
var FILE_NAME = "contacts.json";
|
|
55392
55581
|
var ContactStore = class {
|
|
55393
55582
|
constructor(dataDir) {
|
|
@@ -55397,10 +55586,10 @@ var ContactStore = class {
|
|
|
55397
55586
|
contacts = /* @__PURE__ */ new Map();
|
|
55398
55587
|
load() {
|
|
55399
55588
|
this.contacts.clear();
|
|
55400
|
-
const file =
|
|
55589
|
+
const file = path41.join(this.dataDir, FILE_NAME);
|
|
55401
55590
|
let raw;
|
|
55402
55591
|
try {
|
|
55403
|
-
raw =
|
|
55592
|
+
raw = fs40.readFileSync(file, "utf8");
|
|
55404
55593
|
} catch (err) {
|
|
55405
55594
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
55406
55595
|
return;
|
|
@@ -55469,20 +55658,20 @@ var ContactStore = class {
|
|
|
55469
55658
|
return true;
|
|
55470
55659
|
}
|
|
55471
55660
|
flush() {
|
|
55472
|
-
const file =
|
|
55661
|
+
const file = path41.join(this.dataDir, FILE_NAME);
|
|
55473
55662
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
55474
55663
|
const content = JSON.stringify(
|
|
55475
55664
|
{ contacts: Array.from(this.contacts.values()) },
|
|
55476
55665
|
null,
|
|
55477
55666
|
2
|
|
55478
55667
|
);
|
|
55479
|
-
|
|
55480
|
-
|
|
55481
|
-
|
|
55668
|
+
fs40.mkdirSync(this.dataDir, { recursive: true });
|
|
55669
|
+
fs40.writeFileSync(tmp, content, { mode: 384 });
|
|
55670
|
+
fs40.renameSync(tmp, file);
|
|
55482
55671
|
}
|
|
55483
55672
|
renameBak(file) {
|
|
55484
55673
|
try {
|
|
55485
|
-
|
|
55674
|
+
fs40.renameSync(file, `${file}.bak`);
|
|
55486
55675
|
} catch {
|
|
55487
55676
|
}
|
|
55488
55677
|
}
|
|
@@ -55590,61 +55779,61 @@ async function connectRemote(args) {
|
|
|
55590
55779
|
}
|
|
55591
55780
|
|
|
55592
55781
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
55593
|
-
var
|
|
55594
|
-
var
|
|
55782
|
+
var fs41 = __toESM(require("fs"), 1);
|
|
55783
|
+
var path42 = __toESM(require("path"), 1);
|
|
55595
55784
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
55596
55785
|
function migrateFlattenSessions(opts) {
|
|
55597
55786
|
const dataDir = opts.dataDir;
|
|
55598
55787
|
const now = opts.now ?? Date.now;
|
|
55599
|
-
const sessionsDir =
|
|
55600
|
-
const flagPath =
|
|
55788
|
+
const sessionsDir = path42.join(dataDir, "sessions");
|
|
55789
|
+
const flagPath = path42.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
55601
55790
|
if (existsSync3(flagPath)) {
|
|
55602
55791
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
55603
55792
|
}
|
|
55604
55793
|
let movedBare = 0;
|
|
55605
55794
|
let movedVmOwner = 0;
|
|
55606
55795
|
let archivedListener = 0;
|
|
55607
|
-
const defaultDir =
|
|
55796
|
+
const defaultDir = path42.join(sessionsDir, "default");
|
|
55608
55797
|
if (existsSync3(defaultDir)) {
|
|
55609
55798
|
for (const entry of readdirSafe(defaultDir)) {
|
|
55610
55799
|
if (!entry.endsWith(".json")) continue;
|
|
55611
|
-
const src =
|
|
55612
|
-
const dst =
|
|
55613
|
-
|
|
55800
|
+
const src = path42.join(defaultDir, entry);
|
|
55801
|
+
const dst = path42.join(sessionsDir, entry);
|
|
55802
|
+
fs41.renameSync(src, dst);
|
|
55614
55803
|
movedBare += 1;
|
|
55615
55804
|
}
|
|
55616
55805
|
rmdirIfEmpty(defaultDir);
|
|
55617
55806
|
}
|
|
55618
55807
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
55619
|
-
const personaDir =
|
|
55808
|
+
const personaDir = path42.join(sessionsDir, pid);
|
|
55620
55809
|
if (!isDir(personaDir)) continue;
|
|
55621
55810
|
if (pid === "default") continue;
|
|
55622
|
-
const ownerSrc =
|
|
55811
|
+
const ownerSrc = path42.join(personaDir, "owner");
|
|
55623
55812
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
55624
|
-
const ownerDst =
|
|
55625
|
-
|
|
55813
|
+
const ownerDst = path42.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
55814
|
+
fs41.mkdirSync(ownerDst, { recursive: true });
|
|
55626
55815
|
for (const file of readdirSafe(ownerSrc)) {
|
|
55627
55816
|
if (!file.endsWith(".json")) continue;
|
|
55628
|
-
|
|
55817
|
+
fs41.renameSync(path42.join(ownerSrc, file), path42.join(ownerDst, file));
|
|
55629
55818
|
movedVmOwner += 1;
|
|
55630
55819
|
}
|
|
55631
55820
|
rmdirIfEmpty(ownerSrc);
|
|
55632
55821
|
}
|
|
55633
|
-
const listenerSrc =
|
|
55822
|
+
const listenerSrc = path42.join(personaDir, "listener");
|
|
55634
55823
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
55635
|
-
const archiveDst =
|
|
55636
|
-
|
|
55824
|
+
const archiveDst = path42.join(dataDir, ".legacy", `listener-${pid}`);
|
|
55825
|
+
fs41.mkdirSync(archiveDst, { recursive: true });
|
|
55637
55826
|
for (const file of readdirSafe(listenerSrc)) {
|
|
55638
55827
|
if (!file.endsWith(".json")) continue;
|
|
55639
|
-
|
|
55828
|
+
fs41.renameSync(path42.join(listenerSrc, file), path42.join(archiveDst, file));
|
|
55640
55829
|
archivedListener += 1;
|
|
55641
55830
|
}
|
|
55642
55831
|
rmdirIfEmpty(listenerSrc);
|
|
55643
55832
|
}
|
|
55644
55833
|
rmdirIfEmpty(personaDir);
|
|
55645
55834
|
}
|
|
55646
|
-
|
|
55647
|
-
|
|
55835
|
+
fs41.mkdirSync(sessionsDir, { recursive: true });
|
|
55836
|
+
fs41.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
55648
55837
|
return {
|
|
55649
55838
|
skipped: false,
|
|
55650
55839
|
flagWritten: true,
|
|
@@ -55655,7 +55844,7 @@ function migrateFlattenSessions(opts) {
|
|
|
55655
55844
|
}
|
|
55656
55845
|
function existsSync3(p2) {
|
|
55657
55846
|
try {
|
|
55658
|
-
|
|
55847
|
+
fs41.statSync(p2);
|
|
55659
55848
|
return true;
|
|
55660
55849
|
} catch {
|
|
55661
55850
|
return false;
|
|
@@ -55663,31 +55852,31 @@ function existsSync3(p2) {
|
|
|
55663
55852
|
}
|
|
55664
55853
|
function isDir(p2) {
|
|
55665
55854
|
try {
|
|
55666
|
-
return
|
|
55855
|
+
return fs41.statSync(p2).isDirectory();
|
|
55667
55856
|
} catch {
|
|
55668
55857
|
return false;
|
|
55669
55858
|
}
|
|
55670
55859
|
}
|
|
55671
55860
|
function readdirSafe(p2) {
|
|
55672
55861
|
try {
|
|
55673
|
-
return
|
|
55862
|
+
return fs41.readdirSync(p2);
|
|
55674
55863
|
} catch {
|
|
55675
55864
|
return [];
|
|
55676
55865
|
}
|
|
55677
55866
|
}
|
|
55678
55867
|
function rmdirIfEmpty(p2) {
|
|
55679
55868
|
try {
|
|
55680
|
-
|
|
55869
|
+
fs41.rmdirSync(p2);
|
|
55681
55870
|
} catch {
|
|
55682
55871
|
}
|
|
55683
55872
|
}
|
|
55684
55873
|
|
|
55685
55874
|
// src/transport/http-router.ts
|
|
55686
|
-
var
|
|
55687
|
-
var
|
|
55875
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
55876
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
55688
55877
|
|
|
55689
55878
|
// src/attachment/mime.ts
|
|
55690
|
-
var
|
|
55879
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55691
55880
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
55692
55881
|
var EXT_TO_NATIVE_MIME = {
|
|
55693
55882
|
// 图片
|
|
@@ -55794,7 +55983,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
55794
55983
|
".mk"
|
|
55795
55984
|
]);
|
|
55796
55985
|
function lookupMime(filePathOrName) {
|
|
55797
|
-
const ext =
|
|
55986
|
+
const ext = import_node_path35.default.extname(filePathOrName).toLowerCase();
|
|
55798
55987
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
55799
55988
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
55800
55989
|
return "application/octet-stream";
|
|
@@ -55864,8 +56053,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
55864
56053
|
}
|
|
55865
56054
|
|
|
55866
56055
|
// src/attachment/upload.ts
|
|
55867
|
-
var
|
|
55868
|
-
var
|
|
56056
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
56057
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
55869
56058
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
55870
56059
|
var import_promises4 = require("stream/promises");
|
|
55871
56060
|
var UploadError = class extends Error {
|
|
@@ -55877,22 +56066,22 @@ var UploadError = class extends Error {
|
|
|
55877
56066
|
code;
|
|
55878
56067
|
};
|
|
55879
56068
|
function assertValidFileName(fileName) {
|
|
55880
|
-
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)) {
|
|
55881
56070
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
55882
56071
|
}
|
|
55883
56072
|
}
|
|
55884
56073
|
var HASH_PREFIX_LEN = 16;
|
|
55885
56074
|
async function writeUploadedAttachment(args) {
|
|
55886
56075
|
assertValidFileName(args.fileName);
|
|
55887
|
-
const attachmentsRoot =
|
|
56076
|
+
const attachmentsRoot = import_node_path36.default.join(args.baseDir, ".attachments");
|
|
55888
56077
|
try {
|
|
55889
|
-
|
|
56078
|
+
import_node_fs33.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
55890
56079
|
} catch (err) {
|
|
55891
56080
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
55892
56081
|
}
|
|
55893
56082
|
const hasher = import_node_crypto9.default.createHash("sha256");
|
|
55894
56083
|
let actualSize = 0;
|
|
55895
|
-
const tmpPath =
|
|
56084
|
+
const tmpPath = import_node_path36.default.join(
|
|
55896
56085
|
attachmentsRoot,
|
|
55897
56086
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
|
|
55898
56087
|
);
|
|
@@ -55907,18 +56096,18 @@ async function writeUploadedAttachment(args) {
|
|
|
55907
56096
|
yield buf;
|
|
55908
56097
|
}
|
|
55909
56098
|
},
|
|
55910
|
-
|
|
56099
|
+
import_node_fs33.default.createWriteStream(tmpPath, { mode: 384 })
|
|
55911
56100
|
);
|
|
55912
56101
|
} catch (err) {
|
|
55913
56102
|
try {
|
|
55914
|
-
|
|
56103
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55915
56104
|
} catch {
|
|
55916
56105
|
}
|
|
55917
56106
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
55918
56107
|
}
|
|
55919
56108
|
if (actualSize !== args.contentLength) {
|
|
55920
56109
|
try {
|
|
55921
|
-
|
|
56110
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55922
56111
|
} catch {
|
|
55923
56112
|
}
|
|
55924
56113
|
throw new UploadError(
|
|
@@ -55927,34 +56116,34 @@ async function writeUploadedAttachment(args) {
|
|
|
55927
56116
|
);
|
|
55928
56117
|
}
|
|
55929
56118
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
55930
|
-
const hashDir =
|
|
56119
|
+
const hashDir = import_node_path36.default.join(attachmentsRoot, attachmentId);
|
|
55931
56120
|
let finalFileName;
|
|
55932
56121
|
let hashDirExists = false;
|
|
55933
56122
|
try {
|
|
55934
|
-
hashDirExists =
|
|
56123
|
+
hashDirExists = import_node_fs33.default.statSync(hashDir).isDirectory();
|
|
55935
56124
|
} catch {
|
|
55936
56125
|
}
|
|
55937
56126
|
if (hashDirExists) {
|
|
55938
|
-
const existing =
|
|
56127
|
+
const existing = import_node_fs33.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
55939
56128
|
finalFileName = existing[0] ?? args.fileName;
|
|
55940
56129
|
try {
|
|
55941
|
-
|
|
56130
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55942
56131
|
} catch {
|
|
55943
56132
|
}
|
|
55944
56133
|
} else {
|
|
55945
56134
|
try {
|
|
55946
|
-
|
|
56135
|
+
import_node_fs33.default.mkdirSync(hashDir, { recursive: true });
|
|
55947
56136
|
finalFileName = args.fileName;
|
|
55948
|
-
|
|
56137
|
+
import_node_fs33.default.renameSync(tmpPath, import_node_path36.default.join(hashDir, finalFileName));
|
|
55949
56138
|
} catch (err) {
|
|
55950
56139
|
try {
|
|
55951
|
-
|
|
56140
|
+
import_node_fs33.default.unlinkSync(tmpPath);
|
|
55952
56141
|
} catch {
|
|
55953
56142
|
}
|
|
55954
56143
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
55955
56144
|
}
|
|
55956
56145
|
}
|
|
55957
|
-
const absPath =
|
|
56146
|
+
const absPath = import_node_path36.default.join(hashDir, finalFileName);
|
|
55958
56147
|
const relPath = absPath;
|
|
55959
56148
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
55960
56149
|
relPath: absPath,
|
|
@@ -55969,8 +56158,8 @@ async function writeUploadedAttachment(args) {
|
|
|
55969
56158
|
|
|
55970
56159
|
// src/extension/import.ts
|
|
55971
56160
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
55972
|
-
var
|
|
55973
|
-
var
|
|
56161
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
56162
|
+
var import_node_os13 = __toESM(require("os"), 1);
|
|
55974
56163
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
55975
56164
|
var ImportError = class extends Error {
|
|
55976
56165
|
constructor(code, message) {
|
|
@@ -55987,7 +56176,7 @@ async function importZip(buf, root) {
|
|
|
55987
56176
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
55988
56177
|
}
|
|
55989
56178
|
for (const name of Object.keys(zip.files)) {
|
|
55990
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
56179
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
|
|
55991
56180
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
55992
56181
|
}
|
|
55993
56182
|
}
|
|
@@ -56020,7 +56209,7 @@ async function importZip(buf, root) {
|
|
|
56020
56209
|
);
|
|
56021
56210
|
}
|
|
56022
56211
|
}
|
|
56023
|
-
const destDir =
|
|
56212
|
+
const destDir = import_node_path37.default.join(root, manifest.id);
|
|
56024
56213
|
let destExists = false;
|
|
56025
56214
|
try {
|
|
56026
56215
|
await import_promises5.default.access(destDir);
|
|
@@ -56030,15 +56219,15 @@ async function importZip(buf, root) {
|
|
|
56030
56219
|
if (destExists) {
|
|
56031
56220
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
56032
56221
|
}
|
|
56033
|
-
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}-`));
|
|
56034
56223
|
try {
|
|
56035
56224
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56036
|
-
const dest =
|
|
56225
|
+
const dest = import_node_path37.default.join(stage, name);
|
|
56037
56226
|
if (entry.dir) {
|
|
56038
56227
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
56039
56228
|
continue;
|
|
56040
56229
|
}
|
|
56041
|
-
await import_promises5.default.mkdir(
|
|
56230
|
+
await import_promises5.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
|
|
56042
56231
|
const content = await entry.async("nodebuffer");
|
|
56043
56232
|
await import_promises5.default.writeFile(dest, content);
|
|
56044
56233
|
}
|
|
@@ -56068,7 +56257,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
56068
56257
|
".wasm": "application/wasm"
|
|
56069
56258
|
};
|
|
56070
56259
|
function shareUiAssetMime(filePath) {
|
|
56071
|
-
const ext =
|
|
56260
|
+
const ext = import_node_path38.default.extname(filePath).toLowerCase();
|
|
56072
56261
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
56073
56262
|
}
|
|
56074
56263
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -56167,7 +56356,7 @@ function isValidUploadFileName(fileName) {
|
|
|
56167
56356
|
if (fileName === "." || fileName === "..") return false;
|
|
56168
56357
|
if (fileName.startsWith(".")) return false;
|
|
56169
56358
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
56170
|
-
return fileName ===
|
|
56359
|
+
return fileName === import_node_path38.default.basename(fileName);
|
|
56171
56360
|
}
|
|
56172
56361
|
function createHttpRouter(deps) {
|
|
56173
56362
|
return async (req, res) => {
|
|
@@ -56255,7 +56444,7 @@ function createHttpRouter(deps) {
|
|
|
56255
56444
|
}
|
|
56256
56445
|
let buf;
|
|
56257
56446
|
try {
|
|
56258
|
-
buf = await
|
|
56447
|
+
buf = await import_node_fs34.default.promises.readFile(abs);
|
|
56259
56448
|
} catch {
|
|
56260
56449
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
56261
56450
|
return true;
|
|
@@ -56403,7 +56592,7 @@ function createHttpRouter(deps) {
|
|
|
56403
56592
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
56404
56593
|
return true;
|
|
56405
56594
|
}
|
|
56406
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
56595
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path38.default.basename(r.absPath)));
|
|
56407
56596
|
return true;
|
|
56408
56597
|
}
|
|
56409
56598
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -56524,7 +56713,7 @@ function createHttpRouter(deps) {
|
|
|
56524
56713
|
return true;
|
|
56525
56714
|
}
|
|
56526
56715
|
let absPath;
|
|
56527
|
-
if (
|
|
56716
|
+
if (import_node_path38.default.isAbsolute(pathParam)) {
|
|
56528
56717
|
absPath = pathParam;
|
|
56529
56718
|
} else if (deps.sessionStore) {
|
|
56530
56719
|
const file = deps.sessionStore.read(sid);
|
|
@@ -56532,7 +56721,7 @@ function createHttpRouter(deps) {
|
|
|
56532
56721
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
56533
56722
|
return true;
|
|
56534
56723
|
}
|
|
56535
|
-
absPath =
|
|
56724
|
+
absPath = import_node_path38.default.join(file.cwd, pathParam);
|
|
56536
56725
|
} else {
|
|
56537
56726
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
56538
56727
|
return true;
|
|
@@ -56619,7 +56808,7 @@ function withCtx(ctx, body) {
|
|
|
56619
56808
|
function streamFile(res, absPath, logger) {
|
|
56620
56809
|
let stat;
|
|
56621
56810
|
try {
|
|
56622
|
-
stat =
|
|
56811
|
+
stat = import_node_fs34.default.statSync(absPath);
|
|
56623
56812
|
} catch (err) {
|
|
56624
56813
|
const code = err?.code;
|
|
56625
56814
|
if (code === "ENOENT") {
|
|
@@ -56634,7 +56823,7 @@ function streamFile(res, absPath, logger) {
|
|
|
56634
56823
|
return;
|
|
56635
56824
|
}
|
|
56636
56825
|
const mime = lookupMime(absPath);
|
|
56637
|
-
const basename =
|
|
56826
|
+
const basename = import_node_path38.default.basename(absPath);
|
|
56638
56827
|
res.writeHead(200, {
|
|
56639
56828
|
"Content-Type": mime,
|
|
56640
56829
|
"Content-Length": String(stat.size),
|
|
@@ -56642,7 +56831,7 @@ function streamFile(res, absPath, logger) {
|
|
|
56642
56831
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
56643
56832
|
"X-Content-Type-Options": "nosniff"
|
|
56644
56833
|
});
|
|
56645
|
-
const stream =
|
|
56834
|
+
const stream = import_node_fs34.default.createReadStream(absPath);
|
|
56646
56835
|
stream.on("error", (err) => {
|
|
56647
56836
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
56648
56837
|
res.destroy();
|
|
@@ -56651,8 +56840,8 @@ function streamFile(res, absPath, logger) {
|
|
|
56651
56840
|
}
|
|
56652
56841
|
|
|
56653
56842
|
// src/attachment/gc.ts
|
|
56654
|
-
var
|
|
56655
|
-
var
|
|
56843
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
56844
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
56656
56845
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
56657
56846
|
function runAttachmentGc(args) {
|
|
56658
56847
|
const now = (args.now ?? Date.now)();
|
|
@@ -56661,12 +56850,12 @@ function runAttachmentGc(args) {
|
|
|
56661
56850
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
56662
56851
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
56663
56852
|
if (entry.stale) continue;
|
|
56664
|
-
if (
|
|
56853
|
+
if (import_node_path39.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
56665
56854
|
}
|
|
56666
56855
|
}
|
|
56667
56856
|
const visited = /* @__PURE__ */ new Set();
|
|
56668
56857
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
56669
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
56858
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path39.default.join(
|
|
56670
56859
|
args.dataDir,
|
|
56671
56860
|
"sessions",
|
|
56672
56861
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -56679,28 +56868,28 @@ function runAttachmentGc(args) {
|
|
|
56679
56868
|
return true;
|
|
56680
56869
|
});
|
|
56681
56870
|
for (const rootDir of roots) {
|
|
56682
|
-
const attRoot =
|
|
56871
|
+
const attRoot = import_node_path39.default.join(rootDir, ".attachments");
|
|
56683
56872
|
let hashDirs;
|
|
56684
56873
|
try {
|
|
56685
|
-
hashDirs =
|
|
56874
|
+
hashDirs = import_node_fs35.default.readdirSync(attRoot);
|
|
56686
56875
|
} catch (err) {
|
|
56687
56876
|
if (err.code === "ENOENT") continue;
|
|
56688
56877
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
56689
56878
|
continue;
|
|
56690
56879
|
}
|
|
56691
56880
|
for (const hashDir of hashDirs) {
|
|
56692
|
-
const hashDirAbs =
|
|
56881
|
+
const hashDirAbs = import_node_path39.default.join(attRoot, hashDir);
|
|
56693
56882
|
let files;
|
|
56694
56883
|
try {
|
|
56695
|
-
files =
|
|
56884
|
+
files = import_node_fs35.default.readdirSync(hashDirAbs);
|
|
56696
56885
|
} catch {
|
|
56697
56886
|
continue;
|
|
56698
56887
|
}
|
|
56699
56888
|
for (const name of files) {
|
|
56700
|
-
const file =
|
|
56889
|
+
const file = import_node_path39.default.join(hashDirAbs, name);
|
|
56701
56890
|
let stat;
|
|
56702
56891
|
try {
|
|
56703
|
-
stat =
|
|
56892
|
+
stat = import_node_fs35.default.statSync(file);
|
|
56704
56893
|
} catch {
|
|
56705
56894
|
continue;
|
|
56706
56895
|
}
|
|
@@ -56709,18 +56898,18 @@ function runAttachmentGc(args) {
|
|
|
56709
56898
|
if (age < ttlMs) continue;
|
|
56710
56899
|
if (liveAbs.has(file)) continue;
|
|
56711
56900
|
try {
|
|
56712
|
-
|
|
56901
|
+
import_node_fs35.default.unlinkSync(file);
|
|
56713
56902
|
} catch (err) {
|
|
56714
56903
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
56715
56904
|
}
|
|
56716
56905
|
}
|
|
56717
56906
|
try {
|
|
56718
|
-
if (
|
|
56907
|
+
if (import_node_fs35.default.readdirSync(hashDirAbs).length === 0) import_node_fs35.default.rmdirSync(hashDirAbs);
|
|
56719
56908
|
} catch {
|
|
56720
56909
|
}
|
|
56721
56910
|
}
|
|
56722
56911
|
try {
|
|
56723
|
-
if (
|
|
56912
|
+
if (import_node_fs35.default.readdirSync(attRoot).length === 0) import_node_fs35.default.rmdirSync(attRoot);
|
|
56724
56913
|
} catch {
|
|
56725
56914
|
}
|
|
56726
56915
|
}
|
|
@@ -56728,8 +56917,8 @@ function runAttachmentGc(args) {
|
|
|
56728
56917
|
}
|
|
56729
56918
|
|
|
56730
56919
|
// src/attachment/group.ts
|
|
56731
|
-
var
|
|
56732
|
-
var
|
|
56920
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
56921
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
56733
56922
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
56734
56923
|
init_protocol();
|
|
56735
56924
|
var GroupFileStore = class {
|
|
@@ -56741,11 +56930,11 @@ var GroupFileStore = class {
|
|
|
56741
56930
|
this.logger = opts.logger;
|
|
56742
56931
|
}
|
|
56743
56932
|
rootForScope(scope) {
|
|
56744
|
-
return
|
|
56933
|
+
return import_node_path40.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
56745
56934
|
}
|
|
56746
56935
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
56747
56936
|
filePath(scope, sessionId) {
|
|
56748
|
-
return
|
|
56937
|
+
return import_node_path40.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
56749
56938
|
}
|
|
56750
56939
|
cacheKey(scope, sessionId) {
|
|
56751
56940
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -56754,7 +56943,7 @@ var GroupFileStore = class {
|
|
|
56754
56943
|
readFile(scope, sessionId) {
|
|
56755
56944
|
const file = this.filePath(scope, sessionId);
|
|
56756
56945
|
try {
|
|
56757
|
-
const raw =
|
|
56946
|
+
const raw = import_node_fs36.default.readFileSync(file, "utf8");
|
|
56758
56947
|
const parsed = JSON.parse(raw);
|
|
56759
56948
|
if (!Array.isArray(parsed)) {
|
|
56760
56949
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -56780,10 +56969,10 @@ var GroupFileStore = class {
|
|
|
56780
56969
|
}
|
|
56781
56970
|
writeFile(scope, sessionId, entries) {
|
|
56782
56971
|
const file = this.filePath(scope, sessionId);
|
|
56783
|
-
|
|
56972
|
+
import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(file), { recursive: true });
|
|
56784
56973
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
56785
|
-
|
|
56786
|
-
|
|
56974
|
+
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
56975
|
+
import_node_fs36.default.renameSync(tmp, file);
|
|
56787
56976
|
}
|
|
56788
56977
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
56789
56978
|
list(scope, sessionId) {
|
|
@@ -56869,10 +57058,10 @@ var GroupFileStore = class {
|
|
|
56869
57058
|
};
|
|
56870
57059
|
|
|
56871
57060
|
// src/discovery/state-file.ts
|
|
56872
|
-
var
|
|
56873
|
-
var
|
|
57061
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
57062
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
56874
57063
|
function defaultStateFilePath(dataDir) {
|
|
56875
|
-
return
|
|
57064
|
+
return import_node_path41.default.join(dataDir, "state.json");
|
|
56876
57065
|
}
|
|
56877
57066
|
function isPidAlive(pid) {
|
|
56878
57067
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -56894,7 +57083,7 @@ var StateFileManager = class {
|
|
|
56894
57083
|
}
|
|
56895
57084
|
read() {
|
|
56896
57085
|
try {
|
|
56897
|
-
const raw =
|
|
57086
|
+
const raw = import_node_fs37.default.readFileSync(this.file, "utf8");
|
|
56898
57087
|
const parsed = JSON.parse(raw);
|
|
56899
57088
|
return parsed;
|
|
56900
57089
|
} catch {
|
|
@@ -56908,20 +57097,20 @@ var StateFileManager = class {
|
|
|
56908
57097
|
return { status: "stale", existing };
|
|
56909
57098
|
}
|
|
56910
57099
|
write(state) {
|
|
56911
|
-
|
|
57100
|
+
import_node_fs37.default.mkdirSync(import_node_path41.default.dirname(this.file), { recursive: true });
|
|
56912
57101
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
56913
|
-
|
|
56914
|
-
|
|
57102
|
+
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
57103
|
+
import_node_fs37.default.renameSync(tmp, this.file);
|
|
56915
57104
|
if (process.platform !== "win32") {
|
|
56916
57105
|
try {
|
|
56917
|
-
|
|
57106
|
+
import_node_fs37.default.chmodSync(this.file, 384);
|
|
56918
57107
|
} catch {
|
|
56919
57108
|
}
|
|
56920
57109
|
}
|
|
56921
57110
|
}
|
|
56922
57111
|
delete() {
|
|
56923
57112
|
try {
|
|
56924
|
-
|
|
57113
|
+
import_node_fs37.default.unlinkSync(this.file);
|
|
56925
57114
|
} catch {
|
|
56926
57115
|
}
|
|
56927
57116
|
}
|
|
@@ -56935,14 +57124,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
56935
57124
|
}
|
|
56936
57125
|
|
|
56937
57126
|
// src/tunnel/tunnel-manager.ts
|
|
56938
|
-
var
|
|
56939
|
-
var
|
|
57127
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
57128
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
56940
57129
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
56941
|
-
var
|
|
57130
|
+
var import_node_child_process11 = require("child_process");
|
|
56942
57131
|
|
|
56943
57132
|
// src/tunnel/tunnel-store.ts
|
|
56944
|
-
var
|
|
56945
|
-
var
|
|
57133
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
57134
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
56946
57135
|
var TunnelStore = class {
|
|
56947
57136
|
constructor(filePath) {
|
|
56948
57137
|
this.filePath = filePath;
|
|
@@ -56950,7 +57139,7 @@ var TunnelStore = class {
|
|
|
56950
57139
|
filePath;
|
|
56951
57140
|
async get() {
|
|
56952
57141
|
try {
|
|
56953
|
-
const raw = await
|
|
57142
|
+
const raw = await import_node_fs38.default.promises.readFile(this.filePath, "utf8");
|
|
56954
57143
|
const obj = JSON.parse(raw);
|
|
56955
57144
|
if (!isPersistedTunnel(obj)) return null;
|
|
56956
57145
|
return obj;
|
|
@@ -56961,22 +57150,22 @@ var TunnelStore = class {
|
|
|
56961
57150
|
}
|
|
56962
57151
|
}
|
|
56963
57152
|
async set(v2) {
|
|
56964
|
-
const dir =
|
|
56965
|
-
await
|
|
57153
|
+
const dir = import_node_path42.default.dirname(this.filePath);
|
|
57154
|
+
await import_node_fs38.default.promises.mkdir(dir, { recursive: true });
|
|
56966
57155
|
const data = JSON.stringify(v2, null, 2);
|
|
56967
57156
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
56968
|
-
await
|
|
57157
|
+
await import_node_fs38.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
56969
57158
|
if (process.platform !== "win32") {
|
|
56970
57159
|
try {
|
|
56971
|
-
await
|
|
57160
|
+
await import_node_fs38.default.promises.chmod(tmp, 384);
|
|
56972
57161
|
} catch {
|
|
56973
57162
|
}
|
|
56974
57163
|
}
|
|
56975
|
-
await
|
|
57164
|
+
await import_node_fs38.default.promises.rename(tmp, this.filePath);
|
|
56976
57165
|
}
|
|
56977
57166
|
async clear() {
|
|
56978
57167
|
try {
|
|
56979
|
-
await
|
|
57168
|
+
await import_node_fs38.default.promises.unlink(this.filePath);
|
|
56980
57169
|
} catch (err) {
|
|
56981
57170
|
const code = err?.code;
|
|
56982
57171
|
if (code !== "ENOENT") throw err;
|
|
@@ -57071,10 +57260,10 @@ function escape(v2) {
|
|
|
57071
57260
|
}
|
|
57072
57261
|
|
|
57073
57262
|
// src/tunnel/frpc-binary.ts
|
|
57074
|
-
var
|
|
57075
|
-
var
|
|
57076
|
-
var
|
|
57077
|
-
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");
|
|
57078
57267
|
var import_node_stream3 = require("stream");
|
|
57079
57268
|
var import_promises6 = require("stream/promises");
|
|
57080
57269
|
var FRPC_VERSION = "0.68.0";
|
|
@@ -57105,20 +57294,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
57105
57294
|
}
|
|
57106
57295
|
async function ensureFrpcBinary(opts) {
|
|
57107
57296
|
if (opts.override) {
|
|
57108
|
-
if (!
|
|
57297
|
+
if (!import_node_fs39.default.existsSync(opts.override)) {
|
|
57109
57298
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
57110
57299
|
}
|
|
57111
57300
|
return opts.override;
|
|
57112
57301
|
}
|
|
57113
57302
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
57114
57303
|
const platform = opts.platform ?? detectPlatform();
|
|
57115
|
-
const binDir =
|
|
57116
|
-
|
|
57304
|
+
const binDir = import_node_path43.default.join(opts.dataDir, "bin");
|
|
57305
|
+
import_node_fs39.default.mkdirSync(binDir, { recursive: true });
|
|
57117
57306
|
cleanupStaleArtifacts(binDir);
|
|
57118
|
-
const stableBin =
|
|
57119
|
-
if (
|
|
57307
|
+
const stableBin = import_node_path43.default.join(binDir, "frpc");
|
|
57308
|
+
if (import_node_fs39.default.existsSync(stableBin)) return stableBin;
|
|
57120
57309
|
const partialBin = `${stableBin}.partial`;
|
|
57121
|
-
const tarballPath =
|
|
57310
|
+
const tarballPath = import_node_path43.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
57122
57311
|
try {
|
|
57123
57312
|
const url = frpcDownloadUrl(version2, platform);
|
|
57124
57313
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -57127,8 +57316,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
57127
57316
|
} else {
|
|
57128
57317
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
57129
57318
|
}
|
|
57130
|
-
|
|
57131
|
-
|
|
57319
|
+
import_node_fs39.default.chmodSync(partialBin, 493);
|
|
57320
|
+
import_node_fs39.default.renameSync(partialBin, stableBin);
|
|
57132
57321
|
} finally {
|
|
57133
57322
|
safeUnlink(tarballPath);
|
|
57134
57323
|
safeUnlink(partialBin);
|
|
@@ -57138,15 +57327,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
57138
57327
|
function cleanupStaleArtifacts(binDir) {
|
|
57139
57328
|
let entries;
|
|
57140
57329
|
try {
|
|
57141
|
-
entries =
|
|
57330
|
+
entries = import_node_fs39.default.readdirSync(binDir);
|
|
57142
57331
|
} catch {
|
|
57143
57332
|
return;
|
|
57144
57333
|
}
|
|
57145
57334
|
for (const name of entries) {
|
|
57146
57335
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
57147
|
-
const full =
|
|
57336
|
+
const full = import_node_path43.default.join(binDir, name);
|
|
57148
57337
|
try {
|
|
57149
|
-
|
|
57338
|
+
import_node_fs39.default.rmSync(full, { recursive: true, force: true });
|
|
57150
57339
|
} catch {
|
|
57151
57340
|
}
|
|
57152
57341
|
}
|
|
@@ -57154,7 +57343,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
57154
57343
|
}
|
|
57155
57344
|
function safeUnlink(p2) {
|
|
57156
57345
|
try {
|
|
57157
|
-
|
|
57346
|
+
import_node_fs39.default.unlinkSync(p2);
|
|
57158
57347
|
} catch {
|
|
57159
57348
|
}
|
|
57160
57349
|
}
|
|
@@ -57165,46 +57354,46 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
57165
57354
|
if (!res.ok || !res.body) {
|
|
57166
57355
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
57167
57356
|
}
|
|
57168
|
-
const out =
|
|
57357
|
+
const out = import_node_fs39.default.createWriteStream(dest);
|
|
57169
57358
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
57170
57359
|
await (0, import_promises6.pipeline)(nodeStream, out);
|
|
57171
57360
|
}
|
|
57172
57361
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
57173
|
-
const work =
|
|
57174
|
-
|
|
57362
|
+
const work = import_node_path43.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
57363
|
+
import_node_fs39.default.mkdirSync(work, { recursive: true });
|
|
57175
57364
|
try {
|
|
57176
57365
|
await new Promise((resolve6, reject) => {
|
|
57177
|
-
const proc = (0,
|
|
57366
|
+
const proc = (0, import_node_child_process9.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
57178
57367
|
proc.on("error", reject);
|
|
57179
57368
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
57180
57369
|
});
|
|
57181
57370
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
57182
|
-
const src =
|
|
57183
|
-
if (!
|
|
57371
|
+
const src = import_node_path43.default.join(work, dirName, "frpc");
|
|
57372
|
+
if (!import_node_fs39.default.existsSync(src)) {
|
|
57184
57373
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
57185
57374
|
}
|
|
57186
|
-
|
|
57375
|
+
import_node_fs39.default.copyFileSync(src, destBin);
|
|
57187
57376
|
} finally {
|
|
57188
|
-
|
|
57377
|
+
import_node_fs39.default.rmSync(work, { recursive: true, force: true });
|
|
57189
57378
|
}
|
|
57190
57379
|
}
|
|
57191
57380
|
|
|
57192
57381
|
// src/tunnel/frpc-process.ts
|
|
57193
|
-
var
|
|
57194
|
-
var
|
|
57195
|
-
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");
|
|
57196
57385
|
function frpcPidFilePath(dataDir) {
|
|
57197
|
-
return
|
|
57386
|
+
return import_node_path44.default.join(dataDir, "frpc.pid");
|
|
57198
57387
|
}
|
|
57199
57388
|
function writeFrpcPid(dataDir, pid) {
|
|
57200
57389
|
try {
|
|
57201
|
-
|
|
57390
|
+
import_node_fs40.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
57202
57391
|
} catch {
|
|
57203
57392
|
}
|
|
57204
57393
|
}
|
|
57205
57394
|
function clearFrpcPid(dataDir) {
|
|
57206
57395
|
try {
|
|
57207
|
-
|
|
57396
|
+
import_node_fs40.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
57208
57397
|
} catch {
|
|
57209
57398
|
}
|
|
57210
57399
|
}
|
|
@@ -57220,7 +57409,7 @@ function defaultIsPidAlive(pid) {
|
|
|
57220
57409
|
}
|
|
57221
57410
|
function defaultReadPidFile(file) {
|
|
57222
57411
|
try {
|
|
57223
|
-
return
|
|
57412
|
+
return import_node_fs40.default.readFileSync(file, "utf8");
|
|
57224
57413
|
} catch {
|
|
57225
57414
|
return null;
|
|
57226
57415
|
}
|
|
@@ -57236,7 +57425,7 @@ function defaultSleep2(ms) {
|
|
|
57236
57425
|
}
|
|
57237
57426
|
async function killStaleFrpc(deps) {
|
|
57238
57427
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
57239
|
-
const tomlPath =
|
|
57428
|
+
const tomlPath = import_node_path44.default.join(deps.dataDir, "frpc.toml");
|
|
57240
57429
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
57241
57430
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
57242
57431
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -57260,7 +57449,7 @@ async function killStaleFrpc(deps) {
|
|
|
57260
57449
|
}
|
|
57261
57450
|
if (victims.size === 0) {
|
|
57262
57451
|
try {
|
|
57263
|
-
|
|
57452
|
+
import_node_fs40.default.unlinkSync(pidFile);
|
|
57264
57453
|
} catch {
|
|
57265
57454
|
}
|
|
57266
57455
|
return;
|
|
@@ -57271,14 +57460,14 @@ async function killStaleFrpc(deps) {
|
|
|
57271
57460
|
}
|
|
57272
57461
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
57273
57462
|
try {
|
|
57274
|
-
|
|
57463
|
+
import_node_fs40.default.unlinkSync(pidFile);
|
|
57275
57464
|
} catch {
|
|
57276
57465
|
}
|
|
57277
57466
|
}
|
|
57278
57467
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
57279
57468
|
if (process.platform === "win32") return [];
|
|
57280
57469
|
return new Promise((resolve6) => {
|
|
57281
|
-
const ps = (0,
|
|
57470
|
+
const ps = (0, import_node_child_process10.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
57282
57471
|
let buf = "";
|
|
57283
57472
|
ps.stdout.on("data", (c) => {
|
|
57284
57473
|
buf += c.toString();
|
|
@@ -57308,7 +57497,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
57308
57497
|
var TunnelManager = class {
|
|
57309
57498
|
constructor(deps) {
|
|
57310
57499
|
this.deps = deps;
|
|
57311
|
-
this.store = deps.store ?? new TunnelStore(
|
|
57500
|
+
this.store = deps.store ?? new TunnelStore(import_node_path45.default.join(deps.dataDir, "tunnel.json"));
|
|
57312
57501
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
57313
57502
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
57314
57503
|
}
|
|
@@ -57435,7 +57624,7 @@ var TunnelManager = class {
|
|
|
57435
57624
|
dataDir: this.deps.dataDir,
|
|
57436
57625
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
57437
57626
|
});
|
|
57438
|
-
const tomlPath =
|
|
57627
|
+
const tomlPath = import_node_path45.default.join(this.deps.dataDir, "frpc.toml");
|
|
57439
57628
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
|
|
57440
57629
|
const toml = buildFrpcToml({
|
|
57441
57630
|
serverAddr: t.frpsHost,
|
|
@@ -57446,14 +57635,14 @@ var TunnelManager = class {
|
|
|
57446
57635
|
localPort,
|
|
57447
57636
|
logLevel: "info"
|
|
57448
57637
|
});
|
|
57449
|
-
await
|
|
57450
|
-
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], {
|
|
57451
57640
|
stdio: ["ignore", "pipe", "pipe"]
|
|
57452
57641
|
});
|
|
57453
|
-
const logDir =
|
|
57454
|
-
|
|
57455
|
-
const logFilePath =
|
|
57456
|
-
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 });
|
|
57457
57646
|
logStream.on("error", () => {
|
|
57458
57647
|
});
|
|
57459
57648
|
const tee = (chunk) => {
|
|
@@ -57535,28 +57724,28 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
57535
57724
|
}
|
|
57536
57725
|
|
|
57537
57726
|
// src/tunnel/device-key.ts
|
|
57538
|
-
var
|
|
57539
|
-
var
|
|
57727
|
+
var import_node_os15 = __toESM(require("os"), 1);
|
|
57728
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
57540
57729
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
57541
57730
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
57542
57731
|
function deriveStableDeviceKey(opts = {}) {
|
|
57543
|
-
const hostname = opts.hostname ??
|
|
57544
|
-
const uid = opts.uid ?? (typeof
|
|
57545
|
-
const home = opts.home ??
|
|
57546
|
-
const defaultDataDir =
|
|
57547
|
-
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;
|
|
57548
57737
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
57549
57738
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
57550
57739
|
return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
57551
57740
|
}
|
|
57552
57741
|
|
|
57553
57742
|
// src/auth-store.ts
|
|
57554
|
-
var
|
|
57555
|
-
var
|
|
57743
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
57744
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
57556
57745
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
57557
57746
|
var AUTH_FILE_NAME = "auth.json";
|
|
57558
57747
|
function authFilePath(dataDir) {
|
|
57559
|
-
return
|
|
57748
|
+
return import_node_path47.default.join(dataDir, AUTH_FILE_NAME);
|
|
57560
57749
|
}
|
|
57561
57750
|
function loadOrCreateAuthFile(opts) {
|
|
57562
57751
|
const file = authFilePath(opts.dataDir);
|
|
@@ -57588,7 +57777,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
57588
57777
|
}
|
|
57589
57778
|
function readAuthFile(file) {
|
|
57590
57779
|
try {
|
|
57591
|
-
const raw =
|
|
57780
|
+
const raw = import_node_fs42.default.readFileSync(file, "utf8");
|
|
57592
57781
|
const parsed = JSON.parse(raw);
|
|
57593
57782
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
57594
57783
|
return null;
|
|
@@ -57608,26 +57797,26 @@ function readAuthFile(file) {
|
|
|
57608
57797
|
}
|
|
57609
57798
|
}
|
|
57610
57799
|
function writeAuthFile(file, content) {
|
|
57611
|
-
|
|
57612
|
-
|
|
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 });
|
|
57613
57802
|
try {
|
|
57614
|
-
|
|
57803
|
+
import_node_fs42.default.chmodSync(file, 384);
|
|
57615
57804
|
} catch {
|
|
57616
57805
|
}
|
|
57617
57806
|
}
|
|
57618
57807
|
|
|
57619
57808
|
// src/owner-profile.ts
|
|
57620
|
-
var
|
|
57621
|
-
var
|
|
57622
|
-
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);
|
|
57623
57812
|
var PROFILE_FILENAME = "profile.json";
|
|
57624
57813
|
function profilePath(dataDir) {
|
|
57625
|
-
return
|
|
57814
|
+
return import_node_path48.default.join(dataDir, PROFILE_FILENAME);
|
|
57626
57815
|
}
|
|
57627
57816
|
function loadOwnerProfile(dataDir) {
|
|
57628
57817
|
let raw;
|
|
57629
57818
|
try {
|
|
57630
|
-
raw =
|
|
57819
|
+
raw = import_node_fs43.default.readFileSync(profilePath(dataDir), "utf8");
|
|
57631
57820
|
} catch {
|
|
57632
57821
|
return {};
|
|
57633
57822
|
}
|
|
@@ -57643,11 +57832,11 @@ function loadOwnerProfile(dataDir) {
|
|
|
57643
57832
|
}
|
|
57644
57833
|
function patchOwnerProfile(dataDir, patch) {
|
|
57645
57834
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
57646
|
-
|
|
57835
|
+
import_node_fs43.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
57647
57836
|
return merged;
|
|
57648
57837
|
}
|
|
57649
57838
|
function loadOwnerDisplayName(dataDir) {
|
|
57650
|
-
const fallback =
|
|
57839
|
+
const fallback = import_node_os16.default.userInfo().username;
|
|
57651
57840
|
const displayName = loadOwnerProfile(dataDir).displayName;
|
|
57652
57841
|
if (typeof displayName !== "string" || displayName.length === 0) {
|
|
57653
57842
|
if (displayName !== void 0) {
|
|
@@ -57659,18 +57848,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
57659
57848
|
}
|
|
57660
57849
|
|
|
57661
57850
|
// src/feishu-auth/owner-identity-store.ts
|
|
57662
|
-
var
|
|
57663
|
-
var
|
|
57851
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
57852
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
57664
57853
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
57665
57854
|
var OwnerIdentityStore = class {
|
|
57666
57855
|
file;
|
|
57667
57856
|
constructor(dataDir) {
|
|
57668
|
-
this.file =
|
|
57857
|
+
this.file = import_node_path49.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
57669
57858
|
}
|
|
57670
57859
|
read() {
|
|
57671
57860
|
let raw;
|
|
57672
57861
|
try {
|
|
57673
|
-
raw =
|
|
57862
|
+
raw = import_node_fs44.default.readFileSync(this.file, "utf8");
|
|
57674
57863
|
} catch {
|
|
57675
57864
|
return null;
|
|
57676
57865
|
}
|
|
@@ -57698,16 +57887,16 @@ var OwnerIdentityStore = class {
|
|
|
57698
57887
|
};
|
|
57699
57888
|
}
|
|
57700
57889
|
write(record) {
|
|
57701
|
-
|
|
57702
|
-
|
|
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 });
|
|
57703
57892
|
try {
|
|
57704
|
-
|
|
57893
|
+
import_node_fs44.default.chmodSync(this.file, 384);
|
|
57705
57894
|
} catch {
|
|
57706
57895
|
}
|
|
57707
57896
|
}
|
|
57708
57897
|
clear() {
|
|
57709
57898
|
try {
|
|
57710
|
-
|
|
57899
|
+
import_node_fs44.default.unlinkSync(this.file);
|
|
57711
57900
|
} catch (err) {
|
|
57712
57901
|
const code = err?.code;
|
|
57713
57902
|
if (code !== "ENOENT") throw err;
|
|
@@ -57844,9 +58033,9 @@ var CentralClientError = class extends Error {
|
|
|
57844
58033
|
code;
|
|
57845
58034
|
cause;
|
|
57846
58035
|
};
|
|
57847
|
-
async function centralRequest(opts,
|
|
58036
|
+
async function centralRequest(opts, path82, init) {
|
|
57848
58037
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
57849
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
58038
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path82}`;
|
|
57850
58039
|
const ctrl = new AbortController();
|
|
57851
58040
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
57852
58041
|
let res;
|
|
@@ -58040,8 +58229,8 @@ function verifyConnectToken(args) {
|
|
|
58040
58229
|
}
|
|
58041
58230
|
|
|
58042
58231
|
// src/feishu-auth/server-key.ts
|
|
58043
|
-
var
|
|
58044
|
-
var
|
|
58232
|
+
var fs55 = __toESM(require("fs"), 1);
|
|
58233
|
+
var path58 = __toESM(require("path"), 1);
|
|
58045
58234
|
var FILE_NAME2 = "server-signing-key.json";
|
|
58046
58235
|
var ServerKeyStore = class {
|
|
58047
58236
|
constructor(dataDir) {
|
|
@@ -58049,12 +58238,12 @@ var ServerKeyStore = class {
|
|
|
58049
58238
|
}
|
|
58050
58239
|
dataDir;
|
|
58051
58240
|
filePath() {
|
|
58052
|
-
return
|
|
58241
|
+
return path58.join(this.dataDir, FILE_NAME2);
|
|
58053
58242
|
}
|
|
58054
58243
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
58055
58244
|
read() {
|
|
58056
58245
|
try {
|
|
58057
|
-
const raw =
|
|
58246
|
+
const raw = fs55.readFileSync(this.filePath(), "utf8");
|
|
58058
58247
|
const parsed = JSON.parse(raw);
|
|
58059
58248
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
58060
58249
|
return parsed.publicKeyPem;
|
|
@@ -58069,12 +58258,12 @@ var ServerKeyStore = class {
|
|
|
58069
58258
|
publicKeyPem,
|
|
58070
58259
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
58071
58260
|
};
|
|
58072
|
-
|
|
58073
|
-
|
|
58261
|
+
fs55.mkdirSync(this.dataDir, { recursive: true });
|
|
58262
|
+
fs55.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
58074
58263
|
}
|
|
58075
58264
|
clear() {
|
|
58076
58265
|
try {
|
|
58077
|
-
|
|
58266
|
+
fs55.unlinkSync(this.filePath());
|
|
58078
58267
|
} catch {
|
|
58079
58268
|
}
|
|
58080
58269
|
}
|
|
@@ -58087,12 +58276,12 @@ init_protocol();
|
|
|
58087
58276
|
init_protocol();
|
|
58088
58277
|
|
|
58089
58278
|
// src/session/fork.ts
|
|
58090
|
-
var
|
|
58091
|
-
var
|
|
58092
|
-
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);
|
|
58093
58282
|
init_claude_history();
|
|
58094
58283
|
function readJsonlEntries(file) {
|
|
58095
|
-
const raw =
|
|
58284
|
+
const raw = import_node_fs45.default.readFileSync(file, "utf8");
|
|
58096
58285
|
const out = [];
|
|
58097
58286
|
for (const line of raw.split("\n")) {
|
|
58098
58287
|
const t = line.trim();
|
|
@@ -58105,19 +58294,19 @@ function readJsonlEntries(file) {
|
|
|
58105
58294
|
return out;
|
|
58106
58295
|
}
|
|
58107
58296
|
function forkSession(input) {
|
|
58108
|
-
const baseDir = input.baseDir ??
|
|
58109
|
-
let projectDir =
|
|
58110
|
-
let sourceFile =
|
|
58111
|
-
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)) {
|
|
58112
58301
|
const found = findTranscriptByToolSessionId(
|
|
58113
|
-
|
|
58302
|
+
import_node_path50.default.join(baseDir, "projects"),
|
|
58114
58303
|
input.toolSessionId
|
|
58115
58304
|
);
|
|
58116
58305
|
if (!found) {
|
|
58117
58306
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
58118
58307
|
}
|
|
58119
58308
|
sourceFile = found;
|
|
58120
|
-
projectDir =
|
|
58309
|
+
projectDir = import_node_path50.default.dirname(found);
|
|
58121
58310
|
}
|
|
58122
58311
|
const entries = readJsonlEntries(sourceFile);
|
|
58123
58312
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -58146,27 +58335,27 @@ function forkSession(input) {
|
|
|
58146
58335
|
}
|
|
58147
58336
|
forkedLines.push(JSON.stringify(forked));
|
|
58148
58337
|
}
|
|
58149
|
-
const outDir = input.targetCwd ?
|
|
58150
|
-
const forkedFilePath =
|
|
58151
|
-
|
|
58152
|
-
|
|
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 });
|
|
58153
58342
|
return { forkedToolSessionId, forkedFilePath };
|
|
58154
58343
|
}
|
|
58155
58344
|
|
|
58156
58345
|
// src/session/external-scan.ts
|
|
58157
|
-
var
|
|
58346
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
58158
58347
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
58159
|
-
var
|
|
58160
|
-
var
|
|
58348
|
+
var import_node_os18 = __toESM(require("os"), 1);
|
|
58349
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58161
58350
|
var import_node_module = require("module");
|
|
58162
|
-
var
|
|
58351
|
+
var import_node_child_process12 = require("child_process");
|
|
58163
58352
|
var import_meta4 = {};
|
|
58164
58353
|
function defaultRoots() {
|
|
58165
|
-
const home =
|
|
58354
|
+
const home = import_node_os18.default.homedir();
|
|
58166
58355
|
return {
|
|
58167
|
-
claudeProjectsDir:
|
|
58168
|
-
codexDir:
|
|
58169
|
-
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")
|
|
58170
58359
|
};
|
|
58171
58360
|
}
|
|
58172
58361
|
function width(s) {
|
|
@@ -58194,12 +58383,12 @@ function toMs(v2) {
|
|
|
58194
58383
|
function listFiles(dir, depth = 0, maxDepth = 8, out = []) {
|
|
58195
58384
|
let entries;
|
|
58196
58385
|
try {
|
|
58197
|
-
entries =
|
|
58386
|
+
entries = import_node_fs46.default.readdirSync(dir, { withFileTypes: true });
|
|
58198
58387
|
} catch {
|
|
58199
58388
|
return out;
|
|
58200
58389
|
}
|
|
58201
58390
|
for (const e of entries) {
|
|
58202
|
-
const full =
|
|
58391
|
+
const full = import_node_path51.default.join(dir, e.name);
|
|
58203
58392
|
if (e.isDirectory()) {
|
|
58204
58393
|
if (depth < maxDepth) listFiles(full, depth + 1, maxDepth, out);
|
|
58205
58394
|
} else if (e.isFile()) {
|
|
@@ -58234,7 +58423,7 @@ function userText(msg) {
|
|
|
58234
58423
|
}
|
|
58235
58424
|
function isDir2(p2) {
|
|
58236
58425
|
try {
|
|
58237
|
-
return
|
|
58426
|
+
return import_node_fs46.default.statSync(p2).isDirectory();
|
|
58238
58427
|
} catch {
|
|
58239
58428
|
return false;
|
|
58240
58429
|
}
|
|
@@ -58243,7 +58432,7 @@ async function scanClaude(roots) {
|
|
|
58243
58432
|
const out = [];
|
|
58244
58433
|
let dirs;
|
|
58245
58434
|
try {
|
|
58246
|
-
dirs =
|
|
58435
|
+
dirs = import_node_fs46.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
58247
58436
|
} catch {
|
|
58248
58437
|
return out;
|
|
58249
58438
|
}
|
|
@@ -58251,16 +58440,16 @@ async function scanClaude(roots) {
|
|
|
58251
58440
|
if (!d.isDirectory()) continue;
|
|
58252
58441
|
let files;
|
|
58253
58442
|
try {
|
|
58254
|
-
files =
|
|
58443
|
+
files = import_node_fs46.default.readdirSync(import_node_path51.default.join(roots.claudeProjectsDir, d.name));
|
|
58255
58444
|
} catch {
|
|
58256
58445
|
continue;
|
|
58257
58446
|
}
|
|
58258
58447
|
for (const name of files) {
|
|
58259
58448
|
if (!name.endsWith(".jsonl")) continue;
|
|
58260
|
-
const file =
|
|
58449
|
+
const file = import_node_path51.default.join(roots.claudeProjectsDir, d.name, name);
|
|
58261
58450
|
let st;
|
|
58262
58451
|
try {
|
|
58263
|
-
st =
|
|
58452
|
+
st = import_node_fs46.default.statSync(file);
|
|
58264
58453
|
} catch {
|
|
58265
58454
|
continue;
|
|
58266
58455
|
}
|
|
@@ -58304,13 +58493,14 @@ async function scanClaude(roots) {
|
|
|
58304
58493
|
};
|
|
58305
58494
|
if (!hasMainLine) cand.skip = "subagent \u652F\u7EBF";
|
|
58306
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";
|
|
58307
58497
|
out.push(cand);
|
|
58308
58498
|
}
|
|
58309
58499
|
}
|
|
58310
58500
|
return out;
|
|
58311
58501
|
}
|
|
58312
58502
|
async function countCodexTurns(rolloutPath) {
|
|
58313
|
-
if (!rolloutPath || !
|
|
58503
|
+
if (!rolloutPath || !import_node_fs46.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
58314
58504
|
let turns = 0;
|
|
58315
58505
|
let first = "";
|
|
58316
58506
|
for await (const rec4 of jsonLines(rolloutPath)) {
|
|
@@ -58341,14 +58531,14 @@ function readCodexThreads(db) {
|
|
|
58341
58531
|
} catch {
|
|
58342
58532
|
}
|
|
58343
58533
|
try {
|
|
58344
|
-
const info = (0,
|
|
58534
|
+
const info = (0, import_node_child_process12.spawnSync)("sqlite3", [db, "PRAGMA table_info(threads);"], { encoding: "utf8" });
|
|
58345
58535
|
if (info.status !== 0) return null;
|
|
58346
58536
|
const have = new Set(
|
|
58347
58537
|
info.stdout.split("\n").map((l) => l.split("|")[1]).filter(Boolean)
|
|
58348
58538
|
);
|
|
58349
58539
|
if (!["id", "cwd", "updated_at"].every((c) => have.has(c))) return null;
|
|
58350
58540
|
const sel = COLS.map((c) => have.has(c) ? c : `NULL AS ${c}`).join(", ");
|
|
58351
|
-
const res = (0,
|
|
58541
|
+
const res = (0, import_node_child_process12.spawnSync)("sqlite3", ["-json", db, `SELECT ${sel} FROM threads;`], {
|
|
58352
58542
|
encoding: "utf8",
|
|
58353
58543
|
maxBuffer: 64 * 1024 * 1024
|
|
58354
58544
|
});
|
|
@@ -58382,11 +58572,11 @@ async function codexFromRows(rows) {
|
|
|
58382
58572
|
}
|
|
58383
58573
|
async function scanCodexRollouts(roots) {
|
|
58384
58574
|
const out = [];
|
|
58385
|
-
for (const file of listFiles(
|
|
58575
|
+
for (const file of listFiles(import_node_path51.default.join(roots.codexDir, "sessions"))) {
|
|
58386
58576
|
if (!file.endsWith(".jsonl")) continue;
|
|
58387
58577
|
let st;
|
|
58388
58578
|
try {
|
|
58389
|
-
st =
|
|
58579
|
+
st = import_node_fs46.default.statSync(file);
|
|
58390
58580
|
} catch {
|
|
58391
58581
|
continue;
|
|
58392
58582
|
}
|
|
@@ -58418,7 +58608,7 @@ async function scanCodexRollouts(roots) {
|
|
|
58418
58608
|
async function scanCodex(roots) {
|
|
58419
58609
|
let dbs = [];
|
|
58420
58610
|
try {
|
|
58421
|
-
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));
|
|
58422
58612
|
} catch {
|
|
58423
58613
|
}
|
|
58424
58614
|
if (dbs.length) {
|
|
@@ -58429,14 +58619,14 @@ async function scanCodex(roots) {
|
|
|
58429
58619
|
}
|
|
58430
58620
|
async function scanExternalSessions(rootsIn) {
|
|
58431
58621
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
58432
|
-
const personaRoot =
|
|
58622
|
+
const personaRoot = import_node_path51.default.join(roots.clawdDir, "personas");
|
|
58433
58623
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
58434
58624
|
const out = [];
|
|
58435
58625
|
for (const c of all) {
|
|
58436
58626
|
if (c.skip) continue;
|
|
58437
58627
|
if (c.turns < 1) continue;
|
|
58438
58628
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
58439
|
-
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)) {
|
|
58440
58630
|
continue;
|
|
58441
58631
|
}
|
|
58442
58632
|
out.push({
|
|
@@ -58453,19 +58643,19 @@ async function scanExternalSessions(rootsIn) {
|
|
|
58453
58643
|
}
|
|
58454
58644
|
|
|
58455
58645
|
// src/session/import-ledger.ts
|
|
58456
|
-
var
|
|
58457
|
-
var
|
|
58646
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
58647
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
58458
58648
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
58459
58649
|
function appendImportLedger(dataDir, entry) {
|
|
58460
|
-
const file =
|
|
58650
|
+
const file = import_node_path52.default.join(dataDir, LEDGER_FILENAME);
|
|
58461
58651
|
let entries = [];
|
|
58462
58652
|
try {
|
|
58463
|
-
const parsed = JSON.parse(
|
|
58653
|
+
const parsed = JSON.parse(import_node_fs47.default.readFileSync(file, "utf8"));
|
|
58464
58654
|
if (Array.isArray(parsed)) entries = parsed;
|
|
58465
58655
|
} catch {
|
|
58466
58656
|
}
|
|
58467
58657
|
entries.push(entry);
|
|
58468
|
-
|
|
58658
|
+
import_node_fs47.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
58469
58659
|
}
|
|
58470
58660
|
|
|
58471
58661
|
// src/handlers/session.ts
|
|
@@ -58958,7 +59148,7 @@ function buildPermissionHandlers(deps) {
|
|
|
58958
59148
|
}
|
|
58959
59149
|
|
|
58960
59150
|
// src/handlers/history.ts
|
|
58961
|
-
var
|
|
59151
|
+
var path63 = __toESM(require("path"), 1);
|
|
58962
59152
|
init_protocol();
|
|
58963
59153
|
|
|
58964
59154
|
// src/session/recent-dirs.ts
|
|
@@ -58976,7 +59166,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
58976
59166
|
}
|
|
58977
59167
|
|
|
58978
59168
|
// src/permission/persona-paths.ts
|
|
58979
|
-
var
|
|
59169
|
+
var path62 = __toESM(require("path"), 1);
|
|
58980
59170
|
function getAllowedPersonaIds(grants, action) {
|
|
58981
59171
|
const ids = /* @__PURE__ */ new Set();
|
|
58982
59172
|
for (const g2 of grants) {
|
|
@@ -58989,42 +59179,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
58989
59179
|
return ids;
|
|
58990
59180
|
}
|
|
58991
59181
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
58992
|
-
const target =
|
|
59182
|
+
const target = path62.resolve(absPath);
|
|
58993
59183
|
if (userWorkDir) {
|
|
58994
|
-
const u =
|
|
58995
|
-
const usep = u.endsWith(
|
|
59184
|
+
const u = path62.resolve(userWorkDir);
|
|
59185
|
+
const usep = u.endsWith(path62.sep) ? "" : path62.sep;
|
|
58996
59186
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
58997
59187
|
}
|
|
58998
|
-
const root =
|
|
58999
|
-
const sep3 = root.endsWith(
|
|
59188
|
+
const root = path62.resolve(personaRoot);
|
|
59189
|
+
const sep3 = root.endsWith(path62.sep) ? "" : path62.sep;
|
|
59000
59190
|
if (!target.startsWith(root + sep3)) return false;
|
|
59001
|
-
const rel =
|
|
59191
|
+
const rel = path62.relative(root, target);
|
|
59002
59192
|
if (!rel || rel.startsWith("..")) return false;
|
|
59003
|
-
const personaId2 = rel.split(
|
|
59193
|
+
const personaId2 = rel.split(path62.sep)[0];
|
|
59004
59194
|
if (!personaId2) return false;
|
|
59005
59195
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
59006
59196
|
if (allowed === "*") return true;
|
|
59007
59197
|
return allowed.has(personaId2);
|
|
59008
59198
|
}
|
|
59009
59199
|
function personaIdFromPath(absPath, personaRoot) {
|
|
59010
|
-
const root =
|
|
59011
|
-
const target =
|
|
59012
|
-
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;
|
|
59013
59203
|
if (!target.startsWith(root + sep3)) return null;
|
|
59014
|
-
const rel =
|
|
59204
|
+
const rel = path62.relative(root, target);
|
|
59015
59205
|
if (!rel || rel.startsWith("..")) return null;
|
|
59016
|
-
const id = rel.split(
|
|
59206
|
+
const id = rel.split(path62.sep)[0];
|
|
59017
59207
|
return id || null;
|
|
59018
59208
|
}
|
|
59019
59209
|
function isPathWithin(dir, absPath) {
|
|
59020
|
-
const d =
|
|
59021
|
-
const t =
|
|
59022
|
-
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;
|
|
59023
59213
|
return t === d || t.startsWith(d + sep3);
|
|
59024
59214
|
}
|
|
59025
59215
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
59026
59216
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
59027
|
-
return personaIdFromPath(
|
|
59217
|
+
return personaIdFromPath(path62.resolve(absPath), personaRoot) === personaId2;
|
|
59028
59218
|
}
|
|
59029
59219
|
|
|
59030
59220
|
// src/handlers/history.ts
|
|
@@ -59077,7 +59267,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59077
59267
|
if (!pid) return false;
|
|
59078
59268
|
return isGuestPathAllowed(
|
|
59079
59269
|
ctx.grants,
|
|
59080
|
-
|
|
59270
|
+
path63.join(personaRoot, pid),
|
|
59081
59271
|
personaRoot,
|
|
59082
59272
|
"read",
|
|
59083
59273
|
userWorkDir
|
|
@@ -59089,7 +59279,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59089
59279
|
};
|
|
59090
59280
|
const list = async (frame, _client, ctx) => {
|
|
59091
59281
|
const args = HistoryListArgs.parse(frame);
|
|
59092
|
-
assertGuestPath(ctx,
|
|
59282
|
+
assertGuestPath(ctx, path63.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
59093
59283
|
const sessions = await history.listSessions(args);
|
|
59094
59284
|
return { response: { type: "history:list", sessions } };
|
|
59095
59285
|
};
|
|
@@ -59133,14 +59323,14 @@ function buildHistoryHandlers(deps) {
|
|
|
59133
59323
|
};
|
|
59134
59324
|
const subagents = async (frame, _client, ctx) => {
|
|
59135
59325
|
const args = HistorySubagentsArgs.parse(frame);
|
|
59136
|
-
assertGuestPath(ctx,
|
|
59326
|
+
assertGuestPath(ctx, path63.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
59137
59327
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
59138
59328
|
const subs = await history.listSubagents(args);
|
|
59139
59329
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
59140
59330
|
};
|
|
59141
59331
|
const subagentRead = async (frame, _client, ctx) => {
|
|
59142
59332
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
59143
|
-
assertGuestPath(ctx,
|
|
59333
|
+
assertGuestPath(ctx, path63.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
59144
59334
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
59145
59335
|
const res = await history.readSubagent(args);
|
|
59146
59336
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -59150,7 +59340,7 @@ function buildHistoryHandlers(deps) {
|
|
|
59150
59340
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
59151
59341
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
59152
59342
|
const filtered = dirs.filter(
|
|
59153
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
59343
|
+
(d) => isGuestPathAllowed(ctx.grants, path63.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
59154
59344
|
);
|
|
59155
59345
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
59156
59346
|
}
|
|
@@ -59167,8 +59357,8 @@ function buildHistoryHandlers(deps) {
|
|
|
59167
59357
|
}
|
|
59168
59358
|
|
|
59169
59359
|
// src/handlers/workspace.ts
|
|
59170
|
-
var
|
|
59171
|
-
var
|
|
59360
|
+
var path64 = __toESM(require("path"), 1);
|
|
59361
|
+
var os18 = __toESM(require("os"), 1);
|
|
59172
59362
|
init_protocol();
|
|
59173
59363
|
init_protocol();
|
|
59174
59364
|
function buildEnabledPluginNames(personaManager, personaId2) {
|
|
@@ -59208,23 +59398,23 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59208
59398
|
const list = async (frame, _client, ctx) => {
|
|
59209
59399
|
const args = WorkspaceListArgs.parse(frame);
|
|
59210
59400
|
const isGuest = ctx?.principal.kind === "guest";
|
|
59211
|
-
const fallbackCwd = isGuest && personaRoot ? personaRoot :
|
|
59212
|
-
const resolvedCwd =
|
|
59213
|
-
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;
|
|
59214
59404
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
59215
59405
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
59216
59406
|
return { response: { type: "workspace:list", ...res } };
|
|
59217
59407
|
};
|
|
59218
59408
|
const read = async (frame, _client, ctx) => {
|
|
59219
59409
|
const args = WorkspaceReadArgs.parse(frame);
|
|
59220
|
-
const target =
|
|
59410
|
+
const target = path64.isAbsolute(args.path) ? path64.resolve(args.path) : path64.resolve(args.cwd, args.path);
|
|
59221
59411
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
59222
59412
|
const res = workspace.read(args);
|
|
59223
59413
|
return { response: { type: "workspace:read", ...res } };
|
|
59224
59414
|
};
|
|
59225
59415
|
const skillsList = async (frame, _client, ctx) => {
|
|
59226
59416
|
const args = SkillsListArgs.parse(frame);
|
|
59227
|
-
const cwdAbs =
|
|
59417
|
+
const cwdAbs = path64.resolve(args.cwd);
|
|
59228
59418
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
59229
59419
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
59230
59420
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -59236,7 +59426,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59236
59426
|
};
|
|
59237
59427
|
const agentsList = async (frame, _client, ctx) => {
|
|
59238
59428
|
const args = AgentsListArgs.parse(frame);
|
|
59239
|
-
const cwdAbs =
|
|
59429
|
+
const cwdAbs = path64.resolve(args.cwd);
|
|
59240
59430
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
59241
59431
|
if (args.tool === "codex") {
|
|
59242
59432
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -59258,20 +59448,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
59258
59448
|
}
|
|
59259
59449
|
|
|
59260
59450
|
// src/handlers/git.ts
|
|
59261
|
-
var
|
|
59451
|
+
var path66 = __toESM(require("path"), 1);
|
|
59262
59452
|
init_protocol();
|
|
59263
59453
|
init_protocol();
|
|
59264
59454
|
|
|
59265
59455
|
// src/workspace/git.ts
|
|
59266
|
-
var
|
|
59267
|
-
var
|
|
59268
|
-
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);
|
|
59269
59459
|
var import_node_util = require("util");
|
|
59270
|
-
var pexec = (0, import_node_util.promisify)(
|
|
59460
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process13.execFile);
|
|
59271
59461
|
function normalizePath(p2) {
|
|
59272
|
-
const resolved =
|
|
59462
|
+
const resolved = import_node_path53.default.resolve(p2);
|
|
59273
59463
|
try {
|
|
59274
|
-
return
|
|
59464
|
+
return import_node_fs48.default.realpathSync(resolved);
|
|
59275
59465
|
} catch {
|
|
59276
59466
|
return resolved;
|
|
59277
59467
|
}
|
|
@@ -59345,7 +59535,7 @@ async function listGitBranches(cwd) {
|
|
|
59345
59535
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
59346
59536
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
59347
59537
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
59348
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
59538
|
+
if (!isGuestPathAllowed(ctx.grants, path66.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
59349
59539
|
throw new ClawdError(
|
|
59350
59540
|
ERROR_CODES.UNAUTHORIZED,
|
|
59351
59541
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -59836,7 +60026,9 @@ function buildFeishuAuthHandlers(deps) {
|
|
|
59836
60026
|
type: "auth:getIdentity:ok",
|
|
59837
60027
|
identity: record ? record.identity : null,
|
|
59838
60028
|
// 决策 #15:设备属性,与登录态无关——UI"分享我的 Hub 标识"用
|
|
59839
|
-
deviceId: deps.deviceId
|
|
60029
|
+
deviceId: deps.deviceId,
|
|
60030
|
+
// 过期时间戳(仅时间戳,token 本体永不出 ws)——UI 派生 过期/临期 提示
|
|
60031
|
+
ttcTokenExpiresAt: record ? record.ttcTokenExpiresAt : null
|
|
59840
60032
|
}
|
|
59841
60033
|
};
|
|
59842
60034
|
};
|
|
@@ -59862,11 +60054,20 @@ function ensureOwner3(ctx) {
|
|
|
59862
60054
|
throw new ClawdError(ERROR_CODES.UNAUTHORIZED, "UNAUTHORIZED: device:* requires owner ctx");
|
|
59863
60055
|
}
|
|
59864
60056
|
}
|
|
60057
|
+
function rethrowLoginExpired(e) {
|
|
60058
|
+
if (e instanceof CentralClientError && e.code === "UNAUTHORIZED") {
|
|
60059
|
+
throw new ClawdError(
|
|
60060
|
+
ERROR_CODES.VALIDATION_ERROR,
|
|
60061
|
+
"LOGIN_EXPIRED: \u767B\u5F55\u51ED\u8BC1\u5DF2\u8FC7\u671F\uFF0C\u8BF7\u5728\u8054\u7CFB\u4EBA\u9762\u677F\u91CD\u65B0\u767B\u5F55"
|
|
60062
|
+
);
|
|
60063
|
+
}
|
|
60064
|
+
throw e;
|
|
60065
|
+
}
|
|
59865
60066
|
function buildDeviceHandlers(deps) {
|
|
59866
60067
|
const now = deps.now ?? Date.now;
|
|
59867
60068
|
const list = async (_frame, _client, ctx) => {
|
|
59868
60069
|
ensureOwner3(ctx);
|
|
59869
|
-
const devices = await deps.listDevices();
|
|
60070
|
+
const devices = await deps.listDevices().catch(rethrowLoginExpired);
|
|
59870
60071
|
return {
|
|
59871
60072
|
response: { type: "device:list:ok", devices }
|
|
59872
60073
|
};
|
|
@@ -59882,7 +60083,7 @@ function buildDeviceHandlers(deps) {
|
|
|
59882
60083
|
"TUNNEL_REQUIRED: \u672C\u673A\u672A\u5F00 tunnel\uFF0C\u5F00\u542F\u540E\u91CD\u8BD5"
|
|
59883
60084
|
);
|
|
59884
60085
|
}
|
|
59885
|
-
const exchanged = await deps.exchange(args.deviceId);
|
|
60086
|
+
const exchanged = await deps.exchange(args.deviceId).catch(rethrowLoginExpired);
|
|
59886
60087
|
const url = args.url ?? exchanged.deviceUrl;
|
|
59887
60088
|
if (!url) {
|
|
59888
60089
|
throw new ClawdError(
|
|
@@ -59967,7 +60168,7 @@ function buildDeviceHandlers(deps) {
|
|
|
59967
60168
|
}
|
|
59968
60169
|
|
|
59969
60170
|
// src/handlers/meta.ts
|
|
59970
|
-
var
|
|
60171
|
+
var import_node_os19 = __toESM(require("os"), 1);
|
|
59971
60172
|
init_protocol();
|
|
59972
60173
|
|
|
59973
60174
|
// src/handlers/method-grants.ts
|
|
@@ -60227,21 +60428,21 @@ function computeMethodAccess(args) {
|
|
|
60227
60428
|
}
|
|
60228
60429
|
|
|
60229
60430
|
// src/version.ts
|
|
60230
|
-
var version = "0.2.
|
|
60431
|
+
var version = "0.2.353".length > 0 ? "0.2.353" : "dev";
|
|
60231
60432
|
|
|
60232
60433
|
// src/cli-probe/probe.ts
|
|
60233
|
-
var
|
|
60234
|
-
var
|
|
60434
|
+
var fs60 = __toESM(require("fs"), 1);
|
|
60435
|
+
var path67 = __toESM(require("path"), 1);
|
|
60235
60436
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
60236
60437
|
var BIN_NAME = "clawd";
|
|
60237
60438
|
var MAX_PARENT_HOPS = 5;
|
|
60238
60439
|
function probeGlobalCli(pathEnv) {
|
|
60239
60440
|
if (!pathEnv) return null;
|
|
60240
|
-
for (const dir of pathEnv.split(
|
|
60441
|
+
for (const dir of pathEnv.split(path67.delimiter)) {
|
|
60241
60442
|
if (!dir) continue;
|
|
60242
60443
|
let real;
|
|
60243
60444
|
try {
|
|
60244
|
-
real =
|
|
60445
|
+
real = fs60.realpathSync(path67.join(dir, BIN_NAME));
|
|
60245
60446
|
} catch {
|
|
60246
60447
|
continue;
|
|
60247
60448
|
}
|
|
@@ -60251,15 +60452,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
60251
60452
|
return null;
|
|
60252
60453
|
}
|
|
60253
60454
|
function readOwnPackageVersion(entryPath) {
|
|
60254
|
-
let dir =
|
|
60455
|
+
let dir = path67.dirname(entryPath);
|
|
60255
60456
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
60256
60457
|
try {
|
|
60257
|
-
const raw =
|
|
60458
|
+
const raw = fs60.readFileSync(path67.join(dir, "package.json"), "utf8");
|
|
60258
60459
|
const pkg = JSON.parse(raw);
|
|
60259
60460
|
if (pkg.name !== PKG_NAME) return null;
|
|
60260
60461
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
60261
60462
|
} catch {
|
|
60262
|
-
const parent =
|
|
60463
|
+
const parent = path67.dirname(dir);
|
|
60263
60464
|
if (parent === dir) return null;
|
|
60264
60465
|
dir = parent;
|
|
60265
60466
|
}
|
|
@@ -60295,7 +60496,7 @@ function buildReadyFrame(deps, client) {
|
|
|
60295
60496
|
return {
|
|
60296
60497
|
version,
|
|
60297
60498
|
protocolVersion: PROTOCOL_VERSION,
|
|
60298
|
-
hostname:
|
|
60499
|
+
hostname: import_node_os19.default.hostname(),
|
|
60299
60500
|
os: process.platform,
|
|
60300
60501
|
tools,
|
|
60301
60502
|
runningSessions: info.runningSessions,
|
|
@@ -60422,7 +60623,7 @@ function buildPersonaHandlers(deps) {
|
|
|
60422
60623
|
}
|
|
60423
60624
|
|
|
60424
60625
|
// src/handlers/attachment.ts
|
|
60425
|
-
var
|
|
60626
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
60426
60627
|
init_protocol();
|
|
60427
60628
|
init_protocol();
|
|
60428
60629
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -60502,12 +60703,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
60502
60703
|
`session ${args.sessionId} scope unresolved`
|
|
60503
60704
|
);
|
|
60504
60705
|
}
|
|
60505
|
-
const cwdAbs =
|
|
60506
|
-
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);
|
|
60507
60708
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
60508
60709
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
60509
60710
|
const entry = entries.find((e) => {
|
|
60510
|
-
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);
|
|
60511
60712
|
return storedAbs === candidateAbs && !e.stale;
|
|
60512
60713
|
});
|
|
60513
60714
|
if (!entry) {
|
|
@@ -60532,7 +60733,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
60532
60733
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
60533
60734
|
const f = deps.sessionStore.read(sessionId);
|
|
60534
60735
|
if (!f) return;
|
|
60535
|
-
assertGuestAttachmentPath(ctx,
|
|
60736
|
+
assertGuestAttachmentPath(ctx, import_node_path54.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
60536
60737
|
}
|
|
60537
60738
|
const groupAdd = async (frame, _client, ctx) => {
|
|
60538
60739
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -60547,8 +60748,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
60547
60748
|
if (!scope) {
|
|
60548
60749
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
60549
60750
|
}
|
|
60550
|
-
const cwdAbs =
|
|
60551
|
-
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);
|
|
60552
60753
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
60553
60754
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
60554
60755
|
const size = 0;
|
|
@@ -60607,19 +60808,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
60607
60808
|
|
|
60608
60809
|
// src/handlers/extension.ts
|
|
60609
60810
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
60610
|
-
var
|
|
60811
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
60611
60812
|
init_protocol();
|
|
60612
60813
|
|
|
60613
60814
|
// src/extension/bundle-zip.ts
|
|
60614
60815
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
60615
|
-
var
|
|
60816
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
60616
60817
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
60617
60818
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
60618
60819
|
async function bundleExtensionDir(dir) {
|
|
60619
60820
|
const entries = await listFilesSorted(dir);
|
|
60620
60821
|
const zip = new import_jszip2.default();
|
|
60621
60822
|
for (const rel of entries) {
|
|
60622
|
-
const abs =
|
|
60823
|
+
const abs = import_node_path55.default.join(dir, rel);
|
|
60623
60824
|
const content = await import_promises8.default.readFile(abs);
|
|
60624
60825
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
60625
60826
|
}
|
|
@@ -60640,7 +60841,7 @@ async function listFilesSorted(rootDir) {
|
|
|
60640
60841
|
return out;
|
|
60641
60842
|
}
|
|
60642
60843
|
async function walk(absRoot, relPrefix, out) {
|
|
60643
|
-
const dirAbs =
|
|
60844
|
+
const dirAbs = import_node_path55.default.join(absRoot, relPrefix);
|
|
60644
60845
|
const entries = await import_promises8.default.readdir(dirAbs, { withFileTypes: true });
|
|
60645
60846
|
for (const e of entries) {
|
|
60646
60847
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -60694,25 +60895,25 @@ function computePublishCheck(args) {
|
|
|
60694
60895
|
|
|
60695
60896
|
// src/extension/install-flow.ts
|
|
60696
60897
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
60697
|
-
var
|
|
60698
|
-
var
|
|
60898
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
60899
|
+
var import_node_os21 = __toESM(require("os"), 1);
|
|
60699
60900
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
60700
60901
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
60701
60902
|
|
|
60702
60903
|
// src/extension/paths.ts
|
|
60703
|
-
var
|
|
60704
|
-
var
|
|
60904
|
+
var import_node_os20 = __toESM(require("os"), 1);
|
|
60905
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
60705
60906
|
function clawdHomeRoot(override) {
|
|
60706
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
60907
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path56.default.join(import_node_os20.default.homedir(), ".clawd");
|
|
60707
60908
|
}
|
|
60708
60909
|
function extensionsRoot(override) {
|
|
60709
|
-
return
|
|
60910
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extensions");
|
|
60710
60911
|
}
|
|
60711
60912
|
function publishedChannelsFile(override) {
|
|
60712
|
-
return
|
|
60913
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
60713
60914
|
}
|
|
60714
60915
|
function bundleCacheRoot(override) {
|
|
60715
|
-
return
|
|
60916
|
+
return import_node_path56.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
60716
60917
|
}
|
|
60717
60918
|
|
|
60718
60919
|
// src/extension/install-flow.ts
|
|
@@ -60739,7 +60940,7 @@ async function installFromChannel(args, deps) {
|
|
|
60739
60940
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60740
60941
|
}
|
|
60741
60942
|
for (const name of Object.keys(zip.files)) {
|
|
60742
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
60943
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path57.default.isAbsolute(name)) {
|
|
60743
60944
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
60744
60945
|
}
|
|
60745
60946
|
}
|
|
@@ -60771,7 +60972,7 @@ async function installFromChannel(args, deps) {
|
|
|
60771
60972
|
);
|
|
60772
60973
|
}
|
|
60773
60974
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
60774
|
-
const destDir =
|
|
60975
|
+
const destDir = import_node_path57.default.join(deps.extensionsRoot, localExtId);
|
|
60775
60976
|
let destExists = false;
|
|
60776
60977
|
try {
|
|
60777
60978
|
await import_promises9.default.access(destDir);
|
|
@@ -60785,16 +60986,16 @@ async function installFromChannel(args, deps) {
|
|
|
60785
60986
|
);
|
|
60786
60987
|
}
|
|
60787
60988
|
const stage = await import_promises9.default.mkdtemp(
|
|
60788
|
-
|
|
60989
|
+
import_node_path57.default.join(import_node_os21.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
60789
60990
|
);
|
|
60790
60991
|
try {
|
|
60791
60992
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60792
|
-
const dest =
|
|
60993
|
+
const dest = import_node_path57.default.join(stage, name);
|
|
60793
60994
|
if (entry.dir) {
|
|
60794
60995
|
await import_promises9.default.mkdir(dest, { recursive: true });
|
|
60795
60996
|
continue;
|
|
60796
60997
|
}
|
|
60797
|
-
await import_promises9.default.mkdir(
|
|
60998
|
+
await import_promises9.default.mkdir(import_node_path57.default.dirname(dest), { recursive: true });
|
|
60798
60999
|
if (name === "manifest.json") {
|
|
60799
61000
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60800
61001
|
await import_promises9.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -60815,8 +61016,8 @@ async function installFromChannel(args, deps) {
|
|
|
60815
61016
|
|
|
60816
61017
|
// src/extension/update-flow.ts
|
|
60817
61018
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
60818
|
-
var
|
|
60819
|
-
var
|
|
61019
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
61020
|
+
var import_node_os22 = __toESM(require("os"), 1);
|
|
60820
61021
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
60821
61022
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
60822
61023
|
var UpdateError = class extends Error {
|
|
@@ -60832,11 +61033,11 @@ async function updateFromChannel(args, deps) {
|
|
|
60832
61033
|
channelRef.extId,
|
|
60833
61034
|
channelRef.ownerPrincipalId
|
|
60834
61035
|
);
|
|
60835
|
-
const liveDir =
|
|
61036
|
+
const liveDir = import_node_path58.default.join(deps.extensionsRoot, localExtId);
|
|
60836
61037
|
const prevDir = `${liveDir}.prev`;
|
|
60837
61038
|
let existingVersion;
|
|
60838
61039
|
try {
|
|
60839
|
-
const raw = await import_promises10.default.readFile(
|
|
61040
|
+
const raw = await import_promises10.default.readFile(import_node_path58.default.join(liveDir, "manifest.json"), "utf8");
|
|
60840
61041
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
60841
61042
|
if (!parsed2.success) {
|
|
60842
61043
|
throw new UpdateError(
|
|
@@ -60869,7 +61070,7 @@ async function updateFromChannel(args, deps) {
|
|
|
60869
61070
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
60870
61071
|
}
|
|
60871
61072
|
for (const name of Object.keys(zip.files)) {
|
|
60872
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
61073
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path58.default.isAbsolute(name)) {
|
|
60873
61074
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
60874
61075
|
}
|
|
60875
61076
|
}
|
|
@@ -60904,16 +61105,16 @@ async function updateFromChannel(args, deps) {
|
|
|
60904
61105
|
await import_promises10.default.rm(prevDir, { recursive: true, force: true });
|
|
60905
61106
|
await import_promises10.default.rename(liveDir, prevDir);
|
|
60906
61107
|
const stage = await import_promises10.default.mkdtemp(
|
|
60907
|
-
|
|
61108
|
+
import_node_path58.default.join(import_node_os22.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
60908
61109
|
);
|
|
60909
61110
|
try {
|
|
60910
61111
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
60911
|
-
const dest =
|
|
61112
|
+
const dest = import_node_path58.default.join(stage, name);
|
|
60912
61113
|
if (entry.dir) {
|
|
60913
61114
|
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
60914
61115
|
continue;
|
|
60915
61116
|
}
|
|
60916
|
-
await import_promises10.default.mkdir(
|
|
61117
|
+
await import_promises10.default.mkdir(import_node_path58.default.dirname(dest), { recursive: true });
|
|
60917
61118
|
if (name === "manifest.json") {
|
|
60918
61119
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
60919
61120
|
await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -60980,7 +61181,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
60980
61181
|
);
|
|
60981
61182
|
}
|
|
60982
61183
|
}
|
|
60983
|
-
const manifestPath =
|
|
61184
|
+
const manifestPath = import_node_path59.default.join(root, extId, "manifest.json");
|
|
60984
61185
|
const manifest = await readManifest(root, extId);
|
|
60985
61186
|
const next = { ...manifest, version: newVersion };
|
|
60986
61187
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -60988,7 +61189,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
60988
61189
|
await import_promises11.default.rename(tmp, manifestPath);
|
|
60989
61190
|
}
|
|
60990
61191
|
async function readManifest(root, extId) {
|
|
60991
|
-
const file =
|
|
61192
|
+
const file = import_node_path59.default.join(root, extId, "manifest.json");
|
|
60992
61193
|
let raw;
|
|
60993
61194
|
try {
|
|
60994
61195
|
raw = await import_promises11.default.readFile(file, "utf8");
|
|
@@ -61072,7 +61273,7 @@ function buildExtensionHandlers(deps) {
|
|
|
61072
61273
|
};
|
|
61073
61274
|
async function buildSnapshotMeta(extId) {
|
|
61074
61275
|
const manifest = await readManifest(deps.root, extId);
|
|
61075
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
61276
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path59.default.join(deps.root, extId));
|
|
61076
61277
|
return { manifest, contentHash: sha256, buffer };
|
|
61077
61278
|
}
|
|
61078
61279
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -61247,9 +61448,9 @@ function buildExtensionHandlers(deps) {
|
|
|
61247
61448
|
}
|
|
61248
61449
|
|
|
61249
61450
|
// src/app-builder/project-store.ts
|
|
61250
|
-
var
|
|
61251
|
-
var
|
|
61252
|
-
var
|
|
61451
|
+
var import_node_fs49 = require("fs");
|
|
61452
|
+
var import_node_child_process14 = require("child_process");
|
|
61453
|
+
var import_node_path60 = require("path");
|
|
61253
61454
|
init_protocol();
|
|
61254
61455
|
var PROJECTS_DIR = "projects";
|
|
61255
61456
|
var META_FILE = ".clawd-project.json";
|
|
@@ -61263,19 +61464,19 @@ var ProjectStore = class {
|
|
|
61263
61464
|
root;
|
|
61264
61465
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
61265
61466
|
metaPath(name) {
|
|
61266
|
-
return (0,
|
|
61467
|
+
return (0, import_node_path60.join)(this.projectsRoot(), name, META_FILE);
|
|
61267
61468
|
}
|
|
61268
61469
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
61269
61470
|
projectDir(name) {
|
|
61270
|
-
return (0,
|
|
61471
|
+
return (0, import_node_path60.join)(this.projectsRoot(), name);
|
|
61271
61472
|
}
|
|
61272
61473
|
projectsRoot() {
|
|
61273
|
-
return (0,
|
|
61474
|
+
return (0, import_node_path60.join)(this.root, PROJECTS_DIR);
|
|
61274
61475
|
}
|
|
61275
61476
|
async list() {
|
|
61276
61477
|
let entries;
|
|
61277
61478
|
try {
|
|
61278
|
-
entries = await
|
|
61479
|
+
entries = await import_node_fs49.promises.readdir(this.projectsRoot());
|
|
61279
61480
|
} catch (err) {
|
|
61280
61481
|
if (err.code === "ENOENT") return [];
|
|
61281
61482
|
throw err;
|
|
@@ -61283,7 +61484,7 @@ var ProjectStore = class {
|
|
|
61283
61484
|
const out = [];
|
|
61284
61485
|
for (const name of entries) {
|
|
61285
61486
|
try {
|
|
61286
|
-
const raw = await
|
|
61487
|
+
const raw = await import_node_fs49.promises.readFile(this.metaPath(name), "utf8");
|
|
61287
61488
|
const json = JSON.parse(raw);
|
|
61288
61489
|
let migrated = false;
|
|
61289
61490
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -61294,7 +61495,7 @@ var ProjectStore = class {
|
|
|
61294
61495
|
if (parsed.success) {
|
|
61295
61496
|
out.push(parsed.data);
|
|
61296
61497
|
if (migrated) {
|
|
61297
|
-
void
|
|
61498
|
+
void import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
61298
61499
|
});
|
|
61299
61500
|
}
|
|
61300
61501
|
}
|
|
@@ -61338,8 +61539,8 @@ var ProjectStore = class {
|
|
|
61338
61539
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
61339
61540
|
}
|
|
61340
61541
|
const dir = this.projectDir(name);
|
|
61341
|
-
await
|
|
61342
|
-
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");
|
|
61343
61544
|
return meta;
|
|
61344
61545
|
}
|
|
61345
61546
|
/**
|
|
@@ -61353,7 +61554,7 @@ var ProjectStore = class {
|
|
|
61353
61554
|
async scaffold(name, templateSrcDir, scaffoldScriptPath) {
|
|
61354
61555
|
const destDir = this.projectDir(name);
|
|
61355
61556
|
return await new Promise((resolve6, reject) => {
|
|
61356
|
-
const child = (0,
|
|
61557
|
+
const child = (0, import_node_child_process14.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
61357
61558
|
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
61358
61559
|
stdio: ["ignore", "pipe", "pipe"]
|
|
61359
61560
|
});
|
|
@@ -61382,7 +61583,7 @@ var ProjectStore = class {
|
|
|
61382
61583
|
}
|
|
61383
61584
|
async delete(name) {
|
|
61384
61585
|
const dir = this.projectDir(name);
|
|
61385
|
-
await
|
|
61586
|
+
await import_node_fs49.promises.rm(dir, { recursive: true, force: true });
|
|
61386
61587
|
}
|
|
61387
61588
|
async updatePort(name, newPort) {
|
|
61388
61589
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -61398,7 +61599,7 @@ var ProjectStore = class {
|
|
|
61398
61599
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
61399
61600
|
}
|
|
61400
61601
|
const updated = { ...target, port: newPort };
|
|
61401
|
-
await
|
|
61602
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
61402
61603
|
return updated;
|
|
61403
61604
|
}
|
|
61404
61605
|
/**
|
|
@@ -61415,7 +61616,7 @@ var ProjectStore = class {
|
|
|
61415
61616
|
if (!validated.success) {
|
|
61416
61617
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
61417
61618
|
}
|
|
61418
|
-
await
|
|
61619
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61419
61620
|
return validated.data;
|
|
61420
61621
|
}
|
|
61421
61622
|
/**
|
|
@@ -61436,7 +61637,7 @@ var ProjectStore = class {
|
|
|
61436
61637
|
if (!validated.success) {
|
|
61437
61638
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
61438
61639
|
}
|
|
61439
|
-
await
|
|
61640
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61440
61641
|
return validated.data;
|
|
61441
61642
|
}
|
|
61442
61643
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -61451,13 +61652,13 @@ var ProjectStore = class {
|
|
|
61451
61652
|
if (!validated.success) {
|
|
61452
61653
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
61453
61654
|
}
|
|
61454
|
-
await
|
|
61655
|
+
await import_node_fs49.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
61455
61656
|
return validated.data;
|
|
61456
61657
|
}
|
|
61457
61658
|
};
|
|
61458
61659
|
|
|
61459
61660
|
// src/app-builder/kill-port.ts
|
|
61460
|
-
var
|
|
61661
|
+
var import_node_child_process15 = require("child_process");
|
|
61461
61662
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
61462
61663
|
let pids;
|
|
61463
61664
|
try {
|
|
@@ -61499,7 +61700,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
61499
61700
|
}
|
|
61500
61701
|
function listPidsOnPort(port) {
|
|
61501
61702
|
return new Promise((resolve6, reject) => {
|
|
61502
|
-
(0,
|
|
61703
|
+
(0, import_node_child_process15.execFile)(
|
|
61503
61704
|
"lsof",
|
|
61504
61705
|
["-ti", `:${port}`],
|
|
61505
61706
|
{ timeout: 3e3 },
|
|
@@ -61571,9 +61772,9 @@ var PublishJobRegistry = class {
|
|
|
61571
61772
|
};
|
|
61572
61773
|
|
|
61573
61774
|
// src/app-builder/publish-job-runner.ts
|
|
61574
|
-
var
|
|
61575
|
-
var
|
|
61576
|
-
var
|
|
61775
|
+
var import_node_child_process16 = require("child_process");
|
|
61776
|
+
var import_node_fs50 = require("fs");
|
|
61777
|
+
var import_node_path61 = require("path");
|
|
61577
61778
|
|
|
61578
61779
|
// src/app-builder/publish-stage-parser.ts
|
|
61579
61780
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -61600,19 +61801,19 @@ function tailStderrLines(buf, n) {
|
|
|
61600
61801
|
// src/app-builder/publish-job-runner.ts
|
|
61601
61802
|
async function startPublishJob(deps, args) {
|
|
61602
61803
|
const { registry: registry2, projectDir } = deps;
|
|
61603
|
-
const
|
|
61804
|
+
const spawn13 = deps.spawnImpl ?? import_node_child_process16.spawn;
|
|
61604
61805
|
if (registry2.has(args.name)) {
|
|
61605
61806
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
61606
61807
|
}
|
|
61607
61808
|
const projDir = projectDir(args.name);
|
|
61608
|
-
const logPath = (0,
|
|
61809
|
+
const logPath = (0, import_node_path61.join)(projDir, ".publish.log");
|
|
61609
61810
|
let logStream = null;
|
|
61610
61811
|
try {
|
|
61611
|
-
logStream = (0,
|
|
61812
|
+
logStream = (0, import_node_fs50.createWriteStream)(logPath, { flags: "w" });
|
|
61612
61813
|
} catch {
|
|
61613
61814
|
logStream = null;
|
|
61614
61815
|
}
|
|
61615
|
-
const child =
|
|
61816
|
+
const child = spawn13("bash", [args.scriptPath, projDir, args.personaRoot ?? ""], {
|
|
61616
61817
|
cwd: projDir,
|
|
61617
61818
|
env: process.env,
|
|
61618
61819
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -61865,8 +62066,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
61865
62066
|
|
|
61866
62067
|
// src/handlers/app-builder.ts
|
|
61867
62068
|
init_protocol();
|
|
61868
|
-
var
|
|
61869
|
-
var
|
|
62069
|
+
var import_node_path62 = require("path");
|
|
62070
|
+
var import_node_fs51 = require("fs");
|
|
61870
62071
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
61871
62072
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
61872
62073
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -61947,7 +62148,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
61947
62148
|
async function listAllUsersProjects() {
|
|
61948
62149
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
61949
62150
|
const getStore = deps.getStore;
|
|
61950
|
-
const userIds = await
|
|
62151
|
+
const userIds = await import_node_fs51.promises.readdir(deps.usersRoot).catch(() => []);
|
|
61951
62152
|
const perUser = await Promise.all(
|
|
61952
62153
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
61953
62154
|
);
|
|
@@ -62016,8 +62217,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
62016
62217
|
const project = await userStore.create(f.name, reservedPorts);
|
|
62017
62218
|
try {
|
|
62018
62219
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
62019
|
-
const templateSrcDir = (0,
|
|
62020
|
-
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");
|
|
62021
62222
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
62022
62223
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
62023
62224
|
name: project.name,
|
|
@@ -62221,7 +62422,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
62221
62422
|
await userStore.clearPublishJob(args.name);
|
|
62222
62423
|
}
|
|
62223
62424
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
62224
|
-
const scriptPath = (0,
|
|
62425
|
+
const scriptPath = (0, import_node_path62.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
62225
62426
|
deps.logger?.info("app-builder.publish.start", {
|
|
62226
62427
|
name: args.name,
|
|
62227
62428
|
sessionId: boundSession.sessionId,
|
|
@@ -62641,7 +62842,7 @@ function buildVisitorHandlers(deps) {
|
|
|
62641
62842
|
|
|
62642
62843
|
// src/extension/registry.ts
|
|
62643
62844
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62644
|
-
var
|
|
62845
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
62645
62846
|
async function loadAll(root) {
|
|
62646
62847
|
let entries;
|
|
62647
62848
|
try {
|
|
@@ -62654,13 +62855,13 @@ async function loadAll(root) {
|
|
|
62654
62855
|
for (const ent of entries) {
|
|
62655
62856
|
if (!ent.isDirectory()) continue;
|
|
62656
62857
|
if (ent.name.startsWith(".")) continue;
|
|
62657
|
-
records.push(await loadOne(
|
|
62858
|
+
records.push(await loadOne(import_node_path63.default.join(root, ent.name), ent.name));
|
|
62658
62859
|
}
|
|
62659
62860
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
62660
62861
|
return records;
|
|
62661
62862
|
}
|
|
62662
62863
|
async function loadOne(dir, dirName) {
|
|
62663
|
-
const manifestPath =
|
|
62864
|
+
const manifestPath = import_node_path63.default.join(dir, "manifest.json");
|
|
62664
62865
|
let raw;
|
|
62665
62866
|
try {
|
|
62666
62867
|
raw = await import_promises12.default.readFile(manifestPath, "utf8");
|
|
@@ -62705,7 +62906,7 @@ async function loadOne(dir, dirName) {
|
|
|
62705
62906
|
|
|
62706
62907
|
// src/extension/uninstall.ts
|
|
62707
62908
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
62708
|
-
var
|
|
62909
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
62709
62910
|
var UninstallError = class extends Error {
|
|
62710
62911
|
constructor(code, message) {
|
|
62711
62912
|
super(message);
|
|
@@ -62714,7 +62915,7 @@ var UninstallError = class extends Error {
|
|
|
62714
62915
|
code;
|
|
62715
62916
|
};
|
|
62716
62917
|
async function uninstall(deps) {
|
|
62717
|
-
const dir =
|
|
62918
|
+
const dir = import_node_path64.default.join(deps.root, deps.extId);
|
|
62718
62919
|
try {
|
|
62719
62920
|
await import_promises13.default.access(dir);
|
|
62720
62921
|
} catch {
|
|
@@ -62731,15 +62932,15 @@ var import_node_crypto19 = require("crypto");
|
|
|
62731
62932
|
init_protocol();
|
|
62732
62933
|
|
|
62733
62934
|
// src/peer-ops/run-command.ts
|
|
62734
|
-
var
|
|
62735
|
-
var
|
|
62935
|
+
var import_node_child_process17 = require("child_process");
|
|
62936
|
+
var import_node_os23 = __toESM(require("os"), 1);
|
|
62736
62937
|
var DEFAULT_TIMEOUT_MS4 = 3e4;
|
|
62737
62938
|
var MAX_TIMEOUT_MS = 3e5;
|
|
62738
62939
|
var MAX_OUTPUT_BYTES = 1048576;
|
|
62739
62940
|
function runCommand(command, opts = {}) {
|
|
62740
62941
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS4, MAX_TIMEOUT_MS);
|
|
62741
62942
|
return new Promise((resolve6) => {
|
|
62742
|
-
const child = (0,
|
|
62943
|
+
const child = (0, import_node_child_process17.spawn)("bash", ["-c", command], { cwd: import_node_os23.default.homedir() });
|
|
62743
62944
|
const out = [];
|
|
62744
62945
|
const err = [];
|
|
62745
62946
|
let outBytes = 0;
|
|
@@ -62958,14 +63159,14 @@ function buildMethodHandlers(deps) {
|
|
|
62958
63159
|
init_protocol();
|
|
62959
63160
|
|
|
62960
63161
|
// src/tools/version-probe.ts
|
|
62961
|
-
var
|
|
63162
|
+
var import_node_child_process18 = require("child_process");
|
|
62962
63163
|
init_claude();
|
|
62963
63164
|
function parseVersionOutput(out) {
|
|
62964
63165
|
return /(\d+\.\d+\.\d+)/.exec(out)?.[1];
|
|
62965
63166
|
}
|
|
62966
63167
|
function execVersion(bin) {
|
|
62967
63168
|
return new Promise((resolve6, reject) => {
|
|
62968
|
-
(0,
|
|
63169
|
+
(0, import_node_child_process18.execFile)(bin, ["--version"], { timeout: 5e3 }, (err, stdout) => {
|
|
62969
63170
|
if (err) reject(err);
|
|
62970
63171
|
else resolve6(String(stdout));
|
|
62971
63172
|
});
|
|
@@ -63076,7 +63277,7 @@ function buildOnboardingHandlers(deps) {
|
|
|
63076
63277
|
}
|
|
63077
63278
|
|
|
63078
63279
|
// src/app-builder/dev-server-supervisor.ts
|
|
63079
|
-
var
|
|
63280
|
+
var import_node_child_process19 = require("child_process");
|
|
63080
63281
|
var import_node_events2 = require("events");
|
|
63081
63282
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
63082
63283
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -63113,7 +63314,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
63113
63314
|
tunnelHost: args.tunnelHost,
|
|
63114
63315
|
devCommand: cmd
|
|
63115
63316
|
});
|
|
63116
|
-
const child = (0,
|
|
63317
|
+
const child = (0, import_node_child_process19.spawn)("sh", ["-c", cmd], {
|
|
63117
63318
|
cwd: args.cwd,
|
|
63118
63319
|
env,
|
|
63119
63320
|
stdio: "pipe",
|
|
@@ -63365,8 +63566,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
63365
63566
|
}
|
|
63366
63567
|
|
|
63367
63568
|
// src/extension/runtime.ts
|
|
63368
|
-
var
|
|
63369
|
-
var
|
|
63569
|
+
var import_node_child_process20 = require("child_process");
|
|
63570
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
63370
63571
|
var import_promises14 = require("timers/promises");
|
|
63371
63572
|
|
|
63372
63573
|
// src/extension/port-allocator.ts
|
|
@@ -63467,13 +63668,13 @@ var Runtime = class {
|
|
|
63467
63668
|
/\$CLAWOS_EXT_PORT/g,
|
|
63468
63669
|
String(port)
|
|
63469
63670
|
);
|
|
63470
|
-
const dir =
|
|
63671
|
+
const dir = import_node_path65.default.join(this.root, extId);
|
|
63471
63672
|
const env = {
|
|
63472
63673
|
...process.env,
|
|
63473
63674
|
CLAWOS_EXT_PORT: String(port),
|
|
63474
63675
|
CLAWOS_EXT_ID: extId
|
|
63475
63676
|
};
|
|
63476
|
-
const child = (0,
|
|
63677
|
+
const child = (0, import_node_child_process20.spawn)("sh", ["-c", cmd], {
|
|
63477
63678
|
cwd: dir,
|
|
63478
63679
|
env,
|
|
63479
63680
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -63579,7 +63780,7 @@ ${handle.stderrTail}`
|
|
|
63579
63780
|
|
|
63580
63781
|
// src/extension/published-channels.ts
|
|
63581
63782
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
63582
|
-
var
|
|
63783
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
63583
63784
|
init_zod();
|
|
63584
63785
|
var PublishedChannelsError = class extends Error {
|
|
63585
63786
|
constructor(code, message) {
|
|
@@ -63678,7 +63879,7 @@ var PublishedChannelStore = class {
|
|
|
63678
63879
|
)
|
|
63679
63880
|
};
|
|
63680
63881
|
const tmp = `${this.filePath}.tmp`;
|
|
63681
|
-
await import_promises15.default.mkdir(
|
|
63882
|
+
await import_promises15.default.mkdir(import_node_path66.default.dirname(this.filePath), { recursive: true });
|
|
63682
63883
|
await import_promises15.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
63683
63884
|
await import_promises15.default.rename(tmp, this.filePath);
|
|
63684
63885
|
}
|
|
@@ -63686,7 +63887,7 @@ var PublishedChannelStore = class {
|
|
|
63686
63887
|
|
|
63687
63888
|
// src/extension/bundle-cache.ts
|
|
63688
63889
|
var import_promises16 = __toESM(require("fs/promises"), 1);
|
|
63689
|
-
var
|
|
63890
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
63690
63891
|
var BundleCache = class {
|
|
63691
63892
|
constructor(rootDir) {
|
|
63692
63893
|
this.rootDir = rootDir;
|
|
@@ -63695,14 +63896,14 @@ var BundleCache = class {
|
|
|
63695
63896
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
63696
63897
|
async write(snapshotHash, buffer) {
|
|
63697
63898
|
await import_promises16.default.mkdir(this.rootDir, { recursive: true });
|
|
63698
|
-
const file =
|
|
63899
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63699
63900
|
const tmp = `${file}.tmp`;
|
|
63700
63901
|
await import_promises16.default.writeFile(tmp, buffer, { mode: 384 });
|
|
63701
63902
|
await import_promises16.default.rename(tmp, file);
|
|
63702
63903
|
}
|
|
63703
63904
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
63704
63905
|
async read(snapshotHash) {
|
|
63705
|
-
const file =
|
|
63906
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63706
63907
|
try {
|
|
63707
63908
|
return await import_promises16.default.readFile(file);
|
|
63708
63909
|
} catch (e) {
|
|
@@ -63712,7 +63913,7 @@ var BundleCache = class {
|
|
|
63712
63913
|
}
|
|
63713
63914
|
/** Idempotent — missing file is not an error. */
|
|
63714
63915
|
async delete(snapshotHash) {
|
|
63715
|
-
const file =
|
|
63916
|
+
const file = import_node_path67.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
63716
63917
|
await import_promises16.default.rm(file, { force: true });
|
|
63717
63918
|
}
|
|
63718
63919
|
};
|
|
@@ -63733,26 +63934,26 @@ async function startDaemon(config) {
|
|
|
63733
63934
|
},
|
|
63734
63935
|
source: "daemon",
|
|
63735
63936
|
sampling: logShippingCfg.sampling,
|
|
63736
|
-
homeDir:
|
|
63937
|
+
homeDir: import_node_os24.default.homedir()
|
|
63737
63938
|
});
|
|
63738
|
-
const logDir =
|
|
63739
|
-
|
|
63939
|
+
const logDir = import_node_path68.default.join(config.dataDir, "log");
|
|
63940
|
+
import_node_fs52.default.mkdirSync(logDir, { recursive: true });
|
|
63740
63941
|
const logger = createLogger({
|
|
63741
63942
|
level: config.logLevel,
|
|
63742
|
-
file:
|
|
63943
|
+
file: import_node_path68.default.join(logDir, "clawd.log"),
|
|
63743
63944
|
logClient
|
|
63744
63945
|
});
|
|
63745
63946
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
63746
63947
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
63747
|
-
file:
|
|
63948
|
+
file: import_node_path68.default.join(logDir, "screen-idle-probe.log"),
|
|
63748
63949
|
level: "debug"
|
|
63749
63950
|
});
|
|
63750
63951
|
logger.info("screen-idle probe logger enabled", {
|
|
63751
|
-
file:
|
|
63952
|
+
file: import_node_path68.default.join(logDir, "screen-idle-probe.log")
|
|
63752
63953
|
});
|
|
63753
63954
|
const CAP_TARGETS = [
|
|
63754
|
-
|
|
63755
|
-
|
|
63955
|
+
import_node_path68.default.join(logDir, "clawd.log"),
|
|
63956
|
+
import_node_path68.default.join(logDir, "screen-idle-probe.log")
|
|
63756
63957
|
];
|
|
63757
63958
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
63758
63959
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -63848,8 +64049,8 @@ async function startDaemon(config) {
|
|
|
63848
64049
|
const agents = new AgentsScanner();
|
|
63849
64050
|
const history = new ClaudeHistoryReader();
|
|
63850
64051
|
let transport = null;
|
|
63851
|
-
const personaStore = new PersonaStore(
|
|
63852
|
-
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");
|
|
63853
64054
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
63854
64055
|
if (defaultsRoot) {
|
|
63855
64056
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -63872,7 +64073,7 @@ async function startDaemon(config) {
|
|
|
63872
64073
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
63873
64074
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
63874
64075
|
const dispatchStore = createDispatchStore({
|
|
63875
|
-
filePath:
|
|
64076
|
+
filePath: import_node_path68.default.join(config.dataDir, "dispatch.json"),
|
|
63876
64077
|
now: () => Date.now(),
|
|
63877
64078
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
63878
64079
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -63887,18 +64088,18 @@ async function startDaemon(config) {
|
|
|
63887
64088
|
now: () => Date.now(),
|
|
63888
64089
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
63889
64090
|
});
|
|
63890
|
-
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));
|
|
63891
64092
|
const mcpConfigs = [];
|
|
63892
64093
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
63893
64094
|
const dispatchServerCandidates = [
|
|
63894
|
-
|
|
64095
|
+
import_node_path68.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
63895
64096
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
63896
|
-
|
|
64097
|
+
import_node_path68.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
63897
64098
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
63898
64099
|
];
|
|
63899
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
64100
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63900
64101
|
if (dispatchServerScriptPath) {
|
|
63901
|
-
const dispatchLogPath =
|
|
64102
|
+
const dispatchLogPath = import_node_path68.default.join(logDir, "dispatch-mcp-server.log");
|
|
63902
64103
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
63903
64104
|
dataDir: config.dataDir,
|
|
63904
64105
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -63918,12 +64119,12 @@ async function startDaemon(config) {
|
|
|
63918
64119
|
});
|
|
63919
64120
|
}
|
|
63920
64121
|
const ticketServerCandidates = [
|
|
63921
|
-
|
|
63922
|
-
|
|
64122
|
+
import_node_path68.default.join(here, "ticket", "mcp-server.cjs"),
|
|
64123
|
+
import_node_path68.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
63923
64124
|
];
|
|
63924
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
64125
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63925
64126
|
if (ticketServerScriptPath) {
|
|
63926
|
-
const ticketLogPath =
|
|
64127
|
+
const ticketLogPath = import_node_path68.default.join(logDir, "ticket-mcp-server.log");
|
|
63927
64128
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
63928
64129
|
dataDir: config.dataDir,
|
|
63929
64130
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -63945,12 +64146,12 @@ async function startDaemon(config) {
|
|
|
63945
64146
|
});
|
|
63946
64147
|
}
|
|
63947
64148
|
const shiftServerCandidates = [
|
|
63948
|
-
|
|
63949
|
-
|
|
64149
|
+
import_node_path68.default.join(here, "shift", "mcp-server.cjs"),
|
|
64150
|
+
import_node_path68.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
63950
64151
|
];
|
|
63951
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
64152
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63952
64153
|
if (shiftServerScriptPath) {
|
|
63953
|
-
const shiftLogPath =
|
|
64154
|
+
const shiftLogPath = import_node_path68.default.join(logDir, "shift-mcp-server.log");
|
|
63954
64155
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
63955
64156
|
dataDir: config.dataDir,
|
|
63956
64157
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -63971,12 +64172,12 @@ async function startDaemon(config) {
|
|
|
63971
64172
|
);
|
|
63972
64173
|
}
|
|
63973
64174
|
const inboxServerCandidates = [
|
|
63974
|
-
|
|
63975
|
-
|
|
64175
|
+
import_node_path68.default.join(here, "inbox", "mcp-server.cjs"),
|
|
64176
|
+
import_node_path68.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
63976
64177
|
];
|
|
63977
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
64178
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
63978
64179
|
if (inboxServerScriptPath) {
|
|
63979
|
-
const inboxLogPath =
|
|
64180
|
+
const inboxLogPath = import_node_path68.default.join(logDir, "inbox-mcp-server.log");
|
|
63980
64181
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
63981
64182
|
dataDir: config.dataDir,
|
|
63982
64183
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -63997,10 +64198,10 @@ async function startDaemon(config) {
|
|
|
63997
64198
|
);
|
|
63998
64199
|
}
|
|
63999
64200
|
const peerOpsServerCandidates = [
|
|
64000
|
-
|
|
64001
|
-
|
|
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")
|
|
64002
64203
|
];
|
|
64003
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
64204
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64004
64205
|
if (peerOpsServerScriptPath) {
|
|
64005
64206
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
64006
64207
|
dataDir: config.dataDir,
|
|
@@ -64020,12 +64221,12 @@ async function startDaemon(config) {
|
|
|
64020
64221
|
);
|
|
64021
64222
|
}
|
|
64022
64223
|
const rpcToolServerCandidates = [
|
|
64023
|
-
|
|
64024
|
-
|
|
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")
|
|
64025
64226
|
];
|
|
64026
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
64227
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs52.default.existsSync(p2));
|
|
64027
64228
|
if (rpcToolServerScriptPath) {
|
|
64028
|
-
const rpcToolLogPath =
|
|
64229
|
+
const rpcToolLogPath = import_node_path68.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
64029
64230
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
64030
64231
|
dataDir: config.dataDir,
|
|
64031
64232
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -64046,7 +64247,7 @@ async function startDaemon(config) {
|
|
|
64046
64247
|
);
|
|
64047
64248
|
}
|
|
64048
64249
|
const shiftStore = createShiftStore({
|
|
64049
|
-
filePath:
|
|
64250
|
+
filePath: import_node_path68.default.join(config.dataDir, "shift.json"),
|
|
64050
64251
|
ownerIdProvider: () => ownerPrincipalId,
|
|
64051
64252
|
now: () => Date.now()
|
|
64052
64253
|
});
|
|
@@ -64068,7 +64269,7 @@ async function startDaemon(config) {
|
|
|
64068
64269
|
getAdapter,
|
|
64069
64270
|
historyReader: history,
|
|
64070
64271
|
dataDir: config.dataDir,
|
|
64071
|
-
personaRoot:
|
|
64272
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64072
64273
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
64073
64274
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
64074
64275
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -64100,6 +64301,9 @@ async function startDaemon(config) {
|
|
|
64100
64301
|
// daemon 级 MCP server 登记表(dispatch / ticket / shift / inbox / ...,上方各 writer
|
|
64101
64302
|
// 块写盘成功即登记);reducer 透传到 SpawnContext.mcpConfigs,cc spawn 逐项 --mcp-config。
|
|
64102
64303
|
mcpConfigs,
|
|
64304
|
+
// 会话标题自产(首条 send 并行 fire,claude→haiku / codex→gpt-5.4-mini)。
|
|
64305
|
+
// 不注入 = 功能关(manager 测试默认关闭防烧真调用),这里是唯一的生产装配点。
|
|
64306
|
+
generateTitle: (tool, firstMessage) => generateSessionTitle(tool, firstMessage, { logger }),
|
|
64103
64307
|
broadcastFrame: (frame, target) => {
|
|
64104
64308
|
if (target === "all") {
|
|
64105
64309
|
transport?.broadcastAll(frame);
|
|
@@ -64119,10 +64323,10 @@ async function startDaemon(config) {
|
|
|
64119
64323
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
64120
64324
|
attachmentGroup: {
|
|
64121
64325
|
onFileEdit: (input) => {
|
|
64122
|
-
const absPath =
|
|
64326
|
+
const absPath = import_node_path68.default.isAbsolute(input.relPath) ? input.relPath : import_node_path68.default.join(input.cwd, input.relPath);
|
|
64123
64327
|
let size = 0;
|
|
64124
64328
|
try {
|
|
64125
|
-
size =
|
|
64329
|
+
size = import_node_fs52.default.statSync(absPath).size;
|
|
64126
64330
|
} catch (err) {
|
|
64127
64331
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
64128
64332
|
sessionId: input.sessionId,
|
|
@@ -64390,11 +64594,11 @@ async function startDaemon(config) {
|
|
|
64390
64594
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
64391
64595
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
64392
64596
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
64393
|
-
personaRoot:
|
|
64597
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64394
64598
|
usersRoot
|
|
64395
64599
|
},
|
|
64396
64600
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
64397
|
-
personaRoot:
|
|
64601
|
+
personaRoot: import_node_path68.default.join(config.dataDir, "personas"),
|
|
64398
64602
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
64399
64603
|
usersRoot,
|
|
64400
64604
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -64520,11 +64724,11 @@ async function startDaemon(config) {
|
|
|
64520
64724
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
64521
64725
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
64522
64726
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
64523
|
-
appBuilderPersonaRoot:
|
|
64727
|
+
appBuilderPersonaRoot: import_node_path68.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
64524
64728
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
64525
|
-
deployKitRoot:
|
|
64729
|
+
deployKitRoot: import_node_path68.default.join(config.dataDir, "deploy-kit"),
|
|
64526
64730
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
64527
|
-
resolvePersonaRoot: (personaId2) =>
|
|
64731
|
+
resolvePersonaRoot: (personaId2) => import_node_path68.default.join(config.dataDir, "personas", personaId2),
|
|
64528
64732
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
64529
64733
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
64530
64734
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -64567,7 +64771,7 @@ async function startDaemon(config) {
|
|
|
64567
64771
|
sourceSessionId: args.sourceSessionId
|
|
64568
64772
|
});
|
|
64569
64773
|
const sourceFile = manager.findOwnedSession(args.sourceSessionId);
|
|
64570
|
-
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile,
|
|
64774
|
+
const sourceJsonlPath = resolveSourceJsonlPath(sourceFile, import_node_os24.default.homedir());
|
|
64571
64775
|
logger.info("dispatch.spawnB.source-resolved", {
|
|
64572
64776
|
dispatchId: args.dispatchId,
|
|
64573
64777
|
sourceJsonlPath,
|
|
@@ -64629,7 +64833,7 @@ async function startDaemon(config) {
|
|
|
64629
64833
|
});
|
|
64630
64834
|
shiftScheduler.start();
|
|
64631
64835
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
64632
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
64836
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path68.default.join(config.dataDir, "personas"));
|
|
64633
64837
|
const larkBotCloud = createLarkBotCloudClient({
|
|
64634
64838
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
64635
64839
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -64643,7 +64847,7 @@ async function startDaemon(config) {
|
|
|
64643
64847
|
store: larkBotStore,
|
|
64644
64848
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
64645
64849
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
64646
|
-
mediaRootFor: (chatId) =>
|
|
64850
|
+
mediaRootFor: (chatId) => import_node_path68.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
64647
64851
|
isShuttingDown: () => larkDraining,
|
|
64648
64852
|
logger: {
|
|
64649
64853
|
warn: (msg) => logger.warn(msg),
|
|
@@ -64947,8 +65151,8 @@ async function startDaemon(config) {
|
|
|
64947
65151
|
const lines = [
|
|
64948
65152
|
`Tunnel: ${r.url}`,
|
|
64949
65153
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
64950
|
-
`Frpc config: ${
|
|
64951
|
-
`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")}`
|
|
64952
65156
|
];
|
|
64953
65157
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
64954
65158
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -64961,8 +65165,8 @@ ${bar}
|
|
|
64961
65165
|
|
|
64962
65166
|
`);
|
|
64963
65167
|
try {
|
|
64964
|
-
const connectPath =
|
|
64965
|
-
|
|
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 });
|
|
64966
65170
|
} catch {
|
|
64967
65171
|
}
|
|
64968
65172
|
} catch (err) {
|
|
@@ -65037,9 +65241,9 @@ ${bar}
|
|
|
65037
65241
|
};
|
|
65038
65242
|
}
|
|
65039
65243
|
function migrateDropPersonsDir(dataDir) {
|
|
65040
|
-
const dir =
|
|
65244
|
+
const dir = import_node_path68.default.join(dataDir, "persons");
|
|
65041
65245
|
try {
|
|
65042
|
-
|
|
65246
|
+
import_node_fs52.default.rmSync(dir, { recursive: true, force: true });
|
|
65043
65247
|
} catch {
|
|
65044
65248
|
}
|
|
65045
65249
|
}
|