@band-app/server 0.58.0 → 0.60.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 (131) hide show
  1. package/dist/client/_shell.html +0 -0
  2. package/dist/client/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  3. package/dist/client/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  4. package/dist/client/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  5. package/dist/client/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  6. package/dist/client/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  7. package/dist/client/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  8. package/dist/client/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  9. package/dist/client/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  10. package/dist/client/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  11. package/dist/client/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  12. package/dist/client/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  13. package/dist/client/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  14. package/dist/client/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  15. package/dist/client/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  16. package/dist/client/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  17. package/dist/client/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  18. package/dist/client/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  19. package/dist/client/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  20. package/dist/client/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  21. package/dist/client/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  22. package/dist/client/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  23. package/dist/client/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  24. package/dist/client/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  25. package/dist/client/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  26. package/dist/client/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  27. package/dist/client/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  28. package/dist/client/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  29. package/dist/client/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  30. package/dist/client/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  31. package/dist/client/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  32. package/dist/client/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  33. package/dist/client/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  34. package/dist/client/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  35. package/dist/client/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  36. package/dist/client/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  37. package/dist/client/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  38. package/dist/client/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  39. package/dist/client/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  40. package/dist/client/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  41. package/dist/client/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  42. package/dist/client/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  43. package/dist/client/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  44. package/dist/client/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  45. package/dist/client/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  46. package/dist/client/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  47. package/dist/client/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  48. package/dist/client/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  49. package/dist/client/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  50. package/dist/client/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  51. package/dist/client/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  52. package/dist/client/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  53. package/dist/client/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  54. package/dist/client/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  55. package/dist/client/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  56. package/dist/client/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  57. package/dist/client/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  58. package/dist/client/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  59. package/dist/client/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  60. package/dist/client/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  61. package/dist/client/assets/{TerminalPanel-DZpYM-2e.js → TerminalPanel-B15ghqjC.js} +1 -1
  62. package/dist/client/assets/{_basePickBy-6zU_l56i.js → _basePickBy-DnTEmDSj.js} +1 -1
  63. package/dist/client/assets/{_baseUniq-BmNIWTzJ.js → _baseUniq-vhCiyIYf.js} +1 -1
  64. package/dist/client/assets/{arc-C2guaHsn.js → arc-CZ4Bw9uS.js} +1 -1
  65. package/dist/client/assets/{architectureDiagram-VXUJARFQ-CC-6zRwy.js → architectureDiagram-VXUJARFQ-CvqgWcYx.js} +1 -1
  66. package/dist/client/assets/{blockDiagram-VD42YOAC-SUU89nqx.js → blockDiagram-VD42YOAC-D8REfakL.js} +1 -1
  67. package/dist/client/assets/{c4Diagram-YG6GDRKO-Brqvl68E.js → c4Diagram-YG6GDRKO-BIgJnhrx.js} +1 -1
  68. package/dist/client/assets/channel-DaBOqDcm.js +1 -0
  69. package/dist/client/assets/{chunk-4BX2VUAB-aSJIRJbo.js → chunk-4BX2VUAB-BO8PrQP3.js} +1 -1
  70. package/dist/client/assets/{chunk-55IACEB6-Be_ygmcl.js → chunk-55IACEB6-DO5fHd1T.js} +1 -1
  71. package/dist/client/assets/{chunk-B4BG7PRW-DO9kuFIX.js → chunk-B4BG7PRW-CAtAtkCf.js} +1 -1
  72. package/dist/client/assets/{chunk-DI55MBZ5-Cs6PrThE.js → chunk-DI55MBZ5-DRnZO_Tx.js} +1 -1
  73. package/dist/client/assets/{chunk-FMBD7UC4-NBjR-LSj.js → chunk-FMBD7UC4-DzqqzV_F.js} +1 -1
  74. package/dist/client/assets/{chunk-QN33PNHL-CthBcGPW.js → chunk-QN33PNHL-DETRpC4Q.js} +1 -1
  75. package/dist/client/assets/{chunk-QZHKN3VN-DFzP7rYv.js → chunk-QZHKN3VN-D6X6jOAA.js} +1 -1
  76. package/dist/client/assets/{chunk-TZMSLE5B-BtqUkL_w.js → chunk-TZMSLE5B-C8IfJ5NA.js} +1 -1
  77. package/dist/client/assets/classDiagram-2ON5EDUG-CovRsOYg.js +1 -0
  78. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CovRsOYg.js +1 -0
  79. package/dist/client/assets/clone-CEAieby9.js +1 -0
  80. package/dist/client/assets/{cose-bilkent-S5V4N54A-DhyKm2TQ.js → cose-bilkent-S5V4N54A-DMKRB7Bs.js} +1 -1
  81. package/dist/client/assets/{dagre-6UL2VRFP-NY1AKNho.js → dagre-6UL2VRFP-C_cXM9p2.js} +1 -1
  82. package/dist/client/assets/{diagram-PSM6KHXK-CCYOdCnq.js → diagram-PSM6KHXK-D_A2BJh_.js} +1 -1
  83. package/dist/client/assets/{diagram-QEK2KX5R-EcSNtDiG.js → diagram-QEK2KX5R-BnKjlyrI.js} +1 -1
  84. package/dist/client/assets/{diagram-S2PKOQOG-Cvp7SMU7.js → diagram-S2PKOQOG-R4tiwc1I.js} +1 -1
  85. package/dist/client/assets/{erDiagram-Q2GNP2WA-BF1T1k5o.js → erDiagram-Q2GNP2WA-CNV08IQO.js} +1 -1
  86. package/dist/client/assets/{flowDiagram-NV44I4VS-PZ3CeJSZ.js → flowDiagram-NV44I4VS-BAXwfe4s.js} +1 -1
  87. package/dist/client/assets/{ganttDiagram-JELNMOA3-BHzq_mda.js → ganttDiagram-JELNMOA3-Bk3PXBP9.js} +1 -1
  88. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-CEkwii1J.js → gitGraphDiagram-V2S2FVAM-C8tujQgm.js} +1 -1
  89. package/dist/client/assets/{graph-CKhBarkm.js → graph-BIBqorc8.js} +1 -1
  90. package/dist/client/assets/{highlighted-body-B3W2YXNL-Cyw8VbMw.js → highlighted-body-B3W2YXNL-NymhDWI2.js} +1 -1
  91. package/dist/client/assets/{index-gv92vNY4.js → index-BKBEQAUS.js} +1 -1
  92. package/dist/client/assets/{index-78ZDd0_e.js → index-BYs8YaN9.js} +1 -1
  93. package/dist/client/assets/{index-DsKR-Mzt.js → index-BYzUhLmm.js} +1 -1
  94. package/dist/client/assets/{index-Bunws-S6.js → index-BvS6Fo_E.js} +1 -1
  95. package/dist/client/assets/{index-CXP92XgX.js → index-C6Buf5vO.js} +1 -1
  96. package/dist/client/assets/{index-s6CshXgO.js → index-Cqclrque.js} +1 -1
  97. package/dist/client/assets/{index-D5VI3PBL.js → index-D9qmTeqK.js} +1 -1
  98. package/dist/client/assets/{index-Co0BifvH.js → index-DJlBcjuS.js} +1 -1
  99. package/dist/client/assets/{index-vgGRpYpH.js → index-DSUNlkvo.js} +1 -1
  100. package/dist/client/assets/{index-BcU6fwij.js → index-Dc6DOl2V.js} +1 -1
  101. package/dist/client/assets/{index-ufFGOVtC.js → index-Dg2MZcDG.js} +1 -1
  102. package/dist/client/assets/{index-9FdHLIm3.js → index-PQDlzdDe.js} +1 -1
  103. package/dist/client/assets/{index-CQzYQxW2.js → index-secZqOa5.js} +1 -1
  104. package/dist/client/assets/{infoDiagram-HS3SLOUP-AFDG1cfu.js → infoDiagram-HS3SLOUP-GzU-nr0a.js} +1 -1
  105. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-OD_QroD7.js → journeyDiagram-XKPGCS4Q-Dv_GZIcq.js} +1 -1
  106. package/dist/client/assets/{kanban-definition-3W4ZIXB7-DAnN30hM.js → kanban-definition-3W4ZIXB7-BuCDku9Z.js} +1 -1
  107. package/dist/client/assets/{layout-B5dwS7ni.js → layout-C1BWvm3U.js} +1 -1
  108. package/dist/client/assets/{main-BbrdKUoC.js → main-CW1tJAHn.js} +314 -310
  109. package/dist/client/assets/main-CYIZgqYb.css +1 -0
  110. package/dist/client/assets/{mindmap-definition-VGOIOE7T-AKV3Q3Hd.js → mindmap-definition-VGOIOE7T-D-ySOJ80.js} +1 -1
  111. package/dist/client/assets/{pieDiagram-ADFJNKIX-i4GRsEWp.js → pieDiagram-ADFJNKIX-BCPXro4s.js} +1 -1
  112. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-DNSnhdH3.js → quadrantDiagram-AYHSOK5B-6iX-Hvg-.js} +1 -1
  113. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-iUlIxrQo.js → requirementDiagram-UZGBJVZJ-CZu5itKP.js} +1 -1
  114. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BSJNlHPV.js → sankeyDiagram-TZEHDZUN-C7dzQDVd.js} +1 -1
  115. package/dist/client/assets/{sequenceDiagram-WL72ISMW-CjyKPEZX.js → sequenceDiagram-WL72ISMW-Q9GYKo64.js} +1 -1
  116. package/dist/client/assets/{stateDiagram-FKZM4ZOC-DpwtZO7l.js → stateDiagram-FKZM4ZOC-DcAjq5pM.js} +1 -1
  117. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-D0LqsI9r.js +1 -0
  118. package/dist/client/assets/{timeline-definition-IT6M3QCI-C36BxQGp.js → timeline-definition-IT6M3QCI-CkyryJCh.js} +1 -1
  119. package/dist/client/assets/{treemap-GDKQZRPO-B4ZwYsLv.js → treemap-GDKQZRPO-BW9t3c2Z.js} +1 -1
  120. package/dist/client/assets/{worktree._worktreeId-BuDv4Wcj.js → worktree._worktreeId-BvQb_KmW.js} +1 -1
  121. package/dist/client/assets/{worktree._worktreeId-7gZfrkWN.js → worktree._worktreeId-CWpDyVL-.js} +1 -1
  122. package/dist/client/assets/{xychartDiagram-PRI3JC2R-B5IPrNpQ.js → xychartDiagram-PRI3JC2R-DxUmnBlk.js} +1 -1
  123. package/dist/openapi.json +759 -260
  124. package/dist/start-server.mjs +1216 -548
  125. package/package.json +11 -11
  126. package/dist/client/assets/channel-Cw0fhbpQ.js +0 -1
  127. package/dist/client/assets/classDiagram-2ON5EDUG-B6EGY8M-.js +0 -1
  128. package/dist/client/assets/classDiagram-v2-WZHVMYZB-B6EGY8M-.js +0 -1
  129. package/dist/client/assets/clone-BfwFgnQO.js +0 -1
  130. package/dist/client/assets/main-CsceWi1l.css +0 -1
  131. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-Cq_p4YyT.js +0 -1
