typebulb 0.52.4 → 0.54.0
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/SKILL.md +2 -2
- package/dist/agents/claude/client.js +2 -2
- package/dist/agents/codex/client.js +2 -2
- package/dist/agents/pi/client.js +6 -6
- package/dist/index.js +361 -239
- package/dist/servers.js +69 -69
- package/package.json +1 -1
package/SKILL.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: typebulb
|
|
3
3
|
description: "Author and run Typebulb bulbs — single-file markdown apps (TypeScript/TSX) that run locally via `npx typebulb` (full power: filesystem, database, `server.ts`, `tb.ai`) or render live inline in your coding agent's session through Typebulb's agent mirror (sandboxed, client-only). A bulb can be a visual widget (chart, simulation, diagram, calculator, UI), a full-stack tool with a Node backend, or an AI app that calls models at runtime. Covers the bulb format, the `tb.*` API, trust, and the local run/inline workflow. Use when the user wants a bulb, a quick local tool (visual, backend-backed, or AI-powered), or something visual rendered inline in the conversation."
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.54.0
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
> Generated from typebulb v0.
|
|
7
|
+
> Generated from typebulb v0.54.0. `npx typebulb agent` prints the running version alongside the path to its packaged SKILL.md: if that version is newer than this one, replace this file with that one.
|
|
8
8
|
|
|
9
9
|
# typebulb
|
|
10
10
|
|
|
@@ -1927,13 +1927,13 @@ ${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session
|
|
|
1927
1927
|
`,`or
|
|
1928
1928
|
`,"OPENAI_API_KEY=\u2026"),xt({class:"trust-modal-warn"},"Restart the mirror after saving .env, then Summary will work."),xt({class:"trust-modal-acts"},Po({class:"trust-yes",type:"button",onClick:s},"OK"))))}};var eie=class extends Ia{spread=!1;showingCode=!1;copied=!1;#e="";#n;#t;#r;#i;#s;#o;#c;#u=!1;#f=1;#l=!1;#h;#a="idle";constructor(s,a){super(),this.#n=s,this.#t=a,this.#r=xH(s);let d=Ike(s);this.#i=d.length?d.join(" "):void 0}get name(){return this.#r}get key(){return this.#t}setChainPosition(s){this.#f=s}get chainPosition(){return this.#f}setMounted(s){s!==this.#u&&(this.#u=s,this.#d())}onAttached(){this.#d()}#d(){if(this.#u){if(this.#s||this.#l||this.#o)return;this.#l=!0,this.#h=new AbortController,ISt(this.#n,{signal:this.#h.signal,onError:s=>{this.#c=s,this.#p("runtime",s),this.update()},onReady:()=>this.#p(this.#i?"malformed":"ok",this.#i)}).then(s=>{this.#l=!1,this.#u&&(this.#s=s,this.update())}).catch(s=>{this.#l=!1,this.#o=s instanceof Error?s.message:String(s),this.#p("compile",this.#o),this.update()})}else{if(!this.#s&&!this.#l)return;this.#h?.abort(),this.#h=void 0,this.#s=void 0,this.#c=void 0,this.update()}}#p(s,a){let d=this.#r??this.#t,p=s==="ok"?"ok":s==="malformed"?`malformed: ${a}`:`${s} error: ${a}`;tb.server.logInlineStatus(d,`[inline ${d} v${this.#f}] ${p}`).catch(()=>{})}dispose(){this.#h?.abort()}view(){let s=["embed","bulb-inline",this.spread?"spread":"fit",this.showingCode?"code-open":"",this.#o?"err":""],a=this.#r?`${this.#r} \u2014 `:"",d=this.#o?[`${a}could not render: ${this.#o}`]:this.#s?[this.#m(),xt({class:"bulb-frame",key:"frame",onMounted:p=>{this.#s&&p.replaceChildren(this.#s)}}),this.showingCode?this.#v():null,this.#c?xt({class:"bulb-err-strip",key:"err"},`\u26A0 ${a}${this.#c}`):null,this.#i?xt({class:"bulb-warn-strip",key:"warn"},`\u26A0 ${a}malformed: ${this.#i}`):null]:["compiling bulb\u2026"];return xt({class:"md",key:this.#t},xt({class:s},...d))}#m(){let s=this.#a==="done"?this.#e:"breakout \u2197";return xt({class:"bulb-controls",key:"controls"},this.#b("bulb-view",this.spread?"fit":"spread",this.spread?"Fit into the conversation column":"Spread to the full transcript width and height",()=>{this.spread=!this.spread,this.update()}),this.#b("bulb-toggle",this.showingCode?"run":"code",this.showingCode?"Back to the running bulb":"View this bulb's source",()=>{this.showingCode=!this.showingCode,this.update()}),this.#b(["bulb-copy",this.copied?"done":""],this.copied?"copied":"copy","Copy this bulb's full source",()=>this.#w()),Po({class:["overlay-pill","bulb-breakout",this.#a==="busy"?"launching shimmer":""],type:"button",disabled:this.#a!=="idle",title:"Save as a standalone .bulb.md and open it with typebulb",onClick:a=>{a.stopPropagation(),this.#A()}},s))}#b(s,a,d,p){let b=Array.isArray(s)?s:[s];return Po({class:["overlay-pill",...b],type:"button",title:d,onClick:v=>{v.stopPropagation(),p()}},a)}#w(){navigator.clipboard?.writeText(this.#n),this.copied=!0,this.update(),setTimeout(()=>{this.copied=!1,this.update()},1200)}async#A(){if(this.#a==="idle"){this.#a="busy",this.update();try{let{file:s,pid:a}=await tb.server.breakout(this.#n);this.#e=`launched ${s}`,window.dispatchEvent(new CustomEvent("tb-breakout",{detail:{pid:a}}))}catch(s){this.#e="breakout failed",console.error("[mirror] breakout failed",s)}this.#a="done",this.update(),setTimeout(()=>{this.#a="idle",this.update()},2500)}}#v(){return xt({class:["bulb-code","md"],key:"code",tabIndex:0,onKeyDown:s=>{if(!((s.ctrlKey||s.metaKey)&&(s.key==="a"||s.key==="A")))return;s.preventDefault();let a=getSelection();if(!a)return;let d=document.createRange();d.selectNodeContents(s.currentTarget),a.removeAllRanges(),a.addRange(d)},onMounted:s=>{s.innerHTML=tD.render(EH(this.#n))}})}};function $St(o){return o.map((s,a)=>!!s&&o[a+1]===s)}function HSt(o){let s=[];for(let a=0;a<o.length;a++)s[a]=a>0&&o[a]&&o[a]===o[a-1]?s[a-1]+1:1;return s}var GSt=".typebulb/paste",qSt={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",bmp:"image/bmp"};var Wvn=new RegExp(`@${GSt.replace(/\./g,"\\.")}/([\\w-]+(?:\\.[\\w-]+)*\\.(?:${Object.keys(qSt).join("|")}))`,"gi"),Yvn=new URL("typebulb.png",import.meta.url).href,Xvn=new URL("typebulb-inv.png",import.meta.url).href;function Vvn(o){return!o||typeof o!="object"?"":X1(o.command)??X1(o.file_path)??X1(o.filePath)??X1(o.path)??X1(o.pattern)??X1(o.query)??X1(o.url)??X1(o.skill)??X1(o.description)??""}function Zvn(o){let s=o.indexOf(`
|
|
1929
1929
|
`);return s===-1?o:o.slice(0,s).trimEnd()+" \u2026"}var nEe=o=>_3("caret",["caret-tri",o?"open":""]),e5n=()=>_3("fork","fork-icon");function zSt(o){return/^@@/m.test(o)&&/^[+-]/m.test(o)}function QSt(o){let s=[],a=!1;for(let d of o.split(`
|
|
1930
|
-
`))d.startsWith("@@")?(a&&s.push(xt({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(xt({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return xt({class:"udiff"},s)}var t5n=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function n5n(o){if(!(!o||typeof o!="object"))return(X1(o.file_path)??X1(o.filePath)??X1(o.path))||void 0}function r5n(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:X1(s.old_string),new:X1(s.new_string)}];case"Write":return[{new:X1(s.content)}];case"NotebookEdit":return[{new:X1(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function tie(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function JSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&zSt(s))}function USt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function i5n(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function rEe(o,s){o.has(s)?o.delete(s):o.add(s)}function s5n(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(tie(b.name),(s.get(tie(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var nie=class extends Ia{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new CH(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#n=0;#t=new Set;#r=!0;#i=new Map;#s=0;#o
|
|
1930
|
+
`))d.startsWith("@@")?(a&&s.push(xt({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(xt({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return xt({class:"udiff"},s)}var t5n=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function n5n(o){if(!(!o||typeof o!="object"))return(X1(o.file_path)??X1(o.filePath)??X1(o.path))||void 0}function r5n(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:X1(s.old_string),new:X1(s.new_string)}];case"Write":return[{new:X1(s.content)}];case"NotebookEdit":return[{new:X1(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function tie(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function JSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&zSt(s))}function USt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function i5n(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function rEe(o,s){o.has(s)?o.delete(s):o.add(s)}function s5n(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(tie(b.name),(s.get(tie(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var nie=class extends Ia{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new CH(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#n=0;#t=new Set;#r=!0;#i=new Map;#s=0;#o;#c=new Map;get parent(){return this.ctx.parent}clear(){for(let s of this.inlineBulbs)s.dispose();this.messages=[],this.expandedForks.clear(),this.expandedInlineBulbs.clear(),this.#c.clear(),this.#t=new Set,this.copyButtons=[],this.turnViews=[],this.liveTurnView.reset(),this.inlineBulbs=[]}#u(s){let a=new sD(s);return this.copyButtons.push(a),a}#f(){let s=new CH(()=>this.update());return this.turnViews.push(s),s}#l(s){let a={...s,copy:s.text?this.#u(s.text):void 0};return this.messages.push(a),a}#h(){let s=[];for(let a=this.messages.length-1;a>=0;a--){let d=this.messages[a];if(d.role==="user")return{prose:s.join(`
|
|
1931
1931
|
|
|
1932
1932
|
`),user:d.text};d.text&&s.unshift(d.text)}return{prose:s.join(`
|
|
1933
1933
|
|
|
1934
1934
|
`),user:""}}stickToBottomNextRender(){this.#r=!0}#a(s,a){s.segments=[...s.segments??[s.text],a],s.text=s.segments.join(`
|
|
1935
1935
|
|
|
1936
|
-
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#p(),s.live)for(let v of s.tools)t5n.has(v.name)&&this.openTools.add(v.id)}#d(s,a){let d=Zxe(a);d.some(p=>p.kind==="bulb")&&(s.body=d.map(p=>{if(p.kind==="md")return p.text;let b=new eie(p.source,`inline-${this.#n++}`);return this.inlineBulbs.push(b),b}))}#p(){let s=this.inlineBulbs.map(p=>p.name),a=$St(s),d=HSt(s);this.#t=new Set(this.inlineBulbs.filter((p,b)=>a[b])),this.inlineBulbs.forEach((p,b)=>{p.setChainPosition(d[b]),p.setMounted(!a[b]||this.expandedInlineBulbs.has(p.key))})}#m(s){rEe(this.expandedInlineBulbs,s),this.#p(),this.update()}applyToolResult(s){let a=this.#w(s.id);a&&(a.result=s.content,a.isError=s.isError,a.digest=s.digest)}applyFork(s){let a=this.#b(s.events);this.#l({id:++this.#e,role:"fork",text:"",thinking:"",tools:[],fork:{count:s.count,sub:a}})}#b(s){let a=[];for(let d of s)if(d.type==="user"){let p=a[a.length-1];p&&p.role==="user"?this.#a(p,d.text):a.push({id:++this.#e,role:"user",text:d.text,thinking:"",tools:[]})}else if(d.type==="assistant")a.push({id:++this.#e,role:"assistant",text:d.text,thinking:d.thinking,tools:d.tools.map(p=>({...p,isError:!1}))});else if(d.type==="tool_result"){let p=a.flatMap(b=>b.tools).find(b=>b.id===d.id);p&&(p.result=d.content,p.isError=d.isError,p.digest=d.digest)}return a}#w(s){return this.messages.flatMap(a=>a.tools).find(a=>a.id===s)}scrollSoon(){requestAnimationFrame(()=>{this.scrollEl&&this.#r&&(this.scrollEl.scrollTop=this.scrollEl.scrollHeight)})}onScroll(){let s=this.scrollEl;s&&(this.#r=SF(s,50))}view(){return xt({class:"messages",onScroll:()=>this.onScroll(),onMounted:s=>{this.scrollEl=s}},this.parent.ready?this.renderMessages():xt({class:"note"},"Connecting\u2026"))}renderMessages(){let s=[],a=-1;for(let D of this.messages)D.role==="user"||s.length===0?(D.role==="user"&&a++,s.push({idx:Math.max(0,a),msgs:[D]})):s[s.length-1].msgs.push(D);let d=this.parent.echo,p=this.parent.draft,b=this.parent.working&&!d,v=s.flatMap((D,P)=>this.renderTurn(D.msgs,D.idx,b&&P===s.length-1));v.unshift(this.#v());let w=d?a+1:Math.max(0,a),I=b?s[s.length-1]?.msgs??[]:[],T=[...I].reverse().find(D=>D.role==="assistant")?.turnView,B=!!T&&!!this.#x(I,T,!0);return d&&v.push(this.#C(d,w)),p?v.push(this.#y(p,w,T,!B)):(this.#i.clear(),this.#o
|
|
1936
|
+
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#p(),s.live)for(let v of s.tools)t5n.has(v.name)&&this.openTools.add(v.id)}#d(s,a){let d=Zxe(a);d.some(p=>p.kind==="bulb")&&(s.body=d.map(p=>{if(p.kind==="md")return p.text;let b=new eie(p.source,`inline-${this.#n++}`);return this.inlineBulbs.push(b),b}))}#p(){let s=this.inlineBulbs.map(p=>p.name),a=$St(s),d=HSt(s);this.#t=new Set(this.inlineBulbs.filter((p,b)=>a[b])),this.inlineBulbs.forEach((p,b)=>{p.setChainPosition(d[b]),p.setMounted(!a[b]||this.expandedInlineBulbs.has(p.key))})}#m(s){rEe(this.expandedInlineBulbs,s),this.#p(),this.update()}applyToolResult(s){let a=this.#w(s.id);a&&(a.result=s.content,a.isError=s.isError,a.digest=s.digest)}applyFork(s){let a=this.#b(s.events);this.#l({id:++this.#e,role:"fork",text:"",thinking:"",tools:[],fork:{count:s.count,sub:a}})}#b(s){let a=[];for(let d of s)if(d.type==="user"){let p=a[a.length-1];p&&p.role==="user"?this.#a(p,d.text):a.push({id:++this.#e,role:"user",text:d.text,thinking:"",tools:[]})}else if(d.type==="assistant")a.push({id:++this.#e,role:"assistant",text:d.text,thinking:d.thinking,tools:d.tools.map(p=>({...p,isError:!1}))});else if(d.type==="tool_result"){let p=a.flatMap(b=>b.tools).find(b=>b.id===d.id);p&&(p.result=d.content,p.isError=d.isError,p.digest=d.digest)}return a}#w(s){return this.messages.flatMap(a=>a.tools).find(a=>a.id===s)}scrollSoon(){requestAnimationFrame(()=>{this.scrollEl&&this.#r&&(this.scrollEl.scrollTop=this.scrollEl.scrollHeight)})}onScroll(){let s=this.scrollEl;s&&(this.#r=SF(s,50))}view(){return xt({class:"messages",onScroll:()=>this.onScroll(),onMounted:s=>{this.scrollEl=s}},this.parent.ready?this.renderMessages():xt({class:"note"},"Connecting\u2026"))}renderMessages(){let s=[],a=-1;for(let D of this.messages)D.role==="user"||s.length===0?(D.role==="user"&&a++,s.push({idx:Math.max(0,a),msgs:[D]})):s[s.length-1].msgs.push(D);let d=this.parent.echo,p=this.parent.draft,b=this.parent.working&&!d,v=s.flatMap((D,P)=>this.renderTurn(D.msgs,D.idx,b&&P===s.length-1));v.unshift(this.#v());let w=d?a+1:Math.max(0,a),I=b?s[s.length-1]?.msgs??[]:[],T=[...I].reverse().find(D=>D.role==="assistant")?.turnView,B=!!T&&!!this.#x(I,T,!0);return d&&v.push(this.#C(d,w)),p?v.push(this.#y(p,w,T,!B)):(this.#i.clear(),this.#o=void 0,this.parent.working?v.push(this.#y({text:"",thinking:"",tool:this.#A()},w,T,!B)):this.liveTurnView.reset()),v}#A(){for(let s=this.messages.length-1;s>=0;s--){let a=this.messages[s];if(a.role==="assistant")return a.tools.find(d=>d.result===void 0)?.name}}#v(){return xt({class:"masthead",key:"masthead"},zee({class:"masthead-logo light",src:Yvn,alt:"typebulb"}),zee({class:"masthead-logo dark",src:Xvn,alt:"typebulb"}),xt({class:"masthead-tagline"},"a live mirror of your agent\u2019s session, with inline bulbs, latex, svg, mermaid and more"))}#C(s,a){return xt({class:["bubble","user",bC(a)],key:`echo-${s.length}`},this.#g(`md-echo-${s.length}`,Vxe({id:-1,role:"user",text:s,thinking:"",tools:[]})))}#y(s,a,d,p=!0){let b=`draft-${s.text.length}-${s.thinking.length}`;s.text.length<this.#s&&this.#i.clear(),this.#s=s.text.length;let v=d??this.liveTurnView,w=v.raw(!0),I=w&&!!s.thinking,T=w?s.tool:void 0,B=!s.text.trim()&&!T,D=w&&(T?`${tie(T)}\u2026`:s.text.trim()||I?null:"working\u2026");return xt({class:["bubble","assistant","draft",bC(a)],key:b},p?v.view(!0):null,I?qye({class:"thinking",open:this.#o??!0,onToggle:P=>{this.#o=P.currentTarget.open}},Qye(B?ar({class:"shimmer-text shimmer-slow"},"thinking\u2026"):"thinking"),this.#S(s.thinking)):null,s.text.trim()?this.#I(b,s.text):null,D?xt({class:"draft-wait shimmer-text shimmer-slow"},D):null)}#I(s,a){let d=Zxe(a);return d.some(p=>p.kind==="bulb")?d.map((p,b)=>p.kind==="md"?p.text.trim()?this.#g(`${s}-md-${b}`,nD(p.text)):null:this.#T(p.source,b)):this.#g(s,nD(a))}#k(s,a){return{onScroll:d=>{let p=d.currentTarget;this.#i.set(s,{top:p.scrollTop,stuck:SF(p,50)})},onMounted:d=>{a?.(d);let p=this.#i.get(s);d.scrollTop=p&&!p.stuck?p.top:d.scrollHeight}}}#S(s){return i6({key:`think-${s.length}`,...this.#k(-1)},s)}#T(s,a){let d=xH(s),p=s.split(`
|
|
1937
1937
|
`).length;return xt({class:"md",key:`draft-bulb-${a}`},xt({class:"embed bulb-streaming"},xt({class:"bulb-streaming-head"},ar("\u{1F4A1} "),ar({class:"shimmer-text shimmer-slow"},`${d?`${d} \u2014 `:""}writing\u2026`),ar({class:"bulb-streaming-count"},`${p} lines`)),xt({class:["bulb-code","md"],key:`bulb-code-${s.length}`,...this.#k(a,b=>{b.innerHTML=tD.render(EH(s))})})))}renderTurn(s,a,d){let p=s.filter(B=>B.role==="user"||B.role==="fork"||B.text||B.body),b=p.find(B=>B.role==="assistant"&&(!!B.text||!!B.body)),v=[...p].reverse().find(B=>B.role==="assistant"&&(!!B.text||!!B.body)),w=[...s].reverse().find(B=>B.role==="assistant"),I=(v??w)?.turnView;if(!I)return this.#_(s,a);let T=this.#x(s,I,d);return I.raw(d)?this.#M(s,a,T,I,d):I.summary?this.#B(a,p,b,I,d):this.#D(s,a,p,T,v,I,d)}#x(s,a,d){let p=s.filter(b=>b.role==="assistant");return a.raw(d)?p[0]:p.find(b=>!!b.text||!!b.body)}#_(s,a){return s.map(d=>d.role==="fork"?this.forkStub(d,a):this.bubble(d,a))}#M(s,a,d,p,b){return s.map(v=>v.role==="fork"?this.forkStub(v,a):this.bubble(v,a,void 0,!0,v===d?p:void 0,!0,b))}#D(s,a,d,p,b,v,w){let I=d.flatMap(T=>{if(T.role==="fork")return[this.forkStub(T,a)];let B=T.role==="user"?T.copy:T===b?T.turnCopy:void 0;return[this.bubble(T,a,B??null,!0,T===p?v:void 0,!1,w)]});return p||w||I.splice(d[0]?.role==="user"?1:0,0,this.#L(s,a,v)),I}#B(s,a,d,p,b){return a.flatMap(v=>{if(v.role==="fork")return[this.forkStub(v,s)];if(v.role==="assistant")return v===d?[this.#R(v,s,p.summary,p)]:[];let w=v.role==="user"?v.copy:void 0;return[this.bubble(v,s,w??null,!0,void 0,!1,b)]})}#L(s,a,d){return xt({class:["bubble","assistant",bC(a)],key:`no-prose-${a}`},d.view(!1),xt({class:"no-prose"},s5n(s)))}#N(s,a,d,p,b,v){let w=d.has(p);return xt({class:["bubble","assistant",bC(a)],key:s},xt({class:"turn-summary",onClick:()=>{rEe(d,p),this.update()}},nEe(w),ar({class:"turn-summary-text"},b)),v??null)}forkStub(s,a){let d=s.fork,p=this.expandedForks.has(s.id)?xt({class:"fork-body"},d.sub.map(v=>this.bubble(v,a,void 0,!1))):void 0,b=[e5n(),` ${d.count} message${d.count===1?"":"s"} on an abandoned branch`];return this.#N(`fork-${s.id}`,a,this.expandedForks,s.id,b,p)}bubble(s,a,d=s.copy,p=!0,b,v=!0,w=!1){let I=s.role==="assistant"&&!s.text&&!s.thinking&&s.tools.length>0;return xt({class:["bubble",s.role,I?"tools-only":"",p?bC(a):""],key:s.id},b?b.view(w):null,v&&s.thinking?qye({class:"thinking"},Qye("thinking"),i6(s.thinking)):null,this.#j(s),s.role==="user"?this.#O(s):null,v?s.tools.map(T=>this.tool(T)):null,this.#E(d))}#E(s){return s?xt({class:"bubble-controls"},s.view()):null}#R(s,a,d,p){return xt({class:["bubble","assistant",bC(a)],key:`summary-${s.id}`},p.view(!1),this.#g(`md-summary-${s.id}-${d.length}`,nD(d)),this.#E(p.copy))}#O(s){let d=[...s.text.matchAll(Wvn)].map(p=>p[1]).map(p=>this.#P(p)).filter(p=>!!p);return d.length?xt({class:"paste-thumbs"},d.map(p=>zee({class:"paste-thumb",src:p,alt:"pasted image"}))):null}#P(s){let a=this.#c.get(s);if(!(a==="pending"||a==="failed")){if(a)return a;this.#c.set(s,"pending"),(async()=>{try{let d=await tb.server.composerPasteRead(s);this.#c.set(s,d?.ok?`data:${d.mime};base64,${d.base64}`:"failed"),d?.ok&&(this.update(),this.scrollSoon())}catch{this.#c.set(s,"failed")}})()}}#j(s){return s.body?s.body.flatMap((a,d)=>typeof a=="string"?a.trim()?[this.#g(`md-${s.id}-${d}`,nD(a))]:[]:this.#F(a)):s.text?this.#g(`md-${s.id}`,s.role==="user"?Vxe(s):nD(s.text)):null}#F(s){if(!this.#t.has(s))return[s.view()];let a=this.expandedInlineBulbs.has(s.key),d=xt({class:"md",key:`fold-${s.key}`},xt({class:"bulb-fold",onClick:()=>this.#m(s.key)},nEe(a),ar({class:"bulb-fold-text"},`${s.name??"bulb"} \u2014 Version ${s.chainPosition}`),ar({class:"bulb-fold-app"},"\u{1F4A1}")));return a?[d,s.view()]:[d]}#g(s,a){return xt({class:"md",key:s,onMounted:a})}tool(s){let a=this.openTools.has(s.id),d=n5n(s.input),p=USt(s),b=d?C6t(d,this.parent.cwd):Zvn(Vvn(s.input));return xt({class:["tool",s.isError?"err":""]},xt({class:"tool-head"},xt({class:"tool-label"},ar({class:"tool-name",...s.name.startsWith("mcp__")?{title:s.name}:{}},tie(s.name)),b?d?gC({class:"tool-sum link",title:d,onClick:v=>{v.preventDefault(),tb.server.openFile(d)}},b):ar({class:"tool-sum"},b):null),s.result===void 0?ar({class:"tool-run"},"\u2026"):null),s.result!==void 0?xt({class:["tool-digest",a?"open":""],onClick:()=>{rEe(this.openTools,s.id),this.update()}},nEe(a),(p?i5n(p):s.digest)||"(no output)"):null,a?xt({class:"tool-card"},this.toolBody(s),s.result!==void 0&&(s.isError||!(p||JSt(s).length&&s.result.trim()===s.digest))?i6({class:"tool-out"},s.result.slice(0,4e3)):null):null)}toolBody(s){let a=USt(s);if(a)return xt({class:"todo-list"},a.map(b=>xt({class:["todo",b.status??""]},ar({class:"todo-icon"},b.status==="completed"?"\u2714":b.status==="in_progress"?"\u25FC":"\u25FB"),ar({class:"todo-text"},b.content??""))));let d=JSt(s);if(d.length)return xt({class:"tool-in"},d.map(QSt));let p=r5n(s);if(!p){let b=Object.entries(s.input??{});return b.length?xt({class:"tool-in"},b.map(([v,w])=>xt({class:"tool-field"},ar({class:"tool-key"},`${v}:`),typeof w=="string"&&zSt(w)?QSt(w):i6({class:"tool-val"},typeof w=="string"?w:JSON.stringify(w,null,2))))):null}return xt({class:"diff"},...p.flatMap((b,v)=>[p.length>1?xt({class:"diff-step"},`edit ${v+1}/${p.length}`):null,b.old?i6({class:"diff-old"},String(b.old)):null,b.new?i6({class:"diff-new"},String(b.new)):null]))}};var rie=class extends Ia{ready=!1;cwd="";sessionId=null;sessionPicker=new Wre;tokenPill=new Yre;bulbsPill=new Xre;diffPill=new Zre;messageList=new nie;tokens={in:0,out:0,cached:0,cacheCreate:0};cost=0;stats=null;working=!1;latestModel=null;driverModel=null;busy=[];ownPid=0;pills;composer;draft=null;echo=null;#e=0;#n=!1;#t=!1;#r;#i=null;#s;#o;constructor(s){super(),this.pills=s.pills,this.composer=s.composer,this.#r=s.title,this.#s=s.overlays??[],this.#o=s.onPollTick}onAttached(){this.#t||(this.#t=!0,this.init())}closePopups(s){this.sessionPicker!==s&&this.sessionPicker.close(),this.bulbsPill!==s&&this.bulbsPill.close(),this.diffPill!==s&&this.diffPill.close();for(let a of this.pills)a!==s&&a.close?.()}async init(){let s=await tb.server.info();this.cwd=s.cwd,this.ownPid=s.pid??0,this.#i=s.elsewhere??null,this.composer&&(this.composer.enabled=!!s.composer),this.ready=!0,this.updateTitle(),this.update(),this.pump()}updateTitle(){let s=Uye(this.cwd),a=this.sessionPicker.currentPreview(),d=ete(a,40);document.title=d&&s?`${d} \u2014 ${s}`:d||(s?`${this.#r} \u2014 ${s}`:this.#r)}refreshSessions(){this.sessionPicker.loadSessions().then(()=>this.update()).catch(()=>{})}pump(){if(this.#n)return;this.#n=!0;let s=async()=>{try{let{events:a,cursor:d,working:p,latestModel:b,composer:v,busy:w}=await tb.server.poll(this.#e);this.#e=d;for(let F of a)this.apply(F);let I=p!==this.working;this.working=p;let T=Array.isArray(w)?w:[],B=T.join(`
|
|
1938
1938
|
`)!==this.busy.join(`
|
|
1939
1939
|
`);this.busy=T;let D=b!==this.latestModel;this.latestModel=b??null;let P=this.composer&&v?this.composer.syncFromPoll(v):!1;(a.length||I||D||P||B)&&this.update(),(a.length||P)&&this.messageList.scrollSoon(),this.#o?.()}catch(a){console.error("[mirror] poll failed",a)}setTimeout(s,600)};s()}apply(s){switch(s.type){case"cleared":this.messageList.clear(),this.tokens={in:0,out:0,cached:0,cacheCreate:0},this.cost=0;break;case"session":this.sessionId=s.sessionId,s.sessionId&&!this.sessionPicker.currentRow()?this.refreshSessions():this.updateTitle();break;case"user":this.messageList.applyUser(s);break;case"assistant":this.messageList.applyAssistant(s);break;case"tool_result":this.messageList.applyToolResult(s);break;case"fork":this.messageList.applyFork(s);break;case"usage":this.tokens={in:s.in,out:s.out,cached:s.cached,cacheCreate:s.cacheCreate},this.cost+=s.cost??0;break}}view(){return xt({class:"app"},xt({class:"chat"},this.diffPill.viewing?this.diffPill.docView():this.messageList.view(),this.#c(),...this.#s.map(s=>s()),this.statusbar()),this.composer?.enabled?this.composer.view():null)}#c(){let s=this.#i;return!this.ready||this.sessionId!==null||!s?null:xt({class:"cwd-hint"},xt({class:"cwd-hint-head"},`No sessions for ${this.cwd}`),xt(`${s.count} session${s.count===1?"":"s"} exist for `,ar({class:"cwd-hint-dir"},s.dir)," \u2014 this mirror was likely launched from a subfolder. Relaunch it from the project root."))}statusbar(){return xt({class:"statusbar"},xt({class:["statusbar-actions",this.diffPill.viewing?"doc-open":""]},this.diffPill.view(),...this.pills.map(s=>s.view()),this.tokenPill.view(),this.sessionPicker.view(),this.bulbsPill.view()))}};var o5n=[[0,"Low"],[1,"Med"],[2,"High"]],c5n=1,iie=o=>o?.message??String(o),u5n=()=>y6t({viewBox:"0 0 24 24",width:"15",height:"15",class:"anthropic-glyph",fill:"currentColor"},v6t({d:"M13.827 3.52h3.603L24 20h-3.603l-6.57-16.48zm-7.258 0h3.767L16.906 20h-3.674l-1.343-3.461H5.017l-1.344 3.46H0L6.57 3.522zm4.132 9.959L8.453 7.687 6.205 13.48H10.7z"})),KSt=o=>o===!0?"ok":o===!1?"bad":"warn",sie=class extends y4{models=[];hasKey=!0;loaded=!1;current={active:!1,managed:!1,model:null,port:null,provider:null,routedModel:null,caching:"unknown",reasoning:null,externalBaseUrl:null};busy=!1;err=null;enteringKey=!1;keyDraft="";probes={};probing=null;openDiag=null;infoOpen=!1;ticking=!1;keepOpenSelector=".model-wrap";filterId="model-filter";listSelector="#model-list";filterNoun="model";search(){return Promise.resolve([])}modeToggle(){return null}onActivate(s){let a=this.rows()[s];a&&(a.kind==="default"?this.clear():a.kind==="unlock"?this.beginKeyEntry():this.set(a.id))}onAttached(){this.refresh()}async refresh(){try{let[s,a]=await Promise.all([tb.server.listSwitchModels(),tb.server.switchState()]);this.models=s.models,this.hasKey=s.hasKey,this.current=a,this.err=s.error??null}catch(s){this.err=iie(s),console.error("[mirror] switcher refresh failed",s)}finally{this.loaded=!0,this.update()}}async tickState(){if(!(this.ticking||this.enteringKey)){this.ticking=!0;try{let s=await tb.server.switchState(),a=s.active!==this.current.active||s.model!==this.current.model||s.caching!==this.current.caching||s.routedModel!==this.current.routedModel||s.externalBaseUrl!==this.current.externalBaseUrl||s.provider!==this.current.provider||s.reasoning!==this.current.reasoning;this.current=s,a&&this.update()}catch{}finally{this.ticking=!1}}}rows(){let s=[];if(!this.hasKey)s.push({kind:"unlock"});else{let a=this.filter.trim().toLowerCase(),d=null;for(let p of this.models){if(a&&!p.label.toLowerCase().includes(a)&&!p.id.toLowerCase().includes(a))continue;let b={kind:"model",id:p.id,label:p.label,active:this.current.active&&this.current.model===p.id};b.active?d=b:s.push(b)}d&&s.push(d)}return s.push({kind:"default",active:!this.current.active&&!this.current.externalBaseUrl}),s}activeIndex(){let s=this.rows(),a=s.findIndex(d=>d.active);return a<0?Math.max(0,s.length-1):a}async show(){this.beginOpen(),this.refreshList(this.activeIndex()),this.focusFilter(),await this.refresh(),this.refreshList(this.activeIndex()),this.armClose()}onClosed(){super.onClosed(),this.enteringKey=!1,this.keyDraft="",this.openDiag=null,this.infoOpen=!1,this.err=null}async probe(s){if(!this.probing){this.probing=s,this.update();try{this.probes[s]=await tb.server.probeModel({model:s})}catch(a){this.probes[s]={ok:!1,error:iie(a)}}this.probing=null,this.update()}}showDiag(s){this.openDiag=s,this.update()}closeDiag(){this.openDiag=null,this.update(),this.focusFilter()}label(s){return s?this.models.find(a=>a.id===s)?.label||s.split("/").pop()||s:"Anthropic"}async runBusy(s,a){this.busy=!0,this.err=null,this.update();try{let d=await s();if(d?.ok===!1)return this.err=d.error||a,this.busy=!1,this.update(),!1}catch(d){return this.err=iie(d),this.busy=!1,this.update(),!1}return this.busy=!1,!0}async set(s){await this.runBusy(()=>tb.server.setSwitchModel({model:s}),"failed to set model")&&(await this.refresh(),this.close())}async clear(){await this.runBusy(()=>tb.server.clearSwitchModel(),"failed to revert")&&(await this.refresh(),this.close())}get reasoningSel(){return this.current.reasoning??c5n}set reasoningSel(s){this.setReasoning(s)}async setReasoning(s){if(this.current.reasoning!==s){this.current={...this.current,reasoning:s},this.update();try{let a=await tb.server.setReasoning({level:s});a?.ok===!1&&(this.err=a.error||"failed to set reasoning",this.update())}catch(a){this.err=iie(a),this.update()}}}beginKeyEntry(){this.enteringKey=!0,this.keyDraft="",this.update(),setTimeout(()=>document.getElementById("or-key-input")?.focus())}cancelKeyEntry(){this.enteringKey=!1,this.keyDraft="",this.update(),this.focusFilter()}async saveKey(){let s=this.keyDraft.trim();s&&await this.runBusy(()=>tb.server.saveOpenRouterKey({key:s}),"failed to save key")&&(this.enteringKey=!1,this.keyDraft="",await this.refresh(),this.refreshList(this.activeIndex()))}get overridden(){return this.current.active}get uncached(){return this.current.active&&this.current.caching==="uncached"}watchdogView(){return this.uncached?xt({class:["model-banner","warn"]},ar({class:"model-banner-text"},`${this.label(this.current.model)} was served uncached via OpenRouter \u2014 the full context is re-billed each turn. Probe the model to pin a provider that caches, or pick a different one.`)):null}head(){return this.current.active?xt({class:"model-head"},Po({class:"model-info-toggle",onClick:s=>{s.stopPropagation(),this.infoOpen=!0,this.update()}},"Routing info"),xt({class:"reasoning-ctl",title:"Reasoning sets the route\u2019s base thinking effort."},ar({class:"reasoning-label"},"reasoning"),this.reasoningSelect())):this.current.externalBaseUrl?xt({class:"model-head"},ar({class:["model-route","warn"]},"Custom base URL set elsewhere \u2014 \u201CAnthropic (native)\u201D clears it")):null}reasoningSelect(){return A6t({target:this,prop:()=>this.reasoningSel,attrs:{class:"reasoning-select",onClick:s=>s.stopPropagation()},options:o5n.map(([s,a])=>({value:s,label:a}))})}infoView(){let s=this.label(this.current.model),a=()=>{this.infoOpen=!1,this.update()};return xt({class:"picker model-picker diag-mode",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&(d.stopPropagation(),a())}},xt({class:"diag-head"},ar({class:"diag-name"},"Routing"),xt({class:"diag-head-acts"},Po({class:"diag-back",title:"Back to the model list",onClick:d=>{d.stopPropagation(),a()}},"\u2190 models"))),xt({class:"diag-body"},xt({class:"diag-line"},`You are currently routing to ${s} via OpenRouter, not your Anthropic subscription.`),xt({class:"diag-line"},"The route is shared by every Claude Code conversation scoped to this project."),xt({class:"diag-line"},"Switching to or from Anthropic toggles the proxy, so for existing conversations you\u2019ll need to:"),xt({class:["diag-line","diag-bullet"]},"\u2022 Relaunch the Claude CLI"),xt({class:["diag-line","diag-bullet"]},"\u2022 or, in the VS Code extension, run \u201CDeveloper: Restart Extension Host\u201D (Cmd/Ctrl+Shift+P).")))}view(){let s=this.current.active,a=this.uncached,d=!s&&!!this.current.externalBaseUrl,p=this.label(this.current.model),b=a?`${p} via OpenRouter, uncached \u2014 full context re-billed each turn. Click to switch or revert.`:s?`claude \u2192 ${this.current.model}: its Anthropic API is proxied to OpenRouter. Click to switch or revert.`:d?`Custom ANTHROPIC_BASE_URL set outside this tool (${this.current.externalBaseUrl}). Click to manage.`:"Anthropic (native) \u2014 click to proxy claude\u2019s Anthropic API to an OpenRouter model.",v=s?p:d?"custom route":u5n();return xt({class:"model-wrap pop-center"},Po({class:["pill",s||d?"on":"glyph",a?"warn":""],title:b,ariaLabel:s||d?void 0:"Anthropic (native)",onClick:w=>{w.stopPropagation(),this.open?this.close():this.show()}},v),this.open?this.popup():null)}popup(){if(this.enteringKey)return this.keyView();if(this.infoOpen)return this.infoView();if(this.openDiag)return this.diagView(this.openDiag);let s=this.rows(),a=this.loaded&&this.hasKey&&!this.models.length;return xt({class:"picker model-picker"},this.head(),xt({id:"model-list",class:"picker-list",onScroll:()=>this.onListScroll()},s.map((d,p)=>this.row(d,p)),a?xt({class:"picker-empty"},this.err?`Couldn't load models: ${this.err}`:"No OpenRouter models in the catalog right now."):null),this.err&&!a?xt({class:"model-err"},`\u2717 ${this.err}`):null,this.hasKey&&this.models.length?this.filterBox(this.models.length,"model"):null)}row(s,a){let d=()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},p=["picker-row",a===this.highlighted?"active":""];if(s.kind==="unlock")return xt({class:p,onMouseEnter:d,onClick:()=>this.onActivate(a)},xt({class:"picker-row-main"},ar({class:"picker-dot"}),ar({class:"picker-preview"},"+ Add OpenRouter key to unlock models\u2026")));if(s.kind==="default")return xt({class:[...p,s.active?"current":"","model-row","model-default-row"],title:"Your normal claude (subscription / API) \u2014 clears the override",onMouseEnter:d,onClick:()=>this.onActivate(a)},xt({class:"picker-row-main"},ar({class:"picker-dot"}),ar({class:"picker-preview"},"Anthropic (native)"),xt({class:"model-trailing"},s.active?this.activeBadge():null)));let b=s.id;return xt({class:[...p,s.active?"current":"","model-row"],title:b,onMouseEnter:d,onClick:()=>this.onActivate(a)},xt({class:"picker-row-main"},ar({class:"picker-dot"}),ar({class:"picker-preview"},s.label),xt({class:"model-trailing"},s.active?this.activeBadge():null,this.statusButton(b))))}activeBadge(){return ar({class:["model-btn","model-active"],title:"Active \u2014 bare claude routes here now"},"active")}statusButton(s){if(this.probing===s)return ar({class:["model-btn","model-status","probing"]},"probing\u2026");let a=this.probes[s];if(!a)return Po({class:["model-btn","model-status","probe"],title:"Check if it\u2019s callable and which provider caches \u2014 pins the caching one.",onClick:p=>{p.stopPropagation(),this.probe(s)}},"probe");let d=this.badge(a);return Po({class:["model-btn","model-status",d.cls],title:`${d.title} \xB7 click for details`,onClick:p=>{p.stopPropagation(),this.showDiag(s)}},d.text)}badge(s){if(!s.ok||s.callable===!1)return{text:"error",cls:"bad",title:s.error||"unavailable"};let a=s.provider?` on ${s.provider}`:"",d=s.cache?.works,p=KSt(d);return d===!0?{text:"cached",cls:p,title:`caching confirmed${a} \u2014 ${s.cache?.note||""}`}:d===!1?{text:"uncached",cls:p,title:`no caching${a} \u2014 ${s.cache?.note||""}`}:{text:"cache?",cls:p,title:`${s.cache?.note||"caching unconfirmed"}${a}`}}diagView(s){return xt({class:"picker model-picker diag-mode",tabIndex:0,onMounted:a=>a.focus(),onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeDiag())}},xt({class:"diag-head"},ar({class:"diag-name"},this.label(s)),xt({class:"diag-head-acts"},Po({class:"diag-back",title:"Re-run the probe",disabled:this.probing===s,onClick:a=>{a.stopPropagation(),this.probe(s)}},this.probing===s?"probing\u2026":"probe again"),Po({class:"diag-back",title:"Back to the model list",onClick:a=>{a.stopPropagation(),this.closeDiag()}},"\u2190 models"))),xt({class:"diag-body"},...this.diagLines(s)))}diagLines(s){let a=this.probes[s];if(!a)return[xt({class:["diag-line","muted"]},"Not probed yet \u2014 close this and hit probe.")];let d=[];if(!a.ok||a.callable===!1)d.push(xt({class:["diag-line","bad"]},`\u2717 Not callable${a.status?` (HTTP ${a.status})`:""}: ${a.error||"unknown error"}`)),a.restriction&&d.push(xt({class:["diag-line","warn"]},`\u26A0 ${a.restriction}`));else{d.push(xt({class:["diag-line","ok"]},`\u2713 Callable${a.ms?` \xB7 ${a.ms}ms`:""}${a.sample?` \xB7 replied \u201C${a.sample}\u201D`:""}`)),a.provider&&d.push(xt({class:["diag-line","muted"]},`Served by ${a.provider} this probe \u2014 the proxy will pin CC's turns to it when caching is confirmed.`));let p=a.cache;if(p){let b=KSt(p.works),v=p.works===!0?"\u2713 Caching works":p.works===!1?"\u2717 No caching":"~ Caching unconfirmed",w=a.provider?` on ${a.provider}`:"";d.push(xt({class:["diag-line",b]},`${v}${w} \u2014 ${p.note}`)),p.works!==!0&&d.push(xt({class:["diag-line","muted"]},"Without prompt caching every turn re-bills the whole context \u2014 costly over a long session."))}}return d.push(xt({class:["diag-line","muted","small"]},"Caching on OpenRouter is per-provider; the proxy pins the provider a probe confirms so CC keeps caching. A probe makes two small test calls.")),d}keyView(){return xt({class:"picker model-picker key-entry",tabIndex:0,onKeyDown:s=>{s.key==="Escape"&&(s.stopPropagation(),this.cancelKeyEntry())}},xt({class:"key-entry-head"},"Paste your OpenRouter API key"),Wee({target:this,prop:()=>this.keyDraft,id:"or-key-input",attrs:{class:"bulb-filter",placeholder:"sk-or-\u2026",ariaLabel:"OpenRouter API key",onKeyDown:s=>{s.key==="Enter"?(s.preventDefault(),this.saveKey()):s.key==="Escape"&&(s.stopPropagation(),this.cancelKeyEntry())}}}),this.err?xt({class:"model-err"},`\u2717 ${this.err}`):null,xt({class:"key-entry-acts"},Po({class:"pill",onClick:s=>{s.stopPropagation(),this.cancelKeyEntry()}},"Cancel"),Po({class:["pill","on"],onClick:s=>{s.stopPropagation(),this.saveKey()}},this.busy?"Saving\u2026":"Save")),xt({class:"key-entry-note"},"Written to .env in this project (gitignored). Used only via OpenRouter."))}};document.title="Claude Mirror";var iEe=new sie;new g6t({root:new rie({title:"Claude Mirror",pills:[iEe],overlays:[()=>iEe.watchdogView()],onPollTick:()=>{iEe.tickState()}}),id:"app"});
|
|
@@ -1927,13 +1927,13 @@ ${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session
|
|
|
1927
1927
|
`,`or
|
|
1928
1928
|
`,"OPENAI_API_KEY=\u2026"),rn({class:"trust-modal-warn"},"Restart the mirror after saving .env, then Summary will work."),rn({class:"trust-modal-acts"},Wu({class:"trust-yes",type:"button",onClick:s},"OK"))))}};var Vre=class extends Ku{spread=!1;showingCode=!1;copied=!1;#e="";#n;#t;#r;#i;#s;#o;#c;#u=!1;#f=1;#l=!1;#h;#a="idle";constructor(s,a){super(),this.#n=s,this.#t=a,this.#r=xH(s);let d=yke(s);this.#i=d.length?d.join(" "):void 0}get name(){return this.#r}get key(){return this.#t}setChainPosition(s){this.#f=s}get chainPosition(){return this.#f}setMounted(s){s!==this.#u&&(this.#u=s,this.#d())}onAttached(){this.#d()}#d(){if(this.#u){if(this.#s||this.#l||this.#o)return;this.#l=!0,this.#h=new AbortController,bSt(this.#n,{signal:this.#h.signal,onError:s=>{this.#c=s,this.#p("runtime",s),this.update()},onReady:()=>this.#p(this.#i?"malformed":"ok",this.#i)}).then(s=>{this.#l=!1,this.#u&&(this.#s=s,this.update())}).catch(s=>{this.#l=!1,this.#o=s instanceof Error?s.message:String(s),this.#p("compile",this.#o),this.update()})}else{if(!this.#s&&!this.#l)return;this.#h?.abort(),this.#h=void 0,this.#s=void 0,this.#c=void 0,this.update()}}#p(s,a){let d=this.#r??this.#t,p=s==="ok"?"ok":s==="malformed"?`malformed: ${a}`:`${s} error: ${a}`;tb.server.logInlineStatus(d,`[inline ${d} v${this.#f}] ${p}`).catch(()=>{})}dispose(){this.#h?.abort()}view(){let s=["embed","bulb-inline",this.spread?"spread":"fit",this.showingCode?"code-open":"",this.#o?"err":""],a=this.#r?`${this.#r} \u2014 `:"",d=this.#o?[`${a}could not render: ${this.#o}`]:this.#s?[this.#m(),rn({class:"bulb-frame",key:"frame",onMounted:p=>{this.#s&&p.replaceChildren(this.#s)}}),this.showingCode?this.#v():null,this.#c?rn({class:"bulb-err-strip",key:"err"},`\u26A0 ${a}${this.#c}`):null,this.#i?rn({class:"bulb-warn-strip",key:"warn"},`\u26A0 ${a}malformed: ${this.#i}`):null]:["compiling bulb\u2026"];return rn({class:"md",key:this.#t},rn({class:s},...d))}#m(){let s=this.#a==="done"?this.#e:"breakout \u2197";return rn({class:"bulb-controls",key:"controls"},this.#b("bulb-view",this.spread?"fit":"spread",this.spread?"Fit into the conversation column":"Spread to the full transcript width and height",()=>{this.spread=!this.spread,this.update()}),this.#b("bulb-toggle",this.showingCode?"run":"code",this.showingCode?"Back to the running bulb":"View this bulb's source",()=>{this.showingCode=!this.showingCode,this.update()}),this.#b(["bulb-copy",this.copied?"done":""],this.copied?"copied":"copy","Copy this bulb's full source",()=>this.#w()),Wu({class:["overlay-pill","bulb-breakout",this.#a==="busy"?"launching shimmer":""],type:"button",disabled:this.#a!=="idle",title:"Save as a standalone .bulb.md and open it with typebulb",onClick:a=>{a.stopPropagation(),this.#A()}},s))}#b(s,a,d,p){let b=Array.isArray(s)?s:[s];return Wu({class:["overlay-pill",...b],type:"button",title:d,onClick:v=>{v.stopPropagation(),p()}},a)}#w(){navigator.clipboard?.writeText(this.#n),this.copied=!0,this.update(),setTimeout(()=>{this.copied=!1,this.update()},1200)}async#A(){if(this.#a==="idle"){this.#a="busy",this.update();try{let{file:s,pid:a}=await tb.server.breakout(this.#n);this.#e=`launched ${s}`,window.dispatchEvent(new CustomEvent("tb-breakout",{detail:{pid:a}}))}catch(s){this.#e="breakout failed",console.error("[mirror] breakout failed",s)}this.#a="done",this.update(),setTimeout(()=>{this.#a="idle",this.update()},2500)}}#v(){return rn({class:["bulb-code","md"],key:"code",tabIndex:0,onKeyDown:s=>{if(!((s.ctrlKey||s.metaKey)&&(s.key==="a"||s.key==="A")))return;s.preventDefault();let a=getSelection();if(!a)return;let d=document.createRange();d.selectNodeContents(s.currentTarget),a.removeAllRanges(),a.addRange(d)},onMounted:s=>{s.innerHTML=tD.render(EH(this.#n))}})}};function MSt(o){return o.map((s,a)=>!!s&&o[a+1]===s)}function DSt(o){let s=[];for(let a=0;a<o.length;a++)s[a]=a>0&&o[a]&&o[a]===o[a-1]?s[a-1]+1:1;return s}var BSt=".typebulb/paste",LSt={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",bmp:"image/bmp"};var Ovn=new RegExp(`@${BSt.replace(/\./g,"\\.")}/([\\w-]+(?:\\.[\\w-]+)*\\.(?:${Object.keys(LSt).join("|")}))`,"gi"),Pvn=new URL("typebulb.png",import.meta.url).href,jvn=new URL("typebulb-inv.png",import.meta.url).href;function Fvn(o){return!o||typeof o!="object"?"":Xh(o.command)??Xh(o.file_path)??Xh(o.filePath)??Xh(o.path)??Xh(o.pattern)??Xh(o.query)??Xh(o.url)??Xh(o.skill)??Xh(o.description)??""}function $vn(o){let s=o.indexOf(`
|
|
1929
1929
|
`);return s===-1?o:o.slice(0,s).trimEnd()+" \u2026"}var Xxe=o=>T3("caret",["caret-tri",o?"open":""]),Hvn=()=>T3("fork","fork-icon");function PSt(o){return/^@@/m.test(o)&&/^[+-]/m.test(o)}function NSt(o){let s=[],a=!1;for(let d of o.split(`
|
|
1930
|
-
`))d.startsWith("@@")?(a&&s.push(rn({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(rn({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return rn({class:"udiff"},s)}var Gvn=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function qvn(o){if(!(!o||typeof o!="object"))return(Xh(o.file_path)??Xh(o.filePath)??Xh(o.path))||void 0}function Qvn(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:Xh(s.old_string),new:Xh(s.new_string)}];case"Write":return[{new:Xh(s.content)}];case"NotebookEdit":return[{new:Xh(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function Zre(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function RSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&PSt(s))}function OSt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function Jvn(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function Vxe(o,s){o.has(s)?o.delete(s):o.add(s)}function Uvn(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(Zre(b.name),(s.get(Zre(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var eie=class extends Ku{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new CH(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#n=0;#t=new Set;#r=!0;#i=new Map;#s=0;#o
|
|
1930
|
+
`))d.startsWith("@@")?(a&&s.push(rn({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(rn({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return rn({class:"udiff"},s)}var Gvn=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function qvn(o){if(!(!o||typeof o!="object"))return(Xh(o.file_path)??Xh(o.filePath)??Xh(o.path))||void 0}function Qvn(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:Xh(s.old_string),new:Xh(s.new_string)}];case"Write":return[{new:Xh(s.content)}];case"NotebookEdit":return[{new:Xh(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function Zre(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function RSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&PSt(s))}function OSt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function Jvn(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function Vxe(o,s){o.has(s)?o.delete(s):o.add(s)}function Uvn(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(Zre(b.name),(s.get(Zre(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var eie=class extends Ku{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new CH(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#n=0;#t=new Set;#r=!0;#i=new Map;#s=0;#o;#c=new Map;get parent(){return this.ctx.parent}clear(){for(let s of this.inlineBulbs)s.dispose();this.messages=[],this.expandedForks.clear(),this.expandedInlineBulbs.clear(),this.#c.clear(),this.#t=new Set,this.copyButtons=[],this.turnViews=[],this.liveTurnView.reset(),this.inlineBulbs=[]}#u(s){let a=new sD(s);return this.copyButtons.push(a),a}#f(){let s=new CH(()=>this.update());return this.turnViews.push(s),s}#l(s){let a={...s,copy:s.text?this.#u(s.text):void 0};return this.messages.push(a),a}#h(){let s=[];for(let a=this.messages.length-1;a>=0;a--){let d=this.messages[a];if(d.role==="user")return{prose:s.join(`
|
|
1931
1931
|
|
|
1932
1932
|
`),user:d.text};d.text&&s.unshift(d.text)}return{prose:s.join(`
|
|
1933
1933
|
|
|
1934
1934
|
`),user:""}}stickToBottomNextRender(){this.#r=!0}#a(s,a){s.segments=[...s.segments??[s.text],a],s.text=s.segments.join(`
|
|
1935
1935
|
|
|
1936
|
-
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#p(),s.live)for(let v of s.tools)Gvn.has(v.name)&&this.openTools.add(v.id)}#d(s,a){let d=Kxe(a);d.some(p=>p.kind==="bulb")&&(s.body=d.map(p=>{if(p.kind==="md")return p.text;let b=new Vre(p.source,`inline-${this.#n++}`);return this.inlineBulbs.push(b),b}))}#p(){let s=this.inlineBulbs.map(p=>p.name),a=MSt(s),d=DSt(s);this.#t=new Set(this.inlineBulbs.filter((p,b)=>a[b])),this.inlineBulbs.forEach((p,b)=>{p.setChainPosition(d[b]),p.setMounted(!a[b]||this.expandedInlineBulbs.has(p.key))})}#m(s){Vxe(this.expandedInlineBulbs,s),this.#p(),this.update()}applyToolResult(s){let a=this.#w(s.id);a&&(a.result=s.content,a.isError=s.isError,a.digest=s.digest)}applyFork(s){let a=this.#b(s.events);this.#l({id:++this.#e,role:"fork",text:"",thinking:"",tools:[],fork:{count:s.count,sub:a}})}#b(s){let a=[];for(let d of s)if(d.type==="user"){let p=a[a.length-1];p&&p.role==="user"?this.#a(p,d.text):a.push({id:++this.#e,role:"user",text:d.text,thinking:"",tools:[]})}else if(d.type==="assistant")a.push({id:++this.#e,role:"assistant",text:d.text,thinking:d.thinking,tools:d.tools.map(p=>({...p,isError:!1}))});else if(d.type==="tool_result"){let p=a.flatMap(b=>b.tools).find(b=>b.id===d.id);p&&(p.result=d.content,p.isError=d.isError,p.digest=d.digest)}return a}#w(s){return this.messages.flatMap(a=>a.tools).find(a=>a.id===s)}scrollSoon(){requestAnimationFrame(()=>{this.scrollEl&&this.#r&&(this.scrollEl.scrollTop=this.scrollEl.scrollHeight)})}onScroll(){let s=this.scrollEl;s&&(this.#r=SF(s,50))}view(){return rn({class:"messages",onScroll:()=>this.onScroll(),onMounted:s=>{this.scrollEl=s}},this.parent.ready?this.renderMessages():rn({class:"note"},"Connecting\u2026"))}renderMessages(){let s=[],a=-1;for(let B of this.messages)B.role==="user"||s.length===0?(B.role==="user"&&a++,s.push({idx:Math.max(0,a),msgs:[B]})):s[s.length-1].msgs.push(B);let d=this.parent.echo,p=this.parent.draft,b=this.parent.working&&!d,v=s.flatMap((B,P)=>this.renderTurn(B.msgs,B.idx,b&&P===s.length-1));v.unshift(this.#v());let w=d?a+1:Math.max(0,a),I=b?s[s.length-1]?.msgs??[]:[],T=[...I].reverse().find(B=>B.role==="assistant")?.turnView,D=!!T&&!!this.#x(I,T,!0);return d&&v.push(this.#C(d,w)),p?v.push(this.#y(p,w,T,!D)):(this.#i.clear(),this.#o
|
|
1936
|
+
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#p(),s.live)for(let v of s.tools)Gvn.has(v.name)&&this.openTools.add(v.id)}#d(s,a){let d=Kxe(a);d.some(p=>p.kind==="bulb")&&(s.body=d.map(p=>{if(p.kind==="md")return p.text;let b=new Vre(p.source,`inline-${this.#n++}`);return this.inlineBulbs.push(b),b}))}#p(){let s=this.inlineBulbs.map(p=>p.name),a=MSt(s),d=DSt(s);this.#t=new Set(this.inlineBulbs.filter((p,b)=>a[b])),this.inlineBulbs.forEach((p,b)=>{p.setChainPosition(d[b]),p.setMounted(!a[b]||this.expandedInlineBulbs.has(p.key))})}#m(s){Vxe(this.expandedInlineBulbs,s),this.#p(),this.update()}applyToolResult(s){let a=this.#w(s.id);a&&(a.result=s.content,a.isError=s.isError,a.digest=s.digest)}applyFork(s){let a=this.#b(s.events);this.#l({id:++this.#e,role:"fork",text:"",thinking:"",tools:[],fork:{count:s.count,sub:a}})}#b(s){let a=[];for(let d of s)if(d.type==="user"){let p=a[a.length-1];p&&p.role==="user"?this.#a(p,d.text):a.push({id:++this.#e,role:"user",text:d.text,thinking:"",tools:[]})}else if(d.type==="assistant")a.push({id:++this.#e,role:"assistant",text:d.text,thinking:d.thinking,tools:d.tools.map(p=>({...p,isError:!1}))});else if(d.type==="tool_result"){let p=a.flatMap(b=>b.tools).find(b=>b.id===d.id);p&&(p.result=d.content,p.isError=d.isError,p.digest=d.digest)}return a}#w(s){return this.messages.flatMap(a=>a.tools).find(a=>a.id===s)}scrollSoon(){requestAnimationFrame(()=>{this.scrollEl&&this.#r&&(this.scrollEl.scrollTop=this.scrollEl.scrollHeight)})}onScroll(){let s=this.scrollEl;s&&(this.#r=SF(s,50))}view(){return rn({class:"messages",onScroll:()=>this.onScroll(),onMounted:s=>{this.scrollEl=s}},this.parent.ready?this.renderMessages():rn({class:"note"},"Connecting\u2026"))}renderMessages(){let s=[],a=-1;for(let B of this.messages)B.role==="user"||s.length===0?(B.role==="user"&&a++,s.push({idx:Math.max(0,a),msgs:[B]})):s[s.length-1].msgs.push(B);let d=this.parent.echo,p=this.parent.draft,b=this.parent.working&&!d,v=s.flatMap((B,P)=>this.renderTurn(B.msgs,B.idx,b&&P===s.length-1));v.unshift(this.#v());let w=d?a+1:Math.max(0,a),I=b?s[s.length-1]?.msgs??[]:[],T=[...I].reverse().find(B=>B.role==="assistant")?.turnView,D=!!T&&!!this.#x(I,T,!0);return d&&v.push(this.#C(d,w)),p?v.push(this.#y(p,w,T,!D)):(this.#i.clear(),this.#o=void 0,this.parent.working?v.push(this.#y({text:"",thinking:"",tool:this.#A()},w,T,!D)):this.liveTurnView.reset()),v}#A(){for(let s=this.messages.length-1;s>=0;s--){let a=this.messages[s];if(a.role==="assistant")return a.tools.find(d=>d.result===void 0)?.name}}#v(){return rn({class:"masthead",key:"masthead"},zee({class:"masthead-logo light",src:Pvn,alt:"typebulb"}),zee({class:"masthead-logo dark",src:jvn,alt:"typebulb"}),rn({class:"masthead-tagline"},"a live mirror of your agent\u2019s session, with inline bulbs, latex, svg, mermaid and more"))}#C(s,a){return rn({class:["bubble","user",bC(a)],key:`echo-${s.length}`},this.#g(`md-echo-${s.length}`,zxe({id:-1,role:"user",text:s,thinking:"",tools:[]})))}#y(s,a,d,p=!0){let b=`draft-${s.text.length}-${s.thinking.length}`;s.text.length<this.#s&&this.#i.clear(),this.#s=s.text.length;let v=d??this.liveTurnView,w=v.raw(!0),I=w&&!!s.thinking,T=w?s.tool:void 0,D=!s.text.trim()&&!T,B=w&&(T?`${Zre(T)}\u2026`:s.text.trim()||I?null:"working\u2026");return rn({class:["bubble","assistant","draft",bC(a)],key:b},p?v.view(!0):null,I?jye({class:"thinking",open:this.#o??!0,onToggle:P=>{this.#o=P.currentTarget.open}},Fye(D?Ir({class:"shimmer-text shimmer-slow"},"thinking\u2026"):"thinking"),this.#S(s.thinking)):null,s.text.trim()?this.#I(b,s.text):null,B?rn({class:"draft-wait shimmer-text shimmer-slow"},B):null)}#I(s,a){let d=Kxe(a);return d.some(p=>p.kind==="bulb")?d.map((p,b)=>p.kind==="md"?p.text.trim()?this.#g(`${s}-md-${b}`,nD(p.text)):null:this.#T(p.source,b)):this.#g(s,nD(a))}#k(s,a){return{onScroll:d=>{let p=d.currentTarget;this.#i.set(s,{top:p.scrollTop,stuck:SF(p,50)})},onMounted:d=>{a?.(d);let p=this.#i.get(s);d.scrollTop=p&&!p.stuck?p.top:d.scrollHeight}}}#S(s){return r6({key:`think-${s.length}`,...this.#k(-1)},s)}#T(s,a){let d=xH(s),p=s.split(`
|
|
1937
1937
|
`).length;return rn({class:"md",key:`draft-bulb-${a}`},rn({class:"embed bulb-streaming"},rn({class:"bulb-streaming-head"},Ir("\u{1F4A1} "),Ir({class:"shimmer-text shimmer-slow"},`${d?`${d} \u2014 `:""}writing\u2026`),Ir({class:"bulb-streaming-count"},`${p} lines`)),rn({class:["bulb-code","md"],key:`bulb-code-${s.length}`,...this.#k(a,b=>{b.innerHTML=tD.render(EH(s))})})))}renderTurn(s,a,d){let p=s.filter(D=>D.role==="user"||D.role==="fork"||D.text||D.body),b=p.find(D=>D.role==="assistant"&&(!!D.text||!!D.body)),v=[...p].reverse().find(D=>D.role==="assistant"&&(!!D.text||!!D.body)),w=[...s].reverse().find(D=>D.role==="assistant"),I=(v??w)?.turnView;if(!I)return this.#_(s,a);let T=this.#x(s,I,d);return I.raw(d)?this.#M(s,a,T,I,d):I.summary?this.#B(a,p,b,I,d):this.#D(s,a,p,T,v,I,d)}#x(s,a,d){let p=s.filter(b=>b.role==="assistant");return a.raw(d)?p[0]:p.find(b=>!!b.text||!!b.body)}#_(s,a){return s.map(d=>d.role==="fork"?this.forkStub(d,a):this.bubble(d,a))}#M(s,a,d,p,b){return s.map(v=>v.role==="fork"?this.forkStub(v,a):this.bubble(v,a,void 0,!0,v===d?p:void 0,!0,b))}#D(s,a,d,p,b,v,w){let I=d.flatMap(T=>{if(T.role==="fork")return[this.forkStub(T,a)];let D=T.role==="user"?T.copy:T===b?T.turnCopy:void 0;return[this.bubble(T,a,D??null,!0,T===p?v:void 0,!1,w)]});return p||w||I.splice(d[0]?.role==="user"?1:0,0,this.#L(s,a,v)),I}#B(s,a,d,p,b){return a.flatMap(v=>{if(v.role==="fork")return[this.forkStub(v,s)];if(v.role==="assistant")return v===d?[this.#R(v,s,p.summary,p)]:[];let w=v.role==="user"?v.copy:void 0;return[this.bubble(v,s,w??null,!0,void 0,!1,b)]})}#L(s,a,d){return rn({class:["bubble","assistant",bC(a)],key:`no-prose-${a}`},d.view(!1),rn({class:"no-prose"},Uvn(s)))}#N(s,a,d,p,b,v){let w=d.has(p);return rn({class:["bubble","assistant",bC(a)],key:s},rn({class:"turn-summary",onClick:()=>{Vxe(d,p),this.update()}},Xxe(w),Ir({class:"turn-summary-text"},b)),v??null)}forkStub(s,a){let d=s.fork,p=this.expandedForks.has(s.id)?rn({class:"fork-body"},d.sub.map(v=>this.bubble(v,a,void 0,!1))):void 0,b=[Hvn(),` ${d.count} message${d.count===1?"":"s"} on an abandoned branch`];return this.#N(`fork-${s.id}`,a,this.expandedForks,s.id,b,p)}bubble(s,a,d=s.copy,p=!0,b,v=!0,w=!1){let I=s.role==="assistant"&&!s.text&&!s.thinking&&s.tools.length>0;return rn({class:["bubble",s.role,I?"tools-only":"",p?bC(a):""],key:s.id},b?b.view(w):null,v&&s.thinking?jye({class:"thinking"},Fye("thinking"),r6(s.thinking)):null,this.#j(s),s.role==="user"?this.#O(s):null,v?s.tools.map(T=>this.tool(T)):null,this.#E(d))}#E(s){return s?rn({class:"bubble-controls"},s.view()):null}#R(s,a,d,p){return rn({class:["bubble","assistant",bC(a)],key:`summary-${s.id}`},p.view(!1),this.#g(`md-summary-${s.id}-${d.length}`,nD(d)),this.#E(p.copy))}#O(s){let d=[...s.text.matchAll(Ovn)].map(p=>p[1]).map(p=>this.#P(p)).filter(p=>!!p);return d.length?rn({class:"paste-thumbs"},d.map(p=>zee({class:"paste-thumb",src:p,alt:"pasted image"}))):null}#P(s){let a=this.#c.get(s);if(!(a==="pending"||a==="failed")){if(a)return a;this.#c.set(s,"pending"),(async()=>{try{let d=await tb.server.composerPasteRead(s);this.#c.set(s,d?.ok?`data:${d.mime};base64,${d.base64}`:"failed"),d?.ok&&(this.update(),this.scrollSoon())}catch{this.#c.set(s,"failed")}})()}}#j(s){return s.body?s.body.flatMap((a,d)=>typeof a=="string"?a.trim()?[this.#g(`md-${s.id}-${d}`,nD(a))]:[]:this.#F(a)):s.text?this.#g(`md-${s.id}`,s.role==="user"?zxe(s):nD(s.text)):null}#F(s){if(!this.#t.has(s))return[s.view()];let a=this.expandedInlineBulbs.has(s.key),d=rn({class:"md",key:`fold-${s.key}`},rn({class:"bulb-fold",onClick:()=>this.#m(s.key)},Xxe(a),Ir({class:"bulb-fold-text"},`${s.name??"bulb"} \u2014 Version ${s.chainPosition}`),Ir({class:"bulb-fold-app"},"\u{1F4A1}")));return a?[d,s.view()]:[d]}#g(s,a){return rn({class:"md",key:s,onMounted:a})}tool(s){let a=this.openTools.has(s.id),d=qvn(s.input),p=OSt(s),b=d?g6t(d,this.parent.cwd):$vn(Fvn(s.input));return rn({class:["tool",s.isError?"err":""]},rn({class:"tool-head"},rn({class:"tool-label"},Ir({class:"tool-name",...s.name.startsWith("mcp__")?{title:s.name}:{}},Zre(s.name)),b?d?gC({class:"tool-sum link",title:d,onClick:v=>{v.preventDefault(),tb.server.openFile(d)}},b):Ir({class:"tool-sum"},b):null),s.result===void 0?Ir({class:"tool-run"},"\u2026"):null),s.result!==void 0?rn({class:["tool-digest",a?"open":""],onClick:()=>{Vxe(this.openTools,s.id),this.update()}},Xxe(a),(p?Jvn(p):s.digest)||"(no output)"):null,a?rn({class:"tool-card"},this.toolBody(s),s.result!==void 0&&(s.isError||!(p||RSt(s).length&&s.result.trim()===s.digest))?r6({class:"tool-out"},s.result.slice(0,4e3)):null):null)}toolBody(s){let a=OSt(s);if(a)return rn({class:"todo-list"},a.map(b=>rn({class:["todo",b.status??""]},Ir({class:"todo-icon"},b.status==="completed"?"\u2714":b.status==="in_progress"?"\u25FC":"\u25FB"),Ir({class:"todo-text"},b.content??""))));let d=RSt(s);if(d.length)return rn({class:"tool-in"},d.map(NSt));let p=Qvn(s);if(!p){let b=Object.entries(s.input??{});return b.length?rn({class:"tool-in"},b.map(([v,w])=>rn({class:"tool-field"},Ir({class:"tool-key"},`${v}:`),typeof w=="string"&&PSt(w)?NSt(w):r6({class:"tool-val"},typeof w=="string"?w:JSON.stringify(w,null,2))))):null}return rn({class:"diff"},...p.flatMap((b,v)=>[p.length>1?rn({class:"diff-step"},`edit ${v+1}/${p.length}`):null,b.old?r6({class:"diff-old"},String(b.old)):null,b.new?r6({class:"diff-new"},String(b.new)):null]))}};var tie=class extends Ku{ready=!1;cwd="";sessionId=null;sessionPicker=new zre;tokenPill=new Kre;bulbsPill=new Wre;diffPill=new Xre;messageList=new eie;tokens={in:0,out:0,cached:0,cacheCreate:0};cost=0;stats=null;working=!1;latestModel=null;driverModel=null;busy=[];ownPid=0;pills;composer;draft=null;echo=null;#e=0;#n=!1;#t=!1;#r;#i=null;#s;#o;constructor(s){super(),this.pills=s.pills,this.composer=s.composer,this.#r=s.title,this.#s=s.overlays??[],this.#o=s.onPollTick}onAttached(){this.#t||(this.#t=!0,this.init())}closePopups(s){this.sessionPicker!==s&&this.sessionPicker.close(),this.bulbsPill!==s&&this.bulbsPill.close(),this.diffPill!==s&&this.diffPill.close();for(let a of this.pills)a!==s&&a.close?.()}async init(){let s=await tb.server.info();this.cwd=s.cwd,this.ownPid=s.pid??0,this.#i=s.elsewhere??null,this.composer&&(this.composer.enabled=!!s.composer),this.ready=!0,this.updateTitle(),this.update(),this.pump()}updateTitle(){let s=Hye(this.cwd),a=this.sessionPicker.currentPreview(),d=Vee(a,40);document.title=d&&s?`${d} \u2014 ${s}`:d||(s?`${this.#r} \u2014 ${s}`:this.#r)}refreshSessions(){this.sessionPicker.loadSessions().then(()=>this.update()).catch(()=>{})}pump(){if(this.#n)return;this.#n=!0;let s=async()=>{try{let{events:a,cursor:d,working:p,latestModel:b,composer:v,busy:w}=await tb.server.poll(this.#e);this.#e=d;for(let F of a)this.apply(F);let I=p!==this.working;this.working=p;let T=Array.isArray(w)?w:[],D=T.join(`
|
|
1938
1938
|
`)!==this.busy.join(`
|
|
1939
1939
|
`);this.busy=T;let B=b!==this.latestModel;this.latestModel=b??null;let P=this.composer&&v?this.composer.syncFromPoll(v):!1;(a.length||I||B||P||D)&&this.update(),(a.length||P)&&this.messageList.scrollSoon(),this.#o?.()}catch(a){console.error("[mirror] poll failed",a)}setTimeout(s,600)};s()}apply(s){switch(s.type){case"cleared":this.messageList.clear(),this.tokens={in:0,out:0,cached:0,cacheCreate:0},this.cost=0;break;case"session":this.sessionId=s.sessionId,s.sessionId&&!this.sessionPicker.currentRow()?this.refreshSessions():this.updateTitle();break;case"user":this.messageList.applyUser(s);break;case"assistant":this.messageList.applyAssistant(s);break;case"tool_result":this.messageList.applyToolResult(s);break;case"fork":this.messageList.applyFork(s);break;case"usage":this.tokens={in:s.in,out:s.out,cached:s.cached,cacheCreate:s.cacheCreate},this.cost+=s.cost??0;break}}view(){return rn({class:"app"},rn({class:"chat"},this.diffPill.viewing?this.diffPill.docView():this.messageList.view(),this.#c(),...this.#s.map(s=>s()),this.statusbar()),this.composer?.enabled?this.composer.view():null)}#c(){let s=this.#i;return!this.ready||this.sessionId!==null||!s?null:rn({class:"cwd-hint"},rn({class:"cwd-hint-head"},`No sessions for ${this.cwd}`),rn(`${s.count} session${s.count===1?"":"s"} exist for `,Ir({class:"cwd-hint-dir"},s.dir)," \u2014 this mirror was likely launched from a subfolder. Relaunch it from the project root."))}statusbar(){return rn({class:"statusbar"},rn({class:["statusbar-actions",this.diffPill.viewing?"doc-open":""]},this.diffPill.view(),...this.pills.map(s=>s.view()),this.tokenPill.view(),this.sessionPicker.view(),this.bulbsPill.view()))}};var nie=class extends Ku{get parent(){return this.ctx.parent}view(){let s=this.parent.latestModel;return s?Ir({class:"model-wrap"},Ir({class:"token",title:`Model: ${s}`},s)):Ir({class:"model-wrap"})}};document.title="Codex Mirror";new c6t({root:new tie({title:"Codex Mirror",pills:[new nie]}),id:"app"});
|
package/dist/agents/pi/client.js
CHANGED
|
@@ -1925,20 +1925,20 @@ ${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session
|
|
|
1925
1925
|
|
|
1926
1926
|
`+o,nEe=o=>nc({class:["turn-view",o.which===o.selected?"on":"",o.err?"err":""],title:o.title,onClick:s=>{s.stopPropagation(),o.onClick()}},o.shimmer?wr({class:"shimmer-text shimmer-slow"},o.label):o.label),_H=class extends wu{#e;copy=new uD("");#i="";#t="";#n="";#r=!1;#s=!1;#o="";#c=0;#u;constructor(s){super(),this.#u=s}setText(s,a=""){s===this.#i&&a===this.#t||(this.#i=s,this.#t=a,this.#c++,this.#f(RSt.get(OSt(s,a))??""),this.#s=!1,this.#o="",this.#e==="summary"&&(this.#e="reply"))}#f(s){this.#n=s,this.copy.setText(s)}#l(s){return this.#e??(s?"raw":"reply")}raw(s){return this.#l(s)==="raw"}get summary(){return this.#e==="summary"?this.#n:""}adoptLiveOverride(s){s&&(this.#e=s)}takeOverride(){let s=this.#e;return this.#e=void 0,s}reset(){this.#e=void 0}async#h(){let s=this.#i,a=this.#t,d=++this.#c,p=this.#e;this.#e="reply",this.#r=!0,this.#s=!1,this.#o="",this.#u();let b=()=>s===this.#i&&a===this.#t&&d===this.#c;try{let v=await tb.server.summarizeTurn(s,a);v?.ok?(RSt.set(OSt(s,a),v.text),b()&&(this.#f(v.text),this.#e="summary")):b()&&(this.#s=!!v?.setup,this.#o=v?.error??"could not summarize",this.#e=p)}catch{b()&&(this.#o="could not summarize",this.#e=p)}this.#r=!1,this.#u()}#a(s){if(s!=="summary"&&(this.#s=!1,this.#o=""),s==="summary"){if(this.#r)return;if(!this.#n)return void this.#h()}this.#c++,this.#e=s,this.#u()}view(s){let a=this.#l(s);return Qt({class:"turn-views-row"},nEe({which:"raw",selected:a,label:"Raw",title:"Show this turn\u2019s raw trace",onClick:()=>this.#a("raw")}),nEe({which:"reply",selected:a,label:"Reply",title:"Show this turn\u2019s exact reply",onClick:()=>this.#a("reply")}),!s&&this.#i.trim()?nEe({which:"summary",selected:a,label:"Summary",err:!!this.#o,title:this.#r?"Summarizing\u2026":this.#o||"Summarize this reply (one cheap model call)",shimmer:this.#r,onClick:()=>this.#a("summary")}):null,this.#s?this.#d():null)}#d(){let s=a=>{a.stopPropagation(),this.#s=!1,this.#o="",this.#u()};return Qt({class:"trust-back",onClick:s},Qt({class:"trust-modal summary-setup",onClick:a=>a.stopPropagation()},Qt({class:"trust-modal-h"},"Enable turn summaries"),Qt({class:"trust-modal-b"},"Summary makes one small model call to condense this reply. Add either key to .env in this project:"),Qt({class:"summary-setup-keys"},`OPENROUTER_API_KEY=\u2026
|
|
1927
1927
|
`,`or
|
|
1928
|
-
`,"OPENAI_API_KEY=\u2026"),Qt({class:"trust-modal-warn"},"Restart the mirror after saving .env, then Summary will work."),Qt({class:"trust-modal-acts"},nc({class:"trust-yes",type:"button",onClick:s},"OK"))))}};var nie=class extends wu{spread=!1;showingCode=!1;copied=!1;#e="";#i;#t;#n;#r;#s;#o;#c;#u=!1;#f=1;#l=!1;#h;#a="idle";constructor(s,a){super(),this.#i=s,this.#t=a,this.#n=SH(s);let d=Ske(s);this.#r=d.length?d.join(" "):void 0}get name(){return this.#n}get key(){return this.#t}setChainPosition(s){this.#f=s}get chainPosition(){return this.#f}setMounted(s){s!==this.#u&&(this.#u=s,this.#d())}onAttached(){this.#d()}#d(){if(this.#u){if(this.#s||this.#l||this.#o)return;this.#l=!0,this.#h=new AbortController,xSt(this.#i,{signal:this.#h.signal,onError:s=>{this.#c=s,this.#
|
|
1928
|
+
`,"OPENAI_API_KEY=\u2026"),Qt({class:"trust-modal-warn"},"Restart the mirror after saving .env, then Summary will work."),Qt({class:"trust-modal-acts"},nc({class:"trust-yes",type:"button",onClick:s},"OK"))))}};var nie=class extends wu{spread=!1;showingCode=!1;copied=!1;#e="";#i;#t;#n;#r;#s;#o;#c;#u=!1;#f=1;#l=!1;#h;#a="idle";constructor(s,a){super(),this.#i=s,this.#t=a,this.#n=SH(s);let d=Ske(s);this.#r=d.length?d.join(" "):void 0}get name(){return this.#n}get key(){return this.#t}setChainPosition(s){this.#f=s}get chainPosition(){return this.#f}setMounted(s){s!==this.#u&&(this.#u=s,this.#d())}onAttached(){this.#d()}#d(){if(this.#u){if(this.#s||this.#l||this.#o)return;this.#l=!0,this.#h=new AbortController,xSt(this.#i,{signal:this.#h.signal,onError:s=>{this.#c=s,this.#b("runtime",s),this.update()},onReady:()=>this.#b(this.#r?"malformed":"ok",this.#r)}).then(s=>{this.#l=!1,this.#u&&(this.#s=s,this.update())}).catch(s=>{this.#l=!1,this.#o=s instanceof Error?s.message:String(s),this.#b("compile",this.#o),this.update()})}else{if(!this.#s&&!this.#l)return;this.#h?.abort(),this.#h=void 0,this.#s=void 0,this.#c=void 0,this.update()}}#b(s,a){let d=this.#n??this.#t,p=s==="ok"?"ok":s==="malformed"?`malformed: ${a}`:`${s} error: ${a}`;tb.server.logInlineStatus(d,`[inline ${d} v${this.#f}] ${p}`).catch(()=>{})}dispose(){this.#h?.abort()}view(){let s=["embed","bulb-inline",this.spread?"spread":"fit",this.showingCode?"code-open":"",this.#o?"err":""],a=this.#n?`${this.#n} \u2014 `:"",d=this.#o?[`${a}could not render: ${this.#o}`]:this.#s?[this.#A(),Qt({class:"bulb-frame",key:"frame",onMounted:p=>{this.#s&&p.replaceChildren(this.#s)}}),this.showingCode?this.#m():null,this.#c?Qt({class:"bulb-err-strip",key:"err"},`\u26A0 ${a}${this.#c}`):null,this.#r?Qt({class:"bulb-warn-strip",key:"warn"},`\u26A0 ${a}malformed: ${this.#r}`):null]:["compiling bulb\u2026"];return Qt({class:"md",key:this.#t},Qt({class:s},...d))}#A(){let s=this.#a==="done"?this.#e:"breakout \u2197";return Qt({class:"bulb-controls",key:"controls"},this.#g("bulb-view",this.spread?"fit":"spread",this.spread?"Fit into the conversation column":"Spread to the full transcript width and height",()=>{this.spread=!this.spread,this.update()}),this.#g("bulb-toggle",this.showingCode?"run":"code",this.showingCode?"Back to the running bulb":"View this bulb's source",()=>{this.showingCode=!this.showingCode,this.update()}),this.#g(["bulb-copy",this.copied?"done":""],this.copied?"copied":"copy","Copy this bulb's full source",()=>this.#p()),nc({class:["overlay-pill","bulb-breakout",this.#a==="busy"?"launching shimmer":""],type:"button",disabled:this.#a!=="idle",title:"Save as a standalone .bulb.md and open it with typebulb",onClick:a=>{a.stopPropagation(),this.#v()}},s))}#g(s,a,d,p){let b=Array.isArray(s)?s:[s];return nc({class:["overlay-pill",...b],type:"button",title:d,onClick:v=>{v.stopPropagation(),p()}},a)}#p(){navigator.clipboard?.writeText(this.#i),this.copied=!0,this.update(),setTimeout(()=>{this.copied=!1,this.update()},1200)}async#v(){if(this.#a==="idle"){this.#a="busy",this.update();try{let{file:s,pid:a}=await tb.server.breakout(this.#i);this.#e=`launched ${s}`,window.dispatchEvent(new CustomEvent("tb-breakout",{detail:{pid:a}}))}catch(s){this.#e="breakout failed",console.error("[mirror] breakout failed",s)}this.#a="done",this.update(),setTimeout(()=>{this.#a="idle",this.update()},2500)}}#m(){return Qt({class:["bulb-code","md"],key:"code",tabIndex:0,onKeyDown:s=>{if(!((s.ctrlKey||s.metaKey)&&(s.key==="a"||s.key==="A")))return;s.preventDefault();let a=getSelection();if(!a)return;let d=document.createRange();d.selectNodeContents(s.currentTarget),a.removeAllRanges(),a.addRange(d)},onMounted:s=>{s.innerHTML=iD.render(TH(this.#i))}})}};function PSt(o){return o.map((s,a)=>!!s&&o[a+1]===s)}function jSt(o){let s=[];for(let a=0;a<o.length;a++)s[a]=a>0&&o[a]&&o[a]===o[a-1]?s[a-1]+1:1;return s}var FSt=".typebulb/paste",$St={png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",webp:"image/webp",svg:"image/svg+xml",bmp:"image/bmp"};var zvn=new RegExp(`@${FSt.replace(/\./g,"\\.")}/([\\w-]+(?:\\.[\\w-]+)*\\.(?:${Object.keys($St).join("|")}))`,"gi"),Kvn=new URL("typebulb.png",import.meta.url).href,Wvn=new URL("typebulb-inv.png",import.meta.url).href;function Yvn(o){return!o||typeof o!="object"?"":X1(o.command)??X1(o.file_path)??X1(o.filePath)??X1(o.path)??X1(o.pattern)??X1(o.query)??X1(o.url)??X1(o.skill)??X1(o.description)??""}function Xvn(o){let s=o.indexOf(`
|
|
1929
1929
|
`);return s===-1?o:o.slice(0,s).trimEnd()+" \u2026"}var rEe=o=>Y0("caret",["caret-tri",o?"open":""]),Vvn=()=>Y0("fork","fork-icon");function GSt(o){return/^@@/m.test(o)&&/^[+-]/m.test(o)}function HSt(o){let s=[],a=!1;for(let d of o.split(`
|
|
1930
|
-
`))d.startsWith("@@")?(a&&s.push(Qt({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(Qt({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return Qt({class:"udiff"},s)}var Zvn=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function e5n(o){if(!(!o||typeof o!="object"))return(X1(o.file_path)??X1(o.filePath)??X1(o.path))||void 0}function t5n(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:X1(s.old_string),new:X1(s.new_string)}];case"Write":return[{new:X1(s.content)}];case"NotebookEdit":return[{new:X1(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function rie(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function qSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&GSt(s))}function QSt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function n5n(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function iEe(o,s){o.has(s)?o.delete(s):o.add(s)}function r5n(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(rie(b.name),(s.get(rie(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var iie=class extends wu{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new _H(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#i=0;#t=new Set;#n=!0;#r=new Map;#s=0;#o
|
|
1930
|
+
`))d.startsWith("@@")?(a&&s.push(Qt({class:"udiff-gap"},"\u22EF")),a=!0):/^[+-]/.test(d)&&!d.startsWith("+++")&&!d.startsWith("---")&&s.push(Qt({class:["udiff-line",d.startsWith("+")?"udiff-add":"udiff-del"]},d.slice(1)));return Qt({class:"udiff"},s)}var Zvn=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function e5n(o){if(!(!o||typeof o!="object"))return(X1(o.file_path)??X1(o.filePath)??X1(o.path))||void 0}function t5n(o){let s=o.input??{};switch(o.name){case"Edit":return[{old:X1(s.old_string),new:X1(s.new_string)}];case"Write":return[{new:X1(s.content)}];case"NotebookEdit":return[{new:X1(s.new_source)}];case"MultiEdit":return Array.isArray(s.edits)?s.edits.map(a=>({old:a?.old_string,new:a?.new_string})):void 0;default:return}}function rie(o){let s=/^mcp__(.+?)__(.+)$/.exec(o);return s?`${s[1][0].toUpperCase()}${s[1].slice(1)} [${s[2]}]`:o}function qSt(o){return Object.values(o.input??{}).filter(s=>typeof s=="string"&&GSt(s))}function QSt(o){return o.name==="TodoWrite"&&Array.isArray(o.input?.todos)?o.input.todos:void 0}function n5n(o){let s=o.filter(d=>d.status==="completed").length,a=o.find(d=>d.status==="in_progress");return`${s}/${o.length} done${a?` \xB7 \u25FC ${a.activeForm??a.content??""}`:""}`}function iEe(o,s){o.has(s)?o.delete(s):o.add(s)}function r5n(o){let s=new Map;for(let p of o)for(let b of p.tools)s.set(rie(b.name),(s.get(rie(b.name))??0)+1);let a=[...s.values()].reduce((p,b)=>p+b,0);if(!a)return"no reply text";let d=[...s].map(([p,b])=>b>1?`${p} \xD7${b}`:p).join(", ");return`no reply text \xB7 ${a} step${a===1?"":"s"} \xB7 ${d}`}var iie=class extends wu{messages=[];openTools=new Set;expandedForks=new Set;expandedInlineBulbs=new Set;copyButtons=[];turnViews=[];liveTurnView=new _H(()=>this.update());inlineBulbs=[];scrollEl;#e=0;#i=0;#t=new Set;#n=!0;#r=new Map;#s=0;#o;#c=new Map;get parent(){return this.ctx.parent}clear(){for(let s of this.inlineBulbs)s.dispose();this.messages=[],this.expandedForks.clear(),this.expandedInlineBulbs.clear(),this.#c.clear(),this.#t=new Set,this.copyButtons=[],this.turnViews=[],this.liveTurnView.reset(),this.inlineBulbs=[]}#u(s){let a=new uD(s);return this.copyButtons.push(a),a}#f(){let s=new _H(()=>this.update());return this.turnViews.push(s),s}#l(s){let a={...s,copy:s.text?this.#u(s.text):void 0};return this.messages.push(a),a}#h(){let s=[];for(let a=this.messages.length-1;a>=0;a--){let d=this.messages[a];if(d.role==="user")return{prose:s.join(`
|
|
1931
1931
|
|
|
1932
1932
|
`),user:d.text};d.text&&s.unshift(d.text)}return{prose:s.join(`
|
|
1933
1933
|
|
|
1934
1934
|
`),user:""}}stickToBottomNextRender(){this.#n=!0}#a(s,a){s.segments=[...s.segments??[s.text],a],s.text=s.segments.join(`
|
|
1935
1935
|
|
|
1936
|
-
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#
|
|
1937
|
-
`).length;return Qt({class:"md",key:`draft-bulb-${a}`},Qt({class:"embed bulb-streaming"},Qt({class:"bulb-streaming-head"},wr("\u{1F4A1} "),wr({class:"shimmer-text shimmer-slow"},`${d?`${d} \u2014 `:""}writing\u2026`),wr({class:"bulb-streaming-count"},`${p} lines`)),Qt({class:["bulb-code","md"],key:`bulb-code-${s.length}`,...this.#
|
|
1936
|
+
`)}applyUser(s){let a=this.messages[this.messages.length-1];if(a&&a.role==="user"){this.#a(a,s.text),a.copy?a.copy.setText(a.text):a.text&&(a.copy=this.#u(a.text));return}this.#l({id:++this.#e,role:"user",text:s.text,thinking:"",tools:[]})}applyAssistant(s){let a=this.messages[this.messages.length-1]?.role!=="assistant",d=this.#l({id:++this.#e,role:"assistant",text:s.text,thinking:s.thinking,tools:s.tools.map(v=>({...v,isError:!1}))}),p=this.messages[this.messages.length-2],b=this.#h();if(d.turnCopy=p?.role==="assistant"&&p.turnCopy||this.#u(""),d.turnCopy.setText(b.prose),d.turnView=p?.role==="assistant"&&p.turnView||this.#f(),a&&d.turnView.adoptLiveOverride(this.liveTurnView.takeOverride()),d.turnView.setText(b.prose,b.user),this.#d(d,s.text),this.#b(),s.live)for(let v of s.tools)Zvn.has(v.name)&&this.openTools.add(v.id)}#d(s,a){let d=eEe(a);d.some(p=>p.kind==="bulb")&&(s.body=d.map(p=>{if(p.kind==="md")return p.text;let b=new nie(p.source,`inline-${this.#i++}`);return this.inlineBulbs.push(b),b}))}#b(){let s=this.inlineBulbs.map(p=>p.name),a=PSt(s),d=jSt(s);this.#t=new Set(this.inlineBulbs.filter((p,b)=>a[b])),this.inlineBulbs.forEach((p,b)=>{p.setChainPosition(d[b]),p.setMounted(!a[b]||this.expandedInlineBulbs.has(p.key))})}#A(s){iEe(this.expandedInlineBulbs,s),this.#b(),this.update()}applyToolResult(s){let a=this.#p(s.id);a&&(a.result=s.content,a.isError=s.isError,a.digest=s.digest)}applyFork(s){let a=this.#g(s.events);this.#l({id:++this.#e,role:"fork",text:"",thinking:"",tools:[],fork:{count:s.count,sub:a}})}#g(s){let a=[];for(let d of s)if(d.type==="user"){let p=a[a.length-1];p&&p.role==="user"?this.#a(p,d.text):a.push({id:++this.#e,role:"user",text:d.text,thinking:"",tools:[]})}else if(d.type==="assistant")a.push({id:++this.#e,role:"assistant",text:d.text,thinking:d.thinking,tools:d.tools.map(p=>({...p,isError:!1}))});else if(d.type==="tool_result"){let p=a.flatMap(b=>b.tools).find(b=>b.id===d.id);p&&(p.result=d.content,p.isError=d.isError,p.digest=d.digest)}return a}#p(s){return this.messages.flatMap(a=>a.tools).find(a=>a.id===s)}scrollSoon(){requestAnimationFrame(()=>{this.scrollEl&&this.#n&&(this.scrollEl.scrollTop=this.scrollEl.scrollHeight)})}onScroll(){let s=this.scrollEl;s&&(this.#n=DF(s,50))}view(){return Qt({class:"messages",onScroll:()=>this.onScroll(),onMounted:s=>{this.scrollEl=s}},this.parent.ready?this.renderMessages():Qt({class:"note"},"Connecting\u2026"))}renderMessages(){let s=[],a=-1;for(let D of this.messages)D.role==="user"||s.length===0?(D.role==="user"&&a++,s.push({idx:Math.max(0,a),msgs:[D]})):s[s.length-1].msgs.push(D);let d=this.parent.echo,p=this.parent.draft,b=this.parent.working&&!d,v=s.flatMap((D,P)=>this.renderTurn(D.msgs,D.idx,b&&P===s.length-1));v.unshift(this.#m());let w=d?a+1:Math.max(0,a),I=b?s[s.length-1]?.msgs??[]:[],T=[...I].reverse().find(D=>D.role==="assistant")?.turnView,B=!!T&&!!this.#S(I,T,!0);return d&&v.push(this.#k(d,w)),p?v.push(this.#y(p,w,T,!B)):(this.#r.clear(),this.#o=void 0,this.parent.working?v.push(this.#y({text:"",thinking:"",tool:this.#v()},w,T,!B)):this.liveTurnView.reset()),v}#v(){for(let s=this.messages.length-1;s>=0;s--){let a=this.messages[s];if(a.role==="assistant")return a.tools.find(d=>d.result===void 0)?.name}}#m(){return Qt({class:"masthead",key:"masthead"},Xee({class:"masthead-logo light",src:Kvn,alt:"typebulb"}),Xee({class:"masthead-logo dark",src:Wvn,alt:"typebulb"}),Qt({class:"masthead-tagline"},"a live mirror of your agent\u2019s session, with inline bulbs, latex, svg, mermaid and more"))}#k(s,a){return Qt({class:["bubble","user",mC(a)],key:`echo-${s.length}`},this.#w(`md-echo-${s.length}`,Zxe({id:-1,role:"user",text:s,thinking:"",tools:[]})))}#y(s,a,d,p=!0){let b=`draft-${s.text.length}-${s.thinking.length}`;s.text.length<this.#s&&this.#r.clear(),this.#s=s.text.length;let v=d??this.liveTurnView,w=v.raw(!0),I=w&&!!s.thinking,T=w?s.tool:void 0,B=!s.text.trim()&&!T,D=w&&(T?`${rie(T)}\u2026`:s.text.trim()||I?null:"working\u2026");return Qt({class:["bubble","assistant","draft",mC(a)],key:b},p?v.view(!0):null,I?Qye({class:"thinking",open:this.#o??!0,onToggle:P=>{this.#o=P.currentTarget.open}},Gye(B?wr({class:"shimmer-text shimmer-slow"},"thinking\u2026"):"thinking"),this.#C(s.thinking)):null,s.text.trim()?this.#x(b,s.text):null,D?Qt({class:"draft-wait shimmer-text shimmer-slow"},D):null)}#x(s,a){let d=eEe(a);return d.some(p=>p.kind==="bulb")?d.map((p,b)=>p.kind==="md"?p.text.trim()?this.#w(`${s}-md-${b}`,sD(p.text)):null:this.#I(p.source,b)):this.#w(s,sD(a))}#E(s,a){return{onScroll:d=>{let p=d.currentTarget;this.#r.set(s,{top:p.scrollTop,stuck:DF(p,50)})},onMounted:d=>{a?.(d);let p=this.#r.get(s);d.scrollTop=p&&!p.stuck?p.top:d.scrollHeight}}}#C(s){return i6({key:`think-${s.length}`,...this.#E(-1)},s)}#I(s,a){let d=SH(s),p=s.split(`
|
|
1937
|
+
`).length;return Qt({class:"md",key:`draft-bulb-${a}`},Qt({class:"embed bulb-streaming"},Qt({class:"bulb-streaming-head"},wr("\u{1F4A1} "),wr({class:"shimmer-text shimmer-slow"},`${d?`${d} \u2014 `:""}writing\u2026`),wr({class:"bulb-streaming-count"},`${p} lines`)),Qt({class:["bulb-code","md"],key:`bulb-code-${s.length}`,...this.#E(a,b=>{b.innerHTML=iD.render(TH(s))})})))}renderTurn(s,a,d){let p=s.filter(B=>B.role==="user"||B.role==="fork"||B.text||B.body),b=p.find(B=>B.role==="assistant"&&(!!B.text||!!B.body)),v=[...p].reverse().find(B=>B.role==="assistant"&&(!!B.text||!!B.body)),w=[...s].reverse().find(B=>B.role==="assistant"),I=(v??w)?.turnView;if(!I)return this.#_(s,a);let T=this.#S(s,I,d);return I.raw(d)?this.#M(s,a,T,I,d):I.summary?this.#B(a,p,b,I,d):this.#D(s,a,p,T,v,I,d)}#S(s,a,d){let p=s.filter(b=>b.role==="assistant");return a.raw(d)?p[0]:p.find(b=>!!b.text||!!b.body)}#_(s,a){return s.map(d=>d.role==="fork"?this.forkStub(d,a):this.bubble(d,a))}#M(s,a,d,p,b){return s.map(v=>v.role==="fork"?this.forkStub(v,a):this.bubble(v,a,void 0,!0,v===d?p:void 0,!0,b))}#D(s,a,d,p,b,v,w){let I=d.flatMap(T=>{if(T.role==="fork")return[this.forkStub(T,a)];let B=T.role==="user"?T.copy:T===b?T.turnCopy:void 0;return[this.bubble(T,a,B??null,!0,T===p?v:void 0,!1,w)]});return p||w||I.splice(d[0]?.role==="user"?1:0,0,this.#L(s,a,v)),I}#B(s,a,d,p,b){return a.flatMap(v=>{if(v.role==="fork")return[this.forkStub(v,s)];if(v.role==="assistant")return v===d?[this.#R(v,s,p.summary,p)]:[];let w=v.role==="user"?v.copy:void 0;return[this.bubble(v,s,w??null,!0,void 0,!1,b)]})}#L(s,a,d){return Qt({class:["bubble","assistant",mC(a)],key:`no-prose-${a}`},d.view(!1),Qt({class:"no-prose"},r5n(s)))}#N(s,a,d,p,b,v){let w=d.has(p);return Qt({class:["bubble","assistant",mC(a)],key:s},Qt({class:"turn-summary",onClick:()=>{iEe(d,p),this.update()}},rEe(w),wr({class:"turn-summary-text"},b)),v??null)}forkStub(s,a){let d=s.fork,p=this.expandedForks.has(s.id)?Qt({class:"fork-body"},d.sub.map(v=>this.bubble(v,a,void 0,!1))):void 0,b=[Vvn(),` ${d.count} message${d.count===1?"":"s"} on an abandoned branch`];return this.#N(`fork-${s.id}`,a,this.expandedForks,s.id,b,p)}bubble(s,a,d=s.copy,p=!0,b,v=!0,w=!1){let I=s.role==="assistant"&&!s.text&&!s.thinking&&s.tools.length>0;return Qt({class:["bubble",s.role,I?"tools-only":"",p?mC(a):""],key:s.id},b?b.view(w):null,v&&s.thinking?Qye({class:"thinking"},Gye("thinking"),i6(s.thinking)):null,this.#j(s),s.role==="user"?this.#O(s):null,v?s.tools.map(T=>this.tool(T)):null,this.#T(d))}#T(s){return s?Qt({class:"bubble-controls"},s.view()):null}#R(s,a,d,p){return Qt({class:["bubble","assistant",mC(a)],key:`summary-${s.id}`},p.view(!1),this.#w(`md-summary-${s.id}-${d.length}`,sD(d)),this.#T(p.copy))}#O(s){let d=[...s.text.matchAll(zvn)].map(p=>p[1]).map(p=>this.#P(p)).filter(p=>!!p);return d.length?Qt({class:"paste-thumbs"},d.map(p=>Xee({class:"paste-thumb",src:p,alt:"pasted image"}))):null}#P(s){let a=this.#c.get(s);if(!(a==="pending"||a==="failed")){if(a)return a;this.#c.set(s,"pending"),(async()=>{try{let d=await tb.server.composerPasteRead(s);this.#c.set(s,d?.ok?`data:${d.mime};base64,${d.base64}`:"failed"),d?.ok&&(this.update(),this.scrollSoon())}catch{this.#c.set(s,"failed")}})()}}#j(s){return s.body?s.body.flatMap((a,d)=>typeof a=="string"?a.trim()?[this.#w(`md-${s.id}-${d}`,sD(a))]:[]:this.#F(a)):s.text?this.#w(`md-${s.id}`,s.role==="user"?Zxe(s):sD(s.text)):null}#F(s){if(!this.#t.has(s))return[s.view()];let a=this.expandedInlineBulbs.has(s.key),d=Qt({class:"md",key:`fold-${s.key}`},Qt({class:"bulb-fold",onClick:()=>this.#A(s.key)},rEe(a),wr({class:"bulb-fold-text"},`${s.name??"bulb"} \u2014 Version ${s.chainPosition}`),wr({class:"bulb-fold-app"},"\u{1F4A1}")));return a?[d,s.view()]:[d]}#w(s,a){return Qt({class:"md",key:s,onMounted:a})}tool(s){let a=this.openTools.has(s.id),d=e5n(s.input),p=QSt(s),b=d?k6t(d,this.parent.cwd):Xvn(Yvn(s.input));return Qt({class:["tool",s.isError?"err":""]},Qt({class:"tool-head"},Qt({class:"tool-label"},wr({class:"tool-name",...s.name.startsWith("mcp__")?{title:s.name}:{}},rie(s.name)),b?d?bC({class:"tool-sum link",title:d,onClick:v=>{v.preventDefault(),tb.server.openFile(d)}},b):wr({class:"tool-sum"},b):null),s.result===void 0?wr({class:"tool-run"},"\u2026"):null),s.result!==void 0?Qt({class:["tool-digest",a?"open":""],onClick:()=>{iEe(this.openTools,s.id),this.update()}},rEe(a),(p?n5n(p):s.digest)||"(no output)"):null,a?Qt({class:"tool-card"},this.toolBody(s),s.result!==void 0&&(s.isError||!(p||qSt(s).length&&s.result.trim()===s.digest))?i6({class:"tool-out"},s.result.slice(0,4e3)):null):null)}toolBody(s){let a=QSt(s);if(a)return Qt({class:"todo-list"},a.map(b=>Qt({class:["todo",b.status??""]},wr({class:"todo-icon"},b.status==="completed"?"\u2714":b.status==="in_progress"?"\u25FC":"\u25FB"),wr({class:"todo-text"},b.content??""))));let d=qSt(s);if(d.length)return Qt({class:"tool-in"},d.map(HSt));let p=t5n(s);if(!p){let b=Object.entries(s.input??{});return b.length?Qt({class:"tool-in"},b.map(([v,w])=>Qt({class:"tool-field"},wr({class:"tool-key"},`${v}:`),typeof w=="string"&&GSt(w)?HSt(w):i6({class:"tool-val"},typeof w=="string"?w:JSON.stringify(w,null,2))))):null}return Qt({class:"diff"},...p.flatMap((b,v)=>[p.length>1?Qt({class:"diff-step"},`edit ${v+1}/${p.length}`):null,b.old?i6({class:"diff-old"},String(b.old)):null,b.new?i6({class:"diff-new"},String(b.new)):null]))}};var sie=class extends wu{ready=!1;cwd="";sessionId=null;sessionPicker=new Xre;tokenPill=new Vre;bulbsPill=new Zre;diffPill=new tie;messageList=new iie;tokens={in:0,out:0,cached:0,cacheCreate:0};cost=0;stats=null;working=!1;latestModel=null;driverModel=null;busy=[];ownPid=0;pills;composer;draft=null;echo=null;#e=0;#i=!1;#t=!1;#n;#r=null;#s;#o;constructor(s){super(),this.pills=s.pills,this.composer=s.composer,this.#n=s.title,this.#s=s.overlays??[],this.#o=s.onPollTick}onAttached(){this.#t||(this.#t=!0,this.init())}closePopups(s){this.sessionPicker!==s&&this.sessionPicker.close(),this.bulbsPill!==s&&this.bulbsPill.close(),this.diffPill!==s&&this.diffPill.close();for(let a of this.pills)a!==s&&a.close?.()}async init(){let s=await tb.server.info();this.cwd=s.cwd,this.ownPid=s.pid??0,this.#r=s.elsewhere??null,this.composer&&(this.composer.enabled=!!s.composer),this.ready=!0,this.updateTitle(),this.update(),this.pump()}updateTitle(){let s=zye(this.cwd),a=this.sessionPicker.currentPreview(),d=hM(a,40);document.title=d&&s?`${d} \u2014 ${s}`:d||(s?`${this.#n} \u2014 ${s}`:this.#n)}refreshSessions(){this.sessionPicker.loadSessions().then(()=>this.update()).catch(()=>{})}pump(){if(this.#i)return;this.#i=!0;let s=async()=>{try{let{events:a,cursor:d,working:p,latestModel:b,composer:v,busy:w}=await tb.server.poll(this.#e);this.#e=d;for(let F of a)this.apply(F);let I=p!==this.working;this.working=p;let T=Array.isArray(w)?w:[],B=T.join(`
|
|
1938
1938
|
`)!==this.busy.join(`
|
|
1939
|
-
`);this.busy=T;let D=b!==this.latestModel;this.latestModel=b??null;let P=this.composer&&v?this.composer.syncFromPoll(v):!1;(a.length||I||D||P||B)&&this.update(),(a.length||P)&&this.messageList.scrollSoon(),this.#o?.()}catch(a){console.error("[mirror] poll failed",a)}setTimeout(s,600)};s()}apply(s){switch(s.type){case"cleared":this.messageList.clear(),this.tokens={in:0,out:0,cached:0,cacheCreate:0},this.cost=0;break;case"session":this.sessionId=s.sessionId,s.sessionId&&!this.sessionPicker.currentRow()?this.refreshSessions():this.updateTitle();break;case"user":this.messageList.applyUser(s);break;case"assistant":this.messageList.applyAssistant(s);break;case"tool_result":this.messageList.applyToolResult(s);break;case"fork":this.messageList.applyFork(s);break;case"usage":this.tokens={in:s.in,out:s.out,cached:s.cached,cacheCreate:s.cacheCreate},this.cost+=s.cost??0;break}}view(){return Qt({class:"app"},Qt({class:"chat"},this.diffPill.viewing?this.diffPill.docView():this.messageList.view(),this.#c(),...this.#s.map(s=>s()),this.statusbar()),this.composer?.enabled?this.composer.view():null)}#c(){let s=this.#r;return!this.ready||this.sessionId!==null||!s?null:Qt({class:"cwd-hint"},Qt({class:"cwd-hint-head"},`No sessions for ${this.cwd}`),Qt(`${s.count} session${s.count===1?"":"s"} exist for `,wr({class:"cwd-hint-dir"},s.dir)," \u2014 this mirror was likely launched from a subfolder. Relaunch it from the project root."))}statusbar(){return Qt({class:"statusbar"},Qt({class:["statusbar-actions",this.diffPill.viewing?"doc-open":""]},this.diffPill.view(),...this.pills.map(s=>s.view()),this.tokenPill.view(),this.sessionPicker.view(),this.bulbsPill.view()))}};function sEe(o,s,a){let d=o.map(p=>({item:p,rank:s(p)})).filter(p=>p.rank>=0);return d.sort((p,b)=>p.rank-b.rank),(a?d.slice(0,a):d).map(p=>p.item)}var oie=class extends wu{enabled=!1;streaming=!1;driverError;sendError;input="";status=null;localNotice=null;dlg=null;dlgInput="";dlgFilter="";dlgIndex=0;queue=null;recipes;harnessCommands=[];slashQuery=null;slashIndex=0;composerHeight=90;files=[];atQuery=null;atIndex=0;atStart=0;#e=!1;#i=0;#t="";#n=null;constructor(s=[]){super(),this.recipes=s}get parent(){return this.ctx.parent}onAttached(){this.#r()}async#r(){try{let s=await tb.server.composerFiles();Array.isArray(s)&&(this.files=s,this.update())}catch{}}syncFromPoll(s){let a=s.streaming!==this.streaming||s.error!==this.driverError;this.streaming=s.streaming,this.driverError=s.error;let d=this.parent,p=s.draft??null;(p?.text!==d.draft?.text||p?.thinking!==d.draft?.thinking||p?.tool!==d.draft?.tool)&&(d.draft=p,a=!0);let b=s.echo??null;b!==d.echo&&(d.echo=b,a=!0);let v=s.stats??null;(v?.cost!==d.stats?.cost||v?.contextTokens!==d.stats?.contextTokens||v?.contextPercent!==d.stats?.contextPercent)&&(d.stats=v,a=!0);let w=s.model??null;w!==d.driverModel&&(d.driverModel=w,a=!0),this.localNotice&&Date.now()>=this.localNotice.until&&(this.localNotice=null,a=!0),((s.status?.text??null)!==(this.status?.text??null)||s.status?.kind!==this.status?.kind)&&(this.status=s.status??null,a=!0);let I=s.queue??null;this.#s(I)!==this.#s(this.queue)&&(this.queue=I,a=!0);let T=s.dialog??null;return this.dlg&&!this.dlg.local&&(!T||T.id!==this.dlg.req.id)&&(this.dlg=null,a=!0),T&&!this.dlg&&T.id!==this.#n&&(this.#
|
|
1939
|
+
`);this.busy=T;let D=b!==this.latestModel;this.latestModel=b??null;let P=this.composer&&v?this.composer.syncFromPoll(v):!1;(a.length||I||D||P||B)&&this.update(),(a.length||P)&&this.messageList.scrollSoon(),this.#o?.()}catch(a){console.error("[mirror] poll failed",a)}setTimeout(s,600)};s()}apply(s){switch(s.type){case"cleared":this.messageList.clear(),this.tokens={in:0,out:0,cached:0,cacheCreate:0},this.cost=0;break;case"session":this.sessionId=s.sessionId,s.sessionId&&!this.sessionPicker.currentRow()?this.refreshSessions():this.updateTitle();break;case"user":this.messageList.applyUser(s);break;case"assistant":this.messageList.applyAssistant(s);break;case"tool_result":this.messageList.applyToolResult(s);break;case"fork":this.messageList.applyFork(s);break;case"usage":this.tokens={in:s.in,out:s.out,cached:s.cached,cacheCreate:s.cacheCreate},this.cost+=s.cost??0;break}}view(){return Qt({class:"app"},Qt({class:"chat"},this.diffPill.viewing?this.diffPill.docView():this.messageList.view(),this.#c(),...this.#s.map(s=>s()),this.statusbar()),this.composer?.enabled?this.composer.view():null)}#c(){let s=this.#r;return!this.ready||this.sessionId!==null||!s?null:Qt({class:"cwd-hint"},Qt({class:"cwd-hint-head"},`No sessions for ${this.cwd}`),Qt(`${s.count} session${s.count===1?"":"s"} exist for `,wr({class:"cwd-hint-dir"},s.dir)," \u2014 this mirror was likely launched from a subfolder. Relaunch it from the project root."))}statusbar(){return Qt({class:"statusbar"},Qt({class:["statusbar-actions",this.diffPill.viewing?"doc-open":""]},this.diffPill.view(),...this.pills.map(s=>s.view()),this.tokenPill.view(),this.sessionPicker.view(),this.bulbsPill.view()))}};function sEe(o,s,a){let d=o.map(p=>({item:p,rank:s(p)})).filter(p=>p.rank>=0);return d.sort((p,b)=>p.rank-b.rank),(a?d.slice(0,a):d).map(p=>p.item)}var oie=class extends wu{enabled=!1;streaming=!1;foreign=!1;driverError;sendError;input="";status=null;localNotice=null;dlg=null;dlgInput="";dlgFilter="";dlgIndex=0;queue=null;recipes;harnessCommands=[];slashQuery=null;slashIndex=0;composerHeight=90;files=[];atQuery=null;atIndex=0;atStart=0;#e=!1;#i=0;#t="";#n=null;constructor(s=[]){super(),this.recipes=s}get parent(){return this.ctx.parent}onAttached(){this.#r()}async#r(){try{let s=await tb.server.composerFiles();Array.isArray(s)&&(this.files=s,this.update())}catch{}}syncFromPoll(s){let a=s.streaming!==this.streaming||s.foreign!==this.foreign||s.error!==this.driverError;this.streaming=s.streaming,this.foreign=s.foreign,this.driverError=s.error;let d=this.parent,p=s.draft??null;(p?.text!==d.draft?.text||p?.thinking!==d.draft?.thinking||p?.tool!==d.draft?.tool)&&(d.draft=p,a=!0);let b=s.echo??null;b!==d.echo&&(d.echo=b,a=!0);let v=s.stats??null;(v?.cost!==d.stats?.cost||v?.contextTokens!==d.stats?.contextTokens||v?.contextPercent!==d.stats?.contextPercent)&&(d.stats=v,a=!0);let w=s.model??null;w!==d.driverModel&&(d.driverModel=w,a=!0),this.localNotice&&Date.now()>=this.localNotice.until&&(this.localNotice=null,a=!0),((s.status?.text??null)!==(this.status?.text??null)||s.status?.kind!==this.status?.kind)&&(this.status=s.status??null,a=!0);let I=s.queue??null;this.#s(I)!==this.#s(this.queue)&&(this.queue=I,a=!0);let T=s.dialog??null;return this.dlg&&!this.dlg.local&&(!T||T.id!==this.dlg.req.id)&&(this.dlg=null,a=!0),T&&!this.dlg&&T.id!==this.#n&&(this.#f(T),a=!0),a}#s(s){return s?JSON.stringify(s):""}async send(s=!1){let a=this.input.trim();if(!(!a||this.#e||this.foreign)){if(a.startsWith("!"))return this.runBash(a.slice(1).trim());this.atQuery=null,await this.#o("send failed \u2014 mirror unreachable",async()=>{let d=await tb.server.composerSend(a,{followUp:s});d?.ok?(this.input="",this.streaming=!0):this.sendError=d?.error??"send failed"})}}async#o(s,a){this.#e=!0,this.sendError=void 0,this.update();try{await a()}catch{this.sendError=s}finally{this.#e=!1,this.update(),this.#p()}}async stopTurn(){let s=this.queue,a=s?[...s.steering,...s.followUp]:[];try{await tb.server.composerStop()}catch{}a.length&&(this.input=a.join(`
|
|
1940
1940
|
`)+(this.input?`
|
|
1941
|
-
`+this.input:""),this.queue=null,this.update(),this.#g())}async runBash(s){s&&await this.#c("bash failed \u2014 mirror unreachable",async()=>{let a=await tb.server.composerRpc({type:"bash",command:s},{spawn:!0});a?.ok?(this.input="",this.#p("ran \u2014 output joins context on the next message")):this.sendError=a?.error??"bash failed"})}onPaste(s){let a=[...s.clipboardData?.items??[]].find(p=>p.type.startsWith("image/"));if(!a)return;s.preventDefault();let d=a.getAsFile();d&&this.#u(d,d.type,s.target.selectionStart)}async captureClipboard(){let s=this.#m(),a=s?s.selectionStart:this.input.length;try{for(let d of await navigator.clipboard.read()){let p=d.types.find(b=>b.startsWith("image/"));if(p){this.#u(await d.getType(p),p,a);return}}}catch{}try{let d=(await navigator.clipboard.readText()).trim();if(!d){this.#p("clipboard is empty"),this.update();return}this.#f({kind:"text",data:d},a)}catch{this.sendError="clipboard unavailable",this.update()}}#u(s,a,d){let p=new FileReader;p.onload=()=>{let b=String(p.result??"");this.#f({kind:"image",data:b.slice(b.indexOf(",")+1),mime:a},d)},p.readAsDataURL(s)}async#f(s,a){let d=p=>{this.sendError=p,this.localNotice=null,this.update()};this.#p(s.kind==="image"?"saving image\u2026":"saving text\u2026"),this.update();try{let p=await tb.server.composerPaste(s);if(!p?.ok)return d(p?.error??"paste failed");let b=`@${p.path} `,v=Math.min(a,this.input.length);this.input=this.input.slice(0,v)+b+this.input.slice(v),this.localNotice=null,this.update(),this.#g(v+b.length)}catch{d("paste failed \u2014 mirror unreachable")}}#l(s){this.dlgInput=s.prefill??"",this.#a(s),this.dlg={req:s,local:!1,resolve:a=>{this.#n=s.id,tb.server.composerUiRespond(s.id,a)}}}#h(s){return new Promise(a=>{this.dlgInput=s.prefill??"",this.#a(s),this.dlg={req:{id:`local-${++this.#i}`,...s},local:!0,resolve:a},this.update()})}#a(s){this.dlgFilter="",this.#t="",this.dlgIndex=s.selected?Math.max(0,(s.options??[]).indexOf(s.selected)):0}#d=s=>s.focus();answerDialog(s){let a=this.dlg;a&&(this.dlg=null,a.resolve(s),this.update(),this.#g())}#p(s){this.localNotice={text:s,until:Date.now()+6e3}}#A(){return{rpc:s=>tb.server.composerRpc(s,{spawn:!0}),select:async(s,a,d)=>{let p=await this.#h({method:"select",title:s,options:a,selected:d});return p.cancelled?null:p.value??null},input:async(s,a,d)=>{let p=await this.#h({method:"input",title:s,placeholder:a,prefill:d});return p.cancelled?null:p.value??""},confirm:async(s,a)=>!!(await this.#h({method:"confirm",title:s,message:a})).confirmed,setInput:s=>{this.input=s,this.update(),this.#g()},refreshSessions:()=>this.parent.refreshSessions()}}async runRecipe(s){this.slashQuery=null,this.sendError=void 0,this.update();try{let a=await s.run(this.#A());typeof a=="string"&&a&&this.#p(a)}catch(a){this.sendError=a instanceof Error?a.message:String(a)}this.dlg=null,this.update()}async#b(){try{let s=await tb.server.composerRpc({type:"get_commands"},{spawn:!1}),a=s?.ok?s.data?.commands:null;Array.isArray(a)&&(this.harnessCommands=a.map(d=>({name:String(d.name),description:d.description??""})),this.update())}catch{}}filteredCommands(){if(this.slashQuery===null)return[];let s=this.slashQuery.toLowerCase(),a=[...this.recipes.filter(d=>!d.hidden).map(d=>({name:d.name,description:d.description,recipe:d})),...this.harnessCommands.filter(d=>!this.recipes.some(p=>p.name===d.name)).map(d=>({name:d.name,description:d.description,recipe:void 0}))];return s?sEe(a,d=>{let p=d.name.toLowerCase().indexOf(s);return p===0?0:p>0?100+p:-1},12):a.slice(0,12)}applySlashSelection(){let s=this.filteredCommands();if(this.slashQuery===null||s.length===0)return!1;let a=s[this.slashIndex];if(!a)return!1;this.slashQuery=null;let d=this.input.replace(/^\/\S*\s?/,"");if(a.recipe)return this.input=d,this.runRecipe(a.recipe),!0;let p="/"+a.name+" ";return this.input=p+d,this.update(),this.#g(p.length),!0}async newConversation(){this.#e||await this.#c("could not start a new conversation \u2014 mirror unreachable",async()=>{let s=await tb.server.composerNew();if(!s?.ok){this.sendError=s?.error??"could not start a new conversation";return}this.#r()})}filteredFiles(){if(this.atQuery===null)return[];let s=this.atQuery.toLowerCase();return s?sEe(this.files,a=>{let d=a.toLowerCase().indexOf(s);if(d===-1)return-1;let p=a.slice(a.lastIndexOf("/")+1).toLowerCase().indexOf(s);return p===-1?1e3+d:p},10):this.files.slice(0,10)}onComposerInput(s){let a=s.selectionStart,d=s.value,p=null,b=0;for(let D=a-1;D>=0;D--){let P=d[D];if(P==="@"){let F=D>0?d[D-1]:"";(!F||/[\s([{]/.test(F))&&(p=d.slice(D+1,a),b=D);break}if(/\s/.test(P))break}let v=null;if(d.startsWith("/")&&a>=1){let D=d.slice(1,a);/\s/.test(D)||(v=D)}v!==null&&(p=null);let w=!(p===this.atQuery&&(p===null||b===this.atStart)),I=v!==this.slashQuery;if(!w&&!I)return;let T=p!==null&&this.atQuery===null,B=v!==null&&this.slashQuery===null;this.atQuery=p,p!==null&&(this.atStart=b,this.atIndex=0),this.slashQuery=v,v!==null&&I&&(this.slashIndex=0),T&&this.#r(),B&&this.#b(),this.update()}applyAtSelection(){let s=this.#m(),a=this.filteredFiles();if(!s||this.atQuery===null||a.length===0)return!1;let d=a[this.atIndex];if(!d)return!1;let p=this.input.slice(0,this.atStart),b=this.input.slice(s.selectionStart),v="@"+d+" ";return this.input=p+v+b,this.atQuery=null,this.update(),this.#g(p.length+v.length),!0}#m(){return document.querySelector(".composer-input")}#g(s){setTimeout(()=>{let a=this.#m();a&&(a.focus(),a.selectionStart=a.selectionEnd=s??a.value.length)},0)}beginSplitterDrag(s){s.preventDefault();let a=s.clientY,d=this.composerHeight,p=document.body.style.cursor,b=document.body.style.userSelect;document.body.style.cursor="row-resize",document.body.style.userSelect="none";let v=I=>{let T=d-(I.clientY-a),B=Math.max(120,window.innerHeight*.6);this.composerHeight=Math.max(40,Math.min(B,T)),this.update()},w=()=>{document.removeEventListener("mousemove",v),document.removeEventListener("mouseup",w),document.body.style.cursor=p,document.body.style.userSelect=b};document.addEventListener("mousemove",v),document.addEventListener("mouseup",w)}#v(s){if(this.sendError&&s.key!=="Enter"&&(this.sendError=void 0,this.update()),s.key===";"&&(s.ctrlKey||s.metaKey)){s.preventDefault(),this.captureClipboard();return}this.slashQuery!==null&&this.#x(s,this.filteredCommands().length,this.slashIndex,a=>this.slashIndex=a,()=>this.slashQuery=null,()=>this.applySlashSelection())||this.atQuery!==null&&this.#x(s,this.filteredFiles().length,this.atIndex,a=>this.atIndex=a,()=>this.atQuery=null,()=>this.applyAtSelection())||s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),this.send(s.altKey))}#x(s,a,d,p,b,v){return s.key==="ArrowDown"||s.key==="ArrowUp"?(s.preventDefault(),p(Math.max(0,Math.min(d+(s.key==="ArrowDown"?1:-1),a-1))),this.update(),this.#y(".at-popup"),!0):s.key==="Escape"?(s.preventDefault(),b(),this.update(),!0):(s.key==="Enter"||s.key==="Tab")&&a>0?(s.preventDefault(),v(),!0):!1}#y(s){setTimeout(()=>document.querySelector(`${s} .at-row.active`)?.scrollIntoView({block:"nearest"}),0)}view(){let s=this.#o(),a=s||this.#e?{disabled:!0}:{},d=this.sendError??this.driverError,p=this.localNotice&&Date.now()<this.localNotice.until?{text:this.localNotice.text,kind:"info"}:this.status,b=s?"the agent is working in a terminal \u2014 watch only":this.streaming?"Steer \u2014 Enter queues for after this step, Alt+Enter for after the turn":"Message the agent\u2026 (Enter to send, Shift+Enter for newline, @ files, / commands, ! bash)";return Qt({class:"composer"},this.dlg?this.#S()?this.dialogPopup():this.dialogView():null,this.atQuery!==null?this.atPopup():null,this.slashQuery!==null?this.slashPopup():null,Qt({class:"splitter",key:"splitter",onMouseDown:v=>this.beginSplitterDrag(v)},""),d?Qt({class:"composer-err"},d):null,!d&&p?Qt({class:["composer-status",p.kind],key:"composer-status"},p.text):null,this.queueStrip(),Qt({class:"input-wrap",key:"composer-row"},Jye({target:this,prop:()=>this.input,attrs:{class:"composer-input",placeholder:b,ariaLabel:"Message the agent",style:{height:`${this.composerHeight}px`},onKeyDown:v=>this.#v(v),onKeyUp:v=>{v.key!=="Escape"&&this.onComposerInput(v.target)},onClick:v=>this.onComposerInput(v.target),onPaste:v=>this.onPaste(v),...a}}),Qt({class:"composer-actions"},nc({class:"composer-clip",type:"button",title:"Capture clipboard to a file (Ctrl+;)",ariaLabel:"Capture clipboard",...a,onClick:()=>{this.captureClipboard()}},Y0("attach")),nc({class:"composer-new",type:"button",title:"New conversation",ariaLabel:"New conversation",...this.#e?{disabled:!0}:{},onClick:()=>{this.newConversation()}},Y0("addCircle")),this.streaming?nc({class:"composer-act stop",type:"button",title:"Stop the current turn",ariaLabel:"Stop",onClick:()=>{this.stopTurn()}},Y0("stopCircle")):nc({class:"composer-act send",type:"button",title:"Send (Enter)",ariaLabel:"Send",...a,onClick:()=>{this.send()}},Y0("playCircle")))))}queueStrip(){let s=this.queue,a=s?[...s.steering.map(d=>({tag:"steer",t:d})),...s.followUp.map(d=>({tag:"follow-up",t:d}))]:[];return a.length?Qt({class:"composer-queue",key:"composer-queue"},a.map(d=>Qt({class:"queue-row"},wr({class:"queue-tag"},d.tag),d.t))):null}atPopup(){return this.#E("at-popup",this.filteredFiles(),"No matches",this.atIndex,s=>{this.atIndex=s,this.applyAtSelection()},s=>s)}slashPopup(){return this.#E("slash-popup",this.filteredCommands(),"No commands",this.slashIndex,s=>{this.slashIndex=s,this.applySlashSelection()},s=>[wr({class:"slash-name"},"/"+s.name),s.description?wr({class:"slash-desc"},s.description):null])}#E(s,a,d,p,b,v){return Qt({class:"at-popup",key:s},this.#k(a,d,p,b,v))}#k(s,a,d,p,b){return s.length===0?Qt({class:"at-empty"},a):s.map((v,w)=>Qt({class:["at-row",w===d?"active":""],onMouseDown:I=>{I.preventDefault(),p(w)}},b(v)))}#S(){return!!this.dlg&&this.dlg.local&&(this.dlg.req.method==="select"||this.dlg.req.method==="input")}dialogPopup(){let{req:s}=this.dlg;return Qt({key:"composer-dlg"},Qt({class:"dlg-catcher",onMouseDown:a=>{a.preventDefault(),this.answerDialog({cancelled:!0})}},""),Qt({class:"at-popup dlg-popup",key:"dlg-popup"},s.method==="select"?this.selectBody():[s.title?Qt({class:"dlg-label"},s.title):null,fM({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-input",placeholder:s.placeholder??"",onMounted:this.#d,onKeyDown:a=>this.#C(a)}})]))}dialogView(){let{req:s}=this.dlg,a=s.method==="confirm"?"Confirm":s.method==="select"?"Choose":"Input";return Qt({class:"trust-back",key:"composer-dlg"},Qt({class:"trust-modal composer-dlg"},Qt({class:"trust-modal-h"},s.title??a),s.message?Qt({class:"trust-modal-b"},s.message):null,s.method==="select"?this.selectBody():null,s.method==="input"?fM({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-input",placeholder:s.placeholder??"",onMounted:this.#d,onKeyDown:d=>this.#C(d)}}):null,s.method==="editor"?Jye({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-editor",onMounted:this.#d,onKeyDown:d=>{d.key==="Escape"&&(d.preventDefault(),this.answerDialog({cancelled:!0}))}}}):null,Qt({class:"trust-modal-acts"},nc({class:"trust-no",type:"button",onClick:()=>this.answerDialog(s.method==="confirm"?{confirmed:!1}:{cancelled:!0})},s.method==="confirm"?"No":"Cancel"),s.method==="confirm"?nc({class:"trust-yes",type:"button",onClick:()=>this.answerDialog({confirmed:!0})},"Yes"):s.method!=="select"?nc({class:"trust-yes",type:"button",onClick:()=>this.answerDialog({value:this.dlgInput})},"OK"):null)))}#C(s){s.key==="Enter"&&(s.preventDefault(),this.answerDialog({value:this.dlgInput})),s.key==="Escape"&&(s.preventDefault(),this.answerDialog({cancelled:!0}))}filteredDlgOptions(){let s=this.dlg?.req.options??[],a=this.dlgFilter.trim().toLowerCase();return a?sEe(s,d=>d.toLowerCase().indexOf(a)):s}selectBody(){let s=this.filteredDlgOptions(),a=Math.min(this.dlgIndex,Math.max(0,s.length-1));return Qt({key:"dlg-select"},Qt({class:"dlg-opts",onMounted:d=>d.querySelector(".at-row.active")?.scrollIntoView({block:"nearest"})},this.#k(s,"No matches",a,d=>this.answerDialog({value:s[d]}),d=>d)),fM({target:this,prop:()=>this.dlgFilter,attrs:{class:"dlg-input dlg-filter",placeholder:"Type to filter\u2026",onMounted:this.#d,onKeyDown:d=>this.#I(d),onKeyUp:()=>{this.dlgFilter!==this.#t&&(this.#t=this.dlgFilter,this.dlgIndex=0,this.update())}}}))}#I(s){let a=this.filteredDlgOptions(),d=Math.min(this.dlgIndex,Math.max(0,a.length-1));if(s.key==="ArrowDown"||s.key==="ArrowUp"){s.preventDefault(),this.dlgIndex=Math.max(0,Math.min(d+(s.key==="ArrowDown"?1:-1),a.length-1)),this.update(),this.#y(".dlg-opts");return}if(s.key==="Enter"){s.preventDefault();let p=a[d];p!==void 0&&this.answerDialog({value:p});return}s.key==="Escape"&&(s.preventDefault(),this.answerDialog({cancelled:!0}))}};var cie=class extends wu{get parent(){return this.ctx.parent}view(){let s=this.parent.driverModel??this.parent.latestModel;if(!s)return wr({class:"model-wrap"});let a=s.includes("/")?s.slice(s.lastIndexOf("/")+1):s;return wr({class:"model-wrap"},wr({class:"token",title:`Model: ${s}`},a))}};var oEe=o=>`~${nte(o??0)}`;async function U4(o,s,a){let d=await o.rpc(s);if(!d.ok)throw new Error(d.error??a);return d.data}async function JSt(o){return(await o.rpc({type:"get_state"})).data}var aD=(o,s)=>`${o} ${s}${o===1?"":"s"}`;async function zSt(){let o=await tb.server.composerNew();if(!o?.ok)throw new Error(o?.error??"could not start a new conversation");return"new conversation \u2014 /model now lists your local models"}async function USt(o){let s=o.replace(/\\/g,"/").split("/").pop().replace(/\.jsonl$/,"");return!!(await tb.server.attach(s))?.ok}async function i5n(o,s,a){if(!await o.confirm(s?"Add local Ollama models?":`Sync ${aD(a,"new Ollama model")}?`,"Rewrites the ollama provider in pi's models.json to exactly what's installed. Prefer a hand-curated list? Cancel \u2014 the file is yours."))return;let p=await tb.server.ollamaSync();if(!p?.ok)throw new Error(p?.error??"Ollama sync failed");return await o.confirm(`${aD(p.count??0,"Ollama model")} configured`,"Pi loads models.json when it boots \u2014 start a new conversation now to use them?")?zSt():`${aD(p.count??0,"Ollama model")} configured \u2014 new conversations (+) and terminal pi will list them`}var KSt=[{name:"model",description:"Switch the model",async run(o){let[s,a]=await Promise.all([U4(o,{type:"get_available_models"},"could not list models"),tb.server.ollamaOffer().catch(()=>null)]),d=s?.models??[],p=d.map(K=>`${K.provider}/${K.id}`),{installed:b,configured:v}=a??{installed:[],configured:null},w=b.filter(K=>!v?.includes(K)),I=w.length?v===null?`+ add ${aD(w.length,"local Ollama model")}\u2026`:`\u27F3 sync ${aD(w.length,"new local Ollama model")}\u2026`:null,T=new Set(d.filter(K=>K.provider==="ollama").map(K=>K.id)),B=(v??[]).filter(K=>!T.has(K)).length,D=B?`\u27F3 ${aD(B,"Ollama model")} pending \u2014 new conversation loads them`:null;if(I&&p.push(I),D&&p.push(D),!p.length)return"no models configured";let P=(await JSt(o))?.model,F=await o.select("Switch model",p,P?`${P.provider}/${P.id}`:void 0);if(F===null)return;if(I!==null&&F===I)return i5n(o,v===null,w.length);if(D!==null&&F===D)return zSt();let U=d[p.indexOf(F)];return await U4(o,{type:"set_model",provider:U.provider,modelId:U.id},"set_model failed"),`model: ${F}`}},{name:"thinking",description:"Set the thinking level",async run(o){let s=await o.select("Thinking level",["off","minimal","low","medium","high","xhigh"],(await JSt(o))?.thinkingLevel);if(s!==null)return await U4(o,{type:"set_thinking_level",level:s},"set_thinking_level failed"),`thinking: ${s}`}},{name:"compact",description:"Compact the conversation context",async run(o){let s=await o.input("Compact context","optional instructions \u2014 Enter to compact");if(s===null)return;let a=await U4(o,{type:"compact",...s.trim()?{customInstructions:s.trim()}:{}},"compact failed");return a?.tokensBefore?`compacted: ${oEe(a.tokensBefore)} \u2192 ${oEe(a.estimatedTokensAfter)} tokens`:"compacted"}},{name:"fork",description:"Fork from an earlier message",async run(o){let a=(await U4(o,{type:"get_fork_messages"},"could not list fork points"))?.messages??[];if(!a.length)return"nothing to fork from";let d=a.map((w,I)=>`${I+1}. ${hM(w.text,80)}`),p=await o.select("Fork from\u2026",d);if(p===null)return;let b=a[d.indexOf(p)],v=await U4(o,{type:"fork",entryId:b.entryId},"fork failed");if(v?.sessionFile&&!await USt(v.sessionFile)){let w=await tb.server.composerNew();if(!w?.ok)throw new Error(w?.error??"could not open a new conversation")}return v?.text&&o.setInput(v.text),"forked \u2014 edit the restored prompt and send"}},{name:"clone",description:"Duplicate this branch into a new session",async run(o){if(!await o.confirm("Clone session?","Duplicates the current branch into a new session file."))return;let s=await U4(o,{type:"clone"},"clone failed");if(s?.sessionFile&&!await USt(s.sessionFile))throw new Error("clone finished but its session file never appeared");return"cloned \u2014 this is the duplicate"}},{name:"name",description:"Name this session",async run(o){let s=await o.input("Session name");if(!(s===null||!s.trim()))return await U4(o,{type:"set_session_name",name:s.trim()},"set_session_name failed"),o.refreshSessions(),`named: ${s.trim()}`}},{name:"export",description:"Export the session to HTML",async run(o){return`exported: ${(await U4(o,{type:"export_html"},"export failed"))?.path??"done"}`}},{name:"stats",description:"Token usage, cost, and context headroom",hidden:!0,async run(o){let s=await U4(o,{type:"get_session_stats"},"get_session_stats failed"),a=[s?.tokens?.total!==void 0?`${oEe(s.tokens.total)} tokens`:null,s?.cost!==void 0?`$${s.cost.toFixed(2)}`:null,s?.contextUsage?.percent!=null?`context ${s.contextUsage.percent}%`:null].filter(Boolean);return a.length?a.join(" \xB7 "):"no stats yet"}}];document.title="Pi Mirror";new g6t({root:new sie({title:"Pi Mirror",pills:[new cie],composer:new oie(KSt)}),id:"app"});
|
|
1941
|
+
`+this.input:""),this.queue=null,this.update(),this.#p())}async runBash(s){s&&await this.#o("bash failed \u2014 mirror unreachable",async()=>{let a=await tb.server.composerRpc({type:"bash",command:s},{spawn:!0});a?.ok?(this.input="",this.#d("ran \u2014 output joins context on the next message")):this.sendError=a?.error??"bash failed"})}onPaste(s){let a=[...s.clipboardData?.items??[]].find(p=>p.type.startsWith("image/"));if(!a)return;s.preventDefault();let d=a.getAsFile();d&&this.#c(d,d.type,s.target.selectionStart)}async captureClipboard(){let s=this.#g(),a=s?s.selectionStart:this.input.length;try{for(let d of await navigator.clipboard.read()){let p=d.types.find(b=>b.startsWith("image/"));if(p){this.#c(await d.getType(p),p,a);return}}}catch{}try{let d=(await navigator.clipboard.readText()).trim();if(!d){this.#d("clipboard is empty"),this.update();return}this.#u({kind:"text",data:d},a)}catch{this.sendError="clipboard unavailable",this.update()}}#c(s,a,d){let p=new FileReader;p.onload=()=>{let b=String(p.result??"");this.#u({kind:"image",data:b.slice(b.indexOf(",")+1),mime:a},d)},p.readAsDataURL(s)}async#u(s,a){let d=p=>{this.sendError=p,this.localNotice=null,this.update()};this.#d(s.kind==="image"?"saving image\u2026":"saving text\u2026"),this.update();try{let p=await tb.server.composerPaste(s);if(!p?.ok)return d(p?.error??"paste failed");let b=`@${p.path} `,v=Math.min(a,this.input.length);this.input=this.input.slice(0,v)+b+this.input.slice(v),this.localNotice=null,this.update(),this.#p(v+b.length)}catch{d("paste failed \u2014 mirror unreachable")}}#f(s){this.dlgInput=s.prefill??"",this.#h(s),this.dlg={req:s,local:!1,resolve:a=>{this.#n=s.id,tb.server.composerUiRespond(s.id,a)}}}#l(s){return new Promise(a=>{this.dlgInput=s.prefill??"",this.#h(s),this.dlg={req:{id:`local-${++this.#i}`,...s},local:!0,resolve:a},this.update()})}#h(s){this.dlgFilter="",this.#t="",this.dlgIndex=s.selected?Math.max(0,(s.options??[]).indexOf(s.selected)):0}#a=s=>s.focus();answerDialog(s){let a=this.dlg;a&&(this.dlg=null,a.resolve(s),this.update(),this.#p())}#d(s){this.localNotice={text:s,until:Date.now()+6e3}}#b(){return{rpc:s=>tb.server.composerRpc(s,{spawn:!0}),select:async(s,a,d)=>{let p=await this.#l({method:"select",title:s,options:a,selected:d});return p.cancelled?null:p.value??null},input:async(s,a,d)=>{let p=await this.#l({method:"input",title:s,placeholder:a,prefill:d});return p.cancelled?null:p.value??""},confirm:async(s,a)=>!!(await this.#l({method:"confirm",title:s,message:a})).confirmed,setInput:s=>{this.input=s,this.update(),this.#p()},refreshSessions:()=>this.parent.refreshSessions()}}async runRecipe(s){this.slashQuery=null,this.sendError=void 0,this.update();try{let a=await s.run(this.#b());typeof a=="string"&&a&&this.#d(a)}catch(a){this.sendError=a instanceof Error?a.message:String(a)}this.dlg=null,this.update()}async#A(){try{let s=await tb.server.composerRpc({type:"get_commands"},{spawn:!1}),a=s?.ok?s.data?.commands:null;Array.isArray(a)&&(this.harnessCommands=a.map(d=>({name:String(d.name),description:d.description??""})),this.update())}catch{}}filteredCommands(){if(this.slashQuery===null)return[];let s=this.slashQuery.toLowerCase(),a=[...this.recipes.filter(d=>!d.hidden).map(d=>({name:d.name,description:d.description,recipe:d})),...this.harnessCommands.filter(d=>!this.recipes.some(p=>p.name===d.name)).map(d=>({name:d.name,description:d.description,recipe:void 0}))];return s?sEe(a,d=>{let p=d.name.toLowerCase().indexOf(s);return p===0?0:p>0?100+p:-1},12):a.slice(0,12)}applySlashSelection(){let s=this.filteredCommands();if(this.slashQuery===null||s.length===0)return!1;let a=s[this.slashIndex];if(!a)return!1;this.slashQuery=null;let d=this.input.replace(/^\/\S*\s?/,"");if(a.recipe)return this.input=d,this.runRecipe(a.recipe),!0;let p="/"+a.name+" ";return this.input=p+d,this.update(),this.#p(p.length),!0}async newConversation(){this.#e||await this.#o("could not start a new conversation \u2014 mirror unreachable",async()=>{let s=await tb.server.composerNew();if(!s?.ok){this.sendError=s?.error??"could not start a new conversation";return}this.#r()})}filteredFiles(){if(this.atQuery===null)return[];let s=this.atQuery.toLowerCase();return s?sEe(this.files,a=>{let d=a.toLowerCase().indexOf(s);if(d===-1)return-1;let p=a.slice(a.lastIndexOf("/")+1).toLowerCase().indexOf(s);return p===-1?1e3+d:p},10):this.files.slice(0,10)}onComposerInput(s){let a=s.selectionStart,d=s.value,p=null,b=0;for(let D=a-1;D>=0;D--){let P=d[D];if(P==="@"){let F=D>0?d[D-1]:"";(!F||/[\s([{]/.test(F))&&(p=d.slice(D+1,a),b=D);break}if(/\s/.test(P))break}let v=null;if(d.startsWith("/")&&a>=1){let D=d.slice(1,a);/\s/.test(D)||(v=D)}v!==null&&(p=null);let w=!(p===this.atQuery&&(p===null||b===this.atStart)),I=v!==this.slashQuery;if(!w&&!I)return;let T=p!==null&&this.atQuery===null,B=v!==null&&this.slashQuery===null;this.atQuery=p,p!==null&&(this.atStart=b,this.atIndex=0),this.slashQuery=v,v!==null&&I&&(this.slashIndex=0),T&&this.#r(),B&&this.#A(),this.update()}applyAtSelection(){let s=this.#g(),a=this.filteredFiles();if(!s||this.atQuery===null||a.length===0)return!1;let d=a[this.atIndex];if(!d)return!1;let p=this.input.slice(0,this.atStart),b=this.input.slice(s.selectionStart),v="@"+d+" ";return this.input=p+v+b,this.atQuery=null,this.update(),this.#p(p.length+v.length),!0}#g(){return document.querySelector(".composer-input")}#p(s){setTimeout(()=>{let a=this.#g();a&&(a.focus(),a.selectionStart=a.selectionEnd=s??a.value.length)},0)}beginSplitterDrag(s){s.preventDefault();let a=s.clientY,d=this.composerHeight,p=document.body.style.cursor,b=document.body.style.userSelect;document.body.style.cursor="row-resize",document.body.style.userSelect="none";let v=I=>{let T=d-(I.clientY-a),B=Math.max(120,window.innerHeight*.6);this.composerHeight=Math.max(40,Math.min(B,T)),this.update()},w=()=>{document.removeEventListener("mousemove",v),document.removeEventListener("mouseup",w),document.body.style.cursor=p,document.body.style.userSelect=b};document.addEventListener("mousemove",v),document.addEventListener("mouseup",w)}#v(s){if(this.sendError&&s.key!=="Enter"&&(this.sendError=void 0,this.update()),s.key===";"&&(s.ctrlKey||s.metaKey)){s.preventDefault(),this.captureClipboard();return}this.slashQuery!==null&&this.#m(s,this.filteredCommands().length,this.slashIndex,a=>this.slashIndex=a,()=>this.slashQuery=null,()=>this.applySlashSelection())||this.atQuery!==null&&this.#m(s,this.filteredFiles().length,this.atIndex,a=>this.atIndex=a,()=>this.atQuery=null,()=>this.applyAtSelection())||s.key==="Enter"&&!s.shiftKey&&(s.preventDefault(),this.send(s.altKey))}#m(s,a,d,p,b,v){return s.key==="ArrowDown"||s.key==="ArrowUp"?(s.preventDefault(),p(Math.max(0,Math.min(d+(s.key==="ArrowDown"?1:-1),a-1))),this.update(),this.#k(".at-popup"),!0):s.key==="Escape"?(s.preventDefault(),b(),this.update(),!0):(s.key==="Enter"||s.key==="Tab")&&a>0?(s.preventDefault(),v(),!0):!1}#k(s){setTimeout(()=>document.querySelector(`${s} .at-row.active`)?.scrollIntoView({block:"nearest"}),0)}view(){let s=this.foreign||this.#e?{disabled:!0}:{},a=this.sendError??this.driverError,d=this.localNotice&&Date.now()<this.localNotice.until?{text:this.localNotice.text,kind:"info"}:this.status,p=this.foreign?"the agent is working in a terminal \u2014 watch only":this.streaming?"Steer \u2014 Enter queues for after this step, Alt+Enter for after the turn":"Message the agent\u2026 (Enter to send, Shift+Enter for newline, @ files, / commands, ! bash)";return Qt({class:"composer"},this.dlg?this.#E()?this.dialogPopup():this.dialogView():null,this.atQuery!==null?this.atPopup():null,this.slashQuery!==null?this.slashPopup():null,Qt({class:"splitter",key:"splitter",onMouseDown:b=>this.beginSplitterDrag(b)},""),a?Qt({class:"composer-err"},a):null,!a&&d?Qt({class:["composer-status",d.kind],key:"composer-status"},d.text):null,this.queueStrip(),Qt({class:"input-wrap",key:"composer-row"},Jye({target:this,prop:()=>this.input,attrs:{class:"composer-input",placeholder:p,ariaLabel:"Message the agent",style:{height:`${this.composerHeight}px`},onKeyDown:b=>this.#v(b),onKeyUp:b=>{b.key!=="Escape"&&this.onComposerInput(b.target)},onClick:b=>this.onComposerInput(b.target),onPaste:b=>this.onPaste(b),...s}}),Qt({class:"composer-actions"},nc({class:"composer-clip",type:"button",title:"Capture clipboard to a file (Ctrl+;)",ariaLabel:"Capture clipboard",...s,onClick:()=>{this.captureClipboard()}},Y0("attach")),nc({class:"composer-new",type:"button",title:"New conversation",ariaLabel:"New conversation",...this.#e?{disabled:!0}:{},onClick:()=>{this.newConversation()}},Y0("addCircle")),this.streaming?nc({class:"composer-act stop",type:"button",title:"Stop the current turn",ariaLabel:"Stop",onClick:()=>{this.stopTurn()}},Y0("stopCircle")):nc({class:"composer-act send",type:"button",title:"Send (Enter)",ariaLabel:"Send",...s,onClick:()=>{this.send()}},Y0("playCircle")))))}queueStrip(){let s=this.queue,a=s?[...s.steering.map(d=>({tag:"steer",t:d})),...s.followUp.map(d=>({tag:"follow-up",t:d}))]:[];return a.length?Qt({class:"composer-queue",key:"composer-queue"},a.map(d=>Qt({class:"queue-row"},wr({class:"queue-tag"},d.tag),d.t))):null}atPopup(){return this.#y("at-popup",this.filteredFiles(),"No matches",this.atIndex,s=>{this.atIndex=s,this.applyAtSelection()},s=>s)}slashPopup(){return this.#y("slash-popup",this.filteredCommands(),"No commands",this.slashIndex,s=>{this.slashIndex=s,this.applySlashSelection()},s=>[wr({class:"slash-name"},"/"+s.name),s.description?wr({class:"slash-desc"},s.description):null])}#y(s,a,d,p,b,v){return Qt({class:"at-popup",key:s},this.#x(a,d,p,b,v))}#x(s,a,d,p,b){return s.length===0?Qt({class:"at-empty"},a):s.map((v,w)=>Qt({class:["at-row",w===d?"active":""],onMouseDown:I=>{I.preventDefault(),p(w)}},b(v)))}#E(){return!!this.dlg&&this.dlg.local&&(this.dlg.req.method==="select"||this.dlg.req.method==="input")}dialogPopup(){let{req:s}=this.dlg;return Qt({key:"composer-dlg"},Qt({class:"dlg-catcher",onMouseDown:a=>{a.preventDefault(),this.answerDialog({cancelled:!0})}},""),Qt({class:"at-popup dlg-popup",key:"dlg-popup"},s.method==="select"?this.selectBody():[s.title?Qt({class:"dlg-label"},s.title):null,fM({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-input",placeholder:s.placeholder??"",onMounted:this.#a,onKeyDown:a=>this.#C(a)}})]))}dialogView(){let{req:s}=this.dlg,a=s.method==="confirm"?"Confirm":s.method==="select"?"Choose":"Input";return Qt({class:"trust-back",key:"composer-dlg"},Qt({class:"trust-modal composer-dlg"},Qt({class:"trust-modal-h"},s.title??a),s.message?Qt({class:"trust-modal-b"},s.message):null,s.method==="select"?this.selectBody():null,s.method==="input"?fM({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-input",placeholder:s.placeholder??"",onMounted:this.#a,onKeyDown:d=>this.#C(d)}}):null,s.method==="editor"?Jye({target:this,prop:()=>this.dlgInput,attrs:{class:"dlg-editor",onMounted:this.#a,onKeyDown:d=>{d.key==="Escape"&&(d.preventDefault(),this.answerDialog({cancelled:!0}))}}}):null,Qt({class:"trust-modal-acts"},nc({class:"trust-no",type:"button",onClick:()=>this.answerDialog(s.method==="confirm"?{confirmed:!1}:{cancelled:!0})},s.method==="confirm"?"No":"Cancel"),s.method==="confirm"?nc({class:"trust-yes",type:"button",onClick:()=>this.answerDialog({confirmed:!0})},"Yes"):s.method!=="select"?nc({class:"trust-yes",type:"button",onClick:()=>this.answerDialog({value:this.dlgInput})},"OK"):null)))}#C(s){s.key==="Enter"&&(s.preventDefault(),this.answerDialog({value:this.dlgInput})),s.key==="Escape"&&(s.preventDefault(),this.answerDialog({cancelled:!0}))}filteredDlgOptions(){let s=this.dlg?.req.options??[],a=this.dlgFilter.trim().toLowerCase();return a?sEe(s,d=>d.toLowerCase().indexOf(a)):s}selectBody(){let s=this.filteredDlgOptions(),a=Math.min(this.dlgIndex,Math.max(0,s.length-1));return Qt({key:"dlg-select"},Qt({class:"dlg-opts",onMounted:d=>d.querySelector(".at-row.active")?.scrollIntoView({block:"nearest"})},this.#x(s,"No matches",a,d=>this.answerDialog({value:s[d]}),d=>d)),fM({target:this,prop:()=>this.dlgFilter,attrs:{class:"dlg-input dlg-filter",placeholder:"Type to filter\u2026",onMounted:this.#a,onKeyDown:d=>this.#I(d),onKeyUp:()=>{this.dlgFilter!==this.#t&&(this.#t=this.dlgFilter,this.dlgIndex=0,this.update())}}}))}#I(s){let a=this.filteredDlgOptions(),d=Math.min(this.dlgIndex,Math.max(0,a.length-1));if(s.key==="ArrowDown"||s.key==="ArrowUp"){s.preventDefault(),this.dlgIndex=Math.max(0,Math.min(d+(s.key==="ArrowDown"?1:-1),a.length-1)),this.update(),this.#k(".dlg-opts");return}if(s.key==="Enter"){s.preventDefault();let p=a[d];p!==void 0&&this.answerDialog({value:p});return}s.key==="Escape"&&(s.preventDefault(),this.answerDialog({cancelled:!0}))}};var cie=class extends wu{get parent(){return this.ctx.parent}view(){let s=this.parent.driverModel??this.parent.latestModel;if(!s)return wr({class:"model-wrap"});let a=s.includes("/")?s.slice(s.lastIndexOf("/")+1):s;return wr({class:"model-wrap"},wr({class:"token",title:`Model: ${s}`},a))}};var oEe=o=>`~${nte(o??0)}`;async function U4(o,s,a){let d=await o.rpc(s);if(!d.ok)throw new Error(d.error??a);return d.data}async function JSt(o){return(await o.rpc({type:"get_state"})).data}var aD=(o,s)=>`${o} ${s}${o===1?"":"s"}`;async function zSt(){let o=await tb.server.composerNew();if(!o?.ok)throw new Error(o?.error??"could not start a new conversation");return"new conversation \u2014 /model now lists your local models"}async function USt(o){let s=o.replace(/\\/g,"/").split("/").pop().replace(/\.jsonl$/,"");return!!(await tb.server.attach(s))?.ok}async function i5n(o,s,a){if(!await o.confirm(s?"Add local Ollama models?":`Sync ${aD(a,"new Ollama model")}?`,"Rewrites the ollama provider in pi's models.json to exactly what's installed. Prefer a hand-curated list? Cancel \u2014 the file is yours."))return;let p=await tb.server.ollamaSync();if(!p?.ok)throw new Error(p?.error??"Ollama sync failed");return await o.confirm(`${aD(p.count??0,"Ollama model")} configured`,"Pi loads models.json when it boots \u2014 start a new conversation now to use them?")?zSt():`${aD(p.count??0,"Ollama model")} configured \u2014 new conversations (+) and terminal pi will list them`}var KSt=[{name:"model",description:"Switch the model",async run(o){let[s,a]=await Promise.all([U4(o,{type:"get_available_models"},"could not list models"),tb.server.ollamaOffer().catch(()=>null)]),d=s?.models??[],p=d.map(K=>`${K.provider}/${K.id}`),{installed:b,configured:v}=a??{installed:[],configured:null},w=b.filter(K=>!v?.includes(K)),I=w.length?v===null?`+ add ${aD(w.length,"local Ollama model")}\u2026`:`\u27F3 sync ${aD(w.length,"new local Ollama model")}\u2026`:null,T=new Set(d.filter(K=>K.provider==="ollama").map(K=>K.id)),B=(v??[]).filter(K=>!T.has(K)).length,D=B?`\u27F3 ${aD(B,"Ollama model")} pending \u2014 new conversation loads them`:null;if(I&&p.push(I),D&&p.push(D),!p.length)return"no models configured";let P=(await JSt(o))?.model,F=await o.select("Switch model",p,P?`${P.provider}/${P.id}`:void 0);if(F===null)return;if(I!==null&&F===I)return i5n(o,v===null,w.length);if(D!==null&&F===D)return zSt();let U=d[p.indexOf(F)];return await U4(o,{type:"set_model",provider:U.provider,modelId:U.id},"set_model failed"),`model: ${F}`}},{name:"thinking",description:"Set the thinking level",async run(o){let s=await o.select("Thinking level",["off","minimal","low","medium","high","xhigh"],(await JSt(o))?.thinkingLevel);if(s!==null)return await U4(o,{type:"set_thinking_level",level:s},"set_thinking_level failed"),`thinking: ${s}`}},{name:"compact",description:"Compact the conversation context",async run(o){let s=await o.input("Compact context","optional instructions \u2014 Enter to compact");if(s===null)return;let a=await U4(o,{type:"compact",...s.trim()?{customInstructions:s.trim()}:{}},"compact failed");return a?.tokensBefore?`compacted: ${oEe(a.tokensBefore)} \u2192 ${oEe(a.estimatedTokensAfter)} tokens`:"compacted"}},{name:"fork",description:"Fork from an earlier message",async run(o){let a=(await U4(o,{type:"get_fork_messages"},"could not list fork points"))?.messages??[];if(!a.length)return"nothing to fork from";let d=a.map((w,I)=>`${I+1}. ${hM(w.text,80)}`),p=await o.select("Fork from\u2026",d);if(p===null)return;let b=a[d.indexOf(p)],v=await U4(o,{type:"fork",entryId:b.entryId},"fork failed");if(v?.sessionFile&&!await USt(v.sessionFile)){let w=await tb.server.composerNew();if(!w?.ok)throw new Error(w?.error??"could not open a new conversation")}return v?.text&&o.setInput(v.text),"forked \u2014 edit the restored prompt and send"}},{name:"clone",description:"Duplicate this branch into a new session",async run(o){if(!await o.confirm("Clone session?","Duplicates the current branch into a new session file."))return;let s=await U4(o,{type:"clone"},"clone failed");if(s?.sessionFile&&!await USt(s.sessionFile))throw new Error("clone finished but its session file never appeared");return"cloned \u2014 this is the duplicate"}},{name:"name",description:"Name this session",async run(o){let s=await o.input("Session name");if(!(s===null||!s.trim()))return await U4(o,{type:"set_session_name",name:s.trim()},"set_session_name failed"),o.refreshSessions(),`named: ${s.trim()}`}},{name:"export",description:"Export the session to HTML",async run(o){return`exported: ${(await U4(o,{type:"export_html"},"export failed"))?.path??"done"}`}},{name:"stats",description:"Token usage, cost, and context headroom",hidden:!0,async run(o){let s=await U4(o,{type:"get_session_stats"},"get_session_stats failed"),a=[s?.tokens?.total!==void 0?`${oEe(s.tokens.total)} tokens`:null,s?.cost!==void 0?`$${s.cost.toFixed(2)}`:null,s?.contextUsage?.percent!=null?`context ${s.contextUsage.percent}%`:null].filter(Boolean);return a.length?a.join(" \xB7 "):"no stats yet"}}];document.title="Pi Mirror";new g6t({root:new sie({title:"Pi Mirror",pills:[new cie],composer:new oie(KSt)}),id:"app"});
|
|
1942
1942
|
/*! Bundled license information:
|
|
1943
1943
|
|
|
1944
1944
|
dompurify/dist/purify.es.mjs:
|