async function renderPlugins() {
const content = document.getElementById('pageContent');
content.innerHTML = `
Install a Plugin
`;
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})
| Plugin | Version | Type | Source | Installed | |
${plugins.map(p => `
| ${escapeHtml(p.name)} |
${p.version || '1.0.0'} |
${p.type || 'skill'} |
${escapeHtml(p.source || 'built-in')} |
${formatDate(p.installed)} |
${p.source ? `` : '—'} |
`).join('')}
`;
}
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)}`;
}
}