@openchambery/web 1.19.16 → 1.19.17-beta.1
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-B79FR_5m.js → AssistantView-WtjtyUyg.js} +1 -1
- package/dist/assets/{DiagramView-Bg5pX5aJ.js → DiagramView-hIHOl44C.js} +1 -1
- package/dist/assets/MarkdownRenderer-Ym-7pIpr.js +2 -0
- package/dist/assets/{MarkdownRendererImpl-BWTMbqp6.js → MarkdownRendererImpl-CDnlh1Dp.js} +1 -1
- package/dist/assets/{MarkstreamRendererImpl-Bwxkdtts.js → MarkstreamRendererImpl-4acJU3sf.js} +1 -1
- package/dist/assets/{MobileDetailNavigation-37jfPItf.js → MobileDetailNavigation-6fa0eI33.js} +1 -1
- package/dist/assets/{MobileShareBridge-D2RJnSvI.js → MobileShareBridge-BkJMD_0e.js} +1 -1
- package/dist/assets/MobileSurface-D_6LtVFN.js +2 -0
- package/dist/assets/{MultiRunWindow-CUYEega4.js → MultiRunWindow-2cqeffjI.js} +1 -1
- package/dist/assets/{SettingsView-B5BWCL5K.js → SettingsView-C5sFMDDr.js} +1 -1
- package/dist/assets/{SettingsWindow--F_wFMX-.js → SettingsWindow-Bdv6Aksi.js} +1 -1
- package/dist/assets/{TerminalView-BqnCNcW3.js → TerminalView-CMkOh0DS.js} +1 -1
- package/dist/assets/{ToolOutputDialog-Cxpellmm.js → ToolOutputDialog-CnJIHSL_.js} +1 -1
- package/dist/assets/{appThemeRegistry-DaoSMJG1.js → appThemeRegistry-y_GyQ3ct.js} +1 -1
- package/dist/assets/{fileMentionTouchSelection-COw1MDRz.js → fileMentionTouchSelection-DpvBv5_N.js} +1 -1
- package/dist/assets/{gitApi-uzDmhDPP.js → gitApi-m5nvxxzw.js} +1 -1
- package/dist/assets/{insertionBoundaries-BYOyFrjB.js → insertionBoundaries-BPmqh_Tr.js} +1 -1
- package/dist/assets/{main-Br8P10pP.js → main-B21k2oEx.js} +2 -2
- package/dist/assets/{main-DaaedB65.js → main-D_QwFeXJ.js} +4 -4
- package/dist/assets/{miniChat-aQQ4d-bD.js → miniChat-Bp8luloI.js} +2 -2
- package/dist/assets/{mobile-XeTOB53s.js → mobile-BfgTp3XO.js} +2 -2
- package/dist/assets/{multirun-BKVlVu2V.js → multirun-DVHbCRKI.js} +1 -1
- package/dist/assets/{projectMeta-DX3l1Xzy.js → projectMeta-DRIkQQ-o.js} +1 -1
- package/dist/assets/{renderElectronMiniChatApp-CmYP_apQ.js → renderElectronMiniChatApp-DQM5xlcU.js} +2 -2
- package/dist/assets/{renderMobileApp-ATUEcuRh.js → renderMobileApp-CkvkhgAh.js} +4 -4
- package/dist/assets/{runtimeConfig-Cug6bqDv.js → runtimeConfig-kj6kuVyP.js} +1 -1
- package/dist/assets/{runtimeEndpointReset-CRc6se81.js → runtimeEndpointReset-CgaiwIrw.js} +1 -1
- package/dist/assets/{sessionLookup-D3ISlV8R.js → sessionLookup-D-SPo12C.js} +1 -1
- package/dist/assets/{useAppFontEffects-Cn7pYCz1.js → useAppFontEffects-Cx1Q-PF_.js} +5 -5
- package/dist/assets/{useDesktopWindowControlsLayout-DXAFSQuV.js → useDesktopWindowControlsLayout-Cju9H0m2.js} +1 -1
- package/dist/assets/{useEffectiveDirectory-DT_EmmM0.js → useEffectiveDirectory-8QrZ__Q1.js} +1 -1
- package/dist/assets/{useMobileNavigationStore-gXfZxA1A.js → useMobileNavigationStore-BZYNB0CE.js} +1 -1
- package/dist/assets/{useSessionAutoCleanup-CsVhR6FK.js → useSessionAutoCleanup-CKKtjnuX.js} +1 -1
- package/dist/assets/{useWorkerHighlightedLines-C1rC3WQe.js → useWorkerHighlightedLines-DzP14_K3.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/scheduled-tasks/DOCUMENTATION.md +10 -0
- package/server/lib/scheduled-tasks/run-history-store.js +32 -6
- package/server/lib/scheduled-tasks/run-history-store.test.js +74 -0
- package/server/lib/scheduled-tasks/runtime.js +21 -5
- package/server/lib/scheduled-tasks/runtime.test.js +71 -0
- package/dist/assets/MarkdownRenderer-BrOPSCOy.js +0 -2
- package/dist/assets/MobileSurface-B_jx2mRT.js +0 -2
package/dist/assets/{useWorkerHighlightedLines-C1rC3WQe.js → useWorkerHighlightedLines-DzP14_K3.js}
RENAMED
|
@@ -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-DwRBC4zl.js";import{nt as i,rt as a}from"./vendor-base-ui-CnHfUmDN.js";import{n as o}from"./platform-DQ5_LNKO.js";import{_ as s}from"./useUIStore-CxOoCv7B.js";import{a as c,n as l}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{n as u}from"./vendor-react-DLPElpoQ.js";import{n as d}from"./clipboard-GUUNlWIv.js";import{t as f}from"./utils-2ZK8yboQ.js";import{n as p}from"./Icon-D1BcR8Tz.js";import{t as m}from"./button-9R-WgVMl.js";import{i as h,n as g,t as _}from"./tooltip-DSjr26A_.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{n as y}from"./markdownTheme-DOfGg-A7.js";import{n as b}from"./MarkdownRenderer-BrOPSCOy.js";import{a as x,n as S,o as C,t as w}from"./markdown-worker-CptoICmq.js";import{a as T,i as E,o as D,t as ee}from"./imageSource-BlAJJUEI.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.js";var O=e(a(),1),k=u(),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)(p,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(p,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(p,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let m=u,v=r?`step`:void 0,y=r&&`bg-[var(--surface-muted)] before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-[var(--status-info)]`,b;t[5]===y?b=t[6]:(b=f(`group relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)] items-start gap-2.5`,I,y),t[5]=y,t[6]=b);let x;t[7]!==m||t[8]!==l?(x=(0,A.jsx)(h,{asChild:!0,children:(0,A.jsx)(`span`,{className:`flex size-4 items-center justify-center`,"aria-label":l,children:m})}),t[7]=m,t[8]=l,t[9]=x):x=t[9];let S;t[10]===l?S=t[11]:(S=(0,A.jsx)(g,{side:`left`,sideOffset:6,children:l}),t[10]=l,t[11]=S);let C;t[12]!==x||t[13]!==S?(C=(0,A.jsxs)(_,{children:[x,S]}),t[12]=x,t[13]=S,t[14]=C):C=t[14];let w=ue[o],T;t[15]===w?T=t[16]:(T=f(`block whitespace-normal break-words`,w),t[15]=w,t[16]=T);let E;t[17]!==T||t[18]!==n.content?(E=(0,A.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,A.jsx)(`span`,{className:T,children:n.content})}),t[17]=T,t[18]=n.content,t[19]=E):E=t[19];let D;return t[20]!==i||t[21]!==E||t[22]!==v||t[23]!==b||t[24]!==C?(D=(0,A.jsxs)(`li`,{ref:i,"aria-current":v,className:b,children:[C,E]}),t[20]=i,t[21]=E,t[22]=v,t[23]=b,t[24]=C,t[25]=D):D=t[25],D},z=new Set([`in_progress`,`pending`,`completed`,`cancelled`]),B=`image/png`,V=c(`OpenChamberMedia`),H=e=>{let t=e.toLowerCase().split(`;`)[0]?.trim()||B;if(t===`image/jpeg`||t===`image/jpg`)return`jpg`;if(t===`image/webp`)return`webp`;if(t===`image/gif`)return`gif`;if(t===`image/svg+xml`)return`svg`;if(t===`image/png`)return`png`;let n=t.split(`/`)[1];return n&&/^[a-z0-9.+-]+$/i.test(n)?n:`png`},U=(e,t)=>{let n=`image.${H(t)}`,r=(((e||``).trim()||n).split(/[\\/]/).pop()||n).replace(/[^\w.\- ()[\]]+/g,`_`).replace(/^\.+/,``);return r?/\.[a-z0-9]{1,8}$/i.test(r)?r:`${r}.${H(t)}`:n},W=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{if(typeof r.result==`string`){t(r.result);return}n(Error(`Failed to encode image`))},r.onerror=()=>n(r.error??Error(`Failed to encode image`)),r.readAsDataURL(e)}),de=async e=>{let t=await W(e),n=t.indexOf(`,`);return n>=0?t.slice(n+1):t},fe=(e,t)=>{let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),window.setTimeout(()=>URL.revokeObjectURL(n),1e3)},G=async(e,t)=>{let n=await fetch(e,{signal:t,cache:`no-store`});if(!n.ok)throw Error(`Image fetch failed (${n.status})`);return n.blob()},pe=async(e,t=B)=>{if(!e.naturalWidth||!e.naturalHeight)return null;let n=e.currentSrc||e.src;if(n&&(/^(?:blob:|data:|openchamber-asset:)/i.test(n)||/^https?:/i.test(n)||/^\/api(?=\/|[?#]|$)/.test(n)))try{let e=await G(n);if(e.size>0)return e}catch{}try{let n=document.createElement(`canvas`);n.width=e.naturalWidth,n.height=e.naturalHeight;let r=n.getContext(`2d`);if(!r)return null;r.drawImage(e,0,0);let i=t.startsWith(`image/`)?t:B,a=await new Promise(e=>{n.toBlob(t=>e(t),i===`image/jpg`?`image/jpeg`:i)});return a&&a.size>0?a:null}catch{return null}},me=async(e,t)=>{let n=``;try{return n=await 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()||l===void 0?!1:l.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-zIalUnbb.js";import{Cn as n,tn as r}from"./persistence-DwRBC4zl.js";import{nt as i,rt as a}from"./vendor-base-ui-CnHfUmDN.js";import{n as o}from"./platform-DQ5_LNKO.js";import{_ as s}from"./useUIStore-CxOoCv7B.js";import{a as c,n as l}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{n as u}from"./vendor-react-DLPElpoQ.js";import{n as d}from"./clipboard-GUUNlWIv.js";import{t as f}from"./utils-2ZK8yboQ.js";import{n as p}from"./Icon-D1BcR8Tz.js";import{t as m}from"./button-9R-WgVMl.js";import{i as h,n as g,t as _}from"./tooltip-DSjr26A_.js";import{n as v}from"./useThemeSystem-DMzWVJaW.js";import{n as y}from"./markdownTheme-DOfGg-A7.js";import{n as b}from"./MarkdownRenderer-Ym-7pIpr.js";import{a as x,n as S,o as C,t as w}from"./markdown-worker-CptoICmq.js";import{a as T,i as E,o as D,t as ee}from"./imageSource-BlAJJUEI.js";import{t as te}from"./vendor-tanstack-react-virtual-tlDgH6PG.js";var O=e(a(),1),k=u(),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)(p,{name:`record-circle`,className:`h-3.5 w-3.5 text-[var(--status-info)]`,"aria-hidden":`true`}):o===`completed`?(0,A.jsx)(p,{name:`checkbox-circle`,className:`h-3.5 w-3.5 text-[var(--status-success)]`,"aria-hidden":`true`}):(0,A.jsx)(p,{name:`time`,className:`h-3.5 w-3.5 text-muted-foreground`,"aria-hidden":`true`}),t[3]=o,t[4]=u);let m=u,v=r?`step`:void 0,y=r&&`bg-[var(--surface-muted)] before:absolute before:inset-y-2 before:left-0 before:w-0.5 before:rounded-full before:bg-[var(--status-info)]`,b;t[5]===y?b=t[6]:(b=f(`group relative grid min-w-0 grid-cols-[1rem_minmax(0,1fr)] items-start gap-2.5`,I,y),t[5]=y,t[6]=b);let x;t[7]!==m||t[8]!==l?(x=(0,A.jsx)(h,{asChild:!0,children:(0,A.jsx)(`span`,{className:`flex size-4 items-center justify-center`,"aria-label":l,children:m})}),t[7]=m,t[8]=l,t[9]=x):x=t[9];let S;t[10]===l?S=t[11]:(S=(0,A.jsx)(g,{side:`left`,sideOffset:6,children:l}),t[10]=l,t[11]=S);let C;t[12]!==x||t[13]!==S?(C=(0,A.jsxs)(_,{children:[x,S]}),t[12]=x,t[13]=S,t[14]=C):C=t[14];let w=ue[o],T;t[15]===w?T=t[16]:(T=f(`block whitespace-normal break-words`,w),t[15]=w,t[16]=T);let E;t[17]!==T||t[18]!==n.content?(E=(0,A.jsx)(`span`,{className:`min-w-0 flex-1`,children:(0,A.jsx)(`span`,{className:T,children:n.content})}),t[17]=T,t[18]=n.content,t[19]=E):E=t[19];let D;return t[20]!==i||t[21]!==E||t[22]!==v||t[23]!==b||t[24]!==C?(D=(0,A.jsxs)(`li`,{ref:i,"aria-current":v,className:b,children:[C,E]}),t[20]=i,t[21]=E,t[22]=v,t[23]=b,t[24]=C,t[25]=D):D=t[25],D},z=new Set([`in_progress`,`pending`,`completed`,`cancelled`]),B=`image/png`,V=c(`OpenChamberMedia`),H=e=>{let t=e.toLowerCase().split(`;`)[0]?.trim()||B;if(t===`image/jpeg`||t===`image/jpg`)return`jpg`;if(t===`image/webp`)return`webp`;if(t===`image/gif`)return`gif`;if(t===`image/svg+xml`)return`svg`;if(t===`image/png`)return`png`;let n=t.split(`/`)[1];return n&&/^[a-z0-9.+-]+$/i.test(n)?n:`png`},U=(e,t)=>{let n=`image.${H(t)}`,r=(((e||``).trim()||n).split(/[\\/]/).pop()||n).replace(/[^\w.\- ()[\]]+/g,`_`).replace(/^\.+/,``);return r?/\.[a-z0-9]{1,8}$/i.test(r)?r:`${r}.${H(t)}`:n},W=e=>new Promise((t,n)=>{let r=new FileReader;r.onload=()=>{if(typeof r.result==`string`){t(r.result);return}n(Error(`Failed to encode image`))},r.onerror=()=>n(r.error??Error(`Failed to encode image`)),r.readAsDataURL(e)}),de=async e=>{let t=await W(e),n=t.indexOf(`,`);return n>=0?t.slice(n+1):t},fe=(e,t)=>{let n=URL.createObjectURL(e),r=document.createElement(`a`);r.href=n,r.download=t,document.body.appendChild(r),r.click(),document.body.removeChild(r),window.setTimeout(()=>URL.revokeObjectURL(n),1e3)},G=async(e,t)=>{let n=await fetch(e,{signal:t,cache:`no-store`});if(!n.ok)throw Error(`Image fetch failed (${n.status})`);return n.blob()},pe=async(e,t=B)=>{if(!e.naturalWidth||!e.naturalHeight)return null;let n=e.currentSrc||e.src;if(n&&(/^(?:blob:|data:|openchamber-asset:)/i.test(n)||/^https?:/i.test(n)||/^\/api(?=\/|[?#]|$)/.test(n)))try{let e=await G(n);if(e.size>0)return e}catch{}try{let n=document.createElement(`canvas`);n.width=e.naturalWidth,n.height=e.naturalHeight;let r=n.getContext(`2d`);if(!r)return null;r.drawImage(e,0,0);let i=t.startsWith(`image/`)?t:B,a=await new Promise(e=>{n.toBlob(t=>e(t),i===`image/jpg`?`image/jpeg`:i)});return a&&a.size>0?a:null}catch{return null}},me=async(e,t)=>{let n=``;try{return n=await 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()||l===void 0?!1:l.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-B21k2oEx.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">
|
|
@@ -572,7 +572,7 @@
|
|
|
572
572
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-CfgOfnZk.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-kj6kuVyP.js">
|
|
576
576
|
<link rel="stylesheet" crossorigin href="/assets/src-CO9q_82J.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-Bp8luloI.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">
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-CfgOfnZk.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-kj6kuVyP.js">
|
|
98
98
|
<link rel="stylesheet" crossorigin href="/assets/src-CO9q_82J.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-BfgTp3XO.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">
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
<link rel="modulepreload" crossorigin href="/assets/terminalApi-CfgOfnZk.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-kj6kuVyP.js">
|
|
87
87
|
<link rel="stylesheet" crossorigin href="/assets/src-CO9q_82J.css">
|
|
88
88
|
</head>
|
|
89
89
|
<body class="h-full bg-background text-foreground">
|
package/package.json
CHANGED
|
@@ -25,6 +25,8 @@ Server-owned scheduled task runtime and routes for OpenChamber-only automation.
|
|
|
25
25
|
- Independent SQLite file `scheduled-task-runs.sqlite` (WAL)
|
|
26
26
|
- Keyset-paginated list of run records
|
|
27
27
|
- On open, converges leftover `running` rows to `error` with an interrupted message
|
|
28
|
+
- Scheduled runs claim `(project_id, task_id, slot_at)` so multiple OpenChamber
|
|
29
|
+
processes sharing a data dir cannot occupy the same fire slot
|
|
28
30
|
|
|
29
31
|
- `packages/web/server/lib/scheduled-tasks/routes.js`
|
|
30
32
|
- Global scheduled task list endpoint with per-project partial-result handling
|
|
@@ -101,6 +103,11 @@ Persisted columns:
|
|
|
101
103
|
| `started_at` | Epoch ms |
|
|
102
104
|
| `finished_at` | Nullable epoch ms |
|
|
103
105
|
| `duration_ms` | Nullable |
|
|
106
|
+
| `slot_at` | Scheduled occupancy key (the armed `nextRunAt`). Null for manual runs. List DTO omits this column. |
|
|
107
|
+
|
|
108
|
+
Partial unique index `scheduled_task_run_scheduled_slot` on
|
|
109
|
+
`(project_id, task_id, slot_at)` where `trigger = 'scheduled' AND slot_at IS NOT NULL`.
|
|
110
|
+
A second `startRun` for the same slot throws `SCHEDULED_SLOT_CLAIMED`.
|
|
104
111
|
|
|
105
112
|
Indexes support `started_at DESC, run_id DESC` listing with project/task filters.
|
|
106
113
|
|
|
@@ -168,6 +175,9 @@ failure preserves tasks from completed projects and adds that project ID to
|
|
|
168
175
|
Every actual run (timer or manual):
|
|
169
176
|
|
|
170
177
|
1. Allocate a unique `runID` and persist `status=running` in the history store.
|
|
178
|
+
Timer fires pass the armed `nextRunAt` as `slotAt`. A duplicate scheduled
|
|
179
|
+
slot claim skips the run: no session, no task-state write, no notification.
|
|
180
|
+
The losing scheduler arms the next occurrence and returns `{ skipped: true }`.
|
|
171
181
|
2. Persist task state `lastStatus=running`.
|
|
172
182
|
3. Create a per-run `AbortController` and race `runTaskWithWatchdog` against
|
|
173
183
|
`maxRunDurationMs` (default 2 hours). Only this watchdog timeout aborts
|
|
@@ -8,6 +8,8 @@ const require = createRequire(import.meta.url);
|
|
|
8
8
|
const DEFAULT_LIMIT = 20;
|
|
9
9
|
const MAX_LIMIT = 100;
|
|
10
10
|
const INTERRUPTED_ERROR = 'Run interrupted by process restart';
|
|
11
|
+
export const SCHEDULED_SLOT_CLAIMED_CODE = 'SCHEDULED_SLOT_CLAIMED';
|
|
12
|
+
const SQLITE_UNIQUE_CODES = new Set(['SQLITE_CONSTRAINT', 'SQLITE_CONSTRAINT_UNIQUE']);
|
|
11
13
|
|
|
12
14
|
const asNonEmptyString = (value) => {
|
|
13
15
|
if (typeof value !== 'string') {
|
|
@@ -105,6 +107,18 @@ export const createScheduledTaskRunHistoryStore = ({ dbPath, clock = () => Date.
|
|
|
105
107
|
ON scheduled_task_run (project_id, task_id, started_at DESC, run_id DESC);
|
|
106
108
|
`);
|
|
107
109
|
|
|
110
|
+
const hasSlotAt = db.prepare(`
|
|
111
|
+
SELECT 1 AS ok FROM pragma_table_info('scheduled_task_run') WHERE name = 'slot_at'
|
|
112
|
+
`).get();
|
|
113
|
+
if (!hasSlotAt) {
|
|
114
|
+
db.exec('ALTER TABLE scheduled_task_run ADD COLUMN slot_at INTEGER');
|
|
115
|
+
}
|
|
116
|
+
db.exec(`
|
|
117
|
+
CREATE UNIQUE INDEX IF NOT EXISTS scheduled_task_run_scheduled_slot
|
|
118
|
+
ON scheduled_task_run (project_id, task_id, slot_at)
|
|
119
|
+
WHERE trigger = 'scheduled' AND slot_at IS NOT NULL
|
|
120
|
+
`);
|
|
121
|
+
|
|
108
122
|
const now = () => Math.trunc(clock());
|
|
109
123
|
|
|
110
124
|
const convergeInterruptedRuns = () => {
|
|
@@ -137,17 +151,29 @@ export const createScheduledTaskRunHistoryStore = ({ dbPath, clock = () => Date.
|
|
|
137
151
|
const trigger = record.trigger === 'manual' ? 'manual' : 'scheduled';
|
|
138
152
|
const directory = asNonEmptyString(record.directory);
|
|
139
153
|
const startedAt = asFiniteInteger(record.startedAt) ?? now();
|
|
154
|
+
const slotAt = trigger === 'scheduled'
|
|
155
|
+
? asFiniteInteger(record.slotAt ?? record.slot_at)
|
|
156
|
+
: null;
|
|
140
157
|
|
|
141
158
|
if (!projectId || !taskId) {
|
|
142
159
|
throw new Error('projectId and taskId are required');
|
|
143
160
|
}
|
|
144
161
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
162
|
+
try {
|
|
163
|
+
db.prepare(`
|
|
164
|
+
INSERT INTO scheduled_task_run (
|
|
165
|
+
run_id, project_id, task_id, task_name, trigger, status,
|
|
166
|
+
session_id, directory, error, started_at, finished_at, duration_ms, slot_at
|
|
167
|
+
) VALUES (?, ?, ?, ?, ?, 'running', NULL, ?, NULL, ?, NULL, NULL, ?)
|
|
168
|
+
`).run(id, projectId, taskId, taskName, trigger, directory, startedAt, slotAt);
|
|
169
|
+
} catch (error) {
|
|
170
|
+
if (slotAt !== null && SQLITE_UNIQUE_CODES.has(error?.code)) {
|
|
171
|
+
const claimed = new Error('scheduled slot already claimed');
|
|
172
|
+
claimed.code = SCHEDULED_SLOT_CLAIMED_CODE;
|
|
173
|
+
throw claimed;
|
|
174
|
+
}
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
151
177
|
|
|
152
178
|
return rowToDto(db.prepare('SELECT * FROM scheduled_task_run WHERE run_id = ?').get(id));
|
|
153
179
|
};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { afterEach, describe, expect, it } from 'vitest';
|
|
5
6
|
import { createScheduledTaskRunHistoryStore } from './run-history-store.js';
|
|
6
7
|
|
|
8
|
+
const require = createRequire(import.meta.url);
|
|
9
|
+
|
|
7
10
|
const directories = [];
|
|
8
11
|
|
|
9
12
|
const createTempDbPath = () => {
|
|
@@ -26,6 +29,7 @@ const startSample = (store, overrides = {}) => store.startRun({
|
|
|
26
29
|
trigger: overrides.trigger ?? 'scheduled',
|
|
27
30
|
directory: overrides.directory ?? '/tmp/project-a',
|
|
28
31
|
startedAt: overrides.startedAt,
|
|
32
|
+
slotAt: overrides.slotAt,
|
|
29
33
|
});
|
|
30
34
|
|
|
31
35
|
describe('scheduled task run history store', () => {
|
|
@@ -160,4 +164,74 @@ describe('scheduled task run history store', () => {
|
|
|
160
164
|
expect(() => store.listRuns({ limit: -3 })).toThrow(/limit/i);
|
|
161
165
|
store.close();
|
|
162
166
|
});
|
|
167
|
+
|
|
168
|
+
it('lets only one scheduled startRun occupy a slot, including across store handles', () => {
|
|
169
|
+
const dbPath = createTempDbPath();
|
|
170
|
+
const first = createScheduledTaskRunHistoryStore({ dbPath });
|
|
171
|
+
startSample(first, { id: 'run-a', slotAt: 1_700_000_000_000 });
|
|
172
|
+
|
|
173
|
+
expect(() => startSample(first, { id: 'run-b', slotAt: 1_700_000_000_000 })).toThrow(
|
|
174
|
+
/already claimed/,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const second = createScheduledTaskRunHistoryStore({ dbPath });
|
|
178
|
+
expect(() => startSample(second, { id: 'run-c', slotAt: 1_700_000_000_000 })).toThrow(
|
|
179
|
+
/already claimed/,
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
startSample(first, { id: 'run-next-slot', slotAt: 1_700_000_000_000 + 60_000 });
|
|
183
|
+
startSample(first, {
|
|
184
|
+
id: 'run-manual',
|
|
185
|
+
trigger: 'manual',
|
|
186
|
+
slotAt: 1_700_000_000_000,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
expect(first.listRuns({}).runs.map((run) => run.id).sort()).toEqual([
|
|
190
|
+
'run-a',
|
|
191
|
+
'run-manual',
|
|
192
|
+
'run-next-slot',
|
|
193
|
+
].sort());
|
|
194
|
+
|
|
195
|
+
first.close();
|
|
196
|
+
second.close();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it('adds slot occupancy to databases created before slot_at existed', () => {
|
|
200
|
+
const dbPath = createTempDbPath();
|
|
201
|
+
const Database = require('better-sqlite3');
|
|
202
|
+
const legacy = new Database(dbPath);
|
|
203
|
+
legacy.exec(`
|
|
204
|
+
CREATE TABLE scheduled_task_run (
|
|
205
|
+
run_id TEXT PRIMARY KEY NOT NULL,
|
|
206
|
+
project_id TEXT NOT NULL,
|
|
207
|
+
task_id TEXT NOT NULL,
|
|
208
|
+
task_name TEXT NOT NULL,
|
|
209
|
+
trigger TEXT NOT NULL,
|
|
210
|
+
status TEXT NOT NULL,
|
|
211
|
+
session_id TEXT,
|
|
212
|
+
directory TEXT,
|
|
213
|
+
error TEXT,
|
|
214
|
+
started_at INTEGER NOT NULL,
|
|
215
|
+
finished_at INTEGER,
|
|
216
|
+
duration_ms INTEGER
|
|
217
|
+
);
|
|
218
|
+
`);
|
|
219
|
+
legacy.prepare(`
|
|
220
|
+
INSERT INTO scheduled_task_run (
|
|
221
|
+
run_id, project_id, task_id, task_name, trigger, status,
|
|
222
|
+
session_id, directory, error, started_at, finished_at, duration_ms
|
|
223
|
+
) VALUES ('legacy-run', 'project-a', 'task-1', 'Morning Sync', 'scheduled',
|
|
224
|
+
'success', NULL, '/tmp/project-a', NULL, 50, 60, 10)
|
|
225
|
+
`).run();
|
|
226
|
+
legacy.close();
|
|
227
|
+
|
|
228
|
+
const store = createScheduledTaskRunHistoryStore({ dbPath });
|
|
229
|
+
expect(store.listRuns({}).runs).toHaveLength(1);
|
|
230
|
+
startSample(store, { id: 'run-a', slotAt: 1_700_000_000_000 });
|
|
231
|
+
expect(() => startSample(store, { id: 'run-b', slotAt: 1_700_000_000_000 })).toThrow(
|
|
232
|
+
/already claimed/,
|
|
233
|
+
);
|
|
234
|
+
expect(store.listRuns({}).runs.map((run) => run.id)).toEqual(['run-a', 'legacy-run']);
|
|
235
|
+
store.close();
|
|
236
|
+
});
|
|
163
237
|
});
|
|
@@ -3,6 +3,7 @@ import { createOpencodeClient } from '@opencode-ai/sdk/v2';
|
|
|
3
3
|
import { DateTime } from 'luxon';
|
|
4
4
|
import parser from 'cron-parser';
|
|
5
5
|
import { expandSnippets } from '../opencode/snippets.js';
|
|
6
|
+
import { SCHEDULED_SLOT_CLAIMED_CODE } from './run-history-store.js';
|
|
6
7
|
|
|
7
8
|
const DEFAULT_GLOBAL_CONCURRENCY = 4;
|
|
8
9
|
const DEFAULT_PROJECT_CONCURRENCY = 2;
|
|
@@ -535,7 +536,7 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
535
536
|
if (!task || !task.enabled) {
|
|
536
537
|
return;
|
|
537
538
|
}
|
|
538
|
-
queueTaskRun(projectID, taskID, 'scheduled');
|
|
539
|
+
queueTaskRun(projectID, taskID, 'scheduled', nextRunAt);
|
|
539
540
|
pumpQueue();
|
|
540
541
|
}, boundedDelay);
|
|
541
542
|
|
|
@@ -669,13 +670,13 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
669
670
|
}
|
|
670
671
|
};
|
|
671
672
|
|
|
672
|
-
const queueTaskRun = (projectID, taskID, reason) => {
|
|
673
|
+
const queueTaskRun = (projectID, taskID, reason, slotAt) => {
|
|
673
674
|
const taskKey = buildTaskKey(projectID, taskID);
|
|
674
675
|
if (queuedTaskKeys.has(taskKey) || runningTaskKeys.has(taskKey)) {
|
|
675
676
|
return;
|
|
676
677
|
}
|
|
677
678
|
queuedTaskKeys.add(taskKey);
|
|
678
|
-
queue.push({ projectID, taskID, reason });
|
|
679
|
+
queue.push({ projectID, taskID, reason, slotAt });
|
|
679
680
|
};
|
|
680
681
|
|
|
681
682
|
const canRunTask = (projectID) => {
|
|
@@ -1231,7 +1232,7 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
1231
1232
|
}
|
|
1232
1233
|
};
|
|
1233
1234
|
|
|
1234
|
-
const runTask = async (projectID, taskID, reason) => {
|
|
1235
|
+
const runTask = async (projectID, taskID, reason, slotAt) => {
|
|
1235
1236
|
const taskMap = tasksByProject.get(projectID);
|
|
1236
1237
|
const task = taskMap?.get(taskID);
|
|
1237
1238
|
if (!task || !task.enabled) {
|
|
@@ -1264,6 +1265,9 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
1264
1265
|
if (runHistoryStore && typeof runHistoryStore.startRun === 'function') {
|
|
1265
1266
|
try {
|
|
1266
1267
|
runID = crypto.randomUUID();
|
|
1268
|
+
const resolvedSlotAt = reason === 'scheduled' && Number.isFinite(slotAt)
|
|
1269
|
+
? Math.trunc(slotAt)
|
|
1270
|
+
: undefined;
|
|
1267
1271
|
runHistoryStore.startRun({
|
|
1268
1272
|
id: runID,
|
|
1269
1273
|
projectId: projectID,
|
|
@@ -1272,8 +1276,20 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
1272
1276
|
trigger: reason === 'manual' ? 'manual' : 'scheduled',
|
|
1273
1277
|
directory: projectPath,
|
|
1274
1278
|
startedAt: runStartedAt,
|
|
1279
|
+
...(resolvedSlotAt !== undefined ? { slotAt: resolvedSlotAt } : {}),
|
|
1275
1280
|
});
|
|
1276
1281
|
} catch (error) {
|
|
1282
|
+
if (error?.code === SCHEDULED_SLOT_CLAIMED_CODE) {
|
|
1283
|
+
const nextRunAt = computeNextRunAt(task, Date.now());
|
|
1284
|
+
if (task.enabled && Number.isFinite(nextRunAt)) {
|
|
1285
|
+
scheduleTask(projectID, taskID, nextRunAt);
|
|
1286
|
+
}
|
|
1287
|
+
logger.info?.('[ScheduledTasks] skipped duplicate scheduled slot', {
|
|
1288
|
+
projectID,
|
|
1289
|
+
taskID,
|
|
1290
|
+
});
|
|
1291
|
+
return { ok: false, skipped: true };
|
|
1292
|
+
}
|
|
1277
1293
|
errorMessage = safeErrorMessage(error);
|
|
1278
1294
|
runID = null;
|
|
1279
1295
|
logger.warn?.('[ScheduledTasks] failed to start run history', {
|
|
@@ -1547,7 +1563,7 @@ export const createScheduledTasksRuntime = (deps) => {
|
|
|
1547
1563
|
queuedTaskKeys.delete(taskKey);
|
|
1548
1564
|
consumed = true;
|
|
1549
1565
|
|
|
1550
|
-
void runTask(item.projectID, item.taskID, item.reason).finally(() => {
|
|
1566
|
+
void runTask(item.projectID, item.taskID, item.reason, item.slotAt).finally(() => {
|
|
1551
1567
|
pumpQueue();
|
|
1552
1568
|
});
|
|
1553
1569
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
1
4
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
5
|
|
|
3
6
|
vi.mock('@opencode-ai/sdk/v2', () => ({
|
|
@@ -5,6 +8,7 @@ vi.mock('@opencode-ai/sdk/v2', () => ({
|
|
|
5
8
|
}));
|
|
6
9
|
|
|
7
10
|
const { createOpencodeClient } = await import('@opencode-ai/sdk/v2');
|
|
11
|
+
const { createScheduledTaskRunHistoryStore } = await import('./run-history-store.js');
|
|
8
12
|
const {
|
|
9
13
|
computeNextRunAt,
|
|
10
14
|
createScheduledTasksRuntime,
|
|
@@ -1326,3 +1330,70 @@ describe('scheduled-tasks run history and session lifecycle', () => {
|
|
|
1326
1330
|
vi.unstubAllGlobals();
|
|
1327
1331
|
});
|
|
1328
1332
|
});
|
|
1333
|
+
|
|
1334
|
+
describe('scheduled-tasks cross-process slot occupancy', () => {
|
|
1335
|
+
it('lets only one runtime occupy a scheduled slot when two schedulers share a history store', async () => {
|
|
1336
|
+
const random = vi.spyOn(Math, 'random').mockReturnValue(0);
|
|
1337
|
+
vi.useFakeTimers();
|
|
1338
|
+
vi.setSystemTime(Date.UTC(2026, 0, 1, 9, 29, 54));
|
|
1339
|
+
|
|
1340
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'scheduled-slot-'));
|
|
1341
|
+
const store = createScheduledTaskRunHistoryStore({
|
|
1342
|
+
dbPath: path.join(dir, 'scheduled-task-runs.sqlite'),
|
|
1343
|
+
});
|
|
1344
|
+
const first = { stop() {} };
|
|
1345
|
+
const second = { stop() {} };
|
|
1346
|
+
try {
|
|
1347
|
+
const dueTask = {
|
|
1348
|
+
...scheduledTask,
|
|
1349
|
+
schedule: {
|
|
1350
|
+
kind: 'daily',
|
|
1351
|
+
times: ['09:30'],
|
|
1352
|
+
timezone: 'UTC',
|
|
1353
|
+
},
|
|
1354
|
+
};
|
|
1355
|
+
const stateWrites = [];
|
|
1356
|
+
const notifyTaskRun = vi.fn(async () => {});
|
|
1357
|
+
const createSharedRuntime = () => createScheduledTasksRuntime({
|
|
1358
|
+
projectConfigRuntime: {
|
|
1359
|
+
listScheduledTasks: vi.fn(async () => [dueTask]),
|
|
1360
|
+
updateScheduledTaskState: vi.fn(async (_projectID, _taskID, state) => {
|
|
1361
|
+
stateWrites.push(state);
|
|
1362
|
+
return { task: { ...dueTask, state: { ...dueTask.state, ...state } } };
|
|
1363
|
+
}),
|
|
1364
|
+
upsertScheduledTask: vi.fn(async (_projectID, task) => ({ task })),
|
|
1365
|
+
},
|
|
1366
|
+
listProjects: vi.fn(async () => [{ id: 'project-1', path: '/tmp/project-1' }]),
|
|
1367
|
+
buildOpenCodeUrl: vi.fn(() => 'http://127.0.0.1:4096'),
|
|
1368
|
+
getOpenCodeAuthHeaders: vi.fn(() => ({})),
|
|
1369
|
+
waitForOpenCodeReady: vi.fn(async () => {
|
|
1370
|
+
throw new Error('OpenCode unavailable');
|
|
1371
|
+
}),
|
|
1372
|
+
logger: { info: vi.fn(), warn: vi.fn() },
|
|
1373
|
+
runHistoryStore: store,
|
|
1374
|
+
notifyTaskRun,
|
|
1375
|
+
});
|
|
1376
|
+
|
|
1377
|
+
Object.assign(first, createSharedRuntime());
|
|
1378
|
+
Object.assign(second, createSharedRuntime());
|
|
1379
|
+
await first.start();
|
|
1380
|
+
await second.start();
|
|
1381
|
+
await vi.advanceTimersByTimeAsync(6_000);
|
|
1382
|
+
await Promise.resolve();
|
|
1383
|
+
await Promise.resolve();
|
|
1384
|
+
await Promise.resolve();
|
|
1385
|
+
|
|
1386
|
+
expect(store.listRuns({}).runs).toHaveLength(1);
|
|
1387
|
+
expect(notifyTaskRun).toHaveBeenCalledTimes(1);
|
|
1388
|
+
expect(stateWrites.filter((state) => state.lastStatus === 'running')).toHaveLength(1);
|
|
1389
|
+
expect(stateWrites.filter((state) => state.lastStatus === 'error')).toHaveLength(1);
|
|
1390
|
+
} finally {
|
|
1391
|
+
first.stop();
|
|
1392
|
+
second.stop();
|
|
1393
|
+
store.close();
|
|
1394
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
1395
|
+
random.mockRestore();
|
|
1396
|
+
vi.useRealTimers();
|
|
1397
|
+
}
|
|
1398
|
+
});
|
|
1399
|
+
});
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/MarkstreamRendererImpl-Bwxkdtts.js","assets/rolldown-runtime-C0FnF6B9.js","assets/vendor-base-ui-CnHfUmDN.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-BnW6GxJt.js","assets/vendor-lodash-es-DfLbG5Af.js","assets/vendor-js-cookie-hSOiFTtX.js","assets/useMobileNavigationStore-gXfZxA1A.js","assets/runtime-auth-D66yq6ie.js","assets/runtime-switch-LvWDU-SL.js","assets/runtime-fetch-zIalUnbb.js","assets/persistence-DwRBC4zl.js","assets/vendor-zustand-B4dlGEM2.js","assets/useUIStore-CxOoCv7B.js","assets/vendor-pathe-vBmvQE8f.js","assets/vendor-tanstack-query-core-BWz0ose6.js","assets/platform-DQ5_LNKO.js","assets/vendor-opencode-sdk-C07HQypa.js","assets/vendor-tanstack-react-query-D7pys_c9.js","assets/vendor-sonner-DVzioF3d.js","assets/clipboard-GUUNlWIv.js","assets/store-ClnJdJSj.js","assets/useAssistantUIStore-CLPCNoj_.js","assets/vendor-fuse.js-DB5wDJbI.js","assets/utils-2ZK8yboQ.js","assets/vendor-class-variance-authority-BLUaYARZ.js","assets/vendor-tailwind-merge-BicNWLTg.js","assets/useThemeSystem-DMzWVJaW.js","assets/useRuntimeAPIs-DSLXJybW.js","assets/url-CMQwHq4k.js","assets/useEffectiveDirectory-DT_EmmM0.js","assets/markdownHeightCache-BL8CUQ0M.js","assets/dualLimitLru-D8Sphgua.js","assets/MarkdownRendererImpl-BWTMbqp6.js","assets/vendor-katex--B5dHUyk.js","assets/markdownTheme-DOfGg-A7.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-CptoICmq.js","assets/FadeInOnReveal-UGwClbL_.js","assets/imageSource-BlAJJUEI.js","assets/relay-image-stream-DM7atqJs.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-B4dlGEM2.js";import{nt as n,rt as r}from"./vendor-base-ui-CnHfUmDN.js";import{o as i}from"./vendor-aparajita-capacitor-secure-storage-CjQdwfjS.js";import{n as a}from"./vendor-react-DLPElpoQ.js";import{t as o}from"./utils-2ZK8yboQ.js";import{i as s,n as c,t as l}from"./markdownHeightCache-BL8CUQ0M.js";var u=a(),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`1.19.16:${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??=i(()=>import(`./MarkstreamRendererImpl-Bwxkdtts.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??=i(()=>import(`./MarkdownRendererImpl-BWTMbqp6.js`).then(e=>e.n),__vite__mapDeps([38,1,14,13,15,16,17,2,18,19,3,20,21,22,5,39,9,10,11,25,26,12,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};
|