opencode-session-turns 0.1.7 → 0.1.8

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.
@@ -1,5 +1,5 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const a=require("solid-js/web"),R=require("@opencode/plugin/gui"),i=require("solid-js");var Ot=a.template("<div class=sr-status>"),Nt=a.template('<span class="sr-title sr-progress">跳转中'),Ft=a.template("<div class=sr-rail><div class=sr-head><button type=button class=sr-close>×</button></div><div class=sr-list>"),Ht=a.template("<span class=sr-title>会话轮次"),Ut=a.template("<div class=sr-note>"),zt=a.template("<button type=button class=sr-turn><span class=sr-text><span class=sr-num>#</span><span class=sr-time></span></span><span class=sr-dash>");const tt="v13",nt="message-",Et="session-turns:diag",st="session-turns:open",Gt=40,Wt=200,Vt=50,Kt=30,j=45e3,Yt=12e3,Zt=5e3,Xt=9e3,Qt=220,te=800;let At=0,ot="",at="";const _t=o=>{const r=String(o?.text??"").split(`
2
- `).map(g=>g.trim()).find(g=>g.length>0);if(r)return r;const d=o?.files?.length??0;return d>0?`[附件 ×${d}]`:"(空消息)"},Ct=o=>String(o).padStart(2,"0"),ee=o=>{const r=new Date(o??0);return`${Ct(r.getHours())}:${Ct(r.getMinutes())}`},Tt=o=>new Promise(r=>setTimeout(r,o)),it=()=>document.querySelector('[data-slot="session-timeline-scroll"] > .scroll-view__viewport')??document.querySelector('[data-slot="session-timeline-scroll"] [data-scrollable]')??(()=>{let r=document.querySelector("[data-message-id]")?.parentElement;for(;r;){const d=getComputedStyle(r);if(/(auto|scroll)/.test(d.overflowY)&&r.scrollHeight>r.clientHeight+1)return r;r=r.parentElement}})(),T=o=>document.getElementById(`${nt}${o}`)??[...document.querySelectorAll("[data-message-id]")].find(r=>r.getAttribute("data-message-id")===o),et=o=>{const r=it(),d=[...document.querySelectorAll("[data-message-id]")],g=d[0]?.getAttribute("data-message-id")??"",S=at?` · 目标 ${T(at)?"在":"不在"} DOM`:"",A=g?` · 行ID ${g.slice(0,20)}`:"";let y="(空)";try{y=o.router.path()||"(空)"}catch{}return`轮次 ${At} · 容器 ${r?"OK":"缺失"} · DOM ${d.length} 行${S}${A} · 路由 ${y} · hash ${window.location.hash||"(空)"}${ot?` · ${ot}`:""}`},rt=(o,r)=>{const d=o.querySelector("[data-session-title]"),g=o.getBoundingClientRect(),S=d instanceof HTMLElement?d.getBoundingClientRect().bottom:g.top,y=r.getBoundingClientRect().top-(S+24);Math.abs(y)>2&&(o.scrollTop+=y)},re=o=>{setTimeout(()=>{if(!o.isConnected)return;const r=it();if(!r)return;const d=r.querySelector("[data-session-title]"),g=d instanceof HTMLElement?d.getBoundingClientRect().bottom:r.getBoundingClientRect().top,S=o.getBoundingClientRect().top;S<g+4&&(r.scrollTop+=S-(g+24))},300)},ne=o=>{let r="";try{r=o.router.path()||""}catch{}return r.startsWith("/")?r:""},se=o=>{const r=document.createElement("a");r.setAttribute("href",o),r.setAttribute("replace",""),r.setAttribute("noscroll",""),r.style.display="none",document.body.appendChild(r);try{r.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,button:0,view:window}))}finally{r.remove()}},oe=`
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const a=require("solid-js/web"),q=require("@opencode/plugin/gui"),i=require("solid-js");var Ot=a.template("<div class=sr-status>"),Nt=a.template('<span class="sr-title sr-progress">跳转中'),Ft=a.template("<div class=sr-rail><div class=sr-head><button type=button class=sr-close>×</button></div><div class=sr-list>"),Ht=a.template("<span class=sr-title>会话轮次"),Ut=a.template("<div class=sr-note>"),zt=a.template("<button type=button class=sr-turn><span class=sr-text><span class=sr-num>#</span><span class=sr-time></span></span><span class=sr-dash>");const et="v13",st="message-",Et="session-turns:diag",ot="session-turns:open",Gt=40,Wt=200,Vt=50,Kt=30,R=45e3,Yt=12e3,Zt=5e3,Xt=9e3,Qt=220,te=800;let At=0,at="",it="";const _t=o=>{const r=String(o?.text??"").split(`
2
+ `).map(h=>h.trim()).find(h=>h.length>0);if(r)return r;const d=o?.files?.length??0;return d>0?`[附件 ×${d}]`:"(空消息)"},Ct=o=>String(o).padStart(2,"0"),ee=o=>{const r=new Date(o??0);return`${Ct(r.getHours())}:${Ct(r.getMinutes())}`},Tt=o=>new Promise(r=>setTimeout(r,o)),lt=()=>document.querySelector('[data-slot="session-timeline-scroll"] > .scroll-view__viewport')??document.querySelector('[data-slot="session-timeline-scroll"] [data-scrollable]')??(()=>{let r=document.querySelector("[data-message-id]")?.parentElement;for(;r;){const d=getComputedStyle(r);if(/(auto|scroll)/.test(d.overflowY)&&r.scrollHeight>r.clientHeight+1)return r;r=r.parentElement}})(),A=o=>document.getElementById(`${st}${o}`)??[...document.querySelectorAll("[data-message-id]")].find(r=>r.getAttribute("data-message-id")===o),rt=o=>{const r=lt(),d=[...document.querySelectorAll("[data-message-id]")],h=d[0]?.getAttribute("data-message-id")??"",$=it?` · 目标 ${A(it)?"在":"不在"} DOM`:"",L=h?` · 行ID ${h.slice(0,20)}`:"";let k="(空)";try{k=o.router.path()||"(空)"}catch{}return`轮次 ${At} · 容器 ${r?"OK":"缺失"} · DOM ${d.length} 行${$}${L} · 路由 ${k} · hash ${window.location.hash||"(空)"}${at?` · ${at}`:""}`},nt=(o,r)=>{const d=o.querySelector("[data-session-title]"),h=o.getBoundingClientRect(),$=d instanceof HTMLElement?d.getBoundingClientRect().bottom:h.top,k=r.getBoundingClientRect().top-($+24);Math.abs(k)>2&&(o.scrollTop+=k)},re=o=>{setTimeout(()=>{if(!o.isConnected)return;const r=lt();if(!r)return;const d=r.querySelector("[data-session-title]"),h=d instanceof HTMLElement?d.getBoundingClientRect().bottom:r.getBoundingClientRect().top,$=o.getBoundingClientRect().top;$<h+4&&(r.scrollTop+=$-(h+24))},300)},ne=o=>{let r="";try{r=o.router.path()||""}catch{}return r.startsWith("/")?r:""},se=o=>{const r=document.createElement("a");r.setAttribute("href",o),r.setAttribute("replace",""),r.setAttribute("noscroll",""),r.style.display="none",document.body.appendChild(r);try{r.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,button:0,view:window}))}finally{r.remove()}},oe=`
3
3
  .sr-rail {
4
4
  position: fixed;
5
5
  top: 50%;
@@ -215,4 +215,4 @@
215
215
  white-space: pre-wrap;
216
216
  max-width: min(720px, 90vw);
217
217
  }
