@mrrlin-dev/mcp 0.4.6 → 0.4.7
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/bin.cjs +1902 -789
- package/dist/consensus/personas/pii-gate.md +11 -0
- package/package.json +2 -2
package/dist/bin.cjs
CHANGED
|
@@ -6246,7 +6246,7 @@ var require_websocket = __commonJS({
|
|
|
6246
6246
|
var http2 = require("http");
|
|
6247
6247
|
var net = require("net");
|
|
6248
6248
|
var tls = require("tls");
|
|
6249
|
-
var { randomBytes: randomBytes4, createHash:
|
|
6249
|
+
var { randomBytes: randomBytes4, createHash: createHash5 } = require("crypto");
|
|
6250
6250
|
var { Duplex, Readable } = require("stream");
|
|
6251
6251
|
var { URL: URL2 } = require("url");
|
|
6252
6252
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -6914,7 +6914,7 @@ var require_websocket = __commonJS({
|
|
|
6914
6914
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
6915
6915
|
return;
|
|
6916
6916
|
}
|
|
6917
|
-
const digest =
|
|
6917
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
6918
6918
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
6919
6919
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
6920
6920
|
return;
|
|
@@ -7283,7 +7283,7 @@ var require_websocket_server = __commonJS({
|
|
|
7283
7283
|
var EventEmitter3 = require("events");
|
|
7284
7284
|
var http2 = require("http");
|
|
7285
7285
|
var { Duplex } = require("stream");
|
|
7286
|
-
var { createHash:
|
|
7286
|
+
var { createHash: createHash5 } = require("crypto");
|
|
7287
7287
|
var extension2 = require_extension();
|
|
7288
7288
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
7289
7289
|
var subprotocol2 = require_subprotocol();
|
|
@@ -7590,7 +7590,7 @@ var require_websocket_server = __commonJS({
|
|
|
7590
7590
|
);
|
|
7591
7591
|
}
|
|
7592
7592
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
7593
|
-
const digest =
|
|
7593
|
+
const digest = createHash5("sha1").update(key + GUID).digest("base64");
|
|
7594
7594
|
const headers = [
|
|
7595
7595
|
"HTTP/1.1 101 Switching Protocols",
|
|
7596
7596
|
"Upgrade: websocket",
|
|
@@ -7729,14 +7729,14 @@ var require_polyfills = __commonJS({
|
|
|
7729
7729
|
fs10.fstatSync = statFixSync(fs10.fstatSync);
|
|
7730
7730
|
fs10.lstatSync = statFixSync(fs10.lstatSync);
|
|
7731
7731
|
if (fs10.chmod && !fs10.lchmod) {
|
|
7732
|
-
fs10.lchmod = function(
|
|
7732
|
+
fs10.lchmod = function(path22, mode, cb) {
|
|
7733
7733
|
if (cb) process.nextTick(cb);
|
|
7734
7734
|
};
|
|
7735
7735
|
fs10.lchmodSync = function() {
|
|
7736
7736
|
};
|
|
7737
7737
|
}
|
|
7738
7738
|
if (fs10.chown && !fs10.lchown) {
|
|
7739
|
-
fs10.lchown = function(
|
|
7739
|
+
fs10.lchown = function(path22, uid, gid, cb) {
|
|
7740
7740
|
if (cb) process.nextTick(cb);
|
|
7741
7741
|
};
|
|
7742
7742
|
fs10.lchownSync = function() {
|
|
@@ -7744,7 +7744,7 @@ var require_polyfills = __commonJS({
|
|
|
7744
7744
|
}
|
|
7745
7745
|
if (platform === "win32") {
|
|
7746
7746
|
fs10.rename = typeof fs10.rename !== "function" ? fs10.rename : function(fs$rename) {
|
|
7747
|
-
function
|
|
7747
|
+
function rename4(from, to, cb) {
|
|
7748
7748
|
var start = Date.now();
|
|
7749
7749
|
var backoff = 0;
|
|
7750
7750
|
fs$rename(from, to, function CB(er) {
|
|
@@ -7764,8 +7764,8 @@ var require_polyfills = __commonJS({
|
|
|
7764
7764
|
if (cb) cb(er);
|
|
7765
7765
|
});
|
|
7766
7766
|
}
|
|
7767
|
-
if (Object.setPrototypeOf) Object.setPrototypeOf(
|
|
7768
|
-
return
|
|
7767
|
+
if (Object.setPrototypeOf) Object.setPrototypeOf(rename4, fs$rename);
|
|
7768
|
+
return rename4;
|
|
7769
7769
|
}(fs10.rename);
|
|
7770
7770
|
}
|
|
7771
7771
|
fs10.read = typeof fs10.read !== "function" ? fs10.read : function(fs$read) {
|
|
@@ -7803,9 +7803,9 @@ var require_polyfills = __commonJS({
|
|
|
7803
7803
|
};
|
|
7804
7804
|
}(fs10.readSync);
|
|
7805
7805
|
function patchLchmod(fs11) {
|
|
7806
|
-
fs11.lchmod = function(
|
|
7806
|
+
fs11.lchmod = function(path22, mode, callback) {
|
|
7807
7807
|
fs11.open(
|
|
7808
|
-
|
|
7808
|
+
path22,
|
|
7809
7809
|
constants2.O_WRONLY | constants2.O_SYMLINK,
|
|
7810
7810
|
mode,
|
|
7811
7811
|
function(err, fd) {
|
|
@@ -7821,8 +7821,8 @@ var require_polyfills = __commonJS({
|
|
|
7821
7821
|
}
|
|
7822
7822
|
);
|
|
7823
7823
|
};
|
|
7824
|
-
fs11.lchmodSync = function(
|
|
7825
|
-
var fd = fs11.openSync(
|
|
7824
|
+
fs11.lchmodSync = function(path22, mode) {
|
|
7825
|
+
var fd = fs11.openSync(path22, constants2.O_WRONLY | constants2.O_SYMLINK, mode);
|
|
7826
7826
|
var threw = true;
|
|
7827
7827
|
var ret;
|
|
7828
7828
|
try {
|
|
@@ -7843,8 +7843,8 @@ var require_polyfills = __commonJS({
|
|
|
7843
7843
|
}
|
|
7844
7844
|
function patchLutimes(fs11) {
|
|
7845
7845
|
if (constants2.hasOwnProperty("O_SYMLINK") && fs11.futimes) {
|
|
7846
|
-
fs11.lutimes = function(
|
|
7847
|
-
fs11.open(
|
|
7846
|
+
fs11.lutimes = function(path22, at, mt, cb) {
|
|
7847
|
+
fs11.open(path22, constants2.O_SYMLINK, function(er, fd) {
|
|
7848
7848
|
if (er) {
|
|
7849
7849
|
if (cb) cb(er);
|
|
7850
7850
|
return;
|
|
@@ -7856,8 +7856,8 @@ var require_polyfills = __commonJS({
|
|
|
7856
7856
|
});
|
|
7857
7857
|
});
|
|
7858
7858
|
};
|
|
7859
|
-
fs11.lutimesSync = function(
|
|
7860
|
-
var fd = fs11.openSync(
|
|
7859
|
+
fs11.lutimesSync = function(path22, at, mt) {
|
|
7860
|
+
var fd = fs11.openSync(path22, constants2.O_SYMLINK);
|
|
7861
7861
|
var ret;
|
|
7862
7862
|
var threw = true;
|
|
7863
7863
|
try {
|
|
@@ -7975,11 +7975,11 @@ var require_legacy_streams = __commonJS({
|
|
|
7975
7975
|
ReadStream,
|
|
7976
7976
|
WriteStream
|
|
7977
7977
|
};
|
|
7978
|
-
function ReadStream(
|
|
7979
|
-
if (!(this instanceof ReadStream)) return new ReadStream(
|
|
7978
|
+
function ReadStream(path22, options) {
|
|
7979
|
+
if (!(this instanceof ReadStream)) return new ReadStream(path22, options);
|
|
7980
7980
|
Stream.call(this);
|
|
7981
7981
|
var self = this;
|
|
7982
|
-
this.path =
|
|
7982
|
+
this.path = path22;
|
|
7983
7983
|
this.fd = null;
|
|
7984
7984
|
this.readable = true;
|
|
7985
7985
|
this.paused = false;
|
|
@@ -8024,10 +8024,10 @@ var require_legacy_streams = __commonJS({
|
|
|
8024
8024
|
self._read();
|
|
8025
8025
|
});
|
|
8026
8026
|
}
|
|
8027
|
-
function WriteStream(
|
|
8028
|
-
if (!(this instanceof WriteStream)) return new WriteStream(
|
|
8027
|
+
function WriteStream(path22, options) {
|
|
8028
|
+
if (!(this instanceof WriteStream)) return new WriteStream(path22, options);
|
|
8029
8029
|
Stream.call(this);
|
|
8030
|
-
this.path =
|
|
8030
|
+
this.path = path22;
|
|
8031
8031
|
this.fd = null;
|
|
8032
8032
|
this.writable = true;
|
|
8033
8033
|
this.flags = "w";
|
|
@@ -8169,15 +8169,15 @@ var require_graceful_fs = __commonJS({
|
|
|
8169
8169
|
fs11.createReadStream = createReadStream;
|
|
8170
8170
|
fs11.createWriteStream = createWriteStream;
|
|
8171
8171
|
var fs$readFile = fs11.readFile;
|
|
8172
|
-
fs11.readFile =
|
|
8173
|
-
function
|
|
8172
|
+
fs11.readFile = readFile9;
|
|
8173
|
+
function readFile9(path22, options, cb) {
|
|
8174
8174
|
if (typeof options === "function")
|
|
8175
8175
|
cb = options, options = null;
|
|
8176
|
-
return go$readFile(
|
|
8177
|
-
function go$readFile(
|
|
8178
|
-
return fs$readFile(
|
|
8176
|
+
return go$readFile(path22, options, cb);
|
|
8177
|
+
function go$readFile(path23, options2, cb2, startTime) {
|
|
8178
|
+
return fs$readFile(path23, options2, function(err) {
|
|
8179
8179
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8180
|
-
enqueue([go$readFile, [
|
|
8180
|
+
enqueue([go$readFile, [path23, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8181
8181
|
else {
|
|
8182
8182
|
if (typeof cb2 === "function")
|
|
8183
8183
|
cb2.apply(this, arguments);
|
|
@@ -8186,15 +8186,15 @@ var require_graceful_fs = __commonJS({
|
|
|
8186
8186
|
}
|
|
8187
8187
|
}
|
|
8188
8188
|
var fs$writeFile = fs11.writeFile;
|
|
8189
|
-
fs11.writeFile =
|
|
8190
|
-
function
|
|
8189
|
+
fs11.writeFile = writeFile5;
|
|
8190
|
+
function writeFile5(path22, data, options, cb) {
|
|
8191
8191
|
if (typeof options === "function")
|
|
8192
8192
|
cb = options, options = null;
|
|
8193
|
-
return go$writeFile(
|
|
8194
|
-
function go$writeFile(
|
|
8195
|
-
return fs$writeFile(
|
|
8193
|
+
return go$writeFile(path22, data, options, cb);
|
|
8194
|
+
function go$writeFile(path23, data2, options2, cb2, startTime) {
|
|
8195
|
+
return fs$writeFile(path23, data2, options2, function(err) {
|
|
8196
8196
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8197
|
-
enqueue([go$writeFile, [
|
|
8197
|
+
enqueue([go$writeFile, [path23, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8198
8198
|
else {
|
|
8199
8199
|
if (typeof cb2 === "function")
|
|
8200
8200
|
cb2.apply(this, arguments);
|
|
@@ -8204,15 +8204,15 @@ var require_graceful_fs = __commonJS({
|
|
|
8204
8204
|
}
|
|
8205
8205
|
var fs$appendFile = fs11.appendFile;
|
|
8206
8206
|
if (fs$appendFile)
|
|
8207
|
-
fs11.appendFile =
|
|
8208
|
-
function
|
|
8207
|
+
fs11.appendFile = appendFile2;
|
|
8208
|
+
function appendFile2(path22, data, options, cb) {
|
|
8209
8209
|
if (typeof options === "function")
|
|
8210
8210
|
cb = options, options = null;
|
|
8211
|
-
return go$appendFile(
|
|
8212
|
-
function go$appendFile(
|
|
8213
|
-
return fs$appendFile(
|
|
8211
|
+
return go$appendFile(path22, data, options, cb);
|
|
8212
|
+
function go$appendFile(path23, data2, options2, cb2, startTime) {
|
|
8213
|
+
return fs$appendFile(path23, data2, options2, function(err) {
|
|
8214
8214
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8215
|
-
enqueue([go$appendFile, [
|
|
8215
|
+
enqueue([go$appendFile, [path23, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8216
8216
|
else {
|
|
8217
8217
|
if (typeof cb2 === "function")
|
|
8218
8218
|
cb2.apply(this, arguments);
|
|
@@ -8241,33 +8241,33 @@ var require_graceful_fs = __commonJS({
|
|
|
8241
8241
|
}
|
|
8242
8242
|
}
|
|
8243
8243
|
var fs$readdir = fs11.readdir;
|
|
8244
|
-
fs11.readdir =
|
|
8244
|
+
fs11.readdir = readdir5;
|
|
8245
8245
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
8246
|
-
function
|
|
8246
|
+
function readdir5(path22, options, cb) {
|
|
8247
8247
|
if (typeof options === "function")
|
|
8248
8248
|
cb = options, options = null;
|
|
8249
|
-
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(
|
|
8250
|
-
return fs$readdir(
|
|
8251
|
-
|
|
8249
|
+
var go$readdir = noReaddirOptionVersions.test(process.version) ? function go$readdir2(path23, options2, cb2, startTime) {
|
|
8250
|
+
return fs$readdir(path23, fs$readdirCallback(
|
|
8251
|
+
path23,
|
|
8252
8252
|
options2,
|
|
8253
8253
|
cb2,
|
|
8254
8254
|
startTime
|
|
8255
8255
|
));
|
|
8256
|
-
} : function go$readdir2(
|
|
8257
|
-
return fs$readdir(
|
|
8258
|
-
|
|
8256
|
+
} : function go$readdir2(path23, options2, cb2, startTime) {
|
|
8257
|
+
return fs$readdir(path23, options2, fs$readdirCallback(
|
|
8258
|
+
path23,
|
|
8259
8259
|
options2,
|
|
8260
8260
|
cb2,
|
|
8261
8261
|
startTime
|
|
8262
8262
|
));
|
|
8263
8263
|
};
|
|
8264
|
-
return go$readdir(
|
|
8265
|
-
function fs$readdirCallback(
|
|
8264
|
+
return go$readdir(path22, options, cb);
|
|
8265
|
+
function fs$readdirCallback(path23, options2, cb2, startTime) {
|
|
8266
8266
|
return function(err, files) {
|
|
8267
8267
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8268
8268
|
enqueue([
|
|
8269
8269
|
go$readdir,
|
|
8270
|
-
[
|
|
8270
|
+
[path23, options2, cb2],
|
|
8271
8271
|
err,
|
|
8272
8272
|
startTime || Date.now(),
|
|
8273
8273
|
Date.now()
|
|
@@ -8338,7 +8338,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8338
8338
|
enumerable: true,
|
|
8339
8339
|
configurable: true
|
|
8340
8340
|
});
|
|
8341
|
-
function ReadStream(
|
|
8341
|
+
function ReadStream(path22, options) {
|
|
8342
8342
|
if (this instanceof ReadStream)
|
|
8343
8343
|
return fs$ReadStream.apply(this, arguments), this;
|
|
8344
8344
|
else
|
|
@@ -8358,7 +8358,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8358
8358
|
}
|
|
8359
8359
|
});
|
|
8360
8360
|
}
|
|
8361
|
-
function WriteStream(
|
|
8361
|
+
function WriteStream(path22, options) {
|
|
8362
8362
|
if (this instanceof WriteStream)
|
|
8363
8363
|
return fs$WriteStream.apply(this, arguments), this;
|
|
8364
8364
|
else
|
|
@@ -8376,22 +8376,22 @@ var require_graceful_fs = __commonJS({
|
|
|
8376
8376
|
}
|
|
8377
8377
|
});
|
|
8378
8378
|
}
|
|
8379
|
-
function createReadStream(
|
|
8380
|
-
return new fs11.ReadStream(
|
|
8379
|
+
function createReadStream(path22, options) {
|
|
8380
|
+
return new fs11.ReadStream(path22, options);
|
|
8381
8381
|
}
|
|
8382
|
-
function createWriteStream(
|
|
8383
|
-
return new fs11.WriteStream(
|
|
8382
|
+
function createWriteStream(path22, options) {
|
|
8383
|
+
return new fs11.WriteStream(path22, options);
|
|
8384
8384
|
}
|
|
8385
8385
|
var fs$open = fs11.open;
|
|
8386
8386
|
fs11.open = open;
|
|
8387
|
-
function open(
|
|
8387
|
+
function open(path22, flags, mode, cb) {
|
|
8388
8388
|
if (typeof mode === "function")
|
|
8389
8389
|
cb = mode, mode = null;
|
|
8390
|
-
return go$open(
|
|
8391
|
-
function go$open(
|
|
8392
|
-
return fs$open(
|
|
8390
|
+
return go$open(path22, flags, mode, cb);
|
|
8391
|
+
function go$open(path23, flags2, mode2, cb2, startTime) {
|
|
8392
|
+
return fs$open(path23, flags2, mode2, function(err, fd) {
|
|
8393
8393
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8394
|
-
enqueue([go$open, [
|
|
8394
|
+
enqueue([go$open, [path23, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8395
8395
|
else {
|
|
8396
8396
|
if (typeof cb2 === "function")
|
|
8397
8397
|
cb2.apply(this, arguments);
|
|
@@ -8882,11 +8882,11 @@ var require_mtime_precision = __commonJS({
|
|
|
8882
8882
|
function probe(file2, fs10, callback) {
|
|
8883
8883
|
const cachedPrecision = fs10[cacheSymbol];
|
|
8884
8884
|
if (cachedPrecision) {
|
|
8885
|
-
return fs10.stat(file2, (err,
|
|
8885
|
+
return fs10.stat(file2, (err, stat3) => {
|
|
8886
8886
|
if (err) {
|
|
8887
8887
|
return callback(err);
|
|
8888
8888
|
}
|
|
8889
|
-
callback(null,
|
|
8889
|
+
callback(null, stat3.mtime, cachedPrecision);
|
|
8890
8890
|
});
|
|
8891
8891
|
}
|
|
8892
8892
|
const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
|
|
@@ -8894,13 +8894,13 @@ var require_mtime_precision = __commonJS({
|
|
|
8894
8894
|
if (err) {
|
|
8895
8895
|
return callback(err);
|
|
8896
8896
|
}
|
|
8897
|
-
fs10.stat(file2, (err2,
|
|
8897
|
+
fs10.stat(file2, (err2, stat3) => {
|
|
8898
8898
|
if (err2) {
|
|
8899
8899
|
return callback(err2);
|
|
8900
8900
|
}
|
|
8901
|
-
const precision =
|
|
8901
|
+
const precision = stat3.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
|
|
8902
8902
|
Object.defineProperty(fs10, cacheSymbol, { value: precision });
|
|
8903
|
-
callback(null,
|
|
8903
|
+
callback(null, stat3.mtime, precision);
|
|
8904
8904
|
});
|
|
8905
8905
|
});
|
|
8906
8906
|
}
|
|
@@ -8920,7 +8920,7 @@ var require_mtime_precision = __commonJS({
|
|
|
8920
8920
|
var require_lockfile = __commonJS({
|
|
8921
8921
|
"../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/lockfile.js"(exports2, module2) {
|
|
8922
8922
|
"use strict";
|
|
8923
|
-
var
|
|
8923
|
+
var path22 = require("path");
|
|
8924
8924
|
var fs10 = require_graceful_fs();
|
|
8925
8925
|
var retry = require_retry2();
|
|
8926
8926
|
var onExit = require_signal_exit();
|
|
@@ -8931,7 +8931,7 @@ var require_lockfile = __commonJS({
|
|
|
8931
8931
|
}
|
|
8932
8932
|
function resolveCanonicalPath(file2, options, callback) {
|
|
8933
8933
|
if (!options.realpath) {
|
|
8934
|
-
return callback(null,
|
|
8934
|
+
return callback(null, path22.resolve(file2));
|
|
8935
8935
|
}
|
|
8936
8936
|
options.fs.realpath(file2, callback);
|
|
8937
8937
|
}
|
|
@@ -8954,14 +8954,14 @@ var require_lockfile = __commonJS({
|
|
|
8954
8954
|
if (options.stale <= 0) {
|
|
8955
8955
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
8956
8956
|
}
|
|
8957
|
-
options.fs.stat(lockfilePath, (err2,
|
|
8957
|
+
options.fs.stat(lockfilePath, (err2, stat3) => {
|
|
8958
8958
|
if (err2) {
|
|
8959
8959
|
if (err2.code === "ENOENT") {
|
|
8960
8960
|
return acquireLock(file2, { ...options, stale: 0 }, callback);
|
|
8961
8961
|
}
|
|
8962
8962
|
return callback(err2);
|
|
8963
8963
|
}
|
|
8964
|
-
if (!isLockStale(
|
|
8964
|
+
if (!isLockStale(stat3, options)) {
|
|
8965
8965
|
return callback(Object.assign(new Error("Lock file is already being held"), { code: "ELOCKED", file: file2 }));
|
|
8966
8966
|
}
|
|
8967
8967
|
removeLock(file2, options, (err3) => {
|
|
@@ -8973,8 +8973,8 @@ var require_lockfile = __commonJS({
|
|
|
8973
8973
|
});
|
|
8974
8974
|
});
|
|
8975
8975
|
}
|
|
8976
|
-
function isLockStale(
|
|
8977
|
-
return
|
|
8976
|
+
function isLockStale(stat3, options) {
|
|
8977
|
+
return stat3.mtime.getTime() < Date.now() - options.stale;
|
|
8978
8978
|
}
|
|
8979
8979
|
function removeLock(file2, options, callback) {
|
|
8980
8980
|
options.fs.rmdir(getLockFile(file2, options), (err) => {
|
|
@@ -8992,7 +8992,7 @@ var require_lockfile = __commonJS({
|
|
|
8992
8992
|
lock2.updateDelay = lock2.updateDelay || options.update;
|
|
8993
8993
|
lock2.updateTimeout = setTimeout(() => {
|
|
8994
8994
|
lock2.updateTimeout = null;
|
|
8995
|
-
options.fs.stat(lock2.lockfilePath, (err,
|
|
8995
|
+
options.fs.stat(lock2.lockfilePath, (err, stat3) => {
|
|
8996
8996
|
const isOverThreshold = lock2.lastUpdate + options.stale < Date.now();
|
|
8997
8997
|
if (err) {
|
|
8998
8998
|
if (err.code === "ENOENT" || isOverThreshold) {
|
|
@@ -9001,7 +9001,7 @@ var require_lockfile = __commonJS({
|
|
|
9001
9001
|
lock2.updateDelay = 1e3;
|
|
9002
9002
|
return updateLock(file2, options);
|
|
9003
9003
|
}
|
|
9004
|
-
const isMtimeOurs = lock2.mtime.getTime() ===
|
|
9004
|
+
const isMtimeOurs = lock2.mtime.getTime() === stat3.mtime.getTime();
|
|
9005
9005
|
if (!isMtimeOurs) {
|
|
9006
9006
|
return setLockAsCompromised(
|
|
9007
9007
|
file2,
|
|
@@ -9126,11 +9126,11 @@ var require_lockfile = __commonJS({
|
|
|
9126
9126
|
if (err) {
|
|
9127
9127
|
return callback(err);
|
|
9128
9128
|
}
|
|
9129
|
-
options.fs.stat(getLockFile(file3, options), (err2,
|
|
9129
|
+
options.fs.stat(getLockFile(file3, options), (err2, stat3) => {
|
|
9130
9130
|
if (err2) {
|
|
9131
9131
|
return err2.code === "ENOENT" ? callback(null, false) : callback(err2);
|
|
9132
9132
|
}
|
|
9133
|
-
return callback(null, !isLockStale(
|
|
9133
|
+
return callback(null, !isLockStale(stat3, options));
|
|
9134
9134
|
});
|
|
9135
9135
|
});
|
|
9136
9136
|
}
|
|
@@ -10795,10 +10795,10 @@ var require_segments = __commonJS({
|
|
|
10795
10795
|
const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
|
|
10796
10796
|
const nodes = buildNodes(segs);
|
|
10797
10797
|
const graph = buildGraph(nodes, version2);
|
|
10798
|
-
const
|
|
10798
|
+
const path22 = dijkstra.find_path(graph.map, "start", "end");
|
|
10799
10799
|
const optimizedSegs = [];
|
|
10800
|
-
for (let i = 1; i <
|
|
10801
|
-
optimizedSegs.push(graph.table[
|
|
10800
|
+
for (let i = 1; i < path22.length - 1; i++) {
|
|
10801
|
+
optimizedSegs.push(graph.table[path22[i]].node);
|
|
10802
10802
|
}
|
|
10803
10803
|
return exports2.fromArray(mergeSegments(optimizedSegs));
|
|
10804
10804
|
};
|
|
@@ -13275,7 +13275,7 @@ var require_png2 = __commonJS({
|
|
|
13275
13275
|
});
|
|
13276
13276
|
png.pack();
|
|
13277
13277
|
};
|
|
13278
|
-
exports2.renderToFile = function renderToFile(
|
|
13278
|
+
exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
|
|
13279
13279
|
if (typeof cb === "undefined") {
|
|
13280
13280
|
cb = options;
|
|
13281
13281
|
options = void 0;
|
|
@@ -13286,7 +13286,7 @@ var require_png2 = __commonJS({
|
|
|
13286
13286
|
called = true;
|
|
13287
13287
|
cb.apply(null, args);
|
|
13288
13288
|
};
|
|
13289
|
-
const stream = fs10.createWriteStream(
|
|
13289
|
+
const stream = fs10.createWriteStream(path22);
|
|
13290
13290
|
stream.on("error", done);
|
|
13291
13291
|
stream.on("close", done);
|
|
13292
13292
|
exports2.renderToFileStream(stream, qrData, options);
|
|
@@ -13348,14 +13348,14 @@ var require_utf8 = __commonJS({
|
|
|
13348
13348
|
}
|
|
13349
13349
|
return output3;
|
|
13350
13350
|
};
|
|
13351
|
-
exports2.renderToFile = function renderToFile(
|
|
13351
|
+
exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
|
|
13352
13352
|
if (typeof cb === "undefined") {
|
|
13353
13353
|
cb = options;
|
|
13354
13354
|
options = void 0;
|
|
13355
13355
|
}
|
|
13356
13356
|
const fs10 = require("fs");
|
|
13357
13357
|
const utf8 = exports2.render(qrData, options);
|
|
13358
|
-
fs10.writeFile(
|
|
13358
|
+
fs10.writeFile(path22, utf8, cb);
|
|
13359
13359
|
};
|
|
13360
13360
|
}
|
|
13361
13361
|
});
|
|
@@ -13476,7 +13476,7 @@ var require_svg_tag = __commonJS({
|
|
|
13476
13476
|
return str;
|
|
13477
13477
|
}
|
|
13478
13478
|
function qrToPath(data, size, margin) {
|
|
13479
|
-
let
|
|
13479
|
+
let path22 = "";
|
|
13480
13480
|
let moveBy = 0;
|
|
13481
13481
|
let newRow = false;
|
|
13482
13482
|
let lineLength = 0;
|
|
@@ -13487,19 +13487,19 @@ var require_svg_tag = __commonJS({
|
|
|
13487
13487
|
if (data[i]) {
|
|
13488
13488
|
lineLength++;
|
|
13489
13489
|
if (!(i > 0 && col > 0 && data[i - 1])) {
|
|
13490
|
-
|
|
13490
|
+
path22 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
|
|
13491
13491
|
moveBy = 0;
|
|
13492
13492
|
newRow = false;
|
|
13493
13493
|
}
|
|
13494
13494
|
if (!(col + 1 < size && data[i + 1])) {
|
|
13495
|
-
|
|
13495
|
+
path22 += svgCmd("h", lineLength);
|
|
13496
13496
|
lineLength = 0;
|
|
13497
13497
|
}
|
|
13498
13498
|
} else {
|
|
13499
13499
|
moveBy++;
|
|
13500
13500
|
}
|
|
13501
13501
|
}
|
|
13502
|
-
return
|
|
13502
|
+
return path22;
|
|
13503
13503
|
}
|
|
13504
13504
|
exports2.render = function render(qrData, options, cb) {
|
|
13505
13505
|
const opts = Utils.getOptions(options);
|
|
@@ -13507,10 +13507,10 @@ var require_svg_tag = __commonJS({
|
|
|
13507
13507
|
const data = qrData.modules.data;
|
|
13508
13508
|
const qrcodesize = size + opts.margin * 2;
|
|
13509
13509
|
const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
|
|
13510
|
-
const
|
|
13510
|
+
const path22 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
|
|
13511
13511
|
const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
|
|
13512
13512
|
const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
|
|
13513
|
-
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg +
|
|
13513
|
+
const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path22 + "</svg>\n";
|
|
13514
13514
|
if (typeof cb === "function") {
|
|
13515
13515
|
cb(null, svgTag);
|
|
13516
13516
|
}
|
|
@@ -13524,7 +13524,7 @@ var require_svg = __commonJS({
|
|
|
13524
13524
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/svg.js"(exports2) {
|
|
13525
13525
|
var svgTagRenderer = require_svg_tag();
|
|
13526
13526
|
exports2.render = svgTagRenderer.render;
|
|
13527
|
-
exports2.renderToFile = function renderToFile(
|
|
13527
|
+
exports2.renderToFile = function renderToFile(path22, qrData, options, cb) {
|
|
13528
13528
|
if (typeof cb === "undefined") {
|
|
13529
13529
|
cb = options;
|
|
13530
13530
|
options = void 0;
|
|
@@ -13532,7 +13532,7 @@ var require_svg = __commonJS({
|
|
|
13532
13532
|
const fs10 = require("fs");
|
|
13533
13533
|
const svgTag = exports2.render(qrData, options);
|
|
13534
13534
|
const xmlStr = '<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">' + svgTag;
|
|
13535
|
-
fs10.writeFile(
|
|
13535
|
+
fs10.writeFile(path22, xmlStr, cb);
|
|
13536
13536
|
};
|
|
13537
13537
|
}
|
|
13538
13538
|
});
|
|
@@ -13690,8 +13690,8 @@ var require_server = __commonJS({
|
|
|
13690
13690
|
cb
|
|
13691
13691
|
};
|
|
13692
13692
|
}
|
|
13693
|
-
function getTypeFromFilename(
|
|
13694
|
-
return
|
|
13693
|
+
function getTypeFromFilename(path22) {
|
|
13694
|
+
return path22.slice((path22.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
|
|
13695
13695
|
}
|
|
13696
13696
|
function getRendererFromType(type) {
|
|
13697
13697
|
switch (type) {
|
|
@@ -13755,17 +13755,17 @@ var require_server = __commonJS({
|
|
|
13755
13755
|
const renderer = getRendererFromType(params.opts.type);
|
|
13756
13756
|
return render(renderer.renderToBuffer, text, params);
|
|
13757
13757
|
};
|
|
13758
|
-
exports2.toFile = function toFile(
|
|
13759
|
-
if (typeof
|
|
13758
|
+
exports2.toFile = function toFile(path22, text, opts, cb) {
|
|
13759
|
+
if (typeof path22 !== "string" || !(typeof text === "string" || typeof text === "object")) {
|
|
13760
13760
|
throw new Error("Invalid argument");
|
|
13761
13761
|
}
|
|
13762
13762
|
if (arguments.length < 3 && !canPromise()) {
|
|
13763
13763
|
throw new Error("Too few arguments provided");
|
|
13764
13764
|
}
|
|
13765
13765
|
const params = checkParams(text, opts, cb);
|
|
13766
|
-
const type = params.opts.type || getTypeFromFilename(
|
|
13766
|
+
const type = params.opts.type || getTypeFromFilename(path22);
|
|
13767
13767
|
const renderer = getRendererFromType(type);
|
|
13768
|
-
const renderToFile = renderer.renderToFile.bind(null,
|
|
13768
|
+
const renderToFile = renderer.renderToFile.bind(null, path22);
|
|
13769
13769
|
return render(renderToFile, text, params);
|
|
13770
13770
|
};
|
|
13771
13771
|
exports2.toFileStream = function toFileStream(stream, text, opts) {
|
|
@@ -16983,8 +16983,8 @@ var require_utils3 = __commonJS({
|
|
|
16983
16983
|
}
|
|
16984
16984
|
return ind;
|
|
16985
16985
|
}
|
|
16986
|
-
function removeDotSegments(
|
|
16987
|
-
let input =
|
|
16986
|
+
function removeDotSegments(path22) {
|
|
16987
|
+
let input = path22;
|
|
16988
16988
|
const output3 = [];
|
|
16989
16989
|
let nextSlash = -1;
|
|
16990
16990
|
let len = 0;
|
|
@@ -17236,8 +17236,8 @@ var require_schemes = __commonJS({
|
|
|
17236
17236
|
wsComponent.secure = void 0;
|
|
17237
17237
|
}
|
|
17238
17238
|
if (wsComponent.resourceName) {
|
|
17239
|
-
const [
|
|
17240
|
-
wsComponent.path =
|
|
17239
|
+
const [path22, query] = wsComponent.resourceName.split("?");
|
|
17240
|
+
wsComponent.path = path22 && path22 !== "/" ? path22 : void 0;
|
|
17241
17241
|
wsComponent.query = query;
|
|
17242
17242
|
wsComponent.resourceName = void 0;
|
|
17243
17243
|
}
|
|
@@ -20644,11 +20644,11 @@ var require_dist = __commonJS({
|
|
|
20644
20644
|
});
|
|
20645
20645
|
|
|
20646
20646
|
// src/bin.ts
|
|
20647
|
-
var
|
|
20647
|
+
var import_node_path30 = __toESM(require("node:path"), 1);
|
|
20648
20648
|
var import_node_child_process18 = require("node:child_process");
|
|
20649
20649
|
var import_node_fs17 = require("node:fs");
|
|
20650
20650
|
var import_node_os15 = require("node:os");
|
|
20651
|
-
var
|
|
20651
|
+
var import_node_path31 = __toESM(require("node:path"), 1);
|
|
20652
20652
|
|
|
20653
20653
|
// src/install-codex.ts
|
|
20654
20654
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
@@ -21474,9 +21474,9 @@ async function verifyProviderReadiness(provider, run3, opts = {}) {
|
|
|
21474
21474
|
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
21475
21475
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
21476
21476
|
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
21477
|
-
var
|
|
21477
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
21478
21478
|
var import_node_child_process15 = require("node:child_process");
|
|
21479
|
-
var
|
|
21479
|
+
var import_node_crypto9 = __toESM(require("node:crypto"), 1);
|
|
21480
21480
|
|
|
21481
21481
|
// src/turn-replay-buffer.ts
|
|
21482
21482
|
var DEFAULT_MAX_EVENTS = 2e3;
|
|
@@ -22124,13 +22124,21 @@ var CodexBridgeEventMapper = class {
|
|
|
22124
22124
|
const buffered = this.outputBuffers.get(item.id);
|
|
22125
22125
|
this.outputBuffers.delete(item.id);
|
|
22126
22126
|
let content = "";
|
|
22127
|
-
if (item.type === "commandExecution")
|
|
22128
|
-
content = buffered ?? item.stdout ?? `exit code: ${item.exitCode
|
|
22127
|
+
if (item.type === "commandExecution") {
|
|
22128
|
+
content = buffered ?? item.stdout ?? (item.exitCode !== void 0 ? `exit code: ${item.exitCode}` : "exit code: none");
|
|
22129
|
+
}
|
|
22129
22130
|
if (item.type === "fileChange")
|
|
22130
22131
|
content = buffered ?? item.content ?? "";
|
|
22131
22132
|
if (item.type === "mcpToolCall")
|
|
22132
22133
|
content = item.result ?? "";
|
|
22133
|
-
|
|
22134
|
+
const tool = { id: item.id };
|
|
22135
|
+
if (item.type === "commandExecution") {
|
|
22136
|
+
if (item.exitCode !== void 0)
|
|
22137
|
+
tool.exitCode = item.exitCode;
|
|
22138
|
+
if (item.status !== void 0)
|
|
22139
|
+
tool.status = item.status;
|
|
22140
|
+
}
|
|
22141
|
+
events.push({ type: "tool_result", tool, content });
|
|
22134
22142
|
}
|
|
22135
22143
|
return events;
|
|
22136
22144
|
}
|
|
@@ -22960,10 +22968,10 @@ function mergeDefs(...defs) {
|
|
|
22960
22968
|
function cloneDef(schema) {
|
|
22961
22969
|
return mergeDefs(schema._zod.def);
|
|
22962
22970
|
}
|
|
22963
|
-
function getElementAtPath(obj,
|
|
22964
|
-
if (!
|
|
22971
|
+
function getElementAtPath(obj, path22) {
|
|
22972
|
+
if (!path22)
|
|
22965
22973
|
return obj;
|
|
22966
|
-
return
|
|
22974
|
+
return path22.reduce((acc, key) => acc?.[key], obj);
|
|
22967
22975
|
}
|
|
22968
22976
|
function promiseAllObject(promisesObj) {
|
|
22969
22977
|
const keys = Object.keys(promisesObj);
|
|
@@ -23372,11 +23380,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
23372
23380
|
}
|
|
23373
23381
|
return false;
|
|
23374
23382
|
}
|
|
23375
|
-
function prefixIssues(
|
|
23383
|
+
function prefixIssues(path22, issues) {
|
|
23376
23384
|
return issues.map((iss) => {
|
|
23377
23385
|
var _a3;
|
|
23378
23386
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
23379
|
-
iss.path.unshift(
|
|
23387
|
+
iss.path.unshift(path22);
|
|
23380
23388
|
return iss;
|
|
23381
23389
|
});
|
|
23382
23390
|
}
|
|
@@ -23523,16 +23531,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
23523
23531
|
}
|
|
23524
23532
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
23525
23533
|
const fieldErrors = { _errors: [] };
|
|
23526
|
-
const processError = (error52,
|
|
23534
|
+
const processError = (error52, path22 = []) => {
|
|
23527
23535
|
for (const issue2 of error52.issues) {
|
|
23528
23536
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
23529
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
23537
|
+
issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
|
|
23530
23538
|
} else if (issue2.code === "invalid_key") {
|
|
23531
|
-
processError({ issues: issue2.issues }, [...
|
|
23539
|
+
processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
|
|
23532
23540
|
} else if (issue2.code === "invalid_element") {
|
|
23533
|
-
processError({ issues: issue2.issues }, [...
|
|
23541
|
+
processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
|
|
23534
23542
|
} else {
|
|
23535
|
-
const fullpath = [...
|
|
23543
|
+
const fullpath = [...path22, ...issue2.path];
|
|
23536
23544
|
if (fullpath.length === 0) {
|
|
23537
23545
|
fieldErrors._errors.push(mapper(issue2));
|
|
23538
23546
|
} else {
|
|
@@ -23559,17 +23567,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
23559
23567
|
}
|
|
23560
23568
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
23561
23569
|
const result = { errors: [] };
|
|
23562
|
-
const processError = (error52,
|
|
23570
|
+
const processError = (error52, path22 = []) => {
|
|
23563
23571
|
var _a3, _b;
|
|
23564
23572
|
for (const issue2 of error52.issues) {
|
|
23565
23573
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
23566
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
23574
|
+
issue2.errors.map((issues) => processError({ issues }, [...path22, ...issue2.path]));
|
|
23567
23575
|
} else if (issue2.code === "invalid_key") {
|
|
23568
|
-
processError({ issues: issue2.issues }, [...
|
|
23576
|
+
processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
|
|
23569
23577
|
} else if (issue2.code === "invalid_element") {
|
|
23570
|
-
processError({ issues: issue2.issues }, [...
|
|
23578
|
+
processError({ issues: issue2.issues }, [...path22, ...issue2.path]);
|
|
23571
23579
|
} else {
|
|
23572
|
-
const fullpath = [...
|
|
23580
|
+
const fullpath = [...path22, ...issue2.path];
|
|
23573
23581
|
if (fullpath.length === 0) {
|
|
23574
23582
|
result.errors.push(mapper(issue2));
|
|
23575
23583
|
continue;
|
|
@@ -23601,8 +23609,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
23601
23609
|
}
|
|
23602
23610
|
function toDotPath(_path) {
|
|
23603
23611
|
const segs = [];
|
|
23604
|
-
const
|
|
23605
|
-
for (const seg of
|
|
23612
|
+
const path22 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
23613
|
+
for (const seg of path22) {
|
|
23606
23614
|
if (typeof seg === "number")
|
|
23607
23615
|
segs.push(`[${seg}]`);
|
|
23608
23616
|
else if (typeof seg === "symbol")
|
|
@@ -36294,13 +36302,13 @@ function resolveRef(ref, ctx) {
|
|
|
36294
36302
|
if (!ref.startsWith("#")) {
|
|
36295
36303
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
36296
36304
|
}
|
|
36297
|
-
const
|
|
36298
|
-
if (
|
|
36305
|
+
const path22 = ref.slice(1).split("/").filter(Boolean);
|
|
36306
|
+
if (path22.length === 0) {
|
|
36299
36307
|
return ctx.rootSchema;
|
|
36300
36308
|
}
|
|
36301
36309
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
36302
|
-
if (
|
|
36303
|
-
const key =
|
|
36310
|
+
if (path22[0] === defsKey) {
|
|
36311
|
+
const key = path22[1];
|
|
36304
36312
|
if (!key || !ctx.defs[key]) {
|
|
36305
36313
|
throw new Error(`Reference not found: ${ref}`);
|
|
36306
36314
|
}
|
|
@@ -36833,7 +36841,8 @@ var openApiOperationIds = {
|
|
|
36833
36841
|
promoteSpecReadyCas: "promoteSpecReadyCas",
|
|
36834
36842
|
recordSpecConsensusReview: "recordSpecConsensusReview",
|
|
36835
36843
|
getSpecConsensusReview: "getSpecConsensusReview",
|
|
36836
|
-
onboardingKickoffTransition: "onboardingKickoffTransition"
|
|
36844
|
+
onboardingKickoffTransition: "onboardingKickoffTransition",
|
|
36845
|
+
ingestTelemetry: "ingestTelemetry"
|
|
36837
36846
|
};
|
|
36838
36847
|
|
|
36839
36848
|
// ../../packages/schemas/dist/session.js
|
|
@@ -37074,6 +37083,116 @@ var mrrlinAsyncJobRequeueSchema = external_exports.object({
|
|
|
37074
37083
|
staleSeconds: external_exports.number().int().min(60).max(86400).default(300)
|
|
37075
37084
|
});
|
|
37076
37085
|
|
|
37086
|
+
// ../../packages/schemas/dist/telemetry.js
|
|
37087
|
+
var LOG_PROJECTION_KINDS = ["tool_use", "tool_result", "turn_lifecycle", "plumbing"];
|
|
37088
|
+
var PLUMBING_KINDS = [
|
|
37089
|
+
"socket_close",
|
|
37090
|
+
"ready",
|
|
37091
|
+
"scheduler_tick",
|
|
37092
|
+
"buffer_stats",
|
|
37093
|
+
"rate_limit_status"
|
|
37094
|
+
];
|
|
37095
|
+
var TURN_LIFECYCLES = ["completed", "failed", "interrupted"];
|
|
37096
|
+
var TOOL_OUTCOMES = ["success", "error", "unknown"];
|
|
37097
|
+
var GATE_MARKERS = ["gated", "projection-only"];
|
|
37098
|
+
var logProjectionSchema = external_exports.object({
|
|
37099
|
+
kind: external_exports.enum(LOG_PROJECTION_KINDS),
|
|
37100
|
+
sessionId: external_exports.string(),
|
|
37101
|
+
seq: external_exports.number(),
|
|
37102
|
+
projectSlug: external_exports.string().optional(),
|
|
37103
|
+
turnId: external_exports.string().optional(),
|
|
37104
|
+
toolId: external_exports.string().optional(),
|
|
37105
|
+
toolName: external_exports.string().optional(),
|
|
37106
|
+
plumbingKind: external_exports.enum(PLUMBING_KINDS).optional(),
|
|
37107
|
+
// lifecycle et al: kind "turn_lifecycle" only — the aggregator's sole legal source for these,
|
|
37108
|
+
// since it may never read `payload` and TurnTelemetry/TurnTokenUsage are runtime objects, not
|
|
37109
|
+
// projections. No "started" value: nothing emits it.
|
|
37110
|
+
lifecycle: external_exports.enum(TURN_LIFECYCLES).optional(),
|
|
37111
|
+
promptBytes: external_exports.number().optional(),
|
|
37112
|
+
inputTokens: external_exports.number().nullable().optional(),
|
|
37113
|
+
cachedInputTokens: external_exports.number().nullable().optional(),
|
|
37114
|
+
outputTokens: external_exports.number().nullable().optional(),
|
|
37115
|
+
rateLimitReached: external_exports.boolean().optional(),
|
|
37116
|
+
argKeys: external_exports.array(external_exports.string()).optional(),
|
|
37117
|
+
binary: external_exports.string().optional(),
|
|
37118
|
+
cwdIsRealCheckout: external_exports.boolean().optional(),
|
|
37119
|
+
ms: external_exports.number().optional(),
|
|
37120
|
+
bytes: external_exports.number().optional(),
|
|
37121
|
+
truncated: external_exports.boolean().optional(),
|
|
37122
|
+
exitCode: external_exports.number().optional(),
|
|
37123
|
+
outcome: external_exports.enum(TOOL_OUTCOMES).optional(),
|
|
37124
|
+
statusHash: external_exports.string().nullable().optional()
|
|
37125
|
+
});
|
|
37126
|
+
var toolSequenceEntrySchema = external_exports.object({
|
|
37127
|
+
toolName: external_exports.string(),
|
|
37128
|
+
ms: external_exports.number(),
|
|
37129
|
+
outcome: external_exports.enum(TOOL_OUTCOMES)
|
|
37130
|
+
});
|
|
37131
|
+
var telemetryRowSchema = external_exports.object({
|
|
37132
|
+
day: external_exports.string(),
|
|
37133
|
+
sessionId: external_exports.string(),
|
|
37134
|
+
turnId: external_exports.string().nullable(),
|
|
37135
|
+
toolSequence: external_exports.array(toolSequenceEntrySchema),
|
|
37136
|
+
promptBytes: external_exports.number().nullable(),
|
|
37137
|
+
inputTokens: external_exports.number().nullable(),
|
|
37138
|
+
cachedInputTokens: external_exports.number().nullable(),
|
|
37139
|
+
outputTokens: external_exports.number().nullable(),
|
|
37140
|
+
resultRecordPresent: external_exports.boolean(),
|
|
37141
|
+
// one counter per plumbingKind, so no projected kind is silently uncounted
|
|
37142
|
+
plumbing: external_exports.object({
|
|
37143
|
+
socketCloses: external_exports.number(),
|
|
37144
|
+
readyNotifs: external_exports.number(),
|
|
37145
|
+
schedulerTicks: external_exports.number(),
|
|
37146
|
+
bufferStats: external_exports.number(),
|
|
37147
|
+
rateLimitStatusRecords: external_exports.number(),
|
|
37148
|
+
rateLimitReached: external_exports.boolean()
|
|
37149
|
+
}),
|
|
37150
|
+
projectionFailures: external_exports.number(),
|
|
37151
|
+
gateMarker: external_exports.enum(GATE_MARKERS)
|
|
37152
|
+
});
|
|
37153
|
+
var telemetryBatchSchema = external_exports.object({
|
|
37154
|
+
day: external_exports.string(),
|
|
37155
|
+
bridgeVersion: external_exports.string(),
|
|
37156
|
+
knownCrashCount: external_exports.number(),
|
|
37157
|
+
// pairs still lacking .processed-* after this run completes; a project that never uploads at
|
|
37158
|
+
// all cannot report its own gap this way — silence is not coverage.
|
|
37159
|
+
unprocessedPartitions: external_exports.array(external_exports.object({ projectSlug: external_exports.string(), day: external_exports.string() })),
|
|
37160
|
+
rows: external_exports.array(telemetryRowSchema)
|
|
37161
|
+
});
|
|
37162
|
+
var evidenceStepSchema = external_exports.object({
|
|
37163
|
+
toolName: external_exports.string(),
|
|
37164
|
+
ms: external_exports.number(),
|
|
37165
|
+
outcome: external_exports.enum(TOOL_OUTCOMES),
|
|
37166
|
+
exitCode: external_exports.number().optional(),
|
|
37167
|
+
excerpt: external_exports.string().optional()
|
|
37168
|
+
});
|
|
37169
|
+
var evidenceArtifactSchema = external_exports.object({
|
|
37170
|
+
reportId: external_exports.string(),
|
|
37171
|
+
sessionId: external_exports.string(),
|
|
37172
|
+
turnIds: external_exports.array(external_exports.string()),
|
|
37173
|
+
daysRead: external_exports.array(external_exports.string()),
|
|
37174
|
+
windowPruned: external_exports.boolean(),
|
|
37175
|
+
steps: external_exports.array(evidenceStepSchema),
|
|
37176
|
+
gateMarker: external_exports.enum(GATE_MARKERS)
|
|
37177
|
+
});
|
|
37178
|
+
var extractManifestSchema = external_exports.object({
|
|
37179
|
+
reportId: external_exports.string().optional(),
|
|
37180
|
+
sessionId: external_exports.string().optional(),
|
|
37181
|
+
since: external_exports.string().optional(),
|
|
37182
|
+
until: external_exports.string().optional(),
|
|
37183
|
+
daysRead: external_exports.array(external_exports.string()),
|
|
37184
|
+
recordCount: external_exports.number(),
|
|
37185
|
+
bytesBeforeTruncation: external_exports.number(),
|
|
37186
|
+
truncated: external_exports.boolean(),
|
|
37187
|
+
secretShapesRedacted: external_exports.number(),
|
|
37188
|
+
// null when --out was used and nothing was uploaded
|
|
37189
|
+
deliveredArtifactId: external_exports.string().nullable()
|
|
37190
|
+
});
|
|
37191
|
+
var ingestResultSchema = external_exports.object({
|
|
37192
|
+
accepted: external_exports.number(),
|
|
37193
|
+
unknownCounts: external_exports.record(external_exports.string(), external_exports.object({ count: external_exports.number(), valueLength: external_exports.number() }))
|
|
37194
|
+
});
|
|
37195
|
+
|
|
37077
37196
|
// ../../packages/schemas/dist/memory-budget.js
|
|
37078
37197
|
function evictionKey(item, idx) {
|
|
37079
37198
|
const memClass = item.memoryClass === "historical" ? 0 : 1;
|
|
@@ -39390,11 +39509,21 @@ var ClaudeBridgeEventMapper = class {
|
|
|
39390
39509
|
return [{ type: "rate_limits", snapshot }];
|
|
39391
39510
|
}
|
|
39392
39511
|
handleResult(line) {
|
|
39512
|
+
const tokenUsageEvents = line.usage !== void 0 ? [
|
|
39513
|
+
{
|
|
39514
|
+
type: "token_usage",
|
|
39515
|
+
usage: {
|
|
39516
|
+
inputTokens: line.usage.input_tokens ?? null,
|
|
39517
|
+
cachedInputTokens: line.usage.cache_read_input_tokens ?? null,
|
|
39518
|
+
outputTokens: line.usage.output_tokens ?? null
|
|
39519
|
+
}
|
|
39520
|
+
}
|
|
39521
|
+
] : [];
|
|
39393
39522
|
if (line.is_error === true) {
|
|
39394
39523
|
const content = typeof line.result === "string" && line.result ? line.result : "Unknown Claude error";
|
|
39395
|
-
return [{ type: "error", content }, { type: "turn_completed" }];
|
|
39524
|
+
return [...tokenUsageEvents, { type: "error", content }, { type: "turn_completed" }];
|
|
39396
39525
|
}
|
|
39397
|
-
return [{ type: "result", subtype: "success" }, { type: "turn_completed" }];
|
|
39526
|
+
return [...tokenUsageEvents, { type: "result", subtype: "success" }, { type: "turn_completed" }];
|
|
39398
39527
|
}
|
|
39399
39528
|
contentBlocks(line) {
|
|
39400
39529
|
const content = line.message?.content;
|
|
@@ -39997,18 +40126,18 @@ function createMrrlinClient(config2) {
|
|
|
39997
40126
|
const customFetch = config2.fetch ?? globalThis.fetch;
|
|
39998
40127
|
const baseUrl = config2.baseUrl.replace(/\/$/, "");
|
|
39999
40128
|
const token = config2.token;
|
|
40000
|
-
async function request(
|
|
40129
|
+
async function request(path22, init) {
|
|
40001
40130
|
const method = init?.method ?? "GET";
|
|
40002
40131
|
const headers = new Headers(init?.headers ?? {});
|
|
40003
40132
|
if (token && !headers.has("authorization")) {
|
|
40004
40133
|
headers.set("authorization", `Bearer ${token}`);
|
|
40005
40134
|
}
|
|
40006
|
-
const response = await customFetch(`${baseUrl}${
|
|
40135
|
+
const response = await customFetch(`${baseUrl}${path22}`, { ...init, headers });
|
|
40007
40136
|
if (!response.ok) {
|
|
40008
40137
|
const body = await response.text();
|
|
40009
40138
|
let code = `HTTP_${response.status}`;
|
|
40010
40139
|
let violations = null;
|
|
40011
|
-
let message = `Mrrlin API ${method} ${
|
|
40140
|
+
let message = `Mrrlin API ${method} ${path22} failed: ${response.status}`;
|
|
40012
40141
|
try {
|
|
40013
40142
|
const parsed = JSON.parse(body);
|
|
40014
40143
|
const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
|
|
@@ -40028,7 +40157,7 @@ function createMrrlinClient(config2) {
|
|
|
40028
40157
|
throw new MrrlinApiError({
|
|
40029
40158
|
code,
|
|
40030
40159
|
method,
|
|
40031
|
-
path:
|
|
40160
|
+
path: path22,
|
|
40032
40161
|
responseBody: body,
|
|
40033
40162
|
status: response.status,
|
|
40034
40163
|
violations,
|
|
@@ -40288,16 +40417,16 @@ function createMrrlinClient(config2) {
|
|
|
40288
40417
|
// rejected against the first, MrrlinTask[]-only overload) -- the `any` here is contained to
|
|
40289
40418
|
// this one implementation signature; MrrlinClient's declared overloads keep callers precise.
|
|
40290
40419
|
async listTasks(projectSlug, filters = {}, options) {
|
|
40291
|
-
const
|
|
40292
|
-
const body = await request(
|
|
40420
|
+
const path22 = buildTaskListPath(projectSlug, filters, options?.view);
|
|
40421
|
+
const body = await request(path22);
|
|
40293
40422
|
if (options?.view === "summary") {
|
|
40294
40423
|
return taskSummaryListResponseSchema.parse(body).data;
|
|
40295
40424
|
}
|
|
40296
40425
|
return taskListResponseSchema.parse(body).data;
|
|
40297
40426
|
},
|
|
40298
40427
|
async listTaskSummaries(projectSlug, filters = {}) {
|
|
40299
|
-
const
|
|
40300
|
-
const body = await request(
|
|
40428
|
+
const path22 = buildTaskListPath(projectSlug, filters, "summary");
|
|
40429
|
+
const body = await request(path22);
|
|
40301
40430
|
return taskSummaryListResponseSchema.parse(body).data;
|
|
40302
40431
|
},
|
|
40303
40432
|
async listTaxonomy(projectSlug) {
|
|
@@ -40305,22 +40434,22 @@ function createMrrlinClient(config2) {
|
|
|
40305
40434
|
return taxonomyListResponseSchema.parse(body).data;
|
|
40306
40435
|
},
|
|
40307
40436
|
async listWikiPages(projectSlug, filters = {}) {
|
|
40308
|
-
const
|
|
40437
|
+
const path22 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
|
|
40309
40438
|
folder: filters.folder,
|
|
40310
40439
|
q: filters.q,
|
|
40311
40440
|
taskId: filters.taskId
|
|
40312
40441
|
});
|
|
40313
|
-
const body = await request(
|
|
40442
|
+
const body = await request(path22);
|
|
40314
40443
|
return wikiPageListResponseSchema.parse(body).data;
|
|
40315
40444
|
},
|
|
40316
40445
|
async searchWikiPages(projectSlug, query) {
|
|
40317
|
-
const
|
|
40446
|
+
const path22 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
|
|
40318
40447
|
folder: query.folder,
|
|
40319
40448
|
limit: query.limit === void 0 ? void 0 : String(query.limit),
|
|
40320
40449
|
pathPrefix: query.pathPrefix,
|
|
40321
40450
|
q: query.q
|
|
40322
40451
|
});
|
|
40323
|
-
const body = await request(
|
|
40452
|
+
const body = await request(path22);
|
|
40324
40453
|
return wikiPageSearchResponseSchema.parse(body).data;
|
|
40325
40454
|
},
|
|
40326
40455
|
async updatePlan(projectSlug, planId, patch) {
|
|
@@ -40710,6 +40839,14 @@ function createMrrlinClient(config2) {
|
|
|
40710
40839
|
});
|
|
40711
40840
|
return executionArtifactResponseSchema.parse(body).data;
|
|
40712
40841
|
},
|
|
40842
|
+
async postTelemetry(projectSlug, batch) {
|
|
40843
|
+
const body = await request(`${projectPath(projectSlug)}/telemetry`, {
|
|
40844
|
+
body: JSON.stringify(batch),
|
|
40845
|
+
headers: { "content-type": "application/json" },
|
|
40846
|
+
method: "POST"
|
|
40847
|
+
});
|
|
40848
|
+
return ingestResultSchema.parse(body);
|
|
40849
|
+
},
|
|
40713
40850
|
async createArtifactFile(projectSlug, input) {
|
|
40714
40851
|
const body = await request(`${projectPath(projectSlug)}/artifact-files`, {
|
|
40715
40852
|
body: JSON.stringify(input),
|
|
@@ -41179,7 +41316,7 @@ function sha256(buf) {
|
|
|
41179
41316
|
function startSelfUpdate(deps) {
|
|
41180
41317
|
const log = deps.log ?? (() => {
|
|
41181
41318
|
});
|
|
41182
|
-
const
|
|
41319
|
+
const readFile9 = deps.readFileSyncImpl ?? ((p) => (0, import_node_fs2.readFileSync)(p));
|
|
41183
41320
|
const setIntervalFn = deps.setIntervalImpl ?? setInterval;
|
|
41184
41321
|
const clearIntervalFn = deps.clearIntervalImpl ?? clearInterval;
|
|
41185
41322
|
const intervalMs = deps.intervalMs ?? readIntervalEnv("MRRLIN_DIRECTOR_BRIDGE_SELF_UPDATE_INTERVAL_MS", DEFAULT_INTERVAL_MS);
|
|
@@ -41235,7 +41372,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
41235
41372
|
}
|
|
41236
41373
|
let startupBinSha = null;
|
|
41237
41374
|
try {
|
|
41238
|
-
startupBinSha = sha256(
|
|
41375
|
+
startupBinSha = sha256(readFile9(deps.binPath));
|
|
41239
41376
|
} catch (e) {
|
|
41240
41377
|
log("warn", "bridge.self_update.startup_hash_read_failed", {
|
|
41241
41378
|
err: String(e?.message ?? e)
|
|
@@ -41314,14 +41451,14 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
41314
41451
|
try {
|
|
41315
41452
|
if (!startupBinSha) {
|
|
41316
41453
|
try {
|
|
41317
|
-
startupBinSha = sha256(
|
|
41454
|
+
startupBinSha = sha256(readFile9(deps.binPath));
|
|
41318
41455
|
} catch {
|
|
41319
41456
|
return;
|
|
41320
41457
|
}
|
|
41321
41458
|
}
|
|
41322
41459
|
let currentBinSha;
|
|
41323
41460
|
try {
|
|
41324
|
-
currentBinSha = sha256(
|
|
41461
|
+
currentBinSha = sha256(readFile9(deps.binPath));
|
|
41325
41462
|
} catch {
|
|
41326
41463
|
return;
|
|
41327
41464
|
}
|
|
@@ -41400,7 +41537,7 @@ Do NOT derail the current task - if the operator has an in-flight question, answ
|
|
|
41400
41537
|
}
|
|
41401
41538
|
|
|
41402
41539
|
// src/_generated/version.ts
|
|
41403
|
-
var PKG_VERSION = "0.4.
|
|
41540
|
+
var PKG_VERSION = "0.4.7";
|
|
41404
41541
|
|
|
41405
41542
|
// src/api-base-url-migrate.ts
|
|
41406
41543
|
var import_node_fs3 = __toESM(require("node:fs"), 1);
|
|
@@ -41711,6 +41848,7 @@ var BridgeHealthTracker = class {
|
|
|
41711
41848
|
now;
|
|
41712
41849
|
processExit;
|
|
41713
41850
|
logger;
|
|
41851
|
+
hasLiveTurn;
|
|
41714
41852
|
// Initialized to construction time, NOT 0/undefined: a freshly (re)started process — including
|
|
41715
41853
|
// one that just restarted BECAUSE this breaker tripped — must not treat its own startup instant
|
|
41716
41854
|
// as "ages ago that nothing succeeded." Without this, the very first tracked failure after any
|
|
@@ -41718,14 +41856,21 @@ var BridgeHealthTracker = class {
|
|
|
41718
41856
|
// seconds and inverting this mechanism into the outage it exists to prevent.
|
|
41719
41857
|
lastSuccessAt;
|
|
41720
41858
|
disabled = false;
|
|
41721
|
-
knownCrashCount
|
|
41859
|
+
// Renamed from knownCrashCount to _knownCrashCount (task 9.4): a class can't have both a
|
|
41860
|
+
// private field and a public method of the same name, and 9.4 asks for the public getter to be
|
|
41861
|
+
// named knownCrashCount().
|
|
41862
|
+
_knownCrashCount = null;
|
|
41722
41863
|
lastErrorByOperation = /* @__PURE__ */ new Map();
|
|
41864
|
+
// Rate-limits the "deferring crash-exit" log to once per 60s so a tight sweep-retry loop
|
|
41865
|
+
// while a turn stays live doesn't spam it -- the defer itself still applies every call.
|
|
41866
|
+
lastLiveTurnDeferLogAt = null;
|
|
41723
41867
|
constructor(opts) {
|
|
41724
41868
|
this.stateDir = opts.stateDir;
|
|
41725
41869
|
this.stuckMs = opts.stuckMs ?? readStuckMsFromEnv() ?? DEFAULT_STUCK_MS;
|
|
41726
41870
|
this.now = opts.now ?? Date.now;
|
|
41727
41871
|
this.processExit = opts.processExit ?? ((code) => process.exit(code));
|
|
41728
41872
|
this.logger = opts.logger ?? defaultLogger;
|
|
41873
|
+
this.hasLiveTurn = opts.hasLiveTurn ?? (() => false);
|
|
41729
41874
|
this.lastSuccessAt = this.now();
|
|
41730
41875
|
}
|
|
41731
41876
|
/** Wraps a tracked operation: applies the hard timeout, records the outcome, and re-throws or
|
|
@@ -41742,13 +41887,18 @@ var BridgeHealthTracker = class {
|
|
|
41742
41887
|
}
|
|
41743
41888
|
async recordSuccess() {
|
|
41744
41889
|
this.lastSuccessAt = this.now();
|
|
41745
|
-
if (this.
|
|
41890
|
+
if (this._knownCrashCount === null) {
|
|
41746
41891
|
await this.reconcileCrashCountOnFirstSuccess();
|
|
41747
41892
|
}
|
|
41748
41893
|
}
|
|
41749
41894
|
recordFailure(id, error51) {
|
|
41750
41895
|
this.lastErrorByOperation.set(id, error51 instanceof Error ? error51.message : String(error51));
|
|
41751
41896
|
}
|
|
41897
|
+
/** `null` until the first success reconciles it (see `recordSuccess`) — read by
|
|
41898
|
+
* `daily-uploader.ts`, which stamps the captured value on every `TelemetryBatch` in a run. */
|
|
41899
|
+
knownCrashCount() {
|
|
41900
|
+
return this._knownCrashCount;
|
|
41901
|
+
}
|
|
41752
41902
|
/** True when no tracked operation has succeeded within `stuckMs`. */
|
|
41753
41903
|
isStuck() {
|
|
41754
41904
|
return this.now() - this.lastSuccessAt >= this.stuckMs;
|
|
@@ -41758,6 +41908,23 @@ var BridgeHealthTracker = class {
|
|
|
41758
41908
|
async maybeCrash() {
|
|
41759
41909
|
if (this.disabled) return;
|
|
41760
41910
|
if (!this.isStuck()) return;
|
|
41911
|
+
let hasLiveTurn = false;
|
|
41912
|
+
try {
|
|
41913
|
+
hasLiveTurn = this.hasLiveTurn();
|
|
41914
|
+
} catch (error51) {
|
|
41915
|
+
const message = error51 instanceof Error ? error51.message : String(error51);
|
|
41916
|
+
this.logger.critical(`bridge health: hasLiveTurn() threw, treating as no live turn: ${message}`);
|
|
41917
|
+
}
|
|
41918
|
+
if (hasLiveTurn) {
|
|
41919
|
+
const now = this.now();
|
|
41920
|
+
if (this.lastLiveTurnDeferLogAt === null || now - this.lastLiveTurnDeferLogAt >= 6e4) {
|
|
41921
|
+
this.logger.critical(
|
|
41922
|
+
"bridge health: stuck but a Director turn is still active/resumable \u2014 deferring crash-exit"
|
|
41923
|
+
);
|
|
41924
|
+
this.lastLiveTurnDeferLogAt = now;
|
|
41925
|
+
}
|
|
41926
|
+
return;
|
|
41927
|
+
}
|
|
41761
41928
|
const decision = await this.decideExitOrDisable();
|
|
41762
41929
|
if (decision.exit) {
|
|
41763
41930
|
this.logger.critical(
|
|
@@ -41784,10 +41951,10 @@ var BridgeHealthTracker = class {
|
|
|
41784
41951
|
}
|
|
41785
41952
|
async reconcileCrashCountOnFirstSuccess() {
|
|
41786
41953
|
const sentinel = await readCrashSentinel(this.stateDir, this.now);
|
|
41787
|
-
this.
|
|
41954
|
+
this._knownCrashCount = sentinel.crashCount;
|
|
41788
41955
|
if (sentinel.crashCount > 0) {
|
|
41789
41956
|
await writeCrashSentinel(this.stateDir, { ...sentinel, crashCount: 0 });
|
|
41790
|
-
this.
|
|
41957
|
+
this._knownCrashCount = 0;
|
|
41791
41958
|
}
|
|
41792
41959
|
}
|
|
41793
41960
|
formatLastErrors() {
|
|
@@ -41930,386 +42097,272 @@ function startSchedulerTickLoop(deps) {
|
|
|
41930
42097
|
};
|
|
41931
42098
|
}
|
|
41932
42099
|
|
|
41933
|
-
// src/
|
|
41934
|
-
|
|
41935
|
-
|
|
41936
|
-
|
|
41937
|
-
|
|
41938
|
-
|
|
41939
|
-
|
|
41940
|
-
|
|
41941
|
-
}
|
|
41942
|
-
|
|
41943
|
-
}
|
|
41944
|
-
|
|
41945
|
-
if (!opts.available) {
|
|
41946
|
-
return {
|
|
41947
|
-
collected_at: opts.collectedAt,
|
|
41948
|
-
status: "unavailable",
|
|
41949
|
-
agents: [],
|
|
41950
|
-
totals: { calls: 0, tokens_in: 0, tokens_out: 0 },
|
|
41951
|
-
estimated_savings_usd: 0
|
|
41952
|
-
};
|
|
41953
|
-
}
|
|
41954
|
-
const costPer1M = opts.paidCostPer1MTokens ?? 3;
|
|
41955
|
-
const agents = statusRows.map((row) => {
|
|
41956
|
-
const agentStats = stats.by_agent[row.id];
|
|
41957
|
-
const count2 = agentStats?.count ?? 0;
|
|
41958
|
-
const tokensIn = agentStats?.tokens_in ?? 0;
|
|
41959
|
-
const tokensOut = agentStats?.tokens_out ?? 0;
|
|
41960
|
-
let successRate = 0;
|
|
41961
|
-
if (count2 > 0) {
|
|
41962
|
-
const successOutcomes = agentStats?.outcomes.success ?? 0;
|
|
41963
|
-
successRate = Number((successOutcomes / count2 * 100).toFixed(2)) / 100;
|
|
42100
|
+
// src/retention/pruner.ts
|
|
42101
|
+
var import_promises4 = require("node:fs/promises");
|
|
42102
|
+
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
42103
|
+
async function prune(stateDir, bounds) {
|
|
42104
|
+
const logsDir = import_node_path9.default.join(stateDir, "logs");
|
|
42105
|
+
let entries;
|
|
42106
|
+
try {
|
|
42107
|
+
entries = await (0, import_promises4.readdir)(logsDir);
|
|
42108
|
+
} catch (err) {
|
|
42109
|
+
if (err?.code === "ENOENT") {
|
|
42110
|
+
await emitPruneLog(stateDir, [], {}, 0, null);
|
|
42111
|
+
return { daysRemoved: [], reasonByDay: {}, bytesRemoved: 0, oldestDayRemaining: null };
|
|
41964
42112
|
}
|
|
41965
|
-
|
|
41966
|
-
id: row.id,
|
|
41967
|
-
provider: row.provider,
|
|
41968
|
-
tier: row.tier,
|
|
41969
|
-
tags: row.tags,
|
|
41970
|
-
state: row.state ?? "unknown",
|
|
41971
|
-
calls: count2,
|
|
41972
|
-
tokens_in: tokensIn,
|
|
41973
|
-
tokens_out: tokensOut,
|
|
41974
|
-
success_rate: successRate,
|
|
41975
|
-
last_used_at: normalizeLastUsedAt(row.last_used_at)
|
|
41976
|
-
};
|
|
41977
|
-
});
|
|
41978
|
-
let totalCalls = 0;
|
|
41979
|
-
let totalTokensIn = 0;
|
|
41980
|
-
let totalTokensOut = 0;
|
|
41981
|
-
for (const entry of Object.values(stats.by_agent)) {
|
|
41982
|
-
totalCalls += entry.count;
|
|
41983
|
-
totalTokensIn += entry.tokens_in;
|
|
41984
|
-
totalTokensOut += entry.tokens_out;
|
|
42113
|
+
throw err;
|
|
41985
42114
|
}
|
|
41986
|
-
|
|
41987
|
-
|
|
41988
|
-
|
|
41989
|
-
|
|
41990
|
-
|
|
41991
|
-
|
|
42115
|
+
const bridgeRe = /^bridge-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
42116
|
+
const files = [];
|
|
42117
|
+
for (const entry of entries) {
|
|
42118
|
+
const m = bridgeRe.exec(entry);
|
|
42119
|
+
if (!m?.[1]) continue;
|
|
42120
|
+
const fullPath = import_node_path9.default.join(logsDir, entry);
|
|
42121
|
+
const s = await (0, import_promises4.stat)(fullPath);
|
|
42122
|
+
files.push({ day: m[1], size: s.size, fullPath });
|
|
42123
|
+
}
|
|
42124
|
+
files.sort((a, b) => a.day < b.day ? -1 : a.day > b.day ? 1 : 0);
|
|
42125
|
+
const daysRemoved = [];
|
|
42126
|
+
const reasonByDay = {};
|
|
42127
|
+
let bytesRemoved = 0;
|
|
42128
|
+
async function isDaySafeToDelete(day) {
|
|
42129
|
+
const telemetryDir = import_node_path9.default.join(stateDir, "telemetry");
|
|
42130
|
+
let telemetryEntries;
|
|
42131
|
+
try {
|
|
42132
|
+
telemetryEntries = await (0, import_promises4.readdir)(telemetryDir);
|
|
42133
|
+
} catch (err) {
|
|
42134
|
+
if (err?.code === "ENOENT") return true;
|
|
42135
|
+
throw err;
|
|
42136
|
+
}
|
|
42137
|
+
const rowRe = new RegExp(`^rows-(.+)-${day}\\.jsonl$`);
|
|
42138
|
+
const projectSlugs = [];
|
|
42139
|
+
for (const entry of telemetryEntries) {
|
|
42140
|
+
const m = rowRe.exec(entry);
|
|
42141
|
+
if (m?.[1]) projectSlugs.push(m[1]);
|
|
42142
|
+
}
|
|
42143
|
+
if (projectSlugs.length === 0) return true;
|
|
42144
|
+
for (const slug of projectSlugs) {
|
|
42145
|
+
const markerPath = import_node_path9.default.join(telemetryDir, `.processed-${slug}-${day}`);
|
|
42146
|
+
try {
|
|
42147
|
+
await (0, import_promises4.stat)(markerPath);
|
|
42148
|
+
} catch (err) {
|
|
42149
|
+
if (err?.code === "ENOENT") return false;
|
|
42150
|
+
throw err;
|
|
41992
42151
|
}
|
|
41993
42152
|
}
|
|
42153
|
+
return true;
|
|
41994
42154
|
}
|
|
41995
|
-
const
|
|
41996
|
-
|
|
41997
|
-
|
|
41998
|
-
|
|
41999
|
-
|
|
42000
|
-
|
|
42001
|
-
|
|
42002
|
-
|
|
42003
|
-
|
|
42004
|
-
},
|
|
42005
|
-
estimated_savings_usd: estimatedSavings
|
|
42006
|
-
};
|
|
42007
|
-
}
|
|
42008
|
-
|
|
42009
|
-
// src/agent-pool-collector.ts
|
|
42010
|
-
async function collectAgentPoolSnapshot(deps) {
|
|
42011
|
-
let statusRows;
|
|
42012
|
-
let stats;
|
|
42013
|
-
try {
|
|
42014
|
-
const statusResult = await deps.runCli(["status", "--json"]);
|
|
42015
|
-
if (statusResult.code !== 0) throw new Error("non-zero exit on status");
|
|
42016
|
-
let statusParsed;
|
|
42017
|
-
try {
|
|
42018
|
-
statusParsed = JSON.parse(statusResult.stdout);
|
|
42019
|
-
} catch {
|
|
42020
|
-
throw new Error("invalid status json");
|
|
42155
|
+
const budgetBytes = bounds.budgetMb * 1024 * 1024;
|
|
42156
|
+
let totalSize2 = files.reduce((sum, f) => sum + f.size, 0);
|
|
42157
|
+
let i = 0;
|
|
42158
|
+
while (totalSize2 > budgetBytes && i < files.length) {
|
|
42159
|
+
const candidate = files[i];
|
|
42160
|
+
if (!candidate) break;
|
|
42161
|
+
if (!await isDaySafeToDelete(candidate.day)) {
|
|
42162
|
+
i += 1;
|
|
42163
|
+
continue;
|
|
42021
42164
|
}
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42165
|
+
await (0, import_promises4.unlink)(candidate.fullPath);
|
|
42166
|
+
daysRemoved.push(candidate.day);
|
|
42167
|
+
reasonByDay[candidate.day] = "size";
|
|
42168
|
+
bytesRemoved += candidate.size;
|
|
42169
|
+
totalSize2 -= candidate.size;
|
|
42170
|
+
files.splice(i, 1);
|
|
42171
|
+
}
|
|
42172
|
+
const now = Date.now();
|
|
42173
|
+
const msPerDay = 864e5;
|
|
42174
|
+
const stillRemaining = [];
|
|
42175
|
+
for (const info of files) {
|
|
42176
|
+
const fileDate = /* @__PURE__ */ new Date(`${info.day}T00:00:00Z`);
|
|
42177
|
+
const ageInDays = (now - fileDate.getTime()) / msPerDay;
|
|
42178
|
+
if (ageInDays > bounds.ageDays && await isDaySafeToDelete(info.day)) {
|
|
42179
|
+
await (0, import_promises4.unlink)(info.fullPath);
|
|
42180
|
+
daysRemoved.push(info.day);
|
|
42181
|
+
reasonByDay[info.day] = "age";
|
|
42182
|
+
bytesRemoved += info.size;
|
|
42183
|
+
continue;
|
|
42184
|
+
}
|
|
42185
|
+
stillRemaining.push(info);
|
|
42186
|
+
}
|
|
42187
|
+
const oldestDayRemaining = stillRemaining.length > 0 ? stillRemaining[0]?.day ?? null : null;
|
|
42188
|
+
await emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining);
|
|
42189
|
+
if (daysRemoved.length > 0) {
|
|
42190
|
+
const sessionsPath = import_node_path9.default.join(logsDir, ".sessions.json");
|
|
42191
|
+
let sessionsObj = {};
|
|
42192
|
+
let fileExists = true;
|
|
42026
42193
|
try {
|
|
42027
|
-
|
|
42028
|
-
} catch {
|
|
42029
|
-
|
|
42194
|
+
sessionsObj = JSON.parse(await (0, import_promises4.readFile)(sessionsPath, "utf8"));
|
|
42195
|
+
} catch (err) {
|
|
42196
|
+
if (err?.code === "ENOENT") {
|
|
42197
|
+
fileExists = false;
|
|
42198
|
+
} else {
|
|
42199
|
+
sessionsObj = {};
|
|
42200
|
+
}
|
|
42201
|
+
}
|
|
42202
|
+
if (fileExists) {
|
|
42203
|
+
for (const day of daysRemoved) delete sessionsObj[day];
|
|
42204
|
+
const tmpPath = `${sessionsPath}.tmp`;
|
|
42205
|
+
await (0, import_promises4.writeFile)(tmpPath, JSON.stringify(sessionsObj));
|
|
42206
|
+
await (0, import_promises4.rename)(tmpPath, sessionsPath);
|
|
42030
42207
|
}
|
|
42031
|
-
} catch {
|
|
42032
|
-
return buildAgentPoolSnapshot(
|
|
42033
|
-
[],
|
|
42034
|
-
{},
|
|
42035
|
-
{ collectedAt: deps.now(), available: false }
|
|
42036
|
-
);
|
|
42037
42208
|
}
|
|
42038
|
-
return
|
|
42039
|
-
|
|
42040
|
-
|
|
42041
|
-
|
|
42042
|
-
);
|
|
42209
|
+
return { daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining };
|
|
42210
|
+
}
|
|
42211
|
+
async function emitPruneLog(stateDir, daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining) {
|
|
42212
|
+
const logsDir = import_node_path9.default.join(stateDir, "logs");
|
|
42213
|
+
const logPath = import_node_path9.default.join(logsDir, ".pruned.jsonl");
|
|
42214
|
+
await (0, import_promises4.mkdir)(logsDir, { recursive: true });
|
|
42215
|
+
const record2 = { ts: Date.now(), dir: "logs", daysRemoved, reasonByDay, bytesRemoved, oldestDayRemaining };
|
|
42216
|
+
await (0, import_promises4.appendFile)(logPath, `${JSON.stringify(record2)}
|
|
42217
|
+
`);
|
|
42043
42218
|
}
|
|
42044
42219
|
|
|
42045
|
-
// src/
|
|
42046
|
-
var
|
|
42047
|
-
|
|
42048
|
-
|
|
42049
|
-
|
|
42050
|
-
|
|
42220
|
+
// src/telemetry/turn-aggregator.ts
|
|
42221
|
+
var import_promises5 = require("node:fs/promises");
|
|
42222
|
+
var import_node_path10 = require("node:path");
|
|
42223
|
+
var BRIDGE_FILE_RE = /^bridge-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
42224
|
+
var PLUMBING_COUNTER_KEY = {
|
|
42225
|
+
socket_close: "socketCloses",
|
|
42226
|
+
ready: "readyNotifs",
|
|
42227
|
+
scheduler_tick: "schedulerTicks",
|
|
42228
|
+
buffer_stats: "bufferStats",
|
|
42229
|
+
rate_limit_status: "rateLimitStatusRecords"
|
|
42230
|
+
};
|
|
42231
|
+
async function foldClosedDays(stateDir, today) {
|
|
42232
|
+
const logsDir = (0, import_node_path10.join)(stateDir, "logs");
|
|
42233
|
+
let entries;
|
|
42051
42234
|
try {
|
|
42052
|
-
|
|
42053
|
-
command: "node",
|
|
42054
|
-
prefixArgs: [resolvePackageBin("@mrrlin-dev/external-agents", "external-agents")]
|
|
42055
|
-
};
|
|
42235
|
+
entries = await (0, import_promises5.readdir)(logsDir);
|
|
42056
42236
|
} catch {
|
|
42057
|
-
return
|
|
42058
|
-
}
|
|
42059
|
-
}
|
|
42060
|
-
|
|
42061
|
-
// src/external-agents-spawn.ts
|
|
42062
|
-
function runExternalAgentsCli(args, opts) {
|
|
42063
|
-
let command;
|
|
42064
|
-
let prefixArgs;
|
|
42065
|
-
let source;
|
|
42066
|
-
let triedPath;
|
|
42067
|
-
if (opts.envCliPath && opts.envCliPath.trim()) {
|
|
42068
|
-
command = "node";
|
|
42069
|
-
prefixArgs = [opts.envCliPath];
|
|
42070
|
-
source = "env";
|
|
42071
|
-
triedPath = opts.envCliPath;
|
|
42072
|
-
} else {
|
|
42073
|
-
({ command, prefixArgs } = resolveExternalAgentsCliInvocation());
|
|
42074
|
-
source = command === "node" && prefixArgs.length === 1 ? "bundled" : "path";
|
|
42075
|
-
triedPath = source === "bundled" ? prefixArgs[0] ?? "" : "external-agents (PATH)";
|
|
42237
|
+
return;
|
|
42076
42238
|
}
|
|
42077
|
-
const
|
|
42078
|
-
|
|
42079
|
-
|
|
42080
|
-
|
|
42081
|
-
|
|
42082
|
-
|
|
42083
|
-
|
|
42084
|
-
const
|
|
42085
|
-
|
|
42086
|
-
|
|
42087
|
-
|
|
42088
|
-
}
|
|
42089
|
-
};
|
|
42090
|
-
let spawned;
|
|
42091
|
-
try {
|
|
42092
|
-
spawned = (0, import_node_child_process8.spawn)(command, [...prefixArgs, ...args], { stdio: stdioConfig });
|
|
42093
|
-
} catch {
|
|
42094
|
-
done(1);
|
|
42095
|
-
return;
|
|
42096
|
-
}
|
|
42097
|
-
const child = spawned;
|
|
42098
|
-
let sigkillTimer = null;
|
|
42099
|
-
let budgetTimer = null;
|
|
42100
|
-
if (useStdin && child.stdin) {
|
|
42101
|
-
child.stdin.on("error", () => {
|
|
42102
|
-
});
|
|
42103
|
-
child.stdin.write(opts.stdinValue);
|
|
42104
|
-
child.stdin.end();
|
|
42105
|
-
}
|
|
42106
|
-
child.stdout?.on("data", (d) => {
|
|
42107
|
-
stdout += d.toString();
|
|
42108
|
-
if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
|
|
42109
|
-
});
|
|
42110
|
-
child.stderr?.on("data", (d) => {
|
|
42111
|
-
stderr += d.toString();
|
|
42112
|
-
if (stderr.length > 2e5) stderr = stderr.slice(-2e5);
|
|
42113
|
-
});
|
|
42114
|
-
budgetTimer = setTimeout(() => {
|
|
42115
|
-
budgetTimer = null;
|
|
42116
|
-
timedOut = true;
|
|
42239
|
+
for (const entry of entries) {
|
|
42240
|
+
const m = BRIDGE_FILE_RE.exec(entry);
|
|
42241
|
+
if (!m) continue;
|
|
42242
|
+
const day = m[1];
|
|
42243
|
+
if (day === today) continue;
|
|
42244
|
+
const raw = await (0, import_promises5.readFile)((0, import_node_path10.join)(logsDir, entry), "utf8");
|
|
42245
|
+
const groups = /* @__PURE__ */ new Map();
|
|
42246
|
+
for (const line of raw.split("\n")) {
|
|
42247
|
+
const trimmed = line.trim();
|
|
42248
|
+
if (!trimmed) continue;
|
|
42249
|
+
let rec;
|
|
42117
42250
|
try {
|
|
42118
|
-
|
|
42251
|
+
rec = JSON.parse(trimmed);
|
|
42119
42252
|
} catch {
|
|
42253
|
+
continue;
|
|
42120
42254
|
}
|
|
42121
|
-
|
|
42122
|
-
|
|
42123
|
-
|
|
42124
|
-
|
|
42125
|
-
|
|
42255
|
+
const sessionId = typeof rec.sessionId === "string" ? rec.sessionId : null;
|
|
42256
|
+
const turnId = rec.projection?.turnId ?? null;
|
|
42257
|
+
const key = `${sessionId === null ? 0 : 1}:${sessionId}:${turnId === null ? 0 : 1}:${turnId}`;
|
|
42258
|
+
let group = groups.get(key);
|
|
42259
|
+
if (!group) {
|
|
42260
|
+
group = { sessionId, turnId, records: [], projectionFailures: 0 };
|
|
42261
|
+
groups.set(key, group);
|
|
42262
|
+
}
|
|
42263
|
+
group.records.push(rec);
|
|
42264
|
+
if (rec.projectionFailed === true) group.projectionFailures += 1;
|
|
42265
|
+
}
|
|
42266
|
+
const rowsByProject = /* @__PURE__ */ new Map();
|
|
42267
|
+
for (const group of groups.values()) {
|
|
42268
|
+
if (group.sessionId === null) continue;
|
|
42269
|
+
const records = [...group.records].sort((a, b) => {
|
|
42270
|
+
const aSeq = a.projection?.seq;
|
|
42271
|
+
const bSeq = b.projection?.seq;
|
|
42272
|
+
if (aSeq === void 0 && bSeq === void 0) return 0;
|
|
42273
|
+
if (aSeq === void 0) return 1;
|
|
42274
|
+
if (bSeq === void 0) return -1;
|
|
42275
|
+
return aSeq - bSeq;
|
|
42276
|
+
});
|
|
42277
|
+
let projectSlug;
|
|
42278
|
+
for (const rec of records) {
|
|
42279
|
+
const slug = rec.projection?.projectSlug;
|
|
42280
|
+
if (slug) {
|
|
42281
|
+
projectSlug = slug;
|
|
42282
|
+
break;
|
|
42126
42283
|
}
|
|
42127
|
-
}, 2e3);
|
|
42128
|
-
sigkillTimer.unref?.();
|
|
42129
|
-
done(1);
|
|
42130
|
-
}, opts.budgetMs);
|
|
42131
|
-
budgetTimer.unref?.();
|
|
42132
|
-
child.on("error", () => {
|
|
42133
|
-
if (budgetTimer) {
|
|
42134
|
-
clearTimeout(budgetTimer);
|
|
42135
|
-
budgetTimer = null;
|
|
42136
|
-
}
|
|
42137
|
-
if (sigkillTimer) {
|
|
42138
|
-
clearTimeout(sigkillTimer);
|
|
42139
|
-
sigkillTimer = null;
|
|
42140
|
-
}
|
|
42141
|
-
done(1);
|
|
42142
|
-
});
|
|
42143
|
-
child.on("close", (code) => {
|
|
42144
|
-
if (budgetTimer) {
|
|
42145
|
-
clearTimeout(budgetTimer);
|
|
42146
|
-
budgetTimer = null;
|
|
42147
42284
|
}
|
|
42148
|
-
|
|
42149
|
-
|
|
42150
|
-
|
|
42285
|
+
projectSlug ??= "_unattributed";
|
|
42286
|
+
const toolResults = records.filter((r) => r.projection?.kind === "tool_result");
|
|
42287
|
+
const toolSequence = [];
|
|
42288
|
+
for (const rec of records) {
|
|
42289
|
+
if (rec.projection?.kind !== "tool_use") continue;
|
|
42290
|
+
const toolId = rec.projection.toolId;
|
|
42291
|
+
const paired = toolResults.find((r) => r.projection?.toolId === toolId);
|
|
42292
|
+
toolSequence.push({
|
|
42293
|
+
toolName: rec.projection.toolName ?? "",
|
|
42294
|
+
ms: rec.projection.ms ?? 0,
|
|
42295
|
+
outcome: paired?.projection?.outcome ?? "unknown"
|
|
42296
|
+
});
|
|
42151
42297
|
}
|
|
42152
|
-
|
|
42153
|
-
|
|
42154
|
-
|
|
42155
|
-
|
|
42156
|
-
|
|
42157
|
-
|
|
42158
|
-
|
|
42159
|
-
|
|
42160
|
-
|
|
42161
|
-
|
|
42162
|
-
|
|
42163
|
-
|
|
42164
|
-
|
|
42165
|
-
|
|
42166
|
-
|
|
42167
|
-
|
|
42168
|
-
|
|
42169
|
-
|
|
42170
|
-
|
|
42171
|
-
|
|
42172
|
-
|
|
42173
|
-
|
|
42174
|
-
|
|
42175
|
-
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
|
|
42179
|
-
|
|
42180
|
-
|
|
42181
|
-
|
|
42182
|
-
|
|
42183
|
-
|
|
42184
|
-
|
|
42185
|
-
|
|
42186
|
-
|
|
42187
|
-
|
|
42188
|
-
|
|
42189
|
-
|
|
42190
|
-
|
|
42191
|
-
|
|
42192
|
-
|
|
42193
|
-
|
|
42194
|
-
|
|
42195
|
-
|
|
42196
|
-
|
|
42197
|
-
|
|
42198
|
-
|
|
42298
|
+
const lifecycleRecs = records.filter((r) => r.projection?.kind === "turn_lifecycle");
|
|
42299
|
+
const resultRecordPresent = lifecycleRecs.length > 0;
|
|
42300
|
+
let promptBytes = null;
|
|
42301
|
+
let inputTokens = null;
|
|
42302
|
+
let cachedInputTokens = null;
|
|
42303
|
+
let outputTokens = null;
|
|
42304
|
+
const firstLifecycle = lifecycleRecs[0]?.projection;
|
|
42305
|
+
if (firstLifecycle?.lifecycle === "completed") {
|
|
42306
|
+
promptBytes = firstLifecycle.promptBytes ?? null;
|
|
42307
|
+
inputTokens = firstLifecycle.inputTokens ?? null;
|
|
42308
|
+
cachedInputTokens = firstLifecycle.cachedInputTokens ?? null;
|
|
42309
|
+
outputTokens = firstLifecycle.outputTokens ?? null;
|
|
42310
|
+
}
|
|
42311
|
+
const plumbing = {
|
|
42312
|
+
socketCloses: 0,
|
|
42313
|
+
readyNotifs: 0,
|
|
42314
|
+
schedulerTicks: 0,
|
|
42315
|
+
bufferStats: 0,
|
|
42316
|
+
rateLimitStatusRecords: 0,
|
|
42317
|
+
rateLimitReached: false
|
|
42318
|
+
};
|
|
42319
|
+
for (const rec of records) {
|
|
42320
|
+
const proj = rec.projection;
|
|
42321
|
+
if (!proj || proj.kind !== "plumbing" || !proj.plumbingKind) continue;
|
|
42322
|
+
const counterKey = PLUMBING_COUNTER_KEY[proj.plumbingKind];
|
|
42323
|
+
if (!counterKey) continue;
|
|
42324
|
+
plumbing[counterKey] += 1;
|
|
42325
|
+
if (proj.plumbingKind === "rate_limit_status" && proj.rateLimitReached === true) {
|
|
42326
|
+
plumbing.rateLimitReached = true;
|
|
42327
|
+
}
|
|
42328
|
+
}
|
|
42329
|
+
const row = {
|
|
42330
|
+
day,
|
|
42331
|
+
sessionId: group.sessionId,
|
|
42332
|
+
turnId: group.turnId,
|
|
42333
|
+
toolSequence,
|
|
42334
|
+
promptBytes,
|
|
42335
|
+
inputTokens,
|
|
42336
|
+
cachedInputTokens,
|
|
42337
|
+
outputTokens,
|
|
42338
|
+
resultRecordPresent,
|
|
42339
|
+
plumbing,
|
|
42340
|
+
projectionFailures: group.projectionFailures
|
|
42341
|
+
};
|
|
42342
|
+
const rows = rowsByProject.get(projectSlug) ?? [];
|
|
42343
|
+
rows.push(row);
|
|
42344
|
+
rowsByProject.set(projectSlug, rows);
|
|
42199
42345
|
}
|
|
42200
|
-
|
|
42201
|
-
|
|
42202
|
-
|
|
42203
|
-
|
|
42204
|
-
|
|
42205
|
-
|
|
42206
|
-
|
|
42207
|
-
|
|
42208
|
-
}
|
|
42209
|
-
function defaultRunnerFor(command) {
|
|
42210
|
-
return (args) => {
|
|
42211
|
-
const r = (0, import_node_child_process9.spawnSync)(command, args, { encoding: "utf8", timeout: 8e3 });
|
|
42212
|
-
return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
42213
|
-
};
|
|
42214
|
-
}
|
|
42215
|
-
async function runProviderReadinessCycle(deps) {
|
|
42216
|
-
try {
|
|
42217
|
-
const verify = deps.verify ?? verifyProviderReadiness;
|
|
42218
|
-
const runnerFor = deps.runnerFor ?? defaultRunnerFor;
|
|
42219
|
-
const [codex, claude] = await Promise.all([
|
|
42220
|
-
verify("codex", runnerFor("codex")),
|
|
42221
|
-
verify("claude", runnerFor("claude"))
|
|
42222
|
-
]);
|
|
42223
|
-
await deps.push({ codex, claude });
|
|
42224
|
-
} catch (err) {
|
|
42225
|
-
deps.onError?.(err);
|
|
42226
|
-
}
|
|
42227
|
-
}
|
|
42228
|
-
function startProviderReadinessLoop(deps) {
|
|
42229
|
-
const env = deps.env ?? process.env;
|
|
42230
|
-
const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_PROVIDER_READINESS_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS3);
|
|
42231
|
-
let stopped = false;
|
|
42232
|
-
let timer = null;
|
|
42233
|
-
const schedule = () => {
|
|
42234
|
-
if (stopped) return;
|
|
42235
|
-
timer = setTimeout(() => {
|
|
42236
|
-
void runProviderReadinessCycle(deps).then(() => schedule());
|
|
42237
|
-
}, intervalMs);
|
|
42238
|
-
timer.unref?.();
|
|
42239
|
-
};
|
|
42240
|
-
timer = setTimeout(() => {
|
|
42241
|
-
void runProviderReadinessCycle(deps).then(() => schedule());
|
|
42242
|
-
}, 1e3);
|
|
42243
|
-
timer.unref?.();
|
|
42244
|
-
return {
|
|
42245
|
-
stop() {
|
|
42246
|
-
stopped = true;
|
|
42247
|
-
if (timer) clearTimeout(timer);
|
|
42346
|
+
if (rowsByProject.size === 0) continue;
|
|
42347
|
+
const telemetryDir = (0, import_node_path10.join)(stateDir, "telemetry");
|
|
42348
|
+
await (0, import_promises5.mkdir)(telemetryDir, { recursive: true });
|
|
42349
|
+
for (const [slug, rows] of rowsByProject) {
|
|
42350
|
+
const finalPath = (0, import_node_path10.join)(telemetryDir, `rows-${slug}-${day}.jsonl`);
|
|
42351
|
+
const tmpPath = `${finalPath}.tmp`;
|
|
42352
|
+
await (0, import_promises5.writeFile)(tmpPath, rows.map((r) => JSON.stringify(r)).join("\n") + "\n", "utf8");
|
|
42353
|
+
await (0, import_promises5.rename)(tmpPath, finalPath);
|
|
42248
42354
|
}
|
|
42249
|
-
}
|
|
42250
|
-
}
|
|
42251
|
-
|
|
42252
|
-
// src/selected-provider-store.ts
|
|
42253
|
-
var current = null;
|
|
42254
|
-
function getSelectedProvider() {
|
|
42255
|
-
return current;
|
|
42256
|
-
}
|
|
42257
|
-
function setSelectedProvider(value) {
|
|
42258
|
-
current = value;
|
|
42355
|
+
}
|
|
42259
42356
|
}
|
|
42260
42357
|
|
|
42261
|
-
// src/
|
|
42262
|
-
var
|
|
42263
|
-
var
|
|
42264
|
-
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
42265
|
-
var import_node_util = require("node:util");
|
|
42266
|
-
|
|
42267
|
-
// src/consensus/heads.ts
|
|
42268
|
-
var DEFAULT_DOMAIN = "code";
|
|
42269
|
-
var DOMAINS = ["code", "seo", "marketing", "content"];
|
|
42270
|
-
var HEADS_BY_DOMAIN = {
|
|
42271
|
-
code: ["plan-reviewer", "architect", "security-analyst", "scope-analyst"],
|
|
42272
|
-
seo: ["plan-reviewer", "scope-analyst", "seo-analyst"],
|
|
42273
|
-
marketing: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"],
|
|
42274
|
-
content: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"]
|
|
42275
|
-
};
|
|
42276
|
-
var SPEC_HEADS = HEADS_BY_DOMAIN.code;
|
|
42277
|
-
var CODE_HEADS_BY_IMPACT = {
|
|
42278
|
-
high: HEADS_BY_DOMAIN.code,
|
|
42279
|
-
medium: ["plan-reviewer", "security-analyst", "scope-analyst"],
|
|
42280
|
-
low: ["plan-reviewer", "scope-analyst"]
|
|
42281
|
-
};
|
|
42282
|
-
function normalizeDomain(value) {
|
|
42283
|
-
if (typeof value !== "string") return DEFAULT_DOMAIN;
|
|
42284
|
-
const v = value.trim().toLowerCase();
|
|
42285
|
-
return DOMAINS.includes(v) ? v : DEFAULT_DOMAIN;
|
|
42286
|
-
}
|
|
42287
|
-
function normalizeImpact(value) {
|
|
42288
|
-
if (typeof value !== "string") return null;
|
|
42289
|
-
const v = value.trim().toLowerCase();
|
|
42290
|
-
return v === "low" || v === "medium" || v === "high" ? v : null;
|
|
42291
|
-
}
|
|
42292
|
-
function resolveHeads(domain2, impact) {
|
|
42293
|
-
const d = normalizeDomain(domain2);
|
|
42294
|
-
if (d !== "code") return [...HEADS_BY_DOMAIN[d]];
|
|
42295
|
-
const i = normalizeImpact(impact) ?? "high";
|
|
42296
|
-
return [...CODE_HEADS_BY_IMPACT[i]];
|
|
42297
|
-
}
|
|
42298
|
-
var PERSONAS_BY_DOMAIN = {
|
|
42299
|
-
seo: "seo-writer",
|
|
42300
|
-
content: "content-author",
|
|
42301
|
-
marketing: "content-author"
|
|
42302
|
-
};
|
|
42303
|
-
function resolveProducerPersona(domain2) {
|
|
42304
|
-
const d = normalizeDomain(domain2);
|
|
42305
|
-
if (d === "code") return null;
|
|
42306
|
-
return PERSONAS_BY_DOMAIN[d] ?? null;
|
|
42307
|
-
}
|
|
42358
|
+
// src/telemetry/daily-uploader.ts
|
|
42359
|
+
var import_promises6 = require("node:fs/promises");
|
|
42360
|
+
var import_node_path12 = require("node:path");
|
|
42308
42361
|
|
|
42309
42362
|
// src/consensus/wiring.ts
|
|
42310
42363
|
var import_node_crypto3 = __toESM(require("node:crypto"), 1);
|
|
42311
42364
|
var import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
42312
|
-
var
|
|
42365
|
+
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
42313
42366
|
var import_node_url2 = require("node:url");
|
|
42314
42367
|
|
|
42315
42368
|
// src/consensus/verdict.ts
|
|
@@ -42741,6 +42794,48 @@ function firstTaskIdToken(text) {
|
|
|
42741
42794
|
return m ? m[0] : null;
|
|
42742
42795
|
}
|
|
42743
42796
|
|
|
42797
|
+
// src/consensus/heads.ts
|
|
42798
|
+
var DEFAULT_DOMAIN = "code";
|
|
42799
|
+
var DOMAINS = ["code", "seo", "marketing", "content"];
|
|
42800
|
+
var HEADS_BY_DOMAIN = {
|
|
42801
|
+
code: ["plan-reviewer", "architect", "security-analyst", "scope-analyst"],
|
|
42802
|
+
seo: ["plan-reviewer", "scope-analyst", "seo-analyst"],
|
|
42803
|
+
marketing: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"],
|
|
42804
|
+
content: ["plan-reviewer", "scope-analyst", "content-editor", "compliance-reviewer"]
|
|
42805
|
+
};
|
|
42806
|
+
var SPEC_HEADS = HEADS_BY_DOMAIN.code;
|
|
42807
|
+
var CODE_HEADS_BY_IMPACT = {
|
|
42808
|
+
high: HEADS_BY_DOMAIN.code,
|
|
42809
|
+
medium: ["plan-reviewer", "security-analyst", "scope-analyst"],
|
|
42810
|
+
low: ["plan-reviewer", "scope-analyst"]
|
|
42811
|
+
};
|
|
42812
|
+
function normalizeDomain(value) {
|
|
42813
|
+
if (typeof value !== "string") return DEFAULT_DOMAIN;
|
|
42814
|
+
const v = value.trim().toLowerCase();
|
|
42815
|
+
return DOMAINS.includes(v) ? v : DEFAULT_DOMAIN;
|
|
42816
|
+
}
|
|
42817
|
+
function normalizeImpact(value) {
|
|
42818
|
+
if (typeof value !== "string") return null;
|
|
42819
|
+
const v = value.trim().toLowerCase();
|
|
42820
|
+
return v === "low" || v === "medium" || v === "high" ? v : null;
|
|
42821
|
+
}
|
|
42822
|
+
function resolveHeads(domain2, impact) {
|
|
42823
|
+
const d = normalizeDomain(domain2);
|
|
42824
|
+
if (d !== "code") return [...HEADS_BY_DOMAIN[d]];
|
|
42825
|
+
const i = normalizeImpact(impact) ?? "high";
|
|
42826
|
+
return [...CODE_HEADS_BY_IMPACT[i]];
|
|
42827
|
+
}
|
|
42828
|
+
var PERSONAS_BY_DOMAIN = {
|
|
42829
|
+
seo: "seo-writer",
|
|
42830
|
+
content: "content-author",
|
|
42831
|
+
marketing: "content-author"
|
|
42832
|
+
};
|
|
42833
|
+
function resolveProducerPersona(domain2) {
|
|
42834
|
+
const d = normalizeDomain(domain2);
|
|
42835
|
+
if (d === "code") return null;
|
|
42836
|
+
return PERSONAS_BY_DOMAIN[d] ?? null;
|
|
42837
|
+
}
|
|
42838
|
+
|
|
42744
42839
|
// src/consensus/acceptance-criteria.ts
|
|
42745
42840
|
var HEADING_RE = /^(#{1,6})\s+(.+?)\s*$/;
|
|
42746
42841
|
var CHECKLIST_ITEM_RE = /^\s*[-*]\s+\[[ xX]\]\s+(.+\S)\s*$/;
|
|
@@ -43092,7 +43187,7 @@ ${issuesBlock}`,
|
|
|
43092
43187
|
}
|
|
43093
43188
|
|
|
43094
43189
|
// src/consensus/code-gate-git.ts
|
|
43095
|
-
var
|
|
43190
|
+
var import_node_child_process8 = require("node:child_process");
|
|
43096
43191
|
var DIFF_MAX_BYTES = 2e5;
|
|
43097
43192
|
var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
|
|
43098
43193
|
var GIT_TIMEOUT_MS = 6e4;
|
|
@@ -43108,7 +43203,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
|
|
|
43108
43203
|
};
|
|
43109
43204
|
let child;
|
|
43110
43205
|
try {
|
|
43111
|
-
child = (0,
|
|
43206
|
+
child = (0, import_node_child_process8.spawn)(cmd, args, {
|
|
43112
43207
|
cwd: opts.cwd,
|
|
43113
43208
|
env: process.env,
|
|
43114
43209
|
shell: false,
|
|
@@ -43323,15 +43418,15 @@ ${res.stdout}${res.stderr}`);
|
|
|
43323
43418
|
var import_meta2 = {};
|
|
43324
43419
|
function getPersonasDir() {
|
|
43325
43420
|
if (typeof __dirname !== "undefined") {
|
|
43326
|
-
return
|
|
43421
|
+
return import_node_path11.default.join(__dirname, "consensus", "personas");
|
|
43327
43422
|
}
|
|
43328
|
-
return
|
|
43423
|
+
return import_node_path11.default.join(import_node_path11.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
|
|
43329
43424
|
}
|
|
43330
43425
|
var personaCache = /* @__PURE__ */ new Map();
|
|
43331
43426
|
function loadPersona(name) {
|
|
43332
43427
|
const cached2 = personaCache.get(name);
|
|
43333
43428
|
if (cached2 !== void 0) return cached2;
|
|
43334
|
-
const content = import_node_fs5.default.readFileSync(
|
|
43429
|
+
const content = import_node_fs5.default.readFileSync(import_node_path11.default.join(getPersonasDir(), `${name}.md`), "utf8");
|
|
43335
43430
|
personaCache.set(name, content);
|
|
43336
43431
|
return content;
|
|
43337
43432
|
}
|
|
@@ -43811,6 +43906,497 @@ You revise a deliverable to address the accepted issues so it satisfies the acce
|
|
|
43811
43906
|
};
|
|
43812
43907
|
}
|
|
43813
43908
|
|
|
43909
|
+
// src/telemetry/pii-gate.ts
|
|
43910
|
+
function isRecord(v) {
|
|
43911
|
+
return v !== null && typeof v === "object";
|
|
43912
|
+
}
|
|
43913
|
+
function resolvePath(root, path22) {
|
|
43914
|
+
const parts = path22.split(".");
|
|
43915
|
+
let cur = root;
|
|
43916
|
+
for (let i = 0; i < parts.length - 1; i += 1) {
|
|
43917
|
+
const part = parts[i];
|
|
43918
|
+
const idx = Number(part);
|
|
43919
|
+
if (Array.isArray(cur) && Number.isInteger(idx)) {
|
|
43920
|
+
if (idx < 0 || idx >= cur.length) return null;
|
|
43921
|
+
cur = cur[idx];
|
|
43922
|
+
} else if (isRecord(cur) && part in cur) {
|
|
43923
|
+
cur = cur[part];
|
|
43924
|
+
} else {
|
|
43925
|
+
return null;
|
|
43926
|
+
}
|
|
43927
|
+
}
|
|
43928
|
+
const last = parts[parts.length - 1];
|
|
43929
|
+
const lastIdx = Number(last);
|
|
43930
|
+
if (Array.isArray(cur) && Number.isInteger(lastIdx)) {
|
|
43931
|
+
if (lastIdx < 0 || lastIdx >= cur.length) return null;
|
|
43932
|
+
return { parent: cur, key: lastIdx };
|
|
43933
|
+
}
|
|
43934
|
+
if (isRecord(cur) && last in cur) {
|
|
43935
|
+
return { parent: cur, key: last };
|
|
43936
|
+
}
|
|
43937
|
+
return null;
|
|
43938
|
+
}
|
|
43939
|
+
function withheldExcerptClone(artifact) {
|
|
43940
|
+
const clone2 = { ...artifact };
|
|
43941
|
+
if (Array.isArray(clone2.steps)) {
|
|
43942
|
+
clone2.steps = clone2.steps.map((step) => {
|
|
43943
|
+
if (!isRecord(step)) return step;
|
|
43944
|
+
const copy = { ...step };
|
|
43945
|
+
delete copy.excerpt;
|
|
43946
|
+
return copy;
|
|
43947
|
+
});
|
|
43948
|
+
}
|
|
43949
|
+
return clone2;
|
|
43950
|
+
}
|
|
43951
|
+
async function gate(artifact, prose, ctx) {
|
|
43952
|
+
if (prose.length === 0) {
|
|
43953
|
+
return { ok: true, gated: true, artifact };
|
|
43954
|
+
}
|
|
43955
|
+
const runExec = ctx.runExec ?? runAgentExec;
|
|
43956
|
+
const execResult = await runExec({
|
|
43957
|
+
prompt: JSON.stringify({ fields: prose }),
|
|
43958
|
+
developerInstructions: loadPersona("pii-gate"),
|
|
43959
|
+
cwd: ctx.cwd,
|
|
43960
|
+
timeoutMs: ctx.timeoutMs,
|
|
43961
|
+
sandbox: "read-only",
|
|
43962
|
+
codexExecutable: ctx.codexExecutable,
|
|
43963
|
+
model: ctx.model
|
|
43964
|
+
});
|
|
43965
|
+
if (!execResult.ok) {
|
|
43966
|
+
return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
|
|
43967
|
+
}
|
|
43968
|
+
let parsed;
|
|
43969
|
+
try {
|
|
43970
|
+
parsed = JSON.parse(execResult.text);
|
|
43971
|
+
} catch {
|
|
43972
|
+
return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
|
|
43973
|
+
}
|
|
43974
|
+
const fields = isRecord(parsed) && Array.isArray(parsed.fields) ? parsed.fields : null;
|
|
43975
|
+
const isValidShape = fields !== null && fields.length === prose.length && fields.every(
|
|
43976
|
+
(entry, i) => isRecord(entry) && typeof entry.path === "string" && typeof entry.masked === "string" && entry.path === prose[i]?.path && resolvePath(artifact, entry.path) !== null
|
|
43977
|
+
);
|
|
43978
|
+
if (!isValidShape || fields === null) {
|
|
43979
|
+
return { ok: true, gated: true, artifact: withheldExcerptClone(artifact) };
|
|
43980
|
+
}
|
|
43981
|
+
const maskedClone = typeof structuredClone === "function" ? structuredClone(artifact) : JSON.parse(JSON.stringify(artifact));
|
|
43982
|
+
for (const { path: path22, masked } of fields) {
|
|
43983
|
+
const target = resolvePath(maskedClone, path22);
|
|
43984
|
+
if (!target) throw new Error(`pii-gate: path "${path22}" failed to resolve on the clone after validating on the original`);
|
|
43985
|
+
target.parent[target.key] = masked;
|
|
43986
|
+
}
|
|
43987
|
+
return { ok: true, gated: false, artifact: maskedClone };
|
|
43988
|
+
}
|
|
43989
|
+
|
|
43990
|
+
// src/telemetry/daily-uploader.ts
|
|
43991
|
+
var ROWS_FILE_RE = /^rows-(.+)-(\d{4}-\d{2}-\d{2})\.jsonl$/;
|
|
43992
|
+
async function uploadPendingDays(stateDir, client, bridgeHealth, gateCtx) {
|
|
43993
|
+
const telemetryDir = (0, import_node_path12.join)(stateDir, "telemetry");
|
|
43994
|
+
let files;
|
|
43995
|
+
try {
|
|
43996
|
+
files = await (0, import_promises6.readdir)(telemetryDir);
|
|
43997
|
+
} catch (err) {
|
|
43998
|
+
if (err?.code === "ENOENT") return;
|
|
43999
|
+
throw err;
|
|
44000
|
+
}
|
|
44001
|
+
const pending = [];
|
|
44002
|
+
for (const file2 of files) {
|
|
44003
|
+
const match = ROWS_FILE_RE.exec(file2);
|
|
44004
|
+
if (!match) continue;
|
|
44005
|
+
const [, projectSlug, day] = match;
|
|
44006
|
+
const markerPath = (0, import_node_path12.join)(telemetryDir, `.processed-${projectSlug}-${day}`);
|
|
44007
|
+
try {
|
|
44008
|
+
await (0, import_promises6.access)(markerPath);
|
|
44009
|
+
} catch {
|
|
44010
|
+
pending.push({ projectSlug, day, rowsPath: (0, import_node_path12.join)(telemetryDir, file2), markerPath });
|
|
44011
|
+
}
|
|
44012
|
+
}
|
|
44013
|
+
if (pending.length === 0) return;
|
|
44014
|
+
const knownCrashCount = bridgeHealth.knownCrashCount() ?? 0;
|
|
44015
|
+
const fullUnprocessed = pending.map((p) => ({ projectSlug: p.projectSlug, day: p.day }));
|
|
44016
|
+
pending.sort((a, b) => a.day.localeCompare(b.day));
|
|
44017
|
+
for (const cur of pending) {
|
|
44018
|
+
let raw;
|
|
44019
|
+
try {
|
|
44020
|
+
raw = await (0, import_promises6.readFile)(cur.rowsPath, "utf8");
|
|
44021
|
+
} catch (err) {
|
|
44022
|
+
console.error(`uploadPendingDays: failed to read ${cur.rowsPath}`, err);
|
|
44023
|
+
continue;
|
|
44024
|
+
}
|
|
44025
|
+
const rows = [];
|
|
44026
|
+
for (const line of raw.split("\n")) {
|
|
44027
|
+
if (!line.trim()) continue;
|
|
44028
|
+
try {
|
|
44029
|
+
rows.push({ ...JSON.parse(line), gateMarker: "gated" });
|
|
44030
|
+
} catch {
|
|
44031
|
+
}
|
|
44032
|
+
}
|
|
44033
|
+
const batch = {
|
|
44034
|
+
day: cur.day,
|
|
44035
|
+
bridgeVersion: PKG_VERSION,
|
|
44036
|
+
knownCrashCount,
|
|
44037
|
+
unprocessedPartitions: fullUnprocessed.filter(
|
|
44038
|
+
(p) => !(p.projectSlug === cur.projectSlug && p.day === cur.day)
|
|
44039
|
+
),
|
|
44040
|
+
rows
|
|
44041
|
+
};
|
|
44042
|
+
const gateResult = await gate(batch, [], gateCtx);
|
|
44043
|
+
const gateMarker = gateResult.gated ? "gated" : "projection-only";
|
|
44044
|
+
for (const row of gateResult.artifact.rows) row.gateMarker = gateMarker;
|
|
44045
|
+
const targetProject = cur.projectSlug === "_unattributed" ? process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT : cur.projectSlug;
|
|
44046
|
+
if (!targetProject) {
|
|
44047
|
+
console.error(`uploadPendingDays: no target project resolved for _unattributed/${cur.day}`);
|
|
44048
|
+
continue;
|
|
44049
|
+
}
|
|
44050
|
+
try {
|
|
44051
|
+
await client.postTelemetry(targetProject, gateResult.artifact);
|
|
44052
|
+
} catch (err) {
|
|
44053
|
+
console.error(`uploadPendingDays: postTelemetry failed for ${cur.projectSlug}/${cur.day}`, err);
|
|
44054
|
+
continue;
|
|
44055
|
+
}
|
|
44056
|
+
const tmpMarker = `${cur.markerPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
44057
|
+
try {
|
|
44058
|
+
await (0, import_promises6.writeFile)(tmpMarker, "");
|
|
44059
|
+
await (0, import_promises6.rename)(tmpMarker, cur.markerPath);
|
|
44060
|
+
} catch (err) {
|
|
44061
|
+
console.error(`uploadPendingDays: failed to write marker for ${cur.projectSlug}/${cur.day}`, err);
|
|
44062
|
+
}
|
|
44063
|
+
}
|
|
44064
|
+
}
|
|
44065
|
+
|
|
44066
|
+
// src/agent-pool-snapshot.ts
|
|
44067
|
+
function normalizeLastUsedAt(value) {
|
|
44068
|
+
if (value === void 0 || value === null) return null;
|
|
44069
|
+
if (typeof value === "number") {
|
|
44070
|
+
if (!Number.isFinite(value)) return null;
|
|
44071
|
+
const ms = value < 1e12 ? value * 1e3 : value;
|
|
44072
|
+
const date5 = new Date(ms);
|
|
44073
|
+
return Number.isNaN(date5.getTime()) ? null : date5.toISOString();
|
|
44074
|
+
}
|
|
44075
|
+
return value;
|
|
44076
|
+
}
|
|
44077
|
+
function buildAgentPoolSnapshot(statusRows, stats, opts) {
|
|
44078
|
+
if (!opts.available) {
|
|
44079
|
+
return {
|
|
44080
|
+
collected_at: opts.collectedAt,
|
|
44081
|
+
status: "unavailable",
|
|
44082
|
+
agents: [],
|
|
44083
|
+
totals: { calls: 0, tokens_in: 0, tokens_out: 0 },
|
|
44084
|
+
estimated_savings_usd: 0
|
|
44085
|
+
};
|
|
44086
|
+
}
|
|
44087
|
+
const costPer1M = opts.paidCostPer1MTokens ?? 3;
|
|
44088
|
+
const agents = statusRows.map((row) => {
|
|
44089
|
+
const agentStats = stats.by_agent[row.id];
|
|
44090
|
+
const count2 = agentStats?.count ?? 0;
|
|
44091
|
+
const tokensIn = agentStats?.tokens_in ?? 0;
|
|
44092
|
+
const tokensOut = agentStats?.tokens_out ?? 0;
|
|
44093
|
+
let successRate = 0;
|
|
44094
|
+
if (count2 > 0) {
|
|
44095
|
+
const successOutcomes = agentStats?.outcomes.success ?? 0;
|
|
44096
|
+
successRate = Number((successOutcomes / count2 * 100).toFixed(2)) / 100;
|
|
44097
|
+
}
|
|
44098
|
+
return {
|
|
44099
|
+
id: row.id,
|
|
44100
|
+
provider: row.provider,
|
|
44101
|
+
tier: row.tier,
|
|
44102
|
+
tags: row.tags,
|
|
44103
|
+
state: row.state ?? "unknown",
|
|
44104
|
+
calls: count2,
|
|
44105
|
+
tokens_in: tokensIn,
|
|
44106
|
+
tokens_out: tokensOut,
|
|
44107
|
+
success_rate: successRate,
|
|
44108
|
+
last_used_at: normalizeLastUsedAt(row.last_used_at)
|
|
44109
|
+
};
|
|
44110
|
+
});
|
|
44111
|
+
let totalCalls = 0;
|
|
44112
|
+
let totalTokensIn = 0;
|
|
44113
|
+
let totalTokensOut = 0;
|
|
44114
|
+
for (const entry of Object.values(stats.by_agent)) {
|
|
44115
|
+
totalCalls += entry.count;
|
|
44116
|
+
totalTokensIn += entry.tokens_in;
|
|
44117
|
+
totalTokensOut += entry.tokens_out;
|
|
44118
|
+
}
|
|
44119
|
+
let savedTokens = 0;
|
|
44120
|
+
for (const row of statusRows) {
|
|
44121
|
+
if (row.tags.includes("free")) {
|
|
44122
|
+
const agentStats = stats.by_agent[row.id];
|
|
44123
|
+
if (agentStats) {
|
|
44124
|
+
savedTokens += agentStats.tokens_in + agentStats.tokens_out;
|
|
44125
|
+
}
|
|
44126
|
+
}
|
|
44127
|
+
}
|
|
44128
|
+
const estimatedSavings = Number((savedTokens / 1e6 * costPer1M).toFixed(2));
|
|
44129
|
+
return {
|
|
44130
|
+
collected_at: opts.collectedAt,
|
|
44131
|
+
status: "ok",
|
|
44132
|
+
agents,
|
|
44133
|
+
totals: {
|
|
44134
|
+
calls: totalCalls,
|
|
44135
|
+
tokens_in: totalTokensIn,
|
|
44136
|
+
tokens_out: totalTokensOut
|
|
44137
|
+
},
|
|
44138
|
+
estimated_savings_usd: estimatedSavings
|
|
44139
|
+
};
|
|
44140
|
+
}
|
|
44141
|
+
|
|
44142
|
+
// src/agent-pool-collector.ts
|
|
44143
|
+
async function collectAgentPoolSnapshot(deps) {
|
|
44144
|
+
let statusRows;
|
|
44145
|
+
let stats;
|
|
44146
|
+
try {
|
|
44147
|
+
const statusResult = await deps.runCli(["status", "--json"]);
|
|
44148
|
+
if (statusResult.code !== 0) throw new Error("non-zero exit on status");
|
|
44149
|
+
let statusParsed;
|
|
44150
|
+
try {
|
|
44151
|
+
statusParsed = JSON.parse(statusResult.stdout);
|
|
44152
|
+
} catch {
|
|
44153
|
+
throw new Error("invalid status json");
|
|
44154
|
+
}
|
|
44155
|
+
if (!Array.isArray(statusParsed)) throw new Error("status not array");
|
|
44156
|
+
statusRows = statusParsed;
|
|
44157
|
+
const statsResult = await deps.runCli(["stats", "--json"]);
|
|
44158
|
+
if (statsResult.code !== 0) throw new Error("non-zero exit on stats");
|
|
44159
|
+
try {
|
|
44160
|
+
stats = JSON.parse(statsResult.stdout);
|
|
44161
|
+
} catch {
|
|
44162
|
+
throw new Error("invalid stats json");
|
|
44163
|
+
}
|
|
44164
|
+
} catch {
|
|
44165
|
+
return buildAgentPoolSnapshot(
|
|
44166
|
+
[],
|
|
44167
|
+
{},
|
|
44168
|
+
{ collectedAt: deps.now(), available: false }
|
|
44169
|
+
);
|
|
44170
|
+
}
|
|
44171
|
+
return buildAgentPoolSnapshot(
|
|
44172
|
+
statusRows,
|
|
44173
|
+
stats,
|
|
44174
|
+
{ collectedAt: deps.now(), paidCostPer1MTokens: deps.paidCostPer1MTokens, available: true }
|
|
44175
|
+
);
|
|
44176
|
+
}
|
|
44177
|
+
|
|
44178
|
+
// src/external-agents-spawn.ts
|
|
44179
|
+
var import_node_child_process9 = require("node:child_process");
|
|
44180
|
+
|
|
44181
|
+
// src/external-agents-bin.ts
|
|
44182
|
+
function resolveExternalAgentsCliInvocation(override) {
|
|
44183
|
+
if (override && override.trim()) return { command: override, prefixArgs: [] };
|
|
44184
|
+
try {
|
|
44185
|
+
return {
|
|
44186
|
+
command: "node",
|
|
44187
|
+
prefixArgs: [resolvePackageBin("@mrrlin-dev/external-agents", "external-agents")]
|
|
44188
|
+
};
|
|
44189
|
+
} catch {
|
|
44190
|
+
return { command: "external-agents", prefixArgs: [] };
|
|
44191
|
+
}
|
|
44192
|
+
}
|
|
44193
|
+
|
|
44194
|
+
// src/external-agents-spawn.ts
|
|
44195
|
+
function runExternalAgentsCli(args, opts) {
|
|
44196
|
+
let command;
|
|
44197
|
+
let prefixArgs;
|
|
44198
|
+
let source;
|
|
44199
|
+
let triedPath;
|
|
44200
|
+
if (opts.envCliPath && opts.envCliPath.trim()) {
|
|
44201
|
+
command = "node";
|
|
44202
|
+
prefixArgs = [opts.envCliPath];
|
|
44203
|
+
source = "env";
|
|
44204
|
+
triedPath = opts.envCliPath;
|
|
44205
|
+
} else {
|
|
44206
|
+
({ command, prefixArgs } = resolveExternalAgentsCliInvocation());
|
|
44207
|
+
source = command === "node" && prefixArgs.length === 1 ? "bundled" : "path";
|
|
44208
|
+
triedPath = source === "bundled" ? prefixArgs[0] ?? "" : "external-agents (PATH)";
|
|
44209
|
+
}
|
|
44210
|
+
const useStdin = opts.stdinValue !== void 0;
|
|
44211
|
+
const stdioConfig = useStdin ? ["pipe", "pipe", "pipe"] : ["ignore", "pipe", "pipe"];
|
|
44212
|
+
return new Promise((resolve) => {
|
|
44213
|
+
let stdout = "";
|
|
44214
|
+
let stderr = "";
|
|
44215
|
+
let settled = false;
|
|
44216
|
+
let timedOut = false;
|
|
44217
|
+
const done = (code) => {
|
|
44218
|
+
if (!settled) {
|
|
44219
|
+
settled = true;
|
|
44220
|
+
resolve({ stdout, stderr, code, timedOut, source, triedPath });
|
|
44221
|
+
}
|
|
44222
|
+
};
|
|
44223
|
+
let spawned;
|
|
44224
|
+
try {
|
|
44225
|
+
spawned = (0, import_node_child_process9.spawn)(command, [...prefixArgs, ...args], { stdio: stdioConfig });
|
|
44226
|
+
} catch {
|
|
44227
|
+
done(1);
|
|
44228
|
+
return;
|
|
44229
|
+
}
|
|
44230
|
+
const child = spawned;
|
|
44231
|
+
let sigkillTimer = null;
|
|
44232
|
+
let budgetTimer = null;
|
|
44233
|
+
if (useStdin && child.stdin) {
|
|
44234
|
+
child.stdin.on("error", () => {
|
|
44235
|
+
});
|
|
44236
|
+
child.stdin.write(opts.stdinValue);
|
|
44237
|
+
child.stdin.end();
|
|
44238
|
+
}
|
|
44239
|
+
child.stdout?.on("data", (d) => {
|
|
44240
|
+
stdout += d.toString();
|
|
44241
|
+
if (stdout.length > 2e5) stdout = stdout.slice(-2e5);
|
|
44242
|
+
});
|
|
44243
|
+
child.stderr?.on("data", (d) => {
|
|
44244
|
+
stderr += d.toString();
|
|
44245
|
+
if (stderr.length > 2e5) stderr = stderr.slice(-2e5);
|
|
44246
|
+
});
|
|
44247
|
+
budgetTimer = setTimeout(() => {
|
|
44248
|
+
budgetTimer = null;
|
|
44249
|
+
timedOut = true;
|
|
44250
|
+
try {
|
|
44251
|
+
child.kill("SIGTERM");
|
|
44252
|
+
} catch {
|
|
44253
|
+
}
|
|
44254
|
+
sigkillTimer = setTimeout(() => {
|
|
44255
|
+
sigkillTimer = null;
|
|
44256
|
+
try {
|
|
44257
|
+
child.kill("SIGKILL");
|
|
44258
|
+
} catch {
|
|
44259
|
+
}
|
|
44260
|
+
}, 2e3);
|
|
44261
|
+
sigkillTimer.unref?.();
|
|
44262
|
+
done(1);
|
|
44263
|
+
}, opts.budgetMs);
|
|
44264
|
+
budgetTimer.unref?.();
|
|
44265
|
+
child.on("error", () => {
|
|
44266
|
+
if (budgetTimer) {
|
|
44267
|
+
clearTimeout(budgetTimer);
|
|
44268
|
+
budgetTimer = null;
|
|
44269
|
+
}
|
|
44270
|
+
if (sigkillTimer) {
|
|
44271
|
+
clearTimeout(sigkillTimer);
|
|
44272
|
+
sigkillTimer = null;
|
|
44273
|
+
}
|
|
44274
|
+
done(1);
|
|
44275
|
+
});
|
|
44276
|
+
child.on("close", (code) => {
|
|
44277
|
+
if (budgetTimer) {
|
|
44278
|
+
clearTimeout(budgetTimer);
|
|
44279
|
+
budgetTimer = null;
|
|
44280
|
+
}
|
|
44281
|
+
if (sigkillTimer) {
|
|
44282
|
+
clearTimeout(sigkillTimer);
|
|
44283
|
+
sigkillTimer = null;
|
|
44284
|
+
}
|
|
44285
|
+
done(code ?? 1);
|
|
44286
|
+
});
|
|
44287
|
+
});
|
|
44288
|
+
}
|
|
44289
|
+
|
|
44290
|
+
// src/agent-pool-loop.ts
|
|
44291
|
+
var DEFAULT_INTERVAL_MS2 = 6e4;
|
|
44292
|
+
function agentPoolLoopDisabled(env = process.env) {
|
|
44293
|
+
return env["MRRLIN_BRIDGE_AGENT_POOL_DISABLE"] === "1";
|
|
44294
|
+
}
|
|
44295
|
+
function defaultRunCli(args) {
|
|
44296
|
+
return runExternalAgentsCli(args, {
|
|
44297
|
+
budgetMs: 5e3,
|
|
44298
|
+
envCliPath: process.env["EXTERNAL_AGENTS_CLI"]
|
|
44299
|
+
}).then(({ stdout, code }) => ({ stdout, code }));
|
|
44300
|
+
}
|
|
44301
|
+
async function runAgentPoolCycle(deps) {
|
|
44302
|
+
try {
|
|
44303
|
+
const snapshot = await collectAgentPoolSnapshot({
|
|
44304
|
+
runCli: deps.runCli ?? defaultRunCli,
|
|
44305
|
+
now: deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString())
|
|
44306
|
+
});
|
|
44307
|
+
await deps.push(snapshot);
|
|
44308
|
+
} catch (err) {
|
|
44309
|
+
deps.onError?.(err);
|
|
44310
|
+
}
|
|
44311
|
+
}
|
|
44312
|
+
function startAgentPoolLoop(deps) {
|
|
44313
|
+
const env = deps.env ?? process.env;
|
|
44314
|
+
const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_AGENT_POOL_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS2);
|
|
44315
|
+
let stopped = false;
|
|
44316
|
+
let timer = null;
|
|
44317
|
+
const schedule = () => {
|
|
44318
|
+
if (stopped) return;
|
|
44319
|
+
timer = setTimeout(() => {
|
|
44320
|
+
void runAgentPoolCycle(deps).then(() => schedule());
|
|
44321
|
+
}, intervalMs);
|
|
44322
|
+
timer.unref?.();
|
|
44323
|
+
};
|
|
44324
|
+
timer = setTimeout(() => {
|
|
44325
|
+
void runAgentPoolCycle(deps).then(() => schedule());
|
|
44326
|
+
}, 1e3);
|
|
44327
|
+
timer.unref?.();
|
|
44328
|
+
return {
|
|
44329
|
+
stop() {
|
|
44330
|
+
stopped = true;
|
|
44331
|
+
if (timer) clearTimeout(timer);
|
|
44332
|
+
}
|
|
44333
|
+
};
|
|
44334
|
+
}
|
|
44335
|
+
|
|
44336
|
+
// src/provider-readiness-loop.ts
|
|
44337
|
+
var import_node_child_process10 = require("node:child_process");
|
|
44338
|
+
var DEFAULT_INTERVAL_MS3 = 6e4;
|
|
44339
|
+
function providerReadinessLoopDisabled(env = process.env) {
|
|
44340
|
+
return env["MRRLIN_BRIDGE_PROVIDER_READINESS_DISABLE"] === "1";
|
|
44341
|
+
}
|
|
44342
|
+
function defaultRunnerFor(command) {
|
|
44343
|
+
return (args) => {
|
|
44344
|
+
const r = (0, import_node_child_process10.spawnSync)(command, args, { encoding: "utf8", timeout: 8e3 });
|
|
44345
|
+
return { status: r.status, stdout: r.stdout ?? "", stderr: r.stderr ?? "" };
|
|
44346
|
+
};
|
|
44347
|
+
}
|
|
44348
|
+
async function runProviderReadinessCycle(deps) {
|
|
44349
|
+
try {
|
|
44350
|
+
const verify = deps.verify ?? verifyProviderReadiness;
|
|
44351
|
+
const runnerFor = deps.runnerFor ?? defaultRunnerFor;
|
|
44352
|
+
const [codex, claude] = await Promise.all([
|
|
44353
|
+
verify("codex", runnerFor("codex")),
|
|
44354
|
+
verify("claude", runnerFor("claude"))
|
|
44355
|
+
]);
|
|
44356
|
+
await deps.push({ codex, claude });
|
|
44357
|
+
} catch (err) {
|
|
44358
|
+
deps.onError?.(err);
|
|
44359
|
+
}
|
|
44360
|
+
}
|
|
44361
|
+
function startProviderReadinessLoop(deps) {
|
|
44362
|
+
const env = deps.env ?? process.env;
|
|
44363
|
+
const intervalMs = deps.intervalMs ?? Number(env["MRRLIN_BRIDGE_PROVIDER_READINESS_INTERVAL_MS"] ?? DEFAULT_INTERVAL_MS3);
|
|
44364
|
+
let stopped = false;
|
|
44365
|
+
let timer = null;
|
|
44366
|
+
const schedule = () => {
|
|
44367
|
+
if (stopped) return;
|
|
44368
|
+
timer = setTimeout(() => {
|
|
44369
|
+
void runProviderReadinessCycle(deps).then(() => schedule());
|
|
44370
|
+
}, intervalMs);
|
|
44371
|
+
timer.unref?.();
|
|
44372
|
+
};
|
|
44373
|
+
timer = setTimeout(() => {
|
|
44374
|
+
void runProviderReadinessCycle(deps).then(() => schedule());
|
|
44375
|
+
}, 1e3);
|
|
44376
|
+
timer.unref?.();
|
|
44377
|
+
return {
|
|
44378
|
+
stop() {
|
|
44379
|
+
stopped = true;
|
|
44380
|
+
if (timer) clearTimeout(timer);
|
|
44381
|
+
}
|
|
44382
|
+
};
|
|
44383
|
+
}
|
|
44384
|
+
|
|
44385
|
+
// src/selected-provider-store.ts
|
|
44386
|
+
var current = null;
|
|
44387
|
+
function getSelectedProvider() {
|
|
44388
|
+
return current;
|
|
44389
|
+
}
|
|
44390
|
+
function setSelectedProvider(value) {
|
|
44391
|
+
current = value;
|
|
44392
|
+
}
|
|
44393
|
+
|
|
44394
|
+
// src/execution-consumer.ts
|
|
44395
|
+
var import_node_child_process12 = require("node:child_process");
|
|
44396
|
+
var import_node_crypto5 = __toESM(require("node:crypto"), 1);
|
|
44397
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
44398
|
+
var import_node_util = require("node:util");
|
|
44399
|
+
|
|
43814
44400
|
// src/consensus/deliverable-gate-outcome.ts
|
|
43815
44401
|
var MAX_DELIVERABLE_DIAGNOSTICS = 5;
|
|
43816
44402
|
var MAX_DELIVERABLE_DIAGNOSTIC_LENGTH = 240;
|
|
@@ -45055,15 +45641,15 @@ async function awaitTurnWithDeadline(opts) {
|
|
|
45055
45641
|
var import_node_child_process11 = require("node:child_process");
|
|
45056
45642
|
var import_node_fs7 = require("node:fs");
|
|
45057
45643
|
var import_node_os6 = require("node:os");
|
|
45058
|
-
var
|
|
45644
|
+
var import_node_path14 = require("node:path");
|
|
45059
45645
|
|
|
45060
45646
|
// src/checkout-lock.ts
|
|
45061
45647
|
var import_node_fs6 = require("node:fs");
|
|
45062
|
-
var
|
|
45648
|
+
var import_node_path13 = require("node:path");
|
|
45063
45649
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
45064
45650
|
async function withCheckoutLock(locksDir, slug, fn) {
|
|
45065
45651
|
(0, import_node_fs6.mkdirSync)(locksDir, { recursive: true });
|
|
45066
|
-
const target = (0,
|
|
45652
|
+
const target = (0, import_node_path13.join)(locksDir, `${slug}.lock`);
|
|
45067
45653
|
if (!(0, import_node_fs6.existsSync)(target)) (0, import_node_fs6.writeFileSync)(target, "");
|
|
45068
45654
|
const release = await import_proper_lockfile.default.lock(target, {
|
|
45069
45655
|
retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
|
|
@@ -45089,7 +45675,7 @@ function git(checkout, args) {
|
|
|
45089
45675
|
});
|
|
45090
45676
|
}
|
|
45091
45677
|
async function createRunWorktree(opts) {
|
|
45092
|
-
const worktreePath = (0,
|
|
45678
|
+
const worktreePath = (0, import_node_path14.join)(opts.worktreeRoot, opts.slug, opts.runId);
|
|
45093
45679
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
45094
45680
|
(0, import_node_fs7.mkdirSync)(opts.worktreeRoot, { recursive: true });
|
|
45095
45681
|
try {
|
|
@@ -45166,8 +45752,8 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
45166
45752
|
if (localConfig.trim()) {
|
|
45167
45753
|
throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
|
|
45168
45754
|
}
|
|
45169
|
-
const dir = (0, import_node_fs7.mkdtempSync)((0,
|
|
45170
|
-
const askpass = (0,
|
|
45755
|
+
const dir = (0, import_node_fs7.mkdtempSync)((0, import_node_path14.join)((0, import_node_os6.tmpdir)(), "mrrlin-push-"));
|
|
45756
|
+
const askpass = (0, import_node_path14.join)(dir, "askpass");
|
|
45171
45757
|
try {
|
|
45172
45758
|
(0, import_node_fs7.writeFileSync)(
|
|
45173
45759
|
askpass,
|
|
@@ -45204,7 +45790,7 @@ async function sweepOrphanWorktrees(opts) {
|
|
|
45204
45790
|
} catch {
|
|
45205
45791
|
return opts.worktreeRoot;
|
|
45206
45792
|
}
|
|
45207
|
-
})() +
|
|
45793
|
+
})() + import_node_path14.sep + opts.slug + import_node_path14.sep;
|
|
45208
45794
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
45209
45795
|
const listing = git(opts.checkout, ["worktree", "list", "--porcelain"]);
|
|
45210
45796
|
for (const block of listing.split("\n\n")) {
|
|
@@ -45496,6 +46082,11 @@ var BASE_INSTRUCTIONS_PREFIX = [
|
|
|
45496
46082
|
"- Pick the right open status when you stop a CODE task: if the code work itself is done and only an",
|
|
45497
46083
|
" already-open PR still awaits operator merge or follow-up, leave the task at `awaiting_verification`;",
|
|
45498
46084
|
" if you are blocked and a human must decide before the work can continue, leave it at `handoff_needed`.",
|
|
46085
|
+
"- Before calling update_task with status=handoff_needed because you are missing a concrete",
|
|
46086
|
+
" operational fact (an email address, credential, pricing detail, account name, or similar) --",
|
|
46087
|
+
" NOT a product/scope decision, which is legitimately the operator's call -- first search for it:",
|
|
46088
|
+
" search_wiki_pages / retrieve_context, and re-read anything already loaded in this run's context",
|
|
46089
|
+
" bundle. Only hand off for that input if the search comes up empty.",
|
|
45499
46090
|
"",
|
|
45500
46091
|
"File artifacts:",
|
|
45501
46092
|
"- Decide BEFORE writing your result, by PROVENANCE: output assembled from data you RETRIEVED",
|
|
@@ -45677,8 +46268,8 @@ function newArtifactId() {
|
|
|
45677
46268
|
return `EA-${import_node_crypto5.default.randomUUID()}`;
|
|
45678
46269
|
}
|
|
45679
46270
|
var BLAST_RADIUS_FLOOR_PATTERNS = [/^supabase\/migrations\//, /^packages\/db\/src\/schema\.ts$/];
|
|
45680
|
-
function isBlastRadiusFloorPath(
|
|
45681
|
-
return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(
|
|
46271
|
+
function isBlastRadiusFloorPath(path22) {
|
|
46272
|
+
return BLAST_RADIUS_FLOOR_PATTERNS.some((re) => re.test(path22));
|
|
45682
46273
|
}
|
|
45683
46274
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process12.execFile);
|
|
45684
46275
|
async function defaultListRunDiffPaths(opts) {
|
|
@@ -47041,8 +47632,8 @@ async function runBackstopSweep(deps, drive = (slug, id) => driveRun(deps, slug,
|
|
|
47041
47632
|
function isRunRecoverableByThisBridge(run3, worktreeRoot) {
|
|
47042
47633
|
if (!worktreeRoot) return true;
|
|
47043
47634
|
if (!run3.worktreeId) return false;
|
|
47044
|
-
const relative =
|
|
47045
|
-
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !
|
|
47635
|
+
const relative = import_node_path15.default.relative(import_node_path15.default.resolve(worktreeRoot), import_node_path15.default.resolve(run3.worktreeId));
|
|
47636
|
+
return relative === "" || relative.length > 0 && !relative.startsWith("..") && !import_node_path15.default.isAbsolute(relative);
|
|
47046
47637
|
}
|
|
47047
47638
|
async function deployGateHandoff(deps, projectSlug, task, runId, reason, leaseId) {
|
|
47048
47639
|
await deps.client.updateExecutionRun(projectSlug, runId, { status: "failed", finishedAt: (/* @__PURE__ */ new Date()).toISOString(), leaseId: leaseId ?? void 0 }).catch(() => {
|
|
@@ -47079,7 +47670,7 @@ function maxLeaseReclaims() {
|
|
|
47079
47670
|
}
|
|
47080
47671
|
|
|
47081
47672
|
// src/async-job-consumer.ts
|
|
47082
|
-
var
|
|
47673
|
+
var import_node_crypto7 = __toESM(require("node:crypto"), 1);
|
|
47083
47674
|
|
|
47084
47675
|
// src/async-tools/registry.ts
|
|
47085
47676
|
var registry2 = /* @__PURE__ */ new Map();
|
|
@@ -47090,9 +47681,303 @@ function getAsyncToolDescriptor(toolName) {
|
|
|
47090
47681
|
return registry2.get(toolName);
|
|
47091
47682
|
}
|
|
47092
47683
|
|
|
47684
|
+
// src/bridge-log.ts
|
|
47685
|
+
var import_node_fs8 = require("node:fs");
|
|
47686
|
+
var import_promises7 = require("node:fs/promises");
|
|
47687
|
+
var import_node_path16 = require("node:path");
|
|
47688
|
+
|
|
47689
|
+
// src/redact.ts
|
|
47690
|
+
var REDACTED = "[REDACTED]";
|
|
47691
|
+
var SECRET_PATTERNS = [
|
|
47692
|
+
/ghp_[A-Za-z0-9]{20,}/g,
|
|
47693
|
+
// GitHub personal access token (classic)
|
|
47694
|
+
/github_pat_[A-Za-z0-9_]{20,}/g,
|
|
47695
|
+
// GitHub fine-grained PAT
|
|
47696
|
+
/\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
47697
|
+
// Authorization: Bearer <token>
|
|
47698
|
+
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
47699
|
+
// JWT (header.payload.signature)
|
|
47700
|
+
/\b[A-Fa-f0-9]{32,}\b/g,
|
|
47701
|
+
// long hex run (hashes, hex secrets)
|
|
47702
|
+
/\b[A-Za-z0-9+/]{40,}={0,2}\b/g
|
|
47703
|
+
// long base64-ish run (opaque tokens)
|
|
47704
|
+
];
|
|
47705
|
+
function redact(input) {
|
|
47706
|
+
let out = input;
|
|
47707
|
+
for (const re of SECRET_PATTERNS) out = out.replace(re, REDACTED);
|
|
47708
|
+
return out;
|
|
47709
|
+
}
|
|
47710
|
+
|
|
47711
|
+
// src/telemetry/projector.ts
|
|
47712
|
+
var import_node_crypto6 = require("node:crypto");
|
|
47713
|
+
function isRecord2(x) {
|
|
47714
|
+
return typeof x === "object" && x !== null;
|
|
47715
|
+
}
|
|
47716
|
+
function buildProjection(payload, type, ms, telemetry) {
|
|
47717
|
+
if (!isRecord2(payload)) return null;
|
|
47718
|
+
const seqRaw = payload.seq;
|
|
47719
|
+
const turnIdRaw = payload.turnId;
|
|
47720
|
+
const maybeSeq = typeof seqRaw === "number" ? seqRaw : void 0;
|
|
47721
|
+
const maybeTurnId = typeof turnIdRaw === "string" ? turnIdRaw : void 0;
|
|
47722
|
+
if (type === "event") {
|
|
47723
|
+
const rawEvent = payload.event;
|
|
47724
|
+
if (!isRecord2(rawEvent) || typeof rawEvent.type !== "string") return null;
|
|
47725
|
+
if (rawEvent.type === "tool_use") {
|
|
47726
|
+
const tool = rawEvent.tool;
|
|
47727
|
+
if (!isRecord2(tool)) return null;
|
|
47728
|
+
const toolId = tool.id;
|
|
47729
|
+
const toolName = tool.name;
|
|
47730
|
+
if (typeof toolId !== "string" || typeof toolName !== "string") return null;
|
|
47731
|
+
const input = tool.input;
|
|
47732
|
+
const argKeys = isRecord2(input) ? Object.keys(input) : [];
|
|
47733
|
+
const projectSlug = isRecord2(input) && typeof input.projectSlug === "string" ? input.projectSlug : void 0;
|
|
47734
|
+
const proj = { kind: "tool_use", toolId, toolName, argKeys, seq: maybeSeq ?? 0 };
|
|
47735
|
+
if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
|
|
47736
|
+
if (ms !== void 0) proj.ms = ms;
|
|
47737
|
+
if (projectSlug !== void 0) proj.projectSlug = projectSlug;
|
|
47738
|
+
return proj;
|
|
47739
|
+
}
|
|
47740
|
+
if (rawEvent.type === "tool_result") {
|
|
47741
|
+
const tool = rawEvent.tool;
|
|
47742
|
+
if (!isRecord2(tool)) return null;
|
|
47743
|
+
const toolId = tool.id;
|
|
47744
|
+
if (typeof toolId !== "string") return null;
|
|
47745
|
+
const exitCode = tool.exitCode;
|
|
47746
|
+
const outcome = typeof exitCode === "number" ? exitCode === 0 ? "success" : "error" : "unknown";
|
|
47747
|
+
const proj = { kind: "tool_result", toolId, outcome, seq: maybeSeq ?? 0 };
|
|
47748
|
+
if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
|
|
47749
|
+
if (ms !== void 0) proj.ms = ms;
|
|
47750
|
+
if (typeof exitCode === "number") proj.exitCode = exitCode;
|
|
47751
|
+
const status = tool.status;
|
|
47752
|
+
if (typeof status === "string" && status.trim() !== "") {
|
|
47753
|
+
proj.statusHash = (0, import_node_crypto6.createHash)("sha256").update(status.trim().toLowerCase()).digest("hex").slice(0, 8);
|
|
47754
|
+
}
|
|
47755
|
+
return proj;
|
|
47756
|
+
}
|
|
47757
|
+
if (rawEvent.type === "result") {
|
|
47758
|
+
const subtype = rawEvent.subtype;
|
|
47759
|
+
if (subtype !== "success" && subtype !== "interrupted") return null;
|
|
47760
|
+
const lifecycle = subtype === "success" ? "completed" : "interrupted";
|
|
47761
|
+
const proj = { kind: "turn_lifecycle", lifecycle, seq: maybeSeq ?? 0 };
|
|
47762
|
+
if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
|
|
47763
|
+
if (ms !== void 0) proj.ms = ms;
|
|
47764
|
+
if (lifecycle === "completed" && telemetry !== void 0) {
|
|
47765
|
+
proj.promptBytes = telemetry.promptBytes;
|
|
47766
|
+
if (telemetry.usage !== null) {
|
|
47767
|
+
proj.inputTokens = telemetry.usage.inputTokens ?? null;
|
|
47768
|
+
proj.cachedInputTokens = telemetry.usage.cachedInputTokens ?? null;
|
|
47769
|
+
proj.outputTokens = telemetry.usage.outputTokens ?? null;
|
|
47770
|
+
}
|
|
47771
|
+
}
|
|
47772
|
+
return proj;
|
|
47773
|
+
}
|
|
47774
|
+
if (rawEvent.type === "error") {
|
|
47775
|
+
const proj = { kind: "turn_lifecycle", lifecycle: "failed", seq: maybeSeq ?? 0 };
|
|
47776
|
+
if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
|
|
47777
|
+
if (ms !== void 0) proj.ms = ms;
|
|
47778
|
+
return proj;
|
|
47779
|
+
}
|
|
47780
|
+
return null;
|
|
47781
|
+
}
|
|
47782
|
+
if (type === "ready") {
|
|
47783
|
+
return { kind: "plumbing", plumbingKind: "ready", seq: maybeSeq ?? 0, ...ms !== void 0 ? { ms } : {} };
|
|
47784
|
+
}
|
|
47785
|
+
if (type === "rateLimits") {
|
|
47786
|
+
const rateLimits = payload.rateLimits;
|
|
47787
|
+
const proj = { kind: "plumbing", plumbingKind: "rate_limit_status", seq: maybeSeq ?? 0 };
|
|
47788
|
+
if (maybeTurnId !== void 0) proj.turnId = maybeTurnId;
|
|
47789
|
+
if (ms !== void 0) proj.ms = ms;
|
|
47790
|
+
if (isRecord2(rateLimits)) proj.rateLimitReached = rateLimits.rateLimitReachedType != null;
|
|
47791
|
+
return proj;
|
|
47792
|
+
}
|
|
47793
|
+
const bracketMatch = /^<([a-z-]+)>$/.exec(type);
|
|
47794
|
+
if (bracketMatch) {
|
|
47795
|
+
const candidate = bracketMatch[1]?.replace(/-/g, "_");
|
|
47796
|
+
if (candidate === "scheduler_tick" || candidate === "buffer_stats") {
|
|
47797
|
+
return { kind: "plumbing", plumbingKind: candidate, seq: maybeSeq ?? 0, ...ms !== void 0 ? { ms } : {} };
|
|
47798
|
+
}
|
|
47799
|
+
}
|
|
47800
|
+
return null;
|
|
47801
|
+
}
|
|
47802
|
+
|
|
47803
|
+
// src/bridge-log.ts
|
|
47804
|
+
var NOOP_LOGGER = {
|
|
47805
|
+
logIn() {
|
|
47806
|
+
},
|
|
47807
|
+
logOut() {
|
|
47808
|
+
},
|
|
47809
|
+
close() {
|
|
47810
|
+
}
|
|
47811
|
+
};
|
|
47812
|
+
var REDACT_DEPTH_CAP = 8;
|
|
47813
|
+
var IMAGE_DATA_URI_RE = /^(data:image\/[a-zA-Z0-9.+-]+;base64,)([A-Za-z0-9+/=]+)$/;
|
|
47814
|
+
function redactImageDataUri(value) {
|
|
47815
|
+
const m = value.match(IMAGE_DATA_URI_RE);
|
|
47816
|
+
if (!m) return value;
|
|
47817
|
+
const [, prefix, body] = m;
|
|
47818
|
+
if (prefix === void 0 || body === void 0) return value;
|
|
47819
|
+
return `${prefix}\u2026(${body.length} bytes)`;
|
|
47820
|
+
}
|
|
47821
|
+
function redactValue(value, depth, counter) {
|
|
47822
|
+
if (typeof value === "string") {
|
|
47823
|
+
const redacted = redact(redactImageDataUri(value));
|
|
47824
|
+
if (redacted !== value) counter.count += 1;
|
|
47825
|
+
return redacted;
|
|
47826
|
+
}
|
|
47827
|
+
if (value === null || typeof value !== "object") return value;
|
|
47828
|
+
if (depth >= REDACT_DEPTH_CAP) {
|
|
47829
|
+
try {
|
|
47830
|
+
const flattened = JSON.stringify(value);
|
|
47831
|
+
const redacted = redact(flattened);
|
|
47832
|
+
if (redacted !== flattened) counter.count += 1;
|
|
47833
|
+
return redacted;
|
|
47834
|
+
} catch {
|
|
47835
|
+
counter.count += 1;
|
|
47836
|
+
return REDACTED;
|
|
47837
|
+
}
|
|
47838
|
+
}
|
|
47839
|
+
if (Array.isArray(value)) return value.map((item) => redactValue(item, depth + 1, counter));
|
|
47840
|
+
const out = {};
|
|
47841
|
+
for (const [k, v] of Object.entries(value)) {
|
|
47842
|
+
out[k] = redactValue(v, depth + 1, counter);
|
|
47843
|
+
}
|
|
47844
|
+
return out;
|
|
47845
|
+
}
|
|
47846
|
+
function redactMessage(payload, opts) {
|
|
47847
|
+
const counter = { count: 0 };
|
|
47848
|
+
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
47849
|
+
const msg = payload;
|
|
47850
|
+
if (msg.type === "pairing-qr") {
|
|
47851
|
+
const clone2 = { ...msg };
|
|
47852
|
+
for (const key of ["payload", "svg"]) {
|
|
47853
|
+
if (typeof clone2[key] === "string") clone2[key] = `[REDACTED len=${clone2[key].length}]`;
|
|
47854
|
+
}
|
|
47855
|
+
return { payload: redactValue(clone2, 1, counter), redactedCount: counter.count };
|
|
47856
|
+
}
|
|
47857
|
+
if (!opts.includePrompts && msg.type === "turn" && typeof msg.message === "string") {
|
|
47858
|
+
return { payload: redactValue({ ...msg, message: "[prompt omitted]" }, 1, counter), redactedCount: counter.count };
|
|
47859
|
+
}
|
|
47860
|
+
}
|
|
47861
|
+
return { payload: redactValue(payload, 0, counter), redactedCount: counter.count };
|
|
47862
|
+
}
|
|
47863
|
+
function resolveBridgeLogEnabled(env = process.env) {
|
|
47864
|
+
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
|
|
47865
|
+
return !(raw === "0" || raw === "false");
|
|
47866
|
+
}
|
|
47867
|
+
function resolvePromptsEnabled(env) {
|
|
47868
|
+
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
|
|
47869
|
+
return !(raw === "0" || raw === "false");
|
|
47870
|
+
}
|
|
47871
|
+
function createBridgeLogger(stateDir, env = process.env) {
|
|
47872
|
+
if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
|
|
47873
|
+
const logsDir = (0, import_node_path16.join)(stateDir, "logs");
|
|
47874
|
+
try {
|
|
47875
|
+
(0, import_node_fs8.mkdirSync)(logsDir, { recursive: true });
|
|
47876
|
+
} catch {
|
|
47877
|
+
return NOOP_LOGGER;
|
|
47878
|
+
}
|
|
47879
|
+
const includePrompts = resolvePromptsEnabled(env);
|
|
47880
|
+
const fileFor = () => (0, import_node_path16.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
47881
|
+
const gainDay = (sessionId) => {
|
|
47882
|
+
const sessionsPath = (0, import_node_path16.join)(logsDir, ".sessions.json");
|
|
47883
|
+
let sessionsObj = {};
|
|
47884
|
+
try {
|
|
47885
|
+
const parsed = JSON.parse((0, import_node_fs8.readFileSync)(sessionsPath, "utf8"));
|
|
47886
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) sessionsObj = parsed;
|
|
47887
|
+
} catch {
|
|
47888
|
+
sessionsObj = {};
|
|
47889
|
+
}
|
|
47890
|
+
const day = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
47891
|
+
const idsToday = Array.isArray(sessionsObj[day]) ? sessionsObj[day] : [];
|
|
47892
|
+
if (idsToday.includes(sessionId)) return;
|
|
47893
|
+
sessionsObj[day] = [...idsToday, sessionId];
|
|
47894
|
+
const tmpPath = `${sessionsPath}.tmp`;
|
|
47895
|
+
(0, import_node_fs8.writeFileSync)(tmpPath, JSON.stringify(sessionsObj));
|
|
47896
|
+
(0, import_node_fs8.renameSync)(tmpPath, sessionsPath);
|
|
47897
|
+
};
|
|
47898
|
+
const write = (dir, rec) => {
|
|
47899
|
+
try {
|
|
47900
|
+
let projection = null;
|
|
47901
|
+
let projectionFailed = false;
|
|
47902
|
+
if (rec.sessionId !== null) {
|
|
47903
|
+
try {
|
|
47904
|
+
const built = buildProjection(rec.payload, rec.type, rec.ms, rec.telemetry);
|
|
47905
|
+
if (built) projection = { ...built, sessionId: rec.sessionId };
|
|
47906
|
+
} catch {
|
|
47907
|
+
projectionFailed = true;
|
|
47908
|
+
}
|
|
47909
|
+
}
|
|
47910
|
+
const { payload: redactedPayload, redactedCount } = redactMessage(rec.payload, { includePrompts });
|
|
47911
|
+
const line = JSON.stringify({
|
|
47912
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
47913
|
+
dir,
|
|
47914
|
+
spanId: rec.spanId,
|
|
47915
|
+
sessionId: rec.sessionId,
|
|
47916
|
+
type: rec.type,
|
|
47917
|
+
...rec.ms !== void 0 ? { ms: rec.ms } : {},
|
|
47918
|
+
payload: redactedPayload,
|
|
47919
|
+
redactedCount,
|
|
47920
|
+
projection,
|
|
47921
|
+
...projectionFailed ? { projectionFailed: true } : {}
|
|
47922
|
+
}) + "\n";
|
|
47923
|
+
(0, import_node_fs8.appendFileSync)(fileFor(), line);
|
|
47924
|
+
if (rec.sessionId !== null) gainDay(rec.sessionId);
|
|
47925
|
+
} catch {
|
|
47926
|
+
}
|
|
47927
|
+
};
|
|
47928
|
+
return {
|
|
47929
|
+
logIn: (rec) => write("in", rec),
|
|
47930
|
+
logOut: (rec) => write("out", rec),
|
|
47931
|
+
close() {
|
|
47932
|
+
}
|
|
47933
|
+
};
|
|
47934
|
+
}
|
|
47935
|
+
async function findSessionDays(stateDir, sessionId) {
|
|
47936
|
+
const sessionsPath = (0, import_node_path16.join)(stateDir, "logs", ".sessions.json");
|
|
47937
|
+
let sessionsObj;
|
|
47938
|
+
try {
|
|
47939
|
+
const parsed = JSON.parse(await (0, import_promises7.readFile)(sessionsPath, "utf8"));
|
|
47940
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return [];
|
|
47941
|
+
sessionsObj = parsed;
|
|
47942
|
+
} catch {
|
|
47943
|
+
return [];
|
|
47944
|
+
}
|
|
47945
|
+
const days = [];
|
|
47946
|
+
for (const [day, ids] of Object.entries(sessionsObj)) {
|
|
47947
|
+
if (Array.isArray(ids) && ids.includes(sessionId)) days.push(day);
|
|
47948
|
+
}
|
|
47949
|
+
return days;
|
|
47950
|
+
}
|
|
47951
|
+
|
|
47093
47952
|
// src/async-job-consumer.ts
|
|
47094
47953
|
var ASYNC_JOB_MAX_ATTEMPTS = 2;
|
|
47954
|
+
function ASYNC_UNOWNED_TTL_DAYS() {
|
|
47955
|
+
const raw = Number(process.env.MRRLIN_ASYNC_UNOWNED_TTL_DAYS);
|
|
47956
|
+
return Number.isFinite(raw) && raw > 0 ? raw : 7;
|
|
47957
|
+
}
|
|
47095
47958
|
async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
47959
|
+
const preClaimJob = await deps.client.getAsyncJob(projectSlug, jobId);
|
|
47960
|
+
if (!preClaimJob) return;
|
|
47961
|
+
const preClaimDescriptor = getAsyncToolDescriptor(preClaimJob.toolName);
|
|
47962
|
+
if (preClaimDescriptor?.locationDependent) {
|
|
47963
|
+
const owns = preClaimJob.directorSessionId != null && (await findSessionDays(deps.stateDir, preClaimJob.directorSessionId)).length > 0;
|
|
47964
|
+
if (!owns) {
|
|
47965
|
+
const ttlMs = ASYNC_UNOWNED_TTL_DAYS() * 24 * 60 * 60 * 1e3;
|
|
47966
|
+
const ageMs = Date.now() - new Date(preClaimJob.createdAt).getTime();
|
|
47967
|
+
if (ageMs > ttlMs) {
|
|
47968
|
+
const claimedToTerminate = await deps.client.claimAsyncJob(projectSlug, jobId);
|
|
47969
|
+
if (claimedToTerminate?.leaseId) {
|
|
47970
|
+
await deps.client.terminalizeAsyncJob(projectSlug, jobId, {
|
|
47971
|
+
leaseId: claimedToTerminate.leaseId,
|
|
47972
|
+
status: "failed",
|
|
47973
|
+
failureReason: "provider_unavailable",
|
|
47974
|
+
error: `No machine held the logs for directorSessionId=${String(preClaimJob.directorSessionId)} within MRRLIN_ASYNC_UNOWNED_TTL_DAYS`
|
|
47975
|
+
});
|
|
47976
|
+
}
|
|
47977
|
+
}
|
|
47978
|
+
return;
|
|
47979
|
+
}
|
|
47980
|
+
}
|
|
47096
47981
|
const claimed = await deps.client.claimAsyncJob(projectSlug, jobId);
|
|
47097
47982
|
if (!claimed || !claimed.leaseId) return;
|
|
47098
47983
|
const leaseId = claimed.leaseId;
|
|
@@ -47134,7 +48019,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
|
47134
48019
|
outcome = await deps.run(
|
|
47135
48020
|
"async",
|
|
47136
48021
|
() => descriptor2.run(
|
|
47137
|
-
{ client: deps.client, cwd: deps.cwd, codexExecutable: deps.codexExecutable, seat, projectSlug },
|
|
48022
|
+
{ client: deps.client, cwd: deps.cwd, codexExecutable: deps.codexExecutable, stateDir: deps.stateDir, seat, projectSlug },
|
|
47138
48023
|
input
|
|
47139
48024
|
)
|
|
47140
48025
|
);
|
|
@@ -47180,7 +48065,7 @@ async function driveAsyncJob(deps, projectSlug, jobId) {
|
|
|
47180
48065
|
const delivery = descriptor2.onComplete(outcome, input);
|
|
47181
48066
|
if (!delivery.suppressInbox) {
|
|
47182
48067
|
await deps.client.createInboxItem(projectSlug, {
|
|
47183
|
-
id: delivery.id ?? `II-${
|
|
48068
|
+
id: delivery.id ?? `II-${import_node_crypto7.default.randomUUID()}`,
|
|
47184
48069
|
kind: delivery.kind,
|
|
47185
48070
|
body: delivery.body,
|
|
47186
48071
|
...delivery.taskId ? { taskId: delivery.taskId } : {},
|
|
@@ -47198,13 +48083,13 @@ async function deriveRequestedHash(client, toolName, input) {
|
|
|
47198
48083
|
if (input.requestedHash) return input.requestedHash;
|
|
47199
48084
|
if (toolName === "run_spec_consensus" && input.pageId) {
|
|
47200
48085
|
const page = await client.getWikiPage(input.projectSlug, input.pageId);
|
|
47201
|
-
return page.contentHash ??
|
|
48086
|
+
return page.contentHash ?? import_node_crypto7.default.createHash("sha256").update(page.markdownBody).digest("hex");
|
|
47202
48087
|
}
|
|
47203
48088
|
if (toolName === "draft_task_spec" && input.taskId) {
|
|
47204
48089
|
const task = await client.getTask(input.projectSlug, input.taskId);
|
|
47205
|
-
return task.updatedAt ??
|
|
48090
|
+
return task.updatedAt ?? import_node_crypto7.default.createHash("sha256").update(JSON.stringify(task)).digest("hex");
|
|
47206
48091
|
}
|
|
47207
|
-
return
|
|
48092
|
+
return import_node_crypto7.default.createHash("sha256").update(JSON.stringify(input)).digest("hex");
|
|
47208
48093
|
}
|
|
47209
48094
|
async function runAsyncBackstopSweep(deps, drive = (slug, jobId) => driveAsyncJob(deps, slug, jobId)) {
|
|
47210
48095
|
const projects = await deps.client.listProjects();
|
|
@@ -47392,19 +48277,19 @@ function agentIdleMs(provider) {
|
|
|
47392
48277
|
}
|
|
47393
48278
|
|
|
47394
48279
|
// src/operator-token.ts
|
|
47395
|
-
var
|
|
48280
|
+
var import_node_fs9 = require("node:fs");
|
|
47396
48281
|
var import_node_os7 = __toESM(require("node:os"), 1);
|
|
47397
|
-
var
|
|
48282
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
47398
48283
|
function operatorDir() {
|
|
47399
|
-
const base = process.env.CODEX_HOME ?
|
|
48284
|
+
const base = process.env.CODEX_HOME ? import_node_path17.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path17.default.join(import_node_os7.default.homedir(), ".mrrlin");
|
|
47400
48285
|
return base;
|
|
47401
48286
|
}
|
|
47402
48287
|
function operatorTokenPath() {
|
|
47403
|
-
return
|
|
48288
|
+
return import_node_path17.default.join(operatorDir(), "operator-token");
|
|
47404
48289
|
}
|
|
47405
48290
|
function readOperatorToken() {
|
|
47406
48291
|
try {
|
|
47407
|
-
const token = (0,
|
|
48292
|
+
const token = (0, import_node_fs9.readFileSync)(operatorTokenPath(), "utf8").trim();
|
|
47408
48293
|
return token.length > 0 ? token : null;
|
|
47409
48294
|
} catch {
|
|
47410
48295
|
return null;
|
|
@@ -47412,24 +48297,24 @@ function readOperatorToken() {
|
|
|
47412
48297
|
}
|
|
47413
48298
|
function persistOperatorToken(token) {
|
|
47414
48299
|
const dir = operatorDir();
|
|
47415
|
-
(0,
|
|
47416
|
-
(0,
|
|
48300
|
+
(0, import_node_fs9.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
48301
|
+
(0, import_node_fs9.writeFileSync)(operatorTokenPath(), `${token.trim()}
|
|
47417
48302
|
`, { encoding: "utf8", mode: 384 });
|
|
47418
48303
|
}
|
|
47419
48304
|
function agentCredentialPath() {
|
|
47420
|
-
return
|
|
48305
|
+
return import_node_path17.default.join(operatorDir(), "agent-credential");
|
|
47421
48306
|
}
|
|
47422
48307
|
function persistAgentSecret(secret) {
|
|
47423
48308
|
const dir = operatorDir();
|
|
47424
|
-
(0,
|
|
47425
|
-
(0,
|
|
48309
|
+
(0, import_node_fs9.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
48310
|
+
(0, import_node_fs9.writeFileSync)(agentCredentialPath(), `${secret.trim()}
|
|
47426
48311
|
`, { encoding: "utf8", mode: 384 });
|
|
47427
48312
|
}
|
|
47428
48313
|
function readAgentSecret() {
|
|
47429
48314
|
const fromEnv = process.env.MRRLIN_AGENT_SECRET?.trim();
|
|
47430
48315
|
if (fromEnv) return fromEnv;
|
|
47431
48316
|
try {
|
|
47432
|
-
const raw = (0,
|
|
48317
|
+
const raw = (0, import_node_fs9.readFileSync)(agentCredentialPath(), "utf8").trim();
|
|
47433
48318
|
return raw || void 0;
|
|
47434
48319
|
} catch {
|
|
47435
48320
|
return void 0;
|
|
@@ -47437,16 +48322,16 @@ function readAgentSecret() {
|
|
|
47437
48322
|
}
|
|
47438
48323
|
|
|
47439
48324
|
// src/thread-index.ts
|
|
47440
|
-
var
|
|
47441
|
-
var
|
|
48325
|
+
var import_node_fs10 = require("node:fs");
|
|
48326
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
47442
48327
|
function threadIndexPath(stateDir) {
|
|
47443
|
-
return
|
|
48328
|
+
return import_node_path18.default.join(stateDir, "threads.json");
|
|
47444
48329
|
}
|
|
47445
48330
|
function loadThreadIndex(stateDir, ttlMs, now) {
|
|
47446
48331
|
const result = /* @__PURE__ */ new Map();
|
|
47447
48332
|
let parsed;
|
|
47448
48333
|
try {
|
|
47449
|
-
parsed = JSON.parse((0,
|
|
48334
|
+
parsed = JSON.parse((0, import_node_fs10.readFileSync)(threadIndexPath(stateDir), "utf8"));
|
|
47450
48335
|
} catch {
|
|
47451
48336
|
return result;
|
|
47452
48337
|
}
|
|
@@ -47469,8 +48354,8 @@ function loadThreadIndex(stateDir, ttlMs, now) {
|
|
|
47469
48354
|
return result;
|
|
47470
48355
|
}
|
|
47471
48356
|
function saveThreadIndex(stateDir, entries) {
|
|
47472
|
-
(0,
|
|
47473
|
-
(0,
|
|
48357
|
+
(0, import_node_fs10.mkdirSync)(stateDir, { recursive: true, mode: 448 });
|
|
48358
|
+
(0, import_node_fs10.writeFileSync)(threadIndexPath(stateDir), `${JSON.stringify(Object.fromEntries(entries), null, 2)}
|
|
47474
48359
|
`, {
|
|
47475
48360
|
encoding: "utf8",
|
|
47476
48361
|
mode: 384
|
|
@@ -47605,10 +48490,10 @@ function createToolBusyClock(opts) {
|
|
|
47605
48490
|
}
|
|
47606
48491
|
|
|
47607
48492
|
// src/worker-token.ts
|
|
47608
|
-
var
|
|
47609
|
-
var
|
|
48493
|
+
var import_node_crypto8 = require("node:crypto");
|
|
48494
|
+
var import_node_fs11 = require("node:fs");
|
|
47610
48495
|
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
47611
|
-
var
|
|
48496
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
47612
48497
|
var DEFAULT_WORKER_PORT = 8792;
|
|
47613
48498
|
function workerPort() {
|
|
47614
48499
|
const raw = process.env.MRRLIN_WORKER_PORT;
|
|
@@ -47617,15 +48502,15 @@ function workerPort() {
|
|
|
47617
48502
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
|
|
47618
48503
|
}
|
|
47619
48504
|
function workerDir() {
|
|
47620
|
-
const base = process.env.CODEX_HOME ?
|
|
47621
|
-
return
|
|
48505
|
+
const base = process.env.CODEX_HOME ? import_node_path19.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path19.default.join(import_node_os8.default.homedir(), ".mrrlin");
|
|
48506
|
+
return import_node_path19.default.join(base, "worker");
|
|
47622
48507
|
}
|
|
47623
48508
|
function workerTokenPath() {
|
|
47624
|
-
return
|
|
48509
|
+
return import_node_path19.default.join(workerDir(), "token");
|
|
47625
48510
|
}
|
|
47626
48511
|
function readWorkerToken() {
|
|
47627
48512
|
try {
|
|
47628
|
-
const token = (0,
|
|
48513
|
+
const token = (0, import_node_fs11.readFileSync)(workerTokenPath(), "utf8").trim();
|
|
47629
48514
|
return token.length > 0 ? token : null;
|
|
47630
48515
|
} catch {
|
|
47631
48516
|
return null;
|
|
@@ -47635,18 +48520,18 @@ function readOrCreateWorkerToken() {
|
|
|
47635
48520
|
const existing = readWorkerToken();
|
|
47636
48521
|
if (existing) return existing;
|
|
47637
48522
|
const dir = workerDir();
|
|
47638
|
-
(0,
|
|
47639
|
-
const token = (0,
|
|
47640
|
-
(0,
|
|
48523
|
+
(0, import_node_fs11.mkdirSync)(dir, { recursive: true, mode: 448 });
|
|
48524
|
+
const token = (0, import_node_crypto8.randomBytes)(32).toString("hex");
|
|
48525
|
+
(0, import_node_fs11.writeFileSync)(workerTokenPath(), `${token}
|
|
47641
48526
|
`, { encoding: "utf8", mode: 384 });
|
|
47642
48527
|
return token;
|
|
47643
48528
|
}
|
|
47644
48529
|
|
|
47645
48530
|
// src/remote-phone-relay.ts
|
|
47646
48531
|
var import_node_events2 = require("node:events");
|
|
47647
|
-
var
|
|
48532
|
+
var import_node_fs12 = require("node:fs");
|
|
47648
48533
|
var import_node_os9 = require("node:os");
|
|
47649
|
-
var
|
|
48534
|
+
var import_node_path20 = require("node:path");
|
|
47650
48535
|
|
|
47651
48536
|
// ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
|
|
47652
48537
|
var nc = __toESM(require("node:crypto"), 1);
|
|
@@ -51217,9 +52102,9 @@ var DirectorRelay = class {
|
|
|
51217
52102
|
|
|
51218
52103
|
// src/remote-phone-relay.ts
|
|
51219
52104
|
function loadOrCreateAgentDeviceKey() {
|
|
51220
|
-
const
|
|
52105
|
+
const path22 = (0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-device-key");
|
|
51221
52106
|
try {
|
|
51222
|
-
const raw = JSON.parse((0,
|
|
52107
|
+
const raw = JSON.parse((0, import_node_fs12.readFileSync)(path22, "utf8"));
|
|
51223
52108
|
if (typeof raw.priv === "string" && typeof raw.pub === "string") {
|
|
51224
52109
|
return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
|
|
51225
52110
|
}
|
|
@@ -51227,9 +52112,9 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
51227
52112
|
}
|
|
51228
52113
|
const kp = generateIdentityKeyPair();
|
|
51229
52114
|
try {
|
|
51230
|
-
(0,
|
|
51231
|
-
(0,
|
|
51232
|
-
|
|
52115
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
|
|
52116
|
+
(0, import_node_fs12.writeFileSync)(
|
|
52117
|
+
path22,
|
|
51233
52118
|
JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
|
|
51234
52119
|
{ mode: 384 }
|
|
51235
52120
|
);
|
|
@@ -51237,10 +52122,10 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
51237
52122
|
}
|
|
51238
52123
|
return kp;
|
|
51239
52124
|
}
|
|
51240
|
-
var AGENT_PAIRING_PATH = (0,
|
|
52125
|
+
var AGENT_PAIRING_PATH = (0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin", "agent-pairing.json");
|
|
51241
52126
|
function loadAgentPairing() {
|
|
51242
52127
|
try {
|
|
51243
|
-
const raw = JSON.parse((0,
|
|
52128
|
+
const raw = JSON.parse((0, import_node_fs12.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
|
|
51244
52129
|
if (typeof raw.channelId === "string" && typeof raw.agentControlSecret === "string" && typeof raw.relayAuth === "string" && typeof raw.peerIdentityKey === "string") {
|
|
51245
52130
|
return {
|
|
51246
52131
|
channelId: raw.channelId,
|
|
@@ -51255,8 +52140,8 @@ function loadAgentPairing() {
|
|
|
51255
52140
|
}
|
|
51256
52141
|
function saveAgentPairing(record2) {
|
|
51257
52142
|
try {
|
|
51258
|
-
(0,
|
|
51259
|
-
(0,
|
|
52143
|
+
(0, import_node_fs12.mkdirSync)((0, import_node_path20.join)((0, import_node_os9.homedir)(), ".mrrlin"), { recursive: true });
|
|
52144
|
+
(0, import_node_fs12.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
|
|
51260
52145
|
} catch {
|
|
51261
52146
|
}
|
|
51262
52147
|
}
|
|
@@ -51433,18 +52318,18 @@ async function renderPairingQrSvg(payload) {
|
|
|
51433
52318
|
}
|
|
51434
52319
|
|
|
51435
52320
|
// src/checkout-registry.ts
|
|
51436
|
-
var
|
|
51437
|
-
var
|
|
52321
|
+
var import_node_fs13 = require("node:fs");
|
|
52322
|
+
var import_node_path21 = require("node:path");
|
|
51438
52323
|
var CheckoutRegistry = class {
|
|
51439
52324
|
file;
|
|
51440
52325
|
constructor(stateDir) {
|
|
51441
|
-
this.file = (0,
|
|
51442
|
-
(0,
|
|
52326
|
+
this.file = (0, import_node_path21.join)(stateDir, "checkouts.json");
|
|
52327
|
+
(0, import_node_fs13.mkdirSync)(stateDir, { recursive: true });
|
|
51443
52328
|
}
|
|
51444
52329
|
read() {
|
|
51445
|
-
if (!(0,
|
|
52330
|
+
if (!(0, import_node_fs13.existsSync)(this.file)) return {};
|
|
51446
52331
|
try {
|
|
51447
|
-
return JSON.parse((0,
|
|
52332
|
+
return JSON.parse((0, import_node_fs13.readFileSync)(this.file, "utf8"));
|
|
51448
52333
|
} catch {
|
|
51449
52334
|
return {};
|
|
51450
52335
|
}
|
|
@@ -51452,16 +52337,16 @@ var CheckoutRegistry = class {
|
|
|
51452
52337
|
get(slug) {
|
|
51453
52338
|
return this.read()[slug] ?? null;
|
|
51454
52339
|
}
|
|
51455
|
-
confirm(slug,
|
|
52340
|
+
confirm(slug, path22, now) {
|
|
51456
52341
|
const all = this.read();
|
|
51457
|
-
all[slug] = { path:
|
|
51458
|
-
(0,
|
|
52342
|
+
all[slug] = { path: path22, confirmedAt: now };
|
|
52343
|
+
(0, import_node_fs13.writeFileSync)(this.file, JSON.stringify(all, null, 2));
|
|
51459
52344
|
}
|
|
51460
52345
|
};
|
|
51461
52346
|
|
|
51462
52347
|
// src/checkout-handlers.ts
|
|
51463
52348
|
var import_node_child_process13 = require("node:child_process");
|
|
51464
|
-
var
|
|
52349
|
+
var import_node_fs14 = require("node:fs");
|
|
51465
52350
|
|
|
51466
52351
|
// src/git-remote-match.ts
|
|
51467
52352
|
function normalizeRemote(url2) {
|
|
@@ -51496,7 +52381,7 @@ function validateCheckoutPath(checkoutPath, repo) {
|
|
|
51496
52381
|
}
|
|
51497
52382
|
let resolvedPath;
|
|
51498
52383
|
try {
|
|
51499
|
-
resolvedPath = (0,
|
|
52384
|
+
resolvedPath = (0, import_node_fs14.realpathSync)(trimmedPath);
|
|
51500
52385
|
} catch {
|
|
51501
52386
|
return {
|
|
51502
52387
|
ok: false,
|
|
@@ -51801,131 +52686,13 @@ function extractVerificationSection(markdown) {
|
|
|
51801
52686
|
return body.length > 0 ? body : null;
|
|
51802
52687
|
}
|
|
51803
52688
|
|
|
51804
|
-
// src/bridge-log.ts
|
|
51805
|
-
var import_node_fs14 = require("node:fs");
|
|
51806
|
-
var import_node_path18 = require("node:path");
|
|
51807
|
-
|
|
51808
|
-
// src/redact.ts
|
|
51809
|
-
var REDACTED = "[REDACTED]";
|
|
51810
|
-
var SECRET_PATTERNS = [
|
|
51811
|
-
/ghp_[A-Za-z0-9]{20,}/g,
|
|
51812
|
-
// GitHub personal access token (classic)
|
|
51813
|
-
/github_pat_[A-Za-z0-9_]{20,}/g,
|
|
51814
|
-
// GitHub fine-grained PAT
|
|
51815
|
-
/\bBearer\s+[A-Za-z0-9._~+/-]+=*/gi,
|
|
51816
|
-
// Authorization: Bearer <token>
|
|
51817
|
-
/\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
|
|
51818
|
-
// JWT (header.payload.signature)
|
|
51819
|
-
/\b[A-Fa-f0-9]{32,}\b/g,
|
|
51820
|
-
// long hex run (hashes, hex secrets)
|
|
51821
|
-
/\b[A-Za-z0-9+/]{40,}={0,2}\b/g
|
|
51822
|
-
// long base64-ish run (opaque tokens)
|
|
51823
|
-
];
|
|
51824
|
-
function redact(input) {
|
|
51825
|
-
let out = input;
|
|
51826
|
-
for (const re of SECRET_PATTERNS) out = out.replace(re, REDACTED);
|
|
51827
|
-
return out;
|
|
51828
|
-
}
|
|
51829
|
-
|
|
51830
|
-
// src/bridge-log.ts
|
|
51831
|
-
var NOOP_LOGGER = {
|
|
51832
|
-
logIn() {
|
|
51833
|
-
},
|
|
51834
|
-
logOut() {
|
|
51835
|
-
},
|
|
51836
|
-
close() {
|
|
51837
|
-
}
|
|
51838
|
-
};
|
|
51839
|
-
var REDACT_DEPTH_CAP = 8;
|
|
51840
|
-
var IMAGE_DATA_URI_RE = /^(data:image\/[a-zA-Z0-9.+-]+;base64,)([A-Za-z0-9+/=]+)$/;
|
|
51841
|
-
function redactImageDataUri(value) {
|
|
51842
|
-
const m = value.match(IMAGE_DATA_URI_RE);
|
|
51843
|
-
if (!m) return value;
|
|
51844
|
-
const [, prefix, body] = m;
|
|
51845
|
-
if (prefix === void 0 || body === void 0) return value;
|
|
51846
|
-
return `${prefix}\u2026(${body.length} bytes)`;
|
|
51847
|
-
}
|
|
51848
|
-
function redactValue(value, depth) {
|
|
51849
|
-
if (typeof value === "string") return redact(redactImageDataUri(value));
|
|
51850
|
-
if (value === null || typeof value !== "object") return value;
|
|
51851
|
-
if (depth >= REDACT_DEPTH_CAP) {
|
|
51852
|
-
try {
|
|
51853
|
-
return redact(JSON.stringify(value));
|
|
51854
|
-
} catch {
|
|
51855
|
-
return REDACTED;
|
|
51856
|
-
}
|
|
51857
|
-
}
|
|
51858
|
-
if (Array.isArray(value)) return value.map((item) => redactValue(item, depth + 1));
|
|
51859
|
-
const out = {};
|
|
51860
|
-
for (const [k, v] of Object.entries(value)) {
|
|
51861
|
-
out[k] = redactValue(v, depth + 1);
|
|
51862
|
-
}
|
|
51863
|
-
return out;
|
|
51864
|
-
}
|
|
51865
|
-
function redactMessage(payload, opts) {
|
|
51866
|
-
if (payload && typeof payload === "object" && !Array.isArray(payload)) {
|
|
51867
|
-
const msg = payload;
|
|
51868
|
-
if (msg.type === "pairing-qr") {
|
|
51869
|
-
const clone2 = { ...msg };
|
|
51870
|
-
for (const key of ["payload", "svg"]) {
|
|
51871
|
-
if (typeof clone2[key] === "string") clone2[key] = `[REDACTED len=${clone2[key].length}]`;
|
|
51872
|
-
}
|
|
51873
|
-
return redactValue(clone2, 1);
|
|
51874
|
-
}
|
|
51875
|
-
if (!opts.includePrompts && msg.type === "turn" && typeof msg.message === "string") {
|
|
51876
|
-
return redactValue({ ...msg, message: "[prompt omitted]" }, 1);
|
|
51877
|
-
}
|
|
51878
|
-
}
|
|
51879
|
-
return redactValue(payload, 0);
|
|
51880
|
-
}
|
|
51881
|
-
function resolveBridgeLogEnabled(env = process.env) {
|
|
51882
|
-
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG ?? "").trim().toLowerCase();
|
|
51883
|
-
return !(raw === "0" || raw === "false");
|
|
51884
|
-
}
|
|
51885
|
-
function resolvePromptsEnabled(env) {
|
|
51886
|
-
const raw = (env.MRRLIN_DIRECTOR_BRIDGE_LOG_PROMPTS ?? "").trim().toLowerCase();
|
|
51887
|
-
return !(raw === "0" || raw === "false");
|
|
51888
|
-
}
|
|
51889
|
-
function createBridgeLogger(stateDir, env = process.env) {
|
|
51890
|
-
if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
|
|
51891
|
-
const logsDir = (0, import_node_path18.join)(stateDir, "logs");
|
|
51892
|
-
try {
|
|
51893
|
-
(0, import_node_fs14.mkdirSync)(logsDir, { recursive: true });
|
|
51894
|
-
} catch {
|
|
51895
|
-
return NOOP_LOGGER;
|
|
51896
|
-
}
|
|
51897
|
-
const includePrompts = resolvePromptsEnabled(env);
|
|
51898
|
-
const fileFor = () => (0, import_node_path18.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
51899
|
-
const write = (dir, rec) => {
|
|
51900
|
-
try {
|
|
51901
|
-
const line = JSON.stringify({
|
|
51902
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
51903
|
-
dir,
|
|
51904
|
-
spanId: rec.spanId,
|
|
51905
|
-
sessionId: rec.sessionId,
|
|
51906
|
-
type: rec.type,
|
|
51907
|
-
...rec.ms !== void 0 ? { ms: rec.ms } : {},
|
|
51908
|
-
payload: redactMessage(rec.payload, { includePrompts })
|
|
51909
|
-
}) + "\n";
|
|
51910
|
-
(0, import_node_fs14.appendFileSync)(fileFor(), line);
|
|
51911
|
-
} catch {
|
|
51912
|
-
}
|
|
51913
|
-
};
|
|
51914
|
-
return {
|
|
51915
|
-
logIn: (rec) => write("in", rec),
|
|
51916
|
-
logOut: (rec) => write("out", rec),
|
|
51917
|
-
close() {
|
|
51918
|
-
}
|
|
51919
|
-
};
|
|
51920
|
-
}
|
|
51921
|
-
|
|
51922
52689
|
// src/external-agents-scrub.ts
|
|
51923
52690
|
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
51924
52691
|
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
51925
|
-
var
|
|
52692
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
51926
52693
|
var REDACTION = "[REDACTED]";
|
|
51927
52694
|
var SHORT_VALUE_THRESHOLD = 8;
|
|
51928
|
-
var KEYS_ENV_PATH = () =>
|
|
52695
|
+
var KEYS_ENV_PATH = () => import_node_path22.default.join(import_node_os10.default.homedir(), ".local", "state", "external-agents", "keys.env");
|
|
51929
52696
|
var keysEnvCache = null;
|
|
51930
52697
|
function readKeysEnv() {
|
|
51931
52698
|
const filePath = KEYS_ENV_PATH();
|
|
@@ -52346,9 +53113,9 @@ function readKnownGptSlugsFromTomlFile(filePath) {
|
|
|
52346
53113
|
return Array.from(raw.matchAll(/^\s*model\s*=\s*"([^"]+)"/gm)).map((match) => match[1]?.trim() ?? "").filter(isSelectableModelSlug);
|
|
52347
53114
|
}
|
|
52348
53115
|
function readCodexFallbackModels() {
|
|
52349
|
-
const codexHome = process.env.CODEX_HOME?.trim() ||
|
|
53116
|
+
const codexHome = process.env.CODEX_HOME?.trim() || import_node_path23.default.join(import_node_os11.default.homedir(), ".codex");
|
|
52350
53117
|
const models = /* @__PURE__ */ new Map();
|
|
52351
|
-
const cachePath =
|
|
53118
|
+
const cachePath = import_node_path23.default.join(codexHome, "models_cache.json");
|
|
52352
53119
|
const cacheRaw = readTextIfExists(cachePath);
|
|
52353
53120
|
if (cacheRaw) {
|
|
52354
53121
|
try {
|
|
@@ -52398,7 +53165,7 @@ function readCodexFallbackModels() {
|
|
|
52398
53165
|
);
|
|
52399
53166
|
}
|
|
52400
53167
|
}
|
|
52401
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53168
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path23.default.join(codexHome, "config.toml"))) {
|
|
52402
53169
|
addBridgeModel(
|
|
52403
53170
|
models,
|
|
52404
53171
|
mapBridgeModel({
|
|
@@ -52412,11 +53179,11 @@ function readCodexFallbackModels() {
|
|
|
52412
53179
|
})
|
|
52413
53180
|
);
|
|
52414
53181
|
}
|
|
52415
|
-
const automationsDir =
|
|
53182
|
+
const automationsDir = import_node_path23.default.join(codexHome, "automations");
|
|
52416
53183
|
try {
|
|
52417
53184
|
for (const entry of import_node_fs16.default.readdirSync(automationsDir, { withFileTypes: true })) {
|
|
52418
53185
|
if (!entry.isDirectory()) continue;
|
|
52419
|
-
for (const slug of readKnownGptSlugsFromTomlFile(
|
|
53186
|
+
for (const slug of readKnownGptSlugsFromTomlFile(import_node_path23.default.join(automationsDir, entry.name, "automation.toml"))) {
|
|
52420
53187
|
addBridgeModel(
|
|
52421
53188
|
models,
|
|
52422
53189
|
mapBridgeModel({
|
|
@@ -52436,7 +53203,7 @@ function readCodexFallbackModels() {
|
|
|
52436
53203
|
return [...models.values()];
|
|
52437
53204
|
}
|
|
52438
53205
|
function neutralCheckoutCwd(stateDir) {
|
|
52439
|
-
const dir =
|
|
53206
|
+
const dir = import_node_path23.default.join(stateDir, "no-checkout");
|
|
52440
53207
|
try {
|
|
52441
53208
|
import_node_fs16.default.mkdirSync(dir, { recursive: true });
|
|
52442
53209
|
} catch {
|
|
@@ -52906,8 +53673,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
52906
53673
|
}
|
|
52907
53674
|
}
|
|
52908
53675
|
function readStateDir() {
|
|
52909
|
-
if (process.env.CODEX_HOME) return
|
|
52910
|
-
return
|
|
53676
|
+
if (process.env.CODEX_HOME) return import_node_path23.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
53677
|
+
return import_node_path23.default.join(import_node_os11.default.homedir(), ".mrrlin", "director-bridge");
|
|
52911
53678
|
}
|
|
52912
53679
|
function readAllowedOrigins() {
|
|
52913
53680
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -52982,7 +53749,7 @@ function createBridgeRequestListener(opts) {
|
|
|
52982
53749
|
res.end(JSON.stringify({ ok: false, error: "Origin not allowed." }));
|
|
52983
53750
|
return;
|
|
52984
53751
|
}
|
|
52985
|
-
const nonce =
|
|
53752
|
+
const nonce = import_node_crypto9.default.randomBytes(16).toString("base64url");
|
|
52986
53753
|
res.writeHead(200, { "content-type": "application/json" });
|
|
52987
53754
|
res.end(JSON.stringify({ ok: true, wsUrl: `ws://${host}:${port}/ws`, token, nonce }));
|
|
52988
53755
|
return;
|
|
@@ -53033,7 +53800,11 @@ function attachBridgeWss(server, opts) {
|
|
|
53033
53800
|
sessionId: sessionIdOf(msg),
|
|
53034
53801
|
type: msg.type,
|
|
53035
53802
|
ms: span.at ? Date.now() - span.at : void 0,
|
|
53036
|
-
payload: msg
|
|
53803
|
+
payload: msg,
|
|
53804
|
+
// send() is generic across every OutgoingMessage variant; only the "event" variant ever
|
|
53805
|
+
// carries telemetry (task 4.5), so this is simply undefined — and omitted by BridgeLogRecordInput's
|
|
53806
|
+
// optional telemetry? — for every other message type.
|
|
53807
|
+
telemetry: msg.telemetry
|
|
53037
53808
|
});
|
|
53038
53809
|
socket.send(JSON.stringify(msg));
|
|
53039
53810
|
};
|
|
@@ -53097,6 +53868,20 @@ function attachSeqMetadata(msg, seq, turnId) {
|
|
|
53097
53868
|
}
|
|
53098
53869
|
return msg;
|
|
53099
53870
|
}
|
|
53871
|
+
function describeZeroOutputLimit(signal) {
|
|
53872
|
+
if (!signal) {
|
|
53873
|
+
return {
|
|
53874
|
+
message: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan.",
|
|
53875
|
+
reason: "Director turn completed without output; Codex likely hit its usage or credits limit.",
|
|
53876
|
+
resetAt: null
|
|
53877
|
+
};
|
|
53878
|
+
}
|
|
53879
|
+
return {
|
|
53880
|
+
message: signal.resetAt ? `Director turn completed without any output \u2014 Codex's usage/credits limit is exhausted; it resets at ${signal.resetAt}.` : "Director turn completed without any output \u2014 Codex's usage/credits limit is exhausted (no reset time reported).",
|
|
53881
|
+
reason: "Codex provider limit exhausted during a Director turn.",
|
|
53882
|
+
resetAt: signal.resetAt
|
|
53883
|
+
};
|
|
53884
|
+
}
|
|
53100
53885
|
function createBridgeMessageHandler(deps) {
|
|
53101
53886
|
const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
|
|
53102
53887
|
const pendingTurnSessions = /* @__PURE__ */ new Set();
|
|
@@ -53263,7 +54048,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
53263
54048
|
}
|
|
53264
54049
|
}
|
|
53265
54050
|
socket.on("message", async (data) => {
|
|
53266
|
-
const spanId =
|
|
54051
|
+
const spanId = import_node_crypto9.default.randomUUID();
|
|
53267
54052
|
if (logCtx) {
|
|
53268
54053
|
logCtx.span.id = spanId;
|
|
53269
54054
|
logCtx.span.at = Date.now();
|
|
@@ -53785,7 +54570,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
53785
54570
|
thread.inFlight = true;
|
|
53786
54571
|
pendingTurnSessions.delete(directorSessionId);
|
|
53787
54572
|
thread.replay = createReplayBuffer({
|
|
53788
|
-
turnId: (0,
|
|
54573
|
+
turnId: (0, import_node_crypto9.randomUUID)(),
|
|
53789
54574
|
spanId,
|
|
53790
54575
|
...deps.retentionMs !== void 0 ? { retentionMs: deps.retentionMs } : {},
|
|
53791
54576
|
...deps.ackLingerMs !== void 0 ? { ackLingerMs: deps.ackLingerMs } : {}
|
|
@@ -53860,6 +54645,9 @@ function createBridgeMessageHandler(deps) {
|
|
|
53860
54645
|
rejectTurn = (error51) => reject(error51);
|
|
53861
54646
|
});
|
|
53862
54647
|
let outputEvents = 0;
|
|
54648
|
+
let exhaustedLimitSignal = null;
|
|
54649
|
+
let turnTokenUsage = null;
|
|
54650
|
+
let promptBytes = 0;
|
|
53863
54651
|
const deferredResults = [];
|
|
53864
54652
|
let pokeActivity = () => {
|
|
53865
54653
|
};
|
|
@@ -53869,7 +54657,12 @@ function createBridgeMessageHandler(deps) {
|
|
|
53869
54657
|
deferredResults.push(event);
|
|
53870
54658
|
return;
|
|
53871
54659
|
}
|
|
53872
|
-
if (event.type === "
|
|
54660
|
+
if (event.type === "token_usage") {
|
|
54661
|
+
const usage = event.usage;
|
|
54662
|
+
turnTokenUsage = addTurnTokenUsage(turnTokenUsage, usage);
|
|
54663
|
+
return;
|
|
54664
|
+
}
|
|
54665
|
+
if (event.type === "turn_completed" || event.type === "rate_limits") {
|
|
53873
54666
|
return;
|
|
53874
54667
|
}
|
|
53875
54668
|
outputEvents += 1;
|
|
@@ -53888,6 +54681,7 @@ function createBridgeMessageHandler(deps) {
|
|
|
53888
54681
|
sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: event.snapshot });
|
|
53889
54682
|
}
|
|
53890
54683
|
const signal = detectExhaustedProviderLimit(event.snapshot, Date.now());
|
|
54684
|
+
exhaustedLimitSignal = signal;
|
|
53891
54685
|
if (signal) {
|
|
53892
54686
|
deps.reportLimitPause?.("Codex provider limit exhausted during a Director turn.", signal.resetAt);
|
|
53893
54687
|
}
|
|
@@ -53968,6 +54762,7 @@ ${contextPrefix}` : updateOffer : contextPrefix;
|
|
|
53968
54762
|
const composed = composedPrefix ? `${composedPrefix}
|
|
53969
54763
|
|
|
53970
54764
|
${effectiveText}` : effectiveText;
|
|
54765
|
+
promptBytes = Buffer.byteLength(composed, "utf8");
|
|
53971
54766
|
turnInput.push({ type: "text", text: composed, text_elements: [] });
|
|
53972
54767
|
}
|
|
53973
54768
|
if (imageDataUri) {
|
|
@@ -53983,18 +54778,17 @@ ${effectiveText}` : effectiveText;
|
|
|
53983
54778
|
await Promise.race([runSequence, watchdogExpired]);
|
|
53984
54779
|
deps.setCodexAuth?.("ok");
|
|
53985
54780
|
if (outputEvents === 0) {
|
|
53986
|
-
|
|
53987
|
-
|
|
53988
|
-
null
|
|
53989
|
-
);
|
|
54781
|
+
const zeroOutputLimit = describeZeroOutputLimit(exhaustedLimitSignal);
|
|
54782
|
+
deps.reportLimitPause?.(zeroOutputLimit.reason, zeroOutputLimit.resetAt);
|
|
53990
54783
|
sendInTurn({
|
|
53991
54784
|
type: "error",
|
|
53992
54785
|
directorSessionId,
|
|
53993
|
-
error:
|
|
54786
|
+
error: zeroOutputLimit.message
|
|
53994
54787
|
});
|
|
53995
54788
|
}
|
|
54789
|
+
const telemetry = turnTokenUsage !== null ? { promptBytes, usage: turnTokenUsage } : void 0;
|
|
53996
54790
|
for (const event of deferredResults) {
|
|
53997
|
-
sendInTurn({ type: "event", directorSessionId, event });
|
|
54791
|
+
sendInTurn({ type: "event", directorSessionId, event, telemetry });
|
|
53998
54792
|
}
|
|
53999
54793
|
} finally {
|
|
54000
54794
|
if (thread.replay && (thread.replay.state === "live" || thread.replay.state === "detached")) {
|
|
@@ -54130,6 +54924,9 @@ function scanForOtherBridges() {
|
|
|
54130
54924
|
}
|
|
54131
54925
|
async function startDirectorBridge() {
|
|
54132
54926
|
const config2 = parseConfig();
|
|
54927
|
+
if (!process.env.MRRLIN_TELEMETRY_DEFAULT_PROJECT?.trim()) {
|
|
54928
|
+
throw new Error("MRRLIN_TELEMETRY_DEFAULT_PROJECT must be set (non-empty) at bridge startup.");
|
|
54929
|
+
}
|
|
54133
54930
|
const turnLock = createTurnLock();
|
|
54134
54931
|
let lastTurnEndedAt = Date.now();
|
|
54135
54932
|
const wrappedTurnLock = {
|
|
@@ -54266,8 +55063,8 @@ async function startDirectorBridge() {
|
|
|
54266
55063
|
codexCwd: config2.codexCwd,
|
|
54267
55064
|
codexExecutable: config2.codexExecutable,
|
|
54268
55065
|
checkoutRegistry,
|
|
54269
|
-
worktreeRoot:
|
|
54270
|
-
locksDir:
|
|
55066
|
+
worktreeRoot: import_node_path23.default.join(config2.stateDir, "worktrees"),
|
|
55067
|
+
locksDir: import_node_path23.default.join(config2.stateDir, "locks"),
|
|
54271
55068
|
// Wire the executor server for code-execution runs. Each run gets its own provider process
|
|
54272
55069
|
// (app-server for codex, a resident CLI child for claude) at the run worktree, running
|
|
54273
55070
|
// UNRESTRICTED from the real operator config (owner no-sandbox decision — auth + mrrlin MCP
|
|
@@ -54311,7 +55108,7 @@ async function startDirectorBridge() {
|
|
|
54311
55108
|
// egressDomains is retained in the seam signature (verification-turn.ts still computes the
|
|
54312
55109
|
// env host) but no longer constrains anything — the executor is unrestricted.
|
|
54313
55110
|
startSandbox: async (_egressDomains, providerId) => {
|
|
54314
|
-
const cwd = import_node_fs16.default.mkdtempSync(
|
|
55111
|
+
const cwd = import_node_fs16.default.mkdtempSync(import_node_path23.default.join(import_node_os11.default.tmpdir(), "mrrlin-verify-"));
|
|
54315
55112
|
let executor;
|
|
54316
55113
|
try {
|
|
54317
55114
|
executor = await startExecutorServer({ worktree: cwd, provider: providerId });
|
|
@@ -54356,12 +55153,13 @@ async function startDirectorBridge() {
|
|
|
54356
55153
|
};
|
|
54357
55154
|
const sessionSinks = createSessionSinkRegistry();
|
|
54358
55155
|
const tombstones = /* @__PURE__ */ new Map();
|
|
54359
|
-
const bridgeInstanceId = (0,
|
|
55156
|
+
const bridgeInstanceId = (0, import_node_crypto9.randomUUID)();
|
|
54360
55157
|
const asyncConsumerDeps = {
|
|
54361
55158
|
client,
|
|
54362
55159
|
run: wrappedTurnLock.run,
|
|
54363
55160
|
cwd: config2.codexCwd ?? process.cwd(),
|
|
54364
55161
|
codexExecutable: config2.codexExecutable,
|
|
55162
|
+
stateDir: config2.stateDir,
|
|
54365
55163
|
staleSeconds,
|
|
54366
55164
|
touchIntervalMs: Math.min(DEFAULT_TOUCH_INTERVAL_MS, Math.floor(staleSeconds * 1e3 / 2)),
|
|
54367
55165
|
wake: (slug, directorSessionId, body, deliveryKind) => {
|
|
@@ -54511,7 +55309,7 @@ async function startDirectorBridge() {
|
|
|
54511
55309
|
fileUpdateInboxItem: async (projectSlug) => {
|
|
54512
55310
|
const body = selfUpdateHandle.updateInboxBody();
|
|
54513
55311
|
if (!body) return;
|
|
54514
|
-
const id = `II-MCPUPD-${(0,
|
|
55312
|
+
const id = `II-MCPUPD-${(0, import_node_crypto9.randomUUID)()}`;
|
|
54515
55313
|
try {
|
|
54516
55314
|
const row = await client.createInboxItem(projectSlug, { id, kind: "info", body });
|
|
54517
55315
|
process.stderr.write(
|
|
@@ -54541,7 +55339,7 @@ async function startDirectorBridge() {
|
|
|
54541
55339
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
54542
55340
|
let bridgeBinShaShort = "unknown00000";
|
|
54543
55341
|
try {
|
|
54544
|
-
bridgeBinShaShort =
|
|
55342
|
+
bridgeBinShaShort = import_node_crypto9.default.createHash("sha256").update(import_node_fs16.default.readFileSync(process.argv[1] ?? "")).digest("hex").slice(0, 12);
|
|
54545
55343
|
} catch {
|
|
54546
55344
|
}
|
|
54547
55345
|
attachBridgeWss(server, {
|
|
@@ -54628,7 +55426,10 @@ async function startDirectorBridge() {
|
|
|
54628
55426
|
dispatchServer.on("error", reject);
|
|
54629
55427
|
dispatchServer.listen(workerPort(), "127.0.0.1", () => resolve());
|
|
54630
55428
|
});
|
|
54631
|
-
const bridgeHealth = new BridgeHealthTracker({
|
|
55429
|
+
const bridgeHealth = new BridgeHealthTracker({
|
|
55430
|
+
stateDir: config2.stateDir,
|
|
55431
|
+
hasLiveTurn: () => wrappedTurnLock.activeCount() > 0 || (resumableCountHolder.fn?.() ?? 0) > 0
|
|
55432
|
+
});
|
|
54632
55433
|
const runTrackedSweep = async (id, label, fn) => {
|
|
54633
55434
|
try {
|
|
54634
55435
|
await fn();
|
|
@@ -54665,8 +55466,8 @@ async function startDirectorBridge() {
|
|
|
54665
55466
|
);
|
|
54666
55467
|
void runOrphanWorktreeSweep(client, {
|
|
54667
55468
|
checkoutRegistry,
|
|
54668
|
-
worktreeRoot:
|
|
54669
|
-
locksDir:
|
|
55469
|
+
worktreeRoot: import_node_path23.default.join(config2.stateDir, "worktrees"),
|
|
55470
|
+
locksDir: import_node_path23.default.join(config2.stateDir, "locks")
|
|
54670
55471
|
});
|
|
54671
55472
|
{
|
|
54672
55473
|
const { retainedBuffers, retainedBytes, tombstonesRemoved } = sweepReplayBuffers(threads, tombstones, {
|
|
@@ -54707,6 +55508,28 @@ async function startDirectorBridge() {
|
|
|
54707
55508
|
});
|
|
54708
55509
|
}
|
|
54709
55510
|
}
|
|
55511
|
+
void (async () => {
|
|
55512
|
+
try {
|
|
55513
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
55514
|
+
await foldClosedDays(config2.stateDir, today);
|
|
55515
|
+
await uploadPendingDays(config2.stateDir, client, bridgeHealth, {
|
|
55516
|
+
cwd: config2.codexCwd ?? process.cwd(),
|
|
55517
|
+
codexExecutable: config2.codexExecutable,
|
|
55518
|
+
timeoutMs: readEnvInt("MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS", 60) * 1e3
|
|
55519
|
+
});
|
|
55520
|
+
await prune(config2.stateDir, {
|
|
55521
|
+
ageDays: readEnvInt("MRRLIN_LOG_RETENTION_AGE_DAYS", 30),
|
|
55522
|
+
budgetMb: readEnvInt("MRRLIN_LOG_RETENTION_BUDGET_MB", 1024)
|
|
55523
|
+
});
|
|
55524
|
+
} catch (error51) {
|
|
55525
|
+
bridgeLogger.logOut({
|
|
55526
|
+
spanId: "gc",
|
|
55527
|
+
sessionId: null,
|
|
55528
|
+
type: "<telemetry-pipeline-error>",
|
|
55529
|
+
payload: { error: error51 instanceof Error ? error51.message : String(error51) }
|
|
55530
|
+
});
|
|
55531
|
+
}
|
|
55532
|
+
})();
|
|
54710
55533
|
scheduleClaimLoop();
|
|
54711
55534
|
}, claimIntervalMs());
|
|
54712
55535
|
claimTimer.unref?.();
|
|
@@ -54927,7 +55750,7 @@ function timingSafeTokenEqual(provided, expected) {
|
|
|
54927
55750
|
const a = Buffer.from(provided);
|
|
54928
55751
|
const b = Buffer.from(expected);
|
|
54929
55752
|
if (a.length !== b.length) return false;
|
|
54930
|
-
return
|
|
55753
|
+
return import_node_crypto9.default.timingSafeEqual(a, b);
|
|
54931
55754
|
}
|
|
54932
55755
|
function readDispatchBody(req) {
|
|
54933
55756
|
return new Promise((resolve, reject) => {
|
|
@@ -54949,14 +55772,14 @@ function readDispatchBody(req) {
|
|
|
54949
55772
|
function readOrCreateBridgeToken(stateDir) {
|
|
54950
55773
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
54951
55774
|
if (explicit) return explicit;
|
|
54952
|
-
const tokenPath =
|
|
55775
|
+
const tokenPath = import_node_path23.default.join(stateDir, "token.txt");
|
|
54953
55776
|
try {
|
|
54954
55777
|
const existing = import_node_fs16.default.readFileSync(tokenPath, "utf8").trim();
|
|
54955
55778
|
if (existing) return existing;
|
|
54956
55779
|
} catch {
|
|
54957
55780
|
}
|
|
54958
55781
|
import_node_fs16.default.mkdirSync(stateDir, { recursive: true, mode: 448 });
|
|
54959
|
-
const token =
|
|
55782
|
+
const token = import_node_crypto9.default.randomBytes(32).toString("base64url");
|
|
54960
55783
|
import_node_fs16.default.writeFileSync(tokenPath, `${token}
|
|
54961
55784
|
`, { mode: 384 });
|
|
54962
55785
|
return token;
|
|
@@ -58341,36 +59164,36 @@ var StdioServerTransport = class {
|
|
|
58341
59164
|
};
|
|
58342
59165
|
|
|
58343
59166
|
// src/tools.ts
|
|
58344
|
-
var
|
|
58345
|
-
var
|
|
58346
|
-
var
|
|
59167
|
+
var import_node_crypto12 = require("node:crypto");
|
|
59168
|
+
var import_promises10 = require("node:fs/promises");
|
|
59169
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
58347
59170
|
var import_node_os12 = __toESM(require("node:os"), 1);
|
|
58348
59171
|
|
|
58349
59172
|
// ../../packages/wiki/dist/index.js
|
|
58350
|
-
var
|
|
58351
|
-
var
|
|
59173
|
+
var import_promises8 = __toESM(require("node:fs/promises"), 1);
|
|
59174
|
+
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
58352
59175
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
58353
59176
|
function toPosixPath(input) {
|
|
58354
|
-
return input.split(
|
|
59177
|
+
return input.split(import_node_path24.default.sep).join("/");
|
|
58355
59178
|
}
|
|
58356
59179
|
function slugifyWikiSegment(input) {
|
|
58357
59180
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
58358
59181
|
}
|
|
58359
59182
|
async function pathExists3(input) {
|
|
58360
59183
|
try {
|
|
58361
|
-
await
|
|
59184
|
+
await import_promises8.default.access(input);
|
|
58362
59185
|
return true;
|
|
58363
59186
|
} catch {
|
|
58364
59187
|
return false;
|
|
58365
59188
|
}
|
|
58366
59189
|
}
|
|
58367
59190
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
58368
|
-
let current2 =
|
|
59191
|
+
let current2 = import_node_path24.default.resolve(start);
|
|
58369
59192
|
while (true) {
|
|
58370
|
-
if (await pathExists3(
|
|
59193
|
+
if (await pathExists3(import_node_path24.default.join(current2, "pnpm-workspace.yaml")) && await pathExists3(import_node_path24.default.join(current2, "docs"))) {
|
|
58371
59194
|
return current2;
|
|
58372
59195
|
}
|
|
58373
|
-
const parent =
|
|
59196
|
+
const parent = import_node_path24.default.dirname(current2);
|
|
58374
59197
|
if (parent === current2) {
|
|
58375
59198
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
58376
59199
|
}
|
|
@@ -58379,28 +59202,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
58379
59202
|
}
|
|
58380
59203
|
async function resolveDocsRoot(input) {
|
|
58381
59204
|
if (input) {
|
|
58382
|
-
return
|
|
59205
|
+
return import_node_path24.default.resolve(input);
|
|
58383
59206
|
}
|
|
58384
59207
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
58385
|
-
return
|
|
59208
|
+
return import_node_path24.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
58386
59209
|
}
|
|
58387
|
-
return
|
|
59210
|
+
return import_node_path24.default.join(await findWorkspaceRoot(), "docs");
|
|
58388
59211
|
}
|
|
58389
59212
|
async function resolveIndexPath(input) {
|
|
58390
59213
|
if (input) {
|
|
58391
|
-
return
|
|
59214
|
+
return import_node_path24.default.resolve(input);
|
|
58392
59215
|
}
|
|
58393
59216
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
58394
|
-
return
|
|
59217
|
+
return import_node_path24.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
58395
59218
|
}
|
|
58396
59219
|
const workspaceRoot = await findWorkspaceRoot();
|
|
58397
|
-
return
|
|
59220
|
+
return import_node_path24.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
58398
59221
|
}
|
|
58399
59222
|
async function walkMarkdownFiles(root, dir = root) {
|
|
58400
|
-
const entries = await
|
|
59223
|
+
const entries = await import_promises8.default.readdir(dir, { withFileTypes: true });
|
|
58401
59224
|
const files = [];
|
|
58402
59225
|
for (const entry of entries) {
|
|
58403
|
-
const absolute =
|
|
59226
|
+
const absolute = import_node_path24.default.join(dir, entry.name);
|
|
58404
59227
|
if (entry.isDirectory()) {
|
|
58405
59228
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
58406
59229
|
continue;
|
|
@@ -58419,7 +59242,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
58419
59242
|
return title;
|
|
58420
59243
|
}
|
|
58421
59244
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
58422
|
-
const relativePath = toPosixPath(
|
|
59245
|
+
const relativePath = toPosixPath(import_node_path24.default.relative(docsRoot, absolutePath));
|
|
58423
59246
|
const [section, fileName] = relativePath.split("/");
|
|
58424
59247
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
58425
59248
|
return null;
|
|
@@ -58439,7 +59262,7 @@ async function listWikiDocuments(options = {}) {
|
|
|
58439
59262
|
const files = await walkMarkdownFiles(docsRoot);
|
|
58440
59263
|
const documents = [];
|
|
58441
59264
|
for (const file2 of files) {
|
|
58442
|
-
const markdown = await
|
|
59265
|
+
const markdown = await import_promises8.default.readFile(file2, "utf8");
|
|
58443
59266
|
const document2 = documentFromFile(docsRoot, file2, markdown);
|
|
58444
59267
|
if (document2) {
|
|
58445
59268
|
documents.push(document2);
|
|
@@ -58493,7 +59316,7 @@ async function buildWikiKnowledgeIndex(options = {}) {
|
|
|
58493
59316
|
}
|
|
58494
59317
|
async function loadBuiltWikiKnowledgeIndex(indexPath) {
|
|
58495
59318
|
const resolvedIndexPath = await resolveIndexPath(indexPath);
|
|
58496
|
-
const raw = await
|
|
59319
|
+
const raw = await import_promises8.default.readFile(resolvedIndexPath, "utf8");
|
|
58497
59320
|
return wikiKnowledgeIndexSchema.parse(JSON.parse(raw));
|
|
58498
59321
|
}
|
|
58499
59322
|
function tokenize(input) {
|
|
@@ -58584,9 +59407,9 @@ async function runCodeGate(_target, deps) {
|
|
|
58584
59407
|
accepted
|
|
58585
59408
|
);
|
|
58586
59409
|
}
|
|
58587
|
-
let
|
|
59410
|
+
let gate2;
|
|
58588
59411
|
try {
|
|
58589
|
-
|
|
59412
|
+
gate2 = await deps.fastGate();
|
|
58590
59413
|
} catch (gateErr) {
|
|
58591
59414
|
await deps.restore(ref);
|
|
58592
59415
|
throw new CodeGateUnfixableError(
|
|
@@ -58594,7 +59417,7 @@ async function runCodeGate(_target, deps) {
|
|
|
58594
59417
|
accepted
|
|
58595
59418
|
);
|
|
58596
59419
|
}
|
|
58597
|
-
if (!
|
|
59420
|
+
if (!gate2.ok) {
|
|
58598
59421
|
await deps.restore(ref);
|
|
58599
59422
|
throw new CodeGateUnfixableError("fast-gate red after revision", accepted);
|
|
58600
59423
|
}
|
|
@@ -59031,7 +59854,7 @@ async function resolveActiveRunHead(input, deps) {
|
|
|
59031
59854
|
}
|
|
59032
59855
|
|
|
59033
59856
|
// src/async-tools/consensus.ts
|
|
59034
|
-
var
|
|
59857
|
+
var import_node_crypto10 = require("node:crypto");
|
|
59035
59858
|
|
|
59036
59859
|
// src/consensus/question-similarity.ts
|
|
59037
59860
|
var SUPPRESSION_SIMILARITY_THRESHOLD = 0.6;
|
|
@@ -59307,9 +60130,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
59307
60130
|
}
|
|
59308
60131
|
if (taskId) {
|
|
59309
60132
|
const scopeId = taskId;
|
|
59310
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
60133
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto10.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
59311
60134
|
for (const clarification of toFile) {
|
|
59312
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
60135
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto10.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
59313
60136
|
try {
|
|
59314
60137
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
59315
60138
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -59327,9 +60150,9 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
59327
60150
|
filedQuestionCount = toFile.length;
|
|
59328
60151
|
} else if (planId) {
|
|
59329
60152
|
const scopeId = planId;
|
|
59330
|
-
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0,
|
|
60153
|
+
const groupId = toFile.length > 1 ? `II-${scopeId}-gate-group-${(0, import_node_crypto10.createHash)("sha256").update(toFile.map((c) => c.rawQuestion).sort().join("\n")).digest("hex").slice(0, 10)}` : void 0;
|
|
59331
60154
|
for (const clarification of toFile) {
|
|
59332
|
-
const id = `II-${scopeId}-gate-${(0,
|
|
60155
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto10.createHash)("sha256").update(clarification.rawQuestion).digest("hex").slice(0, 10)}`;
|
|
59333
60156
|
try {
|
|
59334
60157
|
const questionOptions = buildGateQuestionOptions(clarification.rawQuestion, clarification.category);
|
|
59335
60158
|
await ctx.client.createInboxItem(input.projectSlug, {
|
|
@@ -59353,7 +60176,7 @@ async function handleConsensusBlocked(result, ctx, input, resolvedTaskId) {
|
|
|
59353
60176
|
taskId: page.taskId ?? null
|
|
59354
60177
|
});
|
|
59355
60178
|
const reviewHash = domainScopedReviewHash2(page.contentHash, domain2);
|
|
59356
|
-
const baseBlockItemId = `II-${taskId}-gateblock-${(0,
|
|
60179
|
+
const baseBlockItemId = `II-${taskId}-gateblock-${(0, import_node_crypto10.createHash)("sha256").update(reviewHash).digest("hex").slice(0, 10)}`;
|
|
59357
60180
|
const reviewAgainAvailable = !taskInboxItems.some(
|
|
59358
60181
|
(item) => item.id === baseBlockItemId && item.status !== "pending" && item.answer === REVIEW_AGAIN_ANSWER
|
|
59359
60182
|
);
|
|
@@ -59923,8 +60746,159 @@ function createIntentCheckDescriptor() {
|
|
|
59923
60746
|
}
|
|
59924
60747
|
var intentCheckDescriptor = createIntentCheckDescriptor();
|
|
59925
60748
|
|
|
60749
|
+
// src/evidence/assembler.ts
|
|
60750
|
+
var import_promises9 = require("node:fs/promises");
|
|
60751
|
+
var import_node_path25 = require("node:path");
|
|
60752
|
+
function evidenceDedupKey(sessionId, reportId) {
|
|
60753
|
+
return `${sessionId}:${reportId}`;
|
|
60754
|
+
}
|
|
60755
|
+
function isRecord3(v) {
|
|
60756
|
+
return v !== null && typeof v === "object";
|
|
60757
|
+
}
|
|
60758
|
+
async function readDayLines(stateDir, day, sessionId) {
|
|
60759
|
+
let raw;
|
|
60760
|
+
try {
|
|
60761
|
+
raw = await (0, import_promises9.readFile)((0, import_node_path25.join)(stateDir, "logs", `bridge-${day}.jsonl`), "utf8");
|
|
60762
|
+
} catch {
|
|
60763
|
+
return [];
|
|
60764
|
+
}
|
|
60765
|
+
const kept = [];
|
|
60766
|
+
for (const line of raw.split("\n")) {
|
|
60767
|
+
if (!line.trim()) continue;
|
|
60768
|
+
let rec;
|
|
60769
|
+
try {
|
|
60770
|
+
rec = JSON.parse(line);
|
|
60771
|
+
} catch {
|
|
60772
|
+
continue;
|
|
60773
|
+
}
|
|
60774
|
+
if (!isRecord3(rec) || !isRecord3(rec.payload)) continue;
|
|
60775
|
+
if (rec.payload.directorSessionId !== sessionId) continue;
|
|
60776
|
+
kept.push(rec);
|
|
60777
|
+
}
|
|
60778
|
+
return kept;
|
|
60779
|
+
}
|
|
60780
|
+
async function assembleEvidence(stateDir, sessionId, reportId, gateCtx) {
|
|
60781
|
+
const daysRead = await findSessionDays(stateDir, sessionId);
|
|
60782
|
+
const allLines = [];
|
|
60783
|
+
for (const day of daysRead) {
|
|
60784
|
+
allLines.push(...await readDayLines(stateDir, day, sessionId));
|
|
60785
|
+
}
|
|
60786
|
+
const groups = /* @__PURE__ */ new Map();
|
|
60787
|
+
for (const line of allLines) {
|
|
60788
|
+
const turnKey = line.payload?.turnId ?? null;
|
|
60789
|
+
const bucket = groups.get(turnKey);
|
|
60790
|
+
if (bucket) bucket.push(line);
|
|
60791
|
+
else groups.set(turnKey, [line]);
|
|
60792
|
+
}
|
|
60793
|
+
const orderedGroups = [...groups.entries()].sort(([, a], [, b]) => {
|
|
60794
|
+
const aTs = a[0]?.ts ?? "";
|
|
60795
|
+
const bTs = b[0]?.ts ?? "";
|
|
60796
|
+
return aTs < bTs ? -1 : aTs > bTs ? 1 : 0;
|
|
60797
|
+
});
|
|
60798
|
+
const steps = [];
|
|
60799
|
+
const turnIds = [];
|
|
60800
|
+
for (const [turnId, groupLines] of orderedGroups) {
|
|
60801
|
+
const ordered = [...groupLines].sort((a, b) => (a.payload?.seq ?? 0) - (b.payload?.seq ?? 0));
|
|
60802
|
+
const groupHasFailedLifecycle = ordered.some(
|
|
60803
|
+
(l) => l.projection?.kind === "turn_lifecycle" && l.projection.lifecycle === "failed"
|
|
60804
|
+
);
|
|
60805
|
+
const resultByToolId = /* @__PURE__ */ new Map();
|
|
60806
|
+
for (const line of ordered) {
|
|
60807
|
+
if (line.projection?.kind !== "tool_result") continue;
|
|
60808
|
+
const toolId = line.payload?.event?.tool?.id;
|
|
60809
|
+
if (typeof toolId === "string") resultByToolId.set(toolId, line);
|
|
60810
|
+
}
|
|
60811
|
+
let groupProducedStep = false;
|
|
60812
|
+
for (const line of ordered) {
|
|
60813
|
+
if (line.projection?.kind !== "tool_use") continue;
|
|
60814
|
+
const rawToolId = line.payload?.event?.tool?.id;
|
|
60815
|
+
const paired = typeof rawToolId === "string" ? resultByToolId.get(rawToolId) : void 0;
|
|
60816
|
+
const toolName = line.projection.toolName ?? line.payload?.event?.tool?.name ?? "";
|
|
60817
|
+
const ms = line.projection.ms ?? 0;
|
|
60818
|
+
const outcome = paired?.projection?.kind === "tool_result" ? paired.projection.outcome ?? "unknown" : "unknown";
|
|
60819
|
+
const step = { toolName, ms, outcome };
|
|
60820
|
+
if (paired?.projection?.kind === "tool_result" && paired.projection.exitCode !== void 0) {
|
|
60821
|
+
step.exitCode = paired.projection.exitCode;
|
|
60822
|
+
}
|
|
60823
|
+
const needsExcerpt = outcome === "error" || groupHasFailedLifecycle;
|
|
60824
|
+
const rawContent = paired?.payload?.event?.content;
|
|
60825
|
+
if (needsExcerpt && typeof rawContent === "string") {
|
|
60826
|
+
step.excerpt = redact(rawContent).slice(0, 8192);
|
|
60827
|
+
}
|
|
60828
|
+
steps.push(step);
|
|
60829
|
+
groupProducedStep = true;
|
|
60830
|
+
}
|
|
60831
|
+
if (groupProducedStep && turnId !== null) turnIds.push(turnId);
|
|
60832
|
+
}
|
|
60833
|
+
let windowPruned = false;
|
|
60834
|
+
try {
|
|
60835
|
+
const raw = await (0, import_promises9.readFile)((0, import_node_path25.join)(stateDir, "logs", ".pruned.jsonl"), "utf8");
|
|
60836
|
+
outer: for (const line of raw.split("\n")) {
|
|
60837
|
+
if (!line.trim()) continue;
|
|
60838
|
+
let rec;
|
|
60839
|
+
try {
|
|
60840
|
+
rec = JSON.parse(line);
|
|
60841
|
+
} catch {
|
|
60842
|
+
continue;
|
|
60843
|
+
}
|
|
60844
|
+
if (!isRecord3(rec) || !Array.isArray(rec.daysRemoved)) continue;
|
|
60845
|
+
for (const removedDay of rec.daysRemoved) {
|
|
60846
|
+
if (daysRead.includes(removedDay)) {
|
|
60847
|
+
windowPruned = true;
|
|
60848
|
+
break outer;
|
|
60849
|
+
}
|
|
60850
|
+
}
|
|
60851
|
+
}
|
|
60852
|
+
} catch {
|
|
60853
|
+
}
|
|
60854
|
+
const provisional = { reportId, sessionId, turnIds, daysRead, windowPruned, steps, gateMarker: "gated" };
|
|
60855
|
+
const prose = [];
|
|
60856
|
+
steps.forEach((step, i) => {
|
|
60857
|
+
if (step.excerpt !== void 0) prose.push({ path: `steps.${i}.excerpt`, value: step.excerpt });
|
|
60858
|
+
});
|
|
60859
|
+
const gateResult = await gate(provisional, prose, gateCtx);
|
|
60860
|
+
return { ...gateResult.artifact, gateMarker: gateResult.gated ? "gated" : "projection-only" };
|
|
60861
|
+
}
|
|
60862
|
+
|
|
60863
|
+
// src/async-tools/report-evidence.ts
|
|
60864
|
+
function gateTimeoutMs() {
|
|
60865
|
+
const raw = (process.env.MRRLIN_TELEMETRY_GATE_TIMEOUT_SECONDS ?? "").trim();
|
|
60866
|
+
const parsed = Number.parseInt(raw, 10);
|
|
60867
|
+
const seconds = Number.isInteger(parsed) && parsed > 0 ? parsed : 60;
|
|
60868
|
+
return seconds * 1e3;
|
|
60869
|
+
}
|
|
60870
|
+
var REPORT_EVIDENCE_TOOL_NAME = "report-evidence";
|
|
60871
|
+
async function runReportEvidence(ctx, input) {
|
|
60872
|
+
const gateCtx = {
|
|
60873
|
+
cwd: ctx.cwd,
|
|
60874
|
+
codexExecutable: ctx.codexExecutable,
|
|
60875
|
+
timeoutMs: gateTimeoutMs(),
|
|
60876
|
+
runExec: ctx.gateRunExec
|
|
60877
|
+
};
|
|
60878
|
+
const artifact = await assembleEvidence(ctx.stateDir, input.directorSessionId, input.reportId, gateCtx);
|
|
60879
|
+
return { kind: "done", resultJson: JSON.stringify(artifact), finalReviewedHash: null };
|
|
60880
|
+
}
|
|
60881
|
+
function onComplete5(outcome, input) {
|
|
60882
|
+
if (outcome.kind === "done") {
|
|
60883
|
+
return { kind: "info", body: `Evidence assembled for report ${input.reportId}.`, suppressInbox: true };
|
|
60884
|
+
}
|
|
60885
|
+
return { kind: "info", body: `Evidence assembly failed for report ${input.reportId}: ${outcome.error}` };
|
|
60886
|
+
}
|
|
60887
|
+
function createReportEvidenceDescriptor() {
|
|
60888
|
+
return {
|
|
60889
|
+
toolName: REPORT_EVIDENCE_TOOL_NAME,
|
|
60890
|
+
dedupKey: (input) => evidenceDedupKey(input.directorSessionId, input.reportId),
|
|
60891
|
+
run: runReportEvidence,
|
|
60892
|
+
onComplete: onComplete5,
|
|
60893
|
+
// Runs long after the reporting user's turn ended, sometimes with no live session left to wake.
|
|
60894
|
+
wakeDirector: false,
|
|
60895
|
+
locationDependent: true
|
|
60896
|
+
};
|
|
60897
|
+
}
|
|
60898
|
+
var reportEvidenceDescriptor = createReportEvidenceDescriptor();
|
|
60899
|
+
|
|
59926
60900
|
// src/async-tools/enqueue.ts
|
|
59927
|
-
var
|
|
60901
|
+
var import_node_crypto11 = __toESM(require("node:crypto"), 1);
|
|
59928
60902
|
async function enqueueAsyncTool(client, descriptor2, input) {
|
|
59929
60903
|
if (descriptor2.cachedResult) {
|
|
59930
60904
|
const cached2 = await descriptor2.cachedResult(client, input);
|
|
@@ -59937,7 +60911,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
|
|
|
59937
60911
|
if (active) {
|
|
59938
60912
|
return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
|
|
59939
60913
|
}
|
|
59940
|
-
const jobId = `AJ-${
|
|
60914
|
+
const jobId = `AJ-${import_node_crypto11.default.randomUUID()}`;
|
|
59941
60915
|
try {
|
|
59942
60916
|
await client.createAsyncJob(input.projectSlug, {
|
|
59943
60917
|
id: jobId,
|
|
@@ -60506,6 +61480,7 @@ registerAsyncTool(consensusDescriptor);
|
|
|
60506
61480
|
registerAsyncTool(deliverableConsensusDescriptor);
|
|
60507
61481
|
registerAsyncTool(draftSpecDescriptor);
|
|
60508
61482
|
registerAsyncTool(intentCheckDescriptor);
|
|
61483
|
+
registerAsyncTool(reportEvidenceDescriptor);
|
|
60509
61484
|
var projectScopedSchema = external_exports.object({ projectSlug: mrrlinProjectSlugSchema });
|
|
60510
61485
|
var taskScopedSchema = projectScopedSchema.extend({ taskId: mrrlinTaskIdSchema });
|
|
60511
61486
|
var planScopedSchema = projectScopedSchema.extend({ planId: mrrlinPlanIdSchema });
|
|
@@ -61516,7 +62491,7 @@ function createMrrlinTools(options) {
|
|
|
61516
62491
|
"PRODUCED_URL_RECORD_FAILED",
|
|
61517
62492
|
"Unable to record produced URL.",
|
|
61518
62493
|
async (c, { projectSlug, runId, url: url2, label }) => {
|
|
61519
|
-
const id = `EA-pu-${(0,
|
|
62494
|
+
const id = `EA-pu-${(0, import_node_crypto12.randomBytes)(4).toString("hex")}`;
|
|
61520
62495
|
const payload = label ? { url: url2, label } : { url: url2 };
|
|
61521
62496
|
return await c.appendExecutionArtifact(projectSlug, runId, {
|
|
61522
62497
|
id,
|
|
@@ -61590,7 +62565,7 @@ function createMrrlinTools(options) {
|
|
|
61590
62565
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
61591
62566
|
"Unable to upload artifact file.",
|
|
61592
62567
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
61593
|
-
const extension2 =
|
|
62568
|
+
const extension2 = import_node_path26.default.extname(filePath).toLowerCase();
|
|
61594
62569
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
61595
62570
|
if (!contentType) {
|
|
61596
62571
|
throw new McpToolCodedError(
|
|
@@ -61598,7 +62573,7 @@ function createMrrlinTools(options) {
|
|
|
61598
62573
|
`Unsupported artifact extension '${extension2}'. Allowed: ${Object.keys(ARTIFACT_EXTENSION_TYPES).join(", ")}.`
|
|
61599
62574
|
);
|
|
61600
62575
|
}
|
|
61601
|
-
const stats = await (0,
|
|
62576
|
+
const stats = await (0, import_promises10.stat)(filePath);
|
|
61602
62577
|
if (stats.size > MRRLIN_ARTIFACT_FILE_MAX_BYTES) {
|
|
61603
62578
|
throw new McpToolCodedError(
|
|
61604
62579
|
"ARTIFACT_FILE_TOO_LARGE",
|
|
@@ -61611,14 +62586,14 @@ function createMrrlinTools(options) {
|
|
|
61611
62586
|
"File is empty (0 bytes); write content before uploading."
|
|
61612
62587
|
);
|
|
61613
62588
|
}
|
|
61614
|
-
const bytes3 = new Uint8Array(await (0,
|
|
62589
|
+
const bytes3 = new Uint8Array(await (0, import_promises10.readFile)(filePath));
|
|
61615
62590
|
if (bytes3.byteLength > MRRLIN_ARTIFACT_FILE_MAX_BYTES) {
|
|
61616
62591
|
throw new McpToolCodedError(
|
|
61617
62592
|
"ARTIFACT_FILE_TOO_LARGE",
|
|
61618
62593
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
61619
62594
|
);
|
|
61620
62595
|
}
|
|
61621
|
-
const filename =
|
|
62596
|
+
const filename = import_node_path26.default.basename(filePath);
|
|
61622
62597
|
return uploadArtifactBytes(c, {
|
|
61623
62598
|
bytes: bytes3,
|
|
61624
62599
|
class: artifactClass,
|
|
@@ -61643,7 +62618,7 @@ function createMrrlinTools(options) {
|
|
|
61643
62618
|
`Invalid filename '${filename}'; provide a bare filename with no path separators or '..'.`
|
|
61644
62619
|
);
|
|
61645
62620
|
}
|
|
61646
|
-
const extension2 =
|
|
62621
|
+
const extension2 = import_node_path26.default.extname(filename).toLowerCase();
|
|
61647
62622
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
61648
62623
|
if (!contentType) {
|
|
61649
62624
|
throw new McpToolCodedError(
|
|
@@ -61710,7 +62685,7 @@ function createMrrlinTools(options) {
|
|
|
61710
62685
|
"LOCAL_CHECKOUT_REGISTER_FAILED",
|
|
61711
62686
|
"Unable to register local checkout.",
|
|
61712
62687
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
61713
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
62688
|
+
const stateDir = process.env.CODEX_HOME ? import_node_path26.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path26.default.join(import_node_os12.default.homedir(), ".mrrlin", "director-bridge");
|
|
61714
62689
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
61715
62690
|
const result = registerCheckout(registry3, { projectSlug, path: checkoutPath, repo }, import_node_os12.default.hostname());
|
|
61716
62691
|
if (!result.ok) {
|
|
@@ -61950,7 +62925,7 @@ function runSetCredential(args) {
|
|
|
61950
62925
|
|
|
61951
62926
|
// src/install-service.ts
|
|
61952
62927
|
var import_node_os13 = __toESM(require("node:os"), 1);
|
|
61953
|
-
var
|
|
62928
|
+
var import_node_path27 = __toESM(require("node:path"), 1);
|
|
61954
62929
|
function installService(deps) {
|
|
61955
62930
|
if (!deps.hasSecret()) {
|
|
61956
62931
|
deps.log("No agent credential found. Issue one in Settings, then run: mrrlin-mcp set-credential '<secret>'.");
|
|
@@ -61972,7 +62947,7 @@ function installService(deps) {
|
|
|
61972
62947
|
return { ok: false };
|
|
61973
62948
|
}
|
|
61974
62949
|
const resolvedBins = bins.filter((b) => b !== null);
|
|
61975
|
-
const pathEnv = Array.from(new Set(resolvedBins.map((b) =>
|
|
62950
|
+
const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path27.default.dirname(b)))).join(":");
|
|
61976
62951
|
const apiBaseUrl = deps.env.MRRLIN_API_BASE_URL?.trim() || void 0;
|
|
61977
62952
|
const staging = deps.env.MRRLIN_STAGING === "1" || !apiBaseUrl && bridgeUrlImpliesStaging(deps.env.MRRLIN_BRIDGE_URL);
|
|
61978
62953
|
const text = renderEcosystemConfig({
|
|
@@ -61983,7 +62958,7 @@ function installService(deps) {
|
|
|
61983
62958
|
staging,
|
|
61984
62959
|
apiBaseUrl
|
|
61985
62960
|
});
|
|
61986
|
-
const ecoPath =
|
|
62961
|
+
const ecoPath = import_node_path27.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
61987
62962
|
deps.writeFile(ecoPath, text);
|
|
61988
62963
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
61989
62964
|
if (start.code !== 0) {
|
|
@@ -62013,18 +62988,18 @@ function uninstallService(deps) {
|
|
|
62013
62988
|
}
|
|
62014
62989
|
|
|
62015
62990
|
// src/uninstall-codex.ts
|
|
62016
|
-
var
|
|
62991
|
+
var import_promises11 = __toESM(require("node:fs/promises"), 1);
|
|
62017
62992
|
var import_node_os14 = __toESM(require("node:os"), 1);
|
|
62018
|
-
var
|
|
62993
|
+
var import_node_path28 = __toESM(require("node:path"), 1);
|
|
62019
62994
|
var toml3 = __toESM(require_toml(), 1);
|
|
62020
62995
|
function resolveCodexHome3(options) {
|
|
62021
62996
|
if (options.codexHome) return options.codexHome;
|
|
62022
62997
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
62023
|
-
return
|
|
62998
|
+
return import_node_path28.default.join(options.homeDir ?? import_node_os14.default.homedir(), ".codex");
|
|
62024
62999
|
}
|
|
62025
63000
|
async function pathExists4(target) {
|
|
62026
63001
|
try {
|
|
62027
|
-
await
|
|
63002
|
+
await import_promises11.default.access(target);
|
|
62028
63003
|
return true;
|
|
62029
63004
|
} catch {
|
|
62030
63005
|
return false;
|
|
@@ -62033,13 +63008,13 @@ async function pathExists4(target) {
|
|
|
62033
63008
|
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.(?:mrrlin(?:-browser)?|external-agents)(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
62034
63009
|
async function uninstallCodex(options = {}) {
|
|
62035
63010
|
const codexHome = resolveCodexHome3(options);
|
|
62036
|
-
const configPath =
|
|
63011
|
+
const configPath = import_node_path28.default.join(codexHome, "config.toml");
|
|
62037
63012
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
62038
63013
|
if (!await pathExists4(configPath)) {
|
|
62039
63014
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
62040
63015
|
}
|
|
62041
|
-
const realPath = await
|
|
62042
|
-
const existing = await
|
|
63016
|
+
const realPath = await import_promises11.default.realpath(configPath).catch(() => configPath);
|
|
63017
|
+
const existing = await import_promises11.default.readFile(realPath, "utf8");
|
|
62043
63018
|
let parsed = null;
|
|
62044
63019
|
try {
|
|
62045
63020
|
parsed = toml3.parse(existing);
|
|
@@ -62056,17 +63031,17 @@ async function uninstallCodex(options = {}) {
|
|
|
62056
63031
|
return { action: "noop", configPath: realPath, prompts: await removePrompts() };
|
|
62057
63032
|
}
|
|
62058
63033
|
const stripped = existing.replace(MRRLIN_BLOCK_RE, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
62059
|
-
await
|
|
63034
|
+
await import_promises11.default.writeFile(realPath, stripped, { mode: 384 });
|
|
62060
63035
|
return { action: "removed", configPath: realPath, prompts: await removePrompts() };
|
|
62061
63036
|
}
|
|
62062
63037
|
async function uninstallPrompts(codexHome, names) {
|
|
62063
63038
|
if (names.length === 0) return [];
|
|
62064
|
-
const promptsDir =
|
|
63039
|
+
const promptsDir = import_node_path28.default.join(codexHome, "prompts");
|
|
62065
63040
|
const out = [];
|
|
62066
63041
|
for (const name of names) {
|
|
62067
|
-
const promptPath =
|
|
63042
|
+
const promptPath = import_node_path28.default.join(promptsDir, `${name}.md`);
|
|
62068
63043
|
try {
|
|
62069
|
-
await
|
|
63044
|
+
await import_promises11.default.unlink(promptPath);
|
|
62070
63045
|
out.push({ name, action: "removed", promptPath });
|
|
62071
63046
|
} catch (error51) {
|
|
62072
63047
|
const code = error51?.code;
|
|
@@ -62080,6 +63055,129 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
62080
63055
|
return out;
|
|
62081
63056
|
}
|
|
62082
63057
|
|
|
63058
|
+
// src/extract/command.ts
|
|
63059
|
+
var import_promises12 = require("node:fs/promises");
|
|
63060
|
+
var import_node_path29 = require("node:path");
|
|
63061
|
+
function parseArgs(args) {
|
|
63062
|
+
const map2 = /* @__PURE__ */ new Map();
|
|
63063
|
+
for (let i = 0; i < args.length; i++) {
|
|
63064
|
+
const arg = args[i];
|
|
63065
|
+
if (arg?.startsWith("--")) {
|
|
63066
|
+
const key = arg.slice(2);
|
|
63067
|
+
const next = args[i + 1];
|
|
63068
|
+
if (next && !next.startsWith("--")) {
|
|
63069
|
+
map2.set(key, next);
|
|
63070
|
+
i++;
|
|
63071
|
+
}
|
|
63072
|
+
}
|
|
63073
|
+
}
|
|
63074
|
+
return map2;
|
|
63075
|
+
}
|
|
63076
|
+
function isRecord4(v) {
|
|
63077
|
+
return v !== null && typeof v === "object";
|
|
63078
|
+
}
|
|
63079
|
+
async function runExtract(args, deps) {
|
|
63080
|
+
const flags = parseArgs(args);
|
|
63081
|
+
const sessionId = flags.get("session");
|
|
63082
|
+
const projectSlug = flags.get("project");
|
|
63083
|
+
const outPath = flags.get("out") ?? null;
|
|
63084
|
+
if (!sessionId || !projectSlug) {
|
|
63085
|
+
const missing = [];
|
|
63086
|
+
if (!sessionId) missing.push("--session");
|
|
63087
|
+
if (!projectSlug) missing.push("--project");
|
|
63088
|
+
const usage = `Usage: mrrlin-mcp extract --session <directorSessionId> --project <projectSlug> [--out <path>]
|
|
63089
|
+
Missing required flag(s): ${missing.join(
|
|
63090
|
+
", "
|
|
63091
|
+
)}`;
|
|
63092
|
+
return { ok: false, message: usage, deliveredArtifactId: null };
|
|
63093
|
+
}
|
|
63094
|
+
const days = await findSessionDays(deps.stateDir, sessionId);
|
|
63095
|
+
const matchingLines = [];
|
|
63096
|
+
for (const day of days) {
|
|
63097
|
+
const logPath = (0, import_node_path29.join)(deps.stateDir, "logs", `bridge-${day}.jsonl`);
|
|
63098
|
+
let raw;
|
|
63099
|
+
try {
|
|
63100
|
+
raw = await (0, import_promises12.readFile)(logPath, "utf8");
|
|
63101
|
+
} catch {
|
|
63102
|
+
continue;
|
|
63103
|
+
}
|
|
63104
|
+
const lines2 = raw.split("\n");
|
|
63105
|
+
for (const line of lines2) {
|
|
63106
|
+
if (!line.trim()) continue;
|
|
63107
|
+
let parsed;
|
|
63108
|
+
try {
|
|
63109
|
+
parsed = JSON.parse(line);
|
|
63110
|
+
} catch {
|
|
63111
|
+
continue;
|
|
63112
|
+
}
|
|
63113
|
+
const payload = isRecord4(parsed) ? parsed.payload : void 0;
|
|
63114
|
+
if (isRecord4(payload) && payload.directorSessionId === sessionId) {
|
|
63115
|
+
matchingLines.push(line);
|
|
63116
|
+
}
|
|
63117
|
+
}
|
|
63118
|
+
}
|
|
63119
|
+
const maxBytes = deps.maxBytes ?? MRRLIN_ARTIFACT_FILE_MAX_BYTES;
|
|
63120
|
+
const cappedLines = [];
|
|
63121
|
+
let totalBytes = 0;
|
|
63122
|
+
for (const rawLine of matchingLines) {
|
|
63123
|
+
const redacted = redact(rawLine);
|
|
63124
|
+
const lineWithNewline = redacted + "\n";
|
|
63125
|
+
const prospective = totalBytes + Buffer.byteLength(lineWithNewline, "utf8");
|
|
63126
|
+
if (prospective > maxBytes) {
|
|
63127
|
+
break;
|
|
63128
|
+
}
|
|
63129
|
+
cappedLines.push(redacted);
|
|
63130
|
+
totalBytes = prospective;
|
|
63131
|
+
}
|
|
63132
|
+
const outputText = cappedLines.join("\n");
|
|
63133
|
+
if (outPath) {
|
|
63134
|
+
await (0, import_promises12.writeFile)(outPath, outputText, "utf8");
|
|
63135
|
+
return {
|
|
63136
|
+
ok: true,
|
|
63137
|
+
message: `Wrote extract to ${outPath}`,
|
|
63138
|
+
deliveredArtifactId: null
|
|
63139
|
+
};
|
|
63140
|
+
}
|
|
63141
|
+
const firstDay = days[0] ?? "unknown";
|
|
63142
|
+
const lastDay = days[days.length - 1] ?? "unknown";
|
|
63143
|
+
const filename = `extract-${sessionId}-${firstDay}-${lastDay}.txt`;
|
|
63144
|
+
const sizeBytes = Buffer.byteLength(outputText, "utf8");
|
|
63145
|
+
const created = await deps.client.createArtifactFile(projectSlug, {
|
|
63146
|
+
class: "temp",
|
|
63147
|
+
contentType: "text/plain",
|
|
63148
|
+
filename,
|
|
63149
|
+
sizeBytes
|
|
63150
|
+
});
|
|
63151
|
+
if (created.upload.kind === "presigned-post") {
|
|
63152
|
+
const form = new FormData();
|
|
63153
|
+
for (const [k, v] of Object.entries(created.upload.fields)) {
|
|
63154
|
+
form.append(k, v);
|
|
63155
|
+
}
|
|
63156
|
+
const blob = new Blob([outputText], { type: "text/plain" });
|
|
63157
|
+
form.append("file", blob, filename);
|
|
63158
|
+
const resp = await fetch(created.upload.url, { method: "POST", body: form });
|
|
63159
|
+
if (!resp.ok) {
|
|
63160
|
+
throw new Error(`Presigned POST failed with ${resp.status}`);
|
|
63161
|
+
}
|
|
63162
|
+
} else {
|
|
63163
|
+
await deps.client.uploadArtifactFileContent(
|
|
63164
|
+
projectSlug,
|
|
63165
|
+
created.artifact.id,
|
|
63166
|
+
new TextEncoder().encode(outputText),
|
|
63167
|
+
"text/plain"
|
|
63168
|
+
);
|
|
63169
|
+
}
|
|
63170
|
+
const completed = await deps.client.completeArtifactFile(
|
|
63171
|
+
projectSlug,
|
|
63172
|
+
created.artifact.id
|
|
63173
|
+
);
|
|
63174
|
+
return {
|
|
63175
|
+
ok: true,
|
|
63176
|
+
message: `Uploaded artifact ${completed.id} (${created.stableUrl})`,
|
|
63177
|
+
deliveredArtifactId: completed.id
|
|
63178
|
+
};
|
|
63179
|
+
}
|
|
63180
|
+
|
|
62083
63181
|
// src/bin.ts
|
|
62084
63182
|
function pm2Runner(args) {
|
|
62085
63183
|
const r = (0, import_node_child_process18.spawnSync)("pm2", args, { encoding: "utf8" });
|
|
@@ -62244,6 +63342,11 @@ Usage:
|
|
|
62244
63342
|
support/debug packaging flow:
|
|
62245
63343
|
printf %s "$HINT" | mrrlin-mcp redact
|
|
62246
63344
|
|
|
63345
|
+
mrrlin-mcp extract Pull a director session's raw bridge log lines,
|
|
63346
|
+
scrub them, cap the output size, and either write
|
|
63347
|
+
them locally (with --out) or upload as a temporary
|
|
63348
|
+
artifact file.
|
|
63349
|
+
|
|
62247
63350
|
mrrlin-mcp --help Show this help.
|
|
62248
63351
|
|
|
62249
63352
|
Operator notes:
|
|
@@ -62333,8 +63436,8 @@ async function main() {
|
|
|
62333
63436
|
}
|
|
62334
63437
|
}
|
|
62335
63438
|
try {
|
|
62336
|
-
const codexHome = process.env.CODEX_HOME ??
|
|
62337
|
-
(0, import_node_fs17.rmSync)(
|
|
63439
|
+
const codexHome = process.env.CODEX_HOME ?? import_node_path31.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".codex");
|
|
63440
|
+
(0, import_node_fs17.rmSync)(import_node_path31.default.join(codexHome, "prompts", "report-issue.md"), { force: true });
|
|
62338
63441
|
} catch {
|
|
62339
63442
|
}
|
|
62340
63443
|
const claudeResult = await installClaude({ binPath, force, serveEnv });
|
|
@@ -62369,6 +63472,16 @@ async function main() {
|
|
|
62369
63472
|
process.stdout.write(redact(input));
|
|
62370
63473
|
return;
|
|
62371
63474
|
}
|
|
63475
|
+
case "extract": {
|
|
63476
|
+
const stateDir = readStateDir();
|
|
63477
|
+
const apiBaseUrl = readConfiguredApiBaseUrl();
|
|
63478
|
+
const client = createMrrlinClient(withAuth({ apiBaseUrl }));
|
|
63479
|
+
const result = await runExtract(rest, { stateDir, client });
|
|
63480
|
+
process.stderr.write(`${result.message}
|
|
63481
|
+
`);
|
|
63482
|
+
if (!result.ok) process.exit(2);
|
|
63483
|
+
return;
|
|
63484
|
+
}
|
|
62372
63485
|
case "director-bridge": {
|
|
62373
63486
|
await startDirectorBridge();
|
|
62374
63487
|
return;
|
|
@@ -62385,7 +63498,7 @@ async function main() {
|
|
|
62385
63498
|
env: process.env,
|
|
62386
63499
|
cwd: process.cwd(),
|
|
62387
63500
|
writeFile: (p, c) => {
|
|
62388
|
-
(0, import_node_fs17.mkdirSync)(
|
|
63501
|
+
(0, import_node_fs17.mkdirSync)(import_node_path31.default.dirname(p), { recursive: true, mode: 448 });
|
|
62389
63502
|
(0, import_node_fs17.writeFileSync)(p, c, { mode: 384 });
|
|
62390
63503
|
},
|
|
62391
63504
|
runPm2: pm2Runner,
|
|
@@ -62410,7 +63523,7 @@ async function main() {
|
|
|
62410
63523
|
purgeSecret: purge,
|
|
62411
63524
|
secretPath: agentCredentialPath(),
|
|
62412
63525
|
tokenPath: operatorTokenPath(),
|
|
62413
|
-
ecoPath:
|
|
63526
|
+
ecoPath: import_node_path31.default.join(process.env.HOME ?? (0, import_node_os15.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
62414
63527
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
62415
63528
|
`)
|
|
62416
63529
|
});
|
|
@@ -62431,7 +63544,7 @@ async function main() {
|
|
|
62431
63544
|
purgeSecret: true,
|
|
62432
63545
|
secretPath: agentCredentialPath(),
|
|
62433
63546
|
tokenPath: operatorTokenPath(),
|
|
62434
|
-
ecoPath:
|
|
63547
|
+
ecoPath: import_node_path31.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
62435
63548
|
log
|
|
62436
63549
|
});
|
|
62437
63550
|
let codexOk = true;
|
|
@@ -62451,7 +63564,7 @@ async function main() {
|
|
|
62451
63564
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
62452
63565
|
}
|
|
62453
63566
|
try {
|
|
62454
|
-
(0, import_node_fs17.rmSync)(
|
|
63567
|
+
(0, import_node_fs17.rmSync)(import_node_path31.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
62455
63568
|
} catch {
|
|
62456
63569
|
}
|
|
62457
63570
|
log("removed ~/.mrrlin");
|
|
@@ -62492,7 +63605,7 @@ ${HELP_TEXT}`);
|
|
|
62492
63605
|
}
|
|
62493
63606
|
}
|
|
62494
63607
|
function resolveSelfBinPath() {
|
|
62495
|
-
return
|
|
63608
|
+
return import_node_path30.default.resolve(process.argv[1] ?? process.execPath);
|
|
62496
63609
|
}
|
|
62497
63610
|
main().catch((error51) => {
|
|
62498
63611
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|