@viberaven/cli 1.5.1 → 1.5.3

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/dist/stack/app.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";(()=>{function ze(e=document){return e.querySelector('meta[name="viberaven-token"]')?.content??""}async function T(e,i){let n=await fetch(e,{...i,credentials:"same-origin",headers:{"content-type":"application/json","x-viberaven-token":ze(),...i?.headers??{}}}),r=await n.text(),a=null;try{a=r?JSON.parse(r):null}catch{a={error:r}}if(!n.ok){let c=a?.error??a?.message??r??`HTTP ${n.status}`;throw new Error(String(c))}return a}var I=(e,i)=>T(e,{method:"POST",body:JSON.stringify(i)}),b={project:()=>T("/api/project"),scan:()=>I("/api/scan",{}),scanStatus:()=>T("/api/scan-status"),agents:()=>T("/api/cli-agents"),probe:e=>I("/api/cli-agents/probe",{cliId:e}),runSetup:(e,i)=>I("/api/cli-agents/run-setup",{cliId:e,step:i}),openTerminal:(e,i)=>I("/api/cli-agents/open-terminal",{cliId:e,step:i}),chat:e=>I("/api/agent-chat",e),catalog:()=>T("/api/provider-catalog"),verified:()=>T("/api/provider-verify"),stop:e=>I("/api/agent-chat/stop",{runId:e}),verify:e=>I("/api/provider-verify",e),connectMcp:e=>I("/api/mcp/connect",{providerId:e}),compare:(e,i)=>T(`/api/releases/compare?from=${encodeURIComponent(e)}&to=${encodeURIComponent(i)}`),fullCheckStatus:()=>T("/api/fullcheck/status"),fullCheckSignInStart:()=>I("/api/fullcheck/signin/start",{}),fullCheckSignInPoll:()=>I("/api/fullcheck/signin/poll",{}),fullCheckSignOut:()=>I("/api/fullcheck/signout",{}),fullCheckPrepare:()=>I("/api/fullcheck/prepare",{}),fullCheckRun:e=>I("/api/fullcheck/run",{previewId:e}),changelog:(e,i)=>T(`/api/releases/changelog?from=${encodeURIComponent(e)}&to=${encodeURIComponent(i)}`)};function t(e,i,...n){let r=document.createElement(e);if(i){for(let[a,c]of Object.entries(i))if(!(c==null||c===!1))if(a==="class")r.className=String(c);else if(a==="on")for(let[u,o]of Object.entries(c))r.addEventListener(u,o);else if(a==="dataset")for(let[u,o]of Object.entries(c))r.dataset[u]=o;else a==="html"?r.innerHTML=String(c):a==="style"&&typeof c=="object"?Object.assign(r.style,c):a in r&&typeof c!="string"?r[a]=c:r.setAttribute(a,String(c))}return oe(r,n),r}function oe(e,i){for(let n of i)n==null||n===!1||(Array.isArray(n)?oe(e,n):n instanceof Node?e.appendChild(n):e.appendChild(document.createTextNode(String(n))))}function Y(e){return e.replace(/[&<>"']/g,i=>({"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;"})[i])}function H(e){let n=Y(e.replace(/\r\n/g,`
2
2
  `)).split(/```/),r="";return n.forEach((a,c)=>{if(c%2===1){let p=a.replace(/^[a-z0-9-]*\n/i,"");r+=`<pre><code>${p}</code></pre>`;return}let u=a.split(`
3
3
  `),o=null;for(let p of u){let s=p.trimEnd(),l=/^\s*[-*•]\s+(.*)$/.exec(s),d=/^\s*\d+[.)]\s+(.*)$/.exec(s),f=/^(#{1,3})\s+(.*)$/.exec(s),y=l?"ul":d?"ol":null;o&&y!==o&&(r+=`</${o}>`,o=null),y&&!o&&(r+=`<${y}>`,o=y),l||d?r+=`<li>${X((l??d)[1])}</li>`:f?r+=`<h4>${X(f[2])}</h4>`:s.trim()&&(r+=`<p>${X(s)}</p>`)}o&&(r+=`</${o}>`)}),r}function X(e){return e.replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>").replace(/`([^`]+)`/g,"<code>$1</code>")}function D(e){let i=Date.now()-new Date(e).getTime();if(!Number.isFinite(i)||i<0)return"just now";let n=Math.round(i/6e4);if(n<1)return"just now";if(n<60)return`${n} min ago`;let r=Math.round(n/60);return r<24?`${r} h ago`:`${Math.round(r/24)} d ago`}function Q(){return{step:"closed",status:null,signIn:null,preview:null,result:null,limit:null,error:null,notice:null}}var Pe=new Set(["network","timeout","server","rate_limited","busy"]);function ce(e,i={}){let n=i.wait??(g=>new Promise(m=>window.setTimeout(m,g))),r=0,a=()=>e.get().fullCheck,c=g=>e.set(m=>({fullCheck:{...m.fullCheck,...g}})),u=g=>g===r&&a().step!=="closed";async function o(g){try{return await g()}catch(m){return{kind:"error",reason:"unexpected",message:`The Studio did not answer: ${m instanceof Error?m.message:String(m)}`}}}async function p(){try{let g=await b.fullCheckStatus();return c({status:g}),g}catch{return null}}async function s(g,m,M){if(u(M))switch(g.kind){case"signin":c({step:"signin",signIn:{code:g.code,verificationUrl:g.verificationUrl,expiresAt:g.expiresAt,opened:g.opened},error:null}),l(M,g.pollIntervalSeconds);return;case"signin_pending":return;case"signed_in":if(c({signIn:null,notice:g.notice??(a().preview?"Signed in again. Confirm to send the same request.":null)}),await p(),!u(M))return;a().preview?c({step:"preview"}):await f(M);return;case"signin_expired":case"signin_denied":c({step:"error",signIn:null,error:{message:g.message,retry:"signin"}});return;case"signed_out":c({...Q()}),e.toast("Signed out of VibeRaven on this computer.");return;case"signin_required":case"reauth":c({notice:g.message}),await d(M);return;case"preview":c({step:"preview",preview:g.preview,error:null});return;case"result":c({step:"result",result:g.result,preview:null,notice:null,error:null}),await p();return;case"plan_limit":c({step:"limit",preview:null,notice:null,limit:{plan:g.plan,message:g.message,pricingUrl:g.pricingUrl,usage:g.usage}}),await p();return;case"error":{let w=g.reason==="not_confirmed"||g.reason==="prepare_failed"?"prepare":g.reason==="no_signin"?"signin":m==="run"&&!Pe.has(g.reason)?"prepare":m;w==="prepare"&&m==="run"&&c({preview:null}),c({step:"error",error:{message:g.message,retry:w}});return}}}async function l(g,m){for(;u(g)&&a().step==="signin";){if(await n(Math.max(1,m)*1e3),!u(g)||a().step!=="signin")return;let M=await o(()=>b.fullCheckSignInPoll());if(M.kind!=="signin_pending"){await s(M,"signin",g);return}}}async function d(g){c({step:"loading",error:null}),await s(await o(()=>b.fullCheckSignInStart()),"signin",g)}async function f(g){c({step:"preparing",error:null,result:null,limit:null}),await s(await o(()=>b.fullCheckPrepare()),"prepare",g)}async function y(g){c({step:"loading",error:null});let m=await p();if(u(g)){if(!m){c({step:"error",error:{message:"The Studio server did not answer. Reload the page and try again.",retry:"status"}});return}m.signedIn?await f(g):await d(g)}}return{async openFullCheck(){let g=a().step;g!=="closed"&&g!=="result"&&g!=="limit"&&g!=="error"||(r+=1,c({...Q(),step:"loading",status:a().status}),await y(r))},closeFullCheck(){r+=1,c({step:"closed",signIn:null,error:null,notice:null}),document.getElementById("run-full-check")?.focus({preventScroll:!0})},async fullCheckSignIn(){await d(r)},async fullCheckConfirm(){let g=a().preview;if(!g||a().step!=="preview")return;let m=r;c({step:"running",error:null}),await s(await o(()=>b.fullCheckRun(g.id)),"run",m)},async fullCheckRetry(){let g=a().error?.retry??"status",m=r;if(g==="run"&&a().preview){c({step:"preview",error:null});return}g==="signin"?await d(m):g==="prepare"?await f(m):await y(m)},async fullCheckSignOut(){await s(await o(()=>b.fullCheckSignOut()),"status",r),await p()},async copyFullCheckPrompt(g){try{await navigator.clipboard.writeText(g),e.toast("Fix prompt copied. Paste it into your coding agent.")}catch{e.toast("Could not copy. Select the text and copy it by hand.","err")}}}}function O(e){return e?e.plan==="pro"?`${e.used} of ${e.limit} Pro full checks used this month`:`${e.used} of ${e.limit} free full checks used`:null}function de(e){return e==="pro"?"Pro plan":"Free plan"}function J(e){return e<1024?`${e} B`:`${(e/1024).toFixed(1)} KB`}function Ue(e){try{return new URL(e).host}catch{return e}}function le(e){return t("span",{class:`tag ${e==="critical"?"red":e==="warning"?"amber":"dim"}`},e==="critical"?"Critical":e==="warning"?"Important":"Nice to have")}function Fe(e,i){let n=e.status?.account;if(!n)return null;let r=O(e.status?.usage);return t("div",{class:"fc-account"},t("span",{class:"fc-avatar","aria-hidden":"true"},n.email.slice(0,1).toUpperCase()),t("span",{class:"fc-who"},`Signed in as ${n.email}`),t("span",{class:`fc-plan is-${n.plan}`},de(n.plan)),e.status?.sessionOnly?t("span",{class:"fc-dot"},"this session only"):null,r?t("span",{class:"fc-dot"},r):null,t("button",{class:"fc-link",on:{click:()=>i.fullCheckSignOut()}},"Sign out"))}function $e(e,i){let n=e.signIn;return[t("p",{class:"fc-lead"},e.notice??"Full checks run on VibeRaven, so they need your VibeRaven account. Sign in once on this computer."),t("div",{class:"fc-code"},t("span",{class:"fc-code-label"},"Your code"),t("strong",{id:"fc-code"},...n.code.split("").map(r=>t("span",{},r)))),t("p",{class:"fc-hint"},n.opened?"We opened the sign-in page in your browser. Check the code matches, then confirm it there.":"Open the sign-in page, check the code matches, then confirm it there."),t("div",{class:"fc-actions"},t("a",{class:"btn primary",href:n.verificationUrl,target:"_blank",rel:"noopener noreferrer"},"Open the sign-in page"),t("span",{class:"fc-wait",role:"status"},t("span",{class:"spin"}),"Waiting for you to confirm\u2026"),t("button",{class:"btn ghost",on:{click:()=>i.closeFullCheck()}},"Cancel"))]}function B(e,i,n,r=!1){return t("details",{class:"fc-files",open:r},t("summary",{},t("span",{},e),t("span",{class:"fc-files-count"},String(i.length))),i.length?t("ul",{},...i.map(a=>t("li",{},t("code",{},a.path),t("span",{},a.meta)))):t("p",{class:"fc-empty"},n))}function Re(e,i){let n=e.preview,r=n.promptFiles.length;return[e.notice?t("p",{class:"fc-notice",role:"status"},e.notice):null,t("div",{class:"fc-summary"},t("div",{class:"fc-summary-main"},t("span",{class:"fc-summary-size"},J(n.bytes)),t("span",{class:"fc-summary-what"},`${r} file${r===1?"":"s"} in full, plus names and snippets`)),t("p",{class:"fc-lead"},`This is exactly what gets sent to ${Ue(n.endpoint)} when you confirm. Nothing has been uploaded yet.`)),Fe(e,i),t("dl",{class:"fc-facts"},t("div",{},t("dt",{},"Project folder"),t("dd",{},t("code",{},n.workspacePath))),t("div",{},t("dt",{},"Request size"),t("dd",{},J(n.bytes))),t("div",{},t("dt",{},"SPEC.md"),t("dd",{},n.spec.included?`Included (${n.spec.chars.toLocaleString()} characters)`:"Not found, not sent")),t("div",{},t("dt",{},"Dependencies"),t("dd",{},`${n.dependencyCount} package names`)),t("div",{},t("dt",{},"File tree"),t("dd",{},`${n.fileTreeEntries} paths, names only`))),t("div",{class:"fc-filegrid"},B("Files sent in full",n.promptFiles.map(a=>({path:a.path,meta:`${a.chars.toLocaleString()} chars${a.redactions?`, ${a.redactions} redacted`:""}`})),"No file contents are sent.",!0),B("File snippets (first 200 characters)",n.snippetFiles.map(a=>({path:a.path,meta:a.heat})),"None."),B("Skipped as secret files (name sent, contents never read)",n.secretFilesNamedOnly.map(a=>({path:a,meta:"name only"})),"None found."),B("Request text by section",n.promptSections.map(a=>({path:a.title,meta:`${a.chars.toLocaleString()} chars`})),"Empty.")),t("p",{id:"fc-redaction",class:`fc-shield${n.redactions>0?" is-on":""}`},n.redactions>0?`VibeRaven replaced ${n.redactions} secret-looking value${n.redactions===1?"":"s"} with [REDACTED]. `:"VibeRaven found no secret-looking values to replace. ","This is pattern matching, not a guarantee. Other files are sent as they are, so read the exact request body below before you send it."),t("details",{class:"fc-raw"},t("summary",{},`Show the exact request body: the prompt, file snippets and SPEC.md. Shown formatted here; sent compact (${J(n.bytes)}), same content.`),t("pre",{id:"fc-request-json"},n.requestJson)),t("p",{class:"fc-hint"},"Most of the request text is written by VibeRaven on your machine from the local scan: stack notes and the check instructions."),t("div",{class:"fc-actions fc-footer"},t("button",{id:"fc-confirm",class:"btn primary",on:{click:()=>i.fullCheckConfirm()}},"Send and run full check"),t("button",{class:"btn ghost",on:{click:()=>i.closeFullCheck()}},"Cancel"))]}function Ye(e){return e<50?"fail":e<80?"warn":"pass"}function He(e,i){let n=e.result,r=n.areas.reduce((o,p)=>o+p.hiddenCount,0),a=n.nextFix,c=n.areas.filter(o=>!o.locked&&o.findings.length),u=n.areas.filter(o=>o.locked||!o.findings.length);return[t("div",{class:`fc-score is-${Ye(n.score)}`},t("div",{class:"fc-score-num",style:`--score:${Math.max(0,Math.min(100,n.score))}`},String(n.score)),t("div",{},t("div",{class:"fc-score-label"},n.scoreLabel,t("span",{class:"tag dim"},`${n.confidence} confidence`)),t("p",{},n.summary))),t("div",{class:"fc-account"},t("span",{class:`fc-plan is-${n.usage.plan}`},de(n.usage.plan)),t("span",{class:"fc-dot"},O(n.usage)),t("span",{class:"fc-dot"},`${n.usage.remaining} left${n.usage.period==="monthly"?" this month":""}`)),a?t("article",{class:`fc-next is-${a.severity}`},t("div",{class:"fix-top"},t("span",{class:"fc-eyebrow"},"Next fix"),le(a.severity),t("span",{class:"fix-meta"},a.areaTitle)),t("h3",{},a.title),a.detail?t("p",{},a.detail):null,a.prompt?t("button",{class:"btn primary sm",on:{click:()=>i.copyFullCheckPrompt(a.prompt)}},"Copy fix prompt"):null):t("p",{class:"fc-lead"},"No findings in the areas your plan covers."),t("h4",{class:"fc-h4"},"Findings by area"),c.length?t("div",{class:"fc-areas"},...c.map(o=>t("section",{class:"fc-area","aria-label":o.title},t("div",{class:"fc-area-head"},t("h5",{},o.title),t("span",{class:"fc-count on"},String(o.findings.length))),t("ul",{},...o.findings.map(p=>t("li",{},le(p.severity),t("span",{title:p.detail},p.title))))))):null,u.length?t("div",{class:"fc-quiet"},...u.map(o=>t("section",{class:`fc-chip${o.locked?" locked":""}`,"aria-label":o.title},t("span",{class:"fc-chip-mark","aria-hidden":"true"},o.locked?"":"\u2713"),t("span",{},o.title),o.locked?t("span",{class:"tag dim"},"Pro area"):t("span",{class:"fc-sr"},"No findings."),o.locked&&o.hiddenCount?t("span",{class:"fc-sr"},`${o.hiddenCount} finding${o.hiddenCount===1?"":"s"} here. Pro shows every area.`):null))):null,r&&n.usage.plan==="free"?t("p",{class:"fc-upsell"},`${r} finding${r===1?" is":"s are"} in areas Pro covers. `,t("a",{href:"https://viberaven.dev/pricing",target:"_blank",rel:"noopener noreferrer"},"See Pro")):null,t("div",{class:"fc-actions fc-footer"},t("button",{class:"btn",on:{click:()=>i.closeFullCheck()}},"Done"))]}function Be(e,i){let n=e.limit;return[t("h3",{class:"fc-limit",role:"alert"},n.message),O(n.usage)?t("p",{class:"fc-hint"},O(n.usage)):null,n.plan==="free"?t("p",{class:"fc-hint"},"The local Studio checks stay free and unlimited. Pro adds 50 full checks a month across all production areas."):t("p",{class:"fc-hint"},"The local Studio checks keep working until your monthly allowance resets."),t("div",{class:"fc-actions"},n.pricingUrl?t("a",{id:"fc-see-pro",class:"btn primary",href:n.pricingUrl,target:"_blank",rel:"noopener noreferrer"},"See Pro"):null,t("button",{class:"btn ghost",on:{click:()=>i.closeFullCheck()}},"Close"))]}function Qe(e,i){let n=e.error;return[t("p",{class:"fc-error",role:"alert"},n.message),t("div",{class:"fc-actions"},t("button",{class:"btn primary",on:{click:()=>i.fullCheckRetry()}},n.retry==="signin"?"Sign in again":"Try again"),t("button",{class:"btn ghost",on:{click:()=>i.closeFullCheck()}},"Close"))]}function _(e){return t("p",{class:"fc-wait",role:"status"},t("span",{class:"spin"}),e)}var Ge={closed:"",loading:"Full check",signin:"Sign in to run a full check",preparing:"Full check",preview:"Review what gets sent",running:"Running the full check",result:"Full check result",limit:"Full check limit reached",error:"Full check did not run"};function ue(e,i){let n=e.fullCheck;if(n.step==="closed")return[];let r=n.step==="signin"&&n.signIn?$e(n,i):n.step==="preview"&&n.preview?Re(n,i):n.step==="result"&&n.result?He(n,i):n.step==="limit"&&n.limit?Be(n,i):n.step==="error"&&n.error?Qe(n,i):n.step==="preparing"?[_("Reading your project to build the request\u2026")]:n.step==="running"?[_("Sent. VibeRaven is checking your app\u2026")]:[_("Checking your VibeRaven sign-in\u2026")],a=n.step!=="running";return[t("div",{class:"fc-veil",on:{click:()=>{a&&i.closeFullCheck()}}}),t("section",{id:"full-check",class:"fc-sheet",role:"dialog","aria-modal":"true","aria-labelledby":"fc-title"},t("header",{class:"fc-head"},t("h2",{id:"fc-title"},Ge[n.step]),a?t("button",{class:"btn ghost sm","aria-label":"Close full check",on:{click:()=>i.closeFullCheck()}},"Close"):null),t("div",{class:"fc-body"},...r))]}var pe="viberaven.stack.";function F(e,i,n=localStorage){try{let r=n.getItem(pe+e);return r?JSON.parse(r):i}catch{return i}}function $(e,i,n=localStorage){try{n.setItem(pe+e,JSON.stringify(i))}catch{}}function Ze(e){return!e.empty&&!!e.project?.scannedAt?(e.missionCards?.blockers??[]).length?"findings":"ready":"app"}function ge(e){let i=`chat.${e.project?.path??"project"}`,n=`checklist.${e.project?.path??"project"}`,r={project:e,catalog:[],verified:{},agents:[],probes:{},cliId:F("cliId","codex"),accessMode:F("accessMode","approve"),modelId:F("modelId",""),messages:F(i,[],sessionStorage),draft:"",contextProviderId:null,busy:{chat:!1,scan:!1,probe:null,tile:null,compare:!1},terminalOutput:"",compare:{from:"",to:"HEAD",result:null,error:null},drawer:null,section:"stack",agentOpen:!1,moreOpen:!1,showAll:!1,setup:{open:!1,initialized:!1,selected:[],running:!1,progress:[],error:null},scan:null,toasts:[],workingSince:null,runId:null,fullCheck:Q(),flow:{step:Ze(e),fixId:null,handoff:null,recheck:null,checklist:F(n,{})}},a=new Set,c=0,u={get:()=>r,set(o){let p=typeof o=="function"?o(r):o;r={...r,...p},"cliId"in p&&$("cliId",r.cliId),"accessMode"in p&&$("accessMode",r.accessMode),"modelId"in p&&$("modelId",r.modelId),"messages"in p&&$(i,r.messages.slice(-60),sessionStorage),"flow"in p&&$(n,r.flow.checklist);for(let s of a)s(r)},flow(o){u.set(p=>({flow:{...p.flow,...o}}))},subscribe(o){return a.add(o),()=>a.delete(o)},toast(o,p="ok"){let s=++c;u.set(l=>({toasts:[...l.toasts,{id:s,text:o,kind:p}]})),window.setTimeout(()=>u.set(l=>({toasts:l.toasts.filter(d=>d.id!==s)})),p==="err"?7e3:3600)},push(o){let p={...o,id:`${Date.now()}-${Math.random().toString(36).slice(2,7)}`,at:new Date().toISOString()};return u.set(s=>({messages:[...s.messages,p]})),p}};return u}var fe=["sentry","stripe","clerk","cloudflare","render","railway","neon","posthog","upstash","resend","authjs"];function Ve(e){return e?e.launchPath.filter(n=>n.state==="needs_fix"||n.state==="needs_connect"||n.state==="requires_user_action"||n.state==="blocked").length||(e.nextFix?1:0):0}function z(e,i,n){let r=new Map(e.providers.map(s=>[s.id,s])),a=new Set,c=[],u=(s,l)=>{let d=s?.id??l.id;if(a.has(d))return;a.add(d);let f=!!s?.detected||!!(l&&l.state!=="not_detected"),y=!!s?.mcpConfigured||l?.mcp?.status==="connected",g=n[d],m=f?Ve(l):0,M="absent",w="Not in this app";f&&(M="in_repo",w=y?"MCP configured \xB7 not verified live":"In repo \xB7 MCP not set up",y&&(M="mcp"),g&&(M=g.ok&&m===0?"ready":"verified",w=g.ok?"Verified live":"Verified live \xB7 issues found")),c.push({id:d,name:s?.name??l.name,area:s?.area??l.area,logoUrl:s?.logoUrl??We(l?.iconHtml??""),step:M,statusText:w,fixes:m,hasRecipe:!!s?.hasRecipe||l?.mcp?.available===!0,mcpConfigured:y,note:s?.note,mcpSource:s?.mcpSource??l?.mcp?.source,verified:g,provider:l})};for(let s of i)u(s,r.get(s.id));for(let s of e.providers)u(null,s);let o=s=>s.step==="absent"?s.hasRecipe?1:2:0,p=s=>{let l=fe.indexOf(s.id);return l===-1?fe.length:l};return c.sort((s,l)=>o(s)-o(l)||l.fixes-s.fixes||p(s)-p(l)||s.name.localeCompare(l.name))}function We(e){let i=/src="([^"]+)"/.exec(e);return i?i[1]:""}function he(e,i,n){let r=e.setup,a=r.selected.length,c=e.probes[e.cliId]?.ready,u=r.running||e.busy.chat||!!e.busy.tile||e.busy.scan;return t("section",{class:"stack-setup","aria-label":"Connect my app"},t("div",{class:"setup-heading"},t("div",{},t("h2",{id:"stack-setup-heading",tabIndex:-1},"Set up your app"),t("ol",{class:"setup-steps"},t("li",{class:a?"done":""},t("i",{"aria-hidden":"true"},a?"\u2713":"1"),"Pick your services"),t("li",{class:c?"done":""},t("i",{"aria-hidden":"true"},c?"\u2713":"2"),"Connect your coding agent"),t("li",{},t("i",{"aria-hidden":"true"},"3"),e.accessMode==="ask"?"Get a plan":"Start setup"))),t("button",{class:"btn ghost sm",disabled:r.running,on:{click:()=>{i.set({setup:{...i.get().setup,open:!1}}),document.getElementById("connect-my-app")?.focus({preventScroll:!0})}}},"Close")),e.catalog.length?t("div",{class:"setup-services"},...e.catalog.map(o=>{let p=r.selected.includes(o.id);return t("button",{id:`setup-provider-${o.id}`,class:`setup-service${p?" selected":""}`,"aria-pressed":String(p),disabled:u,on:{click:()=>n.toggleSetupProvider(o.id)}},t("img",{src:o.logoUrl,alt:""}),t("span",{class:"setup-service-copy"},t("strong",{},o.name),t("small",{},o.detected?"In your app":o.area)),t("span",{class:"setup-check","aria-hidden":"true"},p?"\u2713":"+"))})):t("p",{class:"setup-note"},"Loading the service catalog\u2026"),t("div",{class:"setup-footer"},t("div",{},t("strong",{},a?c?`${a} service${a===1?"":"s"} ready to set up`:"Connect your agent to continue":"Pick at least one service"),t("p",{},e.accessMode==="ask"?"Ask mode only plans. It does not change your app.":"Your agent edits the repo. Provider sign-ins stay with you.")),r.running?t("button",{class:"btn",on:{click:()=>n.stop()}},"Stop setup"):c?t("button",{class:"btn primary",disabled:!a||u,on:{click:()=>n.startStackSetup()}},e.accessMode==="ask"?"Plan my setup":"Start setup",t("span",{"aria-hidden":"true"},"\u2197")):t("button",{class:"btn primary",disabled:e.busy.probe!==null,on:{click:()=>n.testConnection(e.cliId)}},e.busy.probe?"Testing agent\u2026":"Test agent connection")),r.progress.length?t("ol",{class:"setup-progress","aria-live":"polite"},...r.progress.map(o=>t("li",{class:o.state},t("span",{class:o.state==="working"&&r.running&&!r.error?"spin":"progress-dot","aria-hidden":"true"}),o.label))):null,r.error?t("p",{class:"setup-error",role:"alert"},r.error):null)}var qe={authjs:"data:image/webp;base64,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",clerk:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjNkM0N0ZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+Q2xlcms8L3RpdGxlPjxwYXRoIGQ9Im0yMS40NyAyMC44MjktMi44ODEtMi44ODFhLjU3Mi41NzIgMCAwIDAtLjctLjA4NCA2Ljg1NCA2Ljg1NCAwIDAgMS03LjA4MSAwIC41NzYuNTc2IDAgMCAwLS43LjA4NGwtMi44ODEgMi44ODFhLjU3Ni41NzYgMCAwIDAtLjEwMy42OS41Ny41NyAwIDAgMCAuMTY2LjE4NiAxMiAxMiAwIDAgMCAxNC4xMTMgMCAuNTguNTggMCAwIDAgLjIzOS0uNDIzLjU3Ni41NzYgMCAwIDAtLjE3Mi0uNDUzWm0uMDAyLTE3LjY2OC0yLjg4IDIuODhhLjU2OS41NjkgMCAwIDEtLjcwMS4wODRBNi44NTcgNi44NTcgMCAwIDAgOC43MjQgOC4wOGE2Ljg2MiA2Ljg2MiAwIDAgMC0xLjIyMiAzLjY5MiA2Ljg2IDYuODYgMCAwIDAgLjk3OCAzLjc2NC41NzMuNTczIDAgMCAxLS4wODMuNjk5bC0yLjg4MSAyLjg4YS41NjcuNTY3IDAgMCAxLS44NjQtLjA2M0ExMS45OTMgMTEuOTkzIDAgMCAxIDYuNzcxIDIuN2ExMS45OSAxMS45OSAwIDAgMSAxNC42MzctLjQwNS41NjYuNTY2IDAgMCAxIC4yMzIuNDE4LjU3LjU3IDAgMCAxLS4xNjguNDQ4Wm0tNy4xMTggMTIuMjYxYTMuNDI3IDMuNDI3IDAgMSAwIDAtNi44NTQgMy40MjcgMy40MjcgMCAwIDAgMCA2Ljg1NFoiLz48L3N2Zz4=",cloudflare:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRjM4MDIwIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+Q2xvdWRmbGFyZTwvdGl0bGU+PHBhdGggZD0iTTE2LjUwODggMTYuODQ0N2MuMTQ3NS0uNTA2OC4wOTA4LS45NzA3LS4xNTUzLTEuMzE1NC0uMjI0Ni0uMzE2NC0uNjA0NS0uNDk5LTEuMDYxNS0uNTIwNWwtOC42NTkyLS4xMTIzYS4xNTU5LjE1NTkgMCAwIDEtLjEzMzMtLjA3MTNjLS4wMjgzLS4wNDItLjAzNTEtLjA5ODYtLjAyMS0uMTU1My4wMjc4LS4wODQuMTEyMy0uMTQ4NC4yMDM2LS4xNTYybDguNzM1OS0uMTEyM2MxLjAzNTEtLjA0ODkgMi4xNjAxLS44ODY4IDIuNTUzNy0xLjkxMzZsLjQ5OS0xLjMwMTNjLjAyMTUtLjA1NjEuMDI5My0uMTEyOC4wMTQ3LS4xNjgtLjU2MjUtMi41NDYzLTIuODM1LTQuNDQ1My01LjU0OTktNC40NDUzLTIuNTAzOSAwLTQuNjI4NCAxLjYxNzctNS4zODc2IDMuODYxNC0uNDkyNy0uMzY1OC0xLjExODctLjU2MjUtMS43OTQtLjQ5OS0xLjIwMjYuMTE5LTIuMTY2NSAxLjA4My0yLjI4NjEgMi4yODU2LS4wMjgzLjMxLS4wMDY5LjYxMjguMDYzNS44OTRDMS41NjgzIDEzLjE3MSAwIDE0Ljc3NTQgMCAxNi43NTJjMCAuMTc0OC4wMTQyLjM1MTUuMDM1Mi41MjczLjAxNDEuMDgzLjA4NDQuMTQ3NS4xNjg5LjE0NzVoMTUuOTgxNGMuMDkwOSAwIC4xNzU4LS4wNjQ1LjIwMzItLjE1NTNsLjEyLS40MjY4em0yLjc1NjgtNS41NjM0Yy0uMDc3MSAwLS4xNjExIDAtLjIzODMuMDExMi0uMDU2NiAwLS4xMDU0LjA0MTUtLjEyNy4wOTc2bC0uMzM3OCAxLjE3NDRjLS4xNDc1LjUwNjgtLjA5MTguOTcwNy4xNTQzIDEuMzE2NC4yMjU2LjMxNjQuNjA1NS40OTggMS4wNjI1LjUxOTVsMS44NDM3LjExMzNjLjA1NTcgMCAuMTA1NS4wMjYzLjEzMjkuMDcwMy4wMjgzLjA0My4wMzUxLjEwNzQuMDIxNC4xNTYyLS4wMjgzLjA4NC0uMTEzMi4xNDg1LS4yMDQuMTU1M2wtMS45MjEuMTEyM2MtMS4wNDEuMDQ4OC0yLjE1ODIuODg2Ny0yLjU1MjcgMS45MTRsLS4xNDA2LjM1ODVjLS4wMjgzLjA3MTMuMDIxNS4xNDE2LjA5ODYuMTQxNmg2LjU5NzdjLjA3NzEgMCAuMTQ3NC0uMDQ4OS4xNjktLjEyNi4xMTIyLS40MDgyLjE3NTctLjgzNy4xNzU3LTEuMjgwMyAwLTIuNjAyNS0yLjEyNS00LjcyNy00LjczNDQtNC43MjciLz48L3N2Zz4=",github:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+R2l0SHViPC90aXRsZT48cGF0aCBkPSJNMTIgLjI5N2MtNi42MyAwLTEyIDUuMzczLTEyIDEyIDAgNS4zMDMgMy40MzggOS44IDguMjA1IDExLjM4NS42LjExMy44Mi0uMjU4LjgyLS41NzcgMC0uMjg1LS4wMS0xLjA0LS4wMTUtMi4wNC0zLjMzOC43MjQtNC4wNDItMS42MS00LjA0Mi0xLjYxQzQuNDIyIDE4LjA3IDMuNjMzIDE3LjcgMy42MzMgMTcuN2MtMS4wODctLjc0NC4wODQtLjcyOS4wODQtLjcyOSAxLjIwNS4wODQgMS44MzggMS4yMzYgMS44MzggMS4yMzYgMS4wNyAxLjgzNSAyLjgwOSAxLjMwNSAzLjQ5NS45OTguMTA4LS43NzYuNDE3LTEuMzA1Ljc2LTEuNjA1LTIuNjY1LS4zLTUuNDY2LTEuMzMyLTUuNDY2LTUuOTMgMC0xLjMxLjQ2NS0yLjM4IDEuMjM1LTMuMjItLjEzNS0uMzAzLS41NC0xLjUyMy4xMDUtMy4xNzYgMCAwIDEuMDA1LS4zMjIgMy4zIDEuMjMuOTYtLjI2NyAxLjk4LS4zOTkgMy0uNDA1IDEuMDIuMDA2IDIuMDQuMTM4IDMgLjQwNSAyLjI4LTEuNTUyIDMuMjg1LTEuMjMgMy4yODUtMS4yMy42NDUgMS42NTMuMjQgMi44NzMuMTIgMy4xNzYuNzY1Ljg0IDEuMjMgMS45MSAxLjIzIDMuMjIgMCA0LjYxLTIuODA1IDUuNjI1LTUuNDc1IDUuOTIuNDIuMzYuODEgMS4wOTYuODEgMi4yMiAwIDEuNjA2LS4wMTUgMi44OTYtLjAxNSAzLjI4NiAwIC4zMTUuMjEuNjkuODI1LjU3QzIwLjU2NSAyMi4wOTIgMjQgMTcuNTkyIDI0IDEyLjI5N2MwLTYuNjI3LTUuMzczLTEyLTEyLTEyIi8+PC9zdmc+",neon:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDBFNTk5IiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+TmVvbjwvdGl0bGU+PHBhdGggZD0iTTI0IDBWMjRsLTkuMzY1LTguMDQ1VjI0SDBWMFpNMi45NDIgMjEuMDg3aDguNzUxVjkuNTYzbDkuMzY1IDguMjA0VjIuOTE5TDIuOTQyIDIuOTE0WiIvPjwvc3ZnPg==",posthog:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRjU0RTAwIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+UG9zdEhvZzwvdGl0bGU+PHBhdGggZD0iTTkuODU0IDE0LjUgNSA5LjY0Ny44NTQgNS41QS41LjUgMCAwIDAgMCA1Ljg1NFY4LjQ0YS41LjUgMCAwIDAgLjE0Ni4zNTNMNSAxMy42NDdsLjE0Ny4xNDZMOS44NTQgMTguNWwuMTQ2LjE0N3YtLjA0OWMuMDY1LjAzLjEzNC4wNDkuMjA3LjA0OWgyLjU4NmEuNS41IDAgMCAwIC4zNTMtLjg1NEw5Ljg1NCAxNC41em0wLTUtNC00YS40ODcuNDg3IDAgMCAwLS40MDktLjE0NC41MTUuNTE1IDAgMCAwLS4zNTYuMjEuNDkzLjQ5MyAwIDAgMC0uMDg5LjI4OFY4LjQ0YS41LjUgMCAwIDAgLjE0Ny4zNTNsOSA5YS41LjUgMCAwIDAgLjg1My0uMzU0di0yLjU4NWEuNS41IDAgMCAwLS4xNDYtLjM1NGwtNS01em0xLTRhLjUuNSAwIDAgMC0uODU0LjM1NFY4LjQ0YS41LjUgMCAwIDAgLjE0Ny4zNTNsNCA0YS41LjUgMCAwIDAgLjg1My0uMzU0VjkuODU0YS41LjUgMCAwIDAtLjE0Ni0uMzU0bC00LTR6bTEyLjY0NyAxMS41MTVhMy44NjMgMy44NjMgMCAwIDEtMi4yMzItMS4xbC00LjcwOC00LjcwN2EuNS41IDAgMCAwLS44NTQuMzU0djYuNTg1YS41LjUgMCAwIDAgLjUuNUgyMy41YS41LjUgMCAwIDAgLjUtLjV2LS42YzAtLjI3Ni0uMjI1LS40OTctLjQ5OS0uNTMyem0tNS4zOTQuMDMyYS44LjggMCAxIDEgMC0xLjYuOC44IDAgMCAxIDAgMS42ek0uODU0IDE1LjVhLjUuNSAwIDAgMC0uODU0LjM1NHYyLjI5M2EuNS41IDAgMCAwIC41LjVoMi4yOTNjLjIyMiAwIC4zOS0uMTM1LjQ2Mi0uMzA5YS40OTMuNDkzIDAgMCAwLS4xMDktLjU0NUwuODU0IDE1LjUwMXpNNSAxNC42NDcuODU0IDEwLjVhLjUuNSAwIDAgMC0uODU0LjM1M3YyLjU4NmEuNS41IDAgMCAwIC4xNDYuMzUzTDQuODU0IDE4LjVsLjE0Ni4xNDdoMi43OTNhLjUuNSAwIDAgMCAuMzUzLS44NTRMNSAxNC42NDd6Ii8+PC9zdmc+",railway:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+UmFpbHdheTwvdGl0bGU+PHBhdGggZD0iTS4xMTMgMTAuMjdBMTMuMDI2IDEzLjAyNiAwIDAwMCAxMS40OGgxOC4yM2MtLjA2NC0uMTI1LS4xNS0uMjM3LS4yMzUtLjM0Ny0zLjExNy00LjAyNy00Ljc5My0zLjY3Ny03LjE5LTMuNzgtLjgtLjAzNC0xLjM0LS4wNDgtNC41MjQtLjA0OC0xLjcwNCAwLTMuNTU1LjAwNS01LjM1OC4wMS0uMjM0LjYzLS40NTkgMS4yNC0uNTY3IDEuNzM3aDkuMzQydjEuMjE2SC4xMTN2LjAwMnptMTguMjYgMi40MjZILjAwOWMuMDIuMzI2LjA1LjY0NS4wOTQuOTYxaDE2Ljk1NWMuNzU0IDAgMS4xNzktLjQyOSAxLjMxNS0uOTZ6bS0xNy4zMTggNC4yOHMyLjgxIDYuOTAyIDEwLjkzIDcuMDI0YzQuODU1IDAgOS4wMjctMi44ODMgMTAuOTItNy4wMjRIMS4wNTZ6TTExLjk4OCAwQzcuNSAwIDMuNTkzIDIuNDY2IDEuNTMxIDYuMTA4bDQuNzUtLjAwNXYtLjAwMmMzLjcxIDAgMy44NDkuMDE2IDQuNTczLjA0N2wuNDQ4LjAxNmMxLjU2My4wNTIgMy40ODUuMjIgNC45OTYgMS4zNjQuODIuNjIxIDIuMDA3IDEuOTkgMi43MTIgMi45NjUuNjU0LjkwMi44NDIgMS45NC4zOTYgMi45MzQtLjQwOC45MTQtMS4yODkgMS40NTgtMi4zNTMgMS40NThILjM5MXMuMDk5LjQyLjI0OS44ODZoMjIuNzQ4QTEyLjAyNiAxMi4wMjYgMCAwMDI0IDEyLjAwNUMyNCA1LjM3NyAxOC42MjEgMCAxMS45ODggMHoiLz48L3N2Zz4=",render:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+UmVuZGVyPC90aXRsZT48cGF0aCBkPSJNMTguMjYzLjAwN2MtMy4xMjEtLjE0Ny01Ljc0NCAyLjEwOS02LjE5MiA1LjA4Mi0uMDE4LjEzOC0uMDQ1LjI3Mi0uMDY3LjQwNS0uNjk2IDMuNzAzLTMuOTM2IDYuNTA3LTcuODI3IDYuNTA3LTEuMzg4IDAtMi42OTEtLjM1Ni0zLjgyNS0uOTc5YS4yMDI0LjIwMjQgMCAwIDAtLjMwMi4xNzhWMjRIMTJ2LTguOTk5YzAtMS42NTYgMS4zMzgtMyAyLjk4Ny0zaDIuOTg4YzMuMzgyIDAgNi4xMDMtMi44MTcgNS45Ny02LjI0NC0uMTItMy4wODQtMi42MS01LjYwMy01LjY4Mi01Ljc1Ii8+PC9zdmc+",resend:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+UmVzZW5kPC90aXRsZT48cGF0aCBkPSJNMTQuNjc5IDBjNC42NDggMCA3LjQxMyAyLjc2NSA3LjQxMyA2LjQzNHMtMi43NjUgNi40MzQtNy40MTMgNi40MzRIMTIuMzNMMjQgMjRoLTguMjQ1bC04Ljg4LTguNDRjLS42MzYtLjU4OC0uOTMtMS4yNzMtLjkzLTEuODYgMC0uODMxLjU4Ny0xLjU2NSAxLjcxMy0xLjg4M2w0LjU3NC0xLjIyNGMxLjczNy0uNDY1IDIuOTM2LTEuODEgMi45MzYtMy41NzIgMC0yLjE1My0xLjc2MS0zLjQtMy45MzktMy40SDBWMHoiLz48L3N2Zz4=",sentry:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjOEI1Q0Y2IiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+U2VudHJ5PC90aXRsZT48cGF0aCBkPSJNMTMuOTEgMi41MDVjLS44NzMtMS40NDgtMi45NzItMS40NDgtMy44NDQgMEw2LjkwNCA3LjkyYTE1LjQ3OCAxNS40NzggMCAwIDEgOC41MyAxMi44MTFoLTIuMjIxQTEzLjMwMSAxMy4zMDEgMCAwIDAgNS43ODQgOS44MTRsLTIuOTI2IDUuMDZhNy42NSA3LjY1IDAgMCAxIDQuNDM1IDUuODQ4SDIuMTk0YS4zNjUuMzY1IDAgMCAxLS4yOTgtLjUzNGwxLjQxMy0yLjQwMmE1LjE2IDUuMTYgMCAwIDAtMS42MTQtLjkxM0wuMjk2IDE5LjI3NWEyLjE4MiAyLjE4MiAwIDAgMCAuODEyIDIuOTk5IDIuMjQgMi4yNCAwIDAgMCAxLjA4Ni4yODhoNi45ODNhOS4zMjIgOS4zMjIgMCAwIDAtMy44NDUtOC4zMThsMS4xMS0xLjkyMmExMS40NyAxMS40NyAwIDAgMSA0Ljk1IDEwLjI0aDUuOTE1YTE3LjI0MiAxNy4yNDIgMCAwIDAtNy44ODUtMTUuMjhsMi4yNDQtMy44NDVhLjM3LjM3IDAgMCAxIC41MDQtLjEzYy4yNTUuMTQgOS43NSAxNi43MDggOS45MjggMTYuOWEuMzY1LjM2NSAwIDAgMS0uMzI3LjU0M2gtMi4yODdjLjAyOS42MTIuMDI5IDEuMjIzIDAgMS44MzFoMi4yOTdhMi4yMDYgMi4yMDYgMCAwIDAgMS45MjItMy4zMXoiLz48L3N2Zz4=",stripe:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjNjM1QkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+U3RyaXBlPC90aXRsZT48cGF0aCBkPSJNMTMuOTc2IDkuMTVjLTIuMTcyLS44MDYtMy4zNTYtMS40MjYtMy4zNTYtMi40MDkgMC0uODMxLjY4My0xLjMwNSAxLjkwMS0xLjMwNSAyLjIyNyAwIDQuNTE1Ljg1OCA2LjA5IDEuNjMxbC44OS01LjQ5NEMxOC4yNTIuOTc1IDE1LjY5NyAwIDEyLjE2NSAwIDkuNjY3IDAgNy41ODkuNjU0IDYuMTA0IDEuODcyIDQuNTYgMy4xNDcgMy43NTcgNC45OTIgMy43NTcgNy4yMThjMCA0LjAzOSAyLjQ2NyA1Ljc2IDYuNDc2IDcuMjE5IDIuNTg1LjkyIDMuNDQ1IDEuNTc0IDMuNDQ1IDIuNTgzIDAgLjk4LS44NCAxLjU0NS0yLjM1NCAxLjU0NS0xLjg3NSAwLTQuOTY1LS45MjEtNi45OS0yLjEwOWwtLjkgNS41NTVDNS4xNzUgMjIuOTkgOC4zODUgMjQgMTEuNzE0IDI0YzIuNjQxIDAgNC44NDMtLjYyNCA2LjMyOC0xLjgxMyAxLjY2NC0xLjMwNSAyLjUyNS0zLjIzNiAyLjUyNS01LjczMiAwLTQuMTI4LTIuNTI0LTUuODUxLTYuNTk0LTcuMzA1aC4wMDN6Ii8+PC9zdmc+",supabase:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjM0VDRjhFIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+U3VwYWJhc2U8L3RpdGxlPjxwYXRoIGQ9Ik0xMS45IDEuMDM2Yy0uMDE1LS45ODYtMS4yNi0xLjQxLTEuODc0LS42MzdMLjc2NCAxMi4wNUMtLjMzIDEzLjQyNy42NSAxNS40NTUgMi40MDkgMTUuNDU1aDkuNTc5bC4xMTMgNy41MWMuMDE0Ljk4NSAxLjI1OSAxLjQwOCAxLjg3My42MzZsOS4yNjItMTEuNjUzYzEuMDkzLTEuMzc1LjExMy0zLjQwMy0xLjY0NS0zLjQwM2gtOS42NDJ6Ii8+PC9zdmc+",upstash:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjMDBFOUEzIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+VXBzdGFzaDwvdGl0bGU+PHBhdGggZD0iTTEzLjgwMjcgMEMxMS4xOTMgMCA4LjU4My45OTUyIDYuNTkxOCAyLjk4NjNjLTMuOTgyMyAzLjk4MjMtMy45ODIzIDEwLjQzOTYgMCAxNC40MjE5IDEuOTkxMSAxLjk5MTEgNS4yMTk4IDEuOTkxMSA3LjIxMSAwIDEuOTkxLTEuOTkxMSAxLjk5MS01LjIxOTggMC03LjIxMUwxMiAxMmMuOTk1Ni45OTU2Ljk5NTYgMi42MDk4IDAgMy42MDU1LS45OTU2Ljk5NTUtMi42MDk5Ljk5NTUtMy42MDU1IDAtMi45ODY2LTIuOTg2OC0yLjk4NjYtNy44Mjk3IDAtMTAuODE2NCAyLjk4NjgtMi45ODY4IDcuODI5Ny0yLjk4NjggMTAuODE2NCAwbDEuODAyOC0xLjgwMjhDMTkuMDIyNS45OTUyIDE2LjQxMjUgMCAxMy44MDI3IDB6TTEyIDEyYy0uOTk1Ni0uOTk1Ni0uOTk1Ni0yLjYwOTggMC0zLjYwNTUuOTk1Ni0uOTk1NSAyLjYwOTgtLjk5NTUgMy42MDU1IDAgMi45ODY3IDIuOTg2OCAyLjk4NjcgNy44Mjk3IDAgMTAuODE2NC0yLjk4NjcgMi45ODY4LTcuODI5NyAyLjk4NjgtMTAuODE2NCAwbC0xLjgwMjggMS44MDI4YzMuOTgyMyAzLjk4MjIgMTAuNDM5NiAzLjk4MjIgMTQuNDIxOSAwIDMuOTgyMy0zLjk4MjQgMy45ODIzLTEwLjQzOTYgMC0xNC40MjE5LS45OTU2LS45OTU2LTIuMzAwNi0xLjQ5MjItMy42MDU1LTEuNDkyMi0xLjMwNDggMC0yLjYwOTkuNDk2Ni0zLjYwNTQgMS40OTIyLTEuOTkxMiAxLjk5MTItMS45OTEyIDUuMjE5OCAwIDcuMjExeiIvPjwvc3ZnPg==",vercel:"data:image/svg+xml;base64,PHN2ZyBmaWxsPSIjRkZGRkZGIiByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48dGl0bGU+VmVyY2VsPC90aXRsZT48cGF0aCBkPSJtMTIgMS42MDggMTIgMjAuNzg0SDBaIi8+PC9zdmc+"};function me(e){return qe[e]??null}var ee=[{id:"app",label:"Your app"},{id:"findings",label:"Findings"},{id:"fix",label:"Fix"},{id:"recheck",label:"Re-check"},{id:"ready",label:"Launch checklist"}],R={critical:0,warning:1,info:2},ye={supabase:"https://supabase.com/dashboard/projects",vercel:"https://vercel.com/dashboard",stripe:"https://dashboard.stripe.com",github:"https://github.com/settings/profile",sentry:"https://sentry.io",posthog:"https://app.posthog.com",clerk:"https://dashboard.clerk.com",resend:"https://resend.com/emails",upstash:"https://console.upstash.com",neon:"https://console.neon.tech",railway:"https://railway.com/dashboard",render:"https://dashboard.render.com",cloudflare:"https://dash.cloudflare.com"},Ke="sql|ts|tsx|js|jsx|mjs|cjs|json|toml|ya?ml|env|py|rb|go|rs|vue|svelte|astro|html|css|md|prisma|php|java|kt|sh|lock",Xe=new RegExp(String.raw`((?:[\w.@-]+[\\/])*[\w.@-]+\.(?:${Ke})):(\d{1,6})\b`,"g");function Je(e){if(!e)return[];let i=new Set;for(let n of e.matchAll(Xe))i.add(`${n[1].split("\\").join("/")}:${n[2]}`);return[...i]}function _e(e){let i=(e??"").split(`
4
- `).map(a=>a.trim()).filter(Boolean),[n="",...r]=i;return{summary:n,evidence:r.filter(a=>a!=="Evidence:").map(a=>a.replace(/^-\s*/,""))}}function G(e){return me(e.id)??e.logoUrl}function et(e,i){let n=i?.provider?.nextFix;return n?.id===e.id&&n.prompt?n.prompt:[`Fix this production blocker in the repo now: ${e.title}.`,e.detail??"",e.prompt?`How to fix it: ${e.prompt}`:"","Make the minimal change, then summarize what you changed and which files. Do not claim the app is production-ready; VibeRaven will check again."].filter(Boolean).join(`
4
+ `).map(a=>a.trim()).filter(Boolean),[n="",...r]=i;return{summary:n,evidence:r.filter(a=>a!=="Evidence:").map(a=>a.replace(/^-\s*/,""))}}function G(e){return me(e.id)??e.logoUrl}function et(e,i){let n=i?.provider?.nextFix;return n?.id===e.id&&n.prompt?n.prompt:[e.asksFirst?`${e.asksFirst} Tell the user this before you change anything, and make the change only if they confirm.`:"",`Fix this production blocker in the repo now: ${e.title}.`,e.detail??"",e.prompt?`How to fix it: ${e.prompt}`:"","Make the minimal change, then summarize what you changed and which files. Do not claim the app is production-ready; VibeRaven will check again."].filter(Boolean).join(`
5
5
  `)}function tt(e,i){let n=e.find(a=>a.provider?.nextFix?.id===i.id);if(n)return n;let r=`${i.title} ${i.detail??""}`.toLowerCase();return e.find(a=>r.includes(a.name.toLowerCase())||r.includes(`${a.id}/`))}function Me(e){let[i,n]=[e.slice(0,e.lastIndexOf(":")),e.slice(e.lastIndexOf(":")+1)];return`${i.split("/").pop()??i}:${n}`}function nt(e){return!e.project.empty&&!!e.project.project?.scannedAt}function it(e){return e.busy.scan||e.scan?.state==="running"}function S(e){let i=nt(e),n=it(e),a=z(e.project,e.catalog,e.verified).filter(h=>h.step!=="absent"),c=i?e.project.missionCards?.blockers??[]:[],u=new Set((e.project.missionCards?.planSteps??[]).filter(h=>h.requiresUserAction).map(h=>h.id)),o=c.map(h=>{let k=tt(a,h),{summary:L,evidence:j}=_e(h.detail);return{id:h.id,title:h.title,severity:h.severity,summary:L,evidence:j,locations:Je(h.detail),service:k?{id:k.id,name:k.name,mark:G(k)}:null,dashboard:h.requiresUserAction===!0||u.has(h.id),prompt:et(h,k)}}),p=new Map;for(let h of o){let k=h.service?.id??"app",L=p.get(k)??{key:k,name:h.service?.name??"Your code",mark:h.service?.mark??null,findings:[]};L.findings.push(h),p.set(k,L)}let s=h=>Math.min(...h.findings.map(k=>R[k.severity])),l=[...p.values()].map(h=>({...h,findings:[...h.findings].sort((k,L)=>R[k.severity]-R[L.severity])})).sort((h,k)=>s(h)-s(k)||k.findings.length-h.findings.length),d=l.flatMap(h=>h.findings),f=d.filter(h=>!h.dashboard).sort((h,k)=>R[h.severity]-R[k.severity]),y={critical:0,warning:0,info:0};for(let h of o)y[h.severity]+=1;let g=a.map(h=>{let k=o.filter(K=>K.service?.id===h.id),L=k.filter(K=>K.severity==="critical").length,j=e.verified[h.id],E="pending",U="Unknown \xB7 not checked yet";return n?U="Checking":i&&(L?(E="fail",U=`Not ready \xB7 ${L} blocker${L===1?"":"s"}`):k.length?(E="warn",U=`${k.length} to review`):(E="pass",U=j?.ok?"Ready \xB7 checked live":"Ready \xB7 no blockers found")),{id:h.id,name:h.name,area:h.area,mark:G(h),tone:E,stateText:U,findings:k.length,verified:j}}),m=f.find(h=>h.id===e.flow.fixId)??null,M=[];for(let h of a){let k=e.verified[h.id];M.push({id:`live:${h.id}`,label:`Check ${h.name} live`,detail:k?k.ok?`Your agent checked the real ${h.name} project and it matched.`:`Your agent checked ${h.name} and found issues.`:`Your agent reads your real ${h.name} project and confirms it matches the code.`,kind:"live",done:k?.ok===!0,doneBy:"viberaven",providerId:h.id});let L=h.provider?.cockpit?.proof.checks.filter(j=>j.source==="dashboard"&&j.status!=="yes")??[];for(let j of L){let E=`dash:${h.id}:${j.label}`;M.push({id:E,label:j.label==="Production secret proof"?`Production keys for ${h.name} are set where you deploy`:`${h.name}: ${j.label}`,detail:j.label==="Production secret proof"?`The keys your app reads for ${h.name} go in your hosting provider's environment settings for production. VibeRaven cannot see your dashboards, so you tick this.`:`VibeRaven cannot see your ${h.name} dashboard, so you tick this.`,kind:"dashboard",done:e.flow.checklist[E]===!0,doneBy:"you",providerId:h.id,href:ye[h.id]})}}for(let h of d.filter(k=>k.dashboard))M.push({id:`finding:${h.id}`,label:h.title,detail:`${h.summary} This clears when the next check no longer finds it.`,kind:"finding",done:!1,doneBy:"viberaven",providerId:h.service?.id,href:h.service?ye[h.service.id]:void 0});let w=f.filter(h=>h.severity==="critical").length,N={app:!0,findings:i,fix:i&&f.length>0,recheck:i&&e.flow.recheck!==null,ready:i&&w===0};return{scanned:i,scanning:n,services:g,findings:o,groups:l,fixable:f,counts:y,current:m,checklist:M,gateClear:i&&e.project.gate?.status==="clear",available:N}}function te(e){return e.scanned?e.findings.length===0||!e.available.fix?"ready":"findings":"app"}function be(e,i){let n=i.flow.recheck,r=e.checklist.filter(a=>!a.done).length;return{app:e.scanning?"Checking now":e.services.length?`${e.services.length} service${e.services.length===1?"":"s"} found`:"No services found",findings:e.scanned?e.findings.length===0?"Nothing found":[e.counts.critical?`${e.counts.critical} critical`:null,`${e.findings.length} total`].filter(Boolean).join(" \xB7 "):"After the check",fix:e.scanned?e.fixable.length===0?"Nothing to fix in code":`${e.fixable.length} to fix`:"After the check",recheck:n?n.status==="running"?"Checking now":n.status==="fixed"?"Last fix held":n.status==="open"?"Still open":"Did not finish":"After a fix",ready:e.scanned?e.available.ready?e.gateClear?"No blockers found":r?`${r} step${r===1?"":"s"} left`:"Checklist done":"After the critical fixes":"After the check"}}var C={check:'<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7"/></svg>',arrow:'<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4"/></svg>',back:'<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M13 8H3M7 4L3 8l4 4"/></svg>',copy:'<svg viewBox="0 0 16 16" width="14" height="14" fill="none" stroke="currentColor" stroke-width="1.6" aria-hidden="true"><rect x="5.5" y="5.5" width="8" height="8" rx="1.6"/><path d="M10.5 5.5V3.6c0-.6-.5-1.1-1.1-1.1H3.6c-.6 0-1.1.5-1.1 1.1v5.8c0 .6.5 1.1 1.1 1.1h1.9"/></svg>',more:'<svg viewBox="0 0 16 16" width="14" height="14" fill="currentColor" aria-hidden="true"><circle cx="3" cy="8" r="1.4"/><circle cx="8" cy="8" r="1.4"/><circle cx="13" cy="8" r="1.4"/></svg>',out:'<svg viewBox="0 0 16 16" width="12" height="12" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 3H3v10h10v-3M9 3h4v4M13 3L7.5 8.5"/></svg>'},st={critical:"Critical",warning:"Important",info:"Nice to have"};function P(e){return t("span",{class:"ico",html:e})}function q(e){return(e||"Project").replace(/^@[^/]+\//,"").split(/[-_\s]+/).filter(Boolean).map(i=>i.charAt(0).toUpperCase()+i.slice(1)).join(" ")}function W(e){let i=e.project.project;return(i?.name&&i.name!=="Project"?i.name:(i?.path??"").split(/[\\/]/).filter(Boolean).pop())||"your-app"}function Z(e,i=e.cliId){return e.agents.find(n=>n.id===i)?.label.replace(/ CLI$/,"")??(i==="claude"?"Claude Code":i==="gemini"?"Gemini":"Codex")}function we(e,i){let n=e.project.project,r=e.project.releases?.[0],a=Se(e,S(e));return t("header",{class:"top",dataset:{slot:"top"}},t("span",{class:"wordmark"},"Vibe",t("b",{},"Raven")),t("span",{class:"top-project"},t("span",{class:"top-sep","aria-hidden":"true"},"/"),t("strong",{},q(W(e))),t("span",{class:"top-sep","aria-hidden":"true"},"/"),t("code",{},[r?.branch,n?.version?`v${n.version.replace(/^v/,"")}`:null].filter(Boolean).join(" \xB7 ")||"local")),t("span",{class:"spacer"}),t("span",{class:`top-verdict is-${a.tone}`},t("i",{"aria-hidden":"true"}),a.text),t("div",{class:"more-wrap"},t("button",{id:"open-more",class:`quiet more-button${e.moreOpen?" on":""}`,"aria-haspopup":"menu","aria-expanded":String(e.moreOpen),"aria-controls":"more-menu",on:{click:()=>i.toggleMore()}},"More",P(C.more)),e.moreOpen?rt(e,i):null))}function rt(e,i){let n=e.agents.filter(a=>e.probes[a.id]?.ready).length,r=[{id:"services",label:"Services",note:"Browse, add and check services live"},{id:"terminal",label:"Coding agents",note:n?`${n} connected`:"Install, sign in, test"},{id:"chat",label:"Agent chat",note:"Ask your agent anything about this app"},{id:"releases",label:"Releases",note:(e.project.releases??[]).length?"History and diffs":"Compare any two commits"}];return t("div",{id:"more-menu",class:"more-menu",role:"menu","aria-label":"More",on:{keydown:a=>{let c=a.key;if(c!=="ArrowDown"&&c!=="ArrowUp")return;a.preventDefault();let u=Array.from(a.currentTarget.querySelectorAll('[role="menuitem"]')),o=u.indexOf(document.activeElement);u[(o+(c==="ArrowDown"?1:-1)+u.length)%u.length]?.focus()}}},...r.map(a=>t("button",{role:"menuitem",class:"more-item",on:{click:()=>i.openMore(a.id)}},t("strong",{},a.label),t("span",{},a.note))))}function ve(e,i,n){let r=be(i,e),a=ee.findIndex(c=>c.id===e.flow.step);return t("nav",{class:"rail","aria-label":"Launch path",dataset:{slot:"rail"}},t("ol",{},...ee.map((c,u)=>{let o=c.id===e.flow.step,p=i.available[c.id],s=u<a&&p;return t("li",{class:`rail-step is-${o?"current":s?"passed":p?"open":"locked"}`},t("button",{class:"rail-button","aria-current":o?"step":void 0,disabled:!p,on:{click:()=>n.goToStep(c.id)}},t("span",{class:"rail-mark","aria-hidden":"true",html:s?C.check:""}),t("span",{class:"rail-copy"},t("span",{class:"rail-label"},c.label),t("span",{class:"rail-meta"},r[c.id]))))})))}function Se(e,i){if(i.scanning)return{text:"Checking your app",tone:"pending"};if(!i.scanned)return{text:"Not checked yet",tone:"pending"};if(i.counts.critical)return{text:`${i.counts.critical} blocker${i.counts.critical===1?"":"s"}`,tone:"fail"};if(i.findings.length)return{text:`${i.findings.length} to review`,tone:"warn"};let n=i.checklist.filter(a=>!a.done).length,r=n?` \xB7 ${n} unknown${n===1?"":"s"}`:"";return{text:i.gateClear?`No blockers found${r}`:"No blockers in the code",tone:"pass"}}function ke(e){return t("li",{class:`node is-${e.tone}`,dataset:{provider:e.id}},e.mark?t("img",{src:e.mark,alt:"",width:32,height:32}):t("span",{class:"node-fallback"},e.name.slice(0,1)),t("span",{class:"node-name"},e.name),t("span",{class:"node-state"},t("i",{"aria-hidden":"true"}),e.stateText))}function at(){let e=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.setAttribute("class","board-lines"),e.setAttribute("aria-hidden","true"),e}function ot(e,i){let n=e.project.project,r=Se(e,i),a=i.services.length<=3,c=a?[]:i.services.filter((s,l)=>l%2===0),u=a?i.services:i.services.filter((s,l)=>l%2===1),o=i.scanned?[n?.archetype&&n.archetype!=="unknown"?n.archetype:null,n?.scannedAt?`Checked ${D(n.scannedAt)}`:null,typeof e.project.gate?.score=="number"?`Readiness ${e.project.gate.score} of 100`:null].filter(s=>!!s):[],p=JSON.stringify([i.services.map(s=>[s.id,s.tone,s.stateText]),r,o,i.scanning]);return t("figure",{class:`board${i.scanning?" is-scanning":""}${i.services.length?a?" is-side":"":" is-solo"}`,dataset:{sig:p,lines:i.services.length?"1":""},"aria-label":`${q(W(e))} and the services found in its code`},at(),c.length?t("ul",{class:"board-col left"},...c.map(ke)):null,t("div",{class:`board-app is-${r.tone}`},t("code",{class:"board-app-name"},W(e)),t("p",{class:"board-status"},t("strong",{},r.text)),o.length?t("ul",{class:"board-checks"},...o.map(s=>t("li",{},t("i",{"aria-hidden":"true"}),s))):null),u.length?t("ul",{class:"board-col right"},...u.map(ke)):null)}function Ie(e){let i=e.querySelector(".board-lines"),n=e.querySelector(".board-app");if(!i||!n)return;let r=e.getBoundingClientRect();if(!r.width)return;let a=n.getBoundingClientRect(),c=Array.from(e.querySelectorAll(".node")),u=a.bottom<=Math.min(...c.map(p=>p.getBoundingClientRect().top),1/0)+1;if(i.setAttribute("viewBox",`0 0 ${Math.round(r.width)} ${Math.round(r.height)}`),i.setAttribute("width",String(Math.round(r.width))),i.setAttribute("height",String(Math.round(r.height))),u){i.innerHTML="";return}let o=c.map((p,s)=>{let l=p.getBoundingClientRect(),d=l.right<=a.left,f=(d?a.left:a.right)-r.left,y=a.top-r.top+a.height/2+(s%4-1.5)*Math.min(22,a.height/7),g=(d?l.right:l.left)-r.left,m=l.top-r.top+l.height/2,M=(f+g)/2,w=/is-(pass|warn|fail|pending)/.exec(p.className)?.[1]??"pending",N=`M ${f.toFixed(1)} ${y.toFixed(1)} C ${M.toFixed(1)} ${y.toFixed(1)} ${M.toFixed(1)} ${m.toFixed(1)} ${g.toFixed(1)} ${m.toFixed(1)}`;return`<path class="line is-${w}" d="${N}"/><path class="pulse" pathLength="1" style="animation-delay:${(s*.6).toFixed(2)}s" d="${N}"/>`});i.innerHTML=o.join("")}function x(e,i){let n=[t("h1",{id:"stage-heading",tabindex:-1},e)];return i&&n.push(t("p",{class:"stage-sub"},i)),n}function v(e,i,n={}){return t("div",{class:"primary-row"},t("button",{id:n.id??"primary-action",class:"primary",disabled:n.disabled,on:{click:i}},n.busy?t("span",{class:"spin","aria-hidden":"true"}):null,e,n.busy?null:P(C.arrow)),n.note?t("span",{class:"primary-note"},n.note):null)}function V(e,i,n={}){return t("button",{class:"quiet",disabled:n.disabled,on:{click:i}},n.icon?P(n.icon):null,e)}function Ae(e){return t("span",{class:`sev is-${e.severity}`},t("i",{"aria-hidden":"true"}),st[e.severity])}function Le(e,i=!1){if(!e.locations.length)return null;let[n,...r]=e.locations;return t("span",{class:"where"},t("code",{title:e.locations.join(`
6
6
  `)},i?n:Me(n)),r.length?t("span",{class:"where-more"},`+${r.length} more`):null)}function lt(e,i,n){let r=e.project.project,a=i.services.length,c=i.scanning?"Reading your code and the services it uses. Nothing leaves this computer.":a?`VibeRaven found ${a} service${a===1?"":"s"} in this code. Nothing to set up: the check reads the repo as it is.`:"No hosted services found in this code. The check still reads the app itself.";return[...x(q(W(e)),c),ot(e,i),v(i.scanning?"Checking your app":"Check my app",()=>void n.checkMyApp(),{disabled:i.scanning||e.setup.running,busy:i.scanning,id:"check-my-app",note:i.scanned&&!i.scanning?`Last check ${D(r.scannedAt)}. It runs on this computer, offline.`:"Runs on this computer, offline. No account needed."}),i.scanned&&!i.scanning?t("div",{class:"quiet-row"},V("See the last findings",()=>n.goToStep("findings"))):null].filter(u=>u!==null)}function ct(e,i,n){let r=i.fixable[0],a=e.project.project?.scannedAt;if(!i.findings.length)return[...x("Nothing to fix",`The check ${a?D(a):""} found no blockers in this code.`),v("Go to the launch checklist",()=>n.goToStep("ready"))];let c=[i.counts.critical?`${i.counts.critical} critical`:null,i.counts.warning?`${i.counts.warning} important`:null,i.counts.info?`${i.counts.info} nice to have`:null].filter(Boolean).join(", ");return[...x(`${i.findings.length} finding${i.findings.length===1?"":"s"}`,`${c}. Critical first, grouped by service. From the check ${a?D(a):""}.`),t("div",{class:"findings"},...i.groups.map(u=>t("section",{class:"group","aria-label":u.name},t("header",{class:"group-head"},u.mark?t("img",{src:u.mark,alt:"",width:22,height:22}):t("span",{class:"group-code","aria-hidden":"true"},"</>"),t("h2",{},u.name),t("span",{class:"group-count"},String(u.findings.length))),t("ul",{},...u.findings.map(o=>{let p=o.id===r?.id,s=[Ae(o),t("span",{class:"finding-title"},o.title),o.dashboard?t("span",{class:"finding-tag"},"Dashboard step"):Le(o)];return t("li",{},o.dashboard?t("div",{class:`finding is-${o.severity} is-static`,dataset:{provider:o.service?.id??""}},...s):t("button",{class:`finding is-${o.severity}${p?" is-first":""}`,dataset:{provider:o.service?.id??""},on:{click:()=>n.fixFinding(o.id)}},...s,P(C.arrow)))}))))),r?v("Fix the first blocker",()=>n.fixFinding(),{id:"fix-first",note:r.title}):v("Go to the launch checklist",()=>n.goToStep("ready"),{note:"What is left needs your dashboards, not your code."})]}function dt(e,i,n){let r=e.agents.filter(a=>a.installed);return r.length?t("div",{class:"agent-choice",role:"radiogroup","aria-label":"Coding agent"},...r.map(a=>{let c=e.probes[a.id],u=a.id===e.cliId;return t("button",{role:"radio","aria-checked":String(u),class:`agent-option${u?" on":""}`,disabled:n,on:{click:()=>i.selectCli(a.id)}},t("i",{class:c?.ready?"ok":c?"no":"","aria-hidden":"true"}),a.label.replace(/ CLI$/,""))})):null}function ut(e,i,n){let r=i.current;if(!r)return[...x("Nothing to fix in code","Every finding left needs a dashboard, not the repo."),v("Go to the launch checklist",()=>n.goToStep("ready"))];let a=i.fixable.findIndex(f=>f.id===r.id),c=e.flow.handoff?.findingId===r.id?e.flow.handoff:null,u=Z(e),o=e.probes[e.cliId],p=e.agents.filter(f=>f.installed),s=c?.status==="running",l=e.busy.probe===e.cliId,d;return s?d=v(`${u} is working`,()=>{},{disabled:!0,busy:!0,note:"It edits files in this repo. You review the change."}):c?.status==="done"?d=v("Check again",()=>void n.checkAgain(),{id:"check-again",note:"Runs the same local check to see if the fix held."}):p.length?o?.ready?d=v(c?.status==="failed"?`Send to ${u} again`:`Send to ${u}`,()=>void n.sendFix(),{id:"send-fix",note:e.accessMode==="ask"?"Ask mode is on: the agent will only plan, not edit. Change it in More, Agent chat.":`${u} edits files in this repo. You review the change.`}):d=v(l?`Connecting ${u}`:`Connect ${u}`,()=>void n.testConnection(e.cliId),{disabled:l,busy:l,note:o?o.message:`VibeRaven runs ${u} on this computer with your own sign-in.`}):d=v("Copy the prompt",()=>void n.copyFix(),{note:"No coding agent found on this computer. Paste it into any agent."}),[...x(r.title),t("div",{class:"fix-meta"},Ae(r),t("span",{class:"fix-count"},`Blocker ${a+1} of ${i.fixable.length}${r.service?` \xB7 ${r.service.name}`:""}`),Le(r,!0)),r.summary?t("p",{class:"fix-summary"},r.summary):null,r.evidence.length?t("ul",{class:"fix-evidence"},...r.evidence.slice(0,4).map(f=>t("li",{},f))):null,t("section",{class:"prompt","aria-label":"Prompt for your agent"},t("header",{},t("h2",{},"Prompt for your agent"),V("Copy",()=>void n.copyFix(),{icon:C.copy})),t("pre",{tabindex:0},r.prompt)),dt(e,n,s||e.busy.chat),s?t("p",{class:"working-line",role:"status"},t("span",{dataset:{working:"1"}},`${u} is working\u2026`),t("button",{class:"quiet stop",on:{click:()=>void n.stop()}},"Stop")):null,c&&c.status!=="running"?t("section",{class:`agent-reply is-${c.status}`,"aria-label":`${Z(e,c.cliId)} replied`},t("h2",{},c.status==="done"?`${Z(e,c.cliId)} replied`:`${Z(e,c.cliId)} did not finish`),t("div",{class:"agent-reply-body",html:H(c.output)})):null,d,t("div",{class:"quiet-row"},V("Back to findings",()=>n.goToStep("findings"),{icon:C.back}),c?.status!=="done"?V("Fixed it yourself? Check again",()=>void n.checkAgain(),{disabled:s||i.scanning}):null)].filter(f=>f!==null)}function pt(e,i,n){let r=e.flow.recheck;if(!r)return[...x("Nothing to check yet","Fix a blocker first, then check again here."),v("Back to findings",()=>n.goToStep("findings"))];let a=typeof r.scoreBefore=="number"&&typeof r.scoreAfter=="number"&&r.scoreBefore!==r.scoreAfter?t("p",{class:"score-move"},`Readiness ${r.scoreBefore} \u2192 ${r.scoreAfter}`):null;if(r.status==="running")return[...x("Checking again",`Running the same local check to see if \u201C${r.title}\u201D is gone.`),t("div",{class:"recheck-meter",role:"status"},t("span",{class:"spin"}),"Reading the repo"),v("Checking",()=>{},{disabled:!0,busy:!0})];if(r.status==="fixed"){let c=i.fixable.find(u=>u.id===r.nextId);return[...x("Scenario passed locally",`\u201C${r.title}\u201D no longer shows up in the check.`),a,t("p",{class:"recheck-next",role:"status"},c?`Next: ${c.title}`:"That was the last blocker in the code."),c?v("Next blocker",()=>n.fixFinding(c.id),{note:"Moving on by itself in a moment."}):v("Go to the launch checklist",()=>n.goToStep("ready"),{note:"Moving on by itself in a moment."})].filter(u=>u!==null)}return r.status==="open"?[...x("Still open",`The check still finds \u201C${r.title}\u201D.`),r.message?t("p",{class:"fix-summary"},r.message):null,a,v("Back to the fix",()=>n.fixFinding(r.findingId))].filter(c=>c!==null):[...x("The check did not finish",r.message??""),v("Check again",()=>void n.checkAgain())]}function gt(e,i,n){if(!i.checklist.length)return t("section",{class:"checklist","aria-label":"Launch checklist"},t("h2",{},"Launch checklist"),t("p",{class:"empty-line"},"No dashboard steps found for this app: VibeRaven found no hosted services in the code."));let r=i.checklist.filter(a=>!a.done).length;return t("section",{class:"checklist","aria-label":"Launch checklist"},t("h2",{},"Launch checklist",t("span",{class:"checklist-count"},r?`${r} left`:"All done")),t("ul",{},...i.checklist.map(a=>t("li",{class:`check-item${a.done?" is-done":""}`},a.doneBy==="you"?t("button",{class:"tick",role:"checkbox","aria-checked":String(a.done),"aria-label":a.label,on:{click:()=>n.toggleChecklistItem(a.id)},html:a.done?C.check:""}):t("span",{class:`tick is-auto${a.done?" on":""}`,"aria-hidden":"true",html:a.done?C.check:""}),t("div",{class:"check-copy"},t("strong",{},a.label),t("span",{},a.detail),t("span",{class:"check-who"},a.doneBy==="you"?"You confirm this":a.kind==="live"?"VibeRaven confirms this with your agent":"VibeRaven confirms this on the next check")),a.kind==="live"&&!a.done&&a.providerId?t("button",{class:"quiet",disabled:e.busy.chat||!e.probes[e.cliId]?.ready,title:e.probes[e.cliId]?.ready?void 0:"Connect a coding agent first",on:{click:()=>void n.verifyById(a.providerId)}},"Check live"):a.href?t("a",{class:"quiet",href:a.href,target:"_blank",rel:"noreferrer"},"Open dashboard",P(C.out)):null))))}function ft(e,i){let n=e.fullCheck.status,r=O(n?.usage),a=n?.account?n.account.plan==="pro"?"Pro plan":"Free plan":null;return t("section",{class:"final","aria-label":"Full check"},t("h2",{},"Final confirmation"),t("p",{},"The full check runs on VibeRaven across every production area. You see exactly what gets sent before anything leaves this computer."),t("p",{class:"final-quota"},[a,r??"Free accounts get 2 full checks. Pro gets 50 a month."].filter(Boolean).join(" \xB7 ")),t("button",{id:"run-full-check",class:"primary",disabled:e.fullCheck.step==="running",on:{click:()=>void i.openFullCheck()}},"Run full check",P(C.arrow)))}function ht(e,i,n){if(!i.available.ready)return[...x("Not yet","Fix the critical blockers first. The launch checklist opens when none are left."),v("Back to findings",()=>n.goToStep("findings"))];let r=i.findings.filter(o=>!o.dashboard).length,a=i.gateClear?"No blockers found within tested scope":"No critical blockers left",c=i.checklist.filter(o=>!o.done).length,u=i.gateClear?c?`${c} unknown${c===1?"":"s"}: the checklist items below, which VibeRaven cannot test from this computer.`:"Every item on the checklist is confirmed.":`The code has no critical blockers.${r?` ${r} other finding${r===1?" is":"s are"} still open in Findings.`:""} What is left lives in your dashboards.`;return[...x(a,u),i.services.length?t("ul",{class:"strip","aria-label":"Services"},...i.services.map(o=>t("li",{class:`strip-item is-${o.tone}`},o.mark?t("img",{src:o.mark,alt:"",width:20,height:20}):null,o.name))):null,t("div",{class:"ready-grid"},gt(e,i,n),ft(e,n))].filter(o=>o!==null)}var ne=null;function je(e,i){let n=S(e),r=e.flow.step,a=ne!==null&&ne!==r;ne=r;let c=r==="app"?lt(e,n,i):r==="findings"?ct(e,n,i):r==="fix"?ut(e,n,i):r==="recheck"?pt(e,n,i):ht(e,n,i);return t("main",{class:"stage",dataset:{slot:"stage",step:r}},e.scan?.state==="error"?t("p",{class:"stage-alert",role:"alert"},e.scan.error??"The first check did not finish."):null,t("div",{class:`stage-body step-${r}${a?" arrive":""}`,dataset:{slot:`body-${r}`}},...c))}function xe(e){return S(e)}function Ce(e,i){let n=Array.from(e.children);i.forEach((r,a)=>{let c=n[a];if(!c){e.appendChild(r);return}let u=r.dataset?.sig;if(u&&c.dataset?.sig===u&&c.tagName===r.tagName)return;let o=r.dataset?.slot;if(o&&c.dataset?.slot===o&&c.tagName===r.tagName){for(let p of Array.from(c.attributes))r.hasAttribute(p.name)||c.removeAttribute(p.name);for(let p of Array.from(r.attributes))c.getAttribute(p.name)!==p.value&&c.setAttribute(p.name,p.value);Ce(c,Array.from(r.children));return}e.replaceChild(r,c)});for(let r of Array.from(e.children).slice(i.length))r.remove()}var ie=new WeakMap;function mt(e){for(let i of Array.from(e.querySelectorAll('.board[data-lines="1"]'))){if(ie.has(i))continue;let n=()=>Ie(i);if(requestAnimationFrame(n),typeof ResizeObserver<"u"){let r=new ResizeObserver(n);r.observe(i),ie.set(i,r)}else ie.set(i,{disconnect(){}})}}function Ne(e,i,n){let r=i.get(),a=e.contains(document.activeElement)?document.activeElement:null,c=a?.id,u=a instanceof HTMLTextAreaElement||a instanceof HTMLInputElement?[a.selectionStart,a.selectionEnd]:null,o=xe(r);if(Ce(e,[we(r,n),ve(r,o,n),je(r,n),...r.agentOpen?[t("div",{class:"sheet-veil",on:{click:()=>n.toggleAgent()}}),kt(r,i,n)]:[],...r.drawer?[t("div",{class:"drawer-veil",on:{click:()=>n.toggleDrawer(null)}}),vt(r,i,n)]:[],...ue(r,n),jt(r)]),mt(e),c&&document.activeElement?.id!==c){let p=document.getElementById(c);p?.focus({preventScroll:!0}),u&&(p instanceof HTMLTextAreaElement||p instanceof HTMLInputElement)&&p.setSelectionRange(...u)}}function yt(e,i,n){let r=z(e.project,e.catalog,e.verified),a=r.filter(o=>o.step!=="absent"),c=r.filter(o=>o.step==="absent"),u=e.setup.running||e.busy.chat||e.busy.scan;return t("div",{},e.setup.open?he(e,i,n):null,t("section",{class:"block","aria-label":"In your app"},t("div",{class:"block-head"},t("h4",{},"In your app"),t("button",{id:"connect-my-app",class:"btn sm",disabled:u,on:{click:()=>n.openStackSetup()}},"Set up with your agent")),a.length?t("div",{class:"rail-grid"},...a.map(o=>bt(o,e,n))):t("p",{class:"drawer-empty"},"No services found in this code yet.")),c.length?t("section",{class:"block","aria-label":"Available services"},t("div",{class:"block-head"},t("h4",{},"Available"),t("span",{class:"block-meta"},"Your accounts, your choice of providers")),t("div",{class:"rail-grid"},...c.map(o=>t("article",{class:"slab available"},t("div",{class:"face"},t("div",{class:"face-logo"},t("img",{src:G(o),alt:"",loading:"lazy"})),t("h3",{class:"face-name"},o.name),t("div",{class:"face-area"},o.area)),t("div",{class:"slab-act"},t("button",{class:"btn library-add",disabled:u,"aria-label":`Add ${o.name} to setup`,on:{click:()=>{n.openStackSetup(),i.get().setup.selected.includes(o.id)||n.toggleSetupProvider(o.id),document.getElementById("stack-setup-heading")?.focus()}}},"+ Add to setup")))))):null)}function Mt(e){return e.step==="ready"?{text:`Agent reported checks passed ${e.verified?D(e.verified.at):""}.`,tone:"g"}:e.step==="verified"?{text:e.verified?.ok?`Agent check ${e.verified?D(e.verified.at):""}.`:"Agent check found issues.",tone:e.verified?.ok?"g":"a"}:e.step==="mcp"?{text:"Agent integration configured. Live check needed.",tone:"a"}:e.step==="in_repo"?{text:e.hasRecipe?"Found in your code. Not connected.":"Found in your code.",tone:"a"}:{text:"Not in this app.",tone:""}}function bt(e,i,n){let r=i.busy.tile===e.id,a=r||i.setup.running||i.busy.chat,c=Mt(e),u=e.step==="ready"?t("span",{class:"tag acid"},"Agent checked"):e.step==="verified"?t("span",{class:"tag"},e.verified?.ok?"Checked":"Issues"):e.step==="mcp"?t("span",{class:"tag"},"Configured"):t("span",{class:"tag"},"In code"),o=e.step==="in_repo"&&e.hasRecipe?t("button",{class:"btn primary",disabled:a,on:{click:()=>n.connect(e)}},r?t("span",{class:"spin"}):null,r?"Configuring\u2026":"Configure agent"):e.step==="in_repo"?t("button",{class:"btn",disabled:a,on:{click:()=>n.verify(e)}},"Check with agent"):e.step==="mcp"?t("button",{class:"btn",disabled:a,on:{click:()=>n.verify(e)}},r?t("span",{class:"spin"}):null,r?"Checking\u2026":"Check live"):t("button",{class:"btn",disabled:a,on:{click:()=>n.verify(e)}},r?t("span",{class:"spin"}):null,r?"Checking\u2026":"Check again"),p=At(e.logoUrl)??"#9a9a9a";return t("article",{class:`slab${e.step==="ready"?" ready":""}${r?" scanning":""}`,dataset:{provider:e.id},style:{"--brand":p}},t("div",{class:"face"},t("div",{class:"face-top"},u),t("div",{class:"face-logo"},t("img",{src:e.logoUrl,alt:"",loading:"lazy"})),t("div",{class:"face-name"},e.name),t("div",{class:"face-area"},e.area)),t("div",{class:`slab-status ${c.tone}`},t("i",{class:c.tone}),t("span",{class:"txt"},c.text),e.fixes>0?t("button",{class:"fixlink",on:{click:()=>n.focusBlockers(e.id)}},`${e.fixes} to fix`):null),t("div",{class:"slab-act"},o))}function re(e){return e.agents.find(i=>i.id===e.cliId)?.label.replace(/ CLI$/,"")??e.cliId}function kt(e,i,n){let r=e.agents.find(d=>d.id===e.cliId),a=e.probes[e.cliId],c=a?.ready===!0,u=r?.modelOptions??(r?.models??[]).map(d=>({id:d,label:d})),o=t("div",{class:"thread"},e.messages.length?e.messages.map(d=>wt(d,e,n)):t("div",{class:"welcome"},t("h3",{},"A little less setup. A lot more building."),t("p",{},"Start with Connect my app, or ask your agent to work on something specific."),t("div",{class:"suggest"},...["What does this app need next?","Check my service connections","Explain what changed since the last release"].map(d=>t("button",{class:"suggest-chip",disabled:!c||e.busy.chat||e.setup.running,on:{click:()=>n.send(d)}},d)))),e.busy.chat?t("div",{class:"working"},t("span",{class:"spin"}),t("span",{dataset:{working:"1"}},`${re(e)} is working\u2026`),t("button",{class:"btn sm stop",on:{click:()=>n.stop()}},t("i",{class:"sq"}),"Stop")):null,e.busy.chat?t("div",{class:"slow-run hint",hidden:!e.workingSince||Date.now()-e.workingSince<6e4,dataset:{slowRun:"1"}},t("p",{},"Taking longer than expected. CLI startup hooks or provider sign-in may be waiting. Stop this run and open Terminal to check your agent setup."),t("button",{class:"btn sm",on:{click:()=>n.toggleDrawer("terminal")}},"Open terminal")):null);(e.messages.length||e.busy.chat)&&queueMicrotask(()=>{o.scrollTop=o.scrollHeight});let p=e.contextProviderId?z(e.project,e.catalog,e.verified).find(d=>d.id===e.contextProviderId):null,s=t("textarea",{id:"agent-composer",placeholder:c?"Ask about this app, or tell the agent what to do\u2026":"Test the connection first, then chat.",rows:2,value:e.draft,disabled:e.busy.chat||e.setup.running,on:{input:d=>{i.get().draft=d.target.value},keydown:d=>{let f=d;f.key==="Enter"&&!f.shiftKey&&(f.preventDefault(),n.send(f.target.value))}}}),l=e.busy.probe===e.cliId;return t("aside",{id:"agent-panel",class:"side","aria-label":"Coding agent"},t("div",{class:"side-head"},t("span",{class:"who"},"Agent"),t("div",{class:"seg"},...(e.agents.length?e.agents:[]).map(d=>{let f=e.probes[d.id],y=f?.ready?"g":d.installed?"a":"";return t("button",{class:d.id===e.cliId?"on":"",disabled:e.setup.running||e.busy.chat,title:d.installed?f?.ready?"Connected":"Installed, not tested yet":"Not installed",on:{click:()=>n.selectCli(d.id)}},t("i",{class:y}),d.label.replace(/ CLI$/,"").replace("Claude Code","Claude"))}))),t("div",{class:"side-head tools"},u.length?t("label",{class:"model-field",for:"agent-model"},t("span",{},"Model"),t("select",{id:"agent-model",class:"sel",title:"Model",disabled:e.setup.running||e.busy.chat,on:{change:d=>i.set({modelId:d.target.value})}},t("option",{value:"",selected:!e.modelId},"Use agent default"),e.modelId&&!u.some(d=>d.id===e.modelId)?t("option",{value:e.modelId,selected:!0},`${e.modelId} (saved selection)`):null,...u.map(d=>t("option",{value:d.id,selected:d.id===e.modelId},d.label)))):null,e.cliId==="claude"?t("p",{class:"model-note"},"Versioned models. Availability depends on your Claude account and CLI."):null,t("div",{class:"agent-connection",role:"status"},l?t("span",{class:"pill"},t("span",{class:"spin"}),"Checking connection\u2026"):c?t("span",{class:"pill green",title:a?.message},t("i"),`${re(e).replace("Claude Code","Claude")} connected`):r&&!r.installed?t("span",{class:"pill amber",title:`${r.label} is not installed`},t("i"),"Not installed"):t("span",{class:"pill amber"},t("i"),"Not connected"),t("button",{id:"agent-test-connection",class:"connection-action",disabled:l||e.busy.chat||e.setup.running,on:{click:()=>n.testConnection(e.cliId)}},c?"Test again":"Test connection"))),o,a&&!a.ready?t("div",{class:"hint"},t("b",{},a.message)," ",t("button",{class:"btn sm",on:{click:()=>n.toggleDrawer("terminal")}},"Open terminal")):null,t("div",{class:"composer"},s,t("div",{class:"row"},p?t("span",{class:"chip"},p.logoUrl?t("img",{src:p.logoUrl,alt:""}):null,p.name,t("button",{title:"Remove context","aria-label":"Remove context",on:{click:()=>i.set({contextProviderId:null})},html:'<svg width="10" height="10" viewBox="0 0 10 10" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M1.5 1.5l7 7M8.5 1.5l-7 7"/></svg>'})):null,t("select",{id:"agent-access",class:"sel mode","aria-label":"Agent access",title:"What the agent may do",disabled:e.setup.running||e.busy.chat,on:{change:d=>n.setAccessMode(d.target.value)}},...["ask","approve","full"].map(d=>t("option",{value:d,selected:d===e.accessMode},d==="ask"?"Ask \xB7 plan only":d==="approve"?"Approve \xB7 edit files":"Full access"))),e.busy.chat?t("button",{class:"btn send stop",title:"Stop","aria-label":"Stop",on:{click:()=>n.stop()},html:'<svg width="14" height="14" viewBox="0 0 14 14"><rect x="2" y="2" width="10" height="10" rx="2" fill="currentColor"/></svg>'}):t("button",{class:"btn send",title:"Send","aria-label":"Send",disabled:!c||e.setup.running,on:{click:()=>n.send(s.value)},html:'<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 13V3M3.5 7.5 8 3l4.5 4.5"/></svg>'}))))}function Te(e,i,n=Date.now()){if(!i)return;let r=Math.max(0,Math.floor((n-i)/1e3)),a=e.querySelector("[data-working]");a&&(a.textContent=`${a.textContent?.split(" \xB7")[0]??"Working\u2026"} \xB7 ${r}s`);let c=e.querySelector("[data-slow-run]");c&&(c.hidden=r<60)}function wt(e,i,n){let r=e.role==="me"?"You":e.role==="agent"?i.agents.find(c=>c.id===e.cliId)?.label.replace(/ CLI$/,"").replace("Claude Code","Claude")??"Agent":e.role==="error"?"Something went wrong":"VibeRaven",a=e.card?t("div",{class:"card"},t("span",{},e.card.providerId?t("img",{src:z(i.project,i.catalog,i.verified).find(c=>c.id===e.card?.providerId)?.logoUrl??"",alt:""}):null,e.card.label),e.card.action==="verify"&&e.card.providerId?t("button",{class:"btn sm primary",disabled:i.busy.chat||i.setup.running,on:{click:()=>n.verifyById(e.card.providerId)}},"Verify live"):e.card.action==="recheck"?t("button",{class:"btn sm",disabled:i.busy.scan,on:{click:()=>n.recheck()}},"Re-check"):null):null;return t("div",{class:`msg ${e.role==="me"?"me":e.role==="error"?"err":""}`},t("div",{class:"who"},r,t("span",{class:"t"},D(e.at))),t("div",{class:"body",html:e.role==="me"?`<p>${Y(e.text)}</p>`:H(e.text)}),a)}function vt(e,i,n){let r=e.drawer==="terminal"?St(e,n):e.drawer==="services"?yt(e,i,n):It(e,i,n),a=e.drawer==="terminal"?"Coding agents":e.drawer==="services"?"Services":"Releases",c=e.drawer==="terminal"?"VibeRaven drives the agent CLI installed on this computer. Installed is not connected: test each one.":e.drawer==="services"?"What your app runs on, and what you could add. Check a service live through your agent.":"Release points in this repository, and the real diff between any two of them.";return t("div",{class:"drawer",dataset:{drawer:e.drawer??""},role:"dialog","aria-modal":"true","aria-labelledby":"drawer-heading",on:{keydown:u=>{let o=u;if(o.key==="Escape"&&(o.preventDefault(),o.stopPropagation(),n.toggleDrawer(null)),o.key!=="Tab")return;let p=Array.from(u.currentTarget.querySelectorAll("*")).filter(d=>d.matches('button:not(:disabled), input:not(:disabled), a[href], select:not(:disabled), [tabindex="0"]')),s=p[0],l=p[p.length-1];o.shiftKey&&document.activeElement===s&&(o.preventDefault(),l?.focus()),!o.shiftKey&&document.activeElement===l&&(o.preventDefault(),s?.focus())}}},t("div",{class:"drawer-head"},t("div",{class:"drawer-title"},t("h3",{id:"drawer-heading"},a),t("p",{},c)),t("button",{id:"drawer-close",class:"quiet",on:{click:()=>n.toggleDrawer(null)}},"Close")),t("div",{class:"drawer-body"},r))}function se(e,i,n,r,...a){return t("li",{class:`step${n?" done":""}`},t("span",{class:"step-n","aria-hidden":"true"},n?"\u2713":String(e)),t("div",{class:"step-body"},t("div",{class:"step-title"},i,t("span",{class:`step-state${n?" ok":""}`},n?"Done":"Not confirmed")),t("p",{},r),a.some(Boolean)?t("div",{class:"row step-row"},...a):null))}function St(e,i){return t("div",{},...e.agents.map(n=>{let r=e.probes[n.id],a=r?.ready===!0,c=e.busy.probe===n.id;return t("section",{class:"block agent-block","aria-label":n.label},t("div",{class:"block-head"},t("h4",{},n.label),t("span",{class:`pill ${a?"green":n.installed?"amber":"gray"}`},t("i"),a?"Connected":n.installed?"Installed \xB7 not tested":"Not installed"),t("a",{class:"btn sm ghost",style:{marginLeft:"auto"},href:n.setup.docsUrl,target:"_blank",rel:"noreferrer"},"Docs")),t("ol",{class:"steps"},se(1,"Install the CLI",n.installed,n.installed?`Found on this computer as ${n.command}.`:`Not found on this computer. Install command: ${n.setup.installCommand}`,n.installed?null:t("button",{class:"btn sm primary",on:{click:()=>i.runSetup(n.id,"install")}},"Install here")),se(2,"Sign in to your account",a,a?"Confirmed by the last connection test.":`VibeRaven cannot read your CLI session. Sign in with ${n.setup.signInCommand}, then test below.`,t("button",{class:"btn sm",on:{click:()=>i.openTerminal(n.id,"sign-in")}},"Open a terminal to sign in")),se(3,"Test the connection",a,r?.message??`Not tested in this session. VibeRaven runs ${n.setup.verifyCommand} and reads the result.`,t("button",{class:"btn sm",disabled:c,on:{click:()=>i.testConnection(n.id)}},c?t("span",{class:"spin"}):null,c?"Testing\u2026":a?"Test again":"Test connection"))))}),t("section",{class:"block","aria-label":"Terminal output"},t("div",{class:"block-head"},t("h4",{},"Terminal output"),t("span",{class:"block-meta"},"From the last install, sign-in or connection test")),t("pre",{class:"out",dataset:{terminalOut:"1"}},e.terminalOutput||"Nothing yet. Run a step above and the raw output appears here.")))}function It(e,i,n){let r=e.project.releases??[],a=t("input",{id:"release-from",class:"sel","aria-label":"From revision",placeholder:"Tag, commit or branch",value:e.compare.from,on:{input:p=>{i.get().compare.from=p.target.value}}}),c=t("input",{id:"release-to",class:"sel","aria-label":"To revision",placeholder:"HEAD",value:e.compare.to,on:{input:p=>{i.get().compare.to=p.target.value}}}),u=e.compare.result,o=u?.stats;return t("div",{},t("section",{class:"block","aria-label":"Release history"},t("div",{class:"block-head"},t("h4",{},"History"),t("span",{class:"block-meta"},r.length?`${r.length} release point${r.length===1?"":"s"} \xB7 branch ${r[0].branch}`:"Nothing tagged yet")),r.length?t("ul",{class:"rel-list"},...r.map(p=>t("li",{class:"rel"},t("div",{class:"rel-main"},t("div",{class:"rel-line"},t("span",{class:"lbl"},p.label),t("span",{class:`tag ${p.tone==="current"?"amber":"dim"}`},p.tone==="current"?"Current":p.tone==="prod"?"Released":"Planned")),t("p",{class:"rel-sum"},p.summary),t("p",{class:"rel-meta"},`${p.meta} \xB7 ${p.branch}`)),t("button",{class:"btn sm ghost",on:{click:()=>{i.set({compare:{...i.get().compare,from:p.id}}),document.getElementById("release-from")?.focus()}}},"Compare from here")))):t("p",{class:"drawer-empty"},"No git tags yet. Tag a release (git tag v1.0.0) and it shows up here. You can still compare any branch or commit below.")),t("section",{class:"block","aria-label":"Compare"},t("div",{class:"block-head"},t("h4",{},"Compare two points"),t("span",{class:"block-meta"},"Any tag, branch or commit in this repository")),t("div",{class:"row compare-fields"},t("label",{},"From",a),t("label",{},"To",c),t("div",{class:"compare-actions"},t("button",{class:"btn sm primary",disabled:e.busy.compare,on:{click:()=>n.compare(a.value,c.value)}},e.busy.compare?t("span",{class:"spin"}):null,e.busy.compare?"Reading\u2026":"Diff"),t("button",{class:"btn sm",disabled:e.busy.chat||e.setup.running,on:{click:()=>n.explainDiff(a.value,c.value)}},`Explain with ${re(e)}`))),e.compare.error?t("p",{class:"compare-error",role:"alert"},e.compare.error):null,u?t("div",{class:"diff-result"},t("div",{class:"diff-stats"},t("span",{class:"diff-range"},`${u.fromLabel} \u2192 ${u.toLabel}`),o?t("span",{},`${o.files??0} file${o.files===1?"":"s"}`):null,o?t("span",{class:"add"},`+${o.insertions??0}`):null,o?t("span",{class:"del"},`\u2212${o.deletions??0}`):null),t("pre",{class:"out diff",tabindex:0,role:"region","aria-label":"Diff output",html:Lt(u.diff)})):t("p",{class:"drawer-empty"},"Pick two points and select Diff. The output is read straight from git \u2014 nothing is sent anywhere.")))}function At(e){let i=/cdn\.simpleicons\.org\/[a-z0-9.-]+\/([0-9a-f]{6})/i.exec(e);if(!i)return null;let n=i[1].toLowerCase();return n==="ffffff"?"#c8c8c8":`#${n}`}function Lt(e){return e.split(`
7
7
  `).map(i=>{let n=Y(i);return i.startsWith("+++")||i.startsWith("---")||i.startsWith("diff ")||i.startsWith("@@")?`<span class="hd">${n}</span>`:i.startsWith("+")?`<span class="add">${n}</span>`:i.startsWith("-")?`<span class="del">${n}</span>`:n}).join(`
@@ -10,7 +10,8 @@
10
10
 
11
11
  ${Oe(M.stderr,1200)}`);return!w||N?e.push({role:"error",text:h,cliId:s.cliId}):e.push({role:"agent",text:h,cliId:s.cliId,card:d}),(s.taskKind==="fix"||s.taskKind==="plan")&&await a().catch(()=>{}),N||!w?null:h}catch(m){return e.push({role:"error",text:A(m)}),null}finally{e.set({busy:{...e.get().busy,chat:!1},workingSince:null,runId:null})}}function u(){queueMicrotask(()=>document.getElementById("stage-heading")?.focus({preventScroll:!0}))}function o(){let s=e.get();return{cliId:s.cliId,accessMode:s.accessMode,modelId:s.modelId||void 0}}let p={...ce(e),setSection(s){e.get().setup.running||(e.set(l=>({section:s,setup:{...l.setup,open:!1}})),document.getElementById(`tab-${s}`)?.focus({preventScroll:!0}))},toggleAgent(){let s=!e.get().agentOpen;e.set({agentOpen:s}),document.getElementById(s?"agent-composer":"open-more")?.focus({preventScroll:!0}),s&&document.getElementById("agent-panel")?.scrollIntoView?.({behavior:"smooth",block:"nearest"})},openStackSetup(){let s=e.get();e.set({section:"stack",drawer:"services",moreOpen:!1,setup:{...s.setup,open:!0,initialized:s.setup.initialized||s.catalog.length>0,selected:s.setup.initialized?s.setup.selected:ae(s.catalog)}}),document.getElementById("stack-setup-heading")?.focus({preventScroll:!0})},toggleSetupProvider(s){let l=e.get();if(l.setup.running)return;let d=l.setup.selected.includes(s)?l.setup.selected.filter(f=>f!==s):[...l.setup.selected,s];e.set({setup:{...l.setup,initialized:!0,selected:d,progress:[],error:null}})},async startStackSetup(){let s=e.get();if(s.setup.running||s.busy.chat||s.busy.tile||s.busy.scan)return;if(r(!s.probes[s.cliId]?.ready),!s.probes[s.cliId]?.ready){e.toast(`Connect ${s.cliId} in the agent panel first.`,"err");return}let l=s.catalog.filter(f=>s.setup.selected.includes(f.id));if(!l.length){e.toast("Select at least one service.","err");return}let d=o();i=!1,e.set({setup:{...s.setup,running:!0,progress:[],error:null}});try{await De({providers:l,mode:d.accessMode,connect:f=>b.connectMcp(f),cancelled:()=>i,onProgress:f=>e.set(y=>({setup:{...y.setup,progress:[...y.setup.progress.filter(g=>g.id!==f.id),f]}})),runAgent:f=>c({...d,taskKind:d.accessMode==="ask"?"plan":"fix",prompt:f},`${d.accessMode==="ask"?"Plan":"Set up"} my stack: ${l.map(y=>y.name).join(", ")}`,{label:"Review the response, then check your app",action:"recheck"})})}catch(f){e.set(y=>({setup:{...y.setup,error:A(f)}}))}finally{await a().catch(()=>{}),e.set(f=>({setup:{...f.setup,running:!1}}))}},async stop(){e.get().setup.running&&(i=!0);let s=e.get().runId;if(s)try{await b.stop(s),e.toast("Stopped.")}catch(l){e.toast(A(l),"err")}},async recheck(){if(!(e.get().setup.running||e.get().busy.chat||e.get().busy.scan)){e.set({busy:{...e.get().busy,scan:!0}});try{await b.scan(),await a(),e.toast("Check finished.")}catch(s){e.toast(`Check failed: ${A(s)}`,"err")}finally{e.set({busy:{...e.get().busy,scan:!1}})}}},toggleDrawer(s){let l=e.get().drawer;e.set(d=>({drawer:d.drawer===s?null:s})),document.getElementById(e.get().drawer?"drawer-close":"open-more")?.focus({preventScroll:!0})},selectCli(s){if(e.get().setup.running||e.get().busy.chat)return;e.set({cliId:s,modelId:""}),e.get().agents.find(d=>d.id===s)?.installed&&!e.get().probes[s]&&p.testConnection(s)},setAccessMode(s){e.get().setup.running||e.get().busy.chat||e.set({accessMode:s})},async testConnection(s,l){if(!n.has(s)){n.add(s),e.set({busy:{...e.get().busy,probe:s}});try{let d=await b.probe(s);e.set(f=>({probes:{...f.probes,[s]:d},terminalOutput:d.output||d.message})),l?.silent||e.toast(d.message,d.ready?"ok":"err")}catch(d){e.set(f=>{let y={...f.probes};return delete y[s],{probes:y}}),e.toast(A(d),"err")}finally{n.delete(s),e.set(d=>({busy:{...d.busy,probe:d.busy.probe===s?null:d.busy.probe}}))}}},async runSetup(s,l){e.set({terminalOutput:`$ ${l}\u2026`});try{let d=await b.runSetup(s,l);e.set({terminalOutput:`$ ${d.command}
12
12
  ${d.output}`.trim()});let f=await b.agents();e.set({agents:f.agents.filter(y=>y.id==="codex"||y.id==="claude"||y.id==="gemini")})}catch(d){e.set({terminalOutput:A(d)})}},async openTerminal(s,l){try{let d=await b.openTerminal(s,l);e.set({terminalOutput:`Opened a terminal with: ${d.command}
13
- Sign in there, then press Test connection.`})}catch(d){e.toast(A(d),"err")}},async send(s){if(e.get().setup.running)return;let l=s.trim();if(!l)return;let d=e.get(),f=d.contextProviderId?d.catalog.find(y=>y.id===d.contextProviderId):null;await c({...o(),prompt:l,taskKind:"analyze",provider:f?{id:f.id,name:f.name,area:f.area}:void 0},l)},async connect(s){if(!(e.get().setup.running||e.get().busy.chat||e.get().busy.tile)){r(),e.set({busy:{...e.get().busy,tile:s.id}});try{let l=await b.connectMcp(s.id);e.toast(l.message,l.ok?"ok":"err"),await a(),l.ok&&e.push({role:"system",text:`${l.message} ${s.note??""}`.trim(),card:{providerId:s.id,label:`${s.name} \xB7 MCP configured`,action:"verify"}})}catch(l){e.toast(A(l),"err")}finally{e.set({busy:{...e.get().busy,tile:null}})}}},async verify(s){return p.verifyById(s.id)},async verifyById(s){let l=e.get();if(l.setup.running||l.busy.chat||l.busy.tile)return;let f=(l.catalog.find(m=>m.id===s)??l.project.providers.find(m=>m.id===s))?.name??s,y=l.probes[l.cliId];if(r(!y?.ready),!y?.ready){e.toast(`Test the ${l.cliId} connection first.`,"err");return}e.push({role:"me",text:`Check ${f} live`});let g=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;e.set({busy:{...e.get().busy,tile:s,chat:!0},workingSince:Date.now(),runId:g});try{let m=await b.verify({providerId:s,...o(),runId:g}),M=m.agentRun.output?.trim()||m.agentRun.stderr?.trim()||"No output.";e.push({role:"agent",text:M,cliId:l.cliId,card:{providerId:s,label:m.verified.ok?`${f} \xB7 verified live`:`${f} \xB7 issues found`}}),await a()}catch(m){e.push({role:"error",text:A(m)})}finally{e.set({busy:{...e.get().busy,tile:null,chat:!1},workingSince:null,runId:null})}},async addProvider(s){e.get().setup.running||await c({...o(),taskKind:"fix",provider:{id:s.id,name:s.name,area:s.area},prompt:`Add ${s.name} (${s.area}) to this app. Install the official SDK, wire the minimal integration the app needs, add the required keys to .env.example with placeholder values, and never invent real secrets. Then tell me exactly which dashboard steps remain.`},`Add ${s.name} to this app`,{providerId:s.id,label:`${s.name} \xB7 added to repo`,action:"recheck"})},async fix(s,l){if(e.get().setup.running)return;let d=l?.provider?.nextFix?.id===s.id&&l.provider.nextFix.prompt?l.provider.nextFix.prompt:`Fix this production blocker in the repo now: ${s.title}. ${s.detail??""} Make the minimal change, then summarize what you changed and which files.`;await c({...o(),taskKind:"fix",provider:l?{id:l.id,name:l.name,area:l.area}:void 0,prompt:d},`Fix: ${s.title}`,{providerId:l?.id,label:"Re-check to update the score",action:"recheck"})},async explain(s,l){e.get().setup.running||await c({...o(),taskKind:"analyze",provider:l?{id:l.id,name:l.name,area:l.area}:void 0,prompt:`This blocker needs dashboard work: ${s.title}. ${s.detail??""} Give me the exact steps: which page, which button, which value. If a provider MCP is available, do the read-only parts yourself first.`},`Steps for: ${s.title}`)},async fixAll(){if(e.get().setup.running)return;let{missionCards:s}=e.get().project,l=s.blockers.filter(d=>s.planSteps.some(f=>f.id===d.id&&!f.requiresUserAction));l.length&&await c({...o(),taskKind:"fix",prompt:`Fix these production blockers in the repo, one by one, minimal changes each:
13
+ Sign in there, then press Test connection.`})}catch(d){e.toast(A(d),"err")}},async send(s){if(e.get().setup.running)return;let l=s.trim();if(!l)return;let d=e.get(),f=d.contextProviderId?d.catalog.find(y=>y.id===d.contextProviderId):null;await c({...o(),prompt:l,taskKind:"analyze",provider:f?{id:f.id,name:f.name,area:f.area}:void 0},l)},async connect(s){if(!(e.get().setup.running||e.get().busy.chat||e.get().busy.tile)){r(),e.set({busy:{...e.get().busy,tile:s.id}});try{let l=await b.connectMcp(s.id);e.toast(l.message,l.ok?"ok":"err"),await a(),l.ok&&e.push({role:"system",text:`${l.message} ${s.note??""}`.trim(),card:{providerId:s.id,label:`${s.name} \xB7 MCP configured`,action:"verify"}})}catch(l){e.toast(A(l),"err")}finally{e.set({busy:{...e.get().busy,tile:null}})}}},async verify(s){return p.verifyById(s.id)},async verifyById(s){let l=e.get();if(l.setup.running||l.busy.chat||l.busy.tile)return;let f=(l.catalog.find(m=>m.id===s)??l.project.providers.find(m=>m.id===s))?.name??s,y=l.probes[l.cliId];if(r(!y?.ready),!y?.ready){e.toast(`Test the ${l.cliId} connection first.`,"err");return}e.push({role:"me",text:`Check ${f} live`});let g=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;e.set({busy:{...e.get().busy,tile:s,chat:!0},workingSince:Date.now(),runId:g});try{let m=await b.verify({providerId:s,...o(),runId:g}),M=m.agentRun.output?.trim()||m.agentRun.stderr?.trim()||"No output.";e.push({role:"agent",text:M,cliId:l.cliId,card:{providerId:s,label:m.verified.ok?`${f} \xB7 verified live`:`${f} \xB7 issues found`}}),await a()}catch(m){e.push({role:"error",text:A(m)})}finally{e.set({busy:{...e.get().busy,tile:null,chat:!1},workingSince:null,runId:null})}},async addProvider(s){e.get().setup.running||await c({...o(),taskKind:"fix",provider:{id:s.id,name:s.name,area:s.area},prompt:`Add ${s.name} (${s.area}) to this app. Install the official SDK, wire the minimal integration the app needs, add the required keys to .env.example with placeholder values, and never invent real secrets. Then tell me exactly which dashboard steps remain.`},`Add ${s.name} to this app`,{providerId:s.id,label:`${s.name} \xB7 added to repo`,action:"recheck"})},async fix(s,l){if(e.get().setup.running)return;let d=l?.provider?.nextFix?.id===s.id&&l.provider.nextFix.prompt?l.provider.nextFix.prompt:`Fix this production blocker in the repo now: ${s.title}. ${s.detail??""} Make the minimal change, then summarize what you changed and which files.`,f=s.asksFirst?`${s.asksFirst} Tell the user this before you change anything, and make the change only if they confirm.
14
+ ${d}`:d;await c({...o(),taskKind:"fix",provider:l?{id:l.id,name:l.name,area:l.area}:void 0,prompt:f},`Fix: ${s.title}`,{providerId:l?.id,label:"Re-check to update the score",action:"recheck"})},async explain(s,l){e.get().setup.running||await c({...o(),taskKind:"analyze",provider:l?{id:l.id,name:l.name,area:l.area}:void 0,prompt:`This blocker needs dashboard work: ${s.title}. ${s.detail??""} Give me the exact steps: which page, which button, which value. If a provider MCP is available, do the read-only parts yourself first.`},`Steps for: ${s.title}`)},async fixAll(){if(e.get().setup.running)return;let{missionCards:s}=e.get().project,l=s.blockers.filter(d=>!d.asksFirst&&s.planSteps.some(f=>f.id===d.id&&!f.requiresUserAction&&!f.asksFirst));l.length&&await c({...o(),taskKind:"fix",prompt:`Fix these production blockers in the repo, one by one, minimal changes each:
14
15
  ${l.map((d,f)=>`${f+1}. ${d.title}`).join(`
15
16
  `)}
16
17
  After each, note the files touched. Do not claim production-ready; I will re-check.`},`Fix all ${l.length} repo blockers`,{label:"Re-check to update the score",action:"recheck"})},focusBlockers(s){if(!S(e.get()).available.findings)return;e.set(d=>({section:"findings",drawer:null,contextProviderId:s,setup:{...d.setup,open:!1},flow:{...d.flow,step:"findings"}}));let l=Array.from(document.querySelectorAll(".finding")).find(d=>d.dataset.provider===s)??document.getElementById("stage-heading");l?.focus({preventScroll:!0}),l?.scrollIntoView?.({behavior:"smooth",block:"center"})},async compare(s,l){if(!s.trim()||!l.trim()){e.set({compare:{...e.get().compare,error:"Both refs are required."}});return}e.set({busy:{...e.get().busy,compare:!0},compare:{...e.get().compare,from:s,to:l,error:null}});try{let d=await b.compare(s.trim(),l.trim());e.set({compare:{from:s,to:l,result:d,error:null}})}catch(d){e.set({compare:{from:s,to:l,result:null,error:A(d)}})}finally{e.set({busy:{...e.get().busy,compare:!1}})}},async explainDiff(s,l){e.get().setup.running||await c({...o(),taskKind:"diff",release:{id:`${s.trim()}..${l.trim()}`,label:`${s.trim()} \u2192 ${l.trim()}`},prompt:`Explain what changed between ${s.trim()} and ${l.trim()} in this repo, in plain words. Call out anything risky for production: auth, database writes, webhooks, env, payments.`},`Explain ${s.trim()} \u2192 ${l.trim()}`)},goToStep(s){let l=S(e.get());l.available[s]&&(s==="fix"&&!l.current&&e.flow({fixId:l.fixable[0]?.id??null,handoff:null}),e.flow({step:s}),u())},async checkMyApp(){let s=e.get();if(!(s.busy.scan||s.setup.running)){e.set({busy:{...s.busy,scan:!0}});try{await b.scan(),await a();let l=S(e.get());e.flow({step:te(l),fixId:null,handoff:null,recheck:null}),u()}catch(l){e.toast(`The check did not finish: ${A(l)}`,"err")}finally{e.set({busy:{...e.get().busy,scan:!1}})}}},fixFinding(s){let l=S(e.get()),d=s?l.fixable.find(f=>f.id===s):l.fixable[0];d&&(e.flow({step:"fix",fixId:d.id,handoff:e.get().flow.handoff?.findingId===d.id?e.get().flow.handoff:null}),u())},async sendFix(){let s=e.get(),l=S(s).current;if(!l||s.busy.chat||s.setup.running||!s.probes[s.cliId]?.ready&&(await p.testConnection(s.cliId),!e.get().probes[s.cliId]?.ready))return;let d=e.get().cliId,f=`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;e.set({busy:{...e.get().busy,chat:!0},workingSince:Date.now(),runId:f}),e.flow({handoff:{findingId:l.id,cliId:d,status:"running",output:""}}),e.push({role:"me",text:`Fix: ${l.title}`});try{let g=(await b.chat({...o(),runId:f,taskKind:"fix",prompt:l.prompt,displayPrompt:`Fix: ${l.title}`,provider:l.service?{id:l.service.id,name:l.service.name,area:""}:void 0})).agentRun,m=/Stopped by user/.test(g.stderr??""),M=g.timedOut||m||g.exitCode!==null&&g.exitCode!==0||!g.output?.trim(),w=g.output?.trim()||(m?"Stopped.":g.timedOut?`${d} did not finish in time and was stopped.`:`${d} exited with code ${g.exitCode??"unknown"} and no answer.
package/package.json CHANGED
@@ -1,84 +1,84 @@
1
- {
2
- "name": "@viberaven/cli",
3
- "version": "1.5.1",
4
- "description": "Local Studio cockpit for AI-built apps: agentic chat, provider context, release review, diffs, and approval-controlled repo work.",
5
- "license": "MIT",
6
- "author": "VibeRaven",
7
- "homepage": "https://viberaven.dev",
8
- "bugs": {
9
- "url": "https://github.com/ohad6k/VibeRaven/issues"
10
- },
11
- "repository": {
12
- "type": "git",
13
- "url": "git+https://github.com/ohad6k/VibeRaven.git",
14
- "directory": "packages/cli"
15
- },
16
- "keywords": [
17
- "viberaven",
18
- "launch-readiness",
19
- "production-readiness",
20
- "launch-gaps",
21
- "ai-built-apps",
22
- "agent-mode",
23
- "mcp",
24
- "claude-code",
25
- "codex",
26
- "cursor",
27
- "ai",
28
- "production",
29
- "supabase",
30
- "vercel",
31
- "stripe"
32
- ],
33
- "publishConfig": {
34
- "access": "public",
35
- "tag": "latest"
36
- },
37
- "bin": {
38
- "viberaven": "dist/cli.js"
39
- },
40
- "files": [
41
- "dist",
42
- "playbooks",
43
- "AGENTS.md",
44
- "SECURITY.md",
45
- "templates",
46
- "schemas"
47
- ],
48
- "scripts": {
49
- "sync-report-assets": "node scripts/sync-report-assets.mjs",
50
- "build": "node scripts/build.mjs",
51
- "dev": "node scripts/build.mjs && node dist/cli.js",
52
- "typecheck": "tsc -p tsconfig.json",
53
- "demo-report": "node scripts/demo-report.mjs --open",
54
- "verify:release:smoke": "npm run build && node scripts/verify-beta-flow.mjs --smoke",
55
- "verify:release:live": "npm run build && node scripts/verify-beta-flow.mjs --live",
56
- "test": "vitest run",
57
- "prepublishOnly": "npm run sync-report-assets && npm run check:agent-discovery && npm run typecheck && npm run test && npm run build",
58
- "check:agent-discovery": "node scripts/check-agent-discovery.mjs",
59
- "viberaven:gate": "npx -y viberaven --agent-mode",
60
- "viberaven:verify": "npx -y viberaven --verify",
61
- "viberaven:strict": "npx -y viberaven --strict"
62
- },
63
- "engines": {
64
- "node": ">=20"
65
- },
66
- "dependencies": {
67
- "@clack/prompts": "^0.10.1",
68
- "picocolors": "^1.1.1"
69
- },
70
- "peerDependencies": {
71
- "@electric-sql/pglite": ">=0.5.8 <0.6.0"
72
- },
73
- "peerDependenciesMeta": {
74
- "@electric-sql/pglite": {
75
- "optional": true
76
- }
77
- },
78
- "devDependencies": {
79
- "@electric-sql/pglite": "0.5.8",
80
- "esbuild": "^0.25.0",
81
- "typescript": "^5.8.0",
82
- "vitest": "^3.2.0"
83
- }
84
- }
1
+ {
2
+ "name": "@viberaven/cli",
3
+ "version": "1.5.3",
4
+ "description": "Local Studio cockpit for AI-built apps: agentic chat, provider context, release review, diffs, and approval-controlled repo work.",
5
+ "license": "MIT",
6
+ "author": "VibeRaven",
7
+ "homepage": "https://viberaven.dev",
8
+ "bugs": {
9
+ "url": "https://github.com/ohad6k/VibeRaven/issues"
10
+ },
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/ohad6k/VibeRaven.git",
14
+ "directory": "packages/cli"
15
+ },
16
+ "keywords": [
17
+ "viberaven",
18
+ "launch-readiness",
19
+ "production-readiness",
20
+ "launch-gaps",
21
+ "ai-built-apps",
22
+ "agent-mode",
23
+ "mcp",
24
+ "claude-code",
25
+ "codex",
26
+ "cursor",
27
+ "ai",
28
+ "production",
29
+ "supabase",
30
+ "vercel",
31
+ "stripe"
32
+ ],
33
+ "publishConfig": {
34
+ "access": "public",
35
+ "tag": "latest"
36
+ },
37
+ "bin": {
38
+ "viberaven": "dist/cli.js"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "playbooks",
43
+ "AGENTS.md",
44
+ "SECURITY.md",
45
+ "templates",
46
+ "schemas"
47
+ ],
48
+ "scripts": {
49
+ "sync-report-assets": "node scripts/sync-report-assets.mjs",
50
+ "build": "node scripts/build.mjs",
51
+ "dev": "node scripts/build.mjs && node dist/cli.js",
52
+ "typecheck": "tsc -p tsconfig.json",
53
+ "demo-report": "node scripts/demo-report.mjs --open",
54
+ "verify:release:smoke": "npm run build && node scripts/verify-beta-flow.mjs --smoke",
55
+ "verify:release:live": "npm run build && node scripts/verify-beta-flow.mjs --live",
56
+ "test": "vitest run",
57
+ "prepublishOnly": "npm run sync-report-assets && npm run check:agent-discovery && npm run typecheck && npm run test && npm run build",
58
+ "check:agent-discovery": "node scripts/check-agent-discovery.mjs",
59
+ "viberaven:gate": "npx -y viberaven --agent-mode",
60
+ "viberaven:verify": "npx -y viberaven --verify",
61
+ "viberaven:strict": "npx -y viberaven --strict"
62
+ },
63
+ "engines": {
64
+ "node": ">=20"
65
+ },
66
+ "dependencies": {
67
+ "@clack/prompts": "^0.10.1",
68
+ "picocolors": "^1.1.1"
69
+ },
70
+ "peerDependencies": {
71
+ "@electric-sql/pglite": ">=0.5.8 <0.6.0"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "@electric-sql/pglite": {
75
+ "optional": true
76
+ }
77
+ },
78
+ "devDependencies": {
79
+ "@electric-sql/pglite": "0.5.8",
80
+ "esbuild": "^0.25.0",
81
+ "typescript": "^5.8.0",
82
+ "vitest": "^3.2.0"
83
+ }
84
+ }
@@ -1,8 +1,8 @@
1
1
  ## VibeRaven Launch Readiness
2
2
 
3
- VibeRaven is the Agent Context + Production Gate.
3
+ VibeRaven reads a repository and lists launch gaps for AI-built apps that deploy on Vercel and use Supabase. It runs locally: no login, no API key, no telemetry.
4
4
 
5
- Use VibeRaven when the user asks if their AI-built app is production-ready, launch-ready, safer to deploy, or what is missing before ship.
5
+ Use it when the user asks whether a Vercel + Supabase app built with an AI tool is ready to launch or hand off, or wants to find migrations that create tables without RLS. This is advice, not a gate: the user decides when to ship. It is a repository check, not a live database test.
6
6
 
7
7
  ### Humans
8
8
 
@@ -10,28 +10,24 @@ Use VibeRaven when the user asks if their AI-built app is production-ready, laun
10
10
  npx -y viberaven
11
11
  ```
12
12
 
13
- In a real terminal, this opens the interactive VibeRaven menu.
13
+ This opens the local Studio. `npx -y viberaven check` prints a terminal verdict.
14
14
 
15
15
  ### Agents
16
16
 
17
- Paste this into your coding agent:
18
-
19
17
  ```bash
20
18
  npx -y viberaven --agent-mode
21
19
  ```
22
20
 
23
21
  1. Run `npx -y viberaven --agent-mode` from the project root.
24
- 2. If VibeRaven prints `LOGIN_URL_READY`, open that exact URL for the user. Say: "I opened VibeRaven sign-in so you can approve access; I will continue after approval." Do not ask for passwords, tokens, cookies, or secrets. Keep the terminal alive while the user approves.
25
- If the scan flow cannot start login, run `npx -y viberaven login`.
26
- 3. Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the machine verdict, and `.viberaven/context-map.json` for compact agent context. If the tasklist says `CRITICAL GAPS DETECTED` or `PRODUCTION GATE NOT CLEAR`, fix one listed repo-code gap before deploy.
27
- 4. Read `.viberaven/agent-summary.md` second for scan context.
28
- 5. Read `.viberaven/launch-playbook.md` third for the full checklist.
29
- 6. Use `npx -y viberaven next --json` or `npx -y viberaven prompt --gap <id>` for one focused repo-code fix. Local installs can use `viberaven prompt`.
30
- 7. For Vercel + Supabase, run `npx -y viberaven audit --vercel-supabase` and check RLS, service role exposure, and Supabase pooler port 6543 instead of runtime port 5432.
31
- 8. Do not claim provider dashboard checks are fixed by repo-code edits.
32
- 9. Verify with tests/build, then run `npx -y viberaven --verify`.
33
-
34
- Before deploy or CI pass:
22
+ 2. Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the verdict (`clear`, `warning` or `not_clear`), and `.viberaven/context-map.json` for compact agent context.
23
+ 3. Read `.viberaven/agent-summary.md` second for scan context.
24
+ 4. Read `.viberaven/launch-playbook.md` third for the full checklist.
25
+ 5. Use `npx -y viberaven next --json` or `npx -y viberaven prompt --gap <id>` for one focused repo-code fix. Local installs can use `viberaven prompt`.
26
+ 6. For Vercel + Supabase, run `npx -y viberaven audit --vercel-supabase` and check RLS, service role exposure, and Supabase pooler port 6543 instead of runtime port 5432.
27
+ 7. Do not claim provider dashboard checks are fixed by repo-code edits.
28
+ 8. After a batch of fixes, run tests/build, then `npx -y viberaven --verify`.
29
+
30
+ For a CI verdict when the user wants one:
35
31
 
36
32
  ```bash
37
33
  npx -y viberaven --strict
@@ -44,9 +40,17 @@ Also available:
44
40
  - `npx -y viberaven init --dry-run` - preview local agent rules
45
41
  - `npx -y viberaven clean --plan` - write a non-destructive cleanup plan
46
42
 
47
- Free plan: 2 lifetime scans, 6/12 mission map lanes. Pro: 50 scans/month, all 12 lanes.
48
-
49
- Same VibeRaven account and scan quota as the VS Code extension.
43
+ <!-- viberaven:agent-rules:start -->
44
+ ## VibeRaven Agent Rules
50
45
 
51
- Security: the CLI does not read `OPENAI_API_KEY`. Scans use VibeRaven login and the managed API; your model key stays server-side.
46
+ VibeRaven reads a repository and lists launch gaps for AI-built apps that deploy on Vercel and use Supabase. This is advice, not a gate: the user decides when to ship. It is a repository check, not a live database test, and a clear result is not a security audit.
52
47
 
48
+ - Suggest one pass with `npx -y viberaven --agent-mode` from the project root before a Vercel + Supabase app launches or is handed off, after a Supabase migration or policy change, or when the user reports a production error about RLS, env vars, the database connection, the service role key or a Stripe webhook. It is not needed for apps that do not use Vercel and Supabase, for general SQL or deployment questions, or for one local error.
49
+ - Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the verdict, and `.viberaven/context-map.json` for compact agent context.
50
+ - Read `.viberaven/agent-summary.md` and `.viberaven/launch-playbook.md` before editing code for a listed gap.
51
+ - Use `npx -y viberaven next --json` or `npx -y viberaven prompt --gap <id>` for one focused repo-code fix at a time.
52
+ - Run `npx -y viberaven --verify` once per batch of fixes, not after every edit.
53
+ - For the Vercel + Supabase repo evidence, run `npx -y viberaven audit --vercel-supabase`.
54
+ - `npx -y viberaven --strict` returns the verdict as an exit code for CI when the user wants one.
55
+ - Do not claim provider dashboard work is fixed by repo-code edits. Provider dashboard checks, billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification happen in the provider dashboard.
56
+ <!-- viberaven:agent-rules:end -->
@@ -1,17 +1,14 @@
1
1
  <!-- viberaven:agent-rules:start -->
2
2
  ## VibeRaven Agent Rules
3
3
 
4
- VibeRaven is the Agent Context + Production Gate.
4
+ VibeRaven reads a repository and lists launch gaps for AI-built apps that deploy on Vercel and use Supabase. This is advice, not a gate: the user decides when to ship. It is a repository check, not a live database test, and a clear result is not a security audit.
5
5
 
6
- - When production readiness, launch readiness, Vercel, Supabase, auth, database, payments, monitoring, deployment, rate limits, or error handling comes up, run `npx -y viberaven --agent-mode` from the project root.
7
- - Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the machine verdict, and `.viberaven/context-map.json` for compact agent context.
8
- - Read `.viberaven/agent-summary.md` before editing code.
9
- - Read `.viberaven/launch-playbook.md` before editing code.
6
+ - Suggest one pass with `npx -y viberaven --agent-mode` from the project root before a Vercel + Supabase app launches or is handed off, after a Supabase migration or policy change, or when the user reports a production error about RLS, env vars, the database connection, the service role key or a Stripe webhook. It is not needed for apps that do not use Vercel and Supabase, for general SQL or deployment questions, or for one local error.
7
+ - Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the verdict, and `.viberaven/context-map.json` for compact agent context.
8
+ - Read `.viberaven/agent-summary.md` and `.viberaven/launch-playbook.md` before editing code for a listed gap.
10
9
  - Use `npx -y viberaven next --json` or `npx -y viberaven prompt --gap <id>` for one focused repo-code fix at a time.
11
- - Run `npx -y viberaven --verify` after one fix.
12
- - Run `npx -y viberaven --strict` before deploy or CI pass.
13
- - For Vercel + Supabase launch checks, run `npx -y viberaven audit --vercel-supabase`.
14
- - Do not claim provider dashboard work is fixed by repo-code edits. Provider dashboard checks, billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification must be completed or verified in the provider dashboard.
15
- - If VibeRaven prints `LOGIN_URL_READY`, open that URL for the user using the available browser tool or system browser. Tell the user: "I opened VibeRaven sign-in so you can approve access; I will continue after approval." Do not ask for passwords, tokens, cookies, or secrets. Keep the terminal process alive while the user approves.
10
+ - Run `npx -y viberaven --verify` once per batch of fixes, not after every edit.
11
+ - For the Vercel + Supabase repo evidence, run `npx -y viberaven audit --vercel-supabase`.
12
+ - `npx -y viberaven --strict` returns the verdict as an exit code for CI when the user wants one.
13
+ - Do not claim provider dashboard work is fixed by repo-code edits. Provider dashboard checks, billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification happen in the provider dashboard.
16
14
  <!-- viberaven:agent-rules:end -->
17
-
@@ -1,17 +1,14 @@
1
1
  <!-- viberaven:agent-rules:start -->
2
2
  ## VibeRaven Agent Rules
3
3
 
4
- VibeRaven is the Agent Context + Production Gate.
4
+ VibeRaven reads a repository and lists launch gaps for AI-built apps that deploy on Vercel and use Supabase. This is advice, not a gate: the user decides when to ship. It is a repository check, not a live database test, and a clear result is not a security audit.
5
5
 
6
- - When production readiness, launch readiness, Vercel, Supabase, auth, database, payments, monitoring, deployment, rate limits, or error handling comes up, run `npx -y viberaven --agent-mode` from the project root.
7
- - Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the machine verdict, and `.viberaven/context-map.json` for compact agent context.
8
- - Read `.viberaven/agent-summary.md` before editing code.
9
- - Read `.viberaven/launch-playbook.md` before editing code.
6
+ - Suggest one pass with `npx -y viberaven --agent-mode` from the project root before a Vercel + Supabase app launches or is handed off, after a Supabase migration or policy change, or when the user reports a production error about RLS, env vars, the database connection, the service role key or a Stripe webhook. It is not needed for apps that do not use Vercel and Supabase, for general SQL or deployment questions, or for one local error.
7
+ - Read `.viberaven/agent-tasklist.md` first, `.viberaven/gate-result.json` for the verdict, and `.viberaven/context-map.json` for compact agent context.
8
+ - Read `.viberaven/agent-summary.md` and `.viberaven/launch-playbook.md` before editing code for a listed gap.
10
9
  - Use `npx -y viberaven next --json` or `npx -y viberaven prompt --gap <id>` for one focused repo-code fix at a time.
11
- - Run `npx -y viberaven --verify` after one fix.
12
- - Run `npx -y viberaven --strict` before deploy or CI pass.
13
- - For Vercel + Supabase launch checks, run `npx -y viberaven audit --vercel-supabase`.
14
- - Do not claim provider dashboard work is fixed by repo-code edits. Provider dashboard checks, billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification must be completed or verified in the provider dashboard.
15
- - If VibeRaven prints `LOGIN_URL_READY`, open that URL for the user using the available browser tool or system browser. Tell the user: "I opened VibeRaven sign-in so you can approve access; I will continue after approval." Do not ask for passwords, tokens, cookies, or secrets. Keep the terminal process alive while the user approves.
10
+ - Run `npx -y viberaven --verify` once per batch of fixes, not after every edit.
11
+ - For the Vercel + Supabase repo evidence, run `npx -y viberaven audit --vercel-supabase`.
12
+ - `npx -y viberaven --strict` returns the verdict as an exit code for CI when the user wants one.
13
+ - Do not claim provider dashboard work is fixed by repo-code edits. Provider dashboard checks, billing/product configuration, DNS, webhooks, credentials, quotas, and live provider verification happen in the provider dashboard.
16
14
  <!-- viberaven:agent-rules:end -->
17
-