sessiongraph-app-darwin-arm64 1.0.10 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/package.json +2 -2
  2. package/payload/SessionGraph.app/Contents/Info.plist +2 -2
  3. package/payload/SessionGraph.app/Contents/MacOS/sessiongraph +0 -0
  4. package/payload/SessionGraph.app/Contents/Resources/resources/node +2 -2
  5. package/payload/SessionGraph.app/Contents/Resources/resources/server.mjs +163 -58
  6. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/external-links-D0O8IeG0.js +1 -0
  7. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-BNX-8Jnn.js → index-BS2Voifb.js} +1 -1
  8. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-BtLEIWKh.js → index-CIhs02tq.js} +12 -12
  9. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{index-RfmyzBnX.js → index-GTrhxXlP.js} +1 -1
  10. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/index-Vq4WYmzW.js +1 -0
  11. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/index-cVgPCrFV.css +1 -0
  12. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{mp4-worker-HFPra5JP.js → mp4-worker-Dc_1QUwS.js} +1 -1
  13. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/publishing-ofssf6d6.js +25 -0
  14. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/{scene-B_CpQ0qP.js → scene-KCDTPCOD.js} +1 -1
  15. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/share-DKeJCFAo.js +7 -0
  16. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/worker-C10U_apJ.js +2 -0
  17. package/payload/SessionGraph.app/Contents/Resources/resources/web/index.html +2 -2
  18. package/payload/SessionGraph.app/Contents/_CodeSignature/CodeResources +61 -61
  19. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/gif-worker-CghHEBpp.js +0 -1
  20. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/index-BcoCDV6F.js +0 -1
  21. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/index-BnhC5gO7.css +0 -1
  22. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/publishing-DoHRK4Ea.js +0 -26
  23. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/share-DPdu1Hbo.js +0 -8
  24. package/payload/SessionGraph.app/Contents/Resources/resources/web/assets/worker-DwqxiDWY.js +0 -2
