sessiongraph 1.0.1 → 1.0.3

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/README.md CHANGED
@@ -11,7 +11,7 @@
11
11
 
12
12
  [Watch the 60 FPS demo →](https://github.com/arvindell/sessiongraph/releases/latest/download/sessiongraph-demo.mp4)
13
13
 
14
- Explore **12 coding agents** in one local-first app: OpenCode, Claude Code, Codex, Cursor, Gemini CLI, Qwen Code, Pi, GitHub Copilot CLI, Cline, Roo Code, Kilo Code, and Continue.
14
+ Explore local history from **OpenCode, Claude Code, Codex, Cursor, Gemini, Pi, OpenClaw, Hermes, Kiro, Mux, and many more** in one app. [Source-by-source coverage →](docs/import-coverage.md)
15
15
  Search conversations, explore user and assistant messages, inspect changed files, and continue in another harness.
16
16
  Hover to preview messages, click to focus, and click empty space to deselect. Tune the glowing map, trails, and click sounds in Settings.
17
17
  During playback, session orbs travel through time, leaving trails behind them. Message dots match their session's color.
@@ -57,18 +57,20 @@ npx sessiongraph --browser
57
57
  | <img src="public/sources/opencode.svg" width="14" alt=""/> **OpenCode** | Authenticated local API; run OpenCode when importing | Native resume / saved-context handoff |
58
58
  | <img src="public/sources/claude.svg" width="14" alt=""/> **Claude Code** | Local projects, worktrees, and subagents via SDK | Native resume / saved-context handoff |
59
59
  | <img src="public/sources/openai.svg" width="14" alt=""/> **Codex** | Active and archived local rollouts | Native resume / saved-context handoff |
60
- | <img src="public/sources/cursor.svg" width="14" alt=""/> **Cursor** | IDE transcripts, CLI and ACP stores | CLI resume where supported / saved-context handoff |
60
+ | <img src="public/sources/cursor.svg" width="14" alt=""/> **Cursor** | IDE transcripts, legacy Composer, CLI and ACP stores | CLI resume where supported / saved-context handoff |
61
61
  | <img src="public/sources/gemini.svg" width="14" alt=""/> **Gemini CLI** | Local JSON and append-only JSONL chats | Native resume / saved-context handoff |
62
62
  | <img src="public/sources/qwen.svg" width="14" alt=""/> **Qwen Code** | Local project chat records | Native resume / saved-context handoff |
63
63
  | <img src="public/sources/pi.svg" width="14" alt=""/> **Pi** | Local JSONL session trees | Native resume / saved-context handoff |
64
64
  | <img src="public/sources/copilot.svg" width="14" alt=""/> **GitHub Copilot CLI** | Local persisted session events | Native resume / saved-context handoff |
65
65
  | <img src="public/sources/cline.svg" width="14" alt=""/> **Cline** | Extension tasks and CLI/SDK message snapshots | Saved-context handoff to a supported CLI |
66
66
  | <img src="public/sources/roo.svg" width="14" alt=""/> **Roo Code** | Local extension task histories | Saved-context handoff to a supported CLI |
67
- | <img src="public/sources/kilo.svg" width="14" alt=""/> **Kilo Code** | Legacy extension task JSON; current CLI/migrated databases excluded | Saved-context handoff to a supported CLI |
67
+ | <img src="public/sources/kilo.svg" width="14" alt=""/> **Kilo Code / CLI** | Extension task JSON; separate Kilo CLI SQLite source | Saved-context handoff to a supported CLI |
68
68
  | <img src="public/sources/continue.svg" width="14" alt=""/> **Continue** | Local IDE and CLI session JSON | Saved-context handoff to a supported CLI |
69
69
 
70
70
  Import is read-only. Saved sessions remain available when a harness is offline. [Coverage and limitations →](docs/guide.md#source-coverage)
71
71
 
72
+ Additional sources include OpenClaw, Prime Agent, Oh My Pi, Senpi, Kimchi, Gajae, Hermes, Amp, Droid, Codebuff/Freebuff, Kimi, Grok, Jcode, Cherry Studio, Command Code, ZCode, CodeBuddy, WorkBuddy, Proma, DeepSeek Harness, Aside, Vibe, Goose, Zed, Devin CLI/Desktop, Crush, Octofriend, MiMo Code/Desktop, Unsloth, and Kiro/Mux. Junie, Muse, Augment, and OpenCodeReview have partial event coverage. Fx and Antigravity expose metadata only. Usage-only integrations are labeled **Detection only**; they do not create conversations. See the [format matrix](docs/import-coverage.md) for paths and remaining gaps.
73
+
72
74
  Choose harnesses in **Settings → Sources** or **Manage sources** next to the source filter. **Auto-import is on by default**: SessionGraph checks for new and changed sessions on startup, when you return, and every minute while visible. Turn it off in **Settings → Sources → Auto-import sessions**. **Refresh sessions** also works manually.
73
75
 
74
76
  Your time range, source/project/directory filters, archived and child-session toggles, and appearance preferences are saved with the local library and restored after restarting.
@@ -0,0 +1 @@
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."})}}})();