@openchambery/web 1.18.4-beta.15 → 1.18.4-beta.16

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.
Files changed (44) hide show
  1. package/dist/assets/{AssistantView-8uU58vy0.js → AssistantView-2oaKAdLl.js} +1 -1
  2. package/dist/assets/{ChatContainer-CimpaKcn.js → ChatContainer-C3okCjTT.js} +4 -4
  3. package/dist/assets/{DiagramView-euzFXO_O.js → DiagramView-BdWjzN9Y.js} +1 -1
  4. package/dist/assets/{MarkdownRendererImpl-Dit2Ib5h.js → MarkdownRendererImpl-DXzGhggv.js} +1 -1
  5. package/dist/assets/{MobileDetailNavigation-BUj1ICFS.js → MobileDetailNavigation-BxzzbVuo.js} +1 -1
  6. package/dist/assets/{MobileShareBridge-DFHvcf7Q.js → MobileShareBridge-CO5oEylO.js} +1 -1
  7. package/dist/assets/{MobileSurface-CDowKkJL.js → MobileSurface-DS_tuMUX.js} +1 -1
  8. package/dist/assets/{MultiRunWindow-CvUMhyyj.js → MultiRunWindow-D_z9Yrj0.js} +1 -1
  9. package/dist/assets/{SettingsView-By3I3xXH.js → SettingsView-Dq4d1azT.js} +1 -1
  10. package/dist/assets/{SettingsWindow-5n2DvzeP.js → SettingsWindow-B-2mGlsr.js} +1 -1
  11. package/dist/assets/{TerminalView-BmycLxLS.js → TerminalView-BGg8vpYk.js} +1 -1
  12. package/dist/assets/{ToolOutputDialog-BdhiH4i4.js → ToolOutputDialog-TUgfUyPX.js} +1 -1
  13. package/dist/assets/{appThemeRegistry-NoIEZNtX.js → appThemeRegistry-DYl9pc39.js} +2 -2
  14. package/dist/assets/{context-menu-BOlxzatH.js → context-menu-CHKr-Ai0.js} +1 -1
  15. package/dist/assets/{gitApi-q_WNtocg.js → gitApi-CBvO-0tn.js} +1 -1
  16. package/dist/assets/{insertionBoundaries-tokUZ60O.js → insertionBoundaries-DOABfwfW.js} +1 -1
  17. package/dist/assets/{main-D08xX-l9.js → main-CfHT5-XW.js} +2 -2
  18. package/dist/assets/{main-B5n5utaj.js → main-DmE2qI1o.js} +4 -4
  19. package/dist/assets/{miniChat-S0KGzmRO.js → miniChat-2PBRWMPo.js} +2 -2
  20. package/dist/assets/{mobile-BBGkZDcd.js → mobile-BllXjQxK.js} +2 -2
  21. package/dist/assets/{multirun-CWuU0fcO.js → multirun-CFX1tCht.js} +1 -1
  22. package/dist/assets/{projectMeta-BKC7h4Rl.js → projectMeta-BqjXxia6.js} +1 -1
  23. package/dist/assets/{radio-BNOD9XTZ.js → radio-DpGoPQGD.js} +1 -1
  24. package/dist/assets/{renderElectronMiniChatApp-CNL8yc53.js → renderElectronMiniChatApp-DtSye_u8.js} +2 -2
  25. package/dist/assets/{renderMobileApp-DabtxHdO.js → renderMobileApp-BDpsb0XZ.js} +4 -4
  26. package/dist/assets/{runtimeConfig-Cfrfl4hH.js → runtimeConfig-qlXnVd3m.js} +1 -1
  27. package/dist/assets/{runtimeEndpointReset-C1vjUBL_.js → runtimeEndpointReset-CBslSisj.js} +1 -1
  28. package/dist/assets/{useAppFontEffects-CkLk4g06.js → useAppFontEffects-D6a67KZ8.js} +2 -2
  29. package/dist/assets/{useDesktopWindowControlsLayout-BSeMY94L.js → useDesktopWindowControlsLayout-B-P1qfXu.js} +1 -1
  30. package/dist/assets/{useEffectiveDirectory-CA1iNlkc.js → useEffectiveDirectory-DLsYww1j.js} +1 -1
  31. package/dist/assets/useMobileNavigationStore-wm9JzfV_.js +475 -0
  32. package/dist/assets/{useSessionAutoCleanup-LLUYctRd.js → useSessionAutoCleanup-IpHMdVbd.js} +1 -1
  33. package/dist/assets/{useWorkerHighlightedLines-dTnogsPN.js → useWorkerHighlightedLines-B2PxEV54.js} +1 -1
  34. package/dist/index.html +2 -2
  35. package/dist/mini-chat.html +2 -2
  36. package/dist/mobile.html +2 -2
  37. package/package.json +1 -1
  38. package/server/lib/notifications/DOCUMENTATION.md +2 -1
  39. package/server/lib/notifications/emitter-runtime.js +78 -1
  40. package/server/lib/notifications/emitter-runtime.test.js +94 -1
  41. package/server/lib/scheduled-tasks/DOCUMENTATION.md +4 -1
  42. package/server/lib/scheduled-tasks/routes.js +51 -8
  43. package/server/sse-routes.test.js +64 -1
  44. package/dist/assets/useMobileNavigationStore-DyYYlEY1.js +0 -475
