@preventive/triage 1.0.0-alpha.44 → 1.0.0-alpha.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. package/client/linked-findings.js +3 -0
  2. package/common/bundle-metadata.d.ts +1 -0
  3. package/common/bundle-metadata.js +1 -1
  4. package/common/bundle-sources.js +25 -2
  5. package/common/default-scan-models.ts +1 -1
  6. package/common/dependency-reviews.d.ts +0 -5
  7. package/common/dependency-reviews.js +0 -17
  8. package/common/line-diff.js +5 -4
  9. package/common/managed/agent-tasks.ts +292 -0
  10. package/common/managed/github-agents.ts +92 -0
  11. package/common/managed/github-logins.ts +49 -0
  12. package/common/managed/roles.ts +7 -0
  13. package/common/managed/routes.js +88 -7
  14. package/common/managed/team-app.d.ts +5 -2
  15. package/common/managed/team-app.js +2 -2
  16. package/common/server-info.ts +3 -0
  17. package/common/workspace-app.js +6 -3
  18. package/out/brotli-fallback.js +3 -3
  19. package/out/chunk-2XUEZHIP.js +18 -18
  20. package/out/chunk-2ZDZWLFY.js +1 -0
  21. package/out/chunk-3PS4KWD2.js +10 -0
  22. package/out/chunk-4HI2MSAV.js +17 -0
  23. package/out/chunk-4UFAMJAX.js +1 -0
  24. package/out/chunk-7C7DWL7I.js +1 -0
  25. package/out/chunk-7XRR4OFU.js +1 -0
  26. package/out/chunk-BC2UCLFJ.js +1 -0
  27. package/out/chunk-BOIXMUU5.js +3 -0
  28. package/out/chunk-C4Z6ZBXV.js +6 -6
  29. package/out/chunk-CC4OM6TZ.js +3 -0
  30. package/out/chunk-G24A42V6.js +2 -0
  31. package/out/chunk-GDPCLSOS.js +2 -0
  32. package/out/chunk-GO7FT4OD.js +1 -0
  33. package/out/chunk-I2MDGSQX.js +3 -0
  34. package/out/chunk-IYPY47MC.js +1 -0
  35. package/out/chunk-IZ7POWI3.js +18 -0
  36. package/out/chunk-JCIIBLKR.js +1 -1
  37. package/out/chunk-JKGQ3O7O.js +6 -0
  38. package/out/chunk-LE5ZWLG4.js +235 -0
  39. package/out/chunk-MSION3G4.js +36 -0
  40. package/out/chunk-NRPC74AM.js +1 -1
  41. package/out/chunk-OKRLLE5I.js +17 -0
  42. package/out/chunk-OOJM4CTU.js +1 -1
  43. package/out/chunk-PNHBZGDD.js +1 -1
  44. package/out/chunk-PXK7EU4V.js +1 -0
  45. package/out/chunk-QB4CBOX2.js +1 -0
  46. package/out/chunk-R3NZFXVR.js +1 -0
  47. package/out/chunk-R5O6FAW4.js +1 -1
  48. package/out/chunk-S6GIXWQW.js +52 -0
  49. package/out/chunk-SXV2T5C4.js +80 -0
  50. package/out/chunk-TUII34K2.js +1 -1
  51. package/out/chunk-V3KWNNMY.js +1 -0
  52. package/out/chunk-VFWMQ3LG.js +2 -0
  53. package/out/chunk-VH4XMZIW.js +2 -0
  54. package/out/chunk-WFYLMF6Z.js +10 -0
  55. package/out/chunk-WQ74ZBZF.js +7 -0
  56. package/out/client-managed-import.js +3 -3
  57. package/out/client-managed.js +31 -35
  58. package/out/client-sync.js +11 -11
  59. package/out/compare.js +35 -0
  60. package/out/dialogs.js +51 -0
  61. package/out/github-issue-authorized.html +1 -1
  62. package/out/github-issue-authorized.js +1 -1
  63. package/out/graph.js +17 -17
  64. package/out/index.html +30 -34
  65. package/out/prism.js +14 -14
  66. package/out/scan.js +2 -0
  67. package/out/terminal.js +294 -293
  68. package/out/view.css +1 -1
  69. package/out/view.js +16 -107
  70. package/package.json +53 -6
  71. package/risk/actions/findings.js +161 -0
  72. package/risk/actions/resolve.js +219 -0
  73. package/risk/actions/scripts/commands.js +182 -0
  74. package/risk/actions/scripts/grade.js +113 -0
  75. package/risk/actions/scripts/packages.js +123 -0
  76. package/risk/actions/scripts/shell.js +169 -0
  77. package/risk/actions/uses.js +76 -0
  78. package/risk/actions/workflow.js +110 -0
  79. package/risk/files/hosts.js +6 -6
  80. package/risk/files/readability.js +23 -17
  81. package/risk/files/runs-code.js +18 -6
  82. package/risk/files/script.js +7 -3
  83. package/risk/files/stamps.js +8 -7
  84. package/risk/index.d.ts +71 -1
  85. package/risk/index.js +6 -2
  86. package/risk/npm/assess.js +1 -1
  87. package/risk/npm/compare.js +34 -10
  88. package/risk/npm/files.js +413 -2
  89. package/risk/npm/tarball.js +56 -73
  90. package/server-e2e/app.ts +5 -4
  91. package/server-e2e/http.ts +5 -2
  92. package/server-managed/agent-merges.ts +198 -0
  93. package/server-managed/app-agents.ts +30 -0
  94. package/server-managed/avatar-store.ts +1 -0
  95. package/server-managed/bundle-cache.ts +7 -1
  96. package/server-managed/combined.ts +3 -2
  97. package/server-managed/commit-coauthors.ts +83 -0
  98. package/server-managed/commit-lockfiles.ts +72 -0
  99. package/server-managed/config.ts +6 -0
  100. package/server-managed/db-methods.ts +66 -19
  101. package/server-managed/db-neon.ts +89 -21
  102. package/server-managed/db-schema.ts +13 -2
  103. package/server-managed/db.ts +9 -1
  104. package/server-managed/dependabot-access.ts +60 -0
  105. package/server-managed/dependabot-alerts.ts +185 -0
  106. package/server-managed/dependency-review-comments.ts +97 -0
  107. package/server-managed/dependency-reviews.ts +78 -18
  108. package/server-managed/github-accounts.ts +33 -0
  109. package/server-managed/github-actions.ts +71 -0
  110. package/server-managed/github-app.ts +33 -13
  111. package/server-managed/github-errors.ts +2 -0
  112. package/server-managed/github-issue-links.ts +11 -5
  113. package/server-managed/github-link-oauth.ts +69 -0
  114. package/server-managed/github-links.ts +204 -0
  115. package/server-managed/github-oauth.ts +5 -2
  116. package/server-managed/github-pulls.ts +2 -2
  117. package/server-managed/github-requests.ts +39 -0
  118. package/server-managed/github-users.ts +30 -0
  119. package/server-managed/http-response.ts +10 -2
  120. package/server-managed/http.ts +1251 -97
  121. package/server-managed/index.ts +13 -8
  122. package/server-managed/kept-briefly.ts +37 -0
  123. package/server-managed/locked-packages.ts +37 -16
  124. package/server-managed/lockfile-scope.ts +49 -0
  125. package/server-managed/npm-delta-worker.js +23 -0
  126. package/server-managed/npm-delta.ts +178 -0
  127. package/server-managed/npm-insights.ts +20 -11
  128. package/server-managed/npm-kept.ts +83 -6
  129. package/server-managed/npm-loads.ts +114 -37
  130. package/server-managed/npm-packages.ts +110 -64
  131. package/server-managed/npm-risk.ts +4 -1
  132. package/server-managed/pretty-print.ts +67 -23
  133. package/server-managed/pull-comment-reviews.ts +161 -0
  134. package/server-managed/pull-dependencies.ts +300 -0
  135. package/server-managed/pull-dependency-reviews.ts +318 -0
  136. package/server-managed/pull-reviews.ts +205 -0
  137. package/server-managed/queue.ts +16 -0
  138. package/server-managed/release-commits.ts +84 -0
  139. package/server-managed/rename-diff.ts +22 -13
  140. package/server-managed/report-sources.ts +1 -1
  141. package/server-managed/report-store.ts +42 -9
  142. package/server-managed/repository-actions.ts +218 -0
  143. package/server-managed/repository-agents.ts +220 -0
  144. package/server-managed/repository-browser.ts +166 -37
  145. package/server-managed/repository-changes.ts +284 -0
  146. package/server-managed/repository-code.ts +52 -0
  147. package/server-managed/repository-dependency-reviews.ts +157 -0
  148. package/server-managed/repository-history.ts +461 -0
  149. package/server-managed/repository-issues.ts +181 -0
  150. package/server-managed/repository-pulse.ts +439 -0
  151. package/server-managed/repository-risk-audit.ts +13 -0
  152. package/server-managed/repository-risk-read.ts +170 -0
  153. package/server-managed/repository-risk.ts +133 -118
  154. package/server-managed/reviewed-dependencies.ts +149 -0
  155. package/server-managed/session.ts +27 -9
  156. package/server-managed/sql.ts +6 -3
  157. package/server-managed/storage-stores.ts +5 -0
  158. package/server-managed/storage.ts +4 -2
  159. package/server-managed/team-app.ts +19 -3
  160. package/server-managed/team-reports.ts +24 -12
  161. package/server-managed/upstream-cache.ts +12 -0
  162. package/server-managed/workspace-shares.ts +4 -1
  163. package/server.ts +25 -5
  164. package/out/chunk-2ABLKCOY.js +0 -46
  165. package/out/chunk-2KBF5TZ7.js +0 -2
  166. package/out/chunk-35VE6CDH.js +0 -2
  167. package/out/chunk-3BZ7JERB.js +0 -1
  168. package/out/chunk-4XCDFGDP.js +0 -10
  169. package/out/chunk-5LSXOLUS.js +0 -1
  170. package/out/chunk-5RCM2J63.js +0 -1
  171. package/out/chunk-7B6HB4D7.js +0 -1
  172. package/out/chunk-AJ4GTATZ.js +0 -3
  173. package/out/chunk-CH4UN6WK.js +0 -225
  174. package/out/chunk-CMQA4DM6.js +0 -1
  175. package/out/chunk-CVVJAXVY.js +0 -2
  176. package/out/chunk-DIJJNTRH.js +0 -10
  177. package/out/chunk-EDKLBQQN.js +0 -17
  178. package/out/chunk-F47DXCEV.js +0 -33
  179. package/out/chunk-FK3DZEKL.js +0 -1
  180. package/out/chunk-G6AJWENO.js +0 -1
  181. package/out/chunk-GJ4IUCNS.js +0 -1
  182. package/out/chunk-GNXOKIGP.js +0 -80
  183. package/out/chunk-GZ4MS3TE.js +0 -13
  184. package/out/chunk-GZWM7UQM.js +0 -2
  185. package/out/chunk-IU3CCINR.js +0 -3
  186. package/out/chunk-K3X5EJBQ.js +0 -2
  187. package/out/chunk-KEX2ATEW.js +0 -2
  188. package/out/chunk-KYCNJVB7.js +0 -1
  189. package/out/chunk-LPCTJYNA.js +0 -7
  190. package/out/chunk-O4RJY5TP.js +0 -2
  191. package/out/chunk-OD4LPN3H.js +0 -1
  192. package/out/chunk-QWDWTBM7.js +0 -1
  193. package/out/chunk-QYWKC557.js +0 -1
  194. package/out/chunk-R75XOKUP.js +0 -1
  195. package/out/chunk-SWTLADW5.js +0 -1
  196. package/out/chunk-T7OKH4VW.js +0 -1
  197. package/out/chunk-TZ5KB2Y5.js +0 -10
  198. package/out/chunk-UNTRGE26.js +0 -2
  199. package/out/chunk-UTR2LVME.js +0 -2
  200. package/out/chunk-UYAXVRVL.js +0 -1
  201. package/out/chunk-V3ME6FI5.js +0 -2
  202. package/out/chunk-V5O7M2YT.js +0 -1
  203. package/out/chunk-VIHGO77Y.js +0 -1
  204. package/out/chunk-W4J3MGLB.js +0 -1
  205. package/out/chunk-WGG7KQUH.js +0 -1
  206. package/out/chunk-XYFXXB2G.js +0 -10
  207. package/out/chunk-ZESLQCTF.js +0 -6
