@clawos-dev/clawd 0.2.156-beta.327.ef22c15 → 0.2.157-beta.328.919c18f
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 +547 -474
- package/dist/ticket/mcp-server.cjs +21245 -0
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -720,8 +720,8 @@ var init_parseUtil = __esm({
|
|
|
720
720
|
init_errors2();
|
|
721
721
|
init_en();
|
|
722
722
|
makeIssue = (params) => {
|
|
723
|
-
const { data, path:
|
|
724
|
-
const fullPath = [...
|
|
723
|
+
const { data, path: path61, errorMaps, issueData } = params;
|
|
724
|
+
const fullPath = [...path61, ...issueData.path || []];
|
|
725
725
|
const fullIssue = {
|
|
726
726
|
...issueData,
|
|
727
727
|
path: fullPath
|
|
@@ -1032,11 +1032,11 @@ var init_types = __esm({
|
|
|
1032
1032
|
init_parseUtil();
|
|
1033
1033
|
init_util();
|
|
1034
1034
|
ParseInputLazyPath = class {
|
|
1035
|
-
constructor(parent, value,
|
|
1035
|
+
constructor(parent, value, path61, key) {
|
|
1036
1036
|
this._cachedPath = [];
|
|
1037
1037
|
this.parent = parent;
|
|
1038
1038
|
this.data = value;
|
|
1039
|
-
this._path =
|
|
1039
|
+
this._path = path61;
|
|
1040
1040
|
this._key = key;
|
|
1041
1041
|
}
|
|
1042
1042
|
get path() {
|
|
@@ -6298,8 +6298,8 @@ var require_req = __commonJS({
|
|
|
6298
6298
|
if (req.originalUrl) {
|
|
6299
6299
|
_req.url = req.originalUrl;
|
|
6300
6300
|
} else {
|
|
6301
|
-
const
|
|
6302
|
-
_req.url = typeof
|
|
6301
|
+
const path61 = req.path;
|
|
6302
|
+
_req.url = typeof path61 === "string" ? path61 : req.url ? req.url.path || req.url : void 0;
|
|
6303
6303
|
}
|
|
6304
6304
|
if (req.query) {
|
|
6305
6305
|
_req.query = req.query;
|
|
@@ -6464,14 +6464,14 @@ var require_redact = __commonJS({
|
|
|
6464
6464
|
}
|
|
6465
6465
|
return obj;
|
|
6466
6466
|
}
|
|
6467
|
-
function parsePath(
|
|
6467
|
+
function parsePath(path61) {
|
|
6468
6468
|
const parts = [];
|
|
6469
6469
|
let current = "";
|
|
6470
6470
|
let inBrackets = false;
|
|
6471
6471
|
let inQuotes = false;
|
|
6472
6472
|
let quoteChar = "";
|
|
6473
|
-
for (let i = 0; i <
|
|
6474
|
-
const char =
|
|
6473
|
+
for (let i = 0; i < path61.length; i++) {
|
|
6474
|
+
const char = path61[i];
|
|
6475
6475
|
if (!inBrackets && char === ".") {
|
|
6476
6476
|
if (current) {
|
|
6477
6477
|
parts.push(current);
|
|
@@ -6602,10 +6602,10 @@ var require_redact = __commonJS({
|
|
|
6602
6602
|
return current;
|
|
6603
6603
|
}
|
|
6604
6604
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
6605
|
-
for (const
|
|
6606
|
-
const parts = parsePath(
|
|
6605
|
+
for (const path61 of paths) {
|
|
6606
|
+
const parts = parsePath(path61);
|
|
6607
6607
|
if (parts.includes("*")) {
|
|
6608
|
-
redactWildcardPath(obj, parts, censor,
|
|
6608
|
+
redactWildcardPath(obj, parts, censor, path61, remove);
|
|
6609
6609
|
} else {
|
|
6610
6610
|
if (remove) {
|
|
6611
6611
|
removeKey(obj, parts);
|
|
@@ -6690,8 +6690,8 @@ var require_redact = __commonJS({
|
|
|
6690
6690
|
}
|
|
6691
6691
|
} else {
|
|
6692
6692
|
if (afterWildcard.includes("*")) {
|
|
6693
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6694
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
6693
|
+
const wrappedCensor = typeof censor === "function" ? (value, path61) => {
|
|
6694
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path61];
|
|
6695
6695
|
return censor(value, fullPath);
|
|
6696
6696
|
} : censor;
|
|
6697
6697
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -6726,8 +6726,8 @@ var require_redact = __commonJS({
|
|
|
6726
6726
|
return null;
|
|
6727
6727
|
}
|
|
6728
6728
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
6729
|
-
for (const
|
|
6730
|
-
const parts = parsePath(
|
|
6729
|
+
for (const path61 of pathsToClone) {
|
|
6730
|
+
const parts = parsePath(path61);
|
|
6731
6731
|
let current = pathStructure;
|
|
6732
6732
|
for (let i = 0; i < parts.length; i++) {
|
|
6733
6733
|
const part = parts[i];
|
|
@@ -6779,24 +6779,24 @@ var require_redact = __commonJS({
|
|
|
6779
6779
|
}
|
|
6780
6780
|
return cloneSelectively(obj, pathStructure);
|
|
6781
6781
|
}
|
|
6782
|
-
function validatePath(
|
|
6783
|
-
if (typeof
|
|
6782
|
+
function validatePath(path61) {
|
|
6783
|
+
if (typeof path61 !== "string") {
|
|
6784
6784
|
throw new Error("Paths must be (non-empty) strings");
|
|
6785
6785
|
}
|
|
6786
|
-
if (
|
|
6786
|
+
if (path61 === "") {
|
|
6787
6787
|
throw new Error("Invalid redaction path ()");
|
|
6788
6788
|
}
|
|
6789
|
-
if (
|
|
6790
|
-
throw new Error(`Invalid redaction path (${
|
|
6789
|
+
if (path61.includes("..")) {
|
|
6790
|
+
throw new Error(`Invalid redaction path (${path61})`);
|
|
6791
6791
|
}
|
|
6792
|
-
if (
|
|
6793
|
-
throw new Error(`Invalid redaction path (${
|
|
6792
|
+
if (path61.includes(",")) {
|
|
6793
|
+
throw new Error(`Invalid redaction path (${path61})`);
|
|
6794
6794
|
}
|
|
6795
6795
|
let bracketCount = 0;
|
|
6796
6796
|
let inQuotes = false;
|
|
6797
6797
|
let quoteChar = "";
|
|
6798
|
-
for (let i = 0; i <
|
|
6799
|
-
const char =
|
|
6798
|
+
for (let i = 0; i < path61.length; i++) {
|
|
6799
|
+
const char = path61[i];
|
|
6800
6800
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
6801
6801
|
if (!inQuotes) {
|
|
6802
6802
|
inQuotes = true;
|
|
@@ -6810,20 +6810,20 @@ var require_redact = __commonJS({
|
|
|
6810
6810
|
} else if (char === "]" && !inQuotes) {
|
|
6811
6811
|
bracketCount--;
|
|
6812
6812
|
if (bracketCount < 0) {
|
|
6813
|
-
throw new Error(`Invalid redaction path (${
|
|
6813
|
+
throw new Error(`Invalid redaction path (${path61})`);
|
|
6814
6814
|
}
|
|
6815
6815
|
}
|
|
6816
6816
|
}
|
|
6817
6817
|
if (bracketCount !== 0) {
|
|
6818
|
-
throw new Error(`Invalid redaction path (${
|
|
6818
|
+
throw new Error(`Invalid redaction path (${path61})`);
|
|
6819
6819
|
}
|
|
6820
6820
|
}
|
|
6821
6821
|
function validatePaths(paths) {
|
|
6822
6822
|
if (!Array.isArray(paths)) {
|
|
6823
6823
|
throw new TypeError("paths must be an array");
|
|
6824
6824
|
}
|
|
6825
|
-
for (const
|
|
6826
|
-
validatePath(
|
|
6825
|
+
for (const path61 of paths) {
|
|
6826
|
+
validatePath(path61);
|
|
6827
6827
|
}
|
|
6828
6828
|
}
|
|
6829
6829
|
function slowRedact(options = {}) {
|
|
@@ -6991,8 +6991,8 @@ var require_redaction = __commonJS({
|
|
|
6991
6991
|
if (shape[k2] === null) {
|
|
6992
6992
|
o[k2] = (value) => topCensor(value, [k2]);
|
|
6993
6993
|
} else {
|
|
6994
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
6995
|
-
return censor(value, [k2, ...
|
|
6994
|
+
const wrappedCensor = typeof censor === "function" ? (value, path61) => {
|
|
6995
|
+
return censor(value, [k2, ...path61]);
|
|
6996
6996
|
} : censor;
|
|
6997
6997
|
o[k2] = Redact({
|
|
6998
6998
|
paths: shape[k2],
|
|
@@ -7210,10 +7210,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
7210
7210
|
var require_sonic_boom = __commonJS({
|
|
7211
7211
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
7212
7212
|
"use strict";
|
|
7213
|
-
var
|
|
7213
|
+
var fs55 = require("fs");
|
|
7214
7214
|
var EventEmitter3 = require("events");
|
|
7215
7215
|
var inherits = require("util").inherits;
|
|
7216
|
-
var
|
|
7216
|
+
var path61 = require("path");
|
|
7217
7217
|
var sleep2 = require_atomic_sleep();
|
|
7218
7218
|
var assert = require("assert");
|
|
7219
7219
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -7267,20 +7267,20 @@ var require_sonic_boom = __commonJS({
|
|
|
7267
7267
|
const mode = sonic.mode;
|
|
7268
7268
|
if (sonic.sync) {
|
|
7269
7269
|
try {
|
|
7270
|
-
if (sonic.mkdir)
|
|
7271
|
-
const fd =
|
|
7270
|
+
if (sonic.mkdir) fs55.mkdirSync(path61.dirname(file), { recursive: true });
|
|
7271
|
+
const fd = fs55.openSync(file, flags, mode);
|
|
7272
7272
|
fileOpened(null, fd);
|
|
7273
7273
|
} catch (err) {
|
|
7274
7274
|
fileOpened(err);
|
|
7275
7275
|
throw err;
|
|
7276
7276
|
}
|
|
7277
7277
|
} else if (sonic.mkdir) {
|
|
7278
|
-
|
|
7278
|
+
fs55.mkdir(path61.dirname(file), { recursive: true }, (err) => {
|
|
7279
7279
|
if (err) return fileOpened(err);
|
|
7280
|
-
|
|
7280
|
+
fs55.open(file, flags, mode, fileOpened);
|
|
7281
7281
|
});
|
|
7282
7282
|
} else {
|
|
7283
|
-
|
|
7283
|
+
fs55.open(file, flags, mode, fileOpened);
|
|
7284
7284
|
}
|
|
7285
7285
|
}
|
|
7286
7286
|
function SonicBoom(opts) {
|
|
@@ -7321,8 +7321,8 @@ var require_sonic_boom = __commonJS({
|
|
|
7321
7321
|
this.flush = flushBuffer;
|
|
7322
7322
|
this.flushSync = flushBufferSync;
|
|
7323
7323
|
this._actualWrite = actualWriteBuffer;
|
|
7324
|
-
fsWriteSync = () =>
|
|
7325
|
-
fsWrite = () =>
|
|
7324
|
+
fsWriteSync = () => fs55.writeSync(this.fd, this._writingBuf);
|
|
7325
|
+
fsWrite = () => fs55.write(this.fd, this._writingBuf, this.release);
|
|
7326
7326
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
7327
7327
|
this._writingBuf = "";
|
|
7328
7328
|
this.write = write;
|
|
@@ -7331,15 +7331,15 @@ var require_sonic_boom = __commonJS({
|
|
|
7331
7331
|
this._actualWrite = actualWrite;
|
|
7332
7332
|
fsWriteSync = () => {
|
|
7333
7333
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7334
|
-
return
|
|
7334
|
+
return fs55.writeSync(this.fd, this._writingBuf);
|
|
7335
7335
|
}
|
|
7336
|
-
return
|
|
7336
|
+
return fs55.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7337
7337
|
};
|
|
7338
7338
|
fsWrite = () => {
|
|
7339
7339
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
7340
|
-
return
|
|
7340
|
+
return fs55.write(this.fd, this._writingBuf, this.release);
|
|
7341
7341
|
}
|
|
7342
|
-
return
|
|
7342
|
+
return fs55.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
7343
7343
|
};
|
|
7344
7344
|
} else {
|
|
7345
7345
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -7396,7 +7396,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7396
7396
|
}
|
|
7397
7397
|
}
|
|
7398
7398
|
if (this._fsync) {
|
|
7399
|
-
|
|
7399
|
+
fs55.fsyncSync(this.fd);
|
|
7400
7400
|
}
|
|
7401
7401
|
const len = this._len;
|
|
7402
7402
|
if (this._reopening) {
|
|
@@ -7510,7 +7510,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7510
7510
|
const onDrain = () => {
|
|
7511
7511
|
if (!this._fsync) {
|
|
7512
7512
|
try {
|
|
7513
|
-
|
|
7513
|
+
fs55.fsync(this.fd, (err) => {
|
|
7514
7514
|
this._flushPending = false;
|
|
7515
7515
|
cb(err);
|
|
7516
7516
|
});
|
|
@@ -7612,7 +7612,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7612
7612
|
const fd = this.fd;
|
|
7613
7613
|
this.once("ready", () => {
|
|
7614
7614
|
if (fd !== this.fd) {
|
|
7615
|
-
|
|
7615
|
+
fs55.close(fd, (err) => {
|
|
7616
7616
|
if (err) {
|
|
7617
7617
|
return this.emit("error", err);
|
|
7618
7618
|
}
|
|
@@ -7661,7 +7661,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7661
7661
|
buf = this._bufs[0];
|
|
7662
7662
|
}
|
|
7663
7663
|
try {
|
|
7664
|
-
const n = Buffer.isBuffer(buf) ?
|
|
7664
|
+
const n = Buffer.isBuffer(buf) ? fs55.writeSync(this.fd, buf) : fs55.writeSync(this.fd, buf, "utf8");
|
|
7665
7665
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
7666
7666
|
buf = releasedBufObj.writingBuf;
|
|
7667
7667
|
this._len = releasedBufObj.len;
|
|
@@ -7677,7 +7677,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7677
7677
|
}
|
|
7678
7678
|
}
|
|
7679
7679
|
try {
|
|
7680
|
-
|
|
7680
|
+
fs55.fsyncSync(this.fd);
|
|
7681
7681
|
} catch {
|
|
7682
7682
|
}
|
|
7683
7683
|
}
|
|
@@ -7698,7 +7698,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7698
7698
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
7699
7699
|
}
|
|
7700
7700
|
try {
|
|
7701
|
-
const n =
|
|
7701
|
+
const n = fs55.writeSync(this.fd, buf);
|
|
7702
7702
|
buf = buf.subarray(n);
|
|
7703
7703
|
this._len = Math.max(this._len - n, 0);
|
|
7704
7704
|
if (buf.length <= 0) {
|
|
@@ -7726,13 +7726,13 @@ var require_sonic_boom = __commonJS({
|
|
|
7726
7726
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
7727
7727
|
if (this.sync) {
|
|
7728
7728
|
try {
|
|
7729
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
7729
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs55.writeSync(this.fd, this._writingBuf) : fs55.writeSync(this.fd, this._writingBuf, "utf8");
|
|
7730
7730
|
release(null, written);
|
|
7731
7731
|
} catch (err) {
|
|
7732
7732
|
release(err);
|
|
7733
7733
|
}
|
|
7734
7734
|
} else {
|
|
7735
|
-
|
|
7735
|
+
fs55.write(this.fd, this._writingBuf, release);
|
|
7736
7736
|
}
|
|
7737
7737
|
}
|
|
7738
7738
|
function actualWriteBuffer() {
|
|
@@ -7741,7 +7741,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7741
7741
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
7742
7742
|
if (this.sync) {
|
|
7743
7743
|
try {
|
|
7744
|
-
const written =
|
|
7744
|
+
const written = fs55.writeSync(this.fd, this._writingBuf);
|
|
7745
7745
|
release(null, written);
|
|
7746
7746
|
} catch (err) {
|
|
7747
7747
|
release(err);
|
|
@@ -7750,7 +7750,7 @@ var require_sonic_boom = __commonJS({
|
|
|
7750
7750
|
if (kCopyBuffer) {
|
|
7751
7751
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
7752
7752
|
}
|
|
7753
|
-
|
|
7753
|
+
fs55.write(this.fd, this._writingBuf, release);
|
|
7754
7754
|
}
|
|
7755
7755
|
}
|
|
7756
7756
|
function actualClose(sonic) {
|
|
@@ -7766,12 +7766,12 @@ var require_sonic_boom = __commonJS({
|
|
|
7766
7766
|
sonic._lens = [];
|
|
7767
7767
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
7768
7768
|
try {
|
|
7769
|
-
|
|
7769
|
+
fs55.fsync(sonic.fd, closeWrapped);
|
|
7770
7770
|
} catch {
|
|
7771
7771
|
}
|
|
7772
7772
|
function closeWrapped() {
|
|
7773
7773
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
7774
|
-
|
|
7774
|
+
fs55.close(sonic.fd, done);
|
|
7775
7775
|
} else {
|
|
7776
7776
|
done();
|
|
7777
7777
|
}
|
|
@@ -10906,11 +10906,11 @@ var init_lib = __esm({
|
|
|
10906
10906
|
}
|
|
10907
10907
|
}
|
|
10908
10908
|
},
|
|
10909
|
-
addToPath: function addToPath(
|
|
10910
|
-
var last =
|
|
10909
|
+
addToPath: function addToPath(path61, added, removed, oldPosInc, options) {
|
|
10910
|
+
var last = path61.lastComponent;
|
|
10911
10911
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
10912
10912
|
return {
|
|
10913
|
-
oldPos:
|
|
10913
|
+
oldPos: path61.oldPos + oldPosInc,
|
|
10914
10914
|
lastComponent: {
|
|
10915
10915
|
count: last.count + 1,
|
|
10916
10916
|
added,
|
|
@@ -10920,7 +10920,7 @@ var init_lib = __esm({
|
|
|
10920
10920
|
};
|
|
10921
10921
|
} else {
|
|
10922
10922
|
return {
|
|
10923
|
-
oldPos:
|
|
10923
|
+
oldPos: path61.oldPos + oldPosInc,
|
|
10924
10924
|
lastComponent: {
|
|
10925
10925
|
count: 1,
|
|
10926
10926
|
added,
|
|
@@ -11366,10 +11366,10 @@ function attachmentToHistoryMessage(o, ts) {
|
|
|
11366
11366
|
const memories = raw.map((m2) => {
|
|
11367
11367
|
if (!m2 || typeof m2 !== "object") return null;
|
|
11368
11368
|
const rec3 = m2;
|
|
11369
|
-
const
|
|
11369
|
+
const path61 = typeof rec3.path === "string" ? rec3.path : null;
|
|
11370
11370
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
11371
|
-
if (!
|
|
11372
|
-
const entry = { path:
|
|
11371
|
+
if (!path61 || content == null) return null;
|
|
11372
|
+
const entry = { path: path61, content };
|
|
11373
11373
|
if (typeof rec3.mtimeMs === "number") entry.mtimeMs = rec3.mtimeMs;
|
|
11374
11374
|
return entry;
|
|
11375
11375
|
}).filter((m2) => m2 !== null);
|
|
@@ -11892,6 +11892,9 @@ function buildSpawnArgs(ctx) {
|
|
|
11892
11892
|
if (ctx.dispatchMcpConfigPath) {
|
|
11893
11893
|
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
11894
11894
|
}
|
|
11895
|
+
if (ctx.ticketMcpConfigPath) {
|
|
11896
|
+
args.push("--mcp-config", ctx.ticketMcpConfigPath);
|
|
11897
|
+
}
|
|
11895
11898
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
11896
11899
|
if (ctx.toolSessionId) args.push("--resume", ctx.toolSessionId);
|
|
11897
11900
|
return args;
|
|
@@ -12171,10 +12174,10 @@ function parseAttachment(obj) {
|
|
|
12171
12174
|
const memories = raw.map((m2) => {
|
|
12172
12175
|
if (!m2 || typeof m2 !== "object") return null;
|
|
12173
12176
|
const rec3 = m2;
|
|
12174
|
-
const
|
|
12177
|
+
const path61 = typeof rec3.path === "string" ? rec3.path : null;
|
|
12175
12178
|
const content = typeof rec3.content === "string" ? rec3.content : null;
|
|
12176
|
-
if (!
|
|
12177
|
-
const out = { path:
|
|
12179
|
+
if (!path61 || content == null) return null;
|
|
12180
|
+
const out = { path: path61, content };
|
|
12178
12181
|
if (typeof rec3.mtimeMs === "number") out.mtimeMs = rec3.mtimeMs;
|
|
12179
12182
|
return out;
|
|
12180
12183
|
}).filter((m2) => m2 !== null);
|
|
@@ -23961,8 +23964,8 @@ var require_utils = __commonJS({
|
|
|
23961
23964
|
var result = transform[inputType][outputType](input);
|
|
23962
23965
|
return result;
|
|
23963
23966
|
};
|
|
23964
|
-
exports2.resolve = function(
|
|
23965
|
-
var parts =
|
|
23967
|
+
exports2.resolve = function(path61) {
|
|
23968
|
+
var parts = path61.split("/");
|
|
23966
23969
|
var result = [];
|
|
23967
23970
|
for (var index = 0; index < parts.length; index++) {
|
|
23968
23971
|
var part = parts[index];
|
|
@@ -29815,18 +29818,18 @@ var require_object = __commonJS({
|
|
|
29815
29818
|
var object = new ZipObject(name, zipObjectContent, o);
|
|
29816
29819
|
this.files[name] = object;
|
|
29817
29820
|
};
|
|
29818
|
-
var parentFolder = function(
|
|
29819
|
-
if (
|
|
29820
|
-
|
|
29821
|
+
var parentFolder = function(path61) {
|
|
29822
|
+
if (path61.slice(-1) === "/") {
|
|
29823
|
+
path61 = path61.substring(0, path61.length - 1);
|
|
29821
29824
|
}
|
|
29822
|
-
var lastSlash =
|
|
29823
|
-
return lastSlash > 0 ?
|
|
29825
|
+
var lastSlash = path61.lastIndexOf("/");
|
|
29826
|
+
return lastSlash > 0 ? path61.substring(0, lastSlash) : "";
|
|
29824
29827
|
};
|
|
29825
|
-
var forceTrailingSlash = function(
|
|
29826
|
-
if (
|
|
29827
|
-
|
|
29828
|
+
var forceTrailingSlash = function(path61) {
|
|
29829
|
+
if (path61.slice(-1) !== "/") {
|
|
29830
|
+
path61 += "/";
|
|
29828
29831
|
}
|
|
29829
|
-
return
|
|
29832
|
+
return path61;
|
|
29830
29833
|
};
|
|
29831
29834
|
var folderAdd = function(name, createFolders) {
|
|
29832
29835
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -30828,7 +30831,7 @@ var require_lib3 = __commonJS({
|
|
|
30828
30831
|
// src/run-case/recorder.ts
|
|
30829
30832
|
function startRunCaseRecorder(opts) {
|
|
30830
30833
|
const now = opts.now ?? Date.now;
|
|
30831
|
-
const dir =
|
|
30834
|
+
const dir = import_node_path49.default.dirname(opts.recordPath);
|
|
30832
30835
|
let stream = null;
|
|
30833
30836
|
let closing = false;
|
|
30834
30837
|
let closedSettled = false;
|
|
@@ -30842,8 +30845,8 @@ function startRunCaseRecorder(opts) {
|
|
|
30842
30845
|
});
|
|
30843
30846
|
const ensureStream = () => {
|
|
30844
30847
|
if (stream) return stream;
|
|
30845
|
-
|
|
30846
|
-
stream =
|
|
30848
|
+
import_node_fs38.default.mkdirSync(dir, { recursive: true });
|
|
30849
|
+
stream = import_node_fs38.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
30847
30850
|
stream.on("close", () => closedResolve());
|
|
30848
30851
|
return stream;
|
|
30849
30852
|
};
|
|
@@ -30868,12 +30871,12 @@ function startRunCaseRecorder(opts) {
|
|
|
30868
30871
|
};
|
|
30869
30872
|
return { tap, close, closed };
|
|
30870
30873
|
}
|
|
30871
|
-
var
|
|
30874
|
+
var import_node_fs38, import_node_path49;
|
|
30872
30875
|
var init_recorder = __esm({
|
|
30873
30876
|
"src/run-case/recorder.ts"() {
|
|
30874
30877
|
"use strict";
|
|
30875
|
-
|
|
30876
|
-
|
|
30878
|
+
import_node_fs38 = __toESM(require("fs"), 1);
|
|
30879
|
+
import_node_path49 = __toESM(require("path"), 1);
|
|
30877
30880
|
}
|
|
30878
30881
|
});
|
|
30879
30882
|
|
|
@@ -30916,7 +30919,7 @@ var init_wire = __esm({
|
|
|
30916
30919
|
// src/run-case/controller.ts
|
|
30917
30920
|
async function runController(opts) {
|
|
30918
30921
|
const now = opts.now ?? Date.now;
|
|
30919
|
-
const cwd = opts.cwd ?? (0,
|
|
30922
|
+
const cwd = opts.cwd ?? (0, import_node_fs39.mkdtempSync)(import_node_path50.default.join(import_node_os21.default.tmpdir(), "clawd-runcase-"));
|
|
30920
30923
|
const ownsCwd = opts.cwd === void 0;
|
|
30921
30924
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
30922
30925
|
const spawnCtx = { cwd };
|
|
@@ -31077,19 +31080,19 @@ async function runController(opts) {
|
|
|
31077
31080
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
31078
31081
|
if (ownsCwd) {
|
|
31079
31082
|
try {
|
|
31080
|
-
(0,
|
|
31083
|
+
(0, import_node_fs39.rmSync)(cwd, { recursive: true, force: true });
|
|
31081
31084
|
} catch {
|
|
31082
31085
|
}
|
|
31083
31086
|
}
|
|
31084
31087
|
return exitCode ?? 0;
|
|
31085
31088
|
}
|
|
31086
|
-
var
|
|
31089
|
+
var import_node_fs39, import_node_os21, import_node_path50;
|
|
31087
31090
|
var init_controller = __esm({
|
|
31088
31091
|
"src/run-case/controller.ts"() {
|
|
31089
31092
|
"use strict";
|
|
31090
|
-
|
|
31093
|
+
import_node_fs39 = require("fs");
|
|
31091
31094
|
import_node_os21 = __toESM(require("os"), 1);
|
|
31092
|
-
|
|
31095
|
+
import_node_path50 = __toESM(require("path"), 1);
|
|
31093
31096
|
init_claude();
|
|
31094
31097
|
init_stdout_splitter();
|
|
31095
31098
|
init_permission_stdio();
|
|
@@ -31351,8 +31354,8 @@ Env (advanced):
|
|
|
31351
31354
|
`;
|
|
31352
31355
|
|
|
31353
31356
|
// src/index.ts
|
|
31354
|
-
var
|
|
31355
|
-
var
|
|
31357
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
31358
|
+
var import_node_fs37 = __toESM(require("fs"), 1);
|
|
31356
31359
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
31357
31360
|
|
|
31358
31361
|
// ../node_modules/.pnpm/uuid@10.0.0/node_modules/uuid/dist/esm-node/stringify.js
|
|
@@ -32218,6 +32221,8 @@ function buildSpawnContext(state, deps) {
|
|
|
32218
32221
|
const dispatchId = deps.lookupDispatchByBSessionId?.(file.sessionId);
|
|
32219
32222
|
if (dispatchId) env.CLAWD_DISPATCH_ID = dispatchId;
|
|
32220
32223
|
const dispatchMcpConfigPath2 = deps.getDispatchMcpConfigPath?.() ?? null;
|
|
32224
|
+
const ticketMcpConfigPathRaw = deps.getTicketMcpConfigPath?.() ?? null;
|
|
32225
|
+
const ticketMcpConfigPath2 = ticketMcpConfigPathRaw && file.ownerPersonaId === "persona-developer" ? ticketMcpConfigPathRaw : null;
|
|
32221
32226
|
const ctx = {
|
|
32222
32227
|
cwd: file.cwd,
|
|
32223
32228
|
toolSessionId: file.toolSessionId,
|
|
@@ -32230,7 +32235,8 @@ function buildSpawnContext(state, deps) {
|
|
|
32230
32235
|
personaRoot: deps.personaRoot,
|
|
32231
32236
|
// Persona dispatch:所有 session(A 和 B)都挂同一份 dispatch.mcp.json,让两边的 cc
|
|
32232
32237
|
// 都能看到 personaDispatch / personaDispatchComplete tool;按 env 区分实际行为。
|
|
32233
|
-
dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0
|
|
32238
|
+
dispatchMcpConfigPath: dispatchMcpConfigPath2 ?? void 0,
|
|
32239
|
+
ticketMcpConfigPath: ticketMcpConfigPath2 ?? void 0
|
|
32234
32240
|
};
|
|
32235
32241
|
const meta = state.subSessionMeta;
|
|
32236
32242
|
if (meta?.personaMode) {
|
|
@@ -32996,6 +33002,8 @@ var SessionRunner = class {
|
|
|
32996
33002
|
// Persona dispatch:透传 dispatch.mcp.json 路径闭包 + B→dispatchId 反查闭包。
|
|
32997
33003
|
// 见 reducer.buildSpawnContext 注 CLAWD_DISPATCH_ID env / 派生 SpawnContext.dispatchMcpConfigPath
|
|
32998
33004
|
getDispatchMcpConfigPath: this.hooks.getDispatchMcpConfigPath,
|
|
33005
|
+
// Ticket MCP:透传 ticket.mcp.json 路径闭包(reducer 内做 persona-developer gating)
|
|
33006
|
+
getTicketMcpConfigPath: this.hooks.getTicketMcpConfigPath,
|
|
32999
33007
|
lookupDispatchByBSessionId: this.hooks.lookupDispatchByBSessionId,
|
|
33000
33008
|
// ReadyGate v2:透传 mode 让 reducer send / ready-detected 分支决定走暂存队列还是直写
|
|
33001
33009
|
mode: this.hooks.mode,
|
|
@@ -33791,6 +33799,7 @@ var SessionManager = class {
|
|
|
33791
33799
|
// Persona dispatch (Task 7): dispatch.mcp.json 路径 + B sessionId → dispatchId 反查
|
|
33792
33800
|
// 闭包透传给 reducer,让 cc spawn 加 --mcp-config flag + B session 注 CLAWD_DISPATCH_ID env.
|
|
33793
33801
|
getDispatchMcpConfigPath: this.deps.dispatchMcpConfigPath ? () => this.deps.dispatchMcpConfigPath ?? null : void 0,
|
|
33802
|
+
getTicketMcpConfigPath: this.deps.ticketMcpConfigPath ? () => this.deps.ticketMcpConfigPath ?? null : void 0,
|
|
33794
33803
|
lookupDispatchByBSessionId: this.deps.personaDispatchManager ? (bSid) => this.deps.personaDispatchManager?.lookupDispatchByBSessionId(bSid) : void 0,
|
|
33795
33804
|
// file-sharing (spec §6 PR 3):闭包 scope + sessionId,runner 只暴露 tool/relPath/cwd
|
|
33796
33805
|
onFileEdit: attachmentGroup ? (input) => attachmentGroup.onFileEdit({
|
|
@@ -36328,8 +36337,8 @@ function turnStartInput(text) {
|
|
|
36328
36337
|
const items = [];
|
|
36329
36338
|
let leftover = text;
|
|
36330
36339
|
for (const m2 of text.matchAll(SKILL_RE)) {
|
|
36331
|
-
const [marker, name,
|
|
36332
|
-
items.push({ type: "skill", name, path:
|
|
36340
|
+
const [marker, name, path61] = m2;
|
|
36341
|
+
items.push({ type: "skill", name, path: path61 });
|
|
36333
36342
|
leftover = leftover.replace(marker, "");
|
|
36334
36343
|
}
|
|
36335
36344
|
for (const m2 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -37623,6 +37632,9 @@ function buildTuiSpawnArgs(ctx, isResume = false) {
|
|
|
37623
37632
|
if (ctx.dispatchMcpConfigPath) {
|
|
37624
37633
|
args.push("--mcp-config", ctx.dispatchMcpConfigPath);
|
|
37625
37634
|
}
|
|
37635
|
+
if (ctx.ticketMcpConfigPath) {
|
|
37636
|
+
args.push("--mcp-config", ctx.ticketMcpConfigPath);
|
|
37637
|
+
}
|
|
37626
37638
|
if (ctx.effort) args.push("--effort", ctx.effort);
|
|
37627
37639
|
return args;
|
|
37628
37640
|
}
|
|
@@ -37723,6 +37735,43 @@ function writeDispatchMcpConfig(args) {
|
|
|
37723
37735
|
return cfgPath;
|
|
37724
37736
|
}
|
|
37725
37737
|
|
|
37738
|
+
// src/ticket/mcp-config.ts
|
|
37739
|
+
var import_node_fs15 = __toESM(require("fs"), 1);
|
|
37740
|
+
var import_node_path12 = __toESM(require("path"), 1);
|
|
37741
|
+
function ticketMcpConfigPath(dataDir) {
|
|
37742
|
+
return import_node_path12.default.join(dataDir, "ticket.mcp.json");
|
|
37743
|
+
}
|
|
37744
|
+
function writeTicketMcpConfig(args) {
|
|
37745
|
+
const cfgPath = ticketMcpConfigPath(args.dataDir);
|
|
37746
|
+
const content = {
|
|
37747
|
+
_comment: "daemon \u542F\u52A8\u65F6\u81EA\u52A8\u751F\u6210\uFF1Bcc spawn \u901A\u8FC7 --mcp-config \u6CE8\u5165\u3002ticket-mcp-server.cjs \u662F daemon \u81EA\u5E26\u7684 stdio MCP server\uFF0CHTTP client \u8C03 clawos api /clawd-tickets/*\u3002env \u542B api url\u3001\u5199\u6B7B API key\u3001\u98DE\u4E66 unionId\u3001displayName snapshot\u3002",
|
|
37748
|
+
mcpServers: {
|
|
37749
|
+
"clawd-ticket": {
|
|
37750
|
+
type: "stdio",
|
|
37751
|
+
command: "node",
|
|
37752
|
+
args: [args.serverScriptPath],
|
|
37753
|
+
env: {
|
|
37754
|
+
CLAWD_TICKET_API_URL: args.apiBaseUrl,
|
|
37755
|
+
CLAWD_TICKET_API_KEY: args.apiKey,
|
|
37756
|
+
CLAWD_TICKET_OWNER_UNION_ID: args.ownerUnionId,
|
|
37757
|
+
CLAWD_TICKET_OWNER_NAME: args.ownerName
|
|
37758
|
+
}
|
|
37759
|
+
}
|
|
37760
|
+
}
|
|
37761
|
+
};
|
|
37762
|
+
import_node_fs15.default.mkdirSync(args.dataDir, { recursive: true });
|
|
37763
|
+
import_node_fs15.default.writeFileSync(cfgPath, JSON.stringify(content, null, 2), "utf8");
|
|
37764
|
+
return cfgPath;
|
|
37765
|
+
}
|
|
37766
|
+
|
|
37767
|
+
// src/ticket/constants.ts
|
|
37768
|
+
var DEFAULT_CLAWD_TICKETS_API_KEY = "cf057f047674896978ddcc813adbc4a186551a6fcf59ad9d";
|
|
37769
|
+
function resolveClawdTicketsApiKey() {
|
|
37770
|
+
const fromEnv = process.env.CLAWD_TICKETS_API_KEY;
|
|
37771
|
+
if (fromEnv && fromEnv.length > 0) return fromEnv;
|
|
37772
|
+
return DEFAULT_CLAWD_TICKETS_API_KEY;
|
|
37773
|
+
}
|
|
37774
|
+
|
|
37726
37775
|
// src/handlers/persona-dispatch.ts
|
|
37727
37776
|
init_protocol();
|
|
37728
37777
|
function buildPersonaDispatchHandlers(deps) {
|
|
@@ -37975,13 +38024,13 @@ function mapSkillsListResponse(res) {
|
|
|
37975
38024
|
const r = s ?? {};
|
|
37976
38025
|
const name = str3(r.name);
|
|
37977
38026
|
if (!name) continue;
|
|
37978
|
-
const
|
|
38027
|
+
const path61 = str3(r.path);
|
|
37979
38028
|
const description = str3(r.description);
|
|
37980
38029
|
const isPlugin = name.includes(":");
|
|
37981
38030
|
out.push({
|
|
37982
38031
|
name,
|
|
37983
38032
|
source: isPlugin ? "plugin" : "project",
|
|
37984
|
-
...
|
|
38033
|
+
...path61 ? { path: path61 } : {},
|
|
37985
38034
|
...description ? { description } : {},
|
|
37986
38035
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
37987
38036
|
});
|
|
@@ -38020,23 +38069,23 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
38020
38069
|
}
|
|
38021
38070
|
|
|
38022
38071
|
// src/workspace/browser.ts
|
|
38023
|
-
var
|
|
38072
|
+
var import_node_fs16 = __toESM(require("fs"), 1);
|
|
38024
38073
|
var import_node_os7 = __toESM(require("os"), 1);
|
|
38025
|
-
var
|
|
38074
|
+
var import_node_path13 = __toESM(require("path"), 1);
|
|
38026
38075
|
init_protocol();
|
|
38027
38076
|
var MAX_FILE_BYTES = 2 * 1024 * 1024;
|
|
38028
38077
|
function resolveInsideCwd(cwd, subpath) {
|
|
38029
|
-
const absCwd =
|
|
38030
|
-
const joined =
|
|
38031
|
-
const rel =
|
|
38032
|
-
if (rel.startsWith("..") ||
|
|
38078
|
+
const absCwd = import_node_path13.default.resolve(cwd);
|
|
38079
|
+
const joined = import_node_path13.default.resolve(absCwd, subpath ?? ".");
|
|
38080
|
+
const rel = import_node_path13.default.relative(absCwd, joined);
|
|
38081
|
+
if (rel.startsWith("..") || import_node_path13.default.isAbsolute(rel)) {
|
|
38033
38082
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
38034
38083
|
}
|
|
38035
38084
|
return joined;
|
|
38036
38085
|
}
|
|
38037
38086
|
function ensureCwd(cwd) {
|
|
38038
38087
|
try {
|
|
38039
|
-
const stat =
|
|
38088
|
+
const stat = import_node_fs16.default.statSync(cwd);
|
|
38040
38089
|
if (!stat.isDirectory()) {
|
|
38041
38090
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
38042
38091
|
}
|
|
@@ -38050,7 +38099,7 @@ var WorkspaceBrowser = class {
|
|
|
38050
38099
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os7.default.homedir();
|
|
38051
38100
|
ensureCwd(cwd);
|
|
38052
38101
|
const full = resolveInsideCwd(cwd, args.path);
|
|
38053
|
-
const dirents =
|
|
38102
|
+
const dirents = import_node_fs16.default.readdirSync(full, { withFileTypes: true });
|
|
38054
38103
|
const entries = [];
|
|
38055
38104
|
for (const d of dirents) {
|
|
38056
38105
|
if (!args.showHidden && d.name.startsWith(".")) continue;
|
|
@@ -38060,7 +38109,7 @@ var WorkspaceBrowser = class {
|
|
|
38060
38109
|
mtime: ""
|
|
38061
38110
|
};
|
|
38062
38111
|
try {
|
|
38063
|
-
const st =
|
|
38112
|
+
const st = import_node_fs16.default.statSync(import_node_path13.default.join(full, d.name));
|
|
38064
38113
|
entry.mtime = new Date(st.mtimeMs).toISOString();
|
|
38065
38114
|
if (d.isFile()) entry.size = st.size;
|
|
38066
38115
|
} catch {
|
|
@@ -38076,14 +38125,14 @@ var WorkspaceBrowser = class {
|
|
|
38076
38125
|
read(args) {
|
|
38077
38126
|
ensureCwd(args.cwd);
|
|
38078
38127
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
38079
|
-
const st =
|
|
38128
|
+
const st = import_node_fs16.default.statSync(full);
|
|
38080
38129
|
if (!st.isFile()) {
|
|
38081
38130
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
38082
38131
|
}
|
|
38083
38132
|
if (st.size > MAX_FILE_BYTES) {
|
|
38084
38133
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES} bytes`);
|
|
38085
38134
|
}
|
|
38086
|
-
const buf =
|
|
38135
|
+
const buf = import_node_fs16.default.readFileSync(full);
|
|
38087
38136
|
const isBinary = buf.includes(0);
|
|
38088
38137
|
if (isBinary) {
|
|
38089
38138
|
return {
|
|
@@ -38105,20 +38154,20 @@ var WorkspaceBrowser = class {
|
|
|
38105
38154
|
};
|
|
38106
38155
|
|
|
38107
38156
|
// src/skills/agents-scanner.ts
|
|
38108
|
-
var
|
|
38157
|
+
var import_node_fs17 = __toESM(require("fs"), 1);
|
|
38109
38158
|
var import_node_os8 = __toESM(require("os"), 1);
|
|
38110
|
-
var
|
|
38159
|
+
var import_node_path14 = __toESM(require("path"), 1);
|
|
38111
38160
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
38112
38161
|
function isDirLikeSync2(p2) {
|
|
38113
38162
|
try {
|
|
38114
|
-
return
|
|
38163
|
+
return import_node_fs17.default.statSync(p2).isDirectory();
|
|
38115
38164
|
} catch {
|
|
38116
38165
|
return false;
|
|
38117
38166
|
}
|
|
38118
38167
|
}
|
|
38119
38168
|
function fileExistsSync(p2) {
|
|
38120
38169
|
try {
|
|
38121
|
-
return
|
|
38170
|
+
return import_node_fs17.default.statSync(p2).isFile();
|
|
38122
38171
|
} catch {
|
|
38123
38172
|
return false;
|
|
38124
38173
|
}
|
|
@@ -38126,7 +38175,7 @@ function fileExistsSync(p2) {
|
|
|
38126
38175
|
function parseAgentFile(filePath) {
|
|
38127
38176
|
let content;
|
|
38128
38177
|
try {
|
|
38129
|
-
content =
|
|
38178
|
+
content = import_node_fs17.default.readFileSync(filePath, "utf8");
|
|
38130
38179
|
} catch {
|
|
38131
38180
|
return {};
|
|
38132
38181
|
}
|
|
@@ -38139,16 +38188,16 @@ function parseAgentFile(filePath) {
|
|
|
38139
38188
|
function scanAgentsDir(dir, source, seen, out) {
|
|
38140
38189
|
let entries;
|
|
38141
38190
|
try {
|
|
38142
|
-
entries =
|
|
38191
|
+
entries = import_node_fs17.default.readdirSync(dir, { withFileTypes: true });
|
|
38143
38192
|
} catch {
|
|
38144
38193
|
return;
|
|
38145
38194
|
}
|
|
38146
38195
|
for (const ent of entries) {
|
|
38147
38196
|
if (!ent.name.endsWith(".md")) continue;
|
|
38148
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
38197
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path14.default.join(dir, ent.name)))) {
|
|
38149
38198
|
continue;
|
|
38150
38199
|
}
|
|
38151
|
-
const filePath =
|
|
38200
|
+
const filePath = import_node_path14.default.join(dir, ent.name);
|
|
38152
38201
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
38153
38202
|
if (seen.has(baseName)) continue;
|
|
38154
38203
|
seen.add(baseName);
|
|
@@ -38166,12 +38215,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
38166
38215
|
function walk2(dir, namespaces) {
|
|
38167
38216
|
let entries;
|
|
38168
38217
|
try {
|
|
38169
|
-
entries =
|
|
38218
|
+
entries = import_node_fs17.default.readdirSync(dir, { withFileTypes: true });
|
|
38170
38219
|
} catch {
|
|
38171
38220
|
return;
|
|
38172
38221
|
}
|
|
38173
38222
|
for (const ent of entries) {
|
|
38174
|
-
const childPath =
|
|
38223
|
+
const childPath = import_node_path14.default.join(dir, ent.name);
|
|
38175
38224
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
38176
38225
|
walk2(childPath, [...namespaces, ent.name]);
|
|
38177
38226
|
continue;
|
|
@@ -38196,13 +38245,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
38196
38245
|
walk2(root, []);
|
|
38197
38246
|
}
|
|
38198
38247
|
function readInstalledPlugins2(home) {
|
|
38199
|
-
const pluginsDir =
|
|
38200
|
-
const v2 =
|
|
38201
|
-
const v1 =
|
|
38248
|
+
const pluginsDir = import_node_path14.default.join(home, ".claude", "plugins");
|
|
38249
|
+
const v2 = import_node_path14.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
38250
|
+
const v1 = import_node_path14.default.join(pluginsDir, "installed_plugins.json");
|
|
38202
38251
|
let raw = null;
|
|
38203
38252
|
for (const candidate of [v2, v1]) {
|
|
38204
38253
|
try {
|
|
38205
|
-
raw =
|
|
38254
|
+
raw = import_node_fs17.default.readFileSync(candidate, "utf8");
|
|
38206
38255
|
break;
|
|
38207
38256
|
} catch {
|
|
38208
38257
|
}
|
|
@@ -38227,19 +38276,19 @@ function readInstalledPlugins2(home) {
|
|
|
38227
38276
|
return out;
|
|
38228
38277
|
}
|
|
38229
38278
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
38230
|
-
let cur =
|
|
38231
|
-
const fsRoot =
|
|
38279
|
+
let cur = import_node_path14.default.resolve(startCwd);
|
|
38280
|
+
const fsRoot = import_node_path14.default.parse(cur).root;
|
|
38232
38281
|
while (true) {
|
|
38233
|
-
scanAgentsDir(
|
|
38282
|
+
scanAgentsDir(import_node_path14.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
38234
38283
|
let hasGit = false;
|
|
38235
38284
|
try {
|
|
38236
|
-
hasGit =
|
|
38285
|
+
hasGit = import_node_fs17.default.existsSync(import_node_path14.default.join(cur, ".git"));
|
|
38237
38286
|
} catch {
|
|
38238
38287
|
}
|
|
38239
38288
|
if (hasGit) return;
|
|
38240
38289
|
if (cur === home) return;
|
|
38241
38290
|
if (cur === fsRoot) return;
|
|
38242
|
-
const parent =
|
|
38291
|
+
const parent = import_node_path14.default.dirname(cur);
|
|
38243
38292
|
if (parent === cur) return;
|
|
38244
38293
|
cur = parent;
|
|
38245
38294
|
}
|
|
@@ -38274,7 +38323,7 @@ var AgentsScanner = class {
|
|
|
38274
38323
|
}
|
|
38275
38324
|
const fsBlock = [];
|
|
38276
38325
|
scanAgentsDir(
|
|
38277
|
-
|
|
38326
|
+
import_node_path14.default.join(this.home, ".claude", "agents"),
|
|
38278
38327
|
"global",
|
|
38279
38328
|
seen,
|
|
38280
38329
|
fsBlock
|
|
@@ -38288,7 +38337,7 @@ var AgentsScanner = class {
|
|
|
38288
38337
|
...this.extraPluginRoots
|
|
38289
38338
|
];
|
|
38290
38339
|
for (const { name, root } of plugins) {
|
|
38291
|
-
const agentsRoot =
|
|
38340
|
+
const agentsRoot = import_node_path14.default.join(root, "agents");
|
|
38292
38341
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
38293
38342
|
}
|
|
38294
38343
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -38296,15 +38345,15 @@ var AgentsScanner = class {
|
|
|
38296
38345
|
};
|
|
38297
38346
|
|
|
38298
38347
|
// src/observer/session-observer.ts
|
|
38299
|
-
var
|
|
38348
|
+
var import_node_fs19 = __toESM(require("fs"), 1);
|
|
38300
38349
|
var import_node_os10 = __toESM(require("os"), 1);
|
|
38301
|
-
var
|
|
38350
|
+
var import_node_path16 = __toESM(require("path"), 1);
|
|
38302
38351
|
init_claude_history();
|
|
38303
38352
|
|
|
38304
38353
|
// src/observer/subagent-meta-observer.ts
|
|
38305
|
-
var
|
|
38354
|
+
var import_node_fs18 = __toESM(require("fs"), 1);
|
|
38306
38355
|
var import_node_os9 = __toESM(require("os"), 1);
|
|
38307
|
-
var
|
|
38356
|
+
var import_node_path15 = __toESM(require("path"), 1);
|
|
38308
38357
|
init_claude_history();
|
|
38309
38358
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
38310
38359
|
var SubagentMetaObserver = class {
|
|
@@ -38317,7 +38366,7 @@ var SubagentMetaObserver = class {
|
|
|
38317
38366
|
watches = /* @__PURE__ */ new Map();
|
|
38318
38367
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
38319
38368
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
38320
|
-
return
|
|
38369
|
+
return import_node_path15.default.join(
|
|
38321
38370
|
this.home,
|
|
38322
38371
|
".claude",
|
|
38323
38372
|
"projects",
|
|
@@ -38347,7 +38396,7 @@ var SubagentMetaObserver = class {
|
|
|
38347
38396
|
attachWatcher(w2) {
|
|
38348
38397
|
if (w2.watcher) return;
|
|
38349
38398
|
try {
|
|
38350
|
-
w2.watcher =
|
|
38399
|
+
w2.watcher = import_node_fs18.default.watch(w2.dirPath, { persistent: false }, (_evt, name) => {
|
|
38351
38400
|
if (!name) return;
|
|
38352
38401
|
const m2 = META_RE.exec(String(name));
|
|
38353
38402
|
if (!m2) return;
|
|
@@ -38359,7 +38408,7 @@ var SubagentMetaObserver = class {
|
|
|
38359
38408
|
scan(w2) {
|
|
38360
38409
|
let entries;
|
|
38361
38410
|
try {
|
|
38362
|
-
entries =
|
|
38411
|
+
entries = import_node_fs18.default.readdirSync(w2.dirPath);
|
|
38363
38412
|
} catch {
|
|
38364
38413
|
return;
|
|
38365
38414
|
}
|
|
@@ -38373,10 +38422,10 @@ var SubagentMetaObserver = class {
|
|
|
38373
38422
|
if (!m2) return;
|
|
38374
38423
|
const agentId = m2[1];
|
|
38375
38424
|
if (w2.emitted.has(agentId)) return;
|
|
38376
|
-
const file =
|
|
38425
|
+
const file = import_node_path15.default.join(w2.dirPath, name);
|
|
38377
38426
|
let raw;
|
|
38378
38427
|
try {
|
|
38379
|
-
raw =
|
|
38428
|
+
raw = import_node_fs18.default.readFileSync(file, "utf8");
|
|
38380
38429
|
} catch {
|
|
38381
38430
|
return;
|
|
38382
38431
|
}
|
|
@@ -38433,14 +38482,14 @@ var SessionObserver = class {
|
|
|
38433
38482
|
metaObserver;
|
|
38434
38483
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
38435
38484
|
if (override) return override;
|
|
38436
|
-
return
|
|
38485
|
+
return import_node_path16.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
38437
38486
|
}
|
|
38438
38487
|
start(args) {
|
|
38439
38488
|
this.stop(args.sessionId);
|
|
38440
38489
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
38441
38490
|
let size = 0;
|
|
38442
38491
|
try {
|
|
38443
|
-
size =
|
|
38492
|
+
size = import_node_fs19.default.statSync(filePath).size;
|
|
38444
38493
|
} catch {
|
|
38445
38494
|
}
|
|
38446
38495
|
const w2 = {
|
|
@@ -38454,10 +38503,10 @@ var SessionObserver = class {
|
|
|
38454
38503
|
prevIsRejectSentinel: false
|
|
38455
38504
|
};
|
|
38456
38505
|
try {
|
|
38457
|
-
|
|
38506
|
+
import_node_fs19.default.mkdirSync(import_node_path16.default.dirname(filePath), { recursive: true });
|
|
38458
38507
|
} catch {
|
|
38459
38508
|
}
|
|
38460
|
-
w2.watcher =
|
|
38509
|
+
w2.watcher = import_node_fs19.default.watch(import_node_path16.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
38461
38510
|
if (!changedName || !filePath.endsWith(changedName)) return;
|
|
38462
38511
|
this.poll(w2);
|
|
38463
38512
|
});
|
|
@@ -38480,7 +38529,7 @@ var SessionObserver = class {
|
|
|
38480
38529
|
// 异常静默吞,不阻塞 watcher 启动
|
|
38481
38530
|
hydrateMetaTail(w2, maxLines = 200) {
|
|
38482
38531
|
try {
|
|
38483
|
-
const raw =
|
|
38532
|
+
const raw = import_node_fs19.default.readFileSync(w2.filePath, "utf8");
|
|
38484
38533
|
if (!raw) return;
|
|
38485
38534
|
const allLines = raw.split("\n").filter((l) => l.trim().length > 0);
|
|
38486
38535
|
if (allLines.length === 0) return;
|
|
@@ -38504,7 +38553,7 @@ var SessionObserver = class {
|
|
|
38504
38553
|
poll(w2) {
|
|
38505
38554
|
let size = 0;
|
|
38506
38555
|
try {
|
|
38507
|
-
size =
|
|
38556
|
+
size = import_node_fs19.default.statSync(w2.filePath).size;
|
|
38508
38557
|
} catch {
|
|
38509
38558
|
return;
|
|
38510
38559
|
}
|
|
@@ -38513,11 +38562,11 @@ var SessionObserver = class {
|
|
|
38513
38562
|
w2.buf = "";
|
|
38514
38563
|
}
|
|
38515
38564
|
if (size === w2.lastSize) return;
|
|
38516
|
-
const fd =
|
|
38565
|
+
const fd = import_node_fs19.default.openSync(w2.filePath, "r");
|
|
38517
38566
|
try {
|
|
38518
38567
|
const len = size - w2.lastSize;
|
|
38519
38568
|
const buf = Buffer.alloc(len);
|
|
38520
|
-
|
|
38569
|
+
import_node_fs19.default.readSync(fd, buf, 0, len, w2.lastSize);
|
|
38521
38570
|
w2.lastSize = size;
|
|
38522
38571
|
w2.buf += buf.toString("utf8");
|
|
38523
38572
|
let newlineIndex;
|
|
@@ -38540,7 +38589,7 @@ var SessionObserver = class {
|
|
|
38540
38589
|
}
|
|
38541
38590
|
}
|
|
38542
38591
|
} finally {
|
|
38543
|
-
|
|
38592
|
+
import_node_fs19.default.closeSync(fd);
|
|
38544
38593
|
}
|
|
38545
38594
|
}
|
|
38546
38595
|
// 解析 JSONL 单行:仅当是主链 user 文本行(非 sidechain / 非 sub-agent / message.role='user'
|
|
@@ -39263,14 +39312,14 @@ async function authenticate(token, deps) {
|
|
|
39263
39312
|
}
|
|
39264
39313
|
|
|
39265
39314
|
// src/permission/capability-store.ts
|
|
39266
|
-
var
|
|
39267
|
-
var
|
|
39315
|
+
var fs22 = __toESM(require("fs"), 1);
|
|
39316
|
+
var path21 = __toESM(require("path"), 1);
|
|
39268
39317
|
var CAPABILITIES_FILE_NAME = "capabilities.json";
|
|
39269
39318
|
var FILE_VERSION = 1;
|
|
39270
39319
|
var CapabilityStore = class {
|
|
39271
39320
|
constructor(dataDir) {
|
|
39272
39321
|
this.dataDir = dataDir;
|
|
39273
|
-
|
|
39322
|
+
fs22.mkdirSync(dataDir, { recursive: true });
|
|
39274
39323
|
this.cache = this.readFromDisk();
|
|
39275
39324
|
}
|
|
39276
39325
|
dataDir;
|
|
@@ -39294,13 +39343,13 @@ var CapabilityStore = class {
|
|
|
39294
39343
|
this.flush();
|
|
39295
39344
|
}
|
|
39296
39345
|
filePath() {
|
|
39297
|
-
return
|
|
39346
|
+
return path21.join(this.dataDir, CAPABILITIES_FILE_NAME);
|
|
39298
39347
|
}
|
|
39299
39348
|
readFromDisk() {
|
|
39300
39349
|
const file = this.filePath();
|
|
39301
39350
|
let raw;
|
|
39302
39351
|
try {
|
|
39303
|
-
raw =
|
|
39352
|
+
raw = fs22.readFileSync(file, "utf8");
|
|
39304
39353
|
} catch (err) {
|
|
39305
39354
|
if (err?.code === "ENOENT") return [];
|
|
39306
39355
|
return [];
|
|
@@ -39328,10 +39377,10 @@ var CapabilityStore = class {
|
|
|
39328
39377
|
}
|
|
39329
39378
|
atomicWrite(file, content) {
|
|
39330
39379
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39331
|
-
|
|
39332
|
-
|
|
39380
|
+
fs22.writeFileSync(tmp, content, { mode: 384 });
|
|
39381
|
+
fs22.renameSync(tmp, file);
|
|
39333
39382
|
try {
|
|
39334
|
-
|
|
39383
|
+
fs22.chmodSync(file, 384);
|
|
39335
39384
|
} catch {
|
|
39336
39385
|
}
|
|
39337
39386
|
}
|
|
@@ -39424,14 +39473,14 @@ var CapabilityManager = class {
|
|
|
39424
39473
|
};
|
|
39425
39474
|
|
|
39426
39475
|
// src/permission/cleanup.ts
|
|
39427
|
-
var
|
|
39476
|
+
var fs23 = __toESM(require("fs"), 1);
|
|
39428
39477
|
function cleanupGuestSessionsForCapability(cap, factory) {
|
|
39429
39478
|
const removed = [];
|
|
39430
39479
|
for (const g2 of cap.grants) {
|
|
39431
39480
|
if (g2.resource.type !== "persona") continue;
|
|
39432
39481
|
const dir = factory.vmGuestRoot(g2.resource.id, cap.id);
|
|
39433
39482
|
try {
|
|
39434
|
-
|
|
39483
|
+
fs23.rmSync(dir, { recursive: true, force: true });
|
|
39435
39484
|
removed.push(dir);
|
|
39436
39485
|
} catch {
|
|
39437
39486
|
}
|
|
@@ -39440,13 +39489,13 @@ function cleanupGuestSessionsForCapability(cap, factory) {
|
|
|
39440
39489
|
}
|
|
39441
39490
|
|
|
39442
39491
|
// src/inbox/inbox-store.ts
|
|
39443
|
-
var
|
|
39444
|
-
var
|
|
39492
|
+
var fs24 = __toESM(require("fs"), 1);
|
|
39493
|
+
var path22 = __toESM(require("path"), 1);
|
|
39445
39494
|
var INBOX_SUBDIR = "inbox";
|
|
39446
39495
|
var InboxStore = class {
|
|
39447
39496
|
constructor(dataDir) {
|
|
39448
39497
|
this.dataDir = dataDir;
|
|
39449
|
-
|
|
39498
|
+
fs24.mkdirSync(this.dirPath(), { recursive: true });
|
|
39450
39499
|
}
|
|
39451
39500
|
dataDir;
|
|
39452
39501
|
/**
|
|
@@ -39458,7 +39507,7 @@ var InboxStore = class {
|
|
|
39458
39507
|
const file = this.filePath(peerDeviceId);
|
|
39459
39508
|
let raw;
|
|
39460
39509
|
try {
|
|
39461
|
-
raw =
|
|
39510
|
+
raw = fs24.readFileSync(file, "utf8");
|
|
39462
39511
|
} catch (err) {
|
|
39463
39512
|
if (err?.code === "ENOENT") return [];
|
|
39464
39513
|
return [];
|
|
@@ -39474,7 +39523,7 @@ var InboxStore = class {
|
|
|
39474
39523
|
const dir = this.dirPath();
|
|
39475
39524
|
let entries;
|
|
39476
39525
|
try {
|
|
39477
|
-
entries =
|
|
39526
|
+
entries = fs24.readdirSync(dir);
|
|
39478
39527
|
} catch (err) {
|
|
39479
39528
|
if (err?.code === "ENOENT") return [];
|
|
39480
39529
|
return [];
|
|
@@ -39490,9 +39539,9 @@ var InboxStore = class {
|
|
|
39490
39539
|
if (existing.some((m2) => m2.id === message.id)) return;
|
|
39491
39540
|
const file = this.filePath(message.peerDeviceId);
|
|
39492
39541
|
const line = JSON.stringify(message) + "\n";
|
|
39493
|
-
|
|
39542
|
+
fs24.appendFileSync(file, line, { mode: 384 });
|
|
39494
39543
|
try {
|
|
39495
|
-
|
|
39544
|
+
fs24.chmodSync(file, 384);
|
|
39496
39545
|
} catch {
|
|
39497
39546
|
}
|
|
39498
39547
|
}
|
|
@@ -39522,7 +39571,7 @@ var InboxStore = class {
|
|
|
39522
39571
|
removeByPeerDeviceId(peerDeviceId) {
|
|
39523
39572
|
const file = this.filePath(peerDeviceId);
|
|
39524
39573
|
try {
|
|
39525
|
-
|
|
39574
|
+
fs24.unlinkSync(file);
|
|
39526
39575
|
} catch (err) {
|
|
39527
39576
|
if (err?.code === "ENOENT") return;
|
|
39528
39577
|
}
|
|
@@ -39531,18 +39580,18 @@ var InboxStore = class {
|
|
|
39531
39580
|
const file = this.filePath(peerDeviceId);
|
|
39532
39581
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
39533
39582
|
const content = messages.map((m2) => JSON.stringify(m2)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
39534
|
-
|
|
39535
|
-
|
|
39583
|
+
fs24.writeFileSync(tmp, content, { mode: 384 });
|
|
39584
|
+
fs24.renameSync(tmp, file);
|
|
39536
39585
|
try {
|
|
39537
|
-
|
|
39586
|
+
fs24.chmodSync(file, 384);
|
|
39538
39587
|
} catch {
|
|
39539
39588
|
}
|
|
39540
39589
|
}
|
|
39541
39590
|
dirPath() {
|
|
39542
|
-
return
|
|
39591
|
+
return path22.join(this.dataDir, INBOX_SUBDIR);
|
|
39543
39592
|
}
|
|
39544
39593
|
filePath(peerDeviceId) {
|
|
39545
|
-
return
|
|
39594
|
+
return path22.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
39546
39595
|
}
|
|
39547
39596
|
};
|
|
39548
39597
|
function parseAllLines(raw) {
|
|
@@ -39629,8 +39678,8 @@ var InboxManager = class {
|
|
|
39629
39678
|
};
|
|
39630
39679
|
|
|
39631
39680
|
// src/state/contact-store.ts
|
|
39632
|
-
var
|
|
39633
|
-
var
|
|
39681
|
+
var fs25 = __toESM(require("fs"), 1);
|
|
39682
|
+
var path23 = __toESM(require("path"), 1);
|
|
39634
39683
|
var FILE_NAME = "contacts.json";
|
|
39635
39684
|
var ContactStore = class {
|
|
39636
39685
|
constructor(dataDir) {
|
|
@@ -39640,10 +39689,10 @@ var ContactStore = class {
|
|
|
39640
39689
|
contacts = /* @__PURE__ */ new Map();
|
|
39641
39690
|
load() {
|
|
39642
39691
|
this.contacts.clear();
|
|
39643
|
-
const file =
|
|
39692
|
+
const file = path23.join(this.dataDir, FILE_NAME);
|
|
39644
39693
|
let raw;
|
|
39645
39694
|
try {
|
|
39646
|
-
raw =
|
|
39695
|
+
raw = fs25.readFileSync(file, "utf8");
|
|
39647
39696
|
} catch (err) {
|
|
39648
39697
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
39649
39698
|
return;
|
|
@@ -39686,20 +39735,20 @@ var ContactStore = class {
|
|
|
39686
39735
|
return existed;
|
|
39687
39736
|
}
|
|
39688
39737
|
flush() {
|
|
39689
|
-
const file =
|
|
39738
|
+
const file = path23.join(this.dataDir, FILE_NAME);
|
|
39690
39739
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
39691
39740
|
const content = JSON.stringify(
|
|
39692
39741
|
{ contacts: Array.from(this.contacts.values()) },
|
|
39693
39742
|
null,
|
|
39694
39743
|
2
|
|
39695
39744
|
);
|
|
39696
|
-
|
|
39697
|
-
|
|
39698
|
-
|
|
39745
|
+
fs25.mkdirSync(this.dataDir, { recursive: true });
|
|
39746
|
+
fs25.writeFileSync(tmp, content, { mode: 384 });
|
|
39747
|
+
fs25.renameSync(tmp, file);
|
|
39699
39748
|
}
|
|
39700
39749
|
renameBak(file) {
|
|
39701
39750
|
try {
|
|
39702
|
-
|
|
39751
|
+
fs25.renameSync(file, `${file}.bak`);
|
|
39703
39752
|
} catch {
|
|
39704
39753
|
}
|
|
39705
39754
|
}
|
|
@@ -39849,61 +39898,61 @@ async function autoReverseContact(args) {
|
|
|
39849
39898
|
}
|
|
39850
39899
|
|
|
39851
39900
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
39852
|
-
var
|
|
39853
|
-
var
|
|
39901
|
+
var fs26 = __toESM(require("fs"), 1);
|
|
39902
|
+
var path24 = __toESM(require("path"), 1);
|
|
39854
39903
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
39855
39904
|
function migrateFlattenSessions(opts) {
|
|
39856
39905
|
const dataDir = opts.dataDir;
|
|
39857
39906
|
const now = opts.now ?? Date.now;
|
|
39858
|
-
const sessionsDir =
|
|
39859
|
-
const flagPath =
|
|
39907
|
+
const sessionsDir = path24.join(dataDir, "sessions");
|
|
39908
|
+
const flagPath = path24.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
39860
39909
|
if (existsSync3(flagPath)) {
|
|
39861
39910
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
39862
39911
|
}
|
|
39863
39912
|
let movedBare = 0;
|
|
39864
39913
|
let movedVmOwner = 0;
|
|
39865
39914
|
let archivedListener = 0;
|
|
39866
|
-
const defaultDir =
|
|
39915
|
+
const defaultDir = path24.join(sessionsDir, "default");
|
|
39867
39916
|
if (existsSync3(defaultDir)) {
|
|
39868
39917
|
for (const entry of readdirSafe(defaultDir)) {
|
|
39869
39918
|
if (!entry.endsWith(".json")) continue;
|
|
39870
|
-
const src =
|
|
39871
|
-
const dst =
|
|
39872
|
-
|
|
39919
|
+
const src = path24.join(defaultDir, entry);
|
|
39920
|
+
const dst = path24.join(sessionsDir, entry);
|
|
39921
|
+
fs26.renameSync(src, dst);
|
|
39873
39922
|
movedBare += 1;
|
|
39874
39923
|
}
|
|
39875
39924
|
rmdirIfEmpty(defaultDir);
|
|
39876
39925
|
}
|
|
39877
39926
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
39878
|
-
const personaDir =
|
|
39927
|
+
const personaDir = path24.join(sessionsDir, pid);
|
|
39879
39928
|
if (!isDir(personaDir)) continue;
|
|
39880
39929
|
if (pid === "default") continue;
|
|
39881
|
-
const ownerSrc =
|
|
39930
|
+
const ownerSrc = path24.join(personaDir, "owner");
|
|
39882
39931
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
39883
|
-
const ownerDst =
|
|
39884
|
-
|
|
39932
|
+
const ownerDst = path24.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
39933
|
+
fs26.mkdirSync(ownerDst, { recursive: true });
|
|
39885
39934
|
for (const file of readdirSafe(ownerSrc)) {
|
|
39886
39935
|
if (!file.endsWith(".json")) continue;
|
|
39887
|
-
|
|
39936
|
+
fs26.renameSync(path24.join(ownerSrc, file), path24.join(ownerDst, file));
|
|
39888
39937
|
movedVmOwner += 1;
|
|
39889
39938
|
}
|
|
39890
39939
|
rmdirIfEmpty(ownerSrc);
|
|
39891
39940
|
}
|
|
39892
|
-
const listenerSrc =
|
|
39941
|
+
const listenerSrc = path24.join(personaDir, "listener");
|
|
39893
39942
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
39894
|
-
const archiveDst =
|
|
39895
|
-
|
|
39943
|
+
const archiveDst = path24.join(dataDir, ".legacy", `listener-${pid}`);
|
|
39944
|
+
fs26.mkdirSync(archiveDst, { recursive: true });
|
|
39896
39945
|
for (const file of readdirSafe(listenerSrc)) {
|
|
39897
39946
|
if (!file.endsWith(".json")) continue;
|
|
39898
|
-
|
|
39947
|
+
fs26.renameSync(path24.join(listenerSrc, file), path24.join(archiveDst, file));
|
|
39899
39948
|
archivedListener += 1;
|
|
39900
39949
|
}
|
|
39901
39950
|
rmdirIfEmpty(listenerSrc);
|
|
39902
39951
|
}
|
|
39903
39952
|
rmdirIfEmpty(personaDir);
|
|
39904
39953
|
}
|
|
39905
|
-
|
|
39906
|
-
|
|
39954
|
+
fs26.mkdirSync(sessionsDir, { recursive: true });
|
|
39955
|
+
fs26.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
39907
39956
|
return {
|
|
39908
39957
|
skipped: false,
|
|
39909
39958
|
flagWritten: true,
|
|
@@ -39914,7 +39963,7 @@ function migrateFlattenSessions(opts) {
|
|
|
39914
39963
|
}
|
|
39915
39964
|
function existsSync3(p2) {
|
|
39916
39965
|
try {
|
|
39917
|
-
|
|
39966
|
+
fs26.statSync(p2);
|
|
39918
39967
|
return true;
|
|
39919
39968
|
} catch {
|
|
39920
39969
|
return false;
|
|
@@ -39922,31 +39971,31 @@ function existsSync3(p2) {
|
|
|
39922
39971
|
}
|
|
39923
39972
|
function isDir(p2) {
|
|
39924
39973
|
try {
|
|
39925
|
-
return
|
|
39974
|
+
return fs26.statSync(p2).isDirectory();
|
|
39926
39975
|
} catch {
|
|
39927
39976
|
return false;
|
|
39928
39977
|
}
|
|
39929
39978
|
}
|
|
39930
39979
|
function readdirSafe(p2) {
|
|
39931
39980
|
try {
|
|
39932
|
-
return
|
|
39981
|
+
return fs26.readdirSync(p2);
|
|
39933
39982
|
} catch {
|
|
39934
39983
|
return [];
|
|
39935
39984
|
}
|
|
39936
39985
|
}
|
|
39937
39986
|
function rmdirIfEmpty(p2) {
|
|
39938
39987
|
try {
|
|
39939
|
-
|
|
39988
|
+
fs26.rmdirSync(p2);
|
|
39940
39989
|
} catch {
|
|
39941
39990
|
}
|
|
39942
39991
|
}
|
|
39943
39992
|
|
|
39944
39993
|
// src/transport/http-router.ts
|
|
39945
|
-
var
|
|
39946
|
-
var
|
|
39994
|
+
var import_node_fs21 = __toESM(require("fs"), 1);
|
|
39995
|
+
var import_node_path20 = __toESM(require("path"), 1);
|
|
39947
39996
|
|
|
39948
39997
|
// src/attachment/mime.ts
|
|
39949
|
-
var
|
|
39998
|
+
var import_node_path17 = __toESM(require("path"), 1);
|
|
39950
39999
|
var TEXT_PLAIN = "text/plain; charset=utf-8";
|
|
39951
40000
|
var EXT_TO_NATIVE_MIME = {
|
|
39952
40001
|
// 图片
|
|
@@ -40053,7 +40102,7 @@ var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
40053
40102
|
".mk"
|
|
40054
40103
|
]);
|
|
40055
40104
|
function lookupMime(filePathOrName) {
|
|
40056
|
-
const ext =
|
|
40105
|
+
const ext = import_node_path17.default.extname(filePathOrName).toLowerCase();
|
|
40057
40106
|
if (EXT_TO_NATIVE_MIME[ext]) return EXT_TO_NATIVE_MIME[ext];
|
|
40058
40107
|
if (TEXT_EXTENSIONS.has(ext)) return TEXT_PLAIN;
|
|
40059
40108
|
return "application/octet-stream";
|
|
@@ -40122,8 +40171,8 @@ function verifySignedUrl(secret, absPath, eRaw, s, now = Date.now) {
|
|
|
40122
40171
|
}
|
|
40123
40172
|
|
|
40124
40173
|
// src/attachment/upload.ts
|
|
40125
|
-
var
|
|
40126
|
-
var
|
|
40174
|
+
var import_node_fs20 = __toESM(require("fs"), 1);
|
|
40175
|
+
var import_node_path18 = __toESM(require("path"), 1);
|
|
40127
40176
|
var import_node_crypto5 = __toESM(require("crypto"), 1);
|
|
40128
40177
|
var import_promises = require("stream/promises");
|
|
40129
40178
|
var UploadError = class extends Error {
|
|
@@ -40135,22 +40184,22 @@ var UploadError = class extends Error {
|
|
|
40135
40184
|
code;
|
|
40136
40185
|
};
|
|
40137
40186
|
function assertValidFileName(fileName) {
|
|
40138
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
40187
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path18.default.basename(fileName)) {
|
|
40139
40188
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
40140
40189
|
}
|
|
40141
40190
|
}
|
|
40142
40191
|
var HASH_PREFIX_LEN = 16;
|
|
40143
40192
|
async function writeUploadedAttachment(args) {
|
|
40144
40193
|
assertValidFileName(args.fileName);
|
|
40145
|
-
const attachmentsRoot =
|
|
40194
|
+
const attachmentsRoot = import_node_path18.default.join(args.sessionDir, ".attachments");
|
|
40146
40195
|
try {
|
|
40147
|
-
|
|
40196
|
+
import_node_fs20.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
40148
40197
|
} catch (err) {
|
|
40149
40198
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
40150
40199
|
}
|
|
40151
40200
|
const hasher = import_node_crypto5.default.createHash("sha256");
|
|
40152
40201
|
let actualSize = 0;
|
|
40153
|
-
const tmpPath =
|
|
40202
|
+
const tmpPath = import_node_path18.default.join(
|
|
40154
40203
|
attachmentsRoot,
|
|
40155
40204
|
`.upload-${process.pid}-${Date.now()}-${import_node_crypto5.default.randomBytes(4).toString("hex")}`
|
|
40156
40205
|
);
|
|
@@ -40165,18 +40214,18 @@ async function writeUploadedAttachment(args) {
|
|
|
40165
40214
|
yield buf;
|
|
40166
40215
|
}
|
|
40167
40216
|
},
|
|
40168
|
-
|
|
40217
|
+
import_node_fs20.default.createWriteStream(tmpPath, { mode: 384 })
|
|
40169
40218
|
);
|
|
40170
40219
|
} catch (err) {
|
|
40171
40220
|
try {
|
|
40172
|
-
|
|
40221
|
+
import_node_fs20.default.unlinkSync(tmpPath);
|
|
40173
40222
|
} catch {
|
|
40174
40223
|
}
|
|
40175
40224
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
40176
40225
|
}
|
|
40177
40226
|
if (actualSize !== args.contentLength) {
|
|
40178
40227
|
try {
|
|
40179
|
-
|
|
40228
|
+
import_node_fs20.default.unlinkSync(tmpPath);
|
|
40180
40229
|
} catch {
|
|
40181
40230
|
}
|
|
40182
40231
|
throw new UploadError(
|
|
@@ -40185,35 +40234,35 @@ async function writeUploadedAttachment(args) {
|
|
|
40185
40234
|
);
|
|
40186
40235
|
}
|
|
40187
40236
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
40188
|
-
const hashDir =
|
|
40237
|
+
const hashDir = import_node_path18.default.join(attachmentsRoot, attachmentId);
|
|
40189
40238
|
let finalFileName;
|
|
40190
40239
|
let hashDirExists = false;
|
|
40191
40240
|
try {
|
|
40192
|
-
hashDirExists =
|
|
40241
|
+
hashDirExists = import_node_fs20.default.statSync(hashDir).isDirectory();
|
|
40193
40242
|
} catch {
|
|
40194
40243
|
}
|
|
40195
40244
|
if (hashDirExists) {
|
|
40196
|
-
const existing =
|
|
40245
|
+
const existing = import_node_fs20.default.readdirSync(hashDir).filter((n) => !n.startsWith("."));
|
|
40197
40246
|
finalFileName = existing[0] ?? args.fileName;
|
|
40198
40247
|
try {
|
|
40199
|
-
|
|
40248
|
+
import_node_fs20.default.unlinkSync(tmpPath);
|
|
40200
40249
|
} catch {
|
|
40201
40250
|
}
|
|
40202
40251
|
} else {
|
|
40203
40252
|
try {
|
|
40204
|
-
|
|
40253
|
+
import_node_fs20.default.mkdirSync(hashDir, { recursive: true });
|
|
40205
40254
|
finalFileName = args.fileName;
|
|
40206
|
-
|
|
40255
|
+
import_node_fs20.default.renameSync(tmpPath, import_node_path18.default.join(hashDir, finalFileName));
|
|
40207
40256
|
} catch (err) {
|
|
40208
40257
|
try {
|
|
40209
|
-
|
|
40258
|
+
import_node_fs20.default.unlinkSync(tmpPath);
|
|
40210
40259
|
} catch {
|
|
40211
40260
|
}
|
|
40212
40261
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
40213
40262
|
}
|
|
40214
40263
|
}
|
|
40215
|
-
const absPath =
|
|
40216
|
-
const relPath =
|
|
40264
|
+
const absPath = import_node_path18.default.join(hashDir, finalFileName);
|
|
40265
|
+
const relPath = import_node_path18.default.relative(args.sessionDir, absPath);
|
|
40217
40266
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
40218
40267
|
relPath: absPath,
|
|
40219
40268
|
// 存绝对路径,与现有 agent 入清单的形态一致(attachment.ts:144 双形态兼容)
|
|
@@ -40227,7 +40276,7 @@ async function writeUploadedAttachment(args) {
|
|
|
40227
40276
|
|
|
40228
40277
|
// src/extension/import.ts
|
|
40229
40278
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
40230
|
-
var
|
|
40279
|
+
var import_node_path19 = __toESM(require("path"), 1);
|
|
40231
40280
|
var import_node_os11 = __toESM(require("os"), 1);
|
|
40232
40281
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
40233
40282
|
var ImportError = class extends Error {
|
|
@@ -40245,7 +40294,7 @@ async function importZip(buf, root) {
|
|
|
40245
40294
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
40246
40295
|
}
|
|
40247
40296
|
for (const name of Object.keys(zip.files)) {
|
|
40248
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
40297
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path19.default.isAbsolute(name)) {
|
|
40249
40298
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
40250
40299
|
}
|
|
40251
40300
|
}
|
|
@@ -40278,7 +40327,7 @@ async function importZip(buf, root) {
|
|
|
40278
40327
|
);
|
|
40279
40328
|
}
|
|
40280
40329
|
}
|
|
40281
|
-
const destDir =
|
|
40330
|
+
const destDir = import_node_path19.default.join(root, manifest.id);
|
|
40282
40331
|
let destExists = false;
|
|
40283
40332
|
try {
|
|
40284
40333
|
await import_promises2.default.access(destDir);
|
|
@@ -40288,15 +40337,15 @@ async function importZip(buf, root) {
|
|
|
40288
40337
|
if (destExists) {
|
|
40289
40338
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
40290
40339
|
}
|
|
40291
|
-
const stage = await import_promises2.default.mkdtemp(
|
|
40340
|
+
const stage = await import_promises2.default.mkdtemp(import_node_path19.default.join(import_node_os11.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
40292
40341
|
try {
|
|
40293
40342
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
40294
|
-
const dest =
|
|
40343
|
+
const dest = import_node_path19.default.join(stage, name);
|
|
40295
40344
|
if (entry.dir) {
|
|
40296
40345
|
await import_promises2.default.mkdir(dest, { recursive: true });
|
|
40297
40346
|
continue;
|
|
40298
40347
|
}
|
|
40299
|
-
await import_promises2.default.mkdir(
|
|
40348
|
+
await import_promises2.default.mkdir(import_node_path19.default.dirname(dest), { recursive: true });
|
|
40300
40349
|
const content = await entry.async("nodebuffer");
|
|
40301
40350
|
await import_promises2.default.writeFile(dest, content);
|
|
40302
40351
|
}
|
|
@@ -40418,7 +40467,7 @@ function isValidUploadFileName(fileName) {
|
|
|
40418
40467
|
if (fileName === "." || fileName === "..") return false;
|
|
40419
40468
|
if (fileName.startsWith(".")) return false;
|
|
40420
40469
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
40421
|
-
return fileName ===
|
|
40470
|
+
return fileName === import_node_path20.default.basename(fileName);
|
|
40422
40471
|
}
|
|
40423
40472
|
function createHttpRouter(deps) {
|
|
40424
40473
|
return async (req, res) => {
|
|
@@ -40567,7 +40616,7 @@ function createHttpRouter(deps) {
|
|
|
40567
40616
|
sendHtml(res, statusByCode[r.code], loader.renderErrorHtml(r.code, msgByCode[r.code]));
|
|
40568
40617
|
return true;
|
|
40569
40618
|
}
|
|
40570
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
40619
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path20.default.basename(r.absPath)));
|
|
40571
40620
|
return true;
|
|
40572
40621
|
}
|
|
40573
40622
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -40688,7 +40737,7 @@ function createHttpRouter(deps) {
|
|
|
40688
40737
|
return true;
|
|
40689
40738
|
}
|
|
40690
40739
|
let absPath;
|
|
40691
|
-
if (
|
|
40740
|
+
if (import_node_path20.default.isAbsolute(pathParam)) {
|
|
40692
40741
|
absPath = pathParam;
|
|
40693
40742
|
} else if (deps.sessionStore) {
|
|
40694
40743
|
const file = deps.sessionStore.read(sid);
|
|
@@ -40696,7 +40745,7 @@ function createHttpRouter(deps) {
|
|
|
40696
40745
|
sendJson(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
40697
40746
|
return true;
|
|
40698
40747
|
}
|
|
40699
|
-
absPath =
|
|
40748
|
+
absPath = import_node_path20.default.join(file.cwd, pathParam);
|
|
40700
40749
|
} else {
|
|
40701
40750
|
sendJson(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
40702
40751
|
return true;
|
|
@@ -40783,7 +40832,7 @@ function withCtx(ctx, body) {
|
|
|
40783
40832
|
function streamFile(res, absPath, logger) {
|
|
40784
40833
|
let stat;
|
|
40785
40834
|
try {
|
|
40786
|
-
stat =
|
|
40835
|
+
stat = import_node_fs21.default.statSync(absPath);
|
|
40787
40836
|
} catch (err) {
|
|
40788
40837
|
const code = err?.code;
|
|
40789
40838
|
if (code === "ENOENT") {
|
|
@@ -40798,7 +40847,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40798
40847
|
return;
|
|
40799
40848
|
}
|
|
40800
40849
|
const mime = lookupMime(absPath);
|
|
40801
|
-
const basename =
|
|
40850
|
+
const basename = import_node_path20.default.basename(absPath);
|
|
40802
40851
|
res.writeHead(200, {
|
|
40803
40852
|
"Content-Type": mime,
|
|
40804
40853
|
"Content-Length": String(stat.size),
|
|
@@ -40806,7 +40855,7 @@ function streamFile(res, absPath, logger) {
|
|
|
40806
40855
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
40807
40856
|
"X-Content-Type-Options": "nosniff"
|
|
40808
40857
|
});
|
|
40809
|
-
const stream =
|
|
40858
|
+
const stream = import_node_fs21.default.createReadStream(absPath);
|
|
40810
40859
|
stream.on("error", (err) => {
|
|
40811
40860
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
40812
40861
|
res.destroy();
|
|
@@ -40815,8 +40864,8 @@ function streamFile(res, absPath, logger) {
|
|
|
40815
40864
|
}
|
|
40816
40865
|
|
|
40817
40866
|
// src/attachment/gc.ts
|
|
40818
|
-
var
|
|
40819
|
-
var
|
|
40867
|
+
var import_node_fs22 = __toESM(require("fs"), 1);
|
|
40868
|
+
var import_node_path21 = __toESM(require("path"), 1);
|
|
40820
40869
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
40821
40870
|
function runAttachmentGc(args) {
|
|
40822
40871
|
const now = (args.now ?? Date.now)();
|
|
@@ -40825,38 +40874,38 @@ function runAttachmentGc(args) {
|
|
|
40825
40874
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40826
40875
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
40827
40876
|
if (entry.stale) continue;
|
|
40828
|
-
if (
|
|
40877
|
+
if (import_node_path21.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
40829
40878
|
}
|
|
40830
40879
|
}
|
|
40831
40880
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
40832
|
-
const sessionDir = args.getSessionCwd?.(sessionId) ??
|
|
40881
|
+
const sessionDir = args.getSessionCwd?.(sessionId) ?? import_node_path21.default.join(
|
|
40833
40882
|
args.dataDir,
|
|
40834
40883
|
"sessions",
|
|
40835
40884
|
...scopeSubPath(scope).map(safeFileName),
|
|
40836
40885
|
safeFileName(sessionId)
|
|
40837
40886
|
);
|
|
40838
|
-
const attRoot =
|
|
40887
|
+
const attRoot = import_node_path21.default.join(sessionDir, ".attachments");
|
|
40839
40888
|
let hashDirs;
|
|
40840
40889
|
try {
|
|
40841
|
-
hashDirs =
|
|
40890
|
+
hashDirs = import_node_fs22.default.readdirSync(attRoot);
|
|
40842
40891
|
} catch (err) {
|
|
40843
40892
|
if (err.code === "ENOENT") continue;
|
|
40844
40893
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
40845
40894
|
continue;
|
|
40846
40895
|
}
|
|
40847
40896
|
for (const hashDir of hashDirs) {
|
|
40848
|
-
const hashDirAbs =
|
|
40897
|
+
const hashDirAbs = import_node_path21.default.join(attRoot, hashDir);
|
|
40849
40898
|
let files;
|
|
40850
40899
|
try {
|
|
40851
|
-
files =
|
|
40900
|
+
files = import_node_fs22.default.readdirSync(hashDirAbs);
|
|
40852
40901
|
} catch {
|
|
40853
40902
|
continue;
|
|
40854
40903
|
}
|
|
40855
40904
|
for (const name of files) {
|
|
40856
|
-
const file =
|
|
40905
|
+
const file = import_node_path21.default.join(hashDirAbs, name);
|
|
40857
40906
|
let stat;
|
|
40858
40907
|
try {
|
|
40859
|
-
stat =
|
|
40908
|
+
stat = import_node_fs22.default.statSync(file);
|
|
40860
40909
|
} catch {
|
|
40861
40910
|
continue;
|
|
40862
40911
|
}
|
|
@@ -40865,26 +40914,26 @@ function runAttachmentGc(args) {
|
|
|
40865
40914
|
if (age < ttlMs) continue;
|
|
40866
40915
|
if (liveAbs.has(file)) continue;
|
|
40867
40916
|
try {
|
|
40868
|
-
|
|
40917
|
+
import_node_fs22.default.unlinkSync(file);
|
|
40869
40918
|
} catch (err) {
|
|
40870
40919
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
40871
40920
|
}
|
|
40872
40921
|
}
|
|
40873
40922
|
try {
|
|
40874
|
-
if (
|
|
40923
|
+
if (import_node_fs22.default.readdirSync(hashDirAbs).length === 0) import_node_fs22.default.rmdirSync(hashDirAbs);
|
|
40875
40924
|
} catch {
|
|
40876
40925
|
}
|
|
40877
40926
|
}
|
|
40878
40927
|
try {
|
|
40879
|
-
if (
|
|
40928
|
+
if (import_node_fs22.default.readdirSync(attRoot).length === 0) import_node_fs22.default.rmdirSync(attRoot);
|
|
40880
40929
|
} catch {
|
|
40881
40930
|
}
|
|
40882
40931
|
}
|
|
40883
40932
|
}
|
|
40884
40933
|
|
|
40885
40934
|
// src/attachment/group.ts
|
|
40886
|
-
var
|
|
40887
|
-
var
|
|
40935
|
+
var import_node_fs23 = __toESM(require("fs"), 1);
|
|
40936
|
+
var import_node_path22 = __toESM(require("path"), 1);
|
|
40888
40937
|
var import_node_crypto6 = __toESM(require("crypto"), 1);
|
|
40889
40938
|
init_protocol();
|
|
40890
40939
|
var GroupFileStore = class {
|
|
@@ -40896,11 +40945,11 @@ var GroupFileStore = class {
|
|
|
40896
40945
|
this.logger = opts.logger;
|
|
40897
40946
|
}
|
|
40898
40947
|
rootForScope(scope) {
|
|
40899
|
-
return
|
|
40948
|
+
return import_node_path22.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
40900
40949
|
}
|
|
40901
40950
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
40902
40951
|
filePath(scope, sessionId) {
|
|
40903
|
-
return
|
|
40952
|
+
return import_node_path22.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
40904
40953
|
}
|
|
40905
40954
|
cacheKey(scope, sessionId) {
|
|
40906
40955
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -40909,7 +40958,7 @@ var GroupFileStore = class {
|
|
|
40909
40958
|
readFile(scope, sessionId) {
|
|
40910
40959
|
const file = this.filePath(scope, sessionId);
|
|
40911
40960
|
try {
|
|
40912
|
-
const raw =
|
|
40961
|
+
const raw = import_node_fs23.default.readFileSync(file, "utf8");
|
|
40913
40962
|
const parsed = JSON.parse(raw);
|
|
40914
40963
|
if (!Array.isArray(parsed)) {
|
|
40915
40964
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -40935,10 +40984,10 @@ var GroupFileStore = class {
|
|
|
40935
40984
|
}
|
|
40936
40985
|
writeFile(scope, sessionId, entries) {
|
|
40937
40986
|
const file = this.filePath(scope, sessionId);
|
|
40938
|
-
|
|
40987
|
+
import_node_fs23.default.mkdirSync(import_node_path22.default.dirname(file), { recursive: true });
|
|
40939
40988
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
40940
|
-
|
|
40941
|
-
|
|
40989
|
+
import_node_fs23.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
40990
|
+
import_node_fs23.default.renameSync(tmp, file);
|
|
40942
40991
|
}
|
|
40943
40992
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
40944
40993
|
list(scope, sessionId) {
|
|
@@ -41024,10 +41073,10 @@ var GroupFileStore = class {
|
|
|
41024
41073
|
};
|
|
41025
41074
|
|
|
41026
41075
|
// src/discovery/state-file.ts
|
|
41027
|
-
var
|
|
41028
|
-
var
|
|
41076
|
+
var import_node_fs24 = __toESM(require("fs"), 1);
|
|
41077
|
+
var import_node_path23 = __toESM(require("path"), 1);
|
|
41029
41078
|
function defaultStateFilePath(dataDir) {
|
|
41030
|
-
return
|
|
41079
|
+
return import_node_path23.default.join(dataDir, "state.json");
|
|
41031
41080
|
}
|
|
41032
41081
|
function isPidAlive(pid) {
|
|
41033
41082
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -41049,7 +41098,7 @@ var StateFileManager = class {
|
|
|
41049
41098
|
}
|
|
41050
41099
|
read() {
|
|
41051
41100
|
try {
|
|
41052
|
-
const raw =
|
|
41101
|
+
const raw = import_node_fs24.default.readFileSync(this.file, "utf8");
|
|
41053
41102
|
const parsed = JSON.parse(raw);
|
|
41054
41103
|
return parsed;
|
|
41055
41104
|
} catch {
|
|
@@ -41063,20 +41112,20 @@ var StateFileManager = class {
|
|
|
41063
41112
|
return { status: "stale", existing };
|
|
41064
41113
|
}
|
|
41065
41114
|
write(state) {
|
|
41066
|
-
|
|
41115
|
+
import_node_fs24.default.mkdirSync(import_node_path23.default.dirname(this.file), { recursive: true });
|
|
41067
41116
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
41068
|
-
|
|
41069
|
-
|
|
41117
|
+
import_node_fs24.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
41118
|
+
import_node_fs24.default.renameSync(tmp, this.file);
|
|
41070
41119
|
if (process.platform !== "win32") {
|
|
41071
41120
|
try {
|
|
41072
|
-
|
|
41121
|
+
import_node_fs24.default.chmodSync(this.file, 384);
|
|
41073
41122
|
} catch {
|
|
41074
41123
|
}
|
|
41075
41124
|
}
|
|
41076
41125
|
}
|
|
41077
41126
|
delete() {
|
|
41078
41127
|
try {
|
|
41079
|
-
|
|
41128
|
+
import_node_fs24.default.unlinkSync(this.file);
|
|
41080
41129
|
} catch {
|
|
41081
41130
|
}
|
|
41082
41131
|
}
|
|
@@ -41091,14 +41140,14 @@ function readDaemonSourceFromEnv(env = process.env) {
|
|
|
41091
41140
|
}
|
|
41092
41141
|
|
|
41093
41142
|
// src/tunnel/tunnel-manager.ts
|
|
41094
|
-
var
|
|
41095
|
-
var
|
|
41143
|
+
var import_node_fs28 = __toESM(require("fs"), 1);
|
|
41144
|
+
var import_node_path27 = __toESM(require("path"), 1);
|
|
41096
41145
|
var import_node_crypto7 = __toESM(require("crypto"), 1);
|
|
41097
41146
|
var import_node_child_process9 = require("child_process");
|
|
41098
41147
|
|
|
41099
41148
|
// src/tunnel/tunnel-store.ts
|
|
41100
|
-
var
|
|
41101
|
-
var
|
|
41149
|
+
var import_node_fs25 = __toESM(require("fs"), 1);
|
|
41150
|
+
var import_node_path24 = __toESM(require("path"), 1);
|
|
41102
41151
|
var TunnelStore = class {
|
|
41103
41152
|
constructor(filePath) {
|
|
41104
41153
|
this.filePath = filePath;
|
|
@@ -41106,7 +41155,7 @@ var TunnelStore = class {
|
|
|
41106
41155
|
filePath;
|
|
41107
41156
|
async get() {
|
|
41108
41157
|
try {
|
|
41109
|
-
const raw = await
|
|
41158
|
+
const raw = await import_node_fs25.default.promises.readFile(this.filePath, "utf8");
|
|
41110
41159
|
const obj = JSON.parse(raw);
|
|
41111
41160
|
if (!isPersistedTunnel(obj)) return null;
|
|
41112
41161
|
return obj;
|
|
@@ -41117,22 +41166,22 @@ var TunnelStore = class {
|
|
|
41117
41166
|
}
|
|
41118
41167
|
}
|
|
41119
41168
|
async set(v2) {
|
|
41120
|
-
const dir =
|
|
41121
|
-
await
|
|
41169
|
+
const dir = import_node_path24.default.dirname(this.filePath);
|
|
41170
|
+
await import_node_fs25.default.promises.mkdir(dir, { recursive: true });
|
|
41122
41171
|
const data = JSON.stringify(v2, null, 2);
|
|
41123
41172
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
41124
|
-
await
|
|
41173
|
+
await import_node_fs25.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
41125
41174
|
if (process.platform !== "win32") {
|
|
41126
41175
|
try {
|
|
41127
|
-
await
|
|
41176
|
+
await import_node_fs25.default.promises.chmod(tmp, 384);
|
|
41128
41177
|
} catch {
|
|
41129
41178
|
}
|
|
41130
41179
|
}
|
|
41131
|
-
await
|
|
41180
|
+
await import_node_fs25.default.promises.rename(tmp, this.filePath);
|
|
41132
41181
|
}
|
|
41133
41182
|
async clear() {
|
|
41134
41183
|
try {
|
|
41135
|
-
await
|
|
41184
|
+
await import_node_fs25.default.promises.unlink(this.filePath);
|
|
41136
41185
|
} catch (err) {
|
|
41137
41186
|
const code = err?.code;
|
|
41138
41187
|
if (code !== "ENOENT") throw err;
|
|
@@ -41227,9 +41276,9 @@ function escape(v2) {
|
|
|
41227
41276
|
}
|
|
41228
41277
|
|
|
41229
41278
|
// src/tunnel/frpc-binary.ts
|
|
41230
|
-
var
|
|
41279
|
+
var import_node_fs26 = __toESM(require("fs"), 1);
|
|
41231
41280
|
var import_node_os12 = __toESM(require("os"), 1);
|
|
41232
|
-
var
|
|
41281
|
+
var import_node_path25 = __toESM(require("path"), 1);
|
|
41233
41282
|
var import_node_child_process7 = require("child_process");
|
|
41234
41283
|
var import_node_stream3 = require("stream");
|
|
41235
41284
|
var import_promises3 = require("stream/promises");
|
|
@@ -41261,20 +41310,20 @@ function frpcDownloadUrl(version2, p2) {
|
|
|
41261
41310
|
}
|
|
41262
41311
|
async function ensureFrpcBinary(opts) {
|
|
41263
41312
|
if (opts.override) {
|
|
41264
|
-
if (!
|
|
41313
|
+
if (!import_node_fs26.default.existsSync(opts.override)) {
|
|
41265
41314
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
41266
41315
|
}
|
|
41267
41316
|
return opts.override;
|
|
41268
41317
|
}
|
|
41269
41318
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
41270
41319
|
const platform = opts.platform ?? detectPlatform();
|
|
41271
|
-
const binDir =
|
|
41272
|
-
|
|
41320
|
+
const binDir = import_node_path25.default.join(opts.dataDir, "bin");
|
|
41321
|
+
import_node_fs26.default.mkdirSync(binDir, { recursive: true });
|
|
41273
41322
|
cleanupStaleArtifacts(binDir);
|
|
41274
|
-
const stableBin =
|
|
41275
|
-
if (
|
|
41323
|
+
const stableBin = import_node_path25.default.join(binDir, "frpc");
|
|
41324
|
+
if (import_node_fs26.default.existsSync(stableBin)) return stableBin;
|
|
41276
41325
|
const partialBin = `${stableBin}.partial`;
|
|
41277
|
-
const tarballPath =
|
|
41326
|
+
const tarballPath = import_node_path25.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
41278
41327
|
try {
|
|
41279
41328
|
const url = frpcDownloadUrl(version2, platform);
|
|
41280
41329
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -41283,8 +41332,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
41283
41332
|
} else {
|
|
41284
41333
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
41285
41334
|
}
|
|
41286
|
-
|
|
41287
|
-
|
|
41335
|
+
import_node_fs26.default.chmodSync(partialBin, 493);
|
|
41336
|
+
import_node_fs26.default.renameSync(partialBin, stableBin);
|
|
41288
41337
|
} finally {
|
|
41289
41338
|
safeUnlink(tarballPath);
|
|
41290
41339
|
safeUnlink(partialBin);
|
|
@@ -41294,15 +41343,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
41294
41343
|
function cleanupStaleArtifacts(binDir) {
|
|
41295
41344
|
let entries;
|
|
41296
41345
|
try {
|
|
41297
|
-
entries =
|
|
41346
|
+
entries = import_node_fs26.default.readdirSync(binDir);
|
|
41298
41347
|
} catch {
|
|
41299
41348
|
return;
|
|
41300
41349
|
}
|
|
41301
41350
|
for (const name of entries) {
|
|
41302
41351
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
41303
|
-
const full =
|
|
41352
|
+
const full = import_node_path25.default.join(binDir, name);
|
|
41304
41353
|
try {
|
|
41305
|
-
|
|
41354
|
+
import_node_fs26.default.rmSync(full, { recursive: true, force: true });
|
|
41306
41355
|
} catch {
|
|
41307
41356
|
}
|
|
41308
41357
|
}
|
|
@@ -41310,7 +41359,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
41310
41359
|
}
|
|
41311
41360
|
function safeUnlink(p2) {
|
|
41312
41361
|
try {
|
|
41313
|
-
|
|
41362
|
+
import_node_fs26.default.unlinkSync(p2);
|
|
41314
41363
|
} catch {
|
|
41315
41364
|
}
|
|
41316
41365
|
}
|
|
@@ -41321,13 +41370,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
41321
41370
|
if (!res.ok || !res.body) {
|
|
41322
41371
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
41323
41372
|
}
|
|
41324
|
-
const out =
|
|
41373
|
+
const out = import_node_fs26.default.createWriteStream(dest);
|
|
41325
41374
|
const nodeStream = import_node_stream3.Readable.fromWeb(res.body);
|
|
41326
41375
|
await (0, import_promises3.pipeline)(nodeStream, out);
|
|
41327
41376
|
}
|
|
41328
41377
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
41329
|
-
const work =
|
|
41330
|
-
|
|
41378
|
+
const work = import_node_path25.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
41379
|
+
import_node_fs26.default.mkdirSync(work, { recursive: true });
|
|
41331
41380
|
try {
|
|
41332
41381
|
await new Promise((resolve6, reject) => {
|
|
41333
41382
|
const proc = (0, import_node_child_process7.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -41335,32 +41384,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
41335
41384
|
proc.on("exit", (code) => code === 0 ? resolve6() : reject(new Error(`tar exited ${code}`)));
|
|
41336
41385
|
});
|
|
41337
41386
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
41338
|
-
const src =
|
|
41339
|
-
if (!
|
|
41387
|
+
const src = import_node_path25.default.join(work, dirName, "frpc");
|
|
41388
|
+
if (!import_node_fs26.default.existsSync(src)) {
|
|
41340
41389
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
41341
41390
|
}
|
|
41342
|
-
|
|
41391
|
+
import_node_fs26.default.copyFileSync(src, destBin);
|
|
41343
41392
|
} finally {
|
|
41344
|
-
|
|
41393
|
+
import_node_fs26.default.rmSync(work, { recursive: true, force: true });
|
|
41345
41394
|
}
|
|
41346
41395
|
}
|
|
41347
41396
|
|
|
41348
41397
|
// src/tunnel/frpc-process.ts
|
|
41349
|
-
var
|
|
41350
|
-
var
|
|
41398
|
+
var import_node_fs27 = __toESM(require("fs"), 1);
|
|
41399
|
+
var import_node_path26 = __toESM(require("path"), 1);
|
|
41351
41400
|
var import_node_child_process8 = require("child_process");
|
|
41352
41401
|
function frpcPidFilePath(dataDir) {
|
|
41353
|
-
return
|
|
41402
|
+
return import_node_path26.default.join(dataDir, "frpc.pid");
|
|
41354
41403
|
}
|
|
41355
41404
|
function writeFrpcPid(dataDir, pid) {
|
|
41356
41405
|
try {
|
|
41357
|
-
|
|
41406
|
+
import_node_fs27.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
41358
41407
|
} catch {
|
|
41359
41408
|
}
|
|
41360
41409
|
}
|
|
41361
41410
|
function clearFrpcPid(dataDir) {
|
|
41362
41411
|
try {
|
|
41363
|
-
|
|
41412
|
+
import_node_fs27.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
41364
41413
|
} catch {
|
|
41365
41414
|
}
|
|
41366
41415
|
}
|
|
@@ -41376,7 +41425,7 @@ function defaultIsPidAlive(pid) {
|
|
|
41376
41425
|
}
|
|
41377
41426
|
function defaultReadPidFile(file) {
|
|
41378
41427
|
try {
|
|
41379
|
-
return
|
|
41428
|
+
return import_node_fs27.default.readFileSync(file, "utf8");
|
|
41380
41429
|
} catch {
|
|
41381
41430
|
return null;
|
|
41382
41431
|
}
|
|
@@ -41392,7 +41441,7 @@ function defaultSleep(ms) {
|
|
|
41392
41441
|
}
|
|
41393
41442
|
async function killStaleFrpc(deps) {
|
|
41394
41443
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
41395
|
-
const tomlPath =
|
|
41444
|
+
const tomlPath = import_node_path26.default.join(deps.dataDir, "frpc.toml");
|
|
41396
41445
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
41397
41446
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
41398
41447
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -41416,7 +41465,7 @@ async function killStaleFrpc(deps) {
|
|
|
41416
41465
|
}
|
|
41417
41466
|
if (victims.size === 0) {
|
|
41418
41467
|
try {
|
|
41419
|
-
|
|
41468
|
+
import_node_fs27.default.unlinkSync(pidFile);
|
|
41420
41469
|
} catch {
|
|
41421
41470
|
}
|
|
41422
41471
|
return;
|
|
@@ -41427,7 +41476,7 @@ async function killStaleFrpc(deps) {
|
|
|
41427
41476
|
}
|
|
41428
41477
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
41429
41478
|
try {
|
|
41430
|
-
|
|
41479
|
+
import_node_fs27.default.unlinkSync(pidFile);
|
|
41431
41480
|
} catch {
|
|
41432
41481
|
}
|
|
41433
41482
|
}
|
|
@@ -41464,7 +41513,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
41464
41513
|
var TunnelManager = class {
|
|
41465
41514
|
constructor(deps) {
|
|
41466
41515
|
this.deps = deps;
|
|
41467
|
-
this.store = deps.store ?? new TunnelStore(
|
|
41516
|
+
this.store = deps.store ?? new TunnelStore(import_node_path27.default.join(deps.dataDir, "tunnel.json"));
|
|
41468
41517
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
41469
41518
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
41470
41519
|
}
|
|
@@ -41591,7 +41640,7 @@ var TunnelManager = class {
|
|
|
41591
41640
|
dataDir: this.deps.dataDir,
|
|
41592
41641
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
41593
41642
|
});
|
|
41594
|
-
const tomlPath =
|
|
41643
|
+
const tomlPath = import_node_path27.default.join(this.deps.dataDir, "frpc.toml");
|
|
41595
41644
|
const proxyName = `clawd-${t.subdomain}-${localPort}-${import_node_crypto7.default.randomBytes(3).toString("hex")}`;
|
|
41596
41645
|
const toml = buildFrpcToml({
|
|
41597
41646
|
serverAddr: t.frpsHost,
|
|
@@ -41602,12 +41651,12 @@ var TunnelManager = class {
|
|
|
41602
41651
|
localPort,
|
|
41603
41652
|
logLevel: "info"
|
|
41604
41653
|
});
|
|
41605
|
-
await
|
|
41654
|
+
await import_node_fs28.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
41606
41655
|
const proc = (this.deps.spawnImpl ?? import_node_child_process9.spawn)(frpcBin, ["-c", tomlPath], {
|
|
41607
41656
|
stdio: ["ignore", "pipe", "pipe"]
|
|
41608
41657
|
});
|
|
41609
|
-
const logFilePath =
|
|
41610
|
-
const logStream =
|
|
41658
|
+
const logFilePath = import_node_path27.default.join(this.deps.dataDir, "frpc.log");
|
|
41659
|
+
const logStream = import_node_fs28.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
41611
41660
|
logStream.on("error", () => {
|
|
41612
41661
|
});
|
|
41613
41662
|
const tee = (chunk) => {
|
|
@@ -41690,27 +41739,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
41690
41739
|
|
|
41691
41740
|
// src/tunnel/device-key.ts
|
|
41692
41741
|
var import_node_os13 = __toESM(require("os"), 1);
|
|
41693
|
-
var
|
|
41742
|
+
var import_node_path28 = __toESM(require("path"), 1);
|
|
41694
41743
|
var import_node_crypto8 = __toESM(require("crypto"), 1);
|
|
41695
41744
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
41696
41745
|
function deriveStableDeviceKey(opts = {}) {
|
|
41697
41746
|
const hostname = opts.hostname ?? import_node_os13.default.hostname();
|
|
41698
41747
|
const uid = opts.uid ?? (typeof import_node_os13.default.userInfo === "function" ? import_node_os13.default.userInfo().uid : 0);
|
|
41699
41748
|
const home = opts.home ?? import_node_os13.default.homedir();
|
|
41700
|
-
const defaultDataDir =
|
|
41701
|
-
const normalizedDataDir = opts.dataDir ?
|
|
41749
|
+
const defaultDataDir = import_node_path28.default.resolve(import_node_path28.default.join(home, ".clawd"));
|
|
41750
|
+
const normalizedDataDir = opts.dataDir ? import_node_path28.default.resolve(opts.dataDir) : null;
|
|
41702
41751
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
41703
41752
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
41704
41753
|
return import_node_crypto8.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
41705
41754
|
}
|
|
41706
41755
|
|
|
41707
41756
|
// src/auth-store.ts
|
|
41708
|
-
var
|
|
41709
|
-
var
|
|
41757
|
+
var import_node_fs29 = __toESM(require("fs"), 1);
|
|
41758
|
+
var import_node_path29 = __toESM(require("path"), 1);
|
|
41710
41759
|
var import_node_crypto9 = __toESM(require("crypto"), 1);
|
|
41711
41760
|
var AUTH_FILE_NAME = "auth.json";
|
|
41712
41761
|
function authFilePath(dataDir) {
|
|
41713
|
-
return
|
|
41762
|
+
return import_node_path29.default.join(dataDir, AUTH_FILE_NAME);
|
|
41714
41763
|
}
|
|
41715
41764
|
function loadOrCreateAuthFile(opts) {
|
|
41716
41765
|
const file = authFilePath(opts.dataDir);
|
|
@@ -41744,7 +41793,7 @@ function defaultGenerateOwnerPrincipalId() {
|
|
|
41744
41793
|
}
|
|
41745
41794
|
function readAuthFile(file) {
|
|
41746
41795
|
try {
|
|
41747
|
-
const raw =
|
|
41796
|
+
const raw = import_node_fs29.default.readFileSync(file, "utf8");
|
|
41748
41797
|
const parsed = JSON.parse(raw);
|
|
41749
41798
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
41750
41799
|
return null;
|
|
@@ -41763,25 +41812,25 @@ function readAuthFile(file) {
|
|
|
41763
41812
|
}
|
|
41764
41813
|
}
|
|
41765
41814
|
function writeAuthFile(file, content) {
|
|
41766
|
-
|
|
41767
|
-
|
|
41815
|
+
import_node_fs29.default.mkdirSync(import_node_path29.default.dirname(file), { recursive: true });
|
|
41816
|
+
import_node_fs29.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
41768
41817
|
try {
|
|
41769
|
-
|
|
41818
|
+
import_node_fs29.default.chmodSync(file, 384);
|
|
41770
41819
|
} catch {
|
|
41771
41820
|
}
|
|
41772
41821
|
}
|
|
41773
41822
|
|
|
41774
41823
|
// src/owner-profile.ts
|
|
41775
|
-
var
|
|
41824
|
+
var import_node_fs30 = __toESM(require("fs"), 1);
|
|
41776
41825
|
var import_node_os14 = __toESM(require("os"), 1);
|
|
41777
|
-
var
|
|
41826
|
+
var import_node_path30 = __toESM(require("path"), 1);
|
|
41778
41827
|
var PROFILE_FILENAME = "profile.json";
|
|
41779
41828
|
function loadOwnerDisplayName(dataDir) {
|
|
41780
41829
|
const fallback = import_node_os14.default.userInfo().username;
|
|
41781
|
-
const profilePath =
|
|
41830
|
+
const profilePath = import_node_path30.default.join(dataDir, PROFILE_FILENAME);
|
|
41782
41831
|
let raw;
|
|
41783
41832
|
try {
|
|
41784
|
-
raw =
|
|
41833
|
+
raw = import_node_fs30.default.readFileSync(profilePath, "utf8");
|
|
41785
41834
|
} catch {
|
|
41786
41835
|
return fallback;
|
|
41787
41836
|
}
|
|
@@ -41804,18 +41853,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
41804
41853
|
}
|
|
41805
41854
|
|
|
41806
41855
|
// src/feishu-auth/owner-identity-store.ts
|
|
41807
|
-
var
|
|
41808
|
-
var
|
|
41856
|
+
var import_node_fs31 = __toESM(require("fs"), 1);
|
|
41857
|
+
var import_node_path31 = __toESM(require("path"), 1);
|
|
41809
41858
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
41810
41859
|
var OwnerIdentityStore = class {
|
|
41811
41860
|
file;
|
|
41812
41861
|
constructor(dataDir) {
|
|
41813
|
-
this.file =
|
|
41862
|
+
this.file = import_node_path31.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
41814
41863
|
}
|
|
41815
41864
|
read() {
|
|
41816
41865
|
let raw;
|
|
41817
41866
|
try {
|
|
41818
|
-
raw =
|
|
41867
|
+
raw = import_node_fs31.default.readFileSync(this.file, "utf8");
|
|
41819
41868
|
} catch {
|
|
41820
41869
|
return null;
|
|
41821
41870
|
}
|
|
@@ -41843,16 +41892,16 @@ var OwnerIdentityStore = class {
|
|
|
41843
41892
|
};
|
|
41844
41893
|
}
|
|
41845
41894
|
write(record) {
|
|
41846
|
-
|
|
41847
|
-
|
|
41895
|
+
import_node_fs31.default.mkdirSync(import_node_path31.default.dirname(this.file), { recursive: true });
|
|
41896
|
+
import_node_fs31.default.writeFileSync(this.file, JSON.stringify(record, null, 2), { mode: 384 });
|
|
41848
41897
|
try {
|
|
41849
|
-
|
|
41898
|
+
import_node_fs31.default.chmodSync(this.file, 384);
|
|
41850
41899
|
} catch {
|
|
41851
41900
|
}
|
|
41852
41901
|
}
|
|
41853
41902
|
clear() {
|
|
41854
41903
|
try {
|
|
41855
|
-
|
|
41904
|
+
import_node_fs31.default.unlinkSync(this.file);
|
|
41856
41905
|
} catch (err) {
|
|
41857
41906
|
const code = err?.code;
|
|
41858
41907
|
if (code !== "ENOENT") throw err;
|
|
@@ -41973,9 +42022,9 @@ var CentralClientError = class extends Error {
|
|
|
41973
42022
|
code;
|
|
41974
42023
|
cause;
|
|
41975
42024
|
};
|
|
41976
|
-
async function centralRequest(opts,
|
|
42025
|
+
async function centralRequest(opts, path61, init) {
|
|
41977
42026
|
const f = opts.fetchImpl ?? globalThis.fetch;
|
|
41978
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
42027
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path61}`;
|
|
41979
42028
|
const ctrl = new AbortController();
|
|
41980
42029
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
41981
42030
|
let res;
|
|
@@ -42117,8 +42166,8 @@ function verifyConnectToken(args) {
|
|
|
42117
42166
|
}
|
|
42118
42167
|
|
|
42119
42168
|
// src/feishu-auth/server-key.ts
|
|
42120
|
-
var
|
|
42121
|
-
var
|
|
42169
|
+
var fs40 = __toESM(require("fs"), 1);
|
|
42170
|
+
var path40 = __toESM(require("path"), 1);
|
|
42122
42171
|
var FILE_NAME2 = "server-signing-key.json";
|
|
42123
42172
|
var ServerKeyStore = class {
|
|
42124
42173
|
constructor(dataDir) {
|
|
@@ -42126,12 +42175,12 @@ var ServerKeyStore = class {
|
|
|
42126
42175
|
}
|
|
42127
42176
|
dataDir;
|
|
42128
42177
|
filePath() {
|
|
42129
|
-
return
|
|
42178
|
+
return path40.join(this.dataDir, FILE_NAME2);
|
|
42130
42179
|
}
|
|
42131
42180
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
42132
42181
|
read() {
|
|
42133
42182
|
try {
|
|
42134
|
-
const raw =
|
|
42183
|
+
const raw = fs40.readFileSync(this.filePath(), "utf8");
|
|
42135
42184
|
const parsed = JSON.parse(raw);
|
|
42136
42185
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
42137
42186
|
return parsed.publicKeyPem;
|
|
@@ -42146,12 +42195,12 @@ var ServerKeyStore = class {
|
|
|
42146
42195
|
publicKeyPem,
|
|
42147
42196
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
42148
42197
|
};
|
|
42149
|
-
|
|
42150
|
-
|
|
42198
|
+
fs40.mkdirSync(this.dataDir, { recursive: true });
|
|
42199
|
+
fs40.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
42151
42200
|
}
|
|
42152
42201
|
clear() {
|
|
42153
42202
|
try {
|
|
42154
|
-
|
|
42203
|
+
fs40.unlinkSync(this.filePath());
|
|
42155
42204
|
} catch {
|
|
42156
42205
|
}
|
|
42157
42206
|
}
|
|
@@ -42164,12 +42213,12 @@ init_protocol();
|
|
|
42164
42213
|
init_protocol();
|
|
42165
42214
|
|
|
42166
42215
|
// src/session/fork.ts
|
|
42167
|
-
var
|
|
42216
|
+
var import_node_fs32 = __toESM(require("fs"), 1);
|
|
42168
42217
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
42169
|
-
var
|
|
42218
|
+
var import_node_path32 = __toESM(require("path"), 1);
|
|
42170
42219
|
init_claude_history();
|
|
42171
42220
|
function readJsonlEntries(file) {
|
|
42172
|
-
const raw =
|
|
42221
|
+
const raw = import_node_fs32.default.readFileSync(file, "utf8");
|
|
42173
42222
|
const out = [];
|
|
42174
42223
|
for (const line of raw.split("\n")) {
|
|
42175
42224
|
const t = line.trim();
|
|
@@ -42182,10 +42231,10 @@ function readJsonlEntries(file) {
|
|
|
42182
42231
|
return out;
|
|
42183
42232
|
}
|
|
42184
42233
|
function forkSession(input) {
|
|
42185
|
-
const baseDir = input.baseDir ??
|
|
42186
|
-
const projectDir =
|
|
42187
|
-
const sourceFile =
|
|
42188
|
-
if (!
|
|
42234
|
+
const baseDir = input.baseDir ?? import_node_path32.default.join(import_node_os15.default.homedir(), ".claude");
|
|
42235
|
+
const projectDir = import_node_path32.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
42236
|
+
const sourceFile = import_node_path32.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
42237
|
+
if (!import_node_fs32.default.existsSync(sourceFile)) {
|
|
42189
42238
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
42190
42239
|
}
|
|
42191
42240
|
const entries = readJsonlEntries(sourceFile);
|
|
@@ -42215,9 +42264,9 @@ function forkSession(input) {
|
|
|
42215
42264
|
}
|
|
42216
42265
|
forkedLines.push(JSON.stringify(forked));
|
|
42217
42266
|
}
|
|
42218
|
-
const forkedFilePath =
|
|
42219
|
-
|
|
42220
|
-
|
|
42267
|
+
const forkedFilePath = import_node_path32.default.join(projectDir, `${forkedToolSessionId}.jsonl`);
|
|
42268
|
+
import_node_fs32.default.mkdirSync(projectDir, { recursive: true });
|
|
42269
|
+
import_node_fs32.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
42221
42270
|
return { forkedToolSessionId, forkedFilePath };
|
|
42222
42271
|
}
|
|
42223
42272
|
|
|
@@ -42598,7 +42647,7 @@ function buildPermissionHandlers(deps) {
|
|
|
42598
42647
|
}
|
|
42599
42648
|
|
|
42600
42649
|
// src/handlers/history.ts
|
|
42601
|
-
var
|
|
42650
|
+
var path43 = __toESM(require("path"), 1);
|
|
42602
42651
|
init_protocol();
|
|
42603
42652
|
|
|
42604
42653
|
// src/session/recent-dirs.ts
|
|
@@ -42616,7 +42665,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
42616
42665
|
}
|
|
42617
42666
|
|
|
42618
42667
|
// src/permission/persona-paths.ts
|
|
42619
|
-
var
|
|
42668
|
+
var path42 = __toESM(require("path"), 1);
|
|
42620
42669
|
function getAllowedPersonaIds(grants, action) {
|
|
42621
42670
|
const ids = /* @__PURE__ */ new Set();
|
|
42622
42671
|
for (const g2 of grants) {
|
|
@@ -42629,31 +42678,31 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
42629
42678
|
return ids;
|
|
42630
42679
|
}
|
|
42631
42680
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
42632
|
-
const target =
|
|
42681
|
+
const target = path42.resolve(absPath);
|
|
42633
42682
|
if (userWorkDir) {
|
|
42634
|
-
const u =
|
|
42635
|
-
const usep = u.endsWith(
|
|
42683
|
+
const u = path42.resolve(userWorkDir);
|
|
42684
|
+
const usep = u.endsWith(path42.sep) ? "" : path42.sep;
|
|
42636
42685
|
if (target === u || target.startsWith(u + usep)) return true;
|
|
42637
42686
|
}
|
|
42638
|
-
const root =
|
|
42639
|
-
const sep3 = root.endsWith(
|
|
42687
|
+
const root = path42.resolve(personaRoot);
|
|
42688
|
+
const sep3 = root.endsWith(path42.sep) ? "" : path42.sep;
|
|
42640
42689
|
if (!target.startsWith(root + sep3)) return false;
|
|
42641
|
-
const rel =
|
|
42690
|
+
const rel = path42.relative(root, target);
|
|
42642
42691
|
if (!rel || rel.startsWith("..")) return false;
|
|
42643
|
-
const personaId = rel.split(
|
|
42692
|
+
const personaId = rel.split(path42.sep)[0];
|
|
42644
42693
|
if (!personaId) return false;
|
|
42645
42694
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
42646
42695
|
if (allowed === "*") return true;
|
|
42647
42696
|
return allowed.has(personaId);
|
|
42648
42697
|
}
|
|
42649
42698
|
function personaIdFromPath(absPath, personaRoot) {
|
|
42650
|
-
const root =
|
|
42651
|
-
const target =
|
|
42652
|
-
const sep3 = root.endsWith(
|
|
42699
|
+
const root = path42.resolve(personaRoot);
|
|
42700
|
+
const target = path42.resolve(absPath);
|
|
42701
|
+
const sep3 = root.endsWith(path42.sep) ? "" : path42.sep;
|
|
42653
42702
|
if (!target.startsWith(root + sep3)) return null;
|
|
42654
|
-
const rel =
|
|
42703
|
+
const rel = path42.relative(root, target);
|
|
42655
42704
|
if (!rel || rel.startsWith("..")) return null;
|
|
42656
|
-
const id = rel.split(
|
|
42705
|
+
const id = rel.split(path42.sep)[0];
|
|
42657
42706
|
return id || null;
|
|
42658
42707
|
}
|
|
42659
42708
|
|
|
@@ -42680,7 +42729,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42680
42729
|
if (!pid) return false;
|
|
42681
42730
|
return isGuestPathAllowed(
|
|
42682
42731
|
ctx.grants,
|
|
42683
|
-
|
|
42732
|
+
path43.join(personaRoot, pid),
|
|
42684
42733
|
personaRoot,
|
|
42685
42734
|
"read",
|
|
42686
42735
|
userWorkDir
|
|
@@ -42692,7 +42741,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42692
42741
|
};
|
|
42693
42742
|
const list = async (frame, _client, ctx) => {
|
|
42694
42743
|
const args = HistoryListArgs.parse(frame);
|
|
42695
|
-
assertGuestPath(ctx,
|
|
42744
|
+
assertGuestPath(ctx, path43.resolve(args.projectPath), personaRoot, "history:list");
|
|
42696
42745
|
const sessions = await history.listSessions(args);
|
|
42697
42746
|
return { response: { type: "history:list", sessions } };
|
|
42698
42747
|
};
|
|
@@ -42724,13 +42773,13 @@ function buildHistoryHandlers(deps) {
|
|
|
42724
42773
|
};
|
|
42725
42774
|
const subagents = async (frame, _client, ctx) => {
|
|
42726
42775
|
const args = HistorySubagentsArgs.parse(frame);
|
|
42727
|
-
assertGuestPath(ctx,
|
|
42776
|
+
assertGuestPath(ctx, path43.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
42728
42777
|
const subs = await history.listSubagents(args);
|
|
42729
42778
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
42730
42779
|
};
|
|
42731
42780
|
const subagentRead = async (frame, _client, ctx) => {
|
|
42732
42781
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
42733
|
-
assertGuestPath(ctx,
|
|
42782
|
+
assertGuestPath(ctx, path43.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
42734
42783
|
const res = await history.readSubagent(args);
|
|
42735
42784
|
return { response: { type: "history:subagent-read", ...res } };
|
|
42736
42785
|
};
|
|
@@ -42739,7 +42788,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42739
42788
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
42740
42789
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42741
42790
|
const filtered = dirs.filter(
|
|
42742
|
-
(d) => isGuestPathAllowed(ctx.grants,
|
|
42791
|
+
(d) => isGuestPathAllowed(ctx.grants, path43.resolve(d.cwd), personaRoot, "read", userWorkDir)
|
|
42743
42792
|
);
|
|
42744
42793
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
42745
42794
|
}
|
|
@@ -42756,7 +42805,7 @@ function buildHistoryHandlers(deps) {
|
|
|
42756
42805
|
}
|
|
42757
42806
|
|
|
42758
42807
|
// src/handlers/workspace.ts
|
|
42759
|
-
var
|
|
42808
|
+
var path44 = __toESM(require("path"), 1);
|
|
42760
42809
|
var os15 = __toESM(require("os"), 1);
|
|
42761
42810
|
init_protocol();
|
|
42762
42811
|
init_protocol();
|
|
@@ -42798,22 +42847,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42798
42847
|
const args = WorkspaceListArgs.parse(frame);
|
|
42799
42848
|
const isGuest = ctx?.principal.kind === "guest";
|
|
42800
42849
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os15.homedir();
|
|
42801
|
-
const resolvedCwd =
|
|
42802
|
-
const target = args.path ?
|
|
42850
|
+
const resolvedCwd = path44.resolve(args.cwd ?? fallbackCwd);
|
|
42851
|
+
const target = args.path ? path44.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
42803
42852
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
42804
42853
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
42805
42854
|
return { response: { type: "workspace:list", ...res } };
|
|
42806
42855
|
};
|
|
42807
42856
|
const read = async (frame, _client, ctx) => {
|
|
42808
42857
|
const args = WorkspaceReadArgs.parse(frame);
|
|
42809
|
-
const target =
|
|
42858
|
+
const target = path44.isAbsolute(args.path) ? path44.resolve(args.path) : path44.resolve(args.cwd, args.path);
|
|
42810
42859
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
42811
42860
|
const res = workspace.read(args);
|
|
42812
42861
|
return { response: { type: "workspace:read", ...res } };
|
|
42813
42862
|
};
|
|
42814
42863
|
const skillsList = async (frame, _client, ctx) => {
|
|
42815
42864
|
const args = SkillsListArgs.parse(frame);
|
|
42816
|
-
const cwdAbs =
|
|
42865
|
+
const cwdAbs = path44.resolve(args.cwd);
|
|
42817
42866
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
42818
42867
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
42819
42868
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -42825,7 +42874,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42825
42874
|
};
|
|
42826
42875
|
const agentsList = async (frame, _client, ctx) => {
|
|
42827
42876
|
const args = AgentsListArgs.parse(frame);
|
|
42828
|
-
const cwdAbs =
|
|
42877
|
+
const cwdAbs = path44.resolve(args.cwd);
|
|
42829
42878
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
42830
42879
|
if (args.tool === "codex") {
|
|
42831
42880
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -42847,20 +42896,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
42847
42896
|
}
|
|
42848
42897
|
|
|
42849
42898
|
// src/handlers/git.ts
|
|
42850
|
-
var
|
|
42899
|
+
var path46 = __toESM(require("path"), 1);
|
|
42851
42900
|
init_protocol();
|
|
42852
42901
|
init_protocol();
|
|
42853
42902
|
|
|
42854
42903
|
// src/workspace/git.ts
|
|
42855
42904
|
var import_node_child_process10 = require("child_process");
|
|
42856
|
-
var
|
|
42857
|
-
var
|
|
42905
|
+
var import_node_fs33 = __toESM(require("fs"), 1);
|
|
42906
|
+
var import_node_path33 = __toESM(require("path"), 1);
|
|
42858
42907
|
var import_node_util = require("util");
|
|
42859
42908
|
var pexec = (0, import_node_util.promisify)(import_node_child_process10.execFile);
|
|
42860
42909
|
function normalizePath(p2) {
|
|
42861
|
-
const resolved =
|
|
42910
|
+
const resolved = import_node_path33.default.resolve(p2);
|
|
42862
42911
|
try {
|
|
42863
|
-
return
|
|
42912
|
+
return import_node_fs33.default.realpathSync(resolved);
|
|
42864
42913
|
} catch {
|
|
42865
42914
|
return resolved;
|
|
42866
42915
|
}
|
|
@@ -42934,7 +42983,7 @@ async function listGitBranches(cwd) {
|
|
|
42934
42983
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
42935
42984
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
42936
42985
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
42937
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
42986
|
+
if (!isGuestPathAllowed(ctx.grants, path46.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
42938
42987
|
throw new ClawdError(
|
|
42939
42988
|
ERROR_CODES.UNAUTHORIZED,
|
|
42940
42989
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -43451,7 +43500,7 @@ function buildPersonaHandlers(deps) {
|
|
|
43451
43500
|
}
|
|
43452
43501
|
|
|
43453
43502
|
// src/handlers/attachment.ts
|
|
43454
|
-
var
|
|
43503
|
+
var import_node_path34 = __toESM(require("path"), 1);
|
|
43455
43504
|
init_protocol();
|
|
43456
43505
|
init_protocol();
|
|
43457
43506
|
var DEFAULT_TTL_SECONDS = 24 * 3600;
|
|
@@ -43506,12 +43555,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
43506
43555
|
`session ${args.sessionId} scope unresolved`
|
|
43507
43556
|
);
|
|
43508
43557
|
}
|
|
43509
|
-
const cwdAbs =
|
|
43510
|
-
const candidateAbs =
|
|
43558
|
+
const cwdAbs = import_node_path34.default.resolve(sessionFile.cwd);
|
|
43559
|
+
const candidateAbs = import_node_path34.default.isAbsolute(args.relPath) ? import_node_path34.default.resolve(args.relPath) : import_node_path34.default.resolve(cwdAbs, args.relPath);
|
|
43511
43560
|
assertGuestAttachmentPath(ctx, candidateAbs, deps.personaRoot, "attachment.signUrl", deps.usersRoot);
|
|
43512
43561
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
43513
43562
|
const entry = entries.find((e) => {
|
|
43514
|
-
const storedAbs =
|
|
43563
|
+
const storedAbs = import_node_path34.default.isAbsolute(e.relPath) ? import_node_path34.default.resolve(e.relPath) : import_node_path34.default.resolve(cwdAbs, e.relPath);
|
|
43515
43564
|
return storedAbs === candidateAbs && !e.stale;
|
|
43516
43565
|
});
|
|
43517
43566
|
if (!entry) {
|
|
@@ -43536,7 +43585,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
43536
43585
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
43537
43586
|
const f = deps.sessionStore.read(sessionId);
|
|
43538
43587
|
if (!f) return;
|
|
43539
|
-
assertGuestAttachmentPath(ctx,
|
|
43588
|
+
assertGuestAttachmentPath(ctx, import_node_path34.default.resolve(f.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
43540
43589
|
}
|
|
43541
43590
|
const groupAdd = async (frame, _client, ctx) => {
|
|
43542
43591
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -43608,19 +43657,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
43608
43657
|
|
|
43609
43658
|
// src/handlers/extension.ts
|
|
43610
43659
|
var import_promises7 = __toESM(require("fs/promises"), 1);
|
|
43611
|
-
var
|
|
43660
|
+
var import_node_path39 = __toESM(require("path"), 1);
|
|
43612
43661
|
init_protocol();
|
|
43613
43662
|
|
|
43614
43663
|
// src/extension/bundle-zip.ts
|
|
43615
43664
|
var import_promises4 = __toESM(require("fs/promises"), 1);
|
|
43616
|
-
var
|
|
43665
|
+
var import_node_path35 = __toESM(require("path"), 1);
|
|
43617
43666
|
var import_node_crypto11 = __toESM(require("crypto"), 1);
|
|
43618
43667
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
43619
43668
|
async function bundleExtensionDir(dir) {
|
|
43620
43669
|
const entries = await listFilesSorted(dir);
|
|
43621
43670
|
const zip = new import_jszip2.default();
|
|
43622
43671
|
for (const rel of entries) {
|
|
43623
|
-
const abs =
|
|
43672
|
+
const abs = import_node_path35.default.join(dir, rel);
|
|
43624
43673
|
const content = await import_promises4.default.readFile(abs);
|
|
43625
43674
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
43626
43675
|
}
|
|
@@ -43641,7 +43690,7 @@ async function listFilesSorted(rootDir) {
|
|
|
43641
43690
|
return out;
|
|
43642
43691
|
}
|
|
43643
43692
|
async function walk(absRoot, relPrefix, out) {
|
|
43644
|
-
const dirAbs =
|
|
43693
|
+
const dirAbs = import_node_path35.default.join(absRoot, relPrefix);
|
|
43645
43694
|
const entries = await import_promises4.default.readdir(dirAbs, { withFileTypes: true });
|
|
43646
43695
|
for (const e of entries) {
|
|
43647
43696
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -43695,25 +43744,25 @@ function computePublishCheck(args) {
|
|
|
43695
43744
|
|
|
43696
43745
|
// src/extension/install-flow.ts
|
|
43697
43746
|
var import_promises5 = __toESM(require("fs/promises"), 1);
|
|
43698
|
-
var
|
|
43747
|
+
var import_node_path37 = __toESM(require("path"), 1);
|
|
43699
43748
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
43700
43749
|
var import_node_crypto12 = __toESM(require("crypto"), 1);
|
|
43701
43750
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
43702
43751
|
|
|
43703
43752
|
// src/extension/paths.ts
|
|
43704
43753
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
43705
|
-
var
|
|
43754
|
+
var import_node_path36 = __toESM(require("path"), 1);
|
|
43706
43755
|
function clawdHomeRoot(override) {
|
|
43707
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
43756
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path36.default.join(import_node_os17.default.homedir(), ".clawd");
|
|
43708
43757
|
}
|
|
43709
43758
|
function extensionsRoot(override) {
|
|
43710
|
-
return
|
|
43759
|
+
return import_node_path36.default.join(clawdHomeRoot(override), "extensions");
|
|
43711
43760
|
}
|
|
43712
43761
|
function publishedChannelsFile(override) {
|
|
43713
|
-
return
|
|
43762
|
+
return import_node_path36.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
43714
43763
|
}
|
|
43715
43764
|
function bundleCacheRoot(override) {
|
|
43716
|
-
return
|
|
43765
|
+
return import_node_path36.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
43717
43766
|
}
|
|
43718
43767
|
|
|
43719
43768
|
// src/extension/install-flow.ts
|
|
@@ -43740,7 +43789,7 @@ async function installFromChannel(args, deps) {
|
|
|
43740
43789
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43741
43790
|
}
|
|
43742
43791
|
for (const name of Object.keys(zip.files)) {
|
|
43743
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43792
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path37.default.isAbsolute(name)) {
|
|
43744
43793
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43745
43794
|
}
|
|
43746
43795
|
}
|
|
@@ -43772,7 +43821,7 @@ async function installFromChannel(args, deps) {
|
|
|
43772
43821
|
);
|
|
43773
43822
|
}
|
|
43774
43823
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
43775
|
-
const destDir =
|
|
43824
|
+
const destDir = import_node_path37.default.join(deps.extensionsRoot, localExtId);
|
|
43776
43825
|
let destExists = false;
|
|
43777
43826
|
try {
|
|
43778
43827
|
await import_promises5.default.access(destDir);
|
|
@@ -43786,16 +43835,16 @@ async function installFromChannel(args, deps) {
|
|
|
43786
43835
|
);
|
|
43787
43836
|
}
|
|
43788
43837
|
const stage = await import_promises5.default.mkdtemp(
|
|
43789
|
-
|
|
43838
|
+
import_node_path37.default.join(import_node_os18.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
43790
43839
|
);
|
|
43791
43840
|
try {
|
|
43792
43841
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43793
|
-
const dest =
|
|
43842
|
+
const dest = import_node_path37.default.join(stage, name);
|
|
43794
43843
|
if (entry.dir) {
|
|
43795
43844
|
await import_promises5.default.mkdir(dest, { recursive: true });
|
|
43796
43845
|
continue;
|
|
43797
43846
|
}
|
|
43798
|
-
await import_promises5.default.mkdir(
|
|
43847
|
+
await import_promises5.default.mkdir(import_node_path37.default.dirname(dest), { recursive: true });
|
|
43799
43848
|
if (name === "manifest.json") {
|
|
43800
43849
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43801
43850
|
await import_promises5.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -43816,7 +43865,7 @@ async function installFromChannel(args, deps) {
|
|
|
43816
43865
|
|
|
43817
43866
|
// src/extension/update-flow.ts
|
|
43818
43867
|
var import_promises6 = __toESM(require("fs/promises"), 1);
|
|
43819
|
-
var
|
|
43868
|
+
var import_node_path38 = __toESM(require("path"), 1);
|
|
43820
43869
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
43821
43870
|
var import_node_crypto13 = __toESM(require("crypto"), 1);
|
|
43822
43871
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
@@ -43833,11 +43882,11 @@ async function updateFromChannel(args, deps) {
|
|
|
43833
43882
|
channelRef.extId,
|
|
43834
43883
|
channelRef.ownerPrincipalId
|
|
43835
43884
|
);
|
|
43836
|
-
const liveDir =
|
|
43885
|
+
const liveDir = import_node_path38.default.join(deps.extensionsRoot, localExtId);
|
|
43837
43886
|
const prevDir = `${liveDir}.prev`;
|
|
43838
43887
|
let existingVersion;
|
|
43839
43888
|
try {
|
|
43840
|
-
const raw = await import_promises6.default.readFile(
|
|
43889
|
+
const raw = await import_promises6.default.readFile(import_node_path38.default.join(liveDir, "manifest.json"), "utf8");
|
|
43841
43890
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
43842
43891
|
if (!parsed2.success) {
|
|
43843
43892
|
throw new UpdateError(
|
|
@@ -43870,7 +43919,7 @@ async function updateFromChannel(args, deps) {
|
|
|
43870
43919
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
43871
43920
|
}
|
|
43872
43921
|
for (const name of Object.keys(zip.files)) {
|
|
43873
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
43922
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path38.default.isAbsolute(name)) {
|
|
43874
43923
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
43875
43924
|
}
|
|
43876
43925
|
}
|
|
@@ -43905,16 +43954,16 @@ async function updateFromChannel(args, deps) {
|
|
|
43905
43954
|
await import_promises6.default.rm(prevDir, { recursive: true, force: true });
|
|
43906
43955
|
await import_promises6.default.rename(liveDir, prevDir);
|
|
43907
43956
|
const stage = await import_promises6.default.mkdtemp(
|
|
43908
|
-
|
|
43957
|
+
import_node_path38.default.join(import_node_os19.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
43909
43958
|
);
|
|
43910
43959
|
try {
|
|
43911
43960
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
43912
|
-
const dest =
|
|
43961
|
+
const dest = import_node_path38.default.join(stage, name);
|
|
43913
43962
|
if (entry.dir) {
|
|
43914
43963
|
await import_promises6.default.mkdir(dest, { recursive: true });
|
|
43915
43964
|
continue;
|
|
43916
43965
|
}
|
|
43917
|
-
await import_promises6.default.mkdir(
|
|
43966
|
+
await import_promises6.default.mkdir(import_node_path38.default.dirname(dest), { recursive: true });
|
|
43918
43967
|
if (name === "manifest.json") {
|
|
43919
43968
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
43920
43969
|
await import_promises6.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -44007,7 +44056,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
44007
44056
|
);
|
|
44008
44057
|
}
|
|
44009
44058
|
}
|
|
44010
|
-
const manifestPath =
|
|
44059
|
+
const manifestPath = import_node_path39.default.join(root, extId, "manifest.json");
|
|
44011
44060
|
const manifest = await readManifest(root, extId);
|
|
44012
44061
|
const next = { ...manifest, version: newVersion };
|
|
44013
44062
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -44015,7 +44064,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
44015
44064
|
await import_promises7.default.rename(tmp, manifestPath);
|
|
44016
44065
|
}
|
|
44017
44066
|
async function readManifest(root, extId) {
|
|
44018
|
-
const file =
|
|
44067
|
+
const file = import_node_path39.default.join(root, extId, "manifest.json");
|
|
44019
44068
|
let raw;
|
|
44020
44069
|
try {
|
|
44021
44070
|
raw = await import_promises7.default.readFile(file, "utf8");
|
|
@@ -44106,7 +44155,7 @@ function buildExtensionHandlers(deps) {
|
|
|
44106
44155
|
};
|
|
44107
44156
|
async function buildSnapshotMeta(extId) {
|
|
44108
44157
|
const manifest = await readManifest(deps.root, extId);
|
|
44109
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
44158
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path39.default.join(deps.root, extId));
|
|
44110
44159
|
return { manifest, contentHash: sha256, buffer };
|
|
44111
44160
|
}
|
|
44112
44161
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -44287,9 +44336,9 @@ function buildExtensionHandlers(deps) {
|
|
|
44287
44336
|
}
|
|
44288
44337
|
|
|
44289
44338
|
// src/app-builder/project-store.ts
|
|
44290
|
-
var
|
|
44339
|
+
var import_node_fs34 = require("fs");
|
|
44291
44340
|
var import_node_child_process11 = require("child_process");
|
|
44292
|
-
var
|
|
44341
|
+
var import_node_path40 = require("path");
|
|
44293
44342
|
init_protocol();
|
|
44294
44343
|
var PROJECTS_DIR = "projects";
|
|
44295
44344
|
var META_FILE = ".clawd-project.json";
|
|
@@ -44303,19 +44352,19 @@ var ProjectStore = class {
|
|
|
44303
44352
|
root;
|
|
44304
44353
|
/** projects/<name>/.clawd-project.json 路径 */
|
|
44305
44354
|
metaPath(name) {
|
|
44306
|
-
return (0,
|
|
44355
|
+
return (0, import_node_path40.join)(this.projectsRoot(), name, META_FILE);
|
|
44307
44356
|
}
|
|
44308
44357
|
/** projects/<name>/ 目录路径(cwd 用) */
|
|
44309
44358
|
projectDir(name) {
|
|
44310
|
-
return (0,
|
|
44359
|
+
return (0, import_node_path40.join)(this.projectsRoot(), name);
|
|
44311
44360
|
}
|
|
44312
44361
|
projectsRoot() {
|
|
44313
|
-
return (0,
|
|
44362
|
+
return (0, import_node_path40.join)(this.root, PROJECTS_DIR);
|
|
44314
44363
|
}
|
|
44315
44364
|
async list() {
|
|
44316
44365
|
let entries;
|
|
44317
44366
|
try {
|
|
44318
|
-
entries = await
|
|
44367
|
+
entries = await import_node_fs34.promises.readdir(this.projectsRoot());
|
|
44319
44368
|
} catch (err) {
|
|
44320
44369
|
if (err.code === "ENOENT") return [];
|
|
44321
44370
|
throw err;
|
|
@@ -44323,7 +44372,7 @@ var ProjectStore = class {
|
|
|
44323
44372
|
const out = [];
|
|
44324
44373
|
for (const name of entries) {
|
|
44325
44374
|
try {
|
|
44326
|
-
const raw = await
|
|
44375
|
+
const raw = await import_node_fs34.promises.readFile(this.metaPath(name), "utf8");
|
|
44327
44376
|
const json = JSON.parse(raw);
|
|
44328
44377
|
let migrated = false;
|
|
44329
44378
|
if (typeof json.devCommand !== "string" || json.devCommand.length === 0) {
|
|
@@ -44334,7 +44383,7 @@ var ProjectStore = class {
|
|
|
44334
44383
|
if (parsed.success) {
|
|
44335
44384
|
out.push(parsed.data);
|
|
44336
44385
|
if (migrated) {
|
|
44337
|
-
void
|
|
44386
|
+
void import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(parsed.data, null, 2) + "\n", "utf8").catch(() => {
|
|
44338
44387
|
});
|
|
44339
44388
|
}
|
|
44340
44389
|
}
|
|
@@ -44378,8 +44427,8 @@ var ProjectStore = class {
|
|
|
44378
44427
|
throw new Error(`invalid name "${name}": ${validated.error.message}`);
|
|
44379
44428
|
}
|
|
44380
44429
|
const dir = this.projectDir(name);
|
|
44381
|
-
await
|
|
44382
|
-
await
|
|
44430
|
+
await import_node_fs34.promises.mkdir(dir, { recursive: true });
|
|
44431
|
+
await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
44383
44432
|
return meta;
|
|
44384
44433
|
}
|
|
44385
44434
|
/**
|
|
@@ -44422,7 +44471,7 @@ var ProjectStore = class {
|
|
|
44422
44471
|
}
|
|
44423
44472
|
async delete(name) {
|
|
44424
44473
|
const dir = this.projectDir(name);
|
|
44425
|
-
await
|
|
44474
|
+
await import_node_fs34.promises.rm(dir, { recursive: true, force: true });
|
|
44426
44475
|
}
|
|
44427
44476
|
async updatePort(name, newPort) {
|
|
44428
44477
|
if (newPort < PROJECT_PORT_MIN || newPort > PROJECT_PORT_MAX) {
|
|
@@ -44438,7 +44487,7 @@ var ProjectStore = class {
|
|
|
44438
44487
|
throw new Error(`port ${newPort} already used / \u5DF2\u88AB project "${conflict.name}" \u5360\u7528`);
|
|
44439
44488
|
}
|
|
44440
44489
|
const updated = { ...target, port: newPort };
|
|
44441
|
-
await
|
|
44490
|
+
await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(updated, null, 2) + "\n", "utf8");
|
|
44442
44491
|
return updated;
|
|
44443
44492
|
}
|
|
44444
44493
|
/**
|
|
@@ -44455,7 +44504,7 @@ var ProjectStore = class {
|
|
|
44455
44504
|
if (!validated.success) {
|
|
44456
44505
|
throw new Error(`invalid prodUrl "${url}": ${validated.error.message}`);
|
|
44457
44506
|
}
|
|
44458
|
-
await
|
|
44507
|
+
await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44459
44508
|
return validated.data;
|
|
44460
44509
|
}
|
|
44461
44510
|
/**
|
|
@@ -44476,7 +44525,7 @@ var ProjectStore = class {
|
|
|
44476
44525
|
if (!validated.success) {
|
|
44477
44526
|
throw new Error(`invalid publishJob: ${validated.error.message}`);
|
|
44478
44527
|
}
|
|
44479
|
-
await
|
|
44528
|
+
await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44480
44529
|
return validated.data;
|
|
44481
44530
|
}
|
|
44482
44531
|
/** 清掉 .clawd-project.json.publishJob 字段。其他字段保持原样。 */
|
|
@@ -44491,7 +44540,7 @@ var ProjectStore = class {
|
|
|
44491
44540
|
if (!validated.success) {
|
|
44492
44541
|
throw new Error(`failed to clear publishJob: ${validated.error.message}`);
|
|
44493
44542
|
}
|
|
44494
|
-
await
|
|
44543
|
+
await import_node_fs34.promises.writeFile(this.metaPath(name), JSON.stringify(validated.data, null, 2) + "\n", "utf8");
|
|
44495
44544
|
return validated.data;
|
|
44496
44545
|
}
|
|
44497
44546
|
};
|
|
@@ -44612,8 +44661,8 @@ var PublishJobRegistry = class {
|
|
|
44612
44661
|
|
|
44613
44662
|
// src/app-builder/publish-job-runner.ts
|
|
44614
44663
|
var import_node_child_process13 = require("child_process");
|
|
44615
|
-
var
|
|
44616
|
-
var
|
|
44664
|
+
var import_node_fs35 = require("fs");
|
|
44665
|
+
var import_node_path41 = require("path");
|
|
44617
44666
|
|
|
44618
44667
|
// src/app-builder/publish-stage-parser.ts
|
|
44619
44668
|
var STAGE_RE = /^\s*::stage::(build|deploy|verify)\s*$/;
|
|
@@ -44645,10 +44694,10 @@ async function startPublishJob(deps, args) {
|
|
|
44645
44694
|
return { jobId: registry2.get(args.name).jobId, status: "already-publishing" };
|
|
44646
44695
|
}
|
|
44647
44696
|
const projDir = projectDir(args.name);
|
|
44648
|
-
const logPath = (0,
|
|
44697
|
+
const logPath = (0, import_node_path41.join)(projDir, ".publish.log");
|
|
44649
44698
|
let logStream = null;
|
|
44650
44699
|
try {
|
|
44651
|
-
logStream = (0,
|
|
44700
|
+
logStream = (0, import_node_fs35.createWriteStream)(logPath, { flags: "w" });
|
|
44652
44701
|
} catch {
|
|
44653
44702
|
logStream = null;
|
|
44654
44703
|
}
|
|
@@ -44905,8 +44954,8 @@ async function recoverInterruptedJobs(deps) {
|
|
|
44905
44954
|
|
|
44906
44955
|
// src/handlers/app-builder.ts
|
|
44907
44956
|
init_protocol();
|
|
44908
|
-
var
|
|
44909
|
-
var
|
|
44957
|
+
var import_node_path42 = require("path");
|
|
44958
|
+
var import_node_fs36 = require("fs");
|
|
44910
44959
|
var APP_BUILDER_PERSONAS = ["persona-app-builder", "persona-dataclaw-builder"];
|
|
44911
44960
|
var DEV_SERVER_READY_TIMEOUT_MS = 3e4;
|
|
44912
44961
|
async function recoverInterruptedPublishJobs(store, logger) {
|
|
@@ -44987,7 +45036,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
44987
45036
|
async function listAllUsersProjects() {
|
|
44988
45037
|
if (!deps.usersRoot || !deps.getStore) return [];
|
|
44989
45038
|
const getStore = deps.getStore;
|
|
44990
|
-
const userIds = await
|
|
45039
|
+
const userIds = await import_node_fs36.promises.readdir(deps.usersRoot).catch(() => []);
|
|
44991
45040
|
const perUser = await Promise.all(
|
|
44992
45041
|
userIds.map((uid) => getStore(uid).list().catch(() => []))
|
|
44993
45042
|
);
|
|
@@ -45063,8 +45112,8 @@ function buildAppBuilderHandlers(deps) {
|
|
|
45063
45112
|
const project = await userStore.create(f.name, reservedPorts);
|
|
45064
45113
|
try {
|
|
45065
45114
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(session.ownerPersonaId ?? "") : deps.personaRoot;
|
|
45066
|
-
const templateSrcDir = (0,
|
|
45067
|
-
const scaffoldScript = (0,
|
|
45115
|
+
const templateSrcDir = (0, import_node_path42.join)(personaRoot, "extension-kit", "examples", DEFAULT_TEMPLATE);
|
|
45116
|
+
const scaffoldScript = (0, import_node_path42.join)(deps.deployKitRoot, "scripts", "new-extension.sh");
|
|
45068
45117
|
const scaffoldResult = await userStore.scaffold(project.name, templateSrcDir, scaffoldScript);
|
|
45069
45118
|
deps.logger?.info("app-builder.scaffold.done", {
|
|
45070
45119
|
name: project.name,
|
|
@@ -45285,7 +45334,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
45285
45334
|
await userStore.clearPublishJob(args.name);
|
|
45286
45335
|
}
|
|
45287
45336
|
const personaRoot = deps.resolvePersonaRoot ? deps.resolvePersonaRoot(boundSession.ownerPersonaId ?? "") : deps.personaRoot;
|
|
45288
|
-
const scriptPath = (0,
|
|
45337
|
+
const scriptPath = (0, import_node_path42.join)(deps.deployKitRoot, "scripts", "publish.sh");
|
|
45289
45338
|
deps.logger?.info("app-builder.publish.start", {
|
|
45290
45339
|
name: args.name,
|
|
45291
45340
|
sessionId: boundSession.sessionId,
|
|
@@ -45381,7 +45430,7 @@ function buildAppBuilderHandlers(deps) {
|
|
|
45381
45430
|
|
|
45382
45431
|
// src/extension/registry.ts
|
|
45383
45432
|
var import_promises8 = __toESM(require("fs/promises"), 1);
|
|
45384
|
-
var
|
|
45433
|
+
var import_node_path43 = __toESM(require("path"), 1);
|
|
45385
45434
|
async function loadAll(root) {
|
|
45386
45435
|
let entries;
|
|
45387
45436
|
try {
|
|
@@ -45394,13 +45443,13 @@ async function loadAll(root) {
|
|
|
45394
45443
|
for (const ent of entries) {
|
|
45395
45444
|
if (!ent.isDirectory()) continue;
|
|
45396
45445
|
if (ent.name.startsWith(".")) continue;
|
|
45397
|
-
records.push(await loadOne(
|
|
45446
|
+
records.push(await loadOne(import_node_path43.default.join(root, ent.name), ent.name));
|
|
45398
45447
|
}
|
|
45399
45448
|
records.sort((a, b2) => a.extId < b2.extId ? -1 : a.extId > b2.extId ? 1 : 0);
|
|
45400
45449
|
return records;
|
|
45401
45450
|
}
|
|
45402
45451
|
async function loadOne(dir, dirName) {
|
|
45403
|
-
const manifestPath =
|
|
45452
|
+
const manifestPath = import_node_path43.default.join(dir, "manifest.json");
|
|
45404
45453
|
let raw;
|
|
45405
45454
|
try {
|
|
45406
45455
|
raw = await import_promises8.default.readFile(manifestPath, "utf8");
|
|
@@ -45445,7 +45494,7 @@ async function loadOne(dir, dirName) {
|
|
|
45445
45494
|
|
|
45446
45495
|
// src/extension/uninstall.ts
|
|
45447
45496
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
45448
|
-
var
|
|
45497
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
45449
45498
|
var UninstallError = class extends Error {
|
|
45450
45499
|
constructor(code, message) {
|
|
45451
45500
|
super(message);
|
|
@@ -45454,7 +45503,7 @@ var UninstallError = class extends Error {
|
|
|
45454
45503
|
code;
|
|
45455
45504
|
};
|
|
45456
45505
|
async function uninstall(deps) {
|
|
45457
|
-
const dir =
|
|
45506
|
+
const dir = import_node_path44.default.join(deps.root, deps.extId);
|
|
45458
45507
|
try {
|
|
45459
45508
|
await import_promises9.default.access(dir);
|
|
45460
45509
|
} catch {
|
|
@@ -45965,7 +46014,7 @@ function computeGrantForFrame(method, frame) {
|
|
|
45965
46014
|
|
|
45966
46015
|
// src/extension/runtime.ts
|
|
45967
46016
|
var import_node_child_process15 = require("child_process");
|
|
45968
|
-
var
|
|
46017
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
45969
46018
|
var import_promises10 = require("timers/promises");
|
|
45970
46019
|
|
|
45971
46020
|
// src/extension/port-allocator.ts
|
|
@@ -46066,7 +46115,7 @@ var Runtime = class {
|
|
|
46066
46115
|
/\$CLAWOS_EXT_PORT/g,
|
|
46067
46116
|
String(port)
|
|
46068
46117
|
);
|
|
46069
|
-
const dir =
|
|
46118
|
+
const dir = import_node_path45.default.join(this.root, extId);
|
|
46070
46119
|
const env = {
|
|
46071
46120
|
...process.env,
|
|
46072
46121
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -46178,7 +46227,7 @@ ${handle.stderrTail}`
|
|
|
46178
46227
|
|
|
46179
46228
|
// src/extension/published-channels.ts
|
|
46180
46229
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
46181
|
-
var
|
|
46230
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
46182
46231
|
init_zod();
|
|
46183
46232
|
var PublishedChannelsError = class extends Error {
|
|
46184
46233
|
constructor(code, message) {
|
|
@@ -46277,7 +46326,7 @@ var PublishedChannelStore = class {
|
|
|
46277
46326
|
)
|
|
46278
46327
|
};
|
|
46279
46328
|
const tmp = `${this.filePath}.tmp`;
|
|
46280
|
-
await import_promises11.default.mkdir(
|
|
46329
|
+
await import_promises11.default.mkdir(import_node_path46.default.dirname(this.filePath), { recursive: true });
|
|
46281
46330
|
await import_promises11.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
46282
46331
|
await import_promises11.default.rename(tmp, this.filePath);
|
|
46283
46332
|
}
|
|
@@ -46285,7 +46334,7 @@ var PublishedChannelStore = class {
|
|
|
46285
46334
|
|
|
46286
46335
|
// src/extension/bundle-cache.ts
|
|
46287
46336
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
46288
|
-
var
|
|
46337
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
46289
46338
|
var BundleCache = class {
|
|
46290
46339
|
constructor(rootDir) {
|
|
46291
46340
|
this.rootDir = rootDir;
|
|
@@ -46294,14 +46343,14 @@ var BundleCache = class {
|
|
|
46294
46343
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
46295
46344
|
async write(snapshotHash, buffer) {
|
|
46296
46345
|
await import_promises12.default.mkdir(this.rootDir, { recursive: true });
|
|
46297
|
-
const file =
|
|
46346
|
+
const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46298
46347
|
const tmp = `${file}.tmp`;
|
|
46299
46348
|
await import_promises12.default.writeFile(tmp, buffer, { mode: 384 });
|
|
46300
46349
|
await import_promises12.default.rename(tmp, file);
|
|
46301
46350
|
}
|
|
46302
46351
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
46303
46352
|
async read(snapshotHash) {
|
|
46304
|
-
const file =
|
|
46353
|
+
const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46305
46354
|
try {
|
|
46306
46355
|
return await import_promises12.default.readFile(file);
|
|
46307
46356
|
} catch (e) {
|
|
@@ -46311,7 +46360,7 @@ var BundleCache = class {
|
|
|
46311
46360
|
}
|
|
46312
46361
|
/** Idempotent — missing file is not an error. */
|
|
46313
46362
|
async delete(snapshotHash) {
|
|
46314
|
-
const file =
|
|
46363
|
+
const file = import_node_path47.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
46315
46364
|
await import_promises12.default.rm(file, { force: true });
|
|
46316
46365
|
}
|
|
46317
46366
|
};
|
|
@@ -46336,7 +46385,7 @@ async function startDaemon(config) {
|
|
|
46336
46385
|
});
|
|
46337
46386
|
const logger = createLogger({
|
|
46338
46387
|
level: config.logLevel,
|
|
46339
|
-
file:
|
|
46388
|
+
file: import_node_path48.default.join(config.dataDir, "clawd.log"),
|
|
46340
46389
|
logClient
|
|
46341
46390
|
});
|
|
46342
46391
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
@@ -46472,8 +46521,8 @@ async function startDaemon(config) {
|
|
|
46472
46521
|
const agents = new AgentsScanner();
|
|
46473
46522
|
const history = new ClaudeHistoryReader();
|
|
46474
46523
|
let transport = null;
|
|
46475
|
-
const personaStore = new PersonaStore(
|
|
46476
|
-
const usersRoot =
|
|
46524
|
+
const personaStore = new PersonaStore(import_node_path48.default.join(config.dataDir, "personas"));
|
|
46525
|
+
const usersRoot = import_node_path48.default.join(config.dataDir, "users");
|
|
46477
46526
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
46478
46527
|
if (defaultsRoot) {
|
|
46479
46528
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -46493,17 +46542,17 @@ async function startDaemon(config) {
|
|
|
46493
46542
|
migrateCodexSandbox({ store: personaStore, logger });
|
|
46494
46543
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
46495
46544
|
const personaDispatchManager = new PersonaDispatchManager({ genId: () => v4_default() });
|
|
46496
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
46545
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path48.default.dirname((0, import_node_url3.fileURLToPath)(import_meta5.url));
|
|
46497
46546
|
const dispatchServerCandidates = [
|
|
46498
|
-
|
|
46547
|
+
import_node_path48.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
46499
46548
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
46500
|
-
|
|
46549
|
+
import_node_path48.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
46501
46550
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
46502
46551
|
];
|
|
46503
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) =>
|
|
46552
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p2) => import_node_fs37.default.existsSync(p2));
|
|
46504
46553
|
let dispatchMcpConfigPath2;
|
|
46505
46554
|
if (dispatchServerScriptPath) {
|
|
46506
|
-
const dispatchLogPath =
|
|
46555
|
+
const dispatchLogPath = import_node_path48.default.join(config.dataDir, "dispatch-mcp-server.log");
|
|
46507
46556
|
dispatchMcpConfigPath2 = writeDispatchMcpConfig({
|
|
46508
46557
|
dataDir: config.dataDir,
|
|
46509
46558
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -46519,6 +46568,29 @@ async function startDaemon(config) {
|
|
|
46519
46568
|
tried: dispatchServerCandidates
|
|
46520
46569
|
});
|
|
46521
46570
|
}
|
|
46571
|
+
const ticketServerCandidates = [
|
|
46572
|
+
import_node_path48.default.join(here, "ticket", "mcp-server.cjs"),
|
|
46573
|
+
import_node_path48.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
46574
|
+
];
|
|
46575
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p2) => import_node_fs37.default.existsSync(p2));
|
|
46576
|
+
const ticketOwnerUnionId = feishuIdentity?.identity.unionId ?? "";
|
|
46577
|
+
const ticketOwnerName = feishuIdentity?.identity.displayName ?? "";
|
|
46578
|
+
let ticketMcpConfigPath2;
|
|
46579
|
+
if (ticketServerScriptPath && ticketOwnerUnionId) {
|
|
46580
|
+
ticketMcpConfigPath2 = writeTicketMcpConfig({
|
|
46581
|
+
dataDir: config.dataDir,
|
|
46582
|
+
serverScriptPath: ticketServerScriptPath,
|
|
46583
|
+
apiBaseUrl: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
46584
|
+
apiKey: resolveClawdTicketsApiKey(),
|
|
46585
|
+
ownerUnionId: ticketOwnerUnionId,
|
|
46586
|
+
ownerName: ticketOwnerName
|
|
46587
|
+
});
|
|
46588
|
+
logger.info("ticket.mcp.json written", { path: ticketMcpConfigPath2 });
|
|
46589
|
+
} else {
|
|
46590
|
+
logger.warn("ticket-mcp skipped", {
|
|
46591
|
+
reason: !ticketOwnerUnionId ? "feishu unionId missing (login required)" : "ticket-mcp-server.cjs not found (need build)"
|
|
46592
|
+
});
|
|
46593
|
+
}
|
|
46522
46594
|
const manager = new SessionManager({
|
|
46523
46595
|
store,
|
|
46524
46596
|
// Phase 2 (capability platform plan §1): factory 注入后 manager.storeFor 走
|
|
@@ -46528,7 +46600,7 @@ async function startDaemon(config) {
|
|
|
46528
46600
|
getAdapter,
|
|
46529
46601
|
historyReader: history,
|
|
46530
46602
|
dataDir: config.dataDir,
|
|
46531
|
-
personaRoot:
|
|
46603
|
+
personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
|
|
46532
46604
|
usersRoot,
|
|
46533
46605
|
personaStore,
|
|
46534
46606
|
ownerDisplayName,
|
|
@@ -46546,6 +46618,7 @@ async function startDaemon(config) {
|
|
|
46546
46618
|
// - dispatchMcpConfigPath: reducer 透传到 SpawnContext,cc spawn 加 --mcp-config flag。
|
|
46547
46619
|
personaDispatchManager,
|
|
46548
46620
|
dispatchMcpConfigPath: dispatchMcpConfigPath2,
|
|
46621
|
+
ticketMcpConfigPath: ticketMcpConfigPath2,
|
|
46549
46622
|
broadcastFrame: (frame, target) => {
|
|
46550
46623
|
if (target === "all") {
|
|
46551
46624
|
transport?.broadcastAll(frame);
|
|
@@ -46565,10 +46638,10 @@ async function startDaemon(config) {
|
|
|
46565
46638
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
46566
46639
|
attachmentGroup: {
|
|
46567
46640
|
onFileEdit: (input) => {
|
|
46568
|
-
const absPath =
|
|
46641
|
+
const absPath = import_node_path48.default.isAbsolute(input.relPath) ? input.relPath : import_node_path48.default.join(input.cwd, input.relPath);
|
|
46569
46642
|
let size = 0;
|
|
46570
46643
|
try {
|
|
46571
|
-
size =
|
|
46644
|
+
size = import_node_fs37.default.statSync(absPath).size;
|
|
46572
46645
|
} catch (err) {
|
|
46573
46646
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
46574
46647
|
sessionId: input.sessionId,
|
|
@@ -46754,11 +46827,11 @@ async function startDaemon(config) {
|
|
|
46754
46827
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
46755
46828
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
46756
46829
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
46757
|
-
personaRoot:
|
|
46830
|
+
personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
|
|
46758
46831
|
usersRoot
|
|
46759
46832
|
},
|
|
46760
46833
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
46761
|
-
personaRoot:
|
|
46834
|
+
personaRoot: import_node_path48.default.join(config.dataDir, "personas"),
|
|
46762
46835
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
46763
46836
|
usersRoot,
|
|
46764
46837
|
// capability:list / delete handler 依赖
|
|
@@ -46865,11 +46938,11 @@ async function startDaemon(config) {
|
|
|
46865
46938
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2):
|
|
46866
46939
|
// appBuilderPersonaRoot 用于拼 publish.sh 绝对路径(persona-app-builder 安装在
|
|
46867
46940
|
// dataDir/personas/persona-app-builder 之下,extension-kit/scripts/publish.sh 是相对路径)。
|
|
46868
|
-
appBuilderPersonaRoot:
|
|
46941
|
+
appBuilderPersonaRoot: import_node_path48.default.join(config.dataDir, "personas", "persona-app-builder"),
|
|
46869
46942
|
// 共享 deploy-kit 根:scaffold/publish 脚本骨架 + 阿里云凭证单一真源。
|
|
46870
|
-
deployKitRoot:
|
|
46943
|
+
deployKitRoot: import_node_path48.default.join(config.dataDir, "deploy-kit"),
|
|
46871
46944
|
// scaffold/publish 按当前 session 的 persona 解析其安装根,让每个 persona 用自己的模板/注入配置。
|
|
46872
|
-
resolvePersonaRoot: (personaId) =>
|
|
46945
|
+
resolvePersonaRoot: (personaId) => import_node_path48.default.join(config.dataDir, "personas", personaId),
|
|
46873
46946
|
// 发布上线脚手架化 (spec 2026-06-03 §5.2.2):
|
|
46874
46947
|
// 复用 SessionManagerDeps.broadcastFrame 同款 dispatch 逻辑 —— runner 调 manager.send
|
|
46875
46948
|
// 取回 broadcast 帧后逐帧 push 到 transport,跟 manager 自身的 deps 一致。
|
|
@@ -46903,7 +46976,7 @@ async function startDaemon(config) {
|
|
|
46903
46976
|
if (!sourceFile) {
|
|
46904
46977
|
throw new Error(`personaDispatch:run source session not found: ${args.sourceSessionId}`);
|
|
46905
46978
|
}
|
|
46906
|
-
const sourceJsonlPath = sourceFile.toolSessionId ?
|
|
46979
|
+
const sourceJsonlPath = sourceFile.toolSessionId ? import_node_path48.default.join(
|
|
46907
46980
|
import_node_os20.default.homedir(),
|
|
46908
46981
|
".claude",
|
|
46909
46982
|
"projects",
|
|
@@ -47159,8 +47232,8 @@ async function startDaemon(config) {
|
|
|
47159
47232
|
const lines = [
|
|
47160
47233
|
`Tunnel: ${r.url}`,
|
|
47161
47234
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
47162
|
-
`Frpc config: ${
|
|
47163
|
-
`Frpc log: ${
|
|
47235
|
+
`Frpc config: ${import_node_path48.default.join(config.dataDir, "frpc.toml")}`,
|
|
47236
|
+
`Frpc log: ${import_node_path48.default.join(config.dataDir, "frpc.log")}`
|
|
47164
47237
|
];
|
|
47165
47238
|
const width = Math.max(...lines.map((l) => l.length));
|
|
47166
47239
|
const bar = "\u2550".repeat(width + 4);
|
|
@@ -47173,8 +47246,8 @@ ${bar}
|
|
|
47173
47246
|
|
|
47174
47247
|
`);
|
|
47175
47248
|
try {
|
|
47176
|
-
const connectPath =
|
|
47177
|
-
|
|
47249
|
+
const connectPath = import_node_path48.default.join(config.dataDir, "connect.txt");
|
|
47250
|
+
import_node_fs37.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
47178
47251
|
} catch {
|
|
47179
47252
|
}
|
|
47180
47253
|
} catch (err) {
|
|
@@ -47246,9 +47319,9 @@ ${bar}
|
|
|
47246
47319
|
};
|
|
47247
47320
|
}
|
|
47248
47321
|
function migrateDropPersonsDir(dataDir) {
|
|
47249
|
-
const dir =
|
|
47322
|
+
const dir = import_node_path48.default.join(dataDir, "persons");
|
|
47250
47323
|
try {
|
|
47251
|
-
|
|
47324
|
+
import_node_fs37.default.rmSync(dir, { recursive: true, force: true });
|
|
47252
47325
|
} catch {
|
|
47253
47326
|
}
|
|
47254
47327
|
}
|