async function renderPlugins() { const content = document.getElementById('pageContent'); content.innerHTML = `
Install a Plugin
Paste a GitHub URL to clone a skill from a repo
Connect External App
Connected Apps
`; try { const [pluginsData, integrationsData] = await Promise.all([ api.getPlugins(), api.getIntegrations(), ]); renderPluginTable(pluginsData.plugins || []); renderIntegrations(integrationsData.integrations || []); } catch (err) { document.getElementById('pluginList').innerHTML = `
${escapeHtml(err.message)}
`; } } function renderPluginTable(plugins) { const container = document.getElementById('pluginList'); if (plugins.length === 0) { container.innerHTML = '
🔌
No plugins installed
Install plugins from GitHub or create your own
'; return; } container.innerHTML = `
Installed Plugins (${plugins.length})
${plugins.map(p => ` `).join('')}
PluginVersionTypeSourceInstalled
${escapeHtml(p.name)} ${p.version || '1.0.0'} ${p.type || 'skill'} ${escapeHtml(p.source || 'built-in')} ${formatDate(p.installed)} ${p.source ? `` : '—'}
`; } function renderIntegrations(integrations) { const container = document.getElementById('integrationsList'); if (integrations.length === 0) { container.innerHTML = '
No external apps connected yet
'; return; } container.innerHTML = `
${integrations.map(i => `
${escapeHtml(i.name)} ${escapeHtml(i.type)}
${escapeHtml(i.url)}
● connected
`).join('')}
`; } function showInstallPlugin() { document.getElementById('pluginRepoInput').focus(); } async function installPluginFromRepo() { const repoUrl = document.getElementById('pluginRepoInput').value.trim(); const name = document.getElementById('pluginNameInput').value.trim(); const statusEl = document.getElementById('installStatus'); if (!repoUrl) { statusEl.innerHTML = 'Please enter a GitHub repo URL'; return; } statusEl.innerHTML = 'Installing...'; try { const r = await api.installPlugin(name || repoUrl, repoUrl); statusEl.innerHTML = `✓ ${escapeHtml(r.plugin)} installed`; document.getElementById('pluginRepoInput').value = ''; document.getElementById('pluginNameInput').value = ''; setTimeout(() => renderPlugins(), 2000); } catch (err) { statusEl.innerHTML = `Error: ${escapeHtml(err.message)}`; } } async function uninstallPlugin(name) { if (!confirm(`Remove "${name}"?`)) return; try { await api.uninstallPlugin(name); showToast(`${name} removed`, 'success'); renderPlugins(); } catch (err) { showToast(`Error: ${err.message}`, 'error'); } } async function addIntegration() { const name = document.getElementById('integrationNameInput').value.trim(); const url = document.getElementById('integrationUrlInput').value.trim(); const type = document.getElementById('integrationType').value; const statusEl = document.getElementById('integrationStatus'); if (!name || !url) { statusEl.innerHTML = 'Name and URL required'; return; } statusEl.innerHTML = 'Connecting...'; try { const r = await api.addIntegration(name, url, type); statusEl.innerHTML = `✓ ${escapeHtml(r.name)} connected`; document.getElementById('integrationNameInput').value = ''; document.getElementById('integrationUrlInput').value = ''; setTimeout(() => renderPlugins(), 2000); } catch (err) { statusEl.innerHTML = `Error: ${escapeHtml(err.message)}`; } }