@mrrlin-dev/mcp 0.3.2 → 0.3.4

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.
Files changed (3) hide show
  1. package/README.md +5 -5
  2. package/dist/bin.cjs +1047 -477
  3. package/package.json +7 -5
package/dist/bin.cjs CHANGED
@@ -7703,54 +7703,54 @@ var require_polyfills = __commonJS({
7703
7703
  }
7704
7704
  var chdir;
7705
7705
  module2.exports = patch;
7706
- function patch(fs6) {
7706
+ function patch(fs7) {
7707
7707
  if (constants.hasOwnProperty("O_SYMLINK") && process.version.match(/^v0\.6\.[0-2]|^v0\.5\./)) {
7708
- patchLchmod(fs6);
7709
- }
7710
- if (!fs6.lutimes) {
7711
- patchLutimes(fs6);
7712
- }
7713
- fs6.chown = chownFix(fs6.chown);
7714
- fs6.fchown = chownFix(fs6.fchown);
7715
- fs6.lchown = chownFix(fs6.lchown);
7716
- fs6.chmod = chmodFix(fs6.chmod);
7717
- fs6.fchmod = chmodFix(fs6.fchmod);
7718
- fs6.lchmod = chmodFix(fs6.lchmod);
7719
- fs6.chownSync = chownFixSync(fs6.chownSync);
7720
- fs6.fchownSync = chownFixSync(fs6.fchownSync);
7721
- fs6.lchownSync = chownFixSync(fs6.lchownSync);
7722
- fs6.chmodSync = chmodFixSync(fs6.chmodSync);
7723
- fs6.fchmodSync = chmodFixSync(fs6.fchmodSync);
7724
- fs6.lchmodSync = chmodFixSync(fs6.lchmodSync);
7725
- fs6.stat = statFix(fs6.stat);
7726
- fs6.fstat = statFix(fs6.fstat);
7727
- fs6.lstat = statFix(fs6.lstat);
7728
- fs6.statSync = statFixSync(fs6.statSync);
7729
- fs6.fstatSync = statFixSync(fs6.fstatSync);
7730
- fs6.lstatSync = statFixSync(fs6.lstatSync);
7731
- if (fs6.chmod && !fs6.lchmod) {
7732
- fs6.lchmod = function(path15, mode, cb) {
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
- fs6.lchmodSync = function() {
7735
+ fs7.lchmodSync = function() {
7736
7736
  };
7737
7737
  }
7738
- if (fs6.chown && !fs6.lchown) {
7739
- fs6.lchown = function(path15, uid, gid, cb) {
7738
+ if (fs7.chown && !fs7.lchown) {
7739
+ fs7.lchown = function(path16, uid, gid, cb) {
7740
7740
  if (cb) process.nextTick(cb);
7741
7741
  };
7742
- fs6.lchownSync = function() {
7742
+ fs7.lchownSync = function() {
7743
7743
  };
7744
7744
  }
7745
7745
  if (platform2 === "win32") {
7746
- fs6.rename = typeof fs6.rename !== "function" ? fs6.rename : function(fs$rename) {
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
- fs6.stat(to, function(stater, st) {
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
- }(fs6.rename);
7769
+ }(fs7.rename);
7770
7770
  }
7771
- fs6.read = typeof fs6.read !== "function" ? fs6.read : function(fs$read) {
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(fs6, fd, buffer, offset, length, position, callback);
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(fs6, fd, buffer, offset, length, position, callback);
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
- }(fs6.read);
7789
- fs6.readSync = typeof fs6.readSync !== "function" ? fs6.readSync : /* @__PURE__ */ function(fs$readSync) {
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(fs6, fd, buffer, offset, length, position);
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
- }(fs6.readSync);
7805
- function patchLchmod(fs7) {
7806
- fs7.lchmod = function(path15, mode, callback) {
7807
- fs7.open(
7808
- path15,
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
- fs7.fchmod(fd, mode, function(err2) {
7817
- fs7.close(fd, function(err22) {
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
- fs7.lchmodSync = function(path15, mode) {
7825
- var fd = fs7.openSync(path15, constants.O_WRONLY | constants.O_SYMLINK, mode);
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 = fs7.fchmodSync(fd, mode);
7829
+ ret = fs8.fchmodSync(fd, mode);
7830
7830
  threw = false;
7831
7831
  } finally {
7832
7832
  if (threw) {
7833
7833
  try {
7834
- fs7.closeSync(fd);
7834
+ fs8.closeSync(fd);
7835
7835
  } catch (er) {
7836
7836
  }
7837
7837
  } else {
7838
- fs7.closeSync(fd);
7838
+ fs8.closeSync(fd);
7839
7839
  }
7840
7840
  }
7841
7841
  return ret;
7842
7842
  };
7843
7843
  }
7844
- function patchLutimes(fs7) {
7845
- if (constants.hasOwnProperty("O_SYMLINK") && fs7.futimes) {
7846
- fs7.lutimes = function(path15, at, mt, cb) {
7847
- fs7.open(path15, constants.O_SYMLINK, function(er, fd) {
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
- fs7.futimes(fd, at, mt, function(er2) {
7853
- fs7.close(fd, function(er22) {
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
- fs7.lutimesSync = function(path15, at, mt) {
7860
- var fd = fs7.openSync(path15, constants.O_SYMLINK);
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 = fs7.futimesSync(fd, at, mt);
7864
+ ret = fs8.futimesSync(fd, at, mt);
7865
7865
  threw = false;
7866
7866
  } finally {
7867
7867
  if (threw) {
7868
7868
  try {
7869
- fs7.closeSync(fd);
7869
+ fs8.closeSync(fd);
7870
7870
  } catch (er) {
7871
7871
  }
7872
7872
  } else {
7873
- fs7.closeSync(fd);
7873
+ fs8.closeSync(fd);
7874
7874
  }
7875
7875
  }
7876
7876
  return ret;
7877
7877
  };
7878
- } else if (fs7.futimes) {
7879
- fs7.lutimes = function(_a3, _b, _c, cb) {
7878
+ } else if (fs8.futimes) {
7879
+ fs8.lutimes = function(_a3, _b, _c, cb) {
7880
7880
  if (cb) process.nextTick(cb);
7881
7881
  };
7882
- fs7.lutimesSync = function() {
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(fs6, target, mode, function(er) {
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(fs6, target, mode);
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(fs6, target, uid, gid, function(er) {
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(fs6, target, uid, gid);
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(fs6, target, options, callback) : orig.call(fs6, target, callback);
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(fs6, target, options) : orig.call(fs6, target);
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(fs6) {
7973
+ function legacy(fs7) {
7974
7974
  return {
7975
7975
  ReadStream,
7976
7976
  WriteStream
7977
7977
  };
7978
- function ReadStream(path15, options) {
7979
- if (!(this instanceof ReadStream)) return new ReadStream(path15, options);
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 = path15;
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
- fs6.open(this.path, this.flags, this.mode, function(err, fd) {
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(path15, options) {
8028
- if (!(this instanceof WriteStream)) return new WriteStream(path15, options);
8027
+ function WriteStream(path16, options) {
8028
+ if (!(this instanceof WriteStream)) return new WriteStream(path16, options);
8029
8029
  Stream.call(this);
8030
- this.path = path15;
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 = fs6.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 fs6 = require("fs");
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 (!fs6[gracefulQueue]) {
8122
+ if (!fs7[gracefulQueue]) {
8123
8123
  queue = global[gracefulQueue] || [];
8124
- publishQueue(fs6, queue);
8125
- fs6.close = function(fs$close) {
8124
+ publishQueue(fs7, queue);
8125
+ fs7.close = function(fs$close) {
8126
8126
  function close(fd, cb) {
8127
- return fs$close.call(fs6, fd, function(err) {
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
- }(fs6.close);
8140
- fs6.closeSync = function(fs$closeSync) {
8139
+ }(fs7.close);
8140
+ fs7.closeSync = function(fs$closeSync) {
8141
8141
  function closeSync(fd) {
8142
- fs$closeSync.apply(fs6, arguments);
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
- }(fs6.closeSync);
8149
+ }(fs7.closeSync);
8150
8150
  if (/\bgfs4\b/i.test(process.env.NODE_DEBUG || "")) {
8151
8151
  process.on("exit", function() {
8152
- debug(fs6[gracefulQueue]);
8153
- require("assert").equal(fs6[gracefulQueue].length, 0);
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, fs6[gracefulQueue]);
8160
- }
8161
- module2.exports = patch(clone2(fs6));
8162
- if (process.env.TEST_GRACEFUL_FS_GLOBAL_PATCH && !fs6.__patched) {
8163
- module2.exports = patch(fs6);
8164
- fs6.__patched = true;
8165
- }
8166
- function patch(fs7) {
8167
- polyfills(fs7);
8168
- fs7.gracefulify = patch;
8169
- fs7.createReadStream = createReadStream;
8170
- fs7.createWriteStream = createWriteStream;
8171
- var fs$readFile = fs7.readFile;
8172
- fs7.readFile = readFile2;
8173
- function readFile2(path15, options, cb) {
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(path15, options, cb);
8177
- function go$readFile(path16, options2, cb2, startTime) {
8178
- return fs$readFile(path16, options2, function(err) {
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, [path16, options2, cb2], err, startTime || Date.now(), Date.now()]);
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 = fs7.writeFile;
8189
- fs7.writeFile = writeFile;
8190
- function writeFile(path15, data, options, cb) {
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(path15, data, options, cb);
8194
- function go$writeFile(path16, data2, options2, cb2, startTime) {
8195
- return fs$writeFile(path16, data2, options2, function(err) {
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, [path16, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
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 = fs7.appendFile;
8205
+ var fs$appendFile = fs8.appendFile;
8206
8206
  if (fs$appendFile)
8207
- fs7.appendFile = appendFile;
8208
- function appendFile(path15, data, options, cb) {
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(path15, data, options, cb);
8212
- function go$appendFile(path16, data2, options2, cb2, startTime) {
8213
- return fs$appendFile(path16, data2, options2, function(err) {
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, [path16, data2, options2, cb2], err, startTime || Date.now(), Date.now()]);
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 = fs7.copyFile;
8223
+ var fs$copyFile = fs8.copyFile;
8224
8224
  if (fs$copyFile)
8225
- fs7.copyFile = copyFile;
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 = fs7.readdir;
8244
- fs7.readdir = readdir;
8243
+ var fs$readdir = fs8.readdir;
8244
+ fs8.readdir = readdir2;
8245
8245
  var noReaddirOptionVersions = /^v[0-5]\./;
8246
- function readdir(path15, options, cb) {
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(path16, options2, cb2, startTime) {
8250
- return fs$readdir(path16, fs$readdirCallback(
8251
- path16,
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(path16, options2, cb2, startTime) {
8257
- return fs$readdir(path16, options2, fs$readdirCallback(
8258
- path16,
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(path15, options, cb);
8265
- function fs$readdirCallback(path16, options2, cb2, startTime) {
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
- [path16, options2, cb2],
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(fs7);
8285
+ var legStreams = legacy(fs8);
8286
8286
  ReadStream = legStreams.ReadStream;
8287
8287
  WriteStream = legStreams.WriteStream;
8288
8288
  }
8289
- var fs$ReadStream = fs7.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 = fs7.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(fs7, "ReadStream", {
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(fs7, "WriteStream", {
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(fs7, "FileReadStream", {
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(fs7, "FileWriteStream", {
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(path15, options) {
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(path15, options) {
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(path15, options) {
8380
- return new fs7.ReadStream(path15, options);
8379
+ function createReadStream(path16, options) {
8380
+ return new fs8.ReadStream(path16, options);
8381
8381
  }
8382
- function createWriteStream(path15, options) {
8383
- return new fs7.WriteStream(path15, options);
8382
+ function createWriteStream(path16, options) {
8383
+ return new fs8.WriteStream(path16, options);
8384
8384
  }
8385
- var fs$open = fs7.open;
8386
- fs7.open = open;
8387
- function open(path15, flags, mode, cb) {
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(path15, flags, mode, cb);
8391
- function go$open(path16, flags2, mode2, cb2, startTime) {
8392
- return fs$open(path16, flags2, mode2, function(err, fd) {
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, [path16, flags2, mode2, cb2], err, startTime || Date.now(), Date.now()]);
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 fs7;
8402
+ return fs8;
8403
8403
  }
8404
8404
  function enqueue(elem) {
8405
8405
  debug("ENQUEUE", elem[0].name, elem[1]);
8406
- fs6[gracefulQueue].push(elem);
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 < fs6[gracefulQueue].length; ++i) {
8413
- if (fs6[gracefulQueue][i].length > 2) {
8414
- fs6[gracefulQueue][i][3] = now;
8415
- fs6[gracefulQueue][i][4] = now;
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 (fs6[gracefulQueue].length === 0)
8423
+ if (fs7[gracefulQueue].length === 0)
8424
8424
  return;
8425
- var elem = fs6[gracefulQueue].shift();
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
- fs6[gracefulQueue].push(elem);
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, fs6, callback) {
8883
- const cachedPrecision = fs6[cacheSymbol];
8882
+ function probe(file2, fs7, callback) {
8883
+ const cachedPrecision = fs7[cacheSymbol];
8884
8884
  if (cachedPrecision) {
8885
- return fs6.stat(file2, (err, stat2) => {
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
- fs6.utimes(file2, mtime, mtime, (err) => {
8893
+ fs7.utimes(file2, mtime, mtime, (err) => {
8894
8894
  if (err) {
8895
8895
  return callback(err);
8896
8896
  }
8897
- fs6.stat(file2, (err2, stat2) => {
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(fs6, cacheSymbol, { value: precision });
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 path15 = require("path");
8924
- var fs6 = require_graceful_fs();
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, path15.resolve(file2));
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: fs6,
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: fs6,
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: fs6,
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 fs6 = require_graceful_fs();
9161
- function createSyncFs(fs7) {
9160
+ var fs7 = require_graceful_fs();
9161
+ function createSyncFs(fs8) {
9162
9162
  const methods = ["mkdir", "realpath", "stat", "rmdir", "utimes"];
9163
- const newFs = { ...fs7 };
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 = fs7[`${method}Sync`](...args);
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 || fs6);
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 path15 = dijkstra.find_path(graph.map, "start", "end");
10798
+ const path16 = dijkstra.find_path(graph.map, "start", "end");
10799
10799
  const optimizedSegs = [];
10800
- for (let i = 1; i < path15.length - 1; i++) {
10801
- optimizedSegs.push(graph.table[path15[i]].node);
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 fs6 = require("fs");
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(path15, qrData, options, cb) {
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 = fs6.createWriteStream(path15);
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(path15, qrData, options, cb) {
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 fs6 = require("fs");
13356
+ const fs7 = require("fs");
13357
13357
  const utf8 = exports2.render(qrData, options);
13358
- fs6.writeFile(path15, utf8, cb);
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 path15 = "";
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
- path15 += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
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
- path15 += svgCmd("h", lineLength);
13495
+ path16 += svgCmd("h", lineLength);
13496
13496
  lineLength = 0;
13497
13497
  }
13498
13498
  } else {
13499
13499
  moveBy++;
13500
13500
  }
13501
13501
  }
13502
- return path15;
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 path15 = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
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 + path15 + "</svg>\n";
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(path15, qrData, options, cb) {
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 fs6 = require("fs");
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
- fs6.writeFile(path15, xmlStr, cb);
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(path15) {
13694
- return path15.slice((path15.lastIndexOf(".") - 1 >>> 0) + 2).toLowerCase();
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(path15, text, opts, cb) {
13759
- if (typeof path15 !== "string" || !(typeof text === "string" || typeof text === "object")) {
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(path15);
13766
+ const type = params.opts.type || getTypeFromFilename(path16);
13767
13767
  const renderer = getRendererFromType(type);
13768
- const renderToFile = renderer.renderToFile.bind(null, path15);
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(path15) {
16987
- let input = path15;
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 [path15, query] = wsComponent.resourceName.split("?");
17240
- wsComponent.path = path15 && path15 !== "/" ? path15 : void 0;
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, fs6, exportName) {
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, fs6[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 toml = __toESM(require_toml(), 1);
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 import_node_path.default.join(options.homeDir ?? import_node_os.default.homedir(), ".codex");
20730
+ return import_node_path2.default.join(options.homeDir ?? import_node_os2.default.homedir(), ".codex");
20662
20731
  }
20663
- function expectedTable(binPath, distribution) {
20664
- if (distribution === "npm") {
20665
- return {
20666
- args: ["serve"],
20667
- command: "mrrlin-mcp",
20668
- startup_timeout_sec: 30
20669
- };
20670
- }
20671
- return {
20672
- args: [binPath, "serve"],
20673
- command: "node",
20674
- startup_timeout_sec: 30
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 = import_node_path.default.dirname(options.binPath);
20757
+ let current = import_node_path2.default.dirname(options.binPath);
20680
20758
  while (true) {
20681
- if (await pathExists(import_node_path.default.join(current, "pnpm-workspace.yaml"))) {
20759
+ if (await pathExists(import_node_path2.default.join(current, "pnpm-workspace.yaml"))) {
20682
20760
  return "local";
20683
20761
  }
20684
- const parent = import_node_path.default.dirname(current);
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(binPath, distribution) {
20691
- const expected = expectedTable(binPath, distribution);
20692
- return [
20768
+ function renderBlock(block) {
20769
+ const { id, expected } = block;
20770
+ const lines2 = [
20693
20771
  "",
20694
- "[mcp_servers.mrrlin]",
20695
- `command = "${expected.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
- ].join("\n");
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 = import_node_path.default.join(codexHome, "config.toml");
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
- await import_promises.default.writeFile(configPath, renderBlock(options.binPath, distribution).replace(/^\n/, ""), { mode: 384 });
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
- const existing = await import_promises.default.readFile(realPath, "utf8");
20833
+ let content = await import_promises.default.readFile(realPath, "utf8");
20742
20834
  let parsed = null;
20743
20835
  try {
20744
- parsed = toml.parse(existing);
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
- const existingTable = parsed?.mcp_servers?.["mrrlin"];
20755
- if (existingTable !== void 0) {
20756
- if (tablesEqual(existingTable, expectedTable(options.binPath, distribution))) {
20757
- return { action: "noop", configPath: realPath, prompts: await writePrompts() };
20758
- }
20759
- if (!options.force) {
20760
- const err = {
20761
- code: "CODEX_CONFIG_CONFLICT",
20762
- configPath: realPath,
20763
- detail: "An [mcp_servers.mrrlin] block already exists with different settings. Re-run with --force to replace it, or remove it manually."
20764
- };
20765
- throw Object.assign(new Error(err.detail), err);
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
- const appended = appendMrrlinBlock(existing, renderBlock(options.binPath, distribution));
20772
- await import_promises.default.writeFile(realPath, appended, { mode: 384 });
20773
- return { action: "appended", configPath: realPath, prompts: await writePrompts() };
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 = import_node_path.default.join(codexHome, "prompts");
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 = import_node_path.default.join(promptsDir2, `${prompt.name}.md`);
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 appendMrrlinBlock(existing, block) {
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
- var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.mrrlin\][\s\S]*?(?=\n\[|$)/;
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(MRRLIN_BLOCK_RE, (match) => {
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 import_node_os8 = __toESM(require("node:os"), 1);
20826
- var import_node_path12 = __toESM(require("node:path"), 1);
20827
- var import_node_child_process4 = require("node:child_process");
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 import_node_child_process = require("node:child_process");
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 ?? import_node_child_process.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, path15) {
22138
- if (!path15)
22424
+ function getElementAtPath(obj, path16) {
22425
+ if (!path16)
22139
22426
  return obj;
22140
- return path15.reduce((acc, key) => acc?.[key], obj);
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(path15, issues) {
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(path15);
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, path15 = []) => {
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 }, [...path15, ...issue2.path]));
22990
+ issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
22704
22991
  } else if (issue2.code === "invalid_key") {
22705
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
22992
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22706
22993
  } else if (issue2.code === "invalid_element") {
22707
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
22994
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22708
22995
  } else {
22709
- const fullpath = [...path15, ...issue2.path];
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, path15 = []) => {
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 }, [...path15, ...issue2.path]));
23027
+ issue2.errors.map((issues) => processError({ issues }, [...path16, ...issue2.path]));
22741
23028
  } else if (issue2.code === "invalid_key") {
22742
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
23029
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22743
23030
  } else if (issue2.code === "invalid_element") {
22744
- processError({ issues: issue2.issues }, [...path15, ...issue2.path]);
23031
+ processError({ issues: issue2.issues }, [...path16, ...issue2.path]);
22745
23032
  } else {
22746
- const fullpath = [...path15, ...issue2.path];
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 path15 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
22779
- for (const seg of path15) {
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 path15 = ref.slice(1).split("/").filter(Boolean);
35472
- if (path15.length === 0) {
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 (path15[0] === defsKey) {
35477
- const key = path15[1];
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",
@@ -36643,6 +36931,10 @@ var markSpecReadyResponseSchema = external_exports.object({
36643
36931
  var wikiPageSpecReadyCasResponseSchema = external_exports.object({
36644
36932
  data: external_exports.object({ promoted: external_exports.literal(true) })
36645
36933
  });
36934
+ var mrrlinRunPrerequisiteSchema = external_exports.object({
36935
+ mcp: external_exports.string().min(1),
36936
+ reason: external_exports.string().min(1)
36937
+ });
36646
36938
  var mrrlinExecutionRunSchema = external_exports.object({
36647
36939
  actor: external_exports.string().min(1),
36648
36940
  baseSha: external_exports.string().min(1).nullable(),
@@ -36651,6 +36943,7 @@ var mrrlinExecutionRunSchema = external_exports.object({
36651
36943
  claimedAt: external_exports.string().datetime().nullable(),
36652
36944
  codeExecution: external_exports.boolean(),
36653
36945
  createdAt: external_exports.string().datetime(),
36946
+ devEnvUrl: external_exports.string().min(1).nullable(),
36654
36947
  devRunUrl: external_exports.string().min(1).nullable(),
36655
36948
  devWorkflowId: external_exports.number().int().positive().nullable(),
36656
36949
  directorSessionId: external_exports.string().min(1).nullable(),
@@ -36659,6 +36952,8 @@ var mrrlinExecutionRunSchema = external_exports.object({
36659
36952
  id: mrrlinExecutionRunIdSchema,
36660
36953
  lastActor: external_exports.string().min(1).nullable(),
36661
36954
  leaseId: external_exports.string().min(1).nullable(),
36955
+ prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema),
36956
+ prodEnvUrl: external_exports.string().min(1).nullable(),
36662
36957
  prodRunUrl: external_exports.string().min(1).nullable(),
36663
36958
  prodWorkflowId: external_exports.number().int().positive().nullable(),
36664
36959
  projectSlug: mrrlinProjectSlugSchema,
@@ -36677,6 +36972,7 @@ var mrrlinExecutionRunCreateSchema = external_exports.object({
36677
36972
  codeExecution: external_exports.boolean().optional().default(false),
36678
36973
  devWorkflowId: external_exports.number().int().positive().optional(),
36679
36974
  id: mrrlinExecutionRunIdSchema,
36975
+ prerequisites: external_exports.array(mrrlinRunPrerequisiteSchema).default([]),
36680
36976
  prodWorkflowId: external_exports.number().int().positive().optional(),
36681
36977
  provider: external_exports.string().min(1),
36682
36978
  status: mrrlinExecutionRunStatusSchema.default("pending"),
@@ -36687,11 +36983,13 @@ var mrrlinExecutionRunUpdateSchema = external_exports.object({
36687
36983
  baseSha: external_exports.string().min(1).nullable().optional(),
36688
36984
  branch: external_exports.string().min(1).nullable().optional(),
36689
36985
  checkpointCursor: external_exports.string().min(1).nullable().optional(),
36986
+ devEnvUrl: external_exports.string().min(1).nullable().optional(),
36690
36987
  devRunUrl: external_exports.string().min(1).nullable().optional(),
36691
36988
  devWorkflowId: external_exports.number().int().positive().nullable().optional(),
36692
36989
  finishedAt: external_exports.string().datetime().nullable().optional(),
36693
36990
  headSha: external_exports.string().min(1).nullable().optional(),
36694
36991
  leaseId: external_exports.string().min(1).nullable().optional(),
36992
+ prodEnvUrl: external_exports.string().min(1).nullable().optional(),
36695
36993
  prodRunUrl: external_exports.string().min(1).nullable().optional(),
36696
36994
  prodWorkflowId: external_exports.number().int().positive().nullable().optional(),
36697
36995
  pullRequestUrl: external_exports.string().min(1).nullable().optional(),
@@ -36739,6 +37037,7 @@ var mrrlinResolveHandoffSchema = external_exports.object({
36739
37037
  }
36740
37038
  });
36741
37039
  var resolveHandoffResponseSchema = external_exports.object({ data: mrrlinExecutionRunSchema });
37040
+ var createExecutionRunHandoffSchema = external_exports.object({ reason: external_exports.string().min(1) });
36742
37041
  var mrrlinExecutionRunTouchSchema = external_exports.object({
36743
37042
  leaseId: external_exports.string().min(1)
36744
37043
  });
@@ -36822,6 +37121,7 @@ var mrrlinArtifactFileMimeTypes = [
36822
37121
  ];
36823
37122
  var mrrlinArtifactFileClassSchema = external_exports.enum(["temp", "durable"]);
36824
37123
  var mrrlinArtifactFileStatusSchema = external_exports.enum(["pending", "uploaded", "expired"]);
37124
+ var mrrlinArtifactFileVisibilitySchema = external_exports.enum(["private", "public"]);
36825
37125
  var mrrlinArtifactFileSchema = external_exports.object({
36826
37126
  class: mrrlinArtifactFileClassSchema,
36827
37127
  contentType: external_exports.enum(mrrlinArtifactFileMimeTypes),
@@ -36836,7 +37136,9 @@ var mrrlinArtifactFileSchema = external_exports.object({
36836
37136
  // min(0): reads tolerate 0-byte rows; creation requires min(1) (see create schema).
36837
37137
  sizeBytes: external_exports.number().int().min(0).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
36838
37138
  status: mrrlinArtifactFileStatusSchema,
36839
- taskId: mrrlinTaskIdSchema.nullable()
37139
+ taskId: mrrlinTaskIdSchema.nullable(),
37140
+ // Defaulted (fail-safe → private) so legacy rows/fixtures predating the column read as private.
37141
+ visibility: mrrlinArtifactFileVisibilitySchema.default("private")
36840
37142
  });
36841
37143
  var mrrlinArtifactFileCreateSchema = external_exports.object({
36842
37144
  class: mrrlinArtifactFileClassSchema,
@@ -36844,7 +37146,9 @@ var mrrlinArtifactFileCreateSchema = external_exports.object({
36844
37146
  filename: external_exports.string().min(1).max(255),
36845
37147
  runId: mrrlinExecutionRunIdSchema.optional(),
36846
37148
  sizeBytes: external_exports.number().int().min(1).max(MRRLIN_ARTIFACT_FILE_MAX_BYTES),
36847
- taskId: mrrlinTaskIdSchema.optional()
37149
+ taskId: mrrlinTaskIdSchema.optional(),
37150
+ // Optional + fail-safe: callers must opt in to 'public'; everything else stays private.
37151
+ visibility: mrrlinArtifactFileVisibilitySchema.optional().default("private")
36848
37152
  });
36849
37153
  var mrrlinArtifactFileUploadTargetSchema = external_exports.discriminatedUnion("kind", [
36850
37154
  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()) }),
@@ -37108,18 +37412,18 @@ function createMrrlinClient(config2) {
37108
37412
  const customFetch = config2.fetch ?? globalThis.fetch;
37109
37413
  const baseUrl = config2.baseUrl.replace(/\/$/, "");
37110
37414
  const token = config2.token;
37111
- async function request(path15, init) {
37415
+ async function request(path16, init) {
37112
37416
  const method = init?.method ?? "GET";
37113
37417
  const headers = new Headers(init?.headers ?? {});
37114
37418
  if (token && !headers.has("authorization")) {
37115
37419
  headers.set("authorization", `Bearer ${token}`);
37116
37420
  }
37117
- const response = await customFetch(`${baseUrl}${path15}`, { ...init, headers });
37421
+ const response = await customFetch(`${baseUrl}${path16}`, { ...init, headers });
37118
37422
  if (!response.ok) {
37119
37423
  const body = await response.text();
37120
37424
  let code = `HTTP_${response.status}`;
37121
37425
  let violations = null;
37122
- let message = `Mrrlin API ${method} ${path15} failed: ${response.status}`;
37426
+ let message = `Mrrlin API ${method} ${path16} failed: ${response.status}`;
37123
37427
  try {
37124
37428
  const parsed = JSON.parse(body);
37125
37429
  const violationsParsed = apiViolationsErrorSchema.safeParse(parsed);
@@ -37139,7 +37443,7 @@ function createMrrlinClient(config2) {
37139
37443
  throw new MrrlinApiError({
37140
37444
  code,
37141
37445
  method,
37142
- path: path15,
37446
+ path: path16,
37143
37447
  responseBody: body,
37144
37448
  status: response.status,
37145
37449
  violations,
@@ -37386,7 +37690,7 @@ function createMrrlinClient(config2) {
37386
37690
  return taskEventListResponseSchema.parse(body).data;
37387
37691
  },
37388
37692
  async listTasks(projectSlug, filters = {}) {
37389
- const path15 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
37693
+ const path16 = appendQuery(`${projectPath(projectSlug)}/tasks`, {
37390
37694
  assignee: filters.assignee,
37391
37695
  autonomyLevel: filters.autonomyLevel,
37392
37696
  blockedBy: filters.blockedBy,
@@ -37398,7 +37702,7 @@ function createMrrlinClient(config2) {
37398
37702
  subcategory: filters.subcategory,
37399
37703
  type: filters.type
37400
37704
  });
37401
- const body = await request(path15);
37705
+ const body = await request(path16);
37402
37706
  return taskListResponseSchema.parse(body).data;
37403
37707
  },
37404
37708
  async listTaxonomy(projectSlug) {
@@ -37406,22 +37710,22 @@ function createMrrlinClient(config2) {
37406
37710
  return taxonomyListResponseSchema.parse(body).data;
37407
37711
  },
37408
37712
  async listWikiPages(projectSlug, filters = {}) {
37409
- const path15 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
37713
+ const path16 = appendQuery(`${projectPath(projectSlug)}/wiki`, {
37410
37714
  folder: filters.folder,
37411
37715
  q: filters.q,
37412
37716
  taskId: filters.taskId
37413
37717
  });
37414
- const body = await request(path15);
37718
+ const body = await request(path16);
37415
37719
  return wikiPageListResponseSchema.parse(body).data;
37416
37720
  },
37417
37721
  async searchWikiPages(projectSlug, query) {
37418
- const path15 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
37722
+ const path16 = appendQuery(`${projectPath(projectSlug)}/wiki/search`, {
37419
37723
  folder: query.folder,
37420
37724
  limit: query.limit === void 0 ? void 0 : String(query.limit),
37421
37725
  pathPrefix: query.pathPrefix,
37422
37726
  q: query.q
37423
37727
  });
37424
- const body = await request(path15);
37728
+ const body = await request(path16);
37425
37729
  return wikiPageSearchResponseSchema.parse(body).data;
37426
37730
  },
37427
37731
  async updatePlan(projectSlug, planId, patch) {
@@ -37687,6 +37991,14 @@ function createMrrlinClient(config2) {
37687
37991
  });
37688
37992
  return executionRunResponseSchema.parse(body).data;
37689
37993
  },
37994
+ async createExecutionRunHandoff(projectSlug, runId, input) {
37995
+ const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/handoff`, {
37996
+ body: JSON.stringify(input),
37997
+ headers: { "content-type": "application/json" },
37998
+ method: "POST"
37999
+ });
38000
+ return executionRunResponseSchema.parse(body).data;
38001
+ },
37690
38002
  async listExecutionArtifacts(projectSlug, runId) {
37691
38003
  const body = await request(`${projectPath(projectSlug)}/execution-runs/${encodeURIComponent(runId)}/artifacts`);
37692
38004
  return executionArtifactListResponseSchema.parse(body).data;
@@ -37962,13 +38274,13 @@ function startSelfUpdate(deps) {
37962
38274
  });
37963
38275
  return `[bridge:update] An update for @mrrlin-dev/mcp is available: ${pkgVersion} \u2192 ${latestVersion}.
37964
38276
 
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 \`pnpm install -g @mrrlin-dev/mcp@latest\`)". Do NOT install without explicit confirmation.
38277
+ 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
38278
 
37967
- If the operator confirms (yes / \u0442\u0430\u043A / \u0430\u0433\u0430 / etc.): immediately run \`pnpm 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.
38279
+ 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
38280
 
37969
38281
  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
38282
 
37971
- If the install fails (permission denied, registry pinned, sudo required, network blocked): paste the error verbatim and show the operator the manual command \`pnpm install -g @mrrlin-dev/mcp@latest\` plus a one-line hint about likely cause.
38283
+ 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
38284
 
37973
38285
  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
38286
  }
@@ -38130,7 +38442,7 @@ Do NOT derail the current task \u2014 if the operator has an in-flight question,
38130
38442
  }
38131
38443
 
38132
38444
  // src/_generated/version.ts
38133
- var PKG_VERSION = "0.3.2";
38445
+ var PKG_VERSION = "0.3.4";
38134
38446
 
38135
38447
  // src/api-base-url.ts
38136
38448
  var DEFAULT_API_BASE_URL = "http://127.0.0.1:8787";
@@ -38297,6 +38609,11 @@ async function runDeployGateTick(deps, projectSlug, run2, task) {
38297
38609
  await deps.handoff(projectSlug, task, run2, "no_environment_url");
38298
38610
  return { kind: "handoff", reason: "no_environment_url" };
38299
38611
  }
38612
+ await deps.client.updateExecutionRun(
38613
+ projectSlug,
38614
+ run2.id,
38615
+ env === "dev" ? { devEnvUrl: deployment.environmentUrl } : { prodEnvUrl: deployment.environmentUrl }
38616
+ );
38300
38617
  const section = await deps.loadVerificationSection(projectSlug, task);
38301
38618
  if (!section || section.trim().length === 0) {
38302
38619
  await deps.handoff(projectSlug, task, run2, "verification_steps_missing_at_verify");
@@ -38359,18 +38676,18 @@ async function awaitTurnWithDeadline(opts) {
38359
38676
  }
38360
38677
 
38361
38678
  // src/worktree.ts
38362
- var import_node_child_process2 = require("node:child_process");
38679
+ var import_node_child_process3 = require("node:child_process");
38363
38680
  var import_node_fs3 = require("node:fs");
38364
- var import_node_os2 = require("node:os");
38365
- var import_node_path3 = require("node:path");
38681
+ var import_node_os3 = require("node:os");
38682
+ var import_node_path4 = require("node:path");
38366
38683
 
38367
38684
  // src/checkout-lock.ts
38368
38685
  var import_node_fs2 = require("node:fs");
38369
- var import_node_path2 = require("node:path");
38686
+ var import_node_path3 = require("node:path");
38370
38687
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
38371
38688
  async function withCheckoutLock(locksDir, slug, fn) {
38372
38689
  (0, import_node_fs2.mkdirSync)(locksDir, { recursive: true });
38373
- const target = (0, import_node_path2.join)(locksDir, `${slug}.lock`);
38690
+ const target = (0, import_node_path3.join)(locksDir, `${slug}.lock`);
38374
38691
  if (!(0, import_node_fs2.existsSync)(target)) (0, import_node_fs2.writeFileSync)(target, "");
38375
38692
  const release = await import_proper_lockfile.default.lock(target, {
38376
38693
  retries: { retries: 600, factor: 1, minTimeout: 100, maxTimeout: 100 },
@@ -38387,16 +38704,16 @@ async function withCheckoutLock(locksDir, slug, fn) {
38387
38704
  function worktreeBranch(runId) {
38388
38705
  return `mrrlin/run-${runId}`;
38389
38706
  }
38390
- var defaultGitExec = (args, env) => (0, import_node_child_process2.execFileSync)("git", args, { encoding: "utf8", timeout: 3e4, env });
38707
+ var defaultGitExec = (args, env) => (0, import_node_child_process3.execFileSync)("git", args, { encoding: "utf8", timeout: 3e4, env });
38391
38708
  function git(checkout, args) {
38392
- return (0, import_node_child_process2.execFileSync)("git", ["-C", checkout, ...args], {
38709
+ return (0, import_node_child_process3.execFileSync)("git", ["-C", checkout, ...args], {
38393
38710
  encoding: "utf8",
38394
38711
  timeout: 3e4,
38395
38712
  env: { ...process.env, GIT_TERMINAL_PROMPT: "0" }
38396
38713
  });
38397
38714
  }
38398
38715
  async function createRunWorktree(opts) {
38399
- const worktreePath = (0, import_node_path3.join)(opts.worktreeRoot, opts.slug, opts.runId);
38716
+ const worktreePath = (0, import_node_path4.join)(opts.worktreeRoot, opts.slug, opts.runId);
38400
38717
  await withCheckoutLock(opts.locksDir, opts.slug, async () => {
38401
38718
  (0, import_node_fs3.mkdirSync)(opts.worktreeRoot, { recursive: true });
38402
38719
  try {
@@ -38459,8 +38776,8 @@ async function doPushRunBranch(opts, execGit) {
38459
38776
  if (localConfig.trim()) {
38460
38777
  throw new Error(`push aborted: agent-controlled git config present in worktree: ${localConfig.trim().split("\n")[0]}`);
38461
38778
  }
38462
- const dir = (0, import_node_fs3.mkdtempSync)((0, import_node_path3.join)((0, import_node_os2.tmpdir)(), "mrrlin-push-"));
38463
- const askpass = (0, import_node_path3.join)(dir, "askpass");
38779
+ const dir = (0, import_node_fs3.mkdtempSync)((0, import_node_path4.join)((0, import_node_os3.tmpdir)(), "mrrlin-push-"));
38780
+ const askpass = (0, import_node_path4.join)(dir, "askpass");
38464
38781
  try {
38465
38782
  (0, import_node_fs3.writeFileSync)(
38466
38783
  askpass,
@@ -38946,16 +39263,12 @@ async function resetWedgedThread(deps, projectSlug, taskId, interruptFailed) {
38946
39263
  });
38947
39264
  }
38948
39265
  async function failRun(deps, projectSlug, task, runId, leaseId, reason) {
39266
+ if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
38949
39267
  try {
38950
- if (!await runHasLease(deps, projectSlug, runId, leaseId)) return;
38951
- await deps.client.updateExecutionRun(projectSlug, runId, {
38952
- status: "failed",
38953
- finishedAt: (/* @__PURE__ */ new Date()).toISOString(),
38954
- leaseId
38955
- });
39268
+ await deps.client.createExecutionRunHandoff(projectSlug, runId, { reason });
38956
39269
  } catch {
39270
+ await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
38957
39271
  }
38958
- await notifyOperatorHandoff(deps, projectSlug, task, runId, reason);
38959
39272
  }
38960
39273
  async function notifyOperatorHandoff(deps, projectSlug, task, runId, reason) {
38961
39274
  try {
@@ -39261,14 +39574,14 @@ function codexIdleMs() {
39261
39574
 
39262
39575
  // src/operator-token.ts
39263
39576
  var import_node_fs4 = require("node:fs");
39264
- var import_node_os3 = __toESM(require("node:os"), 1);
39265
- var import_node_path4 = __toESM(require("node:path"), 1);
39577
+ var import_node_os4 = __toESM(require("node:os"), 1);
39578
+ var import_node_path5 = __toESM(require("node:path"), 1);
39266
39579
  function operatorDir() {
39267
- const base = process.env.CODEX_HOME ? import_node_path4.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path4.default.join(import_node_os3.default.homedir(), ".mrrlin");
39580
+ 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
39581
  return base;
39269
39582
  }
39270
39583
  function operatorTokenPath() {
39271
- return import_node_path4.default.join(operatorDir(), "operator-token");
39584
+ return import_node_path5.default.join(operatorDir(), "operator-token");
39272
39585
  }
39273
39586
  function readOperatorToken() {
39274
39587
  try {
@@ -39285,7 +39598,7 @@ function persistOperatorToken(token) {
39285
39598
  `, { encoding: "utf8", mode: 384 });
39286
39599
  }
39287
39600
  function agentCredentialPath() {
39288
- return import_node_path4.default.join(operatorDir(), "agent-credential");
39601
+ return import_node_path5.default.join(operatorDir(), "agent-credential");
39289
39602
  }
39290
39603
  function persistAgentSecret(secret) {
39291
39604
  const dir = operatorDir();
@@ -39306,9 +39619,9 @@ function readAgentSecret() {
39306
39619
 
39307
39620
  // src/thread-index.ts
39308
39621
  var import_node_fs5 = require("node:fs");
39309
- var import_node_path5 = __toESM(require("node:path"), 1);
39622
+ var import_node_path6 = __toESM(require("node:path"), 1);
39310
39623
  function threadIndexPath(stateDir) {
39311
- return import_node_path5.default.join(stateDir, "threads.json");
39624
+ return import_node_path6.default.join(stateDir, "threads.json");
39312
39625
  }
39313
39626
  function loadThreadIndex(stateDir, ttlMs, now) {
39314
39627
  const result = /* @__PURE__ */ new Map();
@@ -39393,8 +39706,8 @@ function chatTurnMaxMs() {
39393
39706
  // src/worker-token.ts
39394
39707
  var import_node_crypto4 = require("node:crypto");
39395
39708
  var import_node_fs6 = require("node:fs");
39396
- var import_node_os4 = __toESM(require("node:os"), 1);
39397
- var import_node_path6 = __toESM(require("node:path"), 1);
39709
+ var import_node_os5 = __toESM(require("node:os"), 1);
39710
+ var import_node_path7 = __toESM(require("node:path"), 1);
39398
39711
  var DEFAULT_WORKER_PORT = 8792;
39399
39712
  function workerPort() {
39400
39713
  const raw = process.env.MRRLIN_WORKER_PORT;
@@ -39403,11 +39716,11 @@ function workerPort() {
39403
39716
  return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_WORKER_PORT;
39404
39717
  }
39405
39718
  function workerDir() {
39406
- const base = process.env.CODEX_HOME ? import_node_path6.default.join(process.env.CODEX_HOME, "mrrlin") : import_node_path6.default.join(import_node_os4.default.homedir(), ".mrrlin");
39407
- return import_node_path6.default.join(base, "worker");
39719
+ 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");
39720
+ return import_node_path7.default.join(base, "worker");
39408
39721
  }
39409
39722
  function workerTokenPath() {
39410
- return import_node_path6.default.join(workerDir(), "token");
39723
+ return import_node_path7.default.join(workerDir(), "token");
39411
39724
  }
39412
39725
  function readWorkerToken() {
39413
39726
  try {
@@ -39431,8 +39744,8 @@ function readOrCreateWorkerToken() {
39431
39744
  // src/remote-phone-relay.ts
39432
39745
  var import_node_events2 = require("node:events");
39433
39746
  var import_node_fs7 = require("node:fs");
39434
- var import_node_os5 = require("node:os");
39435
- var import_node_path7 = require("node:path");
39747
+ var import_node_os6 = require("node:os");
39748
+ var import_node_path8 = require("node:path");
39436
39749
 
39437
39750
  // ../../node_modules/.pnpm/@noble+hashes@1.3.3/node_modules/@noble/hashes/esm/cryptoNode.js
39438
39751
  var nc = __toESM(require("node:crypto"), 1);
@@ -42999,9 +43312,9 @@ var DirectorRelay = class {
42999
43312
 
43000
43313
  // src/remote-phone-relay.ts
43001
43314
  function loadOrCreateAgentDeviceKey() {
43002
- const path15 = (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin", "agent-device-key");
43315
+ const path16 = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-device-key");
43003
43316
  try {
43004
- const raw = JSON.parse((0, import_node_fs7.readFileSync)(path15, "utf8"));
43317
+ const raw = JSON.parse((0, import_node_fs7.readFileSync)(path16, "utf8"));
43005
43318
  if (typeof raw.priv === "string" && typeof raw.pub === "string") {
43006
43319
  return { privateKey: fromBase64Url(raw.priv), publicKey: fromBase64Url(raw.pub) };
43007
43320
  }
@@ -43009,9 +43322,9 @@ function loadOrCreateAgentDeviceKey() {
43009
43322
  }
43010
43323
  const kp = generateIdentityKeyPair();
43011
43324
  try {
43012
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin"), { recursive: true });
43325
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
43013
43326
  (0, import_node_fs7.writeFileSync)(
43014
- path15,
43327
+ path16,
43015
43328
  JSON.stringify({ priv: toBase64Url(kp.privateKey), pub: toBase64Url(kp.publicKey) }),
43016
43329
  { mode: 384 }
43017
43330
  );
@@ -43019,7 +43332,7 @@ function loadOrCreateAgentDeviceKey() {
43019
43332
  }
43020
43333
  return kp;
43021
43334
  }
43022
- var AGENT_PAIRING_PATH = (0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin", "agent-pairing.json");
43335
+ var AGENT_PAIRING_PATH = (0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin", "agent-pairing.json");
43023
43336
  function loadAgentPairing() {
43024
43337
  try {
43025
43338
  const raw = JSON.parse((0, import_node_fs7.readFileSync)(AGENT_PAIRING_PATH, "utf8"));
@@ -43037,7 +43350,7 @@ function loadAgentPairing() {
43037
43350
  }
43038
43351
  function saveAgentPairing(record2) {
43039
43352
  try {
43040
- (0, import_node_fs7.mkdirSync)((0, import_node_path7.join)((0, import_node_os5.homedir)(), ".mrrlin"), { recursive: true });
43353
+ (0, import_node_fs7.mkdirSync)((0, import_node_path8.join)((0, import_node_os6.homedir)(), ".mrrlin"), { recursive: true });
43041
43354
  (0, import_node_fs7.writeFileSync)(AGENT_PAIRING_PATH, JSON.stringify(record2), { mode: 384 });
43042
43355
  } catch {
43043
43356
  }
@@ -43208,11 +43521,11 @@ async function renderPairingQrSvg(payload) {
43208
43521
 
43209
43522
  // src/checkout-registry.ts
43210
43523
  var import_node_fs8 = require("node:fs");
43211
- var import_node_path8 = require("node:path");
43524
+ var import_node_path9 = require("node:path");
43212
43525
  var CheckoutRegistry = class {
43213
43526
  file;
43214
43527
  constructor(stateDir) {
43215
- this.file = (0, import_node_path8.join)(stateDir, "checkouts.json");
43528
+ this.file = (0, import_node_path9.join)(stateDir, "checkouts.json");
43216
43529
  (0, import_node_fs8.mkdirSync)(stateDir, { recursive: true });
43217
43530
  }
43218
43531
  read() {
@@ -43226,17 +43539,17 @@ var CheckoutRegistry = class {
43226
43539
  get(slug) {
43227
43540
  return this.read()[slug] ?? null;
43228
43541
  }
43229
- confirm(slug, path15, now) {
43542
+ confirm(slug, path16, now) {
43230
43543
  const all = this.read();
43231
- all[slug] = { path: path15, confirmedAt: now };
43544
+ all[slug] = { path: path16, confirmedAt: now };
43232
43545
  (0, import_node_fs8.writeFileSync)(this.file, JSON.stringify(all, null, 2));
43233
43546
  }
43234
43547
  };
43235
43548
 
43236
43549
  // src/executor-server.ts
43237
43550
  var import_node_fs9 = require("node:fs");
43238
- var import_node_os6 = require("node:os");
43239
- var import_node_path9 = require("node:path");
43551
+ var import_node_os7 = require("node:os");
43552
+ var import_node_path10 = require("node:path");
43240
43553
  var DENY_READ_GLOBS = [
43241
43554
  "**/.ssh/**",
43242
43555
  "**/.aws/**",
@@ -43267,17 +43580,17 @@ function buildExecutorConfig(opts) {
43267
43580
  trustWorktreeConfig: false
43268
43581
  };
43269
43582
  }
43270
- function operatorSecretPaths(realHome = (0, import_node_os6.homedir)()) {
43583
+ function operatorSecretPaths(realHome = (0, import_node_os7.homedir)()) {
43271
43584
  return [
43272
- (0, import_node_path9.join)(realHome, ".ssh"),
43273
- (0, import_node_path9.join)(realHome, ".aws"),
43274
- (0, import_node_path9.join)(realHome, ".config", "gh"),
43275
- (0, import_node_path9.join)(realHome, ".npmrc"),
43276
- (0, import_node_path9.join)(realHome, ".netrc"),
43277
- (0, import_node_path9.join)(realHome, ".gnupg"),
43278
- (0, import_node_path9.join)(realHome, ".kube"),
43279
- (0, import_node_path9.join)(realHome, ".docker", "config.json"),
43280
- (0, import_node_path9.join)(realHome, ".config", "gcloud")
43585
+ (0, import_node_path10.join)(realHome, ".ssh"),
43586
+ (0, import_node_path10.join)(realHome, ".aws"),
43587
+ (0, import_node_path10.join)(realHome, ".config", "gh"),
43588
+ (0, import_node_path10.join)(realHome, ".npmrc"),
43589
+ (0, import_node_path10.join)(realHome, ".netrc"),
43590
+ (0, import_node_path10.join)(realHome, ".gnupg"),
43591
+ (0, import_node_path10.join)(realHome, ".kube"),
43592
+ (0, import_node_path10.join)(realHome, ".docker", "config.json"),
43593
+ (0, import_node_path10.join)(realHome, ".config", "gcloud")
43281
43594
  ];
43282
43595
  }
43283
43596
  var SECRET_DIRECTORY_BASENAMES = /* @__PURE__ */ new Set([".ssh", ".aws", "gh", ".gnupg", ".kube", "gcloud"]);
@@ -43286,7 +43599,7 @@ function isSecretDirectoryPath(p) {
43286
43599
  return SECRET_DIRECTORY_BASENAMES.has(base);
43287
43600
  }
43288
43601
  function writeExecutorCodexHome(scratchDir, opts) {
43289
- const codexHome = (0, import_node_path9.join)(scratchDir, ".codex");
43602
+ const codexHome = (0, import_node_path10.join)(scratchDir, ".codex");
43290
43603
  (0, import_node_fs9.mkdirSync)(codexHome, { recursive: true });
43291
43604
  const hasEgress = opts.egressDomains.length > 0;
43292
43605
  const networkSection = hasEgress ? [
@@ -43322,14 +43635,14 @@ function writeExecutorCodexHome(scratchDir, opts) {
43322
43635
  networkSection,
43323
43636
  ""
43324
43637
  ].join("\n");
43325
- (0, import_node_fs9.writeFileSync)((0, import_node_path9.join)(codexHome, "config.toml"), toml3, "utf8");
43638
+ (0, import_node_fs9.writeFileSync)((0, import_node_path10.join)(codexHome, "config.toml"), toml3, "utf8");
43326
43639
  return codexHome;
43327
43640
  }
43328
43641
  async function startExecutorServer(opts) {
43329
43642
  const egressDomains = opts.egressDomains ?? DEFAULT_EGRESS_DOMAINS;
43330
- const realHome = (0, import_node_os6.homedir)();
43643
+ const realHome = (0, import_node_os7.homedir)();
43331
43644
  const denySecretPaths = operatorSecretPaths(realHome);
43332
- const scratchDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path9.join)((0, import_node_os6.tmpdir)(), "mrrlin-executor-"));
43645
+ const scratchDir = (0, import_node_fs9.mkdtempSync)((0, import_node_path10.join)((0, import_node_os7.tmpdir)(), "mrrlin-executor-"));
43333
43646
  const scratchHome = scratchDir;
43334
43647
  let scratchCleaned = false;
43335
43648
  const cleanScratch = () => {
@@ -43528,7 +43841,7 @@ function extractVerificationSection(markdown) {
43528
43841
 
43529
43842
  // src/bridge-log.ts
43530
43843
  var import_node_fs10 = require("node:fs");
43531
- var import_node_path10 = require("node:path");
43844
+ var import_node_path11 = require("node:path");
43532
43845
 
43533
43846
  // src/redact.ts
43534
43847
  var REDACTED = "[REDACTED]";
@@ -43613,14 +43926,14 @@ function resolvePromptsEnabled(env) {
43613
43926
  }
43614
43927
  function createBridgeLogger(stateDir, env = process.env) {
43615
43928
  if (!resolveBridgeLogEnabled(env)) return NOOP_LOGGER;
43616
- const logsDir = (0, import_node_path10.join)(stateDir, "logs");
43929
+ const logsDir = (0, import_node_path11.join)(stateDir, "logs");
43617
43930
  try {
43618
43931
  (0, import_node_fs10.mkdirSync)(logsDir, { recursive: true });
43619
43932
  } catch {
43620
43933
  return NOOP_LOGGER;
43621
43934
  }
43622
43935
  const includePrompts = resolvePromptsEnabled(env);
43623
- const fileFor = () => (0, import_node_path10.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
43936
+ const fileFor = () => (0, import_node_path11.join)(logsDir, `bridge-${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}.jsonl`);
43624
43937
  const write = (dir, rec) => {
43625
43938
  try {
43626
43939
  const line = JSON.stringify({
@@ -43646,9 +43959,9 @@ function createBridgeLogger(stateDir, env = process.env) {
43646
43959
 
43647
43960
  // src/issue-report.ts
43648
43961
  var import_node_fs11 = require("node:fs");
43649
- var import_node_os7 = require("node:os");
43650
- var import_node_path11 = __toESM(require("node:path"), 1);
43651
- var import_node_child_process3 = require("node:child_process");
43962
+ var import_node_os8 = require("node:os");
43963
+ var import_node_path12 = __toESM(require("node:path"), 1);
43964
+ var import_node_child_process4 = require("node:child_process");
43652
43965
  var TELEGRAM_BOT_TOKEN = "8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A";
43653
43966
  var TELEGRAM_CHAT_ID = "-5373779177";
43654
43967
  function summarizeTranscript(entries = []) {
@@ -43683,10 +43996,10 @@ function describePayload(payload) {
43683
43996
  function resolveLogDir() {
43684
43997
  const codexHome = process.env.CODEX_HOME?.trim();
43685
43998
  if (codexHome) {
43686
- const candidate = import_node_path11.default.join(codexHome, "mrrlin", "director-bridge", "logs");
43999
+ const candidate = import_node_path12.default.join(codexHome, "mrrlin", "director-bridge", "logs");
43687
44000
  if (existsDir(candidate)) return candidate;
43688
44001
  }
43689
- const fallback = import_node_path11.default.join((0, import_node_os7.homedir)(), ".mrrlin", "director-bridge", "logs");
44002
+ const fallback = import_node_path12.default.join((0, import_node_os8.homedir)(), ".mrrlin", "director-bridge", "logs");
43690
44003
  return fallback;
43691
44004
  }
43692
44005
  function existsDir(candidate) {
@@ -43698,7 +44011,7 @@ function existsDir(candidate) {
43698
44011
  }
43699
44012
  function listRecentLogFiles(logDir) {
43700
44013
  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) => import_node_path11.default.join(logDir, name));
44014
+ 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
44015
  }
43703
44016
  function parseLogFile(file2) {
43704
44017
  const lines2 = (0, import_node_fs11.readFileSync)(file2, "utf8").split(/\r?\n/).filter(Boolean);
@@ -43844,10 +44157,10 @@ function buildIssueDraft(request, logWindow) {
43844
44157
  `- Route: ${request.urlPath?.trim() || "(unknown)"}`,
43845
44158
  `- Director session: ${request.directorSessionId?.trim() || "(none)"}`,
43846
44159
  `- @mrrlin-dev/mcp: ${PKG_VERSION}`,
43847
- `- OS: ${(0, import_node_os7.platform)()}`,
44160
+ `- OS: ${(0, import_node_os8.platform)()}`,
43848
44161
  `- Node: ${process.version}`
43849
44162
  ].join("\n");
43850
- const logLabel = logWindow.file ? import_node_path11.default.basename(logWindow.file) : "(none)";
44163
+ const logLabel = logWindow.file ? import_node_path12.default.basename(logWindow.file) : "(none)";
43851
44164
  const body = [
43852
44165
  "## Summary",
43853
44166
  `${titlePrefix(request.source)} issue report generated from local Mrrlin evidence.`,
@@ -43883,7 +44196,7 @@ function buildTelegramAnnouncement(request, draft, issueUrl) {
43883
44196
  ${issueUrl}`;
43884
44197
  }
43885
44198
  function ensureGhReady() {
43886
- const auth = (0, import_node_child_process3.spawnSync)("gh", ["auth", "status", "-h", "github.com"], { encoding: "utf8" });
44199
+ const auth = (0, import_node_child_process4.spawnSync)("gh", ["auth", "status", "-h", "github.com"], { encoding: "utf8" });
43887
44200
  if (auth.status !== 0) {
43888
44201
  const detail = (auth.stderr || auth.stdout || "gh auth status failed").trim();
43889
44202
  throw new Error(`GitHub CLI is not ready: ${detail}`);
@@ -43891,13 +44204,13 @@ function ensureGhReady() {
43891
44204
  }
43892
44205
  function createGithubIssue(draft) {
43893
44206
  ensureGhReady();
43894
- const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path11.default.join((0, import_node_os7.tmpdir)(), "mrrlin-issue-"));
43895
- const bodyFile = import_node_path11.default.join(tmpDir, "issue-body.md");
44207
+ const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-"));
44208
+ const bodyFile = import_node_path12.default.join(tmpDir, "issue-body.md");
43896
44209
  try {
43897
44210
  (0, import_node_fs11.writeFileSync)(bodyFile, draft.body, "utf8");
43898
44211
  const args = ["issue", "create", "--repo", "fnnzzz/mrrlin", "--title", draft.title, "--body-file", bodyFile];
43899
44212
  for (const label of draft.labels) args.push("--label", label);
43900
- const result = (0, import_node_child_process3.spawnSync)("gh", args, { encoding: "utf8" });
44213
+ const result = (0, import_node_child_process4.spawnSync)("gh", args, { encoding: "utf8" });
43901
44214
  if (result.status !== 0) {
43902
44215
  const detail = (result.stderr || result.stdout || "gh issue create failed").trim();
43903
44216
  throw new Error(detail);
@@ -43913,8 +44226,8 @@ function createGithubIssue(draft) {
43913
44226
  }
43914
44227
  }
43915
44228
  function sendTelegramAnnouncement(text) {
43916
- const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path11.default.join((0, import_node_os7.tmpdir)(), "mrrlin-issue-telegram-"));
43917
- const bodyFile = import_node_path11.default.join(tmpDir, "telegram-body.json");
44229
+ const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path12.default.join((0, import_node_os8.tmpdir)(), "mrrlin-issue-telegram-"));
44230
+ const bodyFile = import_node_path12.default.join(tmpDir, "telegram-body.json");
43918
44231
  try {
43919
44232
  (0, import_node_fs11.writeFileSync)(
43920
44233
  bodyFile,
@@ -43925,7 +44238,7 @@ function sendTelegramAnnouncement(text) {
43925
44238
  }),
43926
44239
  "utf8"
43927
44240
  );
43928
- const result = (0, import_node_child_process3.spawnSync)(
44241
+ const result = (0, import_node_child_process4.spawnSync)(
43929
44242
  "curl",
43930
44243
  [
43931
44244
  "-sS",
@@ -44032,7 +44345,7 @@ function normalizeIssueScreenshots(value) {
44032
44345
  return screenshots;
44033
44346
  }
44034
44347
  function neutralCheckoutCwd(stateDir) {
44035
- const dir = import_node_path12.default.join(stateDir, "no-checkout");
44348
+ const dir = import_node_path13.default.join(stateDir, "no-checkout");
44036
44349
  try {
44037
44350
  import_node_fs12.default.mkdirSync(dir, { recursive: true });
44038
44351
  } catch {
@@ -44058,6 +44371,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
44058
44371
  "- Keep behavior contracts in the spec; implementation details belong in `## Implementation Plan`.",
44059
44372
  "- Apply this format ONLY to Specs/{id} pages; do not retro-fit it onto other wiki page types.",
44060
44373
  "- 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.",
44374
+ '- 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
44375
  "",
44062
44376
  'Research playbook \u2014 when the user asks about a topic, an area, or "what do we have on X":',
44063
44377
  "- Tasks are the source of truth. Start with `list_tasks` using `q=<keyword>`; the filter is a",
@@ -44226,7 +44540,7 @@ function resolveDefaultBranch(checkoutPath) {
44226
44540
  if (!checkoutPath) return "main";
44227
44541
  const runGit = (args) => {
44228
44542
  try {
44229
- return (0, import_node_child_process4.execFileSync)("git", ["-C", checkoutPath, ...args], {
44543
+ return (0, import_node_child_process5.execFileSync)("git", ["-C", checkoutPath, ...args], {
44230
44544
  encoding: "utf8",
44231
44545
  stdio: ["ignore", "pipe", "ignore"],
44232
44546
  timeout: 15e3,
@@ -44295,8 +44609,8 @@ async function runOrphanWorktreeSweep(client, opts) {
44295
44609
  }
44296
44610
  }
44297
44611
  function readStateDir() {
44298
- if (process.env.CODEX_HOME) return import_node_path12.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
44299
- return import_node_path12.default.join(import_node_os8.default.homedir(), ".mrrlin", "director-bridge");
44612
+ if (process.env.CODEX_HOME) return import_node_path13.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
44613
+ return import_node_path13.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
44300
44614
  }
44301
44615
  function readAllowedOrigins() {
44302
44616
  const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
@@ -44384,7 +44698,7 @@ function sessionIdOf(msg) {
44384
44698
  return typeof id === "string" ? id : null;
44385
44699
  }
44386
44700
  function attachBridgeWss(server, opts) {
44387
- const { token, allowedOrigins, onReady, logger, onPaired, selfUpdate } = opts;
44701
+ const { token, allowedOrigins, onReady, logger, onPaired, bridgeInstanceId, selfUpdate } = opts;
44388
44702
  const wss = new import_websocket_server.default({ server, path: "/ws" });
44389
44703
  wss.on("connection", (socket, request) => {
44390
44704
  const origin = request.headers.origin;
@@ -44426,6 +44740,7 @@ function attachBridgeWss(server, opts) {
44426
44740
  send({
44427
44741
  type: "ready",
44428
44742
  bridgeVersion: 1,
44743
+ ...bridgeInstanceId ? { bridgeInstanceId } : {},
44429
44744
  ...selfUpdate ? {
44430
44745
  version: selfUpdate.version,
44431
44746
  binSha: selfUpdate.binSha,
@@ -44439,13 +44754,118 @@ function attachBridgeWss(server, opts) {
44439
44754
  }
44440
44755
  var TurnInterruptedError = class extends Error {
44441
44756
  };
44757
+ function attachSeqMetadata(msg, seq, turnId) {
44758
+ if (msg.type === "event" || msg.type === "rateLimits" || msg.type === "error") {
44759
+ return { ...msg, seq, turnId };
44760
+ }
44761
+ return msg;
44762
+ }
44442
44763
  function createBridgeMessageHandler(deps) {
44764
+ const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
44443
44765
  return (socket, _request, send, logCtx) => {
44444
44766
  const boundSessions = /* @__PURE__ */ new Set();
44445
44767
  socket.on("close", () => {
44446
44768
  for (const id of boundSessions) deps.unbindSessionSink?.(id, send);
44447
44769
  boundSessions.clear();
44448
44770
  });
44771
+ function logResumeRejected(sessionId, reason) {
44772
+ logCtx?.logger.logOut({
44773
+ spanId: logCtx.span.id,
44774
+ sessionId,
44775
+ type: "<resume-rejected>",
44776
+ payload: { sessionId, reason }
44777
+ });
44778
+ }
44779
+ function handleResumeRequest(req, sendMsg) {
44780
+ if (req.lastSeenBridgeInstanceId !== deps.bridgeInstanceId) {
44781
+ sendMsg({ type: "resume", status: "no-buffer", reason: "bridge-restarted" });
44782
+ logResumeRejected(req.directorSessionId, "bridge-restarted");
44783
+ return;
44784
+ }
44785
+ const t = deps.threads.get(req.directorSessionId);
44786
+ const tombstone = lookupTombstone(tombstones, req.directorSessionId);
44787
+ if (!t && !tombstone) {
44788
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
44789
+ logResumeRejected(req.directorSessionId, "wrong-session");
44790
+ return;
44791
+ }
44792
+ if (!t && tombstone) {
44793
+ const reason = tombstone.turnId === req.turnId ? "expired" : "wrong-turn";
44794
+ sendMsg({ type: "resume", status: "no-buffer", reason });
44795
+ logResumeRejected(req.directorSessionId, reason);
44796
+ return;
44797
+ }
44798
+ const buf = t?.replay ?? null;
44799
+ if (!buf) {
44800
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-session" });
44801
+ logResumeRejected(req.directorSessionId, "wrong-session");
44802
+ return;
44803
+ }
44804
+ if (buf.turnId !== req.turnId) {
44805
+ sendMsg({ type: "resume", status: "no-buffer", reason: "wrong-turn" });
44806
+ logResumeRejected(req.directorSessionId, "wrong-turn");
44807
+ return;
44808
+ }
44809
+ const epochMatch = req.epoch === buf.bindEpoch || req.epoch === buf.bindEpoch - 1;
44810
+ if (!epochMatch) {
44811
+ sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
44812
+ logResumeRejected(req.directorSessionId, "superseded");
44813
+ return;
44814
+ }
44815
+ const tail2 = eventsAfter(buf, req.lastSeq);
44816
+ if (tail2 === null) {
44817
+ sendMsg({ type: "resume", status: "no-buffer", reason: "evicted" });
44818
+ logResumeRejected(req.directorSessionId, "evicted");
44819
+ return;
44820
+ }
44821
+ const result = transition(buf.state, { kind: "resume", epochMatch: true });
44822
+ if (result.next === "invalid") {
44823
+ sendMsg({ type: "resume", status: "no-buffer", reason: "superseded" });
44824
+ return;
44825
+ }
44826
+ buf.state = result.next;
44827
+ incrementBindEpoch(buf);
44828
+ buf.replaying = true;
44829
+ deps.bindSessionSink?.(req.directorSessionId, send);
44830
+ boundSessions.add(req.directorSessionId);
44831
+ if (buf.triggerGrace) socket.once("close", buf.triggerGrace);
44832
+ const willStreamLive = result.next === "live";
44833
+ sendMsg({
44834
+ type: "resume",
44835
+ status: "replaying",
44836
+ turnId: buf.turnId,
44837
+ firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
44838
+ lastSeq: buf.lastSeq,
44839
+ spanId: buf.spanId,
44840
+ bindEpoch: buf.bindEpoch,
44841
+ eventCount: tail2.length,
44842
+ willStreamLive
44843
+ });
44844
+ for (const { msg: bufferedMsg } of tail2) sendMsg(bufferedMsg);
44845
+ for (const m of buf.outboundQueue) sendMsg(m);
44846
+ buf.outboundQueue.length = 0;
44847
+ buf.replaying = false;
44848
+ logCtx?.logger.logOut({
44849
+ spanId: logCtx.span.id,
44850
+ sessionId: req.directorSessionId,
44851
+ type: "<resume-replay>",
44852
+ payload: {
44853
+ sessionId: req.directorSessionId,
44854
+ turnId: buf.turnId,
44855
+ willStreamLive,
44856
+ firstSeq: tail2[0]?.seq ?? req.lastSeq + 1,
44857
+ lastSeq: buf.lastSeq,
44858
+ eventCount: tail2.length
44859
+ }
44860
+ });
44861
+ if (result.next === "interrupted") {
44862
+ const closed = transition("interrupted", { kind: "result_delivered_to_client" });
44863
+ if (closed.next !== "invalid") {
44864
+ buf.state = closed.next;
44865
+ buf.finishedAt = Date.now();
44866
+ }
44867
+ }
44868
+ }
44449
44869
  socket.on("message", async (data) => {
44450
44870
  const spanId = import_node_crypto5.default.randomUUID();
44451
44871
  if (logCtx) {
@@ -44532,7 +44952,11 @@ function createBridgeMessageHandler(deps) {
44532
44952
  } catch (error51) {
44533
44953
  bootstrapError = error51 instanceof Error ? error51.message : String(error51);
44534
44954
  }
44535
- sendForSpan({ type: "bootstrap", models, rateLimits, ...bootstrapError ? { error: bootstrapError } : {} });
44955
+ sendForSpan({ type: "bootstrap", models, rateLimits, ...deps.bridgeInstanceId ? { bridgeInstanceId: deps.bridgeInstanceId } : {}, ...bootstrapError ? { error: bootstrapError } : {} });
44956
+ return;
44957
+ }
44958
+ if (msg.type === "resume") {
44959
+ handleResumeRequest(msg, sendForSpan);
44536
44960
  return;
44537
44961
  }
44538
44962
  if (msg.type === "report_issue") {
@@ -44590,6 +45014,15 @@ function createBridgeMessageHandler(deps) {
44590
45014
  sendForSpan({ type: "error", directorSessionId: directorSessionId2, error: "No active Director session to interrupt." });
44591
45015
  return;
44592
45016
  }
45017
+ const interruptBuf = existing.replay;
45018
+ if (interruptBuf && interruptBuf.state === "grace") {
45019
+ const stopResult = transition("grace", { kind: "stop" });
45020
+ if (stopResult.next !== "invalid") {
45021
+ interruptBuf.state = stopResult.next;
45022
+ cancelGrace(interruptBuf);
45023
+ recordInterrupted(interruptBuf);
45024
+ }
45025
+ }
44593
45026
  const codexClient2 = await deps.acquireCodex();
44594
45027
  try {
44595
45028
  await codexClient2.turn.interrupt({ threadId: existing.threadId });
@@ -44660,7 +45093,8 @@ function createBridgeMessageHandler(deps) {
44660
45093
  lastUsedAt: Date.now(),
44661
45094
  inFlight: false,
44662
45095
  model: desiredModel,
44663
- reasoningEffort: desiredEffort
45096
+ reasoningEffort: desiredEffort,
45097
+ replay: null
44664
45098
  };
44665
45099
  await acquireThread(codexClient, {
44666
45100
  threadId: null,
@@ -44710,11 +45144,52 @@ function createBridgeMessageHandler(deps) {
44710
45144
  return;
44711
45145
  }
44712
45146
  thread.inFlight = true;
45147
+ thread.replay = createReplayBuffer({
45148
+ turnId: (0, import_node_crypto5.randomUUID)(),
45149
+ spanId,
45150
+ ...deps.turnGraceMs !== void 0 ? { graceMs: deps.turnGraceMs } : {}
45151
+ });
44713
45152
  thread.lastUsedAt = Date.now();
44714
45153
  const threadId = thread.threadId;
45154
+ sendForSpan({
45155
+ type: "turn-started",
45156
+ directorSessionId,
45157
+ turnId: thread.replay.turnId
45158
+ });
44715
45159
  const mapper = thread.mapper;
44716
45160
  mapper.reset();
44717
45161
  const contextPrefix = renderContextPrefix({ ...msg.context, directorSessionId });
45162
+ const sendInTurn = (msg2) => {
45163
+ const buf = thread.replay;
45164
+ if (!buf) {
45165
+ sendForSpan(msg2);
45166
+ return;
45167
+ }
45168
+ if (isTerminalEvent(msg2) && buf.terminalDelivered) {
45169
+ logCtx?.logger.logOut({
45170
+ spanId,
45171
+ sessionId: directorSessionId,
45172
+ type: "<terminal-event-dropped>",
45173
+ payload: { sessionId: directorSessionId, terminalAlreadyDelivered: true }
45174
+ });
45175
+ return;
45176
+ }
45177
+ const recorded = recordOutgoing(buf, msg2);
45178
+ if (isTerminalEvent(msg2)) buf.terminalDelivered = true;
45179
+ const tagged = attachSeqMetadata(recorded.msg, recorded.seq, buf.turnId);
45180
+ if (buf.replaying) {
45181
+ buf.outboundQueue.push(tagged);
45182
+ return;
45183
+ }
45184
+ const liveSink = deps.getSessionSink?.(directorSessionId);
45185
+ if (liveSink) {
45186
+ liveSink(tagged);
45187
+ return;
45188
+ }
45189
+ if (socket.readyState === socket.OPEN) {
45190
+ sendForSpan(tagged);
45191
+ }
45192
+ };
44718
45193
  try {
44719
45194
  await deps.runExclusive(async () => {
44720
45195
  let resolveTurn = null;
@@ -44734,13 +45209,13 @@ function createBridgeMessageHandler(deps) {
44734
45209
  return;
44735
45210
  }
44736
45211
  outputEvents += 1;
44737
- sendForSpan({ type: "event", directorSessionId, event });
45212
+ sendInTurn({ type: "event", directorSessionId, event });
44738
45213
  };
44739
45214
  const unsub = codexClient.onNotification((method, params) => {
44740
45215
  pokeActivity();
44741
45216
  if (method === "account/rateLimits/updated") {
44742
45217
  const snapshot = params?.rateLimits ?? null;
44743
- if (snapshot) sendForSpan({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
45218
+ if (snapshot) sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
44744
45219
  }
44745
45220
  const events = mapper.mapNotification({ method, params }, threadId);
44746
45221
  for (const event of events) {
@@ -44778,15 +45253,41 @@ function createBridgeMessageHandler(deps) {
44778
45253
  }
44779
45254
  });
44780
45255
  const onSocketClose = () => {
44781
- rejectWatchdog?.(new TurnInterruptedError());
44782
- void withTimeout(codexClient.turn.interrupt({ threadId }), DEFAULT_TURN_INTERRUPT_TIMEOUT_MS, "interrupt timed out").catch(
44783
- () => {
45256
+ const buf = thread.replay;
45257
+ if (!buf || buf.state !== "live") return;
45258
+ const r = transition("live", { kind: "socket_close" });
45259
+ if (r.next === "invalid") return;
45260
+ buf.state = r.next;
45261
+ logCtx?.logger.logOut({
45262
+ spanId,
45263
+ sessionId: directorSessionId,
45264
+ type: "<resume-grace-started>",
45265
+ payload: { sessionId: directorSessionId, turnId: buf.turnId, graceMs: buf.graceMs }
45266
+ });
45267
+ enterGrace(buf, () => {
45268
+ const expired = transition("grace", { kind: "grace_expire" });
45269
+ if (expired.next === "invalid") return;
45270
+ buf.state = expired.next;
45271
+ recordInterrupted(buf);
45272
+ logCtx?.logger.logOut({
45273
+ spanId,
45274
+ sessionId: directorSessionId,
45275
+ type: "<grace-expired>",
45276
+ payload: { sessionId: directorSessionId, turnId: buf.turnId, lastSeq: buf.lastSeq }
45277
+ });
45278
+ rejectWatchdog?.(new TurnInterruptedError());
45279
+ void withTimeout(
45280
+ codexClient.turn.interrupt({ threadId }),
45281
+ DEFAULT_TURN_INTERRUPT_TIMEOUT_MS,
45282
+ "interrupt timed out"
45283
+ ).catch(() => {
44784
45284
  deps.threads.delete(directorSessionId);
44785
45285
  deps.persistThreads();
44786
- }
44787
- );
45286
+ });
45287
+ });
44788
45288
  };
44789
45289
  socket.once("close", onSocketClose);
45290
+ if (thread.replay) thread.replay.triggerGrace = onSocketClose;
44790
45291
  pokeActivity = () => watchdog.poke();
44791
45292
  const runSequence = (async () => {
44792
45293
  const turnInput = [];
@@ -44821,16 +45322,19 @@ ${effectiveText}` : effectiveText;
44821
45322
  forward(event);
44822
45323
  }
44823
45324
  if (outputEvents === 0) {
44824
- sendForSpan({
45325
+ sendInTurn({
44825
45326
  type: "error",
44826
45327
  directorSessionId,
44827
45328
  error: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan."
44828
45329
  });
44829
45330
  }
44830
45331
  for (const event of deferredResults) {
44831
- sendForSpan({ type: "event", directorSessionId, event });
45332
+ sendInTurn({ type: "event", directorSessionId, event });
44832
45333
  }
44833
45334
  } finally {
45335
+ if (thread.replay && thread.replay.state === "live") {
45336
+ markCompleted(thread.replay, Date.now());
45337
+ }
44834
45338
  socket.off("close", onSocketClose);
44835
45339
  watchdog.cancel();
44836
45340
  unsub();
@@ -44839,7 +45343,7 @@ ${effectiveText}` : effectiveText;
44839
45343
  });
44840
45344
  } catch (error51) {
44841
45345
  if (!(error51 instanceof TurnInterruptedError)) {
44842
- sendForSpan({ type: "error", directorSessionId, error: error51 instanceof Error ? error51.message : String(error51) });
45346
+ sendInTurn({ type: "error", directorSessionId, error: error51 instanceof Error ? error51.message : String(error51) });
44843
45347
  const msg2 = error51 instanceof Error ? error51.message : String(error51);
44844
45348
  if (/unauthor|not logged in|login|401|auth/i.test(msg2)) {
44845
45349
  deps.setCodexAuth?.("expired");
@@ -44886,7 +45390,7 @@ function parseConfig() {
44886
45390
  }
44887
45391
  function scanForOtherBridges() {
44888
45392
  try {
44889
- const result = (0, import_node_child_process4.spawnSync)("pgrep", ["-f", "mrrlin-mcp director-bridge"], {
45393
+ const result = (0, import_node_child_process5.spawnSync)("pgrep", ["-f", "mrrlin-mcp director-bridge"], {
44890
45394
  encoding: "utf8"
44891
45395
  });
44892
45396
  if (result.status !== 0) return [];
@@ -45018,8 +45522,8 @@ async function startDirectorBridge() {
45018
45522
  codexCwd: config2.codexCwd,
45019
45523
  codexExecutable: config2.codexExecutable,
45020
45524
  checkoutRegistry,
45021
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
45022
- locksDir: import_node_path12.default.join(config2.stateDir, "locks"),
45525
+ worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
45526
+ locksDir: import_node_path13.default.join(config2.stateDir, "locks"),
45023
45527
  // Wire the profile-enforced executor server for code-execution runs. Each run gets its own
45024
45528
  // sandboxed Codex instance (scrubbed env, scratch CODEX_HOME, deny-read, egress allowlist).
45025
45529
  // The returned handle's dispose() shuts down the spawned app-server CHILD (manager.shutdown(),
@@ -45052,7 +45556,7 @@ async function startDirectorBridge() {
45052
45556
  },
45053
45557
  runVerificationTurn: createRunVerificationTurn({
45054
45558
  startSandbox: async (egressDomains) => {
45055
- const cwd = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os8.default.tmpdir(), "mrrlin-verify-"));
45559
+ const cwd = import_node_fs12.default.mkdtempSync(import_node_path13.default.join(import_node_os9.default.tmpdir(), "mrrlin-verify-"));
45056
45560
  let handle;
45057
45561
  try {
45058
45562
  handle = await startExecutorServer({ worktree: cwd, egressDomains });
@@ -45081,6 +45585,8 @@ async function startDirectorBridge() {
45081
45585
  }
45082
45586
  };
45083
45587
  const sessionSinks = createSessionSinkRegistry();
45588
+ const tombstones = /* @__PURE__ */ new Map();
45589
+ const bridgeInstanceId = (0, import_node_crypto5.randomUUID)();
45084
45590
  const asyncConsumerDeps = {
45085
45591
  client,
45086
45592
  runExclusive: wrappedTurnLock.runExclusive,
@@ -45140,7 +45646,8 @@ async function startDirectorBridge() {
45140
45646
  lastUsedAt: entry.lastUsedAt,
45141
45647
  inFlight: false,
45142
45648
  model: entry.model,
45143
- reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort)
45649
+ reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort),
45650
+ replay: null
45144
45651
  });
45145
45652
  }
45146
45653
  const persistThreads = () => {
@@ -45200,6 +45707,7 @@ async function startDirectorBridge() {
45200
45707
  unbindSessionSink: (directorSessionId, send) => {
45201
45708
  sessionSinks.unbind(directorSessionId, send);
45202
45709
  },
45710
+ getSessionSink: (directorSessionId) => sessionSinks.get(directorSessionId),
45203
45711
  maybeUpdateOffer: () => selfUpdateHandle.maybeUpdateOffer()
45204
45712
  };
45205
45713
  const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
@@ -45211,9 +45719,10 @@ async function startDirectorBridge() {
45211
45719
  attachBridgeWss(server, {
45212
45720
  token: config2.token,
45213
45721
  allowedOrigins: config2.allowedOrigins,
45214
- onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads }),
45722
+ onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads, bridgeInstanceId, tombstones }),
45215
45723
  logger: bridgeLogger,
45216
45724
  onPaired: () => health.setPaired(true),
45725
+ bridgeInstanceId,
45217
45726
  selfUpdate: {
45218
45727
  version: PKG_VERSION,
45219
45728
  binSha: bridgeBinShaShort,
@@ -45313,10 +45822,36 @@ async function startDirectorBridge() {
45313
45822
  enqueueRun(
45314
45823
  () => runOrphanWorktreeSweep(client, {
45315
45824
  checkoutRegistry,
45316
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
45317
- locksDir: import_node_path12.default.join(config2.stateDir, "locks")
45825
+ worktreeRoot: import_node_path13.default.join(config2.stateDir, "worktrees"),
45826
+ locksDir: import_node_path13.default.join(config2.stateDir, "locks")
45318
45827
  })
45319
45828
  );
45829
+ enqueueRun(async () => {
45830
+ const now = Date.now();
45831
+ for (const [sid, t] of threads) {
45832
+ if (t.replay && shouldGc(t.replay, now)) {
45833
+ const turnId = t.replay.turnId;
45834
+ const lastSeq = t.replay.lastSeq;
45835
+ writeTombstone(tombstones, sid, t.replay, now);
45836
+ bridgeLogger.logOut({
45837
+ spanId: "gc",
45838
+ sessionId: sid,
45839
+ type: "<tombstone-written>",
45840
+ payload: { sessionId: sid, turnId, lastSeq }
45841
+ });
45842
+ t.replay = null;
45843
+ }
45844
+ }
45845
+ const removed = sweepExpiredTombstones(tombstones, now);
45846
+ if (removed > 0) {
45847
+ bridgeLogger.logOut({
45848
+ spanId: "gc",
45849
+ sessionId: null,
45850
+ type: "<tombstone-expired>",
45851
+ payload: { removed }
45852
+ });
45853
+ }
45854
+ });
45320
45855
  scheduleClaimLoop();
45321
45856
  }, claimIntervalMs());
45322
45857
  claimTimer.unref?.();
@@ -45500,7 +46035,7 @@ function readDispatchBody(req) {
45500
46035
  function readOrCreateBridgeToken(stateDir) {
45501
46036
  const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
45502
46037
  if (explicit) return explicit;
45503
- const tokenPath = import_node_path12.default.join(stateDir, "token.txt");
46038
+ const tokenPath = import_node_path13.default.join(stateDir, "token.txt");
45504
46039
  try {
45505
46040
  const existing = import_node_fs12.default.readFileSync(tokenPath, "utf8").trim();
45506
46041
  if (existing) return existing;
@@ -48892,16 +49427,16 @@ var StdioServerTransport = class {
48892
49427
  // src/tools.ts
48893
49428
  var import_promises3 = require("node:fs/promises");
48894
49429
  var import_node_fs14 = require("node:fs");
48895
- var import_node_path15 = __toESM(require("node:path"), 1);
48896
- var import_node_os9 = __toESM(require("node:os"), 1);
48897
- var import_node_child_process7 = require("node:child_process");
49430
+ var import_node_path16 = __toESM(require("node:path"), 1);
49431
+ var import_node_os10 = __toESM(require("node:os"), 1);
49432
+ var import_node_child_process8 = require("node:child_process");
48898
49433
 
48899
49434
  // ../../packages/wiki/dist/index.js
48900
49435
  var import_promises2 = __toESM(require("node:fs/promises"), 1);
48901
- var import_node_path13 = __toESM(require("node:path"), 1);
49436
+ var import_node_path14 = __toESM(require("node:path"), 1);
48902
49437
  var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
48903
49438
  function toPosixPath(input) {
48904
- return input.split(import_node_path13.default.sep).join("/");
49439
+ return input.split(import_node_path14.default.sep).join("/");
48905
49440
  }
48906
49441
  function slugifyWikiSegment(input) {
48907
49442
  return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -48915,12 +49450,12 @@ async function pathExists2(input) {
48915
49450
  }
48916
49451
  }
48917
49452
  async function findWorkspaceRoot(start = process.cwd()) {
48918
- let current = import_node_path13.default.resolve(start);
49453
+ let current = import_node_path14.default.resolve(start);
48919
49454
  while (true) {
48920
- if (await pathExists2(import_node_path13.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path13.default.join(current, "docs"))) {
49455
+ if (await pathExists2(import_node_path14.default.join(current, "pnpm-workspace.yaml")) && await pathExists2(import_node_path14.default.join(current, "docs"))) {
48921
49456
  return current;
48922
49457
  }
48923
- const parent = import_node_path13.default.dirname(current);
49458
+ const parent = import_node_path14.default.dirname(current);
48924
49459
  if (parent === current) {
48925
49460
  throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
48926
49461
  }
@@ -48929,28 +49464,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
48929
49464
  }
48930
49465
  async function resolveDocsRoot(input) {
48931
49466
  if (input) {
48932
- return import_node_path13.default.resolve(input);
49467
+ return import_node_path14.default.resolve(input);
48933
49468
  }
48934
49469
  if (process.env.MRRLIN_DOCS_ROOT) {
48935
- return import_node_path13.default.resolve(process.env.MRRLIN_DOCS_ROOT);
49470
+ return import_node_path14.default.resolve(process.env.MRRLIN_DOCS_ROOT);
48936
49471
  }
48937
- return import_node_path13.default.join(await findWorkspaceRoot(), "docs");
49472
+ return import_node_path14.default.join(await findWorkspaceRoot(), "docs");
48938
49473
  }
48939
49474
  async function resolveIndexPath(input) {
48940
49475
  if (input) {
48941
- return import_node_path13.default.resolve(input);
49476
+ return import_node_path14.default.resolve(input);
48942
49477
  }
48943
49478
  if (process.env.MRRLIN_WIKI_INDEX_PATH) {
48944
- return import_node_path13.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
49479
+ return import_node_path14.default.resolve(process.env.MRRLIN_WIKI_INDEX_PATH);
48945
49480
  }
48946
49481
  const workspaceRoot = await findWorkspaceRoot();
48947
- return import_node_path13.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
49482
+ return import_node_path14.default.join(workspaceRoot, "apps", "web", "public", "wiki-index.json");
48948
49483
  }
48949
49484
  async function walkMarkdownFiles(root, dir = root) {
48950
49485
  const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
48951
49486
  const files = [];
48952
49487
  for (const entry of entries) {
48953
- const absolute = import_node_path13.default.join(dir, entry.name);
49488
+ const absolute = import_node_path14.default.join(dir, entry.name);
48954
49489
  if (entry.isDirectory()) {
48955
49490
  files.push(...await walkMarkdownFiles(root, absolute));
48956
49491
  continue;
@@ -48969,7 +49504,7 @@ function parseTitle(markdown, sourcePath) {
48969
49504
  return title;
48970
49505
  }
48971
49506
  function documentFromFile(docsRoot, absolutePath, markdown) {
48972
- const relativePath = toPosixPath(import_node_path13.default.relative(docsRoot, absolutePath));
49507
+ const relativePath = toPosixPath(import_node_path14.default.relative(docsRoot, absolutePath));
48973
49508
  const [section, fileName] = relativePath.split("/");
48974
49509
  if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
48975
49510
  return null;
@@ -49384,7 +49919,7 @@ async function runCodeGate(_target, deps) {
49384
49919
  }
49385
49920
 
49386
49921
  // src/consensus/codex-exec.ts
49387
- var import_node_child_process5 = require("node:child_process");
49922
+ var import_node_child_process6 = require("node:child_process");
49388
49923
  function extractFinalMessage(stdout) {
49389
49924
  let last = null;
49390
49925
  for (const rawLine of stdout.split(/\r?\n/)) {
@@ -49429,7 +49964,7 @@ function firstString(...values) {
49429
49964
  return null;
49430
49965
  }
49431
49966
  function runCodexExec(input, deps) {
49432
- const spawn2 = deps?.spawn ?? import_node_child_process5.spawn;
49967
+ const spawn2 = deps?.spawn ?? import_node_child_process6.spawn;
49433
49968
  const executable = input.codexExecutable ?? "codex";
49434
49969
  const sandbox = input.sandbox ?? "read-only";
49435
49970
  const fullPrompt = input.developerInstructions.trim() ? `${input.developerInstructions.trim()}
@@ -49502,11 +50037,11 @@ function errMessage(err) {
49502
50037
 
49503
50038
  // src/consensus/wiring.ts
49504
50039
  var import_node_fs13 = __toESM(require("node:fs"), 1);
49505
- var import_node_path14 = __toESM(require("node:path"), 1);
49506
- var import_node_url = require("node:url");
50040
+ var import_node_path15 = __toESM(require("node:path"), 1);
50041
+ var import_node_url2 = require("node:url");
49507
50042
 
49508
50043
  // src/consensus/code-gate-git.ts
49509
- var import_node_child_process6 = require("node:child_process");
50044
+ var import_node_child_process7 = require("node:child_process");
49510
50045
  var DIFF_MAX_BYTES = 2e5;
49511
50046
  var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
49512
50047
  var GIT_TIMEOUT_MS = 6e4;
@@ -49522,7 +50057,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
49522
50057
  };
49523
50058
  let child;
49524
50059
  try {
49525
- child = (0, import_node_child_process6.spawn)(cmd, args, {
50060
+ child = (0, import_node_child_process7.spawn)(cmd, args, {
49526
50061
  cwd: opts.cwd,
49527
50062
  env: process.env,
49528
50063
  shell: false,
@@ -49734,18 +50269,18 @@ ${res.stdout}${res.stderr}`);
49734
50269
  }
49735
50270
 
49736
50271
  // src/consensus/wiring.ts
49737
- var import_meta = {};
50272
+ var import_meta2 = {};
49738
50273
  function getPersonasDir() {
49739
50274
  if (typeof __dirname !== "undefined") {
49740
- return import_node_path14.default.join(__dirname, "consensus", "personas");
50275
+ return import_node_path15.default.join(__dirname, "consensus", "personas");
49741
50276
  }
49742
- return import_node_path14.default.join(import_node_path14.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url)), "personas");
50277
+ return import_node_path15.default.join(import_node_path15.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "personas");
49743
50278
  }
49744
50279
  var personaCache = /* @__PURE__ */ new Map();
49745
50280
  function loadPersona(name) {
49746
50281
  const cached2 = personaCache.get(name);
49747
50282
  if (cached2 !== void 0) return cached2;
49748
- const content = import_node_fs13.default.readFileSync(import_node_path14.default.join(getPersonasDir(), `${name}.md`), "utf8");
50283
+ const content = import_node_fs13.default.readFileSync(import_node_path15.default.join(getPersonasDir(), `${name}.md`), "utf8");
49749
50284
  personaCache.set(name, content);
49750
50285
  return content;
49751
50286
  }
@@ -50895,7 +51430,7 @@ var mcpToolDescriptions = {
50895
51430
  [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
51431
  [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
51432
  [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]: "Create a durable Director execution run for a task. Persists status, branch/SHA, workflow ids, and checkpoint cursor outside the chat transcript.",
51433
+ [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
51434
  [mcpToolNames.getExecutionRun]: "Fetch a single execution run by id.",
50900
51435
  [mcpToolNames.listExecutionArtifacts]: "List artifacts captured during an execution run, in chronological order.",
50901
51436
  [mcpToolNames.listExecutionRuns]: "List execution runs for a project. Optional filters: taskId, status.",
@@ -51508,7 +52043,7 @@ function createMrrlinTools(options) {
51508
52043
  "ARTIFACT_FILE_UPLOAD_FAILED",
51509
52044
  "Unable to upload artifact file.",
51510
52045
  async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
51511
- const extension2 = import_node_path15.default.extname(filePath).toLowerCase();
52046
+ const extension2 = import_node_path16.default.extname(filePath).toLowerCase();
51512
52047
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
51513
52048
  if (!contentType) {
51514
52049
  throw new McpToolCodedError(
@@ -51536,7 +52071,7 @@ function createMrrlinTools(options) {
51536
52071
  "Artifact exceeds 5MB; split or summarize instead."
51537
52072
  );
51538
52073
  }
51539
- const filename = import_node_path15.default.basename(filePath);
52074
+ const filename = import_node_path16.default.basename(filePath);
51540
52075
  const created = await c.createArtifactFile(projectSlug, {
51541
52076
  class: artifactClass,
51542
52077
  contentType,
@@ -51619,7 +52154,7 @@ function createMrrlinTools(options) {
51619
52154
  "Unable to register local checkout.",
51620
52155
  async (_c, { projectSlug, path: checkoutPath, repo }) => {
51621
52156
  const trimmedPath = checkoutPath.trim();
51622
- if (!import_node_path15.default.isAbsolute(trimmedPath)) {
52157
+ if (!import_node_path16.default.isAbsolute(trimmedPath)) {
51623
52158
  throw new McpToolCodedError(
51624
52159
  "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
51625
52160
  `Path must be absolute, got: ${trimmedPath}`
@@ -51636,7 +52171,7 @@ function createMrrlinTools(options) {
51636
52171
  }
51637
52172
  let remoteUrl;
51638
52173
  try {
51639
- remoteUrl = (0, import_node_child_process7.execFileSync)("git", ["-C", resolvedPath, "remote", "get-url", "origin"], {
52174
+ remoteUrl = (0, import_node_child_process8.execFileSync)("git", ["-C", resolvedPath, "remote", "get-url", "origin"], {
51640
52175
  encoding: "utf8",
51641
52176
  stdio: ["ignore", "pipe", "ignore"],
51642
52177
  timeout: 15e3,
@@ -51654,7 +52189,7 @@ function createMrrlinTools(options) {
51654
52189
  `Origin remote ${remoteUrl} does not match repo ${repo}.`
51655
52190
  );
51656
52191
  }
51657
- const stateDir = process.env.CODEX_HOME ? import_node_path15.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge") : import_node_path15.default.join(import_node_os9.default.homedir(), ".mrrlin", "director-bridge");
52192
+ 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
52193
  const registry3 = new CheckoutRegistry(stateDir);
51659
52194
  const confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
51660
52195
  registry3.confirm(projectSlug, resolvedPath, confirmedAt);
@@ -51861,13 +52396,13 @@ function runSetCredential(args) {
51861
52396
  }
51862
52397
 
51863
52398
  // src/install-service.ts
51864
- var import_node_os10 = __toESM(require("node:os"), 1);
51865
- var import_node_path17 = __toESM(require("node:path"), 1);
52399
+ var import_node_os11 = __toESM(require("node:os"), 1);
52400
+ var import_node_path18 = __toESM(require("node:path"), 1);
51866
52401
 
51867
52402
  // src/service-paths.ts
51868
- var import_node_path16 = __toESM(require("node:path"), 1);
52403
+ var import_node_path17 = __toESM(require("node:path"), 1);
51869
52404
  function isWorktreePath(p) {
51870
- const norm = import_node_path16.default.normalize(p).split(import_node_path16.default.sep).join("/");
52405
+ const norm = import_node_path17.default.normalize(p).split(import_node_path17.default.sep).join("/");
51871
52406
  return norm.includes("/.claude/worktrees/");
51872
52407
  }
51873
52408
  function resolveServiceCwd(opts) {
@@ -51921,7 +52456,7 @@ function installService(deps) {
51921
52456
  deps.log(resolved.reason);
51922
52457
  return { ok: false };
51923
52458
  }
51924
- const home = deps.env.HOME ?? import_node_os10.default.homedir();
52459
+ const home = deps.env.HOME ?? import_node_os11.default.homedir();
51925
52460
  const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
51926
52461
  if (bins.some((b) => !b)) {
51927
52462
  deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
@@ -51932,7 +52467,7 @@ function installService(deps) {
51932
52467
  return { ok: false };
51933
52468
  }
51934
52469
  const resolvedBins = bins.filter((b) => b !== null);
51935
- const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path17.default.dirname(b)))).join(":");
52470
+ const pathEnv = Array.from(new Set(resolvedBins.map((b) => import_node_path18.default.dirname(b)))).join(":");
51936
52471
  const text = renderEcosystemConfig({
51937
52472
  cwd: resolved.cwd,
51938
52473
  home,
@@ -51941,7 +52476,7 @@ function installService(deps) {
51941
52476
  staging: deps.env.MRRLIN_STAGING === "1",
51942
52477
  apiBaseUrl: deps.env.MRRLIN_API_BASE_URL?.trim() || void 0
51943
52478
  });
51944
- const ecoPath = import_node_path17.default.join(home, ".mrrlin", "ecosystem.config.cjs");
52479
+ const ecoPath = import_node_path18.default.join(home, ".mrrlin", "ecosystem.config.cjs");
51945
52480
  deps.writeFile(ecoPath, text);
51946
52481
  const start = deps.runPm2(["startOrReload", ecoPath]);
51947
52482
  if (start.code !== 0) {
@@ -51972,13 +52507,13 @@ function uninstallService(deps) {
51972
52507
 
51973
52508
  // src/uninstall-codex.ts
51974
52509
  var import_promises4 = __toESM(require("node:fs/promises"), 1);
51975
- var import_node_os11 = __toESM(require("node:os"), 1);
51976
- var import_node_path18 = __toESM(require("node:path"), 1);
52510
+ var import_node_os12 = __toESM(require("node:os"), 1);
52511
+ var import_node_path19 = __toESM(require("node:path"), 1);
51977
52512
  var toml2 = __toESM(require_toml(), 1);
51978
52513
  function resolveCodexHome2(options) {
51979
52514
  if (options.codexHome) return options.codexHome;
51980
52515
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
51981
- return import_node_path18.default.join(options.homeDir ?? import_node_os11.default.homedir(), ".codex");
52516
+ return import_node_path19.default.join(options.homeDir ?? import_node_os12.default.homedir(), ".codex");
51982
52517
  }
51983
52518
  async function pathExists3(target) {
51984
52519
  try {
@@ -51988,10 +52523,10 @@ async function pathExists3(target) {
51988
52523
  return false;
51989
52524
  }
51990
52525
  }
51991
- var MRRLIN_BLOCK_RE2 = /(^|\n)\[mcp_servers\.mrrlin(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
52526
+ var MRRLIN_BLOCK_RE = /(^|\n)\[mcp_servers\.mrrlin(?:-browser)?(?:\]|\.[^\]\n]*\])[\s\S]*?(?=\n\[|$)/g;
51992
52527
  async function uninstallCodex(options = {}) {
51993
52528
  const codexHome = resolveCodexHome2(options);
51994
- const configPath = import_node_path18.default.join(codexHome, "config.toml");
52529
+ const configPath = import_node_path19.default.join(codexHome, "config.toml");
51995
52530
  const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
51996
52531
  if (!await pathExists3(configPath)) {
51997
52532
  return { action: "missing", configPath, prompts: await removePrompts() };
@@ -52010,19 +52545,19 @@ async function uninstallCodex(options = {}) {
52010
52545
  };
52011
52546
  throw Object.assign(new Error(err.detail), err);
52012
52547
  }
52013
- if (parsed?.mcp_servers?.["mrrlin"] === void 0) {
52548
+ if (parsed?.mcp_servers?.["mrrlin"] === void 0 && parsed?.mcp_servers?.["mrrlin-browser"] === void 0) {
52014
52549
  return { action: "noop", configPath: realPath, prompts: await removePrompts() };
52015
52550
  }
52016
- const stripped = existing.replace(MRRLIN_BLOCK_RE2, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
52551
+ const stripped = existing.replace(MRRLIN_BLOCK_RE, (match) => match.startsWith("\n") ? "\n" : "").replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
52017
52552
  await import_promises4.default.writeFile(realPath, stripped, { mode: 384 });
52018
52553
  return { action: "removed", configPath: realPath, prompts: await removePrompts() };
52019
52554
  }
52020
52555
  async function uninstallPrompts(codexHome, names) {
52021
52556
  if (names.length === 0) return [];
52022
- const promptsDir2 = import_node_path18.default.join(codexHome, "prompts");
52557
+ const promptsDir2 = import_node_path19.default.join(codexHome, "prompts");
52023
52558
  const out = [];
52024
52559
  for (const name of names) {
52025
- const promptPath = import_node_path18.default.join(promptsDir2, `${name}.md`);
52560
+ const promptPath = import_node_path19.default.join(promptsDir2, `${name}.md`);
52026
52561
  try {
52027
52562
  await import_promises4.default.unlink(promptPath);
52028
52563
  out.push({ name, action: "removed", promptPath });
@@ -52040,26 +52575,26 @@ async function uninstallPrompts(codexHome, names) {
52040
52575
 
52041
52576
  // src/report-issue-prompt.ts
52042
52577
  var import_node_fs15 = __toESM(require("node:fs"), 1);
52043
- var import_node_path19 = __toESM(require("node:path"), 1);
52044
- var import_node_url2 = require("node:url");
52045
- var import_meta2 = {};
52578
+ var import_node_path20 = __toESM(require("node:path"), 1);
52579
+ var import_node_url3 = require("node:url");
52580
+ var import_meta3 = {};
52046
52581
  function promptsDir() {
52047
- if (typeof __dirname !== "undefined") return import_node_path19.default.join(__dirname, "prompts");
52048
- return import_node_path19.default.join(import_node_path19.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url)), "prompts");
52582
+ if (typeof __dirname !== "undefined") return import_node_path20.default.join(__dirname, "prompts");
52583
+ return import_node_path20.default.join(import_node_path20.default.dirname((0, import_node_url3.fileURLToPath)(import_meta3.url)), "prompts");
52049
52584
  }
52050
52585
  function readReportIssuePrompt() {
52051
- return import_node_fs15.default.readFileSync(import_node_path19.default.join(promptsDir(), "report-issue.md"), "utf8");
52586
+ return import_node_fs15.default.readFileSync(import_node_path20.default.join(promptsDir(), "report-issue.md"), "utf8");
52052
52587
  }
52053
52588
 
52054
52589
  // src/bin.ts
52055
52590
  function pm2Runner(args) {
52056
- const r = (0, import_node_child_process8.spawnSync)("pm2", args, { encoding: "utf8" });
52591
+ const r = (0, import_node_child_process9.spawnSync)("pm2", args, { encoding: "utf8" });
52057
52592
  process.stderr.write(r.stdout ?? "");
52058
52593
  process.stderr.write(r.stderr ?? "");
52059
52594
  return { code: r.status ?? 1, stdout: r.stdout ?? "" };
52060
52595
  }
52061
52596
  function whichBin(bin) {
52062
- const r = (0, import_node_child_process8.spawnSync)("which", [bin], { encoding: "utf8" });
52597
+ const r = (0, import_node_child_process9.spawnSync)("which", [bin], { encoding: "utf8" });
52063
52598
  const out = (r.stdout ?? "").trim();
52064
52599
  return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
52065
52600
  }
@@ -52072,6 +52607,18 @@ Usage:
52072
52607
  MRRLIN_API_ALLOW_REMOTE=1, or use MRRLIN_STAGING=1
52073
52608
  to target the known staging API alias.
52074
52609
 
52610
+ mrrlin-mcp install-browser Idempotently install the dedicated, pinned
52611
+ Chromium into ~/.mrrlin/browser/browsers (its own
52612
+ copy, isolated from the operator's Chrome and
52613
+ codex-chrome). Run by install-codex; safe to
52614
+ re-run. Exits non-zero on download failure.
52615
+
52616
+ mrrlin-mcp browser-serve Launch the vendored @playwright/mcp against the
52617
+ dedicated persistent profile
52618
+ (~/.mrrlin/browser/profile, headed). This is the
52619
+ command install-codex wires for the
52620
+ [mcp_servers.mrrlin-browser] block.
52621
+
52075
52622
  mrrlin-mcp install-codex Idempotently register Mrrlin in
52076
52623
  [--force] ~/.codex/config.toml (or CODEX_HOME). Adds an
52077
52624
  [--force-prompts] [mcp_servers.mrrlin] block AND drops the bundled
@@ -52205,10 +52752,33 @@ async function main() {
52205
52752
  await startStdioServer();
52206
52753
  return;
52207
52754
  }
52755
+ case "install-browser": {
52756
+ const res = await installBrowser();
52757
+ process.stderr.write(`[mrrlin-mcp install-browser] ${res.action} ${res.browsersPath}
52758
+ `);
52759
+ return;
52760
+ }
52761
+ case "browser-serve": {
52762
+ const { command: command2, args, env } = browserServeArgs();
52763
+ const r = (0, import_node_child_process9.spawnSync)(command2, args, { stdio: "inherit", env: { ...process.env, ...env } });
52764
+ process.exitCode = r.status ?? 1;
52765
+ return;
52766
+ }
52208
52767
  case "install-codex": {
52209
52768
  const force = rest.includes("--force");
52210
52769
  const forcePrompts = rest.includes("--force-prompts");
52211
52770
  const binPath = resolveSelfBinPath();
52771
+ try {
52772
+ const b = await installBrowser();
52773
+ process.stderr.write(`[mrrlin-mcp install-codex] install-browser ${b.action} ${b.browsersPath}
52774
+ `);
52775
+ } catch (error51) {
52776
+ process.stderr.write(
52777
+ `[mrrlin-mcp install-codex] install-browser FAILED \u2014 config.toml left untouched: ${error51 instanceof Error ? error51.message : String(error51)}
52778
+ `
52779
+ );
52780
+ process.exit(2);
52781
+ }
52212
52782
  const result = await installCodex({
52213
52783
  binPath,
52214
52784
  force,
@@ -52258,7 +52828,7 @@ async function main() {
52258
52828
  env: process.env,
52259
52829
  cwd: process.cwd(),
52260
52830
  writeFile: (p, c) => {
52261
- (0, import_node_fs16.mkdirSync)(import_node_path21.default.dirname(p), { recursive: true, mode: 448 });
52831
+ (0, import_node_fs16.mkdirSync)(import_node_path22.default.dirname(p), { recursive: true, mode: 448 });
52262
52832
  (0, import_node_fs16.writeFileSync)(p, c, { mode: 384 });
52263
52833
  },
52264
52834
  runPm2: pm2Runner,
@@ -52283,14 +52853,14 @@ async function main() {
52283
52853
  purgeSecret: purge,
52284
52854
  secretPath: agentCredentialPath(),
52285
52855
  tokenPath: operatorTokenPath(),
52286
- ecoPath: import_node_path21.default.join(process.env.HOME ?? (0, import_node_os12.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
52856
+ ecoPath: import_node_path22.default.join(process.env.HOME ?? (0, import_node_os13.homedir)(), ".mrrlin", "ecosystem.config.cjs"),
52287
52857
  log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
52288
52858
  `)
52289
52859
  });
52290
52860
  return;
52291
52861
  }
52292
52862
  case "uninstall": {
52293
- const home = process.env.HOME ?? (0, import_node_os12.homedir)();
52863
+ const home = process.env.HOME ?? (0, import_node_os13.homedir)();
52294
52864
  const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
52295
52865
  `);
52296
52866
  uninstallService({
@@ -52304,7 +52874,7 @@ async function main() {
52304
52874
  purgeSecret: true,
52305
52875
  secretPath: agentCredentialPath(),
52306
52876
  tokenPath: operatorTokenPath(),
52307
- ecoPath: import_node_path21.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
52877
+ ecoPath: import_node_path22.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
52308
52878
  log
52309
52879
  });
52310
52880
  let codexOk = true;
@@ -52324,7 +52894,7 @@ async function main() {
52324
52894
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
52325
52895
  }
52326
52896
  try {
52327
- (0, import_node_fs16.rmSync)(import_node_path21.default.join(home, ".mrrlin"), { recursive: true, force: true });
52897
+ (0, import_node_fs16.rmSync)(import_node_path22.default.join(home, ".mrrlin"), { recursive: true, force: true });
52328
52898
  } catch {
52329
52899
  }
52330
52900
  log("removed ~/.mrrlin");
@@ -52365,7 +52935,7 @@ ${HELP_TEXT}`);
52365
52935
  }
52366
52936
  }
52367
52937
  function resolveSelfBinPath() {
52368
- return import_node_path20.default.resolve(process.argv[1] ?? process.execPath);
52938
+ return import_node_path21.default.resolve(process.argv[1] ?? process.execPath);
52369
52939
  }
52370
52940
  main().catch((error51) => {
52371
52941
  process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}