typebulb 0.59.1 → 0.59.2
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 +1 -1
- package/dist/agents/codex/client.js +1 -1
- package/dist/agents/pi/client.js +1 -1
- package/dist/ai/aiProvider.d.ts +1 -1
- package/dist/ai/aiProvider.d.ts.map +1 -1
- package/dist/ai/aiProviders.d.ts +0 -1
- package/dist/ai/aiProviders.d.ts.map +1 -1
- package/dist/ai/aiProviders.js +1 -1
- package/dist/ai/aiProviders.js.map +1 -1
- package/dist/ai/providers/openRouter.d.ts +7 -1
- package/dist/ai/providers/openRouter.d.ts.map +1 -1
- package/dist/ai/providers/openRouter.js +9 -9
- package/dist/ai/providers/openRouter.js.map +1 -1
- package/dist/index.js +196 -196
- package/dist/servers.js +23 -23
- 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.59.
|
|
4
|
+
version: 0.59.2
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
> Generated from typebulb v0.59.
|
|
7
|
+
> Generated from typebulb v0.59.2. `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
|
|
|
@@ -2188,7 +2188,7 @@ ${MCt(b)}`};let v=SCt(d.code,{jsxImportSource:p.ts?.jsxImportSource});if(v.error
|
|
|
2188
2188
|
`)}),d.push({kind:"bulb",source:b.source}),p=b.end);return p<s.length&&d.push({kind:"md",text:s.slice(p).join(`
|
|
2189
2189
|
`)}),d}var Xre=class extends y4{sessions=[];keepOpenSelector=".sid-wrap";filterId="session-filter";listSelector="#session-list";filterNoun="title";#e=new Map;#n=!1;#t=null;#r=new Map;search(s){return tb.server.searchSessions(s)}onActivate(s){let a=this.rows()[s];a&&this.pick(a.sessionId)}filtered(){let s=this.filter.trim().toLowerCase();return s?this.sessions.filter(a=>a.preview.toLowerCase().includes(s)):this.sessions}rows(){return this.searchActive?this.results:this.filtered()}currentIndex(){let s=this.rows(),a=s.findIndex(d=>d.sessionId===this.parent.sessionId);return a<0?s.length-1:a}async loadSessions(){this.sessions=(await tb.server.listSessions()).reverse(),this.#i(),this.parent.updateTitle()}#i(){let s=this.parent.sessionId;for(let a of this.sessions)(!this.#n||a.sessionId===s)&&this.#e.set(a.sessionId,a.mtime);this.#n=!0}#s(s){if(s.sessionId===this.parent.sessionId)return!1;let a=this.#e.get(s.sessionId);return a===void 0||s.mtime>a}onAttached(){this.loadSessions().then(()=>this.update()).catch(()=>{})}currentRow(){return this.sessions.find(s=>s.sessionId===this.parent.sessionId)}currentPreview(){return this.currentRow()?.preview?.trim()??""}async show(){this.beginOpen(),this.refreshList(this.currentIndex()),this.focusFilter();try{await this.loadSessions(),this.refreshList(this.currentIndex())}catch(s){console.error("[mirror] listSessions failed",s)}this.armClose()}async pick(s){let a=this.rows().find(d=>d.sessionId===s);a&&this.#e.set(s,a.mtime),this.close(),this.parent.messageList.stickToBottomNextRender(),await tb.server.attach(s)}view(){let s=this.parent;if(s.sessionId===null)return _t({class:"sid-wrap"});let a=s.sessionId==="",d=a?"new conversation":this.currentPreview()||"current",p=tte(d,25),b=`${s.cwd}
|
|
2190
2190
|
${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session: ${s.sessionId}`}`;return _t({class:"sid-wrap"},Yo({class:"pill","data-tip":b,onClick:v=>{v.stopPropagation(),this.open?this.close():this.show()}},p),this.open?this.picker():null)}picker(){let s=this.rows();return _t({class:"picker"},_t({class:"picker-body"},s.length===0?this.emptyState("No sessions yet \u2014 start one in your terminal."):_t({id:"session-list",class:"picker-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.pickerRow(a,d))),this.peekCard()),this.filterBox(this.sessions.length,"session"))}pickerRow(s,a){let d=s.sessionId===this.parent.sessionId,p=this.parent.busy.includes(s.sessionId);return _t({class:["picker-row",a===this.highlighted?"active":"",d?"current":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:()=>this.pick(s.sessionId)},_t({class:"picker-row-main"},gr({class:"picker-dot"}),gr({class:["picker-preview",p?"shimmer-text shimmer-slow":""]},s.preview||"(no preview)"),Vee(s.hitCount),gr({class:["picker-time",this.#s(s)?"unseen":""],onMouseEnter:()=>this.#o(s),onMouseLeave:()=>this.#c(s)},ete(s.mtime))),Zee(s.snippet,this.filter.trim()))}#o(s){this.#t=`${s.sessionId}:${s.mtime}`,this.#u(s.sessionId,this.#t),this.update()}#c(s){this.#t===`${s.sessionId}:${s.mtime}`&&(this.#t=null,this.update())}async#u(s,a){if(this.#r.has(a))return;let d="";try{d=String((await tb.server.sessionPeek(s))?.text??"")}catch{}this.#r.set(a,d),this.#t===a&&this.update()}peekCard(){if(!this.#t)return null;let s=this.#r.get(this.#t);return s===void 0?_t({class:"picker-peek muted"},"\u2026"):s?_t({class:"picker-peek md",key:`peek:${this.#t}`,onMounted:a=>{a.innerHTML=eD.render(s)}}):_t({class:"picker-peek muted"},"(no assistant text yet)")}onClosed(){super.onClosed(),this.#t=null}};var Vre=class extends Ia{get parent(){return this.ctx.parent}view(){let s=this.parent.tokens,a=this.parent.stats,d=a?a.contextTokens??0:s.in+s.out+s.cached+s.cacheCreate,p=a?.cost??this.parent.cost,b=this.parent.working,v=p>0?`$${p>=1?p.toFixed(2):p.toFixed(3)}`:"",w=[];if(d>0&&w.push(Wye(d)),a&&a.contextPercent!=null&&w.push(`${Math.round(a.contextPercent)}%`),v&&w.push(v),!w.length&&!b)return gr({class:"token-wrap"});let I=w.length?w.length===1&&d>0?`${w[0]} tokens`:w.join(" \xB7 "):"working\u2026",T=w.length?[d>0?`${Wye(d)} tokens in the context window`:"",a&&a.contextPercent!=null?`${Math.round(a.contextPercent)}% of the model\u2019s window`:"",v?`${v} spent this session`:""].filter(Boolean).join(`
|
|
2191
|
-
`):"Waiting for the harness to flush this turn";return gr({class:"token-wrap"},gr({class:["token",C6t(b)],"data-tip":T},I))}};var GSt={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var Xvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Vvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},Zvn=o=>{let s=Vvn[o]??GSt[Xvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},_3=(o,s="")=>gr({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=Zvn(o)}},"");function QSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var e5n=()=>_3("play","btn-icon"),t5n=()=>_3("stop","btn-icon"),n5n=o=>`typebulbs/u/samples/${o}.bulb.md`,rD=o=>Gh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],r5n=(o,s)=>`https://typebulb.com/u/${s}/${aM(o.path)}/full`,JSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",Zre=class extends y4{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?SF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Gh(p.path)),d=[...this.samples.map(p=>[n5n(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Gh(p.file),v=aM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Gh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Gh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=_6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Gh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>rD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&rD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return QSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Gh(d.path)===Gh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Gh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=rD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,JSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Gh(v.path).endsWith("/"+Gh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,JSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Gh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(rD(s),aM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p)}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Gh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&SF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Gh(d.path)===Gh(s))?.name||aM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#n(),this.#e=setInterval(()=>this.#n(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#n(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return _t({class:"servers-wrap"});let d=this.pendingDenial();return _t({class:"servers-wrap"},Yo({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:gr({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return _t({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},_t({class:"trust-modal",onClick:d=>d.stopPropagation()},_t({class:"trust-modal-h"},s.heading),_t({class:"trust-modal-b"},s.body),_t({class:"trust-modal-warn"},s.warn),_t({class:"trust-modal-acts"},Yo({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),Yo({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=aM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return _t({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):_t({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return _t({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},_t({class:"bulb-log-head"},gr({class:"bulb-log-name"},`console \xB7 ${s.name}`),Yo({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),i6({class:"bulb-log-body"},gr({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Gh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return _t({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?Yo({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},t5n()):Yo({class:["bulb-launch",this.launching.has(Gh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},e5n()),_t({class:"bulb-name-cell"},s.remote?gr({class:"server-name stopped remote",title:s.remote.description},s.name):gr({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),Vee(s.hitCount),v?gr({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):gr({class:"cell-empty"}),p?gC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):gr({class:"cell-empty"}),p?gC({class:"server-port",href:zye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?gr({class:"cell-empty"}):gr({class:"bulb-time"},ete(s.recent)),Zee(s.snippet,this.filter.trim()))}userLink(s){let a=rD(s);return a?gC({class:"sample-link",href:r5n(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=rD(s);if(!a||s.remote)return gr({class:"cell-empty"});let d=(p,b)=>{let v=`${Gh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return Yo({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},_3(I?"check":p,"btn-icon-sm"))};return gr({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return _t({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},gr({class:"fold-caret"},_3("caret",["caret-tri",v?"open":""])),gr({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return Yo({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var eie=class{#e;#n;#t;#r=!1;#i;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#n=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#n=void 0,this.#t=void 0}sync(){this.#r||(this.#r=!0,requestAnimationFrame(()=>{this.#r=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#n?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return _t({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},_t({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>_t({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#i=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#i===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#i=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#i??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var i5n=4e5,rEe="diff-doc-body";function s5n(o,s){let a=o.split(`
|
|
2191
|
+
`):"Waiting for the harness to flush this turn";return gr({class:"token-wrap"},gr({class:["token",C6t(b)],"data-tip":T},I))}};var GSt={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var Xvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Vvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},Zvn=o=>{let s=Vvn[o]??GSt[Xvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},_3=(o,s="")=>gr({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=Zvn(o)}},"");function QSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var e5n=()=>_3("play","btn-icon"),t5n=()=>_3("stop","btn-icon"),n5n=o=>`typebulbs/u/samples/${o}.bulb.md`,rD=o=>Gh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],r5n=(o,s)=>`https://typebulb.com/u/${s}/${aM(o.path)}/full`,JSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",Zre=class extends y4{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?SF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Gh(p.path)),d=[...this.samples.map(p=>[n5n(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Gh(p.file),v=aM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Gh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Gh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=_6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Gh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>rD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&rD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return QSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Gh(d.path)===Gh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Gh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=rD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,JSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Gh(v.path).endsWith("/"+Gh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,JSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Gh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(rD(s),aM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p),this.update()}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Gh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&SF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Gh(d.path)===Gh(s))?.name||aM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#n(),this.#e=setInterval(()=>this.#n(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#n(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return _t({class:"servers-wrap"});let d=this.pendingDenial();return _t({class:"servers-wrap"},Yo({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:gr({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return _t({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},_t({class:"trust-modal",onClick:d=>d.stopPropagation()},_t({class:"trust-modal-h"},s.heading),_t({class:"trust-modal-b"},s.body),_t({class:"trust-modal-warn"},s.warn),_t({class:"trust-modal-acts"},Yo({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),Yo({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=aM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return _t({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):_t({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return _t({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},_t({class:"bulb-log-head"},gr({class:"bulb-log-name"},`console \xB7 ${s.name}`),Yo({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),i6({class:"bulb-log-body"},gr({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Gh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return _t({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?Yo({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},t5n()):Yo({class:["bulb-launch",this.launching.has(Gh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},e5n()),_t({class:"bulb-name-cell"},s.remote?gr({class:"server-name stopped remote",title:s.remote.description},s.name):gr({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),Vee(s.hitCount),v?gr({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):gr({class:"cell-empty"}),p?gC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):gr({class:"cell-empty"}),p?gC({class:"server-port",href:zye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?gr({class:"cell-empty"}):gr({class:"bulb-time"},ete(s.recent)),Zee(s.snippet,this.filter.trim()))}userLink(s){let a=rD(s);return a?gC({class:"sample-link",href:r5n(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=rD(s);if(!a||s.remote)return gr({class:"cell-empty"});let d=(p,b)=>{let v=`${Gh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return Yo({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},_3(I?"check":p,"btn-icon-sm"))};return gr({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return _t({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},gr({class:"fold-caret"},_3("caret",["caret-tri",v?"open":""])),gr({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return Yo({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var eie=class{#e;#n;#t;#r=!1;#i;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#n=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#n=void 0,this.#t=void 0}sync(){this.#r||(this.#r=!0,requestAnimationFrame(()=>{this.#r=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#n?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return _t({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},_t({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>_t({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#i=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#i===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#i=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#i??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var i5n=4e5,rEe="diff-doc-body";function s5n(o,s){let a=o.split(`
|
|
2192
2192
|
`).map(v=>v.replace(/\r$/,""));if(a.length&&a[a.length-1]===""&&a.pop(),s)return a.map(v=>({kind:"add",text:v}));let d=[],p=!1,b=!1;for(let v of a){if(v.startsWith("@@")){b&&d.push({kind:"gap",text:"\u22EF"}),b=!0,p=!0;continue}if(!p){v.startsWith("Binary file")&&d.push({kind:"ctx",text:v});continue}v.startsWith("\\")||(v.startsWith("+")?d.push({kind:"add",text:v.slice(1)}):v.startsWith("-")?d.push({kind:"del",text:v.slice(1)}):d.push({kind:"ctx",text:v.slice(1)}))}return d}function o5n(o,s,a){let d=s5n(o,s),p=o.length>i5n?"txt":a.split(".").pop()??"",b=[],v=[];for(let P of d)(P.kind==="ctx"||P.kind==="del")&&b.push(P.text),(P.kind==="ctx"||P.kind==="add")&&v.push(P.text);let w=eEe(b.join(`
|
|
2193
2193
|
`),p),I=eEe(v.join(`
|
|
2194
2194
|
`),p),T=0,B=0,D=[];for(let P of d){if(P.kind==="gap"){D.push('<div class="udiff-gap">\u22EF</div>');continue}let F=P.kind==="del"?w[T++]:(P.kind==="add"||T++,I[B++]);D.push(`<div class="udiff-line${P.kind==="add"?" udiff-add":P.kind==="del"?" udiff-del":""}">${F??""}</div>`)}return{kinds:d.map(P=>P.kind),bodyHtml:D.join("")}}var tie=class extends y4{files=[];repo=!0;root="";viewing;#e=0;#n=!1;#t=()=>document.getElementById(rEe);#r=new eie(this.#t);#i=[];#s=-1;keepOpenSelector=".gitdiff-wrap";filterId="gitdiff-filter";listSelector=".gitdiff-list";filterNoun="file";search(){return Promise.resolve([])}onActivate(s){let a=this.rows()[s];a&&this.openDiff(a)}onAttached(){this.refreshFiles(),setInterval(()=>this.refreshFiles(),3e3),setInterval(()=>{this.viewing&&this.refreshDiff()},1500)}rows(){let s=this.filter.trim().toLowerCase();return s?this.files.filter(a=>a.path.toLowerCase().includes(s)):this.files}async refreshFiles(){try{let{repo:s,root:a,files:d}=await tb.server.gitChangedFiles(),p=s!==this.repo||d.length!==this.files.length||d.some((b,v)=>{let w=this.files[v];return b.path!==w?.path||b.status!==w.status||b.add!==w.add||b.del!==w.del||b.binary!==w.binary});this.repo=s,this.root=a,this.files=d,p&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] gitChangedFiles failed",s)}}#o(s,a,d){this.viewing?.path!==s&&(this.#i=[]),this.viewing={path:s,status:a,text:d.text,truncated:!!d.truncated,...o5n(d.text,!!d.untracked,s)},this.#e++,this.update()}async openDiff(s){try{let a=await tb.server.gitDiff(s.path);if(!a.ok){console.error("[mirror] gitDiff failed:",a.error);return}this.#o(s.path,s.status,a),this.#n=!0,this.close()}catch(a){console.error("[mirror] gitDiff failed",a)}}async refreshDiff(){let s=this.viewing;if(s)try{let a=await tb.server.gitDiff(s.path);if(this.viewing!==s||!a.ok||a.text===s.text)return;this.#o(s.path,s.status,a)}catch(a){console.error("[mirror] gitDiff refresh failed",a)}}closeDoc(){this.#r.release(),this.viewing=void 0,this.update()}show(){this.beginOpen(),this.refreshFiles(),this.refreshList(),this.armClose(),this.focusFilter()}view(){let s=this.files.length;return!this.repo||s===0&&!this.viewing&&!this.open?_t({class:"gitdiff-wrap"}):_t({class:"gitdiff-wrap pop-center"},this.viewing?this.viewingPill():Yo({class:["pill","glyph","gitdiff-pill",this.open?"on":""],"data-tip":`${s} changed file${s===1?"":"s"} \u2014 view a diff`,ariaLabel:`${s} changed file${s===1?"":"s"}`,onClick:a=>{a.stopPropagation(),this.open?this.close():this.show()}},_3("diff"),gr({class:"gitdiff-count"},String(s))),this.open?this.popup():null)}viewingPill(){let s=this.viewing,a=s.kinds.filter(p=>p==="add").length,d=s.kinds.filter(p=>p==="del").length;return Yo({class:["pill","glyph","gitdiff-pill","viewing","on"],"data-tip":`${this.files.length} changed file${this.files.length===1?"":"s"} \u2014 switch file`,onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},gr({class:["gitdiff-status",`s-${s.status}`]},s.status),gr({class:"gitdiff-doc-path",title:`Open ${s.path}`,onClick:p=>{p.stopPropagation(),tb.server.openFile(`${this.root}/${s.path}`)}},s.path),gr({class:"gitdiff-counts"},gr({class:"count-add"},`+${a}`),gr({class:"count-del"},`\u2212${d}`)),gr({class:"gitdiff-close","data-tip":"Back to the conversation (Esc)",ariaLabel:"Back to the conversation",onClick:p=>{p.stopPropagation(),this.closeDoc()}},_3("close")))}popup(){let s=this.rows();return _t({class:"servers-pop gitdiff-pop"},s.length===0?this.emptyState("No changes in the working tree."):_t({class:"gitdiff-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.row(a,d))),this.filterRow())}filterRow(){let s=this.files.length;return Xee({target:this,prop:()=>this.filter,id:this.filterId,placeholder:s?`Filter ${s} file${s===1?"":"s"}\u2026`:"Filter files\u2026",hasValue:!!this.filter,onKeyDown:a=>this.onFilterKey(a),onClear:()=>this.clearFilter()})}row(s,a){return _t({class:["gitdiff-row",a===this.highlighted?"active":"",this.viewing?.path===s.path?"viewing":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:d=>{d.stopPropagation(),this.openDiff(s)}},gr({class:["gitdiff-status",`s-${s.status}`]},s.status),gr({class:"gitdiff-path",title:s.path},s.path),s.add!==void 0||s.del!==void 0?gr({class:"gitdiff-counts"},gr({class:"count-add"},`+${s.add??0}`),gr({class:"count-del"},`\u2212${s.del??0}`)):s.status==="U"?gr({class:"gitdiff-counts"},gr({class:"count-add"},"new")):gr({class:"gitdiff-counts"},gr({},s.binary?"binary":"\u2014")))}docView(){let s=this.viewing;return _t({class:"diff-doc",onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeDoc())}},_t({class:"diff-doc-scroll"},_t({class:"diff-doc-body",id:rEe,tabIndex:0,onMounted:a=>a.focus(),onScroll:()=>this.#r.sync()},s.kinds.length===0?_t({class:"diff-doc-empty"},"No changes."):_t({class:"diff-doc-code",key:`diff-code-${this.#e}`,onMounted:a=>{a.innerHTML=s.bodyHtml,this.#c(a),this.#u(a)}},""),s.truncated?_t({class:"diff-doc-trunc"},"Diff truncated \u2014 file too large to show in full."):null),s.kinds.length?this.#r.view(this.#i,{class:"diff-ruler",title:"Jump to a change",label:"Diff scroll position",controls:rEe}):null))}#c(s){if(!this.#n)return;this.#n=!1;let a=s.querySelector(".udiff-add, .udiff-del"),d=this.#t();a&&d&&(d.scrollTop=a.offsetTop-d.clientHeight/3)}#u(s){this.#s!==this.#e&&(this.#s=this.#e,requestAnimationFrame(()=>{this.#f(s),this.update(),this.#r.sync()}))}#f(s){let a=this.viewing,d=this.#t();if(!a||!d?.scrollHeight)return;let p=d.scrollHeight,b=[];for(let v=0;v<a.kinds.length;v++){let w=a.kinds[v];if(w!=="add"&&w!=="del")continue;let I=v;for(;I+1<a.kinds.length&&a.kinds[I+1]===w;)I++;let T=s.children[v],B=s.children[I];T&&B&&b.push({top:T.offsetTop/p,height:(B.offsetTop+B.offsetHeight-T.offsetTop)/p,class:w}),v=I}this.#i=b}};var iD=class extends Ia{done=!1;#e;constructor(s){super(),this.#e=s}setText(s){this.#e=s}flash(){navigator.clipboard?.writeText(this.#e),this.done=!0,this.update(),setTimeout(()=>{this.done=!1,this.update()},600)}view(){return Yo({class:["overlay-pill","copy",this.done?"done":""],onClick:s=>{s.stopPropagation(),this.flash()}},this.done?"copied":"copy")}};var USt=new Map,zSt=(o,s)=>s+`
|
|
@@ -2188,7 +2188,7 @@ ${vCt(b)}`};let v=mCt(d.code,{jsxImportSource:p.ts?.jsxImportSource});if(v.error
|
|
|
2188
2188
|
`)}),d.push({kind:"bulb",source:b.source}),p=b.end);return p<s.length&&d.push({kind:"md",text:s.slice(p).join(`
|
|
2189
2189
|
`)}),d}var Wre=class extends M7{sessions=[];keepOpenSelector=".sid-wrap";filterId="session-filter";listSelector="#session-list";filterNoun="title";#e=new Map;#n=!1;#t=null;#r=new Map;search(s){return tb.server.searchSessions(s)}onActivate(s){let a=this.rows()[s];a&&this.pick(a.sessionId)}filtered(){let s=this.filter.trim().toLowerCase();return s?this.sessions.filter(a=>a.preview.toLowerCase().includes(s)):this.sessions}rows(){return this.searchActive?this.results:this.filtered()}currentIndex(){let s=this.rows(),a=s.findIndex(d=>d.sessionId===this.parent.sessionId);return a<0?s.length-1:a}async loadSessions(){this.sessions=(await tb.server.listSessions()).reverse(),this.#i(),this.parent.updateTitle()}#i(){let s=this.parent.sessionId;for(let a of this.sessions)(!this.#n||a.sessionId===s)&&this.#e.set(a.sessionId,a.mtime);this.#n=!0}#s(s){if(s.sessionId===this.parent.sessionId)return!1;let a=this.#e.get(s.sessionId);return a===void 0||s.mtime>a}onAttached(){this.loadSessions().then(()=>this.update()).catch(()=>{})}currentRow(){return this.sessions.find(s=>s.sessionId===this.parent.sessionId)}currentPreview(){return this.currentRow()?.preview?.trim()??""}async show(){this.beginOpen(),this.refreshList(this.currentIndex()),this.focusFilter();try{await this.loadSessions(),this.refreshList(this.currentIndex())}catch(s){console.error("[mirror] listSessions failed",s)}this.armClose()}async pick(s){let a=this.rows().find(d=>d.sessionId===s);a&&this.#e.set(s,a.mtime),this.close(),this.parent.messageList.stickToBottomNextRender(),await tb.server.attach(s)}view(){let s=this.parent;if(s.sessionId===null)return un({class:"sid-wrap"});let a=s.sessionId==="",d=a?"new conversation":this.currentPreview()||"current",p=Zee(d,25),b=`${s.cwd}
|
|
2190
2190
|
${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session: ${s.sessionId}`}`;return un({class:"sid-wrap"},ha({class:"pill","data-tip":b,onClick:v=>{v.stopPropagation(),this.open?this.close():this.show()}},p),this.open?this.picker():null)}picker(){let s=this.rows();return un({class:"picker"},un({class:"picker-body"},s.length===0?this.emptyState("No sessions yet \u2014 start one in your terminal."):un({id:"session-list",class:"picker-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.pickerRow(a,d))),this.peekCard()),this.filterBox(this.sessions.length,"session"))}pickerRow(s,a){let d=s.sessionId===this.parent.sessionId,p=this.parent.busy.includes(s.sessionId);return un({class:["picker-row",a===this.highlighted?"active":"",d?"current":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:()=>this.pick(s.sessionId)},un({class:"picker-row-main"},Nr({class:"picker-dot"}),Nr({class:["picker-preview",p?"shimmer-text shimmer-slow":""]},s.preview||"(no preview)"),Yee(s.hitCount),Nr({class:["picker-time",this.#s(s)?"unseen":""],onMouseEnter:()=>this.#o(s),onMouseLeave:()=>this.#c(s)},Vee(s.mtime))),Xee(s.snippet,this.filter.trim()))}#o(s){this.#t=`${s.sessionId}:${s.mtime}`,this.#u(s.sessionId,this.#t),this.update()}#c(s){this.#t===`${s.sessionId}:${s.mtime}`&&(this.#t=null,this.update())}async#u(s,a){if(this.#r.has(a))return;let d="";try{d=String((await tb.server.sessionPeek(s))?.text??"")}catch{}this.#r.set(a,d),this.#t===a&&this.update()}peekCard(){if(!this.#t)return null;let s=this.#r.get(this.#t);return s===void 0?un({class:"picker-peek muted"},"\u2026"):s?un({class:"picker-peek md",key:`peek:${this.#t}`,onMounted:a=>{a.innerHTML=eD.render(s)}}):un({class:"picker-peek muted"},"(no assistant text yet)")}onClosed(){super.onClosed(),this.#t=null}};var Yre=class extends Ku{get parent(){return this.ctx.parent}view(){let s=this.parent.tokens,a=this.parent.stats,d=a?a.contextTokens??0:s.in+s.out+s.cached+s.cacheCreate,p=a?.cost??this.parent.cost,b=this.parent.working,v=p>0?`$${p>=1?p.toFixed(2):p.toFixed(3)}`:"",w=[];if(d>0&&w.push(Qye(d)),a&&a.contextPercent!=null&&w.push(`${Math.round(a.contextPercent)}%`),v&&w.push(v),!w.length&&!b)return Nr({class:"token-wrap"});let I=w.length?w.length===1&&d>0?`${w[0]} tokens`:w.join(" \xB7 "):"working\u2026",T=w.length?[d>0?`${Qye(d)} tokens in the context window`:"",a&&a.contextPercent!=null?`${Math.round(a.contextPercent)}% of the model\u2019s window`:"",v?`${v} spent this session`:""].filter(Boolean).join(`
|
|
2191
|
-
`):"Waiting for the harness to flush this turn";return Nr({class:"token-wrap"},Nr({class:["token",g6t(b)],"data-tip":T},I))}};var LSt={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var jvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Fvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},$vn=o=>{let s=Fvn[o]??LSt[jvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},T3=(o,s="")=>Nr({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=$vn(o)}},"");function NSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var Hvn=()=>T3("play","btn-icon"),qvn=()=>T3("stop","btn-icon"),Gvn=o=>`typebulbs/u/samples/${o}.bulb.md`,rD=o=>Gh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],Qvn=(o,s)=>`https://typebulb.com/u/${s}/${aM(o.path)}/full`,RSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",Xre=class extends M7{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?SF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Gh(p.path)),d=[...this.samples.map(p=>[Gvn(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Gh(p.file),v=aM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Gh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Gh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=A6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Gh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>rD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&rD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return NSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Gh(d.path)===Gh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Gh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=rD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,RSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Gh(v.path).endsWith("/"+Gh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,RSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Gh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(rD(s),aM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p)}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Gh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&SF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Gh(d.path)===Gh(s))?.name||aM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#n(),this.#e=setInterval(()=>this.#n(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#n(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return un({class:"servers-wrap"});let d=this.pendingDenial();return un({class:"servers-wrap"},ha({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:Nr({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return un({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},un({class:"trust-modal",onClick:d=>d.stopPropagation()},un({class:"trust-modal-h"},s.heading),un({class:"trust-modal-b"},s.body),un({class:"trust-modal-warn"},s.warn),un({class:"trust-modal-acts"},ha({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),ha({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=aM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return un({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):un({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return un({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},un({class:"bulb-log-head"},Nr({class:"bulb-log-name"},`console \xB7 ${s.name}`),ha({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),r6({class:"bulb-log-body"},Nr({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Gh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return un({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?ha({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},qvn()):ha({class:["bulb-launch",this.launching.has(Gh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},Hvn()),un({class:"bulb-name-cell"},s.remote?Nr({class:"server-name stopped remote",title:s.remote.description},s.name):Nr({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),Yee(s.hitCount),v?Nr({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):Nr({class:"cell-empty"}),p?gC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):Nr({class:"cell-empty"}),p?gC({class:"server-port",href:qye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?Nr({class:"cell-empty"}):Nr({class:"bulb-time"},Vee(s.recent)),Xee(s.snippet,this.filter.trim()))}userLink(s){let a=rD(s);return a?gC({class:"sample-link",href:Qvn(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=rD(s);if(!a||s.remote)return Nr({class:"cell-empty"});let d=(p,b)=>{let v=`${Gh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return ha({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},T3(I?"check":p,"btn-icon-sm"))};return Nr({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return un({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},Nr({class:"fold-caret"},T3("caret",["caret-tri",v?"open":""])),Nr({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return ha({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var Vre=class{#e;#n;#t;#r=!1;#i;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#n=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#n=void 0,this.#t=void 0}sync(){this.#r||(this.#r=!0,requestAnimationFrame(()=>{this.#r=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#n?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return un({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},un({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>un({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#i=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#i===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#i=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#i??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var Jvn=4e5,Vxe="diff-doc-body";function Uvn(o,s){let a=o.split(`
|
|
2191
|
+
`):"Waiting for the harness to flush this turn";return Nr({class:"token-wrap"},Nr({class:["token",g6t(b)],"data-tip":T},I))}};var LSt={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var jvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Fvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},$vn=o=>{let s=Fvn[o]??LSt[jvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},T3=(o,s="")=>Nr({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=$vn(o)}},"");function NSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var Hvn=()=>T3("play","btn-icon"),qvn=()=>T3("stop","btn-icon"),Gvn=o=>`typebulbs/u/samples/${o}.bulb.md`,rD=o=>Gh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],Qvn=(o,s)=>`https://typebulb.com/u/${s}/${aM(o.path)}/full`,RSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",Xre=class extends M7{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?SF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Gh(p.path)),d=[...this.samples.map(p=>[Gvn(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Gh(p.file),v=aM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Gh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Gh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=A6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Gh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>rD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&rD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return NSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Gh(d.path)===Gh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Gh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=rD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,RSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Gh(v.path).endsWith("/"+Gh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,RSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Gh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(rD(s),aM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p),this.update()}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Gh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&SF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Gh(d.path)===Gh(s))?.name||aM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#n(),this.#e=setInterval(()=>this.#n(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#n(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return un({class:"servers-wrap"});let d=this.pendingDenial();return un({class:"servers-wrap"},ha({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:Nr({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return un({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},un({class:"trust-modal",onClick:d=>d.stopPropagation()},un({class:"trust-modal-h"},s.heading),un({class:"trust-modal-b"},s.body),un({class:"trust-modal-warn"},s.warn),un({class:"trust-modal-acts"},ha({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),ha({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=aM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return un({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):un({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return un({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},un({class:"bulb-log-head"},Nr({class:"bulb-log-name"},`console \xB7 ${s.name}`),ha({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),r6({class:"bulb-log-body"},Nr({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Gh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return un({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?ha({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},qvn()):ha({class:["bulb-launch",this.launching.has(Gh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},Hvn()),un({class:"bulb-name-cell"},s.remote?Nr({class:"server-name stopped remote",title:s.remote.description},s.name):Nr({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),Yee(s.hitCount),v?Nr({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):Nr({class:"cell-empty"}),p?gC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):Nr({class:"cell-empty"}),p?gC({class:"server-port",href:qye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?Nr({class:"cell-empty"}):Nr({class:"bulb-time"},Vee(s.recent)),Xee(s.snippet,this.filter.trim()))}userLink(s){let a=rD(s);return a?gC({class:"sample-link",href:Qvn(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=rD(s);if(!a||s.remote)return Nr({class:"cell-empty"});let d=(p,b)=>{let v=`${Gh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return ha({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},T3(I?"check":p,"btn-icon-sm"))};return Nr({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return un({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},Nr({class:"fold-caret"},T3("caret",["caret-tri",v?"open":""])),Nr({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return ha({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var Vre=class{#e;#n;#t;#r=!1;#i;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#n=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#n=void 0,this.#t=void 0}sync(){this.#r||(this.#r=!0,requestAnimationFrame(()=>{this.#r=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#n?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return un({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},un({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>un({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#i=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#i===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#i=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#i??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var Jvn=4e5,Vxe="diff-doc-body";function Uvn(o,s){let a=o.split(`
|
|
2192
2192
|
`).map(v=>v.replace(/\r$/,""));if(a.length&&a[a.length-1]===""&&a.pop(),s)return a.map(v=>({kind:"add",text:v}));let d=[],p=!1,b=!1;for(let v of a){if(v.startsWith("@@")){b&&d.push({kind:"gap",text:"\u22EF"}),b=!0,p=!0;continue}if(!p){v.startsWith("Binary file")&&d.push({kind:"ctx",text:v});continue}v.startsWith("\\")||(v.startsWith("+")?d.push({kind:"add",text:v.slice(1)}):v.startsWith("-")?d.push({kind:"del",text:v.slice(1)}):d.push({kind:"ctx",text:v.slice(1)}))}return d}function zvn(o,s,a){let d=Uvn(o,s),p=o.length>Jvn?"txt":a.split(".").pop()??"",b=[],v=[];for(let P of d)(P.kind==="ctx"||P.kind==="del")&&b.push(P.text),(P.kind==="ctx"||P.kind==="add")&&v.push(P.text);let w=Wxe(b.join(`
|
|
2193
2193
|
`),p),I=Wxe(v.join(`
|
|
2194
2194
|
`),p),T=0,D=0,B=[];for(let P of d){if(P.kind==="gap"){B.push('<div class="udiff-gap">\u22EF</div>');continue}let F=P.kind==="del"?w[T++]:(P.kind==="add"||T++,I[D++]);B.push(`<div class="udiff-line${P.kind==="add"?" udiff-add":P.kind==="del"?" udiff-del":""}">${F??""}</div>`)}return{kinds:d.map(P=>P.kind),bodyHtml:B.join("")}}var Zre=class extends M7{files=[];repo=!0;root="";viewing;#e=0;#n=!1;#t=()=>document.getElementById(Vxe);#r=new Vre(this.#t);#i=[];#s=-1;keepOpenSelector=".gitdiff-wrap";filterId="gitdiff-filter";listSelector=".gitdiff-list";filterNoun="file";search(){return Promise.resolve([])}onActivate(s){let a=this.rows()[s];a&&this.openDiff(a)}onAttached(){this.refreshFiles(),setInterval(()=>this.refreshFiles(),3e3),setInterval(()=>{this.viewing&&this.refreshDiff()},1500)}rows(){let s=this.filter.trim().toLowerCase();return s?this.files.filter(a=>a.path.toLowerCase().includes(s)):this.files}async refreshFiles(){try{let{repo:s,root:a,files:d}=await tb.server.gitChangedFiles(),p=s!==this.repo||d.length!==this.files.length||d.some((b,v)=>{let w=this.files[v];return b.path!==w?.path||b.status!==w.status||b.add!==w.add||b.del!==w.del||b.binary!==w.binary});this.repo=s,this.root=a,this.files=d,p&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] gitChangedFiles failed",s)}}#o(s,a,d){this.viewing?.path!==s&&(this.#i=[]),this.viewing={path:s,status:a,text:d.text,truncated:!!d.truncated,...zvn(d.text,!!d.untracked,s)},this.#e++,this.update()}async openDiff(s){try{let a=await tb.server.gitDiff(s.path);if(!a.ok){console.error("[mirror] gitDiff failed:",a.error);return}this.#o(s.path,s.status,a),this.#n=!0,this.close()}catch(a){console.error("[mirror] gitDiff failed",a)}}async refreshDiff(){let s=this.viewing;if(s)try{let a=await tb.server.gitDiff(s.path);if(this.viewing!==s||!a.ok||a.text===s.text)return;this.#o(s.path,s.status,a)}catch(a){console.error("[mirror] gitDiff refresh failed",a)}}closeDoc(){this.#r.release(),this.viewing=void 0,this.update()}show(){this.beginOpen(),this.refreshFiles(),this.refreshList(),this.armClose(),this.focusFilter()}view(){let s=this.files.length;return!this.repo||s===0&&!this.viewing&&!this.open?un({class:"gitdiff-wrap"}):un({class:"gitdiff-wrap pop-center"},this.viewing?this.viewingPill():ha({class:["pill","glyph","gitdiff-pill",this.open?"on":""],"data-tip":`${s} changed file${s===1?"":"s"} \u2014 view a diff`,ariaLabel:`${s} changed file${s===1?"":"s"}`,onClick:a=>{a.stopPropagation(),this.open?this.close():this.show()}},T3("diff"),Nr({class:"gitdiff-count"},String(s))),this.open?this.popup():null)}viewingPill(){let s=this.viewing,a=s.kinds.filter(p=>p==="add").length,d=s.kinds.filter(p=>p==="del").length;return ha({class:["pill","glyph","gitdiff-pill","viewing","on"],"data-tip":`${this.files.length} changed file${this.files.length===1?"":"s"} \u2014 switch file`,onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},Nr({class:["gitdiff-status",`s-${s.status}`]},s.status),Nr({class:"gitdiff-doc-path",title:`Open ${s.path}`,onClick:p=>{p.stopPropagation(),tb.server.openFile(`${this.root}/${s.path}`)}},s.path),Nr({class:"gitdiff-counts"},Nr({class:"count-add"},`+${a}`),Nr({class:"count-del"},`\u2212${d}`)),Nr({class:"gitdiff-close","data-tip":"Back to the conversation (Esc)",ariaLabel:"Back to the conversation",onClick:p=>{p.stopPropagation(),this.closeDoc()}},T3("close")))}popup(){let s=this.rows();return un({class:"servers-pop gitdiff-pop"},s.length===0?this.emptyState("No changes in the working tree."):un({class:"gitdiff-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.row(a,d))),this.filterRow())}filterRow(){let s=this.files.length;return Wee({target:this,prop:()=>this.filter,id:this.filterId,placeholder:s?`Filter ${s} file${s===1?"":"s"}\u2026`:"Filter files\u2026",hasValue:!!this.filter,onKeyDown:a=>this.onFilterKey(a),onClear:()=>this.clearFilter()})}row(s,a){return un({class:["gitdiff-row",a===this.highlighted?"active":"",this.viewing?.path===s.path?"viewing":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:d=>{d.stopPropagation(),this.openDiff(s)}},Nr({class:["gitdiff-status",`s-${s.status}`]},s.status),Nr({class:"gitdiff-path",title:s.path},s.path),s.add!==void 0||s.del!==void 0?Nr({class:"gitdiff-counts"},Nr({class:"count-add"},`+${s.add??0}`),Nr({class:"count-del"},`\u2212${s.del??0}`)):s.status==="U"?Nr({class:"gitdiff-counts"},Nr({class:"count-add"},"new")):Nr({class:"gitdiff-counts"},Nr({},s.binary?"binary":"\u2014")))}docView(){let s=this.viewing;return un({class:"diff-doc",onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeDoc())}},un({class:"diff-doc-scroll"},un({class:"diff-doc-body",id:Vxe,tabIndex:0,onMounted:a=>a.focus(),onScroll:()=>this.#r.sync()},s.kinds.length===0?un({class:"diff-doc-empty"},"No changes."):un({class:"diff-doc-code",key:`diff-code-${this.#e}`,onMounted:a=>{a.innerHTML=s.bodyHtml,this.#c(a),this.#u(a)}},""),s.truncated?un({class:"diff-doc-trunc"},"Diff truncated \u2014 file too large to show in full."):null),s.kinds.length?this.#r.view(this.#i,{class:"diff-ruler",title:"Jump to a change",label:"Diff scroll position",controls:Vxe}):null))}#c(s){if(!this.#n)return;this.#n=!1;let a=s.querySelector(".udiff-add, .udiff-del"),d=this.#t();a&&d&&(d.scrollTop=a.offsetTop-d.clientHeight/3)}#u(s){this.#s!==this.#e&&(this.#s=this.#e,requestAnimationFrame(()=>{this.#f(s),this.update(),this.#r.sync()}))}#f(s){let a=this.viewing,d=this.#t();if(!a||!d?.scrollHeight)return;let p=d.scrollHeight,b=[];for(let v=0;v<a.kinds.length;v++){let w=a.kinds[v];if(w!=="add"&&w!=="del")continue;let I=v;for(;I+1<a.kinds.length&&a.kinds[I+1]===w;)I++;let T=s.children[v],D=s.children[I];T&&D&&b.push({top:T.offsetTop/p,height:(D.offsetTop+D.offsetHeight-T.offsetTop)/p,class:w}),v=I}this.#i=b}};var iD=class extends Ku{done=!1;#e;constructor(s){super(),this.#e=s}setText(s){this.#e=s}flash(){navigator.clipboard?.writeText(this.#e),this.done=!0,this.update(),setTimeout(()=>{this.done=!1,this.update()},600)}view(){return ha({class:["overlay-pill","copy",this.done?"done":""],onClick:s=>{s.stopPropagation(),this.flash()}},this.done?"copied":"copy")}};var OSt=new Map,PSt=(o,s)=>s+`
|
package/dist/agents/pi/client.js
CHANGED
|
@@ -2188,7 +2188,7 @@ ${SCt(b)}`};let v=ECt(d.code,{jsxImportSource:p.ts?.jsxImportSource});if(v.error
|
|
|
2188
2188
|
`)}),d.push({kind:"bulb",source:b.source}),p=b.end);return p<s.length&&d.push({kind:"md",text:s.slice(p).join(`
|
|
2189
2189
|
`)}),d}var Zre=class extends Dk{sessions=[];keepOpenSelector=".sid-wrap";filterId="session-filter";listSelector="#session-list";filterNoun="title";#e=new Map;#i=!1;#t=null;#n=new Map;search(s){return tb.server.searchSessions(s)}onActivate(s){let a=this.rows()[s];a&&this.pick(a.sessionId)}filtered(){let s=this.filter.trim().toLowerCase();return s?this.sessions.filter(a=>a.preview.toLowerCase().includes(s)):this.sessions}rows(){return this.searchActive?this.results:this.filtered()}currentIndex(){let s=this.rows(),a=s.findIndex(d=>d.sessionId===this.parent.sessionId);return a<0?s.length-1:a}async loadSessions(){this.sessions=(await tb.server.listSessions()).reverse(),this.#r(),this.parent.updateTitle()}#r(){let s=this.parent.sessionId;for(let a of this.sessions)(!this.#i||a.sessionId===s)&&this.#e.set(a.sessionId,a.mtime);this.#i=!0}#s(s){if(s.sessionId===this.parent.sessionId)return!1;let a=this.#e.get(s.sessionId);return a===void 0||s.mtime>a}onAttached(){this.loadSessions().then(()=>this.update()).catch(()=>{})}currentRow(){return this.sessions.find(s=>s.sessionId===this.parent.sessionId)}currentPreview(){return this.currentRow()?.preview?.trim()??""}async show(){this.beginOpen(),this.refreshList(this.currentIndex()),this.focusFilter();try{await this.loadSessions(),this.refreshList(this.currentIndex())}catch(s){console.error("[mirror] listSessions failed",s)}this.armClose()}async pick(s){let a=this.rows().find(d=>d.sessionId===s);a&&this.#e.set(s,a.mtime),this.close(),this.parent.messageList.stickToBottomNextRender(),await tb.server.attach(s)}view(){let s=this.parent;if(s.sessionId===null)return Gt({class:"sid-wrap"});let a=s.sessionId==="",d=a?"new conversation":this.currentPreview()||"current",p=fM(d,25),b=`${s.cwd}
|
|
2190
2190
|
${a||this.currentRow()?.pending?"New conversation \u2014 not saved yet":`Session: ${s.sessionId}`}`;return Gt({class:"sid-wrap"},uc({class:"pill","data-tip":b,onClick:v=>{v.stopPropagation(),this.open?this.close():this.show()}},p),this.open?this.picker():null)}picker(){let s=this.rows();return Gt({class:"picker"},Gt({class:"picker-body"},s.length===0?this.emptyState("No sessions yet \u2014 start one in your terminal."):Gt({id:"session-list",class:"picker-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.pickerRow(a,d))),this.peekCard()),this.filterBox(this.sessions.length,"session"))}pickerRow(s,a){let d=s.sessionId===this.parent.sessionId,p=this.parent.busy.includes(s.sessionId);return Gt({class:["picker-row",a===this.highlighted?"active":"",d?"current":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:()=>this.pick(s.sessionId)},Gt({class:"picker-row-main"},Ir({class:"picker-dot"}),Ir({class:["picker-preview",p?"shimmer-text shimmer-slow":""]},s.preview||"(no preview)"),tte(s.hitCount),Ir({class:["picker-time",this.#s(s)?"unseen":""],onMouseEnter:()=>this.#o(s),onMouseLeave:()=>this.#c(s)},rte(s.mtime))),nte(s.snippet,this.filter.trim()))}#o(s){this.#t=`${s.sessionId}:${s.mtime}`,this.#u(s.sessionId,this.#t),this.update()}#c(s){this.#t===`${s.sessionId}:${s.mtime}`&&(this.#t=null,this.update())}async#u(s,a){if(this.#n.has(a))return;let d="";try{d=String((await tb.server.sessionPeek(s))?.text??"")}catch{}this.#n.set(a,d),this.#t===a&&this.update()}peekCard(){if(!this.#t)return null;let s=this.#n.get(this.#t);return s===void 0?Gt({class:"picker-peek muted"},"\u2026"):s?Gt({class:"picker-peek md",key:`peek:${this.#t}`,onMounted:a=>{a.innerHTML=rD.render(s)}}):Gt({class:"picker-peek muted"},"(no assistant text yet)")}onClosed(){super.onClosed(),this.#t=null}};var eie=class extends wu{get parent(){return this.ctx.parent}view(){let s=this.parent.tokens,a=this.parent.stats,d=a?a.contextTokens??0:s.in+s.out+s.cached+s.cacheCreate,p=a?.cost??this.parent.cost,b=this.parent.working,v=p>0?`$${p>=1?p.toFixed(2):p.toFixed(3)}`:"",w=[];if(d>0&&w.push(BF(d)),a&&a.contextPercent!=null&&w.push(`${Math.round(a.contextPercent)}%`),v&&w.push(v),!w.length&&!b)return Ir({class:"token-wrap"});let I=w.length?w.length===1&&d>0?`${w[0]} tokens`:w.join(" \xB7 "):"working\u2026",T=w.length?[d>0?`${BF(d)} tokens in the context window`:"",a&&a.contextPercent!=null?`${Math.round(a.contextPercent)}% of the model\u2019s window`:"",v?`${v} spent this session`:""].filter(Boolean).join(`
|
|
2191
|
-
`):"Waiting for the harness to flush this turn";return Ir({class:"token-wrap"},Ir({class:["token",k6t(b)],"data-tip":T},I))}};var $St={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var Wvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Yvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},Xvn=o=>{let s=Yvn[o]??$St[Wvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},Y0=(o,s="")=>Ir({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=Xvn(o)}},"");function HSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var Vvn=()=>Y0("play","btn-icon"),Zvn=()=>Y0("stop","btn-icon"),e5n=o=>`typebulbs/u/samples/${o}.bulb.md`,oD=o=>Qh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],t5n=(o,s)=>`https://typebulb.com/u/${s}/${hM(o.path)}/full`,qSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",tie=class extends Dk{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?DF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Qh(p.path)),d=[...this.samples.map(p=>[e5n(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Qh(p.file),v=hM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Qh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Qh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=I6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Qh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>oD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&oD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return HSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Qh(d.path)===Qh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Qh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=oD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,qSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Qh(v.path).endsWith("/"+Qh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,qSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Qh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(oD(s),hM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p)}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Qh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&DF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Qh(d.path)===Qh(s))?.name||hM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#i(),this.#e=setInterval(()=>this.#i(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#i(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return Gt({class:"servers-wrap"});let d=this.pendingDenial();return Gt({class:"servers-wrap"},uc({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:Ir({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return Gt({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},Gt({class:"trust-modal",onClick:d=>d.stopPropagation()},Gt({class:"trust-modal-h"},s.heading),Gt({class:"trust-modal-b"},s.body),Gt({class:"trust-modal-warn"},s.warn),Gt({class:"trust-modal-acts"},uc({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),uc({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=hM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return Gt({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):Gt({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return Gt({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},Gt({class:"bulb-log-head"},Ir({class:"bulb-log-name"},`console \xB7 ${s.name}`),uc({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),i6({class:"bulb-log-body"},Ir({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Qh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return Gt({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?uc({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},Zvn()):uc({class:["bulb-launch",this.launching.has(Qh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},Vvn()),Gt({class:"bulb-name-cell"},s.remote?Ir({class:"server-name stopped remote",title:s.remote.description},s.name):Ir({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),tte(s.hitCount),v?Ir({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):Ir({class:"cell-empty"}),p?bC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):Ir({class:"cell-empty"}),p?bC({class:"server-port",href:Kye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?Ir({class:"cell-empty"}):Ir({class:"bulb-time"},rte(s.recent)),nte(s.snippet,this.filter.trim()))}userLink(s){let a=oD(s);return a?bC({class:"sample-link",href:t5n(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=oD(s);if(!a||s.remote)return Ir({class:"cell-empty"});let d=(p,b)=>{let v=`${Qh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return uc({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},Y0(I?"check":p,"btn-icon-sm"))};return Ir({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return Gt({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},Ir({class:"fold-caret"},Y0("caret",["caret-tri",v?"open":""])),Ir({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return uc({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var nie=class{#e;#i;#t;#n=!1;#r;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#i=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#i=void 0,this.#t=void 0}sync(){this.#n||(this.#n=!0,requestAnimationFrame(()=>{this.#n=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#i?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return Gt({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},Gt({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>Gt({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#r=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#r===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#r=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#r??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var n5n=4e5,rEe="diff-doc-body";function r5n(o,s){let a=o.split(`
|
|
2191
|
+
`):"Waiting for the harness to flush this turn";return Ir({class:"token-wrap"},Ir({class:["token",k6t(b)],"data-tip":T},I))}};var $St={"play_arrow.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-200v-560l440 280-440 280Z"/></svg>',"stop.fill":'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M240-240v-480h480v480H240Z"/></svg>',play_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',stop_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',add_circle:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M440-280h80v-160h160v-80H520v-160h-80v160H280v80h160v160Zm40 200q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',attach_file:'<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-370h80v370q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-390h80v390Z"/></svg>'};var Wvn={play:"play_arrow.fill",stop:"stop.fill",playCircle:"play_circle",stopCircle:"stop_circle",addCircle:"add_circle",attach:"attach_file"},Yvn={caret:'<svg viewBox="0 0 16 16"><path d="M4 1.5 L13 8 L4 14.5 Z" fill="currentColor"/></svg>',push:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 11 V3 M4.75 6.25 L8 3 L11.25 6.25" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',pull:'<svg viewBox="0 0 16 16" fill="none"><path d="M8 3 V11 M4.75 7.75 L8 11 L11.25 7.75" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 14 H13" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',check:'<svg viewBox="0 0 16 16" fill="none"><path d="M3 8.5 L6.5 12 L13 4.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>',close:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 4 L12 12 M12 4 L4 12" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/></svg>',fork:'<svg viewBox="0 0 16 16" fill="none"><path d="M4 2 V8 H12 V2 M8 8 V14" stroke="currentColor" stroke-width="1.8" stroke-linecap="square"/></svg>',diff:'<svg viewBox="4 2 8 12" fill="none"><path d="M5.25 6 H10.75 M8 3.25 V8.75" stroke="var(--diff-add)" stroke-width="1.8" stroke-linecap="round"/><path d="M5.25 12.5 H10.75" stroke="var(--err)" stroke-width="1.8" stroke-linecap="round"/></svg>'},Xvn=o=>{let s=Yvn[o]??$St[Wvn[o]??""]??"";return/<svg[^>]*\bfill=/.test(s)?s:s.replace("<svg ",'<svg fill="currentColor" ')},Y0=(o,s="")=>Ir({class:["icon",...Array.isArray(s)?s:[s]],key:`icon-${o}`,onMounted:a=>{a.innerHTML=Xvn(o)}},"");function HSt(o,...s){return o.slice().sort((a,d)=>{for(let{key:p,desc:b}of s){let v=p(a),w=p(d);if(v!==w)return v==null?b?-1:1:w==null||v<w?b?1:-1:b?-1:1}return 0})}var Vvn=()=>Y0("play","btn-icon"),Zvn=()=>Y0("stop","btn-icon"),e5n=o=>`typebulbs/u/samples/${o}.bulb.md`,oD=o=>Qh(o.path).match(/typebulbs\/u\/([^/]+)\//)?.[1],t5n=(o,s)=>`https://typebulb.com/u/${s}/${hM(o.path)}/full`,qSt=o=>o==="HTTP 404"?"not found \u2014 check the URL (private bulbs need their owner's token)":o==="HTTP 401"||o==="HTTP 403"?"private \u2014 needs its owner's TYPEBULB_TOKEN in .env":o||"pull failed",tie=class extends Dk{files=[];servers=[];samples=[];mine=[];myUser;keepOpenSelector=".servers-wrap";filterId="bulb-filter";listSelector=".bulb-list";filterNoun="name";launching=new Set;dismissedDenials=new Set;pendingLaunch;openLog;#e;spotlightPid;openFolds=new Set;pendingOverwrite;pullErrors=new Map;syncBusy=new Set;syncDone=new Set;search(s){return tb.server.searchBulbs(s)}onActivate(s){let a=this.rows()[s];a&&(a.group?this.toggleFold(a.group.user):a.running?DF(a.running.url):a.remote?this.downloadAndLaunch(a):this.launch(a.path))}onAttached(){this.refresh(),setInterval(()=>this.refreshServers(),800),setInterval(()=>this.refreshFiles(),3e3),window.addEventListener("tb-breakout",s=>this.spotlight(s.detail?.pid))}spotlight(s){this.spotlightPid=s,this.show()}refresh(){return Promise.all([this.refreshServers(),this.refreshFiles(),this.refreshSamples(),this.refreshMine()])}async refreshServers(){try{let s=await tb.server.listBreakouts(),a=s.length!==this.servers.length||s.some((d,p)=>d.pid!==this.servers[p]?.pid||d.denied!==this.servers[p]?.denied||d.predicted!==this.servers[p]?.predicted||d.trust!==this.servers[p]?.trust);this.servers=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] server list refresh failed",s)}}async refreshFiles(){try{let s=await tb.server.listBulbFiles(),a=s.length!==this.files.length||s.some((d,p)=>d.path!==this.files[p]?.path||d.mtime!==this.files[p]?.mtime||d.lastRunAt!==this.files[p]?.lastRunAt);this.files=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] bulb list refresh failed",s)}}async refreshSamples(){try{let s=await tb.server.listSamples(),a=s.length!==this.samples.length||s.some((d,p)=>d.slug!==this.samples[p]?.slug);this.samples=s,a&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] samples refresh failed",s)}}async refreshMine(){try{let{user:s,bulbs:a}=await tb.server.listMyBulbs(),d=s!==this.myUser||a.length!==this.mine.length||a.some((p,b)=>p.slug!==this.mine[b]?.slug);this.myUser=s,this.mine=a,d&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] my-bulbs refresh failed",s)}}merged(){let s=new Map,a=this.files.map(p=>Qh(p.path)),d=[...this.samples.map(p=>[e5n(p.slug),p]),...this.myUser?this.mine.map(p=>[`typebulbs/u/${this.myUser}/${p.slug}.bulb.md`,p]):[]];for(let[p,b]of d)a.some(v=>v.endsWith("/"+p))||s.set(p,{path:p,name:b.name,recent:0,remote:b});this.files.forEach((p,b)=>{s.set(a[b],{path:p.path,name:p.name,recent:Math.max(p.mtime,p.lastRunAt??0),trusted:p.trusted})});for(let p of this.servers){if(p.pid===this.parent.ownPid)continue;let b=Qh(p.file),v=hM(p.file)||p.file,w=s.get(b)??{path:p.file,name:v,recent:0};w.running=p,w.recent=Math.max(w.recent,p.startedAt),s.set(b,w)}return[...s.values()]}rows(){let s=this.merged();if(this.searchActive){let a=new Map(this.results.map(d=>[Qh(d.path),d]));s=s.flatMap(d=>{let p=a.get(Qh(d.path));return p?[{...d,hitCount:p.hitCount,snippet:p.snippet}]:[]})}else{let a=this.filter.trim().toLowerCase(),d=I6t(this.filter);if(d){let p=`typebulbs/u/${d.user}/${d.slug}.bulb.md`,b=s.find(v=>("/"+Qh(v.path)).endsWith("/"+p));return b?[b]:[{path:p,name:d.slug,recent:0,remote:{slug:d.slug,name:d.slug,description:`u/${d.user}/${d.slug} on typebulb.com \u2014 play pulls it into the project`}}]}a?s=s.filter(p=>p.name.toLowerCase().includes(a)||p.path.toLowerCase().includes(a)):[...new Set(s.filter(b=>b.remote).map(b=>oD(b)))].forEach((b,v)=>{let w=T=>!!T.remote&&oD(T)===b,I=s.filter(w).length;this.openFolds.has(b)?s=s.map(T=>w(T)?{...T,recent:-.5-v}:T):s=s.filter(T=>!w(T)),s.push({path:`::${b}`,name:this.foldLabel(b),recent:-1-v,group:{user:b,count:I}})})}return HSt(s,{key:a=>!!a.running},{key:a=>a.recent})}show(){this.beginOpen(),this.refresh(),this.refreshList(),this.armClose(),this.focusFilter()}onClosed(){super.onClosed(),this.closeLog(),this.openFolds.clear(),this.pendingOverwrite=void 0,this.pullErrors.clear(),this.spotlightPid=void 0}toggleFold(s){this.openFolds.delete(s)||this.openFolds.add(s),this.update()}foldLabel(s){return s==="samples"?"Samples from typebulb.com":`${s}'s bulbs`}foldTitle(s){return s==="samples"?"Runnable sample bulbs from typebulb.com \u2014 click to browse":`${s===this.myUser?"Your":`${s}'s`} bulbs on typebulb.com \u2014 click to browse; play pulls one into the project`}async launch(s){if(!this.files.find(d=>Qh(d.path)===Qh(s))?.trusted){let d;try{d=(await tb.server.predictTrustOf(s)).cap}catch(p){console.error("[mirror] predictTrustOf failed",p)}if(d){this.pendingLaunch={path:s,name:this.displayName(s),cap:d},this.update();return}}await this.doLaunch(s)}async downloadAndLaunch(s){let a=Qh(s.path);this.launching.add(a),this.pullErrors.delete(a),this.update();try{let d=oD(s),p=d==="samples"?await tb.server.downloadSample(s.remote.slug):await tb.server.pullRemoteBulb(d,s.remote.slug);if(!p.ok||!p.file){console.error("[mirror] remote pull failed",p.error),this.pullErrors.set(a,qSt(p.error));return}await this.refreshFiles();let b=this.files.find(v=>Qh(v.path).endsWith("/"+Qh(p.file)))?.path??p.file;await this.launch(b)}catch(d){console.error("[mirror] remote pull failed",d),this.pullErrors.set(a,qSt(d?.message))}finally{this.launching.delete(a),this.update()}}async syncRow(s,a,d=!1){let p=`${Qh(s.path)}:${a}`;this.syncBusy.add(p),this.update();try{let b=a==="pull"?await tb.server.pullRemoteBulb(oD(s),hM(s.path),d):await tb.server.pushLocalBulb(s.path,d);b.ok?this.tickDone(p):b.conflict?this.pendingOverwrite={...a==="pull"?{heading:`\u201C${s.name}\u201D has local changes`,body:"Your local file differs from the typebulb.com copy. Overwrite the local file with the site's version?",yesLabel:"Overwrite local"}:{heading:`The site copy of \u201C${s.name}\u201D changed`,body:"It changed since your last sync. Overwrite the typebulb.com copy with your local file?",yesLabel:"Overwrite site copy"},onYes:()=>this.syncRow(s,a,!0)}:console.error(`[mirror] ${a} failed`,b.error)}catch(b){console.error(`[mirror] ${a} failed`,b)}finally{this.syncBusy.delete(p),this.update()}await(a==="pull"?this.refreshFiles():this.refreshMine()),this.update()}tickDone(s){this.syncDone.add(s),setTimeout(()=>{this.syncDone.delete(s),this.update()},1200)}async doLaunch(s,a,d=!1){let p=Qh(s);this.launching.add(p),this.update();let b;try{b=await tb.server.launchBulb(s,a)}catch(v){console.error("[mirror] launchBulb failed",v)}finally{this.launching.delete(p)}d&&b?.pid&&this.dismissedDenials.add(b.pid),b?.url&&DF(b.url),await this.refresh(),this.pinToBottom()}displayName(s){return this.files.find(d=>Qh(d.path)===Qh(s))?.name||hM(s)||s}launchTrusted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,!0)}launchRestricted(){let s=this.pendingLaunch;this.pendingLaunch=void 0,s&&this.doLaunch(s.path,void 0,!0)}cancelLaunch(){this.pendingLaunch=void 0,this.update()}async stop(s){this.openLog?.pid===s&&this.closeLog(),this.dismissedDenials.delete(s);try{await tb.server.stopBreakout(s)}catch(a){console.error("[mirror] stopBreakout failed",a)}await this.refresh()}pendingDenial(){return this.servers.find(s=>s.denied&&s.pid!==this.parent.ownPid&&!this.dismissedDenials.has(s.pid))}async elevate(s){this.dismissedDenials.add(s.pid),this.openLog?.pid===s.pid&&this.closeLog();try{await tb.server.launchBulb(s.file,!0)}catch(a){console.error("[mirror] elevate failed",a)}await this.refresh()}dismissDenial(s){this.dismissedDenials.add(s),this.update()}async toggleTrust(s){let a=!(s.running?s.running.trust:s.trusted);try{await tb.server.setBulbTrust(s.path,a),s.running&&(this.openLog?.pid===s.running.pid&&this.closeLog(),await tb.server.launchBulb(s.path,a))}catch(d){console.error("[mirror] toggleTrust failed",d)}await this.refresh()}showLog(s,a){if(this.openLog?.pid===s.pid){this.closeLog();return}this.closeLog(),this.openLog={pid:s.pid,name:a,text:"",offset:0},this.update(),setTimeout(()=>document.getElementById("bulb-console")?.focus()),this.#i(),this.#e=setInterval(()=>this.#i(),700)}closeLog(){this.#e&&(clearInterval(this.#e),this.#e=void 0),this.openLog&&(this.openLog=void 0,this.update())}async#i(){let s=this.openLog;if(s)try{let{text:a,offset:d}=await tb.server.readBulbLog(s.pid,s.offset);if(this.openLog!==s)return;a?(s.text=(s.text+a).slice(-5e4),s.offset=d,this.update()):d!==s.offset&&(s.offset=d)}catch(a){console.error("[mirror] readBulbLog failed",a)}}view(){let s=this.servers.filter(p=>p.pid!==this.parent.ownPid).length;if(!(this.files.length>0||this.samples.length>0)&&s===0)return Gt({class:"servers-wrap"});let d=this.pendingDenial();return Gt({class:"servers-wrap"},uc({class:["pill",s>0?"":"glyph",this.open?"on":""],"data-tip":"Launch a project bulb \xB7 stop a running one",ariaLabel:s>0?`Bulbs (${s} running)`:"Bulbs",onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},s>0?`${s}\u{1F4A1}`:Ir({class:"glyph-img"},"\u{1F4A1}")),this.open?this.popup():null,this.pendingLaunch?this.launchModal(this.pendingLaunch):this.pendingOverwrite?this.overwriteModal(this.pendingOverwrite):d?this.denialModal(d):null)}overwriteModal(s){let a=()=>{this.pendingOverwrite=void 0,this.update()};return this.trustModal({heading:s.heading,body:s.body,warn:"There is no undo \u2014 the overwritten side's changes are gone.",noLabel:"Cancel",yesLabel:s.yesLabel,onNo:a,onYes:()=>{this.pendingOverwrite=void 0,s.onYes()},onDismiss:a})}trustModal(s){let a=(d,p)=>{d.stopPropagation(),p(),this.open&&this.focusFilter()};return Gt({class:"trust-back",tabIndex:0,onMounted:d=>d.focus(),onKeyDown:d=>{d.key==="Escape"&&a(d,s.onDismiss)},onClick:d=>a(d,s.onDismiss)},Gt({class:"trust-modal",onClick:d=>d.stopPropagation()},Gt({class:"trust-modal-h"},s.heading),Gt({class:"trust-modal-b"},s.body),Gt({class:"trust-modal-warn"},s.warn),Gt({class:"trust-modal-acts"},uc({class:"trust-no",onClick:d=>a(d,s.onNo)},s.noLabel),uc({class:"trust-yes",onClick:d=>a(d,s.onYes)},s.yesLabel))))}launchModal(s){return this.trustModal({heading:`\u201C${s.name}\u201D will likely need access`,body:`It looks like it uses ${s.cap}, which is blocked unless you launch it Trusted. Launch Trusted to allow filesystem / AI / server.ts?`,warn:"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Launch restricted",yesLabel:"Launch trusted",onNo:()=>this.launchRestricted(),onYes:()=>this.launchTrusted(),onDismiss:()=>this.cancelLaunch()})}denialModal(s){let a=hM(s.file)||s.file,d=!s.predicted;return this.trustModal({heading:d?`\u201C${a}\u201D reached for access it didn't declare`:`\u201C${a}\u201D wants more access`,body:d?`It tried to use ${s.denied} at runtime, though nothing in its code obviously needed it. Relaunch it Trusted to allow filesystem / AI / server.ts?`:`It tried to use ${s.denied}, blocked while it's restricted. Relaunch it Trusted to allow filesystem / AI / server.ts?`,warn:d?"Code that reaches for capabilities it never visibly uses can be hiding something \u2014 only continue if you wrote this bulb or have read it.":"Only trust bulbs you wrote or have read \u2014 be careful with anything off the internet.",noLabel:"Keep restricted",yesLabel:"Trust & relaunch",onNo:()=>this.dismissDenial(s.pid),onYes:()=>this.elevate(s),onDismiss:()=>this.dismissDenial(s.pid)})}popup(){if(this.openLog)return this.consoleView(this.openLog);let s=this.rows(),a=this.spotlightPid,d=a!==void 0&&s.some(p=>p.running?.pid===a);return Gt({class:"servers-pop"},s.length===0?this.emptyState("No bulbs in this project yet."):Gt({class:"bulb-list",onScroll:()=>this.onListScroll()},s.map((p,b)=>this.row(p,b,d&&p.running?.pid!==a))),this.filterBox(this.merged().filter(p=>!p.remote).length,"bulb"))}consoleView(s){return Gt({id:"bulb-console",class:"servers-pop log-mode",tabIndex:0,onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeLog())}},Gt({class:"bulb-log-head"},Ir({class:"bulb-log-name"},`console \xB7 ${s.name}`),uc({class:"bulb-log-back",title:"Back to the bulb list",onClick:a=>{a.stopPropagation(),this.closeLog()}},"\u2190 bulbs")),i6({class:"bulb-log-body"},Ir({class:"bulb-log-text"},s.text||"(no output yet)")))}hoverRow(s,a){let d=a!==void 0&&a.pid===this.spotlightPid;d&&(this.spotlightPid=void 0),(this.highlighted!==s||d)&&(this.highlighted=s,this.update())}row(s,a,d=!1){if(s.group)return this.groupRow(s,a,d);let p=s.running,b=p&&this.openLog?.pid===p.pid,v=this.pullErrors.get(Qh(s.path)),w=p?!!p.trust:!!s.trusted,I=!!s.remote&&!this.searchActive&&!this.filter.trim();return Gt({class:["server-row",I?"fold-row":"",a===this.highlighted?"active":"",d?"dimmed":""],onMouseEnter:()=>this.hoverRow(a,p)},p?uc({class:"server-stop",title:"Stop this server",ariaLabel:"Stop",onClick:T=>{T.stopPropagation(),this.stop(p.pid)}},Zvn()):uc({class:["bulb-launch",this.launching.has(Qh(s.path))?"launching shimmer":""],title:s.remote?"Download from typebulb.com & launch":w?"Launch (trusted \u2014 remembered)":"Launch (restricted)",ariaLabel:"Launch",onClick:T=>{T.stopPropagation(),s.remote?this.downloadAndLaunch(s):this.launch(s.path)}},Vvn()),Gt({class:"bulb-name-cell"},s.remote?Ir({class:"server-name stopped remote",title:s.remote.description},s.name):Ir({class:["server-name",p?"":"stopped"],title:`Open ${s.path}`,onClick:T=>{T.stopPropagation(),tb.server.openFile(s.path)}},s.name),this.userLink(s),tte(s.hitCount),v?Ir({class:"pull-error"},v):null),this.syncCell(s),p||w?this.trustToggle(s,w):Ir({class:"cell-empty"}),p?bC({class:["server-logs",b?"on":""],title:"Show this server\u2019s console",onClick:T=>{T.stopPropagation(),this.showLog(p,s.name)}},"logs"):Ir({class:"cell-empty"}),p?bC({class:"server-port",href:Kye(p.url),target:"_blank",rel:"noopener noreferrer",title:`Open ${p.url}`},`:${p.port}`):s.remote?Ir({class:"cell-empty"}):Ir({class:"bulb-time"},rte(s.recent)),nte(s.snippet,this.filter.trim()))}userLink(s){let a=oD(s);return a?bC({class:"sample-link",href:t5n(s,a),target:"_blank",rel:"noopener noreferrer",title:"Open this bulb's page on typebulb.com"},a):null}syncCell(s){let a=oD(s);if(!a||s.remote)return Ir({class:"cell-empty"});let d=(p,b)=>{let v=`${Qh(s.path)}:${p}`,w=this.syncBusy.has(v),I=this.syncDone.has(v);return uc({class:["sync-btn",w?"busy shimmer":"",I?"done":""],title:b,ariaLabel:p,onClick:T=>{T.stopPropagation(),w||this.syncRow(s,p)}},Y0(I?"check":p,"btn-icon-sm"))};return Ir({class:"sync-cell"},d("pull",`Pull \u2014 update the local file from typebulb.com/u/${a}`),a===this.myUser?d("push","Push \u2014 upload this file to typebulb.com"):null)}groupRow(s,a,d){let{user:p,count:b}=s.group,v=this.openFolds.has(p);return Gt({class:["server-row","sample-group",v?"open":"",a===this.highlighted?"active":"",d?"dimmed":""],title:v?"Collapse":this.foldTitle(p),onMouseEnter:()=>this.hoverRow(a),onClick:w=>{w.stopPropagation(),this.toggleFold(p)}},Ir({class:"fold-caret"},Y0("caret",["caret-tri",v?"open":""])),Ir({class:"sample-group-label"},`${s.name} (${b})`))}trustToggle(s,a){return uc({class:["trust-toggle",a?"on":""],title:`${a?"Trusted":"Restricted"} \u2014 click to switch to ${a?"restricted":"trusted"}`+(s.running?" (stops + relaunches it)":""),onClick:d=>{d.stopPropagation(),this.toggleTrust(s)}},a?"trusted":"restricted")}};var nie=class{#e;#i;#t;#n=!1;#r;#s;constructor(s){this.#e=s}#o(){this.#e()?.classList.add("oruler-host")}#c(s){this.#i=s;let a=this.#e();a&&(this.#o(),this.#s?.disconnect(),this.#s=new ResizeObserver(()=>this.sync()),this.#s.observe(a),this.sync())}release(){this.#s?.disconnect(),this.#s=void 0,this.#e()?.classList.remove("oruler-host"),this.#i=void 0,this.#t=void 0}sync(){this.#n||(this.#n=!0,requestAnimationFrame(()=>{this.#n=!1;let s=this.#e(),a=this.#t;if(!s||!a||!s.scrollHeight)return;this.#o();let d=s.scrollHeight-s.clientHeight;a.style.display=d>0?"":"none",a.style.top=`${s.scrollTop/s.scrollHeight*100}%`,a.style.height=`${s.clientHeight/s.scrollHeight*100}%`,this.#i?.setAttribute("aria-valuenow",String(d>0?Math.round(s.scrollTop/d*100):0))}))}view(s,a={}){return Gt({class:["oruler",a.class??""],title:a.title,role:"scrollbar",ariaOrientation:"vertical",ariaLabel:a.label??"Scroll position",ariaControls:a.controls,ariaValueMin:0,ariaValueMax:100,ariaValueNow:0,onMounted:d=>this.#c(d),onPointerDown:d=>this.#u(d),onPointerMove:d=>this.#f(d),onPointerUp:d=>this.#l(d),onPointerCancel:d=>this.#l(d),onWheel:d=>this.#h(d)},Gt({class:"oruler-win",onMounted:d=>{this.#t=d,this.sync()}}),s.map(d=>Gt({class:["oruler-mark",d.class??""],style:{top:`${d.top*100}%`,height:`${d.height*100}%`}})))}#u(s){let a=this.#e(),d=s.currentTarget;if(!a)return;s.preventDefault();let p=this.#t?.getBoundingClientRect(),b=!!p&&s.clientY>=p.top&&s.clientY<=p.bottom;this.#r=b?s.clientY-p.top:(p?.height??0)/2,d.setPointerCapture(s.pointerId),this.#a(s,d,a)}#f(s){let a=this.#e();this.#r===void 0||!a||this.#a(s,s.currentTarget,a)}#l(s){let a=s.currentTarget;this.#r=void 0,a.hasPointerCapture(s.pointerId)&&a.releasePointerCapture(s.pointerId)}#h(s){let a=this.#e();if(!a)return;let d=s.deltaMode===1?16:s.deltaMode===2?a.clientHeight:1;a.scrollTop+=s.deltaY*d,this.sync()}#a(s,a,d){let p=s.clientY-a.getBoundingClientRect().top-(this.#r??0);d.scrollTop=p/a.clientHeight*d.scrollHeight,this.sync()}};var n5n=4e5,rEe="diff-doc-body";function r5n(o,s){let a=o.split(`
|
|
2192
2192
|
`).map(v=>v.replace(/\r$/,""));if(a.length&&a[a.length-1]===""&&a.pop(),s)return a.map(v=>({kind:"add",text:v}));let d=[],p=!1,b=!1;for(let v of a){if(v.startsWith("@@")){b&&d.push({kind:"gap",text:"\u22EF"}),b=!0,p=!0;continue}if(!p){v.startsWith("Binary file")&&d.push({kind:"ctx",text:v});continue}v.startsWith("\\")||(v.startsWith("+")?d.push({kind:"add",text:v.slice(1)}):v.startsWith("-")?d.push({kind:"del",text:v.slice(1)}):d.push({kind:"ctx",text:v.slice(1)}))}return d}function i5n(o,s,a){let d=r5n(o,s),p=o.length>n5n?"txt":a.split(".").pop()??"",b=[],v=[];for(let P of d)(P.kind==="ctx"||P.kind==="del")&&b.push(P.text),(P.kind==="ctx"||P.kind==="add")&&v.push(P.text);let w=eEe(b.join(`
|
|
2193
2193
|
`),p),I=eEe(v.join(`
|
|
2194
2194
|
`),p),T=0,B=0,D=[];for(let P of d){if(P.kind==="gap"){D.push('<div class="udiff-gap">\u22EF</div>');continue}let j=P.kind==="del"?w[T++]:(P.kind==="add"||T++,I[B++]);D.push(`<div class="udiff-line${P.kind==="add"?" udiff-add":P.kind==="del"?" udiff-del":""}">${j??""}</div>`)}return{kinds:d.map(P=>P.kind),bodyHtml:D.join("")}}var rie=class extends Dk{files=[];repo=!0;root="";viewing;#e=0;#i=!1;#t=()=>document.getElementById(rEe);#n=new nie(this.#t);#r=[];#s=-1;keepOpenSelector=".gitdiff-wrap";filterId="gitdiff-filter";listSelector=".gitdiff-list";filterNoun="file";search(){return Promise.resolve([])}onActivate(s){let a=this.rows()[s];a&&this.openDiff(a)}onAttached(){this.refreshFiles(),setInterval(()=>this.refreshFiles(),3e3),setInterval(()=>{this.viewing&&this.refreshDiff()},1500)}rows(){let s=this.filter.trim().toLowerCase();return s?this.files.filter(a=>a.path.toLowerCase().includes(s)):this.files}async refreshFiles(){try{let{repo:s,root:a,files:d}=await tb.server.gitChangedFiles(),p=s!==this.repo||d.length!==this.files.length||d.some((b,v)=>{let w=this.files[v];return b.path!==w?.path||b.status!==w.status||b.add!==w.add||b.del!==w.del||b.binary!==w.binary});this.repo=s,this.root=a,this.files=d,p&&(this.update(),this.keepBottom())}catch(s){console.error("[mirror] gitChangedFiles failed",s)}}#o(s,a,d){this.viewing?.path!==s&&(this.#r=[]),this.viewing={path:s,status:a,text:d.text,truncated:!!d.truncated,...i5n(d.text,!!d.untracked,s)},this.#e++,this.update()}async openDiff(s){try{let a=await tb.server.gitDiff(s.path);if(!a.ok){console.error("[mirror] gitDiff failed:",a.error);return}this.#o(s.path,s.status,a),this.#i=!0,this.close()}catch(a){console.error("[mirror] gitDiff failed",a)}}async refreshDiff(){let s=this.viewing;if(s)try{let a=await tb.server.gitDiff(s.path);if(this.viewing!==s||!a.ok||a.text===s.text)return;this.#o(s.path,s.status,a)}catch(a){console.error("[mirror] gitDiff refresh failed",a)}}closeDoc(){this.#n.release(),this.viewing=void 0,this.update()}show(){this.beginOpen(),this.refreshFiles(),this.refreshList(),this.armClose(),this.focusFilter()}view(){let s=this.files.length;return!this.repo||s===0&&!this.viewing&&!this.open?Gt({class:"gitdiff-wrap"}):Gt({class:"gitdiff-wrap pop-center"},this.viewing?this.viewingPill():uc({class:["pill","glyph","gitdiff-pill",this.open?"on":""],"data-tip":`${s} changed file${s===1?"":"s"} \u2014 view a diff`,ariaLabel:`${s} changed file${s===1?"":"s"}`,onClick:a=>{a.stopPropagation(),this.open?this.close():this.show()}},Y0("diff"),Ir({class:"gitdiff-count"},String(s))),this.open?this.popup():null)}viewingPill(){let s=this.viewing,a=s.kinds.filter(p=>p==="add").length,d=s.kinds.filter(p=>p==="del").length;return uc({class:["pill","glyph","gitdiff-pill","viewing","on"],"data-tip":`${this.files.length} changed file${this.files.length===1?"":"s"} \u2014 switch file`,onClick:p=>{p.stopPropagation(),this.open?this.close():this.show()}},Ir({class:["gitdiff-status",`s-${s.status}`]},s.status),Ir({class:"gitdiff-doc-path",title:`Open ${s.path}`,onClick:p=>{p.stopPropagation(),tb.server.openFile(`${this.root}/${s.path}`)}},s.path),Ir({class:"gitdiff-counts"},Ir({class:"count-add"},`+${a}`),Ir({class:"count-del"},`\u2212${d}`)),Ir({class:"gitdiff-close","data-tip":"Back to the conversation (Esc)",ariaLabel:"Back to the conversation",onClick:p=>{p.stopPropagation(),this.closeDoc()}},Y0("close")))}popup(){let s=this.rows();return Gt({class:"servers-pop gitdiff-pop"},s.length===0?this.emptyState("No changes in the working tree."):Gt({class:"gitdiff-list",onScroll:()=>this.onListScroll()},s.map((a,d)=>this.row(a,d))),this.filterRow())}filterRow(){let s=this.files.length;return ete({target:this,prop:()=>this.filter,id:this.filterId,placeholder:s?`Filter ${s} file${s===1?"":"s"}\u2026`:"Filter files\u2026",hasValue:!!this.filter,onKeyDown:a=>this.onFilterKey(a),onClear:()=>this.clearFilter()})}row(s,a){return Gt({class:["gitdiff-row",a===this.highlighted?"active":"",this.viewing?.path===s.path?"viewing":""],onMouseEnter:()=>{this.highlighted!==a&&(this.highlighted=a,this.update())},onClick:d=>{d.stopPropagation(),this.openDiff(s)}},Ir({class:["gitdiff-status",`s-${s.status}`]},s.status),Ir({class:"gitdiff-path",title:s.path},s.path),s.add!==void 0||s.del!==void 0?Ir({class:"gitdiff-counts"},Ir({class:"count-add"},`+${s.add??0}`),Ir({class:"count-del"},`\u2212${s.del??0}`)):s.status==="U"?Ir({class:"gitdiff-counts"},Ir({class:"count-add"},"new")):Ir({class:"gitdiff-counts"},Ir({},s.binary?"binary":"\u2014")))}docView(){let s=this.viewing;return Gt({class:"diff-doc",onKeyDown:a=>{a.key==="Escape"&&(a.stopPropagation(),this.closeDoc())}},Gt({class:"diff-doc-scroll"},Gt({class:"diff-doc-body",id:rEe,tabIndex:0,onMounted:a=>a.focus(),onScroll:()=>this.#n.sync()},s.kinds.length===0?Gt({class:"diff-doc-empty"},"No changes."):Gt({class:"diff-doc-code",key:`diff-code-${this.#e}`,onMounted:a=>{a.innerHTML=s.bodyHtml,this.#c(a),this.#u(a)}},""),s.truncated?Gt({class:"diff-doc-trunc"},"Diff truncated \u2014 file too large to show in full."):null),s.kinds.length?this.#n.view(this.#r,{class:"diff-ruler",title:"Jump to a change",label:"Diff scroll position",controls:rEe}):null))}#c(s){if(!this.#i)return;this.#i=!1;let a=s.querySelector(".udiff-add, .udiff-del"),d=this.#t();a&&d&&(d.scrollTop=a.offsetTop-d.clientHeight/3)}#u(s){this.#s!==this.#e&&(this.#s=this.#e,requestAnimationFrame(()=>{this.#f(s),this.update(),this.#n.sync()}))}#f(s){let a=this.viewing,d=this.#t();if(!a||!d?.scrollHeight)return;let p=d.scrollHeight,b=[];for(let v=0;v<a.kinds.length;v++){let w=a.kinds[v];if(w!=="add"&&w!=="del")continue;let I=v;for(;I+1<a.kinds.length&&a.kinds[I+1]===w;)I++;let T=s.children[v],B=s.children[I];T&&B&&b.push({top:T.offsetTop/p,height:(B.offsetTop+B.offsetHeight-T.offsetTop)/p,class:w}),v=I}this.#r=b}};var cD=class extends wu{done=!1;#e;constructor(s){super(),this.#e=s}setText(s){this.#e=s}flash(){navigator.clipboard?.writeText(this.#e),this.done=!0,this.update(),setTimeout(()=>{this.done=!1,this.update()},600)}view(){return uc({class:["overlay-pill","copy",this.done?"done":""],onClick:s=>{s.stopPropagation(),this.flash()}},this.done?"copied":"copy")}};var QSt=new Map,GSt=(o,s)=>s+`
|
package/dist/ai/aiProvider.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ export declare abstract class AIProvider {
|
|
|
29
29
|
* Get the request path. Override for providers that need dynamic paths (e.g., model in URL).
|
|
30
30
|
*/
|
|
31
31
|
getPath(_model: string, _stream: boolean): string;
|
|
32
|
-
abstract buildHeaders(apiKey: string
|
|
32
|
+
abstract buildHeaders(apiKey: string): Record<string, string>;
|
|
33
33
|
abstract buildPayload(messages: ChatMessageDto[], model: string, opts: ChatRequestOpts, stream: boolean): unknown;
|
|
34
34
|
parseError(errorText: string, status: number): UpstreamErrorDto;
|
|
35
35
|
abstract parseNonStreamingResponse(json: ProviderResponseDto): ChatResponseDto;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiProvider.d.ts","sourceRoot":"","sources":["../../ai/src/aiProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EAChB,MAAM,eAAe,CAAA;AAEtB;;;uBAGuB;AACvB,MAAM,MAAM,eAAe,GACzB;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAA;AAErF;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAG1B,IAAI,EAAE,eAAe;aACrB,SAAS,EAAE,OAAO;gBAFlC,OAAO,EAAE,MAAM,EACC,IAAI,GAAE,eAA2B,EACjC,SAAS,GAAE,OAAe;CAI7C;AAED;;;GAGG;AACH,8BAAsB,UAAU;IAC9B,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAChD,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IACxC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAI9B;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAIjD,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"aiProvider.d.ts","sourceRoot":"","sources":["../../ai/src/aiProvider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EAChB,MAAM,eAAe,CAAA;AAEtB;;;uBAGuB;AACvB,MAAM,MAAM,eAAe,GACzB;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAAA;AAErF;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAG1B,IAAI,EAAE,eAAe;aACrB,SAAS,EAAE,OAAO;gBAFlC,OAAO,EAAE,MAAM,EACC,IAAI,GAAE,eAA2B,EACjC,SAAS,GAAE,OAAe;CAI7C;AAED;;;GAGG;AACH,8BAAsB,UAAU;IAC9B,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAChD,QAAQ,CAAC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;IACxC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAI9B;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM;IAIjD,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAE7D,QAAQ,CAAC,YAAY,CACnB,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,OAAO,GACd,OAAO;IAEV,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAM/D,QAAQ,CAAC,yBAAyB,CAAC,IAAI,EAAE,mBAAmB,GAAG,eAAe;IAE9E;;;OAGG;IACH,gBAAgB,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,SAAS;IAK9E,SAAS,CAAC,QAAQ,CAAC,wBAAwB,CAAC,IAAI,EAAE,sBAAsB,GAAG,kBAAkB,GAAG,SAAS;IAIzG,wDAAwD;IACxD,SAAS,CAAC,qBAAqB,CAAC,QAAQ,EAAE,cAAc,EAAE,EAAE,SAAS,SAAS,GAAG;QAC/E,MAAM,EAAE,MAAM,GAAG,SAAS,CAAA;QAC1B,oBAAoB,EAAE,cAAc,EAAE,CAAA;KACvC;IAQD;;OAEG;IACH,SAAS,CAAC,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB;IAsB7E;;;;;OAKG;IACH,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAyBjD,OAAO,CAAC,mBAAmB;CAe5B"}
|
package/dist/ai/aiProviders.d.ts
CHANGED
|
@@ -20,7 +20,6 @@ export interface SendAIRequestOpts {
|
|
|
20
20
|
* wrote a chat-completions `max_tokens` and so silently failed to bind on the OpenAI Responses
|
|
21
21
|
* API and Gemini — the two whose payloads name it differently. */
|
|
22
22
|
maxOutputTokens?: number;
|
|
23
|
-
origin?: string;
|
|
24
23
|
signal?: AbortSignal;
|
|
25
24
|
}
|
|
26
25
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiProviders.d.ts","sourceRoot":"","sources":["../../ai/src/aiProviders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACtG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAmB5C,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,UAAU,CAMlE;AAED,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;uEAEmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"aiProviders.d.ts","sourceRoot":"","sources":["../../ai/src/aiProviders.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACtG,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAmB5C,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,QAAQ,EAAE,gBAAgB,GAAG,UAAU,CAMlE;AAED,oDAAoD;AACpD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;uEAEmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,uCAAuC;AACvC,wBAAsB,aAAa,CACjC,QAAQ,EAAE,kBAAkB,EAC5B,IAAI,EAAE,iBAAiB,GACtB,OAAO,CAAC,QAAQ,CAAC,CAmBnB;AAED;;;uCAGuC;AACvC,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,uEAAuE;AACvE,wBAAsB,sBAAsB,CAC1C,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,gBAAgB,GACzB,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,CAYvC"}
|
package/dist/ai/aiProviders.js
CHANGED
|
@@ -40,7 +40,7 @@ export async function sendAIRequest(provider, opts) {
|
|
|
40
40
|
const spec = getProvider(provider.protocol);
|
|
41
41
|
const path = spec.getPath(provider.model, opts.stream);
|
|
42
42
|
const url = joinUrl(provider.baseUrl, path);
|
|
43
|
-
const headers = spec.buildHeaders(provider.apiKey
|
|
43
|
+
const headers = spec.buildHeaders(provider.apiKey);
|
|
44
44
|
const payload = spec.buildPayload(opts.messages, provider.model, { effort: opts.effort, webSearch: opts.webSearch, maxOutputTokens: opts.maxOutputTokens }, opts.stream);
|
|
45
45
|
return fetch(url, {
|
|
46
46
|
method: 'POST',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aiProviders.js","sourceRoot":"","sources":["../../ai/src/aiProviders.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,0FAA0F;AAC1F,yFAAyF;AACzF,MAAM,YAAY,GAAG,IAAI,cAAc,EAAE,CAAA;AACzC,MAAM,SAAS,GAAG,IAAI,GAAG,CAA+B;IACtD,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC,YAAY,EAAE,IAAI,kBAAkB,EAAE,CAAC;IACxC,CAAC,WAAW,EAAE,IAAI,iBAAiB,EAAE,CAAC;IACtC,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,eAAe,EAAE,YAAY,CAAC;CAChC,CAAC,CAAA;AAEF,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CAAC,QAA0B;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;
|
|
1
|
+
{"version":3,"file":"aiProviders.js","sourceRoot":"","sources":["../../ai/src/aiProviders.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AAEtD,0FAA0F;AAC1F,yFAAyF;AACzF,MAAM,YAAY,GAAG,IAAI,cAAc,EAAE,CAAA;AACzC,MAAM,SAAS,GAAG,IAAI,GAAG,CAA+B;IACtD,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC,YAAY,EAAE,IAAI,kBAAkB,EAAE,CAAC;IACxC,CAAC,WAAW,EAAE,IAAI,iBAAiB,EAAE,CAAC;IACtC,CAAC,QAAQ,EAAE,IAAI,cAAc,EAAE,CAAC;IAChC,CAAC,QAAQ,EAAE,YAAY,CAAC;IACxB,CAAC,eAAe,EAAE,YAAY,CAAC;CAChC,CAAC,CAAA;AAEF,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CAAC,QAA0B;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IACxC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,EAAE,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAwBD;;;;;;;;;GASG;AACH,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,IAAY;IAChD,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;AAC9E,CAAC;AAED,uCAAuC;AACvC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAA4B,EAC5B,IAAuB;IAEvB,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAE3C,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAClD,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAC/B,IAAI,CAAC,QAAQ,EACb,QAAQ,CAAC,KAAK,EACd,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,EAAE,EACzF,IAAI,CAAC,MAAM,CACe,CAAA;IAE5B,OAAO,KAAK,CAAC,GAAG,EAAE;QAChB,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAA;AACJ,CAAC;AAED;;;uCAGuC;AACvC,MAAM,UAAU,wBAAwB,CAAC,OAAe;IACtD,OAAO,oGAAoG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAC3H,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,QAAkB,EAClB,QAA0B;IAE1B,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAA;IAClC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;IACvD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC/D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAA;IAE9B,IAAI,IAAI,GAA+B,SAAS,CAAA;IAChD,IAAI,MAAM,KAAK,GAAG;QAAE,IAAI,GAAG,YAAY,CAAA;SAClC,IAAI,MAAM,KAAK,GAAG,IAAI,wBAAwB,CAAC,OAAO,CAAC;QAAE,IAAI,GAAG,kBAAkB,CAAA;IAEvF,2FAA2F;IAC3F,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE,CAAA;AACtE,CAAC"}
|
|
@@ -24,12 +24,18 @@ export type OpenRouterRequestPayload = {
|
|
|
24
24
|
};
|
|
25
25
|
plugins?: OpenRouterWebPlugin[];
|
|
26
26
|
};
|
|
27
|
+
/** OpenRouter app attribution: the referer URL keys the app page, a title alone creates nothing. Sent on
|
|
28
|
+
* every call, BYOK included (that is the pair's purpose); the wire proxy (switcher.ts) sends the same pair. */
|
|
29
|
+
export declare const OPENROUTER_ATTRIBUTION: {
|
|
30
|
+
readonly 'HTTP-Referer': "https://typebulb.com";
|
|
31
|
+
readonly 'X-OpenRouter-Title': "Typebulb";
|
|
32
|
+
};
|
|
27
33
|
export declare class OpenRouterProvider extends ChatCompletionsProvider {
|
|
28
34
|
protected readonly providerName = "OpenRouter";
|
|
29
35
|
readonly defaultBaseUrl = "https://openrouter.ai";
|
|
30
36
|
readonly path: string;
|
|
31
37
|
private readonly effortMap;
|
|
32
|
-
buildHeaders(apiKey: string
|
|
38
|
+
buildHeaders(apiKey: string): Record<string, string>;
|
|
33
39
|
buildPayload(messages: ChatMessageDto[], model: string, opts: ChatRequestOpts, stream: boolean): OpenRouterRequestPayload;
|
|
34
40
|
}
|
|
35
41
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openRouter.d.ts","sourceRoot":"","sources":["../../../ai/src/providers/openRouter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAA;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,mCAAmC;AACnC,UAAU,mBAAmB;IAC3B,EAAE,EAAE,KAAK,CAAA;IACT,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,iCAAiC;AACjC,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE,CAAA;IAC3C,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IACpE,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAA;CAChC,CAAA;AAED,qBAAa,kBAAmB,SAAQ,uBAAuB;IAC7D,SAAS,CAAC,QAAQ,CAAC,YAAY,gBAAe;IAO9C,QAAQ,CAAC,cAAc,2BAA0B;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAA6B;IAQlD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAMzB;IAID,YAAY,CAAC,MAAM,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"openRouter.d.ts","sourceRoot":"","sources":["../../../ai/src/providers/openRouter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,cAAc,EAAe,MAAM,gBAAgB,CAAA;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAE9D,mCAAmC;AACnC,UAAU,mBAAmB;IAC3B,EAAE,EAAE,KAAK,CAAA;IACT,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAED,iCAAiC;AACjC,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE;QAAE,aAAa,EAAE,OAAO,CAAA;KAAE,CAAA;IAC3C,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAA;KAAE,CAAA;IACpE,OAAO,CAAC,EAAE,mBAAmB,EAAE,CAAA;CAChC,CAAA;AAED;gHACgH;AAChH,eAAO,MAAM,sBAAsB;;;CAGzB,CAAA;AAEV,qBAAa,kBAAmB,SAAQ,uBAAuB;IAC7D,SAAS,CAAC,QAAQ,CAAC,YAAY,gBAAe;IAO9C,QAAQ,CAAC,cAAc,2BAA0B;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAA6B;IAQlD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAMzB;IAID,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAUpD,YAAY,CACV,QAAQ,EAAE,cAAc,EAAE,EAC1B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,eAAe,EACrB,MAAM,EAAE,OAAO,GACd,wBAAwB;CAoC5B"}
|