@openchambery/web 2.0.0-beta.3 → 2.0.0-beta.4

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 (87) hide show
  1. package/dist/assets/{AgentAvatar-B_JQoreg.js → AgentAvatar-Q1SmFRx2.js} +1 -1
  2. package/dist/assets/AssistantView-CwXkiCAd.js +3 -0
  3. package/dist/assets/{DiagramView-BNnda8qO.js → DiagramView-BW92schO.js} +1 -1
  4. package/dist/assets/{FadeInOnReveal-VYQTSAkr.js → FadeInOnReveal-BZmwl-zE.js} +1 -1
  5. package/dist/assets/{Icon-BiEQEcih.js → Icon-AQPvxMiU.js} +1 -1
  6. package/dist/assets/{MarkdownRenderer-CJHSsWin.js → MarkdownRenderer-Bv05iDZZ.js} +2 -2
  7. package/dist/assets/{MarkdownRendererImpl-DwrHFGUp.js → MarkdownRendererImpl-C81xqYib.js} +1 -1
  8. package/dist/assets/{MarkstreamRendererImpl-CSnbQMu3.js → MarkstreamRendererImpl-CXUCQuKJ.js} +1 -1
  9. package/dist/assets/{MobileDetailNavigation-BXr6AGLT.js → MobileDetailNavigation-BMgIu7zc.js} +1 -1
  10. package/dist/assets/{MobileShareBridge-D7OE9OP_.js → MobileShareBridge-BOXGNHmC.js} +2 -2
  11. package/dist/assets/MobileSurface-xuc_z0_G.js +2 -0
  12. package/dist/assets/{MultiRunWindow-DF3iIFCd.js → MultiRunWindow-B5At2Z95.js} +1 -1
  13. package/dist/assets/{OnboardingScreen-BjHmlwlw.js → OnboardingScreen-bsPLgz4r.js} +1 -1
  14. package/dist/assets/{OverlayScrollbar-DLtWO_Gp.js → OverlayScrollbar-4wp4migh.js} +1 -1
  15. package/dist/assets/{SettingsView-BRxELjow.js → SettingsView-CJ6tcH5_.js} +11 -11
  16. package/dist/assets/{SettingsWindow-BI5swspb.js → SettingsWindow-CMtX2bMl.js} +1 -1
  17. package/dist/assets/{TerminalView-BU3x8-fr.js → TerminalView-Dvr-ysTS.js} +1 -1
  18. package/dist/assets/{ToolOutputDialog-BEWhBcRd.js → ToolOutputDialog-uH1ZZDSS.js} +1 -1
  19. package/dist/assets/{appThemeRegistry-4MR0F7Jz.js → appThemeRegistry-DK7q2juD.js} +1 -1
  20. package/dist/assets/{assistant-attachment-cache-C0aRnFkj.js → assistant-attachment-cache-DphJleHr.js} +1 -1
  21. package/dist/assets/{button-DKuz3L8l.js → button-CcNJUxUd.js} +1 -1
  22. package/dist/assets/{collapsible-DXbDynN4.js → collapsible-ZmZ6rLWs.js} +2 -2
  23. package/dist/assets/{context-menu-CqolsLCm.js → context-menu-B2LXJgXL.js} +1 -1
  24. package/dist/assets/{desktopHosts-CoDkOnyS.js → desktopHosts-C6HrP0jq.js} +1 -1
  25. package/dist/assets/{desktopRelayRestore-DDlVKyOE.js → desktopRelayRestore-DdVBp45U.js} +1 -1
  26. package/dist/assets/{diagram-D7T8HQgj.js → diagram-CxTs9hCQ.js} +1 -1
  27. package/dist/assets/{dialog-DQYl3W_o.js → dialog-KMVL9QKF.js} +1 -1
  28. package/dist/assets/{fileMentionTouchSelection-BZ6ovBYH.js → fileMentionTouchSelection-7RIwlpkB.js} +1 -1
  29. package/dist/assets/{fileQueries-JrpcsOCs.js → fileQueries-CjdBRy8y.js} +1 -1
  30. package/dist/assets/{gitApi-CM42qUed.js → gitApi-yuWg9BN4.js} +3 -3
  31. package/dist/assets/{imageSource-CIl0FL10.js → imageSource-9vQBq3zp.js} +1 -1
  32. package/dist/assets/{input-CzQy8UhV.js → input-CrIvk3HZ.js} +1 -1
  33. package/dist/assets/insertionBoundaries-BiUCSkx-.js +1 -0
  34. package/dist/assets/{main-BeveiW6F.js → main-C9mIBo77.js} +2 -2
  35. package/dist/assets/main-DiL6w6KF.js +169 -0
  36. package/dist/assets/{markdownHeightCache-Cj1I5NDw.js → markdownHeightCache-BmXVY_gc.js} +1 -1
  37. package/dist/assets/{mcpQueries-D5mQymgM.js → mcpQueries-C7jknHV8.js} +1 -1
  38. package/dist/assets/{miniChat-BgrzM3u7.js → miniChat-CwtUaElU.js} +2 -2
  39. package/dist/assets/{mobile-DtYoQE8C.js → mobile-DB-6--ws.js} +2 -2
  40. package/dist/assets/{multirun-jy8dEI96.js → multirun-TAsxFI8e.js} +2 -2
  41. package/dist/assets/{persistence-C9LQpiOS.js → persistence-56kq8Z4V.js} +1 -1
  42. package/dist/assets/{platform-BQghHRfp.js → platform-C13fMVEs.js} +3 -3
  43. package/dist/assets/{relay-image-stream-DM7atqJs.js → relay-image-stream-DrdVj99c.js} +1 -1
  44. package/dist/assets/{renderElectronMiniChatApp-BGrrmeME.js → renderElectronMiniChatApp-CGj0MNRU.js} +2 -2
  45. package/dist/assets/renderMobileApp-CGMMqbsO.js +28 -0
  46. package/dist/assets/runtime-fetch-Fs9ZV2V8.js +1 -0
  47. package/dist/assets/{runtimeConfig-BIGBRGQI.js → runtimeConfig-BEANkvOd.js} +1 -1
  48. package/dist/assets/runtimeEndpointReset-A_ZBUJFS.js +147 -0
  49. package/dist/assets/{sessionChangeSummary-eIbpSfrO.js → sessionChangeSummary-qOLrP9fw.js} +1 -1
  50. package/dist/assets/{sessionLookup-myHe5ltu.js → sessionLookup-34XFmP9C.js} +1 -1
  51. package/dist/assets/{sortable-tabs-strip-BQtmHx9r.js → sortable-tabs-strip-DyEV0Heg.js} +1 -1
  52. package/dist/assets/src-ubCWXZhR.css +2 -0
  53. package/dist/assets/{terminalApi-BxcdiduX.js → terminalApi-CXaBEoa_.js} +1 -1
  54. package/dist/assets/textarea-BBOlRI9O.js +1 -0
  55. package/dist/assets/{tooltip-Cx5gTbdY.js → tooltip-CPI4fr1a.js} +1 -1
  56. package/dist/assets/{url-CDHnjlsm.js → url-DRDQXjyX.js} +1 -1
  57. package/dist/assets/{useAppFontEffects-CNeo0aZs.js → useAppFontEffects-CiDe42I5.js} +52 -52
  58. package/dist/assets/{useDesktopWindowControlsLayout-DBJ56qIo.js → useDesktopWindowControlsLayout-BlizAlOt.js} +1 -1
  59. package/dist/assets/{useEffectiveDirectory-B4LvR8Gt.js → useEffectiveDirectory-C_CouL5v.js} +1 -1
  60. package/dist/assets/{useFontPreferences-CUnQ4TVm.js → useFontPreferences-B0oUZAiB.js} +1 -1
  61. package/dist/assets/useMobileNavigationStore-DfPClaW-.js +414 -0
  62. package/dist/assets/{useSessionAutoCleanup-BIVmrnYU.js → useSessionAutoCleanup-DtrfbxAp.js} +2 -2
  63. package/dist/assets/{useWorkerHighlightedLines-CJZbJDW3.js → useWorkerHighlightedLines-CPNYz6Wf.js} +1 -1
  64. package/dist/index.html +9 -9
  65. package/dist/mini-chat.html +9 -9
  66. package/dist/mobile.html +9 -9
  67. package/package.json +1 -1
  68. package/server/lib/event-stream/DOCUMENTATION.md +3 -1
  69. package/server/lib/event-stream/reasoning-projection.js +16 -1
  70. package/server/lib/event-stream/reasoning-projection.test.js +15 -0
  71. package/server/lib/notifications/runtime.js +18 -5
  72. package/server/lib/notifications/runtime.test.js +11 -0
  73. package/server/lib/opencode/DOCUMENTATION.md +4 -0
  74. package/server/lib/opencode/config-entity-routes.js +6 -1
  75. package/server/lib/opencode/config-entity-routes.test.js +25 -0
  76. package/server/lib/opencode/proxy.js +3 -0
  77. package/server/lib/opencode/proxy.test.js +15 -0
  78. package/dist/assets/AssistantView-ClQAfGOT.js +0 -3
  79. package/dist/assets/MobileSurface-D2jUkX9l.js +0 -2
  80. package/dist/assets/insertionBoundaries-CtkZ9720.js +0 -1
  81. package/dist/assets/main-BILgBI3B.js +0 -169
  82. package/dist/assets/renderMobileApp-u3c4GtFC.js +0 -28
  83. package/dist/assets/runtime-fetch-zIalUnbb.js +0 -1
  84. package/dist/assets/runtimeEndpointReset-D2savkuw.js +0 -147
  85. package/dist/assets/src-CLN7Z-zx.css +0 -2
  86. package/dist/assets/textarea-CakKvqFw.js +0 -1
  87. package/dist/assets/useMobileNavigationStore-ZHJPxlHt.js +0 -414
