@soba-so/react 0.0.13 → 0.0.15

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/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  "use client"
2
- var Sn=class extends Error{status;constructor(n,t){super(n),this.name="ConnectError",this.status=t}},Xe=class{session;baseUrl;doFetch;constructor(n){this.session=n.session,this.baseUrl=(n.baseUrl??"").replace(/\/+$/,""),this.doFetch=n.fetchImpl??fetch.bind(globalThis)}context(){return this.request("GET","/v1/connect")}async machines(){return(await this.request("GET","/v1/machines")).machines}lookup(n){return this.request("GET",`/v1/device/lookup?code=${encodeURIComponent(n)}`)}approve(n){return this.request("POST","/v1/device/approve",{user_code:n})}claim(n){return this.request("POST","/v1/device/claim",{pairing_nonce:n})}deny(n){return this.request("POST","/v1/device/deny",{user_code:n})}plans(){return this.request("GET","/v1/plans")}selectPlan(n){return this.request("POST","/v1/plans/select",{plan:n})}checkoutPlan(n,t){return this.request("POST","/v1/plans/checkout",{plan:n,...t?.successUrl?{success_url:t.successUrl}:{},...t?.cancelUrl?{cancel_url:t.cancelUrl}:{}})}leavePlan(){return this.request("DELETE","/v1/plans/select")}hosted(){return this.request("GET","/v1/hosted")}startHosted(){return this.request("POST","/v1/hosted/start")}disconnectHosted(n){return this.request("DELETE",n?`/v1/hosted?provider=${encodeURIComponent(n)}`:"/v1/hosted")}approveRuntime(n,t){return this.request("POST","/v1/runtimes/approve",{machine_id:n,runtime_id:t})}async request(n,t,s){let o=await this.doFetch(`${this.baseUrl}${t}`,{method:n,headers:{authorization:`Bearer ${this.session}`,...s?{"content-type":"application/json"}:{}},...s?{body:JSON.stringify(s)}:{}}),i={};try{i=await o.json()}catch{}if(!o.ok){let a=typeof i.error=="string"?i.error:`Request failed (${o.status})`;throw new Sn(a,o.status)}return i}};function Qe(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return"#ffffff";let t=n[1].length===3?[...n[1]].map(i=>i+i).join(""):n[1],s=i=>{let a=Number.parseInt(t.slice(i*2,i*2+2),16)/255;return a<=.04045?a/12.92:((a+.055)/1.055)**2.4};return .2126*s(0)+.7152*s(1)+.0722*s(2)>.45?"#101012":"#ffffff"}function qn(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return null;let t=n[1].length===3?[...n[1]].map(s=>s+s).join(""):n[1];return[0,1,2].map(s=>Number.parseInt(t.slice(s*2,s*2+2),16))}function Ve(e,n,t){let s=qn(e),o=qn(n);return!s||!o?e:`#${s.map((a,m)=>Math.round(a+(o[m]-a)*t)).map(a=>a.toString(16).padStart(2,"0")).join("")}`}function en(e,n){if(!qn(e))return{};let t=Qe(e),s=n?.trim();return{"--sc-ground":e,"--sc-shell":e,"--sc-sheet":Ve(e,t,.07),"--sc-raised":Ve(e,t,.13),"--sc-line":Ve(e,t,.18),"--sc-line-2":Ve(e,t,.28),"--sc-text":t,"--sc-text-2":Ve(t,e,.15),"--sc-muted":Ve(t,e,.38),...s?{"--sc-accent":s,"--sc-accent-fg":Qe(s)}:{"--sc-accent":t,"--sc-accent-fg":e}}}function Bn(e){return e.authenticated===!0?{tone:"ok",text:"signed in"}:e.authenticated===!1?{tone:"warn",text:e.auth_hint??"signed out on that machine"}:{tone:"unknown",text:"could not tell"}}function Hn(e){let{platform:n,arch:t}=e;if(!n)return null;let s=n==="darwin"||n==="macos",o=s?"Mac":n==="win32"||n==="windows"?"Windows PC":"Linux machine";return s?`${t==="aarch64"||t==="arm64"?"Apple silicon ":""}${o}`:o}function nn(e){return e.find(n=>n.state==="offline")??null}function tn(e){return e.state==="busy"?{tone:"busy",text:`serving ${e.active} of ${e.capacity}`}:e.state==="online"?{tone:"ok",text:"connected"}:{tone:"off",text:"asleep or offline"}}import{jsx as de,jsxs as ds}from"react/jsx-runtime";function W({className:e}){return ds("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:[de("path",{d:"M18.125 7.039A8.6 8.6 0 1 0 18.125 16.961A6 6 0 0 1 18.125 7.039Z",fill:"currentColor"}),de("path",{d:"M19.925 7.039A8.6 8.6 0 0 1 19.925 16.961A6 6 0 0 0 19.925 7.039Z",fill:"currentColor"})]})}function Rt({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{fill:"currentColor",d:"M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"})})}function Oe({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{fill:"currentColor",d:"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"})})}function We({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{d:"M4 5h16v11H4zM9 20h6M12 16v4",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function Te({className:e}){return de("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:de("path",{d:"M5 6h14v10H5zM2.5 19.5h19",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}var pe={claude:Rt,chatgpt:Oe,local:We};var ne=[{id:"claude",costClass:"user-subscription",short:"Claude Code",label:"Continue with Claude",title:"The Claude plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Claude Code installed and signed in",hint:"Install it from claude.ai/code, then run `claude` once and sign in.",install:"https://claude.com/product/claude-code",expects:["claude-code"]},{id:"chatgpt",costClass:"user-subscription",short:"Codex",label:"Continue with ChatGPT",title:"The ChatGPT plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Codex installed and signed in",hint:"Install Codex, then run `codex` once and sign in.",install:"https://learn.chatgpt.com/codex/cli",expects:["codex"]},{id:"local",costClass:"user-hardware",short:"Local models",label:"Use a model on this machine",title:"A model on your own machine",cost:"Free. You bought the hardware",prerequisite:"Ollama running, with a model pulled",hint:"Install Ollama, then `ollama pull` a model before pairing.",install:"https://ollama.com",expects:["ollama","openai-api"]}],Et=["claude","chatgpt"];function Fn(){return ne.filter(e=>Et.includes(e.id))}function Vn(e){return ne.filter(n=>n.costClass===e)}function sn(e){return ne.find(n=>n.expects.includes(e))??null}import{jsx as H,jsxs as Ie}from"react/jsx-runtime";function Ge({machines:e,onApproveRuntime:n}){return e.length?H("div",{children:e.map(t=>{let s=tn(t),o=Hn(t);return Ie("div",{className:"sc-machine",children:[Ie("div",{className:"sc-idrow",children:[H("span",{className:"sc-opt-tile","aria-hidden":"true",children:H(Te,{className:"sc-opt-mark"})}),Ie("span",{className:"sc-opt-text",children:[H("span",{className:"sc-opt-label",children:t.label??"This machine"}),(o||t.always_on)&&Ie("span",{className:"sc-machine-meta",children:[o&&H("span",{children:o}),t.always_on&&H("span",{className:"sc-machine-tag",children:"always on"})]})]}),Ie("span",{className:"sc-machine-state",children:[H("span",{className:`sc-dot sc-dot-${s.tone}`,"aria-hidden":"true"}),s.text]})]}),Ie("ul",{className:"sc-runtimes",children:[t.runtimes.map(i=>H(ps,{runtime:i,...n?{onApprove:()=>n(t.id,i.id)}:{}},i.id)),!t.runtimes.length&&H("li",{className:"sc-note",children:"No runtime advertised. Install Claude Code, Codex or Ollama on that machine."})]})]},t.id)})}):H("p",{className:"sc-note",children:"Nothing connected yet."})}function ps({runtime:e,onApprove:n}){let t=sn(e.id),s=t?pe[t.id]:null,o=Bn(e);return Ie("li",{className:"sc-runtime",children:[H("span",{className:"sc-runtime-tile","aria-hidden":"true",children:s&&H(s,{className:"sc-runtime-mark"})}),H("span",{className:"sc-runtime-name",children:e.display_name}),e.quarantined?n?H("button",{type:"button",className:"sc-conn-action",onClick:n,children:"Let it serve"}):H("span",{className:"sc-runtime-verdict sc-tone-warn",children:"new, not serving yet"}):H("span",{className:`sc-runtime-verdict sc-tone-${o.tone}`,children:o.text})]})}import{useCallback as me,useEffect as te,useId as gs,useMemo as Pe,useRef as je,useState as L}from"react";var on=[{slug:"mac-arm",label:"macOS, Apple silicon"},{slug:"mac-intel",label:"macOS, Intel"},{slug:"windows",label:"Windows"},{slug:"linux",label:"Linux"}];function rn(e){if(!e)return"";try{return new URL(e).origin}catch{return""}}var Wn="soba";function Lt(){return`${Wn}://show`}function an(e,n,t){let s=`${Wn}://connect?url=${encodeURIComponent(e)}`;return n&&(s+=`&nonce=${encodeURIComponent(n)}`),t&&(s+=`&want=${encodeURIComponent(t)}`),s}function cn(){let e=globalThis.crypto;if(!e?.getRandomValues)return null;let n=e.getRandomValues(new Uint8Array(32)),t="";for(let s of n)t+=String.fromCharCode(s);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var ms=1600;function Gn(e={}){return zn(e)}async function jn(e,n={}){if(typeof window>"u"||typeof document>"u")return"unknown";let t=zn(n);try{window.location.href=an(e,n.nonce,n.want)}catch{return"absent"}return t}async function Yn(e={}){if(typeof window>"u"||typeof document>"u")return"unknown";let n=zn(e);try{window.location.href=Lt()}catch{return"absent"}return n}async function zn(e){if(typeof window>"u"||typeof document>"u")return"unknown";let n=e.graceMs??ms,t=document.visibilityState==="visible"&&document.hasFocus(),s=!1,o=()=>{s=!0},i=()=>{document.visibilityState==="hidden"&&(s=!0)};return window.addEventListener("blur",o),window.addEventListener("pagehide",o),document.addEventListener("visibilitychange",i),await new Promise(a=>setTimeout(a,n)),window.removeEventListener("blur",o),window.removeEventListener("pagehide",o),document.removeEventListener("visibilitychange",i),t?s?"opened":"absent":"unknown"}var Ot="soba.connect.choice",hs=180*24*60*60*1e3;function fs(e){let n=2166136261;for(let t=0;t<e.length;t++)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return(n>>>0).toString(36)}function Kn(e,n){return e?n?`${Ot}.${e}.${fs(n)}`:`${Ot}.${e}`:null}function Jn(e){if(!e||typeof localStorage>"u")return null;try{let n=localStorage.getItem(e);if(!n)return null;let t=JSON.parse(n);if(Date.now()-Date.parse(t.at)>hs)return null;let s=ne.find(o=>o.id===t.choice);return s?s.id:null}catch{return null}}function Zn(e,n){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({choice:n,at:new Date().toISOString()}))}catch{}}import{Fragment as dn,jsx as r,jsxs as w}from"react/jsx-runtime";var Xn=2e3,bs=1e4,ys=9e4,ws=6e4;function Qn(e,n,t,s=[],o){return e?"code":n&&(t.length>0||s.length>0)?"manage":o?"launch":"choose"}function vs(e){let n=Math.max(0,Math.round(e/1e3));return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function nt({client:e,initialCode:n,initialChoice:t,onConnected:s,showStatus:o=!0,initialContext:i=null,initialMachines:a,onClose:m,headingId:c,theme:d,reason:g}){let b=!!i&&a!==void 0,[h,f]=L(b?Qn(n,o,a??[],[],t):"loading"),[p,N]=L(i),[k,P]=L(a??[]),[U,D]=L(n??""),[C,$]=L(null),[q,A]=L(null),[J,z]=L(!1),[F,ce]=L(0),[xe,wn]=L(()=>Date.now()),[K,Ce]=L(null),[vn,Ne]=L(!1),[he,Z]=L(!1),[In,Ke]=L("browser"),[Ue,Cn]=L(null),[le,se]=L([]),[qe,$n]=L(0),[_e,Be]=L(null),oe=je(null),[_,S]=L(t??null),[Me,X]=L(null),Je=Pe(()=>{let l=p?.accent?.trim(),v=p?.background?.trim();if(!(!l&&!v))return v?{...en(v,l),background:v,borderRadius:"inherit"}:{"--sc-accent":l,"--sc-accent-fg":Qe(l)}},[p?.accent,p?.background]),Nn=gs(),re=c??Nn,ke=je(null);te(()=>{if(!e||b)return;let l=!0;return Promise.all([e.context(),e.machines()]).then(([v,M])=>{l&&(N(v),P(M),f(Qn(n,o,M)))}).catch(v=>{l&&(A(v.message),f("choose"))}),()=>{l=!1}},[e,n,o,b]),te(()=>{h!=="loading"||!b||f(Qn(n,o,a??[]))},[h,b,n,o,a]),te(()=>{a&&P(a)},[a]),te(()=>{i&&N(i)},[i]);let He=je(!1),Fe=je(h);Fe.current=h;let Q=je(le);Q.current=le;let V=!!p?.hosted_available,kn=p?.hosted!==!1;te(()=>{if(!e||h!=="manage")return;let l=!0,v=setInterval(async()=>{try{let M=await e.machines();if(!l)return;P(M);let O=!V||He.current;M.length===0&&Q.current.length===0&&O&&Fe.current==="manage"&&f("choose")}catch{}},bs);return()=>{l=!1,clearInterval(v)}},[h,e,V]);let y=Kn(p?.publishable_key??null);te(()=>{X(Jn(y))},[y]),te(()=>{if(!e||!V)return;let l=!0;return e.hosted().then(v=>{l&&(se(v.credentials),!He.current&&(He.current=!0,v.credentials.length>0&&o&&Fe.current==="choose"&&f("manage")))}).catch(()=>{}),()=>{l=!1}},[e,V,o]),te(()=>{if(!e||h!=="hosted")return;let l=!0,v=async()=>{try{let Se=await e.hosted();if(!l)return!1;if(se(Se.credentials),Se.credentials.length>0)return f("hosted_connected"),Be(null),!0}catch{}return!1},M=async()=>{oe.current?.closed&&(oe.current=null,!await v()&&l&&f("choose"))},O=setInterval(()=>{v(),M()},Xn),Le=setInterval(M,400),ge=Se=>{let Mt=Se.data;Mt?.source==="soba"&&Mt.type==="hosted_result"&&v()};return window.addEventListener("message",ge),()=>{l=!1,clearInterval(O),clearInterval(Le),window.removeEventListener("message",ge),oe.current=null}},[e,h]);let B=me(()=>{if(!e)return;let l=window.open("","soba-connect-plan","width=520,height=760,noopener=no");oe.current=l,f("hosted"),$n(Date.now()),Be(null),A(null),e.startHosted().then(({url:v})=>{if(l&&!l.closed){l.location.href=v;return}Be(v)}).catch(v=>{l?.close(),oe.current=null,A(v.message),f("choose")})},[e]),ue=me(async l=>{if(e){z(!0);try{await e.disconnectHosted(l),se((await e.hosted()).credentials)}catch(v){A(v.message)}finally{z(!1)}}},[e]);te(()=>{if(!e||h!=="waiting")return;let l=!0,v=setInterval(async()=>{try{let M=await e.machines();if(!l)return;P(M);let O=ke.current;if(!O)return;let Le=M.filter(Se=>!O.has(Se.id)),ge=Le.find(Se=>Se.state!=="offline")??Le[0];ge&&(Cn(ge.id),_&&Zn(y,_),f("connected"),s?.(M))}catch{}},Xn);return()=>{l=!1,clearInterval(v)}},[h,e,s,_,y]);let St=me(async()=>{if(e){A(null),z(!0);try{let l=await e.lookup(U);$(l),f("confirm")}catch(l){A(l.message)}finally{z(!1)}}},[e,U]),Re=me(async()=>{if(e){A(null),z(!0);try{try{ke.current=new Set((await e.machines()).map(l=>l.id))}catch{ke.current=new Set(k.map(l=>l.id))}await e.approve(U),f("waiting"),ce(Date.now())}catch(l){A(l.message)}finally{z(!1)}}},[e,U,k]),An=me(async()=>{if(e){z(!0);try{await e.deny(U),Ke("browser"),f("denied")}catch(l){A(l.message)}finally{z(!1)}}},[e,U]),E=Pe(()=>p?.connect_url??null,[p]),[ee,Pt]=L(()=>cn()),as=Pe(()=>E?an(E,ee??void 0,_??void 0):null,[E,ee,_]),is=Pe(()=>rn(E),[E]),cs=me(l=>{if(k.length===0)return null;let v=ne.find(O=>O.id===l);if(!v)return null;let M=k.flatMap(O=>O.runtimes??[]).filter(O=>v.expects.includes(O.id));return M.length===0?{tone:"dim",text:"not installed"}:M.some(O=>O.authenticated===!0)?{tone:"ok",text:"ready"}:M.every(O=>O.authenticated===!1)?{tone:"warn",text:"needs signing in"}:{tone:"dim",text:"installed"}},[k]),ls=me((l=null)=>{S(l),A(null),Ce(null),Ne(!1),Z(!1),Dn.current=!1,Pt(cn()),f("launch")},[]),Dn=je(!!t);te(()=>{h!=="launch"||!E||Dn.current||(Dn.current=!0,Ne(!0),jn(E,{...ee?{nonce:ee}:{},..._?{want:_}:{}}).then(Ce))},[h,E,ee,_]);let xt=me(()=>{Ne(!0),Gn().then(Ce)},[]),us=me(l=>{if(he){let v=cn();Z(!1),Pt(v),E&&(l.preventDefault(),window.location.href=an(E,v??void 0,_??void 0))}xt()},[he,xt,E,_]),Ze=Pe(()=>{let l=p?.runtimes;return l?ne.filter(v=>l.includes(v.id)):Fn()},[p?.runtimes]),fe=Pe(()=>{let l=ne.find(v=>v.id===_);return l?{choice:l,Mark:pe[l.id]??null}:null},[_]),Un=Pe(()=>k.find(l=>l.id===Ue),[k,Ue]);te(()=>{let l=ee;if(!e||h!=="launch"||!l)return;let v=!1,M=Date.now()+15e4,O=setInterval(async()=>{if(Date.now()>M){clearInterval(O),Z(!0);return}try{let Le=await e.claim(l);if(v)return;if(Le.declined){clearInterval(O),Ce(null),Ke("machine"),f("denied");return}if(!Le.claimed)return;clearInterval(O);try{ke.current=new Set((await e.machines()).map(ge=>ge.id))}catch{ke.current=new Set(k.map(ge=>ge.id))}f("waiting"),ce(Date.now())}catch{}},Xn);return()=>{v=!0,clearInterval(O)}},[e,h,k,ee]);let Ee=Pe(()=>{if(!C)return null;if(C.approved||C.denied)return"answered";let l=C.expires_at?Date.parse(C.expires_at):Number.NaN;return Number.isFinite(l)&&l<=xe?"expired":"live"},[C,xe]);te(()=>{if(!(h==="confirm"&&Ee==="live"||h==="waiting"||h==="hosted"))return;let v=setInterval(()=>wn(Date.now()),1e3);return()=>clearInterval(v)},[h,Ee]);let _t=me(async(l,v)=>{if(e)try{await e.approveRuntime(l,v),P(await e.machines())}catch(M){A(M.message)}},[e]);return h==="loading"?r("div",{className:"soba-connect",...d?{"data-theme":d}:{},style:Je,children:r("div",{className:"sc-card",children:r("p",{className:"sc-note",children:"Loading\u2026"})})}):w("div",{className:"soba-connect",...d?{"data-theme":d}:{},style:Je,children:[m&&r("button",{type:"button",className:"sc-modal-close",onClick:m,"aria-label":"Close",children:"\xD7"}),h==="manage"&&w("div",{className:"sc-card",children:[r("h2",{className:"sc-title",children:"Your compute"}),w("p",{className:"sc-sub",children:[r(ln,{context:p})," ",k.length>0&&le.length>0?"runs on your connected plan, and on these machines while they are awake.":le.length>0?"runs on the plan you connected. Nothing here is charged to you.":"runs on these machines, while they are awake."]}),w("div",{className:"sc-conns",children:[le.map(l=>w("div",{className:"sc-conn",children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Oe,{className:"sc-opt-mark"})}),w("div",{className:"sc-opt-text",children:[r("span",{className:"sc-opt-label",children:l.provider==="openai-chatgpt"?"ChatGPT plan":l.provider}),r("span",{className:"sc-opt-sub",children:l.account_label??"signed in"})]}),r("button",{type:"button",className:"sc-conn-action",onClick:()=>void ue(l.provider),disabled:J,children:"Disconnect"}),w("p",{className:"sc-conn-note",children:[r(ln,{context:p})," stops using it. To withdraw the grant entirely, remove it in your OpenAI settings."]})]},l.provider)),r(Ge,{machines:k,onApproveRuntime:_t})]}),q&&r("p",{className:"sc-error",children:q}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("choose"),children:k.length>0?"Connect another machine":"Connect compute"})]}),h==="choose"&&w("div",{className:"sc-card",children:[r(Cs,{context:p}),r("h2",{className:"sc-h",id:re,children:g==="payment_required"?"Carry on with your own AI":g==="no_compute"?"This run needs a machine":"Connect your AI"}),r("p",{className:"sc-p",children:"Use compute you already have."}),E&&Ze.length>0&&w(dn,{children:[r("p",{className:"sc-opt-group",children:"On your machine"}),r("div",{className:"sc-opts",children:Ze.map(l=>{let v=pe[l.id];return w("button",{type:"button",className:"sc-opt",onClick:()=>ls(l.id),children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:v&&r(v,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:l.label})}),(()=>{let M=cs(l.id);return M?r("span",{className:`sc-opt-has sc-opt-has-${M.tone}`,children:M.text}):Me===l.id?r("span",{className:"sc-opt-last",children:"last used"}):r(Pn,{className:"sc-opt-go"})})()]},l.id)})}),w("p",{className:"sc-opt-note",children:["Your accounts stay there. ",Tt(p)," never sees them."]})]}),kn&&w(dn,{children:[E&&Ze.length>0&&r("div",{className:"sc-or","aria-hidden":"true",children:r("span",{children:"or"})}),E&&Ze.length>0&&r("p",{className:"sc-opt-group",children:"In your browser"}),r("div",{className:"sc-opts",children:w("button",{type:"button",className:"sc-opt",onClick:V?B:void 0,disabled:!V||!e,children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Oe,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:"Sign in with ChatGPT"})}),V?r(Pn,{className:"sc-opt-go"}):r("span",{className:"sc-opt-last",children:"soon"})]})}),r("p",{className:"sc-opt-note",children:V?"Nothing to install.":"Nothing to install. Not switched on here yet."})]}),(!E||Ze.length===0)&&(!V||!kn)&&r("p",{className:"sc-error",style:{marginTop:16},children:"This app has no publishable key yet, so there is nothing to pair against."}),q&&r("p",{className:"sc-error",children:q}),E&&p?.show_code===!0&&r("div",{className:"sc-opt-alt",children:r("button",{type:"button",className:"sc-alt-link",onClick:()=>f("code"),children:"I have a code"})})]}),h==="launch"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r(xn,{mark:fe?.Mark??W,still:he||!vn&&K===null}),r("h2",{className:"sc-h",id:re,children:he?"No answer from this machine":K==="absent"?"Nothing opened":K===null?"Opening Soba Connect\u2026":"Approve it on this machine"}),he?r("p",{className:"sc-p",children:"Soba Connect did not answer. It may not be open, or nobody was there. Try again when you are ready."}):K==="absent"?r("p",{className:"sc-p",children:"Nothing opened on this machine. Open it yourself below, or install it if it is not here yet."}):r("p",{className:"sc-p",children:K===null?"Approve it there and this page does the rest.":"This page finishes on its own."}),fe&&w("p",{className:"sc-prereq",children:[fe.Mark&&r(fe.Mark,{className:"sc-rt-mark"}),"Needs ",fe.choice.prerequisite]}),w("div",{className:"sc-stack",style:{marginTop:18},children:[r("a",{className:K==="absent"||he?"sc-btn sc-btn-primary":"sc-btn",href:as??"#",onClick:us,children:he?"Try again":K==="absent"?"Open Soba Connect":"Open it again"}),r("p",{className:"sc-note",children:K===null?"Your browser will ask permission first.":"Your browser asks permission the first time."}),fe&&K==="absent"&&r("p",{className:"sc-note",children:r(Ns,{text:fe.choice.hint})}),w("div",{className:"sc-foot-strip",children:[r("span",{children:"Not installed on this machine?"}),w("button",{type:"button",className:"sc-foot-go",onClick:()=>f("get"),children:["Get it",r(Pn,{})]})]})]})]}),h==="get"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("launch")}),r("p",{className:"sc-head-title",children:"Get Soba Connect"})]}),r("div",{className:"sc-opts",children:on.map(l=>w("a",{className:"sc-opt",href:`${is}/download/${l.slug}`,target:"_blank",rel:"noreferrer noopener",children:[r("span",{className:"sc-opt-tile","aria-hidden":"true",children:r(Te,{className:"sc-opt-mark"})}),r("span",{className:"sc-opt-text",children:r("span",{className:"sc-opt-label",children:l.label})}),r(Pn,{className:"sc-opt-go"})]},l.slug))}),r("p",{className:"sc-opt-note",children:"Install it, then come back here and press the row you started with."})]}),h==="code"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r("h2",{className:"sc-h",id:re,children:"Enter the code from that machine"}),r("p",{className:"sc-p",children:"Eight characters, shown by Soba Connect once you paste the link."}),w("form",{className:"sc-stack",style:{marginTop:16},onSubmit:l=>{l.preventDefault(),St()},children:[r("input",{className:"sc-input",value:U,onChange:l=>D(l.target.value),placeholder:"ACDE-F234",autoComplete:"off",autoFocus:!0,"aria-label":"Pairing code"}),q&&r("p",{className:"sc-error",children:q}),r("button",{type:"submit",className:"sc-btn sc-btn-primary",disabled:J||U.length<8,children:J?"Checking\u2026":"Continue"})]})]}),h==="confirm"&&C&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("code")}),r("p",{className:"sc-head-title",children:"Soba Connect"})]}),r("h2",{className:"sc-title",children:"Attach this machine to your account?"}),w("p",{className:"sc-sub",children:[r(ln,{context:p})," may send your runs to it once you approve. It can never see the account or the keys on it."]}),w("ul",{className:"sc-facts",children:[r(un,{k:"Code",v:C.user_code}),r(un,{k:"Machine",v:C.hostname??"not stated"}),r(un,{k:"System",v:[C.platform,C.arch].filter(Boolean).join(" / ")||"not stated"}),r(un,{k:"Asked by",v:C.client??"not stated"}),C.labels.length>0&&r(un,{k:"Labels",v:C.labels.join(", ")})]}),r("p",{className:"sc-note",style:{marginTop:12},children:"Every line above is what that machine said about itself. If none of it looks like a computer of yours, say no."}),Ee==="expired"&&r("p",{className:"sc-error",children:"That code has expired. Ask the machine for a new one. It prints a fresh code each time it starts."}),Ee==="answered"&&r("p",{className:"sc-error",children:"That code has already been answered. If it was not you, deny the next one."}),q&&r("p",{className:"sc-error",children:q}),w("div",{className:"sc-row",style:{marginTop:16},children:[r("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:()=>void Re(),disabled:J||Ee!=="live",children:"Approve"}),r("button",{type:"button",className:"sc-btn",onClick:()=>void An(),disabled:J||Ee==="answered",children:"No, deny it"})]}),Ee==="live"&&C.expires_at&&w("p",{className:"sc-note",style:{marginTop:10},children:["This code expires in ",vs(Date.parse(C.expires_at)-xe),"."]})]}),h==="waiting"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:fe?.choice.short??"Soba Connect"})]}),r(xn,{mark:fe?.Mark??W}),r("h2",{className:"sc-h",id:re,children:"Approved. Waiting for it to connect"}),r("p",{className:"sc-p",children:"Nothing more to do here. This page changes when it arrives."}),F>0&&xe-F>ys&&r("p",{className:"sc-note sc-tone-warn",style:{marginTop:14,textAlign:"center"},children:"Still nothing. Look at Soba Connect on that machine: it says what it is doing. This keeps watching either way."})]}),h==="connected"&&w("div",{className:"sc-card",children:[r(et,{tone:"ok"}),r("h2",{className:"sc-h",id:re,children:Un?.label?`${Un.label} is connected`:"Connected"}),w("p",{className:"sc-p",children:[r(ln,{context:p})," will use ",Un?.label?"it":"this machine"," from now on, while it is awake."]}),o&&w(dn,{children:[r("div",{style:{marginTop:16},children:r(Ge,{machines:k,onApproveRuntime:_t})}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:14},onClick:()=>f("manage"),children:"Done"})]})]}),h==="hosted"&&w("div",{className:"sc-card",children:[w("div",{className:"sc-head",children:[r(Ye,{onClick:()=>f("choose")}),r("p",{className:"sc-head-title",children:"ChatGPT"})]}),_e?r(xn,{mark:Oe,still:!0}):r(xn,{mark:Oe}),r("h2",{className:"sc-h",id:re,children:_e?"Your browser blocked the window":"Finish signing in to ChatGPT"}),r("p",{className:"sc-p",children:_e?"Nothing opened. Open the sign-in yourself below. A link you click is allowed where a window we open is not.":"Approve it in the window that opened."}),w("div",{className:"sc-stack",style:{marginTop:18},children:[_e&&r("a",{className:"sc-btn sc-btn-primary",href:_e,target:"soba-connect-plan",rel:"noreferrer",children:"Open the ChatGPT sign-in"}),q&&r("p",{className:"sc-error",children:q}),qe>0&&xe-qe>ws&&r("p",{className:"sc-note sc-tone-warn",children:"Still nothing. The window may have been closed before it finished, or the sign-in may have been declined. This keeps watching either way."})]})]}),h==="hosted_connected"&&w("div",{className:"sc-card",children:[r(et,{tone:"ok"}),r("h2",{className:"sc-h",id:re,children:"ChatGPT is connected"}),w("p",{className:"sc-p",children:[r(ln,{context:p})," will run on your ChatGPT plan",le[0]?.account_label?` (${le[0].account_label})`:"",". Nothing more to pay, nothing to install."]}),r("p",{className:"sc-opt-note",style:{textAlign:"center"},children:"It runs on our side, so it has no access to your files or your terminal."}),o&&w(dn,{children:[r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("manage"),children:"Done"}),r("div",{className:"sc-opt-alt",children:r("button",{type:"button",className:"sc-alt-link",onClick:()=>f("choose"),children:"Connect a machine too"})})]})]}),h==="denied"&&w("div",{className:"sc-card",children:[r(et,{tone:"off"}),r("h2",{className:"sc-h",id:re,children:"Declined"}),r("p",{className:"sc-p",children:In==="machine"?"Nothing was connected. You can ask again whenever you like.":"That machine was not attached to your account, and the terminal has been told so."}),r("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>f("choose"),children:"Back to the start"})]})]})}function Tt(e){return e?.app.name??"this app"}function It(e){let n=e?.app.icon_urls;if(n?.length)return n;let t=e?.app.icon_url;return t?[t]:[]}function Cs({context:e}){let n=It(e),[t,s]=L(0),o=n[t];return e?.app.mark==="soba"?r(W,{className:"sc-app-mark"}):o?r("img",{className:"sc-app-mark",src:o,alt:"","aria-hidden":"true",onError:()=>s(i=>i+1)}):null}function ln({context:e}){let n=It(e),[t,s]=L(0),o=n[t],i=e?.app.mark==="soba";return w("span",{className:"sc-app",children:[i&&r(W,{className:"sc-app-icon"}),!i&&o&&r("img",{className:"sc-app-icon",src:o,alt:"",onError:()=>s(a=>a+1)}),Tt(e)]})}function Ye({onClick:e}){return r("button",{type:"button",className:"sc-head-back",onClick:e,"aria-label":"Back",children:r("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:r("path",{d:"M15 5 8 12l7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}function Pn({className:e}){return r("svg",{className:e,viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:r("path",{d:"M9 5l7 7-7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function xn({mark:e,still:n}){return w("span",{className:"sc-waiting","aria-hidden":"true",children:[!n&&r("svg",{className:"sc-waiting-orbit",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("circle",{className:"sc-waiting-arc",cx:"50",cy:"50",r:"46"})}),r(e,{className:"sc-waiting-mark"})]})}function et({tone:e}){return w("span",{className:`sc-result sc-result-${e}`,"aria-hidden":"true",children:[r("svg",{className:"sc-result-ring",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("circle",{className:"sc-result-circle",cx:"50",cy:"50",r:"46"})}),r("svg",{className:"sc-result-glyph",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:r("path",{className:"sc-result-path",d:e==="ok"?"M33 51.5 44.5 63 68 39":"M34 50h32"})}),e==="ok"&&r("span",{className:"sc-result-halo"})]})}function Ns({text:e}){return r(dn,{children:e.split("`").map((n,t)=>t%2===1?r("code",{className:"sc-inline-code",children:n},t):n)})}function un({k:e,v:n}){return w("li",{className:"sc-fact",children:[r("span",{className:"sc-fact-key",children:e}),r("span",{children:n})]})}import{useEffect as ks,useRef as st}from"react";var _n=0,tt=null;function $t(){if(typeof document>"u")return()=>{};_n===0&&(tt=document.body.style.overflow,document.body.style.overflow="hidden"),_n+=1;let e=!1;return()=>{e||(e=!0,_n-=1,_n===0&&(document.body.style.overflow=tt??"",tt=null))}}import{jsx as At}from"react/jsx-runtime";function pn({open:e,onClose:n,labelledBy:t,theme:s,style:o,children:i}){let a=st(null),m=st(null),c=st(null);return ks(()=>{let d=a.current;if(d){if(!e){d.open&&d.close();return}return d.open||d.showModal(),document.activeElement===d&&m.current?.focus(),$t()}},[e]),At("dialog",{ref:a,className:"soba-connect sc-modal","aria-labelledby":t,...s?{"data-theme":s}:{},style:o,onCancel:d=>{d.preventDefault(),n()},onPointerDown:d=>{c.current=d.target},onClick:d=>{d.target===d.currentTarget&&c.current===d.currentTarget&&n()},children:At("div",{className:"sc-modal-sheet",ref:m,tabIndex:-1,children:i})})}function be(e){let n=`${e.unit}s`;return e.reward==="unlimited"?`Unlimited ${n} on your own AI`:e.reward==="included"&&e.includedUnits!==null?`${xs(e.includedUnits)} ${n} a month once you connect`:e.reward==="credit"&&e.creditMicros>0?`${Ps(e.creditMicros)} back each month you stay connected`:null}function ye(e){return e==="unlimited"||e==="included"}var Ss=new Set(["user-hardware","user-subscription"]);function ae(e){return e===null||e.length===0?!1:e.every(n=>Ss.has(n))}var Ps=e=>(e/1e6).toLocaleString("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}),xs=e=>e.toLocaleString("en-US");import{createContext as _s,useContext as Ms}from"react";var ot=_s(null);function T(){let e=Ms(ot);if(!e)throw new Error("useSoba() must be used inside a <SobaProvider>.");return e}import{createContext as Dt,useContext as Ut}from"react";var rt=Dt(null);function qt(){return Ut(rt)}var at=Dt({context:null,machines:void 0,theme:"light"});function I(){return Ut(at)}import{jsx as mn}from"react/jsx-runtime";function Rs({className:e}){let{theme:n}=I(),t=e?`soba-connect ${e}`:"soba-connect";return mn("div",{className:t,"data-theme":n,children:mn(it,{})})}function it(){let{compute:e}=T();return e.loading&&!e.machines.length?mn("p",{className:"sc-note",children:"Loading\u2026"}):e.error&&!e.machines.length?mn("p",{className:"sc-error",children:e.error.message}):mn(Ge,{machines:e.machines})}import{useEffect as Ls,useRef as Bt,useState as Os}from"react";import{useId as Es}from"react";import{jsx as ze,jsxs as Mn}from"react/jsx-runtime";function hn({open:e,onOpenChange:n,initialCode:t,onConnected:s,showStatus:o,reason:i}){let{error:a}=T(),m=qt(),c=I(),d=()=>n(!1),g=Es(),b=c.context?.background?.trim(),h=b?en(b,c.context?.accent):void 0;return Mn(pn,{open:e,onClose:d,labelledBy:g,theme:c.theme,style:h,children:[a?Mn("div",{className:"sc-card",children:[ze("h2",{className:"sc-title",id:g,children:"Could not start"}),ze("p",{className:"sc-error",children:a.message})]}):!m&&!c.context?Mn("div",{className:"sc-card",children:[ze("h2",{className:"sc-title",id:g,children:"One moment"}),ze("p",{className:"sc-note",children:"Getting your compute\u2026"})]}):ze(nt,{client:m,onClose:d,headingId:g,theme:c.theme,initialContext:c.context,...c.machines!==void 0?{initialMachines:c.machines}:{},...t?{initialCode:t}:{},...s?{onConnected:s}:{},...o===void 0?{}:{showStatus:o},...i?{reason:i}:{}}),Mn("p",{className:"sc-modal-foot",children:[ze(W,{className:"sc-foot-mark"}),"Secured by Soba"]})]})}import{Fragment as ct,jsx as $e,jsxs as fn}from"react/jsx-runtime";function Ae({children:e,variant:n,className:t,initialCode:s,onConnected:o,defaultOpen:i,open:a,onOpenChange:m,showConnected:c=!0}){let{compute:d,connect:g}=T(),{theme:b}=I(),[h,f]=Os(i??!!s),p=Bt(null),N=a!==void 0,k=!N&&!i&&!s&&g.hasModal,P=N?a:k?g.isOpen:h,U=F=>{k?F?g.open("manual"):g.close():N||f(F),m?.(F)},D=Bt(P);Ls(()=>{D.current&&!P&&p.current?.focus(),D.current=P},[P]);let C=d.machines.find(F=>F.state!=="offline")??d.machines[0],$=C?.runtimes?.find(F=>!F.quarantined)??C?.runtimes?.[0],q=c&&C!==void 0,A=C?tn(C):null,J=$?sn($.id):void 0,z=(J?pe[J.id]:void 0)??($?We:Te);return fn(ct,{children:[$e("button",{ref:p,type:"button","data-theme":b,className:["sc-btn",q?"sc-btn-connected":"sc-btn-icon",!q&&n==="primary"?"sc-btn-primary":"",t].filter(Boolean).join(" "),onClick:()=>U(!0),children:e??(q?fn(ct,{children:[$e("span",{className:"sc-runtime-tile","aria-hidden":"true",children:$e(z,{className:"sc-runtime-mark"})}),fn("span",{className:"sc-btn-connected-text",children:[$?.display_name??"Connected",C?.label&&fn("span",{className:"sc-btn-connected-where",children:[" on ",C.label]})]}),$e("i",{className:`sc-dot sc-dot-${A?.tone??"off"}`,"aria-hidden":"true"}),A&&$e("span",{className:"sc-sr",children:A.text})]}):fn(ct,{children:[$e(W,{className:"sc-btn-mark"}),"Connect compute"]}))}),!k&&$e(hn,{open:P,onOpenChange:U,...s?{initialCode:s}:{},...o?{onConnected:o}:{}})]})}import{jsx as lt,jsxs as Is}from"react/jsx-runtime";function Ts({initialCode:e,onConnected:n,className:t,showStatus:s=!0}){let{theme:o}=I();return Is("div",{className:t?`soba-connect ${t}`:"soba-connect","data-theme":o,children:[s&&lt(it,{}),lt("div",{className:"sc-compute-act",children:lt(Ae,{...e?{initialCode:e}:{},...n?{onConnected:n}:{}})})]})}import{useEffect as Hs,useId as Fs,useState as jt}from"react";import{useCallback as $s,useState as As}from"react";function Rn(){let[e,n]=As(null);return{open:$s(()=>{n(null),Yn().then(n)},[]),launch:e,note:e==="absent"?"Nothing opened here. That machine may be a different computer, or asleep.":null}}import{useCallback as Ht,useMemo as Ft}from"react";function gn(e){if(!e)return null;if(typeof e=="string")return e;if(typeof Response<"u"&&e instanceof Response)return Vt(e.status);let n=e,t=n.error;return typeof t?.code=="string"?t.code:typeof t?.type=="string"?t.type:typeof n.code=="string"?n.code:typeof n.status=="number"?Vt(n.status):n.cause&&n.cause!==e?gn(n.cause):null}function Vt(e){return e===402?"payment_required":e===409?"no_compute":null}function ut(...e){let[n,t]=e,{plan:s,compute:o,connect:i}=T(),a=t?.predict??e.length===0,m=Us(Ds(n),o)??(a?qs(s,o):null),c=s.plan,d=s.plans,g=Ft(()=>{if(m!=="payment_required")return null;let p=c?.price??0,N=c?.included_units??0;return d.find(k=>k.id!==c?.id&&k.price>p&&(k.included_units===null||k.included_units>N))??null},[m,d,c]),b=Ht(async()=>{if(!g)return;if(g.selectable){await s.select(g.id);return}let p=await s.checkout(g.id);window.location.assign(p)},[g,s]),h=i.open,f=Ht(()=>{m&&h(m)},[h,m]);return Ft(()=>{if(!m)return null;let p=c?be({unit:c.unit,reward:c.connected_reward,includedUnits:c.connected_included_units,creditMicros:c.connected_credit*1e6}):null,N=c&&ye(c.connected_reward)?p:null;return{reason:m,...Bs(m,{connectOffer:N,connected:o.connected,online:o.online,machine:nn(o.machines)?.label??null,unit:c?.unit??"message",interval:c?.interval??"month",upgrade:g!==null,resets:s.current?.period_end??null}),connectOffer:N,upgradeTo:g,connect:f,upgrade:b}},[m,c,o,g,f,b,s.current?.period_end])}function Ds(e){let n=gn(e);return n==="payment_required"||n==="no_compute"?n:null}function Us(e,n){return e==="no_compute"&&n.connected&&n.online?null:e}function qs(e,n){let t=e.plan;return!t||n.loading?null:ae(t.route_allow)&&!n.online?"no_compute":e.remaining===0&&t.overage==="stop"?"payment_required":null}function Bs(e,n){if(e==="payment_required"){let t=`No ${n.unit}s left this ${n.interval}`;return n.connectOffer&&!n.connected?{title:t,body:`${n.connectOffer}. Connecting takes a minute and costs nothing.`}:n.connectOffer&&!n.online?{title:t,body:`${n.connectOffer}. Waking ${n.machine??"your machine"} is enough.`}:n.upgrade?{title:t,body:n.resets?`A larger plan carries on now. This one comes back on ${Wt(n.resets)}.`:"A larger plan carries on now, or wait for this one to renew."}:{title:t,body:n.resets?`Your allowance comes back on ${Wt(n.resets)}.`:"Your allowance comes back at the start of the next period."}}return n.connected&&!n.online?{title:`${n.machine??"Your machine"} can't be reached`,body:"This run needs it awake and connected. Open Soba Connect on that machine, or connect another one."}:{title:"Nothing connected yet",body:"This app runs on AI you already pay for, on a machine of your own. Connect one and this run has somewhere to go."}}function Wt(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as dt,jsx as R,jsxs as we}from"react/jsx-runtime";function Vs(e){let{at:n=.25,className:t,error:s,fallback:o=null}=e,i=e.predict??!("error"in e),{plan:a,compute:m,connect:c}=T(),{theme:d}=I(),[g,b]=jt(null),h=Fs(),f=R(dt,{children:o}),p=a.plan;if(!p||a.loading||m.loading)return f;let N=e.allow!==void 0?e.allow:p.route_allow;if(m.connected)return m.online?f:R(Gt,{className:t,theme:d,stalled:!0,children:R(Ws,{machine:nn(m.machines)?.label??null,ownCompute:ae(N),onConnectAnother:()=>c.open("no_compute")})});let k=(()=>{let C=gn(s);return C==="payment_required"||C==="no_compute"})();if(!i&&!k)return f;let P=ae(N)?js(p.unit,ae(p.route_allow)):ye(p.connected_reward)?Ys(a,p,n):null;if(!P)return f;let U=!i||P.meter!==null&&P.meter.left===0,D=g??U;return we(Gt,{className:t,theme:d,children:[R("div",{className:"sc-nudge-top",children:we("div",{className:"sc-nudge-say",children:[R("p",{className:"sc-nudge-title",children:P.title}),R("p",{className:"sc-nudge-detail",children:P.detail}),we("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more","aria-expanded":D,"aria-controls":h,onClick:()=>b(!D),children:[D?"Hide the details":"How it works",R(zs,{})]})]})}),D?R("ol",{className:"sc-nudge-steps",id:h,children:Gs(c.app?.name,rn(c.connectUrl)).map(C=>we("li",{children:[C.opens?R("button",{type:"button",className:"sc-step-lead",onClick:()=>c.open("manual"),children:C.lead}):R("strong",{children:C.lead}),C.detail?R("span",{children:C.detail}):null,C.links.length>0?we("span",{className:"sc-step-links",children:[C.linksLead,C.links.map($=>R("a",{href:$.href,target:"_blank",rel:"noreferrer noopener",children:$.label},$.href))]}):null]},C.lead))}):null,R(Ae,{variant:"primary"})]})}function Gt({className:e,theme:n,stalled:t,children:s}){return R("div",{className:e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill","data-theme":n,children:R("div",{className:t?"sc-nudge sc-nudge-stalled":"sc-nudge",children:s})})}function Ws({machine:e,ownCompute:n,onConnectAnother:t}){let s=Rn(),{compute:o}=T(),[i,a]=jt(!1),{refresh:m}=o;return Hs(()=>{if(s.launch===null||s.launch==="absent")return;a(!1);let c=setInterval(()=>void m(),3e3),d=setTimeout(()=>{clearInterval(c),a(!0)},2e4);return()=>{clearInterval(c),clearTimeout(d)}},[s.launch,m]),we(dt,{children:[R("div",{className:"sc-nudge-top",children:we("div",{className:"sc-nudge-say",children:[we("p",{className:"sc-nudge-title",children:[e??"Your machine"," can\u2019t be reached"]}),R("p",{className:"sc-nudge-detail",children:n?"Soba Connect there has stopped reporting in, so runs have nowhere to go until it is back.":"Soba Connect there has stopped reporting in, so nothing will run on your own AI until it is back."}),s.note&&R("p",{className:"sc-nudge-note",children:s.note}),i&&R("p",{className:"sc-nudge-note",children:"Soba Connect is open, but this machine still isn\u2019t reporting in. It may no longer be connected to this app."}),(s.launch==="absent"||i)&&R("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more",onClick:t,children:i?"Connect it again":"Connect another machine"})]})}),R("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:s.open,children:"Open Soba Connect"})]})}function Gs(e,n){return[{lead:"Download Soba Connect",detail:"",linksLead:n?"Get it for":void 0,links:n?on.map(t=>({label:t.label,href:`${n}/download/${t.slug}`})):[]},{lead:"Connect compute",detail:"Press this, then approve the pairing when the app asks.",opens:!0,links:[]},{lead:"Let your AIs serve",detail:`It finds what is installed on that machine. Allow one, and ${e??"this app"} sends every run there.`,linksLead:"Nothing on it yet?",links:ne.map(t=>({label:t.short,href:t.install}))}]}function js(e,n){return{title:n?"This plan runs on your own AI.":`These ${e}s run on your own AI.`,detail:`Connect a machine and your ${e}s run there, free, on access you already have.`,meter:null}}function Ys(e,n,t){let{remaining:s,included:o}=e;if(s===null||o===null||o===0||s>Math.ceil(o*t))return null;let i=be({unit:n.unit,reward:n.connected_reward,includedUnits:n.connected_included_units,creditMicros:n.connected_credit*1e6});return i?{title:s===0?`No ${n.unit}s left this month.`:`${s} ${n.unit}${s===1?"":"s"} left this month.`,detail:we(dt,{children:[i,"."]}),meter:{left:s,of:o}}:null}function zs(){return R("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-chev",children:R("path",{d:"M4.5 6.5 8 10l3.5-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})})}var Ks=new Set(["delta","thinking","status","done","error"]);function En(e){let n;try{n=JSON.parse(e)}catch{return null}if(!n||typeof n!="object")return null;let t=n,s=t.type==="event"?t.event:t;if(!s||typeof s!="object")return null;let o=s;if(typeof o.type!="string"||!Ks.has(o.type))return null;let i={type:o.type};return typeof o.text=="string"&&(i.text=o.text),typeof o.message=="string"&&(i.message=o.message),typeof o.tool=="string"&&(i.tool=o.tool),typeof o.tier=="string"&&(i.tier=o.tier),o.usage&&typeof o.usage=="object"&&(i.usage=o.usage),i}async function*pt(e){let n=e.body;if(!n)throw new Error("That run response had no body to stream.");let t=(e.headers.get("content-type")??"").includes("ndjson"),s=n.getReader(),o=new TextDecoder,i="",a=[];try{for(;;){let c=await s.read();if(c.done)break;for(i+=o.decode(c.value,{stream:!0});;){let d=i.indexOf(`
3
- `);if(d===-1)break;let g=zt(i.slice(0,d));if(i=i.slice(d+1),t){let b=g.trim()?En(g):null;b&&(yield b);continue}if(g===""){let b=a.join(`
4
- `);if(a=[],b==="[DONE]")return;let h=b?En(b):null;h&&(yield h);continue}Yt(g,a)}}!t&&i&&Yt(zt(i),a);let m=t?i.trim():a.join(`
5
- `);if(m&&m!=="[DONE]"){let c=En(m);c&&(yield c)}}finally{s.cancel().catch(()=>{})}}function Yt(e,n){if(!e||e.startsWith(":"))return;let t=e.indexOf(":");if(t===-1||e.slice(0,t)!=="data")return;let s=e.slice(t+1);n.push(s.startsWith(" ")?s.slice(1):s)}function zt(e){return e.endsWith("\r")?e.slice(0,-1):e}async function Js(e){let n="";for await(let t of e)if(t.type==="delta"&&t.text&&(n+=t.text),t.type==="error")throw new Error(t.message??"The run ended with an error.");return n}import{useId as Zs,useState as Kt}from"react";import{jsx as G,jsxs as Ln}from"react/jsx-runtime";function Xs({reason:e}){return G("span",{className:"sc-limit-mark","aria-hidden":"true",children:e==="no_compute"?G(We,{}):G(W,{})})}function Qs(e){let{error:n,variant:t="card",onDismiss:s,className:o}=e,i=ut(n,{predict:e.predict??!("error"in e)}),a=Zs(),m=I();if(!i)return null;let c=G(eo,{offer:i,headingId:a,onDismiss:s});return t==="dialog"?G(pn,{open:!0,onClose:()=>s?.(),labelledBy:a,theme:m.theme,children:c}):G("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":m.theme,children:c})}function eo({offer:e,headingId:n,onDismiss:t}){let{compute:s}=T(),[o,i]=Kt(!1),[a,m]=Kt(null),c=e.reason==="no_compute"&&s.connected&&!s.online,d=c||e.connectOffer!==null||!s.connected,g=Rn();async function b(){i(!0),m(null);try{await e.upgrade()}catch(h){m(h.message)}finally{i(!1)}}return Ln("div",{className:"sc-card sc-limit",children:[Ln("div",{className:"sc-limit-head",children:[G(Xs,{reason:e.reason}),Ln("div",{children:[G("h2",{className:"sc-limit-title",id:n,children:e.title}),G("p",{className:"sc-limit-body",children:e.body})]})]}),a&&G("p",{className:"sc-error",children:a}),c&&g.note&&G("p",{className:"sc-limit-note",children:g.note}),Ln("div",{className:"sc-limit-actions",children:[t&&G("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,disabled:o,children:"Not now"}),e.upgradeTo&&G("button",{type:"button",className:d?"sc-btn":"sc-btn sc-btn-primary",onClick:()=>void b(),disabled:o,children:o?"Opening\u2026":e.upgradeTo.selectable?`Switch to ${e.upgradeTo.name}`:`${e.upgradeTo.name} for $${e.upgradeTo.price.toLocaleString()}/${e.upgradeTo.interval}`}),d&&G("button",{type:"button",className:c?"sc-btn":"sc-btn sc-btn-primary",onClick:e.connect,disabled:o,children:c?"Connect another machine":"Connect compute"}),c&&G("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:g.open,disabled:o,children:"Open Soba Connect"})]})]})}import{useMemo as no}from"react";function bn(){let{plan:e,compute:n,connect:t}=T();return no(()=>{let s=e.plan,o=e.current,i={plan:s,assignment:o,loading:e.loading,error:e.error,periodEnd:o?.period_end?new Date(o.period_end):null};if(!s)return{...i,state:"none",trialDaysLeft:null,ceiling:null,raised:!1,uncounted:!1,used:0,remaining:null,percent:null,unlimited:!1,reward:null,summary:"Nothing is assigned to this account, so runs are bounded by whatever the app allows."};let a=oo(o?.trial_ends_at??null),m=s.connected_reward==="included"&&n.connected&&s.connected_included_units!==null,c=m?s.connected_included_units:s.included_units,d=s.connected_reward==="unlimited"&&n.connected,g=c===null,b=e.used??0,h=c===null?null:Math.max(0,c-b),f=c&&c>0?Math.min(100,Math.round(b/c*100)):null,p=c!==null&&b>=c,N=a!==null?"trial":g?"unlimited":p?s.overage==="meter"?"metered":"spent":"within";return{...i,state:N,trialDaysLeft:a,ceiling:c,raised:m,uncounted:d,used:b,remaining:h,percent:f,unlimited:g,reward:to(s,m||d,n.connected,()=>t.open("manual")),summary:so({plan:s,assignment:o,used:b,ceiling:c,trialDaysLeft:a,raised:m,uncounted:d,state:N})}},[e,n.connected,t])}function to(e,n,t,s){let o=be({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6});return o?{line:o,inForce:n,required:!1,connected:t,actionable:ye(e.connected_reward)&&!t,open:s}:ae(e.route_allow)&&!t?{line:"Nothing connected yet, so nothing can run.",inForce:!1,required:!0,connected:t,actionable:!0,open:s}:null}function so(e){let{plan:n,assignment:t,used:s,ceiling:o,trialDaysLeft:i,raised:a,uncounted:m,state:c}=e,d=`${n.unit}${s===1?"":"s"}`,g=m?" Runs your own AI serves do not count toward it.":"";if(c==="trial"&&i!==null){let f=n.price===0?"it continues free":`it is $${n.price.toLocaleString()} a ${n.interval}`;return`${i} ${i===1?"day":"days"} left of your trial, then ${f}.`}if(c==="unlimited")return`${s.toLocaleString()} ${d} this period. No ceiling on this plan.`;if(c==="metered"){let f=s-(o??0);return n.overage_per_unit>0?`${f.toLocaleString()} past the allowance, billed at $${n.overage_per_unit} a ${n.unit}.${g}`:`${f.toLocaleString()} past the allowance.${g}`}if(c==="spent")return t?.period_end?`Allowance spent. It comes back on ${Jt(t.period_end)}.${g}`:`Allowance spent. It comes back at the start of the next period.${g}`;let b=Math.max(0,(o??0)-s),h=a?` Raised from ${(n.included_units??0).toLocaleString()} while your own AI is connected.`:t?.period_end?` Resets ${Jt(t.period_end)}.`:"";return`${b.toLocaleString()} of ${(o??0).toLocaleString()} ${n.unit}s left.${h}${g}`}function oo(e){if(!e)return null;let n=new Date(e).getTime()-Date.now();return Number.isNaN(n)||n<=0?null:Math.max(1,Math.ceil(n/864e5))}function Jt(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as ao,jsx as j,jsxs as ie}from"react/jsx-runtime";function mt({heading:e="Current plan",showUsage:n=!0,showName:t=!0,className:s}){let o=bn(),{theme:i}=I(),a=h=>j("section",{className:s?`soba-connect sc-fill ${s}`:"soba-connect sc-fill","data-theme":i,children:ie("div",{className:"sc-card sc-current",children:[e&&j("h2",{className:"sc-section-title",children:e}),h]})});if(o.error)return a(j("p",{className:"sc-error",children:o.error.message}));if(o.loading)return a(j("p",{className:"sc-note",children:"Loading\u2026"}));if(!o.plan)return a(ie("div",{className:"sc-current-main",children:[j("p",{className:"sc-current-name",children:"No plan"}),j("p",{className:"sc-sub",children:o.summary})]}));let{plan:m,trialDaysLeft:c,percent:d,unlimited:g,reward:b}=o;return a(ie(ao,{children:[ie("div",{className:"sc-current-grid",children:[(t||c!==null)&&ie("div",{className:"sc-current-main",children:[t?ie("p",{className:"sc-current-name",children:[m.name,c!==null&&ie("span",{className:"sc-trial-badge",children:[c," ",c===1?"day":"days"," left"]})]}):c!==null&&j("p",{className:"sc-current-trial",children:ie("span",{className:"sc-trial-badge",children:[c," ",c===1?"day":"days"," left"]})}),t&&m.description&&j("p",{className:"sc-sub",children:m.description})]}),n&&ie("div",{className:"sc-usage",children:[ie("div",{className:"sc-row-between",children:[j("span",{className:"sc-fact-key",children:"Usage"}),j("span",{className:d!==null&&d>=100?"sc-usage-figure sc-usage-over":"sc-usage-figure",children:g?"Unlimited":d===null?"Metered":`${d}% used`})]}),d!==null&&j("div",{className:"sc-meter",role:"presentation",children:d>0&&j("span",{className:d>=100?"sc-meter-fill sc-meter-full":"sc-meter-fill",style:{width:`${d}%`}})}),j("p",{className:"sc-usage-line",children:o.summary})]})]}),b&&ie("div",{className:"sc-current-foot",children:[j("p",{className:b.required?"sc-plan-reward-line sc-plan-reward-need":b.inForce?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-open",children:b.required?b.line:b.inForce?`In force: ${ro(b.line)}.`:b.line}),(b.actionable||b.connected)&&j(Ae,{})]})]}))}var ro=e=>e.charAt(0).toLowerCase()+e.slice(1);import{useCallback as io,useMemo as co,useState as Zt}from"react";var lo={"user-hardware":"your own machine","user-subscription":"your own AI subscription","open-weights":"open models we host",frontier:"frontier models"},uo=new Set(["user-hardware","user-subscription"]);function ht(e={}){let{plan:n,compute:t,connect:s}=T(),[o,i]=Zt(null),[a,m]=Zt(null),{featured:c,onSelect:d,successUrl:g,cancelUrl:b}=e,h=io(async p=>{i(p.id),m(null);try{if(p.selectable)await n.select(p.id);else if(d)d(p);else{let N=await n.checkout(p.id,{...g?{successUrl:g}:{},...b?{cancelUrl:b}:{}});window.location.assign(N);return}}catch(N){throw m(N.message),N}finally{(p.selectable||d)&&i(null)}},[n,d,g,b]),f=co(()=>n.plans.map(p=>{let N=n.current?.plan_id===p.id;return{plan:p,current:N,featured:c===p.id&&!N,price:po(p),allowance:p.included_units===null?`Unlimited ${p.unit}s`:`${p.included_units.toLocaleString()} ${p.unit}${p.included_units===1?"":"s"}`,allowanceNote:mo(p),computeLabel:p.route_allow===null?"any compute":p.route_allow.length===0?"no compute":null,compute:(p.route_allow??[]).map(k=>({costClass:k,label:lo[k]??k,owned:uo.has(k),runtimes:Vn(k).map(P=>P.id)})),connect:ho(p,N,t.connected,()=>s.open("manual")),cta:{label:fo(p,N,o===p.id),disabled:N||o!==null,busy:o===p.id,take:()=>h(p)}}}),[n.plans,n.current,c,t.connected,s,o,h]);return{offers:f,current:f.find(p=>p.current)??null,loading:n.loading,error:n.error,failed:a}}function po(e){return e.price===0?{amount:"Free",interval:null,free:!0}:{amount:`$${e.price.toLocaleString()}`,interval:e.interval,free:!1}}function mo(e){let n=[];return e.included_units===null?n.push("No ceiling on this plan"):(n.push(`Included each ${e.interval}`),e.overage==="meter"&&e.overage_per_unit>0?n.push(`then $${e.overage_per_unit} a ${e.unit}`):e.included_units>0&&n.push(`then ${e.unit}s stop`)),e.trial_days>0&&n.push(`${e.trial_days}-day trial`),n.join(" \xB7 ")}function ho(e,n,t,s){let o=be({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6}),i=ae(e.route_allow)&&!t;if(!o&&!i)return null;let a=ye(e.connected_reward);return{key:o?"Connect your own":"To use this",line:o??(n?"Nothing connected yet, so nothing can run.":"Runs only on compute you connect."),reward:o!==null,actionable:n&&(a||i)&&!t,open:s}}function fo(e,n,t){return n?"Your plan":t?e.selectable?"Switching\u2026":"Opening\u2026":e.selectable?"Choose":`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}import{jsx as u,jsxs as x}from"react/jsx-runtime";function On(e){return e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill"}function ft({onSelect:e,successUrl:n,cancelUrl:t,showCompute:s=!0,showConnect:o=!1,variant:i="cards",featured:a,className:m}){let{offers:c,loading:d,error:g,failed:b}=ht({...a?{featured:a}:{},...e?{onSelect:e}:{},...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}}),{theme:h}=I();if(g)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-error",children:g.message})})});if(d)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-note",children:"Loading plans\u2026"})})});if(c.length===0)return u("div",{className:On(m),"data-theme":h,children:u("div",{className:"sc-card",children:u("p",{className:"sc-note",children:"This app has no plans yet."})})});let f={showCompute:s,showConnect:o};return x("div",{className:On(m),"data-theme":h,"data-variant":i,children:[i==="rows"?u(bo,{offers:c,shelf:f}):i==="table"?u(yo,{offers:c,shelf:f}):u(go,{offers:c,shelf:f}),b&&u("p",{className:"sc-error",children:b})]})}function go({offers:e,shelf:n}){return u("div",{className:"sc-plans",children:e.map(t=>x("div",{className:Xt("sc-plan",t),children:[x("div",{className:"sc-row-between",children:[u("span",{className:"sc-title",children:t.plan.name}),u(gt,{offer:t})]}),u("p",{className:"sc-sub",children:t.plan.description}),u(bt,{price:t.price,free:"forever"}),u(vt,{offer:t,shelf:n}),u(Qt,{offer:t}),u("div",{className:"sc-plan-band",children:n.showCompute&&u(wt,{offer:t})}),u("div",{className:"sc-plan-band",children:u(yt,{offer:t})})]},t.plan.id))})}function bo({offers:e,shelf:n}){return u("ul",{className:"sc-plan-rows",children:e.map(t=>x("li",{className:Xt("sc-plan-row",t),children:[x("div",{className:"sc-row-main",children:[x("span",{className:"sc-row-name",children:[u("span",{className:"sc-title",children:t.plan.name}),u(gt,{offer:t})]}),t.plan.description&&u("p",{className:"sc-sub",children:t.plan.description}),u(Qt,{offer:t}),n.showCompute&&u(wt,{offer:t,inline:!0}),u(yt,{offer:t,inline:!0})]}),x("div",{className:"sc-row-side",children:[u(bt,{price:t.price,free:"forever",small:!0}),u(vt,{offer:t,shelf:n})]})]},t.plan.id))})}function yo({offers:e,shelf:n}){let t=e.some(a=>a.plan.overage_per_unit>0),s=e.some(a=>a.plan.trial_days>0),o=e.some(a=>a.connect!==null),i=a=>[a.current?"sc-col-current":"",a.featured?"sc-col-featured":""].filter(Boolean).join(" ")||void 0;return u("div",{className:"sc-table-scroll",children:x("table",{className:"sc-plan-table",children:[u("thead",{children:x("tr",{children:[u("td",{}),e.map(a=>x("th",{scope:"col",className:i(a),children:[x("span",{className:"sc-row-name",children:[u("span",{className:"sc-title",children:a.plan.name}),u(gt,{offer:a})]}),u(bt,{price:a.price,small:!0})]},a.plan.id))]})}),x("tbody",{children:[x("tr",{children:[u("th",{scope:"row",children:"Included"}),e.map(a=>u("td",{className:i(a),children:a.allowance},a.plan.id))]}),t&&x("tr",{children:[u("th",{scope:"row",children:"Then"}),e.map(a=>u("td",{className:i(a),children:a.plan.overage_per_unit>0?`$${a.plan.overage_per_unit} / ${a.plan.unit}`:u("span",{className:"sc-muted-cell",children:"Stops"})},a.plan.id))]}),s&&x("tr",{children:[u("th",{scope:"row",children:"Trial"}),e.map(a=>u("td",{className:i(a),children:a.plan.trial_days>0?`${a.plan.trial_days} days`:u("span",{className:"sc-muted-cell",children:"None"})},a.plan.id))]}),n.showCompute&&x("tr",{children:[u("th",{scope:"row",children:"Runs on"}),e.map(a=>u("td",{className:i(a),children:u(wt,{offer:a,bare:!0})},a.plan.id))]}),o&&x("tr",{children:[u("th",{scope:"row",children:"Connect your own"}),e.map(a=>u("td",{className:i(a),children:u(yt,{offer:a,bare:!0})},a.plan.id))]}),x("tr",{className:"sc-table-buy",children:[u("td",{}),e.map(a=>u("td",{className:i(a),children:u(vt,{offer:a,shelf:n})},a.plan.id))]})]})]})})}function Xt(e,n){return[e,n.current?"sc-plan-current":"",n.featured?"sc-plan-featured":""].filter(Boolean).join(" ")}function gt({offer:e}){return e.current?u("span",{className:"sc-plan-badge",children:"Current"}):e.featured?u("span",{className:"sc-plan-badge-soft",children:"Recommended"}):null}function bt({price:e,small:n,free:t}){return x("p",{className:n?"sc-plan-price sc-plan-price-sm":"sc-plan-price",children:[u("span",{className:"sc-plan-amount",children:e.amount}),e.interval?x("span",{className:"sc-plan-interval",children:["/",e.interval]}):t&&u("span",{className:"sc-plan-interval sc-plan-after",children:t})]})}function Qt({offer:e}){return x("p",{className:"sc-plan-allowance",children:[u("span",{className:"sc-plan-figure",children:e.allowance}),u("span",{className:"sc-plan-qualifier",children:e.allowanceNote})]})}function yt({offer:e,inline:n,bare:t}){let s=e.connect;if(!s)return t?u("span",{className:"sc-muted-cell",children:"None"}):null;let o=s.reward?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-need",i=s.actionable?x("button",{type:"button",className:`${o} sc-plan-reward-act`,"aria-label":"Connect compute",onClick:s.open,children:[u("span",{className:"sc-reward-said",children:s.line}),x("span",{className:"sc-reward-do","aria-hidden":!0,children:[u(W,{className:"sc-reward-mark"}),"Connect compute"]})]}):u("p",{className:o,children:s.line});return t?i:u("div",{className:n?"sc-plan-reward sc-plan-reward-inline":"sc-plan-reward",children:i})}function wt({offer:e,inline:n,bare:t}){let s=e.computeLabel?u("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:u("li",{children:e.computeLabel})}):u("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:e.compute.map(o=>x("li",{className:o.owned?"sc-compute-own":void 0,children:[o.label,u(wo,{runtimes:o.runtimes})]},o.costClass))});return t?s:x("div",{className:n?"sc-plan-compute sc-plan-compute-inline":"sc-plan-compute",children:[u("span",{className:"sc-fact-key",children:"Runs on"}),s]})}function vt({offer:e,shelf:n}){let t=e.connect;return n.showConnect&&t?.actionable?x("button",{type:"button",className:"sc-btn sc-btn-primary sc-btn-icon",onClick:t.open,children:[u(W,{className:"sc-btn-mark"}),"Connect compute"]}):u("button",{type:"button",className:e.current?"sc-btn":"sc-btn sc-btn-primary",disabled:e.cta.disabled,onClick:()=>void e.cta.take().catch(()=>{}),children:e.cta.label})}function wo({runtimes:e}){return e.length===0?null:u("span",{className:"sc-compute-marks",children:e.map(n=>{let t=pe[n];return t?u(t,{className:"sc-rt-mark"},n):null})})}import{jsx as Ct,jsxs as es}from"react/jsx-runtime";function vo({heading:e,plansHeading:n,showUsage:t=!0,showName:s=!0,className:o,...i}){let{plan:a,loading:m}=bn(),{theme:c}=I(),d=n??(m?"Plans":a?"Change plan":"Choose a plan");return es("div",{className:o?`soba-connect sc-fill sc-billing ${o}`:"soba-connect sc-fill sc-billing","data-theme":c,children:[Ct(mt,{...e===void 0?{}:{heading:e},showUsage:t,showName:s}),es("section",{className:"sc-billing-plans",children:[d&&Ct("h2",{className:"sc-section-title",children:d}),Ct(ft,{...i})]})]})}import{useState as ns}from"react";import{jsx as ts,jsxs as No}from"react/jsx-runtime";function Co({plan:e,successUrl:n,cancelUrl:t,label:s,className:o}){let{plan:i}=T(),{theme:a}=I(),[m,c]=ns(!1),[d,g]=ns(null);async function b(){c(!0),g(null);try{let h=await i.checkout(e.id,{...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}});window.location.assign(h)}catch(h){g(h.message),c(!1)}}return No("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":a,children:[ts("button",{type:"button",className:"sc-btn sc-btn-primary",disabled:m,onClick:()=>void b(),children:m?"Opening\u2026":s??`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}),d&&ts("p",{className:"sc-error",children:d})]})}import{useCallback as ve,useEffect as De,useMemo as yn,useRef as So,useState as Y}from"react";var Tn=class{#n;#s=null;#t=null;#e;#o=new Set;constructor(n){this.#e=n,this.#n=n.token??null}get token(){return this.#n}get expiresAt(){return this.#s}get canRefresh(){return!!this.#e.endpoint}get refreshAt(){return!this.canRefresh||this.#s===null?null:Math.max(Date.now()+1e4,this.#s-6e4)}subscribe(n){return this.#o.add(n),()=>this.#o.delete(n)}async ensure(){return this.#n?this.#n:this.refresh()}async refresh(){if(this.#t)return this.#t;let n=this.#e.endpoint;if(!n)throw new Error("This Soba session cannot be refreshed. Pass `sessionEndpoint` so the provider can mint a new one.");let t=this.#e.fetchImpl??fetch.bind(globalThis);this.#t=(async()=>{let s=await t(n,{method:"POST",headers:{"content-type":"application/json"},credentials:"same-origin",body:JSON.stringify(this.#e.user?{user:this.#e.user}:{})});if(!s.ok)throw new Error(`Could not start a Soba session (${s.status} from ${n}).`);let o=await s.json(),i=o.session??o.token;if(!i)throw new Error(`${n} answered without a \`session\`. See @soba-so/react's README.`);let a=o.expires_in??o.expiresIn;this.#n=i,this.#s=typeof a=="number"?Date.now()+a*1e3:null;for(let m of this.#o)m();return i})();try{return await this.#t}finally{this.#t=null}}};function ss(e,n=fetch.bind(globalThis)){return async(t,s)=>{let o=await n(t,s);if(o.status!==401||!e.canRefresh)return o;let i;try{i=await e.refresh()}catch{return o}return n(t,ko(s,i))}}function ko(e,n){let t=new Headers(e?.headers);return t.set("authorization",`Bearer ${n}`),{...e,headers:t}}var os="data-soba-react",rs=!1;function Nt(){if(rs||typeof document>"u"||(rs=!0,document.querySelector(`style[${os}]`)))return;let e=document.createElement("style");e.setAttribute(os,""),e.textContent=`.soba-connect {
2
+ var Gn=class extends Error{status;constructor(n,t){super(n),this.name="ConnectError",this.status=t}},vn=class{session;baseUrl;doFetch;lastMachines=null;constructor(n){this.session=n.session,this.baseUrl=(n.baseUrl??"").replace(/\/+$/,""),this.doFetch=n.fetchImpl??fetch.bind(globalThis)}context(){return this.request("GET","/v1/connect")}async machines(){let n=this.lastMachines,t=n?`?v=${encodeURIComponent(n.version)}`:"",r=await this.request("GET",`/v1/machines${t}`);if(r.unchanged&&n)return n.machines;let o=Array.isArray(r.machines)?r.machines:[];return this.lastMachines=typeof r.version=="string"?{version:r.version,machines:o}:null,o}lookup(n){return this.request("GET",`/v1/device/lookup?code=${encodeURIComponent(n)}`)}approve(n){return this.request("POST","/v1/device/approve",{user_code:n})}claim(n){return this.request("POST","/v1/device/claim",{pairing_nonce:n})}deny(n){return this.request("POST","/v1/device/deny",{user_code:n})}plans(){return this.request("GET","/v1/plans")}selectPlan(n){return this.request("POST","/v1/plans/select",{plan:n})}checkoutPlan(n,t){return this.request("POST","/v1/plans/checkout",{plan:n,...t?.successUrl?{success_url:t.successUrl}:{},...t?.cancelUrl?{cancel_url:t.cancelUrl}:{}})}leavePlan(){return this.request("DELETE","/v1/plans/select")}hosted(){return this.request("GET","/v1/hosted")}startHosted(){return this.request("POST","/v1/hosted/start")}disconnectHosted(n){return this.request("DELETE",n?`/v1/hosted?provider=${encodeURIComponent(n)}`:"/v1/hosted")}approveRuntime(n,t){return this.request("POST","/v1/runtimes/approve",{machine_id:n,runtime_id:t})}async request(n,t,r){let o=await this.doFetch(`${this.baseUrl}${t}`,{method:n,headers:{authorization:`Bearer ${this.session}`,...r?{"content-type":"application/json"}:{}},...r?{body:JSON.stringify(r)}:{}}),a={};try{a=await o.json()}catch{}if(!o.ok){let s=typeof a.error=="string"?a.error:`Request failed (${o.status})`;throw new Gn(s,o.status)}return a}};function Cn(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return"#ffffff";let t=n[1].length===3?[...n[1]].map(a=>a+a).join(""):n[1],r=a=>{let s=Number.parseInt(t.slice(a*2,a*2+2),16)/255;return s<=.04045?s/12.92:((s+.055)/1.055)**2.4};return .2126*r(0)+.7152*r(1)+.0722*r(2)>.45?"#101012":"#ffffff"}function dt(e){let n=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(e.trim());if(!n?.[1])return null;let t=n[1].length===3?[...n[1]].map(r=>r+r).join(""):n[1];return[0,1,2].map(r=>Number.parseInt(t.slice(r*2,r*2+2),16))}function un(e,n,t){let r=dt(e),o=dt(n);return!r||!o?e:`#${r.map((s,c)=>Math.round(s+(o[c]-s)*t)).map(s=>s.toString(16).padStart(2,"0")).join("")}`}function Ke(e,n){if(!dt(e))return{};let t=Cn(e),r=n?.trim();return{"--sc-ground":e,"--sc-shell":e,"--sc-sheet":un(e,t,.07),"--sc-raised":un(e,t,.13),"--sc-line":un(e,t,.18),"--sc-line-2":un(e,t,.28),"--sc-text":t,"--sc-text-2":un(t,e,.15),"--sc-muted":un(t,e,.38),...r?{"--sc-accent":r,"--sc-accent-fg":Cn(r)}:{"--sc-accent":t,"--sc-accent-fg":e}}}function pt(e){return e.authenticated===!0?{tone:"ok",text:"signed in"}:e.authenticated===!1?{tone:"warn",text:e.auth_hint??"signed out on that machine"}:{tone:"unknown",text:"could not tell"}}function mt(e){let{platform:n,arch:t}=e;if(!n)return null;let r=n==="darwin"||n==="macos",o=r?"Mac":n==="win32"||n==="windows"?"Windows PC":"Linux machine";return r?`${t==="aarch64"||t==="arm64"?"Apple silicon ":""}${o}`:o}function Nn(e){return e.find(n=>n.state==="offline")??null}function je(e){let n=e.label?.trim(),t=e.name?.trim();return n&&(!t||n!==t)?n:(t??n??"").replace(/\.(local|lan|home|internal)$/i,"").replace(/[-_]+/g," ").trim()||n||"This machine"}function kn(e){let n=r=>r.state==="busy"?0:r.state==="online"?1:2,t=r=>r.last_seen_at?Date.parse(r.last_seen_at):0;return[...e].sort((r,o)=>n(r)-n(o)||t(o)-t(r))[0]??null}function dn(e){return e?e.state==="busy"?{tone:"busy",word:"Serving"}:e.state==="online"?{tone:"ok",word:"Connected"}:{tone:"off",word:"Asleep"}:{tone:"off",word:"No compute"}}function ht(e){return e.state==="online"||e.state==="busy"}function ft(e){if(!e)return"never seen";let n=Date.parse(e);if(Number.isNaN(n))return"never seen";let t=Date.now()-n,r=6e4;return t<2*r?"just now":t<60*r?`${Math.floor(t/r)} min ago`:t<24*60*r?`${Math.floor(t/(60*r))} hr ago`:`${Math.floor(t/(24*60*r))} days ago`}import{jsx as ge,jsxs as ro}from"react/jsx-runtime";function j({className:e}){return ro("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:[ge("path",{d:"M18.125 7.039A8.6 8.6 0 1 0 18.125 16.961A6 6 0 0 1 18.125 7.039Z",fill:"currentColor"}),ge("path",{d:"M19.925 7.039A8.6 8.6 0 0 1 19.925 16.961A6 6 0 0 0 19.925 7.039Z",fill:"currentColor"})]})}function fr({className:e}){return ge("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:ge("path",{fill:"currentColor",d:"M17.3041 3.541h-3.6718l6.696 16.918H24Zm-10.6082 0L0 20.459h3.7442l1.3693-3.5527h7.0052l1.3693 3.5528h3.7442L10.5363 3.5409Zm-.3712 10.2232 2.2914-5.9456 2.2914 5.9456Z"})})}function Ye({className:e}){return ge("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:ge("path",{fill:"currentColor",d:"M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z"})})}function Vn({className:e}){return ge("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:ge("path",{d:"M4 5h16v11H4zM9 20h6M12 16v4",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function gt({className:e}){return ge("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:ge("path",{d:"M5 6h14v10H5zM2.5 19.5h19",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}var Te={claude:fr,chatgpt:Ye,local:Vn};var se=[{id:"claude",costClass:"user-subscription",short:"Claude Code",label:"Continue with Claude",title:"The Claude plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Claude Code installed and signed in",hint:"Install it from claude.ai/code, then run `claude` once and sign in.",install:"https://claude.com/product/claude-code",expects:["claude-code"]},{id:"chatgpt",costClass:"user-subscription",short:"Codex",label:"Continue with ChatGPT",title:"The ChatGPT plan you already pay for",cost:"Nothing beyond the plan",prerequisite:"Codex installed and signed in",hint:"Install Codex, then run `codex` once and sign in.",install:"https://learn.chatgpt.com/codex/cli",expects:["codex"]},{id:"local",costClass:"user-hardware",short:"Local models",label:"Use a model on this machine",title:"A model on your own machine",cost:"Free. You bought the hardware",prerequisite:"Ollama running, with a model pulled",hint:"Install Ollama, then `ollama pull` a model before pairing.",install:"https://ollama.com",expects:["ollama","openai-api"]}],gr=["claude","chatgpt"];function bt(){return se.filter(e=>gr.includes(e.id))}function yt(e){return se.filter(n=>n.costClass===e)}function wt(e){return se.find(n=>n.expects.includes(e))??null}import{jsx as C,jsxs as G}from"react/jsx-runtime";function Qe({machines:e,hosted:n=[],onApproveRuntime:t,onDisconnectHosted:r,onPair:o,onRefresh:a,refreshing:s,busy:c,appName:i,error:u}){let m=kn(e),f=e.filter(b=>b.id!==m?.id);return!m&&n.length===0&&!o?C("p",{className:"sc-note",children:"Nothing connected yet."}):G("div",{className:"sc-tray",children:[m&&C(zn,{title:"This machine",action:a&&C("button",{type:"button",className:"sc-disc",onClick:a,disabled:s,"aria-label":"Refresh",title:"Refresh",children:C(co,{spinning:!!s})}),children:C(oo,{machine:m})}),m&&C(zn,{title:"Agents on it",children:m.runtimes.length>0?m.runtimes.map(b=>C(ao,{runtime:b,...t?{onApprove:()=>t(m.id,b.id)}:{}},b.id)):C("p",{className:"sc-row-note",children:"No agent advertised. Install Claude Code, Codex or Ollama on that machine."})}),n.length>0&&C(zn,{title:n.length>1?"Connected plans":"Connected plan",children:n.map(b=>C(io,{credential:b,appName:i,busy:c,...r?{onDisconnect:()=>r(b.provider)}:{}},b.provider))}),(f.length>0||o)&&G(zn,{title:f.length>0?"Your other machines":m?"Add a machine":"Your machines",children:[f.map(b=>C(so,{machine:b},b.id)),o&&G("button",{type:"button",className:"sc-pair",onClick:o,children:[C("span",{className:"sc-otile","aria-hidden":"true",children:C(lo,{})}),C("span",{className:"sc-oname",children:e.length>0?"Pair another machine":"Connect a machine"})]})]}),u&&C("p",{className:"sc-error sc-tray-error",children:u})]})}function zn({title:e,action:n,children:t}){return G("section",{className:"sc-group",children:[G("div",{className:"sc-group-cap",children:[C("p",{className:"sc-group-title",children:e}),n]}),C("div",{className:"sc-group-card",children:t})]})}function oo({machine:e}){let n=ht(e),t=[n?null:"Asleep or offline",mt(e),e.always_on?"always on":null,n&&e.capacity>0?`${e.active} of ${e.capacity} in flight`:ft(e.last_seen_at)].filter(Boolean);return G("div",{className:"sc-mrow",children:[G("span",{className:"sc-mtile","aria-hidden":"true",children:[C(br,{}),C("span",{className:`sc-mbadge sc-mbadge-${dn(e).tone}`})]}),G("span",{className:"sc-mid",children:[C("span",{className:"sc-mname",children:je(e)}),C("span",{className:"sc-mmeta",children:t.map((r,o)=>G("span",{children:[o>0&&C("span",{className:"sc-mmeta-sep",children:"\xB7"}),r]},r))})]})]})}function so({machine:e}){let n=dn(e);return G("div",{className:"sc-orow",children:[C("span",{className:"sc-otile","aria-hidden":"true",children:C(br,{})}),C("span",{className:"sc-oname",children:je(e)}),C("span",{className:"sc-oword",children:n.word}),C("span",{className:`sc-dot sc-dot-${n.tone}`,"aria-hidden":"true"})]})}function ao({runtime:e,onApprove:n}){let t=wt(e.id),r=t?Te[t.id]:null,o=pt(e);return G("div",{className:"sc-arow",children:[C("span",{className:"sc-runtime-tile","aria-hidden":"true",children:r&&C(r,{className:"sc-runtime-mark"})}),G("span",{className:"sc-aname",children:[e.display_name,e.version&&G("span",{className:"sc-aversion",children:[" ",e.version]})]}),e.quarantined?n?C("button",{type:"button",className:"sc-row-act",onClick:n,children:"Let it serve"}):C("span",{className:"sc-averdict sc-tone-warn",children:"new, not serving yet"}):o.tone==="ok"?G("span",{className:"sc-averdict",children:[C("span",{className:"sc-dot sc-dot-ok","aria-hidden":"true"}),C("span",{className:"sc-sr",children:o.text})]}):C("span",{className:`sc-averdict sc-tone-${o.tone}`,children:o.text})]})}function io({credential:e,appName:n,busy:t,onDisconnect:r}){return G("div",{className:"sc-hrow",children:[G("div",{className:"sc-orow",children:[C("span",{className:"sc-otile","aria-hidden":"true",children:C(Ye,{className:"sc-omark"})}),G("span",{className:"sc-mid",children:[C("span",{className:"sc-oname",children:e.provider==="openai-chatgpt"?"ChatGPT plan":e.provider}),C("span",{className:"sc-mmeta",children:e.account_label??"signed in"})]}),r&&C("button",{type:"button",className:"sc-row-act",onClick:r,disabled:t,children:"Disconnect"})]}),r&&G("p",{className:"sc-row-note",children:[n??"This app"," stops using it. To withdraw the grant entirely, remove it in your OpenAI settings."]})]})}function br(){return G("svg",{viewBox:"0 0 32 24","aria-hidden":"true",focusable:"false",className:"sc-mglyph",children:[C("rect",{x:"4",y:"1.5",width:"24",height:"15",rx:"2.5",fill:"var(--sc-sheet, #ffffff)",stroke:"currentColor",strokeWidth:"2"}),C("rect",{x:"1",y:"19.5",width:"30",height:"2.5",rx:"1.25",fill:"currentColor"})]})}function lo(){return C("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:"sc-oglyph",children:C("path",{d:"M12 5v14M5 12h14",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round"})})}function co({spinning:e}){return C("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e?"sc-dglyph sc-spin":"sc-dglyph",children:C("path",{d:"M21 12a9 9 0 1 1-2.64-6.36M21 3v6h-6",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}import{jsx as uo}from"react/jsx-runtime";function xn({machines:e,onApproveRuntime:n}){return uo(Qe,{machines:e,...n?{onApproveRuntime:n}:{}})}var vt={ready:{arc:!0},serving:{arc:!0,slot:"stream"},paused:{arc:!1,slot:"zzz"},thinking:{arc:!1,slot:"dots"},connecting:{arc:!1,slot:"orbit"},attention:{arc:!1,slot:"bang"},gone:{arc:!1,slot:"cross"},snap:{arc:!1,slot:"snap"},listening:{arc:!1,slot:"bars"},permission:{arc:!1,slot:"ring"},ai:{arc:!1,slot:"sparks"}};var Ct="105 162 420 420",Nt="M407.1 308.9 A158 158 0 1 0 407.1 491.1 A116 116 0 0 1 407.1 308.9 Z",Ze="M448.5 320 A110 110 0 0 1 448.5 480";import{Fragment as Pn,jsx as x,jsxs as Ae}from"react/jsx-runtime";function kt({kind:e,size:n=44,className:t}){let r=vt[e];return Ae("svg",{className:`bx${t?` ${t}`:""}`,"data-expression":e,viewBox:Ct,overflow:"visible",width:n,height:n,"aria-hidden":"true",children:[x("path",{d:Nt,fill:"currentColor"}),x("path",{className:"bx-arc",d:Ze,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"}),r.slot==="stream"&&x(po,{}),r.slot==="zzz"&&x(mo,{}),r.slot==="dots"&&x(ho,{}),r.slot==="bang"&&x(fo,{}),r.slot==="orbit"&&x(go,{}),r.slot==="cross"&&x(bo,{}),r.slot==="snap"&&x(yo,{}),r.slot==="bars"&&x(wo,{}),r.slot==="ring"&&x(vo,{}),r.slot==="sparks"&&x(Co,{})]})}function po(){return x("path",{className:"bx-st",d:"M475.3 290.3 A150 150 0 0 1 475.3 509.7",fill:"none",stroke:"currentColor",strokeWidth:"15",strokeLinecap:"round",strokeDasharray:"0.1 31"})}function mo(){return Ae(Pn,{children:[x("g",{className:"bx-z1",children:x("path",{d:"M444 372 H496 L444 436 H496",fill:"none",stroke:"currentColor",strokeWidth:"20",strokeLinecap:"round",strokeLinejoin:"round"})}),x("g",{className:"bx-z2",children:x("path",{d:"M492 300 H522 L492 338 H522",fill:"none",stroke:"currentColor",strokeWidth:"15",strokeLinecap:"round",strokeLinejoin:"round"})})]})}function ho(){return Ae(Pn,{children:[x("circle",{className:"bx-th",cx:"463.1",cy:"336.9",r:"21",fill:"currentColor"}),x("circle",{className:"bx-th bx-th2",cx:"483",cy:"400",r:"21",fill:"currentColor"}),x("circle",{className:"bx-th bx-th3",cx:"463.1",cy:"463.1",r:"21",fill:"currentColor"})]})}function fo(){return Ae("g",{className:"bx-at",children:[x("line",{x1:"490",y1:"312",x2:"490",y2:"414",stroke:"currentColor",strokeWidth:"46",strokeLinecap:"round"}),x("circle",{cx:"490",cy:"484",r:"28",fill:"currentColor"})]})}function go(){return Ae("g",{className:"bx-ob",children:[x("path",{d:Ze,fill:"none",stroke:"var(--tile-bg, transparent)",strokeWidth:41,strokeLinecap:"round"}),x("path",{d:Ze,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"})]})}function bo(){return Ae(Pn,{children:[x("path",{className:"bx-xa",d:Ze,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"}),x("g",{className:"bx-xx",children:x("path",{d:"M442 364 L514 436 M514 364 L442 436",fill:"none",stroke:"currentColor",strokeWidth:"24",strokeLinecap:"round"})})]})}function yo(){return x("path",{className:"bx-snap",d:Ze,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"})}function wo(){return Ae("g",{stroke:"currentColor",strokeWidth:"17",strokeLinecap:"round",children:[x("line",{className:"bx-vb",x1:"452",y1:"370",x2:"452",y2:"430"}),x("line",{className:"bx-vb bx-vb2",x1:"482",y1:"330",x2:"482",y2:"470"}),x("line",{className:"bx-vb bx-vb3",x1:"512",y1:"355",x2:"512",y2:"445"})]})}function vo(){return x(Pn,{children:[[450,366],[474,376],[484,400],[474,424],[450,434],[426,424],[416,400],[426,376]].map(([n,t],r)=>x("circle",{className:"bx-w",cx:n,cy:t,r:"11",fill:"currentColor",style:{animationDelay:`${-1.2+r*.15}s`}},r))})}function Co(){return Ae(Pn,{children:[x("g",{className:"bx-sp",children:x("path",{d:"M460 300 Q465.4 324.6 490 330 Q465.4 335.4 460 360 Q454.6 335.4 430 330 Q454.6 324.6 460 300 Z",fill:"currentColor"})}),x("g",{className:"bx-sp bx-sp2",children:x("path",{d:"M486 356 Q493.92 392.08 530 400 Q493.92 407.92 486 444 Q478.08 407.92 442 400 Q478.08 392.08 486 356 Z",fill:"currentColor"})}),x("g",{className:"bx-sp bx-sp3",children:x("path",{d:"M460 440 Q465.4 464.6 490 470 Q465.4 475.4 460 500 Q454.6 475.4 430 470 Q454.6 464.6 460 440 Z",fill:"currentColor"})})]})}import{useCallback as ee,useEffect as X,useId as Eo,useMemo as $e,useRef as pn,useState as D}from"react";var _n=[{slug:"mac-arm",label:"macOS, Apple silicon"},{slug:"mac-intel",label:"macOS, Intel"},{slug:"windows",label:"Windows"},{slug:"linux",label:"Linux"}];function En(e){if(!e)return"";try{return new URL(e).origin}catch{return""}}function vr(e,n){return n<2*6e4?e:n<10*6e4?Math.max(e,6e4):n<30*6e4?Math.max(e,3*6e4):Math.max(e,10*6e4)}var No=3e3,ko=2*6e4,Kn=Date.now(),jn=new Set,wr=!1;function xo(){if(wr||typeof window>"u")return;wr=!0;let e=()=>{let t=Kn;if(Kn=Date.now(),Kn-t>ko)for(let r of jn)r()};for(let t of["pointerdown","keydown","wheel","touchstart"])window.addEventListener(t,e,{capture:!0,passive:!0});let n=()=>{if(!document.hidden)for(let t of jn)t()};window.addEventListener("focus",n),document.addEventListener("visibilitychange",n)}function Ie(e,n,t={}){xo();let r,o=t.immediate===!1?Date.now():0,a=!1,s=!1,c=()=>{s||(r=setTimeout(i,t.idle===!1?n:vr(n,Date.now()-Kn)))},i=async()=>{if(clearTimeout(r),!(s||a)){if(typeof document>"u"||!document.hidden){a=!0,o=Date.now();try{await e()}catch{}finally{a=!1}}c()}},u=()=>{Date.now()-o>Math.min(n,No)&&i()};return jn.add(u),t.immediate===!1?c():i(),()=>{s=!0,clearTimeout(r),jn.delete(u)}}var xt="soba";function Cr(){return`${xt}://show`}function Mn(e,n,t){let r=`${xt}://connect?url=${encodeURIComponent(e)}`;return n&&(r+=`&nonce=${encodeURIComponent(n)}`),t&&(r+=`&want=${encodeURIComponent(t)}`),r}function Rn(){let e=globalThis.crypto;if(!e?.getRandomValues)return null;let n=e.getRandomValues(new Uint8Array(32)),t="";for(let r of n)t+=String.fromCharCode(r);return btoa(t).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}var So=1600;function St(e={}){return Et(e)}async function Pt(e,n={}){if(typeof window>"u"||typeof document>"u")return"unknown";let t=Et(n);try{window.location.href=Mn(e,n.nonce,n.want)}catch{return"absent"}return t}async function _t(e={}){if(typeof window>"u"||typeof document>"u")return"unknown";let n=Et(e);try{window.location.href=Cr()}catch{return"absent"}return n}async function Et(e){if(typeof window>"u"||typeof document>"u")return"unknown";let n=e.graceMs??So,t=document.visibilityState==="visible"&&document.hasFocus(),r=!1,o=()=>{r=!0},a=()=>{document.visibilityState==="hidden"&&(r=!0)};return window.addEventListener("blur",o),window.addEventListener("pagehide",o),document.addEventListener("visibilitychange",a),await new Promise(s=>setTimeout(s,n)),window.removeEventListener("blur",o),window.removeEventListener("pagehide",o),document.removeEventListener("visibilitychange",a),t?r?"opened":"absent":"unknown"}var Nr="soba.connect.choice",Po=180*24*60*60*1e3;function xr(e){let n=2166136261;for(let t=0;t<e.length;t++)n^=e.charCodeAt(t),n=Math.imul(n,16777619);return(n>>>0).toString(36)}function Mt(e,n){return e?n?`${Nr}.${e}.${xr(n)}`:`${Nr}.${e}`:null}function Rt(e){if(!e||typeof localStorage>"u")return null;try{let n=localStorage.getItem(e);if(!n)return null;let t=JSON.parse(n);if(Date.now()-Date.parse(t.at)>Po)return null;let r=se.find(o=>o.id===t.choice);return r?r.id:null}catch{return null}}function Lt(e,n){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({choice:n,at:new Date().toISOString()}))}catch{}}var kr="soba.connect.dismissed",_o=30*24*60*60*1e3;function Ot(e,n){return e?n?`${kr}.${e}.${xr(n)}`:`${kr}.${e}`:null}function Tt(e){if(!e||typeof localStorage>"u")return!1;try{let n=localStorage.getItem(e);if(!n)return!1;let t=JSON.parse(n);return Date.now()-Date.parse(t.at)<_o}catch{return!1}}function At(e){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({at:new Date().toISOString()}))}catch{}}import{Fragment as Zn,jsx as l,jsxs as N}from"react/jsx-runtime";var It=2e3,Mo=1e4,Ro=9e4,Lo=6e4;function $t(e,n,t,r=[],o){return e?"code":n&&(t.length>0||r.length>0)?"manage":o?"launch":"choose"}function Oo(e){let n=Math.max(0,Math.round(e/1e3));return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function Ut({client:e,initialCode:n,initialChoice:t,onConnected:r,showStatus:o=!0,initialContext:a=null,initialMachines:s,onClose:c,headingId:i,theme:u,reason:m,active:f=!0}){let b=!!a&&s!==void 0,[g,p]=D(b?$t(n,o,s??[],[],t):"loading"),[y,E]=D(a),[k,H]=D(s??[]),[M,me]=D(n??""),[P,ne]=D(null),[O,_]=D(null),[q,V]=D(!1),[te,tn]=D(0),[ae,ve]=D(()=>Date.now()),[K,Ce]=D(null),[Ne,He]=D(!1),[W,Re]=D(!1),[rn,ie]=D("browser"),[Ue,on]=D(null),[F,he]=D([]),[T,le]=D(0),[fe,ke]=D(null),U=pn(null),[S,it]=D(t??null),[sn,re]=D(null),an=$e(()=>{let d=y?.accent?.trim(),v=y?.background?.trim();if(!(!d&&!v))return v?{...Ke(v,d),background:v,borderRadius:"inherit"}:{"--sc-accent":d,"--sc-accent-fg":Cn(d)}},[y?.accent,y?.background]),Bn=Eo(),ce=i??Bn,Be=pn(null);X(()=>{if(!e||b)return;let d=!0;return Promise.all([e.context(),e.machines()]).then(([v,A])=>{d&&(E(v),H(A),p($t(n,o,A)))}).catch(v=>{d&&(_(v.message),p("choose"))}),()=>{d=!1}},[e,n,o,b]),X(()=>{g!=="loading"||!b||p($t(n,o,s??[]))},[g,b,n,o,s]),X(()=>{s&&H(s)},[s]),X(()=>{a&&E(a)},[a]);let ln=pn(!1),qe=pn(g);qe.current=g;let yn=pn(F);yn.current=F;let We=!!y?.hosted_available;X(()=>{!o&&qe.current==="manage"&&p("choose")},[o]),X(()=>{if(!e||!f||g!=="manage")return;let d=!0,v=Ie(async()=>{try{let A=await e.machines();if(!d)return;H(A);let I=!We||ln.current;A.length===0&&yn.current.length===0&&I&&qe.current==="manage"&&p("choose")}catch{}},Mo,{immediate:!1});return()=>{d=!1,v()}},[g,e,We,f]);let Fe=Mt(y?.publishable_key??null);X(()=>{re(Rt(Fe))},[Fe]),X(()=>{if(!e||!We)return;let d=!0;return e.hosted().then(v=>{d&&(he(v.credentials),!ln.current&&(ln.current=!0,v.credentials.length>0&&o&&qe.current==="choose"&&p("manage")))}).catch(()=>{}),()=>{d=!1}},[e,We,o]),X(()=>{if(!e||!f||g!=="hosted")return;let d=!0,v=async()=>{try{let Oe=await e.hosted();if(!d)return!1;if(he(Oe.credentials),Oe.credentials.length>0)return p("hosted_connected"),ke(null),!0}catch{}return!1},A=async()=>{U.current?.closed&&(U.current=null,!await v()&&d&&p("choose"))},I=Ie(v,It,{immediate:!1}),ze=setInterval(A,400),_e=Oe=>{let hr=Oe.data;hr?.source==="soba"&&hr.type==="hosted_result"&&v()};return window.addEventListener("message",_e),()=>{d=!1,I(),clearInterval(ze),window.removeEventListener("message",_e),U.current=null}},[e,g,f]);let lt=ee(()=>{if(!e)return;let d=window.open("","soba-connect-plan","width=520,height=760,noopener=no");U.current=d,p("hosted"),le(Date.now()),ke(null),_(null),e.startHosted().then(({url:v})=>{if(d&&!d.closed){d.location.href=v;return}ke(v)}).catch(v=>{d?.close(),U.current=null,_(v.message),p("choose")})},[e]),qn=ee(async d=>{if(e){V(!0);try{await e.disconnectHosted(d),he((await e.hosted()).credentials)}catch(v){_(v.message)}finally{V(!1)}}},[e]);X(()=>{if(!e||!f||g!=="waiting")return;let d=!0,v=Ie(async()=>{try{let A=await e.machines();if(!d)return;H(A);let I=Be.current;if(!I)return;let ze=A.filter(Oe=>!I.has(Oe.id)),_e=ze.find(Oe=>Oe.state!=="offline")??ze[0];_e&&(on(_e.id),S&&Lt(Fe,S),p("connected"),r?.(A))}catch{}},It,{immediate:!1});return()=>{d=!1,v()}},[g,e,r,S,Fe,f]);let Wn=ee(async()=>{if(e){_(null),V(!0);try{let d=await e.lookup(M);ne(d),p("confirm")}catch(d){_(d.message)}finally{V(!1)}}},[e,M]),ue=ee(async()=>{if(e){_(null),V(!0);try{try{Be.current=new Set((await e.machines()).map(d=>d.id))}catch{Be.current=new Set(k.map(d=>d.id))}await e.approve(M),p("waiting"),tn(Date.now())}catch(d){_(d.message)}finally{V(!1)}}},[e,M,k]),Ge=ee(async()=>{if(e){V(!0);try{await e.deny(M),ie("browser"),p("denied")}catch(d){_(d.message)}finally{V(!1)}}},[e,M]),z=$e(()=>y?.connect_url??null,[y]),[xe,w]=D(()=>Rn()),Y=$e(()=>z?Mn(z,xe??void 0,S??void 0):null,[z,xe,S]),oe=$e(()=>En(z),[z]),Fn=ee(d=>{if(k.length===0)return null;let v=se.find(I=>I.id===d);if(!v)return null;let A=k.flatMap(I=>I.runtimes??[]).filter(I=>v.expects.includes(I.id));return A.length===0?{tone:"dim",text:"not installed"}:A.some(I=>I.authenticated===!0)?{tone:"ok",text:"ready"}:A.every(I=>I.authenticated===!1)?{tone:"warn",text:"needs signing in"}:{tone:"dim",text:"installed"}},[k]),Se=ee((d=null)=>{it(d),_(null),Ce(null),He(!1),Re(!1),wn.current=!1,w(Rn()),p("launch")},[]),wn=pn(!!t);X(()=>{g!=="launch"||!z||wn.current||(wn.current=!0,He(!0),Pt(z,{...xe?{nonce:xe}:{},...S?{want:S}:{}}).then(Ce))},[g,z,xe,S]);let Le=ee(()=>{He(!0),St().then(Ce)},[]),cn=ee(d=>{if(W){let v=Rn();Re(!1),w(v),z&&(d.preventDefault(),window.location.href=Mn(z,v??void 0,S??void 0))}Le()},[W,Le,z,S]),ct=$e(()=>{let d=y?.runtimes;return d?se.filter(v=>d.includes(v.id)):bt()},[y?.runtimes]),Pe=$e(()=>{let d=se.find(v=>v.id===S);return d?{choice:d,Mark:Te[d.id]??null}:null},[S]),ut=$e(()=>k.find(d=>d.id===Ue),[k,Ue]);X(()=>{let d=xe;if(!e||!f||g!=="launch"||!d)return;let v=!1,A=Date.now()+15e4,I=()=>{};return I=Ie(async()=>{if(Date.now()>A){I(),Re(!0);return}try{let ze=await e.claim(d);if(v)return;if(ze.declined){I(),Ce(null),ie("machine"),p("denied");return}if(!ze.claimed)return;I();try{Be.current=new Set((await e.machines()).map(_e=>_e.id))}catch{Be.current=new Set(k.map(_e=>_e.id))}p("waiting"),tn(Date.now())}catch{}},It,{immediate:!1,idle:!1}),()=>{v=!0,I()}},[e,g,k,xe,f]);let Ve=$e(()=>{if(!P)return null;if(P.approved||P.denied)return"answered";let d=P.expires_at?Date.parse(P.expires_at):Number.NaN;return Number.isFinite(d)&&d<=ae?"expired":"live"},[P,ae]);X(()=>{if(!(g==="confirm"&&Ve==="live"||g==="waiting"||g==="hosted"))return;let v=setInterval(()=>ve(Date.now()),1e3);return()=>clearInterval(v)},[g,Ve]);let mr=ee(async(d,v)=>{if(e)try{await e.approveRuntime(d,v),H(await e.machines())}catch(A){_(A.message)}},[e]);return g==="loading"?l("div",{className:"soba-connect",...u?{"data-theme":u}:{},style:an,children:l("div",{className:"sc-card",children:l("p",{className:"sc-note",children:"Loading\u2026"})})}):N("div",{className:"soba-connect",...u?{"data-theme":u}:{},style:an,children:[c&&l("button",{type:"button",className:"sc-modal-close",onClick:c,"aria-label":"Close",children:"\xD7"}),g==="manage"&&N("div",{className:"sc-card",children:[l("h2",{className:"sc-title",id:ce,children:"Your compute"}),N("p",{className:"sc-sub",children:[l(Yn,{context:y})," ",k.length>0&&F.length>0?"runs on your connected plan, and on these machines while they are awake.":F.length>0?"runs on the plan you connected. Nothing here is charged to you.":"runs on these machines, while they are awake."]}),l(Qe,{machines:k,hosted:F,onApproveRuntime:mr,onDisconnectHosted:d=>void qn(d),onPair:()=>p("choose"),busy:q,...y?.app.name?{appName:y.app.name}:{}}),O&&l("p",{className:"sc-error",children:O})]}),g==="choose"&&N("div",{className:"sc-card",children:[l(Ao,{context:y}),l("h2",{className:"sc-h",id:ce,children:m==="payment_required"?"Carry on with your own AI":m==="no_compute"?"This run needs a machine":"Connect your AI"}),l("p",{className:"sc-p",children:"Use compute you already have."}),z&&ct.length>0&&N(Zn,{children:[l("div",{className:"sc-opts",children:ct.map(d=>{let v=Te[d.id];return N("button",{type:"button",className:"sc-opt",onClick:()=>Se(d.id),children:[l("span",{className:"sc-opt-tile","aria-hidden":"true",children:v&&l(v,{className:"sc-opt-mark"})}),l("span",{className:"sc-opt-text",children:l("span",{className:"sc-opt-label",children:d.label})}),(()=>{let A=Fn(d.id);return A?l("span",{className:`sc-opt-has sc-opt-has-${A.tone}`,children:A.text}):sn===d.id?l("span",{className:"sc-opt-last",children:"last used"}):l(Dt,{className:"sc-opt-go"})})()]},d.id)})}),N("p",{className:"sc-opt-note",children:["Your accounts stay there. ",Sr(y)," never sees them."]})]}),(!z||ct.length===0)&&l("p",{className:"sc-error",style:{marginTop:16},children:"This app has no publishable key yet, so there is nothing to pair against."}),O&&l("p",{className:"sc-error",children:O}),z&&y?.show_code===!0&&l("div",{className:"sc-opt-alt",children:l("button",{type:"button",className:"sc-alt-link",onClick:()=>p("code"),children:"I have a code"})})]}),g==="launch"&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("choose")}),l("p",{className:"sc-head-title",children:"Soba App"})]}),l(Qn,{mark:Pe?.Mark??j,still:W||!Ne&&K===null}),l("h2",{className:"sc-h",id:ce,children:W?"No answer from this machine":K==="absent"?"Nothing opened":K===null?"Opening Soba App\u2026":"Approve it on this machine"}),W?l("p",{className:"sc-p",children:"The Soba app did not answer. It may not be open, or nobody was there. Try again when you are ready."}):K==="absent"?l("p",{className:"sc-p",children:"Nothing opened on this machine. Open it yourself below, or install it if it is not here yet."}):l("p",{className:"sc-p",children:K===null?"Approve it there and this page does the rest.":"This page finishes on its own."}),Pe&&N("p",{className:"sc-prereq",children:[Pe.Mark&&l(Pe.Mark,{className:"sc-rt-mark"}),"Needs ",Pe.choice.prerequisite]}),N("div",{className:"sc-stack",style:{marginTop:18},children:[l("a",{className:K==="absent"||W?"sc-btn sc-btn-primary":"sc-btn",href:Y??"#",onClick:cn,children:W?"Try again":K==="absent"?"Open Soba App":"Open it again"}),l("p",{className:"sc-note",children:K===null?"Your browser will ask permission first.":"Your browser asks permission the first time."}),Pe&&K==="absent"&&l("p",{className:"sc-note",children:l(Io,{text:Pe.choice.hint})}),N("div",{className:"sc-foot-strip",children:[l("span",{children:"Not installed on this machine?"}),N("button",{type:"button",className:"sc-foot-go",onClick:()=>p("get"),children:["Get it",l(Dt,{})]})]})]})]}),g==="get"&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("launch")}),l("p",{className:"sc-head-title",children:"Get Soba App"})]}),l("div",{className:"sc-opts",children:_n.map(d=>N("a",{className:"sc-opt",href:`${oe}/download/${d.slug}`,target:"_blank",rel:"noreferrer noopener",children:[l("span",{className:"sc-opt-tile","aria-hidden":"true",children:l(gt,{className:"sc-opt-mark"})}),l("span",{className:"sc-opt-text",children:l("span",{className:"sc-opt-label",children:d.label})}),l(Dt,{className:"sc-opt-go"})]},d.slug))}),l("p",{className:"sc-opt-note",children:"Install it, then come back here and press the row you started with."})]}),g==="code"&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("choose")}),l("p",{className:"sc-head-title",children:"Soba App"})]}),l("h2",{className:"sc-h",id:ce,children:"Enter the code from that machine"}),l("p",{className:"sc-p",children:"Eight characters, shown by the Soba app once you paste the link."}),N("form",{className:"sc-stack",style:{marginTop:16},onSubmit:d=>{d.preventDefault(),Wn()},children:[l("input",{className:"sc-input",value:M,onChange:d=>me(d.target.value),placeholder:"ACDE-F234",autoComplete:"off",autoFocus:!0,"aria-label":"Pairing code"}),O&&l("p",{className:"sc-error",children:O}),l("button",{type:"submit",className:"sc-btn sc-btn-primary",disabled:q||M.length<8,children:q?"Checking\u2026":"Continue"})]})]}),g==="confirm"&&P&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("code")}),l("p",{className:"sc-head-title",children:"Soba App"})]}),l("h2",{className:"sc-title",children:"Attach this machine to your account?"}),N("p",{className:"sc-sub",children:[l(Yn,{context:y})," may send your runs to it once you approve. It can never see the account or the keys on it."]}),N("ul",{className:"sc-facts",children:[l(Ln,{k:"Code",v:P.user_code}),l(Ln,{k:"Machine",v:P.hostname??"not stated"}),l(Ln,{k:"System",v:[P.platform,P.arch].filter(Boolean).join(" / ")||"not stated"}),l(Ln,{k:"Asked by",v:P.client??"not stated"}),P.labels.length>0&&l(Ln,{k:"Labels",v:P.labels.join(", ")})]}),l("p",{className:"sc-note",style:{marginTop:12},children:"Every line above is what that machine said about itself. If none of it looks like a computer of yours, say no."}),Ve==="expired"&&l("p",{className:"sc-error",children:"That code has expired. Ask the machine for a new one. It prints a fresh code each time it starts."}),Ve==="answered"&&l("p",{className:"sc-error",children:"That code has already been answered. If it was not you, deny the next one."}),O&&l("p",{className:"sc-error",children:O}),N("div",{className:"sc-row",style:{marginTop:16},children:[l("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:()=>void ue(),disabled:q||Ve!=="live",children:"Approve"}),l("button",{type:"button",className:"sc-btn",onClick:()=>void Ge(),disabled:q||Ve==="answered",children:"No, deny it"})]}),Ve==="live"&&P.expires_at&&N("p",{className:"sc-note",style:{marginTop:10},children:["This code expires in ",Oo(Date.parse(P.expires_at)-ae),"."]})]}),g==="waiting"&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("choose")}),l("p",{className:"sc-head-title",children:Pe?.choice.short??"Soba App"})]}),l(Qn,{mark:Pe?.Mark??j}),l("h2",{className:"sc-h",id:ce,children:"Approved. Waiting for it to connect"}),l("p",{className:"sc-p",children:"Nothing more to do here. This page changes when it arrives."}),te>0&&ae-te>Ro&&l("p",{className:"sc-note sc-tone-warn",style:{marginTop:14,textAlign:"center"},children:"Still nothing. Look at the Soba app on that machine: it says what it is doing. This keeps watching either way."})]}),g==="connected"&&N("div",{className:"sc-card",children:[l(Ht,{tone:"ok"}),l("h2",{className:"sc-h",id:ce,children:ut?.label?`${ut.label} is connected`:"Connected"}),N("p",{className:"sc-p",children:[l(Yn,{context:y})," will use ",ut?.label?"it":"this machine"," from now on, while it is awake."]}),o&&N(Zn,{children:[l("div",{style:{marginTop:16},children:l(xn,{machines:k,onApproveRuntime:mr})}),l("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:14},onClick:()=>p("manage"),children:"Done"})]})]}),g==="hosted"&&N("div",{className:"sc-card",children:[N("div",{className:"sc-head",children:[l(mn,{onClick:()=>p("choose")}),l("p",{className:"sc-head-title",children:"ChatGPT"})]}),fe?l(Qn,{mark:Ye,still:!0}):l(Qn,{mark:Ye}),l("h2",{className:"sc-h",id:ce,children:fe?"Your browser blocked the window":"Finish signing in to ChatGPT"}),l("p",{className:"sc-p",children:fe?"Nothing opened. Open the sign-in yourself below. A link you click is allowed where a window we open is not.":"Approve it in the window that opened."}),N("div",{className:"sc-stack",style:{marginTop:18},children:[fe&&l("a",{className:"sc-btn sc-btn-primary",href:fe,target:"soba-connect-plan",rel:"noreferrer",children:"Open the ChatGPT sign-in"}),O&&l("p",{className:"sc-error",children:O}),T>0&&ae-T>Lo&&l("p",{className:"sc-note sc-tone-warn",children:"Still nothing. The window may have been closed before it finished, or the sign-in may have been declined. This keeps watching either way."})]})]}),g==="hosted_connected"&&N("div",{className:"sc-card",children:[l(Ht,{tone:"ok"}),l("h2",{className:"sc-h",id:ce,children:"ChatGPT is connected"}),N("p",{className:"sc-p",children:[l(Yn,{context:y})," will run on your ChatGPT plan",F[0]?.account_label?` (${F[0].account_label})`:"",". Nothing more to pay, nothing to install."]}),l("p",{className:"sc-opt-note",style:{textAlign:"center"},children:"It runs on our side, so it has no access to your files or your terminal."}),o&&N(Zn,{children:[l("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>p("manage"),children:"Done"}),l("div",{className:"sc-opt-alt",children:l("button",{type:"button",className:"sc-alt-link",onClick:()=>p("choose"),children:"Connect a machine too"})})]})]}),g==="denied"&&N("div",{className:"sc-card",children:[l(Ht,{tone:"off"}),l("h2",{className:"sc-h",id:ce,children:"Declined"}),l("p",{className:"sc-p",children:rn==="machine"?"Nothing was connected. You can ask again whenever you like.":"That machine was not attached to your account, and the terminal has been told so."}),l("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>p("choose"),children:"Back to the start"})]})]})}function Sr(e){return e?.app.name??"this app"}function To(e){let n=e?.app.icon_urls;if(n?.length)return n;let t=e?.app.icon_url;return t?[t]:[]}function Pr(e){let n=To(e),[t,r]=D([]),o=ee(c=>{c&&r(i=>i.includes(c)?i:[...i,c])},[]),a=ee(c=>o(c.currentTarget.getAttribute("src")),[o]),s=ee(c=>{c?.complete&&c.naturalWidth===0&&o(c.getAttribute("src"))},[o]);return{icon:n.find(c=>!t.includes(c)),onError:a,ref:s}}function Ao({context:e}){let{icon:n,onError:t,ref:r}=Pr(e);return e?.app.mark==="soba"?l(j,{className:"sc-app-mark"}):n?l("img",{className:"sc-app-mark",src:n,alt:"","aria-hidden":"true",ref:r,onError:t}):null}function Yn({context:e}){let{icon:n,onError:t,ref:r}=Pr(e),o=e?.app.mark==="soba";return N("span",{className:"sc-app",children:[o&&l(j,{className:"sc-app-icon"}),!o&&n&&l("img",{className:"sc-app-icon",src:n,alt:"",ref:r,onError:t}),Sr(e)]})}function mn({onClick:e}){return l("button",{type:"button",className:"sc-head-back",onClick:e,"aria-label":"Back",children:l("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:l("path",{d:"M15 5 8 12l7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}function Dt({className:e}){return l("svg",{className:e,viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:l("path",{d:"M9 5l7 7-7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function Qn({mark:e,still:n}){return N("span",{className:"sc-waiting","aria-hidden":"true",children:[!n&&l("svg",{className:"sc-waiting-orbit",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:l("circle",{className:"sc-waiting-arc",cx:"50",cy:"50",r:"46"})}),l(e,{className:"sc-waiting-mark"})]})}function Ht({tone:e}){return l("span",{className:`sc-result sc-result-${e}`,"aria-hidden":"true",children:l(kt,{kind:e==="ok"?"snap":"gone",size:84})})}function Io({text:e}){return l(Zn,{children:e.split("`").map((n,t)=>t%2===1?l("code",{className:"sc-inline-code",children:n},t):n)})}function Ln({k:e,v:n}){return N("li",{className:"sc-fact",children:[l("span",{className:"sc-fact-key",children:e}),l("span",{children:n})]})}import{useEffect as $o,useRef as qt}from"react";var Jn=0,Bt=null;function _r(){if(typeof document>"u")return()=>{};Jn===0&&(Bt=document.body.style.overflow,document.body.style.overflow="hidden"),Jn+=1;let e=!1;return()=>{e||(e=!0,Jn-=1,Jn===0&&(document.body.style.overflow=Bt??"",Bt=null))}}import{jsx as Er}from"react/jsx-runtime";function On({open:e,onClose:n,labelledBy:t,theme:r,style:o,children:a}){let s=qt(null),c=qt(null),i=qt(null);return $o(()=>{let u=s.current;if(u){if(!e){u.open&&u.close();return}return u.open||u.showModal(),document.activeElement===u&&c.current?.focus(),_r()}},[e]),Er("dialog",{ref:s,className:"soba-connect sc-modal","aria-labelledby":t,...r?{"data-theme":r}:{},style:o,onCancel:u=>{u.preventDefault(),n()},onPointerDown:u=>{i.current=u.target},onClick:u=>{u.target===u.currentTarget&&i.current===u.currentTarget&&n()},children:Er("div",{className:"sc-modal-sheet",ref:c,tabIndex:-1,children:a})})}import{useEffect as Wt,useRef as Do}from"react";import{jsx as Ho}from"react/jsx-runtime";var Je=8;function Ft({open:e,onClose:n,anchor:t,label:r,theme:o,style:a,children:s}){let c=Do(null);return Wt(()=>{let i=c.current;if(!(!i||!(typeof i.showPopover=="function")))try{e?i.showPopover():i.hidePopover()}catch{}},[e]),Wt(()=>{if(!e)return;let i=()=>{let m=c.current,f=t.current;if(!m||!f)return;let b=f.getBoundingClientRect(),g=m.offsetWidth,p=m.offsetHeight,y=window.innerWidth-g-Je,E=Math.max(Je,Math.min(b.right-g,Math.max(Je,y))),k=b.bottom+Je,H=b.top-Je-p,M=k+p>window.innerHeight-Je&&H>Je?H:k;m.style.left=`${Math.round(E)}px`,m.style.top=`${Math.round(M)}px`};i();let u=requestAnimationFrame(i);return window.addEventListener("scroll",i,!0),window.addEventListener("resize",i),()=>{cancelAnimationFrame(u),window.removeEventListener("scroll",i,!0),window.removeEventListener("resize",i)}},[e,t]),Wt(()=>{if(!e)return;let i=m=>{m.key==="Escape"&&n()},u=m=>{let f=m.target;f&&(c.current?.contains(f)||t.current?.contains(f)||n())};return document.addEventListener("keydown",i),document.addEventListener("pointerdown",u,!0),()=>{document.removeEventListener("keydown",i),document.removeEventListener("pointerdown",u,!0)}},[e,n,t]),Ho("div",{ref:c,role:"dialog","aria-label":r,className:"soba-connect sc-pop",...o?{"data-theme":o}:{},popover:"manual",hidden:!e,style:a,children:s})}function Ee(e){let n=`${e.unit}s`;return e.reward==="unlimited"?`Unlimited ${n} on your own AI`:e.reward==="included"&&e.includedUnits!==null?`${Bo(e.includedUnits)} ${n} a month once you connect`:e.reward==="credit"&&e.creditMicros>0?`${Uo(e.creditMicros)} back each month you stay connected`:null}function Me(e){return e==="unlimited"||e==="included"}var Rr=new Set(["user-hardware","user-subscription"]),Mr=new Set(["open-weights","frontier"]);function de(e){return e===null||e.length===0?!1:e.every(n=>Rr.has(n))}var Uo=e=>(e/1e6).toLocaleString("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}),Bo=e=>e.toLocaleString("en-US");function Gt(e,n){if(!(n===null||n.some(a=>Mr.has(a))))return!1;let r=e.findIndex(a=>Rr.has(a));if(r===-1)return!1;let o=e.findIndex(a=>Mr.has(a));return o===-1||r<o}import{createContext as qo,useContext as Wo}from"react";var Vt=qo(null);function B(){let e=Wo(Vt);if(!e)throw new Error("useSoba() must be used inside a <SobaProvider>.");return e}import{createContext as Lr,useContext as Or}from"react";var zt=Lr(null);function Xn(){return Or(zt)}var Kt=Lr({context:null,machines:void 0,theme:"light"});function $(){return Or(Kt)}import{jsx as Tn}from"react/jsx-runtime";function Fo({className:e}){let{theme:n}=$(),t=e?`soba-connect ${e}`:"soba-connect";return Tn("div",{className:t,"data-theme":n,children:Tn(jt,{})})}function jt(){let{compute:e}=B();return e.loading&&!e.machines.length?Tn("p",{className:"sc-note",children:"Loading\u2026"}):e.error&&!e.machines.length?Tn("p",{className:"sc-error",children:e.error.message}):Tn(xn,{machines:e.machines})}import{useCallback as nt,useEffect as Yt,useRef as Qt,useState as fn}from"react";import{useId as Go}from"react";import{jsx as hn,jsxs as et}from"react/jsx-runtime";function An({open:e,onOpenChange:n,initialCode:t,onConnected:r,showStatus:o,reason:a}){let{error:s}=B(),c=Xn(),i=$(),u=()=>n(!1),m=Go(),f=i.context?.background?.trim(),b=f?Ke(f,i.context?.accent):void 0;return et(On,{open:e,onClose:u,labelledBy:m,theme:i.theme,style:b,children:[s?et("div",{className:"sc-card",children:[hn("h2",{className:"sc-title",id:m,children:"Could not start"}),hn("p",{className:"sc-error",children:s.message})]}):!c&&!i.context?et("div",{className:"sc-card",children:[hn("h2",{className:"sc-title",id:m,children:"One moment"}),hn("p",{className:"sc-note",children:"Getting your compute\u2026"})]}):hn(Ut,{client:c,active:e,onClose:u,headingId:m,theme:i.theme,initialContext:i.context,...i.machines!==void 0?{initialMachines:i.machines}:{},...t?{initialCode:t}:{},...r?{onConnected:r}:{},...o===void 0?{}:{showStatus:o},...a?{reason:a}:{}}),et("p",{className:"sc-modal-foot",children:[hn(j,{className:"sc-foot-mark"}),"Secured by Soba"]})]})}import{Fragment as Zt,jsx as De,jsxs as In}from"react/jsx-runtime";function Xe({children:e,variant:n,className:t,initialCode:r,onConnected:o,defaultOpen:a,open:s,onOpenChange:c,showConnected:i=!0}){let{compute:u,connect:m}=B(),f=$(),{theme:b}=f,g=Xn(),[p,y]=fn(a??!!r),E=Qt(null),k=s!==void 0,H=!k&&!a&&!r&&m.hasModal,M=k?s:H?m.isOpen:p,me=T=>{H?T?m.open("manual"):m.close():k||y(T),c?.(T)},P=Qt(M);Yt(()=>{P.current&&!M&&E.current?.focus(),P.current=M},[M]);let ne=kn(u.machines),O=i&&ne!==null,_=dn(ne),[q,V]=fn(!1),te=nt(()=>V(!1),[]),[tn,ae]=fn(!1),ve=nt(async()=>{ae(!0);try{await u.refresh()}finally{ae(!1)}},[u]),K=Qt(ve);K.current=ve,Yt(()=>{q&&K.current()},[q]);let[Ce,Ne]=fn(!1),[He,W]=fn([]),Re=!!f.context?.hosted_available;Yt(()=>{if(!q||!g||!Re)return;let T=!0;return g.hosted().then(le=>{T&&W(le.credentials)}).catch(()=>{}),()=>{T=!1}},[q,g,Re]);let[rn,ie]=fn(null),Ue=nt(async(T,le)=>{if(g){ie(null);try{await g.approveRuntime(T,le),await u.refresh()}catch(fe){ie(fe.message)}}},[g,u]),on=nt(async T=>{if(g){ie(null);try{await g.disconnectHosted(T),W((await g.hosted()).credentials)}catch(le){ie(le.message)}}},[g]),F=f.context?.background?.trim(),he=F?Ke(F,f.context?.accent):void 0;return In(Zt,{children:[De("button",{ref:E,type:"button","data-theme":b,className:["sc-btn",O?"sc-btn-connected":"sc-btn-icon",!O&&n==="primary"?"sc-btn-primary":"",t].filter(Boolean).join(" "),...O&&!e?{"aria-haspopup":"dialog","aria-expanded":q,"aria-label":ne?`${_.word} on ${je(ne)}`:_.word}:{},onClick:()=>{if(O&&!e&&!k&&!a&&!r){V(T=>!T);return}me(!0)},children:e??(O?In(Zt,{children:[De("span",{className:"sc-pill-tile","aria-hidden":"true",children:De(j,{className:_.tone==="busy"?"sc-pill-mark sc-pill-mark-busy":"sc-pill-mark"})}),In("span",{className:"sc-btn-connected-text",children:[_.word,ne&&In("span",{className:"sc-btn-connected-where",children:[" on ",je(ne)]})]}),De("i",{className:`sc-dot sc-dot-${_.tone}`,"aria-hidden":"true"})]}):In(Zt,{children:[De(j,{className:"sc-btn-mark"}),"Connect compute"]}))}),De(Ft,{open:q,onClose:te,anchor:E,label:"Your compute",theme:b,...he?{style:he}:{},children:De(Qe,{machines:u.machines,hosted:He,onApproveRuntime:(T,le)=>void Ue(T,le),onDisconnectHosted:T=>void on(T),onRefresh:()=>void ve(),refreshing:tn,error:rn,onPair:()=>{V(!1),H?m.open("pair"):(Ne(!0),me(!0))},...f.context?.app.name?{appName:f.context.app.name}:{}})}),!H&&De(An,{open:M,onOpenChange:T=>{T||Ne(!1),me(T)},...Ce?{showStatus:!1}:{},...r?{initialCode:r}:{},...o?{onConnected:o}:{}})]})}import{jsx as Jt,jsxs as zo}from"react/jsx-runtime";function Vo({initialCode:e,onConnected:n,className:t,showStatus:r=!0}){let{theme:o}=$();return zo("div",{className:t?`soba-connect ${t}`:"soba-connect","data-theme":o,children:[r&&Jt(jt,{}),Jt("div",{className:"sc-compute-act",children:Jt(Xe,{...e?{initialCode:e}:{},...n?{onConnected:n}:{}})})]})}import{useEffect as Hr,useId as Xo,useState as er}from"react";import{useCallback as Ko,useState as jo}from"react";function tt(){let[e,n]=jo(null);return{open:Ko(()=>{n(null),_t().then(n)},[]),launch:e,note:e==="absent"?"Nothing opened here. That machine may be a different computer, or asleep.":null}}import{useCallback as Tr,useMemo as Ar}from"react";function en(e){if(!e)return null;if(typeof e=="string")return e;if(typeof Response<"u"&&e instanceof Response)return Ir(e.status);let n=e,t=n.error;return typeof t?.code=="string"?t.code:typeof t?.type=="string"?t.type:typeof n.code=="string"?n.code:typeof n.status=="number"?Ir(n.status):n.cause&&n.cause!==e?en(n.cause):null}function Ir(e){return e===402?"payment_required":e===409?"no_compute":null}function Xt(...e){let[n,t]=e,{plan:r,compute:o,connect:a}=B(),s=t?.predict??e.length===0,c=Qo(Yo(n),o)??(s?Zo(r,o):null),i=r.plan,u=r.plans,m=Ar(()=>{if(c!=="payment_required")return null;let p=i?.price??0,y=i?.included_units??0;return u.find(E=>E.id!==i?.id&&E.price>p&&(E.included_units===null||E.included_units>y))??null},[c,u,i]),f=Tr(async()=>{if(!m)return;if(m.selectable){await r.select(m.id);return}let p=await r.checkout(m.id);window.location.assign(p)},[m,r]),b=a.open,g=Tr(()=>{c&&b(c)},[b,c]);return Ar(()=>{if(!c)return null;let p=i?Ee({unit:i.unit,reward:i.connected_reward,includedUnits:i.connected_included_units,creditMicros:i.connected_credit*1e6}):null,y=i&&Me(i.connected_reward)?p:null;return{reason:c,...Jo(c,{connectOffer:y,connected:o.connected,online:o.online,machine:Nn(o.machines)?.label??null,unit:i?.unit??"message",interval:i?.interval??"month",upgrade:m!==null,resets:r.current?.period_end??null}),connectOffer:y,upgradeTo:m,connect:g,upgrade:f}},[c,i,o,m,g,f,r.current?.period_end])}function Yo(e){let n=en(e);return n==="payment_required"||n==="no_compute"?n:null}function Qo(e,n){return e==="no_compute"&&n.connected&&n.online?null:e}function Zo(e,n){let t=e.plan;return!t||n.loading?null:de(t.route_allow)&&!n.online?"no_compute":e.remaining===0&&t.overage==="stop"?"payment_required":null}function Jo(e,n){if(e==="payment_required"){let t=`No ${n.unit}s left this ${n.interval}`;return n.connectOffer&&!n.connected?{title:t,body:`${n.connectOffer}. Connecting takes a minute and costs nothing.`}:n.connectOffer&&!n.online?{title:t,body:`${n.connectOffer}. Waking ${n.machine??"your machine"} is enough.`}:n.upgrade?{title:t,body:n.resets?`A larger plan carries on now. This one comes back on ${$r(n.resets)}.`:"A larger plan carries on now, or wait for this one to renew."}:{title:t,body:n.resets?`Your allowance comes back on ${$r(n.resets)}.`:"Your allowance comes back at the start of the next period."}}return n.connected&&!n.online?{title:`${n.machine??"Your machine"} can't be reached`,body:"This run needs it awake and connected. Open Soba App on that machine, or connect another one."}:{title:"Nothing connected yet",body:"This app runs on AI you already pay for, on a machine of your own. Connect one and this run has somewhere to go."}}function $r(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as nr,jsx as R,jsxs as be}from"react/jsx-runtime";function es(e){let{at:n=.25,className:t,error:r,fallback:o=null}=e,a=e.predict??!("error"in e),{plan:s,compute:c,connect:i}=B(),{theme:u}=$(),[m,f]=er(null),b=Xo(),g=Ot(i.publishableKey),[p,y]=er(!1);Hr(()=>{y(Tt(g))},[g]);let E=R(nr,{children:o}),k=s.plan;if(!k||s.loading||c.loading)return E;let H=e.allow!==void 0?e.allow:k.route_allow;if(c.connected)return c.online?E:R(Dr,{className:t,theme:u,stalled:!0,children:R(ns,{machine:Nn(c.machines)?.label??null,ownCompute:de(H),onConnectAnother:()=>i.open("no_compute")})});let M=(()=>{let _=en(r);return _==="payment_required"||_==="no_compute"})(),me=k.ask_to_connect!==!1&&Gt(k.route_prefer,H);if(!a&&!M&&!me)return E;let P=de(H)?rs(k.unit,de(k.route_allow)):Me(k.connected_reward)?ss(s,k,n):me?os(k.unit):null;if(!P||P.dismissible&&p)return E;let ne=!P.dismissible&&(!a||P.meter!==null&&P.meter.left===0),O=m??ne;return be(Dr,{className:t,theme:u,children:[be("div",{className:"sc-nudge-top",children:[be("div",{className:"sc-nudge-say",children:[R("p",{className:"sc-nudge-title",children:P.title}),R("p",{className:"sc-nudge-detail",children:P.detail}),be("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more","aria-expanded":O,"aria-controls":b,onClick:()=>f(!O),children:[O?"Hide the details":"How it works",R(is,{})]})]}),P.dismissible?R("button",{type:"button",className:"sc-nudge-dismiss","aria-label":"Dismiss",title:"Dismiss",onClick:()=>{y(!0),At(g)},children:R(as,{})}):null]}),O?R("ol",{className:"sc-nudge-steps",id:b,children:ts(i.app?.name,En(i.connectUrl)).map(_=>be("li",{children:[_.opens?R("button",{type:"button",className:"sc-step-lead",onClick:()=>i.open("manual"),children:_.lead}):R("strong",{children:_.lead}),_.detail?R("span",{children:_.detail}):null,_.links.length>0?be("span",{className:"sc-step-links",children:[_.linksLead,_.links.map(q=>R("a",{href:q.href,target:"_blank",rel:"noreferrer noopener",children:q.label},q.href))]}):null]},_.lead))}):null,R(Xe,{variant:"primary"})]})}function Dr({className:e,theme:n,stalled:t,children:r}){return R("div",{className:e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill","data-theme":n,children:R("div",{className:t?"sc-nudge sc-nudge-stalled":"sc-nudge",children:r})})}function ns({machine:e,ownCompute:n,onConnectAnother:t}){let r=tt(),{compute:o}=B(),[a,s]=er(!1),{refresh:c}=o;return Hr(()=>{if(r.launch===null||r.launch==="absent")return;s(!1);let i=setInterval(()=>void c(),3e3),u=setTimeout(()=>{clearInterval(i),s(!0)},2e4);return()=>{clearInterval(i),clearTimeout(u)}},[r.launch,c]),be(nr,{children:[R("div",{className:"sc-nudge-top",children:be("div",{className:"sc-nudge-say",children:[be("p",{className:"sc-nudge-title",children:[e??"Your machine"," can\u2019t be reached"]}),R("p",{className:"sc-nudge-detail",children:n?"The Soba app there has stopped reporting in, so runs have nowhere to go until it is back.":"The Soba app there has stopped reporting in, so nothing will run on your own AI until it is back."}),r.note&&R("p",{className:"sc-nudge-note",children:r.note}),a&&R("p",{className:"sc-nudge-note",children:"The Soba app is open, but this machine still isn\u2019t reporting in. It may no longer be connected to this app."}),(r.launch==="absent"||a)&&R("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more",onClick:t,children:a?"Connect it again":"Connect another machine"})]})}),R("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:r.open,children:"Open Soba App"})]})}function ts(e,n){return[{lead:"Download Soba App",detail:"",linksLead:n?"Get it for":void 0,links:n?_n.map(t=>({label:t.label,href:`${n}/download/${t.slug}`})):[]},{lead:"Connect compute",detail:"Press this, then approve the pairing when the app asks.",opens:!0,links:[]},{lead:"Let your AIs serve",detail:`It finds what is installed on that machine. Allow one, and ${e??"this app"} sends every run there.`,linksLead:"Nothing on it yet?",links:se.map(t=>({label:t.short,href:t.install}))}]}function rs(e,n){return{title:n?"This plan runs on your own AI.":`These ${e}s run on your own AI.`,detail:`Connect a machine and your ${e}s run there, free, on access you already have.`,meter:null}}function os(e){return{title:"This plan prefers your own AI.",detail:`Connect a machine and your ${e}s run there instead, on access you already have.`,meter:null,dismissible:!0}}function ss(e,n,t){let{remaining:r,included:o}=e;if(r===null||o===null||o===0||r>Math.ceil(o*t))return null;let a=Ee({unit:n.unit,reward:n.connected_reward,includedUnits:n.connected_included_units,creditMicros:n.connected_credit*1e6});return a?{title:r===0?`No ${n.unit}s left this month.`:`${r} ${n.unit}${r===1?"":"s"} left this month.`,detail:be(nr,{children:[a,"."]}),meter:{left:r,of:o}}:null}function as(){return R("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-x",children:R("path",{d:"m4.8 4.8 6.4 6.4M11.2 4.8l-6.4 6.4",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"})})}function is(){return R("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-chev",children:R("path",{d:"M4.5 6.5 8 10l3.5-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})})}var ls=new Set(["delta","thinking","status","done","error"]);function rt(e){let n;try{n=JSON.parse(e)}catch{return null}if(!n||typeof n!="object")return null;let t=n,r=t.type==="event"?t.event:t;if(!r||typeof r!="object")return null;let o=r;if(typeof o.type!="string"||!ls.has(o.type))return null;let a={type:o.type};return typeof o.text=="string"&&(a.text=o.text),typeof o.message=="string"&&(a.message=o.message),typeof o.tool=="string"&&(a.tool=o.tool),typeof o.tier=="string"&&(a.tier=o.tier),o.usage&&typeof o.usage=="object"&&(a.usage=o.usage),a}async function*tr(e){let n=e.body;if(!n)throw new Error("That run response had no body to stream.");let t=(e.headers.get("content-type")??"").includes("ndjson"),r=n.getReader(),o=new TextDecoder,a="",s=[];try{for(;;){let i=await r.read();if(i.done)break;for(a+=o.decode(i.value,{stream:!0});;){let u=a.indexOf(`
3
+ `);if(u===-1)break;let m=Br(a.slice(0,u));if(a=a.slice(u+1),t){let f=m.trim()?rt(m):null;f&&(yield f);continue}if(m===""){let f=s.join(`
4
+ `);if(s=[],f==="[DONE]")return;let b=f?rt(f):null;b&&(yield b);continue}Ur(m,s)}}!t&&a&&Ur(Br(a),s);let c=t?a.trim():s.join(`
5
+ `);if(c&&c!=="[DONE]"){let i=rt(c);i&&(yield i)}}finally{r.cancel().catch(()=>{})}}function Ur(e,n){if(!e||e.startsWith(":"))return;let t=e.indexOf(":");if(t===-1||e.slice(0,t)!=="data")return;let r=e.slice(t+1);n.push(r.startsWith(" ")?r.slice(1):r)}function Br(e){return e.endsWith("\r")?e.slice(0,-1):e}async function cs(e){let n="";for await(let t of e)if(t.type==="delta"&&t.text&&(n+=t.text),t.type==="error")throw new Error(t.message??"The run ended with an error.");return n}import{useEffect as us}from"react";var qr="data-soba-react",Wr=!1;function $n(){if(Wr||typeof document>"u"||(Wr=!0,document.querySelector(`style[${qr}]`)))return;let e=document.createElement("style");e.setAttribute(qr,""),e.textContent=`.soba-connect {
6
6
  --sc-ground: #ffffff;
7
7
  --sc-sheet: #ffffff;
8
8
  --sc-raised: #f6f6f7;
@@ -16,6 +16,10 @@ var Sn=class extends Error{status;constructor(n,t){super(n),this.name="ConnectEr
16
16
  --sc-ok: #22a06b;
17
17
  --sc-warn: #b06f14;
18
18
 
19
+ --sc-tray: var(--sc-raised, #f6f6f7);
20
+ --sc-tray-card: var(--sc-sheet, #ffffff);
21
+ --sc-tray-sunk: var(--sc-raised, #f6f6f7);
22
+
19
23
  --sc-font-size: 15px;
20
24
  --sc-fs-label: max(11px, calc(var(--sc-font-size) * 0.77));
21
25
 
@@ -243,121 +247,182 @@ a.sc-btn {
243
247
  min-width: 92px;
244
248
  }
245
249
 
246
- .sc-machine {
247
- border-top: 1px solid var(--sc-line, #e9e9eb);
248
- padding-top: 12px;
249
- margin-top: 12px;
250
+ .sc-tray {
251
+ display: grid;
252
+ gap: 8px;
253
+ padding: 6px;
254
+ border-radius: 18px;
255
+ background: var(--sc-tray, #f6f6f7);
250
256
  }
251
- .sc-machine:first-child {
252
- border-top: 0;
253
- padding-top: 0;
254
- margin-top: 0;
257
+
258
+ .sc-group {
259
+ min-width: 0;
255
260
  }
256
261
 
257
- .sc-machine-meta {
262
+ .sc-group-cap {
258
263
  display: flex;
259
- flex-wrap: wrap;
260
264
  align-items: center;
261
- gap: 3px 10px;
262
-
263
- margin-top: 1px;
264
- font-size: var(--sc-fs-small);
265
- line-height: 1.35;
266
- color: var(--sc-muted, #6b6b73);
265
+ gap: 4px;
266
+ min-height: 24px;
267
+ padding: 0 2px 3px 12px;
267
268
  }
268
269
 
269
- .sc-machine-tag {
270
+ .sc-group-title {
271
+ flex: 1;
272
+ min-width: 0;
273
+ margin: 0;
274
+ overflow: hidden;
275
+ text-overflow: ellipsis;
276
+ white-space: nowrap;
270
277
  font-size: var(--sc-fs-label);
271
- font-weight: 600;
272
- padding: 1px 6px;
273
- border-radius: var(--sc-r-sm, 6px);
274
- background: var(--sc-raised, #f6f6f7);
278
+ letter-spacing: 0;
279
+ color: var(--sc-muted, #6b6b73);
275
280
  }
276
281
 
277
- .sc-machine-state {
278
- display: inline-flex;
279
- align-items: center;
280
- gap: 6px;
281
- font-size: var(--sc-fs-small);
282
- color: var(--sc-muted, #6b6b73);
283
- white-space: nowrap;
282
+ .sc-group-card {
283
+ padding: 6px 0 6px 12px;
284
+ border-radius: var(--sc-r-lg, 14px);
285
+ background: var(--sc-tray-card, #ffffff);
286
+ box-shadow: var(--sc-shadow-1);
284
287
  }
285
288
 
286
- .sc-runtimes {
289
+ .sc-disc {
290
+ flex: none;
287
291
  display: grid;
288
- gap: 2px;
289
- margin: 12px 0 0;
290
-
291
- --sc-branch: calc(var(--sc-tile, 32px) + 11px);
292
- padding: 0 0 0 var(--sc-branch);
293
- list-style: none;
294
- font-size: var(--sc-fs-small);
292
+ place-items: center;
293
+ width: 26px;
294
+ height: 26px;
295
+ padding: 0;
296
+ border: 0;
297
+ border-radius: 50%;
298
+ background: var(--sc-tray-card, #ffffff);
299
+ box-shadow: var(--sc-shadow-1);
300
+ color: var(--sc-muted, #6b6b73);
301
+ cursor: pointer;
302
+ transition: color 120ms ease;
295
303
  }
296
304
 
297
- .sc-compute-act {
298
- margin-top: 16px;
305
+ .sc-disc:hover:not(:disabled) {
306
+ color: var(--sc-text, #1a1a1c);
299
307
  }
300
308
 
301
- .sc-compute-act:first-child {
302
- margin-top: 0;
309
+ .sc-disc:disabled {
310
+ opacity: 0.6;
311
+ cursor: default;
303
312
  }
304
313
 
305
- .sc-note + .sc-compute-act,
306
- .sc-error + .sc-compute-act {
307
- margin-top: 9px;
314
+ .sc-dglyph {
315
+ width: 13px;
316
+ height: 13px;
317
+ }
318
+
319
+ @keyframes sc-spin {
320
+ to {
321
+ transform: rotate(360deg);
322
+ }
323
+ }
324
+
325
+ .sc-spin {
326
+ animation: sc-spin 900ms linear infinite;
308
327
  }
309
328
 
310
- .sc-runtime {
329
+ .sc-mrow {
330
+ display: flex;
331
+ align-items: center;
332
+ gap: 10px;
333
+ min-height: 52px;
334
+ padding: 4px 12px 4px 0;
335
+ }
336
+
337
+ .sc-mtile {
311
338
  position: relative;
339
+ flex: none;
312
340
  display: grid;
313
- grid-template-columns: auto 1fr auto;
314
- align-items: center;
315
- gap: 9px;
316
- min-height: 26px;
341
+ place-items: center;
342
+ width: 38px;
343
+ height: 38px;
344
+ border-radius: 12px;
345
+ background: var(--sc-tray-sunk, #f6f6f7);
346
+ box-shadow: inset 0 0 0 1px var(--sc-line, #e9e9eb);
347
+ color: var(--sc-text, #1a1a1c);
317
348
  }
318
349
 
319
- .sc-runtime::before {
320
- content: "";
350
+ .sc-mglyph {
351
+ width: 24px;
352
+ height: 18px;
353
+ }
354
+
355
+ .sc-mbadge {
321
356
  position: absolute;
322
- left: calc(var(--sc-tile, 32px) / 2 - var(--sc-branch));
323
- top: -2px;
324
- bottom: -2px;
325
- width: 1px;
357
+ right: 0;
358
+ bottom: 0;
359
+ width: 10px;
360
+ height: 10px;
361
+ border-radius: 50%;
362
+ transform: translate(30%, 30%);
363
+ box-shadow: 0 0 0 2.5px var(--sc-tray-card, #ffffff);
364
+ }
365
+
366
+ .sc-mbadge-ok {
367
+ background: var(--sc-ok, #22a06b);
368
+ }
369
+
370
+ .sc-mbadge-busy {
371
+ background: var(--sc-warn, #b06f14);
372
+ }
373
+
374
+ .sc-mbadge-off {
326
375
  background: var(--sc-line-2, #dcdce0);
327
376
  }
328
377
 
329
- .sc-runtime:first-child::before {
330
- top: -13px;
378
+ .sc-mid {
379
+ display: flex;
380
+ flex: 1;
381
+ min-width: 0;
382
+ flex-direction: column;
383
+ gap: 1px;
331
384
  }
332
385
 
333
- .sc-runtime:last-child::before {
334
- bottom: auto;
335
- height: calc(50% + 2px);
386
+ .sc-mname {
387
+ overflow: hidden;
388
+ text-overflow: ellipsis;
389
+ white-space: nowrap;
390
+ font-size: var(--sc-fs-small);
391
+ font-weight: 550;
336
392
  }
337
393
 
338
- .sc-runtime:first-child:last-child::before {
339
- height: calc(50% + 13px);
394
+ .sc-mmeta {
395
+ display: flex;
396
+ flex-wrap: wrap;
397
+ align-items: center;
398
+ gap: 1px 6px;
399
+ font-size: var(--sc-fs-label);
400
+ line-height: 1.35;
401
+ color: var(--sc-muted, #6b6b73);
340
402
  }
341
403
 
342
- .sc-runtime::after {
343
- content: "";
344
- position: absolute;
345
- left: calc(var(--sc-tile, 32px) / 2 - var(--sc-branch));
346
- top: 50%;
347
- width: 22px;
348
- height: 1px;
349
- background: var(--sc-line-2, #dcdce0);
404
+ .sc-mmeta-sep {
405
+ padding-right: 6px;
406
+ color: var(--sc-line-2, #dcdce0);
407
+ }
408
+
409
+ .sc-arow {
410
+ display: flex;
411
+ align-items: center;
412
+ gap: 10px;
413
+ min-height: 30px;
414
+ padding-right: 12px;
350
415
  }
351
416
 
352
417
  .sc-runtime-tile {
353
- width: 22px;
354
- height: 22px;
355
418
  flex: none;
356
419
  display: grid;
357
420
  place-items: center;
421
+ width: 22px;
422
+ height: 22px;
358
423
  border-radius: var(--sc-r-sm, 6px);
359
424
  border: 1px solid var(--sc-line, #e9e9eb);
360
- background: var(--sc-raised, #f6f6f7);
425
+ background: var(--sc-tray-sunk, #f6f6f7);
361
426
  }
362
427
 
363
428
  .sc-runtime-mark {
@@ -366,16 +431,200 @@ a.sc-btn {
366
431
  color: var(--sc-text-2, #3f3f46);
367
432
  }
368
433
 
369
- .sc-runtime-verdict {
434
+ .sc-aname {
435
+ flex: 1;
436
+ min-width: 0;
437
+ overflow: hidden;
438
+ text-overflow: ellipsis;
439
+ white-space: nowrap;
440
+ font-size: var(--sc-fs-small);
441
+ }
442
+
443
+ .sc-aversion {
444
+ color: var(--sc-muted, #6b6b73);
445
+ }
446
+
447
+ .sc-averdict {
448
+ flex: none;
449
+ display: inline-flex;
450
+ align-items: center;
370
451
  font-size: var(--sc-fs-label);
371
452
  white-space: nowrap;
453
+ color: var(--sc-muted, #6b6b73);
454
+ }
455
+
456
+ .sc-orow {
457
+ display: flex;
458
+ align-items: center;
459
+ gap: 10px;
460
+ min-height: 34px;
461
+ padding-right: 12px;
462
+ }
463
+
464
+ .sc-otile {
465
+ flex: none;
466
+ display: grid;
467
+ place-items: center;
468
+ width: 22px;
469
+ height: 22px;
470
+ border-radius: var(--sc-r-sm, 6px);
471
+ background: var(--sc-tray-sunk, #f6f6f7);
472
+ color: var(--sc-muted, #6b6b73);
473
+ }
474
+
475
+ .sc-otile .sc-mglyph {
476
+ width: 15px;
477
+ height: 11px;
478
+ }
479
+
480
+ .sc-oglyph,
481
+ .sc-omark {
482
+ width: 13px;
483
+ height: 13px;
372
484
  }
373
485
 
374
- .sc-runtime-name {
486
+ .sc-oname {
487
+ flex: 1;
375
488
  min-width: 0;
376
489
  overflow: hidden;
377
490
  text-overflow: ellipsis;
378
491
  white-space: nowrap;
492
+ font-size: var(--sc-fs-small);
493
+ color: var(--sc-text-2, #3f3f46);
494
+ }
495
+
496
+ .sc-oword {
497
+ flex: none;
498
+ font-size: var(--sc-fs-label);
499
+ color: var(--sc-muted, #6b6b73);
500
+ }
501
+
502
+ .sc-pair {
503
+ display: flex;
504
+ align-items: center;
505
+ gap: 10px;
506
+ width: calc(100% + 4px);
507
+ min-height: 34px;
508
+ margin-left: -4px;
509
+ padding: 0 12px 0 4px;
510
+ border: 0;
511
+ border-radius: 8px;
512
+ background: transparent;
513
+ font: inherit;
514
+ font-size: var(--sc-fs-small);
515
+ text-align: left;
516
+ cursor: pointer;
517
+ transition: background-color 120ms ease;
518
+ }
519
+
520
+ .sc-pair:hover {
521
+ background: var(--sc-tray-sunk, #f6f6f7);
522
+ }
523
+
524
+ .sc-hrow {
525
+ padding-bottom: 2px;
526
+ }
527
+
528
+ .sc-row-note {
529
+ margin: 0;
530
+ padding: 2px 12px 4px 0;
531
+ font-size: var(--sc-fs-label);
532
+ line-height: 1.45;
533
+ color: var(--sc-muted, #6b6b73);
534
+ }
535
+
536
+ .sc-row-act {
537
+ flex: none;
538
+ padding: 3px 9px;
539
+ border: 1px solid transparent;
540
+ border-radius: var(--sc-r-pill, 999px);
541
+ background: var(--sc-tray-sunk, #f6f6f7);
542
+ font: inherit;
543
+ font-size: var(--sc-fs-label);
544
+ font-weight: 500;
545
+ color: var(--sc-text-2, #3f3f46);
546
+ cursor: pointer;
547
+ white-space: nowrap;
548
+ }
549
+
550
+ .sc-row-act:hover:not(:disabled) {
551
+ color: var(--sc-text, #1a1a1c);
552
+ }
553
+
554
+ .sc-row-act:disabled {
555
+ opacity: 0.5;
556
+ cursor: default;
557
+ }
558
+
559
+ .sc-tray-error {
560
+ margin: 0;
561
+ padding: 0 12px 2px;
562
+ }
563
+
564
+ .sc-pop {
565
+ position: fixed;
566
+ top: 0;
567
+ left: 0;
568
+ right: auto;
569
+ bottom: auto;
570
+ z-index: 2147483000;
571
+ width: min(92vw, 320px);
572
+ max-width: min(92vw, 320px);
573
+
574
+ max-height: calc(100vh - 24px);
575
+ overflow-y: auto;
576
+ overscroll-behavior: contain;
577
+ margin: 0;
578
+ padding: 0;
579
+ border: 0;
580
+ border-radius: 20px;
581
+ background: var(--sc-tray, #f6f6f7);
582
+
583
+ box-shadow:
584
+ 0 0 0 1px var(--sc-line, #e9e9eb),
585
+ var(--sc-shadow-2);
586
+ }
587
+
588
+ .sc-pop > .sc-tray {
589
+ background: transparent;
590
+ border-radius: inherit;
591
+ }
592
+
593
+ @keyframes sc-pop-in {
594
+ from {
595
+ opacity: 0;
596
+ transform: translateY(-6px) scale(0.98);
597
+ }
598
+ }
599
+
600
+ .sc-pop {
601
+ animation: sc-pop-in 120ms cubic-bezier(0.2, 0.8, 0.2, 1);
602
+ transform-origin: top right;
603
+ }
604
+
605
+ @media (prefers-reduced-motion: reduce) {
606
+ .sc-pop {
607
+ animation: none;
608
+ }
609
+ .sc-spin {
610
+ animation: none;
611
+ }
612
+ .sc-pair {
613
+ transition: none;
614
+ }
615
+ }
616
+
617
+ .sc-compute-act {
618
+ margin-top: 16px;
619
+ }
620
+
621
+ .sc-compute-act:first-child {
622
+ margin-top: 0;
623
+ }
624
+
625
+ .sc-note + .sc-compute-act,
626
+ .sc-error + .sc-compute-act {
627
+ margin-top: 9px;
379
628
  }
380
629
 
381
630
  .soba-connect[data-theme="dark"],
@@ -402,6 +651,10 @@ a.sc-btn {
402
651
  --sc-ok: #4cb782;
403
652
  --sc-warn: #f2994a;
404
653
 
654
+ --sc-tray: var(--sc-ground, #0f0f11);
655
+ --sc-tray-card: var(--sc-raised, #1d1d20);
656
+ --sc-tray-sunk: var(--sc-sheet, #161618);
657
+
405
658
  --sc-shadow-1: 0 1px 2px rgb(0 0 0 / 34%);
406
659
  --sc-shadow-2: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 64%);
407
660
  }
@@ -423,6 +676,10 @@ a.sc-btn {
423
676
  --sc-ok: #4cb782;
424
677
  --sc-warn: #f2994a;
425
678
 
679
+ --sc-tray: var(--sc-ground, #0f0f11);
680
+ --sc-tray-card: var(--sc-raised, #1d1d20);
681
+ --sc-tray-sunk: var(--sc-sheet, #161618);
682
+
426
683
  --sc-shadow-1: 0 1px 2px rgb(0 0 0 / 34%);
427
684
  --sc-shadow-2: 0 1px 2px rgb(0 0 0 / 40%), 0 8px 24px -12px rgb(0 0 0 / 64%);
428
685
  }
@@ -760,22 +1017,6 @@ a.sc-btn {
760
1017
  box-shadow: none;
761
1018
  }
762
1019
 
763
- .sc-modal-sheet .sc-machine {
764
- border: 1px solid var(--sc-line, #e9e9eb);
765
- border-radius: var(--sc-r, 10px);
766
- padding: 11px 12px;
767
- margin-top: 14px;
768
- }
769
-
770
- .sc-conns {
771
- display: grid;
772
- gap: 14px;
773
- }
774
-
775
- .sc-modal-sheet .sc-machine:first-child {
776
- margin-top: 0;
777
- }
778
-
779
1020
  .sc-modal-sheet .sc-title {
780
1021
  font-size: 17px;
781
1022
  font-weight: 600;
@@ -1015,51 +1256,6 @@ a.sc-btn {
1015
1256
  color: var(--sc-text, #1a1a1c);
1016
1257
  }
1017
1258
 
1018
- .sc-conn,
1019
- .sc-idrow {
1020
- display: grid;
1021
- grid-template-columns: auto 1fr auto;
1022
- align-items: center;
1023
- gap: 12px;
1024
- }
1025
-
1026
- .sc-conn {
1027
- padding: 10px 12px;
1028
- border: 1px solid var(--sc-line, #e9e9eb);
1029
- border-radius: var(--sc-r, 10px);
1030
- background: var(--sc-sheet, #ffffff);
1031
- }
1032
-
1033
- .sc-conn-note {
1034
- grid-column: 1 / -1;
1035
- margin: 2px 0 0;
1036
- font-size: 12px;
1037
- line-height: 1.4;
1038
- color: var(--sc-muted, #6b6b73);
1039
- }
1040
-
1041
- .sc-conn-action {
1042
- font: inherit;
1043
- font-size: var(--sc-fs-small);
1044
- font-weight: 500;
1045
- padding: 5px 9px;
1046
- border: 1px solid transparent;
1047
- border-radius: var(--sc-r-sm, 6px);
1048
- background: transparent;
1049
- color: var(--sc-muted, #6b6b73);
1050
- cursor: pointer;
1051
- }
1052
-
1053
- .sc-conn-action:hover:not(:disabled) {
1054
- border-color: var(--sc-line-2, #dcdce0);
1055
- color: var(--sc-text, #1a1a1c);
1056
- }
1057
-
1058
- .sc-conn-action:disabled {
1059
- opacity: 0.5;
1060
- cursor: default;
1061
- }
1062
-
1063
1259
  .sc-btn-wide {
1064
1260
  width: 100%;
1065
1261
  }
@@ -1328,7 +1524,9 @@ a.sc-btn {
1328
1524
  .sc-step-lead:focus-visible,
1329
1525
  .sc-step-links a:focus-visible,
1330
1526
  .sc-alt-link:focus-visible,
1331
- .sc-conn-action:focus-visible,
1527
+ .sc-row-act:focus-visible,
1528
+ .sc-disc:focus-visible,
1529
+ .sc-pair:focus-visible,
1332
1530
  .sc-input:focus-visible,
1333
1531
  .sc-modal-close:focus-visible {
1334
1532
  outline: 2px solid var(--sc-accent, #18181b);
@@ -1379,7 +1577,7 @@ a.sc-btn {
1379
1577
  max-width: 100%;
1380
1578
  min-width: 0;
1381
1579
 
1382
- padding: 4px 13px 4px 4px;
1580
+ padding: 3px 12px 3px 3px;
1383
1581
  border-radius: var(--sc-r-pill, 999px);
1384
1582
  border-color: var(--sc-line, #e9e9eb);
1385
1583
 
@@ -1403,14 +1601,33 @@ a.sc-btn {
1403
1601
  transform: translateY(0.5px);
1404
1602
  }
1405
1603
 
1406
- .sc-btn-connected .sc-runtime-tile {
1604
+ .sc-pill-tile {
1605
+ flex: none;
1606
+ display: grid;
1607
+ place-items: center;
1608
+ width: 26px;
1609
+ height: 26px;
1407
1610
  border-radius: 50%;
1611
+ background: var(--sc-raised, #f6f6f7);
1612
+ box-shadow: inset 0 0 0 1px var(--sc-line, #e9e9eb);
1613
+ color: var(--sc-text, #1a1a1c);
1408
1614
  }
1409
1615
 
1410
- .sc-btn-connected:hover .sc-runtime-tile {
1616
+ .sc-btn-connected:hover .sc-pill-tile {
1411
1617
  background: var(--sc-sheet, #ffffff);
1412
1618
  }
1413
1619
 
1620
+ .sc-pill-mark {
1621
+ width: 16px;
1622
+ height: 16px;
1623
+ }
1624
+
1625
+ @media (prefers-reduced-motion: no-preference) {
1626
+ .sc-pill-mark-busy {
1627
+ animation: sc-spin 2400ms linear infinite;
1628
+ }
1629
+ }
1630
+
1414
1631
  .sc-btn-connected .sc-dot {
1415
1632
  flex: none;
1416
1633
  margin-left: 1px;
@@ -1542,6 +1759,36 @@ a.sc-btn {
1542
1759
  min-width: 0;
1543
1760
  }
1544
1761
 
1762
+ .sc-nudge {
1763
+ position: relative;
1764
+ }
1765
+ .sc-nudge-dismiss {
1766
+ position: absolute;
1767
+ top: 7px;
1768
+ right: 8px;
1769
+ display: grid;
1770
+ place-items: center;
1771
+ width: 28px;
1772
+ height: 28px;
1773
+ padding: 0;
1774
+ border: 0;
1775
+ border-radius: 999px;
1776
+ background: none;
1777
+ color: var(--sc-muted, #6b6b73);
1778
+ cursor: pointer;
1779
+ transition:
1780
+ background-color 0.12s,
1781
+ color 0.12s;
1782
+ }
1783
+ .sc-nudge-dismiss:hover {
1784
+ background: var(--sc-raised, #f6f6f7);
1785
+ color: var(--sc-text, #1a1a1c);
1786
+ }
1787
+ .sc-nudge-x {
1788
+ width: 14px;
1789
+ height: 14px;
1790
+ }
1791
+
1545
1792
  .sc-nudge > .sc-btn {
1546
1793
  grid-column: 2;
1547
1794
  align-self: end;
@@ -2281,6 +2528,18 @@ li.sc-plan-row.sc-plan-current {
2281
2528
  color: var(--sc-muted, #6b6b73);
2282
2529
  }
2283
2530
 
2531
+ .sc-run-error {
2532
+ border-color: color-mix(in srgb, var(--sc-warn, #b06f14) 28%, var(--sc-line, #e9e9eb));
2533
+ }
2534
+ .sc-run-error-mark {
2535
+ background: color-mix(in srgb, var(--sc-warn, #b06f14) 12%, var(--sc-raised, #f6f6f7));
2536
+ color: var(--sc-warn, #b06f14);
2537
+ }
2538
+
2539
+ .sc-run-error-message {
2540
+ overflow-wrap: anywhere;
2541
+ }
2542
+
2284
2543
  .sc-modal-sheet .sc-limit-head {
2285
2544
  flex-direction: column;
2286
2545
  align-items: center;
@@ -2366,13 +2625,13 @@ li.sc-plan-row.sc-plan-current {
2366
2625
  }
2367
2626
  }
2368
2627
 
2369
- .sc-modal-sheet .sc-machine {
2628
+ .sc-modal-sheet .sc-tray {
2370
2629
  animation: sc-arrive 200ms cubic-bezier(0.2, 0.8, 0.2, 1) 60ms both;
2371
2630
  }
2372
2631
 
2373
2632
  @media (prefers-reduced-motion: reduce) {
2374
2633
  .sc-modal-sheet .sc-card,
2375
- .sc-modal-sheet .sc-machine {
2634
+ .sc-modal-sheet .sc-tray {
2376
2635
  animation: none;
2377
2636
  }
2378
2637
  .sc-modal-sheet {
@@ -2397,4 +2656,4 @@ li.sc-plan-row.sc-plan-current {
2397
2656
  .sc-opt-has-warn {
2398
2657
  color: var(--sc-warn, #b06f14);
2399
2658
  }
2400
- `,document.head.appendChild(e)}import{jsx as kt,jsxs as Mo}from"react/jsx-runtime";var Po="https://www.soba.so",xo=15e3;function _o(e){let{children:n,session:t,sessionEndpoint:s,user:o,runEndpoint:i,theme:a,initialMachines:m,initialConnect:c=null,initialPlans:d,initialCurrentPlan:g=null,baseUrl:b=Po,pollMs:h=xo,injectStyles:f=!0,modal:p=!0,fetchImpl:N,onError:k}=e,[P,U]=Y(t??null),[D,C]=Y(null),[$,q]=Y(c),[A,J]=Y(null),[z,F]=Y(c===null),[ce,xe]=Y(m??[]),[wn,K]=Y(null),[Ce,vn]=Y(m===void 0),[Ne,he]=Y(d??[]),[Z,In]=Y(g),[Ke,Ue]=Y(null),[Cn,le]=Y(d===void 0),[se,qe]=Y(null),[$n,_e]=Y(!1),Be=So(k);Be.current=k;let oe=ve(y=>{C(y),Be.current?.(y)},[]);De(()=>{f&&Nt()},[f]);let _=yn(()=>new Tn({...t?{token:t}:{},...s?{endpoint:s}:{},...o?{user:o}:{},...N?{fetchImpl:N}:{}}),[t,s,o,N]);De(()=>{let y=!0,B=_.subscribe(()=>{y&&U(_.token)});return!_.token&&!_.canRefresh?oe(new Error("<SobaProvider> needs a `session` or a `sessionEndpoint`. A browser cannot mint one: that takes your secret key.")):_.ensure().then(()=>y&&U(_.token),ue=>y&&oe(ue)),()=>{y=!1,B()}},[_,oe]),De(()=>{D&&(F(!1),vn(!1),le(!1),J(y=>y??D),K(y=>y??D),Ue(y=>y??D))},[D]),De(()=>{let y=_.refreshAt;if(y===null)return;let B=setTimeout(()=>{_.refresh().catch(ue=>oe(ue))},Math.max(0,y-Date.now()));return()=>clearTimeout(B)},[_,oe,P]);let S=yn(()=>P?new Xe({session:P,baseUrl:b,fetchImpl:ss(_,N??fetch.bind(globalThis))}):null,[P,b,_,N]);De(()=>{if(!S)return;let y=!0;return F(!0),S.context().then(B=>{y&&(q(B),J(null),F(!1))},B=>{y&&(J(B),F(!1))}),()=>{y=!1}},[S]);let Me=ve(async()=>{if(S)try{let y=await S.machines();xe(Array.isArray(y)?y:[]),K(null)}catch(y){K(y)}finally{vn(!1)}},[S]),X=ve(async()=>{if(S)try{let y=await S.plans();he(y.plans),In(y.current),Ue(null)}catch(y){Ue(y)}finally{le(!1)}},[S]);De(()=>{S&&X()},[S,X]);let Je=ve(async y=>{if(!S)throw new Error("No session yet.");await S.selectPlan(y),await X()},[S,X]),Nn=ve(async(y,B)=>{if(!S)throw new Error("No session yet.");let ue=await S.checkoutPlan(y,B);if(!ue.url)throw new Error("Checkout could not be started.");return ue.url},[S]),re=ve(async()=>{if(!S)throw new Error("No session yet.");await S.leavePlan(),await X()},[S,X]);De(()=>{if(!S)return;let y=!0;Me();let B=setInterval(()=>{typeof document<"u"&&document.hidden||y&&Me()},h);return()=>{y=!1,clearInterval(B)}},[S,Me,h]);let ke=ve(async y=>{if(!i)throw new Error("Pass `runEndpoint` to <SobaProvider> to start runs from the browser. It is your own route: it holds your secret key, calls soba.run(), and forwards the stream.");let{signal:B,...ue}=y,Re=await(N??fetch.bind(globalThis))(i,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},credentials:"same-origin",body:JSON.stringify(ue),...B?{signal:B}:{}});if(!Re.ok){let E=await Re.json().catch(()=>null),ee=new Error(E?.error?.message??`${i} answered ${Re.status}.`);throw ee.status=Re.status,E?.error?.code&&(ee.code=E.error.code),E?.error&&(ee.error=E.error),ee}let An=pt(Re);return async function*(){try{yield*An}finally{X()}}()},[i,N,X]),He=ve((y="manual")=>{p&&(_e(!0),qe(y))},[p]),Fe=ve(()=>qe(null),[]),Q=yn(()=>Z?Ne.find(y=>y.id===Z.plan_id)??null:null,[Ne,Z]),V=yn(()=>Q?Q.connected_reward==="included"&&ce.length>0&&Q.connected_included_units!==null?Q.connected_included_units:Q.included_units:null,[Q,ce]),kn=yn(()=>({session:P,client:S,error:D,plan:{plans:Ne,current:Z,plan:Q,used:Z?.units_used??null,included:V,remaining:V!==null&&Z?Math.max(0,V-Z.units_used):null,unlimited:Q!==null&&V===null,loading:Cn,error:Ke,select:Je,checkout:Nn,leave:re,refresh:X},compute:{machines:ce,connected:ce.length>0,online:ce.some(y=>y.state!=="offline"),loading:Ce,error:wn,refresh:Me},connect:{app:$?.app??null,command:$?.command??null,connectUrl:$?.connect_url??null,publishableKey:$?.publishable_key??null,loading:z,error:A,open:He,close:Fe,isOpen:se!==null,hasModal:p},run:ke}),[P,S,D,Q,V,se,He,Fe,p,ce,Ce,wn,Me,Ne,Z,Cn,Ke,Je,Nn,re,X,$,z,A,ke]);return kt(rt.Provider,{value:S,children:kt(at.Provider,{value:{context:$,machines:Ce?void 0:ce,theme:a??$?.theme??"light"},children:Mo(ot.Provider,{value:kn,children:[n,p&&$n&&kt(hn,{open:se!==null,onOpenChange:y=>qe(y?se??"manual":null),...se&&se!=="manual"?{reason:se}:{}})]})})})}export{Rs as ComputeStatus,Ae as ConnectButton,Ts as ConnectCompute,hn as ConnectModal,Vs as ConnectNudge,Qs as RunLimit,vo as SobaBilling,Co as SobaCheckout,mt as SobaCurrentPlan,ft as SobaPlans,_o as SobaProvider,Js as collectText,Nt as injectStyles,En as parseEvent,pt as readEvents,gn as sobaErrorCode,bn as useCurrentPlan,ht as usePlans,ut as useRunLimit,T as useSoba};
2659
+ `,document.head.appendChild(e)}import{jsx as ye,jsxs as Dn}from"react/jsx-runtime";function Fr(e){if(!e)return null;let n=en(e);if(n==="payment_required"||n==="no_compute")return null;if(typeof e=="string")return e||null;let t=e,r=t.error?.message;return typeof r=="string"&&r?r:typeof t.message=="string"&&t.message?t.message:"The run ended with an error."}function ds(){return Dn("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[ye("path",{d:"M8 5v4",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"}),ye("circle",{cx:"8",cy:"11.6",r:"0.9",fill:"currentColor"}),ye("circle",{cx:"8",cy:"8",r:"6.4",stroke:"currentColor",strokeWidth:"1.3"})]})}function ps({error:e,onRetry:n,onDismiss:t,title:r,className:o}){let a=Fr(e),s=$();return us(()=>$n(),[]),a?ye("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":s.theme,role:"alert",children:Dn("div",{className:"sc-card sc-limit sc-run-error",children:[Dn("div",{className:"sc-limit-head",children:[ye("span",{className:"sc-limit-mark sc-run-error-mark","aria-hidden":"true",children:ye(ds,{})}),Dn("div",{children:[ye("h2",{className:"sc-limit-title",children:r??"That run did not finish"}),ye("p",{className:"sc-limit-body sc-run-error-message",children:a})]})]}),(t||n)&&Dn("div",{className:"sc-limit-actions",children:[t&&ye("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,children:"Dismiss"}),n&&ye("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:n,children:"Try again"})]})]})}):null}import{useId as ms,useState as Gr}from"react";import{jsx as Q,jsxs as ot}from"react/jsx-runtime";function hs({reason:e}){return Q("span",{className:"sc-limit-mark","aria-hidden":"true",children:e==="no_compute"?Q(Vn,{}):Q(j,{})})}function fs(e){let{error:n,variant:t="card",onDismiss:r,className:o}=e,a=Xt(n,{predict:e.predict??!("error"in e)}),s=ms(),c=$();if(!a)return null;let i=Q(gs,{offer:a,headingId:s,onDismiss:r});return t==="dialog"?Q(On,{open:!0,onClose:()=>r?.(),labelledBy:s,theme:c.theme,children:i}):Q("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":c.theme,children:i})}function gs({offer:e,headingId:n,onDismiss:t}){let{compute:r}=B(),[o,a]=Gr(!1),[s,c]=Gr(null),i=e.reason==="no_compute"&&r.connected&&!r.online,u=i||e.connectOffer!==null||!r.connected,m=tt();async function f(){a(!0),c(null);try{await e.upgrade()}catch(b){c(b.message)}finally{a(!1)}}return ot("div",{className:"sc-card sc-limit",children:[ot("div",{className:"sc-limit-head",children:[Q(hs,{reason:e.reason}),ot("div",{children:[Q("h2",{className:"sc-limit-title",id:n,children:e.title}),Q("p",{className:"sc-limit-body",children:e.body})]})]}),s&&Q("p",{className:"sc-error",children:s}),i&&m.note&&Q("p",{className:"sc-limit-note",children:m.note}),ot("div",{className:"sc-limit-actions",children:[t&&Q("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,disabled:o,children:"Not now"}),e.upgradeTo&&Q("button",{type:"button",className:u?"sc-btn":"sc-btn sc-btn-primary",onClick:()=>void f(),disabled:o,children:o?"Opening\u2026":e.upgradeTo.selectable?`Switch to ${e.upgradeTo.name}`:`${e.upgradeTo.name} for $${e.upgradeTo.price.toLocaleString()}/${e.upgradeTo.interval}`}),u&&Q("button",{type:"button",className:i?"sc-btn":"sc-btn sc-btn-primary",onClick:e.connect,disabled:o,children:i?"Connect another machine":"Connect compute"}),i&&Q("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:m.open,disabled:o,children:"Open Soba App"})]})]})}import{useMemo as bs}from"react";function Hn(){let{plan:e,compute:n,connect:t}=B();return bs(()=>{let r=e.plan,o=e.current,a={plan:r,assignment:o,loading:e.loading,error:e.error,periodEnd:o?.period_end?new Date(o.period_end):null};if(!r)return{...a,state:"none",trialDaysLeft:null,ceiling:null,raised:!1,uncounted:!1,used:0,remaining:null,percent:null,unlimited:!1,reward:null,summary:"Nothing is assigned to this account, so runs are bounded by whatever the app allows."};let s=vs(o?.trial_ends_at??null),c=r.connected_reward==="included"&&n.connected&&r.connected_included_units!==null,i=c?r.connected_included_units:r.included_units,u=r.connected_reward==="unlimited"&&n.connected,m=i===null,f=e.used??0,b=i===null?null:Math.max(0,i-f),g=i&&i>0?Math.min(100,Math.round(f/i*100)):null,p=i!==null&&f>=i,y=s!==null?"trial":m?"unlimited":p?r.overage==="meter"?"metered":"spent":"within";return{...a,state:y,trialDaysLeft:s,ceiling:i,raised:c,uncounted:u,used:f,remaining:b,percent:g,unlimited:m,reward:ys(r,c||u,n.connected,()=>t.open("manual")),summary:ws({plan:r,assignment:o,used:f,ceiling:i,trialDaysLeft:s,raised:c,uncounted:u,state:y})}},[e,n.connected,t])}function ys(e,n,t,r){let o=Ee({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6});return o?{line:o,inForce:n,required:!1,connected:t,actionable:Me(e.connected_reward)&&!t,open:r}:de(e.route_allow)&&!t?{line:"Nothing connected yet, so nothing can run.",inForce:!1,required:!0,connected:t,actionable:!0,open:r}:null}function ws(e){let{plan:n,assignment:t,used:r,ceiling:o,trialDaysLeft:a,raised:s,uncounted:c,state:i}=e,u=`${n.unit}${r===1?"":"s"}`,m=c?" Runs your own AI serves do not count toward it.":"";if(i==="trial"&&a!==null){let g=n.price===0?"it continues free":`it is $${n.price.toLocaleString()} a ${n.interval}`;return`${a} ${a===1?"day":"days"} left of your trial, then ${g}.`}if(i==="unlimited")return`${r.toLocaleString()} ${u} this period. No ceiling on this plan.`;if(i==="metered"){let g=r-(o??0);return n.overage_per_unit>0?`${g.toLocaleString()} past the allowance, billed at $${n.overage_per_unit} a ${n.unit}.${m}`:`${g.toLocaleString()} past the allowance.${m}`}if(i==="spent")return t?.period_end?`Allowance spent. It comes back on ${Vr(t.period_end)}.${m}`:`Allowance spent. It comes back at the start of the next period.${m}`;let f=Math.max(0,(o??0)-r),b=s?` Raised from ${(n.included_units??0).toLocaleString()} while your own AI is connected.`:t?.period_end?` Resets ${Vr(t.period_end)}.`:"";return`${f.toLocaleString()} of ${(o??0).toLocaleString()} ${n.unit}s left.${b}${m}`}function vs(e){if(!e)return null;let n=new Date(e).getTime()-Date.now();return Number.isNaN(n)||n<=0?null:Math.max(1,Math.ceil(n/864e5))}function Vr(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as Ns,jsx as Z,jsxs as pe}from"react/jsx-runtime";function rr({heading:e="Current plan",showUsage:n=!0,showName:t=!0,className:r}){let o=Hn(),{theme:a}=$(),s=b=>Z("section",{className:r?`soba-connect sc-fill ${r}`:"soba-connect sc-fill","data-theme":a,children:pe("div",{className:"sc-card sc-current",children:[e&&Z("h2",{className:"sc-section-title",children:e}),b]})});if(o.error)return s(Z("p",{className:"sc-error",children:o.error.message}));if(o.loading)return s(Z("p",{className:"sc-note",children:"Loading\u2026"}));if(!o.plan)return s(pe("div",{className:"sc-current-main",children:[Z("p",{className:"sc-current-name",children:"No plan"}),Z("p",{className:"sc-sub",children:o.summary})]}));let{plan:c,trialDaysLeft:i,percent:u,unlimited:m,reward:f}=o;return s(pe(Ns,{children:[pe("div",{className:"sc-current-grid",children:[(t||i!==null)&&pe("div",{className:"sc-current-main",children:[t?pe("p",{className:"sc-current-name",children:[c.name,i!==null&&pe("span",{className:"sc-trial-badge",children:[i," ",i===1?"day":"days"," left"]})]}):i!==null&&Z("p",{className:"sc-current-trial",children:pe("span",{className:"sc-trial-badge",children:[i," ",i===1?"day":"days"," left"]})}),t&&c.description&&Z("p",{className:"sc-sub",children:c.description})]}),n&&pe("div",{className:"sc-usage",children:[pe("div",{className:"sc-row-between",children:[Z("span",{className:"sc-fact-key",children:"Usage"}),Z("span",{className:u!==null&&u>=100?"sc-usage-figure sc-usage-over":"sc-usage-figure",children:m?"Unlimited":u===null?"Metered":`${u}% used`})]}),u!==null&&Z("div",{className:"sc-meter",role:"presentation",children:u>0&&Z("span",{className:u>=100?"sc-meter-fill sc-meter-full":"sc-meter-fill",style:{width:`${u}%`}})}),Z("p",{className:"sc-usage-line",children:o.summary})]})]}),f&&pe("div",{className:"sc-current-foot",children:[Z("p",{className:f.required?"sc-plan-reward-line sc-plan-reward-need":f.inForce?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-open",children:f.required?f.line:f.inForce?`In force: ${Cs(f.line)}.`:f.line}),(f.actionable||f.connected)&&Z(Xe,{})]})]}))}var Cs=e=>e.charAt(0).toLowerCase()+e.slice(1);import{useCallback as ks,useMemo as xs,useState as zr}from"react";var Ss={"user-hardware":"your own machine","user-subscription":"your own AI subscription","open-weights":"open models we host",frontier:"frontier models"},Ps=new Set(["user-hardware","user-subscription"]);function or(e={}){let{plan:n,compute:t,connect:r}=B(),[o,a]=zr(null),[s,c]=zr(null),{featured:i,onSelect:u,successUrl:m,cancelUrl:f}=e,b=ks(async p=>{a(p.id),c(null);try{if(p.selectable)await n.select(p.id);else if(u)u(p);else{let y=await n.checkout(p.id,{...m?{successUrl:m}:{},...f?{cancelUrl:f}:{}});window.location.assign(y);return}}catch(y){throw c(y.message),y}finally{(p.selectable||u)&&a(null)}},[n,u,m,f]),g=xs(()=>n.plans.map(p=>{let y=n.current?.plan_id===p.id;return{plan:p,current:y,featured:i===p.id&&!y,price:_s(p),allowance:p.included_units===null?`Unlimited ${p.unit}s`:`${p.included_units.toLocaleString()} ${p.unit}${p.included_units===1?"":"s"}`,allowanceNote:Es(p),computeLabel:p.route_allow===null?"any compute":p.route_allow.length===0?"no compute":null,compute:(p.route_allow??[]).map(E=>({costClass:E,label:Ss[E]??E,owned:Ps.has(E),runtimes:yt(E).map(k=>k.id)})),connect:Ms(p,y,t.connected,()=>r.open("manual")),cta:{label:Rs(p,y,o===p.id),disabled:y||o!==null,busy:o===p.id,take:()=>b(p)}}}),[n.plans,n.current,i,t.connected,r,o,b]);return{offers:g,current:g.find(p=>p.current)??null,loading:n.loading,error:n.error,failed:s}}function _s(e){return e.price===0?{amount:"Free",interval:null,free:!0}:{amount:`$${e.price.toLocaleString()}`,interval:e.interval,free:!1}}function Es(e){let n=[];return e.included_units===null?n.push("No ceiling on this plan"):(n.push(`Included each ${e.interval}`),e.overage==="meter"&&e.overage_per_unit>0?n.push(`then $${e.overage_per_unit} a ${e.unit}`):e.included_units>0&&n.push(`then ${e.unit}s stop`)),e.trial_days>0&&n.push(`${e.trial_days}-day trial`),n.join(" \xB7 ")}function Ms(e,n,t,r){let o=Ee({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6}),a=de(e.route_allow)&&!t;if(!o&&!a)return null;let s=Me(e.connected_reward);return{key:o?"Connect your own":"To use this",line:o??(n?"Nothing connected yet, so nothing can run.":"Runs only on compute you connect."),reward:o!==null,actionable:n&&(s||a)&&!t,open:r}}function Rs(e,n,t){return n?"Your plan":t?e.selectable?"Switching\u2026":"Opening\u2026":e.selectable?"Choose":`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}import{jsx as h,jsxs as L}from"react/jsx-runtime";function st(e){return e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill"}function sr({onSelect:e,successUrl:n,cancelUrl:t,showCompute:r=!0,showConnect:o=!1,variant:a="cards",featured:s,className:c}){let{offers:i,loading:u,error:m,failed:f}=or({...s?{featured:s}:{},...e?{onSelect:e}:{},...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}}),{theme:b}=$();if(m)return h("div",{className:st(c),"data-theme":b,children:h("div",{className:"sc-card",children:h("p",{className:"sc-error",children:m.message})})});if(u)return h("div",{className:st(c),"data-theme":b,children:h("div",{className:"sc-card",children:h("p",{className:"sc-note",children:"Loading plans\u2026"})})});if(i.length===0)return h("div",{className:st(c),"data-theme":b,children:h("div",{className:"sc-card",children:h("p",{className:"sc-note",children:"This app has no plans yet."})})});let g={showCompute:r,showConnect:o};return L("div",{className:st(c),"data-theme":b,"data-variant":a,children:[a==="rows"?h(Os,{offers:i,shelf:g}):a==="table"?h(Ts,{offers:i,shelf:g}):h(Ls,{offers:i,shelf:g}),f&&h("p",{className:"sc-error",children:f})]})}function Ls({offers:e,shelf:n}){return h("div",{className:"sc-plans",children:e.map(t=>L("div",{className:Kr("sc-plan",t),children:[L("div",{className:"sc-row-between",children:[h("span",{className:"sc-title",children:t.plan.name}),h(ar,{offer:t})]}),h("p",{className:"sc-sub",children:t.plan.description}),h(ir,{price:t.price,free:"forever"}),h(ur,{offer:t,shelf:n}),h(jr,{offer:t}),h("div",{className:"sc-plan-band",children:n.showCompute&&h(cr,{offer:t})}),h("div",{className:"sc-plan-band",children:h(lr,{offer:t})})]},t.plan.id))})}function Os({offers:e,shelf:n}){return h("ul",{className:"sc-plan-rows",children:e.map(t=>L("li",{className:Kr("sc-plan-row",t),children:[L("div",{className:"sc-row-main",children:[L("span",{className:"sc-row-name",children:[h("span",{className:"sc-title",children:t.plan.name}),h(ar,{offer:t})]}),t.plan.description&&h("p",{className:"sc-sub",children:t.plan.description}),h(jr,{offer:t}),n.showCompute&&h(cr,{offer:t,inline:!0}),h(lr,{offer:t,inline:!0})]}),L("div",{className:"sc-row-side",children:[h(ir,{price:t.price,free:"forever",small:!0}),h(ur,{offer:t,shelf:n})]})]},t.plan.id))})}function Ts({offers:e,shelf:n}){let t=e.some(s=>s.plan.overage_per_unit>0),r=e.some(s=>s.plan.trial_days>0),o=e.some(s=>s.connect!==null),a=s=>[s.current?"sc-col-current":"",s.featured?"sc-col-featured":""].filter(Boolean).join(" ")||void 0;return h("div",{className:"sc-table-scroll",children:L("table",{className:"sc-plan-table",children:[h("thead",{children:L("tr",{children:[h("td",{}),e.map(s=>L("th",{scope:"col",className:a(s),children:[L("span",{className:"sc-row-name",children:[h("span",{className:"sc-title",children:s.plan.name}),h(ar,{offer:s})]}),h(ir,{price:s.price,small:!0})]},s.plan.id))]})}),L("tbody",{children:[L("tr",{children:[h("th",{scope:"row",children:"Included"}),e.map(s=>h("td",{className:a(s),children:s.allowance},s.plan.id))]}),t&&L("tr",{children:[h("th",{scope:"row",children:"Then"}),e.map(s=>h("td",{className:a(s),children:s.plan.overage_per_unit>0?`$${s.plan.overage_per_unit} / ${s.plan.unit}`:h("span",{className:"sc-muted-cell",children:"Stops"})},s.plan.id))]}),r&&L("tr",{children:[h("th",{scope:"row",children:"Trial"}),e.map(s=>h("td",{className:a(s),children:s.plan.trial_days>0?`${s.plan.trial_days} days`:h("span",{className:"sc-muted-cell",children:"None"})},s.plan.id))]}),n.showCompute&&L("tr",{children:[h("th",{scope:"row",children:"Runs on"}),e.map(s=>h("td",{className:a(s),children:h(cr,{offer:s,bare:!0})},s.plan.id))]}),o&&L("tr",{children:[h("th",{scope:"row",children:"Connect your own"}),e.map(s=>h("td",{className:a(s),children:h(lr,{offer:s,bare:!0})},s.plan.id))]}),L("tr",{className:"sc-table-buy",children:[h("td",{}),e.map(s=>h("td",{className:a(s),children:h(ur,{offer:s,shelf:n})},s.plan.id))]})]})]})})}function Kr(e,n){return[e,n.current?"sc-plan-current":"",n.featured?"sc-plan-featured":""].filter(Boolean).join(" ")}function ar({offer:e}){return e.current?h("span",{className:"sc-plan-badge",children:"Current"}):e.featured?h("span",{className:"sc-plan-badge-soft",children:"Recommended"}):null}function ir({price:e,small:n,free:t}){return L("p",{className:n?"sc-plan-price sc-plan-price-sm":"sc-plan-price",children:[h("span",{className:"sc-plan-amount",children:e.amount}),e.interval?L("span",{className:"sc-plan-interval",children:["/",e.interval]}):t&&h("span",{className:"sc-plan-interval sc-plan-after",children:t})]})}function jr({offer:e}){return L("p",{className:"sc-plan-allowance",children:[h("span",{className:"sc-plan-figure",children:e.allowance}),h("span",{className:"sc-plan-qualifier",children:e.allowanceNote})]})}function lr({offer:e,inline:n,bare:t}){let r=e.connect;if(!r)return t?h("span",{className:"sc-muted-cell",children:"None"}):null;let o=r.reward?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-need",a=r.actionable?L("button",{type:"button",className:`${o} sc-plan-reward-act`,"aria-label":"Connect compute",onClick:r.open,children:[h("span",{className:"sc-reward-said",children:r.line}),L("span",{className:"sc-reward-do","aria-hidden":!0,children:[h(j,{className:"sc-reward-mark"}),"Connect compute"]})]}):h("p",{className:o,children:r.line});return t?a:h("div",{className:n?"sc-plan-reward sc-plan-reward-inline":"sc-plan-reward",children:a})}function cr({offer:e,inline:n,bare:t}){let r=e.computeLabel?h("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:h("li",{children:e.computeLabel})}):h("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:e.compute.map(o=>L("li",{className:o.owned?"sc-compute-own":void 0,children:[o.label,h(As,{runtimes:o.runtimes})]},o.costClass))});return t?r:L("div",{className:n?"sc-plan-compute sc-plan-compute-inline":"sc-plan-compute",children:[h("span",{className:"sc-fact-key",children:"Runs on"}),r]})}function ur({offer:e,shelf:n}){let t=e.connect;return n.showConnect&&t?.actionable?L("button",{type:"button",className:"sc-btn sc-btn-primary sc-btn-icon",onClick:t.open,children:[h(j,{className:"sc-btn-mark"}),"Connect compute"]}):h("button",{type:"button",className:e.current?"sc-btn":"sc-btn sc-btn-primary",disabled:e.cta.disabled,onClick:()=>void e.cta.take().catch(()=>{}),children:e.cta.label})}function As({runtimes:e}){return e.length===0?null:h("span",{className:"sc-compute-marks",children:e.map(n=>{let t=Te[n];return t?h(t,{className:"sc-rt-mark"},n):null})})}import{jsx as dr,jsxs as Yr}from"react/jsx-runtime";function Is({heading:e,plansHeading:n,showUsage:t=!0,showName:r=!0,className:o,...a}){let{plan:s,loading:c}=Hn(),{theme:i}=$(),u=n??(c?"Plans":s?"Change plan":"Choose a plan");return Yr("div",{className:o?`soba-connect sc-fill sc-billing ${o}`:"soba-connect sc-fill sc-billing","data-theme":i,children:[dr(rr,{...e===void 0?{}:{heading:e},showUsage:t,showName:r}),Yr("section",{className:"sc-billing-plans",children:[u&&dr("h2",{className:"sc-section-title",children:u}),dr(sr,{...a})]})]})}import{useState as Qr}from"react";import{jsx as Zr,jsxs as Ds}from"react/jsx-runtime";function $s({plan:e,successUrl:n,cancelUrl:t,label:r,className:o}){let{plan:a}=B(),{theme:s}=$(),[c,i]=Qr(!1),[u,m]=Qr(null);async function f(){i(!0),m(null);try{let b=await a.checkout(e.id,{...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}});window.location.assign(b)}catch(b){m(b.message),i(!1)}}return Ds("div",{className:o?`soba-connect ${o}`:"soba-connect","data-theme":s,children:[Zr("button",{type:"button",className:"sc-btn sc-btn-primary",disabled:c,onClick:()=>void f(),children:c?"Opening\u2026":r??`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}),u&&Zr("p",{className:"sc-error",children:u})]})}import{useCallback as we,useEffect as nn,useMemo as bn,useRef as Un,useState as J}from"react";var at=class{#n;#r=null;#t=null;#e;#o=new Set;constructor(n){this.#e=n,this.#n=n.token??null}get token(){return this.#n}get expiresAt(){return this.#r}get canRefresh(){return!!this.#e.endpoint}get refreshAt(){return!this.canRefresh||this.#r===null?null:Math.max(Date.now()+1e4,this.#r-6e4)}subscribe(n){return this.#o.add(n),()=>this.#o.delete(n)}async ensure(){return this.#n?this.#n:this.refresh()}async refresh(){if(this.#t)return this.#t;let n=this.#e.endpoint;if(!n)throw new Error("This Soba session cannot be refreshed. Pass `sessionEndpoint` so the provider can mint a new one.");let t=this.#e.fetchImpl??fetch.bind(globalThis);this.#t=(async()=>{let r=await t(n,{method:"POST",headers:{"content-type":"application/json"},credentials:"same-origin",body:JSON.stringify(this.#e.user?{user:this.#e.user}:{})});if(!r.ok)throw new Error(`Could not start a Soba session (${r.status} from ${n}).`);let o=await r.json(),a=o.session??o.token;if(!a)throw new Error(`${n} answered without a \`session\`. See @soba-so/react's README.`);let s=o.expires_in??o.expiresIn;this.#n=a,this.#r=typeof s=="number"?Date.now()+s*1e3:null;for(let c of this.#o)c();return a})();try{return await this.#t}finally{this.#t=null}}},gn=new Map,Jr=new WeakMap,Hs=1;function Us(e){if(e.token||!e.endpoint)return null;let n=0;return e.fetchImpl&&(n=Jr.get(e.fetchImpl)??Hs++,Jr.set(e.fetchImpl,n)),JSON.stringify([e.endpoint,e.user??null,n])}function Xr(e){let n=Us(e);if(!n)return new at(e);let t=gn.get(n)??{holder:new at(e),users:0};return gn.set(n,t),t.holder}function eo(e){for(let n of gn.values())n.holder===e&&n.users++}function no(e){for(let[n,t]of gn)if(t.holder===e){setTimeout(()=>{--t.users<=0&&gn.get(n)===t&&gn.delete(n)},0);return}}function to(e,n=fetch.bind(globalThis)){return async(t,r)=>{let o=await n(t,r);if(o.status!==401||!e.canRefresh)return o;let a;try{a=await e.refresh()}catch{return o}return n(t,Bs(r,a))}}function Bs(e,n){let t=new Headers(e?.headers);return t.set("authorization",`Bearer ${n}`),{...e,headers:t}}import{jsx as pr,jsxs as Gs}from"react/jsx-runtime";var qs="https://www.soba.so",Ws=3e4;function Fs(e){let{children:n,session:t,sessionEndpoint:r,user:o,runEndpoint:a,theme:s,initialMachines:c,initialConnect:i=null,initialPlans:u,initialCurrentPlan:m=null,baseUrl:f=qs,pollMs:b=Ws,injectStyles:g=!0,modal:p=!0,fetchImpl:y,onError:E}=e,[k,H]=J(t??null),[M,me]=J(null),[P,ne]=J(i),[O,_]=J(null),[q,V]=J(i===null),[te,tn]=J(c??[]),[ae,ve]=J(null),[K,Ce]=J(c===void 0),[Ne,He]=J(u??[]),[W,Re]=J(m),[rn,ie]=J(null),[Ue,on]=J(u===void 0),[F,he]=J(null),[T,le]=J(!1),fe=Un(E);fe.current=E;let ke=we(w=>{me(w),fe.current?.(w)},[]);nn(()=>{g&&$n()},[g]);let U=bn(()=>Xr({...t?{token:t}:{},...r?{endpoint:r}:{},...o?{user:o}:{},...y?{fetchImpl:y}:{}}),[t,r,o,y]);nn(()=>{let w=!0;eo(U);let Y=U.subscribe(()=>{w&&H(U.token)});return!U.token&&!U.canRefresh?ke(new Error("<SobaProvider> needs a `session` or a `sessionEndpoint`. A browser cannot mint one: that takes your secret key.")):U.ensure().then(()=>w&&H(U.token),oe=>w&&ke(oe)),()=>{w=!1,Y(),no(U)}},[U,ke]),nn(()=>{M&&(V(!1),Ce(!1),on(!1),_(w=>w??M),ve(w=>w??M),ie(w=>w??M))},[M]),nn(()=>{let w=U.refreshAt;if(w===null)return;let Y=()=>{U.refresh().catch(Se=>ke(Se))},oe=()=>{document.hidden||(document.removeEventListener("visibilitychange",oe),Y())},Fn=setTimeout(()=>{typeof document<"u"&&document.hidden?document.addEventListener("visibilitychange",oe):Y()},Math.max(0,w-Date.now()));return()=>{clearTimeout(Fn),typeof document<"u"&&document.removeEventListener("visibilitychange",oe)}},[U,ke,k]);let S=bn(()=>k?new vn({session:k,baseUrl:f,fetchImpl:to(U,y??fetch.bind(globalThis))}):null,[k,f,U,y]),it=Un(i!==null);nn(()=>{if(!S||it.current)return;let w=!0;return V(!0),S.context().then(Y=>{w&&(ne(Y),_(null),V(!1))},Y=>{w&&(_(Y),V(!1))}),()=>{w=!1}},[S]);let sn=we(async()=>{if(S)try{let w=await S.machines();tn(Array.isArray(w)?w:[]),ve(null)}catch(w){ve(w)}finally{Ce(!1)}},[S]),re=we(async()=>{if(S)try{let w=await S.plans();He(w.plans),Re(w.current),ie(null)}catch(w){ie(w)}finally{on(!1)}},[S]),an=Un(!1),[Bn,ce]=J(!1),Be=Un(u!==void 0),ln=we(()=>{an.current||(an.current=!0,queueMicrotask(()=>ce(!0)))},[]);nn(()=>{!S||!Bn||Be.current||re()},[S,Bn,re]);let qe=we(async w=>{if(!S)throw new Error("No session yet.");await S.selectPlan(w),await re()},[S,re]),yn=we(async(w,Y)=>{if(!S)throw new Error("No session yet.");let oe=await S.checkoutPlan(w,Y);if(!oe.url)throw new Error("Checkout could not be started.");return oe.url},[S]),We=we(async()=>{if(!S)throw new Error("No session yet.");await S.leavePlan(),await re()},[S,re]),Fe=Un(c!==void 0);nn(()=>{if(!S)return;let w=Ie(sn,b,{immediate:!Fe.current});return Fe.current=!1,w},[S,sn,b]);let lt=we(async w=>{if(!a)throw new Error("Pass `runEndpoint` to <SobaProvider> to start runs from the browser. It is your own route: it holds your secret key, calls soba.run(), and forwards the stream.");let{signal:Y,...oe}=w,Se=await(y??fetch.bind(globalThis))(a,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},credentials:"same-origin",body:JSON.stringify(oe),...Y?{signal:Y}:{}});if(!Se.ok){let Le=await Se.json().catch(()=>null),cn=new Error(Le?.error?.message??`${a} answered ${Se.status}.`);throw cn.status=Se.status,Le?.error?.code&&(cn.code=Le.error.code),Le?.error&&(cn.error=Le.error),cn}let wn=tr(Se);return async function*(){try{yield*wn}finally{an.current&&re()}}()},[a,y,re]),qn=we((w="manual")=>{p&&(le(!0),he(w))},[p]),Wn=we(()=>he(null),[]),ue=bn(()=>W?Ne.find(w=>w.id===W.plan_id)??null:null,[Ne,W]),Ge=bn(()=>ue?ue.connected_reward==="included"&&te.length>0&&ue.connected_included_units!==null?ue.connected_included_units:ue.included_units:null,[ue,te]),z=bn(()=>({plans:Ne,current:W,plan:ue,used:W?.units_used??null,included:Ge,remaining:Ge!==null&&W?Math.max(0,Ge-W.units_used):null,unlimited:ue!==null&&Ge===null,loading:Ue,error:rn,select:qe,checkout:yn,leave:We,refresh:re}),[Ne,W,ue,Ge,Ue,rn,qe,yn,We,re]),xe=bn(()=>({session:k,client:S,error:M,get plan(){return ln(),z},compute:{machines:te,connected:te.length>0,online:te.some(w=>w.state!=="offline"),loading:K,error:ae,refresh:sn},connect:{app:P?.app??null,command:P?.command??null,connectUrl:P?.connect_url??null,publishableKey:P?.publishable_key??null,loading:q,error:O,open:qn,close:Wn,isOpen:F!==null,hasModal:p},run:lt}),[k,S,M,z,ln,F,qn,Wn,p,te,K,ae,sn,P,q,O,lt]);return pr(zt.Provider,{value:S,children:pr(Kt.Provider,{value:{context:P,machines:K?void 0:te,theme:s??P?.theme??"light"},children:Gs(Vt.Provider,{value:xe,children:[n,p&&T&&pr(An,{open:F!==null,onOpenChange:w=>he(w?F??"manual":null),...F==="payment_required"||F==="no_compute"?{reason:F}:{},...F==="pair"?{showStatus:!1}:{}})]})})})}export{Fo as ComputeStatus,Xe as ConnectButton,Vo as ConnectCompute,An as ConnectModal,es as ConnectNudge,ps as RunError,fs as RunLimit,Is as SobaBilling,$s as SobaCheckout,rr as SobaCurrentPlan,sr as SobaPlans,Fs as SobaProvider,cs as collectText,$n as injectStyles,rt as parseEvent,tr as readEvents,Fr as runErrorMessage,en as sobaErrorCode,Hn as useCurrentPlan,or as usePlans,Xt as useRunLimit,B as useSoba};