@coseung2/opencodex 2.8.0-cs.11 → 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-BYDeFyGN.js → index-BucjyD4I.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/ocx-notch/README.md +2 -2
- 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/quota.ts +4 -0
- 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.11`,[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,8 +52,8 @@ 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
|
-
- 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.
|
|
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
|
|
|
59
59
|
Quota percentages are shown as used percentages with the same 5-hour/weekly/monthly/custom-window rows, reset countdowns, 5px progress bars, green fill, and green-to-amber threshold warning used by the OCX dashboard. Provider usage is merged by exact provider name, limited to the newest day, and formatted with Korean `만/억/조` units. OpenAI account rows show their own weekly/monthly quotas; OAuth and key-pool rows show their masked identity and active/health state, while provider-level quota remains associated with the active account. The native window uses a subtle 238/255 global alpha.
|
|
@@ -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
|
}
|
package/src/providers/quota.ts
CHANGED
|
@@ -947,6 +947,10 @@ async function fetchOpencodeGoQuota(name: string, config: OcxProviderConfig): Pr
|
|
|
947
947
|
export async function opencodeGoKeyQuotaEstimates(config: OcxConfig, name: string): Promise<Record<string, ProviderQuota> | null> {
|
|
948
948
|
const provider = config.providers[name];
|
|
949
949
|
if (!provider) return null;
|
|
950
|
+
// Key-pool listing is shared by every provider. Only an actual Zen Go
|
|
951
|
+
// provider may receive Go allocation data; free Zen keys must never inherit
|
|
952
|
+
// the Go subscription meter merely because they use the same key API.
|
|
953
|
+
if (!isCanonicalOpencodeGoBaseUrl(provider.baseUrl)) return null;
|
|
950
954
|
const now = Date.now();
|
|
951
955
|
const out: Record<string, ProviderQuota> = {};
|
|
952
956
|
const pool = provider.apiKeyPool ?? [];
|
|
@@ -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
|