@clawos-dev/clawd 0.2.249 → 0.2.251
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 +919 -637
- package/dist/dispatch/mcp-server.cjs +124 -30
- package/dist/persona-defaults/persona-app-builder/CLAUDE.md +1 -1
- package/dist/persona-defaults/persona-builder/CLAUDE.md +6 -3
- package/dist/persona-defaults/persona-clawd-helper/CLAUDE.md +3 -3
- package/dist/persona-defaults/persona-feishu-assistant/CLAUDE.md +1 -1
- package/dist/share-ui/assets/{guest-DsrUx2Ku.js → guest-D6RAMr_5.js} +120 -120
- package/dist/share-ui/guest.html +1 -1
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -751,8 +751,8 @@ var init_parseUtil = __esm({
|
|
|
751
751
|
init_errors2();
|
|
752
752
|
init_en();
|
|
753
753
|
makeIssue = (params) => {
|
|
754
|
-
const { data, path:
|
|
755
|
-
const fullPath = [...
|
|
754
|
+
const { data, path: path74, errorMaps, issueData } = params;
|
|
755
|
+
const fullPath = [...path74, ...issueData.path || []];
|
|
756
756
|
const fullIssue = {
|
|
757
757
|
...issueData,
|
|
758
758
|
path: fullPath
|
|
@@ -1063,11 +1063,11 @@ var init_types = __esm({
|
|
|
1063
1063
|
init_parseUtil();
|
|
1064
1064
|
init_util();
|
|
1065
1065
|
ParseInputLazyPath = class {
|
|
1066
|
-
constructor(parent, value,
|
|
1066
|
+
constructor(parent, value, path74, key) {
|
|
1067
1067
|
this._cachedPath = [];
|
|
1068
1068
|
this.parent = parent;
|
|
1069
1069
|
this.data = value;
|
|
1070
|
-
this._path =
|
|
1070
|
+
this._path = path74;
|
|
1071
1071
|
this._key = key;
|
|
1072
1072
|
}
|
|
1073
1073
|
get path() {
|
|
@@ -6213,7 +6213,12 @@ var init_dispatch = __esm({
|
|
|
6213
6213
|
})
|
|
6214
6214
|
]);
|
|
6215
6215
|
DispatchRunArgsSchema = external_exports.object({
|
|
6216
|
-
|
|
6216
|
+
// 新开必填;续派(dispatchId 非空)时可省略——targetPersonaId 从台账行取。
|
|
6217
|
+
targetPersona: external_exports.string().min(1).optional(),
|
|
6218
|
+
// 续派(spec 2026-07-21,单 dispatchId 语义:一件事一行一 id):非空 = 把 prompt
|
|
6219
|
+
// 作为新 turn 打进该 dispatch 的原 worker session 接着干(台账行复位 running)。
|
|
6220
|
+
// 省略 = 新开一件事,daemon 铸新 id。
|
|
6221
|
+
dispatchId: external_exports.string().min(1).optional(),
|
|
6217
6222
|
prompt: external_exports.string(),
|
|
6218
6223
|
// 跨设备 dispatch:非空 = A 角色,转发到该 contact deviceId 的 peer daemon;
|
|
6219
6224
|
// 省略 = 本地 dispatch / B 角色本地执行。A 转发给 B 时 body 不带此字段。
|
|
@@ -6223,6 +6228,10 @@ var init_dispatch = __esm({
|
|
|
6223
6228
|
// tools/claude.ts CLAUDE_MODEL_IDS);handler 层做二次校验,非法值 fail-fast。
|
|
6224
6229
|
// protocol 层保持 string 便于未来跨 tool 扩展(届时 union 收合法字面量)。
|
|
6225
6230
|
model: external_exports.string().min(1).optional()
|
|
6231
|
+
}).refine((v2) => v2.targetPersona !== void 0 || v2.dispatchId !== void 0, {
|
|
6232
|
+
message: "either targetPersona (new dispatch) or dispatchId (follow-up) is required"
|
|
6233
|
+
}).refine((v2) => !(v2.dispatchId !== void 0 && v2.targetDeviceId !== void 0), {
|
|
6234
|
+
message: "cross-device dispatch cannot be continued (dispatchId + targetDeviceId are mutually exclusive)"
|
|
6226
6235
|
});
|
|
6227
6236
|
DispatchCompleteArgsSchema = external_exports.object({
|
|
6228
6237
|
dispatchId: external_exports.string().min(1),
|
|
@@ -6606,8 +6615,8 @@ var require_req = __commonJS({
|
|
|
6606
6615
|
if (req.originalUrl) {
|
|
6607
6616
|
_req.url = req.originalUrl;
|
|
6608
6617
|
} else {
|
|
6609
|
-
const
|
|
6610
|
-
_req.url = typeof
|
|
6618
|
+
const path74 = req.path;
|
|
6619
|
+
_req.url = typeof path74 === "string" ? path74 : req.url ? req.url.path || req.url : void 0;
|
|
6611
6620
|
}
|
|
6612
6621
|
if (req.query) {
|
|
6613
6622
|
_req.query = req.query;
|
|
@@ -6772,14 +6781,14 @@ var require_redact = __commonJS({
|
|
|
6772
6781
|
}
|
|
6773
6782
|
return obj;
|
|
6774
6783
|
}
|
|
6775
|
-
function parsePath(
|
|
6784
|
+
function parsePath(path74) {
|
|
6776
6785
|
const parts = [];
|
|
6777
6786
|
let current = "";
|
|
6778
6787
|
let inBrackets = false;
|
|
6779
6788
|
let inQuotes = false;
|
|
6780
6789
|
let quoteChar = "";
|
|
6781
|
-
for (let i = 0; i <
|
|
6782
|
-
const char =
|
|
6790
|
+
for (let i = 0; i < path74.length; i++) {
|
|
6791
|
+
const char = path74[i];
|
|
6783
6792
|
if (!inBrackets && char === ".") {
|
|
6784
6793
|
if (current) {
|
|
6785
6794
|
parts.push(current);
|
|
@@ -6910,10 +6919,10 @@ var require_redact = __commonJS({
|
|
|
6910
6919
|
return current;
|
|
6911
6920
|
}
|
|
6912
6921
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6913
|
-
for (const
|
|
6914
|
-
const parts = parsePath(
|
|
6922
|
+
for (const path74 of paths) {
|
|
6923
|
+
const parts = parsePath(path74);
|
|
6915
6924
|
if (parts.includes("*")) {
|
|
6916
|
-
redactWildcardPath(obj, parts, censor,
|
|
6925
|
+
redactWildcardPath(obj, parts, censor, path74, remove);
|
|
6917
6926
|
} else {
|
|
6918
6927
|
if (remove) {
|
|
6919
6928
|
removeKey(obj, parts);
|
|
@@ -6998,8 +7007,8 @@ var require_redact = __commonJS({
|
|
|
6998
7007
|
}
|
|
6999
7008
|
} else {
|
|
7000
7009
|
if (afterWildcard.includes("*")) {
|
|
7001
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
7002
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
7010
|
+
const wrappedCensor = typeof censor === "function" ? (value, path74) => {
|
|
7011
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path74];
|
|
7003
7012
|
return censor(value, fullPath);
|
|
7004
7013
|
} : censor;
|
|
7005
7014
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -7034,8 +7043,8 @@ var require_redact = __commonJS({
|
|
|
7034
7043
|
return null;
|
|
7035
7044
|
}
|
|
7036
7045
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
7037
|
-
for (const
|
|
7038
|
-
const parts = parsePath(
|
|
7046
|
+
for (const path74 of pathsToClone) {
|
|
7047
|
+
const parts = parsePath(path74);
|
|
7039
7048
|
let current = pathStructure;
|
|
7040
7049
|
for (let i = 0; i < parts.length; i++) {
|
|
7041
7050
|
const part = parts[i];
|
|
@@ -7087,24 +7096,24 @@ var require_redact = __commonJS({
|
|
|
7087
7096
|
}
|
|
7088
7097
|
return cloneSelectively(obj, pathStructure);
|
|
7089
7098
|
}
|
|
7090
|
-
function validatePath(
|
|
7091
|
-
if (typeof
|
|
7099
|
+
function validatePath(path74) {
|
|
7100
|
+
if (typeof path74 !== "string") {
|
|
7092
7101
|
throw new Error("Paths must be (non-empty) strings");
|
|
7093
7102
|
}
|
|
7094
|
-
if (
|
|
7103
|
+
if (path74 === "") {
|
|
7095
7104
|
throw new Error("Invalid redaction path ()");
|
|
7096
7105
|
}
|
|
7097
|
-
if (
|
|
7098
|
-
throw new Error(`Invalid redaction path (${
|
|
7106
|
+
if (path74.includes("..")) {
|
|
7107
|
+
throw new Error(`Invalid redaction path (${path74})`);
|
|
7099
7108
|
}
|
|
7100
|
-
if (
|
|
7101
|
-
throw new Error(`Invalid redaction path (${
|
|
7109
|
+
if (path74.includes(",")) {
|
|
7110
|
+
throw new Error(`Invalid redaction path (${path74})`);
|
|
7102
7111
|
}
|
|
7103
7112
|
let bracketCount = 0;
|
|
7104
7113
|
let inQuotes = false;
|
|
7105
7114
|
let quoteChar = "";
|
|
7106
|
-
for (let i = 0; i <
|
|
7107
|
-
const char =
|
|
7115
|
+
for (let i = 0; i < path74.length; i++) {
|
|
7116
|
+
const char = path74[i];
|
|
7108
7117
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
7109
7118
|
if (!inQuotes) {
|
|
7110
7119
|
inQuotes = true;
|
|
@@ -7118,20 +7127,20 @@ var require_redact = __commonJS({
|
|
|
7118
7127
|
} else if (char === "]" && !inQuotes) {
|
|
7119
7128
|
bracketCount--;
|
|
7120
7129
|
if (bracketCount < 0) {
|
|
7121
|
-
throw new Error(`Invalid redaction path (${
|
|
7130
|
+
throw new Error(`Invalid redaction path (${path74})`);
|
|
7122
7131
|
}
|
|
7123
7132
|
}
|
|
7124
7133
|
}
|
|
7125
7134
|
if (bracketCount !== 0) {
|
|
7126
|
-
throw new Error(`Invalid redaction path (${
|
|
7135
|
+
throw new Error(`Invalid redaction path (${path74})`);
|
|
7127
7136
|
}
|
|
7128
7137
|
}
|
|
7129
7138
|
function validatePaths(paths) {
|
|
7130
7139
|
if (!Array.isArray(paths)) {
|
|
7131
7140
|
throw new TypeError("paths must be an array");
|
|
7132
7141
|
}
|
|
7133
|
-
for (const
|
|
7134
|
-
validatePath(
|
|
7142
|
+
for (const path74 of paths) {
|
|
7143
|
+
validatePath(path74);
|
|
7135
7144
|
}
|
|
7136
7145
|
}
|
|
7137
7146
|
function slowRedact(options = {}) {
|
|
@@ -7299,8 +7308,8 @@ var require_redaction = __commonJS({
|
|
|
7299
7308
|
if (shape[k2] === null) {
|
|
7300
7309
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
7301
7310
|
} else {
|
|
7302
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
7303
|
-
return censor(value, [k2, ...
|
|
7311
|
+
const wrappedCensor = typeof censor === "function" ? (value, path74) => {
|
|
7312
|
+
return censor(value, [k2, ...path74]);
|
|
7304
7313
|
} : censor;
|
|
7305
7314
|
o[k2] = Redact({
|
|
7306
7315
|
paths: shape[k2],
|
|
@@ -7518,10 +7527,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
7518
7527
|
var require_sonic_boom = __commonJS({
|
|
7519
7528
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7520
7529
|
"use strict";
|
|
7521
|
-
var
|
|
7530
|
+
var fs66 = require("fs");
|
|
7522
7531
|
var EventEmitter3 = require("events");
|
|
7523
7532
|
var inherits = require("util").inherits;
|
|
7524
|
-
var
|
|
7533
|
+
var path74 = require("path");
|
|
7525
7534
|
var sleep2 = require_atomic_sleep();
|
|
7526
7535
|
var assert = require("assert");
|
|
7527
7536
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -7575,20 +7584,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7575
7584
|
const mode = sonic.mode;
|
|
7576
7585
|
if (sonic.sync) {
|
|
7577
7586
|
try {
|
|
7578
|
-
if (sonic.mkdir)
|
|
7579
|
-
const fd =
|
|
7587
|
+
if (sonic.mkdir) fs66.mkdirSync(path74.dirname(file), { recursive: true });
|
|
7588
|
+
const fd = fs66.openSync(file, flags, mode);
|
|
7580
7589
|
fileOpened(null, fd);
|
|
7581
7590
|
} catch (err) {
|
|
7582
7591
|
fileOpened(err);
|
|
7583
7592
|
throw err;
|
|
7584
7593
|
}
|
|
7585
7594
|
} else if (sonic.mkdir) {
|
|
7586
|
-
|
|
7595
|
+
fs66.mkdir(path74.dirname(file), { recursive: true }, (err) => {
|
|
7587
7596
|
if (err) return fileOpened(err);
|
|
7588
|
-
|
|
7597
|
+
fs66.open(file, flags, mode, fileOpened);
|
|
7589
7598
|
});
|
|
7590
7599
|
} else {
|
|
7591
|
-
|
|
7600
|
+
fs66.open(file, flags, mode, fileOpened);
|
|
7592
7601
|
}
|
|
7593
7602
|
}
|
|
7594
7603
|
function SonicBoom(opts) {
|
|
@@ -7629,8 +7638,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7629
7638
|
this.flush = flushBuffer;
|
|
7630
7639
|
this.flushSync = flushBufferSync;
|
|
7631
7640
|
this._actualWrite = actualWriteBuffer;
|
|
7632
|
-
fsWriteSync = () =>
|
|
7633
|
-
fsWrite = () =>
|
|
7641
|
+
fsWriteSync = () => fs66.writeSync(this.fd, this._writingBuf);
|
|
7642
|
+
fsWrite = () => fs66.write(this.fd, this._writingBuf, this.release);
|
|
7634
7643
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7635
7644
|
this._writingBuf = "";
|
|
7636
7645
|
this.write = write;
|
|
@@ -7639,15 +7648,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7639
7648
|
this._actualWrite = actualWrite;
|
|
7640
7649
|
fsWriteSync = () => {
|
|
7641
7650
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7642
|
-
return
|
|
7651
|
+
return fs66.writeSync(this.fd, this._writingBuf);
|
|
7643
7652
|
}
|
|
7644
|
-
return
|
|
7653
|
+
return fs66.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7645
7654
|
};
|
|
7646
7655
|
fsWrite = () => {
|
|
7647
7656
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7648
|
-
return
|
|
7657
|
+
return fs66.write(this.fd, this._writingBuf, this.release);
|
|
7649
7658
|
}
|
|
7650
|
-
return
|
|
7659
|
+
return fs66.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7651
7660
|
};
|
|
7652
7661
|
} else {
|
|
7653
7662
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7704,7 +7713,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7704
7713
|
}
|
|
7705
7714
|
}
|
|
7706
7715
|
if (this._fsync) {
|
|
7707
|
-
|
|
7716
|
+
fs66.fsyncSync(this.fd);
|
|
7708
7717
|
}
|
|
7709
7718
|
const len = this._len;
|
|
7710
7719
|
if (this._reopening) {
|
|
@@ -7818,7 +7827,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7818
7827
|
const onDrain = () => {
|
|
7819
7828
|
if (!this._fsync) {
|
|
7820
7829
|
try {
|
|
7821
|
-
|
|
7830
|
+
fs66.fsync(this.fd, (err) => {
|
|
7822
7831
|
this._flushPending = false;
|
|
7823
7832
|
cb(err);
|
|
7824
7833
|
});
|
|
@@ -7920,7 +7929,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7920
7929
|
const fd = this.fd;
|
|
7921
7930
|
this.once("ready", () => {
|
|
7922
7931
|
if (fd !== this.fd) {
|
|
7923
|
-
|
|
7932
|
+
fs66.close(fd, (err) => {
|
|
7924
7933
|
if (err) {
|
|
7925
7934
|
return this.emit("error", err);
|
|
7926
7935
|
}
|
|
@@ -7969,7 +7978,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7969
7978
|
buf = this._bufs[0];
|
|
7970
7979
|
}
|
|
7971
7980
|
try {
|
|
7972
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7981
|
+
const n = Buffer.isBuffer(buf) ? fs66.writeSync(this.fd, buf) : fs66.writeSync(this.fd, buf, "utf8");
|
|
7973
7982
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7974
7983
|
buf = releasedBufObj.writingBuf;
|
|
7975
7984
|
this._len = releasedBufObj.len;
|
|
@@ -7985,7 +7994,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7985
7994
|
}
|
|
7986
7995
|
}
|
|
7987
7996
|
try {
|
|
7988
|
-
|
|
7997
|
+
fs66.fsyncSync(this.fd);
|
|
7989
7998
|
} catch {
|
|
7990
7999
|
}
|
|
7991
8000
|
}
|
|
@@ -8006,7 +8015,7 @@ var require_sonic_boom = __commonJS({
|
|
|
8006
8015
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
8007
8016
|
}
|
|
8008
8017
|
try {
|
|
8009
|
-
const n =
|
|
8018
|
+
const n = fs66.writeSync(this.fd, buf);
|
|
8010
8019
|
buf = buf.subarray(n);
|
|
8011
8020
|
this._len = Math.max(this._len - n, 0);
|
|
8012
8021
|
if (buf.length <= 0) {
|
|
@@ -8034,13 +8043,13 @@ var require_sonic_boom = __commonJS({
|
|
|
8034
8043
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
8035
8044
|
if (this.sync) {
|
|
8036
8045
|
try {
|
|
8037
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
8046
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs66.writeSync(this.fd, this._writingBuf) : fs66.writeSync(this.fd, this._writingBuf, "utf8");
|
|
8038
8047
|
release(null, written);
|
|
8039
8048
|
} catch (err) {
|
|
8040
8049
|
release(err);
|
|
8041
8050
|
}
|
|
8042
8051
|
} else {
|
|
8043
|
-
|
|
8052
|
+
fs66.write(this.fd, this._writingBuf, release);
|
|
8044
8053
|
}
|
|
8045
8054
|
}
|
|
8046
8055
|
function actualWriteBuffer() {
|
|
@@ -8049,7 +8058,7 @@ var require_sonic_boom = __commonJS({
|
|
|
8049
8058
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
8050
8059
|
if (this.sync) {
|
|
8051
8060
|
try {
|
|
8052
|
-
const written =
|
|
8061
|
+
const written = fs66.writeSync(this.fd, this._writingBuf);
|
|
8053
8062
|
release(null, written);
|
|
8054
8063
|
} catch (err) {
|
|
8055
8064
|
release(err);
|
|
@@ -8058,7 +8067,7 @@ var require_sonic_boom = __commonJS({
|
|
|
8058
8067
|
if (kCopyBuffer) {
|
|
8059
8068
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
8060
8069
|
}
|
|
8061
|
-
|
|
8070
|
+
fs66.write(this.fd, this._writingBuf, release);
|
|
8062
8071
|
}
|
|
8063
8072
|
}
|
|
8064
8073
|
function actualClose(sonic) {
|
|
@@ -8074,12 +8083,12 @@ var require_sonic_boom = __commonJS({
|
|
|
8074
8083
|
sonic._lens = [];
|
|
8075
8084
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
8076
8085
|
try {
|
|
8077
|
-
|
|
8086
|
+
fs66.fsync(sonic.fd, closeWrapped);
|
|
8078
8087
|
} catch {
|
|
8079
8088
|
}
|
|
8080
8089
|
function closeWrapped() {
|
|
8081
8090
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
8082
|
-
|
|
8091
|
+
fs66.close(sonic.fd, done);
|
|
8083
8092
|
} else {
|
|
8084
8093
|
done();
|
|
8085
8094
|
}
|
|
@@ -11214,11 +11223,11 @@ var init_lib = __esm({
|
|
|
11214
11223
|
}
|
|
11215
11224
|
}
|
|
11216
11225
|
},
|
|
11217
|
-
addToPath: function addToPath(
|
|
11218
|
-
var last =
|
|
11226
|
+
addToPath: function addToPath(path74, added, removed, oldPosInc, options) {
|
|
11227
|
+
var last = path74.lastComponent;
|
|
11219
11228
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
11220
11229
|
return {
|
|
11221
|
-
oldPos:
|
|
11230
|
+
oldPos: path74.oldPos + oldPosInc,
|
|
11222
11231
|
lastComponent: {
|
|
11223
11232
|
count: last.count + 1,
|
|
11224
11233
|
added,
|
|
@@ -11228,7 +11237,7 @@ var init_lib = __esm({
|
|
|
11228
11237
|
};
|
|
11229
11238
|
} else {
|
|
11230
11239
|
return {
|
|
11231
|
-
oldPos:
|
|
11240
|
+
oldPos: path74.oldPos + oldPosInc,
|
|
11232
11241
|
lastComponent: {
|
|
11233
11242
|
count: 1,
|
|
11234
11243
|
added,
|
|
@@ -11737,10 +11746,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11737
11746
|
const memories = raw.map((m2) => {
|
|
11738
11747
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11739
11748
|
const rec3 = m2;
|
|
11740
|
-
const
|
|
11749
|
+
const path74 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11741
11750
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11742
|
-
if (!
|
|
11743
|
-
const entry = { path:
|
|
11751
|
+
if (!path74 || content == null) return null;
|
|
11752
|
+
const entry = { path: path74, content };
|
|
11744
11753
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11745
11754
|
return entry;
|
|
11746
11755
|
}).filter((m2) => m2 !== null);
|
|
@@ -12543,10 +12552,10 @@ function parseAttachment(obj) {
|
|
|
12543
12552
|
const memories = raw.map((m2) => {
|
|
12544
12553
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12545
12554
|
const rec3 = m2;
|
|
12546
|
-
const
|
|
12555
|
+
const path74 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12547
12556
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12548
|
-
if (!
|
|
12549
|
-
const out = { path:
|
|
12557
|
+
if (!path74 || content == null) return null;
|
|
12558
|
+
const out = { path: path74, content };
|
|
12550
12559
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12551
12560
|
return out;
|
|
12552
12561
|
}).filter((m2) => m2 !== null);
|
|
@@ -33515,8 +33524,8 @@ var require_utils = __commonJS({
|
|
|
33515
33524
|
var result = transform[inputType][outputType](input);
|
|
33516
33525
|
return result;
|
|
33517
33526
|
};
|
|
33518
|
-
exports2.resolve = function(
|
|
33519
|
-
var parts =
|
|
33527
|
+
exports2.resolve = function(path74) {
|
|
33528
|
+
var parts = path74.split("/");
|
|
33520
33529
|
var result = [];
|
|
33521
33530
|
for (var index = 0; index < parts.length; index++) {
|
|
33522
33531
|
var part = parts[index];
|
|
@@ -39369,18 +39378,18 @@ var require_object = __commonJS({
|
|
|
39369
39378
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
39370
39379
|
this.files[name] = object;
|
|
39371
39380
|
};
|
|
39372
|
-
var parentFolder = function(
|
|
39373
|
-
if (
|
|
39374
|
-
|
|
39381
|
+
var parentFolder = function(path74) {
|
|
39382
|
+
if (path74.slice(-1) === "/") {
|
|
39383
|
+
path74 = path74.substring(0, path74.length - 1);
|
|
39375
39384
|
}
|
|
39376
|
-
var lastSlash =
|
|
39377
|
-
return lastSlash > 0 ?
|
|
39385
|
+
var lastSlash = path74.lastIndexOf("/");
|
|
39386
|
+
return lastSlash > 0 ? path74.substring(0, lastSlash) : "";
|
|
39378
39387
|
};
|
|
39379
|
-
var forceTrailingSlash = function(
|
|
39380
|
-
if (
|
|
39381
|
-
|
|
39388
|
+
var forceTrailingSlash = function(path74) {
|
|
39389
|
+
if (path74.slice(-1) !== "/") {
|
|
39390
|
+
path74 += "/";
|
|
39382
39391
|
}
|
|
39383
|
-
return
|
|
39392
|
+
return path74;
|
|
39384
39393
|
};
|
|
39385
39394
|
var folderAdd = function(name, createFolders) {
|
|
39386
39395
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -40382,7 +40391,7 @@ var require_lib3 = __commonJS({
|
|
|
40382
40391
|
// src/run-case/recorder.ts
|
|
40383
40392
|
function startRunCaseRecorder(opts) {
|
|
40384
40393
|
const now = opts.now ?? Date.now;
|
|
40385
|
-
const dir =
|
|
40394
|
+
const dir = import_node_path62.default.dirname(opts.recordPath);
|
|
40386
40395
|
let stream = null;
|
|
40387
40396
|
let closing = false;
|
|
40388
40397
|
let closedSettled = false;
|
|
@@ -40396,8 +40405,8 @@ function startRunCaseRecorder(opts) {
|
|
|
40396
40405
|
});
|
|
40397
40406
|
const ensureStream = () => {
|
|
40398
40407
|
if (stream) return stream;
|
|
40399
|
-
|
|
40400
|
-
stream =
|
|
40408
|
+
import_node_fs47.default.mkdirSync(dir, { recursive: true });
|
|
40409
|
+
stream = import_node_fs47.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
40401
40410
|
stream.on("close", () => closedResolve());
|
|
40402
40411
|
return stream;
|
|
40403
40412
|
};
|
|
@@ -40422,12 +40431,12 @@ function startRunCaseRecorder(opts) {
|
|
|
40422
40431
|
};
|
|
40423
40432
|
return { tap, close, closed };
|
|
40424
40433
|
}
|
|
40425
|
-
var
|
|
40434
|
+
var import_node_fs47, import_node_path62;
|
|
40426
40435
|
var init_recorder = __esm({
|
|
40427
40436
|
"src/run-case/recorder.ts"() {
|
|
40428
40437
|
"use strict";
|
|
40429
|
-
|
|
40430
|
-
|
|
40438
|
+
import_node_fs47 = __toESM(require("fs"), 1);
|
|
40439
|
+
import_node_path62 = __toESM(require("path"), 1);
|
|
40431
40440
|
}
|
|
40432
40441
|
});
|
|
40433
40442
|
|
|
@@ -40470,7 +40479,7 @@ var init_wire = __esm({
|
|
|
40470
40479
|
// src/run-case/controller.ts
|
|
40471
40480
|
async function runController(opts) {
|
|
40472
40481
|
const now = opts.now ?? Date.now;
|
|
40473
|
-
const cwd = opts.cwd ?? (0,
|
|
40482
|
+
const cwd = opts.cwd ?? (0, import_node_fs48.mkdtempSync)(import_node_path63.default.join(import_node_os23.default.tmpdir(), "clawd-runcase-"));
|
|
40474
40483
|
const ownsCwd = opts.cwd === void 0;
|
|
40475
40484
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
40476
40485
|
const spawnCtx = { cwd };
|
|
@@ -40631,19 +40640,19 @@ async function runController(opts) {
|
|
|
40631
40640
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
40632
40641
|
if (ownsCwd) {
|
|
40633
40642
|
try {
|
|
40634
|
-
(0,
|
|
40643
|
+
(0, import_node_fs48.rmSync)(cwd, { recursive: true, force: true });
|
|
40635
40644
|
} catch {
|
|
40636
40645
|
}
|
|
40637
40646
|
}
|
|
40638
40647
|
return exitCode ?? 0;
|
|
40639
40648
|
}
|
|
40640
|
-
var
|
|
40649
|
+
var import_node_fs48, import_node_os23, import_node_path63;
|
|
40641
40650
|
var init_controller = __esm({
|
|
40642
40651
|
"src/run-case/controller.ts"() {
|
|
40643
40652
|
"use strict";
|
|
40644
|
-
|
|
40653
|
+
import_node_fs48 = require("fs");
|
|
40645
40654
|
import_node_os23 = __toESM(require("os"), 1);
|
|
40646
|
-
|
|
40655
|
+
import_node_path63 = __toESM(require("path"), 1);
|
|
40647
40656
|
init_claude();
|
|
40648
40657
|
init_stdout_splitter();
|
|
40649
40658
|
init_permission_stdio();
|
|
@@ -40905,8 +40914,8 @@ Env (advanced):
|
|
|
40905
40914
|
`;
|
|
40906
40915
|
|
|
40907
40916
|
// src/index.ts
|
|
40908
|
-
var
|
|
40909
|
-
var
|
|
40917
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
40918
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
40910
40919
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
40911
40920
|
|
|
40912
40921
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -41909,23 +41918,27 @@ var ATTACHMENT_SHARING_HINT = `## \u628A\u4EA7\u51FA\u6587\u4EF6\u5206\u4EAB\u7E
|
|
|
41909
41918
|
|
|
41910
41919
|
- \`relPath\` \u5FC5\u987B\u4F20**\u7EDD\u5BF9\u8DEF\u5F84**\uFF08\u4F60\u4EA7\u51FA\u6587\u4EF6\u7684\u771F\u5B9E\u8DEF\u5F84\uFF09\uFF0C\u4E0D\u8981\u4F20\u76F8\u5BF9\u8DEF\u5F84\u3002
|
|
41911
41920
|
- \u53EA\u80FD\u5206\u4EAB\u4F60\u81EA\u5DF1\u5DE5\u4F5C\u76EE\u5F55\u5185\u7684\u6587\u4EF6\uFF0C\u8D8A\u754C\u4F1A\u88AB\u62D2\u3002
|
|
41912
|
-
- \u88AB dispatch \u63A5\u5230\u4EFB\u52A1\u3001\u8981\u56DE\u4F20\u4EA7\u7269\u65F6\uFF1A\u628A\u7B7E\u540D URL \u5199\u8FDB \`personaDispatchComplete\` \u7684 \`text\` \u91CC\uFF08\`filePaths\` \u53EA\u662F\u4F60\u672C\u673A\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u8DE8\u8BBE\u5907\u5BF9\u65B9\u6253\u4E0D\u5F00\uFF0CURL \u624D\u80FD\u6253\u5F00\uFF09\u3002`;
|
|
41921
|
+
- \u88AB dispatch \u63A5\u5230\u4EFB\u52A1\u3001\u8981\u56DE\u4F20\u4EA7\u7269\u65F6\uFF1A\u628A\u7B7E\u540D URL \u5199\u8FDB \`personaDispatchComplete\` tool\uFF08\`clawd-dispatch\` MCP\uFF09\u7684 \`text\` \u91CC\uFF08\`filePaths\` \u53EA\u662F\u4F60\u672C\u673A\u7684\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u8DE8\u8BBE\u5907\u5BF9\u65B9\u6253\u4E0D\u5F00\uFF0CURL \u624D\u80FD\u6253\u5F00\uFF09\u3002`;
|
|
41913
41922
|
|
|
41914
41923
|
// src/dispatch/system-prompt.ts
|
|
41915
41924
|
var DISPATCH_SYSTEM_PROMPT_HINT = `## \u59D4\u6D3E\u7ED9\u53E6\u4E00\u4E2A persona\uFF08dispatch\uFF09
|
|
41916
41925
|
|
|
41917
|
-
\u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-app-builder\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 MCP
|
|
41926
|
+
\u5F53\u7528\u6237\u6D88\u606F\u91CC\u542B \`@persona/<id>\`\uFF08\u5982 \`@persona/persona-app-builder\`\uFF09\u65F6\uFF0C**\u4F60\u5FC5\u987B**\u7ACB\u5373\u8C03 \`clawd-dispatch\` MCP server \u7684 \`personaDispatch\` tool \u59D4\u6D3E\uFF08\u5404 agent \u5BF9 MCP tool \u7684\u5C55\u793A\u540D\u4E0D\u540C\uFF0C\u5982 claude \u663E\u793A\u4E3A \`mcp__clawd-dispatch__personaDispatch\`\uFF1B\u6309\u4F60\u73AF\u5883\u91CC\u5B9E\u9645\u5217\u51FA\u7684\u540D\u5B57\u8C03\u7528\uFF09\uFF0C\u4E0D\u8981\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF1A
|
|
41918
41927
|
|
|
41919
41928
|
- \`targetPersona = <id>\`\uFF08@ token \u91CC\u7684 persona id\uFF09
|
|
41920
41929
|
- \`prompt = \u53BB\u6389 @persona/<id> token \u7684\u7528\u6237\u539F\u6587\`
|
|
41921
41930
|
|
|
41922
|
-
tool \u4F1A**\u7ACB\u5373\u8FD4\u56DE** dispatchId\uFF08\u5F02\u6B65\u59D4\u6D3E\uFF09\uFF0C\u5BF9\u65B9\u4EBA\u683C\u5728\u540E\u53F0\u5E72\u6D3B\u3002\u4F60\u544A\u8BC9\u7528\u6237"\u4EFB\u52A1\u5DF2\u4EA4\u529E"\u5373\u53EF\u7ED3\u675F\u672C\u8F6E\u2014\u2014**\u4E0D\u8981\u7B49\u5F85\u3001\u4E0D\u8981\u8F6E\u8BE2**\u3002\u5BF9\u65B9\u5E72\u5B8C\u540E\uFF0C\u7ED3\u679C\u4F1A\u4F5C\u4E3A\u4E00\u6761\u65B0\u6D88\u606F\u81EA\u52A8\u6CE8\u5165\u56DE\u4F60\u7684 session\uFF0C\u4F60\u5C4A\u65F6\u518D\u7EFC\u5408\u8F6C\u8FBE\u7ED9\u7528\u6237\u3002\u60F3\u67E5\u8FDB\u5C55\u65F6\uFF08\u7528\u6237\u95EE\u8D77\uFF09\u8C03 \`
|
|
41931
|
+
tool \u4F1A**\u7ACB\u5373\u8FD4\u56DE** dispatchId\uFF08\u5F02\u6B65\u59D4\u6D3E\uFF09\uFF0C\u5BF9\u65B9\u4EBA\u683C\u5728\u540E\u53F0\u5E72\u6D3B\u3002\u4F60\u544A\u8BC9\u7528\u6237"\u4EFB\u52A1\u5DF2\u4EA4\u529E"\u5373\u53EF\u7ED3\u675F\u672C\u8F6E\u2014\u2014**\u4E0D\u8981\u7B49\u5F85\u3001\u4E0D\u8981\u8F6E\u8BE2**\u3002\u5BF9\u65B9\u5E72\u5B8C\u540E\uFF0C\u7ED3\u679C\u4F1A\u4F5C\u4E3A\u4E00\u6761\u65B0\u6D88\u606F\u81EA\u52A8\u6CE8\u5165\u56DE\u4F60\u7684 session\uFF0C\u4F60\u5C4A\u65F6\u518D\u7EFC\u5408\u8F6C\u8FBE\u7ED9\u7528\u6237\u3002\u60F3\u67E5\u8FDB\u5C55\u65F6\uFF08\u7528\u6237\u95EE\u8D77\uFF09\u8C03\u540C\u4E00 MCP \u7684 \`personaDispatchList\`\u3002
|
|
41923
41932
|
|
|
41924
41933
|
- **\u4E0D\u8981**\u5C1D\u8BD5\u81EA\u5DF1\u6267\u884C\uFF08\u4F60\u4E0D\u662F\u90A3\u4E2A persona\uFF09
|
|
41925
41934
|
- **\u4E0D\u8981** in-place \u6A21\u4EFF\u5BF9\u65B9\u4EBA\u683C \u2014\u2014 dispatch \u662F\u771F\u5207\u5230\u53E6\u4E00\u4E2A\u72EC\u7ACB session
|
|
41926
41935
|
- \u4E00\u53E5\u8BDD\u91CC\u591A\u4E2A \`@persona/<id>\` \u65F6\u9009\u7B2C\u4E00\u4E2A\uFF08tool \u4E00\u6B21\u53EA\u5904\u7406\u4E00\u4E2A target\uFF09
|
|
41927
41936
|
- \u59D4\u6D3E\u5931\u8D25\uFF08tool_result.is_error=true\uFF09\u65F6\u5982\u5B9E\u544A\u8BC9\u7528\u6237\u539F\u56E0\uFF0C**\u4E0D\u8981\u91CD\u8BD5**
|
|
41928
41937
|
|
|
41938
|
+
### \u7EED\u6D3E\uFF08\u540C\u4E00\u4EF6\u4E8B\u7684\u540E\u7EED\u6307\u4EE4\uFF09
|
|
41939
|
+
|
|
41940
|
+
\u7528\u6237\u5BF9\u4E00\u4EF6**\u5DF2\u59D4\u6D3E**\u7684\u4E8B\u4E0B\u540E\u7EED\u6307\u4EE4\u65F6\uFF0C\u8C03 \`personaDispatch({ dispatchId: <\u8BE5\u4E8B\u7684 dispatchId>, prompt: <\u65B0\u6307\u4EE4> })\`\uFF08targetPersona \u53EF\u7701\u7565\uFF09\u2014\u2014\u65B0\u6307\u4EE4\u4F1A\u8FDB\u5165\u539F worker session \u63A5\u7740\u5E72\uFF0C\u4E0A\u4E0B\u6587\u4E0D\u4E22\u3002dispatchId \u7528\u4F60\u9996\u6B21\u59D4\u6D3E\u65F6\u62FF\u5230\u7684\u90A3\u4E2A\uFF1B\u4E0D\u786E\u5B9A\u662F\u54EA\u4EF6\u4E8B\u5C31\u5148\u8C03 \`personaDispatchList\` \u67E5\u3002
|
|
41941
|
+
|
|
41929
41942
|
### \u8DE8\u8BBE\u5907\u59D4\u6D3E\uFF08remote persona\uFF09
|
|
41930
41943
|
|
|
41931
41944
|
\u5F53 @ token \u5F62\u5982 \`@persona/<id>@<deviceId>\`\uFF08\u7B2C\u4E8C\u6BB5\u662F\u8054\u7CFB\u4EBA**\u8BBE\u5907\u7684 deviceId**\uFF0CUI \u9009\u8054\u7CFB\u4EBA\u65F6\u5DF2\u89E3\u6790\u597D\u586B\u5165\uFF09\u65F6\uFF0C\u662F\u628A\u4EFB\u52A1\u59D4\u6D3E\u7ED9\u90A3\u53F0\u8BBE\u5907\u4E0A\u7684 persona\u3002\u9664 targetPersona / prompt \u5916\u518D\u5E26\u4E00\u4E2A\u53C2\u6570\uFF1A
|
|
@@ -41940,7 +41953,7 @@ deviceId \u76F4\u63A5\u53D6\u81EA token\uFF0C\u4E0D\u8981\u6539\u5199\u6216\u731
|
|
|
41940
41953
|
|
|
41941
41954
|
- \u4EFB\u52A1\u5728 \`Task:\` \u6BB5
|
|
41942
41955
|
- \u539F\u4F1A\u8BDD\u7684\u5BF9\u8BDD\u5386\u53F2\u5728 \`Source conversation\` \u6BB5\u7ED9\u7684 jsonl \u8DEF\u5F84\u4E0B\uFF1B\u6309\u9700 Read \u5B83\u4E86\u89E3\u4E0A\u4E0B\u6587\uFF08\u4E0D\u5FC5\u8BFB\u5B8C\uFF09
|
|
41943
|
-
- \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`
|
|
41956
|
+
- \u5E72\u5B8C\u540E**\u5FC5\u987B**\u8C03 \`clawd-dispatch\` MCP \u7684 \`personaDispatchComplete\` tool \u62A5\u544A\u7ED3\u679C\uFF1A
|
|
41944
41957
|
- \u6210\u529F\uFF1A\`{ text: "\u603B\u7ED3/\u7ED3\u8BBA", filePaths?: ["\u4F60\u4EA7\u51FA/\u6539\u7684\u6587\u4EF6\u7EDD\u5BF9\u8DEF\u5F84"] }\`
|
|
41945
41958
|
- \u5931\u8D25\uFF1A\`{ isFailure: true, reason: "..." }\`
|
|
41946
41959
|
- \u62A5\u544A\u5B8C\u540E\u4F60\u7684 session \u5C31\u7ED3\u675F\u4E86\uFF0C\u4E0D\u8981\u7EE7\u7EED\u8F93\u51FA`;
|
|
@@ -43340,7 +43353,8 @@ Source conversation (jsonl, CC stream-json format, one message per line):
|
|
|
43340
43353
|
${args.sourceJsonlPath}
|
|
43341
43354
|
You may read this file with your Read tool to understand context. You do not have to read it all.
|
|
43342
43355
|
|
|
43343
|
-
When done, call the
|
|
43356
|
+
When done, call the \`personaDispatchComplete\` tool from the \`clawd-dispatch\` MCP server with your result
|
|
43357
|
+
(tool display name varies by agent, e.g. \`mcp__clawd-dispatch__personaDispatchComplete\` in claude):
|
|
43344
43358
|
- Success: { text: "...", filePaths?: ["abs/path", ...] }
|
|
43345
43359
|
- Failure: { isFailure: true, reason: "..." }
|
|
43346
43360
|
|
|
@@ -43645,18 +43659,20 @@ var SessionManager = class {
|
|
|
43645
43659
|
`newRunner: guest session ${file.sessionId} \u7F3A personaRoot/userWorkDir\uFF0C\u65E0\u6CD5\u7269\u5316 OS \u6C99\u7BB1\uFF08\u62D2\u7EDD\u521B\u5EFA\u65E0\u6C99\u7BB1 guest\uFF09`
|
|
43646
43660
|
);
|
|
43647
43661
|
}
|
|
43648
|
-
|
|
43649
|
-
|
|
43650
|
-
|
|
43651
|
-
|
|
43652
|
-
|
|
43653
|
-
|
|
43654
|
-
|
|
43655
|
-
|
|
43656
|
-
|
|
43657
|
-
|
|
43662
|
+
if ((file.tool ?? "claude") === "claude") {
|
|
43663
|
+
const base = this.deps.personaStore?.readSandboxSettings(scope.personaId) ?? null;
|
|
43664
|
+
const sandboxSettings = composeGuestSandbox(base, subSessionMeta.userWorkDir, file.cwd);
|
|
43665
|
+
const ownerCreds = readOwnerCredentials(import_node_os5.default.homedir(), this.deps.logger);
|
|
43666
|
+
const merged = mergeOwnerCredentials(sandboxSettings, ownerCreds);
|
|
43667
|
+
if (ownerCreds) {
|
|
43668
|
+
this.deps.logger?.info("owner credentials injected into guest spawn", {
|
|
43669
|
+
sessionId: file.sessionId,
|
|
43670
|
+
envKeys: ownerCreds.env ? Object.keys(ownerCreds.env) : [],
|
|
43671
|
+
apiKeyHelper: ownerCreds.apiKeyHelper ? "present" : "absent"
|
|
43672
|
+
});
|
|
43673
|
+
}
|
|
43674
|
+
subSessionMeta.extraSettings = JSON.stringify(merged);
|
|
43658
43675
|
}
|
|
43659
|
-
subSessionMeta.extraSettings = JSON.stringify(merged);
|
|
43660
43676
|
const home = import_node_os5.default.homedir();
|
|
43661
43677
|
const expand = (p2) => p2 === "~" ? home : p2.startsWith("~/") ? import_node_path9.default.join(home, p2.slice(2)) : p2;
|
|
43662
43678
|
const codexCfg = this.deps.personaStore?.readCodexSandboxSettings(scope.personaId) ?? null;
|
|
@@ -44135,9 +44151,25 @@ var SessionManager = class {
|
|
|
44135
44151
|
if (pending.length === 0) return;
|
|
44136
44152
|
const state = this.tryGetState(sourceSessionId);
|
|
44137
44153
|
if (state && compressStatus(state.status) === "running") return;
|
|
44154
|
+
if (!this.injectIntoSession(sourceSessionId, formatDeliveryText(pending))) return;
|
|
44155
|
+
const nowIso3 = new Date(this.deps.now?.() ?? Date.now()).toISOString();
|
|
44156
|
+
for (const r of pending) store.update(r.dispatchId, { deliveredAt: nowIso3 });
|
|
44157
|
+
this.deps.logger?.info("dispatch.deliver.ok", {
|
|
44158
|
+
sourceSessionId,
|
|
44159
|
+
count: pending.length,
|
|
44160
|
+
dispatchIds: pending.map((r) => r.dispatchId)
|
|
44161
|
+
});
|
|
44162
|
+
}
|
|
44163
|
+
/**
|
|
44164
|
+
* 把一段 plain text 以 owner sender 注入指定 session 当新 turn——dispatch 结果投递
|
|
44165
|
+
* (deliverPending)与续派任务包(handlers/persona-dispatch 经 sendFollowUp 闭包)共用。
|
|
44166
|
+
* session 文件不存在或 send 抛错 → false(记 log,不 throw)。直接 runner.input
|
|
44167
|
+
* (无 collector),frames 经 routeFromRunner 正常广播上 wire。
|
|
44168
|
+
*/
|
|
44169
|
+
injectIntoSession(sessionId, text) {
|
|
44138
44170
|
if (!this.deps.ownerPrincipalId) {
|
|
44139
|
-
this.deps.logger?.warn("dispatch.
|
|
44140
|
-
return;
|
|
44171
|
+
this.deps.logger?.warn("dispatch.inject.no-owner-principal", { sessionId });
|
|
44172
|
+
return false;
|
|
44141
44173
|
}
|
|
44142
44174
|
const sender = principalToSender(
|
|
44143
44175
|
makeOwnerPrincipal(
|
|
@@ -44147,34 +44179,24 @@ var SessionManager = class {
|
|
|
44147
44179
|
)
|
|
44148
44180
|
);
|
|
44149
44181
|
try {
|
|
44150
|
-
const file = this.findOwnedSession(
|
|
44182
|
+
const file = this.findOwnedSession(sessionId);
|
|
44151
44183
|
if (!file) {
|
|
44152
|
-
this.deps.logger?.info("dispatch.
|
|
44153
|
-
return;
|
|
44184
|
+
this.deps.logger?.info("dispatch.inject.session-gone", { sessionId });
|
|
44185
|
+
return false;
|
|
44154
44186
|
}
|
|
44155
44187
|
const runner = this.ensureRunnerForScope(file, this.scopeForFile(file));
|
|
44156
44188
|
runner.input({
|
|
44157
44189
|
kind: "command",
|
|
44158
|
-
command: {
|
|
44159
|
-
kind: "send",
|
|
44160
|
-
text: formatDeliveryText(pending),
|
|
44161
|
-
senderPrincipal: sender
|
|
44162
|
-
}
|
|
44190
|
+
command: { kind: "send", text, senderPrincipal: sender }
|
|
44163
44191
|
});
|
|
44192
|
+
return true;
|
|
44164
44193
|
} catch (err) {
|
|
44165
|
-
this.deps.logger?.warn("dispatch.
|
|
44166
|
-
|
|
44194
|
+
this.deps.logger?.warn("dispatch.inject.send-failed", {
|
|
44195
|
+
sessionId,
|
|
44167
44196
|
reason: err instanceof Error ? err.message : String(err)
|
|
44168
44197
|
});
|
|
44169
|
-
return;
|
|
44198
|
+
return false;
|
|
44170
44199
|
}
|
|
44171
|
-
const nowIso3 = new Date(this.deps.now?.() ?? Date.now()).toISOString();
|
|
44172
|
-
for (const r of pending) store.update(r.dispatchId, { deliveredAt: nowIso3 });
|
|
44173
|
-
this.deps.logger?.info("dispatch.deliver.ok", {
|
|
44174
|
-
sourceSessionId,
|
|
44175
|
-
count: pending.length,
|
|
44176
|
-
dispatchIds: pending.map((r) => r.dispatchId)
|
|
44177
|
-
});
|
|
44178
44200
|
}
|
|
44179
44201
|
/**
|
|
44180
44202
|
* 只读拿 SessionState;session 不存在返 null(不 throw)。
|
|
@@ -44700,7 +44722,9 @@ var SessionManager = class {
|
|
|
44700
44722
|
const file = {
|
|
44701
44723
|
sessionId,
|
|
44702
44724
|
cwd,
|
|
44703
|
-
tool
|
|
44725
|
+
// dispatch B session 跟随 persona 绑定的 tool(codex persona 用 codex spawn),
|
|
44726
|
+
// 与 UI 手建路径(handlers/session.ts create 的 persona.tool 优先)同语义
|
|
44727
|
+
tool: this.deps.getPersonaTool?.(args.targetPersona) ?? "claude",
|
|
44704
44728
|
ownerPersonaId: args.targetPersona,
|
|
44705
44729
|
dispatchedFromSessionId: args.sourceSessionId,
|
|
44706
44730
|
// 跨设备显示关键(spec §8):creatorPrincipalId = A 的 deviceId,让 A 的
|
|
@@ -44790,7 +44814,8 @@ var SessionManager = class {
|
|
|
44790
44814
|
const file = {
|
|
44791
44815
|
sessionId,
|
|
44792
44816
|
cwd,
|
|
44793
|
-
tool
|
|
44817
|
+
// shift 定时 spawn 同样跟随 persona 绑定 tool(对齐 dispatch B session)
|
|
44818
|
+
tool: this.deps.getPersonaTool?.(args.targetPersona) ?? "claude",
|
|
44794
44819
|
ownerPersonaId: args.targetPersona,
|
|
44795
44820
|
...args.sourceSessionId ? { shiftFiredFromSessionId: args.sourceSessionId } : {},
|
|
44796
44821
|
createdAt: now,
|
|
@@ -46166,6 +46191,9 @@ function refreshDaemonManagedDirs(args) {
|
|
|
46166
46191
|
const dstPath = path14.join(personaDir, relPath);
|
|
46167
46192
|
try {
|
|
46168
46193
|
fs12.cpSync(srcPath, dstPath, { recursive: true, force: true, dereference: true, filter: skipNodeModulesUnder(srcPath) });
|
|
46194
|
+
if (relPath === "CLAUDE.md") {
|
|
46195
|
+
fs12.cpSync(srcPath, path14.join(personaDir, "AGENTS.md"), { force: true, dereference: true });
|
|
46196
|
+
}
|
|
46169
46197
|
args.logger.info("persona.refresh.synced", {
|
|
46170
46198
|
personaId: entry.personaId,
|
|
46171
46199
|
path: relPath
|
|
@@ -46533,11 +46561,12 @@ function createVisitorStore(opts) {
|
|
|
46533
46561
|
init_claude();
|
|
46534
46562
|
|
|
46535
46563
|
// src/tools/codex.ts
|
|
46536
|
-
var
|
|
46537
|
-
var
|
|
46564
|
+
var import_node_child_process5 = require("child_process");
|
|
46565
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
46538
46566
|
|
|
46539
46567
|
// src/tools/codex-session.ts
|
|
46540
|
-
var
|
|
46568
|
+
var import_node_child_process4 = require("child_process");
|
|
46569
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
46541
46570
|
|
|
46542
46571
|
// src/tools/codex-app-server-client.ts
|
|
46543
46572
|
var import_node_readline = require("readline");
|
|
@@ -46720,7 +46749,7 @@ function resolveApprovalPolicy(ctx) {
|
|
|
46720
46749
|
if (m2 === "untrusted" || m2 === "on-failure" || m2 === "on-request" || m2 === "never") return m2;
|
|
46721
46750
|
return "on-request";
|
|
46722
46751
|
}
|
|
46723
|
-
function buildCodexGuestConfig(cs) {
|
|
46752
|
+
function buildCodexGuestConfig(cs, opts = {}) {
|
|
46724
46753
|
const filesystem = {};
|
|
46725
46754
|
for (const w2 of cs.writableRoots ?? []) filesystem[w2] = "write";
|
|
46726
46755
|
const deny = cs.denyRead ?? [];
|
|
@@ -46735,7 +46764,7 @@ function buildCodexGuestConfig(cs) {
|
|
|
46735
46764
|
clawos_guest: {
|
|
46736
46765
|
extends: ":workspace",
|
|
46737
46766
|
filesystem,
|
|
46738
|
-
network: cs.network ? { enabled: true, domains: { "*": "allow" } } : { enabled: false }
|
|
46767
|
+
network: cs.network ? { enabled: true, domains: { "*": "allow" } } : opts.loopbackDaemonAccess ? { enabled: true, allowed_domains: [], allow_local_binding: true } : { enabled: false }
|
|
46739
46768
|
}
|
|
46740
46769
|
}
|
|
46741
46770
|
};
|
|
@@ -46749,15 +46778,32 @@ function tomlValue(v2) {
|
|
|
46749
46778
|
}
|
|
46750
46779
|
return JSON.stringify(v2);
|
|
46751
46780
|
}
|
|
46752
|
-
function codexGuestCliArgs(cs) {
|
|
46753
|
-
const cfg = buildCodexGuestConfig(cs);
|
|
46781
|
+
function codexGuestCliArgs(cs, opts = {}) {
|
|
46782
|
+
const cfg = buildCodexGuestConfig(cs, opts);
|
|
46754
46783
|
const profile = cfg.permissions.clawos_guest;
|
|
46755
|
-
|
|
46784
|
+
const args = [
|
|
46756
46785
|
"-c",
|
|
46757
46786
|
`default_permissions=${tomlValue("clawos_guest")}`,
|
|
46758
46787
|
"-c",
|
|
46759
46788
|
`permissions.clawos_guest=${tomlValue(profile)}`
|
|
46760
46789
|
];
|
|
46790
|
+
if (!cs.network && opts.loopbackDaemonAccess) {
|
|
46791
|
+
args.push("-c", "features.network_proxy=true");
|
|
46792
|
+
}
|
|
46793
|
+
return args;
|
|
46794
|
+
}
|
|
46795
|
+
function codexMcpCliArgs(defs) {
|
|
46796
|
+
const out = [];
|
|
46797
|
+
for (const d of defs) {
|
|
46798
|
+
const cfg = {
|
|
46799
|
+
command: d.command,
|
|
46800
|
+
...d.args && d.args.length > 0 ? { args: d.args } : {},
|
|
46801
|
+
...d.env && Object.keys(d.env).length > 0 ? { env: d.env } : {}
|
|
46802
|
+
};
|
|
46803
|
+
const key = /^[A-Za-z0-9_-]+$/.test(d.name) ? d.name : JSON.stringify(d.name);
|
|
46804
|
+
out.push("-c", `mcp_servers.${key}=${tomlValue(cfg)}`);
|
|
46805
|
+
}
|
|
46806
|
+
return out;
|
|
46761
46807
|
}
|
|
46762
46808
|
function threadStartParams(ctx) {
|
|
46763
46809
|
const params = {
|
|
@@ -46782,8 +46828,8 @@ function turnStartInput(text) {
|
|
|
46782
46828
|
const items = [];
|
|
46783
46829
|
let leftover = text;
|
|
46784
46830
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
46785
|
-
const [marker, name,
|
|
46786
|
-
items.push({ type: "skill", name, path:
|
|
46831
|
+
const [marker, name, path74] = m2;
|
|
46832
|
+
items.push({ type: "skill", name, path: path74 });
|
|
46787
46833
|
leftover = leftover.replace(marker, "");
|
|
46788
46834
|
}
|
|
46789
46835
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -46798,15 +46844,122 @@ function turnStartInput(text) {
|
|
|
46798
46844
|
return items;
|
|
46799
46845
|
}
|
|
46800
46846
|
|
|
46847
|
+
// src/tools/codex-mcp-config.ts
|
|
46848
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
46849
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
46850
|
+
function loadCodexMcpServerDefs(args) {
|
|
46851
|
+
const out = [];
|
|
46852
|
+
const seen = /* @__PURE__ */ new Set();
|
|
46853
|
+
const sources = [...args.mcpConfigPaths, import_node_path15.default.join(args.cwd, ".mcp.json")];
|
|
46854
|
+
for (const file of sources) {
|
|
46855
|
+
let parsed;
|
|
46856
|
+
try {
|
|
46857
|
+
parsed = JSON.parse(import_node_fs17.default.readFileSync(file, "utf8"));
|
|
46858
|
+
} catch (e) {
|
|
46859
|
+
const code = e.code;
|
|
46860
|
+
if (code !== "ENOENT") {
|
|
46861
|
+
args.logger?.warn("codex mcp config unreadable, skipped", { file, code: code ?? "parse-error" });
|
|
46862
|
+
}
|
|
46863
|
+
continue;
|
|
46864
|
+
}
|
|
46865
|
+
const servers = parsed?.mcpServers;
|
|
46866
|
+
if (!servers || typeof servers !== "object") continue;
|
|
46867
|
+
for (const [name, raw] of Object.entries(servers)) {
|
|
46868
|
+
const def = raw ?? {};
|
|
46869
|
+
const type = typeof def.type === "string" ? def.type : "stdio";
|
|
46870
|
+
if (type !== "stdio") {
|
|
46871
|
+
args.logger?.warn("codex mcp server type unsupported, skipped", { file, name, type });
|
|
46872
|
+
continue;
|
|
46873
|
+
}
|
|
46874
|
+
if (typeof def.command !== "string" || !def.command) {
|
|
46875
|
+
args.logger?.warn("codex mcp server missing command, skipped", { file, name });
|
|
46876
|
+
continue;
|
|
46877
|
+
}
|
|
46878
|
+
if (seen.has(name)) {
|
|
46879
|
+
args.logger?.warn("codex mcp server name collision, first-wins", { file, name });
|
|
46880
|
+
continue;
|
|
46881
|
+
}
|
|
46882
|
+
seen.add(name);
|
|
46883
|
+
const fileEnv = def.env && typeof def.env === "object" ? Object.fromEntries(
|
|
46884
|
+
Object.entries(def.env).filter(
|
|
46885
|
+
(kv) => typeof kv[1] === "string"
|
|
46886
|
+
)
|
|
46887
|
+
) : {};
|
|
46888
|
+
const env = { ...args.baseEnv ?? {}, ...fileEnv };
|
|
46889
|
+
out.push({
|
|
46890
|
+
name,
|
|
46891
|
+
command: def.command,
|
|
46892
|
+
...Array.isArray(def.args) && def.args.every((a) => typeof a === "string") ? { args: def.args } : {},
|
|
46893
|
+
...Object.keys(env).length > 0 ? { env } : {}
|
|
46894
|
+
});
|
|
46895
|
+
}
|
|
46896
|
+
}
|
|
46897
|
+
return out;
|
|
46898
|
+
}
|
|
46899
|
+
|
|
46900
|
+
// src/tools/codex-features.ts
|
|
46901
|
+
var import_node_child_process3 = require("child_process");
|
|
46902
|
+
var cachedNetworkProxy;
|
|
46903
|
+
function hasNetworkProxyFeature(deps = {}) {
|
|
46904
|
+
if (cachedNetworkProxy !== void 0) return cachedNetworkProxy;
|
|
46905
|
+
try {
|
|
46906
|
+
const out = deps.execOverride ? deps.execOverride() : (0, import_node_child_process3.execFileSync)(process.env.CODEX_BIN ?? "codex", ["features", "list"], {
|
|
46907
|
+
encoding: "utf8",
|
|
46908
|
+
timeout: 3e3
|
|
46909
|
+
});
|
|
46910
|
+
const m2 = /^network_proxy\s+(.+?)\s+(?:true|false)\s*$/m.exec(out);
|
|
46911
|
+
cachedNetworkProxy = m2 !== null && m2[1].trim() !== "removed";
|
|
46912
|
+
} catch {
|
|
46913
|
+
cachedNetworkProxy = false;
|
|
46914
|
+
}
|
|
46915
|
+
return cachedNetworkProxy;
|
|
46916
|
+
}
|
|
46917
|
+
var warming = false;
|
|
46918
|
+
function warmCodexFeatureCache() {
|
|
46919
|
+
if (cachedNetworkProxy !== void 0 || warming) return;
|
|
46920
|
+
warming = true;
|
|
46921
|
+
(0, import_node_child_process3.execFile)(
|
|
46922
|
+
process.env.CODEX_BIN ?? "codex",
|
|
46923
|
+
["features", "list"],
|
|
46924
|
+
{ encoding: "utf8", timeout: 3e3 },
|
|
46925
|
+
(err, stdout) => {
|
|
46926
|
+
warming = false;
|
|
46927
|
+
if (cachedNetworkProxy !== void 0) return;
|
|
46928
|
+
if (err) {
|
|
46929
|
+
cachedNetworkProxy = false;
|
|
46930
|
+
return;
|
|
46931
|
+
}
|
|
46932
|
+
const m2 = /^network_proxy\s+(.+?)\s+(?:true|false)\s*$/m.exec(stdout);
|
|
46933
|
+
cachedNetworkProxy = m2 !== null && m2[1].trim() !== "removed";
|
|
46934
|
+
}
|
|
46935
|
+
);
|
|
46936
|
+
}
|
|
46937
|
+
|
|
46801
46938
|
// src/tools/codex-session.ts
|
|
46802
46939
|
function createCodexSession(ctx, sink, deps = {}) {
|
|
46803
46940
|
const cmd = process.env.CODEX_BIN ?? "codex";
|
|
46804
46941
|
const args = ["app-server", "--listen", "stdio://"];
|
|
46805
46942
|
if (ctx.personaMode === "guest" && ctx.codexSandbox) {
|
|
46806
|
-
|
|
46943
|
+
const loopbackDaemonAccess = deps.hasNetworkProxyOverride ? deps.hasNetworkProxyOverride() : hasNetworkProxyFeature();
|
|
46944
|
+
args.push(...codexGuestCliArgs(ctx.codexSandbox, { loopbackDaemonAccess }));
|
|
46807
46945
|
}
|
|
46946
|
+
const clawdEnv = Object.fromEntries(
|
|
46947
|
+
Object.entries(ctx.env ?? {}).filter(
|
|
46948
|
+
(kv) => kv[0].startsWith("CLAWD_") && typeof kv[1] === "string"
|
|
46949
|
+
)
|
|
46950
|
+
);
|
|
46951
|
+
args.push(
|
|
46952
|
+
...codexMcpCliArgs(
|
|
46953
|
+
loadCodexMcpServerDefs({
|
|
46954
|
+
mcpConfigPaths: (ctx.mcpConfigs ?? []).map((m2) => m2.path),
|
|
46955
|
+
cwd: ctx.cwd,
|
|
46956
|
+
baseEnv: clawdEnv,
|
|
46957
|
+
logger: deps.logger
|
|
46958
|
+
})
|
|
46959
|
+
)
|
|
46960
|
+
);
|
|
46808
46961
|
const env = { ...process.env, ...ctx.env };
|
|
46809
|
-
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0,
|
|
46962
|
+
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, ctx.cwd, env) : (0, import_node_child_process4.spawn)(cmd, args, { cwd: ctx.cwd, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
46810
46963
|
let threadId = ctx.toolSessionId;
|
|
46811
46964
|
let turnId;
|
|
46812
46965
|
const approvalIds = /* @__PURE__ */ new Map();
|
|
@@ -46863,6 +47016,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
46863
47016
|
capabilities: null
|
|
46864
47017
|
});
|
|
46865
47018
|
client.notify("initialized", {});
|
|
47019
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path16.default.join(ctx.cwd, ".claude", "skills")] }).catch((e) => deps.logger?.warn("codex skills/extraRoots/set failed", { message: e.message }));
|
|
46866
47020
|
if (threadId) {
|
|
46867
47021
|
await client.request("thread/resume", { threadId, ...threadStartParams(ctx) });
|
|
46868
47022
|
} else {
|
|
@@ -46909,6 +47063,7 @@ function createCodexSession(ctx, sink, deps = {}) {
|
|
|
46909
47063
|
}
|
|
46910
47064
|
|
|
46911
47065
|
// src/tools/codex.ts
|
|
47066
|
+
var CODEX_MODEL_IDS = ["gpt-5.5", "gpt-5.4", "gpt-5.4-mini"];
|
|
46912
47067
|
var CODEX_MODELS = [
|
|
46913
47068
|
{ id: "", label: "Default", description: "codex config.toml \u9ED8\u8BA4", contextWindowSize: 258400, default: true },
|
|
46914
47069
|
{ id: "gpt-5.5", label: "GPT-5.5", description: "Frontier model for complex coding", contextWindowSize: 258400 },
|
|
@@ -46967,10 +47122,10 @@ function sanitizeCodexModel(model) {
|
|
|
46967
47122
|
return CODEX_MODELS.some((m2) => m2.id === model) ? model : void 0;
|
|
46968
47123
|
}
|
|
46969
47124
|
async function probeCodex(env = process.env) {
|
|
46970
|
-
if (env.CODEX_BIN &&
|
|
47125
|
+
if (env.CODEX_BIN && import_node_fs18.default.existsSync(env.CODEX_BIN)) return { available: true, path: env.CODEX_BIN };
|
|
46971
47126
|
try {
|
|
46972
|
-
const out = (0,
|
|
46973
|
-
if (out &&
|
|
47127
|
+
const out = (0, import_node_child_process5.execFileSync)("which", ["codex"], { encoding: "utf8" }).trim();
|
|
47128
|
+
if (out && import_node_fs18.default.existsSync(out)) return { available: true, path: out };
|
|
46974
47129
|
} catch {
|
|
46975
47130
|
}
|
|
46976
47131
|
return { available: false };
|
|
@@ -47016,9 +47171,9 @@ var CodexAdapter = class {
|
|
|
47016
47171
|
|
|
47017
47172
|
// src/tools/claude-tui.ts
|
|
47018
47173
|
var import_node_crypto5 = require("crypto");
|
|
47019
|
-
var
|
|
47174
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
47020
47175
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
47021
|
-
var
|
|
47176
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
47022
47177
|
var import_headless = __toESM(require_xterm_headless(), 1);
|
|
47023
47178
|
|
|
47024
47179
|
// ../node_modules/.pnpm/@xterm+addon-serialize@0.14.0/node_modules/@xterm/addon-serialize/lib/addon-serialize.mjs
|
|
@@ -48251,9 +48406,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
48251
48406
|
function jsonlExistsForCtx(ctx) {
|
|
48252
48407
|
if (!ctx.toolSessionId) return false;
|
|
48253
48408
|
const home = import_node_os7.default.homedir();
|
|
48254
|
-
const file =
|
|
48409
|
+
const file = import_node_path17.default.join(home, ".claude", "projects", cwdToHashDir(ctx.cwd), `${ctx.toolSessionId}.jsonl`);
|
|
48255
48410
|
try {
|
|
48256
|
-
return
|
|
48411
|
+
return import_node_fs19.default.statSync(file).isFile();
|
|
48257
48412
|
} catch {
|
|
48258
48413
|
return false;
|
|
48259
48414
|
}
|
|
@@ -48330,6 +48485,21 @@ var PersonaDispatchManager = class {
|
|
|
48330
48485
|
state.waiters.push(d);
|
|
48331
48486
|
return d.promise;
|
|
48332
48487
|
}
|
|
48488
|
+
/**
|
|
48489
|
+
* 续派(spec 2026-07-21):complete 已清掉 map 条目,续派前重建——bSessionId 映射
|
|
48490
|
+
* 保证 worker 进程死后 respawn 时 reducer lookupDispatchByBSessionId 仍注回同一
|
|
48491
|
+
* CLAWD_DISPATCH_ID env。台账行的复位由 handler 直接走 store(本方法只管内存态)。
|
|
48492
|
+
*/
|
|
48493
|
+
reopen(dispatchId, args) {
|
|
48494
|
+
const existing = this.map.get(dispatchId);
|
|
48495
|
+
this.map.set(dispatchId, {
|
|
48496
|
+
dispatchId,
|
|
48497
|
+
sourceSessionId: args.sourceSessionId,
|
|
48498
|
+
targetPersona: args.targetPersona,
|
|
48499
|
+
bSessionId: args.workerSessionId,
|
|
48500
|
+
waiters: existing?.waiters ?? []
|
|
48501
|
+
});
|
|
48502
|
+
}
|
|
48333
48503
|
/** SessionManager 在 createDispatchedSession 时调,建立 dispatchId → B sessionId 映射 */
|
|
48334
48504
|
registerBSession(dispatchId, bSessionId) {
|
|
48335
48505
|
const state = this.map.get(dispatchId);
|
|
@@ -48348,7 +48518,7 @@ var PersonaDispatchManager = class {
|
|
|
48348
48518
|
|
|
48349
48519
|
// src/dispatch/store.ts
|
|
48350
48520
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
48351
|
-
var
|
|
48521
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
48352
48522
|
|
|
48353
48523
|
// src/shift/constants.ts
|
|
48354
48524
|
var MAX_RUNS_PER_SHIFT = 30;
|
|
@@ -48386,7 +48556,7 @@ function createDispatchStore(deps) {
|
|
|
48386
48556
|
flushTimer = null;
|
|
48387
48557
|
}
|
|
48388
48558
|
const content = { version: 1, records };
|
|
48389
|
-
await import_promises.default.mkdir(
|
|
48559
|
+
await import_promises.default.mkdir(import_node_path18.default.dirname(deps.filePath), { recursive: true });
|
|
48390
48560
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
48391
48561
|
await import_promises.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
48392
48562
|
await import_promises.default.rename(tmp, deps.filePath);
|
|
@@ -48448,10 +48618,10 @@ function createDispatchStore(deps) {
|
|
|
48448
48618
|
}
|
|
48449
48619
|
|
|
48450
48620
|
// src/dispatch/mcp-config.ts
|
|
48451
|
-
var
|
|
48452
|
-
var
|
|
48621
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
48622
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
48453
48623
|
function dispatchMcpConfigPath(dataDir) {
|
|
48454
|
-
return
|
|
48624
|
+
return import_node_path19.default.join(dataDir, "dispatch.mcp.json");
|
|
48455
48625
|
}
|
|
48456
48626
|
function writeDispatchMcpConfig(args) {
|
|
48457
48627
|
const cfgPath = dispatchMcpConfigPath(args.dataDir);
|
|
@@ -48466,16 +48636,16 @@ function writeDispatchMcpConfig(args) {
|
|
|
48466
48636
|
}
|
|
48467
48637
|
}
|
|
48468
48638
|
};
|
|
48469
|
-
|
|
48470
|
-
|
|
48639
|
+
import_node_fs20.default.mkdirSync(args.dataDir, { recursive: true });
|
|
48640
|
+
import_node_fs20.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
48471
48641
|
return cfgPath;
|
|
48472
48642
|
}
|
|
48473
48643
|
|
|
48474
48644
|
// src/ticket/mcp-config.ts
|
|
48475
|
-
var
|
|
48476
|
-
var
|
|
48645
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
48646
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
48477
48647
|
function ticketMcpConfigPath(dataDir) {
|
|
48478
|
-
return
|
|
48648
|
+
return import_node_path20.default.join(dataDir, "ticket.mcp.json");
|
|
48479
48649
|
}
|
|
48480
48650
|
function writeTicketMcpConfig(args) {
|
|
48481
48651
|
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
@@ -48495,16 +48665,16 @@ function writeTicketMcpConfig(args) {
|
|
|
48495
48665
|
}
|
|
48496
48666
|
}
|
|
48497
48667
|
};
|
|
48498
|
-
|
|
48499
|
-
|
|
48668
|
+
import_node_fs21.default.mkdirSync(args.dataDir, { recursive: true });
|
|
48669
|
+
import_node_fs21.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
48500
48670
|
return cfgPath;
|
|
48501
48671
|
}
|
|
48502
48672
|
|
|
48503
48673
|
// src/shift/mcp-config.ts
|
|
48504
|
-
var
|
|
48505
|
-
var
|
|
48674
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
48675
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
48506
48676
|
function shiftMcpConfigPath(dataDir) {
|
|
48507
|
-
return
|
|
48677
|
+
return import_node_path21.default.join(dataDir, "shift.mcp.json");
|
|
48508
48678
|
}
|
|
48509
48679
|
async function writeShiftMcpConfig(args) {
|
|
48510
48680
|
const cfgPath = shiftMcpConfigPath(args.dataDir);
|
|
@@ -48519,16 +48689,16 @@ async function writeShiftMcpConfig(args) {
|
|
|
48519
48689
|
}
|
|
48520
48690
|
}
|
|
48521
48691
|
};
|
|
48522
|
-
await
|
|
48523
|
-
await
|
|
48692
|
+
await import_node_fs22.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
48693
|
+
await import_node_fs22.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
48524
48694
|
return cfgPath;
|
|
48525
48695
|
}
|
|
48526
48696
|
|
|
48527
48697
|
// src/inbox/mcp-config.ts
|
|
48528
|
-
var
|
|
48529
|
-
var
|
|
48698
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
48699
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
48530
48700
|
function inboxMcpConfigPath(dataDir) {
|
|
48531
|
-
return
|
|
48701
|
+
return import_node_path22.default.join(dataDir, "inbox.mcp.json");
|
|
48532
48702
|
}
|
|
48533
48703
|
async function writeInboxMcpConfig(args) {
|
|
48534
48704
|
const cfgPath = inboxMcpConfigPath(args.dataDir);
|
|
@@ -48543,16 +48713,16 @@ async function writeInboxMcpConfig(args) {
|
|
|
48543
48713
|
}
|
|
48544
48714
|
}
|
|
48545
48715
|
};
|
|
48546
|
-
await
|
|
48547
|
-
await
|
|
48716
|
+
await import_node_fs23.default.promises.mkdir(args.dataDir, { recursive: true });
|
|
48717
|
+
await import_node_fs23.default.promises.writeFile(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
48548
48718
|
return cfgPath;
|
|
48549
48719
|
}
|
|
48550
48720
|
|
|
48551
48721
|
// src/peer-ops/mcp-config.ts
|
|
48552
|
-
var
|
|
48553
|
-
var
|
|
48722
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
48723
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
48554
48724
|
function peerOpsMcpConfigPath(dataDir) {
|
|
48555
|
-
return
|
|
48725
|
+
return import_node_path23.default.join(dataDir, "peer-ops.mcp.json");
|
|
48556
48726
|
}
|
|
48557
48727
|
function writePeerOpsMcpConfig(args) {
|
|
48558
48728
|
const cfgPath = peerOpsMcpConfigPath(args.dataDir);
|
|
@@ -48565,14 +48735,14 @@ function writePeerOpsMcpConfig(args) {
|
|
|
48565
48735
|
}
|
|
48566
48736
|
}
|
|
48567
48737
|
};
|
|
48568
|
-
|
|
48569
|
-
|
|
48738
|
+
import_node_fs24.default.mkdirSync(args.dataDir, { recursive: true });
|
|
48739
|
+
import_node_fs24.default.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2));
|
|
48570
48740
|
return cfgPath;
|
|
48571
48741
|
}
|
|
48572
48742
|
|
|
48573
48743
|
// src/shift/store.ts
|
|
48574
48744
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
48575
|
-
var
|
|
48745
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
48576
48746
|
var import_node_crypto6 = require("crypto");
|
|
48577
48747
|
|
|
48578
48748
|
// src/shift/schedule.ts
|
|
@@ -48647,7 +48817,7 @@ function createShiftStore(deps) {
|
|
|
48647
48817
|
flushTimer = null;
|
|
48648
48818
|
}
|
|
48649
48819
|
const content = { version: 1, shifts };
|
|
48650
|
-
await import_promises2.default.mkdir(
|
|
48820
|
+
await import_promises2.default.mkdir(import_node_path24.default.dirname(deps.filePath), { recursive: true });
|
|
48651
48821
|
const tmp = `${deps.filePath}.tmp-${deps.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
48652
48822
|
await import_promises2.default.writeFile(tmp, JSON.stringify(content, null, 2), "utf8");
|
|
48653
48823
|
await import_promises2.default.rename(tmp, deps.filePath);
|
|
@@ -49063,17 +49233,103 @@ function canAccessPersona(grants, personaId, action) {
|
|
|
49063
49233
|
|
|
49064
49234
|
// src/handlers/persona-dispatch.ts
|
|
49065
49235
|
init_claude();
|
|
49236
|
+
function buildFollowUpTaskPack(dispatchId, prompt) {
|
|
49237
|
+
return [
|
|
49238
|
+
`[Follow-up instruction for dispatch ${dispatchId}]`,
|
|
49239
|
+
"",
|
|
49240
|
+
`Task: ${prompt}`,
|
|
49241
|
+
"",
|
|
49242
|
+
`This is a follow-up turn in the same dispatched task (dispatchId=${dispatchId}).`,
|
|
49243
|
+
"When you finish this round, report back by calling personaDispatchComplete again,",
|
|
49244
|
+
"exactly as you did before."
|
|
49245
|
+
].join("\n");
|
|
49246
|
+
}
|
|
49066
49247
|
function buildPersonaDispatchHandlers(deps) {
|
|
49067
49248
|
const { personaDispatchManager: mgr, spawnB, logger } = deps;
|
|
49068
49249
|
const run = async (frame, _client, ctx) => {
|
|
49069
49250
|
const { type: _t, requestId: _r, ...rest } = frame;
|
|
49070
49251
|
const sourceSessionId = typeof rest.sessionId === "string" ? rest.sessionId : void 0;
|
|
49071
49252
|
const args = DispatchRunArgsSchema.parse(rest);
|
|
49072
|
-
if (args.model !== void 0
|
|
49073
|
-
|
|
49074
|
-
|
|
49075
|
-
|
|
49253
|
+
if (args.model !== void 0) {
|
|
49254
|
+
const targetPersona2 = args.targetPersona ?? (args.dispatchId ? deps.store.get(args.dispatchId)?.targetPersonaId : void 0);
|
|
49255
|
+
const targetTool = (targetPersona2 ? deps.getPersonaTool?.(targetPersona2) : void 0) ?? "claude";
|
|
49256
|
+
const allowed = targetTool === "codex" ? CODEX_MODEL_IDS : CLAUDE_MODEL_IDS;
|
|
49257
|
+
if (!allowed.includes(args.model)) {
|
|
49258
|
+
throw new ClawdError(
|
|
49259
|
+
ERROR_CODES.INVALID_PARAM,
|
|
49260
|
+
`model '${args.model}' not supported for tool '${targetTool}'; allowed: ${allowed.join(", ")}`
|
|
49261
|
+
);
|
|
49262
|
+
}
|
|
49263
|
+
}
|
|
49264
|
+
if (args.dispatchId) {
|
|
49265
|
+
if (ctx?.principal.kind === "guest") {
|
|
49266
|
+
throw new ClawdError(
|
|
49267
|
+
ERROR_CODES.UNAUTHORIZED,
|
|
49268
|
+
"follow-up dispatch cannot be initiated by a guest"
|
|
49269
|
+
);
|
|
49270
|
+
}
|
|
49271
|
+
if (!sourceSessionId) {
|
|
49272
|
+
throw new Error(
|
|
49273
|
+
"personaDispatch:run requires sessionId (caller must pass x-clawd-session-id header)"
|
|
49274
|
+
);
|
|
49275
|
+
}
|
|
49276
|
+
const rec3 = deps.store.get(args.dispatchId);
|
|
49277
|
+
if (!rec3) {
|
|
49278
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, `dispatch not found: ${args.dispatchId}`);
|
|
49279
|
+
}
|
|
49280
|
+
if (!rec3.workerSessionId) {
|
|
49281
|
+
throw new ClawdError(
|
|
49282
|
+
ERROR_CODES.INVALID_PARAM,
|
|
49283
|
+
`dispatch ${args.dispatchId} has no worker session and cannot be continued (cross-device or spawn incomplete)`
|
|
49284
|
+
);
|
|
49285
|
+
}
|
|
49286
|
+
if (args.targetPersona && args.targetPersona !== rec3.targetPersonaId) {
|
|
49287
|
+
throw new ClawdError(
|
|
49288
|
+
ERROR_CODES.INVALID_PARAM,
|
|
49289
|
+
`targetPersona mismatch: dispatch ${args.dispatchId} belongs to ${rec3.targetPersonaId}`
|
|
49290
|
+
);
|
|
49291
|
+
}
|
|
49292
|
+
if (!deps.sendFollowUp) {
|
|
49293
|
+
throw new Error("follow-up dispatch not wired (sendFollowUp missing)");
|
|
49294
|
+
}
|
|
49295
|
+
deps.store.update(args.dispatchId, {
|
|
49296
|
+
status: "running",
|
|
49297
|
+
outcome: void 0,
|
|
49298
|
+
completedAt: void 0,
|
|
49299
|
+
deliveredAt: void 0,
|
|
49300
|
+
taskText: args.prompt.slice(0, TASK_TEXT_MAX)
|
|
49301
|
+
});
|
|
49302
|
+
mgr.reopen(args.dispatchId, {
|
|
49303
|
+
sourceSessionId,
|
|
49304
|
+
targetPersona: rec3.targetPersonaId,
|
|
49305
|
+
workerSessionId: rec3.workerSessionId
|
|
49306
|
+
});
|
|
49307
|
+
logger?.info("dispatch.run.follow-up", {
|
|
49308
|
+
dispatchId: args.dispatchId,
|
|
49309
|
+
workerSessionId: rec3.workerSessionId,
|
|
49310
|
+
promptLen: args.prompt.length
|
|
49311
|
+
});
|
|
49312
|
+
const ok = deps.sendFollowUp(
|
|
49313
|
+
rec3.workerSessionId,
|
|
49314
|
+
buildFollowUpTaskPack(args.dispatchId, args.prompt)
|
|
49076
49315
|
);
|
|
49316
|
+
if (!ok) {
|
|
49317
|
+
mgr.complete(args.dispatchId, {
|
|
49318
|
+
kind: "failure",
|
|
49319
|
+
reason: "worker session unavailable for follow-up"
|
|
49320
|
+
});
|
|
49321
|
+
throw new ClawdError(
|
|
49322
|
+
ERROR_CODES.SESSION_NOT_FOUND,
|
|
49323
|
+
`worker session unavailable; follow-up failed for dispatch ${args.dispatchId}`
|
|
49324
|
+
);
|
|
49325
|
+
}
|
|
49326
|
+
return {
|
|
49327
|
+
response: { type: "personaDispatch:run:ok", dispatchId: args.dispatchId }
|
|
49328
|
+
};
|
|
49329
|
+
}
|
|
49330
|
+
const targetPersona = args.targetPersona;
|
|
49331
|
+
if (!targetPersona) {
|
|
49332
|
+
throw new ClawdError(ERROR_CODES.INVALID_PARAM, "targetPersona is required for a new dispatch");
|
|
49077
49333
|
}
|
|
49078
49334
|
if (args.targetDeviceId) {
|
|
49079
49335
|
if (ctx?.principal.kind === "guest") {
|
|
@@ -49092,17 +49348,17 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
49092
49348
|
}
|
|
49093
49349
|
const { dispatchId: dispatchId2 } = mgr.start({
|
|
49094
49350
|
sourceSessionId,
|
|
49095
|
-
targetPersona
|
|
49351
|
+
targetPersona,
|
|
49096
49352
|
taskText: args.prompt
|
|
49097
49353
|
});
|
|
49098
49354
|
logger?.info("dispatch.run.forward", {
|
|
49099
49355
|
dispatchId: dispatchId2,
|
|
49100
49356
|
targetDeviceId: args.targetDeviceId,
|
|
49101
|
-
targetPersona
|
|
49357
|
+
targetPersona
|
|
49102
49358
|
});
|
|
49103
49359
|
void deps.forwardToPeer({
|
|
49104
49360
|
targetDeviceId: args.targetDeviceId,
|
|
49105
|
-
targetPersona
|
|
49361
|
+
targetPersona,
|
|
49106
49362
|
prompt: args.prompt,
|
|
49107
49363
|
...args.model ? { model: args.model } : {}
|
|
49108
49364
|
}).then((outcome) => mgr.complete(dispatchId2, outcome)).catch((err) => {
|
|
@@ -49115,28 +49371,28 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
49115
49371
|
};
|
|
49116
49372
|
}
|
|
49117
49373
|
if (ctx?.principal.kind === "guest") {
|
|
49118
|
-
const isPublic = deps.getPersonaPublic?.(
|
|
49119
|
-
if (!isPublic || !canAccessPersona(ctx.grants,
|
|
49374
|
+
const isPublic = deps.getPersonaPublic?.(targetPersona) ?? false;
|
|
49375
|
+
if (!isPublic || !canAccessPersona(ctx.grants, targetPersona, "send")) {
|
|
49120
49376
|
throw new ClawdError(
|
|
49121
49377
|
ERROR_CODES.UNAUTHORIZED,
|
|
49122
|
-
`persona not dispatchable: ${
|
|
49378
|
+
`persona not dispatchable: ${targetPersona}`
|
|
49123
49379
|
);
|
|
49124
49380
|
}
|
|
49125
49381
|
const { dispatchId: dispatchId2 } = mgr.start({
|
|
49126
49382
|
sourceSessionId: ctx.principal.id,
|
|
49127
|
-
targetPersona
|
|
49383
|
+
targetPersona,
|
|
49128
49384
|
taskText: args.prompt
|
|
49129
49385
|
});
|
|
49130
49386
|
logger?.info("dispatch.run.received.guest", {
|
|
49131
49387
|
dispatchId: dispatchId2,
|
|
49132
49388
|
sourcePrincipal: ctx.principal.id,
|
|
49133
|
-
targetPersona
|
|
49389
|
+
targetPersona,
|
|
49134
49390
|
promptLen: args.prompt.length
|
|
49135
49391
|
});
|
|
49136
49392
|
void spawnB({
|
|
49137
49393
|
dispatchId: dispatchId2,
|
|
49138
49394
|
sourceSessionId: ctx.principal.id,
|
|
49139
|
-
targetPersona
|
|
49395
|
+
targetPersona,
|
|
49140
49396
|
prompt: args.prompt,
|
|
49141
49397
|
guestPrincipalId: ctx.principal.id,
|
|
49142
49398
|
guestDisplayName: ctx.principal.displayName,
|
|
@@ -49163,19 +49419,19 @@ function buildPersonaDispatchHandlers(deps) {
|
|
|
49163
49419
|
}
|
|
49164
49420
|
const { dispatchId } = mgr.start({
|
|
49165
49421
|
sourceSessionId,
|
|
49166
|
-
targetPersona
|
|
49422
|
+
targetPersona,
|
|
49167
49423
|
taskText: args.prompt
|
|
49168
49424
|
});
|
|
49169
49425
|
logger?.info("dispatch.run.received", {
|
|
49170
49426
|
dispatchId,
|
|
49171
49427
|
sourceSessionId,
|
|
49172
|
-
targetPersona
|
|
49428
|
+
targetPersona,
|
|
49173
49429
|
promptLen: args.prompt.length
|
|
49174
49430
|
});
|
|
49175
49431
|
void spawnB({
|
|
49176
49432
|
dispatchId,
|
|
49177
49433
|
sourceSessionId,
|
|
49178
|
-
targetPersona
|
|
49434
|
+
targetPersona,
|
|
49179
49435
|
prompt: args.prompt,
|
|
49180
49436
|
...args.model ? { model: args.model } : {}
|
|
49181
49437
|
}).then(() => {
|
|
@@ -49338,7 +49594,7 @@ async function forwardPeerExecToPeer(args) {
|
|
|
49338
49594
|
}
|
|
49339
49595
|
|
|
49340
49596
|
// src/tools/codex-history.ts
|
|
49341
|
-
var
|
|
49597
|
+
var import_node_child_process6 = require("child_process");
|
|
49342
49598
|
var DEFAULT_TIMEOUT_MS2 = 8e3;
|
|
49343
49599
|
function rec2(v2) {
|
|
49344
49600
|
return v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
@@ -49401,7 +49657,7 @@ function threadItemToHistoryMessages(item) {
|
|
|
49401
49657
|
async function queryCodexAppServer(cwd, method, params, deps) {
|
|
49402
49658
|
const cmd = process.env.CODEX_BIN ?? "codex";
|
|
49403
49659
|
const args = ["app-server", "--listen", "stdio://"];
|
|
49404
|
-
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0,
|
|
49660
|
+
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process6.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
|
|
49405
49661
|
const client = new CodexAppServerClient(proc, {});
|
|
49406
49662
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS2;
|
|
49407
49663
|
let timer;
|
|
@@ -49507,7 +49763,8 @@ var CodexHistoryReader = class {
|
|
|
49507
49763
|
};
|
|
49508
49764
|
|
|
49509
49765
|
// src/tools/codex-skills.ts
|
|
49510
|
-
var
|
|
49766
|
+
var import_node_child_process7 = require("child_process");
|
|
49767
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
49511
49768
|
var DEFAULT_TIMEOUT_MS3 = 8e3;
|
|
49512
49769
|
function str3(v2) {
|
|
49513
49770
|
return typeof v2 === "string" ? v2 : void 0;
|
|
@@ -49523,13 +49780,13 @@ function mapSkillsListResponse(res) {
|
|
|
49523
49780
|
const r = s ?? {};
|
|
49524
49781
|
const name = str3(r.name);
|
|
49525
49782
|
if (!name) continue;
|
|
49526
|
-
const
|
|
49783
|
+
const path74 = str3(r.path);
|
|
49527
49784
|
const description = str3(r.description);
|
|
49528
49785
|
const isPlugin = name.includes(":");
|
|
49529
49786
|
out.push({
|
|
49530
49787
|
name,
|
|
49531
49788
|
source: isPlugin ? "plugin" : "project",
|
|
49532
|
-
...
|
|
49789
|
+
...path74 ? { path: path74 } : {},
|
|
49533
49790
|
...description ? { description } : {},
|
|
49534
49791
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
49535
49792
|
});
|
|
@@ -49540,7 +49797,7 @@ function mapSkillsListResponse(res) {
|
|
|
49540
49797
|
async function listCodexSkills(cwd, deps = {}) {
|
|
49541
49798
|
const cmd = process.env.CODEX_BIN ?? "codex";
|
|
49542
49799
|
const args = ["app-server", "--listen", "stdio://"];
|
|
49543
|
-
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0,
|
|
49800
|
+
const proc = deps.spawnOverride ? deps.spawnOverride(cmd, args, cwd) : (0, import_node_child_process7.spawn)(cmd, args, { cwd, env: process.env, stdio: ["pipe", "pipe", "pipe"] });
|
|
49544
49801
|
const client = new CodexAppServerClient(proc, {});
|
|
49545
49802
|
const timeoutMs = deps.timeoutMs ?? DEFAULT_TIMEOUT_MS3;
|
|
49546
49803
|
let timer;
|
|
@@ -49559,6 +49816,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
49559
49816
|
})(),
|
|
49560
49817
|
timeout
|
|
49561
49818
|
]);
|
|
49819
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path25.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
49562
49820
|
const res = await Promise.race([client.request("skills/list", { cwds: [cwd] }), timeout]);
|
|
49563
49821
|
return mapSkillsListResponse(res);
|
|
49564
49822
|
} finally {
|
|
@@ -49568,23 +49826,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
49568
49826
|
}
|
|
49569
49827
|
|
|
49570
49828
|
// src/workspace/browser.ts
|
|
49571
|
-
var
|
|
49829
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
49572
49830
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
49573
|
-
var
|
|
49831
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
49574
49832
|
init_protocol();
|
|
49575
49833
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
49576
49834
|
function resolveInsideCwd(cwd, subpath) {
|
|
49577
|
-
const absCwd =
|
|
49578
|
-
const joined =
|
|
49579
|
-
const rel =
|
|
49580
|
-
if (rel.startsWith("..") ||
|
|
49835
|
+
const absCwd = import_node_path26.default.resolve(cwd);
|
|
49836
|
+
const joined = import_node_path26.default.resolve(absCwd, subpath ?? ".");
|
|
49837
|
+
const rel = import_node_path26.default.relative(absCwd, joined);
|
|
49838
|
+
if (rel.startsWith("..") || import_node_path26.default.isAbsolute(rel)) {
|
|
49581
49839
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
49582
49840
|
}
|
|
49583
49841
|
return joined;
|
|
49584
49842
|
}
|
|
49585
49843
|
function ensureCwd(cwd) {
|
|
49586
49844
|
try {
|
|
49587
|
-
const stat =
|
|
49845
|
+
const stat = import_node_fs25.default.statSync(cwd);
|
|
49588
49846
|
if (!stat.isDirectory()) {
|
|
49589
49847
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
49590
49848
|
}
|
|
@@ -49598,7 +49856,7 @@ var WorkspaceBrowser = class {
|
|
|
49598
49856
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os8.default.homedir();
|
|
49599
49857
|
ensureCwd(cwd);
|
|
49600
49858
|
const full = resolveInsideCwd(cwd, args.path);
|
|
49601
|
-
const dirents =
|
|
49859
|
+
const dirents = import_node_fs25.default.readdirSync(full, { withFileTypes: true });
|
|
49602
49860
|
const entries = [];
|
|
49603
49861
|
for (const d of dirents) {
|
|
49604
49862
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -49608,7 +49866,7 @@ var WorkspaceBrowser = class {
|
|
|
49608
49866
|
mtime: ""
|
|
49609
49867
|
};
|
|
49610
49868
|
try {
|
|
49611
|
-
const st =
|
|
49869
|
+
const st = import_node_fs25.default.statSync(import_node_path26.default.join(full, d.name));
|
|
49612
49870
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
49613
49871
|
if (d.isFile()) entry.size = st.size;
|
|
49614
49872
|
} catch {
|
|
@@ -49624,14 +49882,14 @@ var WorkspaceBrowser = class {
|
|
|
49624
49882
|
read(args) {
|
|
49625
49883
|
ensureCwd(args.cwd);
|
|
49626
49884
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
49627
|
-
const st =
|
|
49885
|
+
const st = import_node_fs25.default.statSync(full);
|
|
49628
49886
|
if (!st.isFile()) {
|
|
49629
49887
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
49630
49888
|
}
|
|
49631
49889
|
if (st.size > MAX_FILE_BYTES) {
|
|
49632
49890
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
49633
49891
|
}
|
|
49634
|
-
const buf =
|
|
49892
|
+
const buf = import_node_fs25.default.readFileSync(full);
|
|
49635
49893
|
const isBinary = buf.includes(0);
|
|
49636
49894
|
if (isBinary) {
|
|
49637
49895
|
return {
|
|
@@ -49653,20 +49911,20 @@ var WorkspaceBrowser = class {
|
|
|
49653
49911
|
};
|
|
49654
49912
|
|
|
49655
49913
|
// src/skills/agents-scanner.ts
|
|
49656
|
-
var
|
|
49914
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
49657
49915
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
49658
|
-
var
|
|
49916
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
49659
49917
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
49660
49918
|
function isDirLikeSync2(p2) {
|
|
49661
49919
|
try {
|
|
49662
|
-
return
|
|
49920
|
+
return import_node_fs26.default.statSync(p2).isDirectory();
|
|
49663
49921
|
} catch {
|
|
49664
49922
|
return false;
|
|
49665
49923
|
}
|
|
49666
49924
|
}
|
|
49667
49925
|
function fileExistsSync(p2) {
|
|
49668
49926
|
try {
|
|
49669
|
-
return
|
|
49927
|
+
return import_node_fs26.default.statSync(p2).isFile();
|
|
49670
49928
|
} catch {
|
|
49671
49929
|
return false;
|
|
49672
49930
|
}
|
|
@@ -49674,7 +49932,7 @@ function fileExistsSync(p2) {
|
|
|
49674
49932
|
function parseAgentFile(filePath) {
|
|
49675
49933
|
let content;
|
|
49676
49934
|
try {
|
|
49677
|
-
content =
|
|
49935
|
+
content = import_node_fs26.default.readFileSync(filePath, "utf8");
|
|
49678
49936
|
} catch {
|
|
49679
49937
|
return {};
|
|
49680
49938
|
}
|
|
@@ -49687,16 +49945,16 @@ function parseAgentFile(filePath) {
|
|
|
49687
49945
|
function scanAgentsDir(dir, source, seen, out) {
|
|
49688
49946
|
let entries;
|
|
49689
49947
|
try {
|
|
49690
|
-
entries =
|
|
49948
|
+
entries = import_node_fs26.default.readdirSync(dir, { withFileTypes: true });
|
|
49691
49949
|
} catch {
|
|
49692
49950
|
return;
|
|
49693
49951
|
}
|
|
49694
49952
|
for (const ent of entries) {
|
|
49695
49953
|
if (!ent.name.endsWith(".md")) continue;
|
|
49696
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
49954
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path27.default.join(dir, ent.name)))) {
|
|
49697
49955
|
continue;
|
|
49698
49956
|
}
|
|
49699
|
-
const filePath =
|
|
49957
|
+
const filePath = import_node_path27.default.join(dir, ent.name);
|
|
49700
49958
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
49701
49959
|
if (seen.has(baseName)) continue;
|
|
49702
49960
|
seen.add(baseName);
|
|
@@ -49714,12 +49972,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
49714
49972
|
function walk2(dir, namespaces) {
|
|
49715
49973
|
let entries;
|
|
49716
49974
|
try {
|
|
49717
|
-
entries =
|
|
49975
|
+
entries = import_node_fs26.default.readdirSync(dir, { withFileTypes: true });
|
|
49718
49976
|
} catch {
|
|
49719
49977
|
return;
|
|
49720
49978
|
}
|
|
49721
49979
|
for (const ent of entries) {
|
|
49722
|
-
const childPath =
|
|
49980
|
+
const childPath = import_node_path27.default.join(dir, ent.name);
|
|
49723
49981
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
49724
49982
|
walk2(childPath, [...namespaces, ent.name]);
|
|
49725
49983
|
continue;
|
|
@@ -49744,13 +50002,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
49744
50002
|
walk2(root, []);
|
|
49745
50003
|
}
|
|
49746
50004
|
function readInstalledPlugins2(home) {
|
|
49747
|
-
const pluginsDir =
|
|
49748
|
-
const v2 =
|
|
49749
|
-
const v1 =
|
|
50005
|
+
const pluginsDir = import_node_path27.default.join(home, ".claude", "plugins");
|
|
50006
|
+
const v2 = import_node_path27.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
50007
|
+
const v1 = import_node_path27.default.join(pluginsDir, "installed_plugins.json");
|
|
49750
50008
|
let raw = null;
|
|
49751
50009
|
for (const candidate of [v2, v1]) {
|
|
49752
50010
|
try {
|
|
49753
|
-
raw =
|
|
50011
|
+
raw = import_node_fs26.default.readFileSync(candidate, "utf8");
|
|
49754
50012
|
break;
|
|
49755
50013
|
} catch {
|
|
49756
50014
|
}
|
|
@@ -49775,19 +50033,19 @@ function readInstalledPlugins2(home) {
|
|
|
49775
50033
|
return out;
|
|
49776
50034
|
}
|
|
49777
50035
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
49778
|
-
let cur =
|
|
49779
|
-
const fsRoot =
|
|
50036
|
+
let cur = import_node_path27.default.resolve(startCwd);
|
|
50037
|
+
const fsRoot = import_node_path27.default.parse(cur).root;
|
|
49780
50038
|
while (true) {
|
|
49781
|
-
scanAgentsDir(
|
|
50039
|
+
scanAgentsDir(import_node_path27.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
49782
50040
|
let hasGit = false;
|
|
49783
50041
|
try {
|
|
49784
|
-
hasGit =
|
|
50042
|
+
hasGit = import_node_fs26.default.existsSync(import_node_path27.default.join(cur, ".git"));
|
|
49785
50043
|
} catch {
|
|
49786
50044
|
}
|
|
49787
50045
|
if (hasGit) return;
|
|
49788
50046
|
if (cur === home) return;
|
|
49789
50047
|
if (cur === fsRoot) return;
|
|
49790
|
-
const parent =
|
|
50048
|
+
const parent = import_node_path27.default.dirname(cur);
|
|
49791
50049
|
if (parent === cur) return;
|
|
49792
50050
|
cur = parent;
|
|
49793
50051
|
}
|
|
@@ -49822,7 +50080,7 @@ var AgentsScanner = class {
|
|
|
49822
50080
|
}
|
|
49823
50081
|
const fsBlock = [];
|
|
49824
50082
|
scanAgentsDir(
|
|
49825
|
-
|
|
50083
|
+
import_node_path27.default.join(this.home, ".claude", "agents"),
|
|
49826
50084
|
"global",
|
|
49827
50085
|
seen,
|
|
49828
50086
|
fsBlock
|
|
@@ -49836,7 +50094,7 @@ var AgentsScanner = class {
|
|
|
49836
50094
|
...this.extraPluginRoots
|
|
49837
50095
|
];
|
|
49838
50096
|
for (const { name, root } of plugins) {
|
|
49839
|
-
const agentsRoot =
|
|
50097
|
+
const agentsRoot = import_node_path27.default.join(root, "agents");
|
|
49840
50098
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
49841
50099
|
}
|
|
49842
50100
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -49844,15 +50102,15 @@ var AgentsScanner = class {
|
|
|
49844
50102
|
};
|
|
49845
50103
|
|
|
49846
50104
|
// src/observer/session-observer.ts
|
|
49847
|
-
var
|
|
50105
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
49848
50106
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
49849
|
-
var
|
|
50107
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
49850
50108
|
init_claude_history();
|
|
49851
50109
|
|
|
49852
50110
|
// src/observer/subagent-meta-observer.ts
|
|
49853
|
-
var
|
|
50111
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
49854
50112
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
49855
|
-
var
|
|
50113
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
49856
50114
|
init_claude_history();
|
|
49857
50115
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
49858
50116
|
var SubagentMetaObserver = class {
|
|
@@ -49865,7 +50123,7 @@ var SubagentMetaObserver = class {
|
|
|
49865
50123
|
watches = /* @__PURE__ */ new Map();
|
|
49866
50124
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
49867
50125
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
49868
|
-
return
|
|
50126
|
+
return import_node_path28.default.join(
|
|
49869
50127
|
this.home,
|
|
49870
50128
|
".claude",
|
|
49871
50129
|
"projects",
|
|
@@ -49895,7 +50153,7 @@ var SubagentMetaObserver = class {
|
|
|
49895
50153
|
attachWatcher(w2) {
|
|
49896
50154
|
if (w2.watcher) return;
|
|
49897
50155
|
try {
|
|
49898
|
-
w2.watcher =
|
|
50156
|
+
w2.watcher = import_node_fs27.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
49899
50157
|
if (!name) return;
|
|
49900
50158
|
const m2 = META_RE.exec(String(name));
|
|
49901
50159
|
if (!m2) return;
|
|
@@ -49907,7 +50165,7 @@ var SubagentMetaObserver = class {
|
|
|
49907
50165
|
scan(w2) {
|
|
49908
50166
|
let entries;
|
|
49909
50167
|
try {
|
|
49910
|
-
entries =
|
|
50168
|
+
entries = import_node_fs27.default.readdirSync(w2.dirPath);
|
|
49911
50169
|
} catch {
|
|
49912
50170
|
return;
|
|
49913
50171
|
}
|
|
@@ -49921,10 +50179,10 @@ var SubagentMetaObserver = class {
|
|
|
49921
50179
|
if (!m2) return;
|
|
49922
50180
|
const agentId = m2[1];
|
|
49923
50181
|
if (w2.emitted.has(agentId)) return;
|
|
49924
|
-
const file =
|
|
50182
|
+
const file = import_node_path28.default.join(w2.dirPath, name);
|
|
49925
50183
|
let raw;
|
|
49926
50184
|
try {
|
|
49927
|
-
raw =
|
|
50185
|
+
raw = import_node_fs27.default.readFileSync(file, "utf8");
|
|
49928
50186
|
} catch {
|
|
49929
50187
|
return;
|
|
49930
50188
|
}
|
|
@@ -49981,14 +50239,14 @@ var SessionObserver = class {
|
|
|
49981
50239
|
metaObserver;
|
|
49982
50240
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
49983
50241
|
if (override) return override;
|
|
49984
|
-
return
|
|
50242
|
+
return import_node_path29.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
49985
50243
|
}
|
|
49986
50244
|
start(args) {
|
|
49987
50245
|
this.stop(args.sessionId);
|
|
49988
50246
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
49989
50247
|
let size = 0;
|
|
49990
50248
|
try {
|
|
49991
|
-
size =
|
|
50249
|
+
size = import_node_fs28.default.statSync(filePath).size;
|
|
49992
50250
|
} catch {
|
|
49993
50251
|
}
|
|
49994
50252
|
const w2 = {
|
|
@@ -50001,16 +50259,16 @@ var SessionObserver = class {
|
|
|
50001
50259
|
adapter: args.adapter,
|
|
50002
50260
|
prevIsRejectSentinel: false,
|
|
50003
50261
|
toolSessionId: args.toolSessionId,
|
|
50004
|
-
sawFile:
|
|
50262
|
+
sawFile: import_node_fs28.default.existsSync(filePath),
|
|
50005
50263
|
lastRelocateScanMs: 0,
|
|
50006
50264
|
pendingCwdDerive: false,
|
|
50007
50265
|
lastDeriveMs: 0
|
|
50008
50266
|
};
|
|
50009
50267
|
try {
|
|
50010
|
-
|
|
50268
|
+
import_node_fs28.default.mkdirSync(import_node_path29.default.dirname(filePath), { recursive: true });
|
|
50011
50269
|
} catch {
|
|
50012
50270
|
}
|
|
50013
|
-
w2.watcher =
|
|
50271
|
+
w2.watcher = import_node_fs28.default.watch(import_node_path29.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
50014
50272
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
50015
50273
|
this.poll(w2);
|
|
50016
50274
|
});
|
|
@@ -50033,7 +50291,7 @@ var SessionObserver = class {
|
|
|
50033
50291
|
// 异常静默吞,不阻塞 watcher 启动
|
|
50034
50292
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
50035
50293
|
try {
|
|
50036
|
-
const raw =
|
|
50294
|
+
const raw = import_node_fs28.default.readFileSync(w2.filePath, "utf8");
|
|
50037
50295
|
if (!raw) return;
|
|
50038
50296
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
50039
50297
|
if (allLines.length === 0) return;
|
|
@@ -50057,7 +50315,7 @@ var SessionObserver = class {
|
|
|
50057
50315
|
poll(w2) {
|
|
50058
50316
|
let size = 0;
|
|
50059
50317
|
try {
|
|
50060
|
-
size =
|
|
50318
|
+
size = import_node_fs28.default.statSync(w2.filePath).size;
|
|
50061
50319
|
} catch {
|
|
50062
50320
|
if (w2.sawFile) this.maybeRelocate(w2);
|
|
50063
50321
|
return;
|
|
@@ -50068,11 +50326,11 @@ var SessionObserver = class {
|
|
|
50068
50326
|
w2.buf = "";
|
|
50069
50327
|
}
|
|
50070
50328
|
if (size === w2.lastSize) return;
|
|
50071
|
-
const fd =
|
|
50329
|
+
const fd = import_node_fs28.default.openSync(w2.filePath, "r");
|
|
50072
50330
|
try {
|
|
50073
50331
|
const len = size - w2.lastSize;
|
|
50074
50332
|
const buf = Buffer.alloc(len);
|
|
50075
|
-
|
|
50333
|
+
import_node_fs28.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
50076
50334
|
w2.lastSize = size;
|
|
50077
50335
|
w2.buf += buf.toString("utf8");
|
|
50078
50336
|
let newlineIndex;
|
|
@@ -50095,7 +50353,7 @@ var SessionObserver = class {
|
|
|
50095
50353
|
}
|
|
50096
50354
|
}
|
|
50097
50355
|
} finally {
|
|
50098
|
-
|
|
50356
|
+
import_node_fs28.default.closeSync(fd);
|
|
50099
50357
|
}
|
|
50100
50358
|
if (w2.pendingCwdDerive) this.maybeDeriveCwd(w2);
|
|
50101
50359
|
}
|
|
@@ -50107,7 +50365,7 @@ var SessionObserver = class {
|
|
|
50107
50365
|
const now = Date.now();
|
|
50108
50366
|
if (now - w2.lastRelocateScanMs < 1e3) return;
|
|
50109
50367
|
w2.lastRelocateScanMs = now;
|
|
50110
|
-
const projectsRoot =
|
|
50368
|
+
const projectsRoot = import_node_path29.default.join(this.home, ".claude", "projects");
|
|
50111
50369
|
const found = findTranscriptByToolSessionId(projectsRoot, w2.toolSessionId);
|
|
50112
50370
|
if (!found || found === w2.filePath) return;
|
|
50113
50371
|
try {
|
|
@@ -50116,7 +50374,7 @@ var SessionObserver = class {
|
|
|
50116
50374
|
}
|
|
50117
50375
|
w2.filePath = found;
|
|
50118
50376
|
try {
|
|
50119
|
-
w2.watcher =
|
|
50377
|
+
w2.watcher = import_node_fs28.default.watch(import_node_path29.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
50120
50378
|
if (!changedName || !w2.filePath.endsWith(changedName)) return;
|
|
50121
50379
|
this.poll(w2);
|
|
50122
50380
|
});
|
|
@@ -50707,6 +50965,9 @@ var EXPOSED_RPC_METHODS = [
|
|
|
50707
50965
|
"peerExec.run",
|
|
50708
50966
|
"personaDispatch.complete",
|
|
50709
50967
|
"personaDispatch.list",
|
|
50968
|
+
// persona 清单(spec 2026-07-21):两级路由第一级——发起方 cc(loopback owner 语义)
|
|
50969
|
+
// 用 curl 拿全量 personaId+label 紧凑清单,再按需读候选 CLAUDE.md 首段做终选。
|
|
50970
|
+
"persona.list",
|
|
50710
50971
|
// clawd-shift v1 (spec 2026-06-24-clawd-shift):cc 子进程内的 shift MCP server 调
|
|
50711
50972
|
// 这 5 个 method 管理 owner 的 shift(fire-and-forget 排班)。鉴权靠 body.personaId
|
|
50712
50973
|
// (mcp-server 从 process.env.CLAWD_PERSONA_ID 读,源 = SessionFile.ownerPersonaId)。
|
|
@@ -50971,14 +51232,14 @@ async function authenticate(token, deps) {
|
|
|
50971
51232
|
}
|
|
50972
51233
|
|
|
50973
51234
|
// src/permission/capability-store.ts
|
|
50974
|
-
var
|
|
50975
|
-
var
|
|
51235
|
+
var fs33 = __toESM(require("fs"), 1);
|
|
51236
|
+
var path34 = __toESM(require("path"), 1);
|
|
50976
51237
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
50977
51238
|
var FILE_VERSION = 1;
|
|
50978
51239
|
var CapabilityStore = class {
|
|
50979
51240
|
constructor(dataDir) {
|
|
50980
51241
|
this.dataDir = dataDir;
|
|
50981
|
-
|
|
51242
|
+
fs33.mkdirSync(dataDir, { recursive: true });
|
|
50982
51243
|
this.cache = this.readFromDisk();
|
|
50983
51244
|
}
|
|
50984
51245
|
dataDir;
|
|
@@ -51002,13 +51263,13 @@ var CapabilityStore = class {
|
|
|
51002
51263
|
this.flush();
|
|
51003
51264
|
}
|
|
51004
51265
|
filePath() {
|
|
51005
|
-
return
|
|
51266
|
+
return path34.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
51006
51267
|
}
|
|
51007
51268
|
readFromDisk() {
|
|
51008
51269
|
const file = this.filePath();
|
|
51009
51270
|
let raw;
|
|
51010
51271
|
try {
|
|
51011
|
-
raw =
|
|
51272
|
+
raw = fs33.readFileSync(file, "utf8");
|
|
51012
51273
|
} catch (err) {
|
|
51013
51274
|
if (err?.code === "ENOENT") return [];
|
|
51014
51275
|
return [];
|
|
@@ -51036,10 +51297,10 @@ var CapabilityStore = class {
|
|
|
51036
51297
|
}
|
|
51037
51298
|
atomicWrite(file, content) {
|
|
51038
51299
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
51039
|
-
|
|
51040
|
-
|
|
51300
|
+
fs33.writeFileSync(tmp, content, { mode: 384 });
|
|
51301
|
+
fs33.renameSync(tmp, file);
|
|
51041
51302
|
try {
|
|
51042
|
-
|
|
51303
|
+
fs33.chmodSync(file, 384);
|
|
51043
51304
|
} catch {
|
|
51044
51305
|
}
|
|
51045
51306
|
}
|
|
@@ -51132,14 +51393,14 @@ var CapabilityManager = class {
|
|
|
51132
51393
|
};
|
|
51133
51394
|
|
|
51134
51395
|
// src/permission/cleanup.ts
|
|
51135
|
-
var
|
|
51396
|
+
var fs34 = __toESM(require("fs"), 1);
|
|
51136
51397
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
51137
51398
|
const removed = [];
|
|
51138
51399
|
for (const g2 of cap.grants) {
|
|
51139
51400
|
if (g2.resource.type !== "persona") continue;
|
|
51140
51401
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
51141
51402
|
try {
|
|
51142
|
-
|
|
51403
|
+
fs34.rmSync(dir, { recursive: true, force: true });
|
|
51143
51404
|
removed.push(dir);
|
|
51144
51405
|
} catch {
|
|
51145
51406
|
}
|
|
@@ -51148,13 +51409,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
51148
51409
|
}
|
|
51149
51410
|
|
|
51150
51411
|
// src/inbox/inbox-store.ts
|
|
51151
|
-
var
|
|
51152
|
-
var
|
|
51412
|
+
var fs35 = __toESM(require("fs"), 1);
|
|
51413
|
+
var path35 = __toESM(require("path"), 1);
|
|
51153
51414
|
var INBOX_SUBDIR = "inbox";
|
|
51154
51415
|
var InboxStore = class {
|
|
51155
51416
|
constructor(dataDir) {
|
|
51156
51417
|
this.dataDir = dataDir;
|
|
51157
|
-
|
|
51418
|
+
fs35.mkdirSync(this.dirPath(), { recursive: true });
|
|
51158
51419
|
}
|
|
51159
51420
|
dataDir;
|
|
51160
51421
|
/**
|
|
@@ -51166,7 +51427,7 @@ var InboxStore = class {
|
|
|
51166
51427
|
const file = this.filePath(peerDeviceId);
|
|
51167
51428
|
let raw;
|
|
51168
51429
|
try {
|
|
51169
|
-
raw =
|
|
51430
|
+
raw = fs35.readFileSync(file, "utf8");
|
|
51170
51431
|
} catch (err) {
|
|
51171
51432
|
if (err?.code === "ENOENT") return [];
|
|
51172
51433
|
return [];
|
|
@@ -51182,7 +51443,7 @@ var InboxStore = class {
|
|
|
51182
51443
|
const dir = this.dirPath();
|
|
51183
51444
|
let entries;
|
|
51184
51445
|
try {
|
|
51185
|
-
entries =
|
|
51446
|
+
entries = fs35.readdirSync(dir);
|
|
51186
51447
|
} catch (err) {
|
|
51187
51448
|
if (err?.code === "ENOENT") return [];
|
|
51188
51449
|
return [];
|
|
@@ -51198,9 +51459,9 @@ var InboxStore = class {
|
|
|
51198
51459
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
51199
51460
|
const file = this.filePath(message.peerDeviceId);
|
|
51200
51461
|
const line = JSON.stringify(message) + "\n";
|
|
51201
|
-
|
|
51462
|
+
fs35.appendFileSync(file, line, { mode: 384 });
|
|
51202
51463
|
try {
|
|
51203
|
-
|
|
51464
|
+
fs35.chmodSync(file, 384);
|
|
51204
51465
|
} catch {
|
|
51205
51466
|
}
|
|
51206
51467
|
}
|
|
@@ -51230,7 +51491,7 @@ var InboxStore = class {
|
|
|
51230
51491
|
removeByPeerDeviceId(peerDeviceId) {
|
|
51231
51492
|
const file = this.filePath(peerDeviceId);
|
|
51232
51493
|
try {
|
|
51233
|
-
|
|
51494
|
+
fs35.unlinkSync(file);
|
|
51234
51495
|
} catch (err) {
|
|
51235
51496
|
if (err?.code === "ENOENT") return;
|
|
51236
51497
|
}
|
|
@@ -51239,18 +51500,18 @@ var InboxStore = class {
|
|
|
51239
51500
|
const file = this.filePath(peerDeviceId);
|
|
51240
51501
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
51241
51502
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
51242
|
-
|
|
51243
|
-
|
|
51503
|
+
fs35.writeFileSync(tmp, content, { mode: 384 });
|
|
51504
|
+
fs35.renameSync(tmp, file);
|
|
51244
51505
|
try {
|
|
51245
|
-
|
|
51506
|
+
fs35.chmodSync(file, 384);
|
|
51246
51507
|
} catch {
|
|
51247
51508
|
}
|
|
51248
51509
|
}
|
|
51249
51510
|
dirPath() {
|
|
51250
|
-
return
|
|
51511
|
+
return path35.join(this.dataDir, INBOX_SUBDIR);
|
|
51251
51512
|
}
|
|
51252
51513
|
filePath(peerDeviceId) {
|
|
51253
|
-
return
|
|
51514
|
+
return path35.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
51254
51515
|
}
|
|
51255
51516
|
};
|
|
51256
51517
|
function parseAllLines(raw) {
|
|
@@ -51338,8 +51599,8 @@ var InboxManager = class {
|
|
|
51338
51599
|
};
|
|
51339
51600
|
|
|
51340
51601
|
// src/state/contact-store.ts
|
|
51341
|
-
var
|
|
51342
|
-
var
|
|
51602
|
+
var fs36 = __toESM(require("fs"), 1);
|
|
51603
|
+
var path36 = __toESM(require("path"), 1);
|
|
51343
51604
|
var FILE_NAME = "contacts.json";
|
|
51344
51605
|
var ContactStore = class {
|
|
51345
51606
|
constructor(dataDir) {
|
|
@@ -51349,10 +51610,10 @@ var ContactStore = class {
|
|
|
51349
51610
|
contacts = /* @__PURE__ */ new Map();
|
|
51350
51611
|
load() {
|
|
51351
51612
|
this.contacts.clear();
|
|
51352
|
-
const file =
|
|
51613
|
+
const file = path36.join(this.dataDir, FILE_NAME);
|
|
51353
51614
|
let raw;
|
|
51354
51615
|
try {
|
|
51355
|
-
raw =
|
|
51616
|
+
raw = fs36.readFileSync(file, "utf8");
|
|
51356
51617
|
} catch (err) {
|
|
51357
51618
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
51358
51619
|
return;
|
|
@@ -51421,20 +51682,20 @@ var ContactStore = class {
|
|
|
51421
51682
|
return true;
|
|
51422
51683
|
}
|
|
51423
51684
|
flush() {
|
|
51424
|
-
const file =
|
|
51685
|
+
const file = path36.join(this.dataDir, FILE_NAME);
|
|
51425
51686
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
51426
51687
|
const content = JSON.stringify(
|
|
51427
51688
|
{ contacts: Array.from(this.contacts.values()) },
|
|
51428
51689
|
null,
|
|
51429
51690
|
2
|
|
51430
51691
|
);
|
|
51431
|
-
|
|
51432
|
-
|
|
51433
|
-
|
|
51692
|
+
fs36.mkdirSync(this.dataDir, { recursive: true });
|
|
51693
|
+
fs36.writeFileSync(tmp, content, { mode: 384 });
|
|
51694
|
+
fs36.renameSync(tmp, file);
|
|
51434
51695
|
}
|
|
51435
51696
|
renameBak(file) {
|
|
51436
51697
|
try {
|
|
51437
|
-
|
|
51698
|
+
fs36.renameSync(file, `${file}.bak`);
|
|
51438
51699
|
} catch {
|
|
51439
51700
|
}
|
|
51440
51701
|
}
|
|
@@ -51587,61 +51848,61 @@ async function autoReverseContact(args) {
|
|
|
51587
51848
|
}
|
|
51588
51849
|
|
|
51589
51850
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
51590
|
-
var
|
|
51591
|
-
var
|
|
51851
|
+
var fs37 = __toESM(require("fs"), 1);
|
|
51852
|
+
var path37 = __toESM(require("path"), 1);
|
|
51592
51853
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
51593
51854
|
function migrateFlattenSessions(opts) {
|
|
51594
51855
|
const dataDir = opts.dataDir;
|
|
51595
51856
|
const now = opts.now ?? Date.now;
|
|
51596
|
-
const sessionsDir =
|
|
51597
|
-
const flagPath =
|
|
51857
|
+
const sessionsDir = path37.join(dataDir, "sessions");
|
|
51858
|
+
const flagPath = path37.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
51598
51859
|
if (existsSync3(flagPath)) {
|
|
51599
51860
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
51600
51861
|
}
|
|
51601
51862
|
let movedBare = 0;
|
|
51602
51863
|
let movedVmOwner = 0;
|
|
51603
51864
|
let archivedListener = 0;
|
|
51604
|
-
const defaultDir =
|
|
51865
|
+
const defaultDir = path37.join(sessionsDir, "default");
|
|
51605
51866
|
if (existsSync3(defaultDir)) {
|
|
51606
51867
|
for (const entry of readdirSafe(defaultDir)) {
|
|
51607
51868
|
if (!entry.endsWith(".json")) continue;
|
|
51608
|
-
const src =
|
|
51609
|
-
const dst =
|
|
51610
|
-
|
|
51869
|
+
const src = path37.join(defaultDir, entry);
|
|
51870
|
+
const dst = path37.join(sessionsDir, entry);
|
|
51871
|
+
fs37.renameSync(src, dst);
|
|
51611
51872
|
movedBare += 1;
|
|
51612
51873
|
}
|
|
51613
51874
|
rmdirIfEmpty(defaultDir);
|
|
51614
51875
|
}
|
|
51615
51876
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
51616
|
-
const personaDir =
|
|
51877
|
+
const personaDir = path37.join(sessionsDir, pid);
|
|
51617
51878
|
if (!isDir(personaDir)) continue;
|
|
51618
51879
|
if (pid === "default") continue;
|
|
51619
|
-
const ownerSrc =
|
|
51880
|
+
const ownerSrc = path37.join(personaDir, "owner");
|
|
51620
51881
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
51621
|
-
const ownerDst =
|
|
51622
|
-
|
|
51882
|
+
const ownerDst = path37.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
51883
|
+
fs37.mkdirSync(ownerDst, { recursive: true });
|
|
51623
51884
|
for (const file of readdirSafe(ownerSrc)) {
|
|
51624
51885
|
if (!file.endsWith(".json")) continue;
|
|
51625
|
-
|
|
51886
|
+
fs37.renameSync(path37.join(ownerSrc, file), path37.join(ownerDst, file));
|
|
51626
51887
|
movedVmOwner += 1;
|
|
51627
51888
|
}
|
|
51628
51889
|
rmdirIfEmpty(ownerSrc);
|
|
51629
51890
|
}
|
|
51630
|
-
const listenerSrc =
|
|
51891
|
+
const listenerSrc = path37.join(personaDir, "listener");
|
|
51631
51892
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
51632
|
-
const archiveDst =
|
|
51633
|
-
|
|
51893
|
+
const archiveDst = path37.join(dataDir, ".legacy", `listener-${pid}`);
|
|
51894
|
+
fs37.mkdirSync(archiveDst, { recursive: true });
|
|
51634
51895
|
for (const file of readdirSafe(listenerSrc)) {
|
|
51635
51896
|
if (!file.endsWith(".json")) continue;
|
|
51636
|
-
|
|
51897
|
+
fs37.renameSync(path37.join(listenerSrc, file), path37.join(archiveDst, file));
|
|
51637
51898
|
archivedListener += 1;
|
|
51638
51899
|
}
|
|
51639
51900
|
rmdirIfEmpty(listenerSrc);
|
|
51640
51901
|
}
|
|
51641
51902
|
rmdirIfEmpty(personaDir);
|
|
51642
51903
|
}
|
|
51643
|
-
|
|
51644
|
-
|
|
51904
|
+
fs37.mkdirSync(sessionsDir, { recursive: true });
|
|
51905
|
+
fs37.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
51645
51906
|
return {
|
|
51646
51907
|
skipped: false,
|
|
51647
51908
|
flagWritten: true,
|
|
@@ -51652,7 +51913,7 @@ function migrateFlattenSessions(opts) {
|
|
|
51652
51913
|
}
|
|
51653
51914
|
function existsSync3(p2) {
|
|
51654
51915
|
try {
|
|
51655
|
-
|
|
51916
|
+
fs37.statSync(p2);
|
|
51656
51917
|
return true;
|
|
51657
51918
|
} catch {
|
|
51658
51919
|
return false;
|
|
@@ -51660,31 +51921,31 @@ function existsSync3(p2) {
|
|
|
51660
51921
|
}
|
|
51661
51922
|
function isDir(p2) {
|
|
51662
51923
|
try {
|
|
51663
|
-
return
|
|
51924
|
+
return fs37.statSync(p2).isDirectory();
|
|
51664
51925
|
} catch {
|
|
51665
51926
|
return false;
|
|
51666
51927
|
}
|
|
51667
51928
|
}
|
|
51668
51929
|
function readdirSafe(p2) {
|
|
51669
51930
|
try {
|
|
51670
|
-
return
|
|
51931
|
+
return fs37.readdirSync(p2);
|
|
51671
51932
|
} catch {
|
|
51672
51933
|
return [];
|
|
51673
51934
|
}
|
|
51674
51935
|
}
|
|
51675
51936
|
function rmdirIfEmpty(p2) {
|
|
51676
51937
|
try {
|
|
51677
|
-
|
|
51938
|
+
fs37.rmdirSync(p2);
|
|
51678
51939
|
} catch {
|
|
51679
51940
|
}
|
|
51680
51941
|
}
|
|
51681
51942
|
|
|
51682
51943
|
// src/transport/http-router.ts
|
|
51683
|
-
var
|
|
51684
|
-
var
|
|
51944
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
51945
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
51685
51946
|
|
|
51686
51947
|
// src/attachment/mime.ts
|
|
51687
|
-
var
|
|
51948
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
51688
51949
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
51689
51950
|
var EXT_TO_NATIVE_MIME = {
|
|
51690
51951
|
// 图片
|
|
@@ -51791,7 +52052,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
51791
52052
|
".mk"
|
|
51792
52053
|
]);
|
|
51793
52054
|
function lookupMime(filePathOrName) {
|
|
51794
|
-
const ext =
|
|
52055
|
+
const ext = import_node_path30.default.extname(filePathOrName).toLowerCase();
|
|
51795
52056
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
51796
52057
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
51797
52058
|
return "application/octet-stream";
|
|
@@ -51860,8 +52121,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
51860
52121
|
}
|
|
51861
52122
|
|
|
51862
52123
|
// src/attachment/upload.ts
|
|
51863
|
-
var
|
|
51864
|
-
var
|
|
52124
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
52125
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
51865
52126
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
51866
52127
|
var import_promises3 = require("stream/promises");
|
|
51867
52128
|
var UploadError = class extends Error {
|
|
@@ -51873,22 +52134,22 @@ var UploadError = class extends Error {
|
|
|
51873
52134
|
code;
|
|
51874
52135
|
};
|
|
51875
52136
|
function assertValidFileName(fileName) {
|
|
51876
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
52137
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path31.default.basename(fileName)) {
|
|
51877
52138
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
51878
52139
|
}
|
|
51879
52140
|
}
|
|
51880
52141
|
var HASH_PREFIX_LEN = 16;
|
|
51881
52142
|
async function writeUploadedAttachment(args) {
|
|
51882
52143
|
assertValidFileName(args.fileName);
|
|
51883
|
-
const attachmentsRoot =
|
|
52144
|
+
const attachmentsRoot = import_node_path31.default.join(args.sessionDir, ".attachments");
|
|
51884
52145
|
try {
|
|
51885
|
-
|
|
52146
|
+
import_node_fs29.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
51886
52147
|
} catch (err) {
|
|
51887
52148
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
51888
52149
|
}
|
|
51889
52150
|
const hasher = import_node_crypto8.default.createHash("sha256");
|
|
51890
52151
|
let actualSize = 0;
|
|
51891
|
-
const tmpPath =
|
|
52152
|
+
const tmpPath = import_node_path31.default.join(
|
|
51892
52153
|
attachmentsRoot,
|
|
51893
52154
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto8.default.randomBytes(4).toString("hex")}`
|
|
51894
52155
|
);
|
|
@@ -51903,18 +52164,18 @@ async function writeUploadedAttachment(args) {
|
|
|
51903
52164
|
yield buf;
|
|
51904
52165
|
}
|
|
51905
52166
|
},
|
|
51906
|
-
|
|
52167
|
+
import_node_fs29.default.createWriteStream(tmpPath, { mode: 384 })
|
|
51907
52168
|
);
|
|
51908
52169
|
} catch (err) {
|
|
51909
52170
|
try {
|
|
51910
|
-
|
|
52171
|
+
import_node_fs29.default.unlinkSync(tmpPath);
|
|
51911
52172
|
} catch {
|
|
51912
52173
|
}
|
|
51913
52174
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
51914
52175
|
}
|
|
51915
52176
|
if (actualSize !== args.contentLength) {
|
|
51916
52177
|
try {
|
|
51917
|
-
|
|
52178
|
+
import_node_fs29.default.unlinkSync(tmpPath);
|
|
51918
52179
|
} catch {
|
|
51919
52180
|
}
|
|
51920
52181
|
throw new UploadError(
|
|
@@ -51923,35 +52184,35 @@ async function writeUploadedAttachment(args) {
|
|
|
51923
52184
|
);
|
|
51924
52185
|
}
|
|
51925
52186
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
51926
|
-
const hashDir =
|
|
52187
|
+
const hashDir = import_node_path31.default.join(attachmentsRoot, attachmentId);
|
|
51927
52188
|
let finalFileName;
|
|
51928
52189
|
let hashDirExists = false;
|
|
51929
52190
|
try {
|
|
51930
|
-
hashDirExists =
|
|
52191
|
+
hashDirExists = import_node_fs29.default.statSync(hashDir).isDirectory();
|
|
51931
52192
|
} catch {
|
|
51932
52193
|
}
|
|
51933
52194
|
if (hashDirExists) {
|
|
51934
|
-
const existing =
|
|
52195
|
+
const existing = import_node_fs29.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
51935
52196
|
finalFileName = existing[0] ?? args.fileName;
|
|
51936
52197
|
try {
|
|
51937
|
-
|
|
52198
|
+
import_node_fs29.default.unlinkSync(tmpPath);
|
|
51938
52199
|
} catch {
|
|
51939
52200
|
}
|
|
51940
52201
|
} else {
|
|
51941
52202
|
try {
|
|
51942
|
-
|
|
52203
|
+
import_node_fs29.default.mkdirSync(hashDir, { recursive: true });
|
|
51943
52204
|
finalFileName = args.fileName;
|
|
51944
|
-
|
|
52205
|
+
import_node_fs29.default.renameSync(tmpPath, import_node_path31.default.join(hashDir, finalFileName));
|
|
51945
52206
|
} catch (err) {
|
|
51946
52207
|
try {
|
|
51947
|
-
|
|
52208
|
+
import_node_fs29.default.unlinkSync(tmpPath);
|
|
51948
52209
|
} catch {
|
|
51949
52210
|
}
|
|
51950
52211
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
51951
52212
|
}
|
|
51952
52213
|
}
|
|
51953
|
-
const absPath =
|
|
51954
|
-
const relPath =
|
|
52214
|
+
const absPath = import_node_path31.default.join(hashDir, finalFileName);
|
|
52215
|
+
const relPath = import_node_path31.default.relative(args.sessionDir, absPath);
|
|
51955
52216
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
51956
52217
|
relPath: absPath,
|
|
51957
52218
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -51965,7 +52226,7 @@ async function writeUploadedAttachment(args) {
|
|
|
51965
52226
|
|
|
51966
52227
|
// src/extension/import.ts
|
|
51967
52228
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
51968
|
-
var
|
|
52229
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
51969
52230
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
51970
52231
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
51971
52232
|
var ImportError = class extends Error {
|
|
@@ -51983,7 +52244,7 @@ async function importZip(buf, root) {
|
|
|
51983
52244
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
51984
52245
|
}
|
|
51985
52246
|
for (const name of Object.keys(zip.files)) {
|
|
51986
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
52247
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path32.default.isAbsolute(name)) {
|
|
51987
52248
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
51988
52249
|
}
|
|
51989
52250
|
}
|
|
@@ -52016,7 +52277,7 @@ async function importZip(buf, root) {
|
|
|
52016
52277
|
);
|
|
52017
52278
|
}
|
|
52018
52279
|
}
|
|
52019
|
-
const destDir =
|
|
52280
|
+
const destDir = import_node_path32.default.join(root, manifest.id);
|
|
52020
52281
|
let destExists = false;
|
|
52021
52282
|
try {
|
|
52022
52283
|
await import_promises4.default.access(destDir);
|
|
@@ -52026,15 +52287,15 @@ async function importZip(buf, root) {
|
|
|
52026
52287
|
if (destExists) {
|
|
52027
52288
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
52028
52289
|
}
|
|
52029
|
-
const stage = await import_promises4.default.mkdtemp(
|
|
52290
|
+
const stage = await import_promises4.default.mkdtemp(import_node_path32.default.join(import_node_os12.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
52030
52291
|
try {
|
|
52031
52292
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
52032
|
-
const dest =
|
|
52293
|
+
const dest = import_node_path32.default.join(stage, name);
|
|
52033
52294
|
if (entry.dir) {
|
|
52034
52295
|
await import_promises4.default.mkdir(dest, { recursive: true });
|
|
52035
52296
|
continue;
|
|
52036
52297
|
}
|
|
52037
|
-
await import_promises4.default.mkdir(
|
|
52298
|
+
await import_promises4.default.mkdir(import_node_path32.default.dirname(dest), { recursive: true });
|
|
52038
52299
|
const content = await entry.async("nodebuffer");
|
|
52039
52300
|
await import_promises4.default.writeFile(dest, content);
|
|
52040
52301
|
}
|
|
@@ -52065,7 +52326,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
52065
52326
|
".wasm": "application/wasm"
|
|
52066
52327
|
};
|
|
52067
52328
|
function shareUiAssetMime(filePath) {
|
|
52068
|
-
const ext =
|
|
52329
|
+
const ext = import_node_path33.default.extname(filePath).toLowerCase();
|
|
52069
52330
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
52070
52331
|
}
|
|
52071
52332
|
var DISPATCH_HEARTBEAT_MS = 25e3;
|
|
@@ -52152,7 +52413,7 @@ function isValidUploadFileName(fileName) {
|
|
|
52152
52413
|
if (fileName === "." || fileName === "..") return false;
|
|
52153
52414
|
if (fileName.startsWith(".")) return false;
|
|
52154
52415
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
52155
|
-
return fileName ===
|
|
52416
|
+
return fileName === import_node_path33.default.basename(fileName);
|
|
52156
52417
|
}
|
|
52157
52418
|
function createHttpRouter(deps) {
|
|
52158
52419
|
return async (req, res) => {
|
|
@@ -52224,7 +52485,7 @@ function createHttpRouter(deps) {
|
|
|
52224
52485
|
}
|
|
52225
52486
|
let buf;
|
|
52226
52487
|
try {
|
|
52227
|
-
buf = await
|
|
52488
|
+
buf = await import_node_fs30.default.promises.readFile(abs);
|
|
52228
52489
|
} catch {
|
|
52229
52490
|
sendJson(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
52230
52491
|
return true;
|
|
@@ -52448,7 +52709,7 @@ function createHttpRouter(deps) {
|
|
|
52448
52709
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
52449
52710
|
return true;
|
|
52450
52711
|
}
|
|
52451
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
52712
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path33.default.basename(r.absPath)));
|
|
52452
52713
|
return true;
|
|
52453
52714
|
}
|
|
52454
52715
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -52569,7 +52830,7 @@ function createHttpRouter(deps) {
|
|
|
52569
52830
|
return true;
|
|
52570
52831
|
}
|
|
52571
52832
|
let absPath;
|
|
52572
|
-
if (
|
|
52833
|
+
if (import_node_path33.default.isAbsolute(pathParam)) {
|
|
52573
52834
|
absPath = pathParam;
|
|
52574
52835
|
} else if (deps.sessionStore) {
|
|
52575
52836
|
const file = deps.sessionStore.read(sid);
|
|
@@ -52577,7 +52838,7 @@ function createHttpRouter(deps) {
|
|
|
52577
52838
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
52578
52839
|
return true;
|
|
52579
52840
|
}
|
|
52580
|
-
absPath =
|
|
52841
|
+
absPath = import_node_path33.default.join(file.cwd, pathParam);
|
|
52581
52842
|
} else {
|
|
52582
52843
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
52583
52844
|
return true;
|
|
@@ -52664,7 +52925,7 @@ function withCtx(ctx, body) {
|
|
|
52664
52925
|
function streamFile(res, absPath, logger) {
|
|
52665
52926
|
let stat;
|
|
52666
52927
|
try {
|
|
52667
|
-
stat =
|
|
52928
|
+
stat = import_node_fs30.default.statSync(absPath);
|
|
52668
52929
|
} catch (err) {
|
|
52669
52930
|
const code = err?.code;
|
|
52670
52931
|
if (code === "ENOENT") {
|
|
@@ -52679,7 +52940,7 @@ function streamFile(res, absPath, logger) {
|
|
|
52679
52940
|
return;
|
|
52680
52941
|
}
|
|
52681
52942
|
const mime = lookupMime(absPath);
|
|
52682
|
-
const basename =
|
|
52943
|
+
const basename = import_node_path33.default.basename(absPath);
|
|
52683
52944
|
res.writeHead(200, {
|
|
52684
52945
|
"Content-Type": mime,
|
|
52685
52946
|
"Content-Length": String(stat.size),
|
|
@@ -52687,7 +52948,7 @@ function streamFile(res, absPath, logger) {
|
|
|
52687
52948
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
52688
52949
|
"X-Content-Type-Options": "nosniff"
|
|
52689
52950
|
});
|
|
52690
|
-
const stream =
|
|
52951
|
+
const stream = import_node_fs30.default.createReadStream(absPath);
|
|
52691
52952
|
stream.on("error", (err) => {
|
|
52692
52953
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
52693
52954
|
res.destroy();
|
|
@@ -52696,8 +52957,8 @@ function streamFile(res, absPath, logger) {
|
|
|
52696
52957
|
}
|
|
52697
52958
|
|
|
52698
52959
|
// src/attachment/gc.ts
|
|
52699
|
-
var
|
|
52700
|
-
var
|
|
52960
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
52961
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
52701
52962
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
52702
52963
|
function runAttachmentGc(args) {
|
|
52703
52964
|
const now = (args.now ?? Date.now)();
|
|
@@ -52706,38 +52967,38 @@ function runAttachmentGc(args) {
|
|
|
52706
52967
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
52707
52968
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
52708
52969
|
if (entry.stale) continue;
|
|
52709
|
-
if (
|
|
52970
|
+
if (import_node_path34.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
52710
52971
|
}
|
|
52711
52972
|
}
|
|
52712
52973
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
52713
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
52974
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path34.default.join(
|
|
52714
52975
|
args.dataDir,
|
|
52715
52976
|
"sessions",
|
|
52716
52977
|
...scopeSubPath(scope).map(safeFileName),
|
|
52717
52978
|
safeFileName(sessionId)
|
|
52718
52979
|
);
|
|
52719
|
-
const attRoot =
|
|
52980
|
+
const attRoot = import_node_path34.default.join(sessionDir, ".attachments");
|
|
52720
52981
|
let hashDirs;
|
|
52721
52982
|
try {
|
|
52722
|
-
hashDirs =
|
|
52983
|
+
hashDirs = import_node_fs31.default.readdirSync(attRoot);
|
|
52723
52984
|
} catch (err) {
|
|
52724
52985
|
if (err.code === "ENOENT") continue;
|
|
52725
52986
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
52726
52987
|
continue;
|
|
52727
52988
|
}
|
|
52728
52989
|
for (const hashDir of hashDirs) {
|
|
52729
|
-
const hashDirAbs =
|
|
52990
|
+
const hashDirAbs = import_node_path34.default.join(attRoot, hashDir);
|
|
52730
52991
|
let files;
|
|
52731
52992
|
try {
|
|
52732
|
-
files =
|
|
52993
|
+
files = import_node_fs31.default.readdirSync(hashDirAbs);
|
|
52733
52994
|
} catch {
|
|
52734
52995
|
continue;
|
|
52735
52996
|
}
|
|
52736
52997
|
for (const name of files) {
|
|
52737
|
-
const file =
|
|
52998
|
+
const file = import_node_path34.default.join(hashDirAbs, name);
|
|
52738
52999
|
let stat;
|
|
52739
53000
|
try {
|
|
52740
|
-
stat =
|
|
53001
|
+
stat = import_node_fs31.default.statSync(file);
|
|
52741
53002
|
} catch {
|
|
52742
53003
|
continue;
|
|
52743
53004
|
}
|
|
@@ -52746,26 +53007,26 @@ function runAttachmentGc(args) {
|
|
|
52746
53007
|
if (age < ttlMs) continue;
|
|
52747
53008
|
if (liveAbs.has(file)) continue;
|
|
52748
53009
|
try {
|
|
52749
|
-
|
|
53010
|
+
import_node_fs31.default.unlinkSync(file);
|
|
52750
53011
|
} catch (err) {
|
|
52751
53012
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
52752
53013
|
}
|
|
52753
53014
|
}
|
|
52754
53015
|
try {
|
|
52755
|
-
if (
|
|
53016
|
+
if (import_node_fs31.default.readdirSync(hashDirAbs).length === 0) import_node_fs31.default.rmdirSync(hashDirAbs);
|
|
52756
53017
|
} catch {
|
|
52757
53018
|
}
|
|
52758
53019
|
}
|
|
52759
53020
|
try {
|
|
52760
|
-
if (
|
|
53021
|
+
if (import_node_fs31.default.readdirSync(attRoot).length === 0) import_node_fs31.default.rmdirSync(attRoot);
|
|
52761
53022
|
} catch {
|
|
52762
53023
|
}
|
|
52763
53024
|
}
|
|
52764
53025
|
}
|
|
52765
53026
|
|
|
52766
53027
|
// src/attachment/group.ts
|
|
52767
|
-
var
|
|
52768
|
-
var
|
|
53028
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
53029
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
52769
53030
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
52770
53031
|
init_protocol();
|
|
52771
53032
|
var GroupFileStore = class {
|
|
@@ -52777,11 +53038,11 @@ var GroupFileStore = class {
|
|
|
52777
53038
|
this.logger = opts.logger;
|
|
52778
53039
|
}
|
|
52779
53040
|
rootForScope(scope) {
|
|
52780
|
-
return
|
|
53041
|
+
return import_node_path35.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
52781
53042
|
}
|
|
52782
53043
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
52783
53044
|
filePath(scope, sessionId) {
|
|
52784
|
-
return
|
|
53045
|
+
return import_node_path35.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
52785
53046
|
}
|
|
52786
53047
|
cacheKey(scope, sessionId) {
|
|
52787
53048
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -52790,7 +53051,7 @@ var GroupFileStore = class {
|
|
|
52790
53051
|
readFile(scope, sessionId) {
|
|
52791
53052
|
const file = this.filePath(scope, sessionId);
|
|
52792
53053
|
try {
|
|
52793
|
-
const raw =
|
|
53054
|
+
const raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
52794
53055
|
const parsed = JSON.parse(raw);
|
|
52795
53056
|
if (!Array.isArray(parsed)) {
|
|
52796
53057
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -52816,10 +53077,10 @@ var GroupFileStore = class {
|
|
|
52816
53077
|
}
|
|
52817
53078
|
writeFile(scope, sessionId, entries) {
|
|
52818
53079
|
const file = this.filePath(scope, sessionId);
|
|
52819
|
-
|
|
53080
|
+
import_node_fs32.default.mkdirSync(import_node_path35.default.dirname(file), { recursive: true });
|
|
52820
53081
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
52821
|
-
|
|
52822
|
-
|
|
53082
|
+
import_node_fs32.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
53083
|
+
import_node_fs32.default.renameSync(tmp, file);
|
|
52823
53084
|
}
|
|
52824
53085
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
52825
53086
|
list(scope, sessionId) {
|
|
@@ -52905,10 +53166,10 @@ var GroupFileStore = class {
|
|
|
52905
53166
|
};
|
|
52906
53167
|
|
|
52907
53168
|
// src/discovery/state-file.ts
|
|
52908
|
-
var
|
|
52909
|
-
var
|
|
53169
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
53170
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
52910
53171
|
function defaultStateFilePath(dataDir) {
|
|
52911
|
-
return
|
|
53172
|
+
return import_node_path36.default.join(dataDir, "state.json");
|
|
52912
53173
|
}
|
|
52913
53174
|
function isPidAlive(pid) {
|
|
52914
53175
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -52930,7 +53191,7 @@ var StateFileManager = class {
|
|
|
52930
53191
|
}
|
|
52931
53192
|
read() {
|
|
52932
53193
|
try {
|
|
52933
|
-
const raw =
|
|
53194
|
+
const raw = import_node_fs33.default.readFileSync(this.file, "utf8");
|
|
52934
53195
|
const parsed = JSON.parse(raw);
|
|
52935
53196
|
return parsed;
|
|
52936
53197
|
} catch {
|
|
@@ -52944,20 +53205,20 @@ var StateFileManager = class {
|
|
|
52944
53205
|
return { status: "stale", existing };
|
|
52945
53206
|
}
|
|
52946
53207
|
write(state) {
|
|
52947
|
-
|
|
53208
|
+
import_node_fs33.default.mkdirSync(import_node_path36.default.dirname(this.file), { recursive: true });
|
|
52948
53209
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
52949
|
-
|
|
52950
|
-
|
|
53210
|
+
import_node_fs33.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
53211
|
+
import_node_fs33.default.renameSync(tmp, this.file);
|
|
52951
53212
|
if (process.platform !== "win32") {
|
|
52952
53213
|
try {
|
|
52953
|
-
|
|
53214
|
+
import_node_fs33.default.chmodSync(this.file, 384);
|
|
52954
53215
|
} catch {
|
|
52955
53216
|
}
|
|
52956
53217
|
}
|
|
52957
53218
|
}
|
|
52958
53219
|
delete() {
|
|
52959
53220
|
try {
|
|
52960
|
-
|
|
53221
|
+
import_node_fs33.default.unlinkSync(this.file);
|
|
52961
53222
|
} catch {
|
|
52962
53223
|
}
|
|
52963
53224
|
}
|
|
@@ -52971,14 +53232,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
52971
53232
|
}
|
|
52972
53233
|
|
|
52973
53234
|
// src/tunnel/tunnel-manager.ts
|
|
52974
|
-
var
|
|
52975
|
-
var
|
|
53235
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
53236
|
+
var import_node_path40 = __toESM(require("path"), 1);
|
|
52976
53237
|
var import_node_crypto10 = __toESM(require("crypto"), 1);
|
|
52977
|
-
var
|
|
53238
|
+
var import_node_child_process10 = require("child_process");
|
|
52978
53239
|
|
|
52979
53240
|
// src/tunnel/tunnel-store.ts
|
|
52980
|
-
var
|
|
52981
|
-
var
|
|
53241
|
+
var import_node_fs34 = __toESM(require("fs"), 1);
|
|
53242
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
52982
53243
|
var TunnelStore = class {
|
|
52983
53244
|
constructor(filePath) {
|
|
52984
53245
|
this.filePath = filePath;
|
|
@@ -52986,7 +53247,7 @@ var TunnelStore = class {
|
|
|
52986
53247
|
filePath;
|
|
52987
53248
|
async get() {
|
|
52988
53249
|
try {
|
|
52989
|
-
const raw = await
|
|
53250
|
+
const raw = await import_node_fs34.default.promises.readFile(this.filePath, "utf8");
|
|
52990
53251
|
const obj = JSON.parse(raw);
|
|
52991
53252
|
if (!isPersistedTunnel(obj)) return null;
|
|
52992
53253
|
return obj;
|
|
@@ -52997,22 +53258,22 @@ var TunnelStore = class {
|
|
|
52997
53258
|
}
|
|
52998
53259
|
}
|
|
52999
53260
|
async set(v2) {
|
|
53000
|
-
const dir =
|
|
53001
|
-
await
|
|
53261
|
+
const dir = import_node_path37.default.dirname(this.filePath);
|
|
53262
|
+
await import_node_fs34.default.promises.mkdir(dir, { recursive: true });
|
|
53002
53263
|
const data = JSON.stringify(v2, null, 2);
|
|
53003
53264
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
53004
|
-
await
|
|
53265
|
+
await import_node_fs34.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
53005
53266
|
if (process.platform !== "win32") {
|
|
53006
53267
|
try {
|
|
53007
|
-
await
|
|
53268
|
+
await import_node_fs34.default.promises.chmod(tmp, 384);
|
|
53008
53269
|
} catch {
|
|
53009
53270
|
}
|
|
53010
53271
|
}
|
|
53011
|
-
await
|
|
53272
|
+
await import_node_fs34.default.promises.rename(tmp, this.filePath);
|
|
53012
53273
|
}
|
|
53013
53274
|
async clear() {
|
|
53014
53275
|
try {
|
|
53015
|
-
await
|
|
53276
|
+
await import_node_fs34.default.promises.unlink(this.filePath);
|
|
53016
53277
|
} catch (err) {
|
|
53017
53278
|
const code = err?.code;
|
|
53018
53279
|
if (code !== "ENOENT") throw err;
|
|
@@ -53107,10 +53368,10 @@ function escape(v2) {
|
|
|
53107
53368
|
}
|
|
53108
53369
|
|
|
53109
53370
|
// src/tunnel/frpc-binary.ts
|
|
53110
|
-
var
|
|
53371
|
+
var import_node_fs35 = __toESM(require("fs"), 1);
|
|
53111
53372
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
53112
|
-
var
|
|
53113
|
-
var
|
|
53373
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
53374
|
+
var import_node_child_process8 = require("child_process");
|
|
53114
53375
|
var import_node_stream3 = require("stream");
|
|
53115
53376
|
var import_promises5 = require("stream/promises");
|
|
53116
53377
|
var FRPC_VERSION = "0.68.0";
|
|
@@ -53141,20 +53402,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
53141
53402
|
}
|
|
53142
53403
|
async function ensureFrpcBinary(opts) {
|
|
53143
53404
|
if (opts.override) {
|
|
53144
|
-
if (!
|
|
53405
|
+
if (!import_node_fs35.default.existsSync(opts.override)) {
|
|
53145
53406
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
53146
53407
|
}
|
|
53147
53408
|
return opts.override;
|
|
53148
53409
|
}
|
|
53149
53410
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
53150
53411
|
const platform = opts.platform ?? detectPlatform();
|
|
53151
|
-
const binDir =
|
|
53152
|
-
|
|
53412
|
+
const binDir = import_node_path38.default.join(opts.dataDir, "bin");
|
|
53413
|
+
import_node_fs35.default.mkdirSync(binDir, { recursive: true });
|
|
53153
53414
|
cleanupStaleArtifacts(binDir);
|
|
53154
|
-
const stableBin =
|
|
53155
|
-
if (
|
|
53415
|
+
const stableBin = import_node_path38.default.join(binDir, "frpc");
|
|
53416
|
+
if (import_node_fs35.default.existsSync(stableBin)) return stableBin;
|
|
53156
53417
|
const partialBin = `${stableBin}.partial`;
|
|
53157
|
-
const tarballPath =
|
|
53418
|
+
const tarballPath = import_node_path38.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
53158
53419
|
try {
|
|
53159
53420
|
const url = frpcDownloadUrl(version2, platform);
|
|
53160
53421
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -53163,8 +53424,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
53163
53424
|
} else {
|
|
53164
53425
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
53165
53426
|
}
|
|
53166
|
-
|
|
53167
|
-
|
|
53427
|
+
import_node_fs35.default.chmodSync(partialBin, 493);
|
|
53428
|
+
import_node_fs35.default.renameSync(partialBin, stableBin);
|
|
53168
53429
|
} finally {
|
|
53169
53430
|
safeUnlink(tarballPath);
|
|
53170
53431
|
safeUnlink(partialBin);
|
|
@@ -53174,15 +53435,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
53174
53435
|
function cleanupStaleArtifacts(binDir) {
|
|
53175
53436
|
let entries;
|
|
53176
53437
|
try {
|
|
53177
|
-
entries =
|
|
53438
|
+
entries = import_node_fs35.default.readdirSync(binDir);
|
|
53178
53439
|
} catch {
|
|
53179
53440
|
return;
|
|
53180
53441
|
}
|
|
53181
53442
|
for (const name of entries) {
|
|
53182
53443
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
53183
|
-
const full =
|
|
53444
|
+
const full = import_node_path38.default.join(binDir, name);
|
|
53184
53445
|
try {
|
|
53185
|
-
|
|
53446
|
+
import_node_fs35.default.rmSync(full, { recursive: true, force: true });
|
|
53186
53447
|
} catch {
|
|
53187
53448
|
}
|
|
53188
53449
|
}
|
|
@@ -53190,7 +53451,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
53190
53451
|
}
|
|
53191
53452
|
function safeUnlink(p2) {
|
|
53192
53453
|
try {
|
|
53193
|
-
|
|
53454
|
+
import_node_fs35.default.unlinkSync(p2);
|
|
53194
53455
|
} catch {
|
|
53195
53456
|
}
|
|
53196
53457
|
}
|
|
@@ -53201,46 +53462,46 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
53201
53462
|
if (!res.ok || !res.body) {
|
|
53202
53463
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
53203
53464
|
}
|
|
53204
|
-
const out =
|
|
53465
|
+
const out = import_node_fs35.default.createWriteStream(dest);
|
|
53205
53466
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
53206
53467
|
await (0, import_promises5.pipeline)(nodeStream, out);
|
|
53207
53468
|
}
|
|
53208
53469
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
53209
|
-
const work =
|
|
53210
|
-
|
|
53470
|
+
const work = import_node_path38.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
53471
|
+
import_node_fs35.default.mkdirSync(work, { recursive: true });
|
|
53211
53472
|
try {
|
|
53212
53473
|
await new Promise((resolve6, reject) => {
|
|
53213
|
-
const proc = (0,
|
|
53474
|
+
const proc = (0, import_node_child_process8.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
53214
53475
|
proc.on("error", reject);
|
|
53215
53476
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
53216
53477
|
});
|
|
53217
53478
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
53218
|
-
const src =
|
|
53219
|
-
if (!
|
|
53479
|
+
const src = import_node_path38.default.join(work, dirName, "frpc");
|
|
53480
|
+
if (!import_node_fs35.default.existsSync(src)) {
|
|
53220
53481
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
53221
53482
|
}
|
|
53222
|
-
|
|
53483
|
+
import_node_fs35.default.copyFileSync(src, destBin);
|
|
53223
53484
|
} finally {
|
|
53224
|
-
|
|
53485
|
+
import_node_fs35.default.rmSync(work, { recursive: true, force: true });
|
|
53225
53486
|
}
|
|
53226
53487
|
}
|
|
53227
53488
|
|
|
53228
53489
|
// src/tunnel/frpc-process.ts
|
|
53229
|
-
var
|
|
53230
|
-
var
|
|
53231
|
-
var
|
|
53490
|
+
var import_node_fs36 = __toESM(require("fs"), 1);
|
|
53491
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
53492
|
+
var import_node_child_process9 = require("child_process");
|
|
53232
53493
|
function frpcPidFilePath(dataDir) {
|
|
53233
|
-
return
|
|
53494
|
+
return import_node_path39.default.join(dataDir, "frpc.pid");
|
|
53234
53495
|
}
|
|
53235
53496
|
function writeFrpcPid(dataDir, pid) {
|
|
53236
53497
|
try {
|
|
53237
|
-
|
|
53498
|
+
import_node_fs36.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
53238
53499
|
} catch {
|
|
53239
53500
|
}
|
|
53240
53501
|
}
|
|
53241
53502
|
function clearFrpcPid(dataDir) {
|
|
53242
53503
|
try {
|
|
53243
|
-
|
|
53504
|
+
import_node_fs36.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
53244
53505
|
} catch {
|
|
53245
53506
|
}
|
|
53246
53507
|
}
|
|
@@ -53256,7 +53517,7 @@ function defaultIsPidAlive(pid) {
|
|
|
53256
53517
|
}
|
|
53257
53518
|
function defaultReadPidFile(file) {
|
|
53258
53519
|
try {
|
|
53259
|
-
return
|
|
53520
|
+
return import_node_fs36.default.readFileSync(file, "utf8");
|
|
53260
53521
|
} catch {
|
|
53261
53522
|
return null;
|
|
53262
53523
|
}
|
|
@@ -53272,7 +53533,7 @@ function defaultSleep(ms) {
|
|
|
53272
53533
|
}
|
|
53273
53534
|
async function killStaleFrpc(deps) {
|
|
53274
53535
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
53275
|
-
const tomlPath =
|
|
53536
|
+
const tomlPath = import_node_path39.default.join(deps.dataDir, "frpc.toml");
|
|
53276
53537
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
53277
53538
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
53278
53539
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -53296,7 +53557,7 @@ async function killStaleFrpc(deps) {
|
|
|
53296
53557
|
}
|
|
53297
53558
|
if (victims.size === 0) {
|
|
53298
53559
|
try {
|
|
53299
|
-
|
|
53560
|
+
import_node_fs36.default.unlinkSync(pidFile);
|
|
53300
53561
|
} catch {
|
|
53301
53562
|
}
|
|
53302
53563
|
return;
|
|
@@ -53307,14 +53568,14 @@ async function killStaleFrpc(deps) {
|
|
|
53307
53568
|
}
|
|
53308
53569
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
53309
53570
|
try {
|
|
53310
|
-
|
|
53571
|
+
import_node_fs36.default.unlinkSync(pidFile);
|
|
53311
53572
|
} catch {
|
|
53312
53573
|
}
|
|
53313
53574
|
}
|
|
53314
53575
|
async function defaultScanFrpcPidsByCmdline(tomlPath, logger) {
|
|
53315
53576
|
if (process.platform === "win32") return [];
|
|
53316
53577
|
return new Promise((resolve6) => {
|
|
53317
|
-
const ps = (0,
|
|
53578
|
+
const ps = (0, import_node_child_process9.spawn)("ps", ["-axo", "pid=,command="], { stdio: ["ignore", "pipe", "ignore"] });
|
|
53318
53579
|
let buf = "";
|
|
53319
53580
|
ps.stdout.on("data", (c) => {
|
|
53320
53581
|
buf += c.toString();
|
|
@@ -53344,7 +53605,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
53344
53605
|
var TunnelManager = class {
|
|
53345
53606
|
constructor(deps) {
|
|
53346
53607
|
this.deps = deps;
|
|
53347
|
-
this.store = deps.store ?? new TunnelStore(
|
|
53608
|
+
this.store = deps.store ?? new TunnelStore(import_node_path40.default.join(deps.dataDir, "tunnel.json"));
|
|
53348
53609
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
53349
53610
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
53350
53611
|
}
|
|
@@ -53471,7 +53732,7 @@ var TunnelManager = class {
|
|
|
53471
53732
|
dataDir: this.deps.dataDir,
|
|
53472
53733
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
53473
53734
|
});
|
|
53474
|
-
const tomlPath =
|
|
53735
|
+
const tomlPath = import_node_path40.default.join(this.deps.dataDir, "frpc.toml");
|
|
53475
53736
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto10.default.randomBytes(3).toString("hex")}`;
|
|
53476
53737
|
const toml = buildFrpcToml({
|
|
53477
53738
|
serverAddr: t.frpsHost,
|
|
@@ -53482,14 +53743,14 @@ var TunnelManager = class {
|
|
|
53482
53743
|
localPort,
|
|
53483
53744
|
logLevel: "info"
|
|
53484
53745
|
});
|
|
53485
|
-
await
|
|
53486
|
-
const proc = (this.deps.spawnImpl ??
|
|
53746
|
+
await import_node_fs37.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
53747
|
+
const proc = (this.deps.spawnImpl ?? import_node_child_process10.spawn)(frpcBin, ["-c", tomlPath], {
|
|
53487
53748
|
stdio: ["ignore", "pipe", "pipe"]
|
|
53488
53749
|
});
|
|
53489
|
-
const logDir =
|
|
53490
|
-
|
|
53491
|
-
const logFilePath =
|
|
53492
|
-
const logStream =
|
|
53750
|
+
const logDir = import_node_path40.default.join(this.deps.dataDir, "log");
|
|
53751
|
+
import_node_fs37.default.mkdirSync(logDir, { recursive: true });
|
|
53752
|
+
const logFilePath = import_node_path40.default.join(logDir, "frpc.log");
|
|
53753
|
+
const logStream = import_node_fs37.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
53493
53754
|
logStream.on("error", () => {
|
|
53494
53755
|
});
|
|
53495
53756
|
const tee = (chunk) => {
|
|
@@ -53572,27 +53833,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
53572
53833
|
|
|
53573
53834
|
// src/tunnel/device-key.ts
|
|
53574
53835
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
53575
|
-
var
|
|
53836
|
+
var import_node_path41 = __toESM(require("path"), 1);
|
|
53576
53837
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
53577
53838
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
53578
53839
|
function deriveStableDeviceKey(opts = {}) {
|
|
53579
53840
|
const hostname = opts.hostname ?? import_node_os14.default.hostname();
|
|
53580
53841
|
const uid = opts.uid ?? (typeof import_node_os14.default.userInfo === "function" ? import_node_os14.default.userInfo().uid : 0);
|
|
53581
53842
|
const home = opts.home ?? import_node_os14.default.homedir();
|
|
53582
|
-
const defaultDataDir =
|
|
53583
|
-
const normalizedDataDir = opts.dataDir ?
|
|
53843
|
+
const defaultDataDir = import_node_path41.default.resolve(import_node_path41.default.join(home, ".clawd"));
|
|
53844
|
+
const normalizedDataDir = opts.dataDir ? import_node_path41.default.resolve(opts.dataDir) : null;
|
|
53584
53845
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
53585
53846
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
53586
53847
|
return import_node_crypto11.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
53587
53848
|
}
|
|
53588
53849
|
|
|
53589
53850
|
// src/auth-store.ts
|
|
53590
|
-
var
|
|
53591
|
-
var
|
|
53851
|
+
var import_node_fs38 = __toESM(require("fs"), 1);
|
|
53852
|
+
var import_node_path42 = __toESM(require("path"), 1);
|
|
53592
53853
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
53593
53854
|
var AUTH_FILE_NAME = "auth.json";
|
|
53594
53855
|
function authFilePath(dataDir) {
|
|
53595
|
-
return
|
|
53856
|
+
return import_node_path42.default.join(dataDir, AUTH_FILE_NAME);
|
|
53596
53857
|
}
|
|
53597
53858
|
function loadOrCreateAuthFile(opts) {
|
|
53598
53859
|
const file = authFilePath(opts.dataDir);
|
|
@@ -53628,7 +53889,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
53628
53889
|
}
|
|
53629
53890
|
function readAuthFile(file) {
|
|
53630
53891
|
try {
|
|
53631
|
-
const raw =
|
|
53892
|
+
const raw = import_node_fs38.default.readFileSync(file, "utf8");
|
|
53632
53893
|
const parsed = JSON.parse(raw);
|
|
53633
53894
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
53634
53895
|
return null;
|
|
@@ -53648,25 +53909,25 @@ function readAuthFile(file) {
|
|
|
53648
53909
|
}
|
|
53649
53910
|
}
|
|
53650
53911
|
function writeAuthFile(file, content) {
|
|
53651
|
-
|
|
53652
|
-
|
|
53912
|
+
import_node_fs38.default.mkdirSync(import_node_path42.default.dirname(file), { recursive: true });
|
|
53913
|
+
import_node_fs38.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
53653
53914
|
try {
|
|
53654
|
-
|
|
53915
|
+
import_node_fs38.default.chmodSync(file, 384);
|
|
53655
53916
|
} catch {
|
|
53656
53917
|
}
|
|
53657
53918
|
}
|
|
53658
53919
|
|
|
53659
53920
|
// src/owner-profile.ts
|
|
53660
|
-
var
|
|
53921
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
53661
53922
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
53662
|
-
var
|
|
53923
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
53663
53924
|
var PROFILE_FILENAME = "profile.json";
|
|
53664
53925
|
function loadOwnerDisplayName(dataDir) {
|
|
53665
53926
|
const fallback = import_node_os15.default.userInfo().username;
|
|
53666
|
-
const profilePath =
|
|
53927
|
+
const profilePath = import_node_path43.default.join(dataDir, PROFILE_FILENAME);
|
|
53667
53928
|
let raw;
|
|
53668
53929
|
try {
|
|
53669
|
-
raw =
|
|
53930
|
+
raw = import_node_fs39.default.readFileSync(profilePath, "utf8");
|
|
53670
53931
|
} catch {
|
|
53671
53932
|
return fallback;
|
|
53672
53933
|
}
|
|
@@ -53689,18 +53950,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
53689
53950
|
}
|
|
53690
53951
|
|
|
53691
53952
|
// src/feishu-auth/owner-identity-store.ts
|
|
53692
|
-
var
|
|
53693
|
-
var
|
|
53953
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
53954
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
53694
53955
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
53695
53956
|
var OwnerIdentityStore = class {
|
|
53696
53957
|
file;
|
|
53697
53958
|
constructor(dataDir) {
|
|
53698
|
-
this.file =
|
|
53959
|
+
this.file = import_node_path44.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
53699
53960
|
}
|
|
53700
53961
|
read() {
|
|
53701
53962
|
let raw;
|
|
53702
53963
|
try {
|
|
53703
|
-
raw =
|
|
53964
|
+
raw = import_node_fs40.default.readFileSync(this.file, "utf8");
|
|
53704
53965
|
} catch {
|
|
53705
53966
|
return null;
|
|
53706
53967
|
}
|
|
@@ -53728,16 +53989,16 @@ var OwnerIdentityStore = class {
|
|
|
53728
53989
|
};
|
|
53729
53990
|
}
|
|
53730
53991
|
write(record) {
|
|
53731
|
-
|
|
53732
|
-
|
|
53992
|
+
import_node_fs40.default.mkdirSync(import_node_path44.default.dirname(this.file), { recursive: true });
|
|
53993
|
+
import_node_fs40.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
53733
53994
|
try {
|
|
53734
|
-
|
|
53995
|
+
import_node_fs40.default.chmodSync(this.file, 384);
|
|
53735
53996
|
} catch {
|
|
53736
53997
|
}
|
|
53737
53998
|
}
|
|
53738
53999
|
clear() {
|
|
53739
54000
|
try {
|
|
53740
|
-
|
|
54001
|
+
import_node_fs40.default.unlinkSync(this.file);
|
|
53741
54002
|
} catch (err) {
|
|
53742
54003
|
const code = err?.code;
|
|
53743
54004
|
if (code !== "ENOENT") throw err;
|
|
@@ -53874,9 +54135,9 @@ var CentralClientError = class extends Error {
|
|
|
53874
54135
|
code;
|
|
53875
54136
|
cause;
|
|
53876
54137
|
};
|
|
53877
|
-
async function centralRequest(opts,
|
|
54138
|
+
async function centralRequest(opts, path74, init) {
|
|
53878
54139
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
53879
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
54140
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path74}`;
|
|
53880
54141
|
const ctrl = new AbortController();
|
|
53881
54142
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
53882
54143
|
let res;
|
|
@@ -54070,8 +54331,8 @@ function verifyConnectToken(args) {
|
|
|
54070
54331
|
}
|
|
54071
54332
|
|
|
54072
54333
|
// src/feishu-auth/server-key.ts
|
|
54073
|
-
var
|
|
54074
|
-
var
|
|
54334
|
+
var fs51 = __toESM(require("fs"), 1);
|
|
54335
|
+
var path53 = __toESM(require("path"), 1);
|
|
54075
54336
|
var FILE_NAME2 = "server-signing-key.json";
|
|
54076
54337
|
var ServerKeyStore = class {
|
|
54077
54338
|
constructor(dataDir) {
|
|
@@ -54079,12 +54340,12 @@ var ServerKeyStore = class {
|
|
|
54079
54340
|
}
|
|
54080
54341
|
dataDir;
|
|
54081
54342
|
filePath() {
|
|
54082
|
-
return
|
|
54343
|
+
return path53.join(this.dataDir, FILE_NAME2);
|
|
54083
54344
|
}
|
|
54084
54345
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
54085
54346
|
read() {
|
|
54086
54347
|
try {
|
|
54087
|
-
const raw =
|
|
54348
|
+
const raw = fs51.readFileSync(this.filePath(), "utf8");
|
|
54088
54349
|
const parsed = JSON.parse(raw);
|
|
54089
54350
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
54090
54351
|
return parsed.publicKeyPem;
|
|
@@ -54099,12 +54360,12 @@ var ServerKeyStore = class {
|
|
|
54099
54360
|
publicKeyPem,
|
|
54100
54361
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
54101
54362
|
};
|
|
54102
|
-
|
|
54103
|
-
|
|
54363
|
+
fs51.mkdirSync(this.dataDir, { recursive: true });
|
|
54364
|
+
fs51.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
54104
54365
|
}
|
|
54105
54366
|
clear() {
|
|
54106
54367
|
try {
|
|
54107
|
-
|
|
54368
|
+
fs51.unlinkSync(this.filePath());
|
|
54108
54369
|
} catch {
|
|
54109
54370
|
}
|
|
54110
54371
|
}
|
|
@@ -54117,12 +54378,12 @@ init_protocol();
|
|
|
54117
54378
|
init_protocol();
|
|
54118
54379
|
|
|
54119
54380
|
// src/session/fork.ts
|
|
54120
|
-
var
|
|
54381
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
54121
54382
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
54122
|
-
var
|
|
54383
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
54123
54384
|
init_claude_history();
|
|
54124
54385
|
function readJsonlEntries(file) {
|
|
54125
|
-
const raw =
|
|
54386
|
+
const raw = import_node_fs41.default.readFileSync(file, "utf8");
|
|
54126
54387
|
const out = [];
|
|
54127
54388
|
for (const line of raw.split("\n")) {
|
|
54128
54389
|
const t = line.trim();
|
|
@@ -54135,19 +54396,19 @@ function readJsonlEntries(file) {
|
|
|
54135
54396
|
return out;
|
|
54136
54397
|
}
|
|
54137
54398
|
function forkSession(input) {
|
|
54138
|
-
const baseDir = input.baseDir ??
|
|
54139
|
-
let projectDir =
|
|
54140
|
-
let sourceFile =
|
|
54141
|
-
if (!
|
|
54399
|
+
const baseDir = input.baseDir ?? import_node_path45.default.join(import_node_os16.default.homedir(), ".claude");
|
|
54400
|
+
let projectDir = import_node_path45.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
54401
|
+
let sourceFile = import_node_path45.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
54402
|
+
if (!import_node_fs41.default.existsSync(sourceFile)) {
|
|
54142
54403
|
const found = findTranscriptByToolSessionId(
|
|
54143
|
-
|
|
54404
|
+
import_node_path45.default.join(baseDir, "projects"),
|
|
54144
54405
|
input.toolSessionId
|
|
54145
54406
|
);
|
|
54146
54407
|
if (!found) {
|
|
54147
54408
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
54148
54409
|
}
|
|
54149
54410
|
sourceFile = found;
|
|
54150
|
-
projectDir =
|
|
54411
|
+
projectDir = import_node_path45.default.dirname(found);
|
|
54151
54412
|
}
|
|
54152
54413
|
const entries = readJsonlEntries(sourceFile);
|
|
54153
54414
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -54176,9 +54437,9 @@ function forkSession(input) {
|
|
|
54176
54437
|
}
|
|
54177
54438
|
forkedLines.push(JSON.stringify(forked));
|
|
54178
54439
|
}
|
|
54179
|
-
const forkedFilePath =
|
|
54180
|
-
|
|
54181
|
-
|
|
54440
|
+
const forkedFilePath = import_node_path45.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
54441
|
+
import_node_fs41.default.mkdirSync(projectDir, { recursive: true });
|
|
54442
|
+
import_node_fs41.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
54182
54443
|
return { forkedToolSessionId, forkedFilePath };
|
|
54183
54444
|
}
|
|
54184
54445
|
|
|
@@ -54340,21 +54601,34 @@ function buildSessionHandlers(deps) {
|
|
|
54340
54601
|
const { broadcast } = await manager.interrupt(args);
|
|
54341
54602
|
return { response: { type: "session:interrupt", ok: true }, broadcast };
|
|
54342
54603
|
};
|
|
54604
|
+
const ensureRewindSupported = async (sessionId) => {
|
|
54605
|
+
const file = manager.get({ sessionId }).response;
|
|
54606
|
+
const caps = await getAdapter2(file.tool ?? "claude").capabilities();
|
|
54607
|
+
if (caps.features.rewind === false) {
|
|
54608
|
+
throw new ClawdError(
|
|
54609
|
+
ERROR_CODES.TOOL_NOT_SUPPORTED,
|
|
54610
|
+
`tool ${file.tool ?? "claude"} does not support rewind`
|
|
54611
|
+
);
|
|
54612
|
+
}
|
|
54613
|
+
};
|
|
54343
54614
|
const rewind = async (frame, _client, ctx) => {
|
|
54344
54615
|
const args = SessionRewindArgs.parse(frame);
|
|
54345
54616
|
ensureSessionAccess(ctx, args.sessionId, "send");
|
|
54617
|
+
await ensureRewindSupported(args.sessionId);
|
|
54346
54618
|
const { response, broadcast } = await manager.rewind(args);
|
|
54347
54619
|
return { response: { type: "session:rewind", ...response }, broadcast };
|
|
54348
54620
|
};
|
|
54349
54621
|
const rewindDiff = async (frame, _client, ctx) => {
|
|
54350
54622
|
const args = SessionRewindDiffArgs.parse(frame);
|
|
54351
54623
|
ensureSessionAccess(ctx, args.sessionId, "read");
|
|
54624
|
+
await ensureRewindSupported(args.sessionId);
|
|
54352
54625
|
const { response } = await manager.rewindDiff(args);
|
|
54353
54626
|
return { response: { type: "session:rewind-diff", ...response } };
|
|
54354
54627
|
};
|
|
54355
54628
|
const rewindableMessageIds = async (frame, _client, ctx) => {
|
|
54356
54629
|
const args = SessionRewindableMessageIdsArgs.parse(frame);
|
|
54357
54630
|
ensureSessionAccess(ctx, args.sessionId, "read");
|
|
54631
|
+
await ensureRewindSupported(args.sessionId);
|
|
54358
54632
|
const { response } = manager.rewindableMessageIds(args);
|
|
54359
54633
|
return {
|
|
54360
54634
|
response: { type: "session:rewindable-message-ids", ...response }
|
|
@@ -54577,7 +54851,7 @@ function buildPermissionHandlers(deps) {
|
|
|
54577
54851
|
}
|
|
54578
54852
|
|
|
54579
54853
|
// src/handlers/history.ts
|
|
54580
|
-
var
|
|
54854
|
+
var path56 = __toESM(require("path"), 1);
|
|
54581
54855
|
init_protocol();
|
|
54582
54856
|
|
|
54583
54857
|
// src/session/recent-dirs.ts
|
|
@@ -54595,7 +54869,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
54595
54869
|
}
|
|
54596
54870
|
|
|
54597
54871
|
// src/permission/persona-paths.ts
|
|
54598
|
-
var
|
|
54872
|
+
var path55 = __toESM(require("path"), 1);
|
|
54599
54873
|
function getAllowedPersonaIds(grants, action) {
|
|
54600
54874
|
const ids = /* @__PURE__ */ new Set();
|
|
54601
54875
|
for (const g2 of grants) {
|
|
@@ -54608,42 +54882,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
54608
54882
|
return ids;
|
|
54609
54883
|
}
|
|
54610
54884
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
54611
|
-
const target =
|
|
54885
|
+
const target = path55.resolve(absPath);
|
|
54612
54886
|
if (userWorkDir) {
|
|
54613
|
-
const u =
|
|
54614
|
-
const usep = u.endsWith(
|
|
54887
|
+
const u = path55.resolve(userWorkDir);
|
|
54888
|
+
const usep = u.endsWith(path55.sep) ? "" : path55.sep;
|
|
54615
54889
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
54616
54890
|
}
|
|
54617
|
-
const root =
|
|
54618
|
-
const sep3 = root.endsWith(
|
|
54891
|
+
const root = path55.resolve(personaRoot);
|
|
54892
|
+
const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
|
|
54619
54893
|
if (!target.startsWith(root + sep3)) return false;
|
|
54620
|
-
const rel =
|
|
54894
|
+
const rel = path55.relative(root, target);
|
|
54621
54895
|
if (!rel || rel.startsWith("..")) return false;
|
|
54622
|
-
const personaId = rel.split(
|
|
54896
|
+
const personaId = rel.split(path55.sep)[0];
|
|
54623
54897
|
if (!personaId) return false;
|
|
54624
54898
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
54625
54899
|
if (allowed === "*") return true;
|
|
54626
54900
|
return allowed.has(personaId);
|
|
54627
54901
|
}
|
|
54628
54902
|
function personaIdFromPath(absPath, personaRoot) {
|
|
54629
|
-
const root =
|
|
54630
|
-
const target =
|
|
54631
|
-
const sep3 = root.endsWith(
|
|
54903
|
+
const root = path55.resolve(personaRoot);
|
|
54904
|
+
const target = path55.resolve(absPath);
|
|
54905
|
+
const sep3 = root.endsWith(path55.sep) ? "" : path55.sep;
|
|
54632
54906
|
if (!target.startsWith(root + sep3)) return null;
|
|
54633
|
-
const rel =
|
|
54907
|
+
const rel = path55.relative(root, target);
|
|
54634
54908
|
if (!rel || rel.startsWith("..")) return null;
|
|
54635
|
-
const id = rel.split(
|
|
54909
|
+
const id = rel.split(path55.sep)[0];
|
|
54636
54910
|
return id || null;
|
|
54637
54911
|
}
|
|
54638
54912
|
function isPathWithin(dir, absPath) {
|
|
54639
|
-
const d =
|
|
54640
|
-
const t =
|
|
54641
|
-
const sep3 = d.endsWith(
|
|
54913
|
+
const d = path55.resolve(dir);
|
|
54914
|
+
const t = path55.resolve(absPath);
|
|
54915
|
+
const sep3 = d.endsWith(path55.sep) ? "" : path55.sep;
|
|
54642
54916
|
return t === d || t.startsWith(d + sep3);
|
|
54643
54917
|
}
|
|
54644
54918
|
function isPathInGuestBoundary(personaRoot, personaId, userWorkDir, absPath) {
|
|
54645
54919
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
54646
|
-
return personaIdFromPath(
|
|
54920
|
+
return personaIdFromPath(path55.resolve(absPath), personaRoot) === personaId;
|
|
54647
54921
|
}
|
|
54648
54922
|
|
|
54649
54923
|
// src/handlers/history.ts
|
|
@@ -54695,7 +54969,7 @@ function buildHistoryHandlers(deps) {
|
|
|
54695
54969
|
if (!pid) return false;
|
|
54696
54970
|
return isGuestPathAllowed(
|
|
54697
54971
|
ctx.grants,
|
|
54698
|
-
|
|
54972
|
+
path56.join(personaRoot, pid),
|
|
54699
54973
|
personaRoot,
|
|
54700
54974
|
"read",
|
|
54701
54975
|
userWorkDir
|
|
@@ -54707,7 +54981,7 @@ function buildHistoryHandlers(deps) {
|
|
|
54707
54981
|
};
|
|
54708
54982
|
const list = async (frame, _client, ctx) => {
|
|
54709
54983
|
const args = HistoryListArgs.parse(frame);
|
|
54710
|
-
assertGuestPath(ctx,
|
|
54984
|
+
assertGuestPath(ctx, path56.resolve(args.projectPath), personaRoot, "history:list");
|
|
54711
54985
|
const sessions = await history.listSessions(args);
|
|
54712
54986
|
return { response: { type: "history:list", sessions } };
|
|
54713
54987
|
};
|
|
@@ -54740,13 +55014,13 @@ function buildHistoryHandlers(deps) {
|
|
|
54740
55014
|
};
|
|
54741
55015
|
const subagents = async (frame, _client, ctx) => {
|
|
54742
55016
|
const args = HistorySubagentsArgs.parse(frame);
|
|
54743
|
-
assertGuestPath(ctx,
|
|
55017
|
+
assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
54744
55018
|
const subs = await history.listSubagents(args);
|
|
54745
55019
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
54746
55020
|
};
|
|
54747
55021
|
const subagentRead = async (frame, _client, ctx) => {
|
|
54748
55022
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
54749
|
-
assertGuestPath(ctx,
|
|
55023
|
+
assertGuestPath(ctx, path56.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
54750
55024
|
const res = await history.readSubagent(args);
|
|
54751
55025
|
return { response: { type: "history:subagent-read", ...res } };
|
|
54752
55026
|
};
|
|
@@ -54755,7 +55029,7 @@ function buildHistoryHandlers(deps) {
|
|
|
54755
55029
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
54756
55030
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
54757
55031
|
const filtered = dirs.filter(
|
|
54758
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
55032
|
+
(d) => isGuestPathAllowed(ctx.grants, path56.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
54759
55033
|
);
|
|
54760
55034
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
54761
55035
|
}
|
|
@@ -54772,7 +55046,7 @@ function buildHistoryHandlers(deps) {
|
|
|
54772
55046
|
}
|
|
54773
55047
|
|
|
54774
55048
|
// src/handlers/workspace.ts
|
|
54775
|
-
var
|
|
55049
|
+
var path57 = __toESM(require("path"), 1);
|
|
54776
55050
|
var os16 = __toESM(require("os"), 1);
|
|
54777
55051
|
init_protocol();
|
|
54778
55052
|
init_protocol();
|
|
@@ -54814,22 +55088,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
54814
55088
|
const args = WorkspaceListArgs.parse(frame);
|
|
54815
55089
|
const isGuest = ctx?.principal.kind === "guest";
|
|
54816
55090
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os16.homedir();
|
|
54817
|
-
const resolvedCwd =
|
|
54818
|
-
const target = args.path ?
|
|
55091
|
+
const resolvedCwd = path57.resolve(args.cwd ?? fallbackCwd);
|
|
55092
|
+
const target = args.path ? path57.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
54819
55093
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
54820
55094
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
54821
55095
|
return { response: { type: "workspace:list", ...res } };
|
|
54822
55096
|
};
|
|
54823
55097
|
const read = async (frame, _client, ctx) => {
|
|
54824
55098
|
const args = WorkspaceReadArgs.parse(frame);
|
|
54825
|
-
const target =
|
|
55099
|
+
const target = path57.isAbsolute(args.path) ? path57.resolve(args.path) : path57.resolve(args.cwd, args.path);
|
|
54826
55100
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
54827
55101
|
const res = workspace.read(args);
|
|
54828
55102
|
return { response: { type: "workspace:read", ...res } };
|
|
54829
55103
|
};
|
|
54830
55104
|
const skillsList = async (frame, _client, ctx) => {
|
|
54831
55105
|
const args = SkillsListArgs.parse(frame);
|
|
54832
|
-
const cwdAbs =
|
|
55106
|
+
const cwdAbs = path57.resolve(args.cwd);
|
|
54833
55107
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
54834
55108
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
54835
55109
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -54841,7 +55115,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
54841
55115
|
};
|
|
54842
55116
|
const agentsList = async (frame, _client, ctx) => {
|
|
54843
55117
|
const args = AgentsListArgs.parse(frame);
|
|
54844
|
-
const cwdAbs =
|
|
55118
|
+
const cwdAbs = path57.resolve(args.cwd);
|
|
54845
55119
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
54846
55120
|
if (args.tool === "codex") {
|
|
54847
55121
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -54863,20 +55137,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
54863
55137
|
}
|
|
54864
55138
|
|
|
54865
55139
|
// src/handlers/git.ts
|
|
54866
|
-
var
|
|
55140
|
+
var path59 = __toESM(require("path"), 1);
|
|
54867
55141
|
init_protocol();
|
|
54868
55142
|
init_protocol();
|
|
54869
55143
|
|
|
54870
55144
|
// src/workspace/git.ts
|
|
54871
|
-
var
|
|
54872
|
-
var
|
|
54873
|
-
var
|
|
55145
|
+
var import_node_child_process11 = require("child_process");
|
|
55146
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
55147
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
54874
55148
|
var import_node_util = require("util");
|
|
54875
|
-
var pexec = (0, import_node_util.promisify)(
|
|
55149
|
+
var pexec = (0, import_node_util.promisify)(import_node_child_process11.execFile);
|
|
54876
55150
|
function normalizePath(p2) {
|
|
54877
|
-
const resolved =
|
|
55151
|
+
const resolved = import_node_path46.default.resolve(p2);
|
|
54878
55152
|
try {
|
|
54879
|
-
return
|
|
55153
|
+
return import_node_fs42.default.realpathSync(resolved);
|
|
54880
55154
|
} catch {
|
|
54881
55155
|
return resolved;
|
|
54882
55156
|
}
|
|
@@ -54950,7 +55224,7 @@ async function listGitBranches(cwd) {
|
|
|
54950
55224
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
54951
55225
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
54952
55226
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
54953
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
55227
|
+
if (!isGuestPathAllowed(ctx.grants, path59.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
54954
55228
|
throw new ClawdError(
|
|
54955
55229
|
ERROR_CODES.UNAUTHORIZED,
|
|
54956
55230
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -55636,7 +55910,7 @@ function buildPersonaHandlers(deps) {
|
|
|
55636
55910
|
}
|
|
55637
55911
|
|
|
55638
55912
|
// src/handlers/attachment.ts
|
|
55639
|
-
var
|
|
55913
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
55640
55914
|
init_protocol();
|
|
55641
55915
|
init_protocol();
|
|
55642
55916
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -55716,12 +55990,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
55716
55990
|
`session ${args.sessionId} scope unresolved`
|
|
55717
55991
|
);
|
|
55718
55992
|
}
|
|
55719
|
-
const cwdAbs =
|
|
55720
|
-
const candidateAbs =
|
|
55993
|
+
const cwdAbs = import_node_path47.default.resolve(sessionFile.cwd);
|
|
55994
|
+
const candidateAbs = import_node_path47.default.isAbsolute(args.relPath) ? import_node_path47.default.resolve(args.relPath) : import_node_path47.default.resolve(cwdAbs, args.relPath);
|
|
55721
55995
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
55722
55996
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
55723
55997
|
const entry = entries.find((e) => {
|
|
55724
|
-
const storedAbs =
|
|
55998
|
+
const storedAbs = import_node_path47.default.isAbsolute(e.relPath) ? import_node_path47.default.resolve(e.relPath) : import_node_path47.default.resolve(cwdAbs, e.relPath);
|
|
55725
55999
|
return storedAbs === candidateAbs && !e.stale;
|
|
55726
56000
|
});
|
|
55727
56001
|
if (!entry) {
|
|
@@ -55746,7 +56020,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
55746
56020
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
55747
56021
|
const f = deps.sessionStore.read(sessionId);
|
|
55748
56022
|
if (!f) return;
|
|
55749
|
-
assertGuestAttachmentPath(ctx,
|
|
56023
|
+
assertGuestAttachmentPath(ctx, import_node_path47.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
55750
56024
|
}
|
|
55751
56025
|
const groupAdd = async (frame, _client, ctx) => {
|
|
55752
56026
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -55761,8 +56035,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
55761
56035
|
if (!scope) {
|
|
55762
56036
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
55763
56037
|
}
|
|
55764
|
-
const cwdAbs =
|
|
55765
|
-
const candidateAbs =
|
|
56038
|
+
const cwdAbs = import_node_path47.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
56039
|
+
const candidateAbs = import_node_path47.default.isAbsolute(args.relPath) ? import_node_path47.default.resolve(args.relPath) : import_node_path47.default.resolve(cwdAbs, args.relPath);
|
|
55766
56040
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
55767
56041
|
const from = ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
55768
56042
|
const size = 0;
|
|
@@ -55821,19 +56095,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
55821
56095
|
|
|
55822
56096
|
// src/handlers/extension.ts
|
|
55823
56097
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
55824
|
-
var
|
|
56098
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
55825
56099
|
init_protocol();
|
|
55826
56100
|
|
|
55827
56101
|
// src/extension/bundle-zip.ts
|
|
55828
56102
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
55829
|
-
var
|
|
56103
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
55830
56104
|
var import_node_crypto14 = __toESM(require("crypto"), 1);
|
|
55831
56105
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
55832
56106
|
async function bundleExtensionDir(dir) {
|
|
55833
56107
|
const entries = await listFilesSorted(dir);
|
|
55834
56108
|
const zip = new import_jszip2.default();
|
|
55835
56109
|
for (const rel of entries) {
|
|
55836
|
-
const abs =
|
|
56110
|
+
const abs = import_node_path48.default.join(dir, rel);
|
|
55837
56111
|
const content = await import_promises6.default.readFile(abs);
|
|
55838
56112
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
55839
56113
|
}
|
|
@@ -55854,7 +56128,7 @@ async function listFilesSorted(rootDir) {
|
|
|
55854
56128
|
return out;
|
|
55855
56129
|
}
|
|
55856
56130
|
async function walk(absRoot, relPrefix, out) {
|
|
55857
|
-
const dirAbs =
|
|
56131
|
+
const dirAbs = import_node_path48.default.join(absRoot, relPrefix);
|
|
55858
56132
|
const entries = await import_promises6.default.readdir(dirAbs, { withFileTypes: true });
|
|
55859
56133
|
for (const e of entries) {
|
|
55860
56134
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -55908,25 +56182,25 @@ function computePublishCheck(args) {
|
|
|
55908
56182
|
|
|
55909
56183
|
// src/extension/install-flow.ts
|
|
55910
56184
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
55911
|
-
var
|
|
56185
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
55912
56186
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
55913
56187
|
var import_node_crypto15 = __toESM(require("crypto"), 1);
|
|
55914
56188
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
55915
56189
|
|
|
55916
56190
|
// src/extension/paths.ts
|
|
55917
56191
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
55918
|
-
var
|
|
56192
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
55919
56193
|
function clawdHomeRoot(override) {
|
|
55920
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
56194
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path49.default.join(import_node_os18.default.homedir(), ".clawd");
|
|
55921
56195
|
}
|
|
55922
56196
|
function extensionsRoot(override) {
|
|
55923
|
-
return
|
|
56197
|
+
return import_node_path49.default.join(clawdHomeRoot(override), "extensions");
|
|
55924
56198
|
}
|
|
55925
56199
|
function publishedChannelsFile(override) {
|
|
55926
|
-
return
|
|
56200
|
+
return import_node_path49.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
55927
56201
|
}
|
|
55928
56202
|
function bundleCacheRoot(override) {
|
|
55929
|
-
return
|
|
56203
|
+
return import_node_path49.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
55930
56204
|
}
|
|
55931
56205
|
|
|
55932
56206
|
// src/extension/install-flow.ts
|
|
@@ -55953,7 +56227,7 @@ async function installFromChannel(args, deps) {
|
|
|
55953
56227
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
55954
56228
|
}
|
|
55955
56229
|
for (const name of Object.keys(zip.files)) {
|
|
55956
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
56230
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path50.default.isAbsolute(name)) {
|
|
55957
56231
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
55958
56232
|
}
|
|
55959
56233
|
}
|
|
@@ -55985,7 +56259,7 @@ async function installFromChannel(args, deps) {
|
|
|
55985
56259
|
);
|
|
55986
56260
|
}
|
|
55987
56261
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
55988
|
-
const destDir =
|
|
56262
|
+
const destDir = import_node_path50.default.join(deps.extensionsRoot, localExtId);
|
|
55989
56263
|
let destExists = false;
|
|
55990
56264
|
try {
|
|
55991
56265
|
await import_promises7.default.access(destDir);
|
|
@@ -55999,16 +56273,16 @@ async function installFromChannel(args, deps) {
|
|
|
55999
56273
|
);
|
|
56000
56274
|
}
|
|
56001
56275
|
const stage = await import_promises7.default.mkdtemp(
|
|
56002
|
-
|
|
56276
|
+
import_node_path50.default.join(import_node_os19.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
56003
56277
|
);
|
|
56004
56278
|
try {
|
|
56005
56279
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56006
|
-
const dest =
|
|
56280
|
+
const dest = import_node_path50.default.join(stage, name);
|
|
56007
56281
|
if (entry.dir) {
|
|
56008
56282
|
await import_promises7.default.mkdir(dest, { recursive: true });
|
|
56009
56283
|
continue;
|
|
56010
56284
|
}
|
|
56011
|
-
await import_promises7.default.mkdir(
|
|
56285
|
+
await import_promises7.default.mkdir(import_node_path50.default.dirname(dest), { recursive: true });
|
|
56012
56286
|
if (name === "manifest.json") {
|
|
56013
56287
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
56014
56288
|
await import_promises7.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -56029,7 +56303,7 @@ async function installFromChannel(args, deps) {
|
|
|
56029
56303
|
|
|
56030
56304
|
// src/extension/update-flow.ts
|
|
56031
56305
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
56032
|
-
var
|
|
56306
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
56033
56307
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
56034
56308
|
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
56035
56309
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -56046,11 +56320,11 @@ async function updateFromChannel(args, deps) {
|
|
|
56046
56320
|
channelRef.extId,
|
|
56047
56321
|
channelRef.ownerPrincipalId
|
|
56048
56322
|
);
|
|
56049
|
-
const liveDir =
|
|
56323
|
+
const liveDir = import_node_path51.default.join(deps.extensionsRoot, localExtId);
|
|
56050
56324
|
const prevDir = `${liveDir}.prev`;
|
|
56051
56325
|
let existingVersion;
|
|
56052
56326
|
try {
|
|
56053
|
-
const raw = await import_promises8.default.readFile(
|
|
56327
|
+
const raw = await import_promises8.default.readFile(import_node_path51.default.join(liveDir, "manifest.json"), "utf8");
|
|
56054
56328
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
56055
56329
|
if (!parsed2.success) {
|
|
56056
56330
|
throw new UpdateError(
|
|
@@ -56083,7 +56357,7 @@ async function updateFromChannel(args, deps) {
|
|
|
56083
56357
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
56084
56358
|
}
|
|
56085
56359
|
for (const name of Object.keys(zip.files)) {
|
|
56086
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
56360
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path51.default.isAbsolute(name)) {
|
|
56087
56361
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
56088
56362
|
}
|
|
56089
56363
|
}
|
|
@@ -56118,16 +56392,16 @@ async function updateFromChannel(args, deps) {
|
|
|
56118
56392
|
await import_promises8.default.rm(prevDir, { recursive: true, force: true });
|
|
56119
56393
|
await import_promises8.default.rename(liveDir, prevDir);
|
|
56120
56394
|
const stage = await import_promises8.default.mkdtemp(
|
|
56121
|
-
|
|
56395
|
+
import_node_path51.default.join(import_node_os20.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
56122
56396
|
);
|
|
56123
56397
|
try {
|
|
56124
56398
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
56125
|
-
const dest =
|
|
56399
|
+
const dest = import_node_path51.default.join(stage, name);
|
|
56126
56400
|
if (entry.dir) {
|
|
56127
56401
|
await import_promises8.default.mkdir(dest, { recursive: true });
|
|
56128
56402
|
continue;
|
|
56129
56403
|
}
|
|
56130
|
-
await import_promises8.default.mkdir(
|
|
56404
|
+
await import_promises8.default.mkdir(import_node_path51.default.dirname(dest), { recursive: true });
|
|
56131
56405
|
if (name === "manifest.json") {
|
|
56132
56406
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
56133
56407
|
await import_promises8.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -56220,7 +56494,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
56220
56494
|
);
|
|
56221
56495
|
}
|
|
56222
56496
|
}
|
|
56223
|
-
const manifestPath =
|
|
56497
|
+
const manifestPath = import_node_path52.default.join(root, extId, "manifest.json");
|
|
56224
56498
|
const manifest = await readManifest(root, extId);
|
|
56225
56499
|
const next = { ...manifest, version: newVersion };
|
|
56226
56500
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -56228,7 +56502,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
56228
56502
|
await import_promises9.default.rename(tmp, manifestPath);
|
|
56229
56503
|
}
|
|
56230
56504
|
async function readManifest(root, extId) {
|
|
56231
|
-
const file =
|
|
56505
|
+
const file = import_node_path52.default.join(root, extId, "manifest.json");
|
|
56232
56506
|
let raw;
|
|
56233
56507
|
try {
|
|
56234
56508
|
raw = await import_promises9.default.readFile(file, "utf8");
|
|
@@ -56319,7 +56593,7 @@ function buildExtensionHandlers(deps) {
|
|
|
56319
56593
|
};
|
|
56320
56594
|
async function buildSnapshotMeta(extId) {
|
|
56321
56595
|
const manifest = await readManifest(deps.root, extId);
|
|
56322
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
56596
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path52.default.join(deps.root, extId));
|
|
56323
56597
|
return { manifest, contentHash: sha256, buffer };
|
|
56324
56598
|
}
|
|
56325
56599
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -56500,9 +56774,9 @@ function buildExtensionHandlers(deps) {
|
|
|
56500
56774
|
}
|
|
56501
56775
|
|
|
56502
56776
|
// src/app-builder/project-store.ts
|
|
56503
|
-
var
|
|
56504
|
-
var
|
|
56505
|
-
var
|
|
56777
|
+
var import_node_fs43 = require("fs");
|
|
56778
|
+
var import_node_child_process12 = require("child_process");
|
|
56779
|
+
var import_node_path53 = require("path");
|
|
56506
56780
|
init_protocol();
|
|
56507
56781
|
var PROJECTS_DIR = "projects";
|
|
56508
56782
|
var META_FILE = ".clawd-project.json";
|
|
@@ -56516,19 +56790,19 @@ var ProjectStore = class {
|
|
|
56516
56790
|
root;
|
|
56517
56791
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
56518
56792
|
metaPath(name) {
|
|
56519
|
-
return (0,
|
|
56793
|
+
return (0, import_node_path53.join)(this.projectsRoot(), name, META_FILE);
|
|
56520
56794
|
}
|
|
56521
56795
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
56522
56796
|
projectDir(name) {
|
|
56523
|
-
return (0,
|
|
56797
|
+
return (0, import_node_path53.join)(this.projectsRoot(), name);
|
|
56524
56798
|
}
|
|
56525
56799
|
projectsRoot() {
|
|
56526
|
-
return (0,
|
|
56800
|
+
return (0, import_node_path53.join)(this.root, PROJECTS_DIR);
|
|
56527
56801
|
}
|
|
56528
56802
|
async list() {
|
|
56529
56803
|
let entries;
|
|
56530
56804
|
try {
|
|
56531
|
-
entries = await
|
|
56805
|
+
entries = await import_node_fs43.promises.readdir(this.projectsRoot());
|
|
56532
56806
|
} catch (err) {
|
|
56533
56807
|
if (err.code === "ENOENT") return [];
|
|
56534
56808
|
throw err;
|
|
@@ -56536,7 +56810,7 @@ var ProjectStore = class {
|
|
|
56536
56810
|
const out = [];
|
|
56537
56811
|
for (const name of entries) {
|
|
56538
56812
|
try {
|
|
56539
|
-
const raw = await
|
|
56813
|
+
const raw = await import_node_fs43.promises.readFile(this.metaPath(name), "utf8");
|
|
56540
56814
|
const json = JSON.parse(raw);
|
|
56541
56815
|
let migrated = false;
|
|
56542
56816
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -56547,7 +56821,7 @@ var ProjectStore = class {
|
|
|
56547
56821
|
if (parsed.success) {
|
|
56548
56822
|
out.push(parsed.data);
|
|
56549
56823
|
if (migrated) {
|
|
56550
|
-
void
|
|
56824
|
+
void import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
56551
56825
|
});
|
|
56552
56826
|
}
|
|
56553
56827
|
}
|
|
@@ -56591,8 +56865,8 @@ var ProjectStore = class {
|
|
|
56591
56865
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
56592
56866
|
}
|
|
56593
56867
|
const dir = this.projectDir(name);
|
|
56594
|
-
await
|
|
56595
|
-
await
|
|
56868
|
+
await import_node_fs43.promises.mkdir(dir, { recursive: true });
|
|
56869
|
+
await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
56596
56870
|
return meta;
|
|
56597
56871
|
}
|
|
56598
56872
|
/**
|
|
@@ -56606,7 +56880,7 @@ var ProjectStore = class {
|
|
|
56606
56880
|
async scaffold(name, templateSrcDir, scaffoldScriptPath) {
|
|
56607
56881
|
const destDir = this.projectDir(name);
|
|
56608
56882
|
return await new Promise((resolve6, reject) => {
|
|
56609
|
-
const child = (0,
|
|
56883
|
+
const child = (0, import_node_child_process12.spawn)("bash", [scaffoldScriptPath, name, templateSrcDir, destDir], {
|
|
56610
56884
|
env: { ...process.env, PATH: process.env.PATH ?? "" },
|
|
56611
56885
|
stdio: ["ignore", "pipe", "pipe"]
|
|
56612
56886
|
});
|
|
@@ -56635,7 +56909,7 @@ var ProjectStore = class {
|
|
|
56635
56909
|
}
|
|
56636
56910
|
async delete(name) {
|
|
56637
56911
|
const dir = this.projectDir(name);
|
|
56638
|
-
await
|
|
56912
|
+
await import_node_fs43.promises.rm(dir, { recursive: true, force: true });
|
|
56639
56913
|
}
|
|
56640
56914
|
async updatePort(name, newPort) {
|
|
56641
56915
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -56651,7 +56925,7 @@ var ProjectStore = class {
|
|
|
56651
56925
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
56652
56926
|
}
|
|
56653
56927
|
const updated = { ...target, port: newPort };
|
|
56654
|
-
await
|
|
56928
|
+
await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
56655
56929
|
return updated;
|
|
56656
56930
|
}
|
|
56657
56931
|
/**
|
|
@@ -56668,7 +56942,7 @@ var ProjectStore = class {
|
|
|
56668
56942
|
if (!validated.success) {
|
|
56669
56943
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
56670
56944
|
}
|
|
56671
|
-
await
|
|
56945
|
+
await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
56672
56946
|
return validated.data;
|
|
56673
56947
|
}
|
|
56674
56948
|
/**
|
|
@@ -56689,7 +56963,7 @@ var ProjectStore = class {
|
|
|
56689
56963
|
if (!validated.success) {
|
|
56690
56964
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
56691
56965
|
}
|
|
56692
|
-
await
|
|
56966
|
+
await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
56693
56967
|
return validated.data;
|
|
56694
56968
|
}
|
|
56695
56969
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -56704,13 +56978,13 @@ var ProjectStore = class {
|
|
|
56704
56978
|
if (!validated.success) {
|
|
56705
56979
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
56706
56980
|
}
|
|
56707
|
-
await
|
|
56981
|
+
await import_node_fs43.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
56708
56982
|
return validated.data;
|
|
56709
56983
|
}
|
|
56710
56984
|
};
|
|
56711
56985
|
|
|
56712
56986
|
// src/app-builder/kill-port.ts
|
|
56713
|
-
var
|
|
56987
|
+
var import_node_child_process13 = require("child_process");
|
|
56714
56988
|
async function killPortOccupants(port, ownedPids, logger) {
|
|
56715
56989
|
let pids;
|
|
56716
56990
|
try {
|
|
@@ -56752,7 +57026,7 @@ async function killPortOccupants(port, ownedPids, logger) {
|
|
|
56752
57026
|
}
|
|
56753
57027
|
function listPidsOnPort(port) {
|
|
56754
57028
|
return new Promise((resolve6, reject) => {
|
|
56755
|
-
(0,
|
|
57029
|
+
(0, import_node_child_process13.execFile)(
|
|
56756
57030
|
"lsof",
|
|
56757
57031
|
["-ti", `:${port}`],
|
|
56758
57032
|
{ timeout: 3e3 },
|
|
@@ -56824,9 +57098,9 @@ var PublishJobRegistry = class {
|
|
|
56824
57098
|
};
|
|
56825
57099
|
|
|
56826
57100
|
// src/app-builder/publish-job-runner.ts
|
|
56827
|
-
var
|
|
56828
|
-
var
|
|
56829
|
-
var
|
|
57101
|
+
var import_node_child_process14 = require("child_process");
|
|
57102
|
+
var import_node_fs44 = require("fs");
|
|
57103
|
+
var import_node_path54 = require("path");
|
|
56830
57104
|
|
|
56831
57105
|
// src/app-builder/publish-stage-parser.ts
|
|
56832
57106
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -56853,15 +57127,15 @@ function tailStderrLines(buf, n) {
|
|
|
56853
57127
|
// src/app-builder/publish-job-runner.ts
|
|
56854
57128
|
async function startPublishJob(deps, args) {
|
|
56855
57129
|
const { registry: registry2, projectDir } = deps;
|
|
56856
|
-
const spawn13 = deps.spawnImpl ??
|
|
57130
|
+
const spawn13 = deps.spawnImpl ?? import_node_child_process14.spawn;
|
|
56857
57131
|
if (registry2.has(args.name)) {
|
|
56858
57132
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
56859
57133
|
}
|
|
56860
57134
|
const projDir = projectDir(args.name);
|
|
56861
|
-
const logPath = (0,
|
|
57135
|
+
const logPath = (0, import_node_path54.join)(projDir, ".publish.log");
|
|
56862
57136
|
let logStream = null;
|
|
56863
57137
|
try {
|
|
56864
|
-
logStream = (0,
|
|
57138
|
+
logStream = (0, import_node_fs44.createWriteStream)(logPath, { flags: "w" });
|
|
56865
57139
|
} catch {
|
|
56866
57140
|
logStream = null;
|
|
56867
57141
|
}
|
|
@@ -57118,8 +57392,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
57118
57392
|
|
|
57119
57393
|
// src/handlers/app-builder.ts
|
|
57120
57394
|
init_protocol();
|
|
57121
|
-
var
|
|
57122
|
-
var
|
|
57395
|
+
var import_node_path55 = require("path");
|
|
57396
|
+
var import_node_fs45 = require("fs");
|
|
57123
57397
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
57124
57398
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
57125
57399
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -57200,7 +57474,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57200
57474
|
async function listAllUsersProjects() {
|
|
57201
57475
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
57202
57476
|
const getStore = deps.getStore;
|
|
57203
|
-
const userIds = await
|
|
57477
|
+
const userIds = await import_node_fs45.promises.readdir(deps.usersRoot).catch(() => []);
|
|
57204
57478
|
const perUser = await Promise.all(
|
|
57205
57479
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
57206
57480
|
);
|
|
@@ -57276,8 +57550,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57276
57550
|
const project = await userStore.create(f.name, reservedPorts);
|
|
57277
57551
|
try {
|
|
57278
57552
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
57279
|
-
const templateSrcDir = (0,
|
|
57280
|
-
const scaffoldScript = (0,
|
|
57553
|
+
const templateSrcDir = (0, import_node_path55.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
57554
|
+
const scaffoldScript = (0, import_node_path55.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
57281
57555
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
57282
57556
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
57283
57557
|
name: project.name,
|
|
@@ -57498,7 +57772,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
57498
57772
|
await userStore.clearPublishJob(args.name);
|
|
57499
57773
|
}
|
|
57500
57774
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
57501
|
-
const scriptPath = (0,
|
|
57775
|
+
const scriptPath = (0, import_node_path55.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
57502
57776
|
deps.logger?.info("app-builder.publish.start", {
|
|
57503
57777
|
name: args.name,
|
|
57504
57778
|
sessionId: boundSession.sessionId,
|
|
@@ -57674,7 +57948,7 @@ function buildVisitorHandlers(deps) {
|
|
|
57674
57948
|
|
|
57675
57949
|
// src/extension/registry.ts
|
|
57676
57950
|
var import_promises10 = __toESM(require("fs/promises"), 1);
|
|
57677
|
-
var
|
|
57951
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
57678
57952
|
async function loadAll(root) {
|
|
57679
57953
|
let entries;
|
|
57680
57954
|
try {
|
|
@@ -57687,13 +57961,13 @@ async function loadAll(root) {
|
|
|
57687
57961
|
for (const ent of entries) {
|
|
57688
57962
|
if (!ent.isDirectory()) continue;
|
|
57689
57963
|
if (ent.name.startsWith(".")) continue;
|
|
57690
|
-
records.push(await loadOne(
|
|
57964
|
+
records.push(await loadOne(import_node_path56.default.join(root, ent.name), ent.name));
|
|
57691
57965
|
}
|
|
57692
57966
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
57693
57967
|
return records;
|
|
57694
57968
|
}
|
|
57695
57969
|
async function loadOne(dir, dirName) {
|
|
57696
|
-
const manifestPath =
|
|
57970
|
+
const manifestPath = import_node_path56.default.join(dir, "manifest.json");
|
|
57697
57971
|
let raw;
|
|
57698
57972
|
try {
|
|
57699
57973
|
raw = await import_promises10.default.readFile(manifestPath, "utf8");
|
|
@@ -57738,7 +58012,7 @@ async function loadOne(dir, dirName) {
|
|
|
57738
58012
|
|
|
57739
58013
|
// src/extension/uninstall.ts
|
|
57740
58014
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
57741
|
-
var
|
|
58015
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
57742
58016
|
var UninstallError = class extends Error {
|
|
57743
58017
|
constructor(code, message) {
|
|
57744
58018
|
super(message);
|
|
@@ -57747,7 +58021,7 @@ var UninstallError = class extends Error {
|
|
|
57747
58021
|
code;
|
|
57748
58022
|
};
|
|
57749
58023
|
async function uninstall(deps) {
|
|
57750
|
-
const dir =
|
|
58024
|
+
const dir = import_node_path57.default.join(deps.root, deps.extId);
|
|
57751
58025
|
try {
|
|
57752
58026
|
await import_promises11.default.access(dir);
|
|
57753
58027
|
} catch {
|
|
@@ -57764,7 +58038,7 @@ var import_node_crypto18 = require("crypto");
|
|
|
57764
58038
|
init_protocol();
|
|
57765
58039
|
|
|
57766
58040
|
// src/peer-ops/run-command.ts
|
|
57767
|
-
var
|
|
58041
|
+
var import_node_child_process15 = require("child_process");
|
|
57768
58042
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
57769
58043
|
var DEFAULT_TIMEOUT_MS5 = 3e4;
|
|
57770
58044
|
var MAX_TIMEOUT_MS = 3e5;
|
|
@@ -57772,7 +58046,7 @@ var MAX_OUTPUT_BYTES = 1048576;
|
|
|
57772
58046
|
function runCommand(command, opts = {}) {
|
|
57773
58047
|
const timeoutMs = Math.min(opts.timeoutMs ?? DEFAULT_TIMEOUT_MS5, MAX_TIMEOUT_MS);
|
|
57774
58048
|
return new Promise((resolve6) => {
|
|
57775
|
-
const child = (0,
|
|
58049
|
+
const child = (0, import_node_child_process15.spawn)("bash", ["-c", command], { cwd: import_node_os21.default.homedir() });
|
|
57776
58050
|
const out = [];
|
|
57777
58051
|
const err = [];
|
|
57778
58052
|
let outBytes = 0;
|
|
@@ -57986,7 +58260,7 @@ function buildMethodHandlers(deps) {
|
|
|
57986
58260
|
}
|
|
57987
58261
|
|
|
57988
58262
|
// src/app-builder/dev-server-supervisor.ts
|
|
57989
|
-
var
|
|
58263
|
+
var import_node_child_process16 = require("child_process");
|
|
57990
58264
|
var import_node_events2 = require("events");
|
|
57991
58265
|
var DEFAULT_READY_PATTERN = /Local:\s+https?:\/\/|Nest application successfully started|server listening on/i;
|
|
57992
58266
|
var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
@@ -58023,7 +58297,7 @@ var DevServerSupervisor = class extends import_node_events2.EventEmitter {
|
|
|
58023
58297
|
tunnelHost: args.tunnelHost,
|
|
58024
58298
|
devCommand: cmd
|
|
58025
58299
|
});
|
|
58026
|
-
const child = (0,
|
|
58300
|
+
const child = (0, import_node_child_process16.spawn)("sh", ["-c", cmd], {
|
|
58027
58301
|
cwd: args.cwd,
|
|
58028
58302
|
env,
|
|
58029
58303
|
stdio: "pipe",
|
|
@@ -58466,8 +58740,8 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
58466
58740
|
}
|
|
58467
58741
|
|
|
58468
58742
|
// src/extension/runtime.ts
|
|
58469
|
-
var
|
|
58470
|
-
var
|
|
58743
|
+
var import_node_child_process17 = require("child_process");
|
|
58744
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
58471
58745
|
var import_promises12 = require("timers/promises");
|
|
58472
58746
|
|
|
58473
58747
|
// src/extension/port-allocator.ts
|
|
@@ -58568,13 +58842,13 @@ var Runtime = class {
|
|
|
58568
58842
|
/\$CLAWOS_EXT_PORT/g,
|
|
58569
58843
|
String(port)
|
|
58570
58844
|
);
|
|
58571
|
-
const dir =
|
|
58845
|
+
const dir = import_node_path58.default.join(this.root, extId);
|
|
58572
58846
|
const env = {
|
|
58573
58847
|
...process.env,
|
|
58574
58848
|
CLAWOS_EXT_PORT: String(port),
|
|
58575
58849
|
CLAWOS_EXT_ID: extId
|
|
58576
58850
|
};
|
|
58577
|
-
const child = (0,
|
|
58851
|
+
const child = (0, import_node_child_process17.spawn)("sh", ["-c", cmd], {
|
|
58578
58852
|
cwd: dir,
|
|
58579
58853
|
env,
|
|
58580
58854
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -58680,7 +58954,7 @@ ${handle.stderrTail}`
|
|
|
58680
58954
|
|
|
58681
58955
|
// src/extension/published-channels.ts
|
|
58682
58956
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
58683
|
-
var
|
|
58957
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
58684
58958
|
init_zod();
|
|
58685
58959
|
var PublishedChannelsError = class extends Error {
|
|
58686
58960
|
constructor(code, message) {
|
|
@@ -58779,7 +59053,7 @@ var PublishedChannelStore = class {
|
|
|
58779
59053
|
)
|
|
58780
59054
|
};
|
|
58781
59055
|
const tmp = `${this.filePath}.tmp`;
|
|
58782
|
-
await import_promises13.default.mkdir(
|
|
59056
|
+
await import_promises13.default.mkdir(import_node_path59.default.dirname(this.filePath), { recursive: true });
|
|
58783
59057
|
await import_promises13.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
58784
59058
|
await import_promises13.default.rename(tmp, this.filePath);
|
|
58785
59059
|
}
|
|
@@ -58787,7 +59061,7 @@ var PublishedChannelStore = class {
|
|
|
58787
59061
|
|
|
58788
59062
|
// src/extension/bundle-cache.ts
|
|
58789
59063
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
58790
|
-
var
|
|
59064
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
58791
59065
|
var BundleCache = class {
|
|
58792
59066
|
constructor(rootDir) {
|
|
58793
59067
|
this.rootDir = rootDir;
|
|
@@ -58796,14 +59070,14 @@ var BundleCache = class {
|
|
|
58796
59070
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
58797
59071
|
async write(snapshotHash, buffer) {
|
|
58798
59072
|
await import_promises14.default.mkdir(this.rootDir, { recursive: true });
|
|
58799
|
-
const file =
|
|
59073
|
+
const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
58800
59074
|
const tmp = `${file}.tmp`;
|
|
58801
59075
|
await import_promises14.default.writeFile(tmp, buffer, { mode: 384 });
|
|
58802
59076
|
await import_promises14.default.rename(tmp, file);
|
|
58803
59077
|
}
|
|
58804
59078
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
58805
59079
|
async read(snapshotHash) {
|
|
58806
|
-
const file =
|
|
59080
|
+
const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
58807
59081
|
try {
|
|
58808
59082
|
return await import_promises14.default.readFile(file);
|
|
58809
59083
|
} catch (e) {
|
|
@@ -58813,7 +59087,7 @@ var BundleCache = class {
|
|
|
58813
59087
|
}
|
|
58814
59088
|
/** Idempotent — missing file is not an error. */
|
|
58815
59089
|
async delete(snapshotHash) {
|
|
58816
|
-
const file =
|
|
59090
|
+
const file = import_node_path60.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
58817
59091
|
await import_promises14.default.rm(file, { force: true });
|
|
58818
59092
|
}
|
|
58819
59093
|
};
|
|
@@ -58836,24 +59110,24 @@ async function startDaemon(config) {
|
|
|
58836
59110
|
sampling: logShippingCfg.sampling,
|
|
58837
59111
|
homeDir: import_node_os22.default.homedir()
|
|
58838
59112
|
});
|
|
58839
|
-
const logDir =
|
|
58840
|
-
|
|
59113
|
+
const logDir = import_node_path61.default.join(config.dataDir, "log");
|
|
59114
|
+
import_node_fs46.default.mkdirSync(logDir, { recursive: true });
|
|
58841
59115
|
const logger = createLogger({
|
|
58842
59116
|
level: config.logLevel,
|
|
58843
|
-
file:
|
|
59117
|
+
file: import_node_path61.default.join(logDir, "clawd.log"),
|
|
58844
59118
|
logClient
|
|
58845
59119
|
});
|
|
58846
59120
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
58847
59121
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
58848
|
-
file:
|
|
59122
|
+
file: import_node_path61.default.join(logDir, "screen-idle-probe.log"),
|
|
58849
59123
|
level: "debug"
|
|
58850
59124
|
});
|
|
58851
59125
|
logger.info("screen-idle probe logger enabled", {
|
|
58852
|
-
file:
|
|
59126
|
+
file: import_node_path61.default.join(logDir, "screen-idle-probe.log")
|
|
58853
59127
|
});
|
|
58854
59128
|
const CAP_TARGETS = [
|
|
58855
|
-
|
|
58856
|
-
|
|
59129
|
+
import_node_path61.default.join(logDir, "clawd.log"),
|
|
59130
|
+
import_node_path61.default.join(logDir, "screen-idle-probe.log")
|
|
58857
59131
|
];
|
|
58858
59132
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
58859
59133
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -59007,8 +59281,8 @@ async function startDaemon(config) {
|
|
|
59007
59281
|
const agents = new AgentsScanner();
|
|
59008
59282
|
const history = new ClaudeHistoryReader();
|
|
59009
59283
|
let transport = null;
|
|
59010
|
-
const personaStore = new PersonaStore(
|
|
59011
|
-
const usersRoot =
|
|
59284
|
+
const personaStore = new PersonaStore(import_node_path61.default.join(config.dataDir, "personas"));
|
|
59285
|
+
const usersRoot = import_node_path61.default.join(config.dataDir, "users");
|
|
59012
59286
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
59013
59287
|
if (defaultsRoot) {
|
|
59014
59288
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -59028,7 +59302,7 @@ async function startDaemon(config) {
|
|
|
59028
59302
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
59029
59303
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
59030
59304
|
const dispatchStore = createDispatchStore({
|
|
59031
|
-
filePath:
|
|
59305
|
+
filePath: import_node_path61.default.join(config.dataDir, "dispatch.json"),
|
|
59032
59306
|
now: () => Date.now(),
|
|
59033
59307
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
59034
59308
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -59043,17 +59317,17 @@ async function startDaemon(config) {
|
|
|
59043
59317
|
now: () => Date.now(),
|
|
59044
59318
|
onCompleted: (sid) => deliverPendingRef?.(sid)
|
|
59045
59319
|
});
|
|
59046
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
59320
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path61.default.dirname((0, import_node_url4.fileURLToPath)(import_meta6.url));
|
|
59047
59321
|
const mcpConfigs = [];
|
|
59048
59322
|
const dispatchServerCandidates = [
|
|
59049
|
-
|
|
59323
|
+
import_node_path61.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
59050
59324
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
59051
|
-
|
|
59325
|
+
import_node_path61.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
59052
59326
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
59053
59327
|
];
|
|
59054
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
59328
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
|
|
59055
59329
|
if (dispatchServerScriptPath) {
|
|
59056
|
-
const dispatchLogPath =
|
|
59330
|
+
const dispatchLogPath = import_node_path61.default.join(logDir, "dispatch-mcp-server.log");
|
|
59057
59331
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
59058
59332
|
dataDir: config.dataDir,
|
|
59059
59333
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -59071,12 +59345,12 @@ async function startDaemon(config) {
|
|
|
59071
59345
|
});
|
|
59072
59346
|
}
|
|
59073
59347
|
const ticketServerCandidates = [
|
|
59074
|
-
|
|
59075
|
-
|
|
59348
|
+
import_node_path61.default.join(here, "ticket", "mcp-server.cjs"),
|
|
59349
|
+
import_node_path61.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
59076
59350
|
];
|
|
59077
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p2) =>
|
|
59351
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
|
|
59078
59352
|
if (ticketServerScriptPath) {
|
|
59079
|
-
const ticketLogPath =
|
|
59353
|
+
const ticketLogPath = import_node_path61.default.join(logDir, "ticket-mcp-server.log");
|
|
59080
59354
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
59081
59355
|
dataDir: config.dataDir,
|
|
59082
59356
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -59096,12 +59370,12 @@ async function startDaemon(config) {
|
|
|
59096
59370
|
});
|
|
59097
59371
|
}
|
|
59098
59372
|
const shiftServerCandidates = [
|
|
59099
|
-
|
|
59100
|
-
|
|
59373
|
+
import_node_path61.default.join(here, "shift", "mcp-server.cjs"),
|
|
59374
|
+
import_node_path61.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
59101
59375
|
];
|
|
59102
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p2) =>
|
|
59376
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
|
|
59103
59377
|
if (shiftServerScriptPath) {
|
|
59104
|
-
const shiftLogPath =
|
|
59378
|
+
const shiftLogPath = import_node_path61.default.join(logDir, "shift-mcp-server.log");
|
|
59105
59379
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
59106
59380
|
dataDir: config.dataDir,
|
|
59107
59381
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -59120,12 +59394,12 @@ async function startDaemon(config) {
|
|
|
59120
59394
|
);
|
|
59121
59395
|
}
|
|
59122
59396
|
const inboxServerCandidates = [
|
|
59123
|
-
|
|
59124
|
-
|
|
59397
|
+
import_node_path61.default.join(here, "inbox", "mcp-server.cjs"),
|
|
59398
|
+
import_node_path61.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
59125
59399
|
];
|
|
59126
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p2) =>
|
|
59400
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
|
|
59127
59401
|
if (inboxServerScriptPath) {
|
|
59128
|
-
const inboxLogPath =
|
|
59402
|
+
const inboxLogPath = import_node_path61.default.join(logDir, "inbox-mcp-server.log");
|
|
59129
59403
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
59130
59404
|
dataDir: config.dataDir,
|
|
59131
59405
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -59144,10 +59418,10 @@ async function startDaemon(config) {
|
|
|
59144
59418
|
);
|
|
59145
59419
|
}
|
|
59146
59420
|
const peerOpsServerCandidates = [
|
|
59147
|
-
|
|
59148
|
-
|
|
59421
|
+
import_node_path61.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
59422
|
+
import_node_path61.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
59149
59423
|
];
|
|
59150
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) =>
|
|
59424
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p2) => import_node_fs46.default.existsSync(p2));
|
|
59151
59425
|
if (peerOpsServerScriptPath) {
|
|
59152
59426
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
59153
59427
|
dataDir: config.dataDir,
|
|
@@ -59165,7 +59439,7 @@ async function startDaemon(config) {
|
|
|
59165
59439
|
);
|
|
59166
59440
|
}
|
|
59167
59441
|
const shiftStore = createShiftStore({
|
|
59168
|
-
filePath:
|
|
59442
|
+
filePath: import_node_path61.default.join(config.dataDir, "shift.json"),
|
|
59169
59443
|
ownerIdProvider: () => ownerPrincipalId,
|
|
59170
59444
|
now: () => Date.now()
|
|
59171
59445
|
});
|
|
@@ -59187,7 +59461,10 @@ async function startDaemon(config) {
|
|
|
59187
59461
|
getAdapter,
|
|
59188
59462
|
historyReader: history,
|
|
59189
59463
|
dataDir: config.dataDir,
|
|
59190
|
-
personaRoot:
|
|
59464
|
+
personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
|
|
59465
|
+
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
59466
|
+
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
59467
|
+
getPersonaTool: (personaId) => personaRegistry.get(personaId)?.tool,
|
|
59191
59468
|
usersRoot,
|
|
59192
59469
|
personaStore,
|
|
59193
59470
|
ownerDisplayName,
|
|
@@ -59227,10 +59504,10 @@ async function startDaemon(config) {
|
|
|
59227
59504
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
59228
59505
|
attachmentGroup: {
|
|
59229
59506
|
onFileEdit: (input) => {
|
|
59230
|
-
const absPath =
|
|
59507
|
+
const absPath = import_node_path61.default.isAbsolute(input.relPath) ? input.relPath : import_node_path61.default.join(input.cwd, input.relPath);
|
|
59231
59508
|
let size = 0;
|
|
59232
59509
|
try {
|
|
59233
|
-
size =
|
|
59510
|
+
size = import_node_fs46.default.statSync(absPath).size;
|
|
59234
59511
|
} catch (err) {
|
|
59235
59512
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
59236
59513
|
sessionId: input.sessionId,
|
|
@@ -59313,6 +59590,7 @@ async function startDaemon(config) {
|
|
|
59313
59590
|
}) : new ClaudeAdapter({ logger, historyReader: new ClaudeHistoryReader() });
|
|
59314
59591
|
registerAdapter("claude", claudeAdapter);
|
|
59315
59592
|
registerAdapter("codex", new CodexAdapter({ logger, historyReader: new CodexHistoryReader() }));
|
|
59593
|
+
warmCodexFeatureCache();
|
|
59316
59594
|
const personaRegistry = new PersonaRegistry(personaStore);
|
|
59317
59595
|
const personaManager = new PersonaManager({
|
|
59318
59596
|
store: personaStore,
|
|
@@ -59460,11 +59738,11 @@ async function startDaemon(config) {
|
|
|
59460
59738
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
59461
59739
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
59462
59740
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
59463
|
-
personaRoot:
|
|
59741
|
+
personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
|
|
59464
59742
|
usersRoot
|
|
59465
59743
|
},
|
|
59466
59744
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
59467
|
-
personaRoot:
|
|
59745
|
+
personaRoot: import_node_path61.default.join(config.dataDir, "personas"),
|
|
59468
59746
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
59469
59747
|
usersRoot,
|
|
59470
59748
|
// capability:list / delete handler 依赖
|
|
@@ -59575,11 +59853,11 @@ async function startDaemon(config) {
|
|
|
59575
59853
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
59576
59854
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
59577
59855
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
59578
|
-
appBuilderPersonaRoot:
|
|
59856
|
+
appBuilderPersonaRoot: import_node_path61.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
59579
59857
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
59580
|
-
deployKitRoot:
|
|
59858
|
+
deployKitRoot: import_node_path61.default.join(config.dataDir, "deploy-kit"),
|
|
59581
59859
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
59582
|
-
resolvePersonaRoot: (personaId) =>
|
|
59860
|
+
resolvePersonaRoot: (personaId) => import_node_path61.default.join(config.dataDir, "personas", personaId),
|
|
59583
59861
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
59584
59862
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
59585
59863
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -59610,6 +59888,8 @@ async function startDaemon(config) {
|
|
|
59610
59888
|
const dispatchHandlers = buildPersonaDispatchHandlers({
|
|
59611
59889
|
personaDispatchManager,
|
|
59612
59890
|
store: dispatchStore,
|
|
59891
|
+
// 续派(spec 2026-07-21):任务包注入 worker session,复用投递同款注入路径。
|
|
59892
|
+
sendFollowUp: (workerSessionId, text) => manager.injectIntoSession(workerSessionId, text),
|
|
59613
59893
|
logger,
|
|
59614
59894
|
spawnB: async (args) => {
|
|
59615
59895
|
logger.info("dispatch.spawnB.start", {
|
|
@@ -59623,7 +59903,7 @@ async function startDaemon(config) {
|
|
|
59623
59903
|
}
|
|
59624
59904
|
let sourceJsonlPath = "(no transcript yet \u2014 operate from the task description alone)";
|
|
59625
59905
|
if (sourceFile && sourceFile.toolSessionId) {
|
|
59626
|
-
sourceJsonlPath =
|
|
59906
|
+
sourceJsonlPath = import_node_path61.default.join(
|
|
59627
59907
|
import_node_os22.default.homedir(),
|
|
59628
59908
|
".claude",
|
|
59629
59909
|
"projects",
|
|
@@ -59669,7 +59949,9 @@ async function startDaemon(config) {
|
|
|
59669
59949
|
});
|
|
59670
59950
|
},
|
|
59671
59951
|
// B 角色:判断 targetPersona 是否 public(跨设备授权边界,private 拒)。
|
|
59672
|
-
getPersonaPublic: (personaId) => personaRegistry.get(personaId)?.public ?? false
|
|
59952
|
+
getPersonaPublic: (personaId) => personaRegistry.get(personaId)?.public ?? false,
|
|
59953
|
+
// model 校验按 target persona 绑定 tool 选表(claude / codex 模型集不同)
|
|
59954
|
+
getPersonaTool: (personaId) => personaRegistry.get(personaId)?.tool
|
|
59673
59955
|
});
|
|
59674
59956
|
handlers = { ...handlers, ...dispatchHandlers };
|
|
59675
59957
|
const shiftHandlers = buildShiftInternalHandlers({
|
|
@@ -59941,8 +60223,8 @@ async function startDaemon(config) {
|
|
|
59941
60223
|
const lines = [
|
|
59942
60224
|
`Tunnel: ${r.url}`,
|
|
59943
60225
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
59944
|
-
`Frpc config: ${
|
|
59945
|
-
`Frpc log: ${
|
|
60226
|
+
`Frpc config: ${import_node_path61.default.join(config.dataDir, "frpc.toml")}`,
|
|
60227
|
+
`Frpc log: ${import_node_path61.default.join(logDir, "frpc.log")}`
|
|
59946
60228
|
];
|
|
59947
60229
|
const width = Math.max(...lines.map((l) => l.length));
|
|
59948
60230
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -59955,8 +60237,8 @@ ${bar}
|
|
|
59955
60237
|
|
|
59956
60238
|
`);
|
|
59957
60239
|
try {
|
|
59958
|
-
const connectPath =
|
|
59959
|
-
|
|
60240
|
+
const connectPath = import_node_path61.default.join(config.dataDir, "connect.txt");
|
|
60241
|
+
import_node_fs46.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
59960
60242
|
} catch {
|
|
59961
60243
|
}
|
|
59962
60244
|
} catch (err) {
|
|
@@ -60028,9 +60310,9 @@ ${bar}
|
|
|
60028
60310
|
};
|
|
60029
60311
|
}
|
|
60030
60312
|
function migrateDropPersonsDir(dataDir) {
|
|
60031
|
-
const dir =
|
|
60313
|
+
const dir = import_node_path61.default.join(dataDir, "persons");
|
|
60032
60314
|
try {
|
|
60033
|
-
|
|
60315
|
+
import_node_fs46.default.rmSync(dir, { recursive: true, force: true });
|
|
60034
60316
|
} catch {
|
|
60035
60317
|
}
|
|
60036
60318
|
}
|