@clawos-dev/clawd 0.2.383 → 0.2.384
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: path90, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path90, ...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, path90, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path90;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -6192,11 +6192,21 @@ var init_dispatch = __esm({
|
|
|
6192
6192
|
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
6193
6193
|
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
6194
6194
|
targetDeviceId: external_exports.string().min(1).optional(),
|
|
6195
|
-
// 可选:override B session
|
|
6196
|
-
//
|
|
6197
|
-
//
|
|
6198
|
-
// protocol 层保持 string
|
|
6195
|
+
// 可选:override B session 使用的模型。缺省 = 用 persona 默认。
|
|
6196
|
+
// 合法值集**从属于 tool**(见下面的 tool 字段):claude 侧与 tools/claude.ts
|
|
6197
|
+
// CLAUDE_MODEL_IDS 一致,codex 侧是运行时查来的模型表;handler 层做二次校验,
|
|
6198
|
+
// 非法值 fail-fast。protocol 层保持 string(不在协议里钉死枚举)。
|
|
6199
|
+
// **只能用于新开 dispatch**:续派不改任何 spawn 参数(worker session 已经跑起来了),
|
|
6200
|
+
// 与 dispatchId 互斥(下方 refine 硬拒)。
|
|
6199
6201
|
model: external_exports.string().min(1).optional(),
|
|
6202
|
+
// 可选:override B session 使用的 agent tool(engine)。缺省 = 用 persona 绑定的 tool。
|
|
6203
|
+
// 语义是**一次性**——不改 persona 的持久绑定,只决定这条 dispatch 起的 worker session。
|
|
6204
|
+
// 为什么需要:`model` 的合法值集从属于 tool,想让一个 claude persona 这次用
|
|
6205
|
+
// `gpt-5.6-sol` 干活,必须能连 engine 一起换(否则 model 校验按 persona.tool 选表直接拒)。
|
|
6206
|
+
// 合法值集 = daemon 的 adapter 注册表('claude' / 'codex'),handler 层运行时校验;
|
|
6207
|
+
// protocol 层保持 string(与 model / SessionFile.tool 同款处理,不在协议里钉死枚举)。
|
|
6208
|
+
// 与 model 同样**只能用于新开 dispatch**(下方 refine 硬拒 dispatchId 组合)。
|
|
6209
|
+
tool: external_exports.string().min(1).optional(),
|
|
6200
6210
|
// 可选:给新 worker session 起 label(写入 SessionFile.label,sidebar 显示)。
|
|
6201
6211
|
// 仅在**新开 dispatch**(dispatchId 缺席)时生效;续派(dispatchId 非空)
|
|
6202
6212
|
// 时 daemon 层静默丢弃(避免半途改 label 造成 sidebar 抖动)。
|
|
@@ -6211,6 +6221,10 @@ var init_dispatch = __esm({
|
|
|
6211
6221
|
message: "either targetPersona (new dispatch) or dispatchId (follow-up) is required"
|
|
6212
6222
|
}).refine((v2) => !(v2.dispatchId !== void 0 && v2.targetDeviceId !== void 0), {
|
|
6213
6223
|
message: "cross-device dispatch cannot be continued (dispatchId + targetDeviceId are mutually exclusive)"
|
|
6224
|
+
}).refine((v2) => !(v2.tool !== void 0 && v2.targetDeviceId !== void 0), {
|
|
6225
|
+
message: "engine override is not supported for cross-device dispatch (tool + targetDeviceId are mutually exclusive)"
|
|
6226
|
+
}).refine((v2) => !(v2.dispatchId !== void 0 && (v2.tool !== void 0 || v2.model !== void 0)), {
|
|
6227
|
+
message: "a follow-up dispatch cannot change engine or model (dispatchId excludes tool / model); start a new dispatch instead"
|
|
6214
6228
|
});
|
|
6215
6229
|
DispatchCompleteArgsSchema = external_exports.object({
|
|
6216
6230
|
dispatchId: external_exports.string().min(1),
|
|
@@ -9292,8 +9306,8 @@ var require_req = __commonJS({
|
|
|
9292
9306
|
if (req.originalUrl) {
|
|
9293
9307
|
_req.url = req.originalUrl;
|
|
9294
9308
|
} else {
|
|
9295
|
-
const
|
|
9296
|
-
_req.url = typeof
|
|
9309
|
+
const path90 = req.path;
|
|
9310
|
+
_req.url = typeof path90 === "string" ? path90 : req.url ? req.url.path || req.url : void 0;
|
|
9297
9311
|
}
|
|
9298
9312
|
if (req.query) {
|
|
9299
9313
|
_req.query = req.query;
|
|
@@ -9458,14 +9472,14 @@ var require_redact = __commonJS({
|
|
|
9458
9472
|
}
|
|
9459
9473
|
return obj;
|
|
9460
9474
|
}
|
|
9461
|
-
function parsePath(
|
|
9475
|
+
function parsePath(path90) {
|
|
9462
9476
|
const parts = [];
|
|
9463
9477
|
let current = "";
|
|
9464
9478
|
let inBrackets = false;
|
|
9465
9479
|
let inQuotes = false;
|
|
9466
9480
|
let quoteChar = "";
|
|
9467
|
-
for (let i = 0; i <
|
|
9468
|
-
const char =
|
|
9481
|
+
for (let i = 0; i < path90.length; i++) {
|
|
9482
|
+
const char = path90[i];
|
|
9469
9483
|
if (!inBrackets && char === ".") {
|
|
9470
9484
|
if (current) {
|
|
9471
9485
|
parts.push(current);
|
|
@@ -9596,10 +9610,10 @@ var require_redact = __commonJS({
|
|
|
9596
9610
|
return current;
|
|
9597
9611
|
}
|
|
9598
9612
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9599
|
-
for (const
|
|
9600
|
-
const parts = parsePath(
|
|
9613
|
+
for (const path90 of paths) {
|
|
9614
|
+
const parts = parsePath(path90);
|
|
9601
9615
|
if (parts.includes("*")) {
|
|
9602
|
-
redactWildcardPath(obj, parts, censor,
|
|
9616
|
+
redactWildcardPath(obj, parts, censor, path90, remove);
|
|
9603
9617
|
} else {
|
|
9604
9618
|
if (remove) {
|
|
9605
9619
|
removeKey(obj, parts);
|
|
@@ -9684,8 +9698,8 @@ var require_redact = __commonJS({
|
|
|
9684
9698
|
}
|
|
9685
9699
|
} else {
|
|
9686
9700
|
if (afterWildcard.includes("*")) {
|
|
9687
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9688
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9701
|
+
const wrappedCensor = typeof censor === "function" ? (value, path90) => {
|
|
9702
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path90];
|
|
9689
9703
|
return censor(value, fullPath);
|
|
9690
9704
|
} : censor;
|
|
9691
9705
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9720,8 +9734,8 @@ var require_redact = __commonJS({
|
|
|
9720
9734
|
return null;
|
|
9721
9735
|
}
|
|
9722
9736
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9723
|
-
for (const
|
|
9724
|
-
const parts = parsePath(
|
|
9737
|
+
for (const path90 of pathsToClone) {
|
|
9738
|
+
const parts = parsePath(path90);
|
|
9725
9739
|
let current = pathStructure;
|
|
9726
9740
|
for (let i = 0; i < parts.length; i++) {
|
|
9727
9741
|
const part = parts[i];
|
|
@@ -9773,24 +9787,24 @@ var require_redact = __commonJS({
|
|
|
9773
9787
|
}
|
|
9774
9788
|
return cloneSelectively(obj, pathStructure);
|
|
9775
9789
|
}
|
|
9776
|
-
function validatePath(
|
|
9777
|
-
if (typeof
|
|
9790
|
+
function validatePath(path90) {
|
|
9791
|
+
if (typeof path90 !== "string") {
|
|
9778
9792
|
throw new Error("Paths must be (non-empty) strings");
|
|
9779
9793
|
}
|
|
9780
|
-
if (
|
|
9794
|
+
if (path90 === "") {
|
|
9781
9795
|
throw new Error("Invalid redaction path ()");
|
|
9782
9796
|
}
|
|
9783
|
-
if (
|
|
9784
|
-
throw new Error(`Invalid redaction path (${
|
|
9797
|
+
if (path90.includes("..")) {
|
|
9798
|
+
throw new Error(`Invalid redaction path (${path90})`);
|
|
9785
9799
|
}
|
|
9786
|
-
if (
|
|
9787
|
-
throw new Error(`Invalid redaction path (${
|
|
9800
|
+
if (path90.includes(",")) {
|
|
9801
|
+
throw new Error(`Invalid redaction path (${path90})`);
|
|
9788
9802
|
}
|
|
9789
9803
|
let bracketCount = 0;
|
|
9790
9804
|
let inQuotes = false;
|
|
9791
9805
|
let quoteChar = "";
|
|
9792
|
-
for (let i = 0; i <
|
|
9793
|
-
const char =
|
|
9806
|
+
for (let i = 0; i < path90.length; i++) {
|
|
9807
|
+
const char = path90[i];
|
|
9794
9808
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9795
9809
|
if (!inQuotes) {
|
|
9796
9810
|
inQuotes = true;
|
|
@@ -9804,20 +9818,20 @@ var require_redact = __commonJS({
|
|
|
9804
9818
|
} else if (char === "]" && !inQuotes) {
|
|
9805
9819
|
bracketCount--;
|
|
9806
9820
|
if (bracketCount < 0) {
|
|
9807
|
-
throw new Error(`Invalid redaction path (${
|
|
9821
|
+
throw new Error(`Invalid redaction path (${path90})`);
|
|
9808
9822
|
}
|
|
9809
9823
|
}
|
|
9810
9824
|
}
|
|
9811
9825
|
if (bracketCount !== 0) {
|
|
9812
|
-
throw new Error(`Invalid redaction path (${
|
|
9826
|
+
throw new Error(`Invalid redaction path (${path90})`);
|
|
9813
9827
|
}
|
|
9814
9828
|
}
|
|
9815
9829
|
function validatePaths(paths) {
|
|
9816
9830
|
if (!Array.isArray(paths)) {
|
|
9817
9831
|
throw new TypeError("paths must be an array");
|
|
9818
9832
|
}
|
|
9819
|
-
for (const
|
|
9820
|
-
validatePath(
|
|
9833
|
+
for (const path90 of paths) {
|
|
9834
|
+
validatePath(path90);
|
|
9821
9835
|
}
|
|
9822
9836
|
}
|
|
9823
9837
|
function slowRedact(options = {}) {
|
|
@@ -9985,8 +9999,8 @@ var require_redaction = __commonJS({
|
|
|
9985
9999
|
if (shape[k2] === null) {
|
|
9986
10000
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9987
10001
|
} else {
|
|
9988
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9989
|
-
return censor(value, [k2, ...
|
|
10002
|
+
const wrappedCensor = typeof censor === "function" ? (value, path90) => {
|
|
10003
|
+
return censor(value, [k2, ...path90]);
|
|
9990
10004
|
} : censor;
|
|
9991
10005
|
o[k2] = Redact({
|
|
9992
10006
|
paths: shape[k2],
|
|
@@ -10204,10 +10218,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
10204
10218
|
var require_sonic_boom = __commonJS({
|
|
10205
10219
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
10206
10220
|
"use strict";
|
|
10207
|
-
var
|
|
10221
|
+
var fs80 = require("fs");
|
|
10208
10222
|
var EventEmitter3 = require("events");
|
|
10209
10223
|
var inherits = require("util").inherits;
|
|
10210
|
-
var
|
|
10224
|
+
var path90 = require("path");
|
|
10211
10225
|
var sleep2 = require_atomic_sleep();
|
|
10212
10226
|
var assert = require("assert");
|
|
10213
10227
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -10261,20 +10275,20 @@ var require_sonic_boom = __commonJS({
|
|
|
10261
10275
|
const mode = sonic.mode;
|
|
10262
10276
|
if (sonic.sync) {
|
|
10263
10277
|
try {
|
|
10264
|
-
if (sonic.mkdir)
|
|
10265
|
-
const fd =
|
|
10278
|
+
if (sonic.mkdir) fs80.mkdirSync(path90.dirname(file), { recursive: true });
|
|
10279
|
+
const fd = fs80.openSync(file, flags, mode);
|
|
10266
10280
|
fileOpened(null, fd);
|
|
10267
10281
|
} catch (err) {
|
|
10268
10282
|
fileOpened(err);
|
|
10269
10283
|
throw err;
|
|
10270
10284
|
}
|
|
10271
10285
|
} else if (sonic.mkdir) {
|
|
10272
|
-
|
|
10286
|
+
fs80.mkdir(path90.dirname(file), { recursive: true }, (err) => {
|
|
10273
10287
|
if (err) return fileOpened(err);
|
|
10274
|
-
|
|
10288
|
+
fs80.open(file, flags, mode, fileOpened);
|
|
10275
10289
|
});
|
|
10276
10290
|
} else {
|
|
10277
|
-
|
|
10291
|
+
fs80.open(file, flags, mode, fileOpened);
|
|
10278
10292
|
}
|
|
10279
10293
|
}
|
|
10280
10294
|
function SonicBoom(opts) {
|
|
@@ -10315,8 +10329,8 @@ var require_sonic_boom = __commonJS({
|
|
|
10315
10329
|
this.flush = flushBuffer;
|
|
10316
10330
|
this.flushSync = flushBufferSync;
|
|
10317
10331
|
this._actualWrite = actualWriteBuffer;
|
|
10318
|
-
fsWriteSync = () =>
|
|
10319
|
-
fsWrite = () =>
|
|
10332
|
+
fsWriteSync = () => fs80.writeSync(this.fd, this._writingBuf);
|
|
10333
|
+
fsWrite = () => fs80.write(this.fd, this._writingBuf, this.release);
|
|
10320
10334
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
10321
10335
|
this._writingBuf = "";
|
|
10322
10336
|
this.write = write;
|
|
@@ -10325,15 +10339,15 @@ var require_sonic_boom = __commonJS({
|
|
|
10325
10339
|
this._actualWrite = actualWrite;
|
|
10326
10340
|
fsWriteSync = () => {
|
|
10327
10341
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10328
|
-
return
|
|
10342
|
+
return fs80.writeSync(this.fd, this._writingBuf);
|
|
10329
10343
|
}
|
|
10330
|
-
return
|
|
10344
|
+
return fs80.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10331
10345
|
};
|
|
10332
10346
|
fsWrite = () => {
|
|
10333
10347
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
10334
|
-
return
|
|
10348
|
+
return fs80.write(this.fd, this._writingBuf, this.release);
|
|
10335
10349
|
}
|
|
10336
|
-
return
|
|
10350
|
+
return fs80.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
10337
10351
|
};
|
|
10338
10352
|
} else {
|
|
10339
10353
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -10390,7 +10404,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10390
10404
|
}
|
|
10391
10405
|
}
|
|
10392
10406
|
if (this._fsync) {
|
|
10393
|
-
|
|
10407
|
+
fs80.fsyncSync(this.fd);
|
|
10394
10408
|
}
|
|
10395
10409
|
const len = this._len;
|
|
10396
10410
|
if (this._reopening) {
|
|
@@ -10504,7 +10518,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10504
10518
|
const onDrain = () => {
|
|
10505
10519
|
if (!this._fsync) {
|
|
10506
10520
|
try {
|
|
10507
|
-
|
|
10521
|
+
fs80.fsync(this.fd, (err) => {
|
|
10508
10522
|
this._flushPending = false;
|
|
10509
10523
|
cb(err);
|
|
10510
10524
|
});
|
|
@@ -10606,7 +10620,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10606
10620
|
const fd = this.fd;
|
|
10607
10621
|
this.once("ready", () => {
|
|
10608
10622
|
if (fd !== this.fd) {
|
|
10609
|
-
|
|
10623
|
+
fs80.close(fd, (err) => {
|
|
10610
10624
|
if (err) {
|
|
10611
10625
|
return this.emit("error", err);
|
|
10612
10626
|
}
|
|
@@ -10655,7 +10669,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10655
10669
|
buf = this._bufs[0];
|
|
10656
10670
|
}
|
|
10657
10671
|
try {
|
|
10658
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10672
|
+
const n = Buffer.isBuffer(buf) ? fs80.writeSync(this.fd, buf) : fs80.writeSync(this.fd, buf, "utf8");
|
|
10659
10673
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10660
10674
|
buf = releasedBufObj.writingBuf;
|
|
10661
10675
|
this._len = releasedBufObj.len;
|
|
@@ -10671,7 +10685,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10671
10685
|
}
|
|
10672
10686
|
}
|
|
10673
10687
|
try {
|
|
10674
|
-
|
|
10688
|
+
fs80.fsyncSync(this.fd);
|
|
10675
10689
|
} catch {
|
|
10676
10690
|
}
|
|
10677
10691
|
}
|
|
@@ -10692,7 +10706,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10692
10706
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10693
10707
|
}
|
|
10694
10708
|
try {
|
|
10695
|
-
const n =
|
|
10709
|
+
const n = fs80.writeSync(this.fd, buf);
|
|
10696
10710
|
buf = buf.subarray(n);
|
|
10697
10711
|
this._len = Math.max(this._len - n, 0);
|
|
10698
10712
|
if (buf.length <= 0) {
|
|
@@ -10720,13 +10734,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10720
10734
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10721
10735
|
if (this.sync) {
|
|
10722
10736
|
try {
|
|
10723
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
10737
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs80.writeSync(this.fd, this._writingBuf) : fs80.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10724
10738
|
release(null, written);
|
|
10725
10739
|
} catch (err) {
|
|
10726
10740
|
release(err);
|
|
10727
10741
|
}
|
|
10728
10742
|
} else {
|
|
10729
|
-
|
|
10743
|
+
fs80.write(this.fd, this._writingBuf, release);
|
|
10730
10744
|
}
|
|
10731
10745
|
}
|
|
10732
10746
|
function actualWriteBuffer() {
|
|
@@ -10735,7 +10749,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10735
10749
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10736
10750
|
if (this.sync) {
|
|
10737
10751
|
try {
|
|
10738
|
-
const written =
|
|
10752
|
+
const written = fs80.writeSync(this.fd, this._writingBuf);
|
|
10739
10753
|
release(null, written);
|
|
10740
10754
|
} catch (err) {
|
|
10741
10755
|
release(err);
|
|
@@ -10744,7 +10758,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10744
10758
|
if (kCopyBuffer) {
|
|
10745
10759
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10746
10760
|
}
|
|
10747
|
-
|
|
10761
|
+
fs80.write(this.fd, this._writingBuf, release);
|
|
10748
10762
|
}
|
|
10749
10763
|
}
|
|
10750
10764
|
function actualClose(sonic) {
|
|
@@ -10760,12 +10774,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10760
10774
|
sonic._lens = [];
|
|
10761
10775
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10762
10776
|
try {
|
|
10763
|
-
|
|
10777
|
+
fs80.fsync(sonic.fd, closeWrapped);
|
|
10764
10778
|
} catch {
|
|
10765
10779
|
}
|
|
10766
10780
|
function closeWrapped() {
|
|
10767
10781
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10768
|
-
|
|
10782
|
+
fs80.close(sonic.fd, done);
|
|
10769
10783
|
} else {
|
|
10770
10784
|
done();
|
|
10771
10785
|
}
|
|
@@ -13900,11 +13914,11 @@ var init_lib = __esm({
|
|
|
13900
13914
|
}
|
|
13901
13915
|
}
|
|
13902
13916
|
},
|
|
13903
|
-
addToPath: function addToPath(
|
|
13904
|
-
var last =
|
|
13917
|
+
addToPath: function addToPath(path90, added, removed, oldPosInc, options) {
|
|
13918
|
+
var last = path90.lastComponent;
|
|
13905
13919
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13906
13920
|
return {
|
|
13907
|
-
oldPos:
|
|
13921
|
+
oldPos: path90.oldPos + oldPosInc,
|
|
13908
13922
|
lastComponent: {
|
|
13909
13923
|
count: last.count + 1,
|
|
13910
13924
|
added,
|
|
@@ -13914,7 +13928,7 @@ var init_lib = __esm({
|
|
|
13914
13928
|
};
|
|
13915
13929
|
} else {
|
|
13916
13930
|
return {
|
|
13917
|
-
oldPos:
|
|
13931
|
+
oldPos: path90.oldPos + oldPosInc,
|
|
13918
13932
|
lastComponent: {
|
|
13919
13933
|
count: 1,
|
|
13920
13934
|
added,
|
|
@@ -14468,10 +14482,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
14468
14482
|
const memories = raw.map((m2) => {
|
|
14469
14483
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14470
14484
|
const rec4 = m2;
|
|
14471
|
-
const
|
|
14485
|
+
const path90 = typeof rec4.path === "string" ? rec4.path : null;
|
|
14472
14486
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
14473
|
-
if (!
|
|
14474
|
-
const entry = { path:
|
|
14487
|
+
if (!path90 || content == null) return null;
|
|
14488
|
+
const entry = { path: path90, content };
|
|
14475
14489
|
if (typeof rec4.mtimeMs === "number") entry.mtimeMs = rec4.mtimeMs;
|
|
14476
14490
|
return entry;
|
|
14477
14491
|
}).filter((m2) => m2 !== null);
|
|
@@ -15338,10 +15352,10 @@ function parseAttachment(obj) {
|
|
|
15338
15352
|
const memories = raw.map((m2) => {
|
|
15339
15353
|
if (!m2 || typeof m2 !== "object") return null;
|
|
15340
15354
|
const rec4 = m2;
|
|
15341
|
-
const
|
|
15355
|
+
const path90 = typeof rec4.path === "string" ? rec4.path : null;
|
|
15342
15356
|
const content = typeof rec4.content === "string" ? rec4.content : null;
|
|
15343
|
-
if (!
|
|
15344
|
-
const out = { path:
|
|
15357
|
+
if (!path90 || content == null) return null;
|
|
15358
|
+
const out = { path: path90, content };
|
|
15345
15359
|
if (typeof rec4.mtimeMs === "number") out.mtimeMs = rec4.mtimeMs;
|
|
15346
15360
|
return out;
|
|
15347
15361
|
}).filter((m2) => m2 !== null);
|
|
@@ -36315,8 +36329,8 @@ var require_utils = __commonJS({
|
|
|
36315
36329
|
var result = transform[inputType][outputType](input);
|
|
36316
36330
|
return result;
|
|
36317
36331
|
};
|
|
36318
|
-
exports2.resolve = function(
|
|
36319
|
-
var parts =
|
|
36332
|
+
exports2.resolve = function(path90) {
|
|
36333
|
+
var parts = path90.split("/");
|
|
36320
36334
|
var result = [];
|
|
36321
36335
|
for (var index = 0; index < parts.length; index++) {
|
|
36322
36336
|
var part = parts[index];
|
|
@@ -42169,18 +42183,18 @@ var require_object = __commonJS({
|
|
|
42169
42183
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
42170
42184
|
this.files[name] = object;
|
|
42171
42185
|
};
|
|
42172
|
-
var parentFolder = function(
|
|
42173
|
-
if (
|
|
42174
|
-
|
|
42186
|
+
var parentFolder = function(path90) {
|
|
42187
|
+
if (path90.slice(-1) === "/") {
|
|
42188
|
+
path90 = path90.substring(0, path90.length - 1);
|
|
42175
42189
|
}
|
|
42176
|
-
var lastSlash =
|
|
42177
|
-
return lastSlash > 0 ?
|
|
42190
|
+
var lastSlash = path90.lastIndexOf("/");
|
|
42191
|
+
return lastSlash > 0 ? path90.substring(0, lastSlash) : "";
|
|
42178
42192
|
};
|
|
42179
|
-
var forceTrailingSlash = function(
|
|
42180
|
-
if (
|
|
42181
|
-
|
|
42193
|
+
var forceTrailingSlash = function(path90) {
|
|
42194
|
+
if (path90.slice(-1) !== "/") {
|
|
42195
|
+
path90 += "/";
|
|
42182
42196
|
}
|
|
42183
|
-
return
|
|
42197
|
+
return path90;
|
|
42184
42198
|
};
|
|
42185
42199
|
var folderAdd = function(name, createFolders) {
|
|
42186
42200
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -43182,7 +43196,7 @@ var require_lib3 = __commonJS({
|
|
|
43182
43196
|
// src/run-case/recorder.ts
|
|
43183
43197
|
function startRunCaseRecorder(opts) {
|
|
43184
43198
|
const now = opts.now ?? Date.now;
|
|
43185
|
-
const dir =
|
|
43199
|
+
const dir = import_node_path72.default.dirname(opts.recordPath);
|
|
43186
43200
|
let stream = null;
|
|
43187
43201
|
let closing = false;
|
|
43188
43202
|
let closedSettled = false;
|
|
@@ -43196,8 +43210,8 @@ function startRunCaseRecorder(opts) {
|
|
|
43196
43210
|
});
|
|
43197
43211
|
const ensureStream = () => {
|
|
43198
43212
|
if (stream) return stream;
|
|
43199
|
-
|
|
43200
|
-
stream =
|
|
43213
|
+
import_node_fs54.default.mkdirSync(dir, { recursive: true });
|
|
43214
|
+
stream = import_node_fs54.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
43201
43215
|
stream.on("close", () => closedResolve());
|
|
43202
43216
|
return stream;
|
|
43203
43217
|
};
|
|
@@ -43222,12 +43236,12 @@ function startRunCaseRecorder(opts) {
|
|
|
43222
43236
|
};
|
|
43223
43237
|
return { tap, close, closed };
|
|
43224
43238
|
}
|
|
43225
|
-
var
|
|
43239
|
+
var import_node_fs54, import_node_path72;
|
|
43226
43240
|
var init_recorder = __esm({
|
|
43227
43241
|
"src/run-case/recorder.ts"() {
|
|
43228
43242
|
"use strict";
|
|
43229
|
-
|
|
43230
|
-
|
|
43243
|
+
import_node_fs54 = __toESM(require("fs"), 1);
|
|
43244
|
+
import_node_path72 = __toESM(require("path"), 1);
|
|
43231
43245
|
}
|
|
43232
43246
|
});
|
|
43233
43247
|
|
|
@@ -43270,7 +43284,7 @@ var init_wire = __esm({
|
|
|
43270
43284
|
// src/run-case/controller.ts
|
|
43271
43285
|
async function runController(opts) {
|
|
43272
43286
|
const now = opts.now ?? Date.now;
|
|
43273
|
-
const cwd = opts.cwd ?? (0,
|
|
43287
|
+
const cwd = opts.cwd ?? (0, import_node_fs55.mkdtempSync)(import_node_path73.default.join(import_node_os25.default.tmpdir(), "clawd-runcase-"));
|
|
43274
43288
|
const ownsCwd = opts.cwd === void 0;
|
|
43275
43289
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
43276
43290
|
const spawnCtx = { cwd };
|
|
@@ -43431,19 +43445,19 @@ async function runController(opts) {
|
|
|
43431
43445
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
43432
43446
|
if (ownsCwd) {
|
|
43433
43447
|
try {
|
|
43434
|
-
(0,
|
|
43448
|
+
(0, import_node_fs55.rmSync)(cwd, { recursive: true, force: true });
|
|
43435
43449
|
} catch {
|
|
43436
43450
|
}
|
|
43437
43451
|
}
|
|
43438
43452
|
return exitCode ?? 0;
|
|
43439
43453
|
}
|
|
43440
|
-
var
|
|
43454
|
+
var import_node_fs55, import_node_os25, import_node_path73;
|
|
43441
43455
|
var init_controller = __esm({
|
|
43442
43456
|
"src/run-case/controller.ts"() {
|
|
43443
43457
|
"use strict";
|
|
43444
|
-
|
|
43458
|
+
import_node_fs55 = require("fs");
|
|
43445
43459
|
import_node_os25 = __toESM(require("os"), 1);
|
|
43446
|
-
|
|
43460
|
+
import_node_path73 = __toESM(require("path"), 1);
|
|
43447
43461
|
init_claude();
|
|
43448
43462
|
init_stdout_splitter();
|
|
43449
43463
|
init_permission_stdio();
|
|
@@ -43718,8 +43732,8 @@ Env (advanced):
|
|
|
43718
43732
|
`;
|
|
43719
43733
|
|
|
43720
43734
|
// src/index.ts
|
|
43721
|
-
var
|
|
43722
|
-
var
|
|
43735
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
43736
|
+
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
43723
43737
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
43724
43738
|
|
|
43725
43739
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -44789,6 +44803,21 @@ var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A perso
|
|
|
44789
44803
|
|
|
44790
44804
|
\u7528\u6237\u5BF9\u4E00\u4EF6**\u5DF2\u59D4\u6D3E**\u7684\u4E8B\u4E0B\u540E\u7EED\u6307\u4EE4\u65F6\uFF0C\u8C03 \`personaDispatch({ dispatchId: <\u8BE5\u4E8B\u7684 dispatchId>, prompt: <\u65B0\u6307\u4EE4> })\`\uFF08targetPersona \u53EF\u7701\u7565\uFF09\u2014\u2014\u65B0\u6307\u4EE4\u4F1A\u8FDB\u5165\u539F worker session \u63A5\u7740\u5E72\uFF0C\u4E0A\u4E0B\u6587\u4E0D\u4E22\u3002dispatchId \u7528\u4F60\u9996\u6B21\u59D4\u6D3E\u65F6\u62FF\u5230\u7684\u90A3\u4E2A\uFF1B\u4E0D\u786E\u5B9A\u662F\u54EA\u4EF6\u4E8B\u5C31\u5148\u8C03 \`personaDispatchList\` \u67E5\u3002
|
|
44791
44805
|
|
|
44806
|
+
### \u4E34\u65F6\u6362 engine / \u6A21\u578B\uFF08\u4E00\u6B21\u6027\uFF0C\u4E0D\u6539 persona \u7ED1\u5B9A\uFF09
|
|
44807
|
+
|
|
44808
|
+
\u60F3\u8BA9\u8FD9\u6B21\u4EFB\u52A1\u8DD1\u5728\u522B\u7684 engine \u6216\u6A21\u578B\u4E0A\uFF08\u4F8B\u5982\u300C\u7528 Codex \u7684 gpt-5.6-sol \u505A\u8FD9\u4E2A\u5F00\u53D1\u300D\uFF09\uFF0C\u52A0\u4E24\u4E2A\u53C2\u6570\uFF1A
|
|
44809
|
+
|
|
44810
|
+
- \`tool = 'codex' | 'claude'\` \u2014\u2014 \u8FD9\u4E00\u6761 dispatch \u7528\u54EA\u4E2A engine
|
|
44811
|
+
- \`model = <\u8BE5 engine \u7684\u6A21\u578B id>\` \u2014\u2014 \u4F8B\u5982 codex \u7684 \`gpt-5.6-sol\`\u3001claude \u7684 \`opus\`
|
|
44812
|
+
|
|
44813
|
+
**model \u7684\u5408\u6CD5\u503C\u96C6\u4ECE\u5C5E\u4E8E engine**\uFF1A\u7ED9\u4E00\u4E2A claude persona \u4F20 codex \u7684\u6A21\u578B\u65F6**\u5FC5\u987B\u540C\u65F6\u4F20 \`tool='codex'\`**\uFF0C
|
|
44814
|
+
\u5426\u5219\u6309 persona \u7ED1\u5B9A\u7684 engine \u9009\u8868\u6821\u9A8C\u3001\u76F4\u63A5\u88AB\u62D2\u3002\u4E24\u8005\u90FD\u4E0D\u4F20 = \u5B8C\u5168\u8DDF\u968F\u76EE\u6807 persona \u7684\u914D\u7F6E\uFF08\u9ED8\u8BA4\u884C\u4E3A\uFF09\u3002
|
|
44815
|
+
|
|
44816
|
+
\u4E00\u6B21\u6027\u8BED\u4E49\uFF1A\u76EE\u6807 persona \u81EA\u5DF1\u7684\u7ED1\u5B9A\u4E0D\u53D8\uFF0C\u53EA\u6709\u8FD9\u6761 dispatch \u8D77\u7684 worker session \u53D7\u5F71\u54CD\u3002
|
|
44817
|
+
\u8FD9\u4E24\u4E2A\u53C2\u6570**\u53EA\u80FD\u5728\u65B0\u5F00 dispatch \u65F6\u7528**\uFF1A\u7EED\u6D3E\uFF08\u5E26 dispatchId\uFF09\u53EA\u662F\u5F80\u5DF2\u7ECF\u8DD1\u7740\u7684 worker session \u6295\u65B0\u4E00\u8F6E
|
|
44818
|
+
\u6307\u4EE4\u3001\u4E0D\u91CD\u65B0\u8D77\u8FDB\u7A0B\uFF0C\u6240\u4EE5\u5E26 \`tool\` / \`model\` \u4F1A\u88AB\u76F4\u63A5\u62D2 \u2014\u2014 \u8981\u6362\u5C31\u65B0\u5F00\u4E00\u6761 dispatch\u3002\u8DE8\u8BBE\u5907\u59D4\u6D3E\u4E5F\u4E0D
|
|
44819
|
+
\u652F\u6301\u6362 engine\uFF08\u8FDC\u7AEF persona \u7528\u54EA\u4E2A engine \u7531\u90A3\u53F0\u673A\u5668\u7684\u4E3B\u4EBA\u51B3\u5B9A\uFF09\u3002
|
|
44820
|
+
|
|
44792
44821
|
### \u8DE8\u8BBE\u5907\u59D4\u6D3E\uFF08remote persona\uFF09
|
|
44793
44822
|
|
|
44794
44823
|
\u5F53 @ token \u5F62\u5982 \`@persona/<id>@<deviceId>\`\uFF08\u7B2C\u4E8C\u6BB5\u662F\u8054\u7CFB\u4EBA**\u8BBE\u5907\u7684 deviceId**\uFF0CUI \u9009\u8054\u7CFB\u4EBA\u65F6\u5DF2\u89E3\u6790\u597D\u586B\u5165\uFF09\u65F6\uFF0C\u662F\u628A\u4EFB\u52A1\u59D4\u6D3E\u7ED9\u90A3\u53F0\u8BBE\u5907\u4E0A\u7684 persona\u3002\u9664 targetPersona / prompt \u5916\u518D\u5E26\uFF1A
|
|
@@ -47810,12 +47839,14 @@ var SessionManager = class {
|
|
|
47810
47839
|
const cwd = import_node_path9.default.join(this.deps.personaRoot, safeFileName(args.targetPersona));
|
|
47811
47840
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
47812
47841
|
const personaDefaults = this.deps.getPersonaDefaults?.(args.targetPersona);
|
|
47842
|
+
const effectiveTool = args.tool ?? personaDefaults?.tool ?? "claude";
|
|
47843
|
+
const engineOverridden = effectiveTool !== (personaDefaults?.tool ?? "claude");
|
|
47813
47844
|
const file = {
|
|
47814
47845
|
sessionId,
|
|
47815
47846
|
cwd,
|
|
47816
47847
|
// dispatch B session 跟随 persona 绑定的 tool(codex persona 用 codex spawn);
|
|
47817
|
-
// UI 手建路径另允许通过 session:create
|
|
47818
|
-
tool:
|
|
47848
|
+
// UI 手建路径另允许通过 session:create 显式覆盖,dispatch 走 args.tool 一次性 override。
|
|
47849
|
+
tool: effectiveTool,
|
|
47819
47850
|
ownerPersonaId: args.targetPersona,
|
|
47820
47851
|
dispatchedFromSessionId: args.sourceSessionId,
|
|
47821
47852
|
// 跨设备显示关键(spec §8):creatorPrincipalId = A 的 deviceId,让 A 的
|
|
@@ -47829,7 +47860,8 @@ var SessionManager = class {
|
|
|
47829
47860
|
} : {},
|
|
47830
47861
|
// T-20 的 dispatch model override 优先;缺省回落 persona 默认值(spec 2026-08-12)。
|
|
47831
47862
|
// effort 没有 override 参数(续派也不允许改),直接取 persona 默认值。
|
|
47832
|
-
|
|
47863
|
+
// engine 被 override 掉时 persona 的 model / effort 一概不继承(见 engineOverridden)。
|
|
47864
|
+
...personaDefaultFields(engineOverridden ? void 0 : personaDefaults, args.model),
|
|
47833
47865
|
// butler 顶部入口:dispatch 传下来的 label 落盘,sidebar 显示(否则兜底 cwd-basename)
|
|
47834
47866
|
...args.label ? { label: args.label } : {},
|
|
47835
47867
|
createdAt: now,
|
|
@@ -50136,11 +50168,11 @@ init_claude();
|
|
|
50136
50168
|
|
|
50137
50169
|
// src/tools/codex.ts
|
|
50138
50170
|
var import_node_child_process6 = require("child_process");
|
|
50139
|
-
var
|
|
50171
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
50140
50172
|
|
|
50141
50173
|
// src/tools/codex-session.ts
|
|
50142
50174
|
var import_node_child_process4 = require("child_process");
|
|
50143
|
-
var
|
|
50175
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
50144
50176
|
|
|
50145
50177
|
// src/tools/codex-app-server-client.ts
|
|
50146
50178
|
var import_node_readline = require("readline");
|
|
@@ -50573,6 +50605,19 @@ function codexMcpCliArgs(defs) {
|
|
|
50573
50605
|
}
|
|
50574
50606
|
return out;
|
|
50575
50607
|
}
|
|
50608
|
+
function codexAgentsCliArgs(cfg) {
|
|
50609
|
+
const out = [];
|
|
50610
|
+
if (cfg.defaultSubagentModel) {
|
|
50611
|
+
out.push("-c", `agents.default_subagent_model=${tomlValue(cfg.defaultSubagentModel)}`);
|
|
50612
|
+
}
|
|
50613
|
+
if (cfg.defaultSubagentReasoningEffort) {
|
|
50614
|
+
out.push(
|
|
50615
|
+
"-c",
|
|
50616
|
+
`agents.default_subagent_reasoning_effort=${tomlValue(cfg.defaultSubagentReasoningEffort)}`
|
|
50617
|
+
);
|
|
50618
|
+
}
|
|
50619
|
+
return out;
|
|
50620
|
+
}
|
|
50576
50621
|
function threadStartParams(ctx) {
|
|
50577
50622
|
const params = {
|
|
50578
50623
|
cwd: ctx.cwd,
|
|
@@ -50596,8 +50641,8 @@ function turnStartInput(text) {
|
|
|
50596
50641
|
const items = [];
|
|
50597
50642
|
let leftover = text;
|
|
50598
50643
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
50599
|
-
const [marker, name,
|
|
50600
|
-
items.push({ type: "skill", name, path:
|
|
50644
|
+
const [marker, name, path90] = m2;
|
|
50645
|
+
items.push({ type: "skill", name, path: path90 });
|
|
50601
50646
|
leftover = leftover.replace(marker, "");
|
|
50602
50647
|
}
|
|
50603
50648
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -50665,6 +50710,35 @@ function loadCodexMcpServerDefs(args) {
|
|
|
50665
50710
|
return out;
|
|
50666
50711
|
}
|
|
50667
50712
|
|
|
50713
|
+
// src/tools/codex-agents-config.ts
|
|
50714
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
50715
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
50716
|
+
var AGENTS_SECTION = /^\[agents\][^\n]*\n([\s\S]*?)(?=^\[|$(?![\s\S]))/m;
|
|
50717
|
+
function readKey(section, key) {
|
|
50718
|
+
const m2 = new RegExp(`^[ \\t]*${key}[ \\t]*=[ \\t]*(["'])(.*?)\\1`, "m").exec(section);
|
|
50719
|
+
return m2?.[2].trim() || void 0;
|
|
50720
|
+
}
|
|
50721
|
+
function loadCodexAgentsConfig(args) {
|
|
50722
|
+
const file = import_node_path16.default.join(args.cwd, ".codex", "config.toml");
|
|
50723
|
+
let text;
|
|
50724
|
+
try {
|
|
50725
|
+
text = import_node_fs18.default.readFileSync(file, "utf8");
|
|
50726
|
+
} catch (e) {
|
|
50727
|
+
const code = e.code;
|
|
50728
|
+
if (code !== "ENOENT") {
|
|
50729
|
+
args.logger?.warn("codex agents config unreadable, skipped", { file, code: code ?? "read-error" });
|
|
50730
|
+
}
|
|
50731
|
+
return {};
|
|
50732
|
+
}
|
|
50733
|
+
const section = AGENTS_SECTION.exec(text)?.[1] ?? "";
|
|
50734
|
+
const model = readKey(section, "default_subagent_model");
|
|
50735
|
+
const effort = readKey(section, "default_subagent_reasoning_effort");
|
|
50736
|
+
return {
|
|
50737
|
+
...model ? { defaultSubagentModel: model } : {},
|
|
50738
|
+
...effort ? { defaultSubagentReasoningEffort: effort } : {}
|
|
50739
|
+
};
|
|
50740
|
+
}
|
|
50741
|
+
|
|
50668
50742
|
// src/tools/codex-features.ts
|
|
50669
50743
|
var import_node_child_process3 = require("child_process");
|
|
50670
50744
|
var cachedNetworkProxy;
|
|
@@ -50726,6 +50800,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
50726
50800
|
})
|
|
50727
50801
|
)
|
|
50728
50802
|
);
|
|
50803
|
+
args.push(...codexAgentsCliArgs(loadCodexAgentsConfig({ cwd: ctx.cwd, logger: deps.logger })));
|
|
50729
50804
|
const resolvedCodexHome = deps.codexHomeFor?.(ctx.cwd);
|
|
50730
50805
|
const env = {
|
|
50731
50806
|
...process.env,
|
|
@@ -50805,7 +50880,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
50805
50880
|
capabilities: null
|
|
50806
50881
|
});
|
|
50807
50882
|
client.notify("initialized", {});
|
|
50808
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
50883
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path17.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
|
|
50809
50884
|
if (threadId) {
|
|
50810
50885
|
await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
|
|
50811
50886
|
} else {
|
|
@@ -51023,10 +51098,10 @@ function sanitizeCodexModel(model) {
|
|
|
51023
51098
|
return model;
|
|
51024
51099
|
}
|
|
51025
51100
|
async function probeCodex(env = process.env) {
|
|
51026
|
-
if (env.CODEX_BIN &&
|
|
51101
|
+
if (env.CODEX_BIN && import_node_fs19.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
51027
51102
|
try {
|
|
51028
51103
|
const out = (0, import_node_child_process6.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
|
|
51029
|
-
if (out &&
|
|
51104
|
+
if (out && import_node_fs19.default.existsSync(out)) return { available: true, path: out };
|
|
51030
51105
|
} catch {
|
|
51031
51106
|
}
|
|
51032
51107
|
return { available: false };
|
|
@@ -51099,9 +51174,9 @@ var CodexAdapter = class {
|
|
|
51099
51174
|
|
|
51100
51175
|
// src/tools/claude-tui.ts
|
|
51101
51176
|
var import_node_crypto5 = require("crypto");
|
|
51102
|
-
var
|
|
51177
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
51103
51178
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
51104
|
-
var
|
|
51179
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
51105
51180
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
51106
51181
|
|
|
51107
51182
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -52336,9 +52411,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
52336
52411
|
function jsonlExistsForCtx(ctx) {
|
|
52337
52412
|
if (!ctx.toolSessionId) return false;
|
|
52338
52413
|
const home = import_node_os7.default.homedir();
|
|
52339
|
-
const file =
|
|
52414
|
+
const file = import_node_path18.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
52340
52415
|
try {
|
|
52341
|
-
return
|
|
52416
|
+
return import_node_fs20.default.statSync(file).isFile();
|
|
52342
52417
|
} catch {
|
|
52343
52418
|
return false;
|
|
52344
52419
|
}
|
|
@@ -52417,7 +52492,7 @@ var PersonaDispatchManager = class {
|
|
|
52417
52492
|
|
|
52418
52493
|
// src/dispatch/store.ts
|
|
52419
52494
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
52420
|
-
var
|
|
52495
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
52421
52496
|
|
|
52422
52497
|
// src/shift/constants.ts
|
|
52423
52498
|
var MAX_RUNS_PER_SHIFT = 30;
|
|
@@ -52455,7 +52530,7 @@ function createDispatchStore(deps) {
|
|
|
52455
52530
|
flushTimer = null;
|
|
52456
52531
|
}
|
|
52457
52532
|
const content = { version: 1, records };
|
|
52458
|
-
await import_promises.default.mkdir(
|
|
52533
|
+
await import_promises.default.mkdir(import_node_path19.default.dirname(deps.filePath), { recursive: true });
|
|
52459
52534
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52460
52535
|
await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52461
52536
|
await import_promises.default.rename(tmp, deps.filePath);
|
|
@@ -52518,7 +52593,7 @@ function createDispatchStore(deps) {
|
|
|
52518
52593
|
|
|
52519
52594
|
// src/channel/json-store.ts
|
|
52520
52595
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
52521
|
-
var
|
|
52596
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
52522
52597
|
function createJsonStore(deps) {
|
|
52523
52598
|
let items = [];
|
|
52524
52599
|
let flushTimer = null;
|
|
@@ -52528,7 +52603,7 @@ function createJsonStore(deps) {
|
|
|
52528
52603
|
flushTimer = null;
|
|
52529
52604
|
}
|
|
52530
52605
|
const content = { version: 1, [deps.key]: items };
|
|
52531
|
-
await import_promises2.default.mkdir(
|
|
52606
|
+
await import_promises2.default.mkdir(import_node_path20.default.dirname(deps.filePath), { recursive: true });
|
|
52532
52607
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52533
52608
|
await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52534
52609
|
await import_promises2.default.rename(tmp, deps.filePath);
|
|
@@ -52709,10 +52784,10 @@ function createTopicStore(deps) {
|
|
|
52709
52784
|
}
|
|
52710
52785
|
|
|
52711
52786
|
// src/dispatch/mcp-config.ts
|
|
52712
|
-
var
|
|
52713
|
-
var
|
|
52787
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
52788
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
52714
52789
|
function dispatchMcpConfigPath(dataDir) {
|
|
52715
|
-
return
|
|
52790
|
+
return import_node_path21.default.join(dataDir, "dispatch.mcp.json");
|
|
52716
52791
|
}
|
|
52717
52792
|
function writeDispatchMcpConfig(args) {
|
|
52718
52793
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -52731,16 +52806,16 @@ function writeDispatchMcpConfig(args) {
|
|
|
52731
52806
|
}
|
|
52732
52807
|
}
|
|
52733
52808
|
};
|
|
52734
|
-
|
|
52735
|
-
|
|
52809
|
+
import_node_fs21.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52810
|
+
import_node_fs21.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52736
52811
|
return cfgPath;
|
|
52737
52812
|
}
|
|
52738
52813
|
|
|
52739
52814
|
// src/ticket/mcp-config.ts
|
|
52740
|
-
var
|
|
52741
|
-
var
|
|
52815
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
52816
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
52742
52817
|
function ticketMcpConfigPath(dataDir) {
|
|
52743
|
-
return
|
|
52818
|
+
return import_node_path22.default.join(dataDir, "ticket.mcp.json");
|
|
52744
52819
|
}
|
|
52745
52820
|
function writeTicketMcpConfig(args) {
|
|
52746
52821
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
@@ -52762,16 +52837,16 @@ function writeTicketMcpConfig(args) {
|
|
|
52762
52837
|
}
|
|
52763
52838
|
}
|
|
52764
52839
|
};
|
|
52765
|
-
|
|
52766
|
-
|
|
52840
|
+
import_node_fs22.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52841
|
+
import_node_fs22.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52767
52842
|
return cfgPath;
|
|
52768
52843
|
}
|
|
52769
52844
|
|
|
52770
52845
|
// src/shift/mcp-config.ts
|
|
52771
|
-
var
|
|
52772
|
-
var
|
|
52846
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
52847
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
52773
52848
|
function shiftMcpConfigPath(dataDir) {
|
|
52774
|
-
return
|
|
52849
|
+
return import_node_path23.default.join(dataDir, "shift.mcp.json");
|
|
52775
52850
|
}
|
|
52776
52851
|
async function writeShiftMcpConfig(args) {
|
|
52777
52852
|
const cfgPath = shiftMcpConfigPath(args.dataDir);
|
|
@@ -52790,16 +52865,16 @@ async function writeShiftMcpConfig(args) {
|
|
|
52790
52865
|
}
|
|
52791
52866
|
}
|
|
52792
52867
|
};
|
|
52793
|
-
await
|
|
52794
|
-
await
|
|
52868
|
+
await import_node_fs23.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
52869
|
+
await import_node_fs23.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52795
52870
|
return cfgPath;
|
|
52796
52871
|
}
|
|
52797
52872
|
|
|
52798
52873
|
// src/inbox/mcp-config.ts
|
|
52799
|
-
var
|
|
52800
|
-
var
|
|
52874
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
52875
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
52801
52876
|
function inboxMcpConfigPath(dataDir) {
|
|
52802
|
-
return
|
|
52877
|
+
return import_node_path24.default.join(dataDir, "inbox.mcp.json");
|
|
52803
52878
|
}
|
|
52804
52879
|
async function writeInboxMcpConfig(args) {
|
|
52805
52880
|
const cfgPath = inboxMcpConfigPath(args.dataDir);
|
|
@@ -52818,16 +52893,16 @@ async function writeInboxMcpConfig(args) {
|
|
|
52818
52893
|
}
|
|
52819
52894
|
}
|
|
52820
52895
|
};
|
|
52821
|
-
await
|
|
52822
|
-
await
|
|
52896
|
+
await import_node_fs24.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
52897
|
+
await import_node_fs24.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52823
52898
|
return cfgPath;
|
|
52824
52899
|
}
|
|
52825
52900
|
|
|
52826
52901
|
// src/peer-ops/mcp-config.ts
|
|
52827
|
-
var
|
|
52828
|
-
var
|
|
52902
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
52903
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
52829
52904
|
function peerOpsMcpConfigPath(dataDir) {
|
|
52830
|
-
return
|
|
52905
|
+
return import_node_path25.default.join(dataDir, "peer-ops.mcp.json");
|
|
52831
52906
|
}
|
|
52832
52907
|
function writePeerOpsMcpConfig(args) {
|
|
52833
52908
|
const cfgPath = peerOpsMcpConfigPath(args.dataDir);
|
|
@@ -52844,16 +52919,16 @@ function writePeerOpsMcpConfig(args) {
|
|
|
52844
52919
|
}
|
|
52845
52920
|
}
|
|
52846
52921
|
};
|
|
52847
|
-
|
|
52848
|
-
|
|
52922
|
+
import_node_fs25.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52923
|
+
import_node_fs25.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
|
|
52849
52924
|
return cfgPath;
|
|
52850
52925
|
}
|
|
52851
52926
|
|
|
52852
52927
|
// src/rpc-tool/mcp-config.ts
|
|
52853
|
-
var
|
|
52854
|
-
var
|
|
52928
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
52929
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
52855
52930
|
function rpcToolMcpConfigPath(dataDir) {
|
|
52856
|
-
return
|
|
52931
|
+
return import_node_path26.default.join(dataDir, "rpc-tool.mcp.json");
|
|
52857
52932
|
}
|
|
52858
52933
|
function writeRpcToolMcpConfig(args) {
|
|
52859
52934
|
const cfgPath = rpcToolMcpConfigPath(args.dataDir);
|
|
@@ -52872,18 +52947,18 @@ function writeRpcToolMcpConfig(args) {
|
|
|
52872
52947
|
}
|
|
52873
52948
|
}
|
|
52874
52949
|
};
|
|
52875
|
-
|
|
52876
|
-
|
|
52950
|
+
import_node_fs26.default.mkdirSync(args.dataDir, { recursive: true });
|
|
52951
|
+
import_node_fs26.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
52877
52952
|
return cfgPath;
|
|
52878
52953
|
}
|
|
52879
52954
|
|
|
52880
52955
|
// src/dispatch/source-transcript.ts
|
|
52881
|
-
var
|
|
52956
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
52882
52957
|
init_claude_history();
|
|
52883
52958
|
var NO_SOURCE_TRANSCRIPT = "(no transcript yet \u2014 operate from the task description alone)";
|
|
52884
52959
|
function resolveSourceJsonlPath(sourceFile, home) {
|
|
52885
52960
|
if (!sourceFile?.toolSessionId) return NO_SOURCE_TRANSCRIPT;
|
|
52886
|
-
return
|
|
52961
|
+
return import_node_path27.default.join(
|
|
52887
52962
|
home,
|
|
52888
52963
|
".claude",
|
|
52889
52964
|
"projects",
|
|
@@ -52894,7 +52969,7 @@ function resolveSourceJsonlPath(sourceFile, home) {
|
|
|
52894
52969
|
|
|
52895
52970
|
// src/shift/store.ts
|
|
52896
52971
|
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
52897
|
-
var
|
|
52972
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
52898
52973
|
var import_node_crypto6 = require("crypto");
|
|
52899
52974
|
|
|
52900
52975
|
// src/shift/schedule.ts
|
|
@@ -52969,7 +53044,7 @@ function createShiftStore(deps) {
|
|
|
52969
53044
|
flushTimer = null;
|
|
52970
53045
|
}
|
|
52971
53046
|
const content = { version: 1, shifts };
|
|
52972
|
-
await import_promises3.default.mkdir(
|
|
53047
|
+
await import_promises3.default.mkdir(import_node_path28.default.dirname(deps.filePath), { recursive: true });
|
|
52973
53048
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
52974
53049
|
await import_promises3.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
52975
53050
|
await import_promises3.default.rename(tmp, deps.filePath);
|
|
@@ -53637,15 +53712,15 @@ async function refreshTunnelUrlOnStartup(deps) {
|
|
|
53637
53712
|
}
|
|
53638
53713
|
|
|
53639
53714
|
// src/lark-bot-connector/binding-store.ts
|
|
53640
|
-
var
|
|
53641
|
-
var
|
|
53715
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
53716
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
53642
53717
|
function createLarkBotBindingStore(personaRoot) {
|
|
53643
|
-
const filePath = (personaId2) =>
|
|
53718
|
+
const filePath = (personaId2) => import_node_path29.default.join(personaRoot, safeFileName(personaId2), ".clawd", "lark-bot.json");
|
|
53644
53719
|
const read = (personaId2) => {
|
|
53645
53720
|
const file = filePath(personaId2);
|
|
53646
|
-
if (!
|
|
53721
|
+
if (!import_node_fs27.default.existsSync(file)) return null;
|
|
53647
53722
|
try {
|
|
53648
|
-
const raw = JSON.parse(
|
|
53723
|
+
const raw = JSON.parse(import_node_fs27.default.readFileSync(file, "utf8"));
|
|
53649
53724
|
if (typeof raw?.appId !== "string" || raw.appId.length === 0) return null;
|
|
53650
53725
|
return raw;
|
|
53651
53726
|
} catch {
|
|
@@ -53654,16 +53729,16 @@ function createLarkBotBindingStore(personaRoot) {
|
|
|
53654
53729
|
};
|
|
53655
53730
|
const write = (personaId2, meta) => {
|
|
53656
53731
|
const file = filePath(personaId2);
|
|
53657
|
-
|
|
53732
|
+
import_node_fs27.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
|
|
53658
53733
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
53659
|
-
|
|
53660
|
-
|
|
53734
|
+
import_node_fs27.default.writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
53735
|
+
import_node_fs27.default.renameSync(tmp, file);
|
|
53661
53736
|
};
|
|
53662
53737
|
return {
|
|
53663
53738
|
read,
|
|
53664
53739
|
write,
|
|
53665
53740
|
remove(personaId2) {
|
|
53666
|
-
|
|
53741
|
+
import_node_fs27.default.rmSync(filePath(personaId2), { force: true });
|
|
53667
53742
|
},
|
|
53668
53743
|
addRemovedChat(personaId2, chatId) {
|
|
53669
53744
|
const meta = read(personaId2);
|
|
@@ -53817,8 +53892,8 @@ function createLarkBotCloudClient(opts) {
|
|
|
53817
53892
|
}
|
|
53818
53893
|
|
|
53819
53894
|
// src/lark-bot-connector/chat-router.ts
|
|
53820
|
-
var
|
|
53821
|
-
var
|
|
53895
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
53896
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
53822
53897
|
init_protocol();
|
|
53823
53898
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
53824
53899
|
var LOCAL_TURN_RETRIES = 2;
|
|
@@ -53883,9 +53958,9 @@ function createLarkChatRouter(deps) {
|
|
|
53883
53958
|
continue;
|
|
53884
53959
|
}
|
|
53885
53960
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53886
|
-
|
|
53887
|
-
const p2 =
|
|
53888
|
-
|
|
53961
|
+
import_node_fs28.default.mkdirSync(dir, { recursive: true });
|
|
53962
|
+
const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}.${ext}`);
|
|
53963
|
+
import_node_fs28.default.writeFileSync(p2, r.data);
|
|
53889
53964
|
lines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53890
53965
|
} catch (err) {
|
|
53891
53966
|
deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
|
|
@@ -53906,9 +53981,9 @@ function createLarkChatRouter(deps) {
|
|
|
53906
53981
|
continue;
|
|
53907
53982
|
}
|
|
53908
53983
|
const dir = deps.mediaRootFor(env.chatId);
|
|
53909
|
-
|
|
53910
|
-
const p2 =
|
|
53911
|
-
|
|
53984
|
+
import_node_fs28.default.mkdirSync(dir, { recursive: true });
|
|
53985
|
+
const p2 = import_node_path30.default.join(dir, `${safeMediaName(ownerMessageId)}-${i}-${safeAttachmentName(f.name)}`);
|
|
53986
|
+
import_node_fs28.default.writeFileSync(p2, r.data);
|
|
53912
53987
|
lines.push(`[\u6587\u4EF6: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
53913
53988
|
} catch (err) {
|
|
53914
53989
|
deps.logger?.warn(`larkBot file fetch failed ${f.key}: ${err.message}`);
|
|
@@ -54227,16 +54302,11 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54227
54302
|
});
|
|
54228
54303
|
}
|
|
54229
54304
|
const args = DispatchRunArgsSchema.parse(rest);
|
|
54230
|
-
if (args.
|
|
54231
|
-
|
|
54232
|
-
|
|
54233
|
-
|
|
54234
|
-
|
|
54235
|
-
throw new ClawdError(
|
|
54236
|
-
ERROR_CODES.INVALID_PARAM,
|
|
54237
|
-
`model '${args.model}' not supported for tool '${targetTool}'; allowed: ${allowed.join(", ")}`
|
|
54238
|
-
);
|
|
54239
|
-
}
|
|
54305
|
+
if (args.tool !== void 0 && ctx?.principal.kind === "guest") {
|
|
54306
|
+
throw new ClawdError(
|
|
54307
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
54308
|
+
"engine override cannot be requested by a guest"
|
|
54309
|
+
);
|
|
54240
54310
|
}
|
|
54241
54311
|
if (args.dispatchId) {
|
|
54242
54312
|
if (ctx?.principal.kind === "guest") {
|
|
@@ -54304,6 +54374,19 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54304
54374
|
if (!targetPersona) {
|
|
54305
54375
|
throw new ClawdError(ERROR_CODES.INVALID_PARAM, "targetPersona is required for a new dispatch");
|
|
54306
54376
|
}
|
|
54377
|
+
const effectiveTool = args.tool ?? deps.getPersonaDefaults?.(targetPersona)?.tool ?? "claude";
|
|
54378
|
+
if (args.tool !== void 0 && deps.getCapabilities) {
|
|
54379
|
+
await deps.getCapabilities(args.tool);
|
|
54380
|
+
}
|
|
54381
|
+
if (args.model !== void 0) {
|
|
54382
|
+
const allowed = effectiveTool === "codex" ? ((await deps.getCapabilities?.("codex"))?.models ?? []).map((m2) => m2.id).filter((id) => id !== "") : CLAUDE_MODEL_IDS;
|
|
54383
|
+
if (!allowed.includes(args.model)) {
|
|
54384
|
+
throw new ClawdError(
|
|
54385
|
+
ERROR_CODES.INVALID_PARAM,
|
|
54386
|
+
`model '${args.model}' not supported for tool '${effectiveTool}'; allowed: ${allowed.join(", ")}`
|
|
54387
|
+
);
|
|
54388
|
+
}
|
|
54389
|
+
}
|
|
54307
54390
|
if (args.targetDeviceId) {
|
|
54308
54391
|
if (ctx?.principal.kind === "guest") {
|
|
54309
54392
|
throw new ClawdError(
|
|
@@ -54402,6 +54485,8 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
54402
54485
|
targetPersona,
|
|
54403
54486
|
prompt: args.prompt,
|
|
54404
54487
|
...args.model ? { model: args.model } : {},
|
|
54488
|
+
// 一次性 engine override(spec 2026-08-24):只有本机 owner 入口能带(guest 已在上方拒)
|
|
54489
|
+
...args.tool ? { tool: args.tool } : {},
|
|
54405
54490
|
// butler 顶部入口(spec 2026-07-27):sessionLabel 落到 SessionFile.label 让 sidebar 显示
|
|
54406
54491
|
...args.sessionLabel ? { label: args.sessionLabel } : {}
|
|
54407
54492
|
}).then(() => {
|
|
@@ -54938,7 +55023,7 @@ var CodexHistoryReader = class {
|
|
|
54938
55023
|
};
|
|
54939
55024
|
|
|
54940
55025
|
// src/tools/codex-skills.ts
|
|
54941
|
-
var
|
|
55026
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
54942
55027
|
function str3(v2) {
|
|
54943
55028
|
return typeof v2 === "string" ? v2 : void 0;
|
|
54944
55029
|
}
|
|
@@ -54953,13 +55038,13 @@ function mapSkillsListResponse(res) {
|
|
|
54953
55038
|
const r = s ?? {};
|
|
54954
55039
|
const name = str3(r.name);
|
|
54955
55040
|
if (!name) continue;
|
|
54956
|
-
const
|
|
55041
|
+
const path90 = str3(r.path);
|
|
54957
55042
|
const description = str3(r.description);
|
|
54958
55043
|
const isPlugin = name.includes(":");
|
|
54959
55044
|
out.push({
|
|
54960
55045
|
name,
|
|
54961
55046
|
source: isPlugin ? "plugin" : "project",
|
|
54962
|
-
...
|
|
55047
|
+
...path90 ? { path: path90 } : {},
|
|
54963
55048
|
...description ? { description } : {},
|
|
54964
55049
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
54965
55050
|
});
|
|
@@ -54975,7 +55060,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
54975
55060
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
54976
55061
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
54977
55062
|
beforeRequest: (client) => {
|
|
54978
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
55063
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path31.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
54979
55064
|
}
|
|
54980
55065
|
});
|
|
54981
55066
|
return mapSkillsListResponse(res);
|
|
@@ -55060,23 +55145,23 @@ function str4(v2) {
|
|
|
55060
55145
|
}
|
|
55061
55146
|
|
|
55062
55147
|
// src/workspace/browser.ts
|
|
55063
|
-
var
|
|
55148
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
55064
55149
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
55065
|
-
var
|
|
55150
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
55066
55151
|
init_protocol();
|
|
55067
55152
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
55068
55153
|
function resolveInsideCwd(cwd, subpath) {
|
|
55069
|
-
const absCwd =
|
|
55070
|
-
const joined =
|
|
55071
|
-
const rel =
|
|
55072
|
-
if (rel.startsWith("..") ||
|
|
55154
|
+
const absCwd = import_node_path32.default.resolve(cwd);
|
|
55155
|
+
const joined = import_node_path32.default.resolve(absCwd, subpath ?? ".");
|
|
55156
|
+
const rel = import_node_path32.default.relative(absCwd, joined);
|
|
55157
|
+
if (rel.startsWith("..") || import_node_path32.default.isAbsolute(rel)) {
|
|
55073
55158
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
55074
55159
|
}
|
|
55075
55160
|
return joined;
|
|
55076
55161
|
}
|
|
55077
55162
|
function ensureCwd(cwd) {
|
|
55078
55163
|
try {
|
|
55079
|
-
const stat =
|
|
55164
|
+
const stat = import_node_fs29.default.statSync(cwd);
|
|
55080
55165
|
if (!stat.isDirectory()) {
|
|
55081
55166
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
55082
55167
|
}
|
|
@@ -55090,7 +55175,7 @@ var WorkspaceBrowser = class {
|
|
|
55090
55175
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
|
|
55091
55176
|
ensureCwd(cwd);
|
|
55092
55177
|
const full = resolveInsideCwd(cwd, args.path);
|
|
55093
|
-
const dirents =
|
|
55178
|
+
const dirents = import_node_fs29.default.readdirSync(full, { withFileTypes: true });
|
|
55094
55179
|
const entries = [];
|
|
55095
55180
|
for (const d of dirents) {
|
|
55096
55181
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -55100,7 +55185,7 @@ var WorkspaceBrowser = class {
|
|
|
55100
55185
|
mtime: ""
|
|
55101
55186
|
};
|
|
55102
55187
|
try {
|
|
55103
|
-
const st =
|
|
55188
|
+
const st = import_node_fs29.default.statSync(import_node_path32.default.join(full, d.name));
|
|
55104
55189
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
55105
55190
|
if (d.isFile()) entry.size = st.size;
|
|
55106
55191
|
} catch {
|
|
@@ -55116,14 +55201,14 @@ var WorkspaceBrowser = class {
|
|
|
55116
55201
|
read(args) {
|
|
55117
55202
|
ensureCwd(args.cwd);
|
|
55118
55203
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
55119
|
-
const st =
|
|
55204
|
+
const st = import_node_fs29.default.statSync(full);
|
|
55120
55205
|
if (!st.isFile()) {
|
|
55121
55206
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
55122
55207
|
}
|
|
55123
55208
|
if (st.size > MAX_FILE_BYTES2) {
|
|
55124
55209
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
|
|
55125
55210
|
}
|
|
55126
|
-
const buf =
|
|
55211
|
+
const buf = import_node_fs29.default.readFileSync(full);
|
|
55127
55212
|
const isBinary = buf.includes(0);
|
|
55128
55213
|
if (isBinary) {
|
|
55129
55214
|
return {
|
|
@@ -55145,20 +55230,20 @@ var WorkspaceBrowser = class {
|
|
|
55145
55230
|
};
|
|
55146
55231
|
|
|
55147
55232
|
// src/skills/agents-scanner.ts
|
|
55148
|
-
var
|
|
55233
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
55149
55234
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
55150
|
-
var
|
|
55235
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
55151
55236
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
55152
55237
|
function isDirLikeSync2(p2) {
|
|
55153
55238
|
try {
|
|
55154
|
-
return
|
|
55239
|
+
return import_node_fs30.default.statSync(p2).isDirectory();
|
|
55155
55240
|
} catch {
|
|
55156
55241
|
return false;
|
|
55157
55242
|
}
|
|
55158
55243
|
}
|
|
55159
55244
|
function fileExistsSync(p2) {
|
|
55160
55245
|
try {
|
|
55161
|
-
return
|
|
55246
|
+
return import_node_fs30.default.statSync(p2).isFile();
|
|
55162
55247
|
} catch {
|
|
55163
55248
|
return false;
|
|
55164
55249
|
}
|
|
@@ -55166,7 +55251,7 @@ function fileExistsSync(p2) {
|
|
|
55166
55251
|
function parseAgentFile(filePath) {
|
|
55167
55252
|
let content;
|
|
55168
55253
|
try {
|
|
55169
|
-
content =
|
|
55254
|
+
content = import_node_fs30.default.readFileSync(filePath, "utf8");
|
|
55170
55255
|
} catch {
|
|
55171
55256
|
return {};
|
|
55172
55257
|
}
|
|
@@ -55179,16 +55264,16 @@ function parseAgentFile(filePath) {
|
|
|
55179
55264
|
function scanAgentsDir(dir, source, seen, out) {
|
|
55180
55265
|
let entries;
|
|
55181
55266
|
try {
|
|
55182
|
-
entries =
|
|
55267
|
+
entries = import_node_fs30.default.readdirSync(dir, { withFileTypes: true });
|
|
55183
55268
|
} catch {
|
|
55184
55269
|
return;
|
|
55185
55270
|
}
|
|
55186
55271
|
for (const ent of entries) {
|
|
55187
55272
|
if (!ent.name.endsWith(".md")) continue;
|
|
55188
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
55273
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path33.default.join(dir, ent.name)))) {
|
|
55189
55274
|
continue;
|
|
55190
55275
|
}
|
|
55191
|
-
const filePath =
|
|
55276
|
+
const filePath = import_node_path33.default.join(dir, ent.name);
|
|
55192
55277
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
55193
55278
|
if (seen.has(baseName)) continue;
|
|
55194
55279
|
seen.add(baseName);
|
|
@@ -55206,12 +55291,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
55206
55291
|
function walk2(dir, namespaces) {
|
|
55207
55292
|
let entries;
|
|
55208
55293
|
try {
|
|
55209
|
-
entries =
|
|
55294
|
+
entries = import_node_fs30.default.readdirSync(dir, { withFileTypes: true });
|
|
55210
55295
|
} catch {
|
|
55211
55296
|
return;
|
|
55212
55297
|
}
|
|
55213
55298
|
for (const ent of entries) {
|
|
55214
|
-
const childPath =
|
|
55299
|
+
const childPath = import_node_path33.default.join(dir, ent.name);
|
|
55215
55300
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
55216
55301
|
walk2(childPath, [...namespaces, ent.name]);
|
|
55217
55302
|
continue;
|
|
@@ -55236,13 +55321,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
55236
55321
|
walk2(root, []);
|
|
55237
55322
|
}
|
|
55238
55323
|
function readInstalledPlugins2(home) {
|
|
55239
|
-
const pluginsDir =
|
|
55240
|
-
const v2 =
|
|
55241
|
-
const v1 =
|
|
55324
|
+
const pluginsDir = import_node_path33.default.join(home, ".claude", "plugins");
|
|
55325
|
+
const v2 = import_node_path33.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
55326
|
+
const v1 = import_node_path33.default.join(pluginsDir, "installed_plugins.json");
|
|
55242
55327
|
let raw = null;
|
|
55243
55328
|
for (const candidate of [v2, v1]) {
|
|
55244
55329
|
try {
|
|
55245
|
-
raw =
|
|
55330
|
+
raw = import_node_fs30.default.readFileSync(candidate, "utf8");
|
|
55246
55331
|
break;
|
|
55247
55332
|
} catch {
|
|
55248
55333
|
}
|
|
@@ -55267,19 +55352,19 @@ function readInstalledPlugins2(home) {
|
|
|
55267
55352
|
return out;
|
|
55268
55353
|
}
|
|
55269
55354
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
55270
|
-
let cur =
|
|
55271
|
-
const fsRoot =
|
|
55355
|
+
let cur = import_node_path33.default.resolve(startCwd);
|
|
55356
|
+
const fsRoot = import_node_path33.default.parse(cur).root;
|
|
55272
55357
|
while (true) {
|
|
55273
|
-
scanAgentsDir(
|
|
55358
|
+
scanAgentsDir(import_node_path33.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
55274
55359
|
let hasGit = false;
|
|
55275
55360
|
try {
|
|
55276
|
-
hasGit =
|
|
55361
|
+
hasGit = import_node_fs30.default.existsSync(import_node_path33.default.join(cur, ".git"));
|
|
55277
55362
|
} catch {
|
|
55278
55363
|
}
|
|
55279
55364
|
if (hasGit) return;
|
|
55280
55365
|
if (cur === home) return;
|
|
55281
55366
|
if (cur === fsRoot) return;
|
|
55282
|
-
const parent =
|
|
55367
|
+
const parent = import_node_path33.default.dirname(cur);
|
|
55283
55368
|
if (parent === cur) return;
|
|
55284
55369
|
cur = parent;
|
|
55285
55370
|
}
|
|
@@ -55314,7 +55399,7 @@ var AgentsScanner = class {
|
|
|
55314
55399
|
}
|
|
55315
55400
|
const fsBlock = [];
|
|
55316
55401
|
scanAgentsDir(
|
|
55317
|
-
|
|
55402
|
+
import_node_path33.default.join(this.home, ".claude", "agents"),
|
|
55318
55403
|
"global",
|
|
55319
55404
|
seen,
|
|
55320
55405
|
fsBlock
|
|
@@ -55328,7 +55413,7 @@ var AgentsScanner = class {
|
|
|
55328
55413
|
...this.extraPluginRoots
|
|
55329
55414
|
];
|
|
55330
55415
|
for (const { name, root } of plugins) {
|
|
55331
|
-
const agentsRoot =
|
|
55416
|
+
const agentsRoot = import_node_path33.default.join(root, "agents");
|
|
55332
55417
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
55333
55418
|
}
|
|
55334
55419
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -55336,15 +55421,15 @@ var AgentsScanner = class {
|
|
|
55336
55421
|
};
|
|
55337
55422
|
|
|
55338
55423
|
// src/observer/session-observer.ts
|
|
55339
|
-
var
|
|
55424
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
55340
55425
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
55341
|
-
var
|
|
55426
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
55342
55427
|
init_claude_history();
|
|
55343
55428
|
|
|
55344
55429
|
// src/observer/subagent-meta-observer.ts
|
|
55345
|
-
var
|
|
55430
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
55346
55431
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
55347
|
-
var
|
|
55432
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
55348
55433
|
init_claude_history();
|
|
55349
55434
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
55350
55435
|
var SubagentMetaObserver = class {
|
|
@@ -55357,7 +55442,7 @@ var SubagentMetaObserver = class {
|
|
|
55357
55442
|
watches = /* @__PURE__ */ new Map();
|
|
55358
55443
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
55359
55444
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
55360
|
-
return
|
|
55445
|
+
return import_node_path34.default.join(
|
|
55361
55446
|
this.home,
|
|
55362
55447
|
".claude",
|
|
55363
55448
|
"projects",
|
|
@@ -55387,7 +55472,7 @@ var SubagentMetaObserver = class {
|
|
|
55387
55472
|
attachWatcher(w2) {
|
|
55388
55473
|
if (w2.watcher) return;
|
|
55389
55474
|
try {
|
|
55390
|
-
w2.watcher =
|
|
55475
|
+
w2.watcher = import_node_fs31.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
55391
55476
|
if (!name) return;
|
|
55392
55477
|
const m2 = META_RE.exec(String(name));
|
|
55393
55478
|
if (!m2) return;
|
|
@@ -55399,7 +55484,7 @@ var SubagentMetaObserver = class {
|
|
|
55399
55484
|
scan(w2) {
|
|
55400
55485
|
let entries;
|
|
55401
55486
|
try {
|
|
55402
|
-
entries =
|
|
55487
|
+
entries = import_node_fs31.default.readdirSync(w2.dirPath);
|
|
55403
55488
|
} catch {
|
|
55404
55489
|
return;
|
|
55405
55490
|
}
|
|
@@ -55413,10 +55498,10 @@ var SubagentMetaObserver = class {
|
|
|
55413
55498
|
if (!m2) return;
|
|
55414
55499
|
const agentId = m2[1];
|
|
55415
55500
|
if (w2.emitted.has(agentId)) return;
|
|
55416
|
-
const file =
|
|
55501
|
+
const file = import_node_path34.default.join(w2.dirPath, name);
|
|
55417
55502
|
let raw;
|
|
55418
55503
|
try {
|
|
55419
|
-
raw =
|
|
55504
|
+
raw = import_node_fs31.default.readFileSync(file, "utf8");
|
|
55420
55505
|
} catch {
|
|
55421
55506
|
return;
|
|
55422
55507
|
}
|
|
@@ -55473,14 +55558,14 @@ var SessionObserver = class {
|
|
|
55473
55558
|
metaObserver;
|
|
55474
55559
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
55475
55560
|
if (override) return override;
|
|
55476
|
-
return
|
|
55561
|
+
return import_node_path35.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
55477
55562
|
}
|
|
55478
55563
|
start(args) {
|
|
55479
55564
|
this.stop(args.sessionId);
|
|
55480
55565
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
55481
55566
|
let size = 0;
|
|
55482
55567
|
try {
|
|
55483
|
-
size =
|
|
55568
|
+
size = import_node_fs32.default.statSync(filePath).size;
|
|
55484
55569
|
} catch {
|
|
55485
55570
|
}
|
|
55486
55571
|
const w2 = {
|
|
@@ -55493,16 +55578,16 @@ var SessionObserver = class {
|
|
|
55493
55578
|
adapter: args.adapter,
|
|
55494
55579
|
prevIsRejectSentinel: false,
|
|
55495
55580
|
toolSessionId: args.toolSessionId,
|
|
55496
|
-
sawFile:
|
|
55581
|
+
sawFile: import_node_fs32.default.existsSync(filePath),
|
|
55497
55582
|
lastRelocateScanMs: 0,
|
|
55498
55583
|
pendingCwdDerive: false,
|
|
55499
55584
|
lastDeriveMs: 0
|
|
55500
55585
|
};
|
|
55501
55586
|
try {
|
|
55502
|
-
|
|
55587
|
+
import_node_fs32.default.mkdirSync(import_node_path35.default.dirname(filePath), { recursive: true });
|
|
55503
55588
|
} catch {
|
|
55504
55589
|
}
|
|
55505
|
-
w2.watcher =
|
|
55590
|
+
w2.watcher = import_node_fs32.default.watch(import_node_path35.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
55506
55591
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
55507
55592
|
this.poll(w2);
|
|
55508
55593
|
});
|
|
@@ -55525,7 +55610,7 @@ var SessionObserver = class {
|
|
|
55525
55610
|
// 异常静默吞,不阻塞 watcher 启动
|
|
55526
55611
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
55527
55612
|
try {
|
|
55528
|
-
const raw =
|
|
55613
|
+
const raw = import_node_fs32.default.readFileSync(w2.filePath, "utf8");
|
|
55529
55614
|
if (!raw) return;
|
|
55530
55615
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
55531
55616
|
if (allLines.length === 0) return;
|
|
@@ -55549,7 +55634,7 @@ var SessionObserver = class {
|
|
|
55549
55634
|
poll(w2) {
|
|
55550
55635
|
let size = 0;
|
|
55551
55636
|
try {
|
|
55552
|
-
size =
|
|
55637
|
+
size = import_node_fs32.default.statSync(w2.filePath).size;
|
|
55553
55638
|
} catch {
|
|
55554
55639
|
if (w2.sawFile) this.maybeRelocate(w2);
|
|
55555
55640
|
return;
|
|
@@ -55560,11 +55645,11 @@ var SessionObserver = class {
|
|
|
55560
55645
|
w2.buf = "";
|
|
55561
55646
|
}
|
|
55562
55647
|
if (size === w2.lastSize) return;
|
|
55563
|
-
const fd =
|
|
55648
|
+
const fd = import_node_fs32.default.openSync(w2.filePath, "r");
|
|
55564
55649
|
try {
|
|
55565
55650
|
const len = size - w2.lastSize;
|
|
55566
55651
|
const buf = Buffer.alloc(len);
|
|
55567
|
-
|
|
55652
|
+
import_node_fs32.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
55568
55653
|
w2.lastSize = size;
|
|
55569
55654
|
w2.buf += buf.toString("utf8");
|
|
55570
55655
|
let newlineIndex;
|
|
@@ -55587,7 +55672,7 @@ var SessionObserver = class {
|
|
|
55587
55672
|
}
|
|
55588
55673
|
}
|
|
55589
55674
|
} finally {
|
|
55590
|
-
|
|
55675
|
+
import_node_fs32.default.closeSync(fd);
|
|
55591
55676
|
}
|
|
55592
55677
|
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
55593
55678
|
}
|
|
@@ -55599,7 +55684,7 @@ var SessionObserver = class {
|
|
|
55599
55684
|
const now = Date.now();
|
|
55600
55685
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
55601
55686
|
w2.lastRelocateScanMs = now;
|
|
55602
|
-
const projectsRoot =
|
|
55687
|
+
const projectsRoot = import_node_path35.default.join(this.home, ".claude", "projects");
|
|
55603
55688
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
55604
55689
|
if (!found || found === w2.filePath) return;
|
|
55605
55690
|
try {
|
|
@@ -55608,7 +55693,7 @@ var SessionObserver = class {
|
|
|
55608
55693
|
}
|
|
55609
55694
|
w2.filePath = found;
|
|
55610
55695
|
try {
|
|
55611
|
-
w2.watcher =
|
|
55696
|
+
w2.watcher = import_node_fs32.default.watch(import_node_path35.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
55612
55697
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
55613
55698
|
this.poll(w2);
|
|
55614
55699
|
});
|
|
@@ -55729,9 +55814,9 @@ function listRegistered() {
|
|
|
55729
55814
|
|
|
55730
55815
|
// src/tools/title-generator.ts
|
|
55731
55816
|
var import_node_child_process8 = require("child_process");
|
|
55732
|
-
var
|
|
55817
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
55733
55818
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
55734
|
-
var
|
|
55819
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
55735
55820
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
55736
55821
|
var TITLE_MODEL_BY_TOOL = {
|
|
55737
55822
|
claude: "haiku",
|
|
@@ -55802,21 +55887,21 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
55802
55887
|
if (!text) return null;
|
|
55803
55888
|
let workDir;
|
|
55804
55889
|
try {
|
|
55805
|
-
workDir =
|
|
55890
|
+
workDir = import_node_fs33.default.mkdtempSync(import_node_path36.default.join(import_node_os12.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
55806
55891
|
} catch {
|
|
55807
55892
|
return null;
|
|
55808
55893
|
}
|
|
55809
55894
|
const cleanupWorkDir = () => {
|
|
55810
55895
|
try {
|
|
55811
|
-
|
|
55896
|
+
import_node_fs33.default.rmSync(workDir, { recursive: true, force: true });
|
|
55812
55897
|
} catch {
|
|
55813
55898
|
}
|
|
55814
55899
|
};
|
|
55815
|
-
const outFile =
|
|
55816
|
-
const schemaFile =
|
|
55900
|
+
const outFile = import_node_path36.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
55901
|
+
const schemaFile = import_node_path36.default.join(workDir, "title-schema.json");
|
|
55817
55902
|
if (tool === "codex") {
|
|
55818
55903
|
try {
|
|
55819
|
-
|
|
55904
|
+
import_node_fs33.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
55820
55905
|
} catch {
|
|
55821
55906
|
cleanupWorkDir();
|
|
55822
55907
|
return null;
|
|
@@ -55866,7 +55951,7 @@ async function generateSessionTitle(tool, firstMessage, deps = {}) {
|
|
|
55866
55951
|
if (tool === "claude") return finish(parseTitleJson(stdout));
|
|
55867
55952
|
let fileText = "";
|
|
55868
55953
|
try {
|
|
55869
|
-
fileText =
|
|
55954
|
+
fileText = import_node_fs33.default.readFileSync(outFile, "utf8");
|
|
55870
55955
|
} catch {
|
|
55871
55956
|
return finish(null);
|
|
55872
55957
|
}
|
|
@@ -56551,8 +56636,8 @@ async function authenticate(token, deps) {
|
|
|
56551
56636
|
}
|
|
56552
56637
|
|
|
56553
56638
|
// src/legacy-cleanup.ts
|
|
56554
|
-
var
|
|
56555
|
-
var
|
|
56639
|
+
var fs42 = __toESM(require("fs/promises"), 1);
|
|
56640
|
+
var path44 = __toESM(require("path"), 1);
|
|
56556
56641
|
var LEGACY_FILES = [
|
|
56557
56642
|
"personal-capability.json",
|
|
56558
56643
|
"received-capabilities.json",
|
|
@@ -56561,9 +56646,9 @@ var LEGACY_FILES = [
|
|
|
56561
56646
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
56562
56647
|
const removed = [];
|
|
56563
56648
|
for (const name of LEGACY_FILES) {
|
|
56564
|
-
const p2 =
|
|
56649
|
+
const p2 = path44.join(dataDir, name);
|
|
56565
56650
|
try {
|
|
56566
|
-
await
|
|
56651
|
+
await fs42.unlink(p2);
|
|
56567
56652
|
removed.push(name);
|
|
56568
56653
|
logger.debug("legacy capability file removed", { file: name });
|
|
56569
56654
|
} catch (err) {
|
|
@@ -56575,13 +56660,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
56575
56660
|
}
|
|
56576
56661
|
|
|
56577
56662
|
// src/inbox/inbox-store.ts
|
|
56578
|
-
var
|
|
56579
|
-
var
|
|
56663
|
+
var fs43 = __toESM(require("fs"), 1);
|
|
56664
|
+
var path45 = __toESM(require("path"), 1);
|
|
56580
56665
|
var INBOX_SUBDIR = "inbox";
|
|
56581
56666
|
var InboxStore = class {
|
|
56582
56667
|
constructor(dataDir) {
|
|
56583
56668
|
this.dataDir = dataDir;
|
|
56584
|
-
|
|
56669
|
+
fs43.mkdirSync(this.dirPath(), { recursive: true });
|
|
56585
56670
|
}
|
|
56586
56671
|
dataDir;
|
|
56587
56672
|
/**
|
|
@@ -56593,7 +56678,7 @@ var InboxStore = class {
|
|
|
56593
56678
|
const file = this.filePath(peerDeviceId);
|
|
56594
56679
|
let raw;
|
|
56595
56680
|
try {
|
|
56596
|
-
raw =
|
|
56681
|
+
raw = fs43.readFileSync(file, "utf8");
|
|
56597
56682
|
} catch (err) {
|
|
56598
56683
|
if (err?.code === "ENOENT") return [];
|
|
56599
56684
|
return [];
|
|
@@ -56609,7 +56694,7 @@ var InboxStore = class {
|
|
|
56609
56694
|
const dir = this.dirPath();
|
|
56610
56695
|
let entries;
|
|
56611
56696
|
try {
|
|
56612
|
-
entries =
|
|
56697
|
+
entries = fs43.readdirSync(dir);
|
|
56613
56698
|
} catch (err) {
|
|
56614
56699
|
if (err?.code === "ENOENT") return [];
|
|
56615
56700
|
return [];
|
|
@@ -56625,9 +56710,9 @@ var InboxStore = class {
|
|
|
56625
56710
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
56626
56711
|
const file = this.filePath(message.peerDeviceId);
|
|
56627
56712
|
const line = JSON.stringify(message) + "\n";
|
|
56628
|
-
|
|
56713
|
+
fs43.appendFileSync(file, line, { mode: 384 });
|
|
56629
56714
|
try {
|
|
56630
|
-
|
|
56715
|
+
fs43.chmodSync(file, 384);
|
|
56631
56716
|
} catch {
|
|
56632
56717
|
}
|
|
56633
56718
|
}
|
|
@@ -56657,7 +56742,7 @@ var InboxStore = class {
|
|
|
56657
56742
|
removeByPeerDeviceId(peerDeviceId) {
|
|
56658
56743
|
const file = this.filePath(peerDeviceId);
|
|
56659
56744
|
try {
|
|
56660
|
-
|
|
56745
|
+
fs43.unlinkSync(file);
|
|
56661
56746
|
} catch (err) {
|
|
56662
56747
|
if (err?.code === "ENOENT") return;
|
|
56663
56748
|
}
|
|
@@ -56666,18 +56751,18 @@ var InboxStore = class {
|
|
|
56666
56751
|
const file = this.filePath(peerDeviceId);
|
|
56667
56752
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
56668
56753
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
56669
|
-
|
|
56670
|
-
|
|
56754
|
+
fs43.writeFileSync(tmp, content, { mode: 384 });
|
|
56755
|
+
fs43.renameSync(tmp, file);
|
|
56671
56756
|
try {
|
|
56672
|
-
|
|
56757
|
+
fs43.chmodSync(file, 384);
|
|
56673
56758
|
} catch {
|
|
56674
56759
|
}
|
|
56675
56760
|
}
|
|
56676
56761
|
dirPath() {
|
|
56677
|
-
return
|
|
56762
|
+
return path45.join(this.dataDir, INBOX_SUBDIR);
|
|
56678
56763
|
}
|
|
56679
56764
|
filePath(peerDeviceId) {
|
|
56680
|
-
return
|
|
56765
|
+
return path45.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
56681
56766
|
}
|
|
56682
56767
|
};
|
|
56683
56768
|
function parseAllLines(raw) {
|
|
@@ -56765,8 +56850,8 @@ var InboxManager = class {
|
|
|
56765
56850
|
};
|
|
56766
56851
|
|
|
56767
56852
|
// src/state/contact-store.ts
|
|
56768
|
-
var
|
|
56769
|
-
var
|
|
56853
|
+
var fs44 = __toESM(require("fs"), 1);
|
|
56854
|
+
var path46 = __toESM(require("path"), 1);
|
|
56770
56855
|
var FILE_NAME = "contacts.json";
|
|
56771
56856
|
var ContactStore = class {
|
|
56772
56857
|
constructor(dataDir) {
|
|
@@ -56776,10 +56861,10 @@ var ContactStore = class {
|
|
|
56776
56861
|
contacts = /* @__PURE__ */ new Map();
|
|
56777
56862
|
load() {
|
|
56778
56863
|
this.contacts.clear();
|
|
56779
|
-
const file =
|
|
56864
|
+
const file = path46.join(this.dataDir, FILE_NAME);
|
|
56780
56865
|
let raw;
|
|
56781
56866
|
try {
|
|
56782
|
-
raw =
|
|
56867
|
+
raw = fs44.readFileSync(file, "utf8");
|
|
56783
56868
|
} catch (err) {
|
|
56784
56869
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
56785
56870
|
return;
|
|
@@ -56848,20 +56933,20 @@ var ContactStore = class {
|
|
|
56848
56933
|
return true;
|
|
56849
56934
|
}
|
|
56850
56935
|
flush() {
|
|
56851
|
-
const file =
|
|
56936
|
+
const file = path46.join(this.dataDir, FILE_NAME);
|
|
56852
56937
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
56853
56938
|
const content = JSON.stringify(
|
|
56854
56939
|
{ contacts: Array.from(this.contacts.values()) },
|
|
56855
56940
|
null,
|
|
56856
56941
|
2
|
|
56857
56942
|
);
|
|
56858
|
-
|
|
56859
|
-
|
|
56860
|
-
|
|
56943
|
+
fs44.mkdirSync(this.dataDir, { recursive: true });
|
|
56944
|
+
fs44.writeFileSync(tmp, content, { mode: 384 });
|
|
56945
|
+
fs44.renameSync(tmp, file);
|
|
56861
56946
|
}
|
|
56862
56947
|
renameBak(file) {
|
|
56863
56948
|
try {
|
|
56864
|
-
|
|
56949
|
+
fs44.renameSync(file, `${file}.bak`);
|
|
56865
56950
|
} catch {
|
|
56866
56951
|
}
|
|
56867
56952
|
}
|
|
@@ -56969,61 +57054,61 @@ async function connectRemote(args) {
|
|
|
56969
57054
|
}
|
|
56970
57055
|
|
|
56971
57056
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
56972
|
-
var
|
|
56973
|
-
var
|
|
57057
|
+
var fs45 = __toESM(require("fs"), 1);
|
|
57058
|
+
var path47 = __toESM(require("path"), 1);
|
|
56974
57059
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
56975
57060
|
function migrateFlattenSessions(opts) {
|
|
56976
57061
|
const dataDir = opts.dataDir;
|
|
56977
57062
|
const now = opts.now ?? Date.now;
|
|
56978
|
-
const sessionsDir =
|
|
56979
|
-
const flagPath =
|
|
57063
|
+
const sessionsDir = path47.join(dataDir, "sessions");
|
|
57064
|
+
const flagPath = path47.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
56980
57065
|
if (existsSync3(flagPath)) {
|
|
56981
57066
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
56982
57067
|
}
|
|
56983
57068
|
let movedBare = 0;
|
|
56984
57069
|
let movedVmOwner = 0;
|
|
56985
57070
|
let archivedListener = 0;
|
|
56986
|
-
const defaultDir =
|
|
57071
|
+
const defaultDir = path47.join(sessionsDir, "default");
|
|
56987
57072
|
if (existsSync3(defaultDir)) {
|
|
56988
57073
|
for (const entry of readdirSafe(defaultDir)) {
|
|
56989
57074
|
if (!entry.endsWith(".json")) continue;
|
|
56990
|
-
const src =
|
|
56991
|
-
const dst =
|
|
56992
|
-
|
|
57075
|
+
const src = path47.join(defaultDir, entry);
|
|
57076
|
+
const dst = path47.join(sessionsDir, entry);
|
|
57077
|
+
fs45.renameSync(src, dst);
|
|
56993
57078
|
movedBare += 1;
|
|
56994
57079
|
}
|
|
56995
57080
|
rmdirIfEmpty(defaultDir);
|
|
56996
57081
|
}
|
|
56997
57082
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
56998
|
-
const personaDir =
|
|
57083
|
+
const personaDir = path47.join(sessionsDir, pid);
|
|
56999
57084
|
if (!isDir(personaDir)) continue;
|
|
57000
57085
|
if (pid === "default") continue;
|
|
57001
|
-
const ownerSrc =
|
|
57086
|
+
const ownerSrc = path47.join(personaDir, "owner");
|
|
57002
57087
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
57003
|
-
const ownerDst =
|
|
57004
|
-
|
|
57088
|
+
const ownerDst = path47.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
57089
|
+
fs45.mkdirSync(ownerDst, { recursive: true });
|
|
57005
57090
|
for (const file of readdirSafe(ownerSrc)) {
|
|
57006
57091
|
if (!file.endsWith(".json")) continue;
|
|
57007
|
-
|
|
57092
|
+
fs45.renameSync(path47.join(ownerSrc, file), path47.join(ownerDst, file));
|
|
57008
57093
|
movedVmOwner += 1;
|
|
57009
57094
|
}
|
|
57010
57095
|
rmdirIfEmpty(ownerSrc);
|
|
57011
57096
|
}
|
|
57012
|
-
const listenerSrc =
|
|
57097
|
+
const listenerSrc = path47.join(personaDir, "listener");
|
|
57013
57098
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
57014
|
-
const archiveDst =
|
|
57015
|
-
|
|
57099
|
+
const archiveDst = path47.join(dataDir, ".legacy", `listener-${pid}`);
|
|
57100
|
+
fs45.mkdirSync(archiveDst, { recursive: true });
|
|
57016
57101
|
for (const file of readdirSafe(listenerSrc)) {
|
|
57017
57102
|
if (!file.endsWith(".json")) continue;
|
|
57018
|
-
|
|
57103
|
+
fs45.renameSync(path47.join(listenerSrc, file), path47.join(archiveDst, file));
|
|
57019
57104
|
archivedListener += 1;
|
|
57020
57105
|
}
|
|
57021
57106
|
rmdirIfEmpty(listenerSrc);
|
|
57022
57107
|
}
|
|
57023
57108
|
rmdirIfEmpty(personaDir);
|
|
57024
57109
|
}
|
|
57025
|
-
|
|
57026
|
-
|
|
57110
|
+
fs45.mkdirSync(sessionsDir, { recursive: true });
|
|
57111
|
+
fs45.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
57027
57112
|
return {
|
|
57028
57113
|
skipped: false,
|
|
57029
57114
|
flagWritten: true,
|
|
@@ -57034,7 +57119,7 @@ function migrateFlattenSessions(opts) {
|
|
|
57034
57119
|
}
|
|
57035
57120
|
function existsSync3(p2) {
|
|
57036
57121
|
try {
|
|
57037
|
-
|
|
57122
|
+
fs45.statSync(p2);
|
|
57038
57123
|
return true;
|
|
57039
57124
|
} catch {
|
|
57040
57125
|
return false;
|
|
@@ -57042,61 +57127,61 @@ function existsSync3(p2) {
|
|
|
57042
57127
|
}
|
|
57043
57128
|
function isDir(p2) {
|
|
57044
57129
|
try {
|
|
57045
|
-
return
|
|
57130
|
+
return fs45.statSync(p2).isDirectory();
|
|
57046
57131
|
} catch {
|
|
57047
57132
|
return false;
|
|
57048
57133
|
}
|
|
57049
57134
|
}
|
|
57050
57135
|
function readdirSafe(p2) {
|
|
57051
57136
|
try {
|
|
57052
|
-
return
|
|
57137
|
+
return fs45.readdirSync(p2);
|
|
57053
57138
|
} catch {
|
|
57054
57139
|
return [];
|
|
57055
57140
|
}
|
|
57056
57141
|
}
|
|
57057
57142
|
function rmdirIfEmpty(p2) {
|
|
57058
57143
|
try {
|
|
57059
|
-
|
|
57144
|
+
fs45.rmdirSync(p2);
|
|
57060
57145
|
} catch {
|
|
57061
57146
|
}
|
|
57062
57147
|
}
|
|
57063
57148
|
|
|
57064
57149
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
57065
|
-
var
|
|
57066
|
-
var
|
|
57150
|
+
var fs46 = __toESM(require("fs"), 1);
|
|
57151
|
+
var path48 = __toESM(require("path"), 1);
|
|
57067
57152
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
57068
57153
|
function dropSeededProjects(opts) {
|
|
57069
|
-
|
|
57070
|
-
const flag =
|
|
57071
|
-
if (
|
|
57072
|
-
const file =
|
|
57154
|
+
fs46.mkdirSync(opts.dataDir, { recursive: true });
|
|
57155
|
+
const flag = path48.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
57156
|
+
if (fs46.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
57157
|
+
const file = path48.join(opts.dataDir, "projects.json");
|
|
57073
57158
|
let raw = null;
|
|
57074
57159
|
let dropped = 0;
|
|
57075
57160
|
try {
|
|
57076
|
-
raw =
|
|
57161
|
+
raw = fs46.readFileSync(file, "utf8");
|
|
57077
57162
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
57078
57163
|
} catch {
|
|
57079
57164
|
}
|
|
57080
57165
|
let backup = null;
|
|
57081
57166
|
if (raw != null && dropped > 0) {
|
|
57082
|
-
const dir =
|
|
57083
|
-
|
|
57084
|
-
backup =
|
|
57085
|
-
|
|
57167
|
+
const dir = path48.join(opts.dataDir, "backups");
|
|
57168
|
+
fs46.mkdirSync(dir, { recursive: true });
|
|
57169
|
+
backup = path48.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
57170
|
+
fs46.writeFileSync(backup, raw);
|
|
57086
57171
|
}
|
|
57087
57172
|
if (raw != null || dropped > 0) {
|
|
57088
|
-
|
|
57173
|
+
fs46.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
57089
57174
|
}
|
|
57090
|
-
|
|
57175
|
+
fs46.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
57091
57176
|
return { skipped: false, dropped, backup };
|
|
57092
57177
|
}
|
|
57093
57178
|
|
|
57094
57179
|
// src/transport/http-router.ts
|
|
57095
|
-
var
|
|
57096
|
-
var
|
|
57180
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
57181
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
57097
57182
|
|
|
57098
57183
|
// src/attachment/mime.ts
|
|
57099
|
-
var
|
|
57184
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
57100
57185
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
57101
57186
|
var EXT_TO_NATIVE_MIME = {
|
|
57102
57187
|
// 图片
|
|
@@ -57203,7 +57288,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
57203
57288
|
".mk"
|
|
57204
57289
|
]);
|
|
57205
57290
|
function lookupMime(filePathOrName) {
|
|
57206
|
-
const ext =
|
|
57291
|
+
const ext = import_node_path37.default.extname(filePathOrName).toLowerCase();
|
|
57207
57292
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
57208
57293
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
57209
57294
|
return "application/octet-stream";
|
|
@@ -57273,8 +57358,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
57273
57358
|
}
|
|
57274
57359
|
|
|
57275
57360
|
// src/attachment/upload.ts
|
|
57276
|
-
var
|
|
57277
|
-
var
|
|
57361
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
57362
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
57278
57363
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
57279
57364
|
var import_promises5 = require("stream/promises");
|
|
57280
57365
|
var UploadError = class extends Error {
|
|
@@ -57286,22 +57371,22 @@ var UploadError = class extends Error {
|
|
|
57286
57371
|
code;
|
|
57287
57372
|
};
|
|
57288
57373
|
function assertValidFileName(fileName) {
|
|
57289
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
57374
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path38.default.basename(fileName)) {
|
|
57290
57375
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
57291
57376
|
}
|
|
57292
57377
|
}
|
|
57293
57378
|
var HASH_PREFIX_LEN = 16;
|
|
57294
57379
|
async function writeUploadedAttachment(args) {
|
|
57295
57380
|
assertValidFileName(args.fileName);
|
|
57296
|
-
const attachmentsRoot =
|
|
57381
|
+
const attachmentsRoot = import_node_path38.default.join(args.baseDir, ".attachments");
|
|
57297
57382
|
try {
|
|
57298
|
-
|
|
57383
|
+
import_node_fs34.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
57299
57384
|
} catch (err) {
|
|
57300
57385
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
57301
57386
|
}
|
|
57302
57387
|
const hasher = import_node_crypto9.default.createHash("sha256");
|
|
57303
57388
|
let actualSize = 0;
|
|
57304
|
-
const tmpPath =
|
|
57389
|
+
const tmpPath = import_node_path38.default.join(
|
|
57305
57390
|
attachmentsRoot,
|
|
57306
57391
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto9.default.randomBytes(4).toString("hex")}`
|
|
57307
57392
|
);
|
|
@@ -57316,18 +57401,18 @@ async function writeUploadedAttachment(args) {
|
|
|
57316
57401
|
yield buf;
|
|
57317
57402
|
}
|
|
57318
57403
|
},
|
|
57319
|
-
|
|
57404
|
+
import_node_fs34.default.createWriteStream(tmpPath, { mode: 384 })
|
|
57320
57405
|
);
|
|
57321
57406
|
} catch (err) {
|
|
57322
57407
|
try {
|
|
57323
|
-
|
|
57408
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
57324
57409
|
} catch {
|
|
57325
57410
|
}
|
|
57326
57411
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
57327
57412
|
}
|
|
57328
57413
|
if (actualSize !== args.contentLength) {
|
|
57329
57414
|
try {
|
|
57330
|
-
|
|
57415
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
57331
57416
|
} catch {
|
|
57332
57417
|
}
|
|
57333
57418
|
throw new UploadError(
|
|
@@ -57336,34 +57421,34 @@ async function writeUploadedAttachment(args) {
|
|
|
57336
57421
|
);
|
|
57337
57422
|
}
|
|
57338
57423
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
57339
|
-
const hashDir =
|
|
57424
|
+
const hashDir = import_node_path38.default.join(attachmentsRoot, attachmentId);
|
|
57340
57425
|
let finalFileName;
|
|
57341
57426
|
let hashDirExists = false;
|
|
57342
57427
|
try {
|
|
57343
|
-
hashDirExists =
|
|
57428
|
+
hashDirExists = import_node_fs34.default.statSync(hashDir).isDirectory();
|
|
57344
57429
|
} catch {
|
|
57345
57430
|
}
|
|
57346
57431
|
if (hashDirExists) {
|
|
57347
|
-
const existing =
|
|
57432
|
+
const existing = import_node_fs34.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
57348
57433
|
finalFileName = existing[0] ?? args.fileName;
|
|
57349
57434
|
try {
|
|
57350
|
-
|
|
57435
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
57351
57436
|
} catch {
|
|
57352
57437
|
}
|
|
57353
57438
|
} else {
|
|
57354
57439
|
try {
|
|
57355
|
-
|
|
57440
|
+
import_node_fs34.default.mkdirSync(hashDir, { recursive: true });
|
|
57356
57441
|
finalFileName = args.fileName;
|
|
57357
|
-
|
|
57442
|
+
import_node_fs34.default.renameSync(tmpPath, import_node_path38.default.join(hashDir, finalFileName));
|
|
57358
57443
|
} catch (err) {
|
|
57359
57444
|
try {
|
|
57360
|
-
|
|
57445
|
+
import_node_fs34.default.unlinkSync(tmpPath);
|
|
57361
57446
|
} catch {
|
|
57362
57447
|
}
|
|
57363
57448
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
57364
57449
|
}
|
|
57365
57450
|
}
|
|
57366
|
-
const absPath =
|
|
57451
|
+
const absPath = import_node_path38.default.join(hashDir, finalFileName);
|
|
57367
57452
|
const relPath = absPath;
|
|
57368
57453
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
57369
57454
|
relPath: absPath,
|
|
@@ -57378,7 +57463,7 @@ async function writeUploadedAttachment(args) {
|
|
|
57378
57463
|
|
|
57379
57464
|
// src/extension/import.ts
|
|
57380
57465
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
57381
|
-
var
|
|
57466
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
57382
57467
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
57383
57468
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
57384
57469
|
var ImportError = class extends Error {
|
|
@@ -57396,7 +57481,7 @@ async function importZip(buf, root) {
|
|
|
57396
57481
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
57397
57482
|
}
|
|
57398
57483
|
for (const name of Object.keys(zip.files)) {
|
|
57399
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
57484
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path39.default.isAbsolute(name)) {
|
|
57400
57485
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
57401
57486
|
}
|
|
57402
57487
|
}
|
|
@@ -57429,7 +57514,7 @@ async function importZip(buf, root) {
|
|
|
57429
57514
|
);
|
|
57430
57515
|
}
|
|
57431
57516
|
}
|
|
57432
|
-
const destDir =
|
|
57517
|
+
const destDir = import_node_path39.default.join(root, manifest.id);
|
|
57433
57518
|
let destExists = false;
|
|
57434
57519
|
try {
|
|
57435
57520
|
await import_promises6.default.access(destDir);
|
|
@@ -57439,15 +57524,15 @@ async function importZip(buf, root) {
|
|
|
57439
57524
|
if (destExists) {
|
|
57440
57525
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
57441
57526
|
}
|
|
57442
|
-
const stage = await import_promises6.default.mkdtemp(
|
|
57527
|
+
const stage = await import_promises6.default.mkdtemp(import_node_path39.default.join(import_node_os13.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
57443
57528
|
try {
|
|
57444
57529
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
57445
|
-
const dest =
|
|
57530
|
+
const dest = import_node_path39.default.join(stage, name);
|
|
57446
57531
|
if (entry.dir) {
|
|
57447
57532
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
57448
57533
|
continue;
|
|
57449
57534
|
}
|
|
57450
|
-
await import_promises6.default.mkdir(
|
|
57535
|
+
await import_promises6.default.mkdir(import_node_path39.default.dirname(dest), { recursive: true });
|
|
57451
57536
|
const content = await entry.async("nodebuffer");
|
|
57452
57537
|
await import_promises6.default.writeFile(dest, content);
|
|
57453
57538
|
}
|
|
@@ -57477,7 +57562,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
57477
57562
|
".wasm": "application/wasm"
|
|
57478
57563
|
};
|
|
57479
57564
|
function shareUiAssetMime(filePath) {
|
|
57480
|
-
const ext =
|
|
57565
|
+
const ext = import_node_path40.default.extname(filePath).toLowerCase();
|
|
57481
57566
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
57482
57567
|
}
|
|
57483
57568
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -57576,7 +57661,7 @@ function isValidUploadFileName(fileName) {
|
|
|
57576
57661
|
if (fileName === "." || fileName === "..") return false;
|
|
57577
57662
|
if (fileName.startsWith(".")) return false;
|
|
57578
57663
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
57579
|
-
return fileName ===
|
|
57664
|
+
return fileName === import_node_path40.default.basename(fileName);
|
|
57580
57665
|
}
|
|
57581
57666
|
function createHttpRouter(deps) {
|
|
57582
57667
|
return async (req, res) => {
|
|
@@ -57664,7 +57749,7 @@ function createHttpRouter(deps) {
|
|
|
57664
57749
|
}
|
|
57665
57750
|
let buf;
|
|
57666
57751
|
try {
|
|
57667
|
-
buf = await
|
|
57752
|
+
buf = await import_node_fs35.default.promises.readFile(abs);
|
|
57668
57753
|
} catch {
|
|
57669
57754
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
57670
57755
|
return true;
|
|
@@ -57812,7 +57897,7 @@ function createHttpRouter(deps) {
|
|
|
57812
57897
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
57813
57898
|
return true;
|
|
57814
57899
|
}
|
|
57815
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
57900
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path40.default.basename(r.absPath)));
|
|
57816
57901
|
return true;
|
|
57817
57902
|
}
|
|
57818
57903
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -57933,7 +58018,7 @@ function createHttpRouter(deps) {
|
|
|
57933
58018
|
return true;
|
|
57934
58019
|
}
|
|
57935
58020
|
let absPath;
|
|
57936
|
-
if (
|
|
58021
|
+
if (import_node_path40.default.isAbsolute(pathParam)) {
|
|
57937
58022
|
absPath = pathParam;
|
|
57938
58023
|
} else if (deps.sessionStore) {
|
|
57939
58024
|
const file = deps.sessionStore.read(sid);
|
|
@@ -57941,7 +58026,7 @@ function createHttpRouter(deps) {
|
|
|
57941
58026
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
57942
58027
|
return true;
|
|
57943
58028
|
}
|
|
57944
|
-
absPath =
|
|
58029
|
+
absPath = import_node_path40.default.join(file.cwd, pathParam);
|
|
57945
58030
|
} else {
|
|
57946
58031
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
57947
58032
|
return true;
|
|
@@ -58028,7 +58113,7 @@ function withCtx(ctx, body) {
|
|
|
58028
58113
|
function streamFile(res, absPath, logger) {
|
|
58029
58114
|
let stat;
|
|
58030
58115
|
try {
|
|
58031
|
-
stat =
|
|
58116
|
+
stat = import_node_fs35.default.statSync(absPath);
|
|
58032
58117
|
} catch (err) {
|
|
58033
58118
|
const code = err?.code;
|
|
58034
58119
|
if (code === "ENOENT") {
|
|
@@ -58043,7 +58128,7 @@ function streamFile(res, absPath, logger) {
|
|
|
58043
58128
|
return;
|
|
58044
58129
|
}
|
|
58045
58130
|
const mime = lookupMime(absPath);
|
|
58046
|
-
const basename2 =
|
|
58131
|
+
const basename2 = import_node_path40.default.basename(absPath);
|
|
58047
58132
|
res.writeHead(200, {
|
|
58048
58133
|
"Content-Type": mime,
|
|
58049
58134
|
"Content-Length": String(stat.size),
|
|
@@ -58051,7 +58136,7 @@ function streamFile(res, absPath, logger) {
|
|
|
58051
58136
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
58052
58137
|
"X-Content-Type-Options": "nosniff"
|
|
58053
58138
|
});
|
|
58054
|
-
const stream =
|
|
58139
|
+
const stream = import_node_fs35.default.createReadStream(absPath);
|
|
58055
58140
|
stream.on("error", (err) => {
|
|
58056
58141
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
58057
58142
|
res.destroy();
|
|
@@ -58060,8 +58145,8 @@ function streamFile(res, absPath, logger) {
|
|
|
58060
58145
|
}
|
|
58061
58146
|
|
|
58062
58147
|
// src/attachment/gc.ts
|
|
58063
|
-
var
|
|
58064
|
-
var
|
|
58148
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
58149
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
58065
58150
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
58066
58151
|
function runAttachmentGc(args) {
|
|
58067
58152
|
const now = (args.now ?? Date.now)();
|
|
@@ -58070,12 +58155,12 @@ function runAttachmentGc(args) {
|
|
|
58070
58155
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
58071
58156
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
58072
58157
|
if (entry.stale) continue;
|
|
58073
|
-
if (
|
|
58158
|
+
if (import_node_path41.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
58074
58159
|
}
|
|
58075
58160
|
}
|
|
58076
58161
|
const visited = /* @__PURE__ */ new Set();
|
|
58077
58162
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
58078
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
58163
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path41.default.join(
|
|
58079
58164
|
args.dataDir,
|
|
58080
58165
|
"sessions",
|
|
58081
58166
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -58088,28 +58173,28 @@ function runAttachmentGc(args) {
|
|
|
58088
58173
|
return true;
|
|
58089
58174
|
});
|
|
58090
58175
|
for (const rootDir of roots) {
|
|
58091
|
-
const attRoot =
|
|
58176
|
+
const attRoot = import_node_path41.default.join(rootDir, ".attachments");
|
|
58092
58177
|
let hashDirs;
|
|
58093
58178
|
try {
|
|
58094
|
-
hashDirs =
|
|
58179
|
+
hashDirs = import_node_fs36.default.readdirSync(attRoot);
|
|
58095
58180
|
} catch (err) {
|
|
58096
58181
|
if (err.code === "ENOENT") continue;
|
|
58097
58182
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
58098
58183
|
continue;
|
|
58099
58184
|
}
|
|
58100
58185
|
for (const hashDir of hashDirs) {
|
|
58101
|
-
const hashDirAbs =
|
|
58186
|
+
const hashDirAbs = import_node_path41.default.join(attRoot, hashDir);
|
|
58102
58187
|
let files;
|
|
58103
58188
|
try {
|
|
58104
|
-
files =
|
|
58189
|
+
files = import_node_fs36.default.readdirSync(hashDirAbs);
|
|
58105
58190
|
} catch {
|
|
58106
58191
|
continue;
|
|
58107
58192
|
}
|
|
58108
58193
|
for (const name of files) {
|
|
58109
|
-
const file =
|
|
58194
|
+
const file = import_node_path41.default.join(hashDirAbs, name);
|
|
58110
58195
|
let stat;
|
|
58111
58196
|
try {
|
|
58112
|
-
stat =
|
|
58197
|
+
stat = import_node_fs36.default.statSync(file);
|
|
58113
58198
|
} catch {
|
|
58114
58199
|
continue;
|
|
58115
58200
|
}
|
|
@@ -58118,18 +58203,18 @@ function runAttachmentGc(args) {
|
|
|
58118
58203
|
if (age < ttlMs) continue;
|
|
58119
58204
|
if (liveAbs.has(file)) continue;
|
|
58120
58205
|
try {
|
|
58121
|
-
|
|
58206
|
+
import_node_fs36.default.unlinkSync(file);
|
|
58122
58207
|
} catch (err) {
|
|
58123
58208
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
58124
58209
|
}
|
|
58125
58210
|
}
|
|
58126
58211
|
try {
|
|
58127
|
-
if (
|
|
58212
|
+
if (import_node_fs36.default.readdirSync(hashDirAbs).length === 0) import_node_fs36.default.rmdirSync(hashDirAbs);
|
|
58128
58213
|
} catch {
|
|
58129
58214
|
}
|
|
58130
58215
|
}
|
|
58131
58216
|
try {
|
|
58132
|
-
if (
|
|
58217
|
+
if (import_node_fs36.default.readdirSync(attRoot).length === 0) import_node_fs36.default.rmdirSync(attRoot);
|
|
58133
58218
|
} catch {
|
|
58134
58219
|
}
|
|
58135
58220
|
}
|
|
@@ -58137,8 +58222,8 @@ function runAttachmentGc(args) {
|
|
|
58137
58222
|
}
|
|
58138
58223
|
|
|
58139
58224
|
// src/attachment/group.ts
|
|
58140
|
-
var
|
|
58141
|
-
var
|
|
58225
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
58226
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
58142
58227
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
58143
58228
|
init_protocol();
|
|
58144
58229
|
var GroupFileStore = class {
|
|
@@ -58150,11 +58235,11 @@ var GroupFileStore = class {
|
|
|
58150
58235
|
this.logger = opts.logger;
|
|
58151
58236
|
}
|
|
58152
58237
|
rootForScope(scope) {
|
|
58153
|
-
return
|
|
58238
|
+
return import_node_path42.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
58154
58239
|
}
|
|
58155
58240
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
58156
58241
|
filePath(scope, sessionId) {
|
|
58157
|
-
return
|
|
58242
|
+
return import_node_path42.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
58158
58243
|
}
|
|
58159
58244
|
cacheKey(scope, sessionId) {
|
|
58160
58245
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -58163,7 +58248,7 @@ var GroupFileStore = class {
|
|
|
58163
58248
|
readFile(scope, sessionId) {
|
|
58164
58249
|
const file = this.filePath(scope, sessionId);
|
|
58165
58250
|
try {
|
|
58166
|
-
const raw =
|
|
58251
|
+
const raw = import_node_fs37.default.readFileSync(file, "utf8");
|
|
58167
58252
|
const parsed = JSON.parse(raw);
|
|
58168
58253
|
if (!Array.isArray(parsed)) {
|
|
58169
58254
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -58189,10 +58274,10 @@ var GroupFileStore = class {
|
|
|
58189
58274
|
}
|
|
58190
58275
|
writeFile(scope, sessionId, entries) {
|
|
58191
58276
|
const file = this.filePath(scope, sessionId);
|
|
58192
|
-
|
|
58277
|
+
import_node_fs37.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
|
|
58193
58278
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
58194
|
-
|
|
58195
|
-
|
|
58279
|
+
import_node_fs37.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
58280
|
+
import_node_fs37.default.renameSync(tmp, file);
|
|
58196
58281
|
}
|
|
58197
58282
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
58198
58283
|
list(scope, sessionId) {
|
|
@@ -58278,10 +58363,10 @@ var GroupFileStore = class {
|
|
|
58278
58363
|
};
|
|
58279
58364
|
|
|
58280
58365
|
// src/discovery/state-file.ts
|
|
58281
|
-
var
|
|
58282
|
-
var
|
|
58366
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
58367
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
58283
58368
|
function defaultStateFilePath(dataDir) {
|
|
58284
|
-
return
|
|
58369
|
+
return import_node_path43.default.join(dataDir, "state.json");
|
|
58285
58370
|
}
|
|
58286
58371
|
function isPidAlive(pid) {
|
|
58287
58372
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -58303,7 +58388,7 @@ var StateFileManager = class {
|
|
|
58303
58388
|
}
|
|
58304
58389
|
read() {
|
|
58305
58390
|
try {
|
|
58306
|
-
const raw =
|
|
58391
|
+
const raw = import_node_fs38.default.readFileSync(this.file, "utf8");
|
|
58307
58392
|
const parsed = JSON.parse(raw);
|
|
58308
58393
|
return parsed;
|
|
58309
58394
|
} catch {
|
|
@@ -58317,20 +58402,20 @@ var StateFileManager = class {
|
|
|
58317
58402
|
return { status: "stale", existing };
|
|
58318
58403
|
}
|
|
58319
58404
|
write(state) {
|
|
58320
|
-
|
|
58405
|
+
import_node_fs38.default.mkdirSync(import_node_path43.default.dirname(this.file), { recursive: true });
|
|
58321
58406
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
58322
|
-
|
|
58323
|
-
|
|
58407
|
+
import_node_fs38.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
58408
|
+
import_node_fs38.default.renameSync(tmp, this.file);
|
|
58324
58409
|
if (process.platform !== "win32") {
|
|
58325
58410
|
try {
|
|
58326
|
-
|
|
58411
|
+
import_node_fs38.default.chmodSync(this.file, 384);
|
|
58327
58412
|
} catch {
|
|
58328
58413
|
}
|
|
58329
58414
|
}
|
|
58330
58415
|
}
|
|
58331
58416
|
delete() {
|
|
58332
58417
|
try {
|
|
58333
|
-
|
|
58418
|
+
import_node_fs38.default.unlinkSync(this.file);
|
|
58334
58419
|
} catch {
|
|
58335
58420
|
}
|
|
58336
58421
|
}
|
|
@@ -58344,14 +58429,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
58344
58429
|
}
|
|
58345
58430
|
|
|
58346
58431
|
// src/tunnel/tunnel-manager.ts
|
|
58347
|
-
var
|
|
58348
|
-
var
|
|
58432
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
58433
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
58349
58434
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
58350
58435
|
var import_node_child_process11 = require("child_process");
|
|
58351
58436
|
|
|
58352
58437
|
// src/tunnel/tunnel-store.ts
|
|
58353
|
-
var
|
|
58354
|
-
var
|
|
58438
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
58439
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
58355
58440
|
var TunnelStore = class {
|
|
58356
58441
|
constructor(filePath) {
|
|
58357
58442
|
this.filePath = filePath;
|
|
@@ -58359,7 +58444,7 @@ var TunnelStore = class {
|
|
|
58359
58444
|
filePath;
|
|
58360
58445
|
async get() {
|
|
58361
58446
|
try {
|
|
58362
|
-
const raw = await
|
|
58447
|
+
const raw = await import_node_fs39.default.promises.readFile(this.filePath, "utf8");
|
|
58363
58448
|
const obj = JSON.parse(raw);
|
|
58364
58449
|
if (!isPersistedTunnel(obj)) return null;
|
|
58365
58450
|
return obj;
|
|
@@ -58370,22 +58455,22 @@ var TunnelStore = class {
|
|
|
58370
58455
|
}
|
|
58371
58456
|
}
|
|
58372
58457
|
async set(v2) {
|
|
58373
|
-
const dir =
|
|
58374
|
-
await
|
|
58458
|
+
const dir = import_node_path44.default.dirname(this.filePath);
|
|
58459
|
+
await import_node_fs39.default.promises.mkdir(dir, { recursive: true });
|
|
58375
58460
|
const data = JSON.stringify(v2, null, 2);
|
|
58376
58461
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
58377
|
-
await
|
|
58462
|
+
await import_node_fs39.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
58378
58463
|
if (process.platform !== "win32") {
|
|
58379
58464
|
try {
|
|
58380
|
-
await
|
|
58465
|
+
await import_node_fs39.default.promises.chmod(tmp, 384);
|
|
58381
58466
|
} catch {
|
|
58382
58467
|
}
|
|
58383
58468
|
}
|
|
58384
|
-
await
|
|
58469
|
+
await import_node_fs39.default.promises.rename(tmp, this.filePath);
|
|
58385
58470
|
}
|
|
58386
58471
|
async clear() {
|
|
58387
58472
|
try {
|
|
58388
|
-
await
|
|
58473
|
+
await import_node_fs39.default.promises.unlink(this.filePath);
|
|
58389
58474
|
} catch (err) {
|
|
58390
58475
|
const code = err?.code;
|
|
58391
58476
|
if (code !== "ENOENT") throw err;
|
|
@@ -58480,9 +58565,9 @@ function escape(v2) {
|
|
|
58480
58565
|
}
|
|
58481
58566
|
|
|
58482
58567
|
// src/tunnel/frpc-binary.ts
|
|
58483
|
-
var
|
|
58568
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
58484
58569
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
58485
|
-
var
|
|
58570
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
58486
58571
|
var import_node_child_process9 = require("child_process");
|
|
58487
58572
|
var import_node_stream3 = require("stream");
|
|
58488
58573
|
var import_promises7 = require("stream/promises");
|
|
@@ -58514,20 +58599,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
58514
58599
|
}
|
|
58515
58600
|
async function ensureFrpcBinary(opts) {
|
|
58516
58601
|
if (opts.override) {
|
|
58517
|
-
if (!
|
|
58602
|
+
if (!import_node_fs40.default.existsSync(opts.override)) {
|
|
58518
58603
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
58519
58604
|
}
|
|
58520
58605
|
return opts.override;
|
|
58521
58606
|
}
|
|
58522
58607
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
58523
58608
|
const platform = opts.platform ?? detectPlatform();
|
|
58524
|
-
const binDir =
|
|
58525
|
-
|
|
58609
|
+
const binDir = import_node_path45.default.join(opts.dataDir, "bin");
|
|
58610
|
+
import_node_fs40.default.mkdirSync(binDir, { recursive: true });
|
|
58526
58611
|
cleanupStaleArtifacts(binDir);
|
|
58527
|
-
const stableBin =
|
|
58528
|
-
if (
|
|
58612
|
+
const stableBin = import_node_path45.default.join(binDir, "frpc");
|
|
58613
|
+
if (import_node_fs40.default.existsSync(stableBin)) return stableBin;
|
|
58529
58614
|
const partialBin = `${stableBin}.partial`;
|
|
58530
|
-
const tarballPath =
|
|
58615
|
+
const tarballPath = import_node_path45.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
58531
58616
|
try {
|
|
58532
58617
|
const url = frpcDownloadUrl(version2, platform);
|
|
58533
58618
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -58536,8 +58621,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
58536
58621
|
} else {
|
|
58537
58622
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
58538
58623
|
}
|
|
58539
|
-
|
|
58540
|
-
|
|
58624
|
+
import_node_fs40.default.chmodSync(partialBin, 493);
|
|
58625
|
+
import_node_fs40.default.renameSync(partialBin, stableBin);
|
|
58541
58626
|
} finally {
|
|
58542
58627
|
safeUnlink(tarballPath);
|
|
58543
58628
|
safeUnlink(partialBin);
|
|
@@ -58547,15 +58632,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
58547
58632
|
function cleanupStaleArtifacts(binDir) {
|
|
58548
58633
|
let entries;
|
|
58549
58634
|
try {
|
|
58550
|
-
entries =
|
|
58635
|
+
entries = import_node_fs40.default.readdirSync(binDir);
|
|
58551
58636
|
} catch {
|
|
58552
58637
|
return;
|
|
58553
58638
|
}
|
|
58554
58639
|
for (const name of entries) {
|
|
58555
58640
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
58556
|
-
const full =
|
|
58641
|
+
const full = import_node_path45.default.join(binDir, name);
|
|
58557
58642
|
try {
|
|
58558
|
-
|
|
58643
|
+
import_node_fs40.default.rmSync(full, { recursive: true, force: true });
|
|
58559
58644
|
} catch {
|
|
58560
58645
|
}
|
|
58561
58646
|
}
|
|
@@ -58563,7 +58648,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
58563
58648
|
}
|
|
58564
58649
|
function safeUnlink(p2) {
|
|
58565
58650
|
try {
|
|
58566
|
-
|
|
58651
|
+
import_node_fs40.default.unlinkSync(p2);
|
|
58567
58652
|
} catch {
|
|
58568
58653
|
}
|
|
58569
58654
|
}
|
|
@@ -58574,13 +58659,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
58574
58659
|
if (!res.ok || !res.body) {
|
|
58575
58660
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
58576
58661
|
}
|
|
58577
|
-
const out =
|
|
58662
|
+
const out = import_node_fs40.default.createWriteStream(dest);
|
|
58578
58663
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
58579
58664
|
await (0, import_promises7.pipeline)(nodeStream, out);
|
|
58580
58665
|
}
|
|
58581
58666
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
58582
|
-
const work =
|
|
58583
|
-
|
|
58667
|
+
const work = import_node_path45.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
58668
|
+
import_node_fs40.default.mkdirSync(work, { recursive: true });
|
|
58584
58669
|
try {
|
|
58585
58670
|
await new Promise((resolve9, reject) => {
|
|
58586
58671
|
const proc = (0, import_node_child_process9.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -58588,32 +58673,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
58588
58673
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
58589
58674
|
});
|
|
58590
58675
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
58591
|
-
const src =
|
|
58592
|
-
if (!
|
|
58676
|
+
const src = import_node_path45.default.join(work, dirName, "frpc");
|
|
58677
|
+
if (!import_node_fs40.default.existsSync(src)) {
|
|
58593
58678
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
58594
58679
|
}
|
|
58595
|
-
|
|
58680
|
+
import_node_fs40.default.copyFileSync(src, destBin);
|
|
58596
58681
|
} finally {
|
|
58597
|
-
|
|
58682
|
+
import_node_fs40.default.rmSync(work, { recursive: true, force: true });
|
|
58598
58683
|
}
|
|
58599
58684
|
}
|
|
58600
58685
|
|
|
58601
58686
|
// src/tunnel/frpc-process.ts
|
|
58602
|
-
var
|
|
58603
|
-
var
|
|
58687
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
58688
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
58604
58689
|
var import_node_child_process10 = require("child_process");
|
|
58605
58690
|
function frpcPidFilePath(dataDir) {
|
|
58606
|
-
return
|
|
58691
|
+
return import_node_path46.default.join(dataDir, "frpc.pid");
|
|
58607
58692
|
}
|
|
58608
58693
|
function writeFrpcPid(dataDir, pid) {
|
|
58609
58694
|
try {
|
|
58610
|
-
|
|
58695
|
+
import_node_fs41.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
58611
58696
|
} catch {
|
|
58612
58697
|
}
|
|
58613
58698
|
}
|
|
58614
58699
|
function clearFrpcPid(dataDir) {
|
|
58615
58700
|
try {
|
|
58616
|
-
|
|
58701
|
+
import_node_fs41.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
58617
58702
|
} catch {
|
|
58618
58703
|
}
|
|
58619
58704
|
}
|
|
@@ -58629,7 +58714,7 @@ function defaultIsPidAlive(pid) {
|
|
|
58629
58714
|
}
|
|
58630
58715
|
function defaultReadPidFile(file) {
|
|
58631
58716
|
try {
|
|
58632
|
-
return
|
|
58717
|
+
return import_node_fs41.default.readFileSync(file, "utf8");
|
|
58633
58718
|
} catch {
|
|
58634
58719
|
return null;
|
|
58635
58720
|
}
|
|
@@ -58645,7 +58730,7 @@ function defaultSleep2(ms) {
|
|
|
58645
58730
|
}
|
|
58646
58731
|
async function killStaleFrpc(deps) {
|
|
58647
58732
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
58648
|
-
const tomlPath =
|
|
58733
|
+
const tomlPath = import_node_path46.default.join(deps.dataDir, "frpc.toml");
|
|
58649
58734
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
58650
58735
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
58651
58736
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -58669,7 +58754,7 @@ async function killStaleFrpc(deps) {
|
|
|
58669
58754
|
}
|
|
58670
58755
|
if (victims.size === 0) {
|
|
58671
58756
|
try {
|
|
58672
|
-
|
|
58757
|
+
import_node_fs41.default.unlinkSync(pidFile);
|
|
58673
58758
|
} catch {
|
|
58674
58759
|
}
|
|
58675
58760
|
return;
|
|
@@ -58680,7 +58765,7 @@ async function killStaleFrpc(deps) {
|
|
|
58680
58765
|
}
|
|
58681
58766
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
58682
58767
|
try {
|
|
58683
|
-
|
|
58768
|
+
import_node_fs41.default.unlinkSync(pidFile);
|
|
58684
58769
|
} catch {
|
|
58685
58770
|
}
|
|
58686
58771
|
}
|
|
@@ -58717,7 +58802,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
58717
58802
|
var TunnelManager = class {
|
|
58718
58803
|
constructor(deps) {
|
|
58719
58804
|
this.deps = deps;
|
|
58720
|
-
this.store = deps.store ?? new TunnelStore(
|
|
58805
|
+
this.store = deps.store ?? new TunnelStore(import_node_path47.default.join(deps.dataDir, "tunnel.json"));
|
|
58721
58806
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
58722
58807
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
58723
58808
|
}
|
|
@@ -58844,7 +58929,7 @@ var TunnelManager = class {
|
|
|
58844
58929
|
dataDir: this.deps.dataDir,
|
|
58845
58930
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
58846
58931
|
});
|
|
58847
|
-
const tomlPath =
|
|
58932
|
+
const tomlPath = import_node_path47.default.join(this.deps.dataDir, "frpc.toml");
|
|
58848
58933
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto11.default.randomBytes(3).toString("hex")}`;
|
|
58849
58934
|
const toml = buildFrpcToml({
|
|
58850
58935
|
serverAddr: t.frpsHost,
|
|
@@ -58855,14 +58940,14 @@ var TunnelManager = class {
|
|
|
58855
58940
|
localPort,
|
|
58856
58941
|
logLevel: "info"
|
|
58857
58942
|
});
|
|
58858
|
-
await
|
|
58943
|
+
await import_node_fs42.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
58859
58944
|
const proc = (this.deps.spawnImpl ?? import_node_child_process11.spawn)(frpcBin, ["-c", tomlPath], {
|
|
58860
58945
|
stdio: ["ignore", "pipe", "pipe"]
|
|
58861
58946
|
});
|
|
58862
|
-
const logDir =
|
|
58863
|
-
|
|
58864
|
-
const logFilePath =
|
|
58865
|
-
const logStream =
|
|
58947
|
+
const logDir = import_node_path47.default.join(this.deps.dataDir, "log");
|
|
58948
|
+
import_node_fs42.default.mkdirSync(logDir, { recursive: true });
|
|
58949
|
+
const logFilePath = import_node_path47.default.join(logDir, "frpc.log");
|
|
58950
|
+
const logStream = import_node_fs42.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
58866
58951
|
logStream.on("error", () => {
|
|
58867
58952
|
});
|
|
58868
58953
|
const tee = (chunk) => {
|
|
@@ -58945,27 +59030,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
58945
59030
|
|
|
58946
59031
|
// src/tunnel/device-key.ts
|
|
58947
59032
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
58948
|
-
var
|
|
59033
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
58949
59034
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
58950
59035
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
58951
59036
|
function deriveStableDeviceKey(opts = {}) {
|
|
58952
59037
|
const hostname = opts.hostname ?? import_node_os15.default.hostname();
|
|
58953
59038
|
const uid = opts.uid ?? (typeof import_node_os15.default.userInfo === "function" ? import_node_os15.default.userInfo().uid : 0);
|
|
58954
59039
|
const home = opts.home ?? import_node_os15.default.homedir();
|
|
58955
|
-
const defaultDataDir =
|
|
58956
|
-
const normalizedDataDir = opts.dataDir ?
|
|
59040
|
+
const defaultDataDir = import_node_path48.default.resolve(import_node_path48.default.join(home, ".clawd"));
|
|
59041
|
+
const normalizedDataDir = opts.dataDir ? import_node_path48.default.resolve(opts.dataDir) : null;
|
|
58957
59042
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
58958
59043
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
58959
59044
|
return import_node_crypto12.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
58960
59045
|
}
|
|
58961
59046
|
|
|
58962
59047
|
// src/auth-store.ts
|
|
58963
|
-
var
|
|
58964
|
-
var
|
|
59048
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
59049
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
58965
59050
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
58966
59051
|
var AUTH_FILE_NAME = "auth.json";
|
|
58967
59052
|
function authFilePath(dataDir) {
|
|
58968
|
-
return
|
|
59053
|
+
return import_node_path49.default.join(dataDir, AUTH_FILE_NAME);
|
|
58969
59054
|
}
|
|
58970
59055
|
function loadOrCreateAuthFile(opts) {
|
|
58971
59056
|
const file = authFilePath(opts.dataDir);
|
|
@@ -58997,7 +59082,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
58997
59082
|
}
|
|
58998
59083
|
function readAuthFile(file) {
|
|
58999
59084
|
try {
|
|
59000
|
-
const raw =
|
|
59085
|
+
const raw = import_node_fs43.default.readFileSync(file, "utf8");
|
|
59001
59086
|
const parsed = JSON.parse(raw);
|
|
59002
59087
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
59003
59088
|
return null;
|
|
@@ -59017,26 +59102,26 @@ function readAuthFile(file) {
|
|
|
59017
59102
|
}
|
|
59018
59103
|
}
|
|
59019
59104
|
function writeAuthFile(file, content) {
|
|
59020
|
-
|
|
59021
|
-
|
|
59105
|
+
import_node_fs43.default.mkdirSync(import_node_path49.default.dirname(file), { recursive: true });
|
|
59106
|
+
import_node_fs43.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
59022
59107
|
try {
|
|
59023
|
-
|
|
59108
|
+
import_node_fs43.default.chmodSync(file, 384);
|
|
59024
59109
|
} catch {
|
|
59025
59110
|
}
|
|
59026
59111
|
}
|
|
59027
59112
|
|
|
59028
59113
|
// src/owner-profile.ts
|
|
59029
|
-
var
|
|
59114
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
59030
59115
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
59031
|
-
var
|
|
59116
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
59032
59117
|
var PROFILE_FILENAME = "profile.json";
|
|
59033
59118
|
function profilePath(dataDir) {
|
|
59034
|
-
return
|
|
59119
|
+
return import_node_path50.default.join(dataDir, PROFILE_FILENAME);
|
|
59035
59120
|
}
|
|
59036
59121
|
function loadOwnerProfile(dataDir) {
|
|
59037
59122
|
let raw;
|
|
59038
59123
|
try {
|
|
59039
|
-
raw =
|
|
59124
|
+
raw = import_node_fs44.default.readFileSync(profilePath(dataDir), "utf8");
|
|
59040
59125
|
} catch {
|
|
59041
59126
|
return {};
|
|
59042
59127
|
}
|
|
@@ -59052,7 +59137,7 @@ function loadOwnerProfile(dataDir) {
|
|
|
59052
59137
|
}
|
|
59053
59138
|
function patchOwnerProfile(dataDir, patch) {
|
|
59054
59139
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
59055
|
-
|
|
59140
|
+
import_node_fs44.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
59056
59141
|
return merged;
|
|
59057
59142
|
}
|
|
59058
59143
|
function loadOwnerDisplayName(dataDir) {
|
|
@@ -59068,18 +59153,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
59068
59153
|
}
|
|
59069
59154
|
|
|
59070
59155
|
// src/feishu-auth/owner-identity-store.ts
|
|
59071
|
-
var
|
|
59072
|
-
var
|
|
59156
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
59157
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
59073
59158
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
59074
59159
|
var OwnerIdentityStore = class {
|
|
59075
59160
|
file;
|
|
59076
59161
|
constructor(dataDir) {
|
|
59077
|
-
this.file =
|
|
59162
|
+
this.file = import_node_path51.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
59078
59163
|
}
|
|
59079
59164
|
read() {
|
|
59080
59165
|
let raw;
|
|
59081
59166
|
try {
|
|
59082
|
-
raw =
|
|
59167
|
+
raw = import_node_fs45.default.readFileSync(this.file, "utf8");
|
|
59083
59168
|
} catch {
|
|
59084
59169
|
return null;
|
|
59085
59170
|
}
|
|
@@ -59107,16 +59192,16 @@ var OwnerIdentityStore = class {
|
|
|
59107
59192
|
};
|
|
59108
59193
|
}
|
|
59109
59194
|
write(record3) {
|
|
59110
|
-
|
|
59111
|
-
|
|
59195
|
+
import_node_fs45.default.mkdirSync(import_node_path51.default.dirname(this.file), { recursive: true });
|
|
59196
|
+
import_node_fs45.default.writeFileSync(this.file, JSON.stringify(record3, null, 2), { mode: 384 });
|
|
59112
59197
|
try {
|
|
59113
|
-
|
|
59198
|
+
import_node_fs45.default.chmodSync(this.file, 384);
|
|
59114
59199
|
} catch {
|
|
59115
59200
|
}
|
|
59116
59201
|
}
|
|
59117
59202
|
clear() {
|
|
59118
59203
|
try {
|
|
59119
|
-
|
|
59204
|
+
import_node_fs45.default.unlinkSync(this.file);
|
|
59120
59205
|
} catch (err) {
|
|
59121
59206
|
const code = err?.code;
|
|
59122
59207
|
if (code !== "ENOENT") throw err;
|
|
@@ -59253,9 +59338,9 @@ var CentralClientError = class extends Error {
|
|
|
59253
59338
|
code;
|
|
59254
59339
|
cause;
|
|
59255
59340
|
};
|
|
59256
|
-
async function centralRequest(opts,
|
|
59341
|
+
async function centralRequest(opts, path90, init) {
|
|
59257
59342
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
59258
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
59343
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path90}`;
|
|
59259
59344
|
const ctrl = new AbortController();
|
|
59260
59345
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
59261
59346
|
let res;
|
|
@@ -59449,8 +59534,8 @@ function verifyConnectToken(args) {
|
|
|
59449
59534
|
}
|
|
59450
59535
|
|
|
59451
59536
|
// src/feishu-auth/server-key.ts
|
|
59452
|
-
var
|
|
59453
|
-
var
|
|
59537
|
+
var fs60 = __toESM(require("fs"), 1);
|
|
59538
|
+
var path64 = __toESM(require("path"), 1);
|
|
59454
59539
|
var FILE_NAME2 = "server-signing-key.json";
|
|
59455
59540
|
var ServerKeyStore = class {
|
|
59456
59541
|
constructor(dataDir) {
|
|
@@ -59458,12 +59543,12 @@ var ServerKeyStore = class {
|
|
|
59458
59543
|
}
|
|
59459
59544
|
dataDir;
|
|
59460
59545
|
filePath() {
|
|
59461
|
-
return
|
|
59546
|
+
return path64.join(this.dataDir, FILE_NAME2);
|
|
59462
59547
|
}
|
|
59463
59548
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
59464
59549
|
read() {
|
|
59465
59550
|
try {
|
|
59466
|
-
const raw =
|
|
59551
|
+
const raw = fs60.readFileSync(this.filePath(), "utf8");
|
|
59467
59552
|
const parsed = JSON.parse(raw);
|
|
59468
59553
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
59469
59554
|
return parsed.publicKeyPem;
|
|
@@ -59478,12 +59563,12 @@ var ServerKeyStore = class {
|
|
|
59478
59563
|
publicKeyPem,
|
|
59479
59564
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
59480
59565
|
};
|
|
59481
|
-
|
|
59482
|
-
|
|
59566
|
+
fs60.mkdirSync(this.dataDir, { recursive: true });
|
|
59567
|
+
fs60.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
59483
59568
|
}
|
|
59484
59569
|
clear() {
|
|
59485
59570
|
try {
|
|
59486
|
-
|
|
59571
|
+
fs60.unlinkSync(this.filePath());
|
|
59487
59572
|
} catch {
|
|
59488
59573
|
}
|
|
59489
59574
|
}
|
|
@@ -59493,18 +59578,18 @@ var ServerKeyStore = class {
|
|
|
59493
59578
|
init_protocol();
|
|
59494
59579
|
|
|
59495
59580
|
// src/handlers/index.ts
|
|
59496
|
-
var
|
|
59581
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
59497
59582
|
|
|
59498
59583
|
// src/handlers/session.ts
|
|
59499
59584
|
init_protocol();
|
|
59500
59585
|
|
|
59501
59586
|
// src/session/fork.ts
|
|
59502
|
-
var
|
|
59587
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
59503
59588
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
59504
|
-
var
|
|
59589
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
59505
59590
|
init_claude_history();
|
|
59506
59591
|
function readJsonlEntries(file) {
|
|
59507
|
-
const raw =
|
|
59592
|
+
const raw = import_node_fs46.default.readFileSync(file, "utf8");
|
|
59508
59593
|
const out = [];
|
|
59509
59594
|
for (const line of raw.split("\n")) {
|
|
59510
59595
|
const t = line.trim();
|
|
@@ -59517,19 +59602,19 @@ function readJsonlEntries(file) {
|
|
|
59517
59602
|
return out;
|
|
59518
59603
|
}
|
|
59519
59604
|
function forkSession(input) {
|
|
59520
|
-
const baseDir = input.baseDir ??
|
|
59521
|
-
let projectDir =
|
|
59522
|
-
let sourceFile =
|
|
59523
|
-
if (!
|
|
59605
|
+
const baseDir = input.baseDir ?? import_node_path52.default.join(import_node_os17.default.homedir(), ".claude");
|
|
59606
|
+
let projectDir = import_node_path52.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
59607
|
+
let sourceFile = import_node_path52.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
59608
|
+
if (!import_node_fs46.default.existsSync(sourceFile)) {
|
|
59524
59609
|
const found = findTranscriptByToolSessionId(
|
|
59525
|
-
|
|
59610
|
+
import_node_path52.default.join(baseDir, "projects"),
|
|
59526
59611
|
input.toolSessionId
|
|
59527
59612
|
);
|
|
59528
59613
|
if (!found) {
|
|
59529
59614
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
59530
59615
|
}
|
|
59531
59616
|
sourceFile = found;
|
|
59532
|
-
projectDir =
|
|
59617
|
+
projectDir = import_node_path52.default.dirname(found);
|
|
59533
59618
|
}
|
|
59534
59619
|
const entries = readJsonlEntries(sourceFile);
|
|
59535
59620
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -59558,27 +59643,27 @@ function forkSession(input) {
|
|
|
59558
59643
|
}
|
|
59559
59644
|
forkedLines.push(JSON.stringify(forked));
|
|
59560
59645
|
}
|
|
59561
|
-
const outDir = input.targetCwd ?
|
|
59562
|
-
const forkedFilePath =
|
|
59563
|
-
|
|
59564
|
-
|
|
59646
|
+
const outDir = input.targetCwd ? import_node_path52.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
59647
|
+
const forkedFilePath = import_node_path52.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
59648
|
+
import_node_fs46.default.mkdirSync(outDir, { recursive: true });
|
|
59649
|
+
import_node_fs46.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
59565
59650
|
return { forkedToolSessionId, forkedFilePath };
|
|
59566
59651
|
}
|
|
59567
59652
|
|
|
59568
59653
|
// src/session/external-scan.ts
|
|
59569
|
-
var
|
|
59654
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
59570
59655
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
59571
59656
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
59572
|
-
var
|
|
59657
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
59573
59658
|
var import_node_module = require("module");
|
|
59574
59659
|
var import_node_child_process12 = require("child_process");
|
|
59575
59660
|
var import_meta4 = {};
|
|
59576
59661
|
function defaultRoots() {
|
|
59577
59662
|
const home = import_node_os18.default.homedir();
|
|
59578
59663
|
return {
|
|
59579
|
-
claudeProjectsDir:
|
|
59580
|
-
codexDir:
|
|
59581
|
-
clawdDir:
|
|
59664
|
+
claudeProjectsDir: import_node_path53.default.join(home, ".claude", "projects"),
|
|
59665
|
+
codexDir: import_node_path53.default.join(home, ".codex"),
|
|
59666
|
+
clawdDir: import_node_path53.default.join(home, ".clawd")
|
|
59582
59667
|
};
|
|
59583
59668
|
}
|
|
59584
59669
|
function width(s) {
|
|
@@ -59629,7 +59714,7 @@ function userText(msg) {
|
|
|
59629
59714
|
}
|
|
59630
59715
|
function isDir2(p2) {
|
|
59631
59716
|
try {
|
|
59632
|
-
return
|
|
59717
|
+
return import_node_fs47.default.statSync(p2).isDirectory();
|
|
59633
59718
|
} catch {
|
|
59634
59719
|
return false;
|
|
59635
59720
|
}
|
|
@@ -59638,7 +59723,7 @@ async function scanClaude(roots) {
|
|
|
59638
59723
|
const out = [];
|
|
59639
59724
|
let dirs;
|
|
59640
59725
|
try {
|
|
59641
|
-
dirs =
|
|
59726
|
+
dirs = import_node_fs47.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
59642
59727
|
} catch {
|
|
59643
59728
|
return out;
|
|
59644
59729
|
}
|
|
@@ -59646,16 +59731,16 @@ async function scanClaude(roots) {
|
|
|
59646
59731
|
if (!d.isDirectory()) continue;
|
|
59647
59732
|
let files;
|
|
59648
59733
|
try {
|
|
59649
|
-
files =
|
|
59734
|
+
files = import_node_fs47.default.readdirSync(import_node_path53.default.join(roots.claudeProjectsDir, d.name));
|
|
59650
59735
|
} catch {
|
|
59651
59736
|
continue;
|
|
59652
59737
|
}
|
|
59653
59738
|
for (const name of files) {
|
|
59654
59739
|
if (!name.endsWith(".jsonl")) continue;
|
|
59655
|
-
const file =
|
|
59740
|
+
const file = import_node_path53.default.join(roots.claudeProjectsDir, d.name, name);
|
|
59656
59741
|
let st;
|
|
59657
59742
|
try {
|
|
59658
|
-
st =
|
|
59743
|
+
st = import_node_fs47.default.statSync(file);
|
|
59659
59744
|
} catch {
|
|
59660
59745
|
continue;
|
|
59661
59746
|
}
|
|
@@ -59708,7 +59793,7 @@ async function scanClaude(roots) {
|
|
|
59708
59793
|
return out;
|
|
59709
59794
|
}
|
|
59710
59795
|
async function countCodexTurns(rolloutPath) {
|
|
59711
|
-
if (!rolloutPath || !
|
|
59796
|
+
if (!rolloutPath || !import_node_fs47.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
59712
59797
|
let turns = 0;
|
|
59713
59798
|
let first = "";
|
|
59714
59799
|
for await (const rec4 of jsonLines(rolloutPath)) {
|
|
@@ -59782,7 +59867,7 @@ async function codexFromRows(rows) {
|
|
|
59782
59867
|
async function scanCodex(roots) {
|
|
59783
59868
|
let dbs = [];
|
|
59784
59869
|
try {
|
|
59785
|
-
dbs =
|
|
59870
|
+
dbs = import_node_fs47.default.readdirSync(roots.codexDir).filter((n) => /^state_.*\.sqlite$/.test(n)).sort().map((n) => import_node_path53.default.join(roots.codexDir, n));
|
|
59786
59871
|
} catch {
|
|
59787
59872
|
}
|
|
59788
59873
|
if (!dbs.length) return [];
|
|
@@ -59791,14 +59876,14 @@ async function scanCodex(roots) {
|
|
|
59791
59876
|
}
|
|
59792
59877
|
async function scanExternalSessions(rootsIn) {
|
|
59793
59878
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
59794
|
-
const personaRoot =
|
|
59879
|
+
const personaRoot = import_node_path53.default.join(roots.clawdDir, "personas");
|
|
59795
59880
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
59796
59881
|
const out = [];
|
|
59797
59882
|
for (const c of all) {
|
|
59798
59883
|
if (c.skip) continue;
|
|
59799
59884
|
if (c.turns < 1) continue;
|
|
59800
59885
|
if (!c.cwd || !isDir2(c.cwd)) continue;
|
|
59801
|
-
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot +
|
|
59886
|
+
if (c.cwd === roots.clawdDir || c.cwd === personaRoot || c.cwd.startsWith(personaRoot + import_node_path53.default.sep) || c.cwd.startsWith(roots.clawdDir + import_node_path53.default.sep)) {
|
|
59802
59887
|
continue;
|
|
59803
59888
|
}
|
|
59804
59889
|
out.push({
|
|
@@ -59815,13 +59900,13 @@ async function scanExternalSessions(rootsIn) {
|
|
|
59815
59900
|
}
|
|
59816
59901
|
|
|
59817
59902
|
// src/session/import-ledger.ts
|
|
59818
|
-
var
|
|
59819
|
-
var
|
|
59903
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
59904
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
59820
59905
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
59821
59906
|
function readImportLedger(dataDir) {
|
|
59822
59907
|
try {
|
|
59823
59908
|
const parsed = JSON.parse(
|
|
59824
|
-
|
|
59909
|
+
import_node_fs48.default.readFileSync(import_node_path54.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
59825
59910
|
);
|
|
59826
59911
|
return Array.isArray(parsed) ? parsed : [];
|
|
59827
59912
|
} catch {
|
|
@@ -59829,10 +59914,10 @@ function readImportLedger(dataDir) {
|
|
|
59829
59914
|
}
|
|
59830
59915
|
}
|
|
59831
59916
|
function appendImportLedger(dataDir, entry) {
|
|
59832
|
-
const file =
|
|
59917
|
+
const file = import_node_path54.default.join(dataDir, LEDGER_FILENAME);
|
|
59833
59918
|
const entries = readImportLedger(dataDir);
|
|
59834
59919
|
entries.push(entry);
|
|
59835
|
-
|
|
59920
|
+
import_node_fs48.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
59836
59921
|
}
|
|
59837
59922
|
|
|
59838
59923
|
// src/handlers/session.ts
|
|
@@ -60335,7 +60420,7 @@ function buildPermissionHandlers(deps) {
|
|
|
60335
60420
|
}
|
|
60336
60421
|
|
|
60337
60422
|
// src/handlers/history.ts
|
|
60338
|
-
var
|
|
60423
|
+
var path69 = __toESM(require("path"), 1);
|
|
60339
60424
|
init_protocol();
|
|
60340
60425
|
|
|
60341
60426
|
// src/session/recent-dirs.ts
|
|
@@ -60353,7 +60438,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
60353
60438
|
}
|
|
60354
60439
|
|
|
60355
60440
|
// src/permission/persona-paths.ts
|
|
60356
|
-
var
|
|
60441
|
+
var path68 = __toESM(require("path"), 1);
|
|
60357
60442
|
function getAllowedPersonaIds(grants, action) {
|
|
60358
60443
|
const ids = /* @__PURE__ */ new Set();
|
|
60359
60444
|
for (const g2 of grants) {
|
|
@@ -60366,42 +60451,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
60366
60451
|
return ids;
|
|
60367
60452
|
}
|
|
60368
60453
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
60369
|
-
const target =
|
|
60454
|
+
const target = path68.resolve(absPath);
|
|
60370
60455
|
if (userWorkDir) {
|
|
60371
|
-
const u =
|
|
60372
|
-
const usep = u.endsWith(
|
|
60456
|
+
const u = path68.resolve(userWorkDir);
|
|
60457
|
+
const usep = u.endsWith(path68.sep) ? "" : path68.sep;
|
|
60373
60458
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
60374
60459
|
}
|
|
60375
|
-
const root =
|
|
60376
|
-
const sep4 = root.endsWith(
|
|
60460
|
+
const root = path68.resolve(personaRoot);
|
|
60461
|
+
const sep4 = root.endsWith(path68.sep) ? "" : path68.sep;
|
|
60377
60462
|
if (!target.startsWith(root + sep4)) return false;
|
|
60378
|
-
const rel =
|
|
60463
|
+
const rel = path68.relative(root, target);
|
|
60379
60464
|
if (!rel || rel.startsWith("..")) return false;
|
|
60380
|
-
const personaId2 = rel.split(
|
|
60465
|
+
const personaId2 = rel.split(path68.sep)[0];
|
|
60381
60466
|
if (!personaId2) return false;
|
|
60382
60467
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
60383
60468
|
if (allowed === "*") return true;
|
|
60384
60469
|
return allowed.has(personaId2);
|
|
60385
60470
|
}
|
|
60386
60471
|
function personaIdFromPath(absPath, personaRoot) {
|
|
60387
|
-
const root =
|
|
60388
|
-
const target =
|
|
60389
|
-
const sep4 = root.endsWith(
|
|
60472
|
+
const root = path68.resolve(personaRoot);
|
|
60473
|
+
const target = path68.resolve(absPath);
|
|
60474
|
+
const sep4 = root.endsWith(path68.sep) ? "" : path68.sep;
|
|
60390
60475
|
if (!target.startsWith(root + sep4)) return null;
|
|
60391
|
-
const rel =
|
|
60476
|
+
const rel = path68.relative(root, target);
|
|
60392
60477
|
if (!rel || rel.startsWith("..")) return null;
|
|
60393
|
-
const id = rel.split(
|
|
60478
|
+
const id = rel.split(path68.sep)[0];
|
|
60394
60479
|
return id || null;
|
|
60395
60480
|
}
|
|
60396
60481
|
function isPathWithin(dir, absPath) {
|
|
60397
|
-
const d =
|
|
60398
|
-
const t =
|
|
60399
|
-
const sep4 = d.endsWith(
|
|
60482
|
+
const d = path68.resolve(dir);
|
|
60483
|
+
const t = path68.resolve(absPath);
|
|
60484
|
+
const sep4 = d.endsWith(path68.sep) ? "" : path68.sep;
|
|
60400
60485
|
return t === d || t.startsWith(d + sep4);
|
|
60401
60486
|
}
|
|
60402
60487
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
60403
60488
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
60404
|
-
return personaIdFromPath(
|
|
60489
|
+
return personaIdFromPath(path68.resolve(absPath), personaRoot) === personaId2;
|
|
60405
60490
|
}
|
|
60406
60491
|
|
|
60407
60492
|
// src/handlers/history.ts
|
|
@@ -60454,7 +60539,7 @@ function buildHistoryHandlers(deps) {
|
|
|
60454
60539
|
if (!pid) return false;
|
|
60455
60540
|
return isGuestPathAllowed(
|
|
60456
60541
|
ctx.grants,
|
|
60457
|
-
|
|
60542
|
+
path69.join(personaRoot, pid),
|
|
60458
60543
|
personaRoot,
|
|
60459
60544
|
"read",
|
|
60460
60545
|
userWorkDir
|
|
@@ -60466,7 +60551,7 @@ function buildHistoryHandlers(deps) {
|
|
|
60466
60551
|
};
|
|
60467
60552
|
const list = async (frame, _client, ctx) => {
|
|
60468
60553
|
const args = HistoryListArgs.parse(frame);
|
|
60469
|
-
assertGuestPath(ctx,
|
|
60554
|
+
assertGuestPath(ctx, path69.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
60470
60555
|
const sessions = await history.listSessions(args);
|
|
60471
60556
|
return { response: { type: "history:list", sessions } };
|
|
60472
60557
|
};
|
|
@@ -60514,14 +60599,14 @@ function buildHistoryHandlers(deps) {
|
|
|
60514
60599
|
};
|
|
60515
60600
|
const subagents = async (frame, _client, ctx) => {
|
|
60516
60601
|
const args = HistorySubagentsArgs.parse(frame);
|
|
60517
|
-
assertGuestPath(ctx,
|
|
60602
|
+
assertGuestPath(ctx, path69.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
60518
60603
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
60519
60604
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
60520
60605
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
60521
60606
|
};
|
|
60522
60607
|
const subagentRead = async (frame, _client, ctx) => {
|
|
60523
60608
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
60524
|
-
assertGuestPath(ctx,
|
|
60609
|
+
assertGuestPath(ctx, path69.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
60525
60610
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
60526
60611
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
60527
60612
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -60531,7 +60616,7 @@ function buildHistoryHandlers(deps) {
|
|
|
60531
60616
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
60532
60617
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
60533
60618
|
const filtered = dirs.filter(
|
|
60534
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
60619
|
+
(d) => isGuestPathAllowed(ctx.grants, path69.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
60535
60620
|
);
|
|
60536
60621
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
60537
60622
|
}
|
|
@@ -60548,17 +60633,17 @@ function buildHistoryHandlers(deps) {
|
|
|
60548
60633
|
}
|
|
60549
60634
|
|
|
60550
60635
|
// src/handlers/projects.ts
|
|
60551
|
-
var
|
|
60636
|
+
var fs64 = __toESM(require("fs"), 1);
|
|
60552
60637
|
var os20 = __toESM(require("os"), 1);
|
|
60553
|
-
var
|
|
60638
|
+
var path70 = __toESM(require("path"), 1);
|
|
60554
60639
|
var import_node_child_process13 = require("child_process");
|
|
60555
60640
|
init_protocol();
|
|
60556
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
60641
|
+
var DEFAULT_PROJECTS_ROOT = path70.join(os20.homedir(), "Documents", "ChatGPT");
|
|
60557
60642
|
function allocateDir(root, name) {
|
|
60558
|
-
let candidate =
|
|
60643
|
+
let candidate = path70.join(root, name);
|
|
60559
60644
|
let n = 2;
|
|
60560
|
-
while (
|
|
60561
|
-
candidate =
|
|
60645
|
+
while (fs64.existsSync(candidate)) {
|
|
60646
|
+
candidate = path70.join(root, `${name} ${n}`);
|
|
60562
60647
|
n += 1;
|
|
60563
60648
|
}
|
|
60564
60649
|
return candidate;
|
|
@@ -60586,7 +60671,7 @@ function buildProjectHandlers(deps) {
|
|
|
60586
60671
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
60587
60672
|
}
|
|
60588
60673
|
try {
|
|
60589
|
-
if (!
|
|
60674
|
+
if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
60590
60675
|
} catch {
|
|
60591
60676
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
60592
60677
|
}
|
|
@@ -60602,7 +60687,7 @@ function buildProjectHandlers(deps) {
|
|
|
60602
60687
|
let target;
|
|
60603
60688
|
if (args.path) {
|
|
60604
60689
|
try {
|
|
60605
|
-
if (!
|
|
60690
|
+
if (!fs64.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
60606
60691
|
} catch {
|
|
60607
60692
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
60608
60693
|
}
|
|
@@ -60610,15 +60695,15 @@ function buildProjectHandlers(deps) {
|
|
|
60610
60695
|
} else {
|
|
60611
60696
|
const name = args.name;
|
|
60612
60697
|
try {
|
|
60613
|
-
|
|
60698
|
+
fs64.mkdirSync(root, { recursive: true });
|
|
60614
60699
|
target = allocateDir(root, name);
|
|
60615
|
-
|
|
60700
|
+
fs64.mkdirSync(target);
|
|
60616
60701
|
} catch (err) {
|
|
60617
60702
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
60618
60703
|
}
|
|
60619
60704
|
const git = (0, import_node_child_process13.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
60620
60705
|
if (git.status !== 0) {
|
|
60621
|
-
|
|
60706
|
+
fs64.rmSync(target, { recursive: true, force: true });
|
|
60622
60707
|
throw new ClawdError(
|
|
60623
60708
|
ERROR_CODES.INVALID_CWD,
|
|
60624
60709
|
`git init \u5931\u8D25\uFF08${git.error ? String(git.error) : `exit ${git.status}`}\uFF09: ${target}`
|
|
@@ -60643,7 +60728,7 @@ function buildProjectHandlers(deps) {
|
|
|
60643
60728
|
}
|
|
60644
60729
|
|
|
60645
60730
|
// src/handlers/workspace.ts
|
|
60646
|
-
var
|
|
60731
|
+
var path71 = __toESM(require("path"), 1);
|
|
60647
60732
|
var os21 = __toESM(require("os"), 1);
|
|
60648
60733
|
init_protocol();
|
|
60649
60734
|
init_protocol();
|
|
@@ -60685,22 +60770,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60685
60770
|
const args = WorkspaceListArgs.parse(frame);
|
|
60686
60771
|
const isGuest = ctx?.principal.kind === "guest";
|
|
60687
60772
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os21.homedir();
|
|
60688
|
-
const resolvedCwd =
|
|
60689
|
-
const target = args.path ?
|
|
60773
|
+
const resolvedCwd = path71.resolve(args.cwd ?? fallbackCwd);
|
|
60774
|
+
const target = args.path ? path71.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
60690
60775
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
60691
60776
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
60692
60777
|
return { response: { type: "workspace:list", ...res } };
|
|
60693
60778
|
};
|
|
60694
60779
|
const read = async (frame, _client, ctx) => {
|
|
60695
60780
|
const args = WorkspaceReadArgs.parse(frame);
|
|
60696
|
-
const target =
|
|
60781
|
+
const target = path71.isAbsolute(args.path) ? path71.resolve(args.path) : path71.resolve(args.cwd, args.path);
|
|
60697
60782
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
60698
60783
|
const res = workspace.read(args);
|
|
60699
60784
|
return { response: { type: "workspace:read", ...res } };
|
|
60700
60785
|
};
|
|
60701
60786
|
const skillsList = async (frame, _client, ctx) => {
|
|
60702
60787
|
const args = SkillsListArgs.parse(frame);
|
|
60703
|
-
const cwdAbs =
|
|
60788
|
+
const cwdAbs = path71.resolve(args.cwd);
|
|
60704
60789
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
60705
60790
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
60706
60791
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -60712,7 +60797,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60712
60797
|
};
|
|
60713
60798
|
const agentsList = async (frame, _client, ctx) => {
|
|
60714
60799
|
const args = AgentsListArgs.parse(frame);
|
|
60715
|
-
const cwdAbs =
|
|
60800
|
+
const cwdAbs = path71.resolve(args.cwd);
|
|
60716
60801
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
60717
60802
|
if (args.tool === "codex") {
|
|
60718
60803
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -60734,20 +60819,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
60734
60819
|
}
|
|
60735
60820
|
|
|
60736
60821
|
// src/handlers/git.ts
|
|
60737
|
-
var
|
|
60822
|
+
var path73 = __toESM(require("path"), 1);
|
|
60738
60823
|
init_protocol();
|
|
60739
60824
|
init_protocol();
|
|
60740
60825
|
|
|
60741
60826
|
// src/workspace/git.ts
|
|
60742
60827
|
var import_node_child_process14 = require("child_process");
|
|
60743
|
-
var
|
|
60744
|
-
var
|
|
60828
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
60829
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
60745
60830
|
var import_node_util = require("util");
|
|
60746
60831
|
var pexec = (0, import_node_util.promisify)(import_node_child_process14.execFile);
|
|
60747
60832
|
function normalizePath(p2) {
|
|
60748
|
-
const resolved =
|
|
60833
|
+
const resolved = import_node_path55.default.resolve(p2);
|
|
60749
60834
|
try {
|
|
60750
|
-
return
|
|
60835
|
+
return import_node_fs49.default.realpathSync(resolved);
|
|
60751
60836
|
} catch {
|
|
60752
60837
|
return resolved;
|
|
60753
60838
|
}
|
|
@@ -60821,7 +60906,7 @@ async function listGitBranches(cwd) {
|
|
|
60821
60906
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
60822
60907
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
60823
60908
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
60824
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
60909
|
+
if (!isGuestPathAllowed(ctx.grants, path73.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
60825
60910
|
throw new ClawdError(
|
|
60826
60911
|
ERROR_CODES.UNAUTHORIZED,
|
|
60827
60912
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -61740,21 +61825,21 @@ function computeMethodAccess(args) {
|
|
|
61740
61825
|
}
|
|
61741
61826
|
|
|
61742
61827
|
// src/version.ts
|
|
61743
|
-
var version = "0.2.
|
|
61828
|
+
var version = "0.2.384".length > 0 ? "0.2.384" : "dev";
|
|
61744
61829
|
|
|
61745
61830
|
// src/cli-probe/probe.ts
|
|
61746
|
-
var
|
|
61747
|
-
var
|
|
61831
|
+
var fs66 = __toESM(require("fs"), 1);
|
|
61832
|
+
var path74 = __toESM(require("path"), 1);
|
|
61748
61833
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
61749
61834
|
var BIN_NAME = "clawd";
|
|
61750
61835
|
var MAX_PARENT_HOPS = 5;
|
|
61751
61836
|
function probeGlobalCli(pathEnv) {
|
|
61752
61837
|
if (!pathEnv) return null;
|
|
61753
|
-
for (const dir of pathEnv.split(
|
|
61838
|
+
for (const dir of pathEnv.split(path74.delimiter)) {
|
|
61754
61839
|
if (!dir) continue;
|
|
61755
61840
|
let real;
|
|
61756
61841
|
try {
|
|
61757
|
-
real =
|
|
61842
|
+
real = fs66.realpathSync(path74.join(dir, BIN_NAME));
|
|
61758
61843
|
} catch {
|
|
61759
61844
|
continue;
|
|
61760
61845
|
}
|
|
@@ -61764,15 +61849,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
61764
61849
|
return null;
|
|
61765
61850
|
}
|
|
61766
61851
|
function readOwnPackageVersion(entryPath) {
|
|
61767
|
-
let dir =
|
|
61852
|
+
let dir = path74.dirname(entryPath);
|
|
61768
61853
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
61769
61854
|
try {
|
|
61770
|
-
const raw =
|
|
61855
|
+
const raw = fs66.readFileSync(path74.join(dir, "package.json"), "utf8");
|
|
61771
61856
|
const pkg = JSON.parse(raw);
|
|
61772
61857
|
if (pkg.name !== PKG_NAME) return null;
|
|
61773
61858
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
61774
61859
|
} catch {
|
|
61775
|
-
const parent =
|
|
61860
|
+
const parent = path74.dirname(dir);
|
|
61776
61861
|
if (parent === dir) return null;
|
|
61777
61862
|
dir = parent;
|
|
61778
61863
|
}
|
|
@@ -61935,7 +62020,7 @@ function buildPersonaHandlers(deps) {
|
|
|
61935
62020
|
}
|
|
61936
62021
|
|
|
61937
62022
|
// src/handlers/attachment.ts
|
|
61938
|
-
var
|
|
62023
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
61939
62024
|
init_protocol();
|
|
61940
62025
|
init_protocol();
|
|
61941
62026
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -62015,12 +62100,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
62015
62100
|
`session ${args.sessionId} scope unresolved`
|
|
62016
62101
|
);
|
|
62017
62102
|
}
|
|
62018
|
-
const cwdAbs =
|
|
62019
|
-
const candidateAbs =
|
|
62103
|
+
const cwdAbs = import_node_path56.default.resolve(sessionFile.cwd);
|
|
62104
|
+
const candidateAbs = import_node_path56.default.isAbsolute(args.relPath) ? import_node_path56.default.resolve(args.relPath) : import_node_path56.default.resolve(cwdAbs, args.relPath);
|
|
62020
62105
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
62021
62106
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
62022
62107
|
const entry = entries.find((e) => {
|
|
62023
|
-
const storedAbs =
|
|
62108
|
+
const storedAbs = import_node_path56.default.isAbsolute(e.relPath) ? import_node_path56.default.resolve(e.relPath) : import_node_path56.default.resolve(cwdAbs, e.relPath);
|
|
62024
62109
|
return storedAbs === candidateAbs && !e.stale;
|
|
62025
62110
|
});
|
|
62026
62111
|
if (!entry) {
|
|
@@ -62045,7 +62130,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
62045
62130
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
62046
62131
|
const f = deps.sessionStore.read(sessionId);
|
|
62047
62132
|
if (!f) return;
|
|
62048
|
-
assertGuestAttachmentPath(ctx,
|
|
62133
|
+
assertGuestAttachmentPath(ctx, import_node_path56.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
62049
62134
|
}
|
|
62050
62135
|
const groupAdd = async (frame, _client, ctx) => {
|
|
62051
62136
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -62060,8 +62145,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
62060
62145
|
if (!scope) {
|
|
62061
62146
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
62062
62147
|
}
|
|
62063
|
-
const cwdAbs =
|
|
62064
|
-
const candidateAbs =
|
|
62148
|
+
const cwdAbs = import_node_path56.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
62149
|
+
const candidateAbs = import_node_path56.default.isAbsolute(args.relPath) ? import_node_path56.default.resolve(args.relPath) : import_node_path56.default.resolve(cwdAbs, args.relPath);
|
|
62065
62150
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
62066
62151
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
62067
62152
|
const size = 0;
|
|
@@ -62120,19 +62205,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
62120
62205
|
|
|
62121
62206
|
// src/handlers/extension.ts
|
|
62122
62207
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
62123
|
-
var
|
|
62208
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
62124
62209
|
init_protocol();
|
|
62125
62210
|
|
|
62126
62211
|
// src/extension/bundle-zip.ts
|
|
62127
62212
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
62128
|
-
var
|
|
62213
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
62129
62214
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
62130
62215
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
62131
62216
|
async function bundleExtensionDir(dir) {
|
|
62132
62217
|
const entries = await listFilesSorted(dir);
|
|
62133
62218
|
const zip = new import_jszip2.default();
|
|
62134
62219
|
for (const rel of entries) {
|
|
62135
|
-
const abs =
|
|
62220
|
+
const abs = import_node_path57.default.join(dir, rel);
|
|
62136
62221
|
const content = await import_promises9.default.readFile(abs);
|
|
62137
62222
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
62138
62223
|
}
|
|
@@ -62153,7 +62238,7 @@ async function listFilesSorted(rootDir) {
|
|
|
62153
62238
|
return out;
|
|
62154
62239
|
}
|
|
62155
62240
|
async function walk(absRoot, relPrefix, out) {
|
|
62156
|
-
const dirAbs =
|
|
62241
|
+
const dirAbs = import_node_path57.default.join(absRoot, relPrefix);
|
|
62157
62242
|
const entries = await import_promises9.default.readdir(dirAbs, { withFileTypes: true });
|
|
62158
62243
|
for (const e of entries) {
|
|
62159
62244
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -62207,25 +62292,25 @@ function computePublishCheck(args) {
|
|
|
62207
62292
|
|
|
62208
62293
|
// src/extension/install-flow.ts
|
|
62209
62294
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
62210
|
-
var
|
|
62295
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
62211
62296
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
62212
62297
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
62213
62298
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
62214
62299
|
|
|
62215
62300
|
// src/extension/paths.ts
|
|
62216
62301
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
62217
|
-
var
|
|
62302
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
62218
62303
|
function clawdHomeRoot(override) {
|
|
62219
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
62304
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path58.default.join(import_node_os20.default.homedir(), ".clawd");
|
|
62220
62305
|
}
|
|
62221
62306
|
function extensionsRoot(override) {
|
|
62222
|
-
return
|
|
62307
|
+
return import_node_path58.default.join(clawdHomeRoot(override), "extensions");
|
|
62223
62308
|
}
|
|
62224
62309
|
function publishedChannelsFile(override) {
|
|
62225
|
-
return
|
|
62310
|
+
return import_node_path58.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
62226
62311
|
}
|
|
62227
62312
|
function bundleCacheRoot(override) {
|
|
62228
|
-
return
|
|
62313
|
+
return import_node_path58.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
62229
62314
|
}
|
|
62230
62315
|
|
|
62231
62316
|
// src/extension/install-flow.ts
|
|
@@ -62252,7 +62337,7 @@ async function installFromChannel(args, deps) {
|
|
|
62252
62337
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
62253
62338
|
}
|
|
62254
62339
|
for (const name of Object.keys(zip.files)) {
|
|
62255
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
62340
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path59.default.isAbsolute(name)) {
|
|
62256
62341
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
62257
62342
|
}
|
|
62258
62343
|
}
|
|
@@ -62284,7 +62369,7 @@ async function installFromChannel(args, deps) {
|
|
|
62284
62369
|
);
|
|
62285
62370
|
}
|
|
62286
62371
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
62287
|
-
const destDir =
|
|
62372
|
+
const destDir = import_node_path59.default.join(deps.extensionsRoot, localExtId);
|
|
62288
62373
|
let destExists = false;
|
|
62289
62374
|
try {
|
|
62290
62375
|
await import_promises10.default.access(destDir);
|
|
@@ -62298,16 +62383,16 @@ async function installFromChannel(args, deps) {
|
|
|
62298
62383
|
);
|
|
62299
62384
|
}
|
|
62300
62385
|
const stage = await import_promises10.default.mkdtemp(
|
|
62301
|
-
|
|
62386
|
+
import_node_path59.default.join(import_node_os21.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
62302
62387
|
);
|
|
62303
62388
|
try {
|
|
62304
62389
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
62305
|
-
const dest =
|
|
62390
|
+
const dest = import_node_path59.default.join(stage, name);
|
|
62306
62391
|
if (entry.dir) {
|
|
62307
62392
|
await import_promises10.default.mkdir(dest, { recursive: true });
|
|
62308
62393
|
continue;
|
|
62309
62394
|
}
|
|
62310
|
-
await import_promises10.default.mkdir(
|
|
62395
|
+
await import_promises10.default.mkdir(import_node_path59.default.dirname(dest), { recursive: true });
|
|
62311
62396
|
if (name === "manifest.json") {
|
|
62312
62397
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
62313
62398
|
await import_promises10.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -62328,7 +62413,7 @@ async function installFromChannel(args, deps) {
|
|
|
62328
62413
|
|
|
62329
62414
|
// src/extension/update-flow.ts
|
|
62330
62415
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
62331
|
-
var
|
|
62416
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
62332
62417
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
62333
62418
|
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
62334
62419
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -62345,11 +62430,11 @@ async function updateFromChannel(args, deps) {
|
|
|
62345
62430
|
channelRef.extId,
|
|
62346
62431
|
channelRef.ownerPrincipalId
|
|
62347
62432
|
);
|
|
62348
|
-
const liveDir =
|
|
62433
|
+
const liveDir = import_node_path60.default.join(deps.extensionsRoot, localExtId);
|
|
62349
62434
|
const prevDir = `${liveDir}.prev`;
|
|
62350
62435
|
let existingVersion;
|
|
62351
62436
|
try {
|
|
62352
|
-
const raw = await import_promises11.default.readFile(
|
|
62437
|
+
const raw = await import_promises11.default.readFile(import_node_path60.default.join(liveDir, "manifest.json"), "utf8");
|
|
62353
62438
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
62354
62439
|
if (!parsed2.success) {
|
|
62355
62440
|
throw new UpdateError(
|
|
@@ -62382,7 +62467,7 @@ async function updateFromChannel(args, deps) {
|
|
|
62382
62467
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
62383
62468
|
}
|
|
62384
62469
|
for (const name of Object.keys(zip.files)) {
|
|
62385
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
62470
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path60.default.isAbsolute(name)) {
|
|
62386
62471
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
62387
62472
|
}
|
|
62388
62473
|
}
|
|
@@ -62417,16 +62502,16 @@ async function updateFromChannel(args, deps) {
|
|
|
62417
62502
|
await import_promises11.default.rm(prevDir, { recursive: true, force: true });
|
|
62418
62503
|
await import_promises11.default.rename(liveDir, prevDir);
|
|
62419
62504
|
const stage = await import_promises11.default.mkdtemp(
|
|
62420
|
-
|
|
62505
|
+
import_node_path60.default.join(import_node_os22.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
62421
62506
|
);
|
|
62422
62507
|
try {
|
|
62423
62508
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
62424
|
-
const dest =
|
|
62509
|
+
const dest = import_node_path60.default.join(stage, name);
|
|
62425
62510
|
if (entry.dir) {
|
|
62426
62511
|
await import_promises11.default.mkdir(dest, { recursive: true });
|
|
62427
62512
|
continue;
|
|
62428
62513
|
}
|
|
62429
|
-
await import_promises11.default.mkdir(
|
|
62514
|
+
await import_promises11.default.mkdir(import_node_path60.default.dirname(dest), { recursive: true });
|
|
62430
62515
|
if (name === "manifest.json") {
|
|
62431
62516
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
62432
62517
|
await import_promises11.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -62493,7 +62578,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
62493
62578
|
);
|
|
62494
62579
|
}
|
|
62495
62580
|
}
|
|
62496
|
-
const manifestPath =
|
|
62581
|
+
const manifestPath = import_node_path61.default.join(root, extId, "manifest.json");
|
|
62497
62582
|
const manifest = await readManifest(root, extId);
|
|
62498
62583
|
const next = { ...manifest, version: newVersion };
|
|
62499
62584
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -62501,7 +62586,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
62501
62586
|
await import_promises12.default.rename(tmp, manifestPath);
|
|
62502
62587
|
}
|
|
62503
62588
|
async function readManifest(root, extId) {
|
|
62504
|
-
const file =
|
|
62589
|
+
const file = import_node_path61.default.join(root, extId, "manifest.json");
|
|
62505
62590
|
let raw;
|
|
62506
62591
|
try {
|
|
62507
62592
|
raw = await import_promises12.default.readFile(file, "utf8");
|
|
@@ -62585,7 +62670,7 @@ function buildExtensionHandlers(deps) {
|
|
|
62585
62670
|
};
|
|
62586
62671
|
async function buildSnapshotMeta(extId) {
|
|
62587
62672
|
const manifest = await readManifest(deps.root, extId);
|
|
62588
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
62673
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path61.default.join(deps.root, extId));
|
|
62589
62674
|
return { manifest, contentHash: sha256, buffer };
|
|
62590
62675
|
}
|
|
62591
62676
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -62760,9 +62845,9 @@ function buildExtensionHandlers(deps) {
|
|
|
62760
62845
|
}
|
|
62761
62846
|
|
|
62762
62847
|
// src/app-builder/project-store.ts
|
|
62763
|
-
var
|
|
62848
|
+
var import_node_fs50 = require("fs");
|
|
62764
62849
|
var import_node_child_process15 = require("child_process");
|
|
62765
|
-
var
|
|
62850
|
+
var import_node_path62 = require("path");
|
|
62766
62851
|
init_protocol();
|
|
62767
62852
|
var PROJECTS_DIR = "projects";
|
|
62768
62853
|
var META_FILE = ".clawd-project.json";
|
|
@@ -62776,19 +62861,19 @@ var ProjectStore = class {
|
|
|
62776
62861
|
root;
|
|
62777
62862
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
62778
62863
|
metaPath(name) {
|
|
62779
|
-
return (0,
|
|
62864
|
+
return (0, import_node_path62.join)(this.projectsRoot(), name, META_FILE);
|
|
62780
62865
|
}
|
|
62781
62866
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
62782
62867
|
projectDir(name) {
|
|
62783
|
-
return (0,
|
|
62868
|
+
return (0, import_node_path62.join)(this.projectsRoot(), name);
|
|
62784
62869
|
}
|
|
62785
62870
|
projectsRoot() {
|
|
62786
|
-
return (0,
|
|
62871
|
+
return (0, import_node_path62.join)(this.root, PROJECTS_DIR);
|
|
62787
62872
|
}
|
|
62788
62873
|
async list() {
|
|
62789
62874
|
let entries;
|
|
62790
62875
|
try {
|
|
62791
|
-
entries = await
|
|
62876
|
+
entries = await import_node_fs50.promises.readdir(this.projectsRoot());
|
|
62792
62877
|
} catch (err) {
|
|
62793
62878
|
if (err.code === "ENOENT") return [];
|
|
62794
62879
|
throw err;
|
|
@@ -62796,7 +62881,7 @@ var ProjectStore = class {
|
|
|
62796
62881
|
const out = [];
|
|
62797
62882
|
for (const name of entries) {
|
|
62798
62883
|
try {
|
|
62799
|
-
const raw = await
|
|
62884
|
+
const raw = await import_node_fs50.promises.readFile(this.metaPath(name), "utf8");
|
|
62800
62885
|
const json = JSON.parse(raw);
|
|
62801
62886
|
let migrated = false;
|
|
62802
62887
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -62807,7 +62892,7 @@ var ProjectStore = class {
|
|
|
62807
62892
|
if (parsed.success) {
|
|
62808
62893
|
out.push(parsed.data);
|
|
62809
62894
|
if (migrated) {
|
|
62810
|
-
void
|
|
62895
|
+
void import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
62811
62896
|
});
|
|
62812
62897
|
}
|
|
62813
62898
|
}
|
|
@@ -62851,8 +62936,8 @@ var ProjectStore = class {
|
|
|
62851
62936
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
62852
62937
|
}
|
|
62853
62938
|
const dir = this.projectDir(name);
|
|
62854
|
-
await
|
|
62855
|
-
await
|
|
62939
|
+
await import_node_fs50.promises.mkdir(dir, { recursive: true });
|
|
62940
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
62856
62941
|
return meta;
|
|
62857
62942
|
}
|
|
62858
62943
|
/**
|
|
@@ -62895,7 +62980,7 @@ var ProjectStore = class {
|
|
|
62895
62980
|
}
|
|
62896
62981
|
async delete(name) {
|
|
62897
62982
|
const dir = this.projectDir(name);
|
|
62898
|
-
await
|
|
62983
|
+
await import_node_fs50.promises.rm(dir, { recursive: true, force: true });
|
|
62899
62984
|
}
|
|
62900
62985
|
async updatePort(name, newPort) {
|
|
62901
62986
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -62911,7 +62996,7 @@ var ProjectStore = class {
|
|
|
62911
62996
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
62912
62997
|
}
|
|
62913
62998
|
const updated = { ...target, port: newPort };
|
|
62914
|
-
await
|
|
62999
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
62915
63000
|
return updated;
|
|
62916
63001
|
}
|
|
62917
63002
|
/**
|
|
@@ -62928,7 +63013,7 @@ var ProjectStore = class {
|
|
|
62928
63013
|
if (!validated.success) {
|
|
62929
63014
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
62930
63015
|
}
|
|
62931
|
-
await
|
|
63016
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
62932
63017
|
return validated.data;
|
|
62933
63018
|
}
|
|
62934
63019
|
/**
|
|
@@ -62949,7 +63034,7 @@ var ProjectStore = class {
|
|
|
62949
63034
|
if (!validated.success) {
|
|
62950
63035
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
62951
63036
|
}
|
|
62952
|
-
await
|
|
63037
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
62953
63038
|
return validated.data;
|
|
62954
63039
|
}
|
|
62955
63040
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -62964,7 +63049,7 @@ var ProjectStore = class {
|
|
|
62964
63049
|
if (!validated.success) {
|
|
62965
63050
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
62966
63051
|
}
|
|
62967
|
-
await
|
|
63052
|
+
await import_node_fs50.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
62968
63053
|
return validated.data;
|
|
62969
63054
|
}
|
|
62970
63055
|
};
|
|
@@ -63085,8 +63170,8 @@ var PublishJobRegistry = class {
|
|
|
63085
63170
|
|
|
63086
63171
|
// src/app-builder/publish-job-runner.ts
|
|
63087
63172
|
var import_node_child_process17 = require("child_process");
|
|
63088
|
-
var
|
|
63089
|
-
var
|
|
63173
|
+
var import_node_fs51 = require("fs");
|
|
63174
|
+
var import_node_path63 = require("path");
|
|
63090
63175
|
|
|
63091
63176
|
// src/app-builder/publish-stage-parser.ts
|
|
63092
63177
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -63118,10 +63203,10 @@ async function startPublishJob(deps, args) {
|
|
|
63118
63203
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
63119
63204
|
}
|
|
63120
63205
|
const projDir = projectDir(args.name);
|
|
63121
|
-
const logPath = (0,
|
|
63206
|
+
const logPath = (0, import_node_path63.join)(projDir, ".publish.log");
|
|
63122
63207
|
let logStream = null;
|
|
63123
63208
|
try {
|
|
63124
|
-
logStream = (0,
|
|
63209
|
+
logStream = (0, import_node_fs51.createWriteStream)(logPath, { flags: "w" });
|
|
63125
63210
|
} catch {
|
|
63126
63211
|
logStream = null;
|
|
63127
63212
|
}
|
|
@@ -63378,8 +63463,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
63378
63463
|
|
|
63379
63464
|
// src/handlers/app-builder.ts
|
|
63380
63465
|
init_protocol();
|
|
63381
|
-
var
|
|
63382
|
-
var
|
|
63466
|
+
var import_node_path64 = require("path");
|
|
63467
|
+
var import_node_fs52 = require("fs");
|
|
63383
63468
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
63384
63469
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
63385
63470
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -63460,7 +63545,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
63460
63545
|
async function listAllUsersProjects() {
|
|
63461
63546
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
63462
63547
|
const getStore = deps.getStore;
|
|
63463
|
-
const userIds = await
|
|
63548
|
+
const userIds = await import_node_fs52.promises.readdir(deps.usersRoot).catch(() => []);
|
|
63464
63549
|
const perUser = await Promise.all(
|
|
63465
63550
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
63466
63551
|
);
|
|
@@ -63529,8 +63614,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
63529
63614
|
const project = await userStore.create(f.name, reservedPorts);
|
|
63530
63615
|
try {
|
|
63531
63616
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
63532
|
-
const templateSrcDir = (0,
|
|
63533
|
-
const scaffoldScript = (0,
|
|
63617
|
+
const templateSrcDir = (0, import_node_path64.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
63618
|
+
const scaffoldScript = (0, import_node_path64.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
63534
63619
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
63535
63620
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
63536
63621
|
name: project.name,
|
|
@@ -63734,7 +63819,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
63734
63819
|
await userStore.clearPublishJob(args.name);
|
|
63735
63820
|
}
|
|
63736
63821
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
63737
|
-
const scriptPath = (0,
|
|
63822
|
+
const scriptPath = (0, import_node_path64.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
63738
63823
|
deps.logger?.info("app-builder.publish.start", {
|
|
63739
63824
|
name: args.name,
|
|
63740
63825
|
sessionId: boundSession.sessionId,
|
|
@@ -64575,7 +64660,7 @@ function buildVisitorHandlers(deps) {
|
|
|
64575
64660
|
|
|
64576
64661
|
// src/extension/registry.ts
|
|
64577
64662
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
64578
|
-
var
|
|
64663
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
64579
64664
|
async function loadAll(root) {
|
|
64580
64665
|
let entries;
|
|
64581
64666
|
try {
|
|
@@ -64588,13 +64673,13 @@ async function loadAll(root) {
|
|
|
64588
64673
|
for (const ent of entries) {
|
|
64589
64674
|
if (!ent.isDirectory()) continue;
|
|
64590
64675
|
if (ent.name.startsWith(".")) continue;
|
|
64591
|
-
records.push(await loadOne(
|
|
64676
|
+
records.push(await loadOne(import_node_path65.default.join(root, ent.name), ent.name));
|
|
64592
64677
|
}
|
|
64593
64678
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
64594
64679
|
return records;
|
|
64595
64680
|
}
|
|
64596
64681
|
async function loadOne(dir, dirName) {
|
|
64597
|
-
const manifestPath =
|
|
64682
|
+
const manifestPath = import_node_path65.default.join(dir, "manifest.json");
|
|
64598
64683
|
let raw;
|
|
64599
64684
|
try {
|
|
64600
64685
|
raw = await import_promises14.default.readFile(manifestPath, "utf8");
|
|
@@ -64639,7 +64724,7 @@ async function loadOne(dir, dirName) {
|
|
|
64639
64724
|
|
|
64640
64725
|
// src/extension/uninstall.ts
|
|
64641
64726
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
64642
|
-
var
|
|
64727
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
64643
64728
|
var UninstallError = class extends Error {
|
|
64644
64729
|
constructor(code, message) {
|
|
64645
64730
|
super(message);
|
|
@@ -64648,7 +64733,7 @@ var UninstallError = class extends Error {
|
|
|
64648
64733
|
code;
|
|
64649
64734
|
};
|
|
64650
64735
|
async function uninstall(deps) {
|
|
64651
|
-
const dir =
|
|
64736
|
+
const dir = import_node_path66.default.join(deps.root, deps.extId);
|
|
64652
64737
|
try {
|
|
64653
64738
|
await import_promises15.default.access(dir);
|
|
64654
64739
|
} catch {
|
|
@@ -64876,7 +64961,7 @@ function buildMethodHandlers(deps) {
|
|
|
64876
64961
|
}),
|
|
64877
64962
|
...buildChannelHandlers({ channelStore: deps.channelStore, topicStore: deps.topicStore }),
|
|
64878
64963
|
...buildMasterHandlers({
|
|
64879
|
-
authorityTablePath:
|
|
64964
|
+
authorityTablePath: import_node_path67.default.join(deps.masterDataDir, "master-authority.json")
|
|
64880
64965
|
}),
|
|
64881
64966
|
...buildLineHandlers({
|
|
64882
64967
|
dispatchStore: deps.dispatchStore,
|
|
@@ -65317,7 +65402,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
65317
65402
|
|
|
65318
65403
|
// src/extension/runtime.ts
|
|
65319
65404
|
var import_node_child_process21 = require("child_process");
|
|
65320
|
-
var
|
|
65405
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
65321
65406
|
var import_promises16 = require("timers/promises");
|
|
65322
65407
|
|
|
65323
65408
|
// src/extension/port-allocator.ts
|
|
@@ -65418,7 +65503,7 @@ var Runtime = class {
|
|
|
65418
65503
|
/\$CLAWOS_EXT_PORT/g,
|
|
65419
65504
|
String(port)
|
|
65420
65505
|
);
|
|
65421
|
-
const dir =
|
|
65506
|
+
const dir = import_node_path68.default.join(this.root, extId);
|
|
65422
65507
|
const env = {
|
|
65423
65508
|
...process.env,
|
|
65424
65509
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -65530,7 +65615,7 @@ ${handle.stderrTail}`
|
|
|
65530
65615
|
|
|
65531
65616
|
// src/extension/published-channels.ts
|
|
65532
65617
|
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
65533
|
-
var
|
|
65618
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
65534
65619
|
init_zod();
|
|
65535
65620
|
var PublishedChannelsError = class extends Error {
|
|
65536
65621
|
constructor(code, message) {
|
|
@@ -65629,7 +65714,7 @@ var PublishedChannelStore = class {
|
|
|
65629
65714
|
)
|
|
65630
65715
|
};
|
|
65631
65716
|
const tmp = `${this.filePath}.tmp`;
|
|
65632
|
-
await import_promises17.default.mkdir(
|
|
65717
|
+
await import_promises17.default.mkdir(import_node_path69.default.dirname(this.filePath), { recursive: true });
|
|
65633
65718
|
await import_promises17.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
65634
65719
|
await import_promises17.default.rename(tmp, this.filePath);
|
|
65635
65720
|
}
|
|
@@ -65637,7 +65722,7 @@ var PublishedChannelStore = class {
|
|
|
65637
65722
|
|
|
65638
65723
|
// src/extension/bundle-cache.ts
|
|
65639
65724
|
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
65640
|
-
var
|
|
65725
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
65641
65726
|
var BundleCache = class {
|
|
65642
65727
|
constructor(rootDir) {
|
|
65643
65728
|
this.rootDir = rootDir;
|
|
@@ -65646,14 +65731,14 @@ var BundleCache = class {
|
|
|
65646
65731
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
65647
65732
|
async write(snapshotHash, buffer) {
|
|
65648
65733
|
await import_promises18.default.mkdir(this.rootDir, { recursive: true });
|
|
65649
|
-
const file =
|
|
65734
|
+
const file = import_node_path70.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
65650
65735
|
const tmp = `${file}.tmp`;
|
|
65651
65736
|
await import_promises18.default.writeFile(tmp, buffer, { mode: 384 });
|
|
65652
65737
|
await import_promises18.default.rename(tmp, file);
|
|
65653
65738
|
}
|
|
65654
65739
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
65655
65740
|
async read(snapshotHash) {
|
|
65656
|
-
const file =
|
|
65741
|
+
const file = import_node_path70.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
65657
65742
|
try {
|
|
65658
65743
|
return await import_promises18.default.readFile(file);
|
|
65659
65744
|
} catch (e) {
|
|
@@ -65663,7 +65748,7 @@ var BundleCache = class {
|
|
|
65663
65748
|
}
|
|
65664
65749
|
/** Idempotent — missing file is not an error. */
|
|
65665
65750
|
async delete(snapshotHash) {
|
|
65666
|
-
const file =
|
|
65751
|
+
const file = import_node_path70.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
65667
65752
|
await import_promises18.default.rm(file, { force: true });
|
|
65668
65753
|
}
|
|
65669
65754
|
};
|
|
@@ -65686,24 +65771,24 @@ async function startDaemon(config) {
|
|
|
65686
65771
|
sampling: logShippingCfg.sampling,
|
|
65687
65772
|
homeDir: import_node_os24.default.homedir()
|
|
65688
65773
|
});
|
|
65689
|
-
const logDir =
|
|
65690
|
-
|
|
65774
|
+
const logDir = import_node_path71.default.join(config.dataDir, "log");
|
|
65775
|
+
import_node_fs53.default.mkdirSync(logDir, { recursive: true });
|
|
65691
65776
|
const logger = createLogger({
|
|
65692
65777
|
level: config.logLevel,
|
|
65693
|
-
file:
|
|
65778
|
+
file: import_node_path71.default.join(logDir, "clawd.log"),
|
|
65694
65779
|
logClient
|
|
65695
65780
|
});
|
|
65696
65781
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
65697
65782
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
65698
|
-
file:
|
|
65783
|
+
file: import_node_path71.default.join(logDir, "screen-idle-probe.log"),
|
|
65699
65784
|
level: "debug"
|
|
65700
65785
|
});
|
|
65701
65786
|
logger.info("screen-idle probe logger enabled", {
|
|
65702
|
-
file:
|
|
65787
|
+
file: import_node_path71.default.join(logDir, "screen-idle-probe.log")
|
|
65703
65788
|
});
|
|
65704
65789
|
const CAP_TARGETS = [
|
|
65705
|
-
|
|
65706
|
-
|
|
65790
|
+
import_node_path71.default.join(logDir, "clawd.log"),
|
|
65791
|
+
import_node_path71.default.join(logDir, "screen-idle-probe.log")
|
|
65707
65792
|
];
|
|
65708
65793
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
65709
65794
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -65799,8 +65884,8 @@ async function startDaemon(config) {
|
|
|
65799
65884
|
const agents = new AgentsScanner();
|
|
65800
65885
|
const history = new ClaudeHistoryReader();
|
|
65801
65886
|
let transport = null;
|
|
65802
|
-
const personaStore = new PersonaStore(
|
|
65803
|
-
const usersRoot =
|
|
65887
|
+
const personaStore = new PersonaStore(import_node_path71.default.join(config.dataDir, "personas"));
|
|
65888
|
+
const usersRoot = import_node_path71.default.join(config.dataDir, "users");
|
|
65804
65889
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
65805
65890
|
if (defaultsRoot) {
|
|
65806
65891
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -65823,7 +65908,7 @@ async function startDaemon(config) {
|
|
|
65823
65908
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
65824
65909
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
65825
65910
|
const dispatchStore = createDispatchStore({
|
|
65826
|
-
filePath:
|
|
65911
|
+
filePath: import_node_path71.default.join(config.dataDir, "dispatch.json"),
|
|
65827
65912
|
now: () => Date.now(),
|
|
65828
65913
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
65829
65914
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -65832,7 +65917,7 @@ async function startDaemon(config) {
|
|
|
65832
65917
|
await dispatchStore.load();
|
|
65833
65918
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
65834
65919
|
const channelStore = createChannelStore({
|
|
65835
|
-
filePath:
|
|
65920
|
+
filePath: import_node_path71.default.join(config.dataDir, "channels.json"),
|
|
65836
65921
|
now: () => Date.now(),
|
|
65837
65922
|
genId: () => `ch-${v4_default().slice(0, 8)}`,
|
|
65838
65923
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
@@ -65841,7 +65926,7 @@ async function startDaemon(config) {
|
|
|
65841
65926
|
});
|
|
65842
65927
|
await channelStore.load();
|
|
65843
65928
|
const topicStore = createTopicStore({
|
|
65844
|
-
filePath:
|
|
65929
|
+
filePath: import_node_path71.default.join(config.dataDir, "topics.json"),
|
|
65845
65930
|
now: () => Date.now(),
|
|
65846
65931
|
genId: () => `tp-${v4_default().slice(0, 8)}`,
|
|
65847
65932
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
@@ -65856,18 +65941,18 @@ async function startDaemon(config) {
|
|
|
65856
65941
|
now: () => Date.now(),
|
|
65857
65942
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
65858
65943
|
});
|
|
65859
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
65944
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path71.default.dirname((0, import_node_url4.fileURLToPath)(import_meta7.url));
|
|
65860
65945
|
const mcpConfigs = [];
|
|
65861
65946
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
65862
65947
|
const dispatchServerCandidates = [
|
|
65863
|
-
|
|
65948
|
+
import_node_path71.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
65864
65949
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
65865
|
-
|
|
65950
|
+
import_node_path71.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
65866
65951
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
65867
65952
|
];
|
|
65868
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
65953
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65869
65954
|
if (dispatchServerScriptPath) {
|
|
65870
|
-
const dispatchLogPath =
|
|
65955
|
+
const dispatchLogPath = import_node_path71.default.join(logDir, "dispatch-mcp-server.log");
|
|
65871
65956
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
65872
65957
|
dataDir: config.dataDir,
|
|
65873
65958
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -65887,12 +65972,12 @@ async function startDaemon(config) {
|
|
|
65887
65972
|
});
|
|
65888
65973
|
}
|
|
65889
65974
|
const ticketServerCandidates = [
|
|
65890
|
-
|
|
65891
|
-
|
|
65975
|
+
import_node_path71.default.join(here, "ticket", "mcp-server.cjs"),
|
|
65976
|
+
import_node_path71.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
65892
65977
|
];
|
|
65893
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
65978
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65894
65979
|
if (ticketServerScriptPath) {
|
|
65895
|
-
const ticketLogPath =
|
|
65980
|
+
const ticketLogPath = import_node_path71.default.join(logDir, "ticket-mcp-server.log");
|
|
65896
65981
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
65897
65982
|
dataDir: config.dataDir,
|
|
65898
65983
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -65914,12 +65999,12 @@ async function startDaemon(config) {
|
|
|
65914
65999
|
});
|
|
65915
66000
|
}
|
|
65916
66001
|
const shiftServerCandidates = [
|
|
65917
|
-
|
|
65918
|
-
|
|
66002
|
+
import_node_path71.default.join(here, "shift", "mcp-server.cjs"),
|
|
66003
|
+
import_node_path71.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
65919
66004
|
];
|
|
65920
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
66005
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65921
66006
|
if (shiftServerScriptPath) {
|
|
65922
|
-
const shiftLogPath =
|
|
66007
|
+
const shiftLogPath = import_node_path71.default.join(logDir, "shift-mcp-server.log");
|
|
65923
66008
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
65924
66009
|
dataDir: config.dataDir,
|
|
65925
66010
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -65940,12 +66025,12 @@ async function startDaemon(config) {
|
|
|
65940
66025
|
);
|
|
65941
66026
|
}
|
|
65942
66027
|
const inboxServerCandidates = [
|
|
65943
|
-
|
|
65944
|
-
|
|
66028
|
+
import_node_path71.default.join(here, "inbox", "mcp-server.cjs"),
|
|
66029
|
+
import_node_path71.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
65945
66030
|
];
|
|
65946
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
66031
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65947
66032
|
if (inboxServerScriptPath) {
|
|
65948
|
-
const inboxLogPath =
|
|
66033
|
+
const inboxLogPath = import_node_path71.default.join(logDir, "inbox-mcp-server.log");
|
|
65949
66034
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
65950
66035
|
dataDir: config.dataDir,
|
|
65951
66036
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -65966,10 +66051,10 @@ async function startDaemon(config) {
|
|
|
65966
66051
|
);
|
|
65967
66052
|
}
|
|
65968
66053
|
const peerOpsServerCandidates = [
|
|
65969
|
-
|
|
65970
|
-
|
|
66054
|
+
import_node_path71.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
66055
|
+
import_node_path71.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
65971
66056
|
];
|
|
65972
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
66057
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65973
66058
|
if (peerOpsServerScriptPath) {
|
|
65974
66059
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
65975
66060
|
dataDir: config.dataDir,
|
|
@@ -65989,12 +66074,12 @@ async function startDaemon(config) {
|
|
|
65989
66074
|
);
|
|
65990
66075
|
}
|
|
65991
66076
|
const rpcToolServerCandidates = [
|
|
65992
|
-
|
|
65993
|
-
|
|
66077
|
+
import_node_path71.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
66078
|
+
import_node_path71.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
65994
66079
|
];
|
|
65995
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
66080
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs53.default.existsSync(p2));
|
|
65996
66081
|
if (rpcToolServerScriptPath) {
|
|
65997
|
-
const rpcToolLogPath =
|
|
66082
|
+
const rpcToolLogPath = import_node_path71.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
65998
66083
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
65999
66084
|
dataDir: config.dataDir,
|
|
66000
66085
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -66015,7 +66100,7 @@ async function startDaemon(config) {
|
|
|
66015
66100
|
);
|
|
66016
66101
|
}
|
|
66017
66102
|
const shiftStore = createShiftStore({
|
|
66018
|
-
filePath:
|
|
66103
|
+
filePath: import_node_path71.default.join(config.dataDir, "shift.json"),
|
|
66019
66104
|
ownerIdProvider: () => ownerPrincipalId,
|
|
66020
66105
|
now: () => Date.now()
|
|
66021
66106
|
});
|
|
@@ -66037,7 +66122,7 @@ async function startDaemon(config) {
|
|
|
66037
66122
|
getAdapter,
|
|
66038
66123
|
historyReader: history,
|
|
66039
66124
|
dataDir: config.dataDir,
|
|
66040
|
-
personaRoot:
|
|
66125
|
+
personaRoot: import_node_path71.default.join(config.dataDir, "personas"),
|
|
66041
66126
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
66042
66127
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
66043
66128
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -66091,10 +66176,10 @@ async function startDaemon(config) {
|
|
|
66091
66176
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
66092
66177
|
attachmentGroup: {
|
|
66093
66178
|
onFileEdit: (input) => {
|
|
66094
|
-
const absPath =
|
|
66179
|
+
const absPath = import_node_path71.default.isAbsolute(input.relPath) ? input.relPath : import_node_path71.default.join(input.cwd, input.relPath);
|
|
66095
66180
|
let size = 0;
|
|
66096
66181
|
try {
|
|
66097
|
-
size =
|
|
66182
|
+
size = import_node_fs53.default.statSync(absPath).size;
|
|
66098
66183
|
} catch (err) {
|
|
66099
66184
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
66100
66185
|
sessionId: input.sessionId,
|
|
@@ -66124,9 +66209,9 @@ async function startDaemon(config) {
|
|
|
66124
66209
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
66125
66210
|
}
|
|
66126
66211
|
const projectsStore = new ProjectsStore({
|
|
66127
|
-
file:
|
|
66212
|
+
file: import_node_path71.default.join(config.dataDir, "projects.json"),
|
|
66128
66213
|
clawdDir: config.dataDir,
|
|
66129
|
-
codexStateFile:
|
|
66214
|
+
codexStateFile: import_node_path71.default.join(import_node_os24.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
66130
66215
|
logger
|
|
66131
66216
|
});
|
|
66132
66217
|
const observer = new SessionObserver({
|
|
@@ -66186,13 +66271,13 @@ async function startDaemon(config) {
|
|
|
66186
66271
|
screenIdleProbeLogger
|
|
66187
66272
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
66188
66273
|
registerAdapter("claude", claudeAdapter);
|
|
66189
|
-
const codexIsolatedHome =
|
|
66274
|
+
const codexIsolatedHome = import_node_path71.default.join(config.dataDir, "codex-home");
|
|
66190
66275
|
try {
|
|
66191
|
-
|
|
66276
|
+
import_node_fs53.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
66192
66277
|
for (const f of ["auth.json", "config.toml"]) {
|
|
66193
|
-
const link =
|
|
66194
|
-
const target =
|
|
66195
|
-
if (!
|
|
66278
|
+
const link = import_node_path71.default.join(codexIsolatedHome, f);
|
|
66279
|
+
const target = import_node_path71.default.join(import_node_os24.default.homedir(), ".codex", f);
|
|
66280
|
+
if (!import_node_fs53.default.existsSync(link) && import_node_fs53.default.existsSync(target)) import_node_fs53.default.symlinkSync(target, link);
|
|
66196
66281
|
}
|
|
66197
66282
|
} catch (err) {
|
|
66198
66283
|
logger.warn("codex isolated home setup failed", { err: String(err) });
|
|
@@ -66205,11 +66290,11 @@ async function startDaemon(config) {
|
|
|
66205
66290
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
66206
66291
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
66207
66292
|
cwd,
|
|
66208
|
-
personaRoot:
|
|
66293
|
+
personaRoot: import_node_path71.default.join(config.dataDir, "personas"),
|
|
66209
66294
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
66210
66295
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
66211
66296
|
projectPaths: projectsStore.listMerged().map((x) => x.path),
|
|
66212
|
-
sharedHome:
|
|
66297
|
+
sharedHome: import_node_path71.default.join(import_node_os24.default.homedir(), ".codex"),
|
|
66213
66298
|
isolatedHome: codexIsolatedHome
|
|
66214
66299
|
})
|
|
66215
66300
|
})
|
|
@@ -66423,11 +66508,11 @@ async function startDaemon(config) {
|
|
|
66423
66508
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
66424
66509
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
66425
66510
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
66426
|
-
personaRoot:
|
|
66511
|
+
personaRoot: import_node_path71.default.join(config.dataDir, "personas"),
|
|
66427
66512
|
usersRoot
|
|
66428
66513
|
},
|
|
66429
66514
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
66430
|
-
personaRoot:
|
|
66515
|
+
personaRoot: import_node_path71.default.join(config.dataDir, "personas"),
|
|
66431
66516
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
66432
66517
|
usersRoot,
|
|
66433
66518
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -66560,11 +66645,11 @@ async function startDaemon(config) {
|
|
|
66560
66645
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
66561
66646
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
66562
66647
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
66563
|
-
appBuilderPersonaRoot:
|
|
66648
|
+
appBuilderPersonaRoot: import_node_path71.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
66564
66649
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
66565
|
-
deployKitRoot:
|
|
66650
|
+
deployKitRoot: import_node_path71.default.join(config.dataDir, "deploy-kit"),
|
|
66566
66651
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
66567
|
-
resolvePersonaRoot: (personaId2) =>
|
|
66652
|
+
resolvePersonaRoot: (personaId2) => import_node_path71.default.join(config.dataDir, "personas", personaId2),
|
|
66568
66653
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
66569
66654
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
66570
66655
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -66626,6 +66711,8 @@ async function startDaemon(config) {
|
|
|
66626
66711
|
guestFeishuUnionId: args.guestFeishuUnionId,
|
|
66627
66712
|
// T-20: 可选 model override 透到 SessionFile.model
|
|
66628
66713
|
...args.model ? { model: args.model } : {},
|
|
66714
|
+
// 一次性 engine override(spec 2026-08-24)透到 SessionFile.tool
|
|
66715
|
+
...args.tool ? { tool: args.tool } : {},
|
|
66629
66716
|
// butler 顶部入口(spec 2026-07-27):可选 label 透到 SessionFile.label(sidebar 显示)
|
|
66630
66717
|
...args.label ? { label: args.label } : {}
|
|
66631
66718
|
});
|
|
@@ -66669,7 +66756,7 @@ async function startDaemon(config) {
|
|
|
66669
66756
|
});
|
|
66670
66757
|
shiftScheduler.start();
|
|
66671
66758
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
66672
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
66759
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path71.default.join(config.dataDir, "personas"));
|
|
66673
66760
|
const larkBotCloud = createLarkBotCloudClient({
|
|
66674
66761
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
66675
66762
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -66683,7 +66770,7 @@ async function startDaemon(config) {
|
|
|
66683
66770
|
store: larkBotStore,
|
|
66684
66771
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
66685
66772
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
66686
|
-
mediaRootFor: (chatId) =>
|
|
66773
|
+
mediaRootFor: (chatId) => import_node_path71.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
66687
66774
|
isShuttingDown: () => larkDraining,
|
|
66688
66775
|
logger: {
|
|
66689
66776
|
warn: (msg) => logger.warn(msg),
|
|
@@ -66988,8 +67075,8 @@ async function startDaemon(config) {
|
|
|
66988
67075
|
const lines = [
|
|
66989
67076
|
`Tunnel: ${r.url}`,
|
|
66990
67077
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
66991
|
-
`Frpc config: ${
|
|
66992
|
-
`Frpc log: ${
|
|
67078
|
+
`Frpc config: ${import_node_path71.default.join(config.dataDir, "frpc.toml")}`,
|
|
67079
|
+
`Frpc log: ${import_node_path71.default.join(logDir, "frpc.log")}`
|
|
66993
67080
|
];
|
|
66994
67081
|
const width2 = Math.max(...lines.map((l) => l.length));
|
|
66995
67082
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -67002,8 +67089,8 @@ ${bar}
|
|
|
67002
67089
|
|
|
67003
67090
|
`);
|
|
67004
67091
|
try {
|
|
67005
|
-
const connectPath =
|
|
67006
|
-
|
|
67092
|
+
const connectPath = import_node_path71.default.join(config.dataDir, "connect.txt");
|
|
67093
|
+
import_node_fs53.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
67007
67094
|
} catch {
|
|
67008
67095
|
}
|
|
67009
67096
|
} catch (err) {
|
|
@@ -67089,9 +67176,9 @@ ${bar}
|
|
|
67089
67176
|
};
|
|
67090
67177
|
}
|
|
67091
67178
|
function migrateDropPersonsDir(dataDir) {
|
|
67092
|
-
const dir =
|
|
67179
|
+
const dir = import_node_path71.default.join(dataDir, "persons");
|
|
67093
67180
|
try {
|
|
67094
|
-
|
|
67181
|
+
import_node_fs53.default.rmSync(dir, { recursive: true, force: true });
|
|
67095
67182
|
} catch {
|
|
67096
67183
|
}
|
|
67097
67184
|
}
|