@openchambery/web 2.0.5-beta.3 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{AssistantView-BeQjlQi5.js → AssistantView-kXN4mz6j.js} +3 -3
- package/dist/assets/{DiagramView-BPFVXhly.js → DiagramView-CGLAl3iS.js} +1 -1
- package/dist/assets/MarkdownRenderer-DA08bZsM.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-DCim2MBS.js → MarkdownRendererImpl-qaVTVCHe.js} +1 -1
- package/dist/assets/{MarkstreamRendererImpl-DLI17gOM.js → MarkstreamRendererImpl-CQdVI8Vx.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-C9097prS.js → MobileDetailNavigation-xaAVkxD-.js} +1 -1
- package/dist/assets/{MobileShareBridge-BVRtivg8.js → MobileShareBridge-z2TFroKY.js} +1 -1
- package/dist/assets/MobileTabPageHeader-DPlvhJFe.js +2 -0
- package/dist/assets/{MultiRunWindow-VdUAIkKj.js → MultiRunWindow-vJc2NLzu.js} +1 -1
- package/dist/assets/{SettingsView-BcQCG9q0.js → SettingsView-BG7DgHmP.js} +6 -6
- package/dist/assets/{SettingsWindow-BSap8D3j.js → SettingsWindow-3QrhPfuk.js} +1 -1
- package/dist/assets/{TerminalView-CQEmfuGt.js → TerminalView-Ciw0BIiz.js} +1 -1
- package/dist/assets/{ToolOutputDialog-3cIIsSBA.js → ToolOutputDialog-D_23USz-.js} +1 -1
- package/dist/assets/{appThemeRegistry-Dl2OjM9t.js → appThemeRegistry-lhAKuFFB.js} +1 -1
- package/dist/assets/{fileMentionTouchSelection-BJOHH2CX.js → fileMentionTouchSelection-DPSC4Fx2.js} +1 -1
- package/dist/assets/{gitApi-C-zOJTEi.js → gitApi-DeWWyR94.js} +3 -3
- package/dist/assets/insertionBoundaries-aV1Cm6zA.js +1 -0
- package/dist/assets/{main-ctL2Nr48.js → main-0XIuL0dd.js} +11 -11
- package/dist/assets/{main-Fbjmo73O.js → main-DZGXa6wk.js} +2 -2
- package/dist/assets/{mcpQueries-B1I3urB4.js → mcpQueries-pTPWjOQO.js} +1 -1
- package/dist/assets/{miniChat-BFctomLE.js → miniChat-C8K4fwOO.js} +2 -2
- package/dist/assets/{mobile-CgrEAs5U.js → mobile-Brtl2UnC.js} +2 -2
- package/dist/assets/multirun-B7FPVrQ-.js +3 -0
- package/dist/assets/{projectMeta-iGmHOQNp.js → projectMeta-D_jCNzjw.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-B82q9wxX.js → renderElectronMiniChatApp-e6XqcsYi.js} +2 -2
- package/dist/assets/renderMobileApp-BQenfg50.js +28 -0
- package/dist/assets/{runtimeConfig-CCw0l6aJ.js → runtimeConfig-CJE7T1Sr.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-CvWlsn11.js → runtimeEndpointReset-DULSaOrI.js} +6 -6
- package/dist/assets/{sessionChangeSummary-BCz7YMwL.js → sessionChangeSummary-CVZBClsA.js} +1 -1
- package/dist/assets/{sessionLookup-BpO4cCmV.js → sessionLookup--qnazVNO.js} +1 -1
- package/dist/assets/{useAppFontEffects-KlbtUhYE.js → useAppFontEffects-BHenW5Q2.js} +53 -53
- package/dist/assets/{useDesktopWindowControlsLayout-BflHVu5S.js → useDesktopWindowControlsLayout-BGgoqF_n.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-BbQKZPcu.js → useEffectiveDirectory-CF16bcpx.js} +1 -1
- package/dist/assets/useMobileNavigationStore-DBML5LIl.js +415 -0
- package/dist/assets/{useSessionAutoCleanup-Dho6q-O2.js → useSessionAutoCleanup-moxr9XbA.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-CbvulSje.js → useWorkerHighlightedLines-DYVg-cuB.js} +1 -1
- package/dist/index.html +2 -2
- package/dist/mini-chat.html +2 -2
- package/dist/mobile.html +2 -2
- package/package.json +1 -1
- package/server/lib/question-auto-delegate/DOCUMENTATION.md +4 -0
- package/server/lib/question-auto-delegate/core.d.ts +5 -0
- package/server/lib/question-auto-delegate/core.js +62 -13
- package/server/lib/question-auto-delegate/form-io.js +4 -1
- package/server/lib/question-auto-delegate/pause-store.d.ts +7 -0
- package/server/lib/question-auto-delegate/pause-store.js +39 -0
- package/server/lib/question-auto-delegate/runtime.js +3 -0
- package/server/lib/question-auto-delegate/runtime.test.js +128 -1
- package/dist/assets/MarkdownRenderer-D1fVOsHS.js +0 -2
- package/dist/assets/MobileTabPageHeader-tKa6r_KP.js +0 -2
- package/dist/assets/insertionBoundaries-DduQc2QR.js +0 -1
- package/dist/assets/multirun-BuVN-s4M.js +0 -3
- package/dist/assets/renderMobileApp-CM_El_gZ.js +0 -28
- package/dist/assets/useMobileNavigationStore-BjIptzTV.js +0 -415
package/dist/assets/{useWorkerHighlightedLines-CbvulSje.js → useWorkerHighlightedLines-DYVg-cuB.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{n as t}from"./runtime-fetch-CiqQd__Y.js";import{On as n,on as r}from"./persistence-Dnj1QOdX.js";import{nt as i,rt as a}from"./vendor-base-ui-CnHfUmDN.js";import{n as o}from"./platform-wu6wSDfg.js";import{v as s}from"./useUIStore-Dfx6TKvi.js";import{n as c}from"./vendor-react-DLPElpoQ.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-CUwjpv-i.js";import{n as m}from"./Icon-BdzPRCSy.js";import{i as h,n as g,t as _}from"./tooltip-DDNnmcXI.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{n as y}from"./markdownTheme-DM5h1i18.js";import{n as b}from"./MarkdownRenderer-D1fVOsHS.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-BpUsiwFd.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.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,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`),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-CiqQd__Y.js";import{On as n,on as r}from"./persistence-Dnj1QOdX.js";import{nt as i,rt as a}from"./vendor-base-ui-CnHfUmDN.js";import{n as o}from"./platform-wu6wSDfg.js";import{v as s}from"./useUIStore-Dfx6TKvi.js";import{n as c}from"./vendor-react-DLPElpoQ.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-CUwjpv-i.js";import{n as m}from"./Icon-BdzPRCSy.js";import{i as h,n as g,t as _}from"./tooltip-DDNnmcXI.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{n as y}from"./markdownTheme-DM5h1i18.js";import{n as b}from"./MarkdownRenderer-DA08bZsM.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-BpUsiwFd.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.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,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`),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,7 +552,7 @@
|
|
|
552
552
|
opacity: 0.72;
|
|
553
553
|
}
|
|
554
554
|
</style>
|
|
555
|
-
<script type="module" crossorigin src="/assets/main-
|
|
555
|
+
<script type="module" crossorigin src="/assets/main-DZGXa6wk.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-BJM2k_uH.js">
|
|
@@ -572,7 +572,7 @@
|
|
|
572
572
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DXyzaX3K.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-
|
|
575
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-CJE7T1Sr.js">
|
|
576
576
|
<link rel="stylesheet" crossorigin href="/assets/src-Cp_AK_QO.css">
|
|
577
577
|
</head>
|
|
578
578
|
<body class="h-full bg-background text-foreground">
|
package/dist/mini-chat.html
CHANGED
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
}
|
|
75
75
|
</style>
|
|
76
76
|
|
|
77
|
-
<script type="module" crossorigin src="/assets/miniChat-
|
|
77
|
+
<script type="module" crossorigin src="/assets/miniChat-C8K4fwOO.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-BJM2k_uH.js">
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DXyzaX3K.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-
|
|
97
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-CJE7T1Sr.js">
|
|
98
98
|
<link rel="stylesheet" crossorigin href="/assets/src-Cp_AK_QO.css">
|
|
99
99
|
</head>
|
|
100
100
|
<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-
|
|
66
|
+
<script type="module" crossorigin src="/assets/mobile-Brtl2UnC.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-BJM2k_uH.js">
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-DXyzaX3K.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-
|
|
86
|
+
<link rel="modulepreload" crossorigin href="/assets/runtimeConfig-CJE7T1Sr.js">
|
|
87
87
|
<link rel="stylesheet" crossorigin href="/assets/src-Cp_AK_QO.css">
|
|
88
88
|
</head>
|
|
89
89
|
<body class="h-full bg-background text-foreground">
|
package/package.json
CHANGED
|
@@ -41,6 +41,10 @@ Auto-submit requires **settings ready + enabled + authoritative directory**.
|
|
|
41
41
|
|
|
42
42
|
## Architecture
|
|
43
43
|
|
|
44
|
+
`pause-store.js` owns monotonic per-question user holds shared by co-located Web, Electron and VS Code hosts. Default storage is the user's `.config/openchamber/question-pauses`; `OPENCHAMBER_QUESTION_PAUSE_DIR` can select a shared directory. Empty, atomically created files are keyed by the digest of globally unique upstream session/form IDs, contain no answers or credentials, survive host restart and are removed on authoritative settlement. All hosts attached to one upstream must use this shared location and the updated runtime; independent machines require a shared filesystem or a single OpenChamber host. This is not an upstream distributed lock or a cross-host submission claim.
|
|
45
|
+
|
|
46
|
+
Pause acknowledgement follows shared hold publication. Failure leaves the local timer stopped but returns an error so the UI can retry publication. An early pause with no recovered form records only a hold and still returns `not_found`; later discovery cannot arm it. Snapshot reads and automatic expiry adopt shared holds, and form IO rechecks immediately after schema GET, before answer POST. Unreadable coordination fails closed (local pause, partial coverage); explicit user reply/delegation remains allowed. A POST already dispatched upstream cannot be recalled. No polling loop or extra upstream request is introduced.
|
|
47
|
+
|
|
44
48
|
| File | Role |
|
|
45
49
|
|---|---|
|
|
46
50
|
| `core.js` / `core.d.ts` | Platform-agnostic state machine (IO/timer injected). Shared contract for VS Code. |
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* API tip event: `openchamber:question-auto-delegate-changed` with `{ epoch, revision }` only —
|
|
5
5
|
* consumers must GET `/api/question-auto-delegate` for the authoritative snapshot.
|
|
6
6
|
*/
|
|
7
|
+
import type { QuestionPauseStore } from './pause-store.js';
|
|
7
8
|
|
|
8
9
|
export const QUESTION_AUTO_DELEGATE_DELAY_MS: 30000;
|
|
9
10
|
|
|
@@ -140,6 +141,8 @@ export interface QuestionAutoDelegateUpstreamResult {
|
|
|
140
141
|
* body was never transmitted. Must not be set when the send may have reached upstream.
|
|
141
142
|
*/
|
|
142
143
|
notSent?: boolean;
|
|
144
|
+
/** A shared user hold prevented the automatic answer before dispatch. */
|
|
145
|
+
paused?: boolean;
|
|
143
146
|
status: number;
|
|
144
147
|
body: unknown;
|
|
145
148
|
}
|
|
@@ -170,6 +173,7 @@ export interface QuestionAutoDelegateIO {
|
|
|
170
173
|
directory: string | undefined,
|
|
171
174
|
answers: string[][],
|
|
172
175
|
sessionID: string,
|
|
176
|
+
canReply?: () => boolean,
|
|
173
177
|
): Promise<QuestionAutoDelegateUpstreamResult>;
|
|
174
178
|
postReject(
|
|
175
179
|
requestID: string,
|
|
@@ -203,6 +207,7 @@ export interface QuestionAutoDelegateCoreOptions {
|
|
|
203
207
|
io: QuestionAutoDelegateIO;
|
|
204
208
|
delayMs?: number;
|
|
205
209
|
autoAnswer?: string;
|
|
210
|
+
pauseStore?: QuestionPauseStore;
|
|
206
211
|
}
|
|
207
212
|
|
|
208
213
|
export interface QuestionAutoDelegateCore {
|
|
@@ -64,6 +64,7 @@ export function createQuestionAutoDelegateCore({
|
|
|
64
64
|
io,
|
|
65
65
|
delayMs = QUESTION_AUTO_DELEGATE_DELAY_MS,
|
|
66
66
|
autoAnswer = QUESTION_AUTO_DELEGATE_ANSWER,
|
|
67
|
+
pauseStore,
|
|
67
68
|
} = {}) {
|
|
68
69
|
if (!io || typeof io !== 'object') {
|
|
69
70
|
throw new TypeError('createQuestionAutoDelegateCore requires io');
|
|
@@ -107,18 +108,21 @@ export function createQuestionAutoDelegateCore({
|
|
|
107
108
|
}
|
|
108
109
|
};
|
|
109
110
|
|
|
110
|
-
const snapshot = () =>
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
const snapshot = () => {
|
|
112
|
+
for (const entry of requests.values()) syncSharedPause(entry);
|
|
113
|
+
return {
|
|
114
|
+
epoch,
|
|
115
|
+
revision,
|
|
116
|
+
serverNow: io.now(),
|
|
117
|
+
enabled: settingsStatus === 'ready' ? enabled : false,
|
|
118
|
+
delayMs,
|
|
119
|
+
coverage: {
|
|
120
|
+
state: settingsStatus === 'unavailable' && coverageState === 'ready' ? 'partial' : coverageState,
|
|
121
|
+
failedDirectories: failedDirectories.slice(),
|
|
122
|
+
},
|
|
123
|
+
requests: Array.from(requests.values()).map(publicRequest),
|
|
124
|
+
};
|
|
125
|
+
};
|
|
122
126
|
|
|
123
127
|
const rememberSession = (info, directoryHint = '') => {
|
|
124
128
|
if (!info || typeof info !== 'object') return;
|
|
@@ -145,6 +149,23 @@ export function createQuestionAutoDelegateCore({
|
|
|
145
149
|
}
|
|
146
150
|
};
|
|
147
151
|
|
|
152
|
+
const syncSharedPause = (entry) => {
|
|
153
|
+
if (entry.state !== 'counting') return false;
|
|
154
|
+
try {
|
|
155
|
+
if (!pauseStore?.has(entry.requestID, entry.sessionID)) return false;
|
|
156
|
+
} catch {
|
|
157
|
+
// Unreadable coordination is not permission to answer. Pause locally and
|
|
158
|
+
// expose partial coverage; never let an event/timer rejection escape the hub.
|
|
159
|
+
coverageState = 'partial';
|
|
160
|
+
}
|
|
161
|
+
clearTimer(entry);
|
|
162
|
+
entry.state = 'paused';
|
|
163
|
+
entry.deadlineAt = null;
|
|
164
|
+
entry.pauseReason = 'interaction';
|
|
165
|
+
bump();
|
|
166
|
+
return true;
|
|
167
|
+
};
|
|
168
|
+
|
|
148
169
|
const fireTakeover = (entry, reason) => {
|
|
149
170
|
try {
|
|
150
171
|
io.onUserTakeover?.({
|
|
@@ -191,6 +212,7 @@ export function createQuestionAutoDelegateCore({
|
|
|
191
212
|
};
|
|
192
213
|
|
|
193
214
|
const ensureCounting = (entry, { resetDeadline } = { resetDeadline: true }) => {
|
|
215
|
+
if (syncSharedPause(entry)) return false;
|
|
194
216
|
if (entry.state === TERMINAL_SETTLED || entry.state === 'uncertain' || entry.state === 'submitting') {
|
|
195
217
|
return false;
|
|
196
218
|
}
|
|
@@ -304,6 +326,11 @@ export function createQuestionAutoDelegateCore({
|
|
|
304
326
|
entry.resolution = resolution;
|
|
305
327
|
entry.claimAuthority = entry.claimAuthority || 'done';
|
|
306
328
|
if (submittedBy) entry.submittedBy = submittedBy;
|
|
329
|
+
try {
|
|
330
|
+
pauseStore?.remove(entry.requestID, entry.sessionID);
|
|
331
|
+
} catch {
|
|
332
|
+
// Retaining a settled hold is harmless; cleanup must not undo settlement.
|
|
333
|
+
}
|
|
307
334
|
};
|
|
308
335
|
|
|
309
336
|
const markUncertain = (entry, submittedBy) => {
|
|
@@ -538,6 +565,9 @@ export function createQuestionAutoDelegateCore({
|
|
|
538
565
|
};
|
|
539
566
|
}
|
|
540
567
|
const existing = requests.get(requestID);
|
|
568
|
+
if (existing && (syncSharedPause(existing) || existing.state === 'paused')) {
|
|
569
|
+
return { outcome: 'paused', snapshot: snapshot() };
|
|
570
|
+
}
|
|
541
571
|
if (existing && !asTrimmedString(existing.directory) && !asTrimmedString(input.directory)) {
|
|
542
572
|
return {
|
|
543
573
|
outcome: 'error',
|
|
@@ -620,7 +650,8 @@ export function createQuestionAutoDelegateCore({
|
|
|
620
650
|
? input.answers
|
|
621
651
|
: buildAutoDelegateAnswers(count, autoAnswer);
|
|
622
652
|
entry.upstreamDispatched = true;
|
|
623
|
-
upstream = await io.postReply(requestID, directory, answers, entry.sessionID
|
|
653
|
+
upstream = await io.postReply(requestID, directory, answers, entry.sessionID,
|
|
654
|
+
authority === 'auto' ? () => !pauseStore?.has(requestID, entry.sessionID) : undefined);
|
|
624
655
|
}
|
|
625
656
|
} catch (error) {
|
|
626
657
|
// Throw before a classified upstream result: treat as pre-send failure → release for retry.
|
|
@@ -650,6 +681,11 @@ export function createQuestionAutoDelegateCore({
|
|
|
650
681
|
// Compatible extension: only an explicit notSent===true means the request
|
|
651
682
|
// never left the process. Release claim for human retry. Unknown status:0
|
|
652
683
|
// without notSent stays uncertain (may have been sent).
|
|
684
|
+
if (upstream?.paused === true && upstream.notSent === true) {
|
|
685
|
+
releaseClaimToPaused(entry, 'interaction');
|
|
686
|
+
bump();
|
|
687
|
+
return { outcome: 'paused', snapshot: snapshot() };
|
|
688
|
+
}
|
|
653
689
|
if (upstream?.notSent === true) {
|
|
654
690
|
releaseClaimToPaused(entry, authority === 'manual' ? 'interaction' : 'user');
|
|
655
691
|
bump();
|
|
@@ -793,6 +829,13 @@ export function createQuestionAutoDelegateCore({
|
|
|
793
829
|
|
|
794
830
|
let entry = requests.get(requestID);
|
|
795
831
|
if (!entry) {
|
|
832
|
+
// Publish the user's hold before asynchronous discovery: another host's
|
|
833
|
+
// deadline must not win while this host waits for its form list.
|
|
834
|
+
try {
|
|
835
|
+
pauseStore?.pause(requestID, sessionID);
|
|
836
|
+
} catch {
|
|
837
|
+
return { outcome: 'error', snapshot: snapshot(), status: 503, error: 'Could not publish question pause' };
|
|
838
|
+
}
|
|
796
839
|
const recovered = await recoverPendingIdentity({
|
|
797
840
|
requestID,
|
|
798
841
|
sessionID,
|
|
@@ -863,6 +906,12 @@ export function createQuestionAutoDelegateCore({
|
|
|
863
906
|
entry.state = 'paused';
|
|
864
907
|
entry.deadlineAt = null;
|
|
865
908
|
entry.pauseReason = reason === 'goal' ? 'goal' : reason;
|
|
909
|
+
try {
|
|
910
|
+
pauseStore?.pause(requestID, sessionID);
|
|
911
|
+
} catch {
|
|
912
|
+
bump();
|
|
913
|
+
return { outcome: 'error', snapshot: snapshot(), status: 503, error: 'Could not publish question pause' };
|
|
914
|
+
}
|
|
866
915
|
if (reason !== 'goal') {
|
|
867
916
|
fireTakeover(entry, reason);
|
|
868
917
|
}
|
|
@@ -12,7 +12,7 @@ export function createQuestionFormIO(upstream) {
|
|
|
12
12
|
if (!Array.isArray(rows)) return null;
|
|
13
13
|
return rows.filter((form) => form?.metadata?.kind === 'question');
|
|
14
14
|
},
|
|
15
|
-
async postReply(requestID, directory, answers, sessionID) {
|
|
15
|
+
async postReply(requestID, directory, answers, sessionID, canReply) {
|
|
16
16
|
const path = formPath(sessionID, requestID);
|
|
17
17
|
const result = await upstream(path, { directory });
|
|
18
18
|
// A failed schema read never means the answer POST was dispatched.
|
|
@@ -30,6 +30,9 @@ export function createQuestionFormIO(upstream) {
|
|
|
30
30
|
field.options?.find((option) => (option.label || option.value) === value)?.value ?? value);
|
|
31
31
|
return [field.key, field.type === 'multiselect' ? values : values[0] ?? ''];
|
|
32
32
|
}));
|
|
33
|
+
if (canReply && !canReply()) {
|
|
34
|
+
return { ok: false, notSent: true, paused: true, status: 409, body: null };
|
|
35
|
+
}
|
|
33
36
|
return upstream(`${path}/reply`, { directory, method: 'POST', body: { answer } });
|
|
34
37
|
},
|
|
35
38
|
async postReject(requestID, directory, _body, sessionID) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export interface QuestionPauseStore {
|
|
2
|
+
has(requestID: string, sessionID: string): boolean;
|
|
3
|
+
pause(requestID: string, sessionID: string): void;
|
|
4
|
+
remove(requestID: string, sessionID: string): void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function createQuestionPauseStore(directory?: string): QuestionPauseStore;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { mkdirSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
// All local hosts share this boundary, including desktop and VS Code. Form and
|
|
7
|
+
// session IDs are globally unique upstream identities; no URL or credential is stored.
|
|
8
|
+
export function createQuestionPauseStore(directory = process.env.OPENCHAMBER_QUESTION_PAUSE_DIR
|
|
9
|
+
|| join(homedir(), '.config', 'openchamber', 'question-pauses')) {
|
|
10
|
+
const pathFor = (requestID, sessionID) => join(directory,
|
|
11
|
+
createHash('sha256').update(JSON.stringify([sessionID, requestID])).digest('hex'));
|
|
12
|
+
return {
|
|
13
|
+
has(requestID, sessionID) {
|
|
14
|
+
try {
|
|
15
|
+
statSync(pathFor(requestID, sessionID));
|
|
16
|
+
return true;
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error?.code === 'ENOENT') return false;
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
pause(requestID, sessionID) {
|
|
23
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
24
|
+
try {
|
|
25
|
+
// Exclusive creation publishes an immutable hold atomically across processes.
|
|
26
|
+
writeFileSync(pathFor(requestID, sessionID), '', { flag: 'wx', mode: 0o600 });
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error?.code !== 'EEXIST') throw error;
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
remove(requestID, sessionID) {
|
|
32
|
+
try {
|
|
33
|
+
unlinkSync(pathFor(requestID, sessionID));
|
|
34
|
+
} catch (error) {
|
|
35
|
+
if (error?.code !== 'ENOENT') throw error;
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
QUESTION_AUTO_DELEGATE_DELAY_MS,
|
|
4
4
|
} from './core.js';
|
|
5
5
|
import { createQuestionFormIO } from './form-io.js';
|
|
6
|
+
import { createQuestionPauseStore } from './pause-store.js';
|
|
6
7
|
|
|
7
8
|
const REQUEST_TIMEOUT_MS = 15_000;
|
|
8
9
|
|
|
@@ -42,6 +43,7 @@ export function createQuestionAutoDelegateRuntime({
|
|
|
42
43
|
},
|
|
43
44
|
createEpoch = () => `qad-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`,
|
|
44
45
|
onUserTakeover,
|
|
46
|
+
pauseStore = createQuestionPauseStore(),
|
|
45
47
|
} = {}) {
|
|
46
48
|
const upstream = async (path, { directory, method = 'GET', body } = {}) => {
|
|
47
49
|
const url = new URL(buildOpenCodeUrl(path, ''));
|
|
@@ -103,6 +105,7 @@ export function createQuestionAutoDelegateRuntime({
|
|
|
103
105
|
|
|
104
106
|
const core = createQuestionAutoDelegateCore({
|
|
105
107
|
delayMs,
|
|
108
|
+
pauseStore,
|
|
106
109
|
io: {
|
|
107
110
|
now,
|
|
108
111
|
createTimer,
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { afterEach, expect, it, vi } from 'vitest';
|
|
1
|
+
import { afterEach, beforeEach, expect, it, vi } from 'vitest';
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { execFileSync } from 'node:child_process';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
2
6
|
import { createQuestionAutoDelegateRuntime } from './runtime.js';
|
|
3
7
|
import { QUESTION_AUTO_DELEGATE_ANSWER } from './core.js';
|
|
8
|
+
import { createQuestionPauseStore } from './pause-store.js';
|
|
4
9
|
|
|
5
10
|
const form = {
|
|
6
11
|
id: 'frm_question', sessionID: 'ses_test', title: 'Choose',
|
|
@@ -8,9 +13,12 @@ const form = {
|
|
|
8
13
|
fields: [{ key: 'approach', type: 'string', custom: true, options: [{ label: 'A', value: 'a' }] }],
|
|
9
14
|
};
|
|
10
15
|
const runtimes = [];
|
|
16
|
+
let pauseDirectory;
|
|
17
|
+
beforeEach(() => { pauseDirectory = mkdtempSync(join(tmpdir(), 'question-pauses-')); });
|
|
11
18
|
afterEach(() => {
|
|
12
19
|
runtimes.splice(0).forEach((runtime) => runtime.dispose());
|
|
13
20
|
vi.useRealTimers();
|
|
21
|
+
rmSync(pauseDirectory, { recursive: true, force: true });
|
|
14
22
|
});
|
|
15
23
|
|
|
16
24
|
const setup = async (pending = []) => {
|
|
@@ -30,6 +38,7 @@ const setup = async (pending = []) => {
|
|
|
30
38
|
getOpenCodeAuthHeaders: () => ({}),
|
|
31
39
|
readSettingsFromDiskMigrated: async () => ({ projects: [{ path: '/project' }] }),
|
|
32
40
|
fetchImpl,
|
|
41
|
+
pauseStore: createQuestionPauseStore(pauseDirectory),
|
|
33
42
|
});
|
|
34
43
|
runtimes.push(runtime);
|
|
35
44
|
runtime.start();
|
|
@@ -122,6 +131,124 @@ it('honors user takeover and explicit delegation of native forms', async () => {
|
|
|
122
131
|
expect(posts()).toHaveLength(1);
|
|
123
132
|
});
|
|
124
133
|
|
|
134
|
+
it('a confirmed desktop pause stops a second host and survives host recreation', async () => {
|
|
135
|
+
const desktop = await setup();
|
|
136
|
+
const web = await setup();
|
|
137
|
+
desktop.emit('form.created', { form });
|
|
138
|
+
web.emit('form.created', { form });
|
|
139
|
+
const result = await desktop.runtime.pause({ requestID: form.id, sessionID: form.sessionID, reason: 'interaction' });
|
|
140
|
+
expect(result.outcome).toBe('paused');
|
|
141
|
+
const restarted = await setup([form]);
|
|
142
|
+
await vi.advanceTimersByTimeAsync(60_000);
|
|
143
|
+
for (const host of [desktop, web, restarted]) {
|
|
144
|
+
expect(host.posts()).toHaveLength(0);
|
|
145
|
+
expect(host.runtime.snapshot().requests[0].state).toBe('paused');
|
|
146
|
+
}
|
|
147
|
+
await web.runtime.delegate({ requestID: form.id, sessionID: form.sessionID });
|
|
148
|
+
expect(web.posts()).toHaveLength(1);
|
|
149
|
+
expect(createQuestionPauseStore(pauseDirectory).has(form.id, form.sessionID)).toBe(false);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it('a shared hold for one question does not stop another question in the same session', async () => {
|
|
153
|
+
const { emit, runtime, fetchImpl, posts } = await setup();
|
|
154
|
+
const other = { ...form, id: 'frm_other' };
|
|
155
|
+
const original = fetchImpl.getMockImplementation();
|
|
156
|
+
fetchImpl.mockImplementation((url, options) => {
|
|
157
|
+
if (url.pathname.endsWith('/form/frm_other')) return Promise.resolve(Response.json({ data: other }));
|
|
158
|
+
if (url.pathname.endsWith('/form/frm_other/reply')) return Promise.resolve(new Response(null, { status: 204 }));
|
|
159
|
+
return original(url, options);
|
|
160
|
+
});
|
|
161
|
+
emit('form.created', { form });
|
|
162
|
+
emit('form.created', { form: other });
|
|
163
|
+
await runtime.pause({ requestID: form.id, sessionID: form.sessionID, reason: 'interaction' });
|
|
164
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
165
|
+
expect(posts()).toHaveLength(1);
|
|
166
|
+
expect(posts()[0][0].pathname).toContain('/frm_other/reply');
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('checks a cross-host pause again after the asynchronous form schema read', async () => {
|
|
170
|
+
const desktop = await setup();
|
|
171
|
+
const web = await setup();
|
|
172
|
+
web.emit('form.created', { form });
|
|
173
|
+
await vi.advanceTimersByTimeAsync(1000);
|
|
174
|
+
desktop.emit('form.created', { form });
|
|
175
|
+
const original = web.fetchImpl.getMockImplementation();
|
|
176
|
+
let finishSchema;
|
|
177
|
+
web.fetchImpl.mockImplementation((url, options) => url.pathname.endsWith('/form/frm_question')
|
|
178
|
+
? new Promise((resolve) => { finishSchema = () => resolve(Response.json({ data: form })); })
|
|
179
|
+
: original(url, options));
|
|
180
|
+
// Only the web host reaches its timer; desktop takeover arrives while its schema GET waits.
|
|
181
|
+
await vi.advanceTimersByTimeAsync(29_000);
|
|
182
|
+
expect(finishSchema).toBeTypeOf('function');
|
|
183
|
+
await desktop.runtime.pause({ requestID: form.id, sessionID: form.sessionID, reason: 'interaction' });
|
|
184
|
+
finishSchema();
|
|
185
|
+
await vi.advanceTimersByTimeAsync(0);
|
|
186
|
+
expect(web.posts()).toHaveLength(0);
|
|
187
|
+
expect(web.runtime.snapshot().requests[0].state).toBe('paused');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('retains a hold sent before this host discovers the form', async () => {
|
|
191
|
+
const desktop = await setup();
|
|
192
|
+
const result = await desktop.runtime.pause({ requestID: form.id, sessionID: form.sessionID, reason: 'interaction' });
|
|
193
|
+
expect(result.outcome).toBe('not_found');
|
|
194
|
+
const web = await setup([form]);
|
|
195
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
196
|
+
expect(web.posts()).toHaveLength(0);
|
|
197
|
+
expect(web.runtime.snapshot().requests[0].state).toBe('paused');
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('publishes the hold before a slow missing-identity recovery can cross the other host deadline', async () => {
|
|
201
|
+
const desktop = await setup();
|
|
202
|
+
const web = await setup([form]);
|
|
203
|
+
const original = desktop.fetchImpl.getMockImplementation();
|
|
204
|
+
let finishList;
|
|
205
|
+
desktop.fetchImpl.mockImplementation((url, options) => url.pathname === '/api/form'
|
|
206
|
+
? new Promise((resolve) => { finishList = () => resolve(Response.json({ data: [form] })); })
|
|
207
|
+
: original(url, options));
|
|
208
|
+
const pausing = desktop.runtime.pause({ requestID: form.id, sessionID: form.sessionID, directory: '/project', reason: 'interaction' });
|
|
209
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
210
|
+
expect(web.posts()).toHaveLength(0);
|
|
211
|
+
finishList();
|
|
212
|
+
expect((await pausing).outcome).toBe('paused');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('reports shared pause publication failure and allows explicit retry', async () => {
|
|
216
|
+
const { runtime, emit } = await setup();
|
|
217
|
+
emit('form.created', { form });
|
|
218
|
+
const store = createQuestionPauseStore(pauseDirectory);
|
|
219
|
+
const identity = { requestID: form.id, sessionID: form.sessionID, reason: 'interaction' };
|
|
220
|
+
// A file where a directory belongs is a deterministic write failure on every platform.
|
|
221
|
+
rmSync(pauseDirectory, { recursive: true });
|
|
222
|
+
writeFileSync(pauseDirectory, 'blocked');
|
|
223
|
+
expect((await runtime.pause(identity)).outcome).toBe('error');
|
|
224
|
+
rmSync(pauseDirectory);
|
|
225
|
+
expect((await runtime.pause(identity)).outcome).toBe('paused');
|
|
226
|
+
expect(store.has(form.id, form.sessionID)).toBe(true);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('blocks automatic replies on an unreadable shared store without an unhandled timer failure', async () => {
|
|
230
|
+
const { runtime, emit, posts } = await setup();
|
|
231
|
+
emit('form.created', { form });
|
|
232
|
+
rmSync(pauseDirectory, { recursive: true });
|
|
233
|
+
writeFileSync(pauseDirectory, 'blocked');
|
|
234
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
235
|
+
expect(posts()).toHaveLength(0);
|
|
236
|
+
expect(runtime.snapshot().requests[0].state).toBe('paused');
|
|
237
|
+
expect(runtime.snapshot().coverage.state).toBe('partial');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('observes a pause published by a separate Node host process', async () => {
|
|
241
|
+
const { runtime, emit, posts } = await setup();
|
|
242
|
+
emit('form.created', { form });
|
|
243
|
+
execFileSync(process.execPath, ['--input-type=module', '-e', `
|
|
244
|
+
import { createQuestionPauseStore } from ${JSON.stringify(new URL('./pause-store.js', import.meta.url).href)};
|
|
245
|
+
createQuestionPauseStore(process.argv[1]).pause(process.argv[2], process.argv[3]);
|
|
246
|
+
`, pauseDirectory, form.id, form.sessionID]);
|
|
247
|
+
await vi.advanceTimersByTimeAsync(30_000);
|
|
248
|
+
expect(posts()).toHaveLength(0);
|
|
249
|
+
expect(runtime.snapshot().requests[0].state).toBe('paused');
|
|
250
|
+
});
|
|
251
|
+
|
|
125
252
|
it('uses the freshly read schema for multiple fields and array answers', async () => {
|
|
126
253
|
const { emit, fetchImpl, posts } = await setup();
|
|
127
254
|
const original = fetchImpl.getMockImplementation();
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MarkstreamRendererImpl-DLI17gOM.js","assets/rolldown-runtime-C0FnF6B9.js","assets/vendor-base-ui-CnHfUmDN.js","assets/useUIStore-Dfx6TKvi.js","assets/runtime-switch-BJM2k_uH.js","assets/runtime-auth-D66yq6ie.js","assets/vendor-zustand-DzRqcymP.js","assets/vendor-react-DLPElpoQ.js","assets/vendor-markstream-react-DX55XLGO.js","assets/vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js","assets/vendor-markstream-core-Cm34iPLL.js","assets/vendor-floating-ui-dom-BHhLtF5l.js","assets/vendor-floating-ui-core-Co1I1lFV.js","assets/vendor-reactuses-core-Dq5ocTF8.js","assets/vendor-lodash-es-DfLbG5Af.js","assets/vendor-js-cookie-hSOiFTtX.js","assets/button-CUwjpv-i.js","assets/persistence-Dnj1QOdX.js","assets/runtime-fetch-CiqQd__Y.js","assets/vendor-pathe-vBmvQE8f.js","assets/vendor-tanstack-query-core-BWz0ose6.js","assets/store-l_X_jQNz.js","assets/vendor-class-variance-authority-BLUaYARZ.js","assets/vendor-tailwind-merge-BicNWLTg.js","assets/useMobileNavigationStore-BjIptzTV.js","assets/platform-wu6wSDfg.js","assets/vendor-opencode-client-MF2GBrFx.js","assets/vendor-tanstack-react-query-D7pys_c9.js","assets/vendor-sonner-DVzioF3d.js","assets/useAssistantUIStore-DBwfg9nX.js","assets/vendor-zod-Dzk5kdUU.js","assets/vendor-fuse.js-DB5wDJbI.js","assets/useThemeSystem-DMzWVJaW.js","assets/useRuntimeAPIs-DSLXJybW.js","assets/url-DNRMq_0R.js","assets/useEffectiveDirectory-BbQKZPcu.js","assets/markdownHeightCache-CGCWmHgq.js","assets/dualLimitLru-D8Sphgua.js","assets/MarkdownRendererImpl-DCim2MBS.js","assets/vendor-katex--B5dHUyk.js","assets/markdownTheme-DM5h1i18.js","assets/vendor-pierre-diffs-DX7XTPG3.js","assets/vendor-hast-util-to-html-B0p1k5Xa.js","assets/vendor-character-entities-legacy-Wut6vMuj.js","assets/vendor-character-entities-html4-DlN_yAFd.js","assets/vendor-ccount-CyGsA0u7.js","assets/vendor-comma-separated-tokens-B9ouxNNS.js","assets/vendor-oniguruma-to-es-CrHzjjSU.js","assets/vendor-oniguruma-parser-D2DIvhSP.js","assets/vendor-diff-Dq7CZNim.js","assets/vendor-lru_map-DpDied8H.js","assets/markdown-worker-bS5OgGO3.js","assets/FadeInOnReveal-BMSk_tY-.js","assets/imageSource-BpUsiwFd.js","assets/relay-image-stream-D2XooXKZ.js","assets/vendor-morphdom-BbKiNDAu.js","assets/vendor-beautiful-mermaid-DykqIK5D.js","assets/vendor-dompurify-CeJNOzik.js","assets/vendor-marked-WVekxjAN.js","assets/vendor-remend-C3cXc-tf.js","assets/MarkstreamRendererImpl-DKhVy3nF.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{o as e}from"./rolldown-runtime-C0FnF6B9.js";import{a as t}from"./vendor-zustand-DzRqcymP.js";import{nt as n,rt as r}from"./vendor-base-ui-CnHfUmDN.js";import{n as i}from"./vendor-react-DLPElpoQ.js";import{o as a}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{r as o}from"./button-CUwjpv-i.js";import{i as s,n as c,t as l}from"./markdownHeightCache-CGCWmHgq.js";var u=i(),d=e(r(),1),f=`openchamber:chunk-import-reload`,p=250,m=3e4,h=[/Importing a module script failed/i,/Failed to fetch dynamically imported module/i,/error loading dynamically imported module/i,/Loading chunk \S+ failed/i,/ChunkLoadError/i];function g(e){if(e instanceof Error)return`${e.name}\n${e.message}\n${e.stack??``}`;if(typeof e==`string`)return e;try{return JSON.stringify(e)}catch{return String(e)}}function _(e){let t=g(e);return h.some(e=>e.test(t))}function v(e){return`2.0.5-beta.3:${g(e).slice(0,500)}`}function y(e){if(typeof window>`u`)return;let t=Date.now(),n=v(e),r=null;try{let e=window.sessionStorage.getItem(f);if(e)try{r=JSON.parse(e)}catch{r=null}}catch{return}let i=typeof r?.timestamp==`number`?r.timestamp:0;if(!(r?.signature===n&&t-i<m)){try{window.sessionStorage.setItem(f,JSON.stringify({signature:n,timestamp:t}))}catch{return}console.error(`[refresh-debug] chunk-import-reload`,{error:g(e).slice(0,1e3)}),window.setTimeout(()=>{window.location.reload()},0)}}async function b(e,t={}){let n=t.retries??1,r;for(let t=0;t<=n;t+=1)try{return await e()}catch(e){if(r=e,!_(e)||t>=n)break;await new Promise(e=>setTimeout(e,p*(t+1)))}throw _(r)&&y(r),r}var x=e=>(0,d.lazy)(()=>b(e)),S=(e,t)=>{try{let n=t??(typeof localStorage>`u`?null:localStorage);return n?n.getItem(e)===`1`:!1}catch{return!1}},C=(e,t)=>{try{let n=t??(typeof localStorage>`u`?null:localStorage);return!n||n.getItem(e)!==`0`}catch{return!0}},w=(e,t)=>{try{typeof localStorage<`u`&&localStorage.setItem(e,t?`1`:`0`)}catch{}},T=`oc:legend-timeline`,E=e=>S(T,e),D=`oc:markstream-react`,O=e=>C(D,e),k=t(e=>({legendTimelineEnabled:E(),setLegendTimelineEnabled:t=>{w(T,t),e({legendTimelineEnabled:t})},markstreamReactEnabled:O(),setMarkstreamReactEnabled:t=>{w(D,t),e({markstreamReactEnabled:t})}})),A=null,j=()=>(A??=a(()=>import(`./MarkstreamRendererImpl-DLI17gOM.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60])).catch(e=>{throw A=null,e}),A),M=()=>{j().catch(()=>void 0)},N=null,P=()=>(N??=a(()=>import(`./MarkdownRendererImpl-DCim2MBS.js`).then(e=>e.n),__vite__mapDeps([38,1,4,5,18,17,6,2,3,7,19,20,25,26,9,39,13,14,15,16,21,22,23,24,27,28,29,30,31,32,40,41,42,43,44,45,46,47,48,49,50,33,34,51,37,35,52,53,54,36,55,56,57,58,59])).catch(e=>{throw N=null,e}),N),F=()=>{P().catch(()=>void 0),O()&&M()},I=class extends d.Component{state={hasError:!1};static getDerivedStateFromError(){return{hasError:!0}}componentDidCatch(e){console.warn(`[markstream-react] falling back to the current Markdown renderer`,e)}render(){return this.state.hasError?this.props.fallback:this.props.children}},L=d.createContext(!0),R=()=>d.useContext(L),z=n(),B=x(()=>P().then(e=>({default:e.MarkdownRenderer}))),V=x(()=>j().then(e=>({default:e.MarkstreamRenderer}))),H=x(()=>P().then(e=>({default:e.SimpleMarkdownRenderer}))),U=e=>e===`tool`?`markdown-content markdown-tool`:e===`reasoning`?`markdown-content markdown-reasoning`:`markdown-content leading-relaxed`,W=e=>{let t=(0,u.c)(15),n=k(q),r=typeof e.content==`string`?e.content:``,i=typeof e.variant==`string`?e.variant:`assistant`,a;t[0]!==r||t[1]!==n||t[2]!==e.reserveMeasuredHeight||t[3]!==i?(a=e.reserveMeasuredHeight?c(l(r,n?`markstream:${i}`:i)):void 0,t[0]=r,t[1]=n,t[2]=e.reserveMeasuredHeight,t[3]=i,t[4]=a):a=t[4];let d=a,f;t[5]!==e.className||t[6]!==e.variant?(f=o(`relative break-words w-full min-w-0`,U(e.variant),typeof e.className==`string`?e.className:void 0),t[5]=e.className,t[6]=e.variant,t[7]=f):f=t[7];let p;t[8]!==r||t[9]!==e.animated||t[10]!==d?(p=(0,z.jsx)(s,{animated:e.animated,content:r,reservedHeight:d}),t[8]=r,t[9]=e.animated,t[10]=d,t[11]=p):p=t[11];let m;return t[12]!==f||t[13]!==p?(m=(0,z.jsx)(`div`,{className:f,"aria-busy":`true`,"data-markdown-hydration":`deferred`,"data-markdown-ready":`false`,children:p}),t[12]=f,t[13]=p,t[14]=m):m=t[14],m},G=e=>{let t=(0,u.c)(9),n=R(),r=k(J);if(!n&&e.isStreaming!==!0){let n;return t[0]===e?n=t[1]:(n=(0,z.jsx)(W,{...e,animated:!1,reserveMeasuredHeight:!0}),t[0]=e,t[1]=n),n}let i;t[2]===e?i=t[3]:(i=(0,z.jsx)(d.Suspense,{fallback:(0,z.jsx)(W,{...e,reserveMeasuredHeight:!0}),children:(0,z.jsx)(B,{...e})}),t[2]=e,t[3]=i);let a=i;if(!r)return a;let o;t[4]===e?o=t[5]:(o=(0,z.jsx)(d.Suspense,{fallback:(0,z.jsx)(W,{...e,reserveMeasuredHeight:!0}),children:(0,z.jsx)(V,{...e})}),t[4]=e,t[5]=o);let s;return t[6]!==a||t[7]!==o?(s=(0,z.jsx)(I,{fallback:a,children:o}),t[6]=a,t[7]=o,t[8]=s):s=t[8],s},K=e=>{let t=(0,u.c)(4);if(!R()){let n;return t[0]===e?n=t[1]:(n=(0,z.jsx)(W,{...e,animated:!1}),t[0]=e,t[1]=n),n}let n;return t[2]===e?n=t[3]:(n=(0,z.jsx)(d.Suspense,{fallback:(0,z.jsx)(W,{...e}),children:(0,z.jsx)(H,{...e})}),t[2]=e,t[3]=n),n};function q(e){return e.markstreamReactEnabled}function J(e){return e.markstreamReactEnabled}export{k as a,F as i,K as n,x as o,L as r,G as t};
|