@macintacos/caret 0.4.1 → 0.6.0

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 (99) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +1 -4
  3. package/commands/demo.md +7 -8
  4. package/dist/cli.js +1325 -1280
  5. package/opencode/caret.plugin.ts +29 -7
  6. package/package.json +2 -1
  7. package/ui/dist/assets/{angular-html-kKPIob-B.js → angular-html-BI5MKOgL.js} +1 -1
  8. package/ui/dist/assets/{angular-ts-CKjP4O1R.js → angular-ts-NpE6rBGT.js} +1 -1
  9. package/ui/dist/assets/{apl-DCRQgCPD.js → apl-Czt59WyL.js} +1 -1
  10. package/ui/dist/assets/{astro-BYbWYON5.js → astro-DT1AJ4cx.js} +1 -1
  11. package/ui/dist/assets/{blade-CwhP_dxJ.js → blade-DpCiEmbj.js} +1 -1
  12. package/ui/dist/assets/{c-CJEVusFw.js → c-D7DFUCyL.js} +1 -1
  13. package/ui/dist/assets/{cobol-DIBOqviT.js → cobol-RlKqBkL-.js} +1 -1
  14. package/ui/dist/assets/{coffee-BS7TY60J.js → coffee-DP83cIY_.js} +1 -1
  15. package/ui/dist/assets/{cpp-D1DVYlIO.js → cpp-BllPwA2_.js} +1 -1
  16. package/ui/dist/assets/{crystal-1wNBwJ9X.js → crystal-BEYliJwN.js} +1 -1
  17. package/ui/dist/assets/{css-DcRg7BqA.js → css-1jgL8fwJ.js} +1 -1
  18. package/ui/dist/assets/{dist-C7ysmu-x.js → dist--YyKzUET.js} +1 -1
  19. package/ui/dist/assets/{dist-DBvtZoff.js → dist-5Rf4rJ0X.js} +1 -1
  20. package/ui/dist/assets/{dist-Buh6GXb2.js → dist-B5pXy_X7.js} +1 -1
  21. package/ui/dist/assets/{dist-C0x7GorT.js → dist-Bbha_IyL.js} +1 -1
  22. package/ui/dist/assets/{dist-BeSPrXBn.js → dist-Btp41eU_.js} +1 -1
  23. package/ui/dist/assets/{dist-CA76eI1h.js → dist-CHWg1lsZ.js} +1 -1
  24. package/ui/dist/assets/{dist-fAkxRpOI.js → dist-CV8dMtWT.js} +1 -1
  25. package/ui/dist/assets/{dist-Cyz1Y8uV.js → dist-CcduUyxv.js} +1 -1
  26. package/ui/dist/assets/{dist-Bm-_E_MU.js → dist-CmoaxCRS.js} +1 -1
  27. package/ui/dist/assets/{dist-C2049AtS.js → dist-CptuCEQu.js} +1 -1
  28. package/ui/dist/assets/{dist-Dhe__fm5.js → dist-CqLDLPH3.js} +1 -1
  29. package/ui/dist/assets/{dist-DPr7mnLy.js → dist-CqMTRX1k.js} +1 -1
  30. package/ui/dist/assets/{dist-CZ-hU0oG.js → dist-DmLfnDuf.js} +1 -1
  31. package/ui/dist/assets/{dist-DNG5YE4w.js → dist-DsKHdtkl.js} +1 -1
  32. package/ui/dist/assets/{dist-afCEYO1j.js → dist-KhjzrYW3.js} +1 -1
  33. package/ui/dist/assets/{dist-BPvuZVb2.js → dist-QEfOrML6.js} +1 -1
  34. package/ui/dist/assets/{dist-CzDZ2KMv.js → dist-V4YCFxam.js} +1 -1
  35. package/ui/dist/assets/{edge-DhG5RI3d.js → edge-BAd4dfhB.js} +1 -1
  36. package/ui/dist/assets/{elixir-k8JKnHNU.js → elixir-C-S3mGHc.js} +1 -1
  37. package/ui/dist/assets/{elm-BCt58sPl.js → elm-Dc9W4_9C.js} +1 -1
  38. package/ui/dist/assets/{erb-gEaFK19o.js → erb-_HLiMho2.js} +1 -1
  39. package/ui/dist/assets/{git-rebase-PGNnuu_q.js → git-rebase-CxtmTwSl.js} +1 -1
  40. package/ui/dist/assets/{glimmer-js-BShMa8kS.js → glimmer-js-CT0oz8FE.js} +1 -1
  41. package/ui/dist/assets/{glimmer-ts-BBjvNufU.js → glimmer-ts-CX8P96zL.js} +1 -1
  42. package/ui/dist/assets/{glsl-CVu5XUh6.js → glsl-CJhxjXAa.js} +1 -1
  43. package/ui/dist/assets/{graphql-CpSUkXDO.js → graphql-CYzH_iEe.js} +1 -1
  44. package/ui/dist/assets/{hack-vYYr_EuM.js → hack-CP5HqU2D.js} +1 -1
  45. package/ui/dist/assets/{haml-aiyqEFS_.js → haml-BuGxMA-x.js} +1 -1
  46. package/ui/dist/assets/{handlebars-vKdd7ZE6.js → handlebars-DyTBn97H.js} +1 -1
  47. package/ui/dist/assets/{html-BSDB9v3Y.js → html-CiXkGYuH.js} +1 -1
  48. package/ui/dist/assets/{html-derivative-V8cBpxuT.js → html-derivative-C0J_m08l.js} +1 -1
  49. package/ui/dist/assets/{http-DXSNVmLc.js → http-DsBhmeHe.js} +1 -1
  50. package/ui/dist/assets/{hurl-eKV70JUb.js → hurl-BCnlQqoe.js} +1 -1
  51. package/ui/dist/assets/{index-C3YoPLgV.js → index-CXh79vJs.js} +187 -109
  52. package/ui/dist/assets/index-Db4ww_ld.css +1 -0
  53. package/ui/dist/assets/{java-DGolWD2l.js → java-ojPGmrtY.js} +1 -1
  54. package/ui/dist/assets/{javascript-DcKrb1R6.js → javascript-CjPa7lGe.js} +1 -1
  55. package/ui/dist/assets/{jinja-O0MduF1V.js → jinja-CoD-k-ty.js} +1 -1
  56. package/ui/dist/assets/{jison-BGBc5HtG.js → jison-iG8KT2RW.js} +1 -1
  57. package/ui/dist/assets/{json-B-Q47BuG.js → json-XWESeWc3.js} +1 -1
  58. package/ui/dist/assets/{jsx-B__N5PZx.js → jsx-CZiuwLIZ.js} +1 -1
  59. package/ui/dist/assets/{julia-BfiIt3AD.js → julia-Cdh8h4IA.js} +1 -1
  60. package/ui/dist/assets/{just-CN940-eY.js → just-Bn0yH-8D.js} +1 -1
  61. package/ui/dist/assets/{latex-wUKEeqEd.js → latex-DwDjgG8q.js} +1 -1
  62. package/ui/dist/assets/{liquid-D2cnd1Ez.js → liquid-BTIoP9jK.js} +1 -1
  63. package/ui/dist/assets/{lua-BQiIdljT.js → lua-Bx0xYuBy.js} +1 -1
  64. package/ui/dist/assets/{marko-BCqypbre.js → marko-BI79qd8u.js} +1 -1
  65. package/ui/dist/assets/{mdc-105-eiCZ.js → mdc-DiGVImjX.js} +1 -1
  66. package/ui/dist/assets/{nginx-C5dkaLo6.js → nginx-Bowp2swR.js} +1 -1
  67. package/ui/dist/assets/{nim-RJQN31Xa.js → nim-TYJ1U8Vt.js} +1 -1
  68. package/ui/dist/assets/{perl-DZkWjug_.js → perl-D8J2ihQj.js} +1 -1
  69. package/ui/dist/assets/{php-OoKYDxlw.js → php-DiPS9gm-.js} +1 -1
  70. package/ui/dist/assets/{pug-CDXuXfau.js → pug-EdYhWBX9.js} +1 -1
  71. package/ui/dist/assets/{qml-BSj8AX1e.js → qml-Bv8eWpuN.js} +1 -1
  72. package/ui/dist/assets/{r-DlO747T6.js → r-BmHjDWWb.js} +1 -1
  73. package/ui/dist/assets/{razor-D1gVuaXL.js → razor-CPZlbQDC.js} +1 -1
  74. package/ui/dist/assets/{regexp-CGVqhulu.js → regexp-C8qLAV_Z.js} +1 -1
  75. package/ui/dist/assets/{rst-DtURuW7a.js → rst-CC5yEBHt.js} +1 -1
  76. package/ui/dist/assets/{ruby-Bc3kUlvr.js → ruby-BkfV43ex.js} +1 -1
  77. package/ui/dist/assets/{sas-CFQgZChj.js → sas-C3qfp8Hb.js} +1 -1
  78. package/ui/dist/assets/{scss-B8cq7hhb.js → scss-CoSij22O.js} +1 -1
  79. package/ui/dist/assets/{shellscript-C_GHS-ym.js → shellscript-CZ4q-lNs.js} +1 -1
  80. package/ui/dist/assets/{shellsession-CTplGpC8.js → shellsession-ULINZNwY.js} +1 -1
  81. package/ui/dist/assets/{soy-BgD_ErAN.js → soy-DSLR6KaH.js} +1 -1
  82. package/ui/dist/assets/{sql-BnGnr4ii.js → sql-CwkeN_AR.js} +1 -1
  83. package/ui/dist/assets/{stata-qCQsVpGc.js → stata-0i78bIqc.js} +1 -1
  84. package/ui/dist/assets/{surrealql-BqH_LSaF.js → surrealql-BwgPp9Xo.js} +1 -1
  85. package/ui/dist/assets/{svelte-Bu1vTtJQ.js → svelte-fvkc8P53.js} +1 -1
  86. package/ui/dist/assets/{templ-B5jQzs9l.js → templ-B4Og8vuS.js} +1 -1
  87. package/ui/dist/assets/{tex-BJ-wZPSn.js → tex-BVBAYrlA.js} +1 -1
  88. package/ui/dist/assets/{ts-tags-DuLm-TvJ.js → ts-tags-DCTcUEI5.js} +1 -1
  89. package/ui/dist/assets/{tsx-BPiBkGlY.js → tsx-UZnZkenS.js} +1 -1
  90. package/ui/dist/assets/{twig-CdQnHxAS.js → twig-29NZCSG_.js} +1 -1
  91. package/ui/dist/assets/{typescript-Dp_zdoqe.js → typescript-BBB3M1YL.js} +1 -1
  92. package/ui/dist/assets/{vue-BmKvlxSZ.js → vue-DPoVr3JE.js} +1 -1
  93. package/ui/dist/assets/{vue-html-CizabNef.js → vue-html-CkcRmmtF.js} +1 -1
  94. package/ui/dist/assets/{vue-vine-JH1Msnx4.js → vue-vine-BNxcbHJz.js} +1 -1
  95. package/ui/dist/assets/{xml-DW7DdZow.js → xml-5uxMlzmV.js} +1 -1
  96. package/ui/dist/assets/{xsl-6zDkD8bR.js → xsl-DtwduK0O.js} +1 -1
  97. package/ui/dist/assets/{yaml-W1qZ5vOg.js → yaml-D5WeSkGc.js} +1 -1
  98. package/ui/dist/index.html +2 -2
  99. package/ui/dist/assets/index-C6mdkhzF.css +0 -1