218
- `;function ae(o){const r=R.usePlugin(),[d,g]=i.createSignal([]),[S,A]=i.createSignal(""),[y,C]=i.createSignal(!1),[Lt,Mt]=i.createSignal(""),[lt,ct]=i.createSignal(""),[k,q]=i.createSignal(!1),[B,L]=i.createSignal(0),[z,M]=i.createSignal(0),[le,J]=i.createSignal(0),[G,O]=i.createSignal(""),$=new Map;let W=0,N=!1,F=!1,V="",I;const E=()=>o.session()?.id,K=()=>{const t=[...$.values()].sort((n,l)=>n.created-l.created),e=i.untrack(d);e.length===t.length&&e.every((n,l)=>n===t[l])||(g(t),At=t.length)},dt=t=>{const e=$.get(t.id);e&&e.created===t.time&&e.text===t.text||$.set(t.id,{id:t.id,created:t.time,text:t.text})},It=async(t,e,n)=>{const l=n?{sessionID:t,type:"user",limit:e,cursor:n}:{sessionID:t,type:"user",limit:e,order:"desc"};return await r.client.message.list(l)},Y=async(t,e)=>{const n=++W;N=!0;let l="";try{let s;const c=e==="full"?Gt:1,u=e==="full"?Wt:Vt;let m=e!=="full";for(let v=0;v<c;v++){let h;try{h=await It(t,u,s)}catch(p){l=String(p?.message??p);break}if(n!==W)return;m||($.clear(),m=!0);let f=0;for(const p of h?.data??[])$.has(p.id)||(dt({id:p.id,time:p.time?.created??0,text:_t(p)}),f++);K();const x=h?.cursor?.next;if(!x||f===0)break;s=x}}finally{N=!1,V=t,ot=l,Mt($.size===0?l||"暂无用户消息":""),F&&(F=!1,ut())}},ut=()=>{I||(I=setTimeout(()=>{I=void 0;const t=i.untrack(E);t&&Y(t,"light")},300))},pt=t=>{if(!(!t||t!==i.untrack(E))){if(N){F=!0;return}ut()}},Dt=t=>{const e=t?.type;if(e==="message.updated"){const n=t?.data??{},l=n.info;l?.role==="user"&&l?.id&&(dt({id:l.id,time:l.time?.created??0,text:_t(l)}),K()),pt(n.sessionID)}else if(e==="message.removed"){const n=t?.data??{};n.messageID&&$.delete(n.messageID)&&K(),pt(n.sessionID)}else if(e==="location.shutdown"){const n=i.untrack(E);n&&V===n&&Y(n,"full")}};i.onMount(()=>{let t=!1,e=0,n;(async()=>{for(;!t;){const c=r.client.event.subscribe()[Symbol.asyncIterator]();try{for(;!t;){const u=await c.next();if(u.done)break;e=0,Dt(u.value)}}catch{}try{await c.return?.()}catch{}if(t)break;e++,await Tt(Math.min(2e3*e,15e3))}})(),i.onCleanup(()=>{t=!0,clearTimeout(n),I&&clearTimeout(I)})}),i.createEffect(()=>{const t=E();t&&i.untrack(()=>{V!==t&&(W++,N=!1,F=!1,$.clear(),g([]),A(""),X="",Y(t,"full"))})});let H;const D=()=>(H?.isConnected||(H=it()),H),Pt=()=>{const t=D();if(!t)return;const e=t.querySelectorAll("[data-message-id]");if(e.length===0)return;const n=t.getBoundingClientRect().top+40;for(const l of e)if(l.getBoundingClientRect().bottom>=n){const s=l.getAttribute("data-message-id");s&&A(s);break}};let Z=!1;const ft=()=>{Z||(Z=!0,requestAnimationFrame(()=>{Z=!1,Pt()}))};i.onMount(()=>{const t=()=>ft();document.addEventListener("scroll",t,!0);const e=setInterval(ft,1500);i.onCleanup(()=>{document.removeEventListener("scroll",t,!0),clearInterval(e)})});let gt=0;const w=(t,e=2600)=>{const n=++gt;ct(t),setTimeout(()=>{n===gt&&ct("")},e)};i.onMount(()=>{const t=n=>{if(n.key==="Escape"){if(i.untrack(k)){vt(),n.stopPropagation();return}i.untrack(y)&&(C(!1),n.stopPropagation())}},e=n=>{if(!i.untrack(y))return;(n.composedPath?.()??[]).some(c=>c instanceof Element&&c.closest?.(".sr-rail"))||C(!1)};window.addEventListener("keydown",t,!0),document.addEventListener("pointerdown",e,!0),i.onCleanup(()=>{window.removeEventListener("keydown",t,!0),document.removeEventListener("pointerdown",e,!0)})}),i.onMount(()=>{const t=()=>w(`${tt} · ${et(r)}`),e=()=>C(n=>!n);window.addEventListener(Et,t),window.addEventListener(st,e),i.onCleanup(()=>{window.removeEventListener(Et,t),window.removeEventListener(st,e)}),w(`会话轮次 ${tt} 已加载`)});let X="",_=0,ht=0,mt="";const Q=t=>{try{const e=t.querySelector('[data-slot="user-message-text"]')??t.querySelector('[data-slot="user-message-body"]')??t;e.classList.remove("sr-flash-ring"),e.offsetWidth,e.classList.add("sr-flash-ring"),setTimeout(()=>e.classList.remove("sr-flash-ring"),1900)}catch{}},jt=()=>{for(const t of d())if(T(t.id))return t},bt=(t,e)=>{se(`${t}#${nt}${e}`),X=e},wt=()=>{const e=D()?.querySelectorAll("[data-message-id]")??[];if(e.length===0)return"0";const n=e[0].getAttribute("data-message-id")??"",l=e[e.length-1].getAttribute("data-message-id")??"";return`${e.length}:${n}:${l}`},Rt=(t,e,n,l)=>new Promise(s=>{let c=!1,u,m,v;const h=Date.now();let x=wt(),p=h,b=0;const P=U=>{if(!c){c=!0;try{u?.disconnect()}catch{}clearInterval(m),clearTimeout(v),s(U??null)}},xt=U=>{if(e!==_)return P(null);const kt=U?T(t):document.getElementById(`${nt}${t}`);if(kt)return P(kt);if(!U)return;const St=wt(),$t=Date.now();if(St!==x){x=St,p=$t,b++,l?.(b);return}const Jt=b>0?Zt:Xt;$t-p>Jt&&P(null)},yt=T(t);if(yt)return P(yt);u=new MutationObserver(()=>xt(!1)),u.observe(document.documentElement,{childList:!0,subtree:!0}),m=setInterval(()=>xt(!0),120),v=setTimeout(()=>P(T(t)),Math.max(400,n))}),vt=()=>{_++,q(!1),L(0),M(0),J(0),O(""),w("已取消跳转")},qt=async t=>{if(k()&&G()===t.id){w(`正在跳转 · 已加载 ${B()} 页 · ${z()}s`,j);return}const e=++_;q(!1),L(0),M(0),J(0),O(""),at=t.id;const n=Date.now();if(t.id===mt&&n-ht<te){const h=T(t.id),f=D();if(h&&f){rt(f,h),Q(h);return}}ht=n,mt=t.id;const l=D(),s=T(t.id);if(s&&l){rt(l,s),Q(s),w("已定位");return}const c=ne(r);if(!c){w(`无法读取当前路由,无法定位 · ${et(r)}`);return}const u=E();q(!0),O(t.id),L(0),M(0),C(!0),w("正在定位…",j);const m=Date.now(),v=setInterval(()=>{M(Math.round((Date.now()-m)/1e3))},500);try{const h=Date.now()+j;for(let f=0;f<Kt&&Date.now()<h;f++){if(e!==_||E()!==u)return;if(J(f+1),X===t.id){const b=jt()??d()[0];b&&(bt(c,b.id),await Tt(Qt))}if(e!==_||E()!==u)return;bt(c,t.id),w(`跳转中 · 已加载 ${B()} 页`,j);const x=Math.min(Yt,h-Date.now()),p=await Rt(t.id,e,x,b=>{L(b),w(`跳转中 · 已加载 ${b} 页`,j)});if(e!==_||E()!==u)return;if(p){const b=D()??l;b&&rt(b,p),Q(p),w("已定位"),re(p);return}}e===_&&w(`未能定位 · ${et(r)}`)}finally{clearInterval(v),e===_&&(q(!1),L(0),M(0),J(0),O(""))}};i.createEffect(()=>{k()&&G()&&requestAnimationFrame(()=>{try{document.querySelector('.sr-list .sr-turn[data-busy="true"]')?.scrollIntoView({block:"nearest"})}catch{}})});const Bt=[a.createComponent(i.Show,{get when(){return lt()},get children(){var t=Ot();return a.insert(t,lt),t}}),(()=>{var t=Ft(),e=t.firstChild,n=e.firstChild,l=e.nextSibling;return t.addEventListener("mouseleave",()=>{k()||C(!1)}),t.addEventListener("mouseenter",()=>C(!0)),a.insert(e,a.createComponent(i.Show,{get when(){return k()},get fallback(){return(()=>{var s=Ht();return s.firstChild,a.insert(s,(()=>{var c=a.memo(()=>d().length>0);return()=>c()?` · ${d().length}`:""})(),null),s})()},get children(){var s=Nt();return s.firstChild,a.insert(s,(()=>{var c=a.memo(()=>B()>0);return()=>c()?` · 已加载 ${B()} 页`:""})(),null),a.insert(s,(()=>{var c=a.memo(()=>z()>0);return()=>c()?` · ${z()}s`:""})(),null),s}}),n),n.$$click=()=>{k()?vt():C(!1)},a.insert(l,a.createComponent(i.Show,{get when(){return d().length>0},get fallback(){return(()=>{var s=Ut();return a.insert(s,()=>Lt()||`… ${tt}`),s})()},get children(){return a.createComponent(i.For,{get each(){return d()},children:(s,c)=>(()=>{var u=zt(),m=u.firstChild,v=m.firstChild;v.firstChild;var h=v.nextSibling;return u.$$click=()=>{qt(s)},a.insert(v,()=>c()+1,null),a.insert(h,()=>ee(s.created)),a.insert(m,()=>s.text,null),a.effect(f=>{var x=S()===s.id?"true":"false",p=k()&&G()===s.id?"true":"false";return x!==f.e&&a.setAttribute(u,"data-active",f.e=x),p!==f.t&&a.setAttribute(u,"data-busy",f.t=p),f},{e:void 0,t:void 0}),u})()})}})),a.effect(s=>{var c=y()?"true":"false",u=k()?"true":"false",m=k()?"取消跳转 (Esc)":"关闭 (Esc)";return c!==s.e&&a.setAttribute(t,"data-open",s.e=c),u!==s.t&&a.setAttribute(t,"data-jumping",s.t=u),m!==s.a&&a.setAttribute(n,"title",s.a=m),s},{e:void 0,t:void 0,a:void 0}),t})()];return a.createComponent(a.Portal,{get mount(){return document.body},children:Bt})}const ie=R.Plugin.define({i18n:{en:{"command.jump":"Session turns: show / jump","command.jump.description":"Reveal the turn rail; click a turn to jump to that message"}},setup(o){o.add(R.Style,oe),o.add(R.Slot,{at:"window.bottom",render:()=>a.createComponent(i.Show,{get when(){return o.sessions.current()},get children(){return a.createComponent(ae,{session:()=>o.sessions.current()})}})}),o.add(R.Command,()=>({id:"jump",title:o.t("command.jump"),description:o.t("command.jump.description"),group:o.t("command.jump"),section:"navigation",bind:"mod+alt+r",slash:{name:"turns"},run:()=>{window.dispatchEvent(new Event(st))}}))}});a.delegateEvents(["click"]);exports.default=ie;
218
+ `;function ae(o){const r=q.usePlugin(),[d,h]=i.createSignal([]),[$,L]=i.createSignal(""),[k,T]=i.createSignal(!1),[Lt,Mt]=i.createSignal(""),[ct,dt]=i.createSignal(""),[S,B]=i.createSignal(!1),[z,M]=i.createSignal(0),[G,I]=i.createSignal(0),[le,J]=i.createSignal(0),[W,O]=i.createSignal(""),E=new Map;let V=0,N=!1,F=!1,K="",D;const _=()=>o.session()?.id,Y=()=>{const t=[...E.values()].sort((n,l)=>n.created-l.created),e=i.untrack(d);e.length===t.length&&e.every((n,l)=>n===t[l])||(h(t),At=t.length)},ut=t=>{const e=E.get(t.id);e&&e.created===t.time&&e.text===t.text||E.set(t.id,{id:t.id,created:t.time,text:t.text})},It=async(t,e,n)=>{const l=n?{sessionID:t,type:"user",limit:e,cursor:n}:{sessionID:t,type:"user",limit:e,order:"desc"};return await r.client.message.list(l)},Z=async(t,e)=>{const n=++V;N=!0;let l="";try{let s;const c=e==="full"?Gt:1,u=e==="full"?Wt:Vt;let m=e!=="full";for(let x=0;x<c;x++){let b;try{b=await It(t,u,s)}catch(f){l=String(f?.message??f);break}if(n!==V)return;m||(E.clear(),m=!0);let p=0;for(const f of b?.data??[])E.has(f.id)||(ut({id:f.id,time:f.time?.created??0,text:_t(f)}),p++);Y();const g=b?.cursor?.next;if(!g||p===0)break;s=g}}finally{N=!1,K=t,at=l,Mt(E.size===0?l||"暂无用户消息":""),F&&(F=!1,pt())}},pt=()=>{D||(D=setTimeout(()=>{D=void 0;const t=i.untrack(_);t&&Z(t,"light")},300))},ft=t=>{if(!(!t||t!==i.untrack(_))){if(N){F=!0;return}pt()}},Dt=t=>{const e=t?.type;if(e==="message.updated"){const n=t?.data??{},l=n.info;l?.role==="user"&&l?.id&&(ut({id:l.id,time:l.time?.created??0,text:_t(l)}),Y()),ft(n.sessionID)}else if(e==="message.removed"){const n=t?.data??{};n.messageID&&E.delete(n.messageID)&&Y(),ft(n.sessionID)}else if(e==="location.shutdown"){const n=i.untrack(_);n&&K===n&&Z(n,"full")}};i.onMount(()=>{let t=!1,e=0,n;(async()=>{for(;!t;){const c=r.client.event.subscribe()[Symbol.asyncIterator]();try{for(;!t;){const u=await c.next();if(u.done)break;e=0,Dt(u.value)}}catch{}try{await c.return?.()}catch{}if(t)break;e++,await Tt(Math.min(2e3*e,15e3))}})(),i.onCleanup(()=>{t=!0,clearTimeout(n),D&&clearTimeout(D)})}),i.createEffect(()=>{const t=_();t&&i.untrack(()=>{K!==t&&(V++,N=!1,F=!1,E.clear(),h([]),L(""),Q="",Z(t,"full"))})});let H;const P=()=>(H?.isConnected||(H=lt()),H),Pt=()=>{const t=P();if(!t)return;const e=t.querySelectorAll("[data-message-id]");if(e.length===0)return;const n=t.getBoundingClientRect().top+40;for(const l of e)if(l.getBoundingClientRect().bottom>=n){const s=l.getAttribute("data-message-id");s&&L(s);break}};let X=!1;const gt=()=>{X||(X=!0,requestAnimationFrame(()=>{X=!1,Pt()}))};i.onMount(()=>{const t=()=>gt();document.addEventListener("scroll",t,!0);const e=setInterval(gt,1500);i.onCleanup(()=>{document.removeEventListener("scroll",t,!0),clearInterval(e)})});let ht=0;const v=(t,e=2600)=>{const n=++ht;dt(t),setTimeout(()=>{n===ht&&dt("")},e)};i.onMount(()=>{const t=n=>{if(n.key==="Escape"){if(i.untrack(S)){xt(),n.stopPropagation();return}i.untrack(k)&&(T(!1),n.stopPropagation())}},e=n=>{if(!i.untrack(k))return;(n.composedPath?.()??[]).some(c=>c instanceof Element&&c.closest?.(".sr-rail"))||T(!1)};window.addEventListener("keydown",t,!0),document.addEventListener("pointerdown",e,!0),i.onCleanup(()=>{window.removeEventListener("keydown",t,!0),document.removeEventListener("pointerdown",e,!0)})}),i.onMount(()=>{const t=()=>v(`${et} · ${rt(r)}`),e=()=>T(n=>!n);window.addEventListener(Et,t),window.addEventListener(ot,e),i.onCleanup(()=>{window.removeEventListener(Et,t),window.removeEventListener(ot,e)}),v(`会话轮次 ${et} 已加载`)});let Q="",C=0,mt=0,bt="";const tt=t=>{try{const e=t.querySelector('[data-slot="user-message-text"]')??t.querySelector('[data-slot="user-message-body"]')??t;e.classList.remove("sr-flash-ring"),e.offsetWidth,e.classList.add("sr-flash-ring"),setTimeout(()=>e.classList.remove("sr-flash-ring"),1900)}catch{}},jt=()=>{for(const t of d())if(A(t.id))return t},wt=(t,e)=>{se(`${t}#${st}${e}`),Q=e},vt=()=>{const e=P()?.querySelectorAll("[data-message-id]")??[];if(e.length===0)return"0";const n=e[0].getAttribute("data-message-id")??"",l=e[e.length-1].getAttribute("data-message-id")??"";return`${e.length}:${n}:${l}`},Rt=(t,e,n,l)=>new Promise(s=>{let c=!1,u,m,x;const b=Date.now();let g=vt(),f=b,j=0;const y=U=>{if(!c){c=!0;try{u?.disconnect()}catch{}clearInterval(m),clearTimeout(x),s(U??null)}},w=U=>{if(e!==C)return y(null);const kt=U?A(t):document.getElementById(`${st}${t}`);if(kt)return y(kt);if(!U)return;const St=vt(),$t=Date.now();if(St!==g){g=St,f=$t,j++,l?.(j);return}const Jt=j>0?Zt:Xt;$t-f>Jt&&y(null)},yt=A(t);if(yt)return y(yt);u=new MutationObserver(()=>w(!1)),u.observe(document.documentElement,{childList:!0,subtree:!0}),m=setInterval(()=>w(!0),120),x=setTimeout(()=>y(A(t)),Math.max(400,n))}),xt=()=>{C++,B(!1),M(0),I(0),J(0),O(""),v("已取消跳转")},qt=async t=>{if(S()&&W()===t.id){v(`正在跳转 · 已加载 ${z()} 页 · ${G()}s`,R);return}const e=++C;B(!1),M(0),I(0),J(0),O(""),it=t.id;const n=Date.now();if(t.id===bt&&n-mt<te){const p=A(t.id),g=P();if(p&&g){nt(g,p),tt(p);return}}mt=n,bt=t.id;const l=P(),s=A(t.id);if(s&&l){nt(l,s),tt(s),v("已定位");return}const c=ne(r);if(!c){v(`无法读取当前路由,无法定位 · ${rt(r)}`);return}const u=_();B(!0),O(t.id),M(0),I(0),T(!0),v("正在定位…",R);const m=Date.now(),x=setInterval(()=>{I(Math.round((Date.now()-m)/1e3))},500);let b=0;try{const p=Date.now()+R;for(let g=0;g<Kt&&Date.now()<p;g++){if(e!==C||_()!==u)return;if(J(g+1),Q===t.id){const w=jt()??d()[0];w&&(wt(c,w.id),await Tt(Qt))}if(e!==C||_()!==u)return;wt(c,t.id),v(`跳转中 · 已加载 ${b} 页`,R);let f=0;const j=Math.min(Yt,p-Date.now()),y=await Rt(t.id,e,j,w=>{f=w,M(b+w),v(`跳转中 · 已加载 ${b+w} 页`,R)});if(b+=f,e!==C||_()!==u)return;if(y){const w=P()??l;w&&nt(w,y),tt(y),v("已定位"),re(y);return}}e===C&&v(`未能定位 · ${rt(r)}`)}finally{clearInterval(x),e===C&&(B(!1),M(0),I(0),J(0),O(""))}};i.createEffect(()=>{S()&&W()&&requestAnimationFrame(()=>{try{document.querySelector('.sr-list .sr-turn[data-busy="true"]')?.scrollIntoView({block:"nearest"})}catch{}})});const Bt=[a.createComponent(i.Show,{get when(){return ct()},get children(){var t=Ot();return a.insert(t,ct),t}}),(()=>{var t=Ft(),e=t.firstChild,n=e.firstChild,l=e.nextSibling;return t.addEventListener("mouseleave",()=>{S()||T(!1)}),t.addEventListener("mouseenter",()=>T(!0)),a.insert(e,a.createComponent(i.Show,{get when(){return S()},get fallback(){return(()=>{var s=Ht();return s.firstChild,a.insert(s,(()=>{var c=a.memo(()=>d().length>0);return()=>c()?` · ${d().length}`:""})(),null),s})()},get children(){var s=Nt();return s.firstChild,a.insert(s,(()=>{var c=a.memo(()=>z()>0);return()=>c()?` · 已加载 ${z()} 页`:""})(),null),a.insert(s,(()=>{var c=a.memo(()=>G()>0);return()=>c()?` · ${G()}s`:""})(),null),s}}),n),n.$$click=()=>{S()?xt():T(!1)},a.insert(l,a.createComponent(i.Show,{get when(){return d().length>0},get fallback(){return(()=>{var s=Ut();return a.insert(s,()=>Lt()||`… ${et}`),s})()},get children(){return a.createComponent(i.For,{get each(){return d()},children:(s,c)=>(()=>{var u=zt(),m=u.firstChild,x=m.firstChild;x.firstChild;var b=x.nextSibling;return u.$$click=()=>{qt(s)},a.insert(x,()=>c()+1,null),a.insert(b,()=>ee(s.created)),a.insert(m,()=>s.text,null),a.effect(p=>{var g=$()===s.id?"true":"false",f=S()&&W()===s.id?"true":"false";return g!==p.e&&a.setAttribute(u,"data-active",p.e=g),f!==p.t&&a.setAttribute(u,"data-busy",p.t=f),p},{e:void 0,t:void 0}),u})()})}})),a.effect(s=>{var c=k()?"true":"false",u=S()?"true":"false",m=S()?"取消跳转 (Esc)":"关闭 (Esc)";return c!==s.e&&a.setAttribute(t,"data-open",s.e=c),u!==s.t&&a.setAttribute(t,"data-jumping",s.t=u),m!==s.a&&a.setAttribute(n,"title",s.a=m),s},{e:void 0,t:void 0,a:void 0}),t})()];return a.createComponent(a.Portal,{get mount(){return document.body},children:Bt})}const ie=q.Plugin.define({i18n:{en:{"command.jump":"Session turns: show / jump","command.jump.description":"Reveal the turn rail; click a turn to jump to that message"}},setup(o){o.add(q.Style,oe),o.add(q.Slot,{at:"window.bottom",render:()=>a.createComponent(i.Show,{get when(){return o.sessions.current()},get children(){return a.createComponent(ae,{session:()=>o.sessions.current()})}})}),o.add(q.Command,()=>({id:"jump",title:o.t("command.jump"),description:o.t("command.jump.description"),group:o.t("command.jump"),section:"navigation",bind:"mod+alt+r",slash:{name:"turns"},run:()=>{window.dispatchEvent(new Event(ot))}}))}});a.delegateEvents(["click"]);exports.default=ie;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-session-turns",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "OpenCode Desktop 插件:在会话右缘列出每一轮用户提问,点击即可跳转到对应消息。A right-edge rail of user turns; click one to jump to that message.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/gui.tsx CHANGED
@@ -897,6 +897,9 @@ function Rail(props) {
897
897
  const elapsedTimer = setInterval(() => {
898
898
  setJumpElapsed(Math.round((Date.now() - startedAt) / 1000))
899
899
  }, 500)
900
+ // Pages loaded so far, accumulated across chains (a new chain restarts
901
+ // the per-chain counter, the headline must not go backwards).
902
+ let chainBase = 0
900
903
  try {
901
904
  const deadline = Date.now() + JUMP_TOTAL_MS
902
905
  for (let chain = 0; chain < JUMP_ROUNDS && Date.now() < deadline; chain++) {
@@ -919,13 +922,16 @@ function Rail(props) {
919
922
  }
920
923
  if (token !== jumpToken || sessionID() !== sessionAtJump) return
921
924
  navTo(path, turn.id)
922
- flash(`跳转中 · 已加载 ${jumpPages()} 页`, JUMP_TOTAL_MS)
925
+ flash(`跳转中 · 已加载 ${chainBase} 页`, JUMP_TOTAL_MS)
923
926
 
927
+ let chainPages = 0
924
928
  const remaining = Math.min(JUMP_CHAIN_MS, deadline - Date.now())
925
929
  const landed = await waitForRow(turn.id, token, remaining, (pages) => {
926
- setJumpPages(pages)
927
- flash(`跳转中 · 已加载 ${pages} 页`, JUMP_TOTAL_MS)
930
+ chainPages = pages
931
+ setJumpPages(chainBase + pages)
932
+ flash(`跳转中 · 已加载 ${chainBase + pages} 页`, JUMP_TOTAL_MS)
928
933
  })
934
+ chainBase += chainPages
929
935
  if (token !== jumpToken || sessionID() !== sessionAtJump) return
930
936
  if (landed) {
931
937
  const live = scroller() ?? sc