@soba-so/react 0.0.13 → 0.0.14

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.
@@ -0,0 +1,66 @@
1
+ /**
2
+ * THE OTHER HALF OF A RUN THAT DID NOT WORK.
3
+ *
4
+ * `<RunLimit>` and `<ConnectNudge>` answer the two failures a person can do
5
+ * something about — `payment_required` and `no_compute` — both decided BEFORE a
6
+ * run starts, where "connect something" or "upgrade" is a real button. This
7
+ * answers everything else: a supplier that refused, a key with no credit left,
8
+ * a model that is gone, a machine that disconnected mid-answer.
9
+ *
10
+ * It exists because that half was shipped as homework. `useRunLimit` returns
11
+ * null for anything unanswerable, which is correct and is also an instruction
12
+ * to the app to go and render something itself — so every surface in this repo
13
+ * wrote its own, four times, each one slightly different, and the one with the
14
+ * most machinery dropped the message on the floor for a month without anybody
15
+ * noticing. A `<p className="error">` is not a hard component to write. It is a
16
+ * very easy one to forget, and forgetting it looks exactly like the product
17
+ * doing nothing at all.
18
+ *
19
+ * THE PAIR IS THE POINT. Drop both in and they never both speak:
20
+ *
21
+ * <RunLimit error={failure} />
22
+ * <RunError error={failure} />
23
+ *
24
+ * The first draws when the failure is answerable and the second when it is not,
25
+ * so between them every failed run says something. That is the whole
26
+ * integration, and neither one needs the app to classify anything.
27
+ */
28
+ export interface RunErrorProps {
29
+ /**
30
+ * Whatever your catch block caught. `null` — the value every app holds before
31
+ * the first failure — renders nothing, as does any failure `<RunLimit>` is
32
+ * already answering.
33
+ *
34
+ * Required, unlike `RunLimit.error`, and deliberately: there is no state form
35
+ * of this. A limit can be foreseen from the plan before anybody presses
36
+ * anything; an error cannot be foreseen at all, and a component that drew one
37
+ * speculatively would be inventing a failure.
38
+ */
39
+ error: unknown;
40
+ /**
41
+ * Run it again. Omitted draws no button, which is right for a surface where
42
+ * retrying is not one press — a chat has its own regenerate and should not
43
+ * grow a second one.
44
+ */
45
+ onRetry?: () => void;
46
+ /** Dismissing. Without it the message stays until the next run replaces it. */
47
+ onDismiss?: () => void;
48
+ /**
49
+ * The line above the message. The default names no cause, because this
50
+ * component by definition does not know the cause — the one thing it is sure
51
+ * of is that the run did not finish.
52
+ */
53
+ title?: string;
54
+ className?: string;
55
+ }
56
+ /**
57
+ * WHAT TO SAY ABOUT A FAILURE, or null when it is not this component's to say.
58
+ *
59
+ * Exported for the same reason `useRunLimit` is: an app whose errors have their
60
+ * own shape should ask this and draw its own. Null means either nothing failed
61
+ * or `<RunLimit>` has it, and in both cases the right thing to render is
62
+ * nothing — so `{runErrorMessage(e) && <MyError …/>}` is a complete integration
63
+ * without the app ever naming a status code.
64
+ */
65
+ export declare function runErrorMessage(error: unknown): string | null;
66
+ export declare function RunError({ error, onRetry, onDismiss, title, className }: RunErrorProps): import("react").JSX.Element | null;
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ export { ConnectModal, type ConnectModalProps } from "./ConnectModal.js";
5
5
  export { ConnectNudge, type ConnectNudgeProps } from "./ConnectNudge.js";
6
6
  export { type ComputeState, type ConnectReason, type ConnectState, type PlanState, type RunRequest, type SobaContextValue, useSoba, } from "./context.js";
7
7
  export { collectText, parseEvent, readEvents } from "./events.js";
8
+ export { RunError, type RunErrorProps, runErrorMessage } from "./RunError.js";
8
9
  export { RunLimit, type RunLimitProps } from "./RunLimit.js";
9
10
  export { SobaBilling, type SobaBillingProps } from "./SobaBilling.js";
