@preventive/triage 1.0.0-alpha.51 → 1.0.0-alpha.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/common/managed/finding-detail.d.ts +4 -2
- package/common/managed/finding-detail.js +29 -20
- package/common/managed/finding-values.d.ts +2 -0
- package/common/managed/finding-values.js +44 -0
- package/common/managed/lite-name.d.ts +2 -0
- package/common/managed/lite-name.js +20 -0
- package/common/managed/team-app.d.ts +2 -0
- package/common/managed/team-app.js +32 -3
- package/common/workspace-app.js +26 -6
- package/out/activity.js +4 -4
- package/out/chunk-JEFZTVNX.js +3 -0
- package/out/chunk-LJ7XRXFU.js +52 -0
- package/out/{chunk-PBZPYIG7.js → chunk-MYGJBYYJ.js} +1 -1
- package/out/{chunk-7JBSSRD7.js → chunk-NE2UGKRJ.js} +1 -1
- package/out/chunk-TSIFIFBX.js +232 -0
- package/out/{chunk-WRAJVD35.js → chunk-YA4ETCFU.js} +1 -1
- package/out/client-managed.js +26 -26
- package/out/compare.js +5 -5
- package/out/dialogs.js +41 -41
- package/out/index.html +3 -3
- package/out/scan.js +2 -2
- package/out/view.js +11 -11
- package/package.json +7 -1
- package/server-managed/github-requests.ts +54 -24
- package/server-managed/history-windows.ts +172 -0
- package/server-managed/http.ts +192 -62
- package/server-managed/npm-kept.ts +4 -0
- package/server-managed/repository-history.ts +2 -2
- package/server-managed/repository-pulse.ts +15 -4
- package/server-managed/repository-stamp.ts +41 -0
- package/server-managed/team-app.ts +3 -1
- package/server-managed/team-reports.ts +21 -13
- package/out/chunk-6LNQTKAV.js +0 -52
- package/out/chunk-IPAH4LKF.js +0 -232
- package/out/chunk-VDRXHIHN.js +0 -3
package/out/index.html
CHANGED
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
<link rel="preload" href="./view.css" as="style" />
|
|
32
32
|
<link rel="modulepreload" href="./view.js" />
|
|
33
33
|
<link rel="modulepreload" href="./chunk-R3NZFXVR.js" />
|
|
34
|
-
<link rel="modulepreload" href="./chunk-
|
|
35
|
-
<link rel="modulepreload" href="./chunk-
|
|
34
|
+
<link rel="modulepreload" href="./chunk-NE2UGKRJ.js" />
|
|
35
|
+
<link rel="modulepreload" href="./chunk-TSIFIFBX.js" />
|
|
36
36
|
<link rel="modulepreload" href="./chunk-JCIIBLKR.js" />
|
|
37
37
|
<link rel="modulepreload" href="./chunk-VH4XMZIW.js" />
|
|
38
38
|
<link rel="modulepreload" href="./chunk-KOGNQDSJ.js" />
|
|
39
|
-
<link rel="modulepreload" href="./chunk-
|
|
39
|
+
<link rel="modulepreload" href="./chunk-LJ7XRXFU.js" />
|
|
40
40
|
<link rel="modulepreload" href="./chunk-7VAWINQF.js" />
|
|
41
41
|
<link rel="modulepreload" href="./chunk-NRPC74AM.js" />
|
|
42
42
|
<link rel="modulepreload" href="./chunk-7BKKYVWR.js" />
|
package/out/scan.js
CHANGED
|
@@ -1,2 +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-PBZPYIG7.js";import{a as l}from"./chunk-QB4CBOX2.js";import{$ as u,B as d,L as f,X as p,Y as m,Z as h,_ as g,fe as _,qa as v,sf as y,u as ee,we as te,x as ne,xe as re,y as b,z as ie}from"./chunk-IPAH4LKF.js";import"./chunk-JCIIBLKR.js";import"./chunk-VH4XMZIW.js";import"./chunk-KOGNQDSJ.js";import{Ja as ae,_ as x,i as S}from"./chunk-6LNQTKAV.js";import"./chunk-7VAWINQF.js";import"./chunk-NRPC74AM.js";import"./chunk-7BKKYVWR.js";import"./chunk-7C7DWL7I.js";import"./chunk-PNHBZGDD.js";import"./chunk-FMXWXDR4.js";import"./chunk-2K6UN3PC.js";import{a as C,b as oe,c as w,d as T}from"./chunk-WCPJDAYA.js";import"./chunk-IYPY47MC.js";import{a as E,d as D}from"./chunk-PWFUOLZK.js";import"./chunk-HT2SSA3V.js";import"./chunk-SXV2T5C4.js";import{d as O,i as k,o as A,s as j,u as M,v as se}from"./chunk-WFYLMF6Z.js";import"./chunk-C4Z6ZBXV.js";import{a as ce,b as N,c as P,g as F,j as I}from"./chunk-2XUEZHIP.js";import"./chunk-TUII34K2.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">${v(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">${v(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="${E({"--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="${E({"--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)}">${O(S[e.analyzer]??S.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} ${D(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="${x(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="${x(e.model)}" .effort="${x(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="${x(e.model)}" .effort="${x(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">${O(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:O(M),report:O(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 T(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=oe(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:T(e.files)}:e.summary?{...e,summary:{...e.summary,files:e.summary.codeFiles}}:e):this._repoBundles,r=w(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">${O(k)}<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">${D(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="${x(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 d();return Q(t),e(n,f())}async function De(e,n){Q(n);let r=await y(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,f())}async function $(e,t,n){let r=_(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=u(()=>{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{_(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">${v(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);
|
|
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-MYGJBYYJ.js";import{a as l}from"./chunk-QB4CBOX2.js";import{$ as u,B as d,L as f,X as p,Y as m,Z as h,_ as g,he as _,qa as v,u as y,uf as ee,x as te,y as ne,ye as re,z as b,ze as ie}from"./chunk-TSIFIFBX.js";import"./chunk-JCIIBLKR.js";import"./chunk-VH4XMZIW.js";import"./chunk-KOGNQDSJ.js";import{Ja as ae,_ as x,i as S}from"./chunk-LJ7XRXFU.js";import"./chunk-7VAWINQF.js";import"./chunk-NRPC74AM.js";import"./chunk-7BKKYVWR.js";import"./chunk-7C7DWL7I.js";import"./chunk-PNHBZGDD.js";import"./chunk-FMXWXDR4.js";import"./chunk-2K6UN3PC.js";import{a as C,b as oe,c as w,d as T}from"./chunk-WCPJDAYA.js";import"./chunk-IYPY47MC.js";import{a as E,d as D}from"./chunk-PWFUOLZK.js";import"./chunk-HT2SSA3V.js";import"./chunk-SXV2T5C4.js";import{d as O,i as k,o as A,s as j,u as M,v as se}from"./chunk-WFYLMF6Z.js";import"./chunk-C4Z6ZBXV.js";import{a as ce,b as N,c as P,g as F,j as I}from"./chunk-2XUEZHIP.js";import"./chunk-TUII34K2.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">${v(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">${v(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="${E({"--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="${E({"--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)}">${O(S[e.analyzer]??S.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} ${D(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="${x(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="${x(e.model)}" .effort="${x(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="${x(e.model)}" .effort="${x(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">${O(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:O(M),report:O(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 T(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=oe(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:T(e.files)}:e.summary?{...e,summary:{...e.summary,files:e.summary.codeFiles}}:e):this._repoBundles,r=w(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">${O(k)}<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">${D(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="${x(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(),te())throw new DOMException(`Local scan closed`,`AbortError`)}async function Ee(t){Q(t);let n=await d();return Q(t),e(n,f())}async function De(e,n){Q(n);let r=await ee(e.integrity,{name:e.filename},{sources:!1});return Q(n),t(e,r)}async function Oe(e){Q(e);let t=await ne(),r=[];for(let n of t){Q(e);let t=await b(n);Q(e),r.push({name:n,content:t,fallbackRepo:y(n)})}return Q(e),n(r,f())}async function $(e,t,n){let r=_(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=ie(),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=u(()=>{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{_(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">${v(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="${()=>{re()}}"><span aria-hidden="true">‹</span> Home</button>${this._accessPanel()}</deepview-scan-page>`}};customElements.get(`local-scan-page`)||customElements.define(`local-scan-page`,ke);
|