package/out/scan.js ADDED
@@ -0,0 +1,2 @@
1
+ import{a as e,b as t,c as n,e as r,f as i,g as a,h as o,i as s,j as c}from"./chunk-4UFAMJAX.js";import{a as l}from"./chunk-QB4CBOX2.js";import{A as u,K as d,Ue as f,W as p,X as m,Y as h,Z as g,_,ge as v,oa as y,t as ee,ve as te,w as ne,we as re,x as b,y as ie}from"./chunk-LE5ZWLG4.js";import"./chunk-VH4XMZIW.js";import"./chunk-JCIIBLKR.js";import"./chunk-V3KWNNMY.js";import{i as x,l as S,m as ae}from"./chunk-S6GIXWQW.js";import"./chunk-JKGQ3O7O.js";import"./chunk-NRPC74AM.js";import"./chunk-WQ74ZBZF.js";import"./chunk-7C7DWL7I.js";import"./chunk-PNHBZGDD.js";import"./chunk-MSION3G4.js";import"./chunk-I2MDGSQX.js";import{a as C,b as w,c as T,d as E}from"./chunk-3PS4KWD2.js";import"./chunk-IYPY47MC.js";import{c as D,d as O}from"./chunk-OKRLLE5I.js";import"./chunk-BC2UCLFJ.js";import"./chunk-SXV2T5C4.js";import{d as k,i as oe,o as A,s as j,u as M,v as se}from"./chunk-WFYLMF6Z.js";import"./chunk-C4Z6ZBXV.js";import"./chunk-TUII34K2.js";import{a as ce,b as N,c as P,g as F,j as I}from"./chunk-2XUEZHIP.js";import"./chunk-OOJM4CTU.js";function L(e){let t=new Map(e.map(e=>[e.id,e])),n=new Set;return e.flatMap(e=>{if(n.has(e.id))return[];let r=e.id.endsWith(`-pro`)?e.id.slice(0,-4):e.id,i=t.get(r),a=t.get(`${r}-pro`);return!/(?:^|\/)gpt-.+$/u.test(r)||r.endsWith(`-pro`)||!i||!a?[e]:(n.add(i.id),n.add(a.id),[{...i,pro:a}])})}function R(e){return[...Map.groupBy(L(e),e=>i(e.id).key)].map(([e,t])=>({key:e,models:t}))}function z(e,t){if(e.length===0)return[];let n=Math.min(e.length,Math.max(1,t)),r=e.map(e=>e.models.length*2+3),i=r.reduce((e,t)=>e+t,0),a=Math.max(...r);for(;a<i;){let e=Math.floor((a+i)/2),t=0,o=1;for(let n of r)t+n>e&&(o++,t=0),t+=n;o>n?a=e+1:i=e}let o=[],s=[],c=0;for(let[t,i]of e.entries())s.length>0&&(c+r[t]>a||e.length-t===n-o.length-1)&&(o.push(s),s=[],c=0),s.push(i),c+=r[t];return o.push(s),o}var B=P`<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m4 6 4 4 4-4"/></svg>`,V=class extends I{static properties={loadModels:{attribute:!1},pending:{type:Boolean},value:{attribute:!1},effort:{attribute:!1},hasExtra:{type:Boolean,attribute:`has-extra`},_models:{state:!0},_error:{state:!0},_menuColumns:{state:!0}};static styles=N`:host{display:block;min-width:0;container:scan-controls / inline-size}*{box-sizing:border-box}.layout{display:grid;grid-template-columns:minmax(16rem,1fr) minmax(14rem,1fr);gap:1.25rem;align-items:start}.layout.with-extra{grid-template-columns:minmax(16rem,.9fr) minmax(14rem,1.2fr) minmax(14rem,auto)}.field{min-width:0;min-height:4.9rem}.model-placeholder{height:3.25rem;display:flex;align-items:center;padding:.5rem .6rem;border:1px solid var(--border);border-radius:var(--ui-radius, 6px);color:var(--muted);background:var(--bg);font-size:.75rem}.effort-placeholder{height:.3rem;margin:1rem .6rem;border-radius:999px;background:var(--surface-active)}.label{display:flex;justify-content:space-between;align-items:center;margin-bottom:.4rem;color:var(--muted);font-size:.72rem}output{color:var(--text);font-size:.72rem;font-weight:500}details{position:relative}.model-control{position:relative}summary{display:flex;align-items:center;gap:.55rem;padding:.5rem .6rem;border:1px solid var(--border);border-radius:var(--ui-radius, 6px);background:var(--bg);color:var(--text);list-style:none;transition:border-color .12s,background .12s}summary:hover,details[open] summary{border-color:var(--muted);background:var(--surface-active)}summary::-webkit-details-marker{display:none}summary,.menu{user-select:none}summary>svg{width:.9rem;height:.9rem;margin-left:auto;color:var(--muted)}.selected-copy{display:grid;gap:.1rem;flex:1;min-width:0}.selected-copy strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.8rem;font-weight:500}.selected-copy small{color:var(--muted);font-size:.63rem}.pro-space{width:3.65rem;flex:0 0 3.65rem}.pro-toggle,.pro-checkbox{position:absolute;right:2.05rem;top:50%;transform:translateY(-50%);align-items:center;justify-content:center;gap:.3rem;width:3.65rem;height:1.65rem;padding:.2rem .3rem;color:var(--muted);font:inherit;font-size:.65rem;font-weight:600;cursor:default;user-select:none}.pro-toggle{display:var(--switch-button-display, inline-flex);border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg)}.pro-checkbox{display:var(--switch-checkbox-display, none)}.pro-checkbox input{width:.85rem;height:.85rem;margin:0;accent-color:var(--accent)}.pro-toggle:hover{border-color:var(--muted);color:var(--text)}.pro-track{position:relative;flex:0 0 1.3rem;height:.8rem;border-radius:var(--ui-radius, 999px);background:var(--border)}.pro-track:after{content:"";position:absolute;top:.15rem;left:.15rem;width:.5rem;height:.5rem;border-radius:50%;background:var(--muted);transition:transform .12s,background .12s}.pro-toggle[aria-checked=true]{color:var(--accent);border-color:rgb(from var(--accent) r g b / .45);background:rgb(from var(--accent) r g b / .08)}.pro-toggle[aria-checked=true] .pro-track{background:rgb(from var(--accent) r g b / .25)}.pro-toggle[aria-checked=true] .pro-track:after{transform:translate(.5rem);background:var(--accent)}.icon{display:inline-grid;place-items:center;width:1.7rem;height:1.5rem;flex:0 0 1.7rem;color:var(--text)}.icon svg{display:block;width:1.12rem;height:1.12rem}.icon.openai{color:#10a37f}.icon.anthropic{color:#d97757}.icon.moonshotai{color:#8068d9}.icon.google{color:#4285f4}.icon.nvidia{color:#76b900}.icon.qwen{color:#f97316}.icon.deepseek{color:#4d8dff}.icon.xiaomi{color:#ff6900}.icon.meta{color:#0081fb}.icon.moonshotai svg{transform:scale(.78)}.icon.qwen svg{transform:scale(.82)}.icon.nvidia svg{transform:scale(.86)}.icon.deepseek svg{transform:scale(.9)}.extra{display:flex;min-width:0;min-height:4.9rem;align-items:flex-end;align-self:end;padding-bottom:.05rem}.menu{visibility:hidden;position:fixed;z-index:1000;width:min(46rem,calc(100vw - 1rem));max-height:calc(100dvh - 1rem);overflow:auto;overscroll-behavior:contain;padding:.65rem;border:1px solid var(--border);border-radius:var(--ui-radius, 9px);background:var(--surface-active);color:var(--text);box-shadow:0 .65rem 1.8rem #0000008c}details[open] .menu[data-positioned]{visibility:visible}.groups{display:grid;grid-template-columns:repeat(var(--model-columns, 1),minmax(0,1fr));gap:1rem;align-items:start}.provider-column{min-width:0}fieldset{min-width:0;margin:0 0 .6rem;padding:0;border:0}fieldset:last-child{margin-bottom:0}legend{display:flex;align-items:center;gap:.45rem;width:100%;min-height:1.9rem;padding:.35rem .5rem .25rem;border-bottom:1px solid rgb(from var(--border) r g b / .7);color:var(--muted);font-size:.64rem;font-weight:700;letter-spacing:.055em;text-transform:uppercase}legend .icon{width:.88rem;height:1.25rem;flex-basis:.88rem}legend .icon svg{width:.88rem;height:.88rem}.choice{display:flex;align-items:center;gap:.5rem;padding:.35rem .5rem;border-radius:var(--ui-radius, 4px);font-size:.76rem}.choice:hover{background:rgb(from var(--text) r g b / .05)}.choice:has(:checked){color:var(--accent);background:rgb(from var(--accent) r g b / .1)}.choice input{margin:0;accent-color:var(--accent)}.choice span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.slider{--thumb-size: 1rem;padding:.15rem .6rem 0}input[type=range]{appearance:none;display:block;width:100%;height:var(--thumb-size);margin:.4rem 0 .5rem;padding:0;border:0;background:transparent}input[type=range]::-webkit-slider-runnable-track{height:.3rem;border-radius:var(--ui-radius, 999px);background:linear-gradient(to right,var(--accent) var(--effort-fill),var(--surface-active) var(--effort-fill))}input[type=range]::-moz-range-track{height:.3rem;border-radius:var(--ui-radius, 999px);background:linear-gradient(to right,var(--accent) var(--effort-fill),var(--surface-active) var(--effort-fill))}input[type=range]::-webkit-slider-thumb{appearance:none;width:var(--thumb-size);height:var(--thumb-size);margin-top:calc((.3rem - var(--thumb-size)) / 2);border:0;border-radius:50%;background:var(--accent)}input[type=range]::-moz-range-thumb{width:var(--thumb-size);height:var(--thumb-size);border:0;border-radius:50%;background:var(--accent)}input[type=range]:disabled{opacity:.5}.steps{position:relative;height:1.3rem;margin:0 calc(var(--thumb-size) / 2)}.step{position:absolute;top:0;left:var(--step-position);transform:translate(-50%);padding:.35rem 0 0;border:0;background:transparent;color:var(--muted);font:inherit;font-size:.62rem;white-space:nowrap;cursor:default}.step:before{content:"";position:absolute;top:0;left:50%;transform:translate(-50%);width:1px;height:.2rem;background:var(--muted)}.step.active{color:var(--accent)}:is(summary,input,button):focus-visible{outline:2px solid var(--accent);outline-offset:2px}.message{margin:0;color:var(--muted);font-size:.75rem}.error{color:var(--critical, #e5534b)}.retry{margin-left:.5rem;padding:.2rem .4rem;border:1px solid var(--border);border-radius:var(--ui-radius, 4px);background:var(--bg);color:var(--text);font:inherit}@container scan-controls (max-width: 50rem){.layout.with-extra{grid-template-columns:minmax(16rem,1fr) minmax(14rem,1fr)}.layout.with-extra .extra{grid-column:1 / -1;align-self:start;min-height:0}}@container scan-controls (max-width: 33rem){.layout,.layout.with-extra{grid-template-columns:minmax(0,1fr);gap:1rem}.layout.with-extra .extra{grid-column:auto}}:host-context(body.theme-w95) *{overscroll-behavior:none}`;constructor(){super(),this.loadModels=s,this.pending=!1,this.value=null,this.effort=null,this.hasExtra=!1,this._models=[],this._error=null,this._menuColumns=1,this._positionRequest=0,this._onOutside=e=>{e.composedPath().includes(this)||this._close()},this._onViewportChange=()=>this._positionMenu()}connectedCallback(){super.connectedCallback(),document.addEventListener(`pointerdown`,this._onOutside),window.addEventListener(`resize`,this._onViewportChange),window.addEventListener(`scroll`,this._onViewportChange,!0),this.hasUpdated&&this._load()}updated(e){(e.has(`loadModels`)||e.has(`pending`))&&this.isConnected&&this._load(),e.has(`_models`)&&this.renderRoot.querySelector(`details`)?.open&&(this._resetMenuPosition(),this._positionMenu())}disconnectedCallback(){super.disconnectedCallback(),this._controller?.abort(),document.removeEventListener(`pointerdown`,this._onOutside),window.removeEventListener(`resize`,this._onViewportChange),window.removeEventListener(`scroll`,this._onViewportChange,!0)}async _load(){if(this._controller?.abort(),this.pending)return;let e=new AbortController;this._controller=e,this._error=null;let t=!1,n=n=>{if(e.signal.aborted)return;t=!0,this._models=n.models;let r=n.models.find(e=>e.id===this.value);r?r.efforts.includes(this.effort)||this._setEffort(o(r)):this._select(n.defaultModel)};try{n(await this.loadModels(e.signal,n))}catch(n){!e.signal.aborted&&!t&&(this._error=String(n?.message??n))}}_close(){this._resetMenuPosition();let e=this.renderRoot.querySelector(`details`);e&&(e.open=!1)}_resetMenuPosition(){this._positionRequest++;let e=this.renderRoot.querySelector(`.menu`);e&&delete e.dataset.positioned}_toggleMenu(e){this._resetMenuPosition(),e.currentTarget.open&&this._positionMenu()}get _selectedRow(){return L(this._models).find(e=>e.id===this.value||e.pro?.id===this.value)}async _positionMenu(){let e=++this._positionRequest,t=this.renderRoot.querySelector(`details`),n=this.renderRoot.querySelector(`summary`),r=this.renderRoot.querySelector(`.menu`);if(!t?.open||!n||!r)return;let i=n.getBoundingClientRect(),a=R(this._models),o=a.reduce((e,t)=>e+t.models.length,0),s=Math.min(3,a.length,Math.ceil((o+a.length*1.5)/9)),c=parseFloat(getComputedStyle(r).fontSize),l=0;for(let e of r.querySelectorAll(`.choice span, legend`)){let t=document.createRange();t.selectNodeContents(e),l=Math.max(l,t.getBoundingClientRect().width)}let u=Math.max(11*c,Math.min(18*c,l+2.5*c)),d=1.3*c+2,f=Math.max(1,Math.min(s,Math.floor((window.innerWidth-16-d+c)/(u+c)))),p=Math.min(f*u+(f-1)*c+d,window.innerWidth-16),m=Math.max(8,Math.min(i.left,window.innerWidth-p-8));if(this._menuColumns=f,await this.updateComplete,e!==this._positionRequest||!this.isConnected||!t.open)return;r.style.left=`${m}px`,r.style.width=`${p}px`,r.style.setProperty(`--model-columns`,f),r.style.maxHeight=`${Math.max(0,window.innerHeight-16)}px`;let h=r.getBoundingClientRect().height,g=window.innerHeight-i.bottom-6-8,_=i.top-6-8,v=g<h&&_>g?i.top-6-h:i.bottom+6;r.style.bottom=`auto`,r.style.top=`${Math.max(8,Math.min(v,window.innerHeight-h-8))}px`,r.dataset.positioned=``}_select(e,{preserveEffort:t=!1,close:n=!0}={}){let r=this._models.find(t=>t.id===e);r&&(this.value=e,this._setEffort(t&&r.efforts.includes(this.effort)?this.effort:o(r)),n&&this._close())}_selectRow(e){let t=this._selectedRow?.pro?.id===this.value;this._select(t&&e.pro?e.pro.id:e.id)}_togglePro(){let e=this._selectedRow;e?.pro&&this._select(this.value===e.pro.id?e.id:e.pro.id,{preserveEffort:!0,close:!1})}_setEffort(e){this.effort=e,this.dispatchEvent(new CustomEvent(`model-change`,{detail:{model:this.value,effort:e},bubbles:!0,composed:!0}))}render(){let e=this._models.find(e=>e.id===this.value);if(this.pending||!e)return P`<div class="${`layout ${this.hasExtra?`with-extra`:``}`}" aria-busy="true"><div class="field"><span class="label">Model</span><div class="model-placeholder" role="${this._error?`alert`:`status`}">${this._error?P`Couldn’t load models. <button type="button" class="retry" @click="${()=>{this._load()}}">Retry</button>`:`Loading models…`}</div></div><div class="field" aria-hidden="true"><span class="label">Effort</span><div class="effort-placeholder"></div></div>${this.hasExtra?P`<div class="extra"><slot name="effort-extra"></slot></div>`:F}</div>`;let t=this._selectedRow,n=i(e.id),a=z(R(this._models),this._menuColumns);return P`${this._error?P`<p class="message error" role="alert">Couldn’t refresh models: ${this._error}<button class="retry" @click="${()=>{this._load()}}">Retry</button></p>`:F}<div class="${`layout ${this.hasExtra?`with-extra`:``}`}"><div class="field"><span class="label" id="model-label">Model</span><div class="model-control"><details @toggle="${this._toggleMenu}" @keydown="${e=>{e.key===`Escape`&&(this._close(),this.renderRoot.querySelector(`summary`)?.focus())}}"><summary aria-labelledby="model-label selected-model" @click="${this._resetMenuPosition}"><span class="${`icon ${n.key}`}" aria-hidden="true">${y(n.key)}</span><span class="selected-copy"><strong id="selected-model">${r(t.id)}</strong><small>${n.name}</small></span>${t.pro?P`<span class="pro-space" aria-hidden="true"></span>`:F}${B}</summary><div class="menu"><div class="groups">${a.map(e=>P`<div class="provider-column">${e.map(e=>this._modelSection(e))}</div>`)}</div></div></details>${t.pro?P`<button type="button" class="pro-toggle" role="switch" aria-label="Pro model" aria-checked="${e.id===t.pro.id}" @click="${this._togglePro}"><span>Pro</span><span class="pro-track" aria-hidden="true"></span></button><label class="pro-checkbox"><input type="checkbox" aria-label="Pro model" .checked="${e.id===t.pro.id}" @change="${this._togglePro}"><span>Pro</span></label>`:F}</div></div>${e.efforts.length>0?this._effortSlider(e.efforts):P`<div class="field" aria-hidden="true"></div>`} ${this.hasExtra?P`<div class="extra"><slot name="effort-extra"></slot></div>`:F}</div>`}_modelSection({key:e,models:t}){return P`<fieldset><legend><span class="${`icon ${e}`}" aria-hidden="true">${y(e)}</span>${i(t[0].id).name}</legend>${t.map(e=>P`<label class="choice"><input type="radio" name="scan-model" value="${e.id}" .checked="${e.id===this.value||e.pro?.id===this.value}" @change="${()=>{this._selectRow(e),this.renderRoot.querySelector(`summary`)?.focus()}}"><span>${r(e.id)}</span></label>`)}</fieldset>`}_effortSlider(e){let t=Math.max(0,e.indexOf(this.effort)),n=Math.max(1,e.length-1);return P`<div class="field"><div class="label"><label for="effort">Effort</label><output for="effort">${a(e[t])}</output></div><div class="slider" style="${D({"--effort-fill":`calc(var(--thumb-size) / 2 + (100% - var(--thumb-size)) * ${t/n})`})}"><input id="effort" type="range" min="0" max="${n}" step="1" .value="${String(t)}" ?disabled="${e.length===1}" aria-valuetext="${a(e[t])}" @input="${t=>this._setEffort(e[Number(t.target.value)])}"><div class="steps">${e.map((e,t)=>P`<button type="button" class="${`step ${e===this.effort?`active`:``}`}" style="${D({"--step-position":`${t/n*100}%`})}" aria-label="${`Set effort to ${a(e)}`}" aria-pressed="${e===this.effort}" @click="${()=>this._setEffort(e)}">${a(e)}</button>`)}</div></div></div>`}};customElements.get(`scan-model-picker`)||customElements.define(`scan-model-picker`,V);var H=class extends ae{constructor(){super(),this.label=`Choose workspace`,this.placeholder=`Choose workspace`}get searchLabel(){return`Search workspaces`}get optionsLabel(){return`Workspaces`}get noMatchesLabel(){return`No matching workspaces`}get emptyLabel(){return`No workspaces available`}get changeEvent(){return`workspace-change`}choices(){let e=this._query.normalize(`NFKC`).toLocaleLowerCase().trim().split(/\s+/u).filter(Boolean),t=this.options.filter(t=>e.every(e=>t.label.normalize(`NFKC`).toLocaleLowerCase().includes(e))).toSorted((e,t)=>e.label.localeCompare(t.label,void 0,{numeric:!0,sensitivity:`base`}));return{pinned:[],sections:[{label:null,options:t}],facets:[],showFacets:!1,count:t.length,total:this.options.length}}};customElements.get(`workspace-selector`)||customElements.define(`workspace-selector`,H);var U=P`<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>`,W=P`<svg viewBox="0 0 16 16" aria-hidden="true"><path d="m4 4 8 8M12 4l-8 8"/></svg>`,G=N`.row-action{display:grid;place-items:center;flex:0 0 auto;width:1.5rem;height:1.5rem;padding:.25rem;border:0;border-radius:var(--ui-radius, 4px);color:var(--muted);background:transparent}.row-action:hover:not(:disabled){color:var(--text);background:var(--surface-active)}.row-action:disabled{opacity:.4}.row-action svg{width:1rem;height:1rem;fill:none;stroke:currentColor;stroke-width:1.4}`,K=e=>({kind:e,sourceIds:[null],ids:new Set}),le=class extends I{static properties={mode:{type:String},loadSources:{attribute:!1},restore:{attribute:!1},_sources:{state:!0},_loading:{state:!0},_error:{state:!0},_merge:{state:!0},_link:{state:!0}};constructor(){super(),this.mode=`link`,this._sources=null,this._loading=!1,this._error=null,this._merge=K(`bundle`),this._link=K(`repository`)}connectedCallback(){super.connectedCallback(),this.dispatchEvent(new CustomEvent(`tooltip-root-connected`,{bubbles:!0,composed:!0}))}disconnectedCallback(){super.disconnectedCallback(),this._controller?.abort()}updated(e){if(e.has(`loadSources`)){this._load();return}e.has(`mode`)&&this._selectOnlySource(),e.has(`restore`)&&this._restore(),[`_sources`,`_merge`,`_link`,`mode`,`restore`].some(t=>e.has(t))&&this._notify()}get _current(){return this.mode===`merge`?this._merge:this._link}get _parents(){if(this.mode===`merge`)return this._sources?.merge?.bundles??[];let e=this._sources?.link?.reports??[];return this._current.kind===`workspace`?(this._sources?.link?.workspaces??[]).filter(t=>e.some(e=>t.reports.includes(e.id))):(this._sources?.link?.repositories??[]).filter(t=>e.some(e=>e.repoIds.includes(t.id)))}get _selectedParents(){let e=this._parents;return this._current.sourceIds.map(t=>e.find(e=>e.id===t)).filter(Boolean)}get _parent(){return this._selectedParents[0]}get _scopeOptions(){let e=this._sources?.link?.reports??[];return this._parents.map(t=>{let n=e.filter(e=>this._current.kind===`workspace`?t.reports.includes(e.id):e.repoIds.includes(t.id)).length;return{value:t.id,label:t.label,detail:`${n} ${n===1?`report`:`reports`}`}})}get _inputs(){let e=this._selectedParents;return e.length===0?[]:this.mode===`merge`?(this._sources?.merge?.results??[]).filter(t=>t.bundleId===e[0].id):(this._sources?.link?.reports??[]).filter(t=>this._current.kind===`workspace`?e[0].reports.includes(t.id):t.repoIds.some(t=>e.some(e=>e.id===t)))}get selection(){let e=this._selectedParents,t=e[0],n=t?this.mode===`link`&&this._current.kind===`repository`?{kind:`repository`,ids:e.map(e=>e.id),label:e.map(e=>e.label).join(`, `)}:{kind:this._current.kind,id:t.id,label:t.label??t.filename}:null;return{mode:this.mode,source:n,inputs:this._loading||this._error?[]:this._inputs.filter(e=>this._current.ids.has(e.id))}}_notify(){this.dispatchEvent(new CustomEvent(`report-inputs-change`,{detail:this.selection,bubbles:!0,composed:!0}))}async _load(){this._controller?.abort();let e=this._controller=new AbortController;this._loading=!0,this._error=null,this._notify();let t=!1,n=n=>{if(e.signal.aborted)return;let r=!t;t=!0,this._sources=n,r&&(this._merge=K(`bundle`),this._link=K(Array.isArray(n.link?.workspaces)?`workspace`:`repository`)),this._selectOnlySource(),r&&this._restore(),this._loading=!1,this._notify()};try{n(this.loadSources?await this.loadSources(e.signal,n):{merge:{bundles:[],results:[]},link:{repositories:[],reports:[]}})}catch(n){!e.signal.aborted&&!t&&(this._error=String(n?.message??n))}finally{e.signal.aborted||(this._loading=!1,this._notify())}}_setCurrent(e){this.mode===`merge`?this._merge=e:this._link=e}_selectSource(e,t=0){if(t<0||t>=this._current.sourceIds.length||this._current.sourceIds.includes(e)||!this._parents.some(t=>t.id===e))return;let n=new Set(this.mode===`link`&&this._current.kind===`repository`?this._inputs.map(e=>e.id):[]);this._setCurrent({...this._current,sourceIds:this._current.sourceIds.map((n,r)=>r===t?e:n)}),this._setCurrent({...this._current,ids:new Set(this._inputs.filter(e=>!n.has(e.id)||this._current.ids.has(e.id)).map(e=>e.id))}),this._notify()}get _canAddRepository(){return this.mode===`link`&&this._current.kind===`repository`&&!this._loading&&!this._current.sourceIds.includes(null)&&this._parents.some(e=>!this._current.sourceIds.includes(e.id))}_addRepository(){this._canAddRepository&&(this._link={...this._link,sourceIds:[...this._link.sourceIds,null]},this._focusRepository(this._link.sourceIds.length-1))}_removeRepository(e){this.mode!==`link`||this._link.kind!==`repository`||this._loading||this._link.sourceIds.length<=1||e<0||e>=this._link.sourceIds.length||(this._link={...this._link,sourceIds:this._link.sourceIds.filter((t,n)=>n!==e)},this._link={...this._link,ids:new Set(this._inputs.filter(e=>this._link.ids.has(e.id)).map(e=>e.id))},this._notify(),this._focusRepository(Math.min(e,this._link.sourceIds.length-1)))}async _focusRepository(e){await this.updateComplete,this.renderRoot?.querySelectorAll(`repository-selector`)[e]?.renderRoot?.querySelector(`.trigger`)?.focus()}_changeKind(e){[`workspace`,`repository`].includes(e)&&(e===`workspace`&&!Array.isArray(this._sources?.link?.workspaces)||(e!==this._link.kind&&(this._link=K(e)),this._selectOnlySource(),this._notify()))}_selectOnlySource(){this.mode===`link`&&this._current.sourceIds.length===1&&this._current.sourceIds[0]==null&&this._parents.length===1&&this._selectSource(this._parents[0].id)}_toggle(e,t){if(!this._inputs.some(t=>t.id===e))return;let n=new Set(this._current.ids);t?n.add(e):n.delete(e),this._setCurrent({...this._current,ids:n}),this._notify()}_selectAll(e){this._setCurrent({...this._current,ids:new Set(e?this._inputs.map(e=>e.id):[])}),this._notify()}_restore(){let e=this.restore;if(!this._sources||e?.mode!==this.mode||!e.source)return;let t=this.mode===`merge`?`bundle`:e.source.kind;if(this.mode===`link`&&(t===`workspace`?!Array.isArray(this._sources.link?.workspaces):t!==`repository`))return;let n=this.mode===`link`&&t===`repository`?e.source.ids??[e.source.id]:[e.source.id],r=[...new Set(n)].filter(e=>e!=null);this._setCurrent({kind:t,sourceIds:r.length>0?r:[null],ids:new Set}),this._setCurrent({...this._current,ids:new Set(this._inputs.filter(t=>e.inputIds.includes(t.id)).map(e=>e.id))})}render(){let e=this.mode===`merge`,t=this._inputs,n=t.filter(e=>this._current.ids.has(e.id)).length,r=Array.isArray(this._sources?.link?.workspaces),i=this._parent?e?`No scan results for this bundle.`:`No saved reports in this ${this._current.kind}.`:e?`Choose a bundle to see its scan results.`:this._parents.length===0?`No saved reports with app findings.`:`Choose a ${this._current.kind} to see its saved reports.`;return P`<section class="panel" aria-label="${e?`Merge scan results`:`Link saved reports`}" aria-busy="${this._loading}"><div class="source">${!e&&r?P`<div class="kinds" role="radiogroup" aria-label="Report source">${[[`workspace`,`Workspace`],[`repository`,`Repository`]].map(([e,t])=>P`<button type="button" role="radio" aria-checked="${e===this._link.kind}" @click="${()=>this._changeKind(e)}">${t}</button>`)}</div>`:F}<div class="field">${e?P`<span>Bundle with scan results</span>`:F} ${e?P`<bundle-selector .bundles="${this._parents}" .value="${this._current.sourceIds[0]}" ?disabled="${this._loading||this._parents.length===0}" @bundle-change="${e=>this._selectSource(e.detail.value)}"></bundle-selector>`:this._current.kind===`workspace`?P`<workspace-selector .options="${this._scopeOptions}" .value="${this._current.sourceIds[0]}" ?disabled="${this._loading}" @workspace-change="${e=>this._selectSource(e.detail.value)}"></workspace-selector>`:this._repositoryFields()}</div></div><div class="input-results">${this._error?P`<p class="empty" role="alert">Couldn’t load report inputs: ${this._error} <button type="button" @click="${()=>{this._load()}}">Retry</button></p>`:this._loading&&this._sources==null?P`<p class="empty" role="status">Loading report inputs…</p>`:t.length>0?P`<div class="list-head"><label><input type="checkbox" aria-label="Select all" ?disabled="${this._loading}" .checked="${n===t.length}" .indeterminate="${n>0&&n<t.length}" @change="${e=>this._selectAll(e.target.checked)}"><strong>All</strong></label><span>${n} of ${t.length} selected</span></div><div class="list">${t.map(e=>this._row(e))}</div>`:P`<p class="empty">${e&&this._parents.length===0?`No scan results available.`:i}</p>`}</div></section>`}_repositoryFields(){let e=this._current.sourceIds,t=this._scopeOptions;return P`<div class="repository-fields"><div class="repository-rows">${e.map((n,r)=>P`<div class="repository-row"><repository-selector .options="${t.filter(t=>t.value===n||!e.includes(t.value))}" .value="${n}" label="${`Choose repository ${r+1}`}" ?disabled="${this._loading}" @repository-change="${e=>this._selectSource(e.detail.value,r)}"></repository-selector>${e.length>1?P`<button type="button" class="row-action" aria-label="${`Remove repository ${r+1}`}" ?disabled="${this._loading}" @click="${()=>this._removeRepository(r)}">${W}</button>`:F}</div>`)}</div><button type="button" class="row-action" aria-label="Add repository" ?disabled="${!this._canAddRepository}" @click="${()=>this._addRepository()}">${U}</button></div>`}_row(e){let t=this.mode===`link`?e.appFindings:e.findings,n=[e.model?r(e.model):null,t==null?null:`${t} ${this.mode===`link`?`app `:``}${t===1?`finding`:`findings`}`,e.createdAt,e.repo?`${e.repo}${e.directory?`/${e.directory}`:``}`:null].filter(Boolean),i=e.title??e.filename,a=n.join(` · `);return P`<label class="option"><input type="checkbox" ?disabled="${this._loading}" .checked="${this._current.ids.has(e.id)}" @change="${t=>this._toggle(e.id,t.target.checked)}">${k(x[e.analyzer]??x.default)}<span class="copy"><strong data-tooltip-truncated data-tooltip="${i}">${i}</strong><span data-tooltip-truncated data-tooltip="${a}">${a}</span></span></label>`}static styles=[N`:host{display:block;min-width:0}*{box-sizing:border-box}button,.field>span,.list-head,.empty:not([role=alert]){cursor:default;user-select:none;-webkit-user-select:none}.panel{border:1px solid var(--border);border-radius:var(--ui-radius, 9px);background:var(--surface);overflow:hidden}.source{display:flex;flex-wrap:wrap;align-items:start;gap:.7rem;padding:.85rem .9rem;border-bottom:1px solid var(--border)}.field{display:grid;flex:1 1 14rem;gap:.3rem;max-width:32rem;min-width:0}.field>span{color:var(--muted);font-size:.72rem}button{padding:.3rem .55rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font:inherit;font-size:.74rem;cursor:default}.repository-fields{display:flex;align-items:start;gap:.4rem}.repository-fields>.row-action{margin-top:.25rem}.repository-rows{display:grid;flex:1;min-width:0;gap:.65rem}.repository-row{display:flex;align-items:center;gap:.4rem}.repository-row repository-selector{flex:1}.kinds{display:flex;width:fit-content;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);overflow:hidden}.kinds button{padding-block:.5rem;border:0;border-radius:0;color:var(--muted)}.kinds button+button{border-left:1px solid var(--border)}.kinds button[aria-checked=true]{color:var(--text);background:var(--surface-active)}.list-head{flex-shrink:0;display:flex;align-items:center;justify-content:space-between;gap:.5rem;padding:.55rem .9rem;border-bottom:1px solid var(--border)}.list-head label{display:flex;align-items:center;gap:.55rem;user-select:none}.list-head strong{color:var(--text);font-size:.74rem;font-weight:600}.list-head>span{color:var(--muted);font-size:.68rem}.input-results{height:16rem;display:flex;flex-direction:column;overflow:auto}.list{min-height:0;overflow:auto;overscroll-behavior:none}.option{display:flex;align-items:center;gap:.55rem;min-width:0;padding:.35rem .9rem;user-select:none}.option+.option{border-top:1px solid var(--border)}.option:hover{background:var(--surface-active)}input{width:.85rem;height:.85rem;margin:0;flex:0 0 auto;accent-color:var(--accent)}.file-icon{width:1.4rem;height:1.4rem;flex:0 0 auto}.copy{display:flex;align-items:center;justify-content:space-between;gap:.75rem;flex:1;min-width:0}.copy strong,.copy span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.copy strong{flex:1;color:var(--text);font-size:.74rem;font-weight:500}.copy span{max-width:55%;color:var(--muted);font-size:.66rem}.empty{margin:0;padding:1rem .9rem;color:var(--muted);font-size:.76rem}button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}:host-context(body.theme-w95) *{overscroll-behavior:none}`,G]};customElements.get(`scan-report-inputs`)||customElements.define(`scan-report-inputs`,le);var ue=P`<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M6 4h7M6 8h7M6 12h7M3 4h.01M3 8h.01M3 12h.01"/></svg>`,de=P`<svg viewBox="0 0 16 16" aria-hidden="true"><circle cx="7" cy="7" r="4.5"/><path d="m10.5 10.5 3 3M7 5v4M5 7h4"/></svg>`,fe=class extends I{static properties={isolate:{type:Boolean},vertical:{type:Boolean,reflect:!0}};constructor(){super(),this.isolate=!1,this.vertical=!1}_select(e){this.isolate!==e&&(this.isolate=e,this.dispatchEvent(new CustomEvent(`depth-change`,{detail:{isolate:e},bubbles:!0,composed:!0})))}render(){return P`<div class="scan-depth"><div class="depth-options" role="radiogroup" aria-label="Scan depth" aria-orientation="${this.vertical?`vertical`:`horizontal`}" aria-describedby="${this.vertical?F:`scan-depth-description`}">${[[!1,`List`,ue],[!0,`Isolate`,de]].map(([e,t,n])=>P`<label class="depth-choice"><input type="radio" name="scan-depth" value="${e?`isolate`:`list`}" .checked="${this.isolate===e}" @change="${()=>this._select(e)}"><span>${n}${t}</span></label>`)}</div>${this.vertical?F:P`<div class="depth-description" id="scan-depth-description" aria-live="polite"><span class="${this.isolate?`inactive`:``}" aria-hidden="${this.isolate}">Regular scan depth</span><span class="${this.isolate?``:`inactive`}" aria-hidden="${!this.isolate}">Deeper search at ~10x the tokens spent</span></div>`}</div>`}static styles=N`:host{display:block;width:19rem;max-width:100%;min-width:0}*{box-sizing:border-box}.scan-depth{display:grid;gap:.4rem;width:100%;min-width:0;user-select:none}.depth-options{display:flex;position:relative;padding:.2rem;border:1px solid var(--border);border-radius:var(--ui-radius, 8px);background:var(--bg)}.depth-options:before{content:"";position:absolute;inset:.2rem auto .2rem .2rem;width:calc((100% - .4rem)/2);border-radius:var(--ui-radius, 5px);background:var(--surface-active);box-shadow:0 1px 3px #0000001f,inset 0 0 0 1px rgb(from var(--accent) r g b / .18);transition:transform .16s ease-out}.depth-options:has(input[value=isolate]:checked):before{transform:translate(100%)}.depth-choice{position:relative;flex:1;min-width:0}.depth-choice input{position:absolute;width:1px;height:1px;opacity:0}.depth-choice span{display:flex;align-items:center;justify-content:center;gap:.4rem;height:1.9rem;padding:.3rem .65rem;border-radius:var(--ui-radius, 5px);color:var(--muted);font-size:.76rem;font-weight:500;transition:color .12s}.depth-choice svg{width:.95rem;height:.95rem;fill:none;stroke:currentColor;stroke-width:1.4;stroke-linecap:round;stroke-linejoin:round}.depth-choice:hover span{color:var(--text)}.depth-choice input:checked+span{color:var(--accent)}.depth-choice input:focus-visible+span{outline:2px solid var(--accent);outline-offset:-2px}.depth-description{display:grid;color:var(--muted);font-size:.68rem;line-height:1.4}.depth-description span{grid-area:1 / 1}.depth-description .inactive{visibility:hidden}@media(prefers-reduced-motion:reduce){.depth-options:before,.depth-choice span{transition:none}}:host([vertical]){width:5.8rem}:host([vertical]) .depth-options{flex-direction:column}:host([vertical]) .depth-options:before{inset:.2rem .2rem auto;width:auto;height:calc((100% - .4rem)/2)}:host([vertical]) .depth-options:has(input[value=isolate]:checked):before{transform:translateY(100%)}:host([vertical]) .depth-choice span{justify-content:flex-start;height:1.7rem;padding:.25rem .5rem;font-size:.72rem}`};customElements.get(`scan-depth-toggle`)||customElements.define(`scan-depth-toggle`,fe);var q=[`security`,`generic`,`correctness`],pe=e=>JSON.stringify([e.mode,e.model,e.effort,e.isolate]);function me(e){let t=e[0];return t?.model&&e.every(e=>e.model===t.model&&e.effort===t.effort)?{model:t.model,effort:t.effort}:null}function he(e,t){let n=t.models.find(t=>t.id===e?.model)??t.models.find(e=>e.id===t.defaultModel)??t.models[0];return n?{model:n.id,effort:n.efforts.includes(e?.effort)?e.effort:o(n)}:null}function J(e,t){let n=t.models.find(e=>e.id===t.defaultModel)??t.models[0];return n?(e.length>0?e:[{mode:`generic`,isolate:!1}]).map(e=>{let r=t.models.find(t=>t.id===e.model)??n;return{...e,mode:q.includes(e.mode)?e.mode:`generic`,model:r.id,effort:r.efforts.includes(e.effort)?e.effort:o(r),isolate:!!e.isolate}}):[]}function Y(e){let t=new Set;return e.map(e=>{let n=pe(e),r=t.has(n);return t.add(n),r})}var ge=class extends I{static properties={value:{attribute:!1},loadModels:{attribute:!1},appModel:{attribute:!1},appModelAutomatic:{attribute:!1},_rows:{state:!0},_loading:{state:!0},_error:{state:!0},_resolvedAppModel:{state:!0},_appModelOpen:{state:!0}};constructor(){super(),this.value=[],this.appModel=null,this.appModelAutomatic=!0,this._resolvedAppModel=null,this._appModelOpen=!1,this._appModelsAgree=!0,this._rows=[],this._catalogue={models:[]},this._nextId=0,this._loading=!0,this._error=null}disconnectedCallback(){super.disconnectedCallback(),this._controller?.abort()}updated(e){if(e.has(`loadModels`)){this._load();return}e.has(`value`)&&this.value!==this._lastEmitted&&!this._loading?(this._setRows(this.value),this._notify()):(e.has(`appModel`)||e.has(`appModelAutomatic`))&&!this._loading&&this._notify()}_setRows(e){this._rows=J(e,this._catalogue).map(e=>({...e,id:e.id??++this._nextId}))}_notify(){let e=this._loading&&this._rows.length===0?this.value:this._rows.map(({id:e,...t})=>t);this._loading||this._syncAppModel();let t=!this._loading&&!this._error&&this._resolvedAppModel!=null&&e.length>0&&!Y(e).includes(!0);this._lastEmitted=e,this.dispatchEvent(new CustomEvent(`regimes-change`,{detail:{value:e,ready:t,appModel:this._resolvedAppModel??this.appModel,appModelAutomatic:this.appModelAutomatic},bubbles:!0,composed:!0}))}_syncAppModel(){let e=me(this._rows),t=he((this.appModelAutomatic?e:null)??this.appModel??this._rows[0],this._catalogue);(this.appModel?.model!==t?.model||this.appModel?.effort!==t?.effort)&&(this.appModel=t),this._resolvedAppModel=this.appModel;let n=!!e&&e.model===t?.model&&e.effort===t?.effort;n!==this._appModelsAgree&&(this._appModelOpen=!n),this._appModelsAgree=n}_changeAppModel(e){e.model===this._resolvedAppModel?.model&&e.effort===this._resolvedAppModel?.effort||(this.appModelAutomatic=!1,this.appModel={model:e.model,effort:e.effort},this._notify())}async _load(){this._controller?.abort();let e=this._controller=new AbortController;this._loading=!0,this._error=null,this._notify();let t=!1,n=n=>{e.signal.aborted||(t=!0,this._catalogue=n,this._sharedModels=()=>Promise.resolve(n),this._setRows(this._rows.length>0?this._rows:this.value),this._loading=!1,this._notify())};try{n(await this.loadModels(e.signal,n))}catch(n){!e.signal.aborted&&!t&&(this._error=String(n?.message??n))}finally{e.signal.aborted||(this._loading=!1,this._notify())}}_change(e,t){let n=this._rows.find(t=>t.id===e);if(!n)return;let r=J([{...n,...t}],this._catalogue)[0];r&&(this._rows=this._rows.map(t=>t.id===e?r:t),this._notify())}_add(){let e=this._rows.at(-1);e&&(this._rows=[...this._rows,{...e,id:++this._nextId}],this._notify())}_remove(e){this._rows.length<=1||(this._rows=this._rows.filter(t=>t.id!==e),this._notify())}render(){let e=this._loading&&this._rows.length===0,t=e?(this.value.length>0?this.value:[{mode:`generic`,isolate:!1}]).map((e,t)=>({...e,id:`pending-${t}`})):this._rows,n=Y(this._rows);return P`<section aria-label="Scan regimes" aria-busy="${this._loading}"><div class="heading"><h2>Scan regimes</h2><span>${t.length} ${t.length===1?`regime`:`regimes`}</span></div>${this._error?P`<p class="message" role="alert">Couldn’t load models: ${this._error} <button type="button" @click="${()=>{this._load()}}">Retry</button></p>`:F} ${O(t,e=>e.id,(t,r)=>this._row(t,r,n[r],e))}<div class="footer"><button type="button" class="add" ?disabled="${this._loading||this._rows.length===0}" @click="${this._add}"><span aria-hidden="true">+</span> Add regime</button><span class="message" role="status">${n.includes(!0)?`Change or remove duplicate regimes to run the scan`:`Results from these regimes will be merged`}</span></div>${e?P`<div class="app-model"><div class="app-model-placeholder">App model: Loading…</div></div>`:this._appModelRow()}</section>`}_appModelRow(){let e=this._resolvedAppModel;return e?P`<details class="app-model" .open="${S(this._appModelOpen)}" @toggle="${e=>{this._appModelOpen=e.currentTarget.open}}"><summary><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="m6 3 5 5-5 5"/></svg><span class="app-model-name">App model: <strong>${r(e.model)}</strong></span><span class="app-model-effort">Effort: <strong>${a(e.effort)}</strong></span></summary><div class="app-model-controls"><scan-model-picker .loadModels="${this._sharedModels}" .value="${S(e.model)}" .effort="${S(e.effort)}" @model-change="${e=>{e.stopPropagation(),this._changeAppModel(e.detail)}}"></scan-model-picker></div></details>`:F}_row(e,t,n,r=!1){return P`<div class="${`row${n?` duplicate`:``}`}" ?inert="${r}" role="group" aria-label="${`Regime ${t+1}`}" aria-describedby="${n?`duplicate-${e.id}`:F}"><div class="mode" role="radiogroup" aria-label="Scan mode">${q.map(t=>P`<label class="mode-choice"><input type="radio" name="${`regime-mode-${e.id}`}" .checked="${e.mode===t}" @change="${()=>this._change(e.id,{mode:t})}"><span>${t[0].toUpperCase()+t.slice(1)}</span></label>`)}</div><scan-model-picker .pending="${r}" .loadModels="${this._sharedModels}" .value="${S(e.model)}" .effort="${S(e.effort)}" @model-change="${t=>{t.stopPropagation(),this._change(e.id,t.detail)}}"></scan-model-picker><div class="row-actions"><scan-depth-toggle vertical .isolate="${e.isolate}" @depth-change="${t=>{t.stopPropagation(),this._change(e.id,{isolate:t.detail.isolate})}}"></scan-depth-toggle>${n?P`<span class="duplicate-label" id="${`duplicate-${e.id}`}">Duplicate regime</span>`:F}</div><button type="button" class="remove" aria-label="${`Remove regime ${t+1}`}" ?disabled="${this._rows.length===1}" @click="${()=>this._remove(e.id)}"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" aria-hidden="true"><path d="m4 4 8 8M12 4l-8 8"/></svg></button></div>`}static styles=N`:host{display:block;min-width:0;container:regime-editor / inline-size}*{box-sizing:border-box}.heading{display:flex;align-items:baseline;gap:.65rem;margin-bottom:.75rem}h2{margin:0;color:var(--text);font-size:.85rem;font-weight:600}.heading>span{color:var(--muted);font-size:.7rem}.row{position:relative;display:grid;grid-template-columns:7.75rem minmax(0,1fr) 5.8rem;align-items:start;gap:1rem;padding:.85rem 0;border-top:1px solid var(--border)}.mode{display:grid;min-width:0;border:1px solid var(--border);border-radius:var(--ui-radius, 6px);overflow:hidden;background:var(--bg)}.mode-choice{position:relative;user-select:none}.mode-choice+.mode-choice{border-top:1px solid var(--border)}.mode-choice input{position:absolute;width:1px;height:1px;opacity:0}.mode-choice span{display:block;padding:.2rem .6rem;color:var(--muted);font-size:.72rem;line-height:1.15rem}.mode-choice:hover span{background:var(--surface-active)}.mode-choice input:checked+span{color:var(--accent);background:rgb(from var(--accent) r g b / .1);box-shadow:inset 2px 0 var(--accent);font-weight:600}.mode-choice input:focus-visible+span{outline:2px solid var(--accent);outline-offset:-2px}button{border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font:inherit;font-size:.74rem;cursor:default}button{padding:.4rem .55rem;user-select:none}button:hover:not(:disabled){background:var(--surface-active)}button:disabled{opacity:.35}.row-actions{position:relative;display:flex;align-items:center;align-self:stretch;min-height:4.65rem;padding:.8rem 0 .25rem}.remove{position:absolute;top:.15rem;right:0;display:grid;place-items:center;width:1.5rem;height:1.5rem;padding:.25rem;border:0;background:transparent;color:var(--muted)}.duplicate-label{position:absolute;right:.15rem;bottom:-.05rem;transform:rotate(-7deg);padding:.1rem .3rem;border:1px solid rgb(from var(--critical, #e5534b) r g b / .45);border-radius:3px;color:var(--critical, #e5534b);background:var(--surface);font-size:.6rem;line-height:1rem;white-space:nowrap;pointer-events:none;user-select:none}svg{width:1rem;height:1rem}.footer{display:flex;flex-wrap:wrap;align-items:center;gap:.7rem;padding-top:.6rem;border-top:1px solid var(--border)}.add{display:flex;align-items:center;gap:.3rem}.app-model{margin-top:.7rem;border-top:1px solid var(--border)}.app-model-placeholder{padding:.65rem 0 .1rem;color:var(--muted);font-size:.74rem}.app-model>summary{display:flex;flex-wrap:wrap;align-items:center;gap:.35rem .8rem;padding:.65rem 0 .1rem;color:var(--muted);font-size:.74rem;list-style:none;cursor:default;user-select:none}.app-model>summary::-webkit-details-marker{display:none}.app-model>summary:hover{color:var(--text)}.app-model>summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:var(--ui-radius, 3px)}.app-model>summary svg{width:.8rem;height:.8rem;flex:0 0 .8rem}.app-model[open]>summary svg{transform:rotate(90deg)}.app-model strong{color:var(--text);font-weight:500}.app-model-name{min-width:0;overflow-wrap:anywhere}.app-model-effort{white-space:nowrap}.app-model-controls{padding:.85rem 0 .15rem}.message{margin:0;color:var(--muted);font-size:.7rem}button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@container regime-editor (max-width: 54rem){.row{grid-template-columns:minmax(0,1fr) 5.8rem}scan-model-picker{grid-row:2;grid-column:1 / -1}.mode{grid-column:1;max-width:9rem}.row-actions{grid-column:2}}`};customElements.get(`scan-regime-editor`)||customElements.define(`scan-regime-editor`,ge);var _e=`:host{display:block;min-width:0;color:var(--text);container:mode-selector / inline-size}*{box-sizing:border-box}section{overflow:hidden;border:1px solid var(--border);border-radius:var(--ui-radius, 9px);background:var(--surface)}header{display:flex;align-items:baseline;gap:.8rem;padding:.85rem 1rem .7rem}h2{margin:0;font-size:.86rem;font-weight:600}header>span{color:var(--muted);font-size:.73rem}fieldset{min-width:0;margin:0;padding:0;border:0}.modes{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.5rem;padding:0 1rem .9rem}.mode{position:relative;display:flex;align-items:flex-start;gap:.55rem;padding:.7rem .65rem;border:1px solid var(--border);border-radius:var(--ui-radius, 7px);background:var(--bg);cursor:default;text-align:left}.mode:hover{background:var(--surface-active)}.mode:has(:checked){border-color:rgb(from var(--accent) r g b / .6);background:rgb(from var(--accent) r g b / .07)}input{position:absolute;width:1px;height:1px;opacity:0;margin:0}.mode:has(:focus-visible),.subtype-option:has(:focus-visible){outline:2px solid var(--accent);outline-offset:3px}.mode-icon{display:flex;flex-shrink:0;color:var(--muted);padding-top:.1rem}.mode-icon svg{width:1rem;height:1rem}.mode-copy{display:grid;min-width:0;gap:.35rem;padding-right:.55rem}.mode-copy strong{font-size:.78rem;font-weight:500;line-height:1.3}.mode-copy>span{color:var(--muted);font-size:.69rem;line-height:1.4}.mode:has(:checked) .mode-copy strong,.mode:has(:checked) .mode-icon{color:var(--accent)}.indicator{position:absolute;right:.55rem;top:.75rem;width:.55rem;height:.55rem;border:1px solid var(--muted);border-radius:50%;opacity:.5}.mode:has(:checked) .indicator{border-color:var(--accent);background:var(--accent);box-shadow:inset 0 0 0 2px var(--bg);opacity:1}.subtype-wrap{border-top:1px solid var(--border);background:rgb(from var(--accent) r g b / .025)}.subtype-options{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:.45rem;padding:.7rem .9rem .45rem}.report-subtypes{grid-template-columns:repeat(2,minmax(0,1fr));padding-bottom:.7rem}.subtype-option{position:relative;display:grid;gap:.12rem;padding:.42rem .55rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--muted);background:var(--bg);text-align:left}.subtype-option strong{color:var(--text);font-size:.72rem;font-weight:500}.subtype-option span{font-size:.62rem}.subtype-option:has(:checked){border-color:rgb(from var(--accent) r g b / .55);background:rgb(from var(--accent) r g b / .1)}.subtype-option:has(:checked) strong{color:var(--accent)}.subtype-help{margin:0;padding:.15rem .9rem .72rem;color:var(--muted);font-size:.68rem;line-height:1.4}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}@container mode-selector (max-width: 48rem){.modes,.subtype-options{grid-template-columns:repeat(2,minmax(0,1fr))}}@container mode-selector (max-width: 30rem){.mode-icon{display:none}header>span{display:none}}
2
+ `,ve=[{id:`code`,label:`Code`,detail:`Run a full scan of the codebase`,icon:M},{id:`dependencies`,label:`Dependency alerts`,detail:`Validate incoming alerts against actual code`,icon:A},{id:`agentic`,label:`Agentic`,detail:`Free-form analysis with your instructions`,icon:se},{id:`report`,label:`Reports`,detail:`Link saved reports or merge scan results`,icon:j}],ye=[{id:`generic`,label:`Generic`,detail:`Free-form code scan: wide-scoped, most results`},{id:`security`,label:`Security`,detail:`Security findings only`},{id:`correctness`,label:`Correctness`,detail:`Guided correctness scan`},{id:`advanced`,label:`Advanced`,detail:`Merge multiple regimes`}],be=[{id:`link`,label:`Link`,detail:`Link findings across saved reports`},{id:`merge`,label:`Merge`,detail:`Combine scan results for one bundle`}],xe=class extends I{static properties={mode:{},analyzer:{},reportMode:{}};static styles=ce(_e);constructor(){super(),this.mode=`code`,this.analyzer=`generic`,this.reportMode=`link`}_choose(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}render(){let e=this.mode===`code`,t=this.mode===`report`,n=e?ye:be,r=e?this.analyzer:this.reportMode;return P`<section aria-labelledby="mode-heading"><header><h2 id="mode-heading">Scan mode</h2><span>Choose what the server should analyze</span></header><fieldset class="modes"><legend class="sr-only">Scan mode</legend>${ve.map(e=>P`<label class="mode"><input type="radio" name="scan-mode" .checked="${this.mode===e.id}" aria-label="${e.label}" @change="${()=>this._choose(`scan-mode-change`,{mode:e.id})}"> <span class="mode-icon" aria-hidden="true">${k(e.icon)}</span> <span class="mode-copy"><strong>${e.label}</strong><span>${e.detail}</span></span> <span class="indicator" aria-hidden="true"></span></label>`)}</fieldset>${e||t?P`<div class="subtype-wrap"><fieldset class="${`subtype-options ${t?`report-subtypes`:``}`}"><legend class="sr-only">${e?`Code subtype`:`Reports submode`}</legend>${n.map(t=>P`<label class="subtype-option"><input type="radio" name="scan-focus" .checked="${r===t.id}" aria-label="${t.label}" @change="${()=>e?this._choose(`scan-analyzer-change`,{analyzer:t.id}):this._choose(`scan-report-mode-change`,{mode:t.id})}"> <strong>${t.label}</strong><span>${t.detail}</span></label>`)}</fieldset>${e?P`<p class="subtype-help">Focusing controls how effort is spent: while Generic can also find security issues, a focused Security scan is likely to find more.</p>`:F}</div>`:F}</section>`}};customElements.get(`scan-mode-selector`)||customElements.define(`scan-mode-selector`,xe);var Se=N`:host{display:block;box-sizing:border-box;color:var(--text)}*{box-sizing:border-box}.wrap{max-width:76rem;margin:0 auto;container:scan-page / inline-size}.head{display:flex;flex-wrap:wrap;align-items:center;gap:.65rem;min-height:2.1rem;margin-bottom:.45rem}.head-title{display:flex;align-items:center;gap:.65rem}.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}h1{margin:0;font-size:1.65rem;font-weight:600;letter-spacing:-.035em}.head-tabs{display:inline-flex;flex-shrink:0;margin-left:auto;margin-block:calc(-.25rem - 1px);border:1px solid var(--border);border-radius:var(--ui-radius, 6px);overflow:hidden}.head-tabs button{border:0;border-right:1px solid var(--border);padding:.25rem .6rem;color:var(--muted);background:transparent;font:inherit;font-size:.75rem;line-height:1.5}.head-tabs button:last-child{border-right:0}.head-tabs button.active{color:var(--text);background:var(--surface-active)}.head-tabs button:hover{color:var(--text)}.source-choice.single-repository{grid-template-columns:1fr}.head-actions{margin-left:auto;display:flex;gap:.45rem}button,select,input{font:inherit}button,summary,select,h1,.intro,.panel-head,.pane-head,.field>span,.field label,.bundle-label,.bundle-stats,.check,.switch,.offline-help,.empty,.choice-empty{cursor:default;user-select:none;-webkit-user-select:none}input:not([type=checkbox],[type=radio]),textarea{cursor:text;user-select:text;-webkit-user-select:text}a{cursor:default;text-decoration:none}button:focus-visible,select:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.intro-row{display:flex;align-items:center;flex-wrap:wrap;gap:.65rem 1rem;margin-bottom:1.15rem}.intro{margin:0;max-width:52rem;color:var(--muted);font-size:.82rem;line-height:1.5}:host([hide-heading]) .intro-row{gap:.5rem 1rem;margin-bottom:1.25rem}:host([hide-heading]) .intro{max-width:46rem;font-size:.875rem;line-height:1.65}.intro span{display:block}.notice{margin:0 0 1rem;padding:.55rem .7rem;border:1px solid rgb(from var(--accent) r g b / .35);border-radius:var(--ui-radius, 7px);color:var(--text);background:rgb(from var(--accent) r g b / .08);font-size:.78rem}.setup{display:grid;gap:.85rem}.panel{border:1px solid var(--border);border-radius:var(--ui-radius, 9px);background:var(--surface);overflow:hidden}.panel-head{display:flex;align-items:baseline;justify-content:space-between;gap:.7rem;padding:.72rem .9rem;border-bottom:1px solid var(--border)}.panel-head h2{margin:0;font-size:.86rem;font-weight:600}.panel-head p{margin:0;color:var(--muted);font-size:.72rem}.bundle-choice{display:grid;grid-template-columns:minmax(16rem,1.2fr) minmax(0,1fr);gap:1rem;align-items:end;padding:.85rem .9rem}.field{display:grid;gap:.3rem;min-width:0}.source-choice>.field>span,.bundle-label{height:1.25rem}.bundle-label{display:flex;align-items:center;justify-content:space-between;gap:.5rem;min-width:0}.create-bundle-button{display:inline-flex;align-items:center;flex:none;height:1.25rem;padding:0 calc(.4rem + 1px);border:0;border-radius:var(--ui-radius, 4px);color:var(--muted);background:transparent;font-size:.65rem;white-space:nowrap}.create-bundle-button:hover{color:var(--text);background:var(--surface-active)}.create-bundle-button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.field label,.scope-field>span{color:var(--muted);font-size:.68rem}select{min-width:0;height:2rem;padding:.28rem .5rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font-size:.76rem}.bundle-stats{display:grid;grid-template-columns:repeat(4,max-content);align-items:center;gap:.45rem 1.1rem;min-width:0}.metric{display:inline-flex;align-items:center;gap:.3rem;min-width:0;white-space:nowrap}.metric svg{flex:0 0 auto;width:.85rem;height:.85rem;margin-right:.1rem;color:var(--muted)}.metric strong{min-width:0;overflow:hidden;text-overflow:ellipsis;font-size:.72rem;font-weight:600;font-variant-numeric:tabular-nums}.metric span{color:var(--muted);font-size:.7rem}.source-choice{display:grid;grid-template-columns:minmax(12rem,.8fr) minmax(16rem,1.2fr);gap:.7rem;align-items:end;padding:.85rem .9rem}.source-footer{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:start;gap:.7rem 1rem;grid-column:1 / -1;min-width:0}.scope-slot{justify-self:end;width:min(34rem,100%);min-height:2rem}.source-footer .bundle-stats{min-height:2rem}.choice-empty{display:flex;align-items:center;height:2rem;padding:.28rem .5rem;border:1px dashed var(--border);border-radius:var(--ui-radius, 5px);color:var(--muted);background:var(--bg);font-size:.72rem}.choice-empty a{margin-left:.4rem;color:var(--accent);white-space:nowrap}.choice-empty a:hover{color:var(--text)}.choice-empty a:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:var(--ui-radius, 2px)}.scope-head{display:flex;align-items:center;gap:.55rem;padding:.72rem .9rem;list-style:none;cursor:default;user-select:none}.scope-head::-webkit-details-marker{display:none}.scope-head:hover{background:var(--surface-active)}.scope-head:focus-visible{outline:2px solid var(--accent);outline-offset:-3px;border-radius:var(--ui-radius, 8px)}.scope-chevron{width:.85rem;height:.85rem;flex:0 0 auto;transition:transform .15s}.scope-panel[open] .scope-chevron{transform:rotate(90deg)}.scope-panel[open] .scope-head{border-bottom:1px solid var(--border)}.scope-head h2{margin:0;font-size:.86rem;font-weight:600}.scope-head p{display:flex;flex-wrap:wrap;justify-content:end;gap:.15rem .65rem;margin:0 0 0 auto;color:var(--muted);font-size:.7rem;font-variant-numeric:tabular-nums;text-align:right}.scope-head p span{white-space:nowrap}.scope-head p span+span{padding-left:.65rem;border-left:1px solid var(--border)}.scope-grid{display:grid;grid-template-columns:minmax(13rem,.75fr) minmax(0,1.25fr);min-height:0}.scope-pane{min-width:0}.scope-pane+.scope-pane{border-left:1px solid var(--border)}.pane-head{display:flex;align-items:baseline;justify-content:space-between;gap:.5rem;padding:.55rem .75rem;border-bottom:1px solid var(--border)}.pane-head strong{font-size:.72rem;font-weight:600}.pane-head span{color:var(--muted);font-size:.65rem;font-variant-numeric:tabular-nums}.package-list{max-height:22rem;overflow:auto;overscroll-behavior:none}.package-row{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:.45rem;width:100%;padding:.42rem .7rem;border:0;border-bottom:1px solid var(--border);color:var(--text);background:transparent;text-align:left}.package-row:hover{background:var(--surface-active)}.package-row input,.file input{width:.85rem;height:.85rem;accent-color:var(--accent)}.package-name,.package-size{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.package-name{font-size:.7rem}.package-size{color:var(--muted);font-size:.64rem;font-variant-numeric:tabular-nums}.package-row.excluded .package-name{color:var(--muted);text-decoration:line-through}.file-panel{min-width:0}.file-list{display:grid;grid-template-columns:minmax(0,1fr);max-height:22rem;overflow:auto;overscroll-behavior:none}.file{display:flex;align-items:center;gap:.45rem;min-width:0;padding:.35rem .75rem;border-bottom:1px solid var(--border)}.file input{flex:0 0 auto}.file-copy{display:flex;align-items:center;gap:.75rem;flex:1;min-width:0}.file-path{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.72rem}.file-meta{flex:0 1 auto;min-width:0;max-width:50%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:.66rem;font-variant-numeric:tabular-nums}.excluded .file-path{color:var(--muted);text-decoration:line-through}.file-foot{display:flex;justify-content:space-between;gap:.6rem;padding:.6rem .8rem;color:var(--muted);font-size:.7rem}.options{display:grid;grid-template-columns:minmax(0,1fr) auto;column-gap:1rem;position:relative;z-index:2;overflow:visible;padding:.85rem .9rem 1rem}.options-grid{display:grid;grid-column:1 / -1;gap:.7rem;min-width:0}.checks{position:relative;display:grid;grid-column:2;grid-row:3;align-content:center;justify-items:end;margin-top:1rem}.offline-help{position:absolute;top:calc(50% + .75rem);right:0;color:var(--muted);font-size:.66rem;line-height:1.4;white-space:nowrap}.check{display:inline-flex;align-items:center;gap:.4rem;color:var(--text);font-size:.75rem}.check input{width:.85rem;height:.85rem;accent-color:var(--accent)}.switch{display:inline-flex;align-items:center;gap:.45rem;color:var(--text);font-size:.74rem;cursor:default}.switch input{position:var(--switch-input-position, absolute);width:var(--switch-input-size, 1px);height:var(--switch-input-size, 1px);opacity:var(--switch-input-opacity, 0);margin:0;accent-color:var(--accent)}.switch-track{display:var(--switch-track-display, block);position:relative;width:2rem;height:1.1rem;border-radius:var(--ui-radius, 999px);background:var(--surface-active);transition:background .12s}.switch-track:after{content:"";position:absolute;top:.15rem;left:.15rem;width:.8rem;height:.8rem;border-radius:50%;background:var(--muted);transition:transform .12s,background .12s}.switch input:checked+.switch-track{background:rgb(from var(--accent) r g b / .4)}.switch input:checked+.switch-track:after{transform:translate(.9rem);background:var(--accent)}.checks .switch input:checked+.switch-track{background:rgb(from var(--critical, #e5534b) r g b / .3)}.checks .switch input:checked+.switch-track:after{background:var(--critical, #e5534b)}.switch input:focus-visible+.switch-track{outline:2px solid var(--accent);outline-offset:2px}.options-footer{display:flex;flex-wrap:wrap;grid-column:1;grid-row:3;align-items:end;gap:.7rem;min-width:0;margin-top:1rem}.options-footer slot[name=before-run]{display:contents}.agentic-fields{display:grid;gap:.65rem;padding:.85rem .9rem 1rem}.agentic-panel .panel-head{align-items:center}.prompt-row{display:flex;align-items:start;gap:.4rem;min-width:0}.prompt-row textarea{flex:1;width:0}textarea{min-width:0;resize:vertical;padding:.4rem .5rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font:inherit;font-size:.76rem}.run{padding:.48rem .8rem;border:0;border-radius:var(--ui-radius, 6px);color:var(--bg);background:var(--accent);font-size:.8rem;font-weight:600}.run:disabled{opacity:.45}.summary{align-self:end;padding-block:.48rem;color:var(--muted);font-size:.74rem}.history{display:grid;gap:.6rem}.scan-row{display:grid;grid-template-columns:minmax(0,1fr) auto auto;align-items:center;gap:1rem;padding:.85rem .9rem}.scan-row+.scan-row{border-top:1px solid var(--border)}.scan-main{min-width:0}.scan-title{display:flex;align-items:center;gap:.45rem;min-width:0}.scan-title strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.82rem}.scan-meta{display:block;margin-top:.25rem;color:var(--muted);font-size:.7rem}.status{display:inline-flex;align-items:center;gap:.3rem;padding:.15rem .4rem;border-radius:999px;font-size:.66rem;font-weight:600;text-transform:capitalize}.status:before{content:"";width:.4rem;height:.4rem;border-radius:50%;background:currentColor}.status.running{color:var(--accent);background:rgb(from var(--accent) r g b / .1)}.status.completed{color:#48b878;background:#48b8781a}.status.stopped{color:var(--muted);background:var(--surface-active)}.scan-actions{display:flex;align-items:center;gap:.45rem}.action{padding:.35rem .55rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);color:var(--text);background:var(--bg);font-size:.72rem;white-space:nowrap}.action:hover{border-color:var(--muted);background:var(--surface-active)}.empty{margin:0;padding:1.2rem;color:var(--muted);font-size:.8rem}@container scan-page (max-width: 48rem){.bundle-choice,.source-choice,.source-footer{grid-template-columns:1fr;gap:.7rem}.scope-grid{grid-template-columns:1fr}.scope-pane+.scope-pane{border-top:1px solid var(--border);border-left:0}}@container scan-page (max-width: 42rem){.options{display:block;padding-bottom:3rem}.checks{margin-top:.8rem}.offline-help{max-width:100%;white-space:normal}.options-footer{margin-top:.8rem}}@container scan-page (max-width: 34rem){.bundle-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:.45rem .65rem}.scope-head{flex-wrap:wrap}.scope-head p{flex-basis:100%;justify-content:start;margin-left:1.4rem;text-align:left}.scope-head p span{white-space:normal}.scope-head p span+span{padding-left:0;border-left:0}.scan-row{grid-template-columns:1fr;gap:.55rem}.scan-actions{justify-content:flex-start}.head-tabs{margin-left:0}}`,X={code:k(M),report:k(j)},Ce=class extends I{static properties={hideHeading:{type:Boolean,attribute:`hide-heading`},sourceLoading:{type:Boolean,attribute:!1},selection:{attribute:!1},scopeLabel:{type:String,attribute:`scope-label`},createBundleHref:{attribute:!1},source:{attribute:!1},loadBundle:{attribute:!1},loadModels:{attribute:!1},loadReportSources:{attribute:!1},canRun:{attribute:!1},_loadingBundle:{state:!0},_bundleError:{state:!0},_tab:{state:!0},_mode:{state:!0},_bundles:{state:!0},_repositories:{state:!0},_reportMode:{state:!0},_reportInput:{state:!0},_reportRestore:{state:!0},_scans:{state:!0},_selectedRepoId:{state:!0},_selectedBundleId:{state:!0},_reason:{state:!0},_excluded:{state:!0},_excludedModules:{state:!0},_prompts:{state:!0},_options:{state:!0},_regimes:{state:!0},_regimesReady:{state:!0},_appModel:{state:!0},_appModelAutomatic:{state:!0},_notice:{state:!0}};static styles=[Se,G];constructor(){super(),this.loadModels=s,this.canRun=!0,this.hideHeading=!1,this._tab=`new`,this._mode=`code`,this.source=null,this.selection=null,this.scopeLabel=`Repository`,this._pendingSelection=null,this.sourceLoading=!1,this.loadBundle=null,this._loadingBundle=!1,this._bundleError=null,this._bundles=[],this._repositories=[],this._reportMode=`link`,this._reportInput=null,this._reportRestore=null,this._scans=[],this._selectedRepoId=null,this._selectedBundleId=this._bundles[0]?.id??null,this._reason=this._bundles[0]?.reasons[0]?.id??``,this._excluded=new Set,this._excludedModules=new Set,this._nextPromptId=1,this._prompts=[{id:1,text:``}],this._options={analyzer:`generic`,model:null,effort:null,cached:!1,isolate:!1},this._regimes=[],this._appModel=null,this._appModelAutomatic=!0,this._regimesReady=!1,this._notice=null,this._timers=new Set}willUpdate(e){if(e.has(`selection`)&&(this._pendingSelection=this.selection),e.has(`source`)&&(this._bundles=this.source?.bundles??[],this._repositories=this.source?.repositories??[],this._scans=this.source?.scans??[]),e.has(`source`)||e.has(`selection`)){this._excluded=new Set,this._excludedModules=new Set;let e=this._repositories.find(e=>e.id===this._selectedRepoId),t=this._pendingSelection,n=t?this._bundles.find(e=>e.id===t.bundleId&&(t.repoId==null||e.repoId===t.repoId)):this._bundles.find(e=>e.id===this._selectedBundleId&&e.repoId===this._selectedRepoId)??(this.scopeLabel===`Workspace`?null:this._bundles.find(e=>e.id===this._selectedBundleId))??(e?this._bundles.find(t=>t.repoId===e.id):this._bundles[0]);this._selectedRepoId=n?.repoId??t?.repoId??e?.id??this._repositories[0]?.id??`unattached`,this._selectedBundleId=n?.id??null,this._reason=n?.reasons?.[0]?.id??``,t&&(this._tab=`new`,this._mode=[`report`,`dependencies`].includes(t.mode)?t.mode:`code`,t.mode===`report`&&(this._reportMode=`link`,this._reportRestore=null,this._reportInput=null,this._pendingSelection=null),this._notice=t.mode===`report`||n||this.source==null?null:`The selected bundle is no longer available in this source. Choose another bundle.`,n&&(this._pendingSelection=null))}}updated(e){(e.has(`source`)||e.has(`selection`)||e.has(`loadBundle`))&&this._loadSelectedBundle()}async _loadSelectedBundle(){this._bundleController?.abort(),this._loadingBundle=!1,this._bundleError=null;let e=this._bundle;if(!this.loadBundle||!e||Array.isArray(e.files))return;let t=this._bundleController=new AbortController;this._loadingBundle=!0;try{let n=await this.loadBundle(e,t.signal);if(t.signal.aborted)return;this._bundles=this._bundles.map(t=>t.id===e.id?{...n,repoId:t.repoId,repo:t.repo}:t),this._reason=n.reasons?.[0]?.id??``}catch(e){t.signal.aborted||(this._bundleError=String(e?.message??e))}finally{t.signal.aborted||(this._loadingBundle=!1)}}disconnectedCallback(){super.disconnectedCallback(),this._bundleController?.abort();for(let e of this._timers)clearTimeout(e);this._timers.clear()}get _repoBundles(){return this._bundles.filter(e=>e.repoId===this._selectedRepoId)}get _bundle(){return this._repoBundles.find(e=>e.id===this._selectedBundleId)}get _reasonData(){return this._bundle?.reasons.find(e=>e.id===this._reason)??this._bundle?.reasons[0]}_packageLabel(e){return e===`__own__`?`Own code`:e}get _scopeFiles(){let e=this._reasonData,t=e?.fileModules,n=e?.filePaths?new Set(e.filePaths):null;return(this._bundle?.files??[]).filter(e=>(t==null||t.includes(e.module))&&(n==null||n.has(e.path))).toSorted((e,t)=>t.bytes-e.bytes)}get _files(){return E(this._scopeFiles)}render(){return P`<div class="wrap">${this.hideHeading?P`<h1 class="sr-only">Scans</h1>`:P`<div class="head"><div class="head-title"><slot name="navigation"></slot><h1>Scans</h1></div></div>`}<div class="intro-row"><p class="intro">${this._tab===`history`?`Review past scans and save completed results as reports.`:this._mode===`report`?`Choose inputs and start a scan. Save the report when it finishes.`:`Choose a bundle and start a scan. Save the report when it finishes.`}</p><div class="head-tabs" role="tablist" aria-label="Scan views"><button class="${this._tab===`new`?`active`:``}" role="tab" aria-selected="${this._tab===`new`}" @click="${()=>{this._tab=`new`}}">New scan</button> <button class="${this._tab===`history`?`active`:``}" role="tab" aria-selected="${this._tab===`history`}" @click="${()=>{this._tab=`history`}}">Scan history</button></div></div>${this._notice?P`<p class="notice" role="status">${this._notice}</p>`:F} ${this._bundleError?P`<p class="notice" role="alert">Couldn’t load bundle: ${this._bundleError}<button @click="${()=>{this._loadSelectedBundle()}}">Retry</button></p>`:F} ${this._tab===`new`?this._newScan():this._history()}</div>`}_newScan(){let e=this._mode,t=this._bundle,n=e===`code`?this._files:e===`dependencies`?this._scopeFiles:t?.files??[],r=this._excluded,i=this._excludedModules,a=n.filter(e=>!r.has(e.path)&&!i.has(e.module)),o=w(t?.files?a:null),s=new Map;for(let e of n){let t=s.get(e.module)??{bytes:0,count:0,included:0};t.bytes+=e.bytes,t.count++,r.has(e.path)||t.included++,s.set(e.module,t)}let c=[...s.keys()].toSorted((e,t)=>s.get(t).bytes-s.get(e).bytes||this._packageLabel(e).localeCompare(this._packageLabel(t))),l=n.slice(0,80),u=c.filter(e=>!i.has(e)).length,d=this._reportInput?.mode===this._reportMode?this._reportInput.inputs:[];return P`<div class="setup"><scan-mode-selector .mode="${e}" .analyzer="${this._options.analyzer}" .reportMode="${this._reportMode}" @scan-mode-change="${e=>this._changeMode(e.detail.mode)}" @scan-analyzer-change="${e=>this._setOption(`analyzer`,e.detail.analyzer)}" @scan-report-mode-change="${e=>{this._reportMode=e.detail.mode,this._reportRestore=null}}"></scan-mode-selector>${e===`report`?P`<scan-report-inputs .mode="${this._reportMode}" .loadSources="${this.loadReportSources}" .restore="${this._reportRestore}" @report-inputs-change="${e=>{this._reportInput=e.detail}}"></scan-report-inputs>`:this._sourcePanel(t,n)} ${e===`code`?P`<details class="panel scope-panel"><summary class="scope-head"><svg class="scope-chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m6 3 5 5-5 5"/></svg><h2>Source filter</h2><p><span>${a.length} of ${n.length} files · ${u} of ${c.length} packages</span> <span>${C(o.bytes)} · ${o.lines==null?`—`:o.lines.toLocaleString()} LoC</span></p></summary><div class="scope-grid"><section class="scope-pane package-pane" aria-label="Packages in bundle"><div class="pane-head"><strong>Packages</strong><span>${c.length} total · sorted by size</span></div><div class="package-list">${c.map(e=>{let{bytes:t,count:n,included:r}=s.get(e),a=!i.has(e);return P`<label class="${`package-row ${a?``:`excluded`}`}"><input type="checkbox" .checked="${a}" @change="${t=>this._toggleModule(e)}"><span class="package-name" data-tooltip-truncated data-tooltip="${this._packageLabel(e)}">${this._packageLabel(e)}</span><span class="package-size">${C(t)} · ${r}/${n}</span></label>`})}</div></section><section class="scope-pane file-panel" aria-label="Largest files in bundle"><div class="pane-head"><strong>Largest files</strong><span>showing ${l.length} of ${n.length}</span></div>${n.length===0?P`<p class="empty">No files in this selection.</p>`:P`<div class="file-list">${l.map(e=>{let t=!r.has(e.path)&&!i.has(e.module);return P`<label class="${`file ${t?``:`excluded`}`}"><input type="checkbox" .checked="${t}" @change="${t=>this._toggleFile(e,t.target.checked)}"><span class="file-copy"><span class="file-path" data-tooltip-truncated data-tooltip="${e.path}">${e.path}</span><span class="file-meta">${e.size} · ${this._packageLabel(e.module)}</span></span></label>`})}</div>`}</section></div></details>`:F} ${e===`agentic`?this._agenticPanel():F}<slot name="access"></slot>${this._optionsPanel(e,t,e===`report`?d.length:a.length)}</div>`}_sourcePanel(e,t){if(this.sourceLoading)return P`<section class="panel source-panel" aria-busy="true"><div class="panel-head"><h2>Source</h2></div><p class="empty" role="status">Loading scan sources…</p></section>`;let n=this._mode===`code`?this._repoBundles.map(e=>e.files?{...e,files:E(e.files)}:e.summary?{...e,summary:{...e.summary,files:e.summary.codeFiles}}:e):this._repoBundles,r=T(e,t,this._mode),i=new Map;for(let e of this._bundles)i.set(e.repoId,(i.get(e.repoId)??0)+1);let a=this._repositories.length>1,o=[`code`,`agentic`,`dependencies`].includes(this._mode)&&e!=null&&(!e.filename.toLowerCase().endsWith(`.map`)||e.reasons?.some(e=>e.id!==`all`)),s=this._repositories.map(e=>{let t=i.get(e.id)??0;return{value:e.id,label:e.label,detail:`${t} ${t===1?`bundle`:`bundles`}`,special:e.id===`unattached`}});return P`<section class="panel source-panel" aria-busy="${this._loadingBundle}"><div class="panel-head"><h2>Source</h2></div><div class="${`source-choice ${a?``:`single-repository`}`}">${a?P`<div class="field"><span>${this.scopeLabel}</span>${this.scopeLabel===`Workspace`?P`<workspace-selector .options="${s}" .value="${this._selectedRepoId}" @workspace-change="${e=>this._selectRepoById(e.detail.value)}"></workspace-selector>`:P`<repository-selector .options="${s}" .value="${this._selectedRepoId}" @repository-change="${e=>this._selectRepoById(e.detail.value)}"></repository-selector>`}</div>`:F}<div class="field">${a||this.createBundleHref?this._bundleLabel():F}${n.length>0?P`<bundle-selector .bundles="${n}" .value="${e?.id??null}" @bundle-change="${e=>this._selectBundleById(e.detail.value)}"></bundle-selector>`:this._emptyBundles()}</div><div class="source-footer"><div class="bundle-stats" aria-label="Bundle statistics"><div class="metric"><svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><ellipse cx="8" cy="4" rx="5" ry="2"/><path d="M3 4v8c0 1.1 2.2 2 5 2s5-.9 5-2V4M3 8c0 1.1 2.2 2 5 2s5-.9 5-2"/></svg><strong>${e?.size??`—`}</strong><span>bundle size</span></div><div class="metric">${X.report}<strong>${r.files??`—`}</strong><span>files</span></div><div class="metric">${X.code}<strong>${r.lines==null?`—`:r.lines.toLocaleString()}</strong><span>LoC</span></div><div class="metric">${k(oe)}<strong>${r.packages??`—`}</strong><span>packages</span></div></div>${o?P`<div class="scope-slot">${this._scopeField(e)}</div>`:F}</div></div></section>`}_bundleLabel(){let e=this.createBundleHref?.(this._selectedRepoId);return P`<div class="bundle-label"><span>Bundle</span>${e?P`<a class="create-bundle-button" href="${e}">Create a bundle</a>`:F}</div>`}_emptyBundles(){let e=this.createBundleHref?.(this._selectedRepoId);return P`<div class="choice-empty"><span>${this._bundles.length===0?`No stored bundles.`:`No stored bundles for this ${this.scopeLabel.toLowerCase()}.`}</span>${e?P`<a href="${e}">Create?</a>`:F}</div>`}_scopeField(e){if(![`code`,`agentic`,`dependencies`].includes(this._mode))return F;let t=(e?.reasons??[]).filter(e=>e.id!==`all`);return t.length===0?F:P`<bundle-scope-selector .reasons="${t}" .value="${this._reason}" label="${this._mode===`agentic`?`Choose agentic scope`:`Choose scan scope`}" @scope-change="${e=>this._changeReason(e.detail.value)}"></bundle-scope-selector>`}_optionsPanel(e,t,n){let r=e===`report`?`${n} ${this._reportMode===`merge`?`scan results`:`reports`} selected`:`${t?.filename??`No bundle selected`} \xB7 ${n} files will be analyzed`,i=e===`code`&&this._options.analyzer===`advanced`,a=!this.canRun||(e===`report`?n===0:t==null||n===0||i&&(!this._regimesReady||this._regimes.length===0));return P`<section class="panel options"><div class="options-grid">${i?P`<scan-regime-editor .loadModels="${this.loadModels}" .value="${this._regimes}" .appModel="${this._appModel}" .appModelAutomatic="${this._appModelAutomatic}" @regimes-change="${e=>{this._regimesReady=e.detail.ready,this._regimes=e.detail.value,this._appModel=e.detail.appModel,this._appModelAutomatic=e.detail.appModelAutomatic}}"></scan-regime-editor>`:P`<scan-model-picker .loadModels="${this.loadModels}" ?has-extra="${e===`code`}" .value="${this._options.model}" .effort="${this._options.effort}" @model-change="${e=>{this._options={...this._options,model:e.detail.model,effort:e.detail.effort}}}">${e===`code`?P`<scan-depth-toggle slot="effort-extra" .isolate="${this._options.isolate}" @depth-change="${e=>this._setOption(`isolate`,e.detail.isolate)}"></scan-depth-toggle>`:F}</scan-model-picker>`}</div><div class="options-footer"><slot name="before-run"></slot><button type="button" class="run" ?disabled="${a}" @click="${()=>this._runScan()}">${e===`report`?this._reportMode===`merge`?`Merge results`:`Link reports`:`Run scan`}</button><span class="summary">${r}</span></div><div class="checks"><label class="switch"><input type="checkbox" aria-describedby="${this._options.cached?`offline-help`:F}" .checked="${this._options.cached}" @change="${e=>this._setOption(`cached`,e.target.checked)}"><span class="switch-track" aria-hidden="true"></span><span>Offline</span></label>${this._options.cached?P`<small class="offline-help" id="offline-help">Cache only, no new model requests</small>`:F}</div></section>`}_history(){return P`<section class="panel history"><div class="panel-head"><h2>Scan history</h2><p>${this._scans.length} scans</p></div>${this._scans.length===0?P`<p class="empty">No scans yet.</p>`:this._scans.map(e=>this._scanRow(e))}</section>`}_scanRow(e){let t=e.status===`completed`?e.reportSaved?P`<button type="button" class="action" @click="${()=>this._deleteSavedReport(e)}">Delete saved report</button>`:P`<button type="button" class="action" @click="${()=>this._saveReport(e)}">Save report</button>`:F;return P`<div class="scan-row"><div class="scan-main"><div class="scan-title"><strong data-tooltip-truncated data-tooltip="${e.bundleName}">${e.bundleName}</strong><span class="${`status ${e.status}`}">${e.status}</span></div><span class="scan-meta">${e.reason} · ${e.files} ${e.mode===`report`?e.reportMode===`merge`?`results`:`reports`:`files`} · ${e.createdAt}${e.duration?` \xB7 ${e.duration}`:``}${e.reportSaved?` · Report saved`:e.status===`completed`?` · Report available`:``}</span></div><span class="scan-actions">${t}${e.status===`running`?P`<button type="button" class="action" @click="${()=>this._stopScan(e)}">Stop</button>`:F}${e.status===`stopped`?P`<button type="button" class="action" @click="${()=>this._restartScan(e)}">Restart as new scan</button>`:F}</span><span aria-hidden="true"></span></div>`}_selectBundle(e){this._pendingSelection=null,this._selectedRepoId=e.repoId,this._selectedBundleId=e.id,this._reason=e.reasons?.[0]?.id??``,this._excluded=new Set,this._excludedModules=new Set,this._notice=null,this._loadSelectedBundle()}_selectBundleById(e){let t=this._repoBundles.find(t=>t.id===e);t!=null&&this._selectBundle(t)}_selectRepoById(e){if(e===this._selectedRepoId||!this._repositories.some(t=>t.id===e))return;this._selectedRepoId=e,this._pendingSelection=null;let t=this._bundles.find(t=>t.repoId===e);this._selectedBundleId=t?.id??null,this._reason=t?.reasons[0]?.id??``,this._excluded=new Set,this._excludedModules=new Set,this._notice=null,this._loadSelectedBundle()}_changeMode(e){![`dependencies`,`code`,`agentic`,`report`].includes(e)||e===this._mode||(this._mode=e,this._reportInput=null,this._reportRestore=null,this._excluded=new Set,this._excludedModules=new Set,this._notice=null)}_changeReason(e){this._reason=e,this._excluded=new Set,this._excludedModules=new Set}_toggleFile(e,t){let n=new Set(this._excluded);t?n.delete(e.path):n.add(e.path),this._excluded=n}_toggleModule(e){let t=new Set(this._excludedModules);t.has(e)?t.delete(e):t.add(e),this._excludedModules=t}_setOption(e,t){this._options[e]!==t&&(e===`analyzer`&&t===`advanced`&&(this._regimesReady=!1,this._regimes.length===0&&(this._regimes=[{mode:this._options.analyzer,model:this._options.model,effort:this._options.effort,isolate:this._options.isolate}])),this._options={...this._options,[e]:t})}_agenticPanel(){return P`<section class="panel agentic-panel"><div class="panel-head"><h2>Agentic instructions</h2><button type="button" class="row-action" aria-label="Add prompt" @click="${()=>this._addPrompt()}">${U}</button></div><div class="agentic-fields">${O(this._prompts,e=>e.id,(e,t)=>P`<div class="prompt-row"><textarea aria-label="${`Prompt ${t+1}`}" rows="3" placeholder="${this._promptPlaceholder(t)}" .value="${S(e.text)}" @input="${t=>{this._prompts=this._prompts.map(n=>n.id===e.id?{...n,text:t.target.value}:n)}}"></textarea>${this._prompts.length>1?P`<button type="button" class="row-action" aria-label="${`Remove prompt ${t+1}`}" @click="${()=>this._removePrompt(e.id)}">${W}</button>`:F}</div>`)}</div></section>`}_promptPlaceholder(e){let t=[``,`second`,`third`,`fourth`,`fifth`,`sixth`,`seventh`,`eighth`,`ninth`,`tenth`][e];return t==null?`What should agent ${e+1} focus on?`:`What should the ${t?`${t} `:``}agent focus on?`}async _addPrompt(){this._prompts=[...this._prompts,{id:++this._nextPromptId,text:``}],await this.updateComplete,this.renderRoot?.querySelector(`.prompt-row:last-child textarea`)?.focus()}_removePrompt(e){this._prompts.length>1&&(this._prompts=this._prompts.filter(t=>t.id!==e))}_runScan(){if(!this.canRun)return;let e=this._mode,t=e===`code`&&this._options.analyzer===`advanced`;if(t&&(!this._regimesReady||this._regimes.length===0))return;let n=this._bundle,r=this._reportInput?.mode===this._reportMode?this._reportInput:null,i=r?.inputs??[],a=e===`code`?this._files.filter(e=>!this._excluded.has(e.path)&&!this._excludedModules.has(e.module)):e===`dependencies`?this._scopeFiles:n?.files??[];if(e===`report`&&(!r?.source||i.length===0)||e!==`report`&&(!n||a.length===0))return;let o={id:`scan-${Date.now()}`,mode:e,bundleId:e===`report`?this._reportMode===`merge`?r.source.id:null:n?.id??null,bundleName:e===`report`?r.source.label:n.filename,reason:e===`report`?this._reportMode===`merge`?`Merge scan results`:`Link saved reports`:this._reasonData?.label??`All files`,status:`running`,createdAt:`Just now`,duration:``,files:e===`report`?i.length:a.length,reportSaved:!1,cached:this._options.cached,isolate:e===`code`&&this._options.isolate,model:this._options.model,effort:this._options.effort};e!==`report`&&(o.repoId=this._selectedRepoId,o.scopeId=this._reason),e===`code`&&(o.analyzer=this._options.analyzer),t&&(o.regimes=this._regimes.map(e=>({...e})),o.appModel=this._appModel?{...this._appModel}:null,o.appModelAutomatic=this._appModelAutomatic,o.reason=`Advanced \xB7 ${o.regimes.length} regimes \xB7 ${o.reason}`,o.model=null,o.effort=null,o.isolate=!1),e===`agentic`&&(o.prompts=this._prompts.map(e=>e.text)),e===`report`&&(o.reportMode=this._reportMode,o.reportSource={...r.source},o.inputIds=i.map(e=>e.id)),this._scans=[o,...this._scans],this._tab=`history`,this._notice=`Scan started. The server will update its status as work progresses.`;let s=setTimeout(()=>{this._timers.delete(s),o.status===`running`&&(o.status=`completed`,o.duration=`2m 14s`,this._notice=`Scan completed. Its report is ready to save.`,this.requestUpdate())},2200);this._timers.add(s)}_stopScan(e){e.status===`running`&&(e.status=`stopped`,e.duration=e.duration||`stopped by user`,this._notice=`Scan stopped. It cannot continue, but you can restart it as a new scan.`,this.requestUpdate())}_restartScan(e){if(this._options={...this._options,model:e.model??this._options.model,effort:e.effort??this._options.effort,cached:e.cached??!1,isolate:e.isolate??!1,analyzer:e.analyzer??`generic`},e.mode===`report`){this._mode=`report`,this._reportMode=e.reportMode===`link`?`link`:`merge`,this._reportInput=null,this._reportRestore={mode:this._reportMode,source:e.reportSource,inputIds:e.inputIds??[]},this._tab=`new`,this._notice=`New report scan settings restored from the stopped run.`;return}let t=this._bundles.find(t=>t.id===e.bundleId&&(e.repoId==null||t.repoId===e.repoId));t&&(this._selectBundle(t),this._mode=e.mode??`dependencies`,e.mode===`agentic`&&(this._prompts=(e.prompts?.length>0?e.prompts:[``]).map(e=>({id:++this._nextPromptId,text:e}))),e.regimes?.length>0&&(this._options={...this._options,analyzer:`advanced`},this._regimes=e.regimes.map(e=>({...e})),this._appModel=e.appModel?{...e.appModel}:null,this._appModelAutomatic=e.appModelAutomatic!==!1,this._regimesReady=!1),this._reason=t.reasons.find(t=>t.label===e.reason)?.id??t.reasons[0]?.id??``,this._reason=e.scopeId??this._reason,this._tab=`new`,this._notice=`New scan settings restored from the stopped run.`)}_saveReport(e){e.reportSaved=!0,this._notice=`Report saved. You can delete it from Reports and save this completed scan again.`,this.requestUpdate()}_deleteSavedReport(e){e.reportSaved=!1,this._notice=`Saved report deleted. The completed scan can be saved again.`,this.requestUpdate()}};customElements.get(`deepview-scan-page`)||customElements.define(`deepview-scan-page`,Ce);function we(e,t=fetch,n=``){let r=new URL(e);return(e,i={})=>{let a=new URL(e.replace(/^\/+/u,``),r);if(a.origin!==r.origin)throw Error(`Scan requests must use the configured server`);let o=new Headers(i.headers);return n&&o.set(`authorization`,`Bearer ${n}`),t(a,{...i,headers:o,credentials:`omit`,redirect:`error`})}}var Z=class{constructor(e,t=()=>{},n=fetch){this.onChange=t,this.request=n,this.reset(e)}reset(e=this.server){this.server=e,this.apiKey=``,this.provider=null,this._remoteModels=!1,this._disconnect()}_previewModels(){let e=l(this.provider);this.loadModels=()=>Promise.resolve(e)}_disconnect(){this._controller?.abort(),this.connected=!1,this.managed=!1,this.loading=!1,this.error=null,this.catalogue=null,this._remoteModels||this._previewModels(),this.onChange()}get ready(){return this.connected&&!this.loading&&this.catalogue!=null}setKey(e){this.apiKey!==e&&(this.apiKey=e,this._disconnect())}setProvider(e){if(!(this.provider===e||this.managed)){if(this.provider=e,this.connected&&e)return this._load(e);this.connected&&(this._controller?.abort(),this.loading=!1,this.error=null,this.catalogue=null),this._remoteModels||this._previewModels(),this.onChange()}}connect(){if(this._disconnect(),this.server&&this.apiKey.trim())return this._load(null)}async _fetch(e,t){let n=await we(this.server,this.request,this.apiKey.trim())(`api/models${e?`?${new URLSearchParams({provider:e})}`:``}`,{headers:{accept:`application/json`},cache:`no-store`,signal:t});if(n.status===401)throw Object.assign(Error(`DeepView API key not recognized.`),{status:401});if(!n.ok)throw Error(`Scan server returned HTTP ${n.status}.`);let r=await n.json();if(r?.valid!==!0||typeof r.managed!=`boolean`)throw Error(`Invalid response from scan server.`);return{managed:r.managed,catalogue:r.managed||e?c(r):null}}async _load(e){this._controller?.abort();let t=this._controller=new AbortController;this.loading=!0,this.error=null,this.catalogue=null;let n=this._fetch(e,t.signal);this.onChange();try{let r=await n;if(t.signal.aborted)return;if(this.connected=!0,this.managed=r.managed,this.catalogue=r.catalogue,!r.managed&&!e&&this.provider)return this._load(this.provider);if(r.catalogue){let e=r.catalogue;this._remoteModels=!0,this.loadModels=()=>Promise.resolve(e)}else this._remoteModels||this._previewModels();this.loading=!1,this.onChange()}catch(n){if(t.signal.aborted)return;(!e||n.status===401)&&this._disconnect(),this.loading=!1,this.error=n instanceof TypeError?`Couldn’t reach the scan server. Check your connection and try again.`:String(n?.message??n),this.onChange()}}};function Te(e){let t=e.trim();return/^sk-ant-[A-Za-z0-9_-]*$/u.test(t)?`anthropic`:/^sk-or-v1-[A-Za-z0-9_-]*$/u.test(t)?`openrouter`:/^sk-kimi-[A-Za-z0-9_-]*$/u.test(t)?`moonshot`:/^sk-(?:proj|svcacct)-[A-Za-z0-9_-]*$/u.test(t)?`openai`:null}function Q(e){if(e?.throwIfAborted(),ne())throw new DOMException(`Local scan closed`,`AbortError`)}async function Ee(t){Q(t);let n=await u();return Q(t),e(n,d())}async function De(e,n){Q(n);let r=await f(e.integrity,{name:e.filename},{sources:!1});return Q(n),t(e,r)}async function Oe(e){Q(e);let t=await b(),r=[];for(let n of t){Q(e);let t=await ie(n);Q(e),r.push({name:n,content:t,fallbackRepo:ee(n)})}return Q(e),n(r,d())}async function $(e,t,n){let r=v(e,{duration:0});t.addEventListener(`abort`,r,{once:!0});try{return await n()}finally{t.removeEventListener(`abort`,r),r()}}var ke=class extends I{static properties={selection:{attribute:!1},_source:{state:!0},_error:{state:!0},_providerToken:{state:!0},_savedAccess:{state:!0},_savingAccess:{state:!0}};constructor(){super(),this._server=re(),this._access=new Z(this._server,()=>this.requestUpdate()),this._resetAccess(),this._source=null,this._error=null,this._loadBundle=(e,t)=>$(`Loading bundle…`,t,()=>De(e,t))}connectedCallback(){super.connectedCallback(),this._restoreAccess(),this._unsubscribeSavedAccess=_(()=>{this._savedAccess=p()}),this._loadSource()}disconnectedCallback(){super.disconnectedCallback(),this._unsubscribeSavedAccess?.(),this._controller?.abort(),this._resetAccess()}async _loadSource(){this._controller?.abort();let e=this._controller=new AbortController;this._error=null;try{this._source=await $(`Loading bundles…`,e.signal,()=>Ee(e.signal))}catch(t){e.signal.aborted||(this._error=String(t?.message??t))}}_resetAccess(){this._access.reset(this._server),this._providerToken=``}_restoreAccess(){this._savedAccess=p();let e=m(this._server);e&&(this._access.setKey(e.deepview),this._access.setProvider(e.provider),this._providerToken=e.token,this._access.connect())}async _saveOrForgetAccess(){if(this._savingAccess)return;let e=p();if(e||this._access.connected){this._savingAccess=!0;try{e?(await g(),this._resetAccess()):await h({server:this._server,deepview:this._access.apiKey,provider:this._access.provider,token:this._providerToken}),this._savedAccess=p()}catch{v(e?`Couldn’t forget scan credentials. Try again.`:`Couldn’t save scan credentials. Try again.`,{kind:`warning`})}finally{this._savingAccess=!1}}}_connect(e){e.preventDefault(),this._access.connect()}_setProvider(e){this._access.provider!==e&&(this._access.setProvider(e),this._providerToken=``)}_setProviderToken(e){this._providerToken=e;let t=Te(e);t&&this._access.setProvider(t)}setScanServer(e){this._server!==e&&(this._server=e,this._resetAccess(),this._restoreAccess())}static styles=N`:host{display:block}*{box-sizing:border-box}button{display:inline-flex;align-items:center;gap:.35rem;padding:.25rem .5rem;color:var(--muted);background:transparent;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);font:inherit;font-size:.8rem;cursor:default}button:hover:not(:disabled){color:var(--text);background:var(--surface)}button:disabled{opacity:.5}.access{min-width:0;border:1px solid var(--border);border-radius:var(--ui-radius, 9px);background:var(--surface);container:scan-access / inline-size}.access-heading{display:flex;align-items:center;justify-content:space-between;min-height:2.5rem;padding:.45rem .9rem;border-bottom:1px solid var(--border)}.access h2{margin:0;color:var(--text);font-size:.86rem;font-weight:600}.save-access{min-height:1.6rem;margin-left:auto;flex-shrink:0}.access-fields{display:grid;gap:.8rem;padding:.85rem .9rem}.connection-row,.provider-row{display:grid;align-items:end;gap:.65rem;margin:0}.connection-row{grid-template-columns:minmax(0,1fr) auto;width:min(42rem,100%)}.provider-row{grid-template-columns:max-content minmax(0,1fr);width:100%}.access label{display:grid;gap:.3rem;min-width:0;color:var(--muted);font-size:.72rem}input{min-width:0;width:100%;height:2rem;padding:.35rem .55rem;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg);color:var(--text);font:inherit;font-size:.8rem}.provider-field{min-width:0;margin:0;padding:0;border:0}.provider-field legend{margin-bottom:.3rem;padding:0;color:var(--muted);font-size:.72rem}.provider-options{display:flex;width:fit-content;max-width:100%;border:1px solid var(--border);border-radius:var(--ui-radius, 5px);background:var(--bg);overflow:hidden}.access .provider-choice{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:.35rem;height:calc(2rem - 2px);padding:.3rem .6rem;color:var(--muted);font-size:.74rem;white-space:nowrap;user-select:none}.provider-choice+.provider-choice{border-left:1px solid var(--border)}.provider-choice:hover{color:var(--text);background:var(--surface)}.provider-choice:has(:checked){color:var(--text);background:var(--surface-active)}.provider-choice:has(:focus-visible){outline:2px solid var(--accent);outline-offset:-2px}.provider-choice input{position:absolute;inset:0;margin:0;width:100%;height:100%;opacity:0;cursor:default}.provider-icon{display:block;width:1rem;height:1rem;flex:0 0 1rem}.provider-icon svg{display:block;width:100%;height:100%}.provider-icon.anthropic{color:#d97757}.provider-icon.openai{color:#10a37f}.provider-icon.moonshot{color:#8068d9}.provider-icon.moonshot svg{transform:scale(.8)}.provider-icon.openrouter{color:var(--text)}.connect{justify-content:center;height:2rem;padding:.35rem .8rem;color:var(--text);background:var(--surface-active)}.connection-status{flex:1;min-width:0;margin:0 .7rem;line-height:1rem;color:var(--muted);font-size:.7rem}.connection-status.error{color:var(--critical, #e5534b)}button:focus-visible,input:focus-visible{outline:2px solid var(--accent);outline-offset:2px}@container scan-access (max-width: 38rem){.provider-row{grid-template-columns:minmax(0,1fr)}}@container scan-access (max-width: 28rem){.provider-options{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));width:100%}.provider-choice:nth-child(odd){border-left:0}.provider-choice:nth-child(n+3){border-top:1px solid var(--border)}}@container scan-access (max-width: 23rem){.access .provider-choice{gap:.25rem;padding-inline:.4rem;font-size:.7rem}}`;_accessPanel(){let e=this._access,t=e.catalogue?.models.length??0,n=e.error??(e.loading?e.connected?`Loading provider models…`:`Connecting…`:e.connected?e.catalogue?`Connected \xB7 ${t} ${t===1?`model`:`models`}`:`Connected. Choose a provider.`:``);return P`<section slot="access" class="access" aria-labelledby="scan-access-heading"><div class="access-heading"><h2 id="scan-access-heading">Access</h2><p class="${`connection-status ${e.error?`error`:``}`}" role="${e.error?`alert`:`status`}">${n}</p>${this._savedAccess||e.connected?P`<button class="save-access" type="button" ?disabled="${this._savingAccess}" @click="${this._saveOrForgetAccess}">${this._savedAccess?`Forget`:`Save`}</button>`:F}</div><div class="access-fields"><form class="connection-row" @submit="${this._connect}"><label>DeepView API Key<input type="password" name="deepview-api-key" placeholder="Enter API key" autocomplete="off" spellcheck="false" .value="${e.apiKey}" @input="${t=>e.setKey(t.target.value)}"></label> <button type="submit" class="connect" ?disabled="${!e.apiKey.trim()||e.loading||e.connected&&!e.error}">${e.connected&&!e.error?`Connected`:`Connect`}</button></form>${e.managed?F:P`<div class="provider-row"><fieldset class="provider-field"><legend>Provider</legend><div class="provider-options">${[[`anthropic`,`Anthropic`],[`openai`,`OpenAI`],[`moonshot`,`Moonshot`],[`openrouter`,`OpenRouter`]].map(([t,n])=>P`<label class="provider-choice"><input type="radio" name="scan-provider" value="${t}" .checked="${e.provider===t}" @change="${()=>this._setProvider(t)}"><span class="${`provider-icon ${t}`}" aria-hidden="true">${y(t)}</span><span>${n}</span></label>`)}</div></fieldset><label>Token<input type="password" name="provider-token" placeholder="Enter provider token" autocomplete="off" spellcheck="false" .value="${this._providerToken}" @input="${e=>this._setProviderToken(e.target.value)}"></label></div>`}</div></section>`}render(){return P`${this._error?P`<p role="alert">Couldn’t load saved bundles: ${this._error} <button @click="${()=>{this._loadSource()}}">Retry</button></p>`:F}<deepview-scan-page .selection="${this.selection}" scope-label="Workspace" .source="${this._source}" .sourceLoading="${this._source==null&&!this._error}" .loadBundle="${this._loadBundle}" .loadModels="${this._access.loadModels}" .canRun="${this._access.ready}" .loadReportSources="${Oe}"><button slot="navigation" type="button" @click="${()=>{te()}}"><span aria-hidden="true">‹</span> Home</button>${this._accessPanel()}</deepview-scan-page>`}};customElements.get(`local-scan-page`)||customElements.define(`local-scan-page`,ke);