@clawos-dev/clawd 0.2.614 → 0.2.616
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 +662 -1470
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -450,8 +450,8 @@ var init_parseUtil = __esm({
|
|
|
450
450
|
init_errors();
|
|
451
451
|
init_en();
|
|
452
452
|
makeIssue = (params) => {
|
|
453
|
-
const { data, path:
|
|
454
|
-
const fullPath = [...
|
|
453
|
+
const { data, path: path106, errorMaps, issueData } = params;
|
|
454
|
+
const fullPath = [...path106, ...issueData.path || []];
|
|
455
455
|
const fullIssue = {
|
|
456
456
|
...issueData,
|
|
457
457
|
path: fullPath
|
|
@@ -762,11 +762,11 @@ var init_types = __esm({
|
|
|
762
762
|
init_parseUtil();
|
|
763
763
|
init_util();
|
|
764
764
|
ParseInputLazyPath = class {
|
|
765
|
-
constructor(parent, value,
|
|
765
|
+
constructor(parent, value, path106, key) {
|
|
766
766
|
this._cachedPath = [];
|
|
767
767
|
this.parent = parent;
|
|
768
768
|
this.data = value;
|
|
769
|
-
this._path =
|
|
769
|
+
this._path = path106;
|
|
770
770
|
this._key = key;
|
|
771
771
|
}
|
|
772
772
|
get path() {
|
|
@@ -10356,8 +10356,8 @@ var require_req = __commonJS({
|
|
|
10356
10356
|
if (req.originalUrl) {
|
|
10357
10357
|
_req.url = req.originalUrl;
|
|
10358
10358
|
} else {
|
|
10359
|
-
const
|
|
10360
|
-
_req.url = typeof
|
|
10359
|
+
const path106 = req.path;
|
|
10360
|
+
_req.url = typeof path106 === "string" ? path106 : req.url ? req.url.path || req.url : void 0;
|
|
10361
10361
|
}
|
|
10362
10362
|
if (req.query) {
|
|
10363
10363
|
_req.query = req.query;
|
|
@@ -10522,14 +10522,14 @@ var require_redact = __commonJS({
|
|
|
10522
10522
|
}
|
|
10523
10523
|
return obj;
|
|
10524
10524
|
}
|
|
10525
|
-
function parsePath(
|
|
10525
|
+
function parsePath(path106) {
|
|
10526
10526
|
const parts = [];
|
|
10527
10527
|
let current = "";
|
|
10528
10528
|
let inBrackets = false;
|
|
10529
10529
|
let inQuotes = false;
|
|
10530
10530
|
let quoteChar = "";
|
|
10531
|
-
for (let i2 = 0; i2 <
|
|
10532
|
-
const char =
|
|
10531
|
+
for (let i2 = 0; i2 < path106.length; i2++) {
|
|
10532
|
+
const char = path106[i2];
|
|
10533
10533
|
if (!inBrackets && char === ".") {
|
|
10534
10534
|
if (current) {
|
|
10535
10535
|
parts.push(current);
|
|
@@ -10660,10 +10660,10 @@ var require_redact = __commonJS({
|
|
|
10660
10660
|
return current;
|
|
10661
10661
|
}
|
|
10662
10662
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
10663
|
-
for (const
|
|
10664
|
-
const parts = parsePath(
|
|
10663
|
+
for (const path106 of paths) {
|
|
10664
|
+
const parts = parsePath(path106);
|
|
10665
10665
|
if (parts.includes("*")) {
|
|
10666
|
-
redactWildcardPath(obj, parts, censor,
|
|
10666
|
+
redactWildcardPath(obj, parts, censor, path106, remove);
|
|
10667
10667
|
} else {
|
|
10668
10668
|
if (remove) {
|
|
10669
10669
|
removeKey(obj, parts);
|
|
@@ -10748,8 +10748,8 @@ var require_redact = __commonJS({
|
|
|
10748
10748
|
}
|
|
10749
10749
|
} else {
|
|
10750
10750
|
if (afterWildcard.includes("*")) {
|
|
10751
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
10752
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
10751
|
+
const wrappedCensor = typeof censor === "function" ? (value, path106) => {
|
|
10752
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path106];
|
|
10753
10753
|
return censor(value, fullPath);
|
|
10754
10754
|
} : censor;
|
|
10755
10755
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -10784,8 +10784,8 @@ var require_redact = __commonJS({
|
|
|
10784
10784
|
return null;
|
|
10785
10785
|
}
|
|
10786
10786
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
10787
|
-
for (const
|
|
10788
|
-
const parts = parsePath(
|
|
10787
|
+
for (const path106 of pathsToClone) {
|
|
10788
|
+
const parts = parsePath(path106);
|
|
10789
10789
|
let current = pathStructure;
|
|
10790
10790
|
for (let i2 = 0; i2 < parts.length; i2++) {
|
|
10791
10791
|
const part = parts[i2];
|
|
@@ -10837,24 +10837,24 @@ var require_redact = __commonJS({
|
|
|
10837
10837
|
}
|
|
10838
10838
|
return cloneSelectively(obj, pathStructure);
|
|
10839
10839
|
}
|
|
10840
|
-
function validatePath(
|
|
10841
|
-
if (typeof
|
|
10840
|
+
function validatePath(path106) {
|
|
10841
|
+
if (typeof path106 !== "string") {
|
|
10842
10842
|
throw new Error("Paths must be (non-empty) strings");
|
|
10843
10843
|
}
|
|
10844
|
-
if (
|
|
10844
|
+
if (path106 === "") {
|
|
10845
10845
|
throw new Error("Invalid redaction path ()");
|
|
10846
10846
|
}
|
|
10847
|
-
if (
|
|
10848
|
-
throw new Error(`Invalid redaction path (${
|
|
10847
|
+
if (path106.includes("..")) {
|
|
10848
|
+
throw new Error(`Invalid redaction path (${path106})`);
|
|
10849
10849
|
}
|
|
10850
|
-
if (
|
|
10851
|
-
throw new Error(`Invalid redaction path (${
|
|
10850
|
+
if (path106.includes(",")) {
|
|
10851
|
+
throw new Error(`Invalid redaction path (${path106})`);
|
|
10852
10852
|
}
|
|
10853
10853
|
let bracketCount = 0;
|
|
10854
10854
|
let inQuotes = false;
|
|
10855
10855
|
let quoteChar = "";
|
|
10856
|
-
for (let i2 = 0; i2 <
|
|
10857
|
-
const char =
|
|
10856
|
+
for (let i2 = 0; i2 < path106.length; i2++) {
|
|
10857
|
+
const char = path106[i2];
|
|
10858
10858
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
10859
10859
|
if (!inQuotes) {
|
|
10860
10860
|
inQuotes = true;
|
|
@@ -10868,20 +10868,20 @@ var require_redact = __commonJS({
|
|
|
10868
10868
|
} else if (char === "]" && !inQuotes) {
|
|
10869
10869
|
bracketCount--;
|
|
10870
10870
|
if (bracketCount < 0) {
|
|
10871
|
-
throw new Error(`Invalid redaction path (${
|
|
10871
|
+
throw new Error(`Invalid redaction path (${path106})`);
|
|
10872
10872
|
}
|
|
10873
10873
|
}
|
|
10874
10874
|
}
|
|
10875
10875
|
if (bracketCount !== 0) {
|
|
10876
|
-
throw new Error(`Invalid redaction path (${
|
|
10876
|
+
throw new Error(`Invalid redaction path (${path106})`);
|
|
10877
10877
|
}
|
|
10878
10878
|
}
|
|
10879
10879
|
function validatePaths(paths) {
|
|
10880
10880
|
if (!Array.isArray(paths)) {
|
|
10881
10881
|
throw new TypeError("paths must be an array");
|
|
10882
10882
|
}
|
|
10883
|
-
for (const
|
|
10884
|
-
validatePath(
|
|
10883
|
+
for (const path106 of paths) {
|
|
10884
|
+
validatePath(path106);
|
|
10885
10885
|
}
|
|
10886
10886
|
}
|
|
10887
10887
|
function slowRedact(options = {}) {
|
|
@@ -11049,8 +11049,8 @@ var require_redaction = __commonJS({
|
|
|
11049
11049
|
if (shape[k3] === null) {
|
|
11050
11050
|
o2[k3] = (value) => topCensor(value, [k3]);
|
|
11051
11051
|
} else {
|
|
11052
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
11053
|
-
return censor(value, [k3, ...
|
|
11052
|
+
const wrappedCensor = typeof censor === "function" ? (value, path106) => {
|
|
11053
|
+
return censor(value, [k3, ...path106]);
|
|
11054
11054
|
} : censor;
|
|
11055
11055
|
o2[k3] = Redact({
|
|
11056
11056
|
paths: shape[k3],
|
|
@@ -11268,10 +11268,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
11268
11268
|
var require_sonic_boom = __commonJS({
|
|
11269
11269
|
"../node_modules/.pnpm/sonic-boom@4.2.1/node_modules/sonic-boom/index.js"(exports2, module2) {
|
|
11270
11270
|
"use strict";
|
|
11271
|
-
var
|
|
11271
|
+
var fs95 = require("fs");
|
|
11272
11272
|
var EventEmitter2 = require("events");
|
|
11273
11273
|
var inherits = require("util").inherits;
|
|
11274
|
-
var
|
|
11274
|
+
var path106 = require("path");
|
|
11275
11275
|
var sleep2 = require_atomic_sleep();
|
|
11276
11276
|
var assert = require("assert");
|
|
11277
11277
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -11325,20 +11325,20 @@ var require_sonic_boom = __commonJS({
|
|
|
11325
11325
|
const mode = sonic.mode;
|
|
11326
11326
|
if (sonic.sync) {
|
|
11327
11327
|
try {
|
|
11328
|
-
if (sonic.mkdir)
|
|
11329
|
-
const fd =
|
|
11328
|
+
if (sonic.mkdir) fs95.mkdirSync(path106.dirname(file), { recursive: true });
|
|
11329
|
+
const fd = fs95.openSync(file, flags, mode);
|
|
11330
11330
|
fileOpened(null, fd);
|
|
11331
11331
|
} catch (err) {
|
|
11332
11332
|
fileOpened(err);
|
|
11333
11333
|
throw err;
|
|
11334
11334
|
}
|
|
11335
11335
|
} else if (sonic.mkdir) {
|
|
11336
|
-
|
|
11336
|
+
fs95.mkdir(path106.dirname(file), { recursive: true }, (err) => {
|
|
11337
11337
|
if (err) return fileOpened(err);
|
|
11338
|
-
|
|
11338
|
+
fs95.open(file, flags, mode, fileOpened);
|
|
11339
11339
|
});
|
|
11340
11340
|
} else {
|
|
11341
|
-
|
|
11341
|
+
fs95.open(file, flags, mode, fileOpened);
|
|
11342
11342
|
}
|
|
11343
11343
|
}
|
|
11344
11344
|
function SonicBoom(opts) {
|
|
@@ -11379,8 +11379,8 @@ var require_sonic_boom = __commonJS({
|
|
|
11379
11379
|
this.flush = flushBuffer;
|
|
11380
11380
|
this.flushSync = flushBufferSync;
|
|
11381
11381
|
this._actualWrite = actualWriteBuffer;
|
|
11382
|
-
fsWriteSync = () =>
|
|
11383
|
-
fsWrite = () =>
|
|
11382
|
+
fsWriteSync = () => fs95.writeSync(this.fd, this._writingBuf);
|
|
11383
|
+
fsWrite = () => fs95.write(this.fd, this._writingBuf, this.release);
|
|
11384
11384
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
11385
11385
|
this._writingBuf = "";
|
|
11386
11386
|
this.write = write;
|
|
@@ -11389,15 +11389,15 @@ var require_sonic_boom = __commonJS({
|
|
|
11389
11389
|
this._actualWrite = actualWrite;
|
|
11390
11390
|
fsWriteSync = () => {
|
|
11391
11391
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
11392
|
-
return
|
|
11392
|
+
return fs95.writeSync(this.fd, this._writingBuf);
|
|
11393
11393
|
}
|
|
11394
|
-
return
|
|
11394
|
+
return fs95.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11395
11395
|
};
|
|
11396
11396
|
fsWrite = () => {
|
|
11397
11397
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
11398
|
-
return
|
|
11398
|
+
return fs95.write(this.fd, this._writingBuf, this.release);
|
|
11399
11399
|
}
|
|
11400
|
-
return
|
|
11400
|
+
return fs95.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
11401
11401
|
};
|
|
11402
11402
|
} else {
|
|
11403
11403
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -11454,7 +11454,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11454
11454
|
}
|
|
11455
11455
|
}
|
|
11456
11456
|
if (this._fsync) {
|
|
11457
|
-
|
|
11457
|
+
fs95.fsyncSync(this.fd);
|
|
11458
11458
|
}
|
|
11459
11459
|
const len = this._len;
|
|
11460
11460
|
if (this._reopening) {
|
|
@@ -11568,7 +11568,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11568
11568
|
const onDrain = () => {
|
|
11569
11569
|
if (!this._fsync) {
|
|
11570
11570
|
try {
|
|
11571
|
-
|
|
11571
|
+
fs95.fsync(this.fd, (err) => {
|
|
11572
11572
|
this._flushPending = false;
|
|
11573
11573
|
cb(err);
|
|
11574
11574
|
});
|
|
@@ -11670,7 +11670,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11670
11670
|
const fd = this.fd;
|
|
11671
11671
|
this.once("ready", () => {
|
|
11672
11672
|
if (fd !== this.fd) {
|
|
11673
|
-
|
|
11673
|
+
fs95.close(fd, (err) => {
|
|
11674
11674
|
if (err) {
|
|
11675
11675
|
return this.emit("error", err);
|
|
11676
11676
|
}
|
|
@@ -11719,7 +11719,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11719
11719
|
buf = this._bufs[0];
|
|
11720
11720
|
}
|
|
11721
11721
|
try {
|
|
11722
|
-
const n2 = Buffer.isBuffer(buf) ?
|
|
11722
|
+
const n2 = Buffer.isBuffer(buf) ? fs95.writeSync(this.fd, buf) : fs95.writeSync(this.fd, buf, "utf8");
|
|
11723
11723
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n2);
|
|
11724
11724
|
buf = releasedBufObj.writingBuf;
|
|
11725
11725
|
this._len = releasedBufObj.len;
|
|
@@ -11735,7 +11735,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11735
11735
|
}
|
|
11736
11736
|
}
|
|
11737
11737
|
try {
|
|
11738
|
-
|
|
11738
|
+
fs95.fsyncSync(this.fd);
|
|
11739
11739
|
} catch {
|
|
11740
11740
|
}
|
|
11741
11741
|
}
|
|
@@ -11756,7 +11756,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11756
11756
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
11757
11757
|
}
|
|
11758
11758
|
try {
|
|
11759
|
-
const n2 =
|
|
11759
|
+
const n2 = fs95.writeSync(this.fd, buf);
|
|
11760
11760
|
buf = buf.subarray(n2);
|
|
11761
11761
|
this._len = Math.max(this._len - n2, 0);
|
|
11762
11762
|
if (buf.length <= 0) {
|
|
@@ -11784,13 +11784,13 @@ var require_sonic_boom = __commonJS({
|
|
|
11784
11784
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
11785
11785
|
if (this.sync) {
|
|
11786
11786
|
try {
|
|
11787
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
11787
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs95.writeSync(this.fd, this._writingBuf) : fs95.writeSync(this.fd, this._writingBuf, "utf8");
|
|
11788
11788
|
release2(null, written);
|
|
11789
11789
|
} catch (err) {
|
|
11790
11790
|
release2(err);
|
|
11791
11791
|
}
|
|
11792
11792
|
} else {
|
|
11793
|
-
|
|
11793
|
+
fs95.write(this.fd, this._writingBuf, release2);
|
|
11794
11794
|
}
|
|
11795
11795
|
}
|
|
11796
11796
|
function actualWriteBuffer() {
|
|
@@ -11799,7 +11799,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11799
11799
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
11800
11800
|
if (this.sync) {
|
|
11801
11801
|
try {
|
|
11802
|
-
const written =
|
|
11802
|
+
const written = fs95.writeSync(this.fd, this._writingBuf);
|
|
11803
11803
|
release2(null, written);
|
|
11804
11804
|
} catch (err) {
|
|
11805
11805
|
release2(err);
|
|
@@ -11808,7 +11808,7 @@ var require_sonic_boom = __commonJS({
|
|
|
11808
11808
|
if (kCopyBuffer) {
|
|
11809
11809
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
11810
11810
|
}
|
|
11811
|
-
|
|
11811
|
+
fs95.write(this.fd, this._writingBuf, release2);
|
|
11812
11812
|
}
|
|
11813
11813
|
}
|
|
11814
11814
|
function actualClose(sonic) {
|
|
@@ -11824,12 +11824,12 @@ var require_sonic_boom = __commonJS({
|
|
|
11824
11824
|
sonic._lens = [];
|
|
11825
11825
|
assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
11826
11826
|
try {
|
|
11827
|
-
|
|
11827
|
+
fs95.fsync(sonic.fd, closeWrapped);
|
|
11828
11828
|
} catch {
|
|
11829
11829
|
}
|
|
11830
11830
|
function closeWrapped() {
|
|
11831
11831
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
11832
|
-
|
|
11832
|
+
fs95.close(sonic.fd, done);
|
|
11833
11833
|
} else {
|
|
11834
11834
|
done();
|
|
11835
11835
|
}
|
|
@@ -14964,11 +14964,11 @@ var init_lib = __esm({
|
|
|
14964
14964
|
}
|
|
14965
14965
|
}
|
|
14966
14966
|
},
|
|
14967
|
-
addToPath: function addToPath(
|
|
14968
|
-
var last =
|
|
14967
|
+
addToPath: function addToPath(path106, added, removed, oldPosInc, options) {
|
|
14968
|
+
var last = path106.lastComponent;
|
|
14969
14969
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
14970
14970
|
return {
|
|
14971
|
-
oldPos:
|
|
14971
|
+
oldPos: path106.oldPos + oldPosInc,
|
|
14972
14972
|
lastComponent: {
|
|
14973
14973
|
count: last.count + 1,
|
|
14974
14974
|
added,
|
|
@@ -14978,7 +14978,7 @@ var init_lib = __esm({
|
|
|
14978
14978
|
};
|
|
14979
14979
|
} else {
|
|
14980
14980
|
return {
|
|
14981
|
-
oldPos:
|
|
14981
|
+
oldPos: path106.oldPos + oldPosInc,
|
|
14982
14982
|
lastComponent: {
|
|
14983
14983
|
count: 1,
|
|
14984
14984
|
added,
|
|
@@ -15560,10 +15560,10 @@ function attachmentToHistoryMessage(o2, ts) {
|
|
|
15560
15560
|
const memories = raw.map((m3) => {
|
|
15561
15561
|
if (!m3 || typeof m3 !== "object") return null;
|
|
15562
15562
|
const rec6 = m3;
|
|
15563
|
-
const
|
|
15563
|
+
const path106 = typeof rec6.path === "string" ? rec6.path : null;
|
|
15564
15564
|
const content = typeof rec6.content === "string" ? rec6.content : null;
|
|
15565
|
-
if (!
|
|
15566
|
-
const entry = { path:
|
|
15565
|
+
if (!path106 || content == null) return null;
|
|
15566
|
+
const entry = { path: path106, content };
|
|
15567
15567
|
if (typeof rec6.mtimeMs === "number") entry.mtimeMs = rec6.mtimeMs;
|
|
15568
15568
|
return entry;
|
|
15569
15569
|
}).filter((m3) => m3 !== null);
|
|
@@ -16429,10 +16429,10 @@ function parseAttachment(obj) {
|
|
|
16429
16429
|
const memories = raw.map((m3) => {
|
|
16430
16430
|
if (!m3 || typeof m3 !== "object") return null;
|
|
16431
16431
|
const rec6 = m3;
|
|
16432
|
-
const
|
|
16432
|
+
const path106 = typeof rec6.path === "string" ? rec6.path : null;
|
|
16433
16433
|
const content = typeof rec6.content === "string" ? rec6.content : null;
|
|
16434
|
-
if (!
|
|
16435
|
-
const out = { path:
|
|
16434
|
+
if (!path106 || content == null) return null;
|
|
16435
|
+
const out = { path: path106, content };
|
|
16436
16436
|
if (typeof rec6.mtimeMs === "number") out.mtimeMs = rec6.mtimeMs;
|
|
16437
16437
|
return out;
|
|
16438
16438
|
}).filter((m3) => m3 !== null);
|
|
@@ -37406,8 +37406,8 @@ var require_utils = __commonJS({
|
|
|
37406
37406
|
var result = transform[inputType][outputType](input);
|
|
37407
37407
|
return result;
|
|
37408
37408
|
};
|
|
37409
|
-
exports2.resolve = function(
|
|
37410
|
-
var parts =
|
|
37409
|
+
exports2.resolve = function(path106) {
|
|
37410
|
+
var parts = path106.split("/");
|
|
37411
37411
|
var result = [];
|
|
37412
37412
|
for (var index = 0; index < parts.length; index++) {
|
|
37413
37413
|
var part = parts[index];
|
|
@@ -43260,18 +43260,18 @@ var require_object = __commonJS({
|
|
|
43260
43260
|
var object = new ZipObject(name, zipObjectContent, o2);
|
|
43261
43261
|
this.files[name] = object;
|
|
43262
43262
|
};
|
|
43263
|
-
var parentFolder = function(
|
|
43264
|
-
if (
|
|
43265
|
-
|
|
43263
|
+
var parentFolder = function(path106) {
|
|
43264
|
+
if (path106.slice(-1) === "/") {
|
|
43265
|
+
path106 = path106.substring(0, path106.length - 1);
|
|
43266
43266
|
}
|
|
43267
|
-
var lastSlash =
|
|
43268
|
-
return lastSlash > 0 ?
|
|
43267
|
+
var lastSlash = path106.lastIndexOf("/");
|
|
43268
|
+
return lastSlash > 0 ? path106.substring(0, lastSlash) : "";
|
|
43269
43269
|
};
|
|
43270
|
-
var forceTrailingSlash = function(
|
|
43271
|
-
if (
|
|
43272
|
-
|
|
43270
|
+
var forceTrailingSlash = function(path106) {
|
|
43271
|
+
if (path106.slice(-1) !== "/") {
|
|
43272
|
+
path106 += "/";
|
|
43273
43273
|
}
|
|
43274
|
-
return
|
|
43274
|
+
return path106;
|
|
43275
43275
|
};
|
|
43276
43276
|
var folderAdd = function(name, createFolders) {
|
|
43277
43277
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -44273,7 +44273,7 @@ var require_lib3 = __commonJS({
|
|
|
44273
44273
|
// src/run-case/recorder.ts
|
|
44274
44274
|
function startRunCaseRecorder(opts) {
|
|
44275
44275
|
const now = opts.now ?? Date.now;
|
|
44276
|
-
const dir =
|
|
44276
|
+
const dir = import_node_path85.default.dirname(opts.recordPath);
|
|
44277
44277
|
let stream = null;
|
|
44278
44278
|
let closing = false;
|
|
44279
44279
|
let closedSettled = false;
|
|
@@ -44287,8 +44287,8 @@ function startRunCaseRecorder(opts) {
|
|
|
44287
44287
|
});
|
|
44288
44288
|
const ensureStream = () => {
|
|
44289
44289
|
if (stream) return stream;
|
|
44290
|
-
|
|
44291
|
-
stream =
|
|
44290
|
+
import_node_fs66.default.mkdirSync(dir, { recursive: true });
|
|
44291
|
+
stream = import_node_fs66.default.createWriteStream(opts.recordPath, { flags: "a" });
|
|
44292
44292
|
stream.on("close", () => closedResolve());
|
|
44293
44293
|
return stream;
|
|
44294
44294
|
};
|
|
@@ -44313,12 +44313,12 @@ function startRunCaseRecorder(opts) {
|
|
|
44313
44313
|
};
|
|
44314
44314
|
return { tap, close, closed };
|
|
44315
44315
|
}
|
|
44316
|
-
var
|
|
44316
|
+
var import_node_fs66, import_node_path85;
|
|
44317
44317
|
var init_recorder = __esm({
|
|
44318
44318
|
"src/run-case/recorder.ts"() {
|
|
44319
44319
|
"use strict";
|
|
44320
|
-
|
|
44321
|
-
|
|
44320
|
+
import_node_fs66 = __toESM(require("fs"), 1);
|
|
44321
|
+
import_node_path85 = __toESM(require("path"), 1);
|
|
44322
44322
|
}
|
|
44323
44323
|
});
|
|
44324
44324
|
|
|
@@ -44361,7 +44361,7 @@ var init_wire = __esm({
|
|
|
44361
44361
|
// src/run-case/controller.ts
|
|
44362
44362
|
async function runController(opts) {
|
|
44363
44363
|
const now = opts.now ?? Date.now;
|
|
44364
|
-
const cwd = opts.cwd ?? (0,
|
|
44364
|
+
const cwd = opts.cwd ?? (0, import_node_fs67.mkdtempSync)(import_node_path86.default.join(import_node_os32.default.tmpdir(), "clawd-runcase-"));
|
|
44365
44365
|
const ownsCwd = opts.cwd === void 0;
|
|
44366
44366
|
const recorder = startRunCaseRecorder({ recordPath: opts.record, now });
|
|
44367
44367
|
const spawnCtx = { cwd };
|
|
@@ -44522,19 +44522,19 @@ async function runController(opts) {
|
|
|
44522
44522
|
if (sigintHandler) process.off("SIGINT", sigintHandler);
|
|
44523
44523
|
if (ownsCwd) {
|
|
44524
44524
|
try {
|
|
44525
|
-
(0,
|
|
44525
|
+
(0, import_node_fs67.rmSync)(cwd, { recursive: true, force: true });
|
|
44526
44526
|
} catch {
|
|
44527
44527
|
}
|
|
44528
44528
|
}
|
|
44529
44529
|
return exitCode ?? 0;
|
|
44530
44530
|
}
|
|
44531
|
-
var
|
|
44531
|
+
var import_node_fs67, import_node_os32, import_node_path86;
|
|
44532
44532
|
var init_controller = __esm({
|
|
44533
44533
|
"src/run-case/controller.ts"() {
|
|
44534
44534
|
"use strict";
|
|
44535
|
-
|
|
44535
|
+
import_node_fs67 = require("fs");
|
|
44536
44536
|
import_node_os32 = __toESM(require("os"), 1);
|
|
44537
|
-
|
|
44537
|
+
import_node_path86 = __toESM(require("path"), 1);
|
|
44538
44538
|
init_claude();
|
|
44539
44539
|
init_stdout_splitter();
|
|
44540
44540
|
init_permission_stdio();
|
|
@@ -44806,10 +44806,10 @@ Env (advanced):
|
|
|
44806
44806
|
`;
|
|
44807
44807
|
|
|
44808
44808
|
// src/index.ts
|
|
44809
|
-
var
|
|
44810
|
-
var
|
|
44809
|
+
var import_node_path84 = __toESM(require("path"), 1);
|
|
44810
|
+
var import_node_fs65 = __toESM(require("fs"), 1);
|
|
44811
44811
|
var import_node_os31 = __toESM(require("os"), 1);
|
|
44812
|
-
var
|
|
44812
|
+
var import_node_crypto27 = require("crypto");
|
|
44813
44813
|
var import_node_url6 = require("url");
|
|
44814
44814
|
|
|
44815
44815
|
// src/logger.ts
|
|
@@ -46330,6 +46330,7 @@ function pushEventToBufferInPlace(next, event, deps) {
|
|
|
46330
46330
|
const isTurnEnd = withSeq.kind === "turn_end";
|
|
46331
46331
|
const isUserText = withSeq.kind === "user_text";
|
|
46332
46332
|
const isBackgroundEvent = withSeq.kind === "subagent_progress";
|
|
46333
|
+
const isSessionInit = withSeq.kind === "session_init";
|
|
46333
46334
|
if (isBackgroundEvent) {
|
|
46334
46335
|
const bg = withSeq;
|
|
46335
46336
|
const done = bg.status === "completed" || bg.status === "failed";
|
|
@@ -46350,7 +46351,7 @@ function pushEventToBufferInPlace(next, event, deps) {
|
|
|
46350
46351
|
}
|
|
46351
46352
|
next.turnOpen = false;
|
|
46352
46353
|
next.turnStartedAt = null;
|
|
46353
|
-
} else if (!isBackgroundEvent && !next.turnOpen) {
|
|
46354
|
+
} else if (!isBackgroundEvent && !(isSessionInit && next.status === "running-idle") && !next.turnOpen) {
|
|
46354
46355
|
next.turnOpen = true;
|
|
46355
46356
|
next.turnStartedAt = deps.now();
|
|
46356
46357
|
}
|
|
@@ -46362,7 +46363,7 @@ function pushEventToBufferInPlace(next, event, deps) {
|
|
|
46362
46363
|
}
|
|
46363
46364
|
if (next.freshSpawn) next.freshSpawn = false;
|
|
46364
46365
|
const effects = [emitSessionEvent(next.file.sessionId, withSeq)];
|
|
46365
|
-
if (!isTurnEnd && !isBackgroundEvent && withSeq.kind !== "meta-text" && next.status === "running-idle" && next.procAlive) {
|
|
46366
|
+
if (!isTurnEnd && !isBackgroundEvent && !isSessionInit && withSeq.kind !== "meta-text" && next.status === "running-idle" && next.procAlive) {
|
|
46366
46367
|
next.status = "running";
|
|
46367
46368
|
effects.push({ kind: "cancel-idle-kill", sessionId: next.file.sessionId });
|
|
46368
46369
|
effects.push({
|
|
@@ -46672,7 +46673,6 @@ function applyCommand(state, command, deps) {
|
|
|
46672
46673
|
void _titleGeneratedAt;
|
|
46673
46674
|
const nextFile = {
|
|
46674
46675
|
...rest,
|
|
46675
|
-
...command.nextCloudExecutionId ? { cloudExecutionId: command.nextCloudExecutionId } : {},
|
|
46676
46676
|
...command.nextToolSessionId ? { toolSessionId: command.nextToolSessionId } : {},
|
|
46677
46677
|
updatedAt: nowIso(deps)
|
|
46678
46678
|
};
|
|
@@ -46735,18 +46735,6 @@ function reduceSessionInner(state, input, deps) {
|
|
|
46735
46735
|
case "inject-events": {
|
|
46736
46736
|
return applyEventBatch(state, input.events, deps);
|
|
46737
46737
|
}
|
|
46738
|
-
case "cloud-recovery-absent": {
|
|
46739
|
-
if (!state.file.cloudPendingCommand) return { state, effects: [] };
|
|
46740
|
-
const next = cloneState(state);
|
|
46741
|
-
next.file = { ...next.file, cloudPendingCommand: void 0, cloudGatewaySessionId: void 0 };
|
|
46742
|
-
return { state: next, effects: [{ kind: "persist-file", file: next.file }, sessionInfoFrame(next.file)] };
|
|
46743
|
-
}
|
|
46744
|
-
case "cloud-gateway-ready": {
|
|
46745
|
-
if (state.file.cloudGatewaySessionId === input.gatewaySessionId) return { state, effects: [] };
|
|
46746
|
-
const next = cloneState(state);
|
|
46747
|
-
next.file = { ...next.file, cloudGatewaySessionId: input.gatewaySessionId };
|
|
46748
|
-
return { state: next, effects: [{ kind: "persist-file", file: next.file }] };
|
|
46749
|
-
}
|
|
46750
46738
|
case "cloud-command-prepared": {
|
|
46751
46739
|
const pending = state.file.cloudPendingCommand;
|
|
46752
46740
|
const turn = state.file.cloudPendingTurns?.find((item) => item.id === input.commandId);
|
|
@@ -47452,7 +47440,7 @@ var SessionRunner = class {
|
|
|
47452
47440
|
applyEffect(effect) {
|
|
47453
47441
|
switch (effect.kind) {
|
|
47454
47442
|
case "spawn":
|
|
47455
|
-
this.doSpawn(
|
|
47443
|
+
this.doSpawn(effect.ctx);
|
|
47456
47444
|
break;
|
|
47457
47445
|
case "kill":
|
|
47458
47446
|
if (this.session) {
|
|
@@ -47601,15 +47589,6 @@ var SessionRunner = class {
|
|
|
47601
47589
|
kind: CLOUD_HISTORY_REFRESH_KIND,
|
|
47602
47590
|
synchronized
|
|
47603
47591
|
}, "broadcast"),
|
|
47604
|
-
onRecoveryAbsent: () => {
|
|
47605
|
-
this.input({ kind: "cloud-recovery-absent" });
|
|
47606
|
-
this.hooks.broadcastFrame({ type: "session:control", sessionId: this.state.file.sessionId, kind: CLOUD_HISTORY_REFRESH_KIND, synchronized: true }, "broadcast");
|
|
47607
|
-
},
|
|
47608
|
-
onGatewayReady: (gatewaySessionId) => {
|
|
47609
|
-
if (this.state.file.cloudGatewaySessionId === gatewaySessionId) return;
|
|
47610
|
-
this.hooks.store.write({ ...this.state.file, cloudGatewaySessionId: gatewaySessionId });
|
|
47611
|
-
this.input({ kind: "cloud-gateway-ready", gatewaySessionId });
|
|
47612
|
-
},
|
|
47613
47592
|
onCommandPrepared: (commandId, text, prepared) => {
|
|
47614
47593
|
const pending = this.state.file.cloudPendingTurns?.find((turn) => turn.id === commandId) ?? this.state.file.cloudPendingCommand;
|
|
47615
47594
|
if (!pending || pending.id !== commandId || prepared && pending.text !== text) return false;
|
|
@@ -49012,7 +48991,7 @@ var SessionManager = class {
|
|
|
49012
48991
|
}
|
|
49013
48992
|
return { response: normalized, broadcast };
|
|
49014
48993
|
}
|
|
49015
|
-
newSession(args
|
|
48994
|
+
newSession(args) {
|
|
49016
48995
|
const existingFile = this.getFile(args.sessionId);
|
|
49017
48996
|
this.titleGenPending.get(args.sessionId)?.abort();
|
|
49018
48997
|
this.titleGenPending.delete(args.sessionId);
|
|
@@ -49023,7 +49002,7 @@ var SessionManager = class {
|
|
|
49023
49002
|
const { value, broadcast } = this.withCollector(() => {
|
|
49024
49003
|
runner.input({
|
|
49025
49004
|
kind: "command",
|
|
49026
|
-
command: { kind: "new", ...nextToolSessionId ? { nextToolSessionId } : {}
|
|
49005
|
+
command: { kind: "new", ...nextToolSessionId ? { nextToolSessionId } : {} }
|
|
49027
49006
|
});
|
|
49028
49007
|
return runner.getState().file;
|
|
49029
49008
|
});
|
|
@@ -49059,7 +49038,6 @@ var SessionManager = class {
|
|
|
49059
49038
|
void _titleGeneratedAt;
|
|
49060
49039
|
const updated = {
|
|
49061
49040
|
...rest,
|
|
49062
|
-
...nextCloudExecutionId ? { cloudExecutionId: nextCloudExecutionId } : {},
|
|
49063
49041
|
...nextToolSessionId ? { toolSessionId: nextToolSessionId } : {},
|
|
49064
49042
|
updatedAt: nowIso2(this.deps)
|
|
49065
49043
|
};
|
|
@@ -49073,7 +49051,7 @@ var SessionManager = class {
|
|
|
49073
49051
|
if (!this.cloudCancel) throw new Error("cloud canceller is not configured");
|
|
49074
49052
|
await this.cloudCancel(file, runner);
|
|
49075
49053
|
} else runner?.confirmCloudCancelled();
|
|
49076
|
-
return this.newSession(args
|
|
49054
|
+
return this.newSession(args);
|
|
49077
49055
|
}
|
|
49078
49056
|
return this.newSession(args);
|
|
49079
49057
|
}
|
|
@@ -52928,9 +52906,9 @@ var CentralClientError = class extends Error {
|
|
|
52928
52906
|
cause;
|
|
52929
52907
|
status;
|
|
52930
52908
|
};
|
|
52931
|
-
async function centralRequest(opts,
|
|
52909
|
+
async function centralRequest(opts, path106, init) {
|
|
52932
52910
|
const f2 = opts.fetchImpl ?? globalThis.fetch;
|
|
52933
|
-
const url = `${opts.api.replace(/\/+$/, "")}${
|
|
52911
|
+
const url = `${opts.api.replace(/\/+$/, "")}${path106}`;
|
|
52934
52912
|
const ctrl = new AbortController();
|
|
52935
52913
|
const timer = setTimeout(() => ctrl.abort(), opts.timeoutMs ?? 15e3);
|
|
52936
52914
|
let res;
|
|
@@ -53966,8 +53944,8 @@ function turnStartInput(text, resolveImage) {
|
|
|
53966
53944
|
const items = [];
|
|
53967
53945
|
let leftover = text;
|
|
53968
53946
|
for (const m3 of text.matchAll(SKILL_RE)) {
|
|
53969
|
-
const [marker, name,
|
|
53970
|
-
items.push({ type: "skill", name, path:
|
|
53947
|
+
const [marker, name, path106] = m3;
|
|
53948
|
+
items.push({ type: "skill", name, path: path106 });
|
|
53971
53949
|
leftover = leftover.replace(marker, "");
|
|
53972
53950
|
}
|
|
53973
53951
|
for (const m3 of text.matchAll(ATTACHMENT_RE2)) {
|
|
@@ -61342,10 +61320,10 @@ function createGithubApi(args) {
|
|
|
61342
61320
|
const doFetch = args.fetch ?? fetch;
|
|
61343
61321
|
const seal = args.seal ?? sealWithSodium;
|
|
61344
61322
|
const timeoutMs = args.timeoutMs ?? TIMEOUT_MS;
|
|
61345
|
-
async function request(method,
|
|
61323
|
+
async function request(method, path106, body) {
|
|
61346
61324
|
let res;
|
|
61347
61325
|
try {
|
|
61348
|
-
res = await doFetch(`${API}${
|
|
61326
|
+
res = await doFetch(`${API}${path106}`, {
|
|
61349
61327
|
method,
|
|
61350
61328
|
headers: {
|
|
61351
61329
|
Authorization: `Bearer ${args.token}`,
|
|
@@ -61370,8 +61348,8 @@ function createGithubApi(args) {
|
|
|
61370
61348
|
}
|
|
61371
61349
|
return { status: res.status, json };
|
|
61372
61350
|
}
|
|
61373
|
-
async function must(method,
|
|
61374
|
-
const r2 = await request(method,
|
|
61351
|
+
async function must(method, path106, what, body) {
|
|
61352
|
+
const r2 = await request(method, path106, body);
|
|
61375
61353
|
if (r2.status < 200 || r2.status >= 300) throw new GithubApiError(r2.status, explain(r2.status, what, r2.json));
|
|
61376
61354
|
return r2.json;
|
|
61377
61355
|
}
|
|
@@ -61416,9 +61394,9 @@ function createGithubApi(args) {
|
|
|
61416
61394
|
return { env: x2.name, ...Number.isFinite(at3) ? { setAt: at3 } : {} };
|
|
61417
61395
|
});
|
|
61418
61396
|
},
|
|
61419
|
-
async getJson(
|
|
61397
|
+
async getJson(path106) {
|
|
61420
61398
|
try {
|
|
61421
|
-
const r2 = await request("GET",
|
|
61399
|
+
const r2 = await request("GET", path106);
|
|
61422
61400
|
return r2.status >= 200 && r2.status < 300 ? r2.json : void 0;
|
|
61423
61401
|
} catch {
|
|
61424
61402
|
return void 0;
|
|
@@ -62970,8 +62948,8 @@ function refreshPathFromLoginShell() {
|
|
|
62970
62948
|
timeout: 3e3,
|
|
62971
62949
|
stdio: ["ignore", "pipe", "ignore"]
|
|
62972
62950
|
});
|
|
62973
|
-
const
|
|
62974
|
-
if (
|
|
62951
|
+
const path106 = out.trim();
|
|
62952
|
+
if (path106) process.env.PATH = path106;
|
|
62975
62953
|
} catch {
|
|
62976
62954
|
}
|
|
62977
62955
|
}
|
|
@@ -63773,10 +63751,10 @@ function createCloudPersonaBotClient(opts) {
|
|
|
63773
63751
|
const f2 = opts.fetchImpl ?? fetch;
|
|
63774
63752
|
const base = opts.api.replace(/\/+$/, "");
|
|
63775
63753
|
const route = (personaId2) => `/api/lark-bot/cloud/${encodeURIComponent(personaId2)}`;
|
|
63776
|
-
async function request(method,
|
|
63754
|
+
async function request(method, path106, body) {
|
|
63777
63755
|
const pass = opts.getLoginPass();
|
|
63778
63756
|
if (!pass) throw new LarkBotCloudError("\u98DE\u4E66\u767B\u5F55\u540E\u624D\u80FD\u7BA1\u7406\u4E91 Persona \u7684 Bot", 401);
|
|
63779
|
-
const response = await f2(base +
|
|
63757
|
+
const response = await f2(base + path106, {
|
|
63780
63758
|
method,
|
|
63781
63759
|
headers: { authorization: `Bearer ${pass}`, "content-type": "application/json" },
|
|
63782
63760
|
...body ? { body: JSON.stringify(body) } : {},
|
|
@@ -63785,7 +63763,7 @@ function createCloudPersonaBotClient(opts) {
|
|
|
63785
63763
|
const json = await response.json().catch(() => ({}));
|
|
63786
63764
|
if (!response.ok) {
|
|
63787
63765
|
const detail = typeof json.message === "string" ? json.message : `HTTP ${response.status}`;
|
|
63788
|
-
throw new LarkBotCloudError(`cloud bot ${method} ${
|
|
63766
|
+
throw new LarkBotCloudError(`cloud bot ${method} ${path106}: ${detail}`, response.status);
|
|
63789
63767
|
}
|
|
63790
63768
|
return json;
|
|
63791
63769
|
}
|
|
@@ -64771,16 +64749,8 @@ async function forwardPeerExecToPeer(args) {
|
|
|
64771
64749
|
init_protocol();
|
|
64772
64750
|
init_protocol();
|
|
64773
64751
|
var CLOUD_WORKSPACE_SLOT = "{{WORKSPACE}}";
|
|
64774
|
-
var CLOUD_TURN_HEADER = "x-clawd-turn";
|
|
64775
|
-
var CLOUD_TURN_HEADER_START = "start";
|
|
64776
64752
|
var GATEWAY_ROUTES = {
|
|
64777
64753
|
healthz: () => "/healthz",
|
|
64778
|
-
session: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session`,
|
|
64779
|
-
sessionSend: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/${encodeURIComponent(sessionId)}`,
|
|
64780
|
-
sessionMirror: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/${encodeURIComponent(sessionId)}/mirror`,
|
|
64781
|
-
eventSession: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session/events`,
|
|
64782
|
-
eventCancel: (personaId2) => `/p/${encodeURIComponent(personaId2)}/session/events:cancel`,
|
|
64783
|
-
eventSend: (personaId2, sessionId) => `/p/${encodeURIComponent(personaId2)}/session/events/${encodeURIComponent(sessionId)}`,
|
|
64784
64754
|
turn: (personaId2) => `/p/${encodeURIComponent(personaId2)}/v1/chat/completions`,
|
|
64785
64755
|
turnCommand: (personaId2, turnId) => `/p/${encodeURIComponent(personaId2)}/turns/${encodeURIComponent(turnId)}/commands`,
|
|
64786
64756
|
conversationCancel: (personaId2, conversationId) => `/p/${encodeURIComponent(personaId2)}/conversations/${encodeURIComponent(conversationId)}:cancel`,
|
|
@@ -64882,49 +64852,6 @@ var CloudGatewayClient = class {
|
|
|
64882
64852
|
const list = await this.fetchDeployments(trimSlash(gatewayUrl));
|
|
64883
64853
|
return list.find((p3) => p3.personaId === gatewayPersonaId)?.connectors ?? [];
|
|
64884
64854
|
}
|
|
64885
|
-
/**
|
|
64886
|
-
* 会话通道。返回的行流在 Pod 就绪前就能 write:写入先攒着,收到 `ready` 控制行后按序 POST 出去——
|
|
64887
|
-
* 编排那头一构造就发 initialize,不用知道 Pod 还在起。
|
|
64888
|
-
* `toolSessionId`:调用方预分配的引擎会话 id(pi 的 --session-id;codex 的 thread id 是协议内的、不传),进 open 的 body `engineSessionId`
|
|
64889
|
-
* (契约 2026-09-18 §3.2)。`instructions`:会话级指令(pi-cloud 的连接 intro,工作目录写 CLOUD_WORKSPACE_SLOT),进 body `instructions`,
|
|
64890
|
-
* gateway 落成 Pod 里的 /run/agent/instructions.md(契约 §3.1);codex-cloud 不发(走协议内 developerInstructions)。
|
|
64891
|
-
* `expectedEngine` 是 session 创建时的引擎;gateway 在起 Pod 前与当前发布核对。
|
|
64892
|
-
*/
|
|
64893
|
-
async openSession(personaId2, opts = {}) {
|
|
64894
|
-
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64895
|
-
return openHttpLineStream({
|
|
64896
|
-
fetchImpl: this.fetchImpl,
|
|
64897
|
-
gatewayUrl,
|
|
64898
|
-
apiKey,
|
|
64899
|
-
personaId: personaId2,
|
|
64900
|
-
...opts.toolSessionId ? { engineSessionId: opts.toolSessionId } : {},
|
|
64901
|
-
...opts.instructions ? { instructions: opts.instructions } : {},
|
|
64902
|
-
...opts.purpose ? { purpose: opts.purpose } : {},
|
|
64903
|
-
...opts.expectedEngine ? { expectedEngine: opts.expectedEngine } : {},
|
|
64904
|
-
logger: this.deps.logger
|
|
64905
|
-
});
|
|
64906
|
-
}
|
|
64907
|
-
async openEventSession(personaId2, opts) {
|
|
64908
|
-
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64909
|
-
const health = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
|
|
64910
|
-
if (!health.ok || (await health.json()).sessionProtocolVersion !== 2) throw new Error("\u4E91 gateway \u7684\u4F1A\u8BDD\u534F\u8BAE\u7248\u672C\u4E0D\u5339\u914D\uFF0C\u8BF7\u5148\u5347\u7EA7 gateway");
|
|
64911
|
-
return openHttpEventSession({
|
|
64912
|
-
fetchImpl: this.fetchImpl,
|
|
64913
|
-
gatewayUrl,
|
|
64914
|
-
apiKey,
|
|
64915
|
-
personaId: personaId2,
|
|
64916
|
-
clientSessionId: opts.clientSessionId,
|
|
64917
|
-
gatewaySessionId: opts.gatewaySessionId,
|
|
64918
|
-
engineSessionId: opts.toolSessionId,
|
|
64919
|
-
instructions: opts.instructions,
|
|
64920
|
-
purpose: opts.purpose,
|
|
64921
|
-
expectedEngine: opts.expectedEngine,
|
|
64922
|
-
effort: opts.effort,
|
|
64923
|
-
personaMode: opts.personaMode,
|
|
64924
|
-
attachOnly: opts.attachOnly,
|
|
64925
|
-
logger: this.deps.logger
|
|
64926
|
-
});
|
|
64927
|
-
}
|
|
64928
64855
|
async openTurn(personaId2, opts) {
|
|
64929
64856
|
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64930
64857
|
const health = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.healthz());
|
|
@@ -64951,23 +64878,6 @@ var CloudGatewayClient = class {
|
|
|
64951
64878
|
});
|
|
64952
64879
|
if (!res.ok) throw new Error(`gateway conversation cancel returned ${res.status}`);
|
|
64953
64880
|
}
|
|
64954
|
-
async cancelEventSession(personaId2, clientSessionId, gatewaySessionId) {
|
|
64955
|
-
const { apiKey, gatewayUrl } = await this.credentials();
|
|
64956
|
-
const res = await this.fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventCancel(personaId2), {
|
|
64957
|
-
method: "POST",
|
|
64958
|
-
headers: { authorization: `Bearer ${apiKey}`, "content-type": "application/json" },
|
|
64959
|
-
body: JSON.stringify({ protocolVersion: 2, clientSessionId, gatewaySessionId })
|
|
64960
|
-
});
|
|
64961
|
-
if (!res.ok) {
|
|
64962
|
-
let message = `gateway \u56DE ${res.status}`;
|
|
64963
|
-
try {
|
|
64964
|
-
const body = await res.json();
|
|
64965
|
-
if (typeof body.message === "string") message = body.message;
|
|
64966
|
-
} catch {
|
|
64967
|
-
}
|
|
64968
|
-
throw new Error(message);
|
|
64969
|
-
}
|
|
64970
|
-
}
|
|
64971
64881
|
/**
|
|
64972
64882
|
* 看板数据(design 2026-09-23-cloud-persona-metrics §3.8):GET /metrics/<persona>?window&entry,**原样回**状态码与 body——
|
|
64973
64883
|
* 形状真源在 gateway 的 cloud-persona-metrics,daemon 只是替浏览器拿本机 api key 转一跳。拿不到 key / 连不上 / 超时 → 抛(路由折成 502)。
|
|
@@ -65024,7 +64934,7 @@ var CloudGatewayClient = class {
|
|
|
65024
64934
|
}
|
|
65025
64935
|
};
|
|
65026
64936
|
function openHttpTurn(opts) {
|
|
65027
|
-
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, conversationId, turnId, text, expectedEngine, engineSessionId, instructions, effort, personaMode, logger } = opts;
|
|
64937
|
+
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, conversationId, turnId, text, expectedEngine, engineSessionId, instructions, effort, personaMode, purpose, logger } = opts;
|
|
65028
64938
|
const body = JSON.stringify({
|
|
65029
64939
|
messages: [{ role: "user", content: text }],
|
|
65030
64940
|
stream: true,
|
|
@@ -65033,6 +64943,7 @@ function openHttpTurn(opts) {
|
|
|
65033
64943
|
conversationId,
|
|
65034
64944
|
turnId,
|
|
65035
64945
|
expectedEngine,
|
|
64946
|
+
...purpose ? { purpose } : {},
|
|
65036
64947
|
...engineSessionId ? { engineSessionId } : {},
|
|
65037
64948
|
...instructions ? { instructions } : {},
|
|
65038
64949
|
...effort ? { effort } : {},
|
|
@@ -65169,525 +65080,12 @@ function openHttpTurn(opts) {
|
|
|
65169
65080
|
close: finish
|
|
65170
65081
|
};
|
|
65171
65082
|
}
|
|
65172
|
-
function openHttpEventSession(opts) {
|
|
65173
|
-
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, clientSessionId, gatewaySessionId, engineSessionId, instructions, purpose, effort, personaMode, attachOnly, expectedEngine, logger } = opts;
|
|
65174
|
-
const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
|
|
65175
|
-
let abort = new AbortController();
|
|
65176
|
-
const eventCbs = [];
|
|
65177
|
-
const controlCbs = [];
|
|
65178
|
-
const closeCbs = [];
|
|
65179
|
-
const earlyEvents = [];
|
|
65180
|
-
const earlyControls = [];
|
|
65181
|
-
let closed = false;
|
|
65182
|
-
let readyControl = null;
|
|
65183
|
-
let errorControl = null;
|
|
65184
|
-
let sessionId = gatewaySessionId ?? null;
|
|
65185
|
-
let lastSeq = 0;
|
|
65186
|
-
let everReady = false;
|
|
65187
|
-
let connected = false;
|
|
65188
|
-
const attachWaiters = [];
|
|
65189
|
-
let resolveReady;
|
|
65190
|
-
let rejectReady;
|
|
65191
|
-
const ready = new Promise((resolve9, reject) => {
|
|
65192
|
-
resolveReady = resolve9;
|
|
65193
|
-
rejectReady = reject;
|
|
65194
|
-
});
|
|
65195
|
-
void ready.catch(() => {
|
|
65196
|
-
});
|
|
65197
|
-
let sendChain = Promise.resolve();
|
|
65198
|
-
const emitControl = (control) => {
|
|
65199
|
-
if (control.kind === "ready") readyControl = control;
|
|
65200
|
-
if (control.kind === "error") errorControl = control;
|
|
65201
|
-
if (!controlCbs.length) earlyControls.push(control);
|
|
65202
|
-
for (const cb of controlCbs) cb(control);
|
|
65203
|
-
};
|
|
65204
|
-
const finish = (message) => {
|
|
65205
|
-
if (closed) return;
|
|
65206
|
-
if (message) emitControl({ kind: "error", message });
|
|
65207
|
-
closed = true;
|
|
65208
|
-
rejectReady(new Error(message ?? "event session closed"));
|
|
65209
|
-
abort.abort();
|
|
65210
|
-
for (const resolve9 of attachWaiters.splice(0)) resolve9();
|
|
65211
|
-
for (const cb of closeCbs) cb();
|
|
65212
|
-
};
|
|
65213
|
-
const waitForAttach = () => connected ? Promise.resolve() : new Promise((resolve9) => {
|
|
65214
|
-
attachWaiters.push(resolve9);
|
|
65215
|
-
});
|
|
65216
|
-
const retryWait = () => new Promise((resolve9) => {
|
|
65217
|
-
const timer = setTimeout(resolve9, 250);
|
|
65218
|
-
timer.unref?.();
|
|
65219
|
-
abort.signal.addEventListener("abort", () => {
|
|
65220
|
-
clearTimeout(timer);
|
|
65221
|
-
resolve9();
|
|
65222
|
-
}, { once: true });
|
|
65223
|
-
});
|
|
65224
|
-
void (async () => {
|
|
65225
|
-
while (!closed) {
|
|
65226
|
-
abort = new AbortController();
|
|
65227
|
-
let fatal = false;
|
|
65228
|
-
try {
|
|
65229
|
-
const res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventSession(personaId2), {
|
|
65230
|
-
method: "POST",
|
|
65231
|
-
headers,
|
|
65232
|
-
body: JSON.stringify({ protocolVersion: 2, clientSessionId, afterSeq: lastSeq, ...sessionId ? { gatewaySessionId: sessionId } : {}, expectedEngine, ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {}, ...purpose ? { purpose } : {}, ...effort ? { effort } : {}, ...personaMode ? { personaMode } : {}, ...attachOnly ? { attachOnly: true } : {} }),
|
|
65233
|
-
signal: abort.signal
|
|
65234
|
-
});
|
|
65235
|
-
if (!res.ok || !res.body) {
|
|
65236
|
-
let message = `gateway \u56DE ${res.status}`;
|
|
65237
|
-
let code;
|
|
65238
|
-
try {
|
|
65239
|
-
const body = await res.json();
|
|
65240
|
-
if (typeof body.message === "string") message = body.message;
|
|
65241
|
-
code = body.error;
|
|
65242
|
-
if (body.error === "SESSION_VERSION_EXPIRED" && !message.includes("SESSION_VERSION_EXPIRED")) message = `SESSION_VERSION_EXPIRED: ${message}`;
|
|
65243
|
-
} catch {
|
|
65244
|
-
}
|
|
65245
|
-
if ((attachOnly || sessionId) && res.status === 404 && code === "SESSION_NOT_FOUND") {
|
|
65246
|
-
emitControl({ kind: "closed", reason: "not-found" });
|
|
65247
|
-
finish();
|
|
65248
|
-
return;
|
|
65249
|
-
}
|
|
65250
|
-
if (res.status === 426 || res.status === 400 || res.status === 401 || res.status === 403 || res.status === 409 || res.status === 410 || code === "CLIENT_UPGRADE_REQUIRED") {
|
|
65251
|
-
fatal = true;
|
|
65252
|
-
finish(message);
|
|
65253
|
-
return;
|
|
65254
|
-
}
|
|
65255
|
-
throw new Error(message);
|
|
65256
|
-
}
|
|
65257
|
-
connected = true;
|
|
65258
|
-
for (const resolve9 of attachWaiters.splice(0)) resolve9();
|
|
65259
|
-
const reader = res.body.getReader();
|
|
65260
|
-
const decoder = new TextDecoder();
|
|
65261
|
-
let pending = "";
|
|
65262
|
-
for (; ; ) {
|
|
65263
|
-
const { value, done } = await reader.read();
|
|
65264
|
-
if (done) break;
|
|
65265
|
-
pending += decoder.decode(value, { stream: true });
|
|
65266
|
-
const lines = pending.split("\n");
|
|
65267
|
-
pending = lines.pop() ?? "";
|
|
65268
|
-
for (const line of lines) {
|
|
65269
|
-
if (!line.trim()) continue;
|
|
65270
|
-
const data = JSON.parse(line);
|
|
65271
|
-
if (data.clawd === "events") {
|
|
65272
|
-
if (typeof data.seq === "number") {
|
|
65273
|
-
if (data.seq <= lastSeq) continue;
|
|
65274
|
-
lastSeq = data.seq;
|
|
65275
|
-
}
|
|
65276
|
-
const events = ParsedEventSchema.array().parse(data.events);
|
|
65277
|
-
if (!eventCbs.length) earlyEvents.push(events);
|
|
65278
|
-
for (const cb of eventCbs) cb(events);
|
|
65279
|
-
continue;
|
|
65280
|
-
}
|
|
65281
|
-
const control = parseControlLine(line);
|
|
65282
|
-
if (!control) throw new Error("gateway event stream contains an unknown line");
|
|
65283
|
-
if (control.kind === "ready") {
|
|
65284
|
-
if (!control.session) throw new Error("gateway ready line has no session id");
|
|
65285
|
-
if (control.engine !== expectedEngine) {
|
|
65286
|
-
finish(control.engine ? `SESSION_VERSION_EXPIRED: \u5F53\u524D Pod \u662F ${control.engine}\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u9700\u8981 ${expectedEngine}` : "gateway \u7684 ready \u63A7\u5236\u884C\u6CA1\u5E26 engine\uFF0Cgateway \u592A\u8001\uFF0C\u5148\u5347 gateway");
|
|
65287
|
-
return;
|
|
65288
|
-
}
|
|
65289
|
-
sessionId = control.session;
|
|
65290
|
-
everReady = true;
|
|
65291
|
-
resolveReady();
|
|
65292
|
-
}
|
|
65293
|
-
emitControl(control);
|
|
65294
|
-
if (control.kind === "error") {
|
|
65295
|
-
finish();
|
|
65296
|
-
return;
|
|
65297
|
-
}
|
|
65298
|
-
if (control.kind === "closed") {
|
|
65299
|
-
finish();
|
|
65300
|
-
return;
|
|
65301
|
-
}
|
|
65302
|
-
}
|
|
65303
|
-
}
|
|
65304
|
-
connected = false;
|
|
65305
|
-
} catch (e) {
|
|
65306
|
-
if (!closed) {
|
|
65307
|
-
if (e instanceof SyntaxError || e.name === "ZodError") {
|
|
65308
|
-
finish("gateway event stream contains invalid data");
|
|
65309
|
-
return;
|
|
65310
|
-
}
|
|
65311
|
-
connected = false;
|
|
65312
|
-
logger?.warn("cloud event stream failed; reconnecting", { code: e.code, name: e.name, ready: everReady });
|
|
65313
|
-
}
|
|
65314
|
-
}
|
|
65315
|
-
if (!closed && !fatal) await retryWait();
|
|
65316
|
-
}
|
|
65317
|
-
})();
|
|
65318
|
-
return {
|
|
65319
|
-
send(command) {
|
|
65320
|
-
const next = sendChain.then(async () => {
|
|
65321
|
-
await ready;
|
|
65322
|
-
while (!closed) {
|
|
65323
|
-
await waitForAttach();
|
|
65324
|
-
if (!sessionId) continue;
|
|
65325
|
-
let res;
|
|
65326
|
-
try {
|
|
65327
|
-
res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.eventSend(personaId2, sessionId), { method: "POST", headers, body: JSON.stringify(command) });
|
|
65328
|
-
} catch {
|
|
65329
|
-
connected = false;
|
|
65330
|
-
abort.abort();
|
|
65331
|
-
await retryWait();
|
|
65332
|
-
continue;
|
|
65333
|
-
}
|
|
65334
|
-
if (res.ok) return;
|
|
65335
|
-
if (res.status === 404 || res.status >= 500) {
|
|
65336
|
-
connected = false;
|
|
65337
|
-
abort.abort();
|
|
65338
|
-
await retryWait();
|
|
65339
|
-
continue;
|
|
65340
|
-
}
|
|
65341
|
-
let message = `gateway \u56DE ${res.status}`;
|
|
65342
|
-
try {
|
|
65343
|
-
const body = await res.json();
|
|
65344
|
-
if (typeof body.message === "string") message = body.message;
|
|
65345
|
-
} catch {
|
|
65346
|
-
}
|
|
65347
|
-
throw new Error(message);
|
|
65348
|
-
}
|
|
65349
|
-
throw new Error("event session closed");
|
|
65350
|
-
});
|
|
65351
|
-
sendChain = next.catch(() => {
|
|
65352
|
-
});
|
|
65353
|
-
return next;
|
|
65354
|
-
},
|
|
65355
|
-
onEvents(cb) {
|
|
65356
|
-
const first = !eventCbs.length;
|
|
65357
|
-
eventCbs.push(cb);
|
|
65358
|
-
if (first) for (const events of earlyEvents.splice(0)) cb(events);
|
|
65359
|
-
},
|
|
65360
|
-
onControl(cb) {
|
|
65361
|
-
const first = !controlCbs.length;
|
|
65362
|
-
controlCbs.push(cb);
|
|
65363
|
-
if (first) for (const control of earlyControls.splice(0)) cb(control);
|
|
65364
|
-
else {
|
|
65365
|
-
if (readyControl) cb(readyControl);
|
|
65366
|
-
if (errorControl) cb(errorControl);
|
|
65367
|
-
}
|
|
65368
|
-
},
|
|
65369
|
-
onClose(cb) {
|
|
65370
|
-
closeCbs.push(cb);
|
|
65371
|
-
if (closed) cb();
|
|
65372
|
-
},
|
|
65373
|
-
close() {
|
|
65374
|
-
finish();
|
|
65375
|
-
}
|
|
65376
|
-
};
|
|
65377
|
-
}
|
|
65378
|
-
function parseControlLine(line) {
|
|
65379
|
-
let o2;
|
|
65380
|
-
try {
|
|
65381
|
-
o2 = JSON.parse(line);
|
|
65382
|
-
} catch {
|
|
65383
|
-
return null;
|
|
65384
|
-
}
|
|
65385
|
-
if (!o2 || typeof o2 !== "object" || !("clawd" in o2)) return null;
|
|
65386
|
-
const r2 = o2;
|
|
65387
|
-
switch (r2.clawd) {
|
|
65388
|
-
case "queued":
|
|
65389
|
-
return { kind: "queued", running: typeof r2.running === "number" ? r2.running : 0 };
|
|
65390
|
-
case "ready":
|
|
65391
|
-
return {
|
|
65392
|
-
kind: "ready",
|
|
65393
|
-
session: typeof r2.session === "string" ? r2.session : "",
|
|
65394
|
-
personaDir: typeof r2.personaDir === "string" ? r2.personaDir : "",
|
|
65395
|
-
workDir: typeof r2.workDir === "string" ? r2.workDir : "",
|
|
65396
|
-
...typeof r2.model === "string" ? { model: r2.model } : {},
|
|
65397
|
-
...typeof r2.engine === "string" ? { engine: r2.engine } : {},
|
|
65398
|
-
...typeof r2.replayGap === "boolean" ? { replayGap: r2.replayGap } : {},
|
|
65399
|
-
...typeof r2.historySynchronized === "boolean" ? { historySynchronized: r2.historySynchronized } : {},
|
|
65400
|
-
...typeof r2.activeTurn === "boolean" ? { activeTurn: r2.activeTurn } : {}
|
|
65401
|
-
};
|
|
65402
|
-
case "error":
|
|
65403
|
-
return { kind: "error", message: typeof r2.message === "string" ? r2.message : "gateway error" };
|
|
65404
|
-
case "closed":
|
|
65405
|
-
return { kind: "closed", reason: typeof r2.reason === "string" ? r2.reason : "unknown" };
|
|
65406
|
-
case "history":
|
|
65407
|
-
return { kind: "history", synchronized: r2.synchronized === true };
|
|
65408
|
-
default:
|
|
65409
|
-
return { kind: "ping" };
|
|
65410
|
-
}
|
|
65411
|
-
}
|
|
65412
|
-
function openHttpLineStream(opts) {
|
|
65413
|
-
const { fetchImpl, gatewayUrl, apiKey, personaId: personaId2, engineSessionId, instructions, purpose, expectedEngine, logger } = opts;
|
|
65414
|
-
const headers = { authorization: `Bearer ${apiKey}`, "content-type": "application/json" };
|
|
65415
|
-
const ac = new AbortController();
|
|
65416
|
-
const lineCbs = [];
|
|
65417
|
-
const closeCbs = [];
|
|
65418
|
-
const controlCbs = [];
|
|
65419
|
-
let sessionId = null;
|
|
65420
|
-
let closed = false;
|
|
65421
|
-
let closedWith = null;
|
|
65422
|
-
let readyWith = null;
|
|
65423
|
-
const pending = [];
|
|
65424
|
-
let nextIsTurnStart = false;
|
|
65425
|
-
let sendChain = Promise.resolve();
|
|
65426
|
-
const finish = () => {
|
|
65427
|
-
if (closed) return;
|
|
65428
|
-
closed = true;
|
|
65429
|
-
for (const cb of closeCbs) cb();
|
|
65430
|
-
};
|
|
65431
|
-
const emitControl = (c2) => {
|
|
65432
|
-
if (c2.kind === "error") closedWith = c2;
|
|
65433
|
-
if (c2.kind === "ready") readyWith = c2;
|
|
65434
|
-
for (const cb of controlCbs) cb(c2);
|
|
65435
|
-
};
|
|
65436
|
-
const fail = (message) => {
|
|
65437
|
-
if (closed) return;
|
|
65438
|
-
emitControl({ kind: "error", message });
|
|
65439
|
-
ac.abort();
|
|
65440
|
-
finish();
|
|
65441
|
-
};
|
|
65442
|
-
const post = (line, turnStart) => {
|
|
65443
|
-
if (closed || !sessionId) return Promise.resolve();
|
|
65444
|
-
const url = gatewayUrl + GATEWAY_ROUTES.sessionSend(personaId2, sessionId);
|
|
65445
|
-
return fetchImpl(url, { method: "POST", headers: turnStart ? { ...headers, [CLOUD_TURN_HEADER]: CLOUD_TURN_HEADER_START } : headers, body: line + "\n" }).then((res) => {
|
|
65446
|
-
if (res.status === 404) {
|
|
65447
|
-
finish();
|
|
65448
|
-
return;
|
|
65449
|
-
}
|
|
65450
|
-
if (!res.ok) {
|
|
65451
|
-
logger?.warn("cloud session send failed", { status: res.status });
|
|
65452
|
-
fail(
|
|
65453
|
-
res.status === 401 ? "\u8C03\u7528 key \u5DF2\u5931\u6548\uFF08\u64A4\u9500\u6216\u91CD\u65B0\u751F\u6210\u8FC7\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86\u3002\u5230\u300C\u8BBE\u7F6E \u2192 \u8D26\u53F7\u300D\u6216\u8FD9\u4E2A persona \u7684\u5361\u7247\u4E0A\u751F\u6210\u4E00\u628A\uFF0C\u518D\u5F00\u65B0\u4F1A\u8BDD" : `\u4E0A\u884C\u53D1\u4E0D\u51FA\u53BB\uFF08gateway \u56DE ${res.status}\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86`
|
|
65454
|
-
);
|
|
65455
|
-
}
|
|
65456
|
-
}).catch((e) => {
|
|
65457
|
-
if (closed) return;
|
|
65458
|
-
logger?.warn("cloud session send error", { message: e.message });
|
|
65459
|
-
fail(`\u4E0A\u884C\u53D1\u4E0D\u51FA\u53BB\uFF08${e.message}\uFF09\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u65AD\u4E86`);
|
|
65460
|
-
});
|
|
65461
|
-
};
|
|
65462
|
-
const postMirror = async (turn) => {
|
|
65463
|
-
if (closed || !sessionId) return;
|
|
65464
|
-
const url = gatewayUrl + GATEWAY_ROUTES.sessionMirror(personaId2, sessionId);
|
|
65465
|
-
try {
|
|
65466
|
-
const res = await fetchImpl(url, { method: "POST", headers, body: turn ? JSON.stringify({ turn: { outcome: turn.outcome, ...turn.afterFirstByteMs !== void 0 ? { afterFirstByteMs: turn.afterFirstByteMs } : {} } }) : "" });
|
|
65467
|
-
if (!res.ok) logger?.warn("cloud session mirror failed", { status: res.status });
|
|
65468
|
-
} catch (e) {
|
|
65469
|
-
if (!closed) logger?.warn("cloud session mirror error", { message: e.message });
|
|
65470
|
-
}
|
|
65471
|
-
};
|
|
65472
|
-
const flush = () => {
|
|
65473
|
-
for (const { line, turnStart } of pending.splice(0)) sendChain = sendChain.then(() => post(line, turnStart));
|
|
65474
|
-
};
|
|
65475
|
-
void (async () => {
|
|
65476
|
-
let res;
|
|
65477
|
-
try {
|
|
65478
|
-
res = await fetchImpl(gatewayUrl + GATEWAY_ROUTES.session(personaId2), {
|
|
65479
|
-
method: "POST",
|
|
65480
|
-
headers,
|
|
65481
|
-
body: JSON.stringify({ ...engineSessionId ? { engineSessionId } : {}, ...instructions ? { instructions } : {}, ...purpose ? { purpose } : {}, ...expectedEngine ? { expectedEngine } : {} }),
|
|
65482
|
-
signal: ac.signal
|
|
65483
|
-
});
|
|
65484
|
-
} catch (e) {
|
|
65485
|
-
if (!closed) emitControl({ kind: "error", message: `\u8FDE\u4E0D\u4E0A gateway\uFF1A${e.message}` });
|
|
65486
|
-
finish();
|
|
65487
|
-
return;
|
|
65488
|
-
}
|
|
65489
|
-
if (!res.ok || !res.body) {
|
|
65490
|
-
let message = `gateway \u56DE ${res.status}`;
|
|
65491
|
-
try {
|
|
65492
|
-
const body = await res.json();
|
|
65493
|
-
if (typeof body.message === "string") message = body.message;
|
|
65494
|
-
else if (typeof body.error === "string") message = body.error;
|
|
65495
|
-
if (body.error === "SESSION_VERSION_EXPIRED" && !message.includes("SESSION_VERSION_EXPIRED")) message = `SESSION_VERSION_EXPIRED: ${message}`;
|
|
65496
|
-
} catch {
|
|
65497
|
-
}
|
|
65498
|
-
emitControl({ kind: "error", message });
|
|
65499
|
-
finish();
|
|
65500
|
-
return;
|
|
65501
|
-
}
|
|
65502
|
-
const reader = res.body.getReader();
|
|
65503
|
-
const decoder = new TextDecoder();
|
|
65504
|
-
let buf = "";
|
|
65505
|
-
let stop = false;
|
|
65506
|
-
try {
|
|
65507
|
-
for (; ; ) {
|
|
65508
|
-
if (stop) break;
|
|
65509
|
-
const { value, done } = await reader.read();
|
|
65510
|
-
if (done) break;
|
|
65511
|
-
buf += decoder.decode(value, { stream: true });
|
|
65512
|
-
const lines = buf.split("\n");
|
|
65513
|
-
buf = lines.pop() ?? "";
|
|
65514
|
-
for (const raw of lines) {
|
|
65515
|
-
const line = raw.trim();
|
|
65516
|
-
if (!line) continue;
|
|
65517
|
-
const control = parseControlLine(line);
|
|
65518
|
-
if (control) {
|
|
65519
|
-
if (control.kind === "ready") {
|
|
65520
|
-
if (!control.session) {
|
|
65521
|
-
emitControl({ kind: "error", message: "gateway \u7684 ready \u63A7\u5236\u884C\u6CA1\u5E26 session id" });
|
|
65522
|
-
stop = true;
|
|
65523
|
-
ac.abort();
|
|
65524
|
-
void reader.cancel().catch(() => {
|
|
65525
|
-
});
|
|
65526
|
-
break;
|
|
65527
|
-
}
|
|
65528
|
-
if (!control.personaDir || !control.workDir) {
|
|
65529
|
-
emitControl({ kind: "error", message: "gateway \u7684 ready \u63A7\u5236\u884C\u6CA1\u5E26 Pod \u8DEF\u5F84\uFF08personaDir / workDir\uFF09\uFF0Cgateway \u592A\u8001\uFF0C\u5148\u5347 gateway" });
|
|
65530
|
-
stop = true;
|
|
65531
|
-
ac.abort();
|
|
65532
|
-
void reader.cancel().catch(() => {
|
|
65533
|
-
});
|
|
65534
|
-
break;
|
|
65535
|
-
}
|
|
65536
|
-
if (expectedEngine && control.engine !== expectedEngine) {
|
|
65537
|
-
emitControl({ kind: "error", message: control.engine ? `SESSION_VERSION_EXPIRED: \u5F53\u524D Pod \u662F ${control.engine}\uFF0C\u8FD9\u6761\u4F1A\u8BDD\u9700\u8981 ${expectedEngine}` : "gateway \u7684 ready \u63A7\u5236\u884C\u6CA1\u5E26 engine\uFF0Cgateway \u592A\u8001\uFF0C\u5148\u5347 gateway" });
|
|
65538
|
-
stop = true;
|
|
65539
|
-
ac.abort();
|
|
65540
|
-
void reader.cancel().catch(() => {
|
|
65541
|
-
});
|
|
65542
|
-
break;
|
|
65543
|
-
}
|
|
65544
|
-
sessionId = control.session;
|
|
65545
|
-
flush();
|
|
65546
|
-
}
|
|
65547
|
-
emitControl(control);
|
|
65548
|
-
if (control.kind === "error") {
|
|
65549
|
-
stop = true;
|
|
65550
|
-
ac.abort();
|
|
65551
|
-
void reader.cancel().catch(() => {
|
|
65552
|
-
});
|
|
65553
|
-
break;
|
|
65554
|
-
}
|
|
65555
|
-
continue;
|
|
65556
|
-
}
|
|
65557
|
-
for (const cb of lineCbs) cb(line);
|
|
65558
|
-
}
|
|
65559
|
-
}
|
|
65560
|
-
} catch (e) {
|
|
65561
|
-
if (!closed && !ac.signal.aborted) logger?.warn("cloud session stream broke", { message: e.message });
|
|
65562
|
-
}
|
|
65563
|
-
finish();
|
|
65564
|
-
})();
|
|
65565
|
-
return {
|
|
65566
|
-
write: (line) => {
|
|
65567
|
-
if (closed) return;
|
|
65568
|
-
pending.push({ line, turnStart: nextIsTurnStart });
|
|
65569
|
-
nextIsTurnStart = false;
|
|
65570
|
-
if (sessionId) flush();
|
|
65571
|
-
},
|
|
65572
|
-
markNextLineTurnStart: () => {
|
|
65573
|
-
nextIsTurnStart = true;
|
|
65574
|
-
},
|
|
65575
|
-
onLine: (cb) => {
|
|
65576
|
-
lineCbs.push(cb);
|
|
65577
|
-
},
|
|
65578
|
-
onClose: (cb) => {
|
|
65579
|
-
closeCbs.push(cb);
|
|
65580
|
-
if (closed) cb();
|
|
65581
|
-
},
|
|
65582
|
-
onControl: (cb) => {
|
|
65583
|
-
controlCbs.push(cb);
|
|
65584
|
-
if (readyWith) cb(readyWith);
|
|
65585
|
-
if (closedWith) cb(closedWith);
|
|
65586
|
-
},
|
|
65587
|
-
close: () => {
|
|
65588
|
-
ac.abort();
|
|
65589
|
-
finish();
|
|
65590
|
-
},
|
|
65591
|
-
mirror: (turn) => {
|
|
65592
|
-
if (closed || !sessionId) return Promise.resolve();
|
|
65593
|
-
const p3 = sendChain.then(() => postMirror(turn));
|
|
65594
|
-
sendChain = p3;
|
|
65595
|
-
return p3;
|
|
65596
|
-
}
|
|
65597
|
-
};
|
|
65598
|
-
}
|
|
65599
|
-
|
|
65600
|
-
// src/cloud/cancel-outbox.ts
|
|
65601
|
-
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
65602
|
-
var import_node_path44 = __toESM(require("path"), 1);
|
|
65603
|
-
var CloudCancelOutbox = class {
|
|
65604
|
-
constructor(dir, send2, logger) {
|
|
65605
|
-
this.dir = dir;
|
|
65606
|
-
this.send = send2;
|
|
65607
|
-
this.logger = logger;
|
|
65608
|
-
}
|
|
65609
|
-
dir;
|
|
65610
|
-
send;
|
|
65611
|
-
logger;
|
|
65612
|
-
timer = null;
|
|
65613
|
-
inFlight = /* @__PURE__ */ new Set();
|
|
65614
|
-
record(clientSessionId, personaId2, gatewaySessionId) {
|
|
65615
|
-
if (!clientSessionId || !personaId2 || !gatewaySessionId) throw new Error("cloud cancel requires client, gateway and persona IDs");
|
|
65616
|
-
import_node_fs39.default.mkdirSync(this.dir, { recursive: true, mode: 448 });
|
|
65617
|
-
const target = this.pathFor(clientSessionId);
|
|
65618
|
-
const temporary = `${target}.tmp-${process.pid}-${Date.now()}`;
|
|
65619
|
-
import_node_fs39.default.writeFileSync(temporary, JSON.stringify({ clientSessionId, personaId: personaId2, gatewaySessionId }), { mode: 384 });
|
|
65620
|
-
import_node_fs39.default.renameSync(temporary, target);
|
|
65621
|
-
this.inFlight.add(clientSessionId);
|
|
65622
|
-
}
|
|
65623
|
-
confirm(clientSessionId) {
|
|
65624
|
-
import_node_fs39.default.rmSync(this.pathFor(clientSessionId), { force: true });
|
|
65625
|
-
this.inFlight.delete(clientSessionId);
|
|
65626
|
-
}
|
|
65627
|
-
release(clientSessionId) {
|
|
65628
|
-
this.inFlight.delete(clientSessionId);
|
|
65629
|
-
}
|
|
65630
|
-
async request(clientSessionId, personaId2, gatewaySessionId) {
|
|
65631
|
-
this.record(clientSessionId, personaId2, gatewaySessionId);
|
|
65632
|
-
try {
|
|
65633
|
-
await this.send(personaId2, clientSessionId, gatewaySessionId);
|
|
65634
|
-
this.confirm(clientSessionId);
|
|
65635
|
-
} catch (e) {
|
|
65636
|
-
this.release(clientSessionId);
|
|
65637
|
-
throw e;
|
|
65638
|
-
}
|
|
65639
|
-
}
|
|
65640
|
-
async flush() {
|
|
65641
|
-
let names;
|
|
65642
|
-
try {
|
|
65643
|
-
names = import_node_fs39.default.readdirSync(this.dir).filter((name) => name.endsWith(".json"));
|
|
65644
|
-
} catch (e) {
|
|
65645
|
-
if (e.code === "ENOENT") return;
|
|
65646
|
-
throw e;
|
|
65647
|
-
}
|
|
65648
|
-
for (const name of names) {
|
|
65649
|
-
const target = import_node_path44.default.join(this.dir, name);
|
|
65650
|
-
let pending;
|
|
65651
|
-
try {
|
|
65652
|
-
pending = JSON.parse(import_node_fs39.default.readFileSync(target, "utf8"));
|
|
65653
|
-
} catch {
|
|
65654
|
-
continue;
|
|
65655
|
-
}
|
|
65656
|
-
if (!pending.clientSessionId || !pending.personaId || !pending.gatewaySessionId || this.pathFor(pending.clientSessionId) !== target) continue;
|
|
65657
|
-
if (this.inFlight.has(pending.clientSessionId)) continue;
|
|
65658
|
-
this.inFlight.add(pending.clientSessionId);
|
|
65659
|
-
try {
|
|
65660
|
-
await this.send(pending.personaId, pending.clientSessionId, pending.gatewaySessionId);
|
|
65661
|
-
import_node_fs39.default.rmSync(target, { force: true });
|
|
65662
|
-
} catch (e) {
|
|
65663
|
-
this.logger?.warn("cloud cancel pending", { sessionId: pending.clientSessionId, error: e.message });
|
|
65664
|
-
} finally {
|
|
65665
|
-
this.inFlight.delete(pending.clientSessionId);
|
|
65666
|
-
}
|
|
65667
|
-
}
|
|
65668
|
-
}
|
|
65669
|
-
start() {
|
|
65670
|
-
if (this.timer) return;
|
|
65671
|
-
const retry = () => void this.flush().catch((e) => this.logger?.warn("cloud cancel outbox flush failed", { error: e.message }));
|
|
65672
|
-
retry();
|
|
65673
|
-
this.timer = setInterval(retry, 3e4);
|
|
65674
|
-
this.timer.unref?.();
|
|
65675
|
-
}
|
|
65676
|
-
stop() {
|
|
65677
|
-
if (this.timer) clearInterval(this.timer);
|
|
65678
|
-
this.timer = null;
|
|
65679
|
-
}
|
|
65680
|
-
pathFor(clientSessionId) {
|
|
65681
|
-
return import_node_path44.default.join(this.dir, `${safeFileName(clientSessionId)}.json`);
|
|
65682
|
-
}
|
|
65683
|
-
};
|
|
65684
65083
|
|
|
65685
65084
|
// src/tools/codex-cloud.ts
|
|
65686
65085
|
init_protocol();
|
|
65687
65086
|
|
|
65688
65087
|
// src/tools/codex-cloud-session.ts
|
|
65689
|
-
var
|
|
65690
|
-
var import_node_crypto14 = require("crypto");
|
|
65088
|
+
var import_node_fs39 = __toESM(require("fs"), 1);
|
|
65691
65089
|
|
|
65692
65090
|
// src/tools/cloud-portable-input.ts
|
|
65693
65091
|
async function portableCloudInput(text, resolvers) {
|
|
@@ -65746,10 +65144,11 @@ function createCloudTurnSession(args) {
|
|
|
65746
65144
|
turnId: commandId,
|
|
65747
65145
|
text: portable,
|
|
65748
65146
|
expectedEngine: engine,
|
|
65749
|
-
...engine === "pi" ? { engineSessionId: engineSessionId ?? conversationId } : {},
|
|
65147
|
+
...engine === "pi" && !ctx.titleOnly ? { engineSessionId: engineSessionId ?? conversationId } : {},
|
|
65750
65148
|
...instructions ? { instructions } : {},
|
|
65751
65149
|
...ctx.effort ? { effort: ctx.effort } : {},
|
|
65752
|
-
...ctx.personaMode ? { personaMode: ctx.personaMode } : {}
|
|
65150
|
+
...ctx.personaMode ? { personaMode: ctx.personaMode } : {},
|
|
65151
|
+
...ctx.titleOnly ? { purpose: "title" } : {}
|
|
65753
65152
|
});
|
|
65754
65153
|
if (closed) {
|
|
65755
65154
|
stream.close();
|
|
@@ -65826,7 +65225,7 @@ function cloudImageInput(deps) {
|
|
|
65826
65225
|
const mime = lookupMime(p3);
|
|
65827
65226
|
if (!mime.startsWith("image/")) return null;
|
|
65828
65227
|
try {
|
|
65829
|
-
const bytes = (deps.readFile ??
|
|
65228
|
+
const bytes = (deps.readFile ?? import_node_fs39.default.readFileSync)(p3);
|
|
65830
65229
|
return { type: "image", url: `data:${mime};base64,${bytes.toString("base64")}` };
|
|
65831
65230
|
} catch (e) {
|
|
65832
65231
|
deps.logger?.warn("cloud image attachment unreadable", { path: p3, message: e.message });
|
|
@@ -65836,34 +65235,10 @@ function cloudImageInput(deps) {
|
|
|
65836
65235
|
}
|
|
65837
65236
|
function createCloudCodexSession(ctx, sink, deps) {
|
|
65838
65237
|
const personaId2 = personaIdFromCloudCwd(ctx.cwd);
|
|
65839
|
-
if (personaId2
|
|
65840
|
-
return createCloudTurnSession({
|
|
65841
|
-
ctx,
|
|
65842
|
-
sink,
|
|
65843
|
-
client: deps.client,
|
|
65844
|
-
personaId: personaId2,
|
|
65845
|
-
engine: "codex",
|
|
65846
|
-
instructions: ctx.extraSystemPrompt,
|
|
65847
|
-
prepare: (text) => portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) })
|
|
65848
|
-
});
|
|
65849
|
-
}
|
|
65850
|
-
const clientSessionId = ctx.titleOnly ? (0, import_node_crypto14.randomUUID)() : ctx.cloudExecutionId ?? ctx.env?.CLAWD_SESSION_ID;
|
|
65851
|
-
let channel = null;
|
|
65852
|
-
let closed = false;
|
|
65853
|
-
let detached = false;
|
|
65854
|
-
let stopping = null;
|
|
65855
|
-
let exited = false;
|
|
65856
|
-
let ready = false;
|
|
65857
|
-
const exit = () => {
|
|
65858
|
-
if (!exited) {
|
|
65859
|
-
exited = true;
|
|
65860
|
-
sink.onExit(null);
|
|
65861
|
-
}
|
|
65862
|
-
};
|
|
65863
|
-
if (!personaId2 || !clientSessionId) {
|
|
65238
|
+
if (!personaId2 || ctx.cloudGatewaySessionId || ctx.cloudLegacyPendingCommand) {
|
|
65864
65239
|
queueMicrotask(() => {
|
|
65865
|
-
sink.onError(
|
|
65866
|
-
|
|
65240
|
+
sink.onError(personaId2 ? "\u65E7\u4E91\u4F1A\u8BDD\u534F\u8BAE\u5DF2\u505C\u7528\uFF0C\u8BF7\u5347\u7EA7\u5BA2\u6237\u7AEF\u5E76\u65B0\u5F00\u4F1A\u8BDD" : "cloud session is missing persona id");
|
|
65241
|
+
sink.onExit(null);
|
|
65867
65242
|
});
|
|
65868
65243
|
return { startTurn() {
|
|
65869
65244
|
}, respondPermission() {
|
|
@@ -65871,90 +65246,15 @@ function createCloudCodexSession(ctx, sink, deps) {
|
|
|
65871
65246
|
}, async stop() {
|
|
65872
65247
|
} };
|
|
65873
65248
|
}
|
|
65874
|
-
|
|
65875
|
-
|
|
65876
|
-
|
|
65877
|
-
|
|
65878
|
-
|
|
65879
|
-
|
|
65880
|
-
|
|
65881
|
-
|
|
65882
|
-
...ctx.titleOnly ? { purpose: "title" } : {},
|
|
65883
|
-
...ctx.cloudAttachOnly ? { attachOnly: true } : {}
|
|
65884
|
-
}).then(
|
|
65885
|
-
(opened2) => {
|
|
65886
|
-
channel = opened2;
|
|
65887
|
-
channel.onEvents((events) => sink.pushEvents(events));
|
|
65888
|
-
channel.onControl((c2) => {
|
|
65889
|
-
if (c2.kind === "ready") {
|
|
65890
|
-
ready = true;
|
|
65891
|
-
sink.onGatewayReady?.(c2.session);
|
|
65892
|
-
if (c2.replayGap || c2.historySynchronized === false) sink.onHistoryGap?.(c2.historySynchronized === true);
|
|
65893
|
-
} else if (c2.kind === "queued") {
|
|
65894
|
-
sink.pushEvents([{ kind: "meta-text", text: `\u4E91\u4E0A\u673A\u5668\u6709 ${c2.running} \u4E2A\u4EFB\u52A1\u5728\u8DD1\uFF0C\u7B49\u4E00\u4E2A\u7ED3\u675F\u5C31\u8F6E\u5230\u4F60` }]);
|
|
65895
|
-
} else if (c2.kind === "history") {
|
|
65896
|
-
sink.onHistoryGap?.(c2.synchronized);
|
|
65897
|
-
} else if (c2.kind === "error") {
|
|
65898
|
-
sink.onError(`${ready ? "\u4E91\u4E0A\u6267\u884C\u5931\u8D25" : "\u4E91\u4E0A persona \u8D77\u4E0D\u6765"}\uFF1A${c2.message}`);
|
|
65899
|
-
} else if (c2.kind === "closed" && c2.reason === "not-found") {
|
|
65900
|
-
sink.onRecoveryAbsent?.();
|
|
65901
|
-
}
|
|
65902
|
-
});
|
|
65903
|
-
channel.onClose(() => {
|
|
65904
|
-
if (!detached) exit();
|
|
65905
|
-
});
|
|
65906
|
-
if (closed) channel.close();
|
|
65907
|
-
return channel;
|
|
65908
|
-
},
|
|
65909
|
-
(e) => {
|
|
65910
|
-
sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
|
|
65911
|
-
exit();
|
|
65912
|
-
throw e;
|
|
65913
|
-
}
|
|
65914
|
-
);
|
|
65915
|
-
void opened.catch(() => {
|
|
65249
|
+
return createCloudTurnSession({
|
|
65250
|
+
ctx,
|
|
65251
|
+
sink,
|
|
65252
|
+
client: deps.client,
|
|
65253
|
+
personaId: personaId2,
|
|
65254
|
+
engine: "codex",
|
|
65255
|
+
instructions: ctx.titleOnly ? void 0 : ctx.extraSystemPrompt,
|
|
65256
|
+
prepare: (text) => portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) })
|
|
65916
65257
|
});
|
|
65917
|
-
let sendChain = Promise.resolve();
|
|
65918
|
-
const send2 = (command) => {
|
|
65919
|
-
sendChain = sendChain.then(command).catch((e) => {
|
|
65920
|
-
if (!closed && !exited) sink.onError(`\u4E91\u4E0A\u4F1A\u8BDD\u4E0A\u884C\u5931\u8D25\uFF1A${e.message}`);
|
|
65921
|
-
});
|
|
65922
|
-
};
|
|
65923
|
-
return {
|
|
65924
|
-
startTurn(text, commandId = (0, import_node_crypto14.randomUUID)(), prepared = false) {
|
|
65925
|
-
send2(async () => {
|
|
65926
|
-
const ch = await opened;
|
|
65927
|
-
if (closed) return;
|
|
65928
|
-
const portable = prepared ? text : await portableCloudInput(text, { resolveCodexImage: cloudImageInput(deps) });
|
|
65929
|
-
if (sink.onCommandPrepared?.(commandId, portable, prepared) === false) return;
|
|
65930
|
-
await ch.send({ command: "turn", text: portable, commandId });
|
|
65931
|
-
});
|
|
65932
|
-
},
|
|
65933
|
-
respondPermission(requestId, allow) {
|
|
65934
|
-
send2(async () => (await opened).send({ command: "permission", requestId, allow }));
|
|
65935
|
-
},
|
|
65936
|
-
interrupt() {
|
|
65937
|
-
send2(async () => (await opened).send({ command: "interrupt" }));
|
|
65938
|
-
},
|
|
65939
|
-
detach() {
|
|
65940
|
-
detached = true;
|
|
65941
|
-
closed = true;
|
|
65942
|
-
channel?.close();
|
|
65943
|
-
},
|
|
65944
|
-
stop() {
|
|
65945
|
-
if (stopping) return stopping;
|
|
65946
|
-
closed = true;
|
|
65947
|
-
stopping = (async () => {
|
|
65948
|
-
const ch = await opened.catch(() => null);
|
|
65949
|
-
if (ch) {
|
|
65950
|
-
await ch.send({ command: "cancel" });
|
|
65951
|
-
ch.close();
|
|
65952
|
-
}
|
|
65953
|
-
exit();
|
|
65954
|
-
})();
|
|
65955
|
-
return stopping;
|
|
65956
|
-
}
|
|
65957
|
-
};
|
|
65958
65258
|
}
|
|
65959
65259
|
|
|
65960
65260
|
// src/tools/codex-cloud.ts
|
|
@@ -66025,7 +65325,7 @@ init_protocol();
|
|
|
66025
65325
|
|
|
66026
65326
|
// src/tools/pi.ts
|
|
66027
65327
|
var import_node_child_process12 = require("child_process");
|
|
66028
|
-
var
|
|
65328
|
+
var import_node_fs41 = __toESM(require("fs"), 1);
|
|
66029
65329
|
init_protocol();
|
|
66030
65330
|
|
|
66031
65331
|
// src/tools/pi-rpc-client.ts
|
|
@@ -66125,9 +65425,9 @@ var PiRpcClient = class {
|
|
|
66125
65425
|
|
|
66126
65426
|
// src/tools/pi-session.ts
|
|
66127
65427
|
var import_node_child_process11 = require("child_process");
|
|
66128
|
-
var
|
|
66129
|
-
var
|
|
66130
|
-
var
|
|
65428
|
+
var import_node_crypto14 = require("crypto");
|
|
65429
|
+
var import_node_fs40 = __toESM(require("fs"), 1);
|
|
65430
|
+
var import_node_path44 = __toESM(require("path"), 1);
|
|
66131
65431
|
|
|
66132
65432
|
// src/tools/pi-events.ts
|
|
66133
65433
|
init_protocol();
|
|
@@ -66398,9 +65698,9 @@ ${dirs.map((d2) => `- ${d2}`).join("\n")}`;
|
|
|
66398
65698
|
}
|
|
66399
65699
|
function createPiSession(ctx, sink, deps = {}) {
|
|
66400
65700
|
const cmd = process.env.PI_BIN ?? "pi";
|
|
66401
|
-
const sessionId = ctx.toolSessionId ?? (0,
|
|
66402
|
-
const skillsDir =
|
|
66403
|
-
const exists = deps.skillsDirExists ?? ((d2) =>
|
|
65701
|
+
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto14.randomUUID)();
|
|
65702
|
+
const skillsDir = import_node_path44.default.join(ctx.cwd, ".claude", "skills");
|
|
65703
|
+
const exists = deps.skillsDirExists ?? ((d2) => import_node_fs40.default.existsSync(d2));
|
|
66404
65704
|
const args = buildPiArgs(ctx, {
|
|
66405
65705
|
sessionId,
|
|
66406
65706
|
skillsDir: exists(skillsDir) ? skillsDir : void 0,
|
|
@@ -66462,10 +65762,10 @@ var PI_DEFAULT_MODEL_ENTRY = {
|
|
|
66462
65762
|
};
|
|
66463
65763
|
var PI_FULL_ACCESS = { id: "never", label: "Full Access", description: "pi \u65E0\u5BA1\u6279\uFF1A\u4ECE\u4E0D\u8BE2\u95EE\uFF0C\u81EA\u4E3B\u6267\u884C" };
|
|
66464
65764
|
async function probePi(env = process.env) {
|
|
66465
|
-
if (env.PI_BIN &&
|
|
65765
|
+
if (env.PI_BIN && import_node_fs41.default.existsSync(env.PI_BIN)) return { available: true, path: env.PI_BIN };
|
|
66466
65766
|
try {
|
|
66467
65767
|
const out = (0, import_node_child_process12.execFileSync)("which", ["pi"], { encoding: "utf8" }).trim();
|
|
66468
|
-
if (out &&
|
|
65768
|
+
if (out && import_node_fs41.default.existsSync(out)) return { available: true, path: out };
|
|
66469
65769
|
} catch {
|
|
66470
65770
|
}
|
|
66471
65771
|
return { available: false };
|
|
@@ -66635,42 +65935,15 @@ var PiAdapter = class {
|
|
|
66635
65935
|
};
|
|
66636
65936
|
|
|
66637
65937
|
// src/tools/pi-cloud-session.ts
|
|
66638
|
-
var import_node_crypto16 = require("crypto");
|
|
66639
65938
|
function cloudPiInstructions(ctx) {
|
|
66640
65939
|
return [ctx.extraSystemPrompt, workDirPrompt(CLOUD_WORKSPACE_SLOT, ctx.personaMode ?? "owner")].filter((x2) => Boolean(x2)).join("\n\n");
|
|
66641
65940
|
}
|
|
66642
65941
|
function createCloudPiSession(ctx, sink, deps) {
|
|
66643
65942
|
const personaId2 = personaIdFromCloudCwd(ctx.cwd);
|
|
66644
|
-
if (personaId2
|
|
66645
|
-
return createCloudTurnSession({
|
|
66646
|
-
ctx,
|
|
66647
|
-
sink,
|
|
66648
|
-
client: deps.client,
|
|
66649
|
-
personaId: personaId2,
|
|
66650
|
-
engine: "pi",
|
|
66651
|
-
engineSessionId: ctx.toolSessionId,
|
|
66652
|
-
instructions: cloudPiInstructions(ctx),
|
|
66653
|
-
prepare: (text) => portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() })
|
|
66654
|
-
});
|
|
66655
|
-
}
|
|
66656
|
-
const clientSessionId = ctx.titleOnly ? (0, import_node_crypto16.randomUUID)() : ctx.cloudExecutionId ?? ctx.env?.CLAWD_SESSION_ID;
|
|
66657
|
-
const sessionId = ctx.toolSessionId ?? (0, import_node_crypto16.randomUUID)();
|
|
66658
|
-
let channel = null;
|
|
66659
|
-
let closed = false;
|
|
66660
|
-
let detached = false;
|
|
66661
|
-
let stopping = null;
|
|
66662
|
-
let exited = false;
|
|
66663
|
-
let ready = false;
|
|
66664
|
-
const exit = () => {
|
|
66665
|
-
if (!exited) {
|
|
66666
|
-
exited = true;
|
|
66667
|
-
sink.onExit(null);
|
|
66668
|
-
}
|
|
66669
|
-
};
|
|
66670
|
-
if (!personaId2 || !clientSessionId) {
|
|
65943
|
+
if (!personaId2 || ctx.cloudGatewaySessionId || ctx.cloudLegacyPendingCommand) {
|
|
66671
65944
|
queueMicrotask(() => {
|
|
66672
|
-
sink.onError(
|
|
66673
|
-
|
|
65945
|
+
sink.onError(personaId2 ? "\u65E7\u4E91\u4F1A\u8BDD\u534F\u8BAE\u5DF2\u505C\u7528\uFF0C\u8BF7\u5347\u7EA7\u5BA2\u6237\u7AEF\u5E76\u65B0\u5F00\u4F1A\u8BDD" : "cloud session is missing persona id");
|
|
65946
|
+
sink.onExit(null);
|
|
66674
65947
|
});
|
|
66675
65948
|
return { startTurn() {
|
|
66676
65949
|
}, respondPermission() {
|
|
@@ -66678,80 +65951,16 @@ function createCloudPiSession(ctx, sink, deps) {
|
|
|
66678
65951
|
}, async stop() {
|
|
66679
65952
|
} };
|
|
66680
65953
|
}
|
|
66681
|
-
|
|
66682
|
-
|
|
66683
|
-
|
|
66684
|
-
|
|
66685
|
-
|
|
66686
|
-
|
|
66687
|
-
|
|
66688
|
-
|
|
66689
|
-
|
|
66690
|
-
} else if (c2.kind === "queued") {
|
|
66691
|
-
sink.pushEvents([{ kind: "meta-text", text: `\u4E91\u4E0A\u673A\u5668\u6709 ${c2.running} \u4E2A\u4EFB\u52A1\u5728\u8DD1\uFF0C\u7B49\u4E00\u4E2A\u7ED3\u675F\u5C31\u8F6E\u5230\u4F60` }]);
|
|
66692
|
-
} else if (c2.kind === "history") {
|
|
66693
|
-
sink.onHistoryGap?.(c2.synchronized);
|
|
66694
|
-
} else if (c2.kind === "error") {
|
|
66695
|
-
sink.onError(`${ready ? "\u4E91\u4E0A\u6267\u884C\u5931\u8D25" : "\u4E91\u4E0A persona \u8D77\u4E0D\u6765"}\uFF1A${c2.message}`);
|
|
66696
|
-
} else if (c2.kind === "closed" && c2.reason === "not-found") {
|
|
66697
|
-
sink.onRecoveryAbsent?.();
|
|
66698
|
-
}
|
|
66699
|
-
});
|
|
66700
|
-
channel.onClose(() => {
|
|
66701
|
-
if (!detached) exit();
|
|
66702
|
-
});
|
|
66703
|
-
if (closed) channel.close();
|
|
66704
|
-
return channel;
|
|
66705
|
-
},
|
|
66706
|
-
(e) => {
|
|
66707
|
-
sink.onError(e instanceof CloudApiKeyRequiredError ? e.message : `\u8FDE\u4E0D\u4E0A\u4E91 gateway\uFF1A${e.message}`);
|
|
66708
|
-
exit();
|
|
66709
|
-
throw e;
|
|
66710
|
-
}
|
|
66711
|
-
);
|
|
66712
|
-
void opened.catch(() => {
|
|
65954
|
+
return createCloudTurnSession({
|
|
65955
|
+
ctx,
|
|
65956
|
+
sink,
|
|
65957
|
+
client: deps.client,
|
|
65958
|
+
personaId: personaId2,
|
|
65959
|
+
engine: "pi",
|
|
65960
|
+
engineSessionId: ctx.toolSessionId,
|
|
65961
|
+
instructions: ctx.titleOnly ? void 0 : cloudPiInstructions(ctx),
|
|
65962
|
+
prepare: (text) => portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() })
|
|
66713
65963
|
});
|
|
66714
|
-
let sendChain = Promise.resolve();
|
|
66715
|
-
const send2 = (command) => {
|
|
66716
|
-
sendChain = sendChain.then(command).catch((e) => {
|
|
66717
|
-
if (!closed && !exited) sink.onError(`\u4E91\u4E0A\u4F1A\u8BDD\u4E0A\u884C\u5931\u8D25\uFF1A${e.message}`);
|
|
66718
|
-
});
|
|
66719
|
-
};
|
|
66720
|
-
return {
|
|
66721
|
-
startTurn(text, commandId = (0, import_node_crypto16.randomUUID)(), prepared = false) {
|
|
66722
|
-
send2(async () => {
|
|
66723
|
-
const ch = await opened;
|
|
66724
|
-
if (closed) return;
|
|
66725
|
-
const portable = prepared ? text : await portableCloudInput(text, { fetchPiImage: deps.fetchImage ?? makeImageFetcher() });
|
|
66726
|
-
if (sink.onCommandPrepared?.(commandId, portable, prepared) === false) return;
|
|
66727
|
-
await ch.send({ command: "turn", text: portable, commandId });
|
|
66728
|
-
});
|
|
66729
|
-
},
|
|
66730
|
-
respondPermission(requestId, allow) {
|
|
66731
|
-
send2(async () => (await opened).send({ command: "permission", requestId, allow }));
|
|
66732
|
-
},
|
|
66733
|
-
interrupt() {
|
|
66734
|
-
send2(async () => (await opened).send({ command: "interrupt" }));
|
|
66735
|
-
},
|
|
66736
|
-
detach() {
|
|
66737
|
-
detached = true;
|
|
66738
|
-
closed = true;
|
|
66739
|
-
channel?.close();
|
|
66740
|
-
},
|
|
66741
|
-
stop() {
|
|
66742
|
-
if (stopping) return stopping;
|
|
66743
|
-
closed = true;
|
|
66744
|
-
stopping = (async () => {
|
|
66745
|
-
const ch = await opened.catch(() => null);
|
|
66746
|
-
if (ch) {
|
|
66747
|
-
await ch.send({ command: "cancel" });
|
|
66748
|
-
ch.close();
|
|
66749
|
-
}
|
|
66750
|
-
exit();
|
|
66751
|
-
})();
|
|
66752
|
-
return stopping;
|
|
66753
|
-
}
|
|
66754
|
-
};
|
|
66755
65964
|
}
|
|
66756
65965
|
|
|
66757
65966
|
// src/tools/pi-cloud.ts
|
|
@@ -66821,7 +66030,7 @@ var CloudPiAdapter = class {
|
|
|
66821
66030
|
init_protocol();
|
|
66822
66031
|
|
|
66823
66032
|
// src/tools/codex-skills.ts
|
|
66824
|
-
var
|
|
66033
|
+
var import_node_path45 = __toESM(require("path"), 1);
|
|
66825
66034
|
function str4(v3) {
|
|
66826
66035
|
return typeof v3 === "string" ? v3 : void 0;
|
|
66827
66036
|
}
|
|
@@ -66836,13 +66045,13 @@ function mapSkillsListResponse(res) {
|
|
|
66836
66045
|
const r2 = s2 ?? {};
|
|
66837
66046
|
const name = str4(r2.name);
|
|
66838
66047
|
if (!name) continue;
|
|
66839
|
-
const
|
|
66048
|
+
const path106 = str4(r2.path);
|
|
66840
66049
|
const description = str4(r2.description);
|
|
66841
66050
|
const isPlugin = name.includes(":");
|
|
66842
66051
|
out.push({
|
|
66843
66052
|
name,
|
|
66844
66053
|
source: isPlugin ? "plugin" : "project",
|
|
66845
|
-
...
|
|
66054
|
+
...path106 ? { path: path106 } : {},
|
|
66846
66055
|
...description ? { description } : {},
|
|
66847
66056
|
...isPlugin ? { plugin: name.split(":")[0] } : {}
|
|
66848
66057
|
});
|
|
@@ -66858,7 +66067,7 @@ async function listCodexSkills(cwd, deps = {}) {
|
|
|
66858
66067
|
// 先写 extraRoots 再写 list(stdio 按写入顺序处理,fire-and-forget 不 await 回包;
|
|
66859
66068
|
// codex-session.ts ready 序列同款,两处保持一致)。失败不阻塞 list。
|
|
66860
66069
|
beforeRequest: (client) => {
|
|
66861
|
-
void client.request("skills/extraRoots/set", { extraRoots: [
|
|
66070
|
+
void client.request("skills/extraRoots/set", { extraRoots: [import_node_path45.default.join(cwd, ".claude", "skills")] }).catch(() => void 0);
|
|
66862
66071
|
}
|
|
66863
66072
|
});
|
|
66864
66073
|
return mapSkillsListResponse(res);
|
|
@@ -66932,23 +66141,23 @@ function rec4(v3) {
|
|
|
66932
66141
|
}
|
|
66933
66142
|
|
|
66934
66143
|
// src/workspace/browser.ts
|
|
66935
|
-
var
|
|
66144
|
+
var import_node_fs42 = __toESM(require("fs"), 1);
|
|
66936
66145
|
var import_node_os15 = __toESM(require("os"), 1);
|
|
66937
|
-
var
|
|
66146
|
+
var import_node_path46 = __toESM(require("path"), 1);
|
|
66938
66147
|
init_protocol();
|
|
66939
66148
|
var MAX_FILE_BYTES2 = 2 * 1024 * 1024;
|
|
66940
66149
|
function resolveInsideCwd(cwd, subpath) {
|
|
66941
|
-
const absCwd =
|
|
66942
|
-
const joined =
|
|
66943
|
-
const rel =
|
|
66944
|
-
if (rel.startsWith("..") ||
|
|
66150
|
+
const absCwd = import_node_path46.default.resolve(cwd);
|
|
66151
|
+
const joined = import_node_path46.default.resolve(absCwd, subpath ?? ".");
|
|
66152
|
+
const rel = import_node_path46.default.relative(absCwd, joined);
|
|
66153
|
+
if (rel.startsWith("..") || import_node_path46.default.isAbsolute(rel)) {
|
|
66945
66154
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `path escapes cwd: ${subpath}`);
|
|
66946
66155
|
}
|
|
66947
66156
|
return joined;
|
|
66948
66157
|
}
|
|
66949
66158
|
function ensureCwd(cwd) {
|
|
66950
66159
|
try {
|
|
66951
|
-
const stat =
|
|
66160
|
+
const stat = import_node_fs42.default.statSync(cwd);
|
|
66952
66161
|
if (!stat.isDirectory()) {
|
|
66953
66162
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${cwd}`);
|
|
66954
66163
|
}
|
|
@@ -66962,7 +66171,7 @@ var WorkspaceBrowser = class {
|
|
|
66962
66171
|
const cwd = args.cwd && args.cwd.length > 0 ? args.cwd : import_node_os15.default.homedir();
|
|
66963
66172
|
ensureCwd(cwd);
|
|
66964
66173
|
const full = resolveInsideCwd(cwd, args.path);
|
|
66965
|
-
const dirents =
|
|
66174
|
+
const dirents = import_node_fs42.default.readdirSync(full, { withFileTypes: true });
|
|
66966
66175
|
const entries = [];
|
|
66967
66176
|
for (const d2 of dirents) {
|
|
66968
66177
|
if (!args.showHidden && d2.name.startsWith(".")) continue;
|
|
@@ -66972,7 +66181,7 @@ var WorkspaceBrowser = class {
|
|
|
66972
66181
|
mtime: ""
|
|
66973
66182
|
};
|
|
66974
66183
|
try {
|
|
66975
|
-
const st2 =
|
|
66184
|
+
const st2 = import_node_fs42.default.statSync(import_node_path46.default.join(full, d2.name));
|
|
66976
66185
|
entry.mtime = new Date(st2.mtimeMs).toISOString();
|
|
66977
66186
|
if (d2.isFile()) entry.size = st2.size;
|
|
66978
66187
|
} catch {
|
|
@@ -66988,14 +66197,14 @@ var WorkspaceBrowser = class {
|
|
|
66988
66197
|
read(args) {
|
|
66989
66198
|
ensureCwd(args.cwd);
|
|
66990
66199
|
const full = resolveInsideCwd(args.cwd, args.path);
|
|
66991
|
-
const st2 =
|
|
66200
|
+
const st2 = import_node_fs42.default.statSync(full);
|
|
66992
66201
|
if (!st2.isFile()) {
|
|
66993
66202
|
throw new ClawdError(ERROR_CODES.INVALID_PATH, `not a file: ${args.path}`);
|
|
66994
66203
|
}
|
|
66995
66204
|
if (st2.size > MAX_FILE_BYTES2) {
|
|
66996
66205
|
throw new ClawdError(ERROR_CODES.FILE_TOO_LARGE, `file > ${MAX_FILE_BYTES2} bytes`);
|
|
66997
66206
|
}
|
|
66998
|
-
const buf =
|
|
66207
|
+
const buf = import_node_fs42.default.readFileSync(full);
|
|
66999
66208
|
const isBinary = buf.includes(0);
|
|
67000
66209
|
if (isBinary) {
|
|
67001
66210
|
return {
|
|
@@ -67017,20 +66226,20 @@ var WorkspaceBrowser = class {
|
|
|
67017
66226
|
};
|
|
67018
66227
|
|
|
67019
66228
|
// src/skills/agents-scanner.ts
|
|
67020
|
-
var
|
|
66229
|
+
var import_node_fs43 = __toESM(require("fs"), 1);
|
|
67021
66230
|
var import_node_os16 = __toESM(require("os"), 1);
|
|
67022
|
-
var
|
|
66231
|
+
var import_node_path47 = __toESM(require("path"), 1);
|
|
67023
66232
|
var DEFAULT_POLICY_DIR_DARWIN = "/Library/Application Support/ClaudeCode/.claude/agents";
|
|
67024
66233
|
function isDirLikeSync2(p3) {
|
|
67025
66234
|
try {
|
|
67026
|
-
return
|
|
66235
|
+
return import_node_fs43.default.statSync(p3).isDirectory();
|
|
67027
66236
|
} catch {
|
|
67028
66237
|
return false;
|
|
67029
66238
|
}
|
|
67030
66239
|
}
|
|
67031
66240
|
function fileExistsSync(p3) {
|
|
67032
66241
|
try {
|
|
67033
|
-
return
|
|
66242
|
+
return import_node_fs43.default.statSync(p3).isFile();
|
|
67034
66243
|
} catch {
|
|
67035
66244
|
return false;
|
|
67036
66245
|
}
|
|
@@ -67038,7 +66247,7 @@ function fileExistsSync(p3) {
|
|
|
67038
66247
|
function parseAgentFile(filePath) {
|
|
67039
66248
|
let content;
|
|
67040
66249
|
try {
|
|
67041
|
-
content =
|
|
66250
|
+
content = import_node_fs43.default.readFileSync(filePath, "utf8");
|
|
67042
66251
|
} catch {
|
|
67043
66252
|
return {};
|
|
67044
66253
|
}
|
|
@@ -67051,16 +66260,16 @@ function parseAgentFile(filePath) {
|
|
|
67051
66260
|
function scanAgentsDir(dir, source, seen, out) {
|
|
67052
66261
|
let entries;
|
|
67053
66262
|
try {
|
|
67054
|
-
entries =
|
|
66263
|
+
entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
|
|
67055
66264
|
} catch {
|
|
67056
66265
|
return;
|
|
67057
66266
|
}
|
|
67058
66267
|
for (const ent of entries) {
|
|
67059
66268
|
if (!ent.name.endsWith(".md")) continue;
|
|
67060
|
-
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(
|
|
66269
|
+
if (!ent.isFile() && !(ent.isSymbolicLink() && fileExistsSync(import_node_path47.default.join(dir, ent.name)))) {
|
|
67061
66270
|
continue;
|
|
67062
66271
|
}
|
|
67063
|
-
const filePath =
|
|
66272
|
+
const filePath = import_node_path47.default.join(dir, ent.name);
|
|
67064
66273
|
const baseName = ent.name.replace(/\.md$/, "");
|
|
67065
66274
|
if (seen.has(baseName)) continue;
|
|
67066
66275
|
seen.add(baseName);
|
|
@@ -67078,12 +66287,12 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
67078
66287
|
function walk2(dir, namespaces) {
|
|
67079
66288
|
let entries;
|
|
67080
66289
|
try {
|
|
67081
|
-
entries =
|
|
66290
|
+
entries = import_node_fs43.default.readdirSync(dir, { withFileTypes: true });
|
|
67082
66291
|
} catch {
|
|
67083
66292
|
return;
|
|
67084
66293
|
}
|
|
67085
66294
|
for (const ent of entries) {
|
|
67086
|
-
const childPath =
|
|
66295
|
+
const childPath = import_node_path47.default.join(dir, ent.name);
|
|
67087
66296
|
if (ent.isDirectory() || ent.isSymbolicLink() && isDirLikeSync2(childPath)) {
|
|
67088
66297
|
walk2(childPath, [...namespaces, ent.name]);
|
|
67089
66298
|
continue;
|
|
@@ -67108,13 +66317,13 @@ function scanPluginAgentsTree(root, pluginName, seen, out) {
|
|
|
67108
66317
|
walk2(root, []);
|
|
67109
66318
|
}
|
|
67110
66319
|
function readInstalledPlugins2(home) {
|
|
67111
|
-
const pluginsDir =
|
|
67112
|
-
const v22 =
|
|
67113
|
-
const v1 =
|
|
66320
|
+
const pluginsDir = import_node_path47.default.join(home, ".claude", "plugins");
|
|
66321
|
+
const v22 = import_node_path47.default.join(pluginsDir, "installed_plugins_v2.json");
|
|
66322
|
+
const v1 = import_node_path47.default.join(pluginsDir, "installed_plugins.json");
|
|
67114
66323
|
let raw = null;
|
|
67115
66324
|
for (const candidate of [v22, v1]) {
|
|
67116
66325
|
try {
|
|
67117
|
-
raw =
|
|
66326
|
+
raw = import_node_fs43.default.readFileSync(candidate, "utf8");
|
|
67118
66327
|
break;
|
|
67119
66328
|
} catch {
|
|
67120
66329
|
}
|
|
@@ -67139,19 +66348,19 @@ function readInstalledPlugins2(home) {
|
|
|
67139
66348
|
return out;
|
|
67140
66349
|
}
|
|
67141
66350
|
function walkUpProjectAgentsDirs(startCwd, home, seen, out) {
|
|
67142
|
-
let cur =
|
|
67143
|
-
const fsRoot =
|
|
66351
|
+
let cur = import_node_path47.default.resolve(startCwd);
|
|
66352
|
+
const fsRoot = import_node_path47.default.parse(cur).root;
|
|
67144
66353
|
while (true) {
|
|
67145
|
-
scanAgentsDir(
|
|
66354
|
+
scanAgentsDir(import_node_path47.default.join(cur, ".claude", "agents"), "project", seen, out);
|
|
67146
66355
|
let hasGit = false;
|
|
67147
66356
|
try {
|
|
67148
|
-
hasGit =
|
|
66357
|
+
hasGit = import_node_fs43.default.existsSync(import_node_path47.default.join(cur, ".git"));
|
|
67149
66358
|
} catch {
|
|
67150
66359
|
}
|
|
67151
66360
|
if (hasGit) return;
|
|
67152
66361
|
if (cur === home) return;
|
|
67153
66362
|
if (cur === fsRoot) return;
|
|
67154
|
-
const parent =
|
|
66363
|
+
const parent = import_node_path47.default.dirname(cur);
|
|
67155
66364
|
if (parent === cur) return;
|
|
67156
66365
|
cur = parent;
|
|
67157
66366
|
}
|
|
@@ -67186,7 +66395,7 @@ var AgentsScanner = class {
|
|
|
67186
66395
|
}
|
|
67187
66396
|
const fsBlock = [];
|
|
67188
66397
|
scanAgentsDir(
|
|
67189
|
-
|
|
66398
|
+
import_node_path47.default.join(this.home, ".claude", "agents"),
|
|
67190
66399
|
"global",
|
|
67191
66400
|
seen,
|
|
67192
66401
|
fsBlock
|
|
@@ -67200,7 +66409,7 @@ var AgentsScanner = class {
|
|
|
67200
66409
|
...this.extraPluginRoots
|
|
67201
66410
|
];
|
|
67202
66411
|
for (const { name, root } of plugins) {
|
|
67203
|
-
const agentsRoot =
|
|
66412
|
+
const agentsRoot = import_node_path47.default.join(root, "agents");
|
|
67204
66413
|
scanPluginAgentsTree(agentsRoot, name, seen, fsBlock);
|
|
67205
66414
|
}
|
|
67206
66415
|
return [...builtinBlock, ...fsBlock];
|
|
@@ -67208,15 +66417,15 @@ var AgentsScanner = class {
|
|
|
67208
66417
|
};
|
|
67209
66418
|
|
|
67210
66419
|
// src/observer/session-observer.ts
|
|
67211
|
-
var
|
|
66420
|
+
var import_node_fs45 = __toESM(require("fs"), 1);
|
|
67212
66421
|
var import_node_os18 = __toESM(require("os"), 1);
|
|
67213
|
-
var
|
|
66422
|
+
var import_node_path49 = __toESM(require("path"), 1);
|
|
67214
66423
|
init_claude_history();
|
|
67215
66424
|
|
|
67216
66425
|
// src/observer/subagent-meta-observer.ts
|
|
67217
|
-
var
|
|
66426
|
+
var import_node_fs44 = __toESM(require("fs"), 1);
|
|
67218
66427
|
var import_node_os17 = __toESM(require("os"), 1);
|
|
67219
|
-
var
|
|
66428
|
+
var import_node_path48 = __toESM(require("path"), 1);
|
|
67220
66429
|
init_claude_history();
|
|
67221
66430
|
var META_RE = /^agent-([A-Za-z0-9_-]+)\.meta\.json$/;
|
|
67222
66431
|
var SubagentMetaObserver = class {
|
|
@@ -67229,7 +66438,7 @@ var SubagentMetaObserver = class {
|
|
|
67229
66438
|
watches = /* @__PURE__ */ new Map();
|
|
67230
66439
|
// public for spec only:测试直接拼路径写假 meta.json;生产 start() 内部自己解析
|
|
67231
66440
|
resolveSubagentDir(cwd, toolSessionId) {
|
|
67232
|
-
return
|
|
66441
|
+
return import_node_path48.default.join(
|
|
67233
66442
|
this.home,
|
|
67234
66443
|
".claude",
|
|
67235
66444
|
"projects",
|
|
@@ -67259,7 +66468,7 @@ var SubagentMetaObserver = class {
|
|
|
67259
66468
|
attachWatcher(w3) {
|
|
67260
66469
|
if (w3.watcher) return;
|
|
67261
66470
|
try {
|
|
67262
|
-
w3.watcher =
|
|
66471
|
+
w3.watcher = import_node_fs44.default.watch(w3.dirPath, { persistent: false }, (_evt, name) => {
|
|
67263
66472
|
if (!name) return;
|
|
67264
66473
|
const m3 = META_RE.exec(String(name));
|
|
67265
66474
|
if (!m3) return;
|
|
@@ -67271,7 +66480,7 @@ var SubagentMetaObserver = class {
|
|
|
67271
66480
|
scan(w3) {
|
|
67272
66481
|
let entries;
|
|
67273
66482
|
try {
|
|
67274
|
-
entries =
|
|
66483
|
+
entries = import_node_fs44.default.readdirSync(w3.dirPath);
|
|
67275
66484
|
} catch {
|
|
67276
66485
|
return;
|
|
67277
66486
|
}
|
|
@@ -67285,10 +66494,10 @@ var SubagentMetaObserver = class {
|
|
|
67285
66494
|
if (!m3) return;
|
|
67286
66495
|
const agentId = m3[1];
|
|
67287
66496
|
if (w3.emitted.has(agentId)) return;
|
|
67288
|
-
const file =
|
|
66497
|
+
const file = import_node_path48.default.join(w3.dirPath, name);
|
|
67289
66498
|
let raw;
|
|
67290
66499
|
try {
|
|
67291
|
-
raw =
|
|
66500
|
+
raw = import_node_fs44.default.readFileSync(file, "utf8");
|
|
67292
66501
|
} catch {
|
|
67293
66502
|
return;
|
|
67294
66503
|
}
|
|
@@ -67345,14 +66554,14 @@ var SessionObserver = class {
|
|
|
67345
66554
|
metaObserver;
|
|
67346
66555
|
resolveJsonlPath(cwd, toolSessionId, override) {
|
|
67347
66556
|
if (override) return override;
|
|
67348
|
-
return
|
|
66557
|
+
return import_node_path49.default.join(this.home, ".claude", "projects", cwdToHashDir(cwd), `${toolSessionId}.jsonl`);
|
|
67349
66558
|
}
|
|
67350
66559
|
start(args) {
|
|
67351
66560
|
this.stop(args.sessionId);
|
|
67352
66561
|
const filePath = this.resolveJsonlPath(args.cwd, args.toolSessionId, args.jsonlPath);
|
|
67353
66562
|
let size = 0;
|
|
67354
66563
|
try {
|
|
67355
|
-
size =
|
|
66564
|
+
size = import_node_fs45.default.statSync(filePath).size;
|
|
67356
66565
|
} catch {
|
|
67357
66566
|
}
|
|
67358
66567
|
const w3 = {
|
|
@@ -67365,16 +66574,16 @@ var SessionObserver = class {
|
|
|
67365
66574
|
adapter: args.adapter,
|
|
67366
66575
|
prevIsRejectSentinel: false,
|
|
67367
66576
|
toolSessionId: args.toolSessionId,
|
|
67368
|
-
sawFile:
|
|
66577
|
+
sawFile: import_node_fs45.default.existsSync(filePath),
|
|
67369
66578
|
lastRelocateScanMs: 0,
|
|
67370
66579
|
pendingCwdDerive: false,
|
|
67371
66580
|
lastDeriveMs: 0
|
|
67372
66581
|
};
|
|
67373
66582
|
try {
|
|
67374
|
-
|
|
66583
|
+
import_node_fs45.default.mkdirSync(import_node_path49.default.dirname(filePath), { recursive: true });
|
|
67375
66584
|
} catch {
|
|
67376
66585
|
}
|
|
67377
|
-
w3.watcher =
|
|
66586
|
+
w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(filePath), { persistent: false }, (_event, changedName) => {
|
|
67378
66587
|
if (!changedName || !w3.filePath.endsWith(changedName)) return;
|
|
67379
66588
|
this.poll(w3);
|
|
67380
66589
|
});
|
|
@@ -67397,7 +66606,7 @@ var SessionObserver = class {
|
|
|
67397
66606
|
// 异常静默吞,不阻塞 watcher 启动
|
|
67398
66607
|
hydrateMetaTail(w3, maxLines = 200) {
|
|
67399
66608
|
try {
|
|
67400
|
-
const raw =
|
|
66609
|
+
const raw = import_node_fs45.default.readFileSync(w3.filePath, "utf8");
|
|
67401
66610
|
if (!raw) return;
|
|
67402
66611
|
const allLines = raw.split("\n").filter((l2) => l2.trim().length > 0);
|
|
67403
66612
|
if (allLines.length === 0) return;
|
|
@@ -67421,7 +66630,7 @@ var SessionObserver = class {
|
|
|
67421
66630
|
poll(w3) {
|
|
67422
66631
|
let size = 0;
|
|
67423
66632
|
try {
|
|
67424
|
-
size =
|
|
66633
|
+
size = import_node_fs45.default.statSync(w3.filePath).size;
|
|
67425
66634
|
} catch {
|
|
67426
66635
|
if (w3.sawFile) this.maybeRelocate(w3);
|
|
67427
66636
|
return;
|
|
@@ -67432,11 +66641,11 @@ var SessionObserver = class {
|
|
|
67432
66641
|
w3.buf = "";
|
|
67433
66642
|
}
|
|
67434
66643
|
if (size === w3.lastSize) return;
|
|
67435
|
-
const fd =
|
|
66644
|
+
const fd = import_node_fs45.default.openSync(w3.filePath, "r");
|
|
67436
66645
|
try {
|
|
67437
66646
|
const len = size - w3.lastSize;
|
|
67438
66647
|
const buf = Buffer.alloc(len);
|
|
67439
|
-
|
|
66648
|
+
import_node_fs45.default.readSync(fd, buf, 0, len, w3.lastSize);
|
|
67440
66649
|
w3.lastSize = size;
|
|
67441
66650
|
w3.buf += buf.toString("utf8");
|
|
67442
66651
|
let newlineIndex;
|
|
@@ -67459,7 +66668,7 @@ var SessionObserver = class {
|
|
|
67459
66668
|
}
|
|
67460
66669
|
}
|
|
67461
66670
|
} finally {
|
|
67462
|
-
|
|
66671
|
+
import_node_fs45.default.closeSync(fd);
|
|
67463
66672
|
}
|
|
67464
66673
|
if (w3.pendingCwdDerive) this.maybeDeriveCwd(w3);
|
|
67465
66674
|
}
|
|
@@ -67471,7 +66680,7 @@ var SessionObserver = class {
|
|
|
67471
66680
|
const now = Date.now();
|
|
67472
66681
|
if (now - w3.lastRelocateScanMs < 1e3) return;
|
|
67473
66682
|
w3.lastRelocateScanMs = now;
|
|
67474
|
-
const projectsRoot =
|
|
66683
|
+
const projectsRoot = import_node_path49.default.join(this.home, ".claude", "projects");
|
|
67475
66684
|
const found = findTranscriptByToolSessionId(projectsRoot, w3.toolSessionId);
|
|
67476
66685
|
if (!found || found === w3.filePath) return;
|
|
67477
66686
|
try {
|
|
@@ -67480,7 +66689,7 @@ var SessionObserver = class {
|
|
|
67480
66689
|
}
|
|
67481
66690
|
w3.filePath = found;
|
|
67482
66691
|
try {
|
|
67483
|
-
w3.watcher =
|
|
66692
|
+
w3.watcher = import_node_fs45.default.watch(import_node_path49.default.dirname(found), { persistent: false }, (_event, changedName) => {
|
|
67484
66693
|
if (!changedName || !w3.filePath.endsWith(changedName)) return;
|
|
67485
66694
|
this.poll(w3);
|
|
67486
66695
|
});
|
|
@@ -67602,9 +66811,9 @@ function listRegistered() {
|
|
|
67602
66811
|
// src/tools/title-generator.ts
|
|
67603
66812
|
var import_node_child_process13 = require("child_process");
|
|
67604
66813
|
init_protocol();
|
|
67605
|
-
var
|
|
66814
|
+
var import_node_fs46 = __toESM(require("fs"), 1);
|
|
67606
66815
|
var import_node_os19 = __toESM(require("os"), 1);
|
|
67607
|
-
var
|
|
66816
|
+
var import_node_path50 = __toESM(require("path"), 1);
|
|
67608
66817
|
var TITLE_GEN_DIR_PREFIX = "clawd-title-";
|
|
67609
66818
|
var TITLE_INPUT_MAX_CHARS = 400;
|
|
67610
66819
|
var DEFAULT_TITLE_GEN_TIMEOUT_MS = 45e3;
|
|
@@ -67695,21 +66904,21 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
|
|
|
67695
66904
|
}
|
|
67696
66905
|
let workDir;
|
|
67697
66906
|
try {
|
|
67698
|
-
workDir =
|
|
66907
|
+
workDir = import_node_fs46.default.mkdtempSync(import_node_path50.default.join(import_node_os19.default.tmpdir(), TITLE_GEN_DIR_PREFIX));
|
|
67699
66908
|
} catch {
|
|
67700
66909
|
return null;
|
|
67701
66910
|
}
|
|
67702
66911
|
const cleanupWorkDir = () => {
|
|
67703
66912
|
try {
|
|
67704
|
-
|
|
66913
|
+
import_node_fs46.default.rmSync(workDir, { recursive: true, force: true });
|
|
67705
66914
|
} catch {
|
|
67706
66915
|
}
|
|
67707
66916
|
};
|
|
67708
|
-
const outFile =
|
|
67709
|
-
const schemaFile =
|
|
66917
|
+
const outFile = import_node_path50.default.join(workDir, `codex-title-${process.pid}-${++outFileSeq}-${Date.now()}.txt`);
|
|
66918
|
+
const schemaFile = import_node_path50.default.join(workDir, "title-schema.json");
|
|
67710
66919
|
if (tool === "codex") {
|
|
67711
66920
|
try {
|
|
67712
|
-
|
|
66921
|
+
import_node_fs46.default.writeFileSync(schemaFile, CODEX_TITLE_SCHEMA);
|
|
67713
66922
|
} catch {
|
|
67714
66923
|
cleanupWorkDir();
|
|
67715
66924
|
return null;
|
|
@@ -67764,7 +66973,7 @@ async function generateSessionTitle(file, firstMessage, deps = {}) {
|
|
|
67764
66973
|
if (tool === "claude" || tool === "pi") return finish(parseTitleJson(stdout));
|
|
67765
66974
|
let fileText = "";
|
|
67766
66975
|
try {
|
|
67767
|
-
fileText =
|
|
66976
|
+
fileText = import_node_fs46.default.readFileSync(outFile, "utf8");
|
|
67768
66977
|
} catch {
|
|
67769
66978
|
return finish(null);
|
|
67770
66979
|
}
|
|
@@ -67837,7 +67046,7 @@ var wrapper_default = import_websocket.default;
|
|
|
67837
67046
|
|
|
67838
67047
|
// src/transport/local-ws-server.ts
|
|
67839
67048
|
var import_node_http = __toESM(require("http"), 1);
|
|
67840
|
-
var
|
|
67049
|
+
var import_node_crypto15 = require("crypto");
|
|
67841
67050
|
var LocalWsServer = class {
|
|
67842
67051
|
constructor(opts) {
|
|
67843
67052
|
this.opts = opts;
|
|
@@ -68054,7 +67263,7 @@ var LocalWsServer = class {
|
|
|
68054
67263
|
}
|
|
68055
67264
|
}
|
|
68056
67265
|
onConnection(socket, remoteAddress) {
|
|
68057
|
-
const id = (0,
|
|
67266
|
+
const id = (0, import_node_crypto15.randomUUID)();
|
|
68058
67267
|
const subscribedSessions = /* @__PURE__ */ new Map();
|
|
68059
67268
|
const handle = {
|
|
68060
67269
|
id,
|
|
@@ -68460,8 +67669,8 @@ async function authenticate(token, deps) {
|
|
|
68460
67669
|
}
|
|
68461
67670
|
|
|
68462
67671
|
// src/legacy-cleanup.ts
|
|
68463
|
-
var
|
|
68464
|
-
var
|
|
67672
|
+
var fs57 = __toESM(require("fs/promises"), 1);
|
|
67673
|
+
var path58 = __toESM(require("path"), 1);
|
|
68465
67674
|
var LEGACY_FILES = [
|
|
68466
67675
|
"personal-capability.json",
|
|
68467
67676
|
"received-capabilities.json",
|
|
@@ -68470,9 +67679,9 @@ var LEGACY_FILES = [
|
|
|
68470
67679
|
async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
68471
67680
|
const removed = [];
|
|
68472
67681
|
for (const name of LEGACY_FILES) {
|
|
68473
|
-
const p3 =
|
|
67682
|
+
const p3 = path58.join(dataDir, name);
|
|
68474
67683
|
try {
|
|
68475
|
-
await
|
|
67684
|
+
await fs57.unlink(p3);
|
|
68476
67685
|
removed.push(name);
|
|
68477
67686
|
logger.debug("legacy capability file removed", { file: name });
|
|
68478
67687
|
} catch (err) {
|
|
@@ -68484,13 +67693,13 @@ async function cleanupLegacyCapabilityFiles(dataDir, logger) {
|
|
|
68484
67693
|
}
|
|
68485
67694
|
|
|
68486
67695
|
// src/inbox/inbox-store.ts
|
|
68487
|
-
var
|
|
68488
|
-
var
|
|
67696
|
+
var fs58 = __toESM(require("fs"), 1);
|
|
67697
|
+
var path59 = __toESM(require("path"), 1);
|
|
68489
67698
|
var INBOX_SUBDIR = "inbox";
|
|
68490
67699
|
var InboxStore = class {
|
|
68491
67700
|
constructor(dataDir) {
|
|
68492
67701
|
this.dataDir = dataDir;
|
|
68493
|
-
|
|
67702
|
+
fs58.mkdirSync(this.dirPath(), { recursive: true });
|
|
68494
67703
|
}
|
|
68495
67704
|
dataDir;
|
|
68496
67705
|
/**
|
|
@@ -68502,7 +67711,7 @@ var InboxStore = class {
|
|
|
68502
67711
|
const file = this.filePath(peerDeviceId);
|
|
68503
67712
|
let raw;
|
|
68504
67713
|
try {
|
|
68505
|
-
raw =
|
|
67714
|
+
raw = fs58.readFileSync(file, "utf8");
|
|
68506
67715
|
} catch (err) {
|
|
68507
67716
|
if (err?.code === "ENOENT") return [];
|
|
68508
67717
|
return [];
|
|
@@ -68518,7 +67727,7 @@ var InboxStore = class {
|
|
|
68518
67727
|
const dir = this.dirPath();
|
|
68519
67728
|
let entries;
|
|
68520
67729
|
try {
|
|
68521
|
-
entries =
|
|
67730
|
+
entries = fs58.readdirSync(dir);
|
|
68522
67731
|
} catch (err) {
|
|
68523
67732
|
if (err?.code === "ENOENT") return [];
|
|
68524
67733
|
return [];
|
|
@@ -68534,9 +67743,9 @@ var InboxStore = class {
|
|
|
68534
67743
|
if (existing.some((m3) => m3.id === message.id)) return;
|
|
68535
67744
|
const file = this.filePath(message.peerDeviceId);
|
|
68536
67745
|
const line = JSON.stringify(message) + "\n";
|
|
68537
|
-
|
|
67746
|
+
fs58.appendFileSync(file, line, { mode: 384 });
|
|
68538
67747
|
try {
|
|
68539
|
-
|
|
67748
|
+
fs58.chmodSync(file, 384);
|
|
68540
67749
|
} catch {
|
|
68541
67750
|
}
|
|
68542
67751
|
}
|
|
@@ -68566,7 +67775,7 @@ var InboxStore = class {
|
|
|
68566
67775
|
removeByPeerDeviceId(peerDeviceId) {
|
|
68567
67776
|
const file = this.filePath(peerDeviceId);
|
|
68568
67777
|
try {
|
|
68569
|
-
|
|
67778
|
+
fs58.unlinkSync(file);
|
|
68570
67779
|
} catch (err) {
|
|
68571
67780
|
if (err?.code === "ENOENT") return;
|
|
68572
67781
|
}
|
|
@@ -68575,18 +67784,18 @@ var InboxStore = class {
|
|
|
68575
67784
|
const file = this.filePath(peerDeviceId);
|
|
68576
67785
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
68577
67786
|
const content = messages.map((m3) => JSON.stringify(m3)).join("\n") + (messages.length > 0 ? "\n" : "");
|
|
68578
|
-
|
|
68579
|
-
|
|
67787
|
+
fs58.writeFileSync(tmp, content, { mode: 384 });
|
|
67788
|
+
fs58.renameSync(tmp, file);
|
|
68580
67789
|
try {
|
|
68581
|
-
|
|
67790
|
+
fs58.chmodSync(file, 384);
|
|
68582
67791
|
} catch {
|
|
68583
67792
|
}
|
|
68584
67793
|
}
|
|
68585
67794
|
dirPath() {
|
|
68586
|
-
return
|
|
67795
|
+
return path59.join(this.dataDir, INBOX_SUBDIR);
|
|
68587
67796
|
}
|
|
68588
67797
|
filePath(peerDeviceId) {
|
|
68589
|
-
return
|
|
67798
|
+
return path59.join(this.dirPath(), `${peerDeviceId}.jsonl`);
|
|
68590
67799
|
}
|
|
68591
67800
|
};
|
|
68592
67801
|
function parseAllLines(raw) {
|
|
@@ -68674,8 +67883,8 @@ var InboxManager = class {
|
|
|
68674
67883
|
};
|
|
68675
67884
|
|
|
68676
67885
|
// src/state/contact-store.ts
|
|
68677
|
-
var
|
|
68678
|
-
var
|
|
67886
|
+
var fs59 = __toESM(require("fs"), 1);
|
|
67887
|
+
var path60 = __toESM(require("path"), 1);
|
|
68679
67888
|
var FILE_NAME = "contacts.json";
|
|
68680
67889
|
var ContactStore = class {
|
|
68681
67890
|
constructor(dataDir) {
|
|
@@ -68685,10 +67894,10 @@ var ContactStore = class {
|
|
|
68685
67894
|
contacts = /* @__PURE__ */ new Map();
|
|
68686
67895
|
load() {
|
|
68687
67896
|
this.contacts.clear();
|
|
68688
|
-
const file =
|
|
67897
|
+
const file = path60.join(this.dataDir, FILE_NAME);
|
|
68689
67898
|
let raw;
|
|
68690
67899
|
try {
|
|
68691
|
-
raw =
|
|
67900
|
+
raw = fs59.readFileSync(file, "utf8");
|
|
68692
67901
|
} catch (err) {
|
|
68693
67902
|
if (err?.code !== "ENOENT") this.renameBak(file);
|
|
68694
67903
|
return;
|
|
@@ -68769,20 +67978,20 @@ var ContactStore = class {
|
|
|
68769
67978
|
return true;
|
|
68770
67979
|
}
|
|
68771
67980
|
flush() {
|
|
68772
|
-
const file =
|
|
67981
|
+
const file = path60.join(this.dataDir, FILE_NAME);
|
|
68773
67982
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
68774
67983
|
const content = JSON.stringify(
|
|
68775
67984
|
{ contacts: Array.from(this.contacts.values()) },
|
|
68776
67985
|
null,
|
|
68777
67986
|
2
|
|
68778
67987
|
);
|
|
68779
|
-
|
|
68780
|
-
|
|
68781
|
-
|
|
67988
|
+
fs59.mkdirSync(this.dataDir, { recursive: true });
|
|
67989
|
+
fs59.writeFileSync(tmp, content, { mode: 384 });
|
|
67990
|
+
fs59.renameSync(tmp, file);
|
|
68782
67991
|
}
|
|
68783
67992
|
renameBak(file) {
|
|
68784
67993
|
try {
|
|
68785
|
-
|
|
67994
|
+
fs59.renameSync(file, `${file}.bak`);
|
|
68786
67995
|
} catch {
|
|
68787
67996
|
}
|
|
68788
67997
|
}
|
|
@@ -68890,61 +68099,61 @@ async function connectRemote(args) {
|
|
|
68890
68099
|
}
|
|
68891
68100
|
|
|
68892
68101
|
// src/migrations/2026-05-20-flatten-sessions.ts
|
|
68893
|
-
var
|
|
68894
|
-
var
|
|
68102
|
+
var fs60 = __toESM(require("fs"), 1);
|
|
68103
|
+
var path61 = __toESM(require("path"), 1);
|
|
68895
68104
|
var MIGRATION_FLAG_NAME = ".migration.v1.done";
|
|
68896
68105
|
function migrateFlattenSessions(opts) {
|
|
68897
68106
|
const dataDir = opts.dataDir;
|
|
68898
68107
|
const now = opts.now ?? Date.now;
|
|
68899
|
-
const sessionsDir =
|
|
68900
|
-
const flagPath =
|
|
68108
|
+
const sessionsDir = path61.join(dataDir, "sessions");
|
|
68109
|
+
const flagPath = path61.join(sessionsDir, MIGRATION_FLAG_NAME);
|
|
68901
68110
|
if (existsSync3(flagPath)) {
|
|
68902
68111
|
return { skipped: true, flagWritten: false, movedBare: 0, movedVmOwner: 0, archivedListener: 0 };
|
|
68903
68112
|
}
|
|
68904
68113
|
let movedBare = 0;
|
|
68905
68114
|
let movedVmOwner = 0;
|
|
68906
68115
|
let archivedListener = 0;
|
|
68907
|
-
const defaultDir =
|
|
68116
|
+
const defaultDir = path61.join(sessionsDir, "default");
|
|
68908
68117
|
if (existsSync3(defaultDir)) {
|
|
68909
68118
|
for (const entry of readdirSafe(defaultDir)) {
|
|
68910
68119
|
if (!entry.endsWith(".json")) continue;
|
|
68911
|
-
const src =
|
|
68912
|
-
const dst =
|
|
68913
|
-
|
|
68120
|
+
const src = path61.join(defaultDir, entry);
|
|
68121
|
+
const dst = path61.join(sessionsDir, entry);
|
|
68122
|
+
fs60.renameSync(src, dst);
|
|
68914
68123
|
movedBare += 1;
|
|
68915
68124
|
}
|
|
68916
68125
|
rmdirIfEmpty(defaultDir);
|
|
68917
68126
|
}
|
|
68918
68127
|
for (const pid of readdirSafe(sessionsDir)) {
|
|
68919
|
-
const personaDir =
|
|
68128
|
+
const personaDir = path61.join(sessionsDir, pid);
|
|
68920
68129
|
if (!isDir(personaDir)) continue;
|
|
68921
68130
|
if (pid === "default") continue;
|
|
68922
|
-
const ownerSrc =
|
|
68131
|
+
const ownerSrc = path61.join(personaDir, "owner");
|
|
68923
68132
|
if (existsSync3(ownerSrc) && isDir(ownerSrc)) {
|
|
68924
|
-
const ownerDst =
|
|
68925
|
-
|
|
68133
|
+
const ownerDst = path61.join(dataDir, "personas", pid, ".clawd", "sessions", "owner");
|
|
68134
|
+
fs60.mkdirSync(ownerDst, { recursive: true });
|
|
68926
68135
|
for (const file of readdirSafe(ownerSrc)) {
|
|
68927
68136
|
if (!file.endsWith(".json")) continue;
|
|
68928
|
-
|
|
68137
|
+
fs60.renameSync(path61.join(ownerSrc, file), path61.join(ownerDst, file));
|
|
68929
68138
|
movedVmOwner += 1;
|
|
68930
68139
|
}
|
|
68931
68140
|
rmdirIfEmpty(ownerSrc);
|
|
68932
68141
|
}
|
|
68933
|
-
const listenerSrc =
|
|
68142
|
+
const listenerSrc = path61.join(personaDir, "listener");
|
|
68934
68143
|
if (existsSync3(listenerSrc) && isDir(listenerSrc)) {
|
|
68935
|
-
const archiveDst =
|
|
68936
|
-
|
|
68144
|
+
const archiveDst = path61.join(dataDir, ".legacy", `listener-${pid}`);
|
|
68145
|
+
fs60.mkdirSync(archiveDst, { recursive: true });
|
|
68937
68146
|
for (const file of readdirSafe(listenerSrc)) {
|
|
68938
68147
|
if (!file.endsWith(".json")) continue;
|
|
68939
|
-
|
|
68148
|
+
fs60.renameSync(path61.join(listenerSrc, file), path61.join(archiveDst, file));
|
|
68940
68149
|
archivedListener += 1;
|
|
68941
68150
|
}
|
|
68942
68151
|
rmdirIfEmpty(listenerSrc);
|
|
68943
68152
|
}
|
|
68944
68153
|
rmdirIfEmpty(personaDir);
|
|
68945
68154
|
}
|
|
68946
|
-
|
|
68947
|
-
|
|
68155
|
+
fs60.mkdirSync(sessionsDir, { recursive: true });
|
|
68156
|
+
fs60.writeFileSync(flagPath, JSON.stringify({ migratedAt: now() }, null, 2));
|
|
68948
68157
|
return {
|
|
68949
68158
|
skipped: false,
|
|
68950
68159
|
flagWritten: true,
|
|
@@ -68955,7 +68164,7 @@ function migrateFlattenSessions(opts) {
|
|
|
68955
68164
|
}
|
|
68956
68165
|
function existsSync3(p3) {
|
|
68957
68166
|
try {
|
|
68958
|
-
|
|
68167
|
+
fs60.statSync(p3);
|
|
68959
68168
|
return true;
|
|
68960
68169
|
} catch {
|
|
68961
68170
|
return false;
|
|
@@ -68963,63 +68172,63 @@ function existsSync3(p3) {
|
|
|
68963
68172
|
}
|
|
68964
68173
|
function isDir(p3) {
|
|
68965
68174
|
try {
|
|
68966
|
-
return
|
|
68175
|
+
return fs60.statSync(p3).isDirectory();
|
|
68967
68176
|
} catch {
|
|
68968
68177
|
return false;
|
|
68969
68178
|
}
|
|
68970
68179
|
}
|
|
68971
68180
|
function readdirSafe(p3) {
|
|
68972
68181
|
try {
|
|
68973
|
-
return
|
|
68182
|
+
return fs60.readdirSync(p3);
|
|
68974
68183
|
} catch {
|
|
68975
68184
|
return [];
|
|
68976
68185
|
}
|
|
68977
68186
|
}
|
|
68978
68187
|
function rmdirIfEmpty(p3) {
|
|
68979
68188
|
try {
|
|
68980
|
-
|
|
68189
|
+
fs60.rmdirSync(p3);
|
|
68981
68190
|
} catch {
|
|
68982
68191
|
}
|
|
68983
68192
|
}
|
|
68984
68193
|
|
|
68985
68194
|
// src/migrations/2026-08-18-drop-seeded-projects.ts
|
|
68986
|
-
var
|
|
68987
|
-
var
|
|
68195
|
+
var fs61 = __toESM(require("fs"), 1);
|
|
68196
|
+
var path62 = __toESM(require("path"), 1);
|
|
68988
68197
|
var DROP_SEEDED_PROJECTS_FLAG = ".projects-seed-dropped.v1.done";
|
|
68989
68198
|
function dropSeededProjects(opts) {
|
|
68990
|
-
|
|
68991
|
-
const flag =
|
|
68992
|
-
if (
|
|
68993
|
-
const file =
|
|
68199
|
+
fs61.mkdirSync(opts.dataDir, { recursive: true });
|
|
68200
|
+
const flag = path62.join(opts.dataDir, DROP_SEEDED_PROJECTS_FLAG);
|
|
68201
|
+
if (fs61.existsSync(flag)) return { skipped: true, dropped: 0, backup: null };
|
|
68202
|
+
const file = path62.join(opts.dataDir, "projects.json");
|
|
68994
68203
|
let raw = null;
|
|
68995
68204
|
let dropped = 0;
|
|
68996
68205
|
try {
|
|
68997
|
-
raw =
|
|
68206
|
+
raw = fs61.readFileSync(file, "utf8");
|
|
68998
68207
|
dropped = JSON.parse(raw).projects?.length ?? 0;
|
|
68999
68208
|
} catch {
|
|
69000
68209
|
}
|
|
69001
68210
|
let backup = null;
|
|
69002
68211
|
if (raw != null && dropped > 0) {
|
|
69003
|
-
const dir =
|
|
69004
|
-
|
|
69005
|
-
backup =
|
|
69006
|
-
|
|
68212
|
+
const dir = path62.join(opts.dataDir, "backups");
|
|
68213
|
+
fs61.mkdirSync(dir, { recursive: true });
|
|
68214
|
+
backup = path62.join(dir, `projects.seed-dropped.${(opts.now ?? Date.now)()}.json`);
|
|
68215
|
+
fs61.writeFileSync(backup, raw);
|
|
69007
68216
|
}
|
|
69008
68217
|
if (raw != null || dropped > 0) {
|
|
69009
|
-
|
|
68218
|
+
fs61.writeFileSync(file, JSON.stringify({ projects: [] }, null, 2));
|
|
69010
68219
|
}
|
|
69011
|
-
|
|
68220
|
+
fs61.writeFileSync(flag, (/* @__PURE__ */ new Date()).toISOString());
|
|
69012
68221
|
return { skipped: false, dropped, backup };
|
|
69013
68222
|
}
|
|
69014
68223
|
|
|
69015
68224
|
// src/transport/http-router.ts
|
|
69016
|
-
var
|
|
69017
|
-
var
|
|
68225
|
+
var import_node_fs48 = __toESM(require("fs"), 1);
|
|
68226
|
+
var import_node_path53 = __toESM(require("path"), 1);
|
|
69018
68227
|
|
|
69019
68228
|
// src/attachment/upload.ts
|
|
69020
|
-
var
|
|
69021
|
-
var
|
|
69022
|
-
var
|
|
68229
|
+
var import_node_fs47 = __toESM(require("fs"), 1);
|
|
68230
|
+
var import_node_path51 = __toESM(require("path"), 1);
|
|
68231
|
+
var import_node_crypto16 = __toESM(require("crypto"), 1);
|
|
69023
68232
|
var import_promises8 = require("stream/promises");
|
|
69024
68233
|
var UploadError = class extends Error {
|
|
69025
68234
|
constructor(code, message) {
|
|
@@ -69030,24 +68239,24 @@ var UploadError = class extends Error {
|
|
|
69030
68239
|
code;
|
|
69031
68240
|
};
|
|
69032
68241
|
function assertValidFileName(fileName) {
|
|
69033
|
-
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !==
|
|
68242
|
+
if (fileName.length === 0 || fileName === "." || fileName === ".." || fileName.startsWith(".") || fileName.includes("/") || fileName.includes("\\") || fileName !== import_node_path51.default.basename(fileName)) {
|
|
69034
68243
|
throw new UploadError("INVALID_FILENAME", `fileName must be a plain basename, got: ${fileName}`);
|
|
69035
68244
|
}
|
|
69036
68245
|
}
|
|
69037
68246
|
var HASH_PREFIX_LEN = 16;
|
|
69038
68247
|
async function writeUploadedAttachment(args) {
|
|
69039
68248
|
assertValidFileName(args.fileName);
|
|
69040
|
-
const attachmentsRoot =
|
|
68249
|
+
const attachmentsRoot = import_node_path51.default.join(args.baseDir, ".attachments");
|
|
69041
68250
|
try {
|
|
69042
|
-
|
|
68251
|
+
import_node_fs47.default.mkdirSync(attachmentsRoot, { recursive: true });
|
|
69043
68252
|
} catch (err) {
|
|
69044
68253
|
throw new UploadError("STORAGE_ERROR", `mkdir failed: ${err.message}`);
|
|
69045
68254
|
}
|
|
69046
|
-
const hasher =
|
|
68255
|
+
const hasher = import_node_crypto16.default.createHash("sha256");
|
|
69047
68256
|
let actualSize = 0;
|
|
69048
|
-
const tmpPath =
|
|
68257
|
+
const tmpPath = import_node_path51.default.join(
|
|
69049
68258
|
attachmentsRoot,
|
|
69050
|
-
`.upload-${process.pid}-${Date.now()}-${
|
|
68259
|
+
`.upload-${process.pid}-${Date.now()}-${import_node_crypto16.default.randomBytes(4).toString("hex")}`
|
|
69051
68260
|
);
|
|
69052
68261
|
try {
|
|
69053
68262
|
await (0, import_promises8.pipeline)(
|
|
@@ -69060,18 +68269,18 @@ async function writeUploadedAttachment(args) {
|
|
|
69060
68269
|
yield buf;
|
|
69061
68270
|
}
|
|
69062
68271
|
},
|
|
69063
|
-
|
|
68272
|
+
import_node_fs47.default.createWriteStream(tmpPath, { mode: 384 })
|
|
69064
68273
|
);
|
|
69065
68274
|
} catch (err) {
|
|
69066
68275
|
try {
|
|
69067
|
-
|
|
68276
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
69068
68277
|
} catch {
|
|
69069
68278
|
}
|
|
69070
68279
|
throw new UploadError("STORAGE_ERROR", `write failed: ${err.message}`);
|
|
69071
68280
|
}
|
|
69072
68281
|
if (actualSize !== args.contentLength) {
|
|
69073
68282
|
try {
|
|
69074
|
-
|
|
68283
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
69075
68284
|
} catch {
|
|
69076
68285
|
}
|
|
69077
68286
|
throw new UploadError(
|
|
@@ -69080,34 +68289,34 @@ async function writeUploadedAttachment(args) {
|
|
|
69080
68289
|
);
|
|
69081
68290
|
}
|
|
69082
68291
|
const attachmentId = hasher.digest("hex").slice(0, HASH_PREFIX_LEN);
|
|
69083
|
-
const hashDir =
|
|
68292
|
+
const hashDir = import_node_path51.default.join(attachmentsRoot, attachmentId);
|
|
69084
68293
|
let finalFileName;
|
|
69085
68294
|
let hashDirExists = false;
|
|
69086
68295
|
try {
|
|
69087
|
-
hashDirExists =
|
|
68296
|
+
hashDirExists = import_node_fs47.default.statSync(hashDir).isDirectory();
|
|
69088
68297
|
} catch {
|
|
69089
68298
|
}
|
|
69090
68299
|
if (hashDirExists) {
|
|
69091
|
-
const existing =
|
|
68300
|
+
const existing = import_node_fs47.default.readdirSync(hashDir).filter((n2) => !n2.startsWith("."));
|
|
69092
68301
|
finalFileName = existing[0] ?? args.fileName;
|
|
69093
68302
|
try {
|
|
69094
|
-
|
|
68303
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
69095
68304
|
} catch {
|
|
69096
68305
|
}
|
|
69097
68306
|
} else {
|
|
69098
68307
|
try {
|
|
69099
|
-
|
|
68308
|
+
import_node_fs47.default.mkdirSync(hashDir, { recursive: true });
|
|
69100
68309
|
finalFileName = args.fileName;
|
|
69101
|
-
|
|
68310
|
+
import_node_fs47.default.renameSync(tmpPath, import_node_path51.default.join(hashDir, finalFileName));
|
|
69102
68311
|
} catch (err) {
|
|
69103
68312
|
try {
|
|
69104
|
-
|
|
68313
|
+
import_node_fs47.default.unlinkSync(tmpPath);
|
|
69105
68314
|
} catch {
|
|
69106
68315
|
}
|
|
69107
68316
|
throw new UploadError("STORAGE_ERROR", `rename failed: ${err.message}`);
|
|
69108
68317
|
}
|
|
69109
68318
|
}
|
|
69110
|
-
const absPath =
|
|
68319
|
+
const absPath = import_node_path51.default.join(hashDir, finalFileName);
|
|
69111
68320
|
const relPath = absPath;
|
|
69112
68321
|
args.groupFileStore.upsert(args.scope, args.sessionId, {
|
|
69113
68322
|
relPath: absPath,
|
|
@@ -69122,7 +68331,7 @@ async function writeUploadedAttachment(args) {
|
|
|
69122
68331
|
|
|
69123
68332
|
// src/extension/import.ts
|
|
69124
68333
|
var import_promises9 = __toESM(require("fs/promises"), 1);
|
|
69125
|
-
var
|
|
68334
|
+
var import_node_path52 = __toESM(require("path"), 1);
|
|
69126
68335
|
var import_node_os20 = __toESM(require("os"), 1);
|
|
69127
68336
|
var import_jszip = __toESM(require_lib3(), 1);
|
|
69128
68337
|
var ImportError = class extends Error {
|
|
@@ -69140,7 +68349,7 @@ async function importZip(buf, root) {
|
|
|
69140
68349
|
throw new ImportError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
69141
68350
|
}
|
|
69142
68351
|
for (const name of Object.keys(zip.files)) {
|
|
69143
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
68352
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path52.default.isAbsolute(name)) {
|
|
69144
68353
|
throw new ImportError("ZIP_INVALID", `unsafe zip entry path: ${name}`);
|
|
69145
68354
|
}
|
|
69146
68355
|
}
|
|
@@ -69173,7 +68382,7 @@ async function importZip(buf, root) {
|
|
|
69173
68382
|
);
|
|
69174
68383
|
}
|
|
69175
68384
|
}
|
|
69176
|
-
const destDir =
|
|
68385
|
+
const destDir = import_node_path52.default.join(root, manifest.id);
|
|
69177
68386
|
let destExists = false;
|
|
69178
68387
|
try {
|
|
69179
68388
|
await import_promises9.default.access(destDir);
|
|
@@ -69183,15 +68392,15 @@ async function importZip(buf, root) {
|
|
|
69183
68392
|
if (destExists) {
|
|
69184
68393
|
throw new ImportError("ALREADY_EXISTS", `extension ${manifest.id} already installed`);
|
|
69185
68394
|
}
|
|
69186
|
-
const stage = await import_promises9.default.mkdtemp(
|
|
68395
|
+
const stage = await import_promises9.default.mkdtemp(import_node_path52.default.join(import_node_os20.default.tmpdir(), `clawd-ext-stage-${manifest.id}-`));
|
|
69187
68396
|
try {
|
|
69188
68397
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
69189
|
-
const dest =
|
|
68398
|
+
const dest = import_node_path52.default.join(stage, name);
|
|
69190
68399
|
if (entry.dir) {
|
|
69191
68400
|
await import_promises9.default.mkdir(dest, { recursive: true });
|
|
69192
68401
|
continue;
|
|
69193
68402
|
}
|
|
69194
|
-
await import_promises9.default.mkdir(
|
|
68403
|
+
await import_promises9.default.mkdir(import_node_path52.default.dirname(dest), { recursive: true });
|
|
69195
68404
|
const content = await entry.async("nodebuffer");
|
|
69196
68405
|
await import_promises9.default.writeFile(dest, content);
|
|
69197
68406
|
}
|
|
@@ -69245,7 +68454,7 @@ var SHARE_UI_ASSET_MIME = {
|
|
|
69245
68454
|
".wasm": "application/wasm"
|
|
69246
68455
|
};
|
|
69247
68456
|
function shareUiAssetMime(filePath) {
|
|
69248
|
-
const ext =
|
|
68457
|
+
const ext = import_node_path53.default.extname(filePath).toLowerCase();
|
|
69249
68458
|
return SHARE_UI_ASSET_MIME[ext] ?? lookupMime(filePath);
|
|
69250
68459
|
}
|
|
69251
68460
|
var AUTHED_RPC_ROUTE_PREFIX = "/rpc/";
|
|
@@ -69344,7 +68553,7 @@ function isValidUploadFileName(fileName) {
|
|
|
69344
68553
|
if (fileName === "." || fileName === "..") return false;
|
|
69345
68554
|
if (fileName.startsWith(".")) return false;
|
|
69346
68555
|
if (fileName.includes("/") || fileName.includes("\\")) return false;
|
|
69347
|
-
return fileName ===
|
|
68556
|
+
return fileName === import_node_path53.default.basename(fileName);
|
|
69348
68557
|
}
|
|
69349
68558
|
function createHttpRouter(deps) {
|
|
69350
68559
|
return async (req, res) => {
|
|
@@ -69428,7 +68637,7 @@ function createHttpRouter(deps) {
|
|
|
69428
68637
|
}
|
|
69429
68638
|
let buf;
|
|
69430
68639
|
try {
|
|
69431
|
-
buf = await
|
|
68640
|
+
buf = await import_node_fs48.default.promises.readFile(abs);
|
|
69432
68641
|
} catch {
|
|
69433
68642
|
sendJson2(res, 404, { code: "NOT_FOUND", message: "asset not found" });
|
|
69434
68643
|
return true;
|
|
@@ -69574,7 +68783,7 @@ function createHttpRouter(deps) {
|
|
|
69574
68783
|
sendHtml(res, statusByCode[r2.code], loader.renderErrorHtml(r2.code, msgByCode[r2.code]));
|
|
69575
68784
|
return true;
|
|
69576
68785
|
}
|
|
69577
|
-
sendHtml(res, 200, loader.renderViewerHtml(
|
|
68786
|
+
sendHtml(res, 200, loader.renderViewerHtml(import_node_path53.default.basename(r2.absPath)));
|
|
69578
68787
|
return true;
|
|
69579
68788
|
}
|
|
69580
68789
|
const ctx = deps.authResolver.resolveFromHeader(
|
|
@@ -69695,7 +68904,7 @@ function createHttpRouter(deps) {
|
|
|
69695
68904
|
return true;
|
|
69696
68905
|
}
|
|
69697
68906
|
let absPath;
|
|
69698
|
-
if (
|
|
68907
|
+
if (import_node_path53.default.isAbsolute(pathParam)) {
|
|
69699
68908
|
absPath = pathParam;
|
|
69700
68909
|
} else if (deps.sessionStore) {
|
|
69701
68910
|
const file = deps.sessionStore.read(sid);
|
|
@@ -69703,7 +68912,7 @@ function createHttpRouter(deps) {
|
|
|
69703
68912
|
sendJson2(res, 404, { code: "NOT_FOUND", message: `session ${sid} not found` });
|
|
69704
68913
|
return true;
|
|
69705
68914
|
}
|
|
69706
|
-
absPath =
|
|
68915
|
+
absPath = import_node_path53.default.join(file.cwd, pathParam);
|
|
69707
68916
|
} else {
|
|
69708
68917
|
sendJson2(res, 501, withCtx(ctx, { code: "NOT_IMPLEMENTED", message: "sessionStore not wired" }));
|
|
69709
68918
|
return true;
|
|
@@ -69787,7 +68996,7 @@ function withCtx(ctx, body) {
|
|
|
69787
68996
|
function streamFile(res, absPath, logger) {
|
|
69788
68997
|
let stat;
|
|
69789
68998
|
try {
|
|
69790
|
-
stat =
|
|
68999
|
+
stat = import_node_fs48.default.statSync(absPath);
|
|
69791
69000
|
} catch (err) {
|
|
69792
69001
|
const code = err?.code;
|
|
69793
69002
|
if (code === "ENOENT") {
|
|
@@ -69802,7 +69011,7 @@ function streamFile(res, absPath, logger) {
|
|
|
69802
69011
|
return;
|
|
69803
69012
|
}
|
|
69804
69013
|
const mime = lookupMime(absPath);
|
|
69805
|
-
const basename2 =
|
|
69014
|
+
const basename2 = import_node_path53.default.basename(absPath);
|
|
69806
69015
|
res.writeHead(200, {
|
|
69807
69016
|
"Content-Type": mime,
|
|
69808
69017
|
"Content-Length": String(stat.size),
|
|
@@ -69810,7 +69019,7 @@ function streamFile(res, absPath, logger) {
|
|
|
69810
69019
|
// 防止浏览器把任意 mime 当 html 渲染
|
|
69811
69020
|
"X-Content-Type-Options": "nosniff"
|
|
69812
69021
|
});
|
|
69813
|
-
const stream =
|
|
69022
|
+
const stream = import_node_fs48.default.createReadStream(absPath);
|
|
69814
69023
|
stream.on("error", (err) => {
|
|
69815
69024
|
logger?.warn("streamFile read error", { absPath, err: err.message });
|
|
69816
69025
|
res.destroy();
|
|
@@ -69819,8 +69028,8 @@ function streamFile(res, absPath, logger) {
|
|
|
69819
69028
|
}
|
|
69820
69029
|
|
|
69821
69030
|
// src/attachment/gc.ts
|
|
69822
|
-
var
|
|
69823
|
-
var
|
|
69031
|
+
var import_node_fs49 = __toESM(require("fs"), 1);
|
|
69032
|
+
var import_node_path54 = __toESM(require("path"), 1);
|
|
69824
69033
|
var DEFAULT_TTL_MS = 30 * 24 * 3600 * 1e3;
|
|
69825
69034
|
function runAttachmentGc(args) {
|
|
69826
69035
|
const now = (args.now ?? Date.now)();
|
|
@@ -69829,12 +69038,12 @@ function runAttachmentGc(args) {
|
|
|
69829
69038
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
69830
69039
|
for (const entry of args.groupFileStore.list(scope, sessionId)) {
|
|
69831
69040
|
if (entry.stale) continue;
|
|
69832
|
-
if (
|
|
69041
|
+
if (import_node_path54.default.isAbsolute(entry.relPath)) liveAbs.add(entry.relPath);
|
|
69833
69042
|
}
|
|
69834
69043
|
}
|
|
69835
69044
|
const visited = /* @__PURE__ */ new Set();
|
|
69836
69045
|
for (const { scope, sessionId } of args.sessionScopes) {
|
|
69837
|
-
const legacyDir = args.getSessionCwd?.(sessionId) ??
|
|
69046
|
+
const legacyDir = args.getSessionCwd?.(sessionId) ?? import_node_path54.default.join(
|
|
69838
69047
|
args.dataDir,
|
|
69839
69048
|
"sessions",
|
|
69840
69049
|
...scopeSubPath(scope).map(safeFileName),
|
|
@@ -69847,28 +69056,28 @@ function runAttachmentGc(args) {
|
|
|
69847
69056
|
return true;
|
|
69848
69057
|
});
|
|
69849
69058
|
for (const rootDir of roots) {
|
|
69850
|
-
const attRoot =
|
|
69059
|
+
const attRoot = import_node_path54.default.join(rootDir, ".attachments");
|
|
69851
69060
|
let hashDirs;
|
|
69852
69061
|
try {
|
|
69853
|
-
hashDirs =
|
|
69062
|
+
hashDirs = import_node_fs49.default.readdirSync(attRoot);
|
|
69854
69063
|
} catch (err) {
|
|
69855
69064
|
if (err.code === "ENOENT") continue;
|
|
69856
69065
|
args.logger?.warn("attachment gc: readdir failed", { attRoot, err: err.message });
|
|
69857
69066
|
continue;
|
|
69858
69067
|
}
|
|
69859
69068
|
for (const hashDir of hashDirs) {
|
|
69860
|
-
const hashDirAbs =
|
|
69069
|
+
const hashDirAbs = import_node_path54.default.join(attRoot, hashDir);
|
|
69861
69070
|
let files;
|
|
69862
69071
|
try {
|
|
69863
|
-
files =
|
|
69072
|
+
files = import_node_fs49.default.readdirSync(hashDirAbs);
|
|
69864
69073
|
} catch {
|
|
69865
69074
|
continue;
|
|
69866
69075
|
}
|
|
69867
69076
|
for (const name of files) {
|
|
69868
|
-
const file =
|
|
69077
|
+
const file = import_node_path54.default.join(hashDirAbs, name);
|
|
69869
69078
|
let stat;
|
|
69870
69079
|
try {
|
|
69871
|
-
stat =
|
|
69080
|
+
stat = import_node_fs49.default.statSync(file);
|
|
69872
69081
|
} catch {
|
|
69873
69082
|
continue;
|
|
69874
69083
|
}
|
|
@@ -69877,18 +69086,18 @@ function runAttachmentGc(args) {
|
|
|
69877
69086
|
if (age < ttlMs) continue;
|
|
69878
69087
|
if (liveAbs.has(file)) continue;
|
|
69879
69088
|
try {
|
|
69880
|
-
|
|
69089
|
+
import_node_fs49.default.unlinkSync(file);
|
|
69881
69090
|
} catch (err) {
|
|
69882
69091
|
args.logger?.warn("attachment gc: unlink failed", { file, err: err.message });
|
|
69883
69092
|
}
|
|
69884
69093
|
}
|
|
69885
69094
|
try {
|
|
69886
|
-
if (
|
|
69095
|
+
if (import_node_fs49.default.readdirSync(hashDirAbs).length === 0) import_node_fs49.default.rmdirSync(hashDirAbs);
|
|
69887
69096
|
} catch {
|
|
69888
69097
|
}
|
|
69889
69098
|
}
|
|
69890
69099
|
try {
|
|
69891
|
-
if (
|
|
69100
|
+
if (import_node_fs49.default.readdirSync(attRoot).length === 0) import_node_fs49.default.rmdirSync(attRoot);
|
|
69892
69101
|
} catch {
|
|
69893
69102
|
}
|
|
69894
69103
|
}
|
|
@@ -69896,9 +69105,9 @@ function runAttachmentGc(args) {
|
|
|
69896
69105
|
}
|
|
69897
69106
|
|
|
69898
69107
|
// src/attachment/group.ts
|
|
69899
|
-
var
|
|
69900
|
-
var
|
|
69901
|
-
var
|
|
69108
|
+
var import_node_fs50 = __toESM(require("fs"), 1);
|
|
69109
|
+
var import_node_path55 = __toESM(require("path"), 1);
|
|
69110
|
+
var import_node_crypto17 = __toESM(require("crypto"), 1);
|
|
69902
69111
|
init_protocol();
|
|
69903
69112
|
var GroupFileStore = class {
|
|
69904
69113
|
dataDir;
|
|
@@ -69909,11 +69118,11 @@ var GroupFileStore = class {
|
|
|
69909
69118
|
this.logger = opts.logger;
|
|
69910
69119
|
}
|
|
69911
69120
|
rootForScope(scope) {
|
|
69912
|
-
return
|
|
69121
|
+
return import_node_path55.default.join(this.dataDir, "sessions", ...scopeSubPath(scope).map(safeFileName));
|
|
69913
69122
|
}
|
|
69914
69123
|
/** 与 SessionStore.filePath 平级,扩展名 .group-files.json */
|
|
69915
69124
|
filePath(scope, sessionId) {
|
|
69916
|
-
return
|
|
69125
|
+
return import_node_path55.default.join(this.rootForScope(scope), `${safeFileName(sessionId)}.group-files.json`);
|
|
69917
69126
|
}
|
|
69918
69127
|
cacheKey(scope, sessionId) {
|
|
69919
69128
|
return scope.kind === "default" ? `default::${sessionId}` : `persona:${scope.personaId}:${scope.mode}::${sessionId}`;
|
|
@@ -69922,7 +69131,7 @@ var GroupFileStore = class {
|
|
|
69922
69131
|
readFile(scope, sessionId) {
|
|
69923
69132
|
const file = this.filePath(scope, sessionId);
|
|
69924
69133
|
try {
|
|
69925
|
-
const raw =
|
|
69134
|
+
const raw = import_node_fs50.default.readFileSync(file, "utf8");
|
|
69926
69135
|
const parsed = JSON.parse(raw);
|
|
69927
69136
|
if (!Array.isArray(parsed)) {
|
|
69928
69137
|
this.logger?.warn("GroupFileStore.readFile: not an array; resetting session entries", {
|
|
@@ -69948,10 +69157,10 @@ var GroupFileStore = class {
|
|
|
69948
69157
|
}
|
|
69949
69158
|
writeFile(scope, sessionId, entries) {
|
|
69950
69159
|
const file = this.filePath(scope, sessionId);
|
|
69951
|
-
|
|
69160
|
+
import_node_fs50.default.mkdirSync(import_node_path55.default.dirname(file), { recursive: true });
|
|
69952
69161
|
const tmp = `${file}.tmp-${process.pid}-${Date.now()}`;
|
|
69953
|
-
|
|
69954
|
-
|
|
69162
|
+
import_node_fs50.default.writeFileSync(tmp, JSON.stringify(entries, null, 2), { mode: 384 });
|
|
69163
|
+
import_node_fs50.default.renameSync(tmp, file);
|
|
69955
69164
|
}
|
|
69956
69165
|
/** 拉一份当前 session 的清单。读盘 → cache;之后调用复用 cache */
|
|
69957
69166
|
list(scope, sessionId) {
|
|
@@ -69987,7 +69196,7 @@ var GroupFileStore = class {
|
|
|
69987
69196
|
entries[idx] = next;
|
|
69988
69197
|
} else {
|
|
69989
69198
|
next = {
|
|
69990
|
-
id: `gf-${
|
|
69199
|
+
id: `gf-${import_node_crypto17.default.randomBytes(6).toString("base64url")}`,
|
|
69991
69200
|
relPath: input.relPath,
|
|
69992
69201
|
from: input.from,
|
|
69993
69202
|
label: input.label,
|
|
@@ -70043,7 +69252,7 @@ var GroupFileStore = class {
|
|
|
70043
69252
|
*/
|
|
70044
69253
|
deleteSession(scope, sessionId) {
|
|
70045
69254
|
try {
|
|
70046
|
-
|
|
69255
|
+
import_node_fs50.default.unlinkSync(this.filePath(scope, sessionId));
|
|
70047
69256
|
} catch (err) {
|
|
70048
69257
|
if (err?.code !== "ENOENT") throw err;
|
|
70049
69258
|
}
|
|
@@ -70056,7 +69265,7 @@ var GroupFileStore = class {
|
|
|
70056
69265
|
* 不在 persona 目录里(见文件头的路径约定)。没树的 persona 是 noop。
|
|
70057
69266
|
*/
|
|
70058
69267
|
deletePersona(personaId2) {
|
|
70059
|
-
|
|
69268
|
+
import_node_fs50.default.rmSync(import_node_path55.default.join(this.dataDir, "sessions", safeFileName(personaId2)), { recursive: true, force: true });
|
|
70060
69269
|
const prefix = `persona:${personaId2}:`;
|
|
70061
69270
|
for (const key of this.cache.keys()) {
|
|
70062
69271
|
if (key.startsWith(prefix)) this.cache.delete(key);
|
|
@@ -70065,10 +69274,10 @@ var GroupFileStore = class {
|
|
|
70065
69274
|
};
|
|
70066
69275
|
|
|
70067
69276
|
// src/discovery/state-file.ts
|
|
70068
|
-
var
|
|
70069
|
-
var
|
|
69277
|
+
var import_node_fs51 = __toESM(require("fs"), 1);
|
|
69278
|
+
var import_node_path56 = __toESM(require("path"), 1);
|
|
70070
69279
|
function defaultStateFilePath(dataDir) {
|
|
70071
|
-
return
|
|
69280
|
+
return import_node_path56.default.join(dataDir, "state.json");
|
|
70072
69281
|
}
|
|
70073
69282
|
function isPidAlive(pid) {
|
|
70074
69283
|
if (!Number.isFinite(pid) || pid <= 0) return false;
|
|
@@ -70090,7 +69299,7 @@ var StateFileManager = class {
|
|
|
70090
69299
|
}
|
|
70091
69300
|
read() {
|
|
70092
69301
|
try {
|
|
70093
|
-
const raw =
|
|
69302
|
+
const raw = import_node_fs51.default.readFileSync(this.file, "utf8");
|
|
70094
69303
|
const parsed = JSON.parse(raw);
|
|
70095
69304
|
return parsed;
|
|
70096
69305
|
} catch {
|
|
@@ -70104,20 +69313,20 @@ var StateFileManager = class {
|
|
|
70104
69313
|
return { status: "stale", existing };
|
|
70105
69314
|
}
|
|
70106
69315
|
write(state) {
|
|
70107
|
-
|
|
69316
|
+
import_node_fs51.default.mkdirSync(import_node_path56.default.dirname(this.file), { recursive: true });
|
|
70108
69317
|
const tmp = `${this.file}.tmp.${process.pid}.${Date.now()}`;
|
|
70109
|
-
|
|
70110
|
-
|
|
69318
|
+
import_node_fs51.default.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 384 });
|
|
69319
|
+
import_node_fs51.default.renameSync(tmp, this.file);
|
|
70111
69320
|
if (process.platform !== "win32") {
|
|
70112
69321
|
try {
|
|
70113
|
-
|
|
69322
|
+
import_node_fs51.default.chmodSync(this.file, 384);
|
|
70114
69323
|
} catch {
|
|
70115
69324
|
}
|
|
70116
69325
|
}
|
|
70117
69326
|
}
|
|
70118
69327
|
delete() {
|
|
70119
69328
|
try {
|
|
70120
|
-
|
|
69329
|
+
import_node_fs51.default.unlinkSync(this.file);
|
|
70121
69330
|
} catch {
|
|
70122
69331
|
}
|
|
70123
69332
|
}
|
|
@@ -70131,14 +69340,14 @@ function readSpawnedByDesktopFromEnv(env = process.env) {
|
|
|
70131
69340
|
}
|
|
70132
69341
|
|
|
70133
69342
|
// src/tunnel/tunnel-manager.ts
|
|
70134
|
-
var
|
|
70135
|
-
var
|
|
70136
|
-
var
|
|
69343
|
+
var import_node_fs55 = __toESM(require("fs"), 1);
|
|
69344
|
+
var import_node_path60 = __toESM(require("path"), 1);
|
|
69345
|
+
var import_node_crypto18 = __toESM(require("crypto"), 1);
|
|
70137
69346
|
var import_node_child_process16 = require("child_process");
|
|
70138
69347
|
|
|
70139
69348
|
// src/tunnel/tunnel-store.ts
|
|
70140
|
-
var
|
|
70141
|
-
var
|
|
69349
|
+
var import_node_fs52 = __toESM(require("fs"), 1);
|
|
69350
|
+
var import_node_path57 = __toESM(require("path"), 1);
|
|
70142
69351
|
var TunnelStore = class {
|
|
70143
69352
|
constructor(filePath) {
|
|
70144
69353
|
this.filePath = filePath;
|
|
@@ -70146,7 +69355,7 @@ var TunnelStore = class {
|
|
|
70146
69355
|
filePath;
|
|
70147
69356
|
async get() {
|
|
70148
69357
|
try {
|
|
70149
|
-
const raw = await
|
|
69358
|
+
const raw = await import_node_fs52.default.promises.readFile(this.filePath, "utf8");
|
|
70150
69359
|
const obj = JSON.parse(raw);
|
|
70151
69360
|
if (!isPersistedTunnel(obj)) return null;
|
|
70152
69361
|
return obj;
|
|
@@ -70157,22 +69366,22 @@ var TunnelStore = class {
|
|
|
70157
69366
|
}
|
|
70158
69367
|
}
|
|
70159
69368
|
async set(v3) {
|
|
70160
|
-
const dir =
|
|
70161
|
-
await
|
|
69369
|
+
const dir = import_node_path57.default.dirname(this.filePath);
|
|
69370
|
+
await import_node_fs52.default.promises.mkdir(dir, { recursive: true });
|
|
70162
69371
|
const data = JSON.stringify(v3, null, 2);
|
|
70163
69372
|
const tmp = `${this.filePath}.tmp.${process.pid}.${Date.now()}`;
|
|
70164
|
-
await
|
|
69373
|
+
await import_node_fs52.default.promises.writeFile(tmp, data, { mode: 384 });
|
|
70165
69374
|
if (process.platform !== "win32") {
|
|
70166
69375
|
try {
|
|
70167
|
-
await
|
|
69376
|
+
await import_node_fs52.default.promises.chmod(tmp, 384);
|
|
70168
69377
|
} catch {
|
|
70169
69378
|
}
|
|
70170
69379
|
}
|
|
70171
|
-
await
|
|
69380
|
+
await import_node_fs52.default.promises.rename(tmp, this.filePath);
|
|
70172
69381
|
}
|
|
70173
69382
|
async clear() {
|
|
70174
69383
|
try {
|
|
70175
|
-
await
|
|
69384
|
+
await import_node_fs52.default.promises.unlink(this.filePath);
|
|
70176
69385
|
} catch (err) {
|
|
70177
69386
|
const code = err?.code;
|
|
70178
69387
|
if (code !== "ENOENT") throw err;
|
|
@@ -70267,9 +69476,9 @@ function escape2(v3) {
|
|
|
70267
69476
|
}
|
|
70268
69477
|
|
|
70269
69478
|
// src/tunnel/frpc-binary.ts
|
|
70270
|
-
var
|
|
69479
|
+
var import_node_fs53 = __toESM(require("fs"), 1);
|
|
70271
69480
|
var import_node_os21 = __toESM(require("os"), 1);
|
|
70272
|
-
var
|
|
69481
|
+
var import_node_path58 = __toESM(require("path"), 1);
|
|
70273
69482
|
var import_node_child_process14 = require("child_process");
|
|
70274
69483
|
var import_node_stream4 = require("stream");
|
|
70275
69484
|
var import_promises10 = require("stream/promises");
|
|
@@ -70301,20 +69510,20 @@ function frpcDownloadUrl(version2, p3) {
|
|
|
70301
69510
|
}
|
|
70302
69511
|
async function ensureFrpcBinary(opts) {
|
|
70303
69512
|
if (opts.override) {
|
|
70304
|
-
if (!
|
|
69513
|
+
if (!import_node_fs53.default.existsSync(opts.override)) {
|
|
70305
69514
|
throw new Error(`frpc binary not found at override path: ${opts.override}`);
|
|
70306
69515
|
}
|
|
70307
69516
|
return opts.override;
|
|
70308
69517
|
}
|
|
70309
69518
|
const version2 = opts.version ?? FRPC_VERSION;
|
|
70310
69519
|
const platform = opts.platform ?? detectPlatform();
|
|
70311
|
-
const binDir =
|
|
70312
|
-
|
|
69520
|
+
const binDir = import_node_path58.default.join(opts.dataDir, "bin");
|
|
69521
|
+
import_node_fs53.default.mkdirSync(binDir, { recursive: true });
|
|
70313
69522
|
cleanupStaleArtifacts(binDir);
|
|
70314
|
-
const stableBin =
|
|
70315
|
-
if (
|
|
69523
|
+
const stableBin = import_node_path58.default.join(binDir, "frpc");
|
|
69524
|
+
if (import_node_fs53.default.existsSync(stableBin)) return stableBin;
|
|
70316
69525
|
const partialBin = `${stableBin}.partial`;
|
|
70317
|
-
const tarballPath =
|
|
69526
|
+
const tarballPath = import_node_path58.default.join(binDir, `frp_${version2}_${platform.os}_${platform.arch}.tar.gz.partial`);
|
|
70318
69527
|
try {
|
|
70319
69528
|
const url = frpcDownloadUrl(version2, platform);
|
|
70320
69529
|
await downloadToFile(url, tarballPath, opts.fetchImpl);
|
|
@@ -70323,8 +69532,8 @@ async function ensureFrpcBinary(opts) {
|
|
|
70323
69532
|
} else {
|
|
70324
69533
|
await extractFrpcFromTarball(tarballPath, binDir, version2, platform, partialBin);
|
|
70325
69534
|
}
|
|
70326
|
-
|
|
70327
|
-
|
|
69535
|
+
import_node_fs53.default.chmodSync(partialBin, 493);
|
|
69536
|
+
import_node_fs53.default.renameSync(partialBin, stableBin);
|
|
70328
69537
|
} finally {
|
|
70329
69538
|
safeUnlink(tarballPath);
|
|
70330
69539
|
safeUnlink(partialBin);
|
|
@@ -70334,15 +69543,15 @@ async function ensureFrpcBinary(opts) {
|
|
|
70334
69543
|
function cleanupStaleArtifacts(binDir) {
|
|
70335
69544
|
let entries;
|
|
70336
69545
|
try {
|
|
70337
|
-
entries =
|
|
69546
|
+
entries = import_node_fs53.default.readdirSync(binDir);
|
|
70338
69547
|
} catch {
|
|
70339
69548
|
return;
|
|
70340
69549
|
}
|
|
70341
69550
|
for (const name of entries) {
|
|
70342
69551
|
if (name.endsWith(".partial") || name.startsWith("extract-")) {
|
|
70343
|
-
const full =
|
|
69552
|
+
const full = import_node_path58.default.join(binDir, name);
|
|
70344
69553
|
try {
|
|
70345
|
-
|
|
69554
|
+
import_node_fs53.default.rmSync(full, { recursive: true, force: true });
|
|
70346
69555
|
} catch {
|
|
70347
69556
|
}
|
|
70348
69557
|
}
|
|
@@ -70350,7 +69559,7 @@ function cleanupStaleArtifacts(binDir) {
|
|
|
70350
69559
|
}
|
|
70351
69560
|
function safeUnlink(p3) {
|
|
70352
69561
|
try {
|
|
70353
|
-
|
|
69562
|
+
import_node_fs53.default.unlinkSync(p3);
|
|
70354
69563
|
} catch {
|
|
70355
69564
|
}
|
|
70356
69565
|
}
|
|
@@ -70361,13 +69570,13 @@ async function downloadToFile(url, dest, fetchImpl) {
|
|
|
70361
69570
|
if (!res.ok || !res.body) {
|
|
70362
69571
|
throw new Error(`download failed: ${res.status} ${res.statusText}`);
|
|
70363
69572
|
}
|
|
70364
|
-
const out =
|
|
69573
|
+
const out = import_node_fs53.default.createWriteStream(dest);
|
|
70365
69574
|
const nodeStream = import_node_stream4.Readable.fromWeb(res.body);
|
|
70366
69575
|
await (0, import_promises10.pipeline)(nodeStream, out);
|
|
70367
69576
|
}
|
|
70368
69577
|
async function extractFrpcFromTarball(tarball, binDir, version2, platform, destBin) {
|
|
70369
|
-
const work =
|
|
70370
|
-
|
|
69578
|
+
const work = import_node_path58.default.join(binDir, `extract-${process.pid}-${Date.now()}`);
|
|
69579
|
+
import_node_fs53.default.mkdirSync(work, { recursive: true });
|
|
70371
69580
|
try {
|
|
70372
69581
|
await new Promise((resolve9, reject) => {
|
|
70373
69582
|
const proc = (0, import_node_child_process14.spawn)("tar", ["xzf", tarball, "-C", work], { stdio: "pipe" });
|
|
@@ -70375,32 +69584,32 @@ async function extractFrpcFromTarball(tarball, binDir, version2, platform, destB
|
|
|
70375
69584
|
proc.on("exit", (code) => code === 0 ? resolve9() : reject(new Error(`tar exited ${code}`)));
|
|
70376
69585
|
});
|
|
70377
69586
|
const dirName = `frp_${version2}_${platform.os}_${platform.arch}`;
|
|
70378
|
-
const src =
|
|
70379
|
-
if (!
|
|
69587
|
+
const src = import_node_path58.default.join(work, dirName, "frpc");
|
|
69588
|
+
if (!import_node_fs53.default.existsSync(src)) {
|
|
70380
69589
|
throw new Error(`frpc not found inside tarball at ${src}`);
|
|
70381
69590
|
}
|
|
70382
|
-
|
|
69591
|
+
import_node_fs53.default.copyFileSync(src, destBin);
|
|
70383
69592
|
} finally {
|
|
70384
|
-
|
|
69593
|
+
import_node_fs53.default.rmSync(work, { recursive: true, force: true });
|
|
70385
69594
|
}
|
|
70386
69595
|
}
|
|
70387
69596
|
|
|
70388
69597
|
// src/tunnel/frpc-process.ts
|
|
70389
|
-
var
|
|
70390
|
-
var
|
|
69598
|
+
var import_node_fs54 = __toESM(require("fs"), 1);
|
|
69599
|
+
var import_node_path59 = __toESM(require("path"), 1);
|
|
70391
69600
|
var import_node_child_process15 = require("child_process");
|
|
70392
69601
|
function frpcPidFilePath(dataDir) {
|
|
70393
|
-
return
|
|
69602
|
+
return import_node_path59.default.join(dataDir, "frpc.pid");
|
|
70394
69603
|
}
|
|
70395
69604
|
function writeFrpcPid(dataDir, pid) {
|
|
70396
69605
|
try {
|
|
70397
|
-
|
|
69606
|
+
import_node_fs54.default.writeFileSync(frpcPidFilePath(dataDir), String(pid), { mode: 384 });
|
|
70398
69607
|
} catch {
|
|
70399
69608
|
}
|
|
70400
69609
|
}
|
|
70401
69610
|
function clearFrpcPid(dataDir) {
|
|
70402
69611
|
try {
|
|
70403
|
-
|
|
69612
|
+
import_node_fs54.default.unlinkSync(frpcPidFilePath(dataDir));
|
|
70404
69613
|
} catch {
|
|
70405
69614
|
}
|
|
70406
69615
|
}
|
|
@@ -70416,7 +69625,7 @@ function defaultIsPidAlive(pid) {
|
|
|
70416
69625
|
}
|
|
70417
69626
|
function defaultReadPidFile(file) {
|
|
70418
69627
|
try {
|
|
70419
|
-
return
|
|
69628
|
+
return import_node_fs54.default.readFileSync(file, "utf8");
|
|
70420
69629
|
} catch {
|
|
70421
69630
|
return null;
|
|
70422
69631
|
}
|
|
@@ -70432,7 +69641,7 @@ function defaultSleep2(ms) {
|
|
|
70432
69641
|
}
|
|
70433
69642
|
async function killStaleFrpc(deps) {
|
|
70434
69643
|
const pidFile = frpcPidFilePath(deps.dataDir);
|
|
70435
|
-
const tomlPath =
|
|
69644
|
+
const tomlPath = import_node_path59.default.join(deps.dataDir, "frpc.toml");
|
|
70436
69645
|
const readPidFile = deps.readPidFileImpl ?? defaultReadPidFile;
|
|
70437
69646
|
const isAlive = deps.isPidAliveImpl ?? defaultIsPidAlive;
|
|
70438
69647
|
const killPid = deps.killPidImpl ?? defaultKillPid;
|
|
@@ -70456,7 +69665,7 @@ async function killStaleFrpc(deps) {
|
|
|
70456
69665
|
}
|
|
70457
69666
|
if (victims.size === 0) {
|
|
70458
69667
|
try {
|
|
70459
|
-
|
|
69668
|
+
import_node_fs54.default.unlinkSync(pidFile);
|
|
70460
69669
|
} catch {
|
|
70461
69670
|
}
|
|
70462
69671
|
return;
|
|
@@ -70467,7 +69676,7 @@ async function killStaleFrpc(deps) {
|
|
|
70467
69676
|
}
|
|
70468
69677
|
await sleep2(deps.reapWaitMs ?? 300);
|
|
70469
69678
|
try {
|
|
70470
|
-
|
|
69679
|
+
import_node_fs54.default.unlinkSync(pidFile);
|
|
70471
69680
|
} catch {
|
|
70472
69681
|
}
|
|
70473
69682
|
}
|
|
@@ -70504,7 +69713,7 @@ var DEFAULT_TUNNEL_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
70504
69713
|
var TunnelManager = class {
|
|
70505
69714
|
constructor(deps) {
|
|
70506
69715
|
this.deps = deps;
|
|
70507
|
-
this.store = deps.store ?? new TunnelStore(
|
|
69716
|
+
this.store = deps.store ?? new TunnelStore(import_node_path60.default.join(deps.dataDir, "tunnel.json"));
|
|
70508
69717
|
this.ttlMs = deps.ttlMs ?? DEFAULT_TUNNEL_TTL_MS;
|
|
70509
69718
|
this.startupTimeoutMs = deps.startupTimeoutMs ?? 15e3;
|
|
70510
69719
|
}
|
|
@@ -70631,8 +69840,8 @@ var TunnelManager = class {
|
|
|
70631
69840
|
dataDir: this.deps.dataDir,
|
|
70632
69841
|
override: this.deps.frpcBinaryOverride ?? void 0
|
|
70633
69842
|
});
|
|
70634
|
-
const tomlPath =
|
|
70635
|
-
const proxyName = `clawd-${t2.subdomain}-${localPort}-${
|
|
69843
|
+
const tomlPath = import_node_path60.default.join(this.deps.dataDir, "frpc.toml");
|
|
69844
|
+
const proxyName = `clawd-${t2.subdomain}-${localPort}-${import_node_crypto18.default.randomBytes(3).toString("hex")}`;
|
|
70636
69845
|
const toml = buildFrpcToml({
|
|
70637
69846
|
serverAddr: t2.frpsHost,
|
|
70638
69847
|
serverPort: t2.frpsPort,
|
|
@@ -70642,14 +69851,14 @@ var TunnelManager = class {
|
|
|
70642
69851
|
localPort,
|
|
70643
69852
|
logLevel: "info"
|
|
70644
69853
|
});
|
|
70645
|
-
await
|
|
69854
|
+
await import_node_fs55.default.promises.writeFile(tomlPath, toml, { mode: 384 });
|
|
70646
69855
|
const proc = (this.deps.spawnImpl ?? import_node_child_process16.spawn)(frpcBin, ["-c", tomlPath], {
|
|
70647
69856
|
stdio: ["ignore", "pipe", "pipe"]
|
|
70648
69857
|
});
|
|
70649
|
-
const logDir =
|
|
70650
|
-
|
|
70651
|
-
const logFilePath =
|
|
70652
|
-
const logStream =
|
|
69858
|
+
const logDir = import_node_path60.default.join(this.deps.dataDir, "log");
|
|
69859
|
+
import_node_fs55.default.mkdirSync(logDir, { recursive: true });
|
|
69860
|
+
const logFilePath = import_node_path60.default.join(logDir, "frpc.log");
|
|
69861
|
+
const logStream = import_node_fs55.default.createWriteStream(logFilePath, { flags: "a", mode: 384 });
|
|
70653
69862
|
logStream.on("error", () => {
|
|
70654
69863
|
});
|
|
70655
69864
|
const tee = (chunk) => {
|
|
@@ -70732,27 +69941,27 @@ async function waitForFrpcReady(proc, timeoutMs) {
|
|
|
70732
69941
|
|
|
70733
69942
|
// src/tunnel/device-key.ts
|
|
70734
69943
|
var import_node_os22 = __toESM(require("os"), 1);
|
|
70735
|
-
var
|
|
70736
|
-
var
|
|
69944
|
+
var import_node_path61 = __toESM(require("path"), 1);
|
|
69945
|
+
var import_node_crypto19 = __toESM(require("crypto"), 1);
|
|
70737
69946
|
var DERIVE_SALT = "clawd-tunnel-device-v1";
|
|
70738
69947
|
function deriveStableDeviceKey(opts = {}) {
|
|
70739
69948
|
const hostname = opts.hostname ?? import_node_os22.default.hostname();
|
|
70740
69949
|
const uid = opts.uid ?? (typeof import_node_os22.default.userInfo === "function" ? import_node_os22.default.userInfo().uid : 0);
|
|
70741
69950
|
const home = opts.home ?? import_node_os22.default.homedir();
|
|
70742
|
-
const defaultDataDir =
|
|
70743
|
-
const normalizedDataDir = opts.dataDir ?
|
|
69951
|
+
const defaultDataDir = import_node_path61.default.resolve(import_node_path61.default.join(home, ".clawd"));
|
|
69952
|
+
const normalizedDataDir = opts.dataDir ? import_node_path61.default.resolve(opts.dataDir) : null;
|
|
70744
69953
|
const isDefaultDir = normalizedDataDir == null || normalizedDataDir === defaultDataDir;
|
|
70745
69954
|
const input = isDefaultDir ? `${hostname}::${uid}` : `${hostname}::${uid}::${normalizedDataDir}`;
|
|
70746
|
-
return
|
|
69955
|
+
return import_node_crypto19.default.createHmac("sha256", DERIVE_SALT).update(input).digest("hex").slice(0, 32);
|
|
70747
69956
|
}
|
|
70748
69957
|
|
|
70749
69958
|
// src/auth-store.ts
|
|
70750
|
-
var
|
|
70751
|
-
var
|
|
70752
|
-
var
|
|
69959
|
+
var import_node_fs56 = __toESM(require("fs"), 1);
|
|
69960
|
+
var import_node_path62 = __toESM(require("path"), 1);
|
|
69961
|
+
var import_node_crypto20 = __toESM(require("crypto"), 1);
|
|
70753
69962
|
var AUTH_FILE_NAME = "auth.json";
|
|
70754
69963
|
function authFilePath(dataDir) {
|
|
70755
|
-
return
|
|
69964
|
+
return import_node_path62.default.join(dataDir, AUTH_FILE_NAME);
|
|
70756
69965
|
}
|
|
70757
69966
|
function loadOrCreateAuthFile(opts) {
|
|
70758
69967
|
const file = authFilePath(opts.dataDir);
|
|
@@ -70786,14 +69995,14 @@ function loadOrCreateTunnelDeviceKey(opts) {
|
|
|
70786
69995
|
return tunnelDeviceKey;
|
|
70787
69996
|
}
|
|
70788
69997
|
function defaultGenerateToken() {
|
|
70789
|
-
return
|
|
69998
|
+
return import_node_crypto20.default.randomBytes(32).toString("base64url");
|
|
70790
69999
|
}
|
|
70791
70000
|
function defaultGenerateOwnerPrincipalId() {
|
|
70792
|
-
return `owner-${
|
|
70001
|
+
return `owner-${import_node_crypto20.default.randomUUID()}`;
|
|
70793
70002
|
}
|
|
70794
70003
|
function readAuthFile(file) {
|
|
70795
70004
|
try {
|
|
70796
|
-
const raw =
|
|
70005
|
+
const raw = import_node_fs56.default.readFileSync(file, "utf8");
|
|
70797
70006
|
const parsed = JSON.parse(raw);
|
|
70798
70007
|
if (typeof parsed?.token !== "string" || parsed.token.length === 0) {
|
|
70799
70008
|
return null;
|
|
@@ -70814,26 +70023,26 @@ function readAuthFile(file) {
|
|
|
70814
70023
|
}
|
|
70815
70024
|
}
|
|
70816
70025
|
function writeAuthFile(file, content) {
|
|
70817
|
-
|
|
70818
|
-
|
|
70026
|
+
import_node_fs56.default.mkdirSync(import_node_path62.default.dirname(file), { recursive: true });
|
|
70027
|
+
import_node_fs56.default.writeFileSync(file, JSON.stringify(content, null, 2), { mode: 384 });
|
|
70819
70028
|
try {
|
|
70820
|
-
|
|
70029
|
+
import_node_fs56.default.chmodSync(file, 384);
|
|
70821
70030
|
} catch {
|
|
70822
70031
|
}
|
|
70823
70032
|
}
|
|
70824
70033
|
|
|
70825
70034
|
// src/owner-profile.ts
|
|
70826
|
-
var
|
|
70035
|
+
var import_node_fs57 = __toESM(require("fs"), 1);
|
|
70827
70036
|
var import_node_os23 = __toESM(require("os"), 1);
|
|
70828
|
-
var
|
|
70037
|
+
var import_node_path63 = __toESM(require("path"), 1);
|
|
70829
70038
|
var PROFILE_FILENAME = "profile.json";
|
|
70830
70039
|
function profilePath(dataDir) {
|
|
70831
|
-
return
|
|
70040
|
+
return import_node_path63.default.join(dataDir, PROFILE_FILENAME);
|
|
70832
70041
|
}
|
|
70833
70042
|
function loadOwnerProfile(dataDir) {
|
|
70834
70043
|
let raw;
|
|
70835
70044
|
try {
|
|
70836
|
-
raw =
|
|
70045
|
+
raw = import_node_fs57.default.readFileSync(profilePath(dataDir), "utf8");
|
|
70837
70046
|
} catch {
|
|
70838
70047
|
return {};
|
|
70839
70048
|
}
|
|
@@ -70849,7 +70058,7 @@ function loadOwnerProfile(dataDir) {
|
|
|
70849
70058
|
}
|
|
70850
70059
|
function patchOwnerProfile(dataDir, patch) {
|
|
70851
70060
|
const merged = { ...loadOwnerProfile(dataDir), ...patch };
|
|
70852
|
-
|
|
70061
|
+
import_node_fs57.default.writeFileSync(profilePath(dataDir), JSON.stringify(merged, null, 2), { encoding: "utf8", mode: 384 });
|
|
70853
70062
|
return merged;
|
|
70854
70063
|
}
|
|
70855
70064
|
function loadOwnerDisplayName(dataDir) {
|
|
@@ -70865,18 +70074,18 @@ function loadOwnerDisplayName(dataDir) {
|
|
|
70865
70074
|
}
|
|
70866
70075
|
|
|
70867
70076
|
// src/feishu-auth/owner-identity-store.ts
|
|
70868
|
-
var
|
|
70869
|
-
var
|
|
70077
|
+
var import_node_fs58 = __toESM(require("fs"), 1);
|
|
70078
|
+
var import_node_path64 = __toESM(require("path"), 1);
|
|
70870
70079
|
var OWNER_IDENTITY_FILE_NAME = "owner-identity.json";
|
|
70871
70080
|
var OwnerIdentityStore = class {
|
|
70872
70081
|
file;
|
|
70873
70082
|
constructor(dataDir) {
|
|
70874
|
-
this.file =
|
|
70083
|
+
this.file = import_node_path64.default.join(dataDir, OWNER_IDENTITY_FILE_NAME);
|
|
70875
70084
|
}
|
|
70876
70085
|
read() {
|
|
70877
70086
|
let raw;
|
|
70878
70087
|
try {
|
|
70879
|
-
raw =
|
|
70088
|
+
raw = import_node_fs58.default.readFileSync(this.file, "utf8");
|
|
70880
70089
|
} catch {
|
|
70881
70090
|
return null;
|
|
70882
70091
|
}
|
|
@@ -70903,16 +70112,16 @@ var OwnerIdentityStore = class {
|
|
|
70903
70112
|
};
|
|
70904
70113
|
}
|
|
70905
70114
|
write(record4) {
|
|
70906
|
-
|
|
70907
|
-
|
|
70115
|
+
import_node_fs58.default.mkdirSync(import_node_path64.default.dirname(this.file), { recursive: true });
|
|
70116
|
+
import_node_fs58.default.writeFileSync(this.file, JSON.stringify(record4, null, 2), { mode: 384 });
|
|
70908
70117
|
try {
|
|
70909
|
-
|
|
70118
|
+
import_node_fs58.default.chmodSync(this.file, 384);
|
|
70910
70119
|
} catch {
|
|
70911
70120
|
}
|
|
70912
70121
|
}
|
|
70913
70122
|
clear() {
|
|
70914
70123
|
try {
|
|
70915
|
-
|
|
70124
|
+
import_node_fs58.default.unlinkSync(this.file);
|
|
70916
70125
|
} catch (err) {
|
|
70917
70126
|
const code = err?.code;
|
|
70918
70127
|
if (code !== "ENOENT") throw err;
|
|
@@ -70921,7 +70130,7 @@ var OwnerIdentityStore = class {
|
|
|
70921
70130
|
};
|
|
70922
70131
|
|
|
70923
70132
|
// src/feishu-auth/login-flow.ts
|
|
70924
|
-
var
|
|
70133
|
+
var import_node_crypto21 = __toESM(require("crypto"), 1);
|
|
70925
70134
|
var STATE_TTL_MS = 5 * 60 * 1e3;
|
|
70926
70135
|
var LoginFlow = class {
|
|
70927
70136
|
constructor(deps) {
|
|
@@ -70930,7 +70139,7 @@ var LoginFlow = class {
|
|
|
70930
70139
|
deps;
|
|
70931
70140
|
pendingStates = /* @__PURE__ */ new Map();
|
|
70932
70141
|
start() {
|
|
70933
|
-
const state =
|
|
70142
|
+
const state = import_node_crypto21.default.randomBytes(16).toString("base64url");
|
|
70934
70143
|
const now = (this.deps.now ?? Date.now)();
|
|
70935
70144
|
this.pendingStates.set(state, now);
|
|
70936
70145
|
this.gcExpired(now);
|
|
@@ -71408,8 +70617,8 @@ function verifyConnectToken(args) {
|
|
|
71408
70617
|
}
|
|
71409
70618
|
|
|
71410
70619
|
// src/feishu-auth/server-key.ts
|
|
71411
|
-
var
|
|
71412
|
-
var
|
|
70620
|
+
var fs75 = __toESM(require("fs"), 1);
|
|
70621
|
+
var path77 = __toESM(require("path"), 1);
|
|
71413
70622
|
var FILE_NAME2 = "server-signing-key.json";
|
|
71414
70623
|
var ServerKeyStore = class {
|
|
71415
70624
|
constructor(dataDir) {
|
|
@@ -71417,12 +70626,12 @@ var ServerKeyStore = class {
|
|
|
71417
70626
|
}
|
|
71418
70627
|
dataDir;
|
|
71419
70628
|
filePath() {
|
|
71420
|
-
return
|
|
70629
|
+
return path77.join(this.dataDir, FILE_NAME2);
|
|
71421
70630
|
}
|
|
71422
70631
|
/** 读缓存的公钥;无缓存 / 损坏 → null(调用方决定是否触发拉取) */
|
|
71423
70632
|
read() {
|
|
71424
70633
|
try {
|
|
71425
|
-
const raw =
|
|
70634
|
+
const raw = fs75.readFileSync(this.filePath(), "utf8");
|
|
71426
70635
|
const parsed = JSON.parse(raw);
|
|
71427
70636
|
if (typeof parsed.publicKeyPem === "string" && parsed.publicKeyPem.includes("PUBLIC KEY")) {
|
|
71428
70637
|
return parsed.publicKeyPem;
|
|
@@ -71437,12 +70646,12 @@ var ServerKeyStore = class {
|
|
|
71437
70646
|
publicKeyPem,
|
|
71438
70647
|
fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
71439
70648
|
};
|
|
71440
|
-
|
|
71441
|
-
|
|
70649
|
+
fs75.mkdirSync(this.dataDir, { recursive: true });
|
|
70650
|
+
fs75.writeFileSync(this.filePath(), JSON.stringify(content, null, 2), { mode: 384 });
|
|
71442
70651
|
}
|
|
71443
70652
|
clear() {
|
|
71444
70653
|
try {
|
|
71445
|
-
|
|
70654
|
+
fs75.unlinkSync(this.filePath());
|
|
71446
70655
|
} catch {
|
|
71447
70656
|
}
|
|
71448
70657
|
}
|
|
@@ -71452,19 +70661,19 @@ var ServerKeyStore = class {
|
|
|
71452
70661
|
init_protocol();
|
|
71453
70662
|
|
|
71454
70663
|
// src/handlers/index.ts
|
|
71455
|
-
var
|
|
70664
|
+
var import_node_path80 = __toESM(require("path"), 1);
|
|
71456
70665
|
|
|
71457
70666
|
// src/handlers/session.ts
|
|
71458
70667
|
init_protocol();
|
|
71459
70668
|
|
|
71460
70669
|
// src/session/fork.ts
|
|
71461
|
-
var
|
|
70670
|
+
var import_node_fs59 = __toESM(require("fs"), 1);
|
|
71462
70671
|
var import_node_os24 = __toESM(require("os"), 1);
|
|
71463
|
-
var
|
|
71464
|
-
var
|
|
70672
|
+
var import_node_path65 = __toESM(require("path"), 1);
|
|
70673
|
+
var import_node_crypto22 = require("crypto");
|
|
71465
70674
|
init_claude_history();
|
|
71466
70675
|
function readJsonlEntries(file) {
|
|
71467
|
-
const raw =
|
|
70676
|
+
const raw = import_node_fs59.default.readFileSync(file, "utf8");
|
|
71468
70677
|
const out = [];
|
|
71469
70678
|
for (const line of raw.split("\n")) {
|
|
71470
70679
|
const t2 = line.trim();
|
|
@@ -71477,19 +70686,19 @@ function readJsonlEntries(file) {
|
|
|
71477
70686
|
return out;
|
|
71478
70687
|
}
|
|
71479
70688
|
function forkSession(input) {
|
|
71480
|
-
const baseDir = input.baseDir ??
|
|
71481
|
-
let projectDir =
|
|
71482
|
-
let sourceFile =
|
|
71483
|
-
if (!
|
|
70689
|
+
const baseDir = input.baseDir ?? import_node_path65.default.join(import_node_os24.default.homedir(), ".claude");
|
|
70690
|
+
let projectDir = import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.cwd));
|
|
70691
|
+
let sourceFile = import_node_path65.default.join(projectDir, `${input.toolSessionId}.jsonl`);
|
|
70692
|
+
if (!import_node_fs59.default.existsSync(sourceFile)) {
|
|
71484
70693
|
const found = findTranscriptByToolSessionId(
|
|
71485
|
-
|
|
70694
|
+
import_node_path65.default.join(baseDir, "projects"),
|
|
71486
70695
|
input.toolSessionId
|
|
71487
70696
|
);
|
|
71488
70697
|
if (!found) {
|
|
71489
70698
|
throw new Error(`fork: source transcript not found: ${sourceFile}`);
|
|
71490
70699
|
}
|
|
71491
70700
|
sourceFile = found;
|
|
71492
|
-
projectDir =
|
|
70701
|
+
projectDir = import_node_path65.default.dirname(found);
|
|
71493
70702
|
}
|
|
71494
70703
|
const entries = readJsonlEntries(sourceFile);
|
|
71495
70704
|
const mainEntries = entries.filter((e) => e.isSidechain !== true);
|
|
@@ -71498,7 +70707,7 @@ function forkSession(input) {
|
|
|
71498
70707
|
throw new Error(`fork: messageUuid not found in transcript: ${input.messageUuid}`);
|
|
71499
70708
|
}
|
|
71500
70709
|
const sliced = mainEntries.slice(0, targetIdx + 1);
|
|
71501
|
-
const forkedToolSessionId = (0,
|
|
70710
|
+
const forkedToolSessionId = (0, import_node_crypto22.randomUUID)();
|
|
71502
70711
|
let parentUuid = null;
|
|
71503
70712
|
const forkedLines = [];
|
|
71504
70713
|
for (const entry of sliced) {
|
|
@@ -71518,17 +70727,17 @@ function forkSession(input) {
|
|
|
71518
70727
|
}
|
|
71519
70728
|
forkedLines.push(JSON.stringify(forked));
|
|
71520
70729
|
}
|
|
71521
|
-
const outDir = input.targetCwd ?
|
|
71522
|
-
const forkedFilePath =
|
|
71523
|
-
|
|
71524
|
-
|
|
70730
|
+
const outDir = input.targetCwd ? import_node_path65.default.join(baseDir, "projects", cwdToHashDir(input.targetCwd)) : projectDir;
|
|
70731
|
+
const forkedFilePath = import_node_path65.default.join(outDir, `${forkedToolSessionId}.jsonl`);
|
|
70732
|
+
import_node_fs59.default.mkdirSync(outDir, { recursive: true });
|
|
70733
|
+
import_node_fs59.default.writeFileSync(forkedFilePath, forkedLines.join("\n") + "\n", { mode: 384 });
|
|
71525
70734
|
return { forkedToolSessionId, forkedFilePath };
|
|
71526
70735
|
}
|
|
71527
70736
|
|
|
71528
70737
|
// src/tools/codex-fork.ts
|
|
71529
70738
|
var import_node_child_process17 = require("child_process");
|
|
71530
|
-
var
|
|
71531
|
-
var
|
|
70739
|
+
var import_node_fs60 = __toESM(require("fs"), 1);
|
|
70740
|
+
var import_node_path66 = __toESM(require("path"), 1);
|
|
71532
70741
|
function openCodexAppServer(home, cwd) {
|
|
71533
70742
|
const proc = (0, import_node_child_process17.spawn)(process.env.CODEX_BIN ?? "codex", ["app-server", "--listen", "stdio://"], {
|
|
71534
70743
|
cwd,
|
|
@@ -71548,7 +70757,7 @@ function openCodexAppServer(home, cwd) {
|
|
|
71548
70757
|
async function forkCodexThread(input, deps = {}) {
|
|
71549
70758
|
const source = locateCodexThread(input.roots, input.sourceThreadId);
|
|
71550
70759
|
if (!source) throw new Error(`codex fork: source thread not found: ${input.sourceThreadId}`);
|
|
71551
|
-
const rollout = parseCodexRollout(
|
|
70760
|
+
const rollout = parseCodexRollout(import_node_fs60.default.readFileSync(source.file, "utf8"));
|
|
71552
70761
|
if (rollout.meta?.threadId.toLowerCase() !== input.sourceThreadId.toLowerCase()) {
|
|
71553
70762
|
throw new Error(`codex fork: source thread metadata does not match ${input.sourceThreadId}`);
|
|
71554
70763
|
}
|
|
@@ -71578,7 +70787,7 @@ async function forkCodexThread(input, deps = {}) {
|
|
|
71578
70787
|
if (typeof forkedToolSessionId !== "string" || !forkedToolSessionId) {
|
|
71579
70788
|
throw new Error("codex fork: app-server returned no thread id");
|
|
71580
70789
|
}
|
|
71581
|
-
const forked = locateCodexThread([
|
|
70790
|
+
const forked = locateCodexThread([import_node_path66.default.join(source.home, "sessions")], forkedToolSessionId);
|
|
71582
70791
|
if (!forked) throw new Error(`codex fork: rollout not found for forked thread ${forkedToolSessionId}`);
|
|
71583
70792
|
return { forkedToolSessionId, forkedFilePath: forked.file };
|
|
71584
70793
|
})()]);
|
|
@@ -71589,19 +70798,19 @@ async function forkCodexThread(input, deps = {}) {
|
|
|
71589
70798
|
}
|
|
71590
70799
|
|
|
71591
70800
|
// src/session/external-scan.ts
|
|
71592
|
-
var
|
|
70801
|
+
var import_node_fs61 = __toESM(require("fs"), 1);
|
|
71593
70802
|
var import_promises11 = __toESM(require("fs/promises"), 1);
|
|
71594
70803
|
var import_node_os25 = __toESM(require("os"), 1);
|
|
71595
|
-
var
|
|
70804
|
+
var import_node_path67 = __toESM(require("path"), 1);
|
|
71596
70805
|
var import_node_module = require("module");
|
|
71597
70806
|
var import_node_child_process18 = require("child_process");
|
|
71598
70807
|
var import_meta7 = {};
|
|
71599
70808
|
function defaultRoots() {
|
|
71600
70809
|
const home = import_node_os25.default.homedir();
|
|
71601
70810
|
return {
|
|
71602
|
-
claudeProjectsDir:
|
|
71603
|
-
codexDir:
|
|
71604
|
-
clawdDir:
|
|
70811
|
+
claudeProjectsDir: import_node_path67.default.join(home, ".claude", "projects"),
|
|
70812
|
+
codexDir: import_node_path67.default.join(home, ".codex"),
|
|
70813
|
+
clawdDir: import_node_path67.default.join(home, ".clawd")
|
|
71605
70814
|
};
|
|
71606
70815
|
}
|
|
71607
70816
|
function width(s2) {
|
|
@@ -71652,7 +70861,7 @@ function userText(msg) {
|
|
|
71652
70861
|
}
|
|
71653
70862
|
function isDir2(p3) {
|
|
71654
70863
|
try {
|
|
71655
|
-
return
|
|
70864
|
+
return import_node_fs61.default.statSync(p3).isDirectory();
|
|
71656
70865
|
} catch {
|
|
71657
70866
|
return false;
|
|
71658
70867
|
}
|
|
@@ -71661,7 +70870,7 @@ async function scanClaude(roots) {
|
|
|
71661
70870
|
const out = [];
|
|
71662
70871
|
let dirs;
|
|
71663
70872
|
try {
|
|
71664
|
-
dirs =
|
|
70873
|
+
dirs = import_node_fs61.default.readdirSync(roots.claudeProjectsDir, { withFileTypes: true });
|
|
71665
70874
|
} catch {
|
|
71666
70875
|
return out;
|
|
71667
70876
|
}
|
|
@@ -71669,16 +70878,16 @@ async function scanClaude(roots) {
|
|
|
71669
70878
|
if (!d2.isDirectory()) continue;
|
|
71670
70879
|
let files;
|
|
71671
70880
|
try {
|
|
71672
|
-
files =
|
|
70881
|
+
files = import_node_fs61.default.readdirSync(import_node_path67.default.join(roots.claudeProjectsDir, d2.name));
|
|
71673
70882
|
} catch {
|
|
71674
70883
|
continue;
|
|
71675
70884
|
}
|
|
71676
70885
|
for (const name of files) {
|
|
71677
70886
|
if (!name.endsWith(".jsonl")) continue;
|
|
71678
|
-
const file =
|
|
70887
|
+
const file = import_node_path67.default.join(roots.claudeProjectsDir, d2.name, name);
|
|
71679
70888
|
let st2;
|
|
71680
70889
|
try {
|
|
71681
|
-
st2 =
|
|
70890
|
+
st2 = import_node_fs61.default.statSync(file);
|
|
71682
70891
|
} catch {
|
|
71683
70892
|
continue;
|
|
71684
70893
|
}
|
|
@@ -71731,7 +70940,7 @@ async function scanClaude(roots) {
|
|
|
71731
70940
|
return out;
|
|
71732
70941
|
}
|
|
71733
70942
|
async function countCodexTurns(rolloutPath) {
|
|
71734
|
-
if (!rolloutPath || !
|
|
70943
|
+
if (!rolloutPath || !import_node_fs61.default.existsSync(rolloutPath)) return { turns: 0, first: "" };
|
|
71735
70944
|
let turns = 0;
|
|
71736
70945
|
let first = "";
|
|
71737
70946
|
for await (const rec6 of jsonLines(rolloutPath)) {
|
|
@@ -71805,7 +71014,7 @@ async function codexFromRows(rows) {
|
|
|
71805
71014
|
async function scanCodex(roots) {
|
|
71806
71015
|
let dbs = [];
|
|
71807
71016
|
try {
|
|
71808
|
-
dbs =
|
|
71017
|
+
dbs = import_node_fs61.default.readdirSync(roots.codexDir).filter((n2) => /^state_.*\.sqlite$/.test(n2)).sort().map((n2) => import_node_path67.default.join(roots.codexDir, n2));
|
|
71809
71018
|
} catch {
|
|
71810
71019
|
}
|
|
71811
71020
|
if (!dbs.length) return [];
|
|
@@ -71814,14 +71023,14 @@ async function scanCodex(roots) {
|
|
|
71814
71023
|
}
|
|
71815
71024
|
async function scanExternalSessions(rootsIn) {
|
|
71816
71025
|
const roots = { ...defaultRoots(), ...rootsIn };
|
|
71817
|
-
const personaRoot =
|
|
71026
|
+
const personaRoot = import_node_path67.default.join(roots.clawdDir, "personas");
|
|
71818
71027
|
const all = [...await scanClaude(roots), ...await scanCodex(roots)];
|
|
71819
71028
|
const out = [];
|
|
71820
71029
|
for (const c2 of all) {
|
|
71821
71030
|
if (c2.skip) continue;
|
|
71822
71031
|
if (c2.turns < 1) continue;
|
|
71823
71032
|
if (!c2.cwd || !isDir2(c2.cwd)) continue;
|
|
71824
|
-
if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot +
|
|
71033
|
+
if (c2.cwd === roots.clawdDir || c2.cwd === personaRoot || c2.cwd.startsWith(personaRoot + import_node_path67.default.sep) || c2.cwd.startsWith(roots.clawdDir + import_node_path67.default.sep)) {
|
|
71825
71034
|
continue;
|
|
71826
71035
|
}
|
|
71827
71036
|
out.push({
|
|
@@ -71838,13 +71047,13 @@ async function scanExternalSessions(rootsIn) {
|
|
|
71838
71047
|
}
|
|
71839
71048
|
|
|
71840
71049
|
// src/session/import-ledger.ts
|
|
71841
|
-
var
|
|
71842
|
-
var
|
|
71050
|
+
var import_node_fs62 = __toESM(require("fs"), 1);
|
|
71051
|
+
var import_node_path68 = __toESM(require("path"), 1);
|
|
71843
71052
|
var LEDGER_FILENAME = "session-import-ledger.json";
|
|
71844
71053
|
function readImportLedger(dataDir) {
|
|
71845
71054
|
try {
|
|
71846
71055
|
const parsed = JSON.parse(
|
|
71847
|
-
|
|
71056
|
+
import_node_fs62.default.readFileSync(import_node_path68.default.join(dataDir, LEDGER_FILENAME), "utf8")
|
|
71848
71057
|
);
|
|
71849
71058
|
return Array.isArray(parsed) ? parsed : [];
|
|
71850
71059
|
} catch {
|
|
@@ -71852,15 +71061,15 @@ function readImportLedger(dataDir) {
|
|
|
71852
71061
|
}
|
|
71853
71062
|
}
|
|
71854
71063
|
function appendImportLedger(dataDir, entry) {
|
|
71855
|
-
const file =
|
|
71064
|
+
const file = import_node_path68.default.join(dataDir, LEDGER_FILENAME);
|
|
71856
71065
|
const entries = readImportLedger(dataDir);
|
|
71857
71066
|
entries.push(entry);
|
|
71858
|
-
|
|
71067
|
+
import_node_fs62.default.writeFileSync(file, JSON.stringify(entries, null, 2), { encoding: "utf8", mode: 384 });
|
|
71859
71068
|
}
|
|
71860
71069
|
|
|
71861
71070
|
// src/handlers/session.ts
|
|
71862
71071
|
init_protocol();
|
|
71863
|
-
var
|
|
71072
|
+
var import_node_path69 = __toESM(require("path"), 1);
|
|
71864
71073
|
function canReadSearchHit(ctx, file) {
|
|
71865
71074
|
if (!ctx || ctx.principal.kind === "owner") return true;
|
|
71866
71075
|
return canAccessPersona(ctx.grants, file.ownerPersonaId, "read") && file.creatorPrincipalId === ctx.principal.id;
|
|
@@ -72141,7 +71350,7 @@ ${attribution}` } : args;
|
|
|
72141
71350
|
`principal guest:${ctx.principal.id} cannot fork tool session ${args.toolSessionId}`
|
|
72142
71351
|
);
|
|
72143
71352
|
}
|
|
72144
|
-
if (source?.tool === "codex" && args.targetCwd &&
|
|
71353
|
+
if (source?.tool === "codex" && args.targetCwd && import_node_path69.default.resolve(args.targetCwd) !== import_node_path69.default.resolve(source.cwd)) {
|
|
72145
71354
|
throw new ClawdError(ERROR_CODES.FORBIDDEN, "fork: guest targetCwd must match source cwd");
|
|
72146
71355
|
}
|
|
72147
71356
|
}
|
|
@@ -72418,7 +71627,7 @@ function buildPermissionHandlers(deps) {
|
|
|
72418
71627
|
}
|
|
72419
71628
|
|
|
72420
71629
|
// src/handlers/history.ts
|
|
72421
|
-
var
|
|
71630
|
+
var path84 = __toESM(require("path"), 1);
|
|
72422
71631
|
init_protocol();
|
|
72423
71632
|
|
|
72424
71633
|
// src/session/recent-dirs.ts
|
|
@@ -72436,7 +71645,7 @@ function listRecentDirs(store, limit = 50) {
|
|
|
72436
71645
|
}
|
|
72437
71646
|
|
|
72438
71647
|
// src/permission/persona-paths.ts
|
|
72439
|
-
var
|
|
71648
|
+
var path83 = __toESM(require("path"), 1);
|
|
72440
71649
|
function getAllowedPersonaIds(grants, action) {
|
|
72441
71650
|
const ids = /* @__PURE__ */ new Set();
|
|
72442
71651
|
for (const g3 of grants) {
|
|
@@ -72449,42 +71658,42 @@ function getAllowedPersonaIds(grants, action) {
|
|
|
72449
71658
|
return ids;
|
|
72450
71659
|
}
|
|
72451
71660
|
function isGuestPathAllowed(grants, absPath, personaRoot, action = "read", userWorkDir) {
|
|
72452
|
-
const target =
|
|
71661
|
+
const target = path83.resolve(absPath);
|
|
72453
71662
|
if (userWorkDir) {
|
|
72454
|
-
const u2 =
|
|
72455
|
-
const usep = u2.endsWith(
|
|
71663
|
+
const u2 = path83.resolve(userWorkDir);
|
|
71664
|
+
const usep = u2.endsWith(path83.sep) ? "" : path83.sep;
|
|
72456
71665
|
if (target === u2 || target.startsWith(u2 + usep)) return true;
|
|
72457
71666
|
}
|
|
72458
|
-
const root =
|
|
72459
|
-
const sep4 = root.endsWith(
|
|
71667
|
+
const root = path83.resolve(personaRoot);
|
|
71668
|
+
const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
|
|
72460
71669
|
if (!target.startsWith(root + sep4)) return false;
|
|
72461
|
-
const rel =
|
|
71670
|
+
const rel = path83.relative(root, target);
|
|
72462
71671
|
if (!rel || rel.startsWith("..")) return false;
|
|
72463
|
-
const personaId2 = rel.split(
|
|
71672
|
+
const personaId2 = rel.split(path83.sep)[0];
|
|
72464
71673
|
if (!personaId2) return false;
|
|
72465
71674
|
const allowed = getAllowedPersonaIds(grants, action);
|
|
72466
71675
|
if (allowed === "*") return true;
|
|
72467
71676
|
return allowed.has(personaId2);
|
|
72468
71677
|
}
|
|
72469
71678
|
function personaIdFromPath(absPath, personaRoot) {
|
|
72470
|
-
const root =
|
|
72471
|
-
const target =
|
|
72472
|
-
const sep4 = root.endsWith(
|
|
71679
|
+
const root = path83.resolve(personaRoot);
|
|
71680
|
+
const target = path83.resolve(absPath);
|
|
71681
|
+
const sep4 = root.endsWith(path83.sep) ? "" : path83.sep;
|
|
72473
71682
|
if (!target.startsWith(root + sep4)) return null;
|
|
72474
|
-
const rel =
|
|
71683
|
+
const rel = path83.relative(root, target);
|
|
72475
71684
|
if (!rel || rel.startsWith("..")) return null;
|
|
72476
|
-
const id = rel.split(
|
|
71685
|
+
const id = rel.split(path83.sep)[0];
|
|
72477
71686
|
return id || null;
|
|
72478
71687
|
}
|
|
72479
71688
|
function isPathWithin(dir, absPath) {
|
|
72480
|
-
const d2 =
|
|
72481
|
-
const t2 =
|
|
72482
|
-
const sep4 = d2.endsWith(
|
|
71689
|
+
const d2 = path83.resolve(dir);
|
|
71690
|
+
const t2 = path83.resolve(absPath);
|
|
71691
|
+
const sep4 = d2.endsWith(path83.sep) ? "" : path83.sep;
|
|
72483
71692
|
return t2 === d2 || t2.startsWith(d2 + sep4);
|
|
72484
71693
|
}
|
|
72485
71694
|
function isPathInGuestBoundary(personaRoot, personaId2, userWorkDir, absPath) {
|
|
72486
71695
|
if (userWorkDir && isPathWithin(userWorkDir, absPath)) return true;
|
|
72487
|
-
return personaIdFromPath(
|
|
71696
|
+
return personaIdFromPath(path83.resolve(absPath), personaRoot) === personaId2;
|
|
72488
71697
|
}
|
|
72489
71698
|
|
|
72490
71699
|
// src/handlers/history.ts
|
|
@@ -72538,7 +71747,7 @@ function buildHistoryHandlers(deps) {
|
|
|
72538
71747
|
if (!pid) return false;
|
|
72539
71748
|
return isGuestPathAllowed(
|
|
72540
71749
|
ctx.grants,
|
|
72541
|
-
|
|
71750
|
+
path84.join(personaRoot, pid),
|
|
72542
71751
|
personaRoot,
|
|
72543
71752
|
"read",
|
|
72544
71753
|
userWorkDir
|
|
@@ -72550,7 +71759,7 @@ function buildHistoryHandlers(deps) {
|
|
|
72550
71759
|
};
|
|
72551
71760
|
const list = async (frame, _client, ctx) => {
|
|
72552
71761
|
const args = HistoryListArgs.parse(frame);
|
|
72553
|
-
assertGuestPath(ctx,
|
|
71762
|
+
assertGuestPath(ctx, path84.resolve(args.projectPath), personaRoot, "history:list", usersRoot);
|
|
72554
71763
|
const sessions = await history.listSessions(args);
|
|
72555
71764
|
return { response: { type: "history:list", sessions } };
|
|
72556
71765
|
};
|
|
@@ -72625,14 +71834,14 @@ function buildHistoryHandlers(deps) {
|
|
|
72625
71834
|
};
|
|
72626
71835
|
const subagents = async (frame, _client, ctx) => {
|
|
72627
71836
|
const args = HistorySubagentsArgs.parse(frame);
|
|
72628
|
-
assertGuestPath(ctx,
|
|
71837
|
+
assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagents", usersRoot);
|
|
72629
71838
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagents");
|
|
72630
71839
|
const subs = await historyReaderForToolSession(args.toolSessionId).listSubagents(args);
|
|
72631
71840
|
return { response: { type: "history:subagents", subagents: subs } };
|
|
72632
71841
|
};
|
|
72633
71842
|
const subagentRead = async (frame, _client, ctx) => {
|
|
72634
71843
|
const args = HistorySubagentReadArgs.parse(frame);
|
|
72635
|
-
assertGuestPath(ctx,
|
|
71844
|
+
assertGuestPath(ctx, path84.resolve(args.cwd), personaRoot, "history:subagent-read", usersRoot);
|
|
72636
71845
|
assertGuestOwnsToolSession(ctx, args.toolSessionId, "history:subagent-read");
|
|
72637
71846
|
const res = await historyReaderForToolSession(args.toolSessionId).readSubagent(args);
|
|
72638
71847
|
return { response: { type: "history:subagent-read", ...res } };
|
|
@@ -72642,7 +71851,7 @@ function buildHistoryHandlers(deps) {
|
|
|
72642
71851
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
72643
71852
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
72644
71853
|
const filtered = dirs.filter(
|
|
72645
|
-
(d2) => isGuestPathAllowed(ctx.grants,
|
|
71854
|
+
(d2) => isGuestPathAllowed(ctx.grants, path84.resolve(d2.cwd), personaRoot, "read", userWorkDir)
|
|
72646
71855
|
);
|
|
72647
71856
|
return { response: { type: "history:recentDirs", dirs: filtered } };
|
|
72648
71857
|
}
|
|
@@ -72659,17 +71868,17 @@ function buildHistoryHandlers(deps) {
|
|
|
72659
71868
|
}
|
|
72660
71869
|
|
|
72661
71870
|
// src/handlers/projects.ts
|
|
72662
|
-
var
|
|
71871
|
+
var fs80 = __toESM(require("fs"), 1);
|
|
72663
71872
|
var os27 = __toESM(require("os"), 1);
|
|
72664
|
-
var
|
|
71873
|
+
var path85 = __toESM(require("path"), 1);
|
|
72665
71874
|
var import_node_child_process19 = require("child_process");
|
|
72666
71875
|
init_protocol();
|
|
72667
|
-
var DEFAULT_PROJECTS_ROOT =
|
|
71876
|
+
var DEFAULT_PROJECTS_ROOT = path85.join(os27.homedir(), "Documents", "ChatGPT");
|
|
72668
71877
|
function allocateDir(root, name) {
|
|
72669
|
-
let candidate =
|
|
71878
|
+
let candidate = path85.join(root, name);
|
|
72670
71879
|
let n2 = 2;
|
|
72671
|
-
while (
|
|
72672
|
-
candidate =
|
|
71880
|
+
while (fs80.existsSync(candidate)) {
|
|
71881
|
+
candidate = path85.join(root, `${name} ${n2}`);
|
|
72673
71882
|
n2 += 1;
|
|
72674
71883
|
}
|
|
72675
71884
|
return candidate;
|
|
@@ -72697,7 +71906,7 @@ function buildProjectHandlers(deps) {
|
|
|
72697
71906
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, "project:reveal \u4EC5\u652F\u6301 macOS");
|
|
72698
71907
|
}
|
|
72699
71908
|
try {
|
|
72700
|
-
if (!
|
|
71909
|
+
if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
72701
71910
|
} catch {
|
|
72702
71911
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
72703
71912
|
}
|
|
@@ -72713,7 +71922,7 @@ function buildProjectHandlers(deps) {
|
|
|
72713
71922
|
let target;
|
|
72714
71923
|
if (args.path) {
|
|
72715
71924
|
try {
|
|
72716
|
-
if (!
|
|
71925
|
+
if (!fs80.statSync(args.path).isDirectory()) throw new Error("not dir");
|
|
72717
71926
|
} catch {
|
|
72718
71927
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `not a directory: ${args.path}`);
|
|
72719
71928
|
}
|
|
@@ -72721,15 +71930,15 @@ function buildProjectHandlers(deps) {
|
|
|
72721
71930
|
} else {
|
|
72722
71931
|
const name = args.name;
|
|
72723
71932
|
try {
|
|
72724
|
-
|
|
71933
|
+
fs80.mkdirSync(root, { recursive: true });
|
|
72725
71934
|
target = allocateDir(root, name);
|
|
72726
|
-
|
|
71935
|
+
fs80.mkdirSync(target);
|
|
72727
71936
|
} catch (err) {
|
|
72728
71937
|
throw new ClawdError(ERROR_CODES.INVALID_CWD, `\u521B\u5EFA\u9879\u76EE\u76EE\u5F55\u5931\u8D25: ${String(err)}`);
|
|
72729
71938
|
}
|
|
72730
71939
|
const git2 = (0, import_node_child_process19.spawnSync)("git", ["init"], { cwd: target, stdio: "ignore" });
|
|
72731
71940
|
if (git2.status !== 0) {
|
|
72732
|
-
|
|
71941
|
+
fs80.rmSync(target, { recursive: true, force: true });
|
|
72733
71942
|
throw new ClawdError(
|
|
72734
71943
|
ERROR_CODES.INVALID_CWD,
|
|
72735
71944
|
`git init \u5931\u8D25\uFF08${git2.error ? String(git2.error) : `exit ${git2.status}`}\uFF09: ${target}`
|
|
@@ -72754,7 +71963,7 @@ function buildProjectHandlers(deps) {
|
|
|
72754
71963
|
}
|
|
72755
71964
|
|
|
72756
71965
|
// src/handlers/workspace.ts
|
|
72757
|
-
var
|
|
71966
|
+
var path86 = __toESM(require("path"), 1);
|
|
72758
71967
|
init_protocol();
|
|
72759
71968
|
var os28 = __toESM(require("os"), 1);
|
|
72760
71969
|
init_protocol();
|
|
@@ -72797,22 +72006,22 @@ function buildWorkspaceHandlers(deps) {
|
|
|
72797
72006
|
const args = WorkspaceListArgs.parse(frame);
|
|
72798
72007
|
const isGuest = ctx?.principal.kind === "guest";
|
|
72799
72008
|
const fallbackCwd = isGuest && personaRoot ? personaRoot : os28.homedir();
|
|
72800
|
-
const resolvedCwd =
|
|
72801
|
-
const target = args.path ?
|
|
72009
|
+
const resolvedCwd = path86.resolve(args.cwd ?? fallbackCwd);
|
|
72010
|
+
const target = args.path ? path86.resolve(resolvedCwd, args.path) : resolvedCwd;
|
|
72802
72011
|
assertGuestPath2(ctx, target, personaRoot, "workspace:list", usersRoot);
|
|
72803
72012
|
const res = workspace.list({ ...args, cwd: resolvedCwd });
|
|
72804
72013
|
return { response: { type: "workspace:list", ...res } };
|
|
72805
72014
|
};
|
|
72806
72015
|
const read = async (frame, _client, ctx) => {
|
|
72807
72016
|
const args = WorkspaceReadArgs.parse(frame);
|
|
72808
|
-
const target =
|
|
72017
|
+
const target = path86.isAbsolute(args.path) ? path86.resolve(args.path) : path86.resolve(args.cwd, args.path);
|
|
72809
72018
|
assertGuestPath2(ctx, target, personaRoot, "workspace:read", usersRoot);
|
|
72810
72019
|
const res = workspace.read(args);
|
|
72811
72020
|
return { response: { type: "workspace:read", ...res } };
|
|
72812
72021
|
};
|
|
72813
72022
|
const skillsList = async (frame, _client, ctx) => {
|
|
72814
72023
|
const args = SkillsListArgs.parse(frame);
|
|
72815
|
-
const cwdAbs =
|
|
72024
|
+
const cwdAbs = path86.resolve(args.cwd);
|
|
72816
72025
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "skills:list", usersRoot);
|
|
72817
72026
|
const list2 = await getSkillsForTool(args.tool ?? "claude", cwdAbs);
|
|
72818
72027
|
if (ctx?.principal.kind === "guest" && personaRoot) {
|
|
@@ -72824,7 +72033,7 @@ function buildWorkspaceHandlers(deps) {
|
|
|
72824
72033
|
};
|
|
72825
72034
|
const agentsList = async (frame, _client, ctx) => {
|
|
72826
72035
|
const args = AgentsListArgs.parse(frame);
|
|
72827
|
-
const cwdAbs =
|
|
72036
|
+
const cwdAbs = path86.resolve(args.cwd);
|
|
72828
72037
|
assertGuestPath2(ctx, cwdAbs, personaRoot, "agents:list", usersRoot);
|
|
72829
72038
|
if (isCodexFamily(args.tool) || isPiFamily(args.tool)) {
|
|
72830
72039
|
return { response: { type: "agents:list", agents: [] } };
|
|
@@ -72846,20 +72055,20 @@ function buildWorkspaceHandlers(deps) {
|
|
|
72846
72055
|
}
|
|
72847
72056
|
|
|
72848
72057
|
// src/handlers/git.ts
|
|
72849
|
-
var
|
|
72058
|
+
var path88 = __toESM(require("path"), 1);
|
|
72850
72059
|
init_protocol();
|
|
72851
72060
|
init_protocol();
|
|
72852
72061
|
|
|
72853
72062
|
// src/workspace/git.ts
|
|
72854
72063
|
var import_node_child_process20 = require("child_process");
|
|
72855
|
-
var
|
|
72856
|
-
var
|
|
72064
|
+
var import_node_fs63 = __toESM(require("fs"), 1);
|
|
72065
|
+
var import_node_path70 = __toESM(require("path"), 1);
|
|
72857
72066
|
var import_node_util2 = require("util");
|
|
72858
72067
|
var pexec = (0, import_node_util2.promisify)(import_node_child_process20.execFile);
|
|
72859
72068
|
function normalizePath(p3) {
|
|
72860
|
-
const resolved =
|
|
72069
|
+
const resolved = import_node_path70.default.resolve(p3);
|
|
72861
72070
|
try {
|
|
72862
|
-
return
|
|
72071
|
+
return import_node_fs63.default.realpathSync(resolved);
|
|
72863
72072
|
} catch {
|
|
72864
72073
|
return resolved;
|
|
72865
72074
|
}
|
|
@@ -72933,7 +72142,7 @@ async function listGitBranches(cwd) {
|
|
|
72933
72142
|
function assertGuestCwd(ctx, cwd, personaRoot, method, usersRoot) {
|
|
72934
72143
|
if (!ctx || ctx.principal.kind !== "guest" || !personaRoot) return;
|
|
72935
72144
|
const userWorkDir = usersRoot ? deriveUserWorkDir(ctx.principal.id, usersRoot) : void 0;
|
|
72936
|
-
if (!isGuestPathAllowed(ctx.grants,
|
|
72145
|
+
if (!isGuestPathAllowed(ctx.grants, path88.resolve(cwd), personaRoot, "read", userWorkDir)) {
|
|
72937
72146
|
throw new ClawdError(
|
|
72938
72147
|
ERROR_CODES.UNAUTHORIZED,
|
|
72939
72148
|
`guest ${ctx.principal.id} cannot ${method} cwd ${cwd}`
|
|
@@ -73190,12 +72399,12 @@ async function queryCodexAccount(deps = {}) {
|
|
|
73190
72399
|
}
|
|
73191
72400
|
|
|
73192
72401
|
// src/tools/pi-account.ts
|
|
73193
|
-
var
|
|
73194
|
-
var
|
|
72402
|
+
var import_node_fs64 = __toESM(require("fs"), 1);
|
|
72403
|
+
var import_node_path71 = __toESM(require("path"), 1);
|
|
73195
72404
|
function readPiCredentials(agentDir) {
|
|
73196
72405
|
let raw;
|
|
73197
72406
|
try {
|
|
73198
|
-
raw = JSON.parse(
|
|
72407
|
+
raw = JSON.parse(import_node_fs64.default.readFileSync(import_node_path71.default.join(agentDir, "auth.json"), "utf8"));
|
|
73199
72408
|
} catch {
|
|
73200
72409
|
return {};
|
|
73201
72410
|
}
|
|
@@ -74286,21 +73495,21 @@ function computeMethodAccess(args) {
|
|
|
74286
73495
|
}
|
|
74287
73496
|
|
|
74288
73497
|
// src/version.ts
|
|
74289
|
-
var version = "0.2.
|
|
73498
|
+
var version = "0.2.616".length > 0 ? "0.2.616" : "dev";
|
|
74290
73499
|
|
|
74291
73500
|
// src/cli-probe/probe.ts
|
|
74292
|
-
var
|
|
74293
|
-
var
|
|
73501
|
+
var fs83 = __toESM(require("fs"), 1);
|
|
73502
|
+
var path90 = __toESM(require("path"), 1);
|
|
74294
73503
|
var PKG_NAME = "@clawos-dev/clawd";
|
|
74295
73504
|
var BIN_NAME = "clawd";
|
|
74296
73505
|
var MAX_PARENT_HOPS = 5;
|
|
74297
73506
|
function probeGlobalCli(pathEnv) {
|
|
74298
73507
|
if (!pathEnv) return null;
|
|
74299
|
-
for (const dir of pathEnv.split(
|
|
73508
|
+
for (const dir of pathEnv.split(path90.delimiter)) {
|
|
74300
73509
|
if (!dir) continue;
|
|
74301
73510
|
let real;
|
|
74302
73511
|
try {
|
|
74303
|
-
real =
|
|
73512
|
+
real = fs83.realpathSync(path90.join(dir, BIN_NAME));
|
|
74304
73513
|
} catch {
|
|
74305
73514
|
continue;
|
|
74306
73515
|
}
|
|
@@ -74310,15 +73519,15 @@ function probeGlobalCli(pathEnv) {
|
|
|
74310
73519
|
return null;
|
|
74311
73520
|
}
|
|
74312
73521
|
function readOwnPackageVersion(entryPath) {
|
|
74313
|
-
let dir =
|
|
73522
|
+
let dir = path90.dirname(entryPath);
|
|
74314
73523
|
for (let i2 = 0; i2 < MAX_PARENT_HOPS; i2++) {
|
|
74315
73524
|
try {
|
|
74316
|
-
const raw =
|
|
73525
|
+
const raw = fs83.readFileSync(path90.join(dir, "package.json"), "utf8");
|
|
74317
73526
|
const pkg = JSON.parse(raw);
|
|
74318
73527
|
if (pkg.name !== PKG_NAME) return null;
|
|
74319
73528
|
return typeof pkg.version === "string" && pkg.version ? pkg.version : null;
|
|
74320
73529
|
} catch {
|
|
74321
|
-
const parent =
|
|
73530
|
+
const parent = path90.dirname(dir);
|
|
74322
73531
|
if (parent === dir) return null;
|
|
74323
73532
|
dir = parent;
|
|
74324
73533
|
}
|
|
@@ -74494,7 +73703,7 @@ function buildPersonaHandlers(deps) {
|
|
|
74494
73703
|
}
|
|
74495
73704
|
|
|
74496
73705
|
// src/handlers/attachment.ts
|
|
74497
|
-
var
|
|
73706
|
+
var import_node_path72 = __toESM(require("path"), 1);
|
|
74498
73707
|
init_protocol();
|
|
74499
73708
|
init_protocol();
|
|
74500
73709
|
function assertGuestAttachmentPath(ctx, absPath, personaRoot, method, usersRoot) {
|
|
@@ -74573,12 +73782,12 @@ function buildAttachmentHandlers(deps) {
|
|
|
74573
73782
|
`session ${args.sessionId} scope unresolved`
|
|
74574
73783
|
);
|
|
74575
73784
|
}
|
|
74576
|
-
const cwdAbs =
|
|
74577
|
-
const candidateAbs =
|
|
73785
|
+
const cwdAbs = import_node_path72.default.resolve(sessionFile.cwd);
|
|
73786
|
+
const candidateAbs = import_node_path72.default.isAbsolute(args.relPath) ? import_node_path72.default.resolve(args.relPath) : import_node_path72.default.resolve(cwdAbs, args.relPath);
|
|
74578
73787
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.signUrl", "group-acl");
|
|
74579
73788
|
const entries = deps.groupFileStore.list(scope, args.sessionId);
|
|
74580
73789
|
const entry = entries.find((e) => {
|
|
74581
|
-
const storedAbs =
|
|
73790
|
+
const storedAbs = import_node_path72.default.isAbsolute(e.relPath) ? import_node_path72.default.resolve(e.relPath) : import_node_path72.default.resolve(cwdAbs, e.relPath);
|
|
74582
73791
|
return storedAbs === candidateAbs && !e.stale;
|
|
74583
73792
|
});
|
|
74584
73793
|
if (!entry) {
|
|
@@ -74602,7 +73811,7 @@ function buildAttachmentHandlers(deps) {
|
|
|
74602
73811
|
if (!ctx || ctx.principal.kind !== "guest" || !deps.personaRoot || !deps.sessionStore) return;
|
|
74603
73812
|
const f2 = deps.sessionStore.read(sessionId);
|
|
74604
73813
|
if (!f2) return;
|
|
74605
|
-
assertGuestAttachmentPath(ctx,
|
|
73814
|
+
assertGuestAttachmentPath(ctx, import_node_path72.default.resolve(f2.cwd), deps.personaRoot, method, deps.usersRoot);
|
|
74606
73815
|
}
|
|
74607
73816
|
const groupAdd = async (frame, _client, ctx) => {
|
|
74608
73817
|
if (!deps.groupFileStore || !deps.getSessionScope) {
|
|
@@ -74617,8 +73826,8 @@ function buildAttachmentHandlers(deps) {
|
|
|
74617
73826
|
if (!scope) {
|
|
74618
73827
|
throw new ClawdError(ERROR_CODES.VALIDATION_ERROR, `session ${args.sessionId} not found`);
|
|
74619
73828
|
}
|
|
74620
|
-
const cwdAbs =
|
|
74621
|
-
const candidateAbs =
|
|
73829
|
+
const cwdAbs = import_node_path72.default.resolve(deps.sessionStore?.read(args.sessionId)?.cwd ?? ".");
|
|
73830
|
+
const candidateAbs = import_node_path72.default.isAbsolute(args.relPath) ? import_node_path72.default.resolve(args.relPath) : import_node_path72.default.resolve(cwdAbs, args.relPath);
|
|
74622
73831
|
guardAttachmentPath(ctx, args.sessionId, candidateAbs, "attachment.groupAdd", "cwd-subtree");
|
|
74623
73832
|
const from = args.origin === "agent" ? "agent" : ctx?.principal.kind === "owner" ? "owner" : "agent";
|
|
74624
73833
|
const size = 0;
|
|
@@ -74677,19 +73886,19 @@ function buildAttachmentHandlers(deps) {
|
|
|
74677
73886
|
|
|
74678
73887
|
// src/handlers/extension.ts
|
|
74679
73888
|
var import_promises15 = __toESM(require("fs/promises"), 1);
|
|
74680
|
-
var
|
|
73889
|
+
var import_node_path77 = __toESM(require("path"), 1);
|
|
74681
73890
|
init_protocol();
|
|
74682
73891
|
|
|
74683
73892
|
// src/extension/bundle-zip.ts
|
|
74684
73893
|
var import_promises12 = __toESM(require("fs/promises"), 1);
|
|
74685
|
-
var
|
|
74686
|
-
var
|
|
73894
|
+
var import_node_path73 = __toESM(require("path"), 1);
|
|
73895
|
+
var import_node_crypto23 = __toESM(require("crypto"), 1);
|
|
74687
73896
|
var import_jszip2 = __toESM(require_lib3(), 1);
|
|
74688
73897
|
async function bundleExtensionDir(dir) {
|
|
74689
73898
|
const entries = await listFilesSorted(dir);
|
|
74690
73899
|
const zip = new import_jszip2.default();
|
|
74691
73900
|
for (const rel of entries) {
|
|
74692
|
-
const abs =
|
|
73901
|
+
const abs = import_node_path73.default.join(dir, rel);
|
|
74693
73902
|
const content = await import_promises12.default.readFile(abs);
|
|
74694
73903
|
zip.file(rel, content, { date: FIXED_DATE });
|
|
74695
73904
|
}
|
|
@@ -74698,7 +73907,7 @@ async function bundleExtensionDir(dir) {
|
|
|
74698
73907
|
compression: "DEFLATE",
|
|
74699
73908
|
compressionOptions: { level: 6 }
|
|
74700
73909
|
});
|
|
74701
|
-
const sha256 =
|
|
73910
|
+
const sha256 = import_node_crypto23.default.createHash("sha256").update(buffer).digest("hex");
|
|
74702
73911
|
return { buffer, sha256 };
|
|
74703
73912
|
}
|
|
74704
73913
|
var FIXED_DATE = /* @__PURE__ */ new Date("2020-01-01T00:00:00.000Z");
|
|
@@ -74710,7 +73919,7 @@ async function listFilesSorted(rootDir) {
|
|
|
74710
73919
|
return out;
|
|
74711
73920
|
}
|
|
74712
73921
|
async function walk(absRoot, relPrefix, out) {
|
|
74713
|
-
const dirAbs =
|
|
73922
|
+
const dirAbs = import_node_path73.default.join(absRoot, relPrefix);
|
|
74714
73923
|
const entries = await import_promises12.default.readdir(dirAbs, { withFileTypes: true });
|
|
74715
73924
|
for (const e of entries) {
|
|
74716
73925
|
if (IGNORE_BASENAMES.has(e.name)) continue;
|
|
@@ -74764,25 +73973,25 @@ function computePublishCheck(args) {
|
|
|
74764
73973
|
|
|
74765
73974
|
// src/extension/install-flow.ts
|
|
74766
73975
|
var import_promises13 = __toESM(require("fs/promises"), 1);
|
|
74767
|
-
var
|
|
73976
|
+
var import_node_path75 = __toESM(require("path"), 1);
|
|
74768
73977
|
var import_node_os28 = __toESM(require("os"), 1);
|
|
74769
|
-
var
|
|
73978
|
+
var import_node_crypto24 = __toESM(require("crypto"), 1);
|
|
74770
73979
|
var import_jszip3 = __toESM(require_lib3(), 1);
|
|
74771
73980
|
|
|
74772
73981
|
// src/extension/paths.ts
|
|
74773
73982
|
var import_node_os27 = __toESM(require("os"), 1);
|
|
74774
|
-
var
|
|
73983
|
+
var import_node_path74 = __toESM(require("path"), 1);
|
|
74775
73984
|
function clawdHomeRoot(override) {
|
|
74776
|
-
return override ?? process.env.CLAWD_HOME ??
|
|
73985
|
+
return override ?? process.env.CLAWD_HOME ?? import_node_path74.default.join(import_node_os27.default.homedir(), ".clawd");
|
|
74777
73986
|
}
|
|
74778
73987
|
function extensionsRoot(override) {
|
|
74779
|
-
return
|
|
73988
|
+
return import_node_path74.default.join(clawdHomeRoot(override), "extensions");
|
|
74780
73989
|
}
|
|
74781
73990
|
function publishedChannelsFile(override) {
|
|
74782
|
-
return
|
|
73991
|
+
return import_node_path74.default.join(clawdHomeRoot(override), "extensions-published.json");
|
|
74783
73992
|
}
|
|
74784
73993
|
function bundleCacheRoot(override) {
|
|
74785
|
-
return
|
|
73994
|
+
return import_node_path74.default.join(clawdHomeRoot(override), "extension-bundles");
|
|
74786
73995
|
}
|
|
74787
73996
|
|
|
74788
73997
|
// src/extension/install-flow.ts
|
|
@@ -74795,7 +74004,7 @@ var InstallError = class extends Error {
|
|
|
74795
74004
|
};
|
|
74796
74005
|
async function installFromChannel(args, deps) {
|
|
74797
74006
|
const { channelRef, snapshotHash, bundleZip } = args;
|
|
74798
|
-
const computed =
|
|
74007
|
+
const computed = import_node_crypto24.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
74799
74008
|
if (computed !== snapshotHash) {
|
|
74800
74009
|
throw new InstallError(
|
|
74801
74010
|
"HASH_MISMATCH",
|
|
@@ -74809,7 +74018,7 @@ async function installFromChannel(args, deps) {
|
|
|
74809
74018
|
throw new InstallError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
74810
74019
|
}
|
|
74811
74020
|
for (const name of Object.keys(zip.files)) {
|
|
74812
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
74021
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path75.default.isAbsolute(name)) {
|
|
74813
74022
|
throw new InstallError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
74814
74023
|
}
|
|
74815
74024
|
}
|
|
@@ -74841,7 +74050,7 @@ async function installFromChannel(args, deps) {
|
|
|
74841
74050
|
);
|
|
74842
74051
|
}
|
|
74843
74052
|
const localExtId = namespacedExtId(ownerSlug, channelRef.ownerPrincipalId);
|
|
74844
|
-
const destDir =
|
|
74053
|
+
const destDir = import_node_path75.default.join(deps.extensionsRoot, localExtId);
|
|
74845
74054
|
let destExists = false;
|
|
74846
74055
|
try {
|
|
74847
74056
|
await import_promises13.default.access(destDir);
|
|
@@ -74855,16 +74064,16 @@ async function installFromChannel(args, deps) {
|
|
|
74855
74064
|
);
|
|
74856
74065
|
}
|
|
74857
74066
|
const stage = await import_promises13.default.mkdtemp(
|
|
74858
|
-
|
|
74067
|
+
import_node_path75.default.join(import_node_os28.default.tmpdir(), `clawd-ext-install-${localExtId}-`)
|
|
74859
74068
|
);
|
|
74860
74069
|
try {
|
|
74861
74070
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
74862
|
-
const dest =
|
|
74071
|
+
const dest = import_node_path75.default.join(stage, name);
|
|
74863
74072
|
if (entry.dir) {
|
|
74864
74073
|
await import_promises13.default.mkdir(dest, { recursive: true });
|
|
74865
74074
|
continue;
|
|
74866
74075
|
}
|
|
74867
|
-
await import_promises13.default.mkdir(
|
|
74076
|
+
await import_promises13.default.mkdir(import_node_path75.default.dirname(dest), { recursive: true });
|
|
74868
74077
|
if (name === "manifest.json") {
|
|
74869
74078
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
74870
74079
|
await import_promises13.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -74885,9 +74094,9 @@ async function installFromChannel(args, deps) {
|
|
|
74885
74094
|
|
|
74886
74095
|
// src/extension/update-flow.ts
|
|
74887
74096
|
var import_promises14 = __toESM(require("fs/promises"), 1);
|
|
74888
|
-
var
|
|
74097
|
+
var import_node_path76 = __toESM(require("path"), 1);
|
|
74889
74098
|
var import_node_os29 = __toESM(require("os"), 1);
|
|
74890
|
-
var
|
|
74099
|
+
var import_node_crypto25 = __toESM(require("crypto"), 1);
|
|
74891
74100
|
var import_jszip4 = __toESM(require_lib3(), 1);
|
|
74892
74101
|
var UpdateError = class extends Error {
|
|
74893
74102
|
constructor(code, message) {
|
|
@@ -74902,11 +74111,11 @@ async function updateFromChannel(args, deps) {
|
|
|
74902
74111
|
channelRef.extId,
|
|
74903
74112
|
channelRef.ownerPrincipalId
|
|
74904
74113
|
);
|
|
74905
|
-
const liveDir =
|
|
74114
|
+
const liveDir = import_node_path76.default.join(deps.extensionsRoot, localExtId);
|
|
74906
74115
|
const prevDir = `${liveDir}.prev`;
|
|
74907
74116
|
let existingVersion;
|
|
74908
74117
|
try {
|
|
74909
|
-
const raw = await import_promises14.default.readFile(
|
|
74118
|
+
const raw = await import_promises14.default.readFile(import_node_path76.default.join(liveDir, "manifest.json"), "utf8");
|
|
74910
74119
|
const parsed2 = ExtensionManifestSchema.safeParse(JSON.parse(raw));
|
|
74911
74120
|
if (!parsed2.success) {
|
|
74912
74121
|
throw new UpdateError(
|
|
@@ -74925,7 +74134,7 @@ async function updateFromChannel(args, deps) {
|
|
|
74925
74134
|
if (e instanceof UpdateError) throw e;
|
|
74926
74135
|
throw e;
|
|
74927
74136
|
}
|
|
74928
|
-
const computed =
|
|
74137
|
+
const computed = import_node_crypto25.default.createHash("sha256").update(bundleZip).digest("hex");
|
|
74929
74138
|
if (computed !== snapshotHash) {
|
|
74930
74139
|
throw new UpdateError(
|
|
74931
74140
|
"HASH_MISMATCH",
|
|
@@ -74939,7 +74148,7 @@ async function updateFromChannel(args, deps) {
|
|
|
74939
74148
|
throw new UpdateError("ZIP_INVALID", `failed to load zip: ${e.message}`);
|
|
74940
74149
|
}
|
|
74941
74150
|
for (const name of Object.keys(zip.files)) {
|
|
74942
|
-
if (name.includes("..") || name.startsWith("/") ||
|
|
74151
|
+
if (name.includes("..") || name.startsWith("/") || import_node_path76.default.isAbsolute(name)) {
|
|
74943
74152
|
throw new UpdateError("ZIP_INVALID", `unsafe zip entry: ${name}`);
|
|
74944
74153
|
}
|
|
74945
74154
|
}
|
|
@@ -74974,16 +74183,16 @@ async function updateFromChannel(args, deps) {
|
|
|
74974
74183
|
await import_promises14.default.rm(prevDir, { recursive: true, force: true });
|
|
74975
74184
|
await import_promises14.default.rename(liveDir, prevDir);
|
|
74976
74185
|
const stage = await import_promises14.default.mkdtemp(
|
|
74977
|
-
|
|
74186
|
+
import_node_path76.default.join(import_node_os29.default.tmpdir(), `clawd-ext-update-${localExtId}-`)
|
|
74978
74187
|
);
|
|
74979
74188
|
try {
|
|
74980
74189
|
for (const [name, entry] of Object.entries(zip.files)) {
|
|
74981
|
-
const dest =
|
|
74190
|
+
const dest = import_node_path76.default.join(stage, name);
|
|
74982
74191
|
if (entry.dir) {
|
|
74983
74192
|
await import_promises14.default.mkdir(dest, { recursive: true });
|
|
74984
74193
|
continue;
|
|
74985
74194
|
}
|
|
74986
|
-
await import_promises14.default.mkdir(
|
|
74195
|
+
await import_promises14.default.mkdir(import_node_path76.default.dirname(dest), { recursive: true });
|
|
74987
74196
|
if (name === "manifest.json") {
|
|
74988
74197
|
const rewritten = { ...parsed.data, id: localExtId };
|
|
74989
74198
|
await import_promises14.default.writeFile(dest, JSON.stringify(rewritten, null, 2));
|
|
@@ -75050,7 +74259,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
75050
74259
|
);
|
|
75051
74260
|
}
|
|
75052
74261
|
}
|
|
75053
|
-
const manifestPath =
|
|
74262
|
+
const manifestPath = import_node_path77.default.join(root, extId, "manifest.json");
|
|
75054
74263
|
const manifest = await readManifest(root, extId);
|
|
75055
74264
|
const next = { ...manifest, version: newVersion };
|
|
75056
74265
|
const tmp = `${manifestPath}.tmp`;
|
|
@@ -75058,7 +74267,7 @@ async function rewriteManifestVersion(root, extId, newVersion, previousPublished
|
|
|
75058
74267
|
await import_promises15.default.rename(tmp, manifestPath);
|
|
75059
74268
|
}
|
|
75060
74269
|
async function readManifest(root, extId) {
|
|
75061
|
-
const file =
|
|
74270
|
+
const file = import_node_path77.default.join(root, extId, "manifest.json");
|
|
75062
74271
|
let raw;
|
|
75063
74272
|
try {
|
|
75064
74273
|
raw = await import_promises15.default.readFile(file, "utf8");
|
|
@@ -75142,7 +74351,7 @@ function buildExtensionHandlers(deps) {
|
|
|
75142
74351
|
};
|
|
75143
74352
|
async function buildSnapshotMeta(extId) {
|
|
75144
74353
|
const manifest = await readManifest(deps.root, extId);
|
|
75145
|
-
const { sha256, buffer } = await bundleExtensionDir(
|
|
74354
|
+
const { sha256, buffer } = await bundleExtensionDir(import_node_path77.default.join(deps.root, extId));
|
|
75146
74355
|
return { manifest, contentHash: sha256, buffer };
|
|
75147
74356
|
}
|
|
75148
74357
|
const publish = async (frame, _client, ctx) => {
|
|
@@ -75970,7 +75179,7 @@ function buildVisitorHandlers(deps) {
|
|
|
75970
75179
|
|
|
75971
75180
|
// src/extension/registry.ts
|
|
75972
75181
|
var import_promises17 = __toESM(require("fs/promises"), 1);
|
|
75973
|
-
var
|
|
75182
|
+
var import_node_path78 = __toESM(require("path"), 1);
|
|
75974
75183
|
async function loadAll(root) {
|
|
75975
75184
|
let entries;
|
|
75976
75185
|
try {
|
|
@@ -75983,13 +75192,13 @@ async function loadAll(root) {
|
|
|
75983
75192
|
for (const ent of entries) {
|
|
75984
75193
|
if (!ent.isDirectory()) continue;
|
|
75985
75194
|
if (ent.name.startsWith(".")) continue;
|
|
75986
|
-
records.push(await loadOne(
|
|
75195
|
+
records.push(await loadOne(import_node_path78.default.join(root, ent.name), ent.name));
|
|
75987
75196
|
}
|
|
75988
75197
|
records.sort((a2, b3) => a2.extId < b3.extId ? -1 : a2.extId > b3.extId ? 1 : 0);
|
|
75989
75198
|
return records;
|
|
75990
75199
|
}
|
|
75991
75200
|
async function loadOne(dir, dirName) {
|
|
75992
|
-
const manifestPath =
|
|
75201
|
+
const manifestPath = import_node_path78.default.join(dir, "manifest.json");
|
|
75993
75202
|
let raw;
|
|
75994
75203
|
try {
|
|
75995
75204
|
raw = await import_promises17.default.readFile(manifestPath, "utf8");
|
|
@@ -76034,7 +75243,7 @@ async function loadOne(dir, dirName) {
|
|
|
76034
75243
|
|
|
76035
75244
|
// src/extension/uninstall.ts
|
|
76036
75245
|
var import_promises18 = __toESM(require("fs/promises"), 1);
|
|
76037
|
-
var
|
|
75246
|
+
var import_node_path79 = __toESM(require("path"), 1);
|
|
76038
75247
|
var UninstallError = class extends Error {
|
|
76039
75248
|
constructor(code, message) {
|
|
76040
75249
|
super(message);
|
|
@@ -76043,7 +75252,7 @@ var UninstallError = class extends Error {
|
|
|
76043
75252
|
code;
|
|
76044
75253
|
};
|
|
76045
75254
|
async function uninstall(deps) {
|
|
76046
|
-
const dir =
|
|
75255
|
+
const dir = import_node_path79.default.join(deps.root, deps.extId);
|
|
76047
75256
|
try {
|
|
76048
75257
|
await import_promises18.default.access(dir);
|
|
76049
75258
|
} catch {
|
|
@@ -76054,7 +75263,7 @@ async function uninstall(deps) {
|
|
|
76054
75263
|
}
|
|
76055
75264
|
|
|
76056
75265
|
// src/handlers/index.ts
|
|
76057
|
-
var
|
|
75266
|
+
var import_node_crypto26 = require("crypto");
|
|
76058
75267
|
|
|
76059
75268
|
// src/handlers/peer-exec.ts
|
|
76060
75269
|
init_protocol();
|
|
@@ -76211,7 +75420,7 @@ function buildMethodHandlers(deps) {
|
|
|
76211
75420
|
const c2 = deps.contactStore.get(deviceId);
|
|
76212
75421
|
return c2 ? { deviceId: c2.deviceId, remoteUrl: c2.remoteUrl, connectToken: c2.connectToken } : null;
|
|
76213
75422
|
},
|
|
76214
|
-
genId: () => (0,
|
|
75423
|
+
genId: () => (0, import_node_crypto26.randomUUID)(),
|
|
76215
75424
|
now: () => Date.now(),
|
|
76216
75425
|
forwardInboxPostToPeer,
|
|
76217
75426
|
logger: deps.logger
|
|
@@ -76261,7 +75470,7 @@ function buildMethodHandlers(deps) {
|
|
|
76261
75470
|
broadcast: deps.broadcastToOwners
|
|
76262
75471
|
}),
|
|
76263
75472
|
...buildMasterHandlers({
|
|
76264
|
-
authorityTablePath:
|
|
75473
|
+
authorityTablePath: import_node_path80.default.join(deps.masterDataDir, "master-authority.json")
|
|
76265
75474
|
}),
|
|
76266
75475
|
...buildTopicHandlers({
|
|
76267
75476
|
topicStore: deps.topicStore,
|
|
@@ -76404,7 +75613,7 @@ async function dispatchRpc(method, frame, client, ctx, deps) {
|
|
|
76404
75613
|
|
|
76405
75614
|
// src/extension/runtime.ts
|
|
76406
75615
|
var import_node_child_process25 = require("child_process");
|
|
76407
|
-
var
|
|
75616
|
+
var import_node_path81 = __toESM(require("path"), 1);
|
|
76408
75617
|
var import_promises19 = require("timers/promises");
|
|
76409
75618
|
|
|
76410
75619
|
// src/extension/port-allocator.ts
|
|
@@ -76505,7 +75714,7 @@ var Runtime = class {
|
|
|
76505
75714
|
/\$CLAWOS_EXT_PORT/g,
|
|
76506
75715
|
String(port)
|
|
76507
75716
|
);
|
|
76508
|
-
const dir =
|
|
75717
|
+
const dir = import_node_path81.default.join(this.root, extId);
|
|
76509
75718
|
const env = {
|
|
76510
75719
|
...process.env,
|
|
76511
75720
|
CLAWOS_EXT_PORT: String(port),
|
|
@@ -76617,7 +75826,7 @@ ${handle.stderrTail}`
|
|
|
76617
75826
|
|
|
76618
75827
|
// src/extension/published-channels.ts
|
|
76619
75828
|
var import_promises20 = __toESM(require("fs/promises"), 1);
|
|
76620
|
-
var
|
|
75829
|
+
var import_node_path82 = __toESM(require("path"), 1);
|
|
76621
75830
|
init_zod();
|
|
76622
75831
|
var PublishedChannelsError = class extends Error {
|
|
76623
75832
|
constructor(code, message) {
|
|
@@ -76716,7 +75925,7 @@ var PublishedChannelStore = class {
|
|
|
76716
75925
|
)
|
|
76717
75926
|
};
|
|
76718
75927
|
const tmp = `${this.filePath}.tmp`;
|
|
76719
|
-
await import_promises20.default.mkdir(
|
|
75928
|
+
await import_promises20.default.mkdir(import_node_path82.default.dirname(this.filePath), { recursive: true });
|
|
76720
75929
|
await import_promises20.default.writeFile(tmp, JSON.stringify(data, null, 2), { mode: 384 });
|
|
76721
75930
|
await import_promises20.default.rename(tmp, this.filePath);
|
|
76722
75931
|
}
|
|
@@ -76724,7 +75933,7 @@ var PublishedChannelStore = class {
|
|
|
76724
75933
|
|
|
76725
75934
|
// src/extension/bundle-cache.ts
|
|
76726
75935
|
var import_promises21 = __toESM(require("fs/promises"), 1);
|
|
76727
|
-
var
|
|
75936
|
+
var import_node_path83 = __toESM(require("path"), 1);
|
|
76728
75937
|
var BundleCache = class {
|
|
76729
75938
|
constructor(rootDir) {
|
|
76730
75939
|
this.rootDir = rootDir;
|
|
@@ -76733,14 +75942,14 @@ var BundleCache = class {
|
|
|
76733
75942
|
/** Atomic write: stage tmp → rename. Caller passes the hex sha256. */
|
|
76734
75943
|
async write(snapshotHash, buffer) {
|
|
76735
75944
|
await import_promises21.default.mkdir(this.rootDir, { recursive: true });
|
|
76736
|
-
const file =
|
|
75945
|
+
const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
76737
75946
|
const tmp = `${file}.tmp`;
|
|
76738
75947
|
await import_promises21.default.writeFile(tmp, buffer, { mode: 384 });
|
|
76739
75948
|
await import_promises21.default.rename(tmp, file);
|
|
76740
75949
|
}
|
|
76741
75950
|
/** Returns the bundle bytes, or null when the file doesn't exist. */
|
|
76742
75951
|
async read(snapshotHash) {
|
|
76743
|
-
const file =
|
|
75952
|
+
const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
76744
75953
|
try {
|
|
76745
75954
|
return await import_promises21.default.readFile(file);
|
|
76746
75955
|
} catch (e) {
|
|
@@ -76750,7 +75959,7 @@ var BundleCache = class {
|
|
|
76750
75959
|
}
|
|
76751
75960
|
/** Idempotent — missing file is not an error. */
|
|
76752
75961
|
async delete(snapshotHash) {
|
|
76753
|
-
const file =
|
|
75962
|
+
const file = import_node_path83.default.join(this.rootDir, `${snapshotHash}.zip`);
|
|
76754
75963
|
await import_promises21.default.rm(file, { force: true });
|
|
76755
75964
|
}
|
|
76756
75965
|
};
|
|
@@ -76773,24 +75982,24 @@ async function startDaemon(config) {
|
|
|
76773
75982
|
sampling: logShippingCfg.sampling,
|
|
76774
75983
|
homeDir: import_node_os31.default.homedir()
|
|
76775
75984
|
});
|
|
76776
|
-
const logDir =
|
|
76777
|
-
|
|
75985
|
+
const logDir = import_node_path84.default.join(config.dataDir, "log");
|
|
75986
|
+
import_node_fs65.default.mkdirSync(logDir, { recursive: true });
|
|
76778
75987
|
const logger = createLogger({
|
|
76779
75988
|
level: config.logLevel,
|
|
76780
|
-
file:
|
|
75989
|
+
file: import_node_path84.default.join(logDir, "clawd.log"),
|
|
76781
75990
|
logClient
|
|
76782
75991
|
});
|
|
76783
75992
|
logger.info("starting clawd", { version, config: { port: config.port, host: config.host, dataDir: config.dataDir } });
|
|
76784
75993
|
const screenIdleProbeLogger = createFileOnlyLogger({
|
|
76785
|
-
file:
|
|
75994
|
+
file: import_node_path84.default.join(logDir, "screen-idle-probe.log"),
|
|
76786
75995
|
level: "debug"
|
|
76787
75996
|
});
|
|
76788
75997
|
logger.info("screen-idle probe logger enabled", {
|
|
76789
|
-
file:
|
|
75998
|
+
file: import_node_path84.default.join(logDir, "screen-idle-probe.log")
|
|
76790
75999
|
});
|
|
76791
76000
|
const CAP_TARGETS = [
|
|
76792
|
-
|
|
76793
|
-
|
|
76001
|
+
import_node_path84.default.join(logDir, "clawd.log"),
|
|
76002
|
+
import_node_path84.default.join(logDir, "screen-idle-probe.log")
|
|
76794
76003
|
];
|
|
76795
76004
|
const LOG_CAP_MAX_BYTES = 10 * 1024 * 1024;
|
|
76796
76005
|
const LOG_CAP_KEEP_BYTES = 5 * 1024 * 1024;
|
|
@@ -76912,11 +76121,11 @@ async function startDaemon(config) {
|
|
|
76912
76121
|
const agents = new AgentsScanner();
|
|
76913
76122
|
const history = new ClaudeHistoryReader();
|
|
76914
76123
|
let transport = null;
|
|
76915
|
-
const personaStore = new PersonaStore(
|
|
76124
|
+
const personaStore = new PersonaStore(import_node_path84.default.join(config.dataDir, "personas"));
|
|
76916
76125
|
const subscriptionChannelStore = new SubscriptionChannelStore({ dataDir: config.dataDir });
|
|
76917
76126
|
const activeSubscriptionChannel = subscriptionChannelStore.getActive();
|
|
76918
76127
|
if (activeSubscriptionChannel) applyPiSubscriptionChannel({ channel: activeSubscriptionChannel });
|
|
76919
|
-
const usersRoot =
|
|
76128
|
+
const usersRoot = import_node_path84.default.join(config.dataDir, "users");
|
|
76920
76129
|
const defaultsRoot = findDefaultsRoot(logger);
|
|
76921
76130
|
if (defaultsRoot) {
|
|
76922
76131
|
seedDefaultPersonas({ store: personaStore, defaultsRoot, logger });
|
|
@@ -76933,7 +76142,7 @@ async function startDaemon(config) {
|
|
|
76933
76142
|
retirePersonaBuilder({ store: personaStore, logger });
|
|
76934
76143
|
const groupFileStore = new GroupFileStore({ dataDir: config.dataDir, logger });
|
|
76935
76144
|
const dispatchStore = createDispatchStore({
|
|
76936
|
-
filePath:
|
|
76145
|
+
filePath: import_node_path84.default.join(config.dataDir, "dispatch.json"),
|
|
76937
76146
|
now: () => Date.now(),
|
|
76938
76147
|
onFlushError: (err) => logger.error("dispatch store flush failed", {
|
|
76939
76148
|
reason: err instanceof Error ? err.message : String(err)
|
|
@@ -76942,18 +76151,18 @@ async function startDaemon(config) {
|
|
|
76942
76151
|
await dispatchStore.load();
|
|
76943
76152
|
dispatchStore.markInterruptedAsFailed((/* @__PURE__ */ new Date()).toISOString());
|
|
76944
76153
|
const channelStore = createChannelStore({
|
|
76945
|
-
filePath:
|
|
76154
|
+
filePath: import_node_path84.default.join(config.dataDir, "channels.json"),
|
|
76946
76155
|
now: () => Date.now(),
|
|
76947
|
-
genId: () => `ch-${(0,
|
|
76156
|
+
genId: () => `ch-${(0, import_node_crypto27.randomUUID)().slice(0, 8)}`,
|
|
76948
76157
|
onFlushError: (err) => logger.error("channel store flush failed", {
|
|
76949
76158
|
reason: err instanceof Error ? err.message : String(err)
|
|
76950
76159
|
})
|
|
76951
76160
|
});
|
|
76952
76161
|
await channelStore.load();
|
|
76953
76162
|
const topicStore = createTopicStore({
|
|
76954
|
-
filePath:
|
|
76163
|
+
filePath: import_node_path84.default.join(config.dataDir, "topics.json"),
|
|
76955
76164
|
now: () => Date.now(),
|
|
76956
|
-
genId: () => `tp-${(0,
|
|
76165
|
+
genId: () => `tp-${(0, import_node_crypto27.randomUUID)().slice(0, 8)}`,
|
|
76957
76166
|
onFlushError: (err) => logger.error("topic store flush failed", {
|
|
76958
76167
|
reason: err instanceof Error ? err.message : String(err)
|
|
76959
76168
|
})
|
|
@@ -76961,7 +76170,7 @@ async function startDaemon(config) {
|
|
|
76961
76170
|
await topicStore.load();
|
|
76962
76171
|
let deliverPendingRef;
|
|
76963
76172
|
const personaDispatchManager = new PersonaDispatchManager({
|
|
76964
|
-
genId: () => (0,
|
|
76173
|
+
genId: () => (0, import_node_crypto27.randomUUID)(),
|
|
76965
76174
|
store: dispatchStore,
|
|
76966
76175
|
now: () => Date.now(),
|
|
76967
76176
|
onCompleted: (sid) => deliverPendingRef?.(sid),
|
|
@@ -76978,12 +76187,12 @@ async function startDaemon(config) {
|
|
|
76978
76187
|
});
|
|
76979
76188
|
}
|
|
76980
76189
|
});
|
|
76981
|
-
const here = typeof __dirname === "string" ? __dirname :
|
|
76190
|
+
const here = typeof __dirname === "string" ? __dirname : import_node_path84.default.dirname((0, import_node_url6.fileURLToPath)(import_meta10.url));
|
|
76982
76191
|
const mcpConfigs = [];
|
|
76983
76192
|
const secretsBundleRoot = findSecretsBundleRoot(logger);
|
|
76984
|
-
const localSecretsDir =
|
|
76193
|
+
const localSecretsDir = import_node_path84.default.join(config.dataDir, LOCAL_SECRETS_DIRNAME);
|
|
76985
76194
|
const readSecrets = () => readSecretTable({ bundleRoot: secretsBundleRoot, overrideDir: localSecretsDir, logger });
|
|
76986
|
-
const githubTokenFile =
|
|
76195
|
+
const githubTokenFile = import_node_path84.default.join(localSecretsDir, GITHUB_TOKEN_FILE);
|
|
76987
76196
|
const githubIdentity = createGithubIdentity({
|
|
76988
76197
|
resolve: () => resolveGithubAuth({ exec: runCommand, fileToken: () => readEnvFileVar(githubTokenFile, GITHUB_TOKEN_VAR) }),
|
|
76989
76198
|
store: (token) => storeGithubAuth({
|
|
@@ -77021,22 +76230,22 @@ async function startDaemon(config) {
|
|
|
77021
76230
|
void githubIdentity.refresh();
|
|
77022
76231
|
return renderPersonaMcpSecrets({
|
|
77023
76232
|
personaId: personaId2,
|
|
77024
|
-
personaDir:
|
|
76233
|
+
personaDir: import_node_path84.default.join(config.dataDir, "personas", personaId2),
|
|
77025
76234
|
secrets,
|
|
77026
|
-
outDir:
|
|
76235
|
+
outDir: import_node_path84.default.join(config.dataDir, "persona-mcp"),
|
|
77027
76236
|
logger
|
|
77028
76237
|
});
|
|
77029
76238
|
};
|
|
77030
76239
|
const mcpDaemonUrl = `http://127.0.0.1:${config.port}`;
|
|
77031
76240
|
const dispatchServerCandidates = [
|
|
77032
|
-
|
|
76241
|
+
import_node_path84.default.join(here, "dispatch", "mcp-server.cjs"),
|
|
77033
76242
|
// 生产 dist/index → dist/dispatch/mcp-server.cjs
|
|
77034
|
-
|
|
76243
|
+
import_node_path84.default.join(here, "..", "dist", "dispatch", "mcp-server.cjs")
|
|
77035
76244
|
// dev tsx src/index → ../dist/dispatch/mcp-server.cjs
|
|
77036
76245
|
];
|
|
77037
|
-
const dispatchServerScriptPath = dispatchServerCandidates.find((p3) =>
|
|
76246
|
+
const dispatchServerScriptPath = dispatchServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77038
76247
|
if (dispatchServerScriptPath) {
|
|
77039
|
-
const dispatchLogPath =
|
|
76248
|
+
const dispatchLogPath = import_node_path84.default.join(logDir, "dispatch-mcp-server.log");
|
|
77040
76249
|
const dispatchCfgPath = writeDispatchMcpConfig({
|
|
77041
76250
|
dataDir: config.dataDir,
|
|
77042
76251
|
serverScriptPath: dispatchServerScriptPath,
|
|
@@ -77056,12 +76265,12 @@ async function startDaemon(config) {
|
|
|
77056
76265
|
});
|
|
77057
76266
|
}
|
|
77058
76267
|
const ticketServerCandidates = [
|
|
77059
|
-
|
|
77060
|
-
|
|
76268
|
+
import_node_path84.default.join(here, "ticket", "mcp-server.cjs"),
|
|
76269
|
+
import_node_path84.default.join(here, "..", "dist", "ticket", "mcp-server.cjs")
|
|
77061
76270
|
];
|
|
77062
|
-
const ticketServerScriptPath = ticketServerCandidates.find((p3) =>
|
|
76271
|
+
const ticketServerScriptPath = ticketServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77063
76272
|
if (ticketServerScriptPath) {
|
|
77064
|
-
const ticketLogPath =
|
|
76273
|
+
const ticketLogPath = import_node_path84.default.join(logDir, "ticket-mcp-server.log");
|
|
77065
76274
|
const ticketCfgPath = writeTicketMcpConfig({
|
|
77066
76275
|
dataDir: config.dataDir,
|
|
77067
76276
|
serverScriptPath: ticketServerScriptPath,
|
|
@@ -77083,12 +76292,12 @@ async function startDaemon(config) {
|
|
|
77083
76292
|
});
|
|
77084
76293
|
}
|
|
77085
76294
|
const shiftServerCandidates = [
|
|
77086
|
-
|
|
77087
|
-
|
|
76295
|
+
import_node_path84.default.join(here, "shift", "mcp-server.cjs"),
|
|
76296
|
+
import_node_path84.default.join(here, "..", "dist", "shift", "mcp-server.cjs")
|
|
77088
76297
|
];
|
|
77089
|
-
const shiftServerScriptPath = shiftServerCandidates.find((p3) =>
|
|
76298
|
+
const shiftServerScriptPath = shiftServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77090
76299
|
if (shiftServerScriptPath) {
|
|
77091
|
-
const shiftLogPath =
|
|
76300
|
+
const shiftLogPath = import_node_path84.default.join(logDir, "shift-mcp-server.log");
|
|
77092
76301
|
const shiftCfgPath = await writeShiftMcpConfig({
|
|
77093
76302
|
dataDir: config.dataDir,
|
|
77094
76303
|
serverScriptPath: shiftServerScriptPath,
|
|
@@ -77109,12 +76318,12 @@ async function startDaemon(config) {
|
|
|
77109
76318
|
);
|
|
77110
76319
|
}
|
|
77111
76320
|
const inboxServerCandidates = [
|
|
77112
|
-
|
|
77113
|
-
|
|
76321
|
+
import_node_path84.default.join(here, "inbox", "mcp-server.cjs"),
|
|
76322
|
+
import_node_path84.default.join(here, "..", "dist", "inbox", "mcp-server.cjs")
|
|
77114
76323
|
];
|
|
77115
|
-
const inboxServerScriptPath = inboxServerCandidates.find((p3) =>
|
|
76324
|
+
const inboxServerScriptPath = inboxServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77116
76325
|
if (inboxServerScriptPath) {
|
|
77117
|
-
const inboxLogPath =
|
|
76326
|
+
const inboxLogPath = import_node_path84.default.join(logDir, "inbox-mcp-server.log");
|
|
77118
76327
|
const inboxCfgPath = await writeInboxMcpConfig({
|
|
77119
76328
|
dataDir: config.dataDir,
|
|
77120
76329
|
serverScriptPath: inboxServerScriptPath,
|
|
@@ -77135,10 +76344,10 @@ async function startDaemon(config) {
|
|
|
77135
76344
|
);
|
|
77136
76345
|
}
|
|
77137
76346
|
const peerOpsServerCandidates = [
|
|
77138
|
-
|
|
77139
|
-
|
|
76347
|
+
import_node_path84.default.join(here, "peer-ops", "mcp-server.cjs"),
|
|
76348
|
+
import_node_path84.default.join(here, "..", "dist", "peer-ops", "mcp-server.cjs")
|
|
77140
76349
|
];
|
|
77141
|
-
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p3) =>
|
|
76350
|
+
const peerOpsServerScriptPath = peerOpsServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77142
76351
|
if (peerOpsServerScriptPath) {
|
|
77143
76352
|
const peerOpsCfgPath = writePeerOpsMcpConfig({
|
|
77144
76353
|
dataDir: config.dataDir,
|
|
@@ -77158,12 +76367,12 @@ async function startDaemon(config) {
|
|
|
77158
76367
|
);
|
|
77159
76368
|
}
|
|
77160
76369
|
const rpcToolServerCandidates = [
|
|
77161
|
-
|
|
77162
|
-
|
|
76370
|
+
import_node_path84.default.join(here, "rpc-tool", "mcp-server.cjs"),
|
|
76371
|
+
import_node_path84.default.join(here, "..", "dist", "rpc-tool", "mcp-server.cjs")
|
|
77163
76372
|
];
|
|
77164
|
-
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p3) =>
|
|
76373
|
+
const rpcToolServerScriptPath = rpcToolServerCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77165
76374
|
if (rpcToolServerScriptPath) {
|
|
77166
|
-
const rpcToolLogPath =
|
|
76375
|
+
const rpcToolLogPath = import_node_path84.default.join(logDir, "rpc-tool-mcp-server.log");
|
|
77167
76376
|
const rpcToolCfgPath = writeRpcToolMcpConfig({
|
|
77168
76377
|
dataDir: config.dataDir,
|
|
77169
76378
|
serverScriptPath: rpcToolServerScriptPath,
|
|
@@ -77184,7 +76393,7 @@ async function startDaemon(config) {
|
|
|
77184
76393
|
);
|
|
77185
76394
|
}
|
|
77186
76395
|
const shiftStore = createShiftStore({
|
|
77187
|
-
filePath:
|
|
76396
|
+
filePath: import_node_path84.default.join(config.dataDir, "shift.json"),
|
|
77188
76397
|
ownerIdProvider: () => ownerPrincipalId,
|
|
77189
76398
|
now: () => Date.now()
|
|
77190
76399
|
});
|
|
@@ -77206,7 +76415,7 @@ async function startDaemon(config) {
|
|
|
77206
76415
|
getAdapter,
|
|
77207
76416
|
historyReader: history,
|
|
77208
76417
|
dataDir: config.dataDir,
|
|
77209
|
-
personaRoot:
|
|
76418
|
+
personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
|
|
77210
76419
|
// dispatch / shift 自动化 spawn 按 persona 绑定 tool 起 B session(codex persona 用 codex)。
|
|
77211
76420
|
// personaRegistry 声明在 manager 之后(同作用域 const,调用时机在启动完成后,无 TDZ 风险)。
|
|
77212
76421
|
getPersonaDefaults: (personaId2) => personaRegistry.get(personaId2),
|
|
@@ -77267,10 +76476,10 @@ async function startDaemon(config) {
|
|
|
77267
76476
|
// 文件可能 agent 写完又被自己删(罕见),用 size=0 / fallback mime 兜底。
|
|
77268
76477
|
attachmentGroup: {
|
|
77269
76478
|
onFileEdit: (input) => {
|
|
77270
|
-
const absPath =
|
|
76479
|
+
const absPath = import_node_path84.default.isAbsolute(input.relPath) ? input.relPath : import_node_path84.default.join(input.cwd, input.relPath);
|
|
77271
76480
|
let size = 0;
|
|
77272
76481
|
try {
|
|
77273
|
-
size =
|
|
76482
|
+
size = import_node_fs65.default.statSync(absPath).size;
|
|
77274
76483
|
} catch (err) {
|
|
77275
76484
|
logger.warn("attachment.onFileEdit stat failed", {
|
|
77276
76485
|
sessionId: input.sessionId,
|
|
@@ -77311,9 +76520,9 @@ async function startDaemon(config) {
|
|
|
77311
76520
|
logger.info("projects.seed-dropped", { dropped: droppedSeed.dropped, backup: droppedSeed.backup });
|
|
77312
76521
|
}
|
|
77313
76522
|
const projectsStore = new ProjectsStore({
|
|
77314
|
-
file:
|
|
76523
|
+
file: import_node_path84.default.join(config.dataDir, "projects.json"),
|
|
77315
76524
|
clawdDir: config.dataDir,
|
|
77316
|
-
codexStateFile:
|
|
76525
|
+
codexStateFile: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex", ".codex-global-state.json"),
|
|
77317
76526
|
logger
|
|
77318
76527
|
});
|
|
77319
76528
|
const observer = new SessionObserver({
|
|
@@ -77377,11 +76586,6 @@ async function startDaemon(config) {
|
|
|
77377
76586
|
centralApi: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
77378
76587
|
logger
|
|
77379
76588
|
});
|
|
77380
|
-
const cloudCancelOutbox = new CloudCancelOutbox(
|
|
77381
|
-
import_node_path85.default.join(config.dataDir, "cloud-cancel-outbox"),
|
|
77382
|
-
(personaId2, clientSessionId, gatewaySessionId) => cloudGateway.cancelEventSession(personaId2, clientSessionId, gatewaySessionId),
|
|
77383
|
-
logger
|
|
77384
|
-
);
|
|
77385
76589
|
manager.setCloudCanceller(async (file, runner) => {
|
|
77386
76590
|
const personaId2 = personaIdFromCloudCwd(file.cwd);
|
|
77387
76591
|
if (!personaId2) throw new Error(`\u4E91\u4F1A\u8BDD ${file.sessionId} \u7F3A\u5C11 gateway persona ID`);
|
|
@@ -77390,27 +76594,16 @@ async function startDaemon(config) {
|
|
|
77390
76594
|
runner?.confirmCloudCancelled();
|
|
77391
76595
|
return;
|
|
77392
76596
|
}
|
|
77393
|
-
|
|
77394
|
-
if (!file.cloudGatewaySessionId) throw new Error(`\u4E91\u4F1A\u8BDD ${file.sessionId} \u5C1A\u672A\u6536\u5230 gateway ready`);
|
|
77395
|
-
cloudCancelOutbox.record(executionId, personaId2, file.cloudGatewaySessionId);
|
|
77396
|
-
try {
|
|
77397
|
-
await cloudGateway.cancelEventSession(personaId2, executionId, file.cloudGatewaySessionId);
|
|
77398
|
-
cloudCancelOutbox.confirm(executionId);
|
|
77399
|
-
runner?.confirmCloudCancelled();
|
|
77400
|
-
} catch (e) {
|
|
77401
|
-
cloudCancelOutbox.release(executionId);
|
|
77402
|
-
throw e;
|
|
77403
|
-
}
|
|
76597
|
+
runner?.confirmCloudCancelled();
|
|
77404
76598
|
});
|
|
77405
|
-
cloudCancelOutbox.start();
|
|
77406
76599
|
registerAdapter("claude", claudeAdapter);
|
|
77407
|
-
const codexIsolatedHome =
|
|
76600
|
+
const codexIsolatedHome = import_node_path84.default.join(config.dataDir, "codex-home");
|
|
77408
76601
|
try {
|
|
77409
|
-
|
|
76602
|
+
import_node_fs65.default.mkdirSync(codexIsolatedHome, { recursive: true });
|
|
77410
76603
|
for (const f2 of ["auth.json", "config.toml"]) {
|
|
77411
|
-
const link =
|
|
77412
|
-
const target =
|
|
77413
|
-
if (!
|
|
76604
|
+
const link = import_node_path84.default.join(codexIsolatedHome, f2);
|
|
76605
|
+
const target = import_node_path84.default.join(import_node_os31.default.homedir(), ".codex", f2);
|
|
76606
|
+
if (!import_node_fs65.default.existsSync(link) && import_node_fs65.default.existsSync(target)) import_node_fs65.default.symlinkSync(target, link);
|
|
77414
76607
|
}
|
|
77415
76608
|
} catch (err) {
|
|
77416
76609
|
logger.warn("codex isolated home setup failed", { err: String(err) });
|
|
@@ -77421,17 +76614,17 @@ async function startDaemon(config) {
|
|
|
77421
76614
|
logger,
|
|
77422
76615
|
historyReader: new CodexHistoryReader({
|
|
77423
76616
|
roots: codexRolloutRoots(config.dataDir),
|
|
77424
|
-
sharedHome:
|
|
76617
|
+
sharedHome: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex"),
|
|
77425
76618
|
logger
|
|
77426
76619
|
}),
|
|
77427
76620
|
// projectPaths 每次调用现取 —— 用户新建 project 后立即生效,不用重启 daemon
|
|
77428
76621
|
codexHomeFor: (cwd) => resolveCodexHome({
|
|
77429
76622
|
cwd,
|
|
77430
|
-
personaRoot:
|
|
76623
|
+
personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
|
|
77431
76624
|
// 必须用 listMerged(Codex registry ∪ 叠加层):只用本地 list() 的话,用户在
|
|
77432
76625
|
// Codex 里建的 project 不在表里,在它下面开的会话会被误判成隔离 → Codex 侧看不到
|
|
77433
76626
|
projectPaths: projectsStore.listMerged().map((x2) => x2.path),
|
|
77434
|
-
sharedHome:
|
|
76627
|
+
sharedHome: import_node_path84.default.join(import_node_os31.default.homedir(), ".codex"),
|
|
77435
76628
|
isolatedHome: codexIsolatedHome
|
|
77436
76629
|
}),
|
|
77437
76630
|
codexHomeForThread: (threadId) => locateCodexThread(codexRolloutRoots(config.dataDir), threadId)?.home,
|
|
@@ -77457,10 +76650,10 @@ async function startDaemon(config) {
|
|
|
77457
76650
|
);
|
|
77458
76651
|
registerAdapter(PI_CLOUD_TOOL_ID, new CloudPiAdapter({ client: cloudGateway, history: cloudHistorySource, logger }));
|
|
77459
76652
|
const piMcpBridgeCandidates = [
|
|
77460
|
-
|
|
77461
|
-
|
|
76653
|
+
import_node_path84.default.join(here, "pi-mcp-bridge", "extension.cjs"),
|
|
76654
|
+
import_node_path84.default.join(here, "..", "dist", "pi-mcp-bridge", "extension.cjs")
|
|
77462
76655
|
];
|
|
77463
|
-
const piMcpBridgePath = piMcpBridgeCandidates.find((p3) =>
|
|
76656
|
+
const piMcpBridgePath = piMcpBridgeCandidates.find((p3) => import_node_fs65.default.existsSync(p3));
|
|
77464
76657
|
if (piMcpBridgePath) {
|
|
77465
76658
|
logger.info("pi-mcp-bridge extension resolved", { path: piMcpBridgePath });
|
|
77466
76659
|
} else {
|
|
@@ -77766,11 +76959,11 @@ async function startDaemon(config) {
|
|
|
77766
76959
|
// 'persona/<pid>/owner',default 走 'default'。
|
|
77767
76960
|
getSessionScope: (sid) => manager.findOwnedSessionScope(sid),
|
|
77768
76961
|
// guest path guard:candidate 必须在 personaRoot 子树或调用者自己的 user-dir 下
|
|
77769
|
-
personaRoot:
|
|
76962
|
+
personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
|
|
77770
76963
|
usersRoot
|
|
77771
76964
|
},
|
|
77772
76965
|
// workspace/git/history/skills/agents handler 共用的 guest path guard 锚点
|
|
77773
|
-
personaRoot:
|
|
76966
|
+
personaRoot: import_node_path84.default.join(config.dataDir, "personas"),
|
|
77774
76967
|
// v2 多人 persona 隔离:handler 派生 guest user-dir 放行
|
|
77775
76968
|
usersRoot,
|
|
77776
76969
|
// v2 Phase 6: whoami handler 装在 owner principal.displayName + persona 解析
|
|
@@ -78076,7 +77269,7 @@ async function startDaemon(config) {
|
|
|
78076
77269
|
});
|
|
78077
77270
|
shiftScheduler.start();
|
|
78078
77271
|
logger.info("shift scheduler started", { shiftCount: shiftStore.list().length });
|
|
78079
|
-
const larkBotStore = createLarkBotBindingStore(
|
|
77272
|
+
const larkBotStore = createLarkBotBindingStore(import_node_path84.default.join(config.dataDir, "personas"));
|
|
78080
77273
|
const larkBotCloud = createLarkBotCloudClient({
|
|
78081
77274
|
api: config.clawosApi ?? DEFAULT_CLAWOS_API,
|
|
78082
77275
|
getLoginPass: () => ownerIdentityStore.read()?.loginPass ?? null
|
|
@@ -78088,7 +77281,7 @@ async function startDaemon(config) {
|
|
|
78088
77281
|
store: larkBotStore,
|
|
78089
77282
|
fetchResource: (appId, messageId, fileKey, maxBytes, type) => larkBotCloud.fetchResource(appId, messageId, fileKey, maxBytes, type),
|
|
78090
77283
|
// 图片落 guest userWorkDir 下(capId = lark-<chat_id>):CC 经 --add-dir + allowRead carve 可 Read
|
|
78091
|
-
mediaRootFor: (chatId) =>
|
|
77284
|
+
mediaRootFor: (chatId) => import_node_path84.default.join(deriveUserWorkDir(`lark-${chatId}`, usersRoot), "lark-media"),
|
|
78092
77285
|
isShuttingDown: () => larkDraining,
|
|
78093
77286
|
logger: {
|
|
78094
77287
|
warn: (msg) => logger.warn(msg),
|
|
@@ -78401,8 +77594,8 @@ async function startDaemon(config) {
|
|
|
78401
77594
|
const lines = [
|
|
78402
77595
|
`Tunnel: ${r2.url}`,
|
|
78403
77596
|
...resolvedAuthToken ? [`Connect: ${connectUrl}`] : [],
|
|
78404
|
-
`Frpc config: ${
|
|
78405
|
-
`Frpc log: ${
|
|
77597
|
+
`Frpc config: ${import_node_path84.default.join(config.dataDir, "frpc.toml")}`,
|
|
77598
|
+
`Frpc log: ${import_node_path84.default.join(logDir, "frpc.log")}`
|
|
78406
77599
|
];
|
|
78407
77600
|
const width2 = Math.max(...lines.map((l2) => l2.length));
|
|
78408
77601
|
const bar = "\u2550".repeat(width2 + 4);
|
|
@@ -78415,8 +77608,8 @@ ${bar}
|
|
|
78415
77608
|
|
|
78416
77609
|
`);
|
|
78417
77610
|
try {
|
|
78418
|
-
const connectPath =
|
|
78419
|
-
|
|
77611
|
+
const connectPath = import_node_path84.default.join(config.dataDir, "connect.txt");
|
|
77612
|
+
import_node_fs65.default.writeFileSync(connectPath, lines.join("\n") + "\n", { mode: 384 });
|
|
78420
77613
|
} catch {
|
|
78421
77614
|
}
|
|
78422
77615
|
} catch (err) {
|
|
@@ -78485,7 +77678,6 @@ ${bar}
|
|
|
78485
77678
|
larkDraining = true;
|
|
78486
77679
|
clearInterval(attachmentGcInterval);
|
|
78487
77680
|
clearInterval(cloudRecoveryInterval);
|
|
78488
|
-
cloudCancelOutbox.stop();
|
|
78489
77681
|
observer.stopAll();
|
|
78490
77682
|
manager.stopAll();
|
|
78491
77683
|
await extensionRuntime.stopAll();
|
|
@@ -78516,9 +77708,9 @@ ${bar}
|
|
|
78516
77708
|
};
|
|
78517
77709
|
}
|
|
78518
77710
|
function migrateDropPersonsDir(dataDir) {
|
|
78519
|
-
const dir =
|
|
77711
|
+
const dir = import_node_path84.default.join(dataDir, "persons");
|
|
78520
77712
|
try {
|
|
78521
|
-
|
|
77713
|
+
import_node_fs65.default.rmSync(dir, { recursive: true, force: true });
|
|
78522
77714
|
} catch {
|
|
78523
77715
|
}
|
|
78524
77716
|
}
|