@bitkyc08/opencodex 2.32.0 → 2.32.1-preview.20260825
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-BJwu-ldX.js → index-DrjQlNns.js} +1 -1
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/src/adapters/anthropic.ts +2 -2
- package/src/adapters/base.ts +1 -1
- package/src/adapters/openai-responses.ts +1 -1
- package/src/codex/catalog/provider-fetch.ts +20 -3
- package/src/generated/compatibility-version.json +9 -9
- package/src/responses/namespace-tool-compat.ts +84 -4
- package/src/responses/state.ts +94 -4
- package/src/server/responses/fetch-helpers.ts +14 -5
- package/src/server/responses/ws-upstream.ts +75 -2
|
@@ -99,4 +99,4 @@ default_mode_request_user_input = true`})]}),(0,q.jsxs)(`div`,{className:`codex-
|
|
|
99
99
|
}'`;return(0,q.jsxs)(`section`,{className:`panel api-panel awi-usage-panel`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:n(`api.workspace.usageExamples`)}),(0,q.jsxs)(`div`,{className:`awi-usage-panel-body`,children:[(0,q.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,q.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageChatTitle`)}),(0,q.jsx)(Ih,{text:i})]}),(0,q.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,q.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageResponsesTitle`)}),(0,q.jsx)(Ih,{text:a})]}),t&&(0,q.jsxs)(`div`,{className:`awi-usage-example`,children:[(0,q.jsx)(`h4`,{className:`awi-usage-example-title`,children:n(`api.usageMessagesTitle`)}),(0,q.jsx)(Ih,{text:o})]})]})]})}var Hh=[`opencode`,`pi`,`omp`,`hermes`,`openclaw`,`kimi`,`gajae`,`dsh`,`mcode`,`zcode`,`prime`],Uh={opencode:`api.clientConfig.clientOpencode`,pi:`api.clientConfig.clientPi`,omp:`api.clientConfig.clientOmp`,hermes:`api.clientConfig.clientHermes`,openclaw:`api.clientConfig.clientOpenclaw`,kimi:`api.clientConfig.clientKimi`,gajae:`api.clientConfig.clientGajae`,dsh:`api.clientConfig.clientDsh`,mcode:`api.clientConfig.clientMcode`,zcode:`api.clientConfig.clientZcode`,prime:`api.clientConfig.clientPrime`},Wh={opencode:`/provider-icons/opencode.svg`,pi:`/provider-icons/pi.svg`};function Gh({client:e,apiBase:t,onOpenDetails:n,onCopy:r,onDownload:i}){let a=Q(),[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(Uh[e]),g=Wh[e],v=f?.text??``,y=(0,_.useCallback)(t=>{f&&n(e,f,v,t.currentTarget)},[e,f,v,n]);return(0,q.jsxs)(`li`,{className:`awi-clientconfig-row`,children:[(0,q.jsx)(`span`,{className:`awi-clientconfig-mark`,"aria-hidden":`true`,children:g?(0,q.jsx)(`img`,{src:g,alt:``,width:20,height:20}):(0,q.jsx)(`span`,{className:`awi-clientconfig-monogram`,children:h.slice(0,1)})}),(0,q.jsxs)(`span`,{className:`awi-clientconfig-identity`,children:[(0,q.jsx)(`span`,{className:`awi-clientconfig-name`,children:h}),(0,q.jsx)(`span`,{className:`muted text-label awi-clientconfig-meta`,children:m?a(`api.clientConfig.loading`):p||!f?(0,q.jsx)(`span`,{role:`alert`,children:a(`api.clientConfig.rowError`,{client:h})}):a(`api.clientConfig.rowMeta`,{destination:f.destination,count:f.modelCount})})]}),(0,q.jsx)(`span`,{className:`awi-clientconfig-row-actions`,children:p&&!m?(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>s(e=>e+1),children:a(`common.retry`)}):(0,q.jsxs)(q.Fragment,{children:[(0,q.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,q.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,q.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 Kh({client:e,envelope:t,json:n,hasKeys:r,onClose:i,onCopy:a,onDownload:o}){let s=Q(),c=(0,_.useRef)(null),l=`awi-clientconfig-dialog-${e}`;(0,_.useEffect)(()=>{let e=c.current;return e&&!e.open&&e.showModal(),()=>{e?.open&&e.close()}},[]);let u=(0,_.useCallback)(e=>{e.preventDefault(),i()},[i]);return(0,q.jsxs)(`dialog`,{ref:c,className:`modal-overlay`,"aria-labelledby":l,onCancel:u,children:[(0,q.jsx)(`button`,{type:`button`,className:`modal-backdrop-dismiss`,"aria-label":s(`common.close`),tabIndex:-1,onClick:i}),(0,q.jsxs)(`div`,{className:`modal-card awi-clientconfig-dialog`,onClick:e=>e.stopPropagation(),role:`document`,children:[(0,q.jsxs)(`div`,{className:`modal-head`,children:[(0,q.jsx)(`h3`,{id:l,children:s(Uh[e])}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:i,children:s(`common.close`)})]}),(0,q.jsx)(`pre`,{className:`api-code api-example-pre awi-clientconfig-json`,tabIndex:0,role:`group`,"aria-label":s(`api.clientConfig.jsonLabel`,{client:s(Uh[e])}),children:n}),(0,q.jsx)(`p`,{className:`muted small awi-clientconfig-count`,children:s(`api.clientConfig.modelCount`,{count:t.modelCount})}),t.modelsWithoutLimits>0&&(0,q.jsx)(`p`,{className:`muted small awi-clientconfig-degraded`,children:s(`api.clientConfig.missingLimits`,{count:t.modelsWithoutLimits,total:t.modelCount})}),!r&&(0,q.jsx)(`p`,{className:`muted small awi-clientconfig-nokey`,children:s(`api.clientConfig.noKeyYet`,{env:t.apiKeyEnv})}),(0,q.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,q.jsx)(`span`,{className:`muted text-label`,children:s(`api.clientConfig.destination`)}),(0,q.jsx)(Ih,{text:t.destination})]}),(0,q.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,q.jsx)(`span`,{className:`muted text-label`,children:s(`api.clientConfig.envHint`)}),(0,q.jsx)(Ih,{text:t.exportHint})]}),(0,q.jsx)(`p`,{className:`muted small awi-clientconfig-merge`,children:s(`api.clientConfig.mergeWarning`)}),(0,q.jsx)(`p`,{className:`muted text-label awi-clientconfig-where-title`,children:s(`api.clientConfig.whereDisclosure`)}),(0,q.jsx)(`p`,{className:`muted small`,children:s(`api.clientConfig.whereBody`)}),(0,q.jsxs)(`div`,{className:`modal-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,onClick:a,children:s(`api.clientConfig.copy`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:o,children:s(`api.clientConfig.download`)})]})]})]})}function qh({apiBase:e,baseUrl:t,hasKeys:n}){let r=Q(),[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(Uh[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:t.mediaType})),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,q.jsxs)(`section`,{className:`panel api-panel awi-clientconfig-panel`,children:[(0,q.jsx)(`div`,{className:`api-panel-head awi-clientconfig-head`,children:(0,q.jsx)(`h3`,{className:`panel-title`,children:r(`api.clientConfig.title`)})}),(0,q.jsx)(`ul`,{className:`awi-clientconfig-rows`,"aria-label":r(`api.clientConfig.rowsLabel`),children:Hh.map(t=>(0,q.jsx)(Gh,{client:t,apiBase:e,onOpenDetails:f,onCopy:(e,t)=>{l(e,t,!0)},onDownload:u},t))}),(0,q.jsxs)(`div`,{className:`awi-clientconfig-line`,children:[(0,q.jsx)(`span`,{className:`muted text-label`,children:r(`api.baseUrl`)}),(0,q.jsx)(Ih,{text:t})]}),(0,q.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:o}),i&&(0,q.jsx)(Kh,{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 Jh({keys:e,keysLoading:t,keysLoadFailed:n,attributionSince:r,localeTag:i,busy:a,onSelect:o}){let s=Q();return(0,q.jsxs)(`div`,{className:`panel api-panel awi-keylist-panel`,"aria-busy":t,children:[(0,q.jsx)(`div`,{className:`api-panel-head`,children:(0,q.jsx)(`h3`,{className:`panel-title`,children:t?s(`api.activeKeysLoading`):s(`api.activeKeys`,{count:e.length})})}),t?(0,q.jsx)(`div`,{className:`api-active-keys-skeleton`,role:`status`,"aria-label":s(`common.loading`)}):e.length===0?(0,q.jsx)(`p`,{className:`muted small`,children:s(n?`api.keysLoadFailed`:`api.noKeys`)}):(0,q.jsx)(`div`,{className:`tbl-wrap`,children:(0,q.jsxs)(`table`,{className:`tbl awi-keylist-table`,children:[(0,q.jsx)(`thead`,{children:(0,q.jsxs)(`tr`,{children:[(0,q.jsx)(`th`,{children:s(`api.colName`)}),(0,q.jsx)(`th`,{children:s(`api.colKey`)}),(0,q.jsx)(`th`,{children:s(`api.attribution.requests7d`)}),(0,q.jsx)(`th`,{children:s(`api.attribution.lastUsed`)})]})}),(0,q.jsx)(`tbody`,{children:e.map(e=>(0,q.jsxs)(`tr`,{children:[(0,q.jsx)(`td`,{children:(0,q.jsx)(`button`,{type:`button`,className:`awi-keylist-name`,disabled:a,onClick:()=>o(e.id),children:e.name})}),(0,q.jsx)(`td`,{children:(0,q.jsx)(`code`,{children:e.prefix})}),(0,q.jsx)(`td`,{children:r?e.usage.ambiguous?s(`api.attribution.railAmbiguous`):e.usage.requests7d.toLocaleString(i):s(`api.attribution.unavailable`)}),(0,q.jsx)(`td`,{children:!r||e.usage.ambiguous?`—`:e.usage.lastUsedAt?Nh(e.usage.lastUsedAt,i):s(`api.attribution.neverUsed`)})]},e.id))})]})})]})}function Yh({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=Q(),[R,z]=(0,_.useState)(null),[B,V]=(0,_.useState)(!1),[H,U]=(0,_.useState)(!1),[W,ee]=(0,_.useState)(!1),[G,te]=(0,_.useState)(!1),[K,J]=(0,_.useState)(``),[ne,re]=(0,_.useState)(!1),[ie,Y]=(0,_.useState)(!1),[ae,oe]=(0,_.useState)(!1),X=R?e.find(e=>e.id===R)??null:null,se=W||ne,ce=(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]),le=()=>{V(!1),U(!1)},ue=()=>{z(null),le(),te(!1),Y(!1),oe(!1)};(0,_.useEffect)(()=>{if(!B)return;let e=window.setTimeout(()=>U(!0),300);return()=>window.clearTimeout(e)},[B]);let de=()=>{X&&V(!0)},fe=async()=>{if(!(!X||!H||W)){ee(!0),oe(!1);try{await k(X.id)?(le(),z(null)):oe(!0)}finally{ee(!1)}}},pe=()=>{X&&(J(X.name),Y(!1),te(!0))},me=async()=>{if(!X||ne)return;let e=K.trim();if(!e||e===X.name){te(!1);return}re(!0),Y(!1);try{await A(X.id,e)?te(!1):Y(!0)}finally{re(!1)}};return(0,q.jsxs)(`div`,{className:`apikeys-workspace-shell`,children:[!X&&(0,q.jsx)(Vf,{scope:`api`,items:ce,ariaLabel:L(`api.workspace.sections`)}),(0,q.jsx)(`div`,{className:`apikeys-workspace-root`,children:(0,q.jsx)(`section`,{className:`apikeys-workspace-main`,"aria-label":L(`api.workspace.details`),children:X?(0,q.jsxs)(`div`,{className:`awi-detail`,children:[(0,q.jsx)(`div`,{className:`awi-detail-toolbar`,children:(0,q.jsxs)(`button`,{type:`button`,className:`awi-back`,onClick:ue,disabled:se,children:[(0,q.jsx)(xe,{className:`awi-back-chevron`,"aria-hidden":`true`}),L(`modal.back`)]})}),(0,q.jsxs)(`div`,{className:`awi-detail-body`,children:[(0,q.jsxs)(`div`,{className:`awi-detail-head`,children:[(0,q.jsx)(`h2`,{className:`awi-detail-title`,children:X.name}),(0,q.jsx)(`span`,{className:`awi-detail-actions`,children:B?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm awi-confirm-delete`,onClick:()=>{fe()},disabled:!H||W,children:[(0,q.jsx)(he,{}),` `,L(W?`api.key.deleting`:`api.confirm`)]},`confirm-delete`),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:le,disabled:W,children:L(`common.cancel`)})]}):(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:pe,disabled:G,children:L(`api.key.rename`)},`rename`),(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-danger btn-sm`,onClick:de,"aria-label":L(`api.deleteAria`),children:[(0,q.jsx)(he,{}),` `,L(`api.workspace.deleteKey`)]},`request-delete`)]})})]}),B&&(0,q.jsx)(`p`,{className:`muted awi-delete-hint`,children:L(`api.workspace.deleteConfirm`)}),ae&&(0,q.jsx)(`p`,{className:`awi-delete-error`,role:`alert`,children:L(`api.deleteFailed`)}),G&&(0,q.jsxs)(`div`,{className:`awi-rename`,children:[(0,q.jsx)(`label`,{className:`awi-rename-label`,htmlFor:`awi-key-name`,children:L(`api.key.name`)}),(0,q.jsx)(`input`,{id:`awi-key-name`,className:`input`,type:`text`,value:K,maxLength:64,disabled:ne,onChange:e=>J(e.target.value),onKeyDown:e=>{e.key===`Enter`&&(e.preventDefault(),me())}}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>{me()},disabled:ne,children:L(ne?`api.key.renaming`:`api.key.saveName`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>te(!1),disabled:ne,children:L(`common.cancel`)}),ie&&(0,q.jsx)(`p`,{className:`awi-rename-error`,role:`alert`,children:L(`api.key.renameFailed`)})]}),(0,q.jsxs)(`div`,{className:`awi-section`,children:[(0,q.jsx)(`h3`,{className:`awi-section-title`,children:L(`api.workspace.keyDetails`)}),(0,q.jsxs)(`dl`,{className:`awi-kv`,children:[(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(`api.workspace.keyPrefix`)}),(0,q.jsx)(`dd`,{children:(0,q.jsx)(`code`,{children:X.prefix})})]}),(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(`api.colCreated`)}),(0,q.jsx)(`dd`,{children:Nh(X.createdAt,l)})]})]})]}),(0,q.jsxs)(`div`,{className:`awi-section`,children:[(0,q.jsx)(`h3`,{className:`awi-section-title`,children:L(`api.attribution.title`)}),n?X.usage.ambiguous?(0,q.jsx)(`p`,{className:`muted`,children:L(`api.attribution.ambiguous`)}):(0,q.jsxs)(`dl`,{className:`awi-kv`,children:[(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(`api.attribution.requests7d`)}),(0,q.jsx)(`dd`,{children:X.usage.requests7d.toLocaleString(l)})]}),(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(r?`api.attribution.totalRequestsAvailable`:`api.attribution.totalRequests`)}),(0,q.jsx)(`dd`,{children:X.usage.totalRequests.toLocaleString(l)})]}),(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(`api.attribution.lastUsed`)}),(0,q.jsx)(`dd`,{children:X.usage.lastUsedAt?Nh(X.usage.lastUsedAt,l):L(`api.attribution.neverUsed`)})]}),(0,q.jsxs)(`div`,{className:`awi-kv-row`,children:[(0,q.jsx)(`dt`,{children:L(r?`api.attribution.sinceAvailable`:`api.attribution.since`)}),(0,q.jsx)(`dd`,{children:Nh(n,l)})]})]}):(0,q.jsx)(`p`,{className:`muted`,children:L(`api.attribution.unavailableDetail`)})]})]})]}):(0,q.jsx)(`div`,{className:`awi-overview`,children:(0,q.jsxs)(`div`,{className:`awi-overview-section`,children:[(0,q.jsxs)(`div`,{id:Rf(`api`,`keys`),className:`awi-section-anchor`,children:[(0,q.jsx)(zh,{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,q.jsx)(Jh,{keys:e,keysLoading:a,keysLoadFailed:o,attributionSince:n,localeTag:l,busy:se,onSelect:e=>{z(e),le(),te(!1),Y(!1),oe(!1)}})]}),(0,q.jsx)(`div`,{id:Rf(`api`,`connect`),className:`awi-section-anchor`,children:(0,q.jsx)(qh,{apiBase:t,baseUrl:s.baseUrl,hasKeys:e.length>0})}),(0,q.jsx)(`div`,{id:Rf(`api`,`endpoints`),className:`awi-section-anchor`,children:(0,q.jsx)(Rh,{endpoints:s,claudeCodeEnabled:c,authMatrix:i})}),(0,q.jsx)(`div`,{id:Rf(`api`,`models`),className:`awi-section-anchor`,children:(0,q.jsx)(Bh,{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,q.jsx)(`div`,{id:Rf(`api`,`examples`),className:`awi-section-anchor`,children:(0,q.jsx)(Vh,{endpoints:s,claudeCodeEnabled:c})})]})})})})]})}var Xh=[],Zh=15e3;function Qh(e){let t=e.replace(/\/$/,``);if(!t)return jh;try{return new URL(t).host?Mh(`${t}/v1/responses`):jh}catch{return jh}}function $h(e){return!e||!Ah(e.authMatrix)||!Array.isArray(e.keys)||e.keys.some(e=>!e||!Oh(e.usage))?null:e}function eg({apiBase:e,active:t=!0}){let{t:n,locale:r}=st(),i=$e.find(e=>e.code===r)?.htmlLang,a=`ocx.apikeys.list.v2:${e}`,o=`ocx.apikeys.models.v1:${e}`,s=`api-keys:${e}`,c=`api-models:${e}`,l=pr(a),u=pr(o),d=$h(l?.data??null),f=u?.data??null,[p,m]=(0,_.useState)(null),[h,g]=(0,_.useState)(``),[v,y]=(0,_.useState)(null),[b,x]=(0,_.useState)({}),[S,C]=(0,_.useState)(``),[w,T]=(0,_.useState)(!1),[E,D]=(0,_.useState)(null),[O,k]=(0,_.useState)(!1),A=(0,_.useRef)(!1),j=(0,_.useCallback)(async t=>{let r=await Pt(await fetch(`${e}/api/keys`,{signal:t}));if(!r||!Ah(r.authMatrix))throw Error(n(`api.keysLoadFailed`));let i=r.keys??[];if(i.some(e=>!Oh(e.usage)))throw Error(n(`api.keysLoadFailed`));let o=i,s=Mh(r.endpoint??``),c={keys:o,endpoints:{baseUrl:r.baseUrl??s.baseUrl,responses:r.responsesEndpoint??r.endpoint??jh.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 mr(a,c),c},[e,a,n]),M=(0,_.useCallback)(async t=>{let r=await fetch(`${e}/v1/models`,{signal:t});if(!r.ok)throw Error(n(`api.modelsLoadFailed`));let i=await r.json(),a=Array.isArray(i)?i:typeof i==`object`&&i&&Array.isArray(i.data)?i.data:null;if(!a)throw Error(n(`api.modelsLoadFailed`));let s=a.filter(e=>typeof e==`object`&&!!e&&typeof e.id==`string`).map(e=>Eh(e)).sort((e,t)=>Dh(e).localeCompare(Dh(t)));return mr(o,s),s},[e,o,n]),N=Uc(s,[e],j,{isEmpty:e=>e.keys.length===0,initialData:d??void 0,initialDataCachedAt:l?.cachedAt??null,staleAfterMs:6e4,enabled:t}),P=Uc(c,[e],M,{isEmpty:e=>e.length===0,initialData:f??void 0,initialDataCachedAt:u?.cachedAt??null,staleAfterMs:6e4,enabled:t}),F=N.state,I=P.state,L=F.data??d,R=I.data??f??Xh,z=L?.keys??[],B=L?.endpoints??Qh(e),V=L?.claudeCodeEnabled??!0,H=L?.attributionSince,U=L?.historyTruncated===!0,W=L?.authMatrix??[],ee=N.refresh,G=P.refresh,te=(0,_.useMemo)(()=>{let e=h.trim().toLowerCase();return e?R.filter(t=>Dh(t).toLowerCase().includes(e)||t.displayName.toLowerCase().includes(e)||t.provider.toLowerCase().includes(e)):R},[h,R]),K=async t=>{if(A.current)return!1;A.current=!0,T(!0),m(null);try{let r=t??S,i=await Nt(await fetch(`${e}/api/keys`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({name:r||`default`})}),n(`api.createFailed`));return typeof i?.key!=`string`||i.key.length===0?(m(n(`api.createFailed`)),!1):(D(i.key),C(``),ee(),!0)}catch{return m(n(`api.createFailed`)),!1}finally{A.current=!1,T(!1)}},J=async t=>{m(null);let n=In(Zh);try{return(await fetch(`${e}/api/keys`,{method:`DELETE`,headers:{"Content-Type":`application/json`},body:JSON.stringify({id:t}),signal:n.signal})).ok?(ee(),!0):!1}catch{return!1}finally{n.clear()}},ne=async(t,n)=>{m(null);let r=In(Zh);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?(ee(),!0):!1}catch{return!1}finally{r.clear()}},re=async()=>{if(E){m(null);try{await navigator.clipboard.writeText(E),k(!0),window.setTimeout(()=>k(!1),2e3)}catch{k(!1),m(n(`api.key.copyFailed`))}}},ie=async e=>{try{await navigator.clipboard.writeText(e),y(e),window.setTimeout(()=>y(t=>t===e?null:t),2e3)}catch{}},Y=e=>e.native?n(`api.sourceNative`):e.provider===`combo`?n(`api.sourceCombo`):e.custom?n(`api.sourceCustom`):En(e.provider,n),ae=e=>n(e===`responses`?`api.protocolResponses`:e===`messages`?`api.protocolMessages`:`api.protocolChatCompletions`),oe=(e,t)=>e===`responses`?{url:B.responses,body:{model:t,input:`ping`,max_output_tokens:1,stream:!1}}:e===`messages`?{url:B.messages,body:{model:t,max_tokens:1,messages:[{role:`user`,content:`ping`}]}}:{url:B.chatCompletions,body:{model:t,messages:[{role:`user`,content:`ping`}],max_tokens:1,stream:!1}},X=(e,t,n)=>x(r=>({...r,[e]:{...r[e],[t]:n}})),se=async(e,t)=>{if(!E)return;let r=Dh(e),i=oe(t,r);X(r,t,{state:`testing`});try{let e=await fetch(i.url,{method:`POST`,headers:{"Content-Type":`application/json`,"x-opencodex-api-key":E},body:JSON.stringify(i.body)});if(!e.ok){let n=await e.text();X(r,t,{state:`error`,detail:n.slice(0,160)||String(e.status)});return}X(r,t,{state:`ok`})}catch(e){X(r,t,{state:`error`,detail:e instanceof Error?e.message:n(`api.testFailed`)})}},ce=n(`api.subtitle`).split(`{authHeader}`);return(0,q.jsxs)(`section`,{className:`api-page`,"aria-busy":F.refreshing||I.refreshing||void 0,children:[(0,q.jsx)(`div`,{className:`page-head`,children:(0,q.jsx)(`h2`,{children:n(`api.title`)})}),(0,q.jsxs)(`p`,{className:`page-sub`,children:[ce[0],(0,q.jsx)(`code`,{children:`x-opencodex-api-key`}),ce[1]]}),p&&(0,q.jsx)($,{tone:`err`,children:p}),F.showError&&L&&(0,q.jsx)($,{tone:`err`,children:n(`api.keysLoadFailed`)}),F.showSkeleton&&!L?(0,q.jsx)(Gc,{label:n(`api.activeKeysLoading`),rows:4}):F.kind===`failed-cold`&&!L?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)($,{tone:`err`,children:F.error instanceof Error?F.error.message:n(`api.keysLoadFailed`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>ee(),children:n(`common.retry`)})]}):(0,q.jsx)(q.Fragment,{children:(0,q.jsx)(Yh,{keys:z,apiBase:e,attributionSince:H,historyTruncated:U,authMatrix:W,keysLoading:!1,keysLoadFailed:F.showError,endpoints:B,claudeCodeEnabled:V,localeTag:i,newName:S,creating:w,newKey:E,copied:O,filteredModels:te,modelsLoading:I.showSkeleton&&!I.data&&!f,modelsRefreshing:I.refreshing&&I.showError&&(I.data!==void 0||f!==null),modelsLoadFailed:I.showError,modelCount:R.length,hasModelData:I.data!==void 0||f!==null,modelQuery:h,copiedModelId:v,modelTests:b,onNewNameChange:C,onCreate:()=>{K()},onDismissNewKey:()=>D(null),onCopyKey:()=>{re()},onDelete:J,onRename:ne,onModelQueryChange:g,onCopyModelId:e=>{ie(e)},onTestModel:(e,t)=>{se(e,t)},onRetryModels:()=>{G({forceLoading:!0})},canTestModels:E!==null,sourceLabel:Y,protocolLabel:ae})})]})}function tg(e,t){let n=(e??[]).map(e=>({value:e,label:Vc(e)}));return[{value:``,label:t},...n]}function ng(e){let t=e.autoConnectSupported===!0;return{autoConnectSupported:t,systemEnv:t&&e.systemEnv===!0}}function rg(){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)}`}var ig=829800;function ag(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`}var og=[`ANTHROPIC_MODEL`,`ANTHROPIC_DEFAULT_OPUS_MODEL`,`ANTHROPIC_DEFAULT_SONNET_MODEL`,`ANTHROPIC_DEFAULT_HAIKU_MODEL`,`ANTHROPIC_DEFAULT_FABLE_MODEL`];function sg(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=og.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??829800}`]:[],...i,`claude`].join(`
|
|
100
100
|
`)}function cg(e){return e?e.backend??`auto`:`inherit`}function lg(e,t){if(t!==`inherit`)return t===`auto`?{...e,backend:void 0}:{...e,backend:t}}function ug(e,t){return{...e,model:t}}function dg(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 fg({label:e,checked:t,onChange:n,disabled:r=!1,describedBy:i}){return(0,q.jsxs)(`label`,{className:`toggle`,children:[(0,q.jsx)(`input`,{type:`checkbox`,checked:t,disabled:r,"aria-label":e,"aria-describedby":i,onChange:e=>n(e.target.checked)}),(0,q.jsx)(`span`,{className:`slider`,"aria-hidden":`true`})]})}function pg({supported:e,checked:t,onChange:n}){let r=Q(),i=e?void 0:`claude-system-env-unsupported`;return(0,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:r(`claude.systemEnv`)}),e?(0,q.jsx)(`span`,{className:`desc`,children:r(`claude.systemEnvDesc`)}):(0,q.jsx)(`span`,{className:`desc`,id:i,children:(0,q.jsx)(lt,{k:`claude.systemEnvUnsupported`,cmd:`ocx claude`})}),e&&t&&(0,q.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:r(`claude.systemEnvWarn`)})]}),(0,q.jsx)(fg,{label:r(`claude.systemEnv`),checked:e&&t,disabled:!e,describedBy:i,onChange:n})]})}function mg({value:e,tierHaikuModel:t,options:n,onChange:r}){let i=Q(),a=t??e;return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:i(`claude.smallFastModelAccurateHint`)}),(0,q.jsx)(Et,{value:e,options:n,onChange:r,label:i(`claude.smallFastModel`),style:{maxWidth:420}}),a===``&&(0,q.jsx)(`p`,{className:`notice-warn`,role:`status`,style:{marginTop:8},children:i(`claude.smallFastModelNativeWarning`)})]})}function hg(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 gg({state:e,autoCompactOptions:t,availableModels:n,onStateChange:r}){let i=Q();return(0,q.jsxs)(`div`,{className:`card`,style:{overflow:`hidden`},children:[(0,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:i(`claude.authMode`)}),(0,q.jsx)(`span`,{className:`desc`,children:i(`claude.authModeHint`)})]}),(0,q.jsx)(`div`,{className:`setting-controls`,children:(0,q.jsx)(Et,{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,q.jsxs)(`div`,{className:`claude-effective-auth${e.authModeOrigin===`auto-unknown`?` warn`:``}`,role:`status`,children:[(0,q.jsx)(`span`,{className:`claude-effective-auth-label`,children:i(`claude.effectiveMode.label`)}),(0,q.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:hg(e.authFoundBy,i)}):e.authModeOrigin===`auto-absent`?i(`claude.effectiveMode.autoAbsent`):i(`claude.effectiveMode.autoUnknown`),e.admissionKeyActive===!0?` ${i(`claude.effectiveMode.admissionKey`)}`:``]})]}),(0,q.jsx)(pg,{supported:e.autoConnectSupported,checked:e.systemEnv,onChange:t=>r({...e,systemEnv:t})}),(0,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:i(`claude.fastMode`)}),(0,q.jsx)(`span`,{className:`desc`,children:i(`claude.fastModeDesc`)})]}),(0,q.jsx)(`div`,{className:`setting-controls`,children:(0,q.jsx)(Et,{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,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:i(`claude.autoContext`)}),(0,q.jsx)(`span`,{className:`desc`,children:i(`claude.autoContextDesc`)}),e.maxContextTokens!==null&&(0,q.jsx)(`span`,{className:`desc`,style:{color:`var(--muted)`},children:i(`claude.autoContextInert`)})]}),(0,q.jsx)(fg,{label:i(`claude.autoContext`),checked:e.autoContext,onChange:t=>r({...e,autoContext:t})})]}),e.autoContext&&(0,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:i(`claude.autoCompactWindow`)}),(0,q.jsx)(`span`,{className:`desc`,children:i(`claude.autoCompactWindowDesc`)}),e.autoCompactWindow!==null&&(0,q.jsx)(`span`,{className:`desc`,style:{color:`var(--red)`},children:i(`claude.autoCompactWindowWarn`)})]}),(0,q.jsx)(`div`,{className:`setting-controls`,children:(0,q.jsx)(Et,{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,q.jsxs)(`div`,{className:`setting-row`,children:[(0,q.jsxs)(`div`,{className:`setting-label`,children:[(0,q.jsx)(`span`,{className:`title`,children:i(`claude.injectAgents`)}),(0,q.jsx)(`span`,{className:`desc`,children:i(`claude.injectAgentsDesc`)})]}),(0,q.jsx)(fg,{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,q.jsxs)(`div`,{className:`setting-row`,style:{alignItems:`flex-start`},children:[(0,q.jsxs)(`div`,{className:`setting-label setting-copy`,style:{flex:1},children:[(0,q.jsx)(`span`,{className:`title`,children:i(o)}),(0,q.jsx)(`span`,{className:`desc`,children:i(s)})]}),(0,q.jsxs)(`div`,{className:`setting-controls`,style:{display:`flex`,gap:8},children:[(0,q.jsx)(Et,{value:cg(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]:lg(a,n)})},label:i(`dash.sidecarBackend`),portal:!0}),(0,q.jsx)(`input`,{className:`input mono`,value:a?.model??``,onChange:n=>{r({...e,[t]:ug(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,q.jsx)(`datalist`,{id:c,children:n.map(e=>(0,q.jsx)(`option`,{value:e},e))})]})]},t)})]})}function _g({manualEnv:e}){let t=Q();return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:(0,q.jsx)(lt,{k:`claude.quickstartHint`,cmd:`ocx claude`})}),(0,q.jsx)(`pre`,{className:`mono card`,style:{padding:`10px 14px`,overflowX:`auto`,margin:0},children:`ocx claude`}),(0,q.jsxs)(`details`,{style:{margin:`10px 0 0`},children:[(0,q.jsx)(`summary`,{className:`muted text-label`,style:{cursor:`pointer`,padding:`2px 2px`},children:t(`claude.manualEnv`)}),(0,q.jsx)(`pre`,{className:`mono card text-label`,style:{padding:`10px 14px`,overflowX:`auto`,margin:`6px 0 0`},children:e})]})]})}function vg({rows:e,onRowsChange:t}){let n=Q();return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`p`,{className:`muted text-label`,style:{margin:`0 0 8px`},children:n(`claude.modelMapHint`)}),(0,q.jsx)(`div`,{className:`stack`,style:{gap:8},children:e.map((r,i)=>(0,q.jsxs)(`div`,{className:`row`,style:{gap:8},children:[(0,q.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,q.jsx)(`span`,{className:`muted`,"aria-hidden":!0,children:`→`}),(0,q.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,q.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,q.jsx)(ue,{})})]},r.id))}),(0,q.jsx)(`div`,{style:{marginTop:8},children:(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>t([...e,{id:rg(),from:``,to:``}]),children:[(0,q.jsx)(de,{}),` `,n(`claude.addMapping`)]})})]})}var yg=`etc`;function bg(e){let t=new Map;for(let n of e){let e=/\(([^)]+)\)\s*$/.exec(n.display_name),r=e?e[1]:yg,i=t.get(r);i?i.push(n):t.set(r,[n])}return Array.from(t)}function xg({aliases:e}){let t=Q();return(0,q.jsxs)(`div`,{className:`claude-aliases`,children:[(0,q.jsx)(`p`,{className:`muted text-label claude-aliases-hint`,children:t(`claude.aliasesHint`)}),e.length===0?(0,q.jsx)(`div`,{className:`muted text-label`,children:t(`claude.none`)}):(0,q.jsx)(`div`,{className:`claude-aliases-scroll`,children:bg(e).map(([e,n])=>(0,q.jsxs)(`div`,{className:`claude-aliases-group`,children:[(0,q.jsxs)(`div`,{className:`claude-aliases-group-label`,children:[e===yg?t(`claude.aliasProviderOther`):e,(0,q.jsx)(`span`,{className:`claude-aliases-group-count`,children:n.length})]}),(0,q.jsx)(`div`,{className:`claude-aliases-chips`,children:n.map(e=>(0,q.jsxs)(`span`,{className:`claude-aliases-chip`,children:[(0,q.jsx)(`code`,{className:`claude-aliases-chip-id`,children:e.id}),e.display_name?(0,q.jsx)(`span`,{className:`claude-aliases-chip-name`,children:e.display_name}):null]},e.id))})]},e))})]})}function Sg({apiBase:e,active:t=!0}){let n=Q(),{locale:r}=st(),i=$e.find(e=>e.code===r)?.htmlLang??`en`,a=`ocx.claude-code.v1:${e}`,o=`claude-code:${e}`,s=(0,_.useMemo)(()=>pr(a),[a]),c=s?.data??null,[l,u]=(0,_.useState)(()=>c?.state??null),[d,f]=(0,_.useState)(()=>c?.rows??[]),[p,m]=(0,_.useState)(!!c),[h,g]=(0,_.useState)(``),[v,y]=(0,_.useState)(!1),[b,x]=(0,_.useState)(`settings`),[S,C]=(0,_.useState)(!1),w=(0,_.useRef)(!1),T=(0,_.useCallback)(async t=>{let r=await Nt(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`,...ng(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:rg(),from:e,to:String(t)})),s={state:i,rows:o};if(t.aborted)throw Error(`Claude Code request aborted`);return u(i),f(o),m(!0),mr(a,s),s},[e,a,n]),E=Uc(o,[e],T,{isEmpty:()=>!1,enabled:t,initialData:c??void 0,initialDataCachedAt:s?.cachedAt??null,staleAfterMs:6e4}),D=E.state,O=D.data??c,k=l??O?.state??null,A=p?d:O?.rows??d,j=(0,_.useMemo)(()=>tg(k?.available,n(`claude.smallFastModelUnsetOption`)),[k?.available,n]),M=(0,_.useMemo)(()=>{let e=[1e5,2e5,25e4,3e5,35e4,4e5,5e5,6e5,75e4,ig,9e5,1e6].sort((e,t)=>e-t),t=k?.autoCompactWindow??null,r=t!==null&&!e.includes(t)?[...e,t].sort((e,t)=>e-t):e;return[{value:``,label:n(`claude.autoCompactDefault`,{value:ag(ig,i)})},...r.map(e=>({value:String(e),label:ag(e,i)}))]},[k?.autoCompactWindow,n,i]),N=async()=>{if(!k||w.current)return;w.current=!0,C(!0),g(``);let t=!k.enabled;try{await Nt(await fetch(`${e}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:t})}),n(`claude.saveFailed`)),u({...k,enabled:t}),E.refresh()}catch(e){y(!1),g(e instanceof Error&&e.message?e.message:n(`claude.networkError`))}finally{w.current=!1,C(!1)}},P=async()=>{if(!k)return;g(``);let t={};for(let e of A)e.from.trim()&&e.to.trim()&&(t[e.from.trim()]=e.to.trim());try{await Nt(await fetch(`${e}/api/claude-code`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:k.enabled,authMode:k.authMode,systemEnv:k.systemEnv,fastMode:k.fastMode,autoContext:k.autoContext,autoCompactWindow:k.autoCompactWindow,injectAgents:k.injectAgents,smallFastModel:k.smallFastModel,modelMap:t,webSearchSidecar:dg(k.webSearchSidecar),visionSidecar:dg(k.visionSidecar)})}),n(`claude.saveFailed`)),y(!0),g(n(`claude.saved`)),E.refresh()}catch(e){y(!1),g(e instanceof Error&&e.message?e.message:n(`claude.networkError`))}};if(D.kind===`disabled`&&!O)return null;if(D.showSkeleton&&!O)return(0,q.jsx)(Gc,{label:n(`claude.loading`),rows:3});if(D.kind===`failed-cold`){let e=D.error instanceof Error?D.error.message:n(`claude.loadFail`);return(0,q.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[(0,q.jsx)($,{tone:`err`,children:e}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>E.refresh(),children:n(`common.retry`)})]})}if(!k)return null;let F=[{id:`settings`,label:n(`claude.workspace.settings`),body:(0,q.jsx)(gg,{state:k,autoCompactOptions:M,availableModels:k.available??[],onStateChange:u})},{id:`quickstart`,label:n(`claude.quickstart`),body:(0,q.jsx)(_g,{manualEnv:sg(k)})},{id:`smallFast`,label:n(`claude.smallFastModel`),body:(0,q.jsx)(mg,{value:k.smallFastModel,tierHaikuModel:k.tierModels?.haiku,options:j,onChange:e=>u({...k,smallFastModel:e})})},{id:`modelMap`,label:n(`claude.modelMap`),meta:String(A.length),body:(0,q.jsx)(vg,{rows:A,onRowsChange:e=>{m(!0),f(e)}})},{id:`aliases`,label:n(`claude.aliases`),meta:String(k.aliases.length),body:(0,q.jsx)(xg,{aliases:k.aliases})}],I=F.find(e=>e.id===b)??F[0],L=b===`settings`||b===`smallFast`||b===`modelMap`;return(0,q.jsxs)(`div`,{className:`claudecode-workspace-shell`,children:[h&&(0,q.jsx)($,{tone:v?`ok`:`err`,children:h}),D.showError&&(0,q.jsx)($,{tone:`err`,children:n(`claude.loadFail`)}),k&&(0,q.jsxs)(`div`,{className:`claudecode-connection-head`,children:[(0,q.jsx)(`span`,{id:`claudecode-connection-label`,children:n(`claude.enabledLabel`)}),(0,q.jsx)(wt,{on:k.enabled,onClick:()=>void N(),disabled:S,label:n(`claude.toggleAria`)})]}),(0,q.jsxs)(`div`,{className:`claudecode-workspace-root`,children:[(0,q.jsx)(`aside`,{className:`claudecode-workspace-rail`,"aria-label":n(`claude.pageTitle`),children:(0,q.jsx)(`div`,{className:`claudecode-workspace-rail-list`,children:F.map(e=>(0,q.jsx)(`button`,{type:`button`,className:`claudecode-workspace-rail-row${b===e.id?` claudecode-workspace-rail-row--selected`:``}`,onClick:()=>x(e.id),"aria-current":b===e.id?`true`:void 0,children:(0,q.jsx)(`span`,{className:`claudecode-workspace-rail-name`,children:e.label})},e.id))})}),(0,q.jsxs)(`section`,{className:`claudecode-workspace-main`,"aria-label":I.label,children:[(0,q.jsxs)(`div`,{className:`ccw-main-head`,children:[(0,q.jsxs)(`h3`,{className:`ccw-main-title`,children:[I.label,I.meta==null?null:(0,q.jsx)(`span`,{className:`count`,children:I.meta})]}),(0,q.jsx)(`div`,{className:`claudecode-workspace-save`,"data-visible":L?`true`:`false`,children:(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:!L,tabIndex:L?0:-1,"aria-hidden":!L,onClick:()=>{P()},children:n(`common.save`)})})]}),(0,q.jsx)(`div`,{className:`ccw-body`,children:I.body})]})]})]})}function Cg(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 wg(e){return new Set(Object.keys(e))}function Tg(e,t){return t!==null&&e===t}function Eg(e){return e||(typeof localStorage>`u`?void 0:localStorage)}function Dg(e){return{read(t){let n=Eg(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=Eg(n);if(r)try{r.setItem(e,JSON.stringify([...t]))}catch{}}}}function Og(e,t){let n=new Set(e);return n.has(t)?n.delete(t):n.add(t),n}var kg=[`opus`,`fable`,`sonnet`,`haiku`],Ag=Dg(`ocx.claudeDesktop.collapsedFamilies.v2`),jg={opus:`claudeDesktop.family.opus`,fable:`claudeDesktop.family.fable`,sonnet:`claudeDesktop.family.sonnet`,haiku:`claudeDesktop.family.haiku`};function Mg(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 Ng(e){let t={...e.profile.assignments};for(let n of e.models){let e=t[n.route]??n.assignment;t[n.route]={family:kg.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 Pg(e,t){return e&&typeof e==`object`&&`error`in e&&typeof e.error==`string`?e.error:t}function Fg(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 Ig(e){return pr(e)?.data??null}function Lg(e){return pr(e)?.cachedAt??null}function Rg(e){let t=Ig(e);return{held:t,data:t?.data??null,profile:t?.profile??null,savedProfile:t?.profile?Mg(t.profile):null,destinations:t?.data?Object.fromEntries(t.data.models.map(e=>[e.route,t.profile.assignments[e.route]?.family??`opus`])):{}}}function zg({apiBase:e,active:t=!0,onPortChange:n}){let{t:r,locale:i}=st(),a=$e.find(e=>e.code===i)?.htmlLang,o=`ocx.claude-desktop.v1:${e}`,s=`claude-desktop:${e}`,c=(0,_.useMemo)(()=>Rg(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)(()=>Ag.read()??new Set(kg)),[O,k]=(0,_.useState)({}),A=(0,_.useRef)(null),j=(0,_.useCallback)(async t=>{let n=await Nt(await fetch(`${e}/api/claude-desktop`,{signal:t}),r(`claudeDesktop.loadFail`));if(!n||!(`profile`in n)||!(`models`in n))throw Error(Pg(n,r(`claudeDesktop.loadFail`)));let i=Ng(n),a={data:n,profile:i};if(t.aborted)throw Error(`Claude Desktop request aborted`);if(u(i),f(Mg(i)),m(Object.fromEntries(n.models.map(e=>[e.route,i.assignments[e.route]?.family??`opus`]))),Ag.read()===null){let e=Object.fromEntries(kg.map(e=>[e,0]));for(let t of n.models)e[i.assignments[t.route]?.family??`opus`]+=1;D(wg(e))}return mr(o,a),a},[e,o,r,m,u,f]),M=Uc(s,[e],j,{isEmpty:()=>!1,enabled:t,initialData:c.held??void 0,initialDataCachedAt:Lg(o),staleAfterMs:6e4}),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`])):{},z=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 B=(0,_.useMemo)(()=>I!==null&&L!==null&&JSON.stringify(I)!==JSON.stringify(L),[I,L]),V=(0,_.useMemo)(()=>{let e=Object.fromEntries(kg.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]),H=(0,_.useMemo)(()=>{let e={};for(let t of kg){let n=V[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},[V,I]),U=`ocx.claude-desktop.status.v1:${e}`,W=`claude-desktop-status:${e}`,ee=pr(U),G=Uc(W,[e],async t=>{let n=await Pt(await fetch(`${e}/api/claude-desktop/status`,{signal:t}));if(!n)throw Error(`Claude Desktop status unavailable`);return mr(U,n),n},{isEmpty:()=>!1,pollMs:5e3,enabled:t,initialData:ee?.data??void 0}),te=G.state,K=te.data??ee?.data??null,J=te.showError,ne=(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(jg[t])})))},re=e=>{let t=Og(E,e);Ag.write(t),D(t)},ie=async t=>{if(!(!I||b)){x(`save`),g(null);try{await Nt(await fetch(`${e}/api/claude-desktop`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({profile:I})}),r(`claudeDesktop.saveFailed`)),f(Mg(I)),t?(x(`apply`),(await Nt(await fetch(`${e}/api/claude-desktop/apply`,{method:`POST`}),r(`claudeDesktop.applyFailed`)))?.saved===!1?(g({tone:`warn`,text:r(`claudeDesktop.appliedMarkerUnsaved`)}),y(r(`claudeDesktop.appliedMarkerUnsaved`))):(g({tone:`ok`,text:r(`claudeDesktop.savedApplied`)}),y(r(`claudeDesktop.savedAppliedAnnounce`)))):(g({tone:`ok`,text:r(`claudeDesktop.saved`)}),y(r(`claudeDesktop.savedAnnounce`))),G.refresh()}catch(e){let t=e instanceof Error?e.message:r(`claudeDesktop.updateFailed`);g({tone:`err`,text:t}),y(t)}finally{x(null)}}},Y=()=>{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`))},ae=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`));let n=Ng({...F,profile:e});u(n),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}))}},oe=(e,t)=>{e.preventDefault();let n=e.dataTransfer.getData(`text/plain`);n&&ne(n,t)};if(N.kind===`disabled`&&!P)return null;if(N.showSkeleton&&!P)return(0,q.jsx)(Gc,{label:r(`claudeDesktop.loading`),rows:4});if(N.kind===`failed-cold`){let e=N.error instanceof Error?N.error.message:r(`claudeDesktop.loadFail`);return(0,q.jsxs)(`div`,{className:`claude-desktop-error`,children:[(0,q.jsx)($,{tone:`err`,children:e}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>M.refresh(),children:r(`claudeDesktop.retry`)})]})}return!F||!I?null:(0,q.jsxs)(q.Fragment,{children:[(0,q.jsx)(`div`,{className:`claude-desktop-toolbar`,children:(0,q.jsxs)(`div`,{className:`claude-profile-tools`,children:[(0,q.jsx)(`input`,{ref:A,type:`file`,accept:`application/json,.json`,hidden:!0,onChange:e=>void ae(e)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A.current?.click(),children:r(`claudeDesktop.importJson`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:Y,children:r(`claudeDesktop.exportJson`)})]})}),(0,q.jsxs)(`div`,{className:`claude-status-bar ${J&&!K?`not-applied`:K?K.desiredEnabled?K.activeProfile===!1?`not-applied`:K.stale?`stale`:K.applied?`applied`:`not-applied`:`not-applied`:`pending`}`,"aria-busy":!K&&!J||void 0,children:[(0,q.jsx)(`span`,{className:`claude-status-dot`}),(0,q.jsx)(`span`,{children:J&&!K?r(`claudeDesktop.loadFail`):K?K.desiredEnabled?K.activeProfile===!1?r(`claudeDesktop.status.notActiveProfile`):K.stale?r(`claudeDesktop.status.stale`):K.applied?r(`claudeDesktop.status.applied`):r(`claudeDesktop.status.notApplied`):r(`claudeDesktop.status.disabled`):r(`claudeDesktop.loading`)}),K?.health.lastRequestAt&&(0,q.jsxs)(`span`,{className:`claude-status-health`,children:[r(`claudeDesktop.health.lastRequest`),`:`,` `,new Date(K.health.lastRequestAt).toLocaleTimeString(a)]}),K&&K.health.requestCount>0&&(0,q.jsx)(`span`,{className:`claude-status-health`,children:r(`claudeDesktop.health.stats`,{count:K.health.requestCount,errors:K.health.errorCount})})]}),(0,q.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:v}),h&&(0,q.jsx)($,{tone:h.tone,children:h.text}),N.showError&&(0,q.jsx)($,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),J&&K&&(0,q.jsx)($,{tone:`err`,children:r(`claudeDesktop.loadFail`)}),(0,q.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,q.jsx)(`span`,{className:`claude-dirty${B?` active`:``}`,children:r(B?`claudeDesktop.unsaved`:`claudeDesktop.upToDate`)}),(0,q.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!B||b!==null,onClick:()=>void ie(!1),children:r(b===`save`?`claudeDesktop.saving`:`common.save`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:b!==null,onClick:()=>void ie(!0),children:b===`apply`?r(`claudeDesktop.applying`):b===`save`?r(`claudeDesktop.saving`):K?.desiredEnabled===!1?r(`claudeDesktop.enableApply`):r(`claudeDesktop.saveApply`)})]})]}),F.models.length===0&&(0,q.jsx)(Dt,{title:r(`claudeDesktop.emptyTitle`),children:r(`claudeDesktop.emptyHint`)}),(0,q.jsx)(`div`,{className:`ocx-group-stack`,"aria-label":r(`claudeDesktop.assignmentsLabel`),children:kg.map(e=>{let t=V[e],n=Cg(t,S[e]??``,w[e]??6),i=E.has(e),a=H[e];return(0,q.jsxs)(`section`,{className:`ocx-group${i?` collapsed`:``}`,"aria-labelledby":`claude-lane-${e}`,onDragOver:e=>e.preventDefault(),onDrop:t=>oe(t,e),children:[(0,q.jsxs)(`header`,{className:`ocx-group-head${i?``:` open`}`,children:[(0,q.jsx)(`h3`,{id:`claude-lane-${e}`,className:`ocx-group-heading`,children:(0,q.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!i,"aria-controls":`claude-lane-body-${e}`,onClick:()=>re(e),children:[(0,q.jsx)(xe,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:i?`none`:`rotate(90deg)`}}),(0,q.jsx)(`span`,{className:`ocx-group-name`,children:r(jg[e])}),(0,q.jsx)(`span`,{className:`ocx-group-count`,children:r(t.length===1?`claudeDesktop.modelCountOne`:`claudeDesktop.modelCountMany`,{count:t.length})}),a&&(0,q.jsx)(`code`,{className:`claude-lane-default`,title:a,children:a})]})}),t.length>0&&I.defaults[e]===null&&(0,q.jsx)(`span`,{className:`claude-default-needed`,children:r(`claudeDesktop.chooseDefault`)}),a&&a!==I.defaults[e]&&(0,q.jsx)(`span`,{className:`claude-default-needed`,title:a,children:r(`claudeDesktop.temporaryDefault`)})]}),!i&&(0,q.jsxs)(`div`,{id:`claude-lane-body-${e}`,children:[n.showSearch&&(0,q.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,q.jsxs)(`div`,{className:`claude-lane-models`,children:[t.length===0?(0,q.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneEmpty`)}):n.noMatch?(0,q.jsx)(`div`,{className:`claude-lane-empty`,children:r(`claudeDesktop.laneNoMatch`)}):n.shown.map(t=>{let n=I.assignments[t.route],i=Fg(t.contextWindow,r),a=z[t.route]??`opus`,o=O[t.route]??Tg(t.route,H[e]);return(0,q.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,q.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,q.jsx)(xe,{className:`ocx-chevron`,width:12,height:12,"aria-hidden":`true`,style:{transform:o?`rotate(90deg)`:`none`}}),(0,q.jsxs)(`span`,{className:`claude-model-names`,children:[(0,q.jsx)(`strong`,{title:t.label,children:t.label}),(0,q.jsx)(`code`,{title:t.route,children:t.route})]}),i&&(0,q.jsx)(`span`,{className:`claude-model-context`,children:i}),!i&&(0,q.jsx)(`span`,{className:`claude-model-context claude-model-context-unknown`,children:r(`claudeDesktop.contextUnknown`)}),t.supports1m===!0&&(0,q.jsx)(`span`,{className:`claude-1m-chip`,children:r(`claudeDesktop.supports1m`)}),t.effortSupported===!1&&(0,q.jsx)(`span`,{className:`claude-effort-badge off`,children:r(`claudeDesktop.effort.displayOnly`)}),t.effortSupported===!0&&(0,q.jsx)(`span`,{className:`claude-effort-badge on`,children:r(`claudeDesktop.effort.supported`)}),I.defaults[e]===t.route&&(0,q.jsx)(`span`,{className:`claude-row-default`,children:r(`claudeDesktop.defaultBadge`)}),(0,q.jsx)(`span`,{className:`badge ${t.available?`badge-green`:`badge-muted`}`,children:t.available?r(`claudeDesktop.available`):r(`claudeDesktop.unavailable`)})]}),o&&(0,q.jsxs)(`div`,{className:`claude-model-body`,id:`claude-model-body-${t.route}`,children:[H[e]===t.route&&I.defaults[e]!==t.route&&(0,q.jsx)(`span`,{className:`claude-effective-default`,children:r(`claudeDesktop.temporaryDefault`)}),(0,q.jsxs)(`div`,{className:`claude-field`,children:[(0,q.jsx)(`span`,{children:r(`claudeDesktop.alias`)}),(0,q.jsx)(`code`,{className:`claude-alias`,title:n.alias,children:n.alias})]}),(0,q.jsxs)(`label`,{className:`claude-default-radio`,children:[(0,q.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(jg[e])})]}),(0,q.jsxs)(`div`,{className:`claude-move-row`,children:[(0,q.jsx)(`label`,{htmlFor:`move-${t.route}`,children:r(`claudeDesktop.moveTo`)}),(0,q.jsx)(`select`,{id:`move-${t.route}`,className:`input`,value:a,disabled:!t.available,onChange:e=>m(n=>({...n,[t.route]:e.target.value})),children:kg.map(e=>(0,q.jsx)(`option`,{value:e,children:r(jg[e])},e))}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,disabled:!t.available||a===e,onClick:()=>ne(t.route,a),children:r(`claudeDesktop.move`)})]})]})]},t.route)}),n.hidden>0&&(0,q.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)})})]})}var Bg=`integrations/claude`,Vg=`integrations/claude/desktop`;function Hg(e=typeof window<`u`?window.location.hash:``){return ut(e)===Vg?`desktop`:`code`}function Ug(e){let t=dr(`ocx.claude-desktop.v1:${e}`);return typeof t?.data?.port==`number`?t.data.port:null}function Wg({apiBase:e,active:t=!0}){let[n,r]=(0,_.useState)(Hg),i=Q(),a=(0,_.useRef)(null),o=(0,_.useRef)(null),s=Ug(e),[c,l]=(0,_.useState)(null),u=c?.base===e?c.port:s,d=c?.base===e,f=(0,_.useCallback)(t=>{l(n=>n?.base===e&&n.port===t?n:{base:e,port:t})},[e]);(0,_.useEffect)(()=>{let e=()=>r(Hg());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let p=e=>{ft(e===`desktop`?Vg:Bg),r(e),window.requestAnimationFrame(()=>{(e===`code`?a:o).current?.focus({preventScroll:!0})})},m=e=>{e.key===`ArrowLeft`||e.key===`ArrowRight`?(e.preventDefault(),p(n===`code`?`desktop`:`code`)):e.key===`Home`?(e.preventDefault(),p(`code`)):e.key===`End`&&(e.preventDefault(),p(`desktop`))};return(0,q.jsxs)(`section`,{className:`claude-page`,children:[(0,q.jsxs)(`div`,{className:`claude-page-intro`,children:[(0,q.jsx)(`div`,{className:`page-head`,children:(0,q.jsx)(`h2`,{children:i(n===`code`?`claude.pageTitle`:`claudeDesktop.title`)})}),n===`code`?(0,q.jsx)(`p`,{className:`page-sub`,children:i(`claude.subtitle`)}):(0,q.jsx)(`p`,{className:`page-sub`,children:u==null?i(d?`claudeDesktop.loadFail`:`claudeDesktop.loading`):i(`claudeDesktop.subtitle`,{port:u})})]}),(0,q.jsxs)(`div`,{className:`claude-tabs`,role:`tablist`,"aria-label":i(`claude.tabsLabel`),children:[(0,q.jsx)(`button`,{type:`button`,role:`tab`,ref:a,"aria-selected":n===`code`,"aria-controls":`claude-code-panel`,id:`claude-code-tab`,className:n===`code`?`active`:``,tabIndex:n===`code`?0:-1,onKeyDown:m,onClick:()=>p(`code`),children:i(`claude.tabCode`)}),(0,q.jsx)(`button`,{type:`button`,role:`tab`,ref:o,"aria-selected":n===`desktop`,"aria-controls":`claude-desktop-panel`,id:`claude-desktop-tab`,className:n===`desktop`?`active`:``,tabIndex:n===`desktop`?0:-1,onKeyDown:m,onClick:()=>p(`desktop`),children:i(`claude.tabDesktop`)})]}),(0,q.jsx)(`div`,{id:`claude-code-panel`,role:`tabpanel`,"aria-labelledby":`claude-code-tab`,hidden:n!==`code`,children:(0,q.jsx)(Sg,{apiBase:e,active:t&&n===`code`},e)}),(0,q.jsx)(`div`,{id:`claude-desktop-panel`,role:`tabpanel`,"aria-labelledby":`claude-desktop-tab`,hidden:n!==`desktop`,children:(0,q.jsx)(zg,{apiBase:e,active:t&&n===`desktop`,onPortChange:f},e)})]})}function Gg(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 Kg=Dg(`ocx.grok.collapsedGroups.v2`),qg=[{id:`native`,tkey:`grok.groupNative`},{id:`routed`,tkey:`grok.groupRouted`}],Jg=new Set(qg.map(e=>e.id));function Yg(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 Xg({apiBase:e,active:t=!0}){let n=Q(),r=`ocx.grok.status.v1:${e}`,i=pr(r),a=i?.data??null,[o,s]=(0,_.useState)(null),[c,l]=(0,_.useState)(()=>Kg.read()??new Set(Jg)),[u,d]=(0,_.useState)(null),[f,p]=(0,_.useState)(null),[m,h]=(0,_.useState)(``),g=(0,_.useCallback)(async t=>{let i=await Nt(await fetch(`${e}/api/grok`,{signal:t}),n(`grok.loadFail`));if(!i)throw Error(n(`grok.loadFail`));let a={...i,candidates:i.candidates??[],excluded:i.excluded??[]};return mr(r,a),a},[e,r,n]),v=`grok-status:${e}`,y=Uc(v,[e],g,{isEmpty:()=>!1,initialData:a??void 0,initialDataCachedAt:i?.cachedAt??null,staleAfterMs:6e4,enabled:t}),{state:b}=y,x=y.refresh,S=b.data??a,C=(0,_.useMemo)(()=>new Set(S?.excluded??[]),[S]),w=o??C,T=(0,_.useMemo)(()=>o!==null&&(o.size!==C.size||[...o].some(e=>!C.has(e))),[o,C]),E=(0,_.useMemo)(()=>new Map((S?.models??[]).map(e=>[e.id,e.alias])),[S]),D=e=>{let t=Og(c,e);Kg.write(t),l(t)},O=e=>{let t=e?new Set(qg.map(e=>e.id)):new Set;Kg.write(t),l(t)},k=(e,t)=>{s(n=>{let r=new Set(n??C);return t?r.delete(e):r.add(e),r})},A=async t=>{if(!u){d(`save`),p(null);try{await Nt(await fetch(`${e}/api/grok/selection`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({excluded:[...w]})}),n(`grok.saveFailed`));let i=[...w];if(S&&te(v,{...S,excluded:i}),s(null),t){d(`apply`);let t=await fetch(`${e}/api/grok/apply`,{method:`POST`});if(!t.ok){let e=await t.json().catch(()=>({}));throw Error(e.message??e.error??n(`grok.applyFailed`))}let r=await t.json().catch(()=>({}));r.skippedReason?(p({tone:`err`,text:r.message??n(`grok.applySkipped`)}),h(r.message??n(`grok.applySkipped`))):(p({tone:`ok`,text:n(`grok.savedApplied`)}),h(n(`grok.savedApplied`))),await x()}else p({tone:`ok`,text:n(`grok.saved`)}),h(n(`grok.saved`)),S&&mr(r,{...S,excluded:i})}catch(e){let t=e instanceof Error?e.message:n(`grok.saveFailed`);p({tone:`err`,text:t}),h(t)}finally{d(null)}}};if(b.showSkeleton&&!S)return(0,q.jsx)(`section`,{className:`grok-page`,children:(0,q.jsx)(Gc,{label:n(`grok.loading`),rows:4})});if(b.kind===`failed-cold`){let e=b.error instanceof Error?b.error.message:n(`grok.loadFail`);return(0,q.jsxs)(`section`,{className:`grok-page`,children:[(0,q.jsx)(`div`,{className:`alert alert-err`,role:`alert`,children:e}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>x(),children:n(`common.retry`)})]})}return(0,q.jsxs)(`section`,{className:`grok-page`,"aria-busy":b.refreshing||void 0,children:[(0,q.jsx)(`h2`,{className:`page-title`,children:n(`grok.title`)}),(0,q.jsx)(`p`,{className:`page-sub`,children:n(`grok.subtitle`)}),(0,q.jsx)(`div`,{className:`sr-only`,"aria-live":`polite`,"aria-atomic":`true`,children:m}),f&&(0,q.jsx)($,{tone:f.tone,children:f.text}),b.showError&&(0,q.jsx)($,{tone:`err`,children:n(`grok.loadFail`)}),S&&S.candidates.length>0&&(0,q.jsxs)(`div`,{className:`claude-profile-bar`,children:[(0,q.jsx)(`span`,{className:`claude-dirty${T?` active`:``}`,children:n(T?`grok.unsaved`:`grok.upToDate`)}),(0,q.jsxs)(`div`,{className:`claude-save-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,disabled:!T||u!==null,onClick:()=>void A(!1),children:n(u===`save`?`grok.saving`:`common.save`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:!T||u!==null,onClick:()=>void A(!0),children:n(u===`apply`?`grok.applying`:u===`save`?`grok.saving`:`grok.saveApply`)})]})]}),S?.present?(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{className:`grok-endpoint`,children:[(0,q.jsx)(`span`,{children:n(`grok.endpoint`)}),(0,q.jsx)(`code`,{children:S.baseUrl??`—`})]}),(0,q.jsx)(`p`,{className:`page-sub`,children:(0,q.jsx)(`code`,{children:S.configPath})})]}):(0,q.jsxs)(Dt,{title:n(`grok.notConfiguredTitle`),children:[n(`grok.notConfiguredHint`),(0,q.jsx)(`br`,{}),(0,q.jsx)(`code`,{children:S?.configPath})]}),S&&S.candidates.length>0&&(0,q.jsxs)(`div`,{className:`ocx-group-stack`,children:[(0,q.jsxs)(`div`,{className:`row`,style:{gap:6,margin:`2px 0 10px`},children:[(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>O(!0),disabled:u!==null,children:[(0,q.jsx)(xe,{width:12,height:12,"aria-hidden":`true`}),` `,n(`models.collapseAll`)]}),(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm text-caption`,onClick:()=>O(!1),disabled:u!==null,children:[(0,q.jsx)(xe,{width:12,height:12,"aria-hidden":`true`,style:{transform:`rotate(90deg)`}}),` `,n(`models.expandAll`)]})]}),qg.map(e=>{let t=Gg(S.candidates,E,w,e.id);if(t.total===0)return null;let r=c.has(e.id);return(0,q.jsxs)(`section`,{className:`ocx-group${r?` collapsed`:``}`,"aria-labelledby":`grok-group-${e.id}`,children:[(0,q.jsx)(`header`,{className:`ocx-group-head${r?``:` open`}`,children:(0,q.jsx)(`h3`,{id:`grok-group-${e.id}`,className:`ocx-group-heading`,children:(0,q.jsxs)(`button`,{type:`button`,className:`ocx-group-toggle`,"aria-expanded":!r,"aria-controls":`grok-group-body-${e.id}`,onClick:()=>D(e.id),children:[(0,q.jsx)(xe,{className:`ocx-chevron`,width:14,height:14,"aria-hidden":`true`,style:{transform:r?`none`:`rotate(90deg)`}}),(0,q.jsx)(`span`,{className:`ocx-group-name`,children:n(e.tkey)}),(0,q.jsx)(`span`,{className:`ocx-group-count`,children:n(`grok.enabledCount`,{on:t.enabled,total:t.total})})]})})}),!r&&(0,q.jsx)(`div`,{id:`grok-group-body-${e.id}`,className:`grok-model-list`,children:t.rows.map(e=>(0,q.jsxs)(`div`,{className:`grok-model-row`,children:[(0,q.jsx)(wt,{on:e.enabled,onClick:()=>k(e.id,!e.enabled),disabled:u!==null,label:n(`grok.toggleModel`,{id:e.id})}),(0,q.jsxs)(`span`,{className:`grok-model-names`,children:[(0,q.jsx)(`strong`,{title:e.id,children:e.id}),(0,q.jsx)(`code`,{title:e.alias??void 0,children:e.alias??`—`})]}),(0,q.jsx)(`span`,{className:`claude-model-context`,children:Yg(e.contextWindow,n)})]},e.id))})]},e.id)})]})]})}var Zg={"not-installed":`integrations.state.notInstalled`,unknown:`integrations.state.unknown`,absent:`integrations.state.absent`,current:`integrations.state.current`,stale:`integrations.state.stale`,conflict:`integrations.state.conflict`,unsafe:`integrations.state.unsafe`},Qg={"not-installed":`badge badge-muted`,unknown:`badge badge-muted`,absent:`badge badge-muted`,current:`badge badge-green`,stale:`badge badge-amber`,conflict:`badge integration-badge--danger`,unsafe:`badge integration-badge--danger-outline`};function $g({state:e,installed:t,id:n}){let r=Q(),i=e===`unknown`||e===`not-installed`||t?e:`not-installed`;return(0,q.jsx)(`span`,{id:n,className:Qg[i],"data-integration-state":i,children:r(Zg[i])})}function e_({copyKey:e,vars:t}){let n=Q()(e,t),r=t?.path;if(!r||!n.includes(r))return(0,q.jsx)(`p`,{children:n});let[i,...a]=n.split(r);return(0,q.jsxs)(`p`,{children:[i,(0,q.jsx)(`code`,{children:r}),a.join(r)]})}function t_({copy:e,onConfirm:t,onClose:n}){let r=Q(),i=(0,_.useRef)(null),[a,o]=(0,_.useState)(!1),[s,c]=(0,_.useState)(null),l=`integration-consequence-dialog-title`;(0,_.useEffect)(()=>{let e=i.current;return e&&!e.open&&e.showModal(),()=>{e?.open&&e.close()}},[]);let u=(0,_.useCallback)(e=>{e.preventDefault(),a||n()},[n,a]),d=(0,_.useCallback)(async()=>{if(!a){o(!0),c(null);try{await t()}catch(e){c(e instanceof Error?e.message:r(`integrations.error.generic`)),o(!1)}}},[t,a,r]),f=[(0,q.jsx)(e_,{copyKey:e.changesKey,vars:e.vars},`changes`),(0,q.jsx)(e_,{copyKey:e.breakageKey,vars:e.vars},`breakage`),(0,q.jsx)(e_,{copyKey:e.undoKey,vars:e.vars},`undo`)];return e.sideEffectKey&&f.push((0,q.jsx)(e_,{copyKey:e.sideEffectKey,vars:e.vars},`side-effect`)),(0,q.jsxs)(`dialog`,{ref:i,className:`modal-overlay`,"aria-labelledby":l,onCancel:u,children:[(0,q.jsx)(`button`,{type:`button`,className:`modal-backdrop-dismiss`,"aria-label":r(`common.close`),tabIndex:-1,onClick:()=>{a||n()}}),(0,q.jsxs)(`div`,{className:`modal-card integration-consequence-dialog`,role:`document`,children:[(0,q.jsxs)(`div`,{className:`modal-head`,children:[(0,q.jsx)(`h3`,{id:l,children:r(e.titleKey,e.vars)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:n,disabled:a,children:r(`common.close`)})]}),(0,q.jsx)(`div`,{className:`integration-consequence-body`,children:f}),s&&(0,q.jsx)($,{tone:`err`,children:s}),(0,q.jsx)(`div`,{className:`modal-actions`,children:(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:()=>void d(),disabled:a,children:r(e.confirmKey)})})]})]})}var n_=[`opencode`,`pi`,`omp`,`hermes`,`openclaw`,`kimi`,`gajae`,`dsh`,`mcode`,`zcode`,`prime`],r_=new Set([`not_installed`,`conflict`,`unsafe`,`non_loopback`,`drift_requires_confirm`,`snapshot_expired`,`write_failed`]),i_=new Set([`integration_unsafe`,`integration_conflict`,`integration_drift_confirmation_required`,`integration_snapshot_expired`,`integration_mutation_failed`]),a_=new Set([`absent`,`current`,`stale`,`conflict`,`unsafe`]);function o_(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function s_(e){return!o_(e)||!r_.has(String(e.reason))?!1:typeof e.error==`string`&&i_.has(String(e.code))&&n_.includes(e.clientId)&&a_.has(String(e.state))&&typeof e.message==`string`}var c_=class extends Error{refusal;status;body;constructor(e,t){let n=s_(t)?t:null;super(n?.message??t.error??t.message??String(e)),this.name=`IntegrationApiError`,this.status=e,this.body=t,this.refusal=n}};async function l_(e){try{let t=await e.json();return o_(t)?t:{}}catch{return{}}}async function u_(e){if(!e.ok)throw new c_(e.status,await l_(e));let t=await Pt(e);if(t==null)throw new c_(e.status,{});return t}async function d_(e,t){return u_(await fetch(`${e}/api/client-integrations`,{signal:t}))}async function f_(e,t,n){return u_(await fetch(`${e}/api/client-integrations/${encodeURIComponent(t)}`,{signal:n}))}async function p_(e,t,n){let r=t?`?client=${encodeURIComponent(t)}`:``;return u_(await fetch(`${e}/api/client-integrations/journal${r}`,{signal:n}))}async function m_(e,t,n,r){return u_(await fetch(`${e}/api/client-integrations/${encodeURIComponent(t)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:n}),signal:r}))}async function h_(e,t,n=!1,r){return u_(await fetch(`${e}/api/client-integrations/restore`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({opId:t,confirmDrift:n}),signal:r}))}async function g_(e){try{let t=await e;return t.ok?await Pt(t)??null:null}catch{return null}}async function __(e,t){let n=await g_(fetch(`${e}/api/startup-health`,{signal:t}));return n?{routingInjected:n.routingInjected===!0,status:typeof n.status==`string`?n.status:void 0,recommendedCommand:typeof n.recommendedCommand==`string`?n.recommendedCommand:null}:null}async function v_(e,t){let n=await fetch(`${e}/api/keys`,{signal:t});if(!n.ok)throw Error(`/api/keys responded ${n.status}`);let r=await Pt(n);if(!r||!Array.isArray(r.keys))throw Error(`/api/keys returned an unexpected body`);return r.keys.length}async function y_(e,t){let n=await g_(fetch(`${e}/api/claude-code`,{signal:t}));return n?{enabled:n.enabled===!0,authMode:typeof n.authMode==`string`?n.authMode:void 0}:null}async function b_(e,t){let n=await g_(fetch(`${e}/api/claude-desktop/status`,{signal:t}));return!n||typeof n.desiredEnabled!=`boolean`||typeof n.installed!=`boolean`||typeof n.observedKind!=`string`?null:{desiredEnabled:n.desiredEnabled,installed:n.installed,observedKind:n.observedKind,applied:n.applied===!0,stale:n.stale===!0,drift:n.drift===!0,driftReason:typeof n.driftReason==`string`?n.driftReason:null,activeProfile:typeof n.activeProfile==`boolean`?n.activeProfile:null,appliedAt:typeof n.appliedAt==`string`?n.appliedAt:null}}async function x_(e,t){let n=await g_(fetch(`${e}/api/grok`,{signal:t}));return n?{present:n.present===!0,models:Array.isArray(n.models)?n.models:[]}:null}var S_=new Set([`claude`,`grok`,`codex`,`claude-desktop`]),C_=new Set([`native_integration_refused`,`native_integration_failed`]),w_=new Set([`not_installed`,`orphaned_marker`,`home_mismatch`,`config_busy`,`write_failed`,`metadata_unreadable`,`cleanup_incomplete`,`desired_state_changed`]);function T_(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function E_(e){return T_(e)?typeof e.error==`string`&&C_.has(String(e.code))&&S_.has(String(e.clientId))&&w_.has(String(e.reason))&&typeof e.message==`string`:!1}var D_=class extends Error{refusal;status;body;constructor(e,t){let n=E_(t)?t:null;super(n?.message??t.error??t.message??String(e)),this.name=`NativeApiError`,this.status=e,this.body=t,this.refusal=n}};async function O_(e){try{let t=await e;return t.ok?await Pt(t)??null:null}catch{return null}}async function k_(e){try{let t=await e.json();return T_(t)?t:{}}catch{return{}}}async function A_(e){if(!e.ok)throw new D_(e.status,await k_(e));let t=await Pt(e);if(t==null)throw new D_(e.status,{});return t}function j_(e,t){return O_(fetch(`${e}/api/native-integrations`,{signal:t}))}async function M_(e,t,n,r){return A_(await fetch(`${e}/api/native-integrations/${encodeURIComponent(t)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({enabled:n}),signal:r}))}var N_={integration_mutation_busy:`integrations.error.busy`};function P_(e){return e instanceof c_?e.refusal:null}function F_(e){return e instanceof D_?e.refusal:null}function I_(e){return e===`conflict`?`integrations.error.conflict`:e===`unsafe`?`integrations.error.unsafe`:e===`non_loopback`?`integrations.error.nonLoopback`:`integrations.error.generic`}var L_=new Set([`non_loopback`]);function R_(e,t,n){return t.reason===`orphaned_marker`?e(`integrations.native.error.orphanedMarker`,{path:n??``}):t.reason===`home_mismatch`?`${e(`integrations.native.error.homeMismatch`)} ${t.message}`:t.reason===`not_installed`?e(`integrations.native.error.notInstalled`):t.reason===`config_busy`?e(`integrations.native.error.configBusy`):t.reason===`metadata_unreadable`?e(`integrations.native.error.desktopUnsafeMetadata`,{path:n??``}):t.reason===`cleanup_incomplete`?e(`integrations.native.error.desktopCleanupIncomplete`,{paths:(t.residualPaths??[]).join(`, `)}):t.message||e(`integrations.error.generic`)}function z_(e,t,n,r){let i=F_(t);if(i)return R_(e,i,r);let a=P_(t);if(!a){let r=N_[t instanceof c_?String(t.body.code??``):``];return r?e(r):t instanceof Error&&t.message?t.message:n??e(`integrations.error.generic`)}let o=L_.has(a.reason)?e(I_(a.reason),{client:a.clientId}):a.message||e(I_(a.reason));return a.snapshotPath?e(a.residual?`integrations.error.residual`:`integrations.error.recover`,{message:o,path:a.snapshotPath}):a.reason===`conflict`||a.reason===`unsafe`?`${e(I_(a.reason))} ${o}`:o}function B_({apiBase:e,row:t,onClose:n,onRestored:r}){let i=Q(),[a,o]=(0,_.useState)(!1),[s,c]=(0,_.useState)(!1),[l,u]=(0,_.useState)(null),d=async()=>{if(!s){c(!0),u(null);try{await h_(e,t.opId,a),r(),n()}catch(e){if(P_(e)?.reason===`drift_requires_confirm`){o(!0),c(!1);return}u(z_(i,e)),c(!1)}}};return(0,q.jsx)(`dialog`,{className:`modal-overlay`,open:!0,style:{display:`flex`,border:`none`,margin:0,maxWidth:`none`,maxHeight:`none`,width:`100%`,height:`100%`},"aria-labelledby":`integration-restore-title`,onCancel:e=>{e.preventDefault(),n()},children:(0,q.jsxs)(`div`,{className:`modal-card integration-restore-dialog`,children:[(0,q.jsx)(`div`,{className:`modal-head`,children:(0,q.jsx)(`h3`,{id:`integration-restore-title`,children:i(a?`integrations.restore.driftTitle`:`integrations.restore.title`)})}),(0,q.jsx)(`div`,{className:`modal-desc`,children:i(a?`integrations.restore.driftBody`:`integrations.restore.body`)}),(0,q.jsx)(`p`,{className:`integration-path`,children:t.configPath}),l&&(0,q.jsx)($,{tone:`err`,children:l}),(0,q.jsxs)(`div`,{className:`modal-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:n,disabled:s,children:i(`common.cancel`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:()=>void d(),disabled:s,children:i(s?`integrations.restore.pending`:a?`integrations.restore.confirmDrift`:`integrations.restore.confirm`)})]})]})})}var V_={opencode:`integrations.tab.opencode`,pi:`integrations.tab.pi`,omp:`integrations.tab.omp`,hermes:`integrations.tab.hermes`,openclaw:`integrations.tab.openclaw`,kimi:`integrations.tab.kimi`,gajae:`integrations.tab.gajae`,dsh:`integrations.tab.dsh`,mcode:`integrations.tab.mcode`,zcode:`integrations.tab.zcode`,prime:`integrations.tab.prime`};function H_(e){return e===`current`||e===`stale`}function U_(e){let t={id:`codex`,hash:`integrations/codex`,labelKey:`integrations.tab.codex`,toggle:`codex`,toggleBlocked:null,togglePath:null,status:null,detail:null,detailVars:null};return e?e.routingInjected===!0?{...t,state:e.status===`error`?`stale`:`current`,installed:!0,applied:!0,detailKey:`integrations.detail.codexRouted`}:{...t,state:`absent`,installed:!0,applied:!1,detail:e.recommendedCommand??null,detailKey:e.recommendedCommand?null:`integrations.detail.codexAbsent`}:{...t,state:`unknown`,installed:!1,applied:!1,detailKey:null}}function W_(e,t){let n={hash:`integrations/keys`,labelKey:`integrations.tab.keys`};return e===`checking`?{...n,state:`checking`,detailKey:`integrations.detail.keyChecking`,detailVars:null}:e===`unavailable`||t===null?{...n,state:`unavailable`,detailKey:`integrations.detail.keyUnavailable`,detailVars:null}:{...n,state:t>0?`issued`:`none-issued`,detailKey:t>0?`integrations.detail.keyCount`:`integrations.detail.keyNone`,detailVars:t>0?{count:String(t)}:null}}function G_(e){return e?e.enabled===!0?e.authMode===`subscription`?`claude.authModeSubscription`:e.authMode===`proxy`?`claude.authModeProxy`:e.authMode===`auto`?`claude.authModeAuto`:null:`integrations.detail.claudeOff`:null}function K_(e,t,n){let r={id:`claude`,hash:`integrations/claude`,labelKey:`integrations.tab.claude`,toggle:`claude`,toggleBlocked:t?.disableBlocked??null,togglePath:t?.configPath??null,status:null,detail:null,detailVars:null},i=G_(e);if(n===void 0){if(!e)return{...r,state:`unknown`,installed:!1,applied:!1,detailKey:i};let t=e.enabled===!0;return{...r,state:t?`current`:`absent`,installed:!0,applied:t,detailKey:i}}return n?t?{...r,state:t.state,installed:t.installed,applied:t.state===`current`,detailKey:i}:{...r,toggle:null,state:`unknown`,installed:!1,applied:!1,detailKey:i}:{...r,state:`unknown`,installed:!1,applied:!1,detailKey:i}}function q_(e,t,n){let r={id:`claudeDesktop`,hash:`integrations/claude/desktop`,labelKey:`claudeDesktop.title`,toggle:`claude-desktop`,toggleBlocked:t?.disableBlocked??null,togglePath:t?.configPath??null,status:null,detail:null,detailVars:null};if(!e||!n||!t||typeof e.desiredEnabled!=`boolean`)return{...r,toggle:null,state:`unknown`,installed:!1,applied:!1,detailKey:null};let i=e.desiredEnabled;if(!i)return e.applied===!0||e.driftReason===`desired_off_gateway_selected`?{...r,state:`stale`,installed:e.installed===!0,applied:!0,toggleOn:!1,detailKey:`integrations.detail.desktopDesiredOffCleanupPending`}:{...r,state:`absent`,installed:e.installed===!0,applied:!1,toggleOn:!1,detailKey:`integrations.detail.desktopDesiredOff`};if(e.applied!==!0)return{...r,state:`absent`,installed:e.installed===!0,applied:!1,toggleOn:i,detailKey:`integrations.detail.desktopDesiredOnNotApplied`};let a=e.stale===!0||e.activeProfile===!1;return{...r,state:a?`stale`:`current`,installed:!0,applied:!0,toggleOn:i,detailKey:e.activeProfile===!1?`integrations.detail.desktopNotServed`:a?`integrations.detail.desktopStale`:`integrations.detail.desktopCurrent`}}function J_(e){if(!e)return{detailKey:null,detailVars:null};let t=e.present===!0;return{detailKey:t?`integrations.detail.grokModels`:`integrations.detail.grokAbsent`,detailVars:t?{count:String(e.models?.length??0)}:null}}function Y_(e,t,n){let r={id:`grok`,hash:`integrations/grok`,labelKey:`integrations.tab.grok`,toggle:`grok`,toggleBlocked:t?.disableBlocked??null,togglePath:t?.configPath??null,status:null,detail:null},i=J_(e);if(n===void 0){if(!e)return{...r,state:`unknown`,installed:!1,applied:!1,...i};let t=e.present===!0;return{...r,state:t?`current`:`absent`,installed:t,applied:t,...i}}return n?t?{...r,state:t.state,installed:t.installed,applied:t.state===`current`,...i}:{...r,toggle:null,state:`unknown`,installed:!1,applied:!1,...i}:{...r,state:`unknown`,installed:!1,applied:!1,...i}}function X_(e){return{id:e.clientId,hash:`integrations/${e.clientId}`,labelKey:V_[e.clientId],state:e.installed?e.state:`not-installed`,installed:e.installed,applied:e.installed&&H_(e.state),detail:e.configPath,detailKey:null,detailVars:null,toggle:e.clientId,toggleBlocked:null,togglePath:e.configPath,status:e}}function Z_(e){let t=e.native?.find(e=>e.clientId===`claude`),n=e.native?.find(e=>e.clientId===`grok`),r=new Map(e.clients.map(e=>[e.clientId,e])),i=[U_(e.codex),K_(e.claude,t,e.nativeSettled),q_(e.claudeDesktop,e.native?.find(e=>e.clientId===`claude-desktop`),e.nativeSettled),Y_(e.grok,n,e.nativeSettled)];for(let t of n_){let n=r.get(t);if(n){i.push(X_(n));continue}e.clientsSettled||i.push({id:t,hash:`integrations/${t}`,labelKey:V_[t],state:`unknown`,installed:!1,applied:!1,detail:null,detailKey:null,detailVars:null,toggle:null,toggleBlocked:null,togglePath:null,status:null})}return{keysRow:W_(e.keyPhase,e.keyCount),rows:i}}function Q_(e){return{detected:e.filter(e=>e.installed).length,applied:e.filter(e=>e.applied).length,stale:e.filter(e=>e.state===`stale`).length,unknown:e.filter(e=>e.state===`unknown`).length}}var $_={titleKey:`integrations.dialog.grok.title`,changesKey:`integrations.dialog.grok.changes`,breakageKey:`integrations.dialog.grok.breakage`,undoKey:`integrations.dialog.grok.undo`,confirmKey:`integrations.dialog.grok.confirm`},ev={titleKey:`integrations.dialog.desktop.title`,changesKey:`integrations.dialog.desktop.changes`,breakageKey:`integrations.dialog.desktop.breakage`,undoKey:`integrations.dialog.desktop.undo`,sideEffectKey:`integrations.dialog.desktop.restart`,confirmKey:`integrations.dialog.desktop.confirm`},tv={apply:`integrations.kind.apply`,disable:`integrations.kind.disable`,refresh:`integrations.kind.refresh`,restore:`integrations.kind.restore`};function nv(e){return e.state===`current`||e.state===`stale`}function rv({row:e,pending:t,result:n,onOpen:r,onToggle:i}){let a=Q(),o=e.detail??(e.detailKey?a(e.detailKey,e.detailVars??void 0):null),s=e.toggleBlocked!==null&&(e.applied||e.toggleBlocked.reason===`orphaned_marker`),c=s&&e.toggleBlocked&&(e.toggle===`claude`||e.toggle===`grok`)?z_(a,new D_(409,{error:`native integration change refused`,code:`native_integration_refused`,clientId:e.toggle,reason:e.toggleBlocked.reason,message:e.toggleBlocked.message}),void 0,e.togglePath??void 0):null;return(0,q.jsxs)(`li`,{className:`integration-card`,"data-client":e.id,children:[(0,q.jsxs)(`div`,{className:`integration-card-head`,children:[(0,q.jsx)(`h4`,{children:(0,q.jsx)(`button`,{type:`button`,className:`integration-card-link`,onClick:r,children:a(e.labelKey)})}),(0,q.jsx)($g,{state:e.state,installed:e.installed})]}),o&&(0,q.jsx)(`p`,{className:e.detail?`integration-path`:`integration-meta`,children:o}),n?.tone===`err`&&(0,q.jsx)($,{tone:`err`,children:n.text}),n?.tone===`ok`&&(0,q.jsx)($,{tone:`ok`,children:n.text}),(0,q.jsxs)(`div`,{className:`integration-card-actions`,children:[e.toggle&&i&&(0,q.jsxs)(`div`,{className:`integration-toggle-control`,children:[(0,q.jsx)(wt,{on:e.toggleOn??e.applied,onClick:i,disabled:e.state===`unknown`||!e.installed||e.state===`conflict`||e.state===`unsafe`||s||t,label:e.applied?a(`integrations.action.disable`):a(`integrations.action.apply`)}),c&&(0,q.jsx)(`p`,{className:`integration-toggle-blocked`,children:c})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:r,tabIndex:-1,children:a(`integrations.action.settings`)})]})]})}function iv({apiBase:e,active:t=!0}){let n=Q(),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(null),[s,c]=(0,_.useState)(null),[l,u]=(0,_.useState)({}),[d,f]=(0,_.useState)(null),p=(0,_.useRef)(null);(0,_.useEffect)(()=>{if(d!==null)return;let e=p.current;e&&(p.current=null,e.isConnected&&e.focus())},[d]);let m=(0,_.useCallback)(async t=>(await d_(e,t)).clients,[e]),h=(0,_.useCallback)(async t=>(await p_(e,void 0,t)).operations,[e]),g=(0,_.useCallback)(t=>__(e,t),[e]),v=(0,_.useCallback)(t=>v_(e,t),[e]),y=(0,_.useCallback)(t=>y_(e,t),[e]),b=(0,_.useCallback)(t=>b_(e,t),[e]),x=(0,_.useCallback)(t=>x_(e,t),[e]),S=(0,_.useCallback)(async t=>(await j_(e,t))?.clients??null,[e]),C=Uc(`integration-states:${e}`,[e],m,{isEmpty:e=>e.length===0,enabled:t,sessionCacheKey:`ocx.integrations.states.v1:${e}`}),w=Uc(`integration-journal-all:${e}`,[e],h,{isEmpty:e=>e.length===0,enabled:t,sessionCacheKey:`ocx.integrations.journal.v1:${e}`}),T=Uc(`integration-codex:${e}`,[e],g,{isEmpty:e=>e===null,enabled:t,sessionCacheKey:`ocx.integrations.codex.v1:${e}`}),E=Uc(`integration-keys:${e}`,[e],v,{isEmpty:()=>!1,enabled:t,sessionCacheKey:`ocx.integrations.keys.v1:${e}`}),D=Uc(`integration-claude:${e}`,[e],y,{isEmpty:e=>e===null,enabled:t,sessionCacheKey:`ocx.integrations.claude.v1:${e}`}),O=Uc(`integration-claude-desktop:${e}`,[e],b,{isEmpty:e=>e===null,enabled:t,sessionCacheKey:`ocx.integrations.claude-desktop.v1:${e}`}),k=Uc(`integration-grok:${e}`,[e],x,{isEmpty:e=>e===null,enabled:t,sessionCacheKey:`ocx.integrations.grok.v1:${e}`}),A=Uc(`integration-native:${e}`,[e],S,{isEmpty:e=>e===null,enabled:t,sessionCacheKey:`ocx.integrations.native.v1:${e}`}),j=C.state.data??[],M=w.state.data??[],N=j.filter(nv),P=j.filter(e=>e.installed),F=C.state.kind!==`cold`&&C.state.kind!==`retrying-cold`,I=A.state.data??null,L=I!==null,R=E.state.kind===`cold`||E.state.kind===`retrying-cold`?`checking`:E.state.kind===`failed-cold`||E.state.kind===`failed-with-stale`?`unavailable`:`settled`,{keysRow:z,rows:B}=Z_({clients:j,clientsSettled:F,codex:T.state.data??null,keyCount:E.state.data??null,keyPhase:R,claude:D.state.data??null,claudeDesktop:O.state.data??null,grok:k.state.data??null,native:I,nativeSettled:L}),V=Q_(B),H=()=>{C.refresh(),w.refresh(),T.refresh(),E.refresh(),D.refresh(),O.refresh(),k.refresh(),A.refresh()},U=async()=>{if(r||N.length===0)return;let t=[n(`integrations.bulk.title`),n(`integrations.bulk.body`)].join(`
|
|
101
101
|
|
|
102
|
-
`);if(!confirm(t))return;i(!0),o(null);let a=[];for(let t of N)try{await m_(e,t.clientId,!1)}catch(e){a.push(`${t.clientId}: ${z_(n,e)}`)}let s=!1;try{s=(await d_(e)).clients.some(nv)}catch{a.push(n(`integrations.error.stale`))}s&&a.length===0&&a.push(n(`integrations.error.stale`)),H(),i(!1),o(a.length===0?{tone:`ok`,text:n(`integrations.bulk.success`)}:{tone:`err`,text:n(`integrations.bulk.partial`,{clients:a.join(`; `)})})},W=M[0]?.at,[ee,G]=(0,_.useState)(null),te=()=>{A.refresh(),D.refresh(),k.refresh()},K=(e,t)=>{u(n=>{let r={...n};return t?r[e]=t:delete r[e],r})},J=async(t,r)=>{if(!ee&&t.toggle){G(t.id),K(t.id,null);try{if(t.status)await m_(e,t.status.clientId,r),H();else if(t.toggle===`claude`||t.toggle===`grok`||t.toggle===`codex`||t.toggle===`claude-desktop`){let i=await M_(e,t.toggle,r);i.reason===`non_loopback_removed`?K(t.id,{tone:`ok`,text:n(i.changed?`integrations.native.msg.nonLoopbackRemoved`:`integrations.native.msg.nonLoopbackRemovedNoop`)}):i.reason===`non_loopback_superseded`&&K(t.id,{tone:`ok`,text:n(`integrations.native.msg.nonLoopbackSuperseded`)}),te()}}catch(e){K(t.id,{tone:`err`,text:z_(n,e,void 0,t.togglePath??void 0)}),(t.toggle===`claude`||t.toggle===`grok`||t.toggle===`codex`||t.toggle===`claude-desktop`)&&te()}finally{G(null)}}},ne=(e,t)=>{if(e.status||t||e.id===`claude`||e.toggle===null){J(e,t);return}let n=document.activeElement;p.current=n?.tagName===`BUTTON`?n:null,f(e)};return(0,q.jsxs)(`section`,{className:`integrations-overview`,children:[(0,q.jsxs)(`div`,{className:`integration-summary`,children:[(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.detected`)}),(0,q.jsx)(`strong`,{children:V.detected})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.applied`)}),(0,q.jsx)(`strong`,{children:V.applied})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.stale`)}),(0,q.jsx)(`strong`,{children:V.stale})]}),V.unknown>0&&(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.state.unknown`)}),(0,q.jsx)(`strong`,{children:V.unknown})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.lastChange`)}),(0,q.jsx)(`strong`,{children:W?new Date(W).toLocaleString():n(`integrations.status.unknown`)})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>void U(),disabled:r||N.length===0,children:n(`integrations.summary.disableAll`)})]}),(0,q.jsx)(av,{row:z}),(0,q.jsx)(`p`,{className:`page-sub`,children:n(`integrations.onboarding`)}),C.state.kind===`failed-cold`&&(0,q.jsx)($,{tone:`err`,children:n(`integrations.error.load`)}),C.state.kind===`failed-with-stale`&&(0,q.jsx)($,{tone:`err`,children:n(`integrations.error.stale`)}),a&&(0,q.jsx)($,{tone:a.tone,children:a.text}),B.length===0?C.state.kind===`failed-cold`?null:(0,q.jsx)(`p`,{className:`page-sub`,children:n(`common.loading`)}):(0,q.jsx)(`ul`,{className:`integration-cards`,children:B.map(e=>(0,q.jsx)(rv,{row:e,pending:ee!==null,result:l[e.id]??null,onOpen:()=>ft(e.hash),onToggle:e.toggle?()=>ne(e,!(e.toggleOn??e.applied)):null},e.id))}),F&&P.length===0&&(0,q.jsxs)(`div`,{className:`integration-empty`,children:[(0,q.jsx)(`h4`,{children:n(`integrations.empty.title`)}),(0,q.jsx)(`p`,{children:n(`integrations.empty.body`)})]}),(0,q.jsx)(`h4`,{children:n(`integrations.rollback.title`)}),M.length===0?(0,q.jsxs)(`div`,{className:`integration-empty`,children:[(0,q.jsx)(`p`,{children:n(`integrations.rollback.empty`)}),(0,q.jsx)(`p`,{className:`page-sub`,children:n(`integrations.rollback.emptyBody`)})]}):(0,q.jsx)(`ul`,{className:`integration-history`,children:M.map(e=>(0,q.jsxs)(`li`,{children:[(0,q.jsx)(`span`,{className:`integration-history-kind`,children:n(tv[e.kind])}),(0,q.jsx)(`span`,{className:`integration-history-client`,children:e.clientId}),(0,q.jsx)(`span`,{className:`integration-history-at`,children:new Date(e.at).toLocaleString()}),e.snapshot===`expired`?(0,q.jsx)(`span`,{className:`badge badge-muted`,children:n(`integrations.action.snapshotExpired`)}):(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>c(e),children:e.undoable?n(`integrations.action.undo`):n(`integrations.action.restorePoint`)})]},e.opId))}),s&&(0,q.jsx)(B_,{apiBase:e,row:s,onClose:()=>c(null),onRestored:H}),d&&(0,q.jsx)(t_,{copy:{...d.toggle===`claude-desktop`?ev:$_,vars:{path:d.togglePath??``}},onClose:()=>f(null),onConfirm:async()=>{await J(d,!1),f(null)}})]})}function av({row:e}){let t=Q(),n=e.detailKey?t(e.detailKey,e.detailVars??void 0):null;return(0,q.jsxs)(`div`,{className:`integration-api-keys-row`,"data-client":`keys`,"data-key-state":e.state,children:[(0,q.jsxs)(`div`,{className:`integration-api-keys-copy`,children:[(0,q.jsx)(`h4`,{children:t(e.labelKey)}),n&&(0,q.jsx)(`p`,{className:`integration-meta`,children:n})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>ft(e.hash),children:t(`integrations.action.manageKeys`)})]})}var ov={opencode:`integrations.semantics.opencode`,pi:`integrations.semantics.pi`,omp:`integrations.semantics.omp`,hermes:`integrations.semantics.hermes`,openclaw:`integrations.semantics.openclaw`,kimi:`integrations.semantics.kimi`,gajae:`integrations.semantics.gajae`,dsh:`integrations.semantics.dsh`,mcode:`integrations.semantics.mcode`,zcode:`integrations.semantics.zcode`,prime:`integrations.semantics.prime`},sv={opencode:`integrations.tab.opencode`,pi:`integrations.tab.pi`,omp:`integrations.tab.omp`,hermes:`integrations.tab.hermes`,openclaw:`integrations.tab.openclaw`,kimi:`integrations.tab.kimi`,gajae:`integrations.tab.gajae`,dsh:`integrations.tab.dsh`,mcode:`integrations.tab.mcode`,zcode:`integrations.tab.zcode`,prime:`integrations.tab.prime`},cv={apply:`integrations.kind.apply`,disable:`integrations.kind.disable`,refresh:`integrations.kind.refresh`,restore:`integrations.kind.restore`};function lv({apiBase:e,client:t,active:n=!0}){let r=Q(),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(null),[c,l]=(0,_.useState)(null),u=(0,_.useCallback)(n=>f_(e,t,n),[e,t]),d=(0,_.useCallback)(async n=>(await p_(e,t,n)).operations,[e,t]),f=Uc(`integration-state:${e}:${t}`,[e,t],u,{isEmpty:()=>!1,enabled:n,sessionCacheKey:`ocx.integrations.state.v1:${e}:${t}`}),p=Uc(`integration-journal:${e}:${t}`,[e,t],d,{isEmpty:e=>e.length===0,enabled:n,sessionCacheKey:`ocx.integrations.client-journal.v1:${e}:${t}`}),m=f.state.data??null,h=p.state.data??[],g=()=>{f.refresh(),p.refresh()},v=async n=>{if(!(!m||i)){a(!0),s(null);try{await m_(e,t,n),g()}catch(e){s(z_(r,e))}finally{a(!1)}}},y=()=>void v(!(m&&(m.state===`current`||m.state===`stale`)));if(!m)return(0,q.jsx)(`section`,{className:`integration-client-page`,children:f.state.kind===`failed-cold`?(0,q.jsx)($,{tone:`err`,children:r(`integrations.error.load`)}):(0,q.jsx)(`p`,{className:`page-sub`,children:r(`common.loading`)})});let b=m.state===`current`||m.state===`stale`,x=!m.installed||m.state===`conflict`||m.state===`unsafe`;return(0,q.jsxs)(`section`,{className:`integration-client-page`,children:[(0,q.jsxs)(`div`,{className:`integration-client-head`,children:[(0,q.jsx)(`h3`,{children:r(sv[t])}),(0,q.jsx)($g,{state:m.state,installed:m.installed,id:`integration-state-${t}`}),(0,q.jsx)(wt,{on:b,onClick:y,disabled:x||i,label:r(b?`integrations.action.disable`:`integrations.action.apply`)})]}),m.state===`stale`&&(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>void v(!0),disabled:i,children:r(`integrations.action.refresh`)}),(0,q.jsx)(`p`,{className:`page-sub`,children:r(ov[t])}),(0,q.jsx)(`p`,{className:`integration-path`,children:m.configPath}),m.appliedAt&&(0,q.jsxs)(`p`,{className:`integration-meta`,children:[r(`integrations.status.appliedAt`),`: `,new Date(m.appliedAt).toLocaleString()]}),m.retentionDegraded&&(0,q.jsx)($,{tone:`err`,children:r(`integrations.retention.degraded`)}),o&&(0,q.jsx)($,{tone:`err`,children:o}),(0,q.jsx)(`h4`,{children:r(`integrations.rollback.title`)}),h.length===0?(0,q.jsx)(`p`,{className:`page-sub`,children:r(`integrations.rollback.empty`)}):(0,q.jsx)(`ul`,{className:`integration-history`,children:h.map(e=>(0,q.jsxs)(`li`,{children:[(0,q.jsx)(`span`,{className:`integration-history-kind`,children:r(cv[e.kind])}),(0,q.jsx)(`span`,{className:`integration-history-at`,children:new Date(e.at).toLocaleString()}),e.snapshot===`expired`?(0,q.jsx)(`span`,{className:`badge badge-muted`,children:r(`integrations.action.snapshotExpired`)}):(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>l(e),children:e.undoable?r(`integrations.action.undo`):r(`integrations.action.restorePoint`)})]},e.opId))}),c&&(0,q.jsx)(B_,{apiBase:e,row:c,onClose:()=>l(null),onRestored:g})]})}var uv=[{id:`overview`,hash:`integrations`,labelKey:`integrations.tab.overview`},{id:`keys`,hash:`integrations/keys`,labelKey:`integrations.tab.keys`},{id:`codex`,hash:`integrations/codex`,labelKey:`integrations.tab.codex`},{id:`claude`,hash:`integrations/claude`,labelKey:`integrations.tab.claude`},{id:`grok`,hash:`integrations/grok`,labelKey:`integrations.tab.grok`},{id:`opencode`,hash:`integrations/opencode`,labelKey:`integrations.tab.opencode`},{id:`pi`,hash:`integrations/pi`,labelKey:`integrations.tab.pi`},{id:`omp`,hash:`integrations/omp`,labelKey:`integrations.tab.omp`},{id:`hermes`,hash:`integrations/hermes`,labelKey:`integrations.tab.hermes`},{id:`openclaw`,hash:`integrations/openclaw`,labelKey:`integrations.tab.openclaw`},{id:`kimi`,hash:`integrations/kimi`,labelKey:`integrations.tab.kimi`},{id:`gajae`,hash:`integrations/gajae`,labelKey:`integrations.tab.gajae`},{id:`dsh`,hash:`integrations/dsh`,labelKey:`integrations.tab.dsh`},{id:`mcode`,hash:`integrations/mcode`,labelKey:`integrations.tab.mcode`},{id:`zcode`,hash:`integrations/zcode`,labelKey:`integrations.tab.zcode`},{id:`prime`,hash:`integrations/prime`,labelKey:`integrations.tab.prime`}],dv=new Set([`opencode`,`pi`,`omp`,`hermes`,`openclaw`,`kimi`,`gajae`,`dsh`,`mcode`,`zcode`,`prime`]);function fv(e=window.location.hash){let t=ut(e);return t===`integrations/claude/desktop`?`claude`:uv.find(e=>e.hash===t)?.id??`overview`}function pv(e){return`integrations-tab-${e}`}function mv(e){return`integrations-panel-${e}`}function hv({apiBase:e}){let t=Q(),[n,r]=(0,_.useState)(fv),[i,a]=(0,_.useState)(()=>new Set([fv()])),o=(0,_.useRef)(null);o.current===null&&(o.current=new Map);let s=e=>{r(e),a(t=>t.has(e)?t:new Set([...t,e]))};(0,_.useEffect)(()=>{let e=()=>s(fv());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let c=(e,t)=>{let n=uv.find(t=>t.id===e);n&&(ft(n.hash),s(e),t&&window.requestAnimationFrame(()=>{o.current.get(e)?.focus({preventScroll:!0})}))},l=e=>{let t=uv.findIndex(e=>e.id===n),r=null;e.key===`ArrowLeft`?r=(t-1+uv.length)%uv.length:e.key===`ArrowRight`?r=(t+1)%uv.length:e.key===`Home`?r=0:e.key===`End`&&(r=uv.length-1),r!==null&&(e.preventDefault(),c(uv[r].id,!0))};return(0,q.jsxs)(`section`,{className:`integrations-page`,children:[(0,q.jsx)(`div`,{className:`page-head`,children:(0,q.jsx)(`h2`,{children:t(`nav.integrations`)})}),(0,q.jsx)(`p`,{className:`page-sub`,children:t(`integrations.subtitle`)}),(0,q.jsx)(`div`,{className:`page-tabs`,role:`tablist`,"aria-label":t(`integrations.tabsLabel`),children:uv.map(e=>(0,q.jsx)(`button`,{ref:t=>{t?o.current.set(e.id,t):o.current.delete(e.id)},type:`button`,role:`tab`,id:pv(e.id),"aria-selected":n===e.id,"aria-controls":mv(e.id),tabIndex:n===e.id?0:-1,className:`page-tab${n===e.id?` page-tab--active`:``}`,onClick:()=>c(e.id,!0),onKeyDown:l,children:t(e.labelKey)},e.id))}),uv.map(r=>{if(!i.has(r.id))return null;let a=n===r.id;return(0,q.jsxs)(`div`,{role:`tabpanel`,id:mv(r.id),"aria-labelledby":pv(r.id),hidden:!a,children:[r.id===`overview`&&(0,q.jsx)(iv,{apiBase:e,active:a}),r.id===`keys`&&(0,q.jsx)(eg,{apiBase:e,active:a}),r.id===`codex`&&(0,q.jsxs)(`section`,{className:`integration-native-page`,"aria-labelledby":`codex-integration-title`,children:[(0,q.jsx)(`h3`,{id:`codex-integration-title`,children:t(`integrations.codex.title`)}),(0,q.jsx)(`p`,{children:t(`integrations.codex.body`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>ft(`startup`),children:t(`integrations.codex.openService`)})]}),r.id===`claude`&&(0,q.jsx)(Wg,{apiBase:e,active:a}),r.id===`grok`&&(0,q.jsx)(Xg,{apiBase:e,active:a}),dv.has(r.id)&&(0,q.jsx)(lv,{apiBase:e,client:r.id,active:a})]},r.id)})]})}function gv(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 _v={native:`startup.status.native`,protected:`startup.status.protected`,"at-risk":`startup.status.atRisk`},vv={native:`startup.summary.native`,protected:`startup.summary.protected`,"at-risk":`startup.summary.atRisk`},yv={service:`startup.protection.service`,shim:`startup.protection.shim`,none:`startup.protection.none`};function bv({ok:e,yes:t,no:n}){return(0,q.jsx)(`span`,{className:`badge ${e?`badge-green`:`badge-amber`}`,children:e?t:n})}function xv({failed:e,data:t}){let{t:n}=st(),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`?ge:le,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,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`section`,{className:`panel startup-hero ${r}`,"aria-live":`polite`,children:[(0,q.jsx)(`div`,{className:`startup-hero-icon`,children:(0,q.jsx)(i,{})}),(0,q.jsxs)(`div`,{className:`startup-hero-copy`,children:[(0,q.jsx)(`span`,{className:`badge ${e||t.status===`at-risk`?`badge-amber`:`badge-green`}`,children:n(e?`startup.status.atRisk`:_v[t.status])}),(0,q.jsx)(`h3`,{children:n(e?`startup.error`:vv[t.status])}),(0,q.jsx)(`p`,{children:e?n(`startup.staleData`):t.status===`at-risk`?n(gr(t)):n(`startup.safeDetail`)})]})]}),(0,q.jsxs)(`div`,{className:`startup-state-grid`,children:[(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.routing`)}),(0,q.jsx)(`div`,{className:`value`,children:n(a)})]}),(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.restartProtection`)}),(0,q.jsx)(`div`,{className:`value`,children:n(yv[t.protection])})]}),(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.preference`)}),(0,q.jsx)(`div`,{className:`value`,children:n(t.autostartEnabled?`startup.enabled`:`startup.disabled`)})]})]})]})}function Sv({data:e,failed:t,loading:n=!1,installBusy:r,installResult:i,onInstall:a}){let{t:o}=st(),s=e.serviceSupported&&e.serviceInstalled&&e.serviceStale&&!e.serviceConflict,c=e.shimInstalled&&!e.shimHealthy,l=r!==null||t||n;return(0,q.jsxs)(`section`,{className:`panel startup-details`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:o(`startup.details`)}),(0,q.jsx)(`span`,{className:`muted mono`,children:e.platform})]}),(0,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:o(`startup.service`)}),(0,q.jsx)(`span`,{children:o(`startup.serviceHint`)})]}),(0,q.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,q.jsx)(bv,{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,q.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,q.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,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:o(`startup.shim`)}),(0,q.jsx)(`span`,{children:o(`startup.shimHint`)})]}),(0,q.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,q.jsx)(bv,{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,q.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,q.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,q.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 Cv({tray:e,trayLoading:t,trayError:n,trayBusy:r,onTrayAction:i}){let{t:a}=st();return(0,q.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:a(`startup.tray.title`)}),(0,q.jsx)(Ce,{})]}),(0,q.jsx)(`p`,{className:`muted`,children:a(`startup.tray.hint`)}),(0,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:a(`startup.tray.login`)}),(0,q.jsx)(`span`,{children:a(`startup.tray.notProtection`)})]}),t||n||!e?(0,q.jsx)(`span`,{className:`badge badge-amber`,children:a(t?`startup.tray.loading`:`startup.tray.unavailable`)}):(0,q.jsx)(bv,{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,q.jsxs)(`div`,{className:`startup-tray-buttons`,children:[!t&&!n&&e&&!e.installed&&!e.stale&&(0,q.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,q.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,q.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,q.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,q.jsx)(`div`,{className:`notice notice-warn startup-tray-error`,role:`alert`,children:a(`startup.tray.error`)})]})}function wv({data:e,copied:t,onCopy:n}){let{t:r}=st(),i=e.serviceInstalled&&!e.serviceConflict?e.commands.repairService:e.commands.installService;return(0,q.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:r(`startup.recovery`)}),(0,q.jsx)(X,{})]}),(0,q.jsx)(`p`,{className:`muted`,children:r(`startup.recoveryHint`)}),(0,q.jsxs)(`div`,{className:`startup-command-list`,children:[e.serviceSupported&&(0,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.service`)}),(0,q.jsx)(`code`,{children:i})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(i),children:r(t===i?`startup.copied`:`startup.copy`)})]}),(0,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.shim`)}),(0,q.jsx)(`code`,{children:e.commands.installShim})]}),(0,q.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,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.native`)}),(0,q.jsx)(`code`,{children:e.commands.restoreNative})]}),(0,q.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,q.jsxs)(`div`,{className:`notice notice-warn startup-action-notice`,role:`alert`,children:[(0,q.jsx)(Ce,{}),` `,r(`startup.recommended`,{cmd:e.recommendedCommand??e.commands.installService})]})]})}var Tv=`ocx.startup.page.v1:`;function Ev(e,t){let n=t===`win32`?`; `:` && `;return e.join(n)}function Dv(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=Ev([`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 Ov({apiBase:e}){let{t}=st(),n=`${Tv}${e}`,r=(0,_.useMemo)(()=>dr(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();y(e=>e?.kind===`error`&&(o.status===`native`&&e.forLocalRouting===!0||(e.action===`install-service`?o.serviceViable:o.shimInstalled&&o.shimHealthy))?null:e),E.current=!0;let s=dr(n);hr(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(!gv(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=Dv(e.codexRuntime,t,o.platform);x(r.warning),C(r.fix),hr(n,{data:o,warning:r.warning,fix:r.fix,tray:a});return}let s=dr(n);hr(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=Uc(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(!gv(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),forLocalRouting:j?.localRoutingDependency===!0})}finally{g(null)}};return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{className:`page-head`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h2`,{children:t(`startup.title`)}),(0,q.jsx)(`p`,{className:`page-sub startup-page-sub`,children:t(`startup.subtitle`)})]}),(0,q.jsxs)(`div`,{className:`startup-page-head-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>ft(`dashboard`),children:t(`startup.backToDashboard`)}),(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),disabled:M,children:[(0,q.jsx)(fe,{}),` `,t(`startup.refresh`)]})]})]}),k.showSkeleton&&!j?(0,q.jsx)(Gc,{label:t(`startup.loading`),rows:5}):k.kind===`failed-cold`?(0,q.jsxs)(`div`,{className:`startup-page-notice`,children:[(0,q.jsx)($,{tone:`err`,children:k.error instanceof Error?k.error.message:t(`startup.error`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),children:t(`common.retry`)})]}):j?(0,q.jsxs)(q.Fragment,{children:[k.showError&&(0,q.jsx)($,{tone:`err`,children:t(`startup.error`)}),N&&(0,q.jsx)(`div`,{className:`notice notice-warn startup-page-notice`,role:`alert`,children:t(`startup.staleData`)}),(w||b)&&(0,q.jsx)(`div`,{className:`startup-runtime-notice-slot${w&&!b?` startup-runtime-notice-slot--pending`:``}`,"aria-hidden":w&&!b?!0:void 0,children:b&&(0,q.jsxs)(`div`,{className:`notice notice-warn startup-page-notice startup-runtime-notice`,role:`status`,children:[(0,q.jsx)(`p`,{className:`startup-runtime-notice__text`,children:b}),S&&(0,q.jsxs)(`div`,{className:`startup-runtime-notice__fix`,children:[(0,q.jsx)(`code`,{children:S}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>void P(S),children:t(a===S?`startup.copied`:`startup.copy`)})]})]})}),(0,q.jsx)(xv,{failed:N,data:j}),(0,q.jsx)(Sv,{data:j,failed:N,loading:M,installBusy:h,installResult:v,onInstall:(e,t)=>{I(e,t)}}),j.platform===`win32`&&(0,q.jsx)(Cv,{tray:s,trayLoading:l,trayError:p,trayBusy:d,onTrayAction:e=>{F(e)}}),(0,q.jsx)(wv,{data:j,copied:a,onCopy:e=>{P(e)}})]}):null]})}var kv=3e5,Av=6e5,jv=`https://github.com/lidge-jun/opencodex`;async function Mv(e,t){let n=await fetch(e,{signal:t});return n.ok?await n.json():null}function Nv({apiBase:e,onOpenUpdate:t}){let n=Q(),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(null),s=G(`sidebar-star:${e}`,[e],t=>Mv(`${e}/api/github/star`,t),{pollMs:kv}),c=G(`sidebar-update-badge:${e}`,[e],t=>Mv(`${e}/api/update/badge`,t),{pollMs:Av}),l=s.data?.state??null,u=a!==null&&a.basedOn===l?a.state:l??`not-starred`,d=s.data?.url??jv,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,q.jsxs)(`div`,{className:`sidebar-github-row`,children:[(0,q.jsxs)(`a`,{className:`sidebar-link sidebar-github-link`,href:d,target:`_blank`,rel:`noreferrer`,children:[(0,q.jsx)(Se,{}),` `,n(`common.github`)]}),(0,q.jsxs)(`div`,{className:`sidebar-github-actions`,children:[(0,q.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,q.jsx)(Fe,{"aria-hidden":`true`,...f?{fill:`currentColor`}:{}})}),(0,q.jsxs)(`button`,{type:`button`,className:`sidebar-orb${m?` sidebar-orb--update`:``}`,onClick:t,"aria-label":b,title:b,children:[(0,q.jsx)(Z,{"aria-hidden":`true`}),m&&(0,q.jsx)(`span`,{className:`sidebar-orb-dot`,"aria-hidden":`true`})]})]})]})}var Pv=`opencodex-admin-token-dialog`,Fv=`OpenCodex`;function Iv(e,t=rt()){let n=Xe[t],r=n[`auth.adminTokenTitle`];return new Promise(t=>{let i=document.activeElement instanceof HTMLElement?document.activeElement:null,a=!1,o=document.createElement(`dialog`);o.id=Pv,o.className=`modal-overlay`,o.setAttribute(`aria-labelledby`,`${Pv}-title`);let s=document.createElement(`form`);s.className=`modal-card`,s.method=`post`,s.action=window.location.href,s.autocomplete=`on`;let c=document.createElement(`div`);c.className=`modal-head`;let l=document.createElement(`h3`);l.id=`${Pv}-title`,l.textContent=r,c.append(l);let u=document.createElement(`div`),d=document.createElement(`label`);d.className=`field-label`,d.htmlFor=`${Pv}-username`,d.textContent=n[`auth.adminAccountLabel`];let f=document.createElement(`input`);f.id=d.htmlFor,f.className=`input`,f.type=`text`,f.name=`username`,f.autocomplete=`username`,f.value=Fv,f.readOnly=!0,u.append(d,f);let p=document.createElement(`div`);p.style.marginTop=`var(--space-4)`;let m=document.createElement(`label`);m.className=`field-label`,m.htmlFor=`${Pv}-password`,m.textContent=n[`auth.adminTokenFieldLabel`];let h=document.createElement(`input`);h.id=m.htmlFor,h.className=`input`,h.type=`password`,h.name=`password`,h.autocomplete=`current-password`,h.required=!0,h.spellcheck=!1,h.autocapitalize=`none`,p.append(m,h);let g=document.createElement(`div`);g.className=`notice notice-err`,g.setAttribute(`role`,`alert`),g.hidden=!0;let _=document.createElement(`div`);_.className=`modal-actions`;let v=document.createElement(`button`);v.type=`button`,v.className=`btn btn-ghost`,v.textContent=n[`common.cancel`];let y=document.createElement(`button`);y.type=`submit`,y.className=`btn btn-primary`,y.textContent=n[`common.ok`],_.append(v,y),s.append(c,u,p,g,_),o.append(s);let b=e=>{a||(a=!0,o.open&&o.close(),o.remove(),i?.focus(),t(e))};s.addEventListener(`submit`,t=>{t.preventDefault();let r=h.value.trim();if(!r){h.value=``,h.reportValidity();return}h.disabled=!0,y.disabled=!0,g.hidden=!0,e(r).then(e=>{if(!a){if(e===`accepted`){b(r);return}h.value=``,h.disabled=!1,y.disabled=!1,g.textContent=e===`rejected`?n[`auth.adminTokenRejected`]:n[`auth.adminTokenUnavailable`],g.hidden=!1,h.focus()}}).catch(()=>{a||(h.value=``,h.disabled=!1,y.disabled=!1,g.textContent=n[`auth.adminTokenUnavailable`],g.hidden=!1,h.focus())})}),v.addEventListener(`click`,()=>b(null)),o.addEventListener(`cancel`,e=>{e.preventDefault(),b(null)}),document.body.append(o),typeof o.showModal==`function`?o.showModal():o.setAttribute(`open`,``),queueMicrotask(()=>h.focus())})}var Lv=!1,Rv=null,zv=null,Bv=!1,Vv=Iv,Hv=`/opencodex-session`,Uv=`/api/settings`,Wv=1e4,Gv=15e3;function Kv(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/`)}catch{return!1}}var qv=`opencodex-api-token`,Jv=null,Yv=null,Xv=null;function Zv(){return Jv}function Qv(e){Jv=e}function $v(){Jv=null,Yv=null,Xv=null}function ey(e){let t=document.querySelector(`meta[name="${e}"]`),n=t?.content.trim()||null;return t?.remove(),n}function ty(){ry(ey(`opencodex-session-token`),ey(`opencodex-session-csrf`),ey(`opencodex-session-origin`))}function ny(e){e!=null&&Zv()===e&&$v()}function ry(e,t,n){return!e?.startsWith(`ocx_session_`)||!t||n!==window.location.origin?!1:(Jv=e,Yv=t,Xv=n,!0)}function iy(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 ay(){if(!zv)return{kind:`failed`};let e=In(Wv);try{let t=await zv(Hv,{cache:`no-store`,signal:e.signal});if(!t.ok)return t.status>=400&&t.status<500?{kind:`unavailable`}:{kind:`failed`};let n=await t.text(),r=ry(iy(n,`opencodex-session-token`),iy(n,`opencodex-session-csrf`),iy(n,`opencodex-session-origin`)),i=Zv();return r&&i?{kind:`minted`,token:i}:{kind:`unavailable`}}catch{return{kind:`failed`}}finally{e.clear()}}async function oy(e){if(!zv)return`unavailable`;try{let[t,n]=cy(Uv,{cache:`no-store`},e),r=await zv(t,n);return r.status===401?`rejected`:r.ok?`accepted`:`unavailable`}catch{return`unavailable`}}function sy(){try{sessionStorage.removeItem(qv)}catch{}}function cy(e,t,n){let r=new Headers(t?.headers??(e instanceof Request?e.headers:void 0));if(r.set(`X-OpenCodex-API-Key`,n),Xv&&Yv&&n.startsWith(`ocx_session_`)){r.set(`X-OpenCodex-GUI-Origin`,Xv);let n=(t?.method??(e instanceof Request?e.method:`GET`)).toUpperCase();n!==`GET`&&n!==`HEAD`&&r.set(`X-OpenCodex-CSRF-Token`,Yv)}return e instanceof Request?[new Request(e,{headers:r}),t?{...t,headers:r}:void 0]:[e,{...t,headers:r}]}async function ly(e,t){if(Bv||t?.aborted)return null;if(!Rv){let t=(async()=>{if(Bv)return null;let t=Zv();if(t&&t!==e)return t;let n,r=await Promise.race([ay(),new Promise(e=>{n=setTimeout(()=>e({kind:`failed`}),Gv)})]).finally(()=>clearTimeout(n));if(r.kind===`minted`)return r.token;if(r.kind===`failed`)return null;let i=await Vv(oy);return i?(Qv(i),i):(Bv=!0,null)})().finally(()=>{Rv===t&&(Rv=null)});Rv=t}if(!t)return Rv;let n,r=new Promise(e=>{n=()=>e(null),t.addEventListener(`abort`,n,{once:!0})});return Promise.race([Rv,r]).finally(()=>{n&&t.removeEventListener(`abort`,n)})}function uy(){if(Lv)return;Lv=!0,sy(),ty();let e=window.fetch.bind(window);zv=e,window.fetch=async(t,n)=>{if(!Kv(t))return e(t,n);let r=n?.signal??(t instanceof Request?t.signal:void 0),i=Zv(),[a,o]=i?cy(t,n,i):[t,n],s=await e(a,o);if(s.status!==401)return s;let c=Zv();if(c&&c!==i){let[r,i]=cy(t,n,c),a=await e(r,i);if(a.status!==401)return a;ny(c)}else ny(i);let l=await ly(i,r??void 0);if(!l)return s;let[u,d]=cy(t,n,l),f=await e(u,d);return f.status===401&&ny(l),f}}var dy=new Set([`dashboard`,`startup`,`providers`,`models`,`subagents`,`logs`,`usage`,`storage`,`codex-auth`,`integrations`]);function fy(e){let t=ut(e??(typeof window<`u`?window.location.hash:``)).split(`/`)[0];return t===`debug`?`logs`:t===`combos`||t===`routing`||t===`lab`?`models`:t===`api`||t===`claude`||t===`grok`?`integrations`:dy.has(t)?t:`dashboard`}var py=[`dashboard/providers`,`dashboard/models`],my=[`models/combos`,`models/routing`,`models/compatibility`],hy=[`integrations/keys`,`integrations/codex`,`integrations/claude`,`integrations/claude/desktop`,`integrations/grok`,`integrations/opencode`,`integrations/pi`,`integrations/omp`,`integrations/hermes`,`integrations/openclaw`,`integrations/kimi`,`integrations/gajae`,`integrations/dsh`,`integrations/mcode`,`integrations/zcode`,`integrations/prime`];function gy(e,t){return e===t||t===`logs`&&e===`logs/debug`||t===`models`&&my.includes(e)||t===`dashboard`&&(e===`dashboard/update`||py.includes(e))||t===`integrations`&&hy.includes(e)}function _y(e){let t=fy(e);return e===`debug`||e.startsWith(`debug/`)?{page:`logs`,replaceTo:`logs/debug`}:e===`combos`||e.startsWith(`combos/`)?{page:`models`,replaceTo:`models/combos`}:e===`routing`||e.startsWith(`routing/`)?{page:`models`,replaceTo:`models/routing`}:e===`lab`||e.startsWith(`lab/`)?{page:`models`,replaceTo:`models/compatibility`}:e===`api`?{page:`integrations`,replaceTo:`integrations/keys`}:e===`claude`?{page:`integrations`,replaceTo:`integrations/claude`}:e===`grok`?{page:`integrations`,replaceTo:`integrations/grok`}:e===`providers/workspace`?{page:`providers`,replaceTo:`providers`}:gy(e,t)?{page:t,replaceTo:null}:{page:t,replaceTo:t}}var vy=[`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 yy(){try{for(let e of vy)localStorage.removeItem(e)}catch{}}function by(){let[e,t]=(0,_.useState)(fy);(0,_.useEffect)(()=>{yy()},[]);let n=(0,_.useCallback)(e=>{let n=_y(e);n.replaceTo&&dt(n.replaceTo),t(n.page)},[]);return(0,_.useEffect)(()=>{let e=()=>{n(ut(window.location.hash))};return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[n]),(0,_.useEffect)(()=>{let n=_y(ut(window.location.hash));n.replaceTo&&dt(n.replaceTo),n.page!==e&&t(n.page)},[e]),{page:e,setPageState:t,navigateToPage:(e,n)=>{ft(n?`${e}/${n}`:e),t(e)}}}var xy=15e3;function Sy(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 Cy(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}async function wy(e,t={}){let{fetchFn:n=fetch,timeoutMs:r=xy,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 Cy(e),{accepted:!0}}let o=await a.json().catch(()=>null);return!a.ok||o?.success===!1?{accepted:!1,message:Sy(o,a.status,i)}:{accepted:!0}}uy();var Ty={dashboard:`nav.dashboard`,startup:`nav.startup`,providers:`nav.providers`,models:`nav.models`,subagents:`nav.subagents`,logs:`nav.logs`,usage:`nav.usage`,storage:`nav.storage`,"codex-auth":`nav.codexAuth`,integrations:`nav.integrations`},Ey=``,Dy=`ocx-theme`,Oy=[{id:`dashboard`,tkey:`nav.dashboard`,Icon:ne},{id:`codex-auth`,tkey:`nav.codexAuth`,Icon:Te},{id:`providers`,tkey:`nav.providers`,Icon:re},{id:`models`,tkey:`nav.models`,Icon:ie},{id:`subagents`,tkey:`nav.subagents`,Icon:Y},{id:`logs`,tkey:`nav.logs`,Icon:ae},{id:`usage`,tkey:`nav.usage`,Icon:se},{id:`storage`,tkey:`nav.storage`,Icon:ce},{id:`integrations`,tkey:`nav.integrations`,Icon:Me}],ky={light:ke,dark:Ae,system:je},Ay={light:`theme.light`,dark:`theme.dark`,system:`theme.system`};function jy(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 My(){let e=localStorage.getItem(Dy);return e===`light`||e===`dark`?e:`system`}function Ny(){let{page:e,navigateToPage:t}=by(),[n,r]=(0,_.useState)(ef);(0,_.useEffect)(()=>{let e=()=>r(ef());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let[i,a]=(0,_.useState)(My),{locale:o,setLocale:s}=st(),c=Q(),[l,u]=(0,_.useState)(!1),d=(0,_.useRef)(null),f=(0,_.useRef)(null),p=(0,_.useRef)(!1);(0,_.useEffect)(()=>{let e=()=>u(!1);return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]),(0,_.useEffect)(()=>{let e=document.documentElement;i===`system`?(e.removeAttribute(`data-theme`),localStorage.removeItem(Dy)):(e.setAttribute(`data-theme`,i),localStorage.setItem(Dy,i))},[i]);let m=G(`app-healthz:${Ey}`,[],async e=>{let t=await fetch(`${Ey}/healthz`,{signal:e});return t.ok?jy(await t.json()):null},{pollMs:3e4}),h=()=>a(e=>e===`light`?`dark`:e===`dark`?`system`:`light`),g=ky[i],v=m.data??`2.32.0`,[y,b]=(0,_.useState)(!1);(0,_.useEffect)(()=>{if(!l)return;let e=e=>{e.key===`Escape`&&u(!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}},[l]),(0,_.useEffect)(()=>{if(l){p.current=!0;let e=setTimeout(()=>f.current?.focus(),200);return()=>clearTimeout(e)}p.current&&(p.current=!1,d.current?.focus())},[l]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 761px)`),t=()=>{e.matches&&u(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let[x,S]=(0,_.useState)(0),{restarting:C,restart:w}=Ic(Ey,{onSettled:()=>S(e=>e+1)}),T=async()=>{if(!confirm(c(`dash.stopConfirm`)))return;b(!0);let e=await wy(Ey,{formatFailure:e=>c(`dash.stopFailed`,{status:String(e)})});e.accepted||(b(!1),alert(e.message))},E=(0,q.jsxs)(`div`,{className:`brand`,children:[(0,q.jsx)(`span`,{className:`brand-logo`,role:`img`,"aria-label":c(`app.logoAria`)}),(0,q.jsx)(`span`,{className:`name`,children:`opencodex`}),(0,q.jsxs)(`span`,{className:`ver`,children:[`v`,v]})]});return(0,q.jsxs)(`div`,{className:`app`,children:[(0,q.jsxs)(`header`,{className:`mobile-topbar`,inert:l,children:[(0,q.jsx)(`button`,{ref:d,type:`button`,className:`menu-toggle`,onClick:()=>u(e=>!e),"aria-expanded":l,"aria-controls":`app-sidebar`,"aria-label":c(l?`nav.closeMenu`:`nav.openMenu`),title:c(l?`nav.closeMenu`:`nav.openMenu`),children:(0,q.jsx)(oe,{})}),E,(0,q.jsxs)(`div`,{className:`mobile-topbar-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb sidebar-orb--danger`,onClick:T,disabled:y,"aria-label":c(`dash.stop`),title:c(`dash.stop`),children:(0,q.jsx)(Ce,{})}),(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb`,onClick:()=>{w()},disabled:C,"aria-label":c(`dash.codexRestart`),title:c(`dash.codexRestart`),children:(0,q.jsx)(fe,{})})]})]}),l&&(0,q.jsx)(`div`,{className:`drawer-scrim`,onClick:()=>u(!1),"aria-hidden":`true`}),(0,q.jsxs)(`aside`,{id:`app-sidebar`,className:`sidebar${l?` open`:``}`,ref:f,tabIndex:-1,children:[(0,q.jsxs)(`div`,{className:`drawer-head`,children:[E,(0,q.jsx)(`button`,{type:`button`,className:`menu-toggle drawer-close`,onClick:()=>u(!1),"aria-label":c(`nav.closeMenu`),title:c(`nav.closeMenu`),children:(0,q.jsx)(ue,{})})]}),(0,q.jsx)(`nav`,{children:Oy.map(n=>{let{id:r,tkey:i,Icon:a}=n,o=r===e;return(0,q.jsx)(`div`,{className:`nav-entry`,children:(0,q.jsxs)(`button`,{type:`button`,className:`nav-item${o?` active`:``}`,"data-page":r,onClick:()=>{t(r),u(!1)},"aria-current":o?`page`:void 0,children:[(0,q.jsx)(a,{}),` `,c(i)]})},r)})}),(0,q.jsxs)(`div`,{className:`sidebar-foot`,children:[(0,q.jsxs)(`div`,{className:`lang-toggle`,children:[(0,q.jsx)(Me,{"aria-hidden":!0}),(0,q.jsx)(Et,{value:o,options:$e.map(e=>({value:e.code,label:Ze(e.code)})),onChange:e=>s(e),label:c(`lang.label`),placement:`right`,portal:!1,style:{flex:1,minWidth:0,width:`100%`}})]}),(0,q.jsxs)(`button`,{type:`button`,className:`theme-toggle`,onClick:h,"aria-label":`${c(`theme.label`)}: ${c(Ay[i])}`,title:`${c(`theme.label`)}: ${c(Ay[i])}`,children:[(0,q.jsx)(g,{}),` `,(0,q.jsx)(`span`,{className:`mode`,children:c(Ay[i])})]}),(0,q.jsxs)(`div`,{className:`sidebar-action-row`,children:[(0,q.jsx)(`span`,{className:`sidebar-action-label`,children:c(`dash.actions`)}),(0,q.jsxs)(`div`,{className:`sidebar-action-orbs`,children:[(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb sidebar-orb--danger`,onClick:T,disabled:y,"aria-label":c(y?`dash.stopping`:`dash.stop`),title:c(y?`dash.stopping`:`dash.stop`),children:(0,q.jsx)(Ce,{})}),(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb`,onClick:()=>{w()},disabled:C,"aria-label":c(C?`dash.codexRestarting`:`dash.codexRestart`),title:c(C?`dash.codexRestarting`:`dash.codexRestart`),children:(0,q.jsx)(fe,{})})]})]}),(0,q.jsx)(Nv,{apiBase:Ey,onOpenUpdate:()=>{u(!1),t(`dashboard`,`update`)}})]})]}),(0,q.jsx)(`main`,{className:`main`,inert:l,children:(0,q.jsx)(`div`,{className:`main-inner${e===`models`&&n===`combos`?` main-inner--combos`:``}`,children:(0,q.jsxs)(qc,{pageName:c(Ty[e]),title:c(`errorBoundary.title`),message:c(`errorBoundary.message`),detailsLabel:c(`errorBoundary.details`),reloadLabel:c(`errorBoundary.reload`),children:[e===`dashboard`&&(0,q.jsx)(Gr,{apiBase:Ey}),e===`startup`&&(0,q.jsx)(Ov,{apiBase:Ey}),e===`providers`&&(0,q.jsx)(Cc,{apiBase:Ey}),e===`models`&&(0,q.jsx)(If,{apiBase:Ey,restartEpoch:x},Ey),e===`subagents`&&(0,q.jsx)(Jf,{apiBase:Ey},Ey),e===`logs`&&(0,q.jsx)(ym,{apiBase:Ey}),e===`usage`&&(0,q.jsx)(Vm,{apiBase:Ey}),e===`storage`&&(0,q.jsx)(_h,{apiBase:Ey}),e===`codex-auth`&&(0,q.jsx)(wh,{apiBase:Ey}),e===`integrations`&&(0,q.jsx)(hv,{apiBase:Ey})]},e)})})]})}g.createRoot(document.getElementById(`root`)).render((0,q.jsx)(_.StrictMode,{children:(0,q.jsx)(ct,{children:(0,q.jsx)(Ny,{})})}));
|
|
102
|
+
`);if(!confirm(t))return;i(!0),o(null);let a=[];for(let t of N)try{await m_(e,t.clientId,!1)}catch(e){a.push(`${t.clientId}: ${z_(n,e)}`)}let s=!1;try{s=(await d_(e)).clients.some(nv)}catch{a.push(n(`integrations.error.stale`))}s&&a.length===0&&a.push(n(`integrations.error.stale`)),H(),i(!1),o(a.length===0?{tone:`ok`,text:n(`integrations.bulk.success`)}:{tone:`err`,text:n(`integrations.bulk.partial`,{clients:a.join(`; `)})})},W=M[0]?.at,[ee,G]=(0,_.useState)(null),te=()=>{A.refresh(),D.refresh(),k.refresh()},K=(e,t)=>{u(n=>{let r={...n};return t?r[e]=t:delete r[e],r})},J=async(t,r)=>{if(!ee&&t.toggle){G(t.id),K(t.id,null);try{if(t.status)await m_(e,t.status.clientId,r),H();else if(t.toggle===`claude`||t.toggle===`grok`||t.toggle===`codex`||t.toggle===`claude-desktop`){let i=await M_(e,t.toggle,r);i.reason===`non_loopback_removed`?K(t.id,{tone:`ok`,text:n(i.changed?`integrations.native.msg.nonLoopbackRemoved`:`integrations.native.msg.nonLoopbackRemovedNoop`)}):i.reason===`non_loopback_superseded`&&K(t.id,{tone:`ok`,text:n(`integrations.native.msg.nonLoopbackSuperseded`)}),te()}}catch(e){K(t.id,{tone:`err`,text:z_(n,e,void 0,t.togglePath??void 0)}),(t.toggle===`claude`||t.toggle===`grok`||t.toggle===`codex`||t.toggle===`claude-desktop`)&&te()}finally{G(null)}}},ne=(e,t)=>{if(e.status||t||e.id===`claude`||e.toggle===null){J(e,t);return}let n=document.activeElement;p.current=n?.tagName===`BUTTON`?n:null,f(e)};return(0,q.jsxs)(`section`,{className:`integrations-overview`,children:[(0,q.jsxs)(`div`,{className:`integration-summary`,children:[(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.detected`)}),(0,q.jsx)(`strong`,{children:V.detected})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.applied`)}),(0,q.jsx)(`strong`,{children:V.applied})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.stale`)}),(0,q.jsx)(`strong`,{children:V.stale})]}),V.unknown>0&&(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.state.unknown`)}),(0,q.jsx)(`strong`,{children:V.unknown})]}),(0,q.jsxs)(`div`,{className:`integration-summary-cell`,children:[(0,q.jsx)(`span`,{className:`integration-summary-label`,children:n(`integrations.summary.lastChange`)}),(0,q.jsx)(`strong`,{children:W?new Date(W).toLocaleString():n(`integrations.status.unknown`)})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>void U(),disabled:r||N.length===0,children:n(`integrations.summary.disableAll`)})]}),(0,q.jsx)(av,{row:z}),(0,q.jsx)(`p`,{className:`page-sub`,children:n(`integrations.onboarding`)}),C.state.kind===`failed-cold`&&(0,q.jsx)($,{tone:`err`,children:n(`integrations.error.load`)}),C.state.kind===`failed-with-stale`&&(0,q.jsx)($,{tone:`err`,children:n(`integrations.error.stale`)}),a&&(0,q.jsx)($,{tone:a.tone,children:a.text}),B.length===0?C.state.kind===`failed-cold`?null:(0,q.jsx)(`p`,{className:`page-sub`,children:n(`common.loading`)}):(0,q.jsx)(`ul`,{className:`integration-cards`,children:B.map(e=>(0,q.jsx)(rv,{row:e,pending:ee!==null,result:l[e.id]??null,onOpen:()=>ft(e.hash),onToggle:e.toggle?()=>ne(e,!(e.toggleOn??e.applied)):null},e.id))}),F&&P.length===0&&(0,q.jsxs)(`div`,{className:`integration-empty`,children:[(0,q.jsx)(`h4`,{children:n(`integrations.empty.title`)}),(0,q.jsx)(`p`,{children:n(`integrations.empty.body`)})]}),(0,q.jsx)(`h4`,{children:n(`integrations.rollback.title`)}),M.length===0?(0,q.jsxs)(`div`,{className:`integration-empty`,children:[(0,q.jsx)(`p`,{children:n(`integrations.rollback.empty`)}),(0,q.jsx)(`p`,{className:`page-sub`,children:n(`integrations.rollback.emptyBody`)})]}):(0,q.jsx)(`ul`,{className:`integration-history`,children:M.map(e=>(0,q.jsxs)(`li`,{children:[(0,q.jsx)(`span`,{className:`integration-history-kind`,children:n(tv[e.kind])}),(0,q.jsx)(`span`,{className:`integration-history-client`,children:e.clientId}),(0,q.jsx)(`span`,{className:`integration-history-at`,children:new Date(e.at).toLocaleString()}),e.snapshot===`expired`?(0,q.jsx)(`span`,{className:`badge badge-muted`,children:n(`integrations.action.snapshotExpired`)}):(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>c(e),children:e.undoable?n(`integrations.action.undo`):n(`integrations.action.restorePoint`)})]},e.opId))}),s&&(0,q.jsx)(B_,{apiBase:e,row:s,onClose:()=>c(null),onRestored:H}),d&&(0,q.jsx)(t_,{copy:{...d.toggle===`claude-desktop`?ev:$_,vars:{path:d.togglePath??``}},onClose:()=>f(null),onConfirm:async()=>{await J(d,!1),f(null)}})]})}function av({row:e}){let t=Q(),n=e.detailKey?t(e.detailKey,e.detailVars??void 0):null;return(0,q.jsxs)(`div`,{className:`integration-api-keys-row`,"data-client":`keys`,"data-key-state":e.state,children:[(0,q.jsxs)(`div`,{className:`integration-api-keys-copy`,children:[(0,q.jsx)(`h4`,{children:t(e.labelKey)}),n&&(0,q.jsx)(`p`,{className:`integration-meta`,children:n})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>ft(e.hash),children:t(`integrations.action.manageKeys`)})]})}var ov={opencode:`integrations.semantics.opencode`,pi:`integrations.semantics.pi`,omp:`integrations.semantics.omp`,hermes:`integrations.semantics.hermes`,openclaw:`integrations.semantics.openclaw`,kimi:`integrations.semantics.kimi`,gajae:`integrations.semantics.gajae`,dsh:`integrations.semantics.dsh`,mcode:`integrations.semantics.mcode`,zcode:`integrations.semantics.zcode`,prime:`integrations.semantics.prime`},sv={opencode:`integrations.tab.opencode`,pi:`integrations.tab.pi`,omp:`integrations.tab.omp`,hermes:`integrations.tab.hermes`,openclaw:`integrations.tab.openclaw`,kimi:`integrations.tab.kimi`,gajae:`integrations.tab.gajae`,dsh:`integrations.tab.dsh`,mcode:`integrations.tab.mcode`,zcode:`integrations.tab.zcode`,prime:`integrations.tab.prime`},cv={apply:`integrations.kind.apply`,disable:`integrations.kind.disable`,refresh:`integrations.kind.refresh`,restore:`integrations.kind.restore`};function lv({apiBase:e,client:t,active:n=!0}){let r=Q(),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(null),[c,l]=(0,_.useState)(null),u=(0,_.useCallback)(n=>f_(e,t,n),[e,t]),d=(0,_.useCallback)(async n=>(await p_(e,t,n)).operations,[e,t]),f=Uc(`integration-state:${e}:${t}`,[e,t],u,{isEmpty:()=>!1,enabled:n,sessionCacheKey:`ocx.integrations.state.v1:${e}:${t}`}),p=Uc(`integration-journal:${e}:${t}`,[e,t],d,{isEmpty:e=>e.length===0,enabled:n,sessionCacheKey:`ocx.integrations.client-journal.v1:${e}:${t}`}),m=f.state.data??null,h=p.state.data??[],g=()=>{f.refresh(),p.refresh()},v=async n=>{if(!(!m||i)){a(!0),s(null);try{await m_(e,t,n),g()}catch(e){s(z_(r,e))}finally{a(!1)}}},y=()=>void v(!(m&&(m.state===`current`||m.state===`stale`)));if(!m)return(0,q.jsx)(`section`,{className:`integration-client-page`,children:f.state.kind===`failed-cold`?(0,q.jsx)($,{tone:`err`,children:r(`integrations.error.load`)}):(0,q.jsx)(`p`,{className:`page-sub`,children:r(`common.loading`)})});let b=m.state===`current`||m.state===`stale`,x=!m.installed||m.state===`conflict`||m.state===`unsafe`;return(0,q.jsxs)(`section`,{className:`integration-client-page`,children:[(0,q.jsxs)(`div`,{className:`integration-client-head`,children:[(0,q.jsx)(`h3`,{children:r(sv[t])}),(0,q.jsx)($g,{state:m.state,installed:m.installed,id:`integration-state-${t}`}),(0,q.jsx)(wt,{on:b,onClick:y,disabled:x||i,label:r(b?`integrations.action.disable`:`integrations.action.apply`)})]}),m.state===`stale`&&(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>void v(!0),disabled:i,children:r(`integrations.action.refresh`)}),(0,q.jsx)(`p`,{className:`page-sub`,children:r(ov[t])}),(0,q.jsx)(`p`,{className:`integration-path`,children:m.configPath}),m.appliedAt&&(0,q.jsxs)(`p`,{className:`integration-meta`,children:[r(`integrations.status.appliedAt`),`: `,new Date(m.appliedAt).toLocaleString()]}),m.retentionDegraded&&(0,q.jsx)($,{tone:`err`,children:r(`integrations.retention.degraded`)}),o&&(0,q.jsx)($,{tone:`err`,children:o}),(0,q.jsx)(`h4`,{children:r(`integrations.rollback.title`)}),h.length===0?(0,q.jsx)(`p`,{className:`page-sub`,children:r(`integrations.rollback.empty`)}):(0,q.jsx)(`ul`,{className:`integration-history`,children:h.map(e=>(0,q.jsxs)(`li`,{children:[(0,q.jsx)(`span`,{className:`integration-history-kind`,children:r(cv[e.kind])}),(0,q.jsx)(`span`,{className:`integration-history-at`,children:new Date(e.at).toLocaleString()}),e.snapshot===`expired`?(0,q.jsx)(`span`,{className:`badge badge-muted`,children:r(`integrations.action.snapshotExpired`)}):(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>l(e),children:e.undoable?r(`integrations.action.undo`):r(`integrations.action.restorePoint`)})]},e.opId))}),c&&(0,q.jsx)(B_,{apiBase:e,row:c,onClose:()=>l(null),onRestored:g})]})}var uv=[{id:`overview`,hash:`integrations`,labelKey:`integrations.tab.overview`},{id:`keys`,hash:`integrations/keys`,labelKey:`integrations.tab.keys`},{id:`codex`,hash:`integrations/codex`,labelKey:`integrations.tab.codex`},{id:`claude`,hash:`integrations/claude`,labelKey:`integrations.tab.claude`},{id:`grok`,hash:`integrations/grok`,labelKey:`integrations.tab.grok`},{id:`opencode`,hash:`integrations/opencode`,labelKey:`integrations.tab.opencode`},{id:`pi`,hash:`integrations/pi`,labelKey:`integrations.tab.pi`},{id:`omp`,hash:`integrations/omp`,labelKey:`integrations.tab.omp`},{id:`hermes`,hash:`integrations/hermes`,labelKey:`integrations.tab.hermes`},{id:`openclaw`,hash:`integrations/openclaw`,labelKey:`integrations.tab.openclaw`},{id:`kimi`,hash:`integrations/kimi`,labelKey:`integrations.tab.kimi`},{id:`gajae`,hash:`integrations/gajae`,labelKey:`integrations.tab.gajae`},{id:`dsh`,hash:`integrations/dsh`,labelKey:`integrations.tab.dsh`},{id:`mcode`,hash:`integrations/mcode`,labelKey:`integrations.tab.mcode`},{id:`zcode`,hash:`integrations/zcode`,labelKey:`integrations.tab.zcode`},{id:`prime`,hash:`integrations/prime`,labelKey:`integrations.tab.prime`}],dv=new Set([`opencode`,`pi`,`omp`,`hermes`,`openclaw`,`kimi`,`gajae`,`dsh`,`mcode`,`zcode`,`prime`]);function fv(e=window.location.hash){let t=ut(e);return t===`integrations/claude/desktop`?`claude`:uv.find(e=>e.hash===t)?.id??`overview`}function pv(e){return`integrations-tab-${e}`}function mv(e){return`integrations-panel-${e}`}function hv({apiBase:e}){let t=Q(),[n,r]=(0,_.useState)(fv),[i,a]=(0,_.useState)(()=>new Set([fv()])),o=(0,_.useRef)(null);o.current===null&&(o.current=new Map);let s=e=>{r(e),a(t=>t.has(e)?t:new Set([...t,e]))};(0,_.useEffect)(()=>{let e=()=>s(fv());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let c=(e,t)=>{let n=uv.find(t=>t.id===e);n&&(ft(n.hash),s(e),t&&window.requestAnimationFrame(()=>{o.current.get(e)?.focus({preventScroll:!0})}))},l=e=>{let t=uv.findIndex(e=>e.id===n),r=null;e.key===`ArrowLeft`?r=(t-1+uv.length)%uv.length:e.key===`ArrowRight`?r=(t+1)%uv.length:e.key===`Home`?r=0:e.key===`End`&&(r=uv.length-1),r!==null&&(e.preventDefault(),c(uv[r].id,!0))};return(0,q.jsxs)(`section`,{className:`integrations-page`,children:[(0,q.jsx)(`div`,{className:`page-head`,children:(0,q.jsx)(`h2`,{children:t(`nav.integrations`)})}),(0,q.jsx)(`p`,{className:`page-sub`,children:t(`integrations.subtitle`)}),(0,q.jsx)(`div`,{className:`page-tabs`,role:`tablist`,"aria-label":t(`integrations.tabsLabel`),children:uv.map(e=>(0,q.jsx)(`button`,{ref:t=>{t?o.current.set(e.id,t):o.current.delete(e.id)},type:`button`,role:`tab`,id:pv(e.id),"aria-selected":n===e.id,"aria-controls":mv(e.id),tabIndex:n===e.id?0:-1,className:`page-tab${n===e.id?` page-tab--active`:``}`,onClick:()=>c(e.id,!0),onKeyDown:l,children:t(e.labelKey)},e.id))}),uv.map(r=>{if(!i.has(r.id))return null;let a=n===r.id;return(0,q.jsxs)(`div`,{role:`tabpanel`,id:mv(r.id),"aria-labelledby":pv(r.id),hidden:!a,children:[r.id===`overview`&&(0,q.jsx)(iv,{apiBase:e,active:a}),r.id===`keys`&&(0,q.jsx)(eg,{apiBase:e,active:a}),r.id===`codex`&&(0,q.jsxs)(`section`,{className:`integration-native-page`,"aria-labelledby":`codex-integration-title`,children:[(0,q.jsx)(`h3`,{id:`codex-integration-title`,children:t(`integrations.codex.title`)}),(0,q.jsx)(`p`,{children:t(`integrations.codex.body`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>ft(`startup`),children:t(`integrations.codex.openService`)})]}),r.id===`claude`&&(0,q.jsx)(Wg,{apiBase:e,active:a}),r.id===`grok`&&(0,q.jsx)(Xg,{apiBase:e,active:a}),dv.has(r.id)&&(0,q.jsx)(lv,{apiBase:e,client:r.id,active:a})]},r.id)})]})}function gv(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 _v={native:`startup.status.native`,protected:`startup.status.protected`,"at-risk":`startup.status.atRisk`},vv={native:`startup.summary.native`,protected:`startup.summary.protected`,"at-risk":`startup.summary.atRisk`},yv={service:`startup.protection.service`,shim:`startup.protection.shim`,none:`startup.protection.none`};function bv({ok:e,yes:t,no:n}){return(0,q.jsx)(`span`,{className:`badge ${e?`badge-green`:`badge-amber`}`,children:e?t:n})}function xv({failed:e,data:t}){let{t:n}=st(),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`?ge:le,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,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`section`,{className:`panel startup-hero ${r}`,"aria-live":`polite`,children:[(0,q.jsx)(`div`,{className:`startup-hero-icon`,children:(0,q.jsx)(i,{})}),(0,q.jsxs)(`div`,{className:`startup-hero-copy`,children:[(0,q.jsx)(`span`,{className:`badge ${e||t.status===`at-risk`?`badge-amber`:`badge-green`}`,children:n(e?`startup.status.atRisk`:_v[t.status])}),(0,q.jsx)(`h3`,{children:n(e?`startup.error`:vv[t.status])}),(0,q.jsx)(`p`,{children:e?n(`startup.staleData`):t.status===`at-risk`?n(gr(t)):n(`startup.safeDetail`)})]})]}),(0,q.jsxs)(`div`,{className:`startup-state-grid`,children:[(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.routing`)}),(0,q.jsx)(`div`,{className:`value`,children:n(a)})]}),(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.restartProtection`)}),(0,q.jsx)(`div`,{className:`value`,children:n(yv[t.protection])})]}),(0,q.jsxs)(`section`,{className:`stat`,children:[(0,q.jsx)(`div`,{className:`label`,children:n(`startup.preference`)}),(0,q.jsx)(`div`,{className:`value`,children:n(t.autostartEnabled?`startup.enabled`:`startup.disabled`)})]})]})]})}function Sv({data:e,failed:t,loading:n=!1,installBusy:r,installResult:i,onInstall:a}){let{t:o}=st(),s=e.serviceSupported&&e.serviceInstalled&&e.serviceStale&&!e.serviceConflict,c=e.shimInstalled&&!e.shimHealthy,l=r!==null||t||n;return(0,q.jsxs)(`section`,{className:`panel startup-details`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:o(`startup.details`)}),(0,q.jsx)(`span`,{className:`muted mono`,children:e.platform})]}),(0,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:o(`startup.service`)}),(0,q.jsx)(`span`,{children:o(`startup.serviceHint`)})]}),(0,q.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,q.jsx)(bv,{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,q.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,q.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,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:o(`startup.shim`)}),(0,q.jsx)(`span`,{children:o(`startup.shimHint`)})]}),(0,q.jsxs)(`div`,{className:`startup-detail-actions`,children:[(0,q.jsx)(bv,{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,q.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,q.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,q.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 Cv({tray:e,trayLoading:t,trayError:n,trayBusy:r,onTrayAction:i}){let{t:a}=st();return(0,q.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:a(`startup.tray.title`)}),(0,q.jsx)(Ce,{})]}),(0,q.jsx)(`p`,{className:`muted`,children:a(`startup.tray.hint`)}),(0,q.jsxs)(`div`,{className:`startup-detail-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:a(`startup.tray.login`)}),(0,q.jsx)(`span`,{children:a(`startup.tray.notProtection`)})]}),t||n||!e?(0,q.jsx)(`span`,{className:`badge badge-amber`,children:a(t?`startup.tray.loading`:`startup.tray.unavailable`)}):(0,q.jsx)(bv,{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,q.jsxs)(`div`,{className:`startup-tray-buttons`,children:[!t&&!n&&e&&!e.installed&&!e.stale&&(0,q.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,q.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,q.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,q.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,q.jsx)(`div`,{className:`notice notice-warn startup-tray-error`,role:`alert`,children:a(`startup.tray.error`)})]})}function wv({data:e,copied:t,onCopy:n}){let{t:r}=st(),i=e.serviceInstalled&&!e.serviceConflict?e.commands.repairService:e.commands.installService;return(0,q.jsxs)(`section`,{className:`panel startup-actions`,children:[(0,q.jsxs)(`div`,{className:`panel-head`,children:[(0,q.jsx)(`h3`,{className:`panel-title`,children:r(`startup.recovery`)}),(0,q.jsx)(X,{})]}),(0,q.jsx)(`p`,{className:`muted`,children:r(`startup.recoveryHint`)}),(0,q.jsxs)(`div`,{className:`startup-command-list`,children:[e.serviceSupported&&(0,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.service`)}),(0,q.jsx)(`code`,{children:i})]}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>n(i),children:r(t===i?`startup.copied`:`startup.copy`)})]}),(0,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.shim`)}),(0,q.jsx)(`code`,{children:e.commands.installShim})]}),(0,q.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,q.jsxs)(`div`,{className:`startup-command-row`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`strong`,{children:r(`startup.command.native`)}),(0,q.jsx)(`code`,{children:e.commands.restoreNative})]}),(0,q.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,q.jsxs)(`div`,{className:`notice notice-warn startup-action-notice`,role:`alert`,children:[(0,q.jsx)(Ce,{}),` `,r(`startup.recommended`,{cmd:e.recommendedCommand??e.commands.installService})]})]})}var Tv=`ocx.startup.page.v1:`;function Ev(e,t){let n=t===`win32`?`; `:` && `;return e.join(n)}function Dv(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=Ev([`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 Ov({apiBase:e}){let{t}=st(),n=`${Tv}${e}`,r=(0,_.useMemo)(()=>dr(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();y(e=>e?.kind===`error`&&(o.status===`native`&&e.forLocalRouting===!0||(e.action===`install-service`?o.serviceViable:o.shimInstalled&&o.shimHealthy))?null:e),E.current=!0;let s=dr(n);hr(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(!gv(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=Dv(e.codexRuntime,t,o.platform);x(r.warning),C(r.fix),hr(n,{data:o,warning:r.warning,fix:r.fix,tray:a});return}let s=dr(n);hr(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=Uc(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(!gv(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),forLocalRouting:j?.localRoutingDependency===!0})}finally{g(null)}};return(0,q.jsxs)(q.Fragment,{children:[(0,q.jsxs)(`div`,{className:`page-head`,children:[(0,q.jsxs)(`div`,{children:[(0,q.jsx)(`h2`,{children:t(`startup.title`)}),(0,q.jsx)(`p`,{className:`page-sub startup-page-sub`,children:t(`startup.subtitle`)})]}),(0,q.jsxs)(`div`,{className:`startup-page-head-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>ft(`dashboard`),children:t(`startup.backToDashboard`)}),(0,q.jsxs)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),disabled:M,children:[(0,q.jsx)(fe,{}),` `,t(`startup.refresh`)]})]})]}),k.showSkeleton&&!j?(0,q.jsx)(Gc,{label:t(`startup.loading`),rows:5}):k.kind===`failed-cold`?(0,q.jsxs)(`div`,{className:`startup-page-notice`,children:[(0,q.jsx)($,{tone:`err`,children:k.error instanceof Error?k.error.message:t(`startup.error`)}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>A(),children:t(`common.retry`)})]}):j?(0,q.jsxs)(q.Fragment,{children:[k.showError&&(0,q.jsx)($,{tone:`err`,children:t(`startup.error`)}),N&&(0,q.jsx)(`div`,{className:`notice notice-warn startup-page-notice`,role:`alert`,children:t(`startup.staleData`)}),(w||b)&&(0,q.jsx)(`div`,{className:`startup-runtime-notice-slot${w&&!b?` startup-runtime-notice-slot--pending`:``}`,"aria-hidden":w&&!b?!0:void 0,children:b&&(0,q.jsxs)(`div`,{className:`notice notice-warn startup-page-notice startup-runtime-notice`,role:`status`,children:[(0,q.jsx)(`p`,{className:`startup-runtime-notice__text`,children:b}),S&&(0,q.jsxs)(`div`,{className:`startup-runtime-notice__fix`,children:[(0,q.jsx)(`code`,{children:S}),(0,q.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>void P(S),children:t(a===S?`startup.copied`:`startup.copy`)})]})]})}),(0,q.jsx)(xv,{failed:N,data:j}),(0,q.jsx)(Sv,{data:j,failed:N,loading:M,installBusy:h,installResult:v,onInstall:(e,t)=>{I(e,t)}}),j.platform===`win32`&&(0,q.jsx)(Cv,{tray:s,trayLoading:l,trayError:p,trayBusy:d,onTrayAction:e=>{F(e)}}),(0,q.jsx)(wv,{data:j,copied:a,onCopy:e=>{P(e)}})]}):null]})}var kv=3e5,Av=6e5,jv=`https://github.com/lidge-jun/opencodex`;async function Mv(e,t){let n=await fetch(e,{signal:t});return n.ok?await n.json():null}function Nv({apiBase:e,onOpenUpdate:t}){let n=Q(),[r,i]=(0,_.useState)(!1),[a,o]=(0,_.useState)(null),s=G(`sidebar-star:${e}`,[e],t=>Mv(`${e}/api/github/star`,t),{pollMs:kv}),c=G(`sidebar-update-badge:${e}`,[e],t=>Mv(`${e}/api/update/badge`,t),{pollMs:Av}),l=s.data?.state??null,u=a!==null&&a.basedOn===l?a.state:l??`not-starred`,d=s.data?.url??jv,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,q.jsxs)(`div`,{className:`sidebar-github-row`,children:[(0,q.jsxs)(`a`,{className:`sidebar-link sidebar-github-link`,href:d,target:`_blank`,rel:`noreferrer`,children:[(0,q.jsx)(Se,{}),` `,n(`common.github`)]}),(0,q.jsxs)(`div`,{className:`sidebar-github-actions`,children:[(0,q.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,q.jsx)(Fe,{"aria-hidden":`true`,...f?{fill:`currentColor`}:{}})}),(0,q.jsxs)(`button`,{type:`button`,className:`sidebar-orb${m?` sidebar-orb--update`:``}`,onClick:t,"aria-label":b,title:b,children:[(0,q.jsx)(Z,{"aria-hidden":`true`}),m&&(0,q.jsx)(`span`,{className:`sidebar-orb-dot`,"aria-hidden":`true`})]})]})]})}var Pv=`opencodex-admin-token-dialog`,Fv=`OpenCodex`;function Iv(e,t=rt()){let n=Xe[t],r=n[`auth.adminTokenTitle`];return new Promise(t=>{let i=document.activeElement instanceof HTMLElement?document.activeElement:null,a=!1,o=document.createElement(`dialog`);o.id=Pv,o.className=`modal-overlay`,o.setAttribute(`aria-labelledby`,`${Pv}-title`);let s=document.createElement(`form`);s.className=`modal-card`,s.method=`post`,s.action=window.location.href,s.autocomplete=`on`;let c=document.createElement(`div`);c.className=`modal-head`;let l=document.createElement(`h3`);l.id=`${Pv}-title`,l.textContent=r,c.append(l);let u=document.createElement(`div`),d=document.createElement(`label`);d.className=`field-label`,d.htmlFor=`${Pv}-username`,d.textContent=n[`auth.adminAccountLabel`];let f=document.createElement(`input`);f.id=d.htmlFor,f.className=`input`,f.type=`text`,f.name=`username`,f.autocomplete=`username`,f.value=Fv,f.readOnly=!0,u.append(d,f);let p=document.createElement(`div`);p.style.marginTop=`var(--space-4)`;let m=document.createElement(`label`);m.className=`field-label`,m.htmlFor=`${Pv}-password`,m.textContent=n[`auth.adminTokenFieldLabel`];let h=document.createElement(`input`);h.id=m.htmlFor,h.className=`input`,h.type=`password`,h.name=`password`,h.autocomplete=`current-password`,h.required=!0,h.spellcheck=!1,h.autocapitalize=`none`,p.append(m,h);let g=document.createElement(`div`);g.className=`notice notice-err`,g.setAttribute(`role`,`alert`),g.hidden=!0;let _=document.createElement(`div`);_.className=`modal-actions`;let v=document.createElement(`button`);v.type=`button`,v.className=`btn btn-ghost`,v.textContent=n[`common.cancel`];let y=document.createElement(`button`);y.type=`submit`,y.className=`btn btn-primary`,y.textContent=n[`common.ok`],_.append(v,y),s.append(c,u,p,g,_),o.append(s);let b=e=>{a||(a=!0,o.open&&o.close(),o.remove(),i?.focus(),t(e))};s.addEventListener(`submit`,t=>{t.preventDefault();let r=h.value.trim();if(!r){h.value=``,h.reportValidity();return}h.disabled=!0,y.disabled=!0,g.hidden=!0,e(r).then(e=>{if(!a){if(e===`accepted`){b(r);return}h.value=``,h.disabled=!1,y.disabled=!1,g.textContent=e===`rejected`?n[`auth.adminTokenRejected`]:n[`auth.adminTokenUnavailable`],g.hidden=!1,h.focus()}}).catch(()=>{a||(h.value=``,h.disabled=!1,y.disabled=!1,g.textContent=n[`auth.adminTokenUnavailable`],g.hidden=!1,h.focus())})}),v.addEventListener(`click`,()=>b(null)),o.addEventListener(`cancel`,e=>{e.preventDefault(),b(null)}),document.body.append(o),typeof o.showModal==`function`?o.showModal():o.setAttribute(`open`,``),queueMicrotask(()=>h.focus())})}var Lv=!1,Rv=null,zv=null,Bv=!1,Vv=Iv,Hv=`/opencodex-session`,Uv=`/api/settings`,Wv=1e4,Gv=15e3;function Kv(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/`)}catch{return!1}}var qv=`opencodex-api-token`,Jv=null,Yv=null,Xv=null;function Zv(){return Jv}function Qv(e){Jv=e}function $v(){Jv=null,Yv=null,Xv=null}function ey(e){let t=document.querySelector(`meta[name="${e}"]`),n=t?.content.trim()||null;return t?.remove(),n}function ty(){ry(ey(`opencodex-session-token`),ey(`opencodex-session-csrf`),ey(`opencodex-session-origin`))}function ny(e){e!=null&&Zv()===e&&$v()}function ry(e,t,n){return!e?.startsWith(`ocx_session_`)||!t||n!==window.location.origin?!1:(Jv=e,Yv=t,Xv=n,!0)}function iy(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 ay(){if(!zv)return{kind:`failed`};let e=In(Wv);try{let t=await zv(Hv,{cache:`no-store`,signal:e.signal});if(!t.ok)return t.status>=400&&t.status<500?{kind:`unavailable`}:{kind:`failed`};let n=await t.text(),r=ry(iy(n,`opencodex-session-token`),iy(n,`opencodex-session-csrf`),iy(n,`opencodex-session-origin`)),i=Zv();return r&&i?{kind:`minted`,token:i}:{kind:`unavailable`}}catch{return{kind:`failed`}}finally{e.clear()}}async function oy(e){if(!zv)return`unavailable`;try{let[t,n]=cy(Uv,{cache:`no-store`},e),r=await zv(t,n);return r.status===401?`rejected`:r.ok?`accepted`:`unavailable`}catch{return`unavailable`}}function sy(){try{sessionStorage.removeItem(qv)}catch{}}function cy(e,t,n){let r=new Headers(t?.headers??(e instanceof Request?e.headers:void 0));if(r.set(`X-OpenCodex-API-Key`,n),Xv&&Yv&&n.startsWith(`ocx_session_`)){r.set(`X-OpenCodex-GUI-Origin`,Xv);let n=(t?.method??(e instanceof Request?e.method:`GET`)).toUpperCase();n!==`GET`&&n!==`HEAD`&&r.set(`X-OpenCodex-CSRF-Token`,Yv)}return e instanceof Request?[new Request(e,{headers:r}),t?{...t,headers:r}:void 0]:[e,{...t,headers:r}]}async function ly(e,t){if(Bv||t?.aborted)return null;if(!Rv){let t=(async()=>{if(Bv)return null;let t=Zv();if(t&&t!==e)return t;let n,r=await Promise.race([ay(),new Promise(e=>{n=setTimeout(()=>e({kind:`failed`}),Gv)})]).finally(()=>clearTimeout(n));if(r.kind===`minted`)return r.token;if(r.kind===`failed`)return null;let i=await Vv(oy);return i?(Qv(i),i):(Bv=!0,null)})().finally(()=>{Rv===t&&(Rv=null)});Rv=t}if(!t)return Rv;let n,r=new Promise(e=>{n=()=>e(null),t.addEventListener(`abort`,n,{once:!0})});return Promise.race([Rv,r]).finally(()=>{n&&t.removeEventListener(`abort`,n)})}function uy(){if(Lv)return;Lv=!0,sy(),ty();let e=window.fetch.bind(window);zv=e,window.fetch=async(t,n)=>{if(!Kv(t))return e(t,n);let r=n?.signal??(t instanceof Request?t.signal:void 0),i=Zv(),[a,o]=i?cy(t,n,i):[t,n],s=await e(a,o);if(s.status!==401)return s;let c=Zv();if(c&&c!==i){let[r,i]=cy(t,n,c),a=await e(r,i);if(a.status!==401)return a;ny(c)}else ny(i);let l=await ly(i,r??void 0);if(!l)return s;let[u,d]=cy(t,n,l),f=await e(u,d);return f.status===401&&ny(l),f}}var dy=new Set([`dashboard`,`startup`,`providers`,`models`,`subagents`,`logs`,`usage`,`storage`,`codex-auth`,`integrations`]);function fy(e){let t=ut(e??(typeof window<`u`?window.location.hash:``)).split(`/`)[0];return t===`debug`?`logs`:t===`combos`||t===`routing`||t===`lab`?`models`:t===`api`||t===`claude`||t===`grok`?`integrations`:dy.has(t)?t:`dashboard`}var py=[`dashboard/providers`,`dashboard/models`],my=[`models/combos`,`models/routing`,`models/compatibility`],hy=[`integrations/keys`,`integrations/codex`,`integrations/claude`,`integrations/claude/desktop`,`integrations/grok`,`integrations/opencode`,`integrations/pi`,`integrations/omp`,`integrations/hermes`,`integrations/openclaw`,`integrations/kimi`,`integrations/gajae`,`integrations/dsh`,`integrations/mcode`,`integrations/zcode`,`integrations/prime`];function gy(e,t){return e===t||t===`logs`&&e===`logs/debug`||t===`models`&&my.includes(e)||t===`dashboard`&&(e===`dashboard/update`||py.includes(e))||t===`integrations`&&hy.includes(e)}function _y(e){let t=fy(e);return e===`debug`||e.startsWith(`debug/`)?{page:`logs`,replaceTo:`logs/debug`}:e===`combos`||e.startsWith(`combos/`)?{page:`models`,replaceTo:`models/combos`}:e===`routing`||e.startsWith(`routing/`)?{page:`models`,replaceTo:`models/routing`}:e===`lab`||e.startsWith(`lab/`)?{page:`models`,replaceTo:`models/compatibility`}:e===`api`?{page:`integrations`,replaceTo:`integrations/keys`}:e===`claude`?{page:`integrations`,replaceTo:`integrations/claude`}:e===`grok`?{page:`integrations`,replaceTo:`integrations/grok`}:e===`providers/workspace`?{page:`providers`,replaceTo:`providers`}:gy(e,t)?{page:t,replaceTo:null}:{page:t,replaceTo:t}}var vy=[`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 yy(){try{for(let e of vy)localStorage.removeItem(e)}catch{}}function by(){let[e,t]=(0,_.useState)(fy);(0,_.useEffect)(()=>{yy()},[]);let n=(0,_.useCallback)(e=>{let n=_y(e);n.replaceTo&&dt(n.replaceTo),t(n.page)},[]);return(0,_.useEffect)(()=>{let e=()=>{n(ut(window.location.hash))};return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[n]),(0,_.useEffect)(()=>{let n=_y(ut(window.location.hash));n.replaceTo&&dt(n.replaceTo),n.page!==e&&t(n.page)},[e]),{page:e,setPageState:t,navigateToPage:(e,n)=>{ft(n?`${e}/${n}`:e),t(e)}}}var xy=15e3;function Sy(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 Cy(e){return(e instanceof DOMException||e instanceof Error)&&e.name===`AbortError`}async function wy(e,t={}){let{fetchFn:n=fetch,timeoutMs:r=xy,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 Cy(e),{accepted:!0}}let o=await a.json().catch(()=>null);return!a.ok||o?.success===!1?{accepted:!1,message:Sy(o,a.status,i)}:{accepted:!0}}uy();var Ty={dashboard:`nav.dashboard`,startup:`nav.startup`,providers:`nav.providers`,models:`nav.models`,subagents:`nav.subagents`,logs:`nav.logs`,usage:`nav.usage`,storage:`nav.storage`,"codex-auth":`nav.codexAuth`,integrations:`nav.integrations`},Ey=``,Dy=`ocx-theme`,Oy=[{id:`dashboard`,tkey:`nav.dashboard`,Icon:ne},{id:`codex-auth`,tkey:`nav.codexAuth`,Icon:Te},{id:`providers`,tkey:`nav.providers`,Icon:re},{id:`models`,tkey:`nav.models`,Icon:ie},{id:`subagents`,tkey:`nav.subagents`,Icon:Y},{id:`logs`,tkey:`nav.logs`,Icon:ae},{id:`usage`,tkey:`nav.usage`,Icon:se},{id:`storage`,tkey:`nav.storage`,Icon:ce},{id:`integrations`,tkey:`nav.integrations`,Icon:Me}],ky={light:ke,dark:Ae,system:je},Ay={light:`theme.light`,dark:`theme.dark`,system:`theme.system`};function jy(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 My(){let e=localStorage.getItem(Dy);return e===`light`||e===`dark`?e:`system`}function Ny(){let{page:e,navigateToPage:t}=by(),[n,r]=(0,_.useState)(ef);(0,_.useEffect)(()=>{let e=()=>r(ef());return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]);let[i,a]=(0,_.useState)(My),{locale:o,setLocale:s}=st(),c=Q(),[l,u]=(0,_.useState)(!1),d=(0,_.useRef)(null),f=(0,_.useRef)(null),p=(0,_.useRef)(!1);(0,_.useEffect)(()=>{let e=()=>u(!1);return window.addEventListener(`hashchange`,e),window.addEventListener(`popstate`,e),()=>{window.removeEventListener(`hashchange`,e),window.removeEventListener(`popstate`,e)}},[]),(0,_.useEffect)(()=>{let e=document.documentElement;i===`system`?(e.removeAttribute(`data-theme`),localStorage.removeItem(Dy)):(e.setAttribute(`data-theme`,i),localStorage.setItem(Dy,i))},[i]);let m=G(`app-healthz:${Ey}`,[],async e=>{let t=await fetch(`${Ey}/healthz`,{signal:e});return t.ok?jy(await t.json()):null},{pollMs:3e4}),h=()=>a(e=>e===`light`?`dark`:e===`dark`?`system`:`light`),g=ky[i],v=m.data??`2.32.1-preview.20260825`,[y,b]=(0,_.useState)(!1);(0,_.useEffect)(()=>{if(!l)return;let e=e=>{e.key===`Escape`&&u(!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}},[l]),(0,_.useEffect)(()=>{if(l){p.current=!0;let e=setTimeout(()=>f.current?.focus(),200);return()=>clearTimeout(e)}p.current&&(p.current=!1,d.current?.focus())},[l]),(0,_.useEffect)(()=>{let e=window.matchMedia(`(min-width: 761px)`),t=()=>{e.matches&&u(!1)};return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)},[]);let[x,S]=(0,_.useState)(0),{restarting:C,restart:w}=Ic(Ey,{onSettled:()=>S(e=>e+1)}),T=async()=>{if(!confirm(c(`dash.stopConfirm`)))return;b(!0);let e=await wy(Ey,{formatFailure:e=>c(`dash.stopFailed`,{status:String(e)})});e.accepted||(b(!1),alert(e.message))},E=(0,q.jsxs)(`div`,{className:`brand`,children:[(0,q.jsx)(`span`,{className:`brand-logo`,role:`img`,"aria-label":c(`app.logoAria`)}),(0,q.jsx)(`span`,{className:`name`,children:`opencodex`}),(0,q.jsxs)(`span`,{className:`ver`,children:[`v`,v]})]});return(0,q.jsxs)(`div`,{className:`app`,children:[(0,q.jsxs)(`header`,{className:`mobile-topbar`,inert:l,children:[(0,q.jsx)(`button`,{ref:d,type:`button`,className:`menu-toggle`,onClick:()=>u(e=>!e),"aria-expanded":l,"aria-controls":`app-sidebar`,"aria-label":c(l?`nav.closeMenu`:`nav.openMenu`),title:c(l?`nav.closeMenu`:`nav.openMenu`),children:(0,q.jsx)(oe,{})}),E,(0,q.jsxs)(`div`,{className:`mobile-topbar-actions`,children:[(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb sidebar-orb--danger`,onClick:T,disabled:y,"aria-label":c(`dash.stop`),title:c(`dash.stop`),children:(0,q.jsx)(Ce,{})}),(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb`,onClick:()=>{w()},disabled:C,"aria-label":c(`dash.codexRestart`),title:c(`dash.codexRestart`),children:(0,q.jsx)(fe,{})})]})]}),l&&(0,q.jsx)(`div`,{className:`drawer-scrim`,onClick:()=>u(!1),"aria-hidden":`true`}),(0,q.jsxs)(`aside`,{id:`app-sidebar`,className:`sidebar${l?` open`:``}`,ref:f,tabIndex:-1,children:[(0,q.jsxs)(`div`,{className:`drawer-head`,children:[E,(0,q.jsx)(`button`,{type:`button`,className:`menu-toggle drawer-close`,onClick:()=>u(!1),"aria-label":c(`nav.closeMenu`),title:c(`nav.closeMenu`),children:(0,q.jsx)(ue,{})})]}),(0,q.jsx)(`nav`,{children:Oy.map(n=>{let{id:r,tkey:i,Icon:a}=n,o=r===e;return(0,q.jsx)(`div`,{className:`nav-entry`,children:(0,q.jsxs)(`button`,{type:`button`,className:`nav-item${o?` active`:``}`,"data-page":r,onClick:()=>{t(r),u(!1)},"aria-current":o?`page`:void 0,children:[(0,q.jsx)(a,{}),` `,c(i)]})},r)})}),(0,q.jsxs)(`div`,{className:`sidebar-foot`,children:[(0,q.jsxs)(`div`,{className:`lang-toggle`,children:[(0,q.jsx)(Me,{"aria-hidden":!0}),(0,q.jsx)(Et,{value:o,options:$e.map(e=>({value:e.code,label:Ze(e.code)})),onChange:e=>s(e),label:c(`lang.label`),placement:`right`,portal:!1,style:{flex:1,minWidth:0,width:`100%`}})]}),(0,q.jsxs)(`button`,{type:`button`,className:`theme-toggle`,onClick:h,"aria-label":`${c(`theme.label`)}: ${c(Ay[i])}`,title:`${c(`theme.label`)}: ${c(Ay[i])}`,children:[(0,q.jsx)(g,{}),` `,(0,q.jsx)(`span`,{className:`mode`,children:c(Ay[i])})]}),(0,q.jsxs)(`div`,{className:`sidebar-action-row`,children:[(0,q.jsx)(`span`,{className:`sidebar-action-label`,children:c(`dash.actions`)}),(0,q.jsxs)(`div`,{className:`sidebar-action-orbs`,children:[(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb sidebar-orb--danger`,onClick:T,disabled:y,"aria-label":c(y?`dash.stopping`:`dash.stop`),title:c(y?`dash.stopping`:`dash.stop`),children:(0,q.jsx)(Ce,{})}),(0,q.jsx)(`button`,{type:`button`,className:`sidebar-orb`,onClick:()=>{w()},disabled:C,"aria-label":c(C?`dash.codexRestarting`:`dash.codexRestart`),title:c(C?`dash.codexRestarting`:`dash.codexRestart`),children:(0,q.jsx)(fe,{})})]})]}),(0,q.jsx)(Nv,{apiBase:Ey,onOpenUpdate:()=>{u(!1),t(`dashboard`,`update`)}})]})]}),(0,q.jsx)(`main`,{className:`main`,inert:l,children:(0,q.jsx)(`div`,{className:`main-inner${e===`models`&&n===`combos`?` main-inner--combos`:``}`,children:(0,q.jsxs)(qc,{pageName:c(Ty[e]),title:c(`errorBoundary.title`),message:c(`errorBoundary.message`),detailsLabel:c(`errorBoundary.details`),reloadLabel:c(`errorBoundary.reload`),children:[e===`dashboard`&&(0,q.jsx)(Gr,{apiBase:Ey}),e===`startup`&&(0,q.jsx)(Ov,{apiBase:Ey}),e===`providers`&&(0,q.jsx)(Cc,{apiBase:Ey}),e===`models`&&(0,q.jsx)(If,{apiBase:Ey,restartEpoch:x},Ey),e===`subagents`&&(0,q.jsx)(Jf,{apiBase:Ey},Ey),e===`logs`&&(0,q.jsx)(ym,{apiBase:Ey}),e===`usage`&&(0,q.jsx)(Vm,{apiBase:Ey}),e===`storage`&&(0,q.jsx)(_h,{apiBase:Ey}),e===`codex-auth`&&(0,q.jsx)(wh,{apiBase:Ey}),e===`integrations`&&(0,q.jsx)(hv,{apiBase:Ey})]},e)})})]})}g.createRoot(document.getElementById(`root`)).render((0,q.jsx)(_.StrictMode,{children:(0,q.jsx)(ct,{children:(0,q.jsx)(Ny,{})})}));
|
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-DrjQlNns.js"></script>
|
|
20
20
|
<link rel="stylesheet" crossorigin href="/assets/index-DcBbHIAz.css">
|
|
21
21
|
</head>
|
|
22
22
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bitkyc08/opencodex",
|
|
3
|
-
"version": "2.32.
|
|
3
|
+
"version": "2.32.1-preview.20260825",
|
|
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",
|
|
@@ -469,10 +469,10 @@ function claudeFamilyVersion(modelId: string): { family: string; major: number;
|
|
|
469
469
|
// Find the segment that actually starts with `claude-`, rather than assuming it is either
|
|
470
470
|
// the first (breaks `anthropic/claude-sonnet-5`) or the last (breaks `claude-sonnet-5/variant`,
|
|
471
471
|
// where the slash carries a vendor suffix rather than a routing prefix).
|
|
472
|
-
const match = /(?:^|\/)claude-([a-z]+)-(\d+)(
|
|
472
|
+
const match = /(?:^|\/)claude-([a-z]+)-(\d+)(?:[.-](\d{1,2}))?(?!\d)/i.exec(modelId);
|
|
473
473
|
if (!match) return undefined;
|
|
474
474
|
return {
|
|
475
|
-
family: match[1]
|
|
475
|
+
family: match[1]!.toLowerCase(),
|
|
476
476
|
major: Number(match[2]),
|
|
477
477
|
minor: match[3] === undefined ? 0 : Number(match[3]),
|
|
478
478
|
};
|
package/src/adapters/base.ts
CHANGED
|
@@ -75,7 +75,7 @@ export interface AdapterRequest {
|
|
|
75
75
|
/** Client tool-search names actually lowered to upstream function calls for this request. */
|
|
76
76
|
convertedRoutedToolSearchNames?: ReadonlySet<string>;
|
|
77
77
|
/** Upstream-only aliases for namespace tools flattened in this request. */
|
|
78
|
-
convertedRoutedNamespaceToolAliases?: ReadonlyMap<string, { namespace: string; name: string }>;
|
|
78
|
+
convertedRoutedNamespaceToolAliases?: ReadonlyMap<string, { namespace: string; name: string; kind: "function" | "custom" }>;
|
|
79
79
|
/** Releases observation of a serialized request body after its final fetch attempt settles. */
|
|
80
80
|
releaseBodyObservation?: () => void;
|
|
81
81
|
/** Exact reasoning parameter emitted by the adapter, for request-log diagnostics only. */
|
|
@@ -1686,7 +1686,7 @@ export function createResponsesPassthroughAdapter(provider: OcxProviderConfig):
|
|
|
1686
1686
|
let convertedRoutedCustomToolNames: Set<string> | undefined;
|
|
1687
1687
|
let routedCustomToolRepairNames: Set<string> | undefined;
|
|
1688
1688
|
let convertedRoutedToolSearchNames: Set<string> | undefined;
|
|
1689
|
-
let convertedRoutedNamespaceToolAliases: Map<string, { namespace: string; name: string }> | undefined;
|
|
1689
|
+
let convertedRoutedNamespaceToolAliases: Map<string, { namespace: string; name: string; kind: "function" | "custom" }> | undefined;
|
|
1690
1690
|
const unexpandedMiss = !!parsed.previousResponseId && parsed._previousResponseInputExpanded !== true;
|
|
1691
1691
|
let outBody = stripPreviousResponseId(
|
|
1692
1692
|
parsed._rawBody,
|
|
@@ -41,7 +41,7 @@ import type { FastPolicyAuthority } from "../../providers/fastwire";
|
|
|
41
41
|
import { effectiveGoogleMode, getProviderRegistryEntry, providerMatchesRegistryTransport } from "../../providers/registry";
|
|
42
42
|
import { parseAntigravityAvailableModels, registerAntigravityDiscoveredWireModels } from "../../providers/antigravity-models";
|
|
43
43
|
import { applyProviderContextCap, providerContextCap, resolveUnknownRoutedContextWindow } from "../../providers/context-cap";
|
|
44
|
-
import { routedSlug, slugEquals, slugsEquivalent } from "../../providers/slug-codec";
|
|
44
|
+
import { routedSlug, slugEquals, slugEquivalenceKey, slugsEquivalent } from "../../providers/slug-codec";
|
|
45
45
|
import { CODEX_GPT5_IDENTITY_LINE } from "../../adapters/identity";
|
|
46
46
|
import { filterCursorConfiguredModelsByLiveDiscovery } from "../../adapters/cursor/discovery";
|
|
47
47
|
import { fetchCursorUsableModels } from "../../adapters/cursor/live-models";
|
|
@@ -1560,7 +1560,24 @@ export function filterCatalogVisibleModels(
|
|
|
1560
1560
|
const allowByProvider = new Map<string, Set<string>>();
|
|
1561
1561
|
for (const [name, prov] of Object.entries(config.providers)) {
|
|
1562
1562
|
const sel = prov.selectedModels;
|
|
1563
|
-
|
|
1563
|
+
// Keyed the way `sync.ts` keys the same list, so a slash-bearing native id and
|
|
1564
|
+
// the encoded slug the Codex picker displays are one entry rather than two. A
|
|
1565
|
+
// bare `Set(sel)` matched only the native form, so an allowlist written from the
|
|
1566
|
+
// displayed slug — which `ocx models remove` also accepts — hid every model it
|
|
1567
|
+
// was meant to keep.
|
|
1568
|
+
//
|
|
1569
|
+
// The key is deliberately lossy: `p/a/b` and `p/a-b` collapse to one entry, so a
|
|
1570
|
+
// provider publishing both spellings has them selected together. That is a real
|
|
1571
|
+
// limitation, pinned by the tests below and tracked as a follow-up; it is NOT
|
|
1572
|
+
// fixed here. Resolving selections against the current roster instead was tried
|
|
1573
|
+
// and rejected — the roster is an incomplete dictionary (live discovery can omit
|
|
1574
|
+
// a published id), so it produces the same over-grant while additionally
|
|
1575
|
+
// disagreeing with the `slugEquivalenceKey` contract `sync.ts` uses at merge time.
|
|
1576
|
+
// Two catalog stages with different equivalence relations is the exact bug class
|
|
1577
|
+
// this change exists to remove.
|
|
1578
|
+
if (Array.isArray(sel) && sel.length > 0) {
|
|
1579
|
+
allowByProvider.set(name, new Set(sel.map(model => slugEquivalenceKey(routedSlug(name, model)))));
|
|
1580
|
+
}
|
|
1564
1581
|
}
|
|
1565
1582
|
return models.filter(m => {
|
|
1566
1583
|
const nativeAlias = m.provider === COMBO_NAMESPACE && m.nativeAlias === true;
|
|
@@ -1572,7 +1589,7 @@ export function filterCatalogVisibleModels(
|
|
|
1572
1589
|
if (slugEquals(stored, m.provider, m.id)) return false;
|
|
1573
1590
|
}
|
|
1574
1591
|
const allow = allowByProvider.get(m.provider);
|
|
1575
|
-
return !allow || allow.has(m.id);
|
|
1592
|
+
return !allow || allow.has(slugEquivalenceKey(routedSlug(m.provider, m.id)));
|
|
1576
1593
|
});
|
|
1577
1594
|
}
|
|
1578
1595
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"path": "package.json",
|
|
13
|
-
"sha256": "
|
|
13
|
+
"sha256": "8c82bd7116b0573a8cb8fbe60667cdc16acf7db1180937d650c3d5b63e62a65d"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"path": "scripts/model-metadata.source.json",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
"path": "src/adapters/anthropic.ts",
|
|
37
|
-
"sha256": "
|
|
37
|
+
"sha256": "af1369074d4639e8e6863184734837cd6969a6cd5e1c51ceb9f258fcf761a859"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "src/adapters/azure.ts",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
{
|
|
44
44
|
"path": "src/adapters/base.ts",
|
|
45
|
-
"sha256": "
|
|
45
|
+
"sha256": "858067e7562a2a4ac9a52f40a1bf1e4189e99e8695aa610de2ea43eb36446d8a"
|
|
46
46
|
},
|
|
47
47
|
{
|
|
48
48
|
"path": "src/adapters/client-fingerprint.ts",
|
|
@@ -306,7 +306,7 @@
|
|
|
306
306
|
},
|
|
307
307
|
{
|
|
308
308
|
"path": "src/adapters/openai-responses.ts",
|
|
309
|
-
"sha256": "
|
|
309
|
+
"sha256": "422c3895f4ffd3b7f539020e9b535d2305232c597be510a5d14c16d8652b1c5d"
|
|
310
310
|
},
|
|
311
311
|
{
|
|
312
312
|
"path": "src/adapters/registry.ts",
|
|
@@ -746,7 +746,7 @@
|
|
|
746
746
|
},
|
|
747
747
|
{
|
|
748
748
|
"path": "src/codex/catalog/provider-fetch.ts",
|
|
749
|
-
"sha256": "
|
|
749
|
+
"sha256": "8e1fff8e630df65179833156b8affd84643dcb3630218e1cd6d0457a9c1922ef"
|
|
750
750
|
},
|
|
751
751
|
{
|
|
752
752
|
"path": "src/codex/catalog/sync.ts",
|
|
@@ -2278,7 +2278,7 @@
|
|
|
2278
2278
|
},
|
|
2279
2279
|
{
|
|
2280
2280
|
"path": "src/responses/namespace-tool-compat.ts",
|
|
2281
|
-
"sha256": "
|
|
2281
|
+
"sha256": "5e20d17d89ea3e509793f86bcf19654675cac7d4b27208f240e5598db14fae7a"
|
|
2282
2282
|
},
|
|
2283
2283
|
{
|
|
2284
2284
|
"path": "src/responses/parser.ts",
|
|
@@ -2310,7 +2310,7 @@
|
|
|
2310
2310
|
},
|
|
2311
2311
|
{
|
|
2312
2312
|
"path": "src/responses/state.ts",
|
|
2313
|
-
"sha256": "
|
|
2313
|
+
"sha256": "d35e62769ea0667eaf9d1c7d5f8fec6d703bf95a10b9a28db32795867567d3c3"
|
|
2314
2314
|
},
|
|
2315
2315
|
{
|
|
2316
2316
|
"path": "src/responses/thought-signature-replay.ts",
|
|
@@ -2750,7 +2750,7 @@
|
|
|
2750
2750
|
},
|
|
2751
2751
|
{
|
|
2752
2752
|
"path": "src/server/responses/fetch-helpers.ts",
|
|
2753
|
-
"sha256": "
|
|
2753
|
+
"sha256": "314126a9b77354e53ab9888d90a37307e931dc1206e46e74b9d66b6b57bbf158"
|
|
2754
2754
|
},
|
|
2755
2755
|
{
|
|
2756
2756
|
"path": "src/server/responses/input-admission.ts",
|
|
@@ -2782,7 +2782,7 @@
|
|
|
2782
2782
|
},
|
|
2783
2783
|
{
|
|
2784
2784
|
"path": "src/server/responses/ws-upstream.ts",
|
|
2785
|
-
"sha256": "
|
|
2785
|
+
"sha256": "8b4bf9498f67e1521f12618f1db0a21026ec5be36bf0cf3d5bfdf2137827d9d3"
|
|
2786
2786
|
},
|
|
2787
2787
|
{
|
|
2788
2788
|
"path": "src/server/search.ts",
|
|
@@ -4,6 +4,14 @@ import { collectResponsesToolGroups } from "./tool-groups";
|
|
|
4
4
|
export interface RoutedNamespaceToolIdentity {
|
|
5
5
|
namespace: string;
|
|
6
6
|
name: string;
|
|
7
|
+
/**
|
|
8
|
+
* The kind the tool was DECLARED as. Restoration and `tool_choice` matching both
|
|
9
|
+
* need it: a wire name identifies which tool, not which kind of call may carry it,
|
|
10
|
+
* so without this a tool declared `function` could be selected by a `custom`
|
|
11
|
+
* selector and come back as a `custom_tool_call` — the same name/kind mismatch
|
|
12
|
+
* that motivated narrowing the alias map in the first place.
|
|
13
|
+
*/
|
|
14
|
+
kind: "function" | "custom";
|
|
7
15
|
}
|
|
8
16
|
|
|
9
17
|
export type RoutedNamespaceToolAliases = ReadonlyMap<string, RoutedNamespaceToolIdentity>;
|
|
@@ -138,7 +146,10 @@ function buildRewritePlan(groups: readonly unknown[][]): NamespaceRewritePlan {
|
|
|
138
146
|
addSelector(selectors, `${parsed.namespace}.${childName}`, wireName);
|
|
139
147
|
addSelector(selectors, childName, wireName);
|
|
140
148
|
if (parsed.namespace !== BUILTIN_FUNCTIONS_NAMESPACE) {
|
|
141
|
-
|
|
149
|
+
// A child declared `custom` stays custom; everything else lowers to a
|
|
150
|
+
// function, which is how `buildTools` flattens it upstream.
|
|
151
|
+
const kind = child.type === "custom" ? "custom" : "function";
|
|
152
|
+
aliases.set(wireName, { namespace: parsed.namespace, name: childName, kind });
|
|
142
153
|
}
|
|
143
154
|
}
|
|
144
155
|
}
|
|
@@ -206,18 +217,34 @@ function rewriteToolList(
|
|
|
206
217
|
* the failure this layer exists to prevent, and this layer's own response restoration is what put
|
|
207
218
|
* the key on the item.
|
|
208
219
|
*/
|
|
220
|
+
/**
|
|
221
|
+
* A selector's `namespace` is either absent — meaning "unqualified, resolve the bare
|
|
222
|
+
* name" — or a string naming the group. A present-but-non-string value is neither, and
|
|
223
|
+
* a malformed selector must not authorize anything: not through the unqualified
|
|
224
|
+
* fallback, and not by happening to carry an already-flattened wire name, which would
|
|
225
|
+
* otherwise match the alias map exactly and arm it anyway.
|
|
226
|
+
*/
|
|
227
|
+
function hasMalformedNamespace(value: Record<string, unknown>): boolean {
|
|
228
|
+
return "namespace" in value && typeof value.namespace !== "string";
|
|
229
|
+
}
|
|
230
|
+
|
|
209
231
|
function rewriteNamedSelector(
|
|
210
232
|
value: unknown,
|
|
211
233
|
plan: NamespaceRewritePlan,
|
|
212
234
|
bareFallback: boolean,
|
|
213
235
|
): unknown {
|
|
214
236
|
if (!isPlainObject(value) || typeof value.name !== "string") return value;
|
|
215
|
-
|
|
237
|
+
// Malformed: hand it back untouched so no rewrite occurs. Authorization rejects it
|
|
238
|
+
// separately — returning it unchanged is not by itself enough, because the name it
|
|
239
|
+
// carries may already BE a wire name.
|
|
240
|
+
if (hasMalformedNamespace(value)) return value;
|
|
241
|
+
const namespace = value.namespace;
|
|
242
|
+
if (typeof namespace !== "string") {
|
|
216
243
|
if (!bareFallback) return value;
|
|
217
244
|
const wireName = plan.selectors.get(value.name) ?? undefined;
|
|
218
245
|
return wireName === undefined || wireName === value.name ? value : { ...value, name: wireName };
|
|
219
246
|
}
|
|
220
|
-
const { namespace, ...rest } = value;
|
|
247
|
+
const { namespace: _dropped, ...rest } = value;
|
|
221
248
|
const wireName = plan.identities.get(loweredIdentity(namespace, value.name))
|
|
222
249
|
?? loweredWireName(namespace, value.name);
|
|
223
250
|
return { ...rest, name: wireName };
|
|
@@ -239,6 +266,59 @@ function rewriteToolChoice(value: unknown, plan: NamespaceRewritePlan): unknown
|
|
|
239
266
|
return changed ? { ...value, tools } : value;
|
|
240
267
|
}
|
|
241
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Keep response restoration inside the caller's per-turn tool authorization boundary. The
|
|
271
|
+
* upstream sees every flattened declaration even when `tool_choice` narrows the tools it may call,
|
|
272
|
+
* so its output cannot be trusted merely because a wire name appeared in that catalog.
|
|
273
|
+
*/
|
|
274
|
+
function authorizedAliases(
|
|
275
|
+
aliases: Map<string, RoutedNamespaceToolIdentity>,
|
|
276
|
+
toolChoice: unknown,
|
|
277
|
+
): Map<string, RoutedNamespaceToolIdentity> {
|
|
278
|
+
if (toolChoice === undefined || toolChoice === "auto" || toolChoice === "required") return aliases;
|
|
279
|
+
if (toolChoice === "none" || !isPlainObject(toolChoice)) return new Map();
|
|
280
|
+
|
|
281
|
+
// name -> the kind the selector claimed. A selector authorizes a tool only when it
|
|
282
|
+
// names it AND agrees about what kind of tool it is.
|
|
283
|
+
let authorized: Map<string, "function" | "custom">;
|
|
284
|
+
if (
|
|
285
|
+
(toolChoice.type === "function" || toolChoice.type === "custom")
|
|
286
|
+
&& typeof toolChoice.name === "string"
|
|
287
|
+
) {
|
|
288
|
+
// A malformed namespace makes the whole selector untrustworthy, even when its
|
|
289
|
+
// name is already a flattened wire name that would match the alias map exactly.
|
|
290
|
+
if (hasMalformedNamespace(toolChoice)) return new Map();
|
|
291
|
+
authorized = new Map([[toolChoice.name, toolChoice.type]]);
|
|
292
|
+
} else if (toolChoice.type === "allowed_tools" && Array.isArray(toolChoice.tools)) {
|
|
293
|
+
authorized = new Map();
|
|
294
|
+
for (const tool of toolChoice.tools) {
|
|
295
|
+
// Match the top-level branch above: only a function/custom selector can
|
|
296
|
+
// authorize a client namespace call. `allowed_tools` entries are typed
|
|
297
|
+
// `{type: string}` by the schema, so the accepted set is open-ended and
|
|
298
|
+
// an allowlist is the only closure that also covers kinds added later.
|
|
299
|
+
// Without this, `{type: "file_search", name: "<wire-name>"}` keeps the
|
|
300
|
+
// alias, and an upstream `function_call` carrying that name is restored
|
|
301
|
+
// into a namespace call the caller never permitted.
|
|
302
|
+
if (!isPlainObject(tool)) continue;
|
|
303
|
+
if (tool.type !== "function" && tool.type !== "custom") continue;
|
|
304
|
+
if (typeof tool.name !== "string") continue;
|
|
305
|
+
if (hasMalformedNamespace(tool)) continue;
|
|
306
|
+
authorized.set(tool.name, tool.type);
|
|
307
|
+
}
|
|
308
|
+
} else {
|
|
309
|
+
// An explicit selector for another tool kind does not authorize a client namespace call.
|
|
310
|
+
return new Map();
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// The kind must agree too. A wire name says WHICH tool, not what kind of call may
|
|
314
|
+
// carry it, so a `custom` selector naming a tool declared `function` is the same
|
|
315
|
+
// name/kind mismatch as a `file_search` selector naming it — narrower, but the
|
|
316
|
+
// same class, and `allowed_tools[].type` accepts any string so both are reachable.
|
|
317
|
+
return new Map(
|
|
318
|
+
[...aliases].filter(([wireName, identity]) => authorized.get(wireName) === identity.kind),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
242
322
|
function rewriteInputItem(item: unknown, plan: NamespaceRewritePlan, emitted: Set<string>): unknown {
|
|
243
323
|
if (!isPlainObject(item)) return item;
|
|
244
324
|
if (item.type === "additional_tools" && Array.isArray(item.tools)) {
|
|
@@ -292,7 +372,7 @@ export function rewriteRoutedNamespaceToolsForUpstream(body: unknown): {
|
|
|
292
372
|
...(input !== body.input ? { input } : {}),
|
|
293
373
|
...(toolChoice !== body.tool_choice ? { tool_choice: toolChoice } : {}),
|
|
294
374
|
},
|
|
295
|
-
aliases: plan.aliases,
|
|
375
|
+
aliases: authorizedAliases(plan.aliases, toolChoice),
|
|
296
376
|
};
|
|
297
377
|
}
|
|
298
378
|
|
package/src/responses/state.ts
CHANGED
|
@@ -18,6 +18,12 @@ import {
|
|
|
18
18
|
const MAX_STORED_RESPONSES = 1_000;
|
|
19
19
|
const RESPONSE_TTL_MS = 60 * 60 * 1_000;
|
|
20
20
|
const SNAPSHOT_DEBOUNCE_MS = 2_000;
|
|
21
|
+
/** Snapshot size below which the debounce stays at its base value. */
|
|
22
|
+
const SNAPSHOT_DEBOUNCE_SCALE_FROM_BYTES = 1 * 1024 * 1024;
|
|
23
|
+
/** Ceiling for the stretched debounce. Continuation state is only read after a
|
|
24
|
+
* restart, and a graceful shutdown flushes, so the exposure a longer debounce adds
|
|
25
|
+
* is bounded by a hard kill — paid against rewriting the whole snapshot every 2 s. */
|
|
26
|
+
const SNAPSHOT_DEBOUNCE_MAX_MS = 30_000;
|
|
21
27
|
/** In-memory high-water byte cap across all entries. Forced store:false retention (kiro/cursor
|
|
22
28
|
* continuation chains) stores the full expanded input each turn — ~quadratic bytes per chain —
|
|
23
29
|
* so a count cap alone cannot bound memory. Oldest-first eviction applies past this mark. */
|
|
@@ -90,6 +96,43 @@ let oldestResidentId: string | undefined;
|
|
|
90
96
|
let oldestResidentAt: number | null = null;
|
|
91
97
|
let byteCapOverride: number | null = null;
|
|
92
98
|
let stateRevision = 0;
|
|
99
|
+
/** Byte length and digest of the last snapshot actually written, for the
|
|
100
|
+
* identical-payload skip and the size-scaled debounce. The payload itself is not
|
|
101
|
+
* retained: at the 24 MiB bound that would double the snapshot's memory cost. */
|
|
102
|
+
let lastSnapshotBytes = 0;
|
|
103
|
+
let lastSnapshotDigest: string | null = null;
|
|
104
|
+
// The resolved file the digest above describes. Keeping it means a config-dir
|
|
105
|
+
// change or a retargeted symlink is a miss rather than a false "unchanged".
|
|
106
|
+
let lastSnapshotTarget: string | null = null;
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Is the snapshot on disk still byte-for-byte what we last wrote?
|
|
110
|
+
*
|
|
111
|
+
* The cached digest proves what this process wrote, not what is there now. Size is
|
|
112
|
+
* checked first so the common mismatch costs a `stat`, and the content comparison
|
|
113
|
+
* only runs when the size already agrees. Any read failure answers "no" and the
|
|
114
|
+
* caller rewrites — the safe direction.
|
|
115
|
+
*/
|
|
116
|
+
async function snapshotOnDiskMatches(path: string, payload: string, payloadBytes: number): Promise<boolean> {
|
|
117
|
+
try {
|
|
118
|
+
const file = Bun.file(path);
|
|
119
|
+
if (file.size !== payloadBytes) return false;
|
|
120
|
+
if (await file.text() !== payload) return false;
|
|
121
|
+
// Content matching is not the whole invariant. This file holds persisted request
|
|
122
|
+
// and response bodies, and `atomicWriteFileAsync` writes it owner-only; the
|
|
123
|
+
// unconditional rewrite used to restore that on every mutation. Skipping without
|
|
124
|
+
// checking would let a broadened mode persist indefinitely, so treat a widened
|
|
125
|
+
// file as "does not match" and let the caller rewrite it through the hardening
|
|
126
|
+
// path. POSIX only — Windows ACLs are re-applied by that same write path.
|
|
127
|
+
if (process.platform !== "win32") {
|
|
128
|
+
const mode = statSync(path).mode & 0o777;
|
|
129
|
+
if (mode !== 0o600) return false;
|
|
130
|
+
}
|
|
131
|
+
return true;
|
|
132
|
+
} catch {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
93
136
|
const spillCounters = { writes: 0, writeFailures: 0, readFailures: 0 };
|
|
94
137
|
/**
|
|
95
138
|
* Admission-boundary observability (test-visible). directSpills: oversized
|
|
@@ -788,9 +831,38 @@ async function writeBoundedSnapshot(path: string): Promise<SnapshotWriteOutcome>
|
|
|
788
831
|
entries.push(persistEntry);
|
|
789
832
|
}
|
|
790
833
|
entries.reverse();
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
834
|
+
const payload = JSON.stringify({ version: 2, states: entries });
|
|
835
|
+
const payloadBytes = Buffer.byteLength(payload, "utf8");
|
|
836
|
+
const payloadDigest = Bun.hash(payload).toString(36);
|
|
837
|
+
// A mutation does not always change what gets persisted: entries past the
|
|
838
|
+
// per-entry or total byte bound are dropped from the selection, and spill
|
|
839
|
+
// demotion moves bytes out of it. Re-writing a byte-identical 24 MiB file
|
|
840
|
+
// buys nothing, so compare first — but the cached digest describes what THIS
|
|
841
|
+
// process last wrote, which is not the same claim as "that is what is on disk
|
|
842
|
+
// now". A second proxy sharing the home, or anything that rewrites the file
|
|
843
|
+
// in place, leaves the digest describing bytes that are gone. Before every
|
|
844
|
+
// release-of-a-write, the previous behaviour rewrote unconditionally and so
|
|
845
|
+
// repaired that silently; skipping without checking would turn a repaired
|
|
846
|
+
// snapshot into a lost one at the next restart.
|
|
847
|
+
//
|
|
848
|
+
// Verify against the file itself, keyed to the resolved target so a retargeted
|
|
849
|
+
// symlink is also a miss. Reading back a matching-size file costs far less
|
|
850
|
+
// than the atomic replace it avoids, and only happens when the digest already
|
|
851
|
+
// matched — the amplification this fixes is the repeated WRITE, not the read.
|
|
852
|
+
const unchanged = lastSnapshotDigest !== null
|
|
853
|
+
&& payloadDigest === lastSnapshotDigest
|
|
854
|
+
&& payloadBytes === lastSnapshotBytes
|
|
855
|
+
&& lastSnapshotTarget === resolveWriteTarget(path)
|
|
856
|
+
&& existsSync(path)
|
|
857
|
+
&& await snapshotOnDiskMatches(path, payload, payloadBytes);
|
|
858
|
+
if (!unchanged) {
|
|
859
|
+
mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
|
|
860
|
+
try { chmodSync(dirname(path), 0o700); } catch { /* best-effort (e.g. Windows) */ }
|
|
861
|
+
await atomicWriteFileAsync(path, payload);
|
|
862
|
+
lastSnapshotDigest = payloadDigest;
|
|
863
|
+
lastSnapshotBytes = payloadBytes;
|
|
864
|
+
lastSnapshotTarget = resolveWriteTarget(path);
|
|
865
|
+
}
|
|
794
866
|
persistAttemptHookForTests?.();
|
|
795
867
|
if (revision === stateRevision) return "stable";
|
|
796
868
|
}
|
|
@@ -809,11 +881,26 @@ function drainPendingSpillUnlinks(): void {
|
|
|
809
881
|
}
|
|
810
882
|
}
|
|
811
883
|
|
|
884
|
+
/**
|
|
885
|
+
* Debounce scaled by the size of the last snapshot written.
|
|
886
|
+
*
|
|
887
|
+
* The whole snapshot is re-serialized and atomically replaced on every flush, so at
|
|
888
|
+
* the 24 MiB bound a fixed 2 s debounce is up to ~12 MB/s of write amplification for
|
|
889
|
+
* state nothing reads until the next start (#2460). Small snapshots keep the base
|
|
890
|
+
* cadence; the stretch is linear in size and clamped, so the write rate is roughly
|
|
891
|
+
* flat instead of growing with the file.
|
|
892
|
+
*/
|
|
893
|
+
function snapshotDebounceMs(): number {
|
|
894
|
+
if (lastSnapshotBytes <= SNAPSHOT_DEBOUNCE_SCALE_FROM_BYTES) return SNAPSHOT_DEBOUNCE_MS;
|
|
895
|
+
const scaled = Math.round(SNAPSHOT_DEBOUNCE_MS * (lastSnapshotBytes / SNAPSHOT_DEBOUNCE_SCALE_FROM_BYTES));
|
|
896
|
+
return Math.min(scaled, SNAPSHOT_DEBOUNCE_MAX_MS);
|
|
897
|
+
}
|
|
898
|
+
|
|
812
899
|
function schedulePersistAt(path: string, replace = false): void {
|
|
813
900
|
if (persistTimer && !replace) return;
|
|
814
901
|
if (persistTimer) clearTimeout(persistTimer);
|
|
815
902
|
pendingPersistPath = path;
|
|
816
|
-
persistTimer = setTimeout(() => { void persistNow(path); },
|
|
903
|
+
persistTimer = setTimeout(() => { void persistNow(path); }, snapshotDebounceMs());
|
|
817
904
|
(persistTimer as { unref?: () => void }).unref?.();
|
|
818
905
|
}
|
|
819
906
|
|
|
@@ -1418,6 +1505,9 @@ export function clearResponseStateMemoryForTests(): void {
|
|
|
1418
1505
|
replayScopeMismatchDrops = 0;
|
|
1419
1506
|
replayOverlapSkips = 0;
|
|
1420
1507
|
persistAttemptHookForTests = null;
|
|
1508
|
+
lastSnapshotBytes = 0;
|
|
1509
|
+
lastSnapshotDigest = null;
|
|
1510
|
+
lastSnapshotTarget = null;
|
|
1421
1511
|
loaded = false;
|
|
1422
1512
|
}
|
|
1423
1513
|
|
|
@@ -64,14 +64,26 @@ export function providerFetch(
|
|
|
64
64
|
options: ProviderFetchOptions = {},
|
|
65
65
|
): ProviderFetch {
|
|
66
66
|
const base = (provider as OcxProviderConfig & { fetch?: typeof globalThis.fetch }).fetch ?? globalThis.fetch;
|
|
67
|
+
const preconnect = (...args: Parameters<typeof globalThis.fetch.preconnect>): void => {
|
|
68
|
+
base.preconnect?.(...args);
|
|
69
|
+
};
|
|
70
|
+
const httpFetch = Object.assign(
|
|
71
|
+
(input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) =>
|
|
72
|
+
base(input, withUpstreamHttpVersion(input, init, provider)),
|
|
73
|
+
{ preconnect },
|
|
74
|
+
) as typeof globalThis.fetch;
|
|
67
75
|
// ChatGPT Codex backend: streaming turns ride the responses_websockets
|
|
68
76
|
// transport (measured ~3s faster TTFT than the SSE POST queue); everything
|
|
69
77
|
// else keeps the provider's HTTP fetch. See ws-upstream.ts for the details.
|
|
70
78
|
const unpaced = async (input: Parameters<typeof globalThis.fetch>[0], init?: RequestInit) => {
|
|
71
79
|
if (typeof input === "string" && init && shouldUseCodexWsUpstream(input, init, runtime)) {
|
|
72
|
-
|
|
80
|
+
// The fallback has to be the same HTTP fetch the non-WS branch would have
|
|
81
|
+
// used, protocol pin included: a WS turn that falls back is serving the
|
|
82
|
+
// request over HTTP, and dropping the provider's `upstreamHttpVersion`
|
|
83
|
+
// there would silently negotiate a transport the operator ruled out.
|
|
84
|
+
return codexWsUpstreamFetch(input, init, httpFetch, runtime);
|
|
73
85
|
}
|
|
74
|
-
return
|
|
86
|
+
return httpFetch(input, init);
|
|
75
87
|
};
|
|
76
88
|
let pacingSlotAcquired = options.pacingSlotAcquired === true;
|
|
77
89
|
const waitForPacing = (signal?: AbortSignal) => {
|
|
@@ -87,9 +99,6 @@ export function providerFetch(
|
|
|
87
99
|
await waitForPacing(init?.signal ?? undefined);
|
|
88
100
|
return unpaced(input, init);
|
|
89
101
|
};
|
|
90
|
-
const preconnect = (...args: Parameters<typeof globalThis.fetch.preconnect>): void => {
|
|
91
|
-
base.preconnect?.(...args);
|
|
92
|
-
};
|
|
93
102
|
return Object.assign(wrapped, {
|
|
94
103
|
preconnect,
|
|
95
104
|
waitForPacing,
|
|
@@ -28,6 +28,25 @@ const UPGRADE_DEADLINE_MS = 10_000;
|
|
|
28
28
|
export const MAX_CODEX_WS_FRAME_BYTES = MAX_CLIENT_SSE_FRAME_BYTES;
|
|
29
29
|
export const MAX_CODEX_WS_QUEUE_BYTES = 8 * 1024 * 1024;
|
|
30
30
|
export const MIN_BOUNDED_CODEX_WS_BUN_VERSION = "1.4.0";
|
|
31
|
+
// The backend drops any inbound message of 16 MiB or more: it closes the socket
|
|
32
|
+
// (1009) without a Responses terminal event, which reaches clients as a bare
|
|
33
|
+
// 502 upstream_server_error. Measured against the live endpoint 2026-08-23:
|
|
34
|
+
// 16,777,000 B completed, 16,777,300 B closed in ~1s, every time. The same
|
|
35
|
+
// request body succeeds over HTTP SSE, so the ceiling belongs to this transport
|
|
36
|
+
// alone (see #2426). A full-replay thread reaches it with ~11 pasted
|
|
37
|
+
// screenshots, and then never recovers, because each retry resends the frame.
|
|
38
|
+
export const MAX_CODEX_WS_CREATE_FRAME_BYTES = 16 * 1024 * 1024;
|
|
39
|
+
// Bun frames the payload it is handed, so the send-side budget is the JSON text
|
|
40
|
+
// itself, and nothing is appended between the check and the send. The margin is
|
|
41
|
+
// a conservative cushion, not a computed requirement: it covers RFC 6455 frame
|
|
42
|
+
// overhead in case the backend counts it (14 bytes at this payload size — an
|
|
43
|
+
// 8-byte extended length plus a 4-byte client mask, leaving ~65.5 KiB spare),
|
|
44
|
+
// and it leaves room for a future caller that appends to the frame.
|
|
45
|
+
const CODEX_WS_CREATE_FRAME_MARGIN_BYTES = 64 * 1024;
|
|
46
|
+
export const CODEX_WS_CREATE_FRAME_LIMIT_BYTES =
|
|
47
|
+
MAX_CODEX_WS_CREATE_FRAME_BYTES - CODEX_WS_CREATE_FRAME_MARGIN_BYTES;
|
|
48
|
+
/** Close code the backend uses for an oversized message (RFC 6455 "message too big"). */
|
|
49
|
+
const WS_CLOSE_MESSAGE_TOO_BIG = 1009;
|
|
31
50
|
|
|
32
51
|
export type BunRuntimeIdentity = {
|
|
33
52
|
version: string;
|
|
@@ -102,6 +121,52 @@ export function shouldUseCodexWsUpstream(
|
|
|
102
121
|
}
|
|
103
122
|
}
|
|
104
123
|
|
|
124
|
+
const CLOSED_BEFORE_TERMINAL = "codex websocket closed before a Responses terminal event";
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The close code is the only thing that separates "the backend refused this
|
|
128
|
+
* payload" from "the network dropped", and both used to reach the caller as the
|
|
129
|
+
* same bare 502. Naming the oversized case here puts that distinction in the
|
|
130
|
+
* message the client receives.
|
|
131
|
+
*
|
|
132
|
+
* It does NOT reach the request log as a typed code. The eager relay turns any
|
|
133
|
+
* stream error into a generic `upstream_reset` synthetic terminal
|
|
134
|
+
* (`relay.ts`, `relay-eager.ts`) without feeding that frame back through the
|
|
135
|
+
* inspector, so `/api/logs` keeps neither this message nor a specific code —
|
|
136
|
+
* only `streamAborted`. Machine-readable typing would mean changing the error
|
|
137
|
+
* taxonomy, which is deliberately out of scope for this transport fix.
|
|
138
|
+
*/
|
|
139
|
+
function closedBeforeTerminalMessage(event: unknown): string {
|
|
140
|
+
const detail = event as { code?: unknown; reason?: unknown } | null | undefined;
|
|
141
|
+
const code = typeof detail?.code === "number" ? detail.code : null;
|
|
142
|
+
const reason = typeof detail?.reason === "string" ? detail.reason.trim() : "";
|
|
143
|
+
if (code === null) return CLOSED_BEFORE_TERMINAL;
|
|
144
|
+
const suffix = reason ? ` ${code} ${reason}` : ` ${code}`;
|
|
145
|
+
if (code === WS_CLOSE_MESSAGE_TOO_BIG) {
|
|
146
|
+
return `codex websocket rejected the request frame as too large (close${suffix});`
|
|
147
|
+
+ ` requests at or above ${MAX_CODEX_WS_CREATE_FRAME_BYTES} bytes must use the HTTP SSE transport`;
|
|
148
|
+
}
|
|
149
|
+
return `${CLOSED_BEFORE_TERMINAL} (close${suffix})`;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* True when the `response.create` frame is at or above the backend's inbound
|
|
154
|
+
* message ceiling, so this turn must take the HTTP SSE path instead.
|
|
155
|
+
*
|
|
156
|
+
* Sizing a 16 MiB string should not cost a 16 MiB copy. UTF-8 never encodes
|
|
157
|
+
* below one byte per UTF-16 code unit and never above three, so both tails are
|
|
158
|
+
* settled from the string length alone; only the narrow band between them pays
|
|
159
|
+
* for a real byte count, and `Buffer.byteLength` measures without allocating.
|
|
160
|
+
*/
|
|
161
|
+
export function codexWsCreateFrameExceedsLimit(
|
|
162
|
+
frameText: string,
|
|
163
|
+
limitBytes: number = CODEX_WS_CREATE_FRAME_LIMIT_BYTES,
|
|
164
|
+
): boolean {
|
|
165
|
+
if (frameText.length >= limitBytes) return true;
|
|
166
|
+
if (frameText.length * 3 < limitBytes) return false;
|
|
167
|
+
return Buffer.byteLength(frameText, "utf8") >= limitBytes;
|
|
168
|
+
}
|
|
169
|
+
|
|
105
170
|
export function codexWsUpstreamFetch(
|
|
106
171
|
url: string,
|
|
107
172
|
init: RequestInit,
|
|
@@ -127,6 +192,14 @@ export function codexWsUpstreamFetch(
|
|
|
127
192
|
return sseFallback(url, init);
|
|
128
193
|
}
|
|
129
194
|
|
|
195
|
+
// Decide before dialing. Once the socket is open the caller already holds a
|
|
196
|
+
// streaming Response, so the oversized close can only be surfaced as a stream
|
|
197
|
+
// error — and a resend at that point could double-generate. Measuring the
|
|
198
|
+
// frame we are about to send keeps the whole failure mode unreachable.
|
|
199
|
+
if (codexWsCreateFrameExceedsLimit(frameText)) {
|
|
200
|
+
return sseFallback(url, init);
|
|
201
|
+
}
|
|
202
|
+
|
|
130
203
|
const headers: Record<string, string> = {};
|
|
131
204
|
new Headers(init.headers ?? {}).forEach((value, key) => {
|
|
132
205
|
// HTTP-body framing headers do not apply to a WS handshake.
|
|
@@ -279,7 +352,7 @@ export function codexWsUpstreamFetch(
|
|
|
279
352
|
}
|
|
280
353
|
});
|
|
281
354
|
|
|
282
|
-
ws.addEventListener("close", () => {
|
|
355
|
+
ws.addEventListener("close", (event: unknown) => {
|
|
283
356
|
signal?.removeEventListener("abort", onAbort);
|
|
284
357
|
if (!opened) {
|
|
285
358
|
if (settledPreOpen) return;
|
|
@@ -297,7 +370,7 @@ export function codexWsUpstreamFetch(
|
|
|
297
370
|
// here would reach clients with no response.completed/failed at all —
|
|
298
371
|
// relaySseWithFailedTail() only synthesizes a failed terminal when the
|
|
299
372
|
// body read THROWS. Error the stream like a reset TCP socket.
|
|
300
|
-
try { controller.error(new Error(
|
|
373
|
+
try { controller.error(new Error(closedBeforeTerminalMessage(event))); } catch { /* stream already done */ }
|
|
301
374
|
}
|
|
302
375
|
});
|
|
303
376
|
|