@@ -1 +1 @@
1
- import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{j as t,t as n}from"./useUIStore-DzwCfRqr.js";import{Kt as r,kn as i,qt as a,u as o}from"./persistence-6sclr7B6.js";import{h as s}from"./desktopHosts-Txp4xOVQ.js";import{i as c,n as l,r as u}from"./desktopRelayRestore-C_FSEHKM.js";import{nt as d,rt as f}from"./vendor-base-ui-CnHfUmDN.js";import{Nt as p}from"./platform-CbeLpKPk.js";import{n as m}from"./vendor-react-DLPElpoQ.js";import{n as h}from"./vendor-tanstack-query-core-BWz0ose6.js";import{i as g,r as _}from"./vendor-tanstack-react-query-D7pys_c9.js";import{n as v,t as y}from"./clipboard-DWuULPzo.js";import{i as b,t as x}from"./store-DQY8Fkb0.js";import{_r as S,br as ee,ca as te,cr as ne,l as re,mr as ie}from"./useMobileNavigationStore-DyYYlEY1.js";import{t as C}from"./utils-B1EK5zKa.js";import{n as w}from"./Icon-DpjYnXxn.js";import{t as ae}from"./button-C7OXr4ae.js";import{i as oe,n as se,r as ce,t as le}from"./vendor-simplewebauthn-browser-Dwhcdg_5.js";import{n as ue,r as de}from"./radio-BNOD9XTZ.js";var T=m(),E=[`desktopHostSwitch`],D=class extends Error{result;host;constructor(e,t){super(e.reason),this.name=`DesktopHostSwitchError`,this.result=e,this.host=t}},fe=(e,t)=>x(b.getState().dictionary,e,t),pe=async e=>{let{host:n}=e;if(n.id===`local`){let r=(e.localApiOrigin||``).trim();if(!r)throw new D({ok:!1,status:{status:`unreachable`,latencyMs:0},reason:`unreachable`},n);return t({apiBaseUrl:r,clientToken:e.localClientToken||null,runtimeKey:u(n)}),{ok:!0,via:`direct`,status:{status:`ok`,latencyMs:0}}}let r=await c(n,{cachedProbe:e.cachedProbe});if(!r.ok)throw new D(r,n);return r},O=null,me=()=>O||(O=new h(o,{mutationKey:E,mutationFn:pe,onError:(e,t)=>{e instanceof D&&e.result.reason!==`unsupported`&&ee.error(fe(`desktopHostSwitcher.toast.instanceUnreachable`,{host:s(t.host.label)}))}}),O.subscribe(()=>void 0),O),he=async e=>{if(l(e.host))return{ok:!0,via:`direct`,status:e.cachedProbe?.status===`ok`?e.cachedProbe:{status:`ok`,latencyMs:0}};if(o.isMutating({mutationKey:E})>0)return{ok:!1,status:{status:`unreachable`,latencyMs:0},reason:`unsupported`};try{return await me().mutate(e)}catch(e){if(e instanceof D)return e.result;throw e}},ge=()=>{let e=(0,T.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={mutationKey:E},e[0]=t):t=e[0],_(t)>0},_e=()=>{let e=(0,T.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={filters:{mutationKey:E,status:`pending`},select:ve},e[0]=t):t=e[0],g(t)[0]?.host.id??null};function ve(e){return e.state.variables}var k=e=>typeof e==`object`&&!!e,A=(e,t)=>{let n=e[t];return typeof n==`string`?n:null},j=(e,t)=>{let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:null},M=(e,t)=>{let n=e[t];return typeof n==`boolean`?n:null},N=e=>Array.isArray(e)?e.filter(e=>typeof e==`string`):[],P=()=>r()?(e,t)=>a(e,t):null,F=e=>{if(!k(e))return;let t=M(e,`enabled`)??!1,n=A(e,`store`)?.toLowerCase()===`settings`?`settings`:`never`,r=A(e,`value`);return{enabled:t,store:n,...r?{value:r}:{}}},ye=e=>e===`remote`||e===`dynamic`?e:`local`,be=e=>{if(!k(e))return null;let t=A(e,`id`);if(!t)return null;let n=M(e,`enabled`)??!0,r=ye(A(e,`type`)),i=A(e,`localHost`)||A(e,`local_host`)||void 0,a=j(e,`localPort`)??j(e,`local_port`)??void 0,o=A(e,`remoteHost`)||A(e,`remote_host`)||void 0,s=j(e,`remotePort`)??j(e,`remote_port`)??void 0;return{id:t,enabled:n,type:r,...i?{localHost:i}:{},...typeof a==`number`?{localPort:a}:{},...o?{remoteHost:o}:{},...typeof s==`number`?{remotePort:s}:{}}},xe=e=>{if(!k(e))return null;let t=A(e,`id`),n=A(e,`sshCommand`)||A(e,`ssh_command`);if(!t||!n)return null;let r=A(e,`nickname`),i=e.sshParsed,a=k(i)?{destination:A(i,`destination`)||``,args:N(i.args)}:void 0,o=k(e.remoteOpenchamber)?e.remoteOpenchamber:k(e.remote_openchamber)?e.remote_openchamber:{},s=k(e.localForward)?e.localForward:k(e.local_forward)?e.local_forward:{},c=k(e.auth)?e.auth:{},l=A(o,`mode`)?.toLowerCase()===`external`?`external`:`managed`,u=A(o,`installMethod`)||A(o,`install_method`),d=u===`npm`||u===`download_release`||u===`upload_bundle`?u:`bun`,f=A(s,`bindHost`)||A(s,`bind_host`)||`127.0.0.1`,p=f===`localhost`||f===`0.0.0.0`?f:`127.0.0.1`,m=(Array.isArray(e.portForwards)?e.portForwards:Array.isArray(e.port_forwards)?e.port_forwards:[]).map(e=>be(e)).filter(e=>!!e),h=j(o,`preferredPort`)??j(o,`preferred_port`),g=j(s,`preferredLocalPort`)??j(s,`preferred_local_port`),_=F(c.sshPassword||c.ssh_password),v=F(c.openchamberPassword||c.openchamber_password);return{id:t,...r?{nickname:r}:{},sshCommand:n,...a&&a.destination?{sshParsed:a}:{},connectionTimeoutSec:j(e,`connectionTimeoutSec`)??j(e,`connection_timeout_sec`)??60,remoteOpenchamber:{mode:l,keepRunning:M(o,`keepRunning`)??M(o,`keep_running`)??!0,relayHost:M(o,`relayHost`)??M(o,`relay_host`)??!0,...h?{preferredPort:h}:{},installMethod:d,uploadBundleOverSsh:M(o,`uploadBundleOverSsh`)??M(o,`upload_bundle_over_ssh`)??!1},localForward:{...g?{preferredLocalPort:g}:{},bindHost:p},auth:{..._?{sshPassword:_}:{},...v?{openchamberPassword:v}:{}},portForwards:m}},Se=e=>{switch(e){case`config_resolved`:case`auth_check`:case`master_connecting`:case`remote_probe`:case`installing`:case`updating`:case`server_detecting`:case`server_starting`:case`forwarding`:case`ready`:case`degraded`:case`error`:return e;default:return`idle`}},I=e=>{if(!k(e))return null;let t=A(e,`id`);return t?{id:t,phase:Se(A(e,`phase`)),...A(e,`detail`)?{detail:A(e,`detail`)||void 0}:{},...A(e,`localUrl`)||A(e,`local_url`)?{localUrl:A(e,`localUrl`)||A(e,`local_url`)||void 0}:{},...typeof(j(e,`localPort`)??j(e,`local_port`))==`number`?{localPort:j(e,`localPort`)??j(e,`local_port`)??void 0}:{},...typeof(j(e,`remotePort`)??j(e,`remote_port`))==`number`?{remotePort:j(e,`remotePort`)??j(e,`remote_port`)??void 0}:{},startedByUs:M(e,`startedByUs`)??M(e,`started_by_us`)??!1,retryAttempt:j(e,`retryAttempt`)??j(e,`retry_attempt`)??0,requiresUserAction:M(e,`requiresUserAction`)??M(e,`requires_user_action`)??!1,...A(e,`errorCode`)||A(e,`error_code`)?{errorCode:A(e,`errorCode`)||A(e,`error_code`)||void 0}:{},updatedAtMs:j(e,`updatedAtMs`)??j(e,`updated_at_ms`)??Date.now()}:null},Ce=e=>{if(!k(e))return null;let t=A(e,`host`),n=A(e,`source`),r=A(e,`sshCommand`)||A(e,`ssh_command`);return!t||!n||!r?null:{host:t,source:n,sshCommand:r,pattern:M(e,`pattern`)??!1}},we=(e,t)=>({id:e,sshCommand:t,connectionTimeoutSec:60,remoteOpenchamber:{mode:`managed`,keepRunning:!0,relayHost:!0,installMethod:`bun`,uploadBundleOverSsh:!1},localForward:{bindHost:`127.0.0.1`},auth:{},portForwards:[]}),Te=async()=>{let e=P();if(!e)return{instances:[]};let t=await e(`desktop_ssh_instances_get`);return k(t)?{instances:(Array.isArray(t.instances)?t.instances:Array.isArray(t.desktopSshInstances)?t.desktopSshInstances:[]).map(e=>xe(e)).filter(e=>!!e)}:{instances:[]}},Ee=async e=>{let t=P();t&&await t(`desktop_ssh_instances_set`,{config:{instances:e.instances}})},De=async()=>{let e=P();if(!e)return[];let t=await e(`desktop_ssh_import_hosts`);return Array.isArray(t)?t.map(e=>Ce(e)).filter(e=>!!e):[]},Oe=async e=>{let t=P();t&&await t(`desktop_ssh_connect`,{id:e})},ke=async e=>{let t=P();t&&await t(`desktop_ssh_disconnect`,{id:e})},Ae=async e=>{let t=P();if(!t)return[];let n=await t(`desktop_ssh_status`,{...e?{id:e}:{}});return Array.isArray(n)?n.map(e=>I(e)).filter(e=>!!e):[]},je=async(e,t)=>{let n=P();if(!n)return[];let r=await n(`desktop_ssh_logs`,{id:e,...typeof t==`number`?{limit:t}:{}});return Array.isArray(r)?r.filter(e=>typeof e==`string`):[]},Me=async e=>{let t=P();t&&await t(`desktop_ssh_logs_clear`,{id:e})},Ne=(e,t)=>{let n=Math.max(0,Math.trunc(Number(e.fileGroups)||0)),r=Math.max(0,Math.trunc(Number(e.singleFiles)||0)),i=Math.max(0,Math.trunc(Number(e.directories)||0));return{fileGroups:Array.from({length:n},()=>!0),singleFiles:Array.from({length:r},()=>!0),directories:Array.from({length:i},()=>!0),agentsRoot:!0,authFile:t?.includeAuthFile===!0}},Pe=e=>{if(!k(e))return null;let t=A(e,`path`),n=j(e,`bytes`);return!t||n===null?null:{path:t,bytes:n}},Fe=e=>{if(!k(e))return null;let t=A(e,`path`),n=j(e,`fileCount`)??j(e,`file_count`),r=j(e,`bytes`);return!t||n===null||r===null?null:{path:t,fileCount:n,bytes:r}},Ie=e=>{if(e==null||!k(e))return null;let t=j(e,`fileCount`)??j(e,`file_count`),n=j(e,`bytes`);return t===null||n===null?null:{fileCount:t,bytes:n}},L=e=>{if(e==null||!k(e))return null;let t=j(e,`bytes`);return t===null?null:{bytes:t}},R=e=>{if(!k(e))return null;let t=Array.isArray(e.files)?e.files:null,n=Array.isArray(e.directories)?e.directories:null,r=N(e.deletes),i=j(e,`totalBytes`)??j(e,`total_bytes`);if(!t||!n||i===null||!(`agentsRoot`in e)&&!(`agents_root`in e))return null;let a=t.map(e=>Pe(e)).filter(e=>!!e),o=n.map(e=>Fe(e)).filter(e=>!!e);if(a.length!==t.length||o.length!==n.length)return null;let s=e.agentsRoot??e.agents_root,c=s==null?null:Ie(s);if(s!=null&&c===null)return null;let l=e.authFile??e.auth_file,u=l==null?null:L(l),d=e.direction===`pull`||e.direction===`push`?e.direction:void 0,f=e.selections,p=k(f)?{fileGroups:Array.isArray(f.fileGroups)?f.fileGroups.map(e=>e!==!1):[],singleFiles:Array.isArray(f.singleFiles)?f.singleFiles.map(e=>e!==!1):[],directories:Array.isArray(f.directories)?f.directories.map(e=>e!==!1):[],agentsRoot:f.agentsRoot!==!1,authFile:f.authFile===!0}:void 0,m=z(e.selectionShape??e.selection_shape);return{files:a,directories:o,agentsRoot:c,authFile:u,deletes:r,totalBytes:i,...d?{direction:d}:{},...p?{selections:p}:{},...m?{selectionShape:m}:{}}},z=e=>{if(!k(e))return null;let t=j(e,`fileGroups`)??j(e,`file_groups`),n=j(e,`singleFiles`)??j(e,`single_files`),r=j(e,`directories`);return t===null||n===null||r===null||t<0||n<0||r<0?null:{fileGroups:t,singleFiles:n,directories:r}},Le=e=>{if(!k(e))return null;let t=R(e.plan);if(!t)return null;let n=z(e.selectionShape??e.selection_shape)??t.selectionShape??null;return{plan:t,remoteExisting:N(e.remoteExisting??e.remote_existing),remoteAgentsRootExists:M(e,`remoteAgentsRootExists`)??M(e,`remote_agents_root_exists`)??!1,remoteAuthFileExists:M(e,`remoteAuthFileExists`)??M(e,`remote_auth_file_exists`)??!1,...typeof e.credentialAuthorized==`boolean`?{credentialAuthorized:e.credentialAuthorized}:{},...n?{selectionShape:n}:{}}},Re=e=>{if(!k(e)||M(e,`ok`)!==!0)return null;let t=j(e,`files`),n=j(e,`directories`),r=j(e,`deletes`),i=j(e,`totalBytes`)??j(e,`total_bytes`);if(t===null||n===null||r===null||i===null||!(`agentsRoot`in e)&&!(`agents_root`in e))return null;let a=e.agentsRoot??e.agents_root,o=null;if(a!=null){if(!k(a))return null;let e=j(a,`fileCount`)??j(a,`file_count`);if(e===null)return null;o={fileCount:e}}let s=e.authFile??e.auth_file,c=s==null?null:L(s);return{ok:!0,files:t,directories:n,deletes:r,totalBytes:i,agentsRoot:o,authFile:c}},ze=async(e={})=>{let t=P();if(!t)return console.error(`[desktopSsh] config sync local scan skipped: desktop IPC bridge is unavailable in this window`),null;let n=await t(`desktop_ssh_sync_opencode_config`,{stage:`local`,...e.direction?{direction:e.direction}:{},...e.selections?{selections:e.selections}:{}});if(!k(n))return console.error(`[desktopSsh] config sync local scan returned a non-object payload`,n),null;let r=R(n.plan);if(!r)return console.error(`[desktopSsh] config sync local scan plan payload was not recognized`,n),null;let i=z(n.selectionShape??n.selection_shape)??r.selectionShape??null;return i?{...r,selectionShape:i}:r},Be=async(e,t={})=>{let n=P();if(!n)return console.error(`[desktopSsh] config sync preview skipped: desktop IPC bridge is unavailable in this window`),null;let r=await n(`desktop_ssh_sync_opencode_config`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{},...t.direction?{direction:t.direction}:{},...t.selections?{selections:t.selections}:{}}),i=Le(r);return i||console.error(`[desktopSsh] config sync preview payload was not recognized`,r),i},Ve=async(e,t={})=>{let n=P();if(!n)return console.error(`[desktopSsh] config sync apply skipped: desktop IPC bridge is unavailable in this window`),null;let r=await n(`desktop_ssh_sync_opencode_config`,{id:e,apply:!0,...t.targetKind?{targetKind:t.targetKind}:{},...t.direction?{direction:t.direction}:{},...t.selections?{selections:t.selections}:{}}),i=Re(r);return i||console.error(`[desktopSsh] config sync apply payload was not recognized`,r),i},He=async(e,t={})=>{let n=P();if(!n)return[];let r=await n(`desktop_ssh_sync_runs_list`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}});return Array.isArray(r)?r.filter(e=>k(e)&&typeof e.syncRunId==`string`&&typeof e.targetId==`string`):[]},B=e=>{if(!k(e))return null;let t=typeof e.targetId==`string`?e.targetId.trim():``;if(!t)return null;let n=e.authorized===!0,r=typeof e.grantedAt==`string`&&e.grantedAt.trim()?e.grantedAt.trim():void 0,i=typeof e.channel==`string`&&e.channel.trim()?e.channel.trim():void 0;return{targetId:t,authorized:n,...r?{grantedAt:r}:{},...i?{channel:i}:{}}},Ue=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_get`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},We=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_grant`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},Ge=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_revoke`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},Ke=async e=>{if(!r())return async()=>{};let t=window.__OPENCHAMBER_DESKTOP__?.listen;if(typeof t!=`function`)return async()=>{};let n=await t(`openchamber:ssh-instance-status`,t=>{let n=I(t?.payload);n&&e(n)});return async()=>{await n()}},qe=new Set([`nodeRuntimeMissing`,`packageManagerMissing`,`nativeBinding`,`openchamberCliMissing`,`openchamberRegistry`,`openchamberInstall`,`openchamberCliIncompatible`,`opencodeInstall`,`serverStart`,`sshAuth`,`sshUnreachable`,`timeout`,`unknown`]),Je=e=>typeof e==`string`&&qe.has(e),Ye=e=>{let t=String(e||``);return/requires Node\.js \d+|no supported Node runtime/i.test(t)?`nodeRuntimeMissing`:/neither bun nor npm/i.test(t)?`packageManagerMissing`:/better-sqlite3|node_gyp_bins|gyp ERR|failed to prepare better-sqlite3/i.test(t)?`nativeBinding`:/OpenChamber installation completed but the executable is unavailable/i.test(t)?`openchamberCliMissing`:/could not reach the npm registry|ENOTFOUND|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|CERT_HAS_EXPIRED|UNABLE_TO_GET_ISSUER_CERT|self-signed certificate|registry\.npmjs|npm error code E404|npm ERR! code E404|getaddrinfo/i.test(t)?`openchamberRegistry`:/Failed to install OpenChamber/i.test(t)?`openchamberInstall`:/Unknown option:\s*--relay-host|does not advertise --relay-host|does not support --relay-host/i.test(t)||/Unknown option:/i.test(t)?`openchamberCliIncompatible`:/Failed to install OpenCode|OpenCode CLI/i.test(t)?`opencodeInstall`:/failed to become reachable|Managed OpenChamber server failed/i.test(t)?`serverStart`:/Permission denied|Authentication failed|publickey|keyboard-interactive/i.test(t)?`sshAuth`:/Could not resolve hostname|Connection refused|Connection timed out|ControlMaster connection timed out|SSH master process exited|Network is unreachable/i.test(t)?`sshUnreachable`:/Timed out waiting for SSH|Timed out waiting for forwarded/i.test(t)?`timeout`:`unknown`},V=(e,t)=>Je(e)?e:Ye(t),H=e=>{switch(e){case`nodeRuntimeMissing`:return`desktopHostSwitcher.sshError.nodeRuntimeMissing.title`;case`packageManagerMissing`:return`desktopHostSwitcher.sshError.packageManagerMissing.title`;case`nativeBinding`:return`desktopHostSwitcher.sshError.nativeBinding.title`;case`openchamberCliMissing`:return`desktopHostSwitcher.sshError.openchamberCliMissing.title`;case`openchamberRegistry`:return`desktopHostSwitcher.sshError.openchamberRegistry.title`;case`openchamberInstall`:return`desktopHostSwitcher.sshError.openchamberInstall.title`;case`openchamberCliIncompatible`:return`desktopHostSwitcher.sshError.openchamberCliIncompatible.title`;case`opencodeInstall`:return`desktopHostSwitcher.sshError.opencodeInstall.title`;case`serverStart`:return`desktopHostSwitcher.sshError.serverStart.title`;case`sshAuth`:return`desktopHostSwitcher.sshError.sshAuth.title`;case`sshUnreachable`:return`desktopHostSwitcher.sshError.sshUnreachable.title`;case`timeout`:return`desktopHostSwitcher.sshError.timeout.title`;default:return`desktopHostSwitcher.sshError.unknown.title`}},U=e=>{switch(e){case`nodeRuntimeMissing`:return`desktopHostSwitcher.sshError.nodeRuntimeMissing.guidance`;case`packageManagerMissing`:return`desktopHostSwitcher.sshError.packageManagerMissing.guidance`;case`nativeBinding`:return`desktopHostSwitcher.sshError.nativeBinding.guidance`;case`openchamberCliMissing`:return`desktopHostSwitcher.sshError.openchamberCliMissing.guidance`;case`openchamberRegistry`:return`desktopHostSwitcher.sshError.openchamberRegistry.guidance`;case`openchamberInstall`:return`desktopHostSwitcher.sshError.openchamberInstall.guidance`;case`openchamberCliIncompatible`:return`desktopHostSwitcher.sshError.openchamberCliIncompatible.guidance`;case`opencodeInstall`:return`desktopHostSwitcher.sshError.opencodeInstall.guidance`;case`serverStart`:return`desktopHostSwitcher.sshError.serverStart.guidance`;case`sshAuth`:return`desktopHostSwitcher.sshError.sshAuth.guidance`;case`sshUnreachable`:return`desktopHostSwitcher.sshError.sshUnreachable.guidance`;case`timeout`:return`desktopHostSwitcher.sshError.timeout.guidance`;default:return`desktopHostSwitcher.sshError.unknown.guidance`}},W=e=>e===`unknown`||e===`openchamberCliIncompatible`,Xe=(e,t,n)=>{let r=typeof n==`string`?n.trim():``;return!W(t)||!r||r===e?e:`${e}\n${r}`},G=d();function Ze(e){let t=(0,T.c)(27),{errorCode:n,detail:r,className:i}=e,{t:a}=v(),o,s,c,l,u,d;if(t[0]!==i||t[1]!==r||t[2]!==n||t[3]!==a){let e=V(n,r);o=a(U(e));let f;t[10]===r?f=t[11]:(f=typeof r==`string`?r.trim():``,t[10]=r,t[11]=f),s=f,c=W(e)&&!!s&&s!==o,t[12]===i?d=t[13]:(d=C(`space-y-1`,i),t[12]=i,t[13]=d),l=`typography-ui-label text-[var(--status-error)]`,u=a(H(e)),t[0]=i,t[1]=r,t[2]=n,t[3]=a,t[4]=o,t[5]=s,t[6]=c,t[7]=l,t[8]=u,t[9]=d}else o=t[4],s=t[5],c=t[6],l=t[7],u=t[8],d=t[9];let f;t[14]!==l||t[15]!==u?(f=(0,G.jsx)(`p`,{className:l,children:u}),t[14]=l,t[15]=u,t[16]=f):f=t[16];let p;t[17]===o?p=t[18]:(p=(0,G.jsx)(`p`,{className:`typography-meta text-muted-foreground`,children:o}),t[17]=o,t[18]=p);let m;t[19]!==s||t[20]!==c?(m=c?(0,G.jsx)(`p`,{className:`typography-meta break-words text-muted-foreground`,children:s}):null,t[19]=s,t[20]=c,t[21]=m):m=t[21];let h;return t[22]!==d||t[23]!==f||t[24]!==p||t[25]!==m?(h=(0,G.jsxs)(`div`,{className:d,children:[f,p,m]}),t[22]=d,t[23]=f,t[24]=p,t[25]=m,t[26]=h):h=t[26],h}var Qe=`/auth/passkey/authenticate/options`,$e=`/auth/passkey/authenticate/verify`,et=`/auth/passkey/register/options`,tt=`/auth/passkey/register/verify`,K=`/api/passkeys`,nt=`/auth/passkey/status`,rt=`/api/auth/reset`,q={enabled:!1,hasPasskeys:!1,passkeyCount:0,rpID:null},J=async(e,t)=>i(e,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:t===void 0?void 0:JSON.stringify(t)}),Y=async(e,t)=>{try{let t=await e.json();if(t&&typeof t.error==`string`&&t.error.trim())return t.error}catch{}return t},it=e=>e instanceof oe&&e.code===`ERROR_CEREMONY_ABORTED`,at=()=>{ce.cancelCeremony()},X=()=>typeof window>`u`?{supported:!1,reason:`Passkeys are unavailable outside the browser.`}:window.isSecureContext?{supported:!0,reason:``}:{supported:!1,reason:`Passkeys require HTTPS or localhost.`},ot=async()=>{let e=X();if(!e.supported)throw Error(e.reason);let t=await J(et,{label:typeof navigator.userAgent==`string`&&navigator.userAgent.trim()?navigator.userAgent:`This device`});if(!t.ok)throw Error(await Y(t,`Could not start passkey setup.`));let{requestId:n,optionsJSON:r}=await t.json(),i=await J(tt,{requestId:n,response:await se({optionsJSON:r})});if(!i.ok)throw Error(await Y(i,`Could not finish passkey setup.`));return i.json().catch(()=>null)},st=async(e,t={})=>{let n=X();if(!n.supported)throw Error(n.reason);let r=await J(Qe);if(!r.ok)throw Error(await Y(r,`Passkey sign-in is not available right now.`));let{requestId:i,optionsJSON:a}=await r.json(),o=await J($e,{requestId:i,response:await le({optionsJSON:a}),trustDevice:e,issueClientToken:t.issueClientToken===!0,clientLabel:t.clientLabel,clientKind:t.clientKind,dedupeKey:t.dedupeKey});if(!o.ok)throw Error(await Y(o,`Passkey sign-in failed.`));return o.json().catch(()=>null)},ct=async()=>{let e=await i(nt,{method:`GET`,credentials:`include`,headers:{Accept:`application/json`}});if(!e.ok)return q;let t=await e.json().catch(()=>null);return{enabled:t?.enabled===!0,hasPasskeys:t?.hasPasskeys===!0,passkeyCount:typeof t?.passkeyCount==`number`?t.passkeyCount:0,rpID:typeof t?.rpID==`string`&&t.rpID?t.rpID:null}},lt=async()=>{let e=await i(K,{method:`GET`,credentials:`include`,headers:{Accept:`application/json`}});if(!e.ok)throw Error(await Y(e,`Could not load passkeys.`));let t=await e.json().catch(()=>null);return Array.isArray(t?.passkeys)?t.passkeys:[]},ut=async e=>{let t=await i(`${K}/${encodeURIComponent(e)}`,{method:`DELETE`,credentials:`include`,headers:{Accept:`application/json`}});if(!t.ok)throw Error(await Y(t,`Could not remove passkey.`));return t.json().catch(()=>null)},dt=async()=>{let e=await J(rt);if(!e.ok)throw Error(await Y(e,`Could not clear saved authentication.`));return e.json().catch(()=>null)},Z=e(f(),1);function ft(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-none`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function pt(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-header`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function mt(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`leading-none font-semibold`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-title`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function ht(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`px-6`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-content`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}var gt=class extends Z.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.setState({error:e,errorInfo:t,copied:!1}),console.error(`Error caught by boundary:`,e,t)}handleReset=()=>{this.setState({hasError:!1,error:void 0,errorInfo:void 0})};handleCopy=async()=>{let{strings:e}=this.props,t=`${this.state.error?String(this.state.error):e.unknownError}${this.state.error?.stack?`\n\nStack:\n${this.state.error.stack}`:``}${this.state.errorInfo?.componentStack?`\n\n${e.componentStackLabel}${this.state.errorInfo.componentStack}`:``}`;(await y(t)).ok&&(this.setState({copied:!0}),window.setTimeout(()=>{this.setState(e=>e.copied?{copied:!1}:null)},1500))};render(){let{strings:e}=this.props;return this.state.hasError?this.props.fallback?this.props.fallback:(0,G.jsx)(`div`,{className:`p-4 flex items-center justify-center min-h-screen`,children:(0,G.jsxs)(ft,{className:`w-full max-w-md`,children:[(0,G.jsx)(pt,{className:`text-center`,children:(0,G.jsxs)(mt,{className:`flex items-center justify-center gap-2 text-destructive`,children:[(0,G.jsx)(w,{name:`error-warning`,className:`h-5 w-5`}),e.title]})}),(0,G.jsxs)(ht,{className:`space-y-4`,children:[(0,G.jsx)(`p`,{className:`text-sm text-muted-foreground text-center`,children:e.description}),this.state.error&&(0,G.jsxs)(`details`,{className:`text-xs font-mono bg-muted p-3 rounded`,children:[(0,G.jsx)(`summary`,{className:`cursor-pointer hover:bg-interactive-hover/80`,children:e.detailsSummary}),(0,G.jsxs)(`pre`,{className:`mt-2 max-h-48 overflow-auto`,children:[this.state.error.toString(),this.state.errorInfo?.componentStack?`\n\n${e.componentStackLabel}${this.state.errorInfo.componentStack}`:``]})]}),(0,G.jsxs)(`div`,{className:`flex gap-2`,children:[(0,G.jsxs)(ae,{onClick:this.handleReset,variant:`outline`,className:`flex-1`,children:[(0,G.jsx)(w,{name:`restart`,className:`h-4 w-4 mr-2`}),e.tryAgain]}),(0,G.jsx)(ae,{onClick:this.handleCopy,variant:`outline`,className:`flex-1`,children:this.state.copied?e.copied:e.copy})]})]})]})}):this.props.children}},_t=e=>{let t=(0,T.c)(29),{children:n,fallback:r}=e,{t:i}=v(),a;t[0]===i?a=t[1]:(a=i(`errorBoundary.state.unknownError`),t[0]=i,t[1]=a);let o;t[2]===i?o=t[3]:(o=i(`errorBoundary.title`),t[2]=i,t[3]=o);let s;t[4]===i?s=t[5]:(s=i(`errorBoundary.description`),t[4]=i,t[5]=s);let c;t[6]===i?c=t[7]:(c=i(`errorBoundary.actions.errorDetails`),t[6]=i,t[7]=c);let l;t[8]===i?l=t[9]:(l=i(`errorBoundary.state.componentStackLabel`),t[8]=i,t[9]=l);let u;t[10]===i?u=t[11]:(u=i(`errorBoundary.actions.tryAgain`),t[10]=i,t[11]=u);let d;t[12]===i?d=t[13]:(d=i(`errorBoundary.actions.copied`),t[12]=i,t[13]=d);let f;t[14]===i?f=t[15]:(f=i(`errorBoundary.actions.copy`),t[14]=i,t[15]=f);let p;t[16]!==a||t[17]!==o||t[18]!==s||t[19]!==c||t[20]!==l||t[21]!==u||t[22]!==d||t[23]!==f?(p={unknownError:a,title:o,description:s,detailsSummary:c,componentStackLabel:l,tryAgain:u,copied:d,copy:f},t[16]=a,t[17]=o,t[18]=s,t[19]=c,t[20]=l,t[21]=u,t[22]=d,t[23]=f,t[24]=p):p=t[24];let m=p,h;return t[25]!==n||t[26]!==r||t[27]!==m?(h=(0,G.jsx)(gt,{fallback:r,strings:m,children:n}),t[25]=n,t[26]=r,t[27]=m,t[28]=h):h=t[28],h},Q=e=>x(b.getState().dictionary,e),vt=e=>typeof e!=`number`||!Number.isFinite(e)?null:Math.max(0,Math.min(100,Math.round(e))),yt=e=>typeof e!=`number`||!Number.isFinite(e)?`-`:`${Math.round(e)}%`,bt=(e,t)=>e??yt(t),xt=(e,t,n=`auto`)=>{if(!e)return t??``;try{let r=new Date(e);if(!Number.isFinite(r.getTime()))return t??``;let i=new Date;return r.toDateString()===i.toDateString()?de(r,n,{fallback:t??``}):ue(r,n,{month:`short`,day:`numeric`,weekday:`short`,hour:`numeric`,minute:`2-digit`})}catch{return t??``}},St=e=>e===null?`safe`:e>=80?`critical`:e>=50?`warn`:`safe`,Ct=e=>e===`5h`?Q(`quota.window.5h`):e===`7d`?Q(`quota.window.7d`):e===`7d-sonnet`?Q(`quota.window.7dSonnet`):e===`7d-opus`?Q(`quota.window.7dOpus`):e===`weekly`?Q(`quota.window.weekly`):e===`daily`?Q(`quota.window.daily`):e===`monthly`?Q(`quota.window.monthly`):e===`credits`?Q(`quota.window.credits`):e===`credits_balance`?Q(`quota.window.creditsBalance`):e===`billing_cycle`?Q(`quota.window.billingCycle`):e===`auto`?Q(`quota.window.auto`):e===`api`?Q(`quota.window.api`):e===`plan_limit`?Q(`quota.window.planLimit`):e===`on_demand`?Q(`quota.window.onDemand`):e===`session`?Q(`quota.window.session`):e===`premium`?Q(`quota.window.premium`):e===`chat`?Q(`quota.window.chat`):e===`completions`?Q(`quota.window.completions`):e===`premium_interactions`?Q(`quota.window.premiumInteractions`):e,wt=e=>{let t=e.toLowerCase().trim();if(t===`5h`)return 18e3;if(t===`7d`||t===`weekly`||t===`7d-sonnet`||t===`7d-opus`)return 604800;if(t===`monthly`)return 2592e3;if(t===`24h`||t===`daily`)return 86400;if(t===`1h`)return 3600;let n=t.match(/^(\d+)h$/);if(n)return parseInt(n[1],10)*3600;let r=t.match(/^(\d+)d$/);return r?parseInt(r[1],10)*86400:null},Tt=(e,t,n,r)=>{let i=n;if(i===null&&r&&(i=wt(r)),e===null||t===null||i===null||i<=0)return null;let a=Math.max(0,(t-Date.now())/1e3),o=Math.max(0,Math.min(i,i-a)),s=Math.max(0,Math.min(1,o/i)),c=e/100,l=e>=100&&a>0,u;u=s>.01?Math.min(999,c/s*100):e;let d;d=l?`exhausted`:c<=s?`on-track`:u<=130?`slightly-fast`:`too-fast`;let f=i>=432e3,p=f?86400:3600,m=f?`d`:`h`,h=i/p,g=e/Math.max(o/p,h*.01),_=Number.isFinite(g)?`${Math.min(999.9,Math.max(0,g)).toFixed(1)}%/${m}`:`-`,v=u>100?`+${Math.round(u)}%`:`${Math.round(u)}%`,y=null,b=i/86400;return b>=7&&(y=100/b),{elapsedRatio:s,usageRatio:c,predictedFinalPercent:u,remainingSeconds:a,isExhausted:l,elapsedSeconds:o,totalSeconds:i,status:d,paceRateText:_,predictText:v,dailyAllocationPercent:y}},Et=e=>{switch(e){case`exhausted`:case`too-fast`:return`var(--status-error)`;case`slightly-fast`:return`var(--status-warning)`;case`on-track`:return`var(--status-success)`}},Dt=e=>{let t=Math.floor(Math.max(0,Math.floor(e))/60),n=Math.floor(t/60),r=Math.floor(n/24),i=n%24,a=t%60;return r>0?`${r}d ${i}h`:n>0?`${n}h`:t===0?`<1m`:`${a}m`},Ot=e=>Math.min(100,Math.max(0,e*100)),kt=[`standalone`,`minimal-ui`,`fullscreen`,`window-controls-overlay`],At=`openchamber.pwaRecentSessions`,jt=e=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(`(display-mode: ${e})`).matches,Mt=()=>typeof window>`u`?`browser`:typeof document<`u`&&document.referrer.startsWith(`android-app://`)?`twa`:window.navigator.standalone?`standalone`:kt.find(e=>jt(e))??`browser`,Nt=864e5,Pt=5,Ft=864e5,$=e=>e.time?.updated??e.time?.created??0,It=({sessions:e,currentSessionId:t,cutoffDays:n,keepRecent:r=Pt,now:i=Date.now()})=>{if(!Array.isArray(e)||n<=0)return[];let a=i-n*Nt,o=[...e].sort((e,t)=>$(t)-$(e)),s=new Set(o.slice(0,r).map(e=>e.id));return o.filter(e=>{if(!e?.id||s.has(e.id)||e.id===t||e.share)return!1;let n=$(e);return n?n<a:!1}).map(e=>e.id)},Lt=e=>{let t=typeof e==`object`?e:void 0,r=t?.autoRun!==!1,i=typeof e==`boolean`?e:t?.enabled??!0,a=re(e=>e.currentSessionId),o=re(e=>e.isLoading),s=S(e=>e.activeSessions),c=S(e=>e.hasLoadedFullCatalog),l=n(e=>e.autoDeleteEnabled),u=n(e=>e.autoDeleteAfterDays),d=n(e=>e.sessionRetentionAction),f=n(e=>e.autoDeleteLastRunAt),m=n(e=>e.setAutoDeleteLastRunAt),[h,g]=Z.useState(!1),_=Z.useRef(!1);Z.useEffect(()=>{if(!i||!r||!l||u<=0)return;let e=window.setTimeout(()=>{ne(te())},8e3);return()=>window.clearTimeout(e)},[u,l,r,i]);let v=Z.useMemo(()=>u<=0?[]:It({sessions:s,currentSessionId:a,cutoffDays:u}),[u,a,s]),y=Z.useCallback(async({force:e=!1}={})=>{if(_.current)return{completedIds:[],failedIds:[],action:d,skippedReason:`running`};if((!l||u<=0)&&!e)return{completedIds:[],failedIds:[],action:d,skippedReason:`disabled`};if(o)return{completedIds:[],failedIds:[],action:d,skippedReason:`loading`};let t=Date.now();if(!e&&f&&t-f<Ft)return{completedIds:[],failedIds:[],action:d,skippedReason:`cooldown`};let{activeSessions:n}=await ne(te());if(n.length===0)return{completedIds:[],failedIds:[],action:d,skippedReason:`no-candidates`};let r=It({sessions:n,currentSessionId:a,cutoffDays:u,now:t});if(r.length===0)return m(t),{completedIds:[],failedIds:[],action:d,skippedReason:`no-candidates`};_.current=!0,g(!0);try{let e=new Map(n.map(e=>[e.id,e])),t=[],i=[];for(let n of r){let r=e.get(n),a=r?ie(r):null;if(!a){i.push(n);continue}try{d===`archive`?await p.updateSession(n,{time:{archived:Date.now()}},a):await p.deleteSession(n,a),t.push(n)}catch{i.push(n)}}return d===`archive`?S.getState().archiveSessions(t):S.getState().removeSessions(t),{completedIds:t,failedIds:i,action:d}}finally{_.current=!1,g(!1),m(Date.now())}},[u,l,f,a,o,d,m]);return Z.useEffect(()=>{i&&r&&(!l||u<=0||o||!c||s.length===0||f&&Date.now()-f<Ft||y())},[u,l,f,r,i,c,s.length,o,y]),{candidates:v,isRunning:h,runCleanup:y,keepRecentCount:Pt,action:d}};export{_e as $,V as A,De as B,X as C,ut as D,dt as E,Oe as F,Ae as G,Ee as H,Ue as I,Be as J,Ve as K,We as L,H as M,Ne as N,Ze as O,we as P,ge as Q,Ge as R,lt as S,ot as T,je as U,Te as V,Me as W,Ke as X,He as Y,he as Z,mt as _,Tt as a,q as b,bt as c,Et as d,St as f,pt as g,ht as h,Ot as i,U as j,Xe as k,Dt as l,ft as m,At as n,vt as o,_t as p,ze as q,Mt as r,xt as s,Lt as t,Ct as u,st as v,it as w,ct as x,at as y,ke as z};
1
+ import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{j as t,t as n}from"./useUIStore-DzwCfRqr.js";import{Kt as r,kn as i,qt as a,u as o}from"./persistence-6sclr7B6.js";import{h as s}from"./desktopHosts-Txp4xOVQ.js";import{i as c,n as l,r as u}from"./desktopRelayRestore-C_FSEHKM.js";import{nt as d,rt as f}from"./vendor-base-ui-CnHfUmDN.js";import{Nt as p}from"./platform-CbeLpKPk.js";import{n as m}from"./vendor-react-DLPElpoQ.js";import{n as h}from"./vendor-tanstack-query-core-BWz0ose6.js";import{i as g,r as _}from"./vendor-tanstack-react-query-D7pys_c9.js";import{n as v,t as y}from"./clipboard-DWuULPzo.js";import{i as b,t as x}from"./store-DQY8Fkb0.js";import{_r as S,br as ee,ca as te,cr as ne,l as re,mr as ie}from"./useMobileNavigationStore-wm9JzfV_.js";import{t as C}from"./utils-B1EK5zKa.js";import{n as w}from"./Icon-DpjYnXxn.js";import{t as ae}from"./button-C7OXr4ae.js";import{i as oe,n as se,r as ce,t as le}from"./vendor-simplewebauthn-browser-Dwhcdg_5.js";import{n as ue,r as de}from"./radio-DpGoPQGD.js";var T=m(),E=[`desktopHostSwitch`],D=class extends Error{result;host;constructor(e,t){super(e.reason),this.name=`DesktopHostSwitchError`,this.result=e,this.host=t}},fe=(e,t)=>x(b.getState().dictionary,e,t),pe=async e=>{let{host:n}=e;if(n.id===`local`){let r=(e.localApiOrigin||``).trim();if(!r)throw new D({ok:!1,status:{status:`unreachable`,latencyMs:0},reason:`unreachable`},n);return t({apiBaseUrl:r,clientToken:e.localClientToken||null,runtimeKey:u(n)}),{ok:!0,via:`direct`,status:{status:`ok`,latencyMs:0}}}let r=await c(n,{cachedProbe:e.cachedProbe});if(!r.ok)throw new D(r,n);return r},O=null,me=()=>O||(O=new h(o,{mutationKey:E,mutationFn:pe,onError:(e,t)=>{e instanceof D&&e.result.reason!==`unsupported`&&ee.error(fe(`desktopHostSwitcher.toast.instanceUnreachable`,{host:s(t.host.label)}))}}),O.subscribe(()=>void 0),O),he=async e=>{if(l(e.host))return{ok:!0,via:`direct`,status:e.cachedProbe?.status===`ok`?e.cachedProbe:{status:`ok`,latencyMs:0}};if(o.isMutating({mutationKey:E})>0)return{ok:!1,status:{status:`unreachable`,latencyMs:0},reason:`unsupported`};try{return await me().mutate(e)}catch(e){if(e instanceof D)return e.result;throw e}},ge=()=>{let e=(0,T.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={mutationKey:E},e[0]=t):t=e[0],_(t)>0},_e=()=>{let e=(0,T.c)(1),t;return e[0]===Symbol.for(`react.memo_cache_sentinel`)?(t={filters:{mutationKey:E,status:`pending`},select:ve},e[0]=t):t=e[0],g(t)[0]?.host.id??null};function ve(e){return e.state.variables}var k=e=>typeof e==`object`&&!!e,A=(e,t)=>{let n=e[t];return typeof n==`string`?n:null},j=(e,t)=>{let n=e[t];return typeof n==`number`&&Number.isFinite(n)?n:null},M=(e,t)=>{let n=e[t];return typeof n==`boolean`?n:null},N=e=>Array.isArray(e)?e.filter(e=>typeof e==`string`):[],P=()=>r()?(e,t)=>a(e,t):null,F=e=>{if(!k(e))return;let t=M(e,`enabled`)??!1,n=A(e,`store`)?.toLowerCase()===`settings`?`settings`:`never`,r=A(e,`value`);return{enabled:t,store:n,...r?{value:r}:{}}},ye=e=>e===`remote`||e===`dynamic`?e:`local`,be=e=>{if(!k(e))return null;let t=A(e,`id`);if(!t)return null;let n=M(e,`enabled`)??!0,r=ye(A(e,`type`)),i=A(e,`localHost`)||A(e,`local_host`)||void 0,a=j(e,`localPort`)??j(e,`local_port`)??void 0,o=A(e,`remoteHost`)||A(e,`remote_host`)||void 0,s=j(e,`remotePort`)??j(e,`remote_port`)??void 0;return{id:t,enabled:n,type:r,...i?{localHost:i}:{},...typeof a==`number`?{localPort:a}:{},...o?{remoteHost:o}:{},...typeof s==`number`?{remotePort:s}:{}}},xe=e=>{if(!k(e))return null;let t=A(e,`id`),n=A(e,`sshCommand`)||A(e,`ssh_command`);if(!t||!n)return null;let r=A(e,`nickname`),i=e.sshParsed,a=k(i)?{destination:A(i,`destination`)||``,args:N(i.args)}:void 0,o=k(e.remoteOpenchamber)?e.remoteOpenchamber:k(e.remote_openchamber)?e.remote_openchamber:{},s=k(e.localForward)?e.localForward:k(e.local_forward)?e.local_forward:{},c=k(e.auth)?e.auth:{},l=A(o,`mode`)?.toLowerCase()===`external`?`external`:`managed`,u=A(o,`installMethod`)||A(o,`install_method`),d=u===`npm`||u===`download_release`||u===`upload_bundle`?u:`bun`,f=A(s,`bindHost`)||A(s,`bind_host`)||`127.0.0.1`,p=f===`localhost`||f===`0.0.0.0`?f:`127.0.0.1`,m=(Array.isArray(e.portForwards)?e.portForwards:Array.isArray(e.port_forwards)?e.port_forwards:[]).map(e=>be(e)).filter(e=>!!e),h=j(o,`preferredPort`)??j(o,`preferred_port`),g=j(s,`preferredLocalPort`)??j(s,`preferred_local_port`),_=F(c.sshPassword||c.ssh_password),v=F(c.openchamberPassword||c.openchamber_password);return{id:t,...r?{nickname:r}:{},sshCommand:n,...a&&a.destination?{sshParsed:a}:{},connectionTimeoutSec:j(e,`connectionTimeoutSec`)??j(e,`connection_timeout_sec`)??60,remoteOpenchamber:{mode:l,keepRunning:M(o,`keepRunning`)??M(o,`keep_running`)??!0,relayHost:M(o,`relayHost`)??M(o,`relay_host`)??!0,...h?{preferredPort:h}:{},installMethod:d,uploadBundleOverSsh:M(o,`uploadBundleOverSsh`)??M(o,`upload_bundle_over_ssh`)??!1},localForward:{...g?{preferredLocalPort:g}:{},bindHost:p},auth:{..._?{sshPassword:_}:{},...v?{openchamberPassword:v}:{}},portForwards:m}},Se=e=>{switch(e){case`config_resolved`:case`auth_check`:case`master_connecting`:case`remote_probe`:case`installing`:case`updating`:case`server_detecting`:case`server_starting`:case`forwarding`:case`ready`:case`degraded`:case`error`:return e;default:return`idle`}},I=e=>{if(!k(e))return null;let t=A(e,`id`);return t?{id:t,phase:Se(A(e,`phase`)),...A(e,`detail`)?{detail:A(e,`detail`)||void 0}:{},...A(e,`localUrl`)||A(e,`local_url`)?{localUrl:A(e,`localUrl`)||A(e,`local_url`)||void 0}:{},...typeof(j(e,`localPort`)??j(e,`local_port`))==`number`?{localPort:j(e,`localPort`)??j(e,`local_port`)??void 0}:{},...typeof(j(e,`remotePort`)??j(e,`remote_port`))==`number`?{remotePort:j(e,`remotePort`)??j(e,`remote_port`)??void 0}:{},startedByUs:M(e,`startedByUs`)??M(e,`started_by_us`)??!1,retryAttempt:j(e,`retryAttempt`)??j(e,`retry_attempt`)??0,requiresUserAction:M(e,`requiresUserAction`)??M(e,`requires_user_action`)??!1,...A(e,`errorCode`)||A(e,`error_code`)?{errorCode:A(e,`errorCode`)||A(e,`error_code`)||void 0}:{},updatedAtMs:j(e,`updatedAtMs`)??j(e,`updated_at_ms`)??Date.now()}:null},Ce=e=>{if(!k(e))return null;let t=A(e,`host`),n=A(e,`source`),r=A(e,`sshCommand`)||A(e,`ssh_command`);return!t||!n||!r?null:{host:t,source:n,sshCommand:r,pattern:M(e,`pattern`)??!1}},we=(e,t)=>({id:e,sshCommand:t,connectionTimeoutSec:60,remoteOpenchamber:{mode:`managed`,keepRunning:!0,relayHost:!0,installMethod:`bun`,uploadBundleOverSsh:!1},localForward:{bindHost:`127.0.0.1`},auth:{},portForwards:[]}),Te=async()=>{let e=P();if(!e)return{instances:[]};let t=await e(`desktop_ssh_instances_get`);return k(t)?{instances:(Array.isArray(t.instances)?t.instances:Array.isArray(t.desktopSshInstances)?t.desktopSshInstances:[]).map(e=>xe(e)).filter(e=>!!e)}:{instances:[]}},Ee=async e=>{let t=P();t&&await t(`desktop_ssh_instances_set`,{config:{instances:e.instances}})},De=async()=>{let e=P();if(!e)return[];let t=await e(`desktop_ssh_import_hosts`);return Array.isArray(t)?t.map(e=>Ce(e)).filter(e=>!!e):[]},Oe=async e=>{let t=P();t&&await t(`desktop_ssh_connect`,{id:e})},ke=async e=>{let t=P();t&&await t(`desktop_ssh_disconnect`,{id:e})},Ae=async e=>{let t=P();if(!t)return[];let n=await t(`desktop_ssh_status`,{...e?{id:e}:{}});return Array.isArray(n)?n.map(e=>I(e)).filter(e=>!!e):[]},je=async(e,t)=>{let n=P();if(!n)return[];let r=await n(`desktop_ssh_logs`,{id:e,...typeof t==`number`?{limit:t}:{}});return Array.isArray(r)?r.filter(e=>typeof e==`string`):[]},Me=async e=>{let t=P();t&&await t(`desktop_ssh_logs_clear`,{id:e})},Ne=(e,t)=>{let n=Math.max(0,Math.trunc(Number(e.fileGroups)||0)),r=Math.max(0,Math.trunc(Number(e.singleFiles)||0)),i=Math.max(0,Math.trunc(Number(e.directories)||0));return{fileGroups:Array.from({length:n},()=>!0),singleFiles:Array.from({length:r},()=>!0),directories:Array.from({length:i},()=>!0),agentsRoot:!0,authFile:t?.includeAuthFile===!0}},Pe=e=>{if(!k(e))return null;let t=A(e,`path`),n=j(e,`bytes`);return!t||n===null?null:{path:t,bytes:n}},Fe=e=>{if(!k(e))return null;let t=A(e,`path`),n=j(e,`fileCount`)??j(e,`file_count`),r=j(e,`bytes`);return!t||n===null||r===null?null:{path:t,fileCount:n,bytes:r}},Ie=e=>{if(e==null||!k(e))return null;let t=j(e,`fileCount`)??j(e,`file_count`),n=j(e,`bytes`);return t===null||n===null?null:{fileCount:t,bytes:n}},L=e=>{if(e==null||!k(e))return null;let t=j(e,`bytes`);return t===null?null:{bytes:t}},R=e=>{if(!k(e))return null;let t=Array.isArray(e.files)?e.files:null,n=Array.isArray(e.directories)?e.directories:null,r=N(e.deletes),i=j(e,`totalBytes`)??j(e,`total_bytes`);if(!t||!n||i===null||!(`agentsRoot`in e)&&!(`agents_root`in e))return null;let a=t.map(e=>Pe(e)).filter(e=>!!e),o=n.map(e=>Fe(e)).filter(e=>!!e);if(a.length!==t.length||o.length!==n.length)return null;let s=e.agentsRoot??e.agents_root,c=s==null?null:Ie(s);if(s!=null&&c===null)return null;let l=e.authFile??e.auth_file,u=l==null?null:L(l),d=e.direction===`pull`||e.direction===`push`?e.direction:void 0,f=e.selections,p=k(f)?{fileGroups:Array.isArray(f.fileGroups)?f.fileGroups.map(e=>e!==!1):[],singleFiles:Array.isArray(f.singleFiles)?f.singleFiles.map(e=>e!==!1):[],directories:Array.isArray(f.directories)?f.directories.map(e=>e!==!1):[],agentsRoot:f.agentsRoot!==!1,authFile:f.authFile===!0}:void 0,m=z(e.selectionShape??e.selection_shape);return{files:a,directories:o,agentsRoot:c,authFile:u,deletes:r,totalBytes:i,...d?{direction:d}:{},...p?{selections:p}:{},...m?{selectionShape:m}:{}}},z=e=>{if(!k(e))return null;let t=j(e,`fileGroups`)??j(e,`file_groups`),n=j(e,`singleFiles`)??j(e,`single_files`),r=j(e,`directories`);return t===null||n===null||r===null||t<0||n<0||r<0?null:{fileGroups:t,singleFiles:n,directories:r}},Le=e=>{if(!k(e))return null;let t=R(e.plan);if(!t)return null;let n=z(e.selectionShape??e.selection_shape)??t.selectionShape??null;return{plan:t,remoteExisting:N(e.remoteExisting??e.remote_existing),remoteAgentsRootExists:M(e,`remoteAgentsRootExists`)??M(e,`remote_agents_root_exists`)??!1,remoteAuthFileExists:M(e,`remoteAuthFileExists`)??M(e,`remote_auth_file_exists`)??!1,...typeof e.credentialAuthorized==`boolean`?{credentialAuthorized:e.credentialAuthorized}:{},...n?{selectionShape:n}:{}}},Re=e=>{if(!k(e)||M(e,`ok`)!==!0)return null;let t=j(e,`files`),n=j(e,`directories`),r=j(e,`deletes`),i=j(e,`totalBytes`)??j(e,`total_bytes`);if(t===null||n===null||r===null||i===null||!(`agentsRoot`in e)&&!(`agents_root`in e))return null;let a=e.agentsRoot??e.agents_root,o=null;if(a!=null){if(!k(a))return null;let e=j(a,`fileCount`)??j(a,`file_count`);if(e===null)return null;o={fileCount:e}}let s=e.authFile??e.auth_file,c=s==null?null:L(s);return{ok:!0,files:t,directories:n,deletes:r,totalBytes:i,agentsRoot:o,authFile:c}},ze=async(e={})=>{let t=P();if(!t)return console.error(`[desktopSsh] config sync local scan skipped: desktop IPC bridge is unavailable in this window`),null;let n=await t(`desktop_ssh_sync_opencode_config`,{stage:`local`,...e.direction?{direction:e.direction}:{},...e.selections?{selections:e.selections}:{}});if(!k(n))return console.error(`[desktopSsh] config sync local scan returned a non-object payload`,n),null;let r=R(n.plan);if(!r)return console.error(`[desktopSsh] config sync local scan plan payload was not recognized`,n),null;let i=z(n.selectionShape??n.selection_shape)??r.selectionShape??null;return i?{...r,selectionShape:i}:r},Be=async(e,t={})=>{let n=P();if(!n)return console.error(`[desktopSsh] config sync preview skipped: desktop IPC bridge is unavailable in this window`),null;let r=await n(`desktop_ssh_sync_opencode_config`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{},...t.direction?{direction:t.direction}:{},...t.selections?{selections:t.selections}:{}}),i=Le(r);return i||console.error(`[desktopSsh] config sync preview payload was not recognized`,r),i},Ve=async(e,t={})=>{let n=P();if(!n)return console.error(`[desktopSsh] config sync apply skipped: desktop IPC bridge is unavailable in this window`),null;let r=await n(`desktop_ssh_sync_opencode_config`,{id:e,apply:!0,...t.targetKind?{targetKind:t.targetKind}:{},...t.direction?{direction:t.direction}:{},...t.selections?{selections:t.selections}:{}}),i=Re(r);return i||console.error(`[desktopSsh] config sync apply payload was not recognized`,r),i},He=async(e,t={})=>{let n=P();if(!n)return[];let r=await n(`desktop_ssh_sync_runs_list`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}});return Array.isArray(r)?r.filter(e=>k(e)&&typeof e.syncRunId==`string`&&typeof e.targetId==`string`):[]},B=e=>{if(!k(e))return null;let t=typeof e.targetId==`string`?e.targetId.trim():``;if(!t)return null;let n=e.authorized===!0,r=typeof e.grantedAt==`string`&&e.grantedAt.trim()?e.grantedAt.trim():void 0,i=typeof e.channel==`string`&&e.channel.trim()?e.channel.trim():void 0;return{targetId:t,authorized:n,...r?{grantedAt:r}:{},...i?{channel:i}:{}}},Ue=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_get`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},We=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_grant`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},Ge=async(e,t={})=>{let n=P();return n?B(await n(`desktop_ssh_credential_sync_revoke`,{id:e,...t.targetKind?{targetKind:t.targetKind}:{}})):null},Ke=async e=>{if(!r())return async()=>{};let t=window.__OPENCHAMBER_DESKTOP__?.listen;if(typeof t!=`function`)return async()=>{};let n=await t(`openchamber:ssh-instance-status`,t=>{let n=I(t?.payload);n&&e(n)});return async()=>{await n()}},qe=new Set([`nodeRuntimeMissing`,`packageManagerMissing`,`nativeBinding`,`openchamberCliMissing`,`openchamberRegistry`,`openchamberInstall`,`openchamberCliIncompatible`,`opencodeInstall`,`serverStart`,`sshAuth`,`sshUnreachable`,`timeout`,`unknown`]),Je=e=>typeof e==`string`&&qe.has(e),Ye=e=>{let t=String(e||``);return/requires Node\.js \d+|no supported Node runtime/i.test(t)?`nodeRuntimeMissing`:/neither bun nor npm/i.test(t)?`packageManagerMissing`:/better-sqlite3|node_gyp_bins|gyp ERR|failed to prepare better-sqlite3/i.test(t)?`nativeBinding`:/OpenChamber installation completed but the executable is unavailable/i.test(t)?`openchamberCliMissing`:/could not reach the npm registry|ENOTFOUND|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|CERT_HAS_EXPIRED|UNABLE_TO_GET_ISSUER_CERT|self-signed certificate|registry\.npmjs|npm error code E404|npm ERR! code E404|getaddrinfo/i.test(t)?`openchamberRegistry`:/Failed to install OpenChamber/i.test(t)?`openchamberInstall`:/Unknown option:\s*--relay-host|does not advertise --relay-host|does not support --relay-host/i.test(t)||/Unknown option:/i.test(t)?`openchamberCliIncompatible`:/Failed to install OpenCode|OpenCode CLI/i.test(t)?`opencodeInstall`:/failed to become reachable|Managed OpenChamber server failed/i.test(t)?`serverStart`:/Permission denied|Authentication failed|publickey|keyboard-interactive/i.test(t)?`sshAuth`:/Could not resolve hostname|Connection refused|Connection timed out|ControlMaster connection timed out|SSH master process exited|Network is unreachable/i.test(t)?`sshUnreachable`:/Timed out waiting for SSH|Timed out waiting for forwarded/i.test(t)?`timeout`:`unknown`},V=(e,t)=>Je(e)?e:Ye(t),H=e=>{switch(e){case`nodeRuntimeMissing`:return`desktopHostSwitcher.sshError.nodeRuntimeMissing.title`;case`packageManagerMissing`:return`desktopHostSwitcher.sshError.packageManagerMissing.title`;case`nativeBinding`:return`desktopHostSwitcher.sshError.nativeBinding.title`;case`openchamberCliMissing`:return`desktopHostSwitcher.sshError.openchamberCliMissing.title`;case`openchamberRegistry`:return`desktopHostSwitcher.sshError.openchamberRegistry.title`;case`openchamberInstall`:return`desktopHostSwitcher.sshError.openchamberInstall.title`;case`openchamberCliIncompatible`:return`desktopHostSwitcher.sshError.openchamberCliIncompatible.title`;case`opencodeInstall`:return`desktopHostSwitcher.sshError.opencodeInstall.title`;case`serverStart`:return`desktopHostSwitcher.sshError.serverStart.title`;case`sshAuth`:return`desktopHostSwitcher.sshError.sshAuth.title`;case`sshUnreachable`:return`desktopHostSwitcher.sshError.sshUnreachable.title`;case`timeout`:return`desktopHostSwitcher.sshError.timeout.title`;default:return`desktopHostSwitcher.sshError.unknown.title`}},U=e=>{switch(e){case`nodeRuntimeMissing`:return`desktopHostSwitcher.sshError.nodeRuntimeMissing.guidance`;case`packageManagerMissing`:return`desktopHostSwitcher.sshError.packageManagerMissing.guidance`;case`nativeBinding`:return`desktopHostSwitcher.sshError.nativeBinding.guidance`;case`openchamberCliMissing`:return`desktopHostSwitcher.sshError.openchamberCliMissing.guidance`;case`openchamberRegistry`:return`desktopHostSwitcher.sshError.openchamberRegistry.guidance`;case`openchamberInstall`:return`desktopHostSwitcher.sshError.openchamberInstall.guidance`;case`openchamberCliIncompatible`:return`desktopHostSwitcher.sshError.openchamberCliIncompatible.guidance`;case`opencodeInstall`:return`desktopHostSwitcher.sshError.opencodeInstall.guidance`;case`serverStart`:return`desktopHostSwitcher.sshError.serverStart.guidance`;case`sshAuth`:return`desktopHostSwitcher.sshError.sshAuth.guidance`;case`sshUnreachable`:return`desktopHostSwitcher.sshError.sshUnreachable.guidance`;case`timeout`:return`desktopHostSwitcher.sshError.timeout.guidance`;default:return`desktopHostSwitcher.sshError.unknown.guidance`}},W=e=>e===`unknown`||e===`openchamberCliIncompatible`,Xe=(e,t,n)=>{let r=typeof n==`string`?n.trim():``;return!W(t)||!r||r===e?e:`${e}\n${r}`},G=d();function Ze(e){let t=(0,T.c)(27),{errorCode:n,detail:r,className:i}=e,{t:a}=v(),o,s,c,l,u,d;if(t[0]!==i||t[1]!==r||t[2]!==n||t[3]!==a){let e=V(n,r);o=a(U(e));let f;t[10]===r?f=t[11]:(f=typeof r==`string`?r.trim():``,t[10]=r,t[11]=f),s=f,c=W(e)&&!!s&&s!==o,t[12]===i?d=t[13]:(d=C(`space-y-1`,i),t[12]=i,t[13]=d),l=`typography-ui-label text-[var(--status-error)]`,u=a(H(e)),t[0]=i,t[1]=r,t[2]=n,t[3]=a,t[4]=o,t[5]=s,t[6]=c,t[7]=l,t[8]=u,t[9]=d}else o=t[4],s=t[5],c=t[6],l=t[7],u=t[8],d=t[9];let f;t[14]!==l||t[15]!==u?(f=(0,G.jsx)(`p`,{className:l,children:u}),t[14]=l,t[15]=u,t[16]=f):f=t[16];let p;t[17]===o?p=t[18]:(p=(0,G.jsx)(`p`,{className:`typography-meta text-muted-foreground`,children:o}),t[17]=o,t[18]=p);let m;t[19]!==s||t[20]!==c?(m=c?(0,G.jsx)(`p`,{className:`typography-meta break-words text-muted-foreground`,children:s}):null,t[19]=s,t[20]=c,t[21]=m):m=t[21];let h;return t[22]!==d||t[23]!==f||t[24]!==p||t[25]!==m?(h=(0,G.jsxs)(`div`,{className:d,children:[f,p,m]}),t[22]=d,t[23]=f,t[24]=p,t[25]=m,t[26]=h):h=t[26],h}var Qe=`/auth/passkey/authenticate/options`,$e=`/auth/passkey/authenticate/verify`,et=`/auth/passkey/register/options`,tt=`/auth/passkey/register/verify`,K=`/api/passkeys`,nt=`/auth/passkey/status`,rt=`/api/auth/reset`,q={enabled:!1,hasPasskeys:!1,passkeyCount:0,rpID:null},J=async(e,t)=>i(e,{method:`POST`,credentials:`include`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:t===void 0?void 0:JSON.stringify(t)}),Y=async(e,t)=>{try{let t=await e.json();if(t&&typeof t.error==`string`&&t.error.trim())return t.error}catch{}return t},it=e=>e instanceof oe&&e.code===`ERROR_CEREMONY_ABORTED`,at=()=>{ce.cancelCeremony()},X=()=>typeof window>`u`?{supported:!1,reason:`Passkeys are unavailable outside the browser.`}:window.isSecureContext?{supported:!0,reason:``}:{supported:!1,reason:`Passkeys require HTTPS or localhost.`},ot=async()=>{let e=X();if(!e.supported)throw Error(e.reason);let t=await J(et,{label:typeof navigator.userAgent==`string`&&navigator.userAgent.trim()?navigator.userAgent:`This device`});if(!t.ok)throw Error(await Y(t,`Could not start passkey setup.`));let{requestId:n,optionsJSON:r}=await t.json(),i=await J(tt,{requestId:n,response:await se({optionsJSON:r})});if(!i.ok)throw Error(await Y(i,`Could not finish passkey setup.`));return i.json().catch(()=>null)},st=async(e,t={})=>{let n=X();if(!n.supported)throw Error(n.reason);let r=await J(Qe);if(!r.ok)throw Error(await Y(r,`Passkey sign-in is not available right now.`));let{requestId:i,optionsJSON:a}=await r.json(),o=await J($e,{requestId:i,response:await le({optionsJSON:a}),trustDevice:e,issueClientToken:t.issueClientToken===!0,clientLabel:t.clientLabel,clientKind:t.clientKind,dedupeKey:t.dedupeKey});if(!o.ok)throw Error(await Y(o,`Passkey sign-in failed.`));return o.json().catch(()=>null)},ct=async()=>{let e=await i(nt,{method:`GET`,credentials:`include`,headers:{Accept:`application/json`}});if(!e.ok)return q;let t=await e.json().catch(()=>null);return{enabled:t?.enabled===!0,hasPasskeys:t?.hasPasskeys===!0,passkeyCount:typeof t?.passkeyCount==`number`?t.passkeyCount:0,rpID:typeof t?.rpID==`string`&&t.rpID?t.rpID:null}},lt=async()=>{let e=await i(K,{method:`GET`,credentials:`include`,headers:{Accept:`application/json`}});if(!e.ok)throw Error(await Y(e,`Could not load passkeys.`));let t=await e.json().catch(()=>null);return Array.isArray(t?.passkeys)?t.passkeys:[]},ut=async e=>{let t=await i(`${K}/${encodeURIComponent(e)}`,{method:`DELETE`,credentials:`include`,headers:{Accept:`application/json`}});if(!t.ok)throw Error(await Y(t,`Could not remove passkey.`));return t.json().catch(()=>null)},dt=async()=>{let e=await J(rt);if(!e.ok)throw Error(await Y(e,`Could not clear saved authentication.`));return e.json().catch(()=>null)},Z=e(f(),1);function ft(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-none`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function pt(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-header`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function mt(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`leading-none font-semibold`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-title`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}function ht(e){let t=(0,T.c)(8),n,r;t[0]===e?(n=t[1],r=t[2]):({className:n,...r}=e,t[0]=e,t[1]=n,t[2]=r);let i;t[3]===n?i=t[4]:(i=C(`px-6`,n),t[3]=n,t[4]=i);let a;return t[5]!==r||t[6]!==i?(a=(0,G.jsx)(`div`,{"data-slot":`card-content`,className:i,...r}),t[5]=r,t[6]=i,t[7]=a):a=t[7],a}var gt=class extends Z.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.setState({error:e,errorInfo:t,copied:!1}),console.error(`Error caught by boundary:`,e,t)}handleReset=()=>{this.setState({hasError:!1,error:void 0,errorInfo:void 0})};handleCopy=async()=>{let{strings:e}=this.props,t=`${this.state.error?String(this.state.error):e.unknownError}${this.state.error?.stack?`\n\nStack:\n${this.state.error.stack}`:``}${this.state.errorInfo?.componentStack?`\n\n${e.componentStackLabel}${this.state.errorInfo.componentStack}`:``}`;(await y(t)).ok&&(this.setState({copied:!0}),window.setTimeout(()=>{this.setState(e=>e.copied?{copied:!1}:null)},1500))};render(){let{strings:e}=this.props;return this.state.hasError?this.props.fallback?this.props.fallback:(0,G.jsx)(`div`,{className:`p-4 flex items-center justify-center min-h-screen`,children:(0,G.jsxs)(ft,{className:`w-full max-w-md`,children:[(0,G.jsx)(pt,{className:`text-center`,children:(0,G.jsxs)(mt,{className:`flex items-center justify-center gap-2 text-destructive`,children:[(0,G.jsx)(w,{name:`error-warning`,className:`h-5 w-5`}),e.title]})}),(0,G.jsxs)(ht,{className:`space-y-4`,children:[(0,G.jsx)(`p`,{className:`text-sm text-muted-foreground text-center`,children:e.description}),this.state.error&&(0,G.jsxs)(`details`,{className:`text-xs font-mono bg-muted p-3 rounded`,children:[(0,G.jsx)(`summary`,{className:`cursor-pointer hover:bg-interactive-hover/80`,children:e.detailsSummary}),(0,G.jsxs)(`pre`,{className:`mt-2 max-h-48 overflow-auto`,children:[this.state.error.toString(),this.state.errorInfo?.componentStack?`\n\n${e.componentStackLabel}${this.state.errorInfo.componentStack}`:``]})]}),(0,G.jsxs)(`div`,{className:`flex gap-2`,children:[(0,G.jsxs)(ae,{onClick:this.handleReset,variant:`outline`,className:`flex-1`,children:[(0,G.jsx)(w,{name:`restart`,className:`h-4 w-4 mr-2`}),e.tryAgain]}),(0,G.jsx)(ae,{onClick:this.handleCopy,variant:`outline`,className:`flex-1`,children:this.state.copied?e.copied:e.copy})]})]})]})}):this.props.children}},_t=e=>{let t=(0,T.c)(29),{children:n,fallback:r}=e,{t:i}=v(),a;t[0]===i?a=t[1]:(a=i(`errorBoundary.state.unknownError`),t[0]=i,t[1]=a);let o;t[2]===i?o=t[3]:(o=i(`errorBoundary.title`),t[2]=i,t[3]=o);let s;t[4]===i?s=t[5]:(s=i(`errorBoundary.description`),t[4]=i,t[5]=s);let c;t[6]===i?c=t[7]:(c=i(`errorBoundary.actions.errorDetails`),t[6]=i,t[7]=c);let l;t[8]===i?l=t[9]:(l=i(`errorBoundary.state.componentStackLabel`),t[8]=i,t[9]=l);let u;t[10]===i?u=t[11]:(u=i(`errorBoundary.actions.tryAgain`),t[10]=i,t[11]=u);let d;t[12]===i?d=t[13]:(d=i(`errorBoundary.actions.copied`),t[12]=i,t[13]=d);let f;t[14]===i?f=t[15]:(f=i(`errorBoundary.actions.copy`),t[14]=i,t[15]=f);let p;t[16]!==a||t[17]!==o||t[18]!==s||t[19]!==c||t[20]!==l||t[21]!==u||t[22]!==d||t[23]!==f?(p={unknownError:a,title:o,description:s,detailsSummary:c,componentStackLabel:l,tryAgain:u,copied:d,copy:f},t[16]=a,t[17]=o,t[18]=s,t[19]=c,t[20]=l,t[21]=u,t[22]=d,t[23]=f,t[24]=p):p=t[24];let m=p,h;return t[25]!==n||t[26]!==r||t[27]!==m?(h=(0,G.jsx)(gt,{fallback:r,strings:m,children:n}),t[25]=n,t[26]=r,t[27]=m,t[28]=h):h=t[28],h},Q=e=>x(b.getState().dictionary,e),vt=e=>typeof e!=`number`||!Number.isFinite(e)?null:Math.max(0,Math.min(100,Math.round(e))),yt=e=>typeof e!=`number`||!Number.isFinite(e)?`-`:`${Math.round(e)}%`,bt=(e,t)=>e??yt(t),xt=(e,t,n=`auto`)=>{if(!e)return t??``;try{let r=new Date(e);if(!Number.isFinite(r.getTime()))return t??``;let i=new Date;return r.toDateString()===i.toDateString()?de(r,n,{fallback:t??``}):ue(r,n,{month:`short`,day:`numeric`,weekday:`short`,hour:`numeric`,minute:`2-digit`})}catch{return t??``}},St=e=>e===null?`safe`:e>=80?`critical`:e>=50?`warn`:`safe`,Ct=e=>e===`5h`?Q(`quota.window.5h`):e===`7d`?Q(`quota.window.7d`):e===`7d-sonnet`?Q(`quota.window.7dSonnet`):e===`7d-opus`?Q(`quota.window.7dOpus`):e===`weekly`?Q(`quota.window.weekly`):e===`daily`?Q(`quota.window.daily`):e===`monthly`?Q(`quota.window.monthly`):e===`credits`?Q(`quota.window.credits`):e===`credits_balance`?Q(`quota.window.creditsBalance`):e===`billing_cycle`?Q(`quota.window.billingCycle`):e===`auto`?Q(`quota.window.auto`):e===`api`?Q(`quota.window.api`):e===`plan_limit`?Q(`quota.window.planLimit`):e===`on_demand`?Q(`quota.window.onDemand`):e===`session`?Q(`quota.window.session`):e===`premium`?Q(`quota.window.premium`):e===`chat`?Q(`quota.window.chat`):e===`completions`?Q(`quota.window.completions`):e===`premium_interactions`?Q(`quota.window.premiumInteractions`):e,wt=e=>{let t=e.toLowerCase().trim();if(t===`5h`)return 18e3;if(t===`7d`||t===`weekly`||t===`7d-sonnet`||t===`7d-opus`)return 604800;if(t===`monthly`)return 2592e3;if(t===`24h`||t===`daily`)return 86400;if(t===`1h`)return 3600;let n=t.match(/^(\d+)h$/);if(n)return parseInt(n[1],10)*3600;let r=t.match(/^(\d+)d$/);return r?parseInt(r[1],10)*86400:null},Tt=(e,t,n,r)=>{let i=n;if(i===null&&r&&(i=wt(r)),e===null||t===null||i===null||i<=0)return null;let a=Math.max(0,(t-Date.now())/1e3),o=Math.max(0,Math.min(i,i-a)),s=Math.max(0,Math.min(1,o/i)),c=e/100,l=e>=100&&a>0,u;u=s>.01?Math.min(999,c/s*100):e;let d;d=l?`exhausted`:c<=s?`on-track`:u<=130?`slightly-fast`:`too-fast`;let f=i>=432e3,p=f?86400:3600,m=f?`d`:`h`,h=i/p,g=e/Math.max(o/p,h*.01),_=Number.isFinite(g)?`${Math.min(999.9,Math.max(0,g)).toFixed(1)}%/${m}`:`-`,v=u>100?`+${Math.round(u)}%`:`${Math.round(u)}%`,y=null,b=i/86400;return b>=7&&(y=100/b),{elapsedRatio:s,usageRatio:c,predictedFinalPercent:u,remainingSeconds:a,isExhausted:l,elapsedSeconds:o,totalSeconds:i,status:d,paceRateText:_,predictText:v,dailyAllocationPercent:y}},Et=e=>{switch(e){case`exhausted`:case`too-fast`:return`var(--status-error)`;case`slightly-fast`:return`var(--status-warning)`;case`on-track`:return`var(--status-success)`}},Dt=e=>{let t=Math.floor(Math.max(0,Math.floor(e))/60),n=Math.floor(t/60),r=Math.floor(n/24),i=n%24,a=t%60;return r>0?`${r}d ${i}h`:n>0?`${n}h`:t===0?`<1m`:`${a}m`},Ot=e=>Math.min(100,Math.max(0,e*100)),kt=[`standalone`,`minimal-ui`,`fullscreen`,`window-controls-overlay`],At=`openchamber.pwaRecentSessions`,jt=e=>typeof window>`u`||typeof window.matchMedia!=`function`?!1:window.matchMedia(`(display-mode: ${e})`).matches,Mt=()=>typeof window>`u`?`browser`:typeof document<`u`&&document.referrer.startsWith(`android-app://`)?`twa`:window.navigator.standalone?`standalone`:kt.find(e=>jt(e))??`browser`,Nt=864e5,Pt=5,Ft=864e5,$=e=>e.time?.updated??e.time?.created??0,It=({sessions:e,currentSessionId:t,cutoffDays:n,keepRecent:r=Pt,now:i=Date.now()})=>{if(!Array.isArray(e)||n<=0)return[];let a=i-n*Nt,o=[...e].sort((e,t)=>$(t)-$(e)),s=new Set(o.slice(0,r).map(e=>e.id));return o.filter(e=>{if(!e?.id||s.has(e.id)||e.id===t||e.share)return!1;let n=$(e);return n?n<a:!1}).map(e=>e.id)},Lt=e=>{let t=typeof e==`object`?e:void 0,r=t?.autoRun!==!1,i=typeof e==`boolean`?e:t?.enabled??!0,a=re(e=>e.currentSessionId),o=re(e=>e.isLoading),s=S(e=>e.activeSessions),c=S(e=>e.hasLoadedFullCatalog),l=n(e=>e.autoDeleteEnabled),u=n(e=>e.autoDeleteAfterDays),d=n(e=>e.sessionRetentionAction),f=n(e=>e.autoDeleteLastRunAt),m=n(e=>e.setAutoDeleteLastRunAt),[h,g]=Z.useState(!1),_=Z.useRef(!1);Z.useEffect(()=>{if(!i||!r||!l||u<=0)return;let e=window.setTimeout(()=>{ne(te())},8e3);return()=>window.clearTimeout(e)},[u,l,r,i]);let v=Z.useMemo(()=>u<=0?[]:It({sessions:s,currentSessionId:a,cutoffDays:u}),[u,a,s]),y=Z.useCallback(async({force:e=!1}={})=>{if(_.current)return{completedIds:[],failedIds:[],action:d,skippedReason:`running`};if((!l||u<=0)&&!e)return{completedIds:[],failedIds:[],action:d,skippedReason:`disabled`};if(o)return{completedIds:[],failedIds:[],action:d,skippedReason:`loading`};let t=Date.now();if(!e&&f&&t-f<Ft)return{completedIds:[],failedIds:[],action:d,skippedReason:`cooldown`};let{activeSessions:n}=await ne(te());if(n.length===0)return{completedIds:[],failedIds:[],action:d,skippedReason:`no-candidates`};let r=It({sessions:n,currentSessionId:a,cutoffDays:u,now:t});if(r.length===0)return m(t),{completedIds:[],failedIds:[],action:d,skippedReason:`no-candidates`};_.current=!0,g(!0);try{let e=new Map(n.map(e=>[e.id,e])),t=[],i=[];for(let n of r){let r=e.get(n),a=r?ie(r):null;if(!a){i.push(n);continue}try{d===`archive`?await p.updateSession(n,{time:{archived:Date.now()}},a):await p.deleteSession(n,a),t.push(n)}catch{i.push(n)}}return d===`archive`?S.getState().archiveSessions(t):S.getState().removeSessions(t),{completedIds:t,failedIds:i,action:d}}finally{_.current=!1,g(!1),m(Date.now())}},[u,l,f,a,o,d,m]);return Z.useEffect(()=>{i&&r&&(!l||u<=0||o||!c||s.length===0||f&&Date.now()-f<Ft||y())},[u,l,f,r,i,c,s.length,o,y]),{candidates:v,isRunning:h,runCleanup:y,keepRecentCount:Pt,action:d}};export{_e as $,V as A,De as B,X as C,ut as D,dt as E,Oe as F,Ae as G,Ee as H,Ue as I,Be as J,Ve as K,We as L,H as M,Ne as N,Ze as O,we as P,ge as Q,Ge as R,lt as S,ot as T,je as U,Te as V,Me as W,Ke as X,He as Y,he as Z,mt as _,Tt as a,q as b,bt as c,Et as d,St as f,pt as g,ht as h,Ot as i,U as j,Xe as k,Dt as l,ft as m,At as n,vt as o,_t as p,ze as q,Mt as r,xt as s,Lt as t,Ct as u,st as v,it as w,ct as x,at as y,ke as z};
@@ -1,4 +1,4 @@
1
- import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{_ as t}from"./useUIStore-DzwCfRqr.js";import{$t as n,kn as r,xn as i}from"./persistence-6sclr7B6.js";import{nt as a,rt as o}from"./vendor-base-ui-CnHfUmDN.js";import{n as s}from"./platform-CbeLpKPk.js";import{a as c,n as l}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{n as u}from"./vendor-react-DLPElpoQ.js";import{n as d}from"./clipboard-DWuULPzo.js";import{t as f}from"./utils-B1EK5zKa.js";import{n as p}from"./Icon-DpjYnXxn.js";import{t as m}from"./button-C7OXr4ae.js";import{i as h,n as g,t as _}from"./tooltip-D_orJMYd.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{c as y,n as b,o as x,r as S,s as C}from"./markdownTheme-B89dbj3N.js";import{i as w}from"./appThemeRegistry-NoIEZNtX.js";import{d as T,n as E,t as D,u as ee}from"./markdown-worker-W06-MhF5.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.js";var O=e(o(),1),k=u(),A=a(),ne=`w-[min(30rem,calc(100cqw-1rem))] min-w-[280px] max-w-full overflow-hidden rounded-xl shadow-[inset_0_1px_0_0_rgba(255,255,255,0.8),inset_0_0_0_1px_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.10),0_1px_2px_-0.5px_rgba(0,0,0,0.08),0_4px_8px_-2px_rgba(0,0,0,0.08),0_12px_20px_-4px_rgba(0,0,0,0.08)] dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.12),inset_0_0_0_1px_rgba(255,255,255,0.08),0_0_0_1px_rgba(0,0,0,0.36),0_1px_1px_-0.5px_rgba(0,0,0,0.22),0_3px_3px_-1.5px_rgba(0,0,0,0.20),0_6px_6px_-3px_rgba(0,0,0,0.16)]`,j={maxWidth:`min(28rem, calc(100cqw - 4ch))`,backgroundColor:`var(--surface-elevated)`,color:`var(--surface-elevated-foreground)`},M=`flex items-center justify-between gap-3 border-b border-[var(--surface-subtle)] px-3 py-2.5`,N=`text-xs font-medium leading-4 text-foreground md:text-[0.8125rem] md:leading-5`,re=`text-xs tabular-nums leading-4 text-muted-foreground md:text-[0.8125rem] md:leading-5`,P=`m-0 list-none divide-y divide-[var(--surface-subtle)] p-0`,F=`${P} max-h-[min(22rem,50vh)] overflow-y-auto`,ie=`${P} w-full`,ae={className:`p-0 rounded-none`,maxHeightClass:`max-h-[46vh]`,disableHorizontal:!0},I=`px-2.5 py-1.5 text-xs leading-4 md:py-2 md:text-[0.8125rem] md:leading-5`,oe=`flex min-w-0 items-center gap-1 text-xs leading-4 text-muted-foreground md:gap-1.5 md:text-[0.8125rem] md:leading-5`,se=`min-w-0 truncate text-xs leading-4 text-foreground md:text-[0.8125rem] md:leading-5`,ce=`inline-flex shrink-0 items-center gap-1 text-xs leading-4 tabular-nums text-muted-foreground md:text-[0.8125rem] md:leading-5`,le=`h-3 w-3 shrink-0 md:h-3.5 md:w-3.5`,ue={in_progress:`text-foreground`,pending:`text-foreground`,completed:`text-muted-foreground line-through`,cancelled:`text-muted-foreground line-through`},L={in_progress:`chat.statusRow.todo.status.inProgress`,pending:`chat.statusRow.todo.status.pending`,completed:`chat.statusRow.todo.status.completed`,cancelled:`chat.statusRow.todo.status.cancelled`},R=e=>{let t=(0,k.c)(26),{todo:n,isActive:r,activeRef:i}=e,{t:a}=d(),o=z.has(n.status)?n.status:`pending`,s=L[o],c;t[0]!==a||t[1]!==s?(c=a(s),t[0]=a,t[1]=s,t[2]=c):c=t[2];let l=c,u;t[3]===o?u=t[4]:(u=o===`in_progress`?(0,A.jsx)(p,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(p,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(p,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let m=u,v=r?`step`:void 0,y=r&&`bg-[var(--surface-muted)] before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-[var(--status-info)]`,b;t[5]===y?b=t[6]:(b=f(`group relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)] items-start gap-2.5`,I,y),t[5]=y,t[6]=b);let x;t[7]!==m||t[8]!==l?(x=(0,A.jsx)(h,{asChild:!0,children:(0,A.jsx)(`span`,{className:`flex size-4 items-center justify-center`,"aria-label":l,children:m})}),t[7]=m,t[8]=l,t[9]=x):x=t[9];let S;t[10]===l?S=t[11]:(S=(0,A.jsx)(g,{side:`left`,sideOffset:6,children:l}),t[10]=l,t[11]=S);let C;t[12]!==x||t[13]!==S?(C=(0,A.jsxs)(_,{children:[x,S]}),t[12]=x,t[13]=S,t[14]=C):C=t[14];let w=ue[o],T;t[15]===w?T=t[16]:(T=f(`block whitespace-normal break-words`,w),t[15]=w,t[16]=T);let E;t[17]!==T||t[18]!==n.content?(E=(0,A.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,A.jsx)(`span`,{className:T,children:n.content})}),t[17]=T,t[18]=n.content,t[19]=E):E=t[19];let D;return t[20]!==i||t[21]!==E||t[22]!==v||t[23]!==b||t[24]!==C?(D=(0,A.jsxs)(`li`,{ref:i,"aria-current":v,className:b,children:[C,E]}),t[20]=i,t[21]=E,t[22]=v,t[23]=b,t[24]=C,t[25]=D):D=t[25],D},z=new Set([`in_progress`,`pending`,`completed`,`cancelled`]),B=`image/png`,V=c(`OpenChamberMedia`),H=e=>{let t=e.toLowerCase().split(`;`)[0]?.trim()||B;if(t===`image/jpeg`||t===`image/jpg`)return`jpg`;if(t===`image/webp`)return`webp`;if(t===`image/gif`)return`gif`;if(t===`image/svg+xml`)return`svg`;if(t===`image/png`)return`png`;let n=t.split(`/`)[1];return n&&/^[a-z0-9.+-]+$/i.test(n)?n:`png`},U=(e,t)=>{let n=`image.${H(t)}`,r=(((e||``).trim()||n).split(/[\\/]/).pop()||n).replace(/[^\w.\- ()[\]]+/g,`_`).replace(/^\.+/,``);return r?/\.[a-z0-9]{1,8}$/i.test(r)?r:`${r}.${H(t)}`:n},W=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{if(typeof r.result==`string`){t(r.result);return}n(Error(`Failed to encode image`))},r.onerror=()=>n(r.error??Error(`Failed to encode image`)),r.readAsDataURL(e)}),de=async e=>{let t=await W(e),n=t.indexOf(`,`);return n>=0?t.slice(n+1):t},fe=(e,t)=>{let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),window.setTimeout(()=>URL.revokeObjectURL(n),1e3)},G=async(e,t)=>{let n=await fetch(e,{signal:t,cache:`no-store`});if(!n.ok)throw Error(`Image fetch failed (${n.status})`);return n.blob()},pe=async(e,t=B)=>{if(!e.naturalWidth||!e.naturalHeight)return null;let n=e.currentSrc||e.src;if(n&&(/^(?:blob:|data:|openchamber-asset:)/i.test(n)||/^https?:/i.test(n)||/^\/api(?=\/|[?#]|$)/.test(n)))try{let e=await G(n);if(e.size>0)return e}catch{}try{let n=document.createElement(`canvas`);n.width=e.naturalWidth,n.height=e.naturalHeight;let r=n.getContext(`2d`);if(!r)return null;r.drawImage(e,0,0);let i=t.startsWith(`image/`)?t:B,a=await new Promise(e=>{n.toBlob(t=>e(t),i===`image/jpg`?`image/jpeg`:i)});return a&&a.size>0?a:null}catch{return null}},me=async(e,t)=>{let n=``;try{return n=await S(e,t??new AbortController().signal),await G(n,t)}finally{n&&C(n)}},he=async(e,t)=>{let n=e.effectiveDirectory??``,i=null;e.prefetchedBlob&&e.prefetchedBlob.size>0&&(i=e.prefetchedBlob);let a=e.displayUrl?.trim();if(!i&&a)try{i=await G(a,t)}catch{i=null}if(!i){let a=e.sourceUrl.trim();if(!a)throw Error(`Image source is empty`);if(/^(?:data|blob):/i.test(a)||/^https?:/i.test(a)||/^\/api(?=\/|[?#]|$)/.test(a))i=await G(a,t);else{let e=y(a,n);if(x(e))try{i=await me(e.path,t)}catch{let n=await r(`/api/fs/raw`,{method:`GET`,cache:`no-store`,query:{path:e.path},signal:t});if(!n.ok)throw Error(`Image source request failed with status ${n.status}`);i=await n.blob()}else i=await G(e.source,t)}}if(!i||i.size<=0)throw Error(`Image is empty`);let o=(e.mimeType||(i.type&&i.type.startsWith(`image/`)?i.type:``)||B).split(`;`)[0].trim()||B;return{blob:i,filename:U(e.filename,o),mimeType:o}},ge=()=>!s()||l===void 0?!1:l.isPluginAvailable(`OpenChamberMedia`),_e=async(e,t)=>{let{blob:r,filename:a,mimeType:o}=await he(e,t);if(ge()){let e=await de(r);return await V.saveImage({dataBase64:e,mimeType:o,filename:a}),`saved`}if(n()){let e=i()?.vscode;if(e?.saveImage){let t=await W(r);return await e.saveImage({fileName:a,dataUrl:t}),`saved`}}return fe(r,a),`downloaded`},ve=e=>e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`),ye=e=>e?Object.entries(e).map(([e,t])=>t==null?``:`${e.startsWith(`--`)?e:e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}:${typeof t==`number`?`${t}px`:t};`).join(``):``,K=(e,t,n)=>{let r=e.querySelector(`pre`);r&&(r.style.margin=`0`,r.style.background=`transparent`,r.style.whiteSpace=t?`pre-wrap`:`pre`,t&&(r.style.wordBreak=`break-word`,r.style.overflowWrap=`break-word`));let i=e.querySelector(`code`);if(i){let e=ye(n);e&&i.setAttribute(`style`,`${i.getAttribute(`style`)??``}${e}`)}},be=e=>`<pre><code>${ve(e)}</code></pre>`,xe=e=>{let t=(0,k.c)(21),{code:n,language:r,className:i,style:a,codeStyle:o,wrap:s}=e,c=s!==void 0&&s,{currentTheme:l}=v(),u=O.useRef(null),d;t[0]===l?d=t[1]:(d=b(l),t[0]=l,t[1]=d);let p=d,m,h;t[2]!==n||t[3]!==o||t[4]!==c?(m=()=>{let e=u.current;e&&(e.innerHTML=be(n),K(e,c,o))},h=[n,c,o],t[2]=n,t[3]=o,t[4]=c,t[5]=m,t[6]=h):(m=t[5],h=t[6]),O.useLayoutEffect(m,h);let g,_;t[7]!==n||t[8]!==o||t[9]!==r||t[10]!==c?(g=()=>{let e=u.current;if(!e)return;let t=!0,i=new AbortController;return D(n,(r||`text`).toLowerCase(),{signal:i.signal,priority:`visible`}).then(n=>{!t||!e||!n||(e.innerHTML=n,K(e,c,o))}),()=>{t=!1,i.abort()}},_=[n,r,c,o],t[7]=n,t[8]=o,t[9]=r,t[10]=c,t[11]=g,t[12]=_):(g=t[11],_=t[12]),O.useEffect(g,_);let y;t[13]===i?y=t[14]:(y=f(`typography-code`,i),t[13]=i,t[14]=y);let x=p,S;t[15]!==a||t[16]!==x?(S={...x,...a},t[15]=a,t[16]=x,t[17]=S):S=t[17];let C;return t[18]!==y||t[19]!==S?(C=(0,A.jsx)(`div`,{ref:u,className:y,style:S}),t[18]=y,t[19]=S,t[20]=C):C=t[20],C},Se=e=>{let t=e.replace(/^<file>\s*\n?/,``).replace(/\n?<\/file>\s*$/,``);return t=t.replace(/^\s*\d{5}\|\s?/gm,``),t.trim()},Ce=(e,t=``)=>{if(typeof e==`string`)return e;if(e==null)return t;if(typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`)return String(e);try{return JSON.stringify(e)}catch{return t}},we=e=>e?e.includes(`<diagnostics`)||e.includes(`<file_diagnostics>`)||e.includes(`LSP errors detected`)||e.includes(`This file has errors`):!1,Te=e=>e?e.replace(/\n{0,2}LSP errors detected[\s\S]*?<diagnostics[^>]*>[\s\S]*?<\/diagnostics>/g,``).replace(/\n{0,2}This file has errors[\s\S]*?<\/file_diagnostics>/g,``).replace(/<diagnostics[^>]*>[\s\S]*?<\/diagnostics>/g,``).replace(/<file_diagnostics>[\s\S]*?<\/file_diagnostics>/g,``).trim():``,Ee=(e,t)=>!e||typeof e!=`object`?String(e):T(e,t||``),q=e=>{if(typeof e==`string`){let t=e.trim();return t.length>0?t:void 0}if(e&&typeof e==`object`){let t=e.patch;if(typeof t==`string`){let e=t.trim();return e.length>0?e:void 0}}},De=e=>{if(!e||typeof e!=`object`)return;let t=q(e.patch)??q(e.diff);if(t)return t;let n=Array.isArray(e.files)?e.files:[];for(let e of n){if(!e||typeof e!=`object`)continue;let t=q(e.patch)??q(e.diff);if(t)return t}},Oe=e=>{if(!e||typeof e!=`string`)return{data:null,isJson:!1};let t=e.trim();if(!t.startsWith(`{`)&&!t.startsWith(`[`)||!t.endsWith(`}`)&&!t.endsWith(`]`)||t.length<2)return{data:null,isJson:!1};try{let e=JSON.parse(t);return typeof e==`object`&&e?{data:e,isJson:!0}:{data:null,isJson:!1}}catch{return{data:null,isJson:!1}}},ke=(e,t,n)=>{let r=Se(e);if((t===`edit`||t===`multiedit`||t===`write`||t===`apply_patch`)&&we(r)&&(r=Te(r)),(t===`edit`||t===`multiedit`||t===`apply_patch`)&&r.trim().length===0){let e=De(n);if(e)return e}return r},Ae=e=>{let t=e.match(/<type>(file|directory)<\/type>/i)?.[1]?.toLowerCase()??`unknown`,n=(e.match(/<content>([\s\S]*?)<\/content>/i)?.[1]??e).replace(/\r\n/g,`
1
+ import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{_ as t}from"./useUIStore-DzwCfRqr.js";import{$t as n,kn as r,xn as i}from"./persistence-6sclr7B6.js";import{nt as a,rt as o}from"./vendor-base-ui-CnHfUmDN.js";import{n as s}from"./platform-CbeLpKPk.js";import{a as c,n as l}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{n as u}from"./vendor-react-DLPElpoQ.js";import{n as d}from"./clipboard-DWuULPzo.js";import{t as f}from"./utils-B1EK5zKa.js";import{n as p}from"./Icon-DpjYnXxn.js";import{t as m}from"./button-C7OXr4ae.js";import{i as h,n as g,t as _}from"./tooltip-D_orJMYd.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{c as y,n as b,o as x,r as S,s as C}from"./markdownTheme-B89dbj3N.js";import{i as w}from"./appThemeRegistry-DYl9pc39.js";import{d as T,n as E,t as D,u as ee}from"./markdown-worker-W06-MhF5.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.js";var O=e(o(),1),k=u(),A=a(),ne=`w-[min(30rem,calc(100cqw-1rem))] min-w-[280px] max-w-full overflow-hidden rounded-xl shadow-[inset_0_1px_0_0_rgba(255,255,255,0.8),inset_0_0_0_1px_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.10),0_1px_2px_-0.5px_rgba(0,0,0,0.08),0_4px_8px_-2px_rgba(0,0,0,0.08),0_12px_20px_-4px_rgba(0,0,0,0.08)] dark:shadow-[inset_0_1px_0_0_rgba(255,255,255,0.12),inset_0_0_0_1px_rgba(255,255,255,0.08),0_0_0_1px_rgba(0,0,0,0.36),0_1px_1px_-0.5px_rgba(0,0,0,0.22),0_3px_3px_-1.5px_rgba(0,0,0,0.20),0_6px_6px_-3px_rgba(0,0,0,0.16)]`,j={maxWidth:`min(28rem, calc(100cqw - 4ch))`,backgroundColor:`var(--surface-elevated)`,color:`var(--surface-elevated-foreground)`},M=`flex items-center justify-between gap-3 border-b border-[var(--surface-subtle)] px-3 py-2.5`,N=`text-xs font-medium leading-4 text-foreground md:text-[0.8125rem] md:leading-5`,re=`text-xs tabular-nums leading-4 text-muted-foreground md:text-[0.8125rem] md:leading-5`,P=`m-0 list-none divide-y divide-[var(--surface-subtle)] p-0`,F=`${P} max-h-[min(22rem,50vh)] overflow-y-auto`,ie=`${P} w-full`,ae={className:`p-0 rounded-none`,maxHeightClass:`max-h-[46vh]`,disableHorizontal:!0},I=`px-2.5 py-1.5 text-xs leading-4 md:py-2 md:text-[0.8125rem] md:leading-5`,oe=`flex min-w-0 items-center gap-1 text-xs leading-4 text-muted-foreground md:gap-1.5 md:text-[0.8125rem] md:leading-5`,se=`min-w-0 truncate text-xs leading-4 text-foreground md:text-[0.8125rem] md:leading-5`,ce=`inline-flex shrink-0 items-center gap-1 text-xs leading-4 tabular-nums text-muted-foreground md:text-[0.8125rem] md:leading-5`,le=`h-3 w-3 shrink-0 md:h-3.5 md:w-3.5`,ue={in_progress:`text-foreground`,pending:`text-foreground`,completed:`text-muted-foreground line-through`,cancelled:`text-muted-foreground line-through`},L={in_progress:`chat.statusRow.todo.status.inProgress`,pending:`chat.statusRow.todo.status.pending`,completed:`chat.statusRow.todo.status.completed`,cancelled:`chat.statusRow.todo.status.cancelled`},R=e=>{let t=(0,k.c)(26),{todo:n,isActive:r,activeRef:i}=e,{t:a}=d(),o=z.has(n.status)?n.status:`pending`,s=L[o],c;t[0]!==a||t[1]!==s?(c=a(s),t[0]=a,t[1]=s,t[2]=c):c=t[2];let l=c,u;t[3]===o?u=t[4]:(u=o===`in_progress`?(0,A.jsx)(p,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(p,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(p,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let m=u,v=r?`step`:void 0,y=r&&`bg-[var(--surface-muted)] before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-[var(--status-info)]`,b;t[5]===y?b=t[6]:(b=f(`group relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)] items-start gap-2.5`,I,y),t[5]=y,t[6]=b);let x;t[7]!==m||t[8]!==l?(x=(0,A.jsx)(h,{asChild:!0,children:(0,A.jsx)(`span`,{className:`flex size-4 items-center justify-center`,"aria-label":l,children:m})}),t[7]=m,t[8]=l,t[9]=x):x=t[9];let S;t[10]===l?S=t[11]:(S=(0,A.jsx)(g,{side:`left`,sideOffset:6,children:l}),t[10]=l,t[11]=S);let C;t[12]!==x||t[13]!==S?(C=(0,A.jsxs)(_,{children:[x,S]}),t[12]=x,t[13]=S,t[14]=C):C=t[14];let w=ue[o],T;t[15]===w?T=t[16]:(T=f(`block whitespace-normal break-words`,w),t[15]=w,t[16]=T);let E;t[17]!==T||t[18]!==n.content?(E=(0,A.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,A.jsx)(`span`,{className:T,children:n.content})}),t[17]=T,t[18]=n.content,t[19]=E):E=t[19];let D;return t[20]!==i||t[21]!==E||t[22]!==v||t[23]!==b||t[24]!==C?(D=(0,A.jsxs)(`li`,{ref:i,"aria-current":v,className:b,children:[C,E]}),t[20]=i,t[21]=E,t[22]=v,t[23]=b,t[24]=C,t[25]=D):D=t[25],D},z=new Set([`in_progress`,`pending`,`completed`,`cancelled`]),B=`image/png`,V=c(`OpenChamberMedia`),H=e=>{let t=e.toLowerCase().split(`;`)[0]?.trim()||B;if(t===`image/jpeg`||t===`image/jpg`)return`jpg`;if(t===`image/webp`)return`webp`;if(t===`image/gif`)return`gif`;if(t===`image/svg+xml`)return`svg`;if(t===`image/png`)return`png`;let n=t.split(`/`)[1];return n&&/^[a-z0-9.+-]+$/i.test(n)?n:`png`},U=(e,t)=>{let n=`image.${H(t)}`,r=(((e||``).trim()||n).split(/[\\/]/).pop()||n).replace(/[^\w.\- ()[\]]+/g,`_`).replace(/^\.+/,``);return r?/\.[a-z0-9]{1,8}$/i.test(r)?r:`${r}.${H(t)}`:n},W=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{if(typeof r.result==`string`){t(r.result);return}n(Error(`Failed to encode image`))},r.onerror=()=>n(r.error??Error(`Failed to encode image`)),r.readAsDataURL(e)}),de=async e=>{let t=await W(e),n=t.indexOf(`,`);return n>=0?t.slice(n+1):t},fe=(e,t)=>{let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),window.setTimeout(()=>URL.revokeObjectURL(n),1e3)},G=async(e,t)=>{let n=await fetch(e,{signal:t,cache:`no-store`});if(!n.ok)throw Error(`Image fetch failed (${n.status})`);return n.blob()},pe=async(e,t=B)=>{if(!e.naturalWidth||!e.naturalHeight)return null;let n=e.currentSrc||e.src;if(n&&(/^(?:blob:|data:|openchamber-asset:)/i.test(n)||/^https?:/i.test(n)||/^\/api(?=\/|[?#]|$)/.test(n)))try{let e=await G(n);if(e.size>0)return e}catch{}try{let n=document.createElement(`canvas`);n.width=e.naturalWidth,n.height=e.naturalHeight;let r=n.getContext(`2d`);if(!r)return null;r.drawImage(e,0,0);let i=t.startsWith(`image/`)?t:B,a=await new Promise(e=>{n.toBlob(t=>e(t),i===`image/jpg`?`image/jpeg`:i)});return a&&a.size>0?a:null}catch{return null}},me=async(e,t)=>{let n=``;try{return n=await S(e,t??new AbortController().signal),await G(n,t)}finally{n&&C(n)}},he=async(e,t)=>{let n=e.effectiveDirectory??``,i=null;e.prefetchedBlob&&e.prefetchedBlob.size>0&&(i=e.prefetchedBlob);let a=e.displayUrl?.trim();if(!i&&a)try{i=await G(a,t)}catch{i=null}if(!i){let a=e.sourceUrl.trim();if(!a)throw Error(`Image source is empty`);if(/^(?:data|blob):/i.test(a)||/^https?:/i.test(a)||/^\/api(?=\/|[?#]|$)/.test(a))i=await G(a,t);else{let e=y(a,n);if(x(e))try{i=await me(e.path,t)}catch{let n=await r(`/api/fs/raw`,{method:`GET`,cache:`no-store`,query:{path:e.path},signal:t});if(!n.ok)throw Error(`Image source request failed with status ${n.status}`);i=await n.blob()}else i=await G(e.source,t)}}if(!i||i.size<=0)throw Error(`Image is empty`);let o=(e.mimeType||(i.type&&i.type.startsWith(`image/`)?i.type:``)||B).split(`;`)[0].trim()||B;return{blob:i,filename:U(e.filename,o),mimeType:o}},ge=()=>!s()||l===void 0?!1:l.isPluginAvailable(`OpenChamberMedia`),_e=async(e,t)=>{let{blob:r,filename:a,mimeType:o}=await he(e,t);if(ge()){let e=await de(r);return await V.saveImage({dataBase64:e,mimeType:o,filename:a}),`saved`}if(n()){let e=i()?.vscode;if(e?.saveImage){let t=await W(r);return await e.saveImage({fileName:a,dataUrl:t}),`saved`}}return fe(r,a),`downloaded`},ve=e=>e.replace(/&/g,`&amp;`).replace(/</g,`&lt;`).replace(/>/g,`&gt;`).replace(/"/g,`&quot;`).replace(/'/g,`&#39;`),ye=e=>e?Object.entries(e).map(([e,t])=>t==null?``:`${e.startsWith(`--`)?e:e.replace(/[A-Z]/g,e=>`-${e.toLowerCase()}`)}:${typeof t==`number`?`${t}px`:t};`).join(``):``,K=(e,t,n)=>{let r=e.querySelector(`pre`);r&&(r.style.margin=`0`,r.style.background=`transparent`,r.style.whiteSpace=t?`pre-wrap`:`pre`,t&&(r.style.wordBreak=`break-word`,r.style.overflowWrap=`break-word`));let i=e.querySelector(`code`);if(i){let e=ye(n);e&&i.setAttribute(`style`,`${i.getAttribute(`style`)??``}${e}`)}},be=e=>`<pre><code>${ve(e)}</code></pre>`,xe=e=>{let t=(0,k.c)(21),{code:n,language:r,className:i,style:a,codeStyle:o,wrap:s}=e,c=s!==void 0&&s,{currentTheme:l}=v(),u=O.useRef(null),d;t[0]===l?d=t[1]:(d=b(l),t[0]=l,t[1]=d);let p=d,m,h;t[2]!==n||t[3]!==o||t[4]!==c?(m=()=>{let e=u.current;e&&(e.innerHTML=be(n),K(e,c,o))},h=[n,c,o],t[2]=n,t[3]=o,t[4]=c,t[5]=m,t[6]=h):(m=t[5],h=t[6]),O.useLayoutEffect(m,h);let g,_;t[7]!==n||t[8]!==o||t[9]!==r||t[10]!==c?(g=()=>{let e=u.current;if(!e)return;let t=!0,i=new AbortController;return D(n,(r||`text`).toLowerCase(),{signal:i.signal,priority:`visible`}).then(n=>{!t||!e||!n||(e.innerHTML=n,K(e,c,o))}),()=>{t=!1,i.abort()}},_=[n,r,c,o],t[7]=n,t[8]=o,t[9]=r,t[10]=c,t[11]=g,t[12]=_):(g=t[11],_=t[12]),O.useEffect(g,_);let y;t[13]===i?y=t[14]:(y=f(`typography-code`,i),t[13]=i,t[14]=y);let x=p,S;t[15]!==a||t[16]!==x?(S={...x,...a},t[15]=a,t[16]=x,t[17]=S):S=t[17];let C;return t[18]!==y||t[19]!==S?(C=(0,A.jsx)(`div`,{ref:u,className:y,style:S}),t[18]=y,t[19]=S,t[20]=C):C=t[20],C},Se=e=>{let t=e.replace(/^<file>\s*\n?/,``).replace(/\n?<\/file>\s*$/,``);return t=t.replace(/^\s*\d{5}\|\s?/gm,``),t.trim()},Ce=(e,t=``)=>{if(typeof e==`string`)return e;if(e==null)return t;if(typeof e==`number`||typeof e==`boolean`||typeof e==`bigint`)return String(e);try{return JSON.stringify(e)}catch{return t}},we=e=>e?e.includes(`<diagnostics`)||e.includes(`<file_diagnostics>`)||e.includes(`LSP errors detected`)||e.includes(`This file has errors`):!1,Te=e=>e?e.replace(/\n{0,2}LSP errors detected[\s\S]*?<diagnostics[^>]*>[\s\S]*?<\/diagnostics>/g,``).replace(/\n{0,2}This file has errors[\s\S]*?<\/file_diagnostics>/g,``).replace(/<diagnostics[^>]*>[\s\S]*?<\/diagnostics>/g,``).replace(/<file_diagnostics>[\s\S]*?<\/file_diagnostics>/g,``).trim():``,Ee=(e,t)=>!e||typeof e!=`object`?String(e):T(e,t||``),q=e=>{if(typeof e==`string`){let t=e.trim();return t.length>0?t:void 0}if(e&&typeof e==`object`){let t=e.patch;if(typeof t==`string`){let e=t.trim();return e.length>0?e:void 0}}},De=e=>{if(!e||typeof e!=`object`)return;let t=q(e.patch)??q(e.diff);if(t)return t;let n=Array.isArray(e.files)?e.files:[];for(let e of n){if(!e||typeof e!=`object`)continue;let t=q(e.patch)??q(e.diff);if(t)return t}},Oe=e=>{if(!e||typeof e!=`string`)return{data:null,isJson:!1};let t=e.trim();if(!t.startsWith(`{`)&&!t.startsWith(`[`)||!t.endsWith(`}`)&&!t.endsWith(`]`)||t.length<2)return{data:null,isJson:!1};try{let e=JSON.parse(t);return typeof e==`object`&&e?{data:e,isJson:!0}:{data:null,isJson:!1}}catch{return{data:null,isJson:!1}}},ke=(e,t,n)=>{let r=Se(e);if((t===`edit`||t===`multiedit`||t===`write`||t===`apply_patch`)&&we(r)&&(r=Te(r)),(t===`edit`||t===`multiedit`||t===`apply_patch`)&&r.trim().length===0){let e=De(n);if(e)return e}return r},Ae=e=>{let t=e.match(/<type>(file|directory)<\/type>/i)?.[1]?.toLowerCase()??`unknown`,n=(e.match(/<content>([\s\S]*?)<\/content>/i)?.[1]??e).replace(/\r\n/g,`
2
2
  `).split(`
3
3
  `),r=e=>/\(\s*File has more lines\..*offset.*\)/i.test(e.trim());return{type:t,lines:n.map(e=>{let n=e.trim(),i=n.startsWith(`(`)&&n.endsWith(`)`)||r(n);if(t!==`directory`){let t=e.match(/^(\d+):\s?(.*)$/);if(t){let e=t[2],n=e.trim(),i=n.startsWith(`(`)&&n.endsWith(`)`)||r(n);return{lineNumber:i?null:Number(t[1]),text:e,isInfo:i}}}return{lineNumber:null,text:e,isInfo:i}}).filter((e,t,n)=>{if(e.text.trim().length>0)return!0;let r=n[t-1],i=n[t+1],a=!!(r?.isInfo||i?.isInfo),o=e.lineNumber!==null;return!(a&&o)})}},je=(e,n)=>{try{let r=e.trim().split(`
4
4
  `).filter(Boolean);if(r.length===0)return null;let i=[];return r.forEach(e=>{let t=e.match(/^(\s*)(.+)$/);if(t){let[,e,n]=t,r=Math.floor(e.length/2),a=!n.endsWith(`/`);i.push({name:n.replace(/\/$/,``),depth:r,isFile:a})}}),(0,A.jsx)(`div`,{className:f(`w-full min-w-0 font-mono space-y-0.5`,n?.unstyled?null:`p-3 bg-muted/20 rounded-xl border border-border/30`),style:t.tool.popup,children:i.map((e,t)=>(0,A.jsx)(`div`,{className:`min-w-0`,style:{paddingLeft:`${e.depth*20}px`},children:e.isFile?(0,A.jsx)(`span`,{className:`text-foreground/90 block truncate`,children:e.name}):(0,A.jsxs)(`span`,{className:`font-semibold text-foreground block truncate`,children:[e.name,`/`]})},t))})}catch{return null}},Me={backgroundColor:`var(--status-info)`,opacity:.6},Ne=(e,n,r)=>{try{let i=e.trim().split(`
package/dist/index.html CHANGED
@@ -552,7 +552,7 @@
552
552
  opacity: 0.72;
553
553
  }
554
554
  </style>
555
- <script type="module" crossorigin src="/assets/main-D08xX-l9.js"></script>
555
+ <script type="module" crossorigin src="/assets/main-CfHT5-XW.js"></script>
556
556
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
557
557
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
558
558
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
@@ -569,7 +569,7 @@
569
569
  <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
570
570
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
571
571
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
572
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
572
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-qlXnVd3m.js">
573
573
  <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
574
574
  </head>
575
575
  <body class="h-full bg-background text-foreground">
@@ -74,7 +74,7 @@
74
74
  }