10
11
  export { SobaCheckout, type SobaCheckoutProps } from "./SobaCheckout.js";
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 Ln=class extends Error{status;constructor(n,t){super(n),this.name="ConnectError",this.status=t}},sn=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,r){let s=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 s.json()}catch{}if(!s.ok){let i=typeof a.error=="string"?a.error:`Request failed (${s.status})`;throw new Ln(i,s.status)}return a}};function on(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 i=Number.parseInt(t.slice(a*2,a*2+2),16)/255;return i<=.04045?i/12.92:((i+.055)/1.055)**2.4};return .2126*r(0)+.7152*r(1)+.0722*r(2)>.45?"#101012":"#ffffff"}function zn(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 Ye(e,n,t){let r=zn(e),s=zn(n);return!r||!s?e:`#${r.map((i,u)=>Math.round(i+(s[u]-i)*t)).map(i=>i.toString(16).padStart(2,"0")).join("")}`}function an(e,n){if(!zn(e))return{};let t=on(e),r=n?.trim();return{"--sc-ground":e,"--sc-shell":e,"--sc-sheet":Ye(e,t,.07),"--sc-raised":Ye(e,t,.13),"--sc-line":Ye(e,t,.18),"--sc-line-2":Ye(e,t,.28),"--sc-text":t,"--sc-text-2":Ye(t,e,.15),"--sc-muted":Ye(t,e,.38),...r?{"--sc-accent":r,"--sc-accent-fg":on(r)}:{"--sc-accent":t,"--sc-accent-fg":e}}}function Kn(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 jn(e){let{platform:n,arch:t}=e;if(!n)return null;let r=n==="darwin"||n==="macos",s=r?"Mac":n==="win32"||n==="windows"?"Windows PC":"Linux machine";return r?`${t==="aarch64"||t==="arm64"?"Apple silicon ":""}${s}`:s}function ln(e){return e.find(n=>n.state==="offline")??null}function cn(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 me,jsxs as Or}from"react/jsx-runtime";function V({className:e}){return Or("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:[me("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"}),me("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 Gt({className:e}){return me("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:me("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 Qe({className:e}){return me("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:me("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 Ze({className:e}){return me("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:me("path",{d:"M4 5h16v11H4zM9 20h6M12 16v4",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function $e({className:e}){return me("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",className:e,children:me("path",{d:"M5 6h14v10H5zM2.5 19.5h19",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}var he={claude:Gt,chatgpt:Qe,local:Ze};var te=[{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"]}],Vt=["claude","chatgpt"];function Yn(){return te.filter(e=>Vt.includes(e.id))}function Qn(e){return te.filter(n=>n.costClass===e)}function un(e){return te.find(n=>n.expects.includes(e))??null}import{jsx as W,jsxs as De}from"react/jsx-runtime";function Je({machines:e,onApproveRuntime:n}){return e.length?W("div",{children:e.map(t=>{let r=cn(t),s=jn(t);return De("div",{className:"sc-machine",children:[De("div",{className:"sc-idrow",children:[W("span",{className:"sc-opt-tile","aria-hidden":"true",children:W($e,{className:"sc-opt-mark"})}),De("span",{className:"sc-opt-text",children:[W("span",{className:"sc-opt-label",children:t.label??"This machine"}),(s||t.always_on)&&De("span",{className:"sc-machine-meta",children:[s&&W("span",{children:s}),t.always_on&&W("span",{className:"sc-machine-tag",children:"always on"})]})]}),De("span",{className:"sc-machine-state",children:[W("span",{className:`sc-dot sc-dot-${r.tone}`,"aria-hidden":"true"}),r.text]})]}),De("ul",{className:"sc-runtimes",children:[t.runtimes.map(a=>W(Tr,{runtime:a,...n?{onApprove:()=>n(t.id,a.id)}:{}},a.id)),!t.runtimes.length&&W("li",{className:"sc-note",children:"No runtime advertised. Install Claude Code, Codex or Ollama on that machine."})]})]},t.id)})}):W("p",{className:"sc-note",children:"Nothing connected yet."})}function Tr({runtime:e,onApprove:n}){let t=un(e.id),r=t?he[t.id]:null,s=Kn(e);return De("li",{className:"sc-runtime",children:[W("span",{className:"sc-runtime-tile","aria-hidden":"true",children:r&&W(r,{className:"sc-runtime-mark"})}),W("span",{className:"sc-runtime-name",children:e.display_name}),e.quarantined?n?W("button",{type:"button",className:"sc-conn-action",onClick:n,children:"Let it serve"}):W("span",{className:"sc-runtime-verdict sc-tone-warn",children:"new, not serving yet"}):W("span",{className:`sc-runtime-verdict sc-tone-${s.tone}`,children:s.text})]})}var Zn={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 Jn="105 162 420 420",Xn="M407.1 308.9 A158 158 0 1 0 407.1 491.1 A116 116 0 0 1 407.1 308.9 Z",Ue="M448.5 320 A110 110 0 0 1 448.5 480";import{Fragment as pn,jsx as C,jsxs as _e}from"react/jsx-runtime";function et({kind:e,size:n=44,className:t}){let r=Zn[e];return _e("svg",{className:`bx${t?` ${t}`:""}`,"data-expression":e,viewBox:Jn,overflow:"visible",width:n,height:n,"aria-hidden":"true",children:[C("path",{d:Xn,fill:"currentColor"}),C("path",{className:"bx-arc",d:Ue,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"}),r.slot==="stream"&&C(Ir,{}),r.slot==="zzz"&&C(Ar,{}),r.slot==="dots"&&C($r,{}),r.slot==="bang"&&C(Dr,{}),r.slot==="orbit"&&C(Ur,{}),r.slot==="cross"&&C(Hr,{}),r.slot==="snap"&&C(qr,{}),r.slot==="bars"&&C(Br,{}),r.slot==="ring"&&C(Fr,{}),r.slot==="sparks"&&C(Wr,{})]})}function Ir(){return C("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 Ar(){return _e(pn,{children:[C("g",{className:"bx-z1",children:C("path",{d:"M444 372 H496 L444 436 H496",fill:"none",stroke:"currentColor",strokeWidth:"20",strokeLinecap:"round",strokeLinejoin:"round"})}),C("g",{className:"bx-z2",children:C("path",{d:"M492 300 H522 L492 338 H522",fill:"none",stroke:"currentColor",strokeWidth:"15",strokeLinecap:"round",strokeLinejoin:"round"})})]})}function $r(){return _e(pn,{children:[C("circle",{className:"bx-th",cx:"463.1",cy:"336.9",r:"21",fill:"currentColor"}),C("circle",{className:"bx-th bx-th2",cx:"483",cy:"400",r:"21",fill:"currentColor"}),C("circle",{className:"bx-th bx-th3",cx:"463.1",cy:"463.1",r:"21",fill:"currentColor"})]})}function Dr(){return _e("g",{className:"bx-at",children:[C("line",{x1:"490",y1:"312",x2:"490",y2:"414",stroke:"currentColor",strokeWidth:"46",strokeLinecap:"round"}),C("circle",{cx:"490",cy:"484",r:"28",fill:"currentColor"})]})}function Ur(){return _e("g",{className:"bx-ob",children:[C("path",{d:Ue,fill:"none",stroke:"var(--tile-bg, transparent)",strokeWidth:41,strokeLinecap:"round"}),C("path",{d:Ue,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"})]})}function Hr(){return _e(pn,{children:[C("path",{className:"bx-xa",d:Ue,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"}),C("g",{className:"bx-xx",children:C("path",{d:"M442 364 L514 436 M514 364 L442 436",fill:"none",stroke:"currentColor",strokeWidth:"24",strokeLinecap:"round"})})]})}function qr(){return C("path",{className:"bx-snap",d:Ue,fill:"none",stroke:"currentColor",strokeWidth:17,strokeLinecap:"round"})}function Br(){return _e("g",{stroke:"currentColor",strokeWidth:"17",strokeLinecap:"round",children:[C("line",{className:"bx-vb",x1:"452",y1:"370",x2:"452",y2:"430"}),C("line",{className:"bx-vb bx-vb2",x1:"482",y1:"330",x2:"482",y2:"470"}),C("line",{className:"bx-vb bx-vb3",x1:"512",y1:"355",x2:"512",y2:"445"})]})}function Fr(){return C(pn,{children:[[450,366],[474,376],[484,400],[474,424],[450,434],[426,424],[416,400],[426,376]].map(([n,t],r)=>C("circle",{className:"bx-w",cx:n,cy:t,r:"11",fill:"currentColor",style:{animationDelay:`${-1.2+r*.15}s`}},r))})}function Wr(){return _e(pn,{children:[C("g",{className:"bx-sp",children:C("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"})}),C("g",{className:"bx-sp bx-sp2",children:C("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"})}),C("g",{className:"bx-sp bx-sp3",children:C("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 J,useEffect as re,useId as Kr,useMemo as Ee,useRef as Xe,useState as $}from"react";var mn=[{slug:"mac-arm",label:"macOS, Apple silicon"},{slug:"mac-intel",label:"macOS, Intel"},{slug:"windows",label:"Windows"},{slug:"linux",label:"Linux"}];function hn(e){if(!e)return"";try{return new URL(e).origin}catch{return""}}var nt="soba";function Kt(){return`${nt}://show`}function fn(e,n,t){let r=`${nt}://connect?url=${encodeURIComponent(e)}`;return n&&(r+=`&nonce=${encodeURIComponent(n)}`),t&&(r+=`&want=${encodeURIComponent(t)}`),r}function gn(){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 Gr=1600;function tt(e={}){return ot(e)}async function rt(e,n={}){if(typeof window>"u"||typeof document>"u")return"unknown";let t=ot(n);try{window.location.href=fn(e,n.nonce,n.want)}catch{return"absent"}return t}async function st(e={}){if(typeof window>"u"||typeof document>"u")return"unknown";let n=ot(e);try{window.location.href=Kt()}catch{return"absent"}return n}async function ot(e){if(typeof window>"u"||typeof document>"u")return"unknown";let n=e.graceMs??Gr,t=document.visibilityState==="visible"&&document.hasFocus(),r=!1,s=()=>{r=!0},a=()=>{document.visibilityState==="hidden"&&(r=!0)};return window.addEventListener("blur",s),window.addEventListener("pagehide",s),document.addEventListener("visibilitychange",a),await new Promise(i=>setTimeout(i,n)),window.removeEventListener("blur",s),window.removeEventListener("pagehide",s),document.removeEventListener("visibilitychange",a),t?r?"opened":"absent":"unknown"}var jt="soba.connect.choice",Vr=180*24*60*60*1e3;function Qt(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 at(e,n){return e?n?`${jt}.${e}.${Qt(n)}`:`${jt}.${e}`:null}function it(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)>Vr)return null;let r=te.find(s=>s.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 Yt="soba.connect.dismissed",zr=30*24*60*60*1e3;function ct(e,n){return e?n?`${Yt}.${e}.${Qt(n)}`:`${Yt}.${e}`:null}function ut(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)<zr}catch{return!1}}function dt(e){if(!(!e||typeof localStorage>"u"))try{localStorage.setItem(e,JSON.stringify({at:new Date().toISOString()}))}catch{}}import{Fragment as Tn,jsx as o,jsxs as v}from"react/jsx-runtime";var pt=2e3,jr=1e4,Yr=9e4,Qr=6e4;function mt(e,n,t,r=[],s){return e?"code":n&&(t.length>0||r.length>0)?"manage":s?"launch":"choose"}function Zr(e){let n=Math.max(0,Math.round(e/1e3));return`${Math.floor(n/60)}:${String(n%60).padStart(2,"0")}`}function gt({client:e,initialCode:n,initialChoice:t,onConnected:r,showStatus:s=!0,initialContext:a=null,initialMachines:i,onClose:u,headingId:l,theme:p,reason:f}){let g=!!a&&i!==void 0,[m,b]=$(g?mt(n,s,i??[],[],t):"loading"),[h,k]=$(a),[N,x]=$(i??[]),[U,j]=$(n??""),[S,O]=$(null),[H,T]=$(null),[M,q]=$(!1),[G,ce]=$(0),[Me,_n]=$(()=>Date.now()),[Q,ke]=$(null),[En,xe]=$(!1),[be,X]=$(!1),[Bn,tn]=$("browser"),[We,Mn]=$(null),[ue,se]=$([]),[Ge,Fn]=$(0),[Re,Ve]=$(null),oe=Xe(null),[R,P]=$(t??null),[Le,ee]=$(null),rn=Ee(()=>{let c=h?.accent?.trim(),w=h?.background?.trim();if(!(!c&&!w))return w?{...an(w,c),background:w,borderRadius:"inherit"}:{"--sc-accent":c,"--sc-accent-fg":on(c)}},[h?.accent,h?.background]),Rn=Kr(),ae=l??Rn,Se=Xe(null);re(()=>{if(!e||g)return;let c=!0;return Promise.all([e.context(),e.machines()]).then(([w,L])=>{c&&(k(w),x(L),b(mt(n,s,L)))}).catch(w=>{c&&(T(w.message),b("choose"))}),()=>{c=!1}},[e,n,s,g]),re(()=>{m!=="loading"||!g||b(mt(n,s,i??[]))},[m,g,n,s,i]),re(()=>{i&&x(i)},[i]),re(()=>{a&&k(a)},[a]);let ze=Xe(!1),Ke=Xe(m);Ke.current=m;let ne=Xe(ue);ne.current=ue;let de=!!h?.hosted_available;re(()=>{if(!e||m!=="manage")return;let c=!0,w=setInterval(async()=>{try{let L=await e.machines();if(!c)return;x(L);let A=!de||ze.current;L.length===0&&ne.current.length===0&&A&&Ke.current==="manage"&&b("choose")}catch{}},jr);return()=>{c=!1,clearInterval(w)}},[m,e,de]);let je=at(h?.publishable_key??null);re(()=>{ee(it(je))},[je]),re(()=>{if(!e||!de)return;let c=!0;return e.hosted().then(w=>{c&&(se(w.credentials),!ze.current&&(ze.current=!0,w.credentials.length>0&&s&&Ke.current==="choose"&&b("manage")))}).catch(()=>{}),()=>{c=!1}},[e,de,s]),re(()=>{if(!e||m!=="hosted")return;let c=!0,w=async()=>{try{let Pe=await e.hosted();if(!c)return!1;if(se(Pe.credentials),Pe.credentials.length>0)return b("hosted_connected"),Ve(null),!0}catch{}return!1},L=async()=>{oe.current?.closed&&(oe.current=null,!await w()&&c&&b("choose"))},A=setInterval(()=>{w(),L()},pt),Ae=setInterval(L,400),we=Pe=>{let Wt=Pe.data;Wt?.source==="soba"&&Wt.type==="hosted_result"&&w()};return window.addEventListener("message",we),()=>{c=!1,clearInterval(A),clearInterval(Ae),window.removeEventListener("message",we),oe.current=null}},[e,m]);let y=J(()=>{if(!e)return;let c=window.open("","soba-connect-plan","width=520,height=760,noopener=no");oe.current=c,b("hosted"),Fn(Date.now()),Ve(null),T(null),e.startHosted().then(({url:w})=>{if(c&&!c.closed){c.location.href=w;return}Ve(w)}).catch(w=>{c?.close(),oe.current=null,T(w.message),b("choose")})},[e]),B=J(async c=>{if(e){q(!0);try{await e.disconnectHosted(c),se((await e.hosted()).credentials)}catch(w){T(w.message)}finally{q(!1)}}},[e]);re(()=>{if(!e||m!=="waiting")return;let c=!0,w=setInterval(async()=>{try{let L=await e.machines();if(!c)return;x(L);let A=Se.current;if(!A)return;let Ae=L.filter(Pe=>!A.has(Pe.id)),we=Ae.find(Pe=>Pe.state!=="offline")??Ae[0];we&&(Mn(we.id),R&&lt(je,R),b("connected"),r?.(L))}catch{}},pt);return()=>{c=!1,clearInterval(w)}},[m,e,r,R,je]);let pe=J(async()=>{if(e){T(null),q(!0);try{let c=await e.lookup(U);O(c),b("confirm")}catch(c){T(c.message)}finally{q(!1)}}},[e,U]),qt=J(async()=>{if(e){T(null),q(!0);try{try{Se.current=new Set((await e.machines()).map(c=>c.id))}catch{Se.current=new Set(N.map(c=>c.id))}await e.approve(U),b("waiting"),ce(Date.now())}catch(c){T(c.message)}finally{q(!1)}}},[e,U,N]),Oe=J(async()=>{if(e){q(!0);try{await e.deny(U),tn("browser"),b("denied")}catch(c){T(c.message)}finally{q(!1)}}},[e,U]),F=Ee(()=>h?.connect_url??null,[h]),[Z,Te]=$(()=>gn()),_r=Ee(()=>F?fn(F,Z??void 0,R??void 0):null,[F,Z,R]),Er=Ee(()=>hn(F),[F]),Mr=J(c=>{if(N.length===0)return null;let w=te.find(A=>A.id===c);if(!w)return null;let L=N.flatMap(A=>A.runtimes??[]).filter(A=>w.expects.includes(A.id));return L.length===0?{tone:"dim",text:"not installed"}:L.some(A=>A.authenticated===!0)?{tone:"ok",text:"ready"}:L.every(A=>A.authenticated===!1)?{tone:"warn",text:"needs signing in"}:{tone:"dim",text:"installed"}},[N]),Rr=J((c=null)=>{P(c),T(null),ke(null),xe(!1),X(!1),Wn.current=!1,Te(gn()),b("launch")},[]),Wn=Xe(!!t);re(()=>{m!=="launch"||!F||Wn.current||(Wn.current=!0,xe(!0),rt(F,{...Z?{nonce:Z}:{},...R?{want:R}:{}}).then(ke))},[m,F,Z,R]);let Bt=J(()=>{xe(!0),tt().then(ke)},[]),Lr=J(c=>{if(be){let w=gn();X(!1),Te(w),F&&(c.preventDefault(),window.location.href=fn(F,w??void 0,R??void 0))}Bt()},[be,Bt,F,R]),Gn=Ee(()=>{let c=h?.runtimes;return c?te.filter(w=>c.includes(w.id)):Yn()},[h?.runtimes]),ye=Ee(()=>{let c=te.find(w=>w.id===R);return c?{choice:c,Mark:he[c.id]??null}:null},[R]),Vn=Ee(()=>N.find(c=>c.id===We),[N,We]);re(()=>{let c=Z;if(!e||m!=="launch"||!c)return;let w=!1,L=Date.now()+15e4,A=setInterval(async()=>{if(Date.now()>L){clearInterval(A),X(!0);return}try{let Ae=await e.claim(c);if(w)return;if(Ae.declined){clearInterval(A),ke(null),tn("machine"),b("denied");return}if(!Ae.claimed)return;clearInterval(A);try{Se.current=new Set((await e.machines()).map(we=>we.id))}catch{Se.current=new Set(N.map(we=>we.id))}b("waiting"),ce(Date.now())}catch{}},pt);return()=>{w=!0,clearInterval(A)}},[e,m,N,Z]);let Ie=Ee(()=>{if(!S)return null;if(S.approved||S.denied)return"answered";let c=S.expires_at?Date.parse(S.expires_at):Number.NaN;return Number.isFinite(c)&&c<=Me?"expired":"live"},[S,Me]);re(()=>{if(!(m==="confirm"&&Ie==="live"||m==="waiting"||m==="hosted"))return;let w=setInterval(()=>_n(Date.now()),1e3);return()=>clearInterval(w)},[m,Ie]);let Ft=J(async(c,w)=>{if(e)try{await e.approveRuntime(c,w),x(await e.machines())}catch(L){T(L.message)}},[e]);return m==="loading"?o("div",{className:"soba-connect",...p?{"data-theme":p}:{},style:rn,children:o("div",{className:"sc-card",children:o("p",{className:"sc-note",children:"Loading\u2026"})})}):v("div",{className:"soba-connect",...p?{"data-theme":p}:{},style:rn,children:[u&&o("button",{type:"button",className:"sc-modal-close",onClick:u,"aria-label":"Close",children:"\xD7"}),m==="manage"&&v("div",{className:"sc-card",children:[o("h2",{className:"sc-title",children:"Your compute"}),v("p",{className:"sc-sub",children:[o(bn,{context:h})," ",N.length>0&&ue.length>0?"runs on your connected plan, and on these machines while they are awake.":ue.length>0?"runs on the plan you connected. Nothing here is charged to you.":"runs on these machines, while they are awake."]}),v("div",{className:"sc-conns",children:[ue.map(c=>v("div",{className:"sc-conn",children:[o("span",{className:"sc-opt-tile","aria-hidden":"true",children:o(Qe,{className:"sc-opt-mark"})}),v("div",{className:"sc-opt-text",children:[o("span",{className:"sc-opt-label",children:c.provider==="openai-chatgpt"?"ChatGPT plan":c.provider}),o("span",{className:"sc-opt-sub",children:c.account_label??"signed in"})]}),o("button",{type:"button",className:"sc-conn-action",onClick:()=>void B(c.provider),disabled:M,children:"Disconnect"}),v("p",{className:"sc-conn-note",children:[o(bn,{context:h})," stops using it. To withdraw the grant entirely, remove it in your OpenAI settings."]})]},c.provider)),o(Je,{machines:N,onApproveRuntime:Ft})]}),H&&o("p",{className:"sc-error",children:H}),o("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>b("choose"),children:N.length>0?"Connect another machine":"Connect compute"})]}),m==="choose"&&v("div",{className:"sc-card",children:[o(Xr,{context:h}),o("h2",{className:"sc-h",id:ae,children:f==="payment_required"?"Carry on with your own AI":f==="no_compute"?"This run needs a machine":"Connect your AI"}),o("p",{className:"sc-p",children:"Use compute you already have."}),F&&Gn.length>0&&v(Tn,{children:[o("div",{className:"sc-opts",children:Gn.map(c=>{let w=he[c.id];return v("button",{type:"button",className:"sc-opt",onClick:()=>Rr(c.id),children:[o("span",{className:"sc-opt-tile","aria-hidden":"true",children:w&&o(w,{className:"sc-opt-mark"})}),o("span",{className:"sc-opt-text",children:o("span",{className:"sc-opt-label",children:c.label})}),(()=>{let L=Mr(c.id);return L?o("span",{className:`sc-opt-has sc-opt-has-${L.tone}`,children:L.text}):Le===c.id?o("span",{className:"sc-opt-last",children:"last used"}):o(ht,{className:"sc-opt-go"})})()]},c.id)})}),v("p",{className:"sc-opt-note",children:["Your accounts stay there. ",Zt(h)," never sees them."]})]}),(!F||Gn.length===0)&&o("p",{className:"sc-error",style:{marginTop:16},children:"This app has no publishable key yet, so there is nothing to pair against."}),H&&o("p",{className:"sc-error",children:H}),F&&h?.show_code===!0&&o("div",{className:"sc-opt-alt",children:o("button",{type:"button",className:"sc-alt-link",onClick:()=>b("code"),children:"I have a code"})})]}),m==="launch"&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("choose")}),o("p",{className:"sc-head-title",children:"Soba App"})]}),o(On,{mark:ye?.Mark??V,still:be||!En&&Q===null}),o("h2",{className:"sc-h",id:ae,children:be?"No answer from this machine":Q==="absent"?"Nothing opened":Q===null?"Opening Soba App\u2026":"Approve it on this machine"}),be?o("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."}):Q==="absent"?o("p",{className:"sc-p",children:"Nothing opened on this machine. Open it yourself below, or install it if it is not here yet."}):o("p",{className:"sc-p",children:Q===null?"Approve it there and this page does the rest.":"This page finishes on its own."}),ye&&v("p",{className:"sc-prereq",children:[ye.Mark&&o(ye.Mark,{className:"sc-rt-mark"}),"Needs ",ye.choice.prerequisite]}),v("div",{className:"sc-stack",style:{marginTop:18},children:[o("a",{className:Q==="absent"||be?"sc-btn sc-btn-primary":"sc-btn",href:_r??"#",onClick:Lr,children:be?"Try again":Q==="absent"?"Open Soba App":"Open it again"}),o("p",{className:"sc-note",children:Q===null?"Your browser will ask permission first.":"Your browser asks permission the first time."}),ye&&Q==="absent"&&o("p",{className:"sc-note",children:o(es,{text:ye.choice.hint})}),v("div",{className:"sc-foot-strip",children:[o("span",{children:"Not installed on this machine?"}),v("button",{type:"button",className:"sc-foot-go",onClick:()=>b("get"),children:["Get it",o(ht,{})]})]})]})]}),m==="get"&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("launch")}),o("p",{className:"sc-head-title",children:"Get Soba App"})]}),o("div",{className:"sc-opts",children:mn.map(c=>v("a",{className:"sc-opt",href:`${Er}/download/${c.slug}`,target:"_blank",rel:"noreferrer noopener",children:[o("span",{className:"sc-opt-tile","aria-hidden":"true",children:o($e,{className:"sc-opt-mark"})}),o("span",{className:"sc-opt-text",children:o("span",{className:"sc-opt-label",children:c.label})}),o(ht,{className:"sc-opt-go"})]},c.slug))}),o("p",{className:"sc-opt-note",children:"Install it, then come back here and press the row you started with."})]}),m==="code"&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("choose")}),o("p",{className:"sc-head-title",children:"Soba App"})]}),o("h2",{className:"sc-h",id:ae,children:"Enter the code from that machine"}),o("p",{className:"sc-p",children:"Eight characters, shown by the Soba app once you paste the link."}),v("form",{className:"sc-stack",style:{marginTop:16},onSubmit:c=>{c.preventDefault(),pe()},children:[o("input",{className:"sc-input",value:U,onChange:c=>j(c.target.value),placeholder:"ACDE-F234",autoComplete:"off",autoFocus:!0,"aria-label":"Pairing code"}),H&&o("p",{className:"sc-error",children:H}),o("button",{type:"submit",className:"sc-btn sc-btn-primary",disabled:M||U.length<8,children:M?"Checking\u2026":"Continue"})]})]}),m==="confirm"&&S&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("code")}),o("p",{className:"sc-head-title",children:"Soba App"})]}),o("h2",{className:"sc-title",children:"Attach this machine to your account?"}),v("p",{className:"sc-sub",children:[o(bn,{context:h})," may send your runs to it once you approve. It can never see the account or the keys on it."]}),v("ul",{className:"sc-facts",children:[o(yn,{k:"Code",v:S.user_code}),o(yn,{k:"Machine",v:S.hostname??"not stated"}),o(yn,{k:"System",v:[S.platform,S.arch].filter(Boolean).join(" / ")||"not stated"}),o(yn,{k:"Asked by",v:S.client??"not stated"}),S.labels.length>0&&o(yn,{k:"Labels",v:S.labels.join(", ")})]}),o("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."}),Ie==="expired"&&o("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."}),Ie==="answered"&&o("p",{className:"sc-error",children:"That code has already been answered. If it was not you, deny the next one."}),H&&o("p",{className:"sc-error",children:H}),v("div",{className:"sc-row",style:{marginTop:16},children:[o("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:()=>void qt(),disabled:M||Ie!=="live",children:"Approve"}),o("button",{type:"button",className:"sc-btn",onClick:()=>void Oe(),disabled:M||Ie==="answered",children:"No, deny it"})]}),Ie==="live"&&S.expires_at&&v("p",{className:"sc-note",style:{marginTop:10},children:["This code expires in ",Zr(Date.parse(S.expires_at)-Me),"."]})]}),m==="waiting"&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("choose")}),o("p",{className:"sc-head-title",children:ye?.choice.short??"Soba App"})]}),o(On,{mark:ye?.Mark??V}),o("h2",{className:"sc-h",id:ae,children:"Approved. Waiting for it to connect"}),o("p",{className:"sc-p",children:"Nothing more to do here. This page changes when it arrives."}),G>0&&Me-G>Yr&&o("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."})]}),m==="connected"&&v("div",{className:"sc-card",children:[o(ft,{tone:"ok"}),o("h2",{className:"sc-h",id:ae,children:Vn?.label?`${Vn.label} is connected`:"Connected"}),v("p",{className:"sc-p",children:[o(bn,{context:h})," will use ",Vn?.label?"it":"this machine"," from now on, while it is awake."]}),s&&v(Tn,{children:[o("div",{style:{marginTop:16},children:o(Je,{machines:N,onApproveRuntime:Ft})}),o("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:14},onClick:()=>b("manage"),children:"Done"})]})]}),m==="hosted"&&v("div",{className:"sc-card",children:[v("div",{className:"sc-head",children:[o(en,{onClick:()=>b("choose")}),o("p",{className:"sc-head-title",children:"ChatGPT"})]}),Re?o(On,{mark:Qe,still:!0}):o(On,{mark:Qe}),o("h2",{className:"sc-h",id:ae,children:Re?"Your browser blocked the window":"Finish signing in to ChatGPT"}),o("p",{className:"sc-p",children:Re?"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."}),v("div",{className:"sc-stack",style:{marginTop:18},children:[Re&&o("a",{className:"sc-btn sc-btn-primary",href:Re,target:"soba-connect-plan",rel:"noreferrer",children:"Open the ChatGPT sign-in"}),H&&o("p",{className:"sc-error",children:H}),Ge>0&&Me-Ge>Qr&&o("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."})]})]}),m==="hosted_connected"&&v("div",{className:"sc-card",children:[o(ft,{tone:"ok"}),o("h2",{className:"sc-h",id:ae,children:"ChatGPT is connected"}),v("p",{className:"sc-p",children:[o(bn,{context:h})," will run on your ChatGPT plan",ue[0]?.account_label?` (${ue[0].account_label})`:"",". Nothing more to pay, nothing to install."]}),o("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."}),s&&v(Tn,{children:[o("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>b("manage"),children:"Done"}),o("div",{className:"sc-opt-alt",children:o("button",{type:"button",className:"sc-alt-link",onClick:()=>b("choose"),children:"Connect a machine too"})})]})]}),m==="denied"&&v("div",{className:"sc-card",children:[o(ft,{tone:"off"}),o("h2",{className:"sc-h",id:ae,children:"Declined"}),o("p",{className:"sc-p",children:Bn==="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."}),o("button",{type:"button",className:"sc-btn sc-btn-wide",style:{marginTop:16},onClick:()=>b("choose"),children:"Back to the start"})]})]})}function Zt(e){return e?.app.name??"this app"}function Jr(e){let n=e?.app.icon_urls;if(n?.length)return n;let t=e?.app.icon_url;return t?[t]:[]}function Jt(e){let n=Jr(e),[t,r]=$([]),s=J(u=>{u&&r(l=>l.includes(u)?l:[...l,u])},[]),a=J(u=>s(u.currentTarget.getAttribute("src")),[s]),i=J(u=>{u?.complete&&u.naturalWidth===0&&s(u.getAttribute("src"))},[s]);return{icon:n.find(u=>!t.includes(u)),onError:a,ref:i}}function Xr({context:e}){let{icon:n,onError:t,ref:r}=Jt(e);return e?.app.mark==="soba"?o(V,{className:"sc-app-mark"}):n?o("img",{className:"sc-app-mark",src:n,alt:"","aria-hidden":"true",ref:r,onError:t}):null}function bn({context:e}){let{icon:n,onError:t,ref:r}=Jt(e),s=e?.app.mark==="soba";return v("span",{className:"sc-app",children:[s&&o(V,{className:"sc-app-icon"}),!s&&n&&o("img",{className:"sc-app-icon",src:n,alt:"",ref:r,onError:t}),Zt(e)]})}function en({onClick:e}){return o("button",{type:"button",className:"sc-head-back",onClick:e,"aria-label":"Back",children:o("svg",{viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:o("path",{d:"M15 5 8 12l7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})})}function ht({className:e}){return o("svg",{className:e,viewBox:"0 0 24 24","aria-hidden":"true",focusable:"false",children:o("path",{d:"M9 5l7 7-7 7",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function On({mark:e,still:n}){return v("span",{className:"sc-waiting","aria-hidden":"true",children:[!n&&o("svg",{className:"sc-waiting-orbit",viewBox:"0 0 100 100","aria-hidden":"true",focusable:"false",children:o("circle",{className:"sc-waiting-arc",cx:"50",cy:"50",r:"46"})}),o(e,{className:"sc-waiting-mark"})]})}function ft({tone:e}){return o("span",{className:`sc-result sc-result-${e}`,"aria-hidden":"true",children:o(et,{kind:e==="ok"?"snap":"gone",size:84})})}function es({text:e}){return o(Tn,{children:e.split("`").map((n,t)=>t%2===1?o("code",{className:"sc-inline-code",children:n},t):n)})}function yn({k:e,v:n}){return v("li",{className:"sc-fact",children:[o("span",{className:"sc-fact-key",children:e}),o("span",{children:n})]})}import{useEffect as ns,useRef as yt}from"react";var In=0,bt=null;function Xt(){if(typeof document>"u")return()=>{};In===0&&(bt=document.body.style.overflow,document.body.style.overflow="hidden"),In+=1;let e=!1;return()=>{e||(e=!0,In-=1,In===0&&(document.body.style.overflow=bt??"",bt=null))}}import{jsx as er}from"react/jsx-runtime";function wn({open:e,onClose:n,labelledBy:t,theme:r,style:s,children:a}){let i=yt(null),u=yt(null),l=yt(null);return ns(()=>{let p=i.current;if(p){if(!e){p.open&&p.close();return}return p.open||p.showModal(),document.activeElement===p&&u.current?.focus(),Xt()}},[e]),er("dialog",{ref:i,className:"soba-connect sc-modal","aria-labelledby":t,...r?{"data-theme":r}:{},style:s,onCancel:p=>{p.preventDefault(),n()},onPointerDown:p=>{l.current=p.target},onClick:p=>{p.target===p.currentTarget&&l.current===p.currentTarget&&n()},children:er("div",{className:"sc-modal-sheet",ref:u,tabIndex:-1,children:a})})}function ve(e){let n=`${e.unit}s`;return e.reward==="unlimited"?`Unlimited ${n} on your own AI`:e.reward==="included"&&e.includedUnits!==null?`${rs(e.includedUnits)} ${n} a month once you connect`:e.reward==="credit"&&e.creditMicros>0?`${ts(e.creditMicros)} back each month you stay connected`:null}function Ce(e){return e==="unlimited"||e==="included"}var tr=new Set(["user-hardware","user-subscription"]),nr=new Set(["open-weights","frontier"]);function ie(e){return e===null||e.length===0?!1:e.every(n=>tr.has(n))}var ts=e=>(e/1e6).toLocaleString("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}),rs=e=>e.toLocaleString("en-US");function wt(e,n){if(!(n===null||n.some(a=>nr.has(a))))return!1;let r=e.findIndex(a=>tr.has(a));if(r===-1)return!1;let s=e.findIndex(a=>nr.has(a));return s===-1||r<s}import{createContext as ss,useContext as os}from"react";var vt=ss(null);function D(){let e=os(vt);if(!e)throw new Error("useSoba() must be used inside a <SobaProvider>.");return e}import{createContext as rr,useContext as sr}from"react";var Ct=rr(null);function or(){return sr(Ct)}var Nt=rr({context:null,machines:void 0,theme:"light"});function I(){return sr(Nt)}import{jsx as vn}from"react/jsx-runtime";function as({className:e}){let{theme:n}=I(),t=e?`soba-connect ${e}`:"soba-connect";return vn("div",{className:t,"data-theme":n,children:vn(kt,{})})}function kt(){let{compute:e}=D();return e.loading&&!e.machines.length?vn("p",{className:"sc-note",children:"Loading\u2026"}):e.error&&!e.machines.length?vn("p",{className:"sc-error",children:e.error.message}):vn(Je,{machines:e.machines})}import{useEffect as ls,useRef as ar,useState as cs}from"react";import{useId as is}from"react";import{jsx as nn,jsxs as An}from"react/jsx-runtime";function Cn({open:e,onOpenChange:n,initialCode:t,onConnected:r,showStatus:s,reason:a}){let{error:i}=D(),u=or(),l=I(),p=()=>n(!1),f=is(),g=l.context?.background?.trim(),m=g?an(g,l.context?.accent):void 0;return An(wn,{open:e,onClose:p,labelledBy:f,theme:l.theme,style:m,children:[i?An("div",{className:"sc-card",children:[nn("h2",{className:"sc-title",id:f,children:"Could not start"}),nn("p",{className:"sc-error",children:i.message})]}):!u&&!l.context?An("div",{className:"sc-card",children:[nn("h2",{className:"sc-title",id:f,children:"One moment"}),nn("p",{className:"sc-note",children:"Getting your compute\u2026"})]}):nn(gt,{client:u,onClose:p,headingId:f,theme:l.theme,initialContext:l.context,...l.machines!==void 0?{initialMachines:l.machines}:{},...t?{initialCode:t}:{},...r?{onConnected:r}:{},...s===void 0?{}:{showStatus:s},...a?{reason:a}:{}}),An("p",{className:"sc-modal-foot",children:[nn(V,{className:"sc-foot-mark"}),"Secured by Soba"]})]})}import{Fragment as xt,jsx as He,jsxs as Nn}from"react/jsx-runtime";function qe({children:e,variant:n,className:t,initialCode:r,onConnected:s,defaultOpen:a,open:i,onOpenChange:u,showConnected:l=!0}){let{compute:p,connect:f}=D(),{theme:g}=I(),[m,b]=cs(a??!!r),h=ar(null),k=i!==void 0,N=!k&&!a&&!r&&f.hasModal,x=k?i:N?f.isOpen:m,U=G=>{N?G?f.open("manual"):f.close():k||b(G),u?.(G)},j=ar(x);ls(()=>{j.current&&!x&&h.current?.focus(),j.current=x},[x]);let S=p.machines.find(G=>G.state!=="offline")??p.machines[0],O=S?.runtimes?.find(G=>!G.quarantined)??S?.runtimes?.[0],H=l&&S!==void 0,T=S?cn(S):null,M=O?un(O.id):void 0,q=(M?he[M.id]:void 0)??(O?Ze:$e);return Nn(xt,{children:[He("button",{ref:h,type:"button","data-theme":g,className:["sc-btn",H?"sc-btn-connected":"sc-btn-icon",!H&&n==="primary"?"sc-btn-primary":"",t].filter(Boolean).join(" "),onClick:()=>U(!0),children:e??(H?Nn(xt,{children:[He("span",{className:"sc-runtime-tile","aria-hidden":"true",children:He(q,{className:"sc-runtime-mark"})}),Nn("span",{className:"sc-btn-connected-text",children:[O?.display_name??"Connected",S?.label&&Nn("span",{className:"sc-btn-connected-where",children:[" on ",S.label]})]}),He("i",{className:`sc-dot sc-dot-${T?.tone??"off"}`,"aria-hidden":"true"}),T&&He("span",{className:"sc-sr",children:T.text})]}):Nn(xt,{children:[He(V,{className:"sc-btn-mark"}),"Connect compute"]}))}),!N&&He(Cn,{open:x,onOpenChange:U,...r?{initialCode:r}:{},...s?{onConnected:s}:{}})]})}import{jsx as St,jsxs as ds}from"react/jsx-runtime";function us({initialCode:e,onConnected:n,className:t,showStatus:r=!0}){let{theme:s}=I();return ds("div",{className:t?`soba-connect ${t}`:"soba-connect","data-theme":s,children:[r&&St(kt,{}),St("div",{className:"sc-compute-act",children:St(qe,{...e?{initialCode:e}:{},...n?{onConnected:n}:{}})})]})}import{useEffect as pr,useId as ys,useState as _t}from"react";import{useCallback as ps,useState as ms}from"react";function $n(){let[e,n]=ms(null);return{open:ps(()=>{n(null),st().then(n)},[]),launch:e,note:e==="absent"?"Nothing opened here. That machine may be a different computer, or asleep.":null}}import{useCallback as ir,useMemo as lr}from"react";function Be(e){if(!e)return null;if(typeof e=="string")return e;if(typeof Response<"u"&&e instanceof Response)return cr(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"?cr(n.status):n.cause&&n.cause!==e?Be(n.cause):null}function cr(e){return e===402?"payment_required":e===409?"no_compute":null}function Pt(...e){let[n,t]=e,{plan:r,compute:s,connect:a}=D(),i=t?.predict??e.length===0,u=fs(hs(n),s)??(i?gs(r,s):null),l=r.plan,p=r.plans,f=lr(()=>{if(u!=="payment_required")return null;let h=l?.price??0,k=l?.included_units??0;return p.find(N=>N.id!==l?.id&&N.price>h&&(N.included_units===null||N.included_units>k))??null},[u,p,l]),g=ir(async()=>{if(!f)return;if(f.selectable){await r.select(f.id);return}let h=await r.checkout(f.id);window.location.assign(h)},[f,r]),m=a.open,b=ir(()=>{u&&m(u)},[m,u]);return lr(()=>{if(!u)return null;let h=l?ve({unit:l.unit,reward:l.connected_reward,includedUnits:l.connected_included_units,creditMicros:l.connected_credit*1e6}):null,k=l&&Ce(l.connected_reward)?h:null;return{reason:u,...bs(u,{connectOffer:k,connected:s.connected,online:s.online,machine:ln(s.machines)?.label??null,unit:l?.unit??"message",interval:l?.interval??"month",upgrade:f!==null,resets:r.current?.period_end??null}),connectOffer:k,upgradeTo:f,connect:b,upgrade:g}},[u,l,s,f,b,g,r.current?.period_end])}function hs(e){let n=Be(e);return n==="payment_required"||n==="no_compute"?n:null}function fs(e,n){return e==="no_compute"&&n.connected&&n.online?null:e}function gs(e,n){let t=e.plan;return!t||n.loading?null:ie(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 ${ur(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 ${ur(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 ur(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as Et,jsx as _,jsxs as fe}from"react/jsx-runtime";function ws(e){let{at:n=.25,className:t,error:r,fallback:s=null}=e,a=e.predict??!("error"in e),{plan:i,compute:u,connect:l}=D(),{theme:p}=I(),[f,g]=_t(null),m=ys(),b=ct(l.publishableKey),[h,k]=_t(!1);pr(()=>{k(ut(b))},[b]);let N=_(Et,{children:s}),x=i.plan;if(!x||i.loading||u.loading)return N;let U=e.allow!==void 0?e.allow:x.route_allow;if(u.connected)return u.online?N:_(dr,{className:t,theme:p,stalled:!0,children:_(vs,{machine:ln(u.machines)?.label??null,ownCompute:ie(U),onConnectAnother:()=>l.open("no_compute")})});let j=(()=>{let M=Be(r);return M==="payment_required"||M==="no_compute"})(),S=x.ask_to_connect!==!1&&wt(x.route_prefer,U);if(!a&&!j&&!S)return N;let O=ie(U)?Ns(x.unit,ie(x.route_allow)):Ce(x.connected_reward)?xs(i,x,n):S?ks(x.unit):null;if(!O||O.dismissible&&h)return N;let H=!O.dismissible&&(!a||O.meter!==null&&O.meter.left===0),T=f??H;return fe(dr,{className:t,theme:p,children:[fe("div",{className:"sc-nudge-top",children:[fe("div",{className:"sc-nudge-say",children:[_("p",{className:"sc-nudge-title",children:O.title}),_("p",{className:"sc-nudge-detail",children:O.detail}),fe("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more","aria-expanded":T,"aria-controls":m,onClick:()=>g(!T),children:[T?"Hide the details":"How it works",_(Ps,{})]})]}),O.dismissible?_("button",{type:"button",className:"sc-nudge-dismiss","aria-label":"Dismiss",title:"Dismiss",onClick:()=>{k(!0),dt(b)},children:_(Ss,{})}):null]}),T?_("ol",{className:"sc-nudge-steps",id:m,children:Cs(l.app?.name,hn(l.connectUrl)).map(M=>fe("li",{children:[M.opens?_("button",{type:"button",className:"sc-step-lead",onClick:()=>l.open("manual"),children:M.lead}):_("strong",{children:M.lead}),M.detail?_("span",{children:M.detail}):null,M.links.length>0?fe("span",{className:"sc-step-links",children:[M.linksLead,M.links.map(q=>_("a",{href:q.href,target:"_blank",rel:"noreferrer noopener",children:q.label},q.href))]}):null]},M.lead))}):null,_(qe,{variant:"primary"})]})}function dr({className:e,theme:n,stalled:t,children:r}){return _("div",{className:e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill","data-theme":n,children:_("div",{className:t?"sc-nudge sc-nudge-stalled":"sc-nudge",children:r})})}function vs({machine:e,ownCompute:n,onConnectAnother:t}){let r=$n(),{compute:s}=D(),[a,i]=_t(!1),{refresh:u}=s;return pr(()=>{if(r.launch===null||r.launch==="absent")return;i(!1);let l=setInterval(()=>void u(),3e3),p=setTimeout(()=>{clearInterval(l),i(!0)},2e4);return()=>{clearInterval(l),clearTimeout(p)}},[r.launch,u]),fe(Et,{children:[_("div",{className:"sc-nudge-top",children:fe("div",{className:"sc-nudge-say",children:[fe("p",{className:"sc-nudge-title",children:[e??"Your machine"," can\u2019t be reached"]}),_("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&&_("p",{className:"sc-nudge-note",children:r.note}),a&&_("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)&&_("button",{type:"button",className:"sc-btn sc-btn-quiet sc-nudge-more",onClick:t,children:a?"Connect it again":"Connect another machine"})]})}),_("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:r.open,children:"Open Soba App"})]})}function Cs(e,n){return[{lead:"Download Soba App",detail:"",linksLead:n?"Get it for":void 0,links:n?mn.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:te.map(t=>({label:t.short,href:t.install}))}]}function Ns(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 ks(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 xs(e,n,t){let{remaining:r,included:s}=e;if(r===null||s===null||s===0||r>Math.ceil(s*t))return null;let a=ve({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:fe(Et,{children:[a,"."]}),meter:{left:r,of:s}}:null}function Ss(){return _("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-x",children:_("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 Ps(){return _("svg",{viewBox:"0 0 16 16","aria-hidden":"true",focusable:"false",className:"sc-nudge-chev",children:_("path",{d:"M4.5 6.5 8 10l3.5-3.5",fill:"none",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})})}var _s=new Set(["delta","thinking","status","done","error"]);function Dn(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 s=r;if(typeof s.type!="string"||!_s.has(s.type))return null;let a={type:s.type};return typeof s.text=="string"&&(a.text=s.text),typeof s.message=="string"&&(a.message=s.message),typeof s.tool=="string"&&(a.tool=s.tool),typeof s.tier=="string"&&(a.tier=s.tier),s.usage&&typeof s.usage=="object"&&(a.usage=s.usage),a}async function*Mt(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(),s=new TextDecoder,a="",i=[];try{for(;;){let l=await r.read();if(l.done)break;for(a+=s.decode(l.value,{stream:!0});;){let p=a.indexOf(`
3
+ `);if(p===-1)break;let f=hr(a.slice(0,p));if(a=a.slice(p+1),t){let g=f.trim()?Dn(f):null;g&&(yield g);continue}if(f===""){let g=i.join(`
4
+ `);if(i=[],g==="[DONE]")return;let m=g?Dn(g):null;m&&(yield m);continue}mr(f,i)}}!t&&a&&mr(hr(a),i);let u=t?a.trim():i.join(`
5
+ `);if(u&&u!=="[DONE]"){let l=Dn(u);l&&(yield l)}}finally{r.cancel().catch(()=>{})}}function mr(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 hr(e){return e.endsWith("\r")?e.slice(0,-1):e}async function Es(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 Ms}from"react";var fr="data-soba-react",gr=!1;function kn(){if(gr||typeof document>"u"||(gr=!0,document.querySelector(`style[${fr}]`)))return;let e=document.createElement("style");e.setAttribute(fr,""),e.textContent=`.soba-connect {
6
6
  --sc-ground: #ffffff;
7
7
  --sc-sheet: #ffffff;
8
8
  --sc-raised: #f6f6f7;
@@ -1204,7 +1204,8 @@ a.sc-btn {
1204
1204
  }
1205
1205
 
1206
1206
  .sc-result-ok {
1207
- color: var(--sc-ok, #22a06b);
1207
+
1208
+ color: var(--sc-text, #1a1a1c);
1208
1209
  }
1209
1210
 
1210
1211
  .sc-result-off {
@@ -1542,6 +1543,36 @@ a.sc-btn {
1542
1543
  min-width: 0;
1543
1544
  }
1544
1545
 
1546
+ .sc-nudge {
1547
+ position: relative;
1548
+ }
1549
+ .sc-nudge-dismiss {
1550
+ position: absolute;
1551
+ top: 7px;
1552
+ right: 8px;
1553
+ display: grid;
1554
+ place-items: center;
1555
+ width: 28px;
1556
+ height: 28px;
1557
+ padding: 0;
1558
+ border: 0;
1559
+ border-radius: 999px;
1560
+ background: none;
1561
+ color: var(--sc-muted, #6b6b73);
1562
+ cursor: pointer;
1563
+ transition:
1564
+ background-color 0.12s,
1565
+ color 0.12s;
1566
+ }
1567
+ .sc-nudge-dismiss:hover {
1568
+ background: var(--sc-raised, #f6f6f7);
1569
+ color: var(--sc-text, #1a1a1c);
1570
+ }
1571
+ .sc-nudge-x {
1572
+ width: 14px;
1573
+ height: 14px;
1574
+ }
1575
+
1545
1576
  .sc-nudge > .sc-btn {
1546
1577
  grid-column: 2;
1547
1578
  align-self: end;
@@ -2281,6 +2312,18 @@ li.sc-plan-row.sc-plan-current {
2281
2312
  color: var(--sc-muted, #6b6b73);
2282
2313
  }
2283
2314
 
2315
+ .sc-run-error {
2316
+ border-color: color-mix(in srgb, var(--sc-warn, #b06f14) 28%, var(--sc-line, #e9e9eb));
2317
+ }
2318
+ .sc-run-error-mark {
2319
+ background: color-mix(in srgb, var(--sc-warn, #b06f14) 12%, var(--sc-raised, #f6f6f7));
2320
+ color: var(--sc-warn, #b06f14);
2321
+ }
2322
+
2323
+ .sc-run-error-message {
2324
+ overflow-wrap: anywhere;
2325
+ }
2326
+
2284
2327
  .sc-modal-sheet .sc-limit-head {
2285
2328
  flex-direction: column;
2286
2329
  align-items: center;
@@ -2397,4 +2440,303 @@ li.sc-plan-row.sc-plan-current {
2397
2440
  .sc-opt-has-warn {
2398
2441
  color: var(--sc-warn, #b06f14);
2399
2442
  }
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};
2443
+
2444
+ .bx * {
2445
+ transform-box: view-box;
2446
+ }
2447
+
2448
+ .bx-arc,
2449
+ .bx-st,
2450
+ .bx-z1 path,
2451
+ .bx-z2 path,
2452
+ .bx-ob path {
2453
+ stroke-width: var(--bx-w, 17);
2454
+ }
2455
+
2456
+ .bx[data-expression="thinking"] .bx-arc,
2457
+ .bx[data-expression="paused"] .bx-arc,
2458
+ .bx[data-expression="attention"] .bx-arc,
2459
+ .bx[data-expression="connecting"] .bx-arc,
2460
+ .bx[data-expression="gone"] .bx-arc,
2461
+ .bx[data-expression="snap"] .bx-arc,
2462
+ .bx[data-expression="listening"] .bx-arc,
2463
+ .bx[data-expression="permission"] .bx-arc,
2464
+ .bx[data-expression="ai"] .bx-arc {
2465
+ display: none;
2466
+ }
2467
+
2468
+ @keyframes bx-stream {
2469
+ to {
2470
+ stroke-dashoffset: -62;
2471
+ }
2472
+ }
2473
+
2474
+ .bx-st {
2475
+ animation: bx-stream 0.9s linear infinite;
2476
+ }
2477
+
2478
+ @keyframes bx-think {
2479
+ 0%,
2480
+ 100% {
2481
+ opacity: 0.26;
2482
+ }
2483
+ 33% {
2484
+ opacity: 1;
2485
+ }
2486
+ }
2487
+
2488
+ .bx-th {
2489
+ opacity: 0.26;
2490
+ animation: bx-think 1.2s ease-in-out infinite;
2491
+ }
2492
+
2493
+ .bx-th2 {
2494
+ animation-delay: 0.4s;
2495
+ }
2496
+
2497
+ .bx-th3 {
2498
+ animation-delay: 0.8s;
2499
+ }
2500
+
2501
+ @keyframes bx-att {
2502
+ 0%,
2503
+ 80%,
2504
+ 100% {
2505
+ transform: rotate(0);
2506
+ }
2507
+ 85% {
2508
+ transform: rotate(-8deg);
2509
+ }
2510
+ 95% {
2511
+ transform: rotate(8deg);
2512
+ }
2513
+ }
2514
+
2515
+ .bx-at {
2516
+
2517
+ transform-box: fill-box;
2518
+ transform-origin: 50% 100%;
2519
+ animation: bx-att 2s ease-in-out infinite;
2520
+ }
2521
+
2522
+ @keyframes bx-z {
2523
+ 0% {
2524
+ opacity: 0;
2525
+ transform: translate(0, 12px);
2526
+ }
2527
+ 25%,
2528
+ 70% {
2529
+ opacity: 1;
2530
+ transform: translate(0, 0);
2531
+ }
2532
+ 100% {
2533
+ opacity: 0;
2534
+ transform: translate(8px, -16px);
2535
+ }
2536
+ }
2537
+
2538
+ .bx-z1 {
2539
+ animation: bx-z 3s ease-in-out infinite;
2540
+ }
2541
+
2542
+ .bx-z2 {
2543
+ animation: bx-z 3s ease-in-out 0.75s infinite;
2544
+ }
2545
+
2546
+ @keyframes bx-orb {
2547
+ to {
2548
+ transform: rotate(360deg);
2549
+ }
2550
+ }
2551
+
2552
+ .bx-ob {
2553
+ transform-origin: 278px 400px;
2554
+ animation: bx-orb 1.15s cubic-bezier(0.45, 0, 0.55, 1) infinite;
2555
+ }
2556
+
2557
+ @keyframes bx-xa {
2558
+ 0% {
2559
+ opacity: 0;
2560
+ transform: translateX(0);
2561
+ }
2562
+ 8%,
2563
+ 22% {
2564
+ opacity: 1;
2565
+ transform: translateX(0);
2566
+ }
2567
+ 45%,
2568
+ 100% {
2569
+ opacity: 0;
2570
+ transform: translateX(40px);
2571
+ }
2572
+ }
2573
+
2574
+ .bx-xa {
2575
+ opacity: 0;
2576
+ animation: bx-xa 3.2s cubic-bezier(0.45, 0, 0.55, 1) infinite;
2577
+ }
2578
+
2579
+ @keyframes bx-xx {
2580
+ 0%,
2581
+ 40% {
2582
+ opacity: 0;
2583
+ transform: scale(0.4);
2584
+ }
2585
+ 54% {
2586
+ opacity: 1;
2587
+ transform: scale(1.08);
2588
+ }
2589
+ 60%,
2590
+ 90% {
2591
+ opacity: 1;
2592
+ transform: scale(1);
2593
+ }
2594
+ 100% {
2595
+ opacity: 0;
2596
+ transform: scale(1);
2597
+ }
2598
+ }
2599
+
2600
+ .bx-xx {
2601
+ transform-box: fill-box;
2602
+ transform-origin: center;
2603
+ animation: bx-xx 3.2s ease-out infinite;
2604
+ }
2605
+
2606
+ @keyframes bx-voice {
2607
+ 0%,
2608
+ 100% {
2609
+ transform: scaleY(0.45);
2610
+ }
2611
+ 50% {
2612
+ transform: scaleY(1);
2613
+ }
2614
+ }
2615
+
2616
+ .bx-vb {
2617
+ transform-box: fill-box;
2618
+ transform-origin: center;
2619
+ animation: bx-voice 0.9s ease-in-out infinite;
2620
+ }
2621
+
2622
+ .bx-vb2 {
2623
+ animation-delay: 0.15s;
2624
+ }
2625
+
2626
+ .bx-vb3 {
2627
+ animation-delay: 0.3s;
2628
+ }
2629
+
2630
+ @keyframes bx-wait {
2631
+ 0% {
2632
+ opacity: 1;
2633
+ }
2634
+ 100% {
2635
+ opacity: 0.15;
2636
+ }
2637
+ }
2638
+
2639
+ .bx-w {
2640
+ opacity: 0.15;
2641
+ animation: bx-wait 1.2s linear infinite;
2642
+ }
2643
+
2644
+ @keyframes bx-spark {
2645
+ 0%,
2646
+ 100% {
2647
+ transform: scale(1) rotate(0);
2648
+ }
2649
+ 50% {
2650
+ transform: scale(0.7) rotate(22deg);
2651
+ }
2652
+ }
2653
+
2654
+ .bx-sp {
2655
+ transform-box: fill-box;
2656
+ transform-origin: center;
2657
+ animation: bx-spark 2.6s ease-in-out infinite;
2658
+ }
2659
+
2660
+ .bx-sp2 {
2661
+ animation-delay: -0.87s;
2662
+ }
2663
+
2664
+ .bx-sp3 {
2665
+ animation-delay: -1.73s;
2666
+ }
2667
+
2668
+ @keyframes bx-snap {
2669
+ 0%,
2670
+ 6% {
2671
+ transform: translateX(90px);
2672
+ opacity: 0;
2673
+ }
2674
+ 24% {
2675
+ transform: translateX(-10px);
2676
+ opacity: 1;
2677
+ }
2678
+ 30% {
2679
+ transform: translateX(4px);
2680
+ }
2681
+ 35%,
2682
+ 100% {
2683
+ transform: translateX(0);
2684
+ opacity: 1;
2685
+ }
2686
+ }
2687
+
2688
+ .bx-snap {
2689
+ animation: bx-snap 3.6s cubic-bezier(0.3, 0, 0.2, 1) infinite;
2690
+ }
2691
+
2692
+ @media (prefers-reduced-motion: reduce) {
2693
+ .bx .bx-st,
2694
+ .bx .bx-th,
2695
+ .bx .bx-at,
2696
+ .bx .bx-z1,
2697
+ .bx .bx-z2,
2698
+ .bx .bx-ob,
2699
+ .bx .bx-xa,
2700
+ .bx .bx-xx,
2701
+ .bx .bx-snap,
2702
+ .bx .bx-vb,
2703
+ .bx .bx-w,
2704
+ .bx .bx-sp {
2705
+ animation: none;
2706
+ }
2707
+
2708
+
2709
+ .bx .bx-th,
2710
+ .bx .bx-z1,
2711
+ .bx .bx-z2,
2712
+ .bx .bx-xx,
2713
+ .bx .bx-snap,
2714
+ .bx .bx-w {
2715
+ opacity: 1;
2716
+ transform: none;
2717
+ }
2718
+ }
2719
+
2720
+ [data-version="v1"] .bx .bx-arc {
2721
+ display: revert;
2722
+ }
2723
+
2724
+ [data-version="v1"] .bx .bx-st,
2725
+ [data-version="v1"] .bx .bx-th,
2726
+ [data-version="v1"] .bx .bx-at,
2727
+ [data-version="v1"] .bx .bx-z1,
2728
+ [data-version="v1"] .bx .bx-z2,
2729
+ [data-version="v1"] .bx .bx-ob,
2730
+ [data-version="v1"] .bx .bx-xa,
2731
+ [data-version="v1"] .bx .bx-xx,
2732
+ [data-version="v1"] .bx .bx-snap,
2733
+ [data-version="v1"] .bx .bx-vb,
2734
+ [data-version="v1"] .bx .bx-w,
2735
+ [data-version="v1"] .bx .bx-sp {
2736
+ display: none;
2737
+ }
2738
+
2739
+ [data-version="v1"] .sc-result-ok {
2740
+ color: var(--sc-ok, #22a06b);
2741
+ }
2742
+ `,document.head.appendChild(e)}import{jsx as ge,jsxs as xn}from"react/jsx-runtime";function br(e){if(!e)return null;let n=Be(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 Rs(){return xn("svg",{viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:[ge("path",{d:"M8 5v4",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"}),ge("circle",{cx:"8",cy:"11.6",r:"0.9",fill:"currentColor"}),ge("circle",{cx:"8",cy:"8",r:"6.4",stroke:"currentColor",strokeWidth:"1.3"})]})}function Ls({error:e,onRetry:n,onDismiss:t,title:r,className:s}){let a=br(e),i=I();return Ms(()=>kn(),[]),a?ge("div",{className:s?`soba-connect ${s}`:"soba-connect","data-theme":i.theme,role:"alert",children:xn("div",{className:"sc-card sc-limit sc-run-error",children:[xn("div",{className:"sc-limit-head",children:[ge("span",{className:"sc-limit-mark sc-run-error-mark","aria-hidden":"true",children:ge(Rs,{})}),xn("div",{children:[ge("h2",{className:"sc-limit-title",children:r??"That run did not finish"}),ge("p",{className:"sc-limit-body sc-run-error-message",children:a})]})]}),(t||n)&&xn("div",{className:"sc-limit-actions",children:[t&&ge("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,children:"Dismiss"}),n&&ge("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:n,children:"Try again"})]})]})}):null}import{useId as Os,useState as yr}from"react";import{jsx as z,jsxs as Un}from"react/jsx-runtime";function Ts({reason:e}){return z("span",{className:"sc-limit-mark","aria-hidden":"true",children:e==="no_compute"?z(Ze,{}):z(V,{})})}function Is(e){let{error:n,variant:t="card",onDismiss:r,className:s}=e,a=Pt(n,{predict:e.predict??!("error"in e)}),i=Os(),u=I();if(!a)return null;let l=z(As,{offer:a,headingId:i,onDismiss:r});return t==="dialog"?z(wn,{open:!0,onClose:()=>r?.(),labelledBy:i,theme:u.theme,children:l}):z("div",{className:s?`soba-connect ${s}`:"soba-connect","data-theme":u.theme,children:l})}function As({offer:e,headingId:n,onDismiss:t}){let{compute:r}=D(),[s,a]=yr(!1),[i,u]=yr(null),l=e.reason==="no_compute"&&r.connected&&!r.online,p=l||e.connectOffer!==null||!r.connected,f=$n();async function g(){a(!0),u(null);try{await e.upgrade()}catch(m){u(m.message)}finally{a(!1)}}return Un("div",{className:"sc-card sc-limit",children:[Un("div",{className:"sc-limit-head",children:[z(Ts,{reason:e.reason}),Un("div",{children:[z("h2",{className:"sc-limit-title",id:n,children:e.title}),z("p",{className:"sc-limit-body",children:e.body})]})]}),i&&z("p",{className:"sc-error",children:i}),l&&f.note&&z("p",{className:"sc-limit-note",children:f.note}),Un("div",{className:"sc-limit-actions",children:[t&&z("button",{type:"button",className:"sc-btn sc-btn-quiet",onClick:t,disabled:s,children:"Not now"}),e.upgradeTo&&z("button",{type:"button",className:p?"sc-btn":"sc-btn sc-btn-primary",onClick:()=>void g(),disabled:s,children:s?"Opening\u2026":e.upgradeTo.selectable?`Switch to ${e.upgradeTo.name}`:`${e.upgradeTo.name} for $${e.upgradeTo.price.toLocaleString()}/${e.upgradeTo.interval}`}),p&&z("button",{type:"button",className:l?"sc-btn":"sc-btn sc-btn-primary",onClick:e.connect,disabled:s,children:l?"Connect another machine":"Connect compute"}),l&&z("button",{type:"button",className:"sc-btn sc-btn-primary",onClick:f.open,disabled:s,children:"Open Soba App"})]})]})}import{useMemo as $s}from"react";function Sn(){let{plan:e,compute:n,connect:t}=D();return $s(()=>{let r=e.plan,s=e.current,a={plan:r,assignment:s,loading:e.loading,error:e.error,periodEnd:s?.period_end?new Date(s.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 i=Hs(s?.trial_ends_at??null),u=r.connected_reward==="included"&&n.connected&&r.connected_included_units!==null,l=u?r.connected_included_units:r.included_units,p=r.connected_reward==="unlimited"&&n.connected,f=l===null,g=e.used??0,m=l===null?null:Math.max(0,l-g),b=l&&l>0?Math.min(100,Math.round(g/l*100)):null,h=l!==null&&g>=l,k=i!==null?"trial":f?"unlimited":h?r.overage==="meter"?"metered":"spent":"within";return{...a,state:k,trialDaysLeft:i,ceiling:l,raised:u,uncounted:p,used:g,remaining:m,percent:b,unlimited:f,reward:Ds(r,u||p,n.connected,()=>t.open("manual")),summary:Us({plan:r,assignment:s,used:g,ceiling:l,trialDaysLeft:i,raised:u,uncounted:p,state:k})}},[e,n.connected,t])}function Ds(e,n,t,r){let s=ve({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6});return s?{line:s,inForce:n,required:!1,connected:t,actionable:Ce(e.connected_reward)&&!t,open:r}:ie(e.route_allow)&&!t?{line:"Nothing connected yet, so nothing can run.",inForce:!1,required:!0,connected:t,actionable:!0,open:r}:null}function Us(e){let{plan:n,assignment:t,used:r,ceiling:s,trialDaysLeft:a,raised:i,uncounted:u,state:l}=e,p=`${n.unit}${r===1?"":"s"}`,f=u?" Runs your own AI serves do not count toward it.":"";if(l==="trial"&&a!==null){let b=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 ${b}.`}if(l==="unlimited")return`${r.toLocaleString()} ${p} this period. No ceiling on this plan.`;if(l==="metered"){let b=r-(s??0);return n.overage_per_unit>0?`${b.toLocaleString()} past the allowance, billed at $${n.overage_per_unit} a ${n.unit}.${f}`:`${b.toLocaleString()} past the allowance.${f}`}if(l==="spent")return t?.period_end?`Allowance spent. It comes back on ${wr(t.period_end)}.${f}`:`Allowance spent. It comes back at the start of the next period.${f}`;let g=Math.max(0,(s??0)-r),m=i?` Raised from ${(n.included_units??0).toLocaleString()} while your own AI is connected.`:t?.period_end?` Resets ${wr(t.period_end)}.`:"";return`${g.toLocaleString()} of ${(s??0).toLocaleString()} ${n.unit}s left.${m}${f}`}function Hs(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 wr(e){let n=new Date(e);return Number.isNaN(n.getTime())?e:n.toLocaleDateString(void 0,{day:"numeric",month:"long"})}import{Fragment as Bs,jsx as K,jsxs as le}from"react/jsx-runtime";function Rt({heading:e="Current plan",showUsage:n=!0,showName:t=!0,className:r}){let s=Sn(),{theme:a}=I(),i=m=>K("section",{className:r?`soba-connect sc-fill ${r}`:"soba-connect sc-fill","data-theme":a,children:le("div",{className:"sc-card sc-current",children:[e&&K("h2",{className:"sc-section-title",children:e}),m]})});if(s.error)return i(K("p",{className:"sc-error",children:s.error.message}));if(s.loading)return i(K("p",{className:"sc-note",children:"Loading\u2026"}));if(!s.plan)return i(le("div",{className:"sc-current-main",children:[K("p",{className:"sc-current-name",children:"No plan"}),K("p",{className:"sc-sub",children:s.summary})]}));let{plan:u,trialDaysLeft:l,percent:p,unlimited:f,reward:g}=s;return i(le(Bs,{children:[le("div",{className:"sc-current-grid",children:[(t||l!==null)&&le("div",{className:"sc-current-main",children:[t?le("p",{className:"sc-current-name",children:[u.name,l!==null&&le("span",{className:"sc-trial-badge",children:[l," ",l===1?"day":"days"," left"]})]}):l!==null&&K("p",{className:"sc-current-trial",children:le("span",{className:"sc-trial-badge",children:[l," ",l===1?"day":"days"," left"]})}),t&&u.description&&K("p",{className:"sc-sub",children:u.description})]}),n&&le("div",{className:"sc-usage",children:[le("div",{className:"sc-row-between",children:[K("span",{className:"sc-fact-key",children:"Usage"}),K("span",{className:p!==null&&p>=100?"sc-usage-figure sc-usage-over":"sc-usage-figure",children:f?"Unlimited":p===null?"Metered":`${p}% used`})]}),p!==null&&K("div",{className:"sc-meter",role:"presentation",children:p>0&&K("span",{className:p>=100?"sc-meter-fill sc-meter-full":"sc-meter-fill",style:{width:`${p}%`}})}),K("p",{className:"sc-usage-line",children:s.summary})]})]}),g&&le("div",{className:"sc-current-foot",children:[K("p",{className:g.required?"sc-plan-reward-line sc-plan-reward-need":g.inForce?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-open",children:g.required?g.line:g.inForce?`In force: ${qs(g.line)}.`:g.line}),(g.actionable||g.connected)&&K(qe,{})]})]}))}var qs=e=>e.charAt(0).toLowerCase()+e.slice(1);import{useCallback as Fs,useMemo as Ws,useState as vr}from"react";var Gs={"user-hardware":"your own machine","user-subscription":"your own AI subscription","open-weights":"open models we host",frontier:"frontier models"},Vs=new Set(["user-hardware","user-subscription"]);function Lt(e={}){let{plan:n,compute:t,connect:r}=D(),[s,a]=vr(null),[i,u]=vr(null),{featured:l,onSelect:p,successUrl:f,cancelUrl:g}=e,m=Fs(async h=>{a(h.id),u(null);try{if(h.selectable)await n.select(h.id);else if(p)p(h);else{let k=await n.checkout(h.id,{...f?{successUrl:f}:{},...g?{cancelUrl:g}:{}});window.location.assign(k);return}}catch(k){throw u(k.message),k}finally{(h.selectable||p)&&a(null)}},[n,p,f,g]),b=Ws(()=>n.plans.map(h=>{let k=n.current?.plan_id===h.id;return{plan:h,current:k,featured:l===h.id&&!k,price:zs(h),allowance:h.included_units===null?`Unlimited ${h.unit}s`:`${h.included_units.toLocaleString()} ${h.unit}${h.included_units===1?"":"s"}`,allowanceNote:Ks(h),computeLabel:h.route_allow===null?"any compute":h.route_allow.length===0?"no compute":null,compute:(h.route_allow??[]).map(N=>({costClass:N,label:Gs[N]??N,owned:Vs.has(N),runtimes:Qn(N).map(x=>x.id)})),connect:js(h,k,t.connected,()=>r.open("manual")),cta:{label:Ys(h,k,s===h.id),disabled:k||s!==null,busy:s===h.id,take:()=>m(h)}}}),[n.plans,n.current,l,t.connected,r,s,m]);return{offers:b,current:b.find(h=>h.current)??null,loading:n.loading,error:n.error,failed:i}}function zs(e){return e.price===0?{amount:"Free",interval:null,free:!0}:{amount:`$${e.price.toLocaleString()}`,interval:e.interval,free:!1}}function Ks(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 js(e,n,t,r){let s=ve({unit:e.unit,reward:e.connected_reward,includedUnits:e.connected_included_units,creditMicros:e.connected_credit*1e6}),a=ie(e.route_allow)&&!t;if(!s&&!a)return null;let i=Ce(e.connected_reward);return{key:s?"Connect your own":"To use this",line:s??(n?"Nothing connected yet, so nothing can run.":"Runs only on compute you connect."),reward:s!==null,actionable:n&&(i||a)&&!t,open:r}}function Ys(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 d,jsxs as E}from"react/jsx-runtime";function Hn(e){return e?`soba-connect sc-fill ${e}`:"soba-connect sc-fill"}function Ot({onSelect:e,successUrl:n,cancelUrl:t,showCompute:r=!0,showConnect:s=!1,variant:a="cards",featured:i,className:u}){let{offers:l,loading:p,error:f,failed:g}=Lt({...i?{featured:i}:{},...e?{onSelect:e}:{},...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}}),{theme:m}=I();if(f)return d("div",{className:Hn(u),"data-theme":m,children:d("div",{className:"sc-card",children:d("p",{className:"sc-error",children:f.message})})});if(p)return d("div",{className:Hn(u),"data-theme":m,children:d("div",{className:"sc-card",children:d("p",{className:"sc-note",children:"Loading plans\u2026"})})});if(l.length===0)return d("div",{className:Hn(u),"data-theme":m,children:d("div",{className:"sc-card",children:d("p",{className:"sc-note",children:"This app has no plans yet."})})});let b={showCompute:r,showConnect:s};return E("div",{className:Hn(u),"data-theme":m,"data-variant":a,children:[a==="rows"?d(Zs,{offers:l,shelf:b}):a==="table"?d(Js,{offers:l,shelf:b}):d(Qs,{offers:l,shelf:b}),g&&d("p",{className:"sc-error",children:g})]})}function Qs({offers:e,shelf:n}){return d("div",{className:"sc-plans",children:e.map(t=>E("div",{className:Cr("sc-plan",t),children:[E("div",{className:"sc-row-between",children:[d("span",{className:"sc-title",children:t.plan.name}),d(Tt,{offer:t})]}),d("p",{className:"sc-sub",children:t.plan.description}),d(It,{price:t.price,free:"forever"}),d(Dt,{offer:t,shelf:n}),d(Nr,{offer:t}),d("div",{className:"sc-plan-band",children:n.showCompute&&d($t,{offer:t})}),d("div",{className:"sc-plan-band",children:d(At,{offer:t})})]},t.plan.id))})}function Zs({offers:e,shelf:n}){return d("ul",{className:"sc-plan-rows",children:e.map(t=>E("li",{className:Cr("sc-plan-row",t),children:[E("div",{className:"sc-row-main",children:[E("span",{className:"sc-row-name",children:[d("span",{className:"sc-title",children:t.plan.name}),d(Tt,{offer:t})]}),t.plan.description&&d("p",{className:"sc-sub",children:t.plan.description}),d(Nr,{offer:t}),n.showCompute&&d($t,{offer:t,inline:!0}),d(At,{offer:t,inline:!0})]}),E("div",{className:"sc-row-side",children:[d(It,{price:t.price,free:"forever",small:!0}),d(Dt,{offer:t,shelf:n})]})]},t.plan.id))})}function Js({offers:e,shelf:n}){let t=e.some(i=>i.plan.overage_per_unit>0),r=e.some(i=>i.plan.trial_days>0),s=e.some(i=>i.connect!==null),a=i=>[i.current?"sc-col-current":"",i.featured?"sc-col-featured":""].filter(Boolean).join(" ")||void 0;return d("div",{className:"sc-table-scroll",children:E("table",{className:"sc-plan-table",children:[d("thead",{children:E("tr",{children:[d("td",{}),e.map(i=>E("th",{scope:"col",className:a(i),children:[E("span",{className:"sc-row-name",children:[d("span",{className:"sc-title",children:i.plan.name}),d(Tt,{offer:i})]}),d(It,{price:i.price,small:!0})]},i.plan.id))]})}),E("tbody",{children:[E("tr",{children:[d("th",{scope:"row",children:"Included"}),e.map(i=>d("td",{className:a(i),children:i.allowance},i.plan.id))]}),t&&E("tr",{children:[d("th",{scope:"row",children:"Then"}),e.map(i=>d("td",{className:a(i),children:i.plan.overage_per_unit>0?`$${i.plan.overage_per_unit} / ${i.plan.unit}`:d("span",{className:"sc-muted-cell",children:"Stops"})},i.plan.id))]}),r&&E("tr",{children:[d("th",{scope:"row",children:"Trial"}),e.map(i=>d("td",{className:a(i),children:i.plan.trial_days>0?`${i.plan.trial_days} days`:d("span",{className:"sc-muted-cell",children:"None"})},i.plan.id))]}),n.showCompute&&E("tr",{children:[d("th",{scope:"row",children:"Runs on"}),e.map(i=>d("td",{className:a(i),children:d($t,{offer:i,bare:!0})},i.plan.id))]}),s&&E("tr",{children:[d("th",{scope:"row",children:"Connect your own"}),e.map(i=>d("td",{className:a(i),children:d(At,{offer:i,bare:!0})},i.plan.id))]}),E("tr",{className:"sc-table-buy",children:[d("td",{}),e.map(i=>d("td",{className:a(i),children:d(Dt,{offer:i,shelf:n})},i.plan.id))]})]})]})})}function Cr(e,n){return[e,n.current?"sc-plan-current":"",n.featured?"sc-plan-featured":""].filter(Boolean).join(" ")}function Tt({offer:e}){return e.current?d("span",{className:"sc-plan-badge",children:"Current"}):e.featured?d("span",{className:"sc-plan-badge-soft",children:"Recommended"}):null}function It({price:e,small:n,free:t}){return E("p",{className:n?"sc-plan-price sc-plan-price-sm":"sc-plan-price",children:[d("span",{className:"sc-plan-amount",children:e.amount}),e.interval?E("span",{className:"sc-plan-interval",children:["/",e.interval]}):t&&d("span",{className:"sc-plan-interval sc-plan-after",children:t})]})}function Nr({offer:e}){return E("p",{className:"sc-plan-allowance",children:[d("span",{className:"sc-plan-figure",children:e.allowance}),d("span",{className:"sc-plan-qualifier",children:e.allowanceNote})]})}function At({offer:e,inline:n,bare:t}){let r=e.connect;if(!r)return t?d("span",{className:"sc-muted-cell",children:"None"}):null;let s=r.reward?"sc-plan-reward-line":"sc-plan-reward-line sc-plan-reward-need",a=r.actionable?E("button",{type:"button",className:`${s} sc-plan-reward-act`,"aria-label":"Connect compute",onClick:r.open,children:[d("span",{className:"sc-reward-said",children:r.line}),E("span",{className:"sc-reward-do","aria-hidden":!0,children:[d(V,{className:"sc-reward-mark"}),"Connect compute"]})]}):d("p",{className:s,children:r.line});return t?a:d("div",{className:n?"sc-plan-reward sc-plan-reward-inline":"sc-plan-reward",children:a})}function $t({offer:e,inline:n,bare:t}){let r=e.computeLabel?d("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:d("li",{children:e.computeLabel})}):d("ul",{className:n?"sc-compute sc-compute-inline":"sc-compute",children:e.compute.map(s=>E("li",{className:s.owned?"sc-compute-own":void 0,children:[s.label,d(Xs,{runtimes:s.runtimes})]},s.costClass))});return t?r:E("div",{className:n?"sc-plan-compute sc-plan-compute-inline":"sc-plan-compute",children:[d("span",{className:"sc-fact-key",children:"Runs on"}),r]})}function Dt({offer:e,shelf:n}){let t=e.connect;return n.showConnect&&t?.actionable?E("button",{type:"button",className:"sc-btn sc-btn-primary sc-btn-icon",onClick:t.open,children:[d(V,{className:"sc-btn-mark"}),"Connect compute"]}):d("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 Xs({runtimes:e}){return e.length===0?null:d("span",{className:"sc-compute-marks",children:e.map(n=>{let t=he[n];return t?d(t,{className:"sc-rt-mark"},n):null})})}import{jsx as Ut,jsxs as kr}from"react/jsx-runtime";function eo({heading:e,plansHeading:n,showUsage:t=!0,showName:r=!0,className:s,...a}){let{plan:i,loading:u}=Sn(),{theme:l}=I(),p=n??(u?"Plans":i?"Change plan":"Choose a plan");return kr("div",{className:s?`soba-connect sc-fill sc-billing ${s}`:"soba-connect sc-fill sc-billing","data-theme":l,children:[Ut(Rt,{...e===void 0?{}:{heading:e},showUsage:t,showName:r}),kr("section",{className:"sc-billing-plans",children:[p&&Ut("h2",{className:"sc-section-title",children:p}),Ut(Ot,{...a})]})]})}import{useState as xr}from"react";import{jsx as Sr,jsxs as to}from"react/jsx-runtime";function no({plan:e,successUrl:n,cancelUrl:t,label:r,className:s}){let{plan:a}=D(),{theme:i}=I(),[u,l]=xr(!1),[p,f]=xr(null);async function g(){l(!0),f(null);try{let m=await a.checkout(e.id,{...n?{successUrl:n}:{},...t?{cancelUrl:t}:{}});window.location.assign(m)}catch(m){f(m.message),l(!1)}}return to("div",{className:s?`soba-connect ${s}`:"soba-connect","data-theme":i,children:[Sr("button",{type:"button",className:"sc-btn sc-btn-primary",disabled:u,onClick:()=>void g(),children:u?"Opening\u2026":r??`Subscribe for $${e.price.toLocaleString()}/${e.interval}`}),p&&Sr("p",{className:"sc-error",children:p})]})}import{useCallback as Ne,useEffect as Fe,useMemo as Pn,useRef as so,useState as Y}from"react";var qn=class{#n;#r=null;#t=null;#e;#s=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.#s.add(n),()=>this.#s.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 s=await r.json(),a=s.session??s.token;if(!a)throw new Error(`${n} answered without a \`session\`. See @soba-so/react's README.`);let i=s.expires_in??s.expiresIn;this.#n=a,this.#r=typeof i=="number"?Date.now()+i*1e3:null;for(let u of this.#s)u();return a})();try{return await this.#t}finally{this.#t=null}}};function Pr(e,n=fetch.bind(globalThis)){return async(t,r)=>{let s=await n(t,r);if(s.status!==401||!e.canRefresh)return s;let a;try{a=await e.refresh()}catch{return s}return n(t,ro(r,a))}}function ro(e,n){let t=new Headers(e?.headers);return t.set("authorization",`Bearer ${n}`),{...e,headers:t}}import{jsx as Ht,jsxs as lo}from"react/jsx-runtime";var oo="https://www.soba.so",ao=15e3;function io(e){let{children:n,session:t,sessionEndpoint:r,user:s,runEndpoint:a,theme:i,initialMachines:u,initialConnect:l=null,initialPlans:p,initialCurrentPlan:f=null,baseUrl:g=oo,pollMs:m=ao,injectStyles:b=!0,modal:h=!0,fetchImpl:k,onError:N}=e,[x,U]=Y(t??null),[j,S]=Y(null),[O,H]=Y(l),[T,M]=Y(null),[q,G]=Y(l===null),[ce,Me]=Y(u??[]),[_n,Q]=Y(null),[ke,En]=Y(u===void 0),[xe,be]=Y(p??[]),[X,Bn]=Y(f),[tn,We]=Y(null),[Mn,ue]=Y(p===void 0),[se,Ge]=Y(null),[Fn,Re]=Y(!1),Ve=so(N);Ve.current=N;let oe=Ne(y=>{S(y),Ve.current?.(y)},[]);Fe(()=>{b&&kn()},[b]);let R=Pn(()=>new qn({...t?{token:t}:{},...r?{endpoint:r}:{},...s?{user:s}:{},...k?{fetchImpl:k}:{}}),[t,r,s,k]);Fe(()=>{let y=!0,B=R.subscribe(()=>{y&&U(R.token)});return!R.token&&!R.canRefresh?oe(new Error("<SobaProvider> needs a `session` or a `sessionEndpoint`. A browser cannot mint one: that takes your secret key.")):R.ensure().then(()=>y&&U(R.token),pe=>y&&oe(pe)),()=>{y=!1,B()}},[R,oe]),Fe(()=>{j&&(G(!1),En(!1),ue(!1),M(y=>y??j),Q(y=>y??j),We(y=>y??j))},[j]),Fe(()=>{let y=R.refreshAt;if(y===null)return;let B=setTimeout(()=>{R.refresh().catch(pe=>oe(pe))},Math.max(0,y-Date.now()));return()=>clearTimeout(B)},[R,oe,x]);let P=Pn(()=>x?new sn({session:x,baseUrl:g,fetchImpl:Pr(R,k??fetch.bind(globalThis))}):null,[x,g,R,k]);Fe(()=>{if(!P)return;let y=!0;return G(!0),P.context().then(B=>{y&&(H(B),M(null),G(!1))},B=>{y&&(M(B),G(!1))}),()=>{y=!1}},[P]);let Le=Ne(async()=>{if(P)try{let y=await P.machines();Me(Array.isArray(y)?y:[]),Q(null)}catch(y){Q(y)}finally{En(!1)}},[P]),ee=Ne(async()=>{if(P)try{let y=await P.plans();be(y.plans),Bn(y.current),We(null)}catch(y){We(y)}finally{ue(!1)}},[P]);Fe(()=>{P&&ee()},[P,ee]);let rn=Ne(async y=>{if(!P)throw new Error("No session yet.");await P.selectPlan(y),await ee()},[P,ee]),Rn=Ne(async(y,B)=>{if(!P)throw new Error("No session yet.");let pe=await P.checkoutPlan(y,B);if(!pe.url)throw new Error("Checkout could not be started.");return pe.url},[P]),ae=Ne(async()=>{if(!P)throw new Error("No session yet.");await P.leavePlan(),await ee()},[P,ee]);Fe(()=>{if(!P)return;let y=!0;Le();let B=setInterval(()=>{typeof document<"u"&&document.hidden||y&&Le()},m);return()=>{y=!1,clearInterval(B)}},[P,Le,m]);let Se=Ne(async y=>{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:B,...pe}=y,Oe=await(k??fetch.bind(globalThis))(a,{method:"POST",headers:{"content-type":"application/json",accept:"text/event-stream"},credentials:"same-origin",body:JSON.stringify(pe),...B?{signal:B}:{}});if(!Oe.ok){let Z=await Oe.json().catch(()=>null),Te=new Error(Z?.error?.message??`${a} answered ${Oe.status}.`);throw Te.status=Oe.status,Z?.error?.code&&(Te.code=Z.error.code),Z?.error&&(Te.error=Z.error),Te}let F=Mt(Oe);return async function*(){try{yield*F}finally{ee()}}()},[a,k,ee]),ze=Ne((y="manual")=>{h&&(Re(!0),Ge(y))},[h]),Ke=Ne(()=>Ge(null),[]),ne=Pn(()=>X?xe.find(y=>y.id===X.plan_id)??null:null,[xe,X]),de=Pn(()=>ne?ne.connected_reward==="included"&&ce.length>0&&ne.connected_included_units!==null?ne.connected_included_units:ne.included_units:null,[ne,ce]),je=Pn(()=>({session:x,client:P,error:j,plan:{plans:xe,current:X,plan:ne,used:X?.units_used??null,included:de,remaining:de!==null&&X?Math.max(0,de-X.units_used):null,unlimited:ne!==null&&de===null,loading:Mn,error:tn,select:rn,checkout:Rn,leave:ae,refresh:ee},compute:{machines:ce,connected:ce.length>0,online:ce.some(y=>y.state!=="offline"),loading:ke,error:_n,refresh:Le},connect:{app:O?.app??null,command:O?.command??null,connectUrl:O?.connect_url??null,publishableKey:O?.publishable_key??null,loading:q,error:T,open:ze,close:Ke,isOpen:se!==null,hasModal:h},run:Se}),[x,P,j,ne,de,se,ze,Ke,h,ce,ke,_n,Le,xe,X,Mn,tn,rn,Rn,ae,ee,O,q,T,Se]);return Ht(Ct.Provider,{value:P,children:Ht(Nt.Provider,{value:{context:O,machines:ke?void 0:ce,theme:i??O?.theme??"light"},children:lo(vt.Provider,{value:je,children:[n,h&&Fn&&Ht(Cn,{open:se!==null,onOpenChange:y=>Ge(y?se??"manual":null),...se&&se!=="manual"?{reason:se}:{}})]})})})}export{as as ComputeStatus,qe as ConnectButton,us as ConnectCompute,Cn as ConnectModal,ws as ConnectNudge,Ls as RunError,Is as RunLimit,eo as SobaBilling,no as SobaCheckout,Rt as SobaCurrentPlan,Ot as SobaPlans,io as SobaProvider,Es as collectText,kn as injectStyles,Dn as parseEvent,Mt as readEvents,br as runErrorMessage,Be as sobaErrorCode,Sn as useCurrentPlan,Lt as usePlans,Pt as useRunLimit,D as useSoba};
package/dist/styles.css CHANGED
@@ -1200,7 +1200,8 @@ a.sc-btn {
1200
1200
  }
1201
1201
 
1202
1202
  .sc-result-ok {
1203
- color: var(--sc-ok, #22a06b);
1203
+
1204
+ color: var(--sc-text, #1a1a1c);
1204
1205
  }
1205
1206
 
1206
1207
  .sc-result-off {
@@ -1538,6 +1539,36 @@ a.sc-btn {
1538
1539
  min-width: 0;
1539
1540
  }
1540
1541
 
1542
+ .sc-nudge {
1543
+ position: relative;
1544
+ }
1545
+ .sc-nudge-dismiss {
1546
+ position: absolute;
1547
+ top: 7px;
1548
+ right: 8px;
1549
+ display: grid;
1550
+ place-items: center;
1551
+ width: 28px;
1552
+ height: 28px;
1553
+ padding: 0;
1554
+ border: 0;
1555
+ border-radius: 999px;
1556
+ background: none;
1557
+ color: var(--sc-muted, #6b6b73);
1558
+ cursor: pointer;
1559
+ transition:
1560
+ background-color 0.12s,
1561
+ color 0.12s;
1562
+ }
1563
+ .sc-nudge-dismiss:hover {
1564
+ background: var(--sc-raised, #f6f6f7);
1565
+ color: var(--sc-text, #1a1a1c);
1566
+ }
1567
+ .sc-nudge-x {
1568
+ width: 14px;
1569
+ height: 14px;
1570
+ }
1571
+
1541
1572
  .sc-nudge > .sc-btn {
1542
1573
  grid-column: 2;
1543
1574
  align-self: end;
@@ -2277,6 +2308,18 @@ li.sc-plan-row.sc-plan-current {
2277
2308
  color: var(--sc-muted, #6b6b73);
2278
2309
  }
2279
2310
 
2311
+ .sc-run-error {
2312
+ border-color: color-mix(in srgb, var(--sc-warn, #b06f14) 28%, var(--sc-line, #e9e9eb));
2313
+ }
2314
+ .sc-run-error-mark {
2315
+ background: color-mix(in srgb, var(--sc-warn, #b06f14) 12%, var(--sc-raised, #f6f6f7));
2316
+ color: var(--sc-warn, #b06f14);
2317
+ }
2318
+
2319
+ .sc-run-error-message {
2320
+ overflow-wrap: anywhere;
2321
+ }
2322
+
2280
2323
  .sc-modal-sheet .sc-limit-head {
2281
2324
  flex-direction: column;
2282
2325
  align-items: center;
@@ -2393,3 +2436,302 @@ li.sc-plan-row.sc-plan-current {
2393
2436
  .sc-opt-has-warn {
2394
2437
  color: var(--sc-warn, #b06f14);
2395
2438
  }
2439
+
2440
+ .bx * {
2441
+ transform-box: view-box;
2442
+ }
2443
+
2444
+ .bx-arc,
2445
+ .bx-st,
2446
+ .bx-z1 path,
2447
+ .bx-z2 path,
2448
+ .bx-ob path {
2449
+ stroke-width: var(--bx-w, 17);
2450
+ }
2451
+
2452
+ .bx[data-expression="thinking"] .bx-arc,
2453
+ .bx[data-expression="paused"] .bx-arc,
2454
+ .bx[data-expression="attention"] .bx-arc,
2455
+ .bx[data-expression="connecting"] .bx-arc,
2456
+ .bx[data-expression="gone"] .bx-arc,
2457
+ .bx[data-expression="snap"] .bx-arc,
2458
+ .bx[data-expression="listening"] .bx-arc,
2459
+ .bx[data-expression="permission"] .bx-arc,
2460
+ .bx[data-expression="ai"] .bx-arc {
2461
+ display: none;
2462
+ }
2463
+
2464
+ @keyframes bx-stream {
2465
+ to {
2466
+ stroke-dashoffset: -62;
2467
+ }
2468
+ }
2469
+
2470
+ .bx-st {
2471
+ animation: bx-stream 0.9s linear infinite;
2472
+ }
2473
+
2474
+ @keyframes bx-think {
2475
+ 0%,
2476
+ 100% {
2477
+ opacity: 0.26;
2478
+ }
2479
+ 33% {
2480
+ opacity: 1;
2481
+ }
2482
+ }
2483
+
2484
+ .bx-th {
2485
+ opacity: 0.26;
2486
+ animation: bx-think 1.2s ease-in-out infinite;
2487
+ }
2488
+
2489
+ .bx-th2 {
2490
+ animation-delay: 0.4s;
2491
+ }
2492
+
2493
+ .bx-th3 {
2494
+ animation-delay: 0.8s;
2495
+ }
2496
+
2497
+ @keyframes bx-att {
2498
+ 0%,
2499
+ 80%,
2500
+ 100% {
2501
+ transform: rotate(0);
2502
+ }
2503
+ 85% {
2504
+ transform: rotate(-8deg);
2505
+ }
2506
+ 95% {
2507
+ transform: rotate(8deg);
2508
+ }
2509
+ }
2510
+
2511
+ .bx-at {
2512
+
2513
+ transform-box: fill-box;
2514
+ transform-origin: 50% 100%;
2515
+ animation: bx-att 2s ease-in-out infinite;
2516
+ }
2517
+
2518
+ @keyframes bx-z {
2519
+ 0% {
2520
+ opacity: 0;
2521
+ transform: translate(0, 12px);
2522
+ }
2523
+ 25%,
2524
+ 70% {
2525
+ opacity: 1;
2526
+ transform: translate(0, 0);
2527
+ }
2528
+ 100% {
2529
+ opacity: 0;
2530
+ transform: translate(8px, -16px);
2531
+ }
2532
+ }
2533
+
2534
+ .bx-z1 {
2535
+ animation: bx-z 3s ease-in-out infinite;
2536
+ }
2537
+
2538
+ .bx-z2 {
2539
+ animation: bx-z 3s ease-in-out 0.75s infinite;
2540
+ }
2541
+
2542
+ @keyframes bx-orb {
2543
+ to {
2544
+ transform: rotate(360deg);
2545
+ }
2546
+ }
2547
+
2548
+ .bx-ob {
2549
+ transform-origin: 278px 400px;
2550
+ animation: bx-orb 1.15s cubic-bezier(0.45, 0, 0.55, 1) infinite;
2551
+ }
2552
+
2553
+ @keyframes bx-xa {
2554
+ 0% {
2555
+ opacity: 0;
2556
+ transform: translateX(0);
2557
+ }
2558
+ 8%,
2559
+ 22% {
2560
+ opacity: 1;
2561
+ transform: translateX(0);
2562
+ }
2563
+ 45%,
2564
+ 100% {
2565
+ opacity: 0;
2566
+ transform: translateX(40px);
2567
+ }
2568
+ }
2569
+
2570
+ .bx-xa {
2571
+ opacity: 0;
2572
+ animation: bx-xa 3.2s cubic-bezier(0.45, 0, 0.55, 1) infinite;
2573
+ }
2574
+
2575
+ @keyframes bx-xx {
2576
+ 0%,
2577
+ 40% {
2578
+ opacity: 0;
2579
+ transform: scale(0.4);
2580
+ }
2581
+ 54% {
2582
+ opacity: 1;
2583
+ transform: scale(1.08);
2584
+ }
2585
+ 60%,
2586
+ 90% {
2587
+ opacity: 1;
2588
+ transform: scale(1);
2589
+ }
2590
+ 100% {
2591
+ opacity: 0;
2592
+ transform: scale(1);
2593
+ }
2594
+ }
2595
+
2596
+ .bx-xx {
2597
+ transform-box: fill-box;
2598
+ transform-origin: center;
2599
+ animation: bx-xx 3.2s ease-out infinite;
2600
+ }
2601
+
2602
+ @keyframes bx-voice {
2603
+ 0%,
2604
+ 100% {
2605
+ transform: scaleY(0.45);
2606
+ }
2607
+ 50% {
2608
+ transform: scaleY(1);
2609
+ }
2610
+ }
2611
+
2612
+ .bx-vb {
2613
+ transform-box: fill-box;
2614
+ transform-origin: center;
2615
+ animation: bx-voice 0.9s ease-in-out infinite;
2616
+ }
2617
+
2618
+ .bx-vb2 {
2619
+ animation-delay: 0.15s;
2620
+ }
2621
+
2622
+ .bx-vb3 {
2623
+ animation-delay: 0.3s;
2624
+ }
2625
+
2626
+ @keyframes bx-wait {
2627
+ 0% {
2628
+ opacity: 1;
2629
+ }
2630
+ 100% {
2631
+ opacity: 0.15;
2632
+ }
2633
+ }
2634
+
2635
+ .bx-w {
2636
+ opacity: 0.15;
2637
+ animation: bx-wait 1.2s linear infinite;
2638
+ }
2639
+
2640
+ @keyframes bx-spark {
2641
+ 0%,
2642
+ 100% {
2643
+ transform: scale(1) rotate(0);
2644
+ }
2645
+ 50% {
2646
+ transform: scale(0.7) rotate(22deg);
2647
+ }
2648
+ }
2649
+
2650
+ .bx-sp {
2651
+ transform-box: fill-box;
2652
+ transform-origin: center;
2653
+ animation: bx-spark 2.6s ease-in-out infinite;
2654
+ }
2655
+
2656
+ .bx-sp2 {
2657
+ animation-delay: -0.87s;
2658
+ }
2659
+
2660
+ .bx-sp3 {
2661
+ animation-delay: -1.73s;
2662
+ }
2663
+
2664
+ @keyframes bx-snap {
2665
+ 0%,
2666
+ 6% {
2667
+ transform: translateX(90px);
2668
+ opacity: 0;
2669
+ }
2670
+ 24% {
2671
+ transform: translateX(-10px);
2672
+ opacity: 1;
2673
+ }
2674
+ 30% {
2675
+ transform: translateX(4px);
2676
+ }
2677
+ 35%,
2678
+ 100% {
2679
+ transform: translateX(0);
2680
+ opacity: 1;
2681
+ }
2682
+ }
2683
+
2684
+ .bx-snap {
2685
+ animation: bx-snap 3.6s cubic-bezier(0.3, 0, 0.2, 1) infinite;
2686
+ }
2687
+
2688
+ @media (prefers-reduced-motion: reduce) {
2689
+ .bx .bx-st,
2690
+ .bx .bx-th,
2691
+ .bx .bx-at,
2692
+ .bx .bx-z1,
2693
+ .bx .bx-z2,
2694
+ .bx .bx-ob,
2695
+ .bx .bx-xa,
2696
+ .bx .bx-xx,
2697
+ .bx .bx-snap,
2698
+ .bx .bx-vb,
2699
+ .bx .bx-w,
2700
+ .bx .bx-sp {
2701
+ animation: none;
2702
+ }
2703
+
2704
+
2705
+ .bx .bx-th,
2706
+ .bx .bx-z1,
2707
+ .bx .bx-z2,
2708
+ .bx .bx-xx,
2709
+ .bx .bx-snap,
2710
+ .bx .bx-w {
2711
+ opacity: 1;
2712
+ transform: none;
2713
+ }
2714
+ }
2715
+
2716
+ [data-version="v1"] .bx .bx-arc {
2717
+ display: revert;
2718
+ }
2719
+
2720
+ [data-version="v1"] .bx .bx-st,
2721
+ [data-version="v1"] .bx .bx-th,
2722
+ [data-version="v1"] .bx .bx-at,
2723
+ [data-version="v1"] .bx .bx-z1,
2724
+ [data-version="v1"] .bx .bx-z2,
2725
+ [data-version="v1"] .bx .bx-ob,
2726
+ [data-version="v1"] .bx .bx-xa,
2727
+ [data-version="v1"] .bx .bx-xx,
2728
+ [data-version="v1"] .bx .bx-snap,
2729
+ [data-version="v1"] .bx .bx-vb,
2730
+ [data-version="v1"] .bx .bx-w,
2731
+ [data-version="v1"] .bx .bx-sp {
2732
+ display: none;
2733
+ }
2734
+
2735
+ [data-version="v1"] .sc-result-ok {
2736
+ color: var(--sc-ok, #22a06b);
2737
+ }
package/dist/types.d.ts CHANGED
@@ -77,7 +77,7 @@ export interface ConnectContext {
77
77
  name: string;
78
78
  };
79
79
  publishable_key: string | null;
80
- /** The link a person pastes into Soba Connect. */
80
+ /** The link a person pastes into the Soba app. */
81
81
  connect_url: string | null;
82
82
  /** Retired: always null. There is no pairing command any more. */
83
83
  command: string | null;
@@ -107,6 +107,16 @@ export interface Plan {
107
107
  * component has, and the reason these plans are worth rendering from data. */
108
108
  route_prefer: string[];
109
109
  route_allow: string[] | null;
110
+ /**
111
+ * WHETHER THIS PLAN ASKS FOR A MACHINE when its routing already prefers one
112
+ * and the app's own compute would serve the run anyway.
113
+ *
114
+ * Optional, so an older server that does not send it still parses — and
115
+ * `undefined` reads as true, which is what those servers do. Only the
116
+ * preference branch of `<ConnectNudge />` consults it: a plan that cannot run
117
+ * at all, and a machine that has gone quiet, are reported either way.
118
+ */
119
+ ask_to_connect?: boolean;
110
120
  /** Whether it can be taken without a payment rail. */
111
121
  selectable: boolean;
112
122
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soba-so/react",
3
- "version": "0.0.13",
3
+ "version": "0.0.14",
4
4
  "description": "Connect the AI your users already pay for, from your own React app.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://soba.so/docs/components",