From 17077310293c1751f2aa84b0a893b1bd0a896767 Mon Sep 17 00:00:00 2001 From: ReaperOfVeriod Date: Sun, 25 Oct 2026 06:00:51 +0100 Subject: [PATCH] Add plugin rollback control --- src/App.svelte | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/App.svelte b/src/App.svelte index 74fa494..35b9853 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1009,6 +1009,21 @@ } } + async function rollbackPlugin(plugin: (typeof plugins)[number]) { + if (!window.confirm(`Roll back ${plugin.name} to its previous package?`)) return; + pluginBusy = true; + pluginError = ''; + try { + const response = await fetch(`${serverAddress}/api/v1/admin/plugins/${encodeURIComponent(plugin.plugin_id)}/rollback`, { method: 'POST', headers: { authorization: `Bearer ${sessionToken}` } }); + if (!response.ok) throw new Error('Plugin rollback is unavailable for this installation.'); + await loadPlugins(); + } catch (error) { + pluginError = error instanceof Error ? error.message : 'Plugin rollback failed.'; + } finally { + pluginBusy = false; + } + } + async function loadOverlays() { try { const response = await fetch(`${serverAddress}/api/v1/overlays`, { headers: { authorization: `Bearer ${sessionToken}` } }); @@ -1312,7 +1327,7 @@ {:else if activeView === 'Plugins'} -
WEBASSEMBLY PLUGINS

Packages are validated and started in a resource-limited WebAssembly runtime. Only explicitly declared Trixie permissions are accepted; installation never grants filesystem or process access.

{#if pluginError}
{pluginError}
{/if}{#if plugins.length}
{#each plugins as plugin}
{plugin.name}{plugin.plugin_id} · v{plugin.version}
API {plugin.manifest.api_version} · {plugin.manifest.permissions.length ? plugin.manifest.permissions.join(' · ') : 'NO PERMISSIONS'}
{plugin.enabled ? 'ENABLED' : 'DISABLED'}
{/each}
{:else}
No plugins are installed.
{/if}
+
WEBASSEMBLY PLUGINS

Packages are validated and started in a resource-limited WebAssembly runtime. Only explicitly declared Trixie permissions are accepted; installation never grants filesystem or process access.

{#if pluginError}
{pluginError}
{/if}{#if plugins.length}
{#each plugins as plugin}
{plugin.name}{plugin.plugin_id} · v{plugin.version}
API {plugin.manifest.api_version} · {plugin.manifest.permissions.length ? plugin.manifest.permissions.join(' · ') : 'NO PERMISSIONS'}
{plugin.enabled ? 'ENABLED' : 'DISABLED'}
{/each}
{:else}
No plugins are installed.
{/if}
{:else if activeView === 'Bot'}
{commandFormId ? 'EDIT COMMAND' : 'NEW COMMAND'}
{#if commandVariableSuggestions.length}
{#each commandVariableSuggestions as variable}{/each}
{/if}
BOT COMMANDS
PUBLIC COMMAND CATALOG
{#if botCommandError}
{botCommandError}
{:else if botCommands.length}
{#each botCommands as command}
!{command.name}{command.description}{#if command.tags.length}
{command.tags.join(' · ')}
{/if}
{command.permission_level.toUpperCase()}{#if command.cooldown_seconds}{command.cooldown_seconds}s / {command.cooldown_scope}{/if}
{/each}
{:else}
No enabled commandsCreate commands on the server to make them available here.
{/if}
SECRETS MANAGEMENT
Values are encrypted and cannot be read after saving.
{#if botSecrets.length}
{#each botSecrets as secret}
{secret.name}{secret.description || 'No description'}{#if secret.used_by.length}
USED BY: {secret.used_by.join(', ')}
{/if}
{/each}
{:else}
There are no secrets yet.
{/if}{#if secretError}
{secretError}
{/if}