@@ -0,0 +1,25 @@
1
+ import{h as pe,j as me,m as ge,D as be,a as ae,k as q,l as ie,t as he,P as fe,g as ye,c as we,i as V}from"./index-CIhs02tq.js";import{TimelineScene as ve}from"./scene-KCDTPCOD.js";import{s as ke,e as Se,o as Ce}from"./external-links-D0O8IeG0.js";import"./three-D_1Qt16u.js";const xe=["svg",pe,[["path",{d:"M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"}],["path",{d:"M9 18c-4.51 2-5-2-7-2"}]]],Ae={tokens:"Token counts",timestamps:"Session timestamps",messageCounts:"Message counts",messageTimestamps:"Message timestamps",model:"Model used",harness:"Harness used"},Z={tokens:!0,timestamps:!0,messageCounts:!0,messageTimestamps:!0,model:!0,harness:!0};function oe(t){const r={...Z};if(ce(t))for(const n of Object.keys(r))typeof t[n]=="boolean"&&(r[n]=t[n]);return(!r.timestamps||!r.messageCounts)&&(r.messageTimestamps=!1),r}const re=1e4,Ee=2e6,Pe=1e5,Me="Always excluded: project and session names, messages, code, paths, source IDs, and costs. Anonymous groups and recorded branch links are included. Your GitHub username identifies this profile. Your published graph will appear in Explore graphs. Selected timestamps and usage will be public.",Te=/^(?:gpt-[3-6](?:\.[0-9])?(?:-(?:turbo|mini|nano|pro|codex|astra|instant|thinking|chat|latest|preview|[0-9]{4,8}))*|o[1-4](?:-(?:mini|pro|preview|[0-9]{4,8}))*|claude-(?:(?:sonnet|opus|haiku)-[3-5](?:[.-][0-9])?|[3-5](?:-[0-9])?-(?:sonnet|opus|haiku))(?:-(?:latest|thinking|[0-9]{8}))*|gemini-[1-4](?:\.[0-9])?-(?:pro|flash)(?:-(?:lite|preview|exp|latest|[0-9]{2,4}))*|deepseek-(?:chat|reasoner|v[3-4](?:\.[0-9])?|r1)|grok-[2-5](?:\.[0-9])?(?:-(?:fast|code|reasoning|non-reasoning|[0-9]))*|kimi-k[1-3](?:\.[0-9])?(?:-thinking)?|minimax-m[1-3](?:\.[0-9])?)$/i,Le=t=>{const r=t.split("/").at(-1)||"";return r.length<=100&&Te.test(r)?r.toLowerCase():null},ce=t=>!!t&&typeof t=="object"&&!Array.isArray(t),B=(t,r)=>ce(t)&&Object.keys(t).length===r.length&&r.every(n=>Object.hasOwn(t,n)),Y=(t,r=Number.MAX_SAFE_INTEGER)=>Number.isSafeInteger(t)&&t>=0&&t<=r,W=t=>Y(t,Date.UTC(2100,0,1)),z=t=>t===null||Y(t);function de(t){const r=()=>{throw new Error("Invalid anonymous graph. Reopen the publishing preview and try again.")};if(!B(t,["version","settings","sessions"])||t.version!==1||!Array.isArray(t.sessions)||!B(t.settings,Object.keys(Z))||Object.values(t.settings).some(f=>typeof f!="boolean"))return r();const n=t.settings;if(n.messageTimestamps&&(!n.timestamps||!n.messageCounts))return r();if(t.sessions.length<1||t.sessions.length>re)throw new Error(`Choose between 1 and ${re.toLocaleString("en")} sessions to publish.`);const e=["id","group","parent","fork",...n.timestamps?["timestamps"]:[],...n.tokens?["tokens"]:[],...n.messageCounts?["messages"]:[],...n.messageTimestamps?["messageTimes"]:[],...n.model?["model"]:[],...n.harness?["harness"]:[]];let m=0;for(let f=0;f<t.sessions.length;f++){const i=t.sessions[f];if(!B(i,e)||i.id!==f||!Y(i.group,t.sessions.length-1))return r();for(const p of["parent","fork"])if(i[p]!==null&&(!Y(i[p],t.sessions.length-1)||i[p]===f))return r();if(n.timestamps&&(!B(i.timestamps,["created","lastMessageAt"])||!W(i.timestamps.created)||i.timestamps.lastMessageAt!==null&&!W(i.timestamps.lastMessageAt))||n.tokens&&!z(i.tokens)||n.messageCounts&&(!B(i.messages,["count","untimed","partial"])||!z(i.messages.count)||!z(i.messages.untimed)||typeof i.messages.partial!="boolean")||n.messageTimestamps&&(!B(i.messageTimes,["values","limited"])||!Array.isArray(i.messageTimes.values)||i.messageTimes.values.length>2e3||typeof i.messageTimes.limited!="boolean"||i.messageTimes.values.some(p=>!W(p))||(m+=i.messageTimes.values.length,m>Pe))||n.model&&i.model!==null&&(typeof i.model!="string"||Le(i.model)!==i.model)||n.harness&&i.harness!==null&&(typeof i.harness!="string"||!me(i.harness)))return r()}const o=t.sessions,l=new Uint8Array(o.length);for(let f=0;f<o.length;f++){if(l[f])continue;const i=[[f,!1]];for(;i.length;){const[p,M]=i.pop();if(M){l[p]=2;continue}if(l[p]===1)return r();if(l[p]!==2){l[p]=1,i.push([p,!0]);for(const S of[o[p].parent,o[p].fork])S!==null&&i.push([S,!1])}}}if(new TextEncoder().encode(JSON.stringify(t)).length>Ee)throw new Error("This graph is too large. Choose a smaller date range.");return t}function le(t,r){const n=de(t),e=n.sessions.filter(l=>!r||r.has(l.id)).map(l=>({id:String(l.id),projectID:String(l.group),title:`Session ${l.id+1}`,directory:"",created:l.timestamps?.created??l.id*36e5,updated:l.timestamps?.created??l.id*36e5,tokens:l.tokens??null,cost:null,archived:!1,model:l.model??"",provider:"",agent:"",source:l.harness??void 0,activity:{firstMessageAt:null,lastMessageAt:l.timestamps?.lastMessageAt??null,userMessages:0,untimedUserMessages:0},...l.parent===null?{}:{parentID:String(l.parent)},...l.fork===null?{}:{forkID:String(l.fork)}})),m=[...new Set(n.sessions.map(l=>l.group))].map(l=>({id:String(l),name:`Group ${l+1}`,directory:"",worktrees:[]})),o=ge(e.map(l=>({...l,source:void 0})),m);for(const l of o.nodes)l.session.source=n.sessions[Number(l.session.id)].harness??void 0;return o}function $e(t){const r=t.settings.tokens?t.sessions.filter(e=>typeof e.tokens=="number"):[],n=r.reduce((e,m)=>e+m.tokens,0);return{sessionCount:t.sessions.length,tokenCount:r.length&&Number.isSafeInteger(n)?n:null,tokensPartial:r.length>0&&r.length<t.sessions.length}}function ue(t){const r=$e(t),n=[`${r.sessionCount.toLocaleString()} sessions`];if(t.settings.tokens&&n.push(r.tokenCount===null?"Tokens unavailable":`${r.tokenCount.toLocaleString()} recorded tokens${r.tokensPartial?" (partial coverage)":""}`),t.settings.messageCounts){const e=t.sessions.filter(m=>m.messages?.count!=null);n.push(e.length?`${e.reduce((m,o)=>m+o.messages.count,0).toLocaleString()} recorded messages${e.length<t.sessions.length||t.sessions.some(m=>m.messages?.partial)?" (partial history)":""}`:"Message counts unavailable")}return n.join(" · ")}const Q=t=>t==null?"Unknown":t.toLocaleString(),R=t=>t===null?"Unknown":new Date(t).toLocaleString();function Ie(t,r,n={}){const e=de(r);let m=le(e);t.classList.add("public-viewer"),t.classList.toggle("public-viewer-full",!!n.fullscreen),t.innerHTML=`
2
+ <div class="public-canvas" aria-label="Interactive public session graph"></div>
3
+ <div class="public-toolbar"><button type="button" data-sessions aria-expanded="true">☷ Sessions</button><span class="public-badge">Public snapshot</span></div>
4
+ <nav class="public-view-controls" aria-label="Graph controls"><div class="public-view-switch"><button type="button" data-view="3d" aria-pressed="true">3D</button><button type="button" data-view="2d" aria-pressed="false">2D</button></div><button type="button" data-fit title="Fit view (F)">Fit view</button><button type="button" data-motion aria-pressed="true">Motion</button><button type="button" data-timeline aria-expanded="true">Timeline</button></nav>
5
+ <aside class="public-browser public-panel" aria-label="Public sessions">
6
+ <div class="public-panel-heading"><h2>Sessions <span data-count></span></h2><button type="button" data-close-list aria-label="Close sessions">×</button></div>
7
+ <label class="public-search"><span>Search public data</span><input type="search" placeholder="Session, group, model…" aria-label="Search public sessions"></label>
8
+ <div class="public-filters"><select data-group aria-label="Anonymous group"><option value="">All groups</option></select><select data-harness aria-label="Coding agent"><option value="">All agents</option></select><select data-days aria-label="Date range"><option value="0">All dates</option><option value="7">Last 7 days</option><option value="30">Last 30 days</option><option value="90">Last 90 days</option></select></div>
9
+ <div class="public-list" role="list" aria-label="Sessions"></div><button type="button" data-more hidden>Show more sessions</button>
10
+ </aside>
11
+ <aside class="public-session public-panel" aria-label="Public session details" hidden><div class="public-panel-heading"><h2 data-session-heading></h2><button type="button" data-close-detail aria-label="Close session details">×</button></div><div class="public-session-data"></div></aside>
12
+ <div class="public-tooltip" hidden></div>
13
+ <section class="public-playback public-panel" aria-label="Timeline controls"><div class="public-timeline-heading"><span data-period></span><select data-speed aria-label="Playback speed"><option value="0.5">0.5×</option><option value="1" selected>1×</option><option value="2">2×</option></select></div><div class="public-timeline-track"><button type="button" data-play aria-label="Play timeline">▶</button><div class="public-histogram-wrap"><div class="public-histogram" aria-hidden="true"></div><input type="range" min="0" max="1000" value="1000" aria-label="Graph playback position"></div><output></output></div><p data-summary></p></section>
14
+ <p class="public-hints">Drag to orbit · Scroll to zoom · <kbd>F</kbd> fit · <kbd>Esc</kbd> clear</p>
15
+ <p class="public-announcement" role="status"></p>`;const o=s=>t.querySelector(s),l=o(".public-canvas"),f=o(".public-session"),i=o(".public-session-data"),p=o(".public-list"),M=o("[data-group]"),S=o("[data-harness]"),A=o("[data-days]"),C=o("input[type=search]"),j=o("input[type=range]"),E=o("[data-play]"),y=matchMedia("(prefers-reduced-motion: reduce)"),T=new AbortController,b={...be,muted:!0,clickSounds:!1,focusDimming:!1,messageDots:e.settings.messageTimestamps};let h,w=null,L=e.sessions,O=80,D=0,P=1,a=0,c=!1,v=[],$=ae(m.nodes.map(s=>s.session));const x=()=>{cancelAnimationFrame(D),D=0,h?.setPlaying(!1),E.textContent="▶",E.setAttribute("aria-label","Play timeline")},ee=s=>{o(".public-announcement").textContent=s},N=(s,g)=>{const d=document.createElement("p"),k=document.createElement("strong");k.textContent=`${s}: `,d.append(k,g),i.append(d)};function U(s,g=!1){const d=s===null?void 0:e.sessions[Number(s)];w=d&&L.some(u=>u.id===d.id)?d.id:null,h?.select(w===null?null:String(w)),h?.setEvents([]),v=[],i.replaceChildren(),f.hidden=w===null;for(const u of p.querySelectorAll("button"))u.setAttribute("aria-pressed",String(u.dataset.session===String(w)));if(w===null||!d)return;x(),P=1,H(),o("[data-session-heading]").textContent=`Session ${d.id+1}`,N("Group",`Group ${d.group+1}`),d.timestamps&&(N("Created",R(d.timestamps.created)),N("Last message",R(d.timestamps.lastMessageAt))),"tokens"in d&&N("Tokens",Q(d.tokens)),d.messages&&(N("Messages",`${Q(d.messages.count)}${d.messages.partial?" · partial history":""}`),N("Untimed messages",Q(d.messages.untimed))),"model"in d&&N("Model",d.model??"Unknown or private alias"),"harness"in d&&N("Harness",d.harness?q(d.harness):"Unknown");for(const[u,I]of[["Fork of",d.fork],["Child of",d.parent]])if(I!==null){const _=document.createElement("p"),G=document.createElement("button");_.append(`${u} `),G.textContent=`Session ${I+1}`,G.type="button",G.disabled=!L.some(F=>F.id===I),G.onclick=()=>U(String(I),!0),_.append(G),i.append(_)}if(d.messageTimes){N("Message timestamps",`${d.messageTimes.values.length.toLocaleString()}${d.messageTimes.limited?" · limited coverage":""}`);const u=document.createElement("details"),I=document.createElement("summary");I.textContent="View published timestamps";const _=document.createElement("pre");_.textContent=d.messageTimes.values.map(R).join(`
16
+ `)||"No recorded timestamps.",u.append(I,_),i.append(u),v=d.messageTimes.values.map((G,F)=>({id:`public-${F}`,ordinal:F,kind:"message",name:"Message",role:"user",time:G,timeSource:"recorded",preview:""})),h?.setEvents(v)}const k=document.createElement("p");k.className="public-detail-note",k.textContent="Only published metadata. Names, messages, code, paths, and costs stay private.",i.append(k),g&&h?.focus(String(d.id)),ee(`Selected Session ${d.id+1}.`)}function te(){p.replaceChildren(),o("[data-count]").textContent=String(L.length);const s=new Map(m.nodes.map(g=>[Number(g.session.id),g.color]));for(const g of L.slice(0,O)){const d=document.createElement("div"),k=document.createElement("button"),u=document.createElement("span"),I=document.createElement("small");d.setAttribute("role","listitem"),k.type="button",k.dataset.session=String(g.id),k.setAttribute("aria-pressed",String(w===g.id)),k.style.setProperty("--session-color",s.get(g.id)||"#b0e9d6"),u.textContent=`Session ${g.id+1}`,I.textContent=[`Group ${g.group+1}`,g.harness?q(g.harness):"",g.model||""].filter(Boolean).join(" · "),k.append(u,I),k.onclick=()=>U(String(g.id),!0),d.append(k),p.append(d)}L.length||(p.textContent="No sessions match these filters."),o("[data-more]").hidden=O>=L.length}function H(){h?.setCutoff(P),j.value=String(Math.round(P*1e3));const s=m.start+(m.end-m.start)*P;o("output").textContent=e.settings.timestamps&&m.nodes.length?ye(s,m.end-m.start):`${$(s,P===1)} sessions`,o(".public-histogram-wrap").style.setProperty("--progress",`${P*100}%`)}function K(){x(),O=80,P=1;const s=C.value.toLowerCase().trim(),g=e.settings.timestamps&&Number(A.value)?Math.max(...e.sessions.map(u=>u.timestamps.lastMessageAt??u.timestamps.created))-Number(A.value)*864e5:0;L=e.sessions.filter(u=>(!M.value||String(u.group)===M.value)&&(!S.value||u.harness===S.value)&&(!g||Math.max(u.timestamps.created,u.timestamps.lastMessageAt??0)>=g)&&(!s||`session ${u.id+1} group ${u.group+1} ${u.model??""} ${u.harness?q(u.harness):""}`.toLowerCase().includes(s))),m=le(e,new Set(L.map(u=>u.id))),$=ae(m.nodes.map(u=>u.session)),h?.setGraph(m,!0),U(null);const d=he(m.nodes.map(u=>u.session.created),m.start,m.end,50),k=Math.max(1,...d);o(".public-histogram").replaceChildren(...d.map(u=>{const I=document.createElement("span");return I.style.height=`${Math.max(4,u/k*100)}%`,I})),o("[data-period]").textContent=e.settings.timestamps?L.length?`${new Date(m.start).toLocaleDateString()} — ${new Date(m.end).toLocaleDateString()}`:"No sessions":"Session order · timestamps not shared",o("[data-summary]").textContent=ue({...e,sessions:L}),E.disabled=!L.length,j.disabled=!L.length,te(),H()}try{h=new ve(l,{onSelect:s=>U(s),onPlaybackInterrupt:x,onHover:(s,g,d)=>{const k=o(".public-tooltip");if(k.hidden=!s,s){const u=t.getBoundingClientRect();k.textContent=s.session.title,k.style.left=`${Math.max(8,Math.min(t.clientWidth-135,g-u.left+14))}px`,k.style.top=`${Math.max(8,d-u.top-35)}px`}},onEvent:s=>{const g=v.find(d=>d.id===s);g&&(h?.focusEvent(g),ee(`Published message timestamp: ${R(g.time)}.`))},onEventHover(){}}),h.applyPreferences(b)}catch{l.textContent="3D rendering is unavailable. Explore the published data in the sessions panel.",o(".public-view-controls").hidden=!0}[...new Set(e.sessions.map(s=>s.group))].sort((s,g)=>s-g).forEach(s=>M.add(new Option(`Group ${s+1}`,String(s)))),[...new Set(e.sessions.flatMap(s=>s.harness?[s.harness]:[]))].sort().forEach(s=>S.add(new Option(q(s),s))),S.hidden=!e.settings.harness,A.hidden=!e.settings.timestamps;for(const s of[M,S,A])s.onchange=K;C.oninput=K,o("[data-more]").onclick=()=>{O+=80,te()};const J=s=>{o(".public-browser").hidden=!s,o("[data-sessions]").setAttribute("aria-expanded",String(s))};o("[data-sessions]").onclick=()=>J(o(".public-browser").hidden),o("[data-close-list]").onclick=()=>J(!1),o("[data-close-detail]").onclick=()=>U(null),o("[data-fit]").onclick=()=>h?.reset(),o("[data-timeline]").onclick=()=>{const s=o(".public-playback");s.hidden=!s.hidden,o("[data-timeline]").setAttribute("aria-expanded",String(!s.hidden))};for(const s of t.querySelectorAll("[data-view]"))s.onclick=()=>{b.view=s.dataset.view==="2d"?"2d":"3d",h?.setFlat(s.dataset.view==="2d");for(const g of t.querySelectorAll("[data-view]"))g.setAttribute("aria-pressed",String(g===s))};const X=()=>{h?.applyPreferences(b),o("button[data-motion]").setAttribute("aria-pressed",String(ie(b,y.matches)))};o("button[data-motion]").onclick=()=>{b.motion=ie(b,y.matches)?"off":"on",X()},y.addEventListener("change",X,{signal:T.signal});const se=s=>{c||(P=Math.min(1,P+Math.min(s-a,100)/fe*Number(o("[data-speed]").value)),a=s,H(),P===1?x():D=requestAnimationFrame(se))};E.onclick=()=>{if(D)return x();P>=1&&(P=0),a=performance.now(),h?.setPlaying(!0),E.textContent="Ⅱ",E.setAttribute("aria-label","Pause timeline"),D=requestAnimationFrame(se)},j.oninput=()=>{x(),P=Number(j.value)/1e3,H()},t.tabIndex=-1,t.addEventListener("keydown",s=>{s.target.matches("input, select, textarea")||s.metaKey||s.ctrlKey||s.altKey||(s.key.toLowerCase()==="f"&&(s.preventDefault(),h?.reset()),s.key==="Escape"&&U(null),s.key==="/"&&(s.preventDefault(),J(!0),C.focus()))},{signal:T.signal}),document.addEventListener("visibilitychange",()=>{document.hidden&&x(),h?.setSuspended(document.hidden)},{signal:T.signal});const ne=new IntersectionObserver(([s])=>{s.isIntersecting||x(),h?.setSuspended(!s.isIntersecting||document.hidden)});return ne.observe(t),K(),X(),{dispose(){c=!0,x(),T.abort(),ne.disconnect(),h?.dispose(),t.replaceChildren(),t.classList.remove("public-viewer","public-viewer-full")}}}function Ge(t,r){const n=document.createElement("dialog");n.className="publishing-dialog",n.setAttribute("aria-labelledby","publishing-title"),n.innerHTML=`<div class="publishing-account"><span data-account>Not signed in</span><button class="secondary-button" data-login><span data-login-label>Sign in with GitHub</span></button><button class="text-button" data-logout hidden>Sign out</button><a class="secondary-button" href="https://sessiongraph.ai/account" target="_blank" rel="noopener noreferrer" data-manage hidden>Account &amp; organizations ↗</a></div>
17
+ <div class="publishing-connect" hidden><p>Confirm this code in your browser: <strong data-code></strong></p><a class="secondary-button" data-connect target="_blank" rel="noopener noreferrer">Continue in browser ↗</a><button class="text-button" data-check>Check login</button><label class="publishing-browser-link">Browser link<input type="text" data-connect-url readonly aria-label="Browser sign-in link"></label><button class="text-button" data-copy-link>Copy browser link</button></div>
18
+ <p role="status" class="publishing-status"></p>
19
+ <p class="publishing-disclosure"></p><p class="publishing-scope"></p>
20
+ <fieldset class="publishing-fields"><legend>Publishing settings</legend>${Object.entries(Ae).map(([a,c])=>`<label><input type="checkbox" data-field="${a}"><span>${c}</span></label>`).join("")}</fieldset>
21
+ <p class="publishing-note">Message timestamps require session timestamps and message counts. Models show the last recorded public model ID; private aliases stay hidden. Changes apply when you publish again.</p>
22
+ <div class="publishing-preview"></div><p class="publishing-summary"></p>
23
+ <label class="publishing-confirm"><input type="checkbox" data-confirm><span>I reviewed this preview and want to make the selected data public under my GitHub username.</span></label>
24
+ <footer><button class="text-button" data-json disabled>View exact JSON</button><button class="secondary-button" data-remove hidden>Unpublish</button><button class="primary-button" data-publish disabled>Publish graph</button></footer>
25
+ <a class="publishing-link" target="_blank" rel="noopener noreferrer" hidden></a><pre class="publishing-json" hidden></pre>`,document.body.append(n),n.prepend(ke(n,"publish",()=>r()));const e=a=>n.querySelector(a);e(".publishing-disclosure").textContent=Me;const m=we(xe);m.setAttribute("aria-hidden","true"),e("[data-login]").prepend(m);let o=[],l={...Z},f,i,p=null,M=!1,S=0,A=!1,C=0,j=!1,E=!1,y=0,T;const b=a=>{e(".publishing-status").textContent=a},h=async(a,c="GET",v)=>{const $=await fetch(`/api/sessiongraph/publishing/${a}`,{method:c,headers:{"Content-Type":"application/json","x-sessiongraph-action":"1"},...v===void 0?{}:{body:JSON.stringify(v)}}),x=await $.json();if(!$.ok)throw Object.assign(new Error(x.error||"Please try again."),{status:$.status});return x};function w(){e("[data-publish]").disabled=A||!i||!p||!e("[data-confirm]").checked,e("[data-publish]").textContent=M?"Update public graph":"Publish graph",e("[data-remove]").hidden=!M,e("[data-remove]").disabled=A,e("[data-login]").hidden=!!p||!!T,e("[data-login]").disabled=A||E,e("[data-login-label]").textContent=E?"Opening sign-in…":"Sign in with GitHub",e("[data-login]").setAttribute("aria-busy",String(E)),e("[data-logout]").hidden=!p,e("[data-logout]").disabled=A,e("[data-manage]").hidden=!p,e("[data-account]").textContent=p?`Signed in as @${p}`:T?"Waiting for browser approval":"Not signed in",e("[data-json]").disabled=!i;for(const c of n.querySelectorAll("[data-field]")){const v=c.dataset.field;c.checked=l[v],c.disabled=A||v==="messageTimestamps"&&(!l.timestamps||!l.messageCounts)}const a=e(".publishing-link");a.hidden=!p||!M,p&&(a.href=`https://sessiongraph.ai/@${p}`,a.textContent=a.href)}async function L(){const a=++S;if(i=void 0,e("[data-confirm]").checked=!1,f?.dispose(),f=void 0,e(".publishing-json").hidden=!0,e(".publishing-json").textContent="",w(),!o.length){e(".publishing-preview").textContent="Select sessions on the map to preview a public graph.";return}e(".publishing-preview").textContent="Preparing local preview…";try{const c=await h("preview","POST",{ids:o,settings:l});if(!n.open||a!==S)return;i=c,l=c.graph.settings,f=Ie(e(".publishing-preview"),c.graph),e(".publishing-summary").textContent=ue(c.graph),!E&&!T&&b("Preview prepared locally. Nothing has been uploaded.")}catch(c){a===S&&(e(".publishing-preview").textContent="",b(c.message))}w()}async function O(){const a=y,c=await h("status");!n.open||a!==y||(p=c.username??null,M=!!c.publication,p&&(T=void 0,e(".publishing-connect").hidden=!0,window.clearInterval(C),C=0),w())}async function D(){if(j||!n.open)return;const a=y;j=!0,e("[data-check]").disabled=!0;try{const c=await h("poll","POST",{});if(!n.open||a!==y)return;c.username&&(window.clearInterval(C),C=0,T=void 0,e(".publishing-connect").hidden=!0,p=c.username,w(),await O(),n.open&&a===y&&b("Signed in. Review the preview before publishing."))}catch(c){if(!n.open||a!==y)return;[400,401].includes(c.status)&&(window.clearInterval(C),C=0,T=void 0,e(".publishing-connect").hidden=!0,w()),b(c.message)}finally{j=!1,e("[data-check]").disabled=!1}}e("[data-login]").onclick=async()=>{if(E||T)return;const a=++y;E=!0,w(),b("Preparing browser sign-in…");let c=null;if(!V())try{c=window.open("about:blank","_blank"),c&&(c.opener=null)}catch{c=null}try{const v=await h("login","POST",{});if(!n.open||a!==y){c?.close();return}const $=Se(v.url);if(new URL($).origin!=="https://sessiongraph.ai"||typeof v.code!="string")throw new Error("Could not prepare browser sign-in. Please try again.");T=$,e("[data-code]").textContent=v.code,e("[data-connect]").href=$,e("[data-connect-url]").value=$,e(".publishing-connect").hidden=!1,window.clearInterval(C),C=window.setInterval(()=>{D()},4e3),e("[data-connect]").focus(),b("Continue in your browser to connect this app."),V()?await P(e("[data-connect]")):c&&(c.location.replace($),b("Sign in in the browser tab and confirm the matching code, then return here."))}catch(v){c?.close(),a===y&&b(v.message)}finally{a===y&&(E=!1,w())}};async function P(a){if(a.getAttribute("aria-busy")==="true")return;a.setAttribute("aria-busy","true");const c=y,v=a.hasAttribute("data-connect");try{await Ce(a.href),v&&n.open&&c===y&&b("Browser opened. Sign in and confirm the matching code, then return here.")}catch{n.open&&c===y&&b(v?"Could not open your browser. Copy the browser link below and paste it into your browser to continue.":"Could not open your browser. Copy the link and open it in your browser.")}finally{a.removeAttribute("aria-busy")}}n.addEventListener("click",a=>{const c=a.target.closest('a[target="_blank"]');!c||!V()||a.defaultPrevented||a.button!==0||(a.preventDefault(),P(c))}),e("[data-copy-link]").onclick=async()=>{const a=e("[data-connect-url]");try{await navigator.clipboard.writeText(a.value),b("Browser link copied. Paste it into your browser to sign in and confirm the code.")}catch{a.focus(),a.select(),b("Browser link selected. Copy it and paste it into your browser.")}},e("[data-check]").onclick=()=>{D()},e("[data-logout]").onclick=async()=>{A=!0,w();try{await h("logout","POST",{}),p=null,M=!1,i=void 0,b("Signed out. Your published graph stays online until you unpublish it.")}catch(a){b(a.message)}finally{A=!1,w()}};for(const a of n.querySelectorAll("[data-field]"))a.onchange=()=>{l=oe({...l,[a.dataset.field]:a.checked}),L()};return e("[data-confirm]").onchange=w,e("[data-publish]").onclick=async()=>{if(!(!i||!e("[data-confirm]").checked)){A=!0,w(),b("Publishing…");try{await h("publish","POST",{id:i.id,confirmed:!0}),M=!0,i=void 0,e("[data-confirm]").checked=!1,b("Published. Future imports stay local. Publish again to update this snapshot.")}catch(a){b(a.message)}finally{A=!1,w()}}},e("[data-remove]").onclick=async()=>{A=!0,w();try{await h("unpublish","POST",{}),M=!1,b("Unpublished. Your public graph has been removed.")}catch(a){b(a.message)}finally{A=!1,w()}},e("[data-json]").onclick=()=>{const a=e(".publishing-json");a.hidden=!a.hidden,a.textContent=i?JSON.stringify(i.graph,null,2):""},n.addEventListener("close",()=>{n.open||(S++,y++,E=!1,window.clearInterval(C),C=0,f?.dispose(),f=void 0,i=void 0,t())}),{async open(a){if(n.open)return;S++,y++,window.clearInterval(C),C=0,f?.dispose(),f=void 0,o=[...a],p=null,M=!1,i=void 0,E=!1,b(""),e(".publishing-connect").hidden=!T,e(".publishing-scope").textContent=`${o.length.toLocaleString()} sessions in the current filtered view. Change filters on the map to choose what you publish.`,n.showModal(),t(),w();const c=y,v=O().then(()=>{n.open&&c===y&&T&&!p&&(C=window.setInterval(()=>{D()},4e3),D())}).catch(x=>{n.open&&c===y&&b(x.message)}),$=++S;try{const x=await h("settings");if(!n.open||$!==S)return;l=oe(x),await L()}catch(x){n.open&&$===S&&b(x.message)}await v},dispose(){S++,y++,window.clearInterval(C),f?.dispose(),f=void 0,n.close(),n.remove()}}}export{Ge as createPublishing};
@@ -1,4 +1,4 @@
1
- import{M as oe,C as L,S as ce,a as M,G,P as ae,I as ne,b as k,D as F,c as I,A as T,d as Y,e as N,B as D,F as S,f as re,g as H,W as ke,h as Pe,O as Se,i as Ae,H as Ce,E as Re,R as Fe,U as Ee,V as O,j as Ie,k as Te,l as ze,m as Be,n as Ue,o as V,p as Ge,q as g,r as De,s as ee,t as Oe,u as Le,v as j,w as te,x as ie,y as He,L as Ne,z as de,J as ue,K as Xe,N as _e}from"./three-D_1Qt16u.js";import{l as ge,n as R,c as Ve,D as $e,k as je,o as C,q as $,r as We,u as qe,v as Ye,w as se,x as fe}from"./index-BtLEIWKh.js";const Ke=["svg",ge,[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]]];const Qe=["svg",ge,[["circle",{cx:"12",cy:"8",r:"5"}],["path",{d:"M20 21a8 8 0 0 0-16 0"}]]],ye=`
1
+ import{M as oe,C as L,S as ce,a as M,G,P as ae,I as ne,b as k,D as F,c as I,A as T,d as Y,e as N,B as D,F as S,f as re,g as H,W as ke,h as Pe,O as Se,i as Ae,H as Ce,E as Re,R as Fe,U as Ee,V as O,j as Ie,k as Te,l as ze,m as Be,n as Ue,o as V,p as Ge,q as g,r as De,s as ee,t as Oe,u as Le,v as j,w as te,x as ie,y as He,L as Ne,z as de,J as ue,K as Xe,N as _e}from"./three-D_1Qt16u.js";import{h as ge,o as R,c as Ve,D as $e,l as je,q as C,r as $,u as We,v as qe,w as Ye,x as se,y as fe}from"./index-CIhs02tq.js";const Ke=["svg",ge,[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]]];const Qe=["svg",ge,[["circle",{cx:"12",cy:"8",r:"5"}],["path",{d:"M20 21a8 8 0 0 0-16 0"}]]],ye=`
2
2
  attribute float nodeIndex;
