@mrrlin-dev/mcp 0.3.1 → 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 +1115 -478
  3. package/package.json +6 -4
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.1";
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,11 @@ 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");
43965
+ var TELEGRAM_BOT_TOKEN = "8506614214:AAGyhO1phWb7ah2aN6_gAX2Co7OXNN3zb0A";
43966
+ var TELEGRAM_CHAT_ID = "-5373779177";
43652
43967
  function summarizeTranscript(entries = []) {
43653
43968
  const normalized = entries.map((entry) => ({
43654
43969
  kind: entry.kind,
@@ -43681,10 +43996,10 @@ function describePayload(payload) {
43681
43996
  function resolveLogDir() {
43682
43997
  const codexHome = process.env.CODEX_HOME?.trim();
43683
43998
  if (codexHome) {
43684
- 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");
43685
44000
  if (existsDir(candidate)) return candidate;
43686
44001
  }
43687
- 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");
43688
44003
  return fallback;
43689
44004
  }
43690
44005
  function existsDir(candidate) {
@@ -43696,7 +44011,7 @@ function existsDir(candidate) {
43696
44011
  }
43697
44012
  function listRecentLogFiles(logDir) {
43698
44013
  if (!existsDir(logDir)) return [];
43699
- 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));
43700
44015
  }
43701
44016
  function parseLogFile(file2) {
43702
44017
  const lines2 = (0, import_node_fs11.readFileSync)(file2, "utf8").split(/\r?\n/).filter(Boolean);
@@ -43824,7 +44139,10 @@ function formatLogWindow(window) {
43824
44139
  );
43825
44140
  }
43826
44141
  function titlePrefix(source) {
43827
- return source === "director-chat" ? "[Director]" : "[Web]";
44142
+ return source === "shell-menu" ? "[Web]" : "[Director]";
44143
+ }
44144
+ function plainTitle(title) {
44145
+ return title.replace(/^\[[^\]]+\]\s*/, "").trim();
43828
44146
  }
43829
44147
  function buildIssueDraft(request, logWindow) {
43830
44148
  const customerDescription = clip(redact(request.customerDescription.trim() || "(not provided)"), 4e3);
@@ -43839,10 +44157,10 @@ function buildIssueDraft(request, logWindow) {
43839
44157
  `- Route: ${request.urlPath?.trim() || "(unknown)"}`,
43840
44158
  `- Director session: ${request.directorSessionId?.trim() || "(none)"}`,
43841
44159
  `- @mrrlin-dev/mcp: ${PKG_VERSION}`,
43842
- `- OS: ${(0, import_node_os7.platform)()}`,
44160
+ `- OS: ${(0, import_node_os8.platform)()}`,
43843
44161
  `- Node: ${process.version}`
43844
44162
  ].join("\n");
43845
- 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)";
43846
44164
  const body = [
43847
44165
  "## Summary",
43848
44166
  `${titlePrefix(request.source)} issue report generated from local Mrrlin evidence.`,
@@ -43872,8 +44190,13 @@ function buildIssueDraft(request, logWindow) {
43872
44190
  ].join("\n");
43873
44191
  return { title, body, labels: ["bug"] };
43874
44192
  }
44193
+ function buildTelegramAnnouncement(request, draft, issueUrl) {
44194
+ const summary = firstSentence(redact(request.customerDescription.trim())) || firstSentence(plainTitle(draft.title)) || "\u043D\u0435\u0432\u0456\u0434\u0442\u0432\u043E\u0440\u0435\u043D\u0430 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0430";
44195
+ return `\u0437\u0430\u0440\u0435\u043F\u043E\u0440\u0447\u0435\u043D\u043E \u043D\u043E\u0432\u0438\u0439 \u0431\u0430\u0433, \u043A\u043E\u0440\u043E\u0442\u043A\u043E: ${clip(summary, 280)}
44196
+ ${issueUrl}`;
44197
+ }
43875
44198
  function ensureGhReady() {
43876
- 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" });
43877
44200
  if (auth.status !== 0) {
43878
44201
  const detail = (auth.stderr || auth.stdout || "gh auth status failed").trim();
43879
44202
  throw new Error(`GitHub CLI is not ready: ${detail}`);
@@ -43881,13 +44204,13 @@ function ensureGhReady() {
43881
44204
  }
43882
44205
  function createGithubIssue(draft) {
43883
44206
  ensureGhReady();
43884
- const tmpDir = (0, import_node_fs11.mkdtempSync)(import_node_path11.default.join((0, import_node_os7.tmpdir)(), "mrrlin-issue-"));
43885
- 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");
43886
44209
  try {
43887
44210
  (0, import_node_fs11.writeFileSync)(bodyFile, draft.body, "utf8");
43888
44211
  const args = ["issue", "create", "--repo", "fnnzzz/mrrlin", "--title", draft.title, "--body-file", bodyFile];
43889
44212
  for (const label of draft.labels) args.push("--label", label);
43890
- 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" });
43891
44214
  if (result.status !== 0) {
43892
44215
  const detail = (result.stderr || result.stdout || "gh issue create failed").trim();
43893
44216
  throw new Error(detail);
@@ -43902,11 +44225,66 @@ function createGithubIssue(draft) {
43902
44225
  (0, import_node_fs11.rmSync)(tmpDir, { recursive: true, force: true });
43903
44226
  }
43904
44227
  }
44228
+ function sendTelegramAnnouncement(text) {
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");
44231
+ try {
44232
+ (0, import_node_fs11.writeFileSync)(
44233
+ bodyFile,
44234
+ JSON.stringify({
44235
+ chat_id: TELEGRAM_CHAT_ID,
44236
+ text,
44237
+ disable_web_page_preview: true
44238
+ }),
44239
+ "utf8"
44240
+ );
44241
+ const result = (0, import_node_child_process4.spawnSync)(
44242
+ "curl",
44243
+ [
44244
+ "-sS",
44245
+ "-X",
44246
+ "POST",
44247
+ `https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage`,
44248
+ "-H",
44249
+ "Content-Type: application/json",
44250
+ "--data-binary",
44251
+ `@${bodyFile}`
44252
+ ],
44253
+ { encoding: "utf8" }
44254
+ );
44255
+ if (result.error) {
44256
+ return `Telegram announce failed: ${result.error.message}`;
44257
+ }
44258
+ if (result.status !== 0) {
44259
+ const detail = (result.stderr || result.stdout || "curl failed").trim();
44260
+ return `Telegram announce failed: ${detail}`;
44261
+ }
44262
+ let parsed = null;
44263
+ try {
44264
+ parsed = JSON.parse(result.stdout || "{}");
44265
+ } catch {
44266
+ return `Telegram announce failed: could not parse response: ${result.stdout.trim()}`;
44267
+ }
44268
+ if (!parsed?.ok) {
44269
+ return `Telegram announce failed: ${parsed?.description || "unknown Telegram error"}`;
44270
+ }
44271
+ return null;
44272
+ } finally {
44273
+ (0, import_node_fs11.rmSync)(tmpDir, { recursive: true, force: true });
44274
+ }
44275
+ }
43905
44276
  function fileIssueReport(request, opts = {}) {
43906
44277
  const logWindow = findRelevantLogWindow(request, opts);
43907
44278
  const draft = buildIssueDraft(request, logWindow);
43908
44279
  const created = createGithubIssue(draft);
43909
- return { issueNumber: created.issueNumber, title: draft.title, url: created.url };
44280
+ const telegramWarning = sendTelegramAnnouncement(buildTelegramAnnouncement(request, draft, created.url));
44281
+ return {
44282
+ issueNumber: created.issueNumber,
44283
+ title: draft.title,
44284
+ url: created.url,
44285
+ telegramDelivered: telegramWarning === null,
44286
+ telegramWarning
44287
+ };
43910
44288
  }
43911
44289
 
43912
44290
  // src/director-bridge.ts
@@ -43967,7 +44345,7 @@ function normalizeIssueScreenshots(value) {
43967
44345
  return screenshots;
43968
44346
  }
43969
44347
  function neutralCheckoutCwd(stateDir) {
43970
- const dir = import_node_path12.default.join(stateDir, "no-checkout");
44348
+ const dir = import_node_path13.default.join(stateDir, "no-checkout");
43971
44349
  try {
43972
44350
  import_node_fs12.default.mkdirSync(dir, { recursive: true });
43973
44351
  } catch {
@@ -43993,6 +44371,7 @@ function buildThreadStartParams(msg, config2, desiredModel) {
43993
44371
  "- Keep behavior contracts in the spec; implementation details belong in `## Implementation Plan`.",
43994
44372
  "- Apply this format ONLY to Specs/{id} pages; do not retro-fit it onto other wiki page types.",
43995
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.',
43996
44375
  "",
43997
44376
  'Research playbook \u2014 when the user asks about a topic, an area, or "what do we have on X":',
43998
44377
  "- Tasks are the source of truth. Start with `list_tasks` using `q=<keyword>`; the filter is a",
@@ -44161,7 +44540,7 @@ function resolveDefaultBranch(checkoutPath) {
44161
44540
  if (!checkoutPath) return "main";
44162
44541
  const runGit = (args) => {
44163
44542
  try {
44164
- return (0, import_node_child_process4.execFileSync)("git", ["-C", checkoutPath, ...args], {
44543
+ return (0, import_node_child_process5.execFileSync)("git", ["-C", checkoutPath, ...args], {
44165
44544
  encoding: "utf8",
44166
44545
  stdio: ["ignore", "pipe", "ignore"],
44167
44546
  timeout: 15e3,
@@ -44230,8 +44609,8 @@ async function runOrphanWorktreeSweep(client, opts) {
44230
44609
  }
44231
44610
  }
44232
44611
  function readStateDir() {
44233
- if (process.env.CODEX_HOME) return import_node_path12.default.join(process.env.CODEX_HOME, "mrrlin", "director-bridge");
44234
- 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");
44235
44614
  }
44236
44615
  function readAllowedOrigins() {
44237
44616
  const raw = (process.env.MRRLIN_DIRECTOR_BRIDGE_ALLOWED_ORIGINS ?? "").trim();
@@ -44319,7 +44698,7 @@ function sessionIdOf(msg) {
44319
44698
  return typeof id === "string" ? id : null;
44320
44699
  }
44321
44700
  function attachBridgeWss(server, opts) {
44322
- const { token, allowedOrigins, onReady, logger, onPaired, selfUpdate } = opts;
44701
+ const { token, allowedOrigins, onReady, logger, onPaired, bridgeInstanceId, selfUpdate } = opts;
44323
44702
  const wss = new import_websocket_server.default({ server, path: "/ws" });
44324
44703
  wss.on("connection", (socket, request) => {
44325
44704
  const origin = request.headers.origin;
@@ -44361,6 +44740,7 @@ function attachBridgeWss(server, opts) {
44361
44740
  send({
44362
44741
  type: "ready",
44363
44742
  bridgeVersion: 1,
44743
+ ...bridgeInstanceId ? { bridgeInstanceId } : {},
44364
44744
  ...selfUpdate ? {
44365
44745
  version: selfUpdate.version,
44366
44746
  binSha: selfUpdate.binSha,
@@ -44374,13 +44754,118 @@ function attachBridgeWss(server, opts) {
44374
44754
  }
44375
44755
  var TurnInterruptedError = class extends Error {
44376
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
+ }
44377
44763
  function createBridgeMessageHandler(deps) {
44764
+ const tombstones = deps.tombstones ?? /* @__PURE__ */ new Map();
44378
44765
  return (socket, _request, send, logCtx) => {
44379
44766
  const boundSessions = /* @__PURE__ */ new Set();
44380
44767
  socket.on("close", () => {
44381
44768
  for (const id of boundSessions) deps.unbindSessionSink?.(id, send);
44382
44769
  boundSessions.clear();
44383
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
+ }
44384
44869
  socket.on("message", async (data) => {
44385
44870
  const spanId = import_node_crypto5.default.randomUUID();
44386
44871
  if (logCtx) {
@@ -44467,11 +44952,15 @@ function createBridgeMessageHandler(deps) {
44467
44952
  } catch (error51) {
44468
44953
  bootstrapError = error51 instanceof Error ? error51.message : String(error51);
44469
44954
  }
44470
- 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);
44471
44960
  return;
44472
44961
  }
44473
44962
  if (msg.type === "report_issue") {
44474
- if (msg.source !== "director-chat" && msg.source !== "shell-menu") {
44963
+ if (msg.source !== "director-chat" && msg.source !== "director-panel" && msg.source !== "shell-menu") {
44475
44964
  sendForSpan({ type: "report-issue-result", status: "error", error: "report source is invalid." });
44476
44965
  return;
44477
44966
  }
@@ -44505,7 +44994,9 @@ function createBridgeMessageHandler(deps) {
44505
44994
  status: "ok",
44506
44995
  issueNumber: result.issueNumber,
44507
44996
  title: result.title,
44508
- url: result.url
44997
+ url: result.url,
44998
+ telegramDelivered: result.telegramDelivered,
44999
+ telegramWarning: result.telegramWarning
44509
45000
  });
44510
45001
  } catch (error51) {
44511
45002
  sendForSpan({
@@ -44523,6 +45014,15 @@ function createBridgeMessageHandler(deps) {
44523
45014
  sendForSpan({ type: "error", directorSessionId: directorSessionId2, error: "No active Director session to interrupt." });
44524
45015
  return;
44525
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
+ }
44526
45026
  const codexClient2 = await deps.acquireCodex();
44527
45027
  try {
44528
45028
  await codexClient2.turn.interrupt({ threadId: existing.threadId });
@@ -44593,7 +45093,8 @@ function createBridgeMessageHandler(deps) {
44593
45093
  lastUsedAt: Date.now(),
44594
45094
  inFlight: false,
44595
45095
  model: desiredModel,
44596
- reasoningEffort: desiredEffort
45096
+ reasoningEffort: desiredEffort,
45097
+ replay: null
44597
45098
  };
44598
45099
  await acquireThread(codexClient, {
44599
45100
  threadId: null,
@@ -44643,11 +45144,52 @@ function createBridgeMessageHandler(deps) {
44643
45144
  return;
44644
45145
  }
44645
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
+ });
44646
45152
  thread.lastUsedAt = Date.now();
44647
45153
  const threadId = thread.threadId;
45154
+ sendForSpan({
45155
+ type: "turn-started",
45156
+ directorSessionId,
45157
+ turnId: thread.replay.turnId
45158
+ });
44648
45159
  const mapper = thread.mapper;
44649
45160
  mapper.reset();
44650
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
+ };
44651
45193
  try {
44652
45194
  await deps.runExclusive(async () => {
44653
45195
  let resolveTurn = null;
@@ -44667,13 +45209,13 @@ function createBridgeMessageHandler(deps) {
44667
45209
  return;
44668
45210
  }
44669
45211
  outputEvents += 1;
44670
- sendForSpan({ type: "event", directorSessionId, event });
45212
+ sendInTurn({ type: "event", directorSessionId, event });
44671
45213
  };
44672
45214
  const unsub = codexClient.onNotification((method, params) => {
44673
45215
  pokeActivity();
44674
45216
  if (method === "account/rateLimits/updated") {
44675
45217
  const snapshot = params?.rateLimits ?? null;
44676
- if (snapshot) sendForSpan({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
45218
+ if (snapshot) sendInTurn({ type: "rateLimits", directorSessionId, rateLimits: snapshot });
44677
45219
  }
44678
45220
  const events = mapper.mapNotification({ method, params }, threadId);
44679
45221
  for (const event of events) {
@@ -44711,15 +45253,41 @@ function createBridgeMessageHandler(deps) {
44711
45253
  }
44712
45254
  });
44713
45255
  const onSocketClose = () => {
44714
- rejectWatchdog?.(new TurnInterruptedError());
44715
- void withTimeout(codexClient.turn.interrupt({ threadId }), DEFAULT_TURN_INTERRUPT_TIMEOUT_MS, "interrupt timed out").catch(
44716
- () => {
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(() => {
44717
45284
  deps.threads.delete(directorSessionId);
44718
45285
  deps.persistThreads();
44719
- }
44720
- );
45286
+ });
45287
+ });
44721
45288
  };
44722
45289
  socket.once("close", onSocketClose);
45290
+ if (thread.replay) thread.replay.triggerGrace = onSocketClose;
44723
45291
  pokeActivity = () => watchdog.poke();
44724
45292
  const runSequence = (async () => {
44725
45293
  const turnInput = [];
@@ -44754,16 +45322,19 @@ ${effectiveText}` : effectiveText;
44754
45322
  forward(event);
44755
45323
  }
44756
45324
  if (outputEvents === 0) {
44757
- sendForSpan({
45325
+ sendInTurn({
44758
45326
  type: "error",
44759
45327
  directorSessionId,
44760
45328
  error: "Director turn completed without any output \u2014 Codex likely hit its usage/credits limit. Check your Codex account/plan."
44761
45329
  });
44762
45330
  }
44763
45331
  for (const event of deferredResults) {
44764
- sendForSpan({ type: "event", directorSessionId, event });
45332
+ sendInTurn({ type: "event", directorSessionId, event });
44765
45333
  }
44766
45334
  } finally {
45335
+ if (thread.replay && thread.replay.state === "live") {
45336
+ markCompleted(thread.replay, Date.now());
45337
+ }
44767
45338
  socket.off("close", onSocketClose);
44768
45339
  watchdog.cancel();
44769
45340
  unsub();
@@ -44772,7 +45343,7 @@ ${effectiveText}` : effectiveText;
44772
45343
  });
44773
45344
  } catch (error51) {
44774
45345
  if (!(error51 instanceof TurnInterruptedError)) {
44775
- 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) });
44776
45347
  const msg2 = error51 instanceof Error ? error51.message : String(error51);
44777
45348
  if (/unauthor|not logged in|login|401|auth/i.test(msg2)) {
44778
45349
  deps.setCodexAuth?.("expired");
@@ -44819,7 +45390,7 @@ function parseConfig() {
44819
45390
  }
44820
45391
  function scanForOtherBridges() {
44821
45392
  try {
44822
- 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"], {
44823
45394
  encoding: "utf8"
44824
45395
  });
44825
45396
  if (result.status !== 0) return [];
@@ -44951,8 +45522,8 @@ async function startDirectorBridge() {
44951
45522
  codexCwd: config2.codexCwd,
44952
45523
  codexExecutable: config2.codexExecutable,
44953
45524
  checkoutRegistry,
44954
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
44955
- 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"),
44956
45527
  // Wire the profile-enforced executor server for code-execution runs. Each run gets its own
44957
45528
  // sandboxed Codex instance (scrubbed env, scratch CODEX_HOME, deny-read, egress allowlist).
44958
45529
  // The returned handle's dispose() shuts down the spawned app-server CHILD (manager.shutdown(),
@@ -44985,7 +45556,7 @@ async function startDirectorBridge() {
44985
45556
  },
44986
45557
  runVerificationTurn: createRunVerificationTurn({
44987
45558
  startSandbox: async (egressDomains) => {
44988
- 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-"));
44989
45560
  let handle;
44990
45561
  try {
44991
45562
  handle = await startExecutorServer({ worktree: cwd, egressDomains });
@@ -45014,6 +45585,8 @@ async function startDirectorBridge() {
45014
45585
  }
45015
45586
  };
45016
45587
  const sessionSinks = createSessionSinkRegistry();
45588
+ const tombstones = /* @__PURE__ */ new Map();
45589
+ const bridgeInstanceId = (0, import_node_crypto5.randomUUID)();
45017
45590
  const asyncConsumerDeps = {
45018
45591
  client,
45019
45592
  runExclusive: wrappedTurnLock.runExclusive,
@@ -45073,7 +45646,8 @@ async function startDirectorBridge() {
45073
45646
  lastUsedAt: entry.lastUsedAt,
45074
45647
  inFlight: false,
45075
45648
  model: entry.model,
45076
- reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort)
45649
+ reasoningEffort: normalizeReasoningEffort(entry.reasoningEffort),
45650
+ replay: null
45077
45651
  });
45078
45652
  }
45079
45653
  const persistThreads = () => {
@@ -45133,6 +45707,7 @@ async function startDirectorBridge() {
45133
45707
  unbindSessionSink: (directorSessionId, send) => {
45134
45708
  sessionSinks.unbind(directorSessionId, send);
45135
45709
  },
45710
+ getSessionSink: (directorSessionId) => sessionSinks.get(directorSessionId),
45136
45711
  maybeUpdateOffer: () => selfUpdateHandle.maybeUpdateOffer()
45137
45712
  };
45138
45713
  const bridgeLogger = createBridgeLogger(config2.stateDir, process.env);
@@ -45144,9 +45719,10 @@ async function startDirectorBridge() {
45144
45719
  attachBridgeWss(server, {
45145
45720
  token: config2.token,
45146
45721
  allowedOrigins: config2.allowedOrigins,
45147
- onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads }),
45722
+ onReady: createBridgeMessageHandler({ ...sharedHandlerDeps, threads, persistThreads, bridgeInstanceId, tombstones }),
45148
45723
  logger: bridgeLogger,
45149
45724
  onPaired: () => health.setPaired(true),
45725
+ bridgeInstanceId,
45150
45726
  selfUpdate: {
45151
45727
  version: PKG_VERSION,
45152
45728
  binSha: bridgeBinShaShort,
@@ -45246,10 +45822,36 @@ async function startDirectorBridge() {
45246
45822
  enqueueRun(
45247
45823
  () => runOrphanWorktreeSweep(client, {
45248
45824
  checkoutRegistry,
45249
- worktreeRoot: import_node_path12.default.join(config2.stateDir, "worktrees"),
45250
- 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")
45251
45827
  })
45252
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
+ });
45253
45855
  scheduleClaimLoop();
45254
45856
  }, claimIntervalMs());
45255
45857
  claimTimer.unref?.();
@@ -45433,7 +46035,7 @@ function readDispatchBody(req) {
45433
46035
  function readOrCreateBridgeToken(stateDir) {
45434
46036
  const explicit = (process.env.MRRLIN_DIRECTOR_BRIDGE_TOKEN ?? "").trim();
45435
46037
  if (explicit) return explicit;
45436
- const tokenPath = import_node_path12.default.join(stateDir, "token.txt");
46038
+ const tokenPath = import_node_path13.default.join(stateDir, "token.txt");
45437
46039
  try {
45438
46040
  const existing = import_node_fs12.default.readFileSync(tokenPath, "utf8").trim();
45439
46041
  if (existing) return existing;
@@ -48825,16 +49427,16 @@ var StdioServerTransport = class {
48825
49427
  // src/tools.ts
48826
49428
  var import_promises3 = require("node:fs/promises");
48827
49429
  var import_node_fs14 = require("node:fs");
48828
- var import_node_path15 = __toESM(require("node:path"), 1);
48829
- var import_node_os9 = __toESM(require("node:os"), 1);
48830
- 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");
48831
49433
 
48832
49434
  // ../../packages/wiki/dist/index.js
48833
49435
  var import_promises2 = __toESM(require("node:fs/promises"), 1);
48834
- var import_node_path13 = __toESM(require("node:path"), 1);
49436
+ var import_node_path14 = __toESM(require("node:path"), 1);
48835
49437
  var INCLUDED_DOC_FOLDERS = /* @__PURE__ */ new Set(["_meta", "explanation", "how-to", "reference", "sdd", "tutorials"]);
48836
49438
  function toPosixPath(input) {
48837
- return input.split(import_node_path13.default.sep).join("/");
49439
+ return input.split(import_node_path14.default.sep).join("/");
48838
49440
  }
48839
49441
  function slugifyWikiSegment(input) {
48840
49442
  return input.trim().toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -48848,12 +49450,12 @@ async function pathExists2(input) {
48848
49450
  }
48849
49451
  }
48850
49452
  async function findWorkspaceRoot(start = process.cwd()) {
48851
- let current = import_node_path13.default.resolve(start);
49453
+ let current = import_node_path14.default.resolve(start);
48852
49454
  while (true) {
48853
- 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"))) {
48854
49456
  return current;
48855
49457
  }
48856
- const parent = import_node_path13.default.dirname(current);
49458
+ const parent = import_node_path14.default.dirname(current);
48857
49459
  if (parent === current) {
48858
49460
  throw new Error(`Unable to find Mrrlin workspace root from ${start}`);
48859
49461
  }
@@ -48862,28 +49464,28 @@ async function findWorkspaceRoot(start = process.cwd()) {
48862
49464
  }
48863
49465
  async function resolveDocsRoot(input) {
48864
49466
  if (input) {
48865
- return import_node_path13.default.resolve(input);
49467
+ return import_node_path14.default.resolve(input);
48866
49468
  }
48867
49469
  if (process.env.MRRLIN_DOCS_ROOT) {
48868
- return import_node_path13.default.resolve(process.env.MRRLIN_DOCS_ROOT);
49470
+ return import_node_path14.default.resolve(process.env.MRRLIN_DOCS_ROOT);
48869
49471
  }
48870
- return import_node_path13.default.join(await findWorkspaceRoot(), "docs");
49472
+ return import_node_path14.default.join(await findWorkspaceRoot(), "docs");
48871
49473
  }
48872
49474
  async function resolveIndexPath(input) {
48873
49475
  if (input) {
48874
- return import_node_path13.default.resolve(input);
49476
+ return import_node_path14.default.resolve(input);
48875
49477
  }
48876
49478
  if (process.env.MRRLIN_WIKI_INDEX_PATH) {
48877
- 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);
48878
49480
  }
48879
49481
  const workspaceRoot = await findWorkspaceRoot();
48880
- 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");
48881
49483
  }
48882
49484
  async function walkMarkdownFiles(root, dir = root) {
48883
49485
  const entries = await import_promises2.default.readdir(dir, { withFileTypes: true });
48884
49486
  const files = [];
48885
49487
  for (const entry of entries) {
48886
- const absolute = import_node_path13.default.join(dir, entry.name);
49488
+ const absolute = import_node_path14.default.join(dir, entry.name);
48887
49489
  if (entry.isDirectory()) {
48888
49490
  files.push(...await walkMarkdownFiles(root, absolute));
48889
49491
  continue;
@@ -48902,7 +49504,7 @@ function parseTitle(markdown, sourcePath) {
48902
49504
  return title;
48903
49505
  }
48904
49506
  function documentFromFile(docsRoot, absolutePath, markdown) {
48905
- const relativePath = toPosixPath(import_node_path13.default.relative(docsRoot, absolutePath));
49507
+ const relativePath = toPosixPath(import_node_path14.default.relative(docsRoot, absolutePath));
48906
49508
  const [section, fileName] = relativePath.split("/");
48907
49509
  if (!section || !fileName || !INCLUDED_DOC_FOLDERS.has(section)) {
48908
49510
  return null;
@@ -49317,7 +49919,7 @@ async function runCodeGate(_target, deps) {
49317
49919
  }
49318
49920
 
49319
49921
  // src/consensus/codex-exec.ts
49320
- var import_node_child_process5 = require("node:child_process");
49922
+ var import_node_child_process6 = require("node:child_process");
49321
49923
  function extractFinalMessage(stdout) {
49322
49924
  let last = null;
49323
49925
  for (const rawLine of stdout.split(/\r?\n/)) {
@@ -49362,7 +49964,7 @@ function firstString(...values) {
49362
49964
  return null;
49363
49965
  }
49364
49966
  function runCodexExec(input, deps) {
49365
- const spawn2 = deps?.spawn ?? import_node_child_process5.spawn;
49967
+ const spawn2 = deps?.spawn ?? import_node_child_process6.spawn;
49366
49968
  const executable = input.codexExecutable ?? "codex";
49367
49969
  const sandbox = input.sandbox ?? "read-only";
49368
49970
  const fullPrompt = input.developerInstructions.trim() ? `${input.developerInstructions.trim()}
@@ -49435,11 +50037,11 @@ function errMessage(err) {
49435
50037
 
49436
50038
  // src/consensus/wiring.ts
49437
50039
  var import_node_fs13 = __toESM(require("node:fs"), 1);
49438
- var import_node_path14 = __toESM(require("node:path"), 1);
49439
- 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");
49440
50042
 
49441
50043
  // src/consensus/code-gate-git.ts
49442
- var import_node_child_process6 = require("node:child_process");
50044
+ var import_node_child_process7 = require("node:child_process");
49443
50045
  var DIFF_MAX_BYTES = 2e5;
49444
50046
  var FASTGATE_OUTPUT_MAX_BYTES = 16e3;
49445
50047
  var GIT_TIMEOUT_MS = 6e4;
@@ -49455,7 +50057,7 @@ var defaultRunCmd = (cmd, args, opts) => new Promise((resolve) => {
49455
50057
  };
49456
50058
  let child;
49457
50059
  try {
49458
- child = (0, import_node_child_process6.spawn)(cmd, args, {
50060
+ child = (0, import_node_child_process7.spawn)(cmd, args, {
49459
50061
  cwd: opts.cwd,
49460
50062
  env: process.env,
49461
50063
  shell: false,
@@ -49667,18 +50269,18 @@ ${res.stdout}${res.stderr}`);
49667
50269
  }
49668
50270
 
49669
50271
  // src/consensus/wiring.ts
49670
- var import_meta = {};
50272
+ var import_meta2 = {};
49671
50273
  function getPersonasDir() {
49672
50274
  if (typeof __dirname !== "undefined") {
49673
- return import_node_path14.default.join(__dirname, "consensus", "personas");
50275
+ return import_node_path15.default.join(__dirname, "consensus", "personas");
49674
50276
  }
49675
- 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");
49676
50278
  }
49677
50279
  var personaCache = /* @__PURE__ */ new Map();
49678
50280
  function loadPersona(name) {
49679
50281
  const cached2 = personaCache.get(name);
49680
50282
  if (cached2 !== void 0) return cached2;
49681
- 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");
49682
50284
  personaCache.set(name, content);
49683
50285
  return content;
49684
50286
  }
@@ -50828,7 +51430,7 @@ var mcpToolDescriptions = {
50828
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.',
50829
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).`,
50830
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.",
50831
- [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".',
50832
51434
  [mcpToolNames.getExecutionRun]: "Fetch a single execution run by id.",
50833
51435
  [mcpToolNames.listExecutionArtifacts]: "List artifacts captured during an execution run, in chronological order.",
50834
51436
  [mcpToolNames.listExecutionRuns]: "List execution runs for a project. Optional filters: taskId, status.",
@@ -51441,7 +52043,7 @@ function createMrrlinTools(options) {
51441
52043
  "ARTIFACT_FILE_UPLOAD_FAILED",
51442
52044
  "Unable to upload artifact file.",
51443
52045
  async (c, { projectSlug, path: filePath, class: artifactClass, taskId, runId, description }) => {
51444
- const extension2 = import_node_path15.default.extname(filePath).toLowerCase();
52046
+ const extension2 = import_node_path16.default.extname(filePath).toLowerCase();
51445
52047
  const contentType = ARTIFACT_EXTENSION_TYPES[extension2];
51446
52048
  if (!contentType) {
51447
52049
  throw new McpToolCodedError(
@@ -51469,7 +52071,7 @@ function createMrrlinTools(options) {
51469
52071
  "Artifact exceeds 5MB; split or summarize instead."
51470
52072
  );
51471
52073
  }
51472
- const filename = import_node_path15.default.basename(filePath);
52074
+ const filename = import_node_path16.default.basename(filePath);
51473
52075
  const created = await c.createArtifactFile(projectSlug, {
51474
52076
  class: artifactClass,
51475
52077
  contentType,
@@ -51552,7 +52154,7 @@ function createMrrlinTools(options) {
51552
52154
  "Unable to register local checkout.",
51553
52155
  async (_c, { projectSlug, path: checkoutPath, repo }) => {
51554
52156
  const trimmedPath = checkoutPath.trim();
51555
- if (!import_node_path15.default.isAbsolute(trimmedPath)) {
52157
+ if (!import_node_path16.default.isAbsolute(trimmedPath)) {
51556
52158
  throw new McpToolCodedError(
51557
52159
  "LOCAL_CHECKOUT_PATH_NOT_ABSOLUTE",
51558
52160
  `Path must be absolute, got: ${trimmedPath}`
@@ -51569,7 +52171,7 @@ function createMrrlinTools(options) {
51569
52171
  }
51570
52172
  let remoteUrl;
51571
52173
  try {
51572
- 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"], {
51573
52175
  encoding: "utf8",
51574
52176
  stdio: ["ignore", "pipe", "ignore"],
51575
52177
  timeout: 15e3,
@@ -51587,7 +52189,7 @@ function createMrrlinTools(options) {
51587
52189
  `Origin remote ${remoteUrl} does not match repo ${repo}.`
51588
52190
  );
51589
52191
  }
51590
- 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");
51591
52193
  const registry3 = new CheckoutRegistry(stateDir);
51592
52194
  const confirmedAt = (/* @__PURE__ */ new Date()).toISOString();
51593
52195
  registry3.confirm(projectSlug, resolvedPath, confirmedAt);
@@ -51794,13 +52396,13 @@ function runSetCredential(args) {
51794
52396
  }
51795
52397
 
51796
52398
  // src/install-service.ts
51797
- var import_node_os10 = __toESM(require("node:os"), 1);
51798
- 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);
51799
52401
 
51800
52402
  // src/service-paths.ts
51801
- var import_node_path16 = __toESM(require("node:path"), 1);
52403
+ var import_node_path17 = __toESM(require("node:path"), 1);
51802
52404
  function isWorktreePath(p) {
51803
- 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("/");
51804
52406
  return norm.includes("/.claude/worktrees/");
51805
52407
  }
51806
52408
  function resolveServiceCwd(opts) {
@@ -51854,7 +52456,7 @@ function installService(deps) {
51854
52456
  deps.log(resolved.reason);
51855
52457
  return { ok: false };
51856
52458
  }
51857
- const home = deps.env.HOME ?? import_node_os10.default.homedir();
52459
+ const home = deps.env.HOME ?? import_node_os11.default.homedir();
51858
52460
  const bins = ["node", "codex", "mrrlin-mcp"].map((b) => deps.which(b));
51859
52461
  if (bins.some((b) => !b)) {
51860
52462
  deps.log("Could not resolve absolute paths for node/codex/mrrlin-mcp on PATH. Install them or fix PATH.");
@@ -51865,7 +52467,7 @@ function installService(deps) {
51865
52467
  return { ok: false };
51866
52468
  }
51867
52469
  const resolvedBins = bins.filter((b) => b !== null);
51868
- 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(":");
51869
52471
  const text = renderEcosystemConfig({
51870
52472
  cwd: resolved.cwd,
51871
52473
  home,
@@ -51874,7 +52476,7 @@ function installService(deps) {
51874
52476
  staging: deps.env.MRRLIN_STAGING === "1",
51875
52477
  apiBaseUrl: deps.env.MRRLIN_API_BASE_URL?.trim() || void 0
51876
52478
  });
51877
- 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");
51878
52480
  deps.writeFile(ecoPath, text);
51879
52481
  const start = deps.runPm2(["startOrReload", ecoPath]);
51880
52482
  if (start.code !== 0) {
@@ -51905,13 +52507,13 @@ function uninstallService(deps) {
51905
52507
 
51906
52508
  // src/uninstall-codex.ts
51907
52509
  var import_promises4 = __toESM(require("node:fs/promises"), 1);
51908
- var import_node_os11 = __toESM(require("node:os"), 1);
51909
- 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);
51910
52512
  var toml2 = __toESM(require_toml(), 1);
51911
52513
  function resolveCodexHome2(options) {
51912
52514
  if (options.codexHome) return options.codexHome;
51913
52515
  if (process.env.CODEX_HOME) return process.env.CODEX_HOME;
51914
- 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");
51915
52517
  }
51916
52518
  async function pathExists3(target) {
51917
52519
  try {
@@ -51921,10 +52523,10 @@ async function pathExists3(target) {
51921
52523
  return false;
51922
52524
  }
51923
52525
  }
51924
- 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;
51925
52527
  async function uninstallCodex(options = {}) {
51926
52528
  const codexHome = resolveCodexHome2(options);
51927
- const configPath = import_node_path18.default.join(codexHome, "config.toml");
52529
+ const configPath = import_node_path19.default.join(codexHome, "config.toml");
51928
52530
  const removePrompts = async () => uninstallPrompts(codexHome, options.promptNames ?? []);
51929
52531
  if (!await pathExists3(configPath)) {
51930
52532
  return { action: "missing", configPath, prompts: await removePrompts() };
@@ -51943,19 +52545,19 @@ async function uninstallCodex(options = {}) {
51943
52545
  };
51944
52546
  throw Object.assign(new Error(err.detail), err);
51945
52547
  }
51946
- if (parsed?.mcp_servers?.["mrrlin"] === void 0) {
52548
+ if (parsed?.mcp_servers?.["mrrlin"] === void 0 && parsed?.mcp_servers?.["mrrlin-browser"] === void 0) {
51947
52549
  return { action: "noop", configPath: realPath, prompts: await removePrompts() };
51948
52550
  }
51949
- 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+/, "");
51950
52552
  await import_promises4.default.writeFile(realPath, stripped, { mode: 384 });
51951
52553
  return { action: "removed", configPath: realPath, prompts: await removePrompts() };
51952
52554
  }
51953
52555
  async function uninstallPrompts(codexHome, names) {
51954
52556
  if (names.length === 0) return [];
51955
- const promptsDir2 = import_node_path18.default.join(codexHome, "prompts");
52557
+ const promptsDir2 = import_node_path19.default.join(codexHome, "prompts");
51956
52558
  const out = [];
51957
52559
  for (const name of names) {
51958
- const promptPath = import_node_path18.default.join(promptsDir2, `${name}.md`);
52560
+ const promptPath = import_node_path19.default.join(promptsDir2, `${name}.md`);
51959
52561
  try {
51960
52562
  await import_promises4.default.unlink(promptPath);
51961
52563
  out.push({ name, action: "removed", promptPath });
@@ -51973,26 +52575,26 @@ async function uninstallPrompts(codexHome, names) {
51973
52575
 
51974
52576
  // src/report-issue-prompt.ts
51975
52577
  var import_node_fs15 = __toESM(require("node:fs"), 1);
51976
- var import_node_path19 = __toESM(require("node:path"), 1);
51977
- var import_node_url2 = require("node:url");
51978
- 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 = {};
51979
52581
  function promptsDir() {
51980
- if (typeof __dirname !== "undefined") return import_node_path19.default.join(__dirname, "prompts");
51981
- 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");
51982
52584
  }
51983
52585
  function readReportIssuePrompt() {
51984
- 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");
51985
52587
  }
51986
52588
 
51987
52589
  // src/bin.ts
51988
52590
  function pm2Runner(args) {
51989
- 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" });
51990
52592
  process.stderr.write(r.stdout ?? "");
51991
52593
  process.stderr.write(r.stderr ?? "");
51992
52594
  return { code: r.status ?? 1, stdout: r.stdout ?? "" };
51993
52595
  }
51994
52596
  function whichBin(bin) {
51995
- 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" });
51996
52598
  const out = (r.stdout ?? "").trim();
51997
52599
  return r.status === 0 && out ? out.split("\n")[0] ?? null : null;
51998
52600
  }
@@ -52005,6 +52607,18 @@ Usage:
52005
52607
  MRRLIN_API_ALLOW_REMOTE=1, or use MRRLIN_STAGING=1
52006
52608
  to target the known staging API alias.
52007
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
+
52008
52622
  mrrlin-mcp install-codex Idempotently register Mrrlin in
52009
52623
  [--force] ~/.codex/config.toml (or CODEX_HOME). Adds an
52010
52624
  [--force-prompts] [mcp_servers.mrrlin] block AND drops the bundled
@@ -52138,10 +52752,33 @@ async function main() {
52138
52752
  await startStdioServer();
52139
52753
  return;
52140
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
+ }
52141
52767
  case "install-codex": {
52142
52768
  const force = rest.includes("--force");
52143
52769
  const forcePrompts = rest.includes("--force-prompts");
52144
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
+ }
52145
52782
  const result = await installCodex({
52146
52783
  binPath,
52147
52784
  force,
@@ -52191,7 +52828,7 @@ async function main() {
52191
52828
  env: process.env,
52192
52829
  cwd: process.cwd(),
52193
52830
  writeFile: (p, c) => {
52194
- (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 });
52195
52832
  (0, import_node_fs16.writeFileSync)(p, c, { mode: 384 });
52196
52833
  },
52197
52834
  runPm2: pm2Runner,
@@ -52216,14 +52853,14 @@ async function main() {
52216
52853
  purgeSecret: purge,
52217
52854
  secretPath: agentCredentialPath(),
52218
52855
  tokenPath: operatorTokenPath(),
52219
- 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"),
52220
52857
  log: (m) => process.stderr.write(`[mrrlin-mcp uninstall-service] ${m}
52221
52858
  `)
52222
52859
  });
52223
52860
  return;
52224
52861
  }
52225
52862
  case "uninstall": {
52226
- const home = process.env.HOME ?? (0, import_node_os12.homedir)();
52863
+ const home = process.env.HOME ?? (0, import_node_os13.homedir)();
52227
52864
  const log = (m) => process.stderr.write(`[mrrlin-mcp uninstall] ${m}
52228
52865
  `);
52229
52866
  uninstallService({
@@ -52237,7 +52874,7 @@ async function main() {
52237
52874
  purgeSecret: true,
52238
52875
  secretPath: agentCredentialPath(),
52239
52876
  tokenPath: operatorTokenPath(),
52240
- ecoPath: import_node_path21.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
52877
+ ecoPath: import_node_path22.default.join(home, ".mrrlin", "ecosystem.config.cjs"),
52241
52878
  log
52242
52879
  });
52243
52880
  let codexOk = true;
@@ -52257,7 +52894,7 @@ async function main() {
52257
52894
  log(`codex config NOT modified: ${error51 instanceof Error ? error51.message : String(error51)}`);
52258
52895
  }
52259
52896
  try {
52260
- (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 });
52261
52898
  } catch {
52262
52899
  }
52263
52900
  log("removed ~/.mrrlin");
@@ -52298,7 +52935,7 @@ ${HELP_TEXT}`);
52298
52935
  }
52299
52936
  }
52300
52937
  function resolveSelfBinPath() {
52301
- return import_node_path20.default.resolve(process.argv[1] ?? process.execPath);
52938
+ return import_node_path21.default.resolve(process.argv[1] ?? process.execPath);
52302
52939
  }
52303
52940
  main().catch((error51) => {
52304
52941
  process.stderr.write(`mrrlin-mcp fatal error: ${error51 instanceof Error ? error51.message : String(error51)}