package/dist/cli.js CHANGED
@@ -1028,13 +1028,13 @@ var require_time = __commonJS((exports, module) => {
1028
1028
  const secondsSinceEpoch = currentTimeNs / NS_PER_SEC;
1029
1029
  const nanosWithinSecond = currentTimeNs % NS_PER_SEC;
1030
1030
  const msSinceEpoch = Number(secondsSinceEpoch * 1000n + nanosWithinSecond / 1000000n);
1031
- const date = new Date(msSinceEpoch);
1032
- const year = date.getUTCFullYear();
1033
- const month = (date.getUTCMonth() + 1).toString().padStart(2, "0");
1034
- const day = date.getUTCDate().toString().padStart(2, "0");
1035
- const hours = date.getUTCHours().toString().padStart(2, "0");
1036
- const minutes = date.getUTCMinutes().toString().padStart(2, "0");
1037
- const seconds = date.getUTCSeconds().toString().padStart(2, "0");
1031
+ const date5 = new Date(msSinceEpoch);
1032
+ const year = date5.getUTCFullYear();
1033
+ const month = (date5.getUTCMonth() + 1).toString().padStart(2, "0");
1034
+ const day = date5.getUTCDate().toString().padStart(2, "0");
1035
+ const hours = date5.getUTCHours().toString().padStart(2, "0");
1036
+ const minutes = date5.getUTCMinutes().toString().padStart(2, "0");
1037
+ const seconds = date5.getUTCSeconds().toString().padStart(2, "0");
1038
1038
  return `,"time":"${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${nanosWithinSecond.toString().padStart(9, "0")}Z"`;
1039
1039
  };
1040
1040
  module.exports = { nullTime, epochTime, unixTime, isoTime, isoTimeNano };
@@ -1196,7 +1196,7 @@ var require_sonic_boom = __commonJS((exports, module) => {
1196
1196
  var inherits = __require("util").inherits;
1197
1197
  var path = __require("path");
1198
1198
  var sleep = require_atomic_sleep();
1199
- var assert = __require("assert");
1199
+ var assert2 = __require("assert");
1200
1200
  var BUSY_WRITE_TIMEOUT = 100;
1201
1201
  var kEmptyBuffer = Buffer.allocUnsafe(0);
1202
1202
  var MAX_WRITE = 16 * 1024;
@@ -1204,7 +1204,7 @@ var require_sonic_boom = __commonJS((exports, module) => {
1204
1204
  var kContentModeUtf8 = "utf8";
1205
1205
  var [major, minor] = (process.versions.node || "0.0").split(".").map(Number);
1206
1206
  var kCopyBuffer = major >= 22 && minor >= 7;
1207
- function openFile(file, sonic) {
1207
+ function openFile(file2, sonic) {
1208
1208
  sonic._opening = true;
1209
1209
  sonic._writing = true;
1210
1210
  sonic._asyncDrainScheduled = false;
@@ -1226,7 +1226,7 @@ var require_sonic_boom = __commonJS((exports, module) => {
1226
1226
  }
1227
1227
  const reopening = sonic._reopening;
1228
1228
  sonic.fd = fd;
1229
- sonic.file = file;
1229
+ sonic.file = file2;
1230
1230
  sonic._reopening = false;
1231
1231
  sonic._opening = false;
1232
1232
  sonic._writing = false;
@@ -1249,21 +1249,21 @@ var require_sonic_boom = __commonJS((exports, module) => {
1249
1249
  if (sonic.sync) {
1250
1250
  try {
1251
1251
  if (sonic.mkdir)
1252
- fs.mkdirSync(path.dirname(file), { recursive: true });
1253
- const fd = fs.openSync(file, flags, mode);
1252
+ fs.mkdirSync(path.dirname(file2), { recursive: true });
1253
+ const fd = fs.openSync(file2, flags, mode);
1254
1254
  fileOpened(null, fd);
1255
1255
  } catch (err) {
1256
1256
  fileOpened(err);
1257
1257
  throw err;
1258
1258
  }
1259
1259
  } else if (sonic.mkdir) {
1260
- fs.mkdir(path.dirname(file), { recursive: true }, (err) => {
1260
+ fs.mkdir(path.dirname(file2), { recursive: true }, (err) => {
1261
1261
  if (err)
1262
1262
  return fileOpened(err);
1263
- fs.open(file, flags, mode, fileOpened);
1263
+ fs.open(file2, flags, mode, fileOpened);
1264
1264
  });
1265
1265
  } else {
1266
- fs.open(file, flags, mode, fileOpened);
1266
+ fs.open(file2, flags, mode, fileOpened);
1267
1267
  }
1268
1268
  }
1269
1269
  function SonicBoom(opts) {
@@ -1520,12 +1520,12 @@ var require_sonic_boom = __commonJS((exports, module) => {
1520
1520
  throw new Error("flush cb must be a function");
1521
1521
  }
1522
1522
  if (this.destroyed) {
1523
- const error = new Error("SonicBoom destroyed");
1523
+ const error51 = new Error("SonicBoom destroyed");
1524
1524
  if (cb) {
1525
- cb(error);
1525
+ cb(error51);
1526
1526
  return;
1527
1527
  }
1528
- throw error;
1528
+ throw error51;
1529
1529
  }
1530
1530
  if (this.minLength <= 0) {
1531
1531
  cb?.();
@@ -1547,12 +1547,12 @@ var require_sonic_boom = __commonJS((exports, module) => {
1547
1547
  throw new Error("flush cb must be a function");
1548
1548
  }
1549
1549
  if (this.destroyed) {
1550
- const error = new Error("SonicBoom destroyed");
1550
+ const error51 = new Error("SonicBoom destroyed");
1551
1551
  if (cb) {
1552
- cb(error);
1552
+ cb(error51);
1553
1553
  return;
1554
1554
  }
1555
- throw error;
1555
+ throw error51;
1556
1556
  }
1557
1557
  if (this.minLength <= 0) {
1558
1558
  cb?.();
@@ -1570,13 +1570,13 @@ var require_sonic_boom = __commonJS((exports, module) => {
1570
1570
  }
1571
1571
  this._actualWrite();
1572
1572
  }
1573
- SonicBoom.prototype.reopen = function(file) {
1573
+ SonicBoom.prototype.reopen = function(file2) {
1574
1574
  if (this.destroyed) {
1575
1575
  throw new Error("SonicBoom destroyed");
1576
1576
  }
1577
1577
  if (this._opening) {
1578
1578
  this.once("ready", () => {
1579
- this.reopen(file);
1579
+ this.reopen(file2);
1580
1580
  });
1581
1581
  return;
1582
1582
  }
@@ -1586,8 +1586,8 @@ var require_sonic_boom = __commonJS((exports, module) => {
1586
1586
  if (!this.file) {
1587
1587
  throw new Error("Unable to reopen a file descriptor, you must pass a file to SonicBoom");
1588
1588
  }
1589
- if (file) {
1590
- this.file = file;
1589
+ if (file2) {
1590
+ this.file = file2;
1591
1591
  }
1592
1592
  this._reopening = true;
1593
1593
  if (this._writing) {
@@ -1747,7 +1747,7 @@ var require_sonic_boom = __commonJS((exports, module) => {
1747
1747
  sonic.destroyed = true;
1748
1748
  sonic._bufs = [];
1749
1749
  sonic._lens = [];
1750
- assert(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
1750
+ assert2(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
1751
1751
  try {
1752
1752
  fs.fsync(sonic.fd, closeWrapped);
1753
1753
  } catch {}
@@ -1784,10 +1784,10 @@ var require_on_exit_leak_free = __commonJS((exports, module) => {
1784
1784
  exit: onExit,
1785
1785
  beforeExit: onBeforeExit
1786
1786
  };
1787
- var registry;
1787
+ var registry2;
1788
1788
  function ensureRegistry() {
1789
- if (registry === undefined) {
1790
- registry = new FinalizationRegistry(clear);
1789
+ if (registry2 === undefined) {
1790
+ registry2 = new FinalizationRegistry(clear);
1791
1791
  }
1792
1792
  }
1793
1793
  function install(event) {
@@ -1802,7 +1802,7 @@ var require_on_exit_leak_free = __commonJS((exports, module) => {
1802
1802
  }
1803
1803
  process.removeListener(event, functions[event]);
1804
1804
  if (refs.exit.length === 0 && refs.beforeExit.length === 0) {
1805
- registry = undefined;
1805
+ registry2 = undefined;
1806
1806
  }
1807
1807
  }
1808
1808
  function onExit() {
@@ -1836,7 +1836,7 @@ var require_on_exit_leak_free = __commonJS((exports, module) => {
1836
1836
  const ref = new WeakRef(obj);
1837
1837
  ref.fn = fn;
1838
1838
  ensureRegistry();
1839
- registry.register(obj, ref);
1839
+ registry2.register(obj, ref);
1840
1840
  refs[event].push(ref);
1841
1841
  }
1842
1842
  function register(obj, fn) {
@@ -1846,10 +1846,10 @@ var require_on_exit_leak_free = __commonJS((exports, module) => {
1846
1846
  _register("beforeExit", obj, fn);
1847
1847
  }
1848
1848
  function unregister(obj) {
1849
- if (registry === undefined) {
1849
+ if (registry2 === undefined) {
1850
1850
  return;
1851
1851
  }
1852
- registry.unregister(obj);
1852
+ registry2.unregister(obj);
1853
1853
  for (const event of ["exit", "beforeExit"]) {
1854
1854
  refs[event] = refs[event].filter((ref) => {
1855
1855
  const _obj = ref.deref();
@@ -1924,7 +1924,7 @@ var require_wait = __commonJS((exports, module) => {
1924
1924
  var WAIT_MS = 1e4;
1925
1925
  function wait(state, index, expected, timeout, done) {
1926
1926
  const max = timeout === Infinity ? Infinity : Date.now() + timeout;
1927
- const check = () => {
1927
+ const check2 = () => {
1928
1928
  const current = Atomics.load(state, index);
1929
1929
  if (current === expected) {
1930
1930
  done(null, "ok");
@@ -1937,16 +1937,16 @@ var require_wait = __commonJS((exports, module) => {
1937
1937
  const remaining = max === Infinity ? WAIT_MS : Math.min(WAIT_MS, Math.max(1, max - Date.now()));
1938
1938
  const result = Atomics.waitAsync(state, index, current, remaining);
1939
1939
  if (result.async) {
1940
- result.value.then(check);
1940
+ result.value.then(check2);
1941
1941
  } else {
1942
- setImmediate(check);
1942
+ setImmediate(check2);
1943
1943
  }
1944
1944
  };
1945
- check();
1945
+ check2();
1946
1946
  }
1947
1947
  function waitDiff(state, index, expected, timeout, done) {
1948
1948
  const max = timeout === Infinity ? Infinity : Date.now() + timeout;
1949
- const check = () => {
1949
+ const check2 = () => {
1950
1950
  const current = Atomics.load(state, index);
1951
1951
  if (current !== expected) {
1952
1952
  done(null, "ok");
@@ -1964,13 +1964,13 @@ var require_wait = __commonJS((exports, module) => {
1964
1964
  done(null, "ok");
1965
1965
  return;
1966
1966
  }
1967
- check();
1967
+ check2();
1968
1968
  });
1969
1969
  } else {
1970
- setImmediate(check);
1970
+ setImmediate(check2);
1971
1971
  }
1972
1972
  };
1973
- check();
1973
+ check2();
1974
1974
  }
1975
1975
  module.exports = { wait, waitDiff };
1976
1976
  });
@@ -1990,7 +1990,7 @@ var require_indexes = __commonJS((exports, module) => {
1990
1990
  // node_modules/.bun/thread-stream@4.2.0/node_modules/thread-stream/index.js
1991
1991
  var require_thread_stream = __commonJS((exports, module) => {
1992
1992
  var __dirname = "/Users/juliantorres/GitLocal/Play/caret/node_modules/.bun/thread-stream@4.2.0/node_modules/thread-stream";
1993
- var { version } = require_package();
1993
+ var { version: version2 } = require_package();
1994
1994
  var { EventEmitter } = __require("events");
1995
1995
  var { Worker } = __require("worker_threads");
1996
1996
  var { join: join6 } = __require("path");
@@ -2002,7 +2002,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2002
2002
  SEQ_INDEX
2003
2003
  } = require_indexes();
2004
2004
  var buffer = __require("buffer");
2005
- var assert = __require("assert");
2005
+ var assert2 = __require("assert");
2006
2006
  var kImpl = Symbol("kImpl");
2007
2007
  var MAX_STRING = buffer.constants.MAX_STRING_LENGTH;
2008
2008
  function noop() {}
@@ -2034,7 +2034,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2034
2034
  }
2035
2035
  var FinalizationRegistry2 = process.env.NODE_V8_COVERAGE ? FakeFinalizationRegistry : global.FinalizationRegistry || FakeFinalizationRegistry;
2036
2036
  var WeakRef2 = process.env.NODE_V8_COVERAGE ? FakeWeakRef : global.WeakRef || FakeWeakRef;
2037
- var registry = new FinalizationRegistry2((worker) => {
2037
+ var registry2 = new FinalizationRegistry2((worker) => {
2038
2038
  if (worker.exited) {
2039
2039
  return;
2040
2040
  }
@@ -2054,7 +2054,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2054
2054
  stateBuf: stream[kImpl].stateBuf,
2055
2055
  workerData: {
2056
2056
  $context: {
2057
- threadStreamVersion: version
2057
+ threadStreamVersion: version2
2058
2058
  },
2059
2059
  ...workerData
2060
2060
  }
@@ -2063,11 +2063,11 @@ var require_thread_stream = __commonJS((exports, module) => {
2063
2063
  worker.stream = new FakeWeakRef(stream);
2064
2064
  worker.on("message", onWorkerMessage);
2065
2065
  worker.on("exit", onWorkerExit);
2066
- registry.register(stream, worker);
2066
+ registry2.register(stream, worker);
2067
2067
  return worker;
2068
2068
  }
2069
2069
  function drain(stream) {
2070
- assert(!stream[kImpl].sync);
2070
+ assert2(!stream[kImpl].sync);
2071
2071
  if (stream[kImpl].needDrain) {
2072
2072
  stream[kImpl].needDrain = false;
2073
2073
  stream.emit("drain");
@@ -2159,7 +2159,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2159
2159
  if (stream === undefined) {
2160
2160
  return;
2161
2161
  }
2162
- registry.unregister(stream);
2162
+ registry2.unregister(stream);
2163
2163
  stream.worker.exited = true;
2164
2164
  stream.worker.off("exit", onWorkerExit);
2165
2165
  destroy(stream, code !== 0 ? new Error("the worker thread exited") : null);
@@ -2199,11 +2199,11 @@ var require_thread_stream = __commonJS((exports, module) => {
2199
2199
  write(data) {
2200
2200
  const dataBuf = Buffer.isBuffer(data) ? data : Buffer.from(data);
2201
2201
  if (this[kImpl].destroyed) {
2202
- error(this, new Error("the worker has exited"));
2202
+ error51(this, new Error("the worker has exited"));
2203
2203
  return false;
2204
2204
  }
2205
2205
  if (this[kImpl].ending) {
2206
- error(this, new Error("the worker is ending"));
2206
+ error51(this, new Error("the worker is ending"));
2207
2207
  return false;
2208
2208
  }
2209
2209
  if (this[kImpl].flushing && this[kImpl].bufLen + dataBuf.length >= MAX_STRING) {
@@ -2364,7 +2364,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2364
2364
  }
2365
2365
  callbacks.clear();
2366
2366
  }
2367
- function error(stream, err) {
2367
+ function error51(stream, err) {
2368
2368
  setImmediate(() => {
2369
2369
  stream.emit("error", err);
2370
2370
  });
@@ -2377,7 +2377,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2377
2377
  failPendingFlushCallbacks(stream, err);
2378
2378
  if (err) {
2379
2379
  stream[kImpl].errored = err;
2380
- error(stream, err);
2380
+ error51(stream, err);
2381
2381
  }
2382
2382
  if (!stream.worker.exited) {
2383
2383
  stream.worker.terminate().catch(() => {}).then(() => {
@@ -2814,14 +2814,14 @@ var require_tools = __commonJS((exports, module) => {
2814
2814
  }
2815
2815
  return point < 32 ? JSON.stringify(str) : '"' + result + '"';
2816
2816
  }
2817
- function asJson(obj, msg, num, time) {
2817
+ function asJson(obj, msg, num, time3) {
2818
2818
  if (asJsonChan.hasSubscribers === false) {
2819
- return _asJson.call(this, obj, msg, num, time);
2819
+ return _asJson.call(this, obj, msg, num, time3);
2820
2820
  }
2821
2821
  const store = { instance: this, arguments };
2822
- return asJsonChan.traceSync(_asJson, store, this, obj, msg, num, time);
2822
+ return asJsonChan.traceSync(_asJson, store, this, obj, msg, num, time3);
2823
2823
  }
2824
- function _asJson(obj, msg, num, time) {
2824
+ function _asJson(obj, msg, num, time3) {
2825
2825
  const stringify3 = this[stringifySym];
2826
2826
  const stringifySafe = this[stringifySafeSym];
2827
2827
  const stringifiers = this[stringifiersSym];
@@ -2831,7 +2831,7 @@ var require_tools = __commonJS((exports, module) => {
2831
2831
  const formatters = this[formattersSym];
2832
2832
  const messageKey = this[messageKeySym];
2833
2833
  const errorKey = this[errorKeySym];
2834
- let data = this[lsCacheSym][num] + time;
2834
+ let data = this[lsCacheSym][num] + time3;
2835
2835
  data = data + chindings;
2836
2836
  let value;
2837
2837
  if (formatters.log) {
@@ -3292,7 +3292,7 @@ var require_proto = __commonJS((exports, module) => {
3292
3292
  noop
3293
3293
  } = require_tools();
3294
3294
  var {
3295
- version
3295
+ version: version2
3296
3296
  } = require_meta();
3297
3297
  var redaction = require_redaction();
3298
3298
  var constructor = class Pino {
@@ -3304,7 +3304,7 @@ var require_proto = __commonJS((exports, module) => {
3304
3304
  setBindings,
3305
3305
  flush,
3306
3306
  isLevelEnabled,
3307
- version,
3307
+ version: version2,
3308
3308
  get level() {
3309
3309
  return this[getLevelSym]();
3310
3310
  },
@@ -3480,33 +3480,33 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
3480
3480
  }
3481
3481
  return JSON.stringify(str);
3482
3482
  }
3483
- function sort(array, comparator) {
3484
- if (array.length > 200 || comparator) {
3485
- return array.sort(comparator);
3483
+ function sort(array2, comparator) {
3484
+ if (array2.length > 200 || comparator) {
3485
+ return array2.sort(comparator);
3486
3486
  }
3487
- for (let i = 1;i < array.length; i++) {
3488
- const currentValue = array[i];
3487
+ for (let i = 1;i < array2.length; i++) {
3488
+ const currentValue = array2[i];
3489
3489
  let position = i;
3490
- while (position !== 0 && array[position - 1] > currentValue) {
3491
- array[position] = array[position - 1];
3490
+ while (position !== 0 && array2[position - 1] > currentValue) {
3491
+ array2[position] = array2[position - 1];
3492
3492
  position--;
3493
3493
  }
3494
- array[position] = currentValue;
3494
+ array2[position] = currentValue;
3495
3495
  }
3496
- return array;
3496
+ return array2;
3497
3497
  }
3498
3498
  var typedArrayPrototypeGetSymbolToStringTag = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(Object.getPrototypeOf(new Int8Array)), Symbol.toStringTag).get;
3499
3499
  function isTypedArrayWithEntries(value) {
3500
3500
  return typedArrayPrototypeGetSymbolToStringTag.call(value) !== undefined && value.length !== 0;
3501
3501
  }
3502
- function stringifyTypedArray(array, separator, maximumBreadth) {
3503
- if (array.length < maximumBreadth) {
3504
- maximumBreadth = array.length;
3502
+ function stringifyTypedArray(array2, separator, maximumBreadth) {
3503
+ if (array2.length < maximumBreadth) {
3504
+ maximumBreadth = array2.length;
3505
3505
  }
3506
3506
  const whitespace = separator === "," ? "" : " ";
3507
- let res = `"0":${whitespace}${array[0]}`;
3507
+ let res = `"0":${whitespace}${array2[0]}`;
3508
3508
  for (let i = 1;i < maximumBreadth; i++) {
3509
- res += `${separator}"${i}":${whitespace}${array[i]}`;
3509
+ res += `${separator}"${i}":${whitespace}${array2[i]}`;
3510
3510
  }
3511
3511
  return res;
3512
3512
  }
@@ -3566,11 +3566,11 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
3566
3566
  }
3567
3567
  return value === undefined ? Infinity : value;
3568
3568
  }
3569
- function getItemCount(number) {
3570
- if (number === 1) {
3569
+ function getItemCount(number4) {
3570
+ if (number4 === 1) {
3571
3571
  return "1 item";
3572
3572
  }
3573
- return `${number} items`;
3573
+ return `${number4} items`;
3574
3574
  }
3575
3575
  function getUniqueReplacerSet(replacerArray) {
3576
3576
  const replacerSet = new Set;
@@ -3609,7 +3609,7 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
3609
3609
  }
3610
3610
  }
3611
3611
  const circularValue = getCircularValueOption(options);
3612
- const bigint = getBooleanOption(options, "bigint");
3612
+ const bigint4 = getBooleanOption(options, "bigint");
3613
3613
  const deterministic = getDeterministicOption(options);
3614
3614
  const comparator = typeof deterministic === "function" ? deterministic : undefined;
3615
3615
  const maximumDepth = getPositiveIntegerOption(options, "maximumDepth");
@@ -3717,7 +3717,7 @@ ${originalIndentation}`;
3717
3717
  case "undefined":
3718
3718
  return;
3719
3719
  case "bigint":
3720
- if (bigint) {
3720
+ if (bigint4) {
3721
3721
  return String(value);
3722
3722
  }
3723
3723
  default:
@@ -3807,7 +3807,7 @@ ${originalIndentation}`;
3807
3807
  case "undefined":
3808
3808
  return;
3809
3809
  case "bigint":
3810
- if (bigint) {
3810
+ if (bigint4) {
3811
3811
  return String(value);
3812
3812
  }
3813
3813
  default:
@@ -3918,7 +3918,7 @@ ${originalIndentation}`;
3918
3918
  case "undefined":
3919
3919
  return;
3920
3920
  case "bigint":
3921
- if (bigint) {
3921
+ if (bigint4) {
3922
3922
  return String(value);
3923
3923
  }
3924
3924
  default:
@@ -4013,7 +4013,7 @@ ${originalIndentation}`;
4013
4013
  case "undefined":
4014
4014
  return;
4015
4015
  case "bigint":
4016
- if (bigint) {
4016
+ if (bigint4) {
4017
4017
  return String(value);
4018
4018
  }
4019
4019
  default:
@@ -4071,7 +4071,7 @@ var require_multistream = __commonJS((exports, module) => {
4071
4071
  minLevel: 0,
4072
4072
  lastId: 0,
4073
4073
  streams: [],
4074
- clone,
4074
+ clone: clone2,
4075
4075
  [metadata]: true,
4076
4076
  streamLevels
4077
4077
  };
@@ -4175,7 +4175,7 @@ var require_multistream = __commonJS((exports, module) => {
4175
4175
  stream.end();
4176
4176
  }
4177
4177
  }
4178
- function clone(level) {
4178
+ function clone2(level) {
4179
4179
  const streams = new Array(this.streams.length);
4180
4180
  for (let i = 0;i < streams.length; i++) {
4181
4181
  streams[i] = {
@@ -4189,7 +4189,7 @@ var require_multistream = __commonJS((exports, module) => {
4189
4189
  remove,
4190
4190
  minLevel: level,
4191
4191
  streams,
4192
- clone,
4192
+ clone: clone2,
4193
4193
  emit,
4194
4194
  flushSync,
4195
4195
  [metadata]: true
@@ -4217,7 +4217,7 @@ var require_pino = __commonJS((exports, module) => {
4217
4217
  var stdSerializers = require_pino_std_serializers();
4218
4218
  var caller = require_caller();
4219
4219
  var redaction = require_redaction();
4220
- var time = require_time();
4220
+ var time3 = require_time();
4221
4221
  var proto = require_proto();
4222
4222
  var symbols = require_symbols();
4223
4223
  var { configure } = require_safe_stable_stringify();
@@ -4232,7 +4232,7 @@ var require_pino = __commonJS((exports, module) => {
4232
4232
  normalizeDestFileDescriptor,
4233
4233
  noop
4234
4234
  } = require_tools();
4235
- var { version } = require_meta();
4235
+ var { version: version2 } = require_meta();
4236
4236
  var {
4237
4237
  chindingsSym,
4238
4238
  redactFmtSym,
@@ -4258,9 +4258,9 @@ var require_pino = __commonJS((exports, module) => {
4258
4258
  mixinMergeStrategySym,
4259
4259
  msgPrefixSym
4260
4260
  } = symbols;
4261
- var { epochTime, nullTime } = time;
4261
+ var { epochTime, nullTime } = time3;
4262
4262
  var { pid } = process;
4263
- var hostname = os.hostname();
4263
+ var hostname3 = os.hostname();
4264
4264
  var defaultErrorSerializer = stdSerializers.err;
4265
4265
  var defaultOptions = {
4266
4266
  level: "info",
@@ -4270,7 +4270,7 @@ var require_pino = __commonJS((exports, module) => {
4270
4270
  errorKey: "err",
4271
4271
  nestedKey: null,
4272
4272
  enabled: true,
4273
- base: { pid, hostname },
4273
+ base: { pid, hostname: hostname3 },
4274
4274
  serializers: Object.assign(Object.create(null), {
4275
4275
  err: defaultErrorSerializer
4276
4276
  }),
@@ -4278,8 +4278,8 @@ var require_pino = __commonJS((exports, module) => {
4278
4278
  bindings(bindings) {
4279
4279
  return bindings;
4280
4280
  },
4281
- level(label, number) {
4282
- return { level: number };
4281
+ level(label, number4) {
4282
+ return { level: number4 };
4283
4283
  }
4284
4284
  }),
4285
4285
  hooks: {
@@ -4353,8 +4353,8 @@ var require_pino = __commonJS((exports, module) => {
4353
4353
  chindings = coreChindings(Object.assign({}, base, { name }));
4354
4354
  }
4355
4355
  }
4356
- const time2 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime;
4357
- const timeSliceIndex = time2().indexOf(":") + 1;
4356
+ const time4 = timestamp instanceof Function ? timestamp : timestamp ? epochTime : nullTime;
4357
+ const timeSliceIndex = time4().indexOf(":") + 1;
4358
4358
  if (useOnlyCustomLevels && !customLevels)
4359
4359
  throw Error("customLevels is required if useOnlyCustomLevels is set true");
4360
4360
  if (mixin && typeof mixin !== "function")
@@ -4373,7 +4373,7 @@ var require_pino = __commonJS((exports, module) => {
4373
4373
  [levelCompSym]: levelCompFunc,
4374
4374
  [useOnlyCustomLevelsSym]: useOnlyCustomLevels,
4375
4375
  [streamSym]: stream,
4376
- [timeSym]: time2,
4376
+ [timeSym]: time4,
4377
4377
  [timeSliceIndexSym]: timeSliceIndex,
4378
4378
  [stringifySym]: stringify2,
4379
4379
  [stringifySafeSym]: stringifySafe,
@@ -4412,9 +4412,9 @@ var require_pino = __commonJS((exports, module) => {
4412
4412
  module.exports.multistream = require_multistream();
4413
4413
  module.exports.levels = mappings();
4414
4414
  module.exports.stdSerializers = serializers;
4415
- module.exports.stdTimeFunctions = Object.assign({}, time);
4415
+ module.exports.stdTimeFunctions = Object.assign({}, time3);
4416
4416
  module.exports.symbols = symbols;
4417
- module.exports.version = version;
4417
+ module.exports.version = version2;
4418
4418
  module.exports.default = pino;
4419
4419
  module.exports.pino = pino;
4420
4420
  });
@@ -4437,12 +4437,32 @@ function setModeFor(id) {
4437
4437
  return id === "acceptEdits" || id === "auto" ? id : undefined;
4438
4438
  }
4439
4439
 
4440
+ // src/plan/reviewer-notes.ts
4441
+ var NOTES_HEADING = "## Notes from the user";
4442
+ function reviewerNotesSection(notes) {
4443
+ const trimmed = notes.trim();
4444
+ if (trimmed === "")
4445
+ return "";
4446
+ return `
4447
+
4448
+ ---
4449
+
4450
+ ${NOTES_HEADING}
4451
+
4452
+ ${trimmed}
4453
+ `;
4454
+ }
4455
+ function appendReviewerNotes(plan, notes) {
4456
+ return plan + reviewerNotesSection(notes);
4457
+ }
4458
+
4440
4459
  // src/adapters/claude/feedback.ts
4441
4460
  function toHookOutput(input, updatedInput) {
4442
4461
  if (input.behavior === "allow") {
4443
4462
  const decision = { behavior: "allow" };
4444
4463
  if (updatedInput) {
4445
- decision.updatedInput = updatedInput;
4464
+ const notes = input.feedback?.trim();
4465
+ decision.updatedInput = notes && typeof updatedInput.plan === "string" ? { ...updatedInput, plan: appendReviewerNotes(updatedInput.plan, notes) } : updatedInput;
4446
4466
  }
4447
4467
  const mode = setModeFor(input.acceptMode);
4448
4468
  if (mode) {
@@ -4475,7 +4495,7 @@ function fatalDenyLine(reason) {
4475
4495
  import { homedir } from "os";
4476
4496
  import { join } from "path";
4477
4497
 
4478
- // src/json-file.ts
4498
+ // src/lib/json-file.ts
4479
4499
  import { readFileSync } from "fs";
4480
4500
  import { readFile } from "fs/promises";
4481
4501
  function readJsonFileSync(path) {
@@ -4558,6 +4578,7 @@ function toolInputEcho(input) {
4558
4578
  return Object.keys(echo).length > 0 ? echo : undefined;
4559
4579
  }
4560
4580
  var claudeAdapter = {
4581
+ id: "claude",
4561
4582
  approveVariants: APPROVE_VARIANTS,
4562
4583
  parseHookInput(stdin) {
4563
4584
  let hook;
@@ -4616,9 +4637,9 @@ function fatalDenyLine2(reason) {
4616
4637
  }
4617
4638
 
4618
4639
  // src/adapters/codex/install.ts
4640
+ import { readFileSync as readFileSync2 } from "fs";
4619
4641
  import { homedir as homedir2 } from "os";
4620
4642
  import { join as join2 } from "path";
4621
- import { readFileSync as readFileSync2 } from "fs";
4622
4643
 
4623
4644
  // node_modules/.bun/smol-toml@1.6.1/node_modules/smol-toml/dist/error.js
4624
4645
  /*!
@@ -5612,6 +5633,7 @@ function containsCaretHookCommand(value) {
5612
5633
 
5613
5634
  // src/adapters/codex/index.ts
5614
5635
  var codexAdapter = {
5636
+ id: "codex",
5615
5637
  approveVariants: APPROVE_VARIANTS2,
5616
5638
  parseHookInput(stdin) {
5617
5639
  let hook;
@@ -5641,7 +5663,8 @@ var APPROVE_VARIANTS3 = [
5641
5663
  // src/adapters/opencode/feedback.ts
5642
5664
  function toWireDecision(input) {
5643
5665
  if (input.behavior === "allow") {
5644
- return { behavior: "allow" };
5666
+ const notes = input.feedback?.trim();
5667
+ return notes ? { behavior: "allow", feedback: notes } : { behavior: "allow" };
5645
5668
  }
5646
5669
  return { behavior: "deny", feedback: input.feedback?.trim() || "Plan changes requested." };
5647
5670
  }
@@ -7057,6 +7080,7 @@ function readCaretInPluginArray(dir) {
7057
7080
 
7058
7081
  // src/adapters/opencode/index.ts
7059
7082
  var opencodeAdapter = {
7083
+ id: "opencode",
7060
7084
  approveVariants: APPROVE_VARIANTS3,
7061
7085
  parseHookInput(stdin) {
7062
7086
  let hook;
@@ -7118,812 +7142,255 @@ function fatalDeny(reason) {
7118
7142
  return fatalDenyLine(reason);
7119
7143
  }
7120
7144
 
7121
- // src/build-id.ts
7122
- import { createHash } from "crypto";
7123
- // package.json
7124
- var package_default = {
7125
- name: "@macintacos/caret",
7126
- version: "0.4.1",
7127
- license: "MIT",
7128
- type: "module",
7129
- description: "A Claude Code plugin that replaces the terminal plan-approval prompt with a local web UI for inline review, annotation, and approval.",
7130
- main: "./opencode/index.ts",
7131
- exports: {
7132
- ".": "./opencode/index.ts"
7133
- },
7134
- bin: {
7135
- caret: "./bin/caret"
7136
- },
7137
- homepage: "https://github.com/macintacos/caret",
7138
- repository: {
7139
- type: "git",
7140
- url: "git+https://github.com/macintacos/caret.git"
7141
- },
7142
- publishConfig: {
7143
- access: "public"
7144
- },
7145
- files: [
7146
- "dist/",
7147
- "ui/dist/",
7148
- "bin/caret",
7149
- "hooks/",
7150
- "commands/",
7151
- "opencode/",
7152
- ".claude-plugin/plugin.json"
7153
- ],
7154
- scripts: {
7155
- test: "bun test --conditions browser",
7156
- lint: "mise run lint",
7157
- format: "mise run format",
7158
- build: "mise run build"
7159
- },
7160
- devDependencies: {
7161
- "@happy-dom/global-registrator": "^20.9.0",
7162
- "@playwright/test": "^1.60.0",
7163
- "@sveltejs/vite-plugin-svelte": "^7.1.2",
7164
- "@tailwindcss/vite": "^4.3.2",
7165
- "@types/bun": "^1.3.14",
7166
- "@types/semver": "^7.7.1",
7167
- "happy-dom": "^20.9.0",
7168
- listr2: "^10.2.1",
7169
- "pino-pretty": "^13.1.3",
7170
- svelte: "^5.55.9",
7171
- "svelte-check": "^4.4.8",
7172
- tailwindcss: "^4.3.2",
7173
- "tw-animate-css": "^1.4.0",
7174
- typescript: "^6.0.3",
7175
- vite: "^8.0.14"
7176
- },
7177
- dependencies: {
7178
- "@codemirror/commands": "^6.10.3",
7179
- "@codemirror/lang-markdown": "^6.5.0",
7180
- "@codemirror/language": "^6.12.3",
7181
- "@codemirror/language-data": "^6.5.2",
7182
- "@codemirror/state": "^6.6.0",
7183
- "@codemirror/view": "^6.43.0",
7184
- "@commander-js/extra-typings": "^15.0.0",
7185
- "@internationalized/date": "^3.12.2",
7186
- "@lezer/highlight": "^1.2.3",
7187
- "@opencode-ai/plugin": "^1.16.2",
7188
- "@pierre/diffs": "1.2.7",
7189
- "bits-ui": "^2.18.1",
7190
- clsx: "^2.1.1",
7191
- commander: "^15.0.0",
7192
- "jsonc-parser": "^3.3.1",
7193
- marked: "^18.0.4",
7194
- pino: "^10.3.1",
7195
- prettier: "3.8.3",
7196
- semver: "^7.8.1",
7197
- shiki: "^4.1.0",
7198
- "smol-toml": "1.6.1",
7199
- "tailwind-merge": "^3.6.0",
7200
- "tailwind-variants": "^3.2.2",
7201
- xss: "^1.0.15",
7202
- zod: "4.4.3"
7203
- }
7204
- };
7205
-
7206
- // src/ui-assets.ts
7207
- import { readdirSync } from "fs";
7208
- import { dirname, join as join5, relative } from "path";
7209
- import { fileURLToPath } from "url";
7210
- function fromPathMap(map) {
7211
- const paths = Object.keys(map).sort();
7212
- return {
7213
- paths,
7214
- file(urlPath) {
7215
- const filePath = map[urlPath];
7216
- return filePath ? Bun.file(filePath) : undefined;
7217
- }
7218
- };
7219
- }
7220
- function assetsFromDist(distDir) {
7221
- const map = {};
7222
- const walk = (dir) => {
7223
- for (const ent of readdirSync(dir, { withFileTypes: true })) {
7224
- const full = join5(dir, ent.name);
7225
- if (ent.isDirectory())
7226
- walk(full);
7227
- else if (ent.isFile())
7228
- map[`/${relative(distDir, full).split("\\").join("/")}`] = full;
7229
- }
7230
- };
7231
- try {
7232
- walk(distDir);
7233
- } catch {
7234
- return;
7235
- }
7236
- return Object.keys(map).length > 0 ? fromPathMap(map) : undefined;
7237
- }
7238
- async function loadUiAssets() {
7239
- try {
7240
- const mod = await import("./ui-manifest.generated.ts");
7241
- if (mod.UI_MANIFEST && Object.keys(mod.UI_MANIFEST).length > 0) {
7242
- return fromPathMap(mod.UI_MANIFEST);
7243
- }
7244
- } catch {}
7245
- const srcDist = fileURLToPath(new URL("../ui/dist", import.meta.url));
7246
- const fromSrc = assetsFromDist(srcDist);
7247
- if (fromSrc)
7248
- return fromSrc;
7249
- const besideDist = join5(dirname(process.execPath), "ui");
7250
- return assetsFromDist(besideDist);
7251
- }
7252
-
7253
- // src/build-id.ts
7254
- var VERSION = package_default.version;
7255
- var IDENTITY = { service: "caret", version: VERSION };
7256
- function buildKind(argv1 = process.argv[1]) {
7257
- if (argv1?.endsWith(".ts"))
7258
- return "dev";
7259
- if (argv1?.endsWith(".js"))
7260
- return "bundle";
7261
- return "binary";
7262
- }
7263
- function isCompiledBinary() {
7264
- return buildKind() !== "dev";
7265
- }
7266
- async function buildHash(assets) {
7267
- if (!assets || assets.paths.length === 0)
7268
- return "no-ui";
7269
- const h = createHash("sha256");
7270
- for (const urlPath of assets.paths) {
7271
- const bytes = await assets.file(urlPath)?.bytes() ?? new Uint8Array;
7272
- h.update(`${urlPath}\x00${bytes.length}\x00`);
7273
- h.update(bytes);
7274
- }
7275
- return h.digest("hex").slice(0, 12);
7276
- }
7277
- async function computeBuildId(deps) {
7278
- if (deps.kind !== "dev") {
7279
- const h = await deps.hashFile();
7280
- if (h)
7281
- return h;
7282
- }
7283
- return deps.uiHash();
7284
- }
7285
- var cachedBuildId;
7286
- async function currentBuildId() {
7287
- if (cachedBuildId !== undefined)
7288
- return cachedBuildId;
7289
- const kind = buildKind();
7290
- cachedBuildId = await computeBuildId({
7291
- kind,
7292
- hashFile: async () => {
7293
- try {
7294
- const target = kind === "bundle" ? process.argv[1] : process.execPath;
7295
- const bytes = await Bun.file(target).bytes();
7296
- return createHash("sha256").update(bytes).digest("hex").slice(0, 12);
7297
- } catch {
7298
- return null;
7299
- }
7300
- },
7301
- uiHash: async () => buildHash(await loadUiAssets())
7302
- });
7303
- return cachedBuildId;
7304
- }
7305
- function resolveCommit(deps) {
7306
- if (deps.baked)
7307
- return deps.baked;
7308
- return deps.gitHead() || "unknown";
7309
- }
7310
- var cachedCommit;
7311
- function currentCommit() {
7312
- if (cachedCommit !== undefined)
7313
- return cachedCommit;
7314
- cachedCommit = resolveCommit({
7315
- baked: process.env.CARET_BUILD_COMMIT,
7316
- gitHead: () => {
7317
- try {
7318
- const r = Bun.spawnSync(["git", "-C", import.meta.dir, "rev-parse", "HEAD"]);
7319
- if (r.exitCode !== 0)
7320
- return null;
7321
- const out = r.stdout.toString().trim();
7322
- return out.length > 0 ? out : null;
7323
- } catch {
7324
- return null;
7325
- }
7326
- }
7327
- });
7328
- return cachedCommit;
7329
- }
7330
-
7331
7145
  // src/commands/daemon.ts
7332
7146
  import { randomUUID } from "crypto";
7333
7147
  import { existsSync as existsSync4, unlinkSync as unlinkSync3 } from "fs";
7334
7148
 
7335
- // src/daemon-lifecycle.ts
7336
- import { openSync, unlinkSync } from "fs";
7337
- import { normalize } from "path";
7338
-
7339
- // src/daemon-client.ts
7340
- async function httpHealth(baseUrl) {
7341
- try {
7342
- const res = await fetch(`${baseUrl}/api/health`, {
7343
- signal: AbortSignal.timeout(500)
7344
- });
7345
- if (!res.ok)
7346
- return null;
7347
- return await res.json();
7348
- } catch {
7349
- return null;
7350
- }
7351
- }
7352
- async function postReview(baseUrl, input) {
7353
- const res = await fetch(`${baseUrl}/api/reviews`, {
7354
- method: "POST",
7355
- headers: { "Content-Type": "application/json" },
7356
- body: JSON.stringify(input)
7357
- });
7358
- if (!res.ok)
7359
- throw new Error(`POST /api/reviews failed: ${res.status}`);
7360
- return await res.json();
7361
- }
7362
- async function expireReview(baseUrl, id) {
7363
- const res = await fetch(`${baseUrl}/api/reviews/${id}/expire`, {
7364
- method: "POST",
7365
- signal: AbortSignal.timeout(1000)
7366
- });
7367
- if (!res.ok && res.status !== 404)
7368
- throw new Error(`POST /expire failed: ${res.status}`);
7369
- }
7370
- async function longPoll(baseUrl, id) {
7371
- const res = await fetch(`${baseUrl}/api/reviews/${id}/decision`);
7372
- if (res.status === 204)
7373
- return null;
7374
- if (!res.ok)
7375
- throw new Error(`decision long-poll failed: ${res.status}`);
7376
- return await res.json();
7377
- }
7378
- async function listReviews(baseUrl) {
7379
- const res = await fetch(`${baseUrl}/api/reviews`, { signal: AbortSignal.timeout(1000) });
7380
- if (!res.ok)
7381
- throw new Error(`GET /api/reviews failed: ${res.status}`);
7382
- return await res.json();
7383
- }
7384
- async function resolveReview(baseUrl, id, body) {
7385
- const res = await fetch(`${baseUrl}/api/reviews/${id}/resolve`, {
7386
- method: "POST",
7387
- headers: { "Content-Type": "application/json" },
7388
- body: JSON.stringify(body),
7389
- signal: AbortSignal.timeout(1000)
7390
- });
7391
- if (!res.ok)
7392
- throw new Error(`POST /resolve failed: ${res.status}`);
7393
- }
7149
+ // src/config/settings.ts
7150
+ import { readFileSync as readFileSync5, statSync } from "fs";
7394
7151
 
7395
- // src/log.ts
7396
- var import_pino = __toESM(require_pino(), 1);
7397
-
7398
- // src/caller-location.ts
7399
- import { dirname as dirname2 } from "path";
7400
- var PKG_ROOT = dirname2(import.meta.dir);
7401
- var FRAME = /^\s*at (?:.* \()?(?:file:\/\/)?(.+):(\d+):\d+\)?$/;
7402
- var INTERNAL_SUFFIXES = ["src/caller-location.ts", "src/log.ts"];
7403
- function parseCaller(stack, pkgRoot = PKG_ROOT) {
7404
- if (!stack)
7405
- return;
7406
- for (const line of stack.split(`
7407
- `)) {
7408
- const m = FRAME.exec(line);
7409
- if (!m?.[1] || !m[2])
7410
- continue;
7411
- const path = m[1];
7412
- if (INTERNAL_SUFFIXES.some((s) => path.endsWith(s)))
7413
- continue;
7414
- if (!path.includes("/") || path.startsWith("node:"))
7415
- continue;
7416
- const rel = !path.startsWith("/") ? path : path.startsWith(`${pkgRoot}/`) ? path.slice(pkgRoot.length + 1) : path.split("/").slice(-2).join("/");
7417
- return `${rel}:${m[2]}`;
7418
- }
7419
- return;
7420
- }
7421
- function callerLocation() {
7422
- try {
7423
- return parseCaller(new Error().stack);
7424
- } catch {
7425
- return;
7426
- }
7427
- }
7428
-
7429
- // src/paths.ts
7430
- import { chmodSync, mkdirSync } from "fs";
7431
- import { homedir as homedir4 } from "os";
7432
- function xdgDir(envVar, fallback) {
7433
- const base = process.env[envVar] || `${homedir4()}/${fallback}`;
7434
- return `${base}/caret`;
7435
- }
7436
- function stateDir() {
7437
- return xdgDir("XDG_STATE_HOME", ".local/state");
7438
- }
7439
- function reviewsDir() {
7440
- return `${stateDir()}/reviews`;
7441
- }
7442
- function configDir() {
7443
- return xdgDir("XDG_CONFIG_HOME", ".config");
7444
- }
7445
- function configFile() {
7446
- return `${configDir()}/config.toml`;
7447
- }
7448
- function prefsFile() {
7449
- return `${stateDir()}/prefs.json`;
7450
- }
7451
- function logFile() {
7452
- return `${stateDir()}/caret.log`;
7453
- }
7454
- function daemonLogFile() {
7455
- return `${stateDir()}/daemon.log`;
7456
- }
7457
- function daemonLock() {
7458
- return `${stateDir()}/daemon.lock`;
7459
- }
7460
- function ensureStateDir(target = stateDir()) {
7461
- mkdirSync(target, { recursive: true, mode: 448 });
7462
- chmodSync(target, 448);
7463
- const root = stateDir();
7464
- if (target !== root && target.startsWith(`${root}/`)) {
7465
- mkdirSync(root, { recursive: true, mode: 448 });
7466
- chmodSync(root, 448);
7467
- }
7468
- }
7469
-
7470
- // src/redact-core.ts
7471
- var CENSOR = "<redacted>";
7472
- var DENY_KEYS = new Set(["plan", "prompt", "feedback"]);
7473
- var MAX_DEPTH = 6;
7474
- function scrubGraph(v, scrubStr) {
7475
- return walk(v, scrubStr, 0, new WeakSet);
7476
- }
7477
- function walk(v, scrubStr, depth, seen) {
7478
- if (typeof v === "string")
7479
- return scrubStr ? scrubStr(v) : v;
7480
- if (v === null || typeof v !== "object")
7481
- return v;
7482
- if (seen.has(v))
7483
- return "<cyclic>";
7484
- if (depth >= MAX_DEPTH)
7485
- return "<depth-capped>";
7486
- seen.add(v);
7487
- let out;
7488
- if (Array.isArray(v)) {
7489
- out = v.map((el) => walk(el, scrubStr, depth + 1, seen));
7490
- } else {
7491
- const obj = {};
7492
- for (const [k, val] of Object.entries(v)) {
7493
- obj[k] = DENY_KEYS.has(k) ? CENSOR : walk(val, scrubStr, depth + 1, seen);
7494
- }
7495
- out = obj;
7496
- }
7497
- seen.delete(v);
7498
- return out;
7499
- }
7500
- function shortId(id) {
7501
- return id.slice(0, 8);
7502
- }
7503
-
7504
- // src/redact.ts
7505
- import { readFileSync as readFileSync4, writeFileSync } from "fs";
7506
- import { homedir as homedir5 } from "os";
7507
- var FOREIGN_HOME = /(\/Users\/|\/home\/)[^/\s"']+/g;
7508
- function scrubString(s, home = homedir5()) {
7509
- const dehomed = home.length > 1 ? s.replaceAll(home, "~") : s;
7510
- return dehomed.replace(FOREIGN_HOME, `$1${CENSOR}`);
7511
- }
7512
- function scrubValue(v, redact) {
7513
- return scrubGraph(v, redact ? scrubString : undefined);
7514
- }
7515
- function redactLogText(text) {
7516
- return text.split(`
7517
- `).map((line) => {
7518
- if (line.startsWith("{")) {
7519
- try {
7520
- return JSON.stringify(scrubValue(JSON.parse(line), true));
7521
- } catch {}
7522
- }
7523
- return scrubString(line);
7524
- }).join(`
7525
- `);
7526
- }
7527
- function redactLogFiles(files = [logFile(), daemonLogFile()]) {
7528
- const written = [];
7529
- for (const file of files) {
7530
- let text;
7531
- try {
7532
- text = readFileSync4(file, "utf-8");
7533
- } catch {
7534
- continue;
7535
- }
7536
- const sibling = `${file.replace(/\.log$/, "")}.redacted.log`;
7537
- writeFileSync(sibling, redactLogText(text), { mode: 384 });
7538
- written.push(sibling);
7539
- }
7540
- return written;
7541
- }
7542
-
7543
- // src/types.ts
7544
- function errorMessage(err) {
7545
- return err instanceof Error ? err.message : String(err);
7546
- }
7547
- function isUnresolved(status) {
7548
- return status === "pending" || status === "rejected";
7549
- }
7550
- function currentVersion(review) {
7551
- const v = review.versions[review.versions.length - 1];
7552
- if (!v)
7553
- throw new Error(`review ${review.id} has no versions`);
7554
- return v;
7555
- }
7556
- function toClientReview(review) {
7557
- const cur = currentVersion(review);
7558
- return {
7559
- id: review.id,
7560
- sessionId: review.sessionId,
7561
- cwd: review.cwd,
7562
- title: review.title,
7563
- status: review.status,
7564
- planEpoch: review.planEpoch,
7565
- version: cur.version,
7566
- currentPlan: cur.plan,
7567
- annotations: cur.annotations,
7568
- versions: review.versions,
7569
- generalCommentDraft: review.generalCommentDraft ?? "",
7570
- composerScratches: cur.composerScratches ?? [],
7571
- createdAt: review.createdAt,
7572
- updatedAt: review.updatedAt,
7573
- decision: review.decision
7574
- };
7575
- }
7576
-
7577
- // src/log.ts
7578
- var pinoOpts = {
7579
- base: undefined,
7580
- timestamp: import_pino.default.stdTimeFunctions.isoTime,
7581
- serializers: { err: (v) => v }
7582
- };
7583
- function wrap(logger, liveLevel, liveRedact, source) {
7584
- function fields(extra, step, redact) {
7585
- const out = scrubValue({ ...extra }, redact);
7586
- out.step = step;
7587
- if (out.source == null) {
7588
- out.source = source;
7589
- const caller = callerLocation();
7590
- if (caller !== undefined)
7591
- out.caller = redact ? scrubString(caller) : caller;
7592
- }
7593
- return out;
7594
- }
7595
- function emit(method, step, msg, extra) {
7596
- try {
7597
- const next = liveLevel();
7598
- if (logger.level !== next)
7599
- logger.level = next;
7600
- if (!logger.isLevelEnabled(method))
7601
- return;
7602
- const r = liveRedact();
7603
- logger[method](fields(extra, step, r), r ? scrubString(msg) : msg);
7604
- } catch {}
7605
- }
7606
- return {
7607
- debug: (step, msg, extra) => emit("debug", step, msg, extra),
7608
- info: (step, msg, extra) => emit("info", step, msg, extra),
7609
- warn: (step, msg, extra) => emit("warn", step, msg, extra),
7610
- error(step, err, extra) {
7611
- try {
7612
- const r = liveRedact();
7613
- const f = fields(extra, step, r);
7614
- if (err instanceof Error)
7615
- f.err = scrubValue(import_pino.default.stdSerializers.errWithCause(err), r);
7616
- const msg = errorMessage(err);
7617
- logger.error(f, r ? scrubString(msg) : msg);
7618
- } catch {}
7619
- }
7620
- };
7621
- }
7622
- var noopLogger = {
7623
- debug: () => {},
7624
- info: () => {},
7625
- warn: () => {},
7626
- error: () => {}
7627
- };
7628
- function createHookLogger(level, redact) {
7629
- const path = logFile();
7630
- try {
7631
- ensureStateDir();
7632
- const dest = import_pino.default.destination({ dest: path, sync: true, mode: 384 });
7633
- return { log: wrap(import_pino.default(pinoOpts, dest), level, redact, "hook"), dest, path };
7634
- } catch {
7635
- return { log: noopLogger, dest: null, path };
7636
- }
7637
- }
7638
- var hookState = { level: "info", redact: false, instance: null };
7639
- function hook() {
7640
- const path = logFile();
7641
- if (hookState.instance && hookState.instance.path === path) {
7642
- return hookState.instance.log;
7643
- }
7644
- try {
7645
- hookState.instance?.dest?.destroy();
7646
- } catch {}
7647
- const next = createHookLogger(() => hookState.level, () => hookState.redact);
7648
- hookState.instance = next.dest ? next : null;
7649
- return next.log;
7650
- }
7651
- function setLogLevel(level) {
7652
- hookState.level = level;
7653
- }
7654
- function setRedact(on) {
7655
- hookState.redact = on;
7656
- }
7657
- function logDebug(step, msg, extra) {
7658
- hook().debug(step, msg, extra);
7659
- }
7660
- function logInfo(step, msg, extra) {
7661
- hook().info(step, msg, extra);
7662
- }
7663
- function logWarn(step, msg, extra) {
7664
- hook().warn(step, msg, extra);
7665
- }
7666
- function logError(step, err, ctx) {
7667
- hook().error(step, err, ctx);
7668
- }
7669
- function createDaemonLogger(level, dest, redact = () => false) {
7670
- try {
7671
- const target = import_pino.default.destination({
7672
- ...dest === undefined ? { fd: 2 } : { dest },
7673
- sync: true
7674
- });
7675
- const logger = import_pino.default({ ...pinoOpts, base: { pid: process.pid } }, target);
7676
- return wrap(logger, level, redact, "daemon");
7677
- } catch {
7678
- return noopLogger;
7679
- }
7680
- }
7681
-
7682
- // src/settings.ts
7683
- import { readFileSync as readFileSync5, statSync } from "fs";
7684
-
7685
- // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
7686
- var exports_external = {};
7687
- __export(exports_external, {
7688
- xor: () => xor,
7689
- xid: () => xid2,
7690
- void: () => _void2,
7691
- uuidv7: () => uuidv7,
7692
- uuidv6: () => uuidv6,
7693
- uuidv4: () => uuidv4,
7694
- uuid: () => uuid2,
7695
- util: () => exports_util,
7696
- url: () => url,
7697
- uppercase: () => _uppercase,
7698
- unknown: () => unknown,
7699
- union: () => union,
7700
- undefined: () => _undefined3,
7701
- ulid: () => ulid2,
7702
- uint64: () => uint64,
7703
- uint32: () => uint32,
7704
- tuple: () => tuple,
7705
- trim: () => _trim,
7706
- treeifyError: () => treeifyError,
7707
- transform: () => transform,
7708
- toUpperCase: () => _toUpperCase,
7709
- toLowerCase: () => _toLowerCase,
7710
- toJSONSchema: () => toJSONSchema,
7711
- templateLiteral: () => templateLiteral,
7712
- symbol: () => symbol,
7713
- superRefine: () => superRefine,
7714
- success: () => success,
7715
- stringbool: () => stringbool,
7716
- stringFormat: () => stringFormat,
7717
- string: () => string2,
7718
- strictObject: () => strictObject,
7719
- startsWith: () => _startsWith,
7720
- slugify: () => _slugify,
7721
- size: () => _size,
7722
- setErrorMap: () => setErrorMap,
7723
- set: () => set,
7724
- safeParseAsync: () => safeParseAsync2,
7725
- safeParse: () => safeParse2,
7726
- safeEncodeAsync: () => safeEncodeAsync2,
7727
- safeEncode: () => safeEncode2,
7728
- safeDecodeAsync: () => safeDecodeAsync2,
7729
- safeDecode: () => safeDecode2,
7730
- registry: () => registry,
7731
- regexes: () => exports_regexes,
7732
- regex: () => _regex,
7733
- refine: () => refine,
7734
- record: () => record,
7735
- readonly: () => readonly,
7736
- property: () => _property,
7737
- promise: () => promise,
7738
- prettifyError: () => prettifyError,
7739
- preprocess: () => preprocess,
7740
- prefault: () => prefault,
7741
- positive: () => _positive,
7742
- pipe: () => pipe,
7743
- partialRecord: () => partialRecord,
7744
- parseAsync: () => parseAsync2,
7745
- parse: () => parse6,
7746
- overwrite: () => _overwrite,
7747
- optional: () => optional,
7748
- object: () => object,
7749
- number: () => number2,
7750
- nullish: () => nullish2,
7751
- nullable: () => nullable,
7752
- null: () => _null3,
7753
- normalize: () => _normalize,
7754
- nonpositive: () => _nonpositive,
7755
- nonoptional: () => nonoptional,
7756
- nonnegative: () => _nonnegative,
7757
- never: () => never,
7758
- negative: () => _negative,
7759
- nativeEnum: () => nativeEnum,
7760
- nanoid: () => nanoid2,
7761
- nan: () => nan,
7762
- multipleOf: () => _multipleOf,
7763
- minSize: () => _minSize,
7764
- minLength: () => _minLength,
7765
- mime: () => _mime,
7766
- meta: () => meta2,
7767
- maxSize: () => _maxSize,
7768
- maxLength: () => _maxLength,
7769
- map: () => map,
7770
- mac: () => mac2,
7771
- lte: () => _lte,
7772
- lt: () => _lt,
7773
- lowercase: () => _lowercase,
7774
- looseRecord: () => looseRecord,
7775
- looseObject: () => looseObject,
7776
- locales: () => exports_locales,
7777
- literal: () => literal,
7778
- length: () => _length,
7779
- lazy: () => lazy,
7780
- ksuid: () => ksuid2,
7781
- keyof: () => keyof,
7782
- jwt: () => jwt,
7783
- json: () => json,
7784
- iso: () => exports_iso,
7785
- ipv6: () => ipv62,
7786
- ipv4: () => ipv42,
7787
- invertCodec: () => invertCodec,
7788
- intersection: () => intersection,
7789
- int64: () => int64,
7790
- int32: () => int32,
7791
- int: () => int,
7792
- instanceof: () => _instanceof,
7793
- includes: () => _includes,
7794
- httpUrl: () => httpUrl,
7795
- hostname: () => hostname2,
7796
- hex: () => hex2,
7797
- hash: () => hash,
7798
- guid: () => guid2,
7799
- gte: () => _gte,
7800
- gt: () => _gt,
7801
- globalRegistry: () => globalRegistry,
7802
- getErrorMap: () => getErrorMap,
7803
- function: () => _function,
7804
- fromJSONSchema: () => fromJSONSchema,
7805
- formatError: () => formatError,
7806
- float64: () => float64,
7807
- float32: () => float32,
7808
- flattenError: () => flattenError,
7809
- file: () => file,
7810
- exactOptional: () => exactOptional,
7811
- enum: () => _enum2,
7812
- endsWith: () => _endsWith,
7813
- encodeAsync: () => encodeAsync2,
7814
- encode: () => encode2,
7815
- emoji: () => emoji2,
7816
- email: () => email2,
7817
- e164: () => e1642,
7818
- discriminatedUnion: () => discriminatedUnion,
7819
- describe: () => describe2,
7820
- decodeAsync: () => decodeAsync2,
7821
- decode: () => decode2,
7822
- date: () => date3,
7823
- custom: () => custom,
7824
- cuid2: () => cuid22,
7825
- cuid: () => cuid3,
7826
- core: () => exports_core2,
7827
- config: () => config,
7828
- coerce: () => exports_coerce,
7829
- codec: () => codec,
7830
- clone: () => clone,
7831
- cidrv6: () => cidrv62,
7832
- cidrv4: () => cidrv42,
7833
- check: () => check,
7834
- catch: () => _catch2,
7835
- boolean: () => boolean2,
7836
- bigint: () => bigint2,
7837
- base64url: () => base64url2,
7838
- base64: () => base642,
7839
- array: () => array,
7840
- any: () => any,
7841
- _function: () => _function,
7842
- _default: () => _default2,
7843
- _ZodString: () => _ZodString,
7844
- ZodXor: () => ZodXor,
7845
- ZodXID: () => ZodXID,
7846
- ZodVoid: () => ZodVoid,
7847
- ZodUnknown: () => ZodUnknown,
7848
- ZodUnion: () => ZodUnion,
7849
- ZodUndefined: () => ZodUndefined,
7850
- ZodUUID: () => ZodUUID,
7851
- ZodURL: () => ZodURL,
7852
- ZodULID: () => ZodULID,
7853
- ZodType: () => ZodType,
7854
- ZodTuple: () => ZodTuple,
7855
- ZodTransform: () => ZodTransform,
7856
- ZodTemplateLiteral: () => ZodTemplateLiteral,
7857
- ZodSymbol: () => ZodSymbol,
7858
- ZodSuccess: () => ZodSuccess,
7859
- ZodStringFormat: () => ZodStringFormat,
7860
- ZodString: () => ZodString,
7861
- ZodSet: () => ZodSet,
7862
- ZodRecord: () => ZodRecord,
7863
- ZodRealError: () => ZodRealError,
7864
- ZodReadonly: () => ZodReadonly,
7865
- ZodPromise: () => ZodPromise,
7866
- ZodPreprocess: () => ZodPreprocess,
7867
- ZodPrefault: () => ZodPrefault,
7868
- ZodPipe: () => ZodPipe,
7869
- ZodOptional: () => ZodOptional,
7870
- ZodObject: () => ZodObject,
7871
- ZodNumberFormat: () => ZodNumberFormat,
7872
- ZodNumber: () => ZodNumber,
7873
- ZodNullable: () => ZodNullable,
7874
- ZodNull: () => ZodNull,
7875
- ZodNonOptional: () => ZodNonOptional,
7876
- ZodNever: () => ZodNever,
7877
- ZodNanoID: () => ZodNanoID,
7878
- ZodNaN: () => ZodNaN,
7879
- ZodMap: () => ZodMap,
7880
- ZodMAC: () => ZodMAC,
7881
- ZodLiteral: () => ZodLiteral,
7882
- ZodLazy: () => ZodLazy,
7883
- ZodKSUID: () => ZodKSUID,
7884
- ZodJWT: () => ZodJWT,
7885
- ZodIssueCode: () => ZodIssueCode,
7886
- ZodIntersection: () => ZodIntersection,
7887
- ZodISOTime: () => ZodISOTime,
7888
- ZodISODuration: () => ZodISODuration,
7889
- ZodISODateTime: () => ZodISODateTime,
7890
- ZodISODate: () => ZodISODate,
7891
- ZodIPv6: () => ZodIPv6,
7892
- ZodIPv4: () => ZodIPv4,
7893
- ZodGUID: () => ZodGUID,
7894
- ZodFunction: () => ZodFunction,
7895
- ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
7896
- ZodFile: () => ZodFile,
7897
- ZodExactOptional: () => ZodExactOptional,
7898
- ZodError: () => ZodError,
7899
- ZodEnum: () => ZodEnum,
7900
- ZodEmoji: () => ZodEmoji,
7901
- ZodEmail: () => ZodEmail,
7902
- ZodE164: () => ZodE164,
7903
- ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
7904
- ZodDefault: () => ZodDefault,
7905
- ZodDate: () => ZodDate,
7906
- ZodCustomStringFormat: () => ZodCustomStringFormat,
7907
- ZodCustom: () => ZodCustom,
7908
- ZodCodec: () => ZodCodec,
7909
- ZodCatch: () => ZodCatch,
7910
- ZodCUID2: () => ZodCUID2,
7911
- ZodCUID: () => ZodCUID,
7912
- ZodCIDRv6: () => ZodCIDRv6,
7913
- ZodCIDRv4: () => ZodCIDRv4,
7914
- ZodBoolean: () => ZodBoolean,
7915
- ZodBigIntFormat: () => ZodBigIntFormat,
7916
- ZodBigInt: () => ZodBigInt,
7917
- ZodBase64URL: () => ZodBase64URL,
7918
- ZodBase64: () => ZodBase64,
7919
- ZodArray: () => ZodArray,
7920
- ZodAny: () => ZodAny,
7921
- TimePrecision: () => TimePrecision,
7922
- NEVER: () => NEVER,
7923
- $output: () => $output,
7924
- $input: () => $input,
7925
- $brand: () => $brand
7926
- });
7152
+ // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
7153
+ var exports_external = {};
7154
+ __export(exports_external, {
7155
+ xor: () => xor,
7156
+ xid: () => xid2,
7157
+ void: () => _void2,
7158
+ uuidv7: () => uuidv7,
7159
+ uuidv6: () => uuidv6,
7160
+ uuidv4: () => uuidv4,
7161
+ uuid: () => uuid2,
7162
+ util: () => exports_util,
7163
+ url: () => url,
7164
+ uppercase: () => _uppercase,
7165
+ unknown: () => unknown,
7166
+ union: () => union,
7167
+ undefined: () => _undefined3,
7168
+ ulid: () => ulid2,
7169
+ uint64: () => uint64,
7170
+ uint32: () => uint32,
7171
+ tuple: () => tuple,
7172
+ trim: () => _trim,
7173
+ treeifyError: () => treeifyError,
7174
+ transform: () => transform,
7175
+ toUpperCase: () => _toUpperCase,
7176
+ toLowerCase: () => _toLowerCase,
7177
+ toJSONSchema: () => toJSONSchema,
7178
+ templateLiteral: () => templateLiteral,
7179
+ symbol: () => symbol,
7180
+ superRefine: () => superRefine,
7181
+ success: () => success,
7182
+ stringbool: () => stringbool,
7183
+ stringFormat: () => stringFormat,
7184
+ string: () => string2,
7185
+ strictObject: () => strictObject,
7186
+ startsWith: () => _startsWith,
7187
+ slugify: () => _slugify,
7188
+ size: () => _size,
7189
+ setErrorMap: () => setErrorMap,
7190
+ set: () => set,
7191
+ safeParseAsync: () => safeParseAsync2,
7192
+ safeParse: () => safeParse2,
7193
+ safeEncodeAsync: () => safeEncodeAsync2,
7194
+ safeEncode: () => safeEncode2,
7195
+ safeDecodeAsync: () => safeDecodeAsync2,
7196
+ safeDecode: () => safeDecode2,
7197
+ registry: () => registry,
7198
+ regexes: () => exports_regexes,
7199
+ regex: () => _regex,
7200
+ refine: () => refine,
7201
+ record: () => record,
7202
+ readonly: () => readonly,
7203
+ property: () => _property,
7204
+ promise: () => promise,
7205
+ prettifyError: () => prettifyError,
7206
+ preprocess: () => preprocess,
7207
+ prefault: () => prefault,
7208
+ positive: () => _positive,
7209
+ pipe: () => pipe,
7210
+ partialRecord: () => partialRecord,
7211
+ parseAsync: () => parseAsync2,
7212
+ parse: () => parse6,
7213
+ overwrite: () => _overwrite,
7214
+ optional: () => optional,
7215
+ object: () => object,
7216
+ number: () => number2,
7217
+ nullish: () => nullish2,
7218
+ nullable: () => nullable,
7219
+ null: () => _null3,
7220
+ normalize: () => _normalize,
7221
+ nonpositive: () => _nonpositive,
7222
+ nonoptional: () => nonoptional,
7223
+ nonnegative: () => _nonnegative,
7224
+ never: () => never,
7225
+ negative: () => _negative,
7226
+ nativeEnum: () => nativeEnum,
7227
+ nanoid: () => nanoid2,
7228
+ nan: () => nan,
7229
+ multipleOf: () => _multipleOf,
7230
+ minSize: () => _minSize,
7231
+ minLength: () => _minLength,
7232
+ mime: () => _mime,
7233
+ meta: () => meta2,
7234
+ maxSize: () => _maxSize,
7235
+ maxLength: () => _maxLength,
7236
+ map: () => map,
7237
+ mac: () => mac2,
7238
+ lte: () => _lte,
7239
+ lt: () => _lt,
7240
+ lowercase: () => _lowercase,
7241
+ looseRecord: () => looseRecord,
7242
+ looseObject: () => looseObject,
7243
+ locales: () => exports_locales,
7244
+ literal: () => literal,
7245
+ length: () => _length,
7246
+ lazy: () => lazy,
7247
+ ksuid: () => ksuid2,
7248
+ keyof: () => keyof,
7249
+ jwt: () => jwt,
7250
+ json: () => json,
7251
+ iso: () => exports_iso,
7252
+ ipv6: () => ipv62,
7253
+ ipv4: () => ipv42,
7254
+ invertCodec: () => invertCodec,
7255
+ intersection: () => intersection,
7256
+ int64: () => int64,
7257
+ int32: () => int32,
7258
+ int: () => int,
7259
+ instanceof: () => _instanceof,
7260
+ includes: () => _includes,
7261
+ httpUrl: () => httpUrl,
7262
+ hostname: () => hostname2,
7263
+ hex: () => hex2,
7264
+ hash: () => hash,
7265
+ guid: () => guid2,
7266
+ gte: () => _gte,
7267
+ gt: () => _gt,
7268
+ globalRegistry: () => globalRegistry,
7269
+ getErrorMap: () => getErrorMap,
7270
+ function: () => _function,
7271
+ fromJSONSchema: () => fromJSONSchema,
7272
+ formatError: () => formatError,
7273
+ float64: () => float64,
7274
+ float32: () => float32,
7275
+ flattenError: () => flattenError,
7276
+ file: () => file,
7277
+ exactOptional: () => exactOptional,
7278
+ enum: () => _enum2,
7279
+ endsWith: () => _endsWith,
7280
+ encodeAsync: () => encodeAsync2,
7281
+ encode: () => encode2,
7282
+ emoji: () => emoji2,
7283
+ email: () => email2,
7284
+ e164: () => e1642,
7285
+ discriminatedUnion: () => discriminatedUnion,
7286
+ describe: () => describe2,
7287
+ decodeAsync: () => decodeAsync2,
7288
+ decode: () => decode2,
7289
+ date: () => date3,
7290
+ custom: () => custom,
7291
+ cuid2: () => cuid22,
7292
+ cuid: () => cuid3,
7293
+ core: () => exports_core2,
7294
+ config: () => config,
7295
+ coerce: () => exports_coerce,
7296
+ codec: () => codec,
7297
+ clone: () => clone,
7298
+ cidrv6: () => cidrv62,
7299
+ cidrv4: () => cidrv42,
7300
+ check: () => check,
7301
+ catch: () => _catch2,
7302
+ boolean: () => boolean2,
7303
+ bigint: () => bigint2,
7304
+ base64url: () => base64url2,
7305
+ base64: () => base642,
7306
+ array: () => array,
7307
+ any: () => any,
7308
+ _function: () => _function,
7309
+ _default: () => _default2,
7310
+ _ZodString: () => _ZodString,
7311
+ ZodXor: () => ZodXor,
7312
+ ZodXID: () => ZodXID,
7313
+ ZodVoid: () => ZodVoid,
7314
+ ZodUnknown: () => ZodUnknown,
7315
+ ZodUnion: () => ZodUnion,
7316
+ ZodUndefined: () => ZodUndefined,
7317
+ ZodUUID: () => ZodUUID,
7318
+ ZodURL: () => ZodURL,
7319
+ ZodULID: () => ZodULID,
7320
+ ZodType: () => ZodType,
7321
+ ZodTuple: () => ZodTuple,
7322
+ ZodTransform: () => ZodTransform,
7323
+ ZodTemplateLiteral: () => ZodTemplateLiteral,
7324
+ ZodSymbol: () => ZodSymbol,
7325
+ ZodSuccess: () => ZodSuccess,
7326
+ ZodStringFormat: () => ZodStringFormat,
7327
+ ZodString: () => ZodString,
7328
+ ZodSet: () => ZodSet,
7329
+ ZodRecord: () => ZodRecord,
7330
+ ZodRealError: () => ZodRealError,
7331
+ ZodReadonly: () => ZodReadonly,
7332
+ ZodPromise: () => ZodPromise,
7333
+ ZodPreprocess: () => ZodPreprocess,
7334
+ ZodPrefault: () => ZodPrefault,
7335
+ ZodPipe: () => ZodPipe,
7336
+ ZodOptional: () => ZodOptional,
7337
+ ZodObject: () => ZodObject,
7338
+ ZodNumberFormat: () => ZodNumberFormat,
7339
+ ZodNumber: () => ZodNumber,
7340
+ ZodNullable: () => ZodNullable,
7341
+ ZodNull: () => ZodNull,
7342
+ ZodNonOptional: () => ZodNonOptional,
7343
+ ZodNever: () => ZodNever,
7344
+ ZodNanoID: () => ZodNanoID,
7345
+ ZodNaN: () => ZodNaN,
7346
+ ZodMap: () => ZodMap,
7347
+ ZodMAC: () => ZodMAC,
7348
+ ZodLiteral: () => ZodLiteral,
7349
+ ZodLazy: () => ZodLazy,
7350
+ ZodKSUID: () => ZodKSUID,
7351
+ ZodJWT: () => ZodJWT,
7352
+ ZodIssueCode: () => ZodIssueCode,
7353
+ ZodIntersection: () => ZodIntersection,
7354
+ ZodISOTime: () => ZodISOTime,
7355
+ ZodISODuration: () => ZodISODuration,
7356
+ ZodISODateTime: () => ZodISODateTime,
7357
+ ZodISODate: () => ZodISODate,
7358
+ ZodIPv6: () => ZodIPv6,
7359
+ ZodIPv4: () => ZodIPv4,
7360
+ ZodGUID: () => ZodGUID,
7361
+ ZodFunction: () => ZodFunction,
7362
+ ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
7363
+ ZodFile: () => ZodFile,
7364
+ ZodExactOptional: () => ZodExactOptional,
7365
+ ZodError: () => ZodError,
7366
+ ZodEnum: () => ZodEnum,
7367
+ ZodEmoji: () => ZodEmoji,
7368
+ ZodEmail: () => ZodEmail,
7369
+ ZodE164: () => ZodE164,
7370
+ ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
7371
+ ZodDefault: () => ZodDefault,
7372
+ ZodDate: () => ZodDate,
7373
+ ZodCustomStringFormat: () => ZodCustomStringFormat,
7374
+ ZodCustom: () => ZodCustom,
7375
+ ZodCodec: () => ZodCodec,
7376
+ ZodCatch: () => ZodCatch,
7377
+ ZodCUID2: () => ZodCUID2,
7378
+ ZodCUID: () => ZodCUID,
7379
+ ZodCIDRv6: () => ZodCIDRv6,
7380
+ ZodCIDRv4: () => ZodCIDRv4,
7381
+ ZodBoolean: () => ZodBoolean,
7382
+ ZodBigIntFormat: () => ZodBigIntFormat,
7383
+ ZodBigInt: () => ZodBigInt,
7384
+ ZodBase64URL: () => ZodBase64URL,
7385
+ ZodBase64: () => ZodBase64,
7386
+ ZodArray: () => ZodArray,
7387
+ ZodAny: () => ZodAny,
7388
+ TimePrecision: () => TimePrecision,
7389
+ NEVER: () => NEVER,
7390
+ $output: () => $output,
7391
+ $input: () => $input,
7392
+ $brand: () => $brand
7393
+ });
7927
7394
 
7928
7395
  // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/core/index.js
7929
7396
  var exports_core2 = {};
@@ -21895,80 +21362,579 @@ function convertSchema(schema, ctx) {
21895
21362
  if (key in schema) {
21896
21363
  extraMeta[key] = schema[key];
21897
21364
  }
21898
- }
21899
- for (const key of Object.keys(schema)) {
21900
- if (!RECOGNIZED_KEYS.has(key)) {
21901
- extraMeta[key] = schema[key];
21365
+ }
21366
+ for (const key of Object.keys(schema)) {
21367
+ if (!RECOGNIZED_KEYS.has(key)) {
21368
+ extraMeta[key] = schema[key];
21369
+ }
21370
+ }
21371
+ if (Object.keys(extraMeta).length > 0) {
21372
+ ctx.registry.add(baseSchema, extraMeta);
21373
+ }
21374
+ if (schema.description) {
21375
+ baseSchema = baseSchema.describe(schema.description);
21376
+ }
21377
+ return baseSchema;
21378
+ }
21379
+ function fromJSONSchema(schema, params) {
21380
+ if (typeof schema === "boolean") {
21381
+ return schema ? z.any() : z.never();
21382
+ }
21383
+ let normalized;
21384
+ try {
21385
+ normalized = JSON.parse(JSON.stringify(schema));
21386
+ } catch {
21387
+ throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
21388
+ }
21389
+ const version2 = detectVersion(normalized, params?.defaultTarget);
21390
+ const defs = normalized.$defs || normalized.definitions || {};
21391
+ const ctx = {
21392
+ version: version2,
21393
+ defs,
21394
+ refs: new Map,
21395
+ processing: new Set,
21396
+ rootSchema: normalized,
21397
+ registry: params?.registry ?? globalRegistry
21398
+ };
21399
+ return convertSchema(normalized, ctx);
21400
+ }
21401
+ // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
21402
+ var exports_coerce = {};
21403
+ __export(exports_coerce, {
21404
+ string: () => string3,
21405
+ number: () => number3,
21406
+ date: () => date4,
21407
+ boolean: () => boolean3,
21408
+ bigint: () => bigint3
21409
+ });
21410
+ function string3(params) {
21411
+ return _coercedString(ZodString, params);
21412
+ }
21413
+ function number3(params) {
21414
+ return _coercedNumber(ZodNumber, params);
21415
+ }
21416
+ function boolean3(params) {
21417
+ return _coercedBoolean(ZodBoolean, params);
21418
+ }
21419
+ function bigint3(params) {
21420
+ return _coercedBigint(ZodBigInt, params);
21421
+ }
21422
+ function date4(params) {
21423
+ return _coercedDate(ZodDate, params);
21424
+ }
21425
+
21426
+ // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
21427
+ config(en_default());
21428
+ // src/config/constants.ts
21429
+ var DEFAULT_PORT = 42718;
21430
+ var VANITY_HOST = "caret.localhost";
21431
+ var HOOK_TIMEOUT_S = 3900;
21432
+ var BUN_SOCKET_IDLE_CAP_S = 255;
21433
+ var IDLE_TIMEOUT_HEADROOM_S = 5;
21434
+ var MAX_HEARTBEAT_MS = (BUN_SOCKET_IDLE_CAP_S - IDLE_TIMEOUT_HEADROOM_S) * 1000;
21435
+ function deriveIdleTimeoutSec(heartbeatMs) {
21436
+ return Math.min(Math.ceil(heartbeatMs / 1000) + IDLE_TIMEOUT_HEADROOM_S, BUN_SOCKET_IDLE_CAP_S);
21437
+ }
21438
+
21439
+ // src/config/paths.ts
21440
+ import { chmodSync, mkdirSync } from "fs";
21441
+ import { homedir as homedir4 } from "os";
21442
+ function xdgDir(envVar, fallback) {
21443
+ const base = process.env[envVar] || `${homedir4()}/${fallback}`;
21444
+ return `${base}/caret`;
21445
+ }
21446
+ function stateDir() {
21447
+ return xdgDir("XDG_STATE_HOME", ".local/state");
21448
+ }
21449
+ function reviewsDir() {
21450
+ return `${stateDir()}/reviews`;
21451
+ }
21452
+ function configDir() {
21453
+ return xdgDir("XDG_CONFIG_HOME", ".config");
21454
+ }
21455
+ function configFile() {
21456
+ return process.env.CARET_CONFIG_FILE || `${configDir()}/config.toml`;
21457
+ }
21458
+ function prefsFile() {
21459
+ return `${stateDir()}/prefs.json`;
21460
+ }
21461
+ function logFile() {
21462
+ return `${stateDir()}/caret.log`;
21463
+ }
21464
+ function daemonLogFile() {
21465
+ return `${stateDir()}/daemon.log`;
21466
+ }
21467
+ function daemonLock() {
21468
+ return `${stateDir()}/daemon.lock`;
21469
+ }
21470
+ function ensureStateDir(target = stateDir()) {
21471
+ mkdirSync(target, { recursive: true, mode: 448 });
21472
+ chmodSync(target, 448);
21473
+ const root = stateDir();
21474
+ if (target !== root && target.startsWith(`${root}/`)) {
21475
+ mkdirSync(root, { recursive: true, mode: 448 });
21476
+ chmodSync(root, 448);
21477
+ }
21478
+ }
21479
+
21480
+ // src/lib/build-id.ts
21481
+ import { createHash } from "crypto";
21482
+
21483
+ // src/ui/assets.ts
21484
+ import { readdirSync } from "fs";
21485
+ import { dirname, join as join5, relative } from "path";
21486
+ import { fileURLToPath } from "url";
21487
+ function fromPathMap(map2) {
21488
+ const paths = Object.keys(map2).sort();
21489
+ return {
21490
+ paths,
21491
+ file(urlPath) {
21492
+ const filePath = map2[urlPath];
21493
+ return filePath ? Bun.file(filePath) : undefined;
21494
+ }
21495
+ };
21496
+ }
21497
+ function assetsFromDist(distDir) {
21498
+ const map2 = {};
21499
+ const walk = (dir) => {
21500
+ for (const ent of readdirSync(dir, { withFileTypes: true })) {
21501
+ const full = join5(dir, ent.name);
21502
+ if (ent.isDirectory())
21503
+ walk(full);
21504
+ else if (ent.isFile())
21505
+ map2[`/${relative(distDir, full).split("\\").join("/")}`] = full;
21506
+ }
21507
+ };
21508
+ try {
21509
+ walk(distDir);
21510
+ } catch {
21511
+ return;
21512
+ }
21513
+ return Object.keys(map2).length > 0 ? fromPathMap(map2) : undefined;
21514
+ }
21515
+ async function loadUiAssets() {
21516
+ try {
21517
+ const mod = await import("@/ui-manifest.generated.ts");
21518
+ if (mod.UI_MANIFEST && Object.keys(mod.UI_MANIFEST).length > 0) {
21519
+ return fromPathMap(mod.UI_MANIFEST);
21520
+ }
21521
+ } catch {}
21522
+ const srcDist = fileURLToPath(new URL("../../ui/dist", import.meta.url));
21523
+ const fromSrc = assetsFromDist(srcDist);
21524
+ if (fromSrc)
21525
+ return fromSrc;
21526
+ const besideDist = join5(dirname(process.execPath), "ui");
21527
+ return assetsFromDist(besideDist);
21528
+ }
21529
+ // package.json
21530
+ var package_default = {
21531
+ name: "@macintacos/caret",
21532
+ version: "0.6.0",
21533
+ license: "MIT",
21534
+ type: "module",
21535
+ description: "A Claude Code plugin that replaces the terminal plan-approval prompt with a local web UI for inline review, annotation, and approval.",
21536
+ main: "./opencode/index.ts",
21537
+ exports: {
21538
+ ".": "./opencode/index.ts"
21539
+ },
21540
+ bin: {
21541
+ caret: "./bin/caret"
21542
+ },
21543
+ homepage: "https://github.com/macintacos/caret",
21544
+ repository: {
21545
+ type: "git",
21546
+ url: "git+https://github.com/macintacos/caret.git"
21547
+ },
21548
+ publishConfig: {
21549
+ access: "public"
21550
+ },
21551
+ files: [
21552
+ "dist/",
21553
+ "ui/dist/",
21554
+ "bin/caret",
21555
+ "hooks/",
21556
+ "commands/",
21557
+ "opencode/",
21558
+ ".claude-plugin/plugin.json"
21559
+ ],
21560
+ scripts: {
21561
+ test: "bun test --conditions browser",
21562
+ lint: "mise run lint",
21563
+ format: "mise run format",
21564
+ build: "mise run build"
21565
+ },
21566
+ devDependencies: {
21567
+ "@happy-dom/global-registrator": "^20.9.0",
21568
+ "@laststance/tailwind-suggest-canonical-classes": "^0.1.1",
21569
+ "@playwright/test": "^1.60.0",
21570
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
21571
+ "@tailwindcss/vite": "^4.3.2",
21572
+ "@types/bun": "^1.3.14",
21573
+ "@types/semver": "^7.7.1",
21574
+ "happy-dom": "^20.9.0",
21575
+ listr2: "^10.2.1",
21576
+ "pino-pretty": "^13.1.3",
21577
+ svelte: "^5.55.9",
21578
+ "svelte-check": "^4.4.8",
21579
+ tailwindcss: "^4.3.2",
21580
+ "tw-animate-css": "^1.4.0",
21581
+ typescript: "^6.0.3",
21582
+ vite: "^8.0.14"
21583
+ },
21584
+ dependencies: {
21585
+ "@codemirror/commands": "^6.10.3",
21586
+ "@codemirror/lang-markdown": "^6.5.0",
21587
+ "@codemirror/language": "^6.12.3",
21588
+ "@codemirror/language-data": "^6.5.2",
21589
+ "@codemirror/state": "^6.6.0",
21590
+ "@codemirror/view": "^6.43.0",
21591
+ "@commander-js/extra-typings": "^15.0.0",
21592
+ "@internationalized/date": "^3.12.2",
21593
+ "@lezer/highlight": "^1.2.3",
21594
+ "@opencode-ai/plugin": "^1.16.2",
21595
+ "@pierre/diffs": "1.2.7",
21596
+ "bits-ui": "^2.18.1",
21597
+ clsx: "^2.1.1",
21598
+ commander: "^15.0.0",
21599
+ "jsonc-parser": "^3.3.1",
21600
+ marked: "^18.0.4",
21601
+ pino: "^10.3.1",
21602
+ prettier: "3.8.3",
21603
+ semver: "^7.8.1",
21604
+ shiki: "^4.1.0",
21605
+ "smol-toml": "1.6.1",
21606
+ "tailwind-merge": "^3.6.0",
21607
+ "tailwind-variants": "^3.2.2",
21608
+ xss: "^1.0.15",
21609
+ zod: "4.4.3"
21610
+ }
21611
+ };
21612
+
21613
+ // src/lib/build-id.ts
21614
+ var VERSION = package_default.version;
21615
+ var IDENTITY = { service: "caret", version: VERSION };
21616
+ function buildKind(argv1 = process.argv[1]) {
21617
+ if (argv1?.endsWith(".ts"))
21618
+ return "dev";
21619
+ if (argv1?.endsWith(".js"))
21620
+ return "bundle";
21621
+ return "binary";
21622
+ }
21623
+ function isCompiledBinary() {
21624
+ return buildKind() !== "dev";
21625
+ }
21626
+ async function buildHash(assets) {
21627
+ if (!assets || assets.paths.length === 0)
21628
+ return "no-ui";
21629
+ const h = createHash("sha256");
21630
+ for (const urlPath of assets.paths) {
21631
+ const bytes = await assets.file(urlPath)?.bytes() ?? new Uint8Array;
21632
+ h.update(`${urlPath}\x00${bytes.length}\x00`);
21633
+ h.update(bytes);
21634
+ }
21635
+ return h.digest("hex").slice(0, 12);
21636
+ }
21637
+ async function computeBuildId(deps) {
21638
+ if (deps.kind !== "dev") {
21639
+ const h = await deps.hashFile();
21640
+ if (h)
21641
+ return h;
21642
+ }
21643
+ return deps.uiHash();
21644
+ }
21645
+ var cachedBuildId;
21646
+ async function currentBuildId() {
21647
+ if (cachedBuildId !== undefined)
21648
+ return cachedBuildId;
21649
+ const kind = buildKind();
21650
+ cachedBuildId = await computeBuildId({
21651
+ kind,
21652
+ hashFile: async () => {
21653
+ try {
21654
+ const target = kind === "bundle" ? process.argv[1] : process.execPath;
21655
+ const bytes = await Bun.file(target).bytes();
21656
+ return createHash("sha256").update(bytes).digest("hex").slice(0, 12);
21657
+ } catch {
21658
+ return null;
21659
+ }
21660
+ },
21661
+ uiHash: async () => buildHash(await loadUiAssets())
21662
+ });
21663
+ return cachedBuildId;
21664
+ }
21665
+ function resolveCommit(deps) {
21666
+ if (deps.baked)
21667
+ return deps.baked;
21668
+ return deps.gitHead() || "unknown";
21669
+ }
21670
+ var cachedCommit;
21671
+ function currentCommit() {
21672
+ if (cachedCommit !== undefined)
21673
+ return cachedCommit;
21674
+ cachedCommit = resolveCommit({
21675
+ baked: process.env.CARET_BUILD_COMMIT,
21676
+ gitHead: () => {
21677
+ try {
21678
+ const r = Bun.spawnSync(["git", "-C", import.meta.dir, "rev-parse", "HEAD"]);
21679
+ if (r.exitCode !== 0)
21680
+ return null;
21681
+ const out = r.stdout.toString().trim();
21682
+ return out.length > 0 ? out : null;
21683
+ } catch {
21684
+ return null;
21685
+ }
21686
+ }
21687
+ });
21688
+ return cachedCommit;
21689
+ }
21690
+
21691
+ // src/lib/log.ts
21692
+ var import_pino = __toESM(require_pino(), 1);
21693
+
21694
+ // src/lib/caller-location.ts
21695
+ import { dirname as dirname2 } from "path";
21696
+ var PKG_ROOT = dirname2(dirname2(import.meta.dir));
21697
+ var FRAME = /^\s*at (?:.* \()?(?:file:\/\/)?(.+):(\d+):\d+\)?$/;
21698
+ var INTERNAL_SUFFIXES = ["src/lib/caller-location.ts", "src/lib/log.ts"];
21699
+ function parseCaller(stack, pkgRoot = PKG_ROOT) {
21700
+ if (!stack)
21701
+ return;
21702
+ for (const line of stack.split(`
21703
+ `)) {
21704
+ const m = FRAME.exec(line);
21705
+ if (!m?.[1] || !m[2])
21706
+ continue;
21707
+ const path = m[1];
21708
+ if (INTERNAL_SUFFIXES.some((s) => path.endsWith(s)))
21709
+ continue;
21710
+ if (!path.includes("/") || path.startsWith("node:"))
21711
+ continue;
21712
+ const rel = !path.startsWith("/") ? path : path.startsWith(`${pkgRoot}/`) ? path.slice(pkgRoot.length + 1) : path.split("/").slice(-2).join("/");
21713
+ return `${rel}:${m[2]}`;
21714
+ }
21715
+ return;
21716
+ }
21717
+ function callerLocation() {
21718
+ try {
21719
+ return parseCaller(new Error().stack);
21720
+ } catch {
21721
+ return;
21722
+ }
21723
+ }
21724
+
21725
+ // src/lib/types.ts
21726
+ function errorMessage(err) {
21727
+ return err instanceof Error ? err.message : String(err);
21728
+ }
21729
+ function isUnresolved(status) {
21730
+ return status === "pending" || status === "rejected";
21731
+ }
21732
+ function currentVersion(review) {
21733
+ const v = review.versions[review.versions.length - 1];
21734
+ if (!v)
21735
+ throw new Error(`review ${review.id} has no versions`);
21736
+ return v;
21737
+ }
21738
+ function toClientReview(review) {
21739
+ const cur = currentVersion(review);
21740
+ return {
21741
+ id: review.id,
21742
+ sessionId: review.sessionId,
21743
+ cwd: review.cwd,
21744
+ title: review.title,
21745
+ status: review.status,
21746
+ planEpoch: review.planEpoch,
21747
+ version: cur.version,
21748
+ currentPlan: cur.plan,
21749
+ annotations: cur.annotations,
21750
+ versions: review.versions,
21751
+ generalCommentDraft: review.generalCommentDraft ?? "",
21752
+ composerScratches: cur.composerScratches ?? [],
21753
+ createdAt: review.createdAt,
21754
+ updatedAt: review.updatedAt,
21755
+ decision: review.decision
21756
+ };
21757
+ }
21758
+
21759
+ // src/redact/core.ts
21760
+ var CENSOR = "<redacted>";
21761
+ var DENY_KEYS = new Set(["plan", "prompt", "feedback"]);
21762
+ var MAX_DEPTH = 6;
21763
+ function scrubGraph(v, scrubStr) {
21764
+ return walk(v, scrubStr, 0, new WeakSet);
21765
+ }
21766
+ function walk(v, scrubStr, depth, seen) {
21767
+ if (typeof v === "string")
21768
+ return scrubStr ? scrubStr(v) : v;
21769
+ if (v === null || typeof v !== "object")
21770
+ return v;
21771
+ if (seen.has(v))
21772
+ return "<cyclic>";
21773
+ if (depth >= MAX_DEPTH)
21774
+ return "<depth-capped>";
21775
+ seen.add(v);
21776
+ let out;
21777
+ if (Array.isArray(v)) {
21778
+ out = v.map((el) => walk(el, scrubStr, depth + 1, seen));
21779
+ } else {
21780
+ const obj = {};
21781
+ for (const [k, val] of Object.entries(v)) {
21782
+ obj[k] = DENY_KEYS.has(k) ? CENSOR : walk(val, scrubStr, depth + 1, seen);
21783
+ }
21784
+ out = obj;
21785
+ }
21786
+ seen.delete(v);
21787
+ return out;
21788
+ }
21789
+ function shortId(id) {
21790
+ return id.slice(0, 8);
21791
+ }
21792
+
21793
+ // src/redact/node.ts
21794
+ import { readFileSync as readFileSync4, writeFileSync } from "fs";
21795
+ import { homedir as homedir5 } from "os";
21796
+ var FOREIGN_HOME = /(\/Users\/|\/home\/)[^/\s"']+/g;
21797
+ function scrubString(s, home = homedir5()) {
21798
+ const dehomed = home.length > 1 ? s.replaceAll(home, "~") : s;
21799
+ return dehomed.replace(FOREIGN_HOME, `$1${CENSOR}`);
21800
+ }
21801
+ function scrubValue(v, redact) {
21802
+ return scrubGraph(v, redact ? scrubString : undefined);
21803
+ }
21804
+ function redactLogText(text) {
21805
+ return text.split(`
21806
+ `).map((line) => {
21807
+ if (line.startsWith("{")) {
21808
+ try {
21809
+ return JSON.stringify(scrubValue(JSON.parse(line), true));
21810
+ } catch {}
21811
+ }
21812
+ return scrubString(line);
21813
+ }).join(`
21814
+ `);
21815
+ }
21816
+ function redactLogFiles(files = [logFile(), daemonLogFile()]) {
21817
+ const written = [];
21818
+ for (const file2 of files) {
21819
+ let text;
21820
+ try {
21821
+ text = readFileSync4(file2, "utf-8");
21822
+ } catch {
21823
+ continue;
21902
21824
  }
21825
+ const sibling = `${file2.replace(/\.log$/, "")}.redacted.log`;
21826
+ writeFileSync(sibling, redactLogText(text), { mode: 384 });
21827
+ written.push(sibling);
21903
21828
  }
21904
- if (Object.keys(extraMeta).length > 0) {
21905
- ctx.registry.add(baseSchema, extraMeta);
21829
+ return written;
21830
+ }
21831
+
21832
+ // src/lib/log.ts
21833
+ var pinoOpts = {
21834
+ base: undefined,
21835
+ timestamp: import_pino.default.stdTimeFunctions.isoTime,
21836
+ serializers: { err: (v) => v }
21837
+ };
21838
+ function wrap(logger, liveLevel, liveRedact, source) {
21839
+ function fields(extra, step, redact) {
21840
+ const out = scrubValue({ ...extra }, redact);
21841
+ out.step = step;
21842
+ if (out.source == null) {
21843
+ out.source = source;
21844
+ const caller = callerLocation();
21845
+ if (caller !== undefined)
21846
+ out.caller = redact ? scrubString(caller) : caller;
21847
+ }
21848
+ return out;
21906
21849
  }
21907
- if (schema.description) {
21908
- baseSchema = baseSchema.describe(schema.description);
21850
+ function emit(method, step, msg, extra) {
21851
+ try {
21852
+ const next = liveLevel();
21853
+ if (logger.level !== next)
21854
+ logger.level = next;
21855
+ if (!logger.isLevelEnabled(method))
21856
+ return;
21857
+ const r = liveRedact();
21858
+ logger[method](fields(extra, step, r), r ? scrubString(msg) : msg);
21859
+ } catch {}
21909
21860
  }
21910
- return baseSchema;
21861
+ return {
21862
+ debug: (step, msg, extra) => emit("debug", step, msg, extra),
21863
+ info: (step, msg, extra) => emit("info", step, msg, extra),
21864
+ warn: (step, msg, extra) => emit("warn", step, msg, extra),
21865
+ error(step, err, extra) {
21866
+ try {
21867
+ const r = liveRedact();
21868
+ const f = fields(extra, step, r);
21869
+ if (err instanceof Error)
21870
+ f.err = scrubValue(import_pino.default.stdSerializers.errWithCause(err), r);
21871
+ const msg = errorMessage(err);
21872
+ logger.error(f, r ? scrubString(msg) : msg);
21873
+ } catch {}
21874
+ }
21875
+ };
21911
21876
  }
21912
- function fromJSONSchema(schema, params) {
21913
- if (typeof schema === "boolean") {
21914
- return schema ? z.any() : z.never();
21915
- }
21916
- let normalized;
21877
+ var noopLogger = {
21878
+ debug: () => {},
21879
+ info: () => {},
21880
+ warn: () => {},
21881
+ error: () => {}
21882
+ };
21883
+ function createHookLogger(level, redact) {
21884
+ const path = logFile();
21917
21885
  try {
21918
- normalized = JSON.parse(JSON.stringify(schema));
21886
+ ensureStateDir();
21887
+ const dest = import_pino.default.destination({ dest: path, sync: true, mode: 384 });
21888
+ return { log: wrap(import_pino.default(pinoOpts, dest), level, redact, "hook"), dest, path };
21919
21889
  } catch {
21920
- throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
21890
+ return { log: noopLogger, dest: null, path };
21921
21891
  }
21922
- const version2 = detectVersion(normalized, params?.defaultTarget);
21923
- const defs = normalized.$defs || normalized.definitions || {};
21924
- const ctx = {
21925
- version: version2,
21926
- defs,
21927
- refs: new Map,
21928
- processing: new Set,
21929
- rootSchema: normalized,
21930
- registry: params?.registry ?? globalRegistry
21931
- };
21932
- return convertSchema(normalized, ctx);
21933
21892
  }
21934
- // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
21935
- var exports_coerce = {};
21936
- __export(exports_coerce, {
21937
- string: () => string3,
21938
- number: () => number3,
21939
- date: () => date4,
21940
- boolean: () => boolean3,
21941
- bigint: () => bigint3
21942
- });
21943
- function string3(params) {
21944
- return _coercedString(ZodString, params);
21893
+ var hookState = { level: "info", redact: false, instance: null };
21894
+ function hook() {
21895
+ const path = logFile();
21896
+ if (hookState.instance && hookState.instance.path === path) {
21897
+ return hookState.instance.log;
21898
+ }
21899
+ try {
21900
+ hookState.instance?.dest?.destroy();
21901
+ } catch {}
21902
+ const next = createHookLogger(() => hookState.level, () => hookState.redact);
21903
+ hookState.instance = next.dest ? next : null;
21904
+ return next.log;
21945
21905
  }
21946
- function number3(params) {
21947
- return _coercedNumber(ZodNumber, params);
21906
+ function setLogLevel(level) {
21907
+ hookState.level = level;
21948
21908
  }
21949
- function boolean3(params) {
21950
- return _coercedBoolean(ZodBoolean, params);
21909
+ function setRedact(on) {
21910
+ hookState.redact = on;
21951
21911
  }
21952
- function bigint3(params) {
21953
- return _coercedBigint(ZodBigInt, params);
21912
+ function logDebug(step, msg, extra) {
21913
+ hook().debug(step, msg, extra);
21954
21914
  }
21955
- function date4(params) {
21956
- return _coercedDate(ZodDate, params);
21915
+ function logInfo(step, msg, extra) {
21916
+ hook().info(step, msg, extra);
21957
21917
  }
21958
-
21959
- // node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
21960
- config(en_default());
21961
- // src/constants.ts
21962
- var DEFAULT_PORT = 42718;
21963
- var HOOK_TIMEOUT_S = 3900;
21964
- var BUN_SOCKET_IDLE_CAP_S = 255;
21965
- var IDLE_TIMEOUT_HEADROOM_S = 5;
21966
- var MAX_HEARTBEAT_MS = (BUN_SOCKET_IDLE_CAP_S - IDLE_TIMEOUT_HEADROOM_S) * 1000;
21967
- function deriveIdleTimeoutSec(heartbeatMs) {
21968
- return Math.min(Math.ceil(heartbeatMs / 1000) + IDLE_TIMEOUT_HEADROOM_S, BUN_SOCKET_IDLE_CAP_S);
21918
+ function logWarn(step, msg, extra) {
21919
+ hook().warn(step, msg, extra);
21920
+ }
21921
+ function logError(step, err, ctx) {
21922
+ hook().error(step, err, ctx);
21923
+ }
21924
+ function createDaemonLogger(level, dest, redact = () => false) {
21925
+ try {
21926
+ const target = import_pino.default.destination({
21927
+ ...dest === undefined ? { fd: 2 } : { dest },
21928
+ sync: true
21929
+ });
21930
+ const logger = import_pino.default({ ...pinoOpts, base: { pid: process.pid } }, target);
21931
+ return wrap(logger, level, redact, "daemon");
21932
+ } catch {
21933
+ return noopLogger;
21934
+ }
21969
21935
  }
21970
21936
 
21971
- // src/settings.ts
21937
+ // src/config/settings.ts
21972
21938
  var Port = exports_external.number().int().positive();
21973
21939
  var TimeoutS = exports_external.number().positive().lt(HOOK_TIMEOUT_S);
21974
21940
  var IdleMs = exports_external.number().int().nonnegative();
@@ -22139,7 +22105,73 @@ function heartbeatMs(s = settings().current()) {
22139
22105
  return envValue("CARET_HEARTBEAT_MS", HeartbeatMs) ?? s.daemon.heartbeat_ms;
22140
22106
  }
22141
22107
 
22142
- // src/daemon-lifecycle.ts
22108
+ // src/commands/boot.ts
22109
+ function warnInvalidEnvVars(warn) {
22110
+ for (const name of invalidEnvVars())
22111
+ warn(`${name} invalid; using config/default`);
22112
+ }
22113
+
22114
+ // src/daemon/lifecycle.ts
22115
+ import { openSync, unlinkSync } from "fs";
22116
+ import { normalize } from "path";
22117
+
22118
+ // src/daemon/client.ts
22119
+ async function httpHealth(baseUrl) {
22120
+ try {
22121
+ const res = await fetch(`${baseUrl}/api/health`, {
22122
+ signal: AbortSignal.timeout(500)
22123
+ });
22124
+ if (!res.ok)
22125
+ return null;
22126
+ return await res.json();
22127
+ } catch {
22128
+ return null;
22129
+ }
22130
+ }
22131
+ async function postReview(baseUrl, input) {
22132
+ const res = await fetch(`${baseUrl}/api/reviews`, {
22133
+ method: "POST",
22134
+ headers: { "Content-Type": "application/json" },
22135
+ body: JSON.stringify(input)
22136
+ });
22137
+ if (!res.ok)
22138
+ throw new Error(`POST /api/reviews failed: ${res.status}`);
22139
+ return await res.json();
22140
+ }
22141
+ async function expireReview(baseUrl, id) {
22142
+ const res = await fetch(`${baseUrl}/api/reviews/${id}/expire`, {
22143
+ method: "POST",
22144
+ signal: AbortSignal.timeout(1000)
22145
+ });
22146
+ if (!res.ok && res.status !== 404)
22147
+ throw new Error(`POST /expire failed: ${res.status}`);
22148
+ }
22149
+ async function longPoll(baseUrl, id) {
22150
+ const res = await fetch(`${baseUrl}/api/reviews/${id}/decision`);
22151
+ if (res.status === 204)
22152
+ return null;
22153
+ if (!res.ok)
22154
+ throw new Error(`decision long-poll failed: ${res.status}`);
22155
+ return await res.json();
22156
+ }
22157
+ async function listReviews(baseUrl) {
22158
+ const res = await fetch(`${baseUrl}/api/reviews`, { signal: AbortSignal.timeout(1000) });
22159
+ if (!res.ok)
22160
+ throw new Error(`GET /api/reviews failed: ${res.status}`);
22161
+ return await res.json();
22162
+ }
22163
+ async function resolveReview(baseUrl, id, body) {
22164
+ const res = await fetch(`${baseUrl}/api/reviews/${id}/resolve`, {
22165
+ method: "POST",
22166
+ headers: { "Content-Type": "application/json" },
22167
+ body: JSON.stringify(body),
22168
+ signal: AbortSignal.timeout(1000)
22169
+ });
22170
+ if (!res.ok)
22171
+ throw new Error(`POST /resolve failed: ${res.status}`);
22172
+ }
22173
+
22174
+ // src/daemon/lifecycle.ts
22143
22175
  function isAddrInUse(e) {
22144
22176
  if (e && typeof e === "object" && "code" in e) {
22145
22177
  return e.code === "EADDRINUSE";
@@ -22273,21 +22305,312 @@ async function prodEnsureDeps(s) {
22273
22305
  };
22274
22306
  }
22275
22307
 
22276
- // src/daemon.ts
22308
+ // src/daemon/server.ts
22277
22309
  import { renameSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "fs";
22278
22310
  import { dirname as dirname4 } from "path";
22279
22311
 
22280
- // src/decisions.ts
22312
+ // src/config/prefs.ts
22313
+ import { readFile as readFile2, writeFile } from "fs/promises";
22314
+ import { dirname as dirname3 } from "path";
22315
+ var DEFAULT_SET = { valid: ["default"], fallback: "default" };
22316
+ async function readApproveMode(file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
22317
+ try {
22318
+ const parsed = JSON.parse(await readFile2(file2, "utf-8"));
22319
+ if (typeof parsed.approveMode === "string" && set2.valid.includes(parsed.approveMode)) {
22320
+ return parsed.approveMode;
22321
+ }
22322
+ log.debug("prefs", "unrecognized approve mode; using default");
22323
+ return set2.fallback;
22324
+ } catch (err) {
22325
+ const absent = err?.code === "ENOENT";
22326
+ log.debug("prefs", absent ? "no prefs file; using default approve mode" : "prefs unreadable; using default approve mode");
22327
+ return set2.fallback;
22328
+ }
22329
+ }
22330
+ async function writeApproveMode(mode, file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
22331
+ if (!set2.valid.includes(mode)) {
22332
+ log.warn("prefs", "ignoring invalid approve mode");
22333
+ return;
22334
+ }
22335
+ ensureStateDir(dirname3(file2));
22336
+ await writeFile(file2, JSON.stringify({ approveMode: mode }, null, 2), { mode: 384 });
22337
+ log.debug("prefs", `approve mode saved: ${mode}`);
22338
+ }
22339
+
22340
+ // src/daemon/guards.ts
22341
+ var LIVE_CLIENT_WINDOW_MS = 120000;
22342
+ function isClientLive(lastPollAt, now, windowMs) {
22343
+ return lastPollAt !== 0 && now - lastPollAt < windowMs;
22344
+ }
22345
+ function isSafeMethod(method) {
22346
+ return method === "GET" || method === "HEAD";
22347
+ }
22348
+ function isCrossOrigin(req) {
22349
+ const origin = req.headers.get("origin");
22350
+ if (origin) {
22351
+ try {
22352
+ const host = new URL(origin).hostname;
22353
+ if (host !== "127.0.0.1" && host !== "localhost" && host !== VANITY_HOST)
22354
+ return true;
22355
+ } catch {
22356
+ return true;
22357
+ }
22358
+ }
22359
+ const site = req.headers.get("sec-fetch-site");
22360
+ if (site && site !== "same-origin" && site !== "none")
22361
+ return true;
22362
+ return false;
22363
+ }
22364
+
22365
+ // src/daemon/schemas.ts
22366
+ var PlanInputSchema = exports_external.object({
22367
+ sessionId: exports_external.string().optional(),
22368
+ cwd: exports_external.string().optional(),
22369
+ title: exports_external.string().optional(),
22370
+ plan: exports_external.string().optional(),
22371
+ planFilePath: exports_external.string().optional()
22372
+ }).catch({});
22373
+ var MAX_FILE_REFS = 200;
22374
+ var FileRefsBodySchema = exports_external.object({ paths: exports_external.array(exports_external.string()).catch([]) }).catch({ paths: [] });
22375
+ var BehaviorSchema = exports_external.enum(["allow", "deny"]);
22376
+ var ResolveBodySchema = exports_external.object({
22377
+ behavior: BehaviorSchema.catch("allow"),
22378
+ feedback: exports_external.string().optional(),
22379
+ acceptMode: exports_external.string().optional().catch(undefined)
22380
+ }).catch({ behavior: "allow" });
22381
+ var LineAnnotationSchema = exports_external.object({
22382
+ id: exports_external.string(),
22383
+ startLine: exports_external.number().int().min(1),
22384
+ endLine: exports_external.number().int().min(1),
22385
+ comment: exports_external.string(),
22386
+ state: exports_external.enum(["pending", "approved", "rejected", "expired"]).optional()
22387
+ }).refine((a) => a.endLine >= a.startLine, { message: "endLine must be >= startLine" });
22388
+ var LegacyAnnotationSchema = exports_external.object({
22389
+ id: exports_external.string(),
22390
+ blockId: exports_external.string(),
22391
+ startOffset: exports_external.number(),
22392
+ endOffset: exports_external.number(),
22393
+ quote: exports_external.string(),
22394
+ prefix: exports_external.string().optional(),
22395
+ suffix: exports_external.string().optional(),
22396
+ comment: exports_external.string()
22397
+ });
22398
+ var AnnotationSchema = exports_external.union([LineAnnotationSchema, LegacyAnnotationSchema]);
22399
+ var PersistedScratchSchema = exports_external.object({
22400
+ startLine: exports_external.number().int().min(1),
22401
+ endLine: exports_external.number().int().min(1),
22402
+ text: exports_external.string()
22403
+ }).refine((s) => s.endLine >= s.startLine, { message: "endLine must be >= startLine" });
22404
+ function malformedLineAnchor(raw) {
22405
+ if (typeof raw !== "object" || raw === null)
22406
+ return null;
22407
+ const anns = raw.annotations;
22408
+ if (!Array.isArray(anns))
22409
+ return null;
22410
+ for (const a of anns) {
22411
+ if (typeof a !== "object" || a === null)
22412
+ continue;
22413
+ if (!(("startLine" in a) || ("endLine" in a)))
22414
+ continue;
22415
+ const res = LineAnnotationSchema.safeParse(a);
22416
+ if (!res.success)
22417
+ return res.error.issues[0]?.message ?? "invalid line anchor";
22418
+ }
22419
+ return null;
22420
+ }
22421
+ var nullToUndefined = (v) => v ?? undefined;
22422
+ var DraftBodySchema = exports_external.object({
22423
+ annotations: exports_external.array(AnnotationSchema).nullish().transform(nullToUndefined),
22424
+ generalCommentDraft: exports_external.string().nullish().transform(nullToUndefined),
22425
+ composerScratches: exports_external.array(PersistedScratchSchema).nullish().transform(nullToUndefined).catch(undefined),
22426
+ version: exports_external.number().int().min(1).nullish().transform(nullToUndefined).catch(undefined)
22427
+ }).catch({
22428
+ annotations: undefined,
22429
+ generalCommentDraft: undefined,
22430
+ composerScratches: undefined,
22431
+ version: undefined
22432
+ });
22433
+ async function parseBody(req, schema) {
22434
+ return schema.parse(await req.json().catch(() => ({})));
22435
+ }
22436
+
22437
+ // src/plan/excerpt.ts
22438
+ import { readdirSync as readdirSync2, readFileSync as readFileSync6, realpathSync, statSync as statSync2 } from "fs";
22439
+ import { extname, isAbsolute, join as join6, relative as relative2, resolve, sep } from "path";
22440
+ var EXCERPT_RADIUS = 6;
22441
+ var EXCERPT_HEAD_LINES = 13;
22442
+ var MAX_EXCERPT_BYTES = 2 * 1024 * 1024;
22443
+ var MAX_SCAN_ENTRIES = 5000;
22444
+ var SKIP_DIRS = new Set(["node_modules", "dist", "build", "coverage", "out"]);
22445
+ var EXT_LANGUAGE = {
22446
+ ".ts": "typescript",
22447
+ ".mts": "typescript",
22448
+ ".cts": "typescript",
22449
+ ".tsx": "tsx",
22450
+ ".js": "javascript",
22451
+ ".mjs": "javascript",
22452
+ ".cjs": "javascript",
22453
+ ".jsx": "jsx",
22454
+ ".svelte": "svelte",
22455
+ ".vue": "vue",
22456
+ ".json": "json",
22457
+ ".jsonc": "jsonc",
22458
+ ".css": "css",
22459
+ ".scss": "scss",
22460
+ ".less": "less",
22461
+ ".html": "html",
22462
+ ".htm": "html",
22463
+ ".xml": "xml",
22464
+ ".svg": "xml",
22465
+ ".md": "markdown",
22466
+ ".mdx": "mdx",
22467
+ ".py": "python",
22468
+ ".rb": "ruby",
22469
+ ".rs": "rust",
22470
+ ".go": "go",
22471
+ ".java": "java",
22472
+ ".kt": "kotlin",
22473
+ ".c": "c",
22474
+ ".h": "c",
22475
+ ".cc": "cpp",
22476
+ ".cpp": "cpp",
22477
+ ".hpp": "cpp",
22478
+ ".sh": "shellscript",
22479
+ ".bash": "shellscript",
22480
+ ".zsh": "shellscript",
22481
+ ".toml": "toml",
22482
+ ".yaml": "yaml",
22483
+ ".yml": "yaml",
22484
+ ".ini": "ini",
22485
+ ".sql": "sql",
22486
+ ".graphql": "graphql",
22487
+ ".gql": "graphql",
22488
+ ".php": "php",
22489
+ ".swift": "swift",
22490
+ ".dart": "dart"
22491
+ };
22492
+ function languageForPath(path) {
22493
+ return EXT_LANGUAGE[extname(path).toLowerCase()] ?? "text";
22494
+ }
22495
+ function safeRealpath(path) {
22496
+ try {
22497
+ return realpathSync(path);
22498
+ } catch {
22499
+ return null;
22500
+ }
22501
+ }
22502
+ function containedFile(cwdReal, abs) {
22503
+ const real = safeRealpath(abs);
22504
+ if (real === null)
22505
+ return null;
22506
+ if (real !== cwdReal && !real.startsWith(cwdReal + sep))
22507
+ return null;
22508
+ try {
22509
+ if (!statSync2(real).isFile())
22510
+ return null;
22511
+ } catch {
22512
+ return null;
22513
+ }
22514
+ return real;
22515
+ }
22516
+ function basenameSearch(cwdReal, name) {
22517
+ if (name === "")
22518
+ return null;
22519
+ let scanned = 0;
22520
+ const queue = [cwdReal];
22521
+ while (queue.length > 0) {
22522
+ const currentDir = queue.shift();
22523
+ let entries;
22524
+ try {
22525
+ entries = readdirSync2(currentDir, { withFileTypes: true });
22526
+ } catch {
22527
+ continue;
22528
+ }
22529
+ for (const entry of entries) {
22530
+ if (++scanned > MAX_SCAN_ENTRIES)
22531
+ return null;
22532
+ if (entry.isFile()) {
22533
+ if (entry.name === name)
22534
+ return join6(currentDir, entry.name);
22535
+ } else if (entry.isDirectory() && !SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
22536
+ queue.push(join6(currentDir, entry.name));
22537
+ }
22538
+ }
22539
+ }
22540
+ return null;
22541
+ }
22542
+ function resolveFileInCwd(cwd, candidate) {
22543
+ if (cwd === "" || !isAbsolute(cwd))
22544
+ return null;
22545
+ const cwdReal = safeRealpath(cwd);
22546
+ if (cwdReal === null)
22547
+ return null;
22548
+ const cleaned = candidate.trim();
22549
+ if (cleaned === "")
22550
+ return null;
22551
+ const direct = containedFile(cwdReal, resolve(cwdReal, cleaned));
22552
+ if (direct !== null)
22553
+ return direct;
22554
+ const name = cleaned.split("/").pop() ?? "";
22555
+ return basenameSearch(cwdReal, name);
22556
+ }
22557
+ function readFileExcerpt(cwd, candidate, line) {
22558
+ const abs = resolveFileInCwd(cwd, candidate);
22559
+ if (abs === null)
22560
+ return null;
22561
+ let size;
22562
+ try {
22563
+ size = statSync2(abs).size;
22564
+ } catch {
22565
+ return null;
22566
+ }
22567
+ if (size > MAX_EXCERPT_BYTES)
22568
+ return null;
22569
+ let content;
22570
+ try {
22571
+ content = readFileSync6(abs, "utf-8");
22572
+ } catch {
22573
+ return null;
22574
+ }
22575
+ if (content.includes("\x00"))
22576
+ return null;
22577
+ const allLines = content.split(`
22578
+ `);
22579
+ if (allLines.length > 1 && allLines[allLines.length - 1] === "")
22580
+ allLines.pop();
22581
+ const totalLines = allLines.length;
22582
+ let startLine;
22583
+ let endLine;
22584
+ if (line !== undefined && line >= 1) {
22585
+ const target = Math.min(line, totalLines);
22586
+ startLine = Math.max(1, target - EXCERPT_RADIUS);
22587
+ endLine = Math.min(totalLines, target + EXCERPT_RADIUS);
22588
+ } else {
22589
+ startLine = 1;
22590
+ endLine = Math.min(totalLines, EXCERPT_HEAD_LINES);
22591
+ }
22592
+ const cwdReal = safeRealpath(cwd) ?? cwd;
22593
+ return {
22594
+ path: relative2(cwdReal, abs),
22595
+ language: languageForPath(abs),
22596
+ startLine,
22597
+ endLine,
22598
+ lines: allLines.slice(startLine - 1, endLine),
22599
+ totalLines
22600
+ };
22601
+ }
22602
+
22603
+ // src/review/decisions.ts
22281
22604
  function createDecisions(log = noopLogger) {
22282
22605
  const pending = new Map;
22283
22606
  function ensure(id) {
22284
22607
  let entry = pending.get(id);
22285
22608
  if (!entry) {
22286
- let resolve;
22609
+ let resolve2;
22287
22610
  const promise2 = new Promise((r) => {
22288
- resolve = r;
22611
+ resolve2 = r;
22289
22612
  });
22290
- entry = { promise: promise2, resolve, settled: false };
22613
+ entry = { promise: promise2, resolve: resolve2, settled: false };
22291
22614
  pending.set(id, entry);
22292
22615
  }
22293
22616
  return entry;
@@ -22319,219 +22642,34 @@ function createDecisions(log = noopLogger) {
22319
22642
  };
22320
22643
  }
22321
22644
 
22322
- // src/plan-files.ts
22323
- import { readdirSync as readdirSync2, readFileSync as readFileSync6, realpathSync, statSync as statSync2 } from "fs";
22324
- import { extname, isAbsolute, join as join6, relative as relative2, resolve, sep } from "path";
22325
- var EXCERPT_RADIUS = 6;
22326
- var EXCERPT_HEAD_LINES = 13;
22327
- var MAX_EXCERPT_BYTES = 2 * 1024 * 1024;
22328
- var MAX_SCAN_ENTRIES = 5000;
22329
- var SKIP_DIRS = new Set(["node_modules", "dist", "build", "coverage", "out"]);
22330
- var EXT_LANGUAGE = {
22331
- ".ts": "typescript",
22332
- ".mts": "typescript",
22333
- ".cts": "typescript",
22334
- ".tsx": "tsx",
22335
- ".js": "javascript",
22336
- ".mjs": "javascript",
22337
- ".cjs": "javascript",
22338
- ".jsx": "jsx",
22339
- ".svelte": "svelte",
22340
- ".vue": "vue",
22341
- ".json": "json",
22342
- ".jsonc": "jsonc",
22343
- ".css": "css",
22344
- ".scss": "scss",
22345
- ".less": "less",
22346
- ".html": "html",
22347
- ".htm": "html",
22348
- ".xml": "xml",
22349
- ".svg": "xml",
22350
- ".md": "markdown",
22351
- ".mdx": "mdx",
22352
- ".py": "python",
22353
- ".rb": "ruby",
22354
- ".rs": "rust",
22355
- ".go": "go",
22356
- ".java": "java",
22357
- ".kt": "kotlin",
22358
- ".c": "c",
22359
- ".h": "c",
22360
- ".cc": "cpp",
22361
- ".cpp": "cpp",
22362
- ".hpp": "cpp",
22363
- ".sh": "shellscript",
22364
- ".bash": "shellscript",
22365
- ".zsh": "shellscript",
22366
- ".toml": "toml",
22367
- ".yaml": "yaml",
22368
- ".yml": "yaml",
22369
- ".ini": "ini",
22370
- ".sql": "sql",
22371
- ".graphql": "graphql",
22372
- ".gql": "graphql",
22373
- ".php": "php",
22374
- ".swift": "swift",
22375
- ".dart": "dart"
22376
- };
22377
- function languageForPath(path) {
22378
- return EXT_LANGUAGE[extname(path).toLowerCase()] ?? "text";
22379
- }
22380
- function safeRealpath(path) {
22381
- try {
22382
- return realpathSync(path);
22383
- } catch {
22384
- return null;
22385
- }
22386
- }
22387
- function containedFile(cwdReal, abs) {
22388
- const real = safeRealpath(abs);
22389
- if (real === null)
22390
- return null;
22391
- if (real !== cwdReal && !real.startsWith(cwdReal + sep))
22392
- return null;
22393
- try {
22394
- if (!statSync2(real).isFile())
22395
- return null;
22396
- } catch {
22397
- return null;
22398
- }
22399
- return real;
22400
- }
22401
- function basenameSearch(cwdReal, name) {
22402
- if (name === "")
22403
- return null;
22404
- let scanned = 0;
22405
- const queue = [cwdReal];
22406
- while (queue.length > 0) {
22407
- const currentDir = queue.shift();
22408
- let entries;
22409
- try {
22410
- entries = readdirSync2(currentDir, { withFileTypes: true });
22411
- } catch {
22412
- continue;
22413
- }
22414
- for (const entry of entries) {
22415
- if (++scanned > MAX_SCAN_ENTRIES)
22416
- return null;
22417
- if (entry.isFile()) {
22418
- if (entry.name === name)
22419
- return join6(currentDir, entry.name);
22420
- } else if (entry.isDirectory() && !SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
22421
- queue.push(join6(currentDir, entry.name));
22422
- }
22423
- }
22424
- }
22425
- return null;
22426
- }
22427
- function resolveFileInCwd(cwd, candidate) {
22428
- if (cwd === "" || !isAbsolute(cwd))
22429
- return null;
22430
- const cwdReal = safeRealpath(cwd);
22431
- if (cwdReal === null)
22432
- return null;
22433
- const cleaned = candidate.trim();
22434
- if (cleaned === "")
22435
- return null;
22436
- const direct = containedFile(cwdReal, resolve(cwdReal, cleaned));
22437
- if (direct !== null)
22438
- return direct;
22439
- const name = cleaned.split("/").pop() ?? "";
22440
- return basenameSearch(cwdReal, name);
22441
- }
22442
- function readFileExcerpt(cwd, candidate, line) {
22443
- const abs = resolveFileInCwd(cwd, candidate);
22444
- if (abs === null)
22445
- return null;
22446
- let size;
22447
- try {
22448
- size = statSync2(abs).size;
22449
- } catch {
22450
- return null;
22451
- }
22452
- if (size > MAX_EXCERPT_BYTES)
22453
- return null;
22454
- let content;
22455
- try {
22456
- content = readFileSync6(abs, "utf-8");
22457
- } catch {
22458
- return null;
22459
- }
22460
- if (content.includes("\x00"))
22461
- return null;
22462
- const allLines = content.split(`
22463
- `);
22464
- if (allLines.length > 1 && allLines[allLines.length - 1] === "")
22465
- allLines.pop();
22466
- const totalLines = allLines.length;
22467
- let startLine;
22468
- let endLine;
22469
- if (line !== undefined && line >= 1) {
22470
- const target = Math.min(line, totalLines);
22471
- startLine = Math.max(1, target - EXCERPT_RADIUS);
22472
- endLine = Math.min(totalLines, target + EXCERPT_RADIUS);
22473
- } else {
22474
- startLine = 1;
22475
- endLine = Math.min(totalLines, EXCERPT_HEAD_LINES);
22476
- }
22477
- const cwdReal = safeRealpath(cwd) ?? cwd;
22478
- return {
22479
- path: relative2(cwdReal, abs),
22480
- language: languageForPath(abs),
22481
- startLine,
22482
- endLine,
22483
- lines: allLines.slice(startLine - 1, endLine),
22484
- totalLines
22485
- };
22486
- }
22487
-
22488
- // src/prefs.ts
22489
- import { readFile as readFile2, writeFile } from "fs/promises";
22490
- import { dirname as dirname3 } from "path";
22491
- var DEFAULT_SET = { valid: ["default"], fallback: "default" };
22492
- async function readApproveMode(file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
22493
- try {
22494
- const parsed = JSON.parse(await readFile2(file2, "utf-8"));
22495
- if (typeof parsed.approveMode === "string" && set2.valid.includes(parsed.approveMode)) {
22496
- return parsed.approveMode;
22497
- }
22498
- log.debug("prefs", "unrecognized approve mode; using default");
22499
- return set2.fallback;
22500
- } catch (err) {
22501
- const absent = err?.code === "ENOENT";
22502
- log.debug("prefs", absent ? "no prefs file; using default approve mode" : "prefs unreadable; using default approve mode");
22503
- return set2.fallback;
22504
- }
22505
- }
22506
- async function writeApproveMode(mode, file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
22507
- if (!set2.valid.includes(mode)) {
22508
- log.warn("prefs", "ignoring invalid approve mode");
22509
- return;
22510
- }
22511
- ensureStateDir(dirname3(file2));
22512
- await writeFile(file2, JSON.stringify({ approveMode: mode }, null, 2), { mode: 384 });
22513
- log.debug("prefs", `approve mode saved: ${mode}`);
22514
- }
22515
-
22516
- // src/reviews.ts
22645
+ // src/review/threading.ts
22517
22646
  import { randomBytes } from "crypto";
22518
22647
 
22519
- // src/plan-file.ts
22520
- import { existsSync as existsSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
22521
- function writeCanonicalPlanFile(planFilePath, canonical, log) {
22522
- if (!planFilePath)
22523
- return;
22648
+ // src/plan/canonical-file.ts
22649
+ import { appendFileSync, existsSync as existsSync3, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
22650
+ function guardedPlanFileWrite(planFilePath, log, failMsg, write) {
22524
22651
  try {
22525
22652
  if (!planFilePath.endsWith(".md"))
22526
22653
  return;
22527
22654
  if (!existsSync3(planFilePath) || !statSync3(planFilePath).isFile())
22528
22655
  return;
22529
- writeFileSync2(planFilePath, canonical);
22656
+ write(planFilePath);
22530
22657
  } catch (err) {
22531
22658
  const code = err?.code;
22532
- log.warn("review", "plan file canonicalize failed", code ? { code } : {});
22659
+ log.warn("review", failMsg, code ? { code } : {});
22533
22660
  }
22534
22661
  }
22662
+ function writeCanonicalPlanFile(planFilePath, canonical, log) {
22663
+ if (!planFilePath)
22664
+ return;
22665
+ guardedPlanFileWrite(planFilePath, log, "plan file canonicalize failed", (p) => writeFileSync2(p, canonical));
22666
+ }
22667
+ function appendReviewerNotesToPlanFile(planFilePath, notes, log) {
22668
+ const section = reviewerNotesSection(notes);
22669
+ if (!planFilePath || section === "")
22670
+ return;
22671
+ guardedPlanFileWrite(planFilePath, log, "plan file notes append failed", (p) => appendFileSync(p, section));
22672
+ }
22535
22673
 
22536
22674
  // node_modules/.bun/prettier@3.8.3/node_modules/prettier/plugins/markdown.mjs
22537
22675
  var exports_markdown = {};
@@ -29265,7 +29403,7 @@ async function ci2(e, t) {
29265
29403
  var fi2 = me2(it, 0);
29266
29404
  var li2 = { parse: me2(In), formatAST: me2(kn), formatDoc: me2(vn), printToDoc: me2(Rn), printDocToString: me2(Ln) };
29267
29405
 
29268
- // src/plan-markdown.ts
29406
+ // src/plan/markdown.ts
29269
29407
  var MAX_FORMAT_BYTES = 1024 * 1024;
29270
29408
  async function prettierFormat(text) {
29271
29409
  return Jn2(text, {
@@ -29294,7 +29432,7 @@ async function formatPlanMarkdown(plan, log = noopLogger, doFormat = prettierFor
29294
29432
  }
29295
29433
  }
29296
29434
 
29297
- // src/reviews.ts
29435
+ // src/review/threading.ts
29298
29436
  function newReviewId() {
29299
29437
  return randomBytes(8).toString("base64url");
29300
29438
  }
@@ -29370,7 +29508,7 @@ async function routeIncomingPlan(input, store, log = noopLogger) {
29370
29508
  return { id, action: "new", version: 1, planEpoch, expired };
29371
29509
  }
29372
29510
 
29373
- // src/ui-log-bridge.ts
29511
+ // src/ui/log-bridge.ts
29374
29512
  var MAX_BODY_BYTES = 64 * 1024;
29375
29513
  var MAX_EVENTS = 100;
29376
29514
  var MAX_MSG_LEN = 256;
@@ -29419,105 +29557,11 @@ function parseUiLogBatch(raw) {
29419
29557
  return { events };
29420
29558
  }
29421
29559
 
29422
- // src/daemon.ts
29560
+ // src/daemon/server.ts
29423
29561
  var PLACEHOLDER_HTML = `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>caret</title></head><body><div id="app">caret daemon \u2014 UI not built yet</div></body></html>`;
29424
29562
  var INDEX_CACHE_CONTROL = "no-cache";
29425
29563
  var ASSET_CACHE_CONTROL = "public, max-age=31536000, immutable";
29426
29564
  var INDEX_PATH = "/index.html";
29427
- var VANITY_HOST = "caret.localhost";
29428
- var LIVE_CLIENT_WINDOW_MS = 120000;
29429
- function isClientLive(lastPollAt, now, windowMs) {
29430
- return lastPollAt !== 0 && now - lastPollAt < windowMs;
29431
- }
29432
- function isSafeMethod(method) {
29433
- return method === "GET" || method === "HEAD";
29434
- }
29435
- function isCrossOrigin(req) {
29436
- const origin = req.headers.get("origin");
29437
- if (origin) {
29438
- try {
29439
- const host = new URL(origin).hostname;
29440
- if (host !== "127.0.0.1" && host !== "localhost" && host !== VANITY_HOST)
29441
- return true;
29442
- } catch {
29443
- return true;
29444
- }
29445
- }
29446
- const site = req.headers.get("sec-fetch-site");
29447
- if (site && site !== "same-origin" && site !== "none")
29448
- return true;
29449
- return false;
29450
- }
29451
- var PlanInputSchema = exports_external.object({
29452
- sessionId: exports_external.string().optional(),
29453
- cwd: exports_external.string().optional(),
29454
- title: exports_external.string().optional(),
29455
- plan: exports_external.string().optional(),
29456
- planFilePath: exports_external.string().optional()
29457
- }).catch({});
29458
- var MAX_FILE_REFS = 200;
29459
- var FileRefsBodySchema = exports_external.object({ paths: exports_external.array(exports_external.string()).catch([]) }).catch({ paths: [] });
29460
- var BehaviorSchema = exports_external.enum(["allow", "deny"]);
29461
- var ResolveBodySchema = exports_external.object({
29462
- behavior: BehaviorSchema.catch("allow"),
29463
- feedback: exports_external.string().optional(),
29464
- acceptMode: exports_external.string().optional().catch(undefined)
29465
- }).catch({ behavior: "allow" });
29466
- var LineAnnotationSchema = exports_external.object({
29467
- id: exports_external.string(),
29468
- startLine: exports_external.number().int().min(1),
29469
- endLine: exports_external.number().int().min(1),
29470
- comment: exports_external.string(),
29471
- state: exports_external.enum(["pending", "approved", "rejected", "expired"]).optional()
29472
- }).refine((a) => a.endLine >= a.startLine, { message: "endLine must be >= startLine" });
29473
- var LegacyAnnotationSchema = exports_external.object({
29474
- id: exports_external.string(),
29475
- blockId: exports_external.string(),
29476
- startOffset: exports_external.number(),
29477
- endOffset: exports_external.number(),
29478
- quote: exports_external.string(),
29479
- prefix: exports_external.string().optional(),
29480
- suffix: exports_external.string().optional(),
29481
- comment: exports_external.string()
29482
- });
29483
- var AnnotationSchema = exports_external.union([LineAnnotationSchema, LegacyAnnotationSchema]);
29484
- var PersistedScratchSchema = exports_external.object({
29485
- startLine: exports_external.number().int().min(1),
29486
- endLine: exports_external.number().int().min(1),
29487
- text: exports_external.string()
29488
- }).refine((s) => s.endLine >= s.startLine, { message: "endLine must be >= startLine" });
29489
- function malformedLineAnchor(raw) {
29490
- if (typeof raw !== "object" || raw === null)
29491
- return null;
29492
- const anns = raw.annotations;
29493
- if (!Array.isArray(anns))
29494
- return null;
29495
- for (const a of anns) {
29496
- if (typeof a !== "object" || a === null)
29497
- continue;
29498
- if (!(("startLine" in a) || ("endLine" in a)))
29499
- continue;
29500
- const res = LineAnnotationSchema.safeParse(a);
29501
- if (!res.success)
29502
- return res.error.issues[0]?.message ?? "invalid line anchor";
29503
- }
29504
- return null;
29505
- }
29506
- var nullToUndefined = (v2) => v2 ?? undefined;
29507
- var DraftBodySchema = exports_external.object({
29508
- annotations: exports_external.array(AnnotationSchema).nullish().transform(nullToUndefined),
29509
- generalCommentDraft: exports_external.string().nullish().transform(nullToUndefined),
29510
- composerScratches: exports_external.array(PersistedScratchSchema).nullish().transform(nullToUndefined).catch(undefined),
29511
- version: exports_external.number().int().min(1).nullish().transform(nullToUndefined).catch(undefined)
29512
- }).catch({
29513
- annotations: undefined,
29514
- generalCommentDraft: undefined,
29515
- composerScratches: undefined,
29516
- version: undefined
29517
- });
29518
- async function parseBody(req, schema) {
29519
- return schema.parse(await req.json().catch(() => ({})));
29520
- }
29521
29565
  function resolveOptions(opts) {
29522
29566
  return {
29523
29567
  store: opts.store,
@@ -29533,6 +29577,7 @@ function resolveOptions(opts) {
29533
29577
  stateDir: opts.stateDir,
29534
29578
  instanceId: opts.instanceId,
29535
29579
  approveVariants: opts.approveVariants,
29580
+ source: opts.source,
29536
29581
  log: opts.log ?? noopLogger
29537
29582
  };
29538
29583
  }
@@ -29546,7 +29591,7 @@ function matchIdRoute(path) {
29546
29591
  function createServer(opts) {
29547
29592
  const cfg = resolveOptions(opts);
29548
29593
  const { store, idle, heartbeat, assets, onShutdown, routePlan, prefsPath, log } = cfg;
29549
- const { buildId, commit, stateDir: stateDir2, instanceId, approveVariants, lockPath } = cfg;
29594
+ const { buildId, commit, stateDir: stateDir2, instanceId, approveVariants, source, lockPath } = cfg;
29550
29595
  const { awaitDecision, resolveDecision, clearDecision, openDecisionCount } = createDecisions(log);
29551
29596
  const approveModeSet = approveVariants && approveVariants.length > 0 ? { valid: approveVariants.map((v2) => v2.id), fallback: approveVariants[0]?.id ?? "default" } : { valid: ["default"], fallback: "default" };
29552
29597
  function raceDecision(id, ms2) {
@@ -29603,7 +29648,9 @@ function createServer(opts) {
29603
29648
  stateDir: stateDir2,
29604
29649
  instanceId,
29605
29650
  isDev: !isCompiledBinary(),
29606
- ...approveVariants ? { approveVariants: [...approveVariants] } : {}
29651
+ ...process.env.CARET_FRESH === "1" ? { fresh: true } : {},
29652
+ ...approveVariants ? { approveVariants: [...approveVariants] } : {},
29653
+ ...source ? { source } : {}
29607
29654
  };
29608
29655
  return Response.json(body);
29609
29656
  }
@@ -29759,7 +29806,7 @@ function createServer(opts) {
29759
29806
  async function handleResolve(req, id) {
29760
29807
  const body = await parseBody(req, ResolveBodySchema);
29761
29808
  const existing = store.get(id);
29762
- if (!existing || existing.status !== "pending")
29809
+ if (existing?.status !== "pending")
29763
29810
  return notFound();
29764
29811
  const decision = {
29765
29812
  behavior: body.behavior === "deny" ? "deny" : "allow",
@@ -29793,7 +29840,7 @@ function createServer(opts) {
29793
29840
  async function handleExpire(id) {
29794
29841
  clearDecision(id);
29795
29842
  const existing = store.get(id);
29796
- if (!existing || existing.status !== "pending")
29843
+ if (existing?.status !== "pending")
29797
29844
  return notFound();
29798
29845
  await store.expire(id);
29799
29846
  log.info("review", `review expired: ${shortId(id)}`, {
@@ -29916,7 +29963,7 @@ function createServer(opts) {
29916
29963
  return { port: server.port ?? 0, stop };
29917
29964
  }
29918
29965
 
29919
- // src/store.ts
29966
+ // src/review/store.ts
29920
29967
  import { readdir, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
29921
29968
  import { join as join7 } from "path";
29922
29969
  function createStore(dir, log = noopLogger) {
@@ -30019,12 +30066,6 @@ function createStore(dir, log = noopLogger) {
30019
30066
  };
30020
30067
  }
30021
30068
 
30022
- // src/commands/boot.ts
30023
- function warnInvalidEnvVars(warn) {
30024
- for (const name of invalidEnvVars())
30025
- warn(`${name} invalid; using config/default`);
30026
- }
30027
-
30028
30069
  // src/commands/daemon.ts
30029
30070
  async function runDaemon(opts) {
30030
30071
  const svc = watchSettings(settings(), (changes) => log.info("settings", `settings changed: ${changes.join("; ")}`));
@@ -30054,6 +30095,7 @@ async function runDaemon(opts) {
30054
30095
  stateDir: stateDir(),
30055
30096
  instanceId: randomUUID().slice(0, 8),
30056
30097
  approveVariants: adapter.approveVariants,
30098
+ source: adapter.id,
30057
30099
  log
30058
30100
  });
30059
30101
  } catch (e) {
@@ -30658,7 +30700,7 @@ async function runPrewarm() {
30658
30700
  process.exit(0);
30659
30701
  }
30660
30702
 
30661
- // src/reconcile.ts
30703
+ // src/review/reconcile.ts
30662
30704
  async function runReconcile(stdin, deps) {
30663
30705
  const ctx = {};
30664
30706
  try {
@@ -32056,7 +32098,7 @@ var Xt2 = g.parseInline;
32056
32098
  var Vt2 = b2.parse;
32057
32099
  var Yt2 = x3.lex;
32058
32100
 
32059
- // src/plan-format.ts
32101
+ // src/plan/format.ts
32060
32102
  var PLAN_FORMAT_DENY_MESSAGE = "caret: this plan has a code block with no language marker, so it can't be " + "syntax-highlighted in the review UI. Add a language tag to every code block's " + "opening fence (e.g. ```ts, ```bash, ```json), and use `text` for non-code " + "blocks like directory trees, console output, or ASCII art. Then resubmit the plan.";
32061
32103
  function hasUntaggedCodeBlock(plan) {
32062
32104
  if (!plan?.trim())
@@ -32070,7 +32112,7 @@ function hasUntaggedCodeBlock(plan) {
32070
32112
  return untagged;
32071
32113
  }
32072
32114
 
32073
- // src/review.ts
32115
+ // src/review/orchestrate.ts
32074
32116
  function denyDecision(reason) {
32075
32117
  return { behavior: "deny", feedback: reason, decidedAt: Date.now() };
32076
32118
  }
@@ -32220,6 +32262,9 @@ async function runReviewSubcommand() {
32220
32262
  posted = { baseUrl, id };
32221
32263
  };
32222
32264
  const out = await runReview(stdin, deps);
32265
+ if (out.behavior === "allow" && out.feedback && hookInput?.planFilePath) {
32266
+ appendReviewerNotesToPlanFile(hookInput.planFilePath, out.feedback, { warn: logWarn });
32267
+ }
32223
32268
  respond(out);
32224
32269
  process.exit(0);
32225
32270
  }
@@ -34267,7 +34312,7 @@ function useColor() {
34267
34312
 
34268
34313
  // node_modules/.bun/commander@15.0.0/node_modules/commander/index.js
34269
34314
  var program = new Command;
34270
- // src/program.ts
34315
+ // src/lib/program.ts
34271
34316
  function createProgram(name, description) {
34272
34317
  return new Command().name(name).description(description).showHelpAfterError();
34273
34318
  }