@macintacos/caret 0.12.0 → 0.14.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 (106) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +13 -0
  3. package/dist/cli.js +808 -225
  4. package/package.json +2 -1
  5. package/ui/dist/assets/{angular-html-DMUNxAT7.js → angular-html-C0XElF0f.js} +1 -1
  6. package/ui/dist/assets/{angular-ts-CjN6OxaN.js → angular-ts-BVnV1Yg5.js} +1 -1
  7. package/ui/dist/assets/{apl-Dw4C1Sv3.js → apl-BFyMAB9c.js} +1 -1
  8. package/ui/dist/assets/{astro-DzXQf-F7.js → astro-DAtaAFYq.js} +1 -1
  9. package/ui/dist/assets/{blade-CTMS_AXM.js → blade-BoZH76v_.js} +1 -1
  10. package/ui/dist/assets/{c-DBanwSNn.js → c-DyRawzd0.js} +1 -1
  11. package/ui/dist/assets/{chapel-BTstFNqm.js → chapel-CAaCMdek.js} +1 -1
  12. package/ui/dist/assets/{cobol-Ca4PWvOz.js → cobol-BjXiLsat.js} +1 -1
  13. package/ui/dist/assets/{coffee-a9u7Cq0q.js → coffee-DvjcTlIE.js} +1 -1
  14. package/ui/dist/assets/{cpp-oowRqiuJ.js → cpp-sRP7rZGr.js} +1 -1
  15. package/ui/dist/assets/{crystal-D7O4UX-i.js → crystal-CaRkbKnA.js} +1 -1
  16. package/ui/dist/assets/{css-CZVl8Px8.js → css-Igh3vvbt.js} +1 -1
  17. package/ui/dist/assets/{dist-CdQe3tPj.js → dist-5Bv2mYWj.js} +1 -1
  18. package/ui/dist/assets/{dist-DpTOg-NC.js → dist-B5Dwvt_o.js} +1 -1
  19. package/ui/dist/assets/{dist-BbiHto2W.js → dist-BdaKUV8X.js} +1 -1
  20. package/ui/dist/assets/{dist-IHT5kND0.js → dist-BkB3Dkvt.js} +1 -1
  21. package/ui/dist/assets/{dist-DigqW6HL.js → dist-CBxRdWpx.js} +1 -1
  22. package/ui/dist/assets/dist-CF48ImGm.js +1 -0
  23. package/ui/dist/assets/{dist-pedI8d1Q.js → dist-CF4FIhxu.js} +1 -1
  24. package/ui/dist/assets/dist-CGl7bSLs.js +1 -0
  25. package/ui/dist/assets/{dist-vKL_CWkV.js → dist-CYIXdHF6.js} +1 -1
  26. package/ui/dist/assets/dist-CZeI5UV9.js +1 -0
  27. package/ui/dist/assets/{dist-BAGkWecZ.js → dist-C_lXyw3s.js} +1 -1
  28. package/ui/dist/assets/dist-CiBs4R_k.js +12 -0
  29. package/ui/dist/assets/{dist-Bc8Y8K-M.js → dist-D4FUs8dC.js} +1 -1
  30. package/ui/dist/assets/{dist-DaoC_D4S.js → dist-DHAfbOzU.js} +1 -1
  31. package/ui/dist/assets/{dist-CikfqRw0.js → dist-D_g9f9rz.js} +1 -1
  32. package/ui/dist/assets/{dist-CaX-VV5u.js → dist-Dt1D8SWK.js} +1 -1
  33. package/ui/dist/assets/{dist-C3qTFPSx.js → dist-YE9up3VR.js} +1 -1
  34. package/ui/dist/assets/{dist-CWGZKcUs.js → dist-lE2sJQyW.js} +1 -1
  35. package/ui/dist/assets/{edge-I4NpgvYm.js → edge-CvHTOXgI.js} +1 -1
  36. package/ui/dist/assets/{elixir-BJknh2p7.js → elixir-CtokNUaA.js} +1 -1
  37. package/ui/dist/assets/{elm-CRrD_tPY.js → elm-B34p-CC5.js} +1 -1
  38. package/ui/dist/assets/{erb-CROtc598.js → erb-FjaGN5LV.js} +1 -1
  39. package/ui/dist/assets/{git-rebase-BRtkWL3M.js → git-rebase-BFUCuD7O.js} +1 -1
  40. package/ui/dist/assets/{glimmer-js-lqkYwHrU.js → glimmer-js-CRs6sgzF.js} +1 -1
  41. package/ui/dist/assets/{glimmer-ts-CB5BuR0n.js → glimmer-ts-Bkt0v-q2.js} +1 -1
  42. package/ui/dist/assets/{glsl-CBceQiUy.js → glsl-Ckh3d22M.js} +1 -1
  43. package/ui/dist/assets/{graphql-Qo62WpvI.js → graphql-IqxoIj3x.js} +1 -1
  44. package/ui/dist/assets/{hack-BNJdjzLU.js → hack-DG1p8zpS.js} +1 -1
  45. package/ui/dist/assets/{haml-BMBtqt90.js → haml-DA2jQcOV.js} +1 -1
  46. package/ui/dist/assets/{handlebars-CBP-BQZd.js → handlebars-CqT0epoo.js} +1 -1
  47. package/ui/dist/assets/{html-Df586Ko0.js → html-CoTd-Axz.js} +1 -1
  48. package/ui/dist/assets/{html-derivative-yN18G809.js → html-derivative-DDt5A1xL.js} +1 -1
  49. package/ui/dist/assets/{http-YpWiVC6m.js → http-TEp9u8BR.js} +1 -1
  50. package/ui/dist/assets/{hurl-BfSO2S_0.js → hurl-OLD-GtJJ.js} +1 -1
  51. package/ui/dist/assets/index-BucWCjoT.js +6767 -0
  52. package/ui/dist/assets/index-Djrj2rps.css +1 -0
  53. package/ui/dist/assets/{java-BqL-WKyb.js → java-DYZ_BnxQ.js} +1 -1
  54. package/ui/dist/assets/{javascript-C7z4qtlP.js → javascript-B4vvB79r.js} +1 -1
  55. package/ui/dist/assets/{jinja-Dt2LjYg4.js → jinja-BTulBbvB.js} +1 -1
  56. package/ui/dist/assets/{jison-RhcomYXF.js → jison-CDVJmcGj.js} +1 -1
  57. package/ui/dist/assets/{json-C7RFwAc6.js → json-DahQZwqh.js} +1 -1
  58. package/ui/dist/assets/{jsx-DzVoS5cK.js → jsx-Dzcw0XhS.js} +1 -1
  59. package/ui/dist/assets/{julia-C86cVJ4I.js → julia-BB_aSeOr.js} +1 -1
  60. package/ui/dist/assets/{just-DLVt7fko.js → just-C3IsNIar.js} +1 -1
  61. package/ui/dist/assets/{latex-DRxirEYd.js → latex-D7dYt9yW.js} +1 -1
  62. package/ui/dist/assets/{liquid-BR_Lw-Bt.js → liquid-CO9g2vFd.js} +1 -1
  63. package/ui/dist/assets/{lua-CHeMByWu.js → lua-D6OK3PTP.js} +1 -1
  64. package/ui/dist/assets/{marko-B9JYg09W.js → marko-YPWiYUQ_.js} +1 -1
  65. package/ui/dist/assets/{mdc-BkqLhTks.js → mdc-DoQ9fqeC.js} +1 -1
  66. package/ui/dist/assets/{nginx-Jer0MbpA.js → nginx-BuX_dG5x.js} +1 -1
  67. package/ui/dist/assets/{nim-Cy_m8HmF.js → nim-oEF2CEaX.js} +1 -1
  68. package/ui/dist/assets/{org-CokmGrbo.js → org-C1kwr3b8.js} +1 -1
  69. package/ui/dist/assets/{perl-C8zK1dLy.js → perl-CzZcVIM9.js} +1 -1
  70. package/ui/dist/assets/{php-CGPNoYNj.js → php-C_i1TWmy.js} +1 -1
  71. package/ui/dist/assets/{pug-5sES-m6u.js → pug-Oz2JZVGZ.js} +1 -1
  72. package/ui/dist/assets/{qml-BJN6wOEM.js → qml-DWZFG7aa.js} +1 -1
  73. package/ui/dist/assets/{r-Byftp3ZA.js → r-CKwXeGZ_.js} +1 -1
  74. package/ui/dist/assets/{razor-DpZOlAnr.js → razor-DT1mg2x6.js} +1 -1
  75. package/ui/dist/assets/{regexp-BvqsLg1Y.js → regexp-C2K6ptTb.js} +1 -1
  76. package/ui/dist/assets/{rst-9vLxmSRm.js → rst-C5gmF0mo.js} +1 -1
  77. package/ui/dist/assets/{ruby-B0g6MeYE.js → ruby-CrEJdgPT.js} +1 -1
  78. package/ui/dist/assets/{sas-ho_fqc91.js → sas-D1TGFNd_.js} +1 -1
  79. package/ui/dist/assets/{scss-CXllYR3p.js → scss-DBO_Sp1C.js} +1 -1
  80. package/ui/dist/assets/{shellscript-CS4mUnIg.js → shellscript-QIWVo1P5.js} +1 -1
  81. package/ui/dist/assets/{shellsession-BErKFUp0.js → shellsession-iBMCyJwd.js} +1 -1
  82. package/ui/dist/assets/{soy-DLadX5Sh.js → soy-NHBvJjBh.js} +1 -1
  83. package/ui/dist/assets/{sql-D2_tJtd9.js → sql-Yf21hpnW.js} +1 -1
  84. package/ui/dist/assets/{stata-DeuspBBD.js → stata-CluZWHbV.js} +1 -1
  85. package/ui/dist/assets/{surrealql-Dsg6kBYD.js → surrealql-Bu2dU1Qj.js} +1 -1
  86. package/ui/dist/assets/{svelte-BLUhg5N2.js → svelte-Owb3qG7g.js} +1 -1
  87. package/ui/dist/assets/{templ-DmwzJEXE.js → templ-DScnsiaP.js} +1 -1
  88. package/ui/dist/assets/{tex-DvJatE2t.js → tex-DvCQ8DJI.js} +1 -1
  89. package/ui/dist/assets/{ts-tags-DopPyAVy.js → ts-tags-Fh6nOEbM.js} +1 -1
  90. package/ui/dist/assets/{tsx-Df8h3iwb.js → tsx-C_2AyD6m.js} +1 -1
  91. package/ui/dist/assets/{twig-D-FWilfB.js → twig-DjT0rOpv.js} +1 -1
  92. package/ui/dist/assets/{typescript-GaY7hgCy.js → typescript-NDIZTg4J.js} +1 -1
  93. package/ui/dist/assets/{typst-NzoQLrPM.js → typst-DNJZJFvq.js} +1 -1
  94. package/ui/dist/assets/{vue-DlAEzgCu.js → vue-BTZXwXJ_.js} +1 -1
  95. package/ui/dist/assets/{vue-html-ZDj41605.js → vue-html-CBhLp-FO.js} +1 -1
  96. package/ui/dist/assets/{vue-vine-cO7C1w8g.js → vue-vine-KGJI1qvi.js} +1 -1
  97. package/ui/dist/assets/{xml-Cw5Gpdej.js → xml-CeV6vl7T.js} +1 -1
  98. package/ui/dist/assets/{xsl-BJg3bH1H.js → xsl-CibkluSG.js} +1 -1
  99. package/ui/dist/assets/{yaml-kOrEV2t6.js → yaml-D89KUdIt.js} +1 -1
  100. package/ui/dist/index.html +3 -3
  101. package/ui/dist/assets/dist-ByhlQ0Ut.js +0 -1
  102. package/ui/dist/assets/dist-DfISJt9o.js +0 -12
  103. package/ui/dist/assets/dist-UGYOZkY4.js +0 -1
  104. package/ui/dist/assets/dist-oDQCW51e.js +0 -1
  105. package/ui/dist/assets/index-Dml6ilmw.css +0 -1
  106. package/ui/dist/assets/index-DxHUxDDf.js +0 -6766