75
75
  </style>
76
76
 
77
- <script type="module" crossorigin src="/assets/miniChat-S0KGzmRO.js"></script>
77
+ <script type="module" crossorigin src="/assets/miniChat-2PBRWMPo.js"></script>
78
78
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
79
79
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
80
80
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
@@ -91,7 +91,7 @@
91
91
  <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
92
92
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
93
93
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
94
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
94
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-qlXnVd3m.js">
95
95
  <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
96
96
  </head>
97
97
  <body class="h-full bg-background text-foreground">
package/dist/mobile.html CHANGED
@@ -63,7 +63,7 @@
63
63
  })();
64
64
  </script>
65
65
 
66
- <script type="module" crossorigin src="/assets/mobile-BBGkZDcd.js"></script>
66
+ <script type="module" crossorigin src="/assets/mobile-BllXjQxK.js"></script>
67
67
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
68
68
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CnHfUmDN.js">
69
69
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-B4dlGEM2.js">
@@ -80,7 +80,7 @@
80
80
  <link rel="modulepreload" crossorigin href="/assets/terminalApi-BpPeXWIu.js">
81
81
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
82
82
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
83
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-Cfrfl4hH.js">
83
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-qlXnVd3m.js">
84
84
  <link rel="stylesheet" crossorigin href="/assets/src-06zk77Ia.css">