3
3
  uniform float uSelected;
4
4
  uniform float uHovered;
@@ -0,0 +1,7 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-GTrhxXlP.js","assets/index-CIhs02tq.js","assets/index-cVgPCrFV.css","assets/index-BS2Voifb.js"])))=>i.map(i=>d[i]);
2
+ import{TimelineScene as V}from"./scene-KCDTPCOD.js";import{i as U,_ as G,c as X,S as J,p as Y,a as Z,t as K,s as Q,b as H,d as ee,e as te,f as ae,g as oe}from"./index-CIhs02tq.js";import{s as re,o as se}from"./external-links-D0O8IeG0.js";import"./three-D_1Qt16u.js";const ne="#b0e9d6",ie="#dbe7e3",L=128,le=10,ce="M102 24 86 40H36a14 14 0 0 0 0 28h40a14 14 0 0 1 0 28H22",de=[[102,24],[36,40],[22,96]],ue=10;let O;function he(e,l,t,s,i=ne){O??=new Path2D(ce),e.save(),e.translate(l,t),e.scale(s/L,s/L),e.strokeStyle=e.fillStyle=i,e.lineWidth=le,e.lineCap=e.lineJoin="round",e.stroke(O);for(const[p,r]of de)e.beginPath(),e.arc(p,r,ue,0,Math.PI*2),e.fill();e.restore()}const pe="Cosmic Wobbly Disco Sneaky Bouncy Galactic Crispy Dizzy Fuzzy Noodle Groovy Sleepy Spicy Jolly Loopy Squishy Turbo Giggly Velvet Soggy Zippy Fluffy Moonwalking Wiggly Fizzy Snazzy Goofy Jazzy Tiny Chunky Dapper Wacky".split(" "),ye="Wombat Pickle Pancake Badger Potato Narwhal Noodle Goblin Otter Turnip Hamster Comet Dumpling Goose Biscuit Llama Muffin Squid Raccoon Toaster Waffle Penguin Yeti Pudding Walrus Taco Jellybean Platypus Sloth Cactus Donut Mongoose".split(" ");function fe(e,l=()=>crypto.getRandomValues(new Uint32Array(1))[0]/2**32){const t=pe.flatMap(s=>ye.map(i=>`${s} ${i}`));for(let s=t.length-1;s>0;s--){const i=Math.floor(l()*(s+1));[t[s],t[i]]=[t[i],t[s]]}return Array.from({length:e},(s,i)=>{const p=Math.floor(i/t.length);return`Project ${"Mega".repeat(p)}${t[i%t.length]}`})}function me(e){const l=fe(e.lanes.length),t=new Map(e.nodes.map((r,a)=>[r.session.id,`session-${a}`])),s=new Map(e.lanes.flatMap((r,a)=>r.nodes.map(o=>[o.session.id,`project-${a}`]))),i=e.nodes.map(r=>{const a=r.session,o={id:t.get(a.id),title:"Session",projectID:s.get(a.id),directory:"",created:a.created,updated:a.created,activity:a.activity&&{firstMessageAt:a.activity.firstMessageAt,lastMessageAt:a.activity.lastMessageAt,userMessages:a.activity.userMessages,untimedUserMessages:a.activity.untimedUserMessages},archived:!1,model:"",provider:"",agent:"",cost:null,source:a.source==="continue"?"continue":a.source==="opencode"||!a.source?"opencode":"unknown",tokens:a.tokens};return a.parentID&&t.has(a.parentID)&&(o.parentID=t.get(a.parentID)),a.forkID&&t.has(a.forkID)&&(o.forkID=t.get(a.forkID)),{session:o,position:[...r.position],startPosition:[...r.startPosition],color:r.color,radius:r.radius}}),p=new Map(i.map(r=>[r.session.id,r]));return{start:e.start,end:e.end,timeFrame:e.timeFrame&&{...e.timeFrame},nodes:i,edges:e.edges.map(r=>({from:t.get(r.from),to:t.get(r.to),kind:r.kind})),lanes:e.lanes.map((r,a)=>({key:`project-${a}`,label:l[a],color:r.color,kind:"directory",y:r.y,z:r.z,nodes:r.nodes.map(o=>p.get(t.get(o.session.id)))}))}}const $={mp4:{label:"MP4",description:"MP4 video",mime:"video/mp4",filename:"sessiongraph-playback.mp4"}},I=`My coding sessions, visualized with SessionGraph.
3
+ https://github.com/arvindell/sessiongraph`,be=`https://x.com/intent/tweet?text=${encodeURIComponent(I)}`,z=e=>e instanceof Error&&e.name==="AbortError";async function ve(e,l,t){const{label:s,description:i,mime:p,filename:r}=$[t];try{if(U()){const[{save:a},{writeFile:o}]=await Promise.all([G(()=>import("./index-GTrhxXlP.js"),__vite__mapDeps([0,1,2])),G(()=>import("./index-BS2Voifb.js"),__vite__mapDeps([3,1,2]))]),c=await a({title:`Save SessionGraph ${s}`,defaultPath:r,filters:[{name:i,extensions:[t]}]});if(!c)return"cancelled";await o(c,new Uint8Array(await e.arrayBuffer()))}else{const a=window.showSaveFilePicker;if(a){const c=await(await a.call(window,{suggestedName:r,types:[{description:i,accept:{[p]:[`.${t}`]}}]})).createWritable();try{await c.write(e),await c.close()}catch(d){throw await c.abort().catch(()=>{}),d}}else{const o=document.createElement("a");return o.href=l,o.download=r,document.body.append(o),o.click(),o.remove(),"downloaded"}}return"saved"}catch(a){if(z(a))return"cancelled";throw a}}const S=960,T=600,we=e=>Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(e);function ge(e,l,t,s,i,p){const o=T-122,c=Math.max(1,...s);e.save(),he(e,24,14,28),e.fillStyle=ie,e.font='600 14px "Geist Variable", sans-serif',e.textAlign="left",e.textBaseline="middle",e.fillText("SessionGraph",58,28),e.restore();for(let h=0;h<s.length;h++){const f=Math.max(2,s[h]/c*22);e.fillStyle=h/s.length<=t?"#91bfae":"#253d39",e.fillRect(260+h/s.length*440,o-f,440/s.length-2,f)}e.fillStyle="#d6f4e8",e.fillRect(260+440*t,o-27,1,31);const d=l.start+(l.end-l.start)*t,k=i.at(d,t===1).tokens;e.textAlign="center",e.fillStyle="#a0baae",e.font='12px "IBM Plex Mono", monospace',e.fillText(oe(d,l.end-l.start),S/2,o+23),e.fillStyle="#e7f5ee",e.font='36px "Geist Variable", sans-serif',e.fillText(p(d,t===1).toLocaleString("en"),S/2-105,o+66),e.fillText(i.recorded?we(k):"—",S/2+105,o+66),e.font='12px "Geist Variable", sans-serif',e.fillStyle="#92b0a3",e.fillText("Sessions",S/2-105,o+87),e.fillText("Burnt tokens",S/2+105,o+87),e.textAlign="left"}async function Se(e,l,t,s){t.throwIfAborted();const{label:i,mime:p}=$.mp4,r=Y(e.nodes.map(y=>y.session)),a=Z(e.nodes.map(y=>y.session)),o=K(e.nodes.map(y=>Q(y.session)),e.start,e.end),c=document.createElement("div");c.className="share-render-host",c.setAttribute("aria-hidden","true"),c.style.cssText=`position:fixed;left:-12000px;top:0;width:${S}px;height:${T}px;pointer-events:none;visibility:hidden`,document.body.append(c);const d=document.createElement("canvas");d.width=S,d.height=T;const k=d.getContext("2d",{willReadFrequently:!0});let h,f;try{if(!k)throw new Error("Canvas export is unavailable.");h=new V(c,{onSelect(){},onHover(){},onPlaybackInterrupt(){},onEvent(){},onEventHover(){}},{manual:!0}),h.applyPreferences({...l,quality:"balanced",motion:"on",labels:!0,focusDimming:!1,trails:l.trails==="selected"?"all":l.trails}),h.setGraph(e,!0),h.prepareCapture(),await document.fonts.ready,t.throwIfAborted(),f=new Worker(new URL("/assets/mp4-worker-Dc_1QUwS.js",import.meta.url),{type:"module"});const y=(m,C=[])=>new Promise((A,b)=>{t.throwIfAborted();const v=()=>{clearTimeout(D),t.removeEventListener("abort",w),f.onmessage=null,f.onerror=null},w=()=>{v(),b(t.reason)},D=setTimeout(()=>{v(),b(new Error(`${i} encoding timed out. Please try again.`))},6e4);t.addEventListener("abort",w,{once:!0}),f.onmessage=M=>{v(),M.data.error?b(new Error(M.data.error)):A(M.data)},f.onerror=()=>{v(),b(new Error(`Could not start the ${i} encoder.`))},f.postMessage(m,C)});await y({init:!0,width:S,height:T});for(let m=0;m<H;m++){t.throwIfAborted();const C=ee(m);h.captureFrame(C,1/te,k,ae(m)),ge(k,e,C,o,r,a);const A=k.getImageData(0,0,S,T).data.buffer;await y({rgba:A,width:S,height:T},[A]),s((m+1)/H)}const _=await y({finish:!0});return new Blob([_.bytes],{type:p})}finally{f?.terminate(),h?.dispose(),c.remove()}}function De(e,l){const t=document.createElement("dialog");t.className="share-dialog",t.setAttribute("aria-labelledby","share-title"),t.innerHTML=`<p>Create a private MP4 video. Project and session names are hidden, and nothing is uploaded.</p>
4
+ <div class="share-preview"><video aria-label="SessionGraph playback with hidden project and session names" muted loop playsinline controls hidden></video><div class="share-progress"><progress max="100" value="0" aria-label="Creating video"></progress><span role="status">Creating video… 0%</span></div></div>
5
+ <p class="share-notice" role="status" hidden></p>
6
+ <div class="share-actions"><button class="text-button share-close">Cancel</button><button class="secondary-button share-retry" hidden>Try again</button><a class="secondary-button share-x" target="_blank" rel="noopener noreferrer" hidden>Share in X</a><button class="secondary-button share-system" aria-label="Open share tray" aria-controls="playback-share-tray" aria-expanded="false" hidden>Share…</button><button class="primary-button share-save" hidden>Save MP4</button></div>
7
+ <section id="playback-share-tray" class="share-tray" aria-label="Share options" hidden><p>Save the video to attach it in any app.</p><textarea class="share-caption" aria-label="Share caption" readonly rows="3"></textarea><div><button class="secondary-button share-copy">Copy caption</button><a class="secondary-button share-x" target="_blank" rel="noopener noreferrer">Share in X</a><button class="secondary-button share-tray-save">Save MP4</button></div></section>`,t.prepend(re(t,"video",()=>l())),document.body.append(t);const s=t.querySelector("video"),i=t.querySelector("progress"),p=t.querySelector('[role="status"]'),r=t.querySelector(".share-progress"),a=t.querySelector(".share-close"),o=t.querySelector(".share-save"),c=t.querySelector(".share-retry"),d=t.querySelector(".share-system"),k=t.querySelector(".share-actions .share-x"),h=t.querySelector(".share-tray"),f=t.querySelector(".share-notice"),y=t.querySelector(".share-tray-save"),_=t.querySelector(".share-copy"),m=t.querySelector(".share-caption");m.value=I;const C=X(J);C.setAttribute("aria-hidden","true"),C.setAttribute("stroke-width","1.5"),d.prepend(C);let A,b,v,w,D,M,x=Promise.resolve();const g=n=>{f.textContent=n,f.hidden=!n},R=n=>{h.hidden=!n,d.setAttribute("aria-expanded",String(n)),n&&_.focus()},q=()=>{A?.abort(),A=void 0,s.pause(),s.removeAttribute("src"),s.load(),w&&URL.revokeObjectURL(w),w=void 0,b=void 0,v=void 0,R(!1),g(""),t.setAttribute("aria-busy","false")};for(const n of t.querySelectorAll(".share-x"))n.href=be,n.title="Open an X draft, then attach your saved animation",n.onclick=u=>{g("Attach your saved MP4 in X to include the video."),U()&&(u.preventDefault(),se(n.href).catch(()=>g("Could not open your browser. Copy the caption and attach your saved video manually.")))};a.onclick=()=>t.close(),t.addEventListener("cancel",n=>{h.hidden||(n.preventDefault(),R(!1),d.focus())}),t.addEventListener("close",()=>{t.open||(q(),D=void 0,M=void 0,e())});function N(){q();const n=new AbortController;A=n;const{label:u,mime:P,filename:j}=$.mp4;o.textContent=y.textContent=`Save ${u}`,s.hidden=!0,r.hidden=!1,o.hidden=!0,d.hidden=!0,k.hidden=!0,c.hidden=!0,a.textContent="Cancel",i.hidden=!1,i.value=0,i.setAttribute("aria-label",`Creating ${u}`),p.textContent=`Creating ${u}… 0%`,t.setAttribute("aria-busy","true"),x=x.then(async()=>{if(!n.signal.aborted)try{const E=await Se(D,M,n.signal,W=>{if(n.signal.aborted)return;const F=Math.round(W*100);i.value=F,p.textContent=`Creating ${u}… ${F}%`});if(n.signal.aborted)return;b=E,v=new File([E],j,{type:P}),w=URL.createObjectURL(E),s.src=w,s.hidden=!1,s.play().catch(()=>{}),r.hidden=!0,o.hidden=!1,d.hidden=!1,k.hidden=!1,a.textContent="Done"}catch(E){if(n.signal.aborted)return;i.hidden=!0,p.textContent=E instanceof Error?E.message:`Could not create the ${u}.`,c.hidden=!1,a.textContent="Close"}finally{A===n&&t.setAttribute("aria-busy","false")}})}c.onclick=N;const B=async()=>{if(!b||!w||o.disabled)return;const n=b,{label:u}=$.mp4;o.disabled=!0,y.disabled=!0,g(`Choose where to save your ${u}…`);try{const P=await ve(n,w,"mp4");b===n&&g(P==="saved"?`${u} saved.`:P==="downloaded"?`${u} download started. Check your downloads.`:`Save cancelled. Your ${u} is still ready.`)}catch{b===n&&g(`Could not save the ${u}. Try choosing another location.`)}finally{o.disabled=!1,y.disabled=!1}};return o.onclick=B,y.onclick=B,d.onclick=async()=>{if(!v||d.disabled)return;const n=v,u={files:[n],title:"SessionGraph",text:I};if(!navigator.share||!navigator.canShare?.({files:[n]})){R(h.hidden);return}d.disabled=!0,g("");try{await navigator.share(u)}catch(P){v===n&&!z(P)&&(R(!0),g("Could not open system sharing. Save the animation or choose an option below."))}finally{d.disabled=!1}},_.onclick=async()=>{try{await navigator.clipboard.writeText(I),g("Caption copied. Attach your saved animation with it.")}catch{m.focus(),m.select(),g("Copy the selected caption, then attach your saved animation.")}},{open(n,u){t.open||(D=me(n),M={...u},t.showModal(),e(),N())},dispose(){q(),D=void 0,M=void 0,t.close(),t.remove()}}}export{De as createPlaybackShare};
@@ -0,0 +1,2 @@
1
+ (function(){"use strict";const ve="ENTRIES",le="KEYS",he="VALUES";class K{constructor(e,t){const n=e._tree,o=Array.from(n.keys());this.set=e,this._type=t,this._path=o.length>0?[{node:n,keys:o}]:[]}next(){const e=this.dive();return this.backtrack(),e}dive(){if(this._path.length===0)return{done:!0,value:void 0};const{node:e,keys:t}=M(this._path);if(M(t)==="")return{done:!1,value:this.result()};const n=e.get(M(t));return this._path.push({node:n,keys:Array.from(n.keys())}),this.dive()}backtrack(){if(this._path.length===0)return;const e=M(this._path).keys;e.pop(),!(e.length>0)&&(this._path.pop(),this.backtrack())}key(){return this.set._prefix+this._path.map(({keys:e})=>M(e)).filter(e=>e!=="").join("")}value(){return M(this._path).node.get("")}result(){switch(this._type){case he:return this.value();case le:return this.key();default:return[this.key(),this.value()]}}[Symbol.iterator](){return this}}const M=s=>s[s.length-1],ke=(s,e,t)=>{const n=new Map;if(e===void 0)return n;const o=e.length+1,i=o+t,r=new Uint8Array(i*o).fill(t+1);for(let c=0;c<o;++c)r[c]=c;for(let c=1;c<i;++c)r[c*o]=c;return ue(s,e,t,n,r,1,o,""),n},ue=(s,e,t,n,o,i,r,c)=>{const a=i*r;e:for(const d of s.keys())if(d===""){const h=o[a-1];h<=t&&n.set(c,[s.get(d),h])}else{let h=i;for(let _=0;_<d.length;++_,++h){const m=d[_],l=r*h,f=l-r;let p=o[l];const u=Math.max(0,h-t-1),g=Math.min(r-1,h+t);for(let w=u;w<g;++w){const O=m!==e[w],V=o[f+w]+ +O,j=o[f+w+1]+1,x=o[l+w]+1,z=o[l+w+1]=Math.min(V,j,x);z<p&&(p=z)}if(p>t)continue e}ue(s.get(d),e,t,n,o,h,r,c+d)}};class I{constructor(e=new Map,t=""){this._size=void 0,this._tree=e,this._prefix=t}atPrefix(e){if(!e.startsWith(this._prefix))throw new Error("Mismatched prefix");const[t,n]=W(this._tree,e.slice(this._prefix.length));if(t===void 0){const[o,i]=Z(n);for(const r of o.keys())if(r!==""&&r.startsWith(i)){const c=new Map;return c.set(r.slice(i.length),o.get(r)),new I(c,e)}}return new I(t,e)}clear(){this._size=void 0,this._tree.clear()}delete(e){return this._size=void 0,ze(this._tree,e)}entries(){return new K(this,ve)}forEach(e){for(const[t,n]of this)e(t,n,this)}fuzzyGet(e,t){return ke(this._tree,e,t)}get(e){const t=H(this._tree,e);return t!==void 0?t.get(""):void 0}has(e){const t=H(this._tree,e);return t!==void 0&&t.has("")}keys(){return new K(this,le)}set(e,t){if(typeof e!="string")throw new Error("key must be a string");return this._size=void 0,X(this._tree,e).set("",t),this}get size(){if(this._size)return this._size;this._size=0;const e=this.entries();for(;!e.next().done;)this._size+=1;return this._size}update(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const n=X(this._tree,e);return n.set("",t(n.get(""))),this}fetch(e,t){if(typeof e!="string")throw new Error("key must be a string");this._size=void 0;const n=X(this._tree,e);let o=n.get("");return o===void 0&&n.set("",o=t()),o}values(){return new K(this,he)}[Symbol.iterator](){return this.entries()}static from(e){const t=new I;for(const[n,o]of e)t.set(n,o);return t}static fromObject(e){return I.from(Object.entries(e))}}const W=(s,e,t=[])=>{if(e.length===0||s==null)return[s,t];for(const n of s.keys())if(n!==""&&e.startsWith(n))return t.push([s,n]),W(s.get(n),e.slice(n.length),t);return t.push([s,e]),W(void 0,"",t)},H=(s,e)=>{if(e.length===0||s==null)return s;for(const t of s.keys())if(t!==""&&e.startsWith(t))return H(s.get(t),e.slice(t.length))},X=(s,e)=>{const t=e.length;e:for(let n=0;s&&n<t;){for(const i of s.keys())if(i!==""&&e[n]===i[0]){const r=Math.min(t-n,i.length);let c=1;for(;c<r&&e[n+c]===i[c];)++c;const a=s.get(i);if(c===i.length)s=a;else{const d=new Map;d.set(i.slice(c),a),s.set(e.slice(n,n+c),d),s.delete(i),s=d}n+=c;continue e}const o=new Map;return s.set(e.slice(n),o),o}return s},ze=(s,e)=>{const[t,n]=W(s,e);if(t!==void 0){if(t.delete(""),t.size===0)fe(n);else if(t.size===1){const[o,i]=t.entries().next().value;me(n,o,i)}}},fe=s=>{if(s.length===0)return;const[e,t]=Z(s);if(e.delete(t),e.size===0)fe(s.slice(0,-1));else if(e.size===1){const[n,o]=e.entries().next().value;n!==""&&me(s.slice(0,-1),n,o)}},me=(s,e,t)=>{if(s.length===0)return;const[n,o]=Z(s);n.set(o+e,t),n.delete(o)},Z=s=>s[s.length-1],ee="or",pe="and",Me="and_not";class C{constructor(e){if(e?.fields==null)throw new Error('MiniSearch: option "fields" must be provided');const t=e.autoVacuum==null||e.autoVacuum===!0?oe:e.autoVacuum;this._options={...se,...e,autoVacuum:t,searchOptions:{...ge,...e.searchOptions||{}},autoSuggestOptions:{...Te,...e.autoSuggestOptions||{}}},this._index=new I,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldIds={},this._fieldLength=new Map,this._avgFieldLength=[],this._nextId=0,this._storedFields=new Map,this._dirtCount=0,this._currentVacuum=null,this._enqueuedVacuum=null,this._enqueuedVacuumConditions=ie,this.addFields(this._options.fields)}add(e){const{extractField:t,stringifyField:n,tokenize:o,processTerm:i,fields:r,idField:c}=this._options,a=t(e,c);if(a==null)throw new Error(`MiniSearch: document does not have ID field "${c}"`);if(this._idToShortId.has(a))throw new Error(`MiniSearch: duplicate ID ${a}`);const d=this.addDocumentId(a);this.saveStoredFields(d,e);for(const h of r){const _=t(e,h);if(_==null)continue;const m=o(n(_,h),h),l=this._fieldIds[h],f=new Set(m).size;this.addFieldLength(d,l,this._documentCount-1,f);for(const p of m){const u=i(p,h);if(Array.isArray(u))for(const g of u)this.addTerm(l,d,g);else u&&this.addTerm(l,d,u)}}}addAll(e){for(const t of e)this.add(t)}addAllAsync(e,t={}){const{chunkSize:n=10}=t,o={chunk:[],promise:Promise.resolve()},{chunk:i,promise:r}=e.reduce(({chunk:c,promise:a},d,h)=>(c.push(d),(h+1)%n===0?{chunk:[],promise:a.then(()=>new Promise(_=>setTimeout(_,0))).then(()=>this.addAll(c))}:{chunk:c,promise:a}),o);return r.then(()=>this.addAll(i))}remove(e){const{tokenize:t,processTerm:n,extractField:o,stringifyField:i,fields:r,idField:c}=this._options,a=o(e,c);if(a==null)throw new Error(`MiniSearch: document does not have ID field "${c}"`);const d=this._idToShortId.get(a);if(d==null)throw new Error(`MiniSearch: cannot remove document with ID ${a}: it is not in the index`);for(const h of r){const _=o(e,h);if(_==null)continue;const m=t(i(_,h),h),l=this._fieldIds[h],f=new Set(m).size;this.removeFieldLength(d,l,this._documentCount,f);for(const p of m){const u=n(p,h);if(Array.isArray(u))for(const g of u)this.removeTerm(l,d,g);else u&&this.removeTerm(l,d,u)}}this._storedFields.delete(d),this._documentIds.delete(d),this._idToShortId.delete(a),this._fieldLength.delete(d),this._documentCount-=1}removeAll(e){if(e)for(const t of e)this.remove(t);else{if(arguments.length>0)throw new Error("Expected documents to be present. Omit the argument to remove all documents.");this._index=new I,this._documentCount=0,this._documentIds=new Map,this._idToShortId=new Map,this._fieldLength=new Map,this._avgFieldLength=[],this._storedFields=new Map,this._nextId=0}}discard(e){const t=this._idToShortId.get(e);if(t==null)throw new Error(`MiniSearch: cannot discard document with ID ${e}: it is not in the index`);this._idToShortId.delete(e),this._documentIds.delete(t),this._storedFields.delete(t),(this._fieldLength.get(t)||[]).forEach((n,o)=>{this.removeFieldLength(t,o,this._documentCount,n)}),this._fieldLength.delete(t),this._documentCount-=1,this._dirtCount+=1,this.maybeAutoVacuum()}maybeAutoVacuum(){if(this._options.autoVacuum===!1)return;const{minDirtFactor:e,minDirtCount:t,batchSize:n,batchWait:o}=this._options.autoVacuum;this.conditionalVacuum({batchSize:n,batchWait:o},{minDirtCount:t,minDirtFactor:e})}discardAll(e){const t=this._options.autoVacuum;try{this._options.autoVacuum=!1;for(const n of e)this.discard(n)}finally{this._options.autoVacuum=t}this.maybeAutoVacuum()}replace(e){const{idField:t,extractField:n}=this._options,o=n(e,t);this.discard(o),this.add(e)}vacuum(e={}){return this.conditionalVacuum(e)}conditionalVacuum(e,t){return this._currentVacuum?(this._enqueuedVacuumConditions=this._enqueuedVacuumConditions&&t,this._enqueuedVacuum!=null?this._enqueuedVacuum:(this._enqueuedVacuum=this._currentVacuum.then(()=>{const n=this._enqueuedVacuumConditions;return this._enqueuedVacuumConditions=ie,this.performVacuuming(e,n)}),this._enqueuedVacuum)):this.vacuumConditionsMet(t)===!1?Promise.resolve():(this._currentVacuum=this.performVacuuming(e),this._currentVacuum)}async performVacuuming(e,t){const n=this._dirtCount;if(this.vacuumConditionsMet(t)){const o=e.batchSize||ne.batchSize,i=e.batchWait||ne.batchWait;let r=1;for(const[c,a]of this._index){for(const[d,h]of a)for(const[_]of h)this._documentIds.has(_)||(h.size<=1?a.delete(d):h.delete(_));this._index.get(c).size===0&&this._index.delete(c),r%o===0&&await new Promise(d=>setTimeout(d,i)),r+=1}this._dirtCount-=n}await null,this._currentVacuum=this._enqueuedVacuum,this._enqueuedVacuum=null}vacuumConditionsMet(e){if(e==null)return!0;let{minDirtCount:t,minDirtFactor:n}=e;return t=t||oe.minDirtCount,n=n||oe.minDirtFactor,this.dirtCount>=t&&this.dirtFactor>=n}get isVacuuming(){return this._currentVacuum!=null}get dirtCount(){return this._dirtCount}get dirtFactor(){return this._dirtCount/(1+this._documentCount+this._dirtCount)}has(e){return this._idToShortId.has(e)}getStoredFields(e){const t=this._idToShortId.get(e);if(t!=null)return this._storedFields.get(t)}search(e,t={}){const{searchOptions:n}=this._options,o={...n,...t},i=this.executeQuery(e,t),r=[];for(const[c,{score:a,terms:d,match:h}]of i){const _=d.length||1,m={id:this._documentIds.get(c),score:a*_,terms:Object.keys(h),queryTerms:d,match:h};Object.assign(m,this._storedFields.get(c)),(o.filter==null||o.filter(m))&&r.push(m)}return e===C.wildcard&&o.boostDocument==null||r.sort(we),r}autoSuggest(e,t={}){t={...this._options.autoSuggestOptions,...t};const n=new Map;for(const{score:i,terms:r}of this.search(e,t)){const c=r.join(" "),a=n.get(c);a!=null?(a.score+=i,a.count+=1):n.set(c,{score:i,terms:r,count:1})}const o=[];for(const[i,{score:r,terms:c,count:a}]of n)o.push({suggestion:i,terms:c,score:r/a});return o.sort(we),o}get documentCount(){return this._documentCount}get termCount(){return this._index.size}static loadJSON(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJS(JSON.parse(e),t)}static async loadJSONAsync(e,t){if(t==null)throw new Error("MiniSearch: loadJSON should be given the same options used when serializing the index");return this.loadJSAsync(JSON.parse(e),t)}static getDefault(e){if(se.hasOwnProperty(e))return te(se,e);throw new Error(`MiniSearch: unknown option "${e}"`)}static loadJS(e,t){const{index:n,documentIds:o,fieldLength:i,storedFields:r,serializationVersion:c}=e,a=this.instantiateMiniSearch(e,t);a._documentIds=P(o),a._fieldLength=P(i),a._storedFields=P(r);for(const[d,h]of a._documentIds)a._idToShortId.set(h,d);for(const[d,h]of n){const _=new Map;for(const m of Object.keys(h)){let l=h[m];c===1&&(l=l.ds),_.set(parseInt(m,10),P(l))}a._index.set(d,_)}return a}static async loadJSAsync(e,t){const{index:n,documentIds:o,fieldLength:i,storedFields:r,serializationVersion:c}=e,a=this.instantiateMiniSearch(e,t);a._documentIds=await U(o),a._fieldLength=await U(i),a._storedFields=await U(r);for(const[h,_]of a._documentIds)a._idToShortId.set(_,h);let d=0;for(const[h,_]of n){const m=new Map;for(const l of Object.keys(_)){let f=_[l];c===1&&(f=f.ds),m.set(parseInt(l,10),await U(f))}++d%1e3===0&&await xe(0),a._index.set(h,m)}return a}static instantiateMiniSearch(e,t){const{documentCount:n,nextId:o,fieldIds:i,averageFieldLength:r,dirtCount:c,serializationVersion:a}=e;if(a!==1&&a!==2)throw new Error("MiniSearch: cannot deserialize an index created with an incompatible version");const d=new C(t);return d._documentCount=n,d._nextId=o,d._idToShortId=new Map,d._fieldIds=i,d._avgFieldLength=r,d._dirtCount=c||0,d._index=new I,d}executeQuery(e,t={}){if(e===C.wildcard)return this.executeWildcardQuery(t);if(typeof e!="string"){const m={...t,...e,queries:void 0},l=e.queries.map(f=>this.executeQuery(f,m));return this.combineResults(l,m.combineWith)}const{tokenize:n,processTerm:o,searchOptions:i}=this._options,r={tokenize:n,processTerm:o,...i,...t},{tokenize:c,processTerm:a}=r,_=c(e).flatMap(m=>a(m)).filter(m=>!!m).map(De(r)).map(m=>this.executeQuerySpec(m,r));return this.combineResults(_,r.combineWith)}executeQuerySpec(e,t){const n={...this._options.searchOptions,...t},o=(n.fields||this._options.fields).reduce((p,u)=>({...p,[u]:te(n.boost,u)||1}),{}),{boostDocument:i,weights:r,maxFuzzy:c,bm25:a}=n,{fuzzy:d,prefix:h}={...ge.weights,...r},_=this._index.get(e.term),m=this.termResults(e.term,e.term,1,e.termBoost,_,o,i,a);let l,f;if(e.prefix&&(l=this._index.atPrefix(e.term)),e.fuzzy){const p=e.fuzzy===!0?.2:e.fuzzy,u=p<1?Math.min(c,Math.round(e.term.length*p)):p;u&&(f=this._index.fuzzyGet(e.term,u))}if(l)for(const[p,u]of l){const g=p.length-e.term.length;if(!g)continue;f?.delete(p);const w=h*p.length/(p.length+.3*g);this.termResults(e.term,p,w,e.termBoost,u,o,i,a,m)}if(f)for(const p of f.keys()){const[u,g]=f.get(p);if(!g)continue;const w=d*p.length/(p.length+g);this.termResults(e.term,p,w,e.termBoost,u,o,i,a,m)}return m}executeWildcardQuery(e){const t=new Map,n={...this._options.searchOptions,...e};for(const[o,i]of this._documentIds){const r=n.boostDocument?n.boostDocument(i,"",this._storedFields.get(o)):1;t.set(o,{score:r,terms:[],match:{}})}return t}combineResults(e,t=ee){if(e.length===0)return new Map;const n=t.toLowerCase(),o=Ce[n];if(!o)throw new Error(`Invalid combination operator: ${t}`);return e.reduce(o)||new Map}toJSON(){const e=[];for(const[t,n]of this._index){const o={};for(const[i,r]of n)o[i]=Object.fromEntries(r);e.push([t,o])}return{documentCount:this._documentCount,nextId:this._nextId,documentIds:Object.fromEntries(this._documentIds),fieldIds:this._fieldIds,fieldLength:Object.fromEntries(this._fieldLength),averageFieldLength:this._avgFieldLength,storedFields:Object.fromEntries(this._storedFields),dirtCount:this._dirtCount,index:e,serializationVersion:2}}termResults(e,t,n,o,i,r,c,a,d=new Map){if(i==null)return d;for(const h of Object.keys(r)){const _=r[h],m=this._fieldIds[h],l=i.get(m);if(l==null)continue;let f=l.size;const p=this._avgFieldLength[m];for(const u of l.keys()){if(!this._documentIds.has(u)){this.removeTerm(m,u,t),f-=1;continue}const g=c?c(this._documentIds.get(u),t,this._storedFields.get(u)):1;if(!g)continue;const w=l.get(u),O=this._fieldLength.get(u)[m],V=Le(w,f,this._documentCount,O,p,a),j=n*o*_*g*V,x=d.get(u);if(x){x.score+=j,Ae(x.terms,e);const z=te(x.match,t);z?z.push(h):x.match[t]=[h]}else d.set(u,{score:j,terms:[e],match:{[t]:[h]}})}}return d}addTerm(e,t,n){const o=this._index.fetch(n,ye);let i=o.get(e);if(i==null)i=new Map,i.set(t,1),o.set(e,i);else{const r=i.get(t);i.set(t,(r||0)+1)}}removeTerm(e,t,n){if(!this._index.has(n)){this.warnDocumentChanged(t,e,n);return}const o=this._index.fetch(n,ye),i=o.get(e);i==null||i.get(t)==null?this.warnDocumentChanged(t,e,n):i.get(t)<=1?i.size<=1?o.delete(e):i.delete(t):i.set(t,i.get(t)-1),this._index.get(n).size===0&&this._index.delete(n)}warnDocumentChanged(e,t,n){for(const o of Object.keys(this._fieldIds))if(this._fieldIds[o]===t){this._options.logger("warn",`MiniSearch: document with ID ${this._documentIds.get(e)} has changed before removal: term "${n}" was not present in field "${o}". Removing a document after it has changed can corrupt the index!`,"version_conflict");return}}addDocumentId(e){const t=this._nextId;return this._idToShortId.set(e,t),this._documentIds.set(t,e),this._documentCount+=1,this._nextId+=1,t}addFields(e){for(let t=0;t<e.length;t++)this._fieldIds[e[t]]=t}addFieldLength(e,t,n,o){let i=this._fieldLength.get(e);i==null&&this._fieldLength.set(e,i=[]),i[t]=o;const c=(this._avgFieldLength[t]||0)*n+o;this._avgFieldLength[t]=c/(n+1)}removeFieldLength(e,t,n,o){if(n===1){this._avgFieldLength[t]=0;return}const i=this._avgFieldLength[t]*n-o;this._avgFieldLength[t]=i/(n-1)}saveStoredFields(e,t){const{storeFields:n,extractField:o}=this._options;if(n==null||n.length===0)return;let i=this._storedFields.get(e);i==null&&this._storedFields.set(e,i={});for(const r of n){const c=o(t,r);c!==void 0&&(i[r]=c)}}}C.wildcard=Symbol("*");const te=(s,e)=>Object.prototype.hasOwnProperty.call(s,e)?s[e]:void 0,Ce={[ee]:(s,e)=>{for(const t of e.keys()){const n=s.get(t);if(n==null)s.set(t,e.get(t));else{const{score:o,terms:i,match:r}=e.get(t);n.score=n.score+o,n.match=Object.assign(n.match,r),_e(n.terms,i)}}return s},[pe]:(s,e)=>{const t=new Map;for(const n of e.keys()){const o=s.get(n);if(o==null)continue;const{score:i,terms:r,match:c}=e.get(n);_e(o.terms,r),t.set(n,{score:o.score+i,terms:o.terms,match:Object.assign(o.match,c)})}return t},[Me]:(s,e)=>{for(const t of e.keys())s.delete(t);return s}},Ee={k:1.2,b:.7,d:.5},Le=(s,e,t,n,o,i)=>{const{k:r,b:c,d:a}=i;return Math.log(1+(t-e+.5)/(e+.5))*(a+s*(r+1)/(s+r*(1-c+c*n/o)))},De=s=>(e,t,n)=>{const o=typeof s.fuzzy=="function"?s.fuzzy(e,t,n):s.fuzzy||!1,i=typeof s.prefix=="function"?s.prefix(e,t,n):s.prefix===!0,r=typeof s.boostTerm=="function"?s.boostTerm(e,t,n):1;return{term:e,fuzzy:o,prefix:i,termBoost:r}},se={idField:"id",extractField:(s,e)=>s[e],stringifyField:(s,e)=>s.toString(),tokenize:s=>s.split(Oe),processTerm:s=>s.toLowerCase(),fields:void 0,searchOptions:void 0,storeFields:[],logger:(s,e)=>{typeof console?.[s]=="function"&&console[s](e)},autoVacuum:!0},ge={combineWith:ee,prefix:!1,fuzzy:!1,maxFuzzy:6,boost:{},weights:{fuzzy:.45,prefix:.375},bm25:Ee},Te={combineWith:pe,prefix:(s,e,t)=>e===t.length-1},ne={batchSize:1e3,batchWait:10},ie={minDirtFactor:.1,minDirtCount:20},oe={...ne,...ie},Ae=(s,e)=>{s.includes(e)||s.push(e)},_e=(s,e)=>{for(const t of e)s.includes(t)||s.push(t)},we=({score:s},{score:e})=>e-s,ye=()=>new Map,P=s=>{const e=new Map;for(const t of Object.keys(s))e.set(parseInt(t,10),s[t]);return e},U=async s=>{const e=new Map;let t=0;for(const n of Object.keys(s))e.set(parseInt(n,10),s[n]),++t%1e3===0&&await xe(0);return e},xe=s=>new Promise(e=>setTimeout(e,s)),Oe=/[\n\r\p{Z}\p{P}]+/u,F=24e6,J=48e3,Ve=2,E=s=>JSON.stringify([Ve,s.revision,s.updated,s.created,s.projectID,s.directory]);function je(s,e){if(!s||!e||s.id!==e.id||s.version!==E(e)||!Number.isInteger(s.pages)||s.pages<1||s.pages>8||!Number.isInteger(s.characters)||s.characters<0||s.characters>J||typeof s.partial!="boolean"||typeof s.complete!="boolean"||typeof s.capped!="boolean"||s.cursor!==void 0&&(typeof s.cursor!="string"||!/^\d{1,9}$/.test(s.cursor))||s.complete&&(s.partial||s.capped||s.cursor)||!s.complete&&!s.capped&&(!s.cursor||s.pages>=8)||!Array.isArray(s.fragments)||s.fragments.length>J)return!1;let t=0;for(const n of s.fragments){if(!n||!["You","Assistant","Tool","File"].includes(n.kind)||typeof n.text!="string"||n.text.length>2e3||!Number.isFinite(n.time))return!1;t+=n.text.length}return t===s.characters}const b=s=>s.normalize("NFKD").replace(new RegExp("\\p{M}","gu"),"").toLowerCase(),re=s=>b(s).match(/[\p{L}\p{N}]+/gu)||[],ce=s=>re(s).join(" ");function Ne(s){const e={text:"",terms:[],phrases:[],filters:[]},t=[];for(const n of s.slice(0,300).match(/(?:[^\s"]+|"[^"]*")+/g)||[]){const o=/^(source|project|dir|model|is|after|before|in):(.+)$/i.exec(n);if(o){const r=o[1].toLowerCase(),c=b(o[2].replace(/^"|"$/g,""));if(r==="in"){const a={title:["title"],files:["files"],messages:["body"],tools:["tools"]};e.fields=a[c],e.fields||(e.error="Use in:title, in:files, in:messages, or in:tools.")}else r==="is"&&!["fork","child","root","archived"].includes(c)?e.error="Use is:fork, is:child, is:root, or is:archived.":["after","before"].includes(r)&&(!/^\d{4}-\d{2}-\d{2}$/.test(c)||!Number.isFinite(Date.parse(c))||new Date(c).toISOString().slice(0,10)!==c)?e.error="Use a valid date in YYYY-MM-DD format.":e.filters.push([r,c]);continue}const i=n.replace(/^"|"$/g,"");n.startsWith('"')&&n.endsWith('"')&&e.phrases.push(ce(i)),t.push(i)}return e.text=t.join(" "),e.terms=re(e.text).slice(0,12),e.text=e.terms.join(" "),e}function $e(s,e,t=220){const n=b(s),o=e.reduce((r,c)=>{const a=n.indexOf(c);return a<0?r:Math.min(r,a)},1/0),i=Number.isFinite(o)?Math.max(0,o-55):0;return`${i?"…":""}${s.slice(i,i+t).replace(/\s+/g," ").trim()}${s.length>i+t?"…":""}`}class Re{index=new C({fields:["title","project","directory","model","sessionID","files","body","tools"],tokenize:re,processTerm:b,searchOptions:{combineWith:"AND",prefix:!0,boost:{title:12,files:5,project:3,directory:3,model:2,sessionID:12,body:1,tools:.6}}});entries=new Map;cache=new Map;scope=new Set;setData(e,t){const n=new Set(e.map(i=>i.id));for(const[i,r]of this.entries)n.has(i)||(this.index.remove(r.doc),this.entries.delete(i));const o=new Map(t.map(i=>[i.id,i.name]));for(const i of e){const r=this.entries.get(i.id),c=r&&E(r.session)===E(i),a={id:i.id,title:i.title,project:o.get(i.projectID)||"",directory:i.directory,model:i.model,sessionID:i.id,body:c?r.doc.body:"",files:c?r.doc.files:"",tools:c?r.doc.tools:""};if(c&&Object.keys(a).every(d=>r.doc[d]===a[d])){r.session=i;continue}this.entries.set(i.id,{session:i,doc:a,fragments:c?r.fragments:[]}),r&&this.index.remove(r.doc),this.index.add(a)}this.cache.clear()}setScope(e){this.scope=new Set(e),this.cache.clear()}content(e){return this.entries.get(e)?.fragments.slice()||[]}addContent(e,t){const n=this.entries.get(e);if(!n)return;n.fragments.push(...t);const o={...n.doc};for(const i of t){const r=i.kind==="File"?"files":i.kind==="Tool"?"tools":"body";o[r]+=`
2
+ ${i.text}`}this.index.remove(n.doc),this.index.add(o),n.doc=o,this.cache.clear()}search(e,t=!1,n=80,o=0){const i=`${e}\0${t}\0${n}\0${o}`,r=this.cache.get(i);if(r)return r;const c=Ne(e);if(c.error)return{hits:[],total:0,error:c.error};const a=l=>{const{session:f,doc:p}=l;if(t&&!this.scope.has(f.id))return!1;for(const[u,g]of c.filters)if(u==="source"&&![f.source||"opencode",...(f.linkedSessionIDs||[]).map(w=>w.split(":")[0])].some(w=>b(w).includes(g))||u==="project"&&!b(p.project).includes(g)&&!b(f.projectID).includes(g)||u==="dir"&&!b(f.directory).includes(g)||u==="model"&&!b(f.model).includes(g)||u==="after"&&f.created<new Date(`${g}T00:00:00`).getTime()||u==="before"&&f.created>new Date(`${g}T23:59:59.999`).getTime()||u==="is"&&(g==="fork"&&!f.forkID||g==="child"&&(!f.parentID||f.forkID)||g==="root"&&(f.parentID||f.forkID)||g==="archived"&&!f.archived))return!1;if(c.phrases.length){const u=c.fields||["title","body","files","tools","project","directory","model"];if(!c.phrases.every(g=>u.some(w=>ce(p[w]).includes(g))))return!1}return!0},h=(c.terms.length?this.index.search(c.text,{fields:c.fields,fuzzy:l=>l.length<4?!1:l.length>7?2:1,filter:l=>a(this.entries.get(String(l.id)))}):[...this.entries.values()].filter(a).map(l=>({id:l.session.id,score:0,terms:[],match:{}}))).map(l=>{const f=this.entries.get(String(l.id)),p=ce(f.doc.title),u=new Set(Object.values(l.match).flat()),g=c.text?p.includes(c.text)&&(!c.fields||c.fields.includes("title"))?5:u.has("title")||u.has("sessionID")?4:u.has("files")?3:u.has("body")?2:1:0;return{match:l,entry:f,tier:g}}).sort((l,f)=>f.tier-l.tier||f.match.score-l.match.score||f.entry.session.updated-l.entry.session.updated||l.entry.session.id.localeCompare(f.entry.session.id)),m={hits:h.slice(o,o+Math.min(250,Math.max(1,n))).map(({match:l,entry:f,tier:p})=>{const u=l.terms.length?l.terms:c.terms,g=f.fragments.filter(x=>!c.fields||c.fields.includes(x.kind==="File"?"files":x.kind==="Tool"?"tools":"body"));let w,O=0;for(const x of g){const z=b(x.text),G=u.reduce((Je,qe)=>Je+Number(z.includes(qe)),0);if(G>O&&(w=x,O=G),G===u.length&&G>0)break}const V=new Set(Object.values(l.match).flat()),j=p>=4?V.has("sessionID")&&!V.has("title")?"Session ID":"Title":w?w.kind==="File"?"File":w.kind==="Tool"?"Tool":"Message":c.text?"Metadata":"Recent";return{id:f.session.id,score:l.score,source:j,excerpt:w?$e(w.text,u):"",terms:u}}),total:h.length};return this.cache.size>=30&&this.cache.delete(this.cache.keys().next().value),this.cache.set(i,m),m}}function We(s,e){let t=Math.max(0,e),n=!1;const o=[],i=[...s.fragments].sort((c,a)=>+(a.kind==="File"||a.kind==="You")-+(c.kind==="File"||c.kind==="You")),r=Math.max(160,Math.min(2e3,Math.floor(t/Math.max(1,i.length))));for(const c of i){if(t<=0){n=!0;break}const a=c.text.slice(0,Math.min(t,r));n||=a.length<c.text.length,o.push({...c,text:a}),t-=a.length}return{fragments:o,characters:Math.max(0,e)-t,partial:s.truncated||n}}class Pe{available=!0;epoch=0;async restore(e,t,n){const o=new Map(t.map(c=>[c.id,c]));let i,r=0;try{do{const c=await fetch(`/api/sessiongraph/index${i?`?after=${encodeURIComponent(i)}`:""}`);if(!c.ok)throw new Error("Index unavailable");const a=await c.json();this.epoch=a.epoch;for(const d of a.records)je(d,o.get(d.id))&&r+d.characters<=F&&(r+=d.characters,n(d));i=a.cursor}while(i);try{globalThis.indexedDB?.deleteDatabase("atlas-search")}catch{}}catch{this.available=!1}}async save(e){if(this.available)try{const t=await fetch("/api/sessiongraph/index",{method:"POST",headers:{"Content-Type":"application/json","X-SessionGraph-Action":"index"},body:JSON.stringify({record:e,epoch:this.epoch})});!t.ok&&t.status!==409&&(this.available=!1)}catch{this.available=!1}}async clear(){const e=await fetch("/api/sessiongraph/index",{method:"DELETE",headers:{"X-SessionGraph-Action":"index"}});if(this.available=e.ok,!e.ok)throw new Error("Could not clear saved index.")}}const v=new Re,q=new Pe,y=new Map,L=new Set;let D=!1,Q=0,S=0,k=0,B=!1,T,A,be=[],ae,Se=0;const Y=new Set,N=s=>postMessage(s);function $(){if(!A)return;const s=performance.now(),e=v.search(A.text,A.viewOnly,A.limit);be=e.hits.slice(0,12).map(t=>t.id),N({type:"results",request:A.request,...e,elapsed:performance.now()-s})}function R(){const s=[...y.values()];N({type:"status",status:{indexed:s.filter(e=>e.pages>0).length,complete:s.filter(e=>e.complete).length,total:y.size,characters:S,active:D&&Q>0,limited:S>=F||s.some(e=>e.partial||e.capped),failed:s.filter(e=>e.failed>0).length,restored:L.size,storage:B?T?.sourceID&&q.available?"local":"memory":"restoring"}})}function Ie(){ae||(ae=setTimeout(()=>{ae=void 0,$(),R()},200))}function Ue(){const s=t=>!!(t&&!t.inflight&&!t.complete&&!t.capped&&t.failed<1);for(const t of be){const n=y.get(t);if(s(n)&&n.pages<2)return n}let e;for(const t of y.values())s(t)&&(!e||t.pages<e.pages)&&(e=t);return e}function de(){if(!B||!D||S>=F){R();return}for(;Q<2;){const s=Ue();if(!s)break;s.inflight=!0,Q++;const e=k,t=new AbortController;Y.add(t),(async()=>{try{const n=new URLSearchParams({updated:String(s.session.updated)});s.cursor&&n.set("cursor",s.cursor);const o=await fetch(`/api/sessiongraph/session/${encodeURIComponent(s.session.id)}/content?${n}`,{signal:t.signal});if(!o.ok)throw new Error("Conversation unavailable");const i=await o.json();if(e!==k||t.signal.aborted)return;if(i.id!==s.session.id)throw new Error("Unexpected conversation");const r=Math.min(J,Math.floor(F/Math.max(1,y.size))),c=We(i,Math.min(r-s.characters,F-S));s.characters+=c.characters,S+=c.characters,v.addContent(s.session.id,c.fragments),s.pages++,s.partial||=c.partial,s.complete=!i.nextCursor&&!s.partial,s.capped=!s.complete&&(!i.nextCursor||s.characters>=r||s.pages>=8),s.cursor=i.nextCursor||void 0,Ie(),T?.sourceID&&await q.save({id:s.session.id,version:E(s.session),fragments:v.content(s.session.id),pages:s.pages,characters:s.characters,partial:s.partial,complete:s.complete,capped:s.capped,cursor:s.cursor})}catch{!t.signal.aborted&&e===k&&s.failed++}finally{s.inflight=!1,Y.delete(t),Q--,D?setTimeout(de,performance.now()-Se<150?150:35):R()}})()}R()}async function Fe(s,e=!1){const t=++k;B=!1,Y.forEach(r=>r.abort());const n=T?.sourceID===s.sourceID&&!e,o=n?new Map(y):new Map;n||(v.setData([],[]),L.clear()),T=s,y.clear(),S=0;for(const r of[...s.sessions].sort((c,a)=>a.updated-c.updated)){const c=o.get(r.id),a=c&&E(c.session)===E(r),d=a?{...c,session:r,inflight:!1}:{session:r,pages:0,characters:0,partial:!1,complete:!1,capped:!1,failed:0,inflight:!1};a||L.delete(r.id),y.set(r.id,d),S+=d.characters}for(const r of L)y.has(r)||L.delete(r);if(v.setData(s.sessions,s.projects),$(),R(),e&&await q.clear(),t!==k||(s.sourceID&&await q.restore(s.sourceID,s.sessions,r=>{if(t!==k)return;const c=y.get(r.id);!c||c.pages||S+r.characters>F||(v.addContent(r.id,r.fragments),Object.assign(c,{pages:r.pages,characters:r.characters,partial:r.partial,complete:r.complete,capped:r.capped,cursor:r.cursor}),S+=r.characters,L.add(r.id),Ie())}),t!==k))return;const i=Math.min(J,Math.floor(F/Math.max(1,y.size)));for(const r of y.values())!r.complete&&r.characters>=i&&(r.capped=!0);B=!0,$(),de()}self.onmessage=s=>{try{const e=s.data;e.type==="data"?Fe(e).catch(()=>N({type:"error",message:"Search index could not load. Reload to retry."})):e.type==="scope"?(v.setScope(e.ids),$()):e.type==="query"?(Se=performance.now(),A=e,$()):e.type==="clear-cache"?(D=!1,T&&Fe(T,!0).catch(()=>N({type:"error",message:"Search index could not reset. Reload to retry."}))):(D=e.enabled,D?y.forEach(t=>{t.failed=0}):Y.forEach(t=>t.abort()),de())}catch(e){N({type:"error",message:e instanceof Error?e.message:"Search unavailable"})}}})();
@@ -12,8 +12,8 @@
12
12
  <link rel="icon" sizes="any" href="/favicon.ico" />
13
13
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
14
14
  <link rel="apple-touch-icon" href="/apple-touch-icon.png" />
15
- <script type="module" crossorigin src="/assets/index-BtLEIWKh.js"></script>
16
- <link rel="stylesheet" crossorigin href="/assets/index-BnhC5gO7.css">
15
+ <script type="module" crossorigin src="/assets/index-CIhs02tq.js"></script>
16
+ <link rel="stylesheet" crossorigin href="/assets/index-cVgPCrFV.css">
17
17
  </head>
18
18
  <body>
19
19
  <div id="app"></div>
@@ -14,16 +14,20 @@
14
14
  </data>
15
15
  <key>Resources/resources/node</key>
16
16
  <data>
17
- LwhUyzptHAPUkpORN2tZA7T6KfM=
17
+ 12DkJCJ8qYRbNUUmbUVf5mLKJkE=
18
18
  </data>
19
19
  <key>Resources/resources/server.mjs</key>
20
20
  <data>
21
- VEhZu8KsM3wadJyKPbTuy4LDA5o=
21
+ MgN1AEw00F6uro8twjzD0AbZsfo=
22
22
  </data>
23
23
  <key>Resources/resources/web/apple-touch-icon.png</key>
24
24
  <data>
25
25
  7IrT+H6J4h1FxtVwSpZiqT0xzjI=
26
26
  </data>
27
+ <key>Resources/resources/web/assets/external-links-D0O8IeG0.js</key>
28
+ <data>
29
+ qoq5g+btTH8wb4LU5G+LyQjxcr8=
30
+ </data>
27
31
  <key>Resources/resources/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2</key>
28
32
  <data>
29
33
  yYSDXNlt/tTRaj6rJo8ZMqvY7pQ=
@@ -44,10 +48,6 @@
44
48
  <data>
45
49
  6MZ7/PEEOeDVF0eHI650KpwKQV8=
46
50
  </data>
47
- <key>Resources/resources/web/assets/gif-worker-CghHEBpp.js</key>
48
- <data>
49
- AymSGXqQ+/QDZ1A3Wr1PydS5Xs0=
50
- </data>
51
51
  <key>Resources/resources/web/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2</key>
52
52
  <data>
53
53
  mDbzFbXDuciYuRDdYbcJkcocaWU=
@@ -88,53 +88,53 @@
88
88
  <data>
89
89
  LdRX2sBB3T5WDAsZLCwBlsMYXPw=
90
90
  </data>
91
- <key>Resources/resources/web/assets/index-BNX-8Jnn.js</key>
92
- <data>
93
- Xp6L1p+ausNXOvhq3zwaCD+0pgk=
94
- </data>
95
- <key>Resources/resources/web/assets/index-BcoCDV6F.js</key>
91
+ <key>Resources/resources/web/assets/index-BS2Voifb.js</key>
96
92
  <data>
97
- 3E8+JPs+piodH6of6YRH5da4HCI=
93
+ U9c9owi9e1cBBM801BBc80Usxt4=
98
94
  </data>
99
- <key>Resources/resources/web/assets/index-BnhC5gO7.css</key>
95
+ <key>Resources/resources/web/assets/index-CIhs02tq.js</key>
100
96
  <data>
101
- RJSPTuyeJ+yb5dph4+Q0QFnk0r8=
97
+ PxECxIMWc8PAb7biGosjGJEyIRY=
102
98
  </data>
103
- <key>Resources/resources/web/assets/index-BtLEIWKh.js</key>
99
+ <key>Resources/resources/web/assets/index-GTrhxXlP.js</key>
104
100
  <data>
105
- e+/jr3YHpx4iyazA14bQyDb//MQ=
101
+ WbASvcdvbtDo8VZztgCOvnSTKig=
106
102
  </data>
107
- <key>Resources/resources/web/assets/index-RfmyzBnX.js</key>
103
+ <key>Resources/resources/web/assets/index-Vq4WYmzW.js</key>
108
104
  <data>
109
- g75sfvRD5OvbJVQ5Wx5CPddPCd4=
105
+ 5ON5koaa0mgQDMsCSXjOQTeQ1+Q=
110
106
  </data>
111
- <key>Resources/resources/web/assets/mp4-worker-HFPra5JP.js</key>
107
+ <key>Resources/resources/web/assets/index-cVgPCrFV.css</key>
112
108
  <data>
113
- ATVDz7hoBhGkjEraL7M3QJPykT0=
109
+ iF/RrbIsDFqLG24iTldy8j0AaJU=
114
110
  </data>
115
- <key>Resources/resources/web/assets/publishing-DoHRK4Ea.js</key>
111
+ <key>Resources/resources/web/assets/mp4-worker-Dc_1QUwS.js</key>
116
112
  <data>
117
- P0LsULOGy1eADgxt02GIzlKoR5I=
113
+ 2/71pbsZ0DyFW7H+mzqWhzexMXI=
118
114
  </data>
119
115
  <key>Resources/resources/web/assets/publishing-VJhUmdPH.css</key>
120
116
  <data>
121
117
  6fWzMO88QnTllqV2/V6JoSphpq8=
122
118
  </data>
123
- <key>Resources/resources/web/assets/scene-B_CpQ0qP.js</key>
119
+ <key>Resources/resources/web/assets/publishing-ofssf6d6.js</key>
124
120
  <data>
125
- xhNd+SGEFktArCXAEzinW1oLibI=
121
+ K0riTJCU1FzCyGoGUDmTon961Js=
126
122
  </data>
127
- <key>Resources/resources/web/assets/share-DPdu1Hbo.js</key>
123
+ <key>Resources/resources/web/assets/scene-KCDTPCOD.js</key>
128
124
  <data>
129
- 3JsTxUYGeTTkYEwCJ65nrQPyZ6E=
125
+ 3hZJsK37DX0PXuhu35fdRSKkkOA=
126
+ </data>
127
+ <key>Resources/resources/web/assets/share-DKeJCFAo.js</key>
128
+ <data>
129
+ zN+63CcQWEhrDXuDzGSR4bBUHtE=
130
130
  </data>
131
131
  <key>Resources/resources/web/assets/three-D_1Qt16u.js</key>
132
132
  <data>
133
133
  +vkqXmunTgaV0KGoBq/AEc36POU=
134
134
  </data>
135
- <key>Resources/resources/web/assets/worker-DwqxiDWY.js</key>
135
+ <key>Resources/resources/web/assets/worker-C10U_apJ.js</key>
136
136
  <data>
137
- mImryodKVT09sI0yWPkhy8RUFX4=
137
+ ldktmP7HUVpkPsH5F5Z1eTwGXsE=
138
138
  </data>
139
139
  <key>Resources/resources/web/brand/icon.svg</key>
140
140
  <data>
@@ -166,7 +166,7 @@
166
166
  </data>
167
167
  <key>Resources/resources/web/index.html</key>
168
168
  <data>
169
- cARCiBZ8EJNSGsGusJ7MB3q7Fc4=
169
+ v14oGu0PtIuPPMLXWYIiY2rtBlE=
170
170
  </data>
171
171
  <key>Resources/resources/web/sources/LICENSE-APACHE-2.0.txt</key>
172
172
  <data>
@@ -425,14 +425,14 @@
425
425
  <dict>
426
426
  <key>hash2</key>
427
427
  <data>
428
- YUpZ5XuEeDoIjY8doNHS1wIzSNBKRFN5TWzgrEMowmk=
428
+ 2N3Kqsh+d+SLnmGx3m1wl8tfqvPrPfW1IoIaB7Gazp8=
429
429
  </data>
430
430
  </dict>
431
431
  <key>Resources/resources/server.mjs</key>
432
432
  <dict>
433
433
  <key>hash2</key>
434
434
  <data>
435
- xuoB/lT1DcsCafZ/pmNAf1O+VhDA+RMbZKp55aKMFgw=
435
+ 52g3LHzvZPF3ovrGWt5g3hf39KxffiO5T8acadXiEPE=
436
436
  </data>
437
437
  </dict>
438
438
  <key>Resources/resources/web/apple-touch-icon.png</key>
@@ -442,6 +442,13 @@
442
442
  r0avunkAKv+j4kuQJ3Lk5pFwJ+ds28pxrEPQMyqVahc=
443
443
  </data>
444
444
  </dict>
445
+ <key>Resources/resources/web/assets/external-links-D0O8IeG0.js</key>
446
+ <dict>
447
+ <key>hash2</key>
448
+ <data>
449
+ rSd8xSPmILlRtX3INXUvifY7r7BcwHlpIvjXFl1Dn1k=
450
+ </data>
451
+ </dict>
445
452
  <key>Resources/resources/web/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2</key>
446
453
  <dict>
447
454
  <key>hash2</key>
@@ -477,13 +484,6 @@
477
484
  j6QOXSSCR3NeuXoL1ZO4hSRAQwYA1roBNkwx/gq8H+E=
478
485
  </data>
479
486
  </dict>
480
- <key>Resources/resources/web/assets/gif-worker-CghHEBpp.js</key>
481
- <dict>
482
- <key>hash2</key>
483
- <data>
484
- Gqm87v0a6wkspaC1UVuZ9V/7+MroKhoHHeHwsIe3SjM=
485
- </data>
486
- </dict>
487
487
  <key>Resources/resources/web/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2</key>
488
488
  <dict>
489
489
  <key>hash2</key>
@@ -554,74 +554,74 @@
554
554
  vO1WHZkeP4HBUMCOcff6hJ/L/1I1YPYFkkXy7c4ZtgA=
555
555
  </data>
556
556
  </dict>
557
- <key>Resources/resources/web/assets/index-BNX-8Jnn.js</key>
557
+ <key>Resources/resources/web/assets/index-BS2Voifb.js</key>
558
558
  <dict>
559
559
  <key>hash2</key>
560
560
  <data>
561
- 9nukl82gAfqwPqZSYXrqc7takYu/VdQ8bO4rH1R3Elw=
561
+ PDwT4nYjawUSNl2EOADb2EV4grwgOl5LL6lyR+CpJUM=
562
562
  </data>
563
563
  </dict>
564
- <key>Resources/resources/web/assets/index-BcoCDV6F.js</key>
564
+ <key>Resources/resources/web/assets/index-CIhs02tq.js</key>
565
565
  <dict>
566
566
  <key>hash2</key>
567
567
  <data>
568
- JG1JJixpHy2uqRG28hunWpzk+WL+QJwq1QR24o24G4A=
568
+ GTar+BQRbPYvnjChPPqAc+hDe6kSOGAmHCCR1s1cmV8=
569
569
  </data>
570
570
  </dict>
571
- <key>Resources/resources/web/assets/index-BnhC5gO7.css</key>
571
+ <key>Resources/resources/web/assets/index-GTrhxXlP.js</key>
572
572
  <dict>
573
573
  <key>hash2</key>
574
574
  <data>
575
- OOjp+eY6EdTb12LkHD2/hUVlpkUowB8gbTHh6ehJD8o=
575
+ ErOpyjb47NmjXjakKx/+M8sQx4B3wOQu33Un1v2pOyM=
576
576
  </data>
577
577
  </dict>
578
- <key>Resources/resources/web/assets/index-BtLEIWKh.js</key>
578
+ <key>Resources/resources/web/assets/index-Vq4WYmzW.js</key>
579
579
  <dict>
580
580
  <key>hash2</key>
581
581
  <data>
582
- feT4l1fWR0sFu/pRLwDkQhQU7gaT7o7ObPDlTmvM/zc=
582
+ uu64IyfOXsSxbWpKOCclBBG7wIAj7rMLvQ308BGfRNI=
583
583
  </data>
584
584
  </dict>
585
- <key>Resources/resources/web/assets/index-RfmyzBnX.js</key>
585
+ <key>Resources/resources/web/assets/index-cVgPCrFV.css</key>
586
586
  <dict>
587
587
  <key>hash2</key>
588
588
  <data>
589
- WATPvH4HDJ5jEyAVR0HvC3yxdnakkqMRmdWBCRDiZFc=
589
+ u0PLkjTcM8ruYmTQ3Yp4BwAhqq8AohSPTU9Uor/7tbw=
590
590
  </data>
591
591
  </dict>
592
- <key>Resources/resources/web/assets/mp4-worker-HFPra5JP.js</key>
592
+ <key>Resources/resources/web/assets/mp4-worker-Dc_1QUwS.js</key>
593
593
  <dict>
594
594
  <key>hash2</key>
595
595
  <data>
596
- OcBpKX8DX9+EUp27mNDb0LMrwE28fDC5f3PbjJsXOjU=
596
+ VaH6cQJD5lKhlsXhS1dVQylTIaiWiRK8K2VSicyCuzg=
597
597
  </data>
598
598
  </dict>
599
- <key>Resources/resources/web/assets/publishing-DoHRK4Ea.js</key>
599
+ <key>Resources/resources/web/assets/publishing-VJhUmdPH.css</key>
600
600
  <dict>
601
601
  <key>hash2</key>
602
602
  <data>
603
- v/EgvZ8GwuHbVRCjArX4rNSGVoGWhd1MoeXakqEUfUE=
603
+ qp+02zzJ3eDSRmM1QFKIs/gPNJJ1VudOM7MVpmEOywY=
604
604
  </data>
605
605
  </dict>
606
- <key>Resources/resources/web/assets/publishing-VJhUmdPH.css</key>
606
+ <key>Resources/resources/web/assets/publishing-ofssf6d6.js</key>
607
607
  <dict>
608
608
  <key>hash2</key>
609
609
  <data>
610
- qp+02zzJ3eDSRmM1QFKIs/gPNJJ1VudOM7MVpmEOywY=
610
+ tVY7Y0/v7Dla6cQ37EGGZLyUWhrbSHnaLEsIFN5T39E=
611
611
  </data>
612
612
  </dict>
613
- <key>Resources/resources/web/assets/scene-B_CpQ0qP.js</key>
613
+ <key>Resources/resources/web/assets/scene-KCDTPCOD.js</key>
614
614
  <dict>
615
615
  <key>hash2</key>
616
616
  <data>
617
- IWG7kuSklPHLPSqbfRE+99YMJCpBSsaUjvoRfUcSmc0=
617
+ SPkzBgF/bgDrLG/J/AYxmbUgvAcdLvyuuCtvksVlBZA=
618
618
  </data>
619
619
  </dict>
620
- <key>Resources/resources/web/assets/share-DPdu1Hbo.js</key>
620
+ <key>Resources/resources/web/assets/share-DKeJCFAo.js</key>
621
621
  <dict>
622
622
  <key>hash2</key>
623
623
  <data>
624
- 6WjBAdAV8a19ktfDf5AMMKvWosknkWqVk79wWUmAiOE=
624
+ o4nfZne4QFYjrTlJLPTf0ojZ6jK2phzyk1h7qLeONpU=
625
625
  </data>
626
626
  </dict>
627
627
  <key>Resources/resources/web/assets/three-D_1Qt16u.js</key>
@@ -631,11 +631,11 @@
631
631
  jmvag0RMTOx9k51cantgrINZ5EOs/TLx+2WZFlkv3u0=
632
632
  </data>
633
633
  </dict>
634
- <key>Resources/resources/web/assets/worker-DwqxiDWY.js</key>
634
+ <key>Resources/resources/web/assets/worker-C10U_apJ.js</key>
635
635
  <dict>
636
636
  <key>hash2</key>
637
637
  <data>
638
- EOfLd1vncqhtsbvSQsOKlub/6ifr9YRRXzi731FNbJs=
638
+ 7jdvgaFnpFEDygpRzMtaoKzULPDaexTvc1emS8Gz5Q0=
639
639
  </data>
640
640
  </dict>
641
641
  <key>Resources/resources/web/brand/icon.svg</key>
@@ -691,7 +691,7 @@
691
691
  <dict>
692
692
  <key>hash2</key>
693
693
  <data>
694
- Ar6Jz2ncBhP+3uyqrBazcV6UD+NEcqqFQXDptNcwIvU=
694
+ DwVuBe7dVmDbe0uH8P92f8j8zp5diihy7RONtfjXioc=
695
695
  </data>
696
696
  </dict>
697
697
  <key>Resources/resources/web/sources/LICENSE-APACHE-2.0.txt</key>
@@ -1 +0,0 @@
1
- (function(){"use strict";var N={trailer:59};function H(t=256){let r=0,c=new Uint8Array(t);return{get buffer(){return c.buffer},reset(){r=0},bytesView(){return c.subarray(0,r)},bytes(){return c.slice(0,r)},writeByte(a){n(r+1),c[r]=a,r++},writeBytes(a,i=0,f=a.length){n(r+f);for(let l=0;l<f;l++)c[r++]=a[l+i]},writeBytesView(a,i=0,f=a.byteLength){n(r+f),c.set(a.subarray(i,i+f),r),r+=f}};function n(a){var i=c.length;if(i>=a)return;var f=1024*1024;a=Math.max(a,i*(i<f?2:1.125)>>>0),i!=0&&(a=Math.max(a,256));let l=c;c=new Uint8Array(a),r>0&&c.set(l.subarray(0,r),0)}}var C=12,T=5003,Q=[0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535];function X(t,r,c,n,a=H(512),i=new Uint8Array(256),f=new Int32Array(T),l=new Int32Array(T)){let w=f.length,y=Math.max(2,n);i.fill(0),l.fill(0),f.fill(-1);let o=0,e=0,h=y+1,p=h,u=!1,d=p,s=(1<<d)-1,B=1<<h-1,v=B+1,M=B+2,b=0,A=c[0],G=0;for(let g=w;g<65536;g*=2)++G;G=8-G,a.writeByte(y),k(B);let m=c.length;for(let g=1;g<m;g++)t:{let U=c[g],F=(U<<C)+A,x=U<<G^A;if(f[x]===F){A=l[x];break t}let _=x===0?1:w-x;for(;f[x]>=0;)if(x-=_,x<0&&(x+=w),f[x]===F){A=l[x];break t}k(A),A=U,M<1<<C?(l[x]=M++,f[x]=F):(f.fill(-1),M=B+2,u=!0,k(B))}return k(A),k(v),a.writeByte(0),a.bytesView();function k(g){for(o&=Q[e],e>0?o|=g<<e:o=g,e+=d;e>=8;)i[b++]=o&255,b>=254&&(a.writeByte(b),a.writeBytesView(i,0,b),b=0),o>>=8,e-=8;if((M>s||u)&&(u?(d=p,s=(1<<d)-1,u=!1):(++d,s=d===C?1<<d:(1<<d)-1)),g==v){for(;e>0;)i[b++]=o&255,b>=254&&(a.writeByte(b),a.writeBytesView(i,0,b),b=0),o>>=8,e-=8;b>0&&(a.writeByte(b),a.writeBytesView(i,0,b),b=0)}}}var Z=X;function $(t,r,c){return t<<8&63488|r<<2&992|c>>3}function W(t,r,c,n){return t>>4|r&240|(c&240)<<4|(n&240)<<8}function tt(t,r,c){return t>>4<<8|r&240|c>>4}function q(t,r,c){return t<r?r:t>c?c:t}function z(t){return t*t}function j(t,r,c){var n=0,a=1e100;let i=t[r],f=i.cnt;i.ac;let l=i.rc,w=i.gc,y=i.bc;for(var o=i.fw;o!=0;o=t[o].fw){let h=t[o],p=h.cnt,u=f*p/(f+p);if(!(u>=a)){var e=0;e+=u*z(h.rc-l),!(e>=a)&&(e+=u*z(h.gc-w),!(e>=a)&&(e+=u*z(h.bc-y),!(e>=a)&&(a=e,n=o)))}}i.err=a,i.nn=n}function R(){return{ac:0,rc:0,gc:0,bc:0,cnt:0,nn:0,fw:0,bk:0,tm:0,mtm:0,err:0}}function et(t,r){let c=r==="rgb444"?4096:65536,n=new Array(c),a=t.length;if(r==="rgba4444")for(let i=0;i<a;++i){let f=t[i],l=f>>24&255,w=f>>16&255,y=f>>8&255,o=f&255,e=W(o,y,w,l),h=e in n?n[e]:n[e]=R();h.rc+=o,h.gc+=y,h.bc+=w,h.ac+=l,h.cnt++}else if(r==="rgb444")for(let i=0;i<a;++i){let f=t[i],l=f>>16&255,w=f>>8&255,y=f&255,o=tt(y,w,l),e=o in n?n[o]:n[o]=R();e.rc+=y,e.gc+=w,e.bc+=l,e.cnt++}else for(let i=0;i<a;++i){let f=t[i],l=f>>16&255,w=f>>8&255,y=f&255,o=$(y,w,l),e=o in n?n[o]:n[o]=R();e.rc+=y,e.gc+=w,e.bc+=l,e.cnt++}return n}function rt(t,r,c={}){let{format:n="rgb565",clearAlpha:a=!0,clearAlphaColor:i=0,clearAlphaThreshold:f=0,oneBitAlpha:l=!1}=c;if(!t||!t.buffer)throw new Error("quantize() expected RGBA Uint8Array data");if(!(t instanceof Uint8Array)&&!(t instanceof Uint8ClampedArray))throw new Error("quantize() expected RGBA Uint8Array data");let w=new Uint32Array(t.buffer),y=c.useSqrt!==!1,o=n==="rgba4444",e=et(w,n),h=e.length,p=h-1,u=new Uint32Array(h+1);for(var d=0,s=0;s<h;++s){let E=e[s];if(E!=null){var B=1/E.cnt;o&&(E.ac*=B),E.rc*=B,E.gc*=B,E.bc*=B,e[d++]=E}}z(r)/d<.022&&(y=!1);for(var s=0;s<d-1;++s)e[s].fw=s+1,e[s+1].bk=s,y&&(e[s].cnt=Math.sqrt(e[s].cnt));y&&(e[s].cnt=Math.sqrt(e[s].cnt));var v,M,b;for(s=0;s<d;++s){j(e,s);var A=e[s].err;for(M=++u[0];M>1&&(b=M>>1,!(e[v=u[b]].err<=A));M=b)u[M]=v;u[M]=s}var G=d-r;for(s=0;s<G;){for(var m;;){var k=u[1];if(m=e[k],m.tm>=m.mtm&&e[m.nn].mtm<=m.tm)break;m.mtm==p?k=u[1]=u[u[0]--]:(j(e,k),m.tm=s);var A=e[k].err;for(M=1;(b=M+M)<=u[0]&&(b<u[0]&&e[u[b]].err>e[u[b+1]].err&&b++,!(A<=e[v=u[b]].err));M=b)u[M]=v;u[M]=k}var g=e[m.nn],U=m.cnt,F=g.cnt,B=1/(U+F);o&&(m.ac=B*(U*m.ac+F*g.ac)),m.rc=B*(U*m.rc+F*g.rc),m.gc=B*(U*m.gc+F*g.gc),m.bc=B*(U*m.bc+F*g.bc),m.cnt+=g.cnt,m.mtm=++s,e[g.bk].fw=g.fw,e[g.fw].bk=g.bk,g.mtm=p}let x=[];var _=0;for(s=0;;++_){let E=q(Math.round(e[s].rc),0,255),P=q(Math.round(e[s].gc),0,255),D=q(Math.round(e[s].bc),0,255),I=255;o&&(I=q(Math.round(e[s].ac),0,255),l&&(I=I<=(typeof l=="number"?l:127)?0:255),a&&I<=f&&(E=P=D=i,I=0));let K=o?[E,P,D,I]:[E,P,D];if(nt(x,K)||x.push(K),(s=e[s].fw)==0)break}return x}function nt(t,r){for(let c=0;c<t.length;c++){let n=t[c],a=n[0]===r[0]&&n[1]===r[1]&&n[2]===r[2],i=n.length>=4&&r.length>=4?n[3]===r[3]:!0;if(a&&i)return!0}return!1}function at(t={}){let{initialCapacity:r=4096,auto:c=!0}=t,n=H(r),a=5003,i=new Uint8Array(256),f=new Int32Array(a),l=new Int32Array(a),w=!1;return{reset(){n.reset(),w=!1},finish(){n.writeByte(N.trailer)},bytes(){return n.bytes()},bytesView(){return n.bytesView()},get buffer(){return n.buffer},get stream(){return n},writeHeader:y,writeFrame(o,e,h,p={}){let{transparent:u=!1,transparentIndex:d=0,delay:s=0,palette:B=null,repeat:v=0,colorDepth:M=8,dispose:b=-1}=p,A=!1;if(c?w||(A=!0,y(),w=!0):A=!!p.first,e=Math.max(0,Math.floor(e)),h=Math.max(0,Math.floor(h)),A){if(!B)throw new Error("First frame must include a { palette } option");ft(n,e,h,B,M),L(n,B),v>=0&&ct(n,v)}let G=Math.round(s/10);it(n,b,G,u,d);let m=!!B&&!A;lt(n,e,h,m?B:null),m&&L(n,B),ot(n,o,e,h,M,i,f,l)}};function y(){O(n,"GIF89a")}}function it(t,r,c,n,a){t.writeByte(33),t.writeByte(249),t.writeByte(4),a<0&&(a=0,n=!1);var i,f;n?(i=1,f=2):(i=0,f=0),r>=0&&(f=r&7),f<<=2,t.writeByte(0|f|0|i),V(t,c),t.writeByte(a||0),t.writeByte(0)}function ft(t,r,c,n,a=8){let i=1,f=0,l=S(n.length)-1,w=i<<7|a-1<<4|f<<3|l;V(t,r),V(t,c),t.writeBytes([w,0,0])}function ct(t,r){t.writeByte(33),t.writeByte(255),t.writeByte(11),O(t,"NETSCAPE2.0"),t.writeByte(3),t.writeByte(1),V(t,r),t.writeByte(0)}function L(t,r){let c=1<<S(r.length);for(let n=0;n<c;n++){let a=[0,0,0];n<r.length&&(a=r[n]),t.writeByte(a[0]),t.writeByte(a[1]),t.writeByte(a[2])}}function lt(t,r,c,n){if(t.writeByte(44),V(t,0),V(t,0),V(t,r),V(t,c),n){let a=0,i=0,f=S(n.length)-1;t.writeByte(128|a|i|0|f)}else t.writeByte(0)}function ot(t,r,c,n,a=8,i,f,l){Z(c,n,r,a,t,i,f,l)}function V(t,r){t.writeByte(r&255),t.writeByte(r>>8&255)}function O(t,r){for(var c=0;c<r.length;c++)t.writeByte(r.charCodeAt(c))}function S(t){return Math.max(Math.ceil(Math.log2(t)),1)}var st=Object.freeze({__proto__:null,GIFEncoder:at,quantize:rt});const Y=30,ut=t=>(Math.round((t+1)*100/Y)-Math.round(t*100/Y))*10,{GIFEncoder:wt,quantize:ht}=st,yt=[0,8,2,10,12,4,14,6,3,11,1,9,15,7,13,5];function bt(t,r,c){const n=new Uint8Array(t.length/4),a=new Map,i=(f,l,w)=>{const y=f|l<<8|w<<16,o=a.get(y);if(o!==void 0)return o;let e=0,h=1/0;for(let p=0;p<r.length;p++){const u=r[p],d=f-u[0],s=l-u[1],B=w-u[2],v=d*d+s*s+B*B;if(v<h&&(e=p,h=v,!v))break}return a.set(y,e),e};for(let f=0,l=0;f<n.length;f++,l+=4){const w=t[l],y=t[l+1],o=t[l+2];let e=i(w,y,o);const h=r[e],p=(w-h[0])**2+(y-h[1])**2+(o-h[2])**2;if(Math.max(w,y,o)<128&&p>2){const u=(yt[((f/c|0)&3)*4+(f%c&3)]-7.5)/7.5*Math.min(3,Math.sqrt(p/3));e=i(Math.max(0,Math.min(255,Math.round(w+u))),Math.max(0,Math.min(255,Math.round(y+u))),Math.max(0,Math.min(255,Math.round(o+u))))}n[f]=e}return n}function Bt(){const t=wt();let r=0;return{add(c,n,a){if(c.length!==n*a*4)throw new Error("Incomplete GIF frame.");const i=ht(c,256,{format:"rgb565"});t.writeFrame(bt(c,i,n),n,a,{palette:i,delay:ut(r++),repeat:0,dispose:1})},finish(){return t.finish(),t.bytes()}}}const J=Bt();self.onmessage=t=>{try{if(t.data.finish){const r=J.finish();self.postMessage({bytes:r.buffer},{transfer:[r.buffer]})}else J.add(new Uint8Array(t.data.rgba),t.data.width,t.data.height),self.postMessage({ready:!0})}catch{self.postMessage({error:"GIF encoding failed. Please try again."})}}})();
@@ -1 +0,0 @@
1
- import{y as a,R as i,C as o}from"./index-BtLEIWKh.js";class l extends i{constructor(e){super(e.rid),this.available=!0,this.currentVersion=e.currentVersion,this.version=e.version,this.date=e.date,this.body=e.body,this.rawJson=e.rawJson}async download(e,n){const d=new o;e&&(d.onmessage=e);const r=await a("plugin:updater|download",{onEvent:d,rid:this.rid,...n,headers:t(n?.headers)});await this.downloadedBytes?.close().catch(()=>{}),this.downloadedBytes=new i(r)}async install(e){if(!this.downloadedBytes)throw new Error("Update.install called before Update.download");await a("plugin:updater|install",{updateRid:this.rid,bytesRid:this.downloadedBytes.rid,...e}),this.downloadedBytes=void 0}async downloadAndInstall(e,n){const d=new o;e&&(d.onmessage=e),await a("plugin:updater|download_and_install",{onEvent:d,rid:this.rid,...n,headers:t(n?.headers)})}async close(){await this.downloadedBytes?.close(),await super.close()}}async function w(s){const e=await a("plugin:updater|check",{...s,headers:t(s?.headers)});return e?new l(e):null}function t(s){return s?Array.from(new Headers(s).entries()):void 0}export{l as Update,w as check};