package/dist/cli.js CHANGED
@@ -1994,7 +1994,7 @@ var require_thread_stream = __commonJS((exports, module) => {
1994
1994
  var { version: version2 } = require_package();
1995
1995
  var { EventEmitter } = __require("events");
1996
1996
  var { Worker } = __require("worker_threads");
1997
- var { join: join7 } = __require("path");
1997
+ var { join: join9 } = __require("path");
1998
1998
  var { pathToFileURL } = __require("url");
1999
1999
  var { wait } = require_wait();
2000
2000
  var {
@@ -2044,7 +2044,7 @@ var require_thread_stream = __commonJS((exports, module) => {
2044
2044
  function createWorker(stream, opts) {
2045
2045
  const { filename, workerData } = opts;
2046
2046
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
2047
- const toExecute = bundlerOverrides["thread-stream-worker"] || join7(__dirname, "lib", "worker.js");
2047
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join9(__dirname, "lib", "worker.js");
2048
2048
  const worker = new Worker(toExecute, {
2049
2049
  ...opts.workerOpts,
2050
2050
  name: opts.workerOpts?.name || "thread-stream",
@@ -2510,7 +2510,7 @@ var require_transport = __commonJS((exports, module) => {
2510
2510
  var { createRequire } = __require("module");
2511
2511
  var { existsSync: existsSync5 } = __require("fs");
2512
2512
  var getCallers = require_caller();
2513
- var { join: join7, isAbsolute, sep } = __require("path");
2513
+ var { join: join9, isAbsolute, sep: sep3 } = __require("path");
2514
2514
  var { fileURLToPath: fileURLToPath2 } = __require("url");
2515
2515
  var sleep = require_atomic_sleep();
2516
2516
  var onExit = require_on_exit_leak_free();
@@ -2663,7 +2663,7 @@ var require_transport = __commonJS((exports, module) => {
2663
2663
  throw new Error("only one of target or targets can be specified");
2664
2664
  }
2665
2665
  if (targets) {
2666
- target = bundlerOverrides["pino-worker"] || join7(__dirname, "worker.js");
2666
+ target = bundlerOverrides["pino-worker"] || join9(__dirname, "worker.js");
2667
2667
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
2668
2668
  return {
2669
2669
  ...dest,
@@ -2680,7 +2680,7 @@ var require_transport = __commonJS((exports, module) => {
2680
2680
  });
2681
2681
  });
2682
2682
  } else if (pipeline) {
2683
- target = bundlerOverrides["pino-worker"] || join7(__dirname, "worker.js");
2683
+ target = bundlerOverrides["pino-worker"] || join9(__dirname, "worker.js");
2684
2684
  options.pipelines = [pipeline.map((dest) => {
2685
2685
  return {
2686
2686
  ...dest,
@@ -2703,12 +2703,12 @@ var require_transport = __commonJS((exports, module) => {
2703
2703
  return origin;
2704
2704
  }
2705
2705
  if (origin === "pino/file") {
2706
- return join7(__dirname, "..", "file.js");
2706
+ return join9(__dirname, "..", "file.js");
2707
2707
  }
2708
2708
  let fixTarget2;
2709
2709
  for (const filePath of callers) {
2710
2710
  try {
2711
- const context = filePath === "node:repl" ? process.cwd() + sep : filePath;
2711
+ const context = filePath === "node:repl" ? process.cwd() + sep3 : filePath;
2712
2712
  fixTarget2 = createRequire(context).resolve(origin);
2713
2713
  break;
2714
2714
  } catch (err) {
@@ -3632,7 +3632,7 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
3632
3632
  return circularValue;
3633
3633
  }
3634
3634
  let res = "";
3635
- let join7 = ",";
3635
+ let join9 = ",";
3636
3636
  const originalIndentation = indentation;
3637
3637
  if (Array.isArray(value)) {
3638
3638
  if (value.length === 0) {
@@ -3646,7 +3646,7 @@ var require_safe_stable_stringify = __commonJS((exports, module) => {
3646
3646
  indentation += spacer;
3647
3647
  res += `
3648
3648
  ${indentation}`;
3649
- join7 = `,
3649
+ join9 = `,
3650
3650
  ${indentation}`;
3651
3651
  }
3652
3652
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3654,13 +3654,13 @@ ${indentation}`;
3654
3654
  for (;i < maximumValuesToStringify - 1; i++) {
3655
3655
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3656
3656
  res += tmp2 !== undefined ? tmp2 : "null";
3657
- res += join7;
3657
+ res += join9;
3658
3658
  }
3659
3659
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3660
3660
  res += tmp !== undefined ? tmp : "null";
3661
3661
  if (value.length - 1 > maximumBreadth) {
3662
3662
  const removedKeys = value.length - maximumBreadth - 1;
3663
- res += `${join7}"... ${getItemCount(removedKeys)} not stringified"`;
3663
+ res += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
3664
3664
  }
3665
3665
  if (spacer !== "") {
3666
3666
  res += `
@@ -3681,7 +3681,7 @@ ${originalIndentation}`;
3681
3681
  let separator = "";
3682
3682
  if (spacer !== "") {
3683
3683
  indentation += spacer;
3684
- join7 = `,
3684
+ join9 = `,
3685
3685
  ${indentation}`;
3686
3686
  whitespace = " ";
3687
3687
  }
@@ -3695,13 +3695,13 @@ ${indentation}`;
3695
3695
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
3696
3696
  if (tmp !== undefined) {
3697
3697
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3698
- separator = join7;
3698
+ separator = join9;
3699
3699
  }
3700
3700
  }
3701
3701
  if (keyLength > maximumBreadth) {
3702
3702
  const removedKeys = keyLength - maximumBreadth;
3703
3703
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
3704
- separator = join7;
3704
+ separator = join9;
3705
3705
  }
3706
3706
  if (spacer !== "" && separator.length > 1) {
3707
3707
  res = `
@@ -3741,7 +3741,7 @@ ${originalIndentation}`;
3741
3741
  }
3742
3742
  const originalIndentation = indentation;
3743
3743
  let res = "";
3744
- let join7 = ",";
3744
+ let join9 = ",";
3745
3745
  if (Array.isArray(value)) {
3746
3746
  if (value.length === 0) {
3747
3747
  return "[]";
@@ -3754,7 +3754,7 @@ ${originalIndentation}`;
3754
3754
  indentation += spacer;
3755
3755
  res += `
3756
3756
  ${indentation}`;
3757
- join7 = `,
3757
+ join9 = `,
3758
3758
  ${indentation}`;
3759
3759
  }
3760
3760
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3762,13 +3762,13 @@ ${indentation}`;
3762
3762
  for (;i < maximumValuesToStringify - 1; i++) {
3763
3763
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3764
3764
  res += tmp2 !== undefined ? tmp2 : "null";
3765
- res += join7;
3765
+ res += join9;
3766
3766
  }
3767
3767
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3768
3768
  res += tmp !== undefined ? tmp : "null";
3769
3769
  if (value.length - 1 > maximumBreadth) {
3770
3770
  const removedKeys = value.length - maximumBreadth - 1;
3771
- res += `${join7}"... ${getItemCount(removedKeys)} not stringified"`;
3771
+ res += `${join9}"... ${getItemCount(removedKeys)} not stringified"`;
3772
3772
  }
3773
3773
  if (spacer !== "") {
3774
3774
  res += `
@@ -3781,7 +3781,7 @@ ${originalIndentation}`;
3781
3781
  let whitespace = "";
3782
3782
  if (spacer !== "") {
3783
3783
  indentation += spacer;
3784
- join7 = `,
3784
+ join9 = `,
3785
3785
  ${indentation}`;
3786
3786
  whitespace = " ";
3787
3787
  }
@@ -3790,7 +3790,7 @@ ${indentation}`;
3790
3790
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
3791
3791
  if (tmp !== undefined) {
3792
3792
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
3793
- separator = join7;
3793
+ separator = join9;
3794
3794
  }
3795
3795
  }
3796
3796
  if (spacer !== "" && separator.length > 1) {
@@ -3847,20 +3847,20 @@ ${originalIndentation}`;
3847
3847
  indentation += spacer;
3848
3848
  let res2 = `
3849
3849
  ${indentation}`;
3850
- const join8 = `,
3850
+ const join10 = `,
3851
3851
  ${indentation}`;
3852
3852
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
3853
3853
  let i = 0;
3854
3854
  for (;i < maximumValuesToStringify - 1; i++) {
3855
3855
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3856
3856
  res2 += tmp2 !== undefined ? tmp2 : "null";
3857
- res2 += join8;
3857
+ res2 += join10;
3858
3858
  }
3859
3859
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3860
3860
  res2 += tmp !== undefined ? tmp : "null";
3861
3861
  if (value.length - 1 > maximumBreadth) {
3862
3862
  const removedKeys = value.length - maximumBreadth - 1;
3863
- res2 += `${join8}"... ${getItemCount(removedKeys)} not stringified"`;
3863
+ res2 += `${join10}"... ${getItemCount(removedKeys)} not stringified"`;
3864
3864
  }
3865
3865
  res2 += `
3866
3866
  ${originalIndentation}`;
@@ -3876,16 +3876,16 @@ ${originalIndentation}`;
3876
3876
  return '"[Object]"';
3877
3877
  }
3878
3878
  indentation += spacer;
3879
- const join7 = `,
3879
+ const join9 = `,
3880
3880
  ${indentation}`;
3881
3881
  let res = "";
3882
3882
  let separator = "";
3883
3883
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
3884
3884
  if (isTypedArrayWithEntries(value)) {
3885
- res += stringifyTypedArray(value, join7, maximumBreadth);
3885
+ res += stringifyTypedArray(value, join9, maximumBreadth);
3886
3886
  keys = keys.slice(value.length);
3887
3887
  maximumPropertiesToStringify -= value.length;
3888
- separator = join7;
3888
+ separator = join9;
3889
3889
  }
3890
3890
  if (deterministic) {
3891
3891
  keys = sort(keys, comparator);
@@ -3896,13 +3896,13 @@ ${indentation}`;
3896
3896
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
3897
3897
  if (tmp !== undefined) {
3898
3898
  res += `${separator}${strEscape(key2)}: ${tmp}`;
3899
- separator = join7;
3899
+ separator = join9;
3900
3900
  }
3901
3901
  }
3902
3902
  if (keyLength > maximumBreadth) {
3903
3903
  const removedKeys = keyLength - maximumBreadth;
3904
3904
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
3905
- separator = join7;
3905
+ separator = join9;
3906
3906
  }
3907
3907
  if (separator !== "") {
3908
3908
  res = `
@@ -5804,7 +5804,7 @@ __export(exports_dist, {
5804
5804
  import { styleText as styleText2, stripVTControlCharacters } from "util";
5805
5805
  import process$1 from "process";
5806
5806
  import { existsSync as existsSync11, lstatSync, readdirSync as readdirSync6 } from "fs";
5807
- import { dirname as dirname8, join as join14 } from "path";
5807
+ import { dirname as dirname9, join as join17 } from "path";
5808
5808
  function isUnicodeSupported() {
5809
5809
  if (process$1.platform !== "win32") {
5810
5810
  return process$1.env.TERM !== "linux";
@@ -6515,10 +6515,10 @@ ${n3}
6515
6515
  return [];
6516
6516
  try {
6517
6517
  let i;
6518
- existsSync11(t2) ? lstatSync(t2).isDirectory() && (!e.directory || t2.endsWith("/")) ? i = t2 : i = dirname8(t2) : i = dirname8(t2);
6518
+ existsSync11(t2) ? lstatSync(t2).isDirectory() && (!e.directory || t2.endsWith("/")) ? i = t2 : i = dirname9(t2) : i = dirname9(t2);
6519
6519
  const c2 = t2.length > 1 && t2.endsWith("/") ? t2.slice(0, -1) : t2;
6520
6520
  return readdirSync6(i).map((r2) => {
6521
- const n3 = join14(i, r2), m3 = lstatSync(n3);
6521
+ const n3 = join17(i, r2), m3 = lstatSync(n3);
6522
6522
  return {
6523
6523
  name: r2,
6524
6524
  path: n3,
@@ -7066,9 +7066,18 @@ function fatalDenyLine(reason) {
7066
7066
  });
7067
7067
  }
7068
7068
 
7069
- // src/adapters/claude/install.ts
7069
+ // src/adapters/claude/paths.ts
7070
7070
  import { homedir } from "os";
7071
7071
  import { join } from "path";
7072
+ function claudeConfigDir() {
7073
+ return process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
7074
+ }
7075
+ function installedPluginsFile() {
7076
+ return join(claudeConfigDir(), "plugins", "installed_plugins.json");
7077
+ }
7078
+ function userSettingsFile() {
7079
+ return join(claudeConfigDir(), "settings.json");
7080
+ }
7072
7081
 
7073
7082
  // src/lib/json-file.ts
7074
7083
  import { readFileSync } from "fs";
@@ -7089,16 +7098,12 @@ async function readJsonFile(path) {
7089
7098
  }
7090
7099
 
7091
7100
  // src/adapters/claude/install.ts
7092
- function claudeConfigDir() {
7093
- return process.env.CLAUDE_CONFIG_DIR || join(homedir(), ".claude");
7094
- }
7095
7101
  var PLUGIN_ID = "caret@caret";
7096
7102
  function readClaudeInstallState() {
7097
- const dir = claudeConfigDir();
7098
7103
  return {
7099
- pluginVersion: readPluginVersion(join(dir, "plugins", "installed_plugins.json")),
7100
- pluginEnabled: readPluginEnabled(join(dir, "settings.json")),
7101
- hookInUserSettings: readHookInUserSettings(join(dir, "settings.json"))
7104
+ pluginVersion: readPluginVersion(installedPluginsFile()),
7105
+ pluginEnabled: readPluginEnabled(userSettingsFile()),
7106
+ hookInUserSettings: readHookInUserSettings(userSettingsFile())
7102
7107
  };
7103
7108
  }
7104
7109
  function readPluginVersion(path) {
@@ -7141,6 +7146,180 @@ function readHookInUserSettings(path) {
7141
7146
  return false;
7142
7147
  }
7143
7148
 
7149
+ // src/adapters/claude/skills.ts
7150
+ import { access, readdir } from "fs/promises";
7151
+ import { join as join3 } from "path";
7152
+
7153
+ // src/lib/skill-doc.ts
7154
+ import { readFile as readFile2, realpath, stat } from "fs/promises";
7155
+ import { join as join2, sep } from "path";
7156
+ var FENCE = "---";
7157
+ var MAX_DOC_BYTES = 1024 * 1024;
7158
+ var DESCRIPTION_LINE = /^description:[ \t]*(.*)$/;
7159
+ var BLOCK_INTRODUCER = /^([|>])[-+]?\d*$/;
7160
+ function blockJoiner(value) {
7161
+ const introducer = BLOCK_INTRODUCER.exec(value)?.[1];
7162
+ if (introducer === undefined)
7163
+ return;
7164
+ return introducer === "|" ? `
7165
+ ` : " ";
7166
+ }
7167
+ async function containedFile(root, relative) {
7168
+ const [rootReal, real] = await Promise.all([
7169
+ realpath(root).catch(() => null),
7170
+ realpath(join2(root, relative)).catch(() => null)
7171
+ ]);
7172
+ if (rootReal === null || real === null)
7173
+ return null;
7174
+ return real === rootReal || real.startsWith(rootReal + sep) ? real : null;
7175
+ }
7176
+ function frontmatterLines(content) {
7177
+ const lines = content.split(`
7178
+ `).map((line) => line.replace(/\r$/, ""));
7179
+ if (lines[0]?.trimEnd() !== FENCE)
7180
+ return null;
7181
+ const close = lines.findIndex((line, i) => i > 0 && line.trimEnd() === FENCE);
7182
+ return close === -1 ? null : lines.slice(1, close);
7183
+ }
7184
+ function unquote(value) {
7185
+ const quote = value[0];
7186
+ if ((quote === '"' || quote === "'") && value.length > 1 && value.endsWith(quote)) {
7187
+ return value.slice(1, -1);
7188
+ }
7189
+ return value;
7190
+ }
7191
+ function blockScalar(rest, joiner) {
7192
+ const taken = [];
7193
+ for (const line of rest) {
7194
+ if (line.trim() !== "" && !/^[ \t]/.test(line))
7195
+ break;
7196
+ taken.push(line.trim());
7197
+ }
7198
+ const kept = joiner === `
7199
+ ` ? taken : taken.filter((line) => line !== "");
7200
+ return kept.join(joiner).trim();
7201
+ }
7202
+ function descriptionIn(block) {
7203
+ const at = block.findIndex((line) => DESCRIPTION_LINE.test(line));
7204
+ if (at === -1)
7205
+ return null;
7206
+ const value = (block[at]?.match(DESCRIPTION_LINE)?.[1] ?? "").trimEnd();
7207
+ const joiner = blockJoiner(value);
7208
+ const text = joiner === undefined ? unquote(value).trim() : blockScalar(block.slice(at + 1), joiner);
7209
+ return text === "" ? null : text;
7210
+ }
7211
+ async function descriptionOf(abs) {
7212
+ const size = await stat(abs).then((s) => s.size, () => null);
7213
+ if (size === null || size > MAX_DOC_BYTES)
7214
+ return null;
7215
+ let content;
7216
+ try {
7217
+ content = await readFile2(abs, "utf-8");
7218
+ } catch {
7219
+ return null;
7220
+ }
7221
+ const block = frontmatterLines(content);
7222
+ return block === null ? null : descriptionIn(block);
7223
+ }
7224
+ async function readDescriptionUnder(root, relative) {
7225
+ const abs = await containedFile(root, relative);
7226
+ return abs === null ? null : descriptionOf(abs);
7227
+ }
7228
+
7229
+ // src/adapters/claude/skills.ts
7230
+ var SKILL_FILE = "SKILL.md";
7231
+ async function skillNamesUnder(root) {
7232
+ let names;
7233
+ try {
7234
+ names = await readdir(root);
7235
+ } catch {
7236
+ return [];
7237
+ }
7238
+ const found = await Promise.all(names.map((name) => hasSkillFile(join3(root, name))));
7239
+ return names.filter((_, i) => found[i]).sort();
7240
+ }
7241
+ async function hasSkillFile(dir) {
7242
+ try {
7243
+ await access(join3(dir, SKILL_FILE));
7244
+ return true;
7245
+ } catch {
7246
+ return false;
7247
+ }
7248
+ }
7249
+ function settingsLayers(cwd) {
7250
+ const userDir = claudeConfigDir();
7251
+ return [
7252
+ userSettingsFile(),
7253
+ join3(userDir, "settings.local.json"),
7254
+ join3(cwd, ".claude", "settings.json"),
7255
+ join3(cwd, ".claude", "settings.local.json")
7256
+ ];
7257
+ }
7258
+ var userSkillsRoot = () => join3(claudeConfigDir(), "skills");
7259
+ var projectSkillsRoot = (cwd) => join3(cwd, ".claude", "skills");
7260
+ var pluginSkillsRoot = (install) => join3(install, "skills");
7261
+ async function enabledPluginKeys(cwd) {
7262
+ const layers = await Promise.all(settingsLayers(cwd).map((path) => readJsonFile(path)));
7263
+ const merged = {};
7264
+ for (const layer of layers)
7265
+ Object.assign(merged, layer?.enabledPlugins ?? {});
7266
+ return new Set(Object.keys(merged).filter((key) => merged[key] === true));
7267
+ }
7268
+ function pickInstallPath(installs, cwd) {
7269
+ const usable = installs.filter((install) => typeof install.installPath === "string");
7270
+ const here = usable.find((install) => install.projectPath === cwd);
7271
+ const anywhere = usable.find((install) => install.scope === "user" || install.scope === "managed");
7272
+ return (here ?? anywhere ?? usable[0])?.installPath;
7273
+ }
7274
+ async function enabledPlugins(cwd) {
7275
+ const [registry, enabled] = await Promise.all([
7276
+ readJsonFile(installedPluginsFile()),
7277
+ enabledPluginKeys(cwd)
7278
+ ]);
7279
+ const out = [];
7280
+ for (const [key, installs] of Object.entries(registry?.plugins ?? {})) {
7281
+ if (!enabled.has(key))
7282
+ continue;
7283
+ const installPath = pickInstallPath(installs ?? [], cwd);
7284
+ if (installPath === undefined)
7285
+ continue;
7286
+ out.push([key.split("@")[0] ?? key, installPath]);
7287
+ }
7288
+ return out.sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
7289
+ }
7290
+ async function readClaudeSkills(cwd) {
7291
+ const [user, project, plugins] = await Promise.all([
7292
+ skillNamesUnder(userSkillsRoot()),
7293
+ skillNamesUnder(projectSkillsRoot(cwd)),
7294
+ enabledPlugins(cwd)
7295
+ ]);
7296
+ const pluginSkills = await Promise.all(plugins.map(async ([plugin, dir]) => (await skillNamesUnder(pluginSkillsRoot(dir))).map((name) => ({ name: `${plugin}:${name}`, origin: "plugin" }))));
7297
+ return [
7298
+ ...user.map((name) => ({ name, origin: "user" })),
7299
+ ...project.map((name) => ({ name, origin: "project" })),
7300
+ ...pluginSkills.flat()
7301
+ ];
7302
+ }
7303
+ async function skillDocLocation(cwd, skill) {
7304
+ const under = (root, name) => ({ root, relative: join3(name, SKILL_FILE) });
7305
+ if (skill.origin === "user")
7306
+ return under(userSkillsRoot(), skill.name);
7307
+ if (skill.origin === "project")
7308
+ return under(projectSkillsRoot(cwd), skill.name);
7309
+ if (skill.origin !== "plugin")
7310
+ return null;
7311
+ const at = skill.name.indexOf(":");
7312
+ if (at === -1)
7313
+ return null;
7314
+ const plugin = skill.name.slice(0, at);
7315
+ const hit = (await enabledPlugins(cwd)).find(([key]) => key === plugin);
7316
+ return hit === undefined ? null : under(pluginSkillsRoot(hit[1]), skill.name.slice(at + 1));
7317
+ }
7318
+ async function readClaudeSkillDescription(cwd, skill) {
7319
+ const at = await skillDocLocation(cwd, skill);
7320
+ return at === null ? null : readDescriptionUnder(at.root, at.relative);
7321
+ }
7322
+
7144
7323
  // src/adapters/claude/index.ts
7145
7324
  function toolInputEcho(input) {
7146
7325
  if (!input)
@@ -7177,6 +7356,12 @@ var claudeAdapter = {
7177
7356
  },
7178
7357
  readInstallState() {
7179
7358
  return readClaudeInstallState();
7359
+ },
7360
+ listSkills(cwd) {
7361
+ return readClaudeSkills(cwd);
7362
+ },
7363
+ readSkillDescription(cwd, skill) {
7364
+ return readClaudeSkillDescription(cwd, skill);
7180
7365
  }
7181
7366
  };
7182
7367
 
@@ -7214,7 +7399,7 @@ function fatalDenyLine2(reason) {
7214
7399
  // src/adapters/codex/install.ts
7215
7400
  import { readFileSync as readFileSync2 } from "fs";
7216
7401
  import { homedir as homedir2 } from "os";
7217
- import { join as join2 } from "path";
7402
+ import { join as join4 } from "path";
7218
7403
 
7219
7404
  // node_modules/.bun/smol-toml@1.8.0/node_modules/smol-toml/dist/date.js
7220
7405
  /*!
@@ -7468,7 +7653,7 @@ function skipVoid(ctx, banNewLines, banComments) {
7468
7653
  skipComment(ctx);
7469
7654
  }
7470
7655
  }
7471
- function skipUntil(ctx, sep, end) {
7656
+ function skipUntil(ctx, sep2, end) {
7472
7657
  let ptr = ctx.p;
7473
7658
  if (!end) {
7474
7659
  ptr = indexOfNewline(ctx.s, ptr);
@@ -7479,7 +7664,7 @@ function skipUntil(ctx, sep, end) {
7479
7664
  let c = ctx.s.charCodeAt(ctx.p);
7480
7665
  if (c === 35) {
7481
7666
  skipComment(ctx);
7482
- } else if (c === end || c === sep) {
7667
+ } else if (c === end || c === sep2) {
7483
7668
  return;
7484
7669
  }
7485
7670
  }
@@ -8095,14 +8280,14 @@ function parse(toml, { maxDepth = 1000, integersAsBigInt } = {}) {
8095
8280
 
8096
8281
  // src/adapters/codex/install.ts
8097
8282
  function codexConfigDir() {
8098
- return process.env.CODEX_HOME || join2(homedir2(), ".codex");
8283
+ return process.env.CODEX_HOME || join4(homedir2(), ".codex");
8099
8284
  }
8100
8285
  function readCodexInstallState() {
8101
8286
  const dir = codexConfigDir();
8102
8287
  return {
8103
8288
  pluginVersion: "unknown",
8104
- pluginEnabled: readCodexHooksFeature(join2(dir, "config.toml")),
8105
- hookInUserSettings: readHookInUserSettings2(join2(dir, "hooks.json"))
8289
+ pluginEnabled: readCodexHooksFeature(join4(dir, "config.toml")),
8290
+ hookInUserSettings: readHookInUserSettings2(join4(dir, "hooks.json"))
8106
8291
  };
8107
8292
  }
8108
8293
  function readCodexHooksFeature(path) {
@@ -8158,6 +8343,12 @@ var codexAdapter = {
8158
8343
  },
8159
8344
  readInstallState() {
8160
8345
  return readCodexInstallState();
8346
+ },
8347
+ listSkills() {
8348
+ return Promise.resolve([]);
8349
+ },
8350
+ readSkillDescription() {
8351
+ return Promise.resolve(null);
8161
8352
  }
8162
8353
  };
8163
8354
 
@@ -8180,7 +8371,7 @@ function fatalDenyLine3(reason) {
8180
8371
 
8181
8372
  // src/adapters/opencode/install.ts
8182
8373
  import { existsSync as existsSync3, readFileSync as readFileSync4 } from "fs";
8183
- import { join as join5 } from "path";
8374
+ import { join as join7 } from "path";
8184
8375
 
8185
8376
  // node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
8186
8377
  function createScanner(text, ignoreTrivia = false) {
@@ -8962,11 +9153,11 @@ function parseTree(text, errors = [], options = ParseOptions.DEFAULT) {
8962
9153
  onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
8963
9154
  ensurePropertyComplete(offset + length);
8964
9155
  },
8965
- onSeparator: (sep, offset, length) => {
9156
+ onSeparator: (sep2, offset, length) => {
8966
9157
  if (currentParent.type === "property") {
8967
- if (sep === ":") {
9158
+ if (sep2 === ":") {
8968
9159
  currentParent.colonOffset = offset;
8969
- } else if (sep === ",") {
9160
+ } else if (sep2 === ",") {
8970
9161
  ensurePropertyComplete(offset);
8971
9162
  }
8972
9163
  }
@@ -9508,7 +9699,7 @@ function applyEdits(text, edits) {
9508
9699
  // src/adapters/opencode/paths.ts
9509
9700
  import { existsSync, readdirSync } from "fs";
9510
9701
  import { homedir as homedir3 } from "os";
9511
- import { basename, dirname, join as join3 } from "path";
9702
+ import { basename, dirname, join as join5 } from "path";
9512
9703
  var CARET_PACKAGE = "@macintacos/caret";
9513
9704
  function localPluginSpecifier(repoDir) {
9514
9705
  return `file:${repoDir}`;
@@ -9530,39 +9721,42 @@ function opencodeConfigDir() {
9530
9721
  if (override)
9531
9722
  return override;
9532
9723
  const xdg = process.env.XDG_CONFIG_HOME?.trim();
9533
- return join3(xdg || join3(homedir3(), ".config"), "opencode");
9724
+ return join5(xdg || join5(homedir3(), ".config"), "opencode");
9534
9725
  }
9535
9726
  function resolveConfigFile(configDir) {
9536
9727
  for (const name of CONFIG_FILENAMES) {
9537
- const p = join3(configDir, name);
9728
+ const p = join5(configDir, name);
9538
9729
  if (existsSync(p))
9539
9730
  return p;
9540
9731
  }
9541
- return join3(configDir, "opencode.json");
9732
+ return join5(configDir, "opencode.json");
9542
9733
  }
9543
9734
  function commandDir(configDir) {
9544
- return join3(configDir, COMMAND_DIRNAME);
9735
+ return join5(configDir, COMMAND_DIRNAME);
9736
+ }
9737
+ function commandDirs(configDir) {
9738
+ return [commandDir(configDir), join5(configDir, LEGACY_COMMAND_DIRNAME)];
9545
9739
  }
9546
9740
  var LEGACY_PLUGIN_FILENAME = "caret.ts";
9547
9741
  var LEGACY_PLUGIN_DIRNAMES = ["plugins", "plugin"];
9548
9742
  var LEGACY_COMMAND_DIRNAME = "command";
9549
9743
  function existingLegacyInstallFiles(configDir) {
9550
- const plugins = LEGACY_PLUGIN_DIRNAMES.map((d) => join3(configDir, d, LEGACY_PLUGIN_FILENAME));
9744
+ const plugins = LEGACY_PLUGIN_DIRNAMES.map((d) => join5(configDir, d, LEGACY_PLUGIN_FILENAME));
9551
9745
  let entries;
9552
9746
  try {
9553
- entries = readdirSync(join3(configDir, LEGACY_COMMAND_DIRNAME), { withFileTypes: true });
9747
+ entries = readdirSync(join5(configDir, LEGACY_COMMAND_DIRNAME), { withFileTypes: true });
9554
9748
  } catch {
9555
9749
  entries = [];
9556
9750
  }
9557
- const commands = entries.filter((e) => !e.isDirectory() && e.name.startsWith(COMMAND_NAMESPACE)).filter((e) => e.name.endsWith(".md")).map((e) => join3(configDir, LEGACY_COMMAND_DIRNAME, e.name)).sort();
9751
+ const commands = entries.filter((e) => !e.isDirectory() && e.name.startsWith(COMMAND_NAMESPACE)).filter((e) => e.name.endsWith(".md")).map((e) => join5(configDir, LEGACY_COMMAND_DIRNAME, e.name)).sort();
9558
9752
  return [...plugins, ...commands].filter((p) => existsSync(p));
9559
9753
  }
9560
9754
  function opencodeCachePackagesDir() {
9561
9755
  const xdg = process.env.XDG_CACHE_HOME?.trim();
9562
- return join3(xdg || join3(homedir3(), ".cache"), "opencode", "packages");
9756
+ return join5(xdg || join5(homedir3(), ".cache"), "opencode", "packages");
9563
9757
  }
9564
9758
  function opencodeCachePackageDir(pkg = CARET_PACKAGE) {
9565
- return join3(opencodeCachePackagesDir(), pkg);
9759
+ return join5(opencodeCachePackagesDir(), pkg);
9566
9760
  }
9567
9761
  function existingOpencodeCachePackageDirs(pkg = CARET_PACKAGE) {
9568
9762
  const bare = opencodeCachePackageDir(pkg);
@@ -9575,12 +9769,12 @@ function existingOpencodeCachePackageDirs(pkg = CARET_PACKAGE) {
9575
9769
  return [];
9576
9770
  }
9577
9771
  const pinned = names.filter((n) => n.startsWith(`${leaf}@`)).sort();
9578
- return [...names.includes(leaf) ? [bare] : [], ...pinned.map((n) => join3(parent, n))];
9772
+ return [...names.includes(leaf) ? [bare] : [], ...pinned.map((n) => join5(parent, n))];
9579
9773
  }
9580
9774
 
9581
9775
  // src/adapters/opencode/upgrade.ts
9582
9776
  import { existsSync as existsSync2, readFileSync as readFileSync3, rmSync } from "fs";
9583
- import { join as join4 } from "path";
9777
+ import { join as join6 } from "path";
9584
9778
 
9585
9779
  // src/adapters/opencode/config-plugin.ts
9586
9780
  var FORMATTING = { insertSpaces: true, tabSize: 2 };
@@ -9647,9 +9841,7 @@ function removePluginFromConfigText(existing, pkg) {
9647
9841
  return applyEdits(existing, edits);
9648
9842
  }
9649
9843
 
9650
- // src/adapters/opencode/upgrade.ts
9651
- var NPM_LATEST_URL = `https://registry.npmjs.org/${CARET_PACKAGE}/latest`;
9652
- var NPM_TIMEOUT_MS = 3000;
9844
+ // src/lib/semver.ts
9653
9845
  function parseVersionTriple(v) {
9654
9846
  const m = v.trim().replace(/^v/, "").match(/^(\d+)\.(\d+)\.(\d+)/);
9655
9847
  return m ? [Number(m[1]), Number(m[2]), Number(m[3])] : null;
@@ -9667,6 +9859,8 @@ function isNewer(latest, current) {
9667
9859
  return a1 > b1;
9668
9860
  return a2 > b2;
9669
9861
  }
9862
+
9863
+ // src/adapters/opencode/upgrade.ts
9670
9864
  function upgradeVerdict(input) {
9671
9865
  const { entry, cached, published } = input;
9672
9866
  if (published === null) {
@@ -9691,7 +9885,7 @@ function upgradeVerdict(input) {
9691
9885
  function readCachedCaretVersion(dirs = existingOpencodeCachePackageDirs()) {
9692
9886
  for (const d of dirs) {
9693
9887
  try {
9694
- const deps = JSON.parse(readFileSync3(join4(d, "package.json"), "utf-8")).dependencies;
9888
+ const deps = JSON.parse(readFileSync3(join6(d, "package.json"), "utf-8")).dependencies;
9695
9889
  const v = deps?.[CARET_PACKAGE];
9696
9890
  if (typeof v === "string" && v.length > 0)
9697
9891
  return v;
@@ -9709,18 +9903,6 @@ function clearCachedCaret(dirs = existingOpencodeCachePackageDirs()) {
9709
9903
  }
9710
9904
  return cleared;
9711
9905
  }
9712
- async function publishedCaretVersion(fetchImpl = fetch) {
9713
- try {
9714
- const res = await fetchImpl(NPM_LATEST_URL, { signal: AbortSignal.timeout(NPM_TIMEOUT_MS) });
9715
- if (!res.ok)
9716
- return null;
9717
- const body = await res.json();
9718
- const v = body?.version;
9719
- return typeof v === "string" && v.length > 0 ? v : null;
9720
- } catch {
9721
- return null;
9722
- }
9723
- }
9724
9906
 
9725
9907
  // src/adapters/opencode/install.ts
9726
9908
  function readOpencodeInstallState() {
@@ -9738,7 +9920,7 @@ function readOpencodeInstallState() {
9738
9920
  function readCaretInPluginArray(dir) {
9739
9921
  let sawConfig = false;
9740
9922
  for (const name of CONFIG_FILENAMES) {
9741
- const path = join5(dir, name);
9923
+ const path = join7(dir, name);
9742
9924
  if (!existsSync3(path))
9743
9925
  continue;
9744
9926
  let cfg;
@@ -9758,6 +9940,33 @@ function readCaretInPluginArray(dir) {
9758
9940
  return sawConfig ? false : "unknown";
9759
9941
  }
9760
9942
 
9943
+ // src/adapters/opencode/skills.ts
9944
+ import { readdir as readdir2 } from "fs/promises";
9945
+ import { sep as sep2 } from "path";
9946
+ async function commandNamesUnder(dir) {
9947
+ let entries;
9948
+ try {
9949
+ entries = await readdir2(dir, { recursive: true });
9950
+ } catch {
9951
+ return [];
9952
+ }
9953
+ return entries.filter((rel) => rel.endsWith(".md")).map((rel) => rel.slice(0, -".md".length).split(sep2).join("/"));
9954
+ }
9955
+ async function readOpencodeCommands() {
9956
+ const perDir = await Promise.all(commandDirs(opencodeConfigDir()).map(commandNamesUnder));
9957
+ const names = new Set(perDir.flat());
9958
+ return [...names].sort().map((name) => ({ name, origin: "command" }));
9959
+ }
9960
+ async function readOpencodeCommandDescription(name) {
9961
+ const relative = `${name}.md`;
9962
+ for (const dir of commandDirs(opencodeConfigDir())) {
9963
+ const abs = await containedFile(dir, relative);
9964
+ if (abs !== null)
9965
+ return descriptionOf(abs);
9966
+ }
9967
+ return null;
9968
+ }
9969
+
9761
9970
  // src/adapters/opencode/index.ts
9762
9971
  var opencodeAdapter = {
9763
9972
  id: "opencode",
@@ -9784,6 +9993,12 @@ var opencodeAdapter = {
9784
9993
  },
9785
9994
  readInstallState() {
9786
9995
  return readOpencodeInstallState();
9996
+ },
9997
+ listSkills() {
9998
+ return readOpencodeCommands();
9999
+ },
10000
+ readSkillDescription(_cwd, skill) {
10001
+ return readOpencodeCommandDescription(skill.name);
9787
10002
  }
9788
10003
  };
9789
10004
 
@@ -9824,7 +10039,7 @@ function fatalDeny(reason) {
9824
10039
 
9825
10040
  // src/commands/daemon.ts
9826
10041
  import { randomUUID } from "crypto";
9827
- import { existsSync as existsSync7, unlinkSync as unlinkSync4 } from "fs";
10042
+ import { existsSync as existsSync7 } from "fs";
9828
10043
 
9829
10044
  // src/config/settings.ts
9830
10045
  import { readFileSync as readFileSync7, statSync as statSync2 } from "fs";
@@ -24208,6 +24423,9 @@ function configFile() {
24208
24423
  function prefsFile() {
24209
24424
  return `${stateDir()}/prefs.json`;
24210
24425
  }
24426
+ function updateCheckFile() {
24427
+ return `${stateDir()}/update-check.json`;
24428
+ }
24211
24429
  function logsDir() {
24212
24430
  return `${stateDir()}/logs`;
24213
24431
  }
@@ -24254,7 +24472,7 @@ import { createHash } from "crypto";
24254
24472
 
24255
24473
  // src/ui/assets.ts
24256
24474
  import { readdirSync as readdirSync2 } from "fs";
24257
- import { dirname as dirname2, join as join6, relative } from "path";
24475
+ import { dirname as dirname2, join as join8, relative } from "path";
24258
24476
  import { fileURLToPath } from "url";
24259
24477
  function fromPathMap(map2) {
24260
24478
  const paths = Object.keys(map2).sort();
@@ -24270,7 +24488,7 @@ function assetsFromDist(distDir) {
24270
24488
  const map2 = {};
24271
24489
  const walk = (dir) => {
24272
24490
  for (const ent of readdirSync2(dir, { withFileTypes: true })) {
24273
- const full = join6(dir, ent.name);
24491
+ const full = join8(dir, ent.name);
24274
24492
  if (ent.isDirectory())
24275
24493
  walk(full);
24276
24494
  else if (ent.isFile())
@@ -24302,13 +24520,13 @@ async function loadUiAssets() {
24302
24520
  if (fromDist)
24303
24521
  return fromDist;
24304
24522
  }
24305
- const besideDist = join6(dirname2(process.execPath), "ui");
24523
+ const besideDist = join8(dirname2(process.execPath), "ui");
24306
24524
  return assetsFromDist(besideDist);
24307
24525
  }
24308
24526
  // package.json
24309
24527
  var package_default = {
24310
24528
  name: "@macintacos/caret",
24311
- version: "0.12.0",
24529
+ version: "0.14.0",
24312
24530
  license: "MIT",
24313
24531
  type: "module",
24314
24532
  description: "A Claude Code plugin that replaces the terminal plan-approval prompt with a local web UI for inline review, annotation, and approval.",
@@ -24344,6 +24562,7 @@ var package_default = {
24344
24562
  },
24345
24563
  devDependencies: {
24346
24564
  "@clack/prompts": "^1.7.0",
24565
+ "@codemirror/autocomplete": "^6.20.3",
24347
24566
  "@codemirror/commands": "^6.10.3",
24348
24567
  "@codemirror/lang-markdown": "^6.5.0",
24349
24568
  "@codemirror/language": "^6.12.3",
@@ -25013,6 +25232,53 @@ function warnInvalidEnvVars(warn) {
25013
25232
  warn(`${name} invalid; using config/default`);
25014
25233
  }
25015
25234
 
25235
+ // src/config/prefs.ts
25236
+ import { readFile as readFile3, writeFile } from "fs/promises";
25237
+ import { dirname as dirname4 } from "path";
25238
+ var DEFAULT_SET = { valid: ["default"], fallback: "default" };
25239
+ async function readApproveMode(file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
25240
+ try {
25241
+ const parsed = JSON.parse(await readFile3(file2, "utf-8"));
25242
+ if (typeof parsed.approveMode === "string" && set2.valid.includes(parsed.approveMode)) {
25243
+ return parsed.approveMode;
25244
+ }
25245
+ log.debug("prefs", "unrecognized approve mode; using default");
25246
+ return set2.fallback;
25247
+ } catch (err) {
25248
+ const absent = err?.code === "ENOENT";
25249
+ log.debug("prefs", absent ? "no prefs file; using default approve mode" : "prefs unreadable; using default approve mode");
25250
+ return set2.fallback;
25251
+ }
25252
+ }
25253
+ async function readUpdatesCheck(file2 = prefsFile()) {
25254
+ const parsed = await readJsonFile(file2);
25255
+ return parsed?.updates?.check !== false;
25256
+ }
25257
+ function createPrefsWriter(file2 = prefsFile()) {
25258
+ let tail = Promise.resolve();
25259
+ return {
25260
+ merge(patch) {
25261
+ const next = tail.then(async () => {
25262
+ ensureStateDir(dirname4(file2));
25263
+ const existing = await readJsonFile(file2) ?? {};
25264
+ await writeFile(file2, JSON.stringify({ ...existing, ...patch }, null, 2), {
25265
+ mode: 384
25266
+ });
25267
+ });
25268
+ tail = next.catch(() => {});
25269
+ return next;
25270
+ }
25271
+ };
25272
+ }
25273
+ async function writeApproveMode(mode, writer, log = noopLogger, set2 = DEFAULT_SET) {
25274
+ if (!set2.valid.includes(mode)) {
25275
+ log.warn("prefs", "ignoring invalid approve mode");
25276
+ return;
25277
+ }
25278
+ await writer.merge({ approveMode: mode });
25279
+ log.debug("prefs", `approve mode saved: ${mode}`);
25280
+ }
25281
+
25016
25282
  // src/daemon/diagnostics.ts
25017
25283
  function buildDiagnostics(deps) {
25018
25284
  return {
@@ -25165,6 +25431,10 @@ function removeDaemonLock() {
25165
25431
  unlinkSync2(daemonLock());
25166
25432
  } catch {}
25167
25433
  }
25434
+ function removeOwnDaemonLock() {
25435
+ if (readDaemonLock()?.pid === process.pid)
25436
+ removeDaemonLock();
25437
+ }
25168
25438
  async function retireDaemon(baseUrl, lock, currentStateDir, kill = (pid, sig) => process.kill(pid, sig)) {
25169
25439
  try {
25170
25440
  const res = await fetch(`${baseUrl}/api/retire`, {
@@ -25237,34 +25507,6 @@ async function prodEnsureDeps(s) {
25237
25507
  import { renameSync as renameSync3, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
25238
25508
  import { dirname as dirname6 } from "path";
25239
25509
 
25240
- // src/config/prefs.ts
25241
- import { readFile as readFile2, writeFile } from "fs/promises";
25242
- import { dirname as dirname4 } from "path";
25243
- var DEFAULT_SET = { valid: ["default"], fallback: "default" };
25244
- async function readApproveMode(file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
25245
- try {
25246
- const parsed = JSON.parse(await readFile2(file2, "utf-8"));
25247
- if (typeof parsed.approveMode === "string" && set2.valid.includes(parsed.approveMode)) {
25248
- return parsed.approveMode;
25249
- }
25250
- log.debug("prefs", "unrecognized approve mode; using default");
25251
- return set2.fallback;
25252
- } catch (err) {
25253
- const absent = err?.code === "ENOENT";
25254
- log.debug("prefs", absent ? "no prefs file; using default approve mode" : "prefs unreadable; using default approve mode");
25255
- return set2.fallback;
25256
- }
25257
- }
25258
- async function writeApproveMode(mode, file2 = prefsFile(), log = noopLogger, set2 = DEFAULT_SET) {
25259
- if (!set2.valid.includes(mode)) {
25260
- log.warn("prefs", "ignoring invalid approve mode");
25261
- return;
25262
- }
25263
- ensureStateDir(dirname4(file2));
25264
- await writeFile(file2, JSON.stringify({ approveMode: mode }, null, 2), { mode: 384 });
25265
- log.debug("prefs", `approve mode saved: ${mode}`);
25266
- }
25267
-
25268
25510
  // src/daemon/guards.ts
25269
25511
  var LIVE_CLIENT_WINDOW_MS = 120000;
25270
25512
  function isClientLive(lastPollAt, now, windowMs) {
@@ -25273,17 +25515,33 @@ function isClientLive(lastPollAt, now, windowMs) {
25273
25515
  function isSafeMethod(method) {
25274
25516
  return method === "GET" || method === "HEAD";
25275
25517
  }
25276
- function isCrossOrigin(req) {
25277
- const origin = req.headers.get("origin");
25278
- if (origin) {
25279
- try {
25280
- const host = new URL(origin).hostname;
25281
- if (host !== "127.0.0.1" && host !== "localhost" && host !== VANITY_HOST)
25282
- return true;
25283
- } catch {
25284
- return true;
25285
- }
25518
+ var OWN_HOSTNAMES = new Set(["127.0.0.1", "localhost", VANITY_HOST]);
25519
+ function isOwnAuthority(authority, port) {
25520
+ try {
25521
+ const u = new URL(`http://${authority}`);
25522
+ if (u.href !== `http://${u.host}/`)
25523
+ return false;
25524
+ return OWN_HOSTNAMES.has(u.hostname) && (u.port || "80") === String(port);
25525
+ } catch {
25526
+ return false;
25286
25527
  }
25528
+ }
25529
+ function isForeignHost(req, port) {
25530
+ const host = req.headers.get("host");
25531
+ return host === null || !isOwnAuthority(host, port);
25532
+ }
25533
+ function isOwnOrigin(origin, port) {
25534
+ try {
25535
+ const u = new URL(origin);
25536
+ return u.protocol === "http:" && isOwnAuthority(u.host, port);
25537
+ } catch {
25538
+ return false;
25539
+ }
25540
+ }
25541
+ function isCrossOrigin(req, port) {
25542
+ const origin = req.headers.get("origin");
25543
+ if (origin && !isOwnOrigin(origin, port))
25544
+ return true;
25287
25545
  const site = req.headers.get("sec-fetch-site");
25288
25546
  if (site && site !== "same-origin" && site !== "none")
25289
25547
  return true;
@@ -25301,12 +25559,14 @@ var PlanInputSchema = exports_external.object({
25301
25559
  }).catch({});
25302
25560
  var MAX_FILE_REFS = 1000;
25303
25561
  var FileRefsBodySchema = exports_external.object({ paths: exports_external.array(exports_external.string()).catch([]) }).catch({ paths: [] });
25562
+ var FileSearchBodySchema = exports_external.object({ query: exports_external.string().catch("") }).catch({ query: "" });
25304
25563
  var BehaviorSchema = exports_external.enum(["allow", "deny"]);
25305
25564
  var ResolveBodySchema = exports_external.object({
25306
25565
  behavior: BehaviorSchema.catch("allow"),
25307
25566
  feedback: exports_external.string().optional(),
25308
25567
  acceptMode: exports_external.string().optional().catch(undefined)
25309
25568
  }).catch({ behavior: "allow" });
25569
+ var PrefsPatchSchema = exports_external.object({ updates: exports_external.object({ check: exports_external.boolean() }).strict().optional() }).strict();
25310
25570
  var LineAnnotationSchema = exports_external.object({
25311
25571
  id: exports_external.string(),
25312
25572
  startLine: exports_external.number().int().min(1),
@@ -25389,13 +25649,13 @@ function markPaneRead(pane, deps = {}) {
25389
25649
  }
25390
25650
 
25391
25651
  // src/plan/directory.ts
25392
- import { readdir as readdir2 } from "fs/promises";
25393
- import { join as join8, relative as relative3, sep as sep2 } from "path";
25652
+ import { readdir as readdir4 } from "fs/promises";
25653
+ import { join as join10, relative as relative3, sep as sep4 } from "path";
25394
25654
 
25395
25655
  // src/plan/excerpt.ts
25396
25656
  import { readFileSync as readFileSync8 } from "fs";
25397
- import { readdir, realpath, stat } from "fs/promises";
25398
- import { extname, isAbsolute, join as join7, relative as relative2, resolve, sep } from "path";
25657
+ import { readdir as readdir3, realpath as realpath2, stat as stat2 } from "fs/promises";
25658
+ import { extname, isAbsolute, join as join9, relative as relative2, resolve, sep as sep3 } from "path";
25399
25659
  var EXCERPT_HEAD_LINES = 60;
25400
25660
  var MAX_EXCERPT_BYTES = 10 * 1024 * 1024;
25401
25661
  var MAX_SCAN_ENTRIES = 5000;
@@ -25451,16 +25711,16 @@ function languageForPath(path) {
25451
25711
  return EXT_LANGUAGE[extname(path).toLowerCase()] ?? "text";
25452
25712
  }
25453
25713
  function safeRealpath(path) {
25454
- return realpath(path).catch(() => null);
25714
+ return realpath2(path).catch(() => null);
25455
25715
  }
25456
25716
  function safeStat(path) {
25457
- return stat(path).catch(() => null);
25717
+ return stat2(path).catch(() => null);
25458
25718
  }
25459
25719
  async function contained(cwdReal, abs) {
25460
25720
  const real = await safeRealpath(abs);
25461
25721
  if (real === null)
25462
25722
  return null;
25463
- if (real !== cwdReal && !real.startsWith(cwdReal + sep))
25723
+ if (real !== cwdReal && !real.startsWith(cwdReal + sep3))
25464
25724
  return null;
25465
25725
  const stats = await safeStat(real);
25466
25726
  if (stats === null)
@@ -25476,7 +25736,7 @@ async function basenameSearch(cwdReal, name) {
25476
25736
  const currentDir = queue.shift();
25477
25737
  let entries;
25478
25738
  try {
25479
- entries = await readdir(currentDir, { withFileTypes: true });
25739
+ entries = await readdir3(currentDir, { withFileTypes: true });
25480
25740
  } catch {
25481
25741
  continue;
25482
25742
  }
@@ -25485,9 +25745,9 @@ async function basenameSearch(cwdReal, name) {
25485
25745
  return null;
25486
25746
  if (entry.isFile()) {
25487
25747
  if (entry.name === name)
25488
- return join7(currentDir, entry.name);
25748
+ return join9(currentDir, entry.name);
25489
25749
  } else if (entry.isDirectory() && !SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
25490
- queue.push(join7(currentDir, entry.name));
25750
+ queue.push(join9(currentDir, entry.name));
25491
25751
  }
25492
25752
  }
25493
25753
  }
@@ -25599,13 +25859,13 @@ async function listDirectory(cwd, root, path) {
25599
25859
  if (target === null || target.kind !== "directory")
25600
25860
  return null;
25601
25861
  const rel = relative3(rootHit.path, target.path);
25602
- if (rel === ".." || rel.startsWith(`..${sep2}`))
25862
+ if (rel === ".." || rel.startsWith(`..${sep4}`))
25603
25863
  return null;
25604
- if (rel !== "" && rel.split(sep2).length > MAX_DIR_DEPTH)
25864
+ if (rel !== "" && rel.split(sep4).length > MAX_DIR_DEPTH)
25605
25865
  return null;
25606
25866
  let dirents;
25607
25867
  try {
25608
- dirents = await readdir2(target.path, { withFileTypes: true });
25868
+ dirents = await readdir4(target.path, { withFileTypes: true });
25609
25869
  } catch {
25610
25870
  return null;
25611
25871
  }
@@ -25619,7 +25879,7 @@ async function listDirectory(cwd, root, path) {
25619
25879
  else if (d.isSymbolicLink())
25620
25880
  links.push(d);
25621
25881
  }
25622
- const targets = await Promise.all(links.map((d) => resolveInCwd(cwd, join8(target.path, d.name))));
25882
+ const targets = await Promise.all(links.map((d) => resolveInCwd(cwd, join10(target.path, d.name))));
25623
25883
  targets.forEach((hit, i) => {
25624
25884
  const link = links[i];
25625
25885
  if (hit !== null && link !== undefined)
@@ -25634,6 +25894,78 @@ async function listDirectory(cwd, root, path) {
25634
25894
  };
25635
25895
  }
25636
25896
 
25897
+ // src/plan/file-search.ts
25898
+ import { readdir as readdir5 } from "fs/promises";
25899
+ import { isAbsolute as isAbsolute2, join as join11 } from "path";
25900
+ var SEARCH_BUDGET = { dirents: 20000, results: 50 };
25901
+ var MAX_SEARCH_QUERY_CHARS = 128;
25902
+ function subsequence(haystack, needle) {
25903
+ let i = 0;
25904
+ for (let h = 0;h < haystack.length && i < needle.length; h++) {
25905
+ if (haystack[h] === needle[i])
25906
+ i++;
25907
+ }
25908
+ return i === needle.length;
25909
+ }
25910
+ function relPath(dir, name) {
25911
+ return dir === "" ? name : `${dir}/${name}`;
25912
+ }
25913
+ function partition(dirents, allowance) {
25914
+ const files = [];
25915
+ const dirs = [];
25916
+ let scanned = 0;
25917
+ for (const entry of dirents) {
25918
+ if (scanned >= allowance)
25919
+ return { files, dirs, scanned, cut: true };
25920
+ scanned++;
25921
+ if (entry.name === ".git")
25922
+ continue;
25923
+ if (entry.isFile())
25924
+ files.push(entry.name);
25925
+ else if (entry.isDirectory() && !SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
25926
+ dirs.push(entry.name);
25927
+ }
25928
+ }
25929
+ files.sort();
25930
+ dirs.sort();
25931
+ return { files, dirs, scanned, cut: false };
25932
+ }
25933
+ async function searchFiles(cwd, query, budget = SEARCH_BUDGET) {
25934
+ if (cwd === "" || !isAbsolute2(cwd))
25935
+ return null;
25936
+ const cwdReal = await safeRealpath(cwd);
25937
+ if (cwdReal === null)
25938
+ return null;
25939
+ const needle = query.slice(0, MAX_SEARCH_QUERY_CHARS).toLowerCase();
25940
+ const paths = [];
25941
+ const queue = [""];
25942
+ let scanned = 0;
25943
+ while (queue.length > 0) {
25944
+ const rel = queue.shift();
25945
+ let dirents;
25946
+ try {
25947
+ dirents = await readdir5(join11(cwdReal, rel), { withFileTypes: true });
25948
+ } catch {
25949
+ continue;
25950
+ }
25951
+ const level = partition(dirents, budget.dirents - scanned);
25952
+ scanned += level.scanned;
25953
+ if (level.cut)
25954
+ return { paths, stoppedAt: "scan" };
25955
+ for (const name of level.files) {
25956
+ const path = relPath(rel, name);
25957
+ if (!subsequence(path.toLowerCase(), needle))
25958
+ continue;
25959
+ if (paths.length === budget.results)
25960
+ return { paths, stoppedAt: "results" };
25961
+ paths.push(path);
25962
+ }
25963
+ for (const name of level.dirs)
25964
+ queue.push(relPath(rel, name));
25965
+ }
25966
+ return { paths, stoppedAt: null };
25967
+ }
25968
+
25637
25969
  // src/review/decisions.ts
25638
25970
  function createDecisions(log = noopLogger) {
25639
25971
  const pending = new Map;
@@ -25710,7 +26042,7 @@ import { createHash as createHash2 } from "crypto";
25710
26042
  import { chmodSync as chmodSync3, existsSync as existsSync6, mkdirSync as mkdirSync2, renameSync as renameSync2, writeFileSync as writeFileSync4 } from "fs";
25711
26043
  import { mkdtemp, rm } from "fs/promises";
25712
26044
  import { tmpdir } from "os";
25713
- import { dirname as dirname5, join as join9 } from "path";
26045
+ import { dirname as dirname5, join as join12 } from "path";
25714
26046
  var RUMDL_VERSION = "0.2.54";
25715
26047
  var ASSETS = {
25716
26048
  "darwin-arm64": {
@@ -25753,14 +26085,14 @@ async function downloadRumdl(binPath, asset, fetchImpl = fetch) {
25753
26085
  if (actual !== asset.sha256) {
25754
26086
  throw new Error(`rumdl: checksum mismatch for ${asset.url} (expected ${asset.sha256}, got ${actual})`);
25755
26087
  }
25756
- const work = await mkdtemp(join9(tmpdir(), "caret-rumdl-"));
26088
+ const work = await mkdtemp(join12(tmpdir(), "caret-rumdl-"));
25757
26089
  try {
25758
- const archive = join9(work, "rumdl.tar.gz");
26090
+ const archive = join12(work, "rumdl.tar.gz");
25759
26091
  await Bun.write(archive, bytes);
25760
26092
  const tar = Bun.spawn(["tar", "-xzf", archive, "-C", work], { stderr: "pipe" });
25761
26093
  if (await tar.exited !== 0)
25762
26094
  throw new Error(`rumdl: failed to extract ${asset.url}`);
25763
- const extracted = join9(work, "rumdl");
26095
+ const extracted = join12(work, "rumdl");
25764
26096
  if (!existsSync6(extracted))
25765
26097
  throw new Error(`rumdl: binary not found in ${asset.url}`);
25766
26098
  mkdirSync2(dirname5(binPath), { recursive: true });
@@ -25992,6 +26324,7 @@ var PLACEHOLDER_HTML = `<!doctype html><html lang="en"><head><meta charset="utf-
25992
26324
  var INDEX_CACHE_CONTROL = "no-cache";
25993
26325
  var ASSET_CACHE_CONTROL = "public, max-age=31536000, immutable";
25994
26326
  var INDEX_PATH = "/index.html";
26327
+ var FILE_REF_BATCH = 64;
25995
26328
  function resolveOptions(opts) {
25996
26329
  return {
25997
26330
  store: opts.store,
@@ -26008,12 +26341,16 @@ function resolveOptions(opts) {
26008
26341
  instanceId: opts.instanceId,
26009
26342
  approveVariants: opts.approveVariants,
26010
26343
  source: opts.source,
26344
+ listSkills: opts.listSkills,
26345
+ readSkillDescription: opts.readSkillDescription,
26011
26346
  diagnostics: opts.diagnostics,
26347
+ updateReport: opts.updateReport,
26348
+ onUpdatesEnabled: opts.onUpdatesEnabled,
26012
26349
  markPaneRead: opts.markPaneRead ?? ((pane) => markPaneRead(pane, { log: opts.log })),
26013
26350
  log: opts.log ?? noopLogger
26014
26351
  };
26015
26352
  }
26016
- var ID_ROUTE_RE = /^\/api\/reviews\/([^/]+)(\/decision|\/resolve|\/draft|\/expire|\/seen|\/file-refs|\/file|\/dir)?$/;
26353
+ var ID_ROUTE_RE = /^\/api\/reviews\/([^/]+)(\/decision|\/resolve|\/draft|\/expire|\/seen|\/file-refs|\/file-search|\/file|\/dir|\/skills|\/skill-description)?$/;
26017
26354
  function matchIdRoute(path) {
26018
26355
  const m = path.match(ID_ROUTE_RE);
26019
26356
  if (!m)
@@ -26026,6 +26363,7 @@ function createServer(opts) {
26026
26363
  const { buildId, commit, stateDir: stateDir2, instanceId, approveVariants, source, lockPath } = cfg;
26027
26364
  const { awaitDecision, resolveDecision, clearDecision, openDecisionCount } = createDecisions(log);
26028
26365
  const approveModeSet = approveVariants && approveVariants.length > 0 ? { valid: approveVariants.map((v) => v.id), fallback: approveVariants[0]?.id ?? "default" } : { valid: ["default"], fallback: "default" };
26366
+ const prefsWriter = createPrefsWriter(prefsPath);
26029
26367
  function raceDecision(id, ms) {
26030
26368
  return new Promise((resolve2) => {
26031
26369
  const t = setTimeout(() => resolve2(null), ms);
@@ -26094,6 +26432,11 @@ function createServer(opts) {
26094
26432
  return notFound();
26095
26433
  return Response.json(cfg.diagnostics());
26096
26434
  }
26435
+ async function handleUpdate() {
26436
+ if (!cfg.updateReport)
26437
+ return notFound();
26438
+ return Response.json(await cfg.updateReport());
26439
+ }
26097
26440
  function handleRetire() {
26098
26441
  log.info("retire", "retire requested");
26099
26442
  setTimeout(() => {
@@ -26167,7 +26510,23 @@ function createServer(opts) {
26167
26510
  return new Response(null, { status: 204 });
26168
26511
  }
26169
26512
  async function handlePrefs() {
26170
- return Response.json({ approveMode: await readApproveMode(prefsPath, log, approveModeSet) });
26513
+ const body = {
26514
+ approveMode: await readApproveMode(prefsPath, log, approveModeSet)
26515
+ };
26516
+ return Response.json(body);
26517
+ }
26518
+ async function handleSetPrefs(req) {
26519
+ const parsed = PrefsPatchSchema.safeParse(await req.json().catch(() => null));
26520
+ if (!parsed.success) {
26521
+ const error51 = parsed.error.issues[0]?.message ?? "invalid prefs patch";
26522
+ log.warn("prefs", "prefs patch rejected", { reason: error51 });
26523
+ return Response.json({ error: error51 }, { status: 400 });
26524
+ }
26525
+ await prefsWriter.merge(parsed.data);
26526
+ log.debug("prefs", "prefs saved");
26527
+ if (parsed.data.updates?.check === true)
26528
+ cfg.onUpdatesEnabled?.();
26529
+ return Response.json({ ok: true });
26171
26530
  }
26172
26531
  function handleGetReview(id) {
26173
26532
  const r = store.get(id);
@@ -26187,10 +26546,13 @@ function createServer(opts) {
26187
26546
  if (unique.push(p) === MAX_FILE_REFS)
26188
26547
  break;
26189
26548
  }
26190
- const entries = await Promise.all(unique.map(async (p) => {
26191
- const hit = await resolveInCwd(r.cwd, p);
26192
- return hit === null ? null : [p, hit.kind];
26193
- }));
26549
+ const entries = [];
26550
+ for (let i = 0;i < unique.length; i += FILE_REF_BATCH) {
26551
+ entries.push(...await Promise.all(unique.slice(i, i + FILE_REF_BATCH).map(async (p) => {
26552
+ const hit = await resolveInCwd(r.cwd, p);
26553
+ return hit === null ? null : [p, hit.kind];
26554
+ })));
26555
+ }
26194
26556
  const resolved = Object.fromEntries(entries.filter((e) => e !== null));
26195
26557
  log.debug("request", `file-refs resolved: ${Object.keys(resolved).length}/${unique.length}`, {
26196
26558
  reviewId: id,
@@ -26233,6 +26595,45 @@ function createServer(opts) {
26233
26595
  });
26234
26596
  return Response.json(listing);
26235
26597
  }
26598
+ async function handleSkills(id) {
26599
+ if (!cfg.listSkills)
26600
+ return notFound();
26601
+ const r = store.get(id);
26602
+ if (!r)
26603
+ return notFound();
26604
+ const skills = await cfg.listSkills(r.cwd);
26605
+ log.debug("request", "skills listed", { reviewId: id, count: skills.length });
26606
+ return Response.json(skills);
26607
+ }
26608
+ async function handleSkillDescription(req, id) {
26609
+ if (!cfg.readSkillDescription)
26610
+ return notFound();
26611
+ const r = store.get(id);
26612
+ if (!r)
26613
+ return notFound();
26614
+ const params = new URL(req.url).searchParams;
26615
+ const description = await cfg.readSkillDescription(r.cwd, {
26616
+ name: params.get("name") ?? "",
26617
+ origin: params.get("origin") ?? ""
26618
+ });
26619
+ log.debug("request", "skill description read", { reviewId: id, found: description !== null });
26620
+ return Response.json({ description });
26621
+ }
26622
+ async function handleFileSearch(req, id) {
26623
+ const r = store.get(id);
26624
+ if (!r)
26625
+ return notFound();
26626
+ const { query } = await parseBody(req, FileSearchBodySchema);
26627
+ const result = await searchFiles(r.cwd, query);
26628
+ if (result === null)
26629
+ return notFound();
26630
+ log.debug("request", "file search answered", {
26631
+ reviewId: id,
26632
+ returned: result.paths.length,
26633
+ stoppedAt: result.stoppedAt
26634
+ });
26635
+ return Response.json(result);
26636
+ }
26236
26637
  async function handleDecision(id) {
26237
26638
  const inMem = store.get(id);
26238
26639
  if (inMem?.decision) {
@@ -26300,7 +26701,7 @@ function createServer(opts) {
26300
26701
  store.bumpEpoch(existing.sessionId);
26301
26702
  await store.remove(id);
26302
26703
  if (decision.acceptMode !== undefined && approveModeSet.valid.includes(decision.acceptMode)) {
26303
- writeApproveMode(decision.acceptMode, prefsPath, log, approveModeSet).catch(() => {
26704
+ writeApproveMode(decision.acceptMode, prefsWriter, log, approveModeSet).catch(() => {
26304
26705
  log.warn("prefs", "approve mode write failed");
26305
26706
  });
26306
26707
  }
@@ -26340,6 +26741,8 @@ function createServer(opts) {
26340
26741
  return handleHealth();
26341
26742
  if (method === "GET" && path === "/api/diagnostics")
26342
26743
  return handleDiagnostics();
26744
+ if (method === "GET" && path === "/api/update")
26745
+ return handleUpdate();
26343
26746
  if (method === "POST" && path === "/api/retire")
26344
26747
  return handleRetire();
26345
26748
  if (method === "GET" && (path === "/" || path === INDEX_PATH))
@@ -26354,6 +26757,8 @@ function createServer(opts) {
26354
26757
  return handleListReviews();
26355
26758
  if (method === "GET" && path === "/api/prefs")
26356
26759
  return handlePrefs();
26760
+ if (method === "POST" && path === "/api/prefs")
26761
+ return handleSetPrefs(req);
26357
26762
  const route = matchIdRoute(path);
26358
26763
  if (route) {
26359
26764
  const { id, sub } = route;
@@ -26363,8 +26768,15 @@ function createServer(opts) {
26363
26768
  return handleFileExcerpt(req, id);
26364
26769
  if (method === "GET" && sub === "/dir")
26365
26770
  return handleDirListing(req, id);
26771
+ if (method === "GET" && sub === "/skills")
26772
+ return handleSkills(id);
26773
+ if (method === "GET" && sub === "/skill-description") {
26774
+ return handleSkillDescription(req, id);
26775
+ }
26366
26776
  if (method === "POST" && sub === "/file-refs")
26367
26777
  return handleFileRefs(req, id);
26778
+ if (method === "POST" && sub === "/file-search")
26779
+ return handleFileSearch(req, id);
26368
26780
  if (method === "GET" && sub === "/decision")
26369
26781
  return handleDecision(id);
26370
26782
  if (method === "PUT" && sub === "/draft")
@@ -26383,14 +26795,18 @@ function createServer(opts) {
26383
26795
  }
26384
26796
  return notFound();
26385
26797
  }
26386
- async function handle(req) {
26798
+ async function handle(req, self) {
26387
26799
  inFlight++;
26388
26800
  cancelIdle();
26389
26801
  try {
26802
+ const port = self.port ?? -1;
26803
+ if (isForeignHost(req, port)) {
26804
+ return new Response("host not recognized", { status: 403 });
26805
+ }
26390
26806
  const url2 = new URL(req.url);
26391
26807
  const path = url2.pathname;
26392
26808
  const method = req.method;
26393
- if (!isSafeMethod(method) && isCrossOrigin(req)) {
26809
+ if (!isSafeMethod(method) && isCrossOrigin(req, port)) {
26394
26810
  return new Response("cross-origin request blocked", { status: 403 });
26395
26811
  }
26396
26812
  return await dispatch(req, method, path);
@@ -26455,9 +26871,153 @@ function createServer(opts) {
26455
26871
  return { port: server.port ?? 0, stop };
26456
26872
  }
26457
26873
 
26874
+ // src/daemon/update-check.ts
26875
+ import { writeFileSync as writeFileSync6 } from "fs";
26876
+ import { dirname as dirname7 } from "path";
26877
+ var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
26878
+ var REFRESH_COMMAND = "bunx --no-cache @macintacos/caret@latest install --refresh";
26879
+ var REBUILD_COMMAND = "mise run build --install";
26880
+ var NEEDS_COMPARE = "could not compare this build against trunk";
26881
+ var NEVER_CHECKED = {
26882
+ kind: "unknown",
26883
+ reason: "no update check has run for this build yet"
26884
+ };
26885
+ var DISABLED = { kind: "unavailable", reason: "disabled" };
26886
+ function updateStatusFor(facts) {
26887
+ if (facts.kind === "dev")
26888
+ return { kind: "unavailable", reason: "dev" };
26889
+ if (facts.kind === "bundle") {
26890
+ if (facts.npmLatest === null)
26891
+ return unknown2("could not reach npm for the published version");
26892
+ return isNewer(facts.npmLatest, facts.version) ? { kind: "behind-release", available: facts.npmLatest, command: REFRESH_COMMAND } : { kind: "current" };
26893
+ }
26894
+ if (facts.release === null)
26895
+ return unknown2("could not reach GitHub for the newest release");
26896
+ if (isNewer(facts.release, facts.version)) {
26897
+ return { kind: "behind-release", available: facts.release, command: REFRESH_COMMAND };
26898
+ }
26899
+ if (facts.commit === "unknown")
26900
+ return { kind: "current" };
26901
+ if (facts.aheadBy === null)
26902
+ return unknown2(NEEDS_COMPARE);
26903
+ return facts.aheadBy > 0 ? { kind: "behind-commit", aheadBy: facts.aheadBy, command: REBUILD_COMMAND } : { kind: "current" };
26904
+ }
26905
+ function updateReportFor(identity, status, checkEnabled) {
26906
+ const devBuild = status.kind === "unavailable" && status.reason === "dev";
26907
+ return { ...identity, checkEnabled, status: checkEnabled || devBuild ? status : DISABLED };
26908
+ }
26909
+ function readCachedStatus(cache, version2, commit) {
26910
+ const rec = cache.read();
26911
+ if (!rec || rec.version !== version2 || rec.commit !== commit)
26912
+ return NEVER_CHECKED;
26913
+ return rec.status;
26914
+ }
26915
+ async function runUpdateCheck(deps) {
26916
+ if (deps.kind === "dev")
26917
+ return { kind: "unavailable", reason: "dev" };
26918
+ try {
26919
+ if (!await deps.enabled())
26920
+ return null;
26921
+ const now = deps.now();
26922
+ const prev = deps.cache.read();
26923
+ const sameBuild = prev?.version === deps.version && prev?.commit === deps.commit;
26924
+ if (prev && sameBuild && Math.abs(now - prev.checkedAt) < CHECK_INTERVAL_MS)
26925
+ return null;
26926
+ const record2 = (status2) => {
26927
+ deps.cache.write({ checkedAt: now, version: deps.version, commit: deps.commit, status: status2 });
26928
+ };
26929
+ record2(prev && sameBuild ? prev.status : NEVER_CHECKED);
26930
+ const status = await gather(deps);
26931
+ record2(status);
26932
+ deps.log.info("update", `update check: ${status.kind}`, status.kind === "unknown" ? { detail: status.reason } : undefined);
26933
+ return status;
26934
+ } catch (err) {
26935
+ deps.log.warn("update", "update check failed", { detail: errorMessage(err) });
26936
+ return unknown2("the update check failed");
26937
+ }
26938
+ }
26939
+ function fileUpdateCache(path) {
26940
+ return {
26941
+ read: () => asRecord(readJsonFileSync(path)),
26942
+ write: (entry) => {
26943
+ try {
26944
+ ensureStateDir(dirname7(path));
26945
+ writeFileSync6(path, JSON.stringify(entry, null, 2), { mode: 384 });
26946
+ } catch {}
26947
+ }
26948
+ };
26949
+ }
26950
+ async function gather(deps) {
26951
+ const base = { kind: deps.kind, version: deps.version, commit: deps.commit };
26952
+ if (deps.kind === "bundle") {
26953
+ return updateStatusFor({
26954
+ ...base,
26955
+ npmLatest: await deps.npmLatest(),
26956
+ release: null,
26957
+ aheadBy: null
26958
+ });
26959
+ }
26960
+ const release = await deps.release();
26961
+ const first = updateStatusFor({ ...base, npmLatest: null, release, aheadBy: null });
26962
+ if (first.kind !== "unknown" || first.reason !== NEEDS_COMPARE)
26963
+ return first;
26964
+ const aheadBy = await deps.aheadBy(deps.commit);
26965
+ return updateStatusFor({ ...base, npmLatest: null, release, aheadBy });
26966
+ }
26967
+ function asRecord(value) {
26968
+ const r = value;
26969
+ if (typeof r?.checkedAt !== "number")
26970
+ return null;
26971
+ if (typeof r.version !== "string" || typeof r.commit !== "string")
26972
+ return null;
26973
+ if (typeof r.status?.kind !== "string")
26974
+ return null;
26975
+ return r;
26976
+ }
26977
+ function unknown2(reason) {
26978
+ return { kind: "unknown", reason };
26979
+ }
26980
+
26981
+ // src/lib/upstream.ts
26982
+ var NPM_LATEST_URL = `https://registry.npmjs.org/${package_default.name}/latest`;
26983
+ var LATEST_RELEASE_URL = "https://api.github.com/repos/macintacos/caret/releases/latest";
26984
+ var COMPARE_URL = "https://api.github.com/repos/macintacos/caret/compare";
26985
+ var UPSTREAM_TIMEOUT_MS = 3000;
26986
+ var GITHUB_HEADERS = { "user-agent": "caret" };
26987
+ async function readJson(url2, fetchImpl, headers) {
26988
+ try {
26989
+ const res = await fetchImpl(url2, {
26990
+ signal: AbortSignal.timeout(UPSTREAM_TIMEOUT_MS),
26991
+ ...headers ? { headers } : {}
26992
+ });
26993
+ return res.ok ? await res.json() : null;
26994
+ } catch {
26995
+ return null;
26996
+ }
26997
+ }
26998
+ async function publishedCaretVersion(fetchImpl = fetch) {
26999
+ const body = await readJson(NPM_LATEST_URL, fetchImpl);
27000
+ const v = body?.version;
27001
+ return typeof v === "string" && v.length > 0 ? v : null;
27002
+ }
27003
+ async function latestReleaseTag(fetchImpl = fetch) {
27004
+ const body = await readJson(LATEST_RELEASE_URL, fetchImpl, GITHUB_HEADERS);
27005
+ const tag = body?.tag_name;
27006
+ if (typeof tag !== "string" || tag.length === 0)
27007
+ return null;
27008
+ const stripped = tag.replace(/^v/, "");
27009
+ return stripped.length > 0 ? stripped : null;
27010
+ }
27011
+ async function commitsAheadOfTrunk(commit, fetchImpl = fetch) {
27012
+ const url2 = `${COMPARE_URL}/${encodeURIComponent(commit)}...trunk`;
27013
+ const body = await readJson(url2, fetchImpl, GITHUB_HEADERS);
27014
+ const ahead = body?.ahead_by;
27015
+ return typeof ahead === "number" && Number.isFinite(ahead) ? ahead : null;
27016
+ }
27017
+
26458
27018
  // src/review/store.ts
26459
- import { readdir as readdir3, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
26460
- import { join as join10 } from "path";
27019
+ import { readdir as readdir6, readFile as readFile4, writeFile as writeFile2 } from "fs/promises";
27020
+ import { join as join13 } from "path";
26461
27021
  function createStore(dir, log = noopLogger) {
26462
27022
  const reviews = new Map;
26463
27023
  const epochs = new Map;
@@ -26466,7 +27026,7 @@ function createStore(dir, log = noopLogger) {
26466
27026
  const prev = writeChains.get(review.id) ?? Promise.resolve();
26467
27027
  const next = prev.catch(() => {}).then(async () => {
26468
27028
  ensureStateDir(dir);
26469
- await writeFile2(join10(dir, `${review.id}.json`), JSON.stringify(review, null, 2), {
27029
+ await writeFile2(join13(dir, `${review.id}.json`), JSON.stringify(review, null, 2), {
26470
27030
  mode: 384
26471
27031
  });
26472
27032
  log.debug("store", `review persisted: ${shortId(review.id)}`, { reviewId: review.id });
@@ -26516,7 +27076,7 @@ function createStore(dir, log = noopLogger) {
26516
27076
  return review;
26517
27077
  },
26518
27078
  async persisted(id) {
26519
- return await readJsonFile(join10(dir, `${id}.json`)) ?? undefined;
27079
+ return await readJsonFile(join13(dir, `${id}.json`)) ?? undefined;
26520
27080
  },
26521
27081
  size() {
26522
27082
  return reviews.size;
@@ -26533,7 +27093,7 @@ function createStore(dir, log = noopLogger) {
26533
27093
  async rehydrate() {
26534
27094
  let files;
26535
27095
  try {
26536
- files = await readdir3(dir);
27096
+ files = await readdir6(dir);
26537
27097
  } catch {
26538
27098
  log.debug("store", "no reviews dir; nothing to rehydrate");
26539
27099
  return;
@@ -26543,7 +27103,7 @@ function createStore(dir, log = noopLogger) {
26543
27103
  if (!file2.endsWith(".json"))
26544
27104
  continue;
26545
27105
  try {
26546
- const review = JSON.parse(await readFile3(join10(dir, file2), "utf-8"));
27106
+ const review = JSON.parse(await readFile4(join13(dir, file2), "utf-8"));
26547
27107
  if (isUnresolved(review.status)) {
26548
27108
  reviews.set(review.id, review);
26549
27109
  loaded++;
@@ -26568,6 +27128,28 @@ async function runDaemon(opts) {
26568
27128
  log.info("settings", existsSync7(cfg) ? `settings: reading ${cfg}` : `settings: no config at ${cfg}; using defaults`, { settings: boot });
26569
27129
  warnInvalidEnvVars((msg) => log.warn("env", msg));
26570
27130
  const adapter = selectAdapter();
27131
+ const install = buildKind();
27132
+ const version2 = VERSION;
27133
+ const commit = currentCommit();
27134
+ const updateCache = fileUpdateCache(updateCheckFile());
27135
+ let updateStatus = readCachedStatus(updateCache, version2, commit);
27136
+ function refreshUpdate() {
27137
+ runUpdateCheck({
27138
+ kind: install,
27139
+ version: version2,
27140
+ commit,
27141
+ enabled: () => readUpdatesCheck(),
27142
+ now: Date.now,
27143
+ cache: updateCache,
27144
+ npmLatest: publishedCaretVersion,
27145
+ release: latestReleaseTag,
27146
+ aheadBy: commitsAheadOfTrunk,
27147
+ log
27148
+ }).then((status) => {
27149
+ if (status)
27150
+ updateStatus = status;
27151
+ }, (err) => log.error("update", err));
27152
+ }
26571
27153
  const store = createStore(reviewsDir(), log);
26572
27154
  await store.rehydrate();
26573
27155
  const assets = await loadUiAssets();
@@ -26575,6 +27157,19 @@ async function runDaemon(opts) {
26575
27157
  log.info("ui", "no embedded ui; serving placeholder");
26576
27158
  const ephemeral = opts.ephemeral;
26577
27159
  let server;
27160
+ const shutdown = (code) => {
27161
+ server?.stop();
27162
+ process.exit(code);
27163
+ };
27164
+ process.once("SIGTERM", () => {
27165
+ log.info("signal", "sigterm: shutting down");
27166
+ shutdown(0);
27167
+ });
27168
+ process.once("SIGINT", () => {
27169
+ log.info("signal", "sigint: shutting down");
27170
+ shutdown(0);
27171
+ });
27172
+ process.once("exit", removeOwnDaemonLock);
26578
27173
  try {
26579
27174
  server = createServer({
26580
27175
  store,
@@ -26584,11 +27179,13 @@ async function runDaemon(opts) {
26584
27179
  assets,
26585
27180
  lockPath: daemonLock(),
26586
27181
  buildId: await currentBuildId(),
26587
- commit: currentCommit(),
27182
+ commit,
26588
27183
  stateDir: stateDir(),
26589
27184
  instanceId: randomUUID().slice(0, 8),
26590
27185
  approveVariants: adapter.approveVariants,
26591
27186
  source: adapter.id,
27187
+ listSkills: (cwd) => adapter.listSkills(cwd),
27188
+ readSkillDescription: (cwd, skill) => adapter.readSkillDescription(cwd, skill),
26592
27189
  diagnostics: () => buildDiagnostics({
26593
27190
  now: Date.now,
26594
27191
  startedAt,
@@ -26602,6 +27199,8 @@ async function runDaemon(opts) {
26602
27199
  configExists: () => existsSync7(cfg),
26603
27200
  envOverrides
26604
27201
  }),
27202
+ updateReport: async () => updateReportFor({ install, version: version2, commit }, updateStatus, await readUpdatesCheck()),
27203
+ onUpdatesEnabled: refreshUpdate,
26605
27204
  log
26606
27205
  });
26607
27206
  } catch (e) {
@@ -26612,29 +27211,13 @@ async function runDaemon(opts) {
26612
27211
  }
26613
27212
  throw e;
26614
27213
  }
26615
- const shutdown = (code) => {
26616
- server.stop();
26617
- process.exit(code);
26618
- };
26619
- process.once("SIGTERM", () => {
26620
- log.info("signal", "sigterm: shutting down");
26621
- shutdown(0);
26622
- });
26623
- process.once("SIGINT", () => {
26624
- log.info("signal", "sigint: shutting down");
26625
- shutdown(0);
26626
- });
26627
27214
  const onFatal = (label) => (err) => {
26628
27215
  log.error(label, err);
26629
27216
  shutdown(1);
26630
27217
  };
26631
27218
  process.once("uncaughtException", onFatal("uncaughtException"));
26632
27219
  process.once("unhandledRejection", onFatal("unhandledRejection"));
26633
- process.once("exit", () => {
26634
- try {
26635
- unlinkSync4(daemonLock());
26636
- } catch {}
26637
- });
27220
+ refreshUpdate();
26638
27221
  }
26639
27222
 
26640
27223
  // src/commands/discovery.ts
@@ -26643,7 +27226,7 @@ import { release } from "os";
26643
27226
 
26644
27227
  // src/discovery.ts
26645
27228
  import { readdirSync as readdirSync4, statSync as statSync4 } from "fs";
26646
- import { basename as basename3, join as join11 } from "path";
27229
+ import { basename as basename3, join as join14 } from "path";
26647
27230
  var CARET_BIN = "caret-native";
26648
27231
  async function safe(build) {
26649
27232
  try {
@@ -26854,7 +27437,7 @@ function listReviewFiles() {
26854
27437
  continue;
26855
27438
  if (out.length >= 5000)
26856
27439
  break;
26857
- const raw = readJsonFileSync(join11(dir, file2));
27440
+ const raw = readJsonFileSync(join14(dir, file2));
26858
27441
  if (raw && typeof raw.id === "string" && typeof raw.status === "string") {
26859
27442
  out.push({ id: raw.id, status: raw.status });
26860
27443
  }
@@ -26964,31 +27547,31 @@ import {
26964
27547
  rmSync as rmSync2,
26965
27548
  statSync as statSync5,
26966
27549
  symlinkSync,
26967
- writeFileSync as writeFileSync6
27550
+ writeFileSync as writeFileSync7
26968
27551
  } from "fs";
26969
- import { join as join13, resolve as resolve2 } from "path";
27552
+ import { join as join16, resolve as resolve2 } from "path";
26970
27553
 
26971
27554
  // src/adapters/opencode/packaging.ts
26972
27555
  import { existsSync as existsSync9, readdirSync as readdirSync5, readFileSync as readFileSync9 } from "fs";
26973
- import { dirname as dirname7, join as join12 } from "path";
27556
+ import { dirname as dirname8, join as join15 } from "path";
26974
27557
  function resolveCaretRoot() {
26975
27558
  const candidates = [];
26976
27559
  const script = process.argv[1];
26977
27560
  if (script)
26978
- candidates.push(join12(dirname7(script), ".."));
26979
- candidates.push(join12(dirname7(process.execPath), ".."));
27561
+ candidates.push(join15(dirname8(script), ".."));
27562
+ candidates.push(join15(dirname8(process.execPath), ".."));
26980
27563
  for (const root of candidates) {
26981
- if (existsSync9(join12(root, "opencode", "caret.plugin.ts")))
27564
+ if (existsSync9(join15(root, "opencode", "caret.plugin.ts")))
26982
27565
  return root;
26983
27566
  }
26984
27567
  throw new Error(`caret OpenCode packaging not found (no opencode/caret.plugin.ts under: ${candidates.join(", ") || "(none)"}). The OpenCode plugin source must ship with caret.`);
26985
27568
  }
26986
27569
  function loadOpencodePackaging(root = resolveCaretRoot()) {
26987
- const binPath = join12(root, "bin", "caret");
26988
- const commandsDir = join12(root, "opencode", "commands");
27570
+ const binPath = join15(root, "bin", "caret");
27571
+ const commandsDir = join15(root, "opencode", "commands");
26989
27572
  let commands = [];
26990
27573
  try {
26991
- commands = readdirSync5(commandsDir).filter((f) => f.endsWith(".md")).sort().map((f) => ({ name: f, contents: readFileSync9(join12(commandsDir, f), "utf-8") }));
27574
+ commands = readdirSync5(commandsDir).filter((f) => f.endsWith(".md")).sort().map((f) => ({ name: f, contents: readFileSync9(join15(commandsDir, f), "utf-8") }));
26992
27575
  } catch {
26993
27576
  commands = [];
26994
27577
  }
@@ -26997,17 +27580,17 @@ function loadOpencodePackaging(root = resolveCaretRoot()) {
26997
27580
 
26998
27581
  // src/commands/install/local.ts
26999
27582
  function devMarketplaceDir() {
27000
- return join13(stateDir(), "dev-marketplace");
27583
+ return join16(stateDir(), "dev-marketplace");
27001
27584
  }
27002
27585
  function resolveLocalCheckout(opts = {}, deps = {}) {
27003
27586
  const repoDir = resolve2(caretRoot(deps));
27004
- if (!existsSync10(join13(repoDir, ".claude-plugin", "marketplace.json"))) {
27587
+ if (!existsSync10(join16(repoDir, ".claude-plugin", "marketplace.json"))) {
27005
27588
  throw new Error(`--from-local must run from a caret checkout (no .claude-plugin/marketplace.json at ${repoDir}). A published caret installs with a plain \`caret install\`.`);
27006
27589
  }
27007
27590
  if (opts.requireArtifacts !== false) {
27008
27591
  const missing = [
27009
- isExecutable(join13(repoDir, "bin", "caret-native")) ? null : "bin/caret-native",
27010
- isDirectory(join13(repoDir, "bin", "ui")) ? null : "bin/ui"
27592
+ isExecutable(join16(repoDir, "bin", "caret-native")) ? null : "bin/caret-native",
27593
+ isDirectory(join16(repoDir, "bin", "ui")) ? null : "bin/ui"
27011
27594
  ].filter((m) => m !== null);
27012
27595
  if (missing.length > 0) {
27013
27596
  throw new Error(`--from-local reuses the build artifacts bin/caret-native + bin/ui, and ${repoDir} is missing ${missing.join(" + ")} \u2014 run \`mise run build\` first.`);
@@ -27026,9 +27609,9 @@ function caretRoot(deps) {
27026
27609
  }
27027
27610
  function writeDevMarketplace(repoDir, outDir) {
27028
27611
  rmSync2(outDir, { recursive: true, force: true });
27029
- mkdirSync3(join13(outDir, ".claude-plugin"), { recursive: true });
27030
- symlinkSync(resolve2(repoDir), join13(outDir, "caret"));
27031
- writeFileSync6(join13(outDir, ".claude-plugin", "marketplace.json"), `${JSON.stringify({
27612
+ mkdirSync3(join16(outDir, ".claude-plugin"), { recursive: true });
27613
+ symlinkSync(resolve2(repoDir), join16(outDir, "caret"));
27614
+ writeFileSync7(join16(outDir, ".claude-plugin", "marketplace.json"), `${JSON.stringify({
27032
27615
  name: "caret",
27033
27616
  description: "Local caret dev build (generated by caret install --from-local).",
27034
27617
  owner: { name: "macintacos" },
@@ -27039,7 +27622,7 @@ function writeDevMarketplace(repoDir, outDir) {
27039
27622
  async function prewarmLocalBuild(repoDir, deps = {}) {
27040
27623
  const spawn = deps.spawn ?? runCaptured;
27041
27624
  try {
27042
- await spawn([join13(repoDir, "bin", "caret-native"), "prewarm"]);
27625
+ await spawn([join16(repoDir, "bin", "caret-native"), "prewarm"]);
27043
27626
  } catch {}
27044
27627
  }
27045
27628
  function isExecutable(path) {
@@ -27313,12 +27896,12 @@ async function runInstallClaudeTarget(opts, deps = {}) {
27313
27896
  }
27314
27897
 
27315
27898
  // src/commands/install/opencode.ts
27316
- import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
27317
- import { basename as basename4, join as join15 } from "path";
27899
+ import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
27900
+ import { basename as basename4, join as join18 } from "path";
27318
27901
 
27319
27902
  // src/adapters/opencode/deploy.ts
27320
- import { existsSync as existsSync12, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync7 } from "fs";
27321
- import { dirname as dirname9 } from "path";
27903
+ import { existsSync as existsSync12, mkdirSync as mkdirSync4, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
27904
+ import { dirname as dirname10 } from "path";
27322
27905
  function renderPlugin(source, opts) {
27323
27906
  return source.replaceAll("__CARET_VERSION__", () => opts.version).replaceAll("__CARET_BIN__", () => opts.binPath);
27324
27907
  }
@@ -27326,8 +27909,8 @@ function deployFiles(files, opts) {
27326
27909
  const paths = [];
27327
27910
  for (const f2 of files) {
27328
27911
  if (!opts.dryRun) {
27329
- mkdirSync4(dirname9(f2.path), { recursive: true });
27330
- writeFileSync7(f2.path, f2.contents);
27912
+ mkdirSync4(dirname10(f2.path), { recursive: true });
27913
+ writeFileSync8(f2.path, f2.contents);
27331
27914
  }
27332
27915
  paths.push(f2.path);
27333
27916
  }
@@ -27417,7 +28000,7 @@ async function promptUpgrade(verdict, clack) {
27417
28000
 
27418
28001
  // src/commands/install/opencode.ts
27419
28002
  function isCaretCheckout(dir) {
27420
- return existsSync14(join15(dir, "opencode", "caret.plugin.ts"));
28003
+ return existsSync14(join18(dir, "opencode", "caret.plugin.ts"));
27421
28004
  }
27422
28005
  function caretEntries(text2, isCheckout) {
27423
28006
  return pluginEntries(text2).filter((entry) => {
@@ -27443,7 +28026,7 @@ async function runInstallOpencodeTarget(opts, deps = {}) {
27443
28026
  const ui = deps.ui ?? silentUI;
27444
28027
  const isCheckout = deps.isCheckout ?? isCaretCheckout;
27445
28028
  const configFile2 = resolveConfigFile(dir);
27446
- const commandPaths = pkg.commands.map((c3) => join15(commandDir(dir), namespacedCommandFilename(c3.name)));
28029
+ const commandPaths = pkg.commands.map((c3) => join18(commandDir(dir), namespacedCommandFilename(c3.name)));
27447
28030
  const legacy = existingLegacyInstallFiles(dir);
27448
28031
  const specifier = opts.local ? localPluginSpecifier(opts.local.repoDir) : CARET_PACKAGE;
27449
28032
  if (opts.dryRun) {
@@ -27466,7 +28049,7 @@ async function runInstallOpencodeTarget(opts, deps = {}) {
27466
28049
  await upgradeStep(configFile2, opts, deps, ui);
27467
28050
  await sweepLegacy(legacy, dir, ui);
27468
28051
  const files = pkg.commands.map((c3) => ({
27469
- path: join15(commandDir(dir), namespacedCommandFilename(c3.name)),
28052
+ path: join18(commandDir(dir), namespacedCommandFilename(c3.name)),
27470
28053
  contents: renderPlugin(c3.contents, { version: VERSION, binPath: pkg.binPath })
27471
28054
  }));
27472
28055
  await ui.step("Deploying the /caret:* command files", async () => deployFiles(files, { dryRun: false }), (deployed) => `Deployed ${deployed.paths.length} command file(s) to ${dir}`);
@@ -27522,7 +28105,7 @@ function editConfig(path2, transform2) {
27522
28105
  const next = transform2(existing);
27523
28106
  if (next === null || next === existing)
27524
28107
  return [];
27525
- writeFileSync8(path2, next);
28108
+ writeFileSync9(path2, next);
27526
28109
  return [path2];
27527
28110
  }
27528
28111
 
@@ -27534,10 +28117,10 @@ function parseTargets(raw) {
27534
28117
  error: `--target names no agent (it takes a comma-separated list of: ${INSTALL_TARGET_IDS.join(", ")}) \u2014 omit it entirely to choose interactively.`
27535
28118
  };
27536
28119
  }
27537
- const unknown2 = parts.filter((p3) => !INSTALL_TARGET_IDS.includes(p3));
27538
- if (unknown2.length > 0) {
28120
+ const unknown3 = parts.filter((p3) => !INSTALL_TARGET_IDS.includes(p3));
28121
+ if (unknown3.length > 0) {
27539
28122
  return {
27540
- error: `unknown --target value(s): ${unknown2.join(", ")}. Valid: ${INSTALL_TARGET_IDS.join(", ")}.`
28123
+ error: `unknown --target value(s): ${unknown3.join(", ")}. Valid: ${INSTALL_TARGET_IDS.join(", ")}.`
27541
28124
  };
27542
28125
  }
27543
28126
  const targets = [];
@@ -30591,7 +31174,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
30591
31174
  });
30592
31175
  this.runningCommand = proc;
30593
31176
  }
30594
- _dispatchSubcommand(commandName, operands, unknown2) {
31177
+ _dispatchSubcommand(commandName, operands, unknown3) {
30595
31178
  const subCommand = this._findCommand(commandName);
30596
31179
  if (!subCommand)
30597
31180
  this.help({ error: true });
@@ -30600,9 +31183,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
30600
31183
  promiseChain = this._chainOrCallSubCommandHook(promiseChain, subCommand, "preSubcommand");
30601
31184
  promiseChain = this._chainOrCall(promiseChain, () => {
30602
31185
  if (subCommand._executableHandler) {
30603
- this._executeSubCommand(subCommand, operands.concat(unknown2));
31186
+ this._executeSubCommand(subCommand, operands.concat(unknown3));
30604
31187
  } else {
30605
- return subCommand._parseCommand(operands, unknown2);
31188
+ return subCommand._parseCommand(operands, unknown3);
30606
31189
  }
30607
31190
  });
30608
31191
  return promiseChain;
@@ -30699,22 +31282,22 @@ Expecting one of '${allowedValues.join("', '")}'`);
30699
31282
  }
30700
31283
  return result;
30701
31284
  }
30702
- _parseCommand(operands, unknown2) {
30703
- const parsed = this.parseOptions(unknown2);
31285
+ _parseCommand(operands, unknown3) {
31286
+ const parsed = this.parseOptions(unknown3);
30704
31287
  this._parseOptionsEnv();
30705
31288
  this._parseOptionsImplied();
30706
31289
  operands = operands.concat(parsed.operands);
30707
- unknown2 = parsed.unknown;
30708
- this.args = operands.concat(unknown2);
31290
+ unknown3 = parsed.unknown;
31291
+ this.args = operands.concat(unknown3);
30709
31292
  if (operands && this._findCommand(operands[0])) {
30710
- return this._dispatchSubcommand(operands[0], operands.slice(1), unknown2);
31293
+ return this._dispatchSubcommand(operands[0], operands.slice(1), unknown3);
30711
31294
  }
30712
31295
  if (this._getHelpCommand() && operands[0] === this._getHelpCommand().name()) {
30713
31296
  return this._dispatchHelpCommand(operands[1]);
30714
31297
  }
30715
31298
  if (this._defaultCommandName) {
30716
- this._outputHelpIfRequested(unknown2);
30717
- return this._dispatchSubcommand(this._defaultCommandName, operands, unknown2);
31299
+ this._outputHelpIfRequested(unknown3);
31300
+ return this._dispatchSubcommand(this._defaultCommandName, operands, unknown3);
30718
31301
  }
30719
31302
  if (this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName) {
30720
31303
  this.help({ error: true });
@@ -30736,7 +31319,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
30736
31319
  promiseChain = this._chainOrCall(promiseChain, () => this._actionHandler(this.processedArgs));
30737
31320
  if (this.parent) {
30738
31321
  promiseChain = this._chainOrCall(promiseChain, () => {
30739
- this.parent.emit(commandEvent, operands, unknown2);
31322
+ this.parent.emit(commandEvent, operands, unknown3);
30740
31323
  });
30741
31324
  }
30742
31325
  promiseChain = this._chainOrCallHooks(promiseChain, "postAction");
@@ -30745,13 +31328,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
30745
31328
  if (this.parent?.listenerCount(commandEvent)) {
30746
31329
  checkForUnknownOptions();
30747
31330
  this._processArguments();
30748
- this.parent.emit(commandEvent, operands, unknown2);
31331
+ this.parent.emit(commandEvent, operands, unknown3);
30749
31332
  } else if (operands.length) {
30750
31333
  if (this._findCommand("*")) {
30751
- return this._dispatchSubcommand("*", operands, unknown2);
31334
+ return this._dispatchSubcommand("*", operands, unknown3);
30752
31335
  }
30753
31336
  if (this.listenerCount("command:*")) {
30754
- this.emit("command:*", operands, unknown2);
31337
+ this.emit("command:*", operands, unknown3);
30755
31338
  } else if (this.commands.length) {
30756
31339
  this.unknownCommand();
30757
31340
  } else {
@@ -30806,7 +31389,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
30806
31389
  }
30807
31390
  parseOptions(args) {
30808
31391
  const operands = [];
30809
- const unknown2 = [];
31392
+ const unknown3 = [];
30810
31393
  let dest = operands;
30811
31394
  function maybeOption(arg) {
30812
31395
  return arg.length > 1 && arg[0] === "-";
@@ -30823,7 +31406,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
30823
31406
  const arg = activeGroup ?? args[i2++];
30824
31407
  activeGroup = null;
30825
31408
  if (arg === "--") {
30826
- if (dest === unknown2)
31409
+ if (dest === unknown3)
30827
31410
  dest.push(arg);
30828
31411
  dest.push(...args.slice(i2));
30829
31412
  break;
@@ -30875,18 +31458,18 @@ Expecting one of '${allowedValues.join("', '")}'`);
30875
31458
  }
30876
31459
  }
30877
31460
  if (dest === operands && maybeOption(arg) && !(this.commands.length === 0 && negativeNumberArg(arg))) {
30878
- dest = unknown2;
31461
+ dest = unknown3;
30879
31462
  }
30880
- if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown2.length === 0) {
31463
+ if ((this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown3.length === 0) {
30881
31464
  if (this._findCommand(arg)) {
30882
31465
  operands.push(arg);
30883
- unknown2.push(...args.slice(i2));
31466
+ unknown3.push(...args.slice(i2));
30884
31467
  break;
30885
31468
  } else if (this._getHelpCommand() && arg === this._getHelpCommand().name()) {
30886
31469
  operands.push(arg, ...args.slice(i2));
30887
31470
  break;
30888
31471
  } else if (this._defaultCommandName) {
30889
- unknown2.push(arg, ...args.slice(i2));
31472
+ unknown3.push(arg, ...args.slice(i2));
30890
31473
  break;
30891
31474
  }
30892
31475
  }
@@ -30896,7 +31479,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
30896
31479
  }
30897
31480
  dest.push(arg);
30898
31481
  }
30899
- return { operands, unknown: unknown2 };
31482
+ return { operands, unknown: unknown3 };
30900
31483
  }
30901
31484
  opts() {
30902
31485
  if (this._storeOptionsAsProperties) {