85
85
  </head>
86
86
  <body class="h-full bg-background text-foreground">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openchambery/web",
3
- "version": "1.18.4-beta.15",
3
+ "version": "1.18.4-beta.16",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./server/index.js",
@@ -77,9 +77,10 @@ This module provides notification message preparation utilities for the web serv
77
77
  ### Emitter runtime API (emitter-runtime.js)
78
78
  - `createNotificationEmitterRuntime(dependencies)`: creates runtime for unified notification emission channels.
79
79
  - Returned API:
80
- - `writeSseEvent(res, payload)`
80
+ - `writeSseEvent(res, payload)` — best-effort SSE write with backpressure: when `res.write` returns `false`, the client is marked paused and further writes are skipped until `drain`; buffered bytes above `SSE_CLIENT_MAX_BUFFERED_BYTES` (2 MiB, aligned with relay-server) destroy the response. Authoritative data remains HTTP pull.
81
81
  - `emitDesktopNotification(payload)`
82
82
  - `broadcastUiNotification(payload)`
83
+ - Exported constant: `SSE_CLIENT_MAX_BUFFERED_BYTES`
83
84
 
84
85
  ### Template runtime API (template-runtime.js)
85
86
  - `createNotificationTemplateRuntime(dependencies)`: creates shared notification/template runtime. Model-backed summarization was retired after the Zen provider became unavailable.
