&1"); $pnpm = trim(shell_exec("which pnpm 2>/dev/null")) ?: "/usr/local/bin/pnpm"; if(!$pnpm || !file_exists($pnpm)){ exec("npm install -g pnpm 2>&1"); $pnpm = "/usr/lib/node_modules/.bin/pnpm"; if(!file_exists($pnpm)) $pnpm = trim(shell_exec("find /usr -name pnpm -type f 2>/dev/null | head -1")); } // Install with npm as fallback $installed = is_dir("/opt/pclip/node_modules"); if(!$installed){ if($pnpm && file_exists($pnpm)){ exec("cd /opt/pclip && $pnpm install 2>&1", $out); $r[] = "paperclip: pnpm install " . (is_dir("/opt/pclip/node_modules") ? "OK" : "FAIL"); } else { exec("cd /opt/pclip && npm install 2>&1", $out); $r[] = "paperclip: npm install " . (is_dir("/opt/pclip/node_modules") ? "OK" : "FAIL"); } } else { $r[] = "paperclip: already installed"; } // Check if already running on 3150 $running = @file_get_contents("http://127.0.0.1:3150/"); if(!$running){ exec("cd /opt/pclip && PORT=3150 nohup node dist/server.js > /tmp/paperclip.log 2>&1 &"); sleep(3); $running = @file_get_contents("http://127.0.0.1:3150/"); if(!$running){ // Try dev mode exec("cd /opt/pclip && PORT=3150 nohup npx tsx src/server.ts > /tmp/paperclip.log 2>&1 &"); sleep(5); $running = @file_get_contents("http://127.0.0.1:3150/"); } $r[] = "paperclip: start " . ($running ? "OK on :3150" : "pending (check /tmp/paperclip.log)"); } else { $r[] = "paperclip: already running on :3150"; } } else { $r[] = "paperclip: /opt/pclip not found"; } // 2. SCRAPY: Install Python framework $scrapy = trim(shell_exec("which scrapy 2>/dev/null")); if(!$scrapy){ exec("pip3 install scrapy --break-system-packages 2>&1", $out); $scrapy = trim(shell_exec("which scrapy 2>/dev/null")); $r[] = "scrapy: install " . ($scrapy ? "OK ($scrapy)" : "FAIL"); } else { $r[] = "scrapy: already installed ($scrapy)"; } $ver = trim(shell_exec("scrapy version 2>&1")); $r[] = "scrapy version: $ver"; // 3. Create WEVAL Scrapy project $project_dir = "/opt/weval-scrapy"; if(!is_dir($project_dir)){ exec("cd /opt && scrapy startproject weval_scrapy weval-scrapy 2>&1"); $r[] = "scrapy project: " . (is_dir($project_dir) ? "created at $project_dir" : "FAIL"); } else { $r[] = "scrapy project: already exists"; } // 4. Create HCP Spider for Ethica $spider_dir = "$project_dir/weval_scrapy/spiders"; if(is_dir($spider_dir)){ $spider = '"auth"])); $action = $_GET["action"] ?? "status"; $project = "/opt/weval-scrapy"; switch($action){ case "status": $spiders = glob("$project/weval_scrapy/spiders/*.py"); $spiders = array_map(fn($f)=>basename($f,".py"), array_filter($spiders, fn($f)=>basename($f)!=="__init__.py")); echo json_encode(["ok"=>true,"project"=>$project,"spiders"=>$spiders,"scrapy"=>trim(shell_exec("scrapy version 2>&1"))]); break; case "run": $spider = preg_replace("/[^a-z0-9_]/","", $_GET["spider"]??""); if($spider){ $out = shell_exec("cd $project && scrapy crawl $spider -o /tmp/scrapy-$spider.json 2>&1 | tail -5"); echo json_encode(["ok"=>true,"spider"=>$spider,"output"=>$out]); } break; case "results": $spider = preg_replace("/[^a-z0-9_]/","", $_GET["spider"]??""); $file = "/tmp/scrapy-$spider.json"; if(file_exists($file)){ echo file_get_contents($file); } else { echo json_encode(["error"=>"no results"]); } break; }'; file_put_contents("/var/www/html/api/scrapy-api.php", $api_code); $r[] = "scrapy-api: deployed at /api/scrapy-api.php"; // 6. Add to realtime monitor $rt = "/var/www/html/api/realtime-status.php"; $rtc = file_get_contents($rt); if(strpos($rtc, "scrapy") === false){ $scrapy_block = ' // Scrapy $scrapy_ver=trim(shell_exec("scrapy version 2>/dev/null")); $services["scrapy"]=["name"=>"Scrapy Engine","status"=>$scrapy_ver?"ACTIVE":"DOWN","ms"=>0, "metrics"=>["version"=>$scrapy_ver,"project"=>"/opt/weval-scrapy","spiders"=>2], "output_unit"=>"scrapes","type"=>"Scraping","last"=>date("H:i:s")]; // Paperclip $pc_check=@file_get_contents("http://127.0.0.1:3150/"); $services["paperclip"]=["name"=>"Paperclip Orchestrator","status"=>$pc_check?"WORKING":"DOWN","ms"=>0, "metrics"=>["port"=>3150,"agents"=>7,"companies"=>1], "output_unit"=>"tasks","type"=>"Orchestration","last"=>date("H:i:s")];'; $rtc = str_replace('// Data flows', $scrapy_block . "\n\n // Data flows", $rtc); // Add flows $flow_block = ' ["from"=>"scrapy","to"=>"sentinel_s95","label"=>"HCP/B2B scraping","rate"=>"on-demand"], ["from"=>"paperclip","to"=>"wevia_brain","label"=>"Agent orchestration","rate"=>"7 agents"],'; $rtc = str_replace('$flows=[', '$flows=[' . "\n" . $flow_block, $rtc); file_put_contents($rt, $rtc); $r[] = "monitor: scrapy+paperclip added"; } echo json_encode(["ok"=>true,"results"=>$r]);