@3sln/trove 0.0.18 → 0.0.19
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/package.json +1 -1
- package/packages/web/dist/assets/{main-b9jd0fyt.js → main-axerf2vw.js} +3 -3
- package/packages/web/dist/assets/{main-b9jd0fyt.js.map → main-axerf2vw.js.map} +3 -3
- package/packages/web/dist/index.html +1 -1
- package/packages/web/dist/sw.js +1 -1
- package/packages/web/src/platform/pluginRpc.js +14 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@3sln/trove",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Trove — a self-hostable, plugin-extensible Google Drive. Semantic search, pluggable storage (S3 / filesystem / NAS), and a VS Code-style contribution system with sandboxed plugins.",
|
|
6
6
|
"repository": {
|
|
@@ -727,7 +727,7 @@ import{a as RH,c as z1,d as MH}from"./chunk-4xqbzebh.js";var fB={};z1(fB,{wbr:()
|
|
|
727
727
|
})();
|
|
728
728
|
</script>
|
|
729
729
|
</body></html>`}var Y$=/\b(ATTACH|DETACH|VACUUM|PRAGMA)\b/i;function X$(A){let Q="",B=0;while(B<A.length){let C=A[B];if(C==="-"&&A[B+1]==="-"){let E=A.indexOf(`
|
|
730
|
-
`,B);B=E<0?A.length:E;continue}if(C==="/"&&A[B+1]==="*"){let E=A.indexOf("*/",B+2);B=E<0?A.length:E+2,Q+=" ";continue}if(C==="'"||C==='"'||C==="`"){let E=C;B++;while(B<A.length){if(A[B]===E){if(A[B+1]===E){B+=2;continue}B++;break}B++}Q+=" ";continue}if(C==="["){let E=A.indexOf("]",B);B=E<0?A.length:E+1,Q+=" ";continue}Q+=C,B++}return Q}function SJ(A){if(typeof A!=="string"||!A)throw z.invalid("SQL statement is required");if(Y$.test(X$(A)))throw z.invalid("ATTACH, DETACH, VACUUM and PRAGMA are not permitted in plugin storage")}var G$=26214400;async function H$(A,Q){let B=Number(A.headers.get("content-length")||0);if(B&&B>Q)throw Error("Response too large");let C=A.body?.getReader?.();if(!C){let Y=await A.arrayBuffer();if(Y.byteLength>Q)throw Error("Response too large");return Y}let E=[],J=0;for(;;){let{done:Y,value:X}=await C.read();if(Y)break;if(J+=X.byteLength,J>Q)throw await C.cancel().catch(()=>{}),Error("Response too large");E.push(X)}let K=new Uint8Array(J),L=0;for(let Y of E)K.set(Y,L),L+=Y.byteLength;return K.buffer}class _J{constructor({platform:A,clientDb:Q,media:B,dock:C,onChange:E}={}){this.platform=A,this.clientDb=Q,this.media=B,this.dock=C,this.onChange=E||(()=>{})}async hostCall(A,Q,B,C){let E=(K)=>{if(!A.grants.includes(K))throw Error(`Capability "${K}" not granted`)},J=A.id;switch(Q){case"activated":{let K=C||A.frame;if(clearTimeout(K?._timer),B.ok)K?.resolveActivated?.(K);else K?.rejectActivated?.(Error(B.error||"activate() failed"));return{ok:!0}}case"command:execute":{let K=this.#A(A,B.id);if(!dC(A.manifest,K))throw Error(`Command "${B.id}" is not in this plugin's declared commands`);return{ok:!0,result:await this.platform.commands.execute(K,...B.args||[])??null}}case"ui:status":{E("ui");let K=this.#Q(A,B.name,"statusItem");return this.platform.contributions.update(K.uri,{...B.html!==void 0?{html:String(B.html??"")}:{},...B.tooltip!==void 0?{tooltip:String(B.tooltip??"")}:{},...B.visible!==void 0?{visible:!!B.visible}:{visible:!0}}),{ok:!0}}case"context:setRegister":{let K=this.#Q(A,B.name,"register"),L=A.registers?.get(K.uri);if(!L)throw Error(`Register "${B.name}" is not available`);return L(B.value),{ok:!0}}case"resources:list":return[...A.files.keys()].filter(d8);case"resources:read":{if(!d8(B.path))throw Error(`No such resource ${B.path}`);let K=A.files.get(B.path);if(!K)throw Error(`No such resource ${B.path}`);return{bytes:K.slice().buffer}}case"files:read":return E("files"),{text:await this.platform.api.readText(B.id)};case"files:list":return E("files"),this.platform.api.list(B.collection||B.pathOrId,{sort:B.sort,order:B.order,limit:B.limit,cursor:B.cursor});case"files:stat":return E("files"),this.platform.api.stat(B.id);case"files:bytes":{E("files");let K=await this.platform.fileChunks.read(B.id,{start:B.start,end:B.end});return{bytes:K.bytes.buffer,etag:K.etag,total:K.total}}case"files:hasLocal":{E("files");let K=this.platform.fileChunks.status(B.id);return{local:!!K.done,loaded:K.loaded,total:K.total,ratio:K.ratio,filling:K.filling}}case"files:localBlob":{E("files");let K=this.platform.fileChunks.status(B.id);if(!K.done||!K.total)return{blob:null};let L=await this.platform.fileChunks.read(B.id,{start:0,end:K.total}),Y=await this.platform.api.stat(B.id).catch(()=>null);return{blob:new Blob([L.bytes],{type:Y?.node?.contentType||"application/octet-stream"})}}case"items:data:get":return E("files"),this.platform.itemData.get(J,B.id);case"items:data:set":return E("files"),this.platform.itemData.set(J,B.id,B.key,B.value);case"items:data:remove":return E("files"),this.platform.itemData.remove(J,B.id,B.key);case"files:offline:start":return E("files"),this.platform.fileChunks.start(B.id);case"files:offline:status":return E("files"),this.platform.fileChunks.status(B.id);case"files:offline:cancel":return E("files"),this.platform.fileChunks.cancel(B.id),{ok:!0};case"files:offline:remove":return E("files"),this.platform.fileChunks.remove(B.id).then(()=>({ok:!0}));case"files:mediaUrl":{E("files");let{url:K,expiresAt:L}=await this.platform.mediaUrls.url(B.id,{op:B.op||"media"});return{url:K,expiresAt:L}}case"files:index":{E("indexer");let K=kQ(B.indexerId)?B.indexerId:xQ(A.manifest,B.indexerId||"default");return this.platform.api.pushIndex(K,B.nodeId,{semanticTexts:B.semanticTexts,tags:B.tags,metadata:B.metadata,documents:B.documents,facet:B.facet})}case"net:fetch":return E("network"),this.#C(A,B);case"storage:sql":return E("storage"),this.#E(A,B);case"settings:get":return this.platform.settings.get(`${J}.${B.key}`);case"settings:getSecret":return A.secrets?.[B.key]??null;case"settings:set":return this.platform.settings.set(`${J}.${B.key}`,B.value),{ok:!0};case"ui:showPanel":return E("ui"),A.hasUi=!0,this.platform.dispatch(new EC(J)),this.onChange(),{ok:!0};case"media:metadata":{E("media");let K=(B.artwork||[]).filter((L)=>this.#B(A,L?.src));return this.media.apply(C,"metadata",{...B,artwork:K})}case"media:playbackState":return E("media"),this.media.apply(C,"playbackState",B);case"media:position":return E("media"),this.media.apply(C,"position",B);case"media:action":return E("media"),this.media.apply(C,"action",B);case"media:clear":return this.media.apply(C,"clear",B);case"dock:enable":if(E("dock"),C)C.dock={enabled:!0,minSize:B.minSize,maxSize:B.maxSize,dismissed:!1};return{ok:!0};case"dock:disable":if(E("dock"),C?.dock)C.dock.enabled=!1;if(C&&this.dock.docked===C)this.dock.closeDock(C);return{ok:!0};case"dock:close":if(C)this.dock.closeDock(C);return{ok:!0};default:throw Error(`Unknown host method ${Q}`)}}hostEvent(A,Q,B,C){switch(Q){case"manifest":if(C&&C.role!=="primary")break;A.live=B,A.responsive=!0,this.onChange();break;case"ui:toast":this.platform.notifications[B.level||"info"](`${dA(A.manifest)}: ${B.text}`);break;case"ui:badge":A.badge=B.text,this.onChange();break}}#A(A,Q){if(!Q||kQ(Q))return Q;let B=this.platform.contributions.get(xQ(A.manifest,Q));return B?.type==="command"?B.uri:Q}#Q(A,Q,B){let C=Q?this.platform.contributions.get(xQ(A.manifest,Q)):null;if(!C||C.pluginId!==A.id||C.type!==B)throw Error(`"${Q}" is not a ${B} declared by this plugin`);return C}#B(A,Q){if(!Q)return!1;if(/^(blob:|data:image\/)/i.test(Q))return!0;return lC(rQ(A.manifest),Q)}async#C(A,{url:Q,method:B="GET",headers:C,body:E}){let J=rQ(A.manifest);if(c8(Q,this.platform.api?.baseUrl))throw Error("Blocked: a plugin may not call the drive's own API through the network broker");if(!lC(J,Q))throw Error(`Blocked: "${Q}" is not one of this plugin's declared network endpoints`);let K={method:B,credentials:"omit",redirect:"follow",headers:D$(C)};if(E!=null&&B!=="GET"&&B!=="HEAD")K.body=E instanceof ArrayBuffer?new Uint8Array(E):E;let L=await fetch(Q,K);if(L.url&&L.url!==Q){if(c8(L.url,this.platform.api?.baseUrl))throw Error("Blocked: request redirected onto the drive's own API");if(!lC(J,L.url))throw Error(`Blocked: request redirected off this plugin's declared endpoints (${L.url})`)}let Y=await H$(L,G$),X={};return L.headers.forEach((H,G)=>{X[G]=H}),{ok:L.ok,status:L.status,statusText:L.statusText,url:L.url,headers:X,bytes:Y}}async#E(A,{scope:Q="plugin",side:B="server",op:C,sql:E,params:J=[],statements:K}){if(!A.storage?.[Q])throw Error(`Storage scope "${Q}" not granted${Q==="domain"?" (needs a verified domain)":""}`);if(B==="client"){if(C==="batch")for(let G of Array.isArray(K)?K:[])SJ(G?.sql);else SJ(E);let X=Q==="domain"?`dom:${A.manifest.domain}`:`plg:${A.id}`,H=await this.clientDb.obtain(X);return Z$(H,C,E,J,K)}let L={scope:Q,op:C,sql:E,params:J,statements:K,domain:Q==="domain"?A.manifest.domain:void 0};return(await this.platform.api.request("POST",`/api/plugins/${encodeURIComponent(A.id)}/sql`,{body:L})).result}}function c8(A,Q){try{let B=new URL(Q||"",globalThis.location?.href||"http://localhost/");return new URL(A,B).origin===B.origin}catch{return!1}}function d8(A){return A!=="manifest.json"&&!X0(A)}var $$=new Set(["host","cookie","cookie2","set-cookie","origin","referer","content-length","connection"]);function D$(A){let Q={};for(let[B,C]of Object.entries(A||{}))if(!$$.has(String(B).toLowerCase()))Q[B]=C;return Q}function Z$(A,Q,B,C=[],E){switch(Q){case"exec":return A.exec(B);case"run":return A.run(B,...C);case"get":return A.get(B,...C);case"all":return A.all(B,...C);case"batch":return A.batch(E);default:throw Error(`Unknown storage op "${Q}"`)}}var a8=["files","storage","ui","commands","indexer","opener","network","media","dock"];class TJ{constructor(A,{heartbeatMs:Q=20000}={}){this.platform=A,this.plugins=new Map,this.registry=new AE,this.clientDb=new BE({onError:(B,C)=>this.platform.notifications.error(`A plugin's on-device data couldn't be saved (${C}): ${B.message}`)}),this.online=typeof navigator<"u"?navigator.onLine:!0,this.heartbeatMs=Q,this._heartbeat=null,this._probing=!1,this.cell=A.reactive.cell([]),this.media=new GE,this.dock=new HE({destroyFrame:(B)=>this.frames.destroy(B),openFile:(B,C)=>this.platform.dispatch(new GQ(B,C)),onChange:()=>this.#A()}),this.frames=new wJ({media:this.media,dock:this.dock}),this.rpc=new _J({platform:A,clientDb:this.clientDb,media:this.media,dock:this.dock,onChange:()=>this.#A()})}observe(){return this.cell}#A(){this.cell.setValue(this.list())}#Q(A,Q,B){return this.frames.spawn(A,Q,{onCall:(C,E,J,K)=>this.rpc.hostCall(C,E,J,K),onEvent:(C,E,J,K)=>this.rpc.hostEvent(C,E,J,K),online:this.online,entry:B})}#B(A){let Q=A.id,B=this.platform.contributions,C=(J)=>A.disposers.push(J),E=dA(A.manifest);for(let J of IQ(A.manifest)){let K={...J,pluginId:Q};switch(J.type){case"opener":if(A.grants.includes("opener"))C(B.register(J.uri,K));break;case"command":C(this.platform.commands.register({id:J.uri,title:J.title||`${E}: ${J.name}`,category:J.category||E,icon:J.icon,when:J.when,offline:J.offline,palette:J.palette,pluginId:Q,actions:(...L)=>new IJ(Q,J.name,L)}));break;case"statusItem":{let L=J.command?this.#E(A,J.command,E,`status item “${J.name}”`):null;C(B.register(J.uri,{...K,command:L,html:"",visible:!1}));break}case"register":{C(B.register(J.uri,K));let L=this.platform.context.own(J.uri,J.default);A.registers.set(J.uri,L.set),C(()=>{A.registers.delete(J.uri),L.dispose()});break}case"keymap":{let L=A.files.get(J.path);if(!L){this.platform.notifications.warn(`Plugin "${E}": keymap file "${J.path}" is not in the package.`);break}try{let Y=this.#C(A,LL(new TextDecoder().decode(L)),E);C(B.register(J.uri,{...K,bindings:Y}))}catch(Y){this.platform.notifications.warn(`Plugin "${E}": ${Y.message}`)}break}case"indexer":break}}}#C(A,Q,B){let C=[];for(let E of Q){let J=this.#E(A,E.command,B,`shortcut ${E.key}`);if(J)C.push({...E,command:J})}return C}#E(A,Q,B,C){let E=xQ(A.manifest,Q);if(IQ(A.manifest).some((K)=>K.uri===E&&K.type==="command"))return E;if(!dC(A.manifest,Q))return this.platform.notifications.warn(`Plugin "${B}": ${C} runs "${Q}", which it isn't allowed to run — ignored.`),null;return Q}list(){return[...this.plugins.values()].map((A)=>({id:A.id,name:dA(A.manifest),version:A.manifest.version,status:A.status,capabilities:A.grants,error:A.error||null,hasUi:A.hasUi,badge:A.badge||null,trust:A.trust||null,settingsSchema:A.manifest.settings||[],endpoints:cC(rQ(A.manifest)),responsive:!!A.responsive,manifest:A.live||null,features:this.#J(A)}))}#J(A){let Q;try{Q=IQ(A.manifest)}catch{return[]}return Q.map((B)=>({kind:B.type,id:B.uri,name:B.name,title:B.title||B.name,offline:!!B.offline,available:this.#K(A,B)}))}#K(A,Q){if(A.status!=="active"||!A.responsive)return!1;return this.online||!!Q.offline}isAvailable(A){if(!A?.pluginId)return!0;let Q=this.plugins.get(A.pluginId);if(!Q)return!1;return this.#K(Q,A)}canGrant(A,Q){return!KE.has(A)||!!Q}async install(A,{grants:Q,trust:B}={}){let C=EQ(A.manifest),E=LE(A.manifest),J=(Q||E).filter((X)=>a8.includes(X)&&E.includes(X)),K=F$(A.manifest,J)?"account":"device";if(K==="account"){if(!A.raw)throw Error("Package bytes unavailable for a server install");await this.platform.api.installPlugin(A.raw,J)}let L=J.includes("storage")?XE(A.manifest,B):{plugin:!1,domain:!1},Y={id:C,manifest:A.manifest,files:Object.fromEntries([...A.files.entries()]),grants:J,storage:L,trust:B||null,scope:K,settings:{},secrets:{},installedAt:Date.now()};return await this.registry.save(Y),this.#Y(Y),await this.#X(Y),this.plugins.get(C)}async restore(){let A=[];try{A=await this.registry.list()}catch{}for(let Q of A)try{this.#Y(Q),this.#X(Q).catch((B)=>console.error("restore plugin failed",Q.id,B))}catch(B){console.error("skipping corrupt plugin record",Q?.id,B),this.platform.notifications.warn(`Couldn't restore plugin "${Q?.manifest?dA(Q.manifest):Q?.id||"unknown"}" — its saved data looks corrupt.`)}this.#L(A).catch(()=>{})}async#L(A){let Q;try{Q=(await this.platform.api.installedPlugins()).plugins||[]}catch{return}let B=new Set(Q.map((L)=>L.pluginId)),C=new Set(A.map((L)=>L.id)),E=0,J=0,K=0;for(let L of A){if(L.scope!=="account"||B.has(L.id))continue;try{await this.platform.api.installPlugin(SL(U$(L.files)),L.grants||[])}catch(Y){console.error("re-upload plugin failed",L.id,Y),E++}}for(let L of Q){if(C.has(L.pluginId))continue;try{let Y=tQ(await this.platform.api.pluginPackage(L.pluginId)),X=L.grants||[],H={id:L.pluginId,manifest:Y.manifest,files:Object.fromEntries([...Y.files.entries()]),grants:X,storage:X.includes("storage")?{plugin:!0,domain:!!L.sharedStorage}:{plugin:!1,domain:!1},trust:null,scope:"account",settings:{},secrets:{},installedAt:L.createdAt||Date.now()};await this.registry.save(H),this.#Y(H),await this.#X(H),J++}catch(Y){console.error("sync plugin failed",L.pluginId,Y),K++}}if(J)this.platform.notifications.info(`Synced ${J} account plugin${J>1?"s":""} from the server.`);if(E||K){let L=[];if(K)L.push(`${K} couldn't be downloaded`);if(E)L.push(`${E} couldn't be uploaded`);this.platform.notifications.warn(`Some account plugins didn't sync: ${L.join(", ")}.`)}}#Y(A){let Q=(A.manifest.settings||[]).filter((B)=>!B.secret);if(Q.length)A._settingsDispose=this.platform.settings.scopedFor(A.id).register(Q.map((B)=>({...B,category:dA(A.manifest)})))}async#X(A){if(this.plugins.get(A.id)?.status==="active")return;let Q={...A,iframe:null,status:"loading",error:null,disposers:[],channel:null,registers:new Map,hasUi:!1,responsive:!1,frame:null,frames:new Set,storage:A.storage||(A.grants?.includes("storage")?XE(A.manifest,A.trust):{plugin:!1,domain:!1}),files:W$(A.files)};this.plugins.set(A.id,Q);try{this.#B(Q)}catch(B){console.error("registering contributions failed",A.id,B)}this.#A();try{let B=await this.#Q(Q,"primary");if(this.plugins.get(A.id)!==Q)return this.frames.destroy(B),Q;Q.frame=B,Q.iframe=B.iframe,Q.channel=B.channel,Q.status="active",Q.responsive=!0,this.#H(Q).then(()=>this.#A()),this.#G()}catch(B){Q.status="error",Q.error=B?.message||String(B),this.platform.notifications.error(`Plugin "${dA(A.manifest)}" failed to load: ${Q.error}`)}return this.#A(),Q}async setSecret(A,Q,B){let C=await this.registry.get(A);if(!C)return;C.secrets={...C.secrets,[Q]:B},await this.registry.save(C);let E=this.plugins.get(A);if(E)E.secrets=C.secrets;E?.channel?.emit("settings:changed",{key:Q,value:"••••"})}async getSecret(A,Q){return(await this.registry.get(A))?.secrets?.[Q]??""}#G(){if(this._heartbeat||!this.heartbeatMs)return;if(this._heartbeat=setInterval(()=>this.#Z(),this.heartbeatMs),this._heartbeat?.unref)this._heartbeat.unref()}#$(){if(this._heartbeat)clearInterval(this._heartbeat);this._heartbeat=null}async#Z(){if(this._probing)return;this._probing=!0;try{let A=!1;for(let Q of this.plugins.values())if(Q.status==="active")A=await this.#H(Q)||A;if(A)this.#A()}finally{this._probing=!1}}invokeCommand(A,Q,B=[]){return this.plugins.get(A)?.channel?.call("command:execute",{id:Q,args:B})}setHeartbeat(A){if(this.heartbeatMs=A,this.#$(),A&&[...this.plugins.values()].some((Q)=>Q.status==="active"))this.#G()}async#H(A){if(A.status!=="active"||!A.channel)return!1;let Q={responsive:A.responsive,sig:n8(A.live)};try{A.live=await A.channel.call("manifest",{},{timeout:4000}),A.responsive=!0}catch{A.responsive=!1}return Q.responsive!==A.responsive||Q.sig!==n8(A.live)}async setOnline(A){if(this.online===A)return;this.online=A,await Promise.all([...this.plugins.values()].filter((Q)=>Q.status==="active").map(async(Q)=>{try{Q.channel?.emit("connectivity",{online:A})}catch{}for(let B of Q.frames||[])try{B.channel?.emit("connectivity",{online:A})}catch{}await this.#H(Q)})),this.#A()}async refresh(A){let Q=this.plugins.get(A);if(Q)await this.#H(Q),this.#A()}mountPanel(A,Q,{width:B=380,height:C=480}={}){let E=this.plugins.get(A);if(!E?.frame)return null;return Q.style.width=`${B}px`,Q.style.height=`${C}px`,this.dock.place(E.frame,Q,50),E.hasUi=!0,()=>this.dock.hide(E.frame)}mountViewer(A,Q,B,C,E={}){let J=this.plugins.get(A);if(!J)return E.onError?.("Plugin is not available"),null;let K=this.dock.docked;if(K&&K.record===J&&K.node?.id===B.id&&K.openerId===C)return this.dock.undock(K),this.dock.place(K,Q,3),E.onReady?.(),()=>this.#D(K);let L=this.platform.contributions.get(C),Y={cancelled:!1,frame:null};return this.#Q(J,"viewer",L?.entry).then(async(X)=>{if(Y.cancelled){this.frames.destroy(X);return}Y.frame=X,X.node=B,X.openerId=C,J.frames.add(X),this.dock.place(X,Q,3);try{if(await X.channel?.call("opener:open",{openerId:C,file:B,context:{}}),!Y.cancelled)E.onReady?.()}catch(H){if(!Y.cancelled)E.onError?.(H?.message||"Failed to open")}}).catch((X)=>{if(console.error("viewer frame failed to load",X),!Y.cancelled)E.onError?.(X?.message||"This viewer failed to load")}),J.hasUi=!0,()=>{if(Y.cancelled=!0,Y.frame)this.#D(Y.frame)}}#D(A){if(A.dock?.enabled&&!A.dock.dismissed)this.dock.dock(A);else this.frames.destroy(A)}async uninstall(A,{wipeData:Q=!0}={}){let B=this.plugins.get(A),C=B?.manifest?dA(B.manifest):A,E=B?.scope==="account"||(await this.registry.get(A).catch(()=>null))?.scope==="account";if(Q&&E)try{await this.platform.api.uninstallPluginServer(A)}catch(L){this.platform.notifications.error(`Couldn't uninstall "${C}" from the server: ${L.message}. It's still installed.`);return}if(B){try{B.channel?.emit("deactivate")}catch{}for(let L of B.disposers)try{L()}catch{}B._settingsDispose?.();for(let L of[...B.frames||[]])this.frames.destroy(L);if(B.frame)this.dock.stopPlace(B.frame),this.media.releaseActions(B.frame);B.channel?.dispose(),B.iframe?.remove(),this.plugins.delete(A)}let J=[];if(Q){if(!E)await this.platform.api.request("DELETE",`/api/plugins/${encodeURIComponent(A)}/data`).catch(()=>J.push("server-side data"));await this.clientDb.drop(`plg:${A}`).catch(()=>J.push("on-device data"))}let K=!1;try{await this.registry.remove(A)}catch(L){K=!0,console.error("removing the persisted plugin record failed",A,L)}if(![...this.plugins.values()].some((L)=>L.status==="active"))this.#$();if(this.#A(),K)this.platform.notifications.error(`Removed "${C}", but its saved record couldn't be deleted — it may come back when you reload.`);else if(J.length)this.platform.notifications.warn(`Uninstalled "${C}", but couldn't clear its ${J.join(" and ")}.`)}fetchAssetlinks=async(A)=>{return(await this.platform.api.request("GET","/api/plugins/assetlinks",{query:{domain:A}}))?.assetlinks||null};assessTrust(A){return hL(A,this.fetchAssetlinks)}}function W$(A){let Q=new Map;for(let[B,C]of Object.entries(A))Q.set(B,C instanceof Uint8Array?C:new Uint8Array(C));return Q}function U$(A){let Q={};for(let[B,C]of Object.entries(A||{}))Q[B]=C instanceof Uint8Array?C:new Uint8Array(C);return Q}function F$(A,Q){if(Q.includes("storage"))return!0;return T0(A).length>0}function n8(A){if(!A)return"";return`${A.online?1:0}|${[...A.handlers||[]].sort().join(",")}`}var s8=["auto","desktop","phone","tv"],I$=720,R$=1100,M$=/\b(smart-?tv|smarttv|appletv|googletv|android\s*tv|hbbtv|netcast|web0s|webos|tizen|viera|bravia|aquos|crkey|nettv|dtv|philipstv|roku|aft[a-z]{1,3})\b/i;function V$(A="",Q=0){if(!A)return!1;return M$.test(A)&&Q>=R$}class xJ{#A;constructor({window:A=globalThis,settings:Q=null}={}){this.window=A,this.settings=Q,this.urlOverride=N$(A),this.#A=this.#B(),this.cell=c(this.#A),this._onResize=()=>this.refresh()}get(){return this.#A}observe(){return this.cell}install(){if(this.window.addEventListener?.("resize",this._onResize),this.window.addEventListener?.("orientationchange",this._onResize),this.settings)TQ(this.settings.observe(),()=>this.refresh());return this.#Q(this.#A),this}dispose(){this.window.removeEventListener?.("resize",this._onResize),this.window.removeEventListener?.("orientationchange",this._onResize)}refresh(){let A=this.#B();if(A.mode===this.#A.mode&&A.width===this.#A.width&&A.height===this.#A.height&&A.coarse===this.#A.coarse)return;this.#A=A,this.#Q(A),this.cell.setValue(A)}#Q(A){let Q=this.window.document?.documentElement;if(Q)Q.dataset.layout=A.mode}#B(){let A=this.window,Q=A.innerWidth||1280,B=A.innerHeight||800,C=z$(A,"(pointer: coarse)"),E=A.navigator?.userAgent||"",J=this.urlOverride||this.settings?.get?.("workbench.layout")||"auto";return{mode:J!=="auto"&&s8.includes(J)?J:q$({width:Q,coarse:C,ua:E}),width:Q,height:B,coarse:C,forced:J!=="auto"}}}function q$({width:A,coarse:Q,ua:B}){if(V$(B,A))return"tv";if(A<=I$)return"phone";return"desktop"}function z$(A,Q){try{return!!A.matchMedia?.(Q)?.matches}catch{return!1}}function N$(A){try{let Q=new URL(A.location.href).searchParams.get("ui");return Q&&s8.includes(Q)?Q:null}catch{return null}}var r8='a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])',t8=".launch-item, .grid-tile, .sheet-row, .inbox-item, .plugin-card, .act-task, .act-issue, .chapter",P$=`${r8}, ${t8}`,O$=new Set(["BrowserBack","GoBack","Backspace"]),j$=new Set([10009,461]),w$={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down"},S$=new Set(["A","BUTTON","INPUT","SELECT","TEXTAREA"]);class kJ{constructor({workbench:A,viewport:Q,window:B=globalThis}){this.viewport=Q,this.window=B,this.active=!1,this._onKey=(C)=>this.handleKey(C),this._observer=null,this._pending=0,this._bootstrapped=!1}install(){if(this.viewport)TQ(this.viewport.observe(),(A)=>this.setActive(A.mode==="tv"));return this.setActive(this.viewport?.get().mode==="tv"),this}setActive(A){if(A===this.active)return;if(this.active=A,A)this.window.addEventListener?.("keydown",this._onKey),this.#A(),this.prime(),this.window.setTimeout?.(()=>this.prime(),60);else this.window.removeEventListener?.("keydown",this._onKey),this._observer?.disconnect(),this._observer=null,this._bootstrapped=!1}prime(){this.candidates(),this.focusFirst()}#A(){let A=this.window.MutationObserver;if(!A||this._observer)return;this._observer=new A(()=>{if(this._pending)return;this._pending=this.window.requestAnimationFrame?.(()=>{if(this._pending=0,this.active)this.prime()})||0}),this._observer.observe(this.window.document.body,{childList:!0,subtree:!0})}handleKey(A){if(!this.active||A.defaultPrevented||A.altKey||A.ctrlKey||A.metaKey)return;let Q=this.window.document,B=Q.activeElement;if(O$.has(A.key)||j$.has(A.keyCode)){if(A.key==="Backspace"&&o8(B)&&(B.value??"").length>0)return;A.preventDefault(),this.goBack();return}let C=w$[A.key];if(!C){if(A.key==="Enter"&&B&&!S$.has(B.tagName)&&B.matches(t8))A.preventDefault(),B.click();return}if((C==="left"||C==="right")&&o8(B)&&!_$(B,C))return;let E=B&&B!==Q.body?B:null,J=this.find(C,E);if(!J)return;A.preventDefault(),i8(J)}goBack(){if(this.workbench?.closeOverlays())return;this.window.history?.back?.()}candidates(){let A=this.window.document,Q=[];for(let B of A.querySelectorAll(P$)){if(B.getAttribute?.("aria-hidden")==="true"||B.hasAttribute?.("disabled"))continue;let C=B.getBoundingClientRect();if(C.width<2||C.height<2)continue;if(C.bottom<0||C.top>this.window.innerHeight||C.right<0||C.left>this.window.innerWidth)continue;if(!B.matches(r8)&&!B.hasAttribute("tabindex"))B.setAttribute("tabindex","0");Q.push({el:B,rect:C})}return Q}find(A,Q){let B=this.candidates();if(!B.length)return null;let C=Q&&Q.getBoundingClientRect&&Q.getBoundingClientRect().width?Q.getBoundingClientRect():null;if(!C)return B[0].el;let E=null,J=1/0;for(let{el:K,rect:L}of B){if(K===Q)continue;let Y=T$(C,L,A);if(Y==null||Y>=J)continue;J=Y,E=K}return E}focusFirst(){if(this._bootstrapped)return;let A=this.window.document;if(A?.activeElement&&A.activeElement!==A.body)return;let Q=this.candidates();if(!Q.length)return;let B=Q.find((C)=>C.el.classList?.contains("launch-input"))||Q[0];i8(B.el),this._bootstrapped=!0}}function _$(A,Q){let{selectionStart:B,selectionEnd:C}=A;if(B==null||C==null)return!0;if(B!==C)return!1;return Q==="left"?B===0:C>=(A.value??"").length}function o8(A){if(!A)return!1;let Q=A.tagName;if(Q==="TEXTAREA")return!0;if(A.isContentEditable)return!0;if(Q!=="INPUT")return!1;return!["checkbox","radio","button","submit","range","file"].includes(A.type)}function i8(A){A.focus?.({preventScroll:!0}),A.scrollIntoView?.({block:"nearest",inline:"nearest"})}function T$(A,Q,B){let C=B==="up"||B==="down",[E,J]=C?B==="down"?[A.bottom,Q.top]:[A.top,Q.bottom]:B==="right"?[A.right,Q.left]:[A.left,Q.right],L=B==="down"||B==="right"?J-E:E-J;if(L<-2)return null;let[Y,X,H,G]=C?[A.left,A.right,Q.left,Q.right]:[A.top,A.bottom,Q.top,Q.bottom],D=Math.max(0,Math.max(Y,H)-Math.min(X,G)),U=Math.abs((Y+X)/2-(H+G)/2);return Math.max(0,L)+D*3+U*0.2}function DC(){if(typeof window>"u")return null;return window.SpeechRecognition||window.webkitSpeechRecognition||null}function G0(){let A=DC();return!!A&&typeof A.available==="function"}var gJ=(A)=>({langs:[A],processLocally:!0});async function e8(A=navigator.language||"en-US"){if(!G0())return"unavailable";try{return await DC().available(gJ(A))}catch{return"unavailable"}}async function AY(A=navigator.language||"en-US"){if(typeof DC()?.install!=="function")return!1;try{return await DC().install(gJ(A))}catch{return!1}}function QY({lang:A=navigator.language||"en-US",onText:Q,onEnd:B,onError:C}={}){if(!G0())throw Error("On-device speech recognition is not available here");let E=new(DC());E.lang=A,E.interimResults=!0,E.continuous=!1,E.options=gJ(A),E.processLocally=!0;let J=!1;E.onresult=(K)=>{let L="",Y=!1;for(let X=K.resultIndex;X<K.results.length;X++)if(L+=K.results[X][0].transcript,K.results[X].isFinal)Y=!0;Q?.(L.trim(),{final:Y})},E.onerror=(K)=>{if(K.error==="no-speech"||K.error==="aborted")return;C?.(Error(K.error||"Speech recognition failed"))},E.onend=()=>{if(!J)J=!0,B?.()};try{E.start()}catch(K){J=!0,C?.(K),B?.()}return{stop(){if(J)return;J=!0;try{E.stop()}catch{}B?.()}}}class yJ{#A;constructor({notifications:A,settings:Q}={}){this.notifications=A,this.settings=Q,this.session=null,this.#A={supported:G0(),status:"unknown",listening:!1},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async refresh(){if(!this.#A.supported)return"unavailable";let A=await e8(this.#B());return this.#Q({status:A}),A}#B(){return this.settings?.get?.("search.voiceLanguage")||navigator.language||"en-US"}canListen(){return this.#A.supported&&(this.#A.status==="available"||this.#A.status==="downloadable")}async run({onText:A}={}){if(this.openSearchSurface(),await this.focusInput(),!this.#A.supported)return{listening:!1,reason:"unsupported"};let Q=this.#A.status==="unknown"?await this.refresh():this.#A.status;if(Q==="downloadable"){this.notifications?.info("Downloading the on-device voice model — this happens once.");let B=await AY(this.#B());if(this.#Q({status:B?"available":"unavailable"}),!B)return{listening:!1,reason:"install-failed"}}else if(Q!=="available")return{listening:!1,reason:Q};return this.toggle({onText:A})}toggle({onText:A}={}){if(this.session)return this.stop(),{listening:!1};try{return this.session=QY({lang:this.#B(),onText:A,onEnd:()=>{this.session=null,this.#Q({listening:!1})},onError:(Q)=>{if(this.session=null,this.#Q({listening:!1}),!/not-allowed|service-not-allowed|denied/i.test(Q.message))this.notifications?.warn(`Couldn't listen: ${Q.message}`)}}),this.#Q({listening:!0}),{listening:!0}}catch(Q){return this.notifications?.warn(`Couldn't listen: ${Q.message}`),{listening:!1,reason:"error"}}}stop(){this.session?.stop(),this.session=null,this.#Q({listening:!1})}openSearchSurface(){let A=this.workbench;if(!A)return;if(A.state.activity==="home"&&!A.nav?.get?.().activeTabId)A.closeSearchModal?.();else A.openSearchModal()}focusInput({tries:A=12}={}){return new Promise((Q)=>{let B=A,C=()=>{let E=document.querySelector(".search-modal .launch-input")||document.querySelector(".launch-input");if(E){E.focus();try{E.setSelectionRange(E.value.length,E.value.length)}catch{}Q(document.activeElement===E);return}if(--B<=0){Q(!1);return}requestAnimationFrame(C)};C()})}}class hJ{constructor({api:A,settings:Q=null}){this.api=A,this.settings=Q,this.cache=new Map,this._queue=new Map,this._timer=null}get needed(){let A=this.settings?.get("media.signedUrls");if(A==="always")return!0;if(A==="never")return!1;return!!this.api.token?.()}cacheKey(A){return this.api.downloadUrl(A)}async url(A,{op:Q="media"}={}){if(!this.needed)return{url:this.api.downloadUrl(A,{attachment:Q==="download"}),expiresAt:1/0};let B=`${Q}:${A}`,C=this.cache.get(B);if(C&&this.#A(C))return C;return this.#Q(A,Q)}invalidate(A,Q="media"){if(A==null)this.cache.clear();else this.cache.delete(`${Q}:${A}`)}#A(A){if(A.expiresAt===1/0)return!0;let Q=A.expiresAt-A.mintedAt;return Date.now()<A.mintedAt+Q*0.8}#Q(A,Q){if(!this._queue.has(Q))this._queue.set(Q,new Map);let B=this._queue.get(Q),C=B.get(A);if(C)return C.promise;let E,J,K=new Promise((L,Y)=>{E=L,J=Y});if(B.set(A,{resolve:E,reject:J,promise:K}),B.size>=200)this.#B();else if(!this._timer)this._timer=setTimeout(()=>this.#B(),20);return K}async#B(){clearTimeout(this._timer),this._timer=null;let A=this._queue;this._queue=new Map;for(let[Q,B]of A){let C=[...B.keys()];try{let E=await this.api.mintUrls(C,Q),J=Date.now();for(let[K,L]of this.cache)if(L.expiresAt&&L.expiresAt<J)this.cache.delete(K);for(let[K,L]of B){let Y=E.urls?.[K];if(Y){let X={url:Y.url,expiresAt:Y.expiresAt,mintedAt:J};this.cache.set(`${Q}:${K}`,X),L.resolve(X)}else L.reject(Error(E.failed?.[K]==="not_found"?"That file is gone":"You cannot open that file"))}}catch(E){for(let J of B.values())J.reject(E)}}}}class vJ{constructor({api:A,actor:Q=()=>"local"}={}){this.api=A,this.actor=Q,this.local=x$(),this.pending=new Set,this.server=new Map,this.timer=null}async get(A,Q){let B={...this.server.get(bJ(A,Q))||{}};for(let[C,E]of Object.entries(this.local[A]?.[Q]||{}))if(E.present)B[C]=E.value;else delete B[C];return this.#B(A,Q),B}async set(A,Q,B,C){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:C,present:!0}),{ok:!0}}async remove(A,Q,B){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:null,present:!1}),{ok:!0}}#A(A,Q,B,C){this.local[A]||={},this.local[A][Q]||={},this.local[A][Q][B]={...C,at:Date.now(),actor:this.actor()},BY(this.local),this.pending.add(bJ(A,Q)),this.#Q()}#Q(){if(this.timer)return;this.timer=setTimeout(()=>{this.timer=null,this.flush().catch(()=>{})},2000)}async flush(){for(let A of[...this.pending]){let[Q,B]=A.split("\x00"),C=this.local[Q]?.[B];if(!C){this.pending.delete(A);continue}let E=Object.entries(C).map(([J,K])=>({key:J,value:K.value,remove:!K.present}));try{let J=await this.api.request("POST",`/api/items/${encodeURIComponent(B)}/data`,{query:{scope:Q},body:{entries:E}});this.pending.delete(A),this.server.set(A,J?.data||{}),delete this.local[Q][B],BY(this.local)}catch{}}}#B(A,Q){let B=bJ(A,Q);if(this.inflight?.has(B))return;(this.inflight||=new Set).add(B),this.api.request("GET",`/api/items/${encodeURIComponent(Q)}/data`,{query:{scope:A}}).then((C)=>{this.server.set(B,C?.data||{})}).catch(()=>{}).finally(()=>this.inflight.delete(B))}}var bJ=(A,Q)=>`${A}\x00${Q}`;function x$(){try{let A=JSON.parse(localStorage.getItem("trove.itemData"))||{};return A&&typeof A==="object"?A:{}}catch{return{}}}function BY(A){try{let Q=[];for(let[B,C]of Object.entries(A))for(let[E,J]of Object.entries(C))for(let[K,L]of Object.entries(J))Q.push({scope:B,nodeId:E,key:K,cell:L});if(Q.length>5000){Q.sort((B,C)=>(B.cell.at||0)-(C.cell.at||0));for(let{scope:B,nodeId:C,key:E}of Q.slice(0,Q.length-5000))delete A[B][C][E]}localStorage.setItem("trove.itemData",JSON.stringify(A))}catch{}}var CY=(A)=>Math.floor(A/4194304),k$=(A,Q)=>{let B=new Uint8Array(Q),C=0;for(let E of A)B.set(E,C),C+=E.length;return B};class fJ{constructor({api:A,mediaUrls:Q}){this.api=A,this.mediaUrls=Q,this.kept=new Map,this.listeners=new Set}onProgress(A){return this.listeners.add(A),()=>this.listeners.delete(A)}#A(A){let Q=this.status(A);for(let B of[...this.listeners])try{B(A,Q)}catch{}}#Q(A,Q,B){return`${this.mediaUrls.cacheKey(A)}&chunk=${Q||"none"}:4194304:${B}`}async#B(A){if(!("caches"in globalThis))return null;return caches.open(A).catch(()=>null)}async#C(A){let Q=await this.#B("trove-files-v1");if(!Q)return null;return Q.match(this.mediaUrls.cacheKey(A),{ignoreVary:!0}).catch(()=>null)}async read(A,{start:Q=0,end:B,signal:C}={}){let E=await this.#C(A);if(E){let K=await E.blob(),L=B==null?K.size:Math.min(B,K.size);return{bytes:new Uint8Array(await K.slice(Q,L).arrayBuffer()),etag:E.headers.get("etag"),total:K.size}}let J=this.kept.get(A);if(!J)return this.api.readRange(A,{start:Q,end:B,signal:C});return this.#E(A,J,Q,B,C)}async#E(A,Q,B,C,E){let J=await this.#B("trove-chunks-v1");if(!J)return this.api.readRange(A,{start:B,end:C,signal:E});if(Q.total==null){let X=await this.api.readRange(A,{start:0,end:1,signal:E});Q.total=X.total,Q.etag=X.etag}let K=Math.min(C==null?Q.total:C,Q.total);if(K<=B)return{bytes:new Uint8Array(0),etag:Q.etag,total:Q.total};let L=[],Y=0;for(let X=CY(B);X<=CY(K-1);X++){let H=await this.#J(A,Q,X,J,E),G=Math.max(0,B-X*4194304),D=Math.min(H.length,K-X*4194304),U=H.subarray(G,D);L.push(U),Y+=U.length}return{bytes:k$(L,Y),etag:Q.etag,total:Q.total}}async#J(A,Q,B,C,E){let J=this.#Q(A,Q.etag,B),K=await C.match(J).catch(()=>null);if(K)return Q.have.add(B),new Uint8Array(await K.arrayBuffer());let L=B*4194304,Y=Math.min(L+4194304,Q.total),X=await this.api.readRange(A,{start:L,end:Y,signal:E});if(X.etag&&Q.etag&&X.etag!==Q.etag)await this.#L(A),Q.have.clear(),Q.etag=X.etag,Q.total=X.total??Q.total;return await C.put(J,new Response(X.bytes)).catch(()=>{}),Q.have.add(B),this.#A(A),X.bytes}async start(A){if(this.kept.get(A))return this.status(A);let B=await this.api.readRange(A,{start:0,end:1}),C=new AbortController,E={etag:B.etag,total:B.total,filling:!0,done:!1,failed:null,have:new Set,controller:C};return this.kept.set(A,E),this.#A(A),this.#K(A,E,C.signal).catch((J)=>{E.filling=!1,E.failed=J?.message||String(J),this.#A(A)}),this.status(A)}async#K(A,Q,B){let C=await this.#B("trove-chunks-v1");if(!C)throw Error("This browser has no Cache Storage, so nothing can be kept offline");let E=Math.max(1,Math.ceil((Q.total||0)/4194304));for(let J=0;J<E;J++){if(B.aborted)return;await this.#J(A,Q,J,C,B)}Q.filling=!1,Q.done=!0,this.#A(A)}status(A){let Q=this.kept.get(A);if(!Q)return{kept:!1,loaded:0,total:null,ratio:0,filling:!1,done:!1,error:null};let B=Q.total??null,C=B?Math.ceil(B/4194304)-1:-1,E=0;for(let J of Q.have)E+=J===C?B-C*4194304:4194304;return{kept:!0,total:B,loaded:E,ratio:B?Math.min(1,E/B):0,filling:Q.filling,done:Q.done,error:Q.failed}}cancel(A){let Q=this.kept.get(A);if(!Q)return;Q.controller?.abort(),Q.filling=!1,this.#A(A)}async remove(A){let Q=this.kept.get(A);this.cancel(A),this.kept.delete(A),Q?.have?.clear(),await this.#L(A),this.#A(A)}async#L(A){let Q=await this.#B("trove-chunks-v1");if(!Q)return;let B=`${this.mediaUrls.cacheKey(A)}&chunk=`,C=await Q.keys().catch(()=>[]);for(let E of C)if(E.url.startsWith(B))await Q.delete(E).catch(()=>{})}}function g$(){try{return localStorage.getItem("trove.token")||null}catch{return null}}function EY({baseUrl:A=""}={}){let Q=new x0,B=new g0,C=new u0,E=new y0(Q,B,C),J=new f0,K=new UB(Q,E,B,J),L=new m0({baseUrl:A,token:()=>g$()}),Y=new xJ({settings:J}),X=new kJ({viewport:Y}),H=new yJ({notifications:C,settings:J}),G={reactive:tK,contributions:Q,context:B,commands:E,keybindings:K,settings:J,notifications:C,api:L,viewport:Y,spatialNav:X,voice:H};return G.mediaUrls=new hJ({api:G.api,settings:J}),G.fileChunks=new fJ({api:G.api,mediaUrls:G.mediaUrls}),G.itemData=new vJ({api:G.api,actor:()=>G.identity?.get?.()?.principal?.id||"local"}),G.plugins=new TJ(G),E.availability=(D)=>G.plugins.isAvailable(D),y$(G),Y.refresh(),G}function y$(A){A.settings.register([{key:"workbench.theme",type:"enum",enum:["dark","light","midnight"],enumLabels:["Dark","Light","Midnight"],default:"dark",title:"Color theme",category:"Appearance",order:1},{key:"workbench.density",type:"enum",enum:["comfortable","compact"],default:"comfortable",title:"List density",category:"Appearance",order:2},{key:"workbench.layout",type:"enum",enum:["auto","desktop","phone","tv"],enumLabels:["Automatic","Desktop","Phone","TV / remote"],default:"auto",title:"Layout",description:"Automatic follows the screen size. Choose TV for d-pad remote navigation.",category:"Appearance",order:3},{key:"explorer.sort",type:"enum",enum:["name","size","updatedAt"],enumLabels:["Name","Size","Modified"],default:"name",title:"Sort files by",category:"Explorer",order:1},{key:"explorer.sortOrder",type:"enum",enum:["asc","desc"],default:"asc",title:"Sort order",category:"Explorer",order:2},{key:"explorer.confirmDelete",type:"boolean",default:!0,title:"Confirm before deleting",category:"Explorer",order:3},{key:"search.mode",type:"enum",enum:["hybrid","semantic","keyword"],default:"hybrid",title:"Search mode",description:"Hybrid blends semantic meaning with keyword matches.",category:"Search",order:1},{key:"uploads.concurrency",type:"number",minimum:1,maximum:8,default:4,title:"Parallel upload parts",category:"Transfers",order:1},{key:"openers.associations",type:"object",hidden:!0,title:"Default viewers",default:{".md":"core.markdown",".markdown":"core.markdown"}},{key:"explorer.view",type:"string",hidden:!0,title:"Results view"},{key:"media.signedUrls",type:"enum",enum:["auto","always","never"],default:"auto",hidden:!0,title:"Signed media URLs"}]),A.contributions.register("keymap.default",{type:"keymap",bindings:[{key:"mod+shift+p",command:"workbench.showCommandPalette"},{key:"mod+p",command:"workbench.quickOpen"},{key:"mod+shift+f",command:"workbench.view.home"},{key:"mod+shift+e",command:"workbench.view.home"},{key:"mod+,",command:"workbench.openSettings"},{key:"mod+shift+l",command:"explorer.copyLink"},{key:"mod+u",command:"explorer.upload"},{key:"delete",command:"explorer.delete",when:"view.active == 'home' && explorer.hasSelection"},{key:"escape",command:"workbench.closeOverlays"},{key:"f5",command:"explorer.refresh"},{key:"mod+shift+i",command:"workbench.toggleInfoPanel"},{key:"mod+shift+v",command:"search.voice"},{key:"browsersearch",command:"search.voice"}]})}function JY(A,{workbench:Q,overlay:B,navigation:C,explorer:E}){let J=Q.observe(),K=C.observe(),L=B.observe(),Y=E.observe(),X={"view.active":BA([J],(G)=>G.activity),"sidebar.visible":BA([J],(G)=>G.sidebarVisible),"searchModal.open":BA([J],(G)=>!!G.searchModal),"sheet.open":BA([J],(G)=>G.sheet||""),"infoPanel.open":BA([J],(G)=>!!G.infoPanel),"palette.open":BA([L],(G)=>!!G.palette),"editor.open":BA([K],(G)=>!!G.activeFile),"editor.openerId":BA([K],(G)=>G.stack?.at(-1)?.openerId||""),"editor.contentType":BA([K],(G)=>G.activeFile?.contentType||""),"explorer.collectionId":BA([Y],(G)=>G.collectionId??null),"explorer.hasSelection":BA([Y],(G)=>(G.selection?.length||0)>0)},H=Object.entries(X).map(([G,D])=>A.register(G,D));return()=>H.forEach((G)=>G())}function KY(A,Q){let B=Q.observe(),C=[A.register("viewport.mode",BA([B],(E)=>E.mode)),A.register("viewport.phone",BA([B],(E)=>E.mode==="phone")),A.register("viewport.tv",BA([B],(E)=>E.mode==="tv"))];return()=>C.forEach((E)=>E())}var LY="trove.recents",h$=12;class mJ{#A;constructor(){this.#A={stack:[{kind:"search"}],activeTabId:null,activeFile:null,recents:b$()},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}#B(){return this.#A.stack[this.#A.stack.length-1]}activeTab(){let A=this.#B();return A?.kind==="file"?A:null}#C(A,{history:Q=!0}={}){let B=A[A.length-1],C=B&&B.kind==="file"?B:null;if(this.#Q({stack:A,activeTabId:C?C.id:null,activeFile:C?C.node:null}),Q)this.#E()}reset(){this.#C([{kind:"search"}])}openFile(A,Q,{reset:B=!1}={}){let C={kind:"file",id:A.id,node:A,openerId:Q},E;if(B)E=[{kind:"search"},C];else{let J=this.#A.stack.findIndex((K)=>K.kind==="file"&&K.id===A.id);if(J>=0)E=this.#A.stack.slice(0,J+1),E[J]=C;else E=[...this.#A.stack,C]}this.#J(A),this.#C(E)}back(){if(this.#A.stack.length<=1)return;try{history.back()}catch{this.pop()}}pop(){if(this.#A.stack.length>1)this.#C(this.#A.stack.slice(0,-1),{history:!1})}forget(A){let Q=this.#A.recents.filter((C)=>C.id!==A);if(Q.length!==this.#A.recents.length)this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.filter((C)=>!(C.kind==="file"&&C.id===A));this.#C(B.length?B:[{kind:"search"}],{history:!1})}updateTabNode(A){let Q=this.#A.recents.map((C)=>C.id===A.id?{...C,name:A.name,contentType:A.contentType||C.contentType,...RB(A)?{thumbnail:RB(A)}:{}}:C);if(Q.some((C,E)=>C!==this.#A.recents[E]))this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.map((C)=>C.kind==="file"&&C.id===A.id?{...C,node:A}:C);this.#C(B,{history:!1})}#E(A=!1){let Q=this.#B(),B=Q?.node,C={troveDepth:this.#A.stack.length,node:B?{id:B.id,name:B.name,contentType:B.contentType,collectionId:B.collectionId}:null,openerId:Q?.openerId||null};try{(A?history.replaceState:history.pushState).call(history,C,"")}catch{}}onPopState(A){let Q=A?.state||{},B=Q.troveDepth||1;if(B<=this.#A.stack.length)this.#C(this.#A.stack.slice(0,B),{history:!1});else if(Q.node)this.#C([...this.#A.stack,{kind:"file",id:Q.node.id,node:Q.node,openerId:Q.openerId}],{history:!1})}#J(A){if(!A)return;let Q=RB(A),C=[{id:A.id,name:A.name,contentType:A.contentType||"",collectionId:A.collectionId,...Q?{thumbnail:Q}:{}},...this.#A.recents.filter((E)=>E.id!==A.id)].slice(0,h$);this.#Q({recents:C}),uJ(C)}}function b$(){try{return JSON.parse(localStorage.getItem(LY))||[]}catch{return[]}}function uJ(A){try{localStorage.setItem(LY,JSON.stringify(A))}catch{}}class pJ{#A;constructor(A,Q=null){this.offline=Q,this.platform=A,this.api=A.api,this.#A={me:null,notifications:{items:[],unread:0},inboxOpen:!1,pushSupported:"serviceWorker"in navigator&&"PushManager"in window,pushEnabled:!1,sidecar:null,backlinks:null,posting:!1,replyTo:null},this.cell=c(this.#A),this._pollTimer=null}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async init(){try{let A=await this.api.me();this.#Q({me:A.principal,admin:!!A.admin})}catch{}if(await this.refreshNotifications(),this._pollTimer=setInterval(()=>this.refreshNotifications(),45000),this._pollTimer.unref)this._pollTimer.unref();this.#C(),window.addEventListener("focus",()=>this.refreshNotifications()),navigator.serviceWorker?.addEventListener?.("message",(A)=>{if(A.data?.type==="trove-push")this.refreshNotifications()})}async refreshNotifications(){try{let A=await this.api.notifications();this.#Q({notifications:A})}catch{}}toggleInbox(A){let Q=A??!this.#A.inboxOpen;if(this.#Q({inboxOpen:Q}),Q&&this.#A.notifications.unread)this.markAllRead()}async markAllRead(){try{await this.api.markNotificationsRead(),this.#Q({notifications:{...this.#A.notifications,unread:0,items:this.#A.notifications.items.map((A)=>({...A,read:!0}))}})}catch{}}async loadSidecar(A){if(!A)return this.#Q({sidecar:null,backlinks:null});this.#Q({sidecar:{nodeId:A,loading:!0,tags:[],comments:[],subscribers:[]}}),this.loadBacklinks(A);try{let Q=await this.api.sidecar(A);if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{...Q,loading:!1}})}catch(Q){if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{nodeId:A,loading:!1,error:Q.message,tags:[],comments:[]}})}}async loadBacklinks(A){if(!A)return this.#Q({backlinks:null});this.#Q({backlinks:{nodeId:A,items:[],loading:!0,error:null}});try{let Q=await this.api.backlinks(A);if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:Q.items||[],loading:!1,error:null}})}catch(Q){if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:[],loading:!1,error:Q.message}})}}async#B(){if(this.#A.sidecar?.nodeId)await this.loadSidecar(this.#A.sidecar.nodeId)}setReplyTo(A){this.#Q({replyTo:A})}async comment(A){let Q=this.#A.sidecar?.nodeId;if(!Q||!A.trim())return;let B=this.#A.replyTo?.id||null;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(Q)}/comments`,body:{body:A,parentId:B}}),this.#Q({replyTo:null}),this.platform.notifications.info("Offline — your comment will post when you reconnect.");return}this.#Q({posting:!0});try{await this.api.addComment(Q,{body:A,parentId:B}),this.#Q({replyTo:null}),await this.#B()}catch(C){this.platform.notifications.error(`Couldn't post comment: ${C.message}`)}finally{this.#Q({posting:!1})}}async deleteComment(A){let Q=this.#A.sidecar?.nodeId;await this.api.deleteComment(Q,A).catch((B)=>this.platform.notifications.error(B.message)),await this.#B()}async react(A,Q){let B=this.#A.sidecar?.nodeId,E=!(YY(this.#A.sidecar?.comments||[],A)?.reactions?.[Q]||[]).includes(this.#A.me?.id);try{await this.api.reactComment(B,A,Q,E)}catch(J){this.platform.notifications.error(`Couldn't react: ${J.message}`)}await this.#B()}async addTag(A,Q){let B=this.#A.sidecar?.nodeId;if(!A.trim())return;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(B)}/tags`,body:{name:A.trim(),value:Q}}),this.platform.notifications.info("Offline — tag will sync when you reconnect.");return}await this.api.setTag(B,A.trim(),Q).catch((C)=>this.platform.notifications.error(C.message)),await this.#B()}async removeTag(A){let Q=this.#A.sidecar?.nodeId;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"DELETE",path:`/api/items/${encodeURIComponent(Q)}/tags/${encodeURIComponent(A)}`}),this.platform.notifications.info("Offline — tag removal will sync when you reconnect.");return}try{await this.api.removeTag(Q,A)}catch(B){this.platform.notifications.error(`Couldn't remove tag: ${B.message}`)}await this.#B()}async#C(){if(!this.#A.pushSupported)return;try{let Q=await(await navigator.serviceWorker.getRegistration())?.pushManager?.getSubscription();this.#Q({pushEnabled:!!Q})}catch{}}async enablePush(){if(!this.#A.pushSupported){this.platform.notifications.warn("Push notifications are not supported in this browser.");return}try{let{publicKey:A}=await this.api.vapidKey();if(!A){this.platform.notifications.warn("This server has no VAPID key configured for web push.");return}let Q=await navigator.serviceWorker.register("/sw.js");if(await navigator.serviceWorker.ready,await Notification.requestPermission()!=="granted")return this.platform.notifications.info("Notifications permission was denied.");let C=await Q.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:v$(A)});await this.api.subscribePush(C.toJSON()),this.#Q({pushEnabled:!0}),this.platform.notifications.success("Notifications enabled — you’ll be pinged when someone @mentions you.")}catch(A){this.platform.notifications.error(`Couldn't enable notifications: ${A.message}`)}}}function YY(A,Q){for(let B of A){if(B.id===Q)return B;let C=YY(B.replies||[],Q);if(C)return C}return null}function v$(A){let Q="=".repeat((4-A.length%4)%4),B=(A+Q).replace(/-/g,"+").replace(/_/g,"/"),C=atob(B),E=new Uint8Array(C.length);for(let J=0;J<C.length;J++)E[J]=C.charCodeAt(J);return E}class lJ{get dimensions(){return 0}async embed(A){throw z.unsupported("embed not implemented")}async embedOne(A){return(await this.embed([A]))[0]}}var f$=new Set("a an the of to in on for and or is are be as at by with from this that it".split(" "));function u$(A){return String(A).toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter((Q)=>Q.length>1&&!f$.has(Q))}function m$(A){let Q=2166136261;for(let B=0;B<A.length;B++)Q^=A.charCodeAt(B),Q=Math.imul(Q,16777619);return Q>>>0}class cJ extends lJ{constructor({dimensions:A=256}={}){super();this._dim=A}get dimensions(){return this._dim}async embed(A){return A.map((Q)=>this.#A(Q))}#A(A){let Q=new Float64Array(this._dim),B=u$(A),C=[...B];for(let J=0;J<B.length-1;J++)C.push(B[J]+"_"+B[J+1]);for(let J of C){let K=m$(J),L=K%this._dim,Y=K>>31&1?-1:1;Q[L]+=Y}let E=0;for(let J=0;J<Q.length;J++)E+=Q[J]*Q[J];return E=Math.sqrt(E)||1,Array.from(Q,(J)=>J/E)}}class p$ extends lJ{constructor(A){super();if(!A?.url||!A?.dimensions)throw z.invalid("HttpEmbedding requires url and dimensions");this.cfg=A}get dimensions(){return this.cfg.dimensions}async embed(A){let Q=this.cfg.batchSize??64,B=[];for(let C=0;C<A.length;C+=Q){let E=A.slice(C,C+Q);B.push(...await this.#A(E))}return B}async#A(A){return FB(async()=>{let Q;try{Q=await fetch(this.cfg.url,{method:"POST",headers:{"content-type":"application/json",...this.cfg.apiKey?{authorization:`Bearer ${this.cfg.apiKey}`}:{}},body:JSON.stringify({model:this.cfg.model,input:A})})}catch(E){throw uB(E)}if(Q.status===429||Q.status>=500)throw z.transient(`Embedding endpoint ${Q.status}`);if(!Q.ok)throw z.internal(`Embedding endpoint failed: ${Q.status}`);let B=await Q.json();return(B.data??B.embeddings??[]).map((E)=>E.embedding??E)})}}function XY(A,Q,B){let C=[],E=0;while(E<A.length){let J=Math.min(E+Q,A.length);if(J<A.length){let K=A.slice(E,J),L=Math.max(K.lastIndexOf(`
|
|
730
|
+
`,B);B=E<0?A.length:E;continue}if(C==="/"&&A[B+1]==="*"){let E=A.indexOf("*/",B+2);B=E<0?A.length:E+2,Q+=" ";continue}if(C==="'"||C==='"'||C==="`"){let E=C;B++;while(B<A.length){if(A[B]===E){if(A[B+1]===E){B+=2;continue}B++;break}B++}Q+=" ";continue}if(C==="["){let E=A.indexOf("]",B);B=E<0?A.length:E+1,Q+=" ";continue}Q+=C,B++}return Q}function SJ(A){if(typeof A!=="string"||!A)throw z.invalid("SQL statement is required");if(Y$.test(X$(A)))throw z.invalid("ATTACH, DETACH, VACUUM and PRAGMA are not permitted in plugin storage")}var G$=26214400;async function H$(A,Q){let B=Number(A.headers.get("content-length")||0);if(B&&B>Q)throw Error("Response too large");let C=A.body?.getReader?.();if(!C){let Y=await A.arrayBuffer();if(Y.byteLength>Q)throw Error("Response too large");return Y}let E=[],J=0;for(;;){let{done:Y,value:X}=await C.read();if(Y)break;if(J+=X.byteLength,J>Q)throw await C.cancel().catch(()=>{}),Error("Response too large");E.push(X)}let K=new Uint8Array(J),L=0;for(let Y of E)K.set(Y,L),L+=Y.byteLength;return K.buffer}class _J{constructor({platform:A,clientDb:Q,media:B,dock:C,onChange:E}={}){this.platform=A,this.clientDb=Q,this.media=B,this.dock=C,this.onChange=E||(()=>{})}async hostCall(A,Q,B,C){let E=(K)=>{if(!A.grants.includes(K))throw Error(`Capability "${K}" not granted`)},J=A.id;switch(Q){case"activated":{let K=C||A.frame;if(clearTimeout(K?._timer),B.ok)K?.resolveActivated?.(K);else K?.rejectActivated?.(Error(B.error||"activate() failed"));return{ok:!0}}case"command:execute":{let K=this.#A(A,B.id);if(!dC(A.manifest,K))throw Error(`Command "${B.id}" is not in this plugin's declared commands`);return{ok:!0,result:await this.platform.commands.execute(K,...B.args||[])??null}}case"ui:status":{E("ui");let K=this.#Q(A,B.name,"statusItem");return this.platform.contributions.update(K.uri,{...B.html!==void 0?{html:String(B.html??"")}:{},...B.tooltip!==void 0?{tooltip:String(B.tooltip??"")}:{},...B.visible!==void 0?{visible:!!B.visible}:{visible:!0}}),{ok:!0}}case"context:setRegister":{let K=this.#Q(A,B.name,"register"),L=A.registers?.get(K.uri);if(!L)throw Error(`Register "${B.name}" is not available`);return L(B.value),{ok:!0}}case"resources:list":return[...A.files.keys()].filter(d8);case"resources:read":{if(!d8(B.path))throw Error(`No such resource ${B.path}`);let K=A.files.get(B.path);if(!K)throw Error(`No such resource ${B.path}`);return{bytes:K.slice().buffer}}case"files:read":return E("files"),{text:await this.platform.api.readText(B.id)};case"files:list":return E("files"),this.platform.api.list(B.collection||B.pathOrId,{sort:B.sort,order:B.order,limit:B.limit,cursor:B.cursor});case"files:stat":return E("files"),this.platform.api.stat(B.id);case"files:bytes":{E("files");let K=await this.platform.fileChunks.read(B.id,{start:B.start,end:B.end});return{bytes:K.bytes.buffer,etag:K.etag,total:K.total}}case"files:hasLocal":{E("files");let K=this.platform.fileChunks.status(B.id);return{local:!!K.done,loaded:K.loaded,total:K.total,ratio:K.ratio,filling:K.filling}}case"files:localBlob":{E("files");let K=this.platform.fileChunks.status(B.id);if(!K.done||!K.total)return{blob:null};let L=await this.platform.fileChunks.read(B.id,{start:0,end:K.total}),Y=await this.platform.api.stat(B.id).catch(()=>null);return{blob:new Blob([L.bytes],{type:Y?.node?.contentType||"application/octet-stream"})}}case"items:data:get":return E("files"),this.platform.itemData.get(J,B.id);case"items:data:set":return E("files"),this.platform.itemData.set(J,B.id,B.key,B.value);case"items:data:remove":return E("files"),this.platform.itemData.remove(J,B.id,B.key);case"files:offline:start":return E("files"),this.platform.fileChunks.start(B.id);case"files:offline:status":return E("files"),this.platform.fileChunks.status(B.id);case"files:offline:cancel":return E("files"),this.platform.fileChunks.cancel(B.id),{ok:!0};case"files:offline:remove":return E("files"),this.platform.fileChunks.remove(B.id).then(()=>({ok:!0}));case"files:mediaUrl":{E("files");let{url:K,expiresAt:L}=await this.platform.mediaUrls.url(B.id,{op:B.op||"media"});return{url:K,expiresAt:L}}case"files:index":{E("indexer");let K=kQ(B.indexerId)?B.indexerId:xQ(A.manifest,B.indexerId||"default");return this.platform.api.pushIndex(K,B.nodeId,{semanticTexts:B.semanticTexts,tags:B.tags,metadata:B.metadata,documents:B.documents,facet:B.facet})}case"net:fetch":return E("network"),this.#C(A,B);case"storage:sql":return E("storage"),this.#E(A,B);case"settings:get":return this.platform.settings.get(`${J}.${B.key}`);case"settings:getSecret":return A.secrets?.[B.key]??null;case"settings:set":return this.platform.settings.set(`${J}.${B.key}`,B.value),{ok:!0};case"ui:showPanel":return E("ui"),A.hasUi=!0,this.platform.dispatch(new EC(J)),this.onChange(),{ok:!0};case"media:metadata":{E("media");let K=(B.artwork||[]).filter((L)=>this.#B(A,L?.src));return this.media.apply(C,"metadata",{...B,artwork:K})}case"media:playbackState":return E("media"),this.media.apply(C,"playbackState",B);case"media:position":return E("media"),this.media.apply(C,"position",B);case"media:action":return E("media"),this.media.apply(C,"action",B);case"media:clear":return this.media.apply(C,"clear",B);case"dock:enable":if(E("dock"),C)C.dock={enabled:!0,minSize:B.minSize,maxSize:B.maxSize,dismissed:!1};return{ok:!0};case"dock:disable":if(E("dock"),C?.dock)C.dock.enabled=!1;if(C&&this.dock.docked===C)this.dock.closeDock(C);return{ok:!0};case"dock:close":if(C)this.dock.closeDock(C);return{ok:!0};default:throw Error(`Unknown host method ${Q}`)}}hostEvent(A,Q,B,C){switch(Q){case"manifest":if(C&&C.role!=="primary")break;A.live=B,A.responsive=!0,this.onChange();break;case"ui:toast":this.platform.notifications[B.level||"info"](`${dA(A.manifest)}: ${B.text}`);break;case"ui:badge":A.badge=B.text,this.onChange();break}}#A(A,Q){if(!Q||kQ(Q))return Q;let B=this.platform.contributions.get(xQ(A.manifest,Q));return B?.type==="command"?B.uri:Q}#Q(A,Q,B){let C=Q?this.platform.contributions.get(xQ(A.manifest,Q)):null;if(!C||C.pluginId!==A.id||C.type!==B)throw Error(`"${Q}" is not a ${B} declared by this plugin`);return C}#B(A,Q){if(!Q)return!1;if(/^data:image\//i.test(Q))return!0;if(/^blob:/i.test(Q))return console.warn(`[trove] ${A.id}: media artwork must be a data: URL — a blob: from a sandboxed frame is opaque-origin and cannot be loaded here`),!1;return lC(rQ(A.manifest),Q)}async#C(A,{url:Q,method:B="GET",headers:C,body:E}){let J=rQ(A.manifest);if(c8(Q,this.platform.api?.baseUrl))throw Error("Blocked: a plugin may not call the drive's own API through the network broker");if(!lC(J,Q))throw Error(`Blocked: "${Q}" is not one of this plugin's declared network endpoints`);let K={method:B,credentials:"omit",redirect:"follow",headers:D$(C)};if(E!=null&&B!=="GET"&&B!=="HEAD")K.body=E instanceof ArrayBuffer?new Uint8Array(E):E;let L=await fetch(Q,K);if(L.url&&L.url!==Q){if(c8(L.url,this.platform.api?.baseUrl))throw Error("Blocked: request redirected onto the drive's own API");if(!lC(J,L.url))throw Error(`Blocked: request redirected off this plugin's declared endpoints (${L.url})`)}let Y=await H$(L,G$),X={};return L.headers.forEach((H,G)=>{X[G]=H}),{ok:L.ok,status:L.status,statusText:L.statusText,url:L.url,headers:X,bytes:Y}}async#E(A,{scope:Q="plugin",side:B="server",op:C,sql:E,params:J=[],statements:K}){if(!A.storage?.[Q])throw Error(`Storage scope "${Q}" not granted${Q==="domain"?" (needs a verified domain)":""}`);if(B==="client"){if(C==="batch")for(let G of Array.isArray(K)?K:[])SJ(G?.sql);else SJ(E);let X=Q==="domain"?`dom:${A.manifest.domain}`:`plg:${A.id}`,H=await this.clientDb.obtain(X);return Z$(H,C,E,J,K)}let L={scope:Q,op:C,sql:E,params:J,statements:K,domain:Q==="domain"?A.manifest.domain:void 0};return(await this.platform.api.request("POST",`/api/plugins/${encodeURIComponent(A.id)}/sql`,{body:L})).result}}function c8(A,Q){try{let B=new URL(Q||"",globalThis.location?.href||"http://localhost/");return new URL(A,B).origin===B.origin}catch{return!1}}function d8(A){return A!=="manifest.json"&&!X0(A)}var $$=new Set(["host","cookie","cookie2","set-cookie","origin","referer","content-length","connection"]);function D$(A){let Q={};for(let[B,C]of Object.entries(A||{}))if(!$$.has(String(B).toLowerCase()))Q[B]=C;return Q}function Z$(A,Q,B,C=[],E){switch(Q){case"exec":return A.exec(B);case"run":return A.run(B,...C);case"get":return A.get(B,...C);case"all":return A.all(B,...C);case"batch":return A.batch(E);default:throw Error(`Unknown storage op "${Q}"`)}}var a8=["files","storage","ui","commands","indexer","opener","network","media","dock"];class TJ{constructor(A,{heartbeatMs:Q=20000}={}){this.platform=A,this.plugins=new Map,this.registry=new AE,this.clientDb=new BE({onError:(B,C)=>this.platform.notifications.error(`A plugin's on-device data couldn't be saved (${C}): ${B.message}`)}),this.online=typeof navigator<"u"?navigator.onLine:!0,this.heartbeatMs=Q,this._heartbeat=null,this._probing=!1,this.cell=A.reactive.cell([]),this.media=new GE,this.dock=new HE({destroyFrame:(B)=>this.frames.destroy(B),openFile:(B,C)=>this.platform.dispatch(new GQ(B,C)),onChange:()=>this.#A()}),this.frames=new wJ({media:this.media,dock:this.dock}),this.rpc=new _J({platform:A,clientDb:this.clientDb,media:this.media,dock:this.dock,onChange:()=>this.#A()})}observe(){return this.cell}#A(){this.cell.setValue(this.list())}#Q(A,Q,B){return this.frames.spawn(A,Q,{onCall:(C,E,J,K)=>this.rpc.hostCall(C,E,J,K),onEvent:(C,E,J,K)=>this.rpc.hostEvent(C,E,J,K),online:this.online,entry:B})}#B(A){let Q=A.id,B=this.platform.contributions,C=(J)=>A.disposers.push(J),E=dA(A.manifest);for(let J of IQ(A.manifest)){let K={...J,pluginId:Q};switch(J.type){case"opener":if(A.grants.includes("opener"))C(B.register(J.uri,K));break;case"command":C(this.platform.commands.register({id:J.uri,title:J.title||`${E}: ${J.name}`,category:J.category||E,icon:J.icon,when:J.when,offline:J.offline,palette:J.palette,pluginId:Q,actions:(...L)=>new IJ(Q,J.name,L)}));break;case"statusItem":{let L=J.command?this.#E(A,J.command,E,`status item “${J.name}”`):null;C(B.register(J.uri,{...K,command:L,html:"",visible:!1}));break}case"register":{C(B.register(J.uri,K));let L=this.platform.context.own(J.uri,J.default);A.registers.set(J.uri,L.set),C(()=>{A.registers.delete(J.uri),L.dispose()});break}case"keymap":{let L=A.files.get(J.path);if(!L){this.platform.notifications.warn(`Plugin "${E}": keymap file "${J.path}" is not in the package.`);break}try{let Y=this.#C(A,LL(new TextDecoder().decode(L)),E);C(B.register(J.uri,{...K,bindings:Y}))}catch(Y){this.platform.notifications.warn(`Plugin "${E}": ${Y.message}`)}break}case"indexer":break}}}#C(A,Q,B){let C=[];for(let E of Q){let J=this.#E(A,E.command,B,`shortcut ${E.key}`);if(J)C.push({...E,command:J})}return C}#E(A,Q,B,C){let E=xQ(A.manifest,Q);if(IQ(A.manifest).some((K)=>K.uri===E&&K.type==="command"))return E;if(!dC(A.manifest,Q))return this.platform.notifications.warn(`Plugin "${B}": ${C} runs "${Q}", which it isn't allowed to run — ignored.`),null;return Q}list(){return[...this.plugins.values()].map((A)=>({id:A.id,name:dA(A.manifest),version:A.manifest.version,status:A.status,capabilities:A.grants,error:A.error||null,hasUi:A.hasUi,badge:A.badge||null,trust:A.trust||null,settingsSchema:A.manifest.settings||[],endpoints:cC(rQ(A.manifest)),responsive:!!A.responsive,manifest:A.live||null,features:this.#J(A)}))}#J(A){let Q;try{Q=IQ(A.manifest)}catch{return[]}return Q.map((B)=>({kind:B.type,id:B.uri,name:B.name,title:B.title||B.name,offline:!!B.offline,available:this.#K(A,B)}))}#K(A,Q){if(A.status!=="active"||!A.responsive)return!1;return this.online||!!Q.offline}isAvailable(A){if(!A?.pluginId)return!0;let Q=this.plugins.get(A.pluginId);if(!Q)return!1;return this.#K(Q,A)}canGrant(A,Q){return!KE.has(A)||!!Q}async install(A,{grants:Q,trust:B}={}){let C=EQ(A.manifest),E=LE(A.manifest),J=(Q||E).filter((X)=>a8.includes(X)&&E.includes(X)),K=F$(A.manifest,J)?"account":"device";if(K==="account"){if(!A.raw)throw Error("Package bytes unavailable for a server install");await this.platform.api.installPlugin(A.raw,J)}let L=J.includes("storage")?XE(A.manifest,B):{plugin:!1,domain:!1},Y={id:C,manifest:A.manifest,files:Object.fromEntries([...A.files.entries()]),grants:J,storage:L,trust:B||null,scope:K,settings:{},secrets:{},installedAt:Date.now()};return await this.registry.save(Y),this.#Y(Y),await this.#X(Y),this.plugins.get(C)}async restore(){let A=[];try{A=await this.registry.list()}catch{}for(let Q of A)try{this.#Y(Q),this.#X(Q).catch((B)=>console.error("restore plugin failed",Q.id,B))}catch(B){console.error("skipping corrupt plugin record",Q?.id,B),this.platform.notifications.warn(`Couldn't restore plugin "${Q?.manifest?dA(Q.manifest):Q?.id||"unknown"}" — its saved data looks corrupt.`)}this.#L(A).catch(()=>{})}async#L(A){let Q;try{Q=(await this.platform.api.installedPlugins()).plugins||[]}catch{return}let B=new Set(Q.map((L)=>L.pluginId)),C=new Set(A.map((L)=>L.id)),E=0,J=0,K=0;for(let L of A){if(L.scope!=="account"||B.has(L.id))continue;try{await this.platform.api.installPlugin(SL(U$(L.files)),L.grants||[])}catch(Y){console.error("re-upload plugin failed",L.id,Y),E++}}for(let L of Q){if(C.has(L.pluginId))continue;try{let Y=tQ(await this.platform.api.pluginPackage(L.pluginId)),X=L.grants||[],H={id:L.pluginId,manifest:Y.manifest,files:Object.fromEntries([...Y.files.entries()]),grants:X,storage:X.includes("storage")?{plugin:!0,domain:!!L.sharedStorage}:{plugin:!1,domain:!1},trust:null,scope:"account",settings:{},secrets:{},installedAt:L.createdAt||Date.now()};await this.registry.save(H),this.#Y(H),await this.#X(H),J++}catch(Y){console.error("sync plugin failed",L.pluginId,Y),K++}}if(J)this.platform.notifications.info(`Synced ${J} account plugin${J>1?"s":""} from the server.`);if(E||K){let L=[];if(K)L.push(`${K} couldn't be downloaded`);if(E)L.push(`${E} couldn't be uploaded`);this.platform.notifications.warn(`Some account plugins didn't sync: ${L.join(", ")}.`)}}#Y(A){let Q=(A.manifest.settings||[]).filter((B)=>!B.secret);if(Q.length)A._settingsDispose=this.platform.settings.scopedFor(A.id).register(Q.map((B)=>({...B,category:dA(A.manifest)})))}async#X(A){if(this.plugins.get(A.id)?.status==="active")return;let Q={...A,iframe:null,status:"loading",error:null,disposers:[],channel:null,registers:new Map,hasUi:!1,responsive:!1,frame:null,frames:new Set,storage:A.storage||(A.grants?.includes("storage")?XE(A.manifest,A.trust):{plugin:!1,domain:!1}),files:W$(A.files)};this.plugins.set(A.id,Q);try{this.#B(Q)}catch(B){console.error("registering contributions failed",A.id,B)}this.#A();try{let B=await this.#Q(Q,"primary");if(this.plugins.get(A.id)!==Q)return this.frames.destroy(B),Q;Q.frame=B,Q.iframe=B.iframe,Q.channel=B.channel,Q.status="active",Q.responsive=!0,this.#H(Q).then(()=>this.#A()),this.#G()}catch(B){Q.status="error",Q.error=B?.message||String(B),this.platform.notifications.error(`Plugin "${dA(A.manifest)}" failed to load: ${Q.error}`)}return this.#A(),Q}async setSecret(A,Q,B){let C=await this.registry.get(A);if(!C)return;C.secrets={...C.secrets,[Q]:B},await this.registry.save(C);let E=this.plugins.get(A);if(E)E.secrets=C.secrets;E?.channel?.emit("settings:changed",{key:Q,value:"••••"})}async getSecret(A,Q){return(await this.registry.get(A))?.secrets?.[Q]??""}#G(){if(this._heartbeat||!this.heartbeatMs)return;if(this._heartbeat=setInterval(()=>this.#Z(),this.heartbeatMs),this._heartbeat?.unref)this._heartbeat.unref()}#$(){if(this._heartbeat)clearInterval(this._heartbeat);this._heartbeat=null}async#Z(){if(this._probing)return;this._probing=!0;try{let A=!1;for(let Q of this.plugins.values())if(Q.status==="active")A=await this.#H(Q)||A;if(A)this.#A()}finally{this._probing=!1}}invokeCommand(A,Q,B=[]){return this.plugins.get(A)?.channel?.call("command:execute",{id:Q,args:B})}setHeartbeat(A){if(this.heartbeatMs=A,this.#$(),A&&[...this.plugins.values()].some((Q)=>Q.status==="active"))this.#G()}async#H(A){if(A.status!=="active"||!A.channel)return!1;let Q={responsive:A.responsive,sig:n8(A.live)};try{A.live=await A.channel.call("manifest",{},{timeout:4000}),A.responsive=!0}catch{A.responsive=!1}return Q.responsive!==A.responsive||Q.sig!==n8(A.live)}async setOnline(A){if(this.online===A)return;this.online=A,await Promise.all([...this.plugins.values()].filter((Q)=>Q.status==="active").map(async(Q)=>{try{Q.channel?.emit("connectivity",{online:A})}catch{}for(let B of Q.frames||[])try{B.channel?.emit("connectivity",{online:A})}catch{}await this.#H(Q)})),this.#A()}async refresh(A){let Q=this.plugins.get(A);if(Q)await this.#H(Q),this.#A()}mountPanel(A,Q,{width:B=380,height:C=480}={}){let E=this.plugins.get(A);if(!E?.frame)return null;return Q.style.width=`${B}px`,Q.style.height=`${C}px`,this.dock.place(E.frame,Q,50),E.hasUi=!0,()=>this.dock.hide(E.frame)}mountViewer(A,Q,B,C,E={}){let J=this.plugins.get(A);if(!J)return E.onError?.("Plugin is not available"),null;let K=this.dock.docked;if(K&&K.record===J&&K.node?.id===B.id&&K.openerId===C)return this.dock.undock(K),this.dock.place(K,Q,3),E.onReady?.(),()=>this.#D(K);let L=this.platform.contributions.get(C),Y={cancelled:!1,frame:null};return this.#Q(J,"viewer",L?.entry).then(async(X)=>{if(Y.cancelled){this.frames.destroy(X);return}Y.frame=X,X.node=B,X.openerId=C,J.frames.add(X),this.dock.place(X,Q,3);try{if(await X.channel?.call("opener:open",{openerId:C,file:B,context:{}}),!Y.cancelled)E.onReady?.()}catch(H){if(!Y.cancelled)E.onError?.(H?.message||"Failed to open")}}).catch((X)=>{if(console.error("viewer frame failed to load",X),!Y.cancelled)E.onError?.(X?.message||"This viewer failed to load")}),J.hasUi=!0,()=>{if(Y.cancelled=!0,Y.frame)this.#D(Y.frame)}}#D(A){if(A.dock?.enabled&&!A.dock.dismissed)this.dock.dock(A);else this.frames.destroy(A)}async uninstall(A,{wipeData:Q=!0}={}){let B=this.plugins.get(A),C=B?.manifest?dA(B.manifest):A,E=B?.scope==="account"||(await this.registry.get(A).catch(()=>null))?.scope==="account";if(Q&&E)try{await this.platform.api.uninstallPluginServer(A)}catch(L){this.platform.notifications.error(`Couldn't uninstall "${C}" from the server: ${L.message}. It's still installed.`);return}if(B){try{B.channel?.emit("deactivate")}catch{}for(let L of B.disposers)try{L()}catch{}B._settingsDispose?.();for(let L of[...B.frames||[]])this.frames.destroy(L);if(B.frame)this.dock.stopPlace(B.frame),this.media.releaseActions(B.frame);B.channel?.dispose(),B.iframe?.remove(),this.plugins.delete(A)}let J=[];if(Q){if(!E)await this.platform.api.request("DELETE",`/api/plugins/${encodeURIComponent(A)}/data`).catch(()=>J.push("server-side data"));await this.clientDb.drop(`plg:${A}`).catch(()=>J.push("on-device data"))}let K=!1;try{await this.registry.remove(A)}catch(L){K=!0,console.error("removing the persisted plugin record failed",A,L)}if(![...this.plugins.values()].some((L)=>L.status==="active"))this.#$();if(this.#A(),K)this.platform.notifications.error(`Removed "${C}", but its saved record couldn't be deleted — it may come back when you reload.`);else if(J.length)this.platform.notifications.warn(`Uninstalled "${C}", but couldn't clear its ${J.join(" and ")}.`)}fetchAssetlinks=async(A)=>{return(await this.platform.api.request("GET","/api/plugins/assetlinks",{query:{domain:A}}))?.assetlinks||null};assessTrust(A){return hL(A,this.fetchAssetlinks)}}function W$(A){let Q=new Map;for(let[B,C]of Object.entries(A))Q.set(B,C instanceof Uint8Array?C:new Uint8Array(C));return Q}function U$(A){let Q={};for(let[B,C]of Object.entries(A||{}))Q[B]=C instanceof Uint8Array?C:new Uint8Array(C);return Q}function F$(A,Q){if(Q.includes("storage"))return!0;return T0(A).length>0}function n8(A){if(!A)return"";return`${A.online?1:0}|${[...A.handlers||[]].sort().join(",")}`}var s8=["auto","desktop","phone","tv"],I$=720,R$=1100,M$=/\b(smart-?tv|smarttv|appletv|googletv|android\s*tv|hbbtv|netcast|web0s|webos|tizen|viera|bravia|aquos|crkey|nettv|dtv|philipstv|roku|aft[a-z]{1,3})\b/i;function V$(A="",Q=0){if(!A)return!1;return M$.test(A)&&Q>=R$}class xJ{#A;constructor({window:A=globalThis,settings:Q=null}={}){this.window=A,this.settings=Q,this.urlOverride=N$(A),this.#A=this.#B(),this.cell=c(this.#A),this._onResize=()=>this.refresh()}get(){return this.#A}observe(){return this.cell}install(){if(this.window.addEventListener?.("resize",this._onResize),this.window.addEventListener?.("orientationchange",this._onResize),this.settings)TQ(this.settings.observe(),()=>this.refresh());return this.#Q(this.#A),this}dispose(){this.window.removeEventListener?.("resize",this._onResize),this.window.removeEventListener?.("orientationchange",this._onResize)}refresh(){let A=this.#B();if(A.mode===this.#A.mode&&A.width===this.#A.width&&A.height===this.#A.height&&A.coarse===this.#A.coarse)return;this.#A=A,this.#Q(A),this.cell.setValue(A)}#Q(A){let Q=this.window.document?.documentElement;if(Q)Q.dataset.layout=A.mode}#B(){let A=this.window,Q=A.innerWidth||1280,B=A.innerHeight||800,C=z$(A,"(pointer: coarse)"),E=A.navigator?.userAgent||"",J=this.urlOverride||this.settings?.get?.("workbench.layout")||"auto";return{mode:J!=="auto"&&s8.includes(J)?J:q$({width:Q,coarse:C,ua:E}),width:Q,height:B,coarse:C,forced:J!=="auto"}}}function q$({width:A,coarse:Q,ua:B}){if(V$(B,A))return"tv";if(A<=I$)return"phone";return"desktop"}function z$(A,Q){try{return!!A.matchMedia?.(Q)?.matches}catch{return!1}}function N$(A){try{let Q=new URL(A.location.href).searchParams.get("ui");return Q&&s8.includes(Q)?Q:null}catch{return null}}var r8='a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])',t8=".launch-item, .grid-tile, .sheet-row, .inbox-item, .plugin-card, .act-task, .act-issue, .chapter",P$=`${r8}, ${t8}`,O$=new Set(["BrowserBack","GoBack","Backspace"]),j$=new Set([10009,461]),w$={ArrowLeft:"left",ArrowRight:"right",ArrowUp:"up",ArrowDown:"down"},S$=new Set(["A","BUTTON","INPUT","SELECT","TEXTAREA"]);class kJ{constructor({workbench:A,viewport:Q,window:B=globalThis}){this.viewport=Q,this.window=B,this.active=!1,this._onKey=(C)=>this.handleKey(C),this._observer=null,this._pending=0,this._bootstrapped=!1}install(){if(this.viewport)TQ(this.viewport.observe(),(A)=>this.setActive(A.mode==="tv"));return this.setActive(this.viewport?.get().mode==="tv"),this}setActive(A){if(A===this.active)return;if(this.active=A,A)this.window.addEventListener?.("keydown",this._onKey),this.#A(),this.prime(),this.window.setTimeout?.(()=>this.prime(),60);else this.window.removeEventListener?.("keydown",this._onKey),this._observer?.disconnect(),this._observer=null,this._bootstrapped=!1}prime(){this.candidates(),this.focusFirst()}#A(){let A=this.window.MutationObserver;if(!A||this._observer)return;this._observer=new A(()=>{if(this._pending)return;this._pending=this.window.requestAnimationFrame?.(()=>{if(this._pending=0,this.active)this.prime()})||0}),this._observer.observe(this.window.document.body,{childList:!0,subtree:!0})}handleKey(A){if(!this.active||A.defaultPrevented||A.altKey||A.ctrlKey||A.metaKey)return;let Q=this.window.document,B=Q.activeElement;if(O$.has(A.key)||j$.has(A.keyCode)){if(A.key==="Backspace"&&o8(B)&&(B.value??"").length>0)return;A.preventDefault(),this.goBack();return}let C=w$[A.key];if(!C){if(A.key==="Enter"&&B&&!S$.has(B.tagName)&&B.matches(t8))A.preventDefault(),B.click();return}if((C==="left"||C==="right")&&o8(B)&&!_$(B,C))return;let E=B&&B!==Q.body?B:null,J=this.find(C,E);if(!J)return;A.preventDefault(),i8(J)}goBack(){if(this.workbench?.closeOverlays())return;this.window.history?.back?.()}candidates(){let A=this.window.document,Q=[];for(let B of A.querySelectorAll(P$)){if(B.getAttribute?.("aria-hidden")==="true"||B.hasAttribute?.("disabled"))continue;let C=B.getBoundingClientRect();if(C.width<2||C.height<2)continue;if(C.bottom<0||C.top>this.window.innerHeight||C.right<0||C.left>this.window.innerWidth)continue;if(!B.matches(r8)&&!B.hasAttribute("tabindex"))B.setAttribute("tabindex","0");Q.push({el:B,rect:C})}return Q}find(A,Q){let B=this.candidates();if(!B.length)return null;let C=Q&&Q.getBoundingClientRect&&Q.getBoundingClientRect().width?Q.getBoundingClientRect():null;if(!C)return B[0].el;let E=null,J=1/0;for(let{el:K,rect:L}of B){if(K===Q)continue;let Y=T$(C,L,A);if(Y==null||Y>=J)continue;J=Y,E=K}return E}focusFirst(){if(this._bootstrapped)return;let A=this.window.document;if(A?.activeElement&&A.activeElement!==A.body)return;let Q=this.candidates();if(!Q.length)return;let B=Q.find((C)=>C.el.classList?.contains("launch-input"))||Q[0];i8(B.el),this._bootstrapped=!0}}function _$(A,Q){let{selectionStart:B,selectionEnd:C}=A;if(B==null||C==null)return!0;if(B!==C)return!1;return Q==="left"?B===0:C>=(A.value??"").length}function o8(A){if(!A)return!1;let Q=A.tagName;if(Q==="TEXTAREA")return!0;if(A.isContentEditable)return!0;if(Q!=="INPUT")return!1;return!["checkbox","radio","button","submit","range","file"].includes(A.type)}function i8(A){A.focus?.({preventScroll:!0}),A.scrollIntoView?.({block:"nearest",inline:"nearest"})}function T$(A,Q,B){let C=B==="up"||B==="down",[E,J]=C?B==="down"?[A.bottom,Q.top]:[A.top,Q.bottom]:B==="right"?[A.right,Q.left]:[A.left,Q.right],L=B==="down"||B==="right"?J-E:E-J;if(L<-2)return null;let[Y,X,H,G]=C?[A.left,A.right,Q.left,Q.right]:[A.top,A.bottom,Q.top,Q.bottom],D=Math.max(0,Math.max(Y,H)-Math.min(X,G)),U=Math.abs((Y+X)/2-(H+G)/2);return Math.max(0,L)+D*3+U*0.2}function DC(){if(typeof window>"u")return null;return window.SpeechRecognition||window.webkitSpeechRecognition||null}function G0(){let A=DC();return!!A&&typeof A.available==="function"}var gJ=(A)=>({langs:[A],processLocally:!0});async function e8(A=navigator.language||"en-US"){if(!G0())return"unavailable";try{return await DC().available(gJ(A))}catch{return"unavailable"}}async function AY(A=navigator.language||"en-US"){if(typeof DC()?.install!=="function")return!1;try{return await DC().install(gJ(A))}catch{return!1}}function QY({lang:A=navigator.language||"en-US",onText:Q,onEnd:B,onError:C}={}){if(!G0())throw Error("On-device speech recognition is not available here");let E=new(DC());E.lang=A,E.interimResults=!0,E.continuous=!1,E.options=gJ(A),E.processLocally=!0;let J=!1;E.onresult=(K)=>{let L="",Y=!1;for(let X=K.resultIndex;X<K.results.length;X++)if(L+=K.results[X][0].transcript,K.results[X].isFinal)Y=!0;Q?.(L.trim(),{final:Y})},E.onerror=(K)=>{if(K.error==="no-speech"||K.error==="aborted")return;C?.(Error(K.error||"Speech recognition failed"))},E.onend=()=>{if(!J)J=!0,B?.()};try{E.start()}catch(K){J=!0,C?.(K),B?.()}return{stop(){if(J)return;J=!0;try{E.stop()}catch{}B?.()}}}class yJ{#A;constructor({notifications:A,settings:Q}={}){this.notifications=A,this.settings=Q,this.session=null,this.#A={supported:G0(),status:"unknown",listening:!1},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async refresh(){if(!this.#A.supported)return"unavailable";let A=await e8(this.#B());return this.#Q({status:A}),A}#B(){return this.settings?.get?.("search.voiceLanguage")||navigator.language||"en-US"}canListen(){return this.#A.supported&&(this.#A.status==="available"||this.#A.status==="downloadable")}async run({onText:A}={}){if(this.openSearchSurface(),await this.focusInput(),!this.#A.supported)return{listening:!1,reason:"unsupported"};let Q=this.#A.status==="unknown"?await this.refresh():this.#A.status;if(Q==="downloadable"){this.notifications?.info("Downloading the on-device voice model — this happens once.");let B=await AY(this.#B());if(this.#Q({status:B?"available":"unavailable"}),!B)return{listening:!1,reason:"install-failed"}}else if(Q!=="available")return{listening:!1,reason:Q};return this.toggle({onText:A})}toggle({onText:A}={}){if(this.session)return this.stop(),{listening:!1};try{return this.session=QY({lang:this.#B(),onText:A,onEnd:()=>{this.session=null,this.#Q({listening:!1})},onError:(Q)=>{if(this.session=null,this.#Q({listening:!1}),!/not-allowed|service-not-allowed|denied/i.test(Q.message))this.notifications?.warn(`Couldn't listen: ${Q.message}`)}}),this.#Q({listening:!0}),{listening:!0}}catch(Q){return this.notifications?.warn(`Couldn't listen: ${Q.message}`),{listening:!1,reason:"error"}}}stop(){this.session?.stop(),this.session=null,this.#Q({listening:!1})}openSearchSurface(){let A=this.workbench;if(!A)return;if(A.state.activity==="home"&&!A.nav?.get?.().activeTabId)A.closeSearchModal?.();else A.openSearchModal()}focusInput({tries:A=12}={}){return new Promise((Q)=>{let B=A,C=()=>{let E=document.querySelector(".search-modal .launch-input")||document.querySelector(".launch-input");if(E){E.focus();try{E.setSelectionRange(E.value.length,E.value.length)}catch{}Q(document.activeElement===E);return}if(--B<=0){Q(!1);return}requestAnimationFrame(C)};C()})}}class hJ{constructor({api:A,settings:Q=null}){this.api=A,this.settings=Q,this.cache=new Map,this._queue=new Map,this._timer=null}get needed(){let A=this.settings?.get("media.signedUrls");if(A==="always")return!0;if(A==="never")return!1;return!!this.api.token?.()}cacheKey(A){return this.api.downloadUrl(A)}async url(A,{op:Q="media"}={}){if(!this.needed)return{url:this.api.downloadUrl(A,{attachment:Q==="download"}),expiresAt:1/0};let B=`${Q}:${A}`,C=this.cache.get(B);if(C&&this.#A(C))return C;return this.#Q(A,Q)}invalidate(A,Q="media"){if(A==null)this.cache.clear();else this.cache.delete(`${Q}:${A}`)}#A(A){if(A.expiresAt===1/0)return!0;let Q=A.expiresAt-A.mintedAt;return Date.now()<A.mintedAt+Q*0.8}#Q(A,Q){if(!this._queue.has(Q))this._queue.set(Q,new Map);let B=this._queue.get(Q),C=B.get(A);if(C)return C.promise;let E,J,K=new Promise((L,Y)=>{E=L,J=Y});if(B.set(A,{resolve:E,reject:J,promise:K}),B.size>=200)this.#B();else if(!this._timer)this._timer=setTimeout(()=>this.#B(),20);return K}async#B(){clearTimeout(this._timer),this._timer=null;let A=this._queue;this._queue=new Map;for(let[Q,B]of A){let C=[...B.keys()];try{let E=await this.api.mintUrls(C,Q),J=Date.now();for(let[K,L]of this.cache)if(L.expiresAt&&L.expiresAt<J)this.cache.delete(K);for(let[K,L]of B){let Y=E.urls?.[K];if(Y){let X={url:Y.url,expiresAt:Y.expiresAt,mintedAt:J};this.cache.set(`${Q}:${K}`,X),L.resolve(X)}else L.reject(Error(E.failed?.[K]==="not_found"?"That file is gone":"You cannot open that file"))}}catch(E){for(let J of B.values())J.reject(E)}}}}class vJ{constructor({api:A,actor:Q=()=>"local"}={}){this.api=A,this.actor=Q,this.local=x$(),this.pending=new Set,this.server=new Map,this.timer=null}async get(A,Q){let B={...this.server.get(bJ(A,Q))||{}};for(let[C,E]of Object.entries(this.local[A]?.[Q]||{}))if(E.present)B[C]=E.value;else delete B[C];return this.#B(A,Q),B}async set(A,Q,B,C){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:C,present:!0}),{ok:!0}}async remove(A,Q,B){if(!B)return{ok:!1};return this.#A(A,Q,B,{value:null,present:!1}),{ok:!0}}#A(A,Q,B,C){this.local[A]||={},this.local[A][Q]||={},this.local[A][Q][B]={...C,at:Date.now(),actor:this.actor()},BY(this.local),this.pending.add(bJ(A,Q)),this.#Q()}#Q(){if(this.timer)return;this.timer=setTimeout(()=>{this.timer=null,this.flush().catch(()=>{})},2000)}async flush(){for(let A of[...this.pending]){let[Q,B]=A.split("\x00"),C=this.local[Q]?.[B];if(!C){this.pending.delete(A);continue}let E=Object.entries(C).map(([J,K])=>({key:J,value:K.value,remove:!K.present}));try{let J=await this.api.request("POST",`/api/items/${encodeURIComponent(B)}/data`,{query:{scope:Q},body:{entries:E}});this.pending.delete(A),this.server.set(A,J?.data||{}),delete this.local[Q][B],BY(this.local)}catch{}}}#B(A,Q){let B=bJ(A,Q);if(this.inflight?.has(B))return;(this.inflight||=new Set).add(B),this.api.request("GET",`/api/items/${encodeURIComponent(Q)}/data`,{query:{scope:A}}).then((C)=>{this.server.set(B,C?.data||{})}).catch(()=>{}).finally(()=>this.inflight.delete(B))}}var bJ=(A,Q)=>`${A}\x00${Q}`;function x$(){try{let A=JSON.parse(localStorage.getItem("trove.itemData"))||{};return A&&typeof A==="object"?A:{}}catch{return{}}}function BY(A){try{let Q=[];for(let[B,C]of Object.entries(A))for(let[E,J]of Object.entries(C))for(let[K,L]of Object.entries(J))Q.push({scope:B,nodeId:E,key:K,cell:L});if(Q.length>5000){Q.sort((B,C)=>(B.cell.at||0)-(C.cell.at||0));for(let{scope:B,nodeId:C,key:E}of Q.slice(0,Q.length-5000))delete A[B][C][E]}localStorage.setItem("trove.itemData",JSON.stringify(A))}catch{}}var CY=(A)=>Math.floor(A/4194304),k$=(A,Q)=>{let B=new Uint8Array(Q),C=0;for(let E of A)B.set(E,C),C+=E.length;return B};class fJ{constructor({api:A,mediaUrls:Q}){this.api=A,this.mediaUrls=Q,this.kept=new Map,this.listeners=new Set}onProgress(A){return this.listeners.add(A),()=>this.listeners.delete(A)}#A(A){let Q=this.status(A);for(let B of[...this.listeners])try{B(A,Q)}catch{}}#Q(A,Q,B){return`${this.mediaUrls.cacheKey(A)}&chunk=${Q||"none"}:4194304:${B}`}async#B(A){if(!("caches"in globalThis))return null;return caches.open(A).catch(()=>null)}async#C(A){let Q=await this.#B("trove-files-v1");if(!Q)return null;return Q.match(this.mediaUrls.cacheKey(A),{ignoreVary:!0}).catch(()=>null)}async read(A,{start:Q=0,end:B,signal:C}={}){let E=await this.#C(A);if(E){let K=await E.blob(),L=B==null?K.size:Math.min(B,K.size);return{bytes:new Uint8Array(await K.slice(Q,L).arrayBuffer()),etag:E.headers.get("etag"),total:K.size}}let J=this.kept.get(A);if(!J)return this.api.readRange(A,{start:Q,end:B,signal:C});return this.#E(A,J,Q,B,C)}async#E(A,Q,B,C,E){let J=await this.#B("trove-chunks-v1");if(!J)return this.api.readRange(A,{start:B,end:C,signal:E});if(Q.total==null){let X=await this.api.readRange(A,{start:0,end:1,signal:E});Q.total=X.total,Q.etag=X.etag}let K=Math.min(C==null?Q.total:C,Q.total);if(K<=B)return{bytes:new Uint8Array(0),etag:Q.etag,total:Q.total};let L=[],Y=0;for(let X=CY(B);X<=CY(K-1);X++){let H=await this.#J(A,Q,X,J,E),G=Math.max(0,B-X*4194304),D=Math.min(H.length,K-X*4194304),U=H.subarray(G,D);L.push(U),Y+=U.length}return{bytes:k$(L,Y),etag:Q.etag,total:Q.total}}async#J(A,Q,B,C,E){let J=this.#Q(A,Q.etag,B),K=await C.match(J).catch(()=>null);if(K)return Q.have.add(B),new Uint8Array(await K.arrayBuffer());let L=B*4194304,Y=Math.min(L+4194304,Q.total),X=await this.api.readRange(A,{start:L,end:Y,signal:E});if(X.etag&&Q.etag&&X.etag!==Q.etag)await this.#L(A),Q.have.clear(),Q.etag=X.etag,Q.total=X.total??Q.total;return await C.put(J,new Response(X.bytes)).catch(()=>{}),Q.have.add(B),this.#A(A),X.bytes}async start(A){if(this.kept.get(A))return this.status(A);let B=await this.api.readRange(A,{start:0,end:1}),C=new AbortController,E={etag:B.etag,total:B.total,filling:!0,done:!1,failed:null,have:new Set,controller:C};return this.kept.set(A,E),this.#A(A),this.#K(A,E,C.signal).catch((J)=>{E.filling=!1,E.failed=J?.message||String(J),this.#A(A)}),this.status(A)}async#K(A,Q,B){let C=await this.#B("trove-chunks-v1");if(!C)throw Error("This browser has no Cache Storage, so nothing can be kept offline");let E=Math.max(1,Math.ceil((Q.total||0)/4194304));for(let J=0;J<E;J++){if(B.aborted)return;await this.#J(A,Q,J,C,B)}Q.filling=!1,Q.done=!0,this.#A(A)}status(A){let Q=this.kept.get(A);if(!Q)return{kept:!1,loaded:0,total:null,ratio:0,filling:!1,done:!1,error:null};let B=Q.total??null,C=B?Math.ceil(B/4194304)-1:-1,E=0;for(let J of Q.have)E+=J===C?B-C*4194304:4194304;return{kept:!0,total:B,loaded:E,ratio:B?Math.min(1,E/B):0,filling:Q.filling,done:Q.done,error:Q.failed}}cancel(A){let Q=this.kept.get(A);if(!Q)return;Q.controller?.abort(),Q.filling=!1,this.#A(A)}async remove(A){let Q=this.kept.get(A);this.cancel(A),this.kept.delete(A),Q?.have?.clear(),await this.#L(A),this.#A(A)}async#L(A){let Q=await this.#B("trove-chunks-v1");if(!Q)return;let B=`${this.mediaUrls.cacheKey(A)}&chunk=`,C=await Q.keys().catch(()=>[]);for(let E of C)if(E.url.startsWith(B))await Q.delete(E).catch(()=>{})}}function g$(){try{return localStorage.getItem("trove.token")||null}catch{return null}}function EY({baseUrl:A=""}={}){let Q=new x0,B=new g0,C=new u0,E=new y0(Q,B,C),J=new f0,K=new UB(Q,E,B,J),L=new m0({baseUrl:A,token:()=>g$()}),Y=new xJ({settings:J}),X=new kJ({viewport:Y}),H=new yJ({notifications:C,settings:J}),G={reactive:tK,contributions:Q,context:B,commands:E,keybindings:K,settings:J,notifications:C,api:L,viewport:Y,spatialNav:X,voice:H};return G.mediaUrls=new hJ({api:G.api,settings:J}),G.fileChunks=new fJ({api:G.api,mediaUrls:G.mediaUrls}),G.itemData=new vJ({api:G.api,actor:()=>G.identity?.get?.()?.principal?.id||"local"}),G.plugins=new TJ(G),E.availability=(D)=>G.plugins.isAvailable(D),y$(G),Y.refresh(),G}function y$(A){A.settings.register([{key:"workbench.theme",type:"enum",enum:["dark","light","midnight"],enumLabels:["Dark","Light","Midnight"],default:"dark",title:"Color theme",category:"Appearance",order:1},{key:"workbench.density",type:"enum",enum:["comfortable","compact"],default:"comfortable",title:"List density",category:"Appearance",order:2},{key:"workbench.layout",type:"enum",enum:["auto","desktop","phone","tv"],enumLabels:["Automatic","Desktop","Phone","TV / remote"],default:"auto",title:"Layout",description:"Automatic follows the screen size. Choose TV for d-pad remote navigation.",category:"Appearance",order:3},{key:"explorer.sort",type:"enum",enum:["name","size","updatedAt"],enumLabels:["Name","Size","Modified"],default:"name",title:"Sort files by",category:"Explorer",order:1},{key:"explorer.sortOrder",type:"enum",enum:["asc","desc"],default:"asc",title:"Sort order",category:"Explorer",order:2},{key:"explorer.confirmDelete",type:"boolean",default:!0,title:"Confirm before deleting",category:"Explorer",order:3},{key:"search.mode",type:"enum",enum:["hybrid","semantic","keyword"],default:"hybrid",title:"Search mode",description:"Hybrid blends semantic meaning with keyword matches.",category:"Search",order:1},{key:"uploads.concurrency",type:"number",minimum:1,maximum:8,default:4,title:"Parallel upload parts",category:"Transfers",order:1},{key:"openers.associations",type:"object",hidden:!0,title:"Default viewers",default:{".md":"core.markdown",".markdown":"core.markdown"}},{key:"explorer.view",type:"string",hidden:!0,title:"Results view"},{key:"media.signedUrls",type:"enum",enum:["auto","always","never"],default:"auto",hidden:!0,title:"Signed media URLs"}]),A.contributions.register("keymap.default",{type:"keymap",bindings:[{key:"mod+shift+p",command:"workbench.showCommandPalette"},{key:"mod+p",command:"workbench.quickOpen"},{key:"mod+shift+f",command:"workbench.view.home"},{key:"mod+shift+e",command:"workbench.view.home"},{key:"mod+,",command:"workbench.openSettings"},{key:"mod+shift+l",command:"explorer.copyLink"},{key:"mod+u",command:"explorer.upload"},{key:"delete",command:"explorer.delete",when:"view.active == 'home' && explorer.hasSelection"},{key:"escape",command:"workbench.closeOverlays"},{key:"f5",command:"explorer.refresh"},{key:"mod+shift+i",command:"workbench.toggleInfoPanel"},{key:"mod+shift+v",command:"search.voice"},{key:"browsersearch",command:"search.voice"}]})}function JY(A,{workbench:Q,overlay:B,navigation:C,explorer:E}){let J=Q.observe(),K=C.observe(),L=B.observe(),Y=E.observe(),X={"view.active":BA([J],(G)=>G.activity),"sidebar.visible":BA([J],(G)=>G.sidebarVisible),"searchModal.open":BA([J],(G)=>!!G.searchModal),"sheet.open":BA([J],(G)=>G.sheet||""),"infoPanel.open":BA([J],(G)=>!!G.infoPanel),"palette.open":BA([L],(G)=>!!G.palette),"editor.open":BA([K],(G)=>!!G.activeFile),"editor.openerId":BA([K],(G)=>G.stack?.at(-1)?.openerId||""),"editor.contentType":BA([K],(G)=>G.activeFile?.contentType||""),"explorer.collectionId":BA([Y],(G)=>G.collectionId??null),"explorer.hasSelection":BA([Y],(G)=>(G.selection?.length||0)>0)},H=Object.entries(X).map(([G,D])=>A.register(G,D));return()=>H.forEach((G)=>G())}function KY(A,Q){let B=Q.observe(),C=[A.register("viewport.mode",BA([B],(E)=>E.mode)),A.register("viewport.phone",BA([B],(E)=>E.mode==="phone")),A.register("viewport.tv",BA([B],(E)=>E.mode==="tv"))];return()=>C.forEach((E)=>E())}var LY="trove.recents",h$=12;class mJ{#A;constructor(){this.#A={stack:[{kind:"search"}],activeTabId:null,activeFile:null,recents:b$()},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}#B(){return this.#A.stack[this.#A.stack.length-1]}activeTab(){let A=this.#B();return A?.kind==="file"?A:null}#C(A,{history:Q=!0}={}){let B=A[A.length-1],C=B&&B.kind==="file"?B:null;if(this.#Q({stack:A,activeTabId:C?C.id:null,activeFile:C?C.node:null}),Q)this.#E()}reset(){this.#C([{kind:"search"}])}openFile(A,Q,{reset:B=!1}={}){let C={kind:"file",id:A.id,node:A,openerId:Q},E;if(B)E=[{kind:"search"},C];else{let J=this.#A.stack.findIndex((K)=>K.kind==="file"&&K.id===A.id);if(J>=0)E=this.#A.stack.slice(0,J+1),E[J]=C;else E=[...this.#A.stack,C]}this.#J(A),this.#C(E)}back(){if(this.#A.stack.length<=1)return;try{history.back()}catch{this.pop()}}pop(){if(this.#A.stack.length>1)this.#C(this.#A.stack.slice(0,-1),{history:!1})}forget(A){let Q=this.#A.recents.filter((C)=>C.id!==A);if(Q.length!==this.#A.recents.length)this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.filter((C)=>!(C.kind==="file"&&C.id===A));this.#C(B.length?B:[{kind:"search"}],{history:!1})}updateTabNode(A){let Q=this.#A.recents.map((C)=>C.id===A.id?{...C,name:A.name,contentType:A.contentType||C.contentType,...RB(A)?{thumbnail:RB(A)}:{}}:C);if(Q.some((C,E)=>C!==this.#A.recents[E]))this.#Q({recents:Q}),uJ(Q);let B=this.#A.stack.map((C)=>C.kind==="file"&&C.id===A.id?{...C,node:A}:C);this.#C(B,{history:!1})}#E(A=!1){let Q=this.#B(),B=Q?.node,C={troveDepth:this.#A.stack.length,node:B?{id:B.id,name:B.name,contentType:B.contentType,collectionId:B.collectionId}:null,openerId:Q?.openerId||null};try{(A?history.replaceState:history.pushState).call(history,C,"")}catch{}}onPopState(A){let Q=A?.state||{},B=Q.troveDepth||1;if(B<=this.#A.stack.length)this.#C(this.#A.stack.slice(0,B),{history:!1});else if(Q.node)this.#C([...this.#A.stack,{kind:"file",id:Q.node.id,node:Q.node,openerId:Q.openerId}],{history:!1})}#J(A){if(!A)return;let Q=RB(A),C=[{id:A.id,name:A.name,contentType:A.contentType||"",collectionId:A.collectionId,...Q?{thumbnail:Q}:{}},...this.#A.recents.filter((E)=>E.id!==A.id)].slice(0,h$);this.#Q({recents:C}),uJ(C)}}function b$(){try{return JSON.parse(localStorage.getItem(LY))||[]}catch{return[]}}function uJ(A){try{localStorage.setItem(LY,JSON.stringify(A))}catch{}}class pJ{#A;constructor(A,Q=null){this.offline=Q,this.platform=A,this.api=A.api,this.#A={me:null,notifications:{items:[],unread:0},inboxOpen:!1,pushSupported:"serviceWorker"in navigator&&"PushManager"in window,pushEnabled:!1,sidecar:null,backlinks:null,posting:!1,replyTo:null},this.cell=c(this.#A),this._pollTimer=null}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async init(){try{let A=await this.api.me();this.#Q({me:A.principal,admin:!!A.admin})}catch{}if(await this.refreshNotifications(),this._pollTimer=setInterval(()=>this.refreshNotifications(),45000),this._pollTimer.unref)this._pollTimer.unref();this.#C(),window.addEventListener("focus",()=>this.refreshNotifications()),navigator.serviceWorker?.addEventListener?.("message",(A)=>{if(A.data?.type==="trove-push")this.refreshNotifications()})}async refreshNotifications(){try{let A=await this.api.notifications();this.#Q({notifications:A})}catch{}}toggleInbox(A){let Q=A??!this.#A.inboxOpen;if(this.#Q({inboxOpen:Q}),Q&&this.#A.notifications.unread)this.markAllRead()}async markAllRead(){try{await this.api.markNotificationsRead(),this.#Q({notifications:{...this.#A.notifications,unread:0,items:this.#A.notifications.items.map((A)=>({...A,read:!0}))}})}catch{}}async loadSidecar(A){if(!A)return this.#Q({sidecar:null,backlinks:null});this.#Q({sidecar:{nodeId:A,loading:!0,tags:[],comments:[],subscribers:[]}}),this.loadBacklinks(A);try{let Q=await this.api.sidecar(A);if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{...Q,loading:!1}})}catch(Q){if(this.#A.sidecar?.nodeId!==A)return;this.#Q({sidecar:{nodeId:A,loading:!1,error:Q.message,tags:[],comments:[]}})}}async loadBacklinks(A){if(!A)return this.#Q({backlinks:null});this.#Q({backlinks:{nodeId:A,items:[],loading:!0,error:null}});try{let Q=await this.api.backlinks(A);if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:Q.items||[],loading:!1,error:null}})}catch(Q){if(this.#A.backlinks?.nodeId!==A)return;this.#Q({backlinks:{nodeId:A,items:[],loading:!1,error:Q.message}})}}async#B(){if(this.#A.sidecar?.nodeId)await this.loadSidecar(this.#A.sidecar.nodeId)}setReplyTo(A){this.#Q({replyTo:A})}async comment(A){let Q=this.#A.sidecar?.nodeId;if(!Q||!A.trim())return;let B=this.#A.replyTo?.id||null;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(Q)}/comments`,body:{body:A,parentId:B}}),this.#Q({replyTo:null}),this.platform.notifications.info("Offline — your comment will post when you reconnect.");return}this.#Q({posting:!0});try{await this.api.addComment(Q,{body:A,parentId:B}),this.#Q({replyTo:null}),await this.#B()}catch(C){this.platform.notifications.error(`Couldn't post comment: ${C.message}`)}finally{this.#Q({posting:!1})}}async deleteComment(A){let Q=this.#A.sidecar?.nodeId;await this.api.deleteComment(Q,A).catch((B)=>this.platform.notifications.error(B.message)),await this.#B()}async react(A,Q){let B=this.#A.sidecar?.nodeId,E=!(YY(this.#A.sidecar?.comments||[],A)?.reactions?.[Q]||[]).includes(this.#A.me?.id);try{await this.api.reactComment(B,A,Q,E)}catch(J){this.platform.notifications.error(`Couldn't react: ${J.message}`)}await this.#B()}async addTag(A,Q){let B=this.#A.sidecar?.nodeId;if(!A.trim())return;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"POST",path:`/api/items/${encodeURIComponent(B)}/tags`,body:{name:A.trim(),value:Q}}),this.platform.notifications.info("Offline — tag will sync when you reconnect.");return}await this.api.setTag(B,A.trim(),Q).catch((C)=>this.platform.notifications.error(C.message)),await this.#B()}async removeTag(A){let Q=this.#A.sidecar?.nodeId;if(this.offline&&!this.offline.get().online){await this.offline.queueOp({method:"DELETE",path:`/api/items/${encodeURIComponent(Q)}/tags/${encodeURIComponent(A)}`}),this.platform.notifications.info("Offline — tag removal will sync when you reconnect.");return}try{await this.api.removeTag(Q,A)}catch(B){this.platform.notifications.error(`Couldn't remove tag: ${B.message}`)}await this.#B()}async#C(){if(!this.#A.pushSupported)return;try{let Q=await(await navigator.serviceWorker.getRegistration())?.pushManager?.getSubscription();this.#Q({pushEnabled:!!Q})}catch{}}async enablePush(){if(!this.#A.pushSupported){this.platform.notifications.warn("Push notifications are not supported in this browser.");return}try{let{publicKey:A}=await this.api.vapidKey();if(!A){this.platform.notifications.warn("This server has no VAPID key configured for web push.");return}let Q=await navigator.serviceWorker.register("/sw.js");if(await navigator.serviceWorker.ready,await Notification.requestPermission()!=="granted")return this.platform.notifications.info("Notifications permission was denied.");let C=await Q.pushManager.subscribe({userVisibleOnly:!0,applicationServerKey:v$(A)});await this.api.subscribePush(C.toJSON()),this.#Q({pushEnabled:!0}),this.platform.notifications.success("Notifications enabled — you’ll be pinged when someone @mentions you.")}catch(A){this.platform.notifications.error(`Couldn't enable notifications: ${A.message}`)}}}function YY(A,Q){for(let B of A){if(B.id===Q)return B;let C=YY(B.replies||[],Q);if(C)return C}return null}function v$(A){let Q="=".repeat((4-A.length%4)%4),B=(A+Q).replace(/-/g,"+").replace(/_/g,"/"),C=atob(B),E=new Uint8Array(C.length);for(let J=0;J<C.length;J++)E[J]=C.charCodeAt(J);return E}class lJ{get dimensions(){return 0}async embed(A){throw z.unsupported("embed not implemented")}async embedOne(A){return(await this.embed([A]))[0]}}var f$=new Set("a an the of to in on for and or is are be as at by with from this that it".split(" "));function u$(A){return String(A).toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter((Q)=>Q.length>1&&!f$.has(Q))}function m$(A){let Q=2166136261;for(let B=0;B<A.length;B++)Q^=A.charCodeAt(B),Q=Math.imul(Q,16777619);return Q>>>0}class cJ extends lJ{constructor({dimensions:A=256}={}){super();this._dim=A}get dimensions(){return this._dim}async embed(A){return A.map((Q)=>this.#A(Q))}#A(A){let Q=new Float64Array(this._dim),B=u$(A),C=[...B];for(let J=0;J<B.length-1;J++)C.push(B[J]+"_"+B[J+1]);for(let J of C){let K=m$(J),L=K%this._dim,Y=K>>31&1?-1:1;Q[L]+=Y}let E=0;for(let J=0;J<Q.length;J++)E+=Q[J]*Q[J];return E=Math.sqrt(E)||1,Array.from(Q,(J)=>J/E)}}class p$ extends lJ{constructor(A){super();if(!A?.url||!A?.dimensions)throw z.invalid("HttpEmbedding requires url and dimensions");this.cfg=A}get dimensions(){return this.cfg.dimensions}async embed(A){let Q=this.cfg.batchSize??64,B=[];for(let C=0;C<A.length;C+=Q){let E=A.slice(C,C+Q);B.push(...await this.#A(E))}return B}async#A(A){return FB(async()=>{let Q;try{Q=await fetch(this.cfg.url,{method:"POST",headers:{"content-type":"application/json",...this.cfg.apiKey?{authorization:`Bearer ${this.cfg.apiKey}`}:{}},body:JSON.stringify({model:this.cfg.model,input:A})})}catch(E){throw uB(E)}if(Q.status===429||Q.status>=500)throw z.transient(`Embedding endpoint ${Q.status}`);if(!Q.ok)throw z.internal(`Embedding endpoint failed: ${Q.status}`);let B=await Q.json();return(B.data??B.embeddings??[]).map((E)=>E.embedding??E)})}}function XY(A,Q,B){let C=[],E=0;while(E<A.length){let J=Math.min(E+Q,A.length);if(J<A.length){let K=A.slice(E,J),L=Math.max(K.lastIndexOf(`
|
|
731
731
|
|
|
732
732
|
`),K.lastIndexOf(". "),K.lastIndexOf(`
|
|
733
733
|
`));if(L>Q*0.75)J=E+L+1}if(C.push(A.slice(E,J).trim()),J>=A.length)break;E=J-B}return C.filter(Boolean)}var l$=new Set("a an the of to in on for and or is are be as at by with from this that it".split(" "));function dJ(A){return String(A).toLowerCase().replace(/[^a-z0-9\s]/g," ").split(/\s+/).filter((Q)=>Q.length>1&&!l$.has(Q))}var c$="trove-offline",GY="trove-files-v1",aJ=new cJ({dimensions:256});class oJ{#A;constructor(A){this.platform=A,this.api=A.api,this.db=null,this.#A={online:navigator.onLine,pins:[],queued:0,syncing:!1},this.cell=c(this.#A)}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}async init(){if(this.db=await d$(),await this.#E(),await this.#J(),window.addEventListener("online",()=>this.#B()),window.addEventListener("offline",()=>this.#C()),this.#A.online&&!await this.api.reachable())this.#Q({online:!1});if(this.platform.plugins?.setOnline?.(this.#A.online),this.#A.online)this.flushQueue()}async#B(){if(!await this.api.reachable()){this.#Q({online:!1}),await this.platform.plugins?.setOnline?.(!1);return}this.#Q({online:!0}),await this.platform.plugins?.setOnline?.(!0),await this.flushQueue()}async#C(){this.#Q({online:!1}),await this.platform.plugins?.setOnline?.(!1)}async pin(A){if(!A?.id)return;try{if("caches"in window){let E=await caches.open(GY),J=this.platform.mediaUrls,K=J.cacheKey(A.id),{url:L}=await J.url(A.id,{op:"download"}),Y=await fetch(L);if(!Y.ok)throw Error(`Couldn't fetch the file (${Y.status})`);await E.put(new Request(K),Y)}let Q=[],B="";if(C8(A))try{B=await this.api.readText(A.id);let E=XY(B,1000,150),J=await aJ.embed(E.length?E:[A.name]);Q=(E.length?E:[A.name]).map((K,L)=>({text:K,vector:J[L]}))}catch{}let C=(await aJ.embed([A.name]))[0];await n$(this.db,"pins",A.id,{node:A,text:B,chunks:Q,nameVec:C,pinnedAt:Date.now()}),await this.#E(),this.platform.notifications.success(`“${A.name}” is available offline`)}catch(Q){this.platform.notifications.error(`Couldn't make available offline: ${Q.message}`)}}async unpin(A){if(this.#A.pins.find((B)=>B.id===A)&&"caches"in window)await(await caches.open(GY)).delete(this.platform.mediaUrls.cacheKey(A),{ignoreVary:!0}).catch(()=>{});await nJ(this.db,"pins",A),await this.#E()}async#E(){let A=await sJ(this.db,"pins");this.#Q({pins:A.map((Q)=>({id:Q.node.id,name:Q.node.name,contentType:Q.node.contentType,collectionId:Q.node.collectionId,pinnedAt:Q.pinnedAt}))})}async searchOffline(A,{limit:Q=40}={}){let B=await sJ(this.db,"pins");if(!B.length)return[];let C=dJ(A),E=(await aJ.embed([A]))[0],J=[];for(let K of B){let L=dJ(`${K.node.name} ${K.text||""}`),Y=i$(C,new Set(L)),X=HY(E,K.nameVec);for(let G of K.chunks||[])X=Math.max(X,HY(E,G.vector));let H=0.6*X+0.4*Y;if(H>0.02)J.push({nodeId:K.node.id,node:K.node,score:H,snippet:r$(K.text,C),indexerId:"offline"})}return J.sort((K,L)=>L.score-K.score).slice(0,Q)}async queueOp(A){await s$(this.db,"queue",{...A,at:Date.now()}),await this.#J()}async#J(){let A=await sJ(this.db,"queue");this.#Q({queued:A.length})}async flushQueue(){if(!this.#A.online||this.#A.syncing)return;this.#Q({syncing:!0});let A=0,Q=0;try{let B=await o$(this.db,"queue");for(let{key:C,value:E}of B)try{await this.api.request(E.method,E.path,{body:E.body}),await nJ(this.db,"queue",C),A++}catch(J){if(["transient","timeout","unauthorized","quota"].includes(J.code))break;await nJ(this.db,"queue",C),Q++}}finally{if(await this.#J(),this.#Q({syncing:!1}),Q)this.platform.notifications.warn(`${Q} offline change${Q>1?"s":""} couldn't be applied and ${Q>1?"were":"was"} discarded.`);if(A&&this.#A.queued===0)this.platform.notifications.info(`${A} offline change${A>1?"s":""} synced.`)}}}function d$(){return new Promise((A,Q)=>{let B=indexedDB.open(c$,1);B.onupgradeneeded=()=>{let C=B.result;if(!C.objectStoreNames.contains("pins"))C.createObjectStore("pins");if(!C.objectStoreNames.contains("queue"))C.createObjectStore("queue",{autoIncrement:!0})},B.onsuccess=()=>A(B.result),B.onerror=()=>Q(B.error)})}function ZC(A,Q,B,C){return new Promise((E,J)=>{let K=A.transaction(Q,B),L=K.objectStore(Q),Y;Promise.resolve(C(L)).then((X)=>Y=X),K.oncomplete=()=>E(Y),K.onerror=()=>J(K.error)})}var a$=(A)=>new Promise((Q,B)=>{A.onsuccess=()=>Q(A.result),A.onerror=()=>B(A.error)}),n$=(A,Q,B,C)=>ZC(A,Q,"readwrite",(E)=>E.put(C,B)),s$=(A,Q,B)=>ZC(A,Q,"readwrite",(C)=>C.add(B)),nJ=(A,Q,B)=>ZC(A,Q,"readwrite",(C)=>C.delete(B)),sJ=(A,Q)=>ZC(A,Q,"readonly",(B)=>a$(B.getAll()));function o$(A,Q){return ZC(A,Q,"readonly",(B)=>new Promise((C,E)=>{let J=[],K=B.openCursor();K.onsuccess=()=>{let L=K.result;if(!L)return C(J);J.push({key:L.key,value:L.value}),L.continue()},K.onerror=()=>E(K.error)}))}function i$(A,Q){if(!A.length||!Q.size)return 0;let B=0;for(let C of A)if(Q.has(C))B++;return B/A.length}function HY(A,Q){if(!A||!Q)return 0;let B=0;for(let C=0;C<A.length;C++)B+=A[C]*Q[C];return B}function r$(A,Q){if(!A)return null;let B=A.toLowerCase(),C=-1;for(let J of Q){let K=B.indexOf(J);if(K>=0){C=K;break}}if(C<0)return A.slice(0,160).trim();let E=Math.max(0,C-60);return(E>0?"…":"")+A.slice(E,E+200).trim()+"…"}var t$=1000,e$=60000;class iJ{#A;constructor(A){this.platform=A,this.api=A.api,this.#A={tasks:[],issues:[],issuesLoading:!1,tasksError:null,issuesError:null},this.cell=c(this.#A),this._local=new Map,this._server=[],this._timer=null,this._pollMs=null}get(){return this.#A}observe(){return this.cell}#Q(A){this.#A={...this.#A,...A},this.cell.setValue(this.#A)}#B(){this.#Q({tasks:[...this._local.values(),...this._server]})}start(A={}){let Q=A.id||`local_${Math.random().toString(36).slice(2,10)}`,B={id:Q,source:"local",kind:A.kind||"general",title:A.title||"Working",detail:A.detail??null,status:"running",done:0,total:A.total??null,unit:A.unit||null,cancellable:!!A.onCancel,startedAt:Date.now(),endedAt:null,error:null};if(this._local.set(Q,B),this._cancels||=new Map,A.onCancel)this._cancels.set(Q,A.onCancel);this.#B(),this.#E();let C=(E)=>{let J=this._local.get(Q);if(!J||J.status!=="running")return;this._local.set(Q,{...J,...E}),this.#B()};return{id:Q,progress:(E={})=>C({done:E.done??this._local.get(Q)?.done??0,total:E.total===void 0?this._local.get(Q)?.total:E.total,unit:E.unit??this._local.get(Q)?.unit,detail:E.detail??this._local.get(Q)?.detail}),succeed:(E)=>{C({status:"done",endedAt:Date.now(),detail:E??this._local.get(Q)?.detail}),this.#C(Q)},fail:(E)=>{C({status:"failed",endedAt:Date.now(),error:E?.message||String(E||"failed")})},cancel:()=>{C({status:"cancelled",endedAt:Date.now()}),this.#C(Q)}}}#C(A,Q=5000){setTimeout(()=>{this._local.delete(A),this._cancels?.delete(A),this.#B()},Q)}async cancel(A){if(this._local.get(A)){this._cancels?.get(A)?.();return}try{await this.api.cancelTask(A),await this.refreshTasks()}catch(B){this.#Q({tasksError:B.message})}}dismiss(A){if(this._local.delete(A)){this.#B();return}this.api.dismissTask(A).catch(()=>{}),this._server=this._server.filter((Q)=>Q.id!==A),this.#B()}async init(){await this.refresh(),this.#E(),window.addEventListener("focus",()=>this.refresh())}async refresh(){await Promise.all([this.refreshTasks(),this.refreshIssues()])}async refreshTasks(){let A=this.running.length>0;try{let{tasks:Q}=await this.api.tasks();this._server=(Q||[]).map((B)=>({...B,source:"server"})),this.#Q({tasksError:null}),this.#B()}catch(Q){this._server=[],this.#Q({tasksError:Q.message}),this.#B()}if(A&&!this.running.length)this.refreshIssues();this.#E()}async refreshIssues(){this.#Q({issuesLoading:!0});try{let{issues:A}=await this.api.issues();this.#Q({issues:A||[],issuesLoading:!1,issuesError:null})}catch(A){this.#Q({issuesLoading:!1,issuesError:A.message})}}async retryIssue(A){try{await this.api.retryIssue(A),await this.refreshTasks(),this.followUp(),this.platform.notifications.info("Retrying — watch its progress in Activity")}catch(Q){this.platform.notifications.error(`Couldn't retry: ${Q.message}`)}}async dismissIssue(A){let Q=this.#A.issues;this.#Q({issues:Q.filter((B)=>B.id!==A)});try{await this.api.dismissIssue(A)}catch(B){this.#Q({issues:Q}),this.platform.notifications.error(`Couldn't dismiss: ${B.message}`)}}followUp(){for(let A of[400,1500])setTimeout(()=>{this.refreshTasks(),this.refreshIssues()},A)?.unref?.()}get running(){return this.#A.tasks.filter((A)=>A.status==="running")}#E(){let A=this.running.length?t$:e$;if(this._timer&&this._pollMs===A)return;clearTimeout(this._timer),this._pollMs=A,this._timer=setTimeout(()=>{this._timer=null,this.refreshTasks().then(()=>{if(!this.running.length)this.refreshIssues()})},A),this._timer?.unref?.()}dispose(){clearTimeout(this._timer),this._timer=null}}var OB="explorer.hasSelection || editor.open";function $Y(A){let Q=(B,C,E,J={})=>A.platform.commands.register({id:B,title:C,actions:E,...J});Q("workbench.showCommandPalette","Show All Commands",()=>new J0("commands"),{category:"View",icon:"command"}),Q("workbench.quickOpen","Go to File…",()=>new J0("files"),{category:"File",icon:"search"}),Q("workbench.view.home","Go Home (search & browse)",()=>new vQ,{category:"View",icon:"search"}),Q("workbench.view.plugins","Show Plugins",()=>new $C("plugins"),{category:"View"}),Q("workbench.view.admin","Show Administration",()=>new $C("admin"),{category:"View",icon:"gear"}),Q("workbench.openSettings","Open Settings",()=>new $C("settings"),{category:"Preferences",icon:"gear"}),Q("workbench.closeOverlays","Close",()=>new AJ,{palette:!1}),Q("search.voice","Search by Voice",()=>new QJ,{category:"View",icon:"search"}),Q("workbench.showActivity","Show Activity (running work & problems)",()=>new wA(!0),{category:"View",icon:"refresh"}),Q("workbench.rebuildIndex","Rebuild Search Index",()=>new BJ,{category:"View",icon:"refresh"}),Q("workbench.scanCollection","Scan Collection for Outside Changes",()=>new CJ,{category:"Explorer",icon:"refresh"}),Q("workbench.checkStorage","Check Storage Configuration",()=>new EJ,{category:"View",icon:"plug"}),Q("explorer.refresh","Refresh",()=>new tB,{category:"Explorer",icon:"refresh"}),Q("explorer.loadMore","Show More Items",()=>new VE,{palette:!1}),Q("explorer.upload","Upload Files…",()=>new JJ,{category:"Explorer",icon:"upload"}),Q("explorer.copyShareLink","Copy Shareable Link",(B)=>new K0("share",B),{category:"Explorer",icon:"link",when:OB}),Q("explorer.copyLink","Copy Link to Item",(B)=>new K0("trove",B),{category:"Explorer",icon:"link",when:OB}),Q("explorer.rename","Rename",(B)=>new KJ(B),{category:"Explorer",when:OB}),Q("explorer.delete","Delete",()=>new LJ,{category:"Explorer",icon:"trash",when:OB}),Q("explorer.open","Open",(B)=>new XJ(B),{palette:!1}),Q("explorer.download","Download",(B)=>new GJ(B),{category:"Explorer",icon:"download",when:OB}),Q("explorer.showTrash","Show Trash",()=>new YJ,{category:"Explorer",icon:"trash"}),Q("explorer.hideTrash","Hide Trash",()=>new eQ("hide"),{palette:!1}),Q("explorer.restore","Restore from Trash",(B)=>B?new eQ("restore",B):null,{palette:!1}),Q("explorer.purgeOne","Delete Forever",(B)=>B?new eQ("purge",B):null,{palette:!1}),Q("explorer.emptyTrash","Empty Trash",()=>new sA({kind:"confirm",title:"Empty the trash?",body:"Everything in the trash will be destroyed. This cannot be undone.",danger:!0,confirmLabel:"Delete forever",confirmActions:[new eQ("empty")]}),{category:"Explorer",icon:"trash"}),Q("keys.load","Load API Keys",()=>new AC,{palette:!1}),Q("keys.new","New API Key",()=>new HJ,{palette:!1}),Q("keys.cancel","Cancel API Key",()=>new $J,{palette:!1}),Q("keys.dismissMinted","Dismiss API Key",()=>new DJ,{palette:!1}),Q("keys.revoke","Revoke API Key",(B)=>B?new zE(B):null,{palette:!1}),Q("keys.mint","Create API Key",()=>new ZJ,{palette:!1}),Q("offline.pin","Make Available Offline",(B)=>new L0(B,!0),{category:"Offline",icon:"download",when:OB}),Q("offline.unpin","Remove from Offline",(B)=>new L0(B,!1),{palette:!1}),Q("collections.switch","Switch Collection…",(B)=>new WJ(B),{category:"Collections",icon:"files"}),Q("collections.create","New Collection…",()=>new sA({kind:"collection",title:"New collection"}),{category:"Collections",icon:"files"}),Q("workbench.toggleInfoPanel","Toggle Details & Conversation",()=>new UJ,{category:"View",icon:"info"}),Q("notifications.show","Show Notifications",()=>new qQ(!0),{category:"View"}),Q("notifications.enablePush","Enable Push Notifications",()=>new YC,{category:"Notifications"}),Q("plugins.installFromUrl","Install Plugin from URL…",()=>new sA({kind:"prompt",title:"Install plugin from URL",label:"Plugin package (.zip) URL",placeholder:"https://example.com/plugin.zip",confirmLabel:"Fetch",confirmActions:[new rE]}),{category:"Plugins",icon:"plug"}),Q("plugins.installFromFile","Install Plugin from File…",()=>new FJ,{category:"Plugins",icon:"plug"})}function DY(A){let Q=V8(A.settings),B=q8(),C=z8(),E=w8(),J=j8(),K=new iJ(A),L=N8(),Y=O8(),X=P8(),H=new mJ,G=new UE(K),D=new oJ(A),U=new pJ(A,D),I={platform:A,explorer:Q,search:B,transfers:G,social:U,offline:D,activity:K,apiKeys:C,rotation:E,workbench:Y,overlay:X,navigation:H,engine:null},R=new sC({providers:{appState:l.fromSingleton(new Map),explorer:l.fromSingleton(Q),search:l.fromSingleton(B),transfers:l.fromSingleton(G),social:l.fromSingleton(U),offline:l.fromSingleton(D),activity:l.fromSingleton(K),apiKeys:l.fromSingleton(C),rotation:l.fromSingleton(E),acl:l.fromSingleton(J),viewState:l.fromSingleton(L),engine:l.fromLazySingleton(async()=>R,()=>{}),workbench:l.fromSingleton(Y),overlay:l.fromSingleton(X),navigation:l.fromSingleton(H),settings:l.fromSingleton(A.settings),notifications:l.fromSingleton(A.notifications),context:l.fromSingleton(A.context),commands:l.fromSingleton(A.commands),keybindings:l.fromSingleton(A.keybindings),contributions:l.fromSingleton(A.contributions),viewport:l.fromSingleton(A.viewport),voice:l.fromSingleton(A.voice),api:l.fromSingleton(A.api),capabilities:l.fromLazySingleton(async()=>{let V=c(null);return A.api.capabilities().then((_)=>V.setValue(_),()=>{}),V},()=>{}),plugins:l.fromSingleton(A.plugins)}});return I.engine=R,A.commands.dispatch=(V)=>R.dispatch(V),A.dispatch=(V)=>R.dispatch(V),$Y(I),JY(A.context,{workbench:Y,overlay:X,navigation:H,explorer:Q}),KY(A.context,A.viewport),U.init(),D.init(),K.init(),{engine:R,app:I}}var ZY=new WeakMap;function s(A,Q){let B=ZY.get(A);if(!B)B=new WeakMap,ZY.set(A,B);let C=B.get(Q);if(!C)C=_C(A.query(Q),{initial:BQ}),B.set(Q,C);return C}function zA(A,Q,B,C){let E=Object.keys(Q),J=E.map((L)=>s(A,Q[L])),K=BA(J,(...L)=>Object.fromEntries(E.map((Y,X)=>[Y,L[X]])));return T.alias(()=>CQ(K,B,C))}var AD=new FinalizationRegistry(({table:A,key:Q})=>{if(A.get(Q)&&!A.get(Q).deref())A.delete(Q)});function rJ(A,Q){let B=typeof A;if(A===null||B==="string"||B==="number"||B==="boolean")return;if(B!=="object")throw TypeError(`Query argument ${Q} is a ${B}, which cannot be part of a sharing key. Pass an id and let the query look the thing up, or give queryOf a key function.`);if(Array.isArray(A))return A.forEach((E,J)=>rJ(E,`${Q}[${J}]`));let C=Object.getPrototypeOf(A);if(C===Object.prototype||C===null)return Object.entries(A).forEach(([E,J])=>rJ(J,`${Q}.${E}`));throw TypeError(`Query argument ${Q} is a ${A.constructor?.name??"non-plain object"}, which cannot be part of a sharing key. Pass an id and let the query look the thing up, or give queryOf a key function.`)}function tJ(A){if(A===null||typeof A!=="object")return JSON.stringify(A)??"null";if(Array.isArray(A))return`[${A.map(tJ).join(",")}]`;return`{${Object.keys(A).sort().map((Q)=>`${JSON.stringify(Q)}:${tJ(A[Q])}`).join(",")}}`}function QD(...A){return A.forEach((Q,B)=>rJ(Q,`#${B}`)),A.map(tJ).join("|")}function jB(A,Q=QD){let B=new Map;return function(...E){if(this!==void 0&&this!==A)throw TypeError(`${this?.name??"A subclass"}.of() would build a ${A.name}, because \`of\` captures the class it was declared on. Give ${this?.name??"the subclass"} its own \`static of = queryOf(...)\`, or call it on `+A.name+" directly.");let J=Q(...E),K=B.get(J)?.deref();if(K)return K;let L=new A(...E);return B.set(J,new WeakRef(L)),AD.register(L,{table:B,key:J}),L}}function BD(A,Q){if(!Q)return 1;let B=0,C=0;for(let J of Q){let K=A.indexOf(J,C);if(K<0)return 0;B+=K===C?3:1,C=K+1}let E=A.indexOf(Q);if(E>=0)B+=100-Math.min(50,E);return B}function eJ(A,Q,B=60){let C=(Q||"").trim().toLowerCase(),E=A||[];if(!C)return E.slice(0,B);let J=[];for(let K of E){let L=BD(`${K.category||""} ${K.title}`.toLowerCase(),C);if(L>0)J.push([L,K])}return J.sort((K,L)=>L[0]-K[0]||String(K[1].title).localeCompare(String(L[1].title))).slice(0,B).map(([,K])=>K)}function WY({ex:A={},tr:Q={},act:B={},off:C={}}={}){let E=A.items||[],J=B.tasks||[];return{collectionId:A.collectionId??null,collectionLabel:CD(A),totalItems:A.stats?.items??E.length,totalKnown:A.stats?.items!=null,totalBytes:A.stats?.bytes??E.reduce((K,L)=>K+(L.size||0),0),shown:E.length,partial:!!A.nextCursor,usage:A.usage??null,usageLevel:ED(A.usage),uploading:(Q.items||[]).filter((K)=>K.status==="active"),running:J.filter((K)=>K.status==="running"),issues:B.issues||[],off:{online:!0,pins:[],queued:0,syncing:!1,...C}}}function CD(A){if(!A?.collectionId)return"no collection";return(A.collections||[]).find((B)=>B.id===A.collectionId)?.name||A.collectionId}function ED(A){if(!A?.total)return"";let Q=A.available/A.total;return Q<0.05?"critical":Q<0.1?"low":""}function UY(A){let Q=A||{};if(!Q.off?.online)return{kind:"offline",label:"Offline"};if(Q.issues?.length)return{kind:"issues",label:`${Q.issues.length} need${Q.issues.length===1?"s":""} attention`,count:Q.issues.length};if(Q.running?.length||Q.uploading?.length||Q.off?.syncing)return{kind:"working",label:"Working…",count:(Q.running?.length||0)+(Q.uploading?.length||0)};if(Q.usageLevel)return{kind:"lowSpace",label:"Low on space"};return{kind:"idle",label:"Status"}}function AK(A){let Q=A||"";return Q.startsWith("!")?"command":Q.includes("#")?"filter":"search"}function FY(A){return A!=="command"}function JD(A,{pinned:Q=!1,keys:B={}}={}){let C=(E)=>B[E]||void 0;return[{label:"Open",icon:"file-text",actions:[new N("explorer.open",A)]},{label:"Download",icon:"download",actions:[new N("explorer.download",A)]},{label:"Copy shareable link",icon:"link",actions:[new N("explorer.copyShareLink")]},{label:"Copy trove: link",icon:"link",kbd:C("explorer.copyLink"),actions:[new N("explorer.copyLink")]},{sep:!0},{label:"Rename…",actions:[new N("explorer.rename")]},Q?{label:"Remove from offline",icon:"close",actions:[new N("offline.unpin",A)]}:{label:"Make available offline",icon:"download",actions:[new N("offline.pin",A)]},{sep:!0},{label:"Move to trash",icon:"trash",danger:!0,kbd:C("explorer.delete"),actions:[new N("explorer.delete")]}]}function KD(A){return[{label:"Restore",icon:"refresh",actions:[new N("explorer.restore",A.id)]},{sep:!0},{label:"Delete forever",icon:"trash",danger:!0,actions:[new N("explorer.purgeOne",A.id)]}]}function LD(A,{modal:Q,pinnedIds:B,keys:C}){return{icon:MQ(A),title:A.name,detail:A.contentType||"",node:A,actions:[new aA(A,{reset:!!Q}),...Q?[new zB]:[]],menu:()=>JD(A,{pinned:B.has(A.id),keys:C})}}function IY(A,Q=!1){let{ex:B={},se:C={},nav:E={},query:J="",commandMatches:K=[],pinnedIds:L=new Set,keys:Y={}}=A,X=AK(J),H=(O)=>LD(O,{modal:Q,pinnedIds:L,keys:Y}),G=Q?[new zB]:[];if(X==="command")return[{id:"commands",title:"Commands",items:K.map((O)=>({icon:"command",title:O.title,detail:O.category,badge:"command",actions:[new N(O.id),...G]})),empty:"No matching commands."}];let{text:D,filters:U}=sB(J),I=(C.results||[]).map((O)=>O.node),R=C.error,V=(O)=>R?[{icon:"refresh",label:"Retry",title:"Retry",actions:O}]:[];if(U.length){let O=U.map(iC).join(" ")+(D.trim()?` · "${D.trim()}"`:"");return[{id:"filtered",title:C.loading?"Filtering…":R?"Filter failed":"Filtered",verbatim:C.loading||R?null:O,controls:V([new VB(U,D)]),items:I.map(H),empty:C.loading?"Filtering…":R?`Couldn’t filter: ${R}`:"No files match those filters."}]}if(D.trim())return[{id:"results",title:C.loading?"Searching…":R?"Search failed":"Results",controls:V([new VQ(J)]),items:I.map(H),empty:C.loading?"Searching…":R?`Couldn’t search: ${R}`:"No files match."}];let _=[],m=(E.recents||[]).map(H);if(m.length)_.push({id:"recent",title:"Recent",items:m});let b=(B.items||[]).length,q=B.stats?.items??null,p=q??b,k=q!=null?q.toLocaleString():`${b.toLocaleString()}+`,v=(B.items||[]).map(H);if(B.nextCursor)v.push({icon:"refresh",title:B.loadingMore?"Loading…":q!=null?`Show more (${(q-b).toLocaleString()} more)`:"Show more",detail:"or search to jump straight to something",actions:[new N("explorer.loadMore")]});if(B.trash)_.push({id:"trash",title:B.trash.length?`Trash · ${B.trash.length} item${B.trash.length===1?"":"s"}`:"Trash",controls:[...B.trash.length?[{icon:"trash",label:"Empty trash",title:"Destroy everything in the trash",actions:[new N("explorer.emptyTrash")]}]:[],{icon:"close",label:"Close",title:"Hide the trash",actions:[new N("explorer.hideTrash")]}],items:(B.trash||[]).map((O)=>({icon:"trash",title:O.name,detail:`deleted ${new Date(O.deletedAt).toLocaleString()} — restore`,actions:[new N("explorer.restore",O.id)],menu:()=>KD(O)})),empty:"The trash is empty."});return _.push({id:"all",title:B.nextCursor?`All items · showing ${b.toLocaleString()} of ${k}`:"All items",controls:Q?[]:[{icon:"upload",label:"Upload",title:"Upload files to this collection",actions:[new N("explorer.upload")]}],items:v,empty:B.loading?"Loading…":B.error?`Couldn’t load this collection: ${B.error}`:"Nothing here yet — upload a file to get started."}),_}function RY({eligible:A=!1,caps:Q=null}={}){if(!A)return null;let B=Q?.searchPrompt;if(!B?.hint&&!B?.examples?.length)return null;return{hint:B.hint||null,examples:(B.examples||[]).map((C)=>{let{text:E,filters:J}=sB(C.query);return{query:C.query,label:C.label||null,actions:[new AB(C.query),J.length?new VB(J,E):new VQ(E)]}})}}var MY="explorer.view";function VY({views:A=[],saved:Q=null}={},B=[],C=null){if(!A.length)return null;let E=Q&&A.find((L)=>L.id===Q);if(E)return E;let J=C&&A.find((L)=>L.id===C);if(J)return J;let K=B.map((L)=>L.node).filter(Boolean);if(K.length>=3){let L=(X)=>X.match&&Object.keys(X.match).length&&K.filter((H)=>YD(X,H)).length/K.length>0.6,Y=A.find(L);if(Y)return Y}return A[0]}function YD(A,Q){let B=Q.contentType||"",C=(Q.name||"").toLowerCase(),E=C.includes(".")?C.slice(C.lastIndexOf(".")):"";if((A.match.ext||[]).includes(E))return!0;return(A.match.mime||[]).some((J)=>J.endsWith("/*")?B.startsWith(J.slice(0,-1)):B===J)}class KA extends YQ{static deps=[];constructor(A,Q,B,{bootAction:C=null}={}){super();if(this.dep=A,this.cellOf=Q,this.project=B,C)this.bootAction=C}get deps(){return[this.dep,"appState"]}boot(A,{notify:Q}){let B=this.cellOf(A[this.dep]);if(!B){Q(null);return}let C=A[this.dep],E=()=>this.project?this.project(B.getValue(),C):B.getValue();Q(E()),H0(A,this,B.onDirty(()=>Q(E())))}kill(A){$0(A,this)}}function H0(A,Q,B){A.appState.set(Q,B)}function $0(A,Q){let B=A.appState?.get(Q);if(Array.isArray(B))B.forEach((C)=>C());else B?.();A.appState?.delete(Q)}var WC=new KA("explorer",(A)=>A.observe(),(A)=>({...A,selectedNodes:rB(A),collectionMenu:eC(A,(Q)=>new N("collections.switch",Q),()=>new N("collections.create")),collectionAdmin:U8(A,{open:(Q)=>new N("collections.switch",Q),scan:()=>new N("workbench.scanCollection"),rotate:()=>new N("workbench.openSettings"),create:()=>new N("collections.create"),access:(Q)=>new SE(Q)})})),QK=new KA("search",(A)=>A.observe()),BK=new KA("transfers",(A)=>A.observe()),D0=new KA("activity",(A)=>A.observe()),UC=new KA("social",(A)=>A.observe()),Z0=new KA("offline",(A)=>A.observe(),(A)=>({...A,pinnedIds:new Set((A?.pins||[]).map((Q)=>Q.id))})),qY=(A)=>CK.of(A);class CK extends YQ{static deps=["rotation","appState","engine"];static of=jB(CK);constructor(A){super();this.collectionId=A,this.bootAction=new PB(A)}boot(A,{notify:Q}){let B=A.rotation.observe();Q(B.getValue());let C=B.onDirty(()=>Q(B.getValue())),E=setInterval(()=>{if(A.rotation.get().rotation?.status==="running")A.engine.dispatch(new PB(this.collectionId))},2500);H0(A,this,[C,()=>clearInterval(E)])}kill(A){$0(A,this)}}var zY=(A)=>EK.of(A);class EK extends YQ{static deps=["acl","appState"];static of=jB(EK);constructor(A){super();this.collectionId=A,this.bootAction=new Y0(A)}boot(A,{notify:Q}){let B=A.acl.observe();Q(B.getValue()),H0(A,this,B.onDirty(()=>Q(B.getValue())))}kill(A){$0(A,this)}}var NY=new KA("apiKeys",(A)=>A.observe(),(A)=>({...A,draftScopes:tC(A)}),{bootAction:new AC}),FC=new KA("workbench",(A)=>A.observe()),JK=new KA("navigation",(A)=>A.observe()),IC=new KA("overlay",(A)=>A.observe()),PY=new KA("notifications",(A)=>A.observe()),W0=new KA("settings",(A)=>A.observe()),OY=new KA("settings",(A)=>A.observe(),(A,Q)=>Q.grouped()),jY=new KA("context",(A)=>A.observe()),wY=new KA("viewport",(A)=>A.observe()),SY=new KA("voice",(A)=>A.observe(),(A,Q)=>({...A,canListen:!!Q.canListen?.()})),RC=new KA("plugins",(A)=>A?.observe?.()),KK=new KA("viewState",(A)=>A.observe());class DQ extends YQ{static deps=[];constructor(A,Q,B){super();this.deps=[...A,"appState"],this.sources=Q,this.project=B}boot(A,{notify:Q}){let B=()=>Q(this.project(A));B(),H0(A,this,this.sources(A).filter(Boolean).map((C)=>C.onDirty(B)))}kill(A){$0(A,this)}}var fQ=["contributions","context","plugins","settings","commands","keybindings"],uQ=(A)=>[A.contributions.observe(),A.context.observe(),A.plugins?.observe?.(),A.settings.observe()];function _Y(A){return A.commands.paletteCommands().map((Q)=>({id:Q.id,title:Q.title??Q.id,category:Q.category??null,icon:Q.icon??null,keybinding:A.keybindings.labelFor(Q.id),available:A.commands.isAvailable(Q)}))}var XD=[...fQ,"overlay","workbench"],GD=(A)=>[...uQ(A),A.workbench.observe(),A.overlay.observe()],TY=new DQ(XD,GD,(A)=>eJ(_Y(A),A.overlay.get().palette?.query||"")),xY=new DQ(fQ,uQ,(A)=>{return A.contributions.ofType("statusItem").filter((Q)=>Q.visible!==!1&&Q.html).filter((Q)=>!Q.when||A.context.evaluate(Q.when)).filter((Q)=>A.plugins?.isAvailable?.(Q)??!0).sort((Q,B)=>(Q.order??0)-(B.order??0)||String(Q.name).localeCompare(String(B.name))).map((Q)=>({id:Q.id,slot:Q.slot==="left"?"left":"right",html:Q.html,tooltip:Q.tooltip??null,command:Q.command??null}))}),kY=new DQ(fQ,uQ,(A)=>{let Q=A.keybindings.resolved(),B=A.keybindings.overrides(),C=new Map;for(let E of Q)C.set(E.key,(C.get(E.key)||0)+1);return Q.map((E)=>({bindingId:E.bindingId,command:E.command,title:A.contributions.get(E.command)?.title??E.command,key:E.key,label:v0(E.key),custom:!!B[E.bindingId],clash:C.get(E.key)>1}))}),LK=(A=!1)=>YK.of(!!A),HD=[...fQ,"explorer","search","workbench","navigation","offline","capabilities"];class YK extends DQ{static of=jB(YK);constructor(A){super(HD,(Q)=>[...uQ(Q),Q.explorer.observe(),Q.search.observe(),Q.workbench.observe(),Q.navigation.observe(),Q.offline.observe(),Q.capabilities],(Q)=>{let B=Q.workbench.get(),C=Q.offline.observe().getValue()||{},E={ex:Q.explorer.observe().getValue()||{},se:Q.search.observe().getValue()||{},nav:Q.navigation.observe().getValue()||{},query:B.launch.query||"",commandMatches:eJ(_Y(Q),(B.launch.query||"").slice(1)),pinnedIds:new Set((C.pins||[]).map((L)=>L.id)),keys:mY(Q)},J=IY(E,this.modal),K=AK(E.query);return{groups:J,mode:K,view:VY(bY(Q),J.flatMap((L)=>L.items),K==="search"?E.se.resolved?.view??null:null),help:RY({eligible:K!=="command"&&!!E.se.ran&&!E.se.loading&&!E.se.error&&!(E.se.results||[]).length,caps:Q.capabilities.getValue()})}});this.modal=A}}var gY=new DQ(["explorer","transfers","activity","offline"],(A)=>[A.explorer.observe(),A.transfers.observe(),A.activity.observe(),A.offline.observe()],(A)=>{let Q=WY({ex:A.explorer.observe().getValue(),tr:A.transfers.observe().getValue(),act:A.activity.observe().getValue(),off:A.offline.observe().getValue()});return{...Q,condition:UY(Q)}}),yY=new DQ(fQ,uQ,(A)=>A.contributions.ofType("opener").filter((Q)=>!Q.when||A.context.evaluate(Q.when)).filter((Q)=>A.plugins?.isAvailable?.(Q)??!0).sort((Q,B)=>(B.priority??0)-(Q.priority??0)).map((Q)=>WE(Q,A.plugins))),hY=new DQ(fQ,uQ,bY);function bY(A){return{views:A.contributions.ofType("view").filter((Q)=>!Q.when||A.context.evaluate(Q.when)).sort((Q,B)=>(B.priority??0)-(Q.priority??0)).map((Q)=>({id:Q.id,title:Q.title??Q.name??Q.id,icon:Q.icon??null,match:Q.match??null,render:Q.render,move:Q.move})),saved:A.settings.get("explorer.view")||null}}var vY=new DQ(fQ,uQ,(A)=>{let Q=A.settings.get(MB)||{};return Object.entries(Q).map(([B,C])=>{let E=A.contributions.get(C);return{typeKey:B,openerId:C,openerTitle:E?.title||C,missing:!E}})}),fY=(A)=>XK.of(A);class XK extends KA{static of=jB(XK);constructor(A){super("social",(Q)=>Q.observe(),(Q)=>Q?.sidecar??null);this.nodeId=A,this.bootAction=new XC(A),this.killAction=new RJ(A)}}class wB extends YQ{static deps=["api"];static of=jB(wB);constructor(A,Q,B){super();this.nodeId=A,this.maxBytes=Q,this.size=B}async boot({api:A},{notify:Q}){Q(await A.readTextCapped(this.nodeId,{maxBytes:this.maxBytes,size:this.size}))}kill(){}}var uY=new DQ(fQ,uQ,mY);function mY(A){return Object.fromEntries(A.keybindings.resolved().map((Q)=>[Q.command,A.keybindings.labelFor(Q.command)]).filter(([,Q])=>Q))}var MC=new KA("capabilities",(A)=>A);var{svg:DD,h:ZD}=T,GK={link:[{d:"M10 13a5 5 0 0 0 7.07 0l3-3A5 5 0 0 0 13 3l-1.5 1.5"},{d:"M14 11a5 5 0 0 0-7.07 0l-3 3A5 5 0 0 0 11 21l1.5-1.5"}],file:[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5"}],"file-text":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M9 13h6M9 17h6M9 9h2"}],"file-image":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5"},{d:"M8.5 15l2-2 3 3 2-1.5"},{d:"M10 12a1 1 0 1 0 0-.01"}],"file-audio":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M10 12v5M13 10v9"}],"file-video":[{d:"M6 3h8l5 5v13a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"},{d:"M14 3v5h5M10 12l4 2.5-4 2.5z"}],book:[{d:"M4 5a2 2 0 0 1 2-2h13v16H6a2 2 0 0 0-2 2z"},{d:"M4 19a2 2 0 0 1 2-2h13"}],search:[{d:"M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14zM20 20l-3.5-3.5"}],mic:[{d:"M12 3a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V6a3 3 0 0 0-3-3z"},{d:"M5 11a7 7 0 0 0 14 0M12 18v3M9 21h6"}],command:[{d:"M8 6a2 2 0 1 0-2 2h12a2 2 0 1 0-2-2v12a2 2 0 1 0 2-2H6a2 2 0 1 0 2 2z"}],gear:[{d:"M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z"},{d:"M19 12a7 7 0 0 0-.1-1.2l2-1.6-2-3.4-2.4 1a7 7 0 0 0-2-1.2L14 2h-4l-.5 2.6a7 7 0 0 0-2 1.2l-2.4-1-2 3.4 2 1.6A7 7 0 0 0 5 12a7 7 0 0 0 .1 1.2l-2 1.6 2 3.4 2.4-1a7 7 0 0 0 2 1.2L10 22h4l.5-2.6a7 7 0 0 0 2-1.2l2.4 1 2-3.4-2-1.6A7 7 0 0 0 19 12z"}],upload:[{d:"M12 16V4M7 9l5-5 5 5M4 20h16"}],download:[{d:"M12 4v12M7 11l5 5 5-5M4 20h16"}],trash:[{d:"M4 7h16M9 7V4h6v3M6 7l1 13h10l1-13M10 11v6M14 11v6"}],refresh:[{d:"M20 11a8 8 0 1 0-.5 4M20 5v6h-6"}],"chevron-right":[{d:"M9 6l6 6-6 6"}],"chevron-left":[{d:"M15 6l-6 6 6 6"}],"chevron-down":[{d:"M6 9l6 6 6-6"}],close:[{d:"M6 6l12 12M18 6L6 18"}],tag:[{d:"M4 4h6.5a1 1 0 0 1 .7.3l8.5 8.5a1 1 0 0 1 0 1.4l-5.5 5.5a1 1 0 0 1-1.4 0L4.3 11.2a1 1 0 0 1-.3-.7V4z"},{d:"M8 8a0.6 0.6 0 1 0 0-.01"}],play:[{d:"M8 5v14l11-7z",fill:"currentColor",stroke:"none"}],pause:[{d:"M8 5h3v14H8zM13 5h3v14h-3z",fill:"currentColor",stroke:"none"}],"skip-back":[{d:"M11 6v12L3 12zM13 6l8 6-8 6zM21 6v12",fill:"none"}],"skip-forward":[{d:"M13 6v12l8-6zM3 6l8 6-8 6zM3 6v12"}],"back-30":[{d:"M11 8a7 7 0 1 0 7 7"},{d:"M11 4l-3 4 4 1"}],"fwd-30":[{d:"M13 8a7 7 0 1 1-7 7"},{d:"M13 4l3 4-4 1"}],plug:[{d:"M9 3v6M15 3v6M6 9h12v3a6 6 0 0 1-12 0zM12 18v3"}],bell:[{d:"M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9z"},{d:"M13.73 21a2 2 0 0 1-3.46 0"}],files:[{d:"M4 4h9l3 3v3M8 8h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2v-9a2 2 0 0 1 2-2z"}],dots:[{d:"M5 12h.01M12 12h.01M19 12h.01"}],check:[{d:"M5 12l5 5L20 6"}],plus:[{d:"M12 5v14M5 12h14"}],"arrow-up":[{d:"M12 19V5M6 11l6-6 6 6"}],star:[{d:"M12 3l2.7 5.6 6.1.9-4.4 4.3 1 6.1L12 17l-5.4 2.9 1-6.1L3.2 9.5l6.1-.9z"}],info:[{d:"M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 11v5M12 8h.01"}],warn:[{d:"M12 3l9 16H3zM12 10v4M12 17h.01"}],x:[{d:"M6 6l12 12M18 6L6 18"}],list:[{d:"M8 6h12M8 12h12M8 18h12M4 6h.01M4 12h.01M4 18h.01"}],grid:[{d:"M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z"}]};function F(A,{size:Q=18,strokeWidth:B=1.6,className:C}={}){let E=Object.hasOwn(GK,A)?GK[A]:GK.file;return DD({$attrs:{viewBox:"0 0 24 24",width:Q,height:Q,fill:"none",stroke:"currentColor","stroke-width":B,"stroke-linecap":"round","stroke-linejoin":"round",...C?{class:C}:{}}},...E.map((J)=>ZD("path",{$attrs:WD(J)})))}function WD(A){let Q={d:A.d};if(A.fill)Q.fill=A.fill;if(A.stroke)Q.stroke=A.stroke;return Q}function EA(A){if(A==null||Number.isNaN(A))return"—";let Q=["B","KB","MB","GB","TB"],B=0,C=A;while(C>=1024&&B<Q.length-1)C/=1024,B++;return`${C>=100||B===0?Math.round(C):C.toFixed(1)} ${Q[B]}`}function HK(A){if(!A)return"";let Q=Date.now()-A,B=86400000;if(Q<60000)return"just now";if(Q<3600000)return`${Math.floor(Q/60000)}m ago`;if(Q<B)return`${Math.floor(Q/3600000)}h ago`;if(Q<7*B)return`${Math.floor(Q/B)}d ago`;return new Date(A).toLocaleDateString(void 0,{month:"short",day:"numeric",year:Q>330*B?"numeric":void 0})}var UD=/@\[([^\]]+)\]\(([^)]+)\)|(?:^|\s)@([a-zA-Z0-9._@-]{2,})/g;function pY(A){let Q=A||"",B=[],C=new RegExp(UD.source,"g"),E=0,J;while(J=C.exec(Q)){let K=!!J[3],L=J.index+(K&&J[0].startsWith(" ")?1:0);if(L>E)B.push({type:"text",value:Q.slice(E,L)});B.push({type:"mention",name:J[1]||J[3],id:J[2]||null}),E=C.lastIndex}if(E<Q.length)B.push({type:"text",value:Q.slice(E)});return B}var{div:h,span:HA,button:xA,textarea:FD,input:ID,p:l9}=T,RD=["\uD83D\uDC4D","❤️","\uD83C\uDF89","\uD83D\uDC40","\uD83D\uDE80"];function lY(A){let Q=A.so.me;if(!Q||Q.anonymous)return null;let B=(Q.name||Q.id||"?")[0].toUpperCase();return h({className:"principal",title:Q.email||Q.name||Q.id},Q.picture?T.img({src:Q.picture,alt:"",className:"avatar-img"}):HA({className:"avatar-txt"},B))}function cY(A,Q){let B=A.so.notifications;return h({className:"bell-wrap"},xA({className:"iconbtn bell",title:"Notifications"},F("bell",{size:19}),B.unread?HA({className:"bell-badge"},String(B.unread>9?"9+":B.unread)):null).on({click:()=>Q.engine.dispatch(new qQ)}),A.so.inboxOpen?MD(A,Q):null)}function MD(A,Q){let B=A.so.notifications.items;return h({},h({className:"scrim",$styling:{background:"transparent","z-index":"54"}}).on({click:()=>Q.engine.dispatch(new qQ(!1))}),h({className:"inbox"},h({className:"inbox-head"},HA("Notifications"),A.so.pushSupported&&!A.so.pushEnabled?xA({className:"link"},"Enable push").on({click:()=>Q.engine.dispatch(new YC)}):A.so.pushEnabled?HA({className:"muted"},F("check",{size:13})):null),B.length?h({className:"inbox-items"},...B.slice(0,30).map((C)=>VD(C,Q))):h({className:"inbox-empty"},F("info",{size:24}),HA("You’re all caught up."))))}function VD(A,Q){let B=A.items?.[0];return h({className:`inbox-item ${A.read?"":"unread"}`},h({className:"ii-title"},A.title),B?.excerpt?h({className:"ii-excerpt"},"“"+B.excerpt+"”"):null,h({className:"ii-time"},HK(A.createdAt))).on({click:()=>{if(B?.nodeId)Q.engine.dispatch(new oE(B.nodeId));Q.engine.dispatch(new qQ(!1))}})}function dY(A,Q){let B=A.nav,C=B.activeFile?{id:B.activeTabId,node:B.activeFile}:null;return h({className:"infopanel"},h({className:"ip-head"},F("info",{size:15}),HA("Details"),xA({className:"iconbtn",title:"Close"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new CC(!1))})),!C?h({className:"ip-empty"},HA("Open a file to see its tags and conversation.")):Q.watch(s(Q.engine,fY(C.node.id)),(E)=>h({className:"ip-body"},qD(C.node,A,Q),zD(C.node,A,Q),PD(E,Q),OD(A,E,Q))))}function qD(A,Q,B){let C=Q.off?.pinnedIds?.has(A.id)??!1;return h({className:"ip-file"},h({className:"ip-name"},A.name),h({className:"ip-path"},A.contentType||""),xA({className:`btn small ${C?"on":""}`,$styling:{"margin-top":"10px"}},F(C?"check":"download",{size:14}),C?"Available offline":"Make available offline").on({click:()=>C?B.engine.dispatch(new N("offline.unpin",A)):B.engine.dispatch(new N("offline.pin",A))}))}function zD(A,Q,B){let C=Q.so.backlinks,E=A.collectionId?iB(A):null,J=C&&C.nodeId===A.id?C:null;return h({className:"ip-section"},h({className:"ip-label"},"Links"),E?xA({className:"ip-uri",title:"Copy this item’s link"},F("link",{size:12}),HA(E)).on({click:()=>ND(B,E)}):null,h({className:"ip-label",$styling:{"margin-top":"10px"}},"Linked from"),J?.loading?h({className:"ip-muted"},"Loading…"):J?.error?h({className:"ip-muted error"},`Couldn’t load links: ${J.error}`):J?.items?.length?h({className:"ip-backlinks"},...J.items.map((K)=>xA({className:"ip-backlink",title:K.name},F("file-text",{size:12}),HA(K.name)).on({click:()=>B.engine.dispatch(new aA(K))}))):h({className:"ip-muted"},"Nothing links here yet."))}function ND(A,Q){A.engine.dispatch(new tA(Q,`Copied ${Q}`))}function PD(A,Q){let B=A?.tags||[];return h({className:"ip-section"},h({className:"ip-label"},"Tags"),h({className:"tags"},...B.map((C)=>HA({className:"tag"},C.value?`${C.name}: ${C.value}`:C.name,xA({className:"tag-x"},F("close",{size:11})).on({click:()=>Q.engine.dispatch(new pE(C.name))}))),ID({className:"tag-input",placeholder:"+ tag",value:""}).on({keydown:(C)=>{if(C.key==="Enter"&&C.target.value.trim()){let E=C.target.value.trim(),[J,...K]=E.split(":");Q.engine.dispatch(new mE(J.trim(),K.join(":").trim()||void 0)),C.target.value=""}}})))}function OD(A,Q,B){if(Q?.loading)return h({className:"ip-section"},h({className:"spinner"}));let C=Q?.comments||[],E=Q?.error?h({className:"conv-empty"},HA(`Couldn't load the conversation: ${Q.error}`),xA({className:"btn",$styling:{"margin-top":"8px"}},"Retry").on({click:()=>B.engine.dispatch(new XC(Q.nodeId))})):C.length?h({className:"thread"},...C.map((J)=>aY(J,A,B,0))):h({className:"conv-empty"},"No comments yet. Start the discussion — use @ to mention someone.");return h({className:"ip-section conv"},h({className:"ip-label"},`Conversation${Q?.commentCount?` · ${Q.commentCount}`:""}`),E,Q?.error?null:jD(A,B))}function aY(A,Q,B,C){let E=Q.so.me,J=E&&A.author?.id===E.id;return h({className:"comment",$styling:C?{marginLeft:"18px"}:{}},h({className:"c-head"},HA({className:"c-avatar"},(A.author?.name||"?")[0].toUpperCase()),HA({className:"c-author"},A.author?.name||A.author?.id||"Someone"),HA({className:"c-time"},HK(A.createdAt),A.edited?" · edited":"")),A.deleted?h({className:"c-body deleted"},"comment deleted"):h({className:"c-body"},wD(A.body)),!A.deleted?h({className:"c-actions"},...RD.map((K)=>{let L=A.reactions?.[K]||[];return xA({className:`react ${L.includes(E?.id)?"on":""}`},K,L.length?HA({className:"rc"},String(L.length)):null).on({click:()=>B.engine.dispatch(new uE(A.id,K))})}),xA({className:"c-link"},"Reply").on({click:()=>B.engine.dispatch(new C0({id:A.id,author:A.author}))}),J?xA({className:"c-link danger"},"Delete").on({click:()=>B.engine.dispatch(new fE(A.id))}):null):null,(A.replies||[]).length?h({className:"replies"},...A.replies.map((K)=>aY(K,Q,B,C+1))):null).key(A.id)}function jD(A,Q){let B=A.so.me,C=A.so.replyTo;if(!B){if(!A.off?.online)return h({className:"conv-signin"},"You’re offline. Conversations come back when you reconnect.");return h({className:"conv-signin"},HA("You’re signed out, so you can read this conversation but not add to it."),xA({className:"c-link"},"Reload to sign in").on({click:()=>window.location.reload()}))}return h({className:"composer"},C?h({className:"replying"},`Replying to ${C.author?.name||"comment"}`,xA({className:"c-link"},"cancel").on({click:()=>Q.engine.dispatch(new C0(null))})):null,FD({className:"composer-input",placeholder:"Write a comment… @mention someone",rows:2,value:""}).on({keydown:(E)=>{if(E.key==="Enter"&&(E.metaKey||E.ctrlKey))Q.engine.dispatch(new B0(E.target.value)),E.target.value=""}}),h({className:"composer-actions"},HA({className:"muted"},"⌘/Ctrl + Enter"),xA({className:"btn primary",disabled:A.so.posting},"Comment").on({click:(E)=>{let J=E.target.closest(".composer").querySelector(".composer-input");Q.engine.dispatch(new B0(J.value)),J.value=""}})))}function wD(A){return pY(A).map((Q)=>Q.type==="mention"?HA({className:"mention"},`@${Q.name}`):Q.value)}var{div:nY,button:$K,span:SD,img:_D}=T,TD=[{id:"home",icon:"search",title:"Search & files",command:"workbench.view.home"},{id:"plugins",icon:"plug",title:"Plugins",command:"workbench.view.plugins"},{id:"admin",icon:"book",title:"Administration",command:"workbench.view.admin"}];function DK(A,Q){let B=A.wb.activity,C=A.plugins?.filter((E)=>E.status==="active").length||0;return nY({className:"activitybar"},$K({className:"brand-mark",title:"Trove — home"},_D({src:"/icon.svg",alt:"Trove"})).on({click:()=>Q.engine.dispatch(new N("workbench.view.home"))}),...TD.map((E)=>$K({className:`item ${B===E.id?"active":""}`,title:E.title},F(E.icon,{size:22}),E.id==="plugins"&&C?SD({className:"badge"},String(C)):null).on({click:()=>Q.engine.dispatch(new N(E.command))})),nY({className:"spacer"}),cY(A,Q),$K({className:`item ${B==="settings"?"active":""}`,title:"Settings"},F("gear",{size:21})).on({click:()=>Q.engine.dispatch(new N("workbench.openSettings"))}),lY(A))}var xD=new Set(["SPAN","B","STRONG","I","EM","CODE","SMALL","BR","S","U"]),kD=new Set(["class","title"]);function sY(A){let Q=document.createDocumentFragment();if(typeof A!=="string"||!A)return Q;let B=document.createElement("template");B.innerHTML=A.slice(0,4096);let C={nodes:200};for(let E of B.content.childNodes){let J=tY(E,C);if(J)Q.appendChild(J)}return Q}function oY(A){return(sY(A).textContent||"").trim()}function iY(A,Q){return[...sY(A).childNodes].map((B)=>rY(B,Q)).filter((B)=>B!=null)}function rY(A,Q){if(A.nodeType===Node.TEXT_NODE)return A.nodeValue;let B=Q[A.tagName.toLowerCase()];if(!B)return A.textContent;let C={};if(A.className)C.className=A.className;if(A.title)C.title=A.title;return B(C,...[...A.childNodes].map((E)=>rY(E,Q)).filter((E)=>E!=null))}function tY(A,Q){if(Q.nodes--<=0)return null;if(A.nodeType===Node.TEXT_NODE)return document.createTextNode(A.nodeValue);if(A.nodeType!==Node.ELEMENT_NODE)return null;if(!xD.has(A.tagName))return null;let B=document.createElement(A.tagName.toLowerCase());for(let C of A.attributes){let E=C.name.toLowerCase();if(!kD.has(E))continue;B.setAttribute(E,C.value.slice(0,200))}for(let C of A.childNodes){let E=tY(C,Q);if(E)B.appendChild(E)}return B}var{div:BB,button:CB,span:$A}=T;function eY(A,Q){let B=iY(A.html,T);if(!B.length)return null;let C=A.tooltip?oY(A.tooltip):"";return A.command?CB({className:"seg",title:C},...B).on({click:()=>Q.engine.dispatch(new N(A.command))}):$A({className:"seg",title:C},...B)}function gD(A,Q){let B=A.act||{tasks:[],issues:[]},C=B.tasks.filter((K)=>K.status==="running"),E=()=>Q.engine.dispatch(new wA(!0)),J=[];if(C.length){let K=C[0],Y=K.total!=null&&K.total>0?Math.round((K.done||0)/K.total*100):null;J.push(CB({className:"seg sb-activity",title:C.map((X)=>X.title).join(`
|
|
@@ -738,5 +738,5 @@ import{a as RH,c as z1,d as MH}from"./chunk-4xqbzebh.js";var fB={};z1(fB,{wbr:()
|
|
|
738
738
|
`),I=[];U.split(`
|
|
739
739
|
`).forEach((R,V)=>{if(V)I.push(oZ());I.push(...NC(R,Q,B))}),K.push(zX({className:"md-p"},...I))}return E?[...K,MX()]:K}function MX(){return zX({className:"md-truncated"},"This document is too large to display in full. Download it to read the rest.")}function tZ(A){return/^(#{1,6}\s|\s*>|\s*([-*+]|\d+[.)])\s|\s*(```|~~~))/.test(A)||/^\s*(-{3,}|\*{3,}|_{3,})\s*$/.test(A)}var eZ=[{re:/`([^`]+)`/,node:(A)=>NX({className:"md-inline-code"},A[1])},{re:/\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)/,node:(A,Q,B)=>qX(A[2],A[1]||A[2],Q,B)},{re:/(\*\*|__)(.+?)\1/,node:(A,Q,B,C)=>aZ(...NC(A[2],Q,B,C+1))},{re:/(\*|_)(.+?)\1/,node:(A,Q,B,C)=>dZ(...NC(A[2],Q,B,C+1))},{re:/(trove:[^\s<>"'`)\]}]+|https?:\/\/[^\s<>"'`)\]}]+)/,node:(A,Q,B)=>qX(VX(A[1]),VX(A[1]),Q,B)}];function NC(A,Q,B,C=0){if(!A)return[];if(C>12)return[A];let E=[],J=A;while(J){if(E.length>=rZ){E.push(J);break}let K=null;for(let X of eZ){let H=X.re.exec(J);if(H&&(K===null||H.index<K.m.index))K={m:H,rule:X}}if(!K){E.push(J);break}let{m:L,rule:Y}=K;if(L.index)E.push(J.slice(0,L.index));E.push(Y.node(L,Q,B,C)),J=J.slice(L.index+L[0].length)}return E}function VX(A){return A.replace(/[.,;:!?]+$/,"")}function qX(A,Q,B,C){if(rC(A))return IX({className:"md-link md-trove",href:"#",title:A},Q).on({click:(J)=>{J.preventDefault(),C.engine.dispatch(new _K(A,B))}});if(/^https?:\/\//i.test(A))return IX({className:"md-link",href:A,target:"_blank",rel:"noopener noreferrer",title:A},Q);return xK({className:"md-deadlink",title:`Unsupported link: ${A}`},Q)}var{div:DA,pre:A4,img:Q4,span:zQ,button:B4,video:C4,audio:E4}=T,J4={"core.audio":{title:"Audio Player",priority:20,match:{mime:["audio/*"],ext:[".mp3",".flac",".wav",".opus",".ogg",".m4a",".m4b"]},component:G4},"core.video":{title:"Video Player",priority:20,match:{mime:["video/*"],ext:[".mp4",".webm",".mkv",".mov"]},component:H4},"core.image":{title:"Image Viewer",priority:20,match:{mime:["image/*"],ext:[".png",".jpg",".jpeg",".gif",".webp",".svg",".avif"]},component:X4},"core.markdown":{title:"Markdown",priority:30,match:{ext:[".md",".markdown"],mime:["text/markdown"]},component:PX},"core.text":{title:"Text Viewer",priority:10,match:{mime:["text/*","application/json"],ext:[".txt",".md",".json",".js",".mjs",".ts",".jsx",".tsx",".css",".html",".xml",".yaml",".yml",".toml",".ini",".log",".csv",".py",".rb",".go",".rs",".sh",".c",".h",".cpp",".java"]},component:L4}};function jX(A){for(let[Q,B]of Object.entries(J4))A.contributions.register(Q,{type:"opener",...B})}function wX(A,Q,B){let C=B.platform.contributions.get(Q);if(C?.component)try{return C.component(A,B)}catch(E){return _X(E.message)}if(C?.pluginId)return $4(C,A,B);return SX(A,B)}var K4=524288;function L4(A,Q){let B=s(Q.engine,wB.of(A.id,K4,A.size));return T.alias(()=>Q.watch(B,({text:C,truncated:E,total:J})=>DA({className:"viewer text"},A4(C),E?DA({className:"md-truncated"},`Showing the first ${Math.round(C.length/1024)} KB${J?` of ${(J/1048576).toFixed(1)} MB`:""}. `,zQ("Download the file to read all of it.")):null),{placeholder:()=>DA({className:"viewer"},DA({className:"loading"},DA({className:"spinner"}),zQ("Loading…"))),error:(C)=>_X(C.message)}))()}var Y4="This file couldn't be loaded — it may be missing or in an unsupported format.";function kK(A,Q,B){let C=c({error:null}),J=B((K)=>C.setValue({error:K||Y4}));return T.alias(()=>CQ(C,(K)=>K.error?SX(A,Q,K.error):J))()}var gK=(A,Q,B,C)=>A.on({$attach:(E)=>{E._detachMedia=SB(E,Q,B,{onError:C})},$detach:(E)=>{E._detachMedia?.(),E._detachMedia=null}}).opaque();function X4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer image"},gK(Q4({alt:A.name}),A,Q,B)))}function G4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer",$styling:{display:"grid","place-items":"center",gap:"16px",padding:"40px"}},F("file-audio",{size:48}),zQ({$styling:{color:"var(--text-dim)"}},A.name),gK(E4({controls:!0,$styling:{width:"min(520px, 90%)"}}),A,Q,B)))}function H4(A,Q){return kK(A,Q,(B)=>DA({className:"viewer",$styling:{display:"grid","place-items":"center",background:"#000"}},gK(C4({controls:!0,$styling:{"max-width":"100%","max-height":"100%"}}),A,Q,B)))}function SX(A,Q,B){return DA({className:"viewer"},DA({className:"fallback"},F(B?"warn":"file",{size:44}),zQ({$styling:{"font-weight":600}},A.name),zQ(`${A.contentType||"Unknown type"} · ${EA(A.size)}`),zQ({$styling:{color:"var(--text-faint)","max-width":"340px"}},B||"No preview available for this file type. Install a plugin that handles it, or download the file."),B4({className:"btn primary"},F("download",{size:15}),"Download").on({click:()=>Q.engine.dispatch(new N("explorer.download",A))})))}function $4(A,Q,B){let C=c({ready:!1,error:null});return DA({className:"viewer plugin-viewer"},CQ(C,(E)=>{if(E.ready)return null;return DA({className:"pv-status"},E.error?DA({className:"fallback"},F("warn",{size:40}),zQ(E.error)):DA({className:"loading"},DA({className:"spinner"}),zQ("Opening…")))}),DA({className:"pv-host"}).on({$attach:(E)=>{E._detach=B.platform.plugins.mountViewer(A.pluginId,E,Q,A.id,{onReady:()=>C.setValue({ready:!0,error:null}),onError:(J)=>C.setValue({ready:!1,error:J||"This viewer failed to load"})})},$detach:(E)=>{E._detach?.(),E._detach=null}}).opaque())}function _X(A){return DA({className:"viewer"},DA({className:"fallback"},F("warn",{size:40}),zQ(A||"Failed to open")))}var{div:gB,span:TX,button:kB}=T,M0=new Map;function V0(A,Q){let B=A.wb,C=A.nav.stack.filter((J)=>J.kind==="file");U4(C);let E=C[C.length-1];if(!E)return gB({className:"editor"});return gB({className:"editor"},D4(C,E,A,Q),gB({className:"stage"},W4(E,Q)))}function D4(A,Q,B,C){return gB({className:"viewer-nav"},kB({className:"vn-back",title:"Back (Esc)"},F("chevron-left",{size:16})).on({click:()=>C.engine.dispatch(new aE)}),gB({className:"vn-trail"},kB({className:"vn-crumb"},F("search",{size:13}),TX("Search")).on({click:()=>C.engine.dispatch(new vQ)}),...A.map((E)=>kB({className:`vn-crumb ${E.id===Q.id?"active":""}`,title:E.node.name},F(MQ(E.node),{size:13}),TX({className:"label"},E.node.name)).on({click:()=>C.engine.dispatch(new GQ(E.node,E.openerId))}))),gB({className:"vn-actions"},Z4(Q,B,C),kB({className:"iconbtn",title:"Details & comments"},F("info",{size:15})).on({click:()=>C.engine.dispatch(new CC)}),kB({className:"iconbtn",title:"Close (Esc)"},F("close",{size:15})).on({click:()=>C.engine.dispatch(new vQ)})))}function Z4(A,Q,B){let C=E8(Q.openers,A.node);if(C.length<=1)return null;return kB({className:"iconbtn",title:"Open with…"},F("dots",{size:15})).on({click:()=>B.engine.dispatch(new sA({kind:"opener-chooser",node:A.node,openers:C,current:A.openerId}))})}function W4(A,Q){let B=`${A.id}:${A.openerId}`,C=M0.get(B);if(!C)C=()=>wX(A.node,A.openerId,Q),M0.set(B,C);return T.alias(C)().key(A.id)}function U4(A){let Q=new Set(A.map((B)=>`${B.id}:${B.openerId}`));for(let B of M0.keys())if(!Q.has(B))M0.delete(B)}var{div:oA,input:F4,span:lQ}=T;function yK(A,Q){let B=A.overlay.palette;if(!B)return null;let C=B.mode==="files"?B.query.trim()?A.se.paletteFiles||[]:[]:A.matches||[],E=Math.min(B.index,Math.max(0,C.length-1)),J=(K)=>{if(!K)return;if(Q.engine.dispatch(new BC),B.mode==="files")Q.engine.dispatch(new aA(K.node));else Q.engine.dispatch(new N(K.id))};return oA({},oA({className:"scrim"}).on({click:()=>Q.engine.dispatch(new BC)}),oA({className:"palette"},oA({className:"search"},F(B.mode==="files"?"search":"command",{size:18}),F4({type:"text",value:B.query,autofocus:!0,placeholder:B.mode==="files"?"Search files by name…":"Type a command…"}).on({input:(K)=>q4(Q,K.target.value),keydown:(K)=>V4(K,Q,C,E,J),$attach:(K)=>{if(queueMicrotask(()=>K.focus()),K.value!==B.query)K.value=B.query}})),oA({className:"results"},C.length?C.map((K,L)=>{let Y=()=>Q.engine.dispatch(new jE(L));return B.mode==="files"?M4(K,L===E,J,Y):R4(K,L===E,Q,J,Y)}):I4(B,A))))}function I4(A,Q){if(A.mode!=="files")return oA({className:"none"},"No matching commands");if(Q.se.paletteError)return oA({className:"none error"},F("warn",{size:14}),` ${Q.se.paletteError}`);if(Q.se.paletteLoading)return oA({className:"none"},oA({className:"spinner"})," Searching…");return oA({className:"none"},A.query.trim()?"No files found":"Type to search files by name")}function R4(A,Q,B,C,E){return oA({className:`opt ${Q?"active":""} ${A.available?"":"unavailable"}`},lQ({className:"ico"},F(A.icon||"command",{size:16})),A.category?lQ({className:"cat"},A.category+" ›"):null,lQ({className:"title"},A.title),!A.available?lQ({className:"offline-tag"},"offline"):null,A.keybinding?lQ({className:"kbd"},T.h("kbd",A.keybinding)):null).on({click:()=>C(A),mouseenter:E})}function M4(A,Q,B,C){return oA({className:`opt ${Q?"active":""}`},lQ({className:"ico"},F(MQ(A.node),{size:16})),lQ({className:"title"},A.node.name),lQ({className:"sub"},A.node.contentType||"")).on({click:()=>B(A),mouseenter:C})}function V4(A,Q,B,C,E){if(A.key==="ArrowDown")A.preventDefault(),Q.engine.dispatch(new A0(1,B.length));else if(A.key==="ArrowUp")A.preventDefault(),Q.engine.dispatch(new A0(-1,B.length));else if(A.key==="Enter")A.preventDefault(),E(B[C]);else if(A.key==="Escape")A.preventDefault(),Q.engine.dispatch(new BC)}var xX=null;function q4(A,Q){A.engine.dispatch(new OE(Q)),clearTimeout(xX),xX=setTimeout(()=>A.engine.dispatch(new qE(Q)),200)}var{div:a,span:LA,button:kX,h3:sF,p:z4,label:yX,input:hX}=T;function bX(A,Q,B){let C=A.summary,E=oC(B,aB,A,{grants:C.capabilities.filter((X)=>!X.adminOnly||A.isAdmin).map((X)=>X.id),acknowledged:!1}),J=A.policy||{requiresAcknowledgement:!1},K=J.requiresAcknowledgement&&!E.acknowledged,L=(X)=>Q.engine.dispatch(new QB(aB,{...E,...X})),Y=(X)=>L({grants:E.grants.includes(X)?E.grants.filter((H)=>H!==X):[...E.grants,X]});return a({},a({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),a({className:"dialog review",$styling:{width:"min(560px, 96vw)"}},P4(C),a({className:"review-body"},C.description?z4({className:"review-desc"},C.description):null,yB("Capabilities it requests",C.capabilities.length?a({className:"cap-list"},...C.capabilities.map((X)=>j4(X,A.isAdmin,E.grants.includes(X.id),()=>Y(X.id)))):k4("None — this plugin only runs in its sandbox.")),(C.network||[]).length?yB("Network access",a({className:"contrib-list"},...C.network.map(_4))):null,(C.commands||[]).length?yB("Commands it can run",a({className:"contrib-list"},...C.commands.map((X)=>S4(X,Q)))):null,C.storage?yB("Storage",T4(C.storage)):null,C.contributions.length?yB("What it adds",a({className:"contrib-list"},...C.contributions.map(w4))):null,C.settings.length?yB("Settings",a({className:"contrib-list"},...C.settings.map(x4))):null,a({className:"review-meta"},`${C.fileCount} files · ${EA(C.sizeBytes)} · id ${C.id}`)),J.headline?N4(J,E,L):null,a({className:"row-actions"},kX({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),kX({className:`btn primary ${K?"disabled":""}`,disabled:K},F("plug",{size:15}),"Install").on({click:()=>!K&&NA(Q,{actions:A.installActions})}))))}function N4(A,Q,B){return a({className:`review-warning ${A.status}`},a({className:"rw-head"},F("warn",{size:15}),LA(A.headline)),a({className:"rw-detail"},A.detail),A.requiresAcknowledgement?yX({className:"rw-ack"},hX({type:"checkbox",checked:!!Q.acknowledged}).on({change:(C)=>B({acknowledged:!!C.target.checked})}),LA("I know this package is unsigned and I trust where it came from")):null)}function P4(A){let Q=A.trust||{status:"unverified"};return a({className:"review-head"},a({className:"avatar"},(A.name||"?")[0].toUpperCase()),a({className:"rh-main"},a({className:"rh-name"},A.name,LA({className:"rh-ver"},"v"+A.version)),a({className:"rh-author"},"by "+A.author)),O4(Q))}function O4(A){let Q=nB(A),B=Q.status==="verified"&&Q.domain?`Verified · ${Q.domain}`:Q.status==="invalid"?"Invalid signature":Q.status==="signed"?"Signed":"Unverified";return LA({className:`trust ${Q.tone}`,title:Q.explanation},F(Q.icon,{size:13}),B)}function j4(A,Q,B,C){let E=A.adminOnly&&!Q;return yX({className:`cap-row ${E?"blocked":""}`},hX({type:"checkbox",checked:B&&!E,disabled:E}).on({change:()=>!E&&C()}),a({className:"cap-info"},a({className:"cap-name"},A.id,A.adminOnly?LA({className:"pf-badge",$styling:{color:"var(--warn)","margin-left":"6px"}},"admin only"):null),a({className:"cap-desc"},A.description+(E?" — requires an administrator":""))))}function w4(A){let Q={command:"command",opener:"file",indexer:"search",statusItem:"info",register:"info",keymap:"command"}[A.kind]||"command";return a({className:"contrib-row"},F(Q,{size:13}),LA({className:"cr-title"},A.title),A.detail?LA({className:"cr-detail"},A.detail):null,A.offline?LA({className:"pf-badge offline-ok"},"offline"):null,LA({className:"pf-kind"},A.kind))}function S4(A,Q){let B=Q?.platform?.contributions?.get?.(A),C=B?.pluginId?"plugin":B?"built-in":"not installed";return a({className:`contrib-row ${B?"":"blocked"}`},F("command",{size:13}),LA({className:"cr-title"},B?.title||A),LA({className:"cr-detail"},A),LA({className:"pf-kind"},C))}function _4(A){return a({className:"contrib-row"},F("plug",{size:13}),LA({className:"cr-title"},A.host),A.path?LA({className:"cr-detail"},A.path):null,LA({className:"pf-kind"},A.scheme))}function T4(A){let Q=[];if(A.plugin)Q.push(gX("Private database","A SQLite store just for this plugin (server + this device).",!1));if(A.domain)Q.push(gX("Shared database","Shared with other plugins from its domain (SQLite).",A.domainBlocked));return a({className:"contrib-list"},...Q)}function gX(A,Q,B){return a({className:`contrib-row ${B?"blocked":""}`},F("plug",{size:13}),LA({className:"cr-title"},A),LA({className:"cr-detail"},B?Q+" — needs a verified domain":Q),B?LA({className:"pf-badge",$styling:{color:"var(--warn)"}},"unavailable"):null)}function x4(A){return a({className:"contrib-row"},F("gear",{size:13}),LA({className:"cr-title"},A.title),A.secret?LA({className:"pf-badge",$styling:{color:"var(--warn)"}},"secret"):LA({className:"pf-kind"},A.type))}function yB(A,Q){return a({className:"review-section"},a({className:"rs-title"},A),Q)}function k4(A){return a({className:"muted",$styling:{"font-size":"12.5px"}},A)}var{div:w,span:uA,button:mA,input:cQ,h3:hK,p:EI,select:uX,option:q0,label:dQ,textarea:JI}=T;function mX(A,Q){let B=A.overlay.dialog;if(!B)return null;if(B.kind==="collection")return y4(B,Q,A.caps,A.view);if(B.kind==="plugin-review")return bX(B,Q,A.view);if(B.kind==="opener-chooser")return g4(B,Q);let C=sL(A.view,B),E=()=>{if(B.kind==="confirm")Q.engine.dispatch(new TA);NA(Q,{actions:B.confirmActions})};return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog"},hK(B.title),B.body?w({className:"body"},B.body):null,B.kind==="prompt"?w({className:"field"},B.label?uA({$styling:{"font-size":"12px",color:"var(--text-dim)"}},B.label):null,cQ({className:"input",value:C,placeholder:B.placeholder||"",autofocus:!0}).on({input:(J)=>Q.engine.dispatch(new QB(dB,{ref:B,value:J.target.value})),keydown:(J)=>{if(J.key==="Enter")E();if(J.key==="Escape")Q.engine.dispatch(new TA)},$attach:(J)=>queueMicrotask(()=>{J.focus(),J.select()})})):null,w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:`btn ${B.danger?"danger":"primary"}`},B.confirmLabel||"OK").on({click:E}))))}function g4(A,Q){let B=A.openerId||A.current||A.openers[0]?.id,C=!!A.remember,E=()=>{if(C&&B)Q.engine.dispatch(new GC(J8(A.node),B));Q.engine.dispatch(new TA),Q.engine.dispatch(new GQ(A.node,B,{reset:!!A.reset}))};return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog opener-chooser"},hK(`Open “${A.node.name}” with…`),w({className:"opener-list"},...A.openers.map((J)=>dQ({className:`opener-opt ${J.id===B?"sel":""}`},cQ({type:"radio",name:"opener-choice",checked:J.id===B}).on({change:()=>Q.engine.dispatch(new QC({openerId:J.id}))}),F(J.icon||MQ(A.node),{size:18}),w({className:"oo-main"},uA({className:"oo-title"},J.title||J.id),uA({className:"oo-src"},J.source))).on({click:()=>Q.engine.dispatch(new QC({openerId:J.id}))}))),dQ({className:"opener-remember"},cQ({type:"checkbox",checked:C}).on({change:(J)=>Q.engine.dispatch(new QC({remember:J.target.checked}))}),uA(`Always use this for ${K8(A.node)}`)),w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:"btn primary"},"Open").on({click:E}))))}var vX="collectionDialog";function y4(A,Q,B,C){let E=B?.storageDrivers||[],J={name:"",description:"",driver:E[0]?.key||"",encrypt:!1,encryptWhat:"all",encryptList:""},K=oC(C,vX,A,{form:J}),L=K.form,Y=E.find((I)=>I.key===L.driver)||E[0],X=(I)=>(R)=>{let V=R.target.type==="checkbox"?R.target.checked:R.target.value;Q.engine.dispatch(new eE(vX,K.ref,{[I]:V},J))},H=()=>{let I={driver:L.driver};for(let R of Y?.fields||[]){let V=L[R.name];if(V!==void 0&&V!=="")I[R.name]=R.type==="number"?Number(V):V}Q.engine.dispatch(new tE({name:L.name,description:L.description,store:I,encryption:h4(L)}))},G=(I,R,V="")=>w({className:"field",$styling:{"margin-bottom":"10px"}},dQ(I),cQ({className:"input",placeholder:V}).on({input:X(R)})),D=L.encrypt&&L.encryptWhat!=="all"&&!pX(L.encryptList).length?L.encryptWhat==="extensions"?"Name at least one extension, or choose every file.":"Name at least one media type, or choose every file.":null,U=!!L.name.trim()&&!!L.driver&&!D&&(Y?.fields||[]).every((I)=>!I.required||String(L[I.name]??"").trim());return w({},w({className:"scrim"}).on({click:()=>Q.engine.dispatch(new TA)}),w({className:"dialog",$styling:{width:"min(480px, 94vw)"}},hK("New collection"),w({className:"body"},"A collection is a backing store you own. Configure where its files live."),G("Name","name","Team Vault"),E.length?w({className:"field",$styling:{"margin-bottom":"10px"}},dQ("Backing store"),uX({className:"input"},...E.map((I)=>q0({value:I.key,selected:L.driver===I.key},I.label))).on({change:X("driver")})):w({className:"body"},"This server has no storage drivers registered, so a collection cannot be created."),Y?v4(Y,L,X):null,b4(L,X,B,D),w({className:"row-actions"},mA({className:"btn"},"Cancel").on({click:()=>Q.engine.dispatch(new TA)}),mA({className:"btn primary",$attrs:U?{}:{disabled:"true"}},"Create collection").on({click:()=>U&&H()}))))}function h4(A){if(!A.encrypt)return null;let Q=pX(A.encryptList);return{enabled:!0,rules:A.encryptWhat==="all"?{all:!0}:A.encryptWhat==="extensions"?{extensions:Q}:{mimeTypes:Q}}}function pX(A){return String(A||"").split(/[\s,]+/).map((Q)=>Q.trim()).filter(Boolean)}function b4(A,Q,B,C){let E=(B?.indexers||[]).filter((J)=>J.readsContent!==!1);return w({className:"field enc-section",$styling:{"margin-bottom":"10px"}},dQ({className:"enc-toggle"},cQ({type:"checkbox",checked:!!A.encrypt}).on({change:Q("encrypt")}),uA("Encrypt files in this collection")),!A.encrypt?w({className:"enc-hint"},"Files are stored exactly as uploaded."):w({className:"enc-body"},w({className:"field"},dQ("What to encrypt"),uX({className:"input"},q0({value:"all",selected:A.encryptWhat==="all"},"Every file"),q0({value:"extensions",selected:A.encryptWhat==="extensions"},"Only these extensions"),q0({value:"mimeTypes",selected:A.encryptWhat==="mimeTypes"},"Only these media types")).on({change:Q("encryptWhat")})),A.encryptWhat!=="all"?w({className:"field"},cQ({className:"input",value:A.encryptList,placeholder:A.encryptWhat==="extensions"?".pdf, .docx, .key":"image, application/pdf"}).on({input:Q("encryptList")}),w({className:"enc-hint"},A.encryptWhat==="extensions"?"Separated by commas. The leading dot is optional.":"Separated by commas. “image” covers every image type.")):null,C?w({className:"enc-problem"},F("warn",{size:13}),uA(C)):null,w({className:"enc-scope"},w({className:"es-title"},"What this does"),w({className:"es-line"},"Files are sealed in your browser before they are uploaded, so the storage provider only ever holds ciphertext."),w({className:"es-title"},"What it does not do"),w({className:"es-line"},"It is not end-to-end. The drive holds the key and decrypts for anything that reads through it — previews, downloads, and search indexing."),E.length?w({className:"es-line"},`These read file contents in the clear: ${E.map((J)=>J.title||J.id).join(", ")}.`):null,w({className:"es-line note"},"This applies to files uploaded from now on. Turning it off later does not decrypt anything already sealed."))))}function v4(A,Q,B){if(!A.fields.length)return w({className:"body",$styling:{"font-size":"12px"}},A.description||"This store needs no configuration.");return w({},A.description?w({className:"body",$styling:{"font-size":"12px","margin-bottom":"10px"}},A.description):null,...A.fields.map((C)=>C.type==="boolean"?w({className:"field",$styling:{"margin-bottom":"10px"}},dQ({},cQ({type:"checkbox"}).on({change:B(C.name)}),` ${C.label}`),C.help?w({className:"body",$styling:{"font-size":"11.5px"}},C.help):null):w({className:"field",$styling:{"margin-bottom":"10px"}},dQ(C.label+(C.required?"":" (optional)")),cQ({className:"input",placeholder:C.placeholder,autocomplete:"off",type:C.type==="password"||C.secret?"password":C.type==="number"?"number":"text"}).on({input:B(C.name)}),C.help?w({className:"body",$styling:{"font-size":"11.5px"}},C.help):null)))}var fX=220,f4=34,u4=20;function m4(A,Q){let{innerWidth:B,innerHeight:C}=window;if(!A)return{x:Math.round(B/2-fX/2),y:Math.round(C/3)};let E=A.rect?A.rect.left:A.x,J=A.rect?A.prefer==="up"?A.rect.top-8-Q:A.rect.bottom+8:A.y;return{x:Math.max(8,Math.min(E,B-fX)),y:Math.max(8,Math.min(J,C-Q))}}function lX(A,Q){let B=A.overlay.contextMenu;if(!B||!B.items?.length)return null;let C=Math.min(B.items.length*f4+u4,window.innerHeight-24),{x:E,y:J}=m4(B.at,C);return w({},w({className:"scrim",$styling:{background:"transparent"}}).on({click:()=>Q.engine.dispatch(new qB),contextmenu:(K)=>{K.preventDefault(),Q.engine.dispatch(new qB)}}),w({className:"menu",$styling:{left:E+"px",top:J+"px"}},...B.items.map((K,L)=>K.sep?w({className:"sep"}):mA({className:`mi ${K.danger?"danger":""}`,autofocus:L===0},K.icon?F(K.icon,{size:15}):null,uA(K.label),K.kbd?uA({className:"kbd"},K.kbd):null).on({click:()=>{Q.engine.dispatch(new qB),NA(Q,K)},keydown:(Y)=>{if(Y.key==="Escape")Y.preventDefault(),Q.engine.dispatch(new qB)},$attach:(Y)=>{if(L===0)queueMicrotask(()=>Y.focus())}}))))}function cX(A,Q){let B=A.notif||[];if(!B.length)return null;return w({className:"toasts"},...B.slice(-5).map((C)=>w({className:`toast ${C.level}`},w({className:"bar"}),w({className:"msg"},C.message),mA({className:"x"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new PE(C.id))})).key(C.id)))}function dX(A,Q){let B=A.tr.items;if(!B.length)return null;return w({className:"tray"},w({className:"head"},F("upload",{size:14}),uA({$styling:{"margin-left":"6px"}},"Transfers"),w({className:"actions"},mA({className:"iconbtn",title:"Clear finished"},F("check",{size:14})).on({click:()=>Q.engine.dispatch(new vE)}))),w({className:"items"},...B.map((C)=>w({className:`xfer ${C.status}`},w({className:"top"},F(C.status==="error"?"warn":C.status==="done"?"check":"upload",{size:14}),uA({className:"name"},C.name),C.status==="active"?mA({className:"iconbtn",title:"Cancel"},F("close",{size:13})).on({click:()=>Q.engine.dispatch(new LC(C.id))}):uA({className:"pct"},C.status==="done"?EA(C.total):C.status)),C.status==="active"?w({className:"progress"},w({$styling:{width:`${Math.round(C.ratio*100)}%`}})):C.error?w({$styling:{"font-size":"11px",color:"var(--danger)","margin-top":"4px"}},C.error):null,C.status==="active"?w({className:"pct",$styling:{"margin-top":"4px"}},`${EA(C.loaded)} / ${EA(C.total)}`):null,(C.status==="error"||C.status==="cancelled")&&C.retryable?w({className:"xfer-actions"},mA({className:"btn small"},F("refresh",{size:12}),uA("Retry")).on({click:()=>Q.engine.dispatch(new hE(C.id))}),mA({className:"btn small ghost"},"Dismiss").on({click:()=>Q.engine.dispatch(new bE(C.id))})):null).key(C.id))))}function aX(A,Q){let B=A.overlay.pluginPanel;if(!B)return null;let C=(A.plugins||[]).find((E)=>E.id===B);return w({className:"plugin-panel",$styling:{width:"380px"}},w({className:"head"},F("plug",{size:14}),uA(C?.name||B),mA({className:"iconbtn x"},F("close",{size:14})).on({click:()=>Q.engine.dispatch(new TE)})),w({className:"host"}).on({$attach:(E)=>{E._detach=Q.platform.plugins.mountPanel(B,E,{width:380,height:460})},$detach:(E)=>E._detach?.()}))}var{div:d,button:NQ,span:PC,h3:p4,p:nX,pre:l4}=T,c4={running:"refresh",done:"check",failed:"close",cancelled:"close"};function d4(A,Q){Q.engine.dispatch(new tA(A))}function sX(A){if(A.total==null)return null;return A.unit==="bytes"?`${EA(A.done||0)} of ${EA(A.total)}`:`${A.done||0} of ${A.total}${A.unit?` ${A.unit}`:""}`}function oX(A,Q){let B=A.status==="running",C=B&&A.total!=null&&A.total>0,E=C?Math.min(100,Math.round((A.done||0)/A.total*100)):0;return d({className:`act-task act-${A.status}`,"data-task-id":A.id},d({className:"act-row"},B?d({className:"spinner",$styling:{width:"12px",height:"12px"}}):F(c4[A.status]||"info",{size:13}),d({className:"act-body"},d({className:"act-title"},A.title),A.detail?d({className:"act-detail"},A.detail):null,A.error?d({className:"act-error"},A.error):null),B&&A.cancellable?NQ({className:"act-action",title:"Cancel"},F("close",{size:12})).on({click:()=>Q.engine.dispatch(new xE(A.id))}):!B?NQ({className:"act-action",title:"Dismiss"},F("close",{size:12})).on({click:()=>Q.engine.dispatch(new kE(A.id))}):null),B?d({className:`act-bar ${C?"":"indeterminate"}`},d({className:"act-fill",$styling:C?{width:`${E}%`}:{}})):null,B&&sX(A)?d({className:"act-amount"},sX(A)):null)}function a4(A,Q){let B=new Date(A.firstAt||A.lastAt).toLocaleString();return d({className:`act-issue act-sev-${A.severity||"error"}`,"data-issue-id":A.id},d({className:"act-row"},F(A.severity==="warning"?"info":"close",{size:13}),d({className:"act-body"},d({className:"act-title"},A.title),A.detail?d({className:"act-detail"},A.detail):null,A.remedy?l4({className:"act-remedy"},A.remedy):null,d({className:"act-meta"},A.count>1?`${A.count} times, since ${B}`:`since ${B}`))),d({className:"act-actions"},A.remedy?NQ({className:"btn small ghost"},"Copy fix").on({click:()=>d4(A.remedy,Q)}):null,A.retryable?NQ({className:"btn small act-retry"},F("refresh",{size:12}),PC("Retry")).on({click:()=>Q.engine.dispatch(new gE(A.id))}):null,NQ({className:"btn small ghost act-dismiss"},"Dismiss").on({click:()=>Q.engine.dispatch(new yE(A.id))})))}function bK(A,Q){let B=A.act||{tasks:[],issues:[]};if(!A.overlay.activityPanel)return null;let C=B.tasks.filter((J)=>J.status==="running"),E=B.tasks.filter((J)=>J.status!=="running");return d({className:"activity-panel"},d({className:"act-head"},p4("Activity"),NQ({className:"act-action",title:"Close"},F("close",{size:13})).on({click:()=>Q.engine.dispatch(new wA(!1))})),B.tasksError||B.issuesError?d({className:"act-offline"},F("info",{size:12}),PC(`Couldn't reach the server — this list may be out of date (${B.issuesError||B.tasksError})`)):null,d({className:"act-section"},d({className:"act-section-title"},"Running"),C.length?d(...C.map((J)=>oX(J,Q))):nX({className:"act-empty"},"Nothing running.")),B.issues.length?d({className:"act-section"},d({className:"act-section-title"},`Needs attention (${B.issues.length})`),d(...B.issues.map((J)=>a4(J,Q)))):d({className:"act-section"},d({className:"act-section-title"},"Needs attention"),nX({className:"act-empty"},B.issuesError?"Could not load the list of problems.":B.issuesLoading?"Checking…":"No standing problems.")),E.length?d({className:"act-section"},d({className:"act-section-title"},"Recently finished"),d(...E.map((J)=>oX(J,Q)))):null,d({className:"act-foot act-actions"},NQ({className:"btn small ghost act-rebuild"},F("refresh",{size:12}),PC("Rebuild search index")).on({click:()=>Q.engine.dispatch(new N("workbench.rebuildIndex"))}),NQ({className:"btn small ghost act-scan"},F("refresh",{size:12}),PC("Scan for outside changes")).on({click:()=>Q.engine.dispatch(new N("workbench.scanCollection"))}),NQ({className:"btn small ghost act-storage"},F("plug",{size:12}),PC("Check storage")).on({click:()=>Q.engine.dispatch(new N("workbench.checkStorage"))})))}var{div:ZA,button:LB,span:WQ,img:tX}=T,iX=[{id:"home",icon:"search",label:"Files",command:"workbench.view.home"},{id:"upload",icon:"upload",label:"Upload",command:"explorer.upload"},{id:"plugins",icon:"plug",label:"Plugins",command:"workbench.view.plugins"}],rX={offline:{icon:"info",tone:"warn"},issues:{icon:"warn",tone:"danger"},working:{spinner:!0,tone:""},lowSpace:{icon:"info",tone:"warn"},idle:{icon:"info",tone:""}};function eX(A,Q){let B=A.facts,C=B.condition,E={...rX[C.kind]||rX.idle,label:C.label,badge:C.kind==="issues"?C.count:0},J=A.wb.activity==="settings"?"Settings":A.wb.activity==="plugins"?"Plugins":B.collectionLabel;return ZA({className:"phonebar top"},LB({className:"pb-brand",title:"Trove — home"},tX({src:"/icon.svg",alt:"Trove"})).on({click:()=>Q.engine.dispatch(new N("workbench.view.home"))}),ZA({className:"pb-title"},J),LB({className:`pb-status ${E.tone}`,title:E.label,$attrs:{"aria-label":E.label}},E.spinner?ZA({className:"spinner",$styling:{width:"15px",height:"15px"}}):F(E.icon,{size:18}),E.badge?WQ({className:"pb-badge"},String(E.badge>9?"9+":E.badge)):null).on({click:()=>Q.engine.dispatch(new Q0("status"))}))}function A1(A,Q){let B=A.wb.activity,C=A.wb.sheet,E=A.so.notifications.unread;return ZA({className:"phonebar bottom"},...iX.map((J)=>LB({className:`pb-tab ${!C&&B===J.id?"active":""}`,$attrs:{"aria-label":J.label}},F(J.icon,{size:21}),WQ({className:"pb-label"},J.label)).on({click:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(J.command))}})),LB({className:`pb-tab ${C==="more"||!C&&!iX.some((J)=>J.id===B)?"active":""}`,$attrs:{"aria-label":"More"}},F("dots",{size:21}),E?WQ({className:"pb-badge"},String(E>9?"9+":E)):null,WQ({className:"pb-label"},"More")).on({click:()=>Q.engine.dispatch(new Q0("more"))}))}function SA({icon:A,label:Q,value:B,danger:C,onClick:E}){let J=[F(A,{size:18}),WQ({className:"sr-label"},Q),B!=null?WQ({className:"sr-value"},B):null,E?F("chevron-right",{size:16,className:"sr-go"}):null];return E?LB({className:`sheet-row ${C?"danger":""}`},...J).on({click:E}):ZA({className:"sheet-row static"},...J)}function Q1(A,Q){let B=A.wb.sheet;if(!B)return null;return ZA({className:"sheet-wrap"},ZA({className:"scrim"}).on({click:()=>Q.engine.dispatch(new nA)}),ZA({className:"sheet"},ZA({className:"sheet-grip"}).on({click:()=>Q.engine.dispatch(new nA)}),B==="status"?n4(A,Q):s4(A,Q)))}function n4(A,Q){let B=A.facts,C=(E)=>()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(E))};return ZA({className:"sheet-body"},ZA({className:"sheet-title"},B.collectionLabel),B.issues.length?SA({icon:"warn",danger:!0,label:`${B.issues.length} need${B.issues.length===1?"s":""} attention`,onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}):null,B.running.length||B.uploading.length?SA({icon:"refresh",label:`${B.running.length+B.uploading.length} running`,onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}):null,!B.off.online?SA({icon:"info",label:"Offline",value:`${B.off.pins.length} pinned`}):null,B.off.queued?SA({icon:"upload",label:"Waiting to sync",value:String(B.off.queued)}):null,SA({icon:"files",label:"Items",value:B.partial?`${B.shown.toLocaleString()} of ${B.totalKnown?B.totalItems.toLocaleString():"more"}`:B.totalItems.toLocaleString()}),SA({icon:"file",label:"Size",value:`${EA(B.totalBytes)}${B.totalKnown||!B.partial?"":"+"}`}),B.usage?.total?ZA({className:"sheet-row static usage"},F("download",{size:18}),WQ({className:"sr-label"},"Free space"),ZK(B)):null,A.caps?SA({icon:A.caps.storage?.presignDownload?"download":"files",label:"Transfers",value:A.caps.storage?.presignDownload?"Direct to storage":"Through the server"}):null,A.caps?.features?.semanticSearch?SA({icon:"star",label:"Search",value:"Semantic + keyword"}):null,ZA({className:"sheet-actions"},LB({className:"btn small ghost"},F("refresh",{size:13}),WQ("Scan for changes")).on({click:C("workbench.scanCollection")}),LB({className:"btn small ghost"},F("refresh",{size:13}),WQ("Activity")).on({click:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}})))}function s4(A,Q){let B=(J)=>()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new N(J))},C=A.so.me,E=A.so.notifications.unread;return ZA({className:"sheet-body"},C&&!C.anonymous?ZA({className:"sheet-me"},C.picture?tX({src:C.picture,alt:"",className:"avatar-img"}):WQ({className:"avatar-txt"},(C.name||C.id||"?")[0].toUpperCase()),ZA({},ZA({className:"sm-name"},C.name||C.id),C.email?ZA({className:"sm-sub"},C.email):null)):null,SA({icon:"bell",label:E?`Notifications (${E})`:"Notifications",onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new qQ(!0))}}),SA({icon:"refresh",label:"Activity & problems",onClick:()=>{Q.engine.dispatch(new nA),Q.engine.dispatch(new wA(!0))}}),SA({icon:"info",label:"Details & conversation",onClick:B("workbench.toggleInfoPanel")}),SA({icon:"trash",label:"Trash",onClick:B("explorer.showTrash")}),SA({icon:"refresh",label:"Refresh",onClick:B("explorer.refresh")}),SA({icon:"command",label:"All commands",onClick:B("workbench.showCommandPalette")}),SA({icon:"gear",label:"Settings",onClick:B("workbench.openSettings")}))}var{alias:o4,div:UQ}=T;function vK({engine:A,platform:Q}){let B={engine:A,platform:Q,watch:CQ},C=BA([s(A,FC),s(A,IC),s(A,JK),s(A,WC),s(A,QK),s(A,jY),s(A,W0),s(A,Z0),s(A,wY),s(A,SY),s(A,KK),s(A,MC),s(A,uY),s(A,LK(!1)),s(A,LK(!0)),s(A,hY),s(A,yY)],(K,L,Y,X,H,G,D,U,I,R,V,_,m,b,q,p,k)=>({wb:K,overlay:L,nav:Y,ex:X,se:H,ctx:G,settings:D,off:U,vp:I,voice:R,view:V,caps:_,commandKeys:m,content:b,modalContent:q,views:p,openers:k})),E={ex:WC,tr:BK,act:D0,off:Z0,so:UC,wb:FC,statusItems:xY,caps:MC,facts:gY},J={statusBar:zA(A,E,(K)=>WK(K,B),{placeholder:()=>UQ({className:"statusbar"})}),phoneTopBar:zA(A,E,(K)=>eX(K,B),{placeholder:()=>UQ({className:"phonebar top"})}),phoneBottomBar:zA(A,E,(K)=>A1(K,B),{placeholder:()=>UQ({className:"phonebar bottom"})}),phoneSheet:zA(A,E,(K)=>Q1(K,B)),transferTray:zA(A,{tr:BK},(K)=>dX(K,B)),toasts:zA(A,{notif:PY},(K)=>cX(K,B)),activityPanel:zA(A,{act:D0,overlay:IC},(K)=>bK(K,B)),pluginPanel:zA(A,{overlay:IC,plugins:RC},(K)=>aX(K,B)),settingsView:zA(A,{settings:W0,settingsGroups:OY,keys:NY,caps:MC,ex:WC,assoc:vY},(K)=>VK(K,B,J)),keybindings:zA(A,{bindings:kY,view:KK},(K)=>WX(K.bindings||[],B,K.view?.[qK]??null)),pluginsView:zA(A,{plugins:RC,settings:W0},(K)=>jK(K,B)),adminView:zA(A,{caps:MC,ex:WC,plugins:RC,act:D0,so:UC,wb:FC},(K)=>SK(K,B)),infoPanel:zA(A,{so:UC,off:Z0,nav:JK},(K)=>dY(K,B)),activityBar:zA(A,{wb:FC,plugins:RC,so:UC},(K)=>DK(K,B)),commandPalette:zA(A,{overlay:IC,se:QK,matches:TY},(K)=>yK(K,B))};return o4(()=>CQ(C,(K)=>i4(K,B,J)))}function i4(A,Q,B){let C=A.vp?.mode||"desktop",E=C==="phone";return UQ({className:`shell ${C} ${A.settings["workbench.density"]==="compact"?"compact":""}`},E?B.phoneTopBar():null,UQ({className:"body"},E?null:B.activityBar(),r4(A,Q,B)),E?B.phoneBottomBar():B.statusBar(),E?B.phoneSheet():null,t4(A,Q),B.commandPalette(),mX(A,Q),lX(A,Q),B.pluginPanel(),B.toasts(),B.transferTray(),B.activityPanel())}function r4(A,Q,B){if(A.ex?.gate&&A.wb.activity!=="settings")return PK(A,Q);switch(A.wb.activity){case"settings":return B.settingsView();case"plugins":return B.pluginsView();case"admin":return B.adminView();default:{if(!A.nav.activeTabId)return R0(A,Q);if(!A.wb.infoPanel)return V0(A,Q);return A.vp?.mode==="phone"?B.infoPanel():UQ({className:"editor-split"},V0(A,Q),B.infoPanel())}}}function t4(A,Q){if(!A.wb.searchModal)return UQ();return UQ({className:"search-modal"},UQ({className:"scrim"}).on({click:()=>Q.engine.dispatch(new zB)}),UQ({className:"search-modal-panel"},R0(A,Q,{modal:!0})))}function C1({root:A=document.querySelector(".workbench"),baseUrl:Q="",openers:B=[],views:C=[],settings:E=[],serviceWorker:J=!0,debug:K=globalThis.__troveDebug===!0}={}){let L=EY({baseUrl:Q}),{engine:Y,app:X}=DY(L);if(jX(L),KX(L),B1(L,"opener",B),B1(L,"view",C),E.length)L.settings.register(E);L.plugins.restore();let H=vK({engine:Y,platform:L});T.reconcile(A,[H()]);let G=()=>{document.documentElement.dataset.theme=L.settings.get("workbench.theme")||"dark"};if(G(),TQ(L.settings.observe(),()=>G()),L.viewport.install(),L.voice.refresh().catch(()=>{}),L.spatialNav.install(),L.keybindings.install(window),window.addEventListener("popstate",(D)=>X.navigation.onPopState(D)),AW(Y),J&&"serviceWorker"in navigator)window.addEventListener("load",()=>navigator.serviceWorker.register("/sw.js").catch(()=>{}));if(QW(Y),Y.dispatch(new RE),K)e4({platform:L,engine:Y,app:X});return{platform:L,engine:Y,app:X}}function e4({platform:A,engine:Q,app:B}){window.__trove={platform:A,engine:Q,app:B,test:{parsePackage:tQ,assessTrust:(C)=>A.plugins.assessTrust(C),install:(C,E)=>A.plugins.install(C,E),NavigateAction:hA,open:(C,E)=>A.dispatch(new GQ(C,E)),contextMenu:(C,E)=>A.dispatch(new $Q(C,E)),attachMedia:SB}}}function B1(A,Q,B){for(let C of B){if(!C?.id)throw Error(`A ${Q} passed to createWorkbench needs an "id"`);let{id:E,...J}=C;A.contributions.register(E,{type:Q,...J})}}function AW(A){let Q=0;window.addEventListener("keydown",(B)=>{if(B.key==="Shift"&&!B.repeat){let C=Date.now();if(C-Q<400)A.dispatch(new wE),Q=0;else Q=C}else if(B.key!=="Shift")Q=0})}function QW(A){let Q=0;window.addEventListener("dragenter",(B)=>{if(!B.dataTransfer?.types.includes("Files"))return;Q++,document.body.classList.add("dragging-file")}),window.addEventListener("dragover",(B)=>{if(B.dataTransfer?.types.includes("Files"))B.preventDefault()}),window.addEventListener("dragleave",()=>{if(--Q<=0)Q=0,document.body.classList.remove("dragging-file")}),window.addEventListener("drop",(B)=>{if(!B.dataTransfer?.files?.length)return;B.preventDefault(),Q=0,document.body.classList.remove("dragging-file"),A.dispatch(new eB(B.dataTransfer.files))})}C1();
|
|
740
740
|
|
|
741
|
-
//# debugId=
|
|
742
|
-
//# sourceMappingURL=main-
|
|
741
|
+
//# debugId=09842CF07C72A8E664756E2164756E21
|
|
742
|
+
//# sourceMappingURL=main-axerf2vw.js.map
|