@@ -2136,7 +2136,7 @@ var require_thread_stream = __commonJS({
2136
2136
  var { version: version3 } = require_package();
2137
2137
  var { EventEmitter: EventEmitter4 } = __require("events");
2138
2138
  var { Worker: Worker2 } = __require("worker_threads");
2139
- var { join: join62 } = __require("path");
2139
+ var { join: join63 } = __require("path");
2140
2140
  var { pathToFileURL } = __require("url");
2141
2141
  var { wait } = require_wait();
2142
2142
  var {
@@ -2172,7 +2172,7 @@ var require_thread_stream = __commonJS({
2172
2172
  function createWorker(stream, opts) {
2173
2173
  const { filename, workerData } = opts;
2174
2174
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
2175
- const toExecute = bundlerOverrides["thread-stream-worker"] || join62(__dirname, "lib", "worker.js");
2175
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join63(__dirname, "lib", "worker.js");
2176
2176
  const worker2 = new Worker2(toExecute, {
2177
2177
  ...opts.workerOpts,
2178
2178
  trackUnmanagedFds: false,
@@ -2558,7 +2558,7 @@ var require_transport = __commonJS({
2558
2558
  "use strict";
2559
2559
  var { createRequire: createRequire3 } = __require("module");
2560
2560
  var getCallers = require_caller();
2561
- var { join: join62, isAbsolute: isAbsolute7, sep: sep13 } = __require("node:path");
2561
+ var { join: join63, isAbsolute: isAbsolute7, sep: sep13 } = __require("node:path");
2562
2562
  var sleep3 = require_atomic_sleep();
2563
2563
  var onExit = require_on_exit_leak_free();
2564
2564
  var ThreadStream = require_thread_stream();
@@ -2621,7 +2621,7 @@ var require_transport = __commonJS({
2621
2621
  throw new Error("only one of target or targets can be specified");
2622
2622
  }
2623
2623
  if (targets) {
2624
- target = bundlerOverrides["pino-worker"] || join62(__dirname, "worker.js");
2624
+ target = bundlerOverrides["pino-worker"] || join63(__dirname, "worker.js");
2625
2625
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
2626
2626
  return {
2627
2627
  ...dest,
@@ -2639,7 +2639,7 @@ var require_transport = __commonJS({
2639
2639
  });
2640
2640
  });
2641
2641
  } else if (pipeline4) {
2642
- target = bundlerOverrides["pino-worker"] || join62(__dirname, "worker.js");
2642
+ target = bundlerOverrides["pino-worker"] || join63(__dirname, "worker.js");
2643
2643
  options.pipelines = [pipeline4.map((dest) => {
2644
2644
  return {
2645
2645
  ...dest,
@@ -2661,7 +2661,7 @@ var require_transport = __commonJS({
2661
2661
  return origin;
2662
2662
  }
2663
2663
  if (origin === "pino/file") {
2664
- return join62(__dirname, "..", "file.js");
2664
+ return join63(__dirname, "..", "file.js");
2665
2665
  }
2666
2666
  let fixTarget2;
2667
2667
  for (const filePath of callers) {
@@ -3650,7 +3650,7 @@ var require_safe_stable_stringify = __commonJS({
3650
3650
  return circularValue;
3651
3651
  }
3652
3652
  let res = "";
3653
- let join62 = ",";
3653
+ let join63 = ",";
3654
3654
  const originalIndentation = indentation;
3655
3655
  if (Array.isArray(value)) {
3656
3656
  if (value.length === 0) {
@@ -3664,7 +3664,7 @@ var require_safe_stable_stringify = __commonJS({
3664
3664
  indentation += spacer;
3665
3665
  res += `
3666
3666
  ${indentation}`;
3667
- join62 = `,
3667
+ join63 = `,
3668
3668
  ${indentation}`;
3669
3669
  }
3670
3670
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3672,13 +3672,13 @@ ${indentation}`;
3672
3672
  for (; i < maximumValuesToStringify - 1; i++) {
3673
3673
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3674
3674
  res += tmp2 !== void 0 ? tmp2 : "null";
3675
- res += join62;
3675
+ res += join63;
3676
3676
  }
3677
3677
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
3678
3678
  res += tmp !== void 0 ? tmp : "null";
3679
3679
  if (value.length - 1 > maximumBreadth) {
3680
3680
  const removedKeys = value.length - maximumBreadth - 1;
3681
- res += `${join62}"... ${getItemCount(removedKeys)} not stringified"`;
3681
+ res += `${join63}"... ${getItemCount(removedKeys)} not stringified"`;
3682
3682
  }
3683
3683
  if (spacer !== "") {
3684
3684
  res += `
@@ -3699,7 +3699,7 @@ ${originalIndentation}`;
3699
3699
  let separator = "";
3700
3700
  if (spacer !== "") {
3701
3701
  indentation += spacer;
3702
- join62 = `,
3702
+ join63 = `,
3703
3703
  ${indentation}`;
3704
3704
  whitespace = " ";
3705
3705
  }
@@ -3713,13 +3713,13 @@ ${indentation}`;
3713
3713
  const tmp = stringifyFnReplacer(key3, value, stack, replacer, spacer, indentation);
3714
3714
  if (tmp !== void 0) {
3715
3715
  res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
3716
- separator = join62;
3716
+ separator = join63;
3717
3717
  }
3718
3718
  }
3719
3719
  if (keyLength > maximumBreadth) {
3720
3720
  const removedKeys = keyLength - maximumBreadth;
3721
3721
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
3722
- separator = join62;
3722
+ separator = join63;
3723
3723
  }
3724
3724
  if (spacer !== "" && separator.length > 1) {
3725
3725
  res = `
@@ -3760,7 +3760,7 @@ ${originalIndentation}`;
3760
3760
  }
3761
3761
  const originalIndentation = indentation;
3762
3762
  let res = "";
3763
- let join62 = ",";
3763
+ let join63 = ",";
3764
3764
  if (Array.isArray(value)) {
3765
3765
  if (value.length === 0) {
3766
3766
  return "[]";
@@ -3773,7 +3773,7 @@ ${originalIndentation}`;
3773
3773
  indentation += spacer;
3774
3774
  res += `
3775
3775
  ${indentation}`;
3776
- join62 = `,
3776
+ join63 = `,
3777
3777
  ${indentation}`;
3778
3778
  }
3779
3779
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -3781,13 +3781,13 @@ ${indentation}`;
3781
3781
  for (; i < maximumValuesToStringify - 1; i++) {
3782
3782
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3783
3783
  res += tmp2 !== void 0 ? tmp2 : "null";
3784
- res += join62;
3784
+ res += join63;
3785
3785
  }
3786
3786
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
3787
3787
  res += tmp !== void 0 ? tmp : "null";
3788
3788
  if (value.length - 1 > maximumBreadth) {
3789
3789
  const removedKeys = value.length - maximumBreadth - 1;
3790
- res += `${join62}"... ${getItemCount(removedKeys)} not stringified"`;
3790
+ res += `${join63}"... ${getItemCount(removedKeys)} not stringified"`;
3791
3791
  }
3792
3792
  if (spacer !== "") {
3793
3793
  res += `
@@ -3800,7 +3800,7 @@ ${originalIndentation}`;
3800
3800
  let whitespace = "";
3801
3801
  if (spacer !== "") {
3802
3802
  indentation += spacer;
3803
- join62 = `,
3803
+ join63 = `,
3804
3804
  ${indentation}`;
3805
3805
  whitespace = " ";
3806
3806
  }
@@ -3809,7 +3809,7 @@ ${indentation}`;
3809
3809
  const tmp = stringifyArrayReplacer(key3, value[key3], stack, replacer, spacer, indentation);
3810
3810
  if (tmp !== void 0) {
3811
3811
  res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
3812
- separator = join62;
3812
+ separator = join63;
3813
3813
  }
3814
3814
  }
3815
3815
  if (spacer !== "" && separator.length > 1) {
@@ -3867,20 +3867,20 @@ ${originalIndentation}`;
3867
3867
  indentation += spacer;
3868
3868
  let res2 = `
3869
3869
  ${indentation}`;
3870
- const join63 = `,
3870
+ const join64 = `,
3871
3871
  ${indentation}`;
3872
3872
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
3873
3873
  let i = 0;
3874
3874
  for (; i < maximumValuesToStringify - 1; i++) {
3875
3875
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3876
3876
  res2 += tmp2 !== void 0 ? tmp2 : "null";
3877
- res2 += join63;
3877
+ res2 += join64;
3878
3878
  }
3879
3879
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
3880
3880
  res2 += tmp !== void 0 ? tmp : "null";
3881
3881
  if (value.length - 1 > maximumBreadth) {
3882
3882
  const removedKeys = value.length - maximumBreadth - 1;
3883
- res2 += `${join63}"... ${getItemCount(removedKeys)} not stringified"`;
3883
+ res2 += `${join64}"... ${getItemCount(removedKeys)} not stringified"`;
3884
3884
  }
3885
3885
  res2 += `
3886
3886
  ${originalIndentation}`;
@@ -3896,16 +3896,16 @@ ${originalIndentation}`;
3896
3896
  return '"[Object]"';
3897
3897
  }
3898
3898
  indentation += spacer;
3899
- const join62 = `,
3899
+ const join63 = `,
3900
3900
  ${indentation}`;
3901
3901
  let res = "";
3902
3902
  let separator = "";
3903
3903
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
3904
3904
  if (isTypedArrayWithEntries(value)) {
3905
- res += stringifyTypedArray(value, join62, maximumBreadth);
3905
+ res += stringifyTypedArray(value, join63, maximumBreadth);
3906
3906
  keys = keys.slice(value.length);
3907
3907
  maximumPropertiesToStringify -= value.length;
3908
- separator = join62;
3908
+ separator = join63;
3909
3909
  }
3910
3910
  if (deterministic) {
3911
3911
  keys = sort(keys, comparator2);
@@ -3916,13 +3916,13 @@ ${indentation}`;
3916
3916
  const tmp = stringifyIndent(key3, value[key3], stack, spacer, indentation);
3917
3917
  if (tmp !== void 0) {
3918
3918
  res += `${separator}${strEscape(key3)}: ${tmp}`;
3919
- separator = join62;
3919
+ separator = join63;
3920
3920
  }
3921
3921
  }
3922
3922
  if (keyLength > maximumBreadth) {
3923
3923
  const removedKeys = keyLength - maximumBreadth;
3924
3924
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
3925
- separator = join62;
3925
+ separator = join63;
3926
3926
  }
3927
3927
  if (separator !== "") {
3928
3928
  res = `
@@ -4289,7 +4289,7 @@ var require_pino = __commonJS({
4289
4289
  } = symbols;
4290
4290
  var { epochTime, nullTime } = time6;
4291
4291
  var { pid } = process;
4292
- var hostname6 = os.hostname();
4292
+ var hostname7 = os.hostname();
4293
4293
  var defaultErrorSerializer = stdSerializers.err;
4294
4294
  var defaultOptions2 = {
4295
4295
  level: "info",
@@ -4299,7 +4299,7 @@ var require_pino = __commonJS({
4299
4299
  errorKey: "err",
4300
4300
  nestedKey: null,
4301
4301
  enabled: true,
4302
- base: { pid, hostname: hostname6 },
4302
+ base: { pid, hostname: hostname7 },
4303
4303
  serializers: Object.assign(/* @__PURE__ */ Object.create(null), {
4304
4304
  err: defaultErrorSerializer
4305
4305
  }),
@@ -4604,9 +4604,9 @@ function checkEndpointOwner(socketPath) {
4604
4604
  }
4605
4605
  return "ok";
4606
4606
  }
4607
- function entryIdentity(path2, stat8) {
4607
+ function entryIdentity(path2, stat9) {
4608
4608
  try {
4609
- const stats = stat8(path2, { bigint: true });
4609
+ const stats = stat9(path2, { bigint: true });
4610
4610
  return { dev: stats.dev, ino: stats.ino };
4611
4611
  } catch {
4612
4612
  return null;
@@ -15184,7 +15184,7 @@ var require_stream = __commonJS({
15184
15184
  };
15185
15185
  duplex._final = function(callback) {
15186
15186
  if (ws.readyState === ws.CONNECTING) {
15187
- ws.once("open", function open4() {
15187
+ ws.once("open", function open3() {
15188
15188
  duplex._final(callback);
15189
15189
  });
15190
15190
  return;
@@ -15205,7 +15205,7 @@ var require_stream = __commonJS({
15205
15205
  };
15206
15206
  duplex._write = function(chunk, encoding, callback) {
15207
15207
  if (ws.readyState === ws.CONNECTING) {
15208
- ws.once("open", function open4() {
15208
+ ws.once("open", function open3() {
15209
15209
  duplex._write(chunk, encoding, callback);
15210
15210
  });
15211
15211
  return;
@@ -16489,6 +16489,13 @@ var init_pty2 = __esm({
16489
16489
  }
16490
16490
  });
16491
16491
 
16492
+ // ../../packages/host-api/src/resources.ts
16493
+ var init_resources = __esm({
16494
+ "../../packages/host-api/src/resources.ts"() {
16495
+ "use strict";
16496
+ }
16497
+ });
16498
+
16492
16499
  // ../../packages/host-api/src/index.ts
16493
16500
  var init_src3 = __esm({
16494
16501
  "../../packages/host-api/src/index.ts"() {
@@ -16498,6 +16505,7 @@ var init_src3 = __esm({
16498
16505
  init_git_run();
16499
16506
  init_host();
16500
16507
  init_pty2();
16508
+ init_resources();
16501
16509
  }
16502
16510
  });
16503
16511
 
@@ -16835,6 +16843,8 @@ var init_rpc = __esm({
16835
16843
  "fs.copy": 5 * 6e4,
16836
16844
  "fs.rm": 2 * 6e4,
16837
16845
  "fs.du": 2 * 6e4,
16846
+ // Measures every worktree of a worker, three `du` at a time.
16847
+ "resources.storage": 10 * 6e4,
16838
16848
  "fs.glob": 6e4,
16839
16849
  "search.listFiles": 6e4,
16840
16850
  "scripts.runHidden": 10 * 6e4,
@@ -17061,6 +17071,10 @@ var init_remote_host = __esm({
17061
17071
  return duplexOf(this.rpc.channel(reply.chan));
17062
17072
  }
17063
17073
  };
17074
+ resources = {
17075
+ snapshot: () => this.rpc.call("resources.snapshot", {}),
17076
+ storage: (request) => this.rpc.call("resources.storage", request)
17077
+ };
17064
17078
  speech = {
17065
17079
  transcribe: async (req) => {
17066
17080
  const { audio, ...rest } = req;
@@ -17128,7 +17142,7 @@ var init_remote_host = __esm({
17128
17142
  // The worker keeps the browser. `browser.connect` opens one channel of length-prefixed CDP
17129
17143
  // messages, and resetting it drops the connection but not the browser.
17130
17144
  browser = {
17131
- open: (spec) => this.rpc.call("browser.open", spec, { timeoutMs: 6e4 }),
17145
+ open: (spec) => this.rpc.call("browser.open", spec, { timeoutMs: 15e4 }),
17132
17146
  connect: async (worktreeId4) => {
17133
17147
  const reply = await this.rpc.request("browser.connect", { worktreeId: worktreeId4 });
17134
17148
  const ch = this.rpc.channel(reply.chan);
@@ -20859,9 +20873,9 @@ function parseURLObject(trimmed, def) {
20859
20873
  function stripTabAndNewline(value) {
20860
20874
  return value.replace(asciiTabOrNewline, "");
20861
20875
  }
20862
- function urlHostnameOk(url3, hostname6) {
20863
- hostname6.lastIndex = 0;
20864
- return hostname6.test(url3.hostname);
20876
+ function urlHostnameOk(url3, hostname7) {
20877
+ hostname7.lastIndex = 0;
20878
+ return hostname7.test(url3.hostname);
20865
20879
  }
20866
20880
  function urlProtocolOk(url3, protocol) {
20867
20881
  protocol.lastIndex = 0;
@@ -38570,7 +38584,7 @@ function visit(schema, fnOrHandlers) {
38570
38584
  return h ? h(node2, rewritten) : node2;
38571
38585
  };
38572
38586
  const cache2 = /* @__PURE__ */ new Map();
38573
- function run3(s2) {
38587
+ function run4(s2) {
38574
38588
  const cached4 = cache2.get(s2);
38575
38589
  if (cached4 === RESOLVING) {
38576
38590
  return new $ZodLazy({
@@ -38596,21 +38610,21 @@ function visit(schema, fnOrHandlers) {
38596
38610
  let changed = false;
38597
38611
  const newShape = {};
38598
38612
  for (const k2 of keys) {
38599
- const mapped = run3(oldShape[k2]);
38613
+ const mapped = run4(oldShape[k2]);
38600
38614
  if (mapped !== oldShape[k2])
38601
38615
  changed = true;
38602
38616
  newShape[k2] = mapped;
38603
38617
  }
38604
38618
  let newCatchall = def.catchall;
38605
38619
  if (def.catchall) {
38606
- newCatchall = run3(def.catchall);
38620
+ newCatchall = run4(def.catchall);
38607
38621
  if (newCatchall !== def.catchall)
38608
38622
  changed = true;
38609
38623
  }
38610
38624
  return changed ? clone(s2, { ...def, shape: newShape, catchall: newCatchall }) : s2;
38611
38625
  }
38612
38626
  case "array": {
38613
- const mapped = run3(def.element);
38627
+ const mapped = run4(def.element);
38614
38628
  return mapped === def.element ? s2 : clone(s2, { ...def, element: mapped });
38615
38629
  }
38616
38630
  case "tuple": {
@@ -38618,14 +38632,14 @@ function visit(schema, fnOrHandlers) {
38618
38632
  let changed = false;
38619
38633
  const newItems = [];
38620
38634
  for (const item of oldItems) {
38621
- const mapped = run3(item);
38635
+ const mapped = run4(item);
38622
38636
  if (mapped !== item)
38623
38637
  changed = true;
38624
38638
  newItems.push(mapped);
38625
38639
  }
38626
38640
  let newRest = def.rest;
38627
38641
  if (def.rest) {
38628
- newRest = run3(def.rest);
38642
+ newRest = run4(def.rest);
38629
38643
  if (newRest !== def.rest)
38630
38644
  changed = true;
38631
38645
  }
@@ -38633,12 +38647,12 @@ function visit(schema, fnOrHandlers) {
38633
38647
  }
38634
38648
  case "record":
38635
38649
  case "map": {
38636
- const newKey = run3(def.keyType);
38637
- const newVal = run3(def.valueType);
38650
+ const newKey = run4(def.keyType);
38651
+ const newVal = run4(def.valueType);
38638
38652
  return newKey === def.keyType && newVal === def.valueType ? s2 : clone(s2, { ...def, keyType: newKey, valueType: newVal });
38639
38653
  }
38640
38654
  case "set": {
38641
- const newVal = run3(def.valueType);
38655
+ const newVal = run4(def.valueType);
38642
38656
  return newVal === def.valueType ? s2 : clone(s2, { ...def, valueType: newVal });
38643
38657
  }
38644
38658
  case "union": {
@@ -38646,7 +38660,7 @@ function visit(schema, fnOrHandlers) {
38646
38660
  let changed = false;
38647
38661
  const newOptions = [];
38648
38662
  for (const opt of oldOptions) {
38649
- const mapped = run3(opt);
38663
+ const mapped = run4(opt);
38650
38664
  if (mapped !== opt)
38651
38665
  changed = true;
38652
38666
  newOptions.push(mapped);
@@ -38654,8 +38668,8 @@ function visit(schema, fnOrHandlers) {
38654
38668
  return changed ? clone(s2, { ...def, options: newOptions }) : s2;
38655
38669
  }
38656
38670
  case "intersection": {
38657
- const newLeft = run3(def.left);
38658
- const newRight = run3(def.right);
38671
+ const newLeft = run4(def.left);
38672
+ const newRight = run4(def.right);
38659
38673
  return newLeft === def.left && newRight === def.right ? s2 : clone(s2, { ...def, left: newLeft, right: newRight });
38660
38674
  }
38661
38675
  case "optional":
@@ -38667,23 +38681,23 @@ function visit(schema, fnOrHandlers) {
38667
38681
  case "nonoptional":
38668
38682
  case "promise":
38669
38683
  case "success": {
38670
- const newInner = run3(def.innerType);
38684
+ const newInner = run4(def.innerType);
38671
38685
  return newInner === def.innerType ? s2 : clone(s2, { ...def, innerType: newInner });
38672
38686
  }
38673
38687
  case "pipe": {
38674
- const newIn = run3(def.in);
38675
- const newOut = run3(def.out);
38688
+ const newIn = run4(def.in);
38689
+ const newOut = run4(def.out);
38676
38690
  return newIn === def.in && newOut === def.out ? s2 : clone(s2, { ...def, in: newIn, out: newOut });
38677
38691
  }
38678
38692
  case "function": {
38679
- const newInput = run3(def.input);
38680
- const newOutput = run3(def.output);
38693
+ const newInput = run4(def.input);
38694
+ const newOutput = run4(def.output);
38681
38695
  return newInput === def.input && newOutput === def.output ? s2 : clone(s2, { ...def, input: newInput, output: newOutput });
38682
38696
  }
38683
38697
  case "lazy": {
38684
38698
  const original = def.getter;
38685
38699
  const { _cachedInner, ...rest } = def;
38686
- return clone(s2, { ...rest, getter: () => run3(original()) });
38700
+ return clone(s2, { ...rest, getter: () => run4(original()) });
38687
38701
  }
38688
38702
  // A leaf by choice: `parts` are regex fragments, not data positions.
38689
38703
  case "template_literal":
@@ -38714,7 +38728,7 @@ function visit(schema, fnOrHandlers) {
38714
38728
  }
38715
38729
  }
38716
38730
  }
38717
- return run3(schema);
38731
+ return run4(schema);
38718
38732
  }
38719
38733
  var RESOLVING;
38720
38734
  var init_visit = __esm({
@@ -43517,27 +43531,27 @@ function textChunk(row) {
43517
43531
  }
43518
43532
  function rowsToEvents(rows) {
43519
43533
  const out = [];
43520
- let run3 = null;
43534
+ let run4 = null;
43521
43535
  const flush = () => {
43522
- if (!run3) return;
43536
+ if (!run4) return;
43523
43537
  out.push({
43524
43538
  type: "update",
43525
- update: { ...run3.update, content: { type: "text", text: run3.text } },
43526
- eventId: run3.lastId,
43527
- createdAt: run3.createdAt
43539
+ update: { ...run4.update, content: { type: "text", text: run4.text } },
43540
+ eventId: run4.lastId,
43541
+ createdAt: run4.createdAt
43528
43542
  });
43529
- run3 = null;
43543
+ run4 = null;
43530
43544
  };
43531
43545
  for (const row of rows) {
43532
43546
  const chunk = textChunk(row);
43533
- if (chunk && run3 && run3.update.sessionUpdate === chunk.sessionUpdate && (run3.update.messageId ?? null) === (chunk.messageId ?? null)) {
43534
- if (chunk.content.type === "text") run3.text += chunk.content.text;
43535
- run3.lastId = row.id;
43547
+ if (chunk && run4 && run4.update.sessionUpdate === chunk.sessionUpdate && (run4.update.messageId ?? null) === (chunk.messageId ?? null)) {
43548
+ if (chunk.content.type === "text") run4.text += chunk.content.text;
43549
+ run4.lastId = row.id;
43536
43550
  continue;
43537
43551
  }
43538
43552
  flush();
43539
43553
  if (chunk) {
43540
- run3 = {
43554
+ run4 = {
43541
43555
  update: chunk,
43542
43556
  text: chunk.content.type === "text" ? chunk.content.text : "",
43543
43557
  lastId: row.id,
@@ -43831,10 +43845,10 @@ var init_table = __esm({
43831
43845
  [IsDrizzleTable] = true;
43832
43846
  /** @internal */
43833
43847
  [ExtraConfigBuilder] = void 0;
43834
- constructor(name5, schema, baseName) {
43848
+ constructor(name5, schema, baseName2) {
43835
43849
  this[TableName] = this[OriginalName] = name5;
43836
43850
  this[TableSchema] = schema;
43837
- this[BaseName] = baseName;
43851
+ this[BaseName] = baseName2;
43838
43852
  }
43839
43853
  };
43840
43854
  }
@@ -44191,7 +44205,7 @@ var init_sql = __esm({
44191
44205
  return new SQL([new StringChunk(str3)]);
44192
44206
  }
44193
44207
  _sql.raw = raw;
44194
- function join62(chunks, separator) {
44208
+ function join63(chunks, separator) {
44195
44209
  const result = [];
44196
44210
  for (const [i, chunk] of chunks.entries()) {
44197
44211
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -44199,7 +44213,7 @@ var init_sql = __esm({
44199
44213
  }
44200
44214
  return new SQL(result);
44201
44215
  }
44202
- _sql.join = join62;
44216
+ _sql.join = join63;
44203
44217
  function identifier(value) {
44204
44218
  return new Name(value);
44205
44219
  }
@@ -45146,9 +45160,9 @@ var init_all = __esm({
45146
45160
  });
45147
45161
 
45148
45162
  // ../../node_modules/.pnpm/drizzle-orm@1.0.0-rc.1_@opentelemetry+api@1.9.0_@types+better-sqlite3@7.6.13_better-sql_2010f6373f8103f640f869e889df39c3/node_modules/drizzle-orm/sqlite-core/table.js
45149
- function sqliteTableBase(name5, columns, extraConfig, schema, casing, baseName = name5) {
45163
+ function sqliteTableBase(name5, columns, extraConfig, schema, casing, baseName2 = name5) {
45150
45164
  const casingFn = getCasingFn(casing);
45151
- const rawTable = new SQLiteTable(name5, schema, baseName);
45165
+ const rawTable = new SQLiteTable(name5, schema, baseName2);
45152
45166
  const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders()) : columns;
45153
45167
  const builtColumns = Object.fromEntries(Object.entries(parsedColumns).map(([name6, colBuilderBase]) => {
45154
45168
  const colBuilder = colBuilderBase;
@@ -45743,10 +45757,10 @@ var init_table3 = __esm({
45743
45757
  [IsDrizzleTable2] = true;
45744
45758
  /** @internal */
45745
45759
  [ExtraConfigBuilder2] = void 0;
45746
- constructor(name5, schema, baseName) {
45760
+ constructor(name5, schema, baseName2) {
45747
45761
  this[TableName2] = this[OriginalName2] = name5;
45748
45762
  this[TableSchema2] = schema;
45749
- this[BaseName2] = baseName;
45763
+ this[BaseName2] = baseName2;
45750
45764
  }
45751
45765
  };
45752
45766
  }
@@ -46127,7 +46141,7 @@ var init_sql2 = __esm({
46127
46141
  return new SQL3([new StringChunk2(str3)]);
46128
46142
  }
46129
46143
  _sql.raw = raw;
46130
- function join62(chunks, separator) {
46144
+ function join63(chunks, separator) {
46131
46145
  const result = [];
46132
46146
  for (const [i, chunk] of chunks.entries()) {
46133
46147
  if (i > 0 && separator !== void 0) result.push(separator);
@@ -46135,7 +46149,7 @@ var init_sql2 = __esm({
46135
46149
  }
46136
46150
  return new SQL3(result);
46137
46151
  }
46138
- _sql.join = join62;
46152
+ _sql.join = join63;
46139
46153
  function identifier(value) {
46140
46154
  return new Name2(value);
46141
46155
  }
@@ -49667,9 +49681,9 @@ var init_casing2 = __esm({
49667
49681
  });
49668
49682
 
49669
49683
  // ../../node_modules/.pnpm/drizzle-orm@1.0.0-rc.1_@opentelemetry+api@1.9.0_@types+better-sqlite3@7.6.13_better-sql_95478898f63cc8c3fbbd0c5f8c1e464f/node_modules/drizzle-orm/pg-core/table.js
49670
- function pgTableWithSchema(name5, columns, extraConfig, schema, casing, baseName = name5) {
49684
+ function pgTableWithSchema(name5, columns, extraConfig, schema, casing, baseName2 = name5) {
49671
49685
  const casingFn = getCasingFn2(casing);
49672
- const rawTable = new PgTable(name5, schema, baseName);
49686
+ const rawTable = new PgTable(name5, schema, baseName2);
49673
49687
  const parsedColumns = typeof columns === "function" ? columns(getPgColumnBuilders()) : columns;
49674
49688
  const builtColumns = Object.fromEntries(Object.entries(parsedColumns).map(([name6, colBuilderBase]) => {
49675
49689
  const colBuilder = colBuilderBase;
@@ -51046,9 +51060,9 @@ var init_all3 = __esm({
51046
51060
  });
51047
51061
 
51048
51062
  // ../../node_modules/.pnpm/drizzle-orm@1.0.0-rc.1_@opentelemetry+api@1.9.0_@types+better-sqlite3@7.6.13_better-sql_95478898f63cc8c3fbbd0c5f8c1e464f/node_modules/drizzle-orm/sqlite-core/table.js
51049
- function sqliteTableBase2(name5, columns, extraConfig, schema, casing, baseName = name5) {
51063
+ function sqliteTableBase2(name5, columns, extraConfig, schema, casing, baseName2 = name5) {
51050
51064
  const casingFn = getCasingFn2(casing);
51051
- const rawTable = new SQLiteTable2(name5, schema, baseName);
51065
+ const rawTable = new SQLiteTable2(name5, schema, baseName2);
51052
51066
  const parsedColumns = typeof columns === "function" ? columns(getSQLiteColumnBuilders2()) : columns;
51053
51067
  const builtColumns = Object.fromEntries(Object.entries(parsedColumns).map(([name6, colBuilderBase]) => {
51054
51068
  const colBuilder = colBuilderBase;
@@ -51328,7 +51342,7 @@ var init_select3 = __esm({
51328
51342
  const baseTableName = this.tableName;
51329
51343
  const tableName = getTableLikeName(table);
51330
51344
  for (const item of extractUsedTable(table)) this.usedTables.add(item);
51331
- if (typeof tableName === "string" && this.config.joins?.some((join62) => join62.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
51345
+ if (typeof tableName === "string" && this.config.joins?.some((join63) => join63.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
51332
51346
  if (!this.isPartialSelect) {
51333
51347
  if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
51334
51348
  if (typeof tableName === "string" && !is2(table, SQL3)) {
@@ -52593,7 +52607,7 @@ var init_dialect = __esm({
52593
52607
  if (!joins2) return;
52594
52608
  const withEntries = Object.entries(joins2).filter(([_2, v2]) => v2);
52595
52609
  if (!withEntries.length) return;
52596
- return sql2.join(withEntries.map(([k2, join62]) => {
52610
+ return sql2.join(withEntries.map(([k2, join63]) => {
52597
52611
  const relation = tableConfig.relations[k2];
52598
52612
  const isSingle2 = is2(relation, One);
52599
52613
  const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
@@ -52604,7 +52618,7 @@ var init_dialect = __esm({
52604
52618
  table: targetTable,
52605
52619
  mode: isSingle2 ? "first" : "many",
52606
52620
  schema,
52607
- queryConfig: join62,
52621
+ queryConfig: join63,
52608
52622
  tableConfig: schema[relation.targetTableName],
52609
52623
  relationWhere: filter,
52610
52624
  isNested: true,
@@ -52618,7 +52632,7 @@ var init_dialect = __esm({
52618
52632
  key: k2,
52619
52633
  selection: innerQuery.selection,
52620
52634
  isArray: !isSingle2,
52621
- isOptional: (relation.optional ?? false) || join62 !== true && !!join62.where
52635
+ isOptional: (relation.optional ?? false) || join63 !== true && !!join63.where
52622
52636
  });
52623
52637
  const jsonColumns = sql2.join(innerQuery.selection.map((s2) => {
52624
52638
  return sql2`${sql2.raw(this.escapeString(s2.key))}, ${s2.selection ? sql2`${jsonb2}(${sql2.identifier(s2.key)})` : sql2.identifier(s2.key)}`;
@@ -53137,7 +53151,7 @@ var init_update = __esm({
53137
53151
  createJoin(joinType) {
53138
53152
  return ((table, on) => {
53139
53153
  const tableName = getTableLikeName(table);
53140
- if (typeof tableName === "string" && this.config.joins.some((join62) => join62.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
53154
+ if (typeof tableName === "string" && this.config.joins.some((join63) => join63.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
53141
53155
  if (typeof on === "function") {
53142
53156
  const from = this.config.from ? is2(table, SQLiteTable2) ? table[Table2.Symbol.Columns] : is2(table, Subquery2) ? table._.selectedFields : is2(table, SQLiteViewBase) ? table[ViewBaseConfig2].selectedFields : void 0 : void 0;
53143
53157
  on = on(new Proxy(this.config.table[Table2.Symbol.Columns], new SelectionProxyHandler({
@@ -56294,7 +56308,7 @@ var init_held_agent = __esm({
56294
56308
  });
56295
56309
  if (!record4) return null;
56296
56310
  handle = new _HeldAgentProcess(holder, record4, offsets);
56297
- for (const run3 of pending2) run3();
56311
+ for (const run4 of pending2) run4();
56298
56312
  return handle;
56299
56313
  }
56300
56314
  get pid() {
@@ -56885,7 +56899,7 @@ var init_skills_install = __esm({
56885
56899
  // ../../packages/host-local/src/browser/chromium.ts
56886
56900
  import { spawn as spawn2 } from "node:child_process";
56887
56901
  import { closeSync as closeSync4, existsSync as existsSync10, openSync as openSync4, readdirSync as readdirSync7 } from "node:fs";
56888
- import { mkdir as mkdir2, readFile as readFile2, rm } from "node:fs/promises";
56902
+ import { mkdir as mkdir2, readFile as readFile2, rm, stat as stat3 } from "node:fs/promises";
56889
56903
  import { homedir as homedir11 } from "node:os";
56890
56904
  import { join as join22 } from "node:path";
56891
56905
  function playwrightCandidates() {
@@ -56935,9 +56949,19 @@ function findChromium() {
56935
56949
  ];
56936
56950
  return candidates.find((c) => existsSync10(c));
56937
56951
  }
56952
+ async function fileSize(path2) {
56953
+ try {
56954
+ return (await stat3(path2)).size;
56955
+ } catch {
56956
+ return 0;
56957
+ }
56958
+ }
56938
56959
  async function readDevToolsPort(profileDir, proc, logPath, timeoutMs) {
56939
56960
  const file3 = join22(profileDir, "DevToolsActivePort");
56940
- const deadline = Date.now() + timeoutMs;
56961
+ const startedAt = Date.now();
56962
+ const hardDeadline = startedAt + timeoutMs * PROGRESS_CAP_FACTOR;
56963
+ let deadline = startedAt + timeoutMs;
56964
+ let lastProgress = "";
56941
56965
  while (Date.now() < deadline) {
56942
56966
  if (proc.exitCode !== null || proc.signalCode !== null) {
56943
56967
  throw new Error("Chromium exited before it opened a DevTools port");
@@ -56950,6 +56974,16 @@ async function readDevToolsPort(profileDir, proc, logPath, timeoutMs) {
56950
56974
  if (port && path2) return { port: Number(port), path: path2.trim() };
56951
56975
  } catch {
56952
56976
  }
56977
+ let entries = 0;
56978
+ try {
56979
+ entries = readdirSync7(profileDir).length;
56980
+ } catch {
56981
+ }
56982
+ const progress = `${entries}:${await fileSize(logPath)}`;
56983
+ if (progress !== lastProgress) {
56984
+ lastProgress = progress;
56985
+ deadline = Math.min(Date.now() + timeoutMs, hardDeadline);
56986
+ }
56953
56987
  await sleep(50);
56954
56988
  }
56955
56989
  throw new StartTimeoutError("Chromium did not open a DevTools port in time");
@@ -57016,13 +57050,14 @@ function wrapSocket(ws) {
57016
57050
  }
57017
57051
  };
57018
57052
  }
57019
- var FIRST_ATTEMPT_TIMEOUT_MS, RETRY_TIMEOUT_FRACTION, START_ATTEMPTS, SINGLETON_FILES, PROCESS_GROUP_GONE_TIMEOUT_MS, CLOSE_GRACE_MS, sleep, StartTimeoutError, MAX_QUEUED_BYTES, ChromiumManager;
57053
+ var FIRST_ATTEMPT_TIMEOUT_MS, RETRY_TIMEOUT_FRACTION, START_ATTEMPTS, PROGRESS_CAP_FACTOR, SINGLETON_FILES, PROCESS_GROUP_GONE_TIMEOUT_MS, CLOSE_GRACE_MS, sleep, StartTimeoutError, MAX_QUEUED_BYTES, ChromiumManager;
57020
57054
  var init_chromium = __esm({
57021
57055
  "../../packages/host-local/src/browser/chromium.ts"() {
57022
57056
  "use strict";
57023
57057
  FIRST_ATTEMPT_TIMEOUT_MS = 2e4;
57024
57058
  RETRY_TIMEOUT_FRACTION = 0.6;
57025
57059
  START_ATTEMPTS = 3;
57060
+ PROGRESS_CAP_FACTOR = 3;
57026
57061
  SINGLETON_FILES = ["SingletonLock", "SingletonCookie", "SingletonSocket"];
57027
57062
  PROCESS_GROUP_GONE_TIMEOUT_MS = 5e3;
57028
57063
  CLOSE_GRACE_MS = 4e3;
@@ -57356,7 +57391,7 @@ parentPort.on("message", ({ id, command, args, options }) => {
57356
57391
 
57357
57392
  // ../../packages/host-local/src/git/git-client.ts
57358
57393
  import { execFile as execFile6 } from "node:child_process";
57359
- import { readFile as readFile3, stat as stat3 } from "node:fs/promises";
57394
+ import { readFile as readFile3, stat as stat4 } from "node:fs/promises";
57360
57395
  import { join as join24 } from "node:path";
57361
57396
  function parseGitRemoteUrl(url3) {
57362
57397
  const sshMatch = url3.match(/^[\w.-]+@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
@@ -57387,7 +57422,7 @@ async function resolveDetachedBranch(worktreePath) {
57387
57422
  const dotGit = join24(worktreePath, ".git");
57388
57423
  let gitdir;
57389
57424
  try {
57390
- const st = await stat3(dotGit);
57425
+ const st = await stat4(dotGit);
57391
57426
  if (st.isDirectory()) {
57392
57427
  gitdir = dotGit;
57393
57428
  } else {
@@ -57489,9 +57524,9 @@ async function listWorktrees(repoPath) {
57489
57524
  if (currentPath) await pushCurrent();
57490
57525
  return worktrees2;
57491
57526
  }
57492
- async function getRepoInfo(worktreePath, run3 = execGit) {
57527
+ async function getRepoInfo(worktreePath, run4 = execGit) {
57493
57528
  try {
57494
- const remoteUrl = (await run3(["remote", "get-url", "origin"], worktreePath)).trim();
57529
+ const remoteUrl = (await run4(["remote", "get-url", "origin"], worktreePath)).trim();
57495
57530
  const parsed = parseGitRemoteUrl(remoteUrl);
57496
57531
  if (!parsed) {
57497
57532
  log12.debug('getRepoInfo: failed to parse remote URL "%s" for %s', remoteUrl, worktreePath);
@@ -62407,7 +62442,7 @@ var init_capabilities2 = __esm({
62407
62442
 
62408
62443
  // ../../packages/host-local/src/process/du.ts
62409
62444
  import { execFile as execFile8 } from "node:child_process";
62410
- import { readdir as readdir3, stat as stat4 } from "node:fs/promises";
62445
+ import { readdir as readdir3, stat as stat5 } from "node:fs/promises";
62411
62446
  import { join as join27 } from "node:path";
62412
62447
  async function duBytesNodeWalk(path2) {
62413
62448
  const deadline = Date.now() + DU_TIMEOUT_MS;
@@ -62430,7 +62465,7 @@ async function duBytesNodeWalk(path2) {
62430
62465
  if (Date.now() > deadline) break;
62431
62466
  const sizes = await Promise.all(
62432
62467
  filePaths.slice(i, i + STAT_CHUNK).map(
62433
- (p2) => stat4(p2).then(
62468
+ (p2) => stat5(p2).then(
62434
62469
  (s2) => s2.size,
62435
62470
  () => 0
62436
62471
  // vanished between readdir and stat — count as 0
@@ -62679,7 +62714,7 @@ var init_remote_url = __esm({
62679
62714
  import { execFile as execFile11 } from "node:child_process";
62680
62715
  import { createHash as createHash5, randomBytes as randomBytes4 } from "node:crypto";
62681
62716
  import { existsSync as existsSync11 } from "node:fs";
62682
- import { mkdir as mkdir3, readdir as readdir5, readFile as readFile5, realpath as realpath2, rename as rename2, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
62717
+ import { mkdir as mkdir3, readdir as readdir5, readFile as readFile5, realpath as realpath2, rename as rename2, stat as stat6, writeFile as writeFile2 } from "node:fs/promises";
62683
62718
  import { homedir as homedir13 } from "node:os";
62684
62719
  import { dirname as dirname9, join as join29, sep as sep3 } from "node:path";
62685
62720
  function defaultReposDir() {
@@ -62714,7 +62749,7 @@ function clone2(url3, dest) {
62714
62749
  }
62715
62750
  async function isDirectory(path2) {
62716
62751
  try {
62717
- return (await stat5(path2)).isDirectory();
62752
+ return (await stat6(path2)).isDirectory();
62718
62753
  } catch {
62719
62754
  return false;
62720
62755
  }
@@ -62825,11 +62860,11 @@ var init_host_repos = __esm({
62825
62860
  }
62826
62861
  const running = this.ensuring.get(id.key);
62827
62862
  if (running) return running;
62828
- const run3 = this.doEnsure(id.key, id.url, id.owner, id.name).finally(
62863
+ const run4 = this.doEnsure(id.key, id.url, id.owner, id.name).finally(
62829
62864
  () => this.ensuring.delete(id.key)
62830
62865
  );
62831
- this.ensuring.set(id.key, run3);
62832
- return run3;
62866
+ this.ensuring.set(id.key, run4);
62867
+ return run4;
62833
62868
  }
62834
62869
  async doEnsure(key2, url3, owner, name5) {
62835
62870
  const mappings = await this.load();
@@ -62859,8 +62894,462 @@ var init_host_repos = __esm({
62859
62894
  }
62860
62895
  });
62861
62896
 
62897
+ // ../../packages/host-local/src/resources/classify.ts
62898
+ function baseName(command2) {
62899
+ const first = command2.trim().split(/\s+/)[0] ?? "";
62900
+ const name5 = first.split("/").pop() ?? first;
62901
+ return name5.replace(/^-/, "");
62902
+ }
62903
+ function hasRunDir(command2, runDir) {
62904
+ const tokens2 = command2.split(/\s+/);
62905
+ const at = tokens2.indexOf("--run-dir");
62906
+ return at >= 0 && tokens2[at + 1] === runDir;
62907
+ }
62908
+ function classify(rows, opts) {
62909
+ const children = /* @__PURE__ */ new Map();
62910
+ const byPid = /* @__PURE__ */ new Map();
62911
+ for (const row of rows) {
62912
+ byPid.set(row.pid, row);
62913
+ const list = children.get(row.ppid) ?? [];
62914
+ list.push(row.pid);
62915
+ children.set(row.ppid, list);
62916
+ }
62917
+ const roots = [];
62918
+ const seen = /* @__PURE__ */ new Set();
62919
+ const add = (pid, kind, name5, subtree) => {
62920
+ if (seen.has(pid)) return;
62921
+ seen.add(pid);
62922
+ roots.push({ pid, kind, name: name5, subtree });
62923
+ };
62924
+ if (byPid.has(opts.selfPid))
62925
+ add(opts.selfPid, opts.selfKind, opts.selfKind === "hub" ? "Hub server" : "band-worker", false);
62926
+ for (const row of rows) {
62927
+ if (/terminal-daemon/.test(row.command) && hasRunDir(row.command, opts.runDir)) {
62928
+ add(row.pid, "terminal-daemon", "terminal daemon", false);
62929
+ for (const child of children.get(row.pid) ?? []) {
62930
+ const c = byPid.get(child);
62931
+ if (c) add(child, "terminal", baseName(c.command), true);
62932
+ }
62933
+ } else if (/agent-daemon/.test(row.command) && hasRunDir(row.command, `${opts.runDir}/agents`)) {
62934
+ add(row.pid, "agent-daemon", "agent daemon", false);
62935
+ for (const child of children.get(row.pid) ?? []) {
62936
+ const c = byPid.get(child);
62937
+ if (c) add(child, "agent", agentName(c.command), true);
62938
+ }
62939
+ }
62940
+ }
62941
+ for (const child of children.get(opts.selfPid) ?? []) {
62942
+ const c = byPid.get(child);
62943
+ if (!c || seen.has(child)) continue;
62944
+ const name5 = baseName(c.command);
62945
+ if (SHELLS.has(name5)) add(child, "terminal", name5, true);
62946
+ else if (LSP_NAMES.test(c.command)) add(child, "lsp", lspName(c.command), true);
62947
+ else if (BROWSER.test(c.command)) add(child, "browser", "Chromium", true);
62948
+ else if (SIMULATOR.test(c.command)) add(child, "simulator", "Simulator", true);
62949
+ else if (AGENT_NAMES.test(c.command)) add(child, "agent", agentName(c.command), true);
62950
+ else if (/mcp/i.test(c.command)) add(child, "mcp", name5, true);
62951
+ else if (name5 !== "ps" && name5 !== "lsof" && name5 !== "du" && name5 !== "df")
62952
+ add(child, "other", name5, true);
62953
+ }
62954
+ const subtreeRoots = new Set(roots.filter((r) => r.subtree).map((r) => r.pid));
62955
+ for (const row of rows) {
62956
+ if (seen.has(row.pid)) continue;
62957
+ if (hasAncestorIn(row.pid, subtreeRoots, byPid)) continue;
62958
+ if (LSP_NAMES.test(row.command) && isUnder(row.pid, opts.selfPid, byPid)) {
62959
+ add(row.pid, "lsp", lspName(row.command), true);
62960
+ } else if (BROWSER.test(row.command) && isUnder(row.pid, opts.selfPid, byPid)) {
62961
+ add(row.pid, "browser", "Chromium", true);
62962
+ }
62963
+ }
62964
+ return { roots, children };
62965
+ }
62966
+ function hasAncestorIn(pid, set2, byPid) {
62967
+ let cur = byPid.get(pid)?.ppid;
62968
+ for (let i = 0; cur !== void 0 && i < 64; i++) {
62969
+ if (set2.has(cur)) return true;
62970
+ cur = byPid.get(cur)?.ppid;
62971
+ }
62972
+ return false;
62973
+ }
62974
+ function isUnder(pid, ancestor, byPid) {
62975
+ let cur = byPid.get(pid)?.ppid;
62976
+ for (let i = 0; cur !== void 0 && i < 64; i++) {
62977
+ if (cur === ancestor) return true;
62978
+ cur = byPid.get(cur)?.ppid;
62979
+ }
62980
+ return false;
62981
+ }
62982
+ function lspName(command2) {
62983
+ return LSP_NAMES.exec(command2)?.[1] ?? "language server";
62984
+ }
62985
+ function agentName(command2) {
62986
+ if (/claude/i.test(command2)) return "Claude Code";
62987
+ if (/codex/i.test(command2)) return "Codex";
62988
+ if (/gemini/i.test(command2)) return "Gemini";
62989
+ if (/opencode/i.test(command2)) return "OpenCode";
62990
+ if (/cursor/i.test(command2)) return "Cursor";
62991
+ return baseName(command2);
62992
+ }
62993
+ function subtreeOf(root, children) {
62994
+ const out = [];
62995
+ const stack = [root];
62996
+ while (stack.length > 0 && out.length < 5e3) {
62997
+ const pid = stack.pop();
62998
+ out.push(pid);
62999
+ for (const c of children.get(pid) ?? []) stack.push(c);
63000
+ }
63001
+ return out;
63002
+ }
63003
+ function sumRoots(classified, first, second, windowMs) {
63004
+ const out = [];
63005
+ for (const root of classified.roots) {
63006
+ const pids = root.subtree ? subtreeOf(root.pid, classified.children) : [root.pid];
63007
+ let rss = 0;
63008
+ let cpuMs = 0;
63009
+ let count3 = 0;
63010
+ for (const pid of pids) {
63011
+ const b2 = second.get(pid);
63012
+ if (!b2) continue;
63013
+ count3++;
63014
+ rss += b2.rssBytes;
63015
+ const a = first.get(pid);
63016
+ cpuMs += Math.max(0, a ? b2.cpuMs - a.cpuMs : b2.cpuMs);
63017
+ }
63018
+ const self = second.get(root.pid);
63019
+ if (!self) continue;
63020
+ out.push({
63021
+ pid: root.pid,
63022
+ kind: root.kind,
63023
+ name: root.name,
63024
+ command: self.command.slice(0, 200),
63025
+ rssBytes: rss,
63026
+ cpuPercent: windowMs > 0 ? Math.round(cpuMs / windowMs * 1e3) / 10 : 0,
63027
+ processCount: count3
63028
+ });
63029
+ }
63030
+ return out;
63031
+ }
63032
+ var SHELLS, LSP_NAMES, AGENT_NAMES, BROWSER, SIMULATOR;
63033
+ var init_classify = __esm({
63034
+ "../../packages/host-local/src/resources/classify.ts"() {
63035
+ "use strict";
63036
+ SHELLS = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "fish", "dash", "ksh", "tcsh", "csh", "nu", "pwsh"]);
63037
+ LSP_NAMES = /(typescript-language-server|tsserver|rust-analyzer|gopls|pyright|basedpyright|jdtls|clangd|lua-language-server|vscode-[a-z]+-language-server|yaml-language-server)/;
63038
+ AGENT_NAMES = /(claude-agent-acp|claude-code-acp|codex-acp|gemini|opencode|cursor-agent|-acp\b)/;
63039
+ BROWSER = /(chrom(e|ium)|headless_shell).*--remote-debugging-port/i;
63040
+ SIMULATOR = /(serve-sim|simctl|Simulator\.app|CoreSimulator)/;
63041
+ }
63042
+ });
63043
+
63044
+ // ../../packages/host-local/src/resources/process-table.ts
63045
+ import { execFile as execFile12 } from "node:child_process";
63046
+ import { readdir as readdir6, readFile as readFile6 } from "node:fs/promises";
63047
+ function run3(bin, args) {
63048
+ return new Promise((resolve16) => {
63049
+ execFile12(
63050
+ bin,
63051
+ args,
63052
+ { timeout: PS_TIMEOUT_MS, maxBuffer: PS_MAX_BUFFER },
63053
+ (_err, out) => resolve16(out ?? "")
63054
+ );
63055
+ });
63056
+ }
63057
+ function parsePsTime(text4) {
63058
+ const m2 = /^(?:(\d+)-)?(?:(\d+):)?(\d+):(\d+(?:\.\d+)?)$/.exec(text4.trim());
63059
+ if (!m2) return 0;
63060
+ const days = Number(m2[1] ?? 0);
63061
+ const hours = Number(m2[2] ?? 0);
63062
+ const minutes = Number(m2[3]);
63063
+ const seconds = Number(m2[4]);
63064
+ return Math.round((((days * 24 + hours) * 60 + minutes) * 60 + seconds) * 1e3);
63065
+ }
63066
+ function parsePs(output2) {
63067
+ const rows = [];
63068
+ for (const line2 of output2.split("\n")) {
63069
+ const m2 = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(.*)$/.exec(line2);
63070
+ if (!m2) continue;
63071
+ rows.push({
63072
+ pid: Number(m2[1]),
63073
+ ppid: Number(m2[2]),
63074
+ rssBytes: Number(m2[3]) * 1024,
63075
+ cpuMs: parsePsTime(m2[4]),
63076
+ command: m2[5].trim()
63077
+ });
63078
+ }
63079
+ return rows;
63080
+ }
63081
+ function parseProcStat(stat9) {
63082
+ const close = stat9.lastIndexOf(")");
63083
+ if (close < 0) return null;
63084
+ const fields = stat9.slice(close + 2).trim().split(/\s+/);
63085
+ const ppid = Number(fields[1]);
63086
+ const utime = Number(fields[11]);
63087
+ const stime = Number(fields[12]);
63088
+ const rss = Number(fields[21]);
63089
+ if (![ppid, utime, stime, rss].every(Number.isFinite)) return null;
63090
+ return { ppid, cpuMs: (utime + stime) * 1e3 / CLK_TCK, rssPages: rss };
63091
+ }
63092
+ async function readLinux() {
63093
+ let names;
63094
+ try {
63095
+ names = await readdir6("/proc");
63096
+ } catch {
63097
+ return [];
63098
+ }
63099
+ const rows = await Promise.all(
63100
+ names.filter((n) => /^\d+$/.test(n)).map(async (n) => {
63101
+ try {
63102
+ const [stat9, cmd] = await Promise.all([
63103
+ readFile6(`/proc/${n}/stat`, "utf8"),
63104
+ readFile6(`/proc/${n}/cmdline`, "utf8").catch(() => "")
63105
+ ]);
63106
+ const parsed = parseProcStat(stat9);
63107
+ if (!parsed) return null;
63108
+ const comm = /\((.*)\)/s.exec(stat9)?.[1] ?? "";
63109
+ return {
63110
+ pid: Number(n),
63111
+ ppid: parsed.ppid,
63112
+ rssBytes: parsed.rssPages * PAGE_SIZE,
63113
+ cpuMs: parsed.cpuMs,
63114
+ command: cmd.replace(/\0/g, " ").trim() || comm
63115
+ };
63116
+ } catch {
63117
+ return null;
63118
+ }
63119
+ })
63120
+ );
63121
+ return rows.filter((r) => r !== null);
63122
+ }
63123
+ async function readProcessTable() {
63124
+ if (process.platform === "linux") {
63125
+ const rows = await readLinux();
63126
+ if (rows.length > 0) return rows;
63127
+ }
63128
+ if (process.platform === "win32") return [];
63129
+ return parsePs(await run3("ps", ["-axww", "-o", "pid=,ppid=,rss=,time=,command="]));
63130
+ }
63131
+ async function readProcessEnv(pid, names) {
63132
+ const out = {};
63133
+ let text4 = "";
63134
+ if (process.platform === "linux") {
63135
+ text4 = (await readFile6(`/proc/${pid}/environ`, "utf8").catch(() => "")).replace(/\0/g, " ");
63136
+ } else if (process.platform === "darwin") {
63137
+ text4 = await run3("ps", ["-E", "-ww", "-o", "command=", "-p", String(pid)]);
63138
+ }
63139
+ for (const name5 of names) {
63140
+ const m2 = new RegExp(`(?:^|\\s)${name5}=(\\S+)`).exec(text4);
63141
+ if (m2) out[name5] = m2[1];
63142
+ }
63143
+ return out;
63144
+ }
63145
+ async function readProcessCwds(pids) {
63146
+ const out = /* @__PURE__ */ new Map();
63147
+ if (pids.length === 0) return out;
63148
+ if (process.platform === "linux") {
63149
+ const { readlink } = await import("node:fs/promises");
63150
+ await Promise.all(
63151
+ pids.map(async (pid) => {
63152
+ try {
63153
+ out.set(pid, await readlink(`/proc/${pid}/cwd`));
63154
+ } catch {
63155
+ }
63156
+ })
63157
+ );
63158
+ return out;
63159
+ }
63160
+ if (process.platform === "darwin") {
63161
+ const text4 = await run3("lsof", ["-a", "-d", "cwd", "-Fpn", "-p", pids.join(",")]);
63162
+ let current3 = 0;
63163
+ for (const line2 of text4.split("\n")) {
63164
+ if (line2.startsWith("p")) current3 = Number(line2.slice(1));
63165
+ else if (line2.startsWith("n") && current3) out.set(current3, line2.slice(1));
63166
+ }
63167
+ }
63168
+ return out;
63169
+ }
63170
+ var PS_TIMEOUT_MS, PS_MAX_BUFFER, CLK_TCK, PAGE_SIZE;
63171
+ var init_process_table = __esm({
63172
+ "../../packages/host-local/src/resources/process-table.ts"() {
63173
+ "use strict";
63174
+ PS_TIMEOUT_MS = 5e3;
63175
+ PS_MAX_BUFFER = 64 * 1024 * 1024;
63176
+ CLK_TCK = 100;
63177
+ PAGE_SIZE = 4096;
63178
+ }
63179
+ });
63180
+
63181
+ // ../../packages/host-local/src/resources/resources.ts
63182
+ import { execFile as execFile13 } from "node:child_process";
63183
+ import { readdir as readdir7, readFile as readFile7 } from "node:fs/promises";
63184
+ import { cpus, freemem, hostname as hostname4, loadavg, totalmem } from "node:os";
63185
+ import { join as join30 } from "node:path";
63186
+ function execOut(bin, args) {
63187
+ return new Promise((resolve16) => {
63188
+ execFile13(bin, args, { timeout: 5e3 }, (_e, out) => resolve16(out ?? ""));
63189
+ });
63190
+ }
63191
+ async function memoryUsedBytes(total) {
63192
+ if (process.platform === "linux") {
63193
+ const meminfo = await readFile7("/proc/meminfo", "utf8").catch(() => "");
63194
+ const m2 = /MemAvailable:\s+(\d+) kB/.exec(meminfo);
63195
+ if (m2) return Math.max(0, total - Number(m2[1]) * 1024);
63196
+ }
63197
+ if (process.platform === "darwin") {
63198
+ const out = await execOut("vm_stat", []);
63199
+ const page = Number(/page size of (\d+) bytes/.exec(out)?.[1] ?? 16384);
63200
+ const pages = (label2) => Number(new RegExp(`${label2}:\\s+(\\d+)`).exec(out)?.[1] ?? 0);
63201
+ const reclaimable = pages("Pages free") + pages("Pages inactive") + pages("Pages speculative");
63202
+ if (reclaimable > 0) return Math.max(0, total - reclaimable * page);
63203
+ }
63204
+ return Math.max(0, total - freemem());
63205
+ }
63206
+ function cpuTimes() {
63207
+ let busy = 0;
63208
+ let total = 0;
63209
+ for (const c of cpus()) {
63210
+ const t2 = c.times;
63211
+ total += t2.user + t2.nice + t2.sys + t2.idle + t2.irq;
63212
+ busy += t2.user + t2.nice + t2.sys + t2.irq;
63213
+ }
63214
+ return { busy, total };
63215
+ }
63216
+ async function diskOf(path2) {
63217
+ const out = await execOut("df", ["-k", path2]);
63218
+ const line2 = out.trim().split("\n").pop();
63219
+ const f2 = line2?.trim().split(/\s+/);
63220
+ if (!f2 || f2.length < 4) return null;
63221
+ const total = Number(f2[1]);
63222
+ const free = Number(f2[3]);
63223
+ if (!Number.isFinite(total) || !Number.isFinite(free)) return null;
63224
+ return { path: path2, totalBytes: total * 1024, freeBytes: free * 1024 };
63225
+ }
63226
+ async function limited(items, limit, fn) {
63227
+ const results = new Array(items.length);
63228
+ let next = 0;
63229
+ await Promise.all(
63230
+ Array.from({ length: Math.min(limit, items.length) }, async () => {
63231
+ while (next < items.length) {
63232
+ const i = next++;
63233
+ results[i] = await fn(items[i]);
63234
+ }
63235
+ })
63236
+ );
63237
+ return results;
63238
+ }
63239
+ var SAMPLE_WINDOW_MS, CACHE_MS, DU_CONCURRENCY, ENV_NAMES, LocalResources;
63240
+ var init_resources2 = __esm({
63241
+ "../../packages/host-local/src/resources/resources.ts"() {
63242
+ "use strict";
63243
+ init_du();
63244
+ init_classify();
63245
+ init_process_table();
63246
+ SAMPLE_WINDOW_MS = 500;
63247
+ CACHE_MS = 3e3;
63248
+ DU_CONCURRENCY = 3;
63249
+ ENV_NAMES = ["BAND_WORKTREE_ID", "BAND_CHAT_ID", "BAND_TERMINAL_ID"];
63250
+ LocalResources = class {
63251
+ constructor(options) {
63252
+ this.options = options;
63253
+ }
63254
+ cached = null;
63255
+ snapshot() {
63256
+ const now = Date.now();
63257
+ if (this.cached && now - this.cached.at < CACHE_MS) return this.cached.value;
63258
+ const value = this.sample();
63259
+ this.cached = { at: now, value };
63260
+ value.catch(() => {
63261
+ if (this.cached?.value === value) this.cached = null;
63262
+ });
63263
+ return value;
63264
+ }
63265
+ async sample() {
63266
+ const stateDir = this.options.stateDir();
63267
+ const cpu1 = cpuTimes();
63268
+ const started = Date.now();
63269
+ const firstRows = await readProcessTable();
63270
+ await new Promise((r) => setTimeout(r, SAMPLE_WINDOW_MS));
63271
+ const secondRows = await readProcessTable();
63272
+ const windowMs = Date.now() - started;
63273
+ const cpu2 = cpuTimes();
63274
+ const first = new Map(firstRows.map((r) => [r.pid, r]));
63275
+ const second = new Map(secondRows.map((r) => [r.pid, r]));
63276
+ const classified = classify(secondRows, {
63277
+ selfPid: process.pid,
63278
+ selfKind: this.options.selfKind,
63279
+ runDir: join30(stateDir, "run")
63280
+ });
63281
+ const processes = sumRoots(classified, first, second, windowMs);
63282
+ await this.attachIds(processes);
63283
+ const total = totalmem();
63284
+ const totalDelta = cpu2.total - cpu1.total;
63285
+ return {
63286
+ hostname: hostname4(),
63287
+ os: process.platform,
63288
+ cores: cpus().length,
63289
+ memTotalBytes: total,
63290
+ memUsedBytes: await memoryUsedBytes(total),
63291
+ machineCpuPercent: totalDelta > 0 ? Math.round((cpu2.busy - cpu1.busy) / totalDelta * 1e3) / 10 : null,
63292
+ loadAverage: loadavg()[0],
63293
+ windowMs,
63294
+ takenAt: Date.now(),
63295
+ processes
63296
+ };
63297
+ }
63298
+ /** Reads the ids a terminal or agent was started with, and its folder. */
63299
+ async attachIds(processes) {
63300
+ const wanted = processes.filter(
63301
+ (p2) => p2.kind === "terminal" || p2.kind === "agent" || p2.kind === "lsp" || p2.kind === "browser"
63302
+ );
63303
+ const cwds = await readProcessCwds(wanted.map((p2) => p2.pid));
63304
+ await limited(wanted, 6, async (p2) => {
63305
+ const cwd = cwds.get(p2.pid);
63306
+ if (cwd) p2.cwd = cwd;
63307
+ if (p2.kind !== "terminal" && p2.kind !== "agent") return;
63308
+ const env = await readProcessEnv(p2.pid, ENV_NAMES);
63309
+ if (env.BAND_WORKTREE_ID) p2.worktreeId = env.BAND_WORKTREE_ID;
63310
+ if (env.BAND_CHAT_ID) p2.chatId = env.BAND_CHAT_ID;
63311
+ if (env.BAND_TERMINAL_ID) p2.terminalId = env.BAND_TERMINAL_ID;
63312
+ });
63313
+ }
63314
+ /** Calls with the same worktrees share one run, so a repeated refresh does not stack `du` passes. */
63315
+ storageRuns = /* @__PURE__ */ new Map();
63316
+ storage(request) {
63317
+ const key2 = JSON.stringify(request.worktrees);
63318
+ const running = this.storageRuns.get(key2);
63319
+ if (running) return running;
63320
+ const run4 = this.measureStorage(request);
63321
+ this.storageRuns.set(key2, run4);
63322
+ const done = () => this.storageRuns.delete(key2);
63323
+ run4.then(done, done);
63324
+ return run4;
63325
+ }
63326
+ async measureStorage(request) {
63327
+ const stateDir = this.options.stateDir();
63328
+ const worktrees2 = await limited(request.worktrees, DU_CONCURRENCY, async (wt) => {
63329
+ try {
63330
+ return { id: wt.id, sizeBytes: await duBytes(wt.path) };
63331
+ } catch (err) {
63332
+ return {
63333
+ id: wt.id,
63334
+ sizeBytes: 0,
63335
+ error: err instanceof Error ? err.message : String(err)
63336
+ };
63337
+ }
63338
+ });
63339
+ const names = await readdir7(stateDir).catch(() => []);
63340
+ const state2 = await limited(names, DU_CONCURRENCY, async (name5) => ({
63341
+ name: name5,
63342
+ sizeBytes: await duBytes(join30(stateDir, name5)).catch(() => 0)
63343
+ }));
63344
+ state2.sort((a, b2) => b2.sizeBytes - a.sizeBytes);
63345
+ return { worktrees: worktrees2, state: state2, disk: await diskOf(stateDir) };
63346
+ }
63347
+ };
63348
+ }
63349
+ });
63350
+
62862
63351
  // ../../packages/host-local/src/search/ripgrep-client.ts
62863
- import { execFile as execFile12, spawn as spawn4 } from "node:child_process";
63352
+ import { execFile as execFile14, spawn as spawn4 } from "node:child_process";
62864
63353
  import { rgPath } from "@vscode/ripgrep";
62865
63354
  function streamMatches(options) {
62866
63355
  return {
@@ -62981,7 +63470,7 @@ function listFiles(cwd) {
62981
63470
  "!**/.DS_Store"
62982
63471
  ];
62983
63472
  return new Promise((resolve16, reject) => {
62984
- execFile12(
63473
+ execFile14(
62985
63474
  rgPath,
62986
63475
  args,
62987
63476
  { cwd, maxBuffer: LIST_FILES_MAX_BUFFER, encoding: "utf-8" },
@@ -63005,10 +63494,10 @@ var init_ripgrep_client = __esm({
63005
63494
  });
63006
63495
 
63007
63496
  // ../../packages/host-local/src/setup/repo-config.ts
63008
- import { join as join30 } from "node:path";
63497
+ import { join as join31 } from "node:path";
63009
63498
  async function loadRepoConfig(host, worktreePath, repoPath) {
63010
63499
  for (const base of [worktreePath, repoPath]) {
63011
- const text4 = await readConfig(host, join30(base, ".band", "config.json"));
63500
+ const text4 = await readConfig(host, join31(base, ".band", "config.json"));
63012
63501
  if (text4 === null) continue;
63013
63502
  try {
63014
63503
  return JSON.parse(text4);
@@ -63019,10 +63508,10 @@ async function loadRepoConfig(host, worktreePath, repoPath) {
63019
63508
  }
63020
63509
  async function loadEnvironment(host, worktreePath, repoPath) {
63021
63510
  for (const base of [worktreePath, repoPath]) {
63022
- const file3 = join30(base, ENVIRONMENT_FILE);
63511
+ const file3 = join31(base, ENVIRONMENT_FILE);
63023
63512
  const text4 = await readConfig(host, file3);
63024
63513
  if (text4 === null) continue;
63025
- const exists4 = (relative2) => host.fs.stat(join30(base, relative2)).then(
63514
+ const exists4 = (relative2) => host.fs.stat(join31(base, relative2)).then(
63026
63515
  () => true,
63027
63516
  () => false
63028
63517
  );
@@ -63053,7 +63542,7 @@ async function readConfig(host, configPath) {
63053
63542
  }
63054
63543
  }
63055
63544
  async function getCopyFiles(host, repoPath) {
63056
- const configPath = join30(repoPath, ".band", "config.json");
63545
+ const configPath = join31(repoPath, ".band", "config.json");
63057
63546
  const text4 = await readConfig(host, configPath);
63058
63547
  if (text4 === null) return null;
63059
63548
  let raw;
@@ -63088,14 +63577,14 @@ var init_repo_config = __esm({
63088
63577
  });
63089
63578
 
63090
63579
  // ../../packages/host-local/src/setup/script-run.ts
63091
- import { join as join31 } from "node:path";
63580
+ import { join as join32 } from "node:path";
63092
63581
  function quote(value) {
63093
63582
  return `'${value.replace(/'/g, `'\\''`)}'`;
63094
63583
  }
63095
63584
  async function prepareScriptRun(host, script, label2) {
63096
63585
  const dir = await host.fs.mkdtemp("band-script-");
63097
- const scriptFile = join31(dir, `${label2}.sh`);
63098
- const exitFile = join31(dir, "exit-code");
63586
+ const scriptFile = join32(dir, `${label2}.sh`);
63587
+ const exitFile = join32(dir, "exit-code");
63099
63588
  const partialFile = `${exitFile}.partial`;
63100
63589
  const onExit = [
63101
63590
  "rc=$?",
@@ -63164,7 +63653,7 @@ var init_script_run = __esm({
63164
63653
  });
63165
63654
 
63166
63655
  // ../../packages/host-local/src/setup/worktree-files.ts
63167
- import { dirname as dirname10, isAbsolute, join as join32, relative, resolve as resolve6, sep as sep4 } from "node:path";
63656
+ import { dirname as dirname10, isAbsolute, join as join33, relative, resolve as resolve6, sep as sep4 } from "node:path";
63168
63657
  async function copyWorktreeFiles(host, repoPath, worktreePath) {
63169
63658
  const byAbs = /* @__PURE__ */ new Map();
63170
63659
  const missingFromConfig = [];
@@ -63192,7 +63681,7 @@ async function copyWorktreeFiles(host, repoPath, worktreePath) {
63192
63681
  }
63193
63682
  for (const [absSource, source] of byAbs) {
63194
63683
  const rel = relative(repoPath, absSource);
63195
- const dest = join32(worktreePath, rel);
63684
+ const dest = join33(worktreePath, rel);
63196
63685
  if (rel.startsWith("..") || isAbsolute(rel)) {
63197
63686
  log16.warn({ source, entry: absSource }, "refusing to copy file outside repo root \u2014 skipping");
63198
63687
  continue;
@@ -63281,7 +63770,7 @@ async function resolveFromConfig(host, repoPath, missing) {
63281
63770
  return out;
63282
63771
  }
63283
63772
  async function resolveFromWorktreeInclude(host, repoPath) {
63284
- const includePath = join32(repoPath, ".worktreeinclude");
63773
+ const includePath = join33(repoPath, ".worktreeinclude");
63285
63774
  let includeContent;
63286
63775
  try {
63287
63776
  includeContent = new TextDecoder().decode(await host.fs.readFile(includePath));
@@ -63399,11 +63888,11 @@ var init_common4 = __esm({
63399
63888
  });
63400
63889
 
63401
63890
  // ../../packages/host-local/src/usage/claude-usage.ts
63402
- import { execFile as execFile13 } from "node:child_process";
63891
+ import { execFile as execFile15 } from "node:child_process";
63403
63892
  import { createHash as createHash6 } from "node:crypto";
63404
- import { readFile as readFile6 } from "node:fs/promises";
63893
+ import { readFile as readFile8 } from "node:fs/promises";
63405
63894
  import { homedir as homedir14, userInfo } from "node:os";
63406
- import { join as join33 } from "node:path";
63895
+ import { join as join34 } from "node:path";
63407
63896
  function windowOf(label2, raw) {
63408
63897
  if (!raw || typeof raw !== "object") return null;
63409
63898
  const percent = percentOf(raw.utilization ?? raw.used_percentage);
@@ -63423,7 +63912,7 @@ function mapClaudeUsage(data) {
63423
63912
  );
63424
63913
  }
63425
63914
  function claudeConfigDir3() {
63426
- return process.env.CLAUDE_CONFIG_DIR || join33(homedir14(), ".claude");
63915
+ return process.env.CLAUDE_CONFIG_DIR || join34(homedir14(), ".claude");
63427
63916
  }
63428
63917
  function parseCredentials(raw) {
63429
63918
  try {
@@ -63438,7 +63927,7 @@ function parseCredentials(raw) {
63438
63927
  }
63439
63928
  function keychainPassword(service) {
63440
63929
  return new Promise((resolve16) => {
63441
- execFile13(
63930
+ execFile15(
63442
63931
  "security",
63443
63932
  ["find-generic-password", "-s", service, "-a", userInfo().username, "-w"],
63444
63933
  { timeout: KEYCHAIN_TIMEOUT_MS },
@@ -63449,7 +63938,7 @@ function keychainPassword(service) {
63449
63938
  async function readLogin() {
63450
63939
  const dir = claudeConfigDir3();
63451
63940
  try {
63452
- const fromFile = parseCredentials(await readFile6(join33(dir, ".credentials.json"), "utf8"));
63941
+ const fromFile = parseCredentials(await readFile8(join34(dir, ".credentials.json"), "utf8"));
63453
63942
  if (fromFile) return fromFile;
63454
63943
  } catch {
63455
63944
  }
@@ -63459,9 +63948,9 @@ async function readLogin() {
63459
63948
  return raw ? parseCredentials(raw) : null;
63460
63949
  }
63461
63950
  async function readIdentity() {
63462
- const file3 = process.env.CLAUDE_CONFIG_DIR ? join33(process.env.CLAUDE_CONFIG_DIR, ".claude.json") : join33(homedir14(), ".claude.json");
63951
+ const file3 = process.env.CLAUDE_CONFIG_DIR ? join34(process.env.CLAUDE_CONFIG_DIR, ".claude.json") : join34(homedir14(), ".claude.json");
63463
63952
  try {
63464
- const account = JSON.parse(await readFile6(file3, "utf8")).oauthAccount;
63953
+ const account = JSON.parse(await readFile8(file3, "utf8")).oauthAccount;
63465
63954
  const email4 = account?.emailAddress;
63466
63955
  if (typeof email4 === "string" && email4) return email4;
63467
63956
  const id = account?.accountUuid;
@@ -63502,9 +63991,9 @@ var init_claude_usage = __esm({
63502
63991
  });
63503
63992
 
63504
63993
  // ../../packages/host-local/src/usage/codex-usage.ts
63505
- import { readFile as readFile7 } from "node:fs/promises";
63994
+ import { readFile as readFile9 } from "node:fs/promises";
63506
63995
  import { homedir as homedir15 } from "node:os";
63507
- import { join as join34 } from "node:path";
63996
+ import { join as join35 } from "node:path";
63508
63997
  function labelFor(raw, fallback) {
63509
63998
  const seconds = raw.limit_window_seconds;
63510
63999
  if (typeof seconds === "number" && Number.isFinite(seconds) && seconds > 0) {
@@ -63538,9 +64027,9 @@ function emailOfIdToken(idToken) {
63538
64027
  }
63539
64028
  }
63540
64029
  async function readLogin2() {
63541
- const home = process.env.CODEX_HOME || join34(homedir15(), ".codex");
64030
+ const home = process.env.CODEX_HOME || join35(homedir15(), ".codex");
63542
64031
  try {
63543
- const auth2 = JSON.parse(await readFile7(join34(home, "auth.json"), "utf8"));
64032
+ const auth2 = JSON.parse(await readFile9(join35(home, "auth.json"), "utf8"));
63544
64033
  const token = auth2.tokens?.access_token;
63545
64034
  if (typeof token !== "string" || token === "") return null;
63546
64035
  const accountId = auth2.tokens?.account_id;
@@ -63645,7 +64134,7 @@ var init_account_usage = __esm({
63645
64134
  });
63646
64135
 
63647
64136
  // ../../packages/host-local/src/local-host.ts
63648
- import { execFile as execFile14, spawn as spawn5 } from "node:child_process";
64137
+ import { execFile as execFile16, spawn as spawn5 } from "node:child_process";
63649
64138
  import { createReadStream as createReadStream3, watch as fsWatch } from "node:fs";
63650
64139
  import {
63651
64140
  cp,
@@ -63653,16 +64142,16 @@ import {
63653
64142
  lstat,
63654
64143
  mkdir as mkdir4,
63655
64144
  mkdtemp,
63656
- readdir as readdir6,
63657
- readFile as readFile8,
64145
+ readdir as readdir8,
64146
+ readFile as readFile10,
63658
64147
  realpath as realpath3,
63659
64148
  rename as rename3,
63660
64149
  rm as rm2,
63661
- stat as stat6,
64150
+ stat as stat7,
63662
64151
  writeFile as writeFile3
63663
64152
  } from "node:fs/promises";
63664
- import { homedir as homedir16, hostname as hostname4, tmpdir as tmpdir2 } from "node:os";
63665
- import { join as join35 } from "node:path";
64153
+ import { homedir as homedir16, hostname as hostname5, tmpdir as tmpdir2 } from "node:os";
64154
+ import { join as join36 } from "node:path";
63666
64155
  async function createWorktree(spec) {
63667
64156
  const refs = await execGit(
63668
64157
  ["for-each-ref", "--format=%(refname)", "refs/heads", "refs/remotes/origin"],
@@ -63815,6 +64304,7 @@ var init_local_host = __esm({
63815
64304
  init_power();
63816
64305
  init_tools();
63817
64306
  init_host_repos();
64307
+ init_resources2();
63818
64308
  init_ripgrep_client();
63819
64309
  init_repo_config();
63820
64310
  init_script_run();
@@ -63829,11 +64319,15 @@ var init_local_host = __esm({
63829
64319
  LocalHost = class {
63830
64320
  constructor(options) {
63831
64321
  this.options = options;
63832
- const bandHome2 = () => process.env.BAND_HOME ?? join35(homedir16(), ".band");
64322
+ const bandHome2 = () => process.env.BAND_HOME ?? join36(homedir16(), ".band");
63833
64323
  this.repos = new LocalRepos({
63834
- mappingsFile: options.repos?.mappingsFile ?? (() => join35(bandHome2(), "repo-mappings.json")),
64324
+ mappingsFile: options.repos?.mappingsFile ?? (() => join36(bandHome2(), "repo-mappings.json")),
63835
64325
  reposDir: options.repos?.reposDir ?? defaultReposDir
63836
64326
  });
64327
+ this.resources = new LocalResources({
64328
+ selfKind: options.resources?.selfKind ?? "worker",
64329
+ stateDir: options.resources?.stateDir ?? bandHome2
64330
+ });
63837
64331
  void this.toolVersions();
63838
64332
  }
63839
64333
  id = LOCAL_HOST_ID;
@@ -63870,7 +64364,7 @@ var init_local_host = __esm({
63870
64364
  openStdio: (spec) => openMcpStdio(spec)
63871
64365
  };
63872
64366
  chromium = new ChromiumManager(
63873
- () => join35(process.env.BAND_HOME ?? join35(homedir16(), ".band"), "browser-profiles")
64367
+ () => join36(process.env.BAND_HOME ?? join36(homedir16(), ".band"), "browser-profiles")
63874
64368
  );
63875
64369
  browser = {
63876
64370
  open: (spec) => this.chromium.open(spec),
@@ -63879,6 +64373,7 @@ var init_local_host = __esm({
63879
64373
  };
63880
64374
  desktop = { open: () => openDesktop() };
63881
64375
  speech = { transcribe: (req) => transcribeLocally(req) };
64376
+ resources;
63882
64377
  scripts = {
63883
64378
  command: (worktree) => scriptCommand(this, worktree),
63884
64379
  runHidden: (script, cwd, timeoutMs) => runScriptHidden(script, cwd, timeoutMs),
@@ -64018,7 +64513,7 @@ var init_local_host = __esm({
64018
64513
  id: this.id,
64019
64514
  os: process.platform,
64020
64515
  arch: process.arch,
64021
- hostname: hostname4(),
64516
+ hostname: hostname5(),
64022
64517
  home: homedir16(),
64023
64518
  labels: [],
64024
64519
  roots: [],
@@ -64043,7 +64538,7 @@ var init_local_host = __esm({
64043
64538
  return new Promise((resolve16, reject) => {
64044
64539
  const env = { ...process.env, ...options.env };
64045
64540
  env.PATH = prependBinDirs(env.PATH);
64046
- execFile14(
64541
+ execFile16(
64047
64542
  bin,
64048
64543
  args,
64049
64544
  { cwd: options.cwd, env, maxBuffer: EXEC_MAX_BUFFER, timeout: options.timeoutMs },
@@ -64060,11 +64555,11 @@ var init_local_host = __esm({
64060
64555
  };
64061
64556
  localFs = {
64062
64557
  async stat(path2, options) {
64063
- const stats = options?.followSymlinks ? await stat6(path2) : await lstat(path2);
64558
+ const stats = options?.followSymlinks ? await stat7(path2) : await lstat(path2);
64064
64559
  return { kind: kindOf(stats), size: stats.size, mtimeMs: stats.mtimeMs };
64065
64560
  },
64066
64561
  async readFile(path2) {
64067
- return new Uint8Array(await readFile8(path2));
64562
+ return new Uint8Array(await readFile10(path2));
64068
64563
  },
64069
64564
  realpath: (path2) => realpath3(path2),
64070
64565
  async *readStream(path2, range) {
@@ -64082,9 +64577,9 @@ var init_local_host = __esm({
64082
64577
  for await (const match of fsGlob(pattern, { cwd })) matches2.push(match);
64083
64578
  return matches2;
64084
64579
  },
64085
- mkdtemp: (prefix) => mkdtemp(join35(tmpdir2(), prefix)),
64580
+ mkdtemp: (prefix) => mkdtemp(join36(tmpdir2(), prefix)),
64086
64581
  async list(path2) {
64087
- const entries = await readdir6(path2, { withFileTypes: true });
64582
+ const entries = await readdir8(path2, { withFileTypes: true });
64088
64583
  return entries.map((entry) => ({ name: entry.name, kind: kindOf(entry) }));
64089
64584
  },
64090
64585
  async mkdir(path2, options) {
@@ -64124,10 +64619,10 @@ var init_drizzle_orm2 = __esm({
64124
64619
 
64125
64620
  // src/server/infra/db/queries/repos.ts
64126
64621
  import { existsSync as existsSync12 } from "node:fs";
64127
- import { join as join36 } from "node:path";
64622
+ import { join as join37 } from "node:path";
64128
64623
  function reconcileKindForRepo(repo) {
64129
64624
  if (!repo.path || !existsSync12(repo.path)) return false;
64130
- const detectedKind = existsSync12(join36(repo.path, ".git")) ? "git" : "plain";
64625
+ const detectedKind = existsSync12(join37(repo.path, ".git")) ? "git" : "plain";
64131
64626
  if (detectedKind === repo.kind) return false;
64132
64627
  repo.kind = detectedKind;
64133
64628
  if (detectedKind === "plain") {
@@ -64889,7 +65384,7 @@ var init_isolation = __esm({
64889
65384
 
64890
65385
  // src/server/services/_utils/runner-config.ts
64891
65386
  import { existsSync as existsSync13 } from "node:fs";
64892
- import { dirname as dirname11, isAbsolute as isAbsolute2, join as join37, resolve as resolve7 } from "node:path";
65387
+ import { dirname as dirname11, isAbsolute as isAbsolute2, join as join38, resolve as resolve7 } from "node:path";
64893
65388
  function parseRunners(raw) {
64894
65389
  if (raw === void 0 || raw === null) return { runners: [], errors: [] };
64895
65390
  if (!Array.isArray(raw)) return { runners: [], errors: ["runners must be a list"] };
@@ -64914,8 +65409,8 @@ function bundledRunnersDir() {
64914
65409
  if (fromEnv) return resolve7(fromEnv);
64915
65410
  let dir = import.meta.dirname;
64916
65411
  for (let i = 0; i < 10; i++) {
64917
- const candidate = join37(dir, "runners");
64918
- if (existsSync13(join37(candidate, "local", "spawn.sh"))) return candidate;
65412
+ const candidate = join38(dir, "runners");
65413
+ if (existsSync13(join38(candidate, "local", "spawn.sh"))) return candidate;
64919
65414
  const parent = dirname11(dir);
64920
65415
  if (parent === dir) break;
64921
65416
  dir = parent;
@@ -64926,7 +65421,7 @@ function resolveHookPath(spec, script) {
64926
65421
  if (spec.startsWith(BUNDLED_PREFIX)) {
64927
65422
  const name5 = spec.slice(BUNDLED_PREFIX.length);
64928
65423
  if (!/^[a-z][a-z0-9-]*$/.test(name5)) throw new Error(`invalid bundled hook "${spec}"`);
64929
- return join37(bundledRunnersDir(), name5, `${script}.sh`);
65424
+ return join38(bundledRunnersDir(), name5, `${script}.sh`);
64930
65425
  }
64931
65426
  return isAbsolute2(spec) ? spec : resolve7(bandHome(), spec);
64932
65427
  }
@@ -65025,7 +65520,7 @@ var init_runner_config = __esm({
65025
65520
  });
65026
65521
 
65027
65522
  // src/server/services/settings-service.ts
65028
- import { join as join38 } from "node:path";
65523
+ import { join as join39 } from "node:path";
65029
65524
  function agentModeFromVia(via) {
65030
65525
  if (via === "chat") return "gui";
65031
65526
  if (via === "terminal") return "tui";
@@ -65243,7 +65738,7 @@ var init_settings_service = __esm({
65243
65738
  */
65244
65739
  worktreesDir() {
65245
65740
  const raw = this.rawWorktreesDir();
65246
- return raw ?? join38(bandHome(), "worktrees");
65741
+ return raw ?? join39(bandHome(), "worktrees");
65247
65742
  }
65248
65743
  /**
65249
65744
  * Return the raw `worktreesDir` value from settings without applying the
@@ -65669,6 +66164,7 @@ var init_registry = __esm({
65669
66164
  terminalBackend = null;
65670
66165
  hostRegistry = new HostRegistry(
65671
66166
  new LocalHost({
66167
+ resources: { selfKind: "hub" },
65672
66168
  // `gh` is the GitHub plugin's tool: with that plugin disabled the host never runs it. The
65673
66169
  // import is dynamic because the services import this registry.
65674
66170
  ghEnabled: async () => {
@@ -65913,11 +66409,11 @@ var init_credential_events = __esm({
65913
66409
  // src/server/services/_utils/shared-dir.ts
65914
66410
  import { readdirSync as readdirSync8 } from "node:fs";
65915
66411
  import { mkdir as mkdir5 } from "node:fs/promises";
65916
- import { join as join39 } from "node:path";
66412
+ import { join as join40 } from "node:path";
65917
66413
  async function openSharedDir(worktreeId4, chatId) {
65918
66414
  const host = hostRegistry.hostFor(worktreeId4);
65919
66415
  if (host.id === hostRegistry.local.id) {
65920
- const path3 = join39(bandHome(), "shared", worktreeId4, chatId);
66416
+ const path3 = join40(bandHome(), "shared", worktreeId4, chatId);
65921
66417
  await mkdir5(path3, { recursive: true });
65922
66418
  return {
65923
66419
  path: path3,
@@ -65932,7 +66428,7 @@ async function openSharedDir(worktreeId4, chatId) {
65932
66428
  }
65933
66429
  const dirs = (await host.info()).dirs;
65934
66430
  if (!dirs) throw new Error(`Worker ${host.id} has no directory for shared files`);
65935
- const path2 = join39(dirs.shared, worktreeId4, chatId);
66431
+ const path2 = join40(dirs.shared, worktreeId4, chatId);
65936
66432
  await host.fs.mkdir(path2, { recursive: true });
65937
66433
  return {
65938
66434
  path: path2,
@@ -65948,7 +66444,7 @@ async function openSharedDir(worktreeId4, chatId) {
65948
66444
  async function agentExtraDirs(worktreeId4) {
65949
66445
  const host = hostRegistry.hostFor(worktreeId4);
65950
66446
  if (host.id === hostRegistry.local.id) {
65951
- return [join39(bandHome(), "uploads"), join39(bandHome(), "shared")];
66447
+ return [join40(bandHome(), "uploads"), join40(bandHome(), "shared")];
65952
66448
  }
65953
66449
  const dirs = (await host.info()).dirs;
65954
66450
  return dirs ? [dirs.uploads, dirs.shared] : [];
@@ -66462,9 +66958,9 @@ var init_oauth_client = __esm({
66462
66958
  // src/server/services/_utils/vault-crypto.ts
66463
66959
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes6 } from "node:crypto";
66464
66960
  import { chmodSync as chmodSync2, existsSync as existsSync14, readFileSync as readFileSync9, renameSync as renameSync7, rmSync as rmSync3, writeFileSync as writeFileSync5 } from "node:fs";
66465
- import { join as join40 } from "node:path";
66961
+ import { join as join41 } from "node:path";
66466
66962
  function vaultKeyFile() {
66467
- return join40(bandHome(), "vault.key");
66963
+ return join41(bandHome(), "vault.key");
66468
66964
  }
66469
66965
  function keySource() {
66470
66966
  return process.env.BAND_VAULT_KEY?.trim() ? "env" : "file";
@@ -66538,9 +67034,9 @@ var init_vault_crypto = __esm({
66538
67034
  // src/server/infra/subscriptions/webhook-secret.ts
66539
67035
  import { randomBytes as randomBytes7 } from "node:crypto";
66540
67036
  import { chmodSync as chmodSync3, existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "node:fs";
66541
- import { dirname as dirname12, join as join41 } from "node:path";
67037
+ import { dirname as dirname12, join as join42 } from "node:path";
66542
67038
  function secretPath() {
66543
- return join41(bandHome(), "github-webhook-secret");
67039
+ return join42(bandHome(), "github-webhook-secret");
66544
67040
  }
66545
67041
  function readWebhookSecret() {
66546
67042
  const fromEnv = process.env.BAND_GITHUB_WEBHOOK_SECRET;
@@ -66611,10 +67107,10 @@ async function hubGhEnv() {
66611
67107
  async function hubGhHasNoCredential() {
66612
67108
  return !await machineHasLogin() && vaultService.findGitHubToken() === void 0;
66613
67109
  }
66614
- async function withHubGhCredential(run3) {
67110
+ async function withHubGhCredential(run4) {
66615
67111
  const env = await hubGhEnv();
66616
67112
  try {
66617
- return await run3(env);
67113
+ return await run4(env);
66618
67114
  } catch (err) {
66619
67115
  const message = err instanceof Error ? err.message : String(err);
66620
67116
  if (env.GH_TOKEN === void 0 && UNAUTHENTICATED.test(message) && await hubGhHasNoCredential()) {
@@ -66990,14 +67486,14 @@ function pickPullRequest(allNodes, repoOwner2, isDefaultBranch) {
66990
67486
  );
66991
67487
  const node2 = nodes2.find((n) => n.state === "OPEN") ?? (isDefaultBranch ? void 0 : nodes2.find((n) => n.state === "MERGED") ?? nodes2.find((n) => n.state === "CLOSED"));
66992
67488
  if (!node2) return null;
66993
- const open4 = node2.state === "OPEN";
66994
- const mergeQueue = open4 ? parseMergeQueue(node2) : null;
66995
- const autoMerge = open4 ? parseAutoMerge(node2) : null;
67489
+ const open3 = node2.state === "OPEN";
67490
+ const mergeQueue = open3 ? parseMergeQueue(node2) : null;
67491
+ const autoMerge = open3 ? parseAutoMerge(node2) : null;
66996
67492
  return {
66997
67493
  number: node2.number,
66998
67494
  title: node2.title,
66999
67495
  url: node2.url,
67000
- state: open4 ? "open" : node2.state === "MERGED" ? "merged" : "closed",
67496
+ state: open3 ? "open" : node2.state === "MERGED" ? "merged" : "closed",
67001
67497
  isDraft: node2.isDraft,
67002
67498
  ...mergeQueue && { mergeQueue },
67003
67499
  ...autoMerge && { autoMerge }
@@ -67055,20 +67551,20 @@ function parseBranchStatusResponse(data, branches) {
67055
67551
  }
67056
67552
  let aggregatedState = "success";
67057
67553
  let aggregatedUrl = null;
67058
- for (const run3 of latestByWorkflow.values()) {
67554
+ for (const run4 of latestByWorkflow.values()) {
67059
67555
  let runState;
67060
- if (run3.status === "IN_PROGRESS" || run3.status === "QUEUED") {
67061
- runState = run3.status === "QUEUED" ? "pending" : "running";
67062
- } else if (run3.conclusion === "FAILURE") {
67556
+ if (run4.status === "IN_PROGRESS" || run4.status === "QUEUED") {
67557
+ runState = run4.status === "QUEUED" ? "pending" : "running";
67558
+ } else if (run4.conclusion === "FAILURE") {
67063
67559
  runState = "failure";
67064
- } else if (run3.conclusion === "CANCELLED") {
67560
+ } else if (run4.conclusion === "CANCELLED") {
67065
67561
  runState = "cancelled";
67066
67562
  } else {
67067
67563
  runState = "success";
67068
67564
  }
67069
67565
  if (statePriority(runState) >= statePriority(aggregatedState)) {
67070
67566
  aggregatedState = runState;
67071
- aggregatedUrl = run3.url;
67567
+ aggregatedUrl = run4.url;
67072
67568
  }
67073
67569
  }
67074
67570
  results[branch] = { state: aggregatedState, url: reviewUrl ?? aggregatedUrl, review };
@@ -67203,11 +67699,11 @@ function parseBranchChecks(data) {
67203
67699
  if (!suite.workflowRun) continue;
67204
67700
  const workflowName = suite.workflowRun.workflow.name;
67205
67701
  for (const node2 of suite.checkRuns.nodes) {
67206
- const run3 = fromCheckRun(node2, workflowName);
67207
- const key2 = `${workflowName}\0${run3.name}`;
67702
+ const run4 = fromCheckRun(node2, workflowName);
67703
+ const key2 = `${workflowName}\0${run4.name}`;
67208
67704
  const existing = latest.get(key2);
67209
- if (!existing || (run3.startedAt ?? "") > (existing.startedAt ?? "")) {
67210
- latest.set(key2, run3);
67705
+ if (!existing || (run4.startedAt ?? "") > (existing.startedAt ?? "")) {
67706
+ latest.set(key2, run4);
67211
67707
  }
67212
67708
  }
67213
67709
  }
@@ -67558,15 +68054,15 @@ function parseCheckRuns(output2) {
67558
68054
  const runs = parsed?.check_runs;
67559
68055
  if (!Array.isArray(runs)) throw new Error("Unexpected check-runs response");
67560
68056
  return runs.flatMap((r) => {
67561
- const run3 = obj(r);
67562
- if (!run3) return [];
68057
+ const run4 = obj(r);
68058
+ if (!run4) return [];
67563
68059
  return [
67564
68060
  {
67565
- name: str2(run3.name) || "unnamed check",
67566
- status: str2(run3.status),
67567
- conclusion: typeof run3.conclusion === "string" ? run3.conclusion : null,
67568
- url: str2(run3.html_url) || void 0,
67569
- headSha: str2(run3.head_sha) || void 0
68061
+ name: str2(run4.name) || "unnamed check",
68062
+ status: str2(run4.status),
68063
+ conclusion: typeof run4.conclusion === "string" ? run4.conclusion : null,
68064
+ url: str2(run4.html_url) || void 0,
68065
+ headSha: str2(run4.head_sha) || void 0
67570
68066
  }
67571
68067
  ];
67572
68068
  });
@@ -67810,10 +68306,10 @@ function parseGithubDelivery(eventType, delivery, payload, now = Date.now()) {
67810
68306
  case "check_suite":
67811
68307
  case "workflow_run": {
67812
68308
  if (action !== "completed") return { type: "ignored" };
67813
- const run3 = obj(body[eventType]);
67814
- const suite = obj(run3?.check_suite);
67815
- const branch = str2(run3?.head_branch) || str2(suite?.head_branch);
67816
- const sha = str2(run3?.head_sha) || str2(suite?.head_sha);
68309
+ const run4 = obj(body[eventType]);
68310
+ const suite = obj(run4?.check_suite);
68311
+ const branch = str2(run4?.head_branch) || str2(suite?.head_branch);
68312
+ const sha = str2(run4?.head_sha) || str2(suite?.head_sha);
67817
68313
  if (!branch || !/^[0-9a-f]{7,64}$/i.test(sha)) return { type: "ignored" };
67818
68314
  return { type: "check", trigger: { repo, branch, sha } };
67819
68315
  }
@@ -67851,9 +68347,9 @@ function reviewTargetOf(eventType, payload) {
67851
68347
  return match ? target("", match[1]) : { repo };
67852
68348
  }
67853
68349
  default: {
67854
- const run3 = obj(body[eventType]);
67855
- const suite = obj(run3?.check_suite);
67856
- const branch = str2(run3?.head_branch) || str2(suite?.head_branch);
68350
+ const run4 = obj(body[eventType]);
68351
+ const suite = obj(run4?.check_suite);
68352
+ const branch = str2(run4?.head_branch) || str2(suite?.head_branch);
67857
68353
  return branch ? target(branch, void 0) : { repo };
67858
68354
  }
67859
68355
  }
@@ -68096,14 +68592,14 @@ var init_server3 = __esm({
68096
68592
  const handoff2 = /* @__PURE__ */ new Map();
68097
68593
  const keyOf2 = (repo, branch) => `${repoArg(repo)}#${branch}`;
68098
68594
  const noMergeQueue = /* @__PURE__ */ new Set();
68099
- async function withMergeQueueFallback(repo, run3) {
68100
- if (noMergeQueue.has(repo.host)) return run3(false);
68595
+ async function withMergeQueueFallback(repo, run4) {
68596
+ if (noMergeQueue.has(repo.host)) return run4(false);
68101
68597
  try {
68102
- return await run3(true);
68598
+ return await run4(true);
68103
68599
  } catch (error63) {
68104
68600
  if (!isUnknownMergeQueueField(error63)) throw error63;
68105
68601
  noMergeQueue.add(repo.host);
68106
- return run3(false);
68602
+ return run4(false);
68107
68603
  }
68108
68604
  }
68109
68605
  function query(repo, branch, ctx) {
@@ -69060,12 +69556,12 @@ var init_worktree_checkpoints = __esm({
69060
69556
 
69061
69557
  // src/server/services/_utils/checkpoint-store.ts
69062
69558
  import { rmSync as rmSync4 } from "node:fs";
69063
- import { join as join42 } from "node:path";
69559
+ import { join as join43 } from "node:path";
69064
69560
  function worktreeCheckpointDir(worktreeId4) {
69065
- return join42(bandHome(), "checkpoints", worktreeId4);
69561
+ return join43(bandHome(), "checkpoints", worktreeId4);
69066
69562
  }
69067
69563
  function checkpointDir(worktreeId4, checkpointId2) {
69068
- return join42(worktreeCheckpointDir(worktreeId4), checkpointId2);
69564
+ return join43(worktreeCheckpointDir(worktreeId4), checkpointId2);
69069
69565
  }
69070
69566
  function forgetCheckpoints(worktreeId4) {
69071
69567
  queries.deleteForWorktree(worktreeId4);
@@ -72280,7 +72776,7 @@ var init_chat_ownership_service = __esm({
72280
72776
  this.deliverAgain.add(hostId2);
72281
72777
  return;
72282
72778
  }
72283
- const run3 = (async () => {
72779
+ const run4 = (async () => {
72284
72780
  do {
72285
72781
  this.deliverAgain.delete(hostId2);
72286
72782
  for (; ; ) {
@@ -72302,8 +72798,8 @@ var init_chat_ownership_service = __esm({
72302
72798
  }
72303
72799
  } while (this.deliverAgain.has(hostId2));
72304
72800
  })();
72305
- this.delivering.set(hostId2, run3);
72306
- void run3.catch((err) => log24.warn({ hostId: hostId2, err }, "chat outbox delivery failed")).finally(() => {
72801
+ this.delivering.set(hostId2, run4);
72802
+ void run4.catch((err) => log24.warn({ hostId: hostId2, err }, "chat outbox delivery failed")).finally(() => {
72307
72803
  this.delivering.delete(hostId2);
72308
72804
  if (this.deliverAgain.delete(hostId2) && !this.retryTimers.has(hostId2)) {
72309
72805
  this.deliver(hostId2);
@@ -75175,8 +75671,8 @@ var init_placement_service = __esm({
75175
75671
  */
75176
75672
  async placeWorktree(input3, placement) {
75177
75673
  const worktreeId4 = toWorktreeId(input3.repo, input3.branch, void 0);
75178
- const open4 = this.queries.findOpenForWorktree(worktreeId4);
75179
- if (open4) return { kind: "request", requestId: open4.id };
75674
+ const open3 = this.queries.findOpenForWorktree(worktreeId4);
75675
+ if (open3) return { kind: "request", requestId: open3.id };
75180
75676
  const holders = this.holdersOfRemotelessRepo(input3.repo);
75181
75677
  const agent = input3.codingAgentId ? loadSettings().codingAgents?.find((a) => a.id === input3.codingAgentId)?.type ?? input3.codingAgentId : void 0;
75182
75678
  const allowed2 = allowedHostsOf(input3.repo);
@@ -75244,8 +75740,8 @@ var init_placement_service = __esm({
75244
75740
  requestWake(wake, repo, branch) {
75245
75741
  const first = wake.worktreeIds[0];
75246
75742
  if (!first) throw new Error("A wake request names no worktree");
75247
- const open4 = this.queries.findOpenForWorktree(first);
75248
- if (open4) return open4;
75743
+ const open3 = this.queries.findOpenForWorktree(first);
75744
+ if (open3) return open3;
75249
75745
  const earlier = this.queries.latestForHost(wake.hostId);
75250
75746
  const now = this.now();
75251
75747
  const row = {
@@ -76331,7 +76827,7 @@ var init_git_credential_service = __esm({
76331
76827
  import { spawn as spawn6 } from "node:child_process";
76332
76828
  import { randomBytes as randomBytes10 } from "node:crypto";
76333
76829
  import { appendFileSync, mkdirSync as mkdirSync8, readFileSync as readFileSync11, rmSync as rmSync5, statSync as statSync14 } from "node:fs";
76334
- import { dirname as dirname13, join as join43 } from "node:path";
76830
+ import { dirname as dirname13, join as join44 } from "node:path";
76335
76831
  function snapshotSweepMs() {
76336
76832
  const raw = Number(process.env.BAND_SNAPSHOT_SWEEP_MS);
76337
76833
  return Number.isFinite(raw) && raw > 0 ? raw : SNAPSHOT_SWEEP_MS;
@@ -76528,7 +77024,7 @@ var init_runner_service = __esm({
76528
77024
  }
76529
77025
  }
76530
77026
  logFile(requestId2) {
76531
- return join43(bandHome(), "runners", "logs", `${requestId2}.log`);
77027
+ return join44(bandHome(), "runners", "logs", `${requestId2}.log`);
76532
77028
  }
76533
77029
  /** Every valid runner in settings. */
76534
77030
  configs() {
@@ -76544,12 +77040,12 @@ var init_runner_service = __esm({
76544
77040
  }
76545
77041
  /** Whether the worker id belongs to an attempt in flight. */
76546
77042
  isAttempting(workerId) {
76547
- for (const run3 of this.running.values()) if (run3.workerId === workerId) return true;
77043
+ for (const run4 of this.running.values()) if (run4.workerId === workerId) return true;
76548
77044
  return false;
76549
77045
  }
76550
77046
  runningCount(runnerId2) {
76551
77047
  let n = 0;
76552
- for (const run3 of this.running.values()) if (run3.runnerId === runnerId2) n++;
77048
+ for (const run4 of this.running.values()) if (run4.runnerId === runnerId2) n++;
76553
77049
  return n;
76554
77050
  }
76555
77051
  // ---- leasing -------------------------------------------------------------
@@ -76585,7 +77081,7 @@ var init_runner_service = __esm({
76585
77081
  }
76586
77082
  }
76587
77083
  begin(runner, row) {
76588
- const run3 = {
77084
+ const run4 = {
76589
77085
  requestId: row.id,
76590
77086
  runnerId: runner.id,
76591
77087
  worktreeId: row.worktreeId,
@@ -76596,27 +77092,27 @@ var init_runner_service = __esm({
76596
77092
  endedAt: null,
76597
77093
  error: null
76598
77094
  };
76599
- this.running.set(row.id, run3);
76600
- const done = this.run(runner, row, run3).catch(
77095
+ this.running.set(row.id, run4);
77096
+ const done = this.run(runner, row, run4).catch(
76601
77097
  (err) => log32.error(`run of ${row.id} crashed: ${err instanceof Error ? err.stack : err}`)
76602
77098
  ).finally(() => {
76603
77099
  this.running.delete(row.id);
76604
- run3.endedAt = Date.now();
76605
- this.history.push(run3);
77100
+ run4.endedAt = Date.now();
77101
+ this.history.push(run4);
76606
77102
  if (this.history.length > HISTORY_LIMIT) this.history.shift();
76607
77103
  this.settled.delete(done);
76608
77104
  });
76609
77105
  this.settled.add(done);
76610
77106
  }
76611
77107
  // ---- one request ---------------------------------------------------------
76612
- async run(runner, row, run3) {
77108
+ async run(runner, row, run4) {
76613
77109
  const runLog = new RunLog(this.logFile(row.id));
76614
77110
  runLog.write("hub", `runner ${runner.id} took request ${row.id} for ${row.worktreeId}`);
76615
77111
  const environment = parseRequestEnvironment(row);
76616
77112
  if (!environment.ok) {
76617
77113
  runLog.write("hub", environment.error);
76618
- run3.status = "failed";
76619
- run3.error = environment.error;
77114
+ run4.status = "failed";
77115
+ run4.error = environment.error;
76620
77116
  try {
76621
77117
  placementService.fail(row.id, environment.error);
76622
77118
  } catch (err) {
@@ -76626,19 +77122,19 @@ var init_runner_service = __esm({
76626
77122
  }
76627
77123
  let lastError = "";
76628
77124
  for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {
76629
- run3.attempt = attempt;
77125
+ run4.attempt = attempt;
76630
77126
  runLog.write("hub", `attempt ${attempt} of ${ATTEMPTS}`);
76631
77127
  const attemptState = { hostId: null, token: null };
76632
77128
  try {
76633
- const hostId2 = await this.attempt(runner, row, run3, runLog, attemptState);
76634
- run3.workerId = hostId2;
76635
- run3.status = "ready";
77129
+ const hostId2 = await this.attempt(runner, row, run4, runLog, attemptState);
77130
+ run4.workerId = hostId2;
77131
+ run4.status = "ready";
76636
77132
  runLog.write("hub", `worker ${hostId2} said hello; request fulfilled`);
76637
77133
  return;
76638
77134
  } catch (err) {
76639
77135
  if (err instanceof Aborted) {
76640
- run3.status = "aborted";
76641
- run3.error = err.message;
77136
+ run4.status = "aborted";
77137
+ run4.error = err.message;
76642
77138
  runLog.write("hub", `stopped: ${err.message}`);
76643
77139
  await this.cleanup(runner, row, attemptState, runLog);
76644
77140
  return;
@@ -76649,8 +77145,8 @@ var init_runner_service = __esm({
76649
77145
  }
76650
77146
  }
76651
77147
  const reason = this.failureReason(runner, lastError, runLog);
76652
- run3.status = "failed";
76653
- run3.error = lastError;
77148
+ run4.status = "failed";
77149
+ run4.error = lastError;
76654
77150
  try {
76655
77151
  placementService.fail(row.id, reason);
76656
77152
  } catch (err) {
@@ -76723,13 +77219,13 @@ ${tail}` : head;
76723
77219
  * runner holds a snapshot for tries `restore` first, and starts a fresh worker with `spawn` when
76724
77220
  * that fails, so the git and session state the sleep stored is what brings the worktree back.
76725
77221
  */
76726
- async attempt(runner, row, run3, runLog, state2) {
77222
+ async attempt(runner, row, run4, runLog, state2) {
76727
77223
  const wake = wakeOf(row);
76728
77224
  const snapshot = wake ? this.restorableSnapshot(runner, wake.hostId) : void 0;
76729
77225
  if (snapshot) {
76730
77226
  this.restoring.add(snapshot.id);
76731
77227
  try {
76732
- return await this.launch(runner, row, run3, runLog, state2, "restore", snapshot);
77228
+ return await this.launch(runner, row, run4, runLog, state2, "restore", snapshot);
76733
77229
  } catch (err) {
76734
77230
  if (err instanceof Aborted) throw err;
76735
77231
  runLog.write(
@@ -76742,7 +77238,7 @@ ${tail}` : head;
76742
77238
  this.restoring.delete(snapshot.id);
76743
77239
  }
76744
77240
  }
76745
- return this.launch(runner, row, run3, runLog, state2, "spawn");
77241
+ return this.launch(runner, row, run4, runLog, state2, "spawn");
76746
77242
  }
76747
77243
  /** The snapshot a wake can restore from: this runner's, still alive, and the runner has a `restore` hook. */
76748
77244
  restorableSnapshot(runner, hostId2) {
@@ -76752,7 +77248,7 @@ ${tail}` : head;
76752
77248
  return void 0;
76753
77249
  return latest;
76754
77250
  }
76755
- async launch(runner, row, run3, runLog, state2, kind, snapshot) {
77251
+ async launch(runner, row, run4, runLog, state2, kind, snapshot) {
76756
77252
  const deadline = Date.now() + runner.timeoutSec * 1e3;
76757
77253
  const labelList = Object.entries(row.labels).map(([k2, v2]) => `${k2}=${v2}`);
76758
77254
  const wanted = requestedIsolation(row.environment);
@@ -76770,7 +77266,7 @@ ${tail}` : head;
76770
77266
  state2.reused = wake !== null;
76771
77267
  state2.token = issued.token;
76772
77268
  runLog.addSecret(issued.token);
76773
- run3.workerId = issued.hostId;
77269
+ run4.workerId = issued.hostId;
76774
77270
  runLog.write("hub", `issued worker ${issued.hostId}`);
76775
77271
  const machineId = this.recordMachine(runner, row, issued.hostId);
76776
77272
  state2.machineId = machineId;
@@ -76905,11 +77401,11 @@ ${tail}` : head;
76905
77401
  destroyMachine(machineId, reason) {
76906
77402
  const inflight = this.destroying.get(machineId);
76907
77403
  if (inflight) return inflight;
76908
- const run3 = this.doDestroyMachine(machineId, reason).finally(
77404
+ const run4 = this.doDestroyMachine(machineId, reason).finally(
76909
77405
  () => this.destroying.delete(machineId)
76910
77406
  );
76911
- this.destroying.set(machineId, run3);
76912
- return run3;
77407
+ this.destroying.set(machineId, run4);
77408
+ return run4;
76913
77409
  }
76914
77410
  async doDestroyMachine(machineId, reason) {
76915
77411
  const machine = this.machines.get(machineId);
@@ -76918,7 +77414,7 @@ ${tail}` : head;
76918
77414
  const runner = this.findRunner(machine.runnerId);
76919
77415
  const request = machine.requestId ? placementService.get(machine.requestId) : void 0;
76920
77416
  const runLog = new RunLog(
76921
- machine.requestId ? this.logFile(machine.requestId) : join43(bandHome(), "runners", "logs", `${machine.id}.log`)
77417
+ machine.requestId ? this.logFile(machine.requestId) : join44(bandHome(), "runners", "logs", `${machine.id}.log`)
76922
77418
  );
76923
77419
  runLog.write(
76924
77420
  "hub",
@@ -76966,7 +77462,7 @@ ${tail}` : head;
76966
77462
  /** Runs `destroy` for a machine the hub has no record of, named only by the handle `status` printed. */
76967
77463
  async destroyHandle(runner, handle, reason) {
76968
77464
  if (!runner.destroy) return false;
76969
- const file3 = join43(bandHome(), "runners", "logs", "reaper.log");
77465
+ const file3 = join44(bandHome(), "runners", "logs", "reaper.log");
76970
77466
  try {
76971
77467
  if (statSync14(file3).size > LOG_FILE_LIMIT) rmSync5(file3, { force: true });
76972
77468
  } catch {
@@ -77188,7 +77684,7 @@ ${tail}` : head;
77188
77684
  // The repo's current environment image (plan step 3.2), empty before its first ready build.
77189
77685
  BAND_REPO_IMAGE: row ? this.repoImage(row.repo) : "",
77190
77686
  BAND_RUNNER_ID: runner.id,
77191
- BAND_RUNNER_DIR: join43(bandHome(), "runners", runner.id),
77687
+ BAND_RUNNER_DIR: join44(bandHome(), "runners", runner.id),
77192
77688
  BAND_NODE: process.execPath
77193
77689
  });
77194
77690
  if (runner.desktop) env.BAND_DESKTOP = "1";
@@ -77217,7 +77713,7 @@ ${tail}` : head;
77217
77713
  */
77218
77714
  runHook(opts) {
77219
77715
  const { runner, name: name5, path: path2, env, timeoutMs, runLog, watch, onStdout, onStderr } = opts;
77220
- const cwd = join43(bandHome(), "runners", runner.id);
77716
+ const cwd = join44(bandHome(), "runners", runner.id);
77221
77717
  mkdirSync8(cwd, { recursive: true, mode: 448 });
77222
77718
  return new Promise((resolve16, reject) => {
77223
77719
  let child;
@@ -77277,14 +77773,14 @@ ${tail}` : head;
77277
77773
 
77278
77774
  // src/server/services/ephemeral-lifecycle-service.ts
77279
77775
  import { rmSync as rmSync6 } from "node:fs";
77280
- import { mkdir as mkdir6, readFile as readFile9, writeFile as writeFile4 } from "node:fs/promises";
77281
- import { join as join44, posix as posix5 } from "node:path";
77776
+ import { mkdir as mkdir6, readFile as readFile11, writeFile as writeFile4 } from "node:fs/promises";
77777
+ import { join as join45, posix as posix5 } from "node:path";
77282
77778
  function idleTimeoutMs() {
77283
77779
  const raw = Number(process.env.BAND_EPHEMERAL_IDLE_TIMEOUT_MS);
77284
77780
  return Number.isFinite(raw) && raw > 0 ? raw : void 0;
77285
77781
  }
77286
77782
  function sleepDir(worktreeId4) {
77287
- return join44(bandHome(), "sleep", worktreeId4);
77783
+ return join45(bandHome(), "sleep", worktreeId4);
77288
77784
  }
77289
77785
  var log33, LOCAL_HOST_ID6, WAKE_POLL_MS, WAKE_GRACE_MS, EXIT_GRACE_MS2, SleepError, errorText2, EphemeralLifecycleService, ephemeralLifecycleService;
77290
77786
  var init_ephemeral_lifecycle_service = __esm({
@@ -77606,7 +78102,7 @@ var init_ephemeral_lifecycle_service = __esm({
77606
78102
  const dir = sleepDir(worktreeId4);
77607
78103
  try {
77608
78104
  await mkdir6(dir, { recursive: true, mode: 448 });
77609
- await writeFile4(join44(dir, "snapshot.bundle"), await host.fs.readFile(bundle), {
78105
+ await writeFile4(join45(dir, "snapshot.bundle"), await host.fs.readFile(bundle), {
77610
78106
  mode: 384
77611
78107
  });
77612
78108
  } catch (err) {
@@ -77630,7 +78126,7 @@ var init_ephemeral_lifecycle_service = __esm({
77630
78126
  try {
77631
78127
  const dir = sleepDir(worktreeId4);
77632
78128
  await mkdir6(dir, { recursive: true, mode: 448 });
77633
- await writeFile4(join44(dir, "sessions.json"), JSON.stringify({ files }), { mode: 384 });
78129
+ await writeFile4(join45(dir, "sessions.json"), JSON.stringify({ files }), { mode: 384 });
77634
78130
  } catch (err) {
77635
78131
  log33.warn(`could not keep the agent sessions of ${worktreeId4}: ${errorText2(err)}`);
77636
78132
  return [];
@@ -77756,7 +78252,7 @@ var init_ephemeral_lifecycle_service = __esm({
77756
78252
  const bundle = posix5.join(wipDir, `${row.worktreeId}.bundle`);
77757
78253
  await host.fs.writeFile(
77758
78254
  bundle,
77759
- await readFile9(join44(sleepDir(row.worktreeId), "snapshot.bundle"))
78255
+ await readFile11(join45(sleepDir(row.worktreeId), "snapshot.bundle"))
77760
78256
  );
77761
78257
  try {
77762
78258
  await git2(["fetch", "--force", bundle, `${local}:${local}`]);
@@ -77813,7 +78309,7 @@ var init_ephemeral_lifecycle_service = __esm({
77813
78309
  if (row.sessionIds.length === 0) return;
77814
78310
  let files;
77815
78311
  try {
77816
- files = JSON.parse(await readFile9(join44(sleepDir(row.worktreeId), "sessions.json"), "utf8")).files;
78312
+ files = JSON.parse(await readFile11(join45(sleepDir(row.worktreeId), "sessions.json"), "utf8")).files;
77817
78313
  } catch (err) {
77818
78314
  log33.warn(`${row.worktreeId}: no saved agent sessions: ${errorText2(err)}`);
77819
78315
  return;
@@ -78553,7 +79049,7 @@ var init_watcher_service = __esm({
78553
79049
  this.poller.start();
78554
79050
  const statuses = loadCurrentStatuses();
78555
79051
  const runningScripts = worktreeScriptService.getRunning();
78556
- const runningSetups = [...new Set(runningScripts.map((run3) => run3.worktreeId))];
79052
+ const runningSetups = [...new Set(runningScripts.map((run4) => run4.worktreeId))];
78557
79053
  listener({ kind: "snapshot", statuses, runningSetups });
78558
79054
  for (const event of this.loadCurrentBranchStatuses()) {
78559
79055
  listener(event);
@@ -78645,13 +79141,13 @@ var init_agent_session_registry_service = __esm({
78645
79141
  * agent sessions gets its row here, the first time its id is known.
78646
79142
  */
78647
79143
  recordChatProviderSession(chat, providerSessionId) {
78648
- const open4 = this.queries.findOpenByChat(chat.id);
78649
- if (open4 && open4.providerSessionId === providerSessionId) return;
78650
- if (open4 && open4.providerSessionId === null) {
78651
- if (providerSessionId) this.update(open4.id, { providerSessionId, state: "running" });
79144
+ const open3 = this.queries.findOpenByChat(chat.id);
79145
+ if (open3 && open3.providerSessionId === providerSessionId) return;
79146
+ if (open3 && open3.providerSessionId === null) {
79147
+ if (providerSessionId) this.update(open3.id, { providerSessionId, state: "running" });
78652
79148
  return;
78653
79149
  }
78654
- if (open4) this.end(open4.id);
79150
+ if (open3) this.end(open3.id);
78655
79151
  if (!providerSessionId) return;
78656
79152
  this.create({
78657
79153
  worktreeId: chat.worktreeId,
@@ -78662,12 +79158,12 @@ var init_agent_session_registry_service = __esm({
78662
79158
  });
78663
79159
  }
78664
79160
  endForChat(chatId) {
78665
- const open4 = this.queries.findOpenByChat(chatId);
78666
- if (open4) this.end(open4.id);
79161
+ const open3 = this.queries.findOpenByChat(chatId);
79162
+ if (open3) this.end(open3.id);
78667
79163
  }
78668
79164
  endForTerminal(terminalId) {
78669
- const open4 = this.queries.findOpenByTerminal(terminalId);
78670
- if (open4) this.end(open4.id);
79165
+ const open3 = this.queries.findOpenByTerminal(terminalId);
79166
+ if (open3) this.end(open3.id);
78671
79167
  }
78672
79168
  end(id) {
78673
79169
  const ended = this.queries.update(id, { state: "ended", updatedAt: Date.now() });
@@ -80675,7 +81171,7 @@ var init_worker_lease_service = __esm({
80675
81171
  entry.again = true;
80676
81172
  return entry.running;
80677
81173
  }
80678
- const run3 = (async () => {
81174
+ const run4 = (async () => {
80679
81175
  do {
80680
81176
  entry.again = false;
80681
81177
  await this.renewOnce(hostId2, entry);
@@ -80684,8 +81180,8 @@ var init_worker_lease_service = __esm({
80684
81180
  entry.running = null;
80685
81181
  entry.again = false;
80686
81182
  });
80687
- entry.running = run3;
80688
- return run3;
81183
+ entry.running = run4;
81184
+ return run4;
80689
81185
  }
80690
81186
  async renewOnce(hostId2, entry) {
80691
81187
  const params = { ttlMs: leaseMs(), blockedPaths: this.blockedPaths(hostId2) };
@@ -80922,7 +81418,7 @@ __export(worktree_service_exports, {
80922
81418
  });
80923
81419
  import { randomUUID as randomUUID14 } from "node:crypto";
80924
81420
  import { unlinkSync as unlinkSync5 } from "node:fs";
80925
- import { join as join45, posix as posix6 } from "node:path";
81421
+ import { join as join46, posix as posix6 } from "node:path";
80926
81422
  function findWorktreeRow(worktrees2, name5, hostId2) {
80927
81423
  const named = worktrees2.filter((wt) => wt.name === name5);
80928
81424
  if (hostId2 !== void 0) return named.find((wt) => (wt.hostId ?? "local") === hostId2);
@@ -81383,8 +81879,8 @@ var init_worktree_service = __esm({
81383
81879
  try {
81384
81880
  repoPath = await this.checkoutOn(repo, host, input3.hostRepoPath);
81385
81881
  const wtDir = remote ? await this.remoteWorktreesDir(host) : worktreesDir();
81386
- worktreePath = remote ? posix6.join(wtDir, input3.repo, input3.branch) : join45(wtDir, input3.repo, input3.branch);
81387
- await host.fs.mkdir(remote ? posix6.join(wtDir, input3.repo) : join45(wtDir, input3.repo), {
81882
+ worktreePath = remote ? posix6.join(wtDir, input3.repo, input3.branch) : join46(wtDir, input3.repo, input3.branch);
81883
+ await host.fs.mkdir(remote ? posix6.join(wtDir, input3.repo) : join46(wtDir, input3.repo), {
81388
81884
  recursive: true
81389
81885
  });
81390
81886
  try {
@@ -81666,7 +82162,7 @@ var init_worktree_service = __esm({
81666
82162
  if (gone.supersededBy)
81667
82163
  void workerLeaseService.pushBlockedPaths(gone.hostId ?? hostRegistry.local.id);
81668
82164
  try {
81669
- unlinkSync5(join45(bandHome(), "workspace-prompts", `${worktreeId4}.json`));
82165
+ unlinkSync5(join46(bandHome(), "workspace-prompts", `${worktreeId4}.json`));
81670
82166
  } catch {
81671
82167
  }
81672
82168
  deleteWorktreeStatus(worktreeId4);
@@ -82273,7 +82769,7 @@ var init_worktree_service = __esm({
82273
82769
  if (!/^[a-zA-Z0-9._-]+$/.test(input3.scriptType) || input3.scriptType.includes("..")) {
82274
82770
  throw new Error(`Invalid script type "${input3.scriptType}"`);
82275
82771
  }
82276
- const scriptPath = join45(input3.path, ".band", input3.scriptType);
82772
+ const scriptPath = join46(input3.path, ".band", input3.scriptType);
82277
82773
  const host = hostRegistry.local;
82278
82774
  try {
82279
82775
  await host.fs.stat(scriptPath);
@@ -82851,11 +83347,11 @@ var init_subscription_source_service = __esm({
82851
83347
  if (running) {
82852
83348
  await running;
82853
83349
  }
82854
- const run3 = this.fetchAndIngest(provider, check3.trigger).finally(() => {
82855
- if (checking.get(check3.flight) === run3) checking.delete(check3.flight);
83350
+ const run4 = this.fetchAndIngest(provider, check3.trigger).finally(() => {
83351
+ if (checking.get(check3.flight) === run4) checking.delete(check3.flight);
82856
83352
  });
82857
- checking.set(check3.flight, run3);
82858
- await run3;
83353
+ checking.set(check3.flight, run4);
83354
+ await run4;
82859
83355
  }
82860
83356
  async fetchAndIngest(provider, trigger) {
82861
83357
  const event = await provider.aggregateChecks(trigger, subscriptionContext());
@@ -82882,11 +83378,11 @@ var init_subscription_source_service = __esm({
82882
83378
  const repo = sub.config.repo;
82883
83379
  if (sub.source !== GITHUB || !repo) return;
82884
83380
  const previous = registering.get(repo) ?? Promise.resolve();
82885
- const run3 = previous.then(() => this.register(sub.id, repo, sub.source)).finally(() => {
82886
- if (registering.get(repo) === run3) registering.delete(repo);
83381
+ const run4 = previous.then(() => this.register(sub.id, repo, sub.source)).finally(() => {
83382
+ if (registering.get(repo) === run4) registering.delete(repo);
82887
83383
  });
82888
- registering.set(repo, run3);
82889
- await run3;
83384
+ registering.set(repo, run4);
83385
+ await run4;
82890
83386
  }
82891
83387
  async register(subscriptionId, repo, source) {
82892
83388
  const set2 = (status, error63) => {
@@ -85469,6 +85965,15 @@ var init_agent_session_service = __esm({
85469
85965
  observeBackgroundTasks(observer) {
85470
85966
  backgroundObserver = observer;
85471
85967
  }
85968
+ /** The agent process of each chat that has one: the chat, its worktree and the pid on the worker. */
85969
+ agentPids() {
85970
+ const out = [];
85971
+ for (const rt of runtimes.values()) {
85972
+ const pid = rt.process?.pid;
85973
+ if (pid !== void 0) out.push({ chatId: rt.chatId, worktreeId: rt.worktreeId, pid });
85974
+ }
85975
+ return out;
85976
+ }
85472
85977
  /** When the chat's agent last sent anything (ms since epoch), or null. */
85473
85978
  lastActivityAt(chatId) {
85474
85979
  return runtimes.get(chatId)?.lastActivityAt ?? null;
@@ -92859,7 +93364,7 @@ import {
92859
93364
  statSync as statSync17
92860
93365
  } from "node:fs";
92861
93366
  import { createServer as createServer3 } from "node:http";
92862
- import { basename as basename7, join as join61, resolve as resolve15, sep as sep12 } from "node:path";
93367
+ import { basename as basename7, join as join62, resolve as resolve15, sep as sep12 } from "node:path";
92863
93368
  import { pipeline as pipeline3, Readable as Readable2 } from "node:stream";
92864
93369
  import { parseArgs } from "node:util";
92865
93370
 
@@ -96282,7 +96787,7 @@ var sessionIdSchema = external_exports2.string().regex(SESSION_ID_PATTERN2, "inv
96282
96787
  init_registry();
96283
96788
  init_state();
96284
96789
  import { mkdir as mkdir7, writeFile as writeFile5 } from "node:fs/promises";
96285
- import { join as join46, resolve as resolve8, sep as sep5 } from "node:path";
96790
+ import { join as join47, resolve as resolve8, sep as sep5 } from "node:path";
96286
96791
  function decodeParts(fileParts) {
96287
96792
  const baseTimestamp = Date.now();
96288
96793
  const decoded = [];
@@ -96302,11 +96807,11 @@ function decodeParts(fileParts) {
96302
96807
  return decoded;
96303
96808
  }
96304
96809
  async function saveUploadedFilesDetailed(fileParts) {
96305
- const uploadDir = join46(bandHome(), "uploads");
96810
+ const uploadDir = join47(bandHome(), "uploads");
96306
96811
  await mkdir7(uploadDir, { recursive: true });
96307
96812
  const saved = [];
96308
96813
  for (const part of decodeParts(fileParts)) {
96309
- const filePath = join46(uploadDir, part.storedName);
96814
+ const filePath = join47(uploadDir, part.storedName);
96310
96815
  await writeFile5(filePath, part.buffer);
96311
96816
  saved.push({
96312
96817
  path: filePath,
@@ -96321,7 +96826,7 @@ async function saveUploadedFilesDetailed(fileParts) {
96321
96826
  async function remoteUploadDir(host, worktreeId4) {
96322
96827
  const dirs = (await host.info()).dirs;
96323
96828
  if (!dirs) throw new Error(`Worker ${host.id} has no directory for uploads`);
96324
- return join46(dirs.uploads, worktreeId4);
96829
+ return join47(dirs.uploads, worktreeId4);
96325
96830
  }
96326
96831
  async function saveWorktreeUploads(worktreeId4, fileParts) {
96327
96832
  const host = hostRegistry.hostFor(worktreeId4);
@@ -96330,7 +96835,7 @@ async function saveWorktreeUploads(worktreeId4, fileParts) {
96330
96835
  await host.fs.mkdir(dir, { recursive: true });
96331
96836
  const saved = [];
96332
96837
  for (const part of decodeParts(fileParts)) {
96333
- const filePath = join46(dir, part.storedName);
96838
+ const filePath = join47(dir, part.storedName);
96334
96839
  await host.fs.writeFile(filePath, part.buffer, { exclusive: true, mode: 384 });
96335
96840
  saved.push({
96336
96841
  path: filePath,
@@ -96346,19 +96851,19 @@ async function uploadPathFromUrl(worktreeId4, url3) {
96346
96851
  const host = hostRegistry.hostFor(worktreeId4);
96347
96852
  const match = url3.match(/^\/api\/uploads\/(.+)$/);
96348
96853
  if (!match) return null;
96349
- if (host.id === hostRegistry.local.id) return join46(bandHome(), "uploads", match[1]);
96854
+ if (host.id === hostRegistry.local.id) return join47(bandHome(), "uploads", match[1]);
96350
96855
  const rest = match[1].split("/");
96351
96856
  if (rest.length !== 2) return null;
96352
96857
  try {
96353
96858
  if (decodeURIComponent(rest[0]) !== worktreeId4) return null;
96354
- return join46(await remoteUploadDir(host, worktreeId4), decodeURIComponent(rest[1]));
96859
+ return join47(await remoteUploadDir(host, worktreeId4), decodeURIComponent(rest[1]));
96355
96860
  } catch {
96356
96861
  return null;
96357
96862
  }
96358
96863
  }
96359
96864
  async function isWithinUploads(worktreeId4, path2) {
96360
96865
  const host = hostRegistry.hostFor(worktreeId4);
96361
- const dir = host.id === hostRegistry.local.id ? join46(bandHome(), "uploads") : await remoteUploadDir(host, worktreeId4).catch(() => null);
96866
+ const dir = host.id === hostRegistry.local.id ? join47(bandHome(), "uploads") : await remoteUploadDir(host, worktreeId4).catch(() => null);
96362
96867
  if (!dir) return false;
96363
96868
  const normalized2 = resolve8(path2);
96364
96869
  return normalized2 === dir || normalized2.startsWith(dir + sep5);
@@ -96410,8 +96915,8 @@ init_src4();
96410
96915
  init_src2();
96411
96916
  init_src();
96412
96917
  import { createHash as createHash12, randomBytes as randomBytes15 } from "node:crypto";
96413
- import { mkdir as mkdir9, readFile as readFile11, rm as rm3, writeFile as writeFile7 } from "node:fs/promises";
96414
- import { join as join49, posix as posix8 } from "node:path";
96918
+ import { mkdir as mkdir9, readFile as readFile13, rm as rm3, writeFile as writeFile7 } from "node:fs/promises";
96919
+ import { join as join50, posix as posix8 } from "node:path";
96415
96920
  init_repo_hosts();
96416
96921
  init_worktree_id();
96417
96922
  init_errors6();
@@ -96480,7 +96985,7 @@ init_remote_worktrees();
96480
96985
  init_repo_host_policy();
96481
96986
  init_ephemeral_lifecycle_service();
96482
96987
  import { existsSync as existsSync16 } from "node:fs";
96483
- import { basename as basename2, join as join48, posix as posix7, resolve as resolve9 } from "node:path";
96988
+ import { basename as basename2, join as join49, posix as posix7, resolve as resolve9 } from "node:path";
96484
96989
 
96485
96990
  // src/server/services/repo-avatar-service.ts
96486
96991
  init_src3();
@@ -96488,8 +96993,8 @@ init_git_client();
96488
96993
  init_src();
96489
96994
  init_repos();
96490
96995
  init_settings();
96491
- import { mkdir as mkdir8, readFile as readFile10, rename as rename4, writeFile as writeFile6 } from "node:fs/promises";
96492
- import { join as join47 } from "node:path";
96996
+ import { mkdir as mkdir8, readFile as readFile12, rename as rename4, writeFile as writeFile6 } from "node:fs/promises";
96997
+ import { join as join48 } from "node:path";
96493
96998
 
96494
96999
  // src/server/infra/github/github-client.ts
96495
97000
  var FETCH_TIMEOUT_MS2 = 1e4;
@@ -96639,7 +97144,7 @@ var RepoAvatarService = class {
96639
97144
  return null;
96640
97145
  }
96641
97146
  await mkdir8(cacheDir(), { recursive: true });
96642
- const imagePath = join47(cacheDir(), `${key2}.img`);
97147
+ const imagePath = join48(cacheDir(), `${key2}.img`);
96643
97148
  await writeFile6(`${imagePath}.tmp`, result.bytes);
96644
97149
  await rename4(`${imagePath}.tmp`, imagePath);
96645
97150
  await this.writeMeta(key2, entry, {
@@ -96657,7 +97162,7 @@ var RepoAvatarService = class {
96657
97162
  async readCached(key2, meta3) {
96658
97163
  if (meta3?.status !== "ok" || !meta3.contentType) return null;
96659
97164
  try {
96660
- const bytes = await readFile10(join47(cacheDir(), `${key2}.img`));
97165
+ const bytes = await readFile12(join48(cacheDir(), `${key2}.img`));
96661
97166
  return { bytes, contentType: meta3.contentType };
96662
97167
  } catch {
96663
97168
  return null;
@@ -96667,7 +97172,7 @@ var RepoAvatarService = class {
96667
97172
  entry.meta = meta3;
96668
97173
  entry.retryAfter = 0;
96669
97174
  await mkdir8(cacheDir(), { recursive: true });
96670
- await writeFile6(join47(cacheDir(), `${key2}.json`), JSON.stringify(meta3));
97175
+ await writeFile6(join48(cacheDir(), `${key2}.json`), JSON.stringify(meta3));
96671
97176
  }
96672
97177
  /** In-memory view of one owner's cache sidecar, loaded from disk once. */
96673
97178
  async entry(ref) {
@@ -96676,7 +97181,7 @@ var RepoAvatarService = class {
96676
97181
  if (entry) return entry;
96677
97182
  let meta3 = null;
96678
97183
  try {
96679
- meta3 = JSON.parse(await readFile10(join47(cacheDir(), `${key2}.json`), "utf-8"));
97184
+ meta3 = JSON.parse(await readFile12(join48(cacheDir(), `${key2}.json`), "utf-8"));
96680
97185
  } catch {
96681
97186
  }
96682
97187
  entry = this.entries.get(key2) ?? { meta: meta3, retryAfter: 0 };
@@ -96698,7 +97203,7 @@ var RepoAvatarService = class {
96698
97203
  }
96699
97204
  };
96700
97205
  function cacheDir() {
96701
- return join47(bandHome(), "cache", "github-avatars");
97206
+ return join48(bandHome(), "cache", "github-avatars");
96702
97207
  }
96703
97208
  function cacheKey(ref) {
96704
97209
  return `${ref.host.replace(/[^a-z0-9.-]/g, "_")}__${ref.owner.toLowerCase()}`;
@@ -96868,7 +97373,7 @@ var RepoService = class {
96868
97373
  throw new Error(`Repo "${name5}" already registered`);
96869
97374
  }
96870
97375
  const resolvedPath = resolve9(path2);
96871
- const kind = existsSync16(join48(resolvedPath, ".git")) ? "git" : "plain";
97376
+ const kind = existsSync16(join49(resolvedPath, ".git")) ? "git" : "plain";
96872
97377
  let defaultBranch = "main";
96873
97378
  let worktrees2 = [];
96874
97379
  if (kind === "git") {
@@ -97503,10 +98008,10 @@ function sessionsHashOf(files) {
97503
98008
  }
97504
98009
  return hash2.digest("hex");
97505
98010
  }
97506
- async function retryRefLock(run3) {
98011
+ async function retryRefLock(run4) {
97507
98012
  for (let attempt = 1; ; attempt++) {
97508
98013
  try {
97509
- return await run3();
98014
+ return await run4();
97510
98015
  } catch (err) {
97511
98016
  if (attempt >= 4 || !/cannot lock ref/i.test(errorText3(err))) throw err;
97512
98017
  await new Promise((r) => setTimeout(r, 50 * attempt));
@@ -97614,13 +98119,13 @@ var CheckpointService = class {
97614
98119
  */
97615
98120
  take(worktreeId4, trigger, opts = {}) {
97616
98121
  const previous = this.inflight.get(worktreeId4) ?? Promise.resolve();
97617
- const run3 = previous.catch(() => void 0).then(() => this.doTake(worktreeId4, trigger, opts));
97618
- this.inflight.set(worktreeId4, run3);
98122
+ const run4 = previous.catch(() => void 0).then(() => this.doTake(worktreeId4, trigger, opts));
98123
+ this.inflight.set(worktreeId4, run4);
97619
98124
  const clear = () => {
97620
- if (this.inflight.get(worktreeId4) === run3) this.inflight.delete(worktreeId4);
98125
+ if (this.inflight.get(worktreeId4) === run4) this.inflight.delete(worktreeId4);
97621
98126
  };
97622
- run3.then(clear, clear);
97623
- return run3;
98127
+ run4.then(clear, clear);
98128
+ return run4;
97624
98129
  }
97625
98130
  async takeAllOn(hostId2, trigger) {
97626
98131
  let stored = 0;
@@ -97733,12 +98238,12 @@ var CheckpointService = class {
97733
98238
  try {
97734
98239
  await mkdir9(dir, { recursive: true, mode: 448 });
97735
98240
  if (hasBundle) {
97736
- await writeFile7(join49(dir, "bundle.pack"), await host.fs.readFile(remoteBundle), {
98241
+ await writeFile7(join50(dir, "bundle.pack"), await host.fs.readFile(remoteBundle), {
97737
98242
  mode: 384
97738
98243
  });
97739
98244
  }
97740
98245
  if (sessionsJson)
97741
- await writeFile7(join49(dir, "sessions.json"), sessionsJson, { mode: 384 });
98246
+ await writeFile7(join50(dir, "sessions.json"), sessionsJson, { mode: 384 });
97742
98247
  } catch (err) {
97743
98248
  await rm3(dir, { recursive: true, force: true }).catch(() => void 0);
97744
98249
  throw new CheckpointError(
@@ -97856,7 +98361,7 @@ var CheckpointService = class {
97856
98361
  }
97857
98362
  await this.withViewLock(
97858
98363
  worktreeId4,
97859
- () => rm3(join49(worktreeCheckpointDir(worktreeId4), "view.git"), {
98364
+ () => rm3(join50(worktreeCheckpointDir(worktreeId4), "view.git"), {
97860
98365
  recursive: true,
97861
98366
  force: true
97862
98367
  }).catch(() => void 0)
@@ -97929,8 +98434,8 @@ ${diff}`).digest("hex");
97929
98434
  /** Builds and removals of one worktree's view repo run one at a time, because parallel fetches into a bare repo can fail on ref locks. */
97930
98435
  withViewLock(worktreeId4, fn) {
97931
98436
  const previous = this.viewLocks.get(worktreeId4) ?? Promise.resolve();
97932
- const run3 = previous.then(fn, fn);
97933
- const tail = run3.then(
98437
+ const run4 = previous.then(fn, fn);
98438
+ const tail = run4.then(
97934
98439
  () => void 0,
97935
98440
  () => void 0
97936
98441
  );
@@ -97938,11 +98443,11 @@ ${diff}`).digest("hex");
97938
98443
  void tail.then(() => {
97939
98444
  if (this.viewLocks.get(worktreeId4) === tail) this.viewLocks.delete(worktreeId4);
97940
98445
  });
97941
- return run3;
98446
+ return run4;
97942
98447
  }
97943
98448
  async buildViewRepo(worktreeId4, row) {
97944
98449
  const local = hostRegistry.local;
97945
- const dir = join49(worktreeCheckpointDir(worktreeId4), "view.git");
98450
+ const dir = join50(worktreeCheckpointDir(worktreeId4), "view.git");
97946
98451
  const git2 = gitIn(local, dir);
97947
98452
  await mkdir9(dir, { recursive: true, mode: 448 });
97948
98453
  const hasRef = async () => git2(["cat-file", "-e", `${row.snapshotSha}^{commit}`]).then(
@@ -97968,7 +98473,7 @@ ${diff}`).digest("hex");
97968
98473
  "fetch",
97969
98474
  "-q",
97970
98475
  "--force",
97971
- join49(checkpointDir(worktreeId4, r.id), "bundle.pack"),
98476
+ join50(checkpointDir(worktreeId4, r.id), "bundle.pack"),
97972
98477
  `refs/band/wip/${worktreeId4}:refs/checkpoints/${r.id}`
97973
98478
  ]).catch((err) => {
97974
98479
  log58.debug(
@@ -98213,7 +98718,7 @@ ${diff}`).digest("hex");
98213
98718
  const bundle = posix8.join(wipDir, `${newId}.restore.bundle`);
98214
98719
  await host.fs.writeFile(
98215
98720
  bundle,
98216
- await readFile11(join49(checkpointDir(worktreeId4, row.id), "bundle.pack"))
98721
+ await readFile13(join50(checkpointDir(worktreeId4, row.id), "bundle.pack"))
98217
98722
  );
98218
98723
  try {
98219
98724
  await retryRefLock(
@@ -98355,7 +98860,7 @@ ${diff}`).digest("hex");
98355
98860
  let files;
98356
98861
  try {
98357
98862
  files = JSON.parse(
98358
- await readFile11(join49(checkpointDir(row.worktreeId, row.id), "sessions.json"), "utf8")
98863
+ await readFile13(join50(checkpointDir(row.worktreeId, row.id), "sessions.json"), "utf8")
98359
98864
  ).files;
98360
98865
  } catch (err) {
98361
98866
  log58.warn(
@@ -99075,9 +99580,9 @@ var FollowService = class {
99075
99580
  continueOn(input3) {
99076
99581
  const running = this.inflight.get(input3.worktreeId);
99077
99582
  if (running) return running;
99078
- const run3 = this.doContinue(input3).finally(() => this.inflight.delete(input3.worktreeId));
99079
- this.inflight.set(input3.worktreeId, run3);
99080
- return run3;
99583
+ const run4 = this.doContinue(input3).finally(() => this.inflight.delete(input3.worktreeId));
99584
+ this.inflight.set(input3.worktreeId, run4);
99585
+ return run4;
99081
99586
  }
99082
99587
  async doContinue(input3) {
99083
99588
  const { worktreeId: worktreeId4 } = input3;
@@ -100314,7 +100819,7 @@ var cidrv43 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5
100314
100819
  var cidrv63 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
100315
100820
  var base643 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
100316
100821
  var base64url3 = /^[A-Za-z0-9_-]*$/;
100317
- var hostname5 = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
100822
+ var hostname6 = /^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+$/;
100318
100823
  var e1643 = /^\+(?:[0-9]){6,14}[0-9]$/;
100319
100824
  var dateSource2 = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
100320
100825
  var date6 = /* @__PURE__ */ new RegExp(`^${dateSource2}$`);
@@ -100927,7 +101432,7 @@ var $ZodURL2 = /* @__PURE__ */ $constructor2("$ZodURL", (inst, def) => {
100927
101432
  code: "invalid_format",
100928
101433
  format: "url",
100929
101434
  note: "Invalid hostname",
100930
- pattern: hostname5.source,
101435
+ pattern: hostname6.source,
100931
101436
  input: payload.value,
100932
101437
  inst,
100933
101438
  continue: !def.abort
@@ -111423,8 +111928,6 @@ var agentSessionsRouter = t.router({
111423
111928
  // src/server/api/browser-host/router.ts
111424
111929
  init_src();
111425
111930
  init_zod();
111426
- import { constants as fsConstants, open as open3 } from "node:fs/promises";
111427
- import { extname as extname2, isAbsolute as isAbsolute3 } from "node:path";
111428
111931
 
111429
111932
  // src/server/infra/browser-host/host-state.ts
111430
111933
  init_src();
@@ -111560,123 +112063,6 @@ var browserHostService = new BrowserHostService();
111560
112063
 
111561
112064
  // src/server/api/browser-host/router.ts
111562
112065
  var log63 = createLogger("trpc.browser-host");
111563
- var MAX_FILE_SIZE = 1024 * 1024;
111564
- var LANG_MAP = {
111565
- ".js": "javascript",
111566
- ".jsx": "jsx",
111567
- ".ts": "typescript",
111568
- ".tsx": "tsx",
111569
- ".mjs": "javascript",
111570
- ".cjs": "javascript",
111571
- ".json": "json",
111572
- ".html": "html",
111573
- ".css": "css",
111574
- ".scss": "scss",
111575
- ".md": "markdown",
111576
- ".yaml": "yaml",
111577
- ".yml": "yaml",
111578
- ".toml": "toml",
111579
- ".py": "python",
111580
- ".rb": "ruby",
111581
- ".rs": "rust",
111582
- ".go": "go",
111583
- ".java": "java",
111584
- ".swift": "swift",
111585
- ".c": "c",
111586
- ".cpp": "cpp",
111587
- ".sh": "bash",
111588
- ".sql": "sql",
111589
- ".graphql": "graphql",
111590
- ".vue": "vue",
111591
- ".svelte": "svelte",
111592
- ".diff": "diff"
111593
- };
111594
- function mapFsError(err) {
111595
- const code = err.code;
111596
- if (code === "ENOENT") return new Error("File not found");
111597
- if (code === "ELOOP") return new Error("Symbolic links are not allowed");
111598
- if (code === "EACCES" || code === "EPERM") return new Error("Permission denied");
111599
- if (code === "EISDIR") return new Error("Cannot operate on a directory");
111600
- return err instanceof Error ? err : new Error(String(err));
111601
- }
111602
- var hostRouter = t.router({
111603
- readFile: publicProcedure.input(external_exports2.object({ absolutePath: external_exports2.string().min(1) })).query(async ({ input: input3 }) => {
111604
- const target = input3.absolutePath;
111605
- if (!isAbsolute3(target)) {
111606
- throw new Error("Absolute path required");
111607
- }
111608
- let fh;
111609
- try {
111610
- fh = await open3(target, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
111611
- } catch (err) {
111612
- throw mapFsError(err);
111613
- }
111614
- try {
111615
- const stats = await fh.stat();
111616
- if (stats.isDirectory()) {
111617
- throw new Error("Cannot operate on a directory");
111618
- }
111619
- if (!stats.isFile()) {
111620
- throw new Error("Not a regular file");
111621
- }
111622
- const size = stats.size;
111623
- if (size > MAX_FILE_SIZE) {
111624
- return { tooLarge: true, size };
111625
- }
111626
- const sampleLen = Math.min(8192, size);
111627
- const sample = Buffer.alloc(sampleLen);
111628
- if (sampleLen > 0) {
111629
- await fh.read(sample, 0, sampleLen, 0);
111630
- if (sample.includes(0)) {
111631
- return { binary: true, size };
111632
- }
111633
- }
111634
- const buffer = await fh.readFile();
111635
- const ext = extname2(target).toLowerCase();
111636
- const language = LANG_MAP[ext];
111637
- return {
111638
- content: buffer.toString("utf-8"),
111639
- size,
111640
- language
111641
- };
111642
- } finally {
111643
- await fh.close();
111644
- }
111645
- }),
111646
- saveFile: publicProcedure.input(
111647
- external_exports2.object({
111648
- absolutePath: external_exports2.string().min(1),
111649
- // Match the read-side cap so a misbehaving client can't fill
111650
- // disk via the save endpoint while the read endpoint refuses
111651
- // anything that wide.
111652
- content: external_exports2.string().max(MAX_FILE_SIZE)
111653
- })
111654
- ).mutation(async ({ input: input3 }) => {
111655
- const target = input3.absolutePath;
111656
- if (!isAbsolute3(target)) {
111657
- throw new Error("Absolute path required");
111658
- }
111659
- let fh;
111660
- try {
111661
- fh = await open3(
111662
- target,
111663
- fsConstants.O_WRONLY | fsConstants.O_TRUNC | fsConstants.O_NOFOLLOW
111664
- );
111665
- } catch (err) {
111666
- throw mapFsError(err);
111667
- }
111668
- try {
111669
- const stats = await fh.stat();
111670
- if (!stats.isFile()) {
111671
- throw new Error("Not a regular file");
111672
- }
111673
- await fh.writeFile(input3.content, "utf-8");
111674
- } finally {
111675
- await fh.close();
111676
- }
111677
- return { ok: true };
111678
- })
111679
- });
111680
112066
  var browserHostRouter = t.router({
111681
112067
  // Diagnostic: the desktop's BrowserHostBridge calls this on mount so we
111682
112068
  // can confirm in the server log that the bridge component actually
@@ -112434,7 +112820,7 @@ init_zod();
112434
112820
  // src/server/services/cli-service.ts
112435
112821
  init_cli_binary();
112436
112822
  init_local_host_enabled();
112437
- import { execFile as execFile15 } from "node:child_process";
112823
+ import { execFile as execFile17 } from "node:child_process";
112438
112824
  import {
112439
112825
  accessSync as accessSync3,
112440
112826
  constants as constants3,
@@ -112448,12 +112834,12 @@ import {
112448
112834
  writeFileSync as writeFileSync7
112449
112835
  } from "node:fs";
112450
112836
  import { homedir as homedir17, platform as platform2 } from "node:os";
112451
- import { basename as basename3, dirname as dirname14, join as join50 } from "node:path";
112837
+ import { basename as basename3, dirname as dirname14, join as join51 } from "node:path";
112452
112838
  function windowsBinDir() {
112453
- const localAppData = process.env.LOCALAPPDATA || join50(homedir17(), "AppData", "Local");
112454
- return join50(localAppData, "band", "bin");
112839
+ const localAppData = process.env.LOCALAPPDATA || join51(homedir17(), "AppData", "Local");
112840
+ return join51(localAppData, "band", "bin");
112455
112841
  }
112456
- var SYMLINK_PATH = platform2() === "win32" ? join50(windowsBinDir(), "band.cmd") : "/usr/local/bin/band";
112842
+ var SYMLINK_PATH = platform2() === "win32" ? join51(windowsBinDir(), "band.cmd") : "/usr/local/bin/band";
112457
112843
  function symlinkPath() {
112458
112844
  if (platform2() === "win32") return SYMLINK_PATH;
112459
112845
  return process.env.BAND_CLI_SYMLINK_PATH?.trim() || SYMLINK_PATH;
@@ -112482,8 +112868,8 @@ async function checkCli() {
112482
112868
  }
112483
112869
  const linkPath = symlinkPath();
112484
112870
  try {
112485
- const stat8 = lstatSync4(linkPath);
112486
- if (!stat8.isSymbolicLink()) {
112871
+ const stat9 = lstatSync4(linkPath);
112872
+ if (!stat9.isSymbolicLink()) {
112487
112873
  return "ConflictingBinary";
112488
112874
  }
112489
112875
  let target;
@@ -112492,8 +112878,8 @@ async function checkCli() {
112492
112878
  } catch {
112493
112879
  return "NotInstalled";
112494
112880
  }
112495
- const isCargoBuild = target.includes(join50("apps", "cli", "target"));
112496
- const isElectronSidecar = target.endsWith(join50("binaries", "band"));
112881
+ const isCargoBuild = target.includes(join51("apps", "cli", "target"));
112882
+ const isElectronSidecar = target.endsWith(join51("binaries", "band"));
112497
112883
  if (isCargoBuild || isElectronSidecar) {
112498
112884
  return "Installed";
112499
112885
  }
@@ -112543,7 +112929,7 @@ function noBinaryError(env = process.env) {
112543
112929
  }
112544
112930
  function runReg(args) {
112545
112931
  return new Promise((resolve16) => {
112546
- execFile15("reg", args, { windowsHide: true }, (err, stdout) => {
112932
+ execFile17("reg", args, { windowsHide: true }, (err, stdout) => {
112547
112933
  resolve16(err ? "" : stdout ?? "");
112548
112934
  });
112549
112935
  });
@@ -112757,7 +113143,7 @@ function formatFileLocation(filePath, line2, options) {
112757
113143
 
112758
113144
  // ../../packages/worktree-ops/src/resolve-path.ts
112759
113145
  init_resolver();
112760
- import { isAbsolute as isAbsolute4, join as join51, resolve as resolve10, sep as sep6 } from "node:path";
113146
+ import { isAbsolute as isAbsolute3, join as join52, resolve as resolve10, sep as sep6 } from "node:path";
112761
113147
  var PathsService = class {
112762
113148
  constructor(worktrees2) {
112763
113149
  this.worktrees = worktrees2;
@@ -112775,7 +113161,7 @@ var PathsService = class {
112775
113161
  }
112776
113162
  };
112777
113163
  async function resolveTarget(fs3, root, filePath) {
112778
- const absoluteTarget = isAbsolute4(filePath) ? resolve10(filePath) : resolve10(root, filePath);
113164
+ const absoluteTarget = isAbsolute3(filePath) ? resolve10(filePath) : resolve10(root, filePath);
112779
113165
  let canonicalRoot = root;
112780
113166
  try {
112781
113167
  canonicalRoot = await fs3.realpath(root);
@@ -112808,7 +113194,7 @@ async function canonicalizeMaybeMissing(fs3, p2) {
112808
113194
  const prefix = parts.slice(0, i).join(sep6) || sep6;
112809
113195
  try {
112810
113196
  const canonicalPrefix = await fs3.realpath(prefix);
112811
- return join51(canonicalPrefix, ...parts.slice(i));
113197
+ return join52(canonicalPrefix, ...parts.slice(i));
112812
113198
  } catch {
112813
113199
  }
112814
113200
  }
@@ -112890,10 +113276,10 @@ async function pumpChanges(worktreeId4, entry, host, root) {
112890
113276
  for (const listener of entry.listeners) listener(null);
112891
113277
  stopWatcher(worktreeId4, entry);
112892
113278
  }
112893
- function subscribeToFileChanges(worktreeId4, open4, listener) {
113279
+ function subscribeToFileChanges(worktreeId4, open3, listener) {
112894
113280
  let entry = watchers.get(worktreeId4);
112895
113281
  if (!entry) {
112896
- const target = open4();
113282
+ const target = open3();
112897
113283
  if (!target) return () => {
112898
113284
  };
112899
113285
  entry = { controller: new AbortController(), listeners: /* @__PURE__ */ new Set(), pendingTimers: /* @__PURE__ */ new Map() };
@@ -112924,7 +113310,7 @@ function subscribeToFileChanges2(worktreeId4, listener) {
112924
113310
  // src/server/services/formatter.ts
112925
113311
  init_src();
112926
113312
  init_registry();
112927
- import { basename as basename4, dirname as dirname15, isAbsolute as isAbsolute5, join as join52, resolve as resolvePath3 } from "node:path";
113313
+ import { basename as basename4, dirname as dirname15, isAbsolute as isAbsolute4, join as join53, resolve as resolvePath3 } from "node:path";
112928
113314
  import prettier from "prettier";
112929
113315
  var log65 = createLogger("formatter");
112930
113316
  var FormatterError = class extends Error {
@@ -112940,7 +113326,7 @@ var FormatterError = class extends Error {
112940
113326
  async function formatFile(worktreePath, filePath, content, options = {}) {
112941
113327
  const fs3 = options.fs ?? hostRegistry.local.fs;
112942
113328
  const onHub = fs3 === hostRegistry.local.fs;
112943
- const absFile = isAbsolute5(filePath) ? filePath : resolvePath3(worktreePath, filePath);
113329
+ const absFile = isAbsolute4(filePath) ? filePath : resolvePath3(worktreePath, filePath);
112944
113330
  if (!await isInsideWorktree(fs3, absFile, worktreePath)) {
112945
113331
  throw new FormatterError(
112946
113332
  "FILE_NOT_IN_WORKTREE",
@@ -113006,10 +113392,10 @@ async function resolveConfigOnHost(fs3, absFile, worktreePath) {
113006
113392
  let dir = dirname15(absFile);
113007
113393
  for (; ; ) {
113008
113394
  for (const name5 of JSON_CONFIGS) {
113009
- const parsed = await readJson2(fs3, join52(dir, name5));
113395
+ const parsed = await readJson2(fs3, join53(dir, name5));
113010
113396
  if (parsed && typeof parsed === "object") return withoutPlugins(parsed);
113011
113397
  }
113012
- const pkg = await readJson2(fs3, join52(dir, "package.json"));
113398
+ const pkg = await readJson2(fs3, join53(dir, "package.json"));
113013
113399
  if (pkg && typeof pkg.prettier === "object" && pkg.prettier !== null) {
113014
113400
  return withoutPlugins(pkg.prettier);
113015
113401
  }
@@ -113047,7 +113433,7 @@ async function isInsideWorktree(fs3, absFile, worktreePath) {
113047
113433
  realFile = await fs3.realpath(absFile);
113048
113434
  } catch {
113049
113435
  try {
113050
- realFile = join52(await fs3.realpath(dirname15(absFile)), basename4(absFile));
113436
+ realFile = join53(await fs3.realpath(dirname15(absFile)), basename4(absFile));
113051
113437
  } catch {
113052
113438
  realFile = absFile;
113053
113439
  }
@@ -113230,7 +113616,7 @@ init_environment_build_service();
113230
113616
  init_src6();
113231
113617
  init_dist();
113232
113618
  init_registry();
113233
- import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute6 } from "node:path";
113619
+ import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute5 } from "node:path";
113234
113620
  init_token_service();
113235
113621
  var EnvironmentService = class {
113236
113622
  /** The environment of a repo's main checkout, and which hosts meet its `requires`. */
@@ -113245,7 +113631,7 @@ var EnvironmentService = class {
113245
113631
  * name the `.band/environment.json` file itself.
113246
113632
  */
113247
113633
  async validatePath(path2) {
113248
- if (!isAbsolute6(path2)) {
113634
+ if (!isAbsolute5(path2)) {
113249
113635
  throw new TRPCError({ code: "BAD_REQUEST", message: "path must be absolute" });
113250
113636
  }
113251
113637
  const isFile2 = basename5(path2) === "environment.json" && basename5(dirname16(path2)) === ".band";
@@ -113306,8 +113692,8 @@ init_http_files();
113306
113692
  init_settings();
113307
113693
  import { createHash as createHash13, randomBytes as randomBytes16 } from "node:crypto";
113308
113694
  import { createReadStream as createReadStream4 } from "node:fs";
113309
- import { mkdir as mkdir10, readdir as readdir7, readFile as readFile12, realpath as realpath4, rename as rename5, rm as rm4, stat as stat7, writeFile as writeFile8 } from "node:fs/promises";
113310
- import { dirname as dirname17, join as join53, sep as sep7 } from "node:path";
113695
+ import { mkdir as mkdir10, readdir as readdir9, readFile as readFile14, realpath as realpath4, rename as rename5, rm as rm4, stat as stat8, writeFile as writeFile8 } from "node:fs/promises";
113696
+ import { dirname as dirname17, join as join54, sep as sep7 } from "node:path";
113311
113697
 
113312
113698
  // src/server/services/_utils/tar-extract.ts
113313
113699
  import { gunzipSync } from "node:zlib";
@@ -113413,7 +113799,7 @@ var ExtensionService = class {
113413
113799
  /** Counts scans started. Only the newest scan may replace `loaded`. */
113414
113800
  scanSeq = 0;
113415
113801
  root() {
113416
- return join53(bandHome(), "extensions");
113802
+ return join54(bandHome(), "extensions");
113417
113803
  }
113418
113804
  /** Reads every manifest again. A manifest that fails validation is skipped and listed as an error. */
113419
113805
  async reload() {
@@ -113443,7 +113829,7 @@ var ExtensionService = class {
113443
113829
  const errors = [];
113444
113830
  let folders;
113445
113831
  try {
113446
- folders = (await readdir7(this.root(), { withFileTypes: true })).filter((d) => (d.isDirectory() || d.isSymbolicLink()) && !d.name.startsWith(".")).map((d) => d.name).sort();
113832
+ folders = (await readdir9(this.root(), { withFileTypes: true })).filter((d) => (d.isDirectory() || d.isSymbolicLink()) && !d.name.startsWith(".")).map((d) => d.name).sort();
113447
113833
  } catch {
113448
113834
  return { extensions, errors };
113449
113835
  }
@@ -113454,7 +113840,7 @@ var ExtensionService = class {
113454
113840
  };
113455
113841
  let raw;
113456
113842
  try {
113457
- raw = await readFile12(join53(this.root(), folder, MANIFEST_FILE), "utf8");
113843
+ raw = await readFile14(join54(this.root(), folder, MANIFEST_FILE), "utf8");
113458
113844
  } catch {
113459
113845
  problem2(`${MANIFEST_FILE} not found`);
113460
113846
  continue;
@@ -113554,12 +113940,12 @@ var ExtensionService = class {
113554
113940
  }
113555
113941
  const root = this.root();
113556
113942
  const tag = randomBytes16(6).toString("hex");
113557
- const staging = join53(root, `.install-${tag}`);
113558
- const target = join53(root, folder);
113559
- const backup = join53(root, `.old-${tag}`);
113943
+ const staging = join54(root, `.install-${tag}`);
113944
+ const target = join54(root, folder);
113945
+ const backup = join54(root, `.old-${tag}`);
113560
113946
  try {
113561
113947
  for (const file3 of files) {
113562
- const dest = join53(staging, file3.path);
113948
+ const dest = join54(staging, file3.path);
113563
113949
  await mkdir10(dirname17(dest), { recursive: true });
113564
113950
  await writeFile8(dest, file3.data, { mode: 420 });
113565
113951
  }
@@ -113570,7 +113956,7 @@ var ExtensionService = class {
113570
113956
  } catch {
113571
113957
  }
113572
113958
  try {
113573
- await rename5(join53(staging, folder), target);
113959
+ await rename5(join54(staging, folder), target);
113574
113960
  } catch (err) {
113575
113961
  if (hadOld) await rename5(backup, target).catch(() => {
113576
113962
  });
@@ -113588,9 +113974,9 @@ var ExtensionService = class {
113588
113974
  async remove(id) {
113589
113975
  if (!ID_PATTERN.test(id))
113590
113976
  throw new ExtensionInstallError(`"${id}" is not a valid extension id`);
113591
- const dir = join53(this.root(), id);
113977
+ const dir = join54(this.root(), id);
113592
113978
  try {
113593
- await stat7(dir);
113979
+ await stat8(dir);
113594
113980
  } catch {
113595
113981
  throw new ExtensionInstallError(`No extension "${id}" is installed`);
113596
113982
  }
@@ -113608,7 +113994,7 @@ var ExtensionService = class {
113608
113994
  if (segments.some((s2) => s2 === ".." || s2 === "." || s2 === "")) return void 0;
113609
113995
  let dir;
113610
113996
  try {
113611
- dir = await realpath4(join53(this.root(), id));
113997
+ dir = await realpath4(join54(this.root(), id));
113612
113998
  } catch {
113613
113999
  return void 0;
113614
114000
  }
@@ -113618,11 +114004,11 @@ var ExtensionService = class {
113618
114004
  if (/\bgzip\b/.test(acceptEncoding)) wanted.push({ suffix: ".gz", encoding: "gzip" });
113619
114005
  wanted.push({ suffix: "" });
113620
114006
  for (const { suffix, encoding } of wanted) {
113621
- const candidate = join53(dir, ...segments) + suffix;
114007
+ const candidate = join54(dir, ...segments) + suffix;
113622
114008
  try {
113623
114009
  const real4 = await realpath4(candidate);
113624
114010
  if (!real4.startsWith(dir + sep7)) return void 0;
113625
- const info = await stat7(real4);
114011
+ const info = await stat8(real4);
113626
114012
  if (!info.isFile()) continue;
113627
114013
  return { stream: createReadStream4(real4), size: info.size, contentType, encoding };
113628
114014
  } catch {
@@ -113696,9 +114082,9 @@ async function downloadChecksum(url3) {
113696
114082
  var extensionService = new ExtensionService();
113697
114083
 
113698
114084
  // src/server/api/extensions/router.ts
113699
- async function refuse(run3) {
114085
+ async function refuse(run4) {
113700
114086
  try {
113701
- return await run3();
114087
+ return await run4();
113702
114088
  } catch (err) {
113703
114089
  if (err instanceof ExtensionInstallError) {
113704
114090
  throw new TRPCError({ code: "BAD_REQUEST", message: err.message });
@@ -114345,7 +114731,7 @@ init_registry();
114345
114731
  // package.json
114346
114732
  var package_default = {
114347
114733
  name: "@band-app/server",
114348
- version: "0.58.0",
114734
+ version: "0.60.0",
114349
114735
  type: "module",
114350
114736
  types: "src/index.ts",
114351
114737
  exports: {
@@ -114637,7 +115023,7 @@ import {
114637
115023
  rmSync as rmSync7,
114638
115024
  writeFileSync as writeFileSync8
114639
115025
  } from "node:fs";
114640
- import { join as join54 } from "node:path";
115026
+ import { join as join55 } from "node:path";
114641
115027
  init_settings();
114642
115028
  init_agent_session_service();
114643
115029
 
@@ -114745,10 +115131,10 @@ var HubUpdateError = class extends Error {
114745
115131
  };
114746
115132
  var HubUpdateService = class {
114747
115133
  runPath() {
114748
- return join54(bandHome(), "hub-update.json");
115134
+ return join55(bandHome(), "hub-update.json");
114749
115135
  }
114750
115136
  logPath() {
114751
- return join54(bandHome(), "hub-update.log");
115137
+ return join55(bandHome(), "hub-update.log");
114752
115138
  }
114753
115139
  read() {
114754
115140
  try {
@@ -114758,8 +115144,8 @@ var HubUpdateService = class {
114758
115144
  return null;
114759
115145
  }
114760
115146
  }
114761
- write(run3) {
114762
- writeFileSync8(this.runPath(), JSON.stringify(run3), { mode: 384 });
115147
+ write(run4) {
115148
+ writeFileSync8(this.runPath(), JSON.stringify(run4), { mode: 384 });
114763
115149
  }
114764
115150
  command() {
114765
115151
  const raw = settingsService.get().hubUpdate?.command;
@@ -114774,12 +115160,12 @@ var HubUpdateService = class {
114774
115160
  return "";
114775
115161
  }
114776
115162
  }
114777
- failed(run3, message) {
115163
+ failed(run4, message) {
114778
115164
  const tail = this.logTail();
114779
115165
  return {
114780
115166
  configured: this.command() !== null,
114781
115167
  state: "failed",
114782
- target: run3.target,
115168
+ target: run4.target,
114783
115169
  error: tail ? `${message}
114784
115170
  ${tail}` : message
114785
115171
  };
@@ -114787,21 +115173,21 @@ ${tail}` : message
114787
115173
  /** Where the run stands. Reads the state file, so it also answers after the hub restarted. */
114788
115174
  status() {
114789
115175
  const configured = this.command() !== null;
114790
- const run3 = this.read();
114791
- if (!run3) return { configured, state: "idle", target: null, error: null };
114792
- if ((compareVersions(HUB_VERSION, run3.target) ?? -1) >= 0) {
115176
+ const run4 = this.read();
115177
+ if (!run4) return { configured, state: "idle", target: null, error: null };
115178
+ if ((compareVersions(HUB_VERSION, run4.target) ?? -1) >= 0) {
114793
115179
  rmSync7(this.runPath(), { force: true });
114794
115180
  return { configured, state: "idle", target: null, error: null };
114795
115181
  }
114796
- if (run3.failure) return this.failed(run3, run3.failure);
114797
- if (BOOT_AT > run3.startedAt) {
114798
- return this.failed(run3, `The hub restarted on ${HUB_VERSION}, not ${run3.target}.`);
115182
+ if (run4.failure) return this.failed(run4, run4.failure);
115183
+ if (BOOT_AT > run4.startedAt) {
115184
+ return this.failed(run4, `The hub restarted on ${HUB_VERSION}, not ${run4.target}.`);
114799
115185
  }
114800
115186
  const wait = Number(process.env.BAND_HUB_UPDATE_TIMEOUT_MS);
114801
- if (Date.now() - run3.startedAt > (wait > 0 ? wait : DEFAULT_TIMEOUT_MS2)) {
114802
- return this.failed(run3, `The hub did not come back on ${run3.target} in time.`);
115187
+ if (Date.now() - run4.startedAt > (wait > 0 ? wait : DEFAULT_TIMEOUT_MS2)) {
115188
+ return this.failed(run4, `The hub did not come back on ${run4.target} in time.`);
114803
115189
  }
114804
- return { configured, state: "updating", target: run3.target, error: null };
115190
+ return { configured, state: "updating", target: run4.target, error: null };
114805
115191
  }
114806
115192
  /**
114807
115193
  * The agents a hub restart ends, on every worker. A hub restart stops every agent it runs,
@@ -114829,8 +115215,8 @@ ${tail}` : message
114829
115215
  );
114830
115216
  }
114831
115217
  mkdirSync10(bandHome(), { recursive: true });
114832
- const run3 = { target, startedAt: Date.now() };
114833
- this.write(run3);
115218
+ const run4 = { target, startedAt: Date.now() };
115219
+ this.write(run4);
114834
115220
  const fd = openSync5(this.logPath(), "w", 384);
114835
115221
  try {
114836
115222
  writeFileSync8(fd, `$ ${command2}
@@ -114856,12 +115242,12 @@ ${tail}` : message
114856
115242
  env
114857
115243
  });
114858
115244
  child.on("error", (err) => {
114859
- this.write({ ...run3, failure: `The command could not start: ${err.message}` });
115245
+ this.write({ ...run4, failure: `The command could not start: ${err.message}` });
114860
115246
  });
114861
115247
  child.on("exit", (code, signal) => {
114862
115248
  if (code === 0) return;
114863
115249
  this.write({
114864
- ...run3,
115250
+ ...run4,
114865
115251
  failure: `The command ${signal ? `was stopped by ${signal}` : `exited with code ${code}`}.`
114866
115252
  });
114867
115253
  });
@@ -119012,10 +119398,10 @@ var pluginsRouter = t.router({
119012
119398
  });
119013
119399
 
119014
119400
  // ../../packages/host-local/src/process/install.ts
119015
- import { execFile as execFile16 } from "node:child_process";
119401
+ import { execFile as execFile18 } from "node:child_process";
119016
119402
  async function brewInstall(pkg, resolvedPath) {
119017
119403
  await new Promise((resolve16, reject) => {
119018
- execFile16(
119404
+ execFile18(
119019
119405
  "brew",
119020
119406
  ["install", pkg],
119021
119407
  { env: { ...process.env, PATH: resolvedPath }, timeout: 12e4 },
@@ -119150,7 +119536,7 @@ init_src();
119150
119536
  init_dist();
119151
119537
  import { createHash as createHash14, randomBytes as randomBytes17, randomUUID as randomUUID19 } from "node:crypto";
119152
119538
  import { createReadStream as createReadStream5, existsSync as existsSync19, mkdirSync as mkdirSync11, rmSync as rmSync8, statSync as statSync15 } from "node:fs";
119153
- import { join as join55 } from "node:path";
119539
+ import { join as join56 } from "node:path";
119154
119540
 
119155
119541
  // src/server/infra/db/queries/provisions.ts
119156
119542
  init_drizzle_orm2();
@@ -119470,8 +119856,8 @@ function sha2562(text4) {
119470
119856
  function newSecret(prefix) {
119471
119857
  return `${prefix}${randomBytes17(32).toString("base64url")}`;
119472
119858
  }
119473
- function isLoopbackHost2(hostname6) {
119474
- const h = hostname6.replace(/^\[|\]$/g, "").toLowerCase();
119859
+ function isLoopbackHost2(hostname7) {
119860
+ const h = hostname7.replace(/^\[|\]$/g, "").toLowerCase();
119475
119861
  return h === "localhost" || h === "::1" || /^127\.\d+\.\d+\.\d+$/.test(h);
119476
119862
  }
119477
119863
  function checkHubUrl(input3) {
@@ -119508,7 +119894,7 @@ var ProvisioningService = class {
119508
119894
  return Date.now();
119509
119895
  }
119510
119896
  dir(id) {
119511
- return join55(bandHome(), "provisioning", id);
119897
+ return join56(bandHome(), "provisioning", id);
119512
119898
  }
119513
119899
  settings() {
119514
119900
  const s2 = settingsService.get().provisioning ?? {};
@@ -119628,7 +120014,7 @@ var ProvisioningService = class {
119628
120014
  /** The bundle file and size for a code, once its run token is shown. */
119629
120015
  bundle(code, runToken) {
119630
120016
  const row = this.authorize(code, runToken);
119631
- const file3 = join55(this.dir(row.id), "bundle.tgz");
120017
+ const file3 = join56(this.dir(row.id), "bundle.tgz");
119632
120018
  if (!row.repoUrl || !existsSync19(file3)) throw new ProvisionAuthError();
119633
120019
  return { stream: createReadStream5(file3), size: statSync15(file3).size };
119634
120020
  }
@@ -119707,7 +120093,7 @@ band provision: the worker did not say hello within ${minutes} min. Marked faile
119707
120093
  async buildBundle(id, settings3) {
119708
120094
  const dir = this.dir(id);
119709
120095
  mkdirSync11(dir, { recursive: true });
119710
- const src = join55(dir, "src");
120096
+ const src = join56(dir, "src");
119711
120097
  const host = hostRegistry.local;
119712
120098
  const env = { GIT_TERMINAL_PROMPT: "0" };
119713
120099
  const key2 = parseRemoteUrl2(settings3.repoUrl);
@@ -119729,10 +120115,10 @@ band provision: the worker did not say hello within ${minutes} min. Marked faile
119729
120115
  await host.exec("git", args, { env, timeoutMs: 12e4 });
119730
120116
  const sha = (await host.exec("git", ["-C", src, "rev-parse", "HEAD"], { env })).stdout.trim();
119731
120117
  const command2 = settings3.command || DEFAULT_START_COMMAND;
119732
- if (!existsSync19(join55(src, command2))) {
120118
+ if (!existsSync19(join56(src, command2))) {
119733
120119
  throw new Error(`the repo at ${sha.slice(0, 12)} has no ${command2}`);
119734
120120
  }
119735
- await host.exec("tar", ["-czf", join55(dir, "bundle.tgz"), "--exclude=.git", "-C", src, "."], {
120121
+ await host.exec("tar", ["-czf", join56(dir, "bundle.tgz"), "--exclude=.git", "-C", src, "."], {
119736
120122
  timeoutMs: 12e4
119737
120123
  });
119738
120124
  rmSync8(src, { recursive: true, force: true });
@@ -119825,7 +120211,7 @@ init_zod();
119825
120211
  init_registry();
119826
120212
  init_queued_message_store();
119827
120213
  import { realpathSync as realpathSync6 } from "node:fs";
119828
- import { join as join56, resolve as resolve11, sep as sep8 } from "node:path";
120214
+ import { join as join57, resolve as resolve11, sep as sep8 } from "node:path";
119829
120215
  init_chat_ownership_service();
119830
120216
  init_chat_service();
119831
120217
  init_state();
@@ -119838,7 +120224,7 @@ var queuedFileSchema = external_exports2.object({
119838
120224
  filename: external_exports2.string().optional()
119839
120225
  });
119840
120226
  function isPathWithinUploadDir(p2) {
119841
- const uploadDir = join56(bandHome(), "uploads");
120227
+ const uploadDir = join57(bandHome(), "uploads");
119842
120228
  const normalized2 = resolve11(p2);
119843
120229
  if (normalized2 !== uploadDir && !normalized2.startsWith(uploadDir + sep8)) {
119844
120230
  return false;
@@ -120651,6 +121037,186 @@ var reposRouter = t.router({
120651
121037
  })
120652
121038
  });
120653
121039
 
121040
+ // src/server/api/resources/router.ts
121041
+ init_dist();
121042
+ init_zod();
121043
+
121044
+ // src/server/services/resources-service.ts
121045
+ init_worktree_id();
121046
+ init_registry();
121047
+ init_agent_session_service();
121048
+ init_chat_service();
121049
+ init_state();
121050
+ init_task_service();
121051
+ init_token_service();
121052
+ var LOCAL_HOST_ID13 = "local";
121053
+ var SNAPSHOT_TIMEOUT_MS = 8e3;
121054
+ var IDLE_AGENT_MS = 60 * 6e4;
121055
+ function withTimeout3(promise2, ms) {
121056
+ return new Promise((resolve16, reject) => {
121057
+ const timer = setTimeout(() => reject(new Error("timed out")), ms);
121058
+ promise2.then(
121059
+ (v2) => {
121060
+ clearTimeout(timer);
121061
+ resolve16(v2);
121062
+ },
121063
+ (e) => {
121064
+ clearTimeout(timer);
121065
+ reject(e);
121066
+ }
121067
+ );
121068
+ });
121069
+ }
121070
+ function knownWorktrees() {
121071
+ const out = [];
121072
+ for (const repo of loadState().repos) {
121073
+ for (const wt of repo.worktrees) {
121074
+ const hostId2 = wt.hostId ?? LOCAL_HOST_ID13;
121075
+ out.push({
121076
+ id: toWorktreeId(repo.name, wt.name, wt.hostId),
121077
+ repo: repo.name,
121078
+ branch: wt.branch,
121079
+ title: wt.title ?? null,
121080
+ hostId: hostId2,
121081
+ path: wt.path
121082
+ });
121083
+ }
121084
+ }
121085
+ return out;
121086
+ }
121087
+ function refOf(w2) {
121088
+ return { id: w2.id, repo: w2.repo, branch: w2.branch, title: w2.title };
121089
+ }
121090
+ function worktreeOf(proc, hostId2, worktrees2) {
121091
+ if (proc.worktreeId) {
121092
+ const byId = worktrees2.find((w2) => w2.id === proc.worktreeId);
121093
+ if (byId) return refOf(byId);
121094
+ }
121095
+ if (!proc.cwd) return void 0;
121096
+ const cwd = proc.cwd;
121097
+ let best;
121098
+ for (const w2 of worktrees2) {
121099
+ if (w2.hostId !== hostId2 || !w2.path) continue;
121100
+ if (cwd === w2.path || cwd.startsWith(`${w2.path}/`)) {
121101
+ if (!best || w2.path.length > best.path.length) best = w2;
121102
+ }
121103
+ }
121104
+ return best ? refOf(best) : void 0;
121105
+ }
121106
+ function chatOf(chatId, now) {
121107
+ if (!chatId) return void 0;
121108
+ const chat = chatService.get(chatId);
121109
+ if (!chat) return void 0;
121110
+ const running = hasRunningTask(chatId);
121111
+ const last = agentSessionService.lastActivityAt(chatId);
121112
+ const idleMs2 = last === null ? null : Math.max(0, now - last);
121113
+ return {
121114
+ id: chat.id,
121115
+ name: chat.name,
121116
+ agent: chat.agent,
121117
+ running,
121118
+ idleMs: idleMs2,
121119
+ idle: !running && idleMs2 !== null && idleMs2 >= IDLE_AGENT_MS
121120
+ };
121121
+ }
121122
+ function chatIdOf(p2, hostId2, pids) {
121123
+ if (p2.chatId) return p2.chatId;
121124
+ if (p2.kind !== "agent") return void 0;
121125
+ return pids.find(
121126
+ (a) => a.pid === p2.pid && (hostRegistry.hostIdOfScope(a.worktreeId) ?? LOCAL_HOST_ID13) === hostId2
121127
+ )?.chatId;
121128
+ }
121129
+ async function readMachine(host, builtInWorker, worktrees2, now, agentPids) {
121130
+ const isLocal = host.id === LOCAL_HOST_ID13;
121131
+ const base = {
121132
+ id: host.id,
121133
+ role: isLocal ? "hub" : "worker",
121134
+ name: isLocal ? "Hub" : host.name,
121135
+ version: host.version,
121136
+ builtInWorker: isLocal && builtInWorker,
121137
+ onBattery: null
121138
+ };
121139
+ if (!isLocal && host.status !== "online") {
121140
+ return { ...base, status: "unavailable", reason: "offline", snapshot: null };
121141
+ }
121142
+ try {
121143
+ const target = hostRegistry.hostById(host.id);
121144
+ const snap = await withTimeout3(target.resources.snapshot(), SNAPSHOT_TIMEOUT_MS);
121145
+ const processes = snap.processes.map((p2) => {
121146
+ const chatId = chatIdOf(p2, host.id, agentPids);
121147
+ const worktree = worktreeOf(
121148
+ chatId && !p2.worktreeId ? { ...p2, worktreeId: chatService.get(chatId)?.worktreeId ?? p2.worktreeId } : p2,
121149
+ host.id,
121150
+ worktrees2
121151
+ );
121152
+ const chat = chatOf(chatId, now);
121153
+ const { command: _command, cwd: _cwd, ...rest } = p2;
121154
+ return { ...rest, ...worktree ? { worktree } : {}, ...chat ? { chat } : {} };
121155
+ });
121156
+ return { ...base, status: "ok", reason: null, snapshot: { ...snap, processes } };
121157
+ } catch {
121158
+ return { ...base, status: "unavailable", reason: "no-answer", snapshot: null };
121159
+ }
121160
+ }
121161
+ async function listResources() {
121162
+ const now = Date.now();
121163
+ const worktrees2 = knownWorktrees();
121164
+ const agentPids = agentSessionService.agentPids();
121165
+ const hosts3 = tokenService.listHosts();
121166
+ const builtIn = hosts3.find((h) => h.id === LOCAL_HOST_ID13)?.usable ?? false;
121167
+ const wanted = hosts3.filter((h) => h.id !== LOCAL_HOST_ID13);
121168
+ const local = hosts3.find((h) => h.id === LOCAL_HOST_ID13) ?? {
121169
+ id: LOCAL_HOST_ID13,
121170
+ name: "Hub",
121171
+ version: null,
121172
+ status: "online"
121173
+ };
121174
+ const machines = await Promise.all(
121175
+ [local, ...wanted].map(
121176
+ (h) => readMachine(
121177
+ { id: h.id, name: h.name, version: h.version ?? null, status: h.status },
121178
+ builtIn,
121179
+ worktrees2,
121180
+ now,
121181
+ agentPids
121182
+ )
121183
+ )
121184
+ );
121185
+ return { takenAt: now, machines };
121186
+ }
121187
+ async function resourceStorage(hostId2) {
121188
+ const worktrees2 = knownWorktrees().filter((w2) => w2.hostId === hostId2 && w2.path);
121189
+ const host = hostRegistry.hostById(hostId2);
121190
+ const result = await host.resources.storage({
121191
+ worktrees: worktrees2.map((w2) => ({ id: w2.id, path: w2.path }))
121192
+ });
121193
+ const byId = new Map(worktrees2.map((w2) => [w2.id, w2]));
121194
+ return {
121195
+ worktrees: result.worktrees.flatMap((r) => {
121196
+ const w2 = byId.get(r.id);
121197
+ return w2 ? [{ ...refOf(w2), sizeBytes: r.sizeBytes, ...r.error ? { error: r.error } : {} }] : [];
121198
+ }),
121199
+ state: result.state,
121200
+ disk: result.disk
121201
+ };
121202
+ }
121203
+
121204
+ // src/server/api/resources/router.ts
121205
+ var resourcesRouter = t.router({
121206
+ snapshot: publicProcedure.query(() => listResources()),
121207
+ storage: publicProcedure.input(external_exports2.object({ hostId: external_exports2.string().min(1) })).query(async ({ input: input3 }) => {
121208
+ try {
121209
+ return await resourceStorage(input3.hostId);
121210
+ } catch (err) {
121211
+ console.error(`[resources] storage on ${input3.hostId} failed:`, err);
121212
+ throw new TRPCError({
121213
+ code: "SERVICE_UNAVAILABLE",
121214
+ message: `Could not measure storage on ${input3.hostId}`
121215
+ });
121216
+ }
121217
+ })
121218
+ });
121219
+
120654
121220
  // src/server/api/reviews/router.ts
120655
121221
  init_dist();
120656
121222
  init_zod();
@@ -120703,12 +121269,12 @@ function allowed(args) {
120703
121269
  var UNAUTHENTICATED2 = /gh auth login|GH_TOKEN|GITHUB_TOKEN|authentication|HTTP 401|bad credentials/i;
120704
121270
  var MISSING_GH = /ENOENT|command not found|executable file not found|no such file/i;
120705
121271
  var GH_TIMEOUT_MS2 = 3e4;
120706
- function withTimeout3(run3) {
121272
+ function withTimeout4(run4) {
120707
121273
  let timer;
120708
121274
  const timeout = new Promise((_2, reject) => {
120709
121275
  timer = setTimeout(() => reject(new Error("gh timed out")), GH_TIMEOUT_MS2);
120710
121276
  });
120711
- return Promise.race([run3, timeout]).finally(() => clearTimeout(timer));
121277
+ return Promise.race([run4, timeout]).finally(() => clearTimeout(timer));
120712
121278
  }
120713
121279
  function firstLine2(err) {
120714
121280
  return (err instanceof Error ? err.message : String(err)).split("\n")[0];
@@ -120735,17 +121301,17 @@ function fallbackGh(args, cwd) {
120735
121301
  function worktreeGh(host, localHostId, cwd) {
120736
121302
  return async (args) => {
120737
121303
  if (!allowed(args)) throw new Error(`gh ${args.slice(0, 2).join(" ")} is not allowed here`);
120738
- if (host.id === localHostId) return withTimeout3(localGh(args, cwd));
121304
+ if (host.id === localHostId) return withTimeout4(localGh(args, cwd));
120739
121305
  let hostError;
120740
121306
  try {
120741
- return (await withTimeout3(host.git.gh(args, cwd))).stdout;
121307
+ return (await withTimeout4(host.git.gh(args, cwd))).stdout;
120742
121308
  } catch (err) {
120743
121309
  if (err instanceof Error) err.message = err.message.trim();
120744
121310
  if (!hostCannotAnswer(err)) throw err;
120745
121311
  hostError = err;
120746
121312
  }
120747
121313
  try {
120748
- return await withTimeout3(fallbackGh(args, tmpdir5()));
121314
+ return await withTimeout4(fallbackGh(args, tmpdir5()));
120749
121315
  } catch (hubError) {
120750
121316
  if (!hostCannotAnswer(hubError)) throw hubError;
120751
121317
  throw new Error(
@@ -122559,7 +123125,7 @@ init_speech_transcription();
122559
123125
  init_registry();
122560
123126
  init_settings_service();
122561
123127
  init_vault_service();
122562
- var LOCAL_HOST_ID13 = "local";
123128
+ var LOCAL_HOST_ID14 = "local";
122563
123129
  function readConfig2() {
122564
123130
  return settingsService.get().voice ?? {};
122565
123131
  }
@@ -122609,7 +123175,7 @@ var VoiceService = class {
122609
123175
  }
122610
123176
  if (!config3.model?.trim()) throw new SpeechError("not_configured", "Enter a model first.");
122611
123177
  await this.send(config3, silentWav(1), "audio/wav");
122612
- return { ok: true, hostId: config3.hostId || LOCAL_HOST_ID13 };
123178
+ return { ok: true, hostId: config3.hostId || LOCAL_HOST_ID14 };
122613
123179
  }
122614
123180
  async send(config3, audio, mimeType) {
122615
123181
  if (audio.byteLength === 0) throw new SpeechError("bad_response", "The recording is empty.");
@@ -122622,7 +123188,7 @@ var VoiceService = class {
122622
123188
  const apiKey = await this.apiKey(config3.apiKeyItemId);
122623
123189
  try {
122624
123190
  const hostId2 = config3.hostId?.trim();
122625
- if (!hostId2 || hostId2 === LOCAL_HOST_ID13) {
123191
+ if (!hostId2 || hostId2 === LOCAL_HOST_ID14) {
122626
123192
  return await requestTranscription({ baseUrl, apiKey, model, language, audio, mimeType });
122627
123193
  }
122628
123194
  let host;
@@ -122633,7 +123199,7 @@ var VoiceService = class {
122633
123199
  }
122634
123200
  let result;
122635
123201
  try {
122636
- result = await withTimeout4(
123202
+ result = await withTimeout5(
122637
123203
  host.speech.transcribe({ baseUrl, apiKey, model, language, audio, mimeType }),
122638
123204
  WORKER_TRANSCRIBE_TIMEOUT_MS
122639
123205
  );
@@ -122678,7 +123244,7 @@ var VoiceService = class {
122678
123244
  function scrub2(message, apiKey) {
122679
123245
  return scrubSecrets(message, apiKey);
122680
123246
  }
122681
- function withTimeout4(promise2, ms) {
123247
+ function withTimeout5(promise2, ms) {
122682
123248
  let timer;
122683
123249
  const timeout = new Promise((_2, reject) => {
122684
123250
  timer = setTimeout(
@@ -122936,7 +123502,7 @@ function verifyWorktreePreviewGrant(worktreeId4, grant, filePath, now = Date.now
122936
123502
  init_src3();
122937
123503
  init_src();
122938
123504
  init_resolver();
122939
- import { join as join57, resolve as resolve12, sep as sep9 } from "node:path";
123505
+ import { join as join58, resolve as resolve12, sep as sep9 } from "node:path";
122940
123506
  var log82 = createLogger("diff-service");
122941
123507
  var EMPTY_TREE_ARGS = ["hash-object", "-t", "tree", "/dev/null"];
122942
123508
  var DEFAULT_BRANCH_LIMIT = 50;
@@ -123033,7 +123599,7 @@ function parseFileStatuses(nameStatusOutput) {
123033
123599
  return fileStatuses;
123034
123600
  }
123035
123601
  function assertWorktreeRelative(cwd, filePath) {
123036
- const target = resolve12(join57(cwd, filePath));
123602
+ const target = resolve12(join58(cwd, filePath));
123037
123603
  if (target !== cwd && !target.startsWith(cwd + sep9)) {
123038
123604
  throw new Error("Invalid path");
123039
123605
  }
@@ -123048,7 +123614,7 @@ function assertWorktreeRelative(cwd, filePath) {
123048
123614
  }
123049
123615
  async function readUntrackedFileLines(host, cwd, file3) {
123050
123616
  try {
123051
- const content = new TextDecoder().decode(await host.fs.readFile(join57(cwd, file3)));
123617
+ const content = new TextDecoder().decode(await host.fs.readFile(join58(cwd, file3)));
123052
123618
  const lines = content.split("\n");
123053
123619
  if (lines.length > 0 && lines[lines.length - 1] === "") {
123054
123620
  lines.pop();
@@ -123395,7 +123961,7 @@ var DiffService = class {
123395
123961
  const compareBranch = options.compareBranch ?? defaultBranch;
123396
123962
  const cwd = worktree.worktree.path;
123397
123963
  const execGit2 = gitRunner(worktree.host);
123398
- const hasGit = await worktree.host.fs.stat(join57(cwd, ".git")).then(
123964
+ const hasGit = await worktree.host.fs.stat(join58(cwd, ".git")).then(
123399
123965
  () => true,
123400
123966
  (err) => {
123401
123967
  if (err instanceof HostOfflineError || err instanceof HostTimeoutError) throw err;
@@ -123433,7 +123999,7 @@ var DiffService = class {
123433
123999
  applyLineCounts(status.staged, parseNumstat(stagedNumstat));
123434
124000
  await Promise.all(
123435
124001
  status.untracked.map(async (entry) => {
123436
- const lines = await countUntrackedLines(worktree.host, join57(cwd, entry.path));
124002
+ const lines = await countUntrackedLines(worktree.host, join58(cwd, entry.path));
123437
124003
  if (lines !== null) {
123438
124004
  entry.additions = lines;
123439
124005
  entry.deletions = 0;
@@ -123635,9 +124201,95 @@ var DirectAccessService = class {
123635
124201
  };
123636
124202
  var directAccessService = new DirectAccessService();
123637
124203
 
124204
+ // src/server/services/external-file-service.ts
124205
+ init_errors6();
124206
+ init_worktree_service();
124207
+ import { extname as extname2, isAbsolute as isAbsolute6 } from "node:path";
124208
+ var MAX_FILE_SIZE = 1024 * 1024;
124209
+ var LANG_MAP = {
124210
+ ".js": "javascript",
124211
+ ".jsx": "jsx",
124212
+ ".ts": "typescript",
124213
+ ".tsx": "tsx",
124214
+ ".mjs": "javascript",
124215
+ ".cjs": "javascript",
124216
+ ".json": "json",
124217
+ ".html": "html",
124218
+ ".css": "css",
124219
+ ".scss": "scss",
124220
+ ".md": "markdown",
124221
+ ".yaml": "yaml",
124222
+ ".yml": "yaml",
124223
+ ".toml": "toml",
124224
+ ".py": "python",
124225
+ ".rb": "ruby",
124226
+ ".rs": "rust",
124227
+ ".go": "go",
124228
+ ".java": "java",
124229
+ ".swift": "swift",
124230
+ ".c": "c",
124231
+ ".cpp": "cpp",
124232
+ ".sh": "bash",
124233
+ ".sql": "sql",
124234
+ ".graphql": "graphql",
124235
+ ".vue": "vue",
124236
+ ".svelte": "svelte",
124237
+ ".diff": "diff"
124238
+ };
124239
+ function hostFor2(worktreeId4) {
124240
+ const resolved = worktreeService.resolve(worktreeId4);
124241
+ if (!resolved) throw new WorktreeNotFoundError(worktreeId4);
124242
+ return resolved.host;
124243
+ }
124244
+ async function statFile(fs3, path2) {
124245
+ try {
124246
+ return await fs3.stat(path2);
124247
+ } catch (err) {
124248
+ const text4 = err instanceof Error ? `${err.code ?? ""} ${err.message}` : "";
124249
+ if (/ENOENT|no such file|not found/i.test(text4)) throw new Error("File not found");
124250
+ throw err;
124251
+ }
124252
+ }
124253
+ function assertAbsolute(path2) {
124254
+ if (!isAbsolute6(path2)) throw new Error("Absolute path required");
124255
+ }
124256
+ var ExternalFileService = class {
124257
+ async read(worktreeId4, absolutePath) {
124258
+ assertAbsolute(absolutePath);
124259
+ const { fs: fs3 } = hostFor2(worktreeId4);
124260
+ const stat9 = await statFile(fs3, absolutePath);
124261
+ if (stat9.kind === "symlink") throw new Error("Symbolic links are not allowed");
124262
+ if (stat9.kind === "directory") throw new Error("Cannot operate on a directory");
124263
+ if (stat9.kind !== "file") throw new Error("Not a regular file");
124264
+ if (stat9.size > MAX_FILE_SIZE) return { tooLarge: true, size: stat9.size };
124265
+ const bytes = await fs3.readFile(absolutePath);
124266
+ const buffer = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
124267
+ if (buffer.subarray(0, 8192).includes(0)) return { binary: true, size: stat9.size };
124268
+ return {
124269
+ content: buffer.toString("utf-8"),
124270
+ size: stat9.size,
124271
+ language: LANG_MAP[extname2(absolutePath).toLowerCase()]
124272
+ };
124273
+ }
124274
+ async save(worktreeId4, absolutePath, content) {
124275
+ assertAbsolute(absolutePath);
124276
+ if (Buffer.byteLength(content, "utf-8") > MAX_FILE_SIZE) throw new Error("File too large");
124277
+ const { fs: fs3 } = hostFor2(worktreeId4);
124278
+ const stat9 = await statFile(fs3, absolutePath);
124279
+ if (stat9.kind === "symlink") throw new Error("Symbolic links are not allowed");
124280
+ if (stat9.kind !== "file") throw new Error("Not a regular file");
124281
+ if (absolutePath.split(/[\\/]/).includes(".git")) {
124282
+ throw new Error("Refusing to write inside a .git folder");
124283
+ }
124284
+ await fs3.writeFile(absolutePath, content);
124285
+ return { ok: true };
124286
+ }
124287
+ };
124288
+ var externalFileService = new ExternalFileService();
124289
+
123638
124290
  // ../../packages/worktree-ops/src/files.ts
123639
124291
  init_resolver();
123640
- import { dirname as dirname18, extname as extname3, join as join58, resolve as resolve13, sep as sep10 } from "node:path";
124292
+ import { dirname as dirname18, extname as extname3, join as join59, resolve as resolve13, sep as sep10 } from "node:path";
123641
124293
  var MAX_FILE_SIZE2 = 1024 * 1024;
123642
124294
  var LANG_MAP2 = {
123643
124295
  ".js": "javascript",
@@ -123704,7 +124356,7 @@ var FilesService = class {
123704
124356
  throw new WorktreeNotFoundError(worktreeId4);
123705
124357
  }
123706
124358
  const root = worktree.worktree.path;
123707
- const target = resolve13(join58(root, relative2));
124359
+ const target = resolve13(join59(root, relative2));
123708
124360
  const insideRoot = target === root || target.startsWith(root + sep10);
123709
124361
  if (!insideRoot) {
123710
124362
  throw new Error("Invalid path");
@@ -125288,6 +125940,20 @@ var worktreeRouter = t.router({
125288
125940
  listFiles: publicProcedure.input(directOps["worktree.listFiles"].input).query(({ input: input3 }) => directOps["worktree.listFiles"].run(worktreeOps, input3)),
125289
125941
  getFile: publicProcedure.input(directOps["worktree.getFile"].input).query(({ input: input3 }) => directOps["worktree.getFile"].run(worktreeOps, input3)),
125290
125942
  saveFile: publicProcedure.input(directOps["worktree.saveFile"].input).mutation(({ input: input3 }) => directOps["worktree.saveFile"].run(worktreeOps, input3)),
125943
+ /**
125944
+ * A file outside the worktree, read on the worktree's own worker (never the
125945
+ * hub's disk). Left out of the relay and the direct path: device tokens only.
125946
+ */
125947
+ readExternalFile: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string().min(1), absolutePath: external_exports2.string().min(1) })).query(({ input: input3 }) => externalFileService.read(input3.worktreeId, input3.absolutePath)),
125948
+ saveExternalFile: publicProcedure.input(
125949
+ external_exports2.object({
125950
+ worktreeId: external_exports2.string().min(1),
125951
+ absolutePath: external_exports2.string().min(1),
125952
+ content: external_exports2.string()
125953
+ })
125954
+ ).mutation(
125955
+ ({ input: input3 }) => externalFileService.save(input3.worktreeId, input3.absolutePath, input3.content)
125956
+ ),
125291
125957
  createFile: publicProcedure.input(directOps["worktree.createFile"].input).mutation(({ input: input3 }) => directOps["worktree.createFile"].run(worktreeOps, input3)),
125292
125958
  createDirectory: publicProcedure.input(directOps["worktree.createDirectory"].input).mutation(({ input: input3 }) => directOps["worktree.createDirectory"].run(worktreeOps, input3)),
125293
125959
  deletePath: publicProcedure.input(directOps["worktree.deletePath"].input).mutation(({ input: input3 }) => directOps["worktree.deletePath"].run(worktreeOps, input3)),
@@ -125312,7 +125978,7 @@ var worktreeRouter = t.router({
125312
125978
  // path an authenticated caller supplies (not just in-worktree ones), so it
125313
125979
  // is a filesystem-existence oracle. That is acceptable under Band's threat
125314
125980
  // model — the same auth scope already reads arbitrary absolute paths via
125315
- // `host.readFile` — and the `external` flag is load-bearing, not dead code:
125981
+ // `worktree.readExternalFile` — and the `external` flag is load-bearing, not dead code:
125316
125982
  // it's how the client decides between a worktree-relative and an external
125317
125983
  // tab. Do not "harden" this by dropping the out-of-worktree classification.
125318
125984
  resolvePath: publicProcedure.input(resolvePathInput).query(
@@ -125448,8 +126114,8 @@ var appRouter = t.router({
125448
126114
  ...terminalsRouters,
125449
126115
  cli: cliRouter,
125450
126116
  accountUsage: accountUsageRouter,
126117
+ resources: resourcesRouter,
125451
126118
  hooks: hooksRouter,
125452
- host: hostRouter,
125453
126119
  workers: hostsRouter,
125454
126120
  // Old name, kept for desktop, mobile and CLI builds that still call it.
125455
126121
  hosts: hostsRouter,
@@ -125495,12 +126161,14 @@ function discoverProcedures() {
125495
126161
  for (const [path2, procedure] of Object.entries(procRecord)) {
125496
126162
  const type = procedure._def.type;
125497
126163
  if (type === "subscription") continue;
125498
- if (path2.startsWith("tokens.") || path2.startsWith("vault.") || path2.startsWith("agentLogins.") || path2.startsWith("checkpoints.") || path2.startsWith("follow.") || path2.startsWith("mcp.") || path2.startsWith("hosts.") && path2 !== "hosts.forAgents" || path2.startsWith("workers.") && path2 !== "workers.forAgents" || path2.startsWith("hostRequests.") || path2.startsWith("runners.") || path2.startsWith("accountUsage.") || // The Simulator tab is a person's; an agent uses the simulator_* tools.
126164
+ if (path2.startsWith("tokens.") || path2.startsWith("vault.") || path2.startsWith("agentLogins.") || path2.startsWith("checkpoints.") || path2.startsWith("follow.") || path2.startsWith("mcp.") || path2.startsWith("hosts.") && path2 !== "hosts.forAgents" || path2.startsWith("workers.") && path2 !== "workers.forAgents" || path2.startsWith("hostRequests.") || path2.startsWith("runners.") || path2.startsWith("accountUsage.") || // The machine's process table and disk use are a person's page, not an agent's tool.
126165
+ path2.startsWith("resources.") || // The Simulator tab is a person's; an agent uses the simulator_* tools.
125499
126166
  path2.startsWith("simulators.") || path2.startsWith("voice.") || path2.startsWith("extensions.") || path2.startsWith("provisioning.") || // Writes ~/.claude/settings.json on a host; only a person's click may.
125500
126167
  path2.startsWith("hooks."))
125501
126168
  continue;
125502
126169
  if (path2 === "worktree.previewUrl") continue;
125503
126170
  if (path2 === "worktree.directAccess") continue;
126171
+ if (path2 === "worktree.readExternalFile" || path2 === "worktree.saveExternalFile") continue;
125504
126172
  if (path2 === "environment.validate") continue;
125505
126173
  if (path2 === "repos.addFromWorker") continue;
125506
126174
  if (path2 === "repos.addByUrl") continue;
@@ -125979,12 +126647,12 @@ function lookUpToolsOnce(server, listPage) {
125979
126647
  if (running) return running;
125980
126648
  const last = lookupMissedAt.get(server.id);
125981
126649
  if (last !== void 0 && Date.now() - last < LOOKUP_COOLDOWN_MS) return Promise.resolve();
125982
- const run3 = lookUpTools(server, listPage).catch(() => void 0).finally(() => {
126650
+ const run4 = lookUpTools(server, listPage).catch(() => void 0).finally(() => {
125983
126651
  lookupsInFlight.delete(server.id);
125984
126652
  lookupMissedAt.set(server.id, Date.now());
125985
126653
  });
125986
- lookupsInFlight.set(server.id, run3);
125987
- return run3;
126654
+ lookupsInFlight.set(server.id, run4);
126655
+ return run4;
125988
126656
  }
125989
126657
  async function lookUpTools(server, listPage) {
125990
126658
  const tools = /* @__PURE__ */ new Map();
@@ -126683,7 +127351,7 @@ function parseModeRequest(text4) {
126683
127351
  }
126684
127352
  return null;
126685
127353
  }
126686
- async function bridgePluginStream(ws, label2, open4, onOpenFailed) {
127354
+ async function bridgePluginStream(ws, label2, open3, onOpenFailed) {
126687
127355
  let controlling = false;
126688
127356
  let stream = null;
126689
127357
  ws.on("message", (data, isBinary) => {
@@ -126701,7 +127369,7 @@ async function bridgePluginStream(ws, label2, open4, onOpenFailed) {
126701
127369
  });
126702
127370
  ws.once("close", () => stream?.close());
126703
127371
  try {
126704
- stream = await open4();
127372
+ stream = await open3();
126705
127373
  } catch (err) {
126706
127374
  const message = err instanceof Error ? err.message : String(err);
126707
127375
  log87.warn("%s is unavailable: %s", label2, message);
@@ -127335,14 +128003,14 @@ async function handleVoiceTranscribe(req, res) {
127335
128003
 
127336
128004
  // src/server/api/web-app-manifest.ts
127337
128005
  import { createReadStream as createReadStream6, statSync as statSync16 } from "node:fs";
127338
- import { join as join59 } from "node:path";
128006
+ import { join as join60 } from "node:path";
127339
128007
  var WEB_APP_MANIFEST_PATH = "/manifest.webmanifest";
127340
128008
  var ICON_FILES = ["band-192.png", "band-512.png", "apple-touch-icon.png"];
127341
128009
  function handleWebAppManifest(req, res, publicDir) {
127342
128010
  if (req.method !== "GET" && req.method !== "HEAD") return false;
127343
128011
  const pathname = req.url?.split("?")[0];
127344
128012
  if (pathname === WEB_APP_MANIFEST_PATH) {
127345
- sendFile(req, res, join59(publicDir, "manifest.webmanifest"), {
128013
+ sendFile(req, res, join60(publicDir, "manifest.webmanifest"), {
127346
128014
  "Content-Type": "application/manifest+json",
127347
128015
  "Cache-Control": "no-cache"
127348
128016
  });
@@ -127350,7 +128018,7 @@ function handleWebAppManifest(req, res, publicDir) {
127350
128018
  }
127351
128019
  const icon = ICON_FILES.find((name5) => pathname === `/icons/${name5}`);
127352
128020
  if (!icon) return false;
127353
- sendFile(req, res, join59(publicDir, "icons", icon), {
128021
+ sendFile(req, res, join60(publicDir, "icons", icon), {
127354
128022
  "Content-Type": "image/png",
127355
128023
  "Cache-Control": "public, max-age=86400"
127356
128024
  });
@@ -127602,18 +128270,18 @@ async function bridgeRemote(ws, worktreeId4) {
127602
128270
  ws.removeAllListeners("message");
127603
128271
  return pending2;
127604
128272
  }
127605
- const open4 = cdp;
128273
+ const open3 = cdp;
127606
128274
  if (ws.readyState !== ws.OPEN) {
127607
- open4.close();
128275
+ open3.close();
127608
128276
  return true;
127609
128277
  }
127610
- for (const msg of pending2) open4.send(msg);
128278
+ for (const msg of pending2) open3.send(msg);
127611
128279
  pending2.length = 0;
127612
- ws.on("close", () => open4.close());
127613
- ws.on("error", () => open4.close());
128280
+ ws.on("close", () => open3.close());
128281
+ ws.on("error", () => open3.close());
127614
128282
  void (async () => {
127615
128283
  try {
127616
- for await (const message of open4.messages) {
128284
+ for await (const message of open3.messages) {
127617
128285
  if (ws.readyState === ws.OPEN) ws.send(message);
127618
128286
  }
127619
128287
  } catch (err) {
@@ -128143,7 +128811,7 @@ init_http_files();
128143
128811
 
128144
128812
  // src/server/services/_utils/hosted-file.ts
128145
128813
  init_registry();
128146
- import { basename as basename6, dirname as dirname19, join as join60 } from "node:path";
128814
+ import { basename as basename6, dirname as dirname19, join as join61 } from "node:path";
128147
128815
  async function openHostedFile(kind, worktreeId4, rawName, chatId) {
128148
128816
  const host = hostRegistry.hostFor(worktreeId4);
128149
128817
  if (host.id === hostRegistry.local.id) return null;
@@ -128157,12 +128825,12 @@ async function openHostedFile(kind, worktreeId4, rawName, chatId) {
128157
128825
  try {
128158
128826
  const dirs = (await host.info()).dirs;
128159
128827
  if (!dirs) return null;
128160
- const path2 = chatId ? join60(dirs[kind], worktreeId4, chatId, name5) : join60(dirs[kind], worktreeId4, name5);
128828
+ const path2 = chatId ? join61(dirs[kind], worktreeId4, chatId, name5) : join61(dirs[kind], worktreeId4, name5);
128161
128829
  const dir = await host.fs.realpath(dirname19(path2));
128162
128830
  if (!(await host.fs.realpath(path2)).startsWith(`${dir}/`)) return null;
128163
- const stat8 = await host.fs.stat(path2, { followSymlinks: true });
128164
- if (stat8.kind !== "file") return null;
128165
- return { size: stat8.size, stream: host.fs.readStream(path2) };
128831
+ const stat9 = await host.fs.stat(path2, { followSymlinks: true });
128832
+ if (stat9.kind !== "file") return null;
128833
+ return { size: stat9.size, stream: host.fs.readStream(path2) };
128166
128834
  } catch {
128167
128835
  return null;
128168
128836
  }
@@ -136525,7 +137193,7 @@ init_worktree_service();
136525
137193
  function logCrash(message) {
136526
137194
  try {
136527
137195
  mkdirSync12(bandHome(), { recursive: true });
136528
- appendFileSync2(join61(bandHome(), "server.log"), message, "utf-8");
137196
+ appendFileSync2(join62(bandHome(), "server.log"), message, "utf-8");
136529
137197
  } catch {
136530
137198
  }
136531
137199
  }
@@ -136565,9 +137233,9 @@ function resolveUiDir() {
136565
137233
  if (explicit) return resolve15(explicit);
136566
137234
  const candidates = [
136567
137235
  resolve15(SERVER_ROOT, "..", "..", "web", "dist", "client"),
136568
- join61(SERVER_ROOT, "client")
137236
+ join62(SERVER_ROOT, "client")
136569
137237
  ];
136570
- return candidates.find((dir) => existsSync20(join61(dir, "_shell.html"))) ?? candidates[1];
137238
+ return candidates.find((dir) => existsSync20(join62(dir, "_shell.html"))) ?? candidates[1];
136571
137239
  }
136572
137240
  var clientDir = resolveUiDir();
136573
137241
  var uiRoot = process.env.BAND_UI_ROOT ? resolve15(process.env.BAND_UI_ROOT) : resolve15(SERVER_ROOT, "..", "web");
@@ -136618,7 +137286,7 @@ function getOpenApiSpec() {
136618
137286
  if (isDev) {
136619
137287
  const { generateOpenAPIDocument } = await import("@trpc/openapi");
136620
137288
  const doc = await generateOpenAPIDocument(
136621
- join61(SERVER_ROOT, "src", "server", "api", "router.ts"),
137289
+ join62(SERVER_ROOT, "src", "server", "api", "router.ts"),
136622
137290
  {
136623
137291
  title: "Band API",
136624
137292
  version: "1.0.0"
@@ -136627,7 +137295,7 @@ function getOpenApiSpec() {
136627
137295
  doc.servers = [{ url: "/trpc" }];
136628
137296
  return JSON.stringify(doc, null, 2);
136629
137297
  }
136630
- const openApiDoc = JSON.parse(readFileSync14(join61(SERVER_ROOT, "openapi.json"), "utf-8"));
137298
+ const openApiDoc = JSON.parse(readFileSync14(join62(SERVER_ROOT, "openapi.json"), "utf-8"));
136631
137299
  openApiDoc.servers = [{ url: "/trpc" }];
136632
137300
  return JSON.stringify(openApiDoc, null, 2);
136633
137301
  })().catch((err) => {
@@ -136650,9 +137318,9 @@ function serveStaticFile(res, root, subdir, rawFilename) {
136650
137318
  res.end("Bad request");
136651
137319
  return;
136652
137320
  }
136653
- const filePath = join61(root, subdir, filename);
137321
+ const filePath = join62(root, subdir, filename);
136654
137322
  try {
136655
- const dir = realpathSync7(join61(root, subdir));
137323
+ const dir = realpathSync7(join62(root, subdir));
136656
137324
  if (!realpathSync7(filePath).startsWith(dir + sep12)) {
136657
137325
  res.writeHead(404);
136658
137326
  res.end("Not found");
@@ -136703,7 +137371,7 @@ async function serveWorktreeFile(res, worktreeId4, rawPath, extraHeaders = {}, v
136703
137371
  return;
136704
137372
  }
136705
137373
  const root = worktree.worktree.path;
136706
- const target = resolve15(join61(root, rawPath));
137374
+ const target = resolve15(join62(root, rawPath));
136707
137375
  if (!target.startsWith(root + sep12) && target !== root) {
136708
137376
  res.writeHead(400);
136709
137377
  res.end("Bad request");
@@ -137036,7 +137704,7 @@ async function main() {
137036
137704
  res.end(JSON.stringify({ status: "ok", app: "band-web-server" }));
137037
137705
  return;
137038
137706
  }
137039
- if (handleWebAppManifest(req, res, isDev ? join61(uiRoot, "public") : clientDir)) return;
137707
+ if (handleWebAppManifest(req, res, isDev ? join62(uiRoot, "public") : clientDir)) return;
137040
137708
  if (req.url?.split("?")[0] === WORKER_EXCHANGE_PATH) {
137041
137709
  await workerLinkService.handleExchange(req, res);
137042
137710
  return;
@@ -137148,7 +137816,7 @@ async function main() {
137148
137816
  const encodedName = encodeURIComponent(parsed.name);
137149
137817
  if (await serveHostedFile(res, "shared", parsed.worktreeId, encodedName, parsed.chatId))
137150
137818
  return;
137151
- const subdir = parsed.chatId ? join61("shared", parsed.worktreeId, parsed.chatId) : join61("shared", parsed.worktreeId);
137819
+ const subdir = parsed.chatId ? join62("shared", parsed.worktreeId, parsed.chatId) : join62("shared", parsed.worktreeId);
137152
137820
  serveStaticFile(res, bandHome(), subdir, encodedName);
137153
137821
  return;
137154
137822
  }
@@ -137374,7 +138042,7 @@ async function main() {
137374
138042
  if (pathname.startsWith("/_shell")) res.setHeader("Cache-Control", "no-cache");
137375
138043
  }
137376
138044
  });
137377
- const shellPath2 = join61(clientDir, "_shell.html");
138045
+ const shellPath2 = join62(clientDir, "_shell.html");
137378
138046
  if (!existsSync20(shellPath2)) {
137379
138047
  throw new Error(
137380
138048
  `UI build not found at ${clientDir} (no _shell.html). Run \`pnpm build\` or pass --ui-dir <path>.`