@@ -1,3 +1,41 @@
1
+ // Align with relay-server per-connection queue cap (2 MiB).
2
+ export const SSE_CLIENT_MAX_BUFFERED_BYTES = 2 * 1024 * 1024;
3
+
4
+ const isSseResponseClosed = (res) => Boolean(res?.writableEnded || res?.destroyed);
5
+
6
+ const getSseBufferedBytes = (res) => {
7
+ if (typeof res?.writableLength === 'number' && Number.isFinite(res.writableLength)) {
8
+ return res.writableLength;
9
+ }
10
+ const tracked = res?.__sseBufferedBytes;
11
+ return typeof tracked === 'number' && Number.isFinite(tracked) ? tracked : 0;
12
+ };
13
+
14
+ const attachSseDrainListener = (res) => {
15
+ if (res.__sseDrainAttached) {
16
+ return;
17
+ }
18
+ res.__sseDrainAttached = true;
19
+ res.once('drain', () => {
20
+ res.__ssePaused = false;
21
+ res.__sseBufferedBytes = 0;
22
+ res.__sseDrainAttached = false;
23
+ res.__ssePausedHeartbeatCycles = 0;
24
+ });
25
+ };
26
+
27
+ // Intentional resource protection for slow/zombie SSE clients.
28
+ // SSE is best-effort; authoritative data is fetched over HTTP.
29
+ const destroySseClientForBackpressure = (res) => {
30
+ try {
31
+ if (!res.destroyed) {
32
+ res.destroy();
33
+ }
34
+ } catch {
35
+ // ignore — cleanup must stay idempotent
36
+ }
37
+ };
38
+
1
39
  export const createNotificationEmitterRuntime = (dependencies) => {
2
40
  const {
3
41
  process,
@@ -23,7 +61,46 @@ export const createNotificationEmitterRuntime = (dependencies) => {
23
61
  };
24
62
 
25
63
  const writeSseEvent = (res, payload) => {
26
- res.write(`data: ${JSON.stringify(payload)}\n\n`);
64
+ if (!res || isSseResponseClosed(res)) {
65
+ throw new Error('SSE response closed');
66
+ }
67
+
68
+ // Drop while backpressured — SSE is best-effort; authoritative data is HTTP pull.
69
+ if (res.__ssePaused) {
70
+ return false;
71
+ }
72
+
73
+ const data = `data: ${JSON.stringify(payload)}\n\n`;
74
+ const byteLength = Buffer.byteLength(data);
75
+
76
+ let ok;
77
+ try {
78
+ ok = res.write(data);
79
+ } catch (error) {
80
+ destroySseClientForBackpressure(res);
81
+ throw error;
82
+ }
83
+
84
+ const bufferedBytes = ok === false
85
+ ? Math.max(getSseBufferedBytes(res), (res.__sseBufferedBytes || 0) + byteLength)
86
+ : getSseBufferedBytes(res);
87
+ res.__sseBufferedBytes = bufferedBytes;
88
+
89
+ if (bufferedBytes > SSE_CLIENT_MAX_BUFFERED_BYTES) {
90
+ // Intentional resource protection: a slow client must not unbounded-buffer
91
+ // response body in host memory. SSE is best-effort; authoritative data is
92
+ // fetched over HTTP.
93
+ destroySseClientForBackpressure(res);
94
+ throw new Error('SSE client buffer exceeded');
95
+ }
96
+
97
+ if (ok === false) {
98
+ res.__ssePaused = true;
99
+ attachSseDrainListener(res);
100
+ return false;
101
+ }
102
+
103
+ return true;
27
104
  };
28
105
 
29
106
  const emitDesktopNotification = (payload) => {
@@ -1,6 +1,9 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
2
 
3
- import { createNotificationEmitterRuntime } from './emitter-runtime.js';
3
+ import {
4
+ createNotificationEmitterRuntime,
5
+ SSE_CLIENT_MAX_BUFFERED_BYTES,
6
+ } from './emitter-runtime.js';
4
7
 
5
8
  const createRuntime = (overrides = {}) => createNotificationEmitterRuntime({
6
9
  process: { stdout: { write: vi.fn() } },
@@ -11,6 +14,59 @@ const createRuntime = (overrides = {}) => createNotificationEmitterRuntime({
11
14
  ...overrides,
12
15
  });
13
16
 
17
+ const createMockSseResponse = ({ writeImpl } = {}) => {
18
+ const listeners = new Map();
19
+ let destroyed = false;
20
+ let writableEnded = false;
21
+ let bufferedBytes = 0;
22
+
23
+ const res = {
24
+ get destroyed() {
25
+ return destroyed;
26
+ },
27
+ get writableEnded() {
28
+ return writableEnded;
29
+ },
30
+ get writableLength() {
31
+ return bufferedBytes;
32
+ },
33
+ on(event, handler) {
34
+ listeners.set(event, handler);
35
+ return this;
36
+ },
37
+ once(event, handler) {
38
+ listeners.set(event, handler);
39
+ return this;
40
+ },
41
+ emit(event) {
42
+ const handler = listeners.get(event);
43
+ listeners.delete(event);
44
+ if (typeof handler === 'function') {
45
+ handler();
46
+ }
47
+ },
48
+ write(chunk) {
49
+ if (typeof writeImpl === 'function') {
50
+ return writeImpl(chunk, {
51
+ addBuffered(bytes) {
52
+ bufferedBytes += bytes;
53
+ },
54
+ getBuffered() {
55
+ return bufferedBytes;
56
+ },
57
+ });
58
+ }
59
+ return true;
60
+ },
61
+ destroy() {
62
+ destroyed = true;
63
+ this.emit('error');
64
+ },
65
+ };
66
+
67
+ return res;
68
+ };
69
+
14
70
  describe('notification emitter runtime', () => {
15
71
  it('reports desktop delivery through the injected native callback', () => {
16
72
  const onDesktopNotification = vi.fn();
@@ -44,4 +100,41 @@ describe('notification emitter runtime', () => {
44
100
  },
45
101
  });
46
102
  });
103
+
104
+ it('pauses slow SSE clients when write returns false and skips further buffering until drain', () => {
105
+ const runtime = createRuntime();
106
+ let writeCount = 0;
107
+ const res = createMockSseResponse({
108
+ writeImpl(chunk, { addBuffered }) {
109
+ writeCount += 1;
110
+ addBuffered(Buffer.byteLength(String(chunk)));
111
+ return false;
112
+ },
113
+ });
114
+
115
+ expect(runtime.writeSseEvent(res, { type: 'a' })).toBe(false);
116
+ expect(res.__ssePaused).toBe(true);
117
+ expect(writeCount).toBe(1);
118
+
119
+ expect(runtime.writeSseEvent(res, { type: 'b' })).toBe(false);
120
+ expect(writeCount).toBe(1);
121
+
122
+ res.emit('drain');
123
+ expect(res.__ssePaused).toBe(false);
124
+ expect(runtime.writeSseEvent(res, { type: 'c' })).toBe(false);
125
+ expect(writeCount).toBe(2);
126
+ });
127
+
128
+ it('destroys an SSE client whose buffered bytes exceed the per-client cap', () => {
129
+ const runtime = createRuntime();
130
+ const res = createMockSseResponse({
131
+ writeImpl(chunk, { addBuffered }) {
132
+ addBuffered(SSE_CLIENT_MAX_BUFFERED_BYTES + Buffer.byteLength(String(chunk)));
133
+ return false;
134
+ },
135
+ });
136
+
137
+ expect(() => runtime.writeSseEvent(res, { type: 'overflow' })).toThrow(/buffer exceeded/);
138
+ expect(res.destroyed).toBe(true);
139
+ });
47
140
  });
@@ -31,7 +31,10 @@ Server-owned scheduled task runtime and routes for OpenChamber-only automation.
31
31
  - Global run history list endpoint
32
32
  - Project scheduled task CRUD endpoints
33
33
  - Manual run endpoint
34
- - OpenChamber events SSE stream endpoint
34
+ - OpenChamber events SSE stream endpoint (`GET /api/openchamber/events`): 25s
35
+ heartbeat interval unchanged; half-open clients that stay paused across two
36
+ consecutive heartbeat cycles are destroyed and removed from the client set
37
+ (idempotent cleanup). SSE is best-effort; authoritative data is HTTP pull.
35
38
  - Returns persisted mutation results with `schedulerSynced`; a failed scheduler
36
39
  sync schedules one bounded retry while preserving the committed response
37
40
 
@@ -321,6 +321,33 @@ export const registerScheduledTaskRoutes = (app, dependencies) => {
321
321
  const clients = getOpenChamberEventClients();
322
322
  clients.add(res);
323
323
 
324
+ let closed = false;
325
+ let heartbeatTimer = null;
326
+ // Half-open / stalled-drain eviction: destroy after this many consecutive
327
+ // heartbeat cycles while the socket remains paused (no drain). Interval
328
+ // itself is unchanged — only failure cleanup was added.
329
+ // SSE is best-effort; authoritative data is fetched over HTTP.
330
+ const maxPausedHeartbeatCycles = 2;
331
+
332
+ const cleanup = () => {
333
+ if (closed) {
334
+ return;
335
+ }
336
+ closed = true;
337
+ if (heartbeatTimer) {
338
+ clearInterval(heartbeatTimer);
339
+ heartbeatTimer = null;
340
+ }
341
+ clients.delete(res);
342
+ try {
343
+ if (!res.destroyed && !res.writableEnded) {
344
+ res.destroy();
345
+ }
346
+ } catch {
347
+ // ignore — destroy + delete must stay idempotent
348
+ }
349
+ };
350
+
324
351
  try {
325
352
  writeSseEvent(res, {
326
353
  type: 'openchamber:event-stream-ready',
@@ -329,25 +356,41 @@ export const registerScheduledTaskRoutes = (app, dependencies) => {
329
356
  },
330
357
  });
331
358
  } catch {
359
+ cleanup();
360
+ return;
332
361
  }
333
362
 
334
- const heartbeat = setInterval(() => {
363
+ heartbeatTimer = setInterval(() => {
364
+ if (closed || res.writableEnded || res.destroyed) {
365
+ cleanup();
366
+ return;
367
+ }
368
+
335
369
  try {
336
- writeSseEvent(res, {
370
+ const ok = writeSseEvent(res, {
337
371
  type: 'openchamber:heartbeat',
338
372
  properties: {
339
373
  timestamp: Date.now(),
340
374
  },
341
375
  });
376
+ if (ok === false || res.__ssePaused) {
377
+ const cycles = (res.__ssePausedHeartbeatCycles || 0) + 1;
378
+ res.__ssePausedHeartbeatCycles = cycles;
379
+ if (cycles >= maxPausedHeartbeatCycles) {
380
+ // Intentional half-open cleanup: TCP may still look open while the
381
+ // relay tunnel is dead and drain never fires. SSE is best-effort;
382
+ // authoritative data is fetched over HTTP.
383
+ cleanup();
384
+ }
385
+ return;
386
+ }
387
+ res.__ssePausedHeartbeatCycles = 0;
342
388
  } catch {
343
- clearInterval(heartbeat);
344
- clients.delete(res);
389
+ cleanup();
345
390
  }
346
391
  }, 25_000);
347
392
 
348
- req.on('close', () => {
349
- clearInterval(heartbeat);
350
- clients.delete(res);
351
- });
393
+ req.on('close', cleanup);
394
+ res.on('error', cleanup);
352
395
  });
353
396
  };