@@ -1,4 +1,4 @@
1
- import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{n as t}from"./runtime-fetch-zIalUnbb.js";import{Cn as n,tn as r}from"./persistence-C9LQpiOS.js";import{nt as i,rt as a}from"./vendor-base-ui-CDjyofeD.js";import{n as o}from"./platform-BQghHRfp.js";import{_ as s}from"./useUIStore-CQYKJnrg.js";import{n as c}from"./vendor-react-C94A0AHl.js";import{a as l,n as u}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{f as d,r as f,t as p}from"./button-DKuz3L8l.js";import{n as m}from"./Icon-BiEQEcih.js";import{i as h,n as g,t as _}from"./tooltip-Cx5gTbdY.js";import{n as v}from"./useThemeSystem-BlNUWH47.js";import{n as y}from"./markdownTheme-CKac3wKC.js";import{n as b}from"./MarkdownRenderer-CJHSsWin.js";import{n as x,o as S,s as C,t as w}from"./markdown-worker-bS5OgGO3.js";import{a as T,i as E,o as D,t as ee}from"./imageSource-CIl0FL10.js";import{t as te}from"./vendor-tanstack-react-virtual-B2kV6cnT.js";var O=e(a(),1),k=c(),A=i(),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)(m,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(m,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(m,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let p=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]!==p||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:p})}),t[7]=p,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=l(`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 ee(e,t??new AbortController().signal),await G(n,t)}finally{n&&T(n)}},he=async(e,n)=>{let r=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,n)}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,n);else{let e=D(a,r);if(E(e))try{i=await me(e.path,n)}catch{let r=await t(`/api/fs/raw`,{method:`GET`,cache:`no-store`,query:{path:e.path},signal:n});if(!r.ok)throw Error(`Image source request failed with status ${r.status}`);i=await r.blob()}else i=await G(e.source,n)}}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=()=>!o()||u===void 0?!1:u.isPluginAvailable(`OpenChamberMedia`),_e=async(e,t)=>{let{blob:i,filename:a,mimeType:o}=await he(e,t);if(ge()){let e=await de(i);return await V.saveImage({dataBase64:e,mimeType:o,filename:a}),`saved`}if(r()){let e=n()?.vscode;if(e?.saveImage){let t=await W(i);return await e.saveImage({fileName:a,dataUrl:t}),`saved`}}return fe(i,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=y(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 w(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 b;t[13]===i?b=t[14]:(b=f(`typography-code`,i),t[13]=i,t[14]=b);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]!==b||t[19]!==S?(C=(0,A.jsx)(`div`,{ref:u,className:b,style:S}),t[18]=b,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):C(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{n as t}from"./runtime-fetch-Fs9ZV2V8.js";import{Cn as n,tn as r}from"./persistence-56kq8Z4V.js";import{nt as i,rt as a}from"./vendor-base-ui-CDjyofeD.js";import{n as o}from"./platform-C13fMVEs.js";import{_ as s}from"./useUIStore-CQYKJnrg.js";import{n as c}from"./vendor-react-C94A0AHl.js";import{a as l,n as u}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{f as d,r as f,t as p}from"./button-CcNJUxUd.js";import{n as m}from"./Icon-AQPvxMiU.js";import{i as h,n as g,t as _}from"./tooltip-CPI4fr1a.js";import{n as v}from"./useThemeSystem-BlNUWH47.js";import{n as y}from"./markdownTheme-CKac3wKC.js";import{n as b}from"./MarkdownRenderer-Bv05iDZZ.js";import{n as x,o as S,s as C,t as w}from"./markdown-worker-bS5OgGO3.js";import{a as T,i as E,o as D,t as ee}from"./imageSource-9vQBq3zp.js";import{t as te}from"./vendor-tanstack-react-virtual-B2kV6cnT.js";var O=e(a(),1),k=c(),A=i(),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)(m,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(m,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(m,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let p=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]!==p||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:p})}),t[7]=p,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=l(`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 ee(e,t??new AbortController().signal),await G(n,t)}finally{n&&T(n)}},he=async(e,n)=>{let r=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,n)}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,n);else{let e=D(a,r);if(E(e))try{i=await me(e.path,n)}catch{let r=await t(`/api/fs/raw`,{method:`GET`,cache:`no-store`,query:{path:e.path},signal:n});if(!r.ok)throw Error(`Image source request failed with status ${r.status}`);i=await r.blob()}else i=await G(e.source,n)}}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=()=>!o()||u===void 0?!1:u.isPluginAvailable(`OpenChamberMedia`),_e=async(e,t)=>{let{blob:i,filename:a,mimeType:o}=await he(e,t);if(ge()){let e=await de(i);return await V.saveImage({dataBase64:e,mimeType:o,filename:a}),`saved`}if(r()){let e=n()?.vscode;if(e?.saveImage){let t=await W(i);return await e.saveImage({fileName:a,dataUrl:t}),`saved`}}return fe(i,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=y(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 w(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 b;t[13]===i?b=t[14]:(b=f(`typography-code`,i),t[13]=i,t[14]=b);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]!==b||t[19]!==S?(C=(0,A.jsx)(`div`,{ref:u,className:b,style:S}),t[18]=b,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):C(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,t)=>{try{let n=e.trim().split(`
4
4
  `).filter(Boolean);if(n.length===0)return null;let r=[];return n.forEach(e=>{let t=e.match(/^(\s*)(.+)$/);if(t){let[,e,n]=t,i=Math.floor(e.length/2),a=!n.endsWith(`/`);r.push({name:n.replace(/\/$/,``),depth:i,isFile:a})}}),(0,A.jsx)(`div`,{className:f(`w-full min-w-0 font-mono space-y-0.5`,t?.unstyled?null:`p-3 bg-muted/20 rounded-xl border border-border/30`),style:s.tool.popup,children:r.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,t,n)=>{try{let r=e.trim().split(`
package/dist/index.html CHANGED
@@ -552,28 +552,28 @@
552
552
  opacity: 0.72;
553
553
  }
554
554
  </style>
555
- <script type="module" crossorigin src="/assets/main-BeveiW6F.js"></script>
555
+ <script type="module" crossorigin src="/assets/main-C9mIBo77.js"></script>
556
556
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
557
557
  <link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
558
558
  <link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
559
- <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
559
+ <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-Fs9ZV2V8.js">
560
560
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CDjyofeD.js">
561
561
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BqLKf6ZY.js">
562
562
  <link rel="modulepreload" crossorigin href="/assets/useUIStore-CQYKJnrg.js">
563
563
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-C94A0AHl.js">
564
564
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
565
565
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
566
- <link rel="modulepreload" crossorigin href="/assets/persistence-C9LQpiOS.js">
567
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-CoDkOnyS.js">
568
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DDlVKyOE.js">
566
+ <link rel="modulepreload" crossorigin href="/assets/persistence-56kq8Z4V.js">
567
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-C6HrP0jq.js">
568
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DdVBp45U.js">
569
569
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BOe2qpQb.js">
570
570
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
571
- <link rel="modulepreload" crossorigin href="/assets/platform-BQghHRfp.js">
572
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-BxcdiduX.js">
571
+ <link rel="modulepreload" crossorigin href="/assets/platform-C13fMVEs.js">
572
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-CXaBEoa_.js">
573
573
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
574
574
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
575
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BIGBRGQI.js">
576
- <link rel="stylesheet" crossorigin href="/assets/src-CLN7Z-zx.css">
575
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BEANkvOd.js">
576
+ <link rel="stylesheet" crossorigin href="/assets/src-ubCWXZhR.css">
577
577
  </head>
578
578
  <body class="h-full bg-background text-foreground">
579
579
  <!-- Keep the startup layer outside #root. React replaces every child of
@@ -74,28 +74,28 @@
74
74
  }
75
75
  </style>
76
76
 
77
- <script type="module" crossorigin src="/assets/miniChat-BgrzM3u7.js"></script>
77
+ <script type="module" crossorigin src="/assets/miniChat-CwtUaElU.js"></script>
78
78
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
79
79
  <link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
80
80
  <link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
81
- <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
81
+ <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-Fs9ZV2V8.js">
82
82
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CDjyofeD.js">
83
83
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BqLKf6ZY.js">
84
84
  <link rel="modulepreload" crossorigin href="/assets/useUIStore-CQYKJnrg.js">
85
85
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-C94A0AHl.js">
86
86
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
87
87
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
88
- <link rel="modulepreload" crossorigin href="/assets/persistence-C9LQpiOS.js">
89
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-CoDkOnyS.js">
90
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DDlVKyOE.js">
88
+ <link rel="modulepreload" crossorigin href="/assets/persistence-56kq8Z4V.js">
89
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-C6HrP0jq.js">
90
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DdVBp45U.js">
91
91
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BOe2qpQb.js">
92
92
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
93
- <link rel="modulepreload" crossorigin href="/assets/platform-BQghHRfp.js">
94
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-BxcdiduX.js">
93
+ <link rel="modulepreload" crossorigin href="/assets/platform-C13fMVEs.js">
94
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-CXaBEoa_.js">
95
95
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
96
96
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
97
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BIGBRGQI.js">
98
- <link rel="stylesheet" crossorigin href="/assets/src-CLN7Z-zx.css">
97
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BEANkvOd.js">
98
+ <link rel="stylesheet" crossorigin href="/assets/src-ubCWXZhR.css">
99
99
  </head>
100
100
  <body class="h-full bg-background text-foreground">
101
101
  <div id="root" class="h-full">
package/dist/mobile.html CHANGED
@@ -63,28 +63,28 @@
63
63
  })();
64
64
  </script>
65
65
 
66
- <script type="module" crossorigin src="/assets/mobile-DtYoQE8C.js"></script>
66
+ <script type="module" crossorigin src="/assets/mobile-DB-6--ws.js"></script>
67
67
  <link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-C0FnF6B9.js">
68
68
  <link rel="modulepreload" crossorigin href="/assets/runtime-auth-D66yq6ie.js">
69
69
  <link rel="modulepreload" crossorigin href="/assets/runtime-switch-LvWDU-SL.js">
70
- <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-zIalUnbb.js">
70
+ <link rel="modulepreload" crossorigin href="/assets/runtime-fetch-Fs9ZV2V8.js">
71
71
  <link rel="modulepreload" crossorigin href="/assets/vendor-base-ui-CDjyofeD.js">
72
72
  <link rel="modulepreload" crossorigin href="/assets/vendor-zustand-BqLKf6ZY.js">
73
73
  <link rel="modulepreload" crossorigin href="/assets/useUIStore-CQYKJnrg.js">
74
74
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-C94A0AHl.js">
75
75
  <link rel="modulepreload" crossorigin href="/assets/vendor-pathe-vBmvQE8f.js">
76
76
  <link rel="modulepreload" crossorigin href="/assets/vendor-tanstack-query-core-BWz0ose6.js">
77
- <link rel="modulepreload" crossorigin href="/assets/persistence-C9LQpiOS.js">
78
- <link rel="modulepreload" crossorigin href="/assets/desktopHosts-CoDkOnyS.js">
79
- <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DDlVKyOE.js">
77
+ <link rel="modulepreload" crossorigin href="/assets/persistence-56kq8Z4V.js">
78
+ <link rel="modulepreload" crossorigin href="/assets/desktopHosts-C6HrP0jq.js">
79
+ <link rel="modulepreload" crossorigin href="/assets/desktopRelayRestore-DdVBp45U.js">
80
80
  <link rel="modulepreload" crossorigin href="/assets/vendor-opencode-client-BOe2qpQb.js">
81
81
  <link rel="modulepreload" crossorigin href="/assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js">
82
- <link rel="modulepreload" crossorigin href="/assets/platform-BQghHRfp.js">
83
- <link rel="modulepreload" crossorigin href="/assets/terminalApi-BxcdiduX.js">
82
+ <link rel="modulepreload" crossorigin href="/assets/platform-C13fMVEs.js">
83
+ <link rel="modulepreload" crossorigin href="/assets/terminalApi-CXaBEoa_.js">
84
84
  <link rel="modulepreload" crossorigin href="/assets/types-BuiqMmh_.js">
85
85
  <link rel="modulepreload" crossorigin href="/assets/capgoAdapter-DCowZ2ab.js">
86
- <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BIGBRGQI.js">
87
- <link rel="stylesheet" crossorigin href="/assets/src-CLN7Z-zx.css">
86
+ <link rel="modulepreload" crossorigin href="/assets/runtimeConfig-BEANkvOd.js">
87
+ <link rel="stylesheet" crossorigin href="/assets/src-ubCWXZhR.css">
88
88
  </head>
89
89
  <body class="h-full bg-background text-foreground">
90
90
  <div id="root" class="h-full"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openchambery/web",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./server/index.js",
@@ -33,7 +33,7 @@ The following APIs are exported by their owning modules. `event-stream/index.js`
33
33
  ### Reasoning projection helpers (`reasoning-projection.js`)
34
34
  Import from the module file (not the event-stream barrel). Public surface:
35
35
  - `shouldIncludeReasoning` / `readIncludeReasoningQuery` / `readIncludeReasoningFromUrl` / `stripIncludeReasoningParam`
36
- - `projectMessagesPayloadForReasoning` / `projectMessagesPayloadWithoutReasoning` — array / `{ records }` / `{ record }` / `{ parts }` only
36
+ - `projectMessagesPayloadForReasoning` / `projectMessagesPayloadWithoutReasoning` — array / `{ records }` / `{ record }` / `{ parts }`, plus native v2 `{ data }` list/context envelopes and assistant `content[]`. Filtering preserves message identities, cursor, text/tool content and token totals.
37
37
  - `createReasoningOutboundFilter` — per-connection stream filter (version-suffix-aware type match; preserves original `type` on kept events)
38
38
  - `filterSseBlock` / `createSseBlockSplitter` — SSE disabled path (CR-safe chunk boundaries)
39
39
 
@@ -49,6 +49,8 @@ Import from the module file (not the event-stream barrel). Public surface:
49
49
  - `createUpstreamSseReader(...)`: creates a start/stop reader for OpenCode SSE streams. The reader parses SSE blocks, tracks the latest `Last-Event-ID`, reconnects after closed or stalled upstream streams, and reports events through callbacks.
50
50
 
51
51
  ## Runtime behavior
52
+
53
+ Native v2 `session.reasoning.*` events are filtered at the same outbound boundary as legacy `session.next.reasoning.*`. Both `/api/session/:id/message` and `/api/session/:id/context` use the snapshot projection before relay encryption.
52
54
  - Browser clients connect to the WS endpoints above.
53
55
  - OpenChamber still fetches OpenCode upstream event streams over SSE.
54
56
  - The web server creates one shared global message-stream hub. OpenCode watcher side effects and global WS clients subscribe to that hub, so there is one upstream `/global/event` SSE reader for both server-side processing and browser fan-out.
@@ -96,6 +96,10 @@ function projectParts(parts) {
96
96
  * @param {unknown} record
97
97
  */
98
98
  function projectRecord(record) {
99
+ if (isPlainObject(record) && record.type === 'assistant' && Array.isArray(record.content)) {
100
+ const content = projectParts(record.content);
101
+ return content === record.content ? record : { ...record, content };
102
+ }
99
103
  if (!isPlainObject(record) || !Array.isArray(record.parts)) return record;
100
104
  const parts = projectParts(record.parts);
101
105
  return parts === record.parts ? record : { ...record, parts };
@@ -126,6 +130,17 @@ export function projectMessagesPayloadWithoutReasoning(payload) {
126
130
  let next = payload;
127
131
  let changed = false;
128
132
 
133
+ if (Array.isArray(payload.data)) {
134
+ const data = projectMessagesPayloadWithoutReasoning(payload.data);
135
+ if (data !== payload.data) {
136
+ next = { ...next, data };
137
+ changed = true;
138
+ }
139
+ }
140
+ if (payload.type === 'assistant' && Array.isArray(payload.content)) {
141
+ return projectRecord(payload);
142
+ }
143
+
129
144
  if (Array.isArray(payload.records)) {
130
145
  const records = projectMessagesPayloadWithoutReasoning(payload.records);
131
146
  if (records !== payload.records) {
@@ -222,7 +237,7 @@ export function createReasoningOutboundFilter() {
222
237
  const type = baseEventType(rawType);
223
238
 
224
239
  // session.next.reasoning.* (incl. versioned …reasoning.delta.1)
225
- if (type.startsWith('session.next.reasoning.')) return null;
240
+ if (type.startsWith('session.next.reasoning.') || type.startsWith('session.reasoning.')) return null;
226
241
 
227
242
  if (type === 'message.part.updated') {
228
243
  const body = eventBodyOf(payload);
@@ -13,6 +13,21 @@ import {
13
13
  } from './reasoning-projection.js';
14
14
 
15
15
  describe('shouldIncludeReasoning / query helpers', () => {
16
+ it('projects v2 list/context and exact snapshots without dropping rows or cursor', () => {
17
+ const row = { id: 'm', type: 'assistant', tokens: { reasoning: 12 }, content: [
18
+ { type: 'reasoning', text: 'hidden' }, { type: 'text', text: 'visible' },
19
+ ] };
20
+ const payload = { data: [row], cursor: { next: 'older' } };
21
+ const projected = projectMessagesPayloadForReasoning(payload, false);
22
+ expect(projected).toEqual({ data: [{ ...row, content: [row.content[1]] }], cursor: payload.cursor });
23
+ expect(projectMessagesPayloadForReasoning(row, false)).toEqual(projected.data[0]);
24
+ expect(projectMessagesPayloadForReasoning(payload, true)).toBe(payload);
25
+ expect(row.content).toHaveLength(2);
26
+ const filter = createReasoningOutboundFilter();
27
+ expect(filter.projectEvent({ type: 'session.reasoning.delta.1', data: { delta: 'hidden' } })).toBeNull();
28
+ const text = { type: 'session.text.delta', data: { delta: 'visible' } };
29
+ expect(filter.projectEvent(text)).toBe(text);
30
+ });
16
31
  it('only treats the strict string false as disabled', () => {
17
32
  expect(shouldIncludeReasoning(undefined)).toBe(true);
18
33
  expect(shouldIncludeReasoning(null)).toBe(true);
@@ -346,7 +346,9 @@ export const createNotificationTriggerRuntime = (deps) => {
346
346
 
347
347
  const extractSessionIdFromPayload = (payload) => {
348
348
  if (!payload || typeof payload !== 'object') return null;
349
- const props = payload.properties;
349
+ const props = payload.properties && typeof payload.properties === 'object'
350
+ ? payload.properties
351
+ : (payload.data && typeof payload.data === 'object' ? payload.data : null);
350
352
  const info = props?.info;
351
353
  const sessionId =
352
354
  info?.sessionID ??
@@ -417,20 +419,31 @@ export const createNotificationTriggerRuntime = (deps) => {
417
419
  const reason = payload.properties?.reason ?? payload.data?.reason;
418
420
  if (reason === 'shutdown') return;
419
421
  }
420
- if ((payload.type === 'session.idle' || payload.type === 'session.error') && sessionId) {
421
- const error = payload.properties?.error;
422
+ // v2 completion is session.execution.succeeded. session.idle is a deprecated
423
+ // fallback; the ready-notification cooldown below collapses the pair.
424
+ if ((
425
+ payload.type === 'session.idle'
426
+ || payload.type === 'session.execution.succeeded'
427
+ || payload.type === 'session.error'
428
+ || payload.type === 'session.execution.failed'
429
+ ) && sessionId) {
430
+ const body = payload.properties && typeof payload.properties === 'object'
431
+ ? payload.properties
432
+ : (payload.data && typeof payload.data === 'object' ? payload.data : {});
433
+ const error = body?.error;
422
434
  const errorText = typeof error?.message === 'string'
423
435
  ? error.message
424
436
  : typeof error === 'string' ? error : '';
437
+ const failed = payload.type === 'session.error' || payload.type === 'session.execution.failed';
425
438
  await maybeSendPushForTrigger({
426
439
  ...payload,
427
440
  type: 'message.updated',
428
441
  properties: {
429
- ...payload.properties,
442
+ ...(payload.properties && typeof payload.properties === 'object' ? payload.properties : body),
430
443
  info: {
431
444
  sessionID: sessionId,
432
445
  role: 'assistant',
433
- finish: payload.type === 'session.error' ? 'error' : 'stop',
446
+ finish: failed ? 'error' : 'stop',
434
447
  ...(errorText ? { parts: [{ type: 'text', text: errorText }] } : {}),
435
448
  },
436
449
  },
@@ -457,6 +457,17 @@ describe('contact turn notifications', () => {
457
457
  });
458
458
 
459
459
  describe('notification trigger live activity end', () => {
460
+ it('treats session.execution.succeeded as completion, including a v2 data envelope', async () => {
461
+ vi.stubGlobal('fetch', vi.fn(async () => rootSessionResponse('ses_done')));
462
+ const { runtime, sendLiveActivityEnd, emitDesktopNotification } = createRuntime();
463
+ await runtime.maybeSendPushForTrigger({
464
+ type: 'session.execution.succeeded',
465
+ data: { sessionID: 'ses_done' },
466
+ });
467
+ expect(sendLiveActivityEnd).toHaveBeenCalledWith({ sessionId: 'ses_done', status: 'complete' });
468
+ expect(emitDesktopNotification).toHaveBeenCalled();
469
+ });
470
+
460
471
  it('ends the live activity on top-level completion and error', async () => {
461
472
  vi.stubGlobal('fetch', vi.fn(async () => rootSessionResponse()));
462
473
  const { runtime, sendLiveActivityEnd } = createRuntime();
@@ -305,6 +305,10 @@ configuration reload uses official SDK `location.reload`. The historical
305
305
  `/api/config/reload` host/bridge endpoint remains reserved for existing process
306
306
  startup/recovery/binary-change callers, not ordinary Settings mutations.
307
307
 
308
+ Command catalog SDK fetch forwarding preserves the generated request options,
309
+ including authentication headers, and combines caller cancellation with its
310
+ eight-second request deadline.
311
+
308
312
  `config-hot-reload.integration.test.js` is opt-in via
309
313
  `OPENCHAMBER_TEST_OPENCODE_BINARY=<absolute-v2-cli>`. It starts a separate loopback
310
314
  server with isolated HOME/XDG/config/database, checks global command changes,
@@ -531,7 +531,12 @@ export const registerConfigEntityRoutes = (app, dependencies) => {
531
531
  const client = createOpenCodeClient({
532
532
  baseUrl: buildOpenCodeUrl('/', '').replace(/\/$/, ''),
533
533
  headers: getOpenCodeAuthHeaders(),
534
- fetch: (request) => fetch(request, { signal: AbortSignal.timeout(8_000) }),
534
+ fetch: (request, init) => fetch(request, {
535
+ ...init,
536
+ signal: init?.signal
537
+ ? AbortSignal.any([init.signal, AbortSignal.timeout(8_000)])
538
+ : AbortSignal.timeout(8_000),
539
+ }),
535
540
  });
536
541
  const response = await client.command.list({ location: { directory } });
537
542
  if (!Array.isArray(response?.data)) {
@@ -69,6 +69,31 @@ describe('V2 configuration persistence', () => {
69
69
  });
70
70
 
71
71
  describe('config entity command metadata route', () => {
72
+ it('preserves real SDK authentication and request options when fetching the catalog', async () => {
73
+ const { OpenCode: realOpenCode } = await vi.importActual('@opencode/client');
74
+ createOpencodeClient.mockImplementation(realOpenCode.make);
75
+ const upstream = vi.spyOn(globalThis, 'fetch').mockImplementation(async (_input, init) => {
76
+ if (new Headers(init?.headers).get('Authorization') !== 'Basic example') {
77
+ return new Response('Unauthorized', { status: 401 });
78
+ }
79
+ return Response.json({ data: [{ name: 'review', description: 'Review changes' }] });
80
+ });
81
+ try {
82
+ const app = express();
83
+ app.use(express.json());
84
+ registerConfigEntityRoutes(app, createDependencies(() => ({ md: { exists: false }, json: { exists: false } })));
85
+ const response = await request(app).post('/api/config/commands/metadata').send({ catalog: true });
86
+ expect(response.status).toBe(200);
87
+ expect(response.body.commands).toEqual([expect.objectContaining({ name: 'review' })]);
88
+ const [url, init] = upstream.mock.calls[0];
89
+ expect(new URL(url).pathname).toBe('/api/command');
90
+ expect(init.method).toBe('GET');
91
+ expect(init.signal).toBeInstanceOf(AbortSignal);
92
+ } finally {
93
+ upstream.mockRestore();
94
+ }
95
+ });
96
+
72
97
  it('returns metadata for many commands through one request', async () => {
73
98
  const app = express();
74
99
  app.use(express.json());
@@ -1207,6 +1207,9 @@ export const registerOpenCodeProxy = (app, deps) => {
1207
1207
  app.get('/api/session/:sessionID/message', (req, res, next) => {
1208
1208
  return forwardSessionMessagesListRequest(req, res, next);
1209
1209
  });
1210
+ app.get('/api/session/:sessionID/context', (req, res, next) => {
1211
+ return forwardSessionMessagesListRequest(req, res, next);
1212
+ });
1210
1213
 
1211
1214
  app.get('/api/global/event', forwardSseRequest);
1212
1215
  app.get('/api/event', forwardSseRequest);
@@ -460,6 +460,21 @@ describe('registerOpenCodeProxy reasoning projection routes', () => {
460
460
  expect(JSON.stringify(res.body)).not.toContain('hidden');
461
461
  });
462
462
 
463
+ it.each(['message', 'context'])('filters native v2 %s before outbound transport', async (surface) => {
464
+ const upstreamUrls = [];
465
+ globalThis.fetch = vi.fn(async (url) => {
466
+ upstreamUrls.push(String(url));
467
+ return new Response(JSON.stringify({ data: [{ id: 'm', type: 'assistant', content: [
468
+ { type: 'reasoning', text: 'hidden' }, { type: 'text', text: 'visible' },
469
+ ] }], cursor: { next: 'older' } }), { headers: { 'content-type': 'application/json' } });
470
+ });
471
+ const res = await request(mountProxy()).get(`/api/session/ses_1/${surface}?includeReasoning=false`);
472
+ expect(res.status).toBe(200);
473
+ expect(res.body.data[0].content).toEqual([{ type: 'text', text: 'visible' }]);
474
+ expect(res.body.cursor.next).toBe('older');
475
+ expect(upstreamUrls[0]).not.toContain('includeReasoning');
476
+ });
477
+
463
478
  it('keeps reasoning parts on session.messages list when includeReasoning is omitted', async () => {
464
479
  globalThis.fetch = vi.fn(async () => ({
465
480
  ok: true,