@coseung2/opencodex 2.8.0-cs.12 → 2.8.0-cs.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/gui/dist/assets/{index-GgF1IpQa.js → index-BucjyD4I.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/ocx-notch/README.md +1 -1
- package/src/codex/account-store.ts +72 -10
- package/src/codex/auth-api.ts +209 -33
- package/src/codex/warmup.ts +14 -0
- package/src/oauth/token-guardian.ts +130 -9
- package/src/providers/registry.ts +4 -0
- package/src/router.ts +6 -0
- package/src/types.ts +5 -1
- package/vendor/ocx-notch/win32-x64/ocx-notch.exe +0 -0
|
@@ -64,4 +64,4 @@ v2: spawn_agent を備えたマルチスレッドエージェント。すべて
|
|
|
64
64
|
"max_tokens": 64,
|
|
65
65
|
"messages": [{"role": "user", "content": ${r}}]
|
|
66
66
|
}'`;return(0,z.jsxs)(`section`,{className:`panel api-panel awi-usage-panel`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:n(`api.workspace.usageExamples`)}),(0,z.jsxs)(`div`,{className:`awi-usage-panel-body`,children:[(0,z.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,z.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageChatTitle`)}),(0,z.jsx)(Iu,{text:i})]}),(0,z.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,z.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageResponsesTitle`)}),(0,z.jsx)(Iu,{text:a})]}),t&&(0,z.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,z.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageMessagesTitle`)}),(0,z.jsx)(Iu,{text:o})]})]})]})}var Hu=[`opencode`,`pi`],Uu={opencode:`api.clientConfig.clientOpencode`,pi:`api.clientConfig.clientPi`},Wu={opencode:`/provider-icons/opencode.svg`,pi:`/provider-icons/pi.svg`};function Gu({client:e,apiBase:t,onOpenDetails:n,onCopy:r,onDownload:i}){let a=K(),[o,s]=(0,_.useState)(0),c=[t,e,String(o)].join(`|`),[l,u]=(0,_.useState)(null);(0,_.useEffect)(()=>{let n=new AbortController,r=!1;return(async()=>{try{let i=await fetch(`${t}/api/client-config?client=${encodeURIComponent(e)}`,{signal:n.signal});if(!i.ok)throw Error(String(i.status));let a=await i.json();if(r)return;u({key:c,data:a,failed:!1})}catch{if(r)return;u({key:c,data:null,failed:!0})}})(),()=>{r=!0,n.abort()}},[t,e,c]);let d=l!==null&&l.key===c?l:null,f=d?.data??null,p=d?.failed??!1,m=d===null,h=a(Uu[e]),g=Wu[e],v=f?`${JSON.stringify(f.config,null,2)}\n`:``,y=(0,_.useCallback)(t=>{f&&n(e,f,v,t.currentTarget)},[e,f,v,n]);return(0,z.jsxs)(`li`,{className:`awi-clientconfig-row`,children:[(0,z.jsx)(`span`,{className:`awi-clientconfig-mark`,"aria-hidden":`true`,children:g?(0,z.jsx)(`img`,{src:g,alt:``,width:20,height:20}):(0,z.jsx)(`span`,{className:`awi-clientconfig-monogram`,children:h.slice(0,1)})}),(0,z.jsxs)(`span`,{className:`awi-clientconfig-identity`,children:[(0,z.jsx)(`span`,{className:`awi-clientconfig-name`,children:h}),(0,z.jsx)(`span`,{className:`muted text-label awi-clientconfig-meta`,children:m?a(`api.clientConfig.loading`):p||!f?(0,z.jsx)(`span`,{role:`alert`,children:a(`api.clientConfig.rowError`,{client:h})}):a(`api.clientConfig.rowMeta`,{destination:f.destination,count:f.modelCount})})]}),(0,z.jsx)(`span`,{className:`awi-clientconfig-row-actions`,children:p&&!m?(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>s(e=>e+1),children:a(`common.retry`)}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":a(`api.clientConfig.copyAria`,{client:h}),disabled:!f,onClick:()=>{f&&r(e,v)},children:a(`api.clientConfig.copy`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-sm`,"aria-label":a(`api.clientConfig.downloadAria`,{client:h}),disabled:!f,onClick:()=>{f&&i(e,f,v)},children:a(`api.clientConfig.download`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,"aria-label":a(`api.clientConfig.detailsAria`,{client:h}),disabled:!f,onClick:y,children:a(`api.clientConfig.details`)})]})})]})}function Ku({client:e,envelope:t,json:n,hasKeys:r,onClose:i,onCopy:a,onDownload:o}){let s=K(),c=(0,_.useRef)(null),l=`awi-clientconfig-dialog-${e}`;return(0,_.useEffect)(()=>{let e=c.current;return e&&!e.open&&e.showModal(),()=>{e?.open&&e.close()}},[]),(0,z.jsxs)(`dialog`,{ref:c,className:`modal-overlay`,"aria-labelledby":l,onCancel:(0,_.useCallback)(e=>{e.preventDefault(),i()},[i]),children:[(0,z.jsx)(`button`,{type:`button`,className:`modal-backdrop-dismiss`,"aria-label":s(`common.close`),tabIndex:-1,onClick:i}),(0,z.jsxs)(`div`,{className:`modal-card awi-clientconfig-dialog`,onClick:e=>e.stopPropagation(),role:`document`,children:[(0,z.jsxs)(`div`,{className:`modal-head`,children:[(0,z.jsx)(`h3`,{id:l,children:s(Uu[e])}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:i,children:s(`common.close`)})]}),(0,z.jsx)(`pre`,{className:`api-code api-example-pre awi-clientconfig-json`,tabIndex:0,role:`group`,"aria-label":s(`api.clientConfig.jsonLabel`,{client:s(Uu[e])}),children:n}),(0,z.jsx)(`p`,{className:`muted small awi-clientconfig-count`,children:s(`api.clientConfig.modelCount`,{count:t.modelCount})}),t.modelsWithoutLimits>0&&(0,z.jsx)(`p`,{className:`muted small awi-clientconfig-degraded`,children:s(`api.clientConfig.missingLimits`,{count:t.modelsWithoutLimits,total:t.modelCount})}),!r&&(0,z.jsx)(`p`,{className:`muted small awi-clientconfig-nokey`,children:s(`api.clientConfig.noKeyYet`,{env:t.apiKeyEnv})}),(0,z.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,z.jsx)(`span`,{className:`muted text-label`,children:s(`api.clientConfig.destination`)}),(0,z.jsx)(Iu,{text:t.destination})]}),(0,z.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,z.jsx)(`span`,{className:`muted text-label`,children:s(`api.clientConfig.envHint`)}),(0,z.jsx)(Iu,{text:t.exportHint})]}),(0,z.jsx)(`p`,{className:`muted small awi-clientconfig-merge`,children:s(`api.clientConfig.mergeWarning`)}),(0,z.jsx)(`p`,{className:`muted text-label awi-clientconfig-where-title`,children:s(`api.clientConfig.whereDisclosure`)}),(0,z.jsx)(`p`,{className:`muted small`,children:s(`api.clientConfig.whereBody`)}),(0,z.jsxs)(`div`,{className:`modal-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:a,children:s(`api.clientConfig.copy`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:o,children:s(`api.clientConfig.download`)})]})]})]})}function qu({apiBase:e,baseUrl:t,hasKeys:n}){let r=K(),[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(``),c=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(i!==null)return;let e=c.current;e&&(c.current=null,e.isConnected&&e.focus())},[i]);let l=(0,_.useCallback)(async(e,t,n)=>{try{await navigator.clipboard.writeText(t),s(n?r(`api.clientConfig.copiedAnnounceClient`,{client:r(Uu[e])}):r(`api.clientConfig.copiedAnnounce`))}catch{s(r(`api.clientConfig.copyFailed`))}},[r]),u=(0,_.useCallback)((e,t,n)=>{let i=URL.createObjectURL(new Blob([n],{type:`application/json`})),a=document.createElement(`a`);a.href=i,a.download=t.filename,a.click(),URL.revokeObjectURL(i),s(r(`api.clientConfig.downloadedAnnounce`,{filename:t.filename,destination:t.destination}))},[r]),d=(0,_.useCallback)(()=>a(null),[]),f=(0,_.useCallback)((e,t,n,r)=>{c.current=r,a({client:e,envelope:t,json:n})},[]);return(0,z.jsxs)(`section`,{className:`panel api-panel awi-clientconfig-panel`,children:[(0,z.jsx)(`div`,{className:`api-panel-head awi-clientconfig-head`,children:(0,z.jsx)(`h3`,{className:`panel-title`,children:r(`api.clientConfig.title`)})}),(0,z.jsx)(`ul`,{className:`awi-clientconfig-rows`,"aria-label":r(`api.clientConfig.rowsLabel`),children:Hu.map(t=>(0,z.jsx)(Gu,{client:t,apiBase:e,onOpenDetails:f,onCopy:(e,t)=>{l(e,t,!0)},onDownload:u},t))}),(0,z.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,z.jsx)(`span`,{className:`muted text-label`,children:r(`api.baseUrl`)}),(0,z.jsx)(Iu,{text:t})]}),(0,z.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:o}),i&&(0,z.jsx)(Ku,{client:i.client,envelope:i.envelope,json:i.json,hasKeys:n,onClose:d,onCopy:()=>{l(i.client,i.json,!1)},onDownload:()=>u(i.client,i.envelope,i.json)})]})}function Ju({keys:e,keysLoading:t,keysLoadFailed:n,attributionSince:r,localeTag:i,busy:a,onSelect:o}){let s=K();return(0,z.jsxs)(`div`,{className:`panel api-panel awi-keylist-panel`,"aria-busy":t,children:[(0,z.jsx)(`div`,{className:`api-panel-head`,children:(0,z.jsx)(`h3`,{className:`panel-title`,children:t?s(`api.activeKeysLoading`):s(`api.activeKeys`,{count:e.length})})}),t?(0,z.jsx)(`div`,{className:`api-active-keys-skeleton`,role:`status`,"aria-label":s(`common.loading`)}):e.length===0?(0,z.jsx)(`p`,{className:`muted small`,children:s(n?`api.keysLoadFailed`:`api.noKeys`)}):(0,z.jsx)(`div`,{className:`tbl-wrap`,children:(0,z.jsxs)(`table`,{className:`tbl awi-keylist-table`,children:[(0,z.jsx)(`thead`,{children:(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`th`,{children:s(`api.colName`)}),(0,z.jsx)(`th`,{children:s(`api.colKey`)}),(0,z.jsx)(`th`,{children:s(`api.attribution.requests7d`)}),(0,z.jsx)(`th`,{children:s(`api.attribution.lastUsed`)})]})}),(0,z.jsx)(`tbody`,{children:e.map(e=>(0,z.jsxs)(`tr`,{children:[(0,z.jsx)(`td`,{children:(0,z.jsx)(`button`,{type:`button`,className:`awi-keylist-name`,disabled:a,onClick:()=>o(e.id),children:e.name})}),(0,z.jsx)(`td`,{children:(0,z.jsx)(`code`,{children:e.prefix})}),(0,z.jsx)(`td`,{children:r?e.usage.ambiguous?s(`api.attribution.railAmbiguous`):e.usage.requests7d.toLocaleString(i):s(`api.attribution.unavailable`)}),(0,z.jsx)(`td`,{children:!r||e.usage.ambiguous?`—`:e.usage.lastUsedAt?Nu(e.usage.lastUsedAt,i):s(`api.attribution.neverUsed`)})]},e.id))})]})})]})}function Yu({keys:e,apiBase:t,attributionSince:n,historyTruncated:r,authMatrix:i,keysLoading:a,keysLoadFailed:o,endpoints:s,claudeCodeEnabled:c,localeTag:l,newName:u,creating:d,newKey:f,copied:p,filteredModels:m,modelsLoading:h,modelsRefreshing:g=!1,modelsLoadFailed:v,modelCount:y,hasModelData:b,modelQuery:x,copiedModelId:S,modelTests:C,canTestModels:w,onNewNameChange:T,onCreate:E,onDismissNewKey:D,onCopyKey:O,onDelete:k,onRename:A,onModelQueryChange:j,onCopyModelId:M,onTestModel:N,onRetryModels:P,sourceLabel:F,protocolLabel:I}){let L=K(),[R,B]=(0,_.useState)(null),[V,H]=(0,_.useState)(!1),[U,W]=(0,_.useState)(!1),[ee,te]=(0,_.useState)(!1),[ne,re]=(0,_.useState)(!1),[G,ie]=(0,_.useState)(``),[ae,oe]=(0,_.useState)(!1),[se,ce]=(0,_.useState)(!1),[le,de]=(0,_.useState)(!1),fe=R?e.find(e=>e.id===R)??null:null,pe=ee||ae,me=(0,_.useMemo)(()=>[{id:`keys`,label:L(`api.section.keys`),meta:a?void 0:String(e.length)},{id:`connect`,label:L(`api.section.connect`)},{id:`endpoints`,label:L(`api.section.endpoints`)},{id:`models`,label:L(`api.section.models`),meta:String(y)},{id:`examples`,label:L(`api.section.examples`)}],[L,e.length,a,y]),he=()=>{H(!1),W(!1)},ge=()=>{B(null),he(),re(!1),ce(!1),de(!1)};(0,_.useEffect)(()=>{if(!V)return;let e=window.setTimeout(()=>W(!0),300);return()=>window.clearTimeout(e)},[V]);let ve=()=>{fe&&H(!0)},ye=async()=>{if(!(!fe||!U||ee)){te(!0),de(!1);try{await k(fe.id)?(he(),B(null)):de(!0)}finally{te(!1)}}},be=()=>{fe&&(ie(fe.name),ce(!1),re(!0))},xe=async()=>{if(!fe||ae)return;let e=G.trim();if(!e||e===fe.name){re(!1);return}oe(!0),ce(!1);try{await A(fe.id,e)?re(!1):ce(!0)}finally{oe(!1)}};return(0,z.jsxs)(`div`,{className:`apikeys-workspace-shell`,children:[!fe&&(0,z.jsx)(fc,{scope:`api`,items:me,ariaLabel:L(`api.workspace.sections`)}),(0,z.jsx)(`div`,{className:`apikeys-workspace-root`,children:(0,z.jsx)(`section`,{className:`apikeys-workspace-main`,"aria-label":L(`api.workspace.details`),children:fe?(0,z.jsxs)(`div`,{className:`awi-detail`,children:[(0,z.jsx)(`div`,{className:`awi-detail-toolbar`,children:(0,z.jsxs)(`button`,{type:`button`,className:`awi-back`,onClick:ge,disabled:pe,children:[(0,z.jsx)(_e,{className:`awi-back-chevron`,"aria-hidden":`true`}),L(`modal.back`)]})}),(0,z.jsxs)(`div`,{className:`awi-detail-body`,children:[(0,z.jsxs)(`div`,{className:`awi-detail-head`,children:[(0,z.jsx)(`h2`,{className:`awi-detail-title`,children:fe.name}),(0,z.jsx)(`span`,{className:`awi-detail-actions`,children:V?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm awi-confirm-delete`,onClick:()=>{ye()},disabled:!U||ee,children:[(0,z.jsx)(ue,{}),` `,L(ee?`api.key.deleting`:`api.confirm`)]},`confirm-delete`),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:he,disabled:ee,children:L(`common.cancel`)})]}):(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:be,disabled:ne,children:L(`api.key.rename`)},`rename`),(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,onClick:ve,"aria-label":L(`api.deleteAria`),children:[(0,z.jsx)(ue,{}),` `,L(`api.workspace.deleteKey`)]},`request-delete`)]})})]}),V&&(0,z.jsx)(`p`,{className:`muted awi-delete-hint`,children:L(`api.workspace.deleteConfirm`)}),le&&(0,z.jsx)(`p`,{className:`awi-delete-error`,role:`alert`,children:L(`api.deleteFailed`)}),ne&&(0,z.jsxs)(`div`,{className:`awi-rename`,children:[(0,z.jsx)(`label`,{className:`awi-rename-label`,htmlFor:`awi-key-name`,children:L(`api.key.name`)}),(0,z.jsx)(`input`,{id:`awi-key-name`,className:`input`,type:`text`,value:G,maxLength:64,disabled:ae,onChange:e=>ie(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),xe())}}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>{xe()},disabled:ae,children:L(ae?`api.key.renaming`:`api.key.saveName`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>re(!1),disabled:ae,children:L(`common.cancel`)}),se&&(0,z.jsx)(`p`,{className:`awi-rename-error`,role:`alert`,children:L(`api.key.renameFailed`)})]}),(0,z.jsxs)(`div`,{className:`awi-section`,children:[(0,z.jsx)(`h3`,{className:`awi-section-title`,children:L(`api.workspace.keyDetails`)}),(0,z.jsxs)(`dl`,{className:`awi-kv`,children:[(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(`api.workspace.keyPrefix`)}),(0,z.jsx)(`dd`,{children:(0,z.jsx)(`code`,{children:fe.prefix})})]}),(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(`api.colCreated`)}),(0,z.jsx)(`dd`,{children:Nu(fe.createdAt,l)})]})]})]}),(0,z.jsxs)(`div`,{className:`awi-section`,children:[(0,z.jsx)(`h3`,{className:`awi-section-title`,children:L(`api.attribution.title`)}),n?fe.usage.ambiguous?(0,z.jsx)(`p`,{className:`muted`,children:L(`api.attribution.ambiguous`)}):(0,z.jsxs)(`dl`,{className:`awi-kv`,children:[(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(`api.attribution.requests7d`)}),(0,z.jsx)(`dd`,{children:fe.usage.requests7d.toLocaleString(l)})]}),(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(r?`api.attribution.totalRequestsAvailable`:`api.attribution.totalRequests`)}),(0,z.jsx)(`dd`,{children:fe.usage.totalRequests.toLocaleString(l)})]}),(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(`api.attribution.lastUsed`)}),(0,z.jsx)(`dd`,{children:fe.usage.lastUsedAt?Nu(fe.usage.lastUsedAt,l):L(`api.attribution.neverUsed`)})]}),(0,z.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,z.jsx)(`dt`,{children:L(r?`api.attribution.sinceAvailable`:`api.attribution.since`)}),(0,z.jsx)(`dd`,{children:Nu(n,l)})]})]}):(0,z.jsx)(`p`,{className:`muted`,children:L(`api.attribution.unavailableDetail`)})]})]})]}):(0,z.jsx)(`div`,{className:`awi-overview`,children:(0,z.jsxs)(`div`,{className:`awi-overview-section`,children:[(0,z.jsxs)(`div`,{id:lc(`api`,`keys`),className:`awi-section-anchor`,children:[(0,z.jsx)(zu,{keys:e,keysLoading:a,keysLoadFailed:o,newName:u,creating:d,newKey:f,copied:p,confirmDelete:null,localeTag:l,showKeyList:!1,onNewNameChange:T,onCreate:E,onDismissNewKey:D,onCopyKey:O,onConfirmDelete:()=>{},onCancelDelete:()=>{},onDelete:()=>{}}),(0,z.jsx)(Ju,{keys:e,keysLoading:a,keysLoadFailed:o,attributionSince:n,localeTag:l,busy:pe,onSelect:e=>{B(e),he(),re(!1),ce(!1),de(!1)}})]}),(0,z.jsx)(`div`,{id:lc(`api`,`connect`),className:`awi-section-anchor`,children:(0,z.jsx)(qu,{apiBase:t,baseUrl:s.baseUrl,hasKeys:e.length>0})}),(0,z.jsx)(`div`,{id:lc(`api`,`endpoints`),className:`awi-section-anchor`,children:(0,z.jsx)(Ru,{endpoints:s,claudeCodeEnabled:c,authMatrix:i})}),(0,z.jsx)(`div`,{id:lc(`api`,`models`),className:`awi-section-anchor`,children:(0,z.jsx)(Bu,{filteredModels:m,modelsLoading:h,modelsRefreshing:g,modelsLoadFailed:v,modelCount:y,hasModelData:b,modelQuery:x,copiedModelId:S,modelTests:C,claudeCodeEnabled:c,onModelQueryChange:j,onCopyModelId:M,onTestModel:N,onRetryModels:P,canTestModels:w,sourceLabel:F,protocolLabel:I})}),(0,z.jsx)(`div`,{id:lc(`api`,`examples`),className:`awi-section-anchor`,children:(0,z.jsx)(Vu,{endpoints:s,claudeCodeEnabled:c})})]})})})})]})}var Xu=[],Zu=15e3;function Qu(e){let t=e.replace(/\/$/,``);if(!t)return ju;try{return new URL(t).host?Mu(`${t}/v1/responses`):ju}catch{return ju}}function $u(e){return!e||!Au(e.authMatrix)||!Array.isArray(e.keys)||e.keys.some(e=>!e||!Ou(e.usage))?null:e}function ed({apiBase:e}){let{t,locale:n}=Ve(),r=Ie.find(e=>e.code===n)?.htmlLang,i=`ocx.apikeys.list.v2:${e}`,a=`ocx.apikeys.models.v1:${e}`,o=`api-keys:${e}`,s=`api-models:${e}`,c=$u(Y(i)),l=Y(a),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(``),[m,h]=(0,_.useState)(null),[g,v]=(0,_.useState)({}),[y,b]=(0,_.useState)(``),[x,S]=(0,_.useState)(!1),[C,w]=(0,_.useState)(null),[T,E]=(0,_.useState)(!1),D=(0,_.useRef)(!1),O=(0,_.useCallback)(async n=>{let r=await ut(await fetch(`${e}/api/keys`,{signal:n}));if(!r||!Au(r.authMatrix))throw Error(t(`api.keysLoadFailed`));let a=r.keys??[];if(a.some(e=>!Ou(e.usage)))throw Error(t(`api.keysLoadFailed`));let o=a,s=Mu(r.endpoint??``),c={keys:o,endpoints:{baseUrl:r.baseUrl??s.baseUrl,responses:r.responsesEndpoint??r.endpoint??ju.responses,chatCompletions:r.chatCompletionsEndpoint??s.chatCompletions,messages:r.messagesEndpoint??s.messages,models:r.modelsEndpoint??s.models},claudeCodeEnabled:r.claudeCodeEnabled!==!1,...r.attributionSince?{attributionSince:r.attributionSince}:{},...r.historyTruncated===!0?{historyTruncated:!0}:{},authMatrix:r.authMatrix};return X(i,c),c},[e,i,t]),k=(0,_.useCallback)(async n=>{let r=await fetch(`${e}/v1/models`,{signal:n});if(!r.ok)throw Error(t(`api.modelsLoadFailed`));let i=await r.json(),o=Array.isArray(i)?i:typeof i==`object`&&i&&Array.isArray(i.data)?i.data:null;if(!o)throw Error(t(`api.modelsLoadFailed`));let s=o.filter(e=>typeof e==`object`&&!!e&&typeof e.id==`string`).map(e=>Eu(e)).sort((e,t)=>Du(e).localeCompare(Du(t)));return X(a,s),s},[e,a,t]),A=ps(o,[e],O,{isEmpty:e=>e.keys.length===0,initialData:c??void 0}),j=ps(s,[e],k,{isEmpty:e=>e.length===0,initialData:l??void 0}),M=A.state,N=j.state,P=M.data??c,F=N.data??l??Xu,I=P?.keys??[],L=P?.endpoints??Qu(e),R=P?.claudeCodeEnabled??!0,B=P?.attributionSince,V=P?.historyTruncated===!0,H=P?.authMatrix??[],U=A.refresh,W=j.refresh,ee=(0,_.useMemo)(()=>{let e=f.trim().toLowerCase();return e?F.filter(t=>Du(t).toLowerCase().includes(e)||t.displayName.toLowerCase().includes(e)||t.provider.toLowerCase().includes(e)):F},[f,F]),te=async n=>{if(D.current)return!1;D.current=!0,S(!0),d(null);try{let r=n??y,i=await J(await fetch(`${e}/api/keys`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:r||`default`})}),t(`api.createFailed`));return typeof i?.key!=`string`||i.key.length===0?(d(t(`api.createFailed`)),!1):(w(i.key),b(``),U(),!0)}catch{return d(t(`api.createFailed`)),!1}finally{D.current=!1,S(!1)}},ne=async t=>{d(null);let n=Rt(Zu);try{return(await fetch(`${e}/api/keys`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t}),signal:n.signal})).ok?(U(),!0):!1}catch{return!1}finally{n.clear()}},re=async(t,n)=>{d(null);let r=Rt(Zu);try{return(await fetch(`${e}/api/keys`,{method:`PATCH`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t,name:n}),signal:r.signal})).ok?(U(),!0):!1}catch{return!1}finally{r.clear()}},G=async()=>{if(C){d(null);try{await navigator.clipboard.writeText(C),E(!0),window.setTimeout(()=>E(!1),2e3)}catch{E(!1),d(t(`api.key.copyFailed`))}}},ie=async e=>{try{await navigator.clipboard.writeText(e),h(e),window.setTimeout(()=>h(t=>t===e?null:t),2e3)}catch{}},ae=e=>e.native?t(`api.sourceNative`):e.provider===`combo`?t(`api.sourceCombo`):e.custom?t(`api.sourceCustom`):e.provider,oe=e=>t(e===`responses`?`api.protocolResponses`:e===`messages`?`api.protocolMessages`:`api.protocolChatCompletions`),se=(e,t)=>e===`responses`?{url:L.responses,body:{model:t,input:`ping`,max_output_tokens:1,stream:!1}}:e===`messages`?{url:L.messages,body:{model:t,max_tokens:1,messages:[{role:`user`,content:`ping`}]}}:{url:L.chatCompletions,body:{model:t,messages:[{role:`user`,content:`ping`}],max_tokens:1,stream:!1}},ce=(e,t,n)=>v(r=>({...r,[e]:{...r[e],[t]:n}})),le=async(e,n)=>{if(!C)return;let r=Du(e),i=se(n,r);ce(r,n,{state:`testing`});try{let e=await fetch(i.url,{method:`POST`,headers:{"Content-Type":`application/json`,"x-opencodex-api-key":C},body:JSON.stringify(i.body)});if(!e.ok){ce(r,n,{state:`error`,detail:(await e.text()).slice(0,160)||String(e.status)});return}ce(r,n,{state:`ok`})}catch(e){ce(r,n,{state:`error`,detail:e instanceof Error?e.message:t(`api.testFailed`)})}},ue=t(`api.subtitle`).split(`{authHeader}`);return(0,z.jsxs)(`section`,{className:`api-page`,"aria-busy":M.refreshing||N.refreshing||void 0,children:[(0,z.jsx)(`div`,{className:`page-head`,children:(0,z.jsx)(`h2`,{children:t(`api.title`)})}),(0,z.jsxs)(`p`,{className:`page-sub`,children:[ue[0],(0,z.jsx)(`code`,{children:`x-opencodex-api-key`}),ue[1]]}),u&&(0,z.jsx)(q,{tone:`err`,children:u}),M.showError&&P&&(0,z.jsx)(q,{tone:`err`,children:t(`api.keysLoadFailed`)}),M.showSkeleton&&!P?(0,z.jsx)(hs,{label:t(`api.activeKeysLoading`),rows:4}):M.kind===`failed-cold`&&!P?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(q,{tone:`err`,children:M.error instanceof Error?M.error.message:t(`api.keysLoadFailed`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>U(),children:t(`common.retry`)})]}):(0,z.jsx)(z.Fragment,{children:(0,z.jsx)(Yu,{keys:I,apiBase:e,attributionSince:B,historyTruncated:V,authMatrix:H,keysLoading:!1,keysLoadFailed:M.showError,endpoints:L,claudeCodeEnabled:R,localeTag:r,newName:y,creating:x,newKey:C,copied:T,filteredModels:ee,modelsLoading:N.showSkeleton&&!N.data&&!l,modelsRefreshing:N.refreshing&&N.showError&&(N.data!==void 0||l!==null),modelsLoadFailed:N.showError,modelCount:F.length,hasModelData:N.data!==void 0||l!==null,modelQuery:f,copiedModelId:m,modelTests:g,onNewNameChange:b,onCreate:()=>{te()},onDismissNewKey:()=>w(null),onCopyKey:()=>{G()},onDelete:ne,onRename:re,onModelQueryChange:p,onCopyModelId:e=>{ie(e)},onTestModel:(e,t)=>{le(e,t)},onRetryModels:()=>{W({forceLoading:!0})},canTestModels:C!==null,sourceLabel:ae,protocolLabel:oe})})]})}function td(e,t){let n=(e??[]).map(e=>({value:e,label:Ho(e)}));return[{value:``,label:t},...n]}function nd(e){let t=e.autoConnectSupported===!0;return{autoConnectSupported:t,systemEnv:t&&e.systemEnv===!0}}var rd=[`ANTHROPIC_MODEL`,`ANTHROPIC_DEFAULT_OPUS_MODEL`,`ANTHROPIC_DEFAULT_SONNET_MODEL`,`ANTHROPIC_DEFAULT_HAIKU_MODEL`,`ANTHROPIC_DEFAULT_FABLE_MODEL`];function id(e){let t=`http://127.0.0.1:${e.port}`,n=e.authMode===`auto`?e.markerMode??`subscription`:e.authMode,r=e.autoContext&&e.maxContextTokens===null,i=rd.filter(t=>e.effectiveModelEnv[t]).map(t=>`export ${t}=${e.effectiveModelEnv[t]}`);return[`export ANTHROPIC_BASE_URL=${t}`,...n===`proxy`?[`export ANTHROPIC_AUTH_TOKEN=opencodex-proxy`]:[`# no ANTHROPIC_AUTH_TOKEN: your claude.ai login (and connectors) stay active`],`export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`,...n===`proxy`?['[ -z "${CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST+x}" ] && export CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST=1']:[],...r?[`export CLAUDE_CODE_AUTO_COMPACT_WINDOW=${e.autoCompactWindow??35e4}`]:[],...i,`claude`].join(`
|
|
67
|
-
`)}function ad(e){return e?e.backend??`auto`:`inherit`}function od(e,t){if(t!==`inherit`)return t===`auto`?{...e,backend:void 0}:{...e,backend:t}}function sd(e,t){return{...e,model:t}}function cd(e){if(!e)return null;let t=(e.model??``).trim();return e.backend?{backend:e.backend,model:t}:t?{backend:null,model:t}:null}function ld({label:e,checked:t,onChange:n,disabled:r=!1,describedBy:i}){return(0,z.jsxs)(`label`,{className:`toggle`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:t,disabled:r,"aria-label":e,"aria-describedby":i,onChange:e=>n(e.target.checked)}),(0,z.jsx)(`span`,{className:`slider`,"aria-hidden":`true`})]})}function ud({supported:e,checked:t,onChange:n}){let r=K(),i=e?void 0:`claude-system-env-unsupported`;return(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:r(`claude.systemEnv`)}),e?(0,z.jsx)(`span`,{className:`desc`,children:r(`claude.systemEnvDesc`)}):(0,z.jsx)(`span`,{className:`desc`,id:i,children:(0,z.jsx)(Ue,{k:`claude.systemEnvUnsupported`,cmd:`ocx claude`})}),e&&t&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:r(`claude.systemEnvWarn`)})]}),(0,z.jsx)(ld,{label:r(`claude.systemEnv`),checked:e&&t,disabled:!e,describedBy:i,onChange:n})]})}function dd({value:e,tierHaikuModel:t,options:n,onChange:r}){let i=K(),a=t??e;return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:i(`claude.smallFastModelAccurateHint`)}),(0,z.jsx)(at,{value:e,options:n,onChange:r,label:i(`claude.smallFastModel`),style:{maxWidth:420}}),a===``&&(0,z.jsx)(`p`,{className:`notice-warn`,role:`status`,style:{marginTop:8},children:i(`claude.smallFastModelNativeWarning`)})]})}function fd(){if(typeof crypto<`u`&&typeof crypto.randomUUID==`function`)try{return crypto.randomUUID()}catch{}let e=new Uint8Array(16);if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`)crypto.getRandomValues(e);else for(let t=0;t<16;t++)e[t]=Math.floor(Math.random()*256);e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}function pd(e,t=`en`){if(e>=1e6){let n=e/1e6,r=n.toFixed(1).replace(/\.0$/,``);return Number.isInteger(n)||Number(r)*1e6===e?new Intl.NumberFormat(t,{notation:`compact`,compactDisplay:`short`,maximumFractionDigits:+!Number.isInteger(n)}).format(e):`${Math.round(e/1e3)}k`}return`${Math.round(e/1e3)}k`}function md(e,t){return e&&[`claude-json-oauth`,`claude-credentials-file`,`macos-keychain`,`exported-env`].includes(e)?t(`claude.authSource.${e}`):t(`claude.authSource.unknown`)}function hd({state:e,autoCompactOptions:t,availableModels:n,onStateChange:r}){let i=K();return(0,z.jsxs)(`div`,{className:`card`,style:{overflow:`hidden`},children:[(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.enabledLabel`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.enabledHint`)})]}),(0,z.jsx)(ld,{label:i(`claude.enabledLabel`),checked:e.enabled,onChange:t=>r({...e,enabled:t})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.authMode`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.authModeHint`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.authMode,options:[{value:`auto`,label:i(`claude.authModeAuto`)},{value:`subscription`,label:i(`claude.authModeSubscription`)},{value:`proxy`,label:i(`claude.authModeProxy`)}],onChange:t=>r({...e,authMode:t}),label:i(`claude.authMode`),style:{minWidth:220},align:`right`,portal:!0})})]}),e.authModeOrigin&&(0,z.jsxs)(`div`,{className:`claude-effective-auth${e.authModeOrigin===`auto-unknown`?` warn`:``}`,role:`status`,children:[(0,z.jsx)(`span`,{className:`claude-effective-auth-label`,children:i(`claude.effectiveMode.label`)}),(0,z.jsxs)(`span`,{children:[e.authModeOrigin===`manual`?i(`claude.effectiveMode.manual`,{mode:e.markerMode===`proxy`?i(`claude.authModeProxy`):i(`claude.authModeSubscription`)}):e.authModeOrigin===`auto-present`?i(`claude.effectiveMode.autoPresent`,{source:md(e.authFoundBy,i)}):e.authModeOrigin===`auto-absent`?i(`claude.effectiveMode.autoAbsent`):i(`claude.effectiveMode.autoUnknown`),e.admissionKeyActive===!0?` ${i(`claude.effectiveMode.admissionKey`)}`:``]})]}),(0,z.jsx)(ud,{supported:e.autoConnectSupported,checked:e.systemEnv,onChange:t=>r({...e,systemEnv:t})}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.fastMode`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.fastModeDesc`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.fastMode===null?`auto`:e.fastMode?`on`:`off`,options:[{value:`auto`,label:i(`claude.fastAuto`)},{value:`on`,label:i(`claude.fastOn`)},{value:`off`,label:i(`claude.fastOff`)}],onChange:t=>r({...e,fastMode:t===`auto`?null:t===`on`}),label:i(`claude.fastMode`),style:{minWidth:140},align:`right`,portal:!0})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.autoContext`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.autoContextDesc`)}),e.maxContextTokens!==null&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--muted)`},children:i(`claude.autoContextInert`)})]}),(0,z.jsx)(ld,{label:i(`claude.autoContext`),checked:e.autoContext,onChange:t=>r({...e,autoContext:t})})]}),e.autoContext&&(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.autoCompactWindow`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.autoCompactWindowDesc`)}),e.autoCompactWindow!==null&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:i(`claude.autoCompactWindowWarn`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.autoCompactWindow===null?``:String(e.autoCompactWindow),options:t,onChange:t=>r({...e,autoCompactWindow:t===``?null:Number(t)}),label:i(`claude.autoCompactWindow`),style:{minWidth:130},align:`right`,portal:!0})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.injectAgents`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.injectAgentsDesc`)})]}),(0,z.jsx)(ld,{label:i(`claude.injectAgents`),checked:e.injectAgents,onChange:t=>r({...e,injectAgents:t})})]}),[`webSearchSidecar`,`visionSidecar`].map(t=>{let a=e[t],o=t===`webSearchSidecar`?`claude.webSearchSidecar`:`claude.visionSidecar`,s=t===`webSearchSidecar`?`claude.webSearchSidecarHint`:`claude.visionSidecarHint`,c=`claude-sidecar-models-${t}`;return(0,z.jsxs)(`div`,{className:`setting-row`,style:{alignItems:`flex-start`},children:[(0,z.jsxs)(`div`,{className:`setting-label setting-copy`,style:{flex:1},children:[(0,z.jsx)(`span`,{className:`title`,children:i(o)}),(0,z.jsx)(`span`,{className:`desc`,children:i(s)})]}),(0,z.jsxs)(`div`,{className:`setting-controls`,style:{display:`flex`,gap:8},children:[(0,z.jsx)(at,{value:ad(a),options:[{value:`inherit`,label:i(`claude.useMainSetting`)},{value:`auto`,label:i(`dash.backendAuto`)},{value:`openai`,label:i(`dash.backendOpenAI`)},{value:`anthropic`,label:i(`dash.backendAnthropic`)}],onChange:n=>{r({...e,[t]:od(a,n)})},label:i(`dash.sidecarBackend`),portal:!0}),(0,z.jsx)(`input`,{className:`input mono`,value:a?.model??``,onChange:n=>{r({...e,[t]:sd(a,n.target.value)})},placeholder:i(`claude.sidecarModelPlaceholder`),disabled:!a,list:a?c:void 0,"aria-label":i(`dash.sidecarModel`),style:{minWidth:210},autoComplete:`off`}),a&&(0,z.jsx)(`datalist`,{id:c,children:n.map(e=>(0,z.jsx)(`option`,{value:e},e))})]})]},t)})]})}function gd({manualEnv:e}){let t=K();return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:(0,z.jsx)(Ue,{k:`claude.quickstartHint`,cmd:`ocx claude`})}),(0,z.jsx)(`pre`,{className:`mono card`,style:{padding:`10px 14px`,overflowX:`auto`,margin:0},children:`ocx claude`}),(0,z.jsxs)(`details`,{style:{margin:`10px 0 0`},children:[(0,z.jsx)(`summary`,{className:`muted text-label`,style:{cursor:`pointer`,padding:`2px 2px`},children:t(`claude.manualEnv`)}),(0,z.jsx)(`pre`,{className:`mono card text-label`,style:{padding:`10px 14px`,overflowX:`auto`,margin:`6px 0 0`},children:e})]})]})}function _d({rows:e,onRowsChange:t}){let n=K();return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:n(`claude.modelMapHint`)}),(0,z.jsx)(`div`,{className:`stack`,style:{gap:8},children:e.map((r,i)=>(0,z.jsxs)(`div`,{className:`row`,style:{gap:8},children:[(0,z.jsx)(`input`,{className:`input mono`,value:r.from,placeholder:n(`claude.mapFrom`),"aria-label":n(`claude.mapFrom`),onChange:n=>t(e.map((e,t)=>t===i?{...e,from:n.target.value}:e)),style:{flex:1}}),(0,z.jsx)(`span`,{className:`muted`,"aria-hidden":!0,children:`→`}),(0,z.jsx)(`input`,{className:`input mono`,value:r.to,placeholder:n(`claude.mapTo`),"aria-label":n(`claude.mapTo`),onChange:n=>t(e.map((e,t)=>t===i?{...e,to:n.target.value}:e)),style:{flex:1}}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-icon btn-sm`,onClick:()=>t(e.filter((e,t)=>t!==i)),"aria-label":n(`claude.removeMapping`),style:{color:`var(--red)`},children:(0,z.jsx)(ae,{})})]},r.id))}),(0,z.jsx)(`div`,{style:{marginTop:8},children:(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>t([...e,{id:fd(),from:``,to:``}]),children:[(0,z.jsx)(oe,{}),` `,n(`claude.addMapping`)]})})]})}var vd=`etc`;function $(e){let t=new Map;for(let n of e){let e=/\(([^)]+)\)\s*$/.exec(n.display_name),r=e?e[1]:vd,i=t.get(r);i?i.push(n):t.set(r,[n])}return Array.from(t)}function yd({aliases:e}){let t=K();return(0,z.jsxs)(`div`,{className:`claude-aliases`,children:[(0,z.jsx)(`p`,{className:`muted text-label claude-aliases-hint`,children:t(`claude.aliasesHint`)}),e.length===0?(0,z.jsx)(`div`,{className:`muted text-label`,children:t(`claude.none`)}):(0,z.jsx)(`div`,{className:`claude-aliases-scroll`,children:$(e).map(([e,n])=>(0,z.jsxs)(`div`,{className:`claude-aliases-group`,children:[(0,z.jsxs)(`div`,{className:`claude-aliases-group-label`,children:[e===vd?t(`claude.aliasProviderOther`):e,(0,z.jsx)(`span`,{className:`claude-aliases-group-count`,children:n.length})]}),(0,z.jsx)(`div`,{className:`claude-aliases-chips`,children:n.map(e=>(0,z.jsxs)(`span`,{className:`claude-aliases-chip`,children:[(0,z.jsx)(`code`,{className:`claude-aliases-chip-id`,children:e.id}),e.display_name?(0,z.jsx)(`span`,{className:`claude-aliases-chip-name`,children:e.display_name}):null]},e.id))})]},e))})]})}function bd({apiBase:e,active:t=!0}){let n=K(),{locale:r}=Ve(),i=Ie.find(e=>e.code===r)?.htmlLang??`en`,a=`ocx.claude-code.v1:${e}`,o=`claude-code:${e}`,s=(0,_.useMemo)(()=>Y(a),[a]),[c,l]=(0,_.useState)(()=>s?.state??null),[u,d]=(0,_.useState)(()=>s?.rows??[]),[f,p]=(0,_.useState)(!!s),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(!1),[y,b]=(0,_.useState)(`settings`),x=(0,_.useCallback)(async t=>{let r=await J(await fetch(`${e}/api/claude-code`,{signal:t}),n(`claude.loadFail`));if(!r)throw Error(n(`claude.loadFail`));let i={...r,authMode:r.authMode===`proxy`||r.authMode===`subscription`?r.authMode:`auto`,...nd(r),fastMode:r.fastMode??null,maxContextTokens:r.maxContextTokens??null,autoContext:r.autoContext!==!1,autoCompactWindow:r.autoCompactWindow??null,injectAgents:r.injectAgents!==!1,effectiveModelEnv:r.effectiveModelEnv??{}},o=Object.entries(r.modelMap??{}).map(([e,t])=>({id:fd(),from:e,to:String(t)})),s={state:i,rows:o};if(t.aborted)throw Error(`Claude Code request aborted`);return l(i),d(o),p(!0),X(a,s),s},[e,a,n]),S=ps(o,[e],x,{isEmpty:()=>!1,enabled:t,initialData:s??void 0}),C=S.state,w=C.data??s,T=c??w?.state??null,E=f?u:w?.rows??u,D=(0,_.useMemo)(()=>td(T?.available,n(`claude.smallFastModelUnsetOption`)),[T?.available,n]),O=(0,_.useMemo)(()=>{let e=[1e5,2e5,25e4,3e5,35e4,4e5,5e5,6e5,75e4,9e5,1e6],t=T?.autoCompactWindow??null,r=t!==null&&!e.includes(t)?[...e,t].sort((e,t)=>e-t):e;return[{value:``,label:n(`claude.autoCompactDefault`)},...r.map(e=>({value:String(e),label:pd(e,i)}))]},[T?.autoCompactWindow,n,i]),k=async()=>{if(!T)return;h(``);let t={};for(let e of E)e.from.trim()&&e.to.trim()&&(t[e.from.trim()]=e.to.trim());try{await J(await fetch(`${e}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:T.enabled,authMode:T.authMode,systemEnv:T.systemEnv,fastMode:T.fastMode,autoContext:T.autoContext,autoCompactWindow:T.autoCompactWindow,injectAgents:T.injectAgents,smallFastModel:T.smallFastModel,modelMap:t,webSearchSidecar:cd(T.webSearchSidecar),visionSidecar:cd(T.visionSidecar)})}),n(`claude.saveFailed`)),v(!0),h(n(`claude.saved`)),S.refresh()}catch(e){v(!1),h(e instanceof Error&&e.message?e.message:n(`claude.networkError`))}};if(C.kind===`disabled`&&!w)return null;if(C.showSkeleton&&!w)return(0,z.jsx)(hs,{label:n(`claude.loading`),rows:3});if(C.kind===`failed-cold`)return(0,z.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[(0,z.jsx)(q,{tone:`err`,children:C.error instanceof Error?C.error.message:n(`claude.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>S.refresh(),children:n(`common.retry`)})]});if(!T)return null;let A=[{id:`settings`,label:n(`claude.workspace.settings`),body:(0,z.jsx)(hd,{state:T,autoCompactOptions:O,availableModels:T.available??[],onStateChange:l})},{id:`quickstart`,label:n(`claude.quickstart`),body:(0,z.jsx)(gd,{manualEnv:id(T)})},{id:`smallFast`,label:n(`claude.smallFastModel`),body:(0,z.jsx)(dd,{value:T.smallFastModel,tierHaikuModel:T.tierModels?.haiku,options:D,onChange:e=>l({...T,smallFastModel:e})})},{id:`modelMap`,label:n(`claude.modelMap`),meta:String(E.length),body:(0,z.jsx)(_d,{rows:E,onRowsChange:e=>{p(!0),d(e)}})},{id:`aliases`,label:n(`claude.aliases`),meta:String(T.aliases.length),body:(0,z.jsx)(yd,{aliases:T.aliases})}],j=A.find(e=>e.id===y)??A[0],M=y===`settings`||y===`smallFast`||y===`modelMap`;return(0,z.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[m&&(0,z.jsx)(q,{tone:g?`ok`:`err`,children:m}),C.showError&&(0,z.jsx)(q,{tone:`err`,children:n(`claude.loadFail`)}),(0,z.jsxs)(`div`,{className:`claudecode-workspace-root`,children:[(0,z.jsx)(`aside`,{className:`claudecode-workspace-rail`,"aria-label":n(`claude.pageTitle`),children:(0,z.jsx)(`div`,{className:`claudecode-workspace-rail-list`,children:A.map(e=>(0,z.jsx)(`button`,{type:`button`,className:`claudecode-workspace-rail-row${y===e.id?` claudecode-workspace-rail-row--selected`:``}`,onClick:()=>b(e.id),"aria-current":y===e.id?`true`:void 0,children:(0,z.jsx)(`span`,{className:`claudecode-workspace-rail-name`,children:e.label})},e.id))})}),(0,z.jsxs)(`section`,{className:`claudecode-workspace-main`,"aria-label":j.label,children:[(0,z.jsxs)(`div`,{className:`ccw-main-head`,children:[(0,z.jsxs)(`h3`,{className:`ccw-main-title`,children:[j.label,j.meta==null?null:(0,z.jsx)(`span`,{className:`count`,children:j.meta})]}),(0,z.jsx)(`div`,{className:`claudecode-workspace-save`,"data-visible":M?`true`:`false`,children:(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:!M,tabIndex:M?0:-1,"aria-hidden":!M,onClick:()=>{k()},children:n(`common.save`)})})]}),(0,z.jsx)(`div`,{className:`ccw-body`,children:j.body})]})]})]})}function xd(e,t,n){let r=t.trim().toLowerCase(),i=(r?e.filter(e=>e.label.toLowerCase().includes(r)||e.route.toLowerCase().includes(r)):e).toSorted((e,t)=>Number(!e.available)-Number(!t.available)),a=i.slice(0,n);return{total:e.length,showSearch:e.length>4,shown:a,hidden:i.length-a.length,noMatch:e.length>0&&i.length===0}}function Sd(e){return new Set(Object.keys(e))}function Cd(e,t){return t!==null&&e===t}function wd(e){return e||(typeof localStorage>`u`?void 0:localStorage)}function Td(e){return{read(t){let n=wd(t);if(!n)return null;try{let t=n.getItem(e);if(t===null)return null;let r=JSON.parse(t);return Array.isArray(r)?new Set(r.filter(e=>typeof e==`string`)):null}catch{return null}},write(t,n){let r=wd(n);if(r)try{r.setItem(e,JSON.stringify([...t]))}catch{}}}}function Ed(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}var Dd=[`opus`,`fable`,`sonnet`,`haiku`],Od=Td(`ocx.claudeDesktop.collapsedFamilies.v2`),kd={opus:`claudeDesktop.family.opus`,fable:`claudeDesktop.family.fable`,sonnet:`claudeDesktop.family.sonnet`,haiku:`claudeDesktop.family.haiku`};function Ad(e){return{version:1,assignments:Object.fromEntries(Object.entries(e.assignments).map(([e,t])=>[e,{...t}])),defaults:{...e.defaults},...e.appliedFingerprint===void 0?{}:{appliedFingerprint:e.appliedFingerprint},...e.appliedAt===void 0?{}:{appliedAt:e.appliedAt}}}function jd(e){let t={...e.profile.assignments};for(let n of e.models){let e=t[n.route]??n.assignment;t[n.route]={family:Dd.includes(e?.family)?e.family:`opus`,alias:typeof e?.alias==`string`?e.alias:``}}return{version:1,assignments:t,defaults:{opus:e.profile.defaults.opus??null,fable:e.profile.defaults.fable??null,sonnet:e.profile.defaults.sonnet??null,haiku:e.profile.defaults.haiku??null}}}function Md(e,t){return e&&typeof e==`object`&&`error`in e&&typeof e.error==`string`?e.error:t}function Nd(e,t){return e?e>=1048576?t(`claudeDesktop.contextM`,{n:Math.round(e/1048576)}):e>=1e6?t(`claudeDesktop.contextM`,{n:e/1e6}):t(`claudeDesktop.contextK`,{n:Math.round(e/1e3)}):null}function Pd(e){return Y(e)}function Fd(e){let t=Pd(e);return{held:t,data:t?.data??null,profile:t?.profile??null,savedProfile:t?.profile?Ad(t.profile):null,destinations:t?.data?Object.fromEntries(t.data.models.map(e=>[e.route,t.profile.assignments[e.route]?.family??`opus`])):{}}}function Id({apiBase:e,active:t=!0,onPortChange:n}){let{t:r,locale:i}=Ve(),a=Ie.find(e=>e.code===i)?.htmlLang,o=`ocx.claude-desktop.v1:${e}`,s=`claude-desktop:${e}`,c=(0,_.useMemo)(()=>Fd(o),[o]),[l,u]=(0,_.useState)(()=>c.profile),[d,f]=(0,_.useState)(()=>c.savedProfile),[p,m]=(0,_.useState)(()=>c.destinations),[h,g]=(0,_.useState)(null),[v,y]=(0,_.useState)(``),[b,x]=(0,_.useState)(null),[S,C]=(0,_.useState)({}),[w,T]=(0,_.useState)({}),[E,D]=(0,_.useState)(()=>Od.read()??new Set(Dd)),[O,k]=(0,_.useState)({}),A=(0,_.useRef)(null),j=(0,_.useCallback)(async t=>{let n=await J(await fetch(`${e}/api/claude-desktop`,{signal:t}),r(`claudeDesktop.loadFail`));if(!n||!(`profile`in n)||!(`models`in n))throw Error(Md(n,r(`claudeDesktop.loadFail`)));let i=jd(n),a={data:n,profile:i};if(t.aborted)throw Error(`Claude Desktop request aborted`);if(u(i),f(Ad(i)),m(Object.fromEntries(n.models.map(e=>[e.route,i.assignments[e.route]?.family??`opus`]))),Od.read()===null){let e=Object.fromEntries(Dd.map(e=>[e,0]));for(let t of n.models)e[i.assignments[t.route]?.family??`opus`]+=1;D(Sd(e))}return X(o,a),a},[e,o,r,m,u,f]),M=ps(s,[e],j,{isEmpty:()=>!1,enabled:t,initialData:c.held??void 0}),N=M.state,P=N.data??(c.data&&c.profile?{data:c.data,profile:c.profile}:null),F=P?.data??null,I=l??P?.profile??null,L=d??P?.profile??null,R=P?Object.fromEntries(P.data.models.map(e=>[e.route,P.profile.assignments[e.route]?.family??`opus`])):{},B=Object.keys(p).length>0?p:R;(0,_.useEffect)(()=>{if(n){if(typeof F?.port==`number`){n(F.port);return}N.kind===`failed-cold`&&n(null)}},[F?.port,N.kind,n]);let V=(0,_.useMemo)(()=>I!==null&&L!==null&&JSON.stringify(I)!==JSON.stringify(L),[I,L]),H=(0,_.useMemo)(()=>{let e=Object.fromEntries(Dd.map(e=>[e,[]]));if(!F||!I)return e;for(let t of F.models)e[I.assignments[t.route]?.family??`opus`].push(t);return e},[F,I]),U=(0,_.useMemo)(()=>{let e={};for(let t of Dd){let n=H[t].filter(e=>e.available).map(e=>e.route).sort(),r=I?.defaults[t]??null;e[t]=r&&n.includes(r)?r:n[0]??null}return e},[H,I]),W=`ocx.claude-desktop.status.v1:${e}`,ee=`claude-desktop-status:${e}`,te=Y(W),ne=ps(ee,[e],async t=>{let n=await ut(await fetch(`${e}/api/claude-desktop/status`,{signal:t}));if(!n)throw Error(`Claude Desktop status unavailable`);return X(W,n),n},{isEmpty:()=>!1,pollMs:5e3,enabled:t,initialData:te??void 0}),re=ne.state,G=re.data??te??null,ie=re.showError,ae=(e,t)=>{!I||I.assignments[e]?.family===t||(u(n=>{if(!n)return n;let r=n.assignments[e];if(!r||r.family===t)return n;let i={...n.assignments,[e]:{...r,family:t}},a={...n.defaults};return a[r.family]===e&&(a[r.family]=Object.keys(i).filter(t=>t!==e&&i[t].family===r.family).sort()[0]??null),a[t]===null&&(a[t]=e),{...n,assignments:i,defaults:a}}),m(n=>({...n,[e]:t})),y(r(`claudeDesktop.moved`,{route:e,family:r(kd[t])})))},oe=e=>{let t=Ed(E,e);Od.write(t),D(t)},se=async t=>{if(!(!I||b)){x(`save`),g(null);try{await J(await fetch(`${e}/api/claude-desktop`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({profile:I})}),r(`claudeDesktop.saveFailed`)),f(Ad(I)),t?(x(`apply`),await J(await fetch(`${e}/api/claude-desktop/apply`,{method:`POST`}),r(`claudeDesktop.applyFailed`)),g({tone:`ok`,text:r(`claudeDesktop.savedApplied`)}),y(r(`claudeDesktop.savedAppliedAnnounce`))):(g({tone:`ok`,text:r(`claudeDesktop.saved`)}),y(r(`claudeDesktop.savedAnnounce`))),ne.refresh()}catch(e){let t=e instanceof Error?e.message:r(`claudeDesktop.updateFailed`);g({tone:`err`,text:t}),y(t)}finally{x(null)}}},ce=()=>{if(!I)return;let e=URL.createObjectURL(new Blob([`${JSON.stringify(I,null,2)}\n`],{type:`application/json`})),t=document.createElement(`a`);t.href=e,t.download=`claude-desktop-profile.json`,t.click(),URL.revokeObjectURL(e),y(r(`claudeDesktop.exported`))},le=async e=>{let t=e.target.files?.[0];if(e.target.value=``,t)try{let e=JSON.parse(await t.text());if(e.version!==1||!e.assignments||!e.defaults)throw Error(r(`claudeDesktop.importExpected`));u(jd({...F,profile:e})),g({tone:`ok`,text:r(`claudeDesktop.importReady`)}),y(r(`claudeDesktop.importedAnnounce`))}catch(e){let t=e instanceof Error?e.message:r(`claudeDesktop.importInvalid`);g({tone:`err`,text:t}),y(r(`claudeDesktop.importFailed`,{error:t}))}},ue=(e,t)=>{e.preventDefault();let n=e.dataTransfer.getData(`text/plain`);n&&ae(n,t)};return N.kind===`disabled`&&!P?null:N.showSkeleton&&!P?(0,z.jsx)(hs,{label:r(`claudeDesktop.loading`),rows:4}):N.kind===`failed-cold`?(0,z.jsxs)(`div`,{className:`claude-desktop-error`,children:[(0,z.jsx)(q,{tone:`err`,children:N.error instanceof Error?N.error.message:r(`claudeDesktop.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>M.refresh(),children:r(`claudeDesktop.retry`)})]}):!F||!I?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`div`,{className:`claude-desktop-toolbar`,children:(0,z.jsxs)(`div`,{className:`claude-profile-tools`,children:[(0,z.jsx)(`input`,{ref:A,type:`file`,accept:`application/json,.json`,hidden:!0,onChange:e=>void le(e)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A.current?.click(),children:r(`claudeDesktop.importJson`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:ce,children:r(`claudeDesktop.exportJson`)})]})}),(0,z.jsxs)(`div`,{className:`claude-status-bar ${ie&&!G?`not-applied`:G?G.activeProfile===!1?`not-applied`:G.stale?`stale`:G.applied?`applied`:`not-applied`:`pending`}`,"aria-busy":!G&&!ie||void 0,children:[(0,z.jsx)(`span`,{className:`claude-status-dot`}),(0,z.jsx)(`span`,{children:ie&&!G?r(`claudeDesktop.loadFail`):G?G.activeProfile===!1?r(`claudeDesktop.status.notActiveProfile`):G.stale?r(`claudeDesktop.status.stale`):G.applied?r(`claudeDesktop.status.applied`):r(`claudeDesktop.status.notApplied`):r(`claudeDesktop.loading`)}),G?.health.lastRequestAt&&(0,z.jsxs)(`span`,{className:`claude-status-health`,children:[r(`claudeDesktop.health.lastRequest`),`:`,` `,new Date(G.health.lastRequestAt).toLocaleTimeString(a)]}),G&&G.health.requestCount>0&&(0,z.jsx)(`span`,{className:`claude-status-health`,children:r(`claudeDesktop.health.stats`,{count:G.health.requestCount,errors:G.health.errorCount})})]}),(0,z.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:v}),h&&(0,z.jsx)(q,{tone:h.tone,children:h.text}),N.showError&&(0,z.jsx)(q,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),ie&&G&&(0,z.jsx)(q,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),(0,z.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,z.jsx)(`span`,{className:`claude-dirty${V?` active`:``}`,children:r(V?`claudeDesktop.unsaved`:`claudeDesktop.upToDate`)}),(0,z.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!V||b!==null,onClick:()=>void se(!1),children:r(b===`save`?`claudeDesktop.saving`:`common.save`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:b!==null,onClick:()=>void se(!0),children:r(b===`apply`?`claudeDesktop.applying`:b===`save`?`claudeDesktop.saving`:`claudeDesktop.saveApply`)})]})]}),F.models.length===0&&(0,z.jsx)(ot,{title:r(`claudeDesktop.emptyTitle`),children:r(`claudeDesktop.emptyHint`)}),(0,z.jsx)(`div`,{className:`ocx-group-stack`,"aria-label":r(`claudeDesktop.assignmentsLabel`),children:Dd.map(e=>{let t=H[e],n=xd(t,S[e]??``,w[e]??6),i=E.has(e),a=U[e];return(0,z.jsxs)(`section`,{className:`ocx-group${i?` collapsed`:``}`,"aria-labelledby":`claude-lane-${e}`,onDragOver:e=>e.preventDefault(),onDrop:t=>ue(t,e),children:[(0,z.jsxs)(`header`,{className:`ocx-group-head${i?``:` open`}`,children:[(0,z.jsx)(`h3`,{id:`claude-lane-${e}`,className:`ocx-group-heading`,children:(0,z.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!i,"aria-controls":`claude-lane-body-${e}`,onClick:()=>oe(e),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:i?`none`:`rotate(90deg)`}}),(0,z.jsx)(`span`,{className:`ocx-group-name`,children:r(kd[e])}),(0,z.jsx)(`span`,{className:`ocx-group-count`,children:r(t.length===1?`claudeDesktop.modelCountOne`:`claudeDesktop.modelCountMany`,{count:t.length})}),a&&(0,z.jsx)(`code`,{className:`claude-lane-default`,title:a,children:a})]})}),t.length>0&&I.defaults[e]===null&&(0,z.jsx)(`span`,{className:`claude-default-needed`,children:r(`claudeDesktop.chooseDefault`)}),a&&a!==I.defaults[e]&&(0,z.jsx)(`span`,{className:`claude-default-needed`,title:a,children:r(`claudeDesktop.temporaryDefault`)})]}),!i&&(0,z.jsxs)(`div`,{id:`claude-lane-body-${e}`,children:[n.showSearch&&(0,z.jsx)(`input`,{className:`input claude-lane-search`,type:`search`,placeholder:r(`models.search`),"aria-label":r(`models.search`),value:S[e]??``,onChange:t=>{let n=t.target.value;C(t=>({...t,[e]:n})),T(t=>({...t,[e]:6}))}}),(0,z.jsxs)(`div`,{className:`claude-lane-models`,children:[t.length===0?(0,z.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneEmpty`)}):n.noMatch?(0,z.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneNoMatch`)}):n.shown.map(t=>{let n=I.assignments[t.route],i=Nd(t.contextWindow,r),a=B[t.route]??`opus`,o=O[t.route]??Cd(t.route,U[e]);return(0,z.jsxs)(`article`,{className:`claude-model-card${o?` open`:``}`,draggable:t.available,onDragStart:e=>{e.dataTransfer.effectAllowed=`move`,e.dataTransfer.setData(`text/plain`,t.route)},children:[(0,z.jsxs)(`button`,{type:`button`,className:`claude-model-summary`,"aria-expanded":o,"aria-controls":`claude-model-body-${t.route}`,onClick:()=>k(e=>({...e,[t.route]:!o})),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:12,height:12,"aria-hidden":`true`,style:{transform:o?`rotate(90deg)`:`none`}}),(0,z.jsxs)(`span`,{className:`claude-model-names`,children:[(0,z.jsx)(`strong`,{title:t.label,children:t.label}),(0,z.jsx)(`code`,{title:t.route,children:t.route})]}),i&&(0,z.jsx)(`span`,{className:`claude-model-context`,children:i}),!i&&(0,z.jsx)(`span`,{className:`claude-model-context claude-model-context-unknown`,children:r(`claudeDesktop.contextUnknown`)}),t.supports1m===!0&&(0,z.jsx)(`span`,{className:`claude-1m-chip`,children:r(`claudeDesktop.supports1m`)}),t.effortSupported===!1&&(0,z.jsx)(`span`,{className:`claude-effort-badge off`,children:r(`claudeDesktop.effort.displayOnly`)}),t.effortSupported===!0&&(0,z.jsx)(`span`,{className:`claude-effort-badge on`,children:r(`claudeDesktop.effort.supported`)}),I.defaults[e]===t.route&&(0,z.jsx)(`span`,{className:`claude-row-default`,children:r(`claudeDesktop.defaultBadge`)}),(0,z.jsx)(`span`,{className:`badge ${t.available?`badge-green`:`badge-muted`}`,children:t.available?r(`claudeDesktop.available`):r(`claudeDesktop.unavailable`)})]}),o&&(0,z.jsxs)(`div`,{className:`claude-model-body`,id:`claude-model-body-${t.route}`,children:[U[e]===t.route&&I.defaults[e]!==t.route&&(0,z.jsx)(`span`,{className:`claude-effective-default`,children:r(`claudeDesktop.temporaryDefault`)}),(0,z.jsxs)(`div`,{className:`claude-field`,children:[(0,z.jsx)(`span`,{children:r(`claudeDesktop.alias`)}),(0,z.jsx)(`code`,{className:`claude-alias`,title:n.alias,children:n.alias})]}),(0,z.jsxs)(`label`,{className:`claude-default-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`default-${e}`,checked:I.defaults[e]===t.route,disabled:!t.available,onChange:()=>u(n=>n&&{...n,defaults:{...n.defaults,[e]:t.route}})}),r(`claudeDesktop.useAsDefault`,{family:r(kd[e])})]}),(0,z.jsxs)(`div`,{className:`claude-move-row`,children:[(0,z.jsx)(`label`,{htmlFor:`move-${t.route}`,children:r(`claudeDesktop.moveTo`)}),(0,z.jsx)(`select`,{id:`move-${t.route}`,className:`input`,value:a,disabled:!t.available,onChange:e=>m(n=>({...n,[t.route]:e.target.value})),children:Dd.map(e=>(0,z.jsx)(`option`,{value:e,children:r(kd[e])},e))}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,disabled:!t.available||a===e,onClick:()=>ae(t.route,a),children:r(`claudeDesktop.move`)})]})]})]},t.route)}),n.hidden>0&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm claude-lane-more`,onClick:()=>T(t=>({...t,[e]:(t[e]??6)+6})),children:r(`models.showMore`,{n:n.hidden})})]})]})]},e)})})]})}function Ld(e){let t=Y(`ocx.claude-desktop.v1:${e}`);return typeof t?.data?.port==`number`?t.data.port:null}function Rd({apiBase:e}){let[t,n]=(0,_.useState)(`code`),r=K(),i=(0,_.useRef)(null),a=(0,_.useRef)(null),o=Ld(e),[s,c]=(0,_.useState)(null),l=s?.base===e?s.port:o,u=s?.base===e,d=(0,_.useCallback)(t=>{c(n=>n?.base===e&&n.port===t?n:{base:e,port:t})},[e]),f=e=>{n(e),window.requestAnimationFrame(()=>{(e===`code`?i:a).current?.focus({preventScroll:!0})})},p=e=>{e.key===`ArrowLeft`||e.key===`ArrowRight`?(e.preventDefault(),f(t===`code`?`desktop`:`code`)):e.key===`Home`?(e.preventDefault(),f(`code`)):e.key===`End`&&(e.preventDefault(),f(`desktop`))};return(0,z.jsxs)(`section`,{className:`claude-page`,children:[(0,z.jsxs)(`div`,{className:`claude-page-intro`,children:[(0,z.jsx)(`div`,{className:`page-head`,children:(0,z.jsx)(`h2`,{children:r(t===`code`?`claude.pageTitle`:`claudeDesktop.title`)})}),t===`code`?(0,z.jsx)(`p`,{className:`page-sub`,children:r(`claude.subtitle`)}):(0,z.jsx)(`p`,{className:`page-sub`,children:l==null?r(u?`claudeDesktop.loadFail`:`claudeDesktop.loading`):r(`claudeDesktop.subtitle`,{port:l})})]}),(0,z.jsxs)(`div`,{className:`claude-tabs`,role:`tablist`,"aria-label":r(`claude.tabsLabel`),children:[(0,z.jsx)(`button`,{type:`button`,role:`tab`,ref:i,"aria-selected":t===`code`,"aria-controls":`claude-code-panel`,id:`claude-code-tab`,className:t===`code`?`active`:``,tabIndex:t===`code`?0:-1,onKeyDown:p,onClick:()=>f(`code`),children:r(`claude.tabCode`)}),(0,z.jsx)(`button`,{type:`button`,role:`tab`,ref:a,"aria-selected":t===`desktop`,"aria-controls":`claude-desktop-panel`,id:`claude-desktop-tab`,className:t===`desktop`?`active`:``,tabIndex:t===`desktop`?0:-1,onKeyDown:p,onClick:()=>f(`desktop`),children:r(`claude.tabDesktop`)})]}),(0,z.jsx)(`div`,{id:`claude-code-panel`,role:`tabpanel`,"aria-labelledby":`claude-code-tab`,hidden:t!==`code`,children:(0,z.jsx)(bd,{apiBase:e,active:t===`code`},e)}),(0,z.jsx)(`div`,{id:`claude-desktop-panel`,role:`tabpanel`,"aria-labelledby":`claude-desktop-tab`,hidden:t!==`desktop`,children:(0,z.jsx)(Id,{apiBase:e,active:t===`desktop`,onPortChange:d},e)})]})}function zd(e,t,n,r){let i=e.filter(e=>r===`native`===e.native).map(e=>({...e,alias:t.get(e.id)??null,enabled:!n.has(e.id)})).toSorted((e,t)=>Number(!e.enabled)-Number(!t.enabled));return{rows:i,total:i.length,enabled:i.filter(e=>e.enabled).length}}var Bd=Td(`ocx.grok.collapsedGroups.v2`),Vd=[{id:`native`,tkey:`grok.groupNative`},{id:`routed`,tkey:`grok.groupRouted`}],Hd=new Set(Vd.map(e=>e.id));function Ud(e,t){return e?e>=1048576?t(`claudeDesktop.contextM`,{n:Math.round(e/1048576)}):e>=1e6?t(`claudeDesktop.contextM`,{n:e/1e6}):t(`claudeDesktop.contextK`,{n:Math.round(e/1e3)}):`—`}function Wd({apiBase:e}){let t=K(),n=`ocx.grok.status.v1:${e}`,r=Y(n),[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(()=>Bd.read()??new Set(Hd)),[c,l]=(0,_.useState)(null),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(``),m=(0,_.useCallback)(async()=>{let r=await J(await fetch(`${e}/api/grok`),t(`grok.loadFail`));if(!r)throw Error(t(`grok.loadFail`));let i={...r,candidates:r.candidates??[],excluded:r.excluded??[]};return X(n,i),i},[e,n,t]),h=`grok-status:${e}`,g=ps(h,[e],m,{isEmpty:()=>!1,initialData:r??void 0}),{state:v}=g,y=g.refresh,b=v.data??r,x=(0,_.useMemo)(()=>new Set(b?.excluded??[]),[b]),S=i??x,C=(0,_.useMemo)(()=>i!==null&&(i.size!==x.size||[...i].some(e=>!x.has(e))),[i,x]),w=(0,_.useMemo)(()=>new Map((b?.models??[]).map(e=>[e.id,e.alias])),[b]),T=e=>{let t=Ed(o,e);Bd.write(t),s(t)},E=e=>{let t=e?new Set(Vd.map(e=>e.id)):new Set;Bd.write(t),s(t)},D=(e,t)=>{a(n=>{let r=new Set(n??x);return t?r.delete(e):r.add(e),r})},O=async r=>{if(!c){l(`save`),d(null);try{await J(await fetch(`${e}/api/grok/selection`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({excluded:[...S]})}),t(`grok.saveFailed`));let i=[...S];if(b&&L(h,{...b,excluded:i}),a(null),r){l(`apply`);let n=await fetch(`${e}/api/grok/apply`,{method:`POST`});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.message??e.error??t(`grok.applyFailed`))}let r=await n.json().catch(()=>({}));r.skippedReason?(d({tone:`err`,text:r.message??t(`grok.applySkipped`)}),p(r.message??t(`grok.applySkipped`))):(d({tone:`ok`,text:t(`grok.savedApplied`)}),p(t(`grok.savedApplied`))),await y()}else d({tone:`ok`,text:t(`grok.saved`)}),p(t(`grok.saved`)),b&&X(n,{...b,excluded:i})}catch(e){let n=e instanceof Error?e.message:t(`grok.saveFailed`);d({tone:`err`,text:n}),p(n)}finally{l(null)}}};return v.showSkeleton&&!b?(0,z.jsx)(`section`,{className:`grok-page`,children:(0,z.jsx)(hs,{label:t(`grok.loading`),rows:4})}):v.kind===`failed-cold`?(0,z.jsxs)(`section`,{className:`grok-page`,children:[(0,z.jsx)(`div`,{className:`alert alert-err`,role:`alert`,children:v.error instanceof Error?v.error.message:t(`grok.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>y(),children:t(`common.retry`)})]}):(0,z.jsxs)(`section`,{className:`grok-page`,"aria-busy":v.refreshing||void 0,children:[(0,z.jsx)(`h2`,{className:`page-title`,children:t(`grok.title`)}),(0,z.jsx)(`p`,{className:`page-sub`,children:t(`grok.subtitle`)}),(0,z.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:f}),u&&(0,z.jsx)(q,{tone:u.tone,children:u.text}),v.showError&&(0,z.jsx)(q,{tone:`err`,children:t(`grok.loadFail`)}),b&&b.candidates.length>0&&(0,z.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,z.jsx)(`span`,{className:`claude-dirty${C?` active`:``}`,children:t(C?`grok.unsaved`:`grok.upToDate`)}),(0,z.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!C||c!==null,onClick:()=>void O(!1),children:t(c===`save`?`grok.saving`:`common.save`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:!C||c!==null,onClick:()=>void O(!0),children:t(c===`apply`?`grok.applying`:c===`save`?`grok.saving`:`grok.saveApply`)})]})]}),b?.present?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`grok-endpoint`,children:[(0,z.jsx)(`span`,{children:t(`grok.endpoint`)}),(0,z.jsx)(`code`,{children:b.baseUrl??`—`})]}),(0,z.jsx)(`p`,{className:`page-sub`,children:(0,z.jsx)(`code`,{children:b.configPath})})]}):(0,z.jsxs)(ot,{title:t(`grok.notConfiguredTitle`),children:[t(`grok.notConfiguredHint`),(0,z.jsx)(`br`,{}),(0,z.jsx)(`code`,{children:b?.configPath})]}),b&&b.candidates.length>0&&(0,z.jsxs)(`div`,{className:`ocx-group-stack`,children:[(0,z.jsxs)(`div`,{className:`row`,style:{gap:6,margin:`2px 0 10px`},children:[(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>E(!0),disabled:c!==null,children:[(0,z.jsx)(_e,{width:12,height:12,"aria-hidden":`true`}),` `,t(`models.collapseAll`)]}),(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>E(!1),disabled:c!==null,children:[(0,z.jsx)(_e,{width:12,height:12,"aria-hidden":`true`,style:{transform:`rotate(90deg)`}}),` `,t(`models.expandAll`)]})]}),Vd.map(e=>{let n=zd(b.candidates,w,S,e.id);if(n.total===0)return null;let r=o.has(e.id);return(0,z.jsxs)(`section`,{className:`ocx-group${r?` collapsed`:``}`,"aria-labelledby":`grok-group-${e.id}`,children:[(0,z.jsx)(`header`,{className:`ocx-group-head${r?``:` open`}`,children:(0,z.jsx)(`h3`,{id:`grok-group-${e.id}`,className:`ocx-group-heading`,children:(0,z.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!r,"aria-controls":`grok-group-body-${e.id}`,onClick:()=>T(e.id),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:r?`none`:`rotate(90deg)`}}),(0,z.jsx)(`span`,{className:`ocx-group-name`,children:t(e.tkey)}),(0,z.jsx)(`span`,{className:`ocx-group-count`,children:t(`grok.enabledCount`,{on:n.enabled,total:n.total})})]})})}),!r&&(0,z.jsx)(`div`,{id:`grok-group-body-${e.id}`,className:`grok-model-list`,children:n.rows.map(e=>(0,z.jsxs)(`div`,{className:`grok-model-row`,children:[(0,z.jsx)(it,{on:e.enabled,onClick:()=>D(e.id,!e.enabled),disabled:c!==null,label:t(`grok.toggleModel`,{id:e.id})}),(0,z.jsxs)(`span`,{className:`grok-model-names`,children:[(0,z.jsx)(`strong`,{title:e.id,children:e.id}),(0,z.jsx)(`code`,{title:e.alias??void 0,children:e.alias??`—`})]}),(0,z.jsx)(`span`,{className:`claude-model-context`,children:Ud(e.contextWindow,t)})]},e.id))})]},e.id)})]})]})}function Gd(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.supported==`boolean`&&typeof t.installed==`boolean`&&typeof t.running==`boolean`&&typeof t.stale==`boolean`&&typeof t.summary==`string`}var Kd={native:`startup.status.native`,protected:`startup.status.protected`,"at-risk":`startup.status.atRisk`},qd={native:`startup.summary.native`,protected:`startup.summary.protected`,"at-risk":`startup.summary.atRisk`},Jd={service:`startup.protection.service`,shim:`startup.protection.shim`,none:`startup.protection.none`};function Yd({ok:e,yes:t,no:n}){return(0,z.jsx)(`span`,{className:`badge ${e?`badge-green`:`badge-amber`}`,children:e?t:n})}function Xd({failed:e,data:t}){let{t:n}=Ve(),r=e?`startup-hero--risk`:t.status===`protected`?`startup-hero--safe`:t.status===`at-risk`?`startup-hero--risk`:`startup-hero--native`,i=e||t.status===`at-risk`?de:ie,a=t.routingKind===`opencodex-local`?`startup.routing.proxy`:t.routingKind===`custom-local`?`startup.routing.customLocal`:t.routingKind===`custom-remote`?`startup.routing.customRemote`:t.routingKind===`unknown`?`startup.routing.unknown`:`startup.routing.native`;return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`panel startup-hero ${r}`,"aria-live":`polite`,children:[(0,z.jsx)(`div`,{className:`startup-hero-icon`,children:(0,z.jsx)(i,{})}),(0,z.jsxs)(`div`,{className:`startup-hero-copy`,children:[(0,z.jsx)(`span`,{className:`badge ${e||t.status===`at-risk`?`badge-amber`:`badge-green`}`,children:n(e?`startup.status.atRisk`:Kd[t.status])}),(0,z.jsx)(`h3`,{children:n(e?`startup.error`:qd[t.status])}),(0,z.jsx)(`p`,{children:e?n(`startup.staleData`):t.status===`at-risk`?n(cn(t)):n(`startup.safeDetail`)})]})]}),(0,z.jsxs)(`div`,{className:`startup-state-grid`,children:[(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.routing`)}),(0,z.jsx)(`div`,{className:`value`,children:n(a)})]}),(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.restartProtection`)}),(0,z.jsx)(`div`,{className:`value`,children:n(Jd[t.protection])})]}),(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.preference`)}),(0,z.jsx)(`div`,{className:`value`,children:n(t.autostartEnabled?`startup.enabled`:`startup.disabled`)})]})]})]})}function Zd({data:e,failed:t,loading:n=!1,installBusy:r,installResult:i,onInstall:a}){let{t:o}=Ve(),s=e.serviceSupported&&e.serviceInstalled&&e.serviceStale&&!e.serviceConflict,c=e.shimInstalled&&!e.shimHealthy,l=r!==null||t||n;return(0,z.jsxs)(`section`,{className:`panel startup-details`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:o(`startup.details`)}),(0,z.jsx)(`span`,{className:`muted mono`,children:e.platform})]}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:o(`startup.service`)}),(0,z.jsx)(`span`,{children:o(`startup.serviceHint`)})]}),(0,z.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,z.jsx)(Yd,{ok:e.serviceViable,yes:o(`startup.viable`),no:o(e.serviceConflict?`startup.conflict`:e.serviceStale?`startup.stale`:e.serviceInstalled?`startup.unhealthy`:e.serviceSupported?`startup.notInstalled`:`startup.unsupported`)}),e.serviceSupported&&!e.serviceInstalled&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.service`)} - ${o(`startup.install`)}`,disabled:l,onClick:()=>a(`install-service`),children:o(r===`install-service`?`startup.installing`:`startup.install`)}),s&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.service`)} - ${o(`startup.repair`)}`,disabled:l,onClick:()=>a(`install-service`,{repair:!0}),children:o(r===`install-service`?`startup.repairing`:`startup.repair`)})]})]}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:o(`startup.shim`)}),(0,z.jsx)(`span`,{children:o(`startup.shimHint`)})]}),(0,z.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,z.jsx)(Yd,{ok:e.shimHealthy&&e.autostartEnabled,yes:o(e.shimCoverage===`cli-only`?`startup.cliOnly`:`startup.healthy`),no:o(e.shimInstalled?e.shimHealthy&&!e.autostartEnabled?`startup.installedDisabled`:`startup.stale`:`startup.notInstalled`)}),!e.shimInstalled&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.shim`)} - ${o(`startup.install`)}`,disabled:l,onClick:()=>a(`install-shim`),children:o(r===`install-shim`?`startup.installing`:`startup.install`)}),c&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.shim`)} - ${o(`startup.repair`)}`,disabled:l,onClick:()=>a(`install-shim`,{repair:!0}),children:o(r===`install-shim`?`startup.repairing`:`startup.repair`)})]})]}),i&&(0,z.jsx)(`div`,{className:`notice ${i.kind===`success`?`notice-ok`:`notice-warn`} startup-action-notice`,role:`status`,"aria-live":`polite`,children:i.kind===`success`?i.action===`install-service`?o(i.repair?`startup.serviceRepaired`:`startup.serviceInstalled`):o(i.repair?`startup.shimRepaired`:`startup.shimInstalled`):`${o(`startup.installFailed`)} ${i.detail??``}`})]})}function Qd({tray:e,trayLoading:t,trayError:n,trayBusy:r,onTrayAction:i}){let{t:a}=Ve();return(0,z.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:a(`startup.tray.title`)}),(0,z.jsx)(ye,{})]}),(0,z.jsx)(`p`,{className:`muted`,children:a(`startup.tray.hint`)}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:a(`startup.tray.login`)}),(0,z.jsx)(`span`,{children:a(`startup.tray.notProtection`)})]}),t||n||!e?(0,z.jsx)(`span`,{className:`badge badge-amber`,children:a(t?`startup.tray.loading`:`startup.tray.unavailable`)}):(0,z.jsx)(Yd,{ok:e.running&&!e.stale,yes:a(`startup.tray.running`),no:a(e.stale?`startup.tray.stale`:e.installed?`startup.tray.stopped`:`startup.tray.notInstalled`)})]}),(0,z.jsxs)(`div`,{className:`startup-tray-buttons`,children:[!t&&!n&&e&&!e.installed&&!e.stale&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:r,onClick:()=>i(`install`),children:a(`startup.tray.install`)}),!t&&!n&&e?.installed&&!e.stale&&!e.running&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:r,onClick:()=>i(`start`),children:a(`startup.tray.start`)}),!t&&!n&&e?.running&&!e.stale&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:r,onClick:()=>i(`stop`),children:a(`startup.tray.stop`)}),!t&&!n&&e&&(e.installed||e.stale)&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-danger`,disabled:r,onClick:()=>{window.confirm(a(`startup.tray.uninstall`))&&i(`uninstall`)},children:a(`startup.tray.uninstall`)})]}),(n||e?.stale)&&(0,z.jsx)(`div`,{className:`notice notice-warn startup-tray-error`,role:`alert`,children:a(`startup.tray.error`)})]})}function $d({data:e,copied:t,onCopy:n}){let{t:r}=Ve();return(0,z.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:r(`startup.recovery`)}),(0,z.jsx)(ne,{})]}),(0,z.jsx)(`p`,{className:`muted`,children:r(`startup.recoveryHint`)}),(0,z.jsxs)(`div`,{className:`startup-command-list`,children:[e.serviceSupported&&(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.service`)}),(0,z.jsx)(`code`,{children:e.commands.installService})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.installService),children:t===e.commands.installService?r(`startup.copied`):r(`startup.copy`)})]}),(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.shim`)}),(0,z.jsx)(`code`,{children:e.commands.installShim})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.installShim),children:t===e.commands.installShim?r(`startup.copied`):r(`startup.copy`)})]}),(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.native`)}),(0,z.jsx)(`code`,{children:e.commands.restoreNative})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.restoreNative),children:t===e.commands.restoreNative?r(`startup.copied`):r(`startup.copy`)})]})]}),e.status===`at-risk`&&(0,z.jsxs)(`div`,{className:`notice notice-warn startup-action-notice`,role:`alert`,children:[(0,z.jsx)(ye,{}),` `,r(`startup.recommended`,{cmd:e.recommendedCommand??e.commands.installService})]})]})}var ef=`ocx.startup.page.v1:`;function tf(e,t){let n=t===`win32`?`; `:` && `;return e.join(n)}function nf(e,t,n){if(!e)return{warning:null,fix:null};let r=!!e.catalogClamp?.active,i=!!e.newerAvailable,a=(r?e.catalogClamp?.runtimeVersion:e.version)??e.version??`unknown`,o=(e.catalogClamp?.removedEfforts??[]).join(`, `),s=tf([`ocx doctor --fix-codex-runtime`,`ocx sync`],n);return r?{warning:o?t(`startup.codexRuntime.clampHiddenWithEfforts`,{version:a,efforts:o}):t(`startup.codexRuntime.clampHidden`,{version:a}),fix:i?s:`ocx sync`}:i?{warning:t(`startup.codexRuntime.olderBinary`,{version:a}),fix:s}:{warning:null,fix:null}}function rf({apiBase:e}){let{t}=Ve(),n=`${ef}${e}`,r=(0,_.useMemo)(()=>Y(n),[n]),i=`startup-page:${e}`,[a,o]=(0,_.useState)(null),[s,c]=(0,_.useState)(()=>r?.tray??null),[l,u]=(0,_.useState)(()=>!r?.data),[d,f]=(0,_.useState)(!1),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(null),[v,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(()=>r?.warning??null),[S,C]=(0,_.useState)(()=>r?.fix??null),[w,T]=(0,_.useState)(()=>!r?.data),E=(0,_.useRef)(!!r?.data),D=(0,_.useCallback)(async r=>{let i=E.current;i||(u(!0),T(!0));try{let i=fetch(`${e}/api/settings`,{signal:r}).then(async e=>e.ok?await e.json():null).catch(()=>null),a=await fetch(`${e}/api/startup-health`,{signal:r});if(!a.ok)throw Error(`fetch failed`);let o=await a.json();E.current=!0;let s=Y(n);X(n,{data:o,warning:s?.warning??null,fix:s?.fix??null,tray:s?.tray??null});let l=o.platform===`win32`?fetch(`${e}/api/windows-tray`,{signal:r}).then(async e=>{if(!e.ok)throw Error(`tray status failed`);let t=await e.json();if(!Gd(t))throw Error(`invalid tray status`);return{tray:t,error:!1}}).catch(()=>({tray:null,error:!0})):Promise.resolve({tray:null,error:!1});return Promise.all([i,l]).then(([e,i])=>{if(r.aborted)return;let a=o.platform===`win32`?i.tray:null;if(o.platform===`win32`?(c(a),m(i.error)):(c(null),m(!1)),u(!1),T(!1),e){let r=nf(e.codexRuntime,t,o.platform);x(r.warning),C(r.fix),X(n,{data:o,warning:r.warning,fix:r.fix,tray:a});return}let s=Y(n);X(n,{data:o,warning:s?.warning??null,fix:s?.fix??null,tray:a})}),o}catch(e){throw r.aborted?e:(i||(c(null),m(!0),x(null),C(null)),T(!1),u(!1),e)}},[e,n,t]),O=ps(i,[e],D,{isEmpty:()=>!1,initialData:r?.data??void 0}),k=O.state,A=O.refresh,j=k.data??r?.data??null,M=k.refreshing,N=!!j?.diagnosticStale||k.showError;(0,_.useEffect)(()=>{if(!j?.diagnosticStale)return;let e=window.setTimeout(A,2e3);return()=>window.clearTimeout(e)},[j,A]);let P=async e=>{try{await navigator.clipboard.writeText(e),o(e),window.setTimeout(()=>o(t=>t===e?null:t),1600)}catch{o(null)}},F=async t=>{f(!0),m(!1);try{let n=await fetch(`${e}/api/windows-tray`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:t})});if(!n.ok)throw Error(`tray action failed`);let r=await n.json();if(!Gd(r.status))throw Error(`invalid tray action status`);c(r.status),m(!1)}catch{c(null),m(!0)}finally{f(!1)}},I=async(t,n)=>{g(t),y(null);try{let r=await fetch(`${e}/api/startup-action`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:t,repair:n?.repair===!0})});if(!r.ok){let e=await r.json().catch(()=>null);throw Error(typeof e?.error==`string`?e.error:`installation failed`)}y({kind:`success`,action:t,repair:n?.repair===!0}),A()}catch(e){y({kind:`error`,action:t,repair:n?.repair===!0,detail:e instanceof Error?e.message:String(e)})}finally{g(null)}};return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`page-head`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{children:t(`startup.title`)}),(0,z.jsx)(`p`,{className:`page-sub startup-page-sub`,children:t(`startup.subtitle`)})]}),(0,z.jsxs)(`div`,{className:`startup-page-head-actions`,children:[(0,z.jsx)(`a`,{className:`btn btn-ghost btn-sm`,href:`#dashboard`,children:t(`startup.backToDashboard`)}),(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),disabled:M,children:[(0,z.jsx)(se,{}),` `,t(`startup.refresh`)]})]})]}),k.showSkeleton&&!j?(0,z.jsx)(hs,{label:t(`startup.loading`),rows:5}):k.kind===`failed-cold`?(0,z.jsxs)(`div`,{className:`startup-page-notice`,children:[(0,z.jsx)(q,{tone:`err`,children:k.error instanceof Error?k.error.message:t(`startup.error`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),children:t(`common.retry`)})]}):j?(0,z.jsxs)(z.Fragment,{children:[k.showError&&(0,z.jsx)(q,{tone:`err`,children:t(`startup.error`)}),N&&(0,z.jsx)(`div`,{className:`notice notice-warn startup-page-notice`,role:`alert`,children:t(`startup.staleData`)}),(w||b)&&(0,z.jsx)(`div`,{className:`startup-runtime-notice-slot${w&&!b?` startup-runtime-notice-slot--pending`:``}`,"aria-hidden":w&&!b?!0:void 0,children:b&&(0,z.jsxs)(`div`,{className:`notice notice-warn startup-page-notice startup-runtime-notice`,role:`status`,children:[(0,z.jsx)(`p`,{className:`startup-runtime-notice__text`,children:b}),S&&(0,z.jsxs)(`div`,{className:`startup-runtime-notice__fix`,children:[(0,z.jsx)(`code`,{children:S}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>void P(S),children:t(a===S?`startup.copied`:`startup.copy`)})]})]})}),(0,z.jsx)(Xd,{failed:N,data:j}),(0,z.jsx)(Zd,{data:j,failed:N,loading:M,installBusy:h,installResult:v,onInstall:(e,t)=>{I(e,t)}}),j.platform===`win32`&&(0,z.jsx)(Qd,{tray:s,trayLoading:l,trayError:p,trayBusy:d,onTrayAction:e=>{F(e)}}),(0,z.jsx)($d,{data:j,copied:a,onCopy:e=>{P(e)}})]}):null]})}var af=class extends _.Component{state={error:null};static getDerivedStateFromError(e){return{error:e instanceof Error?e:Error(String(e))}}reload=()=>{this.setState({error:null})};render(){return this.state.error?(0,z.jsxs)(`section`,{className:`card`,role:`alert`,style:{maxWidth:720,padding:`var(--space-6)`},children:[(0,z.jsxs)(`h2`,{style:{margin:`0 0 var(--space-2)`,fontSize:`var(--text-title)`},children:[this.props.pageName,`: `,this.props.title]}),(0,z.jsx)(`p`,{className:`muted`,style:{margin:`0 0 var(--space-4)`},children:this.props.message}),(0,z.jsxs)(`p`,{style:{margin:`0 0 var(--space-5)`,overflowWrap:`anywhere`},children:[(0,z.jsxs)(`strong`,{children:[this.props.detailsLabel,`:`]}),` `,this.state.error.message]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:this.reload,children:this.props.reloadLabel})]}):this.props.children}},of=5*6e4,sf=10*6e4,cf=`https://github.com/lidge-jun/opencodex`;async function lf(e,t){let n=await fetch(e,{signal:t});return n.ok?await n.json():null}function uf({apiBase:e,onOpenUpdate:t}){let n=K(),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(null),s=I(`sidebar-star:${e}`,[e],t=>lf(`${e}/api/github/star`,t),{pollMs:of}),c=I(`sidebar-update-badge:${e}`,[e],t=>lf(`${e}/api/update/badge`,t),{pollMs:sf}),l=s.data?.state??null,u=a!==null&&a.basedOn===l?a.state:l??`not-starred`,d=s.data?.url??cf,f=u===`starred`,p=c.data,m=p?.updateAvailable===!0,h=p?.latestVersion??null,g=()=>window.open(d,`_blank`,`noopener,noreferrer`),v=async()=>{if(!(f||r)){if(u===`unauthenticated`){g();return}i(!0);try{let t=await fetch(`${e}/api/github/star`,{method:`POST`}),n=t.ok?await t.json():null;if(n?.ok===!0){o({state:`starred`,basedOn:l});return}n?.state&&o({state:n.state,basedOn:l}),g()}catch{g()}finally{i(!1),s.refresh()}}},y=n(f?`sidebar.starred`:u===`unauthenticated`?`sidebar.starUnauthenticated`:`sidebar.star`),b=m&&h?n(`sidebar.updateAvailable`,{version:h}):n(`sidebar.checkUpdate`);return(0,z.jsxs)(`div`,{className:`sidebar-github-row`,children:[(0,z.jsxs)(`a`,{className:`sidebar-link sidebar-github-link`,href:d,target:`_blank`,rel:`noreferrer`,children:[(0,z.jsx)(ve,{}),` `,n(`common.github`)]}),(0,z.jsxs)(`div`,{className:`sidebar-github-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`sidebar-orb${f?` sidebar-orb--starred`:``}`,onClick:()=>{v()},disabled:r||f,"aria-label":y,"aria-pressed":f,title:y,children:(0,z.jsx)(Me,{"aria-hidden":`true`,...f?{fill:`currentColor`}:{}})}),(0,z.jsxs)(`button`,{type:`button`,className:`sidebar-orb${m?` sidebar-orb--update`:``}`,onClick:t,"aria-label":b,title:b,children:[(0,z.jsx)(ge,{"aria-hidden":`true`}),m&&(0,z.jsx)(`span`,{className:`sidebar-orb-dot`,"aria-hidden":`true`})]})]})]})}var df=!1,ff=null,pf=null,mf=!1,hf=`/`;function gf(e){try{let t=e instanceof Request?e.url:String(e),n=new URL(t,window.location.href);return n.origin===window.location.origin?n.pathname.startsWith(`/api/`):!1}catch{return!1}}var _f=`opencodex-api-token`,vf=null,yf=null,bf=null;function xf(){return vf}function Sf(e){vf=e}function Cf(){vf=null,yf=null,bf=null}function wf(e){let t=document.querySelector(`meta[name="${e}"]`),n=t?.content.trim()||null;return t?.remove(),n}function Tf(){Df(wf(`opencodex-session-token`),wf(`opencodex-session-csrf`),wf(`opencodex-session-origin`))}function Ef(e){e!=null&&xf()===e&&Cf()}function Df(e,t,n){return!e?.startsWith(`ocx_session_`)||!t||n!==window.location.origin?!1:(vf=e,yf=t,bf=n,!0)}function Of(e,t){for(let n of e.match(/<meta\b[^>]*>/gi)??[])if(n.match(/\bname="([^"]+)"/i)?.[1]===t)return n.match(/\bcontent="([^"]*)"/i)?.[1]?.trim()||null;return null}async function kf(){if(!pf)return null;try{let e=await pf(hf,{cache:`no-store`});if(!e.ok)return null;let t=await e.text();return Df(Of(t,`opencodex-session-token`),Of(t,`opencodex-session-csrf`),Of(t,`opencodex-session-origin`))?xf():null}catch{return null}}function Af(){try{sessionStorage.removeItem(_f)}catch{}}function jf(e,t,n){let r=new Headers(t?.headers??(e instanceof Request?e.headers:void 0));if(r.set(`X-OpenCodex-API-Key`,n),bf&&yf&&n.startsWith(`ocx_session_`)){r.set(`X-OpenCodex-GUI-Origin`,bf);let n=(t?.method??(e instanceof Request?e.method:`GET`)).toUpperCase();n!==`GET`&&n!==`HEAD`&&r.set(`X-OpenCodex-CSRF-Token`,yf)}return e instanceof Request?[new Request(e,{headers:r}),t?{...t,headers:r}:void 0]:[e,{...t,headers:r}]}async function Mf(e){return mf?null:ff||(ff=(async()=>{if(mf)return null;let t=xf();if(t&&t!==e)return t;let n=await kf();if(n)return n;let r=window.prompt(`OpenCodex admin token (OPENCODEX_ADMIN_AUTH_TOKEN)`)?.trim()||null;return r?(Sf(r),r):(mf=!0,null)})().finally(()=>{ff=null}),ff)}function Nf(){if(df)return;df=!0,Af(),Tf();let e=window.fetch.bind(window);pf=e,window.fetch=async(t,n)=>{if(!gf(t))return e(t,n);let r=xf(),[i,a]=r?jf(t,n,r):[t,n],o=await e(i,a);if(o.status!==401)return o;let s=xf();if(s&&s!==r){let[r,i]=jf(t,n,s),a=await e(r,i);if(a.status!==401)return a;Ef(s)}else Ef(r);let c=await Mf(r);if(!c)return o;let[l,u]=jf(t,n,c),d=await e(l,u);return d.status===401&&Ef(c),d}}var Pf=new Set([`dashboard`,`startup`,`providers`,`models`,`combos`,`subagents`,`logs`,`usage`,`storage`,`codex-auth`,`api`,`claude`,`grok`]);function Ff(e){let t=We(e??(typeof window<`u`?window.location.hash:``)).split(`/`)[0];return t===`debug`?`logs`:Pf.has(t)?t:`dashboard`}var If=[`dashboard/providers`,`dashboard/models`];function Lf(e,t){return e===t||t===`logs`&&e===`logs/debug`||t===`dashboard`&&(e===`dashboard/update`||If.includes(e))}function Rf(e){let t=Ff(e);return e===`debug`||e.startsWith(`debug/`)?{page:`logs`,replaceTo:`logs/debug`}:e===`providers/workspace`?{page:`providers`,replaceTo:`providers`}:Lf(e,t)?{page:t,replaceTo:null}:{page:t,replaceTo:t}}var zf=[`ocx-global-view`,`ocx-view`,`ocx-providers-view`,`ocx-subagents-view`,`ocx-storage-view`,`ocx-codexauth-view`,`ocx-apikeys-view`,`ocx-claudecode-view`,`ocx-usage-view`,`ocx-logs-view`,`ocx-models-view`,`ocx-dashboard-view`];function Bf(){try{for(let e of zf)localStorage.removeItem(e)}catch{}}function Vf(){let[e,t]=(0,_.useState)(Ff);(0,_.useEffect)(()=>{Bf()},[]);let n=(0,_.useCallback)(e=>{let n=Rf(e);n.replaceTo&&Ge(n.replaceTo),t(n.page)},[]);return(0,_.useEffect)(()=>{let e=()=>{n(We(window.location.hash))};return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[n]),(0,_.useEffect)(()=>{let t=We(window.location.hash);if(t===`debug`||t.startsWith(`debug/`)){Ge(`logs/debug`);return}if(t===`providers/workspace`){Ge(`providers`);return}Lf(t,e)||Ge(e)},[e]),{page:e,setPageState:t,navigateToPage:(e,n)=>{Ke(n?`${e}/${n}`:e),t(e)}}}var Hf=15e3;function Uf(e,t,n){return typeof e?.message==`string`&&e.message.trim()?e.message:typeof e?.error==`string`&&e.error.trim()?e.error:n(t)}function Wf(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}async function Gf(e,t={}){let{fetchFn:n=fetch,timeoutMs:r=Hf,formatFailure:i=e=>`Failed to stop proxy (HTTP ${e}).`}=t,a;try{a=await n(`${e}/api/stop`,{method:`POST`,signal:AbortSignal.timeout(r)})}catch(e){return Wf(e),{accepted:!0}}let o=await a.json().catch(()=>null);return!a.ok||o?.success===!1?{accepted:!1,message:Uf(o,a.status,i)}:{accepted:!0}}Nf();var Kf={dashboard:`nav.dashboard`,startup:`nav.startup`,providers:`nav.providers`,models:`nav.models`,combos:`nav.combos`,subagents:`nav.subagents`,logs:`nav.logs`,usage:`nav.usage`,storage:`nav.storage`,"codex-auth":`nav.codexAuth`,api:`nav.api`,claude:`nav.claude`,grok:`nav.grok`},qf=``,Jf=`ocx-theme`,Yf=[{id:`dashboard`,tkey:`nav.dashboard`,Icon:V},{id:`codex-auth`,tkey:`nav.codexAuth`,Icon:xe},{id:`providers`,tkey:`nav.providers`,Icon:H},{id:`models`,tkey:`nav.models`,Icon:U},{id:`subagents`,tkey:`nav.subagents`,Icon:W},{id:`logs`,tkey:`nav.logs`,Icon:ee},{id:`usage`,tkey:`nav.usage`,Icon:re},{id:`storage`,tkey:`nav.storage`,Icon:G},{id:`api`,tkey:`nav.api`,Icon:Oe},{id:`claude`,tkey:`nav.claude`,Icon:ke},{id:`grok`,tkey:`nav.grok`,Icon:U}],Xf={light:Te,dark:Ee,system:De},Zf={light:`theme.light`,dark:`theme.dark`,system:`theme.system`};function Qf(e){if(!e||typeof e!=`object`||!(`version`in e))return null;let t=e.version;return typeof t==`string`&&t.length>0?t:null}function $f(){let e=localStorage.getItem(Jf);return e===`light`||e===`dark`?e:`system`}function ep(){let{page:e,navigateToPage:t}=Vf(),[n,r]=(0,_.useState)($f),{locale:i,setLocale:a}=Ve(),o=K(),[s,c]=(0,_.useState)(!1),l=(0,_.useRef)(null),u=(0,_.useRef)(null),d=(0,_.useRef)(!1);(0,_.useEffect)(()=>{let e=()=>c(!1);return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]),(0,_.useEffect)(()=>{let e=document.documentElement;n===`system`?(e.removeAttribute(`data-theme`),localStorage.removeItem(Jf)):(e.setAttribute(`data-theme`,n),localStorage.setItem(Jf,n))},[n]);let f=I(`app-healthz:${qf}`,[],async e=>{let t=await fetch(`${qf}/healthz`,{signal:e});return t.ok?Qf(await t.json()):null},{pollMs:3e4}),p=()=>r(e=>e===`light`?`dark`:e===`dark`?`system`:`light`),m=Xf[n],h=f.data??`2.8.0-cs.12`,[g,v]=(0,_.useState)(!1),y=(0,_.useCallback)(async e=>{let t=await ut(await fetch(`${qf}/api/claude-code`,{signal:e}));return t&&typeof t.enabled==`boolean`?t.enabled:null},[]),b=I(`app-claude-code:${qf}`,[],y).data??null,x=(0,_.useRef)(!1),[S,C]=(0,_.useState)(!1);(0,_.useEffect)(()=>{if(!s)return;let e=e=>{e.key===`Escape`&&c(!1)};window.addEventListener(`keydown`,e);let t=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{window.removeEventListener(`keydown`,e),document.body.style.overflow=t}},[s]),(0,_.useEffect)(()=>{if(s){d.current=!0;let e=setTimeout(()=>u.current?.focus(),200);return()=>clearTimeout(e)}d.current&&(d.current=!1,l.current?.focus())},[s]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 761px)`),t=()=>{e.matches&&c(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let w=async()=>{if(b===null||x.current)return;x.current=!0,C(!0);let e=!b;L(`app-claude-code:${qf}`,e);try{(await fetch(`${qf}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:e})})).ok||L(`app-claude-code:${qf}`,!e)}catch{L(`app-claude-code:${qf}`,!e)}finally{x.current=!1,C(!1)}},T=async()=>{if(!confirm(o(`dash.stopConfirm`)))return;v(!0);let e=await Gf(qf,{formatFailure:e=>o(`dash.stopFailed`,{status:String(e)})});e.accepted||(v(!1),alert(e.message))},E=(0,z.jsxs)(`div`,{className:`brand`,children:[(0,z.jsx)(`span`,{className:`brand-logo`,role:`img`,"aria-label":o(`app.logoAria`)}),(0,z.jsx)(`span`,{className:`name`,children:`opencodex`}),(0,z.jsxs)(`span`,{className:`ver`,children:[`v`,h]})]});return(0,z.jsxs)(`div`,{className:`app`,children:[(0,z.jsxs)(`header`,{className:`mobile-topbar`,inert:s,children:[(0,z.jsx)(`button`,{ref:l,type:`button`,className:`menu-toggle`,onClick:()=>c(e=>!e),"aria-expanded":s,"aria-controls":`app-sidebar`,"aria-label":o(s?`nav.closeMenu`:`nav.openMenu`),title:o(s?`nav.closeMenu`:`nav.openMenu`),children:(0,z.jsx)(te,{})}),E,(0,z.jsx)(`button`,{type:`button`,className:`theme-toggle stop-toggle`,onClick:T,disabled:g,"aria-label":o(`dash.stop`),title:o(`dash.stop`),children:(0,z.jsx)(ye,{})})]}),s&&(0,z.jsx)(`div`,{className:`drawer-scrim`,onClick:()=>c(!1),"aria-hidden":`true`}),(0,z.jsxs)(`aside`,{id:`app-sidebar`,className:`sidebar${s?` open`:``}`,ref:u,tabIndex:-1,children:[(0,z.jsxs)(`div`,{className:`drawer-head`,children:[E,(0,z.jsx)(`button`,{type:`button`,className:`menu-toggle drawer-close`,onClick:()=>c(!1),"aria-label":o(`nav.closeMenu`),title:o(`nav.closeMenu`),children:(0,z.jsx)(ae,{})})]}),(0,z.jsx)(`nav`,{children:Yf.map(({id:n,tkey:r,Icon:i})=>(0,z.jsxs)(`div`,{className:`nav-entry${n===`claude`?` nav-entry-claude${e===n?` active`:``}`:``}`,children:[(0,z.jsxs)(`button`,{type:`button`,className:`nav-item${e===n?` active`:``}`,"data-page":n,onClick:()=>{t(n),c(!1)},"aria-current":e===n?`page`:void 0,children:[(0,z.jsx)(i,{}),` `,o(r)]}),n===`claude`&&b!==null&&(0,z.jsx)(it,{on:b,onClick:()=>void w(),disabled:S,label:o(`claude.toggleAria`)})]},n))}),(0,z.jsxs)(`div`,{className:`sidebar-foot`,children:[(0,z.jsxs)(`div`,{className:`lang-toggle`,children:[(0,z.jsx)(Oe,{"aria-hidden":!0}),(0,z.jsx)(at,{value:i,options:Ie.map(e=>({value:e.code,label:e.name})),onChange:e=>a(e),label:o(`lang.label`),placement:`right`,portal:!1,style:{flex:1,minWidth:0,width:`100%`}})]}),(0,z.jsxs)(`button`,{type:`button`,className:`theme-toggle`,onClick:p,"aria-label":`${o(`theme.label`)}: ${o(Zf[n])}`,title:`${o(`theme.label`)}: ${o(Zf[n])}`,children:[(0,z.jsx)(m,{}),` `,(0,z.jsx)(`span`,{className:`mode`,children:o(Zf[n])})]}),(0,z.jsxs)(`button`,{type:`button`,className:`theme-toggle stop-toggle`,onClick:T,disabled:g,"aria-label":o(`dash.stop`),title:o(`dash.stop`),children:[(0,z.jsx)(ye,{}),` `,(0,z.jsx)(`span`,{className:`mode`,children:o(g?`dash.stopping`:`dash.stop`)})]}),(0,z.jsx)(uf,{apiBase:qf,onOpenUpdate:()=>{c(!1),t(`dashboard`,`update`)}})]})]}),(0,z.jsx)(`main`,{className:`main`,inert:s,children:(0,z.jsx)(`div`,{className:`main-inner${e===`combos`?` main-inner--combos`:``}`,children:(0,z.jsxs)(af,{pageName:o(Kf[e]),title:o(`errorBoundary.title`),message:o(`errorBoundary.message`),detailsLabel:o(`errorBoundary.details`),reloadLabel:o(`errorBoundary.reload`),children:[e===`dashboard`&&(0,z.jsx)(Fn,{apiBase:qf}),e===`startup`&&(0,z.jsx)(rf,{apiBase:qf}),e===`providers`&&(0,z.jsx)(Lo,{apiBase:qf}),e===`models`&&(0,z.jsx)(Us,{apiBase:qf}),e===`combos`&&(0,z.jsx)(sc,{apiBase:qf},qf),e===`subagents`&&(0,z.jsx)(_c,{apiBase:qf},qf),e===`logs`&&(0,z.jsx)(Fl,{apiBase:qf}),e===`usage`&&(0,z.jsx)(ru,{apiBase:qf}),e===`storage`&&(0,z.jsx)(bu,{apiBase:qf}),e===`codex-auth`&&(0,z.jsx)(wu,{apiBase:qf}),e===`api`&&(0,z.jsx)(ed,{apiBase:qf}),e===`claude`&&(0,z.jsx)(Rd,{apiBase:qf}),e===`grok`&&(0,z.jsx)(Wd,{apiBase:qf})]},e)})})]})}g.createRoot(document.getElementById(`root`)).render((0,z.jsx)(_.StrictMode,{children:(0,z.jsx)(He,{children:(0,z.jsx)(ep,{})})}));
|
|
67
|
+
`)}function ad(e){return e?e.backend??`auto`:`inherit`}function od(e,t){if(t!==`inherit`)return t===`auto`?{...e,backend:void 0}:{...e,backend:t}}function sd(e,t){return{...e,model:t}}function cd(e){if(!e)return null;let t=(e.model??``).trim();return e.backend?{backend:e.backend,model:t}:t?{backend:null,model:t}:null}function ld({label:e,checked:t,onChange:n,disabled:r=!1,describedBy:i}){return(0,z.jsxs)(`label`,{className:`toggle`,children:[(0,z.jsx)(`input`,{type:`checkbox`,checked:t,disabled:r,"aria-label":e,"aria-describedby":i,onChange:e=>n(e.target.checked)}),(0,z.jsx)(`span`,{className:`slider`,"aria-hidden":`true`})]})}function ud({supported:e,checked:t,onChange:n}){let r=K(),i=e?void 0:`claude-system-env-unsupported`;return(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:r(`claude.systemEnv`)}),e?(0,z.jsx)(`span`,{className:`desc`,children:r(`claude.systemEnvDesc`)}):(0,z.jsx)(`span`,{className:`desc`,id:i,children:(0,z.jsx)(Ue,{k:`claude.systemEnvUnsupported`,cmd:`ocx claude`})}),e&&t&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:r(`claude.systemEnvWarn`)})]}),(0,z.jsx)(ld,{label:r(`claude.systemEnv`),checked:e&&t,disabled:!e,describedBy:i,onChange:n})]})}function dd({value:e,tierHaikuModel:t,options:n,onChange:r}){let i=K(),a=t??e;return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:i(`claude.smallFastModelAccurateHint`)}),(0,z.jsx)(at,{value:e,options:n,onChange:r,label:i(`claude.smallFastModel`),style:{maxWidth:420}}),a===``&&(0,z.jsx)(`p`,{className:`notice-warn`,role:`status`,style:{marginTop:8},children:i(`claude.smallFastModelNativeWarning`)})]})}function fd(){if(typeof crypto<`u`&&typeof crypto.randomUUID==`function`)try{return crypto.randomUUID()}catch{}let e=new Uint8Array(16);if(typeof crypto<`u`&&typeof crypto.getRandomValues==`function`)crypto.getRandomValues(e);else for(let t=0;t<16;t++)e[t]=Math.floor(Math.random()*256);e[6]=e[6]&15|64,e[8]=e[8]&63|128;let t=Array.from(e,e=>e.toString(16).padStart(2,`0`)).join(``);return`${t.slice(0,8)}-${t.slice(8,12)}-${t.slice(12,16)}-${t.slice(16,20)}-${t.slice(20)}`}function pd(e,t=`en`){if(e>=1e6){let n=e/1e6,r=n.toFixed(1).replace(/\.0$/,``);return Number.isInteger(n)||Number(r)*1e6===e?new Intl.NumberFormat(t,{notation:`compact`,compactDisplay:`short`,maximumFractionDigits:+!Number.isInteger(n)}).format(e):`${Math.round(e/1e3)}k`}return`${Math.round(e/1e3)}k`}function md(e,t){return e&&[`claude-json-oauth`,`claude-credentials-file`,`macos-keychain`,`exported-env`].includes(e)?t(`claude.authSource.${e}`):t(`claude.authSource.unknown`)}function hd({state:e,autoCompactOptions:t,availableModels:n,onStateChange:r}){let i=K();return(0,z.jsxs)(`div`,{className:`card`,style:{overflow:`hidden`},children:[(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.enabledLabel`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.enabledHint`)})]}),(0,z.jsx)(ld,{label:i(`claude.enabledLabel`),checked:e.enabled,onChange:t=>r({...e,enabled:t})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.authMode`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.authModeHint`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.authMode,options:[{value:`auto`,label:i(`claude.authModeAuto`)},{value:`subscription`,label:i(`claude.authModeSubscription`)},{value:`proxy`,label:i(`claude.authModeProxy`)}],onChange:t=>r({...e,authMode:t}),label:i(`claude.authMode`),style:{minWidth:220},align:`right`,portal:!0})})]}),e.authModeOrigin&&(0,z.jsxs)(`div`,{className:`claude-effective-auth${e.authModeOrigin===`auto-unknown`?` warn`:``}`,role:`status`,children:[(0,z.jsx)(`span`,{className:`claude-effective-auth-label`,children:i(`claude.effectiveMode.label`)}),(0,z.jsxs)(`span`,{children:[e.authModeOrigin===`manual`?i(`claude.effectiveMode.manual`,{mode:e.markerMode===`proxy`?i(`claude.authModeProxy`):i(`claude.authModeSubscription`)}):e.authModeOrigin===`auto-present`?i(`claude.effectiveMode.autoPresent`,{source:md(e.authFoundBy,i)}):e.authModeOrigin===`auto-absent`?i(`claude.effectiveMode.autoAbsent`):i(`claude.effectiveMode.autoUnknown`),e.admissionKeyActive===!0?` ${i(`claude.effectiveMode.admissionKey`)}`:``]})]}),(0,z.jsx)(ud,{supported:e.autoConnectSupported,checked:e.systemEnv,onChange:t=>r({...e,systemEnv:t})}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.fastMode`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.fastModeDesc`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.fastMode===null?`auto`:e.fastMode?`on`:`off`,options:[{value:`auto`,label:i(`claude.fastAuto`)},{value:`on`,label:i(`claude.fastOn`)},{value:`off`,label:i(`claude.fastOff`)}],onChange:t=>r({...e,fastMode:t===`auto`?null:t===`on`}),label:i(`claude.fastMode`),style:{minWidth:140},align:`right`,portal:!0})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.autoContext`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.autoContextDesc`)}),e.maxContextTokens!==null&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--muted)`},children:i(`claude.autoContextInert`)})]}),(0,z.jsx)(ld,{label:i(`claude.autoContext`),checked:e.autoContext,onChange:t=>r({...e,autoContext:t})})]}),e.autoContext&&(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.autoCompactWindow`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.autoCompactWindowDesc`)}),e.autoCompactWindow!==null&&(0,z.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:i(`claude.autoCompactWindowWarn`)})]}),(0,z.jsx)(`div`,{className:`setting-controls`,children:(0,z.jsx)(at,{value:e.autoCompactWindow===null?``:String(e.autoCompactWindow),options:t,onChange:t=>r({...e,autoCompactWindow:t===``?null:Number(t)}),label:i(`claude.autoCompactWindow`),style:{minWidth:130},align:`right`,portal:!0})})]}),(0,z.jsxs)(`div`,{className:`setting-row`,children:[(0,z.jsxs)(`div`,{className:`setting-label`,children:[(0,z.jsx)(`span`,{className:`title`,children:i(`claude.injectAgents`)}),(0,z.jsx)(`span`,{className:`desc`,children:i(`claude.injectAgentsDesc`)})]}),(0,z.jsx)(ld,{label:i(`claude.injectAgents`),checked:e.injectAgents,onChange:t=>r({...e,injectAgents:t})})]}),[`webSearchSidecar`,`visionSidecar`].map(t=>{let a=e[t],o=t===`webSearchSidecar`?`claude.webSearchSidecar`:`claude.visionSidecar`,s=t===`webSearchSidecar`?`claude.webSearchSidecarHint`:`claude.visionSidecarHint`,c=`claude-sidecar-models-${t}`;return(0,z.jsxs)(`div`,{className:`setting-row`,style:{alignItems:`flex-start`},children:[(0,z.jsxs)(`div`,{className:`setting-label setting-copy`,style:{flex:1},children:[(0,z.jsx)(`span`,{className:`title`,children:i(o)}),(0,z.jsx)(`span`,{className:`desc`,children:i(s)})]}),(0,z.jsxs)(`div`,{className:`setting-controls`,style:{display:`flex`,gap:8},children:[(0,z.jsx)(at,{value:ad(a),options:[{value:`inherit`,label:i(`claude.useMainSetting`)},{value:`auto`,label:i(`dash.backendAuto`)},{value:`openai`,label:i(`dash.backendOpenAI`)},{value:`anthropic`,label:i(`dash.backendAnthropic`)}],onChange:n=>{r({...e,[t]:od(a,n)})},label:i(`dash.sidecarBackend`),portal:!0}),(0,z.jsx)(`input`,{className:`input mono`,value:a?.model??``,onChange:n=>{r({...e,[t]:sd(a,n.target.value)})},placeholder:i(`claude.sidecarModelPlaceholder`),disabled:!a,list:a?c:void 0,"aria-label":i(`dash.sidecarModel`),style:{minWidth:210},autoComplete:`off`}),a&&(0,z.jsx)(`datalist`,{id:c,children:n.map(e=>(0,z.jsx)(`option`,{value:e},e))})]})]},t)})]})}function gd({manualEnv:e}){let t=K();return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:(0,z.jsx)(Ue,{k:`claude.quickstartHint`,cmd:`ocx claude`})}),(0,z.jsx)(`pre`,{className:`mono card`,style:{padding:`10px 14px`,overflowX:`auto`,margin:0},children:`ocx claude`}),(0,z.jsxs)(`details`,{style:{margin:`10px 0 0`},children:[(0,z.jsx)(`summary`,{className:`muted text-label`,style:{cursor:`pointer`,padding:`2px 2px`},children:t(`claude.manualEnv`)}),(0,z.jsx)(`pre`,{className:`mono card text-label`,style:{padding:`10px 14px`,overflowX:`auto`,margin:`6px 0 0`},children:e})]})]})}function _d({rows:e,onRowsChange:t}){let n=K();return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:n(`claude.modelMapHint`)}),(0,z.jsx)(`div`,{className:`stack`,style:{gap:8},children:e.map((r,i)=>(0,z.jsxs)(`div`,{className:`row`,style:{gap:8},children:[(0,z.jsx)(`input`,{className:`input mono`,value:r.from,placeholder:n(`claude.mapFrom`),"aria-label":n(`claude.mapFrom`),onChange:n=>t(e.map((e,t)=>t===i?{...e,from:n.target.value}:e)),style:{flex:1}}),(0,z.jsx)(`span`,{className:`muted`,"aria-hidden":!0,children:`→`}),(0,z.jsx)(`input`,{className:`input mono`,value:r.to,placeholder:n(`claude.mapTo`),"aria-label":n(`claude.mapTo`),onChange:n=>t(e.map((e,t)=>t===i?{...e,to:n.target.value}:e)),style:{flex:1}}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-icon btn-sm`,onClick:()=>t(e.filter((e,t)=>t!==i)),"aria-label":n(`claude.removeMapping`),style:{color:`var(--red)`},children:(0,z.jsx)(ae,{})})]},r.id))}),(0,z.jsx)(`div`,{style:{marginTop:8},children:(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>t([...e,{id:fd(),from:``,to:``}]),children:[(0,z.jsx)(oe,{}),` `,n(`claude.addMapping`)]})})]})}var vd=`etc`;function $(e){let t=new Map;for(let n of e){let e=/\(([^)]+)\)\s*$/.exec(n.display_name),r=e?e[1]:vd,i=t.get(r);i?i.push(n):t.set(r,[n])}return Array.from(t)}function yd({aliases:e}){let t=K();return(0,z.jsxs)(`div`,{className:`claude-aliases`,children:[(0,z.jsx)(`p`,{className:`muted text-label claude-aliases-hint`,children:t(`claude.aliasesHint`)}),e.length===0?(0,z.jsx)(`div`,{className:`muted text-label`,children:t(`claude.none`)}):(0,z.jsx)(`div`,{className:`claude-aliases-scroll`,children:$(e).map(([e,n])=>(0,z.jsxs)(`div`,{className:`claude-aliases-group`,children:[(0,z.jsxs)(`div`,{className:`claude-aliases-group-label`,children:[e===vd?t(`claude.aliasProviderOther`):e,(0,z.jsx)(`span`,{className:`claude-aliases-group-count`,children:n.length})]}),(0,z.jsx)(`div`,{className:`claude-aliases-chips`,children:n.map(e=>(0,z.jsxs)(`span`,{className:`claude-aliases-chip`,children:[(0,z.jsx)(`code`,{className:`claude-aliases-chip-id`,children:e.id}),e.display_name?(0,z.jsx)(`span`,{className:`claude-aliases-chip-name`,children:e.display_name}):null]},e.id))})]},e))})]})}function bd({apiBase:e,active:t=!0}){let n=K(),{locale:r}=Ve(),i=Ie.find(e=>e.code===r)?.htmlLang??`en`,a=`ocx.claude-code.v1:${e}`,o=`claude-code:${e}`,s=(0,_.useMemo)(()=>Y(a),[a]),[c,l]=(0,_.useState)(()=>s?.state??null),[u,d]=(0,_.useState)(()=>s?.rows??[]),[f,p]=(0,_.useState)(!!s),[m,h]=(0,_.useState)(``),[g,v]=(0,_.useState)(!1),[y,b]=(0,_.useState)(`settings`),x=(0,_.useCallback)(async t=>{let r=await J(await fetch(`${e}/api/claude-code`,{signal:t}),n(`claude.loadFail`));if(!r)throw Error(n(`claude.loadFail`));let i={...r,authMode:r.authMode===`proxy`||r.authMode===`subscription`?r.authMode:`auto`,...nd(r),fastMode:r.fastMode??null,maxContextTokens:r.maxContextTokens??null,autoContext:r.autoContext!==!1,autoCompactWindow:r.autoCompactWindow??null,injectAgents:r.injectAgents!==!1,effectiveModelEnv:r.effectiveModelEnv??{}},o=Object.entries(r.modelMap??{}).map(([e,t])=>({id:fd(),from:e,to:String(t)})),s={state:i,rows:o};if(t.aborted)throw Error(`Claude Code request aborted`);return l(i),d(o),p(!0),X(a,s),s},[e,a,n]),S=ps(o,[e],x,{isEmpty:()=>!1,enabled:t,initialData:s??void 0}),C=S.state,w=C.data??s,T=c??w?.state??null,E=f?u:w?.rows??u,D=(0,_.useMemo)(()=>td(T?.available,n(`claude.smallFastModelUnsetOption`)),[T?.available,n]),O=(0,_.useMemo)(()=>{let e=[1e5,2e5,25e4,3e5,35e4,4e5,5e5,6e5,75e4,9e5,1e6],t=T?.autoCompactWindow??null,r=t!==null&&!e.includes(t)?[...e,t].sort((e,t)=>e-t):e;return[{value:``,label:n(`claude.autoCompactDefault`)},...r.map(e=>({value:String(e),label:pd(e,i)}))]},[T?.autoCompactWindow,n,i]),k=async()=>{if(!T)return;h(``);let t={};for(let e of E)e.from.trim()&&e.to.trim()&&(t[e.from.trim()]=e.to.trim());try{await J(await fetch(`${e}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:T.enabled,authMode:T.authMode,systemEnv:T.systemEnv,fastMode:T.fastMode,autoContext:T.autoContext,autoCompactWindow:T.autoCompactWindow,injectAgents:T.injectAgents,smallFastModel:T.smallFastModel,modelMap:t,webSearchSidecar:cd(T.webSearchSidecar),visionSidecar:cd(T.visionSidecar)})}),n(`claude.saveFailed`)),v(!0),h(n(`claude.saved`)),S.refresh()}catch(e){v(!1),h(e instanceof Error&&e.message?e.message:n(`claude.networkError`))}};if(C.kind===`disabled`&&!w)return null;if(C.showSkeleton&&!w)return(0,z.jsx)(hs,{label:n(`claude.loading`),rows:3});if(C.kind===`failed-cold`)return(0,z.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[(0,z.jsx)(q,{tone:`err`,children:C.error instanceof Error?C.error.message:n(`claude.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>S.refresh(),children:n(`common.retry`)})]});if(!T)return null;let A=[{id:`settings`,label:n(`claude.workspace.settings`),body:(0,z.jsx)(hd,{state:T,autoCompactOptions:O,availableModels:T.available??[],onStateChange:l})},{id:`quickstart`,label:n(`claude.quickstart`),body:(0,z.jsx)(gd,{manualEnv:id(T)})},{id:`smallFast`,label:n(`claude.smallFastModel`),body:(0,z.jsx)(dd,{value:T.smallFastModel,tierHaikuModel:T.tierModels?.haiku,options:D,onChange:e=>l({...T,smallFastModel:e})})},{id:`modelMap`,label:n(`claude.modelMap`),meta:String(E.length),body:(0,z.jsx)(_d,{rows:E,onRowsChange:e=>{p(!0),d(e)}})},{id:`aliases`,label:n(`claude.aliases`),meta:String(T.aliases.length),body:(0,z.jsx)(yd,{aliases:T.aliases})}],j=A.find(e=>e.id===y)??A[0],M=y===`settings`||y===`smallFast`||y===`modelMap`;return(0,z.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[m&&(0,z.jsx)(q,{tone:g?`ok`:`err`,children:m}),C.showError&&(0,z.jsx)(q,{tone:`err`,children:n(`claude.loadFail`)}),(0,z.jsxs)(`div`,{className:`claudecode-workspace-root`,children:[(0,z.jsx)(`aside`,{className:`claudecode-workspace-rail`,"aria-label":n(`claude.pageTitle`),children:(0,z.jsx)(`div`,{className:`claudecode-workspace-rail-list`,children:A.map(e=>(0,z.jsx)(`button`,{type:`button`,className:`claudecode-workspace-rail-row${y===e.id?` claudecode-workspace-rail-row--selected`:``}`,onClick:()=>b(e.id),"aria-current":y===e.id?`true`:void 0,children:(0,z.jsx)(`span`,{className:`claudecode-workspace-rail-name`,children:e.label})},e.id))})}),(0,z.jsxs)(`section`,{className:`claudecode-workspace-main`,"aria-label":j.label,children:[(0,z.jsxs)(`div`,{className:`ccw-main-head`,children:[(0,z.jsxs)(`h3`,{className:`ccw-main-title`,children:[j.label,j.meta==null?null:(0,z.jsx)(`span`,{className:`count`,children:j.meta})]}),(0,z.jsx)(`div`,{className:`claudecode-workspace-save`,"data-visible":M?`true`:`false`,children:(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:!M,tabIndex:M?0:-1,"aria-hidden":!M,onClick:()=>{k()},children:n(`common.save`)})})]}),(0,z.jsx)(`div`,{className:`ccw-body`,children:j.body})]})]})]})}function xd(e,t,n){let r=t.trim().toLowerCase(),i=(r?e.filter(e=>e.label.toLowerCase().includes(r)||e.route.toLowerCase().includes(r)):e).toSorted((e,t)=>Number(!e.available)-Number(!t.available)),a=i.slice(0,n);return{total:e.length,showSearch:e.length>4,shown:a,hidden:i.length-a.length,noMatch:e.length>0&&i.length===0}}function Sd(e){return new Set(Object.keys(e))}function Cd(e,t){return t!==null&&e===t}function wd(e){return e||(typeof localStorage>`u`?void 0:localStorage)}function Td(e){return{read(t){let n=wd(t);if(!n)return null;try{let t=n.getItem(e);if(t===null)return null;let r=JSON.parse(t);return Array.isArray(r)?new Set(r.filter(e=>typeof e==`string`)):null}catch{return null}},write(t,n){let r=wd(n);if(r)try{r.setItem(e,JSON.stringify([...t]))}catch{}}}}function Ed(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}var Dd=[`opus`,`fable`,`sonnet`,`haiku`],Od=Td(`ocx.claudeDesktop.collapsedFamilies.v2`),kd={opus:`claudeDesktop.family.opus`,fable:`claudeDesktop.family.fable`,sonnet:`claudeDesktop.family.sonnet`,haiku:`claudeDesktop.family.haiku`};function Ad(e){return{version:1,assignments:Object.fromEntries(Object.entries(e.assignments).map(([e,t])=>[e,{...t}])),defaults:{...e.defaults},...e.appliedFingerprint===void 0?{}:{appliedFingerprint:e.appliedFingerprint},...e.appliedAt===void 0?{}:{appliedAt:e.appliedAt}}}function jd(e){let t={...e.profile.assignments};for(let n of e.models){let e=t[n.route]??n.assignment;t[n.route]={family:Dd.includes(e?.family)?e.family:`opus`,alias:typeof e?.alias==`string`?e.alias:``}}return{version:1,assignments:t,defaults:{opus:e.profile.defaults.opus??null,fable:e.profile.defaults.fable??null,sonnet:e.profile.defaults.sonnet??null,haiku:e.profile.defaults.haiku??null}}}function Md(e,t){return e&&typeof e==`object`&&`error`in e&&typeof e.error==`string`?e.error:t}function Nd(e,t){return e?e>=1048576?t(`claudeDesktop.contextM`,{n:Math.round(e/1048576)}):e>=1e6?t(`claudeDesktop.contextM`,{n:e/1e6}):t(`claudeDesktop.contextK`,{n:Math.round(e/1e3)}):null}function Pd(e){return Y(e)}function Fd(e){let t=Pd(e);return{held:t,data:t?.data??null,profile:t?.profile??null,savedProfile:t?.profile?Ad(t.profile):null,destinations:t?.data?Object.fromEntries(t.data.models.map(e=>[e.route,t.profile.assignments[e.route]?.family??`opus`])):{}}}function Id({apiBase:e,active:t=!0,onPortChange:n}){let{t:r,locale:i}=Ve(),a=Ie.find(e=>e.code===i)?.htmlLang,o=`ocx.claude-desktop.v1:${e}`,s=`claude-desktop:${e}`,c=(0,_.useMemo)(()=>Fd(o),[o]),[l,u]=(0,_.useState)(()=>c.profile),[d,f]=(0,_.useState)(()=>c.savedProfile),[p,m]=(0,_.useState)(()=>c.destinations),[h,g]=(0,_.useState)(null),[v,y]=(0,_.useState)(``),[b,x]=(0,_.useState)(null),[S,C]=(0,_.useState)({}),[w,T]=(0,_.useState)({}),[E,D]=(0,_.useState)(()=>Od.read()??new Set(Dd)),[O,k]=(0,_.useState)({}),A=(0,_.useRef)(null),j=(0,_.useCallback)(async t=>{let n=await J(await fetch(`${e}/api/claude-desktop`,{signal:t}),r(`claudeDesktop.loadFail`));if(!n||!(`profile`in n)||!(`models`in n))throw Error(Md(n,r(`claudeDesktop.loadFail`)));let i=jd(n),a={data:n,profile:i};if(t.aborted)throw Error(`Claude Desktop request aborted`);if(u(i),f(Ad(i)),m(Object.fromEntries(n.models.map(e=>[e.route,i.assignments[e.route]?.family??`opus`]))),Od.read()===null){let e=Object.fromEntries(Dd.map(e=>[e,0]));for(let t of n.models)e[i.assignments[t.route]?.family??`opus`]+=1;D(Sd(e))}return X(o,a),a},[e,o,r,m,u,f]),M=ps(s,[e],j,{isEmpty:()=>!1,enabled:t,initialData:c.held??void 0}),N=M.state,P=N.data??(c.data&&c.profile?{data:c.data,profile:c.profile}:null),F=P?.data??null,I=l??P?.profile??null,L=d??P?.profile??null,R=P?Object.fromEntries(P.data.models.map(e=>[e.route,P.profile.assignments[e.route]?.family??`opus`])):{},B=Object.keys(p).length>0?p:R;(0,_.useEffect)(()=>{if(n){if(typeof F?.port==`number`){n(F.port);return}N.kind===`failed-cold`&&n(null)}},[F?.port,N.kind,n]);let V=(0,_.useMemo)(()=>I!==null&&L!==null&&JSON.stringify(I)!==JSON.stringify(L),[I,L]),H=(0,_.useMemo)(()=>{let e=Object.fromEntries(Dd.map(e=>[e,[]]));if(!F||!I)return e;for(let t of F.models)e[I.assignments[t.route]?.family??`opus`].push(t);return e},[F,I]),U=(0,_.useMemo)(()=>{let e={};for(let t of Dd){let n=H[t].filter(e=>e.available).map(e=>e.route).sort(),r=I?.defaults[t]??null;e[t]=r&&n.includes(r)?r:n[0]??null}return e},[H,I]),W=`ocx.claude-desktop.status.v1:${e}`,ee=`claude-desktop-status:${e}`,te=Y(W),ne=ps(ee,[e],async t=>{let n=await ut(await fetch(`${e}/api/claude-desktop/status`,{signal:t}));if(!n)throw Error(`Claude Desktop status unavailable`);return X(W,n),n},{isEmpty:()=>!1,pollMs:5e3,enabled:t,initialData:te??void 0}),re=ne.state,G=re.data??te??null,ie=re.showError,ae=(e,t)=>{!I||I.assignments[e]?.family===t||(u(n=>{if(!n)return n;let r=n.assignments[e];if(!r||r.family===t)return n;let i={...n.assignments,[e]:{...r,family:t}},a={...n.defaults};return a[r.family]===e&&(a[r.family]=Object.keys(i).filter(t=>t!==e&&i[t].family===r.family).sort()[0]??null),a[t]===null&&(a[t]=e),{...n,assignments:i,defaults:a}}),m(n=>({...n,[e]:t})),y(r(`claudeDesktop.moved`,{route:e,family:r(kd[t])})))},oe=e=>{let t=Ed(E,e);Od.write(t),D(t)},se=async t=>{if(!(!I||b)){x(`save`),g(null);try{await J(await fetch(`${e}/api/claude-desktop`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({profile:I})}),r(`claudeDesktop.saveFailed`)),f(Ad(I)),t?(x(`apply`),await J(await fetch(`${e}/api/claude-desktop/apply`,{method:`POST`}),r(`claudeDesktop.applyFailed`)),g({tone:`ok`,text:r(`claudeDesktop.savedApplied`)}),y(r(`claudeDesktop.savedAppliedAnnounce`))):(g({tone:`ok`,text:r(`claudeDesktop.saved`)}),y(r(`claudeDesktop.savedAnnounce`))),ne.refresh()}catch(e){let t=e instanceof Error?e.message:r(`claudeDesktop.updateFailed`);g({tone:`err`,text:t}),y(t)}finally{x(null)}}},ce=()=>{if(!I)return;let e=URL.createObjectURL(new Blob([`${JSON.stringify(I,null,2)}\n`],{type:`application/json`})),t=document.createElement(`a`);t.href=e,t.download=`claude-desktop-profile.json`,t.click(),URL.revokeObjectURL(e),y(r(`claudeDesktop.exported`))},le=async e=>{let t=e.target.files?.[0];if(e.target.value=``,t)try{let e=JSON.parse(await t.text());if(e.version!==1||!e.assignments||!e.defaults)throw Error(r(`claudeDesktop.importExpected`));u(jd({...F,profile:e})),g({tone:`ok`,text:r(`claudeDesktop.importReady`)}),y(r(`claudeDesktop.importedAnnounce`))}catch(e){let t=e instanceof Error?e.message:r(`claudeDesktop.importInvalid`);g({tone:`err`,text:t}),y(r(`claudeDesktop.importFailed`,{error:t}))}},ue=(e,t)=>{e.preventDefault();let n=e.dataTransfer.getData(`text/plain`);n&&ae(n,t)};return N.kind===`disabled`&&!P?null:N.showSkeleton&&!P?(0,z.jsx)(hs,{label:r(`claudeDesktop.loading`),rows:4}):N.kind===`failed-cold`?(0,z.jsxs)(`div`,{className:`claude-desktop-error`,children:[(0,z.jsx)(q,{tone:`err`,children:N.error instanceof Error?N.error.message:r(`claudeDesktop.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>M.refresh(),children:r(`claudeDesktop.retry`)})]}):!F||!I?null:(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(`div`,{className:`claude-desktop-toolbar`,children:(0,z.jsxs)(`div`,{className:`claude-profile-tools`,children:[(0,z.jsx)(`input`,{ref:A,type:`file`,accept:`application/json,.json`,hidden:!0,onChange:e=>void le(e)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A.current?.click(),children:r(`claudeDesktop.importJson`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:ce,children:r(`claudeDesktop.exportJson`)})]})}),(0,z.jsxs)(`div`,{className:`claude-status-bar ${ie&&!G?`not-applied`:G?G.activeProfile===!1?`not-applied`:G.stale?`stale`:G.applied?`applied`:`not-applied`:`pending`}`,"aria-busy":!G&&!ie||void 0,children:[(0,z.jsx)(`span`,{className:`claude-status-dot`}),(0,z.jsx)(`span`,{children:ie&&!G?r(`claudeDesktop.loadFail`):G?G.activeProfile===!1?r(`claudeDesktop.status.notActiveProfile`):G.stale?r(`claudeDesktop.status.stale`):G.applied?r(`claudeDesktop.status.applied`):r(`claudeDesktop.status.notApplied`):r(`claudeDesktop.loading`)}),G?.health.lastRequestAt&&(0,z.jsxs)(`span`,{className:`claude-status-health`,children:[r(`claudeDesktop.health.lastRequest`),`:`,` `,new Date(G.health.lastRequestAt).toLocaleTimeString(a)]}),G&&G.health.requestCount>0&&(0,z.jsx)(`span`,{className:`claude-status-health`,children:r(`claudeDesktop.health.stats`,{count:G.health.requestCount,errors:G.health.errorCount})})]}),(0,z.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:v}),h&&(0,z.jsx)(q,{tone:h.tone,children:h.text}),N.showError&&(0,z.jsx)(q,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),ie&&G&&(0,z.jsx)(q,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),(0,z.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,z.jsx)(`span`,{className:`claude-dirty${V?` active`:``}`,children:r(V?`claudeDesktop.unsaved`:`claudeDesktop.upToDate`)}),(0,z.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!V||b!==null,onClick:()=>void se(!1),children:r(b===`save`?`claudeDesktop.saving`:`common.save`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:b!==null,onClick:()=>void se(!0),children:r(b===`apply`?`claudeDesktop.applying`:b===`save`?`claudeDesktop.saving`:`claudeDesktop.saveApply`)})]})]}),F.models.length===0&&(0,z.jsx)(ot,{title:r(`claudeDesktop.emptyTitle`),children:r(`claudeDesktop.emptyHint`)}),(0,z.jsx)(`div`,{className:`ocx-group-stack`,"aria-label":r(`claudeDesktop.assignmentsLabel`),children:Dd.map(e=>{let t=H[e],n=xd(t,S[e]??``,w[e]??6),i=E.has(e),a=U[e];return(0,z.jsxs)(`section`,{className:`ocx-group${i?` collapsed`:``}`,"aria-labelledby":`claude-lane-${e}`,onDragOver:e=>e.preventDefault(),onDrop:t=>ue(t,e),children:[(0,z.jsxs)(`header`,{className:`ocx-group-head${i?``:` open`}`,children:[(0,z.jsx)(`h3`,{id:`claude-lane-${e}`,className:`ocx-group-heading`,children:(0,z.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!i,"aria-controls":`claude-lane-body-${e}`,onClick:()=>oe(e),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:i?`none`:`rotate(90deg)`}}),(0,z.jsx)(`span`,{className:`ocx-group-name`,children:r(kd[e])}),(0,z.jsx)(`span`,{className:`ocx-group-count`,children:r(t.length===1?`claudeDesktop.modelCountOne`:`claudeDesktop.modelCountMany`,{count:t.length})}),a&&(0,z.jsx)(`code`,{className:`claude-lane-default`,title:a,children:a})]})}),t.length>0&&I.defaults[e]===null&&(0,z.jsx)(`span`,{className:`claude-default-needed`,children:r(`claudeDesktop.chooseDefault`)}),a&&a!==I.defaults[e]&&(0,z.jsx)(`span`,{className:`claude-default-needed`,title:a,children:r(`claudeDesktop.temporaryDefault`)})]}),!i&&(0,z.jsxs)(`div`,{id:`claude-lane-body-${e}`,children:[n.showSearch&&(0,z.jsx)(`input`,{className:`input claude-lane-search`,type:`search`,placeholder:r(`models.search`),"aria-label":r(`models.search`),value:S[e]??``,onChange:t=>{let n=t.target.value;C(t=>({...t,[e]:n})),T(t=>({...t,[e]:6}))}}),(0,z.jsxs)(`div`,{className:`claude-lane-models`,children:[t.length===0?(0,z.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneEmpty`)}):n.noMatch?(0,z.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneNoMatch`)}):n.shown.map(t=>{let n=I.assignments[t.route],i=Nd(t.contextWindow,r),a=B[t.route]??`opus`,o=O[t.route]??Cd(t.route,U[e]);return(0,z.jsxs)(`article`,{className:`claude-model-card${o?` open`:``}`,draggable:t.available,onDragStart:e=>{e.dataTransfer.effectAllowed=`move`,e.dataTransfer.setData(`text/plain`,t.route)},children:[(0,z.jsxs)(`button`,{type:`button`,className:`claude-model-summary`,"aria-expanded":o,"aria-controls":`claude-model-body-${t.route}`,onClick:()=>k(e=>({...e,[t.route]:!o})),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:12,height:12,"aria-hidden":`true`,style:{transform:o?`rotate(90deg)`:`none`}}),(0,z.jsxs)(`span`,{className:`claude-model-names`,children:[(0,z.jsx)(`strong`,{title:t.label,children:t.label}),(0,z.jsx)(`code`,{title:t.route,children:t.route})]}),i&&(0,z.jsx)(`span`,{className:`claude-model-context`,children:i}),!i&&(0,z.jsx)(`span`,{className:`claude-model-context claude-model-context-unknown`,children:r(`claudeDesktop.contextUnknown`)}),t.supports1m===!0&&(0,z.jsx)(`span`,{className:`claude-1m-chip`,children:r(`claudeDesktop.supports1m`)}),t.effortSupported===!1&&(0,z.jsx)(`span`,{className:`claude-effort-badge off`,children:r(`claudeDesktop.effort.displayOnly`)}),t.effortSupported===!0&&(0,z.jsx)(`span`,{className:`claude-effort-badge on`,children:r(`claudeDesktop.effort.supported`)}),I.defaults[e]===t.route&&(0,z.jsx)(`span`,{className:`claude-row-default`,children:r(`claudeDesktop.defaultBadge`)}),(0,z.jsx)(`span`,{className:`badge ${t.available?`badge-green`:`badge-muted`}`,children:t.available?r(`claudeDesktop.available`):r(`claudeDesktop.unavailable`)})]}),o&&(0,z.jsxs)(`div`,{className:`claude-model-body`,id:`claude-model-body-${t.route}`,children:[U[e]===t.route&&I.defaults[e]!==t.route&&(0,z.jsx)(`span`,{className:`claude-effective-default`,children:r(`claudeDesktop.temporaryDefault`)}),(0,z.jsxs)(`div`,{className:`claude-field`,children:[(0,z.jsx)(`span`,{children:r(`claudeDesktop.alias`)}),(0,z.jsx)(`code`,{className:`claude-alias`,title:n.alias,children:n.alias})]}),(0,z.jsxs)(`label`,{className:`claude-default-radio`,children:[(0,z.jsx)(`input`,{type:`radio`,name:`default-${e}`,checked:I.defaults[e]===t.route,disabled:!t.available,onChange:()=>u(n=>n&&{...n,defaults:{...n.defaults,[e]:t.route}})}),r(`claudeDesktop.useAsDefault`,{family:r(kd[e])})]}),(0,z.jsxs)(`div`,{className:`claude-move-row`,children:[(0,z.jsx)(`label`,{htmlFor:`move-${t.route}`,children:r(`claudeDesktop.moveTo`)}),(0,z.jsx)(`select`,{id:`move-${t.route}`,className:`input`,value:a,disabled:!t.available,onChange:e=>m(n=>({...n,[t.route]:e.target.value})),children:Dd.map(e=>(0,z.jsx)(`option`,{value:e,children:r(kd[e])},e))}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,disabled:!t.available||a===e,onClick:()=>ae(t.route,a),children:r(`claudeDesktop.move`)})]})]})]},t.route)}),n.hidden>0&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm claude-lane-more`,onClick:()=>T(t=>({...t,[e]:(t[e]??6)+6})),children:r(`models.showMore`,{n:n.hidden})})]})]})]},e)})})]})}function Ld(e){let t=Y(`ocx.claude-desktop.v1:${e}`);return typeof t?.data?.port==`number`?t.data.port:null}function Rd({apiBase:e}){let[t,n]=(0,_.useState)(`code`),r=K(),i=(0,_.useRef)(null),a=(0,_.useRef)(null),o=Ld(e),[s,c]=(0,_.useState)(null),l=s?.base===e?s.port:o,u=s?.base===e,d=(0,_.useCallback)(t=>{c(n=>n?.base===e&&n.port===t?n:{base:e,port:t})},[e]),f=e=>{n(e),window.requestAnimationFrame(()=>{(e===`code`?i:a).current?.focus({preventScroll:!0})})},p=e=>{e.key===`ArrowLeft`||e.key===`ArrowRight`?(e.preventDefault(),f(t===`code`?`desktop`:`code`)):e.key===`Home`?(e.preventDefault(),f(`code`)):e.key===`End`&&(e.preventDefault(),f(`desktop`))};return(0,z.jsxs)(`section`,{className:`claude-page`,children:[(0,z.jsxs)(`div`,{className:`claude-page-intro`,children:[(0,z.jsx)(`div`,{className:`page-head`,children:(0,z.jsx)(`h2`,{children:r(t===`code`?`claude.pageTitle`:`claudeDesktop.title`)})}),t===`code`?(0,z.jsx)(`p`,{className:`page-sub`,children:r(`claude.subtitle`)}):(0,z.jsx)(`p`,{className:`page-sub`,children:l==null?r(u?`claudeDesktop.loadFail`:`claudeDesktop.loading`):r(`claudeDesktop.subtitle`,{port:l})})]}),(0,z.jsxs)(`div`,{className:`claude-tabs`,role:`tablist`,"aria-label":r(`claude.tabsLabel`),children:[(0,z.jsx)(`button`,{type:`button`,role:`tab`,ref:i,"aria-selected":t===`code`,"aria-controls":`claude-code-panel`,id:`claude-code-tab`,className:t===`code`?`active`:``,tabIndex:t===`code`?0:-1,onKeyDown:p,onClick:()=>f(`code`),children:r(`claude.tabCode`)}),(0,z.jsx)(`button`,{type:`button`,role:`tab`,ref:a,"aria-selected":t===`desktop`,"aria-controls":`claude-desktop-panel`,id:`claude-desktop-tab`,className:t===`desktop`?`active`:``,tabIndex:t===`desktop`?0:-1,onKeyDown:p,onClick:()=>f(`desktop`),children:r(`claude.tabDesktop`)})]}),(0,z.jsx)(`div`,{id:`claude-code-panel`,role:`tabpanel`,"aria-labelledby":`claude-code-tab`,hidden:t!==`code`,children:(0,z.jsx)(bd,{apiBase:e,active:t===`code`},e)}),(0,z.jsx)(`div`,{id:`claude-desktop-panel`,role:`tabpanel`,"aria-labelledby":`claude-desktop-tab`,hidden:t!==`desktop`,children:(0,z.jsx)(Id,{apiBase:e,active:t===`desktop`,onPortChange:d},e)})]})}function zd(e,t,n,r){let i=e.filter(e=>r===`native`===e.native).map(e=>({...e,alias:t.get(e.id)??null,enabled:!n.has(e.id)})).toSorted((e,t)=>Number(!e.enabled)-Number(!t.enabled));return{rows:i,total:i.length,enabled:i.filter(e=>e.enabled).length}}var Bd=Td(`ocx.grok.collapsedGroups.v2`),Vd=[{id:`native`,tkey:`grok.groupNative`},{id:`routed`,tkey:`grok.groupRouted`}],Hd=new Set(Vd.map(e=>e.id));function Ud(e,t){return e?e>=1048576?t(`claudeDesktop.contextM`,{n:Math.round(e/1048576)}):e>=1e6?t(`claudeDesktop.contextM`,{n:e/1e6}):t(`claudeDesktop.contextK`,{n:Math.round(e/1e3)}):`—`}function Wd({apiBase:e}){let t=K(),n=`ocx.grok.status.v1:${e}`,r=Y(n),[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(()=>Bd.read()??new Set(Hd)),[c,l]=(0,_.useState)(null),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(``),m=(0,_.useCallback)(async()=>{let r=await J(await fetch(`${e}/api/grok`),t(`grok.loadFail`));if(!r)throw Error(t(`grok.loadFail`));let i={...r,candidates:r.candidates??[],excluded:r.excluded??[]};return X(n,i),i},[e,n,t]),h=`grok-status:${e}`,g=ps(h,[e],m,{isEmpty:()=>!1,initialData:r??void 0}),{state:v}=g,y=g.refresh,b=v.data??r,x=(0,_.useMemo)(()=>new Set(b?.excluded??[]),[b]),S=i??x,C=(0,_.useMemo)(()=>i!==null&&(i.size!==x.size||[...i].some(e=>!x.has(e))),[i,x]),w=(0,_.useMemo)(()=>new Map((b?.models??[]).map(e=>[e.id,e.alias])),[b]),T=e=>{let t=Ed(o,e);Bd.write(t),s(t)},E=e=>{let t=e?new Set(Vd.map(e=>e.id)):new Set;Bd.write(t),s(t)},D=(e,t)=>{a(n=>{let r=new Set(n??x);return t?r.delete(e):r.add(e),r})},O=async r=>{if(!c){l(`save`),d(null);try{await J(await fetch(`${e}/api/grok/selection`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({excluded:[...S]})}),t(`grok.saveFailed`));let i=[...S];if(b&&L(h,{...b,excluded:i}),a(null),r){l(`apply`);let n=await fetch(`${e}/api/grok/apply`,{method:`POST`});if(!n.ok){let e=await n.json().catch(()=>({}));throw Error(e.message??e.error??t(`grok.applyFailed`))}let r=await n.json().catch(()=>({}));r.skippedReason?(d({tone:`err`,text:r.message??t(`grok.applySkipped`)}),p(r.message??t(`grok.applySkipped`))):(d({tone:`ok`,text:t(`grok.savedApplied`)}),p(t(`grok.savedApplied`))),await y()}else d({tone:`ok`,text:t(`grok.saved`)}),p(t(`grok.saved`)),b&&X(n,{...b,excluded:i})}catch(e){let n=e instanceof Error?e.message:t(`grok.saveFailed`);d({tone:`err`,text:n}),p(n)}finally{l(null)}}};return v.showSkeleton&&!b?(0,z.jsx)(`section`,{className:`grok-page`,children:(0,z.jsx)(hs,{label:t(`grok.loading`),rows:4})}):v.kind===`failed-cold`?(0,z.jsxs)(`section`,{className:`grok-page`,children:[(0,z.jsx)(`div`,{className:`alert alert-err`,role:`alert`,children:v.error instanceof Error?v.error.message:t(`grok.loadFail`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>y(),children:t(`common.retry`)})]}):(0,z.jsxs)(`section`,{className:`grok-page`,"aria-busy":v.refreshing||void 0,children:[(0,z.jsx)(`h2`,{className:`page-title`,children:t(`grok.title`)}),(0,z.jsx)(`p`,{className:`page-sub`,children:t(`grok.subtitle`)}),(0,z.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:f}),u&&(0,z.jsx)(q,{tone:u.tone,children:u.text}),v.showError&&(0,z.jsx)(q,{tone:`err`,children:t(`grok.loadFail`)}),b&&b.candidates.length>0&&(0,z.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,z.jsx)(`span`,{className:`claude-dirty${C?` active`:``}`,children:t(C?`grok.unsaved`:`grok.upToDate`)}),(0,z.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!C||c!==null,onClick:()=>void O(!1),children:t(c===`save`?`grok.saving`:`common.save`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:!C||c!==null,onClick:()=>void O(!0),children:t(c===`apply`?`grok.applying`:c===`save`?`grok.saving`:`grok.saveApply`)})]})]}),b?.present?(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`grok-endpoint`,children:[(0,z.jsx)(`span`,{children:t(`grok.endpoint`)}),(0,z.jsx)(`code`,{children:b.baseUrl??`—`})]}),(0,z.jsx)(`p`,{className:`page-sub`,children:(0,z.jsx)(`code`,{children:b.configPath})})]}):(0,z.jsxs)(ot,{title:t(`grok.notConfiguredTitle`),children:[t(`grok.notConfiguredHint`),(0,z.jsx)(`br`,{}),(0,z.jsx)(`code`,{children:b?.configPath})]}),b&&b.candidates.length>0&&(0,z.jsxs)(`div`,{className:`ocx-group-stack`,children:[(0,z.jsxs)(`div`,{className:`row`,style:{gap:6,margin:`2px 0 10px`},children:[(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>E(!0),disabled:c!==null,children:[(0,z.jsx)(_e,{width:12,height:12,"aria-hidden":`true`}),` `,t(`models.collapseAll`)]}),(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>E(!1),disabled:c!==null,children:[(0,z.jsx)(_e,{width:12,height:12,"aria-hidden":`true`,style:{transform:`rotate(90deg)`}}),` `,t(`models.expandAll`)]})]}),Vd.map(e=>{let n=zd(b.candidates,w,S,e.id);if(n.total===0)return null;let r=o.has(e.id);return(0,z.jsxs)(`section`,{className:`ocx-group${r?` collapsed`:``}`,"aria-labelledby":`grok-group-${e.id}`,children:[(0,z.jsx)(`header`,{className:`ocx-group-head${r?``:` open`}`,children:(0,z.jsx)(`h3`,{id:`grok-group-${e.id}`,className:`ocx-group-heading`,children:(0,z.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!r,"aria-controls":`grok-group-body-${e.id}`,onClick:()=>T(e.id),children:[(0,z.jsx)(_e,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:r?`none`:`rotate(90deg)`}}),(0,z.jsx)(`span`,{className:`ocx-group-name`,children:t(e.tkey)}),(0,z.jsx)(`span`,{className:`ocx-group-count`,children:t(`grok.enabledCount`,{on:n.enabled,total:n.total})})]})})}),!r&&(0,z.jsx)(`div`,{id:`grok-group-body-${e.id}`,className:`grok-model-list`,children:n.rows.map(e=>(0,z.jsxs)(`div`,{className:`grok-model-row`,children:[(0,z.jsx)(it,{on:e.enabled,onClick:()=>D(e.id,!e.enabled),disabled:c!==null,label:t(`grok.toggleModel`,{id:e.id})}),(0,z.jsxs)(`span`,{className:`grok-model-names`,children:[(0,z.jsx)(`strong`,{title:e.id,children:e.id}),(0,z.jsx)(`code`,{title:e.alias??void 0,children:e.alias??`—`})]}),(0,z.jsx)(`span`,{className:`claude-model-context`,children:Ud(e.contextWindow,t)})]},e.id))})]},e.id)})]})]})}function Gd(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.supported==`boolean`&&typeof t.installed==`boolean`&&typeof t.running==`boolean`&&typeof t.stale==`boolean`&&typeof t.summary==`string`}var Kd={native:`startup.status.native`,protected:`startup.status.protected`,"at-risk":`startup.status.atRisk`},qd={native:`startup.summary.native`,protected:`startup.summary.protected`,"at-risk":`startup.summary.atRisk`},Jd={service:`startup.protection.service`,shim:`startup.protection.shim`,none:`startup.protection.none`};function Yd({ok:e,yes:t,no:n}){return(0,z.jsx)(`span`,{className:`badge ${e?`badge-green`:`badge-amber`}`,children:e?t:n})}function Xd({failed:e,data:t}){let{t:n}=Ve(),r=e?`startup-hero--risk`:t.status===`protected`?`startup-hero--safe`:t.status===`at-risk`?`startup-hero--risk`:`startup-hero--native`,i=e||t.status===`at-risk`?de:ie,a=t.routingKind===`opencodex-local`?`startup.routing.proxy`:t.routingKind===`custom-local`?`startup.routing.customLocal`:t.routingKind===`custom-remote`?`startup.routing.customRemote`:t.routingKind===`unknown`?`startup.routing.unknown`:`startup.routing.native`;return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`section`,{className:`panel startup-hero ${r}`,"aria-live":`polite`,children:[(0,z.jsx)(`div`,{className:`startup-hero-icon`,children:(0,z.jsx)(i,{})}),(0,z.jsxs)(`div`,{className:`startup-hero-copy`,children:[(0,z.jsx)(`span`,{className:`badge ${e||t.status===`at-risk`?`badge-amber`:`badge-green`}`,children:n(e?`startup.status.atRisk`:Kd[t.status])}),(0,z.jsx)(`h3`,{children:n(e?`startup.error`:qd[t.status])}),(0,z.jsx)(`p`,{children:e?n(`startup.staleData`):t.status===`at-risk`?n(cn(t)):n(`startup.safeDetail`)})]})]}),(0,z.jsxs)(`div`,{className:`startup-state-grid`,children:[(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.routing`)}),(0,z.jsx)(`div`,{className:`value`,children:n(a)})]}),(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.restartProtection`)}),(0,z.jsx)(`div`,{className:`value`,children:n(Jd[t.protection])})]}),(0,z.jsxs)(`section`,{className:`stat`,children:[(0,z.jsx)(`div`,{className:`label`,children:n(`startup.preference`)}),(0,z.jsx)(`div`,{className:`value`,children:n(t.autostartEnabled?`startup.enabled`:`startup.disabled`)})]})]})]})}function Zd({data:e,failed:t,loading:n=!1,installBusy:r,installResult:i,onInstall:a}){let{t:o}=Ve(),s=e.serviceSupported&&e.serviceInstalled&&e.serviceStale&&!e.serviceConflict,c=e.shimInstalled&&!e.shimHealthy,l=r!==null||t||n;return(0,z.jsxs)(`section`,{className:`panel startup-details`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:o(`startup.details`)}),(0,z.jsx)(`span`,{className:`muted mono`,children:e.platform})]}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:o(`startup.service`)}),(0,z.jsx)(`span`,{children:o(`startup.serviceHint`)})]}),(0,z.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,z.jsx)(Yd,{ok:e.serviceViable,yes:o(`startup.viable`),no:o(e.serviceConflict?`startup.conflict`:e.serviceStale?`startup.stale`:e.serviceInstalled?`startup.unhealthy`:e.serviceSupported?`startup.notInstalled`:`startup.unsupported`)}),e.serviceSupported&&!e.serviceInstalled&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.service`)} - ${o(`startup.install`)}`,disabled:l,onClick:()=>a(`install-service`),children:o(r===`install-service`?`startup.installing`:`startup.install`)}),s&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.service`)} - ${o(`startup.repair`)}`,disabled:l,onClick:()=>a(`install-service`,{repair:!0}),children:o(r===`install-service`?`startup.repairing`:`startup.repair`)})]})]}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:o(`startup.shim`)}),(0,z.jsx)(`span`,{children:o(`startup.shimHint`)})]}),(0,z.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,z.jsx)(Yd,{ok:e.shimHealthy&&e.autostartEnabled,yes:o(e.shimCoverage===`cli-only`?`startup.cliOnly`:`startup.healthy`),no:o(e.shimInstalled?e.shimHealthy&&!e.autostartEnabled?`startup.installedDisabled`:`startup.stale`:`startup.notInstalled`)}),!e.shimInstalled&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.shim`)} - ${o(`startup.install`)}`,disabled:l,onClick:()=>a(`install-shim`),children:o(r===`install-shim`?`startup.installing`:`startup.install`)}),c&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,"aria-label":`${o(`startup.shim`)} - ${o(`startup.repair`)}`,disabled:l,onClick:()=>a(`install-shim`,{repair:!0}),children:o(r===`install-shim`?`startup.repairing`:`startup.repair`)})]})]}),i&&(0,z.jsx)(`div`,{className:`notice ${i.kind===`success`?`notice-ok`:`notice-warn`} startup-action-notice`,role:`status`,"aria-live":`polite`,children:i.kind===`success`?i.action===`install-service`?o(i.repair?`startup.serviceRepaired`:`startup.serviceInstalled`):o(i.repair?`startup.shimRepaired`:`startup.shimInstalled`):`${o(`startup.installFailed`)} ${i.detail??``}`})]})}function Qd({tray:e,trayLoading:t,trayError:n,trayBusy:r,onTrayAction:i}){let{t:a}=Ve();return(0,z.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:a(`startup.tray.title`)}),(0,z.jsx)(ye,{})]}),(0,z.jsx)(`p`,{className:`muted`,children:a(`startup.tray.hint`)}),(0,z.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:a(`startup.tray.login`)}),(0,z.jsx)(`span`,{children:a(`startup.tray.notProtection`)})]}),t||n||!e?(0,z.jsx)(`span`,{className:`badge badge-amber`,children:a(t?`startup.tray.loading`:`startup.tray.unavailable`)}):(0,z.jsx)(Yd,{ok:e.running&&!e.stale,yes:a(`startup.tray.running`),no:a(e.stale?`startup.tray.stale`:e.installed?`startup.tray.stopped`:`startup.tray.notInstalled`)})]}),(0,z.jsxs)(`div`,{className:`startup-tray-buttons`,children:[!t&&!n&&e&&!e.installed&&!e.stale&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:r,onClick:()=>i(`install`),children:a(`startup.tray.install`)}),!t&&!n&&e?.installed&&!e.stale&&!e.running&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:r,onClick:()=>i(`start`),children:a(`startup.tray.start`)}),!t&&!n&&e?.running&&!e.stale&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:r,onClick:()=>i(`stop`),children:a(`startup.tray.stop`)}),!t&&!n&&e&&(e.installed||e.stale)&&(0,z.jsx)(`button`,{type:`button`,className:`btn btn-danger`,disabled:r,onClick:()=>{window.confirm(a(`startup.tray.uninstall`))&&i(`uninstall`)},children:a(`startup.tray.uninstall`)})]}),(n||e?.stale)&&(0,z.jsx)(`div`,{className:`notice notice-warn startup-tray-error`,role:`alert`,children:a(`startup.tray.error`)})]})}function $d({data:e,copied:t,onCopy:n}){let{t:r}=Ve();return(0,z.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,z.jsxs)(`div`,{className:`panel-head`,children:[(0,z.jsx)(`h3`,{className:`panel-title`,children:r(`startup.recovery`)}),(0,z.jsx)(ne,{})]}),(0,z.jsx)(`p`,{className:`muted`,children:r(`startup.recoveryHint`)}),(0,z.jsxs)(`div`,{className:`startup-command-list`,children:[e.serviceSupported&&(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.service`)}),(0,z.jsx)(`code`,{children:e.commands.installService})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.installService),children:t===e.commands.installService?r(`startup.copied`):r(`startup.copy`)})]}),(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.shim`)}),(0,z.jsx)(`code`,{children:e.commands.installShim})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.installShim),children:t===e.commands.installShim?r(`startup.copied`):r(`startup.copy`)})]}),(0,z.jsxs)(`div`,{className:`startup-command-row`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`strong`,{children:r(`startup.command.native`)}),(0,z.jsx)(`code`,{children:e.commands.restoreNative})]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(e.commands.restoreNative),children:t===e.commands.restoreNative?r(`startup.copied`):r(`startup.copy`)})]})]}),e.status===`at-risk`&&(0,z.jsxs)(`div`,{className:`notice notice-warn startup-action-notice`,role:`alert`,children:[(0,z.jsx)(ye,{}),` `,r(`startup.recommended`,{cmd:e.recommendedCommand??e.commands.installService})]})]})}var ef=`ocx.startup.page.v1:`;function tf(e,t){let n=t===`win32`?`; `:` && `;return e.join(n)}function nf(e,t,n){if(!e)return{warning:null,fix:null};let r=!!e.catalogClamp?.active,i=!!e.newerAvailable,a=(r?e.catalogClamp?.runtimeVersion:e.version)??e.version??`unknown`,o=(e.catalogClamp?.removedEfforts??[]).join(`, `),s=tf([`ocx doctor --fix-codex-runtime`,`ocx sync`],n);return r?{warning:o?t(`startup.codexRuntime.clampHiddenWithEfforts`,{version:a,efforts:o}):t(`startup.codexRuntime.clampHidden`,{version:a}),fix:i?s:`ocx sync`}:i?{warning:t(`startup.codexRuntime.olderBinary`,{version:a}),fix:s}:{warning:null,fix:null}}function rf({apiBase:e}){let{t}=Ve(),n=`${ef}${e}`,r=(0,_.useMemo)(()=>Y(n),[n]),i=`startup-page:${e}`,[a,o]=(0,_.useState)(null),[s,c]=(0,_.useState)(()=>r?.tray??null),[l,u]=(0,_.useState)(()=>!r?.data),[d,f]=(0,_.useState)(!1),[p,m]=(0,_.useState)(!1),[h,g]=(0,_.useState)(null),[v,y]=(0,_.useState)(null),[b,x]=(0,_.useState)(()=>r?.warning??null),[S,C]=(0,_.useState)(()=>r?.fix??null),[w,T]=(0,_.useState)(()=>!r?.data),E=(0,_.useRef)(!!r?.data),D=(0,_.useCallback)(async r=>{let i=E.current;i||(u(!0),T(!0));try{let i=fetch(`${e}/api/settings`,{signal:r}).then(async e=>e.ok?await e.json():null).catch(()=>null),a=await fetch(`${e}/api/startup-health`,{signal:r});if(!a.ok)throw Error(`fetch failed`);let o=await a.json();E.current=!0;let s=Y(n);X(n,{data:o,warning:s?.warning??null,fix:s?.fix??null,tray:s?.tray??null});let l=o.platform===`win32`?fetch(`${e}/api/windows-tray`,{signal:r}).then(async e=>{if(!e.ok)throw Error(`tray status failed`);let t=await e.json();if(!Gd(t))throw Error(`invalid tray status`);return{tray:t,error:!1}}).catch(()=>({tray:null,error:!0})):Promise.resolve({tray:null,error:!1});return Promise.all([i,l]).then(([e,i])=>{if(r.aborted)return;let a=o.platform===`win32`?i.tray:null;if(o.platform===`win32`?(c(a),m(i.error)):(c(null),m(!1)),u(!1),T(!1),e){let r=nf(e.codexRuntime,t,o.platform);x(r.warning),C(r.fix),X(n,{data:o,warning:r.warning,fix:r.fix,tray:a});return}let s=Y(n);X(n,{data:o,warning:s?.warning??null,fix:s?.fix??null,tray:a})}),o}catch(e){throw r.aborted?e:(i||(c(null),m(!0),x(null),C(null)),T(!1),u(!1),e)}},[e,n,t]),O=ps(i,[e],D,{isEmpty:()=>!1,initialData:r?.data??void 0}),k=O.state,A=O.refresh,j=k.data??r?.data??null,M=k.refreshing,N=!!j?.diagnosticStale||k.showError;(0,_.useEffect)(()=>{if(!j?.diagnosticStale)return;let e=window.setTimeout(A,2e3);return()=>window.clearTimeout(e)},[j,A]);let P=async e=>{try{await navigator.clipboard.writeText(e),o(e),window.setTimeout(()=>o(t=>t===e?null:t),1600)}catch{o(null)}},F=async t=>{f(!0),m(!1);try{let n=await fetch(`${e}/api/windows-tray`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:t})});if(!n.ok)throw Error(`tray action failed`);let r=await n.json();if(!Gd(r.status))throw Error(`invalid tray action status`);c(r.status),m(!1)}catch{c(null),m(!0)}finally{f(!1)}},I=async(t,n)=>{g(t),y(null);try{let r=await fetch(`${e}/api/startup-action`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({action:t,repair:n?.repair===!0})});if(!r.ok){let e=await r.json().catch(()=>null);throw Error(typeof e?.error==`string`?e.error:`installation failed`)}y({kind:`success`,action:t,repair:n?.repair===!0}),A()}catch(e){y({kind:`error`,action:t,repair:n?.repair===!0,detail:e instanceof Error?e.message:String(e)})}finally{g(null)}};return(0,z.jsxs)(z.Fragment,{children:[(0,z.jsxs)(`div`,{className:`page-head`,children:[(0,z.jsxs)(`div`,{children:[(0,z.jsx)(`h2`,{children:t(`startup.title`)}),(0,z.jsx)(`p`,{className:`page-sub startup-page-sub`,children:t(`startup.subtitle`)})]}),(0,z.jsxs)(`div`,{className:`startup-page-head-actions`,children:[(0,z.jsx)(`a`,{className:`btn btn-ghost btn-sm`,href:`#dashboard`,children:t(`startup.backToDashboard`)}),(0,z.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),disabled:M,children:[(0,z.jsx)(se,{}),` `,t(`startup.refresh`)]})]})]}),k.showSkeleton&&!j?(0,z.jsx)(hs,{label:t(`startup.loading`),rows:5}):k.kind===`failed-cold`?(0,z.jsxs)(`div`,{className:`startup-page-notice`,children:[(0,z.jsx)(q,{tone:`err`,children:k.error instanceof Error?k.error.message:t(`startup.error`)}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),children:t(`common.retry`)})]}):j?(0,z.jsxs)(z.Fragment,{children:[k.showError&&(0,z.jsx)(q,{tone:`err`,children:t(`startup.error`)}),N&&(0,z.jsx)(`div`,{className:`notice notice-warn startup-page-notice`,role:`alert`,children:t(`startup.staleData`)}),(w||b)&&(0,z.jsx)(`div`,{className:`startup-runtime-notice-slot${w&&!b?` startup-runtime-notice-slot--pending`:``}`,"aria-hidden":w&&!b?!0:void 0,children:b&&(0,z.jsxs)(`div`,{className:`notice notice-warn startup-page-notice startup-runtime-notice`,role:`status`,children:[(0,z.jsx)(`p`,{className:`startup-runtime-notice__text`,children:b}),S&&(0,z.jsxs)(`div`,{className:`startup-runtime-notice__fix`,children:[(0,z.jsx)(`code`,{children:S}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>void P(S),children:t(a===S?`startup.copied`:`startup.copy`)})]})]})}),(0,z.jsx)(Xd,{failed:N,data:j}),(0,z.jsx)(Zd,{data:j,failed:N,loading:M,installBusy:h,installResult:v,onInstall:(e,t)=>{I(e,t)}}),j.platform===`win32`&&(0,z.jsx)(Qd,{tray:s,trayLoading:l,trayError:p,trayBusy:d,onTrayAction:e=>{F(e)}}),(0,z.jsx)($d,{data:j,copied:a,onCopy:e=>{P(e)}})]}):null]})}var af=class extends _.Component{state={error:null};static getDerivedStateFromError(e){return{error:e instanceof Error?e:Error(String(e))}}reload=()=>{this.setState({error:null})};render(){return this.state.error?(0,z.jsxs)(`section`,{className:`card`,role:`alert`,style:{maxWidth:720,padding:`var(--space-6)`},children:[(0,z.jsxs)(`h2`,{style:{margin:`0 0 var(--space-2)`,fontSize:`var(--text-title)`},children:[this.props.pageName,`: `,this.props.title]}),(0,z.jsx)(`p`,{className:`muted`,style:{margin:`0 0 var(--space-4)`},children:this.props.message}),(0,z.jsxs)(`p`,{style:{margin:`0 0 var(--space-5)`,overflowWrap:`anywhere`},children:[(0,z.jsxs)(`strong`,{children:[this.props.detailsLabel,`:`]}),` `,this.state.error.message]}),(0,z.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:this.reload,children:this.props.reloadLabel})]}):this.props.children}},of=5*6e4,sf=10*6e4,cf=`https://github.com/lidge-jun/opencodex`;async function lf(e,t){let n=await fetch(e,{signal:t});return n.ok?await n.json():null}function uf({apiBase:e,onOpenUpdate:t}){let n=K(),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(null),s=I(`sidebar-star:${e}`,[e],t=>lf(`${e}/api/github/star`,t),{pollMs:of}),c=I(`sidebar-update-badge:${e}`,[e],t=>lf(`${e}/api/update/badge`,t),{pollMs:sf}),l=s.data?.state??null,u=a!==null&&a.basedOn===l?a.state:l??`not-starred`,d=s.data?.url??cf,f=u===`starred`,p=c.data,m=p?.updateAvailable===!0,h=p?.latestVersion??null,g=()=>window.open(d,`_blank`,`noopener,noreferrer`),v=async()=>{if(!(f||r)){if(u===`unauthenticated`){g();return}i(!0);try{let t=await fetch(`${e}/api/github/star`,{method:`POST`}),n=t.ok?await t.json():null;if(n?.ok===!0){o({state:`starred`,basedOn:l});return}n?.state&&o({state:n.state,basedOn:l}),g()}catch{g()}finally{i(!1),s.refresh()}}},y=n(f?`sidebar.starred`:u===`unauthenticated`?`sidebar.starUnauthenticated`:`sidebar.star`),b=m&&h?n(`sidebar.updateAvailable`,{version:h}):n(`sidebar.checkUpdate`);return(0,z.jsxs)(`div`,{className:`sidebar-github-row`,children:[(0,z.jsxs)(`a`,{className:`sidebar-link sidebar-github-link`,href:d,target:`_blank`,rel:`noreferrer`,children:[(0,z.jsx)(ve,{}),` `,n(`common.github`)]}),(0,z.jsxs)(`div`,{className:`sidebar-github-actions`,children:[(0,z.jsx)(`button`,{type:`button`,className:`sidebar-orb${f?` sidebar-orb--starred`:``}`,onClick:()=>{v()},disabled:r||f,"aria-label":y,"aria-pressed":f,title:y,children:(0,z.jsx)(Me,{"aria-hidden":`true`,...f?{fill:`currentColor`}:{}})}),(0,z.jsxs)(`button`,{type:`button`,className:`sidebar-orb${m?` sidebar-orb--update`:``}`,onClick:t,"aria-label":b,title:b,children:[(0,z.jsx)(ge,{"aria-hidden":`true`}),m&&(0,z.jsx)(`span`,{className:`sidebar-orb-dot`,"aria-hidden":`true`})]})]})]})}var df=!1,ff=null,pf=null,mf=!1,hf=`/`;function gf(e){try{let t=e instanceof Request?e.url:String(e),n=new URL(t,window.location.href);return n.origin===window.location.origin?n.pathname.startsWith(`/api/`):!1}catch{return!1}}var _f=`opencodex-api-token`,vf=null,yf=null,bf=null;function xf(){return vf}function Sf(e){vf=e}function Cf(){vf=null,yf=null,bf=null}function wf(e){let t=document.querySelector(`meta[name="${e}"]`),n=t?.content.trim()||null;return t?.remove(),n}function Tf(){Df(wf(`opencodex-session-token`),wf(`opencodex-session-csrf`),wf(`opencodex-session-origin`))}function Ef(e){e!=null&&xf()===e&&Cf()}function Df(e,t,n){return!e?.startsWith(`ocx_session_`)||!t||n!==window.location.origin?!1:(vf=e,yf=t,bf=n,!0)}function Of(e,t){for(let n of e.match(/<meta\b[^>]*>/gi)??[])if(n.match(/\bname="([^"]+)"/i)?.[1]===t)return n.match(/\bcontent="([^"]*)"/i)?.[1]?.trim()||null;return null}async function kf(){if(!pf)return null;try{let e=await pf(hf,{cache:`no-store`});if(!e.ok)return null;let t=await e.text();return Df(Of(t,`opencodex-session-token`),Of(t,`opencodex-session-csrf`),Of(t,`opencodex-session-origin`))?xf():null}catch{return null}}function Af(){try{sessionStorage.removeItem(_f)}catch{}}function jf(e,t,n){let r=new Headers(t?.headers??(e instanceof Request?e.headers:void 0));if(r.set(`X-OpenCodex-API-Key`,n),bf&&yf&&n.startsWith(`ocx_session_`)){r.set(`X-OpenCodex-GUI-Origin`,bf);let n=(t?.method??(e instanceof Request?e.method:`GET`)).toUpperCase();n!==`GET`&&n!==`HEAD`&&r.set(`X-OpenCodex-CSRF-Token`,yf)}return e instanceof Request?[new Request(e,{headers:r}),t?{...t,headers:r}:void 0]:[e,{...t,headers:r}]}async function Mf(e){return mf?null:ff||(ff=(async()=>{if(mf)return null;let t=xf();if(t&&t!==e)return t;let n=await kf();if(n)return n;let r=window.prompt(`OpenCodex admin token (OPENCODEX_ADMIN_AUTH_TOKEN)`)?.trim()||null;return r?(Sf(r),r):(mf=!0,null)})().finally(()=>{ff=null}),ff)}function Nf(){if(df)return;df=!0,Af(),Tf();let e=window.fetch.bind(window);pf=e,window.fetch=async(t,n)=>{if(!gf(t))return e(t,n);let r=xf(),[i,a]=r?jf(t,n,r):[t,n],o=await e(i,a);if(o.status!==401)return o;let s=xf();if(s&&s!==r){let[r,i]=jf(t,n,s),a=await e(r,i);if(a.status!==401)return a;Ef(s)}else Ef(r);let c=await Mf(r);if(!c)return o;let[l,u]=jf(t,n,c),d=await e(l,u);return d.status===401&&Ef(c),d}}var Pf=new Set([`dashboard`,`startup`,`providers`,`models`,`combos`,`subagents`,`logs`,`usage`,`storage`,`codex-auth`,`api`,`claude`,`grok`]);function Ff(e){let t=We(e??(typeof window<`u`?window.location.hash:``)).split(`/`)[0];return t===`debug`?`logs`:Pf.has(t)?t:`dashboard`}var If=[`dashboard/providers`,`dashboard/models`];function Lf(e,t){return e===t||t===`logs`&&e===`logs/debug`||t===`dashboard`&&(e===`dashboard/update`||If.includes(e))}function Rf(e){let t=Ff(e);return e===`debug`||e.startsWith(`debug/`)?{page:`logs`,replaceTo:`logs/debug`}:e===`providers/workspace`?{page:`providers`,replaceTo:`providers`}:Lf(e,t)?{page:t,replaceTo:null}:{page:t,replaceTo:t}}var zf=[`ocx-global-view`,`ocx-view`,`ocx-providers-view`,`ocx-subagents-view`,`ocx-storage-view`,`ocx-codexauth-view`,`ocx-apikeys-view`,`ocx-claudecode-view`,`ocx-usage-view`,`ocx-logs-view`,`ocx-models-view`,`ocx-dashboard-view`];function Bf(){try{for(let e of zf)localStorage.removeItem(e)}catch{}}function Vf(){let[e,t]=(0,_.useState)(Ff);(0,_.useEffect)(()=>{Bf()},[]);let n=(0,_.useCallback)(e=>{let n=Rf(e);n.replaceTo&&Ge(n.replaceTo),t(n.page)},[]);return(0,_.useEffect)(()=>{let e=()=>{n(We(window.location.hash))};return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[n]),(0,_.useEffect)(()=>{let t=We(window.location.hash);if(t===`debug`||t.startsWith(`debug/`)){Ge(`logs/debug`);return}if(t===`providers/workspace`){Ge(`providers`);return}Lf(t,e)||Ge(e)},[e]),{page:e,setPageState:t,navigateToPage:(e,n)=>{Ke(n?`${e}/${n}`:e),t(e)}}}var Hf=15e3;function Uf(e,t,n){return typeof e?.message==`string`&&e.message.trim()?e.message:typeof e?.error==`string`&&e.error.trim()?e.error:n(t)}function Wf(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}async function Gf(e,t={}){let{fetchFn:n=fetch,timeoutMs:r=Hf,formatFailure:i=e=>`Failed to stop proxy (HTTP ${e}).`}=t,a;try{a=await n(`${e}/api/stop`,{method:`POST`,signal:AbortSignal.timeout(r)})}catch(e){return Wf(e),{accepted:!0}}let o=await a.json().catch(()=>null);return!a.ok||o?.success===!1?{accepted:!1,message:Uf(o,a.status,i)}:{accepted:!0}}Nf();var Kf={dashboard:`nav.dashboard`,startup:`nav.startup`,providers:`nav.providers`,models:`nav.models`,combos:`nav.combos`,subagents:`nav.subagents`,logs:`nav.logs`,usage:`nav.usage`,storage:`nav.storage`,"codex-auth":`nav.codexAuth`,api:`nav.api`,claude:`nav.claude`,grok:`nav.grok`},qf=``,Jf=`ocx-theme`,Yf=[{id:`dashboard`,tkey:`nav.dashboard`,Icon:V},{id:`codex-auth`,tkey:`nav.codexAuth`,Icon:xe},{id:`providers`,tkey:`nav.providers`,Icon:H},{id:`models`,tkey:`nav.models`,Icon:U},{id:`subagents`,tkey:`nav.subagents`,Icon:W},{id:`logs`,tkey:`nav.logs`,Icon:ee},{id:`usage`,tkey:`nav.usage`,Icon:re},{id:`storage`,tkey:`nav.storage`,Icon:G},{id:`api`,tkey:`nav.api`,Icon:Oe},{id:`claude`,tkey:`nav.claude`,Icon:ke},{id:`grok`,tkey:`nav.grok`,Icon:U}],Xf={light:Te,dark:Ee,system:De},Zf={light:`theme.light`,dark:`theme.dark`,system:`theme.system`};function Qf(e){if(!e||typeof e!=`object`||!(`version`in e))return null;let t=e.version;return typeof t==`string`&&t.length>0?t:null}function $f(){let e=localStorage.getItem(Jf);return e===`light`||e===`dark`?e:`system`}function ep(){let{page:e,navigateToPage:t}=Vf(),[n,r]=(0,_.useState)($f),{locale:i,setLocale:a}=Ve(),o=K(),[s,c]=(0,_.useState)(!1),l=(0,_.useRef)(null),u=(0,_.useRef)(null),d=(0,_.useRef)(!1);(0,_.useEffect)(()=>{let e=()=>c(!1);return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]),(0,_.useEffect)(()=>{let e=document.documentElement;n===`system`?(e.removeAttribute(`data-theme`),localStorage.removeItem(Jf)):(e.setAttribute(`data-theme`,n),localStorage.setItem(Jf,n))},[n]);let f=I(`app-healthz:${qf}`,[],async e=>{let t=await fetch(`${qf}/healthz`,{signal:e});return t.ok?Qf(await t.json()):null},{pollMs:3e4}),p=()=>r(e=>e===`light`?`dark`:e===`dark`?`system`:`light`),m=Xf[n],h=f.data??`2.8.0-cs.13`,[g,v]=(0,_.useState)(!1),y=(0,_.useCallback)(async e=>{let t=await ut(await fetch(`${qf}/api/claude-code`,{signal:e}));return t&&typeof t.enabled==`boolean`?t.enabled:null},[]),b=I(`app-claude-code:${qf}`,[],y).data??null,x=(0,_.useRef)(!1),[S,C]=(0,_.useState)(!1);(0,_.useEffect)(()=>{if(!s)return;let e=e=>{e.key===`Escape`&&c(!1)};window.addEventListener(`keydown`,e);let t=document.body.style.overflow;return document.body.style.overflow=`hidden`,()=>{window.removeEventListener(`keydown`,e),document.body.style.overflow=t}},[s]),(0,_.useEffect)(()=>{if(s){d.current=!0;let e=setTimeout(()=>u.current?.focus(),200);return()=>clearTimeout(e)}d.current&&(d.current=!1,l.current?.focus())},[s]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 761px)`),t=()=>{e.matches&&c(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let w=async()=>{if(b===null||x.current)return;x.current=!0,C(!0);let e=!b;L(`app-claude-code:${qf}`,e);try{(await fetch(`${qf}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:e})})).ok||L(`app-claude-code:${qf}`,!e)}catch{L(`app-claude-code:${qf}`,!e)}finally{x.current=!1,C(!1)}},T=async()=>{if(!confirm(o(`dash.stopConfirm`)))return;v(!0);let e=await Gf(qf,{formatFailure:e=>o(`dash.stopFailed`,{status:String(e)})});e.accepted||(v(!1),alert(e.message))},E=(0,z.jsxs)(`div`,{className:`brand`,children:[(0,z.jsx)(`span`,{className:`brand-logo`,role:`img`,"aria-label":o(`app.logoAria`)}),(0,z.jsx)(`span`,{className:`name`,children:`opencodex`}),(0,z.jsxs)(`span`,{className:`ver`,children:[`v`,h]})]});return(0,z.jsxs)(`div`,{className:`app`,children:[(0,z.jsxs)(`header`,{className:`mobile-topbar`,inert:s,children:[(0,z.jsx)(`button`,{ref:l,type:`button`,className:`menu-toggle`,onClick:()=>c(e=>!e),"aria-expanded":s,"aria-controls":`app-sidebar`,"aria-label":o(s?`nav.closeMenu`:`nav.openMenu`),title:o(s?`nav.closeMenu`:`nav.openMenu`),children:(0,z.jsx)(te,{})}),E,(0,z.jsx)(`button`,{type:`button`,className:`theme-toggle stop-toggle`,onClick:T,disabled:g,"aria-label":o(`dash.stop`),title:o(`dash.stop`),children:(0,z.jsx)(ye,{})})]}),s&&(0,z.jsx)(`div`,{className:`drawer-scrim`,onClick:()=>c(!1),"aria-hidden":`true`}),(0,z.jsxs)(`aside`,{id:`app-sidebar`,className:`sidebar${s?` open`:``}`,ref:u,tabIndex:-1,children:[(0,z.jsxs)(`div`,{className:`drawer-head`,children:[E,(0,z.jsx)(`button`,{type:`button`,className:`menu-toggle drawer-close`,onClick:()=>c(!1),"aria-label":o(`nav.closeMenu`),title:o(`nav.closeMenu`),children:(0,z.jsx)(ae,{})})]}),(0,z.jsx)(`nav`,{children:Yf.map(({id:n,tkey:r,Icon:i})=>(0,z.jsxs)(`div`,{className:`nav-entry${n===`claude`?` nav-entry-claude${e===n?` active`:``}`:``}`,children:[(0,z.jsxs)(`button`,{type:`button`,className:`nav-item${e===n?` active`:``}`,"data-page":n,onClick:()=>{t(n),c(!1)},"aria-current":e===n?`page`:void 0,children:[(0,z.jsx)(i,{}),` `,o(r)]}),n===`claude`&&b!==null&&(0,z.jsx)(it,{on:b,onClick:()=>void w(),disabled:S,label:o(`claude.toggleAria`)})]},n))}),(0,z.jsxs)(`div`,{className:`sidebar-foot`,children:[(0,z.jsxs)(`div`,{className:`lang-toggle`,children:[(0,z.jsx)(Oe,{"aria-hidden":!0}),(0,z.jsx)(at,{value:i,options:Ie.map(e=>({value:e.code,label:e.name})),onChange:e=>a(e),label:o(`lang.label`),placement:`right`,portal:!1,style:{flex:1,minWidth:0,width:`100%`}})]}),(0,z.jsxs)(`button`,{type:`button`,className:`theme-toggle`,onClick:p,"aria-label":`${o(`theme.label`)}: ${o(Zf[n])}`,title:`${o(`theme.label`)}: ${o(Zf[n])}`,children:[(0,z.jsx)(m,{}),` `,(0,z.jsx)(`span`,{className:`mode`,children:o(Zf[n])})]}),(0,z.jsxs)(`button`,{type:`button`,className:`theme-toggle stop-toggle`,onClick:T,disabled:g,"aria-label":o(`dash.stop`),title:o(`dash.stop`),children:[(0,z.jsx)(ye,{}),` `,(0,z.jsx)(`span`,{className:`mode`,children:o(g?`dash.stopping`:`dash.stop`)})]}),(0,z.jsx)(uf,{apiBase:qf,onOpenUpdate:()=>{c(!1),t(`dashboard`,`update`)}})]})]}),(0,z.jsx)(`main`,{className:`main`,inert:s,children:(0,z.jsx)(`div`,{className:`main-inner${e===`combos`?` main-inner--combos`:``}`,children:(0,z.jsxs)(af,{pageName:o(Kf[e]),title:o(`errorBoundary.title`),message:o(`errorBoundary.message`),detailsLabel:o(`errorBoundary.details`),reloadLabel:o(`errorBoundary.reload`),children:[e===`dashboard`&&(0,z.jsx)(Fn,{apiBase:qf}),e===`startup`&&(0,z.jsx)(rf,{apiBase:qf}),e===`providers`&&(0,z.jsx)(Lo,{apiBase:qf}),e===`models`&&(0,z.jsx)(Us,{apiBase:qf}),e===`combos`&&(0,z.jsx)(sc,{apiBase:qf},qf),e===`subagents`&&(0,z.jsx)(_c,{apiBase:qf},qf),e===`logs`&&(0,z.jsx)(Fl,{apiBase:qf}),e===`usage`&&(0,z.jsx)(ru,{apiBase:qf}),e===`storage`&&(0,z.jsx)(bu,{apiBase:qf}),e===`codex-auth`&&(0,z.jsx)(wu,{apiBase:qf}),e===`api`&&(0,z.jsx)(ed,{apiBase:qf}),e===`claude`&&(0,z.jsx)(Rd,{apiBase:qf}),e===`grok`&&(0,z.jsx)(Wd,{apiBase:qf})]},e)})})]})}g.createRoot(document.getElementById(`root`)).render((0,z.jsx)(_.StrictMode,{children:(0,z.jsx)(He,{children:(0,z.jsx)(ep,{})})}));
|
package/gui/dist/index.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
} catch (e) {}
|
|
17
17
|
})();
|
|
18
18
|
</script>
|
|
19
|
-
<script type="module" crossorigin src="/assets/index-
|
|
19
|
+
<script type="module" crossorigin src="/assets/index-BucjyD4I.js"></script>
|
|
20
20
|
<link rel="stylesheet" crossorigin href="/assets/index-CxisOo-q.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coseung2/opencodex",
|
|
3
|
-
"version": "2.8.0-cs.
|
|
3
|
+
"version": "2.8.0-cs.13",
|
|
4
4
|
"description": "Universal provider proxy for OpenAI Codex & Claude Code — use any LLM with Codex CLI/App/SDK and Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./bin/package-main.mjs",
|
|
@@ -52,7 +52,7 @@ Startup failures and Rust panics are written to the bounded diagnostic log `%LOC
|
|
|
52
52
|
- Click a provider with multiple accounts to expand or collapse its account rows.
|
|
53
53
|
- Click the pause icon beside an OpenAI account to exclude it from the rotation pool. A paused account shows a play icon that includes it again. The icon updates immediately and rolls back if OCX rejects the request.
|
|
54
54
|
- Accounts that require renewed credentials expose an inline **재인증** action on the same row. OpenAI's main account is intentionally excluded; eligible OpenAI pool and generic OAuth accounts can start, cancel, and retry browser authentication.
|
|
55
|
-
- Providers with quota data are shown first.
|
|
55
|
+
- Providers with quota data are shown first. Configured providers without quota data remain visible with their usage and account controls.
|
|
56
56
|
- Press **Esc** to collapse.
|
|
57
57
|
- Right-click to add a provider, set the real OCX account rotation threshold, fine-tune it by 1%, **Refresh**, or **Exit**. The opaque provider modal groups supported presets into Account, Free, and Paid tabs. Canonical OpenAI adds another Codex account, OAuth presets use browser/device authorization, and required-key presets use masked API-key entry. Fixed-endpoint key-optional presets (including OpenCode Free and MiMo Free) accept an empty key; entering a key instead adds a distinct account slot to OCX's existing key pool, which can be switched from the provider row. Ollama, vLLM, and LM Studio use local auth without a key. Cloudflare Workers AI also appears in Free and asks for its Account ID before creating the provider. Endpoint-choice and other unresolved placeholder-URL presets remain omitted because this compact modal cannot preserve those setup contracts safely. `Off` writes threshold `0`.
|
|
58
58
|
|
|
@@ -55,8 +55,10 @@ function isCredentialRecord(value: unknown): value is CodexAccountCredentialReco
|
|
|
55
55
|
&& (value.deletedAt === undefined || typeof value.deletedAt === "number")
|
|
56
56
|
&& (value.replacedAt === undefined || typeof value.replacedAt === "number")
|
|
57
57
|
&& (value.lastCodexValidatedAt === undefined || typeof value.lastCodexValidatedAt === "number")
|
|
58
|
-
&& (value.lastCodexValidationStatus === undefined || value.lastCodexValidationStatus === "ok" || value.lastCodexValidationStatus === "failed")
|
|
59
|
-
&& (value.lastCodexValidationError === undefined || typeof value.lastCodexValidationError === "string")
|
|
58
|
+
&& (value.lastCodexValidationStatus === undefined || value.lastCodexValidationStatus === "ok" || value.lastCodexValidationStatus === "failed" || value.lastCodexValidationStatus === "quota_pending")
|
|
59
|
+
&& (value.lastCodexValidationError === undefined || typeof value.lastCodexValidationError === "string")
|
|
60
|
+
&& (value.codexQuotaRetryAt === undefined || typeof value.codexQuotaRetryAt === "number")
|
|
61
|
+
&& (value.codexQuotaPauseOwned === undefined || typeof value.codexQuotaPauseOwned === "boolean");
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
export function refreshGrantFingerprintForToken(refreshToken: string): string {
|
|
@@ -113,12 +115,14 @@ function persist(store: CodexAccountStore): void {
|
|
|
113
115
|
|
|
114
116
|
function preservedValidationMetadata(record: CodexAccountCredentialRecord | undefined): Pick<
|
|
115
117
|
CodexAccountCredentialRecord,
|
|
116
|
-
"lastCodexValidatedAt" | "lastCodexValidationStatus" | "lastCodexValidationError"
|
|
118
|
+
"lastCodexValidatedAt" | "lastCodexValidationStatus" | "lastCodexValidationError" | "codexQuotaRetryAt" | "codexQuotaPauseOwned"
|
|
117
119
|
> {
|
|
118
120
|
return {
|
|
119
121
|
...(record?.lastCodexValidatedAt !== undefined ? { lastCodexValidatedAt: record.lastCodexValidatedAt } : {}),
|
|
120
122
|
...(record?.lastCodexValidationStatus !== undefined ? { lastCodexValidationStatus: record.lastCodexValidationStatus } : {}),
|
|
121
123
|
...(record?.lastCodexValidationError !== undefined ? { lastCodexValidationError: record.lastCodexValidationError } : {}),
|
|
124
|
+
...(record?.codexQuotaRetryAt !== undefined ? { codexQuotaRetryAt: record.codexQuotaRetryAt } : {}),
|
|
125
|
+
...(record?.codexQuotaPauseOwned !== undefined ? { codexQuotaPauseOwned: record.codexQuotaPauseOwned } : {}),
|
|
122
126
|
};
|
|
123
127
|
}
|
|
124
128
|
|
|
@@ -128,50 +132,97 @@ export function getCodexAccountCredential(id: string): CodexAccountCredentials |
|
|
|
128
132
|
return record.credential ?? null;
|
|
129
133
|
}
|
|
130
134
|
|
|
131
|
-
export function saveCodexAccountCredential(id: string, cred: CodexAccountCredentials):
|
|
132
|
-
withCredentialMutationLockSync(() => {
|
|
135
|
+
export function saveCodexAccountCredential(id: string, cred: CodexAccountCredentials): number {
|
|
136
|
+
return withCredentialMutationLockSync(() => {
|
|
133
137
|
const store = loadCodexAccountRecordStore();
|
|
134
138
|
const current = store[id];
|
|
135
139
|
const refreshGrantFingerprint = current?.credential?.refreshToken === cred.refreshToken
|
|
136
140
|
? current.refreshGrantFingerprint ?? refreshGrantFingerprintForToken(cred.refreshToken)
|
|
137
141
|
: refreshGrantFingerprintForToken(cred.refreshToken);
|
|
142
|
+
const generation = (current?.generation ?? 0) + 1;
|
|
138
143
|
store[id] = {
|
|
139
144
|
credential: cred,
|
|
140
|
-
generation
|
|
145
|
+
generation,
|
|
141
146
|
refreshGrantFingerprint,
|
|
142
147
|
replacedAt: current ? Date.now() : undefined,
|
|
143
148
|
...preservedValidationMetadata(current),
|
|
144
149
|
};
|
|
145
150
|
persist(store);
|
|
151
|
+
return generation;
|
|
146
152
|
});
|
|
147
153
|
}
|
|
148
154
|
|
|
149
|
-
export function markCodexAccountValidated(
|
|
150
|
-
|
|
155
|
+
export function markCodexAccountValidated(
|
|
156
|
+
id: string,
|
|
157
|
+
atMs: number = Date.now(),
|
|
158
|
+
expectedGeneration?: number,
|
|
159
|
+
): boolean {
|
|
160
|
+
return withCredentialMutationLockSync(() => {
|
|
151
161
|
const store = loadCodexAccountRecordStore();
|
|
152
162
|
const current = store[id];
|
|
153
|
-
if (!current || current.deletedAt != null || !current.credential
|
|
163
|
+
if (!current || current.deletedAt != null || !current.credential
|
|
164
|
+
|| (expectedGeneration !== undefined && current.generation !== expectedGeneration)) return false;
|
|
154
165
|
store[id] = {
|
|
155
166
|
...current,
|
|
156
167
|
lastCodexValidatedAt: atMs,
|
|
157
168
|
lastCodexValidationStatus: "ok",
|
|
158
169
|
lastCodexValidationError: undefined,
|
|
170
|
+
codexQuotaRetryAt: undefined,
|
|
171
|
+
codexQuotaPauseOwned: undefined,
|
|
159
172
|
};
|
|
160
173
|
persist(store);
|
|
174
|
+
return true;
|
|
161
175
|
});
|
|
162
176
|
}
|
|
163
177
|
|
|
164
|
-
export function
|
|
178
|
+
export function markCodexAccountQuotaValidationPending(
|
|
179
|
+
id: string,
|
|
180
|
+
reason: string,
|
|
181
|
+
retryAtMs: number | undefined,
|
|
182
|
+
): void {
|
|
165
183
|
withCredentialMutationLockSync(() => {
|
|
166
184
|
const store = loadCodexAccountRecordStore();
|
|
167
185
|
const current = store[id];
|
|
168
186
|
if (!current || current.deletedAt != null || !current.credential) return;
|
|
187
|
+
store[id] = {
|
|
188
|
+
...current,
|
|
189
|
+
lastCodexValidationStatus: "quota_pending",
|
|
190
|
+
lastCodexValidationError: reason,
|
|
191
|
+
...(retryAtMs !== undefined ? { codexQuotaRetryAt: retryAtMs } : {}),
|
|
192
|
+
codexQuotaPauseOwned: true,
|
|
193
|
+
};
|
|
194
|
+
persist(store);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function clearCodexAccountQuotaPauseOwnership(id: string): void {
|
|
199
|
+
withCredentialMutationLockSync(() => {
|
|
200
|
+
const store = loadCodexAccountRecordStore();
|
|
201
|
+
const current = store[id];
|
|
202
|
+
if (!current || current.codexQuotaPauseOwned === undefined) return;
|
|
203
|
+
store[id] = { ...current, codexQuotaPauseOwned: undefined };
|
|
204
|
+
persist(store);
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function markCodexAccountValidationFailed(
|
|
209
|
+
id: string,
|
|
210
|
+
reason: string,
|
|
211
|
+
expectedGeneration?: number,
|
|
212
|
+
): boolean {
|
|
213
|
+
return withCredentialMutationLockSync(() => {
|
|
214
|
+
const store = loadCodexAccountRecordStore();
|
|
215
|
+
const current = store[id];
|
|
216
|
+
if (!current || current.deletedAt != null || !current.credential
|
|
217
|
+
|| (expectedGeneration !== undefined && current.generation !== expectedGeneration)) return false;
|
|
169
218
|
store[id] = {
|
|
170
219
|
...current,
|
|
171
220
|
lastCodexValidationStatus: "failed",
|
|
172
221
|
lastCodexValidationError: reason,
|
|
222
|
+
codexQuotaRetryAt: undefined,
|
|
173
223
|
};
|
|
174
224
|
persist(store);
|
|
225
|
+
return true;
|
|
175
226
|
});
|
|
176
227
|
}
|
|
177
228
|
|
|
@@ -229,6 +280,17 @@ export function tombstoneCodexAccount(id: string): number {
|
|
|
229
280
|
});
|
|
230
281
|
}
|
|
231
282
|
|
|
283
|
+
export function tombstoneCodexAccountIfGeneration(id: string, expectedGeneration: number): boolean {
|
|
284
|
+
return withCredentialMutationLockSync(() => {
|
|
285
|
+
const store = loadCodexAccountRecordStore();
|
|
286
|
+
const current = store[id];
|
|
287
|
+
if (!current || current.generation !== expectedGeneration || current.deletedAt != null) return false;
|
|
288
|
+
store[id] = { generation: expectedGeneration + 1, deletedAt: Date.now() };
|
|
289
|
+
persist(store);
|
|
290
|
+
return true;
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
232
294
|
const CHATGPT_TOKEN_URL = "https://auth.openai.com/oauth/token";
|
|
233
295
|
const CHATGPT_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
234
296
|
|
package/src/codex/auth-api.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { ConfigMutationLockError, loadConfig, mutatePersistedConfig, saveConfigPreservingClaudeCode } from "../config";
|
|
1
|
+
import { ConfigMutationLockError, loadConfig, mutatePersistedConfig, reconcileLiveConfigFromDisk, saveConfigPreservingClaudeCode } from "../config";
|
|
2
2
|
import { withCodexAccountLogLabel } from "./account-label";
|
|
3
3
|
import {
|
|
4
4
|
getCodexAccountCredential,
|
|
5
5
|
getValidCodexToken,
|
|
6
6
|
isCodexAccountGenerationLive,
|
|
7
|
+
clearCodexAccountQuotaPauseOwnership,
|
|
8
|
+
markCodexAccountQuotaValidationPending,
|
|
7
9
|
markCodexAccountValidated,
|
|
8
10
|
readCodexAccountRecord,
|
|
9
11
|
saveCodexAccountCredential,
|
|
12
|
+
tombstoneCodexAccountIfGeneration,
|
|
10
13
|
CodexCredentialGenerationConflictError,
|
|
11
14
|
CodexCredentialRefreshLockTimeoutError,
|
|
12
15
|
CodexCredentialRefreshBusyError,
|
|
@@ -63,7 +66,7 @@ import {
|
|
|
63
66
|
} from "./main-account-cache";
|
|
64
67
|
export { clearMainAccountInfoCache } from "./main-account-cache";
|
|
65
68
|
import { maskEmail } from "../lib/privacy";
|
|
66
|
-
import { CodexWarmupError, codexWarmupFailureReason, warmCodexAccount } from "./warmup";
|
|
69
|
+
import { CodexWarmupError, codexWarmupFailureReason, isCodexWarmupQuotaFailure, warmCodexAccount } from "./warmup";
|
|
67
70
|
export { maskEmail } from "../lib/privacy";
|
|
68
71
|
import type { CodexAccount, OcxConfig } from "../types";
|
|
69
72
|
import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
|
|
@@ -83,6 +86,7 @@ import {
|
|
|
83
86
|
} from "./account-id";
|
|
84
87
|
import { codexAccountIdNamespaceCollisionError } from "./account-namespace-match";
|
|
85
88
|
import { ResourceAdmissionError } from "../lib/admission";
|
|
89
|
+
import { requestCodexQuotaWarmupRetry } from "../oauth/token-guardian";
|
|
86
90
|
|
|
87
91
|
function jsonResponse(data: unknown, status = 200): Response {
|
|
88
92
|
return new Response(JSON.stringify(data), {
|
|
@@ -248,7 +252,7 @@ async function verifyCodexAccountWarmup(
|
|
|
248
252
|
accountId: string,
|
|
249
253
|
accessToken: string,
|
|
250
254
|
chatgptAccountId: string,
|
|
251
|
-
): Promise<{ ok: true; validatedAt: number } | { ok: false; response: Response }> {
|
|
255
|
+
): Promise<{ ok: true; validatedAt: number } | { ok: false; response: Response; error: unknown }> {
|
|
252
256
|
try {
|
|
253
257
|
await warmCodexAccount({ accessToken, chatgptAccountId });
|
|
254
258
|
return { ok: true, validatedAt: Date.now() };
|
|
@@ -257,6 +261,7 @@ async function verifyCodexAccountWarmup(
|
|
|
257
261
|
const upstream = err instanceof CodexWarmupError ? err.upstreamDetail : undefined;
|
|
258
262
|
return {
|
|
259
263
|
ok: false,
|
|
264
|
+
error: err,
|
|
260
265
|
response: jsonResponse({
|
|
261
266
|
error: upstream
|
|
262
267
|
? `Codex account warmup failed: ${upstream}`
|
|
@@ -269,6 +274,64 @@ async function verifyCodexAccountWarmup(
|
|
|
269
274
|
}
|
|
270
275
|
}
|
|
271
276
|
|
|
277
|
+
interface FreshRegistrationQuota {
|
|
278
|
+
quota: Omit<StoredAccountQuota, "updatedAt">;
|
|
279
|
+
plan?: string;
|
|
280
|
+
email?: string;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function fetchFreshRegistrationQuota(
|
|
284
|
+
accessToken: string,
|
|
285
|
+
chatgptAccountId: string,
|
|
286
|
+
configuredPlan?: string,
|
|
287
|
+
): Promise<FreshRegistrationQuota | null> {
|
|
288
|
+
try {
|
|
289
|
+
const resp = await fetch("https://chatgpt.com/backend-api/wham/usage", {
|
|
290
|
+
headers: { Authorization: `Bearer ${accessToken}`, "ChatGPT-Account-Id": chatgptAccountId },
|
|
291
|
+
signal: AbortSignal.timeout(8000),
|
|
292
|
+
});
|
|
293
|
+
if (!resp.ok) return null;
|
|
294
|
+
const data = (await resp.json()) as WhamUsageResponse;
|
|
295
|
+
const plan = nonEmptyPlan(data.plan_type) ?? nonEmptyPlan(configuredPlan) ?? undefined;
|
|
296
|
+
const quota = parseUsageQuota({ ...data, ...(plan ? { plan_type: plan } : {}) });
|
|
297
|
+
if (!quota) return null;
|
|
298
|
+
return {
|
|
299
|
+
quota,
|
|
300
|
+
...(plan ? { plan } : {}),
|
|
301
|
+
...(typeof data.email === "string" && data.email.trim() ? { email: data.email } : {}),
|
|
302
|
+
};
|
|
303
|
+
} catch {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function exhaustedQuotaRetryAt(
|
|
309
|
+
quota: Omit<StoredAccountQuota, "updatedAt">,
|
|
310
|
+
plan?: string | null,
|
|
311
|
+
nowMs: number = Date.now(),
|
|
312
|
+
): number | undefined {
|
|
313
|
+
const monthlyOnly = isThirtyDayOnlyPlan(plan);
|
|
314
|
+
const resetSeconds: number[] = [];
|
|
315
|
+
if (!monthlyOnly && quota.weeklyPercent !== undefined && quota.weeklyPercent >= 100
|
|
316
|
+
&& quota.weeklyResetAt !== undefined) resetSeconds.push(quota.weeklyResetAt);
|
|
317
|
+
if (quota.monthlyPercent !== undefined && quota.monthlyPercent >= 100
|
|
318
|
+
&& quota.monthlyResetAt !== undefined) resetSeconds.push(quota.monthlyResetAt);
|
|
319
|
+
const retryAtMs = resetSeconds.length > 0 ? Math.max(...resetSeconds) * 1000 : undefined;
|
|
320
|
+
return retryAtMs !== undefined && Number.isFinite(retryAtMs) && retryAtMs > nowMs
|
|
321
|
+
? retryAtMs
|
|
322
|
+
: undefined;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function mayDeferQuotaWarmup(
|
|
326
|
+
warmup: { ok: false; error: unknown },
|
|
327
|
+
fresh: FreshRegistrationQuota | null,
|
|
328
|
+
): fresh is FreshRegistrationQuota {
|
|
329
|
+
return isCodexWarmupQuotaFailure(warmup.error)
|
|
330
|
+
&& fresh !== null
|
|
331
|
+
&& isCodexQuotaExhausted(fresh.quota, fresh.plan)
|
|
332
|
+
&& exhaustedQuotaRetryAt(fresh.quota, fresh.plan) !== undefined;
|
|
333
|
+
}
|
|
334
|
+
|
|
272
335
|
function expireCodexAuthFlow(flowId: string | null, error = "Login cancelled"): void {
|
|
273
336
|
const ids = flowId
|
|
274
337
|
? [flowId]
|
|
@@ -311,6 +374,64 @@ function saveRuntimeConfig(sourceConfig: OcxConfig, nextConfig: OcxConfig): void
|
|
|
311
374
|
Object.assign(sourceConfig, nextConfig);
|
|
312
375
|
}
|
|
313
376
|
|
|
377
|
+
type CodexAccountConfigCommit = { ok: true } | { ok: false; error: string };
|
|
378
|
+
|
|
379
|
+
function commitCodexAccountConfig(
|
|
380
|
+
sourceConfig: OcxConfig,
|
|
381
|
+
account: CodexAccount,
|
|
382
|
+
mode: "create" | "reauth",
|
|
383
|
+
credentialGeneration: number,
|
|
384
|
+
quotaPause: "add" | "release" | "preserve",
|
|
385
|
+
): CodexAccountConfigCommit {
|
|
386
|
+
const liveBaseline = structuredClone(sourceConfig);
|
|
387
|
+
const applyMutation = (persisted: OcxConfig) => {
|
|
388
|
+
if (!isCodexAccountGenerationLive(account.id, credentialGeneration)) {
|
|
389
|
+
return { changed: false, value: { ok: false, error: "Codex account changed while login was being saved" } as CodexAccountConfigCommit };
|
|
390
|
+
}
|
|
391
|
+
const conflict = mode === "create"
|
|
392
|
+
? codexAccountIdNamespaceCollisionError(persisted.codexAccountNamespaces, account.id)
|
|
393
|
+
?? ((persisted.codexAccounts ?? []).some(candidate => candidate.id === account.id)
|
|
394
|
+
? `Account id already exists: ${account.id}`
|
|
395
|
+
: undefined)
|
|
396
|
+
: (configuredPoolAccount(persisted, account.id)
|
|
397
|
+
? undefined
|
|
398
|
+
: "Pool account was removed while login was in progress. Add it again as a new account.");
|
|
399
|
+
if (conflict) {
|
|
400
|
+
return { changed: false, value: { ok: false, error: conflict } as CodexAccountConfigCommit };
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
const accounts = persisted.codexAccounts ?? [];
|
|
404
|
+
const existingIdx = accounts.findIndex(candidate => candidate.id === account.id);
|
|
405
|
+
if (existingIdx >= 0) {
|
|
406
|
+
accounts[existingIdx] = withCodexAccountLogLabel({
|
|
407
|
+
...accounts[existingIdx],
|
|
408
|
+
...account,
|
|
409
|
+
isMain: false,
|
|
410
|
+
}, accounts);
|
|
411
|
+
} else {
|
|
412
|
+
accounts.push(withCodexAccountLogLabel({ ...account, isMain: false }, accounts));
|
|
413
|
+
}
|
|
414
|
+
persisted.codexAccounts = accounts;
|
|
415
|
+
if (quotaPause === "add") setCodexAccountPaused(persisted, account.id, true);
|
|
416
|
+
else if (quotaPause === "release") setCodexAccountPaused(persisted, account.id, false);
|
|
417
|
+
return { changed: true, value: { ok: true } as CodexAccountConfigCommit };
|
|
418
|
+
};
|
|
419
|
+
const outcome = mutatePersistedConfig(applyMutation);
|
|
420
|
+
if (outcome.status === "unavailable") {
|
|
421
|
+
if (outcome.reason === "missing") {
|
|
422
|
+
const fallback = structuredClone(sourceConfig);
|
|
423
|
+
const applied = applyMutation(fallback);
|
|
424
|
+
if (!applied.value.ok) return applied.value;
|
|
425
|
+
saveRuntimeConfig(sourceConfig, fallback);
|
|
426
|
+
return { ok: true };
|
|
427
|
+
}
|
|
428
|
+
return { ok: false, error: `Configuration could not be updated (${outcome.reason})` };
|
|
429
|
+
}
|
|
430
|
+
if (!outcome.value.ok) return outcome.value;
|
|
431
|
+
reconcileLiveConfigFromDisk(sourceConfig, liveBaseline);
|
|
432
|
+
return { ok: true };
|
|
433
|
+
}
|
|
434
|
+
|
|
314
435
|
async function mapWithConcurrency<T, R>(
|
|
315
436
|
items: T[],
|
|
316
437
|
concurrency: number,
|
|
@@ -937,24 +1058,52 @@ export async function handleCodexAuthAPI(
|
|
|
937
1058
|
const payload = decodeJwtPayload(body.accessToken);
|
|
938
1059
|
const exp = typeof payload?.exp === "number" ? payload.exp * 1000 : Date.now() + 3600_000;
|
|
939
1060
|
const warmup = await verifyCodexAccountWarmup(body.id, body.accessToken, derivedAccountId);
|
|
940
|
-
|
|
1061
|
+
const freshQuota = !warmup.ok && isCodexWarmupQuotaFailure(warmup.error)
|
|
1062
|
+
? await fetchFreshRegistrationQuota(body.accessToken, derivedAccountId, body.plan)
|
|
1063
|
+
: null;
|
|
1064
|
+
const quotaDeferred = !warmup.ok && mayDeferQuotaWarmup(warmup, freshQuota);
|
|
1065
|
+
if (!warmup.ok && !quotaDeferred) return warmup.response;
|
|
941
1066
|
const latestConfig = getRuntimeConfig(config);
|
|
942
1067
|
const commitConflict = codexAccountPersistenceConflict(latestConfig, body.id, "create");
|
|
943
1068
|
if (commitConflict) return jsonResponse({ error: commitConflict }, 400);
|
|
944
|
-
saveCodexAccountCredential(body.id, {
|
|
1069
|
+
const credentialGeneration = saveCodexAccountCredential(body.id, {
|
|
945
1070
|
accessToken: body.accessToken,
|
|
946
1071
|
refreshToken: body.refreshToken,
|
|
947
1072
|
expiresAt: exp,
|
|
948
1073
|
chatgptAccountId: derivedAccountId,
|
|
949
1074
|
});
|
|
950
|
-
|
|
1075
|
+
const commit = commitCodexAccountConfig(
|
|
1076
|
+
config,
|
|
1077
|
+
{
|
|
1078
|
+
id: body.id,
|
|
1079
|
+
email: body.email,
|
|
1080
|
+
plan: freshQuota?.plan ?? body.plan,
|
|
1081
|
+
isMain: false,
|
|
1082
|
+
},
|
|
1083
|
+
"create",
|
|
1084
|
+
credentialGeneration,
|
|
1085
|
+
quotaDeferred ? "add" : "preserve",
|
|
1086
|
+
);
|
|
1087
|
+
if (!commit.ok) {
|
|
1088
|
+
tombstoneCodexAccountIfGeneration(body.id, credentialGeneration);
|
|
1089
|
+
return jsonResponse({ error: commit.error }, 409);
|
|
1090
|
+
}
|
|
1091
|
+
if (quotaDeferred) {
|
|
1092
|
+
markCodexAccountQuotaValidationPending(
|
|
1093
|
+
body.id,
|
|
1094
|
+
codexWarmupFailureReason(warmup.error),
|
|
1095
|
+
exhaustedQuotaRetryAt(freshQuota.quota, freshQuota.plan),
|
|
1096
|
+
);
|
|
1097
|
+
} else if (warmup.ok) {
|
|
1098
|
+
markCodexAccountValidated(body.id, warmup.validatedAt, credentialGeneration);
|
|
1099
|
+
}
|
|
951
1100
|
clearAccountNeedsReauth(body.id);
|
|
952
|
-
const accounts = latestConfig.codexAccounts ?? [];
|
|
953
|
-
accounts.push(withCodexAccountLogLabel({ id: body.id, email: body.email, plan: body.plan, isMain: false }, accounts));
|
|
954
|
-
latestConfig.codexAccounts = accounts;
|
|
955
|
-
saveRuntimeConfig(config, latestConfig);
|
|
956
1101
|
reconcileLiveStateStores();
|
|
957
|
-
|
|
1102
|
+
if (quotaDeferred) {
|
|
1103
|
+
setAccountQuotaFromParsed(body.id, freshQuota.quota);
|
|
1104
|
+
requestCodexQuotaWarmupRetry();
|
|
1105
|
+
}
|
|
1106
|
+
return jsonResponse({ ok: true, ...(quotaDeferred ? { validation: "pending_quota_reset" } : {}) });
|
|
958
1107
|
}
|
|
959
1108
|
|
|
960
1109
|
if (url.pathname === "/api/codex-auth/accounts" && req.method === "DELETE") {
|
|
@@ -1002,6 +1151,13 @@ export async function handleCodexAuthAPI(
|
|
|
1002
1151
|
const exists = id === MAIN_CODEX_ACCOUNT_ID
|
|
1003
1152
|
|| (runtimeConfig.codexAccounts ?? []).some(account => isSelectableCodexPoolAccount(account) && account.id === id);
|
|
1004
1153
|
if (!exists) return jsonResponse({ error: "Account not found" }, 404);
|
|
1154
|
+
const record = id === MAIN_CODEX_ACCOUNT_ID ? null : readCodexAccountRecord(id);
|
|
1155
|
+
if (body.paused === false && record?.lastCodexValidationStatus === "quota_pending") {
|
|
1156
|
+
return jsonResponse({ error: "Account validation is waiting for its quota reset" }, 409);
|
|
1157
|
+
}
|
|
1158
|
+
if (body.paused === true && record?.codexQuotaPauseOwned === true) {
|
|
1159
|
+
clearCodexAccountQuotaPauseOwnership(id);
|
|
1160
|
+
}
|
|
1005
1161
|
|
|
1006
1162
|
setCodexAccountPaused(runtimeConfig, id, body.paused);
|
|
1007
1163
|
if (body.paused) {
|
|
@@ -1377,7 +1533,11 @@ export async function handleCodexAuthAPI(
|
|
|
1377
1533
|
}
|
|
1378
1534
|
|
|
1379
1535
|
const warmup = await verifyCodexAccountWarmup(accountId, cred.access, oauthAccountId);
|
|
1380
|
-
|
|
1536
|
+
const freshRegistrationQuota = quota ? { quota, ...(plan ? { plan } : {}) } : null;
|
|
1537
|
+
const quotaDeferred = !reauth
|
|
1538
|
+
&& !warmup.ok
|
|
1539
|
+
&& mayDeferQuotaWarmup(warmup, freshRegistrationQuota);
|
|
1540
|
+
if (!warmup.ok && !quotaDeferred) {
|
|
1381
1541
|
const body = await warmup.response.json().catch(() => ({})) as { error?: string; reason?: string };
|
|
1382
1542
|
setCodexLoginState(flowId, {
|
|
1383
1543
|
status: "error",
|
|
@@ -1391,6 +1551,7 @@ export async function handleCodexAuthAPI(
|
|
|
1391
1551
|
const latestConfig = getRuntimeConfig(config);
|
|
1392
1552
|
const accounts = latestConfig.codexAccounts ?? [];
|
|
1393
1553
|
const existingIdx = accounts.findIndex(account => account.id === accountId);
|
|
1554
|
+
const existingAccount = existingIdx >= 0 ? accounts[existingIdx] : undefined;
|
|
1394
1555
|
const commitConflict = codexAccountPersistenceConflict(
|
|
1395
1556
|
latestConfig,
|
|
1396
1557
|
accountId,
|
|
@@ -1406,37 +1567,52 @@ export async function handleCodexAuthAPI(
|
|
|
1406
1567
|
break;
|
|
1407
1568
|
}
|
|
1408
1569
|
|
|
1409
|
-
|
|
1570
|
+
const releaseOwnedQuotaPause = reauth
|
|
1571
|
+
&& readCodexAccountRecord(accountId)?.codexQuotaPauseOwned === true;
|
|
1572
|
+
const credentialGeneration = saveCodexAccountCredential(accountId, {
|
|
1410
1573
|
accessToken: cred.access,
|
|
1411
1574
|
refreshToken: cred.refresh,
|
|
1412
1575
|
expiresAt: cred.expires,
|
|
1413
1576
|
chatgptAccountId: oauthAccountId,
|
|
1414
1577
|
});
|
|
1578
|
+
const configCommit = commitCodexAccountConfig(
|
|
1579
|
+
config,
|
|
1580
|
+
{
|
|
1581
|
+
id: accountId,
|
|
1582
|
+
email,
|
|
1583
|
+
plan: plan ?? existingAccount?.plan,
|
|
1584
|
+
isMain: false,
|
|
1585
|
+
},
|
|
1586
|
+
reauth ? "reauth" : "create",
|
|
1587
|
+
credentialGeneration,
|
|
1588
|
+
quotaDeferred ? "add" : releaseOwnedQuotaPause ? "release" : "preserve",
|
|
1589
|
+
);
|
|
1590
|
+
if (!configCommit.ok) {
|
|
1591
|
+
if (!reauth) tombstoneCodexAccountIfGeneration(accountId, credentialGeneration);
|
|
1592
|
+
setCodexLoginState(flowId, {
|
|
1593
|
+
status: "error",
|
|
1594
|
+
error: configCommit.error,
|
|
1595
|
+
doneAt: Date.now(),
|
|
1596
|
+
});
|
|
1597
|
+
completed = true;
|
|
1598
|
+
break;
|
|
1599
|
+
}
|
|
1415
1600
|
// A successful reauthentication replaces the credential generation. Do not let a
|
|
1416
1601
|
// failed optional WHAM probe make the replacement inherit quota from the old record.
|
|
1417
1602
|
if (reauth) clearAccountQuota(accountId);
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
if (
|
|
1425
|
-
|
|
1426
|
-
accounts[existingIdx] = withCodexAccountLogLabel({
|
|
1427
|
-
...accounts[existingIdx],
|
|
1428
|
-
email,
|
|
1429
|
-
plan: plan ?? accounts[existingIdx].plan,
|
|
1430
|
-
isMain: false,
|
|
1431
|
-
}, accounts);
|
|
1432
|
-
latestConfig.codexAccounts = accounts;
|
|
1433
|
-
saveRuntimeConfig(config, latestConfig);
|
|
1434
|
-
} else {
|
|
1435
|
-
accounts.push(withCodexAccountLogLabel({ id: accountId, email, plan, isMain: false }, accounts));
|
|
1436
|
-
latestConfig.codexAccounts = accounts;
|
|
1437
|
-
saveRuntimeConfig(config, latestConfig);
|
|
1603
|
+
if (quotaDeferred) {
|
|
1604
|
+
markCodexAccountQuotaValidationPending(
|
|
1605
|
+
accountId,
|
|
1606
|
+
codexWarmupFailureReason(warmup.error),
|
|
1607
|
+
exhaustedQuotaRetryAt(freshRegistrationQuota.quota, freshRegistrationQuota.plan),
|
|
1608
|
+
);
|
|
1609
|
+
} else if (warmup.ok) {
|
|
1610
|
+
markCodexAccountValidated(accountId, warmup.validatedAt, credentialGeneration);
|
|
1438
1611
|
}
|
|
1612
|
+
clearAccountNeedsReauth(accountId);
|
|
1439
1613
|
reconcileLiveStateStores();
|
|
1614
|
+
if (quota) setAccountQuotaFromParsed(accountId, quota);
|
|
1615
|
+
if (quotaDeferred) requestCodexQuotaWarmupRetry();
|
|
1440
1616
|
setCodexLoginState(flowId, { status: "done", accountId, email, doneAt: Date.now() });
|
|
1441
1617
|
completed = true;
|
|
1442
1618
|
}
|
package/src/codex/warmup.ts
CHANGED
|
@@ -68,6 +68,20 @@ export function codexWarmupFailureReason(err: unknown): string {
|
|
|
68
68
|
return safeWarmupReason(err);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A warmup rejection that can be caused by an exhausted account quota.
|
|
73
|
+
*
|
|
74
|
+
* The structured HTTP status is authoritative. Detail text only narrows a 403;
|
|
75
|
+
* arbitrary upstream prose (especially on auth failures) is never enough.
|
|
76
|
+
*/
|
|
77
|
+
export function isCodexWarmupQuotaFailure(err: unknown): boolean {
|
|
78
|
+
if (!(err instanceof CodexWarmupError) || err.code !== "http_status") return false;
|
|
79
|
+
if (err.status === 429) return true;
|
|
80
|
+
return err.status === 403
|
|
81
|
+
&& typeof err.upstreamDetail === "string"
|
|
82
|
+
&& /\b(?:quota|rate[\s_-]*limit|usage[\s_-]*limit)\b/i.test(err.upstreamDetail);
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
function eventTypeFromData(data: unknown): string | undefined {
|
|
72
86
|
if (!data || typeof data !== "object") return undefined;
|
|
73
87
|
const record = data as Record<string, unknown>;
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
* "proactive", and the global switch (config.tokenGuardian.enabled) defaults OFF, so a default
|
|
12
12
|
* install adds zero ToS-detection surface. See devlog 260703_oauth-multi-account-refresh-and-tos.
|
|
13
13
|
*/
|
|
14
|
-
import { loadConfig } from "../config";
|
|
14
|
+
import { loadConfig, mutatePersistedConfig } from "../config";
|
|
15
15
|
import type { OcxConfig, OcxTokenGuardianConfig } from "../types";
|
|
16
16
|
import { listAccounts } from "./store";
|
|
17
17
|
import { getValidAccessTokenForAccount, listOAuthProviders, OAuthLoginRequiredError, resolveRefreshPolicy } from "./index";
|
|
18
18
|
import {
|
|
19
19
|
getValidCodexToken,
|
|
20
|
+
isCodexAccountGenerationLive,
|
|
20
21
|
listCodexAccountIds,
|
|
21
22
|
markCodexAccountValidated,
|
|
22
23
|
markCodexAccountValidationFailed,
|
|
@@ -25,11 +26,14 @@ import {
|
|
|
25
26
|
CodexCredentialRefreshBusyError,
|
|
26
27
|
CodexCredentialRefreshStaleError,
|
|
27
28
|
} from "../codex/account-store";
|
|
28
|
-
import { codexWarmupFailureReason, warmCodexAccount } from "../codex/warmup";
|
|
29
|
+
import { CodexWarmupError, codexWarmupFailureReason, isCodexWarmupQuotaFailure, warmCodexAccount } from "../codex/warmup";
|
|
29
30
|
import { getMainAccountToken, MAIN_CODEX_ACCOUNT_ID } from "../codex/main-account";
|
|
30
31
|
import { isCanonicalOpenAiForwardProvider, OPENAI_CODEX_PROVIDER_ID } from "../providers/openai-tiers";
|
|
31
32
|
import { providerCodexAccountMode } from "../providers/registry";
|
|
32
33
|
import { captureConfigGeneration, type GenerationContext } from "../lib/state-store-sweeper";
|
|
34
|
+
import { setCodexAccountPaused } from "../codex/account-pause";
|
|
35
|
+
import { reconcileLiveStateStores } from "../lib/state-store-registrations";
|
|
36
|
+
import { markAccountNeedsReauth } from "../codex/account-runtime-state";
|
|
33
37
|
|
|
34
38
|
export interface TokenGuardianHandle {
|
|
35
39
|
stop(): void;
|
|
@@ -63,12 +67,44 @@ interface BackoffEntry {
|
|
|
63
67
|
const backoff = new Map<string, BackoffEntry>();
|
|
64
68
|
let lastReconciledGeneration = 0;
|
|
65
69
|
let liveBackoffKeys = new Set<string>();
|
|
70
|
+
let wakeQuotaRetryLoop: (() => void) | null = null;
|
|
71
|
+
const MIN_QUOTA_RETRY_TIMER_MS = 1_000;
|
|
66
72
|
|
|
67
73
|
/** Test hook: clear backoff state between cases. */
|
|
68
74
|
export function __resetGuardianState(): void {
|
|
69
75
|
backoff.clear();
|
|
70
76
|
}
|
|
71
77
|
|
|
78
|
+
function quotaPendingSweepEligible(config: OcxConfig): boolean {
|
|
79
|
+
const openai = config.providers[OPENAI_CODEX_PROVIDER_ID];
|
|
80
|
+
return openai?.disabled !== true
|
|
81
|
+
&& openai !== undefined
|
|
82
|
+
&& isCanonicalOpenAiForwardProvider(openai)
|
|
83
|
+
&& (providerCodexAccountMode(OPENAI_CODEX_PROVIDER_ID, openai) ?? "pool") === "pool";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function nextPendingQuotaRetryDelayMs(config: OcxConfig, nowMs = Date.now()): number | undefined {
|
|
87
|
+
if (!quotaPendingSweepEligible(config)) return undefined;
|
|
88
|
+
let earliest: number | undefined;
|
|
89
|
+
for (const id of listCodexAccountIds()) {
|
|
90
|
+
const record = readCodexAccountRecord(id);
|
|
91
|
+
if (record?.lastCodexValidationStatus !== "quota_pending" || !record.credential) continue;
|
|
92
|
+
const retryAt = Math.max(
|
|
93
|
+
record.codexQuotaRetryAt ?? nowMs,
|
|
94
|
+
backoff.get(`codex:${id}`)?.retryAfterMs ?? nowMs,
|
|
95
|
+
);
|
|
96
|
+
if (earliest === undefined || retryAt < earliest) earliest = retryAt;
|
|
97
|
+
}
|
|
98
|
+
return earliest === undefined
|
|
99
|
+
? undefined
|
|
100
|
+
: Math.max(MIN_QUOTA_RETRY_TIMER_MS, earliest - nowMs);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Wake the background loop after registration creates a new quota-pending account. */
|
|
104
|
+
export function requestCodexQuotaWarmupRetry(): void {
|
|
105
|
+
wakeQuotaRetryLoop?.();
|
|
106
|
+
}
|
|
107
|
+
|
|
72
108
|
function num(value: number | undefined, fallback: number, min: number): number {
|
|
73
109
|
return typeof value === "number" && Number.isFinite(value) && value >= min ? value : fallback;
|
|
74
110
|
}
|
|
@@ -133,12 +169,77 @@ export async function guardianSweep(nowMs: number = Date.now()): Promise<Guardia
|
|
|
133
169
|
const config: OcxConfig = loadConfig();
|
|
134
170
|
const g = config.tokenGuardian;
|
|
135
171
|
const result: GuardianSweepResult = { enabled: !!g?.enabled, refreshed: [], warmed: [], failed: [], skippedBackoff: [] };
|
|
136
|
-
if (!g?.enabled) return result;
|
|
137
|
-
|
|
138
172
|
const opts = resolved(g);
|
|
139
173
|
const horizonMs = (opts.tickSeconds + opts.leadSeconds) * 1000;
|
|
140
174
|
const tasks: Array<() => Promise<void>> = [];
|
|
141
175
|
|
|
176
|
+
// Registration-time quota deferrals are a safety invariant, not an optional keep-alive
|
|
177
|
+
// feature. Retry them after their freshly observed WHAM reset even when Token Guardian's
|
|
178
|
+
// user-facing refresh/warmup switches are off.
|
|
179
|
+
const openai = config.providers[OPENAI_CODEX_PROVIDER_ID];
|
|
180
|
+
if (quotaPendingSweepEligible(config)) {
|
|
181
|
+
for (const id of listCodexAccountIds()) {
|
|
182
|
+
const record = readCodexAccountRecord(id);
|
|
183
|
+
if (record?.lastCodexValidationStatus !== "quota_pending" || !record.credential) continue;
|
|
184
|
+
if (record.codexQuotaRetryAt !== undefined && record.codexQuotaRetryAt > nowMs) continue;
|
|
185
|
+
const key = `codex:${id}`;
|
|
186
|
+
if (inBackoff(key, nowMs)) { result.skippedBackoff.push(key); continue; }
|
|
187
|
+
tasks.push(async () => {
|
|
188
|
+
let attemptedGeneration = record.generation;
|
|
189
|
+
try {
|
|
190
|
+
const token = await getValidCodexToken(id);
|
|
191
|
+
attemptedGeneration = token.generation;
|
|
192
|
+
await warmCodexAccount({
|
|
193
|
+
accessToken: token.accessToken,
|
|
194
|
+
chatgptAccountId: token.chatgptAccountId,
|
|
195
|
+
model: opts.codexWarmupModel,
|
|
196
|
+
});
|
|
197
|
+
if (!isCodexAccountGenerationLive(id, token.generation)) return;
|
|
198
|
+
if (readCodexAccountRecord(id)?.codexQuotaPauseOwned === true) {
|
|
199
|
+
const outcome = mutatePersistedConfig(persisted => {
|
|
200
|
+
const current = readCodexAccountRecord(id);
|
|
201
|
+
if (!current || current.generation !== token.generation || current.codexQuotaPauseOwned !== true) {
|
|
202
|
+
return { changed: false, value: false };
|
|
203
|
+
}
|
|
204
|
+
const wasPaused = persisted.pausedCodexAccountIds?.includes(id) ?? false;
|
|
205
|
+
setCodexAccountPaused(persisted, id, false);
|
|
206
|
+
return { changed: wasPaused, value: true };
|
|
207
|
+
});
|
|
208
|
+
if (outcome.status === "unavailable" || outcome.value !== true) {
|
|
209
|
+
throw new Error("Codex quota-deferred pause could not be released");
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (!markCodexAccountValidated(id, Date.now(), token.generation)) {
|
|
213
|
+
throw new Error("Codex account changed while quota validation completed");
|
|
214
|
+
}
|
|
215
|
+
reconcileLiveStateStores();
|
|
216
|
+
backoff.delete(key);
|
|
217
|
+
result.warmed.push(key);
|
|
218
|
+
} catch (err) {
|
|
219
|
+
const terminalWarmupFailure = err instanceof CodexWarmupError
|
|
220
|
+
&& err.code === "http_status"
|
|
221
|
+
&& (err.status === 401 || err.status === 403)
|
|
222
|
+
&& !isCodexWarmupQuotaFailure(err);
|
|
223
|
+
const terminalTokenFailure = err instanceof TokenRefreshError
|
|
224
|
+
&& (err.reason === "revoked" || err.reason === "expired");
|
|
225
|
+
if (terminalWarmupFailure || terminalTokenFailure) {
|
|
226
|
+
if (markCodexAccountValidationFailed(id, codexWarmupFailureReason(err), attemptedGeneration)) {
|
|
227
|
+
markAccountNeedsReauth(id, writerGeneration);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const permanent = terminalWarmupFailure || terminalTokenFailure;
|
|
231
|
+
recordFailure(key, nowMs, opts.backoffBaseSeconds, opts.backoffMaxSeconds, permanent, writerGeneration);
|
|
232
|
+
result.failed.push(key);
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!g?.enabled) {
|
|
239
|
+
await runWithConcurrency(tasks, opts.concurrency);
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
|
|
142
243
|
// A) OAuth providers — every account in each provider's set (multiauth keep-alive),
|
|
143
244
|
// skipping accounts already marked needsReauth (terminal; only a re-login fixes them).
|
|
144
245
|
for (const provider of listOAuthProviders()) {
|
|
@@ -166,14 +267,13 @@ export async function guardianSweep(nowMs: number = Date.now()): Promise<Guardia
|
|
|
166
267
|
|
|
167
268
|
// B) canonical OpenAI Codex login. Direct warms main only; pool additionally maintains every
|
|
168
269
|
// added account. The direct branch returns before the managed account store is enumerated.
|
|
169
|
-
const openai = config.providers[OPENAI_CODEX_PROVIDER_ID];
|
|
170
270
|
if (
|
|
171
271
|
openai
|
|
172
272
|
&& openai.disabled !== true
|
|
173
273
|
&& isCanonicalOpenAiForwardProvider(openai)
|
|
174
274
|
&& resolveRefreshPolicy(OPENAI_CODEX_PROVIDER_ID, config) === "proactive"
|
|
175
275
|
) {
|
|
176
|
-
const
|
|
276
|
+
const configuredMode = providerCodexAccountMode(OPENAI_CODEX_PROVIDER_ID, openai) ?? "pool";
|
|
177
277
|
if (opts.codexWarmupEnabled) {
|
|
178
278
|
const mainToken = getMainAccountToken();
|
|
179
279
|
const key = `codex:${MAIN_CODEX_ACCOUNT_ID}`;
|
|
@@ -197,10 +297,11 @@ export async function guardianSweep(nowMs: number = Date.now()): Promise<Guardia
|
|
|
197
297
|
}
|
|
198
298
|
}
|
|
199
299
|
|
|
200
|
-
const addedAccountIds =
|
|
300
|
+
const addedAccountIds = configuredMode === "pool" ? listCodexAccountIds() : [];
|
|
201
301
|
for (const id of addedAccountIds) {
|
|
202
302
|
const record = readCodexAccountRecord(id);
|
|
203
303
|
if (!record || record.deletedAt != null) continue;
|
|
304
|
+
if (record.lastCodexValidationStatus === "quota_pending") continue;
|
|
204
305
|
const cred = record.credential;
|
|
205
306
|
if (!cred) continue;
|
|
206
307
|
const needsRefresh = cred.expiresAt <= nowMs + horizonMs;
|
|
@@ -273,16 +374,24 @@ export function reconcileGuardianBackoff(context: GenerationContext): number {
|
|
|
273
374
|
export function startTokenGuardian(): TokenGuardianHandle {
|
|
274
375
|
let stopped = false;
|
|
275
376
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
377
|
+
let sweepRunning = false;
|
|
276
378
|
|
|
277
379
|
const scheduleNext = () => {
|
|
278
380
|
if (stopped) return;
|
|
279
381
|
const opts = resolved(loadConfig().tokenGuardian);
|
|
280
|
-
const
|
|
382
|
+
const regularDelayMs = (opts.tickSeconds + Math.random() * opts.jitterSeconds) * 1000;
|
|
383
|
+
const pendingDelayMs = nextPendingQuotaRetryDelayMs(loadConfig());
|
|
384
|
+
const delayMs = pendingDelayMs === undefined
|
|
385
|
+
? regularDelayMs
|
|
386
|
+
: Math.min(regularDelayMs, pendingDelayMs);
|
|
281
387
|
timer = setTimeout(runSweep, delayMs);
|
|
282
388
|
if (typeof timer.unref === "function") timer.unref(); // never keep the process alive for a sweep
|
|
283
389
|
};
|
|
284
390
|
|
|
285
391
|
const runSweep = () => {
|
|
392
|
+
timer = undefined;
|
|
393
|
+
if (stopped || sweepRunning) return;
|
|
394
|
+
sweepRunning = true;
|
|
286
395
|
void guardianSweep()
|
|
287
396
|
.then(r => {
|
|
288
397
|
if (r.enabled && (r.refreshed.length || r.warmed.length || r.failed.length)) {
|
|
@@ -290,14 +399,26 @@ export function startTokenGuardian(): TokenGuardianHandle {
|
|
|
290
399
|
}
|
|
291
400
|
})
|
|
292
401
|
.catch(err => console.log(`token-guardian sweep error: ${err instanceof Error ? err.message : String(err)}`))
|
|
293
|
-
.finally(
|
|
402
|
+
.finally(() => {
|
|
403
|
+
sweepRunning = false;
|
|
404
|
+
scheduleNext();
|
|
405
|
+
});
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
const wake = () => {
|
|
409
|
+
if (stopped || sweepRunning) return;
|
|
410
|
+
if (timer) clearTimeout(timer);
|
|
411
|
+
timer = setTimeout(runSweep, 0);
|
|
412
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
294
413
|
};
|
|
295
414
|
|
|
415
|
+
wakeQuotaRetryLoop = wake;
|
|
296
416
|
scheduleNext();
|
|
297
417
|
return {
|
|
298
418
|
stop() {
|
|
299
419
|
stopped = true;
|
|
300
420
|
if (timer) clearTimeout(timer);
|
|
421
|
+
if (wakeQuotaRetryLoop === wake) wakeQuotaRetryLoop = null;
|
|
301
422
|
},
|
|
302
423
|
};
|
|
303
424
|
}
|
|
@@ -1423,6 +1423,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
|
|
|
1423
1423
|
dashboardUrl: "https://opencode.ai",
|
|
1424
1424
|
staticHeaders: {
|
|
1425
1425
|
"x-opencode-client": "desktop",
|
|
1426
|
+
// Zen's free tier identifies the OpenCode desktop client from this header. Without it,
|
|
1427
|
+
// otherwise identical requests can be classified as an exhausted free request and return
|
|
1428
|
+
// FreeUsageLimitError. Keep this in the registry so it also reaches legacy persisted rows.
|
|
1429
|
+
"User-Agent": "opencode/1.18.18",
|
|
1426
1430
|
},
|
|
1427
1431
|
modelReasoningEfforts: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS])),
|
|
1428
1432
|
modelReasoningEffortMap: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP])),
|
package/src/router.ts
CHANGED
|
@@ -272,6 +272,12 @@ function routedProviderConfig(providerName: string, provider: OcxProviderConfig)
|
|
|
272
272
|
...(provider.escapeBuiltinToolNames === undefined && registryEntry.escapeBuiltinToolNames !== undefined ? { escapeBuiltinToolNames: registryEntry.escapeBuiltinToolNames } : {}),
|
|
273
273
|
...(provider.keyOptional === undefined && registryEntry.keyOptional !== undefined ? { keyOptional: registryEntry.keyOptional } : {}),
|
|
274
274
|
...(provider.modelSuffixBracketStrip === undefined && registryEntry.modelSuffixBracketStrip !== undefined ? { modelSuffixBracketStrip: registryEntry.modelSuffixBracketStrip } : {}),
|
|
275
|
+
// Registry static headers are transport metadata, not user configuration. Re-apply them at
|
|
276
|
+
// request time so providers created before a header was introduced (or stripped from disk by
|
|
277
|
+
// management persistence) still make the same request as a freshly seeded provider.
|
|
278
|
+
...(registryEntry.staticHeaders
|
|
279
|
+
? { headers: { ...registryEntry.staticHeaders, ...(provider.headers ?? {}) } }
|
|
280
|
+
: {}),
|
|
275
281
|
// Scalar backfill: a persisted config created before the flag shipped inherits the registry
|
|
276
282
|
// opt-in, while an explicit user `false` keeps overriding registry `true`.
|
|
277
283
|
...(provider.parallelToolCalls === undefined && registryEntry.parallelToolCalls !== undefined ? { parallelToolCalls: registryEntry.parallelToolCalls } : {}),
|
package/src/types.ts
CHANGED
|
@@ -1241,6 +1241,10 @@ export interface CodexAccountCredentialRecord {
|
|
|
1241
1241
|
deletedAt?: number;
|
|
1242
1242
|
replacedAt?: number;
|
|
1243
1243
|
lastCodexValidatedAt?: number;
|
|
1244
|
-
lastCodexValidationStatus?: "ok" | "failed";
|
|
1244
|
+
lastCodexValidationStatus?: "ok" | "failed" | "quota_pending";
|
|
1245
1245
|
lastCodexValidationError?: string;
|
|
1246
|
+
/** Earliest sweep time for a registration deferred by freshly confirmed quota exhaustion. */
|
|
1247
|
+
codexQuotaRetryAt?: number;
|
|
1248
|
+
/** The registration flow, rather than the user, added the persisted pause. */
|
|
1249
|
+
codexQuotaPauseOwned?: boolean;
|
|
1246
1250
|
}
|
|
Binary file
|