@threadcrumbs/threadgauge 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +34 -0
- package/NOTICES.md +137 -0
- package/README.md +423 -3
- package/bin/threadgauge.mjs +99 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-ext-wght-normal-CXgNM06D.woff2 +0 -0
- package/dist/assets/atkinson-hyperlegible-mono-latin-wght-normal-CoA7y8X5.woff2 +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-ext-wght-normal-C6vrW8VD.woff2 +0 -0
- package/dist/assets/atkinson-hyperlegible-next-latin-wght-normal-BcXVPD7q.woff2 +0 -0
- package/dist/assets/barlow-latin-400-normal-qiz4-Cze.woff2 +0 -0
- package/dist/assets/barlow-latin-500-normal-BPAOfeC8.woff2 +0 -0
- package/dist/assets/barlow-latin-600-normal-DILqtrty.woff2 +0 -0
- package/dist/assets/barlow-latin-700-normal-A9pxMQ4z.woff2 +0 -0
- package/dist/assets/barlow-latin-ext-400-normal-HxX4XjxC.woff2 +0 -0
- package/dist/assets/barlow-latin-ext-500-normal-DOaysfXq.woff2 +0 -0
- package/dist/assets/barlow-latin-ext-600-normal-B8NK_A3D.woff2 +0 -0
- package/dist/assets/barlow-latin-ext-700-normal-BLuWmldJ.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-400-normal-DlzeKIMS.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-500-normal-G0uxJNrM.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-600-normal-BkLiAYu4.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-ext-400-normal-BDztQS4c.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-ext-500-normal-BXdp1BvY.woff2 +0 -0
- package/dist/assets/barlow-semi-condensed-latin-ext-600-normal-BkQ9hN72.woff2 +0 -0
- package/dist/assets/fira-code-latin-ext-wght-normal-Dvfvaomy.woff2 +0 -0
- package/dist/assets/fira-code-latin-wght-normal-CHoedHDv.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-400-normal-BmvZHCvU.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-500-normal-B1UMRPS4.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-600-normal-CdJSnjCb.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-ext-400-normal-BHj09Mzt.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-ext-500-normal-CDI94yGp.woff2 +0 -0
- package/dist/assets/fira-sans-condensed-latin-ext-600-normal-10nHsj_O.woff2 +0 -0
- package/dist/assets/fira-sans-latin-400-normal-a0AnQzuD.woff2 +0 -0
- package/dist/assets/fira-sans-latin-500-normal-Bvbxc8ch.woff2 +0 -0
- package/dist/assets/fira-sans-latin-600-normal-CXKlxLG9.woff2 +0 -0
- package/dist/assets/fira-sans-latin-700-normal-CRhwpWTq.woff2 +0 -0
- package/dist/assets/fira-sans-latin-ext-400-normal-BLG_mAEf.woff2 +0 -0
- package/dist/assets/fira-sans-latin-ext-500-normal-OO1QnNpY.woff2 +0 -0
- package/dist/assets/fira-sans-latin-ext-600-normal-DTQBTt1m.woff2 +0 -0
- package/dist/assets/fira-sans-latin-ext-700-normal-g2Yrd4J5.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
- package/dist/assets/ibm-plex-mono-latin-ext-600-normal-D38SheWl.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-400-normal-DKyD6XsY.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-500-normal-BqaLkUoX.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-600-normal-CRd5VyFf.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-ext-400-normal-BJ9nxTJg.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-ext-500-normal--oYb3bSD.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-condensed-latin-ext-600-normal-CBdNZ9Ci.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-700-normal-Bxkt5Cjx.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-ext-400-normal-C5H60-Va.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-ext-500-normal-DakdToA3.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-ext-600-normal-DOrvGEcy.woff2 +0 -0
- package/dist/assets/ibm-plex-sans-latin-ext-700-normal-aMgXseD4.woff2 +0 -0
- package/dist/assets/inconsolata-latin-ext-wght-normal-C75G6mlG.woff2 +0 -0
- package/dist/assets/inconsolata-latin-wght-normal-DBskYKbm.woff2 +0 -0
- package/dist/assets/index-DGQBjXpa.js +2 -0
- package/dist/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/dist/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/dist/assets/inter-tight-latin-ext-wght-normal-B4u9PlvR.woff2 +0 -0
- package/dist/assets/inter-tight-latin-wght-normal-DX-nOvPD.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/dist/assets/main-CEA6P2m0.js +2 -0
- package/dist/assets/preload-helper-BXl3LOEh.js +1 -0
- package/dist/assets/shell-DBhI_m_t.css +1 -0
- package/dist/assets/shell-fZRN8tMb.js +251 -0
- package/dist/assets/source-code-pro-latin-ext-wght-normal-0UZNSh4u.woff2 +0 -0
- package/dist/assets/source-code-pro-latin-wght-normal-BP8Zz55n.woff2 +0 -0
- package/dist/assets/source-sans-3-latin-ext-wght-normal-C8iNium2.woff2 +0 -0
- package/dist/assets/source-sans-3-latin-wght-normal-Bo_j9asI.woff2 +0 -0
- package/dist/favicon.svg +17 -0
- package/dist/index.html +16 -0
- package/package.json +75 -6
- package/server/api.mjs +188 -0
- package/server/details.mjs +64 -0
- package/server/history.mjs +65 -0
- package/server/http-server.mjs +87 -0
- package/server/lib/local-request.mjs +41 -0
- package/server/lib/open-url.mjs +16 -0
- package/server/lib/ports.mjs +54 -0
- package/server/license.mjs +100 -0
- package/server/monitor.mjs +136 -0
- package/server/open.mjs +49 -0
- package/server/paths.mjs +104 -0
- package/server/serve.mjs +8 -0
- package/server/threadnauts.mjs +23 -0
- package/server/threads.mjs +12 -0
- package/src/tiers.js +20 -0
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
const $e=[{key:"inter",label:"Inter",note:"Drawn for screens at small sizes. Labels use its tighter cut, Inter Tight."},{key:"barlow",label:"Barlow",note:"Labels use Barlow Semi Condensed."},{key:"plex",label:"IBM Plex Sans",note:"Labels use IBM Plex Sans Condensed."},{key:"atkinson",label:"Atkinson Hyperlegible",note:"The Braille Institute drew it so that letters that look alike, such as I, l, and 1, stay easy to tell apart."},{key:"fira",label:"Fira Sans",note:"Drawn for small phone screens. Labels use Fira Sans Condensed."},{key:"source",label:"Source Sans",note:"Narrow enough that labels need no condensed cut."}],ye=[{key:"jetbrains",label:"JetBrains Mono",note:"Drawn for reading code, with tall lowercase letters."},{key:"inconsolata",label:"Inconsolata",note:"The mono the mockup started with."},{key:"plex-mono",label:"IBM Plex Mono",note:"IBM's mono, drawn alongside Plex Sans."},{key:"atkinson-mono",label:"Atkinson Hyperlegible Mono",note:"The Braille Institute's mono, drawn so characters that look alike stay distinct."},{key:"fira-code",label:"Fira Code",note:"Fira Mono with ligatures for common code symbols."},{key:"source-code",label:"Source Code Pro",note:"Adobe's mono, drawn alongside Source Sans."}],cs="inter",ds="jetbrains";function Xa(t,{sans:e=cs,mono:n=ds}={}){const s=(o,r,i)=>o.some(c=>c.key===r)?r:i,a={sans:s($e,e,cs),mono:s(ye,n,ds)};return t.dataset.font=a.sans,t.dataset.mono=a.mono,a}const us=[{key:"asking",name:"Needs you",color:"--lamp",plate:"--lamp-wash"},{key:"working",name:"Working",color:"--work",plate:"--work-plate"},{key:"delegating",name:"Waiting on agents",color:"--wait",plate:"--wait-plate"},{key:"done",name:"Done",color:"--done",plate:"--done-plate"},{key:"error",name:"Error",color:"--err",plate:"--err-plate"},{key:"idle",name:"Idle",color:"--idle",plate:"--idle-plate"}],Ja=us.map(t=>t.key),Yt=["asking","error","done","working","delegating","idle"],ui=new Set(["asking","working","delegating"]),vt=t=>us.find(e=>e.key===t)||us.at(-1),Ns={asking:'<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><g class="blink"><path d="M8 .9 15.100 8 8 15.100.9 8Z" fill="var(--sign)" stroke="var(--sign)" stroke-width="1"/><path d="M6.300 6.300a1.750 1.750 0 1 1 2.700 1.500c-.7.4-1 .8-1 1.400" fill="none" stroke="var(--sign-ink)" stroke-width="1.400" stroke-linecap="round"/><circle cx="8" cy="11.300" r=".85" fill="var(--sign-ink)"/></g></svg>',working:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="5.600" stroke="currentColor" stroke-opacity=".28" stroke-width="2"/><g class="spin"><path d="M8 2.400a5.600 5.600 0 0 1 5.600 5.600" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></g></svg>',delegating:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><g class="spin-slow"><circle cx="8" cy="8" r="5.800" stroke="currentColor" stroke-width="1.800" stroke-dasharray="2.600 2.460"/></g><circle cx="8" cy="8" r="2.100" fill="currentColor"/></svg>',done:'<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="8" cy="8" r="6.600" fill="currentColor"/><path d="M4.900 8.200 7.100 10.400 11.100 5.800" fill="none" stroke="var(--knock)" stroke-width="1.700" stroke-linecap="round" stroke-linejoin="round"/></svg>',error:'<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 1.500 15.200 14.200H.8Z" fill="currentColor"/><path d="M8 6v4" stroke="var(--knock)" stroke-width="1.600" stroke-linecap="round"/><circle cx="8" cy="12" r=".9" fill="var(--knock)"/></svg>',idle:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="5.200" stroke="currentColor" stroke-width="1.600"/></svg>',pending:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="4.600" stroke="currentColor" stroke-width="1.500"/></svg>'},at=(t,e="")=>{const n=Ja.includes(t)||t==="pending"?t:"idle";return`<span class="lamp${e?` ${e}`:""}" data-st="${n}">${Ns[n]}</span>`},pi=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10.5 -223.3 569 317.3" role="img" aria-label="Threadgauge">
|
|
2
|
+
<defs>
|
|
3
|
+
<linearGradient id="logo-shell" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffffff"/><stop offset="1" stop-color="#d9dfe8"/></linearGradient>
|
|
4
|
+
<radialGradient id="logo-face" cx="-9.7" cy="-17.3" r="55" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2f4466"/><stop offset="0.6" stop-color="#141e33"/><stop offset="1" stop-color="#0b1120"/></radialGradient>
|
|
5
|
+
<linearGradient id="logo-arc" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#d27d60"/><stop offset="1" stop-color="#b1583a"/></linearGradient>
|
|
6
|
+
<filter id="logo-glow" x="-1" y="-1" width="3" height="3"><feGaussianBlur stdDeviation="3.2"/></filter>
|
|
7
|
+
</defs>
|
|
8
|
+
<g transform="translate(282 -118.6) scale(1.6427)">
|
|
9
|
+
<path d="M12,28 C-26,46 -70,54 -90,36 C-110,18 -98,-10 -81,-2 C-64,6 -74,34 -100,46 C-113,52 -126,52 -137,48" fill="none" stroke="#c96442" stroke-width="4.2" stroke-linecap="round"/>
|
|
10
|
+
<circle cx="-150" cy="43" r="3.8" fill="#c96442" opacity="0.8"/>
|
|
11
|
+
<circle cx="-162" cy="38" r="3" fill="#c96442" opacity="0.55"/>
|
|
12
|
+
<circle cx="-173" cy="34" r="2.3" fill="#c96442" opacity="0.3"/>
|
|
13
|
+
<circle r="50" fill="url(#logo-shell)" stroke="#121319" stroke-width="3" paint-order="stroke"/>
|
|
14
|
+
<circle r="44.5" fill="#c3cbd8" stroke="#121319" stroke-width="2.4"/>
|
|
15
|
+
<circle r="42.5" fill="url(#logo-face)"/>
|
|
16
|
+
<path d="M-34.3,-12.48 A36.5,36.5 0 0 1 -15.43,-33.08" fill="none" stroke="#fff" stroke-opacity="0.28" stroke-width="4.4" stroke-linecap="round"/>
|
|
17
|
+
<path d="M-21.21,21.21 A30,30 0 1 1 21.21,21.21" fill="none" stroke="#2f4466" stroke-width="8" stroke-linecap="round"/>
|
|
18
|
+
<path d="M-21.21,21.21 A30,30 0 0 1 21.21,-21.21" fill="none" stroke="url(#logo-arc)" stroke-width="8" stroke-linecap="round"/>
|
|
19
|
+
<path d="M0,0 L16.26,-16.26" stroke="#7fcfff" stroke-width="5.5" stroke-linecap="round" filter="url(#logo-glow)" opacity="0.9"/>
|
|
20
|
+
<path d="M0,0 L16.26,-16.26" stroke="#eef8ff" stroke-width="5.5" stroke-linecap="round"/>
|
|
21
|
+
<circle r="7" fill="#e8ecf2" stroke="#121319" stroke-width="2.4" paint-order="stroke"/>
|
|
22
|
+
</g>
|
|
23
|
+
<g fill="none" stroke="currentColor" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"><path d="M9,4 V46 A14,14 0 0 0 23,60 M0,20 H24"/><path transform="translate(37 0)" d="M0,0 V60 M0,39 A19,19 0 0 1 38,39 V60"/><path transform="translate(90 0)" d="M0,20 V60 M0,42 A22,22 0 0 1 22,20 H26"/><path transform="translate(127 0)" d="M1,40 H40 A20,20 0 1 0 34.14,54.14"/><path transform="translate(182 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V60"/><path transform="translate(237 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,0 V60"/><path transform="translate(292 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V62 A20,20 0 0 1 2.68,72"/><path transform="translate(347 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V60"/><path transform="translate(402 0)" d="M0,20 V41 A19,19 0 0 0 38,41 M38,20 V60"/><path transform="translate(453 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V62 A20,20 0 0 1 2.68,72"/><path transform="translate(508 0)" d="M1,40 H40 A20,20 0 1 0 34.14,54.14"/></g>
|
|
24
|
+
</svg>
|
|
25
|
+
`,hi=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="-140 -54 194 108" aria-hidden="true">
|
|
26
|
+
<defs>
|
|
27
|
+
<linearGradient id="mark-shell" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ffffff"/><stop offset="1" stop-color="#d9dfe8"/></linearGradient>
|
|
28
|
+
<radialGradient id="mark-face" cx="-9.7" cy="-17.3" r="55" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2f4466"/><stop offset="0.6" stop-color="#141e33"/><stop offset="1" stop-color="#0b1120"/></radialGradient>
|
|
29
|
+
<linearGradient id="mark-arc" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#d27d60"/><stop offset="1" stop-color="#b1583a"/></linearGradient>
|
|
30
|
+
<filter id="mark-glow" x="-1" y="-1" width="3" height="3"><feGaussianBlur stdDeviation="3.2"/></filter>
|
|
31
|
+
</defs>
|
|
32
|
+
<path d="M12,28 C-26,46 -70,54 -90,36 C-110,18 -98,-10 -81,-2 C-64,6 -74,34 -100,46" fill="none" stroke="#c96442" stroke-width="5.5" stroke-linecap="round"/>
|
|
33
|
+
<circle cx="-112.3" cy="49.3" r="4.6" fill="#c96442" opacity="0.8"/>
|
|
34
|
+
<circle cx="-123.8" cy="46.8" r="3.7" fill="#c96442" opacity="0.55"/>
|
|
35
|
+
<circle cx="-134.3" cy="43.8" r="2.9" fill="#c96442" opacity="0.3"/>
|
|
36
|
+
<circle r="50" fill="url(#mark-shell)" stroke="#121319" stroke-width="3" paint-order="stroke"/>
|
|
37
|
+
<circle r="44.5" fill="#c3cbd8" stroke="#121319" stroke-width="2.4"/>
|
|
38
|
+
<circle r="42.5" fill="url(#mark-face)"/>
|
|
39
|
+
<path d="M-34.3,-12.48 A36.5,36.5 0 0 1 -15.43,-33.08" fill="none" stroke="#fff" stroke-opacity="0.28" stroke-width="4.4" stroke-linecap="round"/>
|
|
40
|
+
<path d="M-21.21,21.21 A30,30 0 1 1 21.21,21.21" fill="none" stroke="#2f4466" stroke-width="8" stroke-linecap="round"/>
|
|
41
|
+
<path d="M-21.21,21.21 A30,30 0 0 1 21.21,-21.21" fill="none" stroke="url(#mark-arc)" stroke-width="8" stroke-linecap="round"/>
|
|
42
|
+
<path d="M0,0 L16.26,-16.26" stroke="#7fcfff" stroke-width="5.5" stroke-linecap="round" filter="url(#mark-glow)" opacity="0.9"/>
|
|
43
|
+
<path d="M0,0 L16.26,-16.26" stroke="#eef8ff" stroke-width="5.5" stroke-linecap="round"/>
|
|
44
|
+
<circle r="7" fill="#e8ecf2" stroke="#121319" stroke-width="2.4" paint-order="stroke"/>
|
|
45
|
+
</svg>
|
|
46
|
+
`,fi=`<svg xmlns="http://www.w3.org/2000/svg" class="wordmark" viewBox="-4.5 -10 557 96.5" aria-hidden="true">
|
|
47
|
+
<g fill="none" stroke="currentColor" stroke-width="9" stroke-linecap="round" stroke-linejoin="round"><path d="M9,4 V46 A14,14 0 0 0 23,60 M0,20 H24"/><path transform="translate(37 0)" d="M0,0 V60 M0,39 A19,19 0 0 1 38,39 V60"/><path transform="translate(90 0)" d="M0,20 V60 M0,42 A22,22 0 0 1 22,20 H26"/><path transform="translate(127 0)" d="M1,40 H40 A20,20 0 1 0 34.14,54.14"/><path transform="translate(182 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V60"/><path transform="translate(237 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,0 V60"/><path transform="translate(292 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V62 A20,20 0 0 1 2.68,72"/><path transform="translate(347 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V60"/><path transform="translate(402 0)" d="M0,20 V41 A19,19 0 0 0 38,41 M38,20 V60"/><path transform="translate(453 0)" d="M40,40 A20,20 0 1 0 0,40 A20,20 0 1 0 40,40 M40,20 V62 A20,20 0 0 1 2.68,72"/><path transform="translate(508 0)" d="M1,40 H40 A20,20 0 1 0 34.14,54.14"/></g>
|
|
48
|
+
</svg>
|
|
49
|
+
`;async function mi(){try{const t=await fetch("/api/entitlements",{cache:"no-store"});return t.ok?await t.json():null}catch{return null}}async function gi(t){try{const e=await fetch("/api/license",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:t})});return await e.json().catch(()=>null)||{ok:!1,error:`Threadgauge answered ${e.status}`}}catch(e){return{ok:!1,error:`Couldn't reach Threadgauge: ${e.message}`}}}async function $i(t){const e=await fetch(`/api/sessions/${encodeURIComponent(t)}`,{cache:"no-store"});if(e.status===404)return null;if(!e.ok)throw new Error(`Threadgauge answered ${e.status}`);return e.json()}async function Za(t){const e=await fetch(t,{cache:"no-store"});if(e.status===404)return null;if(!e.ok)throw new Error(`Threadgauge answered ${e.status}`);return e.json()}function yi(t,e,n=null){const s=new URLSearchParams({path:e});return n&&s.set("agent",n),Za(`/api/sessions/${encodeURIComponent(t)}/hunks?${s}`)}function wi(t,e){return Za(`/api/sessions/${encodeURIComponent(t)}/subagents/${encodeURIComponent(e)}`)}async function bi(){try{const t=await fetch("/api/history",{cache:"no-store"});return t.ok?(await t.json()).sessions||[]:null}catch{return null}}async function vi(){try{const t=await fetch("/api/threadnauts",{cache:"no-store"});return t.ok&&(await t.json()).url||null}catch{return null}}async function ki(t){try{const e=await fetch("/api/open-path",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)});return await e.json().catch(()=>null)||{ok:!1,error:`Threadgauge answered ${e.status}`}}catch(e){return{ok:!1,error:`Couldn't reach Threadgauge: ${e.message}`}}}async function xi(t,e="app"){const n=await fetch("/api/open",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({id:t,via:e})});return await n.json().catch(()=>null)||{ok:!1,error:`Threadgauge answered ${n.status}`}}function Mi({onChange:t,onConnection:e}){const n=new Map;let s=[];const a=new EventSource("/api/stream");return e("connecting"),a.addEventListener("open",()=>e("live")),a.addEventListener("error",()=>e(a.readyState===EventSource.CLOSED?"offline":"connecting")),a.addEventListener("snapshot",o=>{const r=JSON.parse(o.data);n.clear();for(const i of r.sessions)n.set(i.id,i);s=r.harnesses,t({sessions:n,harnesses:s})}),a.addEventListener("update",o=>{const r=JSON.parse(o.data);for(const i of r.upserts)n.set(i.id,i);for(const i of r.removed)n.delete(i);r.harnesses&&(s=r.harnesses),t({sessions:n,harnesses:s})}),()=>a.close()}function j(t,e,n){const s=document.createElement(t);return e&&(s.className=e),n!=null&&(s.textContent=n),s}const Ai=typeof matchMedia=="function"?matchMedia("(prefers-reduced-motion: reduce)"):null;function Si(t,e="flash"){if(Ai?.matches||!t.isConnected)return;t.classList.remove(e),t.getBoundingClientRect(),t.classList.add(e);const n=s=>{s.target!==t||s.pseudoElement||(t.classList.remove(e),t.removeEventListener("animationend",n))};t.addEventListener("animationend",n)}function ot(t,e,n=!1){const s=String(e??"");return t.textContent===s?!1:(t.textContent=s,n&&Si(t),!0)}function Xt(t,e){t.hidden!==e&&(t.hidden=e)}const Ti=new Set(["hermes"]),Hs=t=>!Ti.has(t),sa=t=>new Date(t*1e3).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"});class Ci{constructor({activate:e}){this.activate=e,this.el=j("dialog","upgrade license"),this.el.setAttribute("aria-labelledby","license-title");const n=j("div","upgrade-sheet");this.title=j("h2","upgrade-title"),this.title.id="license-title",this.text=j("p","upgrade-text"),this.note=j("p","license-note"),this.form=j("form","license-form"),this.input=j("input","license-input"),this.input.type="text",this.input.autocomplete="off",this.input.spellcheck=!1,this.input.placeholder="THREADCRUMBS-…",this.input.setAttribute("aria-label","License key"),this.submit=j("button","btn primary","Activate"),this.submit.type="submit",this.form.append(this.input,this.submit),this.form.addEventListener("submit",a=>{a.preventDefault(),this.send()}),this.message=j("p","license-message"),this.message.setAttribute("role","status"),this.other=j("button","text-button","Use a different key"),this.other.type="button",this.other.addEventListener("click",()=>{Xt(this.other,!0),Xt(this.form,!1),this.input.focus()});const s=j("div","upgrade-actions");this.close=j("button","btn","Not now"),this.close.type="button",this.close.addEventListener("click",()=>this.el.close()),s.append(this.close),n.append(j("p","kicker","Threadgauge Pro"),this.title,this.text,this.note,this.other,this.form,this.message,s),this.el.append(n),this.el.addEventListener("click",a=>{a.target===this.el&&this.el.close()}),this.onActivated=()=>{}}show(e,{previewFree:n=!1,onActivated:s=()=>{}}={}){this.onActivated=s;const a=e?.license,o=!!e?.pro&&!n,r=a?.paidThrough,i=!!e?.activation;o&&r?(ot(this.title,"Threadgauge Pro is on"),ot(this.text,`Paid through ${sa(r)}. The license renews itself about once a week while this computer is online.`)):r?(ot(this.title,"Threadgauge Pro has ended"),ot(this.text,`It was paid through ${sa(r)}. Pro features released before then stay yours. Enter a key to turn the rest back on.`)):(ot(this.title,"Enter your license key"),ot(this.text,"Paste the Threadcrumbs license key from your Polar receipt. One key covers every Threadcrumbs app your plan includes."));const c=[];o&&!r&&c.push("This is a development build, so every Pro feature is open."),i||c.push("This copy of Threadgauge can't activate a license yet."),ot(this.note,c.join(" ")),Xt(this.note,c.length===0),Xt(this.form,!i||o&&!!r),Xt(this.other,!i||!(o&&r)),ot(this.close,o?"Done":"Not now"),this.input.value="",this.showMessage(""),this.setBusy(!1),this.el.open||this.el.showModal(),this.form.hidden?this.close.focus({preventScroll:!0}):this.input.focus({preventScroll:!0})}showMessage(e,n="error"){ot(this.message,e),this.message.dataset.kind=n,Xt(this.message,!e)}setBusy(e){this.submit.disabled=e,this.input.disabled=e,this.submit.dataset.busy=String(e),ot(this.submit,e?"Activating…":"Activate")}async send(){const e=this.input.value.trim();if(!e){this.showMessage("Paste a license key first."),this.input.focus();return}this.setBusy(!0),this.showMessage("");const n=await this.activate(e);if(this.setBusy(!1),!n.ok){this.showMessage(n.error||"That key didn't work."),this.input.focus();return}if(this.onActivated(n.entitlements),n.note){this.showMessage(n.note,"note");return}this.el.close()}}const Li=/^https:\/\//i;function Ei(t){const e=t?.missing;if(!e?.name)return null;const n=[e,...Array.isArray(e.also)?e.also:[]];return{title:`${e.name} isn't installed`,text:"Install it, open it once, then click Open again.",downloads:n.filter(s=>s?.name&&Li.test(String(s.download||""))).map(s=>({label:`Get ${s.name}`,href:s.download})),terminal:t.terminal===!0}}class Oi{constructor(){this.el=j("dialog","upgrade missing-app"),this.el.setAttribute("aria-labelledby","missing-app-title");const e=j("div","upgrade-sheet");this.kicker=j("p","kicker"),this.title=j("h2","upgrade-title"),this.title.id="missing-app-title",this.text=j("p","upgrade-text"),this.actions=j("div","upgrade-actions"),e.append(this.kicker,this.title,this.text,this.actions),this.el.append(e),this.el.addEventListener("click",n=>{n.target===this.el&&this.el.close()}),this.el.addEventListener("close",()=>{this.returnTo?.isConnected&&this.returnTo.focus({preventScroll:!0}),this.returnTo=null})}show(e,{harnessName:n="",returnTo:s=null,onTerminal:a=null}={}){const o=Ei(e);if(!o)return!1;ot(this.kicker,n?`Open in ${n}`:"Open"),ot(this.title,o.title),ot(this.text,o.text);const r=j("button","btn","Not now");r.type="button",r.addEventListener("click",()=>this.el.close());const i=[r];if(o.terminal&&a){const d=j("button","btn","Open in terminal instead");d.type="button",d.addEventListener("click",()=>{this.returnTo=null,this.el.close(),a()}),i.push(d)}const c=o.downloads.map((d,p)=>{const h=j("a",p===0?"btn primary":"btn",d.label);return h.href=d.href,h.target="_blank",h.rel="noopener",h.addEventListener("click",()=>this.el.close()),h});return this.actions.replaceChildren(...i,...c.reverse()),this.returnTo=s,this.el.open||this.el.showModal(),(c.at(-1)||r).focus({preventScroll:!0}),!0}}const Qa=t=>String(t||"").trim().replace(/^["']|["']$/g,""),he=t=>Qa(t).toLowerCase(),Ni=t=>String(t||"U+0-10FFFF").toUpperCase().replace(/\s+/g,"").replace(/U\+0*([0-9A-F?]+)/g,"U+$1").replace(/-0*([0-9A-F]+)/g,"-$1"),Hi=t=>String(t||"normal").trim().replace(/\bnormal\b/,"400").replace(/\bbold\b/,"700").replace(/\s+/g," "),_n=({family:t,weight:e,style:n,unicodeRange:s})=>[he(t),Hi(e),String(n||"normal").trim(),Ni(s)].join("|");function Bi(t,e){const n=/url\(\s*(["']?)([^"')]+)\1\s*\)/.exec(String(t||""));if(!n)return null;try{return new URL(n[2],e).href}catch{return null}}function Ri(t){const e=t instanceof Uint8Array?t:new Uint8Array(t);let n="";const s=32768;for(let a=0;a<e.length;a+=s)n+=String.fromCharCode(...e.subarray(a,a+s));return btoa(n)}function _i({family:t,weight:e,style:n,unicodeRange:s,display:a},o,r="woff2"){return`@font-face{${[`font-family:"${Qa(t).replace(/"/g,"")}"`,`font-style:${n||"normal"}`,`font-weight:${e||"normal"}`,a?`font-display:${a}`:"",s?`unicode-range:${s}`:"",`src:url(${o}) format('${r}')`].filter(Boolean).join(";")}}`}function Ii(t,e){const n=new Set(e.map(_n)),s=new Set(e.map(o=>he(o.family))),a=new Set(t.filter(o=>n.has(_n(o))).map(o=>he(o.family)));return t.filter(o=>n.has(_n(o))||s.has(he(o.family))&&!a.has(he(o.family)))}const we="http://www.w3.org/2000/svg",In="http://www.w3.org/1999/xhtml",ji=new Set(["SCRIPT","STYLE","LINK","META","IFRAME","TEMPLATE","NOSCRIPT"]),Pi=/^(--|animation|transition)/,Fi=["::before","::after"];function Di(){const t=new Set(["display","position","width","height","content"]),e=n=>{for(const s of n){if(s.style)for(let a=0;a<s.style.length;a++)t.add(s.style[a]);s.cssRules&&e(s.cssRules)}};for(const n of document.styleSheets)try{e(n.cssRules)}catch{}for(const n of document.querySelectorAll("[style]"))for(let s=0;s<n.style.length;s++)t.add(n.style[s]);return[...t].filter(n=>!Pi.test(n))}function ps(t,e){const n=new Array(e.length);for(let s=0;s<e.length;s++)n[s]=t.getPropertyValue(e[s]);return n}function Wi(t){const e=document.createElement("iframe");e.setAttribute("aria-hidden","true"),e.tabIndex=-1,Object.assign(e.style,{position:"fixed",width:"0",height:"0",border:"0",visibility:"hidden"}),document.body.append(e);const n=e.contentDocument,s=n.createElementNS(we,"svg");n.body.append(s);const a=new Map;return{valuesOf(o){const r=o.namespaceURI===we,i=`${r?"svg:":""}${o.localName}`;if(!a.has(i)){const c=r?n.createElementNS(we,o.localName):n.createElement(o.localName);(r&&o.localName!=="svg"?s:n.body).append(c),a.set(i,ps(e.contentWindow.getComputedStyle(c),t))}return a.get(i)},remove:()=>e.remove()}}const jn=new Map;function Ui(){const t=[],e=(n,s)=>{for(const a of n){if(a.cssRules&&e(a.cssRules,s),a.type!==CSSRule.FONT_FACE_RULE)continue;const o=a.style,r=Bi(o.getPropertyValue("src"),s);r&&t.push({family:o.getPropertyValue("font-family"),weight:o.getPropertyValue("font-weight")||"normal",style:o.getPropertyValue("font-style")||"normal",unicodeRange:o.getPropertyValue("unicode-range"),display:o.getPropertyValue("font-display"),url:r})}};for(const n of document.styleSheets)try{e(n.cssRules,n.href||location.href)}catch{}return t}async function qi(t){return jn.has(t)||jn.set(t,fetch(t).then(e=>e.ok?e.arrayBuffer():null).then(e=>e?`data:font/woff2;base64,${Ri(e)}`:null).catch(()=>null)),jn.get(t)}async function Vi(){if(!document.fonts)return"";await document.fonts.ready;const t=[...document.fonts].filter(s=>s.status==="loaded").map(s=>({family:s.family,weight:s.weight,style:s.style,unicodeRange:s.unicodeRange}));if(!t.length)return"";const e=Ii(Ui(),t);return(await Promise.all(e.map(async s=>{const a=await qi(s.url);return a?_i(s,a):""}))).filter(Boolean).join(`
|
|
50
|
+
`)}function Gi(t,e){if(/^(pre|nowrap)/.test(e.whiteSpace)||e.whiteSpace==="pre")return!1;const n=document.createRange();let s=0;for(const a of t.childNodes)if(!(a.nodeType!==Node.TEXT_NODE||!a.nodeValue.trim())){if(n.selectNodeContents(a),n.getClientRects().length!==1)return!1;s++}return s>0}function Ki(){const t=window.scrollX,e=window.scrollY,n=new Map,s=new Map;for(const a of document.body.querySelectorAll("*")){const o=getComputedStyle(a);if(o.display!=="none"){if(o.position==="fixed"){const r=a.getBoundingClientRect();n.set(a,{fixed:!0,top:r.top+e,left:r.left+t})}else if(o.position==="sticky"){const r=a.getBoundingClientRect(),i=a.style.position;a.style.position="static";const c=a.getBoundingClientRect();a.style.position=i,n.set(a,{fixed:!1,top:r.top-c.top,left:r.left-c.left})}(a.scrollTop||a.scrollLeft)&&o.overflow!=="visible"&&s.set(a,{x:a.scrollLeft,y:a.scrollTop})}}return{scrollX:t,scrollY:e,pinned:n,scrolled:s}}function Yi(t,e,n,s){const a=`${location.origin}${location.pathname}${location.search}`,o=[],r=[];let i=0;const c=(p,h)=>`${p}:${h.includes(a)?h.split(a).join(""):h};`;function u(p,h,f){if(p.nodeType===Node.TEXT_NODE)return document.createTextNode(p.nodeValue);if(p.nodeType!==Node.ELEMENT_NODE||ji.has(p.tagName))return null;const m=getComputedStyle(p);if(m.display==="none")return null;const y=p.cloneNode(!1),$=e.pinned.get(p),x=ps(m,n),E=s.valuesOf(p),B=$?.fixed?null:h,N=p.localName==="a"&&p.hasAttribute("href");let C="";for(let L=0;L<n.length;L++)x[L]===E[L]&&(!B||x[L]===B[L])&&!(N&&n[L].startsWith("text-decoration"))||(C+=c(n[L],x[L]));(/^(auto|scroll)/.test(m.overflowX)||/^(auto|scroll)/.test(m.overflowY))&&(C+="overflow:hidden;"),Gi(p,m)&&(C+="white-space:nowrap;"),f&&(C+=`translate:${-f.x}px ${-f.y}px;`),$&&$.fixed?C+=`position:absolute;top:${$.top}px;left:${$.left}px;right:auto;bottom:auto;margin:0;`:$&&(C+=`position:relative;top:${$.top}px;left:${$.left}px;right:auto;bottom:auto;`),y.style.cssText=`${C}animation:none;transition:none;`;for(const L of Fi){const X=getComputedStyle(p,L),Et=X.getPropertyValue("content");if(!Et||Et==="none"||Et==="normal")continue;const Ft=`shot-${++i}`;y.classList.add(Ft);const Ot=ps(X,n);let Fe="";for(let Nt=0;Nt<n.length;Nt++)Ot[Nt]&&(Fe+=c(n[Nt],Ot[Nt]));o.push(`.${Ft}${L}{${Fe}animation:none;transition:none;}`)}if(p instanceof HTMLSelectElement){for(const L of p.options){const X=L.cloneNode(!0);L.selected&&X.setAttribute("selected",""),y.append(X)}return y}const q=e.scrolled.get(p)||null;for(const L of p.childNodes){const X=u(L,x,L.nodeType===Node.ELEMENT_NODE?q:null);X&&(L.nodeType===Node.ELEMENT_NODE&&e.pinned.get(L)?.fixed?r.push(X):y.append(X))}return y}return{body:u(t,null,null),lifted:r,rules:o}}async function zi(){const t=window.innerWidth,e=window.innerHeight,n=window.devicePixelRatio||1,s=await Vi(),a=Di(),o=Wi(a);let r;try{const d=Ki(),{body:p,lifted:h,rules:f}=Yi(document.body,d,a,o),m=document.createElementNS(In,"div");m.style.cssText=`position:absolute;left:${-d.scrollX}px;top:${-d.scrollY}px;width:${document.documentElement.scrollWidth}px;margin:0;`;const y=document.createElementNS(In,"style");y.textContent=[s,...f].filter(Boolean).join(`
|
|
51
|
+
`),p.style.margin="0",m.append(y,p,...h);const $=document.createElementNS(In,"div");$.style.cssText=`position:relative;width:${t}px;height:${e}px;overflow:hidden;margin:0;`,$.append(m);const x=document.createElementNS(we,"svg");x.setAttribute("width",String(Math.round(t*n))),x.setAttribute("height",String(Math.round(e*n))),x.setAttribute("viewBox",`0 0 ${t} ${e}`);const E=document.createElementNS(we,"foreignObject");E.setAttribute("width",String(t)),E.setAttribute("height",String(e)),E.append($),x.append(E),r=new XMLSerializer().serializeToString(x)}finally{o.remove()}const i=new Image;i.src=`data:image/svg+xml;charset=utf-8,${encodeURIComponent(r)}`,await i.decode();const c=document.createElement("canvas");c.width=Math.round(t*n),c.height=Math.round(e*n);const u=c.getContext("2d");return u.fillStyle=getComputedStyle(document.body).backgroundColor,u.fillRect(0,0,c.width,c.height),u.drawImage(i,0,0,c.width,c.height),new Promise((d,p)=>c.toBlob(h=>h?d(h):p(new Error("The browser could not encode the image")),"image/png"))}function Xi(t,e){const n=URL.createObjectURL(t),s=document.createElement("a");s.href=n,s.download=e,s.click(),setTimeout(()=>URL.revokeObjectURL(n),3e4)}const Ji=new Set(["asking","working","delegating"]),Zi=[{key:"live",label:"Live"},{key:"repo",label:"Repo"},{key:"status",label:"State"}],aa=[{key:"status",label:"Needs you first"},{key:"recent",label:"Most recent"},{key:"context",label:"Context used"},{key:"title",label:"Title"}],ze=t=>!!t.live||Ji.has(t.status),Pn=["asking","done"];function Qi(t){return t.filter(e=>Pn.includes(e.status)).sort((e,n)=>Pn.indexOf(e.status)-Pn.indexOf(n.status)||n.lastActivityAt-e.lastActivityAt||e.id.localeCompare(n.id))}function Xe(t){const e=String(t.projectPath||t.project||"").replace(/\\/g,"/").replace(/\/+$/,"");return/^[a-z]:\//i.test(e)?e.toLowerCase():e}const oa=(t,e)=>t.localeCompare(e,void 0,{sensitivity:"base"});function to(t){const e=new Map;for(const a of t){const o=Xe(a),r=e.get(o)||{key:o,name:a.project||"unknown",path:a.projectPath||"",org:null,count:0};r.org||=a.org||null,r.count++,e.set(o,r)}const n=[...e.values()],s=new Map;for(const a of n)s.set(a.name,(s.get(a.name)||0)+1);for(const a of n){const o=a.key.split("/").slice(-2,-1)[0];a.label=s.get(a.name)>1&&o?`${o}/${a.name}`:a.name}return n.sort((a,o)=>(a.org?0:1)-(o.org?0:1)||oa(a.org||"",o.org||"")||oa(a.label,o.label))}const tl=[["B",1e9],["M",1e6],["K",1e3]];function k(t){if(!Number.isFinite(t))return"—";const e=Math.abs(t);for(const[n,s]of tl){if(e<s*.9995)continue;const a=t/s;return`${Math.abs(a)>=99.95?String(Math.round(a)):a.toFixed(1).replace(/\.0$/,"")}${n}`}return String(Math.round(t))}function Bs(t){return t==null||!Number.isFinite(t)?"—":t>0&&t<.01?"<$0.01":`$${t.toLocaleString("en-US",{minimumFractionDigits:2,maximumFractionDigits:2})}`}function At(t){const e=Math.max(0,Math.floor(t/1e3));if(e<60)return`${e}s`;const n=Math.floor(e/60);if(n<60)return`${n}m ${e%60}s`;const s=Math.floor(n/60);return s<24?`${s}h ${n%60}m`:`${Math.floor(s/24)}d ${s%24}h`}function nt(t){if(!Number.isFinite(t)||t<0)return"—";const e=Math.round(t/100);return e<10?`${(e/10).toFixed(1)}s`:At(Math.max(t,1e3))}function Bt(t){return t?new Date(t).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit",second:"2-digit"}):"—"}function st(t){return t?new Date(t).toLocaleTimeString("en-US",{hour:"numeric",minute:"2-digit"}):"—"}function hs(t){return t?new Date(t).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):"—"}function eo(t){const e=Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\"));return e<0?{dir:"",name:t}:{dir:t.slice(0,e+1),name:t.slice(e+1)}}function no(t,e){if(!e)return t||"";if(!t||/^([a-zA-Z]:[\\/]|[\\/])/.test(e))return e;const n=t.includes("\\")?"\\":"/",s=t.replace(/[\\/]+$/,"").split(/[\\/]/);for(const a of e.split(/[\\/]/))a===".."?s.length>1&&s.pop():a&&a!=="."&&s.push(a);return s.join(n)}function el(t){if(!Number.isFinite(t)||t<=0)return 1;const e=10**Math.floor(Math.log10(t));for(const n of[1,2,2.5,5,10])if(n*e>=t)return n*e;return 10*e}function $t(t){if(t<45*1e3)return"just now";const e=Math.round(t/6e4);if(e<60)return`${e}m ago`;const n=Math.round(e/60);return n<24?`${n}h ago`:`${Math.round(n/24)}d ago`}function Rs(t,e){return e?Math.min(100,Math.max(0,t/e*100)):null}function ht(t){const e=/^(?:[\w.-]+\/)?claude-([a-z]+)-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?(\[.*\])?$/.exec(t||"");if(!e)return t||"";const[,n,s,a]=e;return`${n[0].toUpperCase()}${n.slice(1)} ${a?`${s}.${a}`:s}`}function P(t){const e=/^mcp__(.+?)__(.+)$/.exec(t||"");return e?`${e[2]} (${e[1]})`:t||""}const nl=7;function sl(t,e=n=>n){const n=t.ask,s=n?.type==="question"?(n.questions||[]).flatMap(a=>[a.header,a.text]).join(" "):n?.type==="approval"?`${n.tool||""} ${n.target||""}`:n?.type==="error"?n.text:"";return[t.title,t.org,t.project,t.gitBranch,t.worktree,ht(t.model),t.model,e(t.harness),s].filter(Boolean).join(" ").toLowerCase()}const so=t=>String(t||"").trim().toLowerCase().split(/\s+/).filter(Boolean);function al(t,e,n){const s=so(e);if(!s.length)return!0;const a=sl(t,n);return s.every(o=>a.includes(o))}const ol=Object.freeze([{act:"next-waiting",label:"Next thread waiting on you",key:"N"},{act:"table",label:"All threads table",wide:!0},{act:"settings",label:"Settings",key:"?"},{act:"shot",label:"Screenshot",key:"P"}]);function rl(t,{stacked:e=!1}={}){const n=so(t);return ol.filter(s=>!(e&&s.wide)).filter(s=>n.every(a=>s.label.toLowerCase().includes(a))).slice(0,nl)}const Me=Object.fromEntries(Yt.map((t,e)=>[t,e])),fs=t=>Me[t.status]??Yt.length,ra=t=>t.context?.limit?t.context.used/t.context.limit:-1,ao=(t,e)=>t.localeCompare(e,void 0,{sensitivity:"base"}),Fn=t=>["asking","error","done"].includes(t.status)?0:1,ia={status:(t,e)=>fs(t)-fs(e)||e.lastActivityAt-t.lastActivityAt,recent:(t,e)=>e.lastActivityAt-t.lastActivityAt,context:(t,e)=>ra(e)-ra(t)||e.lastActivityAt-t.lastActivityAt,title:(t,e)=>ao(t.title,e.title)||e.lastActivityAt-t.lastActivityAt,wait:(t,e)=>Fn(t)-Fn(e)||(Fn(t)===0?t.lastActivityAt-e.lastActivityAt:e.lastActivityAt-t.lastActivityAt)},_s=t=>["asking","error","done"].includes(t.status)?"you":["working","delegating"].includes(t.status)?"run":"quiet",la=[["you","Your turn"],["run","Agents' turn"],["quiet","Idle"]],ca=[["live","Live"],["recent","Last 24 hours"],["older","Older"]];function il(t,{group:e="turn",sort:n="status",repo:s="",status:a=null,q:o="",harnessName:r}={}){const i=o?t.filter(h=>al(h,o,r)):t,c=s?i.filter(h=>Xe(h)===s):[...i],u=(a?c.filter(h=>h.status===a):[...c]).sort(ia[n]||ia.status),d=new Map,p=(h,f,m,y)=>{d.has(h)||d.set(h,{key:h,kind:f,...m(),items:[]}),d.get(h).items.push(y)};if(e==="repo"){const h=new Map(to(t).map($=>[$.key,$]));for(const $ of u){const x=Xe($);p(x,"repo",()=>({label:h.get(x)?.label||$.project||"unknown",org:h.get(x)?.org||null,path:$.projectPath||""}),$)}const f=$=>Math.min(...$.items.map(fs)),m=$=>Math.max(...$.items.map(x=>x.lastActivityAt)),y=[...d.values()].sort(($,x)=>($.org?1:0)-(x.org?1:0)||ao($.org||"",x.org||"")||f($)-f(x)||m(x)-m($));return{inRepo:c,visible:u,groups:y}}if(e==="status"){for(const h of u)p(h.status,"status",()=>({label:vt(h.status).name}),h);return{inRepo:c,visible:u,groups:[...d.values()].sort((h,f)=>(Me[h.key]??99)-(Me[f.key]??99))}}if(e==="live"){for(const h of u){const f=ze(h)?"live":h.older?"older":"recent";p(f,"live",()=>({label:ca.find(([m])=>m===f)[1]}),h)}return{inRepo:c,visible:u,groups:ca.map(([h])=>d.get(h)).filter(Boolean)}}for(const h of u){const f=_s(h);p(f,"turn",()=>({label:la.find(([m])=>m===f)[1]}),h)}return{inRepo:c,visible:u,groups:la.map(([h])=>d.get(h)).filter(Boolean)}}const mn=(t,e)=>`${t}:${e.key}`,oo=(t,e=null,n=null,s="")=>t.flatMap(a=>(e?.has(mn(s,a))?a.items.filter(o=>o.id===n):a.items).map(o=>o.id));function Is(t,e=""){const n=to(t);e&&!n.some(o=>o.key===e)&&n.push({key:e,label:e.split("/").filter(Boolean).pop()||e,org:null,count:0});const s=new Map,a=[];for(const o of n)o.org?(s.has(o.org)||s.set(o.org,[]),s.get(o.org).push(o)):a.push(o);return{total:t.length,orgs:[...s].map(([o,r])=>({org:o,repos:r})),loose:a}}const ll=/^#thread=(.+)$/;function cl(t){const e=ll.exec(t||"");if(!e)return null;try{return decodeURIComponent(e[1])||null}catch{return null}}const Dn=t=>`#thread=${encodeURIComponent(t)}`;function dl(t,e,n){return e&&!t?"push":e&&t?e===t?null:"replace":t?n?"back":"clear":null}function ul(t,{received:e,olderLoaded:n,listed:s}){return e?t?s(t)?"open":n?"drop":"wait":"start":"wait"}const l=t=>String(t??"").replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e]),ct=(t,e,n)=>`${t} ${t===1?e:n}`;function Ae(t){return t.length<=1?t[0]||"":`${t.slice(0,-1).join(", ")} and ${t.at(-1)}`}const pl={read:["read","notebookread","read_file","read_many_files","view","view_file","view_file_outline","view_code_item","view_image","todoread","cat"],search:["grep","glob","ls","list","list_dir","list_directory","search_file_content","search_files","grep_search","find_by_name","codesearch","file_search","codebase_search"],edit:["edit","multiedit","write","notebookedit","apply_patch","applypatch","patch","create","write_file","replace","str_replace","strreplace","write_to_file","replace_file_content","multi_replace_file_content","search_replace"],delete:["delete","delete_file"],move:["move","move_file","rename","rename_file"],execute:["bash","powershell","shell","exec_command","write_stdin","run_shell_command","run_command","terminal","execute_code","process","bashoutput","killshell","command_status","send_command_input","local_shell"],think:["think","save_memory","memory","report_intent"],fetch:["webfetch","websearch","web_fetch","web_search","google_web_search","web_extract","read_url_content","search_web","fetch"],agent:["agent","task","spawn_agent","wait_agent","send_input","delegate_task","subagent"],plan:["todowrite","todo_write","update_plan","write_todos","todo","todo_list","task_boundary"],communicate:["askuserquestion","ask_user","request_user_input","request_permissions","question","clarify","notify_user"],switch_mode:["enterplanmode","exitplanmode","switch_mode"]};new Map(Object.entries(pl).flatMap(([t,e])=>e.map(n=>[n,t])));function hl(t){return/^mcp__(.+?)__./.exec(String(t||""))?.[1]||null}const Mt=t=>String(t??"").replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e]),ro={key:'<circle cx="8" cy="15.5" r="4.5"/><path d="M11.3 12.2 20 3.5M16.5 7l2.5 2.5M14 9.5l2 2"/>',folder:'<path d="M3 7.4A1.4 1.4 0 0 1 4.4 6h4.2l2 2.5h7A1.4 1.4 0 0 1 19 9.9v7.7a1.4 1.4 0 0 1-1.4 1.4H4.4A1.4 1.4 0 0 1 3 17.6z"/>',org:'<path d="M4.5 20V5.4A1.4 1.4 0 0 1 5.9 4h6.7A1.4 1.4 0 0 1 14 5.4V20"/><path d="M14 9h4.1a1.4 1.4 0 0 1 1.4 1.4V20"/><path d="M3 20h18"/><path d="M7.5 8h3M7.5 11.5h3M7.5 15h3M16.8 13h.01M16.8 16.5h.01"/>',branch:'<circle cx="7" cy="5.5" r="2.2"/><circle cx="7" cy="18.5" r="2.2"/><circle cx="17" cy="7.5" r="2.2"/><path d="M7 7.7v8.6"/><path d="M17 9.7c0 3.4-2.6 4.6-6 5.2-1.9.3-3.3.9-4 1.4"/>',worktree:'<circle cx="6.5" cy="5" r="2.2"/><circle cx="17.5" cy="5" r="2.2"/><circle cx="12" cy="19" r="2.2"/><path d="M6.5 7.2v1.3a3 3 0 0 0 3 3h5a3 3 0 0 0 3-3V7.2"/><path d="M12 11.5v5.3"/>',model:'<path d="M11 3.5l1.8 4.9 4.9 1.8-4.9 1.8L11 16.9l-1.8-4.9-4.9-1.8 4.9-1.8z"/><path d="M18 14.5l.8 2 2 .8-2 .8-.8 2-.8-2-2-.8 2-.8z"/>',"k-read":'<path d="M13.5 3.5H7.4A1.4 1.4 0 0 0 6 4.9v14.2a1.4 1.4 0 0 0 1.4 1.4h9.2a1.4 1.4 0 0 0 1.4-1.4V8z"/><path d="M13.5 3.5V8H18"/><path d="M9 12.5h6M9 16h4"/>',"k-search":'<circle cx="10.5" cy="10.5" r="6"/><path d="M15 15l5 5"/>',"k-edit":'<path d="M15.2 5.3a2 2 0 0 1 2.8 0l.7.7a2 2 0 0 1 0 2.8L8.5 19 4 20l1-4.5z"/><path d="M13.5 7l3.5 3.5"/>',"k-delete":'<path d="M4.5 7h15"/><path d="M9.5 7V5.2a1 1 0 0 1 1-1h3a1 1 0 0 1 1 1V7"/><path d="M6.5 7l.8 11.8a1.5 1.5 0 0 0 1.5 1.4h6.4a1.5 1.5 0 0 0 1.5-1.4L17.5 7"/><path d="M10.2 11v5.5M13.8 11v5.5"/>',"k-move":'<path d="M12 20.5H7.4A1.4 1.4 0 0 1 6 19.1V4.9a1.4 1.4 0 0 1 1.4-1.4h6.1L18 8v3"/><path d="M13.5 3.5V8H18"/><path d="M11.5 16h9M17.5 13l3 3-3 3"/>',"k-execute":'<path d="M5 7l5 5-5 5"/><path d="M12.5 17H19"/>',"k-fetch":'<circle cx="12" cy="12" r="8.5"/><path d="M3.5 12h17"/><path d="M12 3.5c2.3 2.3 3.5 5.2 3.5 8.5s-1.2 6.2-3.5 8.5C9.7 18.2 8.5 15.3 8.5 12S9.7 5.8 12 3.5z"/>',"k-think":'<path d="M9.5 17.5h5M10.5 20.5h3"/><path d="M12 3.5a5.5 5.5 0 0 0-3.3 9.9c.6.5 1 1.2 1 2v.1h4.6v-.1c0-.8.4-1.5 1-2A5.5 5.5 0 0 0 12 3.5z"/>',"k-agent":'<path d="M2.5 12H9M6.5 9.2 9.3 12l-2.8 2.8"/><circle cx="15.5" cy="12" r="5.5" stroke-linecap="butt" stroke-dasharray="3.2 2.56"/><circle cx="15.5" cy="12" r="1.7" fill="currentColor" stroke="none"/>',"k-plan":'<path d="M3.5 7.2 5.8 9.5 10 5M3.5 15.7 5.8 18 10 13.5"/><path d="M13.5 7.5H20.5M13.5 16H20.5"/>',"k-communicate":'<path d="M4 6.4A1.9 1.9 0 0 1 5.9 4.5h12.2A1.9 1.9 0 0 1 20 6.4v8.2a1.9 1.9 0 0 1-1.9 1.9H11.5L7 20v-3.5H5.9A1.9 1.9 0 0 1 4 14.6z"/><path d="M10.1 8.7a1.9 1.9 0 1 1 2.8 1.7c-.6.3-.9.7-.9 1.3"/><path d="M12 14h.01"/>',"k-switch_mode":'<rect x="2.5" y="7" width="19" height="10" rx="5"/><circle cx="16.5" cy="12" r="2.5"/>',"k-other":'<path d="M17.57 4.17A4.8 4.8 0 0 0 11.13 10.47L5.11 16.49a1.7 1.7 0 0 0 2.4 2.4L13.53 12.87A4.8 4.8 0 0 0 19.83 6.43L17.76 8.5 15.5 6.24z"/>',"k-mcp":'<path d="M9 3.5v4M15 3.5v4"/><path d="M6.5 7.5h11V10a5.5 5.5 0 0 1-11 0z"/><path d="M12 15.5v5"/>'};Object.freeze(Object.keys(ro));const Q=(t,e=13)=>`<svg class="ico" width="${e}" height="${e}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${ro[t]||""}</svg>`,fl={minimal:1,low:1,medium:2,high:3,xhigh:4,max:5},ml={minimal:"Minimal",low:"Low",medium:"Medium",high:"High",xhigh:"Extra high",max:"Max"},gn=t=>ml[String(t).toLowerCase()]||t||"";function io(t){if(!t)return"";const e=fl[String(t).toLowerCase()]??0,n=[1,2,3,4,5].map(a=>`<rect x="${a*4-1.5}" y="${(20-a*3.2).toFixed(1)}" width="2.6" height="${(a*3.2).toFixed(1)}" rx="1.1" class="${a<=e?"eb-on":"eb-off"}"/>`).join(""),s=Mt(`${gn(t)} effort`);return`<svg class="ico eff" width="14" height="14" viewBox="0 0 24 24" role="img" aria-label="${s}"><title>${s}</title>${n}</svg>`}const gl=Object.freeze({"claude-code":"CC",codex:"Cx",cursor:"Cu",antigravity:"AG",hermes:"H",opencode:"OC",kilocode:"K","gemini-cli":"Gm","copilot-cli":"Cp"}),$n=(t,e=t)=>gl[t]||String(e||"?")[0].toUpperCase(),Ke=Object.freeze({read:{name:"Read",tip:"Reads a file"},search:{name:"Search",tip:"Searches for text or lists files"},edit:{name:"Edit",tip:"Creates or changes a file"},delete:{name:"Delete",tip:"Deletes files"},move:{name:"Move",tip:"Moves or renames files"},execute:{name:"Run",tip:"Runs a command"},fetch:{name:"Web",tip:"Fetches a page or searches the web"},think:{name:"Think",tip:"Thinks or takes notes, without changing anything"},agent:{name:"Subagent",tip:"Hands work to a subagent"},plan:{name:"Plan",tip:"Updates the plan"},communicate:{name:"Ask",tip:"Asks you something"},switch_mode:{name:"Mode",tip:"Changes the agent's mode"},other:{name:"Other",tip:"A tool that has no kind yet"},mcp:{name:"MCP",tip:"A tool from an MCP server"}}),$l=/bash|shell|command|exec|terminal|powershell/i;function lo(t,e=null){const n=t?.server||hl(t?.name);if(n)return{kind:"mcp",server:n,shell:!1};const s=Ke[t?.kind]?t.kind:"other",a=e?.get(t?.name)??($l.test(t?.name||"")?"execute":null);return{kind:s,server:null,shell:s!=="execute"&&s!=="other"&&a==="execute"}}function yl({kind:t,server:e,shell:n}){if(t==="mcp")return e?`A tool from the ${e} MCP server`:Ke.mcp.tip;const s=(Ke[t]||Ke.other).tip;return n?`${s}, with a shell command`:s}const co=t=>`<span class="tk" data-k="${Mt(t.kind)}" data-tip="${Mt(yl(t))}">${Q(`k-${t.kind}`)}</span>`,wl=t=>new Map((t||[]).map(e=>[e.name,e.kind])),F=(t,e=16)=>`<svg width="${e}" height="${e}" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${t}</svg>`,T={x:F('<path d="M4 4l8 8M12 4l-8 8"/>'),up:F('<path d="M3.5 10 8 5.5 12.5 10"/>'),down:F('<path d="M3.5 6 8 10.5 12.5 6"/>'),open:F('<path d="M6.5 3H3.5A1 1 0 0 0 2.5 4v8.5a1 1 0 0 0 1 1H12a1 1 0 0 0 1-1v-3"/><path d="M9.5 2.5h4v4M13.5 2.5 7.5 8.5"/>',14),lock:F('<rect x="3.5" y="7" width="9" height="6.5" rx="1.3"/><path d="M5.5 7V5a2.5 2.5 0 0 1 5 0v2"/>',14),cam:F('<path d="M2 5.5a1 1 0 0 1 1-1h2l1-1.5h4l1 1.5h2a1 1 0 0 1 1 1V12a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1z"/><circle cx="8" cy="8.5" r="2.3"/>'),panelIn:F('<rect x="2" y="2.5" width="12" height="11" rx="1.5"/><path d="M6 2.5v11M10.5 6 8.5 8l2 2"/>'),listIcon:F('<path d="M5.5 4h8M5.5 8h8M5.5 12h8"/><path d="M2.5 4h.01M2.5 8h.01M2.5 12h.01"/>',20),chev:F('<path d="M6 4l4 4-4 4"/>',12),search:F('<circle cx="7" cy="7" r="4.3"/><path d="M10.3 10.3 13.5 13.5"/>'),copy:F('<rect x="5.5" y="5.5" width="8" height="8" rx="1.5"/><path d="M10.5 3.5v-.5A1 1 0 0 0 9.5 2h-6A1 1 0 0 0 2.5 3v6a1 1 0 0 0 1 1h.5"/>',14),check:F('<path d="M3 8.5l3.2 3.2L13 4.8"/>',14),back:F('<path d="M9.5 3.5 5 8l4.5 4.5"/>'),bubble:F('<path d="M2.5 4.2A1.7 1.7 0 0 1 4.2 2.5h7.6a1.7 1.7 0 0 1 1.7 1.7v5.1a1.7 1.7 0 0 1-1.7 1.7H7l-3.3 2.5V11h.5A1.7 1.7 0 0 1 2.5 9.3z"/>',18),panelOut:F('<rect x="2" y="2.5" width="12" height="11" rx="1.5"/><path d="M10 2.5v11M5.5 6 7.5 8l-2 2"/>'),xs:'<svg class="x-mark" width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>'},bl='<svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>',vl='<svg width="20" height="16" viewBox="0 0 20 16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><circle cx="10" cy="8" r="2.2" fill="currentColor" stroke="none"/><path class="cw cw1" d="M6.9 4.9a4.4 4.4 0 0 0 0 6.2M13.1 4.9a4.4 4.4 0 0 1 0 6.2"/><path class="cw cw2" d="M4.2 2.2a8.2 8.2 0 0 0 0 11.6M15.8 2.2a8.2 8.2 0 0 1 0 11.6"/><path class="cx" d="M3.5 14.5 16.5 1.5"/></svg>',kl=`<svg viewBox="-52 -52 104 104" width="32" height="32" aria-hidden="true"><defs>
|
|
52
|
+
<linearGradient id="lsm-shell" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#555d70"/><stop offset="1" stop-color="#262a35"/></linearGradient>
|
|
53
|
+
<radialGradient id="lsm-face" cx="-9.7" cy="-17.3" r="55" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2f4466"/><stop offset="0.6" stop-color="#141e33"/><stop offset="1" stop-color="#0b1120"/></radialGradient>
|
|
54
|
+
<linearGradient id="lsm-arc" x1="0" y1="-50" x2="0" y2="50" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#e08a6a"/><stop offset="1" stop-color="#c0603f"/></linearGradient>
|
|
55
|
+
<filter id="lsm-glow" x="-1" y="-1" width="3" height="3"><feGaussianBlur stdDeviation="3.2"/></filter></defs>
|
|
56
|
+
<circle r="50" fill="url(#lsm-shell)"/>
|
|
57
|
+
<circle r="49" fill="none" stroke="#8a93a8" stroke-opacity=".45" stroke-width="1.6"/>
|
|
58
|
+
<circle r="44.5" fill="#1a2030" stroke="#0b0d12" stroke-width="2.4"/>
|
|
59
|
+
<circle r="42.5" fill="url(#lsm-face)"/>
|
|
60
|
+
<path d="M-34.3,-12.48 A36.5,36.5 0 0 1 -15.43,-33.08" fill="none" stroke="#fff" stroke-opacity="0.22" stroke-width="4.4" stroke-linecap="round"/>
|
|
61
|
+
<path d="M-21.21,21.21 A30,30 0 1 1 21.21,21.21" fill="none" stroke="#2f4466" stroke-width="8" stroke-linecap="round"/>
|
|
62
|
+
<path d="M-21.21,21.21 A30,30 0 0 1 21.21,-21.21" fill="none" stroke="url(#lsm-arc)" stroke-width="8" stroke-linecap="round"/>
|
|
63
|
+
<path d="M0,0 L16.26,-16.26" stroke="#7fcfff" stroke-width="5.5" stroke-linecap="round" filter="url(#lsm-glow)" opacity="0.9"/>
|
|
64
|
+
<path d="M0,0 L16.26,-16.26" stroke="#eef8ff" stroke-width="5.5" stroke-linecap="round"/>
|
|
65
|
+
<circle r="7" fill="#cfd6e2" stroke="#0b0d12" stroke-width="2.4" paint-order="stroke"/></svg>`,xl={threads:F('<path d="M5.5 4h8M5.5 8h8M5.5 12h8"/><path d="M2.5 4h.01M2.5 8h.01M2.5 12h.01"/>'),look:F('<path d="M2.5 4.5h6M12 4.5h1.5M2.5 11.5H4M7.5 11.5h6"/><circle cx="10.2" cy="4.5" r="1.7"/><circle cx="5.8" cy="11.5" r="1.7"/>'),connection:F('<path d="M1.5 8h3l1.5-4 3 8 1.5-4h4"/>'),threadcrumbs:F('<circle cx="5.5" cy="10.5" r="2.8"/><path d="M7.5 8.5 13 3M11 5l1.5 1.5M9.5 6.5 11 8"/>'),keys:F('<rect x="1.5" y="4" width="13" height="8.5" rx="1.5"/><path d="M4 7h.01M6.5 7h.01M9 7h.01M11.5 7h.01M5 10h6"/>')};function Ml(t,{typing:e=!1,onControl:n=!1,dialog:s=!1,mode:a="side",sel:o=null,thread:r=!1}={}){if(t.key==="Escape")return s||t.defaultPrevented?null:{act:"back"};const i=t.key.length===1?t.key.toLowerCase():t.key;return i==="k"&&(t.ctrlKey||t.metaKey)&&!t.altKey&&!t.defaultPrevented?s?null:{act:"find"}:t.metaKey||t.ctrlKey||t.altKey||t.defaultPrevented||e?null:i==="p"?t.repeat?null:{act:"shot"}:s?null:i==="?"?{act:"settings"}:i==="/"?{act:"find"}:i==="["?!t.repeat&&a==="side"&&o!=="overview"?{act:"list-toggle"}:null:i==="n"?{act:"next-waiting"}:i==="j"||i==="k"?{act:"step",dir:i==="j"?1:-1}:i==="r"?!t.repeat&&r?{act:"conversation"}:null:i==="Enter"&&!t.repeat&&!n&&r?{act:"open"}:null}const Al='input, select, textarea, [contenteditable]:not([contenteditable="false"])',Sl='button, a, input, select, textarea, summary, [role="button"], [contenteditable="true"]',uo=56,Se=196,po=300,da=24,Tl=(t,e,n)=>Math.max(e,Math.min(n,t)),ua=()=>({rw:0,over:!1}),Cl=(t,e)=>t<720&&e/t>=1.25;function Ll(t){return t<900?Math.max(Se,Math.min(304,Math.round(t*.39))):t<1700?Math.round(240+t*.1):Math.min(680,Math.round(t*.25))}function El(t,e){return Number.isFinite(e)?Tl(Math.round(e),Se,Math.max(Se,t-po)):Ll(t)}function ho({thread:t=!1,open:e=!1}={},n,s,a){return t?e?s-a-n>=420?{rw:n,over:!1}:{rw:Math.max(0,s-a),over:!0}:{rw:uo,over:!1}:{rw:0,over:!1}}function Ol({w:t,h:e,saved:n=null,listShut:s=!1,sel:a=null,prefs:o=!1,conversation:r=ua}){const i=Cl(t,e),c=i?t:El(t,n),u=!i&&s&&a!=="overview"&&!o?uo:c,d=i?ua():r(c,t,u),p=i?t:Math.max(0,t-u-d.rw),h=e>=640;let f=1;return p>=1900?f=4:p>=1360?f=3:p>=820&&(f=2),!h&&p>=1100&&(f=3),e<400&&(f=1),{mode:i?"stack":"side",w:t,h:e,lw:c,lwc:u,rw:d.rw,dw:p,cols:f,span:f>=2&&h,flat:f>=2&&!h,table:!i&&a==="overview",shut:!i&&u!==c,cvOver:d.over,rail:!i&&c<262,wide:!i&&c>=460,xwide:!i&&c>=600,tight:!i&&c<300,short:e<520,narrowDet:p<460,bandh:Math.round(Math.max(88+40*2.3,(e-48-40)*.24+48+40))}}function Nl(t){return{"data-table":t.table,"data-list-shut":t.shut,"data-cv-over":t.cvOver,"data-rail":t.rail,"data-wide-list":t.wide||t.table,"data-xwide-list":t.xwide,"data-tight-list":t.tight,"data-small":t.w<320,"data-tiny":t.w<280,"data-snug":t.lw<355,"data-narrow-det":t.narrowDet,"data-short-list":t.short}}const Hl=["mode","cols","span","rail","wide","xwide","narrowDet","tight","table","shut","cvOver"],Bl=(t,e)=>!t||Hl.some(n=>t[n]!==e[n]),_t=1200,Je=500,Rl=2e3,fo=(t,e)=>t==null||e-t<Rl,ms=(t,e,n,s)=>new Map([...t].filter(([a,o])=>n-o<s&&e.has(a)));function mo(t,e,n){const s=new Map(e.map(r=>[r.id,r.status]));if(!t)return{seen:s,arrived:new Map,changed:new Map};const a=ms(t.arrived,s,n,Je),o=ms(t.changed,s,n,_t);for(const[r,i]of s)t.seen.has(r)?t.seen.get(r)!==i&&o.set(r,n):a.set(r,n);return{seen:s,arrived:a,changed:o}}function go(t,e,n,s="",a=_t){if(!t||t.scope!==s)return{scope:s,seen:new Map(e),at:new Map};const o=ms(t.at,e,n,a);for(const[r,i]of e)t.seen.has(r)&&t.seen.get(r)!==i&&o.set(r,n);return{scope:s,seen:new Map(e),at:o}}function $o(t,e,n=_t){return t==null||e-t>=n?null:`${-Math.max(0,e-t)}ms`}function _l(t){const e=[],n=new Array(t.length);for(let a=0;a<t.length;a++){let o=0,r=e.length;for(;o<r;){const i=o+r>>1;t[e[i]]<t[a]?o=i+1:r=i}n[a]=o>0?e[o-1]:-1,e[o]=a}const s=new Set;for(let a=e.length?e.at(-1):-1;a>=0;a=n[a])s.add(a);return s}function Il(t,e){const n=new Map(t.map((i,c)=>[i.key,{sig:i.sig,at:c}])),s=new Array(e.length).fill("new"),a=[],o=new Set;for(let i=0;i<e.length;i++){const{key:c,sig:u}=e[i],d=n.get(c);!d||d.sig!==u||o.has(c)||(o.add(c),a.push([i,d.at]))}const r=_l(a.map(([,i])=>i));return a.forEach(([i],c)=>s[i]=r.has(c)?"keep":"move"),{remove:t.filter(i=>!o.has(i.key)).map(i=>i.key),steps:s}}const pa=new WeakMap;function yo(t){if(!t||typeof t!="object")return JSON.stringify(t??null);let e=pa.get(t);return e===void 0&&(e=JSON.stringify(t),pa.set(t,e)),e}const ha=new WeakMap;let jl=0;function Pl(t){if(!t||typeof t!="object")return 0;let e=ha.get(t);return e||(e=++jl,ha.set(t,e)),e}const fa=new WeakMap;function Oe(t,e){const n=fa.get(t);return n&&n.html===e&&n.first===t.firstChild?!1:(t.innerHTML=e,fa.set(t,{html:e,first:t.firstChild}),!0)}function wo(t){if(!t.length)return[];const e=document.createElement("template");return e.innerHTML=t.join(""),[...e.content.children]}function bo(t,e,n){if(t.moveBefore&&e.isConnected)try{return t.moveBefore(e,n),!0}catch{}return t.insertBefore(e,n),!1}function vo(t,e,n){const s=Il([...e].map(([d,p])=>({key:d,sig:p.sig})),n);for(const d of s.remove)e.get(d).el.remove();const a=wo(n.filter((d,p)=>s.steps[p]==="new").map(d=>d.html())),o=new Array(n.length),r=[],i=[];let c=a.length,u=null;for(let d=n.length-1;d>=0;d--){const p=n[d];let h;s.steps[d]==="new"?(h=a[--c],t.insertBefore(h,u),r.push([p.key,h])):(h=e.get(p.key).el,s.steps[d]==="move"&&!bo(t,h,u)&&i.push([p.key,h])),o[d]=[p.key,{el:h,sig:p.sig}],u=h}return{drawn:new Map(o),added:r,restarted:i}}const Wn="M-19.8,19.8 A28,28 0 1 1 19.8,19.8",ma=t=>t.toFixed(2),Fl=(t,e,n)=>Math.min(n,Math.max(e,t)),yn=t=>t==null?"unknown":t>=90?"full":t>=70?"high":"ok",wn=t=>t.level==="full"?"x":t.level==="high"?"h":"f";function Dl(t,e=18){const n=e<=30,s=Fl(t.pct??0,0,100),a=t.level||yn(t.pct??null),o=`<path d="${Wn}" class="i-track" pathLength="100"/><path d="${Wn}" class="i-red" pathLength="100" stroke-dasharray="10 100" stroke-dashoffset="-90"/><path d="${Wn}" class="i-fill" pathLength="100" stroke-dasharray="${ma(s)} 100"/><line x1="0" y1="0" x2="${n?19:21}" y2="0" class="i-needle" transform="rotate(${ma(135+270*s/100)})"/>${n?"":`<text x="0" y="28" class="i-label" text-anchor="middle">${Math.round(s)}%</text>`}`;return`<svg class="inst${n?" i-mini":""}" data-k="gauge" data-level="${a}" width="${e}" height="${e}" viewBox="-36 -36 72 72" aria-hidden="true"><circle r="35" class="i-dial"/>${o}<circle r="${n?6:4.5}" class="i-hub"/></svg>`}const b=t=>t.toFixed(2),St=(t,e,n)=>Math.min(n,Math.max(e,t)),Ye=t=>String(t).replace(/[&<>"]/g,e=>({"&":"&","<":"<",">":">",'"':"""})[e]);function js(t,e){return{W:e?300:Math.round(t*1.9),H:e?46:t>=24?16:13}}function Ze(t,e,n,s){return`<svg class="inst g-inst ${t}" width="${e}" height="${n}" viewBox="0 0 ${e} ${n}" aria-hidden="true">${s}</svg>`}const ga=(t,e,n)=>t>0?St((Math.log10(t/e)+1)/n,0,1):0,ko=t=>t>0?St(Math.log10(Math.max(t/6e4,.1)*10)/Math.log10(6e3),0,1):0,Wl=[[6e4,"1m"],[6e5,"10m"],[36e5,"1h"]];function qt(t){return t.k==="gauge"?t.plan?t.plan.done/Math.max(1,t.plan.total):St((t.pct??0)/100,0,1):t.k==="pips"?t.of?St((t.v||0)/t.of,0,1):ga(t.v||0,t.base,5):t.k==="tally"?ga(t.n||0,1,4):t.k==="watch"?ko(t.ms||0):0}function Qe(t,e,n,s,a=14){const o=Array(a).fill(0),r=Math.max(1,n-e);return t.forEach((i,c)=>{i&&(o[St(Math.floor((i-e)/r*a),0,a-1)]+=s?s[c]:1)}),o}function Ul(t,e){const n=t.map(o=>o.startedAt).filter(Boolean);if(!n.length)return null;const s=Math.min(...n),a=Math.max(...t.map(o=>o.running?e:o.endedAt||o.startedAt||0));return{from:s,to:Math.max(a,s+1)}}function bn(t,e=Date.now()){const n=t||[],s=Ul(n,e);return s?{bins:Qe(n.map(a=>a.startedAt),s.from,s.to),failBins:Qe(n.filter(a=>a.error).map(a=>a.startedAt),s.from,s.to)}:{bins:[],failBins:[]}}function ql(t){if(!t.length)return[];const e=t.map(a=>a.at),n=Math.min(...e),s=Math.max(...e);return Qe(e,n,Math.max(s,n+1),t.map(a=>a.output||0))}function xo(t,e,{points:n=24,used:s=null}={}){if(!t||t.length<2||!e)return null;const a=Math.min(n,t.length),o=[];for(let r=0;r<a;r++){const i=t[Math.round(r*(t.length-1)/(a-1))];o.push(Math.round(i.context/e*1e3)/10)}if(s!=null){const r=Math.round(s/e*1e3)/10;Math.abs(o.at(-1)-r)>=.5&&o.push(r)}return o}function Mo(t,e,n=5){const s=t.reduce((u,d)=>u+d,0)||1,a=[...t.slice(0,n-1),t.slice(n-1).reduce((u,d)=>u+d,0)],o=a.map(u=>u/s*e),r=o.map(Math.floor);let i=e-r.reduce((u,d)=>u+d,0);o.map((u,d)=>[u-Math.floor(u),d]).sort((u,d)=>d[0]-u[0]).forEach(([,u])=>{i>0&&a[u]>0&&(r[u]++,i--)});const c=[];return r.forEach((u,d)=>{for(let p=0;p<u;p++)c.push({tone:d})}),c}function Vl(t,e,n=Yt){const s=t.reduce((i,c)=>i+c,0)||1,a=t.map(i=>i/s*e),o=a.map(Math.floor);t.forEach((i,c)=>{i&&!o[c]&&o.reduce((u,d)=>u+d,0)<e&&(o[c]=1)});for(const[,i]of a.map((c,u)=>[c-Math.floor(c),u]).sort((c,u)=>u[0]-c[0])){if(o.reduce((c,u)=>c+u,0)>=e)break;t[i]&&o[i]++}const r=[];for(o.forEach((i,c)=>{for(let u=0;u<i&&r.length<e;u++)r.push(n[c])});r.length<e;)r.push("idle");return r}function Gl(t){if(t.k==="pips"&&!t.of){const e=t.dir==="$"?Bs:k;return[1,2,3,4].map(n=>[n/5,e(t.base*10**(n-1))])}return t.k==="tally"?[1,2,3].map(e=>[e/4,String(10**(e-1))]):t.k==="watch"?Wl.map(([e,n])=>[ko(e),n]):t.k==="gauge"&&!t.plan?[[.7,"70%"],[.9,"90%"]]:[]}const Ps=(t,e)=>Array.from({length:e},(n,s)=>{const a=s/e*t.total;return{cls:a<t.done?"p":Math.floor(a)===t.done&&t.cur?"c":"t"}}),vn=(t,e)=>{const n=t.total||1,s=Math.min(n,e),a=t.run?Math.max(1,Math.round(t.run/n*s)):0;return Array.from({length:s},(o,r)=>({cls:r<a?"r":"o"}))},Kl=(t,e)=>Dl(t,e);function Un(t,e,n,s,a=!1){const o=t.length||1,r=s>20?6:2,i=s>20?3:1,c=Math.max(.8,(n-r*2-i*(o-1))/o),u=Math.max(1,...t),d=s-r,p=s-r*2;let h=-1;t.forEach((m,y)=>{m>0&&(h=y)});let f=`<line x1="${r}" x2="${n-r}" y1="${d-.5}" y2="${d-.5}" class="m-base"/>`;return t.forEach((m,y)=>{if(!m)return;const $=a?p:Math.max(1.5,m/u*p),x=e?.[y]?Math.min($,Math.max(1.5,e[y]/u*p)):0,E=r+y*(c+i);$-x>0&&(f+=`<rect x="${b(E)}" y="${b(d-$)}" width="${b(c)}" height="${b($-x)}" class="${y===h?"m-tip":"m-bar"}"/>`),x&&(f+=`<rect x="${b(E)}" y="${b(d-x)}" width="${b(c)}" height="${b(x)}" class="m-bad"/>`)}),f}function qn(t,e,n,s){const a=s>20?14:4,o=n-a*2,r=s-a*2;let i=a,c=`<rect x="${a}" y="${a}" width="${o}" height="${r}" rx="1" class="m-track"/>`;for(const u of t){if(!u.v)continue;const d=Math.max(1.5,u.v/(e||1)*o);c+=`<rect x="${b(i)}" y="${a}" width="${b(Math.min(d,a+o-i))}" height="${r}" class="${u.cls}"/>`,i+=d}return c}function $a(t,e,n){const s=t.length||1,a=n>20?14:4,o=n>20?4:1.5,r=(e-a*2-o*(s-1))/s;return t.map((i,c)=>`<rect x="${b(a+c*(r+o))}" y="${a}" width="${b(r)}" height="${n-a*2}" rx="1" class="m-${i}"/>`).join("")}function Yl(t,e){if(t.k==="gauge"&&!t.plan)return Kl(t,e);const n=e>30,s=n?300:Math.round(e*1.9),a=n?46:e>=24?16:13,o=r=>`<svg class="inst m-inst" width="${s}" height="${a}" viewBox="0 0 ${s} ${a}" aria-hidden="true"><rect x=".5" y=".5" width="${s-1}" height="${a-1}" rx="${n?5:3}" class="m-plate"/>${r}</svg>`;if(t.plan){const r=t.plan,i=[];for(let c=0;c<r.total;c++)i.push(c<r.done?"done":c===r.done&&r.cur?"cur":"todo");return o($a(i,s,a))}switch(t.k){case"tally":return o(Un(t.bins?.length?t.bins:[t.n||0],t.failBins,s,a));case"watch":return o(Un(t.bins||[],null,s,a,!0));case"pips":return t.bars?o(Un(t.bars,null,s,a)):o(qn([{v:t.v||0,cls:"m-tip"}],t.of||t.v||1,s,a));case"split":return o(qn([{v:t.a||0,cls:"m-add"},{v:t.r||0,cls:"m-del"}],(t.a||0)+(t.r||0),s,a));case"mix":{const r=t.parts||[],i=r.reduce((u,d)=>u+d,0),c=r.slice(4).reduce((u,d)=>u+d,0);return o(qn([...r.slice(0,4),c].map((u,d)=>({v:u,cls:`n${d}`})),i,s,a))}case"orbit":return o($a(vn(t,n?24:8).map(r=>r.cls==="r"?"run":"done"),s,a))}return o("")}function Wt(t,e,n,s=0){return t<=0?"":`<circle r="${n}" class="${e}" pathLength="100" stroke-dasharray="${b(Math.min(t,1)*100)} 100" stroke-dashoffset="${b(-s*100)}" transform="rotate(-90)"/>`}function ya(t,e,n){const s=t.length||1,a=(100-n*s)/s;return t.map((o,r)=>`<circle r="${e}" class="${o.cls}" pathLength="100" stroke-dasharray="${b(a)} ${b(100-a)}" stroke-dashoffset="${b(-(r*(a+n)))}" transform="rotate(-90)"/>`).join("")}function zl(t,e){const n=e>30,s=n?27:25;let a=`<circle r="${s}" class="t"/>`,o="";if(t.k==="gauge"&&t.plan){const r=Math.min(t.plan.total,n?24:12);a+=ya(Ps(t.plan,r),s,r>1?3:0)}else if(t.k==="gauge")a+=Wt(qt(t),wn(t),s),n&&(o=`<text x="0" y="6" text-anchor="middle" class="big">${Math.round(t.pct??0)}%</text>`);else if(t.k==="split"){const r=(t.a||0)+(t.r||0)||1;a+=Wt((t.a||0)/r,"a",s)+Wt((t.r||0)/r,"d",s,(t.a||0)/r)}else if(t.k==="mix"){const r=t.parts||[],i=r.reduce((u,d)=>u+d,0)||1;let c=0;[...r.slice(0,4),r.slice(4).reduce((u,d)=>u+d,0)].forEach((u,d)=>{if(!u)return;const p=u/i;a+=Wt(Math.max(p-.012,.006),`n${d}`,s,c),c+=p})}else if(t.k==="orbit"){const r=vn(t,n?24:8);a+=ya(r,s,r.length>1?4:0)}else if(t.k==="tally"){const r=qt(t),i=t.fail&&t.n?Math.max(.04,r*t.fail/t.n):0;a+=Wt(r-i,"s",s)+Wt(i,"x",s,r-i)}else a+=Wt(qt(t),"s",s),n&&t.k==="watch"&&t.ms>=36e5&&(o=`<text x="0" y="6" text-anchor="middle" class="big">${Math.floor(t.ms/36e5)}h</text>`);return`<svg class="inst g-inst g-ring${n?"":" g-mini"}" width="${e}" height="${e}" viewBox="-36 -36 72 72" aria-hidden="true">${a}${o}</svg>`}function Ao(t,e,n,s){const a=s?8:1,o=e-(s?8:1)-a,r=s?12:5,i=s?10:(n-r)/2,c=(p,h,f)=>h>0?`<rect x="${b(p)}" y="${b(i)}" width="${b(Math.max(h,.8))}" height="${r}" rx="${s?2:1}" class="${f}"/>`:"";let u=c(a,o,"t");const d=(p,h)=>{const f=p.length||1,m=(o-h*(f-1))/f;return p.map((y,$)=>c(a+$*(m+h),m,y.cls)).join("")};if(t.k==="gauge"&&t.plan)u=d(Ps(t.plan,t.plan.total),s?4:1.5);else if(t.k==="split"){const p=(t.a||0)+(t.r||0)||1;u+=c(a,(t.a||0)/p*o,"a")+c(a+(t.a||0)/p*o,(t.r||0)/p*o,"d")}else if(t.k==="mix")u=d(Mo(t.parts||[],s?40:16).map(p=>({cls:`n${p.tone}`})),s?2:1);else if(t.k==="orbit")u=d(vn(t,s?24:8),s?4:1.5);else{const p=qt(t),h=t.k==="tally"&&t.fail&&t.n?Math.max(.04,p*t.fail/t.n):0;u+=c(a,(p-h)*o,t.k==="gauge"?wn(t):"s"),h&&(u+=c(a+(p-h)*o,h*o,"x"))}for(const[p,h]of Gl(t)){const f=a+p*o;u+=`<line x1="${b(f)}" x2="${b(f)}" y1="${b(i-(s?4:2))}" y2="${b(i+r+(s?4:2))}" class="m"/>`,s&&(u+=`<text x="${b(f)}" y="${i+r+18}" text-anchor="middle" class="lbl">${Ye(h)}</text>`)}return u}function So(t,e){const n=e>=60,{W:s,H:a}=js(e,n);return Ze(`g-meter${n?"":" g-mini"}`,s,a,Ao(t,s,a,n))}function Jt(t,e,n,s){const a=t.length||1,o=s?8:1,r=s?a>16?2:3:a>10?1:1.5,i=(e-o*2-r*(a-1))/a,c=s?8:2,u=s?24:n-4;return t.map((d,p)=>`<rect x="${b(o+p*(i+r))}" y="${c}" width="${b(Math.max(i,.8))}" height="${u}" rx="${s?1.5:.8}" class="${d.cls}"/>`).join("")}function Vn(t,e,n,s,a,o=!1){const r=a?8:1,i=o?a?14:5:0,c=a?5:2,u=(n-r*2-i-c*(e-1))/e,d=a?6:1,p=a?34:s-1;let h="";for(let f=0;f<e;f++){const m=(p-d)*(f+1)/e;h+=`<rect x="${b(r+f*(u+c))}" y="${b(p-m)}" width="${b(u)}" height="${b(m)}" rx="${a?1.5:.8}" class="${f<t?"s":"t"}"/>`}return o&&(h+=`<circle cx="${b(n-r-i/2)}" cy="${b(p-(a?4:2))}" r="${a?4:2}" class="x"/>`),h}function Xl(t,e){const n=e>=60,{W:s,H:a}=js(e,n),o=(i,c)=>{const u=i>0?Math.max(1,Math.round(i*10)):0;return Array.from({length:10},(d,p)=>({cls:p<u?c(p):"t"}))};let r="";if(t.k==="gauge"&&t.plan)r=Jt(Ps(t.plan,Math.min(t.plan.total,n?24:12)),s,a,n);else if(t.k==="gauge")r=Jt(o(qt(t),i=>i<7?"f":i<9?"h":"x"),s,a,n);else if(t.k==="split"){const i=(t.a||0)+(t.r||0),c=i?Math.round((t.a||0)/i*10):0;r=Jt(Array.from({length:10},(u,d)=>({cls:i?d<c?"a":"d":"t"})),s,a,n)}else if(t.k==="mix")r=Jt(Mo(t.parts||[],10).map(i=>({cls:`n${i.tone}`})),s,a,n);else if(t.k==="orbit")r=Jt(vn(t,n?16:8),s,a,n);else if(t.k==="pips"&&t.of)r=Jt(o(qt(t),()=>"s"),s,a,n);else if(t.k==="pips"){const i=t.v||0;r=Vn(i>=t.base?St(Math.floor(Math.log10(i/t.base))+1,1,5):0,5,s,a,n)}else if(t.k==="tally"){const i=t.n||0;r=Vn(i?St(Math.floor(Math.log10(i))+1,1,4):0,4,s,a,n,!!t.fail)}else if(t.k==="watch"){const i=t.ms||0;r=Vn([0,6e4,6e5,36e5,36e6].filter(c=>i>c||c===0&&i>0).length,5,s,a,n)}return Ze(`g-seg${n?"":" g-mini"}`,s,a,r)}function Jl(t,e,n,s,a){const o=s?8:1,r=e-(s?8:1),i=s?8:2,c=n-(s?12:2),u=t.length,d=t.map((h,f)=>[o+(u>1?f/(u-1):1)*(r-o),c-St(h/a,0,1)*(c-i)]),p=d.map((h,f)=>`${f?"L":"M"}${b(h[0])},${b(h[1])}`).join("");return{pts:d,line:p,area:`${p}L${b(d[u-1][0])},${c}L${b(d[0][0])},${c}Z`,top:i,bottom:c,x0:o,x1:r}}let Zl=0;function Ql(t,e){const n=e>=60,{W:s,H:a}=js(e,n);let o=null,r=1,i="s",c=!1,u=null;if(t.k==="gauge"&&!t.plan&&t.hist?.length>1)o=t.hist,r=100,i=wn(t),c=!0;else if(t.k==="tally"&&t.bins?.some(Boolean)){let f=0;o=t.bins.map(m=>f+=m),r=Math.max(1,f),u=t.failBins}else t.k==="watch"&&t.bins?.some(Boolean)?(o=t.bins,r=Math.max(1,...t.bins)):t.k==="pips"&&t.bars?.some(Boolean)&&(o=t.bars,r=Math.max(1,...t.bars));if(!o)return Ze(`g-meter${n?"":" g-mini"}`,s,a,Ao(t,s,a,n));o.length===1&&(o=[o[0],o[0]]);const d=Jl(o,s,a,n,r);let p=`<line x1="${b(d.x0)}" x2="${b(d.x1)}" y1="${b(d.bottom+.5)}" y2="${b(d.bottom+.5)}" class="m base"/>`;if(c){const f=`tg-spark-${++Zl}`;p=`<defs><linearGradient id="${f}" x1="0" y1="0" x2="0" y2="1"><stop offset="0" class="g0 ${i}"/><stop offset="1" class="g1 ${i}"/></linearGradient></defs>${p}<line x1="${b(d.x0)}" x2="${b(d.x1)}" y1="${b(d.top)}" y2="${b(d.top)}" class="m lim"/><path d="${d.area}" class="area grad" fill="url(#${f})"/>`}else p+=`<path d="${d.area}" class="area ${i}"/>`;p+=`<path d="${d.line}" class="line ${i}"/>`,u&&u.forEach((f,m)=>{f&&d.pts[m]&&(p+=`<circle cx="${b(d.pts[m][0])}" cy="${b(d.pts[m][1])}" r="${n?3.5:1.6}" class="x"/>`)});const h=d.pts[d.pts.length-1];return p+=`<circle cx="${b(h[0])}" cy="${b(h[1])}" r="${n?4:2}" class="dot ${i}"/>`,n&&c&&(p+=`<text x="${b(d.x1)}" y="${b(d.top-2)}" text-anchor="end" class="lbl">Limit</text>`),Ze(`g-spark${n?"":" g-mini"}`,s,a,p)}function tc(t,e){if(t.k!=="gauge"||t.plan)return"";if(e>=60)return So(t,e);const n=Math.round(e*.8),s=5,a=qt(t);return`<svg class="inst g-inst g-slim" width="${s}" height="${n}" viewBox="0 0 ${s} ${n}" aria-hidden="true"><rect x="0" y="0" width="${s}" height="${n}" rx="1.5" class="t"/>${a>0?`<rect x="0" y="${b(n-Math.max(1,a*n))}" width="${s}" height="${b(Math.max(1,a*n))}" rx="1.5" class="${wn(t)}"/>`:""}</svg>`}const ec={mine:Yl,rings:zl,meters:So,segments:Xl,spark:Ql,numbers:tc},nc=34;function sc(t,e){if(t.length<=e)return t.slice();const n=Array(e).fill(0);return t.forEach((s,a)=>{n[Math.min(e-1,Math.floor(a*e/t.length))]+=s}),n}const tn=(t,e,n)=>`<svg class="inst g-inst g-foot ${t}" width="${e}" height="${e}" viewBox="0 0 ${e} ${e}" aria-hidden="true">${n}</svg>`;function ac(t,e){const n=t.a||0,s=t.r||0,a=n+s,o=e/2,r=o-.5;if(!a)return tn("g-pie",e,`<circle cx="${b(o)}" cy="${b(o)}" r="${b(r)}" class="t"/>`);const i=d=>{const p=d*2*Math.PI-Math.PI/2;return`${b(o+r*Math.cos(p))},${b(o+r*Math.sin(p))}`},c=(d,p,h)=>p-d>=.9999?`<circle cx="${b(o)}" cy="${b(o)}" r="${b(r)}" class="${h}"/>`:p<=d?"":`<path d="M${b(o)},${b(o)}L${i(d)}A${b(r)},${b(r)} 0 ${p-d>.5?1:0} 1 ${i(p)}Z" class="${h}"/>`,u=n/a;return tn("g-pie",e,c(0,u,"a")+c(u,1,"d"))}function oc(t,e){const n=e>=60,s=Math.max(0,t.total||0),a=Math.min(s,n?64:25);if(!a)return"";const o=Math.max(2,Math.ceil(Math.sqrt(a))),r=n?3:o>4?1.5:2,i=(e-r*(o-1))/o,c=t.run?Math.max(1,Math.round(t.run/s*a)):0,u=t.sts?Vl(t.sts,a):null;let d="";for(let p=0;p<a;p++){const h=p%o*(i+r),f=Math.floor(p/o)*(i+r);d+=`<rect x="${b(h)}" y="${b(f)}" width="${b(i)}" height="${b(i)}" rx="${b(Math.min(2,i*.22))}" ${u?`data-st="${u[p]}"`:`class="${p<c?"r":"t"}"`}/>`}return tn("g-waf",e,d)}function rc(t,e){const n=e>=60,s=t.bars?.some(Boolean)?sc(t.bars,n?14:7):null,a=e-1,o=1;let r=`<line x1="0" x2="${e}" y1="${b(a+.5)}" y2="${b(a+.5)}" class="m base"/>`;const i=(c,u,d,p,h)=>{const f=(e-d*(u-1))/u;return`<rect x="${b(c*(f+d))}" y="${b(a-p)}" width="${b(f)}" height="${b(p)}" rx="${n?1.5:.6}" class="${h}"/>`};if(s){const c=Math.max(1,...s);let u=-1;s.forEach((d,p)=>{d>0&&(u=p)}),s.forEach((d,p)=>{d&&(r+=i(p,s.length,n?3:1.5,Math.max(1.5,d/c*(a-o)),p===u?"f":"s"))})}else{const c=t.v||0,u=c>=t.base?St(Math.floor(Math.log10(c/t.base))+1,1,5):0;for(let d=0;d<5;d++)r+=i(d,5,n?4:2,(a-o)*(d+1)/5,d<u?"s":"t")}return tn("g-cols",e,r)}const gs={pie:ac,waffle:oc,cols:rc};function ic(t){return t.k==="pie"?"Green is the share of lines added, and red is the share removed.":t.k==="waffle"&&t.sts?`${(t.total||0)>64?"Each square stands for a few threads":"One square for each thread in the list"}, in its status color, with the ones that need you first.`:t.k==="waffle"?(t.total||0)>64?"Each square stands for a few threads. Blue squares are running, and gray ones are not.":"One square for each thread in the list. Blue squares are running, and gray ones are not.":t.k==="cols"?t.bars?.some(Boolean)?"Each column is a slice of time, oldest on the left. The brighter column is the latest.":"Each bar is ten times the one before it, so this shows size, not a limit.":""}function kn(t,e,n=""){if(!t?.total)return"";let s="";for(let o=0;o<t.total;o++){const r=o<t.done?"d":o===t.done&&t.current?"c":"t";s+=`<i data-s="${r}"></i>`}const a=`${t.done} of ${t.total} steps done`;return`<span class="ticks${n?` ${Ye(n)}`:""}" data-st="${Ye(e||"idle")}" role="img" aria-label="${Ye(a)}">${s}</span>`}const Fs=t=>t?.total?{k:"gauge",pct:t.done/t.total*100,plan:{done:t.done,total:t.total,cur:!!t.current}}:null,Te=Object.freeze({activity:"mine",toolCalls:"mine",limits:"mine",tools:"segments",subagents:"segments",files:"rings",tokens:"rings",spend:"rings",context:"mine",contextHistory:"spark",prompts:"numbers",session:"spark",duration:"spark",planTip:"mine"}),lc=new Set(["toolCalls","duration"]);function Tt(t,e,n=18){const s=Te[t];return!s||!e?"":ec[s](e,n)}const De={rings:"Each fifth of the ring is ten times more, so this shows size, not a limit.",segments:"Each bar is ten times the one before it, so this shows size, not a limit.",meters:"Each mark is ten times the one before it, so this shows size, not a limit."};function cc(t){return t.plan?"One mark for each step.":t.k==="tally"?t.failBins?.some(Boolean)?"Bars show when these happened, oldest on the left. Red marks failures.":"Bars show when these happened, oldest on the left.":t.k==="watch"?"Marks show when the thread was active, from its start until now. Gaps are quiet time.":t.k==="pips"&&t.bars?"Each bar is a slice of time, oldest on the left. The bright bar is the latest.":t.k==="pips"&&t.of?`The bright part is its share of ${t.ofLabel||"the total"}.`:t.k==="orbit"?"One mark each, scaled down when there are many. Blue means running.":t.k==="mix"?"Each color is one tool, largest first.":""}function To(t,e){const n=e.k;return t==="mine"?cc(e):t==="numbers"?n==="gauge"?"The bar fills as it gets closer to the limit.":"":t==="spark"?n==="gauge"&&!e.plan&&e.hist?.length>1?"The line is the context over the thread, oldest on the left. The dashed line is the limit.":n==="tally"&&e.bins?.some(Boolean)?e.failBins?.some(Boolean)?"The line climbs with each one, oldest on the left. Red dots mark failures.":"The line climbs with each one, oldest on the left.":n==="watch"&&e.bins?.some(Boolean)?"The shape shows how busy the thread was, oldest on the left.":n==="pips"&&e.bars?.some(Boolean)?"The line shows the output in each slice of time, oldest on the left. The dot is the latest.":To("meters",e):n==="gauge"&&e.plan?t==="meters"||t==="segments"?"One block for each step.":"One segment for each step.":n==="gauge"?t==="segments"?"Each block is 10%. Blocks past 70% light amber, and the last one lights red.":t==="meters"?"The marks are at 70% and 90%, where the color changes.":"The color changes at 70% and again at 90%.":n==="split"?"Green is lines added and red is lines removed.":n==="mix"?"Each color is one tool, largest first.":n==="orbit"?"One mark each, scaled down when there are many. Blue means running.":n==="pips"&&e.of?`The filled part is its share of ${e.ofLabel||"the total"}.`:n==="pips"?De[t]||De.meters:n==="tally"?`${De[t]||De.meters}${e.fail?" Red is the failed share.":""}`:n==="watch"?t==="segments"?"The bars light at any time, 1 minute, 10 minutes, 1 hour, and 10 hours.":t==="rings"?"The ring fills on a time scale: about a quarter at 1 minute, half at 10 minutes, and three quarters at an hour.":"The marks are at 1 minute, 10 minutes, and 1 hour.":""}function Gn(t,e){const n=Te[t];return n&&e?To(n,e):""}function Ne(t,e){const n=/^@([^/]+)\/(.+)$/.exec(t||"");return n&&e&&n[1].toLowerCase()===String(e).toLowerCase()?n[2]:t}function $s(t){return`${t.org?`<span class="w w-org" title="${Mt(`Organization ${t.org}`)}">${Q("org")}<span>${Mt(t.org)}</span></span>`:""}<span class="w w-folder" title="${Mt(t.projectPath||t.project||"")}">${Q("folder")}<span>${Mt(Ne(t.project,t.org)||"unknown")}</span></span>`}function dc(t){const e=(n,s)=>`<span class="w">${Q(n)}<span>${Mt(s)}</span></span>`;return[t.org&&e("org",t.org),`<span class="w w-folder">${Q("folder")}<span>${Mt(Ne(t.project,t.org)||"unknown")}</span></span>`,t.worktree&&e("worktree",t.worktree),t.gitBranch&&e("branch",t.gitBranch)].filter(Boolean).join("")}const Co={label:"Claude Code: managing costs",href:"https://code.claude.com/docs/en/costs"},wa={label:"Anthropic API pricing",href:"https://platform.claude.com/docs/en/about-claude/pricing"},We={label:"Claude Code: prompt caching",href:"https://code.claude.com/docs/en/prompt-caching"},Kn={label:"Claude: context windows",href:"https://platform.claude.com/docs/en/build-with-claude/context-windows"},uc={label:"Claude Code: subagents",href:"https://code.claude.com/docs/en/sub-agents"},ys={"claude-code":{name:"Claude Code",docs:Co},codex:{name:"Codex",docs:{label:"Codex docs",href:"https://developers.openai.com/codex"}},cursor:{name:"Cursor",docs:{label:"Cursor docs",href:"https://cursor.com/docs"}},antigravity:{name:"Antigravity CLI",docs:null},hermes:{name:"Hermes",docs:{label:"Hermes on GitHub",href:"https://github.com/NousResearch/hermes-agent"}},opencode:{name:"OpenCode",docs:{label:"OpenCode docs",href:"https://opencode.ai/docs"}},kilocode:{name:"Kilo Code",docs:{label:"Kilo Code docs",href:"https://kilo.ai/docs"}}},ba=t=>ys[t]?.name||"This harness",va=t=>ys[t]?.docs?[ys[t].docs]:[],Zt=(t,e)=>t==="claude-code"?e:[],pc={"claude-code":["What this thread's tokens would cost at Anthropic's API list prices, subagents included. Threadgauge prices every reply the same way Claude Code's own /usage total does.","On a Pro or Max plan, your subscription covers this usage, so it isn't what you pay. Use it to compare how much work threads did."],codex:["Codex doesn't save a cost for its threads, so there's nothing to show."],cursor:["Cursor doesn't save a cost, tokens, or the model on disk, so there's nothing to show."],antigravity:["Antigravity CLI keeps its usage in a format Threadgauge doesn't read, so there's nothing to show."],hermes:["What the provider billed when it reports that, and Hermes's own estimate otherwise, added up across the thread's compressed segments."],opencode:["The cost OpenCode records for the thread, priced from each model's rates in its model catalog. With a subscription provider, it may not be what you pay."],kilocode:["The cost Kilo Code records for the thread, priced from each model's rates in its model catalog. With a subscription provider, it may not be what you pay."]},hc={"claude-code":"Lines added and removed by the agent's edits: Edit and Write, plus files that shell commands changed. Counted from the transcript, subagents included.",codex:"Lines added and removed by the patches Codex applied.",opencode:"Lines added and removed in each turn's diff summary. OpenCode 2.x doesn't record them.",kilocode:"Kilo Code's own running totals of lines added and removed."},Lo={spend:{title:"Spend",text:t=>pc[t]||[`${ba(t)} doesn't record a cost.`],links:t=>t==="claude-code"?[Co,wa]:va(t)},window:{title:"Context",text:()=>["What filled the context window in the latest request. Cache reads are the part of the conversation read back from the prompt cache, cache writes are the part stored in it for next time, new input is the rest of the prompt, and latest output is the model's reply.","Free space is what's left before the model's limit. Before it runs out, the harness compacts the conversation."],links:t=>[Kn,...Zt(t,[We])]},output:{title:"Output tokens",text:()=>["Tokens the model wrote: its replies, its tool calls, and its thinking. They cost the most per token."],links:t=>Zt(t,[wa])},outputTotal:{title:"Output tokens",text:()=>["Output tokens across every thread shown that records them: replies, tool calls, and thinking."],links:()=>[]},input:{title:"Input tokens",text:()=>["Prompt tokens the model read fresh: new input, plus tokens written to the prompt cache for later requests."],links:t=>Zt(t,[We])},cacheRead:{title:"Cache reads",text:()=>["Prompt tokens read back from the prompt cache. Every request resends the whole conversation, and the cache makes that repeated part cheap."],links:t=>Zt(t,[We])},cacheWrite:{title:"Cache writes",text:()=>["Prompt tokens stored in the prompt cache, so later requests can read them back cheaply."],links:t=>Zt(t,[We])},lines:{title:"Lines changed",text:t=>[hc[t]||`${ba(t)} doesn't record lines changed.`],links:t=>va(t)},linesTotal:{title:"Lines changed",text:()=>["Lines added and removed across every thread shown that records them."],links:()=>[]},prompts:{title:"Prompts",text:()=>["Messages you typed in this thread. Messages the harness adds itself, like compaction summaries, don't count."],links:()=>[]},toolCalls:{title:"Tool calls",text:()=>["Every tool call in the thread: reading and editing files, running commands, searching, and so on."],links:()=>[]},subagents:{title:"Subagents",text:()=>["Helper agents this thread started. Each works in its own context and reports back when it finishes.",'Finished subagents stay listed and counted, the way finished tool calls stay in Activity: the harness keeps their records, and nothing archives them. Only working ones put the thread in "Waiting on agents".'],links:t=>Zt(t,[uc])},duration:{title:"Duration",text:()=>["From the thread's first record until now while it's live, or until its last activity."],links:()=>[]},context:{title:"Context",text:()=>["How full the model's context window is: everything in the latest request, against the model's limit.","Near the limit, the harness compacts the conversation into a summary to make room."],links:()=>[Kn]},liveAgents:{title:"Live agents",text:()=>["Threads with a running harness process. For a harness that keeps no record of its processes, a thread counts while a turn is in progress."],links:()=>[]},history:{title:"Context over time",text:()=>["Context after each reply, against the model's limit. A mark shows where the conversation was compacted. Hover a point for its numbers."],links:()=>[Kn]},plan:{title:"Plan",text:()=>["The agent's own to-do list for this thread, from its plan or todo tool. The current step pulses while the thread is live."],links:()=>[]},activity:{title:"Activity",text:()=>["The newest tool calls: when each started, what it worked on, how long it took, and whether it failed."],links:()=>[]},tools:{title:"Tools",text:()=>["Calls, time, and failures for each tool, over the whole thread."],links:()=>[]},files:{title:"Files changed",text:()=>["Lines added and removed in each file, counted from the agent's edits."],links:()=>[]},promptList:{title:"Prompts",text:()=>["The messages you typed, newest first."],links:()=>[]},errors:{title:"Errors",text:()=>["API errors and turns that failed, newest first."],links:()=>[]}},fc={limits:{title:"Usage limits",text:()=>["How much of each account's usage limit is used, as the harness itself last recorded it. The limits cover the whole account, so each harness shows the newest it saved in any thread."],links:()=>[]},thoughts:{title:"Thoughts",text:()=>["What the agent last wrote while working, newest first. It shows the agent's own words, so it explains why it's doing what you see in Activity."],links:()=>[]},linesColumn:{title:"Lines changed",text:()=>["Lines added and removed by each thread's edits, as its harness records them. A thread whose harness doesn't record them shows —."],links:()=>[]},contextWindow:{title:"Context",text:()=>["What fills the context window now, from the agent's own count of the latest request. Messages are your prompts, the replies, and every tool result. The rest is set up before the first message: the system prompt, the tools, skills, and memory files.","Threadgauge estimates the parts from the thread's record. Free space is what's left before the harness compacts the conversation."],links:()=>Lo.context.links()},room:{title:"Room left",text:()=>["A straight-line estimate of how long until the context fills, from the pace since the last compaction. It can change quickly."],links:()=>[]},session:{title:"Session",text:()=>["Where this thread lives on your computer and how to get back to it: its id, the command that resumes it, its folders, its branch, and the file it was read from."],links:()=>[]},"ctx-system":{title:"System prompt",text:()=>["The harness's own instructions to the model, sent with every request. You can't change it from the thread."],links:()=>[]},"ctx-tools":{title:"Built-in tools",text:()=>["The descriptions of the harness's own tools, like Read, Edit, and Bash, sent with every request."],links:()=>[]},"ctx-reserve":{title:"Kept free for compacting",text:()=>["Room the harness keeps empty so it can summarize the conversation before the window fills. It compacts once the free space reaches this.","This is the harness's default. Threadgauge doesn't read the setting that changes it."],links:()=>[]},"ctx-free":{title:"Free space",text:()=>["What's left for new prompts, replies, and tool results before the harness compacts."],links:()=>[]}},Eo=t=>Lo[t]||fc[t]||null,ft=(t,e,n="")=>`<button type="button" class="term" data-term="${l(t)}" aria-expanded="false"${n?` ${n}`:""}>${l(e)}</button>`,kt=(t,e="",n="")=>`data-inst="${l(JSON.stringify(t))}" data-val="${l(e)}" data-sub="${l(n)}"`;function mc(t){try{const e=JSON.parse(t||"null");return e&&typeof e=="object"?e:null}catch{return null}}function gc(t,e,n){if(!e)return null;if(gs[e.k])return{html:gs[e.k](e,72),note:ic(e),square:!0};if(e.plan){const s={total:e.plan.total,done:e.plan.done,current:e.plan.cur?"now":""};return{html:kn(s,n,"tip-ticks"),note:Gn("planTip",e),square:!1}}if(e.sec&&Te[e.sec]){const s=Te[e.sec],a=s==="rings"||s==="mine"&&e.k==="gauge";return{html:Tt(e.sec,e,72),note:Gn(e.sec,e),square:a}}return t==="limits"?{html:Tt("limits",e,72),note:Gn("limits",e),square:!0}:null}function $c(t,{harness:e="",spec:n=null,val:s="",sub:a="",status:o="idle"}={}){const r=Eo(t);if(!r)return"";const i=gc(t,n,o),c=`<h4>${l(r.title)}</h4>${s?`<div class="tip-val">${l(s)}</div>`:""}${a?`<div class="tip-sub">${l(a)}</div>`:""}`,u=[...r.text(e),i?.note].filter(Boolean).map(h=>`<p>${l(h)}</p>`).join(""),d=r.links(e),p=d.length?`<div class="lnks">${d.map(h=>`<a href="${l(h.href)}" target="_blank" rel="noopener">${l(h.label)}</a>`).join("")}</div>`:"";return i?i.square?`<div class="tip-top">${i.html}<div>${c}</div></div>${u}${p}`:`${c}<div class="tip-wide">${i.html}</div>${u}${p}`:`${c}${u}${p}`}const ka=(t,e,n)=>Math.max(e,Math.min(n,t));function yc(t,e,n,s,a,o="below"){if(o==="right"&&t.right+e+10<s)return{x:t.right+8,y:ka(t.top,8,a-n-8)};const r=ka(t.left,8,Math.max(8,s-e-8));let i=t.bottom+6;return i+n>a-8&&(i=Math.max(8,t.top-n-6)),{x:r,y:i}}const It=t=>At(t).replace(/ \d+s$/,""),ws=t=>t.turnStartedAt||t.lastActivityAt,Yn=t=>$t(t).replace(/ ago$/,"");function ie(t){const e=t?.plan;return e&&t.status==="done"&&e.done<e.total?{...e,done:e.total,current:""}:e}function Oo(t){const e=[];t.subagents&&e.push(ct(t.subagents,"subagent","subagents"));const n=t.awaiting||[],s=a=>a.title||"another session";return n.length>2?e.push(s(n[0]),ct(n.length-1,"other session","other sessions")):e.push(...n.map(s)),e.length?`Waiting on ${Ae(e)}`:"Waiting on agents"}function No(t,e){switch(t.status){case"working":return{h:"Working",v:It(e-ws(t))};case"delegating":return{h:Oo(t),v:It(e-ws(t))};case"asking":return{h:"Waiting for your answer",v:At(e-t.lastActivityAt)};case"done":return{h:"Finished",v:$t(e-t.lastActivityAt)};case"error":return{h:"Stopped on an API error",v:$t(e-t.lastActivityAt)};default:return{h:"Last active",v:$t(e-t.lastActivityAt)}}}function xn(t,e){const n=No(t,e);return n.v?`${n.h} ${n.v}`:n.h}function He(t,e){const n=No(t,e);return`<span class="now-h">${l(n.h)}</span>${n.v?`<span class="now-v">${l(n.v)}</span>`:""}`}function wc(t,e){if(t.status==="working"){if(!t.tool)return null;const n=Number.isFinite(t.tool.startedAt)?t.tool.startedAt:e;return{cls:"rich",html:`<span class="nd-tool">${l(P(t.tool.name))}</span><span class="nd-dur num" data-since="${n}">${l(nt(e-n))}</span>${t.tool.target?`<span class="nd-t">${l(t.tool.target)}</span>`:""}`}}if(t.status==="delegating"){const n=(t.workingSubagents||[]).map(s=>s.name).filter(Boolean);return n.length?{cls:"plain",html:l(n.join(", "))}:null}return null}function Mn(t){const e=/^(API Error:\s*\d+)\s*(\{.*\})\s*$/s.exec(t||"");if(e)try{const n=JSON.parse(e[2]);if(n?.error?.message)return`${e[1]} ${n.error.message}`}catch{}return t||""}function Ho(t){if(t.status!=="asking"&&t.status!=="error"||!t.ask)return null;const e=t.ask;if(e.type==="question"){const n=e.questions?.[0],s=n?.text||n?.header;return s?{kind:"question",text:s}:null}return e.type==="approval"?e.target?{kind:"approval",text:e.target,mono:!0}:e.tool?{kind:"approval",text:P(e.tool),mono:!1}:null:e.type==="error"?{kind:"error",text:Mn(e.text)||"The last turn failed."}:null}function bc(t){const e=Ho(t);return e?e.kind==="approval"?`Asking to run ${e.text}`:e.text:""}function Bo(t,e,n=s=>s){const s=$t(e-t.lastActivityAt),a=t.tool?P(t.tool.name):"";switch(`${t.status}:${t.statusReason||""}`){case"asking:question":return`It asked you a question ${s}, and it's waiting for the answer.`;case"asking:approval":return`Its ${P(t.ask?.tool)||"tool"} call needs your approval. The call started ${s} and has no result yet.`;case"asking:waiting":return`${n(t.harness)} says it's waiting on you, with no open question or call to say why.`;case"asking:marked-blocked":return"The Claude app marked its turn as waiting on you.";case"working:new-prompt":return"A prompt is newer than its transcript, so a turn is underway.";case"delegating:subagents":case"delegating:awaiting":{const o=[];return t.subagents&&o.push(ct(t.subagents,"subagent","subagents")),t.awaiting?.length&&o.push(ct(t.awaiting.length,"other thread","other threads")),`Its turn isn't over: it's waiting on ${Ae(o)||"other agents"}.`}case"done:recent":return`Its last turn ended ${s}. ${n(t.harness)} doesn't record whether you've read it, so it shows as Done for 30 minutes.`;case"idle:quiet":return`Nothing has happened for ${Yn(e-t.lastActivityAt)}.`;case"done:process-idle":return`Its last turn ended ${s}, and ${n(t.harness)} says it's idle.`;case"idle:process-idle":return`${n(t.harness)} says it's idle, and nothing has happened for ${Yn(e-t.lastActivityAt)}.`}switch(t.status){case"asking":return"It stopped and is waiting for you.";case"working":{const o=nt(Math.max(0,e-t.lastActivityAt));if(!t.tool)return`Its turn is underway, and no tool call is open. Its newest record is ${o} old.`;const r=`${/^[aeiou]/i.test(a)?"An":"A"} ${a} call`;return Number.isFinite(t.tool.startedAt)?`${r} started ${nt(e-t.tool.startedAt)} ago and hasn't finished.`:`${r} is open and hasn't finished. Its newest record is ${o} old.`}case"delegating":return`Its turn isn't over: it's waiting on ${t.subagents?ct(t.subagents,"subagent","subagents"):"other agents"}.`;case"done":return`Its last turn ended ${s}, and you haven't looked at it since.`;case"error":return`Its last turn stopped on an API error ${s}.`;default:return`Nothing has happened since ${Yn(e-t.lastActivityAt)} ago, and you've seen its last turn.`}}const Be=t=>t?`<span class="add">+${k(t.added)}</span> <span class="del">−${k(t.removed)}</span>`:"—";function vc(t,e=n=>n){const n=ie(t),s=t.context?Rs(t.context.used,t.context.limit):null;return[t.org,t.project,vt(t.status).name,t.title,e(t.harness),t.gitBranch,ht(t.model),t.effort&&`${gn(t.effort)} effort`,s!=null&&`Context ${Math.round(s)}%`,n?.total&&`Plan ${n.done} of ${n.total}`].filter(Boolean).join(", ")}function kc(t){const e=ie(t);return!e?.total||t.status==="idle"?"":`<span class="row-plan" data-term="plan" data-rowtip ${kt(Fs(e),`${e.done} of ${e.total} steps`,e.current||"All steps done")}>${kn(e,t.status)}</span>`}function Ro(t,{sel:e=null,now:n=Date.now(),harnessName:s=a=>a}={}){const a=t.id===e,o=s(t.harness),r=wc(t,n),i=Ho(t),c=[t.gitBranch&&`<span>${Q("branch")}${l(t.gitBranch)}</span>`,t.worktree&&`<span>${Q("worktree")}${l(t.worktree)}</span>`,t.model&&`<span>${Q("model")}${l(ht(t.model))}${io(t.effort)}</span>`].filter(Boolean).join("");return`<li class="row" data-id="${l(t.id)}" data-st="${l(t.status)}" data-turn="${_s(t)}"${a?" data-current":""}>
|
|
66
|
+
<button type="button" class="row-main" data-act="select" data-key="${l(t.id)}" data-peek="${l(t.id)}" aria-label="${l(vc(t,s))}"${a?' aria-current="true"':""}>
|
|
67
|
+
<span class="row-where">${$s(t)}<span class="hmark row-h" title="${l(o)}">${l($n(t.harness,o))}</span></span>
|
|
68
|
+
${at(t.status)}
|
|
69
|
+
<span class="row-text"><span class="row-title">${l(t.title)}</span><span class="row-sub"><span class="row-now num" data-now="${l(t.id)}">${He(t,n)}</span>${r?`<span class="now-d ${r.cls}">${r.html}</span>`:""}</span></span>
|
|
70
|
+
<span class="nums"><span class="xtra">${l(k(t.tokens?.output))}</span><span class="xtra">${Be(t.lines)}</span></span>
|
|
71
|
+
${i?`<span class="row-why${i.mono?" mono":""}">${l(i.text)}</span>`:""}
|
|
72
|
+
<span class="row-meta">${c}</span>
|
|
73
|
+
${kc(t)}
|
|
74
|
+
</button>
|
|
75
|
+
</li>`}function xc(t){return t.kind!=="repo"?`<span class="g-l">${l(t.label)}</span>`:`<span class="g-l">${t.org?`<span class="g-c">${Q("org")}<span>${l(t.org)}</span></span>`:""}<span class="g-c" title="${l(t.path||t.label)}">${Q("folder")}<span>${l(Ne(t.label,t.org))}</span></span></span>`}function Mc(t){if(t.kind==="status")return"";const e=new Map;for(const s of t.items)e.set(s.status,(e.get(s.status)||0)+1);const n=Yt.filter(s=>e.get(s)).map(s=>`<span class="g-tally" data-st="${s}" title="${l(`${vt(s).name}: ${e.get(s)}`)}">${at(s)}<b>${e.get(s)}</b></span>`);return n.length?`<span class="g-tallies">${n.join("")}</span>`:""}function _o(t,e,{group:n="turn",shut:s=!1}={}){const a=mn(n,t),o=e?`<span class="hint"><kbd>N</kbd>next waiting</span><span class="g-cols">${ft("output","Output")}${ft("linesColumn","Lines")}</span>`:"";return`<h2 class="grp-h" data-k="${l(t.key)}" data-kind="${l(t.kind)}"><button type="button" class="grp-t" data-act="grp-toggle" data-key="${l(a)}" aria-expanded="${!s}" aria-label="${l(`${s?"Show":"Hide"} ${t.label}, ${t.items.length}`)}">${T.chev}<span class="g-flow">${xc(t)}<span class="n">${t.items.length}</span>${s?Mc(t):""}</span></button>${o}</h2>`}function Ac({arranged:t,sel:e=null,now:n=Date.now(),harnessName:s,group:a="turn",collapsed:o=new Set}){return t.groups.map((r,i)=>{const c=o.has(mn(a,r)),u=c?r.items.filter(d=>d.id===e):r.items;return`<section${c?" data-shut":""}>${_o(r,i===0,{group:a,shut:c})}<ul>${u.map(d=>Ro(d,{sel:e,now:n,harnessName:s})).join("")}</ul></section>`}).join("")}function Io({total:t=0,harnesses:e=[],q:n="",filtered:s=!1}){if(!t){const i=e.some(c=>c.detected)?"Nothing has run in the last 24 hours. Start a session and it shows up here as it works.":"Threadgauge reads Claude Code, Codex, and other coding agents on this machine. Install one or start a session, and it shows up here.";return`<div class="empty"><h2>No agents yet</h2><p>${l(i)}</p></div>`}const a=n&&!s?`Nothing matches "${n.trim()}".`:n?`Nothing matches "${n.trim()}" in this repo and status.`:"Nothing fits this repo and status.",o=s?'<p><button type="button" class="linkbtn" data-act="clear">Clear filters</button></p>':"";return`<div class="empty"><h2>No threads match</h2><p>${l(a)}</p>${o}</div>`}function Sc(t,{now:e=Date.now(),harnessName:n=s=>s}={}){const s=ie(t),a=t.tokens,o=_s(t)==="you"?bc(t):"",r=t.context?Rs(t.context.used,t.context.limit):null,i=t.context?r!=null?`${Math.round(r)}%, ${k(t.context.used)}/${k(t.context.limit)}`:`${k(t.context.used)} used`:"—",c=[n(t.harness),ht(t.model),t.effort&&`${gn(t.effort)} effort`].filter(Boolean).join(", ");return`<h4>${l(t.title)}</h4>
|
|
76
|
+
<div class="where pk-where">${dc(t)}</div>
|
|
77
|
+
<p class="pk-state" data-st="${l(t.status)}">${at(t.status)}<b>${l(vt(t.status).name)}</b><span>${l(t.status==="working"?It(e-ws(t)):xn(t,e))}</span></p>
|
|
78
|
+
<p class="pk-why">${l(Bo(t,e,n))}</p>
|
|
79
|
+
${o?`<p class="pk-ask">${l(o)}</p>`:""}
|
|
80
|
+
<p>${l(c)}</p>
|
|
81
|
+
<dl class="pk">
|
|
82
|
+
<dt>Context</dt><dd>${l(i)}</dd>
|
|
83
|
+
<dt>Output</dt><dd>${l(k(a?.output))}</dd>
|
|
84
|
+
<dt>Input</dt><dd>${l(k(a?a.input+a.cacheWrite:null))}</dd>
|
|
85
|
+
<dt>Cache reads</dt><dd>${l(k(a?.cacheRead))}</dd>
|
|
86
|
+
<dt>Lines</dt><dd>${Be(t.lines)}</dd>
|
|
87
|
+
<dt>Prompts</dt><dd>${l(t.prompts??"—")}</dd>
|
|
88
|
+
</dl>
|
|
89
|
+
${s?.total?`<p class="pk-plan">Plan ${s.done}/${s.total}${s.current?`: ${l(s.current)}`:""}</p>`:""}`}function jo(t){const e=Object.fromEntries(Yt.map(n=>[n,0]));for(const n of t)n.status in e&&e[n.status]++;return e}function Tc(t,e,n=null){return`${Yt.map(a=>{const o=vt(a).name,r=t[a]||0;return`<button type="button" class="lamp-btn" data-st="${a}" data-act="status" data-key="${a}" aria-pressed="${n===a}"${r?"":" data-zero"} data-tip="${l(`${o}: ${r}. Show only these.`)}" aria-label="${l(`${o}: ${r}`)}">${at(a)}<b>${r}</b><span class="word">${l(o)}</span></button>`}).join("")}<button type="button" class="lamp-btn total" data-act="status" data-key="" aria-pressed="false" data-tip="${l(`${e} threads in total. Show them all.`)}" aria-label="${l(`${e} threads in total`)}"><b>${e}</b><span class="word">${e===1?"Thread":"Threads"}</span></button>`}function Cc({shown:t,total:e,status:n=null,repoLabel:s="",q:a=""}){const o=String(a||"").trim(),i=[[n&&vt(n).name,s].filter(Boolean).join(" in "),o&&`matching "${o}"`].filter(Boolean).join(", ");return i?`${t} of ${e}: ${i}`:""}function Lc(t){let e=0,n=!1,s=0,a=0,o=!1;for(const i of t)i.tokens&&Number.isFinite(i.tokens.output)&&(e+=i.tokens.output,n=!0),i.lines&&(s+=i.lines.added||0,a+=i.lines.removed||0,o=!0);const r=jo(t);return{live:t.filter(i=>i.live).length,total:t.length,sts:Yt.map(i=>r[i]),out:e,outKnown:n,added:s,removed:a,linesKnown:o}}const Ec=t=>new Map([["live",t.live],["output",t.outKnown?t.out:null],["lines",t.linesKnown?`${t.added}|${t.removed}`:null]]);function zn(t,e,n,s,a,o){const r=n?gs[n.k](n,nc):"",i=r?kt(n,s):"";return`<span class="tot" data-k="${t}">${r?`<span class="i-wrap" data-term="${e}" ${i}>${r}</span>`:""}<span class="tot-t"><b>${a}</b>${ft(e,o,i)}</span></span>`}function Xn(t,{short:e=!1,bars:n=null}={}){const s=k(t.out);return[zn("live","liveAgents",{k:"waffle",run:t.live,total:t.total,sts:t.sts},`${t.live} of ${t.total} threads`,t.live,e?"Live":"Live agents"),zn("output","outputTotal",t.outKnown&&{k:"cols",v:t.out,base:1e3,...n?{bars:n}:{}},s,t.outKnown?l(s):"—",e?"Output":"Output tokens"),zn("lines","linesTotal",t.linesKnown&&{k:"pie",a:t.added,r:t.removed},`+${k(t.added)} −${k(t.removed)}`,t.linesKnown?Be({added:t.added,removed:t.removed}):"—",e?"Lines":"Lines changed")].join("")}const Po=3600*1e3,Oc=3,Nc=14,Hc=()=>({since:null,last:new Map,samples:[]});function Bc(t,e,n){const s=new Map,a=[];for(const r of e){const i=r.tokens?.output;if(!Number.isFinite(i))continue;s.set(r.id,i);const c=t.last.get(r.id);c!=null&&i>c&&a.push([r.id,i-c])}const o=t.samples.filter(r=>n-r.at<=Po);return a.length&&o.push({at:n,out:new Map(a)}),{since:t.since??n,last:s,samples:o}}function Rc(t,e,n,s=Nc){if(t.since==null)return null;const a=new Set(e),o=[],r=[];for(const c of t.samples){let u=0;for(const[d,p]of c.out)a.has(d)&&(u+=p);u&&(o.push(c.at),r.push(u))}if(o.length<Oc)return null;const i=Math.max(t.since,n-Po);return Qe(o,i,Math.max(n,i+1),r,s)}const Jn={300:["5-hour","5h"],10080:["Weekly","Week"]};function _c(t){return Jn[t]?{label:Jn[t][0],short:Jn[t][1]}:!Number.isFinite(t)||t<=0?{label:"Usage",short:""}:t%1440===0?{label:`${t/1440}-day`,short:`${t/1440}d`}:t%60===0?{label:`${t/60}-hour`,short:`${t/60}h`}:{label:`${t}-minute`,short:`${t}m`}}function Ic(t,e=Date.now()){const n=new Map;for(const s of t){const a=s.usageLimits;if(!a?.windows?.length)continue;const o=n.get(s.harness);(!o||(a.at||0)>(o.at||0))&&n.set(s.harness,a)}return[...n].map(([s,a])=>({harness:s,windows:a.windows.filter(o=>Number.isFinite(o.usedPercent)).map(o=>({id:o.id,pct:Math.round(Math.max(0,Math.min(100,o.usedPercent))),resetsAt:o.resetsAt??null,reset:Number.isFinite(o.resetsAt)&&o.resetsAt<=e,..._c(o.windowMinutes)}))})).filter(s=>s.windows.length)}const Fo=(t,e)=>Number.isFinite(t.resetsAt)&&t.resetsAt>e?`Resets in ${It(t.resetsAt-e)}`:"";function jc(t,e=Date.now()){const n=t.flatMap(s=>s.windows.map(a=>a.resetsAt)).filter(s=>Number.isFinite(s)&&s>e);return n.length?Math.min(...n):null}function Pc(t,{now:e=Date.now(),harnessName:n=s=>s}={}){return t.map(({harness:s,windows:a})=>{const o=n(s),r=a.map(i=>{if(i.reset){const d=`${o}'s ${i.label.toLowerCase()} limit has reset. It shows again with ${o}'s next reading.`;return`<span class="lim-i lim-reset" tabindex="0" data-tip="${l(d)}"><span class="v-d">${l(i.short?`${i.short} reset`:"Reset")}</span></span>`}const c={k:"gauge",pct:i.pct,level:yn(i.pct)};return`<span class="lim-i"><span class="i-wrap" data-term="limits" ${kt(c,`${o}, ${i.label.toLowerCase()} limit: ${i.pct}% used`,Fo(i,e))}>${Tt("limits",c,18)}</span><b class="num">${i.pct}%</b>${i.short?`<span class="v-d">${l(i.short)}</span>`:""}</span>`}).join("");return`<span class="lim"><span class="hmark" title="${l(o)}">${l($n(s,o))}</span>${r}</span>`}).join("")}function Fc(t,{now:e=Date.now(),harnessName:n=s=>s}={}){return t.length?`<h4 class="pf-sub">Usage limits</h4><ul class="hlist">${t.map(({harness:a,windows:o})=>{const r=o.map(i=>i.reset?`${i.label} reset`:[`${i.label} ${i.pct}%`,Fo(i,e).toLowerCase()].filter(Boolean).join(", ")).join("; ");return`<li><span>${l(n(a))}</span><span>${l(r)}</span></li>`}).join("")}</ul>`:""}const O={bootAt:null,rows:null,noted:null,lamps:null,lampsHTML:null,foot:null,footHTML:null,output:Hc()};function Dc(t,e=Date.now()){O.bootAt??=e,O.output=Bc(O.output,t,e)}function Wc(t,e=Date.now(),{quiet:n=!1}={}){t!==O.noted&&(O.noted=t,O.bootAt??=e,O.rows=mo(fo(O.bootAt,e)||n?null:O.rows,t,e))}const Do=(t,e,n,s)=>go(fo(O.bootAt,n.now)||n.quiet?null:t,e,n.now,s);function en(t,e,n,s,a="data-flash",o="--fd"){const r=$o(e,n,s);r!=null&&(t.setAttribute(a,""),t.style.setProperty(o,r))}const Wo=new WeakMap;function xa(t,e,n){t.removeAttribute("data-arrive"),t.removeAttribute("data-flash");const s=O.rows.arrived.get(e),a=O.rows.changed.get(e);s==null&&a==null||(s!=null&&en(t,s,n,Je,"data-arrive","--ad"),a!=null&&en(t,a,n,_t),Wo.set(t,{arrive:(s??0)+Je,flash:(a??0)+_t}))}function Uc(t,e){for(const n of t.querySelectorAll(".row[data-arrive], .row[data-flash]")){const s=Wo.get(n);(!s||s.arrive<=e)&&n.removeAttribute("data-arrive"),(!s||s.flash<=e)&&n.removeAttribute("data-flash")}}function nn(t,e,n){const s=t?.querySelector("[data-now]");s&&(s.dataset.t=xn(e,n))}const Zn=new WeakMap,qc=(t=[])=>t.map(e=>`${e.id}=${e.name}`).join("|"),Vc=(t,e)=>t.childElementCount===e.sections.size&&[...e.sections.values()].every(n=>n.el.parentNode===t);function Gc(t,e){const{arranged:n,now:s}=e;if(!n.groups.length){Zn.delete(t),Oe(t,Io({total:e.total,harnesses:e.harnesses,q:e.q,filtered:!!(e.view.status||e.view.repo)}));return}const a=e.view.group,o={sel:e.sel,now:s,harnessName:e.harnessName},r=n.groups.map((h,f)=>{const m=mn(a,h),y=e.collapsed.has(m),$=(y?h.items.filter(x=>x.id===e.sel):h.items).map(x=>({key:x.id,sig:`${x.id===e.sel?1:0}${yo(x)}`,html:()=>Ro(x,o),s:x}));return{key:m,shut:y,head:_o(h,f===0,{group:a,shut:y}),items:$}}),i=qc(e.harnesses);let c=Zn.get(t);if(!c||c.harness!==i||!Vc(t,c)){t.innerHTML=Ac({arranged:n,sel:e.sel,now:s,harnessName:e.harnessName,group:a,collapsed:e.collapsed});const h=r.map((f,m)=>{const y=t.children[m],$=y.lastElementChild,x=f.items.map((E,B)=>{const N=$.children[B];return nn(N,E.s,s),O.rows&&xa(N,E.key,s),[E.key,{el:N,sig:E.sig}]});return[f.key,{el:y,head:f.head,ul:$,rows:new Map(x)}]});Zn.set(t,{harness:i,sections:new Map(h)});return}const u=new Set(r.map(h=>h.key));for(const[h,f]of c.sections)u.has(h)||f.el.remove();const d=new Map,p=[];r.forEach((h,f)=>{let m=c.sections.get(h.key);if(m)m.head!==h.head&&(m.el.firstElementChild.replaceWith(...wo([h.head])),m.head=h.head);else{const $=document.createElement("section");$.innerHTML=`${h.head}<ul></ul>`,m={el:$,head:h.head,ul:$.lastElementChild,rows:new Map}}h.shut?m.el.setAttribute("data-shut",""):m.el.removeAttribute("data-shut");const y=t.children[f]??null;if(y!==m.el&&!bo(t,m.el,y))for(const[$,x]of m.rows)p.push([$,x.el]);d.set(h.key,m)});for(const h of r){const f=d.get(h.key),m=vo(f.ul,f.rows,h.items);f.rows=m.drawn;const y=new Map(h.items.map($=>[$.key,$.s]));for(const[$,x]of m.added)nn(x,y.get($),s);p.push(...m.added,...m.restarted)}if(c.sections=d,O.rows)for(const[h,f]of p)f.isConnected&&xa(f,h,s)}function Kc(t){t.removeAttribute("data-tight"),new Set([...t.children].map(n=>n.offsetTop)).size>1&&t.setAttribute("data-tight","")}const Uo=t=>String(t).replace(/\d/g,"0"),qo=t=>`${t.mode}|${t.w}|${t.lw}|${t.table}`;function Yc(t,e,{live:n=!1}={}){const{inRepo:s}=e.arranged,a=jo(s),o=Tc(a,s.length,e.view.status),r=new Map([...Object.entries(a),["",s.length]]);if(O.lamps=Do(O.lamps,r,e,`${e.view.repo}|${e.q}`),n&&o===O.lampsHTML&&t.firstChild)return;O.lampsHTML=o,t.innerHTML=o;for(const[c,u]of O.lamps.at){const d=t.querySelector(`[data-key="${CSS.escape(c)}"]`);d&&en(d,u,e.now,_t)}const i=`${qo(e.layout)}|${Uo(o)}`;n&&i===O.lampsFit||(Kc(t),O.lampsFit=i)}function zc(t,e){const n=Cc({shown:e.arranged.visible.length,total:e.total,status:e.view.status,repoLabel:e.repoLabel,q:e.q});t.hidden=!n,Oe(t,n?`<span>${l(n)}</span>${e.view.status||e.view.repo?'<button type="button" class="linkbtn" data-act="clear">Clear filters</button>':""}`:"")}function Xc(t,e){Oe(t,Pc(e.limits||[],{now:e.now,harnessName:e.harnessName}))}const Jc=8,Ma=t=>t.scrollWidth>t.clientWidth+1||[...t.querySelectorAll(".tot")].some(e=>e.scrollWidth>e.clientWidth+Jc);function Zc(t,e,{live:n=!1}={}){const{visible:s}=e.arranged,a=Lc(s),o=Rc(O.output,s.map(d=>d.id),e.now),r=e.layout.mode==="side"&&e.layout.lw<300,i=Xn(a,{short:r,bars:o});if(O.foot=Do(O.foot,Ec(a),e,`${e.view.repo}|${e.q}|${e.view.status}`),n&&i===O.footHTML&&t.firstChild)return;O.footHTML=i;const c=[a.live,a.outKnown?k(a.out):"",a.linesKnown?`${k(a.added)} ${k(a.removed)}`:""],u=`${qo(e.layout)}|${r}|${Uo(c.join("|"))}`;if(n&&u===O.footFit?.key)t.innerHTML=O.footFit.short?Xn(a,{short:!0,bars:o}):i;else{t.removeAttribute("data-bare"),t.innerHTML=i;const d=!r&&Ma(t);d&&(t.innerHTML=Xn(a,{short:!0,bars:o})),Ma(t)&&t.setAttribute("data-bare",""),O.footFit={key:u,short:r||d}}for(const[d,p]of O.foot.at){const h=t.querySelector(`.tot[data-k="${d}"]`);h&&en(h,p,e.now,_t)}}function Qc(t,e,n){Uc(t,e);for(const s of t.querySelectorAll("[data-now], [data-since], [data-ago]")){const{dataset:a}=s;if(a.now!=null){const r=n(a.now);if(!r)continue;const i=xn(r,e);if(a.t===i)continue;a.t=i,s.innerHTML=He(r,e);continue}const o=a.since!=null?nt(e-Number(a.since)):$t(e-Number(a.ago));s.textContent!==o&&(s.textContent=o)}}const td=1e4;function ed(t,e,n){if(!t.length)return null;const s=t.indexOf(e),a=s<0?0:Math.max(0,Math.min(t.length-1,s+n));return t[a]===e?null:t[a]}function nd(t,e,n){const s=Qi(t);if(!s.length)return{id:null,memo:e};const a=n-e.at>td?0:e.index;return{id:s[a%s.length].id,memo:{index:a+1,at:n}}}const sd=Object.freeze({index:0,at:-1/0});function Vo(t,e){if(!e||!t?.context?.limit||!ui.has(t.status))return null;const n=(e.compactions||[]).at(-1),s=n?(e.history||[]).filter(i=>i.at>n.at):e.history||[];if(s.length<3)return null;const a=s[0],o=s.at(-1),r=(o.context-a.context)/Math.max(1,o.at-a.at);return r<=0?null:(t.context.limit-t.context.used)/r}function ad(t,e){const n=Vo(t,e);return n==null?"":`Room left: about ${It(n)}`}const Qn=(t,e)=>String(t||"").localeCompare(String(e||""),void 0,{sensitivity:"base"}),Ht=t=>(e,n)=>t(e)-t(n),Ue=t=>Number.isFinite(t)?t:-1,Go=t=>t.tokens?t.tokens.input+t.tokens.cacheWrite:null,od=t=>{const e=ie(t);return e?.total?e.done/e.total:-1},Ko=Object.freeze([{key:"repo",label:"Where",cls:"l where-col",first:1,compare:(t,e)=>(t.org?0:1)-(e.org?0:1)||Qn(t.org,e.org)||Qn(t.project,e.project)},{key:"title",label:"Thread",cls:"l",first:1,compare:(t,e)=>Qn(t.title,e.title)},{key:"plan",label:"Plan",first:-1,compare:Ht(od)},{key:"lines",label:"Lines",first:-1,compare:Ht(t=>t.lines?t.lines.added+t.lines.removed:-1)},{key:"ctx",label:"Context",first:-1,compare:Ht(t=>t.context?.limit?t.context.used/t.context.limit:-1)},{key:"input",label:"Input",first:-1,compare:Ht(t=>Ue(Go(t)))},{key:"output",label:"Output",first:-1,compare:Ht(t=>Ue(t.tokens?.output))},{key:"cache",label:"Cache reads",first:-1,compare:Ht(t=>Ue(t.tokens?.cacheRead))},{key:"prompts",label:"Prompts",first:-1,compare:Ht(t=>Ue(t.prompts))},{key:"last",label:"Last active",first:-1,compare:Ht(t=>t.lastActivityAt)}]),Ds=t=>Ko.find(e=>e.key===t)||null,An=Object.freeze({key:"last",dir:-1});function oe(t){return t&&typeof t=="object"&&Ds(t.key)&&(t.dir===1||t.dir===-1)?{key:t.key,dir:t.dir}:{...An}}function rd(t,e){const n=Ds(e);if(!n)return oe(t);const s=oe(t);return s.key===e?{key:e,dir:-s.dir}:{key:e,dir:n.first}}function Yo(t,e){const{key:n,dir:s}=oe(e),a=Ds(n).compare;return[...t].sort((o,r)=>a(o,r)*s||r.lastActivityAt-o.lastActivityAt)}function id(t){const e=ie(t);return e?.total?`<span class="tc-ticks" data-term="plan" data-rowtip ${kt(Fs(e),`${e.done} of ${e.total} steps`,e.current||"All steps done")}>${kn(e,t.status,"compact")}</span><span class="ratio"><b class="v-b">${e.done}</b><span class="v-d">/${e.total}</span></span>`:"—"}function ld(t){const e=t.lines;if(!e)return"—";const n={k:"split",sec:"files",a:e.added,r:e.removed};return`<span class="row-lines">${Be(e)}<span class="i-wrap" data-term="lines" data-rowtip ${kt(n,`+${k(e.added)} −${k(e.removed)}`)}>${Tt("files",n,20)}</span></span>`}function cd(t,e=null){const n=t.context,s=n?Rs(n.used,n.limit):null;if(s==null)return'<span class="row-ctx"><span class="pct">—</span></span>';const a=yn(s),o=`${k(n.used)} of ${k(n.limit)}`,r={k:"gauge",sec:"context",pct:s,level:a},i=xo(t.contextHistory?.map(h=>({context:h})),n.limit,{used:n.used}),c={...r,sec:"contextHistory",...i?{hist:i}:{}},u=ad(t,e),d=h=>`<span class="i-wrap" data-term="context" data-rowtip ${kt(h,o,u)}>${Tt(h.sec,h,20)}</span>`;return`<span class="row-ctx"${a==="full"?" data-full":a==="high"?" data-high":""}><span class="pct">${Math.round(s)}%</span>${d(r)}${d(c)}</span>`}function dd(t,{now:e=Date.now(),detail:n=null}={}){return{plan:id(t),lines:ld(t),ctx:cd(t,n),input:l(k(Go(t))),output:l(k(t.tokens?.output)),cache:l(k(t.tokens?.cacheRead)),prompts:l(t.prompts??"—"),last:l($t(e-t.lastActivityAt))}}function zo(t,{now:e=Date.now(),detail:n=null}={}){const s=dd(t,{now:e,detail:n}),a=l(t.id);return`<tr data-id="${a}" data-st="${l(t.status)}"${t.older?" data-older":""} data-act="select" data-key="${a}">
|
|
90
|
+
<td class="l where-col"><div class="where">${$s(t)}</div></td>
|
|
91
|
+
<td class="l tc-thread"><button type="button" class="ttl" data-act="select" data-key="${a}" title="${l(vt(t.status).name)}"><span class="where t-where">${$s(t)}</span>${at(t.status)}<span class="tn">${l(t.title)}</span><span class="row-now num" data-now="${a}">${He(t,e)}</span></button></td>
|
|
92
|
+
<td>${s.plan}</td>
|
|
93
|
+
<td>${s.lines}</td>
|
|
94
|
+
<td>${s.ctx}</td>
|
|
95
|
+
<td>${s.input}</td>
|
|
96
|
+
<td>${s.output}</td>
|
|
97
|
+
<td>${s.cache}</td>
|
|
98
|
+
<td>${s.prompts}</td>
|
|
99
|
+
<td data-ago="${Number(t.lastActivityAt)||0}">${s.last}</td>
|
|
100
|
+
</tr>`}function Xo(t){const{key:e,dir:n}=oe(t);return Ko.map(s=>`<th${s.cls?` class="${s.cls}"`:""}${s.key===e?` aria-sort="${n>0?"ascending":"descending"}"`:""}><button type="button" data-act="table-sort" data-key="${s.key}">${l(s.label)}</button></th>`).join("")}function Jo(t,e=n=>n){const n=[...new Set(t.filter(s=>s.older&&!s.tokens).map(s=>e(s.harness)))];return n.length?`${Ae(n)} did not record figures for older threads, so they show —.`:""}function ud(t,{sort:e=An,now:n=Date.now(),harnessName:s=o=>o,detailOf:a=()=>null}={}){const o=Yo(t,e).map(i=>zo(i,{now:n,detail:a(i.id)})).join(""),r=Jo(t,s);return`<div class="tbl-wrap"><table aria-label="All threads"><thead><tr>${Xo(e)}</tr></thead><tbody>${o}</tbody></table>${r?`<p class="unrec">${l(r)}</p>`:""}</div>`}const bs="threadgauge:view",Zo=[{key:"turn",label:"Turn"},...Zi],Qo=[aa[0],{key:"wait",label:"Longest wait"},...aa.slice(1)],tr=200,fe=Object.freeze({group:"turn",sort:"status",repo:"",status:null,listWidth:null,listShut:!1,conversation:!1,font:cs,mono:ds,collapsed:Object.freeze([]),tableSort:An});function er(t){try{const e=JSON.parse(t||"{}");return e&&typeof e=="object"&&!Array.isArray(e)?e:{}}catch{return{}}}function pd(t){const e=er(t),n=(s,a,o)=>s.some(r=>r.key===a)?a:o;return{group:n(Zo,e.group,fe.group),sort:n(Qo,e.sort,fe.sort),repo:typeof e.repo=="string"?e.repo:"",status:Ja.includes(e.status)?e.status:null,listWidth:Number.isFinite(e.listWidth)?Math.round(e.listWidth):null,listShut:e.listShut===!0,conversation:e.conversation===!0,font:n($e,e.font,fe.font),mono:n(ye,e.mono,fe.mono),collapsed:Array.isArray(e.collapsed)?e.collapsed.filter(s=>typeof s=="string").slice(0,tr):[],tableSort:oe(e.tableSort)}}function hd(t,e=null){const{group:n,sort:s,repo:a,status:o,listWidth:r,listShut:i,conversation:c=!1,font:u,mono:d,collapsed:p=[],tableSort:h}=t;return JSON.stringify({...er(e),group:n,sort:s,repo:a,status:o,listWidth:r,listShut:i,conversation:c,font:u,mono:d,collapsed:[...p].slice(0,tr),tableSort:oe(h)})}function fd(t){try{return pd(t.getItem(bs))}catch{return{...fe,collapsed:[],tableSort:{...An}}}}function md(t,e){try{t.setItem(bs,hd(e,t.getItem(bs)))}catch{}}const gd=[["N","Next thread waiting on you"],["J","Next thread in the list"],["K","Previous thread in the list"],["Enter","Open the thread in its harness"],["Esc","Step back"],["P","Screenshot"],["?","Settings"],["[","Collapse or show the threads"],["R","Open or close the conversation"],["Ctrl K","Search threads and actions"],["/","Search threads"]],$d={live:"Live",connecting:"Connecting",offline:"Offline"},sn=t=>$d[t]||t;function yd(t){return t.error?{cls:"e",text:t.error}:t.detected?{cls:"w",text:"Watching"}:{cls:"x",text:"Not found"}}function wd(t,e){const n=e.filter(r=>r.detected&&!r.error).map(r=>r.name),s=e.filter(r=>!r.detected).map(r=>r.name),a=e.filter(r=>r.detected&&r.error).map(r=>`${r.name}: ${r.error}`),o=[`${sn(t)}.`,`Watching ${Ae(n)||"nothing"}.`,`Not found: ${Ae(s)||"none"}.`];return a.length&&o.push(`${a.join(". ")}.`),o.join(" ")}const Re=t=>`<span class="pf-ico" aria-hidden="true">${xl[t]}</span>`,vs=(t,e,n,s)=>`<div class="chips" role="group" aria-label="${l(s)}">${e.map(a=>`<button type="button" class="chip" data-act="${t}" data-key="${l(a.key)}" aria-pressed="${n===a.key}">${l(a.label)}</button>`).join("")}</div>`;function bd(t,e){const{total:n,orgs:s,loose:a}=Is(t,e),o=i=>`<option value="${l(i.key)}"${i.key===e?" selected":""}>${l(Ne(i.label,i.org))} (${i.count})</option>`,r=s.map(({org:i,repos:c})=>`<optgroup label="${l(i)}">${c.map(o).join("")}</optgroup>`).join("");return`<select class="sel" data-change="repo"><option value=""${e?"":" selected"}>All repos (${n})</option>${r}${a.map(o).join("")}</select>`}function vd({view:t,sessions:e}){const n=t.repo?Is(e,t.repo):null,s=n?[...n.orgs.flatMap(o=>o.repos),...n.loose].find(o=>o.key===t.repo)?.label:"",a=[t.status&&vt(t.status).name,s].filter(Boolean).join(" in ");return`<section class="pf-g" data-g="threads">
|
|
101
|
+
<h3>${Re("threads")}Threads</h3>
|
|
102
|
+
<div class="pf-row pf-stack"><span class="pf-l">Group by</span>${vs("group",Zo,t.group,"Group threads by")}</div>
|
|
103
|
+
<label class="pf-row"><span class="pf-l">Sort</span><select class="sel" data-change="sort">${Qo.map(o=>`<option value="${o.key}"${t.sort===o.key?" selected":""}>${l(o.label)}</option>`).join("")}</select></label>
|
|
104
|
+
<label class="pf-row"><span class="pf-l">Repo</span>${bd(e,t.repo)}</label>
|
|
105
|
+
${a?`<div class="pf-row"><span class="pf-l pf-quiet">Showing ${l(a)}</span><button type="button" class="linkbtn" data-act="clear">Clear filters</button></div>`:""}
|
|
106
|
+
</section>`}function kd({fonts:t}){const e=$e.find(s=>s.key===t.sans)||$e[0],n=ye.find(s=>s.key===t.mono)||ye[0];return`<section class="pf-g" data-g="look">
|
|
107
|
+
<h3>${Re("look")}Look</h3>
|
|
108
|
+
<div class="pf-row pf-stack"><span class="pf-l">Font</span>${vs("font-sans",$e,e.key,"Font")}<p class="pf-hint">${l(e.note)}</p></div>
|
|
109
|
+
<div class="pf-row pf-stack"><span class="pf-l">Mono font</span>${vs("font-mono",ye,n.key,"Mono font")}<p class="pf-hint">${l(n.note)}</p></div>
|
|
110
|
+
</section>`}function xd({connection:t,harnesses:e,limits:n=[],now:s=Date.now()}){const a=e.map(o=>{const r=yd(o);return`<li><span>${l(o.name)}</span><span class="${r.cls}">${l(r.text)}</span></li>`}).join("");return`<section class="pf-g" data-g="connection">
|
|
111
|
+
<h3>${Re("connection")}Connection</h3>
|
|
112
|
+
<p class="pf-quiet">${l(sn(t))}: reading this computer's agent files.</p>
|
|
113
|
+
${a?`<ul class="hlist">${a}</ul>`:""}
|
|
114
|
+
${Fc(n,{now:s,harnessName:o=>e.find(r=>r.id===o)?.name||o})}
|
|
115
|
+
</section>`}const Aa=t=>new Date(t*1e3).toLocaleDateString(void 0,{year:"numeric",month:"long",day:"numeric"});function Md(t,{previewFree:e=!1}={}){if(e)return"No key entered";const n=t?.license?.paidThrough,s=!!t?.pro;return s&&n?`On, paid through ${Aa(n)}`:s?"On in this development build":n?`Ended, paid through ${Aa(n)}`:"No key entered"}function Ad(t=null,{previewFree:e=!1}={}){const n=!!t?.license&&!e;return`<div class="pf-row pf-stack" data-row="license"><div class="pf-line"><span class="pf-l">Threadgauge Pro</span><button type="button" class="btn" data-act="license">${Q("key",14)}${n?"License":"Enter a key"}</button></div><p class="pf-quiet">${l(Md(t,{previewFree:e}))}</p><p class="pf-hint">Threadgauge Pro arrives with Threadbare. Until then, everything here is free.</p></div>`}function Sd(t){return t?`<div class="pf-row" data-row="threadnauts"><span class="pf-l">Threadnauts</span><a class="btn" href="${l(t)}" target="threadnauts">Open colony</a></div>`:""}function Td({threadnauts:t,entitlements:e=null,previewFree:n=!1}){return`<section class="pf-g" data-g="threadcrumbs">
|
|
116
|
+
<h3>${Re("threadcrumbs")}Threadcrumbs</h3>
|
|
117
|
+
${Ad(e,{previewFree:n})}
|
|
118
|
+
${Sd(t)}
|
|
119
|
+
</section>`}function Cd(){return`<section class="pf-g" data-g="keys">
|
|
120
|
+
<h3>${Re("keys")}Keys</h3>
|
|
121
|
+
<div class="keys">${gd.map(([t,e])=>`<kbd>${l(t)}</kbd><span>${l(e)}</span>`).join("")}</div>
|
|
122
|
+
</section>`}function Ld(t){return`<header class="pf-h"><h2>Settings</h2><button type="button" class="ib" data-act="prefs-close" aria-label="Close settings (Esc)">${T.x}</button></header>
|
|
123
|
+
<div class="pf-body"><div class="pf-cols">
|
|
124
|
+
${vd(t)}
|
|
125
|
+
${kd(t)}
|
|
126
|
+
${xd(t)}
|
|
127
|
+
${Td(t)}
|
|
128
|
+
${Cd()}
|
|
129
|
+
</div></div>`}const Ed=500;function Od({draw:t,hidden:e,clock:n,frame:s,setTimer:a,gap:o=Ed}){let r=!1,i=!1,c=-1/0,u=!1,d=!1;function p(){if(d=!1,!r)return;if(e()){i=!0;return}const f=i;r=!1,i=!1,c=n(),t({catchUp:f})}function h(){if(!r||u||d)return;if(e()){i=!0;return}const f=c+o-n();if(f>0){u=!0,a(()=>{u=!1,h()},f);return}d=!0,s(p)}return{request(){r=!0,h()},resume:h,pending:()=>r}}const Nd=1e3,Hd=6e4,Bd=3e4,Rd=20,_d="Threadgauge can only read older Claude Code threads in full so far.";function Id({api:t,previewFree:e=!1,clock:n=()=>Date.now(),timers:s=globalThis,hidden:a=()=>!1}={}){const o={connection:"connecting",harnesses:[],received:!1,olderLoaded:!1,entitlements:null,threadnauts:null,previewFree:e},r=new Set,i=v=>{for(const H of r)H(v)};let c=new Map,u=new Map;const d=new Map;let p=new Map,h=[],f=0,m={key:"",value:null};function y(){const v=new Map(c);for(const[H,Dt]of u){if(v.has(H))continue;const ue=d.get(H);v.set(H,ue&&ue.lastActivityAt>=Dt.lastActivityAt?ue:Dt)}p=v,h=[...v.values()],f++}const $=v=>o.harnesses.find(H=>H.id===v)?.name||v;async function x(){const v=await t.fetchHistory();if(!v){o.olderLoaded||(o.olderLoaded=!0,i("sessions"));return}o.olderLoaded=!0,u=new Map(v.map(H=>[H.id,H]));for(const H of d.keys())u.has(H)||d.delete(H);y(),i("sessions"),Nt()}const E=new Map;let B=null,N=null,C=!1,q=!1,L=null,X=0,Et=!1;function Ft(v,H){E.delete(v),E.set(v,{...H,at:n()}),E.size>Rd&&E.delete(E.keys().next().value)}function Ot(){if(!B)return;if(a()){Et=!0;return}if(C){q=!0;return}if(L)return;const v=X+Nd-n();if(v>0){L=s.setTimeout(()=>{L=null,Ot()},v);return}Fe()}async function Fe(){const v=B;C=!0,X=n();try{const H=await t.fetchDetail(v);H?.session&&u.has(v)&&!c.has(v)&&(d.set(v,{...H.session,older:!0}),y(),i("sessions")),H?Ft(v,{found:H,error:"",gone:!1}):u.has(v)?Ft(v,{found:null,error:_d,gone:!1}):Ft(v,{found:null,error:"",gone:!0})}catch(H){Ft(v,{found:E.get(v)?.found??null,error:`Couldn't read this thread: ${H.message}`,gone:!1})}finally{C=!1,i("detail"),q&&(q=!1,Ot())}}function Nt(){if(!B)return;const v=p.get(B);v!==N&&(N=v,v&&Ot())}function li(v){v!==B&&(B=v||null,N=B?p.get(B):null,X=0,Et=!1,L&&s.clearTimeout(L),L=null,Ot())}function ci(){Et&&(Et=!1,Ot())}function ea(v){o.entitlements=v,i("entitlements")}async function na(){const v=await t.fetchEntitlements();return v&&ea(v),v}async function Rn(){const v=await t.findThreadnauts()||null;v!==o.threadnauts&&(o.threadnauts=v,i("threadnauts"))}function di(){t.connectLive({onChange:({sessions:v,harnesses:H})=>{const Dt=[...c.keys()].some(ue=>!v.has(ue));c=new Map(v),o.harnesses=H||[],y(),o.received=!0,i("sessions"),Nt(),Dt&&x()},onConnection:v=>{v!==o.connection&&(o.connection=v,i("connection"))}}),na(),x(),Rn(),s.setInterval(Rn,Bd),s.setInterval(x,Hd)}return{state:o,start:di,on(v){return r.add(v),()=>r.delete(v)},list:()=>h,get:v=>p.get(v)||null,listed:v=>p.has(v),arranged(v,H=""){const Dt=`${f}|${v.group}|${v.sort}|${v.repo}|${v.status}|${H}`;return m.key!==Dt&&(m={key:Dt,value:il(h,{...v,q:H,harnessName:$})}),m.value},open:li,resume:ci,detail:v=>E.get(v)||null,pro:()=>!e&&!!o.entitlements?.pro,harnessName:$,setEntitlements:ea,refreshEntitlements:na,checkThreadnauts:Rn,refreshOlder:x}}const Sa=["where","tight","bare","lean","scroll"],nr=(t,e)=>{const n=getComputedStyle(t);return e.getBoundingClientRect().width>t.clientWidth-parseFloat(n.paddingLeft)-parseFloat(n.paddingRight)+.5};function an(t){const e=t.querySelector(".tbl-wrap"),n=e?.querySelector("table");if(n){for(const s of Sa)e.removeAttribute(`data-fit-${s}`);for(const s of Sa){if(!nr(e,n))return;e.setAttribute(`data-fit-${s}`,"")}}}function jd(t){const e=t.querySelector(".tbl-wrap"),n=e?.querySelector("table");n&&!e.hasAttribute("data-fit-scroll")&&nr(e,n)&&an(t)}const ts=new WeakMap;function Pd(t,e,{live:n=!1}={}){const s=e.arranged.visible;if(!s.length){ts.delete(t),t.innerHTML=Io({total:e.total,harnesses:e.harnesses,q:e.q,filtered:!!(e.view.status||e.view.repo)});return}const a=e.view.tableSort,o=Yo(s,a).map(h=>{const f=e.detailOf(h.id);return{key:h.id,sig:`${Pl(f)}|${yo(h)}`,html:()=>zo(h,{now:e.now,detail:f}),s:h}}),r=Xo(a),i=Jo(s,e.harnessName);let c=ts.get(t);if(!c||c.wrap.parentNode!==t||t.childElementCount!==1){t.innerHTML=ud(s,{sort:a,now:e.now,harnessName:e.harnessName,detailOf:e.detailOf});const h=t.firstElementChild,f=h.querySelector("tbody"),m=o.map((y,$)=>(nn(f.children[$],y.s,e.now),[y.key,{el:f.children[$],sig:y.sig}]));c={wrap:h,head:r,note:i,row:h.querySelector("thead tr"),body:f,rows:new Map(m)},ts.set(t,c),an(t);return}r!==c.head&&(c.row.innerHTML=r,c.head=r);const u=c.rows,d=vo(c.body,c.rows,o);if(c.rows=d.drawn,d.added.length){const h=new Map(o.map(f=>[f.key,f.s]));for(const[f,m]of d.added)nn(m,h.get(f),e.now)}i!==c.note&&(c.wrap.querySelector(".unrec")?.remove(),i&&c.wrap.insertAdjacentHTML("beforeend",`<p class="unrec">${l(i)}</p>`),c.note=i);const p=u.size!==c.rows.size||[...c.rows.keys()].some(h=>!u.has(h));(!n||p)&&an(t)}const on=[{id:"vscode",name:"VS Code"},{id:"cursor",name:"Cursor"},{id:"windsurf",name:"Windsurf"},{id:"zed",name:"Zed"},{id:"system",name:"the default app"}],sr="threadgauge:editor",Ta=()=>navigator.userAgentData?.platform||navigator.platform||"",ar=/mac/i.test(Ta())?"Finder":/win/i.test(Ta())?"Explorer":"Files";function or(){try{const t=localStorage.getItem(sr);return on.some(e=>e.id===t)?t:"vscode"}catch{return"vscode"}}function Fd(t){try{localStorage.setItem(sr,t)}catch{}}const Dd=t=>on.find(e=>e.id===t)?.name||"VS Code",Wd=Object.freeze({top:14,left:36,right:8,rug:24,axis:16}),Ca=(t,e,n)=>Math.max(e,Math.min(n,t)),G=t=>t.toFixed(1);function Ud(t){return t.cols===1?t.short?84:112:t.span?t.h>=1300?210:t.h>=1e3?160:120:88}function qd(t){if(!t.length)return null;const e=o=>o>=90?"x":o>=70?"h":"f",n=[];let s=e(t[0].v),a=t[0].x;for(let o=1;o<t.length;o++){const r=t[o-1],i=t[o],c=[70,90].filter(u=>r.v<u&&i.v>=u||r.v>=u&&i.v<u);i.v<r.v&&c.reverse();for(const u of c){const d=i.v===r.v?r.x:r.x+(u-r.v)/(i.v-r.v)*(i.x-r.x);n.push({x0:a,x1:d,cls:s}),a=d,s=i.v>=r.v?e(u):e(u-1e-6)}}return n.push({x0:a,x1:t.at(-1).x,cls:s}),n}function Vd(t,e){let n=0,s=t.length-1;for(;n<s;){const a=n+s>>1;t[a].at<e?n=a+1:s=a}return n>0&&e-t[n-1].at<t[n].at-e?n-1:n}function Gd(t,{W:e,plotH:n,limit:s=0}){const a=t?.history||[];if(!a.length)return null;const{top:o,left:r,right:i,rug:c,axis:u}=Wd,d=t.activity||[],p=t.prompts||[],h=t.errors||[],f=t.compactions||[],m=[...a.map(N=>N.at),...d.map(N=>N.startedAt).filter(Boolean),...p.map(N=>N.at)],y=Math.min(...m),$=Math.max(y+1,...m,...h.map(N=>N.at||0)),x=Math.max(...a.map(N=>N.context)),E=el(Math.max(s,x)),B=e-r-i;return{W:e,H:o+n+c+u,plotH:n,top:o,left:r,right:i,rug:c,base:o+n,t0:y,t1:$,yTop:E,peak:x,limit:s,pts:a,calls:d,prompts:p,errors:h,comps:f,x:N=>r+(Ca(N,y,$)-y)/($-y)*B,y:N=>o+n-Math.min(N,E)/E*n,timeAt:N=>y+(Ca(N,r,e-i)-r)/B*($-y)}}function Kd(t,{ping:e=!1}={}){const{pts:n,x:s,y:a,left:o,right:r,top:i,base:c,W:u,H:d,limit:p,comps:h}=t,f=n.map((C,q)=>`${q?"L":"M"}${G(s(C.at))},${G(a(C.context))}`).join(""),m=`${f}L${G(s(n.at(-1).at))},${c}L${G(s(n[0].at))},${c}Z`;let y="";const $=p?qd(n.map(C=>({x:s(C.at),v:C.context/p*100}))):null;if($){const C=u-o-r,q=(L,X)=>`<stop offset="${((L-o)/C).toFixed(4)}" class="c-stop ${X}"/>`;y+=`<defs><linearGradient id="ctx-level" gradientUnits="userSpaceOnUse" x1="${o}" y1="0" x2="${u-r}" y2="0">${$.map(L=>q(L.x0,L.cls)+q(L.x1,L.cls)).join("")}</linearGradient></defs>`}for(const C of[0,t.yTop/2,t.yTop])y+=`<line class="c-grid" x1="${o}" x2="${u-r}" y1="${G(a(C))}" y2="${G(a(C))}"/><text class="c-t" x="${o-6}" y="${G(a(C)+4)}" text-anchor="end">${l(k(C))}</text>`;y+=`<path class="c-area${$?" lvl":""}" d="${m}"/>`,p&&(y+=`<line class="c-limit" x1="${o}" x2="${u-r}" y1="${G(a(p))}" y2="${G(a(p))}"/><text class="c-t" x="${o+4}" y="${G(a(p)-4)}">${l(`Limit ${k(p)}`)}</text>`);for(const C of h){if(C.at<t.t0||C.at>t.t1)continue;const q=G(s(C.at));y+=`<line class="c-comp" x1="${q}" x2="${q}" y1="${i}" y2="${c}"/><path class="c-compm" d="M${q},${i-5}l4,4-4,4-4-4z"/>`}y+=`<path class="c-line${$?" lvl":""}" d="${f}"/>`;const x=c+5;for(const C of t.calls){if(!C.startedAt)continue;const q=G(s(C.startedAt));y+=`<line class="c-tick${C.error?" fail":C.running?" run":""}" x1="${q}" x2="${q}" y1="${x}" y2="${x+(C.error?10:7)}"/>`}for(const C of t.prompts)y+=`<path class="c-prompt" d="M${G(s(C.at))},${x+11}l4,6h-8z"/>`;for(const C of t.errors)C.at&&(y+=`<circle class="c-errm" cx="${G(s(C.at))}" cy="${x+14}" r="2"/>`);y+=`<text class="c-t" x="${o}" y="${d-3}">${l(st(t.t0))}</text><text class="c-t" x="${u-r}" y="${d-3}" text-anchor="end">${l(st(t.t1))}</text>`;const E=n.at(-1),B=G(s(E.at)),N=G(a(E.context));return e&&(y+=`<circle class="c-ping" cx="${B}" cy="${N}" r="3"/>`),y+=`<circle class="c-end" cx="${B}" cy="${N}" r="3"/>`,y+=`<line class="c-mark" data-m x1="0" x2="0" y1="${i}" y2="${c+t.rug-4}" visibility="hidden"/><line class="c-cross" data-c x1="0" x2="0" y1="${i}" y2="${c+t.rug-4}" visibility="hidden"/><circle class="c-dot" data-d r="4" visibility="hidden"/>`,y}function Yd(t){const e=t.pts.at(-1),n=t.comps.length?`Compacted ${t.comps.length===1?"once":`${t.comps.length} times`}`:"never compacted";return`Context over ${ct(t.pts.length,"reply","replies")}: ${k(e.context)}${t.limit?` of ${k(t.limit)}`:""} now, peak ${k(t.peak)}, ${n}. Use the left and right arrow keys to read each point.`}function zd(t,{agent:e=!1}={}){return[e?`<span>${ft("history","Context over time")}</span>`:"",'<span><i class="k-tick"></i>Tool call</span>',t.calls.some(n=>n.error)?'<span><i class="k-fail"></i>Failed</span>':"",t.prompts.length?'<span><i class="k-prompt"></i>Your prompt</span>':"",...t.comps.map(n=>`<span class="num"><i class="k-comp"></i>${l(`Compacted ${k(n.before)} to ${k(n.after)} at ${st(n.at)}`)}</span>`)].join("")}function Xd(t,e,{pinned:n=!1,agent:s=!1}={}){const a=e??t.pts.length-1,o=t.pts[a],r=a>0?t.pts[a-1].at:-1/0,i=t.comps.find(d=>d.at>r&&d.at<=o.at),c=t.limit?Math.round(Math.min(100,Math.max(0,o.context/t.limit*100))):null,u=n&&!s?`<button type="button" class="linkbtn" data-act="calls-near" data-key="${a}">Show its calls</button>`:e==null&&!s?'<span class="v-d">Click a point to pin it</span>':"";return`<span class="v-d">${e==null?"Latest":l(`Reply ${a+1} of ${t.pts.length}`)}</span><span class="v-d">${l(Bt(o.at))}</span><b>${l(k(o.context))}</b>${c==null?"":`<span>${c}%</span>`}<span>${l(`${k(o.output)} output`)}</span>${i?`<span>${l(`Compacted from ${k(i.before)} to ${k(i.after)}`)}</span>`:""}${u}`}function Jd(t,e,n=0){if(!t?.[e])return null;const s=t[e].at,a=e?t[e-1].at:n||0;return{from:a,to:s,label:`${st(a)} to ${st(s)}`}}const rr=()=>'<figure class="chart" data-chart><svg class="chart-svg" data-act="chart" tabindex="0" role="img"></svg><div class="chart-read" aria-live="polite"></div><div class="chart-key"></div></figure>',Sn=t=>t<45e3?"0m":$t(t).replace(/ ago$/,""),rn=160,Tn=(t,e)=>t.length>e?`${t.slice(0,e).replace(/\s+\S*$/,"")}…`:t,Cn=t=>t.cols>=3&&t.h>=1300?20:t.cols>=3&&t.h>=1e3?10:5,La=Object.freeze({1:[["#Activity and progress","plan","thoughts","subagents","activity","errors","files","tools","#History","context","prompts","session","note"]],2:[["#Progress","plan","thoughts","subagents","#History","context","prompts","session","note"],["#Activity","activity","errors","files","tools"]],3:[["#Progress","plan","thoughts","subagents"],["#Activity","activity","errors","files","tools"],["#History","context","prompts","session","note"]],4:[["#Progress","plan","thoughts","subagents"],["#Activity","activity","errors"],["#Changes","files","tools"],["#History","context","prompts","session","note"]]}),Ea=Object.freeze({1:[["activity","tools","files","prompts","errors","session","note"]],2:[["activity","files"],["tools","prompts","errors","session","note"]],3:[["activity"],["tools","files","errors"],["prompts","session","note"]],4:[["activity"],["tools"],["files","errors"],["prompts","session","note"]]});function ir(t,e){return t.map(n=>{let s="",a="";for(const o of n)o.startsWith("#")?a=`<h2 class="kick">${l(o.slice(1))}</h2>`:e[o]&&(s+=a+e[o],a="");return`<div class="col">${s}</div>`}).join("")}function Zd(t,{agent:e=!1,status:n="idle",layout:s}){return e?s.cols>=2&&(s.span?["activity","tools","prompts","files"]:["activity","files"]).includes(t):t==="thoughts"?!1:t==="plan"||t==="errors"&&n==="error"||t==="subagents"&&n==="delegating"?!0:s.cols===1?s.mode==="side"&&s.h>=640&&["plan","activity"].includes(t):s.span?s.cols===2?["plan","context","activity","files"].includes(t):s.cols===3?["plan","subagents","thoughts","activity","files","tools","context"].includes(t):t!=="session"||s.h>=1100:["activity","files"].includes(t)}const lr=(t,e,n)=>t in e?e[t]:Zd(t,n),mt=(t,e)=>`${t?`<span class="s-lead only-closed">${t}</span>`:""}<span class="s-tail">${e}</span>`,Lt=t=>mt("",`<span class="v-d">${t?"0":"Not recorded"}</span>`);function dt({id:t,name:e,term:n=null,summary:s,body:a,empty:o=!1,open:r=!1,harness:i="",flash:c=""}){const u=!o&&r,d=u&&n?Eo(n)?.text(i)?.[0]:"";return`<section class="sec" data-sec="${l(t)}"${u?" data-open":""}${c}>
|
|
130
|
+
<div class="sec-h"><button type="button" class="sec-t" data-act="sec" data-key="${l(t)}" aria-expanded="${u}"${o?" disabled":""}>${T.chev}<span class="sec-name"${n?` data-term="${l(n)}" data-rowtip`:""}>${l(e)}</span><span class="sec-sum num">${s}</span></button></div>
|
|
131
|
+
${u?`<div class="sec-b">${a()}${d?`<p class="sec-note">${l(d)}</p>`:""}</div>`:""}
|
|
132
|
+
</section>`}const le=(t,e,n="",s="",a=18)=>`<span class="i-wrap" data-term="${l(t)}" ${kt(e,n,s)}>${Tt(e.sec,e,a)}</span>`,pt=(t,e)=>`<button type="button" class="ib sm" data-act="copy" data-copy="${l(e)}" data-tip="${l(t)}" aria-label="${l(t)}">${T.copy}</button>`,Ce=(t,e,n)=>`<button type="button" class="ib sm" data-act="open-path" data-path="${l(t)}" data-line="${e??""}" data-tip="${l(`Open in ${n}`)}" aria-label="${l(`Open in ${n}`)}">${T.open}</button>`,_e=(t,e,n,s)=>n>s?`<button type="button" class="more" data-act="show-all" data-key="${l(t)}">${e?"Show fewer":`Show all ${n}`}</button>`:"";function z(t,e){const n=t?.arrived?.get(e);if(n!=null)return` data-arrive="${n}"`;const s=t?.changed?.get(e);return s!=null?` data-flash="${s}"`:""}const Ws=new Set(["claude-code"]);function Us(t,e=""){const n=t?.activity||[];for(let s=n.length-1;s>=0;s--)if(n[s].running&&(!e||n[s].name===e))return n[s];return e?Us(t):null}function Qd(t){let e=0;for(const n of t||[]){const s=/retry (\d+) of (\d+)/i.exec(n.message||"");s&&(e=Math.max(e,Number(s[1])))}return e}function Ln(t,e){const n=t?.ask;if(t?.status==="asking"){if(n?.type==="question"){const s=n.questions?.[0];if(s)return{kind:"question",head:s.header||"",text:s.text||"",options:s.options||[]}}if(n?.type==="approval"){const s=Us(e,n.tool);return{kind:"permission",tool:n.tool||s?.name||"",text:n.target||s?.target||s?.input||"",raw:s?.input||n.target||s?.target||""}}return{kind:"unknown"}}if(t?.status==="error"){const s=e?.errors||[],a=s.at(-1);return{kind:"error",text:Mn(n?.text||a?.message||"")||"The last turn failed.",retries:Qd(s),at:a?.at??null}}return null}function tu(t,e){if(t?.status!=="working")return null;const n=Us(e);return n?.target?{tool:n.name,target:n.target,input:n.input||n.target,startedAt:n.startedAt}:!n&&t.tool?.target?{tool:t.tool.name,target:t.tool.target,input:t.tool.target,startedAt:t.tool.startedAt}:null}function eu(t,e){if(t?.status!=="delegating")return null;const n=e?.subagents?e.subagents.filter(a=>a.status==="working"):t.workingSubagents||[],s=t.awaiting||[];return n.length||s.length?{agents:n,peers:s}:null}function nu(t){const e=t?.prompts?.length?t.prompts.at(-1):null;return e?{...e,long:e.text.length>rn||e.text.includes(`
|
|
133
|
+
`)}:null}function su(t,e=""){const n=[];t.org&&n.push(`<span class="w w-org" tabindex="0" data-tip="${l(`Organization ${t.org}, from the repo's package names`)}">${Q("org")}<span>${l(t.org)}</span></span>`);const s=Xe(t),a=!!e&&e===s,o=`${t.projectPath||t.project||"unknown"}. ${a?"Click to show every repo again.":"Click to show only this repo's threads."}`;return n.push(`<button type="button" class="w w-btn w-folder" data-act="where-repo" data-key="${l(s)}" aria-pressed="${a}" data-tip="${l(o)}">${Q("folder")}<span>${l(Ne(t.project,t.org)||"unknown")}</span></button>`),t.worktree&&n.push(`<button type="button" class="w w-btn" data-act="copy" data-copy="${l(t.worktree)}" data-tip="${l(`Worktree ${t.worktree}. Click to copy its name.`)}">${Q("worktree")}<span>${l(t.worktree)}</span></button>`),t.gitBranch&&n.push(`<button type="button" class="w w-btn" data-act="copy" data-copy="${l(t.gitBranch)}" data-tip="${l(`Branch ${t.gitBranch}. Click to copy its name.`)}">${Q("branch")}<span>${l(t.gitBranch)}</span></button>`),n.join("")}const au=t=>`${T.open}Open ${l(t)}`;function ou(){return`<span class="d-acts"><button type="button" class="ib nav-step" data-act="step" data-key="-1" aria-label="Previous thread" data-tip="Previous thread (K)">${T.up}</button><button type="button" class="ib nav-step" data-act="step" data-key="1" aria-label="Next thread" data-tip="Next thread (J)">${T.down}</button><button type="button" class="ib" data-act="close" aria-label="Close details" data-tip="Close details (Esc)">${T.x}</button></span>`}function ru(t,{id:e,harnessName:n,now:s,canOpen:a=!1}){const o=t.status==="delegating"?"":`<span class="d-now num" data-now="${l(e)}">${He(t,s)}</span>`,r=`<button type="button" class="term st" data-term="why" data-key="${l(e)}" aria-expanded="false">${l(vt(t.status).name)}</button>`;return`<div class="d-state" data-st="${l(t.status)}">${at(t.status)}${r}${o}${cu(t,{id:e,harnessName:n,canOpen:a})}</div>`}function iu(t,e,n=s=>s){return`<h4>${l(`Why it's ${vt(t.status).name}`)}</h4><p>${l(Bo(t,e,n))}</p><p class="tip-sub">${l(`Read from ${n(t.harness)}'s own files.`)}</p>`}function lu(t,e,n){const s=nu(t);if(!s)return"";const a=e.has("latest-prompt")||!s.long,o=s.long?` <button type="button" class="linkbtn" data-act="row" data-key="latest-prompt" aria-expanded="${a}">${a?"Show less":"Show all"}</button>`:"";return`<div class="latest"><span class="k"><span>Latest prompt</span><span data-ago="${s.at}">${l($t(n-s.at))}</span></span><span class="t">${l(a?s.text:Tn(s.text,rn))}</span>${o}</div>`}function cu(t,{id:e,harnessName:n,canOpen:s}){const a=`<span class="hmark">${l($n(t.harness,n))}</span>${l(n)}`;return s?`<button type="button" class="hn hn-open" data-act="open" data-key="${l(e)}" data-tip="${l(`Open this thread in ${n} (Enter)`)}">${a}${T.open}</button>`:`<span class="hn" title="${l(n)}">${a}</span>`}function cr(t){const e=`<button type="button" class="btn primary ans-respond" data-act="respond" data-key="${l(t.id)}">Respond${T.lock}</button>`,n=t.canOpen?`<button type="button" class="btn" data-act="open" data-key="${l(t.id)}">${au(t.harnessName)}</button>`:"";return e+n}function Qt(t,e){const n=e?`<button type="button" class="btn cv-ask-open" data-act="cv-open">${T.bubble}<span>Open the conversation</span></button>`:"";return`<div class="ans">${cr(t)}${n}</div>`}function du(t){const{s:e,d:n,now:s}=t,a=Ln(e,n);if(a?.kind==="question"){const i=a.options.length?`<dl class="opts">${a.options.map(c=>`<dt>${l(c.label)}</dt><dd>${l(c.description||"")}</dd>`).join("")}</dl>`:"";return`<div class="ask" data-kind="question"><span class="lbl">It asks${a.head?`: ${l(a.head)}`:""}</span><p>${l(a.text)}</p>${i}${Qt(t,!0)}</div>`}if(a?.kind==="permission")return`<div class="ask" data-kind="permission"><span class="lbl">It wants permission to run ${l(P(a.tool))}</span><div class="cmd"><code>${l(a.text)}</code>${a.raw?pt("Copy command",a.raw):""}</div>${Qt(t,!0)}</div>`;if(a?.kind==="unknown")return`<div class="ask" data-kind="unknown"><span class="lbl">It's waiting for you</span>${Qt(t,!0)}</div>`;if(a?.kind==="error"){const i=`${a.retries?`It retried ${a.retries} times, then stopped. `:""}Open the thread in ${t.harnessName} and send the turn again once the API recovers.`;return`<div class="ask" data-kind="error"><span class="lbl">${l(a.text)}</span><p>${l(i)}</p>${Qt(t,!0)}</div>`}const o=tu(e,n);if(o)return`<div class="ask" data-kind="work"><span class="lbl lbl-work">${l(P(o.tool))}, running <span class="num" data-since="${o.startedAt}">${l(nt(s-o.startedAt))}</span></span><div class="cmd"><code>${l(o.target)}</code>${pt("Copy input",o.input)}</div>${Qt(t,!1)}</div>`;const r=eu(e,n);if(r){const i=Ws.has(e.harness)&&!!n?.subagents,c=r.agents.map(d=>{const p=i?`<button type="button" class="linkbtn wrap" data-act="agent" data-key="${l(d.id)}">${l(d.name)}</button>`:`<span class="nm">${l(d.name)}</span>`,h=d.tool&&Number.isFinite(d.tool.startedAt)?`<span class="dim num">${l(P(d.tool.name))} <span data-dur="${d.tool.startedAt}">${l(At(s-d.tool.startedAt))}</span></span>`:"";return`<li>${p}${h}</li>`}),u=r.peers.map(d=>`<li><button type="button" class="linkbtn wrap" data-act="select" data-key="${l(d.id)}">${l(d.title||"another session")}</button><span class="dim">another thread</span></li>`);return`<div class="ask" data-kind="wait"><ul>${[...c,...u].join("")}</ul>${Qt(t,!1)}</div>`}return""}function uu(t){const{s:e,d:n}=t,s=Ln(e,n)?.kind,a=t.cvOpen&&["question","permission","unknown","error"].includes(s);return`<header class="d-head d-pad">
|
|
134
|
+
<div class="d-line1"><div class="where">${su(e,t.repo)}</div>${ou()}</div>
|
|
135
|
+
<h1 class="d-title">${l(e.title)}</h1>
|
|
136
|
+
${ru(e,t)}
|
|
137
|
+
${a?"":du(t)}
|
|
138
|
+
${t.cvOpen?"":lu(n,t.rows,t.now)}
|
|
139
|
+
${t.note?`<p class="d-note">${l(t.note)}</p>`:""}
|
|
140
|
+
</header>`}function pu(){return`<header class="d-head d-pad"><div class="d-line1"><div class="where"></div><span class="d-acts"><button type="button" class="ib" data-act="close" aria-label="Close details" data-tip="Close details (Esc)">${T.x}</button></span></div><p class="d-note">This thread isn't listed anymore.</p></header>`}const hu=1200*1e3,fu=600*1e3;function mu(t,e){const n=[];return(t||[]).forEach((s,a)=>{if(e==="error"&&a===t.length-1)return;const o=Mn(s.message).replace(/\s*\(retry \d+ of \d+\)\s*$/i,""),r=n.at(-1);r&&r.base===o&&s.at-r.last<fu?(r.n++,r.last=s.at):n.push({base:o,n:1,first:s.at,last:s.at})}),n}function dr(t,e){if(!e)return[];const n=[];for(const i of e.prompts||[])n.push({kind:"you",at:i.at,text:i.text});for(const i of e.replies||[])n.push({kind:"agent",at:i.at,text:i.text});for(const i of e.compactions||[])n.push({kind:"event",at:i.at,text:`Compacted its context from ${k(i.before)} to ${k(i.after)}.`});for(const i of mu(e.errors,t?.status))n.push({kind:"error",at:i.first,text:i.n>1?`${i.base} ${i.n} times, until ${st(i.last)}`:i.base});for(const i of e.subagents||[])i.startedAt&&n.push({kind:"event",at:i.startedAt,text:"Started the subagent",agent:i});n.sort((i,c)=>i.at-c.at);const s=(e.activity||[]).filter(i=>i.startedAt).sort((i,c)=>i.startedAt-c.startedAt),a=[];let o=0;const r=i=>{const c=[];for(;o<s.length&&s[o].startedAt<=i;)c.push(s[o++]);c.length&&a.push({kind:"tools",at:c[0].startedAt,end:c.at(-1).endedAt||c.at(-1).startedAt,calls:c})};for(const i of n)r(i.at),a.push(i);return r(1/0),a}function ur(t,e){if(t?.status!=="done")return null;const n=e?.prompts||[];return n.length?n.at(-1).at+1:null}function qs(t,e,n=dr(t,e)){const s=ur(t,e);return{items:n,yours:n.filter(a=>a.kind==="you").length,replies:n.filter(a=>a.kind==="agent").length,fresh:s?n.filter(a=>a.at>=s&&a.kind==="agent").length:0}}function pr(t,e,n,s){const a=Ln(t,e);if(t.status==="asking"&&(a?.kind==="question"||a?.kind==="permission"))return{who:a.kind==="question"?"It asks":`It wants to run ${P(a.tool)}`,text:a.text,at:t.lastActivityAt};const o=[...n].reverse().find(i=>i.kind==="agent"||i.kind==="you");if(!o)return{who:s,text:"No messages yet.",at:null};const r=String(o.text||"").replace(/```[\s\S]*?```/g,"").replace(/`/g,"").trim();return{who:o.kind==="you"?"You":s,text:r,at:o.at}}function Oa(t){return String(t||"").split(/```(?:\w+)?\n?([\s\S]*?)```/g).map((n,s)=>s%2?`<pre class="cv-code"><code>${l(n.replace(/\n$/,""))}</code></pre>`:n.split(/\n{2,}/).map(a=>a.trim()).filter(Boolean).map(a=>`<p>${l(a).replace(/`([^`]+)`/g,"<code>$1</code>").replace(/\n/g,"<br>")}</p>`).join("")).join("")}const Ie=(t,e)=>`<span class="cv-av" data-h="${l(t.harness)}" title="${l(e)}">${l($n(t.harness,e))}</span>`,qe=t=>`<span class="cv-when num" title="${l(new Date(t).toLocaleString("en-US"))}">${l(st(t))}</span>`;function gu(t,e){const{s:n,harnessName:s}=e;switch(t.kind){case"you":return`<li class="cv-row cv-you"><div class="cv-bub"><div class="cv-meta"><b>You</b>${qe(t.at)}</div><div class="cv-text">${Oa(t.text)}</div></div><span class="cv-tools">${pt("Copy message",t.text)}</span></li>`;case"agent":return`<li class="cv-row cv-agent">${Ie(n,s)}<div class="cv-body"><div class="cv-meta"><b>${l(s)}</b>${n.model?`<span class="v-d">${l(ht(n.model))}</span>`:""}${qe(t.at)}</div><div class="cv-text">${Oa(t.text)}</div></div><span class="cv-tools">${pt("Copy message",t.text)}</span></li>`;case"tools":{if(!e.cv.tools)return"";const a=`${n.id}|${t.at}`,o=e.cv.runs.has(a),r=new Map;for(const f of t.calls)r.set(P(f.name),(r.get(P(f.name))||0)+1);const i=t.calls.filter(f=>f.error).length,c=t.calls.some(f=>f.running),u=[...r].sort((f,m)=>m[1]-f[1]),d=(t.end||t.at)-t.at,p=u.slice(0,4).map(([f,m])=>`<span><b>${l(f)}</b>${m>1?`<span class="v-d">${m}</span>`:""}</span>`).join(""),h=o?`<ol class="cv-calls">${t.calls.map(f=>`<li data-state="${f.running?"running":f.error?"error":"done"}"><span class="cv-c-n">${l(P(f.name))}</span><span class="cv-c-t">${l(f.target||"")}</span><span class="cv-c-d num">${f.running?`<span data-since="${f.startedAt}">${l(nt(e.now-f.startedAt))}</span>`:f.endedAt?l(nt(f.endedAt-f.startedAt)):""}</span>${f.error?'<span class="del">Failed</span>':""}</li>`).join("")}</ol>`:"";return`<li class="cv-row cv-run"><button type="button" class="cv-run-h" data-act="cv-run" data-key="${l(a)}" aria-expanded="${o}">${T.chev}<span class="cv-run-n">${l(ct(t.calls.length,"tool call","tool calls"))}</span><span class="cv-run-t">${p}${u.length>4?`<span class="v-d">and ${u.length-4} more</span>`:""}</span>${i?`<span class="del">${i} failed</span>`:""}${c?'<span class="cv-live">Running</span>':d>1e3?`<span class="v-d">${l(It(d))}</span>`:""}</button>${h}</li>`}case"event":{const a=t.agent?Ws.has(n.harness)?` <button type="button" class="linkbtn" data-act="agent" data-key="${l(t.agent.id)}">${l(t.agent.name)}</button>`:` ${l(t.agent.name)}`:"";return`<li class="cv-row cv-ev"><span>${l(t.text)}${a}</span>${qe(t.at)}</li>`}case"error":return`<li class="cv-row cv-ev cv-err"><span>${l(t.text)}</span>${qe(t.at)}</li>`}return""}function $u(t){const{s:e,d:n,harnessName:s,now:a}=t,o=Ie(e,s),r=Ln(e,n),i=`<div class="ans">${cr({...t,id:t.id||e.id})}</div>`;if(e.status==="asking"){if(r?.kind==="question"){const d=r.options.length?`<dl class="opts">${r.options.map(p=>`<dt>${l(p.label)}</dt><dd>${l(p.description||"")}</dd>`).join("")}</dl>`:"";return`<li class="cv-row cv-agent">${o}<div class="cv-body cv-askc"><div class="cv-meta"><b class="cv-ask-l">It asks${r.head?`: ${l(r.head)}`:""}</b><span class="cv-when num">${l(st(e.lastActivityAt))}</span></div><div class="cv-text"><p>${l(r.text)}</p></div>${d}${i}</div></li>`}return r?.kind==="permission"?`<li class="cv-row cv-agent">${o}<div class="cv-body cv-askc"><div class="cv-meta"><b class="cv-ask-l">It wants to run ${l(P(r.tool))}</b><span class="cv-when num">${l(st(e.lastActivityAt))}</span></div><pre class="cv-code"><code>${l(r.text)}</code></pre>${i}</div></li>`:`<li class="cv-row cv-pend">${o}<div class="cv-body"><span>It's waiting for you.</span>${i}</div></li>`}if(e.status==="error"&&r?.kind==="error"){const d=`${r.retries?`It retried ${r.retries} times, then stopped. `:""}Send the turn again once the API recovers.`;return`<li class="cv-row cv-agent">${o}<div class="cv-body cv-errc"><div class="cv-meta"><b class="cv-err-l">${l(r.text)}</b><span class="cv-when num">${l(st(r.at||e.lastActivityAt))}</span></div><div class="cv-text"><p>${l(d)}</p></div>${i}</div></li>`}if(e.status!=="working"&&e.status!=="delegating")return"";let c=l(Oo(e));e.status==="working"&&(c=e.tool?l(P(e.tool.name)):"Working");const u=e.status==="working"&&Number.isFinite(e.tool?.startedAt)?`<span class="num" data-since="${e.tool.startedAt}">${l(nt(a-e.tool.startedAt))}</span>`:"";return`<li class="cv-row cv-pend cv-typing" data-st="${e.status}">${o}<span class="cv-now">${at(e.status)}<span class="cv-st">${c}</span>${u}</span></li>`}function yu(t,e=dr(t.s,t.d)){const n=ur(t.s,t.d);let s=null,a=!1,o="";for(const r of e){if(!s||r.at-s.at>hu){const i=new Date(r.at).toLocaleDateString("en-US",{weekday:"short"});o+=`<li class="cv-row cv-time"><span>${l(`${i} ${st(r.at)}`)}</span></li>`}n&&!a&&r.at>=n&&r.kind!=="you"&&(a=!0,o+='<li class="cv-row cv-new"><span>New since you last looked</span></li>'),o+=gu(r,t),s=r}return o+=$u(t).replace("<li ","<li data-tail "),`<ol class="cv-stream" data-cv="${l(t.id)}">${o}</ol>`}function hr(t,e){return[t.status==="asking"?`<span class="cv-b cv-b-ask" title="It needs you">${Ns.asking}</span>`:"",e?`<span class="cv-b cv-b-new" title="${l(ct(e,"new reply","new replies"))}">${e}</span>`:""].join("")}function wu(t){const e=qs(t.s,t.d),n=pr(t.s,t.d,e.items,t.harnessName),s=e.fresh||t.s.status==="asking";return`<button type="button" class="cv-rail" data-act="cv-open" data-st="${l(t.s.status)}"${s?" data-lit":""} aria-label="Open the conversation (R)" aria-expanded="false" aria-controls="cv-panel">
|
|
141
|
+
<span class="cv-rail-av">${Ie(t.s,t.harnessName)}</span>
|
|
142
|
+
<span class="cv-rail-label">Conversation</span>
|
|
143
|
+
<span class="cv-rail-badges">${hr(t.s,e.fresh)}</span>
|
|
144
|
+
<span class="cv-rail-go">${T.bubble}<kbd>R</kbd></span>
|
|
145
|
+
</button>
|
|
146
|
+
<div class="cv-peek" aria-hidden="true">
|
|
147
|
+
<div class="cv-peek-h"><b>${l(n.who)}</b>${n.at?`<span>${l($t(t.now-n.at))}</span>`:""}</div>
|
|
148
|
+
<p>${l(Tn(n.text,260))}</p>
|
|
149
|
+
<span class="cv-peek-f">Open the conversation<kbd>R</kbd></span>
|
|
150
|
+
</div>`}function bu(t,{stack:e=!1,over:n=!1,enter:s=!1}={}){const a=qs(t.s,t.d),o=n?"Back to the details":"Close the conversation";return`<div class="cvp"${s?" data-enter":""}>
|
|
151
|
+
<header class="cvp-h">
|
|
152
|
+
${e?`<button type="button" class="back" data-act="cv-close">${T.back}<span>Details</span></button>`:""}
|
|
153
|
+
<div class="cvp-t">${e?"":Ie(t.s,t.harnessName)}<div class="cvp-tt"><h2 class="cv-title">Conversation</h2><span class="cv-sum num"><span><b>${a.yours}</b> ${a.yours===1?"prompt":"prompts"}</span><span><b>${a.replies}</b> ${a.replies===1?"reply":"replies"}</span></span></div></div>
|
|
154
|
+
<span class="cv-hacts"><button type="button" class="btn sm" data-act="cv-tools" aria-pressed="${!t.cv.tools}">${t.cv.tools?"Hide tool calls":"Show tool calls"}</button>${e?"":`<button type="button" class="ib" data-act="cv-close" aria-label="${l(`${o} (R)`)}" data-tip="${l(`${o} (R)`)}">${T.panelOut}</button>`}</span>
|
|
155
|
+
</header>
|
|
156
|
+
${e||n?`<div class="cvp-thread" data-st="${l(t.s.status)}">${at(t.s.status)}<span>${l(t.s.title)}</span></div>`:""}
|
|
157
|
+
${yu(t,a.items)}
|
|
158
|
+
</div>`}function vu(t){const e=qs(t.s,t.d),n=pr(t.s,t.d,e.items,t.harnessName);return`<div class="reply-dock d-pad"><button type="button" class="cv-dockbar" data-act="cv-open" data-st="${l(t.s.status)}" aria-label="Open the conversation">${Ie(t.s,t.harnessName)}<span class="cv-db-t"><b>Conversation</b><span><span class="cv-db-who">${l(n.who)}</span> ${l(n.text)}</span></span><span class="cv-db-b">${hr(t.s,e.fresh)}</span>${T.chev}</button></div>`}const ku=Object.freeze([...on.filter(t=>t.id!=="system"),...on.filter(t=>t.id==="system")].map(t=>({id:t.id,label:t.id==="system"?"Default app":t.name}))),fr=t=>`file:${t.path}`,Vs=(t,e,n)=>`${t}|${e||""}|${n.path}|${n.edits??""}`,mr=t=>Number(t.diff)>0;function gr(t){return{added:t.reduce((e,n)=>e+(n.added||0),0),removed:t.reduce((e,n)=>e+(n.removed||0),0)}}const $r=(t,e)=>({k:"split",sec:"files",a:t,r:e}),yr=(t,e)=>`+${k(t)} −${k(e)}`;function xu(t){return t.slice().reverse().map(e=>{let n=e.line||0,s=e.oldLine||0;const a=(e.lines||[]).map(o=>{const r=o.startsWith("+")?"add":o.startsWith("-")?"del":o.startsWith("\\")?"meta":"ctx";let i="";return r==="add"&&n?i=String(n++):r==="del"&&s?i=String(s++):r==="ctx"&&(n&&(i=String(n++)),s&&s++),`<div class="dl" data-k="${r}"><span class="g">${i}</span><span class="s">${r==="meta"?"":l(o[0]||"")}</span><span class="t">${l(r==="meta"?o:o.slice(1))}</span></div>`}).join("");return`<div class="diff-head">${e.line?`Line ${e.line}`:"Change"}</div>${a}${e.cut?`<div class="diff-cut">${e.cut} more ${e.cut===1?"line":"lines"} not kept</div>`:""}`}).join("")}function Mu(t,e){return t.diff===0?'<p class="note">Its lines are no longer kept. Threadgauge keeps them for the 25 files changed most recently.</p>':mr(t)?e?e.error?`<p class="note">${l(e.error)}</p>`:e.hunks?.length?`<div class="diff" tabindex="0" role="region" aria-label="${l(`Changes to ${t.path}`)}"><div class="diff-inner">${xu(e.hunks)}</div></div>`:'<p class="note">No lines were recorded for this change.</p>':'<p class="note">Reading the change…</p>':'<p class="note">No lines were recorded for this change.</p>'}function Au(t,e){const n=fr(t),s=e.rows.has(n),{dir:a,name:o}=eo(t.path),r=no(e.base,t.path),i=e.agentView?null:e.overlaps?.[t.path],c=t.line?` at line ${t.line}`:"";return`<li class="file">
|
|
159
|
+
<button type="button" class="file-main" data-act="row" data-key="${l(n)}" aria-expanded="${s}">${T.chev}<span class="file-path" title="${l(t.path)}"><span class="dir">${l(a)}</span><span class="fn">${l(o)}</span></span><span class="file-n">${Be({added:t.added,removed:t.removed})}</span>${le("lines",$r(t.added,t.removed),yr(t.added,t.removed),o)}</button>
|
|
160
|
+
<span class="acts">${pt("Copy path",r)}${Ce(t.path,t.line,e.editor)}</span>
|
|
161
|
+
${i?.length?`<p class="overlap">Also changed by ${i.map(u=>`<button type="button" class="linkbtn wrap" data-act="select" data-key="${l(u.id)}" title="Show that thread">${l(u.title||"another thread")}</button>`).join(" and ")}</p>`:""}
|
|
162
|
+
${s?`<div class="call-body"><div class="body-acts"><button type="button" class="btn" data-act="copy" data-copy="${l(r)}">${T.copy}Copy path</button><button type="button" class="btn" data-act="open-path" data-path="${l(t.path)}" data-line="${t.line??""}">${T.open}${l(`Open in ${e.editor}${c}`)}</button></div>${Mu(t,e.hunkOf?.(t))}</div>`:""}
|
|
163
|
+
</li>`}function wr(t){const{s:e,d:n}=t,s=n?.files||[],{added:a,removed:o}=gr(s),r=t.agentView?0:s.filter(d=>t.overlaps?.[d.path]?.length).length,i=r?`<span class="warn-t">${l(`${r} also changed by another thread`)}</span>`:"",c=s.length?mt(i,`<b class="v-b">${s.length}</b><span class="paren"><span class="add">+${l(k(a))}</span> <span class="del">−${l(k(o))}</span></span>${le("lines",$r(a,o),yr(a,o),ct(s.length,"file","files"))}`):Lt(n?.files!=null);return dt({id:"files",name:"Files changed",term:"files",summary:c,body:()=>{const d=Cn(t.layout),p=t.showAll.has("files"),h=p?s:s.slice(0,d);return`<div class="tools"><label class="field">Open files in <select class="sel" data-change="editor">${ku.map(m=>`<option value="${l(m.id)}"${t.editorId===m.id?" selected":""}>${l(m.label)}</option>`).join("")}</select></label></div>
|
|
164
|
+
<ul>${h.map(m=>Au(m,t)).join("")}</ul>
|
|
165
|
+
${_e("files",p,s.length,d)}`},empty:!s.length,open:t.isOpen("files"),harness:e.harness,flash:z(t.flash,"sec:files")})}function Su(t,e,n,s,a){return(t?.files||[]).filter(o=>e.has(fr(o))&&mr(o)&&!n(Vs(s,a,o)))}const br=t=>(t||[]).slice().reverse();function Tu(t,{toolFilter:e=null,failedOnly:n=!1,timeFilter:s=null}={}){return t.filter(a=>(!e||a.name===e)&&(!n||a.error)&&(!s||a.startedAt>s.from&&a.startedAt<=s.to))}function Cu(t){const e=new Map;for(const n of t)e.set(n.name,(e.get(n.name)||0)+1);return[...e].map(([n,s])=>({name:n,n:s}))}const Lu=t=>t.find(e=>e.running)||t[0]||null;function Eu(t,e,n){return n?`${t} of ${e}`:ct(e,"call","calls")}function Ou(t,e){return e&&t>=100?"Activity keeps this thread's newest 100 calls, and none of them ran in this time.":e?"No tool calls ran in this time.":"No calls match these filters."}const Nu=/bash|shell|command|exec|terminal|powershell/i;function Hu(t,e,n){const s=`call:${t.id}`,a=e.rows.has(s),o=lo(t,n),r=t.running?`<span class="c-dur" data-since="${t.startedAt}">${l(nt(e.now-t.startedAt))}</span>`:`<span class="c-dur">${t.endedAt?l(nt(t.endedAt-t.startedAt)):"—"}</span>`,i=o.kind==="execute"||o.shell||Nu.test(t.name)?"Copy command":"Copy input",c=t.input||t.target||"",u=t.path?no(e.base,t.path):"",d=t.path?`${pt("Copy path",u)}${Ce(t.path,t.line,e.editor)}`:c?pt(i,c):"",p=t.running?"running":t.error?"error":"done",h=a?`<div class="call-body">
|
|
166
|
+
${t.input?`<div class="code"><pre>${l(t.input)}</pre>${pt(i,t.input)}</div>`:""}
|
|
167
|
+
${t.errorText?`<div class="code" data-err><pre>${l(t.errorText)}</pre>${pt("Copy error",t.errorText)}</div>`:""}
|
|
168
|
+
<p class="note num">${l(`Started ${Bt(t.startedAt)}${t.endedAt?`, finished ${Bt(t.endedAt)}, after ${nt(t.endedAt-t.startedAt)}`:t.running?", still running":""}`)}</p>
|
|
169
|
+
${t.path?`<div class="body-acts"><button type="button" class="btn" data-act="copy" data-copy="${l(u)}">${T.copy}Copy path</button><button type="button" class="btn" data-act="open-path" data-path="${l(t.path)}" data-line="${t.line??""}">${T.open}${l(`Open in ${e.editor}${t.line?` at line ${t.line}`:""}`)}</button></div>`:""}
|
|
170
|
+
</div>`:"";return`<li class="call" data-state="${p}" data-at="${t.startedAt||""}" data-call="${l(t.id)}"${z(e.flash,s)}>
|
|
171
|
+
<button type="button" class="call-main" data-act="row" data-key="${l(s)}" aria-expanded="${a}">${T.chev}<span class="c-time">${l(Bt(t.startedAt))}</span><span class="c-line1"><span class="c-tool">${co(o)}${l(P(t.name))}</span><span class="c-target"${t.target?` title="${l(t.target)}"`:""}>${l(Tn(t.target||"",120))}</span></span><span class="c-fail">${t.error?"Failed":""}</span>${r}</button>
|
|
172
|
+
${d?`<span class="acts">${d}</span>`:""}
|
|
173
|
+
${h}
|
|
174
|
+
</li>`}function vr(t){const{s:e,d:n,now:s}=t,a=br(n?.activity),o=a.filter(p=>p.error).length,r=Lu(a);let i="";if(r){const p=r.running?`<span class="v-d" data-since="${r.startedAt}">${l(nt(s-r.startedAt))}</span>`:`<span class="v-d" data-age="${r.startedAt}">${l(Sn(s-r.startedAt))}</span>`;i=`<span class="v-b${r.running?" v-run":""}">${l(P(r.name))}</span> ${p}${r.target?` <span class="mono">${l(r.target)}</span>`:""}`}const c={k:"tally",sec:"activity",n:a.length,fail:o,...bn(a,s)},u=a.length?mt(i,`<b class="v-b">${a.length}</b>${o?`<span class="paren">(<span class="del" title="${l(`${o} failed`)}">${T.xs}${o}</span>)</span>`:""}${le("activity",c,ct(a.length,"call","calls"),o?`${o} failed`:"")}`):Lt(!!n);return dt({id:"activity",name:"Activity",term:"activity",summary:u,body:()=>{const p=t.filter,h=Tu(a,p),f=Cn(t.layout),m=t.showAll.has("activity"),y=m?h:h.slice(0,f),$=wl(n?.tools),x=Cu(a).map(B=>`<option value="${l(B.name)}"${p.toolFilter===B.name?" selected":""}>${l(`${P(B.name)} (${B.n})`)}</option>`).join(""),E=!!(p.toolFilter||p.failedOnly||p.timeFilter);return`<div class="tools">
|
|
175
|
+
<button type="button" class="btn" data-act="failed" aria-pressed="${!!p.failedOnly}">Failed only</button>
|
|
176
|
+
<label class="field"><select class="sel" data-change="tool-filter" aria-label="Show one tool"><option value="">All tools</option>${x}</select></label>
|
|
177
|
+
${p.timeFilter?`<button type="button" class="chipx" data-act="clear-time" aria-label="Show calls from every time">${l(p.timeFilter.label)}${T.xs}</button>`:""}
|
|
178
|
+
<span class="count">${l(Eu(h.length,a.length,E))}</span>
|
|
179
|
+
${p.toolFilter||p.failedOnly?'<button type="button" class="linkbtn" data-act="clear-activity">Clear</button>':""}
|
|
180
|
+
</div>
|
|
181
|
+
${h.length?`<ol>${y.map(B=>Hu(B,t,$)).join("")}</ol>`:`<p class="note">${l(Ou(a.length,p.timeFilter))}</p>`}
|
|
182
|
+
${_e("activity",m,h.length,f)}`},empty:!a.length,open:t.isOpen("activity"),harness:e.harness,flash:z(t.flash,"sec:activity")})}function kr(t){const{s:e,d:n}=t,s=br(n?.errors),a=s.length?mt(`<span class="del">${l(Mn(s[0].message))}</span>`,`<b class="v-b del">${s.length}</b>`):Lt(!!n);return dt({id:"errors",name:"Errors",term:"errors",summary:a,body:()=>{const r=Cn(t.layout),i=t.showAll.has("errors");return`<ol>${(i?s:s.slice(0,r)).map(u=>`<li class="err-row"${z(t.flash,`error:${u.at}:${u.message}`)}>${at("error")}<span class="t">${l(u.message)}</span><span class="when num">${l(u.at?Bt(u.at):"")}</span>${pt("Copy error",u.message)}</li>`).join("")}</ol>${_e("errors",i,s.length,r)}`},empty:!s.length,open:t.isOpen("errors"),harness:e.harness,flash:z(t.flash,"sec:errors")})}const Na=t=>String(t??"").replace(/<[^>]+>/g,"").replace(/</g,"<").replace(/>/g,">").replace(/"/g,'"').replace(/'/g,"'").replace(/&/g,"&").trim(),Bu={rings:"square",numbers:"slim"};function Ut(t,e,n,s="",a=null){if(!a)return`<div class="fig"><span class="fig-t">${ft(e,t)}<b>${n}</b>${s?`<small>${s}</small>`:""}</span></div>`;const o=kt(a,Na(n),Na(s)),r=Bu[Te[a.sec]]||"wide",i=lc.has(a.sec)?" data-side":"";return`<div class="fig has-inst" data-shape="${r}"${i}><span class="i-wrap" data-term="${l(e)}" ${o}>${Tt(a.sec,a,24)}</span><span class="fig-t">${ft(e,t,o)}<b>${n}</b>${s?`<small>${s}</small>`:""}</span></div>`}const Ru=t=>t?t.input+t.cacheWrite+t.cacheRead:0,Ve=(t,e,n={})=>({k:"pips",sec:"tokens",v:t||0,base:1e3,dir:e,...n});function xr(t,e){const n=t?t.input+t.cacheWrite:null,s={of:Ru(t),ofLabel:"all prompt tokens"};return[Ut("Output","output",l(k(t?.output)),"",Ve(t?.output,"out",{bars:ql(e?.history||[])})),Ut("Input","input",l(k(n)),"",Ve(n,"in",s)),Ut("Cache reads","cacheRead",l(k(t?.cacheRead)),"",Ve(t?.cacheRead,"loop",s)),Ut("Cache writes","cacheWrite",l(k(t?.cacheWrite)),"",Ve(t?.cacheWrite,"in",s))].join("")}function Mr(t,e){const n=t?.tools?t.tools.reduce((o,r)=>o+r.calls,0):null,s=t?.tools?t.tools.reduce((o,r)=>o+(r.errors||0),0):0,a={k:"tally",sec:"toolCalls",n:n||0,fail:s,...bn(t?.activity,e)};return Ut("Tool calls","toolCalls",l(k(n)),s?`<span class="del">${l(`${s} failed`)}</span>`:"",a)}function Ar({startedAt:t,endAt:e,live:n},s,a){const o=Math.max(0,e-t||0),r=l(At(o)),i=n?`<span data-dur="${t}">${r}</span>`:r;return Ut("Duration","duration",i,l(`since ${st(t)}`),{k:"watch",sec:"duration",ms:o,bins:bn(s?.activity,a).bins})}function Sr(t,e,n){return Ut("Spend","spend",l(Bs(t)),"",{k:"pips",sec:"spend",v:t||0,base:.1,dir:"$",of:e||t||0,ofLabel:n})}const _u=(t,e)=>({startedAt:t.startedAt,endAt:ze(t)?e:t.lastActivityAt,live:ze(t)}),Iu=(t,e)=>({startedAt:t.startedAt,endAt:t.status==="working"?e:t.lastActivityAt,live:t.status==="working"});function ju(t,e,{now:n,threadCost:s=null}){const a=(e?.models||[]).reduce((o,r)=>o+(r.costUsd||0),0);return`<div class="figs-row">${xr(t.tokens,e)}${Mr(e,n)}${Ar(Iu(t,n),e,n)}${Sr(a,s||a,"this thread's spend")}</div>`}const Tr=(t,e)=>`${(t/(e||1)*100).toFixed(1)}%`,Cr=(t,e)=>Math.max(.4,t/(e||1)*100).toFixed(2);function Pu(t,e){const n=t.context;if(!n)return null;const s=n.limit?n.used/n.limit*100:0,a={k:"gauge",sec:"context",pct:s,level:yn(s)},o=e?.history?.length>1?e.history:t.contextHistory?.map(c=>({context:c})),r=xo(o,n.limit,{used:n.used}),i=Vo(t,e);return{gauge:a,spark:{...a,sec:"contextHistory",...r?{hist:r}:{}},val:n.limit?`${k(n.used)} of ${k(n.limit)}`:`${k(n.used)} used`,sub:i==null?"":`Room left: about ${It(i)}`,room:i}}const Ha=(t,e,n)=>`<span class="i-wrap" data-term="context" ${kt(t,e,n)}>${Tt(t.sec,t,18)}</span>`,Fu=[["messages","Messages"],["system","System prompt","ctx-system"],["tools","Built-in tools","ctx-tools"],["mcp","MCP tools"],["skills","Skills"],["memory","Memory files"],["reserve","Kept free for compacting (default)","ctx-reserve"],["free","Free space","ctx-free"]];function Du(t,e){const n=Wu(t?.parts?.length?t:null,e),s=new Map((n?.groups||[]).map(o=>[o.key,o])),a=Fu.map(([o,r,i])=>s.get(o)||{key:o,label:r,term:i,missing:!0});return{whole:n?.whole||1,limit:n?.limit||0,reserve:n?.reserve||0,total:n?.total??null,recorded:!!n,groups:a}}function Wu(t,e){if(!t)return null;const n=m=>t.parts.find(y=>y.id===m)||null,s=t.limit||0,a=s&&t.reserved||0,o=s||t.total||1,r=new Map;if(e?.tools?.length)for(const m of e.tools)r.set(m.name,m.calls);else for(const m of e?.activity||[])r.set(m.name,(r.get(m.name)||0)+1);const i=[],c=n("messages");if(c){const m=$=>c.items?.find(x=>x.id===$),y=e?.history?.length||e?.replies?.length||0;i.push({key:"messages",label:"Messages",tokens:c.tokens,tip:"Your prompts, the replies, and every tool result. Click to see each part.",kids:[{kind:"sub",label:"Your prompts",count:e?.prompts?.length??0,tokens:m("prompts")?.tokens||0},{kind:"sub",label:"Agent replies",count:y,tokens:m("replies")?.tokens||0},...m("summary")?.tokens?[{kind:"sub",label:"Summary from compacting",tokens:m("summary").tokens}]:[],...(c.items||[]).filter($=>$.id==="tool").sort(($,x)=>x.tokens-$.tokens).map($=>({kind:"tool",name:$.name,count:r.get($.name)??null,tokens:$.tokens}))]})}const u=n("system");u&&i.push({key:"system",label:"System prompt",tokens:u.tokens,term:"ctx-system"});const d=n("builtInTools");d&&i.push({key:"tools",label:"Built-in tools",tokens:d.tokens,term:"ctx-tools"});const p=n("mcpTools");if(p){const m=p.items||[],y=m.reduce(($,x)=>$+(x.tools||0),0);i.push({key:"mcp",label:"MCP tools",count:y||null,tokens:p.tokens,tip:"Tools from the MCP servers this project uses. Click to see each server.",kids:m.map($=>({kind:"server",name:$.name,tools:$.tools,tokens:$.tokens})),none:"No MCP servers are set up for this project."})}const h=n("skills");if(h){const m=h.items||[];i.push({key:"skills",label:"Skills",count:m.length||null,tokens:h.tokens,tip:"The name and description of each skill the agent can load. Click to see them.",kids:m.map(y=>({kind:"skill",name:y.name,tokens:y.tokens})),none:"no-skills"})}const f=n("memory");if(f){const m=f.items||[];i.push({key:"memory",label:"Memory files",count:m.length,tokens:f.tokens,tip:"Instruction files the harness reads at the start. Click to see and open them.",kids:m.map(y=>({kind:"file",path:y.path,tokens:y.tokens}))})}return s&&t.reserved!=null&&i.push({key:"reserve",label:"Kept free for compacting (default)",tokens:a,term:"ctx-reserve"}),s&&i.push({key:"free",label:"Free space",tokens:Math.max(0,s-t.total-a),term:"ctx-free"}),{whole:o,limit:s,reserve:a,total:t.total,groups:i}}const Uu=["messages","system","tools","mcp","skills","memory"];function qu(t,e){const n=s=>`<span class="cm-v num">${l(k(s))}</span>`;if(t.kind==="tool"){const s=P(t.name);return`<li class="cm-s"><button type="button" class="cm-go" data-act="tool" data-key="${l(t.name)}" aria-pressed="${e.filter?.toolFilter===t.name}" data-tip="${l(`Show only ${s} calls in Activity`)}"><span class="cm-n">${l(`${s} results`)}${t.count!=null?` <span class="cm-c num">${t.count}</span>`:""}</span>${n(t.tokens)}</button></li>`}return t.kind==="server"?`<li class="cm-s"><span class="cm-n"><span class="mono">${l(t.name)}</span>${t.tools!=null?` <span class="cm-c">${l(ct(t.tools,"tool","tools"))}</span>`:""}</span>${n(t.tokens)}</li>`:t.kind==="skill"?`<li class="cm-s"><span class="cm-n"><span class="mono">${l(t.name)}</span></span>${n(t.tokens)}</li>`:t.kind==="file"?`<li class="cm-s cm-file"><span class="cm-n mono" title="${l(t.path)}"><bdi>${l(t.path)}</bdi></span>${Ce(t.path,null,e.editor)}${n(t.tokens)}</li>`:`<li class="cm-s"><span class="cm-n">${l(t.label)}${t.count!=null?` <span class="cm-c num">${t.count}</span>`:""}</span>${n(t.tokens)}</li>`}function Vu(t,e){const n=Du(t.d?.contextBreakdown,t.d),s=c=>`<span class="cm-v num">${l(k(c))}</span><span class="cm-p num">${Tr(c,n.whole)}</span>`,a=n.groups.filter(c=>!c.missing&&Uu.includes(c.key)&&c.tokens>0),o=n.recorded?`<div class="stack cm-bar" aria-hidden="true">${a.map(c=>`<i data-k="${c.key}" data-w="${Cr(c.tokens,n.whole)}"></i>`).join("")}${n.reserve?`<i class="cm-res" data-w="${(n.reserve/n.whole*100).toFixed(2)}"></i>`:""}</div>`:"",r=n.groups.map(c=>{if(c.missing)return`<li class="cm" data-k="${c.key}" data-missing><div class="cm-r"><span class="cm-sp"></span><i></i><span class="cm-n">${c.term?ft(c.term,c.label):`<span class="cm-l">${l(c.label)}</span>`}</span><span class="cm-nr v-d">Not recorded</span></div></li>`;if(!c.kids)return`<li class="cm" data-k="${c.key}"><div class="cm-r"><span class="cm-sp"></span><i></i><span class="cm-n">${ft(c.term,c.label)}</span>${s(c.tokens)}</div></li>`;const u=`ctx:${c.key}`,d=t.rows.has(u),p=c.none==="no-skills"?`${e} has no skills loaded here.`:c.none,h=c.kids.length?c.kids.map(f=>qu(f,t)).join(""):`<li class="cm-s cm-none">${l(p||"")}</li>`;return`<li class="cm" data-k="${c.key}"${d?" data-open":""}><button type="button" class="cm-r" data-act="row" data-key="${u}" aria-expanded="${d}" data-tip="${l(c.tip)}">${T.chev}<i></i><span class="cm-n"><span class="cm-l">${l(c.label)}</span>${c.count!=null?`<span class="cm-c num">${c.count}</span>`:""}</span>${s(c.tokens)}</button>${d?`<ul class="cm-sub">${h}</ul>`:""}</li>`}).join(""),i=n.recorded?`<p class="cm-note">${l(`The total is ${e}'s own count. Threadgauge estimates the parts.`)}</p>`:"";return`${o}<ul class="cmix">${r}</ul>${i}`}const Gu=t=>(t||[]).map(e=>`<p class="comp-list">${l(`Compacted at ${st(e.at)}, from ${k(e.before)} to ${k(e.after)}`)}</p>`).join("");function Ku(t){const{s:e,d:n}=t,s=e.context;if(!s)return dt({id:"context",name:"Context",term:"contextWindow",summary:Lt(!1),body:()=>"",empty:!0});const a=s.limit||0,o=a?s.used/a*100:null,r=Pu(e,n),i=mt("",`<b class="v-b">${o==null?l(k(s.used)):`${Math.round(o)}%`}</b>${a?`<span class="v-d">${l(`${k(s.used)}/${k(a)}`)}</span>`:""}${Ha(r.gauge,r.val,r.sub)}${Ha(r.spark,r.val,r.sub)}`);return dt({id:"context",name:"Context",term:"contextWindow",summary:i,body:()=>{const u=o==null?"":Tt("context",{...r.gauge,...r.spark.hist?{hist:r.spark.hist}:{}},34),d=r.room==null?"":`<span class="v-d">${ft("room","Room left")} ${l(`about ${It(r.room)}`)}</span>`,p=n?.history==null?"":`<h3 class="subhead">${ft("history","Context over time")}</h3>${n.history.length?rr():'<p class="note">No replies yet</p>'}${Gu(n.compactions)}`;return`<div class="ctx-top">${u}<b>${o==null?l(k(s.used)):`${o.toFixed(1)}%`}</b><span>used</span><span class="v-d">${l(`${k(s.used)}${a?` of ${k(a)}`:""}`)}</span>${d}</div>
|
|
183
|
+
${Vu(t,t.harnessName)}
|
|
184
|
+
${p}
|
|
185
|
+
<h3 class="subhead">Tokens over the whole thread</h3>
|
|
186
|
+
<div class="figs-row">${xr(e.tokens,n)}</div>`},open:t.isOpen("context"),harness:e.harness,flash:z(t.flash,"sec:context")})}const Yu=[["cacheRead","Cache reads","cacheRead"],["cacheWrite","Cache writes","cacheWrite"],["input","New input","window"],["output","Latest output","window"]];function zu(t,{open:e=!1,toggle:n=!1}={}){const s=t?.contextParts;if(!s)return"";const a=s.input+s.cacheRead+s.cacheWrite+s.output,o=Yu.map(([i,c,u])=>({key:i,label:c,term:u,v:s[i]||0})),r=o.filter(i=>i.v>0).map(i=>`<i data-k="${i.key}" data-w="${Cr(i.v,a)}"></i>`).join("");return`<section class="ctx">
|
|
187
|
+
<div class="ctx-h">${ft("context","Context")}<b>${l(`${k(a)} used`)}</b></div>
|
|
188
|
+
<div class="ctx-bar" role="img" aria-label="${l(o.map(i=>`${i.label} ${k(i.v)}`).join(", "))}">${r}</div>
|
|
189
|
+
${e?`<div class="ctx-rows">${o.map(i=>`<span class="dot" data-k="${i.key}"></span>${ft(i.term,i.label)}<span class="num">${l(k(i.v))}</span><span class="num dim">${Tr(i.v,a)}</span>`).join("")}</div>`:""}
|
|
190
|
+
${n?`<button type="button" class="toggle-line" data-act="ctx-rows" aria-expanded="${e}">${T.chev}${e?"Hide the breakdown":"What fills it"}</button>`:""}
|
|
191
|
+
</section>`}const Ba=3;function Xu(t,e){return!e||t?.status!=="done"?e:e.map(n=>n.status==="completed"?n:{...n,status:"completed"})}const Lr={completed:"Done",in_progress:"Current",pending:"Pending"},es=t=>t in Lr?t:"pending";function Ju(t,e){return t.status==="completed"?at("done"):t.status==="in_progress"?at(["asking","working","delegating","error"].includes(e)?e:"working"):`<span class="lamp" data-st="idle">${Ns.pending}</span>`}function Zu(t){const{s:e,d:n}=t,s=Xu(e,n?.plan)||[],a=ie(e),o=a?.total?`<span class="s-plan only-closed" data-st="${l(e.status)}" data-term="plan" data-rowtip ${kt(Fs(a),`${a.done} of ${a.total} steps`,a.current||"All steps done")}>${kn(a,e.status,"compact")}</span>`:"",r=a?.total?mt(a.current?l(a.current):'<span class="v-d">All steps done</span>',`${o}<span class="ratio"><b class="v-b">${a.done}</b><span class="v-d">/${a.total}</span></span>`):Lt(!!n);return dt({id:"plan",name:"Plan",term:"plan",summary:r,body:()=>`<div class="plan-bar" data-st="${l(e.status)}" aria-hidden="true">${s.map(c=>`<i data-s="${es(c.status)}"></i>`).join("")}</div><ol>${s.map((c,u)=>`<li class="step" data-s="${es(c.status)}" aria-label="${l(`${Lr[es(c.status)]}: ${c.content}`)}"${z(t.flash,`step:${u}`)}>${Ju(c,e.status)}<span>${l(c.content)}</span></li>`).join("")}</ol>`,empty:!s.length,open:t.isOpen("plan"),harness:e.harness,flash:z(t.flash,"sec:plan")})}function Qu(t){const n=String(t||"").split(`
|
|
192
|
+
`).map(a=>a.trim()).filter(Boolean).at(-1)||"";return n.split(/(?<=[.?!])\s+/).at(-1)||n}function tp(t){const{s:e,d:n,now:s}=t;if(n&&n.thoughts==null)return"";const a=(n?.thoughts||[]).slice().reverse();if(!a.length)return dt({id:"thoughts",name:"Thoughts",term:"thoughts",summary:Lt(!!n),body:()=>"",empty:!0});const o=a[0],r=t.showAll.has("thoughts"),i=mt(l(Qu(o.text)),`<span class="v-d" data-age="${o.at}">${l(Sn(s-o.at))}</span>`);return dt({id:"thoughts",name:"Thoughts",term:"thoughts",summary:i,body:()=>`<ol>${(r?a:a.slice(0,Ba)).map(d=>`<li class="thought"${z(t.flash,`thought:${d.at}`)}><span class="t">${l(d.text)}</span><span class="when num">${l(Bt(d.at))}</span></li>`).join("")}</ol>${_e("thoughts",r,a.length,Ba)}`,open:t.isOpen("thoughts"),harness:e.harness,flash:z(t.flash,"sec:thoughts")})}const Er={working:"Working",done:"Done",error:"Error",idle:"Idle"},Or=t=>t==="working"?"working":t==="error"?"error":t==="idle"?"idle":"done",Nr=t=>(t||[]).slice().sort((e,n)=>(n.startedAt||n.lastActivityAt||0)-(e.startedAt||e.lastActivityAt||0));function Hr(t){const e=t||[];return{running:e.filter(n=>n.status==="working").length,total:e.length}}function ep(t,e){const n=[t.type,ht(t.model),t.tokens&&`${k(t.tokens.output)} output`].filter(Boolean).map(s=>`<span>${l(s)}</span>`);return t.tool&&Number.isFinite(t.tool.startedAt)?n.push(`<span>${l(P(t.tool.name))} <span data-dur="${t.tool.startedAt}">${l(At(e-t.tool.startedAt))}</span></span>`):t.lastActivityAt&&n.push(`<span>last active ${l(Bt(t.lastActivityAt))}</span>`),n.join("")}function np(t){const{s:e,d:n,now:s}=t,a=Nr(n?.subagents),{running:o,total:r}=Hr(a),i=Ws.has(e.harness),c=r?mt("",`<span class="ratio"><b class="v-b${o?" v-run":""}">${o}</b><span class="v-d">/${r}</span></span>${le("subagents",{k:"orbit",sec:"subagents",run:o,total:r},`${o} of ${r} running`)}`):Lt(!!n),u=d=>{const p=Or(d.status),h=`${at(p)}<span><span class="nm">${l(d.name)}</span><span class="fx num"><span class="fs">${l(Er[d.status]||d.status||"")}</span>${ep(d,s)}</span></span>`,f=`data-st="${p}"${z(t.flash,`agent:${d.id}`)}`;return i?`<li><button type="button" class="agent" data-act="agent" data-key="${l(d.id)}" ${f} title="${l(`Show what ${d.name} did`)}">${h}${T.chev}</button></li>`:`<li><div class="agent" ${f}>${h}</div></li>`};return dt({id:"subagents",name:"Subagents",term:"subagents",summary:c,body:()=>`<ul>${a.map(u).join("")}</ul>`,empty:!r,open:t.isOpen("subagents"),harness:e.harness,flash:z(t.flash,"sec:subagents")})}function sp(t,e){const n=Or(e.status),s=[e.type,ht(e.model),e.tokens&&`${k(e.tokens.output)} output`,e.tool&&`now ${P(e.tool.name)}`].filter(Boolean);return`<header class="d-head d-pad">
|
|
193
|
+
<button type="button" class="back" data-act="agent-back">${T.back}<span>${l(`Back to ${t.title}`)}</span></button>
|
|
194
|
+
<div class="d-state" data-st="${n}">${at(n)}<span class="st">${l(Er[e.status]||e.status||"")}</span><span class="hn">Subagent</span></div>
|
|
195
|
+
<h1 class="d-title">${l(e.name)}</h1>
|
|
196
|
+
${s.length?`<div class="where agent-facts">${s.map(a=>`<span class="w">${l(a)}</span>`).join("")}</div>`:""}
|
|
197
|
+
</header>`}function Br(t,e=null){const{s:n,d:s,now:a}=t,o=(s?.prompts||[]).slice().reverse(),r=e??o.length,i=o.length?mt("",`<b class="v-b">${r}</b><span class="v-d" data-age="${o[0].at}">${l(Sn(a-o[0].at))}</span>`):Lt(s?.prompts!=null);return dt({id:"prompts",name:"Prompts",term:"promptList",summary:i,body:()=>{const u=Cn(t.layout),d=t.showAll.has("prompts");return`<ol>${(d?o:o.slice(0,u)).map(h=>{const f=`prompt:${h.at}`,m=h.text.length>rn||h.text.includes(`
|
|
198
|
+
`),y=t.rows.has(f)||!m,$=m?` <button type="button" class="linkbtn" data-act="row" data-key="${l(f)}" aria-expanded="${y}">${y?"Show less":"Show all"}</button>`:"";return`<li class="prompt"${z(t.flash,f)}><span class="t">${l(y?h.text:Tn(h.text,rn))}${$}</span><span class="when num">${l(Bt(h.at))}</span>${pt("Copy prompt",h.text)}</li>`}).join("")}</ol>${_e("prompts",d,o.length,u)}`},empty:!o.length,open:t.isOpen("prompts"),harness:n.harness,flash:z(t.flash,"sec:prompts")})}function Rr(t,e,n={},s={}){if(e==null||e==="")return"";const a=[];return n.copy&&a.push(pt(n.copy,e)),n.folder&&a.push(Ce(e,null,s.fileManager||"Files")),n.file&&a.push(Ce(e,null,s.editor||"VS Code")),`<dt>${l(t)}</dt><dd><span class="v${n.mono?" mono":""}">${l(e)}</span>${a.join("")}</dd>`}function ap(t,e){return e?.models?.length?e.models.map(n=>`${ht(n.model)}, ${n.costUsd==null?`${k(n.tokens?.output)} output`:Bs(n.costUsd)}`).join(`
|
|
199
|
+
`):ht(t.model)}const op=(t,e)=>e?.sessionId||t.id.slice(t.id.indexOf(":")+1);function rp(t){const{s:e,d:n,now:s}=t,a=_u(e,s),o=Math.max(0,a.endAt-e.startedAt||0),r=`<span${a.live?` data-dur="${e.startedAt}"`:""}>${l(At(o))}</span>`,i=`since ${st(e.startedAt)}`,c=mt("",`<b class="v-b">${r}</b><span class="v-d">${l(ht(e.model))}</span>${io(e.effort)}${le("duration",{k:"watch",sec:"duration",ms:o,bins:bn(n?.activity,s).bins},At(o),i)}`),u=(p,h,f)=>Rr(p,h,f,t);return dt({id:"session",name:"Session",term:"session",summary:c,body:()=>`<div class="figs-row">${Ar(a,n,s)}${Sr(e.costUsd,t.allSpend,"the spend across all threads")}</div><dl class="facts">
|
|
200
|
+
${u("Session id",op(e,n),{mono:1,copy:"Copy session id"})}
|
|
201
|
+
${u("Resume",t.resume,{mono:1,copy:"Copy resume command"})}
|
|
202
|
+
${u("Folder",e.cwd,{mono:1,copy:"Copy path",folder:1})}
|
|
203
|
+
${u("Project",e.projectPath,{mono:1,copy:"Copy path",folder:1})}
|
|
204
|
+
${u("Branch",e.gitBranch,{copy:"Copy branch name"})}
|
|
205
|
+
${e.worktree?u("Worktree",e.worktree,{copy:"Copy worktree name"}):u("Worktree","None, it runs in the main checkout")}
|
|
206
|
+
${u("Effort",e.effort&&gn(e.effort),{copy:"Copy effort"})}
|
|
207
|
+
${u("Models",ap(e,n),{copy:"Copy models"})}
|
|
208
|
+
${u("Started",e.startedAt?hs(e.startedAt):"",{copy:"Copy start time"})}
|
|
209
|
+
${u("Last active",e.lastActivityAt?hs(e.lastActivityAt):"",{copy:"Copy last active time"})}
|
|
210
|
+
${u("Source",n?.source,{mono:1,copy:"Copy path",file:1})}
|
|
211
|
+
</dl>`,open:t.isOpen("session"),harness:e.harness,flash:z(t.flash,"sec:session")})}function ip(t,e){const{d:n}=t,s=n?.activity?.[0]?.startedAt||e.startedAt,a=(i,c,u)=>Rr(i,c,u,t),o=mt("",`<span class="mono v-d">${l(String(e.id).slice(0,8))}</span><span class="v-d">${l(ht(e.model))}</span>`);return dt({id:"session",name:"Facts",summary:o,body:()=>`<dl class="facts">
|
|
212
|
+
${a("Subagent id",e.id,{mono:1,copy:"Copy subagent id"})}
|
|
213
|
+
${a("Type",e.type,{copy:"Copy type"})}
|
|
214
|
+
${a("Model",ht(e.model),{copy:"Copy model"})}
|
|
215
|
+
${a("Started",s?hs(s):"",{copy:"Copy start time"})}
|
|
216
|
+
${a("Source",n?.source,{mono:1,copy:"Copy path",file:1})}
|
|
217
|
+
</dl>`,open:t.isOpen("session")})}const lp=t=>t.length>1?`${t.slice(0,-1).join(", ")}, or ${t.at(-1)}`:t[0];function cp(t,e,n){const s=[[t.tokens==null,"tokens"],[t.context==null,"context"],[t.costUsd==null,"spend"],[t.lines==null,"lines changed"],[t.prompts==null&&e?.prompts==null,"prompts"],[t.plan==null&&!e?.plan,"a plan"],[!e,"tool calls"],[!e,"files"],[!e,"subagents"]].filter(o=>o[0]).map(o=>o[1]),a=[];return s.length&&a.push(`${n} did not record ${lp(s)}${t.older?" for this older thread":""}, so those figures show —.`),e||a.push(`Threadgauge can't read more detail for ${n} threads yet.`),a.join(" ")}function dp(t,e,n){const s=cp(t,e,n);return s?`<p class="unrec">${l(s)}</p>`:""}const up=t=>(t||[]).slice().sort((e,n)=>n.calls-e.calls),pp=(t,e)=>Math.max(2,t/Math.max(1,e)*100).toFixed(2);function hp(t,e,n){const s=[`<span>${t.calls===1?"1 call":`${t.calls} calls`}</span>`];t.ms&&s.push(`<span>${l(nt(t.ms))}</span>`),t.errors&&s.push(`<em>${t.errors} failed</em>`);const a=P(t.name);return`<li><button type="button" class="bar-row" data-act="tool" data-key="${l(t.name)}" aria-pressed="${n.toolFilter===t.name}" title="${l(`Show only ${a} calls in Activity`)}"><span class="name">${co(lo(t))}<span>${l(a)}</span></span><span class="bar-track"><i data-w="${pp(t.calls,e)}"></i></span><span class="val">${s.join("")}</span></button></li>`}function _r(t){const{s:e,d:n,now:s}=t,a=up(n?.tools),o=a.reduce((u,d)=>u+d.calls,0),r=a[0],i=r?mt("",`<span class="v-b">${l(P(r.name))}</span><span class="v-d">${r.calls}</span>${le("tools",{k:"mix",sec:"tools",parts:a.map(u=>u.calls)},ct(a.length,"tool","tools"),`${o} calls in all`)}`):Lt(n?.tools!=null);return dt({id:"tools",name:"Tools",term:"tools",summary:i,body:()=>{const u=Math.max(1,...a.map(d=>d.calls));return`<div class="figs-row">${Mr(n,s)}</div><ul class="bars">${a.map(d=>hp(d,u,t.filter)).join("")}</ul>`},empty:!a.length,open:t.isOpen("tools"),harness:e.harness,flash:z(t.flash,"sec:tools")})}const Ir=t=>`<div class="d-scan d-pad"><p>${l(`Scanning this ${t}…`)}</p><div class="scan-bar"><i></i></div></div>`;function fp(t){return t?t.gone?{loaded:!1,note:"This thread isn't listed anymore."}:t.found?{loaded:!0,note:t.error||""}:{loaded:!1,note:t.error||""}:{loaded:!1,note:""}}function mp(t,e){const n=uu({...t,note:e.note}),s=t.layout.mode==="stack"?vu(t):"";if(!e.loaded)return`<div class="d-wrap">${n}${e.note?"":Ir("thread")}</div>${s}`;const a={thoughts:tp(t),plan:Zu(t),subagents:np(t),activity:vr(t),errors:kr(t),files:wr(t),tools:_r(t),context:Ku(t),prompts:Br(t,t.s.prompts),session:rp(t),note:dp(t.s,t.d,t.harnessName)},o=ir(La[t.layout.cols]||La[1],a);return`<div class="d-wrap">${n}<div class="cols d-pad">${o}</div></div>${s}`}function gp(t,e,n){const s=t.layout.cols<2,a=t.ctxRows??!s;return`<div class="d-top d-pad">${ju(e,n,{now:t.now,threadCost:t.s.costUsd})}${n?.history?.length?rr():""}${zu(n,{open:a,toggle:s})}</div>`}function $p(t,e,n){const s=sp(t.s,e);if(!n?.loaded)return`<div class="d-wrap">${s}${n?.error?`<p class="d-note d-pad">${l(n.error)}</p>`:Ir("subagent")}</div>`;const a=n.detail,o={...t,d:a,agentView:!0,overlaps:{},resume:null},r={activity:vr(o),tools:_r(o),files:wr(o),prompts:Br(o),errors:kr(o),session:ip(o,e),note:a?"":`<p class="unrec">This subagent's record is no longer in the thread.</p>`},i=ir(Ea[t.layout.cols]||Ea[1],r);return`<div class="d-wrap">${s}${gp(o,e,a)}<div class="cols d-pad">${i}</div></div>`}function yp(t){return t?[...(t.activity||[]).map(e=>({id:`call:${e.id}`,status:""})),...(t.subagents||[]).map(e=>({id:`agent:${e.id}`,status:e.status})),...(t.plan||[]).map((e,n)=>({id:`step:${n}`,status:e.status})),...(t.thoughts||[]).map(e=>({id:`thought:${e.at}`,status:""})),...(t.errors||[]).map(e=>({id:`error:${e.at}:${e.message}`,status:""})),...(t.files||[]).map(e=>({id:`file:${e.path}`,status:`${e.added}|${e.removed}`})),...(t.prompts||[]).map(e=>({id:`prompt:${e.at}`,status:""}))]:[]}function wp(t,e){if(!e)return new Map;const n=e.activity||[],{running:s,total:a}=Hr(Nr(e.subagents)),o=gr(e.files||[]);return new Map([["sec:plan",t?.plan?`${t.plan.done}/${t.plan.total}`:""],["sec:activity",`${n.length}|${n.filter(r=>r.error).length}`],["sec:subagents",`${s}/${a}`],["sec:thoughts",String(e.thoughts?.length??0)],["sec:errors",String(e.errors?.length??0)],["sec:files",`${e.files?.length??0}|${o.added}|${o.removed}`],["sec:tools",String((e.tools||[]).reduce((r,i)=>r+i.calls,0))],["sec:prompts",String(t?.prompts??e.prompts?.length??0)],["sec:context",t?.context?String(t.context.used):""]])}const bp=1200,Y=(t,e=document)=>e.querySelector(t),Le=(t,e=document)=>[...e.querySelectorAll(t)],Ra=(t,e,n)=>n?t.setAttribute(e,""):t.removeAttribute(e),w={open:{},rows:new Set,showAll:new Set,filter:{toolFilter:null,failedOnly:!1,timeFilter:null},pin:null,ctxRows:null,agent:null,phoneConversation:!1,cvTools:!0,cvRuns:new Set,cvFor:null,cvStick:!0,cvScroll:0,enterPanel:!1,version:0};let I=null,lt=null,W=null,rt=null,yt=null,be="",ns="";const En=new Map,ks=new Set;function Gs(){w.rows.clear(),w.showAll.clear(),w.filter={toolFilter:null,failedOnly:!1,timeFilter:null},w.pin=null}function vp(t){I=t,lt=t.det;for(const e of[t.det,t.panel])e.addEventListener("click",Ip),e.addEventListener("change",jp);lt.addEventListener("pointerover",e=>{const n=e.target.closest?.(".call[data-at]");n?.dataset.at&&ss(Number(n.dataset.at))}),lt.addEventListener("pointerout",e=>{const n=e.target.closest?.(".call[data-at]");n&&!n.contains(e.relatedTarget)&&ss(null)}),lt.addEventListener("focusin",e=>{const n=e.target.closest?.(".call[data-at]");n?.dataset.at&&e.target.matches?.(":focus-visible")&&ss(Number(n.dataset.at))})}const xs=()=>W?.layout?.mode==="stack",On=()=>xs()?w.phoneConversation:!!I?.view().conversation;function tt(){w.version++,I.rerender()}function kp(t,e,n,s){const a=t.session,o=t.layout,r=or(),i=t.entry?.found;return{s:a,d:e,id:t.id,harnessName:t.harnessName,canOpen:t.canOpen,layout:o,now:n,repo:I.view().repo||"",rows:w.rows,showAll:w.showAll,filter:w.filter,editor:Dd(r),editorId:r,fileManager:ar,base:a.cwd||a.projectPath||"",resume:i?.resume??null,overlaps:i?.overlaps||{},allSpend:I.allSpend?.()??null,hunkOf:c=>En.get(Vs(t.id,w.agent,c)),ctxRows:w.ctxRows,flash:s,isOpen:c=>lr(c,w.open,{agent:!!w.agent,status:a.status,layout:o}),cvOpen:On(),cv:{tools:w.cvTools,runs:w.cvRuns}}}function xp(t,e,n,s){return n?(yt?.scope!==t&&(yt={scope:t,rows:null,values:null}),yt.rows=mo(yt.rows,yp(n),s),yt.values=go(yt.values,wp(e,n),s,t),{arrived:yt.rows.arrived,changed:new Map([...yt.rows.changed,...yt.values.at])}):null}function Mp(t,e){for(const[n,s,a]of[["arrive","--ad",Je],["flash","--fd",_t]])for(const o of Le(`[data-${n}]`,t)){const r=$o(Number(o.dataset[n]),e,a);r==null?o.removeAttribute(`data-${n}`):o.style.setProperty(s,r)}}const Ap=t=>[t.mode,t.cols,t.span,t.flat,t.h,t.narrowDet,t.cvOver].join(",");function Sp(t,e){lt=t,W=e;const n=e.session;if(!n){be="",_a({d:null}),t.innerHTML=`<div class="d-wrap">${pu()}</div>`,Ms(null);return}const s=e.entry,a=s?.found?.detail??null;w.agent&&s?.found&&!a?.subagents?.some(p=>p.id===w.agent)&&(w.agent=null,rt=null);const o=w.agent?a?.subagents?.find(p=>p.id===w.agent)??null:null,r=Date.now(),i=o?rt?.loaded?rt.detail:null:a,c=xp(`${e.id}|${w.agent||""}`,n,i,r),u=kp(e,a,r,c),d=[JSON.stringify(n),s?.at,s?.error,s?.gone,w.version,Ap(e.layout),u.repo,u.cvOpen,rt?.version,u.editorId].join("|");(d!==be||!t.firstChild)&&(be=d,t.innerHTML=o?$p(u,o,rt):mp(u,fp(s)),Mp(t,r),Tp(t),_a({d:i,s:n,agent:!!o,layout:e.layout})),Ms(u),o&&rt&&!rt.fetching&&rt.forAt!==s?.at&&jr();for(const p of Su(i,w.rows,h=>En.has(h)||ks.has(h),e.id,w.agent))Cp(e.id,w.agent,p)}function Tp(t){for(const e of Le("[data-w]",t))e.style.width=`${e.dataset.w}%`}async function Cp(t,e,n){const s=Vs(t,e,n);ks.add(s);let a;try{const o=await I.fetchHunks(t,n.path,e);a=o?{hunks:o.hunks||[]}:{error:"That change is no longer in this thread."}}catch(o){a={error:`Couldn't read the change: ${o.message}`}}ks.delete(s),En.set(s,a),W?.id===t&&(w.agent||null)===(e||null)&&tt()}let R=null,ne=null;function _a(t){ne?.disconnect(),ne=null,R=null;const e=Y("[data-chart]",lt);if(!e||!t.d?.history?.length)return;const n=Y("svg",e);let s=0;const a=()=>{s=Math.floor(e.clientWidth);const o=t.agent?0:t.s.context?.limit||0,r=Gd(t.d,{W:Math.max(120,s),plotH:Ud(t.layout),limit:o});r&&(n.setAttribute("viewBox",`0 0 ${r.W} ${r.H}`),n.setAttribute("height",String(r.H)),n.innerHTML=Kd(r,{ping:!t.agent&&ze(t.s)}),n.setAttribute("aria-label",Yd(r)),Y(".chart-key",e).innerHTML=zd(r,{agent:t.agent}),R={host:e,svg:n,m:r,agent:t.agent},ve(w.pin!=null&&w.pin<r.pts.length?w.pin:null))};a(),n.dataset.wired||(n.dataset.wired="",n.addEventListener("pointermove",o=>Ia(o)),n.addEventListener("pointerleave",()=>ve(w.pin)),n.addEventListener("pointerdown",o=>{const r=Ia(o);r!=null&&(w.pin=w.pin===r?null:r,ve(w.pin??r))}),n.addEventListener("keydown",Lp)),ne=new ResizeObserver(()=>{Math.floor(e.clientWidth)!==s&&a()}),ne.observe(e)}function ve(t){if(!R)return;const e=Y("[data-c]",R.svg),n=Y("[data-d]",R.svg);if(t==null)e.setAttribute("visibility","hidden"),n.setAttribute("visibility","hidden");else{const s=R.m.pts[t],a=R.m.x(s.at);for(const[o,r]of[["x1",a],["x2",a],["visibility","visible"]])e.setAttribute(o,r);n.setAttribute("cx",a),n.setAttribute("cy",R.m.y(s.context)),n.setAttribute("visibility","visible")}Y(".chart-read",R.host).innerHTML=Xd(R.m,t,{pinned:t!=null&&w.pin===t,agent:R.agent})}function Ia(t){if(!R)return null;const e=R.svg.getBoundingClientRect(),n=(t.clientX-e.left)/Math.max(1,e.width)*R.m.W,s=Vd(R.m.pts,R.m.timeAt(n));return ve(s),s}function Lp(t){if(!R)return;const e=R.m.pts.length-1,n=w.pin==null?e:w.pin,s={ArrowLeft:Math.max(0,n-1),ArrowRight:Math.min(e,n+1),Home:0,End:e}[t.key];s!=null&&(t.preventDefault(),w.pin=s,ve(s))}function ss(t){if(!R)return;const e=Y("[data-m]",R.svg);if(t==null)return e.setAttribute("visibility","hidden");const n=R.m.x(t);e.setAttribute("x1",n),e.setAttribute("x2",n),e.setAttribute("visibility","visible")}function Ep(){W=null,be="",ne?.disconnect(),ne=null,R=null,Ms(null)}function Ms(t){const e=I?.panel;if(!e)return;const n=t?.layout;if(!t||n.table||n.mode==="stack"&&!w.phoneConversation){e.hidden=!0,Ra(e,"data-open",!1),e.firstChild&&e.replaceChildren(),ns="";return}const s=t.cvOpen,a=s?bu(t,{stack:n.mode==="stack",over:n.cvOver,enter:w.enterPanel}):wu(t);if(w.enterPanel=!1,e.hidden=!1,e.dataset.st=t.s.status,Ra(e,"data-open",s),a===ns)return;ns=a;const o=document.activeElement,r=o&&e.contains(o)&&o.dataset.act?`[data-act="${o.dataset.act}"]${o.dataset.key!=null?`[data-key="${CSS.escape(o.dataset.key)}"]`:""}`:null;e.innerHTML=a,r&&!e.contains(document.activeElement)&&Y(r,e)?.focus({preventScroll:!0});const i=Y(".cv-stream",e);i&&(w.cvFor!==t.id&&(w.cvFor=t.id,w.cvStick=!0),i.scrollTop=w.cvStick?ja(i):w.cvScroll,i.addEventListener("scroll",()=>{w.cvScroll=i.scrollTop,w.cvStick=i.scrollHeight-i.scrollTop-i.clientHeight<24||Math.abs(i.scrollTop-ja(i))<24},{passive:!0}))}function ja(t){const e=t.scrollHeight-t.clientHeight,n=t.lastElementChild;if(!n?.hasAttribute("data-tail"))return e;let s=n.previousElementSibling;for(;s&&s.matches(".cv-time, .cv-new");)s=s.previousElementSibling;if(!s)return e;const a=s.getBoundingClientRect().top-t.getBoundingClientRect().top+t.scrollTop-8;return Math.max(0,Math.min(e,a))}function Op(t,e){for(const n of[lt,I?.panel])if(n?.firstChild){for(const s of Le("[data-now]",n)){const a=e(s.dataset.now);if(!a)continue;const o=xn(a,t);s.dataset.t!==o&&(s.dataset.t=o,s.innerHTML=He(a,t))}for(const[s,a]of[["since",o=>nt(t-o)],["ago",o=>$t(t-o)],["age",o=>Sn(t-o)],["dur",o=>At(t-o)]])for(const o of Le(`[data-${s}]`,n)){const r=a(Number(o.dataset[s]));o.textContent!==r&&(o.textContent=r)}}}async function jr(){const t=rt;if(!t||!W)return;t.fetching=!0,t.forAt=W.entry?.at;let e;try{e={loaded:!0,detail:(await I.fetchSubagent(t.thread,t.id))?.detail??null,error:""}}catch(n){e={loaded:t.loaded,detail:t.detail,error:t.loaded?"":`Couldn't read this subagent: ${n.message}`}}t.fetching=!1,rt===t&&(Object.assign(t,e,{version:t.version+1}),I.rerender())}function Np(){for(const t of Le(".d-wrap, .col",lt))t.scrollTop=0}function Hp(t){W?.session&&I.morph(()=>{w.agent=t,rt={thread:W.id,id:t,loaded:!1,detail:null,error:"",fetching:!1,forAt:null,version:0},Gs(),w.version++}).then(()=>{Np(),Y('[data-act="agent-back"]',lt)?.focus({preventScroll:!0}),jr()})}function Pr(){const t=w.agent;I.morph(()=>{w.agent=null,rt=null,Gs(),w.version++}).then(()=>{(Y(`[data-act="agent"][data-key="${CSS.escape(t||"")}"]`,lt)||lt)?.focus({preventScroll:!0})})}function ln(t){if(!W?.session||On()===t)return;const e=W.layout,n=xs()||ho({thread:!0,open:!0},e.lw,e.w,e.lwc).over,s=document.activeElement?.closest?.('[data-act="cv-open"], [data-act="cv-close"]');I.relayout(()=>{xs()?w.phoneConversation=t:I.saveConversation(t),w.cvStick=!0,w.enterPanel=t&&!n,w.version++},n).then(()=>{const a=I.panel;t&&s?Y('[data-act="cv-close"]',a)?.focus({preventScroll:!0}):t||(Y(".cv-rail",a)||Y(".cv-dockbar",lt))?.focus({preventScroll:!0})})}function Bp(){W?.session&&ln(!On())}async function Rp(t){const e=t.dataset.copy||"";let n=!1;try{await navigator.clipboard.writeText(e),n=!0}catch{const a=document.createElement("textarea");a.value=e,a.setAttribute("readonly",""),a.style.position="fixed",a.style.opacity="0",document.body.append(a),a.select();try{n=document.execCommand("copy")}catch{}a.remove()}if(!n){I.toast("The browser blocked the clipboard. Select the text and copy it by hand.","err");return}if(!t.classList.contains("ib")){I.toast("Copied.");return}const s=t.innerHTML;t.innerHTML=T.check,t.dataset.copied="",setTimeout(()=>{t.isConnected&&(t.innerHTML=s,delete t.dataset.copied)},bp)}async function _p(t){const e=t.dataset.path||"",n=t.dataset.line?Number(t.dataset.line):null,s=await I.openPath({id:W?.id,path:e,line:n,editor:or(),agent:w.agent}),a=eo(String(s.path||e)).name||"that file";s.ok?s.kind==="folder"?I.toast(`Opened ${a} in ${ar}`):I.toast(`Opened ${a} in ${s.editor}`):I.toast(s.error||`Couldn't open ${a}`,"err")}const as=(t,e)=>t.has(e)?t.delete(e):t.add(e);function Ip(t){if(t.target.closest?.("[data-term]:not([data-rowtip])"))return;const e=t.target.closest?.("[data-act]");if(!e||!W?.session)return;const{act:n,key:s}=e.dataset;switch(n){case"sec":{const a=W.layout;w.open[s]=!lr(s,w.open,{agent:!!w.agent,status:W.session.status,layout:a}),tt();break}case"row":as(w.rows,s),tt();break;case"show-all":as(w.showAll,s),tt();break;case"failed":w.filter.failedOnly=!w.filter.failedOnly,tt();break;case"clear-activity":w.filter={toolFilter:null,failedOnly:!1,timeFilter:null},tt();break;case"clear-time":w.filter.timeFilter=null,tt();break;case"tool":w.filter.toolFilter=w.filter.toolFilter===s?null:s,w.open.activity=!0,tt(),w.filter.toolFilter&&Pa(!0);break;case"calls-near":{const a=R?Jd(R.m.pts,Number(s),W.session.startedAt):null;if(!a)break;w.filter={toolFilter:null,failedOnly:!1,timeFilter:a},w.open.activity=!0,tt(),Pa(!1);break}case"ctx-rows":w.ctxRows=!(w.ctxRows??W.layout.cols>=2),tt();break;case"agent":Hp(s);break;case"agent-back":Pr();break;case"copy":Rp(e);break;case"open-path":_p(e);break;case"where-repo":I.setRepo(s);break;case"cv-open":ln(!0);break;case"cv-close":ln(!1);break;case"cv-run":{const a=Y(".cv-stream",I.panel);a&&(w.cvScroll=a.scrollTop,w.cvStick=!1),as(w.cvRuns,s),tt();break}case"cv-tools":w.cvTools=!w.cvTools,tt();break}}function Pa(t){const e=matchMedia("(prefers-reduced-motion: reduce)").matches;Y('[data-sec="activity"]',lt)?.scrollIntoView({block:"nearest",behavior:t&&!e?"smooth":"auto"})}function jp(t){const e=t.target.dataset?.change;e==="tool-filter"?(w.filter.toolFilter=t.target.value||null,tt()):e==="editor"&&(Fd(t.target.value),tt())}function Pp(){const t=W?.layout;return t&&W?.session&&On()&&(t.mode==="stack"||t.cvOver||document.activeElement?.closest?.("#cv-panel"))?(ln(!1),!0):w.agent?(Pr(),!0):!1}function Fp(){w.agent=null,rt=null,Gs(),En.clear(),yt=null,be=""}const Fa=".row, tbody tr";function Dp(t){const e=new IntersectionObserver(a=>{for(const o of a)o.target.toggleAttribute("data-off",!o.isIntersecting)},{root:t,rootMargin:"200px 0px"}),n=(a,o)=>{if(a.nodeType===1){a.matches(Fa)&&o(a);for(const r of a.querySelectorAll(Fa))o(r)}};new MutationObserver(a=>{for(const o of a){for(const r of o.removedNodes)n(r,i=>e.unobserve(i));for(const r of o.addedNodes)n(r,i=>e.observe(i))}}).observe(t,{childList:!0,subtree:!0}),n(t,a=>e.observe(a));const s=()=>document.documentElement.toggleAttribute("data-hidden",document.visibilityState==="hidden");document.addEventListener("visibilitychange",s),s()}function Wp(t,e){return{kicker:"Threadgauge Pro",title:"Answering is coming soon",text:`Answering threads from Threadgauge comes with Threadgauge Pro, which is coming soon. For now, answer in ${t}.`,open:e?`Open ${t}`:null,close:"Close"}}function Up(){const t=document.createElement("dialog");t.className="upgrade pro-soon",t.setAttribute("aria-labelledby","pro-soon-title");let e=()=>{};return t.addEventListener("click",n=>{n.target===t&&t.close();const s=n.target.closest?.("[data-pro]")?.dataset.pro;s==="close"&&t.close(),s==="open"&&(t.close(),e())}),{el:t,show({harnessName:n,canOpen:s,open:a}){e=a;const o=Wp(n,s);t.innerHTML=`<div class="upgrade-sheet"><p class="kicker">${l(o.kicker)}</p><h2 class="upgrade-title" id="pro-soon-title">${l(o.title)}</h2><p class="upgrade-text">${l(o.text)}</p><div class="upgrade-actions"><button type="button" class="btn" data-pro="close">${l(o.close)}</button>${o.open?`<button type="button" class="btn primary" data-pro="open">${T.open}${l(o.open)}</button>`:""}</div></div>`,t.open||t.showModal(),t.querySelector(o.open?'[data-pro="open"]':'[data-pro="close"]').focus({preventScroll:!0})}}}const qp=4200,Vp=350,Gp=400,Kp=800,Yp=1e3,zp=550,Xp=15e3,S=(t,e=document)=>e.querySelector(t),re=(t,e=document)=>[...e.querySelectorAll(t)],ee=(t,e,n)=>n?t.setAttribute(e,""):t.removeAttribute(e),Z=t=>!!t&&t!=="overview",Fr=(()=>{try{return window.localStorage}catch{return null}})(),Dr=document.documentElement,Ks=!1,Nn=()=>document.visibilityState!=="visible",M=Id({api:{connectLive:Mi,fetchDetail:$i,fetchEntitlements:mi,fetchHistory:bi,findThreadnauts:vi},previewFree:Ks,hidden:Nn}),g={view:fd(Fr),sel:null,next:sd,booted:!1,q:"",findOpen:!1,findI:0};let me=Xa(Dr,{sans:g.view.font,mono:g.view.mono}),A=null;const J=document.getElementById("app");J.innerHTML=`
|
|
218
|
+
<aside id="list" aria-label="Threads">
|
|
219
|
+
<header class="l-head">
|
|
220
|
+
<a class="brand" href="https://threadgauge.io" target="_blank" rel="noopener" title="threadgauge.io" aria-label="Threadgauge">${hi}${fi}</a>
|
|
221
|
+
<button type="button" class="conn" id="conn" data-act="connection" data-state="connecting"><i>${vl}</i><span>Connecting</span></button>
|
|
222
|
+
<button type="button" class="ib" data-act="find" data-tip="Search and actions (Ctrl+K)" aria-label="Search and actions" aria-expanded="false">${T.search}</button>
|
|
223
|
+
<button type="button" class="ib" data-act="shot" data-tip="Screenshot (P)" aria-label="Take a screenshot">${T.cam}</button>
|
|
224
|
+
<button type="button" class="ib" data-act="list-shut" data-tip="Collapse the threads ([)" aria-label="Collapse the threads ([)">${T.panelIn}</button>
|
|
225
|
+
<button type="button" class="ib" data-act="menu" data-tip="Settings (?)" aria-label="Settings" aria-expanded="false" aria-controls="prefs">${bl}</button>
|
|
226
|
+
</header>
|
|
227
|
+
<div class="find" hidden><span class="find-ico" aria-hidden="true">${T.search}</span><input id="q" type="search" placeholder="Search threads, or type an action" aria-label="Search threads and actions" autocomplete="off" spellcheck="false"><button type="button" class="ib" data-act="find-close" aria-label="Close search" data-tip="Close search (Esc)">${T.x}</button><div class="find-acts" hidden></div></div>
|
|
228
|
+
<div class="lamps" role="group" aria-label="Filter by status"></div>
|
|
229
|
+
<div class="filtered" hidden></div>
|
|
230
|
+
<div id="rows"></div>
|
|
231
|
+
<div id="rows-bar" aria-hidden="true" hidden><i></i></div>
|
|
232
|
+
<div class="band-bar"></div>
|
|
233
|
+
<div class="l-limits" aria-label="Usage limits"></div>
|
|
234
|
+
<footer class="l-foot" aria-label="Totals across the threads shown"></footer>
|
|
235
|
+
<div id="prefs" hidden role="region" aria-label="Settings"></div>
|
|
236
|
+
<div id="list-rail" hidden></div>
|
|
237
|
+
</aside>
|
|
238
|
+
<div id="split" role="separator" aria-orientation="vertical" aria-label="Resize the list" aria-controls="list" tabindex="0"></div>
|
|
239
|
+
<main id="det" aria-label="Details" tabindex="-1"></main>
|
|
240
|
+
<aside id="cv-panel" aria-label="Conversation" hidden></aside>`;document.body.insertAdjacentHTML("beforeend",`<div id="tip" hidden role="tooltip"></div><div id="toasts" role="status" aria-live="polite"></div>
|
|
241
|
+
<div class="boot" role="status"><div class="boot-inner"><div class="boot-brand">${pi}</div><p>Scanning for agent threads…</p><div class="scan-bar"><i></i></div></div></div>`);const Jp=S("#list"),je=S(".l-head"),Da=S(".brand"),te=S("#conn"),os=S('[data-act="shot"]',je),Wa=S('[data-act="menu"]',je),As=S(".find"),bt=S("#q"),cn=S(".find-acts"),Wr=S('[data-act="find"]',je),Ua=S(".lamps"),qa=S(".filtered"),Va=S(".l-limits"),Ga=S(".l-foot"),_=S("#rows");Dp(_);const ae=S("#rows-bar"),gt=S("#rows-bar i"),rs=S(".band-bar"),D=S("#prefs"),se=S("#list-rail"),et=S("#split"),K=S("#det"),Zp=S("#cv-panel"),ut=S("#tip"),Qp=S("#toasts"),Ur=new Ci({activate:gi}),qr=new Oi,Vr=Up();document.body.append(Ur.el,qr.el,Vr.el);const ce=()=>md(Fr,g.view),Ss=()=>Z(g.sel)?M.get(g.sel):null,Gr=()=>M.arranged(g.view,g.q),Ys=()=>new Set(g.view.collapsed),zs=()=>oo(Gr().groups,Ys(),g.sel,g.view.group),Kr=()=>A.mode==="stack"?null:"overview",Yr=()=>A.mode==="stack"?null:zs()[0]||"overview";vp({det:K,panel:Zp,fetchSubagent:wi,fetchHunks:yi,openPath:ki,toast:(t,e)=>it(t,e),rerender:()=>Ee(),morph:t=>jt(()=>{t(),Ee()}),relayout:(t,e=!0)=>{const n=()=>{t(),Pt()};return e?jt(n):(n(),Promise.resolve())},view:()=>g.view,allSpend:()=>M.list().reduce((t,e)=>t+(e.costUsd||0),0),saveConversation:t=>{g.view.conversation=t,ce()},setRepo:t=>{const e=g.view.repo===t;xt({repo:e?"":t}),it(e?"Showing every repo again.":"Showing only this repo's threads. Click the folder again to show every repo.")}});function zr(){const t=A,e=Z(g.sel)&&!!M.get(g.sel),n=(s,a,o)=>ho({thread:e,open:g.view.conversation},s,a,o);A=Ol({w:innerWidth,h:innerHeight,saved:g.view.listWidth,listShut:g.view.listShut,sel:g.sel,prefs:!D.hidden,conversation:n}),J.dataset.mode=A.mode,J.dataset.group=g.view.group,J.style.setProperty("--lw",`${A.lw}px`),J.style.setProperty("--lwc",`${A.lwc}px`),J.style.setProperty("--rw",`${A.rw}px`),J.style.setProperty("--bandh",`${A.bandh}px`);for(const[s,a]of Object.entries(Nl(A)))ee(J,s,a);return ee(J,"data-open",!!g.sel),ee(J,"data-band",A.mode==="stack"&&Z(g.sel)),K.dataset.cols=String(A.cols),ee(K,"data-span",A.span),ee(K,"data-flat",A.flat),et.setAttribute("aria-valuenow",String(A.lw)),et.setAttribute("aria-valuemin",String(Se)),et.setAttribute("aria-valuemax",String(Math.max(Se,A.w-po))),Bl(t,A)}function Xs(){const t=A.mode==="stack",e=A.lw,n=zr();if(V(),g.booted&&t&&A.mode==="side"&&!g.sel)return Vt(Yr(),"auto");if(A.mode==="stack"&&g.sel==="overview")return Vt(null,"auto");n?Pt():A.lw!==e&&zt(),!D.hidden&&A.table&&Gt(!0)}let Ts=!1;function Js(t,e){const n=document.activeElement;let s=null;if(n&&t.contains(n)&&(n.dataset.act?s=`${n.localName}[data-act="${n.dataset.act}"]${n.dataset.key!=null?`[data-key="${CSS.escape(n.dataset.key)}"]`:""}`:n.dataset.change?s=`[data-change="${n.dataset.change}"]`:n.dataset.term&&(s=`.term[data-term="${n.dataset.term}"]`)),e(),!s||t.contains(document.activeElement))return;const a=S(s,t);a&&(Ts=!0,a.focus({preventScroll:!0}),Ts=!1)}function Pt(){zr(),zt(),Ee(),oh()}const Xr=()=>Ic(M.list(),Date.now());function th(t){if(!g.view.repo)return"";const{orgs:e,loose:n}=Is(t,g.view.repo);return[...e.flatMap(s=>s.repos),...n].find(s=>s.key===g.view.repo)?.label||""}function eh(t,e=!1){const n=M.list();return{arranged:t,sel:g.sel,total:n.length,harnesses:M.state.harnesses,harnessName:M.harnessName,now:Date.now(),layout:A,view:g.view,q:g.q,quiet:e,collapsed:Ys(),repoLabel:th(n),limits:Xr(),detailOf:s=>M.detail(s)?.found?.detail??null}}function zt({live:t=!1,quiet:e=!1}={}){const n=Gr();Js(Jp,()=>{const o=t?0:_.scrollTop;if(M.state.received){Wc(M.list(),Date.now(),{quiet:e});const r=eh(n,e);Yc(Ua,r,{live:t}),zc(qa,r),Xc(Va,r),g.limitsResetAt=jc(r.limits,Date.now()),Zc(Ga,r,{live:t}),A.table?Pd(_,r,{live:t}):Gc(_,r)}else{for(const r of[_,Ua,Va,Ga])r.replaceChildren();qa.hidden=!0}t||(_.scrollTop=o),rh(n),ih()}),t?nh():de();const s=M.list().filter(o=>o.status==="asking").length,a=s?`(${s}) Threadgauge`:"Threadgauge";document.title!==a&&(document.title=a),U&&!U.isConnected&&V()}let is=0;function nh(){is||(is=requestAnimationFrame(()=>{is=0,A.table&&jd(_),de()}))}let ke={sel:null,session:null,entry:null};function Ee(){if(!Z(g.sel)){K.firstChild&&K.replaceChildren(),delete K.dataset.key,Ep(),ke={sel:null,session:null,entry:null};return}const t=`${g.sel}|${A.cols}|${A.span}`,e=K.dataset.key===t,n=e?re(".d-wrap, .col",K).map(o=>o.scrollTop):[],s=M.get(g.sel),a=M.detail(g.sel);Js(K,()=>Sp(K,{id:g.sel,session:s,entry:a,harnessName:s?M.harnessName(s.harness):"",canOpen:s?Hs(s.harness):!1,layout:A})),ke={sel:g.sel,session:s,entry:a},K.dataset.key=t,e&&re(".d-wrap, .col",K).forEach((o,r)=>o.scrollTop=n[r]||0),U&&!U.isConnected&&V()}const sh=()=>Z(g.sel)&&(ke.sel!==g.sel||ke.session!==M.get(g.sel)||ke.entry!==M.detail(g.sel));function ah({catchUp:t=!1}={}){dn(),zt({live:!0,quiet:t}),sh()&&Ee(),Gt(),t&&ii()}const Jr=Od({draw:ah,hidden:Nn,clock:()=>performance.now(),frame:t=>requestAnimationFrame(t),setTimer:(t,e)=>setTimeout(t,e)});function oh(){if(!Z(g.sel))return;const t=S(".row[data-current]",_);if(!t)return;const e=t.getBoundingClientRect(),n=_.getBoundingClientRect();(e.top<n.top+28||e.bottom>n.bottom)&&(_.scrollTop+=e.top-n.top-(A.mode==="stack"?Math.max(0,(n.height-e.height)/2):n.height*.3))}function rh(t){if(A.mode!=="stack"||!Z(g.sel)){rs.firstChild&&rs.replaceChildren();return}const e=oo(t.groups,Ys(),g.sel,g.view.group),n=e.indexOf(g.sel);Oe(rs,`<button type="button" class="ib" data-act="step" data-key="-1" aria-label="Previous thread" data-tip="Previous thread (K)">${T.up}</button><button type="button" class="mid" data-act="to-list">${n>=0?`<b>${n+1}</b><span class="v-d">/${e.length}</span> `:""}Show the list</button><button type="button" class="ib" data-act="step" data-key="1" aria-label="Next thread" data-tip="Next thread (J)">${T.down}</button>`)}function ih(){if(se.hidden=!A.shut,!A.shut){se.firstChild&&se.replaceChildren();return}const t=M.list(),e=(s,a,o)=>{const r=t.filter(i=>i.status===s).length;return r?`<span class="cv-b ${a}" title="${l(`${o}: ${r}`)}">${r}</span>`:""},n=t.filter(s=>["asking","error","done"].includes(s.status)).sort((s,a)=>Me[s.status]-Me[a.status]||a.lastActivityAt-s.lastActivityAt);Oe(se,`<button type="button" class="cv-rail ls-rail" data-act="list-open" aria-label="Show the threads ([)" aria-expanded="false">
|
|
242
|
+
<span class="ls-mark">${kl}</span>
|
|
243
|
+
<span class="cv-rail-label">Threads</span>
|
|
244
|
+
<span class="cv-rail-badges">${e("asking","cv-b-wait","Needs you")}${e("error","ls-b-err","Error")}${e("done","ls-b-done","Done")}</span>
|
|
245
|
+
<span class="cv-rail-go">${T.listIcon}<kbd>[</kbd></span>
|
|
246
|
+
</button>
|
|
247
|
+
<div class="cv-peek ls-peek" aria-hidden="true">
|
|
248
|
+
<div class="cv-peek-h"><b>Your turn</b><span>${n.length}</span></div>
|
|
249
|
+
${n.length?n.slice(0,6).map(s=>`<p class="ls-pk">${at(s.status)}<span>${l(s.title)}</span></p>`).join(""):"<p>Nothing is waiting on you.</p>"}
|
|
250
|
+
<span class="cv-peek-f">Show the threads<kbd>[</kbd></span>
|
|
251
|
+
</div>`)}function dn(){const t=M.state.connection;te.dataset.state!==t&&(te.dataset.state=t);const e=S("span",te),n=e.textContent!==sn(t);n&&(e.textContent=sn(t));const s=wd(t,M.state.harnesses);te.dataset.tip!==s&&(te.dataset.tip=s,te.setAttribute("aria-label",s)),n&&Hn()}function Hn(){J.removeAttribute("data-brand-tight"),J.removeAttribute("data-conn-tight");const t=()=>Da.scrollWidth>Da.clientWidth+1;t()&&J.setAttribute("data-conn-tight",""),t()&&J.setAttribute("data-brand-tight","")}function de(){const t=_.scrollHeight,e=_.clientHeight,n=t>e+1&&_.offsetParent!==null;if(ae.hidden=!n,!n)return;const s=e-6,a=Math.max(28,s*e/t);ae.style.top=`${_.offsetTop+3}px`,ae.style.height=`${s}px`,gt.style.height=`${a}px`,gt.style.top=`${(s-a)*_.scrollTop/Math.max(1,t-e)}px`}function lh(t,e,n){const s=history.state?.pushed===!0;t==="push"&&n==="user"?history.pushState({thread:e,pushed:!0},"",Dn(e)):t==="push"?history.replaceState({thread:e,pushed:!1},"",Dn(e)):t==="replace"?history.replaceState({thread:e,pushed:s},"",Dn(e)):(t==="clear"||t==="back")&&history.replaceState(null,"",location.pathname+location.search)}function Vt(t,e="user"){const n=Z(g.sel)?g.sel:null,s=Z(t)?t:null,a=dl(n,s,history.state?.pushed===!0);if(a==="back"&&e==="user"){history.back();return}lh(a,s,e),e==="user"&&!!n!=!!s?jt(()=>un(t,e)):un(t,e)}function un(t,e){const n=g.sel,s=!Z(n)&&Z(t),a=Z(n)&&!Z(t);if(n!==t&&(g.sel=t,Fp()),M.open(Z(t)?t:null),V(),Pt(),n!==t){const o=S(".d-wrap",K);o&&(o.scrollTop=0)}e==="user"&&(s?K.focus({preventScroll:!0}):a&&ch(n))}function ch(t){const e=S(`button[data-act="select"][data-key="${CSS.escape(t)}"]`,_);e&&(e.focus({preventScroll:!0}),e.scrollIntoView({block:"nearest"}))}function Zr(t){const e=cl(location.hash),n=ul(e,{received:M.state.received,olderLoaded:M.state.olderLoaded,listed:M.listed});return n==="wait"?!1:n==="open"?(un(e,t?"auto":"user"),!0):(n==="drop"&&history.replaceState(null,"",location.pathname+location.search),t?Vt(Yr(),"auto"):un(Kr(),"user"),!0)}const Bn=t=>t&&Vt(t),Qr=()=>Vt(Kr());function ti(t){const e=ed(zs(),g.sel,t);e&&Bn(e)}function ei(){const{id:t,memo:e}=nd(M.list(),g.next,Date.now());g.next=e,t?Bn(t):it("No thread is waiting on you.")}function dh(){return ut.hidden?D.hidden?Z(g.sel)&&Pp()?!0:g.sel==="overview"&&A.mode==="side"||!g.sel?!1:(Qr(),!0):(Rt(!1),!0):(V(),!0)}const uh=matchMedia("(prefers-reduced-motion: reduce)");let ls=!1;function jt(t){if(ls||!document.startViewTransition||uh.matches)return t(),Promise.resolve();V();const e=document.startViewTransition(()=>{ls=!0;try{t()}finally{ls=!1}});return e.ready.catch(()=>{}),e.updateCallbackDone.catch(()=>{})}let pe=null,Cs="";function Gt(t=!1){if(D.hidden)return;const e=Ld({view:g.view,sessions:M.list(),fonts:me,connection:M.state.connection,harnesses:M.state.harnesses,threadnauts:M.state.threadnauts,entitlements:M.state.entitlements,previewFree:Ks,limits:Xr(),now:Date.now()});if(!t&&e===Cs)return;Cs=e;const n=S(".pf-body",D),s=n?n.scrollTop:0,a=re(".pf-col",D).map(r=>r.scrollTop);Js(D,()=>{D.innerHTML=e,ph()});const o=S(".pf-body",D);o&&(o.scrollTop=s),re(".pf-col",D).forEach((r,i)=>r.scrollTop=a[i]||0)}function ph(){const t=S(".pf-cols",D);if(!t||!A.table)return;const e=Math.max(1,Math.min(4,Math.floor((t.clientWidth+48)/348)));if(e<2)return;const n=re(".pf-g",t);t.style.setProperty("--pfn",String(e)),t.setAttribute("data-measure","");const s=n.map(i=>i.offsetHeight);t.removeAttribute("data-measure");const a=s.reduce((i,c)=>i+c,0)/e,o=[[]];let r=0;n.forEach((i,c)=>{o.at(-1).length&&o.length<e&&r+s[c]/2>a&&(o.push([]),r=0),o.at(-1).push(i),r+=s[c]}),t.replaceChildren(...o.map(i=>{const c=document.createElement("div");return c.className="pf-col",c.append(...i),c})),t.style.setProperty("--pfn",String(o.length)),t.setAttribute("data-split","")}function Ka(t){const e=t&&S(`[data-g="${t}"]`,D),n=S(".pf-body",D);if(!e||!n)return;n.scrollTop=Math.max(0,e.offsetTop-n.offsetTop-8);const s=e.closest(".pf-col");s&&(s.scrollTop=Math.max(0,e.offsetTop-8)),e.dataset.flash="",setTimeout(()=>delete e.dataset.flash,1400)}function Rt(t,e=""){const n=t??D.hidden;if(n===!D.hidden){n&&Ka(e);return}n&&(pe=document.activeElement?.closest?.("#list")?document.activeElement:null),jt(()=>{V(),D.hidden=!n,ee(J,"data-prefs",n);for(const s of re("#list > :not(#prefs)"))s.inert=n;Wa.setAttribute("aria-expanded",String(n)),Pt(),n?(Gt(!0),S('[data-act="prefs-close"]',D)?.focus({preventScroll:!0}),Ka(e)):(Cs="",D.replaceChildren(),(pe?.isConnected&&pe.offsetParent?pe:A.shut?S(".ls-rail",se):Wa)?.focus({preventScroll:!0}),pe=null)})}function xt(t){Object.assign(g.view,t),ce(),Pt(),Gt()}function Ya(t,e){me=Xa(Dr,{...me,[t]:e}),xt({font:me.sans,mono:me.mono}),document.fonts?.ready.then(()=>{Hn(),de()})}function Ls(t){t&&!D.hidden&&Rt(!1),g.view.listShut=t,ce(),V(),jt(Pt),setTimeout(()=>S(t?".ls-rail":'[data-act="list-shut"]',t?se:je)?.focus({preventScroll:!0}),60)}function hh(){Ur.show(M.state.entitlements,{previewFree:Ks,onActivated:t=>{const e=M.pro();M.setEntitlements(t),M.pro()&&!e&&it("Threadgauge Pro is on")}})}function it(t,e="ok"){const n=document.createElement("div");n.className="toast",n.dataset.kind=e,n.textContent=t,Qp.append(n),setTimeout(()=>n.remove(),qp)}function fh(){const t=new Date,e=n=>String(n).padStart(2,"0");return`${t.getFullYear()}${e(t.getMonth()+1)}${e(t.getDate())}-${e(t.getHours())}${e(t.getMinutes())}${e(t.getSeconds())}`}async function Zs(){if(os.disabled)return;V();const t=zi();os.disabled=!0;try{Xi(await t,`threadgauge-${fh()}.png`),it("Screenshot saved")}catch(e){it(`Couldn't take a screenshot: ${e.message}`,"err")}finally{os.disabled=!1}}async function xe(t,e=null,n="app"){if(!t)return;const s=M.harnessName(t.harness);if(!Hs(t.harness)){it(`${s} has nothing to link to, so this thread can't be opened from here.`);return}if(!e?.disabled){e&&(e.disabled=!0);try{const a=await xi(t.id,n);if(!a.ok&&a.missing&&n!=="terminal"&&qr.show(a,{harnessName:s,returnTo:e,onTerminal:()=>xe(t,e,"terminal")}))return;a.ok?a.focused?it(`Brought ${s}'s window to the front`):a.note?it(a.note):a.via==="terminal"?it(`Opened in a terminal with ${s}`):it(`Opened in ${s}`):it(a.error||`Couldn't open that thread in ${s}`,"err")}catch(a){it(`Couldn't open that thread: ${a.message}`,"err")}finally{e&&(e.disabled=!1)}}}let U=null,wt=null,Ct=null,Pe=!1,Ge=null,ge=null;const mh=matchMedia("(hover: hover)");function gh(t,e="below"){ut.hidden=!1,ut.style.left="0",ut.style.top="0";const{x:n,y:s}=yc(t.getBoundingClientRect(),ut.offsetWidth,ut.offsetHeight,innerWidth,innerHeight,e);ut.style.left=`${n}px`,ut.style.top=`${s}px`}const Es=(t,e)=>t?.classList?.contains("term")&&t.setAttribute("aria-expanded",String(e));function pn(t,e,{side:n="below",pinned:s=!1}={}){clearTimeout(wt),clearTimeout(Ct),U&&U!==t&&Es(U,!1),U=t,Pe=s,ut.innerHTML=e,Es(t,!0),gh(t,n)}const ni=t=>pn(t,`<p>${l(t.dataset.tip)}</p>`);function Qs(t,e){if(t.dataset.term==="why"){const o=M.get(t.dataset.key);o&&pn(t,iu(o,Date.now(),M.harnessName),{pinned:e});return}const n=t.closest("[data-id]"),s=n?M.get(n.dataset.id):t.closest("#det, #cv-panel")?Ss():null,a=$c(t.dataset.term,{harness:s?.harness||"",spec:mc(t.dataset.inst),val:t.dataset.val||"",sub:t.dataset.sub||"",status:t.closest("[data-st]")?.dataset.st||"idle"});a&&pn(t,a,{pinned:e})}function si(t){const e=M.get(t.dataset.peek);!e||!t.isConnected||e.id===g.sel||pn(t,Sc(e,{now:Date.now(),harnessName:M.harnessName}),{side:"right"})}function V(){clearTimeout(wt),clearTimeout(Ct),ut.hidden=!0,Es(U,!1),U=null,Pe=!1}function za(){Pe||(clearTimeout(wt),wt=setTimeout(V,180))}document.addEventListener("pointerover",t=>{if(t.pointerType==="touch")return;const e=t.target.closest?.("[data-term]");if(e){if(clearTimeout(wt),U===e)return;clearTimeout(Ct),wt=setTimeout(()=>e.isConnected&&Qs(e,!1),Gp);return}if(t.target.closest?.("#tip"))return clearTimeout(wt);const n=t.target.closest?.("[data-tip]");n&&(clearTimeout(wt),U!==n&&(clearTimeout(Ct),wt=setTimeout(()=>n.isConnected&&ni(n),Vp)))});document.addEventListener("pointermove",t=>{if(t.pointerType==="touch"||!mh.matches||Ge&&t.clientX===Ge.x&&t.clientY===Ge.y)return;if(Ge={x:t.clientX,y:t.clientY},clearTimeout(Ct),ge){if(Math.hypot(t.clientX-ge.x,t.clientY-ge.y)<6)return;ge=null}if(t.target.closest?.("[data-term]"))return;const e=t.target.closest?.("[data-peek]");!e||e.dataset.peek===g.sel||U===e||(U?.dataset?.peek&&V(),Ct=setTimeout(()=>si(e),Kp))});document.addEventListener("pointerout",t=>{if(t.pointerType==="touch")return;const e=t.target.closest?.("[data-term]");if(e){(!t.relatedTarget||!e.contains(t.relatedTarget))&&za();return}if(t.target.closest?.("#tip"))return za();const n=t.target.closest?.("[data-tip]");if(n){if(t.relatedTarget&&n.contains(t.relatedTarget))return;clearTimeout(wt),U===n&&V();return}const s=t.target.closest?.("[data-peek]");s&&(clearTimeout(Ct),(!t.relatedTarget||!s.contains(t.relatedTarget))&&U===s&&V())});document.addEventListener("focusin",t=>{const e=t.target;Ts||!e.matches?.(":focus-visible")||(e.dataset?.term?Qs(e,!1):e.dataset?.tip?ni(e):e.dataset?.peek&&si(e))});document.addEventListener("focusout",t=>{U===t.target&&!Pe&&V()});const ta=()=>rl(g.q,{stacked:A.mode==="stack"});function Kt(){As.hidden=!g.findOpen,Wr.setAttribute("aria-expanded",String(g.findOpen));const t=ta();g.findI=Math.max(0,Math.min(g.findI,t.length-1));const e=g.findOpen&&As.contains(document.activeElement)&&t.length>0;cn.hidden=!e,cn.innerHTML=e?`<h3 class="pa-h">Actions</h3><ul class="pa-list">${t.map((n,s)=>`<li><button type="button" class="pa-item" data-act="palette-run" data-key="${s}"${s===g.findI?" data-on":""}><span class="pa-n">${l(n.label)}</span>${n.key?`<kbd>${l(n.key)}</kbd>`:""}</button></li>`).join("")}</ul>`:""}function ai(t){g.q=t,g.findI=0,bt.value!==t&&(bt.value=t),zt(),Kt()}function oi(){D.hidden||Rt(!1);const t=A.shut;t&&(g.view.listShut=!1,ce());const e=()=>{bt.focus(),bt.select(),Kt()};if(g.findOpen&&!t)return e();jt(()=>{g.findOpen=!0,t&&Pt(),Kt()}).then(e)}function hn(t=!0){g.findOpen&&jt(()=>{g.findOpen=!1,g.q="",g.findI=0,bt.value="",Kt(),zt()}).then(()=>t&&Wr.focus({preventScroll:!0}))}function ri(t){hn(!1),t==="next-waiting"?ei():t==="table"&&A.mode==="side"?Vt("overview"):t==="settings"?Rt(!0):t==="shot"&&setTimeout(Zs,300)}bt.addEventListener("input",()=>ai(bt.value));bt.addEventListener("focus",Kt);bt.addEventListener("blur",()=>setTimeout(()=>As.contains(document.activeElement)||Kt(),0));cn.addEventListener("mousedown",t=>t.preventDefault());bt.addEventListener("keydown",t=>{const e=ta();if(t.key==="Escape")t.preventDefault(),t.stopPropagation(),g.q?ai(""):hn();else if(t.key==="ArrowDown"||t.key==="ArrowUp")t.preventDefault(),g.findI=Math.max(0,Math.min(e.length-1,g.findI+(t.key==="ArrowDown"?1:-1))),Kt();else if(t.key==="Enter"){if(t.preventDefault(),!cn.hidden&&e[g.findI])return ri(e[g.findI].act);const n=zs()[0];n&&Bn(n)}});document.addEventListener("click",t=>{clearTimeout(Ct),ge={x:t.clientX,y:t.clientY};const e=t.target.closest?.("[data-term]");if(e&&!("rowtip"in e.dataset)){t.preventDefault(),U===e&&!ut.hidden&&Pe?V():Qs(e,!0);return}!ut.hidden&&!t.target.closest?.("#tip")&&V();const n=t.target.closest?.("[data-act]");if(!n)return;const{act:s,key:a}=n.dataset;switch(s){case"select":t.detail===0&&n.classList.contains("row-main")&&a===g.sel?xe(M.get(a),null):Bn(a);break;case"open":xe(M.get(a),n);break;case"respond":{const o=M.get(a);o&&Vr.show({harnessName:M.harnessName(o.harness),canOpen:Hs(o.harness),open:()=>xe(o,n)});break}case"close":Qr();break;case"to-list":Vt(null);break;case"step":ti(Number(a));break;case"shot":Zs();break;case"menu":Rt();break;case"prefs-close":Rt(!1);break;case"connection":Rt(!0,"connection");break;case"group":xt({group:a});break;case"clear":xt({repo:"",status:null});break;case"status":xt({status:a&&g.view.status!==a?a:null});break;case"table-sort":xt({tableSort:rd(g.view.tableSort,a)});break;case"grp-toggle":{const o=new Set(g.view.collapsed);o.has(a)?o.delete(a):o.add(a),xt({collapsed:[...o]});break}case"find":g.findOpen?hn():oi();break;case"find-close":hn();break;case"palette-run":{const o=ta()[Number(a)];o&&ri(o.act);break}case"font-sans":Ya("sans",a);break;case"font-mono":Ya("mono",a);break;case"license":hh();break;case"list-shut":Ls(!0);break;case"list-open":Ls(!1);break}});document.addEventListener("change",t=>{const e=t.target.dataset?.change;e==="sort"?xt({sort:t.target.value}):e==="repo"&&xt({repo:t.target.value})});document.addEventListener("keydown",t=>{const e=t.target instanceof Element?t.target:null,n=Ml(t,{typing:!!e?.closest(Al),onControl:!!e?.closest(Sl),dialog:!!S("dialog[open]"),mode:A.mode,sel:g.sel,thread:!!Ss()});if(n){if(n.act==="back"){dh()&&t.preventDefault();return}t.preventDefault(),n.act==="shot"?Zs():n.act==="settings"?Rt():n.act==="list-toggle"?Ls(!g.view.listShut):n.act==="next-waiting"?ei():n.act==="find"?oi():n.act==="step"?ti(n.dir):n.act==="open"?xe(Ss(),S('[data-act="open"]',K)):n.act==="conversation"&&Bp()}});addEventListener("popstate",()=>{g.booted&&jt(()=>Zr(!1))});let fn=0;addEventListener("resize",()=>{cancelAnimationFrame(fn),fn=requestAnimationFrame(Xs)});et.addEventListener("pointerdown",t=>{t.preventDefault(),et.setPointerCapture(t.pointerId),et.dataset.drag="";const e=s=>{g.view.listWidth=Math.round(s.clientX),cancelAnimationFrame(fn),fn=requestAnimationFrame(Xs)},n=()=>{et.removeEventListener("pointermove",e),et.removeEventListener("pointerup",n),et.removeEventListener("pointercancel",n),delete et.dataset.drag,g.view.listWidth=A.lw,ce()};et.addEventListener("pointermove",e),et.addEventListener("pointerup",n),et.addEventListener("pointercancel",n)});et.addEventListener("keydown",t=>{t.key!=="ArrowLeft"&&t.key!=="ArrowRight"||(t.preventDefault(),g.view.listWidth=A.lw+(t.key==="ArrowLeft"?-da:da),Xs(),g.view.listWidth=A.lw,ce())});_.addEventListener("scroll",()=>{de(),clearTimeout(Ct),U?.dataset?.peek&&V()},{passive:!0});new ResizeObserver(()=>{A?.table&&an(_),de()}).observe(_);new ResizeObserver(Hn).observe(je);gt.addEventListener("pointerdown",t=>{t.preventDefault(),gt.setPointerCapture(t.pointerId);const e=t.clientY,n=_.scrollTop,s=(_.scrollHeight-_.clientHeight)/Math.max(1,ae.offsetHeight-gt.offsetHeight),a=r=>_.scrollTop=n+(r.clientY-e)*s,o=()=>{gt.removeEventListener("pointermove",a),gt.removeEventListener("pointerup",o),gt.removeEventListener("pointercancel",o),delete ae.dataset.drag};ae.dataset.drag="",gt.addEventListener("pointermove",a),gt.addEventListener("pointerup",o),gt.addEventListener("pointercancel",o)});document.addEventListener("visibilitychange",()=>{Nn()||(M.refreshEntitlements(),M.resume(),Jr.resume())});addEventListener("focus",()=>M.checkThreadnauts());function Os(){const t=S(".boot");!t||t.classList.contains("gone")||(t.classList.add("gone"),setTimeout(()=>t.remove(),zp))}M.on(t=>{if(t==="sessions"){if(Dc(M.list()),!g.booted){if(dn(),!Zr(!0))return;g.booted=!0,Os();return}Jr.request()}else t==="connection"?(dn(),Gt(),M.state.connection==="offline"&&Os()):t==="threadnauts"||t==="entitlements"?Gt():t==="detail"&&Ee()});function ii(){const t=Date.now();Qc(_,t,M.get),Op(t,M.get),g.limitsResetAt&&t>=g.limitsResetAt&&(zt(),Gt())}setInterval(()=>{g.booted&&!Nn()&&ii()},Yp);setTimeout(Os,Xp);document.title="Threadgauge";Pt();dn();document.fonts?.ready.then(()=>{Hn(),de()});M.start();document.fonts?.addEventListener("loadingdone",()=>g.booted&&zt());
|