@mrrlin-dev/mcp 0.3.2 → 0.3.5
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/README.md +5 -5
- package/dist/bin.cjs +1231 -516
- package/dist/consensus/personas/plan-reviewer.md +2 -0
- package/dist/consensus/personas/scope-analyst.md +7 -0
- package/package.json +4 -2
package/dist/bin.cjs
CHANGED
|
@@ -4273,7 +4273,7 @@ var require_websocket = __commonJS({
|
|
|
4273
4273
|
var http2 = require("http");
|
|
4274
4274
|
var net = require("net");
|
|
4275
4275
|
var tls = require("tls");
|
|
4276
|
-
var { randomBytes: randomBytes3, createHash:
|
|
4276
|
+
var { randomBytes: randomBytes3, createHash: createHash3 } = require("crypto");
|
|
4277
4277
|
var { Duplex, Readable } = require("stream");
|
|
4278
4278
|
var { URL: URL2 } = require("url");
|
|
4279
4279
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -4941,7 +4941,7 @@ var require_websocket = __commonJS({
|
|
|
4941
4941
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
4942
4942
|
return;
|
|
4943
4943
|
}
|
|
4944
|
-
const digest =
|
|
4944
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
4945
4945
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
4946
4946
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
4947
4947
|
return;
|
|
@@ -5310,7 +5310,7 @@ var require_websocket_server = __commonJS({
|
|
|
5310
5310
|
var EventEmitter3 = require("events");
|
|
5311
5311
|
var http2 = require("http");
|
|
5312
5312
|
var { Duplex } = require("stream");
|
|
5313
|
-
var { createHash:
|
|
5313
|
+
var { createHash: createHash3 } = require("crypto");
|
|
5314
5314
|
var extension2 = require_extension();
|
|
5315
5315
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
5316
5316
|
var subprotocol2 = require_subprotocol();
|
|
@@ -5617,7 +5617,7 @@ var require_websocket_server = __commonJS({
|
|
|
5617
5617
|
);
|
|
5618
5618
|
}
|
|
5619
5619
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
5620
|
-
const digest =
|
|
5620
|
+
const digest = createHash3("sha1").update(key + GUID).digest("base64");
|
|
5621
5621
|
const headers = [
|
|
5622
5622
|
"HTTP/1.1 101 Switching Protocols",
|
|
5623
5623
|
"Upgrade: websocket",
|
|
@@ -7703,54 +7703,54 @@ var require_polyfills = __commonJS({
|
|
|
7703
7703
|
}
|
|
7704
7704
|
var chdir;
|
|
7705
7705
|
module2.exports = patch;
|
|
7706
|
-
function patch(
|
|
7706
|
+
function patch(fs7) {
|
|
7707
7707
|
if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
|
|
7708
|
-
patchLchmod(
|
|
7709
|
-
}
|
|
7710
|
-
if (!
|
|
7711
|
-
patchLutimes(
|
|
7712
|
-
}
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
|
|
7724
|
-
|
|
7725
|
-
|
|
7726
|
-
|
|
7727
|
-
|
|
7728
|
-
|
|
7729
|
-
|
|
7730
|
-
|
|
7731
|
-
if (
|
|
7732
|
-
|
|
7708
|
+
patchLchmod(fs7);
|
|
7709
|
+
}
|
|
7710
|
+
if (!fs7.lutimes) {
|
|
7711
|
+
patchLutimes(fs7);
|
|
7712
|
+
}
|
|
7713
|
+
fs7.chown = chownFix(fs7.chown);
|
|
7714
|
+
fs7.fchown = chownFix(fs7.fchown);
|
|
7715
|
+
fs7.lchown = chownFix(fs7.lchown);
|
|
7716
|
+
fs7.chmod = chmodFix(fs7.chmod);
|
|
7717
|
+
fs7.fchmod = chmodFix(fs7.fchmod);
|
|
7718
|
+
fs7.lchmod = chmodFix(fs7.lchmod);
|
|
7719
|
+
fs7.chownSync = chownFixSync(fs7.chownSync);
|
|
7720
|
+
fs7.fchownSync = chownFixSync(fs7.fchownSync);
|
|
7721
|
+
fs7.lchownSync = chownFixSync(fs7.lchownSync);
|
|
7722
|
+
fs7.chmodSync = chmodFixSync(fs7.chmodSync);
|
|
7723
|
+
fs7.fchmodSync = chmodFixSync(fs7.fchmodSync);
|
|
7724
|
+
fs7.lchmodSync = chmodFixSync(fs7.lchmodSync);
|
|
7725
|
+
fs7.stat = statFix(fs7.stat);
|
|
7726
|
+
fs7.fstat = statFix(fs7.fstat);
|
|
7727
|
+
fs7.lstat = statFix(fs7.lstat);
|
|
7728
|
+
fs7.statSync = statFixSync(fs7.statSync);
|
|
7729
|
+
fs7.fstatSync = statFixSync(fs7.fstatSync);
|
|
7730
|
+
fs7.lstatSync = statFixSync(fs7.lstatSync);
|
|
7731
|
+
if (fs7.chmod && !fs7.lchmod) {
|
|
7732
|
+
fs7.lchmod = function(path16, mode, cb) {
|
|
7733
7733
|
if (cb) process.nextTick(cb);
|
|
7734
7734
|
};
|
|
7735
|
-
|
|
7735
|
+
fs7.lchmodSync = function() {
|
|
7736
7736
|
};
|
|
7737
7737
|
}
|
|
7738
|
-
if (
|
|
7739
|
-
|
|
7738
|
+
if (fs7.chown && !fs7.lchown) {
|
|
7739
|
+
fs7.lchown = function(path16, uid, gid, cb) {
|
|
7740
7740
|
if (cb) process.nextTick(cb);
|
|
7741
7741
|
};
|
|
7742
|
-
|
|
7742
|
+
fs7.lchownSync = function() {
|
|
7743
7743
|
};
|
|
7744
7744
|
}
|
|
7745
7745
|
if (platform2 === "win32") {
|
|
7746
|
-
|
|
7746
|
+
fs7.rename = typeof fs7.rename !== "function" ? fs7.rename : function(fs$rename) {
|
|
7747
7747
|
function rename(from, to, cb) {
|
|
7748
7748
|
var start = Date.now();
|
|
7749
7749
|
var backoff = 0;
|
|
7750
7750
|
fs$rename(from, to, function CB(er) {
|
|
7751
7751
|
if (er && (er.code === "EACCES" || er.code === "EPERM" || er.code === "EBUSY") && Date.now() - start < 6e4) {
|
|
7752
7752
|
setTimeout(function() {
|
|
7753
|
-
|
|
7753
|
+
fs7.stat(to, function(stater, st) {
|
|
7754
7754
|
if (stater && stater.code === "ENOENT")
|
|
7755
7755
|
fs$rename(from, to, CB);
|
|
7756
7756
|
else
|
|
@@ -7766,9 +7766,9 @@ var require_polyfills = __commonJS({
|
|
|
7766
7766
|
}
|
|
7767
7767
|
if (Object.setPrototypeOf) Object.setPrototypeOf(rename, fs$rename);
|
|
7768
7768
|
return rename;
|
|
7769
|
-
}(
|
|
7769
|
+
}(fs7.rename);
|
|
7770
7770
|
}
|
|
7771
|
-
|
|
7771
|
+
fs7.read = typeof fs7.read !== "function" ? fs7.read : function(fs$read) {
|
|
7772
7772
|
function read(fd, buffer, offset, length, position, callback_) {
|
|
7773
7773
|
var callback;
|
|
7774
7774
|
if (callback_ && typeof callback_ === "function") {
|
|
@@ -7776,22 +7776,22 @@ var require_polyfills = __commonJS({
|
|
|
7776
7776
|
callback = function(er, _, __) {
|
|
7777
7777
|
if (er && er.code === "EAGAIN" && eagCounter < 10) {
|
|
7778
7778
|
eagCounter++;
|
|
7779
|
-
return fs$read.call(
|
|
7779
|
+
return fs$read.call(fs7, fd, buffer, offset, length, position, callback);
|
|
7780
7780
|
}
|
|
7781
7781
|
callback_.apply(this, arguments);
|
|
7782
7782
|
};
|
|
7783
7783
|
}
|
|
7784
|
-
return fs$read.call(
|
|
7784
|
+
return fs$read.call(fs7, fd, buffer, offset, length, position, callback);
|
|
7785
7785
|
}
|
|
7786
7786
|
if (Object.setPrototypeOf) Object.setPrototypeOf(read, fs$read);
|
|
7787
7787
|
return read;
|
|
7788
|
-
}(
|
|
7789
|
-
|
|
7788
|
+
}(fs7.read);
|
|
7789
|
+
fs7.readSync = typeof fs7.readSync !== "function" ? fs7.readSync : /* @__PURE__ */ function(fs$readSync) {
|
|
7790
7790
|
return function(fd, buffer, offset, length, position) {
|
|
7791
7791
|
var eagCounter = 0;
|
|
7792
7792
|
while (true) {
|
|
7793
7793
|
try {
|
|
7794
|
-
return fs$readSync.call(
|
|
7794
|
+
return fs$readSync.call(fs7, fd, buffer, offset, length, position);
|
|
7795
7795
|
} catch (er) {
|
|
7796
7796
|
if (er.code === "EAGAIN" && eagCounter < 10) {
|
|
7797
7797
|
eagCounter++;
|
|
@@ -7801,11 +7801,11 @@ var require_polyfills = __commonJS({
|
|
|
7801
7801
|
}
|
|
7802
7802
|
}
|
|
7803
7803
|
};
|
|
7804
|
-
}(
|
|
7805
|
-
function patchLchmod(
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7804
|
+
}(fs7.readSync);
|
|
7805
|
+
function patchLchmod(fs8) {
|
|
7806
|
+
fs8.lchmod = function(path16, mode, callback) {
|
|
7807
|
+
fs8.open(
|
|
7808
|
+
path16,
|
|
7809
7809
|
constants.O_WRONLY | constants.O_SYMLINK,
|
|
7810
7810
|
mode,
|
|
7811
7811
|
function(err, fd) {
|
|
@@ -7813,80 +7813,80 @@ var require_polyfills = __commonJS({
|
|
|
7813
7813
|
if (callback) callback(err);
|
|
7814
7814
|
return;
|
|
7815
7815
|
}
|
|
7816
|
-
|
|
7817
|
-
|
|
7816
|
+
fs8.fchmod(fd, mode, function(err2) {
|
|
7817
|
+
fs8.close(fd, function(err22) {
|
|
7818
7818
|
if (callback) callback(err2 || err22);
|
|
7819
7819
|
});
|
|
7820
7820
|
});
|
|
7821
7821
|
}
|
|
7822
7822
|
);
|
|
7823
7823
|
};
|
|
7824
|
-
|
|
7825
|
-
var fd =
|
|
7824
|
+
fs8.lchmodSync = function(path16, mode) {
|
|
7825
|
+
var fd = fs8.openSync(path16, constants.O_WRONLY | constants.O_SYMLINK, mode);
|
|
7826
7826
|
var threw = true;
|
|
7827
7827
|
var ret;
|
|
7828
7828
|
try {
|
|
7829
|
-
ret =
|
|
7829
|
+
ret = fs8.fchmodSync(fd, mode);
|
|
7830
7830
|
threw = false;
|
|
7831
7831
|
} finally {
|
|
7832
7832
|
if (threw) {
|
|
7833
7833
|
try {
|
|
7834
|
-
|
|
7834
|
+
fs8.closeSync(fd);
|
|
7835
7835
|
} catch (er) {
|
|
7836
7836
|
}
|
|
7837
7837
|
} else {
|
|
7838
|
-
|
|
7838
|
+
fs8.closeSync(fd);
|
|
7839
7839
|
}
|
|
7840
7840
|
}
|
|
7841
7841
|
return ret;
|
|
7842
7842
|
};
|
|
7843
7843
|
}
|
|
7844
|
-
function patchLutimes(
|
|
7845
|
-
if (constants.hasOwnProperty("O_SYMLINK") &&
|
|
7846
|
-
|
|
7847
|
-
|
|
7844
|
+
function patchLutimes(fs8) {
|
|
7845
|
+
if (constants.hasOwnProperty("O_SYMLINK") && fs8.futimes) {
|
|
7846
|
+
fs8.lutimes = function(path16, at, mt, cb) {
|
|
7847
|
+
fs8.open(path16, constants.O_SYMLINK, function(er, fd) {
|
|
7848
7848
|
if (er) {
|
|
7849
7849
|
if (cb) cb(er);
|
|
7850
7850
|
return;
|
|
7851
7851
|
}
|
|
7852
|
-
|
|
7853
|
-
|
|
7852
|
+
fs8.futimes(fd, at, mt, function(er2) {
|
|
7853
|
+
fs8.close(fd, function(er22) {
|
|
7854
7854
|
if (cb) cb(er2 || er22);
|
|
7855
7855
|
});
|
|
7856
7856
|
});
|
|
7857
7857
|
});
|
|
7858
7858
|
};
|
|
7859
|
-
|
|
7860
|
-
var fd =
|
|
7859
|
+
fs8.lutimesSync = function(path16, at, mt) {
|
|
7860
|
+
var fd = fs8.openSync(path16, constants.O_SYMLINK);
|
|
7861
7861
|
var ret;
|
|
7862
7862
|
var threw = true;
|
|
7863
7863
|
try {
|
|
7864
|
-
ret =
|
|
7864
|
+
ret = fs8.futimesSync(fd, at, mt);
|
|
7865
7865
|
threw = false;
|
|
7866
7866
|
} finally {
|
|
7867
7867
|
if (threw) {
|
|
7868
7868
|
try {
|
|
7869
|
-
|
|
7869
|
+
fs8.closeSync(fd);
|
|
7870
7870
|
} catch (er) {
|
|
7871
7871
|
}
|
|
7872
7872
|
} else {
|
|
7873
|
-
|
|
7873
|
+
fs8.closeSync(fd);
|
|
7874
7874
|
}
|
|
7875
7875
|
}
|
|
7876
7876
|
return ret;
|
|
7877
7877
|
};
|
|
7878
|
-
} else if (
|
|
7879
|
-
|
|
7878
|
+
} else if (fs8.futimes) {
|
|
7879
|
+
fs8.lutimes = function(_a3, _b, _c, cb) {
|
|
7880
7880
|
if (cb) process.nextTick(cb);
|
|
7881
7881
|
};
|
|
7882
|
-
|
|
7882
|
+
fs8.lutimesSync = function() {
|
|
7883
7883
|
};
|
|
7884
7884
|
}
|
|
7885
7885
|
}
|
|
7886
7886
|
function chmodFix(orig) {
|
|
7887
7887
|
if (!orig) return orig;
|
|
7888
7888
|
return function(target, mode, cb) {
|
|
7889
|
-
return orig.call(
|
|
7889
|
+
return orig.call(fs7, target, mode, function(er) {
|
|
7890
7890
|
if (chownErOk(er)) er = null;
|
|
7891
7891
|
if (cb) cb.apply(this, arguments);
|
|
7892
7892
|
});
|
|
@@ -7896,7 +7896,7 @@ var require_polyfills = __commonJS({
|
|
|
7896
7896
|
if (!orig) return orig;
|
|
7897
7897
|
return function(target, mode) {
|
|
7898
7898
|
try {
|
|
7899
|
-
return orig.call(
|
|
7899
|
+
return orig.call(fs7, target, mode);
|
|
7900
7900
|
} catch (er) {
|
|
7901
7901
|
if (!chownErOk(er)) throw er;
|
|
7902
7902
|
}
|
|
@@ -7905,7 +7905,7 @@ var require_polyfills = __commonJS({
|
|
|
7905
7905
|
function chownFix(orig) {
|
|
7906
7906
|
if (!orig) return orig;
|
|
7907
7907
|
return function(target, uid, gid, cb) {
|
|
7908
|
-
return orig.call(
|
|
7908
|
+
return orig.call(fs7, target, uid, gid, function(er) {
|
|
7909
7909
|
if (chownErOk(er)) er = null;
|
|
7910
7910
|
if (cb) cb.apply(this, arguments);
|
|
7911
7911
|
});
|
|
@@ -7915,7 +7915,7 @@ var require_polyfills = __commonJS({
|
|
|
7915
7915
|
if (!orig) return orig;
|
|
7916
7916
|
return function(target, uid, gid) {
|
|
7917
7917
|
try {
|
|
7918
|
-
return orig.call(
|
|
7918
|
+
return orig.call(fs7, target, uid, gid);
|
|
7919
7919
|
} catch (er) {
|
|
7920
7920
|
if (!chownErOk(er)) throw er;
|
|
7921
7921
|
}
|
|
@@ -7935,13 +7935,13 @@ var require_polyfills = __commonJS({
|
|
|
7935
7935
|
}
|
|
7936
7936
|
if (cb) cb.apply(this, arguments);
|
|
7937
7937
|
}
|
|
7938
|
-
return options ? orig.call(
|
|
7938
|
+
return options ? orig.call(fs7, target, options, callback) : orig.call(fs7, target, callback);
|
|
7939
7939
|
};
|
|
7940
7940
|
}
|
|
7941
7941
|
function statFixSync(orig) {
|
|
7942
7942
|
if (!orig) return orig;
|
|
7943
7943
|
return function(target, options) {
|
|
7944
|
-
var stats = options ? orig.call(
|
|
7944
|
+
var stats = options ? orig.call(fs7, target, options) : orig.call(fs7, target);
|
|
7945
7945
|
if (stats) {
|
|
7946
7946
|
if (stats.uid < 0) stats.uid += 4294967296;
|
|
7947
7947
|
if (stats.gid < 0) stats.gid += 4294967296;
|
|
@@ -7970,16 +7970,16 @@ var require_legacy_streams = __commonJS({
|
|
|
7970
7970
|
"../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/legacy-streams.js"(exports2, module2) {
|
|
7971
7971
|
var Stream = require("stream").Stream;
|
|
7972
7972
|
module2.exports = legacy;
|
|
7973
|
-
function legacy(
|
|
7973
|
+
function legacy(fs7) {
|
|
7974
7974
|
return {
|
|
7975
7975
|
ReadStream,
|
|
7976
7976
|
WriteStream
|
|
7977
7977
|
};
|
|
7978
|
-
function ReadStream(
|
|
7979
|
-
if (!(this instanceof ReadStream)) return new ReadStream(
|
|
7978
|
+
function ReadStream(path16, options) {
|
|
7979
|
+
if (!(this instanceof ReadStream)) return new ReadStream(path16, options);
|
|
7980
7980
|
Stream.call(this);
|
|
7981
7981
|
var self = this;
|
|
7982
|
-
this.path =
|
|
7982
|
+
this.path = path16;
|
|
7983
7983
|
this.fd = null;
|
|
7984
7984
|
this.readable = true;
|
|
7985
7985
|
this.paused = false;
|
|
@@ -8013,7 +8013,7 @@ var require_legacy_streams = __commonJS({
|
|
|
8013
8013
|
});
|
|
8014
8014
|
return;
|
|
8015
8015
|
}
|
|
8016
|
-
|
|
8016
|
+
fs7.open(this.path, this.flags, this.mode, function(err, fd) {
|
|
8017
8017
|
if (err) {
|
|
8018
8018
|
self.emit("error", err);
|
|
8019
8019
|
self.readable = 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(path16, options) {
|
|
8028
|
+
if (!(this instanceof WriteStream)) return new WriteStream(path16, options);
|
|
8029
8029
|
Stream.call(this);
|
|
8030
|
-
this.path =
|
|
8030
|
+
this.path = path16;
|
|
8031
8031
|
this.fd = null;
|
|
8032
8032
|
this.writable = true;
|
|
8033
8033
|
this.flags = "w";
|
|
@@ -8052,7 +8052,7 @@ var require_legacy_streams = __commonJS({
|
|
|
8052
8052
|
this.busy = false;
|
|
8053
8053
|
this._queue = [];
|
|
8054
8054
|
if (this.fd === null) {
|
|
8055
|
-
this._open =
|
|
8055
|
+
this._open = fs7.open;
|
|
8056
8056
|
this._queue.push([this._open, this.path, this.flags, this.mode, void 0]);
|
|
8057
8057
|
this.flush();
|
|
8058
8058
|
}
|
|
@@ -8087,7 +8087,7 @@ var require_clone = __commonJS({
|
|
|
8087
8087
|
// ../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js
|
|
8088
8088
|
var require_graceful_fs = __commonJS({
|
|
8089
8089
|
"../../node_modules/.pnpm/graceful-fs@4.2.11/node_modules/graceful-fs/graceful-fs.js"(exports2, module2) {
|
|
8090
|
-
var
|
|
8090
|
+
var fs7 = require("fs");
|
|
8091
8091
|
var polyfills = require_polyfills();
|
|
8092
8092
|
var legacy = require_legacy_streams();
|
|
8093
8093
|
var clone2 = require_clone();
|
|
@@ -8119,12 +8119,12 @@ var require_graceful_fs = __commonJS({
|
|
|
8119
8119
|
m = "GFS4: " + m.split(/\n/).join("\nGFS4: ");
|
|
8120
8120
|
console.error(m);
|
|
8121
8121
|
};
|
|
8122
|
-
if (!
|
|
8122
|
+
if (!fs7[gracefulQueue]) {
|
|
8123
8123
|
queue = global[gracefulQueue] || [];
|
|
8124
|
-
publishQueue(
|
|
8125
|
-
|
|
8124
|
+
publishQueue(fs7, queue);
|
|
8125
|
+
fs7.close = function(fs$close) {
|
|
8126
8126
|
function close(fd, cb) {
|
|
8127
|
-
return fs$close.call(
|
|
8127
|
+
return fs$close.call(fs7, fd, function(err) {
|
|
8128
8128
|
if (!err) {
|
|
8129
8129
|
resetQueue();
|
|
8130
8130
|
}
|
|
@@ -8136,48 +8136,48 @@ var require_graceful_fs = __commonJS({
|
|
|
8136
8136
|
value: fs$close
|
|
8137
8137
|
});
|
|
8138
8138
|
return close;
|
|
8139
|
-
}(
|
|
8140
|
-
|
|
8139
|
+
}(fs7.close);
|
|
8140
|
+
fs7.closeSync = function(fs$closeSync) {
|
|
8141
8141
|
function closeSync(fd) {
|
|
8142
|
-
fs$closeSync.apply(
|
|
8142
|
+
fs$closeSync.apply(fs7, arguments);
|
|
8143
8143
|
resetQueue();
|
|
8144
8144
|
}
|
|
8145
8145
|
Object.defineProperty(closeSync, previousSymbol, {
|
|
8146
8146
|
value: fs$closeSync
|
|
8147
8147
|
});
|
|
8148
8148
|
return closeSync;
|
|
8149
|
-
}(
|
|
8149
|
+
}(fs7.closeSync);
|
|
8150
8150
|
if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
|
|
8151
8151
|
process.on("exit", function() {
|
|
8152
|
-
debug(
|
|
8153
|
-
require("assert").equal(
|
|
8152
|
+
debug(fs7[gracefulQueue]);
|
|
8153
|
+
require("assert").equal(fs7[gracefulQueue].length, 0);
|
|
8154
8154
|
});
|
|
8155
8155
|
}
|
|
8156
8156
|
}
|
|
8157
8157
|
var queue;
|
|
8158
8158
|
if (!global[gracefulQueue]) {
|
|
8159
|
-
publishQueue(global,
|
|
8160
|
-
}
|
|
8161
|
-
module2.exports = patch(clone2(
|
|
8162
|
-
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !
|
|
8163
|
-
module2.exports = patch(
|
|
8164
|
-
|
|
8165
|
-
}
|
|
8166
|
-
function patch(
|
|
8167
|
-
polyfills(
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
var fs$readFile =
|
|
8172
|
-
|
|
8173
|
-
function readFile2(
|
|
8159
|
+
publishQueue(global, fs7[gracefulQueue]);
|
|
8160
|
+
}
|
|
8161
|
+
module2.exports = patch(clone2(fs7));
|
|
8162
|
+
if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs7.__patched) {
|
|
8163
|
+
module2.exports = patch(fs7);
|
|
8164
|
+
fs7.__patched = true;
|
|
8165
|
+
}
|
|
8166
|
+
function patch(fs8) {
|
|
8167
|
+
polyfills(fs8);
|
|
8168
|
+
fs8.gracefulify = patch;
|
|
8169
|
+
fs8.createReadStream = createReadStream;
|
|
8170
|
+
fs8.createWriteStream = createWriteStream;
|
|
8171
|
+
var fs$readFile = fs8.readFile;
|
|
8172
|
+
fs8.readFile = readFile2;
|
|
8173
|
+
function readFile2(path16, 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(path16, options, cb);
|
|
8177
|
+
function go$readFile(path17, options2, cb2, startTime) {
|
|
8178
|
+
return fs$readFile(path17, options2, function(err) {
|
|
8179
8179
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8180
|
-
enqueue([go$readFile, [
|
|
8180
|
+
enqueue([go$readFile, [path17, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8181
8181
|
else {
|
|
8182
8182
|
if (typeof cb2 === "function")
|
|
8183
8183
|
cb2.apply(this, arguments);
|
|
@@ -8185,16 +8185,16 @@ var require_graceful_fs = __commonJS({
|
|
|
8185
8185
|
});
|
|
8186
8186
|
}
|
|
8187
8187
|
}
|
|
8188
|
-
var fs$writeFile =
|
|
8189
|
-
|
|
8190
|
-
function writeFile(
|
|
8188
|
+
var fs$writeFile = fs8.writeFile;
|
|
8189
|
+
fs8.writeFile = writeFile;
|
|
8190
|
+
function writeFile(path16, 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(path16, data, options, cb);
|
|
8194
|
+
function go$writeFile(path17, data2, options2, cb2, startTime) {
|
|
8195
|
+
return fs$writeFile(path17, data2, options2, function(err) {
|
|
8196
8196
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8197
|
-
enqueue([go$writeFile, [
|
|
8197
|
+
enqueue([go$writeFile, [path17, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8198
8198
|
else {
|
|
8199
8199
|
if (typeof cb2 === "function")
|
|
8200
8200
|
cb2.apply(this, arguments);
|
|
@@ -8202,17 +8202,17 @@ var require_graceful_fs = __commonJS({
|
|
|
8202
8202
|
});
|
|
8203
8203
|
}
|
|
8204
8204
|
}
|
|
8205
|
-
var fs$appendFile =
|
|
8205
|
+
var fs$appendFile = fs8.appendFile;
|
|
8206
8206
|
if (fs$appendFile)
|
|
8207
|
-
|
|
8208
|
-
function appendFile(
|
|
8207
|
+
fs8.appendFile = appendFile;
|
|
8208
|
+
function appendFile(path16, 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(path16, data, options, cb);
|
|
8212
|
+
function go$appendFile(path17, data2, options2, cb2, startTime) {
|
|
8213
|
+
return fs$appendFile(path17, data2, options2, function(err) {
|
|
8214
8214
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8215
|
-
enqueue([go$appendFile, [
|
|
8215
|
+
enqueue([go$appendFile, [path17, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8216
8216
|
else {
|
|
8217
8217
|
if (typeof cb2 === "function")
|
|
8218
8218
|
cb2.apply(this, arguments);
|
|
@@ -8220,9 +8220,9 @@ var require_graceful_fs = __commonJS({
|
|
|
8220
8220
|
});
|
|
8221
8221
|
}
|
|
8222
8222
|
}
|
|
8223
|
-
var fs$copyFile =
|
|
8223
|
+
var fs$copyFile = fs8.copyFile;
|
|
8224
8224
|
if (fs$copyFile)
|
|
8225
|
-
|
|
8225
|
+
fs8.copyFile = copyFile;
|
|
8226
8226
|
function copyFile(src, dest, flags, cb) {
|
|
8227
8227
|
if (typeof flags === "function") {
|
|
8228
8228
|
cb = flags;
|
|
@@ -8240,34 +8240,34 @@ var require_graceful_fs = __commonJS({
|
|
|
8240
8240
|
});
|
|
8241
8241
|
}
|
|
8242
8242
|
}
|
|
8243
|
-
var fs$readdir =
|
|
8244
|
-
|
|
8243
|
+
var fs$readdir = fs8.readdir;
|
|
8244
|
+
fs8.readdir = readdir2;
|
|
8245
8245
|
var noReaddirOptionVersions = /^v[0-5]\./;
|
|
8246
|
-
function
|
|
8246
|
+
function readdir2(path16, 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(path17, options2, cb2, startTime) {
|
|
8250
|
+
return fs$readdir(path17, fs$readdirCallback(
|
|
8251
|
+
path17,
|
|
8252
8252
|
options2,
|
|
8253
8253
|
cb2,
|
|
8254
8254
|
startTime
|
|
8255
8255
|
));
|
|
8256
|
-
} : function go$readdir2(
|
|
8257
|
-
return fs$readdir(
|
|
8258
|
-
|
|
8256
|
+
} : function go$readdir2(path17, options2, cb2, startTime) {
|
|
8257
|
+
return fs$readdir(path17, options2, fs$readdirCallback(
|
|
8258
|
+
path17,
|
|
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(path16, options, cb);
|
|
8265
|
+
function fs$readdirCallback(path17, 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
|
+
[path17, options2, cb2],
|
|
8271
8271
|
err,
|
|
8272
8272
|
startTime || Date.now(),
|
|
8273
8273
|
Date.now()
|
|
@@ -8282,21 +8282,21 @@ var require_graceful_fs = __commonJS({
|
|
|
8282
8282
|
}
|
|
8283
8283
|
}
|
|
8284
8284
|
if (process.version.substr(0, 4) === "v0.8") {
|
|
8285
|
-
var legStreams = legacy(
|
|
8285
|
+
var legStreams = legacy(fs8);
|
|
8286
8286
|
ReadStream = legStreams.ReadStream;
|
|
8287
8287
|
WriteStream = legStreams.WriteStream;
|
|
8288
8288
|
}
|
|
8289
|
-
var fs$ReadStream =
|
|
8289
|
+
var fs$ReadStream = fs8.ReadStream;
|
|
8290
8290
|
if (fs$ReadStream) {
|
|
8291
8291
|
ReadStream.prototype = Object.create(fs$ReadStream.prototype);
|
|
8292
8292
|
ReadStream.prototype.open = ReadStream$open;
|
|
8293
8293
|
}
|
|
8294
|
-
var fs$WriteStream =
|
|
8294
|
+
var fs$WriteStream = fs8.WriteStream;
|
|
8295
8295
|
if (fs$WriteStream) {
|
|
8296
8296
|
WriteStream.prototype = Object.create(fs$WriteStream.prototype);
|
|
8297
8297
|
WriteStream.prototype.open = WriteStream$open;
|
|
8298
8298
|
}
|
|
8299
|
-
Object.defineProperty(
|
|
8299
|
+
Object.defineProperty(fs8, "ReadStream", {
|
|
8300
8300
|
get: function() {
|
|
8301
8301
|
return ReadStream;
|
|
8302
8302
|
},
|
|
@@ -8306,7 +8306,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8306
8306
|
enumerable: true,
|
|
8307
8307
|
configurable: true
|
|
8308
8308
|
});
|
|
8309
|
-
Object.defineProperty(
|
|
8309
|
+
Object.defineProperty(fs8, "WriteStream", {
|
|
8310
8310
|
get: function() {
|
|
8311
8311
|
return WriteStream;
|
|
8312
8312
|
},
|
|
@@ -8317,7 +8317,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8317
8317
|
configurable: true
|
|
8318
8318
|
});
|
|
8319
8319
|
var FileReadStream = ReadStream;
|
|
8320
|
-
Object.defineProperty(
|
|
8320
|
+
Object.defineProperty(fs8, "FileReadStream", {
|
|
8321
8321
|
get: function() {
|
|
8322
8322
|
return FileReadStream;
|
|
8323
8323
|
},
|
|
@@ -8328,7 +8328,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8328
8328
|
configurable: true
|
|
8329
8329
|
});
|
|
8330
8330
|
var FileWriteStream = WriteStream;
|
|
8331
|
-
Object.defineProperty(
|
|
8331
|
+
Object.defineProperty(fs8, "FileWriteStream", {
|
|
8332
8332
|
get: function() {
|
|
8333
8333
|
return FileWriteStream;
|
|
8334
8334
|
},
|
|
@@ -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(path16, 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(path16, 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
|
|
8379
|
+
function createReadStream(path16, options) {
|
|
8380
|
+
return new fs8.ReadStream(path16, options);
|
|
8381
8381
|
}
|
|
8382
|
-
function createWriteStream(
|
|
8383
|
-
return new
|
|
8382
|
+
function createWriteStream(path16, options) {
|
|
8383
|
+
return new fs8.WriteStream(path16, options);
|
|
8384
8384
|
}
|
|
8385
|
-
var fs$open =
|
|
8386
|
-
|
|
8387
|
-
function open(
|
|
8385
|
+
var fs$open = fs8.open;
|
|
8386
|
+
fs8.open = open;
|
|
8387
|
+
function open(path16, 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(path16, flags, mode, cb);
|
|
8391
|
+
function go$open(path17, flags2, mode2, cb2, startTime) {
|
|
8392
|
+
return fs$open(path17, flags2, mode2, function(err, fd) {
|
|
8393
8393
|
if (err && (err.code === "EMFILE" || err.code === "ENFILE"))
|
|
8394
|
-
enqueue([go$open, [
|
|
8394
|
+
enqueue([go$open, [path17, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
|
|
8395
8395
|
else {
|
|
8396
8396
|
if (typeof cb2 === "function")
|
|
8397
8397
|
cb2.apply(this, arguments);
|
|
@@ -8399,20 +8399,20 @@ var require_graceful_fs = __commonJS({
|
|
|
8399
8399
|
});
|
|
8400
8400
|
}
|
|
8401
8401
|
}
|
|
8402
|
-
return
|
|
8402
|
+
return fs8;
|
|
8403
8403
|
}
|
|
8404
8404
|
function enqueue(elem) {
|
|
8405
8405
|
debug("ENQUEUE", elem[0].name, elem[1]);
|
|
8406
|
-
|
|
8406
|
+
fs7[gracefulQueue].push(elem);
|
|
8407
8407
|
retry();
|
|
8408
8408
|
}
|
|
8409
8409
|
var retryTimer;
|
|
8410
8410
|
function resetQueue() {
|
|
8411
8411
|
var now = Date.now();
|
|
8412
|
-
for (var i = 0; i <
|
|
8413
|
-
if (
|
|
8414
|
-
|
|
8415
|
-
|
|
8412
|
+
for (var i = 0; i < fs7[gracefulQueue].length; ++i) {
|
|
8413
|
+
if (fs7[gracefulQueue][i].length > 2) {
|
|
8414
|
+
fs7[gracefulQueue][i][3] = now;
|
|
8415
|
+
fs7[gracefulQueue][i][4] = now;
|
|
8416
8416
|
}
|
|
8417
8417
|
}
|
|
8418
8418
|
retry();
|
|
@@ -8420,9 +8420,9 @@ var require_graceful_fs = __commonJS({
|
|
|
8420
8420
|
function retry() {
|
|
8421
8421
|
clearTimeout(retryTimer);
|
|
8422
8422
|
retryTimer = void 0;
|
|
8423
|
-
if (
|
|
8423
|
+
if (fs7[gracefulQueue].length === 0)
|
|
8424
8424
|
return;
|
|
8425
|
-
var elem =
|
|
8425
|
+
var elem = fs7[gracefulQueue].shift();
|
|
8426
8426
|
var fn = elem[0];
|
|
8427
8427
|
var args = elem[1];
|
|
8428
8428
|
var err = elem[2];
|
|
@@ -8444,7 +8444,7 @@ var require_graceful_fs = __commonJS({
|
|
|
8444
8444
|
debug("RETRY", fn.name, args);
|
|
8445
8445
|
fn.apply(null, args.concat([startTime]));
|
|
8446
8446
|
} else {
|
|
8447
|
-
|
|
8447
|
+
fs7[gracefulQueue].push(elem);
|
|
8448
8448
|
}
|
|
8449
8449
|
}
|
|
8450
8450
|
if (retryTimer === void 0) {
|
|
@@ -8879,10 +8879,10 @@ var require_mtime_precision = __commonJS({
|
|
|
8879
8879
|
"../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/mtime-precision.js"(exports2, module2) {
|
|
8880
8880
|
"use strict";
|
|
8881
8881
|
var cacheSymbol = Symbol();
|
|
8882
|
-
function probe(file2,
|
|
8883
|
-
const cachedPrecision =
|
|
8882
|
+
function probe(file2, fs7, callback) {
|
|
8883
|
+
const cachedPrecision = fs7[cacheSymbol];
|
|
8884
8884
|
if (cachedPrecision) {
|
|
8885
|
-
return
|
|
8885
|
+
return fs7.stat(file2, (err, stat2) => {
|
|
8886
8886
|
if (err) {
|
|
8887
8887
|
return callback(err);
|
|
8888
8888
|
}
|
|
@@ -8890,16 +8890,16 @@ var require_mtime_precision = __commonJS({
|
|
|
8890
8890
|
});
|
|
8891
8891
|
}
|
|
8892
8892
|
const mtime = new Date(Math.ceil(Date.now() / 1e3) * 1e3 + 5);
|
|
8893
|
-
|
|
8893
|
+
fs7.utimes(file2, mtime, mtime, (err) => {
|
|
8894
8894
|
if (err) {
|
|
8895
8895
|
return callback(err);
|
|
8896
8896
|
}
|
|
8897
|
-
|
|
8897
|
+
fs7.stat(file2, (err2, stat2) => {
|
|
8898
8898
|
if (err2) {
|
|
8899
8899
|
return callback(err2);
|
|
8900
8900
|
}
|
|
8901
8901
|
const precision = stat2.mtime.getTime() % 1e3 === 0 ? "s" : "ms";
|
|
8902
|
-
Object.defineProperty(
|
|
8902
|
+
Object.defineProperty(fs7, cacheSymbol, { value: precision });
|
|
8903
8903
|
callback(null, stat2.mtime, precision);
|
|
8904
8904
|
});
|
|
8905
8905
|
});
|
|
@@ -8920,8 +8920,8 @@ 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
|
|
8924
|
-
var
|
|
8923
|
+
var path16 = require("path");
|
|
8924
|
+
var fs7 = require_graceful_fs();
|
|
8925
8925
|
var retry = require_retry2();
|
|
8926
8926
|
var onExit = require_signal_exit();
|
|
8927
8927
|
var mtimePrecision = require_mtime_precision();
|
|
@@ -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, path16.resolve(file2));
|
|
8935
8935
|
}
|
|
8936
8936
|
options.fs.realpath(file2, callback);
|
|
8937
8937
|
}
|
|
@@ -9052,7 +9052,7 @@ var require_lockfile = __commonJS({
|
|
|
9052
9052
|
update: null,
|
|
9053
9053
|
realpath: true,
|
|
9054
9054
|
retries: 0,
|
|
9055
|
-
fs:
|
|
9055
|
+
fs: fs7,
|
|
9056
9056
|
onCompromised: (err) => {
|
|
9057
9057
|
throw err;
|
|
9058
9058
|
},
|
|
@@ -9096,7 +9096,7 @@ var require_lockfile = __commonJS({
|
|
|
9096
9096
|
}
|
|
9097
9097
|
function unlock(file2, options, callback) {
|
|
9098
9098
|
options = {
|
|
9099
|
-
fs:
|
|
9099
|
+
fs: fs7,
|
|
9100
9100
|
realpath: true,
|
|
9101
9101
|
...options
|
|
9102
9102
|
};
|
|
@@ -9118,7 +9118,7 @@ var require_lockfile = __commonJS({
|
|
|
9118
9118
|
options = {
|
|
9119
9119
|
stale: 1e4,
|
|
9120
9120
|
realpath: true,
|
|
9121
|
-
fs:
|
|
9121
|
+
fs: fs7,
|
|
9122
9122
|
...options
|
|
9123
9123
|
};
|
|
9124
9124
|
options.stale = Math.max(options.stale || 0, 2e3);
|
|
@@ -9157,16 +9157,16 @@ var require_lockfile = __commonJS({
|
|
|
9157
9157
|
var require_adapter = __commonJS({
|
|
9158
9158
|
"../../node_modules/.pnpm/proper-lockfile@4.1.2/node_modules/proper-lockfile/lib/adapter.js"(exports2, module2) {
|
|
9159
9159
|
"use strict";
|
|
9160
|
-
var
|
|
9161
|
-
function createSyncFs(
|
|
9160
|
+
var fs7 = require_graceful_fs();
|
|
9161
|
+
function createSyncFs(fs8) {
|
|
9162
9162
|
const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
|
|
9163
|
-
const newFs = { ...
|
|
9163
|
+
const newFs = { ...fs8 };
|
|
9164
9164
|
methods.forEach((method) => {
|
|
9165
9165
|
newFs[method] = (...args) => {
|
|
9166
9166
|
const callback = args.pop();
|
|
9167
9167
|
let ret;
|
|
9168
9168
|
try {
|
|
9169
|
-
ret =
|
|
9169
|
+
ret = fs8[`${method}Sync`](...args);
|
|
9170
9170
|
} catch (err) {
|
|
9171
9171
|
return callback(err);
|
|
9172
9172
|
}
|
|
@@ -9204,7 +9204,7 @@ var require_adapter = __commonJS({
|
|
|
9204
9204
|
}
|
|
9205
9205
|
function toSyncOptions(options) {
|
|
9206
9206
|
options = { ...options };
|
|
9207
|
-
options.fs = createSyncFs(options.fs ||
|
|
9207
|
+
options.fs = createSyncFs(options.fs || fs7);
|
|
9208
9208
|
if (typeof options.retries === "number" && options.retries > 0 || options.retries && typeof options.retries.retries === "number" && options.retries.retries > 0) {
|
|
9209
9209
|
throw Object.assign(new Error("Cannot use retries with the sync api"), { code: "ESYNC" });
|
|
9210
9210
|
}
|
|
@@ -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 path16 = 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 < path16.length - 1; i++) {
|
|
10801
|
+
optimizedSegs.push(graph.table[path16[i]].node);
|
|
10802
10802
|
}
|
|
10803
10803
|
return exports2.fromArray(mergeSegments(optimizedSegs));
|
|
10804
10804
|
};
|
|
@@ -13234,7 +13234,7 @@ var require_utils2 = __commonJS({
|
|
|
13234
13234
|
// ../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js
|
|
13235
13235
|
var require_png2 = __commonJS({
|
|
13236
13236
|
"../../node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/png.js"(exports2) {
|
|
13237
|
-
var
|
|
13237
|
+
var fs7 = require("fs");
|
|
13238
13238
|
var PNG = require_png().PNG;
|
|
13239
13239
|
var Utils = require_utils2();
|
|
13240
13240
|
exports2.render = function render(qrData, options) {
|
|
@@ -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(path16, 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 =
|
|
13289
|
+
const stream = fs7.createWriteStream(path16);
|
|
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(path16, qrData, options, cb) {
|
|
13352
13352
|
if (typeof cb === "undefined") {
|
|
13353
13353
|
cb = options;
|
|
13354
13354
|
options = void 0;
|
|
13355
13355
|
}
|
|
13356
|
-
const
|
|
13356
|
+
const fs7 = require("fs");
|
|
13357
13357
|
const utf8 = exports2.render(qrData, options);
|
|
13358
|
-
|
|
13358
|
+
fs7.writeFile(path16, 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 path16 = "";
|
|
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
|
+
path16 += 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
|
+
path16 += svgCmd("h", lineLength);
|
|
13496
13496
|
lineLength = 0;
|
|
13497
13497
|
}
|
|
13498
13498
|
} else {
|
|
13499
13499
|
moveBy++;
|
|
13500
13500
|
}
|
|
13501
13501
|
}
|
|
13502
|
-
return
|
|
13502
|
+
return path16;
|
|
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 path16 = "<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 + path16 + "</svg>\n";
|
|
13514
13514
|
if (typeof cb === "function") {
|
|
13515
13515
|
cb(null, svgTag);
|
|
13516
13516
|
}
|
|
@@ -13524,15 +13524,15 @@ 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(path16, qrData, options, cb) {
|
|
13528
13528
|
if (typeof cb === "undefined") {
|
|
13529
13529
|
cb = options;
|
|
13530
13530
|
options = void 0;
|
|
13531
13531
|
}
|
|
13532
|
-
const
|
|
13532
|
+
const fs7 = 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
|
-
|
|
13535
|
+
fs7.writeFile(path16, 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(path16) {
|
|
13694
|
+
return path16.slice((path16.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(path16, text, opts, cb) {
|
|
13759
|
+
if (typeof path16 !== "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(path16);
|
|
13767
13767
|
const renderer = getRendererFromType(type);
|
|
13768
|
-
const renderToFile = renderer.renderToFile.bind(null,
|
|
13768
|
+
const renderToFile = renderer.renderToFile.bind(null, path16);
|
|
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(path16) {
|
|
16987
|
+
let input = path16;
|
|
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 [path16, query] = wsComponent.resourceName.split("?");
|
|
17240
|
+
wsComponent.path = path16 && path16 !== "/" ? path16 : void 0;
|
|
17241
17241
|
wsComponent.query = query;
|
|
17242
17242
|
wsComponent.resourceName = void 0;
|
|
17243
17243
|
}
|
|
@@ -20630,12 +20630,12 @@ var require_dist = __commonJS({
|
|
|
20630
20630
|
throw new Error(`Unknown format "${name}"`);
|
|
20631
20631
|
return f;
|
|
20632
20632
|
};
|
|
20633
|
-
function addFormats(ajv, list,
|
|
20633
|
+
function addFormats(ajv, list, fs7, exportName) {
|
|
20634
20634
|
var _a3;
|
|
20635
20635
|
var _b;
|
|
20636
20636
|
(_a3 = (_b = ajv.opts.code).formats) !== null && _a3 !== void 0 ? _a3 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
20637
20637
|
for (const f of list)
|
|
20638
|
-
ajv.addFormat(f,
|
|
20638
|
+
ajv.addFormat(f, fs7[f]);
|
|
20639
20639
|
}
|
|
20640
20640
|
module2.exports = exports2 = formatsPlugin;
|
|
20641
20641
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -20644,59 +20644,142 @@ var require_dist = __commonJS({
|
|
|
20644
20644
|
});
|
|
20645
20645
|
|
|
20646
20646
|
// src/bin.ts
|
|
20647
|
-
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
20648
|
-
var import_node_child_process8 = require("node:child_process");
|
|
20649
|
-
var import_node_fs16 = require("node:fs");
|
|
20650
|
-
var import_node_os12 = require("node:os");
|
|
20651
20647
|
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
20648
|
+
var import_node_child_process9 = require("node:child_process");
|
|
20649
|
+
var import_node_fs16 = require("node:fs");
|
|
20650
|
+
var import_node_os13 = require("node:os");
|
|
20651
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
20652
20652
|
|
|
20653
20653
|
// src/install-codex.ts
|
|
20654
20654
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
20655
|
+
var import_node_os2 = __toESM(require("node:os"), 1);
|
|
20656
|
+
var import_node_path2 = __toESM(require("node:path"), 1);
|
|
20657
|
+
var toml = __toESM(require_toml(), 1);
|
|
20658
|
+
|
|
20659
|
+
// src/browser-runtime.ts
|
|
20655
20660
|
var import_node_os = __toESM(require("node:os"), 1);
|
|
20656
20661
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
20657
|
-
var
|
|
20662
|
+
var fs = __toESM(require("node:fs/promises"), 1);
|
|
20663
|
+
var import_node_child_process = require("node:child_process");
|
|
20664
|
+
var import_node_module = require("node:module");
|
|
20665
|
+
var import_node_url = require("node:url");
|
|
20666
|
+
var import_meta = {};
|
|
20667
|
+
function moduleRequire() {
|
|
20668
|
+
const base = typeof __dirname !== "undefined" ? import_node_path.default.join(__dirname, "browser-runtime.js") : (0, import_node_url.fileURLToPath)(import_meta.url);
|
|
20669
|
+
return (0, import_node_module.createRequire)(base);
|
|
20670
|
+
}
|
|
20671
|
+
function browserPaths(homeDir = import_node_os.default.homedir()) {
|
|
20672
|
+
const root = import_node_path.default.join(homeDir, ".mrrlin", "browser");
|
|
20673
|
+
return { root, browsersPath: import_node_path.default.join(root, "browsers"), profilePath: import_node_path.default.join(root, "profile") };
|
|
20674
|
+
}
|
|
20675
|
+
function resolvePackageBin(pkg) {
|
|
20676
|
+
const require2 = moduleRequire();
|
|
20677
|
+
const pkgJsonPath = require2.resolve(`${pkg}/package.json`);
|
|
20678
|
+
const pkgJson = require2(`${pkg}/package.json`);
|
|
20679
|
+
const bin = pkgJson.bin;
|
|
20680
|
+
const rel = typeof bin === "string" ? bin : bin ? Object.values(bin)[0] : void 0;
|
|
20681
|
+
if (!rel) throw new Error(`${pkg} has no bin entry to resolve a CLI from`);
|
|
20682
|
+
return import_node_path.default.join(import_node_path.default.dirname(pkgJsonPath), rel);
|
|
20683
|
+
}
|
|
20684
|
+
function browserServeArgs(homeDir = import_node_os.default.homedir()) {
|
|
20685
|
+
const { browsersPath, profilePath } = browserPaths(homeDir);
|
|
20686
|
+
const cli = resolvePackageBin("@playwright/mcp");
|
|
20687
|
+
return {
|
|
20688
|
+
command: process.execPath,
|
|
20689
|
+
// node
|
|
20690
|
+
args: [cli, "--browser", "chromium", "--user-data-dir", profilePath],
|
|
20691
|
+
env: { PLAYWRIGHT_BROWSERS_PATH: browsersPath }
|
|
20692
|
+
};
|
|
20693
|
+
}
|
|
20694
|
+
async function installBrowser(opts = {}) {
|
|
20695
|
+
const homeDir = opts.homeDir ?? import_node_os.default.homedir();
|
|
20696
|
+
const { browsersPath } = browserPaths(homeDir);
|
|
20697
|
+
const alreadyInstalled = opts.alreadyInstalled ?? (async (candidateBrowsersPath) => {
|
|
20698
|
+
try {
|
|
20699
|
+
const entries = await fs.readdir(candidateBrowsersPath);
|
|
20700
|
+
return entries.some((entry) => entry.startsWith("chromium"));
|
|
20701
|
+
} catch (error51) {
|
|
20702
|
+
if (error51.code === "ENOENT") {
|
|
20703
|
+
return false;
|
|
20704
|
+
}
|
|
20705
|
+
throw error51;
|
|
20706
|
+
}
|
|
20707
|
+
});
|
|
20708
|
+
if (await alreadyInstalled(browsersPath)) {
|
|
20709
|
+
return { action: "noop", browsersPath };
|
|
20710
|
+
}
|
|
20711
|
+
const run2 = opts.run ?? (async (cmd, args, env2) => {
|
|
20712
|
+
const r = (0, import_node_child_process.spawnSync)(cmd, args, { encoding: "utf8", env: env2, stdio: ["ignore", "inherit", "pipe"] });
|
|
20713
|
+
return { code: r.status ?? 1, stderr: r.stderr ?? "" };
|
|
20714
|
+
});
|
|
20715
|
+
const playwrightCli = resolvePackageBin("playwright-core");
|
|
20716
|
+
const env = { ...process.env, PLAYWRIGHT_BROWSERS_PATH: browsersPath };
|
|
20717
|
+
const result = await run2(process.execPath, [playwrightCli, "install", "chromium"], env);
|
|
20718
|
+
if (result.code !== 0) {
|
|
20719
|
+
throw new Error(
|
|
20720
|
+
`install-browser failed (exit ${result.code}). Fix the issue (often network/proxy), then re-run \`mrrlin-mcp install-browser\`: ${result.stderr.trim()}`
|
|
20721
|
+
);
|
|
20722
|
+
}
|
|
20723
|
+
return { action: "installed", browsersPath };
|
|
20724
|
+
}
|
|
20725
|
+
|
|
20726
|
+
// src/install-codex.ts
|
|
20658
20727
|
function resolveCodexHome(options) {
|
|
20659
20728
|
if (options.codexHome) return options.codexHome;
|
|
20660
20729
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
20661
|
-
return
|
|
20730
|
+
return import_node_path2.default.join(options.homeDir ?? import_node_os2.default.homedir(), ".codex");
|
|
20662
20731
|
}
|
|
20663
|
-
function
|
|
20664
|
-
if (distribution === "npm") {
|
|
20665
|
-
|
|
20666
|
-
|
|
20667
|
-
|
|
20668
|
-
|
|
20669
|
-
|
|
20670
|
-
|
|
20671
|
-
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20732
|
+
function mrrlinTable(binPath, distribution) {
|
|
20733
|
+
if (distribution === "npm") return { command: "mrrlin-mcp", args: ["serve"], startup_timeout_sec: 30 };
|
|
20734
|
+
return { command: "node", args: [binPath, "serve"], startup_timeout_sec: 30 };
|
|
20735
|
+
}
|
|
20736
|
+
function browserTable(binPath, distribution, homeDir) {
|
|
20737
|
+
const base = distribution === "npm" ? { command: "mrrlin-mcp", args: ["browser-serve"] } : { command: "node", args: [binPath, "browser-serve"] };
|
|
20738
|
+
return { ...base, startup_timeout_sec: 30, env: { PLAYWRIGHT_BROWSERS_PATH: browserPaths(homeDir).browsersPath } };
|
|
20739
|
+
}
|
|
20740
|
+
function blockRegex(id) {
|
|
20741
|
+
const escaped = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
20742
|
+
return new RegExp(`(^|\\n)\\[mcp_servers\\.${escaped}\\][\\s\\S]*?(?=\\n\\[|$)`);
|
|
20743
|
+
}
|
|
20744
|
+
function managedBlocks(options, distribution) {
|
|
20745
|
+
const homeDir = options.homeDir ?? import_node_os2.default.homedir();
|
|
20746
|
+
return [
|
|
20747
|
+
{ id: "mrrlin", expected: mrrlinTable(options.binPath, distribution), blockRe: blockRegex("mrrlin") },
|
|
20748
|
+
{
|
|
20749
|
+
id: "mrrlin-browser",
|
|
20750
|
+
expected: browserTable(options.binPath, distribution, homeDir),
|
|
20751
|
+
blockRe: blockRegex("mrrlin-browser")
|
|
20752
|
+
}
|
|
20753
|
+
];
|
|
20676
20754
|
}
|
|
20677
20755
|
async function detectInstallDistribution(options) {
|
|
20678
20756
|
if (options.distribution && options.distribution !== "auto") return options.distribution;
|
|
20679
|
-
let current =
|
|
20757
|
+
let current = import_node_path2.default.dirname(options.binPath);
|
|
20680
20758
|
while (true) {
|
|
20681
|
-
if (await pathExists(
|
|
20759
|
+
if (await pathExists(import_node_path2.default.join(current, "pnpm-workspace.yaml"))) {
|
|
20682
20760
|
return "local";
|
|
20683
20761
|
}
|
|
20684
|
-
const parent =
|
|
20762
|
+
const parent = import_node_path2.default.dirname(current);
|
|
20685
20763
|
if (parent === current) break;
|
|
20686
20764
|
current = parent;
|
|
20687
20765
|
}
|
|
20688
20766
|
return "npm";
|
|
20689
20767
|
}
|
|
20690
|
-
function renderBlock(
|
|
20691
|
-
const expected =
|
|
20692
|
-
|
|
20768
|
+
function renderBlock(block) {
|
|
20769
|
+
const { id, expected } = block;
|
|
20770
|
+
const lines2 = [
|
|
20693
20771
|
"",
|
|
20694
|
-
|
|
20695
|
-
`command =
|
|
20772
|
+
`[mcp_servers.${id}]`,
|
|
20773
|
+
`command = ${JSON.stringify(expected.command)}`,
|
|
20696
20774
|
`args = [${expected.args.map((value) => JSON.stringify(value)).join(", ")}]`,
|
|
20697
|
-
`startup_timeout_sec = ${expected.startup_timeout_sec}
|
|
20698
|
-
|
|
20699
|
-
|
|
20775
|
+
`startup_timeout_sec = ${expected.startup_timeout_sec}`
|
|
20776
|
+
];
|
|
20777
|
+
if (expected.env && Object.keys(expected.env).length > 0) {
|
|
20778
|
+
const inline = Object.entries(expected.env).map(([key, value]) => `${key} = ${JSON.stringify(value)}`).join(", ");
|
|
20779
|
+
lines2.push(`env = { ${inline} }`);
|
|
20780
|
+
}
|
|
20781
|
+
lines2.push("");
|
|
20782
|
+
return lines2.join("\n");
|
|
20700
20783
|
}
|
|
20701
20784
|
function tablesEqual(actual, expected) {
|
|
20702
20785
|
if (typeof actual !== "object" || actual === null) return false;
|
|
@@ -20710,6 +20793,13 @@ function tablesEqual(actual, expected) {
|
|
|
20710
20793
|
if (candidate.startup_timeout_sec !== void 0 && candidate.startup_timeout_sec !== expected.startup_timeout_sec) {
|
|
20711
20794
|
return false;
|
|
20712
20795
|
}
|
|
20796
|
+
const expectedEnv = expected.env ?? {};
|
|
20797
|
+
const actualEnv = candidate.env && typeof candidate.env === "object" ? candidate.env : {};
|
|
20798
|
+
const expectedKeys = Object.keys(expectedEnv);
|
|
20799
|
+
if (expectedKeys.length !== Object.keys(actualEnv).length) return false;
|
|
20800
|
+
for (const key of expectedKeys) {
|
|
20801
|
+
if (actualEnv[key] !== expectedEnv[key]) return false;
|
|
20802
|
+
}
|
|
20713
20803
|
return true;
|
|
20714
20804
|
}
|
|
20715
20805
|
async function pathExists(target) {
|
|
@@ -20729,19 +20819,21 @@ async function resolveRealConfigPath(configPath) {
|
|
|
20729
20819
|
}
|
|
20730
20820
|
async function installCodex(options) {
|
|
20731
20821
|
const codexHome = resolveCodexHome(options);
|
|
20732
|
-
const configPath =
|
|
20822
|
+
const configPath = import_node_path2.default.join(codexHome, "config.toml");
|
|
20733
20823
|
const distribution = await detectInstallDistribution(options);
|
|
20734
20824
|
await import_promises.default.mkdir(codexHome, { recursive: true, mode: 448 });
|
|
20735
20825
|
const writePrompts = async () => installPrompts(codexHome, options.prompts ?? [], options.forcePrompts === true);
|
|
20826
|
+
const blocks = managedBlocks(options, distribution);
|
|
20736
20827
|
if (!await pathExists(configPath)) {
|
|
20737
|
-
|
|
20828
|
+
const content2 = blocks.map(renderBlock).join("").replace(/^\n/, "");
|
|
20829
|
+
await import_promises.default.writeFile(configPath, content2, { mode: 384 });
|
|
20738
20830
|
return { action: "created", configPath, prompts: await writePrompts() };
|
|
20739
20831
|
}
|
|
20740
20832
|
const realPath = await resolveRealConfigPath(configPath);
|
|
20741
|
-
|
|
20833
|
+
let content = await import_promises.default.readFile(realPath, "utf8");
|
|
20742
20834
|
let parsed = null;
|
|
20743
20835
|
try {
|
|
20744
|
-
parsed = toml.parse(
|
|
20836
|
+
parsed = toml.parse(content);
|
|
20745
20837
|
} catch (error51) {
|
|
20746
20838
|
const detail = error51 instanceof Error ? error51.message : String(error51);
|
|
20747
20839
|
const err = {
|
|
@@ -20751,34 +20843,38 @@ async function installCodex(options) {
|
|
|
20751
20843
|
};
|
|
20752
20844
|
throw Object.assign(new Error(err.detail), err);
|
|
20753
20845
|
}
|
|
20754
|
-
|
|
20755
|
-
|
|
20756
|
-
|
|
20757
|
-
|
|
20758
|
-
|
|
20759
|
-
|
|
20760
|
-
|
|
20761
|
-
|
|
20762
|
-
|
|
20763
|
-
|
|
20764
|
-
|
|
20765
|
-
|
|
20846
|
+
let action = "noop";
|
|
20847
|
+
for (const block of blocks) {
|
|
20848
|
+
const existingTable = parsed?.mcp_servers?.[block.id];
|
|
20849
|
+
if (existingTable !== void 0) {
|
|
20850
|
+
if (tablesEqual(existingTable, block.expected)) continue;
|
|
20851
|
+
if (!options.force) {
|
|
20852
|
+
const err = {
|
|
20853
|
+
code: "CODEX_CONFIG_CONFLICT",
|
|
20854
|
+
configPath: realPath,
|
|
20855
|
+
detail: `An [mcp_servers.${block.id}] block already exists with different settings. Re-run with --force to replace it, or remove it manually.`
|
|
20856
|
+
};
|
|
20857
|
+
throw Object.assign(new Error(err.detail), err);
|
|
20858
|
+
}
|
|
20859
|
+
content = replaceBlock(content, block.blockRe, renderBlock(block));
|
|
20860
|
+
action = "replaced";
|
|
20861
|
+
} else {
|
|
20862
|
+
content = appendBlock(content, renderBlock(block));
|
|
20863
|
+
if (action !== "replaced") action = "appended";
|
|
20766
20864
|
}
|
|
20767
|
-
const replaced = replaceMrrlinBlock(existing, renderBlock(options.binPath, distribution));
|
|
20768
|
-
await import_promises.default.writeFile(realPath, replaced, { mode: 384 });
|
|
20769
|
-
return { action: "replaced", configPath: realPath, prompts: await writePrompts() };
|
|
20770
20865
|
}
|
|
20771
|
-
|
|
20772
|
-
|
|
20773
|
-
|
|
20866
|
+
if (action !== "noop") {
|
|
20867
|
+
await import_promises.default.writeFile(realPath, content, { mode: 384 });
|
|
20868
|
+
}
|
|
20869
|
+
return { action, configPath: realPath, prompts: await writePrompts() };
|
|
20774
20870
|
}
|
|
20775
20871
|
async function installPrompts(codexHome, prompts, forcePrompts) {
|
|
20776
20872
|
if (prompts.length === 0) return [];
|
|
20777
|
-
const promptsDir2 =
|
|
20873
|
+
const promptsDir2 = import_node_path2.default.join(codexHome, "prompts");
|
|
20778
20874
|
await import_promises.default.mkdir(promptsDir2, { recursive: true, mode: 448 });
|
|
20779
20875
|
const out = [];
|
|
20780
20876
|
for (const prompt of prompts) {
|
|
20781
|
-
const promptPath =
|
|
20877
|
+
const promptPath = import_node_path2.default.join(promptsDir2, `${prompt.name}.md`);
|
|
20782
20878
|
let existing = null;
|
|
20783
20879
|
try {
|
|
20784
20880
|
existing = await import_promises.default.readFile(promptPath, "utf8");
|
|
@@ -20803,17 +20899,16 @@ async function installPrompts(codexHome, prompts, forcePrompts) {
|
|
|
20803
20899
|
}
|
|
20804
20900
|
return out;
|
|
20805
20901
|
}
|
|
20806
|
-
function
|
|
20902
|
+
function appendBlock(existing, block) {
|
|
20807
20903
|
const trimmed = existing.replace(/\s+$/, "");
|
|
20808
20904
|
return `${trimmed}
|
|
20809
20905
|
${block.startsWith("\n") ? block : `
|
|
20810
20906
|
${block}`}`.replace(/\n{3,}/g, "\n\n");
|
|
20811
20907
|
}
|
|
20812
|
-
|
|
20813
|
-
function replaceMrrlinBlock(existing, block) {
|
|
20908
|
+
function replaceBlock(existing, blockRe, block) {
|
|
20814
20909
|
const replacement = block.startsWith("\n") ? block : `
|
|
20815
20910
|
${block}`;
|
|
20816
|
-
return existing.replace(
|
|
20911
|
+
return existing.replace(blockRe, (match) => {
|
|
20817
20912
|
const prefix = match.startsWith("\n") ? "\n" : "";
|
|
20818
20913
|
return `${prefix}${replacement.replace(/^\n+/, "")}`;
|
|
20819
20914
|
});
|
|
@@ -20822,11 +20917,203 @@ ${block}`;
|
|
|
20822
20917
|
// src/director-bridge.ts
|
|
20823
20918
|
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
20824
20919
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
20825
|
-
var
|
|
20826
|
-
var
|
|
20827
|
-
var
|
|
20920
|
+
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
20921
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
20922
|
+
var import_node_child_process5 = require("node:child_process");
|
|
20828
20923
|
var import_node_crypto5 = __toESM(require("node:crypto"), 1);
|
|
20829
20924
|
|
|
20925
|
+
// src/turn-replay-buffer.ts
|
|
20926
|
+
var DEFAULT_GRACE_MS = 3e4;
|
|
20927
|
+
var DEFAULT_MAX_EVENTS = 2e3;
|
|
20928
|
+
var DEFAULT_MAX_BYTES = 4e6;
|
|
20929
|
+
var DEFAULT_POST_COMPLETION_TTL_MS = 1e4;
|
|
20930
|
+
function createReplayBuffer(opts) {
|
|
20931
|
+
return {
|
|
20932
|
+
turnId: opts.turnId,
|
|
20933
|
+
spanId: opts.spanId,
|
|
20934
|
+
bindEpoch: opts.bindEpoch ?? 0,
|
|
20935
|
+
events: [],
|
|
20936
|
+
lastSeq: 0,
|
|
20937
|
+
state: "live",
|
|
20938
|
+
terminalDelivered: false,
|
|
20939
|
+
replaying: false,
|
|
20940
|
+
outboundQueue: [],
|
|
20941
|
+
graceTimer: null,
|
|
20942
|
+
finishedAt: null,
|
|
20943
|
+
bytesUsed: 0,
|
|
20944
|
+
graceMs: opts.graceMs ?? DEFAULT_GRACE_MS,
|
|
20945
|
+
maxEvents: opts.maxEvents ?? DEFAULT_MAX_EVENTS,
|
|
20946
|
+
maxBytes: opts.maxBytes ?? DEFAULT_MAX_BYTES,
|
|
20947
|
+
postCompletionTtlMs: opts.postCompletionTtlMs ?? DEFAULT_POST_COMPLETION_TTL_MS,
|
|
20948
|
+
triggerGrace: null
|
|
20949
|
+
};
|
|
20950
|
+
}
|
|
20951
|
+
function recordOutgoing(buf, msg) {
|
|
20952
|
+
const seq = ++buf.lastSeq;
|
|
20953
|
+
const entry = { seq, msg };
|
|
20954
|
+
buf.events.push(entry);
|
|
20955
|
+
buf.bytesUsed += approxByteSize(msg);
|
|
20956
|
+
while ((buf.events.length > buf.maxEvents || buf.bytesUsed > buf.maxBytes) && buf.events.length > 0) {
|
|
20957
|
+
const dropped = buf.events.shift();
|
|
20958
|
+
if (!dropped) break;
|
|
20959
|
+
buf.bytesUsed -= approxByteSize(dropped.msg);
|
|
20960
|
+
}
|
|
20961
|
+
return entry;
|
|
20962
|
+
}
|
|
20963
|
+
function eventsAfter(buf, lastSeq) {
|
|
20964
|
+
const first = buf.events[0];
|
|
20965
|
+
if (first && lastSeq < first.seq - 1) return null;
|
|
20966
|
+
return buf.events.filter((e) => e.seq > lastSeq);
|
|
20967
|
+
}
|
|
20968
|
+
function enterGrace(buf, onExpire) {
|
|
20969
|
+
if (buf.graceTimer !== null) return;
|
|
20970
|
+
buf.state = "grace";
|
|
20971
|
+
buf.graceTimer = setTimeout(onExpire, buf.graceMs);
|
|
20972
|
+
}
|
|
20973
|
+
function cancelGrace(buf) {
|
|
20974
|
+
if (buf.graceTimer !== null) {
|
|
20975
|
+
clearTimeout(buf.graceTimer);
|
|
20976
|
+
buf.graceTimer = null;
|
|
20977
|
+
}
|
|
20978
|
+
if (buf.state === "grace") buf.state = "live";
|
|
20979
|
+
}
|
|
20980
|
+
function recordInterrupted(buf) {
|
|
20981
|
+
if (buf.terminalDelivered) return null;
|
|
20982
|
+
const msg = {
|
|
20983
|
+
type: "event",
|
|
20984
|
+
event: { type: "result", subtype: "interrupted" }
|
|
20985
|
+
};
|
|
20986
|
+
const entry = recordOutgoing(buf, msg);
|
|
20987
|
+
buf.terminalDelivered = true;
|
|
20988
|
+
return entry;
|
|
20989
|
+
}
|
|
20990
|
+
function markCompleted(buf, now) {
|
|
20991
|
+
buf.state = "completed";
|
|
20992
|
+
buf.finishedAt = now;
|
|
20993
|
+
}
|
|
20994
|
+
function shouldGc(buf, now) {
|
|
20995
|
+
if (buf.state !== "completed") return false;
|
|
20996
|
+
if (buf.finishedAt === null) return false;
|
|
20997
|
+
return now - buf.finishedAt > buf.postCompletionTtlMs;
|
|
20998
|
+
}
|
|
20999
|
+
function incrementBindEpoch(buf) {
|
|
21000
|
+
return ++buf.bindEpoch;
|
|
21001
|
+
}
|
|
21002
|
+
function isTerminalEvent(msg) {
|
|
21003
|
+
if (typeof msg !== "object" || msg === null) return false;
|
|
21004
|
+
const outer = msg;
|
|
21005
|
+
if (outer.type !== "event") return false;
|
|
21006
|
+
if (typeof outer.event !== "object" || outer.event === null) return false;
|
|
21007
|
+
const inner = outer.event;
|
|
21008
|
+
return inner.type === "result";
|
|
21009
|
+
}
|
|
21010
|
+
function approxByteSize(msg) {
|
|
21011
|
+
try {
|
|
21012
|
+
return JSON.stringify(msg).length;
|
|
21013
|
+
} catch {
|
|
21014
|
+
return 0;
|
|
21015
|
+
}
|
|
21016
|
+
}
|
|
21017
|
+
|
|
21018
|
+
// src/replay-state-machine.ts
|
|
21019
|
+
function transition(state, event) {
|
|
21020
|
+
if (event.kind === "resume" && !event.epochMatch) return { next: "invalid" };
|
|
21021
|
+
switch (state) {
|
|
21022
|
+
case "live":
|
|
21023
|
+
switch (event.kind) {
|
|
21024
|
+
case "socket_close":
|
|
21025
|
+
return { next: "grace", sideEffects: ["start_grace_timer"] };
|
|
21026
|
+
case "codex_terminal":
|
|
21027
|
+
return { next: "completed", sideEffects: ["mark_finished"] };
|
|
21028
|
+
case "stop":
|
|
21029
|
+
return {
|
|
21030
|
+
next: "interrupted",
|
|
21031
|
+
sideEffects: ["record_interrupted", "fire_turn_interrupt"]
|
|
21032
|
+
};
|
|
21033
|
+
default:
|
|
21034
|
+
return { next: "invalid" };
|
|
21035
|
+
}
|
|
21036
|
+
case "grace":
|
|
21037
|
+
switch (event.kind) {
|
|
21038
|
+
case "resume":
|
|
21039
|
+
return {
|
|
21040
|
+
next: "live",
|
|
21041
|
+
sideEffects: [
|
|
21042
|
+
"cancel_grace_timer",
|
|
21043
|
+
"rebind_sink_increment_epoch",
|
|
21044
|
+
"replay_drain"
|
|
21045
|
+
]
|
|
21046
|
+
};
|
|
21047
|
+
case "grace_expire":
|
|
21048
|
+
return {
|
|
21049
|
+
next: "interrupted",
|
|
21050
|
+
sideEffects: ["record_interrupted", "fire_turn_interrupt"]
|
|
21051
|
+
};
|
|
21052
|
+
case "stop":
|
|
21053
|
+
return {
|
|
21054
|
+
next: "interrupted",
|
|
21055
|
+
sideEffects: [
|
|
21056
|
+
"cancel_grace_timer",
|
|
21057
|
+
"record_interrupted",
|
|
21058
|
+
"fire_turn_interrupt"
|
|
21059
|
+
]
|
|
21060
|
+
};
|
|
21061
|
+
case "codex_terminal":
|
|
21062
|
+
return {
|
|
21063
|
+
next: "completed",
|
|
21064
|
+
sideEffects: ["cancel_grace_timer", "mark_finished"]
|
|
21065
|
+
};
|
|
21066
|
+
default:
|
|
21067
|
+
return { next: "invalid" };
|
|
21068
|
+
}
|
|
21069
|
+
case "interrupted":
|
|
21070
|
+
switch (event.kind) {
|
|
21071
|
+
case "resume":
|
|
21072
|
+
return {
|
|
21073
|
+
next: "interrupted",
|
|
21074
|
+
sideEffects: ["rebind_sink_increment_epoch", "replay_drain"]
|
|
21075
|
+
};
|
|
21076
|
+
case "codex_terminal":
|
|
21077
|
+
return { next: "interrupted", sideEffects: ["drop_with_warn"] };
|
|
21078
|
+
case "result_delivered_to_client":
|
|
21079
|
+
return { next: "completed", sideEffects: ["mark_finished"] };
|
|
21080
|
+
default:
|
|
21081
|
+
return { next: "invalid" };
|
|
21082
|
+
}
|
|
21083
|
+
case "completed":
|
|
21084
|
+
if (event.kind === "resume") {
|
|
21085
|
+
return {
|
|
21086
|
+
next: "completed",
|
|
21087
|
+
sideEffects: ["rebind_sink_increment_epoch", "replay_drain"]
|
|
21088
|
+
};
|
|
21089
|
+
}
|
|
21090
|
+
return { next: "completed", sideEffects: [] };
|
|
21091
|
+
}
|
|
21092
|
+
}
|
|
21093
|
+
|
|
21094
|
+
// src/bridge-tombstone.ts
|
|
21095
|
+
var DEFAULT_TOMBSTONE_TTL_MS = 36e5;
|
|
21096
|
+
function writeTombstone(tombstones, directorSessionId, buf, now) {
|
|
21097
|
+
tombstones.set(directorSessionId, {
|
|
21098
|
+
turnId: buf.turnId,
|
|
21099
|
+
lastSeq: buf.lastSeq,
|
|
21100
|
+
expiredAt: now
|
|
21101
|
+
});
|
|
21102
|
+
}
|
|
21103
|
+
function lookupTombstone(tombstones, directorSessionId) {
|
|
21104
|
+
return tombstones.get(directorSessionId) ?? null;
|
|
21105
|
+
}
|
|
21106
|
+
function sweepExpiredTombstones(tombstones, now, ttlMs = DEFAULT_TOMBSTONE_TTL_MS) {
|
|
21107
|
+
let removed = 0;
|
|
21108
|
+
for (const [sid, t] of tombstones) {
|
|
21109
|
+
if (now - t.expiredAt > ttlMs) {
|
|
21110
|
+
tombstones.delete(sid);
|
|
21111
|
+
removed += 1;
|
|
21112
|
+
}
|
|
21113
|
+
}
|
|
21114
|
+
return removed;
|
|
21115
|
+
}
|
|
21116
|
+
|
|
20830
21117
|
// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
|
|
20831
21118
|
var import_stream = __toESM(require_stream(), 1);
|
|
20832
21119
|
var import_extension = __toESM(require_extension(), 1);
|
|
@@ -20948,7 +21235,7 @@ var CodexJsonRpcClient = class {
|
|
|
20948
21235
|
};
|
|
20949
21236
|
|
|
20950
21237
|
// ../../packages/codex-client/dist/server-manager.js
|
|
20951
|
-
var
|
|
21238
|
+
var import_node_child_process2 = require("node:child_process");
|
|
20952
21239
|
var CodexServerManager = class {
|
|
20953
21240
|
client = null;
|
|
20954
21241
|
process = null;
|
|
@@ -20989,7 +21276,7 @@ var CodexServerManager = class {
|
|
|
20989
21276
|
}
|
|
20990
21277
|
async startServer(config2) {
|
|
20991
21278
|
const executable = config2?.codexExecutable ?? "codex";
|
|
20992
|
-
const spawnFn = config2?.spawn ??
|
|
21279
|
+
const spawnFn = config2?.spawn ?? import_node_child_process2.spawn;
|
|
20993
21280
|
const child = spawnFn(executable, ["app-server"], {
|
|
20994
21281
|
stdio: ["pipe", "pipe", "pipe"],
|
|
20995
21282
|
cwd: config2?.cwd,
|
|
@@ -22134,10 +22421,10 @@ function mergeDefs(...defs) {
|
|
|
22134
22421
|
function cloneDef(schema) {
|
|
22135
22422
|
return mergeDefs(schema._zod.def);
|
|
22136
22423
|
}
|
|
22137
|
-
function getElementAtPath(obj,
|
|
22138
|
-
if (!
|
|
22424
|
+
function getElementAtPath(obj, path16) {
|
|
22425
|
+
if (!path16)
|
|
22139
22426
|
return obj;
|
|
22140
|
-
return
|
|
22427
|
+
return path16.reduce((acc, key) => acc?.[key], obj);
|
|
22141
22428
|
}
|
|
22142
22429
|
function promiseAllObject(promisesObj) {
|
|
22143
22430
|
const keys = Object.keys(promisesObj);
|
|
@@ -22546,11 +22833,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
22546
22833
|
}
|
|
22547
22834
|
return false;
|
|
22548
22835
|
}
|
|
22549
|
-
function prefixIssues(
|
|
22836
|
+
function prefixIssues(path16, issues) {
|
|
22550
22837
|
return issues.map((iss) => {
|
|
22551
22838
|
var _a3;
|
|
22552
22839
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
22553
|
-
iss.path.unshift(
|
|
22840
|
+
iss.path.unshift(path16);
|
|
22554
22841
|
return iss;
|
|
22555
22842
|
});
|
|
22556
22843
|
}
|
|
@@ -22697,16 +22984,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
22697
22984
|
}
|
|
22698
22985
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
22699
22986
|
const fieldErrors = { _errors: [] };
|
|
22700
|
-
const processError = (error52,
|
|
22987
|
+
const processError = (error52, path16 = []) => {
|
|
22701
22988
|
for (const issue2 of error52.issues) {
|
|
22702
22989
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
22703
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
22990
|
+
issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
|
|
22704
22991
|
} else if (issue2.code === "invalid_key") {
|
|
22705
|
-
processError({ issues: issue2.issues }, [...
|
|
22992
|
+
processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
|
|
22706
22993
|
} else if (issue2.code === "invalid_element") {
|
|
22707
|
-
processError({ issues: issue2.issues }, [...
|
|
22994
|
+
processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
|
|
22708
22995
|
} else {
|
|
22709
|
-
const fullpath = [...
|
|
22996
|
+
const fullpath = [...path16, ...issue2.path];
|
|
22710
22997
|
if (fullpath.length === 0) {
|
|
22711
22998
|
fieldErrors._errors.push(mapper(issue2));
|
|
22712
22999
|
} else {
|
|
@@ -22733,17 +23020,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
22733
23020
|
}
|
|
22734
23021
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
22735
23022
|
const result = { errors: [] };
|
|
22736
|
-
const processError = (error52,
|
|
23023
|
+
const processError = (error52, path16 = []) => {
|
|
22737
23024
|
var _a3, _b;
|
|
22738
23025
|
for (const issue2 of error52.issues) {
|
|
22739
23026
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
22740
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
23027
|
+
issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
|
|
22741
23028
|
} else if (issue2.code === "invalid_key") {
|
|
22742
|
-
processError({ issues: issue2.issues }, [...
|
|
23029
|
+
processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
|
|
22743
23030
|
} else if (issue2.code === "invalid_element") {
|
|
22744
|
-
processError({ issues: issue2.issues }, [...
|
|
23031
|
+
processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
|
|
22745
23032
|
} else {
|
|
22746
|
-
const fullpath = [...
|
|
23033
|
+
const fullpath = [...path16, ...issue2.path];
|
|
22747
23034
|
if (fullpath.length === 0) {
|
|
22748
23035
|
result.errors.push(mapper(issue2));
|
|
22749
23036
|
continue;
|
|
@@ -22775,8 +23062,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
22775
23062
|
}
|
|
22776
23063
|
function toDotPath(_path) {
|
|
22777
23064
|
const segs = [];
|
|
22778
|
-
const
|
|
22779
|
-
for (const seg of
|
|
23065
|
+
const path16 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
23066
|
+
for (const seg of path16) {
|
|
22780
23067
|
if (typeof seg === "number")
|
|
22781
23068
|
segs.push(`[${seg}]`);
|
|
22782
23069
|
else if (typeof seg === "symbol")
|
|
@@ -35468,13 +35755,13 @@ function resolveRef(ref, ctx) {
|
|
|
35468
35755
|
if (!ref.startsWith("#")) {
|
|
35469
35756
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
35470
35757
|
}
|
|
35471
|
-
const
|
|
35472
|
-
if (
|
|
35758
|
+
const path16 = ref.slice(1).split("/").filter(Boolean);
|
|
35759
|
+
if (path16.length === 0) {
|
|
35473
35760
|
return ctx.rootSchema;
|
|
35474
35761
|
}
|
|
35475
35762
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
35476
|
-
if (
|
|
35477
|
-
const key =
|
|
35763
|
+
if (path16[0] === defsKey) {
|
|
35764
|
+
const key = path16[1];
|
|
35478
35765
|
if (!key || !ctx.defs[key]) {
|
|
35479
35766
|
throw new Error(`Reference not found: ${ref}`);
|
|
35480
35767
|
}
|
|
@@ -35888,6 +36175,7 @@ var openApiOperationIds = {
|
|
|
35888
36175
|
archivePlan: "archivePlan",
|
|
35889
36176
|
bindProjectGithubRepo: "bindProjectGithubRepo",
|
|
35890
36177
|
createExecutionRun: "createExecutionRun",
|
|
36178
|
+
createExecutionRunHandoff: "createExecutionRunHandoff",
|
|
35891
36179
|
createAsyncJob: "createAsyncJob",
|
|
35892
36180
|
getAsyncJob: "getAsyncJob",
|
|
35893
36181
|
getActiveAsyncJob: "getActiveAsyncJob",
|
|
@@ -35987,7 +36275,7 @@ var operatorSessionSchema = external_exports.object({
|
|
|
35987
36275
|
issuedAt: external_exports.number().int().positive(),
|
|
35988
36276
|
kind: external_exports.enum(["web", "agent"]).default("web"),
|
|
35989
36277
|
login: external_exports.string().min(1),
|
|
35990
|
-
projectSlug: external_exports.string().min(1),
|
|
36278
|
+
projectSlug: external_exports.string().min(1).optional(),
|
|
35991
36279
|
provider: external_exports.literal("github"),
|
|
35992
36280
|
repo: external_exports.string().min(1).nullable(),
|
|
35993
36281
|
// ADR 0016: `scope` distinguishes project-pinned agent tokens (legacy, default) from
|
|
@@ -35996,7 +36284,7 @@ var operatorSessionSchema = external_exports.object({
|
|
|
35996
36284
|
// cleanly into the project branch of the middleware (which mirrors today's behavior).
|
|
35997
36285
|
scope: external_exports.enum(["project", "operator"]).default("project")
|
|
35998
36286
|
});
|
|
35999
|
-
var AGENT_SESSION_TTL_MS = 1e3 * 60 *
|
|
36287
|
+
var AGENT_SESSION_TTL_MS = 1e3 * 60 * 15;
|
|
36000
36288
|
|
|
36001
36289
|
// ../../packages/schemas/dist/github-state.js
|
|
36002
36290
|
var TTL_MS = 10 * 6e4;
|
|
@@ -36114,6 +36402,7 @@ var mrrlinTaskTypeSchema = external_exports.enum(["task", "bug"]);
|
|
|
36114
36402
|
var mrrlinTaskImpactSchema = external_exports.enum(["low", "medium", "high"]);
|
|
36115
36403
|
var mrrlinAutonomyLevelSchema = external_exports.enum(["auto", "minimal_human", "human_only"]);
|
|
36116
36404
|
var mrrlinAutoDeploySchema = external_exports.enum(["off", "dev", "prod"]);
|
|
36405
|
+
var mrrlinSpecApprovedSchema = external_exports.enum(["pending", "approved", "skipped", "skipped_legacy"]);
|
|
36117
36406
|
var mrrlinTaskSourceSchema = external_exports.enum(["fixture-import", "api"]);
|
|
36118
36407
|
var mrrlinPlanStatusSchema = external_exports.enum(["active", "paused", "done", "archived"]);
|
|
36119
36408
|
var mrrlinTaskEventTypeSchema = external_exports.enum(["autonomy_set", "director_thread_reset", "note"]);
|
|
@@ -36204,7 +36493,13 @@ var mrrlinTaskSchema = external_exports.object({
|
|
|
36204
36493
|
latestJudgementAt: external_exports.string().datetime().nullable().default(null),
|
|
36205
36494
|
latestJudgementKind: external_exports.enum(["autonomy", "handoff"]).nullable().default(null),
|
|
36206
36495
|
notes: external_exports.string().nullable().default(null),
|
|
36496
|
+
// Raw operator request captured at task creation (operator-authored ONLY, never Director-generated).
|
|
36497
|
+
// The intent-aware spec gate judges the spec against this; null/absent ⇒ the gate fail-closes.
|
|
36498
|
+
// Output-optional (not .default) so existing task fixtures need no churn; DB rows always resolve it
|
|
36499
|
+
// to `string | null` via taskRowToTask.
|
|
36500
|
+
operatorSeedRequest: external_exports.string().max(8e3).nullable().optional(),
|
|
36207
36501
|
planId: mrrlinPlanIdSchema.nullable(),
|
|
36502
|
+
specApproved: mrrlinSpecApprovedSchema.optional(),
|
|
36208
36503
|
specWikiPageId: mrrlinWikiPageIdSchema.nullable(),
|
|
36209
36504
|
status: mrrlinTaskStatusSchema,
|
|
36210
36505
|
subcategory: taxonomySubcategorySchema,
|
|
@@ -36220,6 +36515,7 @@ var mrrlinPlanSchema = external_exports.object({
|
|
|
36220
36515
|
id: mrrlinPlanIdSchema,
|
|
36221
36516
|
name: external_exports.string().min(1),
|
|
36222
36517
|
progress: external_exports.number().min(0).max(1),
|
|
36518
|
+
specWikiPageId: external_exports.string().nullable().default(null),
|
|
36223
36519
|
status: mrrlinPlanStatusSchema,
|
|
36224
36520
|
taskCount: external_exports.number().int().nonnegative()
|
|
36225
36521
|
});
|
|
@@ -36344,6 +36640,7 @@ var mrrlinTaskCreateSchema = external_exports.object({
|
|
|
36344
36640
|
id: mrrlinTaskIdSchema,
|
|
36345
36641
|
impact: mrrlinTaskImpactSchema.default("medium"),
|
|
36346
36642
|
notes: external_exports.string().nullable().optional(),
|
|
36643
|
+
operatorSeedRequest: external_exports.string().max(8e3).nullable().optional(),
|
|
36347
36644
|
planId: mrrlinPlanIdSchema.nullable().optional(),
|
|
36348
36645
|
specWikiPageId: mrrlinWikiPageIdSchema.nullable().optional(),
|
|
36349
36646
|
tags: mrrlinTaskTagsSchema.optional(),
|
|
@@ -36367,6 +36664,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
|
|
|
36367
36664
|
impact: mrrlinTaskImpactSchema.optional(),
|
|
36368
36665
|
notes: external_exports.string().nullable().optional(),
|
|
36369
36666
|
planId: mrrlinPlanIdSchema.nullable().optional(),
|
|
36667
|
+
specApproved: mrrlinSpecApprovedSchema.optional(),
|
|
36370
36668
|
specWikiPageId: mrrlinWikiPageIdSchema.nullable().optional(),
|
|
36371
36669
|
status: mrrlinTaskStatusSchema.optional(),
|
|
36372
36670
|
subcategory: taxonomySubcategorySchema.optional(),
|
|
@@ -36374,7 +36672,7 @@ var mrrlinTaskUpdateSchema = external_exports.object({
|
|
|
36374
36672
|
type: mrrlinTaskTypeSchema.optional(),
|
|
36375
36673
|
followUpAt: external_exports.string().datetime().nullable().optional(),
|
|
36376
36674
|
verificationDueAt: external_exports.string().datetime().nullable().optional()
|
|
36377
|
-
}).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
|
|
36675
|
+
}).refine((value) => value.assignee !== void 0 || value.autoDeploy !== void 0 || value.autonomyLevel !== void 0 || value.autonomyReason !== void 0 || value.category !== void 0 || value.directorThreadId !== void 0 || value.dueDate !== void 0 || value.followUpAt !== void 0 || value.impact !== void 0 || value.notes !== void 0 || value.planId !== void 0 || value.specApproved !== void 0 || value.specWikiPageId !== void 0 || value.status !== void 0 || value.subcategory !== void 0 || value.tags !== void 0 || value.type !== void 0 || value.verificationDueAt !== void 0, { message: "TaskUpdate requires at least one field" }).superRefine((value, context) => {
|
|
36378
36676
|
if (value.autonomyLevel !== void 0 && value.autonomyReason === void 0) {
|
|
36379
36677
|
context.addIssue({
|
|
36380
36678
|
code: external_exports.ZodIssueCode.custom,
|
|
@@ -36415,12 +36713,14 @@ var mrrlinPlanCreateSchema = external_exports.object({
|
|
|
36415
36713
|
goal: external_exports.string().min(1),
|
|
36416
36714
|
id: mrrlinPlanIdSchema,
|
|
36417
36715
|
name: external_exports.string().min(1),
|
|
36716
|
+
specWikiPageId: external_exports.string().nullable().optional(),
|
|
36418
36717
|
status: mrrlinPlanStatusSchema.default("active")
|
|
36419
36718
|
});
|
|
36420
36719
|
var mrrlinPlanUpdateSchema = external_exports.object({
|
|
36421
36720
|
dueDate: external_exports.string().date().nullable().optional(),
|
|
36422
36721
|
goal: external_exports.string().min(1).optional(),
|
|
36423
36722
|
name: external_exports.string().min(1).optional(),
|
|
36723
|
+
specWikiPageId: external_exports.string().nullable().optional(),
|
|
36424
36724
|
status: mrrlinPlanStatusSchema.optional()
|
|
36425
36725
|
}).refine((value) => Object.keys(value).length > 0, { message: "PlanUpdate requires at least one field" });
|
|
36426
36726
|
var mrrlinTaxonomyCreateSchema = mrrlinTaxonomyEntrySchema;
|
|
@@ -36643,6 +36943,10 @@ var markSpecReadyResponseSchema = external_exports.object({
|
|
|
36643
36943
|
var wikiPageSpecReadyCasResponseSchema = external_exports.object({
|
|
36644
36944
|
data: external_exports.object({ promoted: external_exports.literal(true) })
|
|
36645
36945
|
});
|
|
36946
|
+
var mrrlinRunPrerequisiteSchema = external_exports.object({
|
|
36947
|
+
mcp: external_exports.string().min(1),
|
|
36948
|
+
reason: external_exports.string().min(1)
|
|
36949
|
+
});
|
|
36646
36950
|
var mrrlinExecutionRunSchema = external_exports.object({
|
|
36647
36951
|
actor: external_exports.string().min(1),
|
|
36648
36952
|
baseSha: external_exports.string().min(1).nullable(),
|
|
@@ -36651,6 +36955,7 @@ var mrrlinExecutionRunSchema = external_exports.object({
|
|
|
36651
36955
|
claimedAt: external_exports.string().datetime().nullable(),
|
|
36652
36956
|
codeExecution: external_exports.boolean(),
|
|
36653
36957
|
createdAt: external_exports.string().datetime(),
|
|
36958
|
+
devEnvUrl: external_exports.string().min(1).nullable(),
|
|
36654
36959
|
devRunUrl: external_exports.string().min(1).nullable(),
|
|
36655
36960
|
devWorkflowId: external_exports.number().int().positive().nullable(),
|
|
36656
36961
|
directorSessionId: external_exports.string().min(1).nullable(),
|
|
@@ -36659,6 +36964,8 @@ var mrrlinExecutionRunSchema = external_exports.object({
|
|
|
36659
36964
|
id: mrrlinExecutionRunIdSchema,
|
|
36660
36965
|
lastActor: external_exports.string().min(1).nullable(),
|
|
36661
36966
|
leaseId: external_exports.string().min(1).nullable(),
|
|
36967
|
+
prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema),
|
|
36968
|
+
prodEnvUrl: external_exports.string().min(1).nullable(),
|
|
36662
36969
|
prodRunUrl: external_exports.string().min(1).nullable(),
|
|
36663
36970
|
prodWorkflowId: external_exports.number().int().positive().nullable(),
|
|
36664
36971
|
projectSlug: mrrlinProjectSlugSchema,
|
|
@@ -36677,6 +36984,7 @@ var mrrlinExecutionRunCreateSchema = external_exports.object({
|
|
|
36677
36984
|
codeExecution: external_exports.boolean().optional().default(false),
|
|
36678
36985
|
devWorkflowId: external_exports.number().int().positive().optional(),
|
|
36679
36986
|
id: mrrlinExecutionRunIdSchema,
|
|
36987
|
+
prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema).default([]),
|
|
36680
36988
|
prodWorkflowId: external_exports.number().int().positive().optional(),
|
|
36681
36989
|
provider: external_exports.string().min(1),
|
|
36682
36990
|
status: mrrlinExecutionRunStatusSchema.default("pending"),
|
|
@@ -36687,11 +36995,13 @@ var mrrlinExecutionRunUpdateSchema = external_exports.object({
|
|
|
36687
36995
|
baseSha: external_exports.string().min(1).nullable().optional(),
|
|
36688
36996
|
branch: external_exports.string().min(1).nullable().optional(),
|
|
36689
36997
|
checkpointCursor: external_exports.string().min(1).nullable().optional(),
|
|
36998
|
+
devEnvUrl: external_exports.string().min(1).nullable().optional(),
|
|
36690
36999
|
devRunUrl: external_exports.string().min(1).nullable().optional(),
|
|
36691
37000
|
devWorkflowId: external_exports.number().int().positive().nullable().optional(),
|
|
36692
37001
|
finishedAt: external_exports.string().datetime().nullable().optional(),
|
|
36693
37002
|
headSha: external_exports.string().min(1).nullable().optional(),
|
|
36694
37003
|
leaseId: external_exports.string().min(1).nullable().optional(),
|
|
37004
|
+
prodEnvUrl: external_exports.string().min(1).nullable().optional(),
|
|
36695
37005
|
prodRunUrl: external_exports.string().min(1).nullable().optional(),
|
|
36696
37006
|
prodWorkflowId: external_exports.number().int().positive().nullable().optional(),
|
|
36697
37007
|
pullRequestUrl: external_exports.string().min(1).nullable().optional(),
|
|
@@ -36739,6 +37049,7 @@ var mrrlinResolveHandoffSchema = external_exports.object({
|
|
|
36739
37049
|
}
|
|
36740
37050
|
});
|
|
36741
37051
|
var resolveHandoffResponseSchema = external_exports.object({ data: mrrlinExecutionRunSchema });
|
|
37052
|
+
var createExecutionRunHandoffSchema = external_exports.object({ reason: external_exports.string().min(1) });
|
|
36742
37053
|
var mrrlinExecutionRunTouchSchema = external_exports.object({
|
|
36743
37054
|
leaseId: external_exports.string().min(1)
|
|
36744
37055
|
});
|
|
@@ -36804,7 +37115,9 @@ var exchangeAgentTokenRequestSchema = external_exports.object({
|
|
|
36804
37115
|
var exchangeAgentTokenResponseSchema = external_exports.object({
|
|
36805
37116
|
token: external_exports.string().min(1),
|
|
36806
37117
|
expiresAt: external_exports.string().datetime(),
|
|
36807
|
-
|
|
37118
|
+
// ADR 0016 §T7 amendment: operator-scope exchanges return no projectSlug (the token is
|
|
37119
|
+
// operator-wide); project-scope exchanges still return the pinned slug.
|
|
37120
|
+
projectSlug: external_exports.string().min(1).optional(),
|
|
36808
37121
|
login: external_exports.string().min(1)
|
|
36809
37122
|
});
|
|
36810
37123
|
var MRRLIN_ARTIFACT_FILE_MAX_BYTES = 5 * 1024 * 1024;
|
|
@@ -36822,6 +37135,7 @@ var mrrlinArtifactFileMimeTypes = [
|
|
|
36822
37135
|
];
|
|
36823
37136
|
var mrrlinArtifactFileClassSchema = external_exports.enum(["temp", "durable"]);
|
|
36824
37137
|
var mrrlinArtifactFileStatusSchema = external_exports.enum(["pending", "uploaded", "expired"]);
|
|
37138
|
+
var mrrlinArtifactFileVisibilitySchema = external_exports.enum(["private", "public"]);
|
|
36825
37139
|
var mrrlinArtifactFileSchema = external_exports.object({
|
|
36826
37140
|
class: mrrlinArtifactFileClassSchema,
|
|
36827
37141
|
contentType: external_exports.enum(mrrlinArtifactFileMimeTypes),
|
|
@@ -36836,7 +37150,9 @@ var mrrlinArtifactFileSchema = external_exports.object({
|
|
|
36836
37150
|
// min(0): reads tolerate 0-byte rows; creation requires min(1) (see create schema).
|
|
36837
37151
|
sizeBytes: external_exports.number().int().min(0).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
|
|
36838
37152
|
status: mrrlinArtifactFileStatusSchema,
|
|
36839
|
-
taskId: mrrlinTaskIdSchema.nullable()
|
|
37153
|
+
taskId: mrrlinTaskIdSchema.nullable(),
|
|
37154
|
+
// Defaulted (fail-safe → private) so legacy rows/fixtures predating the column read as private.
|
|
37155
|
+
visibility: mrrlinArtifactFileVisibilitySchema.default("private")
|
|
36840
37156
|
});
|
|
36841
37157
|
var mrrlinArtifactFileCreateSchema = external_exports.object({
|
|
36842
37158
|
class: mrrlinArtifactFileClassSchema,
|
|
@@ -36844,7 +37160,9 @@ var mrrlinArtifactFileCreateSchema = external_exports.object({
|
|
|
36844
37160
|
filename: external_exports.string().min(1).max(255),
|
|
36845
37161
|
runId: mrrlinExecutionRunIdSchema.optional(),
|
|
36846
37162
|
sizeBytes: external_exports.number().int().min(1).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
|
|
36847
|
-
taskId: mrrlinTaskIdSchema.optional()
|
|
37163
|
+
taskId: mrrlinTaskIdSchema.optional(),
|
|
37164
|
+
// Optional + fail-safe: callers must opt in to 'public'; everything else stays private.
|
|
37165
|
+
visibility: mrrlinArtifactFileVisibilitySchema.optional().default("private")
|
|
36848
37166
|
});
|
|
36849
37167
|
var mrrlinArtifactFileUploadTargetSchema = external_exports.discriminatedUnion("kind", [
|
|
36850
37168
|
external_exports.object({ kind: external_exports.literal("presigned-post"), url: external_exports.string().min(1), fields: external_exports.record(external_exports.string(), external_exports.string()) }),
|
|
@@ -36967,6 +37285,8 @@ var mrrlinInboxItemSchema = external_exports.object({
|
|
|
36967
37285
|
directorSessionId: external_exports.string().min(1).nullable(),
|
|
36968
37286
|
id: mrrlinInboxItemIdSchema,
|
|
36969
37287
|
kind: mrrlinInboxItemKindSchema,
|
|
37288
|
+
origin: external_exports.string().nullable().optional(),
|
|
37289
|
+
planId: mrrlinPlanIdSchema.nullable().default(null),
|
|
36970
37290
|
projectSlug: mrrlinProjectSlugSchema,
|
|
36971
37291
|
readAt: external_exports.string().datetime().nullable(),
|
|
36972
37292
|
status: mrrlinInboxItemStatusSchema,
|
|
@@ -36978,6 +37298,8 @@ var mrrlinInboxItemCreateSchema = external_exports.object({
|
|
|
36978
37298
|
directorSessionId: external_exports.string().min(1).optional(),
|
|
36979
37299
|
id: mrrlinInboxItemIdSchema,
|
|
36980
37300
|
kind: mrrlinInboxItemKindSchema,
|
|
37301
|
+
origin: external_exports.string().min(1).optional(),
|
|
37302
|
+
planId: mrrlinPlanIdSchema.nullable().optional(),
|
|
36981
37303
|
taskId: mrrlinTaskIdSchema.nullable().optional()
|
|
36982
37304
|
});
|
|
36983
37305
|
var mrrlinInboxItemDecideSchema = external_exports.object({
|
|
@@ -37108,18 +37430,18 @@ function createMrrlinClient(config2) {
|
|
|
37108
37430
|
const customFetch = config2.fetch ?? globalThis.fetch;
|
|
37109
37431
|
const baseUrl = config2.baseUrl.replace(/\/$/, "");
|
|
37110
37432
|
const token = config2.token;
|
|
37111
|
-
async function request(
|
|
37433
|
+
async function request(path16, init) {
|
|
37112
37434
|
const method = init?.method ?? "GET";
|
|
37113
37435
|
const headers = new Headers(init?.headers ?? {});
|
|
37114
37436
|
if (token && !headers.has("authorization")) {
|
|
37115
37437
|
headers.set("authorization", `Bearer ${token}`);
|
|
37116
37438
|
}
|
|
37117
|
-
const response = await customFetch(`${baseUrl}${
|
|
37439
|
+
const response = await customFetch(`${baseUrl}${path16}`, { ...init, headers });
|
|
37118
37440
|
if (!response.ok) {
|
|
37119
37441
|
const body = await response.text();
|
|
37120
37442
|
let code = `HTTP_${response.status}`;
|
|
37121
37443
|
let violations = null;
|
|
37122
|
-
let message = `Mrrlin API ${method} ${
|
|
37444
|
+
let message = `Mrrlin API ${method} ${path16} failed: ${response.status}`;
|
|
37123
37445
|
try {
|
|
37124
37446
|
const parsed = JSON.parse(body);
|
|
37125
37447
|
const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
|
|
@@ -37139,7 +37461,7 @@ function createMrrlinClient(config2) {
|
|
|
37139
37461
|
throw new MrrlinApiError({
|
|
37140
37462
|
code,
|
|
37141
37463
|
method,
|
|
37142
|
-
path:
|
|
37464
|
+
path: path16,
|
|
37143
37465
|
responseBody: body,
|
|
37144
37466
|
status: response.status,
|
|
37145
37467
|
violations,
|
|
@@ -37386,7 +37708,7 @@ function createMrrlinClient(config2) {
|
|
|
37386
37708
|
return taskEventListResponseSchema.parse(body).data;
|
|
37387
37709
|
},
|
|
37388
37710
|
async listTasks(projectSlug, filters = {}) {
|
|
37389
|
-
const
|
|
37711
|
+
const path16 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
|
|
37390
37712
|
assignee: filters.assignee,
|
|
37391
37713
|
autonomyLevel: filters.autonomyLevel,
|
|
37392
37714
|
blockedBy: filters.blockedBy,
|
|
@@ -37398,7 +37720,7 @@ function createMrrlinClient(config2) {
|
|
|
37398
37720
|
subcategory: filters.subcategory,
|
|
37399
37721
|
type: filters.type
|
|
37400
37722
|
});
|
|
37401
|
-
const body = await request(
|
|
37723
|
+
const body = await request(path16);
|
|
37402
37724
|
return taskListResponseSchema.parse(body).data;
|
|
37403
37725
|
},
|
|
37404
37726
|
async listTaxonomy(projectSlug) {
|
|
@@ -37406,22 +37728,22 @@ function createMrrlinClient(config2) {
|
|
|
37406
37728
|
return taxonomyListResponseSchema.parse(body).data;
|
|
37407
37729
|
},
|
|
37408
37730
|
async listWikiPages(projectSlug, filters = {}) {
|
|
37409
|
-
const
|
|
37731
|
+
const path16 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
|
|
37410
37732
|
folder: filters.folder,
|
|
37411
37733
|
q: filters.q,
|
|
37412
37734
|
taskId: filters.taskId
|
|
37413
37735
|
});
|
|
37414
|
-
const body = await request(
|
|
37736
|
+
const body = await request(path16);
|
|
37415
37737
|
return wikiPageListResponseSchema.parse(body).data;
|
|
37416
37738
|
},
|
|
37417
37739
|
async searchWikiPages(projectSlug, query) {
|
|
37418
|
-
const
|
|
37740
|
+
const path16 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
|
|
37419
37741
|
folder: query.folder,
|
|
37420
37742
|
limit: query.limit === void 0 ? void 0 : String(query.limit),
|
|
37421
37743
|
pathPrefix: query.pathPrefix,
|
|
37422
37744
|
q: query.q
|
|
37423
37745
|
});
|
|
37424
|
-
const body = await request(
|
|
37746
|
+
const body = await request(path16);
|
|
37425
37747
|
return wikiPageSearchResponseSchema.parse(body).data;
|
|
37426
37748
|
},
|
|
37427
37749
|
async updatePlan(projectSlug, planId, patch) {
|
|
@@ -37687,6 +38009,14 @@ function createMrrlinClient(config2) {
|
|
|
37687
38009
|
});
|
|
37688
38010
|
return executionRunResponseSchema.parse(body).data;
|
|
37689
38011
|
},
|
|
38012
|
+
async createExecutionRunHandoff(projectSlug, runId, input) {
|
|
38013
|
+
const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/handoff`, {
|
|
38014
|
+
body: JSON.stringify(input),
|
|
38015
|
+
headers: { "content-type": "application/json" },
|
|
38016
|
+
method: "POST"
|
|
38017
|
+
});
|
|
38018
|
+
return executionRunResponseSchema.parse(body).data;
|
|
38019
|
+
},
|
|
37690
38020
|
async listExecutionArtifacts(projectSlug, runId) {
|
|
37691
38021
|
const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/artifacts`);
|
|
37692
38022
|
return executionArtifactListResponseSchema.parse(body).data;
|
|
@@ -37962,13 +38292,13 @@ function startSelfUpdate(deps) {
|
|
|
37962
38292
|
});
|
|
37963
38293
|
return `[bridge:update] An update for @mrrlin-dev/mcp is available: ${pkgVersion} \u2192 ${latestVersion}.
|
|
37964
38294
|
|
|
37965
|
-
This turn, at a natural pause, ASK the operator a yes/no question \u2014 e.g. "\u0411\u0430\u0447\u0443 \u0449\u043E bridge \u043D\u0430 ${pkgVersion}, \u043D\u0430 npm \u0443\u0436\u0435 ${latestVersion} \u2014 \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437? (\u0437\u0430\u043F\u0443\u0449\u0443 \`
|
|
38295
|
+
This turn, at a natural pause, ASK the operator a yes/no question \u2014 e.g. "\u0411\u0430\u0447\u0443 \u0449\u043E bridge \u043D\u0430 ${pkgVersion}, \u043D\u0430 npm \u0443\u0436\u0435 ${latestVersion} \u2014 \u043E\u043D\u043E\u0432\u0438\u0442\u0438 \u0437\u0430\u0440\u0430\u0437? (\u0437\u0430\u043F\u0443\u0449\u0443 \`npm install -g @mrrlin-dev/mcp@latest\`)". Do NOT install without explicit confirmation.
|
|
37966
38296
|
|
|
37967
|
-
If the operator confirms (yes / \u0442\u0430\u043A / \u0430\u0433\u0430 / etc.): immediately run \`
|
|
38297
|
+
If the operator confirms (yes / \u0442\u0430\u043A / \u0430\u0433\u0430 / etc.): immediately run \`npm install -g @mrrlin-dev/mcp@latest\` via your shell tool and report the outcome in chat. After a successful install, the bridge auto-restarts via its self-update loop within a couple of minutes \u2014 you do NOT need to call pm2.
|
|
37968
38298
|
|
|
37969
38299
|
If the operator declines / says "later": acknowledge briefly and do not bring it up again this turn. The bridge has a cooldown and will re-offer in 48h.
|
|
37970
38300
|
|
|
37971
|
-
If the install fails (permission denied, registry pinned, sudo required, network blocked): paste the error verbatim and show the operator the manual command \`
|
|
38301
|
+
If the install fails (permission denied, registry pinned, sudo required, network blocked): paste the error verbatim and show the operator the manual command \`npm install -g @mrrlin-dev/mcp@latest\` plus a one-line hint about likely cause.
|
|
37972
38302
|
|
|
37973
38303
|
Do NOT derail the current task \u2014 if the operator has an in-flight question, answer that first; the update offer is a brief aside, not the main subject.`;
|
|
37974
38304
|
}
|
|
@@ -38130,7 +38460,7 @@ Do NOT derail the current task \u2014 if the operator has an in-flight question,
|
|
|
38130
38460
|
}
|
|
38131
38461
|
|
|
38132
38462
|
// src/_generated/version.ts
|
|
38133
|
-
var PKG_VERSION = "0.3.
|
|
38463
|
+
var PKG_VERSION = "0.3.5";
|
|
38134
38464
|
|
|
38135
38465
|
// src/api-base-url.ts
|
|
38136
38466
|
var DEFAULT_API_BASE_URL = "http://127.0.0.1:8787";
|
|
@@ -38297,6 +38627,11 @@ async function runDeployGateTick(deps, projectSlug, run2, task) {
|
|
|
38297
38627
|
await deps.handoff(projectSlug, task, run2, "no_environment_url");
|
|
38298
38628
|
return { kind: "handoff", reason: "no_environment_url" };
|
|
38299
38629
|
}
|
|
38630
|
+
await deps.client.updateExecutionRun(
|
|
38631
|
+
projectSlug,
|
|
38632
|
+
run2.id,
|
|
38633
|
+
env === "dev" ? { devEnvUrl: deployment.environmentUrl } : { prodEnvUrl: deployment.environmentUrl }
|
|
38634
|
+
);
|
|
38300
38635
|
const section = await deps.loadVerificationSection(projectSlug, task);
|
|
38301
38636
|
if (!section || section.trim().length === 0) {
|
|
38302
38637
|
await deps.handoff(projectSlug, task, run2, "verification_steps_missing_at_verify");
|
|
@@ -38359,18 +38694,18 @@ async function awaitTurnWithDeadline(opts) {
|
|
|
38359
38694
|
}
|
|
38360
38695
|
|
|
38361
38696
|
// src/worktree.ts
|
|
38362
|
-
var
|
|
38697
|
+
var import_node_child_process3 = require("node:child_process");
|
|
38363
38698
|
var import_node_fs3 = require("node:fs");
|
|
38364
|
-
var
|
|
38365
|
-
var
|
|
38699
|
+
var import_node_os3 = require("node:os");
|
|
38700
|
+
var import_node_path4 = require("node:path");
|
|
38366
38701
|
|
|
38367
38702
|
// src/checkout-lock.ts
|
|
38368
38703
|
var import_node_fs2 = require("node:fs");
|
|
38369
|
-
var
|
|
38704
|
+
var import_node_path3 = require("node:path");
|
|
38370
38705
|
var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
|
|
38371
38706
|
async function withCheckoutLock(locksDir, slug, fn) {
|
|
38372
38707
|
(0, import_node_fs2.mkdirSync)(locksDir, { recursive: true });
|
|
38373
|
-
const target = (0,
|
|
38708
|
+
const target = (0, import_node_path3.join)(locksDir, `${slug}.lock`);
|
|
38374
38709
|
if (!(0, import_node_fs2.existsSync)(target)) (0, import_node_fs2.writeFileSync)(target, "");
|
|
38375
38710
|
const release = await import_proper_lockfile.default.lock(target, {
|
|
38376
38711
|
retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
|
|
@@ -38387,16 +38722,16 @@ async function withCheckoutLock(locksDir, slug, fn) {
|
|
|
38387
38722
|
function worktreeBranch(runId) {
|
|
38388
38723
|
return `mrrlin/run-${runId}`;
|
|
38389
38724
|
}
|
|
38390
|
-
var defaultGitExec = (args, env) => (0,
|
|
38725
|
+
var defaultGitExec = (args, env) => (0, import_node_child_process3.execFileSync)("git", args, { encoding: "utf8", timeout: 3e4, env });
|
|
38391
38726
|
function git(checkout, args) {
|
|
38392
|
-
return (0,
|
|
38727
|
+
return (0, import_node_child_process3.execFileSync)("git", ["-C", checkout, ...args], {
|
|
38393
38728
|
encoding: "utf8",
|
|
38394
38729
|
timeout: 3e4,
|
|
38395
38730
|
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
|
|
38396
38731
|
});
|
|
38397
38732
|
}
|
|
38398
38733
|
async function createRunWorktree(opts) {
|
|
38399
|
-
const worktreePath = (0,
|
|
38734
|
+
const worktreePath = (0, import_node_path4.join)(opts.worktreeRoot, opts.slug, opts.runId);
|
|
38400
38735
|
await withCheckoutLock(opts.locksDir, opts.slug, async () => {
|
|
38401
38736
|
(0, import_node_fs3.mkdirSync)(opts.worktreeRoot, { recursive: true });
|
|
38402
38737
|
try {
|
|
@@ -38459,8 +38794,8 @@ async function doPushRunBranch(opts, execGit) {
|
|
|
38459
38794
|
if (localConfig.trim()) {
|
|
38460
38795
|
throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
|
|
38461
38796
|
}
|
|
38462
|
-
const dir = (0, import_node_fs3.mkdtempSync)((0,
|
|
38463
|
-
const askpass = (0,
|
|
38797
|
+
const dir = (0, import_node_fs3.mkdtempSync)((0, import_node_path4.join)((0, import_node_os3.tmpdir)(), "mrrlin-push-"));
|
|
38798
|
+
const askpass = (0, import_node_path4.join)(dir, "askpass");
|
|
38464
38799
|
try {
|
|
38465
38800
|
(0, import_node_fs3.writeFileSync)(
|
|
38466
38801
|
askpass,
|
|
@@ -38946,16 +39281,12 @@ async function resetWedgedThread(deps, projectSlug, taskId, interruptFailed) {
|
|
|
38946
39281
|
});
|
|
38947
39282
|
}
|
|
38948
39283
|
async function failRun(deps, projectSlug, task, runId, leaseId, reason) {
|
|
39284
|
+
if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
|
|
38949
39285
|
try {
|
|
38950
|
-
|
|
38951
|
-
await deps.client.updateExecutionRun(projectSlug, runId, {
|
|
38952
|
-
status: "failed",
|
|
38953
|
-
finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38954
|
-
leaseId
|
|
38955
|
-
});
|
|
39286
|
+
await deps.client.createExecutionRunHandoff(projectSlug, runId, { reason });
|
|
38956
39287
|
} catch {
|
|
39288
|
+
await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
|
|
38957
39289
|
}
|
|
38958
|
-
await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
|
|
38959
39290
|
}
|
|
38960
39291
|
async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
|
|
38961
39292
|
try {
|
|
@@ -39261,14 +39592,14 @@ function codexIdleMs() {
|
|
|
39261
39592
|
|
|
39262
39593
|
// src/operator-token.ts
|
|
39263
39594
|
var import_node_fs4 = require("node:fs");
|
|
39264
|
-
var
|
|
39265
|
-
var
|
|
39595
|
+
var import_node_os4 = __toESM(require("node:os"), 1);
|
|
39596
|
+
var import_node_path5 = __toESM(require("node:path"), 1);
|
|
39266
39597
|
function operatorDir() {
|
|
39267
|
-
const base = process.env.CODEX_HOME ?
|
|
39598
|
+
const base = process.env.CODEX_HOME ? import_node_path5.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path5.default.join(import_node_os4.default.homedir(), ".mrrlin");
|
|
39268
39599
|
return base;
|
|
39269
39600
|
}
|
|
39270
39601
|
function operatorTokenPath() {
|
|
39271
|
-
return
|
|
39602
|
+
return import_node_path5.default.join(operatorDir(), "operator-token");
|
|
39272
39603
|
}
|
|
39273
39604
|
function readOperatorToken() {
|
|
39274
39605
|
try {
|
|
@@ -39285,7 +39616,7 @@ function persistOperatorToken(token) {
|
|
|
39285
39616
|
`, { encoding: "utf8", mode: 384 });
|
|
39286
39617
|
}
|
|
39287
39618
|
function agentCredentialPath() {
|
|
39288
|
-
return
|
|
39619
|
+
return import_node_path5.default.join(operatorDir(), "agent-credential");
|
|
39289
39620
|
}
|
|
39290
39621
|
function persistAgentSecret(secret) {
|
|
39291
39622
|
const dir = operatorDir();
|
|
@@ -39306,9 +39637,9 @@ function readAgentSecret() {
|
|
|
39306
39637
|
|
|
39307
39638
|
// src/thread-index.ts
|
|
39308
39639
|
var import_node_fs5 = require("node:fs");
|
|
39309
|
-
var
|
|
39640
|
+
var import_node_path6 = __toESM(require("node:path"), 1);
|
|
39310
39641
|
function threadIndexPath(stateDir) {
|
|
39311
|
-
return
|
|
39642
|
+
return import_node_path6.default.join(stateDir, "threads.json");
|
|
39312
39643
|
}
|
|
39313
39644
|
function loadThreadIndex(stateDir, ttlMs, now) {
|
|
39314
39645
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -39393,8 +39724,8 @@ function chatTurnMaxMs() {
|
|
|
39393
39724
|
// src/worker-token.ts
|
|
39394
39725
|
var import_node_crypto4 = require("node:crypto");
|
|
39395
39726
|
var import_node_fs6 = require("node:fs");
|
|
39396
|
-
var
|
|
39397
|
-
var
|
|
39727
|
+
var import_node_os5 = __toESM(require("node:os"), 1);
|
|
39728
|
+
var import_node_path7 = __toESM(require("node:path"), 1);
|
|
39398
39729
|
var DEFAULT_WORKER_PORT = 8792;
|
|
39399
39730
|
function workerPort() {
|
|
39400
39731
|
const raw = process.env.MRRLIN_WORKER_PORT;
|
|
@@ -39403,11 +39734,11 @@ function workerPort() {
|
|
|
39403
39734
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
|
|
39404
39735
|
}
|
|
39405
39736
|
function workerDir() {
|
|
39406
|
-
const base = process.env.CODEX_HOME ?
|
|
39407
|
-
return
|
|
39737
|
+
const base = process.env.CODEX_HOME ? import_node_path7.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path7.default.join(import_node_os5.default.homedir(), ".mrrlin");
|
|
39738
|
+
return import_node_path7.default.join(base, "worker");
|
|
39408
39739
|
}
|
|
39409
39740
|
function workerTokenPath() {
|
|
39410
|
-
return
|
|
39741
|
+
return import_node_path7.default.join(workerDir(), "token");
|
|
39411
39742
|
}
|
|
39412
39743
|
function readWorkerToken() {
|
|
39413
39744
|
try {
|
|
@@ -39431,8 +39762,8 @@ function readOrCreateWorkerToken() {
|
|
|
39431
39762
|
// src/remote-phone-relay.ts
|
|
39432
39763
|
var import_node_events2 = require("node:events");
|
|
39433
39764
|
var import_node_fs7 = require("node:fs");
|
|
39434
|
-
var
|
|
39435
|
-
var
|
|
39765
|
+
var import_node_os6 = require("node:os");
|
|
39766
|
+
var import_node_path8 = require("node:path");
|
|
39436
39767
|
|
|
39437
39768
|
// ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
|
|
39438
39769
|
var nc = __toESM(require("node:crypto"), 1);
|
|
@@ -42207,7 +42538,10 @@ function parseFrame(bytes3) {
|
|
|
42207
42538
|
};
|
|
42208
42539
|
}
|
|
42209
42540
|
case "inbox_read":
|
|
42210
|
-
return {
|
|
42541
|
+
return {
|
|
42542
|
+
type: "inbox_read",
|
|
42543
|
+
...isString(f.projectSlug) ? { projectSlug: f.projectSlug } : {}
|
|
42544
|
+
};
|
|
42211
42545
|
case "inbox_decide":
|
|
42212
42546
|
if (!isString(f.itemId) || !isString(f.idempotencyKey))
|
|
42213
42547
|
throw new Error("frame inbox_decide: itemId + idempotencyKey required");
|
|
@@ -42220,7 +42554,8 @@ function parseFrame(bytes3) {
|
|
|
42220
42554
|
itemId: f.itemId,
|
|
42221
42555
|
decision: f.decision,
|
|
42222
42556
|
idempotencyKey: f.idempotencyKey,
|
|
42223
|
-
...f.reason === void 0 ? {} : { reason: f.reason }
|
|
42557
|
+
...f.reason === void 0 ? {} : { reason: f.reason },
|
|
42558
|
+
...isString(f.projectSlug) ? { projectSlug: f.projectSlug } : {}
|
|
42224
42559
|
};
|
|
42225
42560
|
case "ack":
|
|
42226
42561
|
if (!isString(f.refId))
|
|
@@ -42966,12 +43301,12 @@ var DirectorRelay = class {
|
|
|
42966
43301
|
this.sendFrame(channelId, { type: "ack", refId: frame.idempotencyKey });
|
|
42967
43302
|
return;
|
|
42968
43303
|
}
|
|
42969
|
-
await this.deps.onInboxDecide?.(frame.itemId, frame.decision, frame.idempotencyKey, frame.reason);
|
|
43304
|
+
await this.deps.onInboxDecide?.(frame.itemId, frame.decision, frame.idempotencyKey, frame.reason, frame.projectSlug);
|
|
42970
43305
|
this.seenDecideKeys.add(frame.idempotencyKey);
|
|
42971
43306
|
this.sendFrame(channelId, { type: "ack", refId: frame.idempotencyKey });
|
|
42972
43307
|
return;
|
|
42973
43308
|
case "inbox_read": {
|
|
42974
|
-
const items = await this.deps.onInboxRead?.();
|
|
43309
|
+
const items = await this.deps.onInboxRead?.(frame.projectSlug);
|
|
42975
43310
|
if (items !== void 0) this.sendDirectorEvent(channelId, { type: "inbox_items", items });
|
|
42976
43311
|
this.sendFrame(channelId, { type: "ack", refId: "inbox_read" });
|
|
42977
43312
|
return;
|
|
@@ -42999,9 +43334,9 @@ var DirectorRelay = class {
|
|
|
42999
43334
|
|
|
43000
43335
|
// src/remote-phone-relay.ts
|
|
43001
43336
|
function loadOrCreateAgentDeviceKey() {
|
|
43002
|
-
const
|
|
43337
|
+
const path16 = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-device-key");
|
|
43003
43338
|
try {
|
|
43004
|
-
const raw = JSON.parse((0, import_node_fs7.readFileSync)(
|
|
43339
|
+
const raw = JSON.parse((0, import_node_fs7.readFileSync)(path16, "utf8"));
|
|
43005
43340
|
if (typeof raw.priv === "string" && typeof raw.pub === "string") {
|
|
43006
43341
|
return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
|
|
43007
43342
|
}
|
|
@@ -43009,9 +43344,9 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
43009
43344
|
}
|
|
43010
43345
|
const kp = generateIdentityKeyPair();
|
|
43011
43346
|
try {
|
|
43012
|
-
(0, import_node_fs7.mkdirSync)((0,
|
|
43347
|
+
(0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
|
|
43013
43348
|
(0, import_node_fs7.writeFileSync)(
|
|
43014
|
-
|
|
43349
|
+
path16,
|
|
43015
43350
|
JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
|
|
43016
43351
|
{ mode: 384 }
|
|
43017
43352
|
);
|
|
@@ -43019,7 +43354,7 @@ function loadOrCreateAgentDeviceKey() {
|
|
|
43019
43354
|
}
|
|
43020
43355
|
return kp;
|
|
43021
43356
|
}
|
|
43022
|
-
var AGENT_PAIRING_PATH = (0,
|
|
43357
|
+
var AGENT_PAIRING_PATH = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-pairing.json");
|
|
43023
43358
|
function loadAgentPairing() {
|
|
43024
43359
|
try {
|
|
43025
43360
|
const raw = JSON.parse((0, import_node_fs7.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
|
|
@@ -43037,7 +43372,7 @@ function loadAgentPairing() {
|
|
|
43037
43372
|
}
|
|
43038
43373
|
function saveAgentPairing(record2) {
|
|
43039
43374
|
try {
|
|
43040
|
-
(0, import_node_fs7.mkdirSync)((0,
|
|
43375
|
+
(0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
|
|
43041
43376
|
(0, import_node_fs7.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
|
|
43042
43377
|
} catch {
|
|
43043
43378
|
}
|
|
@@ -43116,30 +43451,38 @@ function decisionToVerdict(decision) {
|
|
|
43116
43451
|
throw new Error(`remote-relay: unknown inbox decision "${decision}"`);
|
|
43117
43452
|
}
|
|
43118
43453
|
}
|
|
43119
|
-
function
|
|
43120
|
-
const
|
|
43121
|
-
`));
|
|
43122
|
-
const provider = createAgentTokenProvider({ secret: deps.agentSecret, baseUrl: deps.apiBaseUrl });
|
|
43123
|
-
const authed = async () => {
|
|
43454
|
+
function _makeRelayInboxCallbacks(provider, apiBaseUrl) {
|
|
43455
|
+
const authed = async (frameSlug) => {
|
|
43124
43456
|
const session = await provider.getSession();
|
|
43457
|
+
const slug = frameSlug ?? session.projectSlug;
|
|
43458
|
+
if (!slug) {
|
|
43459
|
+
throw new Error("[mrrlin-mcp remote-relay] missing project context for inbox action");
|
|
43460
|
+
}
|
|
43125
43461
|
return {
|
|
43126
|
-
client: createMrrlinClient({ baseUrl:
|
|
43127
|
-
slug
|
|
43462
|
+
client: createMrrlinClient({ baseUrl: apiBaseUrl, token: session.token }),
|
|
43463
|
+
slug,
|
|
43128
43464
|
login: session.login
|
|
43129
43465
|
};
|
|
43130
43466
|
};
|
|
43131
|
-
const onInboxRead = async () => {
|
|
43132
|
-
const { client, slug } = await authed();
|
|
43467
|
+
const onInboxRead = async (projectSlug) => {
|
|
43468
|
+
const { client, slug } = await authed(projectSlug);
|
|
43133
43469
|
return boundInboxItems(await client.listInboxItems(slug, { status: "pending" }));
|
|
43134
43470
|
};
|
|
43135
|
-
const onInboxDecide = async (itemId, decision, _key, reason) => {
|
|
43136
|
-
const { client, slug, login } = await authed();
|
|
43471
|
+
const onInboxDecide = async (itemId, decision, _key, reason, projectSlug) => {
|
|
43472
|
+
const { client, slug, login } = await authed(projectSlug);
|
|
43137
43473
|
await client.decideInboxItem(slug, itemId, {
|
|
43138
43474
|
verdict: decisionToVerdict(decision),
|
|
43139
43475
|
decidedBy: login,
|
|
43140
43476
|
...reason ? { reason } : {}
|
|
43141
43477
|
});
|
|
43142
43478
|
};
|
|
43479
|
+
return { onInboxRead, onInboxDecide };
|
|
43480
|
+
}
|
|
43481
|
+
function startRemotePhoneRelay(deps) {
|
|
43482
|
+
const log = deps.log ?? ((m) => process.stderr.write(`[mrrlin-mcp remote-relay] ${m}
|
|
43483
|
+
`));
|
|
43484
|
+
const provider = createAgentTokenProvider({ secret: deps.agentSecret, baseUrl: deps.apiBaseUrl });
|
|
43485
|
+
const { onInboxRead, onInboxDecide } = _makeRelayInboxCallbacks(provider, deps.apiBaseUrl);
|
|
43143
43486
|
const relayClient = new RelayClient({
|
|
43144
43487
|
relayUrl: deps.relayUrl,
|
|
43145
43488
|
now: () => Date.now(),
|
|
@@ -43208,11 +43551,11 @@ async function renderPairingQrSvg(payload) {
|
|
|
43208
43551
|
|
|
43209
43552
|
// src/checkout-registry.ts
|
|
43210
43553
|
var import_node_fs8 = require("node:fs");
|
|
43211
|
-
var
|
|
43554
|
+
var import_node_path9 = require("node:path");
|
|
43212
43555
|
var CheckoutRegistry = class {
|
|
43213
43556
|
file;
|
|
43214
43557
|
constructor(stateDir) {
|
|
43215
|
-
this.file = (0,
|
|
43558
|
+
this.file = (0, import_node_path9.join)(stateDir, "checkouts.json");
|
|
43216
43559
|
(0, import_node_fs8.mkdirSync)(stateDir, { recursive: true });
|
|
43217
43560
|
}
|
|
43218
43561
|
read() {
|
|
@@ -43226,17 +43569,17 @@ var CheckoutRegistry = class {
|
|
|
43226
43569
|
get(slug) {
|
|
43227
43570
|
return this.read()[slug] ?? null;
|
|
43228
43571
|
}
|
|
43229
|
-
confirm(slug,
|
|
43572
|
+
confirm(slug, path16, now) {
|
|
43230
43573
|
const all = this.read();
|
|
43231
|
-
all[slug] = { path:
|
|
43574
|
+
all[slug] = { path: path16, confirmedAt: now };
|
|
43232
43575
|
(0, import_node_fs8.writeFileSync)(this.file, JSON.stringify(all, null, 2));
|
|
43233
43576
|
}
|
|
43234
43577
|
};
|
|
43235
43578
|
|
|
43236
43579
|
// src/executor-server.ts
|
|
43237
43580
|
var import_node_fs9 = require("node:fs");
|
|
43238
|
-
var
|
|
43239
|
-
var
|
|
43581
|
+
var import_node_os7 = require("node:os");
|
|
43582
|
+
var import_node_path10 = require("node:path");
|
|
43240
43583
|
var DENY_READ_GLOBS = [
|
|
43241
43584
|
"**/.ssh/**",
|
|
43242
43585
|
"**/.aws/**",
|
|
@@ -43267,17 +43610,17 @@ function buildExecutorConfig(opts) {
|
|
|
43267
43610
|
trustWorktreeConfig: false
|
|
43268
43611
|
};
|
|
43269
43612
|
}
|
|
43270
|
-
function operatorSecretPaths(realHome = (0,
|
|
43613
|
+
function operatorSecretPaths(realHome = (0, import_node_os7.homedir)()) {
|
|
43271
43614
|
return [
|
|
43272
|
-
(0,
|
|
43273
|
-
(0,
|
|
43274
|
-
(0,
|
|
43275
|
-
(0,
|
|
43276
|
-
(0,
|
|
43277
|
-
(0,
|
|
43278
|
-
(0,
|
|
43279
|
-
(0,
|
|
43280
|
-
(0,
|
|
43615
|
+
(0, import_node_path10.join)(realHome, ".ssh"),
|
|
43616
|
+
(0, import_node_path10.join)(realHome, ".aws"),
|
|
43617
|
+
(0, import_node_path10.join)(realHome, ".config", "gh"),
|
|
43618
|
+
(0, import_node_path10.join)(realHome, ".npmrc"),
|
|
43619
|
+
(0, import_node_path10.join)(realHome, ".netrc"),
|
|
43620
|
+
(0, import_node_path10.join)(realHome, ".gnupg"),
|
|
43621
|
+
(0, import_node_path10.join)(realHome, ".kube"),
|
|
43622
|
+
(0, import_node_path10.join)(realHome, ".docker", "config.json"),
|
|
43623
|
+
(0, import_node_path10.join)(realHome, ".config", "gcloud")
|
|
43281
43624
|
];
|
|
43282
43625
|
}
|
|
43283
43626
|
var SECRET_DIRECTORY_BASENAMES = /* @__PURE__ */ new Set([".ssh", ".aws", "gh", ".gnupg", ".kube", "gcloud"]);
|
|
@@ -43286,7 +43629,7 @@ function isSecretDirectoryPath(p) {
|
|
|
43286
43629
|
return SECRET_DIRECTORY_BASENAMES.has(base);
|
|
43287
43630
|
}
|
|
43288
43631
|
function writeExecutorCodexHome(scratchDir, opts) {
|
|
43289
|
-
const codexHome = (0,
|
|
43632
|
+
const codexHome = (0, import_node_path10.join)(scratchDir, ".codex");
|
|
43290
43633
|
(0, import_node_fs9.mkdirSync)(codexHome, { recursive: true });
|
|
43291
43634
|
const hasEgress = opts.egressDomains.length > 0;
|
|
43292
43635
|
const networkSection = hasEgress ? [
|
|
@@ -43322,14 +43665,14 @@ function writeExecutorCodexHome(scratchDir, opts) {
|
|
|
43322
43665
|
networkSection,
|
|
43323
43666
|
""
|
|
43324
43667
|
].join("\n");
|
|
43325
|
-
(0, import_node_fs9.writeFileSync)((0,
|
|
43668
|
+
(0, import_node_fs9.writeFileSync)((0, import_node_path10.join)(codexHome, "config.toml"), toml3, "utf8");
|
|
43326
43669
|
return codexHome;
|
|
43327
43670
|
}
|
|
43328
43671
|
async function startExecutorServer(opts) {
|
|
43329
43672
|
const egressDomains = opts.egressDomains ?? DEFAULT_EGRESS_DOMAINS;
|
|
43330
|
-
const realHome = (0,
|
|
43673
|
+
const realHome = (0, import_node_os7.homedir)();
|
|
43331
43674
|
const denySecretPaths = operatorSecretPaths(realHome);
|
|
43332
|
-
const scratchDir = (0, import_node_fs9.mkdtempSync)((0,
|
|
43675
|
+
const scratchDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path10.join)((0, import_node_os7.tmpdir)(), "mrrlin-executor-"));
|
|
43333
43676
|
const scratchHome = scratchDir;
|
|
43334
43677
|
let scratchCleaned = false;
|
|
43335
43678
|
const cleanScratch = () => {
|
|
@@ -43528,7 +43871,7 @@ function extractVerificationSection(markdown) {
|
|
|
43528
43871
|
|
|
43529
43872
|
// src/bridge-log.ts
|
|
43530
43873
|
var import_node_fs10 = require("node:fs");
|
|
43531
|
-
var
|
|
43874
|
+
var import_node_path11 = require("node:path");
|
|
43532
43875
|
|
|
43533
43876
|
// src/redact.ts
|
|
43534
43877
|
var REDACTED = "[REDACTED]";
|
|
@@ -43613,14 +43956,14 @@ function resolvePromptsEnabled(env) {
|
|
|
43613
43956
|
}
|
|
43614
43957
|
function createBridgeLogger(stateDir, env = process.env) {
|
|
43615
43958
|
if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
|
|
43616
|
-
const logsDir = (0,
|
|
43959
|
+
const logsDir = (0, import_node_path11.join)(stateDir, "logs");
|
|
43617
43960
|
try {
|
|
43618
43961
|
(0, import_node_fs10.mkdirSync)(logsDir, { recursive: true });
|
|
43619
43962
|
} catch {
|
|
43620
43963
|
return NOOP_LOGGER;
|
|
43621
43964
|
}
|
|
43622
43965
|
const includePrompts = resolvePromptsEnabled(env);
|
|
43623
|
-
const fileFor = () => (0,
|
|
43966
|
+
const fileFor = () => (0, import_node_path11.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
|
|
43624
43967
|
const write = (dir, rec) => {
|
|
43625
43968
|
try {
|
|
43626
43969
|
const line = JSON.stringify({
|
|
@@ -43646,9 +43989,9 @@ function createBridgeLogger(stateDir, env = process.env) {
|
|
|
43646
43989
|
|
|
43647
43990
|
// src/issue-report.ts
|
|
43648
43991
|
var import_node_fs11 = require("node:fs");
|
|
43649
|
-
var
|
|
43650
|
-
var
|
|
43651
|
-
var
|
|
43992
|
+
var import_node_os8 = require("node:os");
|
|
43993
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
43994
|
+
var import_node_child_process4 = require("node:child_process");
|
|
43652
43995
|
var TELEGRAM_BOT_TOKEN = "8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A";
|
|
43653
43996
|
var TELEGRAM_CHAT_ID = "-5373779177";
|
|
43654
43997
|
function summarizeTranscript(entries = []) {
|
|
@@ -43683,10 +44026,10 @@ function describePayload(payload) {
|
|
|
43683
44026
|
function resolveLogDir() {
|
|
43684
44027
|
const codexHome = process.env.CODEX_HOME?.trim();
|
|
43685
44028
|
if (codexHome) {
|
|
43686
|
-
const candidate =
|
|
44029
|
+
const candidate = import_node_path12.default.join(codexHome, "mrrlin", "director-bridge", "logs");
|
|
43687
44030
|
if (existsDir(candidate)) return candidate;
|
|
43688
44031
|
}
|
|
43689
|
-
const fallback =
|
|
44032
|
+
const fallback = import_node_path12.default.join((0, import_node_os8.homedir)(), ".mrrlin", "director-bridge", "logs");
|
|
43690
44033
|
return fallback;
|
|
43691
44034
|
}
|
|
43692
44035
|
function existsDir(candidate) {
|
|
@@ -43698,7 +44041,7 @@ function existsDir(candidate) {
|
|
|
43698
44041
|
}
|
|
43699
44042
|
function listRecentLogFiles(logDir) {
|
|
43700
44043
|
if (!existsDir(logDir)) return [];
|
|
43701
|
-
return (0, import_node_fs11.readdirSync)(logDir).filter((name) => /^bridge-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name)).sort((a, b) => b.localeCompare(a)).slice(0, 3).map((name) =>
|
|
44044
|
+
return (0, import_node_fs11.readdirSync)(logDir).filter((name) => /^bridge-\d{4}-\d{2}-\d{2}\.jsonl$/.test(name)).sort((a, b) => b.localeCompare(a)).slice(0, 3).map((name) => import_node_path12.default.join(logDir, name));
|
|
43702
44045
|
}
|
|
43703
44046
|
function parseLogFile(file2) {
|
|
43704
44047
|
const lines2 = (0, import_node_fs11.readFileSync)(file2, "utf8").split(/\r?\n/).filter(Boolean);
|
|
@@ -43844,10 +44187,10 @@ function buildIssueDraft(request, logWindow) {
|
|
|
43844
44187
|
`- Route: ${request.urlPath?.trim() || "(unknown)"}`,
|
|
43845
44188
|
`- Director session: ${request.directorSessionId?.trim() || "(none)"}`,
|
|
43846
44189
|
`- @mrrlin-dev/mcp: ${PKG_VERSION}`,
|
|
43847
|
-
`- OS: ${(0,
|
|
44190
|
+
`- OS: ${(0, import_node_os8.platform)()}`,
|
|
43848
44191
|
`- Node: ${process.version}`
|
|
43849
44192
|
].join("\n");
|
|
43850
|
-
const logLabel = logWindow.file ?
|
|
44193
|
+
const logLabel = logWindow.file ? import_node_path12.default.basename(logWindow.file) : "(none)";
|
|
43851
44194
|
const body = [
|
|
43852
44195
|
"## Summary",
|
|
43853
44196
|
`${titlePrefix(request.source)} issue report generated from local Mrrlin evidence.`,
|
|
@@ -43883,7 +44226,7 @@ function buildTelegramAnnouncement(request, draft, issueUrl) {
|
|
|
43883
44226
|
${issueUrl}`;
|
|
43884
44227
|
}
|
|
43885
44228
|
function ensureGhReady() {
|
|
43886
|
-
const auth = (0,
|
|
44229
|
+
const auth = (0, import_node_child_process4.spawnSync)("gh", ["auth", "status", "-h", "github.com"], { encoding: "utf8" });
|
|
43887
44230
|
if (auth.status !== 0) {
|
|
43888
44231
|
const detail = (auth.stderr || auth.stdout || "gh auth status failed").trim();
|
|
43889
44232
|
throw new Error(`GitHub CLI is not ready: ${detail}`);
|
|
@@ -43891,13 +44234,13 @@ function ensureGhReady() {
|
|
|
43891
44234
|
}
|
|
43892
44235
|
function createGithubIssue(draft) {
|
|
43893
44236
|
ensureGhReady();
|
|
43894
|
-
const tmpDir = (0, import_node_fs11.mkdtempSync)(
|
|
43895
|
-
const bodyFile =
|
|
44237
|
+
const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-"));
|
|
44238
|
+
const bodyFile = import_node_path12.default.join(tmpDir, "issue-body.md");
|
|
43896
44239
|
try {
|
|
43897
44240
|
(0, import_node_fs11.writeFileSync)(bodyFile, draft.body, "utf8");
|
|
43898
44241
|
const args = ["issue", "create", "--repo", "fnnzzz/mrrlin", "--title", draft.title, "--body-file", bodyFile];
|
|
43899
44242
|
for (const label of draft.labels) args.push("--label", label);
|
|
43900
|
-
const result = (0,
|
|
44243
|
+
const result = (0, import_node_child_process4.spawnSync)("gh", args, { encoding: "utf8" });
|
|
43901
44244
|
if (result.status !== 0) {
|
|
43902
44245
|
const detail = (result.stderr || result.stdout || "gh issue create failed").trim();
|
|
43903
44246
|
throw new Error(detail);
|
|
@@ -43913,8 +44256,8 @@ function createGithubIssue(draft) {
|
|
|
43913
44256
|
}
|
|
43914
44257
|
}
|
|
43915
44258
|
function sendTelegramAnnouncement(text) {
|
|
43916
|
-
const tmpDir = (0, import_node_fs11.mkdtempSync)(
|
|
43917
|
-
const bodyFile =
|
|
44259
|
+
const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-telegram-"));
|
|
44260
|
+
const bodyFile = import_node_path12.default.join(tmpDir, "telegram-body.json");
|
|
43918
44261
|
try {
|
|
43919
44262
|
(0, import_node_fs11.writeFileSync)(
|
|
43920
44263
|
bodyFile,
|
|
@@ -43925,7 +44268,7 @@ function sendTelegramAnnouncement(text) {
|
|
|
43925
44268
|
}),
|
|
43926
44269
|
"utf8"
|
|
43927
44270
|
);
|
|
43928
|
-
const result = (0,
|
|
44271
|
+
const result = (0, import_node_child_process4.spawnSync)(
|
|
43929
44272
|
"curl",
|
|
43930
44273
|
[
|
|
43931
44274
|
"-sS",
|
|
@@ -44032,7 +44375,7 @@ function normalizeIssueScreenshots(value) {
|
|
|
44032
44375
|
return screenshots;
|
|
44033
44376
|
}
|
|
44034
44377
|
function neutralCheckoutCwd(stateDir) {
|
|
44035
|
-
const dir =
|
|
44378
|
+
const dir = import_node_path13.default.join(stateDir, "no-checkout");
|
|
44036
44379
|
try {
|
|
44037
44380
|
import_node_fs12.default.mkdirSync(dir, { recursive: true });
|
|
44038
44381
|
} catch {
|
|
@@ -44043,12 +44386,19 @@ function buildThreadStartParams(msg, config2, desiredModel) {
|
|
|
44043
44386
|
const baseInstructions = [
|
|
44044
44387
|
"You are the Mrrlin Director assistant.",
|
|
44045
44388
|
"You can call MCP tools to read and write project state.",
|
|
44046
|
-
"Prefer calling tools over guessing. Be concise.
|
|
44389
|
+
"Prefer calling tools over guessing. Be concise.",
|
|
44390
|
+
"Autonomy level is NOT a reason to skip clarification. `auto` means only that no human gate is",
|
|
44391
|
+
"required before the result LANDS (merge/deploy); it does not authorize building on unvalidated",
|
|
44392
|
+
"assumptions. Judge clarification on requirement clarity, independently of autonomy_level.",
|
|
44047
44393
|
"Never announce or pre-narrate that you are about to use tools, and never name the toolset in",
|
|
44048
44394
|
`prose. Do NOT write openers like "I'll use the Mrrlin tools to\u2026", "\u0412\u0438\u043A\u043E\u0440\u0438\u0441\u0442\u0430\u044E Mrrlin tools\u2026",`,
|
|
44049
44395
|
'or "let me call the \u2026 tool" in ANY language. The operator already sees tool calls in the',
|
|
44050
44396
|
"transcript. Just call the tools and reply with the outcome \u2014 start your reply with the result.",
|
|
44051
44397
|
"When creating or updating tasks, always provide `autonomyLevel` and `autonomyReason`.",
|
|
44398
|
+
"When you create a task out of an operator request, set `operatorSeedRequest` to the operator's",
|
|
44399
|
+
"VERBATIM words (their request as they wrote it \u2014 NOT your paraphrase or synthesized notes). It is",
|
|
44400
|
+
"the spec gate's independent record of intent; omit it only when there is genuinely no operator",
|
|
44401
|
+
"request behind the task (pure system bookkeeping) \u2014 note that omitting it makes the gate fail-closed.",
|
|
44052
44402
|
"",
|
|
44053
44403
|
"Spec authoring contract \u2014 when creating or updating a `Specs/{id}` wiki page:",
|
|
44054
44404
|
"- In `## Specification`, write each requirement as `### Requirement: <name>` followed by one",
|
|
@@ -44058,6 +44408,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
|
|
|
44058
44408
|
"- Keep behavior contracts in the spec; implementation details belong in `## Implementation Plan`.",
|
|
44059
44409
|
"- Apply this format ONLY to Specs/{id} pages; do not retro-fit it onto other wiki page types.",
|
|
44060
44410
|
"- Spec consensus runs ASYNCHRONOUSLY. Call `run_spec_consensus` for a `Specs/{id}` page; it returns IMMEDIATELY. On `already_converged`, the spec is already marked ready \u2014 proceed straight to `create_execution_run`; do NOT call `mark_spec_ready` and do NOT re-run consensus. On `queued` or `already_running`, tell the user it was launched and END your turn \u2014 do NOT poll or call it again; the result arrives in the inbox (an `info` item on CONVERGED, a `handoff` item if it was blocked/failed). When a consensus `info` item says CONVERGED, proceed to `create_execution_run`. When a `handoff` says it was blocked, address the recorded issues in the spec (any edit re-arms the gate) and call `run_spec_consensus` once more.",
|
|
44411
|
+
'- When a task needs a browser (login flows, UI verification/clicks, scraping), pass `prerequisites:[{mcp:"mrrlin-browser",reason:"..."}]` to `create_execution_run`. If that run later fails into a handoff, the operator gets a one-click "Launch browser & resume" that brings up the dedicated browser as the turn starts.',
|
|
44061
44412
|
"",
|
|
44062
44413
|
'Research playbook \u2014 when the user asks about a topic, an area, or "what do we have on X":',
|
|
44063
44414
|
"- Tasks are the source of truth. Start with `list_tasks` using `q=<keyword>`; the filter is a",
|
|
@@ -44119,12 +44470,20 @@ function buildThreadStartParams(msg, config2, desiredModel) {
|
|
|
44119
44470
|
" call `list_inbox_items` (kind=question), fold any relevant `acknowledged` TASKLESS answer",
|
|
44120
44471
|
" into the new task's Specs/{id} Clarifications, and `reject` (with a reason) any taskless",
|
|
44121
44472
|
" question the new task makes moot \u2014 so taskless answers never linger unconsumed.",
|
|
44122
|
-
"-
|
|
44123
|
-
"
|
|
44473
|
+
"- Gate-origin questions (origin='gate', filed by the spec consensus gate) are auto-folded",
|
|
44474
|
+
" into the spec and re-gated by the system when the operator answers them in the inbox.",
|
|
44475
|
+
" Do NOT fold or `decide_inbox_item` them yourself \u2014 your fold-contract above applies only",
|
|
44476
|
+
" to YOUR OWN discretionary questions.",
|
|
44477
|
+
"- When resuming a task, call `list_inbox_items` (kind=question) and fold any `acknowledged`",
|
|
44478
|
+
" answer from YOUR questions (origin is null/absent) not yet reflected into the spec's",
|
|
44479
|
+
" Clarifications section \u2014 THEN re-run `run_spec_consensus` on the updated spec. Skip",
|
|
44480
|
+
" gate-origin items (origin='gate') as those are handled automatically.",
|
|
44124
44481
|
"- If a question becomes moot (task cancelled, superseded, or no longer relevant), close it",
|
|
44125
44482
|
' with `decide_inbox_item` `verdict="rejected"` + a `reason`; never leave it pending.',
|
|
44126
|
-
"-
|
|
44127
|
-
" runs; use the handoff contract above when there is no live operator.",
|
|
44483
|
+
"- YOUR discretionary questions are a chat-only mechanism: do not create question items yourself",
|
|
44484
|
+
" from non-interactive runs; use the handoff contract above when there is no live operator.",
|
|
44485
|
+
" The spec consensus GATE, however, may file its own clarification questions on non-interactive",
|
|
44486
|
+
" runs (that is gate-driven, not your discretion) \u2014 resume them via the rule above when answered.",
|
|
44128
44487
|
"",
|
|
44129
44488
|
"Onboarding contract \u2014 seed project context when there is none:",
|
|
44130
44489
|
`- A project is un-onboarded when it has no \`${PROJECT_CONSTITUTION_PAGE.path}\` wiki page.`,
|
|
@@ -44226,7 +44585,7 @@ function resolveDefaultBranch(checkoutPath) {
|
|
|
44226
44585
|
if (!checkoutPath) return "main";
|
|
44227
44586
|
const runGit = (args) => {
|
|
44228
44587
|
try {
|
|
44229
|
-
return (0,
|
|
44588
|
+
return (0, import_node_child_process5.execFileSync)("git", ["-C", checkoutPath, ...args], {
|
|
44230
44589
|
encoding: "utf8",
|
|
44231
44590
|
stdio: ["ignore", "pipe", "ignore"],
|
|
44232
44591
|
timeout: 15e3,
|
|
@@ -44295,8 +44654,8 @@ async function runOrphanWorktreeSweep(client, opts) {
|
|
|
44295
44654
|
}
|
|
44296
44655
|
}
|
|
44297
44656
|
function readStateDir() {
|
|
44298
|
-
if (process.env.CODEX_HOME) return
|
|
44299
|
-
return
|
|
44657
|
+
if (process.env.CODEX_HOME) return import_node_path13.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
|
|
44658
|
+
return import_node_path13.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
|
|
44300
44659
|
}
|
|
44301
44660
|
function readAllowedOrigins() {
|
|
44302
44661
|
const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
|
|
@@ -44384,7 +44743,7 @@ function sessionIdOf(msg) {
|
|
|
44384
44743
|
return typeof id === "string" ? id : null;
|
|
44385
44744
|
}
|
|
44386
44745
|
function attachBridgeWss(server, opts) {
|
|
44387
|
-
const { token, allowedOrigins, onReady, logger, onPaired, selfUpdate } = opts;
|
|
44746
|
+
const { token, allowedOrigins, onReady, logger, onPaired, bridgeInstanceId, selfUpdate } = opts;
|
|
44388
44747
|
const wss = new import_websocket_server.default({ server, path: "/ws" });
|
|
44389
44748
|
wss.on("connection", (socket, request) => {
|
|
44390
44749
|
const origin = request.headers.origin;
|
|
@@ -44426,6 +44785,7 @@ function attachBridgeWss(server, opts) {
|
|
|
44426
44785
|
send({
|
|
44427
44786
|
type: "ready",
|
|
44428
44787
|
bridgeVersion: 1,
|
|
44788
|
+
...bridgeInstanceId ? { bridgeInstanceId } : {},
|
|
44429
44789
|
...selfUpdate ? {
|
|
44430
44790
|
version: selfUpdate.version,
|
|
44431
44791
|
binSha: selfUpdate.binSha,
|
|
@@ -44439,13 +44799,118 @@ function attachBridgeWss(server, opts) {
|
|
|
44439
44799
|
}
|
|
44440
44800
|
var TurnInterruptedError = class extends Error {
|
|
44441
44801
|
};
|
|
44802
|
+
function attachSeqMetadata(msg, seq, turnId) {
|
|
44803
|
+
if (msg.type === "event" || msg.type === "rateLimits" || msg.type === "error") {
|
|
44804
|
+
return { ...msg, seq, turnId };
|
|
44805
|
+
}
|
|
44806
|
+
return msg;
|
|
44807
|
+
}
|
|
44442
44808
|
function createBridgeMessageHandler(deps) {
|
|
44809
|
+
const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
|
|
44443
44810
|
return (socket, _request, send, logCtx) => {
|
|
44444
44811
|
const boundSessions = /* @__PURE__ */ new Set();
|
|
44445
44812
|
socket.on("close", () => {
|
|
44446
44813
|
for (const id of boundSessions) deps.unbindSessionSink?.(id, send);
|
|
44447
44814
|
boundSessions.clear();
|
|
44448
44815
|
});
|
|
44816
|
+
function logResumeRejected(sessionId, reason) {
|
|
44817
|
+
logCtx?.logger.logOut({
|
|
44818
|
+
spanId: logCtx.span.id,
|
|
44819
|
+
sessionId,
|
|
44820
|
+
type: "<resume-rejected>",
|
|
44821
|
+
payload: { sessionId, reason }
|
|
44822
|
+
});
|
|
44823
|
+
}
|
|
44824
|
+
function handleResumeRequest(req, sendMsg) {
|
|
44825
|
+
if (req.lastSeenBridgeInstanceId !== deps.bridgeInstanceId) {
|
|
44826
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "bridge-restarted" });
|
|
44827
|
+
logResumeRejected(req.directorSessionId, "bridge-restarted");
|
|
44828
|
+
return;
|
|
44829
|
+
}
|
|
44830
|
+
const t = deps.threads.get(req.directorSessionId);
|
|
44831
|
+
const tombstone = lookupTombstone(tombstones, req.directorSessionId);
|
|
44832
|
+
if (!t && !tombstone) {
|
|
44833
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
|
|
44834
|
+
logResumeRejected(req.directorSessionId, "wrong-session");
|
|
44835
|
+
return;
|
|
44836
|
+
}
|
|
44837
|
+
if (!t && tombstone) {
|
|
44838
|
+
const reason = tombstone.turnId === req.turnId ? "expired" : "wrong-turn";
|
|
44839
|
+
sendMsg({ type: "resume", status: "no-buffer", reason });
|
|
44840
|
+
logResumeRejected(req.directorSessionId, reason);
|
|
44841
|
+
return;
|
|
44842
|
+
}
|
|
44843
|
+
const buf = t?.replay ?? null;
|
|
44844
|
+
if (!buf) {
|
|
44845
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
|
|
44846
|
+
logResumeRejected(req.directorSessionId, "wrong-session");
|
|
44847
|
+
return;
|
|
44848
|
+
}
|
|
44849
|
+
if (buf.turnId !== req.turnId) {
|
|
44850
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-turn" });
|
|
44851
|
+
logResumeRejected(req.directorSessionId, "wrong-turn");
|
|
44852
|
+
return;
|
|
44853
|
+
}
|
|
44854
|
+
const epochMatch = req.epoch === buf.bindEpoch || req.epoch === buf.bindEpoch - 1;
|
|
44855
|
+
if (!epochMatch) {
|
|
44856
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
|
|
44857
|
+
logResumeRejected(req.directorSessionId, "superseded");
|
|
44858
|
+
return;
|
|
44859
|
+
}
|
|
44860
|
+
const tail2 = eventsAfter(buf, req.lastSeq);
|
|
44861
|
+
if (tail2 === null) {
|
|
44862
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "evicted" });
|
|
44863
|
+
logResumeRejected(req.directorSessionId, "evicted");
|
|
44864
|
+
return;
|
|
44865
|
+
}
|
|
44866
|
+
const result = transition(buf.state, { kind: "resume", epochMatch: true });
|
|
44867
|
+
if (result.next === "invalid") {
|
|
44868
|
+
sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
|
|
44869
|
+
return;
|
|
44870
|
+
}
|
|
44871
|
+
buf.state = result.next;
|
|
44872
|
+
incrementBindEpoch(buf);
|
|
44873
|
+
buf.replaying = true;
|
|
44874
|
+
deps.bindSessionSink?.(req.directorSessionId, send);
|
|
44875
|
+
boundSessions.add(req.directorSessionId);
|
|
44876
|
+
if (buf.triggerGrace) socket.once("close", buf.triggerGrace);
|
|
44877
|
+
const willStreamLive = result.next === "live";
|
|
44878
|
+
sendMsg({
|
|
44879
|
+
type: "resume",
|
|
44880
|
+
status: "replaying",
|
|
44881
|
+
turnId: buf.turnId,
|
|
44882
|
+
firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
|
|
44883
|
+
lastSeq: buf.lastSeq,
|
|
44884
|
+
spanId: buf.spanId,
|
|
44885
|
+
bindEpoch: buf.bindEpoch,
|
|
44886
|
+
eventCount: tail2.length,
|
|
44887
|
+
willStreamLive
|
|
44888
|
+
});
|
|
44889
|
+
for (const { msg: bufferedMsg } of tail2) sendMsg(bufferedMsg);
|
|
44890
|
+
for (const m of buf.outboundQueue) sendMsg(m);
|
|
44891
|
+
buf.outboundQueue.length = 0;
|
|
44892
|
+
buf.replaying = false;
|
|
44893
|
+
logCtx?.logger.logOut({
|
|
44894
|
+
spanId: logCtx.span.id,
|
|
44895
|
+
sessionId: req.directorSessionId,
|
|
44896
|
+
type: "<resume-replay>",
|
|
44897
|
+
payload: {
|
|
44898
|
+
sessionId: req.directorSessionId,
|
|
44899
|
+
turnId: buf.turnId,
|
|
44900
|
+
willStreamLive,
|
|
44901
|
+
firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
|
|
44902
|
+
lastSeq: buf.lastSeq,
|
|
44903
|
+
eventCount: tail2.length
|
|
44904
|
+
}
|
|
44905
|
+
});
|
|
44906
|
+
if (result.next === "interrupted") {
|
|
44907
|
+
const closed = transition("interrupted", { kind: "result_delivered_to_client" });
|
|
44908
|
+
if (closed.next !== "invalid") {
|
|
44909
|
+
buf.state = closed.next;
|
|
44910
|
+
buf.finishedAt = Date.now();
|
|
44911
|
+
}
|
|
44912
|
+
}
|
|
44913
|
+
}
|
|
44449
44914
|
socket.on("message", async (data) => {
|
|
44450
44915
|
const spanId = import_node_crypto5.default.randomUUID();
|
|
44451
44916
|
if (logCtx) {
|
|
@@ -44532,7 +44997,11 @@ function createBridgeMessageHandler(deps) {
|
|
|
44532
44997
|
} catch (error51) {
|
|
44533
44998
|
bootstrapError = error51 instanceof Error ? error51.message : String(error51);
|
|
44534
44999
|
}
|
|
44535
|
-
sendForSpan({ type: "bootstrap", models, rateLimits, ...bootstrapError ? { error: bootstrapError } : {} });
|
|
45000
|
+
sendForSpan({ type: "bootstrap", models, rateLimits, ...deps.bridgeInstanceId ? { bridgeInstanceId: deps.bridgeInstanceId } : {}, ...bootstrapError ? { error: bootstrapError } : {} });
|
|
45001
|
+
return;
|
|
45002
|
+
}
|
|
45003
|
+
if (msg.type === "resume") {
|
|
45004
|
+
handleResumeRequest(msg, sendForSpan);
|
|
44536
45005
|
return;
|
|
44537
45006
|
}
|
|
44538
45007
|
if (msg.type === "report_issue") {
|
|
@@ -44590,6 +45059,15 @@ function createBridgeMessageHandler(deps) {
|
|
|
44590
45059
|
sendForSpan({ type: "error", directorSessionId: directorSessionId2, error: "No active Director session to interrupt." });
|
|
44591
45060
|
return;
|
|
44592
45061
|
}
|
|
45062
|
+
const interruptBuf = existing.replay;
|
|
45063
|
+
if (interruptBuf && interruptBuf.state === "grace") {
|
|
45064
|
+
const stopResult = transition("grace", { kind: "stop" });
|
|
45065
|
+
if (stopResult.next !== "invalid") {
|
|
45066
|
+
interruptBuf.state = stopResult.next;
|
|
45067
|
+
cancelGrace(interruptBuf);
|
|
45068
|
+
recordInterrupted(interruptBuf);
|
|
45069
|
+
}
|
|
45070
|
+
}
|
|
44593
45071
|
const codexClient2 = await deps.acquireCodex();
|
|
44594
45072
|
try {
|
|
44595
45073
|
await codexClient2.turn.interrupt({ threadId: existing.threadId });
|
|
@@ -44660,7 +45138,8 @@ function createBridgeMessageHandler(deps) {
|
|
|
44660
45138
|
lastUsedAt: Date.now(),
|
|
44661
45139
|
inFlight: false,
|
|
44662
45140
|
model: desiredModel,
|
|
44663
|
-
reasoningEffort: desiredEffort
|
|
45141
|
+
reasoningEffort: desiredEffort,
|
|
45142
|
+
replay: null
|
|
44664
45143
|
};
|
|
44665
45144
|
await acquireThread(codexClient, {
|
|
44666
45145
|
threadId: null,
|
|
@@ -44710,11 +45189,52 @@ function createBridgeMessageHandler(deps) {
|
|
|
44710
45189
|
return;
|
|
44711
45190
|
}
|
|
44712
45191
|
thread.inFlight = true;
|
|
45192
|
+
thread.replay = createReplayBuffer({
|
|
45193
|
+
turnId: (0, import_node_crypto5.randomUUID)(),
|
|
45194
|
+
spanId,
|
|
45195
|
+
...deps.turnGraceMs !== void 0 ? { graceMs: deps.turnGraceMs } : {}
|
|
45196
|
+
});
|
|
44713
45197
|
thread.lastUsedAt = Date.now();
|
|
44714
45198
|
const threadId = thread.threadId;
|
|
45199
|
+
sendForSpan({
|
|
45200
|
+
type: "turn-started",
|
|
45201
|
+
directorSessionId,
|
|
45202
|
+
turnId: thread.replay.turnId
|
|
45203
|
+
});
|
|
44715
45204
|
const mapper = thread.mapper;
|
|
44716
45205
|
mapper.reset();
|
|
44717
45206
|
const contextPrefix = renderContextPrefix({ ...msg.context, directorSessionId });
|
|
45207
|
+
const sendInTurn = (msg2) => {
|
|
45208
|
+
const buf = thread.replay;
|
|
45209
|
+
if (!buf) {
|
|
45210
|
+
sendForSpan(msg2);
|
|
45211
|
+
return;
|
|
45212
|
+
}
|
|
45213
|
+
if (isTerminalEvent(msg2) && buf.terminalDelivered) {
|
|
45214
|
+
logCtx?.logger.logOut({
|
|
45215
|
+
spanId,
|
|
45216
|
+
sessionId: directorSessionId,
|
|
45217
|
+
type: "<terminal-event-dropped>",
|
|
45218
|
+
payload: { sessionId: directorSessionId, terminalAlreadyDelivered: true }
|
|
45219
|
+
});
|
|
45220
|
+
return;
|
|
45221
|
+
}
|
|
45222
|
+
const recorded = recordOutgoing(buf, msg2);
|
|
45223
|
+
if (isTerminalEvent(msg2)) buf.terminalDelivered = true;
|
|
45224
|
+
const tagged = attachSeqMetadata(recorded.msg, recorded.seq, buf.turnId);
|
|
45225
|
+
if (buf.replaying) {
|
|
45226
|
+
buf.outboundQueue.push(tagged);
|
|
45227
|
+
return;
|
|
45228
|
+
}
|
|
45229
|
+
const liveSink = deps.getSessionSink?.(directorSessionId);
|
|
45230
|
+
if (liveSink) {
|
|
45231
|
+
liveSink(tagged);
|
|
45232
|
+
return;
|
|
45233
|
+
}
|
|
45234
|
+
if (socket.readyState === socket.OPEN) {
|
|
45235
|
+
sendForSpan(tagged);
|
|
45236
|
+
}
|
|
45237
|
+
};
|
|
44718
45238
|
try {
|
|
44719
45239
|
await deps.runExclusive(async () => {
|
|
44720
45240
|
let resolveTurn = null;
|
|
@@ -44734,13 +45254,13 @@ function createBridgeMessageHandler(deps) {
|
|
|
44734
45254
|
return;
|
|
44735
45255
|
}
|
|
44736
45256
|
outputEvents += 1;
|
|
44737
|
-
|
|
45257
|
+
sendInTurn({ type: "event", directorSessionId, event });
|
|
44738
45258
|
};
|
|
44739
45259
|
const unsub = codexClient.onNotification((method, params) => {
|
|
44740
45260
|
pokeActivity();
|
|
44741
45261
|
if (method === "account/rateLimits/updated") {
|
|
44742
45262
|
const snapshot = params?.rateLimits ?? null;
|
|
44743
|
-
if (snapshot)
|
|
45263
|
+
if (snapshot) sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
|
|
44744
45264
|
}
|
|
44745
45265
|
const events = mapper.mapNotification({ method, params }, threadId);
|
|
44746
45266
|
for (const event of events) {
|
|
@@ -44778,15 +45298,41 @@ function createBridgeMessageHandler(deps) {
|
|
|
44778
45298
|
}
|
|
44779
45299
|
});
|
|
44780
45300
|
const onSocketClose = () => {
|
|
44781
|
-
|
|
44782
|
-
|
|
44783
|
-
|
|
45301
|
+
const buf = thread.replay;
|
|
45302
|
+
if (!buf || buf.state !== "live") return;
|
|
45303
|
+
const r = transition("live", { kind: "socket_close" });
|
|
45304
|
+
if (r.next === "invalid") return;
|
|
45305
|
+
buf.state = r.next;
|
|
45306
|
+
logCtx?.logger.logOut({
|
|
45307
|
+
spanId,
|
|
45308
|
+
sessionId: directorSessionId,
|
|
45309
|
+
type: "<resume-grace-started>",
|
|
45310
|
+
payload: { sessionId: directorSessionId, turnId: buf.turnId, graceMs: buf.graceMs }
|
|
45311
|
+
});
|
|
45312
|
+
enterGrace(buf, () => {
|
|
45313
|
+
const expired = transition("grace", { kind: "grace_expire" });
|
|
45314
|
+
if (expired.next === "invalid") return;
|
|
45315
|
+
buf.state = expired.next;
|
|
45316
|
+
recordInterrupted(buf);
|
|
45317
|
+
logCtx?.logger.logOut({
|
|
45318
|
+
spanId,
|
|
45319
|
+
sessionId: directorSessionId,
|
|
45320
|
+
type: "<grace-expired>",
|
|
45321
|
+
payload: { sessionId: directorSessionId, turnId: buf.turnId, lastSeq: buf.lastSeq }
|
|
45322
|
+
});
|
|
45323
|
+
rejectWatchdog?.(new TurnInterruptedError());
|
|
45324
|
+
void withTimeout(
|
|
45325
|
+
codexClient.turn.interrupt({ threadId }),
|
|
45326
|
+
DEFAULT_TURN_INTERRUPT_TIMEOUT_MS,
|
|
45327
|
+
"interrupt timed out"
|
|
45328
|
+
).catch(() => {
|
|
44784
45329
|
deps.threads.delete(directorSessionId);
|
|
44785
45330
|
deps.persistThreads();
|
|
44786
|
-
}
|
|
44787
|
-
);
|
|
45331
|
+
});
|
|
45332
|
+
});
|
|
44788
45333
|
};
|
|
44789
45334
|
socket.once("close", onSocketClose);
|
|
45335
|
+
if (thread.replay) thread.replay.triggerGrace = onSocketClose;
|
|
44790
45336
|
pokeActivity = () => watchdog.poke();
|
|
44791
45337
|
const runSequence = (async () => {
|
|
44792
45338
|
const turnInput = [];
|
|
@@ -44821,16 +45367,19 @@ ${effectiveText}` : effectiveText;
|
|
|
44821
45367
|
forward(event);
|
|
44822
45368
|
}
|
|
44823
45369
|
if (outputEvents === 0) {
|
|
44824
|
-
|
|
45370
|
+
sendInTurn({
|
|
44825
45371
|
type: "error",
|
|
44826
45372
|
directorSessionId,
|
|
44827
45373
|
error: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan."
|
|
44828
45374
|
});
|
|
44829
45375
|
}
|
|
44830
45376
|
for (const event of deferredResults) {
|
|
44831
|
-
|
|
45377
|
+
sendInTurn({ type: "event", directorSessionId, event });
|
|
44832
45378
|
}
|
|
44833
45379
|
} finally {
|
|
45380
|
+
if (thread.replay && thread.replay.state === "live") {
|
|
45381
|
+
markCompleted(thread.replay, Date.now());
|
|
45382
|
+
}
|
|
44834
45383
|
socket.off("close", onSocketClose);
|
|
44835
45384
|
watchdog.cancel();
|
|
44836
45385
|
unsub();
|
|
@@ -44839,7 +45388,7 @@ ${effectiveText}` : effectiveText;
|
|
|
44839
45388
|
});
|
|
44840
45389
|
} catch (error51) {
|
|
44841
45390
|
if (!(error51 instanceof TurnInterruptedError)) {
|
|
44842
|
-
|
|
45391
|
+
sendInTurn({ type: "error", directorSessionId, error: error51 instanceof Error ? error51.message : String(error51) });
|
|
44843
45392
|
const msg2 = error51 instanceof Error ? error51.message : String(error51);
|
|
44844
45393
|
if (/unauthor|not logged in|login|401|auth/i.test(msg2)) {
|
|
44845
45394
|
deps.setCodexAuth?.("expired");
|
|
@@ -44886,7 +45435,7 @@ function parseConfig() {
|
|
|
44886
45435
|
}
|
|
44887
45436
|
function scanForOtherBridges() {
|
|
44888
45437
|
try {
|
|
44889
|
-
const result = (0,
|
|
45438
|
+
const result = (0, import_node_child_process5.spawnSync)("pgrep", ["-f", "mrrlin-mcp director-bridge"], {
|
|
44890
45439
|
encoding: "utf8"
|
|
44891
45440
|
});
|
|
44892
45441
|
if (result.status !== 0) return [];
|
|
@@ -45018,8 +45567,8 @@ async function startDirectorBridge() {
|
|
|
45018
45567
|
codexCwd: config2.codexCwd,
|
|
45019
45568
|
codexExecutable: config2.codexExecutable,
|
|
45020
45569
|
checkoutRegistry,
|
|
45021
|
-
worktreeRoot:
|
|
45022
|
-
locksDir:
|
|
45570
|
+
worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
|
|
45571
|
+
locksDir: import_node_path13.default.join(config2.stateDir, "locks"),
|
|
45023
45572
|
// Wire the profile-enforced executor server for code-execution runs. Each run gets its own
|
|
45024
45573
|
// sandboxed Codex instance (scrubbed env, scratch CODEX_HOME, deny-read, egress allowlist).
|
|
45025
45574
|
// The returned handle's dispose() shuts down the spawned app-server CHILD (manager.shutdown(),
|
|
@@ -45052,7 +45601,7 @@ async function startDirectorBridge() {
|
|
|
45052
45601
|
},
|
|
45053
45602
|
runVerificationTurn: createRunVerificationTurn({
|
|
45054
45603
|
startSandbox: async (egressDomains) => {
|
|
45055
|
-
const cwd = import_node_fs12.default.mkdtempSync(
|
|
45604
|
+
const cwd = import_node_fs12.default.mkdtempSync(import_node_path13.default.join(import_node_os9.default.tmpdir(), "mrrlin-verify-"));
|
|
45056
45605
|
let handle;
|
|
45057
45606
|
try {
|
|
45058
45607
|
handle = await startExecutorServer({ worktree: cwd, egressDomains });
|
|
@@ -45081,6 +45630,8 @@ async function startDirectorBridge() {
|
|
|
45081
45630
|
}
|
|
45082
45631
|
};
|
|
45083
45632
|
const sessionSinks = createSessionSinkRegistry();
|
|
45633
|
+
const tombstones = /* @__PURE__ */ new Map();
|
|
45634
|
+
const bridgeInstanceId = (0, import_node_crypto5.randomUUID)();
|
|
45084
45635
|
const asyncConsumerDeps = {
|
|
45085
45636
|
client,
|
|
45086
45637
|
runExclusive: wrappedTurnLock.runExclusive,
|
|
@@ -45140,7 +45691,8 @@ async function startDirectorBridge() {
|
|
|
45140
45691
|
lastUsedAt: entry.lastUsedAt,
|
|
45141
45692
|
inFlight: false,
|
|
45142
45693
|
model: entry.model,
|
|
45143
|
-
reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort)
|
|
45694
|
+
reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort),
|
|
45695
|
+
replay: null
|
|
45144
45696
|
});
|
|
45145
45697
|
}
|
|
45146
45698
|
const persistThreads = () => {
|
|
@@ -45200,6 +45752,7 @@ async function startDirectorBridge() {
|
|
|
45200
45752
|
unbindSessionSink: (directorSessionId, send) => {
|
|
45201
45753
|
sessionSinks.unbind(directorSessionId, send);
|
|
45202
45754
|
},
|
|
45755
|
+
getSessionSink: (directorSessionId) => sessionSinks.get(directorSessionId),
|
|
45203
45756
|
maybeUpdateOffer: () => selfUpdateHandle.maybeUpdateOffer()
|
|
45204
45757
|
};
|
|
45205
45758
|
const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
|
|
@@ -45211,9 +45764,10 @@ async function startDirectorBridge() {
|
|
|
45211
45764
|
attachBridgeWss(server, {
|
|
45212
45765
|
token: config2.token,
|
|
45213
45766
|
allowedOrigins: config2.allowedOrigins,
|
|
45214
|
-
onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads }),
|
|
45767
|
+
onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads, bridgeInstanceId, tombstones }),
|
|
45215
45768
|
logger: bridgeLogger,
|
|
45216
45769
|
onPaired: () => health.setPaired(true),
|
|
45770
|
+
bridgeInstanceId,
|
|
45217
45771
|
selfUpdate: {
|
|
45218
45772
|
version: PKG_VERSION,
|
|
45219
45773
|
binSha: bridgeBinShaShort,
|
|
@@ -45313,10 +45867,36 @@ async function startDirectorBridge() {
|
|
|
45313
45867
|
enqueueRun(
|
|
45314
45868
|
() => runOrphanWorktreeSweep(client, {
|
|
45315
45869
|
checkoutRegistry,
|
|
45316
|
-
worktreeRoot:
|
|
45317
|
-
locksDir:
|
|
45870
|
+
worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
|
|
45871
|
+
locksDir: import_node_path13.default.join(config2.stateDir, "locks")
|
|
45318
45872
|
})
|
|
45319
45873
|
);
|
|
45874
|
+
enqueueRun(async () => {
|
|
45875
|
+
const now = Date.now();
|
|
45876
|
+
for (const [sid, t] of threads) {
|
|
45877
|
+
if (t.replay && shouldGc(t.replay, now)) {
|
|
45878
|
+
const turnId = t.replay.turnId;
|
|
45879
|
+
const lastSeq = t.replay.lastSeq;
|
|
45880
|
+
writeTombstone(tombstones, sid, t.replay, now);
|
|
45881
|
+
bridgeLogger.logOut({
|
|
45882
|
+
spanId: "gc",
|
|
45883
|
+
sessionId: sid,
|
|
45884
|
+
type: "<tombstone-written>",
|
|
45885
|
+
payload: { sessionId: sid, turnId, lastSeq }
|
|
45886
|
+
});
|
|
45887
|
+
t.replay = null;
|
|
45888
|
+
}
|
|
45889
|
+
}
|
|
45890
|
+
const removed = sweepExpiredTombstones(tombstones, now);
|
|
45891
|
+
if (removed > 0) {
|
|
45892
|
+
bridgeLogger.logOut({
|
|
45893
|
+
spanId: "gc",
|
|
45894
|
+
sessionId: null,
|
|
45895
|
+
type: "<tombstone-expired>",
|
|
45896
|
+
payload: { removed }
|
|
45897
|
+
});
|
|
45898
|
+
}
|
|
45899
|
+
});
|
|
45320
45900
|
scheduleClaimLoop();
|
|
45321
45901
|
}, claimIntervalMs());
|
|
45322
45902
|
claimTimer.unref?.();
|
|
@@ -45500,7 +46080,7 @@ function readDispatchBody(req) {
|
|
|
45500
46080
|
function readOrCreateBridgeToken(stateDir) {
|
|
45501
46081
|
const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
|
|
45502
46082
|
if (explicit) return explicit;
|
|
45503
|
-
const tokenPath =
|
|
46083
|
+
const tokenPath = import_node_path13.default.join(stateDir, "token.txt");
|
|
45504
46084
|
try {
|
|
45505
46085
|
const existing = import_node_fs12.default.readFileSync(tokenPath, "utf8").trim();
|
|
45506
46086
|
if (existing) return existing;
|
|
@@ -48892,16 +49472,16 @@ var StdioServerTransport = class {
|
|
|
48892
49472
|
// src/tools.ts
|
|
48893
49473
|
var import_promises3 = require("node:fs/promises");
|
|
48894
49474
|
var import_node_fs14 = require("node:fs");
|
|
48895
|
-
var
|
|
48896
|
-
var
|
|
48897
|
-
var
|
|
49475
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
49476
|
+
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
49477
|
+
var import_node_child_process8 = require("node:child_process");
|
|
48898
49478
|
|
|
48899
49479
|
// ../../packages/wiki/dist/index.js
|
|
48900
49480
|
var import_promises2 = __toESM(require("node:fs/promises"), 1);
|
|
48901
|
-
var
|
|
49481
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
48902
49482
|
var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
|
|
48903
49483
|
function toPosixPath(input) {
|
|
48904
|
-
return input.split(
|
|
49484
|
+
return input.split(import_node_path14.default.sep).join("/");
|
|
48905
49485
|
}
|
|
48906
49486
|
function slugifyWikiSegment(input) {
|
|
48907
49487
|
return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -48915,12 +49495,12 @@ async function pathExists2(input) {
|
|
|
48915
49495
|
}
|
|
48916
49496
|
}
|
|
48917
49497
|
async function findWorkspaceRoot(start = process.cwd()) {
|
|
48918
|
-
let current =
|
|
49498
|
+
let current = import_node_path14.default.resolve(start);
|
|
48919
49499
|
while (true) {
|
|
48920
|
-
if (await pathExists2(
|
|
49500
|
+
if (await pathExists2(import_node_path14.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path14.default.join(current, "docs"))) {
|
|
48921
49501
|
return current;
|
|
48922
49502
|
}
|
|
48923
|
-
const parent =
|
|
49503
|
+
const parent = import_node_path14.default.dirname(current);
|
|
48924
49504
|
if (parent === current) {
|
|
48925
49505
|
throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
|
|
48926
49506
|
}
|
|
@@ -48929,28 +49509,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
|
|
|
48929
49509
|
}
|
|
48930
49510
|
async function resolveDocsRoot(input) {
|
|
48931
49511
|
if (input) {
|
|
48932
|
-
return
|
|
49512
|
+
return import_node_path14.default.resolve(input);
|
|
48933
49513
|
}
|
|
48934
49514
|
if (process.env.MRRLIN_DOCS_ROOT) {
|
|
48935
|
-
return
|
|
49515
|
+
return import_node_path14.default.resolve(process.env.MRRLIN_DOCS_ROOT);
|
|
48936
49516
|
}
|
|
48937
|
-
return
|
|
49517
|
+
return import_node_path14.default.join(await findWorkspaceRoot(), "docs");
|
|
48938
49518
|
}
|
|
48939
49519
|
async function resolveIndexPath(input) {
|
|
48940
49520
|
if (input) {
|
|
48941
|
-
return
|
|
49521
|
+
return import_node_path14.default.resolve(input);
|
|
48942
49522
|
}
|
|
48943
49523
|
if (process.env.MRRLIN_WIKI_INDEX_PATH) {
|
|
48944
|
-
return
|
|
49524
|
+
return import_node_path14.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
|
|
48945
49525
|
}
|
|
48946
49526
|
const workspaceRoot = await findWorkspaceRoot();
|
|
48947
|
-
return
|
|
49527
|
+
return import_node_path14.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
|
|
48948
49528
|
}
|
|
48949
49529
|
async function walkMarkdownFiles(root, dir = root) {
|
|
48950
49530
|
const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
|
|
48951
49531
|
const files = [];
|
|
48952
49532
|
for (const entry of entries) {
|
|
48953
|
-
const absolute =
|
|
49533
|
+
const absolute = import_node_path14.default.join(dir, entry.name);
|
|
48954
49534
|
if (entry.isDirectory()) {
|
|
48955
49535
|
files.push(...await walkMarkdownFiles(root, absolute));
|
|
48956
49536
|
continue;
|
|
@@ -48969,7 +49549,7 @@ function parseTitle(markdown, sourcePath) {
|
|
|
48969
49549
|
return title;
|
|
48970
49550
|
}
|
|
48971
49551
|
function documentFromFile(docsRoot, absolutePath, markdown) {
|
|
48972
|
-
const relativePath = toPosixPath(
|
|
49552
|
+
const relativePath = toPosixPath(import_node_path14.default.relative(docsRoot, absolutePath));
|
|
48973
49553
|
const [section, fileName] = relativePath.split("/");
|
|
48974
49554
|
if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
|
|
48975
49555
|
return null;
|
|
@@ -49267,6 +49847,19 @@ ${dismissedFwd.slice(-20).join("\n")}` : "";
|
|
|
49267
49847
|
var SPEC_HEADS = ["plan-reviewer", "architect", "security-analyst", "scope-analyst"];
|
|
49268
49848
|
async function runSpecGate(_target, deps, opts) {
|
|
49269
49849
|
if (!await deps.consensusEnabled()) return { outcome: "SKIPPED" };
|
|
49850
|
+
const intent = await deps.readIntent();
|
|
49851
|
+
if (intent.taskId !== null && (intent.seed === null || intent.seed.trim() === "")) {
|
|
49852
|
+
return {
|
|
49853
|
+
outcome: "CONSENSUS_BLOCKED",
|
|
49854
|
+
clarifications: [
|
|
49855
|
+
{
|
|
49856
|
+
question: "What are the requirements for this task? There is no operator request on record, so the spec cannot be validated against your intent \u2014 please state what this task must do.",
|
|
49857
|
+
whyBlocking: "operator_seed_request is empty",
|
|
49858
|
+
category: "scope"
|
|
49859
|
+
}
|
|
49860
|
+
]
|
|
49861
|
+
};
|
|
49862
|
+
}
|
|
49270
49863
|
const extraHeads = opts?.extraHeads ?? [];
|
|
49271
49864
|
const heads = [...SPEC_HEADS, ...extraHeads.filter((h) => !SPEC_HEADS.includes(h))];
|
|
49272
49865
|
const spec = await deps.readSpec();
|
|
@@ -49308,6 +49901,15 @@ async function runSpecGate(_target, deps, opts) {
|
|
|
49308
49901
|
await deps.promoteSpecReady(currentHash);
|
|
49309
49902
|
return { outcome: "CONVERGED" };
|
|
49310
49903
|
}
|
|
49904
|
+
if (result.outcome === "CONSENSUS_BLOCKED") {
|
|
49905
|
+
const accepted = result.history.at(-1)?.accepted ?? [];
|
|
49906
|
+
const clarifications = accepted.filter((issue2) => issue2.category === "ambiguity" || issue2.category === "scope").map((issue2) => ({
|
|
49907
|
+
question: issue2.text,
|
|
49908
|
+
whyBlocking: `reviewer raised a ${issue2.category} issue`,
|
|
49909
|
+
category: issue2.category
|
|
49910
|
+
}));
|
|
49911
|
+
return clarifications.length > 0 ? { outcome: "CONSENSUS_BLOCKED", clarifications } : { outcome: "CONSENSUS_BLOCKED" };
|
|
49912
|
+
}
|
|
49311
49913
|
return { outcome: result.outcome };
|
|
49312
49914
|
}
|
|
49313
49915
|
|
|
@@ -49384,7 +49986,7 @@ async function runCodeGate(_target, deps) {
|
|
|
49384
49986
|
}
|
|
49385
49987
|
|
|
49386
49988
|
// src/consensus/codex-exec.ts
|
|
49387
|
-
var
|
|
49989
|
+
var import_node_child_process6 = require("node:child_process");
|
|
49388
49990
|
function extractFinalMessage(stdout) {
|
|
49389
49991
|
let last = null;
|
|
49390
49992
|
for (const rawLine of stdout.split(/\r?\n/)) {
|
|
@@ -49429,7 +50031,7 @@ function firstString(...values) {
|
|
|
49429
50031
|
return null;
|
|
49430
50032
|
}
|
|
49431
50033
|
function runCodexExec(input, deps) {
|
|
49432
|
-
const spawn2 = deps?.spawn ??
|
|
50034
|
+
const spawn2 = deps?.spawn ?? import_node_child_process6.spawn;
|
|
49433
50035
|
const executable = input.codexExecutable ?? "codex";
|
|
49434
50036
|
const sandbox = input.sandbox ?? "read-only";
|
|
49435
50037
|
const fullPrompt = input.developerInstructions.trim() ? `${input.developerInstructions.trim()}
|
|
@@ -49502,11 +50104,11 @@ function errMessage(err) {
|
|
|
49502
50104
|
|
|
49503
50105
|
// src/consensus/wiring.ts
|
|
49504
50106
|
var import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
49505
|
-
var
|
|
49506
|
-
var
|
|
50107
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
50108
|
+
var import_node_url2 = require("node:url");
|
|
49507
50109
|
|
|
49508
50110
|
// src/consensus/code-gate-git.ts
|
|
49509
|
-
var
|
|
50111
|
+
var import_node_child_process7 = require("node:child_process");
|
|
49510
50112
|
var DIFF_MAX_BYTES = 2e5;
|
|
49511
50113
|
var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
|
|
49512
50114
|
var GIT_TIMEOUT_MS = 6e4;
|
|
@@ -49522,7 +50124,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
|
|
|
49522
50124
|
};
|
|
49523
50125
|
let child;
|
|
49524
50126
|
try {
|
|
49525
|
-
child = (0,
|
|
50127
|
+
child = (0, import_node_child_process7.spawn)(cmd, args, {
|
|
49526
50128
|
cwd: opts.cwd,
|
|
49527
50129
|
env: process.env,
|
|
49528
50130
|
shell: false,
|
|
@@ -49734,18 +50336,18 @@ ${res.stdout}${res.stderr}`);
|
|
|
49734
50336
|
}
|
|
49735
50337
|
|
|
49736
50338
|
// src/consensus/wiring.ts
|
|
49737
|
-
var
|
|
50339
|
+
var import_meta2 = {};
|
|
49738
50340
|
function getPersonasDir() {
|
|
49739
50341
|
if (typeof __dirname !== "undefined") {
|
|
49740
|
-
return
|
|
50342
|
+
return import_node_path15.default.join(__dirname, "consensus", "personas");
|
|
49741
50343
|
}
|
|
49742
|
-
return
|
|
50344
|
+
return import_node_path15.default.join(import_node_path15.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
|
|
49743
50345
|
}
|
|
49744
50346
|
var personaCache = /* @__PURE__ */ new Map();
|
|
49745
50347
|
function loadPersona(name) {
|
|
49746
50348
|
const cached2 = personaCache.get(name);
|
|
49747
50349
|
if (cached2 !== void 0) return cached2;
|
|
49748
|
-
const content = import_node_fs13.default.readFileSync(
|
|
50350
|
+
const content = import_node_fs13.default.readFileSync(import_node_path15.default.join(getPersonasDir(), `${name}.md`), "utf8");
|
|
49749
50351
|
personaCache.set(name, content);
|
|
49750
50352
|
return content;
|
|
49751
50353
|
}
|
|
@@ -49754,6 +50356,19 @@ function buildSpecGateDeps(args) {
|
|
|
49754
50356
|
const rounds = Number(process.env["MRRLIN_CONSENSUS_ROUNDS"] ?? 3);
|
|
49755
50357
|
const maxHeadCalls = rounds * (4 + extraHeadCount + 1);
|
|
49756
50358
|
const timeoutMs = Number(process.env["MRRLIN_CONSENSUS_HEAD_TIMEOUT_MS"] ?? 15e4);
|
|
50359
|
+
let intentPromise = null;
|
|
50360
|
+
function loadIntent() {
|
|
50361
|
+
if (!intentPromise) {
|
|
50362
|
+
intentPromise = (async () => {
|
|
50363
|
+
const page = await client.getWikiPage(projectSlug, specPageId);
|
|
50364
|
+
const taskId = page?.taskId ?? null;
|
|
50365
|
+
if (taskId === null) return { taskId: null, seed: null };
|
|
50366
|
+
const task = await client.getTask(projectSlug, taskId);
|
|
50367
|
+
return { taskId, seed: task?.operatorSeedRequest ?? null };
|
|
50368
|
+
})();
|
|
50369
|
+
}
|
|
50370
|
+
return intentPromise;
|
|
50371
|
+
}
|
|
49757
50372
|
return {
|
|
49758
50373
|
rounds,
|
|
49759
50374
|
maxHeadCalls,
|
|
@@ -49769,15 +50384,23 @@ function buildSpecGateDeps(args) {
|
|
|
49769
50384
|
contentHash: page.contentHash
|
|
49770
50385
|
};
|
|
49771
50386
|
},
|
|
50387
|
+
readIntent() {
|
|
50388
|
+
return loadIntent();
|
|
50389
|
+
},
|
|
49772
50390
|
async runHead(personaName, artifact, dismissed) {
|
|
49773
50391
|
const persona = loadPersona(personaName);
|
|
50392
|
+
const { seed } = await loadIntent();
|
|
50393
|
+
const intentBlock = seed ? `--- OPERATOR INTENT (the operator's own words \u2014 judge the spec against THIS) ---
|
|
50394
|
+
${seed}
|
|
50395
|
+
|
|
50396
|
+
` : "";
|
|
49774
50397
|
return runCodexExec(
|
|
49775
50398
|
{
|
|
49776
|
-
prompt: `Review this spec.
|
|
50399
|
+
prompt: `Review this spec against the operator's intent.
|
|
49777
50400
|
|
|
49778
50401
|
${dismissed}
|
|
49779
50402
|
|
|
49780
|
-
--- SPEC ---
|
|
50403
|
+
${intentBlock}--- SPEC ---
|
|
49781
50404
|
${artifact}`,
|
|
49782
50405
|
developerInstructions: persona,
|
|
49783
50406
|
cwd,
|
|
@@ -49953,6 +50576,7 @@ ${artifact}`,
|
|
|
49953
50576
|
}
|
|
49954
50577
|
|
|
49955
50578
|
// src/async-tools/consensus.ts
|
|
50579
|
+
var import_node_crypto6 = require("node:crypto");
|
|
49956
50580
|
async function cachedResult(client, input) {
|
|
49957
50581
|
const page = await client.getWikiPage(input.projectSlug, input.pageId);
|
|
49958
50582
|
if (!page) return null;
|
|
@@ -49979,16 +50603,58 @@ async function run(ctx, input) {
|
|
|
49979
50603
|
deps,
|
|
49980
50604
|
input.extraHeads && input.extraHeads.length > 0 ? { extraHeads: input.extraHeads } : void 0
|
|
49981
50605
|
);
|
|
50606
|
+
if (result.outcome === "CONSENSUS_BLOCKED") {
|
|
50607
|
+
const clarifications = result.clarifications ?? [];
|
|
50608
|
+
if (clarifications.length > 0) {
|
|
50609
|
+
const page = await ctx.client.getWikiPage(input.projectSlug, input.pageId);
|
|
50610
|
+
const taskId = page?.taskId ?? null;
|
|
50611
|
+
let planId = null;
|
|
50612
|
+
if (!taskId) {
|
|
50613
|
+
const plans = await ctx.client.listPlans(input.projectSlug);
|
|
50614
|
+
planId = plans.find((p) => p.specWikiPageId === input.pageId)?.id ?? null;
|
|
50615
|
+
}
|
|
50616
|
+
if (taskId) {
|
|
50617
|
+
for (const clarification of clarifications) {
|
|
50618
|
+
const scopeId = taskId;
|
|
50619
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto6.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
|
|
50620
|
+
try {
|
|
50621
|
+
await ctx.client.createInboxItem(input.projectSlug, {
|
|
50622
|
+
id,
|
|
50623
|
+
kind: "question",
|
|
50624
|
+
taskId: scopeId,
|
|
50625
|
+
body: clarification.question,
|
|
50626
|
+
origin: "gate"
|
|
50627
|
+
});
|
|
50628
|
+
} catch {
|
|
50629
|
+
}
|
|
50630
|
+
}
|
|
50631
|
+
} else if (planId) {
|
|
50632
|
+
for (const clarification of clarifications) {
|
|
50633
|
+
const scopeId = planId;
|
|
50634
|
+
const id = `II-${scopeId}-gate-${(0, import_node_crypto6.createHash)("sha256").update(clarification.question).digest("hex").slice(0, 10)}`;
|
|
50635
|
+
try {
|
|
50636
|
+
await ctx.client.createInboxItem(input.projectSlug, {
|
|
50637
|
+
id,
|
|
50638
|
+
kind: "question",
|
|
50639
|
+
planId: scopeId,
|
|
50640
|
+
body: clarification.question,
|
|
50641
|
+
origin: "gate"
|
|
50642
|
+
});
|
|
50643
|
+
} catch {
|
|
50644
|
+
}
|
|
50645
|
+
}
|
|
50646
|
+
}
|
|
50647
|
+
}
|
|
50648
|
+
return {
|
|
50649
|
+
kind: "failed",
|
|
50650
|
+
failureReason: "consensus_blocked",
|
|
50651
|
+
error: clarifications.length > 0 ? `Consensus blocked on ${clarifications.length} clarification(s); filed as operator question(s).` : "Consensus blocked: reviewers did not converge within budget."
|
|
50652
|
+
};
|
|
50653
|
+
}
|
|
49982
50654
|
switch (result.outcome) {
|
|
49983
50655
|
case "CONVERGED":
|
|
49984
50656
|
case "SKIPPED":
|
|
49985
50657
|
return { kind: "done", resultJson: JSON.stringify(result), finalReviewedHash: null };
|
|
49986
|
-
case "CONSENSUS_BLOCKED":
|
|
49987
|
-
return {
|
|
49988
|
-
kind: "failed",
|
|
49989
|
-
failureReason: "consensus_blocked",
|
|
49990
|
-
error: "Consensus blocked: reviewers did not converge within budget."
|
|
49991
|
-
};
|
|
49992
50658
|
case "CONSENSUS_UNAVAILABLE":
|
|
49993
50659
|
return { kind: "retry", failureReason: "provider_unavailable", error: "Consensus unavailable (provider/quota)." };
|
|
49994
50660
|
case "SPEC_CHANGED_DURING_REVIEW":
|
|
@@ -50003,6 +50669,17 @@ async function run(ctx, input) {
|
|
|
50003
50669
|
}
|
|
50004
50670
|
function onComplete(outcome, input) {
|
|
50005
50671
|
if (outcome.kind === "done") {
|
|
50672
|
+
let specOutcome = "CONVERGED";
|
|
50673
|
+
try {
|
|
50674
|
+
specOutcome = JSON.parse(outcome.resultJson).outcome ?? "CONVERGED";
|
|
50675
|
+
} catch {
|
|
50676
|
+
}
|
|
50677
|
+
if (specOutcome === "SKIPPED") {
|
|
50678
|
+
return {
|
|
50679
|
+
kind: "info",
|
|
50680
|
+
body: `Consensus is disabled for this project; Specs/${input.pageId} was not gated and spec_ready is unchanged.`
|
|
50681
|
+
};
|
|
50682
|
+
}
|
|
50006
50683
|
return {
|
|
50007
50684
|
kind: "info",
|
|
50008
50685
|
body: `Consensus CONVERGED for Specs/${input.pageId}; spec_ready set. Ready to create an execution run.`
|
|
@@ -50023,7 +50700,7 @@ var consensusDescriptor = {
|
|
|
50023
50700
|
};
|
|
50024
50701
|
|
|
50025
50702
|
// src/async-tools/enqueue.ts
|
|
50026
|
-
var
|
|
50703
|
+
var import_node_crypto7 = __toESM(require("node:crypto"), 1);
|
|
50027
50704
|
async function enqueueAsyncTool(client, descriptor2, input) {
|
|
50028
50705
|
if (descriptor2.cachedResult) {
|
|
50029
50706
|
const cached2 = await descriptor2.cachedResult(client, input);
|
|
@@ -50036,7 +50713,7 @@ async function enqueueAsyncTool(client, descriptor2, input) {
|
|
|
50036
50713
|
if (active) {
|
|
50037
50714
|
return { status: "already_running", jobId: active.id, message: "Already running; will notify in inbox." };
|
|
50038
50715
|
}
|
|
50039
|
-
const jobId = `AJ-${
|
|
50716
|
+
const jobId = `AJ-${import_node_crypto7.default.randomUUID()}`;
|
|
50040
50717
|
try {
|
|
50041
50718
|
await client.createAsyncJob(input.projectSlug, {
|
|
50042
50719
|
id: jobId,
|
|
@@ -50895,7 +51572,7 @@ var mcpToolDescriptions = {
|
|
|
50895
51572
|
[mcpToolNames.runSpecConsensus]: 'Enqueue the consensus review gate over a Specs/{id} page. Returns IMMEDIATELY with one of: already_converged (a CONVERGED review already exists for the current content \u2014 proceed straight to create_execution_run, do NOT call mark_spec_ready, it is already set), already_reviewed (a terminal CONSENSUS_BLOCKED for this content), already_running (a consensus job is in flight), or queued (a new job was launched). The review runs in the background; its result/blocker arrives in the inbox (info on CONVERGED, handoff on failure) and is surfaced into the open chat. Do NOT call again for the same spec and do NOT poll. On queued/already_running, tell the user it was launched and end the turn. Pass extraHeads: ["researcher"] for specs referencing external libraries/APIs, or ["debugger"] for root-cause/investigation specs to add opt-in specialist reviewers on top of the fixed four.',
|
|
50896
51573
|
[mcpToolNames.runCodeReviewerGate]: `Review the current branch's code diff (vs baseRef) with a Code Reviewer gate \u2014 independent reviewers iterate review\u2192fix\u2192re-check (checkpoint, scope-limited reviser edits, typecheck/build fast-gate, rollback) until the diff converges or is blocked. Run before opening a PR. Pass extraHeads: ["security-analyst"] for sensitive diffs (auth, secrets, input handling, new endpoints).`,
|
|
50897
51574
|
[mcpToolNames.appendExecutionArtifact]: "Append a durable artifact (plan, checkpoint, command output, test result, diff summary, self-review, error, deploy attempt, or handoff judgement) to an execution run.",
|
|
50898
|
-
[mcpToolNames.createExecutionRun]:
|
|
51575
|
+
[mcpToolNames.createExecutionRun]: 'Create a durable Director execution run for a task. Persists status, branch/SHA, workflow ids, and checkpoint cursor outside the chat transcript. For tasks that require a browser (login flows, UI verification, scraping), set prerequisites:[{mcp:"mrrlin-browser",reason:"<why a browser is needed>"}] so any resulting handoff offers a one-click "Launch browser & resume".',
|
|
50899
51576
|
[mcpToolNames.getExecutionRun]: "Fetch a single execution run by id.",
|
|
50900
51577
|
[mcpToolNames.listExecutionArtifacts]: "List artifacts captured during an execution run, in chronological order.",
|
|
50901
51578
|
[mcpToolNames.listExecutionRuns]: "List execution runs for a project. Optional filters: taskId, status.",
|
|
@@ -51339,7 +52016,10 @@ function createMrrlinTools(options) {
|
|
|
51339
52016
|
if (ready !== true) return await c.markSpecReady({ projectSlug, pageId, ready });
|
|
51340
52017
|
const settings = await c.getOperatorSettings();
|
|
51341
52018
|
if (!settings.consensusEnabled) {
|
|
51342
|
-
|
|
52019
|
+
throw new McpToolCodedError(
|
|
52020
|
+
"SPEC_CONSENSUS_REQUIRED",
|
|
52021
|
+
`Spec ${pageId} cannot be marked ready by the Director while consensus is disabled for this project \u2014 an operator must approve it (web wiki / markSpecReady route). Autonomy is a landing gate, not a license to self-promote.`
|
|
52022
|
+
);
|
|
51343
52023
|
}
|
|
51344
52024
|
const page = await c.getWikiPage(projectSlug, pageId);
|
|
51345
52025
|
if (!page || page.folder !== "Specs") {
|
|
@@ -51508,7 +52188,7 @@ function createMrrlinTools(options) {
|
|
|
51508
52188
|
"ARTIFACT_FILE_UPLOAD_FAILED",
|
|
51509
52189
|
"Unable to upload artifact file.",
|
|
51510
52190
|
async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
|
|
51511
|
-
const extension2 =
|
|
52191
|
+
const extension2 = import_node_path16.default.extname(filePath).toLowerCase();
|
|
51512
52192
|
const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
|
|
51513
52193
|
if (!contentType) {
|
|
51514
52194
|
throw new McpToolCodedError(
|
|
@@ -51536,7 +52216,7 @@ function createMrrlinTools(options) {
|
|
|
51536
52216
|
"Artifact exceeds 5MB; split or summarize instead."
|
|
51537
52217
|
);
|
|
51538
52218
|
}
|
|
51539
|
-
const filename =
|
|
52219
|
+
const filename = import_node_path16.default.basename(filePath);
|
|
51540
52220
|
const created = await c.createArtifactFile(projectSlug, {
|
|
51541
52221
|
class: artifactClass,
|
|
51542
52222
|
contentType,
|
|
@@ -51619,7 +52299,7 @@ function createMrrlinTools(options) {
|
|
|
51619
52299
|
"Unable to register local checkout.",
|
|
51620
52300
|
async (_c, { projectSlug, path: checkoutPath, repo }) => {
|
|
51621
52301
|
const trimmedPath = checkoutPath.trim();
|
|
51622
|
-
if (!
|
|
52302
|
+
if (!import_node_path16.default.isAbsolute(trimmedPath)) {
|
|
51623
52303
|
throw new McpToolCodedError(
|
|
51624
52304
|
"LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
|
|
51625
52305
|
`Path must be absolute, got: ${trimmedPath}`
|
|
@@ -51636,7 +52316,7 @@ function createMrrlinTools(options) {
|
|
|
51636
52316
|
}
|
|
51637
52317
|
let remoteUrl;
|
|
51638
52318
|
try {
|
|
51639
|
-
remoteUrl = (0,
|
|
52319
|
+
remoteUrl = (0, import_node_child_process8.execFileSync)("git", ["-C", resolvedPath, "remote", "get-url", "origin"], {
|
|
51640
52320
|
encoding: "utf8",
|
|
51641
52321
|
stdio: ["ignore", "pipe", "ignore"],
|
|
51642
52322
|
timeout: 15e3,
|
|
@@ -51654,7 +52334,7 @@ function createMrrlinTools(options) {
|
|
|
51654
52334
|
`Origin remote ${remoteUrl} does not match repo ${repo}.`
|
|
51655
52335
|
);
|
|
51656
52336
|
}
|
|
51657
|
-
const stateDir = process.env.CODEX_HOME ?
|
|
52337
|
+
const stateDir = process.env.CODEX_HOME ? import_node_path16.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path16.default.join(import_node_os10.default.homedir(), ".mrrlin", "director-bridge");
|
|
51658
52338
|
const registry3 = new CheckoutRegistry(stateDir);
|
|
51659
52339
|
const confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
51660
52340
|
registry3.confirm(projectSlug, resolvedPath, confirmedAt);
|
|
@@ -51861,13 +52541,13 @@ function runSetCredential(args) {
|
|
|
51861
52541
|
}
|
|
51862
52542
|
|
|
51863
52543
|
// src/install-service.ts
|
|
51864
|
-
var
|
|
51865
|
-
var
|
|
52544
|
+
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
52545
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
51866
52546
|
|
|
51867
52547
|
// src/service-paths.ts
|
|
51868
|
-
var
|
|
52548
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
51869
52549
|
function isWorktreePath(p) {
|
|
51870
|
-
const norm =
|
|
52550
|
+
const norm = import_node_path17.default.normalize(p).split(import_node_path17.default.sep).join("/");
|
|
51871
52551
|
return norm.includes("/.claude/worktrees/");
|
|
51872
52552
|
}
|
|
51873
52553
|
function resolveServiceCwd(opts) {
|
|
@@ -51921,7 +52601,7 @@ function installService(deps) {
|
|
|
51921
52601
|
deps.log(resolved.reason);
|
|
51922
52602
|
return { ok: false };
|
|
51923
52603
|
}
|
|
51924
|
-
const home = deps.env.HOME ??
|
|
52604
|
+
const home = deps.env.HOME ?? import_node_os11.default.homedir();
|
|
51925
52605
|
const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
|
|
51926
52606
|
if (bins.some((b) => !b)) {
|
|
51927
52607
|
deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
|
|
@@ -51932,7 +52612,7 @@ function installService(deps) {
|
|
|
51932
52612
|
return { ok: false };
|
|
51933
52613
|
}
|
|
51934
52614
|
const resolvedBins = bins.filter((b) => b !== null);
|
|
51935
|
-
const pathEnv = Array.from(new Set(resolvedBins.map((b) =>
|
|
52615
|
+
const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path18.default.dirname(b)))).join(":");
|
|
51936
52616
|
const text = renderEcosystemConfig({
|
|
51937
52617
|
cwd: resolved.cwd,
|
|
51938
52618
|
home,
|
|
@@ -51941,7 +52621,7 @@ function installService(deps) {
|
|
|
51941
52621
|
staging: deps.env.MRRLIN_STAGING === "1",
|
|
51942
52622
|
apiBaseUrl: deps.env.MRRLIN_API_BASE_URL?.trim() || void 0
|
|
51943
52623
|
});
|
|
51944
|
-
const ecoPath =
|
|
52624
|
+
const ecoPath = import_node_path18.default.join(home, ".mrrlin", "ecosystem.config.cjs");
|
|
51945
52625
|
deps.writeFile(ecoPath, text);
|
|
51946
52626
|
const start = deps.runPm2(["startOrReload", ecoPath]);
|
|
51947
52627
|
if (start.code !== 0) {
|
|
@@ -51972,13 +52652,13 @@ function uninstallService(deps) {
|
|
|
51972
52652
|
|
|
51973
52653
|
// src/uninstall-codex.ts
|
|
51974
52654
|
var import_promises4 = __toESM(require("node:fs/promises"), 1);
|
|
51975
|
-
var
|
|
51976
|
-
var
|
|
52655
|
+
var import_node_os12 = __toESM(require("node:os"), 1);
|
|
52656
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
51977
52657
|
var toml2 = __toESM(require_toml(), 1);
|
|
51978
52658
|
function resolveCodexHome2(options) {
|
|
51979
52659
|
if (options.codexHome) return options.codexHome;
|
|
51980
52660
|
if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
|
|
51981
|
-
return
|
|
52661
|
+
return import_node_path19.default.join(options.homeDir ?? import_node_os12.default.homedir(), ".codex");
|
|
51982
52662
|
}
|
|
51983
52663
|
async function pathExists3(target) {
|
|
51984
52664
|
try {
|
|
@@ -51988,10 +52668,10 @@ async function pathExists3(target) {
|
|
|
51988
52668
|
return false;
|
|
51989
52669
|
}
|
|
51990
52670
|
}
|
|
51991
|
-
var
|
|
52671
|
+
var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.mrrlin(?:-browser)?(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
|
|
51992
52672
|
async function uninstallCodex(options = {}) {
|
|
51993
52673
|
const codexHome = resolveCodexHome2(options);
|
|
51994
|
-
const configPath =
|
|
52674
|
+
const configPath = import_node_path19.default.join(codexHome, "config.toml");
|
|
51995
52675
|
const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
|
|
51996
52676
|
if (!await pathExists3(configPath)) {
|
|
51997
52677
|
return { action: "missing", configPath, prompts: await removePrompts() };
|
|
@@ -52010,19 +52690,19 @@ async function uninstallCodex(options = {}) {
|
|
|
52010
52690
|
};
|
|
52011
52691
|
throw Object.assign(new Error(err.detail), err);
|
|
52012
52692
|
}
|
|
52013
|
-
if (parsed?.mcp_servers?.["mrrlin"] === void 0) {
|
|
52693
|
+
if (parsed?.mcp_servers?.["mrrlin"] === void 0 && parsed?.mcp_servers?.["mrrlin-browser"] === void 0) {
|
|
52014
52694
|
return { action: "noop", configPath: realPath, prompts: await removePrompts() };
|
|
52015
52695
|
}
|
|
52016
|
-
const stripped = existing.replace(
|
|
52696
|
+
const stripped = existing.replace(MRRLIN_BLOCK_RE, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
52017
52697
|
await import_promises4.default.writeFile(realPath, stripped, { mode: 384 });
|
|
52018
52698
|
return { action: "removed", configPath: realPath, prompts: await removePrompts() };
|
|
52019
52699
|
}
|
|
52020
52700
|
async function uninstallPrompts(codexHome, names) {
|
|
52021
52701
|
if (names.length === 0) return [];
|
|
52022
|
-
const promptsDir2 =
|
|
52702
|
+
const promptsDir2 = import_node_path19.default.join(codexHome, "prompts");
|
|
52023
52703
|
const out = [];
|
|
52024
52704
|
for (const name of names) {
|
|
52025
|
-
const promptPath =
|
|
52705
|
+
const promptPath = import_node_path19.default.join(promptsDir2, `${name}.md`);
|
|
52026
52706
|
try {
|
|
52027
52707
|
await import_promises4.default.unlink(promptPath);
|
|
52028
52708
|
out.push({ name, action: "removed", promptPath });
|
|
@@ -52040,26 +52720,26 @@ async function uninstallPrompts(codexHome, names) {
|
|
|
52040
52720
|
|
|
52041
52721
|
// src/report-issue-prompt.ts
|
|
52042
52722
|
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
52043
|
-
var
|
|
52044
|
-
var
|
|
52045
|
-
var
|
|
52723
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
52724
|
+
var import_node_url3 = require("node:url");
|
|
52725
|
+
var import_meta3 = {};
|
|
52046
52726
|
function promptsDir() {
|
|
52047
|
-
if (typeof __dirname !== "undefined") return
|
|
52048
|
-
return
|
|
52727
|
+
if (typeof __dirname !== "undefined") return import_node_path20.default.join(__dirname, "prompts");
|
|
52728
|
+
return import_node_path20.default.join(import_node_path20.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url)), "prompts");
|
|
52049
52729
|
}
|
|
52050
52730
|
function readReportIssuePrompt() {
|
|
52051
|
-
return import_node_fs15.default.readFileSync(
|
|
52731
|
+
return import_node_fs15.default.readFileSync(import_node_path20.default.join(promptsDir(), "report-issue.md"), "utf8");
|
|
52052
52732
|
}
|
|
52053
52733
|
|
|
52054
52734
|
// src/bin.ts
|
|
52055
52735
|
function pm2Runner(args) {
|
|
52056
|
-
const r = (0,
|
|
52736
|
+
const r = (0, import_node_child_process9.spawnSync)("pm2", args, { encoding: "utf8" });
|
|
52057
52737
|
process.stderr.write(r.stdout ?? "");
|
|
52058
52738
|
process.stderr.write(r.stderr ?? "");
|
|
52059
52739
|
return { code: r.status ?? 1, stdout: r.stdout ?? "" };
|
|
52060
52740
|
}
|
|
52061
52741
|
function whichBin(bin) {
|
|
52062
|
-
const r = (0,
|
|
52742
|
+
const r = (0, import_node_child_process9.spawnSync)("which", [bin], { encoding: "utf8" });
|
|
52063
52743
|
const out = (r.stdout ?? "").trim();
|
|
52064
52744
|
return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
|
|
52065
52745
|
}
|
|
@@ -52072,6 +52752,18 @@ Usage:
|
|
|
52072
52752
|
MRRLIN_API_ALLOW_REMOTE=1, or use MRRLIN_STAGING=1
|
|
52073
52753
|
to target the known staging API alias.
|
|
52074
52754
|
|
|
52755
|
+
mrrlin-mcp install-browser Idempotently install the dedicated, pinned
|
|
52756
|
+
Chromium into ~/.mrrlin/browser/browsers (its own
|
|
52757
|
+
copy, isolated from the operator's Chrome and
|
|
52758
|
+
codex-chrome). Run by install-codex; safe to
|
|
52759
|
+
re-run. Exits non-zero on download failure.
|
|
52760
|
+
|
|
52761
|
+
mrrlin-mcp browser-serve Launch the vendored @playwright/mcp against the
|
|
52762
|
+
dedicated persistent profile
|
|
52763
|
+
(~/.mrrlin/browser/profile, headed). This is the
|
|
52764
|
+
command install-codex wires for the
|
|
52765
|
+
[mcp_servers.mrrlin-browser] block.
|
|
52766
|
+
|
|
52075
52767
|
mrrlin-mcp install-codex Idempotently register Mrrlin in
|
|
52076
52768
|
[--force] ~/.codex/config.toml (or CODEX_HOME). Adds an
|
|
52077
52769
|
[--force-prompts] [mcp_servers.mrrlin] block AND drops the bundled
|
|
@@ -52205,10 +52897,33 @@ async function main() {
|
|
|
52205
52897
|
await startStdioServer();
|
|
52206
52898
|
return;
|
|
52207
52899
|
}
|
|
52900
|
+
case "install-browser": {
|
|
52901
|
+
const res = await installBrowser();
|
|
52902
|
+
process.stderr.write(`[mrrlin-mcp install-browser] ${res.action} ${res.browsersPath}
|
|
52903
|
+
`);
|
|
52904
|
+
return;
|
|
52905
|
+
}
|
|
52906
|
+
case "browser-serve": {
|
|
52907
|
+
const { command: command2, args, env } = browserServeArgs();
|
|
52908
|
+
const r = (0, import_node_child_process9.spawnSync)(command2, args, { stdio: "inherit", env: { ...process.env, ...env } });
|
|
52909
|
+
process.exitCode = r.status ?? 1;
|
|
52910
|
+
return;
|
|
52911
|
+
}
|
|
52208
52912
|
case "install-codex": {
|
|
52209
52913
|
const force = rest.includes("--force");
|
|
52210
52914
|
const forcePrompts = rest.includes("--force-prompts");
|
|
52211
52915
|
const binPath = resolveSelfBinPath();
|
|
52916
|
+
try {
|
|
52917
|
+
const b = await installBrowser();
|
|
52918
|
+
process.stderr.write(`[mrrlin-mcp install-codex] install-browser ${b.action} ${b.browsersPath}
|
|
52919
|
+
`);
|
|
52920
|
+
} catch (error51) {
|
|
52921
|
+
process.stderr.write(
|
|
52922
|
+
`[mrrlin-mcp install-codex] install-browser FAILED \u2014 config.toml left untouched: ${error51 instanceof Error ? error51.message : String(error51)}
|
|
52923
|
+
`
|
|
52924
|
+
);
|
|
52925
|
+
process.exit(2);
|
|
52926
|
+
}
|
|
52212
52927
|
const result = await installCodex({
|
|
52213
52928
|
binPath,
|
|
52214
52929
|
force,
|
|
@@ -52258,7 +52973,7 @@ async function main() {
|
|
|
52258
52973
|
env: process.env,
|
|
52259
52974
|
cwd: process.cwd(),
|
|
52260
52975
|
writeFile: (p, c) => {
|
|
52261
|
-
(0, import_node_fs16.mkdirSync)(
|
|
52976
|
+
(0, import_node_fs16.mkdirSync)(import_node_path22.default.dirname(p), { recursive: true, mode: 448 });
|
|
52262
52977
|
(0, import_node_fs16.writeFileSync)(p, c, { mode: 384 });
|
|
52263
52978
|
},
|
|
52264
52979
|
runPm2: pm2Runner,
|
|
@@ -52283,14 +52998,14 @@ async function main() {
|
|
|
52283
52998
|
purgeSecret: purge,
|
|
52284
52999
|
secretPath: agentCredentialPath(),
|
|
52285
53000
|
tokenPath: operatorTokenPath(),
|
|
52286
|
-
ecoPath:
|
|
53001
|
+
ecoPath: import_node_path22.default.join(process.env.HOME ?? (0, import_node_os13.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
|
|
52287
53002
|
log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
|
|
52288
53003
|
`)
|
|
52289
53004
|
});
|
|
52290
53005
|
return;
|
|
52291
53006
|
}
|
|
52292
53007
|
case "uninstall": {
|
|
52293
|
-
const home = process.env.HOME ?? (0,
|
|
53008
|
+
const home = process.env.HOME ?? (0, import_node_os13.homedir)();
|
|
52294
53009
|
const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
|
|
52295
53010
|
`);
|
|
52296
53011
|
uninstallService({
|
|
@@ -52304,7 +53019,7 @@ async function main() {
|
|
|
52304
53019
|
purgeSecret: true,
|
|
52305
53020
|
secretPath: agentCredentialPath(),
|
|
52306
53021
|
tokenPath: operatorTokenPath(),
|
|
52307
|
-
ecoPath:
|
|
53022
|
+
ecoPath: import_node_path22.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
|
|
52308
53023
|
log
|
|
52309
53024
|
});
|
|
52310
53025
|
let codexOk = true;
|
|
@@ -52324,7 +53039,7 @@ async function main() {
|
|
|
52324
53039
|
log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
52325
53040
|
}
|
|
52326
53041
|
try {
|
|
52327
|
-
(0, import_node_fs16.rmSync)(
|
|
53042
|
+
(0, import_node_fs16.rmSync)(import_node_path22.default.join(home, ".mrrlin"), { recursive: true, force: true });
|
|
52328
53043
|
} catch {
|
|
52329
53044
|
}
|
|
52330
53045
|
log("removed ~/.mrrlin");
|
|
@@ -52365,7 +53080,7 @@ ${HELP_TEXT}`);
|
|
|
52365
53080
|
}
|
|
52366
53081
|
}
|
|
52367
53082
|
function resolveSelfBinPath() {
|
|
52368
|
-
return
|
|
53083
|
+
return import_node_path21.default.resolve(process.argv[1] ?? process.execPath);
|
|
52369
53084
|
}
|
|
52370
53085
|
main().catch((error51) => {
|
|
52371
53086
|
process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}
|