@clawos-dev/clawd 0.2.292 → 0.2.294
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: path79, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path79, ...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, path79, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path79;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -7034,8 +7034,10 @@ var init_schemas = __esm({
|
|
|
7034
7034
|
* 由 daemon lark-bot-connector 模块写入,UI 只读(sidebar 按此字段隐藏,Drawer 群清单按此聚合)。
|
|
7035
7035
|
*/
|
|
7036
7036
|
larkChatId: external_exports.string().min(1).optional(),
|
|
7037
|
-
/**
|
|
7037
|
+
/** 飞书会话名快照(展示用):群会话为群名、私聊会话为对方用户名;随事件更新,可能滞后 */
|
|
7038
7038
|
larkChatName: external_exports.string().min(1).optional(),
|
|
7039
|
+
/** lark 会话类型(spec 2026-08-06 P9):p2p 与群的 chat_id 形态无法区分,UI 文案分支需要。可选=兼容老数据(缺省按 group 展示) */
|
|
7040
|
+
larkChatType: external_exports.enum(["p2p", "group"]).optional(),
|
|
7039
7041
|
createdAt: external_exports.string().min(1),
|
|
7040
7042
|
updatedAt: external_exports.string().min(1)
|
|
7041
7043
|
});
|
|
@@ -8769,8 +8771,8 @@ var require_req = __commonJS({
|
|
|
8769
8771
|
if (req.originalUrl) {
|
|
8770
8772
|
_req.url = req.originalUrl;
|
|
8771
8773
|
} else {
|
|
8772
|
-
const
|
|
8773
|
-
_req.url = typeof
|
|
8774
|
+
const path79 = req.path;
|
|
8775
|
+
_req.url = typeof path79 === "string" ? path79 : req.url ? req.url.path || req.url : void 0;
|
|
8774
8776
|
}
|
|
8775
8777
|
if (req.query) {
|
|
8776
8778
|
_req.query = req.query;
|
|
@@ -8935,14 +8937,14 @@ var require_redact = __commonJS({
|
|
|
8935
8937
|
}
|
|
8936
8938
|
return obj;
|
|
8937
8939
|
}
|
|
8938
|
-
function parsePath(
|
|
8940
|
+
function parsePath(path79) {
|
|
8939
8941
|
const parts = [];
|
|
8940
8942
|
let current = "";
|
|
8941
8943
|
let inBrackets = false;
|
|
8942
8944
|
let inQuotes = false;
|
|
8943
8945
|
let quoteChar = "";
|
|
8944
|
-
for (let i = 0; i <
|
|
8945
|
-
const char =
|
|
8946
|
+
for (let i = 0; i < path79.length; i++) {
|
|
8947
|
+
const char = path79[i];
|
|
8946
8948
|
if (!inBrackets && char === ".") {
|
|
8947
8949
|
if (current) {
|
|
8948
8950
|
parts.push(current);
|
|
@@ -9073,10 +9075,10 @@ var require_redact = __commonJS({
|
|
|
9073
9075
|
return current;
|
|
9074
9076
|
}
|
|
9075
9077
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
9076
|
-
for (const
|
|
9077
|
-
const parts = parsePath(
|
|
9078
|
+
for (const path79 of paths) {
|
|
9079
|
+
const parts = parsePath(path79);
|
|
9078
9080
|
if (parts.includes("*")) {
|
|
9079
|
-
redactWildcardPath(obj, parts, censor,
|
|
9081
|
+
redactWildcardPath(obj, parts, censor, path79, remove);
|
|
9080
9082
|
} else {
|
|
9081
9083
|
if (remove) {
|
|
9082
9084
|
removeKey(obj, parts);
|
|
@@ -9161,8 +9163,8 @@ var require_redact = __commonJS({
|
|
|
9161
9163
|
}
|
|
9162
9164
|
} else {
|
|
9163
9165
|
if (afterWildcard.includes("*")) {
|
|
9164
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9165
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
9166
|
+
const wrappedCensor = typeof censor === "function" ? (value, path79) => {
|
|
9167
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path79];
|
|
9166
9168
|
return censor(value, fullPath);
|
|
9167
9169
|
} : censor;
|
|
9168
9170
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -9197,8 +9199,8 @@ var require_redact = __commonJS({
|
|
|
9197
9199
|
return null;
|
|
9198
9200
|
}
|
|
9199
9201
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
9200
|
-
for (const
|
|
9201
|
-
const parts = parsePath(
|
|
9202
|
+
for (const path79 of pathsToClone) {
|
|
9203
|
+
const parts = parsePath(path79);
|
|
9202
9204
|
let current = pathStructure;
|
|
9203
9205
|
for (let i = 0; i < parts.length; i++) {
|
|
9204
9206
|
const part = parts[i];
|
|
@@ -9250,24 +9252,24 @@ var require_redact = __commonJS({
|
|
|
9250
9252
|
}
|
|
9251
9253
|
return cloneSelectively(obj, pathStructure);
|
|
9252
9254
|
}
|
|
9253
|
-
function validatePath(
|
|
9254
|
-
if (typeof
|
|
9255
|
+
function validatePath(path79) {
|
|
9256
|
+
if (typeof path79 !== "string") {
|
|
9255
9257
|
throw new Error("Paths must be (non-empty) strings");
|
|
9256
9258
|
}
|
|
9257
|
-
if (
|
|
9259
|
+
if (path79 === "") {
|
|
9258
9260
|
throw new Error("Invalid redaction path ()");
|
|
9259
9261
|
}
|
|
9260
|
-
if (
|
|
9261
|
-
throw new Error(`Invalid redaction path (${
|
|
9262
|
+
if (path79.includes("..")) {
|
|
9263
|
+
throw new Error(`Invalid redaction path (${path79})`);
|
|
9262
9264
|
}
|
|
9263
|
-
if (
|
|
9264
|
-
throw new Error(`Invalid redaction path (${
|
|
9265
|
+
if (path79.includes(",")) {
|
|
9266
|
+
throw new Error(`Invalid redaction path (${path79})`);
|
|
9265
9267
|
}
|
|
9266
9268
|
let bracketCount = 0;
|
|
9267
9269
|
let inQuotes = false;
|
|
9268
9270
|
let quoteChar = "";
|
|
9269
|
-
for (let i = 0; i <
|
|
9270
|
-
const char =
|
|
9271
|
+
for (let i = 0; i < path79.length; i++) {
|
|
9272
|
+
const char = path79[i];
|
|
9271
9273
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
9272
9274
|
if (!inQuotes) {
|
|
9273
9275
|
inQuotes = true;
|
|
@@ -9281,20 +9283,20 @@ var require_redact = __commonJS({
|
|
|
9281
9283
|
} else if (char === "]" && !inQuotes) {
|
|
9282
9284
|
bracketCount--;
|
|
9283
9285
|
if (bracketCount < 0) {
|
|
9284
|
-
throw new Error(`Invalid redaction path (${
|
|
9286
|
+
throw new Error(`Invalid redaction path (${path79})`);
|
|
9285
9287
|
}
|
|
9286
9288
|
}
|
|
9287
9289
|
}
|
|
9288
9290
|
if (bracketCount !== 0) {
|
|
9289
|
-
throw new Error(`Invalid redaction path (${
|
|
9291
|
+
throw new Error(`Invalid redaction path (${path79})`);
|
|
9290
9292
|
}
|
|
9291
9293
|
}
|
|
9292
9294
|
function validatePaths(paths) {
|
|
9293
9295
|
if (!Array.isArray(paths)) {
|
|
9294
9296
|
throw new TypeError("paths must be an array");
|
|
9295
9297
|
}
|
|
9296
|
-
for (const
|
|
9297
|
-
validatePath(
|
|
9298
|
+
for (const path79 of paths) {
|
|
9299
|
+
validatePath(path79);
|
|
9298
9300
|
}
|
|
9299
9301
|
}
|
|
9300
9302
|
function slowRedact(options = {}) {
|
|
@@ -9462,8 +9464,8 @@ var require_redaction = __commonJS({
|
|
|
9462
9464
|
if (shape[k2] === null) {
|
|
9463
9465
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
9464
9466
|
} else {
|
|
9465
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
9466
|
-
return censor(value, [k2, ...
|
|
9467
|
+
const wrappedCensor = typeof censor === "function" ? (value, path79) => {
|
|
9468
|
+
return censor(value, [k2, ...path79]);
|
|
9467
9469
|
} : censor;
|
|
9468
9470
|
o[k2] = Redact({
|
|
9469
9471
|
paths: shape[k2],
|
|
@@ -9681,10 +9683,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
9681
9683
|
var require_sonic_boom = __commonJS({
|
|
9682
9684
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
9683
9685
|
"use strict";
|
|
9684
|
-
var
|
|
9686
|
+
var fs69 = require("fs");
|
|
9685
9687
|
var EventEmitter3 = require("events");
|
|
9686
9688
|
var inherits = require("util").inherits;
|
|
9687
|
-
var
|
|
9689
|
+
var path79 = require("path");
|
|
9688
9690
|
var sleep2 = require_atomic_sleep();
|
|
9689
9691
|
var assert = require("assert");
|
|
9690
9692
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -9738,20 +9740,20 @@ var require_sonic_boom = __commonJS({
|
|
|
9738
9740
|
const mode = sonic.mode;
|
|
9739
9741
|
if (sonic.sync) {
|
|
9740
9742
|
try {
|
|
9741
|
-
if (sonic.mkdir)
|
|
9742
|
-
const fd =
|
|
9743
|
+
if (sonic.mkdir) fs69.mkdirSync(path79.dirname(file), { recursive: true });
|
|
9744
|
+
const fd = fs69.openSync(file, flags, mode);
|
|
9743
9745
|
fileOpened(null, fd);
|
|
9744
9746
|
} catch (err) {
|
|
9745
9747
|
fileOpened(err);
|
|
9746
9748
|
throw err;
|
|
9747
9749
|
}
|
|
9748
9750
|
} else if (sonic.mkdir) {
|
|
9749
|
-
|
|
9751
|
+
fs69.mkdir(path79.dirname(file), { recursive: true }, (err) => {
|
|
9750
9752
|
if (err) return fileOpened(err);
|
|
9751
|
-
|
|
9753
|
+
fs69.open(file, flags, mode, fileOpened);
|
|
9752
9754
|
});
|
|
9753
9755
|
} else {
|
|
9754
|
-
|
|
9756
|
+
fs69.open(file, flags, mode, fileOpened);
|
|
9755
9757
|
}
|
|
9756
9758
|
}
|
|
9757
9759
|
function SonicBoom(opts) {
|
|
@@ -9792,8 +9794,8 @@ var require_sonic_boom = __commonJS({
|
|
|
9792
9794
|
this.flush = flushBuffer;
|
|
9793
9795
|
this.flushSync = flushBufferSync;
|
|
9794
9796
|
this._actualWrite = actualWriteBuffer;
|
|
9795
|
-
fsWriteSync = () =>
|
|
9796
|
-
fsWrite = () =>
|
|
9797
|
+
fsWriteSync = () => fs69.writeSync(this.fd, this._writingBuf);
|
|
9798
|
+
fsWrite = () => fs69.write(this.fd, this._writingBuf, this.release);
|
|
9797
9799
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
9798
9800
|
this._writingBuf = "";
|
|
9799
9801
|
this.write = write;
|
|
@@ -9802,15 +9804,15 @@ var require_sonic_boom = __commonJS({
|
|
|
9802
9804
|
this._actualWrite = actualWrite;
|
|
9803
9805
|
fsWriteSync = () => {
|
|
9804
9806
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9805
|
-
return
|
|
9807
|
+
return fs69.writeSync(this.fd, this._writingBuf);
|
|
9806
9808
|
}
|
|
9807
|
-
return
|
|
9809
|
+
return fs69.writeSync(this.fd, this._writingBuf, "utf8");
|
|
9808
9810
|
};
|
|
9809
9811
|
fsWrite = () => {
|
|
9810
9812
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
9811
|
-
return
|
|
9813
|
+
return fs69.write(this.fd, this._writingBuf, this.release);
|
|
9812
9814
|
}
|
|
9813
|
-
return
|
|
9815
|
+
return fs69.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
9814
9816
|
};
|
|
9815
9817
|
} else {
|
|
9816
9818
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -9867,7 +9869,7 @@ var require_sonic_boom = __commonJS({
|
|
|
9867
9869
|
}
|
|
9868
9870
|
}
|
|
9869
9871
|
if (this._fsync) {
|
|
9870
|
-
|
|
9872
|
+
fs69.fsyncSync(this.fd);
|
|
9871
9873
|
}
|
|
9872
9874
|
const len = this._len;
|
|
9873
9875
|
if (this._reopening) {
|
|
@@ -9981,7 +9983,7 @@ var require_sonic_boom = __commonJS({
|
|
|
9981
9983
|
const onDrain = () => {
|
|
9982
9984
|
if (!this._fsync) {
|
|
9983
9985
|
try {
|
|
9984
|
-
|
|
9986
|
+
fs69.fsync(this.fd, (err) => {
|
|
9985
9987
|
this._flushPending = false;
|
|
9986
9988
|
cb(err);
|
|
9987
9989
|
});
|
|
@@ -10083,7 +10085,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10083
10085
|
const fd = this.fd;
|
|
10084
10086
|
this.once("ready", () => {
|
|
10085
10087
|
if (fd !== this.fd) {
|
|
10086
|
-
|
|
10088
|
+
fs69.close(fd, (err) => {
|
|
10087
10089
|
if (err) {
|
|
10088
10090
|
return this.emit("error", err);
|
|
10089
10091
|
}
|
|
@@ -10132,7 +10134,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10132
10134
|
buf = this._bufs[0];
|
|
10133
10135
|
}
|
|
10134
10136
|
try {
|
|
10135
|
-
const n = Buffer.isBuffer(buf) ?
|
|
10137
|
+
const n = Buffer.isBuffer(buf) ? fs69.writeSync(this.fd, buf) : fs69.writeSync(this.fd, buf, "utf8");
|
|
10136
10138
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
10137
10139
|
buf = releasedBufObj.writingBuf;
|
|
10138
10140
|
this._len = releasedBufObj.len;
|
|
@@ -10148,7 +10150,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10148
10150
|
}
|
|
10149
10151
|
}
|
|
10150
10152
|
try {
|
|
10151
|
-
|
|
10153
|
+
fs69.fsyncSync(this.fd);
|
|
10152
10154
|
} catch {
|
|
10153
10155
|
}
|
|
10154
10156
|
}
|
|
@@ -10169,7 +10171,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10169
10171
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
10170
10172
|
}
|
|
10171
10173
|
try {
|
|
10172
|
-
const n =
|
|
10174
|
+
const n = fs69.writeSync(this.fd, buf);
|
|
10173
10175
|
buf = buf.subarray(n);
|
|
10174
10176
|
this._len = Math.max(this._len - n, 0);
|
|
10175
10177
|
if (buf.length <= 0) {
|
|
@@ -10197,13 +10199,13 @@ var require_sonic_boom = __commonJS({
|
|
|
10197
10199
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
10198
10200
|
if (this.sync) {
|
|
10199
10201
|
try {
|
|
10200
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
10202
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs69.writeSync(this.fd, this._writingBuf) : fs69.writeSync(this.fd, this._writingBuf, "utf8");
|
|
10201
10203
|
release(null, written);
|
|
10202
10204
|
} catch (err) {
|
|
10203
10205
|
release(err);
|
|
10204
10206
|
}
|
|
10205
10207
|
} else {
|
|
10206
|
-
|
|
10208
|
+
fs69.write(this.fd, this._writingBuf, release);
|
|
10207
10209
|
}
|
|
10208
10210
|
}
|
|
10209
10211
|
function actualWriteBuffer() {
|
|
@@ -10212,7 +10214,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10212
10214
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
10213
10215
|
if (this.sync) {
|
|
10214
10216
|
try {
|
|
10215
|
-
const written =
|
|
10217
|
+
const written = fs69.writeSync(this.fd, this._writingBuf);
|
|
10216
10218
|
release(null, written);
|
|
10217
10219
|
} catch (err) {
|
|
10218
10220
|
release(err);
|
|
@@ -10221,7 +10223,7 @@ var require_sonic_boom = __commonJS({
|
|
|
10221
10223
|
if (kCopyBuffer) {
|
|
10222
10224
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
10223
10225
|
}
|
|
10224
|
-
|
|
10226
|
+
fs69.write(this.fd, this._writingBuf, release);
|
|
10225
10227
|
}
|
|
10226
10228
|
}
|
|
10227
10229
|
function actualClose(sonic) {
|
|
@@ -10237,12 +10239,12 @@ var require_sonic_boom = __commonJS({
|
|
|
10237
10239
|
sonic._lens = [];
|
|
10238
10240
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
10239
10241
|
try {
|
|
10240
|
-
|
|
10242
|
+
fs69.fsync(sonic.fd, closeWrapped);
|
|
10241
10243
|
} catch {
|
|
10242
10244
|
}
|
|
10243
10245
|
function closeWrapped() {
|
|
10244
10246
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
10245
|
-
|
|
10247
|
+
fs69.close(sonic.fd, done);
|
|
10246
10248
|
} else {
|
|
10247
10249
|
done();
|
|
10248
10250
|
}
|
|
@@ -13377,11 +13379,11 @@ var init_lib = __esm({
|
|
|
13377
13379
|
}
|
|
13378
13380
|
}
|
|
13379
13381
|
},
|
|
13380
|
-
addToPath: function addToPath(
|
|
13381
|
-
var last =
|
|
13382
|
+
addToPath: function addToPath(path79, added, removed, oldPosInc, options) {
|
|
13383
|
+
var last = path79.lastComponent;
|
|
13382
13384
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
13383
13385
|
return {
|
|
13384
|
-
oldPos:
|
|
13386
|
+
oldPos: path79.oldPos + oldPosInc,
|
|
13385
13387
|
lastComponent: {
|
|
13386
13388
|
count: last.count + 1,
|
|
13387
13389
|
added,
|
|
@@ -13391,7 +13393,7 @@ var init_lib = __esm({
|
|
|
13391
13393
|
};
|
|
13392
13394
|
} else {
|
|
13393
13395
|
return {
|
|
13394
|
-
oldPos:
|
|
13396
|
+
oldPos: path79.oldPos + oldPosInc,
|
|
13395
13397
|
lastComponent: {
|
|
13396
13398
|
count: 1,
|
|
13397
13399
|
added,
|
|
@@ -13900,10 +13902,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
13900
13902
|
const memories = raw.map((m2) => {
|
|
13901
13903
|
if (!m2 || typeof m2 !== "object") return null;
|
|
13902
13904
|
const rec3 = m2;
|
|
13903
|
-
const
|
|
13905
|
+
const path79 = typeof rec3.path === "string" ? rec3.path : null;
|
|
13904
13906
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
13905
|
-
if (!
|
|
13906
|
-
const entry = { path:
|
|
13907
|
+
if (!path79 || content == null) return null;
|
|
13908
|
+
const entry = { path: path79, content };
|
|
13907
13909
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
13908
13910
|
return entry;
|
|
13909
13911
|
}).filter((m2) => m2 !== null);
|
|
@@ -14720,10 +14722,10 @@ function parseAttachment(obj) {
|
|
|
14720
14722
|
const memories = raw.map((m2) => {
|
|
14721
14723
|
if (!m2 || typeof m2 !== "object") return null;
|
|
14722
14724
|
const rec3 = m2;
|
|
14723
|
-
const
|
|
14725
|
+
const path79 = typeof rec3.path === "string" ? rec3.path : null;
|
|
14724
14726
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
14725
|
-
if (!
|
|
14726
|
-
const out = { path:
|
|
14727
|
+
if (!path79 || content == null) return null;
|
|
14728
|
+
const out = { path: path79, content };
|
|
14727
14729
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
14728
14730
|
return out;
|
|
14729
14731
|
}).filter((m2) => m2 !== null);
|
|
@@ -35692,8 +35694,8 @@ var require_utils = __commonJS({
|
|
|
35692
35694
|
var result = transform[inputType][outputType](input);
|
|
35693
35695
|
return result;
|
|
35694
35696
|
};
|
|
35695
|
-
exports2.resolve = function(
|
|
35696
|
-
var parts =
|
|
35697
|
+
exports2.resolve = function(path79) {
|
|
35698
|
+
var parts = path79.split("/");
|
|
35697
35699
|
var result = [];
|
|
35698
35700
|
for (var index = 0; index < parts.length; index++) {
|
|
35699
35701
|
var part = parts[index];
|
|
@@ -41546,18 +41548,18 @@ var require_object = __commonJS({
|
|
|
41546
41548
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
41547
41549
|
this.files[name] = object;
|
|
41548
41550
|
};
|
|
41549
|
-
var parentFolder = function(
|
|
41550
|
-
if (
|
|
41551
|
-
|
|
41551
|
+
var parentFolder = function(path79) {
|
|
41552
|
+
if (path79.slice(-1) === "/") {
|
|
41553
|
+
path79 = path79.substring(0, path79.length - 1);
|
|
41552
41554
|
}
|
|
41553
|
-
var lastSlash =
|
|
41554
|
-
return lastSlash > 0 ?
|
|
41555
|
+
var lastSlash = path79.lastIndexOf("/");
|
|
41556
|
+
return lastSlash > 0 ? path79.substring(0, lastSlash) : "";
|
|
41555
41557
|
};
|
|
41556
|
-
var forceTrailingSlash = function(
|
|
41557
|
-
if (
|
|
41558
|
-
|
|
41558
|
+
var forceTrailingSlash = function(path79) {
|
|
41559
|
+
if (path79.slice(-1) !== "/") {
|
|
41560
|
+
path79 += "/";
|
|
41559
41561
|
}
|
|
41560
|
-
return
|
|
41562
|
+
return path79;
|
|
41561
41563
|
};
|
|
41562
41564
|
var folderAdd = function(name, createFolders) {
|
|
41563
41565
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -42559,7 +42561,7 @@ var require_lib3 = __commonJS({
|
|
|
42559
42561
|
// src/run-case/recorder.ts
|
|
42560
42562
|
function startRunCaseRecorder(opts) {
|
|
42561
42563
|
const now = opts.now ?? Date.now;
|
|
42562
|
-
const dir =
|
|
42564
|
+
const dir = import_node_path66.default.dirname(opts.recordPath);
|
|
42563
42565
|
let stream = null;
|
|
42564
42566
|
let closing = false;
|
|
42565
42567
|
let closedSettled = false;
|
|
@@ -42573,8 +42575,8 @@ function startRunCaseRecorder(opts) {
|
|
|
42573
42575
|
});
|
|
42574
42576
|
const ensureStream = () => {
|
|
42575
42577
|
if (stream) return stream;
|
|
42576
|
-
|
|
42577
|
-
stream =
|
|
42578
|
+
import_node_fs50.default.mkdirSync(dir, { recursive: true });
|
|
42579
|
+
stream = import_node_fs50.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
42578
42580
|
stream.on("close", () => closedResolve());
|
|
42579
42581
|
return stream;
|
|
42580
42582
|
};
|
|
@@ -42599,12 +42601,12 @@ function startRunCaseRecorder(opts) {
|
|
|
42599
42601
|
};
|
|
42600
42602
|
return { tap, close, closed };
|
|
42601
42603
|
}
|
|
42602
|
-
var
|
|
42604
|
+
var import_node_fs50, import_node_path66;
|
|
42603
42605
|
var init_recorder = __esm({
|
|
42604
42606
|
"src/run-case/recorder.ts"() {
|
|
42605
42607
|
"use strict";
|
|
42606
|
-
|
|
42607
|
-
|
|
42608
|
+
import_node_fs50 = __toESM(require("fs"), 1);
|
|
42609
|
+
import_node_path66 = __toESM(require("path"), 1);
|
|
42608
42610
|
}
|
|
42609
42611
|
});
|
|
42610
42612
|
|
|
@@ -42647,7 +42649,7 @@ var init_wire = __esm({
|
|
|
42647
42649
|
// src/run-case/controller.ts
|
|
42648
42650
|
async function runController(opts) {
|
|
42649
42651
|
const now = opts.now ?? Date.now;
|
|
42650
|
-
const cwd = opts.cwd ?? (0,
|
|
42652
|
+
const cwd = opts.cwd ?? (0, import_node_fs51.mkdtempSync)(import_node_path67.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
|
|
42651
42653
|
const ownsCwd = opts.cwd === void 0;
|
|
42652
42654
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
42653
42655
|
const spawnCtx = { cwd };
|
|
@@ -42808,19 +42810,19 @@ async function runController(opts) {
|
|
|
42808
42810
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
42809
42811
|
if (ownsCwd) {
|
|
42810
42812
|
try {
|
|
42811
|
-
(0,
|
|
42813
|
+
(0, import_node_fs51.rmSync)(cwd, { recursive: true, force: true });
|
|
42812
42814
|
} catch {
|
|
42813
42815
|
}
|
|
42814
42816
|
}
|
|
42815
42817
|
return exitCode ?? 0;
|
|
42816
42818
|
}
|
|
42817
|
-
var
|
|
42819
|
+
var import_node_fs51, import_node_os23, import_node_path67;
|
|
42818
42820
|
var init_controller = __esm({
|
|
42819
42821
|
"src/run-case/controller.ts"() {
|
|
42820
42822
|
"use strict";
|
|
42821
|
-
|
|
42823
|
+
import_node_fs51 = require("fs");
|
|
42822
42824
|
import_node_os23 = __toESM(require("os"), 1);
|
|
42823
|
-
|
|
42825
|
+
import_node_path67 = __toESM(require("path"), 1);
|
|
42824
42826
|
init_claude();
|
|
42825
42827
|
init_stdout_splitter();
|
|
42826
42828
|
init_permission_stdio();
|
|
@@ -43095,8 +43097,8 @@ Env (advanced):
|
|
|
43095
43097
|
`;
|
|
43096
43098
|
|
|
43097
43099
|
// src/index.ts
|
|
43098
|
-
var
|
|
43099
|
-
var
|
|
43100
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
43101
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
43100
43102
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
43101
43103
|
|
|
43102
43104
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -43776,9 +43778,14 @@ init_protocol();
|
|
|
43776
43778
|
var import_node_os2 = require("os");
|
|
43777
43779
|
var FORCED_DENY_READ = ["~/"];
|
|
43778
43780
|
function personaEditDeny(personaDir) {
|
|
43781
|
+
return `Edit(${tildePath(personaDir)}/**)`;
|
|
43782
|
+
}
|
|
43783
|
+
function personaReadAllow(personaDir) {
|
|
43784
|
+
return `Read(${tildePath(personaDir)}/**)`;
|
|
43785
|
+
}
|
|
43786
|
+
function tildePath(p2) {
|
|
43779
43787
|
const home = (0, import_node_os2.homedir)();
|
|
43780
|
-
|
|
43781
|
-
return `Edit(${rel}/**)`;
|
|
43788
|
+
return p2.startsWith(`${home}/`) ? `~${p2.slice(home.length)}` : p2;
|
|
43782
43789
|
}
|
|
43783
43790
|
function unionArr(a, b2) {
|
|
43784
43791
|
const out = [...a ?? []];
|
|
@@ -43794,8 +43801,8 @@ function buildGuestSettingsV1() {
|
|
|
43794
43801
|
return {
|
|
43795
43802
|
permissions: {
|
|
43796
43803
|
defaultMode: "dontAsk"
|
|
43797
|
-
// persona-dir 的 Edit deny 由
|
|
43798
|
-
// (base
|
|
43804
|
+
// persona-dir 的 Edit deny 由 store.writeSandboxSettings 落盘注入 '~/<persona>/**' 绝对规则
|
|
43805
|
+
// (base 模板不放相对 './'——会随 getCwd 漂移误拦项目,见 personaEditDeny)。
|
|
43799
43806
|
},
|
|
43800
43807
|
sandbox: {
|
|
43801
43808
|
enabled: true,
|
|
@@ -43808,7 +43815,7 @@ function buildGuestSettingsV1() {
|
|
|
43808
43815
|
denyWrite: [],
|
|
43809
43816
|
// **不放 '~/'**(写是白名单制,home 自动不可写);persona(cwd) 由 compose 强制 deny
|
|
43810
43817
|
allowRead: [],
|
|
43811
|
-
//
|
|
43818
|
+
// persona 读权由 store.writeSandboxSettings 落盘注入;userWorkDir 由 compose 注入;profile 加工具链精确路径
|
|
43812
43819
|
allowWrite: []
|
|
43813
43820
|
}
|
|
43814
43821
|
}
|
|
@@ -43846,8 +43853,9 @@ function composeGuestSandbox(base, userWorkDir, spawnCwd) {
|
|
|
43846
43853
|
s.sandbox.allowUnsandboxedCommands = false;
|
|
43847
43854
|
fsv.denyRead = unionArr(fsv.denyRead, FORCED_DENY_READ);
|
|
43848
43855
|
fsv.denyWrite = unionArr((fsv.denyWrite ?? []).filter((p2) => p2 !== "~/"), [spawnCwd]);
|
|
43849
|
-
fsv.allowRead = unionArr(fsv.allowRead, [userWorkDir
|
|
43856
|
+
fsv.allowRead = unionArr(fsv.allowRead, [userWorkDir]);
|
|
43850
43857
|
fsv.allowWrite = unionArr(fsv.allowWrite, [userWorkDir]);
|
|
43858
|
+
s.permissions.allow = unionArr(s.permissions.allow, [`Read(${tildePath(userWorkDir)}/**)`]);
|
|
43851
43859
|
return s;
|
|
43852
43860
|
}
|
|
43853
43861
|
|
|
@@ -44088,6 +44096,8 @@ function buildConnectionPrompt(args) {
|
|
|
44088
44096
|
let line = `\u4F60\u7684\u6587\u4EF6\u5DE5\u4F5C\u76EE\u5F55\u662F ${args.workDir}\uFF0C\u8FD9\u4E2A\u76EE\u5F55\u5BF9\u4F60\u53EF\u8BFB\u53EF\u5199\uFF0C\u6587\u4EF6\u7684\u8BFB\u53D6/\u521B\u5EFA/\u4FEE\u6539\u90FD\u5728\u8FD9\u91CC\u8FDB\u884C\u3002`;
|
|
44089
44097
|
if (args.mode === "guest") {
|
|
44090
44098
|
line += "persona \u76EE\u5F55\u5BF9\u4F60\u53EA\u8BFB\uFF0C\u4E0D\u8981\u5F80\u91CC\u5199\u3002";
|
|
44099
|
+
} else {
|
|
44100
|
+
line += "persona \u76EE\u5F55\u5B58\u653E\u7684\u662F\u4EBA\u683C\u914D\u7F6E\uFF1B\u5DE5\u4F5C\u4EA7\u7269\u3001\u4E34\u65F6\u6587\u4EF6\u3001\u4E0B\u8F7D\u5185\u5BB9\u9ED8\u8BA4\u5199\u5230\u4E0A\u9762\u7684\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u4E0D\u8981\u843D\u5728 persona \u76EE\u5F55\u91CC\uFF08\u66F4\u65B0\u4EBA\u683C\u914D\u7F6E\u672C\u8EAB\u9664\u5916\uFF09\u3002";
|
|
44091
44101
|
}
|
|
44092
44102
|
parts.push(line);
|
|
44093
44103
|
}
|
|
@@ -47177,8 +47187,9 @@ var SessionManager = class {
|
|
|
47177
47187
|
// guest 三件套:creatorPrincipalId=capId(scopeForFile 回落防线)、
|
|
47178
47188
|
// creatorDisplayName(reducer guest 分支硬性要求,缺则 spawn 抛)
|
|
47179
47189
|
creatorPrincipalId: capId,
|
|
47180
|
-
creatorDisplayName:
|
|
47190
|
+
creatorDisplayName: `${(args.chatType ?? "group") === "p2p" ? "\u98DE\u4E66\u79C1\u804A" : "\u98DE\u4E66\u7FA4"}\xB7${args.chatName ?? args.chatId}`,
|
|
47181
47191
|
larkChatId: args.chatId,
|
|
47192
|
+
larkChatType: args.chatType ?? "group",
|
|
47182
47193
|
...args.chatName ? { larkChatName: args.chatName } : {},
|
|
47183
47194
|
createdAt: now,
|
|
47184
47195
|
updatedAt: now
|
|
@@ -47736,21 +47747,47 @@ var PersonaStore = class {
|
|
|
47736
47747
|
* 覆盖式写 persona 级 sandbox 配置(seed 给有 profile 的 persona 写 base⊕profile;owner 之后可手编)。
|
|
47737
47748
|
* 这份是 guest 沙箱的 **base 真源**:manager spawn 时 composeGuestSandbox 读它 + 叠 sandbox 强制底座
|
|
47738
47749
|
* (enabled/denyRead/denyWrite/userWorkDir owner 削弱不了)→ 写 per-guest 文件给 CC。
|
|
47739
|
-
* 写入时强制注入本 persona
|
|
47740
|
-
* 让落盘 base 就是 source of truth(compose 不再运行时替换 permission deny
|
|
47750
|
+
* 写入时强制注入本 persona 的**基线**(Edit-deny + allowRead,见 injectPersonaBaseline),
|
|
47751
|
+
* 让落盘 base 就是 source of truth(compose 不再运行时替换 permission deny / 注入 persona 读权)。
|
|
47741
47752
|
*/
|
|
47742
47753
|
writeSandboxSettings(personaId2, settings) {
|
|
47743
47754
|
this.atomicWrite(
|
|
47744
47755
|
this.sandboxSettingsPath(personaId2),
|
|
47745
|
-
JSON.stringify(this.
|
|
47756
|
+
JSON.stringify(this.injectPersonaBaseline(personaId2, settings), null, 2)
|
|
47746
47757
|
);
|
|
47747
47758
|
}
|
|
47748
|
-
/**
|
|
47749
|
-
|
|
47759
|
+
/**
|
|
47760
|
+
* persona 基线注入:Edit-deny(绝对 '~/<persona>/**')并进 permissions.deny + 剥掉历史相对
|
|
47761
|
+
* 'Edit(./**)';persona 目录 '~/' 路径 union 进 sandbox.filesystem.allowRead(guest 读权
|
|
47762
|
+
* 落盘即真源,compose 不再运行时注入——spec 2026-08-06-persona-workdir-discipline §1-§2);
|
|
47763
|
+
* `Read(~/<persona>/**)` union 进 permissions.allow——OS 沙箱层可读只放行了 Bash,CC 自带
|
|
47764
|
+
* Read 工具在最严格 base(dontAsk + 无 allow)下仍被拒,工具层与 OS 层必须同构放行
|
|
47765
|
+
* (guest「自由读 persona 目录、只写自己 userWorkDir」,spec 2026-08-06-lark-dm §P10 通用化)。
|
|
47766
|
+
*/
|
|
47767
|
+
injectPersonaBaseline(personaId2, settings) {
|
|
47768
|
+
const dir = this.personaDir(personaId2);
|
|
47750
47769
|
const s = settings;
|
|
47751
|
-
const rule = personaEditDeny(
|
|
47752
|
-
const
|
|
47753
|
-
|
|
47770
|
+
const rule = personaEditDeny(dir);
|
|
47771
|
+
const rawDeny = s.permissions && typeof s.permissions === "object" ? s.permissions.deny : void 0;
|
|
47772
|
+
const prevDeny = (Array.isArray(rawDeny) ? rawDeny : []).filter((r) => r !== "Edit(./**)" && r !== rule);
|
|
47773
|
+
const readRule = personaReadAllow(dir);
|
|
47774
|
+
const rawAllow = s.permissions && typeof s.permissions === "object" ? s.permissions.allow : void 0;
|
|
47775
|
+
const prevAllow = (Array.isArray(rawAllow) ? rawAllow : []).filter((r) => r !== readRule);
|
|
47776
|
+
const readPath = tildePath(dir);
|
|
47777
|
+
const sandbox = s.sandbox && typeof s.sandbox === "object" && !Array.isArray(s.sandbox) ? s.sandbox : {};
|
|
47778
|
+
const rawFs = sandbox.filesystem;
|
|
47779
|
+
const filesystem = rawFs && typeof rawFs === "object" && !Array.isArray(rawFs) ? rawFs : {};
|
|
47780
|
+
const rawRead = filesystem.allowRead;
|
|
47781
|
+
const prevRead = (Array.isArray(rawRead) ? rawRead : []).filter((p2) => p2 !== readPath);
|
|
47782
|
+
return {
|
|
47783
|
+
...s,
|
|
47784
|
+
permissions: {
|
|
47785
|
+
...s.permissions && typeof s.permissions === "object" ? s.permissions : {},
|
|
47786
|
+
allow: [...prevAllow, readRule],
|
|
47787
|
+
deny: [...prevDeny, rule]
|
|
47788
|
+
},
|
|
47789
|
+
sandbox: { ...sandbox, filesystem: { ...filesystem, allowRead: [...prevRead, readPath] } }
|
|
47790
|
+
};
|
|
47754
47791
|
}
|
|
47755
47792
|
codexSandboxSettingsPath(personaId2) {
|
|
47756
47793
|
return path12.join(this.personaDir(personaId2), ".clawd", "codex-sandbox.json");
|
|
@@ -48615,6 +48652,38 @@ function migrateCodexSandbox(args) {
|
|
|
48615
48652
|
}
|
|
48616
48653
|
if (n > 0) args.logger.info("persona.codex-sandbox.done", { migrated: n });
|
|
48617
48654
|
}
|
|
48655
|
+
function migrateSandboxAllowRead(args) {
|
|
48656
|
+
let n = 0;
|
|
48657
|
+
for (const personaId2 of args.store.list()) {
|
|
48658
|
+
try {
|
|
48659
|
+
const readPath = tildePath(args.store.personaDirPath(personaId2));
|
|
48660
|
+
if (!fs12.existsSync(args.store.sandboxSettingsPath(personaId2))) {
|
|
48661
|
+
args.store.writeSandboxSettings(personaId2, buildGuestSettingsV1());
|
|
48662
|
+
n++;
|
|
48663
|
+
continue;
|
|
48664
|
+
}
|
|
48665
|
+
const raw = args.store.readSandboxSettings(personaId2);
|
|
48666
|
+
if (raw === null) {
|
|
48667
|
+
args.logger.warn("persona.sandbox.allow-read.corrupt-skip", { personaId: personaId2 });
|
|
48668
|
+
continue;
|
|
48669
|
+
}
|
|
48670
|
+
const allowRead = raw.sandbox?.filesystem?.allowRead;
|
|
48671
|
+
const permAllow = raw.permissions?.allow;
|
|
48672
|
+
const readRule = personaReadAllow(args.store.personaDirPath(personaId2));
|
|
48673
|
+
if (Array.isArray(allowRead) && allowRead.includes(readPath) && Array.isArray(permAllow) && permAllow.includes(readRule))
|
|
48674
|
+
continue;
|
|
48675
|
+
args.store.writeSandboxSettings(personaId2, raw);
|
|
48676
|
+
n++;
|
|
48677
|
+
args.logger.info("persona.sandbox.allow-read.migrated", { personaId: personaId2 });
|
|
48678
|
+
} catch (err) {
|
|
48679
|
+
args.logger.warn("persona.sandbox.allow-read.failed", {
|
|
48680
|
+
personaId: personaId2,
|
|
48681
|
+
error: err instanceof Error ? err.message : String(err)
|
|
48682
|
+
});
|
|
48683
|
+
}
|
|
48684
|
+
}
|
|
48685
|
+
if (n > 0) args.logger.info("persona.sandbox.allow-read.done", { migrated: n });
|
|
48686
|
+
}
|
|
48618
48687
|
var PERSONA_BUILDER_ID = "persona-builder";
|
|
48619
48688
|
var PERSONA_BUILDER_TOMBSTONE_MARKER = "<!-- clawd:persona-builder-retired -->";
|
|
48620
48689
|
var PERSONA_BUILDER_TOMBSTONE = `${PERSONA_BUILDER_TOMBSTONE_MARKER}
|
|
@@ -49249,8 +49318,8 @@ function turnStartInput(text) {
|
|
|
49249
49318
|
const items = [];
|
|
49250
49319
|
let leftover = text;
|
|
49251
49320
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
49252
|
-
const [marker, name,
|
|
49253
|
-
items.push({ type: "skill", name, path:
|
|
49321
|
+
const [marker, name, path79] = m2;
|
|
49322
|
+
items.push({ type: "skill", name, path: path79 });
|
|
49254
49323
|
leftover = leftover.replace(marker, "");
|
|
49255
49324
|
}
|
|
49256
49325
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -51944,14 +52013,62 @@ function createLarkBotCloudClient(opts) {
|
|
|
51944
52013
|
async claimEvents() {
|
|
51945
52014
|
const json = await request("POST", "/api/lark-bot/events/claim");
|
|
51946
52015
|
return json.items ?? [];
|
|
52016
|
+
},
|
|
52017
|
+
async fetchResource(appId, messageId, fileKey, maxBytes) {
|
|
52018
|
+
const ac = new AbortController();
|
|
52019
|
+
const timer = setTimeout(() => ac.abort(), opts.timeoutMs ?? 15e3);
|
|
52020
|
+
const qs = new URLSearchParams({
|
|
52021
|
+
appId,
|
|
52022
|
+
messageId,
|
|
52023
|
+
fileKey,
|
|
52024
|
+
...maxBytes ? { maxBytes: String(maxBytes) } : {}
|
|
52025
|
+
}).toString();
|
|
52026
|
+
let res;
|
|
52027
|
+
try {
|
|
52028
|
+
res = await f(`${base}/api/lark-bot/resource?${qs}`, {
|
|
52029
|
+
method: "GET",
|
|
52030
|
+
signal: ac.signal,
|
|
52031
|
+
headers: {
|
|
52032
|
+
authorization: `Bearer ${opts.apiKey}`,
|
|
52033
|
+
"x-did": encodeURIComponent(opts.deviceId),
|
|
52034
|
+
"x-name": encodeURIComponent(opts.displayName),
|
|
52035
|
+
"x-scene": "daemon"
|
|
52036
|
+
}
|
|
52037
|
+
});
|
|
52038
|
+
} catch (err) {
|
|
52039
|
+
throw new LarkBotCloudError(`lark-bot cloud resource fetch failed: ${err.message}`);
|
|
52040
|
+
} finally {
|
|
52041
|
+
clearTimeout(timer);
|
|
52042
|
+
}
|
|
52043
|
+
if (!res.ok) {
|
|
52044
|
+
throw new LarkBotCloudError(`lark-bot cloud resource: HTTP ${res.status}`, res.status);
|
|
52045
|
+
}
|
|
52046
|
+
const data = Buffer.from(await res.arrayBuffer());
|
|
52047
|
+
const contentType = res.headers.get("content-type") ?? "application/octet-stream";
|
|
52048
|
+
return { data, contentType };
|
|
51947
52049
|
}
|
|
51948
52050
|
};
|
|
51949
52051
|
}
|
|
51950
52052
|
|
|
51951
52053
|
// src/lark-bot-connector/chat-router.ts
|
|
52054
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
52055
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
51952
52056
|
init_protocol();
|
|
51953
52057
|
var ERROR_REPLY_TEXT = "\u5904\u7406\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
51954
52058
|
var DEFAULT_TURN_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
52059
|
+
var MAX_IMAGE_BYTES = 8 * 1024 * 1024;
|
|
52060
|
+
var EXT_BY_MIME = {
|
|
52061
|
+
"image/png": "png",
|
|
52062
|
+
"image/jpeg": "jpg",
|
|
52063
|
+
"image/gif": "gif",
|
|
52064
|
+
"image/webp": "webp"
|
|
52065
|
+
};
|
|
52066
|
+
var IMAGE_OVERSIZE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u8D85\u51FA\u5927\u5C0F\u9650\u5236]";
|
|
52067
|
+
var IMAGE_UNAVAILABLE_TEXT = "[\u56FE\u7247\u6D88\u606F\uFF0C\u6682\u4E0D\u652F\u6301\u67E5\u770B]";
|
|
52068
|
+
function safeMediaName(raw) {
|
|
52069
|
+
const cleaned = raw.replace(/[^a-zA-Z0-9_\-.]/g, "_").replace(/^\.+/, (d) => "_".repeat(d.length));
|
|
52070
|
+
return (cleaned || "msg").replace(/\.\./g, "__");
|
|
52071
|
+
}
|
|
51955
52072
|
function createLarkChatRouter(deps) {
|
|
51956
52073
|
const timeoutMs = deps.turnTimeoutMs ?? DEFAULT_TURN_TIMEOUT_MS;
|
|
51957
52074
|
const replyDelays = deps.replyRetryDelaysMs ?? [2e3, 8e3, 3e4];
|
|
@@ -51964,7 +52081,34 @@ function createLarkChatRouter(deps) {
|
|
|
51964
52081
|
return;
|
|
51965
52082
|
}
|
|
51966
52083
|
const speaker = env.senderName || env.senderOpenId || "\u672A\u77E5\u6210\u5458";
|
|
51967
|
-
const
|
|
52084
|
+
const imageLines = [];
|
|
52085
|
+
for (const [i, key] of (env.imageKeys ?? []).entries()) {
|
|
52086
|
+
try {
|
|
52087
|
+
if (!deps.fetchResource || !deps.mediaRootFor) throw new Error("resource pipeline not wired");
|
|
52088
|
+
const r = await deps.fetchResource(env.appId, env.messageId, key, MAX_IMAGE_BYTES);
|
|
52089
|
+
if (r.data.byteLength > MAX_IMAGE_BYTES) {
|
|
52090
|
+
deps.logger?.warn(`larkBot image oversize ${key}: ${r.data.byteLength}B`);
|
|
52091
|
+
imageLines.push(IMAGE_OVERSIZE_TEXT);
|
|
52092
|
+
continue;
|
|
52093
|
+
}
|
|
52094
|
+
const ext = EXT_BY_MIME[r.contentType];
|
|
52095
|
+
if (!ext) {
|
|
52096
|
+
deps.logger?.warn(`larkBot image unsupported mime ${key}: ${r.contentType}`);
|
|
52097
|
+
imageLines.push(IMAGE_UNAVAILABLE_TEXT);
|
|
52098
|
+
continue;
|
|
52099
|
+
}
|
|
52100
|
+
const dir = deps.mediaRootFor(env.chatId);
|
|
52101
|
+
import_node_fs27.default.mkdirSync(dir, { recursive: true });
|
|
52102
|
+
const p2 = import_node_path28.default.join(dir, `${safeMediaName(env.messageId)}-${i}.${ext}`);
|
|
52103
|
+
import_node_fs27.default.writeFileSync(p2, r.data);
|
|
52104
|
+
imageLines.push(`[\u56FE\u7247: ${p2}]\uFF08\u7528 Read \u5DE5\u5177\u67E5\u770B\uFF09`);
|
|
52105
|
+
} catch (err) {
|
|
52106
|
+
deps.logger?.warn(`larkBot image fetch failed ${key}: ${err.message}`);
|
|
52107
|
+
imageLines.push(IMAGE_UNAVAILABLE_TEXT);
|
|
52108
|
+
}
|
|
52109
|
+
}
|
|
52110
|
+
const rawBody = [env.text?.trim(), ...imageLines].filter(Boolean).join("\n");
|
|
52111
|
+
const body = rawBody || "[\u975E\u6587\u672C\u6D88\u606F]";
|
|
51968
52112
|
const text = `${body}
|
|
51969
52113
|
|
|
51970
52114
|
${formatLarkSpeakerReminder(speaker)}`;
|
|
@@ -51972,6 +52116,7 @@ ${formatLarkSpeakerReminder(speaker)}`;
|
|
|
51972
52116
|
personaId: env.personaId,
|
|
51973
52117
|
chatId: env.chatId,
|
|
51974
52118
|
chatName: env.chatName,
|
|
52119
|
+
chatType: env.chatType ?? "group",
|
|
51975
52120
|
senderOpenId: env.senderOpenId ?? "",
|
|
51976
52121
|
senderName: env.senderName ?? env.senderOpenId ?? "\u672A\u77E5\u6210\u5458",
|
|
51977
52122
|
text
|
|
@@ -52734,7 +52879,7 @@ var CodexHistoryReader = class {
|
|
|
52734
52879
|
};
|
|
52735
52880
|
|
|
52736
52881
|
// src/tools/codex-skills.ts
|
|
52737
|
-
var
|
|
52882
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
52738
52883
|
function str3(v2) {
|
|
52739
52884
|
return typeof v2 === "string" ? v2 : void 0;
|
|
52740
52885
|
}
|
|
@@ -52749,13 +52894,13 @@ function mapSkillsListResponse(res) {
|
|
|
52749
52894
|
const r = s ?? {};
|
|
52750
52895
|
const name = str3(r.name);
|
|
52751
52896
|
if (!name) continue;
|
|
52752
|
-
const
|
|
52897
|
+
const path79 = str3(r.path);
|
|
52753
52898
|
const description = str3(r.description);
|
|
52754
52899
|
const isPlugin = name.includes(":");
|
|
52755
52900
|
out.push({
|
|
52756
52901
|
name,
|
|
52757
52902
|
source: isPlugin ? "plugin" : "project",
|
|
52758
|
-
...
|
|
52903
|
+
...path79 ? { path: path79 } : {},
|
|
52759
52904
|
...description ? { description } : {},
|
|
52760
52905
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
52761
52906
|
});
|
|
@@ -52771,30 +52916,30 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
52771
52916
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
52772
52917
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
52773
52918
|
beforeRequest: (client) => {
|
|
52774
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
52919
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path29.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
52775
52920
|
}
|
|
52776
52921
|
});
|
|
52777
52922
|
return mapSkillsListResponse(res);
|
|
52778
52923
|
}
|
|
52779
52924
|
|
|
52780
52925
|
// src/workspace/browser.ts
|
|
52781
|
-
var
|
|
52926
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
52782
52927
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
52783
|
-
var
|
|
52928
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
52784
52929
|
init_protocol();
|
|
52785
52930
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
52786
52931
|
function resolveInsideCwd(cwd, subpath) {
|
|
52787
|
-
const absCwd =
|
|
52788
|
-
const joined =
|
|
52789
|
-
const rel =
|
|
52790
|
-
if (rel.startsWith("..") ||
|
|
52932
|
+
const absCwd = import_node_path30.default.resolve(cwd);
|
|
52933
|
+
const joined = import_node_path30.default.resolve(absCwd, subpath ?? ".");
|
|
52934
|
+
const rel = import_node_path30.default.relative(absCwd, joined);
|
|
52935
|
+
if (rel.startsWith("..") || import_node_path30.default.isAbsolute(rel)) {
|
|
52791
52936
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
52792
52937
|
}
|
|
52793
52938
|
return joined;
|
|
52794
52939
|
}
|
|
52795
52940
|
function ensureCwd(cwd) {
|
|
52796
52941
|
try {
|
|
52797
|
-
const stat =
|
|
52942
|
+
const stat = import_node_fs28.default.statSync(cwd);
|
|
52798
52943
|
if (!stat.isDirectory()) {
|
|
52799
52944
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
52800
52945
|
}
|
|
@@ -52808,7 +52953,7 @@ var WorkspaceBrowser = class {
|
|
|
52808
52953
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
|
|
52809
52954
|
ensureCwd(cwd);
|
|
52810
52955
|
const full = resolveInsideCwd(cwd, args.path);
|
|
52811
|
-
const dirents =
|
|
52956
|
+
const dirents = import_node_fs28.default.readdirSync(full, { withFileTypes: true });
|
|
52812
52957
|
const entries = [];
|
|
52813
52958
|
for (const d of dirents) {
|
|
52814
52959
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -52818,7 +52963,7 @@ var WorkspaceBrowser = class {
|
|
|
52818
52963
|
mtime: ""
|
|
52819
52964
|
};
|
|
52820
52965
|
try {
|
|
52821
|
-
const st =
|
|
52966
|
+
const st = import_node_fs28.default.statSync(import_node_path30.default.join(full, d.name));
|
|
52822
52967
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
52823
52968
|
if (d.isFile()) entry.size = st.size;
|
|
52824
52969
|
} catch {
|
|
@@ -52834,14 +52979,14 @@ var WorkspaceBrowser = class {
|
|
|
52834
52979
|
read(args) {
|
|
52835
52980
|
ensureCwd(args.cwd);
|
|
52836
52981
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
52837
|
-
const st =
|
|
52982
|
+
const st = import_node_fs28.default.statSync(full);
|
|
52838
52983
|
if (!st.isFile()) {
|
|
52839
52984
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
52840
52985
|
}
|
|
52841
52986
|
if (st.size > MAX_FILE_BYTES) {
|
|
52842
52987
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
52843
52988
|
}
|
|
52844
|
-
const buf =
|
|
52989
|
+
const buf = import_node_fs28.default.readFileSync(full);
|
|
52845
52990
|
const isBinary = buf.includes(0);
|
|
52846
52991
|
if (isBinary) {
|
|
52847
52992
|
return {
|
|
@@ -52863,20 +53008,20 @@ var WorkspaceBrowser = class {
|
|
|
52863
53008
|
};
|
|
52864
53009
|
|
|
52865
53010
|
// src/skills/agents-scanner.ts
|
|
52866
|
-
var
|
|
53011
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
52867
53012
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
52868
|
-
var
|
|
53013
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
52869
53014
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
52870
53015
|
function isDirLikeSync2(p2) {
|
|
52871
53016
|
try {
|
|
52872
|
-
return
|
|
53017
|
+
return import_node_fs29.default.statSync(p2).isDirectory();
|
|
52873
53018
|
} catch {
|
|
52874
53019
|
return false;
|
|
52875
53020
|
}
|
|
52876
53021
|
}
|
|
52877
53022
|
function fileExistsSync(p2) {
|
|
52878
53023
|
try {
|
|
52879
|
-
return
|
|
53024
|
+
return import_node_fs29.default.statSync(p2).isFile();
|
|
52880
53025
|
} catch {
|
|
52881
53026
|
return false;
|
|
52882
53027
|
}
|
|
@@ -52884,7 +53029,7 @@ function fileExistsSync(p2) {
|
|
|
52884
53029
|
function parseAgentFile(filePath) {
|
|
52885
53030
|
let content;
|
|
52886
53031
|
try {
|
|
52887
|
-
content =
|
|
53032
|
+
content = import_node_fs29.default.readFileSync(filePath, "utf8");
|
|
52888
53033
|
} catch {
|
|
52889
53034
|
return {};
|
|
52890
53035
|
}
|
|
@@ -52897,16 +53042,16 @@ function parseAgentFile(filePath) {
|
|
|
52897
53042
|
function scanAgentsDir(dir, source, seen, out) {
|
|
52898
53043
|
let entries;
|
|
52899
53044
|
try {
|
|
52900
|
-
entries =
|
|
53045
|
+
entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
|
|
52901
53046
|
} catch {
|
|
52902
53047
|
return;
|
|
52903
53048
|
}
|
|
52904
53049
|
for (const ent of entries) {
|
|
52905
53050
|
if (!ent.name.endsWith(".md")) continue;
|
|
52906
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
53051
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path31.default.join(dir, ent.name)))) {
|
|
52907
53052
|
continue;
|
|
52908
53053
|
}
|
|
52909
|
-
const filePath =
|
|
53054
|
+
const filePath = import_node_path31.default.join(dir, ent.name);
|
|
52910
53055
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
52911
53056
|
if (seen.has(baseName)) continue;
|
|
52912
53057
|
seen.add(baseName);
|
|
@@ -52924,12 +53069,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
52924
53069
|
function walk2(dir, namespaces) {
|
|
52925
53070
|
let entries;
|
|
52926
53071
|
try {
|
|
52927
|
-
entries =
|
|
53072
|
+
entries = import_node_fs29.default.readdirSync(dir, { withFileTypes: true });
|
|
52928
53073
|
} catch {
|
|
52929
53074
|
return;
|
|
52930
53075
|
}
|
|
52931
53076
|
for (const ent of entries) {
|
|
52932
|
-
const childPath =
|
|
53077
|
+
const childPath = import_node_path31.default.join(dir, ent.name);
|
|
52933
53078
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
52934
53079
|
walk2(childPath, [...namespaces, ent.name]);
|
|
52935
53080
|
continue;
|
|
@@ -52954,13 +53099,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
52954
53099
|
walk2(root, []);
|
|
52955
53100
|
}
|
|
52956
53101
|
function readInstalledPlugins2(home) {
|
|
52957
|
-
const pluginsDir =
|
|
52958
|
-
const v2 =
|
|
52959
|
-
const v1 =
|
|
53102
|
+
const pluginsDir = import_node_path31.default.join(home, ".claude", "plugins");
|
|
53103
|
+
const v2 = import_node_path31.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
53104
|
+
const v1 = import_node_path31.default.join(pluginsDir, "installed_plugins.json");
|
|
52960
53105
|
let raw = null;
|
|
52961
53106
|
for (const candidate of [v2, v1]) {
|
|
52962
53107
|
try {
|
|
52963
|
-
raw =
|
|
53108
|
+
raw = import_node_fs29.default.readFileSync(candidate, "utf8");
|
|
52964
53109
|
break;
|
|
52965
53110
|
} catch {
|
|
52966
53111
|
}
|
|
@@ -52985,19 +53130,19 @@ function readInstalledPlugins2(home) {
|
|
|
52985
53130
|
return out;
|
|
52986
53131
|
}
|
|
52987
53132
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
52988
|
-
let cur =
|
|
52989
|
-
const fsRoot =
|
|
53133
|
+
let cur = import_node_path31.default.resolve(startCwd);
|
|
53134
|
+
const fsRoot = import_node_path31.default.parse(cur).root;
|
|
52990
53135
|
while (true) {
|
|
52991
|
-
scanAgentsDir(
|
|
53136
|
+
scanAgentsDir(import_node_path31.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
52992
53137
|
let hasGit = false;
|
|
52993
53138
|
try {
|
|
52994
|
-
hasGit =
|
|
53139
|
+
hasGit = import_node_fs29.default.existsSync(import_node_path31.default.join(cur, ".git"));
|
|
52995
53140
|
} catch {
|
|
52996
53141
|
}
|
|
52997
53142
|
if (hasGit) return;
|
|
52998
53143
|
if (cur === home) return;
|
|
52999
53144
|
if (cur === fsRoot) return;
|
|
53000
|
-
const parent =
|
|
53145
|
+
const parent = import_node_path31.default.dirname(cur);
|
|
53001
53146
|
if (parent === cur) return;
|
|
53002
53147
|
cur = parent;
|
|
53003
53148
|
}
|
|
@@ -53032,7 +53177,7 @@ var AgentsScanner = class {
|
|
|
53032
53177
|
}
|
|
53033
53178
|
const fsBlock = [];
|
|
53034
53179
|
scanAgentsDir(
|
|
53035
|
-
|
|
53180
|
+
import_node_path31.default.join(this.home, ".claude", "agents"),
|
|
53036
53181
|
"global",
|
|
53037
53182
|
seen,
|
|
53038
53183
|
fsBlock
|
|
@@ -53046,7 +53191,7 @@ var AgentsScanner = class {
|
|
|
53046
53191
|
...this.extraPluginRoots
|
|
53047
53192
|
];
|
|
53048
53193
|
for (const { name, root } of plugins) {
|
|
53049
|
-
const agentsRoot =
|
|
53194
|
+
const agentsRoot = import_node_path31.default.join(root, "agents");
|
|
53050
53195
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
53051
53196
|
}
|
|
53052
53197
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -53054,15 +53199,15 @@ var AgentsScanner = class {
|
|
|
53054
53199
|
};
|
|
53055
53200
|
|
|
53056
53201
|
// src/observer/session-observer.ts
|
|
53057
|
-
var
|
|
53202
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
53058
53203
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
53059
|
-
var
|
|
53204
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
53060
53205
|
init_claude_history();
|
|
53061
53206
|
|
|
53062
53207
|
// src/observer/subagent-meta-observer.ts
|
|
53063
|
-
var
|
|
53208
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
53064
53209
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
53065
|
-
var
|
|
53210
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
53066
53211
|
init_claude_history();
|
|
53067
53212
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
53068
53213
|
var SubagentMetaObserver = class {
|
|
@@ -53075,7 +53220,7 @@ var SubagentMetaObserver = class {
|
|
|
53075
53220
|
watches = /* @__PURE__ */ new Map();
|
|
53076
53221
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
53077
53222
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
53078
|
-
return
|
|
53223
|
+
return import_node_path32.default.join(
|
|
53079
53224
|
this.home,
|
|
53080
53225
|
".claude",
|
|
53081
53226
|
"projects",
|
|
@@ -53105,7 +53250,7 @@ var SubagentMetaObserver = class {
|
|
|
53105
53250
|
attachWatcher(w2) {
|
|
53106
53251
|
if (w2.watcher) return;
|
|
53107
53252
|
try {
|
|
53108
|
-
w2.watcher =
|
|
53253
|
+
w2.watcher = import_node_fs30.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
53109
53254
|
if (!name) return;
|
|
53110
53255
|
const m2 = META_RE.exec(String(name));
|
|
53111
53256
|
if (!m2) return;
|
|
@@ -53117,7 +53262,7 @@ var SubagentMetaObserver = class {
|
|
|
53117
53262
|
scan(w2) {
|
|
53118
53263
|
let entries;
|
|
53119
53264
|
try {
|
|
53120
|
-
entries =
|
|
53265
|
+
entries = import_node_fs30.default.readdirSync(w2.dirPath);
|
|
53121
53266
|
} catch {
|
|
53122
53267
|
return;
|
|
53123
53268
|
}
|
|
@@ -53131,10 +53276,10 @@ var SubagentMetaObserver = class {
|
|
|
53131
53276
|
if (!m2) return;
|
|
53132
53277
|
const agentId = m2[1];
|
|
53133
53278
|
if (w2.emitted.has(agentId)) return;
|
|
53134
|
-
const file =
|
|
53279
|
+
const file = import_node_path32.default.join(w2.dirPath, name);
|
|
53135
53280
|
let raw;
|
|
53136
53281
|
try {
|
|
53137
|
-
raw =
|
|
53282
|
+
raw = import_node_fs30.default.readFileSync(file, "utf8");
|
|
53138
53283
|
} catch {
|
|
53139
53284
|
return;
|
|
53140
53285
|
}
|
|
@@ -53191,14 +53336,14 @@ var SessionObserver = class {
|
|
|
53191
53336
|
metaObserver;
|
|
53192
53337
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
53193
53338
|
if (override) return override;
|
|
53194
|
-
return
|
|
53339
|
+
return import_node_path33.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
53195
53340
|
}
|
|
53196
53341
|
start(args) {
|
|
53197
53342
|
this.stop(args.sessionId);
|
|
53198
53343
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
53199
53344
|
let size = 0;
|
|
53200
53345
|
try {
|
|
53201
|
-
size =
|
|
53346
|
+
size = import_node_fs31.default.statSync(filePath).size;
|
|
53202
53347
|
} catch {
|
|
53203
53348
|
}
|
|
53204
53349
|
const w2 = {
|
|
@@ -53211,16 +53356,16 @@ var SessionObserver = class {
|
|
|
53211
53356
|
adapter: args.adapter,
|
|
53212
53357
|
prevIsRejectSentinel: false,
|
|
53213
53358
|
toolSessionId: args.toolSessionId,
|
|
53214
|
-
sawFile:
|
|
53359
|
+
sawFile: import_node_fs31.default.existsSync(filePath),
|
|
53215
53360
|
lastRelocateScanMs: 0,
|
|
53216
53361
|
pendingCwdDerive: false,
|
|
53217
53362
|
lastDeriveMs: 0
|
|
53218
53363
|
};
|
|
53219
53364
|
try {
|
|
53220
|
-
|
|
53365
|
+
import_node_fs31.default.mkdirSync(import_node_path33.default.dirname(filePath), { recursive: true });
|
|
53221
53366
|
} catch {
|
|
53222
53367
|
}
|
|
53223
|
-
w2.watcher =
|
|
53368
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
53224
53369
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
53225
53370
|
this.poll(w2);
|
|
53226
53371
|
});
|
|
@@ -53243,7 +53388,7 @@ var SessionObserver = class {
|
|
|
53243
53388
|
// 异常静默吞,不阻塞 watcher 启动
|
|
53244
53389
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
53245
53390
|
try {
|
|
53246
|
-
const raw =
|
|
53391
|
+
const raw = import_node_fs31.default.readFileSync(w2.filePath, "utf8");
|
|
53247
53392
|
if (!raw) return;
|
|
53248
53393
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
53249
53394
|
if (allLines.length === 0) return;
|
|
@@ -53267,7 +53412,7 @@ var SessionObserver = class {
|
|
|
53267
53412
|
poll(w2) {
|
|
53268
53413
|
let size = 0;
|
|
53269
53414
|
try {
|
|
53270
|
-
size =
|
|
53415
|
+
size = import_node_fs31.default.statSync(w2.filePath).size;
|
|
53271
53416
|
} catch {
|
|
53272
53417
|
if (w2.sawFile) this.maybeRelocate(w2);
|
|
53273
53418
|
return;
|
|
@@ -53278,11 +53423,11 @@ var SessionObserver = class {
|
|
|
53278
53423
|
w2.buf = "";
|
|
53279
53424
|
}
|
|
53280
53425
|
if (size === w2.lastSize) return;
|
|
53281
|
-
const fd =
|
|
53426
|
+
const fd = import_node_fs31.default.openSync(w2.filePath, "r");
|
|
53282
53427
|
try {
|
|
53283
53428
|
const len = size - w2.lastSize;
|
|
53284
53429
|
const buf = Buffer.alloc(len);
|
|
53285
|
-
|
|
53430
|
+
import_node_fs31.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
53286
53431
|
w2.lastSize = size;
|
|
53287
53432
|
w2.buf += buf.toString("utf8");
|
|
53288
53433
|
let newlineIndex;
|
|
@@ -53305,7 +53450,7 @@ var SessionObserver = class {
|
|
|
53305
53450
|
}
|
|
53306
53451
|
}
|
|
53307
53452
|
} finally {
|
|
53308
|
-
|
|
53453
|
+
import_node_fs31.default.closeSync(fd);
|
|
53309
53454
|
}
|
|
53310
53455
|
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
53311
53456
|
}
|
|
@@ -53317,7 +53462,7 @@ var SessionObserver = class {
|
|
|
53317
53462
|
const now = Date.now();
|
|
53318
53463
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
53319
53464
|
w2.lastRelocateScanMs = now;
|
|
53320
|
-
const projectsRoot =
|
|
53465
|
+
const projectsRoot = import_node_path33.default.join(this.home, ".claude", "projects");
|
|
53321
53466
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
53322
53467
|
if (!found || found === w2.filePath) return;
|
|
53323
53468
|
try {
|
|
@@ -53326,7 +53471,7 @@ var SessionObserver = class {
|
|
|
53326
53471
|
}
|
|
53327
53472
|
w2.filePath = found;
|
|
53328
53473
|
try {
|
|
53329
|
-
w2.watcher =
|
|
53474
|
+
w2.watcher = import_node_fs31.default.watch(import_node_path33.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
53330
53475
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
53331
53476
|
this.poll(w2);
|
|
53332
53477
|
});
|
|
@@ -54121,8 +54266,8 @@ async function authenticate(token, deps) {
|
|
|
54121
54266
|
}
|
|
54122
54267
|
|
|
54123
54268
|
// src/legacy-cleanup.ts
|
|
54124
|
-
var
|
|
54125
|
-
var
|
|
54269
|
+
var fs36 = __toESM(require("fs/promises"), 1);
|
|
54270
|
+
var path38 = __toESM(require("path"), 1);
|
|
54126
54271
|
var LEGACY_FILES = [
|
|
54127
54272
|
"personal-capability.json",
|
|
54128
54273
|
"received-capabilities.json",
|
|
@@ -54131,9 +54276,9 @@ var LEGACY_FILES = [
|
|
|
54131
54276
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
54132
54277
|
const removed = [];
|
|
54133
54278
|
for (const name of LEGACY_FILES) {
|
|
54134
|
-
const p2 =
|
|
54279
|
+
const p2 = path38.join(dataDir, name);
|
|
54135
54280
|
try {
|
|
54136
|
-
await
|
|
54281
|
+
await fs36.unlink(p2);
|
|
54137
54282
|
removed.push(name);
|
|
54138
54283
|
logger.debug("legacy capability file removed", { file: name });
|
|
54139
54284
|
} catch (err) {
|
|
@@ -54145,13 +54290,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
54145
54290
|
}
|
|
54146
54291
|
|
|
54147
54292
|
// src/inbox/inbox-store.ts
|
|
54148
|
-
var
|
|
54149
|
-
var
|
|
54293
|
+
var fs37 = __toESM(require("fs"), 1);
|
|
54294
|
+
var path39 = __toESM(require("path"), 1);
|
|
54150
54295
|
var INBOX_SUBDIR = "inbox";
|
|
54151
54296
|
var InboxStore = class {
|
|
54152
54297
|
constructor(dataDir) {
|
|
54153
54298
|
this.dataDir = dataDir;
|
|
54154
|
-
|
|
54299
|
+
fs37.mkdirSync(this.dirPath(), { recursive: true });
|
|
54155
54300
|
}
|
|
54156
54301
|
dataDir;
|
|
54157
54302
|
/**
|
|
@@ -54163,7 +54308,7 @@ var InboxStore = class {
|
|
|
54163
54308
|
const file = this.filePath(peerDeviceId);
|
|
54164
54309
|
let raw;
|
|
54165
54310
|
try {
|
|
54166
|
-
raw =
|
|
54311
|
+
raw = fs37.readFileSync(file, "utf8");
|
|
54167
54312
|
} catch (err) {
|
|
54168
54313
|
if (err?.code === "ENOENT") return [];
|
|
54169
54314
|
return [];
|
|
@@ -54179,7 +54324,7 @@ var InboxStore = class {
|
|
|
54179
54324
|
const dir = this.dirPath();
|
|
54180
54325
|
let entries;
|
|
54181
54326
|
try {
|
|
54182
|
-
entries =
|
|
54327
|
+
entries = fs37.readdirSync(dir);
|
|
54183
54328
|
} catch (err) {
|
|
54184
54329
|
if (err?.code === "ENOENT") return [];
|
|
54185
54330
|
return [];
|
|
@@ -54195,9 +54340,9 @@ var InboxStore = class {
|
|
|
54195
54340
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
54196
54341
|
const file = this.filePath(message.peerDeviceId);
|
|
54197
54342
|
const line = JSON.stringify(message) + "\n";
|
|
54198
|
-
|
|
54343
|
+
fs37.appendFileSync(file, line, { mode: 384 });
|
|
54199
54344
|
try {
|
|
54200
|
-
|
|
54345
|
+
fs37.chmodSync(file, 384);
|
|
54201
54346
|
} catch {
|
|
54202
54347
|
}
|
|
54203
54348
|
}
|
|
@@ -54227,7 +54372,7 @@ var InboxStore = class {
|
|
|
54227
54372
|
removeByPeerDeviceId(peerDeviceId) {
|
|
54228
54373
|
const file = this.filePath(peerDeviceId);
|
|
54229
54374
|
try {
|
|
54230
|
-
|
|
54375
|
+
fs37.unlinkSync(file);
|
|
54231
54376
|
} catch (err) {
|
|
54232
54377
|
if (err?.code === "ENOENT") return;
|
|
54233
54378
|
}
|
|
@@ -54236,18 +54381,18 @@ var InboxStore = class {
|
|
|
54236
54381
|
const file = this.filePath(peerDeviceId);
|
|
54237
54382
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
54238
54383
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
54239
|
-
|
|
54240
|
-
|
|
54384
|
+
fs37.writeFileSync(tmp, content, { mode: 384 });
|
|
54385
|
+
fs37.renameSync(tmp, file);
|
|
54241
54386
|
try {
|
|
54242
|
-
|
|
54387
|
+
fs37.chmodSync(file, 384);
|
|
54243
54388
|
} catch {
|
|
54244
54389
|
}
|
|
54245
54390
|
}
|
|
54246
54391
|
dirPath() {
|
|
54247
|
-
return
|
|
54392
|
+
return path39.join(this.dataDir, INBOX_SUBDIR);
|
|
54248
54393
|
}
|
|
54249
54394
|
filePath(peerDeviceId) {
|
|
54250
|
-
return
|
|
54395
|
+
return path39.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
54251
54396
|
}
|
|
54252
54397
|
};
|
|
54253
54398
|
function parseAllLines(raw) {
|
|
@@ -54335,8 +54480,8 @@ var InboxManager = class {
|
|
|
54335
54480
|
};
|
|
54336
54481
|
|
|
54337
54482
|
// src/state/contact-store.ts
|
|
54338
|
-
var
|
|
54339
|
-
var
|
|
54483
|
+
var fs38 = __toESM(require("fs"), 1);
|
|
54484
|
+
var path40 = __toESM(require("path"), 1);
|
|
54340
54485
|
var FILE_NAME = "contacts.json";
|
|
54341
54486
|
var ContactStore = class {
|
|
54342
54487
|
constructor(dataDir) {
|
|
@@ -54346,10 +54491,10 @@ var ContactStore = class {
|
|
|
54346
54491
|
contacts = /* @__PURE__ */ new Map();
|
|
54347
54492
|
load() {
|
|
54348
54493
|
this.contacts.clear();
|
|
54349
|
-
const file =
|
|
54494
|
+
const file = path40.join(this.dataDir, FILE_NAME);
|
|
54350
54495
|
let raw;
|
|
54351
54496
|
try {
|
|
54352
|
-
raw =
|
|
54497
|
+
raw = fs38.readFileSync(file, "utf8");
|
|
54353
54498
|
} catch (err) {
|
|
54354
54499
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
54355
54500
|
return;
|
|
@@ -54418,20 +54563,20 @@ var ContactStore = class {
|
|
|
54418
54563
|
return true;
|
|
54419
54564
|
}
|
|
54420
54565
|
flush() {
|
|
54421
|
-
const file =
|
|
54566
|
+
const file = path40.join(this.dataDir, FILE_NAME);
|
|
54422
54567
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
54423
54568
|
const content = JSON.stringify(
|
|
54424
54569
|
{ contacts: Array.from(this.contacts.values()) },
|
|
54425
54570
|
null,
|
|
54426
54571
|
2
|
|
54427
54572
|
);
|
|
54428
|
-
|
|
54429
|
-
|
|
54430
|
-
|
|
54573
|
+
fs38.mkdirSync(this.dataDir, { recursive: true });
|
|
54574
|
+
fs38.writeFileSync(tmp, content, { mode: 384 });
|
|
54575
|
+
fs38.renameSync(tmp, file);
|
|
54431
54576
|
}
|
|
54432
54577
|
renameBak(file) {
|
|
54433
54578
|
try {
|
|
54434
|
-
|
|
54579
|
+
fs38.renameSync(file, `${file}.bak`);
|
|
54435
54580
|
} catch {
|
|
54436
54581
|
}
|
|
54437
54582
|
}
|
|
@@ -54539,61 +54684,61 @@ async function connectRemote(args) {
|
|
|
54539
54684
|
}
|
|
54540
54685
|
|
|
54541
54686
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
54542
|
-
var
|
|
54543
|
-
var
|
|
54687
|
+
var fs39 = __toESM(require("fs"), 1);
|
|
54688
|
+
var path41 = __toESM(require("path"), 1);
|
|
54544
54689
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
54545
54690
|
function migrateFlattenSessions(opts) {
|
|
54546
54691
|
const dataDir = opts.dataDir;
|
|
54547
54692
|
const now = opts.now ?? Date.now;
|
|
54548
|
-
const sessionsDir =
|
|
54549
|
-
const flagPath =
|
|
54693
|
+
const sessionsDir = path41.join(dataDir, "sessions");
|
|
54694
|
+
const flagPath = path41.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
54550
54695
|
if (existsSync3(flagPath)) {
|
|
54551
54696
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
54552
54697
|
}
|
|
54553
54698
|
let movedBare = 0;
|
|
54554
54699
|
let movedVmOwner = 0;
|
|
54555
54700
|
let archivedListener = 0;
|
|
54556
|
-
const defaultDir =
|
|
54701
|
+
const defaultDir = path41.join(sessionsDir, "default");
|
|
54557
54702
|
if (existsSync3(defaultDir)) {
|
|
54558
54703
|
for (const entry of readdirSafe(defaultDir)) {
|
|
54559
54704
|
if (!entry.endsWith(".json")) continue;
|
|
54560
|
-
const src =
|
|
54561
|
-
const dst =
|
|
54562
|
-
|
|
54705
|
+
const src = path41.join(defaultDir, entry);
|
|
54706
|
+
const dst = path41.join(sessionsDir, entry);
|
|
54707
|
+
fs39.renameSync(src, dst);
|
|
54563
54708
|
movedBare += 1;
|
|
54564
54709
|
}
|
|
54565
54710
|
rmdirIfEmpty(defaultDir);
|
|
54566
54711
|
}
|
|
54567
54712
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
54568
|
-
const personaDir =
|
|
54713
|
+
const personaDir = path41.join(sessionsDir, pid);
|
|
54569
54714
|
if (!isDir(personaDir)) continue;
|
|
54570
54715
|
if (pid === "default") continue;
|
|
54571
|
-
const ownerSrc =
|
|
54716
|
+
const ownerSrc = path41.join(personaDir, "owner");
|
|
54572
54717
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
54573
|
-
const ownerDst =
|
|
54574
|
-
|
|
54718
|
+
const ownerDst = path41.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
54719
|
+
fs39.mkdirSync(ownerDst, { recursive: true });
|
|
54575
54720
|
for (const file of readdirSafe(ownerSrc)) {
|
|
54576
54721
|
if (!file.endsWith(".json")) continue;
|
|
54577
|
-
|
|
54722
|
+
fs39.renameSync(path41.join(ownerSrc, file), path41.join(ownerDst, file));
|
|
54578
54723
|
movedVmOwner += 1;
|
|
54579
54724
|
}
|
|
54580
54725
|
rmdirIfEmpty(ownerSrc);
|
|
54581
54726
|
}
|
|
54582
|
-
const listenerSrc =
|
|
54727
|
+
const listenerSrc = path41.join(personaDir, "listener");
|
|
54583
54728
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
54584
|
-
const archiveDst =
|
|
54585
|
-
|
|
54729
|
+
const archiveDst = path41.join(dataDir, ".legacy", `listener-${pid}`);
|
|
54730
|
+
fs39.mkdirSync(archiveDst, { recursive: true });
|
|
54586
54731
|
for (const file of readdirSafe(listenerSrc)) {
|
|
54587
54732
|
if (!file.endsWith(".json")) continue;
|
|
54588
|
-
|
|
54733
|
+
fs39.renameSync(path41.join(listenerSrc, file), path41.join(archiveDst, file));
|
|
54589
54734
|
archivedListener += 1;
|
|
54590
54735
|
}
|
|
54591
54736
|
rmdirIfEmpty(listenerSrc);
|
|
54592
54737
|
}
|
|
54593
54738
|
rmdirIfEmpty(personaDir);
|
|
54594
54739
|
}
|
|
54595
|
-
|
|
54596
|
-
|
|
54740
|
+
fs39.mkdirSync(sessionsDir, { recursive: true });
|
|
54741
|
+
fs39.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
54597
54742
|
return {
|
|
54598
54743
|
skipped: false,
|
|
54599
54744
|
flagWritten: true,
|
|
@@ -54604,7 +54749,7 @@ function migrateFlattenSessions(opts) {
|
|
|
54604
54749
|
}
|
|
54605
54750
|
function existsSync3(p2) {
|
|
54606
54751
|
try {
|
|
54607
|
-
|
|
54752
|
+
fs39.statSync(p2);
|
|
54608
54753
|
return true;
|
|
54609
54754
|
} catch {
|
|
54610
54755
|
return false;
|
|
@@ -54612,31 +54757,31 @@ function existsSync3(p2) {
|
|
|
54612
54757
|
}
|
|
54613
54758
|
function isDir(p2) {
|
|
54614
54759
|
try {
|
|
54615
|
-
return
|
|
54760
|
+
return fs39.statSync(p2).isDirectory();
|
|
54616
54761
|
} catch {
|
|
54617
54762
|
return false;
|
|
54618
54763
|
}
|
|
54619
54764
|
}
|
|
54620
54765
|
function readdirSafe(p2) {
|
|
54621
54766
|
try {
|
|
54622
|
-
return
|
|
54767
|
+
return fs39.readdirSync(p2);
|
|
54623
54768
|
} catch {
|
|
54624
54769
|
return [];
|
|
54625
54770
|
}
|
|
54626
54771
|
}
|
|
54627
54772
|
function rmdirIfEmpty(p2) {
|
|
54628
54773
|
try {
|
|
54629
|
-
|
|
54774
|
+
fs39.rmdirSync(p2);
|
|
54630
54775
|
} catch {
|
|
54631
54776
|
}
|
|
54632
54777
|
}
|
|
54633
54778
|
|
|
54634
54779
|
// src/transport/http-router.ts
|
|
54635
|
-
var
|
|
54636
|
-
var
|
|
54780
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
54781
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
54637
54782
|
|
|
54638
54783
|
// src/attachment/mime.ts
|
|
54639
|
-
var
|
|
54784
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
54640
54785
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
54641
54786
|
var EXT_TO_NATIVE_MIME = {
|
|
54642
54787
|
// 图片
|
|
@@ -54743,7 +54888,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
54743
54888
|
".mk"
|
|
54744
54889
|
]);
|
|
54745
54890
|
function lookupMime(filePathOrName) {
|
|
54746
|
-
const ext =
|
|
54891
|
+
const ext = import_node_path34.default.extname(filePathOrName).toLowerCase();
|
|
54747
54892
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
54748
54893
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
54749
54894
|
return "application/octet-stream";
|
|
@@ -54813,8 +54958,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
54813
54958
|
}
|
|
54814
54959
|
|
|
54815
54960
|
// src/attachment/upload.ts
|
|
54816
|
-
var
|
|
54817
|
-
var
|
|
54961
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
54962
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
54818
54963
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
54819
54964
|
var import_promises3 = require("stream/promises");
|
|
54820
54965
|
var UploadError = class extends Error {
|
|
@@ -54826,22 +54971,22 @@ var UploadError = class extends Error {
|
|
|
54826
54971
|
code;
|
|
54827
54972
|
};
|
|
54828
54973
|
function assertValidFileName(fileName) {
|
|
54829
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
54974
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path35.default.basename(fileName)) {
|
|
54830
54975
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
54831
54976
|
}
|
|
54832
54977
|
}
|
|
54833
54978
|
var HASH_PREFIX_LEN = 16;
|
|
54834
54979
|
async function writeUploadedAttachment(args) {
|
|
54835
54980
|
assertValidFileName(args.fileName);
|
|
54836
|
-
const attachmentsRoot =
|
|
54981
|
+
const attachmentsRoot = import_node_path35.default.join(args.baseDir, ".attachments");
|
|
54837
54982
|
try {
|
|
54838
|
-
|
|
54983
|
+
import_node_fs32.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
54839
54984
|
} catch (err) {
|
|
54840
54985
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
54841
54986
|
}
|
|
54842
54987
|
const hasher = import_node_crypto8.default.createHash("sha256");
|
|
54843
54988
|
let actualSize = 0;
|
|
54844
|
-
const tmpPath =
|
|
54989
|
+
const tmpPath = import_node_path35.default.join(
|
|
54845
54990
|
attachmentsRoot,
|
|
54846
54991
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
|
|
54847
54992
|
);
|
|
@@ -54856,18 +55001,18 @@ async function writeUploadedAttachment(args) {
|
|
|
54856
55001
|
yield buf;
|
|
54857
55002
|
}
|
|
54858
55003
|
},
|
|
54859
|
-
|
|
55004
|
+
import_node_fs32.default.createWriteStream(tmpPath, { mode: 384 })
|
|
54860
55005
|
);
|
|
54861
55006
|
} catch (err) {
|
|
54862
55007
|
try {
|
|
54863
|
-
|
|
55008
|
+
import_node_fs32.default.unlinkSync(tmpPath);
|
|
54864
55009
|
} catch {
|
|
54865
55010
|
}
|
|
54866
55011
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
54867
55012
|
}
|
|
54868
55013
|
if (actualSize !== args.contentLength) {
|
|
54869
55014
|
try {
|
|
54870
|
-
|
|
55015
|
+
import_node_fs32.default.unlinkSync(tmpPath);
|
|
54871
55016
|
} catch {
|
|
54872
55017
|
}
|
|
54873
55018
|
throw new UploadError(
|
|
@@ -54876,35 +55021,35 @@ async function writeUploadedAttachment(args) {
|
|
|
54876
55021
|
);
|
|
54877
55022
|
}
|
|
54878
55023
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
54879
|
-
const hashDir =
|
|
55024
|
+
const hashDir = import_node_path35.default.join(attachmentsRoot, attachmentId);
|
|
54880
55025
|
let finalFileName;
|
|
54881
55026
|
let hashDirExists = false;
|
|
54882
55027
|
try {
|
|
54883
|
-
hashDirExists =
|
|
55028
|
+
hashDirExists = import_node_fs32.default.statSync(hashDir).isDirectory();
|
|
54884
55029
|
} catch {
|
|
54885
55030
|
}
|
|
54886
55031
|
if (hashDirExists) {
|
|
54887
|
-
const existing =
|
|
55032
|
+
const existing = import_node_fs32.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
54888
55033
|
finalFileName = existing[0] ?? args.fileName;
|
|
54889
55034
|
try {
|
|
54890
|
-
|
|
55035
|
+
import_node_fs32.default.unlinkSync(tmpPath);
|
|
54891
55036
|
} catch {
|
|
54892
55037
|
}
|
|
54893
55038
|
} else {
|
|
54894
55039
|
try {
|
|
54895
|
-
|
|
55040
|
+
import_node_fs32.default.mkdirSync(hashDir, { recursive: true });
|
|
54896
55041
|
finalFileName = args.fileName;
|
|
54897
|
-
|
|
55042
|
+
import_node_fs32.default.renameSync(tmpPath, import_node_path35.default.join(hashDir, finalFileName));
|
|
54898
55043
|
} catch (err) {
|
|
54899
55044
|
try {
|
|
54900
|
-
|
|
55045
|
+
import_node_fs32.default.unlinkSync(tmpPath);
|
|
54901
55046
|
} catch {
|
|
54902
55047
|
}
|
|
54903
55048
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
54904
55049
|
}
|
|
54905
55050
|
}
|
|
54906
|
-
const absPath =
|
|
54907
|
-
const relPath =
|
|
55051
|
+
const absPath = import_node_path35.default.join(hashDir, finalFileName);
|
|
55052
|
+
const relPath = absPath;
|
|
54908
55053
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
54909
55054
|
relPath: absPath,
|
|
54910
55055
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -54918,7 +55063,7 @@ async function writeUploadedAttachment(args) {
|
|
|
54918
55063
|
|
|
54919
55064
|
// src/extension/import.ts
|
|
54920
55065
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
54921
|
-
var
|
|
55066
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
54922
55067
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
54923
55068
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
54924
55069
|
var ImportError = class extends Error {
|
|
@@ -54936,7 +55081,7 @@ async function importZip(buf, root) {
|
|
|
54936
55081
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
54937
55082
|
}
|
|
54938
55083
|
for (const name of Object.keys(zip.files)) {
|
|
54939
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
55084
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path36.default.isAbsolute(name)) {
|
|
54940
55085
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
54941
55086
|
}
|
|
54942
55087
|
}
|
|
@@ -54969,7 +55114,7 @@ async function importZip(buf, root) {
|
|
|
54969
55114
|
);
|
|
54970
55115
|
}
|
|
54971
55116
|
}
|
|
54972
|
-
const destDir =
|
|
55117
|
+
const destDir = import_node_path36.default.join(root, manifest.id);
|
|
54973
55118
|
let destExists = false;
|
|
54974
55119
|
try {
|
|
54975
55120
|
await import_promises4.default.access(destDir);
|
|
@@ -54979,15 +55124,15 @@ async function importZip(buf, root) {
|
|
|
54979
55124
|
if (destExists) {
|
|
54980
55125
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
54981
55126
|
}
|
|
54982
|
-
const stage = await import_promises4.default.mkdtemp(
|
|
55127
|
+
const stage = await import_promises4.default.mkdtemp(import_node_path36.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
54983
55128
|
try {
|
|
54984
55129
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
54985
|
-
const dest =
|
|
55130
|
+
const dest = import_node_path36.default.join(stage, name);
|
|
54986
55131
|
if (entry.dir) {
|
|
54987
55132
|
await import_promises4.default.mkdir(dest, { recursive: true });
|
|
54988
55133
|
continue;
|
|
54989
55134
|
}
|
|
54990
|
-
await import_promises4.default.mkdir(
|
|
55135
|
+
await import_promises4.default.mkdir(import_node_path36.default.dirname(dest), { recursive: true });
|
|
54991
55136
|
const content = await entry.async("nodebuffer");
|
|
54992
55137
|
await import_promises4.default.writeFile(dest, content);
|
|
54993
55138
|
}
|
|
@@ -55017,7 +55162,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
55017
55162
|
".wasm": "application/wasm"
|
|
55018
55163
|
};
|
|
55019
55164
|
function shareUiAssetMime(filePath) {
|
|
55020
|
-
const ext =
|
|
55165
|
+
const ext = import_node_path37.default.extname(filePath).toLowerCase();
|
|
55021
55166
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
55022
55167
|
}
|
|
55023
55168
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -55116,7 +55261,7 @@ function isValidUploadFileName(fileName) {
|
|
|
55116
55261
|
if (fileName === "." || fileName === "..") return false;
|
|
55117
55262
|
if (fileName.startsWith(".")) return false;
|
|
55118
55263
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
55119
|
-
return fileName ===
|
|
55264
|
+
return fileName === import_node_path37.default.basename(fileName);
|
|
55120
55265
|
}
|
|
55121
55266
|
function createHttpRouter(deps) {
|
|
55122
55267
|
return async (req, res) => {
|
|
@@ -55204,7 +55349,7 @@ function createHttpRouter(deps) {
|
|
|
55204
55349
|
}
|
|
55205
55350
|
let buf;
|
|
55206
55351
|
try {
|
|
55207
|
-
buf = await
|
|
55352
|
+
buf = await import_node_fs33.default.promises.readFile(abs);
|
|
55208
55353
|
} catch {
|
|
55209
55354
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
55210
55355
|
return true;
|
|
@@ -55352,7 +55497,7 @@ function createHttpRouter(deps) {
|
|
|
55352
55497
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
55353
55498
|
return true;
|
|
55354
55499
|
}
|
|
55355
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
55500
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path37.default.basename(r.absPath)));
|
|
55356
55501
|
return true;
|
|
55357
55502
|
}
|
|
55358
55503
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -55411,9 +55556,9 @@ function createHttpRouter(deps) {
|
|
|
55411
55556
|
});
|
|
55412
55557
|
return true;
|
|
55413
55558
|
}
|
|
55414
|
-
const
|
|
55559
|
+
const baseDir = up.getAttachmentBaseDir(sessionId);
|
|
55415
55560
|
const scope = up.getSessionScope(sessionId);
|
|
55416
|
-
if (!
|
|
55561
|
+
if (!baseDir || !scope) {
|
|
55417
55562
|
sendUploadJson(404, { code: "NOT_FOUND", message: `session ${sessionId} not found` });
|
|
55418
55563
|
return true;
|
|
55419
55564
|
}
|
|
@@ -55435,7 +55580,7 @@ function createHttpRouter(deps) {
|
|
|
55435
55580
|
}
|
|
55436
55581
|
try {
|
|
55437
55582
|
const result = await writeUploadedAttachment({
|
|
55438
|
-
|
|
55583
|
+
baseDir,
|
|
55439
55584
|
sessionId,
|
|
55440
55585
|
scope,
|
|
55441
55586
|
fileName,
|
|
@@ -55473,7 +55618,7 @@ function createHttpRouter(deps) {
|
|
|
55473
55618
|
return true;
|
|
55474
55619
|
}
|
|
55475
55620
|
let absPath;
|
|
55476
|
-
if (
|
|
55621
|
+
if (import_node_path37.default.isAbsolute(pathParam)) {
|
|
55477
55622
|
absPath = pathParam;
|
|
55478
55623
|
} else if (deps.sessionStore) {
|
|
55479
55624
|
const file = deps.sessionStore.read(sid);
|
|
@@ -55481,7 +55626,7 @@ function createHttpRouter(deps) {
|
|
|
55481
55626
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
55482
55627
|
return true;
|
|
55483
55628
|
}
|
|
55484
|
-
absPath =
|
|
55629
|
+
absPath = import_node_path37.default.join(file.cwd, pathParam);
|
|
55485
55630
|
} else {
|
|
55486
55631
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
55487
55632
|
return true;
|
|
@@ -55568,7 +55713,7 @@ function withCtx(ctx, body) {
|
|
|
55568
55713
|
function streamFile(res, absPath, logger) {
|
|
55569
55714
|
let stat;
|
|
55570
55715
|
try {
|
|
55571
|
-
stat =
|
|
55716
|
+
stat = import_node_fs33.default.statSync(absPath);
|
|
55572
55717
|
} catch (err) {
|
|
55573
55718
|
const code = err?.code;
|
|
55574
55719
|
if (code === "ENOENT") {
|
|
@@ -55583,7 +55728,7 @@ function streamFile(res, absPath, logger) {
|
|
|
55583
55728
|
return;
|
|
55584
55729
|
}
|
|
55585
55730
|
const mime = lookupMime(absPath);
|
|
55586
|
-
const basename =
|
|
55731
|
+
const basename = import_node_path37.default.basename(absPath);
|
|
55587
55732
|
res.writeHead(200, {
|
|
55588
55733
|
"Content-Type": mime,
|
|
55589
55734
|
"Content-Length": String(stat.size),
|
|
@@ -55591,7 +55736,7 @@ function streamFile(res, absPath, logger) {
|
|
|
55591
55736
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
55592
55737
|
"X-Content-Type-Options": "nosniff"
|
|
55593
55738
|
});
|
|
55594
|
-
const stream =
|
|
55739
|
+
const stream = import_node_fs33.default.createReadStream(absPath);
|
|
55595
55740
|
stream.on("error", (err) => {
|
|
55596
55741
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
55597
55742
|
res.destroy();
|
|
@@ -55600,8 +55745,8 @@ function streamFile(res, absPath, logger) {
|
|
|
55600
55745
|
}
|
|
55601
55746
|
|
|
55602
55747
|
// src/attachment/gc.ts
|
|
55603
|
-
var
|
|
55604
|
-
var
|
|
55748
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
55749
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
55605
55750
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
55606
55751
|
function runAttachmentGc(args) {
|
|
55607
55752
|
const now = (args.now ?? Date.now)();
|
|
@@ -55610,66 +55755,75 @@ function runAttachmentGc(args) {
|
|
|
55610
55755
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
55611
55756
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
55612
55757
|
if (entry.stale) continue;
|
|
55613
|
-
if (
|
|
55758
|
+
if (import_node_path38.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
55614
55759
|
}
|
|
55615
55760
|
}
|
|
55761
|
+
const visited = /* @__PURE__ */ new Set();
|
|
55616
55762
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
55617
|
-
const
|
|
55763
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path38.default.join(
|
|
55618
55764
|
args.dataDir,
|
|
55619
55765
|
"sessions",
|
|
55620
55766
|
...scopeSubPath(scope).map(safeFileName),
|
|
55621
55767
|
safeFileName(sessionId)
|
|
55622
55768
|
);
|
|
55623
|
-
const
|
|
55624
|
-
|
|
55625
|
-
|
|
55626
|
-
|
|
55627
|
-
|
|
55628
|
-
|
|
55629
|
-
|
|
55630
|
-
|
|
55631
|
-
|
|
55632
|
-
for (const hashDir of hashDirs) {
|
|
55633
|
-
const hashDirAbs = import_node_path37.default.join(attRoot, hashDir);
|
|
55634
|
-
let files;
|
|
55769
|
+
const userWorkDir = args.getUserWorkDir?.(sessionId) ?? null;
|
|
55770
|
+
const roots = [legacyDir, ...userWorkDir ? [userWorkDir] : []].filter((r) => {
|
|
55771
|
+
if (visited.has(r)) return false;
|
|
55772
|
+
visited.add(r);
|
|
55773
|
+
return true;
|
|
55774
|
+
});
|
|
55775
|
+
for (const rootDir of roots) {
|
|
55776
|
+
const attRoot = import_node_path38.default.join(rootDir, ".attachments");
|
|
55777
|
+
let hashDirs;
|
|
55635
55778
|
try {
|
|
55636
|
-
|
|
55637
|
-
} catch {
|
|
55779
|
+
hashDirs = import_node_fs34.default.readdirSync(attRoot);
|
|
55780
|
+
} catch (err) {
|
|
55781
|
+
if (err.code === "ENOENT") continue;
|
|
55782
|
+
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
55638
55783
|
continue;
|
|
55639
55784
|
}
|
|
55640
|
-
for (const
|
|
55641
|
-
const
|
|
55642
|
-
let
|
|
55785
|
+
for (const hashDir of hashDirs) {
|
|
55786
|
+
const hashDirAbs = import_node_path38.default.join(attRoot, hashDir);
|
|
55787
|
+
let files;
|
|
55643
55788
|
try {
|
|
55644
|
-
|
|
55789
|
+
files = import_node_fs34.default.readdirSync(hashDirAbs);
|
|
55645
55790
|
} catch {
|
|
55646
55791
|
continue;
|
|
55647
55792
|
}
|
|
55648
|
-
|
|
55649
|
-
|
|
55650
|
-
|
|
55651
|
-
|
|
55793
|
+
for (const name of files) {
|
|
55794
|
+
const file = import_node_path38.default.join(hashDirAbs, name);
|
|
55795
|
+
let stat;
|
|
55796
|
+
try {
|
|
55797
|
+
stat = import_node_fs34.default.statSync(file);
|
|
55798
|
+
} catch {
|
|
55799
|
+
continue;
|
|
55800
|
+
}
|
|
55801
|
+
if (!stat.isFile()) continue;
|
|
55802
|
+
const age = now - stat.mtimeMs;
|
|
55803
|
+
if (age < ttlMs) continue;
|
|
55804
|
+
if (liveAbs.has(file)) continue;
|
|
55805
|
+
try {
|
|
55806
|
+
import_node_fs34.default.unlinkSync(file);
|
|
55807
|
+
} catch (err) {
|
|
55808
|
+
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
55809
|
+
}
|
|
55810
|
+
}
|
|
55652
55811
|
try {
|
|
55653
|
-
|
|
55654
|
-
} catch
|
|
55655
|
-
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
55812
|
+
if (import_node_fs34.default.readdirSync(hashDirAbs).length === 0) import_node_fs34.default.rmdirSync(hashDirAbs);
|
|
55813
|
+
} catch {
|
|
55656
55814
|
}
|
|
55657
55815
|
}
|
|
55658
55816
|
try {
|
|
55659
|
-
if (
|
|
55817
|
+
if (import_node_fs34.default.readdirSync(attRoot).length === 0) import_node_fs34.default.rmdirSync(attRoot);
|
|
55660
55818
|
} catch {
|
|
55661
55819
|
}
|
|
55662
55820
|
}
|
|
55663
|
-
try {
|
|
55664
|
-
if (import_node_fs33.default.readdirSync(attRoot).length === 0) import_node_fs33.default.rmdirSync(attRoot);
|
|
55665
|
-
} catch {
|
|
55666
|
-
}
|
|
55667
55821
|
}
|
|
55668
55822
|
}
|
|
55669
55823
|
|
|
55670
55824
|
// src/attachment/group.ts
|
|
55671
|
-
var
|
|
55672
|
-
var
|
|
55825
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
55826
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
55673
55827
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
55674
55828
|
init_protocol();
|
|
55675
55829
|
var GroupFileStore = class {
|
|
@@ -55681,11 +55835,11 @@ var GroupFileStore = class {
|
|
|
55681
55835
|
this.logger = opts.logger;
|
|
55682
55836
|
}
|
|
55683
55837
|
rootForScope(scope) {
|
|
55684
|
-
return
|
|
55838
|
+
return import_node_path39.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
55685
55839
|
}
|
|
55686
55840
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
55687
55841
|
filePath(scope, sessionId) {
|
|
55688
|
-
return
|
|
55842
|
+
return import_node_path39.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
55689
55843
|
}
|
|
55690
55844
|
cacheKey(scope, sessionId) {
|
|
55691
55845
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -55694,7 +55848,7 @@ var GroupFileStore = class {
|
|
|
55694
55848
|
readFile(scope, sessionId) {
|
|
55695
55849
|
const file = this.filePath(scope, sessionId);
|
|
55696
55850
|
try {
|
|
55697
|
-
const raw =
|
|
55851
|
+
const raw = import_node_fs35.default.readFileSync(file, "utf8");
|
|
55698
55852
|
const parsed = JSON.parse(raw);
|
|
55699
55853
|
if (!Array.isArray(parsed)) {
|
|
55700
55854
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -55720,10 +55874,10 @@ var GroupFileStore = class {
|
|
|
55720
55874
|
}
|
|
55721
55875
|
writeFile(scope, sessionId, entries) {
|
|
55722
55876
|
const file = this.filePath(scope, sessionId);
|
|
55723
|
-
|
|
55877
|
+
import_node_fs35.default.mkdirSync(import_node_path39.default.dirname(file), { recursive: true });
|
|
55724
55878
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
55725
|
-
|
|
55726
|
-
|
|
55879
|
+
import_node_fs35.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
55880
|
+
import_node_fs35.default.renameSync(tmp, file);
|
|
55727
55881
|
}
|
|
55728
55882
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
55729
55883
|
list(scope, sessionId) {
|
|
@@ -55809,10 +55963,10 @@ var GroupFileStore = class {
|
|
|
55809
55963
|
};
|
|
55810
55964
|
|
|
55811
55965
|
// src/discovery/state-file.ts
|
|
55812
|
-
var
|
|
55813
|
-
var
|
|
55966
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
55967
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
55814
55968
|
function defaultStateFilePath(dataDir) {
|
|
55815
|
-
return
|
|
55969
|
+
return import_node_path40.default.join(dataDir, "state.json");
|
|
55816
55970
|
}
|
|
55817
55971
|
function isPidAlive(pid) {
|
|
55818
55972
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -55834,7 +55988,7 @@ var StateFileManager = class {
|
|
|
55834
55988
|
}
|
|
55835
55989
|
read() {
|
|
55836
55990
|
try {
|
|
55837
|
-
const raw =
|
|
55991
|
+
const raw = import_node_fs36.default.readFileSync(this.file, "utf8");
|
|
55838
55992
|
const parsed = JSON.parse(raw);
|
|
55839
55993
|
return parsed;
|
|
55840
55994
|
} catch {
|
|
@@ -55848,20 +56002,20 @@ var StateFileManager = class {
|
|
|
55848
56002
|
return { status: "stale", existing };
|
|
55849
56003
|
}
|
|
55850
56004
|
write(state) {
|
|
55851
|
-
|
|
56005
|
+
import_node_fs36.default.mkdirSync(import_node_path40.default.dirname(this.file), { recursive: true });
|
|
55852
56006
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
55853
|
-
|
|
55854
|
-
|
|
56007
|
+
import_node_fs36.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
56008
|
+
import_node_fs36.default.renameSync(tmp, this.file);
|
|
55855
56009
|
if (process.platform !== "win32") {
|
|
55856
56010
|
try {
|
|
55857
|
-
|
|
56011
|
+
import_node_fs36.default.chmodSync(this.file, 384);
|
|
55858
56012
|
} catch {
|
|
55859
56013
|
}
|
|
55860
56014
|
}
|
|
55861
56015
|
}
|
|
55862
56016
|
delete() {
|
|
55863
56017
|
try {
|
|
55864
|
-
|
|
56018
|
+
import_node_fs36.default.unlinkSync(this.file);
|
|
55865
56019
|
} catch {
|
|
55866
56020
|
}
|
|
55867
56021
|
}
|
|
@@ -55875,14 +56029,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
55875
56029
|
}
|
|
55876
56030
|
|
|
55877
56031
|
// src/tunnel/tunnel-manager.ts
|
|
55878
|
-
var
|
|
55879
|
-
var
|
|
56032
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
56033
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
55880
56034
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
55881
56035
|
var import_node_child_process9 = require("child_process");
|
|
55882
56036
|
|
|
55883
56037
|
// src/tunnel/tunnel-store.ts
|
|
55884
|
-
var
|
|
55885
|
-
var
|
|
56038
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
56039
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
55886
56040
|
var TunnelStore = class {
|
|
55887
56041
|
constructor(filePath) {
|
|
55888
56042
|
this.filePath = filePath;
|
|
@@ -55890,7 +56044,7 @@ var TunnelStore = class {
|
|
|
55890
56044
|
filePath;
|
|
55891
56045
|
async get() {
|
|
55892
56046
|
try {
|
|
55893
|
-
const raw = await
|
|
56047
|
+
const raw = await import_node_fs37.default.promises.readFile(this.filePath, "utf8");
|
|
55894
56048
|
const obj = JSON.parse(raw);
|
|
55895
56049
|
if (!isPersistedTunnel(obj)) return null;
|
|
55896
56050
|
return obj;
|
|
@@ -55901,22 +56055,22 @@ var TunnelStore = class {
|
|
|
55901
56055
|
}
|
|
55902
56056
|
}
|
|
55903
56057
|
async set(v2) {
|
|
55904
|
-
const dir =
|
|
55905
|
-
await
|
|
56058
|
+
const dir = import_node_path41.default.dirname(this.filePath);
|
|
56059
|
+
await import_node_fs37.default.promises.mkdir(dir, { recursive: true });
|
|
55906
56060
|
const data = JSON.stringify(v2, null, 2);
|
|
55907
56061
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
55908
|
-
await
|
|
56062
|
+
await import_node_fs37.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
55909
56063
|
if (process.platform !== "win32") {
|
|
55910
56064
|
try {
|
|
55911
|
-
await
|
|
56065
|
+
await import_node_fs37.default.promises.chmod(tmp, 384);
|
|
55912
56066
|
} catch {
|
|
55913
56067
|
}
|
|
55914
56068
|
}
|
|
55915
|
-
await
|
|
56069
|
+
await import_node_fs37.default.promises.rename(tmp, this.filePath);
|
|
55916
56070
|
}
|
|
55917
56071
|
async clear() {
|
|
55918
56072
|
try {
|
|
55919
|
-
await
|
|
56073
|
+
await import_node_fs37.default.promises.unlink(this.filePath);
|
|
55920
56074
|
} catch (err) {
|
|
55921
56075
|
const code = err?.code;
|
|
55922
56076
|
if (code !== "ENOENT") throw err;
|
|
@@ -56011,9 +56165,9 @@ function escape(v2) {
|
|
|
56011
56165
|
}
|
|
56012
56166
|
|
|
56013
56167
|
// src/tunnel/frpc-binary.ts
|
|
56014
|
-
var
|
|
56168
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
56015
56169
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
56016
|
-
var
|
|
56170
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
56017
56171
|
var import_node_child_process7 = require("child_process");
|
|
56018
56172
|
var import_node_stream3 = require("stream");
|
|
56019
56173
|
var import_promises5 = require("stream/promises");
|
|
@@ -56045,20 +56199,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
56045
56199
|
}
|
|
56046
56200
|
async function ensureFrpcBinary(opts) {
|
|
56047
56201
|
if (opts.override) {
|
|
56048
|
-
if (!
|
|
56202
|
+
if (!import_node_fs38.default.existsSync(opts.override)) {
|
|
56049
56203
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
56050
56204
|
}
|
|
56051
56205
|
return opts.override;
|
|
56052
56206
|
}
|
|
56053
56207
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
56054
56208
|
const platform = opts.platform ?? detectPlatform();
|
|
56055
|
-
const binDir =
|
|
56056
|
-
|
|
56209
|
+
const binDir = import_node_path42.default.join(opts.dataDir, "bin");
|
|
56210
|
+
import_node_fs38.default.mkdirSync(binDir, { recursive: true });
|
|
56057
56211
|
cleanupStaleArtifacts(binDir);
|
|
56058
|
-
const stableBin =
|
|
56059
|
-
if (
|
|
56212
|
+
const stableBin = import_node_path42.default.join(binDir, "frpc");
|
|
56213
|
+
if (import_node_fs38.default.existsSync(stableBin)) return stableBin;
|
|
56060
56214
|
const partialBin = `${stableBin}.partial`;
|
|
56061
|
-
const tarballPath =
|
|
56215
|
+
const tarballPath = import_node_path42.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
56062
56216
|
try {
|
|
56063
56217
|
const url = frpcDownloadUrl(version2, platform);
|
|
56064
56218
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -56067,8 +56221,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
56067
56221
|
} else {
|
|
56068
56222
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
56069
56223
|
}
|
|
56070
|
-
|
|
56071
|
-
|
|
56224
|
+
import_node_fs38.default.chmodSync(partialBin, 493);
|
|
56225
|
+
import_node_fs38.default.renameSync(partialBin, stableBin);
|
|
56072
56226
|
} finally {
|
|
56073
56227
|
safeUnlink(tarballPath);
|
|
56074
56228
|
safeUnlink(partialBin);
|
|
@@ -56078,15 +56232,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
56078
56232
|
function cleanupStaleArtifacts(binDir) {
|
|
56079
56233
|
let entries;
|
|
56080
56234
|
try {
|
|
56081
|
-
entries =
|
|
56235
|
+
entries = import_node_fs38.default.readdirSync(binDir);
|
|
56082
56236
|
} catch {
|
|
56083
56237
|
return;
|
|
56084
56238
|
}
|
|
56085
56239
|
for (const name of entries) {
|
|
56086
56240
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
56087
|
-
const full =
|
|
56241
|
+
const full = import_node_path42.default.join(binDir, name);
|
|
56088
56242
|
try {
|
|
56089
|
-
|
|
56243
|
+
import_node_fs38.default.rmSync(full, { recursive: true, force: true });
|
|
56090
56244
|
} catch {
|
|
56091
56245
|
}
|
|
56092
56246
|
}
|
|
@@ -56094,7 +56248,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
56094
56248
|
}
|
|
56095
56249
|
function safeUnlink(p2) {
|
|
56096
56250
|
try {
|
|
56097
|
-
|
|
56251
|
+
import_node_fs38.default.unlinkSync(p2);
|
|
56098
56252
|
} catch {
|
|
56099
56253
|
}
|
|
56100
56254
|
}
|
|
@@ -56105,13 +56259,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
56105
56259
|
if (!res.ok || !res.body) {
|
|
56106
56260
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
56107
56261
|
}
|
|
56108
|
-
const out =
|
|
56262
|
+
const out = import_node_fs38.default.createWriteStream(dest);
|
|
56109
56263
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
56110
56264
|
await (0, import_promises5.pipeline)(nodeStream, out);
|
|
56111
56265
|
}
|
|
56112
56266
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
56113
|
-
const work =
|
|
56114
|
-
|
|
56267
|
+
const work = import_node_path42.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
56268
|
+
import_node_fs38.default.mkdirSync(work, { recursive: true });
|
|
56115
56269
|
try {
|
|
56116
56270
|
await new Promise((resolve6, reject) => {
|
|
56117
56271
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -56119,32 +56273,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
56119
56273
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
56120
56274
|
});
|
|
56121
56275
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
56122
|
-
const src =
|
|
56123
|
-
if (!
|
|
56276
|
+
const src = import_node_path42.default.join(work, dirName, "frpc");
|
|
56277
|
+
if (!import_node_fs38.default.existsSync(src)) {
|
|
56124
56278
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
56125
56279
|
}
|
|
56126
|
-
|
|
56280
|
+
import_node_fs38.default.copyFileSync(src, destBin);
|
|
56127
56281
|
} finally {
|
|
56128
|
-
|
|
56282
|
+
import_node_fs38.default.rmSync(work, { recursive: true, force: true });
|
|
56129
56283
|
}
|
|
56130
56284
|
}
|
|
56131
56285
|
|
|
56132
56286
|
// src/tunnel/frpc-process.ts
|
|
56133
|
-
var
|
|
56134
|
-
var
|
|
56287
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
56288
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
56135
56289
|
var import_node_child_process8 = require("child_process");
|
|
56136
56290
|
function frpcPidFilePath(dataDir) {
|
|
56137
|
-
return
|
|
56291
|
+
return import_node_path43.default.join(dataDir, "frpc.pid");
|
|
56138
56292
|
}
|
|
56139
56293
|
function writeFrpcPid(dataDir, pid) {
|
|
56140
56294
|
try {
|
|
56141
|
-
|
|
56295
|
+
import_node_fs39.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
56142
56296
|
} catch {
|
|
56143
56297
|
}
|
|
56144
56298
|
}
|
|
56145
56299
|
function clearFrpcPid(dataDir) {
|
|
56146
56300
|
try {
|
|
56147
|
-
|
|
56301
|
+
import_node_fs39.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
56148
56302
|
} catch {
|
|
56149
56303
|
}
|
|
56150
56304
|
}
|
|
@@ -56160,7 +56314,7 @@ function defaultIsPidAlive(pid) {
|
|
|
56160
56314
|
}
|
|
56161
56315
|
function defaultReadPidFile(file) {
|
|
56162
56316
|
try {
|
|
56163
|
-
return
|
|
56317
|
+
return import_node_fs39.default.readFileSync(file, "utf8");
|
|
56164
56318
|
} catch {
|
|
56165
56319
|
return null;
|
|
56166
56320
|
}
|
|
@@ -56176,7 +56330,7 @@ function defaultSleep2(ms) {
|
|
|
56176
56330
|
}
|
|
56177
56331
|
async function killStaleFrpc(deps) {
|
|
56178
56332
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
56179
|
-
const tomlPath =
|
|
56333
|
+
const tomlPath = import_node_path43.default.join(deps.dataDir, "frpc.toml");
|
|
56180
56334
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
56181
56335
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
56182
56336
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -56200,7 +56354,7 @@ async function killStaleFrpc(deps) {
|
|
|
56200
56354
|
}
|
|
56201
56355
|
if (victims.size === 0) {
|
|
56202
56356
|
try {
|
|
56203
|
-
|
|
56357
|
+
import_node_fs39.default.unlinkSync(pidFile);
|
|
56204
56358
|
} catch {
|
|
56205
56359
|
}
|
|
56206
56360
|
return;
|
|
@@ -56211,7 +56365,7 @@ async function killStaleFrpc(deps) {
|
|
|
56211
56365
|
}
|
|
56212
56366
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
56213
56367
|
try {
|
|
56214
|
-
|
|
56368
|
+
import_node_fs39.default.unlinkSync(pidFile);
|
|
56215
56369
|
} catch {
|
|
56216
56370
|
}
|
|
56217
56371
|
}
|
|
@@ -56248,7 +56402,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
56248
56402
|
var TunnelManager = class {
|
|
56249
56403
|
constructor(deps) {
|
|
56250
56404
|
this.deps = deps;
|
|
56251
|
-
this.store = deps.store ?? new TunnelStore(
|
|
56405
|
+
this.store = deps.store ?? new TunnelStore(import_node_path44.default.join(deps.dataDir, "tunnel.json"));
|
|
56252
56406
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
56253
56407
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
56254
56408
|
}
|
|
@@ -56375,7 +56529,7 @@ var TunnelManager = class {
|
|
|
56375
56529
|
dataDir: this.deps.dataDir,
|
|
56376
56530
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
56377
56531
|
});
|
|
56378
|
-
const tomlPath =
|
|
56532
|
+
const tomlPath = import_node_path44.default.join(this.deps.dataDir, "frpc.toml");
|
|
56379
56533
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
|
|
56380
56534
|
const toml = buildFrpcToml({
|
|
56381
56535
|
serverAddr: t.frpsHost,
|
|
@@ -56386,14 +56540,14 @@ var TunnelManager = class {
|
|
|
56386
56540
|
localPort,
|
|
56387
56541
|
logLevel: "info"
|
|
56388
56542
|
});
|
|
56389
|
-
await
|
|
56543
|
+
await import_node_fs40.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
56390
56544
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
56391
56545
|
stdio: ["ignore", "pipe", "pipe"]
|
|
56392
56546
|
});
|
|
56393
|
-
const logDir =
|
|
56394
|
-
|
|
56395
|
-
const logFilePath =
|
|
56396
|
-
const logStream =
|
|
56547
|
+
const logDir = import_node_path44.default.join(this.deps.dataDir, "log");
|
|
56548
|
+
import_node_fs40.default.mkdirSync(logDir, { recursive: true });
|
|
56549
|
+
const logFilePath = import_node_path44.default.join(logDir, "frpc.log");
|
|
56550
|
+
const logStream = import_node_fs40.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
56397
56551
|
logStream.on("error", () => {
|
|
56398
56552
|
});
|
|
56399
56553
|
const tee = (chunk) => {
|
|
@@ -56476,27 +56630,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
56476
56630
|
|
|
56477
56631
|
// src/tunnel/device-key.ts
|
|
56478
56632
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
56479
|
-
var
|
|
56633
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
56480
56634
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
56481
56635
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
56482
56636
|
function deriveStableDeviceKey(opts = {}) {
|
|
56483
56637
|
const hostname = opts.hostname ?? import_node_os14.default.hostname();
|
|
56484
56638
|
const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
|
|
56485
56639
|
const home = opts.home ?? import_node_os14.default.homedir();
|
|
56486
|
-
const defaultDataDir =
|
|
56487
|
-
const normalizedDataDir = opts.dataDir ?
|
|
56640
|
+
const defaultDataDir = import_node_path45.default.resolve(import_node_path45.default.join(home, ".clawd"));
|
|
56641
|
+
const normalizedDataDir = opts.dataDir ? import_node_path45.default.resolve(opts.dataDir) : null;
|
|
56488
56642
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
56489
56643
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
56490
56644
|
return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
56491
56645
|
}
|
|
56492
56646
|
|
|
56493
56647
|
// src/auth-store.ts
|
|
56494
|
-
var
|
|
56495
|
-
var
|
|
56648
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
56649
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
56496
56650
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
56497
56651
|
var AUTH_FILE_NAME = "auth.json";
|
|
56498
56652
|
function authFilePath(dataDir) {
|
|
56499
|
-
return
|
|
56653
|
+
return import_node_path46.default.join(dataDir, AUTH_FILE_NAME);
|
|
56500
56654
|
}
|
|
56501
56655
|
function loadOrCreateAuthFile(opts) {
|
|
56502
56656
|
const file = authFilePath(opts.dataDir);
|
|
@@ -56528,7 +56682,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
56528
56682
|
}
|
|
56529
56683
|
function readAuthFile(file) {
|
|
56530
56684
|
try {
|
|
56531
|
-
const raw =
|
|
56685
|
+
const raw = import_node_fs41.default.readFileSync(file, "utf8");
|
|
56532
56686
|
const parsed = JSON.parse(raw);
|
|
56533
56687
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
56534
56688
|
return null;
|
|
@@ -56548,25 +56702,25 @@ function readAuthFile(file) {
|
|
|
56548
56702
|
}
|
|
56549
56703
|
}
|
|
56550
56704
|
function writeAuthFile(file, content) {
|
|
56551
|
-
|
|
56552
|
-
|
|
56705
|
+
import_node_fs41.default.mkdirSync(import_node_path46.default.dirname(file), { recursive: true });
|
|
56706
|
+
import_node_fs41.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
56553
56707
|
try {
|
|
56554
|
-
|
|
56708
|
+
import_node_fs41.default.chmodSync(file, 384);
|
|
56555
56709
|
} catch {
|
|
56556
56710
|
}
|
|
56557
56711
|
}
|
|
56558
56712
|
|
|
56559
56713
|
// src/owner-profile.ts
|
|
56560
|
-
var
|
|
56714
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
56561
56715
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
56562
|
-
var
|
|
56716
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
56563
56717
|
var PROFILE_FILENAME = "profile.json";
|
|
56564
56718
|
function loadOwnerDisplayName(dataDir) {
|
|
56565
56719
|
const fallback = import_node_os15.default.userInfo().username;
|
|
56566
|
-
const profilePath =
|
|
56720
|
+
const profilePath = import_node_path47.default.join(dataDir, PROFILE_FILENAME);
|
|
56567
56721
|
let raw;
|
|
56568
56722
|
try {
|
|
56569
|
-
raw =
|
|
56723
|
+
raw = import_node_fs42.default.readFileSync(profilePath, "utf8");
|
|
56570
56724
|
} catch {
|
|
56571
56725
|
return fallback;
|
|
56572
56726
|
}
|
|
@@ -56589,18 +56743,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
56589
56743
|
}
|
|
56590
56744
|
|
|
56591
56745
|
// src/feishu-auth/owner-identity-store.ts
|
|
56592
|
-
var
|
|
56593
|
-
var
|
|
56746
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
56747
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
56594
56748
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
56595
56749
|
var OwnerIdentityStore = class {
|
|
56596
56750
|
file;
|
|
56597
56751
|
constructor(dataDir) {
|
|
56598
|
-
this.file =
|
|
56752
|
+
this.file = import_node_path48.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
56599
56753
|
}
|
|
56600
56754
|
read() {
|
|
56601
56755
|
let raw;
|
|
56602
56756
|
try {
|
|
56603
|
-
raw =
|
|
56757
|
+
raw = import_node_fs43.default.readFileSync(this.file, "utf8");
|
|
56604
56758
|
} catch {
|
|
56605
56759
|
return null;
|
|
56606
56760
|
}
|
|
@@ -56628,16 +56782,16 @@ var OwnerIdentityStore = class {
|
|
|
56628
56782
|
};
|
|
56629
56783
|
}
|
|
56630
56784
|
write(record) {
|
|
56631
|
-
|
|
56632
|
-
|
|
56785
|
+
import_node_fs43.default.mkdirSync(import_node_path48.default.dirname(this.file), { recursive: true });
|
|
56786
|
+
import_node_fs43.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
56633
56787
|
try {
|
|
56634
|
-
|
|
56788
|
+
import_node_fs43.default.chmodSync(this.file, 384);
|
|
56635
56789
|
} catch {
|
|
56636
56790
|
}
|
|
56637
56791
|
}
|
|
56638
56792
|
clear() {
|
|
56639
56793
|
try {
|
|
56640
|
-
|
|
56794
|
+
import_node_fs43.default.unlinkSync(this.file);
|
|
56641
56795
|
} catch (err) {
|
|
56642
56796
|
const code = err?.code;
|
|
56643
56797
|
if (code !== "ENOENT") throw err;
|
|
@@ -56774,9 +56928,9 @@ var CentralClientError = class extends Error {
|
|
|
56774
56928
|
code;
|
|
56775
56929
|
cause;
|
|
56776
56930
|
};
|
|
56777
|
-
async function centralRequest(opts,
|
|
56931
|
+
async function centralRequest(opts, path79, init) {
|
|
56778
56932
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
56779
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
56933
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path79}`;
|
|
56780
56934
|
const ctrl = new AbortController();
|
|
56781
56935
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
56782
56936
|
let res;
|
|
@@ -56970,8 +57124,8 @@ function verifyConnectToken(args) {
|
|
|
56970
57124
|
}
|
|
56971
57125
|
|
|
56972
57126
|
// src/feishu-auth/server-key.ts
|
|
56973
|
-
var
|
|
56974
|
-
var
|
|
57127
|
+
var fs53 = __toESM(require("fs"), 1);
|
|
57128
|
+
var path57 = __toESM(require("path"), 1);
|
|
56975
57129
|
var FILE_NAME2 = "server-signing-key.json";
|
|
56976
57130
|
var ServerKeyStore = class {
|
|
56977
57131
|
constructor(dataDir) {
|
|
@@ -56979,12 +57133,12 @@ var ServerKeyStore = class {
|
|
|
56979
57133
|
}
|
|
56980
57134
|
dataDir;
|
|
56981
57135
|
filePath() {
|
|
56982
|
-
return
|
|
57136
|
+
return path57.join(this.dataDir, FILE_NAME2);
|
|
56983
57137
|
}
|
|
56984
57138
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
56985
57139
|
read() {
|
|
56986
57140
|
try {
|
|
56987
|
-
const raw =
|
|
57141
|
+
const raw = fs53.readFileSync(this.filePath(), "utf8");
|
|
56988
57142
|
const parsed = JSON.parse(raw);
|
|
56989
57143
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
56990
57144
|
return parsed.publicKeyPem;
|
|
@@ -56999,12 +57153,12 @@ var ServerKeyStore = class {
|
|
|
56999
57153
|
publicKeyPem,
|
|
57000
57154
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
57001
57155
|
};
|
|
57002
|
-
|
|
57003
|
-
|
|
57156
|
+
fs53.mkdirSync(this.dataDir, { recursive: true });
|
|
57157
|
+
fs53.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
57004
57158
|
}
|
|
57005
57159
|
clear() {
|
|
57006
57160
|
try {
|
|
57007
|
-
|
|
57161
|
+
fs53.unlinkSync(this.filePath());
|
|
57008
57162
|
} catch {
|
|
57009
57163
|
}
|
|
57010
57164
|
}
|
|
@@ -57017,12 +57171,12 @@ init_protocol();
|
|
|
57017
57171
|
init_protocol();
|
|
57018
57172
|
|
|
57019
57173
|
// src/session/fork.ts
|
|
57020
|
-
var
|
|
57174
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
57021
57175
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
57022
|
-
var
|
|
57176
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
57023
57177
|
init_claude_history();
|
|
57024
57178
|
function readJsonlEntries(file) {
|
|
57025
|
-
const raw =
|
|
57179
|
+
const raw = import_node_fs44.default.readFileSync(file, "utf8");
|
|
57026
57180
|
const out = [];
|
|
57027
57181
|
for (const line of raw.split("\n")) {
|
|
57028
57182
|
const t = line.trim();
|
|
@@ -57035,19 +57189,19 @@ function readJsonlEntries(file) {
|
|
|
57035
57189
|
return out;
|
|
57036
57190
|
}
|
|
57037
57191
|
function forkSession(input) {
|
|
57038
|
-
const baseDir = input.baseDir ??
|
|
57039
|
-
let projectDir =
|
|
57040
|
-
let sourceFile =
|
|
57041
|
-
if (!
|
|
57192
|
+
const baseDir = input.baseDir ?? import_node_path49.default.join(import_node_os16.default.homedir(), ".claude");
|
|
57193
|
+
let projectDir = import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
57194
|
+
let sourceFile = import_node_path49.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
57195
|
+
if (!import_node_fs44.default.existsSync(sourceFile)) {
|
|
57042
57196
|
const found = findTranscriptByToolSessionId(
|
|
57043
|
-
|
|
57197
|
+
import_node_path49.default.join(baseDir, "projects"),
|
|
57044
57198
|
input.toolSessionId
|
|
57045
57199
|
);
|
|
57046
57200
|
if (!found) {
|
|
57047
57201
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
57048
57202
|
}
|
|
57049
57203
|
sourceFile = found;
|
|
57050
|
-
projectDir =
|
|
57204
|
+
projectDir = import_node_path49.default.dirname(found);
|
|
57051
57205
|
}
|
|
57052
57206
|
const entries = readJsonlEntries(sourceFile);
|
|
57053
57207
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -57076,10 +57230,10 @@ function forkSession(input) {
|
|
|
57076
57230
|
}
|
|
57077
57231
|
forkedLines.push(JSON.stringify(forked));
|
|
57078
57232
|
}
|
|
57079
|
-
const outDir = input.targetCwd ?
|
|
57080
|
-
const forkedFilePath =
|
|
57081
|
-
|
|
57082
|
-
|
|
57233
|
+
const outDir = input.targetCwd ? import_node_path49.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
57234
|
+
const forkedFilePath = import_node_path49.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
57235
|
+
import_node_fs44.default.mkdirSync(outDir, { recursive: true });
|
|
57236
|
+
import_node_fs44.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
57083
57237
|
return { forkedToolSessionId, forkedFilePath };
|
|
57084
57238
|
}
|
|
57085
57239
|
|
|
@@ -57538,7 +57692,7 @@ function buildPermissionHandlers(deps) {
|
|
|
57538
57692
|
}
|
|
57539
57693
|
|
|
57540
57694
|
// src/handlers/history.ts
|
|
57541
|
-
var
|
|
57695
|
+
var path60 = __toESM(require("path"), 1);
|
|
57542
57696
|
init_protocol();
|
|
57543
57697
|
|
|
57544
57698
|
// src/session/recent-dirs.ts
|
|
@@ -57556,7 +57710,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
57556
57710
|
}
|
|
57557
57711
|
|
|
57558
57712
|
// src/permission/persona-paths.ts
|
|
57559
|
-
var
|
|
57713
|
+
var path59 = __toESM(require("path"), 1);
|
|
57560
57714
|
function getAllowedPersonaIds(grants, action) {
|
|
57561
57715
|
const ids = /* @__PURE__ */ new Set();
|
|
57562
57716
|
for (const g2 of grants) {
|
|
@@ -57569,42 +57723,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
57569
57723
|
return ids;
|
|
57570
57724
|
}
|
|
57571
57725
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
57572
|
-
const target =
|
|
57726
|
+
const target = path59.resolve(absPath);
|
|
57573
57727
|
if (userWorkDir) {
|
|
57574
|
-
const u =
|
|
57575
|
-
const usep = u.endsWith(
|
|
57728
|
+
const u = path59.resolve(userWorkDir);
|
|
57729
|
+
const usep = u.endsWith(path59.sep) ? "" : path59.sep;
|
|
57576
57730
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
57577
57731
|
}
|
|
57578
|
-
const root =
|
|
57579
|
-
const sep3 = root.endsWith(
|
|
57732
|
+
const root = path59.resolve(personaRoot);
|
|
57733
|
+
const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
|
|
57580
57734
|
if (!target.startsWith(root + sep3)) return false;
|
|
57581
|
-
const rel =
|
|
57735
|
+
const rel = path59.relative(root, target);
|
|
57582
57736
|
if (!rel || rel.startsWith("..")) return false;
|
|
57583
|
-
const personaId2 = rel.split(
|
|
57737
|
+
const personaId2 = rel.split(path59.sep)[0];
|
|
57584
57738
|
if (!personaId2) return false;
|
|
57585
57739
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
57586
57740
|
if (allowed === "*") return true;
|
|
57587
57741
|
return allowed.has(personaId2);
|
|
57588
57742
|
}
|
|
57589
57743
|
function personaIdFromPath(absPath, personaRoot) {
|
|
57590
|
-
const root =
|
|
57591
|
-
const target =
|
|
57592
|
-
const sep3 = root.endsWith(
|
|
57744
|
+
const root = path59.resolve(personaRoot);
|
|
57745
|
+
const target = path59.resolve(absPath);
|
|
57746
|
+
const sep3 = root.endsWith(path59.sep) ? "" : path59.sep;
|
|
57593
57747
|
if (!target.startsWith(root + sep3)) return null;
|
|
57594
|
-
const rel =
|
|
57748
|
+
const rel = path59.relative(root, target);
|
|
57595
57749
|
if (!rel || rel.startsWith("..")) return null;
|
|
57596
|
-
const id = rel.split(
|
|
57750
|
+
const id = rel.split(path59.sep)[0];
|
|
57597
57751
|
return id || null;
|
|
57598
57752
|
}
|
|
57599
57753
|
function isPathWithin(dir, absPath) {
|
|
57600
|
-
const d =
|
|
57601
|
-
const t =
|
|
57602
|
-
const sep3 = d.endsWith(
|
|
57754
|
+
const d = path59.resolve(dir);
|
|
57755
|
+
const t = path59.resolve(absPath);
|
|
57756
|
+
const sep3 = d.endsWith(path59.sep) ? "" : path59.sep;
|
|
57603
57757
|
return t === d || t.startsWith(d + sep3);
|
|
57604
57758
|
}
|
|
57605
57759
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
57606
57760
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
57607
|
-
return personaIdFromPath(
|
|
57761
|
+
return personaIdFromPath(path59.resolve(absPath), personaRoot) === personaId2;
|
|
57608
57762
|
}
|
|
57609
57763
|
|
|
57610
57764
|
// src/handlers/history.ts
|
|
@@ -57656,7 +57810,7 @@ function buildHistoryHandlers(deps) {
|
|
|
57656
57810
|
if (!pid) return false;
|
|
57657
57811
|
return isGuestPathAllowed(
|
|
57658
57812
|
ctx.grants,
|
|
57659
|
-
|
|
57813
|
+
path60.join(personaRoot, pid),
|
|
57660
57814
|
personaRoot,
|
|
57661
57815
|
"read",
|
|
57662
57816
|
userWorkDir
|
|
@@ -57668,7 +57822,7 @@ function buildHistoryHandlers(deps) {
|
|
|
57668
57822
|
};
|
|
57669
57823
|
const list = async (frame, _client, ctx) => {
|
|
57670
57824
|
const args = HistoryListArgs.parse(frame);
|
|
57671
|
-
assertGuestPath(ctx,
|
|
57825
|
+
assertGuestPath(ctx, path60.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
57672
57826
|
const sessions = await history.listSessions(args);
|
|
57673
57827
|
return { response: { type: "history:list", sessions } };
|
|
57674
57828
|
};
|
|
@@ -57712,14 +57866,14 @@ function buildHistoryHandlers(deps) {
|
|
|
57712
57866
|
};
|
|
57713
57867
|
const subagents = async (frame, _client, ctx) => {
|
|
57714
57868
|
const args = HistorySubagentsArgs.parse(frame);
|
|
57715
|
-
assertGuestPath(ctx,
|
|
57869
|
+
assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
57716
57870
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
57717
57871
|
const subs = await history.listSubagents(args);
|
|
57718
57872
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
57719
57873
|
};
|
|
57720
57874
|
const subagentRead = async (frame, _client, ctx) => {
|
|
57721
57875
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
57722
|
-
assertGuestPath(ctx,
|
|
57876
|
+
assertGuestPath(ctx, path60.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
57723
57877
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
57724
57878
|
const res = await history.readSubagent(args);
|
|
57725
57879
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -57729,7 +57883,7 @@ function buildHistoryHandlers(deps) {
|
|
|
57729
57883
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
57730
57884
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
57731
57885
|
const filtered = dirs.filter(
|
|
57732
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
57886
|
+
(d) => isGuestPathAllowed(ctx.grants, path60.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
57733
57887
|
);
|
|
57734
57888
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
57735
57889
|
}
|
|
@@ -57746,7 +57900,7 @@ function buildHistoryHandlers(deps) {
|
|
|
57746
57900
|
}
|
|
57747
57901
|
|
|
57748
57902
|
// src/handlers/workspace.ts
|
|
57749
|
-
var
|
|
57903
|
+
var path61 = __toESM(require("path"), 1);
|
|
57750
57904
|
var os16 = __toESM(require("os"), 1);
|
|
57751
57905
|
init_protocol();
|
|
57752
57906
|
init_protocol();
|
|
@@ -57788,22 +57942,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
57788
57942
|
const args = WorkspaceListArgs.parse(frame);
|
|
57789
57943
|
const isGuest = ctx?.principal.kind === "guest";
|
|
57790
57944
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
|
|
57791
|
-
const resolvedCwd =
|
|
57792
|
-
const target = args.path ?
|
|
57945
|
+
const resolvedCwd = path61.resolve(args.cwd ?? fallbackCwd);
|
|
57946
|
+
const target = args.path ? path61.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
57793
57947
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
57794
57948
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
57795
57949
|
return { response: { type: "workspace:list", ...res } };
|
|
57796
57950
|
};
|
|
57797
57951
|
const read = async (frame, _client, ctx) => {
|
|
57798
57952
|
const args = WorkspaceReadArgs.parse(frame);
|
|
57799
|
-
const target =
|
|
57953
|
+
const target = path61.isAbsolute(args.path) ? path61.resolve(args.path) : path61.resolve(args.cwd, args.path);
|
|
57800
57954
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
57801
57955
|
const res = workspace.read(args);
|
|
57802
57956
|
return { response: { type: "workspace:read", ...res } };
|
|
57803
57957
|
};
|
|
57804
57958
|
const skillsList = async (frame, _client, ctx) => {
|
|
57805
57959
|
const args = SkillsListArgs.parse(frame);
|
|
57806
|
-
const cwdAbs =
|
|
57960
|
+
const cwdAbs = path61.resolve(args.cwd);
|
|
57807
57961
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
57808
57962
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
57809
57963
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -57815,7 +57969,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
57815
57969
|
};
|
|
57816
57970
|
const agentsList = async (frame, _client, ctx) => {
|
|
57817
57971
|
const args = AgentsListArgs.parse(frame);
|
|
57818
|
-
const cwdAbs =
|
|
57972
|
+
const cwdAbs = path61.resolve(args.cwd);
|
|
57819
57973
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
57820
57974
|
if (args.tool === "codex") {
|
|
57821
57975
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -57837,20 +57991,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
57837
57991
|
}
|
|
57838
57992
|
|
|
57839
57993
|
// src/handlers/git.ts
|
|
57840
|
-
var
|
|
57994
|
+
var path63 = __toESM(require("path"), 1);
|
|
57841
57995
|
init_protocol();
|
|
57842
57996
|
init_protocol();
|
|
57843
57997
|
|
|
57844
57998
|
// src/workspace/git.ts
|
|
57845
57999
|
var import_node_child_process10 = require("child_process");
|
|
57846
|
-
var
|
|
57847
|
-
var
|
|
58000
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
58001
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
57848
58002
|
var import_node_util = require("util");
|
|
57849
58003
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
57850
58004
|
function normalizePath(p2) {
|
|
57851
|
-
const resolved =
|
|
58005
|
+
const resolved = import_node_path50.default.resolve(p2);
|
|
57852
58006
|
try {
|
|
57853
|
-
return
|
|
58007
|
+
return import_node_fs45.default.realpathSync(resolved);
|
|
57854
58008
|
} catch {
|
|
57855
58009
|
return resolved;
|
|
57856
58010
|
}
|
|
@@ -57924,7 +58078,7 @@ async function listGitBranches(cwd) {
|
|
|
57924
58078
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
57925
58079
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
57926
58080
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
57927
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
58081
|
+
if (!isGuestPathAllowed(ctx.grants, path63.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
57928
58082
|
throw new ClawdError(
|
|
57929
58083
|
ERROR_CODES.UNAUTHORIZED,
|
|
57930
58084
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -58789,21 +58943,21 @@ function computeMethodAccess(args) {
|
|
|
58789
58943
|
}
|
|
58790
58944
|
|
|
58791
58945
|
// src/version.ts
|
|
58792
|
-
var version = "0.2.
|
|
58946
|
+
var version = "0.2.294".length > 0 ? "0.2.294" : "dev";
|
|
58793
58947
|
|
|
58794
58948
|
// src/cli-probe/probe.ts
|
|
58795
|
-
var
|
|
58796
|
-
var
|
|
58949
|
+
var fs56 = __toESM(require("fs"), 1);
|
|
58950
|
+
var path64 = __toESM(require("path"), 1);
|
|
58797
58951
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
58798
58952
|
var BIN_NAME = "clawd";
|
|
58799
58953
|
var MAX_PARENT_HOPS = 5;
|
|
58800
58954
|
function probeGlobalCli(pathEnv) {
|
|
58801
58955
|
if (!pathEnv) return null;
|
|
58802
|
-
for (const dir of pathEnv.split(
|
|
58956
|
+
for (const dir of pathEnv.split(path64.delimiter)) {
|
|
58803
58957
|
if (!dir) continue;
|
|
58804
58958
|
let real;
|
|
58805
58959
|
try {
|
|
58806
|
-
real =
|
|
58960
|
+
real = fs56.realpathSync(path64.join(dir, BIN_NAME));
|
|
58807
58961
|
} catch {
|
|
58808
58962
|
continue;
|
|
58809
58963
|
}
|
|
@@ -58813,15 +58967,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
58813
58967
|
return null;
|
|
58814
58968
|
}
|
|
58815
58969
|
function readOwnPackageVersion(entryPath) {
|
|
58816
|
-
let dir =
|
|
58970
|
+
let dir = path64.dirname(entryPath);
|
|
58817
58971
|
for (let i = 0; i < MAX_PARENT_HOPS; i++) {
|
|
58818
58972
|
try {
|
|
58819
|
-
const raw =
|
|
58973
|
+
const raw = fs56.readFileSync(path64.join(dir, "package.json"), "utf8");
|
|
58820
58974
|
const pkg = JSON.parse(raw);
|
|
58821
58975
|
if (pkg.name !== PKG_NAME) return null;
|
|
58822
58976
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
58823
58977
|
} catch {
|
|
58824
|
-
const parent =
|
|
58978
|
+
const parent = path64.dirname(dir);
|
|
58825
58979
|
if (parent === dir) return null;
|
|
58826
58980
|
dir = parent;
|
|
58827
58981
|
}
|
|
@@ -58979,7 +59133,7 @@ function buildPersonaHandlers(deps) {
|
|
|
58979
59133
|
}
|
|
58980
59134
|
|
|
58981
59135
|
// src/handlers/attachment.ts
|
|
58982
|
-
var
|
|
59136
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
58983
59137
|
init_protocol();
|
|
58984
59138
|
init_protocol();
|
|
58985
59139
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -59059,12 +59213,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
59059
59213
|
`session ${args.sessionId} scope unresolved`
|
|
59060
59214
|
);
|
|
59061
59215
|
}
|
|
59062
|
-
const cwdAbs =
|
|
59063
|
-
const candidateAbs =
|
|
59216
|
+
const cwdAbs = import_node_path51.default.resolve(sessionFile.cwd);
|
|
59217
|
+
const candidateAbs = import_node_path51.default.isAbsolute(args.relPath) ? import_node_path51.default.resolve(args.relPath) : import_node_path51.default.resolve(cwdAbs, args.relPath);
|
|
59064
59218
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
59065
59219
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
59066
59220
|
const entry = entries.find((e) => {
|
|
59067
|
-
const storedAbs =
|
|
59221
|
+
const storedAbs = import_node_path51.default.isAbsolute(e.relPath) ? import_node_path51.default.resolve(e.relPath) : import_node_path51.default.resolve(cwdAbs, e.relPath);
|
|
59068
59222
|
return storedAbs === candidateAbs && !e.stale;
|
|
59069
59223
|
});
|
|
59070
59224
|
if (!entry) {
|
|
@@ -59089,7 +59243,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
59089
59243
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
59090
59244
|
const f = deps.sessionStore.read(sessionId);
|
|
59091
59245
|
if (!f) return;
|
|
59092
|
-
assertGuestAttachmentPath(ctx,
|
|
59246
|
+
assertGuestAttachmentPath(ctx, import_node_path51.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
59093
59247
|
}
|
|
59094
59248
|
const groupAdd = async (frame, _client, ctx) => {
|
|
59095
59249
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -59104,8 +59258,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
59104
59258
|
if (!scope) {
|
|
59105
59259
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
59106
59260
|
}
|
|
59107
|
-
const cwdAbs =
|
|
59108
|
-
const candidateAbs =
|
|
59261
|
+
const cwdAbs = import_node_path51.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
59262
|
+
const candidateAbs = import_node_path51.default.isAbsolute(args.relPath) ? import_node_path51.default.resolve(args.relPath) : import_node_path51.default.resolve(cwdAbs, args.relPath);
|
|
59109
59263
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
59110
59264
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
59111
59265
|
const size = 0;
|
|
@@ -59164,19 +59318,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
59164
59318
|
|
|
59165
59319
|
// src/handlers/extension.ts
|
|
59166
59320
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
59167
|
-
var
|
|
59321
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
59168
59322
|
init_protocol();
|
|
59169
59323
|
|
|
59170
59324
|
// src/extension/bundle-zip.ts
|
|
59171
59325
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
59172
|
-
var
|
|
59326
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
59173
59327
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
59174
59328
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
59175
59329
|
async function bundleExtensionDir(dir) {
|
|
59176
59330
|
const entries = await listFilesSorted(dir);
|
|
59177
59331
|
const zip = new import_jszip2.default();
|
|
59178
59332
|
for (const rel of entries) {
|
|
59179
|
-
const abs =
|
|
59333
|
+
const abs = import_node_path52.default.join(dir, rel);
|
|
59180
59334
|
const content = await import_promises6.default.readFile(abs);
|
|
59181
59335
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
59182
59336
|
}
|
|
@@ -59197,7 +59351,7 @@ async function listFilesSorted(rootDir) {
|
|
|
59197
59351
|
return out;
|
|
59198
59352
|
}
|
|
59199
59353
|
async function walk(absRoot, relPrefix, out) {
|
|
59200
|
-
const dirAbs =
|
|
59354
|
+
const dirAbs = import_node_path52.default.join(absRoot, relPrefix);
|
|
59201
59355
|
const entries = await import_promises6.default.readdir(dirAbs, { withFileTypes: true });
|
|
59202
59356
|
for (const e of entries) {
|
|
59203
59357
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -59251,25 +59405,25 @@ function computePublishCheck(args) {
|
|
|
59251
59405
|
|
|
59252
59406
|
// src/extension/install-flow.ts
|
|
59253
59407
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
59254
|
-
var
|
|
59408
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
59255
59409
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
59256
59410
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
59257
59411
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
59258
59412
|
|
|
59259
59413
|
// src/extension/paths.ts
|
|
59260
59414
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
59261
|
-
var
|
|
59415
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
59262
59416
|
function clawdHomeRoot(override) {
|
|
59263
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
59417
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path53.default.join(import_node_os18.default.homedir(), ".clawd");
|
|
59264
59418
|
}
|
|
59265
59419
|
function extensionsRoot(override) {
|
|
59266
|
-
return
|
|
59420
|
+
return import_node_path53.default.join(clawdHomeRoot(override), "extensions");
|
|
59267
59421
|
}
|
|
59268
59422
|
function publishedChannelsFile(override) {
|
|
59269
|
-
return
|
|
59423
|
+
return import_node_path53.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
59270
59424
|
}
|
|
59271
59425
|
function bundleCacheRoot(override) {
|
|
59272
|
-
return
|
|
59426
|
+
return import_node_path53.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
59273
59427
|
}
|
|
59274
59428
|
|
|
59275
59429
|
// src/extension/install-flow.ts
|
|
@@ -59296,7 +59450,7 @@ async function installFromChannel(args, deps) {
|
|
|
59296
59450
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
59297
59451
|
}
|
|
59298
59452
|
for (const name of Object.keys(zip.files)) {
|
|
59299
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
59453
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path54.default.isAbsolute(name)) {
|
|
59300
59454
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
59301
59455
|
}
|
|
59302
59456
|
}
|
|
@@ -59328,7 +59482,7 @@ async function installFromChannel(args, deps) {
|
|
|
59328
59482
|
);
|
|
59329
59483
|
}
|
|
59330
59484
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
59331
|
-
const destDir =
|
|
59485
|
+
const destDir = import_node_path54.default.join(deps.extensionsRoot, localExtId);
|
|
59332
59486
|
let destExists = false;
|
|
59333
59487
|
try {
|
|
59334
59488
|
await import_promises7.default.access(destDir);
|
|
@@ -59342,16 +59496,16 @@ async function installFromChannel(args, deps) {
|
|
|
59342
59496
|
);
|
|
59343
59497
|
}
|
|
59344
59498
|
const stage = await import_promises7.default.mkdtemp(
|
|
59345
|
-
|
|
59499
|
+
import_node_path54.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
59346
59500
|
);
|
|
59347
59501
|
try {
|
|
59348
59502
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
59349
|
-
const dest =
|
|
59503
|
+
const dest = import_node_path54.default.join(stage, name);
|
|
59350
59504
|
if (entry.dir) {
|
|
59351
59505
|
await import_promises7.default.mkdir(dest, { recursive: true });
|
|
59352
59506
|
continue;
|
|
59353
59507
|
}
|
|
59354
|
-
await import_promises7.default.mkdir(
|
|
59508
|
+
await import_promises7.default.mkdir(import_node_path54.default.dirname(dest), { recursive: true });
|
|
59355
59509
|
if (name === "manifest.json") {
|
|
59356
59510
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
59357
59511
|
await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -59372,7 +59526,7 @@ async function installFromChannel(args, deps) {
|
|
|
59372
59526
|
|
|
59373
59527
|
// src/extension/update-flow.ts
|
|
59374
59528
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
59375
|
-
var
|
|
59529
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
59376
59530
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
59377
59531
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
59378
59532
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -59389,11 +59543,11 @@ async function updateFromChannel(args, deps) {
|
|
|
59389
59543
|
channelRef.extId,
|
|
59390
59544
|
channelRef.ownerPrincipalId
|
|
59391
59545
|
);
|
|
59392
|
-
const liveDir =
|
|
59546
|
+
const liveDir = import_node_path55.default.join(deps.extensionsRoot, localExtId);
|
|
59393
59547
|
const prevDir = `${liveDir}.prev`;
|
|
59394
59548
|
let existingVersion;
|
|
59395
59549
|
try {
|
|
59396
|
-
const raw = await import_promises8.default.readFile(
|
|
59550
|
+
const raw = await import_promises8.default.readFile(import_node_path55.default.join(liveDir, "manifest.json"), "utf8");
|
|
59397
59551
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
59398
59552
|
if (!parsed2.success) {
|
|
59399
59553
|
throw new UpdateError(
|
|
@@ -59426,7 +59580,7 @@ async function updateFromChannel(args, deps) {
|
|
|
59426
59580
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
59427
59581
|
}
|
|
59428
59582
|
for (const name of Object.keys(zip.files)) {
|
|
59429
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
59583
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path55.default.isAbsolute(name)) {
|
|
59430
59584
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
59431
59585
|
}
|
|
59432
59586
|
}
|
|
@@ -59461,16 +59615,16 @@ async function updateFromChannel(args, deps) {
|
|
|
59461
59615
|
await import_promises8.default.rm(prevDir, { recursive: true, force: true });
|
|
59462
59616
|
await import_promises8.default.rename(liveDir, prevDir);
|
|
59463
59617
|
const stage = await import_promises8.default.mkdtemp(
|
|
59464
|
-
|
|
59618
|
+
import_node_path55.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
59465
59619
|
);
|
|
59466
59620
|
try {
|
|
59467
59621
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
59468
|
-
const dest =
|
|
59622
|
+
const dest = import_node_path55.default.join(stage, name);
|
|
59469
59623
|
if (entry.dir) {
|
|
59470
59624
|
await import_promises8.default.mkdir(dest, { recursive: true });
|
|
59471
59625
|
continue;
|
|
59472
59626
|
}
|
|
59473
|
-
await import_promises8.default.mkdir(
|
|
59627
|
+
await import_promises8.default.mkdir(import_node_path55.default.dirname(dest), { recursive: true });
|
|
59474
59628
|
if (name === "manifest.json") {
|
|
59475
59629
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
59476
59630
|
await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -59537,7 +59691,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
59537
59691
|
);
|
|
59538
59692
|
}
|
|
59539
59693
|
}
|
|
59540
|
-
const manifestPath =
|
|
59694
|
+
const manifestPath = import_node_path56.default.join(root, extId, "manifest.json");
|
|
59541
59695
|
const manifest = await readManifest(root, extId);
|
|
59542
59696
|
const next = { ...manifest, version: newVersion };
|
|
59543
59697
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -59545,7 +59699,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
59545
59699
|
await import_promises9.default.rename(tmp, manifestPath);
|
|
59546
59700
|
}
|
|
59547
59701
|
async function readManifest(root, extId) {
|
|
59548
|
-
const file =
|
|
59702
|
+
const file = import_node_path56.default.join(root, extId, "manifest.json");
|
|
59549
59703
|
let raw;
|
|
59550
59704
|
try {
|
|
59551
59705
|
raw = await import_promises9.default.readFile(file, "utf8");
|
|
@@ -59629,7 +59783,7 @@ function buildExtensionHandlers(deps) {
|
|
|
59629
59783
|
};
|
|
59630
59784
|
async function buildSnapshotMeta(extId) {
|
|
59631
59785
|
const manifest = await readManifest(deps.root, extId);
|
|
59632
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
59786
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path56.default.join(deps.root, extId));
|
|
59633
59787
|
return { manifest, contentHash: sha256, buffer };
|
|
59634
59788
|
}
|
|
59635
59789
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -59804,9 +59958,9 @@ function buildExtensionHandlers(deps) {
|
|
|
59804
59958
|
}
|
|
59805
59959
|
|
|
59806
59960
|
// src/app-builder/project-store.ts
|
|
59807
|
-
var
|
|
59961
|
+
var import_node_fs46 = require("fs");
|
|
59808
59962
|
var import_node_child_process11 = require("child_process");
|
|
59809
|
-
var
|
|
59963
|
+
var import_node_path57 = require("path");
|
|
59810
59964
|
init_protocol();
|
|
59811
59965
|
var PROJECTS_DIR = "projects";
|
|
59812
59966
|
var META_FILE = ".clawd-project.json";
|
|
@@ -59820,19 +59974,19 @@ var ProjectStore = class {
|
|
|
59820
59974
|
root;
|
|
59821
59975
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
59822
59976
|
metaPath(name) {
|
|
59823
|
-
return (0,
|
|
59977
|
+
return (0, import_node_path57.join)(this.projectsRoot(), name, META_FILE);
|
|
59824
59978
|
}
|
|
59825
59979
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
59826
59980
|
projectDir(name) {
|
|
59827
|
-
return (0,
|
|
59981
|
+
return (0, import_node_path57.join)(this.projectsRoot(), name);
|
|
59828
59982
|
}
|
|
59829
59983
|
projectsRoot() {
|
|
59830
|
-
return (0,
|
|
59984
|
+
return (0, import_node_path57.join)(this.root, PROJECTS_DIR);
|
|
59831
59985
|
}
|
|
59832
59986
|
async list() {
|
|
59833
59987
|
let entries;
|
|
59834
59988
|
try {
|
|
59835
|
-
entries = await
|
|
59989
|
+
entries = await import_node_fs46.promises.readdir(this.projectsRoot());
|
|
59836
59990
|
} catch (err) {
|
|
59837
59991
|
if (err.code === "ENOENT") return [];
|
|
59838
59992
|
throw err;
|
|
@@ -59840,7 +59994,7 @@ var ProjectStore = class {
|
|
|
59840
59994
|
const out = [];
|
|
59841
59995
|
for (const name of entries) {
|
|
59842
59996
|
try {
|
|
59843
|
-
const raw = await
|
|
59997
|
+
const raw = await import_node_fs46.promises.readFile(this.metaPath(name), "utf8");
|
|
59844
59998
|
const json = JSON.parse(raw);
|
|
59845
59999
|
let migrated = false;
|
|
59846
60000
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -59851,7 +60005,7 @@ var ProjectStore = class {
|
|
|
59851
60005
|
if (parsed.success) {
|
|
59852
60006
|
out.push(parsed.data);
|
|
59853
60007
|
if (migrated) {
|
|
59854
|
-
void
|
|
60008
|
+
void import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
59855
60009
|
});
|
|
59856
60010
|
}
|
|
59857
60011
|
}
|
|
@@ -59895,8 +60049,8 @@ var ProjectStore = class {
|
|
|
59895
60049
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
59896
60050
|
}
|
|
59897
60051
|
const dir = this.projectDir(name);
|
|
59898
|
-
await
|
|
59899
|
-
await
|
|
60052
|
+
await import_node_fs46.promises.mkdir(dir, { recursive: true });
|
|
60053
|
+
await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
59900
60054
|
return meta;
|
|
59901
60055
|
}
|
|
59902
60056
|
/**
|
|
@@ -59939,7 +60093,7 @@ var ProjectStore = class {
|
|
|
59939
60093
|
}
|
|
59940
60094
|
async delete(name) {
|
|
59941
60095
|
const dir = this.projectDir(name);
|
|
59942
|
-
await
|
|
60096
|
+
await import_node_fs46.promises.rm(dir, { recursive: true, force: true });
|
|
59943
60097
|
}
|
|
59944
60098
|
async updatePort(name, newPort) {
|
|
59945
60099
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -59955,7 +60109,7 @@ var ProjectStore = class {
|
|
|
59955
60109
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
59956
60110
|
}
|
|
59957
60111
|
const updated = { ...target, port: newPort };
|
|
59958
|
-
await
|
|
60112
|
+
await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
59959
60113
|
return updated;
|
|
59960
60114
|
}
|
|
59961
60115
|
/**
|
|
@@ -59972,7 +60126,7 @@ var ProjectStore = class {
|
|
|
59972
60126
|
if (!validated.success) {
|
|
59973
60127
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
59974
60128
|
}
|
|
59975
|
-
await
|
|
60129
|
+
await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
59976
60130
|
return validated.data;
|
|
59977
60131
|
}
|
|
59978
60132
|
/**
|
|
@@ -59993,7 +60147,7 @@ var ProjectStore = class {
|
|
|
59993
60147
|
if (!validated.success) {
|
|
59994
60148
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
59995
60149
|
}
|
|
59996
|
-
await
|
|
60150
|
+
await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
59997
60151
|
return validated.data;
|
|
59998
60152
|
}
|
|
59999
60153
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -60008,7 +60162,7 @@ var ProjectStore = class {
|
|
|
60008
60162
|
if (!validated.success) {
|
|
60009
60163
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
60010
60164
|
}
|
|
60011
|
-
await
|
|
60165
|
+
await import_node_fs46.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
60012
60166
|
return validated.data;
|
|
60013
60167
|
}
|
|
60014
60168
|
};
|
|
@@ -60129,8 +60283,8 @@ var PublishJobRegistry = class {
|
|
|
60129
60283
|
|
|
60130
60284
|
// src/app-builder/publish-job-runner.ts
|
|
60131
60285
|
var import_node_child_process13 = require("child_process");
|
|
60132
|
-
var
|
|
60133
|
-
var
|
|
60286
|
+
var import_node_fs47 = require("fs");
|
|
60287
|
+
var import_node_path58 = require("path");
|
|
60134
60288
|
|
|
60135
60289
|
// src/app-builder/publish-stage-parser.ts
|
|
60136
60290
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -60162,10 +60316,10 @@ async function startPublishJob(deps, args) {
|
|
|
60162
60316
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
60163
60317
|
}
|
|
60164
60318
|
const projDir = projectDir(args.name);
|
|
60165
|
-
const logPath = (0,
|
|
60319
|
+
const logPath = (0, import_node_path58.join)(projDir, ".publish.log");
|
|
60166
60320
|
let logStream = null;
|
|
60167
60321
|
try {
|
|
60168
|
-
logStream = (0,
|
|
60322
|
+
logStream = (0, import_node_fs47.createWriteStream)(logPath, { flags: "w" });
|
|
60169
60323
|
} catch {
|
|
60170
60324
|
logStream = null;
|
|
60171
60325
|
}
|
|
@@ -60422,8 +60576,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
60422
60576
|
|
|
60423
60577
|
// src/handlers/app-builder.ts
|
|
60424
60578
|
init_protocol();
|
|
60425
|
-
var
|
|
60426
|
-
var
|
|
60579
|
+
var import_node_path59 = require("path");
|
|
60580
|
+
var import_node_fs48 = require("fs");
|
|
60427
60581
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
60428
60582
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
60429
60583
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -60504,7 +60658,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
60504
60658
|
async function listAllUsersProjects() {
|
|
60505
60659
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
60506
60660
|
const getStore = deps.getStore;
|
|
60507
|
-
const userIds = await
|
|
60661
|
+
const userIds = await import_node_fs48.promises.readdir(deps.usersRoot).catch(() => []);
|
|
60508
60662
|
const perUser = await Promise.all(
|
|
60509
60663
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
60510
60664
|
);
|
|
@@ -60573,8 +60727,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
60573
60727
|
const project = await userStore.create(f.name, reservedPorts);
|
|
60574
60728
|
try {
|
|
60575
60729
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
60576
|
-
const templateSrcDir = (0,
|
|
60577
|
-
const scaffoldScript = (0,
|
|
60730
|
+
const templateSrcDir = (0, import_node_path59.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
60731
|
+
const scaffoldScript = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
60578
60732
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
60579
60733
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
60580
60734
|
name: project.name,
|
|
@@ -60778,7 +60932,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
60778
60932
|
await userStore.clearPublishJob(args.name);
|
|
60779
60933
|
}
|
|
60780
60934
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
60781
|
-
const scriptPath = (0,
|
|
60935
|
+
const scriptPath = (0, import_node_path59.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
60782
60936
|
deps.logger?.info("app-builder.publish.start", {
|
|
60783
60937
|
name: args.name,
|
|
60784
60938
|
sessionId: boundSession.sessionId,
|
|
@@ -60954,7 +61108,7 @@ function buildVisitorHandlers(deps) {
|
|
|
60954
61108
|
|
|
60955
61109
|
// src/extension/registry.ts
|
|
60956
61110
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
60957
|
-
var
|
|
61111
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
60958
61112
|
async function loadAll(root) {
|
|
60959
61113
|
let entries;
|
|
60960
61114
|
try {
|
|
@@ -60967,13 +61121,13 @@ async function loadAll(root) {
|
|
|
60967
61121
|
for (const ent of entries) {
|
|
60968
61122
|
if (!ent.isDirectory()) continue;
|
|
60969
61123
|
if (ent.name.startsWith(".")) continue;
|
|
60970
|
-
records.push(await loadOne(
|
|
61124
|
+
records.push(await loadOne(import_node_path60.default.join(root, ent.name), ent.name));
|
|
60971
61125
|
}
|
|
60972
61126
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
60973
61127
|
return records;
|
|
60974
61128
|
}
|
|
60975
61129
|
async function loadOne(dir, dirName) {
|
|
60976
|
-
const manifestPath =
|
|
61130
|
+
const manifestPath = import_node_path60.default.join(dir, "manifest.json");
|
|
60977
61131
|
let raw;
|
|
60978
61132
|
try {
|
|
60979
61133
|
raw = await import_promises10.default.readFile(manifestPath, "utf8");
|
|
@@ -61018,7 +61172,7 @@ async function loadOne(dir, dirName) {
|
|
|
61018
61172
|
|
|
61019
61173
|
// src/extension/uninstall.ts
|
|
61020
61174
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
61021
|
-
var
|
|
61175
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
61022
61176
|
var UninstallError = class extends Error {
|
|
61023
61177
|
constructor(code, message) {
|
|
61024
61178
|
super(message);
|
|
@@ -61027,7 +61181,7 @@ var UninstallError = class extends Error {
|
|
|
61027
61181
|
code;
|
|
61028
61182
|
};
|
|
61029
61183
|
async function uninstall(deps) {
|
|
61030
|
-
const dir =
|
|
61184
|
+
const dir = import_node_path61.default.join(deps.root, deps.extId);
|
|
61031
61185
|
try {
|
|
61032
61186
|
await import_promises11.default.access(dir);
|
|
61033
61187
|
} catch {
|
|
@@ -61557,7 +61711,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
61557
61711
|
|
|
61558
61712
|
// src/extension/runtime.ts
|
|
61559
61713
|
var import_node_child_process16 = require("child_process");
|
|
61560
|
-
var
|
|
61714
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
61561
61715
|
var import_promises12 = require("timers/promises");
|
|
61562
61716
|
|
|
61563
61717
|
// src/extension/port-allocator.ts
|
|
@@ -61658,7 +61812,7 @@ var Runtime = class {
|
|
|
61658
61812
|
/\$CLAWOS_EXT_PORT/g,
|
|
61659
61813
|
String(port)
|
|
61660
61814
|
);
|
|
61661
|
-
const dir =
|
|
61815
|
+
const dir = import_node_path62.default.join(this.root, extId);
|
|
61662
61816
|
const env = {
|
|
61663
61817
|
...process.env,
|
|
61664
61818
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -61770,7 +61924,7 @@ ${handle.stderrTail}`
|
|
|
61770
61924
|
|
|
61771
61925
|
// src/extension/published-channels.ts
|
|
61772
61926
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
61773
|
-
var
|
|
61927
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
61774
61928
|
init_zod();
|
|
61775
61929
|
var PublishedChannelsError = class extends Error {
|
|
61776
61930
|
constructor(code, message) {
|
|
@@ -61869,7 +62023,7 @@ var PublishedChannelStore = class {
|
|
|
61869
62023
|
)
|
|
61870
62024
|
};
|
|
61871
62025
|
const tmp = `${this.filePath}.tmp`;
|
|
61872
|
-
await import_promises13.default.mkdir(
|
|
62026
|
+
await import_promises13.default.mkdir(import_node_path63.default.dirname(this.filePath), { recursive: true });
|
|
61873
62027
|
await import_promises13.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
61874
62028
|
await import_promises13.default.rename(tmp, this.filePath);
|
|
61875
62029
|
}
|
|
@@ -61877,7 +62031,7 @@ var PublishedChannelStore = class {
|
|
|
61877
62031
|
|
|
61878
62032
|
// src/extension/bundle-cache.ts
|
|
61879
62033
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
61880
|
-
var
|
|
62034
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
61881
62035
|
var BundleCache = class {
|
|
61882
62036
|
constructor(rootDir) {
|
|
61883
62037
|
this.rootDir = rootDir;
|
|
@@ -61886,14 +62040,14 @@ var BundleCache = class {
|
|
|
61886
62040
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
61887
62041
|
async write(snapshotHash, buffer) {
|
|
61888
62042
|
await import_promises14.default.mkdir(this.rootDir, { recursive: true });
|
|
61889
|
-
const file =
|
|
62043
|
+
const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
61890
62044
|
const tmp = `${file}.tmp`;
|
|
61891
62045
|
await import_promises14.default.writeFile(tmp, buffer, { mode: 384 });
|
|
61892
62046
|
await import_promises14.default.rename(tmp, file);
|
|
61893
62047
|
}
|
|
61894
62048
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
61895
62049
|
async read(snapshotHash) {
|
|
61896
|
-
const file =
|
|
62050
|
+
const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
61897
62051
|
try {
|
|
61898
62052
|
return await import_promises14.default.readFile(file);
|
|
61899
62053
|
} catch (e) {
|
|
@@ -61903,7 +62057,7 @@ var BundleCache = class {
|
|
|
61903
62057
|
}
|
|
61904
62058
|
/** Idempotent — missing file is not an error. */
|
|
61905
62059
|
async delete(snapshotHash) {
|
|
61906
|
-
const file =
|
|
62060
|
+
const file = import_node_path64.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
61907
62061
|
await import_promises14.default.rm(file, { force: true });
|
|
61908
62062
|
}
|
|
61909
62063
|
};
|
|
@@ -61926,24 +62080,24 @@ async function startDaemon(config) {
|
|
|
61926
62080
|
sampling: logShippingCfg.sampling,
|
|
61927
62081
|
homeDir: import_node_os22.default.homedir()
|
|
61928
62082
|
});
|
|
61929
|
-
const logDir =
|
|
61930
|
-
|
|
62083
|
+
const logDir = import_node_path65.default.join(config.dataDir, "log");
|
|
62084
|
+
import_node_fs49.default.mkdirSync(logDir, { recursive: true });
|
|
61931
62085
|
const logger = createLogger({
|
|
61932
62086
|
level: config.logLevel,
|
|
61933
|
-
file:
|
|
62087
|
+
file: import_node_path65.default.join(logDir, "clawd.log"),
|
|
61934
62088
|
logClient
|
|
61935
62089
|
});
|
|
61936
62090
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
61937
62091
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
61938
|
-
file:
|
|
62092
|
+
file: import_node_path65.default.join(logDir, "screen-idle-probe.log"),
|
|
61939
62093
|
level: "debug"
|
|
61940
62094
|
});
|
|
61941
62095
|
logger.info("screen-idle probe logger enabled", {
|
|
61942
|
-
file:
|
|
62096
|
+
file: import_node_path65.default.join(logDir, "screen-idle-probe.log")
|
|
61943
62097
|
});
|
|
61944
62098
|
const CAP_TARGETS = [
|
|
61945
|
-
|
|
61946
|
-
|
|
62099
|
+
import_node_path65.default.join(logDir, "clawd.log"),
|
|
62100
|
+
import_node_path65.default.join(logDir, "screen-idle-probe.log")
|
|
61947
62101
|
];
|
|
61948
62102
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
61949
62103
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -62039,8 +62193,8 @@ async function startDaemon(config) {
|
|
|
62039
62193
|
const agents = new AgentsScanner();
|
|
62040
62194
|
const history = new ClaudeHistoryReader();
|
|
62041
62195
|
let transport = null;
|
|
62042
|
-
const personaStore = new PersonaStore(
|
|
62043
|
-
const usersRoot =
|
|
62196
|
+
const personaStore = new PersonaStore(import_node_path65.default.join(config.dataDir, "personas"));
|
|
62197
|
+
const usersRoot = import_node_path65.default.join(config.dataDir, "users");
|
|
62044
62198
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
62045
62199
|
if (defaultsRoot) {
|
|
62046
62200
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -62058,10 +62212,11 @@ async function startDaemon(config) {
|
|
|
62058
62212
|
refreshSandboxSettings({ store: personaStore, logger });
|
|
62059
62213
|
migrateAgentsMirror({ store: personaStore, logger });
|
|
62060
62214
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
62215
|
+
migrateSandboxAllowRead({ store: personaStore, logger });
|
|
62061
62216
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
62062
62217
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
62063
62218
|
const dispatchStore = createDispatchStore({
|
|
62064
|
-
filePath:
|
|
62219
|
+
filePath: import_node_path65.default.join(config.dataDir, "dispatch.json"),
|
|
62065
62220
|
now: () => Date.now(),
|
|
62066
62221
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
62067
62222
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -62076,18 +62231,18 @@ async function startDaemon(config) {
|
|
|
62076
62231
|
now: () => Date.now(),
|
|
62077
62232
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
62078
62233
|
});
|
|
62079
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
62234
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path65.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
|
|
62080
62235
|
const mcpConfigs = [];
|
|
62081
62236
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
62082
62237
|
const dispatchServerCandidates = [
|
|
62083
|
-
|
|
62238
|
+
import_node_path65.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
62084
62239
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
62085
|
-
|
|
62240
|
+
import_node_path65.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
62086
62241
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
62087
62242
|
];
|
|
62088
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
62243
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62089
62244
|
if (dispatchServerScriptPath) {
|
|
62090
|
-
const dispatchLogPath =
|
|
62245
|
+
const dispatchLogPath = import_node_path65.default.join(logDir, "dispatch-mcp-server.log");
|
|
62091
62246
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
62092
62247
|
dataDir: config.dataDir,
|
|
62093
62248
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -62107,12 +62262,12 @@ async function startDaemon(config) {
|
|
|
62107
62262
|
});
|
|
62108
62263
|
}
|
|
62109
62264
|
const ticketServerCandidates = [
|
|
62110
|
-
|
|
62111
|
-
|
|
62265
|
+
import_node_path65.default.join(here, "ticket", "mcp-server.cjs"),
|
|
62266
|
+
import_node_path65.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
62112
62267
|
];
|
|
62113
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
62268
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62114
62269
|
if (ticketServerScriptPath) {
|
|
62115
|
-
const ticketLogPath =
|
|
62270
|
+
const ticketLogPath = import_node_path65.default.join(logDir, "ticket-mcp-server.log");
|
|
62116
62271
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
62117
62272
|
dataDir: config.dataDir,
|
|
62118
62273
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -62134,12 +62289,12 @@ async function startDaemon(config) {
|
|
|
62134
62289
|
});
|
|
62135
62290
|
}
|
|
62136
62291
|
const shiftServerCandidates = [
|
|
62137
|
-
|
|
62138
|
-
|
|
62292
|
+
import_node_path65.default.join(here, "shift", "mcp-server.cjs"),
|
|
62293
|
+
import_node_path65.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
62139
62294
|
];
|
|
62140
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
62295
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62141
62296
|
if (shiftServerScriptPath) {
|
|
62142
|
-
const shiftLogPath =
|
|
62297
|
+
const shiftLogPath = import_node_path65.default.join(logDir, "shift-mcp-server.log");
|
|
62143
62298
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
62144
62299
|
dataDir: config.dataDir,
|
|
62145
62300
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -62160,12 +62315,12 @@ async function startDaemon(config) {
|
|
|
62160
62315
|
);
|
|
62161
62316
|
}
|
|
62162
62317
|
const inboxServerCandidates = [
|
|
62163
|
-
|
|
62164
|
-
|
|
62318
|
+
import_node_path65.default.join(here, "inbox", "mcp-server.cjs"),
|
|
62319
|
+
import_node_path65.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
62165
62320
|
];
|
|
62166
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
62321
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62167
62322
|
if (inboxServerScriptPath) {
|
|
62168
|
-
const inboxLogPath =
|
|
62323
|
+
const inboxLogPath = import_node_path65.default.join(logDir, "inbox-mcp-server.log");
|
|
62169
62324
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
62170
62325
|
dataDir: config.dataDir,
|
|
62171
62326
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -62186,10 +62341,10 @@ async function startDaemon(config) {
|
|
|
62186
62341
|
);
|
|
62187
62342
|
}
|
|
62188
62343
|
const peerOpsServerCandidates = [
|
|
62189
|
-
|
|
62190
|
-
|
|
62344
|
+
import_node_path65.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
62345
|
+
import_node_path65.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
62191
62346
|
];
|
|
62192
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
62347
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62193
62348
|
if (peerOpsServerScriptPath) {
|
|
62194
62349
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
62195
62350
|
dataDir: config.dataDir,
|
|
@@ -62209,12 +62364,12 @@ async function startDaemon(config) {
|
|
|
62209
62364
|
);
|
|
62210
62365
|
}
|
|
62211
62366
|
const rpcToolServerCandidates = [
|
|
62212
|
-
|
|
62213
|
-
|
|
62367
|
+
import_node_path65.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
62368
|
+
import_node_path65.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
62214
62369
|
];
|
|
62215
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) =>
|
|
62370
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p2) => import_node_fs49.default.existsSync(p2));
|
|
62216
62371
|
if (rpcToolServerScriptPath) {
|
|
62217
|
-
const rpcToolLogPath =
|
|
62372
|
+
const rpcToolLogPath = import_node_path65.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
62218
62373
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
62219
62374
|
dataDir: config.dataDir,
|
|
62220
62375
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -62235,7 +62390,7 @@ async function startDaemon(config) {
|
|
|
62235
62390
|
);
|
|
62236
62391
|
}
|
|
62237
62392
|
const shiftStore = createShiftStore({
|
|
62238
|
-
filePath:
|
|
62393
|
+
filePath: import_node_path65.default.join(config.dataDir, "shift.json"),
|
|
62239
62394
|
ownerIdProvider: () => ownerPrincipalId,
|
|
62240
62395
|
now: () => Date.now()
|
|
62241
62396
|
});
|
|
@@ -62257,7 +62412,7 @@ async function startDaemon(config) {
|
|
|
62257
62412
|
getAdapter,
|
|
62258
62413
|
historyReader: history,
|
|
62259
62414
|
dataDir: config.dataDir,
|
|
62260
|
-
personaRoot:
|
|
62415
|
+
personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
|
|
62261
62416
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
62262
62417
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
62263
62418
|
getPersonaTool: (personaId2) => personaRegistry.get(personaId2)?.tool,
|
|
@@ -62308,10 +62463,10 @@ async function startDaemon(config) {
|
|
|
62308
62463
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
62309
62464
|
attachmentGroup: {
|
|
62310
62465
|
onFileEdit: (input) => {
|
|
62311
|
-
const absPath =
|
|
62466
|
+
const absPath = import_node_path65.default.isAbsolute(input.relPath) ? input.relPath : import_node_path65.default.join(input.cwd, input.relPath);
|
|
62312
62467
|
let size = 0;
|
|
62313
62468
|
try {
|
|
62314
|
-
size =
|
|
62469
|
+
size = import_node_fs49.default.statSync(absPath).size;
|
|
62315
62470
|
} catch (err) {
|
|
62316
62471
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
62317
62472
|
sessionId: input.sessionId,
|
|
@@ -62487,6 +62642,12 @@ async function startDaemon(config) {
|
|
|
62487
62642
|
});
|
|
62488
62643
|
const getProjectStore = (userId) => new ProjectStore(deriveUserWorkDir(userId, usersRoot));
|
|
62489
62644
|
const appBuilderStore = getProjectStore(ownerPrincipalId);
|
|
62645
|
+
const attachmentUserWorkDir = (sid) => {
|
|
62646
|
+
const scope = manager.findOwnedSessionScope(sid);
|
|
62647
|
+
if (scope?.kind !== "persona") return null;
|
|
62648
|
+
const userId = scope.mode === "owner" ? ownerPrincipalId : scope.capId;
|
|
62649
|
+
return deriveUserWorkDir(userId, usersRoot);
|
|
62650
|
+
};
|
|
62490
62651
|
recoverInterruptedPublishJobs(appBuilderStore, logger).catch((err) => {
|
|
62491
62652
|
logger.warn("app-builder.publish.recover-startup-failed", {
|
|
62492
62653
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -62552,11 +62713,11 @@ async function startDaemon(config) {
|
|
|
62552
62713
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
62553
62714
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
62554
62715
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
62555
|
-
personaRoot:
|
|
62716
|
+
personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
|
|
62556
62717
|
usersRoot
|
|
62557
62718
|
},
|
|
62558
62719
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
62559
|
-
personaRoot:
|
|
62720
|
+
personaRoot: import_node_path65.default.join(config.dataDir, "personas"),
|
|
62560
62721
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
62561
62722
|
usersRoot,
|
|
62562
62723
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -62682,11 +62843,11 @@ async function startDaemon(config) {
|
|
|
62682
62843
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
62683
62844
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
62684
62845
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
62685
|
-
appBuilderPersonaRoot:
|
|
62846
|
+
appBuilderPersonaRoot: import_node_path65.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
62686
62847
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
62687
|
-
deployKitRoot:
|
|
62848
|
+
deployKitRoot: import_node_path65.default.join(config.dataDir, "deploy-kit"),
|
|
62688
62849
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
62689
|
-
resolvePersonaRoot: (personaId2) =>
|
|
62850
|
+
resolvePersonaRoot: (personaId2) => import_node_path65.default.join(config.dataDir, "personas", personaId2),
|
|
62690
62851
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
62691
62852
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
62692
62853
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -62789,7 +62950,7 @@ async function startDaemon(config) {
|
|
|
62789
62950
|
});
|
|
62790
62951
|
shiftScheduler.start();
|
|
62791
62952
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
62792
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
62953
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path65.default.join(config.dataDir, "personas"));
|
|
62793
62954
|
const larkBotCloud = createLarkBotCloudClient({
|
|
62794
62955
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
62795
62956
|
apiKey: resolveClawdTicketsApiKey(),
|
|
@@ -62800,6 +62961,9 @@ async function startDaemon(config) {
|
|
|
62800
62961
|
manager,
|
|
62801
62962
|
cloud: larkBotCloud,
|
|
62802
62963
|
store: larkBotStore,
|
|
62964
|
+
fetchResource: (appId, messageId, fileKey, maxBytes) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes),
|
|
62965
|
+
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
62966
|
+
mediaRootFor: (chatId) => import_node_path65.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
62803
62967
|
logger: {
|
|
62804
62968
|
warn: (msg) => logger.warn(msg),
|
|
62805
62969
|
info: (msg) => logger.info(msg)
|
|
@@ -62879,15 +63043,17 @@ async function startDaemon(config) {
|
|
|
62879
63043
|
larkBotEvent: larkBotEventEndpoint,
|
|
62880
63044
|
// /files HMAC verify 用 auth.json token(与 attachment.signUrl 同源)。
|
|
62881
63045
|
getSignSecret: () => authFile.token,
|
|
62882
|
-
// chatinput 附件上传(POST /attachments/upload,spec §6.1
|
|
62883
|
-
//
|
|
62884
|
-
//
|
|
63046
|
+
// chatinput 附件上传(POST /attachments/upload,spec §6.1 + 2026-08-06 §5)。落盘根按
|
|
63047
|
+
// scope 切换:persona 会话 → 连接者 userWorkDir(与 connection-prompt 宣称的工作目录一致,
|
|
63048
|
+
// guest 对 persona 目录的读权不再连带看到 owner 上传的附件);非 persona 会话 → session.cwd
|
|
63049
|
+
// (项目目录本就是用户地盘)。签名 secret 与 /files HMAC 同源;tunnel 未启时返 503。
|
|
62885
63050
|
attachmentUpload: {
|
|
62886
63051
|
groupFileStore,
|
|
62887
63052
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
62888
|
-
|
|
63053
|
+
getAttachmentBaseDir: (sid) => {
|
|
62889
63054
|
const f = manager.findOwnedSession(sid);
|
|
62890
|
-
|
|
63055
|
+
if (!f) return null;
|
|
63056
|
+
return attachmentUserWorkDir(sid) ?? f.cwd;
|
|
62891
63057
|
},
|
|
62892
63058
|
getHttpBaseUrl: () => currentTunnelUrl ? getHttpBaseUrl() : null
|
|
62893
63059
|
},
|
|
@@ -63080,8 +63246,8 @@ async function startDaemon(config) {
|
|
|
63080
63246
|
const lines = [
|
|
63081
63247
|
`Tunnel: ${r.url}`,
|
|
63082
63248
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
63083
|
-
`Frpc config: ${
|
|
63084
|
-
`Frpc log: ${
|
|
63249
|
+
`Frpc config: ${import_node_path65.default.join(config.dataDir, "frpc.toml")}`,
|
|
63250
|
+
`Frpc log: ${import_node_path65.default.join(logDir, "frpc.log")}`
|
|
63085
63251
|
];
|
|
63086
63252
|
const width = Math.max(...lines.map((l) => l.length));
|
|
63087
63253
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -63094,8 +63260,8 @@ ${bar}
|
|
|
63094
63260
|
|
|
63095
63261
|
`);
|
|
63096
63262
|
try {
|
|
63097
|
-
const connectPath =
|
|
63098
|
-
|
|
63263
|
+
const connectPath = import_node_path65.default.join(config.dataDir, "connect.txt");
|
|
63264
|
+
import_node_fs49.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
63099
63265
|
} catch {
|
|
63100
63266
|
}
|
|
63101
63267
|
} catch (err) {
|
|
@@ -63131,8 +63297,10 @@ ${bar}
|
|
|
63131
63297
|
scope,
|
|
63132
63298
|
sessionId
|
|
63133
63299
|
})),
|
|
63134
|
-
//
|
|
63300
|
+
// 双根扫描(spec 2026-08-06 §5):legacy cwd 根(迁移前落盘点,30 天自然老化)+
|
|
63301
|
+
// userWorkDir 根(迁移后 upload 落盘点,与 getAttachmentBaseDir 同源派生)
|
|
63135
63302
|
getSessionCwd: (sid) => manager.findOwnedSession(sid)?.cwd ?? null,
|
|
63303
|
+
getUserWorkDir: attachmentUserWorkDir,
|
|
63136
63304
|
logger
|
|
63137
63305
|
});
|
|
63138
63306
|
} catch (err) {
|
|
@@ -63167,9 +63335,9 @@ ${bar}
|
|
|
63167
63335
|
};
|
|
63168
63336
|
}
|
|
63169
63337
|
function migrateDropPersonsDir(dataDir) {
|
|
63170
|
-
const dir =
|
|
63338
|
+
const dir = import_node_path65.default.join(dataDir, "persons");
|
|
63171
63339
|
try {
|
|
63172
|
-
|
|
63340
|
+
import_node_fs49.default.rmSync(dir, { recursive: true, force: true });
|
|
63173
63341
|
} catch {
|
|
63174
63342
|
}
|
|
63175
63343
|
}
|