Files
html/api/opus5-plugin-store.php

127 lines
5.1 KiB
PHP

<?php
// OPUS5 — Plugin Store autodiscovery (doctrine 73)
// Scanne /opt/weval-plugins/, lit manifest.json, liste + expose intents
// Pattern: GET ?action=(discover|list|install|enable|disable|run)
header('Content-Type: application/json');
$R = ['ts'=>date('c'), 'source'=>'opus5-plugin-store'];
$PLUGIN_DIR = '/opt/weval-plugins';
$REGISTRY = '/var/www/html/api/wevia-plugin-registry.json';
if (!file_exists($PLUGIN_DIR)) {
@mkdir($PLUGIN_DIR, 0755, true);
}
$action = $_GET['action'] ?? 'list';
function scan_plugins($dir) {
$plugins = [];
if (!is_dir($dir)) return $plugins;
foreach (scandir($dir) as $name) {
if ($name === '.' || $name === '..') continue;
$path = "$dir/$name";
if (!is_dir($path)) continue;
$manifest_file = "$path/manifest.json";
$readme_file = "$path/README.md";
$plugin = [
'id' => $name,
'path' => $path,
'has_manifest' => file_exists($manifest_file),
'has_readme' => file_exists($readme_file),
];
if ($plugin['has_manifest']) {
$manifest = @json_decode(file_get_contents($manifest_file), true) ?: [];
$plugin['name'] = $manifest['name'] ?? $name;
$plugin['version'] = $manifest['version'] ?? '0.1.0';
$plugin['description'] = $manifest['description'] ?? '';
$plugin['author'] = $manifest['author'] ?? 'unknown';
$plugin['intents'] = $manifest['intents'] ?? [];
$plugin['entrypoint'] = $manifest['entrypoint'] ?? 'run.sh';
$plugin['enabled'] = !empty($manifest['enabled']);
} else {
// Auto-detect basic info
$plugin['name'] = $name;
$plugin['version'] = '0.0.1';
$plugin['description'] = '[no manifest]';
$plugin['enabled'] = false;
// Try to detect entrypoint
foreach (['run.sh', 'index.php', 'main.py', 'plugin.sh'] as $ep) {
if (file_exists("$path/$ep")) {
$plugin['entrypoint'] = $ep;
break;
}
}
}
$plugins[] = $plugin;
}
return $plugins;
}
switch ($action) {
case 'discover':
case 'list':
$plugins = scan_plugins($PLUGIN_DIR);
$R['count'] = count($plugins);
$R['plugins'] = $plugins;
// Write registry
@file_put_contents($REGISTRY, json_encode([
'ts' => date('c'),
'count' => count($plugins),
'plugins' => $plugins
], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
$R['registry_written'] = $REGISTRY;
break;
case 'enable':
$pid = preg_replace('/[^a-z0-9_-]/i', '', $_GET['id'] ?? '');
if (!$pid) { http_response_code(400); echo json_encode(['err'=>'no_id']); exit; }
$mf = "$PLUGIN_DIR/$pid/manifest.json";
if (!file_exists($mf)) { http_response_code(404); echo json_encode(['err'=>'manifest_not_found']); exit; }
$m = json_decode(file_get_contents($mf), true);
$m['enabled'] = true;
@file_put_contents($mf, json_encode($m, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
$R['enabled'] = $pid;
break;
case 'disable':
$pid = preg_replace('/[^a-z0-9_-]/i', '', $_GET['id'] ?? '');
if (!$pid) { http_response_code(400); echo json_encode(['err'=>'no_id']); exit; }
$mf = "$PLUGIN_DIR/$pid/manifest.json";
if (!file_exists($mf)) { http_response_code(404); echo json_encode(['err'=>'manifest_not_found']); exit; }
$m = json_decode(file_get_contents($mf), true);
$m['enabled'] = false;
@file_put_contents($mf, json_encode($m, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
$R['disabled'] = $pid;
break;
case 'run':
$pid = preg_replace('/[^a-z0-9_-]/i', '', $_GET['id'] ?? '');
if (!$pid) { http_response_code(400); echo json_encode(['err'=>'no_id']); exit; }
$path = "$PLUGIN_DIR/$pid";
$mf = "$path/manifest.json";
if (!file_exists($mf)) { http_response_code(404); echo json_encode(['err'=>'manifest_not_found']); exit; }
$m = json_decode(file_get_contents($mf), true);
if (empty($m['enabled'])) { http_response_code(403); echo json_encode(['err'=>'plugin_disabled']); exit; }
$ep = $m['entrypoint'] ?? 'run.sh';
$full_ep = "$path/$ep";
if (!file_exists($full_ep)) { http_response_code(404); echo json_encode(['err'=>'entrypoint_not_found', 'ep'=>$full_ep]); exit; }
// Safe exec with timeout 10s
$out = @shell_exec("timeout 10 bash " . escapeshellarg($full_ep) . " 2>&1");
$R['plugin'] = $pid;
$R['exec_output'] = substr((string)$out, 0, 3000);
$R['truncated'] = strlen((string)$out) > 3000;
break;
default:
$R['err'] = 'unknown_action';
$R['available'] = ['discover', 'list', 'enable', 'disable', 'run'];
}
$R['doctrine'] = '73 — plugin store autodiscovery (manifest.json scan + registry + enable/disable/run)';
echo json_encode($R, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);