@dylanpiercey/work 0.0.37 → 0.0.40

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 (158) hide show
  1. package/README.md +15 -2
  2. package/bin/work.mjs +76 -1
  3. package/dist/index.mjs +1393 -745
  4. package/dist/public/assets/{_pFmckaaP2.js → _-KsWGHKz2.js} +2 -2
  5. package/dist/public/assets/{_pFmckaaP2.js.map → _-KsWGHKz2.js.map} +1 -1
  6. package/dist/public/assets/{_BjiamLhC2.js → _3VenI2OT2.js} +2 -2
  7. package/dist/public/assets/{_BjiamLhC2.js.map → _3VenI2OT2.js.map} +1 -1
  8. package/dist/public/assets/{_e1mFK4xC.js → _8DPiXP2D.js} +2 -2
  9. package/dist/public/assets/{_e1mFK4xC.js.map → _8DPiXP2D.js.map} +1 -1
  10. package/dist/public/assets/{_aCPbjwsL2.js → _8UwDOo_Z2.js} +2 -2
  11. package/dist/public/assets/{_aCPbjwsL2.js.map → _8UwDOo_Z2.js.map} +1 -1
  12. package/dist/public/assets/{_7WXRxrlU.js → _B0ILW1ln.js} +2 -2
  13. package/dist/public/assets/{_7WXRxrlU.js.map → _B0ILW1ln.js.map} +1 -1
  14. package/dist/public/assets/{_ChxFmNZf2.js → _B7cE3DDh2.js} +2 -2
  15. package/dist/public/assets/{_ChxFmNZf2.js.map → _B7cE3DDh2.js.map} +1 -1
  16. package/dist/public/assets/{_ETxOUn4j2.js → _B8CG1lYk2.js} +2 -2
  17. package/dist/public/assets/{_ETxOUn4j2.js.map → _B8CG1lYk2.js.map} +1 -1
  18. package/dist/public/assets/{_CKmHgYfe.js → _BFoRA3M-.js} +2 -2
  19. package/dist/public/assets/{_CKmHgYfe.js.map → _BFoRA3M-.js.map} +1 -1
  20. package/dist/public/assets/{_CH2C5dSU.js → _BHNTdpyr.js} +2 -2
  21. package/dist/public/assets/{_CH2C5dSU.js.map → _BHNTdpyr.js.map} +1 -1
  22. package/dist/public/assets/{_qFxIW2tY.js → _BJLP6wPD.js} +2 -2
  23. package/dist/public/assets/{_qFxIW2tY.js.map → _BJLP6wPD.js.map} +1 -1
  24. package/dist/public/assets/{_uHn5Sjo52.js → _BKoDBxkc2.js} +2 -2
  25. package/dist/public/assets/{_uHn5Sjo52.js.map → _BKoDBxkc2.js.map} +1 -1
  26. package/dist/public/assets/{_snZlpI9-2.js → _BPQMLvu02.js} +2 -2
  27. package/dist/public/assets/{_snZlpI9-2.js.map → _BPQMLvu02.js.map} +1 -1
  28. package/dist/public/assets/{_D_QEBWxx.js → _BTgtIJbs.js} +2 -2
  29. package/dist/public/assets/{_D_QEBWxx.js.map → _BTgtIJbs.js.map} +1 -1
  30. package/dist/public/assets/{__8BegO0O.js → _BVhbSv_7.js} +2 -2
  31. package/dist/public/assets/{__8BegO0O.js.map → _BVhbSv_7.js.map} +1 -1
  32. package/dist/public/assets/{_ChALr73Q.js → _BXFyaVzV.js} +2 -2
  33. package/dist/public/assets/{_ChALr73Q.js.map → _BXFyaVzV.js.map} +1 -1
  34. package/dist/public/assets/{_WtSbc-0z2.js → _Ba56VGPa2.js} +2 -2
  35. package/dist/public/assets/{_WtSbc-0z2.js.map → _Ba56VGPa2.js.map} +1 -1
  36. package/dist/public/assets/{_CJ4f2Gn22.js → _BbczFSm62.js} +2 -2
  37. package/dist/public/assets/{_CJ4f2Gn22.js.map → _BbczFSm62.js.map} +1 -1
  38. package/dist/public/assets/{_TzFjCY4x.js → _BdxRwSdd.js} +2 -2
  39. package/dist/public/assets/{_TzFjCY4x.js.map → _BdxRwSdd.js.map} +1 -1
  40. package/dist/public/assets/{_CpZyjYVd.js → _BgyAIeMk.js} +2 -2
  41. package/dist/public/assets/{_CpZyjYVd.js.map → _BgyAIeMk.js.map} +1 -1
  42. package/dist/public/assets/{_BbK3eXZN2.js → _BjYoD_6z2.js} +2 -2
  43. package/dist/public/assets/{_BbK3eXZN2.js.map → _BjYoD_6z2.js.map} +1 -1
  44. package/dist/public/assets/{_CqgeXAyq.js → _BlnfI-cd.js} +2 -2
  45. package/dist/public/assets/{_CqgeXAyq.js.map → _BlnfI-cd.js.map} +1 -1
  46. package/dist/public/assets/{_Cgcy-XAW.js → _Bm15UJ5r.js} +2 -2
  47. package/dist/public/assets/{_Cgcy-XAW.js.map → _Bm15UJ5r.js.map} +1 -1
  48. package/dist/public/assets/{_ickmOHj-.js → _BmY-aR2i.js} +2 -2
  49. package/dist/public/assets/{_ickmOHj-.js.map → _BmY-aR2i.js.map} +1 -1
  50. package/dist/public/assets/{_DMqId9I32.js → _Bq9rbiCa2.js} +2 -2
  51. package/dist/public/assets/{_DMqId9I32.js.map → _Bq9rbiCa2.js.map} +1 -1
  52. package/dist/public/assets/{_CerTTqHR.js → _Br2uo0OK.js} +2 -2
  53. package/dist/public/assets/{_CerTTqHR.js.map → _Br2uo0OK.js.map} +1 -1
  54. package/dist/public/assets/{_C0Jt_Xjm.js → _Brtx9zLF.js} +2 -2
  55. package/dist/public/assets/{_C0Jt_Xjm.js.map → _Brtx9zLF.js.map} +1 -1
  56. package/dist/public/assets/{_DCP8qFc6.js → _BtnmnAxJ.js} +2 -2
  57. package/dist/public/assets/{_DCP8qFc6.js.map → _BtnmnAxJ.js.map} +1 -1
  58. package/dist/public/assets/{_BnSuNHJ7.js → _Bv_RWYiQ.js} +2 -2
  59. package/dist/public/assets/{_BnSuNHJ7.js.map → _Bv_RWYiQ.js.map} +1 -1
  60. package/dist/public/assets/{_CEkpXUQi2.js → _BvtYDSuT2.js} +2 -2
  61. package/dist/public/assets/{_CEkpXUQi2.js.map → _BvtYDSuT2.js.map} +1 -1
  62. package/dist/public/assets/{_BgZq7RwW.js → _C83jn7M7.js} +2 -2
  63. package/dist/public/assets/{_BgZq7RwW.js.map → _C83jn7M7.js.map} +1 -1
  64. package/dist/public/assets/{_TZbrx97x2.js → _CA4_OXC62.js} +2 -2
  65. package/dist/public/assets/{_TZbrx97x2.js.map → _CA4_OXC62.js.map} +1 -1
  66. package/dist/public/assets/{_C6Ku6tce.js → _CEr-0D0d.js} +2 -2
  67. package/dist/public/assets/{_C6Ku6tce.js.map → _CEr-0D0d.js.map} +1 -1
  68. package/dist/public/assets/{_DeL04cfO2.js → _CGlOgonA2.js} +2 -2
  69. package/dist/public/assets/{_DeL04cfO2.js.map → _CGlOgonA2.js.map} +1 -1
  70. package/dist/public/assets/{_BduevJm5.js → _CLJ7h8rZ.js} +2 -2
  71. package/dist/public/assets/{_BduevJm5.js.map → _CLJ7h8rZ.js.map} +1 -1
  72. package/dist/public/assets/{_Dzo0xXFy2.js → _CV6LlXY32.js} +2 -2
  73. package/dist/public/assets/{_Dzo0xXFy2.js.map → _CV6LlXY32.js.map} +1 -1
  74. package/dist/public/assets/{_B0l1050s.js → _CVFOAkWc.js} +2 -2
  75. package/dist/public/assets/{_B0l1050s.js.map → _CVFOAkWc.js.map} +1 -1
  76. package/dist/public/assets/{_B62EUIfl2.js → _CVgZFxTy2.js} +2 -2
  77. package/dist/public/assets/{_B62EUIfl2.js.map → _CVgZFxTy2.js.map} +1 -1
  78. package/dist/public/assets/{_B1zT643d.js → _CWG8S2bO.js} +2 -2
  79. package/dist/public/assets/{_B1zT643d.js.map → _CWG8S2bO.js.map} +1 -1
  80. package/dist/public/assets/{_BS-0-1w-.js → _CX2FR9en.js} +2 -2
  81. package/dist/public/assets/{_BS-0-1w-.js.map → _CX2FR9en.js.map} +1 -1
  82. package/dist/public/assets/{_BfOhO-ik.js → _CcyXwmyV.js} +2 -2
  83. package/dist/public/assets/{_BfOhO-ik.js.map → _CcyXwmyV.js.map} +1 -1
  84. package/dist/public/assets/{_B61Z1jwf.js → _CfNBAgk5.js} +2 -2
  85. package/dist/public/assets/{_B61Z1jwf.js.map → _CfNBAgk5.js.map} +1 -1
  86. package/dist/public/assets/{_CFlhxTwD.js → _CmH32z5I.js} +2 -2
  87. package/dist/public/assets/{_CFlhxTwD.js.map → _CmH32z5I.js.map} +1 -1
  88. package/dist/public/assets/{_328LsgJQ.js → _Cn-JhCBl.js} +2 -2
  89. package/dist/public/assets/{_328LsgJQ.js.map → _Cn-JhCBl.js.map} +1 -1
  90. package/dist/public/assets/{_CCquK4b1.js → _Cn880iWo.js} +2 -2
  91. package/dist/public/assets/{_CCquK4b1.js.map → _Cn880iWo.js.map} +1 -1
  92. package/dist/public/assets/{_Dt-7Y3TE2.js → _CpelmBB72.js} +2 -2
  93. package/dist/public/assets/{_Dt-7Y3TE2.js.map → _CpelmBB72.js.map} +1 -1
  94. package/dist/public/assets/{_T9N_IxyL.js → _CqS9_RIm.js} +2 -2
  95. package/dist/public/assets/{_T9N_IxyL.js.map → _CqS9_RIm.js.map} +1 -1
  96. package/dist/public/assets/{_C0UJDcvl2.js → _Ct5nAVXE2.js} +2 -2
  97. package/dist/public/assets/{_C0UJDcvl2.js.map → _Ct5nAVXE2.js.map} +1 -1
  98. package/dist/public/assets/{_CnWV64BG2.js → _Cu-YDqqS2.js} +2 -2
  99. package/dist/public/assets/{_CnWV64BG2.js.map → _Cu-YDqqS2.js.map} +1 -1
  100. package/dist/public/assets/{_Bpw8-M-2.js → _Cw00Etn-.js} +2 -2
  101. package/dist/public/assets/{_Bpw8-M-2.js.map → _Cw00Etn-.js.map} +1 -1
  102. package/dist/public/assets/{_y6dVQHpH.js → _Cy0mebiK.js} +2 -2
  103. package/dist/public/assets/{_y6dVQHpH.js.map → _Cy0mebiK.js.map} +1 -1
  104. package/dist/public/assets/{_DJ0lGemR.js → _D1KsrNGN.js} +2 -2
  105. package/dist/public/assets/{_DJ0lGemR.js.map → _D1KsrNGN.js.map} +1 -1
  106. package/dist/public/assets/{_BwHIIw2E2.js → _D63K5MAL2.js} +2 -2
  107. package/dist/public/assets/{_BwHIIw2E2.js.map → _D63K5MAL2.js.map} +1 -1
  108. package/dist/public/assets/{_CiLcz-CP.js → _DDn1qNlx.js} +2 -2
  109. package/dist/public/assets/{_CiLcz-CP.js.map → _DDn1qNlx.js.map} +1 -1
  110. package/dist/public/assets/{_B0p7k1Wy.js → _DGWkqOrB.js} +2 -2
  111. package/dist/public/assets/{_B0p7k1Wy.js.map → _DGWkqOrB.js.map} +1 -1
  112. package/dist/public/assets/{_BG7PgpSh.js → _DIsTDKVR.js} +2 -2
  113. package/dist/public/assets/{_BG7PgpSh.js.map → _DIsTDKVR.js.map} +1 -1
  114. package/dist/public/assets/{_DimDQHw9.js → _DQ-kE1KO.js} +2 -2
  115. package/dist/public/assets/{_DimDQHw9.js.map → _DQ-kE1KO.js.map} +1 -1
  116. package/dist/public/assets/{_Dghs5wz6.js → _DXPT_5Ww.js} +2 -2
  117. package/dist/public/assets/{_Dghs5wz6.js.map → _DXPT_5Ww.js.map} +1 -1
  118. package/dist/public/assets/{_BlnqFsCL.js → _Dgbb7WCq.js} +2 -2
  119. package/dist/public/assets/{_BlnqFsCL.js.map → _Dgbb7WCq.js.map} +1 -1
  120. package/dist/public/assets/{_DE45Wi_v2.js → _DiGEIi7y2.js} +2 -2
  121. package/dist/public/assets/{_DE45Wi_v2.js.map → _DiGEIi7y2.js.map} +1 -1
  122. package/dist/public/assets/{_BzyfiiMx.js → _DlycnL0G.js} +2 -2
  123. package/dist/public/assets/{_BzyfiiMx.js.map → _DlycnL0G.js.map} +1 -1
  124. package/dist/public/assets/{_OntiqL02.js → _DsnM-qIE.js} +2 -2
  125. package/dist/public/assets/{_OntiqL02.js.map → _DsnM-qIE.js.map} +1 -1
  126. package/dist/public/assets/{_CznN3jlr.js → _DvhrN_AC.js} +2 -2
  127. package/dist/public/assets/{_CznN3jlr.js.map → _DvhrN_AC.js.map} +1 -1
  128. package/dist/public/assets/{_DC_ioCXZ.js → _Dzmzf0jy.js} +2 -2
  129. package/dist/public/assets/{_DC_ioCXZ.js.map → _Dzmzf0jy.js.map} +1 -1
  130. package/dist/public/assets/{_aJqK30432.js → _FK3N8vMM2.js} +2 -2
  131. package/dist/public/assets/{_aJqK30432.js.map → _FK3N8vMM2.js.map} +1 -1
  132. package/dist/public/assets/{_Cbz3Zb2r.js → _Ivuhnz8D.js} +2 -2
  133. package/dist/public/assets/{_Cbz3Zb2r.js.map → _Ivuhnz8D.js.map} +1 -1
  134. package/dist/public/assets/{_BiVb_8fl2.js → _TKY_rFIy2.js} +2 -2
  135. package/dist/public/assets/{_BiVb_8fl2.js.map → _TKY_rFIy2.js.map} +1 -1
  136. package/dist/public/assets/{_D-9YZFuF.js → _UeUsduDg.js} +2 -2
  137. package/dist/public/assets/{_D-9YZFuF.js.map → _UeUsduDg.js.map} +1 -1
  138. package/dist/public/assets/{_BTDPW9iy.js → _ZG408fQc.js} +2 -2
  139. package/dist/public/assets/{_BTDPW9iy.js.map → _ZG408fQc.js.map} +1 -1
  140. package/dist/public/assets/{_CjmNk-3X.js → _dpF9TA5S.js} +2 -2
  141. package/dist/public/assets/{_CjmNk-3X.js.map → _dpF9TA5S.js.map} +1 -1
  142. package/dist/public/assets/{_B35oLYjV.js → _fIQDai7d.js} +2 -2
  143. package/dist/public/assets/{_B35oLYjV.js.map → _fIQDai7d.js.map} +1 -1
  144. package/dist/public/assets/{_4oI4DLD12.js → _irjxI44N2.js} +2 -2
  145. package/dist/public/assets/{_4oI4DLD12.js.map → _irjxI44N2.js.map} +1 -1
  146. package/dist/public/assets/{_7Hr6x6JT.js → _jifvQF0M.js} +2 -2
  147. package/dist/public/assets/{_7Hr6x6JT.js.map → _jifvQF0M.js.map} +1 -1
  148. package/dist/public/assets/{_BpJ6F21O.js → _mH9R9oGB.js} +2 -2
  149. package/dist/public/assets/{_BpJ6F21O.js.map → _mH9R9oGB.js.map} +1 -1
  150. package/dist/public/assets/{_CuVyPGCR.js → _pUoTA7Pg.js} +2 -2
  151. package/dist/public/assets/{_CuVyPGCR.js.map → _pUoTA7Pg.js.map} +1 -1
  152. package/dist/public/assets/index--QwhN0hy.css +1 -0
  153. package/dist/public/assets/index-CdVBL6Kf.js +1615 -0
  154. package/dist/public/assets/index-CdVBL6Kf.js.map +1 -0
  155. package/package.json +1 -1
  156. package/dist/public/assets/index-B-C71W3M.js +0 -1615
  157. package/dist/public/assets/index-B-C71W3M.js.map +0 -1
  158. package/dist/public/assets/index-DxoJXJz6.css +0 -1
package/dist/index.mjs CHANGED
@@ -8,6 +8,7 @@ import { Readable } from "node:stream";
8
8
  import { AsyncLocalStorage } from "node:async_hooks";
9
9
  import fs from "node:fs";
10
10
  import os from "node:os";
11
+ import { DatabaseSync } from "node:sqlite";
11
12
  import { spawn } from "node:child_process";
12
13
  import fsp from "node:fs/promises";
13
14
  import crypto from "node:crypto";
@@ -2068,8 +2069,15 @@ function swr(ttlMs, load, seed) {
2068
2069
  }
2069
2070
  //#endregion
2070
2071
  //#region src/server/prs.ts
2071
- var PR_JSON = "number,title,url,headRefName,baseRefName,headRefOid,isDraft,state,reviewDecision";
2072
+ var PR_JSON = "number,title,url,headRefName,baseRefName,headRefOid,isDraft,state";
2072
2073
  var TTL_MS$3 = 12e4;
2074
+ function mapPr(raw) {
2075
+ const { headRef, ...rest } = raw;
2076
+ return {
2077
+ ...rest,
2078
+ headRefOid: rest.headRefOid || headRef?.oid
2079
+ };
2080
+ }
2073
2081
  /** PRs in every state for a repo, stale-while-revalidate cached. */
2074
2082
  var prs = swr(TTL_MS$3, fetchPrs);
2075
2083
  /** PRs whose head is the workspace branch or one of its `-topic` lanes.
@@ -2101,7 +2109,7 @@ var headPrs = swr(TTL_MS$3, async (key) => {
2101
2109
  "--json",
2102
2110
  PR_JSON
2103
2111
  ]).catch(() => "[]");
2104
- return JSON.parse(out);
2112
+ return JSON.parse(out).map(mapPr);
2105
2113
  });
2106
2114
  /** A workspace repo's PRs: the recency-windowed list filtered to the
2107
2115
  * branch prefix, plus the exact-head lookup merged in. */
@@ -2124,17 +2132,17 @@ async function fetchPrs(fullName) {
2124
2132
  "--json",
2125
2133
  PR_JSON
2126
2134
  ]).catch(() => "[]");
2127
- return JSON.parse(out);
2135
+ return JSON.parse(out).map(mapPr);
2128
2136
  }
2129
2137
  /** Refresh many repos' PRs with one GraphQL request (vs one `gh pr list`
2130
2138
  * process per repo) — called from the status watcher for active
2131
- * workspaces so PR/CI flips surface in ~watch-tick time instead of
2132
- * waiting out the per-repo TTL. Throttled internally. */
2133
- var BATCH_MIN_MS = 3e4;
2134
- /** After a detected local push, poll fast for a bit — the PR appears and
2135
- * CI starts flipping in the minutes right after. */
2136
- var HOT_MIN_MS = 4e3;
2137
- var HOT_WINDOW_MS = 12e4;
2139
+ * workspaces so open/merge/close flips surface in ~watch-tick time
2140
+ * instead of waiting out the per-repo TTL. Throttled internally. */
2141
+ var BATCH_MIN_MS = 15e3;
2142
+ /** After a detected local push, poll fast for a bit — the PR appears
2143
+ * and merges/closes in the minutes right after. */
2144
+ var HOT_MIN_MS = 3e3;
2145
+ var HOT_WINDOW_MS = 18e4;
2138
2146
  var lastBatch = 0;
2139
2147
  var hotUntil = 0;
