@runweave/server-darwin-x64 0.1.2 → 0.1.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 (88) hide show
  1. package/manifest.json +161 -156
  2. package/native.tar.gz +0 -0
  3. package/package.json +1 -1
  4. package/payload/app-server/build-info.json +4 -4
  5. package/payload/app-server/index.cjs +290 -89
  6. package/payload/app-server/index.cjs.map +1 -1
  7. package/payload/backend/build-info.json +4 -4
  8. package/payload/backend/dev-resources/control.cjs +197 -20
  9. package/payload/backend/evolution-sqlite-worker.cjs +58 -1
  10. package/payload/backend/index.cjs +3108 -2061
  11. package/payload/backend/scheduled-tasks-sqlite-worker.cjs +11 -7
  12. package/payload/frontend/dist/assets/{_baseUniq-B6OtH5JH.js → _baseUniq-2DZJ97aQ.js} +1 -1
  13. package/payload/frontend/dist/assets/{access-CpH3nCnI.js → access-Jw5gZrYY.js} +1 -1
  14. package/payload/frontend/dist/assets/{advanced-U5MqNTD5.js → advanced-DRe-Doxo.js} +1 -1
  15. package/payload/frontend/dist/assets/{appearance-Cb8XjaOT.js → appearance-D1wpkdXT.js} +1 -1
  16. package/payload/frontend/dist/assets/{arc-CEnFQNMK.js → arc-keTQ5uhA.js} +1 -1
  17. package/payload/frontend/dist/assets/{architectureDiagram-Q4EWVU46-T438RyEG.js → architectureDiagram-Q4EWVU46-BXbCJ77m.js} +1 -1
  18. package/payload/frontend/dist/assets/{blockDiagram-DXYQGD6D-B6Mqb9og.js → blockDiagram-DXYQGD6D-De0Ki8tO.js} +1 -1
  19. package/payload/frontend/dist/assets/{c4Diagram-AHTNJAMY-CO3eA3hw.js → c4Diagram-AHTNJAMY-EfazoSVi.js} +1 -1
  20. package/payload/frontend/dist/assets/channel-CExZE0tD.js +1 -0
  21. package/payload/frontend/dist/assets/{chunk-4BX2VUAB-1vjsV_mH.js → chunk-4BX2VUAB-BXCGPL07.js} +1 -1
  22. package/payload/frontend/dist/assets/{chunk-4TB4RGXK-CtMNFDLV.js → chunk-4TB4RGXK-ByjQ1_yc.js} +1 -1
  23. package/payload/frontend/dist/assets/{chunk-55IACEB6-DVWWqMjZ.js → chunk-55IACEB6-D-KjMbGJ.js} +1 -1
  24. package/payload/frontend/dist/assets/{chunk-EDXVE4YY-BBf3C6eJ.js → chunk-EDXVE4YY-tAgLMZ4w.js} +1 -1
  25. package/payload/frontend/dist/assets/{chunk-FMBD7UC4-BUQfXSvf.js → chunk-FMBD7UC4-D3J3ERtV.js} +1 -1
  26. package/payload/frontend/dist/assets/{chunk-OYMX7WX6-DM1nFyON.js → chunk-OYMX7WX6-DZHtmvkW.js} +1 -1
  27. package/payload/frontend/dist/assets/{chunk-QZHKN3VN-Bz3CUNpU.js → chunk-QZHKN3VN-D6IIGd1d.js} +1 -1
  28. package/payload/frontend/dist/assets/{chunk-YZCP3GAM-Bb6CnKMv.js → chunk-YZCP3GAM-KD19-lMa.js} +1 -1
  29. package/payload/frontend/dist/assets/classDiagram-6PBFFD2Q-DNOAkizi.js +1 -0
  30. package/payload/frontend/dist/assets/classDiagram-v2-HSJHXN6E-DNOAkizi.js +1 -0
  31. package/payload/frontend/dist/assets/clone-CzOxlTa8.js +1 -0
  32. package/payload/frontend/dist/assets/connection-Cm6G1HOW.js +12 -0
  33. package/payload/frontend/dist/assets/{connections-1OP6Izpn.js → connections-B8tSRWt9.js} +1 -1
  34. package/payload/frontend/dist/assets/{cose-bilkent-S5V4N54A-DvX1W1oQ.js → cose-bilkent-S5V4N54A-AYXbL8jP.js} +1 -1
  35. package/payload/frontend/dist/assets/{dagre-KV5264BT-BYV7l80W.js → dagre-KV5264BT-DCunJ-sG.js} +1 -1
  36. package/payload/frontend/dist/assets/{desktop-DKYPd_Z3.js → desktop-DnY652OH.js} +1 -1
  37. package/payload/frontend/dist/assets/{diagram-5BDNPKRD-BU_VxMcA.js → diagram-5BDNPKRD-Ch2b63ll.js} +1 -1
  38. package/payload/frontend/dist/assets/{diagram-G4DWMVQ6-6jnkLcPr.js → diagram-G4DWMVQ6-BAuc_Uar.js} +1 -1
  39. package/payload/frontend/dist/assets/{diagram-MMDJMWI5-DAjbbS4T.js → diagram-MMDJMWI5-DH8qMuDA.js} +1 -1
  40. package/payload/frontend/dist/assets/{diagram-TYMM5635-p2T86-Pr.js → diagram-TYMM5635-BflD7Kjb.js} +1 -1
  41. package/payload/frontend/dist/assets/{erDiagram-SMLLAGMA-DcZPoxkO.js → erDiagram-SMLLAGMA-BGzvzTP9.js} +1 -1
  42. package/payload/frontend/dist/assets/{flowDiagram-DWJPFMVM-CDB-5IUB.js → flowDiagram-DWJPFMVM-BR4mXArp.js} +1 -1
  43. package/payload/frontend/dist/assets/{ganttDiagram-T4ZO3ILL-imCnxO5S.js → ganttDiagram-T4ZO3ILL-uXtJoz5O.js} +1 -1
  44. package/payload/frontend/dist/assets/{gitGraphDiagram-UUTBAWPF-DW7bWVfm.js → gitGraphDiagram-UUTBAWPF-BeLB68OO.js} +1 -1
  45. package/payload/frontend/dist/assets/{graph-rPoUAwm2.js → graph-DakNuFNs.js} +1 -1
  46. package/payload/frontend/dist/assets/{image-pt4OUNUX.js → image-BICNaNq8.js} +1 -1
  47. package/payload/frontend/dist/assets/{index-CpU0rt1e.js → index-Cf9Vl4GJ.js} +92 -89
  48. package/payload/frontend/dist/assets/{infoDiagram-42DDH7IO-C6DYDEhQ.js → infoDiagram-42DDH7IO-CAGn0b04.js} +1 -1
  49. package/payload/frontend/dist/assets/{ishikawaDiagram-UXIWVN3A-o3dlbDPW.js → ishikawaDiagram-UXIWVN3A-fbaDUCpd.js} +1 -1
  50. package/payload/frontend/dist/assets/{journeyDiagram-VCZTEJTY-ukG3M2cI.js → journeyDiagram-VCZTEJTY-ZOmjleqG.js} +1 -1
  51. package/payload/frontend/dist/assets/{kanban-definition-6JOO6SKY-CzFLztFd.js → kanban-definition-6JOO6SKY-BmODq4tv.js} +1 -1
  52. package/payload/frontend/dist/assets/{layout-C8SEMYSj.js → layout-CLfuo3Vs.js} +1 -1
  53. package/payload/frontend/dist/assets/{linear-DY8vPita.js → linear-csTsZ7Al.js} +1 -1
  54. package/payload/frontend/dist/assets/main-DtzgJZEf.css +33 -0
  55. package/payload/frontend/dist/assets/{main-B_ifx48h.js → main-DwDuhfcr.js} +154 -151
  56. package/payload/frontend/dist/assets/{min-9StlgeN8.js → min-B4B7Rr4j.js} +1 -1
  57. package/payload/frontend/dist/assets/{mindmap-definition-QFDTVHPH-CyJisFtS.js → mindmap-definition-QFDTVHPH-CiV2UasH.js} +1 -1
  58. package/payload/frontend/dist/assets/{monitoring-Bjm0etKL.js → monitoring-1_Fnxura.js} +1 -1
  59. package/payload/frontend/dist/assets/{notifications-DhRLCgMU.js → notifications-VJaMbzoX.js} +1 -1
  60. package/payload/frontend/dist/assets/{pieDiagram-DEJITSTG-DHSht7rk.js → pieDiagram-DEJITSTG-DwazVxKI.js} +1 -1
  61. package/payload/frontend/dist/assets/{quadrantDiagram-34T5L4WZ-92xIujrE.js → quadrantDiagram-34T5L4WZ-CAn9HHbO.js} +1 -1
  62. package/payload/frontend/dist/assets/{record-content-Cy_dPSdi.js → record-content-Bewq09_f.js} +1 -1
  63. package/payload/frontend/dist/assets/{requirementDiagram-MS252O5E-CXuOqrNd.js → requirementDiagram-MS252O5E-CFot9peV.js} +1 -1
  64. package/payload/frontend/dist/assets/{sankeyDiagram-XADWPNL6-DR-mjY0Y.js → sankeyDiagram-XADWPNL6-CdRX6WuA.js} +1 -1
  65. package/payload/frontend/dist/assets/{sequenceDiagram-FGHM5R23-DmmUpAoP.js → sequenceDiagram-FGHM5R23-vRc1a5W1.js} +1 -1
  66. package/payload/frontend/dist/assets/{stateDiagram-FHFEXIEX-CKoqQ0-j.js → stateDiagram-FHFEXIEX-Bxcr7s70.js} +1 -1
  67. package/payload/frontend/dist/assets/stateDiagram-v2-QKLJ7IA2-YGvbZNwL.js +1 -0
  68. package/payload/frontend/dist/assets/{status-B__OyRqS.js → status-9tZZeoV7.js} +1 -1
  69. package/payload/frontend/dist/assets/suiji-DX2ioZ0I.js +1 -0
  70. package/payload/frontend/dist/assets/{svg-BpvEgtI3.js → svg-qpyWsADE.js} +1 -1
  71. package/payload/frontend/dist/assets/{tabs-BjCNEXFA.js → tabs-CwPtRQY0.js} +1 -1
  72. package/payload/frontend/dist/assets/{timeline-definition-GMOUNBTQ-CHT2sQNz.js → timeline-definition-GMOUNBTQ-2mD2ePS6.js} +1 -1
  73. package/payload/frontend/dist/assets/{vennDiagram-DHZGUBPP-Bvnh5q4I.js → vennDiagram-DHZGUBPP-w4DbLykx.js} +1 -1
  74. package/payload/frontend/dist/assets/{wardley-RL74JXVD-DeQXKB6h.js → wardley-RL74JXVD-C3H8SQaZ.js} +1 -1
  75. package/payload/frontend/dist/assets/{wardleyDiagram-NUSXRM2D-jWo5oC0L.js → wardleyDiagram-NUSXRM2D-DEI0kC2c.js} +1 -1
  76. package/payload/frontend/dist/assets/{xychartDiagram-5P7HB3ND-Btji0cq9.js → xychartDiagram-5P7HB3ND-DDVlpQ28.js} +1 -1
  77. package/payload/frontend/dist/build-info.json +4 -4
  78. package/payload/frontend/dist/companion.html +1 -1
  79. package/payload/frontend/dist/index.html +3 -3
  80. package/payload/server/index.cjs +205 -19
  81. package/payload/frontend/dist/assets/channel-D7VgadXd.js +0 -1
  82. package/payload/frontend/dist/assets/classDiagram-6PBFFD2Q-DHRHkXVC.js +0 -1
  83. package/payload/frontend/dist/assets/classDiagram-v2-HSJHXN6E-DHRHkXVC.js +0 -1
  84. package/payload/frontend/dist/assets/clone-BzLTnNJj.js +0 -1
  85. package/payload/frontend/dist/assets/connection-ChK196PA.js +0 -12
  86. package/payload/frontend/dist/assets/main-C-ZLrzMh.css +0 -33
  87. package/payload/frontend/dist/assets/stateDiagram-v2-QKLJ7IA2-BfZc0BCX.js +0 -1
  88. package/payload/frontend/dist/assets/suiji-nz2Jwmpc.js +0 -1
