127 lines
5.1 KiB
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);
|