2140
2148
  function notePushActivity() {
@@ -2144,6 +2152,7 @@ function notePushActivity() {
2144
2152
  function inHotWindow() {
2145
2153
  return Date.now() < hotUntil;
2146
2154
  }
2155
+ var GQL_PR_FIELDS = "number title url headRefName baseRefName isDraft state headRef { oid }";
2147
2156
  async function refreshPrsBatch(fullNames, force = false) {
2148
2157
  const names = [...new Set(fullNames)].filter((n) => n.includes("/"));
2149
2158
  const minMs = force ? 2e3 : Date.now() < hotUntil ? HOT_MIN_MS : BATCH_MIN_MS;
@@ -2153,7 +2162,7 @@ async function refreshPrsBatch(fullNames, force = false) {
2153
2162
  try {
2154
2163
  const query = "query {" + names.map((fullName, i) => {
2155
2164
  const [owner, name] = fullName.split("/");
2156
- return `r${i}: repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { pullRequests(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) { nodes { number title url headRefName baseRefName isDraft state reviewDecision headRef { oid } } } }`;
2165
+ return `r${i}: repository(owner: ${JSON.stringify(owner)}, name: ${JSON.stringify(name)}) { pullRequests(first: 50, orderBy: {field: UPDATED_AT, direction: DESC}) { nodes { ${GQL_PR_FIELDS} } } }`;
2157
2166
  }).join(" ") + "}";
2158
2167
  const out = await gh([
2159
2168
  "api",
@@ -2169,10 +2178,7 @@ async function refreshPrsBatch(fullNames, force = false) {
2169
2178
  names.forEach((fullName, i) => {
2170
2179
  const repo = data[`r${i}`];
2171
2180
  if (!repo) return;
2172
- prs.set(fullName, repo.pullRequests.nodes.map((n) => ({
2173
- ...n,
2174
- headRefOid: n.headRefOid || n.headRef?.oid
2175
- })));
2181
+ prs.set(fullName, repo.pullRequests.nodes.map(mapPr));
2176
2182
  });
2177
2183
  return true;
2178
2184
  } catch (err) {
@@ -2221,13 +2227,13 @@ function statusForAll() {
2221
2227
  }
2222
2228
  /** Push-based freshness: while any events-bus client is connected,
2223
2229
  * recompute the (shared, deduped) snapshot on a slow tick and publish it
2224
- * only when it actually changed — ports appearing, PR/CI flips reach
2230
+ * only when it actually changed — ports appearing, PR open/merge/close flips reach
2225
2231
  * every client in ~15s instead of waiting out a slow poll, and idle
2226
2232
  * systems push nothing at all. */
2227
- var WATCH_MS = 15e3;
2228
- /** Right after a local push PR state flips within seconds — tick fast so
2229
- * the badge lands while it still feels immediate. */
2230
- var WATCH_HOT_MS = 5e3;
2233
+ var WATCH_MS = 1e4;
2234
+ /** Right after a local push, PR+check state flips within seconds — tick
2235
+ * fast so the badge lands while it still feels immediate. */
2236
+ var WATCH_HOT_MS = 4e3;
2231
2237
  var watching = false;
2232
2238
  var lastPushed = "";
2233
2239
  async function watchTick() {
@@ -2300,7 +2306,7 @@ async function computeStatus() {
2300
2306
  }
2301
2307
  async function repoStatus(ws, repo, foreign) {
2302
2308
  const dir = path.join(ws.path, repo.worktree);
2303
- const [repoPrs, localHead] = await Promise.all([workspacePrs(repo.full_name, ws.branch, foreign).then((list) => list.filter((pr) => pr.state === "OPEN")), git(["rev-parse", "HEAD"], dir).catch(() => "")]);
2309
+ const [repoPrs, localHead] = await Promise.all([workspacePrs(repo.full_name, ws.branch, foreign).then((list) => withoutDismissed(ws.id, repo.full_name, list)), git(["rev-parse", "HEAD"], dir).catch(() => "")]);
2304
2310
  return {
2305
2311
  full_name: repo.full_name,
2306
2312
  worktree: repo.worktree,
@@ -4372,30 +4378,30 @@ var _layout_default = _template("a", (input) => {
4372
4378
  _trailers("</body></html>");
4373
4379
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, {});
4374
4380
  }, 1);
4375
- var page_module_default = { boot: "_w" };
4381
+ var page_module_default = { boot: "_a" };
4376
4382
  var ui_module_default = {
4377
- icon: "_a",
4378
- btn: "_b",
4379
- primary: "_c",
4380
- danger: "_d",
4381
- armed: "_e",
4382
- chip: "_f",
4383
- lane: "_g",
4384
- pr: "_h",
4385
- draft: "_i",
4386
- dim: "_j",
4387
- mono: "_k",
4388
- spacer: "_l",
4389
- dot: "_m",
4390
- working: "_n",
4391
- waiting: "_o",
4392
- idle: "_p",
4393
- off: "_q",
4394
- splitBtn: "_r",
4395
- splitPrimary: "_s _r",
4396
- splitGrow: "_t",
4397
- spin: "_u",
4398
- workSpin: "_v"
4383
+ icon: "_b",
4384
+ btn: "_c",
4385
+ primary: "_d",
4386
+ danger: "_e",
4387
+ armed: "_f",
4388
+ chip: "_g",
4389
+ lane: "_h",
4390
+ pr: "_i",
4391
+ draft: "_j",
4392
+ dim: "_k",
4393
+ mono: "_l",
4394
+ spacer: "_m",
4395
+ dot: "_n",
4396
+ working: "_o",
4397
+ waiting: "_p",
4398
+ idle: "_q",
4399
+ off: "_r",
4400
+ splitBtn: "_s",
4401
+ splitPrimary: "_t _s",
4402
+ splitGrow: "_u",
4403
+ spin: "_v",
4404
+ workSpin: "_w"
4399
4405
  };
4400
4406
  var page_boot_module_default = { root: "_x" };
4401
4407
  var bus = new EventTarget();
@@ -4438,17 +4444,17 @@ function isTouch() {
4438
4444
  return typeof window !== "undefined" && window.matchMedia("(pointer: coarse)").matches;
4439
4445
  }
4440
4446
  var toast_module_default = {
4441
- toast: "_G",
4442
- toastFloat: "_H",
4443
- toastInline: "_I",
4444
- toastError: "_J",
4445
- toastTitle: "_K",
4446
- toastWarn: "_L",
4447
- toastInfo: "_M",
4448
- toastBody: "_N",
4449
- toastContent: "_O",
4450
- toastActions: "_P",
4451
- toastDismiss: "_Q _cw"
4447
+ toast: "_y",
4448
+ toastFloat: "_z",
4449
+ toastInline: "_A",
4450
+ toastError: "_B",
4451
+ toastTitle: "_C",
4452
+ toastWarn: "_D",
4453
+ toastInfo: "_E",
4454
+ toastBody: "_F",
4455
+ toastContent: "_G",
4456
+ toastActions: "_H",
4457
+ toastDismiss: "_I _eA"
4452
4458
  };
4453
4459
  //#endregion
4454
4460
  //#region src/tags/toast.marko
@@ -4592,27 +4598,27 @@ function sessionPhase(state) {
4592
4598
  return state?.phase === "working" ? "working" : state?.phase === "waiting" ? "waiting" : state?.alive ? "idle" : "off";
4593
4599
  }
4594
4600
  var palette_module_default = {
4595
- paletteBackdrop: "_bp",
4596
- palette: "_bq",
4597
- inline: "_br",
4598
- rows: "_bs",
4599
- rowWrap: "_bt",
4600
- row: "_bu",
4601
- rowMore: "_bv",
4602
- hi: "_bw",
4603
- archived: "_bx",
4604
- cmdRow: "_by",
4605
- onboard: "_bz",
4606
- rowName: "_bA",
4607
- rowNameText: "_bB",
4608
- rowStats: "_bC",
4609
- open: "_bD",
4610
- stat: "_bE",
4611
- rowRepos: "_bF",
4612
- paletteFoot: "_bG",
4613
- hint: "_bH",
4614
- archivedLink: "_bI",
4615
- newSessionPop: "_bJ"
4601
+ paletteBackdrop: "_R",
4602
+ palette: "_S",
4603
+ inline: "_T",
4604
+ rows: "_U",
4605
+ rowWrap: "_V",
4606
+ row: "_W",
4607
+ rowMore: "_X",
4608
+ hi: "_Y",
4609
+ archived: "_Z",
4610
+ cmdRow: "_0",
4611
+ onboard: "_1",
4612
+ rowName: "_2",
4613
+ rowNameText: "_3",
4614
+ rowStats: "_4",
4615
+ open: "_5",
4616
+ stat: "_6",
4617
+ rowRepos: "_7",
4618
+ paletteFoot: "_8",
4619
+ hint: "_9",
4620
+ archivedLink: "__",
4621
+ newSessionPop: "_ba"
4616
4622
  };
4617
4623
  //#endregion
4618
4624
  //#region src/tags/icons/icon-base.marko
@@ -4625,7 +4631,7 @@ var icon_base_default = _template("B", (input) => {
4625
4631
  });
4626
4632
  //#endregion
4627
4633
  //#region src/tags/icons/icon-diff.marko
4628
- var icon_diff_default = _template("E", (input) => {
4634
+ var icon_diff_default = _template("F", (input) => {
4629
4635
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
4630
4636
  const $scope0_id = _scope_id();
4631
4637
  _set_serialize_reason({
@@ -4642,7 +4648,7 @@ var icon_diff_default = _template("E", (input) => {
4642
4648
  });
4643
4649
  //#endregion
4644
4650
  //#region src/tags/icons/icon-manage.marko
4645
- var icon_manage_default = _template("L", (input) => {
4651
+ var icon_manage_default = _template("M", (input) => {
4646
4652
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
4647
4653
  const $scope0_id = _scope_id();
4648
4654
  _set_serialize_reason({
@@ -4659,7 +4665,7 @@ var icon_manage_default = _template("L", (input) => {
4659
4665
  });
4660
4666
  //#endregion
4661
4667
  //#region src/tags/icons/icon-plus.marko
4662
- var icon_plus_default = _template("M", (input) => {
4668
+ var icon_plus_default = _template("N", (input) => {
4663
4669
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
4664
4670
  const $scope0_id = _scope_id();
4665
4671
  _set_serialize_reason({
@@ -5012,47 +5018,47 @@ var palette_default = _template("o", (input) => {
5012
5018
  _resume_branch($scope0_id);
5013
5019
  });
5014
5020
  var new_workspace_module_default = {
5015
- content: "_R _A",
5016
- actions: "_S",
5017
- barPrimary: "_T",
5018
- iconBtn: "_U _cw",
5019
- spinning: "_V _cx",
5020
- field: "_W",
5021
- section: "_X",
5022
- reposHead: "_Y",
5023
- curRepos: "_Z",
5024
- curRepo: "_0",
5025
- curFull: "_1",
5026
- curBase: "_2",
5027
- curRemove: "_3",
5028
- emptyNote: "_4",
5029
- steps: "_5",
5030
- active: "_6",
5031
- stepDone: "_7",
5032
- archived: "_8",
5033
- archivedCount: "_9",
5034
- archivedHint: "__",
5035
- archivedList: "_ba",
5036
- archivedCard: "_bb",
5037
- archivedMain: "_bc",
5038
- archivedName: "_bd",
5039
- archivedMeta: "_be",
5040
- restoreBtn: "_bf",
5041
- btn: "_bg"
5021
+ content: "_bj _bd",
5022
+ actions: "_bk",
5023
+ barPrimary: "_bl",
5024
+ iconBtn: "_bm _eA",
5025
+ spinning: "_bn _eB",
5026
+ field: "_bo",
5027
+ section: "_bp",
5028
+ reposHead: "_bq",
5029
+ curRepos: "_br",
5030
+ curRepo: "_bs",
5031
+ curFull: "_bt",
5032
+ curBase: "_bu",
5033
+ curRemove: "_bv",
5034
+ emptyNote: "_bw",
5035
+ steps: "_bx",
5036
+ active: "_by",
5037
+ stepDone: "_bz",
5038
+ archived: "_bA",
5039
+ archivedCount: "_bB",
5040
+ archivedHint: "_bC",
5041
+ archivedList: "_bD",
5042
+ archivedCard: "_bE",
5043
+ archivedMain: "_bF",
5044
+ archivedName: "_bG",
5045
+ archivedMeta: "_bH",
5046
+ restoreBtn: "_bI",
5047
+ btn: "_bJ"
5042
5048
  };
5043
5049
  var page_shell_module_default = {
5044
- page: "_y",
5045
- body: "_z",
5046
- content: "_A",
5047
- contentWide: "_B",
5048
- pageHead: "_C",
5049
- pageHeadText: "_D",
5050
- pageMeta: "_E",
5051
- pageHeadAside: "_F"
5050
+ page: "_bb",
5051
+ body: "_bc",
5052
+ content: "_bd",
5053
+ contentWide: "_be",
5054
+ pageHead: "_bf",
5055
+ pageHeadText: "_bg",
5056
+ pageMeta: "_bh",
5057
+ pageHeadAside: "_bi"
5052
5058
  };
5053
5059
  //#endregion
5054
5060
  //#region src/tags/icons/icon-refresh.marko
5055
- var icon_refresh_default = _template("N", (input) => {
5061
+ var icon_refresh_default = _template("O", (input) => {
5056
5062
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
5057
5063
  const $scope0_id = _scope_id();
5058
5064
  _set_serialize_reason({
@@ -5553,14 +5559,14 @@ function diffUncommitted() {
5553
5559
  return get("diff-uncommitted") === "1";
5554
5560
  }
5555
5561
  var work_view_module_default = {
5556
- workView: "_bh",
5557
- sideWrap: "_bi",
5558
- navPage: "_bj",
5559
- mainCol: "_bk",
5560
- termArea: "_bl",
5561
- asBar: "_bm",
5562
- padInline: "_bn",
5563
- emptySess: "_bo"
5562
+ workView: "_J",
5563
+ sideWrap: "_K",
5564
+ navPage: "_L",
5565
+ mainCol: "_M",
5566
+ termArea: "_N",
5567
+ asBar: "_O",
5568
+ padInline: "_P",
5569
+ emptySess: "_Q"
5564
5570
  };
5565
5571
  //#endregion
5566
5572
  //#region src/client/api.ts
@@ -5625,23 +5631,23 @@ function vapidKey(base64) {
5625
5631
  return Uint8Array.from(raw, (c) => c.charCodeAt(0));
5626
5632
  }
5627
5633
  var side_nav_module_default = {
5628
- iconBtn: "_cz _cw",
5629
- spinning: "_cA _cx",
5630
- navToggle: "_cB _cw",
5631
- notifyBtn: "_cC _cw",
5632
- sideNav: "_cD",
5633
- pageHead: "_cE",
5634
- pageHeadActions: "_cF",
5635
- sectionLabel: "_cG",
5636
- newSpaceBtn: "_cH",
5637
- page: "_cI",
5638
- sideList: "_cJ",
5639
- sideRail: "_cK",
5640
- sideFoot: "_cL",
5641
- footSpacer: "_cM",
5642
- on: "_cN",
5643
- closed: "_cO",
5644
- railPop: "_cP"
5634
+ iconBtn: "_dJ _eA",
5635
+ spinning: "_dK _eB",
5636
+ navToggle: "_dL _eA",
5637
+ notifyBtn: "_dM _eA",
5638
+ sideNav: "_dN",
5639
+ pageHead: "_dO",
5640
+ pageHeadActions: "_dP",
5641
+ sectionLabel: "_dQ",
5642
+ newSpaceBtn: "_dR",
5643
+ page: "_dS",
5644
+ sideList: "_dT",
5645
+ sideRail: "_dU",
5646
+ sideFoot: "_dV",
5647
+ footSpacer: "_dW",
5648
+ on: "_dX",
5649
+ closed: "_dY",
5650
+ railPop: "_dZ"
5645
5651
  };
5646
5652
  _template("C", (input) => {
5647
5653
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
@@ -5660,7 +5666,7 @@ _template("C", (input) => {
5660
5666
  });
5661
5667
  //#endregion
5662
5668
  //#region src/tags/icons/icon-gauge.marko
5663
- var icon_gauge_default = _template("I", (input) => {
5669
+ var icon_gauge_default = _template("J", (input) => {
5664
5670
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
5665
5671
  const $scope0_id = _scope_id();
5666
5672
  _set_serialize_reason({
@@ -5676,37 +5682,37 @@ var icon_gauge_default = _template("I", (input) => {
5676
5682
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
5677
5683
  });
5678
5684
  var side_nav_item_module_default = {
5679
- railBtn: "_eG _cw",
5680
- current: "_eH",
5681
- railDot: "_eI",
5682
- ws: "_eJ",
5683
- railPopWs: "_eK",
5684
- wsRow: "_eL",
5685
- wsBtn: "_eM",
5686
- wsActions: "_eN",
5687
- rowIcon: "_eO",
5688
- on: "_eP",
5689
- newSessionPop: "_eQ",
5690
- wsText: "_eR",
5691
- wsName: "_eS",
5692
- wsMeta: "_eT",
5693
- wsOpenHint: "_eU",
5694
- statusDot: "_eV",
5695
- pageCard: "_eW",
5696
- sessTitle: "_eX",
5697
- sessActions: "_eY",
5698
- sessRenameDot: "_eZ",
5699
- sessRename: "_e0",
5700
- close: "_e1",
5701
- sess: "_e2",
5702
- armed: "_e3",
5703
- sessions: "_e4",
5704
- sessBtn: "_e5",
5705
- sessIcon: "_e6"
5685
+ railBtn: "_e2 _eA",
5686
+ current: "_e3",
5687
+ railDot: "_e4",
5688
+ ws: "_e5",
5689
+ railPopWs: "_e6",
5690
+ wsRow: "_e7",
5691
+ wsBtn: "_e8",
5692
+ wsActions: "_e9",
5693
+ rowIcon: "_e_",
5694
+ on: "_fa",
5695
+ newSessionPop: "_fb",
5696
+ wsText: "_fc",
5697
+ wsName: "_fd",
5698
+ wsMeta: "_fe",
5699
+ wsOpenHint: "_ff",
5700
+ statusDot: "_fg",
5701
+ pageCard: "_fh",
5702
+ sessTitle: "_fi",
5703
+ sessActions: "_fj",
5704
+ sessRenameDot: "_fk",
5705
+ sessRename: "_fl",
5706
+ close: "_fm",
5707
+ sess: "_fn",
5708
+ armed: "_fo",
5709
+ sessions: "_fp",
5710
+ sessBtn: "_fq",
5711
+ sessIcon: "_fr"
5706
5712
  };
5707
5713
  //#endregion
5708
5714
  //#region src/tags/icons/icon-edit.marko
5709
- var icon_edit_default = _template("G", (input) => {
5715
+ var icon_edit_default = _template("H", (input) => {
5710
5716
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
5711
5717
  const $scope0_id = _scope_id();
5712
5718
  _set_serialize_reason({
@@ -5722,29 +5728,68 @@ var icon_edit_default = _template("G", (input) => {
5722
5728
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
5723
5729
  });
5724
5730
  var side_nav_chips_module_default = {
5725
- sideChips: "_fF",
5726
- prBtn: "_fG",
5727
- portChip: "_fH",
5728
- portOpen: "_fI",
5729
- portKill: "_fJ",
5730
- rejected: "_fK",
5731
- armed: "_fL"
5731
+ sideChips: "_fC",
5732
+ prChip: "_fD",
5733
+ portChip: "_fE",
5734
+ seg: "_fF",
5735
+ portOpen: "_fG",
5736
+ action: "_fH",
5737
+ dismiss: "_fI",
5738
+ armed: "_fJ",
5739
+ merged: "_fK",
5740
+ closed: "_fL"
5732
5741
  };
5733
5742
  //#endregion
5743
+ //#region src/tags/icons/icon-xmark.marko
5744
+ var icon_xmark_default = _template("U", (input) => {
5745
+ const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
5746
+ const $scope0_id = _scope_id();
5747
+ _set_serialize_reason({
5748
+ 0: $sg__input_size__OR__input_class,
5749
+ 1: $sg__input_size__OR__input_class
5750
+ });
5751
+ const $childScope = _peek_scope_id();
5752
+ icon_base_default({
5753
+ d: "M6.75827 17.2426L12.0009 12M17.2435 6.75736L12.0009 12M12.0009 12L6.75827 6.75736M12.0009 12L17.2435 17.2426",
5754
+ size: input.size,
5755
+ class: input.class
5756
+ });
5757
+ _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
5758
+ });
5759
+ //#endregion
5734
5760
  //#region src/tags/side-nav-chips.marko
5761
+ var prTitle = (repo, pr) => {
5762
+ const parts = [`${repo.worktree} — ${pr.title}`];
5763
+ if (pr.state === "MERGED") parts.push("merged");
5764
+ else if (pr.state === "CLOSED") parts.push("closed");
5765
+ else if (pr.isDraft) parts.push("draft");
5766
+ else parts.push("open");
5767
+ return parts.join(" · ");
5768
+ };
5769
+ var isOpen = (pr) => !pr.state || pr.state === "OPEN";
5735
5770
  var side_nav_chips_default = _template("r", (input) => {
5736
5771
  const $scope0_reason = _scope_reason(), $sg__input_status_repos = _serialize_guard($scope0_reason, 1), $si__input_status_repos = _serialize_if($scope0_reason, 1), $sg__input_status_ports = _serialize_guard($scope0_reason, 2), $sg__input_status_repos__OR__input_status_ports = _serialize_guard($scope0_reason, 0), $si__input_status_repos__OR__input_status_ports = _serialize_if($scope0_reason, 0);
5737
5772
  const $scope0_id = _scope_id();
5738
5773
  const $armedPid__closures = /* @__PURE__ */ new Set();
5739
5774
  let armedPid = null;
5740
5775
  const armBox = { timer: 0 };
5741
- const arm = _resume((pid) => {
5776
+ const armPid = _resume((pid) => {
5742
5777
  clearTimeout(armBox.timer);
5743
5778
  armedPid = pid;
5744
5779
  armBox.timer = setTimeout(() => {
5745
5780
  armedPid = null;
5746
5781
  }, 3500);
5747
5782
  }, "r0", $scope0_id);
5783
+ const dismissPr = _resume((fullName, number) => {
5784
+ fetch(`/api/workspaces/${input.workspaceId}/prs`, {
5785
+ method: "POST",
5786
+ headers: { "content-type": "application/json" },
5787
+ body: JSON.stringify({
5788
+ fullName,
5789
+ number
5790
+ })
5791
+ }).catch(() => {});
5792
+ }, "r1", $scope0_id);
5748
5793
  const repos = input.status?.repos || [];
5749
5794
  const ports = input.status?.ports || [];
5750
5795
  _if(() => {
@@ -5755,22 +5800,47 @@ var side_nav_chips_default = _template("r", (input) => {
5755
5800
  if (repos.length < 2) return "";
5756
5801
  const name = repo.full_name.split("/")[1];
5757
5802
  return repos.some((r) => r.full_name !== repo.full_name && r.full_name.split("/")[1] === name) ? repo.full_name : name;
5758
- }, "r1", $scope1_id);
5803
+ }, "r2", $scope1_id);
5759
5804
  _html(`<div${_attr_class(side_nav_chips_module_default.sideChips)}>`);
5760
5805
  _for_of(repos, (repo) => {
5761
5806
  const $scope2_id = _scope_id();
5762
5807
  _for_of(repo.prs || [], (pr) => {
5763
5808
  const $scope3_id = _scope_id();
5764
- _html(`<button type=button${_attr_class([
5809
+ const open = isOpen(pr);
5810
+ _html(`<span${_attr_class([
5765
5811
  ui_module_default.chip,
5766
- ui_module_default.pr,
5767
- side_nav_chips_module_default.prBtn,
5812
+ side_nav_chips_module_default.prChip,
5768
5813
  {
5769
- [ui_module_default.draft]: pr.isDraft,
5770
- [side_nav_chips_module_default.rejected]: pr.reviewDecision === "CHANGES_REQUESTED"
5814
+ [ui_module_default.pr]: open && !pr.isDraft,
5815
+ [ui_module_default.draft]: open && pr.isDraft,
5816
+ [side_nav_chips_module_default.merged]: pr.state === "MERGED",
5817
+ [side_nav_chips_module_default.closed]: pr.state === "CLOSED"
5771
5818
  }
5772
- ])}${_attr("title", `${repo.worktree}${pr.title}${pr.reviewDecision === "APPROVED" ? " (approved)" : pr.reviewDecision === "CHANGES_REQUESTED" ? " (changes requested)" : ""}`)}>${_escape(repoLabel(repo))}${_el_resume($scope3_id, "b", $sg__input_status_repos)}#${_sep($sg__input_status_repos)}${_escape(pr.number)}${_el_resume($scope3_id, "c", $sg__input_status_repos)}${_sep($sg__input_status_repos)}${pr.reviewDecision === "APPROVED" ? " ✓" : pr.reviewDecision === "CHANGES_REQUESTED" ? " ✗" : ""}${_el_resume($scope3_id, "d", $sg__input_status_repos)}</button>${_el_resume($scope3_id, "a")}`);
5773
- _script($scope3_id, "r2");
5819
+ ])}${_attr("title", prTitle(repo, pr))}><a${_attr_class(side_nav_chips_module_default.seg)}${_attr("href", pr.url)} target=_blank rel=noopener>${_escape(repoLabel(repo))}${_el_resume($scope3_id, "c", $sg__input_status_repos)}#${_sep($sg__input_status_repos)}${_escape(pr.number)}${_el_resume($scope3_id, "d", $sg__input_status_repos)}</a>${_el_resume($scope3_id, "b", $sg__input_status_repos)}`);
5820
+ _if(() => {
5821
+ if (open) {
5822
+ const $scope4_id = _scope_id();
5823
+ _html(`<button type=button${_attr_class([side_nav_chips_module_default.seg, side_nav_chips_module_default.action])}${_attr("title", `Review #${pr.number} diff`)}>`);
5824
+ icon_diff_default({ size: 12 });
5825
+ _html(`</button>${_el_resume($scope4_id, "a")}`);
5826
+ _script($scope4_id, "r3");
5827
+ writeScope($scope4_id, { _: _scope_with_id($scope3_id) });
5828
+ return 0;
5829
+ } else {
5830
+ const $scope6_id = _scope_id();
5831
+ _html(`<button type=button${_attr_class([
5832
+ side_nav_chips_module_default.seg,
5833
+ side_nav_chips_module_default.action,
5834
+ side_nav_chips_module_default.dismiss
5835
+ ])}${_attr("title", `Clear #${pr.number} from this list`)}>`);
5836
+ icon_xmark_default({ size: 12 });
5837
+ _html(`</button>${_el_resume($scope6_id, "a")}`);
5838
+ _script($scope6_id, "r4");
5839
+ writeScope($scope6_id, { _: _scope_with_id($scope3_id) });
5840
+ return 1;
5841
+ }
5842
+ }, $scope3_id, "e", $sg__input_status_repos, $sg__input_status_repos, $sg__input_status_repos, 0, 1);
5843
+ _html(`</span>${_el_resume($scope3_id, "a", $sg__input_status_repos)}`);
5774
5844
  _subscribe($si__input_status_repos && $if_content__repoLabel__closures, writeScope($scope3_id, {
5775
5845
  l: pr?.number,
5776
5846
  _: _scope_with_id($scope2_id)
@@ -5779,17 +5849,25 @@ var side_nav_chips_default = _template("r", (input) => {
5779
5849
  writeScope($scope2_id, {
5780
5850
  c: $si__input_status_repos && repo,
5781
5851
  e: repo?.worktree,
5852
+ f: repo?.full_name,
5782
5853
  _: _scope_with_id($scope1_id)
5783
5854
  });
5784
5855
  }, "full_name", $scope1_id, "b", $sg__input_status_repos, $sg__input_status_repos, $sg__input_status_repos__OR__input_status_ports);
5785
5856
  _for_of(ports, (p) => {
5786
- const $scope4_id = _scope_id();
5787
- _html(`<span${_attr_class([ui_module_default.chip, side_nav_chips_module_default.portChip])}${_attr("title", p.cmd)}><button type=button${_attr_class(side_nav_chips_module_default.portOpen)}${_attr("title", `Open http://${typeof location === "undefined" ? "localhost" : location.hostname}:${p.port}`)}>:${_sep($sg__input_status_ports)}${_escape(p.port)}${_el_resume($scope4_id, "c", $sg__input_status_ports)}</button>${_el_resume($scope4_id, "b")}<button type=button${_attr_class([side_nav_chips_module_default.portKill, { [side_nav_chips_module_default.armed]: armedPid === p.pid }])}${armedPid === p.pid ? _attr("title", `Really kill ${p.cmd}?`) : _attr("title", `Kill ${p.cmd} (pid ${p.pid})`)}>×</button>${_el_resume($scope4_id, "d")}</span>${_el_resume($scope4_id, "a", $sg__input_status_ports)}`);
5788
- _script($scope4_id, "r3");
5789
- _subscribe($armedPid__closures, writeScope($scope4_id, {
5790
- g: p?.cmd,
5791
- h: p?.port,
5792
- i: p?.pid,
5857
+ const $scope5_id = _scope_id();
5858
+ _html(`<span${_attr_class([ui_module_default.chip, side_nav_chips_module_default.portChip])}${_attr("title", p.cmd)}><button type=button${_attr_class([side_nav_chips_module_default.seg, side_nav_chips_module_default.portOpen])}${_attr("title", `Open http://${typeof location === "undefined" ? "localhost" : location.hostname}:${p.port}`)}>:${_sep($sg__input_status_ports)}${_escape(p.port)}${_el_resume($scope5_id, "c", $sg__input_status_ports)}</button>${_el_resume($scope5_id, "b")}<button type=button${_attr_class([
5859
+ side_nav_chips_module_default.seg,
5860
+ side_nav_chips_module_default.action,
5861
+ side_nav_chips_module_default.dismiss,
5862
+ { [side_nav_chips_module_default.armed]: armedPid === p.pid }
5863
+ ])}${armedPid === p.pid ? _attr("title", `Really kill ${p.cmd}?`) : _attr("title", `Kill ${p.cmd} (pid ${p.pid})`)}>`);
5864
+ icon_xmark_default({ size: 12 });
5865
+ _html(`</button>${_el_resume($scope5_id, "d")}</span>${_el_resume($scope5_id, "a", $sg__input_status_ports)}`);
5866
+ _script($scope5_id, "r5");
5867
+ _subscribe($armedPid__closures, writeScope($scope5_id, {
5868
+ h: p?.cmd,
5869
+ i: p?.port,
5870
+ j: p?.pid,
5793
5871
  _: _scope_with_id($scope1_id)
5794
5872
  }));
5795
5873
  }, "port", $scope1_id, "c", $sg__input_status_ports, $sg__input_status_ports, $sg__input_status_repos__OR__input_status_ports, 0, 1);
@@ -5803,21 +5881,23 @@ var side_nav_chips_default = _template("r", (input) => {
5803
5881
  }
5804
5882
  }, $scope0_id, "a", $sg__input_status_repos__OR__input_status_ports, $sg__input_status_repos__OR__input_status_ports, $sg__input_status_repos__OR__input_status_ports, 0, 1);
5805
5883
  writeScope($scope0_id, {
5806
- g: input.onReviewPr,
5807
- h: armedPid,
5808
- j: armBox.timer,
5809
- k: arm,
5810
- l: $si__input_status_repos__OR__input_status_ports && repos,
5811
- m: $si__input_status_repos__OR__input_status_ports && ports,
5812
- n: $si__input_status_repos && ports.length,
5813
- p: $armedPid__closures
5884
+ d: input.workspaceId,
5885
+ h: input.onReviewPr,
5886
+ i: armedPid,
5887
+ k: armBox.timer,
5888
+ l: armPid,
5889
+ m: dismissPr,
5890
+ n: $si__input_status_repos__OR__input_status_ports && repos,
5891
+ o: $si__input_status_repos__OR__input_status_ports && ports,
5892
+ p: $si__input_status_repos && ports.length,
5893
+ r: $armedPid__closures
5814
5894
  });
5815
5895
  _resume_branch($scope0_id);
5816
5896
  });
5817
5897
  //#endregion
5818
5898
  //#region src/tags/side-nav-item.marko
5819
5899
  var side_nav_item_default = _template("s", (input) => {
5820
- const $scope0_reason = _scope_reason(), $sg__input_workspaceId__OR__input_status = _serialize_guard($scope0_reason, 1), $sg__input_page = _serialize_guard($scope0_reason, 22), $si__input_current = _serialize_if($scope0_reason, 18), $sg__input_agents = _serialize_guard($scope0_reason, 24), $si__input_agents = _serialize_if($scope0_reason, 24), $sg__input_onNewSession = _serialize_guard($scope0_reason, 23), $sg__input_onNewSession__OR__input_onReview = _serialize_guard($scope0_reason, 2), $sg__input_onReview = _serialize_guard($scope0_reason, 25), $sg__input_sessions = _serialize_guard($scope0_reason, 20), $si__input_sessions = _serialize_if($scope0_reason, 20), $si__input_workspaces__OR__input_workspaceId = _serialize_if($scope0_reason, 0), $si__input_workspaceId__OR__input_status = _serialize_if($scope0_reason, 1), $si__input_page = _serialize_if($scope0_reason, 22), $sg__input_rail = _serialize_guard($scope0_reason, 17), $si__input_rail = _serialize_if($scope0_reason, 17), $sg__input_workspaces__OR__input_workspaceId = _serialize_guard($scope0_reason, 0), $si__input_workspaces__OR__input_workspaceId__OR__input_rail = _serialize_if($scope0_reason, 4), $si__input_workspaces__OR__input_workspaceId__OR__input_rail__OR__input_current__OR__input_page = _serialize_if($scope0_reason, 13), $si__input_index = _serialize_if($scope0_reason, 19), $si__input_onNewSession = _serialize_if($scope0_reason, 23), $si__input_onReview = _serialize_if($scope0_reason, 25), $si__input_managing = _serialize_if($scope0_reason, 26), $si__input_currentTab = _serialize_if($scope0_reason, 27), $si__input_railPop = _serialize_if($scope0_reason, 21), $si__input_onReviewPr = _serialize_if($scope0_reason, 28);
5900
+ const $scope0_reason = _scope_reason(), $sg__input_workspaceId__OR__input_status = _serialize_guard($scope0_reason, 1), $sg__input_page = _serialize_guard($scope0_reason, 21), $si__input_current = _serialize_if($scope0_reason, 17), $sg__input_agents = _serialize_guard($scope0_reason, 23), $si__input_agents = _serialize_if($scope0_reason, 23), $sg__input_onNewSession = _serialize_guard($scope0_reason, 22), $sg__input_onNewSession__OR__input_onReview = _serialize_guard($scope0_reason, 2), $sg__input_onReview = _serialize_guard($scope0_reason, 24), $sg__input_sessions = _serialize_guard($scope0_reason, 19), $si__input_sessions = _serialize_if($scope0_reason, 19), $si__input_workspaces__OR__input_workspaceId = _serialize_if($scope0_reason, 0), $si__input_workspaceId__OR__input_status = _serialize_if($scope0_reason, 1), $si__input_page = _serialize_if($scope0_reason, 21), $sg__input_rail = _serialize_guard($scope0_reason, 16), $si__input_rail = _serialize_if($scope0_reason, 16), $sg__input_workspaces__OR__input_workspaceId = _serialize_guard($scope0_reason, 0), $si__input_workspaceId = _serialize_if($scope0_reason, 15), $si__input_workspaces__OR__input_workspaceId__OR__input_rail = _serialize_if($scope0_reason, 3), $si__input_workspaces__OR__input_workspaceId__OR__input_rail__OR__input_current__OR__input_page = _serialize_if($scope0_reason, 12), $si__input_index = _serialize_if($scope0_reason, 18), $si__input_onNewSession = _serialize_if($scope0_reason, 22), $si__input_onReview = _serialize_if($scope0_reason, 24), $si__input_managing = _serialize_if($scope0_reason, 25), $si__input_currentTab = _serialize_if($scope0_reason, 26), $si__input_railPop = _serialize_if($scope0_reason, 20), $si__input_onReviewPr = _serialize_if($scope0_reason, 27);
5821
5901
  const $scope0_id = _scope_id();
5822
5902
  const $input_current__closures = /* @__PURE__ */ new Set();
5823
5903
  const $input_index__closures = /* @__PURE__ */ new Set();
@@ -5830,6 +5910,7 @@ var side_nav_item_default = _template("s", (input) => {
5830
5910
  const $armedKill__closures = /* @__PURE__ */ new Set();
5831
5911
  const $input_currentTab__closures = /* @__PURE__ */ new Set();
5832
5912
  const $renamingId__closures = /* @__PURE__ */ new Set();
5913
+ const $input_workspaceId__closures = /* @__PURE__ */ new Set();
5833
5914
  const $input_sessions__closures = /* @__PURE__ */ new Set();
5834
5915
  const $input_railPop__closures = /* @__PURE__ */ new Set();
5835
5916
  const $input_page__closures = /* @__PURE__ */ new Set();
@@ -5860,7 +5941,7 @@ var side_nav_item_default = _template("s", (input) => {
5860
5941
  _if(() => {
5861
5942
  if (input.rail) {
5862
5943
  const $scope2_id = _scope_id();
5863
- _html(`<button${_attr_class([side_nav_item_module_default.railBtn, { [side_nav_item_module_default.current]: input.current }])}${_attr("title", ws.name)}>${_escape((input.index ?? 0) + 1)}${_el_resume($scope2_id, "b", _serialize_guard($scope0_reason, 19))}<span${_attr_class([
5944
+ _html(`<button${_attr_class([side_nav_item_module_default.railBtn, { [side_nav_item_module_default.current]: input.current }])}${_attr("title", ws.name)}>${_escape((input.index ?? 0) + 1)}${_el_resume($scope2_id, "b", _serialize_guard($scope0_reason, 18))}<span${_attr_class([
5864
5945
  ui_module_default.dot,
5865
5946
  ui_module_default[dot],
5866
5947
  side_nav_item_module_default.railDot
@@ -5885,16 +5966,16 @@ var side_nav_item_default = _template("s", (input) => {
5885
5966
  _if(() => {
5886
5967
  if (input.page) {
5887
5968
  const $scope12_id = _scope_id();
5888
- _html(`<span${_attr_class(side_nav_item_module_default.wsMeta)}>${_escape(meta)}${_el_resume($scope12_id, "b", _serialize_guard($scope0_reason, 6))}</span>`);
5889
- _serialize_if($scope0_reason, 11) && writeScope($scope12_id, { _: _serialize_if($scope0_reason, 6) && _scope_with_id($scope3_id) });
5969
+ _html(`<span${_attr_class(side_nav_item_module_default.wsMeta)}>${_escape(meta)}${_el_resume($scope12_id, "b", _serialize_guard($scope0_reason, 5))}</span>`);
5970
+ _serialize_if($scope0_reason, 10) && writeScope($scope12_id, { _: _serialize_if($scope0_reason, 5) && _scope_with_id($scope3_id) });
5890
5971
  return 0;
5891
5972
  }
5892
- }, $scope3_id, "h", _serialize_guard($scope0_reason, 11), $sg__input_page, $sg__input_page, 0, 1);
5973
+ }, $scope3_id, "h", _serialize_guard($scope0_reason, 10), $sg__input_page, $sg__input_page, 0, 1);
5893
5974
  _html("</span>");
5894
5975
  _if(() => {
5895
5976
  if (input.page) {
5896
5977
  const $scope4_id = _scope_id();
5897
- _html(`<span${_attr_class(side_nav_item_module_default.wsOpenHint)}>${input.current ? "Open" : ""}${_el_resume($scope4_id, "b", _serialize_guard($scope0_reason, 18))}</span>`);
5978
+ _html(`<span${_attr_class(side_nav_item_module_default.wsOpenHint)}>${input.current ? "Open" : ""}${_el_resume($scope4_id, "b", _serialize_guard($scope0_reason, 17))}</span>`);
5898
5979
  $si__input_workspaces__OR__input_workspaceId__OR__input_rail__OR__input_current__OR__input_page && _subscribe($si__input_current && $input_current__closures, writeScope($scope4_id, {
5899
5980
  _: _scope_with_id($scope3_id),
5900
5981
  Cab: $si__input_current && 2
@@ -6026,25 +6107,26 @@ var side_nav_item_default = _template("s", (input) => {
6026
6107
  });
6027
6108
  const $childScope4 = _peek_scope_id();
6028
6109
  side_nav_chips_default({
6110
+ workspaceId: input.workspaceId,
6029
6111
  status: st,
6030
6112
  onReviewPr: input.onReviewPr
6031
6113
  });
6032
6114
  _html(`</div></section>${_el_resume($scope3_id, "a")}`);
6033
6115
  _script($scope3_id, "s10");
6034
- _subscribe($si__input_workspaces__OR__input_workspaceId && $ws_name__closures, _subscribe($si__input_onReviewPr && $input_onReviewPr__closures, _subscribe($si__input_page && $input_page__closures, _subscribe($si__input_railPop && $input_railPop__closures, _subscribe($si__input_sessions && $input_sessions__closures, _subscribe($si__input_current && $input_current__closures, writeScope($scope3_id, {
6116
+ _subscribe($si__input_workspaces__OR__input_workspaceId && $ws_name__closures, _subscribe($si__input_onReviewPr && $input_onReviewPr__closures, _subscribe($si__input_page && $input_page__closures, _subscribe($si__input_railPop && $input_railPop__closures, _subscribe($si__input_sessions && $input_sessions__closures, _subscribe($si__input_current && $input_current__closures, _subscribe($si__input_workspaceId && $input_workspaceId__closures, writeScope($scope3_id, {
6035
6117
  o: $si__input_workspaceId__OR__input_status && sessions.length,
6036
6118
  q: $si__input_workspaceId__OR__input_status && sessions[0]?.title,
6037
6119
  r: $si__input_workspaceId__OR__input_status && sessions[0]?.agent,
6038
6120
  s: $si__input_sessions && phaseLabel,
6039
6121
  u: $si__input_page && meta,
6040
6122
  _: _scope_with_id($scope1_id),
6041
- m: _serialize_if($scope0_reason, 7) && _existing_scope($childScope4),
6123
+ m: _serialize_if($scope0_reason, 6) && _existing_scope($childScope4),
6042
6124
  Cab: $si__input_current && 1,
6043
6125
  Cap: $si__input_workspaces__OR__input_workspaceId && 1
6044
- })))))));
6126
+ }))))))));
6045
6127
  return 1;
6046
6128
  }
6047
- }, $scope1_id, "a", _serialize_guard($scope0_reason, 5), $sg__input_rail, $sg__input_rail, 0, 1);
6129
+ }, $scope1_id, "a", _serialize_guard($scope0_reason, 4), $sg__input_rail, $sg__input_rail, 0, 1);
6048
6130
  writeScope($scope1_id, {
6049
6131
  b: $si__input_rail && st,
6050
6132
  c: $si__input_rail && dot,
@@ -6052,25 +6134,25 @@ var side_nav_item_default = _template("s", (input) => {
6052
6134
  });
6053
6135
  return 0;
6054
6136
  }
6055
- }, $scope0_id, "a", _serialize_guard($scope0_reason, 8), $sg__input_workspaces__OR__input_workspaceId, $sg__input_workspaces__OR__input_workspaceId);
6137
+ }, $scope0_id, "a", _serialize_guard($scope0_reason, 7), $sg__input_workspaces__OR__input_workspaceId, $sg__input_workspaces__OR__input_workspaceId);
6056
6138
  writeScope($scope0_id, {
6057
6139
  d: input.onRenameSession,
6058
- e: _serialize_if($scope0_reason, 16) && input.workspaces,
6059
- f: _serialize_if($scope0_reason, 3) && input.workspaceId,
6140
+ e: $si__input_workspaceId && input.workspaces,
6141
+ f: _serialize_if($scope0_reason, 7) && input.workspaceId,
6060
6142
  h: $si__input_workspaces__OR__input_workspaceId && input.status,
6061
6143
  i: $si__input_workspaces__OR__input_workspaceId && input.rail,
6062
- j: _serialize_if($scope0_reason, 14) && input.current,
6144
+ j: _serialize_if($scope0_reason, 13) && input.current,
6063
6145
  k: input.onSelect,
6064
6146
  l: $si__input_workspaces__OR__input_workspaceId__OR__input_rail && input.index,
6065
6147
  m: $si__input_workspaces__OR__input_workspaceId__OR__input_rail && input.sessions,
6066
6148
  n: $si__input_workspaces__OR__input_workspaceId__OR__input_rail__OR__input_current__OR__input_page && input.railPop,
6067
- o: _serialize_if($scope0_reason, 12) && input.page,
6149
+ o: _serialize_if($scope0_reason, 11) && input.page,
6068
6150
  p: input.onNewSession,
6069
- q: _serialize_if($scope0_reason, 15) && input.agents,
6151
+ q: _serialize_if($scope0_reason, 14) && input.agents,
6070
6152
  r: input.onReview,
6071
- s: _serialize_if($scope0_reason, 10) && input.managing,
6153
+ s: _serialize_if($scope0_reason, 9) && input.managing,
6072
6154
  t: input.onManage,
6073
- u: _serialize_if($scope0_reason, 9) && input.currentTab,
6155
+ u: _serialize_if($scope0_reason, 8) && input.currentTab,
6074
6156
  v: input.onOpenTab,
6075
6157
  w: input.onCloseSession,
6076
6158
  x: $si__input_workspaces__OR__input_workspaceId__OR__input_rail && input.onReviewPr,
@@ -6092,6 +6174,7 @@ var side_nav_item_default = _template("s", (input) => {
6092
6174
  am: $armedKill__closures,
6093
6175
  ak: $si__input_currentTab && $input_currentTab__closures,
6094
6176
  an: $renamingId__closures,
6177
+ a8: $si__input_workspaceId && $input_workspaceId__closures,
6095
6178
  ad: $si__input_sessions && $input_sessions__closures,
6096
6179
  ae: $si__input_railPop && $input_railPop__closures,
6097
6180
  af: $si__input_page && $input_page__closures,
@@ -6101,7 +6184,7 @@ var side_nav_item_default = _template("s", (input) => {
6101
6184
  });
6102
6185
  //#endregion
6103
6186
  //#region src/tags/icons/icon-folder-plus.marko
6104
- var icon_folder_plus_default = _template("H", (input) => {
6187
+ var icon_folder_plus_default = _template("I", (input) => {
6105
6188
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
6106
6189
  const $scope0_id = _scope_id();
6107
6190
  _set_serialize_reason({
@@ -6118,7 +6201,7 @@ var icon_folder_plus_default = _template("H", (input) => {
6118
6201
  });
6119
6202
  //#endregion
6120
6203
  //#region src/tags/icons/icon-sidebar-collapse.marko
6121
- var icon_sidebar_collapse_default = _template("P", (input) => {
6204
+ var icon_sidebar_collapse_default = _template("Q", (input) => {
6122
6205
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
6123
6206
  const $scope0_id = _scope_id();
6124
6207
  _set_serialize_reason({
@@ -6135,7 +6218,7 @@ var icon_sidebar_collapse_default = _template("P", (input) => {
6135
6218
  });
6136
6219
  //#endregion
6137
6220
  //#region src/tags/icons/icon-sidebar.marko
6138
- var icon_sidebar_default = _template("Q", (input) => {
6221
+ var icon_sidebar_default = _template("R", (input) => {
6139
6222
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
6140
6223
  const $scope0_id = _scope_id();
6141
6224
  _set_serialize_reason({
@@ -6153,7 +6236,7 @@ var icon_sidebar_default = _template("Q", (input) => {
6153
6236
  //#endregion
6154
6237
  //#region src/tags/side-nav.marko
6155
6238
  var side_nav_default = _template("t", (input) => {
6156
- const $scope0_reason = _scope_reason(), $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus = _serialize_guard($scope0_reason, 1), $sg__input_workspace__OR__input_allWorkspaces = _serialize_guard($scope0_reason, 0), $sg__input_agents = _serialize_guard($scope0_reason, 10), $sg__input_workspace = _serialize_guard($scope0_reason, 2), $si__input_workspace = _serialize_if($scope0_reason, 2), $si__input_workspace__OR__input_allWorkspaces = _serialize_if($scope0_reason, 0), $si__input_allStatus = _serialize_if($scope0_reason, 8), $si__input_onSelectWorkspace = _serialize_if($scope0_reason, 9), $si__input_agents = _serialize_if($scope0_reason, 10), $si__input_onNewSession = _serialize_if($scope0_reason, 11), $si__input_onReviewOpened = _serialize_if($scope0_reason, 12), $si__input_sessions = _serialize_if($scope0_reason, 13), $si__input_onRenameSession = _serialize_if($scope0_reason, 14), $si__input_onCloseSession = _serialize_if($scope0_reason, 15);
6239
+ const $scope0_reason = _scope_reason(), $sg__input_workspace__OR__input_allWorkspaces = _serialize_guard($scope0_reason, 0), $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus = _serialize_guard($scope0_reason, 1), $sg__input_agents = _serialize_guard($scope0_reason, 10), $sg__input_workspace = _serialize_guard($scope0_reason, 2), $si__input_workspace = _serialize_if($scope0_reason, 2), $si__input_workspace__OR__input_allWorkspaces = _serialize_if($scope0_reason, 0), $si__input_allStatus = _serialize_if($scope0_reason, 8), $si__input_onSelectWorkspace = _serialize_if($scope0_reason, 9), $si__input_agents = _serialize_if($scope0_reason, 10), $si__input_onNewSession = _serialize_if($scope0_reason, 11), $si__input_onReviewOpened = _serialize_if($scope0_reason, 12), $si__input_sessions = _serialize_if($scope0_reason, 13), $si__input_onRenameSession = _serialize_if($scope0_reason, 14), $si__input_onCloseSession = _serialize_if($scope0_reason, 15);
6157
6240
  const $scope0_id = _scope_id();
6158
6241
  const $notifyOn__closures = /* @__PURE__ */ new Set();
6159
6242
  const $ws_id__closures = /* @__PURE__ */ new Set();
@@ -6253,16 +6336,15 @@ var side_nav_default = _template("t", (input) => {
6253
6336
  13: 1,
6254
6337
  14: 1,
6255
6338
  15: 1,
6256
- 16: 1,
6257
- 18: 1,
6258
- 20: 1,
6339
+ 17: 1,
6340
+ 19: 1,
6341
+ 21: 1,
6259
6342
  22: 1,
6260
- 23: 1,
6261
- 24: $sg__input_agents,
6343
+ 23: $sg__input_agents,
6344
+ 24: 1,
6262
6345
  25: 1,
6263
6346
  26: 1,
6264
- 27: 1,
6265
- 28: $sg__input_workspace
6347
+ 27: $sg__input_workspace
6266
6348
  });
6267
6349
  const $childScope = _peek_scope_id();
6268
6350
  side_nav_item_default({
@@ -6338,22 +6420,21 @@ var side_nav_default = _template("t", (input) => {
6338
6420
  _set_serialize_reason({
6339
6421
  0: $sg__input_workspace__OR__input_allWorkspaces,
6340
6422
  1: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6341
- 3: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6342
- 4: $sg__input_workspace__OR__input_allWorkspaces,
6423
+ 3: $sg__input_workspace__OR__input_allWorkspaces,
6424
+ 4: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6343
6425
  5: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6344
6426
  6: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6345
6427
  7: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6346
- 8: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6428
+ 8: $sg__input_workspace__OR__input_allWorkspaces,
6347
6429
  9: $sg__input_workspace__OR__input_allWorkspaces,
6348
- 10: $sg__input_workspace__OR__input_allWorkspaces,
6349
- 11: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6430
+ 10: $sg__input_workspace__OR__input_allWorkspaces__OR__input_allStatus,
6431
+ 11: 1,
6350
6432
  12: 1,
6351
- 13: 1,
6433
+ 13: $sg__input_workspace__OR__input_allWorkspaces,
6352
6434
  14: $sg__input_workspace__OR__input_allWorkspaces,
6353
6435
  15: $sg__input_workspace__OR__input_allWorkspaces,
6354
- 16: $sg__input_workspace__OR__input_allWorkspaces,
6355
- 18: 1,
6356
- 19: $sg__input_workspace__OR__input_allWorkspaces
6436
+ 17: 1,
6437
+ 18: $sg__input_workspace__OR__input_allWorkspaces
6357
6438
  });
6358
6439
  const $childScope2 = _peek_scope_id();
6359
6440
  side_nav_item_default({
@@ -6398,15 +6479,14 @@ var side_nav_default = _template("t", (input) => {
6398
6479
  13: 1,
6399
6480
  14: 1,
6400
6481
  15: 1,
6401
- 16: 1,
6402
- 18: 1,
6403
- 20: 1,
6404
- 23: 1,
6405
- 24: $sg__input_agents,
6482
+ 17: 1,
6483
+ 19: 1,
6484
+ 22: 1,
6485
+ 23: $sg__input_agents,
6486
+ 24: 1,
6406
6487
  25: 1,
6407
6488
  26: 1,
6408
- 27: 1,
6409
- 28: $sg__input_workspace
6489
+ 27: $sg__input_workspace
6410
6490
  });
6411
6491
  const $childScope3 = _peek_scope_id();
6412
6492
  side_nav_item_default({
@@ -6834,61 +6914,61 @@ function treeRows(files) {
6834
6914
  return rows;
6835
6915
  }
6836
6916
  var diff_view_module_default = {
6837
- iconBtn: "_dO _cw",
6838
- spinning: "_dP _cx",
6839
- diffView: "_dQ",
6840
- treeToggle: "_dR _cw",
6841
- diffTools: "_dS",
6842
- on: "_dT",
6843
- diffCol: "_dU",
6844
- chrome: "_dV",
6845
- backBtn: "_dW",
6846
- headText: "_dX",
6847
- pageTitle: "_dY",
6848
- headWithSend: "_dZ",
6849
- toolCtrl: "_d0",
6850
- findBtn: "_d1",
6851
- findSlot: "_d2",
6852
- findSlotClosed: "_d3",
6853
- toolsFind: "_d4",
6854
- fileFindActive: "_d5",
6855
- pathFindActive: "_d6",
6856
- diffMain: "_d7",
6857
- toastMeta: "_d8",
6858
- diffHead: "_d9",
6859
- filterSlot: "_d_",
6860
- diffStats: "_ea",
6861
- statAdd: "_eb",
6862
- statDel: "_ec",
6863
- statEmpty: "_ed",
6864
- statSep: "_ee",
6865
- scope: "_ef",
6866
- scopeOpt: "_eg",
6867
- scopeOn: "_eh",
6868
- scopeChip: "_ei",
6869
- repoSection: "_ej",
6870
- repoSep: "_ek",
6871
- repoSepCollapsed: "_el",
6872
- repoWorktree: "_em _k",
6873
- repoState: "_en",
6874
- repoTitle: "_eo _j",
6875
- repoMeta: "_ep",
6876
- compare: "_eq",
6877
- compareBase: "_er",
6878
- compareHead: "_es",
6879
- compareVs: "_et",
6880
- compareTopic: "_eu",
6881
- files: "_ev",
6882
- file: "_ew",
6883
- diffWait: "_ex",
6884
- treeChev: "_ey",
6885
- treeChevOpen: "_ez",
6886
- treeChevBusy: "_eA",
6887
- status: "_eB",
6888
- path: "_eC",
6889
- centerPad: "_eD",
6890
- filesBtn: "_eE",
6891
- diffPad: "_eF"
6917
+ iconBtn: "_cR _eA",
6918
+ spinning: "_cS _eB",
6919
+ diffView: "_cT",
6920
+ treeToggle: "_cU _eA",
6921
+ diffTools: "_cV",
6922
+ on: "_cW",
6923
+ diffCol: "_cX",
6924
+ chrome: "_cY",
6925
+ backBtn: "_cZ",
6926
+ headText: "_c0",
6927
+ pageTitle: "_c1",
6928
+ headWithSend: "_c2",
6929
+ toolCtrl: "_c3",
6930
+ findBtn: "_c4",
6931
+ findSlot: "_c5",
6932
+ findSlotClosed: "_c6",
6933
+ toolsFind: "_c7",
6934
+ fileFindActive: "_c8",
6935
+ pathFindActive: "_c9",
6936
+ diffMain: "_c_",
6937
+ toastMeta: "_da",
6938
+ diffHead: "_db",
6939
+ filterSlot: "_dc",
6940
+ diffStats: "_dd",
6941
+ statAdd: "_de",
6942
+ statDel: "_df",
6943
+ statEmpty: "_dg",
6944
+ statSep: "_dh",
6945
+ scope: "_di",
6946
+ scopeOpt: "_dj",
6947
+ scopeOn: "_dk",
6948
+ scopeChip: "_dl",
6949
+ repoSection: "_dm",
6950
+ repoSep: "_dn",
6951
+ repoSepCollapsed: "_do",
6952
+ repoWorktree: "_dp _l",
6953
+ repoState: "_dq",
6954
+ repoTitle: "_dr _k",
6955
+ repoMeta: "_ds",
6956
+ compare: "_dt",
6957
+ compareBase: "_du",
6958
+ compareHead: "_dv",
6959
+ compareVs: "_dw",
6960
+ compareTopic: "_dx",
6961
+ files: "_dy",
6962
+ file: "_dz",
6963
+ diffWait: "_dA",
6964
+ treeChev: "_dB",
6965
+ treeChevOpen: "_dC",
6966
+ treeChevBusy: "_dD",
6967
+ status: "_dE",
6968
+ path: "_dF",
6969
+ centerPad: "_dG",
6970
+ filesBtn: "_dH",
6971
+ diffPad: "_dI"
6892
6972
  };
6893
6973
  //#endregion
6894
6974
  //#region src/tags/icons/icon-back.marko
@@ -6908,8 +6988,8 @@ var icon_back_default = _template("A", (input) => {
6908
6988
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
6909
6989
  });
6910
6990
  var file_filter_module_default = {
6911
- wrap: "_fg",
6912
- fileFilter: "_fh"
6991
+ wrap: "_eZ",
6992
+ fileFilter: "_e0"
6913
6993
  };
6914
6994
  //#endregion
6915
6995
  //#region src/tags/file-filter.marko
@@ -6957,7 +7037,7 @@ var file_filter_default = _template("j", (input) => {
6957
7037
  });
6958
7038
  _resume_branch($scope0_id);
6959
7039
  });
6960
- var diff_send_module_default = { headActions: "_fs" };
7040
+ var diff_send_module_default = { headActions: "_e1" };
6961
7041
  //#endregion
6962
7042
  //#region src/tags/diff-send.marko
6963
7043
  var diff_send_default = _template("g", (input) => {
@@ -8449,17 +8529,17 @@ function clip(line, at, len) {
8449
8529
  return (start > 0 ? "…" : "") + line.slice(start, end) + (end < line.length ? "…" : "");
8450
8530
  }
8451
8531
  var diff_find_module_default = {
8452
- findBar: "_fu",
8453
- closed: "_fv",
8454
- findInput: "_fw",
8455
- termOverlay: "_fx",
8456
- count: "_fy",
8457
- findIconBtn: "_fz _cw",
8458
- findWrap: "_fA",
8459
- termOverlayWrap: "_fB",
8460
- termKeybarWrap: "_fC",
8461
- termKeybar: "_fD",
8462
- termClosed: "_fE"
8532
+ findBar: "_eD",
8533
+ closed: "_eE",
8534
+ findInput: "_eF",
8535
+ termOverlay: "_eG",
8536
+ count: "_eH",
8537
+ findIconBtn: "_eI _eA",
8538
+ findWrap: "_eJ",
8539
+ termOverlayWrap: "_eK",
8540
+ termKeybarWrap: "_eL",
8541
+ termKeybar: "_eM",
8542
+ termClosed: "_eN"
8463
8543
  };
8464
8544
  //#endregion
8465
8545
  //#region src/tags/diff-find.marko
@@ -8567,7 +8647,7 @@ var diff_find_default = _template("f", (input) => {
8567
8647
  });
8568
8648
  //#endregion
8569
8649
  //#region src/tags/icons/icon-search.marko
8570
- var icon_search_default = _template("O", (input) => {
8650
+ var icon_search_default = _template("P", (input) => {
8571
8651
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
8572
8652
  const $scope0_id = _scope_id();
8573
8653
  _set_serialize_reason({
@@ -8582,7 +8662,7 @@ var icon_search_default = _template("O", (input) => {
8582
8662
  });
8583
8663
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
8584
8664
  });
8585
- var diff_file_module_default = { diffFile: "_ft" };
8665
+ var diff_file_module_default = { diffFile: "_eO" };
8586
8666
  //#endregion
8587
8667
  //#region src/tags/diff-file.marko
8588
8668
  var diff_file_default = _template("e", (input) => {
@@ -8607,16 +8687,16 @@ var diff_file_default = _template("e", (input) => {
8607
8687
  _resume_branch($scope0_id);
8608
8688
  });
8609
8689
  var diff_tree_module_default = {
8610
- tree: "_fi",
8611
- closed: "_fj",
8612
- treeRepo: "_fk",
8613
- treeRepoName: "_fl",
8614
- treeDir: "_fm",
8615
- treeFile: "_fn",
8616
- treeFileName: "_fo",
8617
- treeNote: "_fp",
8618
- treeChev: "_fq",
8619
- status: "_fr"
8690
+ tree: "_fs",
8691
+ closed: "_ft",
8692
+ treeRepo: "_fu",
8693
+ treeRepoName: "_fv",
8694
+ treeDir: "_fw",
8695
+ treeFile: "_fx",
8696
+ treeFileName: "_fy",
8697
+ treeNote: "_fz",
8698
+ treeChev: "_fA",
8699
+ status: "_fB"
8620
8700
  };
8621
8701
  //#endregion
8622
8702
  //#region src/tags/diff-tree.marko
@@ -8730,16 +8810,16 @@ var diff_tree_default = _template("h", (input) => {
8730
8810
  _resume_branch($scope0_id);
8731
8811
  });
8732
8812
  var diff_file_sheet_module_default = {
8733
- iconBtn: "_e7 _cw",
8734
- spinning: "_e8 _cx",
8735
- sheetBackdrop: "_e9",
8736
- fileSheet: "_e_",
8737
- sheetHead: "_fa",
8738
- fileCount: "_fb",
8739
- sheetList: "_fc",
8740
- sheetFile: "_fd",
8741
- sheetPath: "_fe",
8742
- status: "_ff"
8813
+ iconBtn: "_eP _eA",
8814
+ spinning: "_eQ _eB",
8815
+ sheetBackdrop: "_eR",
8816
+ fileSheet: "_eS",
8817
+ sheetHead: "_eT",
8818
+ fileCount: "_eU",
8819
+ sheetList: "_eV",
8820
+ sheetFile: "_eW",
8821
+ sheetPath: "_eX",
8822
+ status: "_eY"
8743
8823
  };
8744
8824
  //#endregion
8745
8825
  //#region src/tags/diff-file-sheet.marko
@@ -9853,41 +9933,37 @@ var diff_view_default = _template("i", (input) => {
9853
9933
  _resume_branch($scope0_id);
9854
9934
  });
9855
9935
  var manage_workspace_module_default = {
9856
- content: "_df _A",
9857
- pageMeta: "_dg _E",
9858
- wsLabel: "_dh",
9859
- metaSep: "_di",
9860
- pathMeta: "_dj",
9861
- statusPill: "_dk",
9862
- statusOff: "_dl",
9863
- progress: "_dm",
9864
- section: "_dn",
9865
- sectionHead: "_do",
9866
- sectionCount: "_dp",
9867
- sectionBtn: "_dq",
9868
- groupLabel: "_dr",
9869
- pickerWrap: "_ds",
9870
- cardList: "_dt",
9871
- card: "_du",
9872
- pending: "_dv",
9873
- cardMain: "_dw",
9874
- cardTitle: "_dx",
9875
- cardMeta: "_dy",
9876
- cardSub: "_dz",
9877
- cardTag: "_dA",
9878
- cardAction: "_dB",
9879
- dangerAction: "_dC",
9880
- armed: "_dD",
9881
- okAction: "_dE",
9882
- prState: "_dF",
9883
- portLink: "_dG",
9884
- emptyNote: "_dH",
9885
- dangerZone: "_dI",
9886
- dangerRow: "_dJ",
9887
- dangerBtn: "_dK",
9888
- dangerHint: "_dL",
9889
- iconBtn: "_dM _cw",
9890
- spinning: "_dN _cx"
9936
+ content: "_cm _bd",
9937
+ pageMeta: "_cn _bh",
9938
+ wsLabel: "_co",
9939
+ metaSep: "_cp",
9940
+ pathMeta: "_cq",
9941
+ statusPill: "_cr",
9942
+ statusOff: "_cs",
9943
+ progress: "_ct",
9944
+ section: "_cu",
9945
+ sectionHead: "_cv",
9946
+ sectionCount: "_cw",
9947
+ pickerWrap: "_cx",
9948
+ cardList: "_cy",
9949
+ card: "_cz",
9950
+ pending: "_cA",
9951
+ cardMain: "_cB",
9952
+ cardTitle: "_cC",
9953
+ cardMeta: "_cD",
9954
+ cardSub: "_cE",
9955
+ cardTag: "_cF",
9956
+ cardAction: "_cG",
9957
+ dangerAction: "_cH",
9958
+ armed: "_cI",
9959
+ portLink: "_cJ",
9960
+ emptyNote: "_cK",
9961
+ dangerZone: "_cL",
9962
+ dangerRow: "_cM",
9963
+ dangerBtn: "_cN",
9964
+ dangerHint: "_cO",
9965
+ iconBtn: "_cP _eA",
9966
+ spinning: "_cQ _eB"
9891
9967
  };
9892
9968
  //#endregion
9893
9969
  //#region src/tags/manage-workspace.marko
@@ -9898,12 +9974,8 @@ var manage_workspace_default = _template("k", (input) => {
9898
9974
  const $scope0_id = _scope_id();
9899
9975
  const $error__closures = /* @__PURE__ */ new Set();
9900
9976
  const $confirmingRemove__closures = /* @__PURE__ */ new Set();
9901
- const $finishedCount__closures = /* @__PURE__ */ new Set();
9902
- const $prRepos_length__closures = /* @__PURE__ */ new Set();
9903
9977
  let catalogRefreshing = false;
9904
9978
  let procs = lastData.get(`procs:${input.workspace.id}`) || null;
9905
- let prs = lastData.get(`prs:${input.workspace.id}`) || null;
9906
- let prsRefreshing = false;
9907
9979
  let busy = /* @__PURE__ */ new Set();
9908
9980
  let error = null;
9909
9981
  let pendingAction = null;
@@ -9919,56 +9991,13 @@ var manage_workspace_default = _template("k", (input) => {
9919
9991
  lastData.set(`procs:${ws.id}`, data);
9920
9992
  } catch {}
9921
9993
  }, "k0", $scope0_id);
9922
- const loadPrs = _resume(async (signal, refresh) => {
9923
- try {
9924
- const data = await api$3(`/api/workspaces/${ws.id}/prs${refresh ? "?refresh" : ""}`, { signal });
9925
- prs = data;
9926
- lastData.set(`prs:${ws.id}`, data);
9927
- } catch {}
9928
- }, "k1", $scope0_id);
9929
- const refreshPrs = _resume(async () => {
9930
- prsRefreshing = true;
9931
- await loadPrs(void 0, true);
9932
- prsRefreshing = false;
9933
- }, "k2", $scope0_id);
9934
- const clearFinished = _resume(async () => {
9935
- for (const repo of prs || []) for (const pr of repo.prs) {
9936
- if (pr.state === "OPEN") continue;
9937
- await api$3(`/api/workspaces/${ws.id}/prs`, {
9938
- method: "POST",
9939
- headers: { "content-type": "application/json" },
9940
- body: JSON.stringify({
9941
- fullName: repo.full_name,
9942
- number: pr.number
9943
- })
9944
- }).catch(() => {});
9945
- }
9946
- await loadPrs(void 0, false);
9947
- }, "k3", $scope0_id);
9948
- const dismissPr = _resume(async (fullName, number) => {
9949
- error = null;
9950
- try {
9951
- const data = await api$3(`/api/workspaces/${ws.id}/prs`, {
9952
- method: "POST",
9953
- headers: { "content-type": "application/json" },
9954
- body: JSON.stringify({
9955
- fullName,
9956
- number
9957
- })
9958
- });
9959
- prs = data;
9960
- lastData.set(`prs:${ws.id}`, data);
9961
- } catch (err) {
9962
- error = String(err.message || err);
9963
- }
9964
- }, "k4", $scope0_id);
9965
9994
  const inWorkspace = new Set(ws.repos.map((r) => r.full_name));
9966
9995
  const setBusy = _resume((name, on) => {
9967
9996
  const next = new Set(busy);
9968
9997
  if (on) next.add(name);
9969
9998
  else next.delete(name);
9970
9999
  busy = next;
9971
- }, "k5", $scope0_id);
10000
+ }, "k1", $scope0_id);
9972
10001
  const addRepo = _resume(async (name, baseBranch) => {
9973
10002
  if (!name || busy.has(name)) return;
9974
10003
  error = null;
@@ -9986,7 +10015,7 @@ var manage_workspace_default = _template("k", (input) => {
9986
10015
  error = String(err.message || err);
9987
10016
  }
9988
10017
  setBusy(name, false);
9989
- }, "k6", $scope0_id);
10018
+ }, "k2", $scope0_id);
9990
10019
  const removeRepo = _resume(async (row) => {
9991
10020
  if (busy.has(row.full_name)) return;
9992
10021
  error = null;
@@ -10001,7 +10030,7 @@ var manage_workspace_default = _template("k", (input) => {
10001
10030
  error = String(err.message || err);
10002
10031
  }
10003
10032
  setBusy(row.full_name, false);
10004
- }, "k7", $scope0_id);
10033
+ }, "k3", $scope0_id);
10005
10034
  const runAction = _resume(async (action) => {
10006
10035
  error = null;
10007
10036
  pendingAction = action;
@@ -10023,48 +10052,47 @@ var manage_workspace_default = _template("k", (input) => {
10023
10052
  pendingAction = null;
10024
10053
  actionStep = null;
10025
10054
  }
10026
- }, "k8", $scope0_id);
10055
+ }, "k4", $scope0_id);
10027
10056
  const killProc = _resume(async (pid) => {
10028
10057
  await fetch(`/api/procs/${pid}`, { method: "DELETE" });
10029
10058
  setTimeout(() => loadProcs(void 0), 500);
10030
- }, "k9", $scope0_id);
10031
- const finishedCount = (prs || []).reduce((n, r) => n + r.prs.filter((pr) => pr.state !== "OPEN").length, 0);
10059
+ }, "k5", $scope0_id);
10032
10060
  const titleId = _id();
10033
10061
  _html(`<div${_attr_class(page_shell_module_default.page)} role=region${_attr("aria-labelledby", titleId)}><div${_attr_class(page_shell_module_default.body)}><div${_attr_class(manage_workspace_module_default.content)}><header${_attr_class(page_shell_module_default.pageHead)}><div${_attr_class(page_shell_module_default.pageHeadText)}><h1${_attr("id", titleId)}>Manage</h1><p${_attr_class(manage_workspace_module_default.pageMeta)}${_attr("title", ws.display_path || ws.path)}><span${_attr_class(manage_workspace_module_default.wsLabel)}>${_escape(ws.name)}${_el_resume($scope0_id, "i")}</span>`);
10034
10062
  _if(() => {
10035
10063
  if (ws.status !== "active") {
10036
- const $scope15_id = _scope_id();
10064
+ const $scope10_id = _scope_id();
10037
10065
  _html(`<span${_attr_class([manage_workspace_module_default.statusPill, manage_workspace_module_default.statusOff])}>Archived</span>`);
10038
- writeScope($scope15_id, {});
10066
+ writeScope($scope10_id, {});
10039
10067
  return 0;
10040
10068
  }
10041
10069
  }, $scope0_id, "j", 1, 1, 1, 0, 1);
10042
10070
  _html(`<span${_attr_class(manage_workspace_module_default.metaSep)} aria-hidden=true>·</span><span${_attr_class([manage_workspace_module_default.pathMeta, ui_module_default.mono])}>${_escape(ws.display_path || ws.path)}${_el_resume($scope0_id, "m")}</span></p>${_el_resume($scope0_id, "g")}</div></header>`);
10043
10071
  _if(() => {
10044
10072
  if (error) {
10045
- const $scope3_id = _scope_id();
10073
+ const $scope2_id = _scope_id();
10046
10074
  toast_default({
10047
10075
  placement: "inline",
10048
10076
  onDismiss: _resume(function() {
10049
10077
  error = null;
10050
- }, "k10", $scope3_id),
10051
- content: _content_resume("k14", () => {
10078
+ }, "k6", $scope2_id),
10079
+ content: _content_resume("k10", () => {
10052
10080
  _scope_reason();
10053
- const $scope4_id = _scope_id();
10054
- _html(`${_escape(error)}${_el_resume($scope4_id, "a")}`);
10055
- _subscribe($error__closures, writeScope($scope4_id, { _: _scope_with_id($scope3_id) }));
10056
- _resume_branch($scope4_id);
10057
- }, $scope3_id)
10081
+ const $scope3_id = _scope_id();
10082
+ _html(`${_escape(error)}${_el_resume($scope3_id, "a")}`);
10083
+ _subscribe($error__closures, writeScope($scope3_id, { _: _scope_with_id($scope2_id) }));
10084
+ _resume_branch($scope3_id);
10085
+ }, $scope2_id)
10058
10086
  });
10059
- writeScope($scope3_id, {});
10087
+ writeScope($scope2_id, {});
10060
10088
  return 0;
10061
10089
  }
10062
10090
  }, $scope0_id, "n", 1, 1, 1, 0, 1);
10063
10091
  _if(() => {
10064
10092
  if (pendingAction && actionStep) {
10065
- const $scope8_id = _scope_id();
10066
- _html(`<p${_attr_class(manage_workspace_module_default.progress)}><span${_attr_class(ui_module_default.spin)}></span><!>${_escape(actionStep)}${_el_resume($scope8_id, "c")}</p>`);
10067
- writeScope($scope8_id, {});
10093
+ const $scope7_id = _scope_id();
10094
+ _html(`<p${_attr_class(manage_workspace_module_default.progress)}><span${_attr_class(ui_module_default.spin)}></span><!>${_escape(actionStep)}${_el_resume($scope7_id, "c")}</p>`);
10095
+ writeScope($scope7_id, {});
10068
10096
  return 0;
10069
10097
  }
10070
10098
  }, $scope0_id, "o", 1, 1, 1, 0, 1);
@@ -10072,37 +10100,37 @@ var manage_workspace_default = _template("k", (input) => {
10072
10100
  icon_refresh_default({ size: 14 });
10073
10101
  _html(`</button>${_el_resume($scope0_id, "u")}</div><ul${_attr_class(manage_workspace_module_default.cardList)}>`);
10074
10102
  _for_of(ws.repos, (row) => {
10075
- const $scope2_id = _scope_id();
10076
- _html(`<li${_attr_class(manage_workspace_module_default.card)}><div${_attr_class(manage_workspace_module_default.cardMain)}><span${_attr_class([manage_workspace_module_default.cardTitle, ui_module_default.mono])}>${_escape(row.worktree)}${_el_resume($scope2_id, "d")}/</span><span${_attr_class(manage_workspace_module_default.cardMeta)}><span${_attr_class(manage_workspace_module_default.cardSub)}>${_escape(row.full_name)}${_el_resume($scope2_id, "g")}</span>`);
10103
+ const $scope1_id = _scope_id();
10104
+ _html(`<li${_attr_class(manage_workspace_module_default.card)}><div${_attr_class(manage_workspace_module_default.cardMain)}><span${_attr_class([manage_workspace_module_default.cardTitle, ui_module_default.mono])}>${_escape(row.worktree)}${_el_resume($scope1_id, "d")}/</span><span${_attr_class(manage_workspace_module_default.cardMeta)}><span${_attr_class(manage_workspace_module_default.cardSub)}>${_escape(row.full_name)}${_el_resume($scope1_id, "g")}</span>`);
10077
10105
  _if(() => {
10078
10106
  if (row.base_branch !== row.default_branch) {
10079
- const $scope16_id = _scope_id();
10080
- _html(`<span${_attr_class([manage_workspace_module_default.cardTag, ui_module_default.mono])} title="Base branch">⎇ <!>${_escape(row.base_branch)}${_el_resume($scope16_id, "b")}</span>`);
10081
- writeScope($scope16_id, {});
10107
+ const $scope11_id = _scope_id();
10108
+ _html(`<span${_attr_class([manage_workspace_module_default.cardTag, ui_module_default.mono])} title="Base branch">⎇ <!>${_escape(row.base_branch)}${_el_resume($scope11_id, "b")}</span>`);
10109
+ writeScope($scope11_id, {});
10082
10110
  return 0;
10083
10111
  }
10084
- }, $scope2_id, "h", 1, 1, 1, 0, 1);
10112
+ }, $scope1_id, "h", 1, 1, 1, 0, 1);
10085
10113
  _html("</span></div>");
10086
10114
  _if(() => {
10087
10115
  if (busy.has(row.full_name)) {
10088
- const $scope17_id = _scope_id();
10116
+ const $scope12_id = _scope_id();
10089
10117
  _html(`<span${_attr_class(ui_module_default.spin)}></span>`);
10090
- writeScope($scope17_id, {});
10118
+ writeScope($scope12_id, {});
10091
10119
  return 0;
10092
10120
  } else {
10093
- const $scope7_id = _scope_id();
10121
+ const $scope6_id = _scope_id();
10094
10122
  _html(`<button${_attr_class([
10095
10123
  manage_workspace_module_default.cardAction,
10096
10124
  manage_workspace_module_default.dangerAction,
10097
10125
  { [manage_workspace_module_default.armed]: confirmingRemove === row.full_name }
10098
- ])}${confirmingRemove === row.full_name ? _attr("title", `Really remove ${row.worktree}/? Uncommitted changes are lost.`) : _attr("title", `Remove ${row.worktree}/`)}>${confirmingRemove === row.full_name ? "Remove?" : "×"}${_el_resume($scope7_id, "b")}</button>${_el_resume($scope7_id, "a")}`);
10099
- _script($scope7_id, "k15");
10100
- _subscribe($confirmingRemove__closures, writeScope($scope7_id, {}));
10126
+ ])}${confirmingRemove === row.full_name ? _attr("title", `Really remove ${row.worktree}/? Uncommitted changes are lost.`) : _attr("title", `Remove ${row.worktree}/`)}>${confirmingRemove === row.full_name ? "Remove?" : "×"}${_el_resume($scope6_id, "b")}</button>${_el_resume($scope6_id, "a")}`);
10127
+ _script($scope6_id, "k11");
10128
+ _subscribe($confirmingRemove__closures, writeScope($scope6_id, {}));
10101
10129
  return 1;
10102
10130
  }
10103
- }, $scope2_id, "i", 1, 1, 1, 0, 1);
10131
+ }, $scope1_id, "i", 1, 1, 1, 0, 1);
10104
10132
  _html("</li>");
10105
- writeScope($scope2_id, {
10133
+ writeScope($scope1_id, {
10106
10134
  k: row,
10107
10135
  l: row?.worktree,
10108
10136
  m: row?.full_name,
@@ -10110,16 +10138,16 @@ var manage_workspace_default = _template("k", (input) => {
10110
10138
  });
10111
10139
  }, "full_name", $scope0_id, "x", 1, 1, 1, 0, 1);
10112
10140
  _for_of([...busy].filter((n) => !inWorkspace.has(n)), (name) => {
10113
- const $scope18_id = _scope_id();
10114
- _html(`<li${_attr_class([manage_workspace_module_default.card, manage_workspace_module_default.pending])}><span${_attr_class(ui_module_default.spin)}></span><div${_attr_class(manage_workspace_module_default.cardMain)}><span${_attr_class(manage_workspace_module_default.cardSub)}>Adding <!>${_escape(name)}${_el_resume($scope18_id, "e")}…</span></div></li>`);
10115
- writeScope($scope18_id, {});
10141
+ const $scope13_id = _scope_id();
10142
+ _html(`<li${_attr_class([manage_workspace_module_default.card, manage_workspace_module_default.pending])}><span${_attr_class(ui_module_default.spin)}></span><div${_attr_class(manage_workspace_module_default.cardMain)}><span${_attr_class(manage_workspace_module_default.cardSub)}>Adding <!>${_escape(name)}${_el_resume($scope13_id, "e")}…</span></div></li>`);
10143
+ writeScope($scope13_id, {});
10116
10144
  }, (n) => n, $scope0_id, "y", 1, 1, 1, 0, 1);
10117
10145
  _html("</ul>");
10118
10146
  _if(() => {
10119
10147
  if (!ws.repos.length && !busy.size) {
10120
- const $scope19_id = _scope_id();
10148
+ const $scope14_id = _scope_id();
10121
10149
  _html(`<p${_attr_class(manage_workspace_module_default.emptyNote)}>No repos yet — search below to add one.</p>`);
10122
- writeScope($scope19_id, {});
10150
+ writeScope($scope14_id, {});
10123
10151
  return 0;
10124
10152
  }
10125
10153
  }, $scope0_id, "z", 1, 1, 1, 0, 1);
@@ -10129,213 +10157,133 @@ var manage_workspace_default = _template("k", (input) => {
10129
10157
  exclude: inWorkspace,
10130
10158
  onPick: _resume(function(name, baseBranch) {
10131
10159
  addRepo(name, baseBranch);
10132
- }, "k11", $scope0_id),
10160
+ }, "k7", $scope0_id),
10133
10161
  onError: _resume(function(message) {
10134
10162
  error = message;
10135
- }, "k12", $scope0_id),
10163
+ }, "k8", $scope0_id),
10136
10164
  refreshingChange: _resume(function(busy) {
10137
10165
  catalogRefreshing = busy;
10138
- }, "k13", $scope0_id)
10166
+ }, "k9", $scope0_id)
10139
10167
  });
10140
- _var($scope0_id, "a2", $childScope, "k16");
10141
- const prRepos = (prs || []).filter((r) => r.prs.length);
10142
- _html("</div></section>");
10143
- _if(() => {
10144
- if (prRepos.length) {
10145
- const $scope1_id = _scope_id();
10146
- _html(`<section${_attr_class(manage_workspace_module_default.section)}><div${_attr_class(manage_workspace_module_default.sectionHead)}><h2>Pull requests</h2><div${_attr_class(ui_module_default.spacer)}></div>`);
10147
- _if(() => {
10148
- if (finishedCount) {
10149
- const $scope9_id = _scope_id();
10150
- _html(`<button${_attr_class([ui_module_default.btn, manage_workspace_module_default.sectionBtn])} title="Confirm every merged/closed PR is done — remove them from this list">Clear <!>${_escape(finishedCount)}${_el_resume($scope9_id, "b")}</button>${_el_resume($scope9_id, "a")}`);
10151
- _script($scope9_id, "k17");
10152
- _subscribe($finishedCount__closures, writeScope($scope9_id, {}));
10153
- return 0;
10154
- }
10155
- }, $scope1_id, "d", 1, 1, 1, 0, 1);
10156
- _html(`<button${_attr_class([manage_workspace_module_default.iconBtn, { [manage_workspace_module_default.spinning]: prsRefreshing }])} title="Refresh PRs" aria-label="Refresh PRs"${_attr("disabled", prsRefreshing)}>`);
10157
- icon_refresh_default({ size: 14 });
10158
- _html(`</button>${_el_resume($scope1_id, "e")}</div>`);
10159
- _for_of(prRepos, (repo) => {
10160
- const $scope10_id = _scope_id();
10161
- _if(() => {
10162
- if (prRepos.length > 1) {
10163
- const $scope20_id = _scope_id();
10164
- _html(`<p${_attr_class([manage_workspace_module_default.groupLabel, ui_module_default.mono])}>${_escape(repo.worktree)}${_el_resume($scope20_id, "b")}</p>`);
10165
- writeScope($scope20_id, {});
10166
- return 0;
10167
- }
10168
- }, $scope10_id, "a", 1, 1, 1, 0, 1);
10169
- _html(`<ul${_attr_class(manage_workspace_module_default.cardList)}>`);
10170
- _for_of(repo.prs, (pr) => {
10171
- const $scope11_id = _scope_id();
10172
- const prState = pr.state === "OPEN" && pr.isDraft ? "open" : (pr.state || "open").toLowerCase();
10173
- const prLabel = pr.state === "OPEN" && pr.isDraft ? "draft" : (pr.state || "open").toLowerCase();
10174
- _html(`<li${_attr_class(manage_workspace_module_default.card)}><a${_attr_class(manage_workspace_module_default.cardMain)}${_attr("href", pr.url)} target=_blank rel=noopener><span${_attr_class(manage_workspace_module_default.cardTitle)}>${_escape(pr.title)}${_el_resume($scope11_id, "d")}</span><span${_attr_class(manage_workspace_module_default.cardMeta)}><span${_attr_class(manage_workspace_module_default.prState)}${_attr("data-state", prState)}>${_escape(prLabel)}${_el_resume($scope11_id, "g")}</span>${_el_resume($scope11_id, "f")}`);
10175
- _if(() => {
10176
- if (pr.state === "OPEN" && pr.reviewDecision === "APPROVED") {
10177
- const $scope21_id = _scope_id();
10178
- _html(`<span${_attr_class(manage_workspace_module_default.prState)} data-state=open title=Approved>✓</span>`);
10179
- writeScope($scope21_id, {});
10180
- return 0;
10181
- } else if (pr.state === "OPEN" && pr.reviewDecision === "CHANGES_REQUESTED") {
10182
- const $scope22_id = _scope_id();
10183
- _html(`<span${_attr_class(manage_workspace_module_default.prState)} data-state=closed title="Changes requested">✗</span>`);
10184
- writeScope($scope22_id, {});
10185
- return 1;
10186
- }
10187
- }, $scope11_id, "h", 1, 1, 1, 0, 1);
10188
- _html(`<span${_attr_class([manage_workspace_module_default.cardTag, ui_module_default.mono])}>#<!>${_escape(pr.number)}${_el_resume($scope11_id, "j")}</span></span></a>${_el_resume($scope11_id, "b")}`);
10189
- _if(() => {
10190
- if (pr.state !== "OPEN") {
10191
- const $scope12_id = _scope_id();
10192
- _html(`<button${_attr_class([manage_workspace_module_default.cardAction, manage_workspace_module_default.okAction])}${_attr("title", `Confirm #${pr.number} is done — remove from this list`)}>✓</button>${_el_resume($scope12_id, "a")}`);
10193
- _script($scope12_id, "k18");
10194
- writeScope($scope12_id, {});
10195
- return 0;
10196
- }
10197
- }, $scope11_id, "k", 1, 1, 1, 0, 1);
10198
- _html("</li>");
10199
- writeScope($scope11_id, { u: pr?.number });
10200
- }, "number", $scope10_id, "b", 1, 1, 1, "</ul>", 1);
10201
- _subscribe($prRepos_length__closures, writeScope($scope10_id, {
10202
- e: repo?.worktree,
10203
- g: repo?.full_name
10204
- }));
10205
- }, "full_name", $scope1_id, "g");
10206
- _html("</section>");
10207
- _script($scope1_id, "k19");
10208
- writeScope($scope1_id, {});
10209
- return 0;
10210
- }
10211
- }, $scope0_id, "a3", 1, 1, 1, 0, 1);
10168
+ _var($scope0_id, "a2", $childScope, "k12");
10212
10169
  const running = procs || [];
10170
+ _html("</div></section>");
10213
10171
  _if(() => {
10214
10172
  if (running.length) {
10215
- const $scope13_id = _scope_id();
10216
- _html(`<section${_attr_class(manage_workspace_module_default.section)}><div${_attr_class(manage_workspace_module_default.sectionHead)}><h2>Running</h2><span${_attr_class(manage_workspace_module_default.sectionCount)}>${_escape(running.length)}${_el_resume($scope13_id, "d")}</span></div><ul${_attr_class(manage_workspace_module_default.cardList)}>`);
10173
+ const $scope8_id = _scope_id();
10174
+ _html(`<section${_attr_class(manage_workspace_module_default.section)}><div${_attr_class(manage_workspace_module_default.sectionHead)}><h2>Running</h2><span${_attr_class(manage_workspace_module_default.sectionCount)}>${_escape(running.length)}${_el_resume($scope8_id, "d")}</span></div><ul${_attr_class(manage_workspace_module_default.cardList)}>`);
10217
10175
  _for_of(running, (p) => {
10218
- const $scope14_id = _scope_id();
10219
- _html(`<li${_attr_class(manage_workspace_module_default.card)}><div${_attr_class(manage_workspace_module_default.cardMain)}${_attr("title", p.args)}><span${_attr_class([manage_workspace_module_default.cardTitle, ui_module_default.mono])}>${_escape(p.cmd)}${_el_resume($scope14_id, "d")}</span>`);
10176
+ const $scope9_id = _scope_id();
10177
+ _html(`<li${_attr_class(manage_workspace_module_default.card)}><div${_attr_class(manage_workspace_module_default.cardMain)}${_attr("title", p.args)}><span${_attr_class([manage_workspace_module_default.cardTitle, ui_module_default.mono])}>${_escape(p.cmd)}${_el_resume($scope9_id, "d")}</span>`);
10220
10178
  _if(() => {
10221
10179
  if (p.ports.length) {
10222
- const $scope23_id = _scope_id();
10180
+ const $scope15_id = _scope_id();
10223
10181
  _html(`<span${_attr_class(manage_workspace_module_default.cardMeta)}>`);
10224
10182
  _for_of(p.ports, (port) => {
10225
- const $scope24_id = _scope_id();
10226
- _html(`<button${_attr_class([ui_module_default.chip, manage_workspace_module_default.portLink])}${_attr("title", `Open http://${typeof location === "undefined" ? "localhost" : location.hostname}:${port}`)}>:<!>${_escape(port)}${_el_resume($scope24_id, "b")}</button>${_el_resume($scope24_id, "a")}`);
10227
- _script($scope24_id, "k20");
10228
- writeScope($scope24_id, { d: port });
10229
- }, (x) => String(x), $scope23_id, "a", 1, 1, 1, "</span>", 1);
10230
- writeScope($scope23_id, {});
10183
+ const $scope16_id = _scope_id();
10184
+ _html(`<button${_attr_class([ui_module_default.chip, manage_workspace_module_default.portLink])}${_attr("title", `Open http://${typeof location === "undefined" ? "localhost" : location.hostname}:${port}`)}>:<!>${_escape(port)}${_el_resume($scope16_id, "b")}</button>${_el_resume($scope16_id, "a")}`);
10185
+ _script($scope16_id, "k13");
10186
+ writeScope($scope16_id, { d: port });
10187
+ }, (x) => String(x), $scope15_id, "a", 1, 1, 1, "</span>", 1);
10188
+ writeScope($scope15_id, {});
10231
10189
  return 0;
10232
10190
  }
10233
- }, $scope14_id, "e", 1, 1, 1, 0, 1);
10234
- _html(`</div>${_el_resume($scope14_id, "b")}<button${_attr_class([manage_workspace_module_default.cardAction, manage_workspace_module_default.dangerAction])} type=button${_attr("title", `Kill ${p.pid}`)}${_attr("aria-label", `Kill process ${p.pid}`)}>×</button>${_el_resume($scope14_id, "f")}</li>`);
10235
- _script($scope14_id, "k21");
10236
- writeScope($scope14_id, {
10191
+ }, $scope9_id, "e", 1, 1, 1, 0, 1);
10192
+ _html(`</div>${_el_resume($scope9_id, "b")}<button${_attr_class([manage_workspace_module_default.cardAction, manage_workspace_module_default.dangerAction])} type=button${_attr("title", `Kill ${p.pid}`)}${_attr("aria-label", `Kill process ${p.pid}`)}>×</button>${_el_resume($scope9_id, "f")}</li>`);
10193
+ _script($scope9_id, "k14");
10194
+ writeScope($scope9_id, {
10237
10195
  k: p?.ports,
10238
10196
  m: p?.pid
10239
10197
  });
10240
- }, "pid", $scope13_id, "e", 1, 1, 1, "</ul>", 1);
10198
+ }, "pid", $scope8_id, "e", 1, 1, 1, "</ul>", 1);
10241
10199
  _html("</section>");
10242
- writeScope($scope13_id, {});
10200
+ writeScope($scope8_id, {});
10243
10201
  return 0;
10244
10202
  }
10245
- }, $scope0_id, "a4", 1, 1, 1, 0, 1);
10203
+ }, $scope0_id, "a3", 1, 1, 1, 0, 1);
10246
10204
  _html(`<section${_attr_class([manage_workspace_module_default.section, manage_workspace_module_default.dangerZone])}><div${_attr_class(manage_workspace_module_default.sectionHead)}><h2>Workspace</h2></div><div${_attr_class(manage_workspace_module_default.dangerRow)}>`);
10247
10205
  _if(() => {
10248
10206
  if (ws.status === "active") {
10249
- const $scope5_id = _scope_id();
10250
- _html(`<button type=button${_attr_class([ui_module_default.btn, manage_workspace_module_default.dangerBtn])}${_attr("disabled", !!pendingAction)}>${pendingAction === "archive" ? "Archiving…" : "Archive"}${_el_resume($scope5_id, "b")}</button>${_el_resume($scope5_id, "a")}`);
10251
- _script($scope5_id, "k22");
10252
- writeScope($scope5_id, {});
10207
+ const $scope4_id = _scope_id();
10208
+ _html(`<button type=button${_attr_class([ui_module_default.btn, manage_workspace_module_default.dangerBtn])}${_attr("disabled", !!pendingAction)}>${pendingAction === "archive" ? "Archiving…" : "Archive"}${_el_resume($scope4_id, "b")}</button>${_el_resume($scope4_id, "a")}`);
10209
+ _script($scope4_id, "k15");
10210
+ writeScope($scope4_id, {});
10253
10211
  return 0;
10254
10212
  } else {
10255
- const $scope6_id = _scope_id();
10256
- _html(`<button type=button${_attr_class([ui_module_default.btn, manage_workspace_module_default.dangerBtn])}${_attr("disabled", !!pendingAction)}>Restore</button>${_el_resume($scope6_id, "a")}`);
10257
- _script($scope6_id, "k23");
10258
- writeScope($scope6_id, {});
10213
+ const $scope5_id = _scope_id();
10214
+ _html(`<button type=button${_attr_class([ui_module_default.btn, manage_workspace_module_default.dangerBtn])}${_attr("disabled", !!pendingAction)}>Restore</button>${_el_resume($scope5_id, "a")}`);
10215
+ _script($scope5_id, "k16");
10216
+ writeScope($scope5_id, {});
10259
10217
  return 1;
10260
10218
  }
10261
- }, $scope0_id, "a8", 1, 1, 1, 0, 1);
10219
+ }, $scope0_id, "a7", 1, 1, 1, 0, 1);
10262
10220
  _html(`<button type=button${_attr_class([
10263
10221
  ui_module_default.btn,
10264
10222
  ui_module_default.danger,
10265
10223
  manage_workspace_module_default.dangerBtn,
10266
10224
  { [ui_module_default.armed]: confirmingDelete }
10267
- ])}${_attr("disabled", !!pendingAction)}>${pendingAction === "delete" ? "Deleting…" : "Delete"}${_el_resume($scope0_id, "aa")}</button>${_el_resume($scope0_id, "a9")}</div><p${_attr_class(manage_workspace_module_default.dangerHint)}>Archive hides the space from the list. Delete removes it and its worktrees.</p></section></div></div></div>`);
10268
- _script($scope0_id, "k24");
10269
- _script($scope0_id, "k25");
10225
+ ])}${_attr("disabled", !!pendingAction)}>${pendingAction === "delete" ? "Deleting…" : "Delete"}${_el_resume($scope0_id, "a9")}</button>${_el_resume($scope0_id, "a8")}</div><p${_attr_class(manage_workspace_module_default.dangerHint)}>Archive hides the space from the list. Delete removes it and its worktrees.</p></section></div></div></div>`);
10226
+ _script($scope0_id, "k17");
10227
+ _script($scope0_id, "k18");
10270
10228
  writeScope($scope0_id, {
10271
- ae: _serialize_if($scope0_reason, 0) && input.workspace,
10272
- ag: input.workspaceChange,
10273
- ai: input.onExit,
10274
- al: prs,
10275
- am: prsRefreshing,
10276
- an: busy,
10277
- ao: busy?.size,
10278
- ap: error,
10279
- aq: pendingAction,
10280
- ar: confirmingDelete,
10281
- at: confirmingRemove,
10282
- au: actionStep,
10283
- aw: workspace,
10284
- ay: workspace?.id,
10285
- b4: workspace?.repos?.length,
10286
- b5: loadProcs,
10287
- b6: loadPrs,
10288
- b7: refreshPrs,
10289
- b8: clearFinished,
10290
- b9: dismissPr,
10291
- ba: inWorkspace,
10292
- bb: setBusy,
10293
- bc: addRepo,
10294
- bd: removeRepo,
10295
- be: runAction,
10296
- bf: killProc,
10297
- bg: finishedCount,
10298
- bi: refreshCatalog,
10299
- bj: prRepos,
10300
- bk: prRepos?.length,
10301
- bl: running,
10302
- bm: running.length,
10303
- ax: input.workspaceChange || void 0,
10304
- bw: $error__closures,
10305
- by: $confirmingRemove__closures,
10306
- a1: _existing_scope($childScope),
10307
- c0: $finishedCount__closures,
10308
- c2: $prRepos_length__closures
10229
+ ad: _serialize_if($scope0_reason, 0) && input.workspace,
10230
+ af: input.workspaceChange,
10231
+ ah: input.onExit,
10232
+ ak: busy,
10233
+ al: busy?.size,
10234
+ am: error,
10235
+ an: pendingAction,
10236
+ ao: confirmingDelete,
10237
+ aq: confirmingRemove,
10238
+ ar: actionStep,
10239
+ at: workspace,
10240
+ av: workspace?.id,
10241
+ b1: workspace?.repos?.length,
10242
+ b2: loadProcs,
10243
+ b3: inWorkspace,
10244
+ b4: setBusy,
10245
+ b5: addRepo,
10246
+ b6: removeRepo,
10247
+ b7: runAction,
10248
+ b8: killProc,
10249
+ ba: refreshCatalog,
10250
+ bb: running,
10251
+ bc: running.length,
10252
+ au: input.workspaceChange || void 0,
10253
+ bk: $error__closures,
10254
+ bm: $confirmingRemove__closures,
10255
+ a1: _existing_scope($childScope)
10309
10256
  });
10310
10257
  _resume_branch($scope0_id);
10311
10258
  });
10312
10259
  var usage_stats_module_default = {
10313
- content: "_cQ _cQ _B",
10314
- iconBtn: "_cR _cw",
10315
- spinning: "_cS _cx",
10316
- refreshBtn: "_cT",
10317
- note: "_cU",
10318
- usageList: "_cV",
10319
- usageRow: "_cW",
10320
- usageName: "_cX",
10321
- plan: "_cY",
10322
- usageStale: "_cZ",
10323
- stale: "_c0",
10324
- usageMeters: "_c1",
10325
- meter: "_c2",
10326
- meterLabel: "_c3",
10327
- meterTrack: "_c4",
10328
- meterFill: "_c5",
10329
- fillOk: "_c6",
10330
- fillMid: "_c7",
10331
- fillWarm: "_c8",
10332
- fillHot: "_c9",
10333
- meterPct: "_c_",
10334
- pctOk: "_da",
10335
- pctMid: "_db",
10336
- pctWarm: "_dc",
10337
- pctHot: "_dd",
10338
- meterReset: "_de"
10260
+ content: "_bW _bW _be",
10261
+ iconBtn: "_bX _eA",
10262
+ spinning: "_bY _eB",
10263
+ refreshBtn: "_bZ",
10264
+ note: "_b0",
10265
+ usageList: "_b1",
10266
+ usageRow: "_b2",
10267
+ usageName: "_b3",
10268
+ plan: "_b4",
10269
+ usageStale: "_b5",
10270
+ stale: "_b6",
10271
+ usageMeters: "_b7",
10272
+ usageNote: "_b8",
10273
+ meter: "_b9",
10274
+ meterLabel: "_b_",
10275
+ meterTrack: "_ca",
10276
+ meterFill: "_cb",
10277
+ fillOk: "_cc",
10278
+ fillMid: "_cd",
10279
+ fillWarm: "_ce",
10280
+ fillHot: "_cf",
10281
+ meterPct: "_cg",
10282
+ pctOk: "_ch",
10283
+ pctMid: "_ci",
10284
+ pctWarm: "_cj",
10285
+ pctHot: "_ck",
10286
+ meterReset: "_cl"
10339
10287
  };
10340
10288
  //#endregion
10341
10289
  //#region src/tags/usage-stats.marko
@@ -10406,7 +10354,7 @@ var usage_stats_default = _template("x", (input) => {
10406
10354
  _if(() => {
10407
10355
  if (agent.stale_seconds != null) {
10408
10356
  const $scope6_id = _scope_id();
10409
- _html(`<span${_attr_class(usage_stats_module_default.usageStale)}${_attr("title", `plan-usage could not reach this provider — these are its last cached numbers, ${duration(agent.stale_seconds * 1e3)} old`)}>⚠ <!>${_escape(duration(agent.stale_seconds * 1e3))}${_el_resume($scope6_id, "b")} old</span>${_el_resume($scope6_id, "a")}`);
10357
+ _html(`<span${_attr_class(usage_stats_module_default.usageStale)}${_attr("title", `${agent.note || "couldn't reach this provider"} — these are the last cached numbers, ${duration(agent.stale_seconds * 1e3)} old`)}>⚠ <!>${_escape(duration(agent.stale_seconds * 1e3))}${_el_resume($scope6_id, "b")} old</span>${_el_resume($scope6_id, "a")}`);
10410
10358
  writeScope($scope6_id, {});
10411
10359
  return 0;
10412
10360
  }
@@ -10420,11 +10368,20 @@ var usage_stats_default = _template("x", (input) => {
10420
10368
  const pctClass = win.used_percent >= 90 ? usage_stats_module_default.pctHot : win.used_percent >= 70 ? usage_stats_module_default.pctWarm : win.used_percent >= 40 ? usage_stats_module_default.pctMid : usage_stats_module_default.pctOk;
10421
10369
  _html(`<div${_attr_class(usage_stats_module_default.meter)}${_attr("title", `${win.window}: ${pct}% used${win.resets_at ? ` — resets ${new Date(win.resets_at).toLocaleString()}` : ""}`)}><span${_attr_class(usage_stats_module_default.meterLabel)}>${_escape(win.window)}${_el_resume($scope7_id, "c")}</span><span${_attr_class(usage_stats_module_default.meterTrack)}><span${_attr_class([usage_stats_module_default.meterFill, fillClass])}${_attr_style(`width:${Math.min(100, Math.max(2, win.used_percent))}%`)}></span>${_el_resume($scope7_id, "e")}</span><span${_attr_class([usage_stats_module_default.meterPct, pctClass])}>${_escape(pct)}${_el_resume($scope7_id, "g")}%</span>${_el_resume($scope7_id, "f")}<span${_attr_class(usage_stats_module_default.meterReset)}>${label ? `↻ ${_escape(`${_to_text(label)}`)}` : ""}${_el_resume($scope7_id, "i")}</span></div>${_el_resume($scope7_id, "a")}`);
10422
10370
  writeScope($scope7_id, {});
10423
- }, "window", $scope4_id, "f", 1, 1, 1, "</div>", 1);
10424
- _html(`</div>${_el_resume($scope4_id, "a")}`);
10371
+ }, "window", $scope4_id, "g", 1, 1, 1, 0, 1);
10372
+ _if(() => {
10373
+ if (agent.note) {
10374
+ const $scope8_id = _scope_id();
10375
+ _html(`<p${_attr_class(usage_stats_module_default.usageNote)}>${_escape(agent.note)}${_el_resume($scope8_id, "b")}</p>`);
10376
+ writeScope($scope8_id, {});
10377
+ return 0;
10378
+ }
10379
+ }, $scope4_id, "h", 1, 1, 1, 0, 1);
10380
+ _html(`</div></div>${_el_resume($scope4_id, "a")}`);
10425
10381
  writeScope($scope4_id, {
10426
- i: agent?.stale_seconds,
10427
- k: agent?.plan
10382
+ k: agent?.stale_seconds,
10383
+ m: agent?.plan,
10384
+ n: agent?.note
10428
10385
  });
10429
10386
  }, (a) => `${a.agent}-${a.account || ""}`, $scope2_id, "a", 1, 1, 1, "</div>", 1);
10430
10387
  writeScope($scope2_id, {});
@@ -10443,43 +10400,43 @@ var usage_stats_default = _template("x", (input) => {
10443
10400
  _resume_branch($scope0_id);
10444
10401
  });
10445
10402
  var term_module_default = {
10446
- iconBtn: "_bW _cw",
10447
- termWrap: "_bX",
10448
- term: "_bY",
10449
- xterm: "_bZ",
10450
- termDead: "_b0",
10451
- termCopied: "_b1",
10452
- termCopiedFade: "_b2",
10453
- termUploading: "_b3",
10454
- trapBackdrop: "_b4",
10455
- pasteTrap: "_b5",
10456
- kbSlot: "_b6",
10457
- keyBar: "_b7",
10458
- keyBarBtns: "_b8",
10459
- keyBarBtnsHidden: "_b9",
10460
- kspacer: "_b_",
10461
- sessBtn: "_ca",
10462
- sessDot: "_cb",
10463
- sessPop: "_cc",
10464
- sessRow: "_cd",
10465
- current: "_ce",
10466
- sessOpen: "_cf",
10467
- sessTitle: "_cg",
10468
- sessRename: "_ch",
10469
- sessX: "_ci",
10470
- armed: "_cj",
10471
- sessEdit: "_ck",
10472
- sessNew: "_cl",
10473
- lone: "_cm",
10474
- kbarWs: "_cn",
10475
- kbarWsName: "_co",
10476
- kbtn: "_cp _cw",
10477
- dpadGrid: "_cq",
10478
- repeat: "_cr",
10479
- on: "_cs",
10480
- bigGlyph: "_ct",
10481
- enter: "_cu",
10482
- dpadEsc: "_cv"
10403
+ iconBtn: "_d0 _eA",
10404
+ termWrap: "_d1",
10405
+ term: "_d2",
10406
+ xterm: "_d3",
10407
+ termDead: "_d4",
10408
+ termCopied: "_d5",
10409
+ termCopiedFade: "_d6",
10410
+ termUploading: "_d7",
10411
+ trapBackdrop: "_d8",
10412
+ pasteTrap: "_d9",
10413
+ kbSlot: "_d_",
10414
+ keyBar: "_ea",
10415
+ keyBarBtns: "_eb",
10416
+ keyBarBtnsHidden: "_ec",
10417
+ kspacer: "_ed",
10418
+ sessBtn: "_ee",
10419
+ sessDot: "_ef",
10420
+ sessPop: "_eg",
10421
+ sessRow: "_eh",
10422
+ current: "_ei",
10423
+ sessOpen: "_ej",
10424
+ sessTitle: "_ek",
10425
+ sessRename: "_el",
10426
+ sessX: "_em",
10427
+ armed: "_en",
10428
+ sessEdit: "_eo",
10429
+ sessNew: "_ep",
10430
+ lone: "_eq",
10431
+ kbarWs: "_er",
10432
+ kbarWsName: "_es",
10433
+ kbtn: "_et _eA",
10434
+ dpadGrid: "_eu",
10435
+ repeat: "_ev",
10436
+ on: "_ew",
10437
+ bigGlyph: "_ex",
10438
+ enter: "_ey",
10439
+ dpadEsc: "_ez"
10483
10440
  };
10484
10441
  //#endregion
10485
10442
  //#region src/tags/term-find.marko
@@ -10550,7 +10507,7 @@ var term_find_default = _template("u", (input) => {
10550
10507
  });
10551
10508
  _resume_branch($scope0_id);
10552
10509
  });
10553
- _template("R", (input) => {
10510
+ _template("T", (input) => {
10554
10511
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
10555
10512
  const $scope0_id = _scope_id();
10556
10513
  _set_serialize_reason({
@@ -10565,7 +10522,7 @@ _template("R", (input) => {
10565
10522
  });
10566
10523
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
10567
10524
  });
10568
- _template("F", (input) => {
10525
+ _template("G", (input) => {
10569
10526
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
10570
10527
  const $scope0_id = _scope_id();
10571
10528
  _set_serialize_reason({
@@ -10580,7 +10537,7 @@ _template("F", (input) => {
10580
10537
  });
10581
10538
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
10582
10539
  });
10583
- _template("K", (input) => {
10540
+ _template("L", (input) => {
10584
10541
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
10585
10542
  const $scope0_id = _scope_id();
10586
10543
  _set_serialize_reason({
@@ -10595,7 +10552,7 @@ _template("K", (input) => {
10595
10552
  });
10596
10553
  _serialize_if($scope0_reason, 0) && writeScope($scope0_id, { a: _existing_scope($childScope) });
10597
10554
  });
10598
- _template("D", (input) => {
10555
+ _template("E", (input) => {
10599
10556
  const $scope0_reason = _scope_reason(), $sg__input_size__OR__input_class = _serialize_guard($scope0_reason, 0);
10600
10557
  const $scope0_id = _scope_id();
10601
10558
  _set_serialize_reason({
@@ -10617,19 +10574,19 @@ var REPEAT_EVERY = 55;
10617
10574
  var term_default = _template("v", (input) => {
10618
10575
  const $scope0_reason = _scope_reason();
10619
10576
  _serialize_guard($scope0_reason, 3);
10620
- _serialize_guard($scope0_reason, 5);
10621
- _serialize_guard($scope0_reason, 7);
10577
+ _serialize_guard($scope0_reason, 6);
10622
10578
  _serialize_guard($scope0_reason, 8);
10623
- const $si__input_sessions = _serialize_if($scope0_reason, 7);
10579
+ _serialize_guard($scope0_reason, 9);
10580
+ const $si__input_sessions = _serialize_if($scope0_reason, 8);
10624
10581
  _serialize_guard($scope0_reason, 1);
10625
10582
  _serialize_guard($scope0_reason, 10);
10626
- const $si__input_onRenameSession = _serialize_if($scope0_reason, 8);
10583
+ const $si__input_onRenameSession = _serialize_if($scope0_reason, 9);
10627
10584
  _serialize_guard($scope0_reason, 11);
10628
- const $si__input_agents = _serialize_if($scope0_reason, 11), $si__input_agent = _serialize_if($scope0_reason, 5);
10585
+ const $si__input_agents = _serialize_if($scope0_reason, 11), $si__input_mode = _serialize_if($scope0_reason, 3), $si__input_agent = _serialize_if($scope0_reason, 6);
10629
10586
  _serialize_guard($scope0_reason, 2);
10630
10587
  _serialize_guard($scope0_reason, 4);
10631
10588
  _serialize_guard($scope0_reason, 12);
10632
- const $si__input_onCloseSession = _serialize_if($scope0_reason, 10), $si__input_sessionId = _serialize_if($scope0_reason, 9), $si__input_sessionState = _serialize_if($scope0_reason, 6), $si__input_workspaceName = _serialize_if($scope0_reason, 12);
10589
+ const $si__input_onCloseSession = _serialize_if($scope0_reason, 10), $si__input_sessionId = _serialize_if($scope0_reason, 5), $si__input_sessionState = _serialize_if($scope0_reason, 7), $si__input_workspaceName = _serialize_if($scope0_reason, 12);
10633
10590
  const $scope0_id = _scope_id();
10634
10591
  _hoist($scope0_id, "v20");
10635
10592
  const $findOpen__closures = /* @__PURE__ */ new Set();
@@ -10641,6 +10598,7 @@ var term_default = _template("v", (input) => {
10641
10598
  const $input_agent__closures = /* @__PURE__ */ new Set();
10642
10599
  const $input_sessionState__closures = /* @__PURE__ */ new Set();
10643
10600
  const $input_agents__closures = /* @__PURE__ */ new Set();
10601
+ const $onTermPage__closures = /* @__PURE__ */ new Set();
10644
10602
  const $input_workspaceName__closures = /* @__PURE__ */ new Set();
10645
10603
  let dead = false;
10646
10604
  let kb = false;
@@ -10709,14 +10667,12 @@ var term_default = _template("v", (input) => {
10709
10667
  }
10710
10668
  openFind();
10711
10669
  }, "v7", $scope0_id);
10712
- const canFind = (() => {
10713
- const mode = input.mode;
10714
- return mode == null || mode === "term" || mode === "diff";
10715
- })();
10716
- const findLit = !input.mode || input.mode === "term" ? findOpen : input.mode === "diff" && !!input.reviewFindOpen;
10670
+ const onTermPage = input.mode == null || input.mode === "term";
10671
+ const canKeys = onTermPage || input.mode === "diff";
10672
+ const findLit = onTermPage ? findOpen : input.mode === "diff" && !!input.reviewFindOpen;
10717
10673
  const toggleSharedFind = _resume(() => {
10718
- if (!canFind) return;
10719
- if (!input.mode || input.mode === "term") {
10674
+ if (!canKeys) return;
10675
+ if (onTermPage) {
10720
10676
  toggleFind();
10721
10677
  return;
10722
10678
  }
@@ -10790,7 +10746,7 @@ var term_default = _template("v", (input) => {
10790
10746
  trapOpen = true;
10791
10747
  }
10792
10748
  }, "v14", $scope0_id);
10793
- _html(`<div${_attr("hidden", input.mode != null && input.mode !== "term")}${_attr_class(term_module_default.termWrap)}><div${_attr_class(term_module_default.term)}></div>${_el_resume($scope0_id, "b")}`);
10749
+ _html(`<div${_attr("hidden", !onTermPage)}${_attr_class(term_module_default.termWrap)}><div${_attr_class(term_module_default.term)}></div>${_el_resume($scope0_id, "b")}`);
10794
10750
  _if(() => {
10795
10751
  if (findOpen) {
10796
10752
  const $scope11_id = _scope_id();
@@ -10843,9 +10799,9 @@ var term_default = _template("v", (input) => {
10843
10799
  }, $scope0_id, "g", 1, 1, 1, 0, 1);
10844
10800
  _html(`</div>${_el_resume($scope0_id, "a")}`);
10845
10801
  _if(() => {}, $scope0_id, "h", 1, 1, 1, 0, 1);
10846
- _script($scope0_id, "v38");
10847
10802
  _script($scope0_id, "v39");
10848
10803
  _script($scope0_id, "v40");
10804
+ _script($scope0_id, "v41");
10849
10805
  writeScope($scope0_id, {
10850
10806
  k: input.mode,
10851
10807
  l: input.reviewFindOpen,
@@ -10856,12 +10812,12 @@ var term_default = _template("v", (input) => {
10856
10812
  q: input.onExitReview,
10857
10813
  r: input.onToggleDiff,
10858
10814
  s: input.onNewSession,
10859
- t: input.agent,
10860
- u: input.sessionState,
10861
- v: input.sessions,
10862
- w: input.onRenameSession,
10863
- x: input.sessionId,
10864
- y: input.onOpenTab,
10815
+ t: input.onOpenTab,
10816
+ u: input.sessionId,
10817
+ v: input.agent,
10818
+ w: input.sessionState,
10819
+ x: input.sessions,
10820
+ y: input.onRenameSession,
10865
10821
  z: input.onCloseSession,
10866
10822
  a0: input.agents,
10867
10823
  a1: input.workspaceName,
@@ -10871,39 +10827,41 @@ var term_default = _template("v", (input) => {
10871
10827
  a5: touch,
10872
10828
  a8: trapOpen,
10873
10829
  a9: findOpen,
10874
- ac: $openChange,
10875
- ad: findTick,
10876
- af: ioBox.current,
10877
- ai: searchBox.query,
10878
- aj: searchBox.overlay,
10879
- ak: searchBox.refreshTimer,
10880
- am: findFocusRef,
10881
- ao: scheduleFindRefresh,
10882
- ap: runFind,
10883
- aq: clearFind,
10884
- as: openFind,
10885
- au: toggleFind,
10886
- av: canFind,
10887
- ax: findLit,
10888
- ay: toggleSharedFind,
10889
- b0: copyFlashBox.timer,
10890
- b1: flashCopied,
10891
- b3: holdBox.current,
10892
- b5: startHold,
10893
- b6: stopHold,
10894
- b7: uploadAsset,
10895
- ba: handlePasted,
10896
- bb: pasteClipboard,
10897
- bp: $findOpen__closures,
10898
- br: $findTick__closures,
10899
- bi: $si__input_onRenameSession && $input_onRenameSession__closures,
10900
- bk: $si__input_onCloseSession && $input_onCloseSession__closures,
10901
- bj: $si__input_sessionId && $input_sessionId__closures,
10902
- bh: $si__input_sessions && $input_sessions__closures,
10903
- bf: $si__input_agent && $input_agent__closures,
10904
- bg: $si__input_sessionState && $input_sessionState__closures,
10905
- bl: $si__input_agents && $input_agents__closures,
10906
- bm: $si__input_workspaceName && $input_workspaceName__closures
10830
+ ab: $openChange,
10831
+ ac: findTick,
10832
+ ae: ioBox.current,
10833
+ ah: searchBox.query,
10834
+ ai: searchBox.overlay,
10835
+ aj: searchBox.refreshTimer,
10836
+ al: findFocusRef,
10837
+ an: scheduleFindRefresh,
10838
+ ao: runFind,
10839
+ ap: clearFind,
10840
+ aq: openFind,
10841
+ as: toggleFind,
10842
+ at: onTermPage,
10843
+ aw: canKeys,
10844
+ ay: findLit,
10845
+ az: toggleSharedFind,
10846
+ b1: copyFlashBox.timer,
10847
+ b2: flashCopied,
10848
+ b4: holdBox.current,
10849
+ b6: startHold,
10850
+ b7: stopHold,
10851
+ b8: uploadAsset,
10852
+ bb: handlePasted,
10853
+ bc: pasteClipboard,
10854
+ bq: $findOpen__closures,
10855
+ bs: $findTick__closures,
10856
+ bk: $si__input_onRenameSession && $input_onRenameSession__closures,
10857
+ bl: $si__input_onCloseSession && $input_onCloseSession__closures,
10858
+ bg: $si__input_sessionId && $input_sessionId__closures,
10859
+ bj: $si__input_sessions && $input_sessions__closures,
10860
+ bh: $si__input_agent && $input_agent__closures,
10861
+ bi: $si__input_sessionState && $input_sessionState__closures,
10862
+ bm: $si__input_agents && $input_agents__closures,
10863
+ bx: $si__input_mode && $onTermPage__closures,
10864
+ bn: $si__input_workspaceName && $input_workspaceName__closures
10907
10865
  });
10908
10866
  _resume_branch($scope0_id);
10909
10867
  });
@@ -13529,31 +13487,720 @@ function head16(context) {
13529
13487
  return stripResponseBody(get16(context));
13530
13488
  }
13531
13489
  //#endregion
13532
- //#region src/server/usage.ts
13490
+ //#region src/server/usage/shared.ts
13491
+ var HOME = os.homedir();
13492
+ var obj = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
13493
+ var arr = (value) => Array.isArray(value) ? value : [];
13494
+ var str = (value) => typeof value === "string" ? value : "";
13495
+ /** Numeric coercion that refuses NaN/Infinity — a provider sending "n/a"
13496
+ * must read as "no number", not as a percentage that renders a bar. */
13497
+ function num(value) {
13498
+ if (value == null || value === "") return null;
13499
+ const n = typeof value === "number" ? value : Number(value);
13500
+ return Number.isFinite(n) ? n : null;
13501
+ }
13502
+ function readJson(file) {
13503
+ try {
13504
+ return obj(JSON.parse(fs.readFileSync(file, "utf8")));
13505
+ } catch {
13506
+ return null;
13507
+ }
13508
+ }
13509
+ /** True if an epoch (seconds or ms) or ISO-8601 expiry is in the past. */
13510
+ function expired(value) {
13511
+ if (value == null) return false;
13512
+ if (typeof value === "string") {
13513
+ const t = Date.parse(value.replace(/\.\d+/, ""));
13514
+ return Number.isFinite(t) && t < Date.now();
13515
+ }
13516
+ const n = num(value);
13517
+ if (n == null) return false;
13518
+ return (n > 1e11 ? n : n * 1e3) < Date.now();
13519
+ }
13520
+ function isoFromEpoch(value) {
13521
+ const n = num(value);
13522
+ if (n == null || n <= 0) return null;
13523
+ const ms = n > 1e11 ? n : n * 1e3;
13524
+ return new Date(ms).toISOString();
13525
+ }
13526
+ /** `p•••@g•••.com` — enough to tell two accounts apart, and the page is
13527
+ * screenshotted into PRs and chat, so the address itself doesn't belong. */
13528
+ function maskEmail(email) {
13529
+ if (!email || !email.includes("@")) return email || "—";
13530
+ const [local, domain] = email.split("@");
13531
+ if (!local || !domain) return email;
13532
+ const tld = domain.split(".").pop() || "";
13533
+ return `${local[0]}•••@${domain[0]}•••.${tld}`;
13534
+ }
13535
+ /** A fetch that failed, carrying a reason fit to show on the row.
13536
+ *
13537
+ * A stale number with no explanation is what makes a usage table untrustworthy
13538
+ * — "why is claude2 from yesterday?" deserves an answer next to the number. */
13539
+ var FetchFailed = class extends Error {
13540
+ reason;
13541
+ constructor(reason) {
13542
+ super(reason);
13543
+ this.reason = reason;
13544
+ }
13545
+ };
13546
+ function httpReason(status) {
13547
+ if (status === 401 || status === 403) return "auth expired";
13548
+ if (status === 429) return "rate limited or auth expired";
13549
+ if (status >= 500) return `provider error (HTTP ${status})`;
13550
+ return `HTTP ${status}`;
13551
+ }
13552
+ var TIMEOUT_MS = 15e3;
13553
+ /** JSON over HTTPS, with every failure mode collapsed into a FetchFailed
13554
+ * whose reason is worth showing to a human. */
13555
+ async function fetchJson(url, init = {}) {
13556
+ let res;
13557
+ try {
13558
+ res = await fetch(url, {
13559
+ ...init,
13560
+ signal: AbortSignal.timeout(TIMEOUT_MS)
13561
+ });
13562
+ } catch (err) {
13563
+ const name = err?.name;
13564
+ throw new FetchFailed(name === "TimeoutError" || name === "AbortError" ? "timed out" : "network unreachable");
13565
+ }
13566
+ if (!res.ok) throw new FetchFailed(httpReason(res.status));
13567
+ try {
13568
+ return await res.json();
13569
+ } catch {
13570
+ throw new FetchFailed("unreadable response");
13571
+ }
13572
+ }
13573
+ var cacheDir = path.join(config.dataDir, "usage");
13574
+ function readCache(key) {
13575
+ const blob = readJson(path.join(cacheDir, `${key}.json`));
13576
+ if (!blob) return null;
13577
+ const payload = blob.payload;
13578
+ const at = num(blob.fetched_at);
13579
+ if (!payload || typeof payload !== "object" || at == null) return null;
13580
+ return {
13581
+ payload: obj(payload),
13582
+ ageMs: Math.max(0, Date.now() - at)
13583
+ };
13584
+ }
13585
+ function writeCache(key, payload) {
13586
+ try {
13587
+ fs.mkdirSync(cacheDir, { recursive: true });
13588
+ fs.writeFileSync(path.join(cacheDir, `${key}.json`), JSON.stringify({
13589
+ fetched_at: Date.now(),
13590
+ payload
13591
+ }));
13592
+ } catch {}
13593
+ }
13594
+ /** Live fetch, falling back to the last good payload on disk.
13595
+ *
13596
+ * There is no "cache is fresh enough, skip the fetch" branch: the page's own
13597
+ * 60s stale-while-revalidate (server/usage/index.ts) already decides how often
13598
+ * this runs, and a second TTL underneath it only makes the numbers older than
13599
+ * the page claims. */
13600
+ async function loadPayload(key, live) {
13601
+ let reason;
13602
+ try {
13603
+ const data = await live();
13604
+ if (data) {
13605
+ writeCache(key, data);
13606
+ return {
13607
+ payload: data,
13608
+ source: "live"
13609
+ };
13610
+ }
13611
+ } catch (err) {
13612
+ reason = err instanceof FetchFailed ? err.reason : "fetch failed";
13613
+ }
13614
+ const disk = readCache(key);
13615
+ if (disk) return {
13616
+ payload: disk.payload,
13617
+ source: `stale-cache ${Math.round(disk.ageMs / 1e3)}s`,
13618
+ reason
13619
+ };
13620
+ return {
13621
+ payload: null,
13622
+ source: "missing",
13623
+ reason
13624
+ };
13625
+ }
13626
+ /** How to get a fresh token back, per provider. */
13627
+ var REAUTH = {
13628
+ codex: "codex login",
13629
+ cursor: "cursor-agent login",
13630
+ grok: "grok",
13631
+ copilot: "gh auth login"
13632
+ };
13633
+ /** Never signed in (or the CLI's credentials went missing) — not an outage.
13634
+ * Distinct from a failed request: nothing was ever sent, so blaming the
13635
+ * network would send you debugging the wrong thing. */
13636
+ function noAuthReason(key) {
13637
+ const hint = REAUTH[key];
13638
+ return hint ? `not signed in (run \`${hint}\`)` : "no credentials on disk";
13639
+ }
13640
+ function blankRow(agent, source = "missing") {
13641
+ return {
13642
+ agent,
13643
+ plan: agent,
13644
+ account: "—",
13645
+ five_h: null,
13646
+ five_h_resets: null,
13647
+ seven_d: null,
13648
+ seven_d_resets: null,
13649
+ fable: null,
13650
+ fable_resets: null,
13651
+ source
13652
+ };
13653
+ }
13654
+ /** Say *why* a row is showing last-known numbers, on the row itself.
13655
+ *
13656
+ * `tokenExpired` is the local credential check: true/false where an expiry is
13657
+ * readable off disk, undefined where it isn't. It beats guessing from the
13658
+ * status code — a dead token comes back 429 or 403 as readily as 401 — and
13659
+ * knowing the token is *good* is what lets a 429 be reported as plain
13660
+ * throttling instead of sending you to re-authenticate for nothing. */
13661
+ function markStale(row, key, tokenExpired, reason) {
13662
+ if (!/^(stale|claude\.json|missing)/.test(row.source)) return row;
13663
+ let why = reason ?? (tokenExpired ? "auth expired" : void 0);
13664
+ if (!why) why = "couldn't reach provider";
13665
+ if (why.startsWith("rate limited") && tokenExpired === false) why = "rate limited — retry shortly";
13666
+ else if (/^(auth expired|rate limited)/.test(why)) {
13667
+ const hint = REAUTH[key];
13668
+ why += hint ? ` (run \`${hint}\`)` : " (sign in again)";
13669
+ }
13670
+ return {
13671
+ ...row,
13672
+ stale_reason: why
13673
+ };
13674
+ }
13675
+ //#endregion
13676
+ //#region src/server/usage/claude.ts
13677
+ /** Every Claude account this machine can read.
13678
+ *
13679
+ * Numbered dirs (~/.claude-1, -2) keep metadata at <dir>/.claude.json; the
13680
+ * stock single-account install keeps it at ~/.claude.json with only
13681
+ * credentials under ~/.claude/. */
13682
+ function claudeAccounts() {
13683
+ const candidates = [...[1, 2].map((n) => ({
13684
+ suffix: String(n),
13685
+ dir: path.join(HOME, `.claude-${n}`),
13686
+ meta: path.join(HOME, `.claude-${n}`, ".claude.json"),
13687
+ label: `claude${n}`
13688
+ })), {
13689
+ suffix: "",
13690
+ dir: path.join(HOME, ".claude"),
13691
+ meta: path.join(HOME, ".claude.json"),
13692
+ label: "claude"
13693
+ }];
13694
+ const out = [];
13695
+ for (const candidate of candidates) {
13696
+ const meta = readJson(candidate.meta);
13697
+ if (!meta) continue;
13698
+ const oauth = obj(meta.oauthAccount);
13699
+ out.push({
13700
+ ...candidate,
13701
+ email: str(oauth.emailAddress).trim(),
13702
+ plan: str(oauth.organizationRateLimitTier || oauth.organizationType)
13703
+ });
13704
+ }
13705
+ return out;
13706
+ }
13707
+ var credentials = (account) => readJson(path.join(account.dir, ".credentials.json"));
13708
+ /** Why an account has no live data — an expired token is the common case
13709
+ * and only that account's own CLI can refresh it. */
13710
+ function credentialNote(account) {
13711
+ const cred = credentials(account);
13712
+ if (!cred) return "no credentials — run: claude";
13713
+ if (expired(obj(cred.claudeAiOauth).expiresAt)) return "token expired — use this Claude account to refresh";
13714
+ return "usage unavailable";
13715
+ }
13716
+ function tokenExpired(account) {
13717
+ const cred = credentials(account);
13718
+ return cred ? expired(obj(cred.claudeAiOauth).expiresAt) : false;
13719
+ }
13720
+ async function fetchUsage$3(account) {
13721
+ const token = str(obj(credentials(account)?.claudeAiOauth).accessToken);
13722
+ if (!token) return null;
13723
+ return obj(await fetchJson("https://api.anthropic.com/api/oauth/usage", { headers: {
13724
+ Authorization: `Bearer ${token}`,
13725
+ "anthropic-beta": "oauth-2025-04-20",
13726
+ "User-Agent": "claude-cli",
13727
+ Accept: "application/json"
13728
+ } }));
13729
+ }
13730
+ /** The CLI's own last-seen utilization, written into .claude.json. Older and
13731
+ * coarser than the API, but it survives an expired token. */
13732
+ function claudeJsonFallback(account) {
13733
+ const cached = readJson(account.meta)?.cachedUsageUtilization;
13734
+ return cached && typeof cached === "object" ? obj(cached) : null;
13735
+ }
13736
+ /** The payload nests windows under `utilization` on some plans and inlines
13737
+ * them on others. */
13738
+ function utilRoot(data) {
13739
+ const util = obj(data.utilization);
13740
+ return "five_hour" in util || "limits" in util ? util : data;
13741
+ }
13742
+ function window$2(data, key) {
13743
+ const win = obj(utilRoot(data)[key]);
13744
+ const used = num(win.utilization);
13745
+ return [used == null ? null : Math.trunc(used), str(win.resets_at) || null];
13746
+ }
13747
+ /** Fable gets its own weekly cap, listed as a model-scoped limit rather than
13748
+ * a top-level window. */
13749
+ function fableWindow(data) {
13750
+ for (const entry of arr(utilRoot(data).limits)) {
13751
+ const limit = obj(entry);
13752
+ if (limit.kind !== "weekly_scoped") continue;
13753
+ const model = obj(obj(limit.scope).model);
13754
+ if (!str(model.display_name || model.id).toLowerCase().includes("fable")) continue;
13755
+ const pct = num(limit.percent);
13756
+ return [pct == null ? null : Math.trunc(pct), str(limit.resets_at) || null];
13757
+ }
13758
+ return [null, null];
13759
+ }
13760
+ function parseRow$4(account, data, source) {
13761
+ const [five, fiveResets] = data ? window$2(data, "five_hour") : [null, null];
13762
+ const [seven, sevenResets] = data ? window$2(data, "seven_day") : [null, null];
13763
+ const [fable, fableResets] = data ? fableWindow(data) : [null, null];
13764
+ const row = {
13765
+ agent: account.label,
13766
+ plan: account.plan || "claude",
13767
+ account: maskEmail(account.email),
13768
+ five_h: five,
13769
+ five_h_resets: fiveResets,
13770
+ seven_d: seven,
13771
+ seven_d_resets: sevenResets,
13772
+ fable,
13773
+ fable_resets: fableResets,
13774
+ source
13775
+ };
13776
+ if (five == null && seven == null && fable == null) row.note = credentialNote(account);
13777
+ return row;
13778
+ }
13779
+ async function claudeRow(account) {
13780
+ const loaded = await loadPayload(`claude${account.suffix}`, () => fetchUsage$3(account));
13781
+ const fallback = loaded.payload ? null : claudeJsonFallback(account);
13782
+ return markStale(parseRow$4(account, loaded.payload ?? fallback, fallback ? "claude.json" : loaded.source), account.label, tokenExpired(account), loaded.reason);
13783
+ }
13784
+ //#endregion
13785
+ //#region src/server/usage/codex.ts
13786
+ var AUTH$2 = path.join(HOME, ".codex", "auth.json");
13787
+ /** Live rate-limit windows from the endpoint the Codex CLI itself uses. */
13788
+ async function fetchUsage$2() {
13789
+ const tokens = obj(readJson(AUTH$2)?.tokens);
13790
+ const token = str(tokens.access_token);
13791
+ if (!token) return null;
13792
+ return obj(await fetchJson("https://chatgpt.com/backend-api/wham/usage", { headers: {
13793
+ Authorization: `Bearer ${token}`,
13794
+ "chatgpt-account-id": str(tokens.account_id),
13795
+ "User-Agent": "codex-cli",
13796
+ Accept: "application/json"
13797
+ } }));
13798
+ }
13799
+ /** (used percent, reset) for whichever window is `seconds` long — the two
13800
+ * windows arrive as primary/secondary rather than named 5h / 7d. */
13801
+ function window$1(rateLimit, seconds) {
13802
+ for (const key of ["primary_window", "secondary_window"]) {
13803
+ const win = obj(rateLimit[key]);
13804
+ if (num(win.limit_window_seconds) !== seconds) continue;
13805
+ const used = num(win.used_percent);
13806
+ return [used == null ? null : Math.trunc(used), isoFromEpoch(win.reset_at)];
13807
+ }
13808
+ return [null, null];
13809
+ }
13810
+ function parseRow$3(payload, source) {
13811
+ const rateLimit = obj(payload.rate_limit);
13812
+ const [five, fiveResets] = window$1(rateLimit, 18e3);
13813
+ const [seven, sevenResets] = window$1(rateLimit, 604800);
13814
+ return {
13815
+ agent: "codex",
13816
+ plan: str(payload.plan_type) || "codex",
13817
+ account: maskEmail(str(payload.email)),
13818
+ five_h: five,
13819
+ five_h_resets: fiveResets,
13820
+ seven_d: seven,
13821
+ seven_d_resets: sevenResets,
13822
+ fable: null,
13823
+ fable_resets: null,
13824
+ source
13825
+ };
13826
+ }
13827
+ async function codexRow() {
13828
+ const { payload, source, reason } = await loadPayload("codex", fetchUsage$2);
13829
+ const missingAuth = fs.existsSync(AUTH$2) ? void 0 : noAuthReason("codex");
13830
+ return markStale(payload ? parseRow$3(payload, source) : {
13831
+ ...blankRow("codex", source),
13832
+ note: missingAuth ?? "usage unavailable"
13833
+ }, "codex", void 0, missingAuth ?? reason);
13834
+ }
13835
+ //#endregion
13836
+ //#region src/server/usage/copilot.ts
13837
+ var USER_API = "https://api.github.com/copilot_internal/user";
13838
+ var HOSTS = path.join(process.env.XDG_CONFIG_HOME || path.join(HOME, ".config"), "gh", "hosts.yml");
13839
+ var SESSION_DB = path.join(HOME, ".copilot", "session-store.db");
13840
+ /** github.com's `oauth_token` straight out of gh's own hosts.yml.
13841
+ *
13842
+ * Deliberately not a YAML parse (no dependency): track the current top-level
13843
+ * host key by indentation and take the first token beneath github.com. */
13844
+ function hostsToken() {
13845
+ let text;
13846
+ try {
13847
+ text = fs.readFileSync(HOSTS, "utf8");
13848
+ } catch {
13849
+ return null;
13850
+ }
13851
+ let host = "";
13852
+ for (const line of text.split("\n")) {
13853
+ if (line[0]?.trim() && line.trimEnd().endsWith(":")) {
13854
+ host = line.trim().replace(/:$/, "");
13855
+ continue;
13856
+ }
13857
+ if (host !== "github.com") continue;
13858
+ const match = /^\s+oauth_token:\s*(\S+)/.exec(line);
13859
+ if (match) return match[1] ?? null;
13860
+ }
13861
+ return null;
13862
+ }
13863
+ /** The Copilot CLI keeps its own auth in the OS keyring, so reuse the token
13864
+ * gh manages. Copilot entitlement is account-scoped, so any valid token for
13865
+ * the entitled user reads the quota. */
13866
+ async function token() {
13867
+ for (const key of ["GH_TOKEN", "GITHUB_TOKEN"]) {
13868
+ const value = process.env[key]?.trim();
13869
+ if (value) return value;
13870
+ }
13871
+ const fromHosts = hostsToken();
13872
+ if (fromHosts) return fromHosts;
13873
+ try {
13874
+ return await run("gh", ["auth", "token"]) || null;
13875
+ } catch {
13876
+ return null;
13877
+ }
13878
+ }
13879
+ async function fetchUsage$1(auth) {
13880
+ if (!auth) return null;
13881
+ const data = obj(await fetchJson(USER_API, { headers: {
13882
+ Authorization: `token ${auth}`,
13883
+ "User-Agent": "GitHubCopilotCLI",
13884
+ Accept: "application/json"
13885
+ } }));
13886
+ return data.quota_snapshots == null ? null : data;
13887
+ }
13888
+ /** Billing period start = one month before the quota reset date. */
13889
+ function periodStart(resetIso) {
13890
+ const reset = new Date(resetIso);
13891
+ if (Number.isNaN(reset.getTime())) return null;
13892
+ const year = reset.getUTCMonth() === 0 ? reset.getUTCFullYear() - 1 : reset.getUTCFullYear();
13893
+ const month = reset.getUTCMonth() === 0 ? 12 : reset.getUTCMonth();
13894
+ const day = Math.min(reset.getUTCDate(), 28);
13895
+ return `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
13896
+ }
13897
+ /** Credits this machine's Copilot CLI has spent in the current period.
13898
+ *
13899
+ * GitHub's own quota snapshot is batched — it can still read `credits_used: 0`
13900
+ * minutes after a session that plainly spent credits — so the CLI's local
13901
+ * ledger is the only number that moves in real time. It sees this machine
13902
+ * only, which is why the caller floors it with upstream rather than trusting
13903
+ * it alone. */
13904
+ function localCredits(start) {
13905
+ if (!start || !fs.existsSync(SESSION_DB)) return null;
13906
+ try {
13907
+ const db = new DatabaseSync(SESSION_DB, { readOnly: true });
13908
+ try {
13909
+ const nano = num(db.prepare("select sum(total_nano_aiu) as nano from assistant_usage_events where created_at >= ?").get(start)?.nano);
13910
+ return nano == null ? 0 : nano / 1e9;
13911
+ } finally {
13912
+ db.close();
13913
+ }
13914
+ } catch {
13915
+ return null;
13916
+ }
13917
+ }
13918
+ function parseRow$2(payload, source) {
13919
+ const premium = obj(obj(payload.quota_snapshots).premium_interactions);
13920
+ const reset = str(payload.quota_reset_date_utc || payload.quota_reset_date) || null;
13921
+ let pct = null;
13922
+ let note;
13923
+ if (!Object.keys(premium).length || !premium.has_quota) note = "no premium quota";
13924
+ else if (premium.unlimited) note = "unlimited premium requests";
13925
+ else {
13926
+ const remaining = num(premium.percent_remaining);
13927
+ if (remaining != null) pct = 100 - remaining;
13928
+ const entitlement = num(premium.entitlement) ?? 0;
13929
+ const used = reset ? localCredits(periodStart(reset)) : null;
13930
+ if (entitlement > 0 && used != null) {
13931
+ const localPct = 100 * used / entitlement;
13932
+ if (pct == null || localPct > pct) {
13933
+ pct = localPct;
13934
+ source = `${source}+local`;
13935
+ }
13936
+ }
13937
+ }
13938
+ if (pct != null) pct = Math.round(pct * 1e3) / 1e3;
13939
+ const row = {
13940
+ agent: "copilot",
13941
+ plan: str(payload.copilot_plan) || "copilot",
13942
+ account: str(payload.login) || "—",
13943
+ five_h: null,
13944
+ five_h_resets: null,
13945
+ seven_d: pct,
13946
+ seven_d_resets: pct == null ? null : reset,
13947
+ fable: null,
13948
+ fable_resets: null,
13949
+ source
13950
+ };
13951
+ if (note) row.note = note;
13952
+ return row;
13953
+ }
13954
+ async function copilotRow() {
13955
+ const auth = await token();
13956
+ const { payload, source, reason } = await loadPayload("copilot", () => fetchUsage$1(auth));
13957
+ const missingAuth = auth ? void 0 : noAuthReason("copilot");
13958
+ return markStale(payload ? parseRow$2(payload, source) : {
13959
+ ...blankRow("copilot", source),
13960
+ note: missingAuth ?? "usage unavailable"
13961
+ }, "copilot", void 0, missingAuth ?? reason);
13962
+ }
13963
+ //#endregion
13964
+ //#region src/server/usage/cursor.ts
13965
+ var AUTH$1 = path.join(HOME, ".config", "cursor", "auth.json");
13966
+ var CLI_CONFIG = path.join(HOME, ".cursor", "cli-config.json");
13967
+ var API = "https://api2.cursor.sh";
13968
+ var WWW = "https://cursor.com";
13969
+ function cursorAuth() {
13970
+ const auth = readJson(AUTH$1);
13971
+ if (!auth) return null;
13972
+ const token = str(auth.accessToken || auth.access_token);
13973
+ if (!token) return null;
13974
+ let sub = "";
13975
+ try {
13976
+ sub = str(obj(JSON.parse(Buffer.from(str(token.split(".")[1]), "base64url").toString())).sub);
13977
+ } catch {}
13978
+ return {
13979
+ token,
13980
+ sub,
13981
+ email: str(obj(readJson(CLI_CONFIG)?.authInfo).email).trim()
13982
+ };
13983
+ }
13984
+ var dashboardPost = async (token, method) => obj(await fetchJson(`${API}/aiserver.v1.DashboardService/${method}`, {
13985
+ method: "POST",
13986
+ body: "{}",
13987
+ headers: {
13988
+ Authorization: `Bearer ${token}`,
13989
+ "Content-Type": "application/json",
13990
+ Accept: "application/json",
13991
+ "Connect-Protocol-Version": "1",
13992
+ "User-Agent": "cursor-agent"
13993
+ }
13994
+ }));
13995
+ /** Enterprise/team monthly pool, which the dashboard service leaves empty —
13996
+ * it is only readable with the web session cookie. */
13997
+ async function usageSummary(auth) {
13998
+ if (!auth.sub) return null;
13999
+ const cookie = `WorkosCursorSessionToken=${encodeURIComponent(`${auth.sub}::${auth.token}`)}`;
14000
+ return obj(await fetchJson(`${WWW}/api/usage-summary`, { headers: {
14001
+ Cookie: cookie,
14002
+ Accept: "application/json",
14003
+ "User-Agent": "Mozilla/5.0"
14004
+ } }));
14005
+ }
14006
+ /** Prefer the dashboard's planUsage (Pro/Ultra); fall back to the web
14007
+ * summary for Enterprise/team accounts, where planUsage comes back empty.
14008
+ * Each call is optional on its own, so one failing endpoint must not hide a
14009
+ * number another would have produced — but if nothing lands, the first
14010
+ * failure is rethrown so the row can say why. */
14011
+ async function fetchUsage(auth) {
14012
+ let failure;
14013
+ const soft = async (load) => {
14014
+ try {
14015
+ return await load();
14016
+ } catch (err) {
14017
+ failure ??= err;
14018
+ return null;
14019
+ }
14020
+ };
14021
+ const [period, planInfo] = await Promise.all([soft(() => dashboardPost(auth.token, "GetCurrentPeriodUsage")), soft(() => dashboardPost(auth.token, "GetPlanInfo"))]);
14022
+ const planUsage = obj(obj(period).planUsage);
14023
+ const summary = num(planUsage.limit) ? null : await soft(() => usageSummary(auth));
14024
+ if (!Object.keys(planUsage).length && !summary) {
14025
+ if (failure) throw failure;
14026
+ return null;
14027
+ }
14028
+ return {
14029
+ period: obj(period),
14030
+ plan_info: obj(obj(planInfo).planInfo),
14031
+ summary
14032
+ };
14033
+ }
14034
+ function parseRow$1(payload, auth, source) {
14035
+ const period = obj(payload.period);
14036
+ const planInfo = obj(payload.plan_info);
14037
+ const summary = obj(payload.summary);
14038
+ let pct = num(obj(period.planUsage).totalPercentUsed);
14039
+ let resets = isoFromEpoch(period.billingCycleEnd);
14040
+ if (pct == null) {
14041
+ const overall = obj(obj(summary.individualUsage).overall);
14042
+ const used = num(overall.used);
14043
+ const limit = num(overall.limit);
14044
+ if (used != null && limit) pct = Math.round(100 * used / limit);
14045
+ resets = str(summary.billingCycleEnd) || resets;
14046
+ }
14047
+ return {
14048
+ agent: "cursor",
14049
+ plan: str(planInfo.planName || summary.membershipType) || "cursor",
14050
+ account: auth?.email ? maskEmail(auth.email) : "—",
14051
+ five_h: null,
14052
+ five_h_resets: null,
14053
+ seven_d: pct == null ? null : Math.trunc(pct),
14054
+ seven_d_resets: resets,
14055
+ fable: null,
14056
+ fable_resets: null,
14057
+ source
14058
+ };
14059
+ }
14060
+ async function cursorRow() {
14061
+ const auth = cursorAuth();
14062
+ const { payload, source, reason } = await loadPayload("cursor", () => auth ? fetchUsage(auth) : Promise.resolve(null));
14063
+ const missingAuth = auth ? void 0 : noAuthReason("cursor");
14064
+ return markStale(payload ? parseRow$1(payload, auth, source) : {
14065
+ ...blankRow("cursor", source),
14066
+ note: missingAuth ?? "usage unavailable"
14067
+ }, "cursor", void 0, missingAuth ?? reason);
14068
+ }
14069
+ //#endregion
14070
+ //#region src/server/usage/grok.ts
14071
+ var AUTH = path.join(HOME, ".grok", "auth.json");
14072
+ var LOG = path.join(HOME, ".grok", "logs", "unified.jsonl");
14073
+ /** The newest usable entry in ~/.grok/auth.json, which is keyed by scope
14074
+ * rather than being a single credential. */
14075
+ function grokAuth() {
14076
+ const auth = readJson(AUTH);
14077
+ if (!auth) return null;
14078
+ const entry = Object.values(auth).map(obj).filter((entry) => str(entry.key) || str(entry.access_token)).sort((a, b) => str(b.create_time || b.expires_at).localeCompare(str(a.create_time || a.expires_at)))[0];
14079
+ if (!entry) return null;
14080
+ return {
14081
+ token: str(entry.key) || str(entry.access_token),
14082
+ email: str(entry.email),
14083
+ expiresAt: entry.expires_at
14084
+ };
14085
+ }
14086
+ /** Weekly credit pool from the Grok Build CLI's own proxy. */
14087
+ async function fetchBilling(token) {
14088
+ const data = obj(await fetchJson("https://cli-chat-proxy.grok.com/v1/billing?format=credits", { headers: {
14089
+ Authorization: `Bearer ${token}`,
14090
+ Accept: "application/json",
14091
+ "User-Agent": "grok-cli",
14092
+ "x-grok-client-mode": "cli"
14093
+ } }));
14094
+ return data.config ? data : null;
14095
+ }
14096
+ /** Fallback: the last credits config the CLI logged, normalized to the live
14097
+ * API's shape. Reads only the tail — this log grows without bound. */
14098
+ function billingFromLogs() {
14099
+ let chunk;
14100
+ try {
14101
+ const { size } = fs.statSync(LOG);
14102
+ const start = Math.max(0, size - 512e3);
14103
+ const fd = fs.openSync(LOG, "r");
14104
+ try {
14105
+ const buf = Buffer.alloc(size - start);
14106
+ fs.readSync(fd, buf, 0, buf.length, start);
14107
+ chunk = buf.toString("utf8");
14108
+ } finally {
14109
+ fs.closeSync(fd);
14110
+ }
14111
+ } catch {
14112
+ return null;
14113
+ }
14114
+ let latest = null;
14115
+ for (const line of chunk.split("\n")) {
14116
+ if (!line.includes("billing: fetched credits config")) continue;
14117
+ try {
14118
+ const entry = obj(JSON.parse(line));
14119
+ if (entry.msg === "billing: fetched credits config") latest = entry;
14120
+ } catch {}
14121
+ }
14122
+ if (!latest) return null;
14123
+ const ctx = obj(latest.ctx);
14124
+ const cfg = obj(ctx.config);
14125
+ if (!Object.keys(cfg).length) return null;
14126
+ return {
14127
+ config: cfg,
14128
+ subscriptionTier: ctx.subscriptionTier
14129
+ };
14130
+ }
14131
+ function parseRow(payload, auth, source) {
14132
+ const cfg = payload.config ? obj(payload.config) : payload;
14133
+ const pct = num(cfg.creditUsagePercent);
14134
+ let productPct = null;
14135
+ for (const entry of arr(cfg.productUsage)) {
14136
+ const usage = obj(entry);
14137
+ if (!str(usage.product).toLowerCase().includes("grok")) continue;
14138
+ productPct = num(usage.usagePercent);
14139
+ break;
14140
+ }
14141
+ const used = pct ?? productPct;
14142
+ const period = obj(cfg.currentPeriod);
14143
+ return {
14144
+ agent: "grok",
14145
+ plan: str(payload.subscriptionTier || cfg.subscriptionTier) || "Grok Build",
14146
+ account: auth?.email ? maskEmail(auth.email) : "—",
14147
+ five_h: null,
14148
+ five_h_resets: null,
14149
+ seven_d: used == null ? null : Math.trunc(used),
14150
+ seven_d_resets: str(period.end || cfg.billingPeriodEnd) || null,
14151
+ fable: null,
14152
+ fable_resets: null,
14153
+ source
14154
+ };
14155
+ }
14156
+ async function grokRow() {
14157
+ const auth = grokAuth();
14158
+ const loaded = await loadPayload("grok", () => auth?.token ? fetchBilling(auth.token) : Promise.resolve(null));
14159
+ const fromLog = loaded.payload ? null : billingFromLogs();
14160
+ const payload = loaded.payload ?? fromLog;
14161
+ const source = fromLog ? "unified.jsonl" : loaded.source;
14162
+ const missingAuth = auth?.token ? void 0 : noAuthReason("grok");
14163
+ return markStale(payload ? parseRow(payload, auth, source) : {
14164
+ ...blankRow("grok", source),
14165
+ note: missingAuth ?? "usage unavailable"
14166
+ }, "grok", expired(auth?.expiresAt), missingAuth ?? loaded.reason);
14167
+ }
14168
+ //#endregion
14169
+ //#region src/server/usage/index.ts
13533
14170
  var TTL_MS = 6e4;
13534
- /** Plan/quota usage across agent accounts, via the plan-usage CLI. */
13535
- var usage = (refresh = false) => cached("usage", refresh);
13536
- var cached = swr(TTL_MS, fetchUsage);
13537
- /** Age of a row that the CLI served from a failed refresh, in seconds
13538
- * undefined when the numbers are current. Percentages from a stale row
13539
- * describe a window that has since moved on, so they can't be shown as
13540
- * live figures. */
14171
+ /** Plan/quota usage across every agent account this machine is signed into.
14172
+ *
14173
+ * Each provider is one blocking HTTPS round trip against the same endpoint its
14174
+ * own CLI uses; they touch disjoint credentials and cache files, so they run
14175
+ * concurrently and the wait is the slowest single provider, not their sum. */
14176
+ async function collect() {
14177
+ const providers = [
14178
+ ...claudeAccounts().map((account) => [account.label, () => claudeRow(account)]),
14179
+ ["codex", codexRow],
14180
+ ["cursor", cursorRow],
14181
+ ["grok", grokRow],
14182
+ ["copilot", copilotRow]
14183
+ ];
14184
+ return Promise.all(providers.map(([key, load]) => load().catch(() => ({
14185
+ ...blankRow(key, "error"),
14186
+ note: "fetch failed"
14187
+ }))));
14188
+ }
14189
+ /** Age of a row served from a failed refresh, in seconds — undefined when the
14190
+ * numbers are current. Percentages from a stale row describe a window that has
14191
+ * since moved on, so they can't be shown as live figures. */
13541
14192
  function staleSeconds(source) {
13542
- const match = /^stale-cache\s+(\d+(?:\.\d+)?)s/.exec(source || "");
14193
+ const match = /^stale-cache\s+(\d+)s/.exec(source);
13543
14194
  return match ? Number(match[1]) : void 0;
13544
14195
  }
13545
- async function fetchUsage(_key, refresh) {
13546
- let out = refresh ? await run("plan-usage", ["--json", "--refresh"]) : await run("plan-usage", ["--json", "--no-wait"]);
13547
- let rows = JSON.parse(out);
13548
- if (!rows.length && !refresh) {
13549
- out = await run("plan-usage", ["--json"]);
13550
- rows = JSON.parse(out);
13551
- }
13552
- return { agents: rows.map((row) => ({
14196
+ var cached = swr(TTL_MS, (_key, _refresh) => collect());
14197
+ var usage = async (refresh = false) => {
14198
+ return { agents: (await cached("usage", refresh)).map((row) => ({
13553
14199
  agent: row.agent,
13554
14200
  plan: row.plan,
13555
14201
  account: row.account,
13556
14202
  stale_seconds: staleSeconds(row.source),
14203
+ note: row.stale_reason || row.note,
13557
14204
  windows: [
13558
14205
  {
13559
14206
  window: "5h",
@@ -13572,7 +14219,7 @@ async function fetchUsage(_key, refresh) {
13572
14219
  }
13573
14220
  ].filter((w) => w.used_percent != null)
13574
14221
  })) };
13575
- }
14222
+ };
13576
14223
  //#endregion
13577
14224
  //#region __marko-run__api.usage.js
13578
14225
  var getHandler$6 = normalizeHandler(Run.GET({ search: (value) => ({ refresh: "refresh" in value }) }, async (ctx) => Response.json(await usage(ctx.search.refresh))), "GET");
@@ -14109,6 +14756,7 @@ var Dismiss = /* @__PURE__ */ object({
14109
14756
  var POST$3 = Run.POST({ json: Dismiss }, async (ctx) => {
14110
14757
  const body = await readBody(ctx);
14111
14758
  dismissPr(ctx.data.workspace.id, body.fullName, body.number);
14759
+ pokeStatusWatch();
14112
14760
  return Response.json(await listPrs(ctx.data.workspace, false));
14113
14761
  });
14114
14762
  async function listPrs(ws, refresh) {
@@ -18703,4 +19351,4 @@ server.listen(port, () => {
18703
19351
  //#endregion
18704
19352
  export {};
18705
19353
 
18706
- ;var __MARKO_MANIFEST__={"esfPH6H":{"block":[2,"stylesheet#/assets/index-DxoJXJz6.css",6,"<link",0," rel=\"stylesheet\" crossorigin href=\"",1,"assets/index-DxoJXJz6.css\"",">"],"defer":[2,"/assets/index-B-C71W3M.js",6,"<script",0," async type=\"module\" crossorigin src=\"",1,"assets/index-B-C71W3M.js\"","></script>"]}};
19354
+ ;var __MARKO_MANIFEST__={"esfPH6H":{"block":[2,"stylesheet#/assets/index--QwhN0hy.css",6,"<link",0," rel=\"stylesheet\" crossorigin href=\"",1,"assets/index--QwhN0hy.css\"",">"],"defer":[2,"/assets/index-CdVBL6Kf.js",6,"<script",0," async type=\"module\" crossorigin src=\"",1,"assets/index-CdVBL6Kf.js\"","></script>"]}};