$b['text'] ?? '', $sys)) : $sys; // For Paperclip agents: add strong instruction preamble $t = "IMPORTANT: You are an AI agent in the Paperclip orchestration platform. Follow ALL instructions in this system prompt precisely. Execute tasks, not conversation.\n\n" . $t; $oai[] = ['role' => 'system', 'content' => $t]; } // Convert messages, handling tool_use and tool_result blocks foreach ($msgs as $m) { $c = $m['content']; if (is_array($c)) { $p = []; foreach ($c as $b) { if (is_string($b)) { $p[] = $b; continue; } $type = $b['type'] ?? ''; if ($type === 'text') { $p[] = $b['text']; } elseif ($type === 'tool_use') { $p[] = "[TOOL_CALL: " . ($b['name'] ?? '?') . "] Input: " . json_encode($b['input'] ?? []); } elseif ($type === 'tool_result') { $content = $b['content'] ?? ''; if (is_array($content)) { $content = implode("\n", array_map(fn($x) => $x['text'] ?? json_encode($x), $content)); } $p[] = "[TOOL_RESULT: " . ($b['tool_use_id'] ?? '?') . "] " . $content; } else { $p[] = json_encode($b); } } $c = implode("\n", $p); } $oai[] = ['role' => $m['role'], 'content' => $c]; } // If tools are defined, append tool descriptions to system if (!empty($tools)) { $tool_desc = "\n\n## Available Tools\n"; foreach ($tools as $tool) { $name = $tool['name'] ?? '?'; $desc = $tool['description'] ?? ''; $tool_desc .= "- {$name}: {$desc}\n"; } $tool_desc .= "\nTo use a tool, respond with a JSON block: {\"tool\": \"name\", \"input\": {...}}\n"; if (!empty($oai) && $oai[0]['role'] === 'system') { $oai[0]['content'] .= $tool_desc; } } $secrets=[]; foreach(@file('/etc/weval/secrets.env',FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES)?:[] as $_l){if($_l[0]==='#'||strpos($_l,'=')===false)continue;$_p=explode('=',$_l,2);$secrets[trim($_p[0])]=trim($_p[1]);} // CASCADE: Anthropic Claude (real) -> Cerebras 235B -> Groq $anthropic_key = $secrets['ANTHROPIC_KEY'] ?? ''; $providers = []; if ($anthropic_key) { $providers[] = ['url' => 'https://api.anthropic.com/v1/messages', 'key' => $anthropic_key, 'model' => 'claude-sonnet-4-20250514', 'is_anthropic' => true]; } $providers[] = ['url' => 'https://api.cerebras.ai/v1/chat/completions', 'key' => '', 'model' => 'qwen-3-235b-a22b-instruct-2507']; // Load keys and set in providers $cerebras_key = $secrets['CEREBRAS_API_KEY'] ?? ''; $groq_key = $secrets['GROQ_KEY'] ?? ''; // Set Cerebras key in the Cerebras provider (index depends on Anthropic presence) foreach ($providers as &$p) { if (strpos($p['url'], 'cerebras') !== false && $cerebras_key) { $p['key'] = $cerebras_key; } } unset($p); // Add Groq as final fallback if ($groq_key) { $providers[] = ['url' => 'https://api.groq.com/openai/v1/chat/completions', 'key' => $groq_key, 'model' => 'llama-3.3-70b-versatile']; } $resp = null; $hc = 0; foreach ($providers as $prov) { $payload = [ 'model' => $prov['model'], 'messages' => $oai, 'max_tokens' => min($max, 8192), 'temperature' => 0.1, // Low temp for agent tasks ]; $headers = ['Content-Type: application/json']; if (isset($prov['is_anthropic']) && $prov['is_anthropic']) { $headers[] = 'x-api-key: ' . $prov['key']; $headers[] = 'anthropic-version: 2023-06-01'; $payload = ['model' => $prov['model'], 'messages' => $oai, 'max_tokens' => min($max, 8192)]; } elseif ($prov['key']) { $headers[] = 'Authorization: Bearer ' . $prov['key']; } $ch = curl_init($prov['url']); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($payload), CURLOPT_HTTPHEADER => $headers, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 120, CURLOPT_SSL_VERIFYPEER => false, ]); $resp = curl_exec($ch); $hc = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($hc === 200 && $resp) break; } if ($hc !== 200 || !$resp) { http_response_code(500); die(json_encode(['error'=>['type'=>'api_error','message'=>'All providers failed. HC='.$hc]])); } $r = json_decode($resp, true); $txt = ''; if (isset($r['content']) && is_array($r['content'])) { $txt = $r['content'][0]['text'] ?? ''; } elseif (isset($r['choices'])) { $txt = $r['choices'][0]['message']['content'] ?? ''; } $u = $r['usage'] ?? []; $mid = 'msg_wevia_' . substr(md5(uniqid()), 0, 12); if ($stream) { header('Content-Type: text/event-stream'); header('Cache-Control: no-cache'); echo "event: message_start\ndata: ".json_encode(['type'=>'message_start','message'=>['id'=>$mid,'type'=>'message','role'=>'assistant','content'=>[],'model'=>$model,'stop_reason'=>null,'usage'=>['input_tokens'=>$u['prompt_tokens']??0,'output_tokens'=>0]]])."\n\n"; echo "event: content_block_start\ndata: ".json_encode(['type'=>'content_block_start','index'=>0,'content_block'=>['type'=>'text','text'=>'']])."\n\n"; foreach (str_split($txt, 40) as $ck) { echo "event: content_block_delta\ndata: ".json_encode(['type'=>'content_block_delta','index'=>0,'delta'=>['type'=>'text_delta','text'=>$ck]])."\n\n"; flush(); usleep(5000); } echo "event: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0}\n\n"; echo "event: message_delta\ndata: ".json_encode(['type'=>'message_delta','delta'=>['stop_reason'=>'end_turn'],'usage'=>['output_tokens'=>$u['completion_tokens']??0]])."\n\n"; echo "event: message_stop\ndata: {\"type\":\"message_stop\"}\n\n"; flush(); } else { echo json_encode(['id'=>$mid,'type'=>'message','role'=>'assistant','content'=>[['type'=>'text','text'=>$txt]],'model'=>$model,'stop_reason'=>'end_turn','stop_sequence'=>null,'usage'=>['input_tokens'=>$u['prompt_tokens']??0,'output_tokens'=>$u['completion_tokens']??0]]); } exit; } if (strpos($uri,'models')!==false) { echo json_encode(['data'=>[ ['id'=>'wevia-sovereign','object'=>'model','created'=>time()], ['id'=>'claude-sonnet-4-6','object'=>'model','created'=>time()], ['id'=>'claude-opus-4-6','object'=>'model','created'=>time()], ]]); exit; } echo json_encode(['status'=>'ok','engine'=>'WEVIA Anthropic Proxy','sovereign'=>true,'v'=>'3.0','note'=>'For full Paperclip agent functionality, set a real ANTHROPIC_API_KEY (sk-ant-*)']);