@@ -1,4 +1,4 @@
1
- /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261101T021552392Z-f96ecff6","sourceRevision":"f96ecff6b81b7dfd1d421a0bc3dada24bf1d5fa1","sourceDirty":false,"builtAt":"2026-11-01T02:15:52.392Z","contentSha256":"12d69ee2a5501059b7d0c43f5b9b10f0f3c5a18c5b259c6d8fd2e1ced4285668"};
1
+ /* runweave:build-info */var __RUNWEAVE_BUILD_INFO__={"version":"0.1.0","buildId":"20261107T223319383Z-f6afc191","sourceRevision":"f6afc191b5f9be76aa35a6ee494a0d752c21af08","sourceDirty":false,"builtAt":"2026-11-07T22:33:19.383Z","contentSha256":"c391a00b597ca25406e1b3afa7654d2fa4ecc180b3a685c649dbd2acd40c8900"};
2
2
  const __IMPORT_META_URL__ = require('url').pathToFileURL(__filename).href;
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -25745,13 +25745,13 @@ var require_view = __commonJS({
25745
25745
  View.prototype.resolve = function resolve2(dir, file) {
25746
25746
  var ext = this.ext;
25747
25747
  var path22 = join(dir, file);
25748
- var stat2 = tryStat(path22);
25749
- if (stat2 && stat2.isFile()) {
25748
+ var stat3 = tryStat(path22);
25749
+ if (stat3 && stat3.isFile()) {
25750
25750
  return path22;
25751
25751
  }
25752
25752
  path22 = join(dir, basename(file, ext), "index" + ext);
25753
- stat2 = tryStat(path22);
25754
- if (stat2 && stat2.isFile()) {
25753
+ stat3 = tryStat(path22);
25754
+ if (stat3 && stat3.isFile()) {
25755
25755
  return path22;
25756
25756
  }
25757
25757
  };
@@ -26021,9 +26021,9 @@ var require_etag = __commonJS({
26021
26021
  }
26022
26022
  return obj && typeof obj === "object" && "ctime" in obj && toString.call(obj.ctime) === "[object Date]" && "mtime" in obj && toString.call(obj.mtime) === "[object Date]" && "ino" in obj && typeof obj.ino === "number" && "size" in obj && typeof obj.size === "number";
26023
26023
  }
26024
- function stattag(stat2) {
26025
- var mtime = stat2.mtime.getTime().toString(16);
26026
- var size = stat2.size.toString(16);
26024
+ function stattag(stat3) {
26025
+ var mtime = stat3.mtime.getTime().toString(16);
26026
+ var size = stat3.size.toString(16);
26027
26027
  return '"' + size + "-" + mtime + '"';
26028
26028
  }
26029
26029
  }
@@ -26636,8 +26636,8 @@ var require_send = __commonJS({
26636
26636
  this.sendFile(path22);
26637
26637
  return res;
26638
26638
  };
26639
- SendStream.prototype.send = function send3(path22, stat2) {
26640
- var len = stat2.size;
26639
+ SendStream.prototype.send = function send3(path22, stat3) {
26640
+ var len = stat3.size;
26641
26641
  var options = this.options;
26642
26642
  var opts = {};
26643
26643
  var res = this.res;
@@ -26649,7 +26649,7 @@ var require_send = __commonJS({
26649
26649
  return;
26650
26650
  }
26651
26651
  debug('pipe "%s"', path22);
26652
- this.setHeader(path22, stat2);
26652
+ this.setHeader(path22, stat3);
26653
26653
  this.type(path22);
26654
26654
  if (this.isConditionalGET()) {
26655
26655
  if (this.isPreconditionFailure()) {
@@ -26705,14 +26705,14 @@ var require_send = __commonJS({
26705
26705
  var i = 0;
26706
26706
  var self = this;
26707
26707
  debug('stat "%s"', path22);
26708
- fs.stat(path22, function onstat(err, stat2) {
26708
+ fs.stat(path22, function onstat(err, stat3) {
26709
26709
  if (err && err.code === "ENOENT" && !extname(path22) && path22[path22.length - 1] !== sep) {
26710
26710
  return next(err);
26711
26711
  }
26712
26712
  if (err) return self.onStatError(err);
26713
- if (stat2.isDirectory()) return self.redirect(path22);
26714
- self.emit("file", path22, stat2);
26715
- self.send(path22, stat2);
26713
+ if (stat3.isDirectory()) return self.redirect(path22);
26714
+ self.emit("file", path22, stat3);
26715
+ self.send(path22, stat3);
26716
26716
  });
26717
26717
  function next(err) {
26718
26718
  if (self._extensions.length <= i) {
@@ -26720,11 +26720,11 @@ var require_send = __commonJS({
26720
26720
  }
26721
26721
  var p = path22 + "." + self._extensions[i++];
26722
26722
  debug('stat "%s"', p);
26723
- fs.stat(p, function(err2, stat2) {
26723
+ fs.stat(p, function(err2, stat3) {
26724
26724
  if (err2) return next(err2);
26725
- if (stat2.isDirectory()) return next();
26726
- self.emit("file", p, stat2);
26727
- self.send(p, stat2);
26725
+ if (stat3.isDirectory()) return next();
26726
+ self.emit("file", p, stat3);
26727
+ self.send(p, stat3);
26728
26728
  });
26729
26729
  }
26730
26730
  };
@@ -26738,11 +26738,11 @@ var require_send = __commonJS({
26738
26738
  }
26739
26739
  var p = join(path22, self._index[i]);
26740
26740
  debug('stat "%s"', p);
26741
- fs.stat(p, function(err2, stat2) {
26741
+ fs.stat(p, function(err2, stat3) {
26742
26742
  if (err2) return next(err2);
26743
- if (stat2.isDirectory()) return next();
26744
- self.emit("file", p, stat2);
26745
- self.send(p, stat2);
26743
+ if (stat3.isDirectory()) return next();
26744
+ self.emit("file", p, stat3);
26745
+ self.send(p, stat3);
26746
26746
  });
26747
26747
  }
26748
26748
  next();
@@ -26777,9 +26777,9 @@ var require_send = __commonJS({
26777
26777
  debug("content-type %s", type2);
26778
26778
  res.setHeader("Content-Type", type2 + (charset ? "; charset=" + charset : ""));
26779
26779
  };
26780
- SendStream.prototype.setHeader = function setHeader(path22, stat2) {
26780
+ SendStream.prototype.setHeader = function setHeader(path22, stat3) {
26781
26781
  var res = this.res;
26782
- this.emit("headers", res, path22, stat2);
26782
+ this.emit("headers", res, path22, stat3);
26783
26783
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
26784
26784
  debug("accept ranges");
26785
26785
  res.setHeader("Accept-Ranges", "bytes");
@@ -26793,12 +26793,12 @@ var require_send = __commonJS({
26793
26793
  res.setHeader("Cache-Control", cacheControl);
26794
26794
  }
26795
26795
  if (this._lastModified && !res.getHeader("Last-Modified")) {
26796
- var modified = stat2.mtime.toUTCString();
26796
+ var modified = stat3.mtime.toUTCString();
26797
26797
  debug("modified %s", modified);
26798
26798
  res.setHeader("Last-Modified", modified);
26799
26799
  }
26800
26800
  if (this._etag && !res.getHeader("ETag")) {
26801
- var val = etag(stat2);
26801
+ var val = etag(stat3);
26802
26802
  debug("etag %s", val);
26803
26803
  res.setHeader("ETag", val);
26804
26804
  }
@@ -33560,16 +33560,16 @@ async function scanConversationSource(file, consume, signal) {
33560
33560
  try {
33561
33561
  if (await (0, import_promises.realpath)(file) !== file) return null;
33562
33562
  handle = await (0, import_promises.open)(file, import_node_fs2.constants.O_RDONLY | import_node_fs2.constants.O_NOFOLLOW);
33563
- const stat2 = await handle.stat();
33564
- if (!stat2.isFile()) return null;
33563
+ const stat3 = await handle.stat();
33564
+ if (!stat3.isFile()) return null;
33565
33565
  const windowBytes = 64 * 1024 * 1024;
33566
- const truncated = stat2.size > windowBytes;
33566
+ const truncated = stat3.size > windowBytes;
33567
33567
  let partial = truncated;
33568
33568
  const chunk = Buffer.alloc(256 * 1024);
33569
33569
  const ranges = truncated ? [
33570
- { start: 0, end: Math.min(chunk.length, stat2.size), header: true },
33571
- { start: stat2.size - windowBytes, end: stat2.size, header: false }
33572
- ] : [{ start: 0, end: stat2.size, header: false }];
33570
+ { start: 0, end: Math.min(chunk.length, stat3.size), header: true },
33571
+ { start: stat3.size - windowBytes, end: stat3.size, header: false }
33572
+ ] : [{ start: 0, end: stat3.size, header: false }];
33573
33573
  for (const range of ranges) {
33574
33574
  let position = range.start;
33575
33575
  let lineOffset = position;
@@ -34558,15 +34558,15 @@ var ConfigurationError = class extends Error {
34558
34558
  // packages/config-node/src/private-file.ts
34559
34559
  var import_node_fs4 = require("node:fs");
34560
34560
  function assertPrivateDirectory(directory) {
34561
- const stat2 = (0, import_node_fs4.lstatSync)(directory);
34562
- if (!stat2.isDirectory() || stat2.isSymbolicLink() || stat2.mode & 63 || typeof process.getuid === "function" && stat2.uid !== process.getuid()) throw new ConfigurationError("CONFIG_ROOT_PERMISSIONS_INVALID");
34561
+ const stat3 = (0, import_node_fs4.lstatSync)(directory);
34562
+ if (!stat3.isDirectory() || stat3.isSymbolicLink() || stat3.mode & 63 || typeof process.getuid === "function" && stat3.uid !== process.getuid()) throw new ConfigurationError("CONFIG_ROOT_PERMISSIONS_INVALID");
34563
34563
  }
34564
34564
  function assertPrivateDescriptor(fd, maxBytes = 1024 * 1024) {
34565
- const stat2 = (0, import_node_fs4.fstatSync)(fd);
34566
- if (!stat2.isFile() || stat2.nlink !== 1) throw new ConfigurationError("CONFIG_FILE_NOT_PRIVATE_REGULAR");
34567
- if (typeof process.getuid === "function" && stat2.uid !== process.getuid()) throw new ConfigurationError("CONFIG_FILE_OWNER_MISMATCH");
34568
- if (stat2.mode & 63) throw new ConfigurationError("CONFIG_FILE_PERMISSIONS_INVALID");
34569
- if (stat2.size > maxBytes) throw new ConfigurationError("CONFIG_FILE_TOO_LARGE");
34565
+ const stat3 = (0, import_node_fs4.fstatSync)(fd);
34566
+ if (!stat3.isFile() || stat3.nlink !== 1) throw new ConfigurationError("CONFIG_FILE_NOT_PRIVATE_REGULAR");
34567
+ if (typeof process.getuid === "function" && stat3.uid !== process.getuid()) throw new ConfigurationError("CONFIG_FILE_OWNER_MISMATCH");
34568
+ if (stat3.mode & 63) throw new ConfigurationError("CONFIG_FILE_PERMISSIONS_INVALID");
34569
+ if (stat3.size > maxBytes) throw new ConfigurationError("CONFIG_FILE_TOO_LARGE");
34570
34570
  }
34571
34571
  function readPrivateFile(file, maxBytes = 1024 * 1024) {
34572
34572
  const fd = (0, import_node_fs4.openSync)(file, import_node_fs4.constants.O_RDONLY | import_node_fs4.constants.O_NOFOLLOW);
@@ -34696,7 +34696,39 @@ function registerStableConfigurationRoot(context) {
34696
34696
  (0, import_node_fs6.closeSync)(registryFd);
34697
34697
  }
34698
34698
  }
34699
+ function withUpgradeGate(context, shared, run) {
34700
+ const directory = ownerDirectory(context);
34701
+ const fd = (0, import_node_fs6.openSync)(import_node_path4.default.join(directory, "configuration-upgrade.lock"), import_node_fs6.constants.O_CREAT | import_node_fs6.constants.O_RDWR | import_node_fs6.constants.O_NOFOLLOW, 384);
34702
+ try {
34703
+ assertPrivateDescriptor(fd);
34704
+ if (!(0, import_fs_native_extensions.tryLock)(fd, 0, 0, { shared })) throw new ConfigurationError("CONFIG_UPGRADE_BUSY");
34705
+ return run();
34706
+ } finally {
34707
+ (0, import_node_fs6.closeSync)(fd);
34708
+ }
34709
+ }
34710
+ function withConfigurationUpgradeOwnership(context, run, ignoredRoles = []) {
34711
+ return withUpgradeGate(context, false, () => {
34712
+ const directory = ownerDirectory(context);
34713
+ const held = [];
34714
+ try {
34715
+ for (const file of (0, import_node_fs6.readdirSync)(directory).filter((name) => name.endsWith(".owner.lock"))) {
34716
+ if (ignoredRoles.includes(file.replace(/\.owner\.lock$/, ""))) continue;
34717
+ const fd = (0, import_node_fs6.openSync)(import_node_path4.default.join(directory, file), import_node_fs6.constants.O_RDWR | import_node_fs6.constants.O_NOFOLLOW);
34718
+ held.push(fd);
34719
+ assertPrivateDescriptor(fd);
34720
+ if (!(0, import_fs_native_extensions.tryLock)(fd)) throw new ConfigurationError("CONFIG_UPGRADE_CONSUMER_RUNNING", [file.replace(/\.owner\.lock$/, "")]);
34721
+ }
34722
+ return run();
34723
+ } finally {
34724
+ for (const fd of held) (0, import_node_fs6.closeSync)(fd);
34725
+ }
34726
+ });
34727
+ }
34699
34728
  function acquireConfigurationOwner(context, role) {
34729
+ return withUpgradeGate(context, true, () => acquireOwner(context, role));
34730
+ }
34731
+ function acquireOwner(context, role) {
34700
34732
  const directory = ownerDirectory(context);
34701
34733
  const fd = (0, import_node_fs6.openSync)(import_node_path4.default.join(directory, `${role}.owner.lock`), import_node_fs6.constants.O_CREAT | import_node_fs6.constants.O_RDWR | import_node_fs6.constants.O_NOFOLLOW, 384);
34702
34734
  let closed = false;
@@ -34717,13 +34749,6 @@ function acquireConfigurationOwner(context, role) {
34717
34749
  }
34718
34750
  }
34719
34751
 
34720
- // packages/config-node/src/store.ts
34721
- var import_node_fs7 = require("node:fs");
34722
- var import_node_path6 = __toESM(require("node:path"), 1);
34723
- var import_node_crypto4 = require("node:crypto");
34724
- var import_yaml = __toESM(require_dist(), 1);
34725
- var import_fs_native_extensions2 = require("fs-native-extensions");
34726
-
34727
34752
  // packages/shared/src/configuration/fields.ts
34728
34753
  var CONFIGURATION_FIELDS = [
34729
34754
  { "path": "screenRecording.analysis.enabled", "type": "boolean", "domain": "screenRecording.analysis", "sensitive": false, "remote": false, "apply": "reload", "description": "\u542F\u7528\u672C\u673A\u5C4F\u5E55\u4E8B\u9879\u5206\u6790\uFF0C\u9ED8\u8BA4\u5173\u95ED", "environmentKeys": [], "owner": "backend/screen-recording-analysis", "scope": "instance", "storage": "settings.yaml", "default": { "value": false }, "migrationSources": ["new-field:no-legacy-source"] },
@@ -34896,14 +34921,18 @@ var CONFIGURATION_FIELDS = [
34896
34921
  ];
34897
34922
 
34898
34923
  // packages/shared/src/configuration/compatibility.ts
34924
+ var CONFIGURATION_SCHEMA_VERSION = 1;
34925
+ var CONFIGURATION_DOMAIN_VERSIONS = Object.fromEntries(
34926
+ [...new Set(CONFIGURATION_FIELDS.map((field) => field.domain))].map((domain) => [domain, 1])
34927
+ );
34899
34928
  var CONFIGURATION_COMPATIBILITY = {
34900
34929
  format: "runweave-yaml",
34901
- schemaVersions: [1],
34902
- domainVersions: Object.fromEntries([...new Set(CONFIGURATION_FIELDS.map((field) => field.domain))].map((domain) => [domain, [1]]))
34930
+ schemaVersions: [CONFIGURATION_SCHEMA_VERSION],
34931
+ domainVersions: Object.fromEntries(Object.entries(CONFIGURATION_DOMAIN_VERSIONS).map(([domain, version]) => [domain, [version]]))
34903
34932
  };
34904
34933
  var APP_SERVER_CONFIGURATION_COMPATIBILITY = {
34905
34934
  ...CONFIGURATION_COMPATIBILITY,
34906
- domainVersions: Object.fromEntries(["appServer", "agents.codex", "agents.traex"].map((domain) => [domain, [1]]))
34935
+ domainVersions: Object.fromEntries(["appServer", "agents.codex", "agents.traex"].map((domain) => [domain, [CONFIGURATION_DOMAIN_VERSIONS[domain]]]))
34907
34936
  };
34908
34937
  function supportsConfiguration(target, value) {
34909
34938
  if (!target || typeof target !== "object") return false;
@@ -34979,6 +35008,66 @@ function configurationPathSegment(key) {
34979
35008
  return key.replace(/\\/g, "\\\\").replace(/\./g, "\\.");
34980
35009
  }
34981
35010
 
35011
+ // packages/config-node/src/version-migrations.ts
35012
+ var CONFIGURATION_VERSION_MIGRATIONS = [];
35013
+ function migrateConfigurationDocument(document2) {
35014
+ const steps = [];
35015
+ const ids = /* @__PURE__ */ new Set();
35016
+ const edges = /* @__PURE__ */ new Set();
35017
+ for (const step of CONFIGURATION_VERSION_MIGRATIONS) {
35018
+ const edge = `${step.domain ?? "$schema"}:${step.from}`;
35019
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]+$/.test(step.id) || ids.has(step.id) || edges.has(edge) || !Number.isSafeInteger(step.from) || step.from < 1 || step.to !== step.from + 1 || step.domain !== void 0 && !Object.hasOwn(CONFIGURATION_DOMAIN_VERSIONS, step.domain) || step.to > (step.domain ? CONFIGURATION_DOMAIN_VERSIONS[step.domain] : CONFIGURATION_SCHEMA_VERSION)) {
35020
+ throw new ConfigurationError("CONFIG_UPGRADE_REGISTRY_INVALID");
35021
+ }
35022
+ ids.add(step.id);
35023
+ edges.add(edge);
35024
+ }
35025
+ const advance = (domain, target) => {
35026
+ const versionPath = domain ? ["domainVersions", domain] : ["schemaVersion"];
35027
+ let version = Number(document2.getIn(versionPath) ?? 1);
35028
+ if (version > target) throw new ConfigurationError("CONFIG_UPGRADE_FUTURE_VERSION", [domain ?? "schemaVersion"]);
35029
+ while (version < target) {
35030
+ const step = CONFIGURATION_VERSION_MIGRATIONS.find((item) => item.domain === domain && item.from === version);
35031
+ if (!step) throw new ConfigurationError("CONFIG_UPGRADE_PATH_MISSING", [domain ?? "schemaVersion"]);
35032
+ const before = document2.toJS();
35033
+ try {
35034
+ step.migrate(document2);
35035
+ } catch {
35036
+ throw new ConfigurationError("CONFIG_UPGRADE_STEP_FAILED", [step.id]);
35037
+ }
35038
+ const after = document2.toJS();
35039
+ for (const key of ["schemaVersion", "revision", "kind", "instanceId", "domainVersions", "migrations"]) {
35040
+ if (JSON.stringify(before[key]) !== JSON.stringify(after[key])) throw new ConfigurationError("CONFIG_UPGRADE_METADATA_CHANGED", [step.id]);
35041
+ }
35042
+ if (domain) {
35043
+ const strip = (value) => {
35044
+ const copy = structuredClone(value);
35045
+ const parts = domain.split(".");
35046
+ let parent = copy;
35047
+ for (const key of parts.slice(0, -1)) parent = parent[key] ?? {};
35048
+ delete parent[parts.at(-1)];
35049
+ return copy;
35050
+ };
35051
+ if (JSON.stringify(strip(before)) !== JSON.stringify(strip(after))) throw new ConfigurationError("CONFIG_UPGRADE_SCOPE_CHANGED", [step.id]);
35052
+ }
35053
+ document2.setIn(versionPath, step.to);
35054
+ document2.setIn(["migrations", `version:${step.id}`], { from: step.from, to: step.to, domain: domain ?? "$schema" });
35055
+ steps.push(step.id);
35056
+ version = step.to;
35057
+ }
35058
+ };
35059
+ advance(void 0, CONFIGURATION_SCHEMA_VERSION);
35060
+ for (const [domain, target] of Object.entries(CONFIGURATION_DOMAIN_VERSIONS)) advance(domain, target);
35061
+ return steps;
35062
+ }
35063
+
35064
+ // packages/config-node/src/store.ts
35065
+ var import_node_fs7 = require("node:fs");
35066
+ var import_node_path6 = __toESM(require("node:path"), 1);
35067
+ var import_node_crypto4 = require("node:crypto");
35068
+ var import_yaml = __toESM(require_dist(), 1);
35069
+ var import_fs_native_extensions2 = require("fs-native-extensions");
35070
+
34982
35071
  // packages/config-node/src/validation.ts
34983
35072
  var import_node_path5 = __toESM(require("node:path"), 1);
34984
35073
  var patterns = CONFIGURATION_FIELDS.map((field) => ({ field, segments: field.path.replace(/\[\]/g, ".#").split(".") }));
@@ -34997,12 +35086,14 @@ function isConfigurationContainer(key, array = false) {
34997
35086
  });
34998
35087
  }
34999
35088
  function domainForPath(key) {
35089
+ const declared = Object.keys(CONFIGURATION_DOMAIN_VERSIONS).find((domain) => key === domain || key.startsWith(`${domain}.`));
35090
+ if (declared) return declared;
35000
35091
  const parts = key.split(".");
35001
35092
  return ["backend", "services", "desktop", "agents"].includes(parts[0]) ? parts.slice(0, 2).join(".") : parts[0];
35002
35093
  }
35003
35094
  function validateEnvelope(value, context) {
35004
35095
  if (!isConfigurationObject(value)) throw new ConfigurationError("CONFIG_ROOT_INVALID");
35005
- if (value.schemaVersion !== 1) throw new ConfigurationError("CONFIG_SCHEMA_UNSUPPORTED");
35096
+ if (value.schemaVersion !== CONFIGURATION_SCHEMA_VERSION) throw new ConfigurationError("CONFIG_SCHEMA_UNSUPPORTED");
35006
35097
  if (!Number.isSafeInteger(value.revision) || Number(value.revision) < 0) throw new ConfigurationError("CONFIG_REVISION_INVALID");
35007
35098
  if (value.kind !== context.kind || value.instanceId !== context.instanceId) throw new ConfigurationError("CONFIG_IDENTITY_MISMATCH");
35008
35099
  if (!isConfigurationObject(value.domainVersions) || !isConfigurationObject(value.migrations)) throw new ConfigurationError("CONFIG_METADATA_INVALID");
@@ -35024,7 +35115,7 @@ function validateDomains(value, context) {
35024
35115
  if (["schemaVersion", "revision", "kind", "instanceId", "domainVersions", "migrations"].includes(key.split(".")[0])) continue;
35025
35116
  const domain = domainForPath(key);
35026
35117
  if (domain === "agents.team") continue;
35027
- if (value.domainVersions[domain] !== void 0 && value.domainVersions[domain] !== 1) {
35118
+ if (value.domainVersions[domain] !== void 0 && value.domainVersions[domain] !== CONFIGURATION_DOMAIN_VERSIONS[domain]) {
35028
35119
  issue(key, "CONFIG_DOMAIN_VERSION_UNSUPPORTED");
35029
35120
  continue;
35030
35121
  }
@@ -35099,7 +35190,7 @@ function validateDomains(value, context) {
35099
35190
  }
35100
35191
  for (const [domain, version] of Object.entries(value.domainVersions)) {
35101
35192
  if (domain === "agents.team") continue;
35102
- if (version !== 1 && !result[domain]) result[domain] = [{ path: domain, code: "CONFIG_DOMAIN_VERSION_UNSUPPORTED" }];
35193
+ if (version !== CONFIGURATION_DOMAIN_VERSIONS[domain] && !result[domain]) result[domain] = [{ path: domain, code: "CONFIG_DOMAIN_VERSION_UNSUPPORTED" }];
35103
35194
  }
35104
35195
  return result;
35105
35196
  }
@@ -35165,11 +35256,11 @@ function parseConfigurationYaml(source, context) {
35165
35256
  return { document: document2, value, digest: (0, import_node_crypto4.createHash)("sha256").update(source).digest("hex"), issues: validateDomains(value, context) };
35166
35257
  }
35167
35258
  function assertPrivateFile(file, fd) {
35168
- const stat2 = fd === void 0 ? (0, import_node_fs7.lstatSync)(file) : (0, import_node_fs7.fstatSync)(fd);
35169
- if (!stat2.isFile() || stat2.isSymbolicLink() || stat2.nlink !== 1) throw new ConfigurationError("CONFIG_FILE_NOT_PRIVATE_REGULAR");
35170
- if (typeof process.getuid === "function" && stat2.uid !== process.getuid()) throw new ConfigurationError("CONFIG_FILE_OWNER_MISMATCH");
35171
- if ((stat2.mode & 63) !== 0) throw new ConfigurationError("CONFIG_FILE_PERMISSIONS_INVALID");
35172
- if (stat2.size > MAX_BYTES) throw new ConfigurationError("CONFIG_FILE_TOO_LARGE", [], { line: 1, column: 1 });
35259
+ const stat3 = fd === void 0 ? (0, import_node_fs7.lstatSync)(file) : (0, import_node_fs7.fstatSync)(fd);
35260
+ if (!stat3.isFile() || stat3.isSymbolicLink() || stat3.nlink !== 1) throw new ConfigurationError("CONFIG_FILE_NOT_PRIVATE_REGULAR");
35261
+ if (typeof process.getuid === "function" && stat3.uid !== process.getuid()) throw new ConfigurationError("CONFIG_FILE_OWNER_MISMATCH");
35262
+ if ((stat3.mode & 63) !== 0) throw new ConfigurationError("CONFIG_FILE_PERMISSIONS_INVALID");
35263
+ if (stat3.size > MAX_BYTES) throw new ConfigurationError("CONFIG_FILE_TOO_LARGE", [], { line: 1, column: 1 });
35173
35264
  }
35174
35265
  var ConfigurationStore = class {
35175
35266
  constructor(context) {
@@ -35204,7 +35295,7 @@ var ConfigurationStore = class {
35204
35295
  (0, import_node_fs7.closeSync)(fd);
35205
35296
  }
35206
35297
  }
35207
- publish(document2, previous) {
35298
+ publish(document2, previous, backupId) {
35208
35299
  const source = document2.toString({ lineWidth: 0 });
35209
35300
  const checked = parseConfigurationYaml(source, this.context);
35210
35301
  registerStableConfigurationRoot(this.context);
@@ -35214,7 +35305,7 @@ var ConfigurationStore = class {
35214
35305
  (0, import_node_fs7.mkdirSync)(backupRoot, { recursive: true, mode: 448 });
35215
35306
  const backupStat = (0, import_node_fs7.lstatSync)(backupRoot);
35216
35307
  if (!backupStat.isDirectory() || backupStat.isSymbolicLink() || backupStat.mode & 63 || typeof process.getuid === "function" && backupStat.uid !== process.getuid()) throw new ConfigurationError("CONFIG_BACKUP_ROOT_INVALID");
35217
- const backup = import_node_path6.default.join(backupRoot, `${Date.now()}-${(0, import_node_crypto4.randomUUID)()}.yaml`);
35308
+ const backup = import_node_path6.default.join(backupRoot, backupId ?? `${Date.now()}-${(0, import_node_crypto4.randomUUID)()}.yaml`);
35218
35309
  const fd2 = (0, import_node_fs7.openSync)(backup, "wx", 384);
35219
35310
  try {
35220
35311
  (0, import_node_fs7.writeFileSync)(fd2, previous);
@@ -35261,7 +35352,7 @@ var ConfigurationStore = class {
35261
35352
  const segments = configurationPathSegments(key);
35262
35353
  if (!segments.length || segments.some((part) => !part || unsafeKeys.has(part))) throw new ConfigurationError("CONFIG_FIELD_INVALID");
35263
35354
  const domain = domainForPath(key);
35264
- if (current.value.domainVersions[domain] !== void 0 && current.value.domainVersions[domain] !== 1) throw new ConfigurationError("CONFIG_DOMAIN_VERSION_UNSUPPORTED", [domain]);
35355
+ if (current.value.domainVersions[domain] !== void 0 && current.value.domainVersions[domain] !== CONFIGURATION_DOMAIN_VERSIONS[domain]) throw new ConfigurationError("CONFIG_DOMAIN_VERSION_UNSUPPORTED", [domain]);
35265
35356
  const field = fieldForPath(key);
35266
35357
  if (!field && !(isConfigurationObject(value) && isConfigurationContainer(key)) && !(Array.isArray(value) && isConfigurationContainer(key, true)) && !(value === null && (isConfigurationContainer(key) || isConfigurationContainer(key, true)))) throw new ConfigurationError("CONFIG_FIELD_UNKNOWN", [key]);
35267
35358
  if (options.remote && (!field || !field.remote)) throw new ConfigurationError("CONFIG_FIELD_FORBIDDEN", [key]);
@@ -35271,7 +35362,7 @@ var ConfigurationStore = class {
35271
35362
  for (const segment of segments) target.push((0, import_yaml.isSeq)(current.document.getIn(target, true)) && /^\d+$/.test(segment) ? Number(segment) : segment);
35272
35363
  if (!field && value === null) current.document.deleteIn(target);
35273
35364
  else current.document.setIn(target, value);
35274
- current.document.setIn(["domainVersions", domain], 1);
35365
+ current.document.setIn(["domainVersions", domain], CONFIGURATION_DOMAIN_VERSIONS[domain]);
35275
35366
  domains.add(domain);
35276
35367
  }
35277
35368
  const revision = Math.max(current.value.revision, options.minimumRevision ?? 0) + 1;
@@ -35309,7 +35400,7 @@ var ConfigurationStore = class {
35309
35400
  const source = readPrivateFile(this.file);
35310
35401
  const { value } = parseYamlDocument(source);
35311
35402
  if (!isConfigurationObject(value) || !Number.isSafeInteger(value.schemaVersion) || Number(value.schemaVersion) < 1) throw new ConfigurationError("CONFIG_SCHEMA_INVALID");
35312
- validateEnvelope({ ...value, schemaVersion: 1 }, this.context);
35403
+ validateEnvelope({ ...value, schemaVersion: CONFIGURATION_SCHEMA_VERSION }, this.context);
35313
35404
  const backup = this.readBackup(id);
35314
35405
  const before = new Map(flattenConfiguration(value));
35315
35406
  const after = new Map(flattenConfiguration(backup.value));
@@ -35328,6 +35419,89 @@ var ConfigurationStore = class {
35328
35419
  previewRestore(id) {
35329
35420
  return this.prepareRestore(id).preview;
35330
35421
  }
35422
+ /** Upgrade control plane only; business readers must use read(). */
35423
+ readUpgradeSource() {
35424
+ assertPrivateDirectory(this.context.configRoot);
35425
+ const source = readPrivateFile(this.file);
35426
+ const { document: document2, value } = parseYamlDocument(source);
35427
+ if (!isConfigurationObject(value) || !Number.isSafeInteger(value.schemaVersion) || Number(value.schemaVersion) < 1) throw new ConfigurationError("CONFIG_SCHEMA_INVALID");
35428
+ validateEnvelope({ ...value, schemaVersion: CONFIGURATION_SCHEMA_VERSION }, this.context);
35429
+ return { source, document: document2, value, digest: (0, import_node_crypto4.createHash)("sha256").update(source).digest("hex") };
35430
+ }
35431
+ prepareUpgrade() {
35432
+ const { source, document: document2, value, digest } = this.readUpgradeSource();
35433
+ const original = value;
35434
+ const expectedDigest = digest;
35435
+ const steps = migrateConfigurationDocument(document2);
35436
+ const next = parseConfigurationYaml(document2.toString({ lineWidth: 0 }), this.context);
35437
+ const failures = Object.values(next.issues).flat();
35438
+ if (failures.length) throw new ConfigurationError("CONFIG_VALIDATION_FAILED", failures.map((issue) => issue.path));
35439
+ const before = new Map(flattenConfiguration(original));
35440
+ const after = new Map(flattenConfiguration(next.value));
35441
+ const changedFields = [.../* @__PURE__ */ new Set([...before.keys(), ...after.keys()])].filter((key) => JSON.stringify(before.get(key)) !== JSON.stringify(after.get(key))).sort();
35442
+ const preview = {
35443
+ expectedRevision: original.revision,
35444
+ expectedDigest,
35445
+ source: { schemaVersion: original.schemaVersion, domainVersions: original.domainVersions },
35446
+ target: { schemaVersion: next.value.schemaVersion, domainVersions: { ...CONFIGURATION_DOMAIN_VERSIONS, ...next.value.domainVersions } },
35447
+ steps,
35448
+ changedFields,
35449
+ changed: changedFields.length > 0
35450
+ };
35451
+ return { source, document: document2, preview };
35452
+ }
35453
+ previewUpgrade() {
35454
+ return this.prepareUpgrade().preview;
35455
+ }
35456
+ recordUpgrade(value) {
35457
+ const file = import_node_path6.default.join(this.context.configRoot, "config-upgrade.json");
35458
+ const temporary = `${file}.${(0, import_node_crypto4.randomUUID)()}.tmp`;
35459
+ const fd = (0, import_node_fs7.openSync)(temporary, "wx", 384);
35460
+ try {
35461
+ (0, import_node_fs7.writeFileSync)(fd, JSON.stringify(value, null, 2) + "\n");
35462
+ (0, import_node_fs7.fsyncSync)(fd);
35463
+ } finally {
35464
+ (0, import_node_fs7.closeSync)(fd);
35465
+ }
35466
+ try {
35467
+ (0, import_node_fs7.renameSync)(temporary, file);
35468
+ const parent = (0, import_node_fs7.openSync)(this.context.configRoot, "r");
35469
+ try {
35470
+ (0, import_node_fs7.fsyncSync)(parent);
35471
+ } finally {
35472
+ (0, import_node_fs7.closeSync)(parent);
35473
+ }
35474
+ } finally {
35475
+ if ((0, import_node_fs7.existsSync)(temporary)) (0, import_node_fs7.unlinkSync)(temporary);
35476
+ }
35477
+ }
35478
+ upgrade(expected) {
35479
+ return this.locked(() => {
35480
+ const { source, document: document2, preview } = this.prepareUpgrade();
35481
+ if (preview.expectedRevision !== expected.revision || preview.expectedDigest !== expected.digest) throw new ConfigurationError("CONFIG_REVISION_CONFLICT");
35482
+ if (!preview.changed) {
35483
+ const receiptFile = import_node_path6.default.join(this.context.configRoot, "config-upgrade.json");
35484
+ if ((0, import_node_fs7.existsSync)(receiptFile)) {
35485
+ const receipt = JSON.parse(readPrivateFile(receiptFile));
35486
+ if (isConfigurationObject(receipt) && receipt.phase === "prepared" && receipt.plannedDigest === expected.digest)
35487
+ this.recordUpgrade({ ...receipt, phase: "committed", savedRevision: expected.revision, digest: expected.digest });
35488
+ }
35489
+ return { ...preview, savedRevision: expected.revision, digest: expected.digest };
35490
+ }
35491
+ return withConfigurationUpgradeOwnership(this.context, () => {
35492
+ const revision = expected.revision + 1;
35493
+ if (!Number.isSafeInteger(revision)) throw new ConfigurationError("CONFIG_REVISION_INVALID");
35494
+ document2.set("revision", revision);
35495
+ const backupId = `${Date.now()}-${(0, import_node_crypto4.randomUUID)()}.yaml`;
35496
+ const plannedDigest = (0, import_node_crypto4.createHash)("sha256").update(document2.toString({ lineWidth: 0 })).digest("hex");
35497
+ this.recordUpgrade({ ...preview, backupId, plannedDigest, phase: "prepared" });
35498
+ const next = this.publish(document2, source, backupId);
35499
+ const result = { ...preview, savedRevision: next.value.revision, digest: next.digest, backupId };
35500
+ this.recordUpgrade({ ...result, phase: "committed" });
35501
+ return result;
35502
+ });
35503
+ });
35504
+ }
35331
35505
  restoreBackup(id, expected) {
35332
35506
  return this.locked(() => {
35333
35507
  const { source, backup, preview } = this.prepareRestore(id);
@@ -35738,8 +35912,8 @@ var PiSessionReader = class {
35738
35912
  try {
35739
35913
  if (await (0, import_promises4.realpath)(file) !== file) return null;
35740
35914
  handle = await (0, import_promises4.open)(file, "r");
35741
- const stat2 = await handle.stat();
35742
- if (!stat2.isFile() || stat2.size > 64 * 1024 * 1024) return null;
35915
+ const stat3 = await handle.stat();
35916
+ if (!stat3.isFile() || stat3.size > 64 * 1024 * 1024) return null;
35743
35917
  const content = await handle.readFile("utf8");
35744
35918
  const lines = content.split("\n");
35745
35919
  lines.pop();
@@ -35869,7 +36043,7 @@ ${entry.summary}`
35869
36043
  preview,
35870
36044
  status: status === "running" ? "active" : status === "idle" ? "idle" : "notLoaded",
35871
36045
  createdAt: String(header.timestamp ?? ""),
35872
- updatedAt: new Date(stat2.mtimeMs).toISOString(),
36046
+ updatedAt: new Date(stat3.mtimeMs).toISOString(),
35873
36047
  turns
35874
36048
  },
35875
36049
  latest
@@ -36236,15 +36410,15 @@ var ThreadPreviewReader = class {
36236
36410
  }
36237
36411
  const handle = await (0, import_promises6.open)(file, "r");
36238
36412
  try {
36239
- const stat2 = await handle.stat();
36240
- if (!stat2.isFile()) {
36413
+ const stat3 = await handle.stat();
36414
+ if (!stat3.isFile()) {
36241
36415
  entry.ready = false;
36242
36416
  entry.availability = "source_missing";
36243
36417
  return;
36244
36418
  }
36245
- if (entry.file !== file || entry.inode !== stat2.ino || stat2.size < entry.offset) {
36419
+ if (entry.file !== file || entry.inode !== stat3.ino || stat3.size < entry.offset) {
36246
36420
  entry.file = file;
36247
- entry.inode = stat2.ino;
36421
+ entry.inode = stat3.ino;
36248
36422
  entry.offset = 0;
36249
36423
  entry.pending = Buffer.alloc(0);
36250
36424
  entry.skippingLine = false;
@@ -36256,11 +36430,11 @@ var ThreadPreviewReader = class {
36256
36430
  entry.leaf = null;
36257
36431
  entry.piCursor = null;
36258
36432
  }
36259
- const buffer = Buffer.alloc(Math.min(READ_BYTES, stat2.size - entry.offset));
36433
+ const buffer = Buffer.alloc(Math.min(READ_BYTES, stat3.size - entry.offset));
36260
36434
  const { bytesRead } = await handle.read(buffer, 0, buffer.length, entry.offset);
36261
36435
  entry.offset += bytesRead;
36262
36436
  this.consume(entry, buffer.subarray(0, bytesRead));
36263
- if (entry.offset < stat2.size) {
36437
+ if (entry.offset < stat3.size) {
36264
36438
  this.queued.add(entry);
36265
36439
  return;
36266
36440
  }
@@ -37181,6 +37355,7 @@ var import_promises9 = require("node:fs/promises");
37181
37355
  var import_node_os5 = __toESM(require("node:os"), 1);
37182
37356
  var import_node_path16 = __toESM(require("node:path"), 1);
37183
37357
  var ROLLOUT_TAIL_BYTES = 1024 * 1024;
37358
+ var ROLLOUT_LOOKBACK_BYTES = 64 * ROLLOUT_TAIL_BYTES;
37184
37359
  var TERMINAL_LIFECYCLE_TYPES = /* @__PURE__ */ new Set([
37185
37360
  "task_started",
37186
37361
  "task_complete",
@@ -37206,13 +37381,11 @@ var CodexRolloutLifecycleReader = class {
37206
37381
  }
37207
37382
  try {
37208
37383
  const previous = this.snapshots.get(threadId);
37209
- const tail = await readFileTail(filePath, previous?.signature);
37210
- if (tail.content === null) return previous.lifecycle;
37211
- const lifecycle = parseLatestLifecycle(tail.content);
37384
+ const snapshot = await readFileLifecycle(filePath, previous);
37212
37385
  this.snapshots.delete(threadId);
37213
- this.snapshots.set(threadId, { signature: tail.signature, lifecycle });
37386
+ this.snapshots.set(threadId, snapshot);
37214
37387
  if (this.snapshots.size > 128) this.snapshots.delete(this.snapshots.keys().next().value);
37215
- return lifecycle;
37388
+ return snapshot.lifecycle;
37216
37389
  } catch {
37217
37390
  this.threadPaths.delete(threadId);
37218
37391
  this.snapshots.delete(threadId);
@@ -37245,21 +37418,32 @@ var CodexRolloutLifecycleReader = class {
37245
37418
  return this.threadPaths.get(threadId) ?? [...this.threadPaths].find(([id]) => id.endsWith(`-${threadId}`))?.[1] ?? null;
37246
37419
  }
37247
37420
  };
37248
- async function readFileTail(filePath, previousSignature) {
37421
+ async function readFileLifecycle(filePath, previous) {
37249
37422
  const handle = await (0, import_promises9.open)(filePath, "r");
37250
37423
  try {
37251
37424
  const { size, dev, ino, mtimeMs, ctimeMs } = await handle.stat();
37252
37425
  const signature = `${filePath}:${dev}:${ino}:${size}:${mtimeMs}:${ctimeMs}`;
37253
- if (signature === previousSignature) return { signature, content: null };
37254
- const start = Math.max(0, size - ROLLOUT_TAIL_BYTES);
37255
- const buffer = Buffer.alloc(size - start);
37256
- const { bytesRead } = await handle.read(buffer, 0, buffer.length, start);
37257
- const value = buffer.subarray(0, bytesRead).toString("utf8");
37258
- if (start === 0) {
37259
- return { signature, content: value };
37260
- }
37261
- const firstNewline = value.indexOf("\n");
37262
- return { signature, content: firstNewline === -1 ? "" : value.slice(firstNewline + 1) };
37426
+ if (signature === previous?.signature) return previous;
37427
+ const floor = Math.max(0, size - ROLLOUT_LOOKBACK_BYTES);
37428
+ let end = size;
37429
+ let suffix = Buffer.alloc(0);
37430
+ let lifecycle = null;
37431
+ while (end > floor && !lifecycle) {
37432
+ const start = Math.max(floor, end - ROLLOUT_TAIL_BYTES);
37433
+ const buffer = Buffer.alloc(end - start);
37434
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, start);
37435
+ if (bytesRead !== buffer.length) return { signature, lifecycle: null };
37436
+ const value = Buffer.concat([buffer, suffix]);
37437
+ const boundary = start > 0 ? value.indexOf(10) : -1;
37438
+ const complete = start === 0 ? value : boundary < 0 ? Buffer.alloc(0) : value.subarray(boundary + 1);
37439
+ lifecycle = parseLatestLifecycle(complete.toString("utf8"));
37440
+ suffix = boundary >= 0 && boundary < ROLLOUT_TAIL_BYTES ? Buffer.from(value.subarray(0, boundary + 1)) : Buffer.alloc(0);
37441
+ end = start;
37442
+ }
37443
+ const current = await (0, import_promises9.stat)(filePath);
37444
+ if (current.dev !== dev || current.ino !== ino || current.size !== size || current.mtimeMs !== mtimeMs || current.ctimeMs !== ctimeMs)
37445
+ return { signature, lifecycle: null };
37446
+ return { signature, lifecycle };
37263
37447
  } finally {
37264
37448
  await handle.close();
37265
37449
  }
@@ -37457,6 +37641,7 @@ var AgentThreadStatusReconciler = class {
37457
37641
  collectCandidates() {
37458
37642
  const cutoff = Date.now() - ACTIVE_WINDOW_MS;
37459
37643
  return this.options.eventCenter.getStateStore().listThreads({ limit: 1e4 }).filter((thread) => RECONCILED_AGENTS.has(thread.agent)).filter((thread) => !thread.threadId.startsWith("unknown-thread:")).filter((thread) => {
37644
+ if (thread.status === "running") return true;
37460
37645
  const lastActivityAtMs = Date.parse(thread.lastActivityAt);
37461
37646
  return !Number.isFinite(lastActivityAtMs) || lastActivityAtMs >= cutoff;
37462
37647
  }).sort(
@@ -37492,8 +37677,19 @@ var AgentThreadStatusReconciler = class {
37492
37677
  const lifecycle2 = await this.options.codexRolloutLifecycleReader.readLatestLifecycle(
37493
37678
  thread.threadId
37494
37679
  );
37680
+ if (lifecycle2?.status === "running" && (thread.status === "running" || !isOlderThanThreadProjection(lifecycle2.timestamp, thread))) {
37681
+ return {
37682
+ status: "running",
37683
+ lifecycleType: `rollout:${lifecycle2.type}`,
37684
+ lifecycleCursor: lifecycle2.cursor,
37685
+ detailStatus: null,
37686
+ preview: null,
37687
+ turnId: lifecycle2.turnId
37688
+ };
37689
+ }
37495
37690
  const sameObservedFailure = lifecycle2?.error && thread.status === "idle" && thread.lastLifecycleType === `rollout:${lifecycle2.type}` && thread.lastLifecycleCursor === lifecycle2.cursor;
37496
- if (lifecycle2?.status === "idle" && (!isOlderThanThreadProjection(lifecycle2.timestamp, thread) || sameObservedFailure) && // A terminal error is a fact even if a Hook already marked the thread
37691
+ const followsObservedStart = lifecycle2 && thread.lastLifecycleType === "rollout:task_started" && newerRolloutCursor(lifecycle2.cursor, thread.lastLifecycleCursor);
37692
+ if (lifecycle2?.status === "idle" && (!isOlderThanThreadProjection(lifecycle2.timestamp, thread) || sameObservedFailure || followsObservedStart) && // A terminal error is a fact even if a Hook already marked the thread
37497
37693
  // idle, or thread/read still reports active. Never adopt an old turn.
37498
37694
  (lifecycle2.error || thread.status === "running" && status !== "active")) {
37499
37695
  return {
@@ -37612,6 +37808,11 @@ var AgentThreadStatusReconciler = class {
37612
37808
  });
37613
37809
  }
37614
37810
  };
37811
+ function newerRolloutCursor(current, previous) {
37812
+ const currentOrdinal = current.match(/^rollout:(\d+)$/)?.[1];
37813
+ const previousOrdinal = previous?.match(/^rollout:(\d+)$/)?.[1];
37814
+ return Boolean(currentOrdinal && previousOrdinal && BigInt(currentOrdinal) > BigInt(previousOrdinal));
37815
+ }
37615
37816
  function isOlderThanThreadProjection(observedAt, thread) {
37616
37817
  const observedAtMs = Date.parse(observedAt);
37617
37818
  const projectedAtMs = Date.parse(thread.updatedAt);