Files

1 line
48 KiB
JSON

{"repo": "aipilotbyjd/agent1o1-api", "files": {"app/Engine/Nodes/Apps/Ai/LlmNode.php": {"a9537fc1a54e5998f5b5691825013f951c585b4e": {"t": 1785746167.774255, "n": 11965, "h": "70b82afab9a03293", "c": "<?php\n\nnamespace App\\Engine\\Nodes\\Apps\\Ai;\n\nuse App\\Engine\\NodeInput;\nuse App\\Engine\\NodeResult;\nuse App\\Engine\\Nodes\\Apps\\AppNode;\n\nclass LlmNode extends AppNode\n{\n protected function execute(string $operation, NodeInput $input): NodeResult\n {\n return match ($operation) {\n 'generate', 'complete', 'chat' => $this->generate($input),\n 'classify' => $this->classify($input),\n 'summarize' => $this->summarize($input),\n 'sentiment' => $this->sentiment($input),\n 'extract' => $this->extract($input),\n default => $this->fail(\"Llm: unknown operation '{$operation}'\"),\n };\n }\n\n private function generate(NodeInput $input, ?string $systemOverride = null): NodeResult\n {\n $provider = $input->config['provider'] ?? ($input->credentials['provider'] ?? 'anthropic');\n\n return match ($provider) {\n 'anthropic' => $this->anthropic($input, $systemOverride),\n 'openai' => $this->openai($input, $systemOverride),\n 'gemini' => $this->gemini($input, $systemOverride),\n 'azure' => $this->azure($input, $systemOverride),\n 'cohere' => $this->cohere($input, $systemOverride),\n 'ollama' => $this->ollama($input, $systemOverride),\n 'groq' => $this->openaiCompatible($input, $systemOverride, 'Groq', 'https://api.groq.com/openai/v1', 'llama-3.3-70b-versatile', 'GROQ_API_KEY'),\n 'mistral' => $this->openaiCompatible($input, $systemOverride, 'Mistral', 'https://api.mistral.ai/v1', 'mistral-small-latest', 'MISTRAL_API_KEY'),\n 'deepseek' => $this->openaiCompatible($input, $systemOverride, 'DeepSeek', 'https://api.deepseek.com/v1', 'deepseek-chat', 'DEEPSEEK_API_KEY'),\n 'xai' => $this->openaiCompatible($input, $systemOverride, 'xAI', 'https://api.x.ai/v1', 'grok-3-mini', 'XAI_API_KEY'),\n 'openrouter' => $this->openaiCompatible($input, $systemOverride, 'OpenRouter', 'https://openrouter.ai/api/v1', 'openai/gpt-4o-mini', 'OPENROUTER_API_KEY'),\n 'anyapi' => $this->openaiCompatible($input, $systemOverride, 'AnyAPI', env('ANYAPI_URL', 'https://api.anyapi.ai/v1'), env('ANYAPI_MODEL', 'gpt-4o-mini'), 'ANYAPI_API_KEY'),\n default => $this->fail(\"Llm: unknown provider '{$provider}'\"),\n };\n }\n\n private function classify(NodeInput $input): NodeResult\n {\n $categories = implode(', ', (array) ($input->config['categories'] ?? []));\n\n return $this->generate($input, \"Classify the user's text into exactly one of these categories: {$categories}. Respond with only the category name.\");\n }\n\n private function summarize(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Summarize the following text concisely.');\n }\n\n private function sentiment(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Analyze the sentiment of the text. Respond with only: positive, negative, or neutral.');\n }\n\n private function extract(NodeInput $input): NodeResult\n {\n $fields = json_encode($input->config['fields'] ?? []);\n\n return $this->generate($input, \"Extract the following fields from the text and respond with only valid JSON: {$fields}\");\n }\n\n private function anthropic(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('ANTHROPIC_API_KEY', '');\n $system = $systemOverride ?? ($input->config['system_prompt'] ?? null);\n\n $response = $this->http()\n ->baseUrl('https://api.anthropic.com/v1')\n ->withHeaders(['x-api-key' => $apiKey, 'anthropic-version' => '2023-06-01'])\n ->post('/messages', array_filter([\n 'model' => $input->config['model'] ?? 'claude-sonnet-5',\n 'max_tokens' => (int) ($input->config['max_tokens'] ?? 4096),\n 'system' => $system,\n 'messages' => [['role' => 'user', 'content' => $input->config['prompt'] ?? '']],\n ]));\n\n if (! $response->successful()) {\n return $this->fail(\"Anthropic API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function openai(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('OPENAI_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.openai.com/v1')\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'gpt-4o-mini',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function gemini(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('GEMINI_API_KEY', '');\n $model = $input->config['model'] ?? 'gemini-2.0-flash';\n $baseUrl = rtrim(env('GEMINI_URL', 'https://generativelanguage.googleapis.com/v1beta'), '/');\n\n $body = [\n 'contents' => [\n ['role' => 'user', 'parts' => [['text' => $input->config['prompt'] ?? '']]],\n ],\n ];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $body['systemInstruction'] = ['parts' => [['text' => $system]]];\n }\n\n if ($maxTokens = $input->config['max_tokens'] ?? null) {\n $body['generationConfig'] = ['maxOutputTokens' => (int) $maxTokens];\n }\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post(\"/models/{$model}:generateContent?key={$apiKey}\", $body);\n\n if (! $response->successful()) {\n return $this->fail(\"Gemini API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['candidates'][0]['content']['parts'][0]['text'] ?? '',\n 'usage' => [\n 'input_tokens' => $data['usageMetadata']['promptTokenCount'] ?? 0,\n 'output_tokens' => $data['usageMetadata']['candidatesTokenCount'] ?? 0,\n ],\n 'model' => $model,\n ]);\n }\n\n private function azure(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('AZURE_OPENAI_API_KEY', '');\n $endpoint = rtrim($input->credentials['endpoint'] ?? env('AZURE_OPENAI_URL', ''), '/');\n $deployment = $input->credentials['deployment'] ?? env('AZURE_OPENAI_DEPLOYMENT', 'gpt-4o');\n $apiVersion = $input->credentials['api_version'] ?? env('AZURE_OPENAI_API_VERSION', '2025-04-01-preview');\n\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $url = \"{$endpoint}/openai/deployments/{$deployment}/chat/completions?api-version={$apiVersion}\";\n\n $response = $this->http()\n ->withHeaders(['api-key' => $apiKey])\n ->post($url, ['messages' => $messages]);\n\n if (! $response->successful()) {\n return $this->fail(\"Azure OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $deployment,\n ]);\n }\n\n private function cohere(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('COHERE_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.cohere.com/v2')\n ->post('/chat', [\n 'model' => $input->config['model'] ?? 'command-r-plus',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Cohere API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['message']['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['id'] ?? '',\n ]);\n }\n\n private function ollama(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $baseUrl = rtrim($input->credentials['url'] ?? env('OLLAMA_URL', 'http://localhost:11434'), '/').'/v1';\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'llama3.2',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Ollama API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n /**\n * Shared handler for OpenAI-compatible providers (Groq, Mistral, DeepSeek, xAI, OpenRouter).\n */\n private function openaiCompatible(\n NodeInput $input,\n ?string $systemOverride,\n string $providerName,\n string $baseUrl,\n string $defaultModel,\n string $envKey,\n ): NodeResult {\n $apiKey = $input->credentials['api_key'] ?? env($envKey, '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? $defaultModel,\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"{$providerName} API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n}\n"}, "74fdab86c196bf2dc1f885851639ea73b5129fe1": {"t": 1785760299.2996774, "n": 11965, "h": "70b82afab9a03293", "c": "<?php\n\nnamespace App\\Engine\\Nodes\\Apps\\Ai;\n\nuse App\\Engine\\NodeInput;\nuse App\\Engine\\NodeResult;\nuse App\\Engine\\Nodes\\Apps\\AppNode;\n\nclass LlmNode extends AppNode\n{\n protected function execute(string $operation, NodeInput $input): NodeResult\n {\n return match ($operation) {\n 'generate', 'complete', 'chat' => $this->generate($input),\n 'classify' => $this->classify($input),\n 'summarize' => $this->summarize($input),\n 'sentiment' => $this->sentiment($input),\n 'extract' => $this->extract($input),\n default => $this->fail(\"Llm: unknown operation '{$operation}'\"),\n };\n }\n\n private function generate(NodeInput $input, ?string $systemOverride = null): NodeResult\n {\n $provider = $input->config['provider'] ?? ($input->credentials['provider'] ?? 'anthropic');\n\n return match ($provider) {\n 'anthropic' => $this->anthropic($input, $systemOverride),\n 'openai' => $this->openai($input, $systemOverride),\n 'gemini' => $this->gemini($input, $systemOverride),\n 'azure' => $this->azure($input, $systemOverride),\n 'cohere' => $this->cohere($input, $systemOverride),\n 'ollama' => $this->ollama($input, $systemOverride),\n 'groq' => $this->openaiCompatible($input, $systemOverride, 'Groq', 'https://api.groq.com/openai/v1', 'llama-3.3-70b-versatile', 'GROQ_API_KEY'),\n 'mistral' => $this->openaiCompatible($input, $systemOverride, 'Mistral', 'https://api.mistral.ai/v1', 'mistral-small-latest', 'MISTRAL_API_KEY'),\n 'deepseek' => $this->openaiCompatible($input, $systemOverride, 'DeepSeek', 'https://api.deepseek.com/v1', 'deepseek-chat', 'DEEPSEEK_API_KEY'),\n 'xai' => $this->openaiCompatible($input, $systemOverride, 'xAI', 'https://api.x.ai/v1', 'grok-3-mini', 'XAI_API_KEY'),\n 'openrouter' => $this->openaiCompatible($input, $systemOverride, 'OpenRouter', 'https://openrouter.ai/api/v1', 'openai/gpt-4o-mini', 'OPENROUTER_API_KEY'),\n 'anyapi' => $this->openaiCompatible($input, $systemOverride, 'AnyAPI', env('ANYAPI_URL', 'https://api.anyapi.ai/v1'), env('ANYAPI_MODEL', 'gpt-4o-mini'), 'ANYAPI_API_KEY'),\n default => $this->fail(\"Llm: unknown provider '{$provider}'\"),\n };\n }\n\n private function classify(NodeInput $input): NodeResult\n {\n $categories = implode(', ', (array) ($input->config['categories'] ?? []));\n\n return $this->generate($input, \"Classify the user's text into exactly one of these categories: {$categories}. Respond with only the category name.\");\n }\n\n private function summarize(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Summarize the following text concisely.');\n }\n\n private function sentiment(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Analyze the sentiment of the text. Respond with only: positive, negative, or neutral.');\n }\n\n private function extract(NodeInput $input): NodeResult\n {\n $fields = json_encode($input->config['fields'] ?? []);\n\n return $this->generate($input, \"Extract the following fields from the text and respond with only valid JSON: {$fields}\");\n }\n\n private function anthropic(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('ANTHROPIC_API_KEY', '');\n $system = $systemOverride ?? ($input->config['system_prompt'] ?? null);\n\n $response = $this->http()\n ->baseUrl('https://api.anthropic.com/v1')\n ->withHeaders(['x-api-key' => $apiKey, 'anthropic-version' => '2023-06-01'])\n ->post('/messages', array_filter([\n 'model' => $input->config['model'] ?? 'claude-sonnet-5',\n 'max_tokens' => (int) ($input->config['max_tokens'] ?? 4096),\n 'system' => $system,\n 'messages' => [['role' => 'user', 'content' => $input->config['prompt'] ?? '']],\n ]));\n\n if (! $response->successful()) {\n return $this->fail(\"Anthropic API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function openai(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('OPENAI_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.openai.com/v1')\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'gpt-4o-mini',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function gemini(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('GEMINI_API_KEY', '');\n $model = $input->config['model'] ?? 'gemini-2.0-flash';\n $baseUrl = rtrim(env('GEMINI_URL', 'https://generativelanguage.googleapis.com/v1beta'), '/');\n\n $body = [\n 'contents' => [\n ['role' => 'user', 'parts' => [['text' => $input->config['prompt'] ?? '']]],\n ],\n ];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $body['systemInstruction'] = ['parts' => [['text' => $system]]];\n }\n\n if ($maxTokens = $input->config['max_tokens'] ?? null) {\n $body['generationConfig'] = ['maxOutputTokens' => (int) $maxTokens];\n }\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post(\"/models/{$model}:generateContent?key={$apiKey}\", $body);\n\n if (! $response->successful()) {\n return $this->fail(\"Gemini API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['candidates'][0]['content']['parts'][0]['text'] ?? '',\n 'usage' => [\n 'input_tokens' => $data['usageMetadata']['promptTokenCount'] ?? 0,\n 'output_tokens' => $data['usageMetadata']['candidatesTokenCount'] ?? 0,\n ],\n 'model' => $model,\n ]);\n }\n\n private function azure(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('AZURE_OPENAI_API_KEY', '');\n $endpoint = rtrim($input->credentials['endpoint'] ?? env('AZURE_OPENAI_URL', ''), '/');\n $deployment = $input->credentials['deployment'] ?? env('AZURE_OPENAI_DEPLOYMENT', 'gpt-4o');\n $apiVersion = $input->credentials['api_version'] ?? env('AZURE_OPENAI_API_VERSION', '2025-04-01-preview');\n\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $url = \"{$endpoint}/openai/deployments/{$deployment}/chat/completions?api-version={$apiVersion}\";\n\n $response = $this->http()\n ->withHeaders(['api-key' => $apiKey])\n ->post($url, ['messages' => $messages]);\n\n if (! $response->successful()) {\n return $this->fail(\"Azure OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $deployment,\n ]);\n }\n\n private function cohere(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('COHERE_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.cohere.com/v2')\n ->post('/chat', [\n 'model' => $input->config['model'] ?? 'command-r-plus',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Cohere API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['message']['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['id'] ?? '',\n ]);\n }\n\n private function ollama(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $baseUrl = rtrim($input->credentials['url'] ?? env('OLLAMA_URL', 'http://localhost:11434'), '/').'/v1';\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'llama3.2',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Ollama API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n /**\n * Shared handler for OpenAI-compatible providers (Groq, Mistral, DeepSeek, xAI, OpenRouter).\n */\n private function openaiCompatible(\n NodeInput $input,\n ?string $systemOverride,\n string $providerName,\n string $baseUrl,\n string $defaultModel,\n string $envKey,\n ): NodeResult {\n $apiKey = $input->credentials['api_key'] ?? env($envKey, '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? $defaultModel,\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"{$providerName} API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n}\n"}, "b703976b43986bda9672b727e6ad38562478aeab": {"t": 1785760301.1177897, "n": 11967, "h": "3be17b00e90b8089", "c": "<?php\n\nnamespace App\\Engine\\Nodes\\Apps\\Ai;\n\nuse App\\Engine\\NodeInput;\nuse App\\Engine\\NodeResult;\nuse App\\Engine\\Nodes\\Apps\\AppNode;\n\nclass LlmNode extends AppNode\n{\n protected function execute(string $operation, NodeInput $input): NodeResult\n {\n return match ($operation) {\n 'generate', 'complete', 'chat' => $this->generate($input),\n 'classify' => $this->classify($input),\n 'summarize' => $this->summarize($input),\n 'sentiment' => $this->sentiment($input),\n 'extract' => $this->extract($input),\n default => $this->fail(\"Llm: unknown operation '{$operation}'\"),\n };\n }\n\n private function generate(NodeInput $input, ?string $systemOverride = null): NodeResult\n {\n $provider = $input->config['provider'] ?? ($input->credentials['provider'] ?? 'anthropic');\n\n return match ($provider) {\n 'anthropic' => $this->anthropic($input, $systemOverride),\n 'openai' => $this->openai($input, $systemOverride),\n 'gemini' => $this->gemini($input, $systemOverride),\n 'azure' => $this->azure($input, $systemOverride),\n 'cohere' => $this->cohere($input, $systemOverride),\n 'ollama' => $this->ollama($input, $systemOverride),\n 'groq' => $this->openaiCompatible($input, $systemOverride, 'Groq', 'https://api.groq.com/openai/v1', 'llama-3.3-70b-versatile', 'GROQ_API_KEY'),\n 'mistral' => $this->openaiCompatible($input, $systemOverride, 'Mistral', 'https://api.mistral.ai/v1', 'mistral-small-latest', 'MISTRAL_API_KEY'),\n 'deepseek' => $this->openaiCompatible($input, $systemOverride, 'DeepSeek', 'https://api.deepseek.com/v1', 'deepseek-chat', 'DEEPSEEK_API_KEY'),\n 'xai' => $this->openaiCompatible($input, $systemOverride, 'xAI', 'https://api.x.ai/v1', 'grok-3-mini', 'XAI_API_KEY'),\n 'openrouter' => $this->openaiCompatible($input, $systemOverride, 'OpenRouter', 'https://openrouter.ai/api/v1', 'openai/gpt-4o-mini', 'OPENROUTER_API_KEY'),\n 'anyapi' => $this->openaiCompatible($input, $systemOverride, 'AnyAPI', env('ANYAPI_URL', 'https://api.anyapi.ai/v1'), env('ANYAPI_MODEL', 'gpt-4o-mini'), 'ANYAPI_API_KEY'),\n default => $this->fail(\"Llm: unknown provider '{$provider}'\"),\n };\n }\n\n private function classify(NodeInput $input): NodeResult\n {\n $categories = implode(', ', (array) ($input->config['categories'] ?? []));\n\n return $this->generate($input, \"Classify the user's text into exactly one of these categories: {$categories}. Respond with only the category name.\");\n }\n\n private function summarize(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Summarize the following text concisely.');\n }\n\n private function sentiment(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Analyze the sentiment of the text. Respond with only: positive, negative, or neutral.');\n }\n\n private function extract(NodeInput $input): NodeResult\n {\n $fields = json_encode($input->config['fields'] ?? []);\n\n return $this->generate($input, \"Extract the following fields from the text and respond with only valid JSON: {$fields}\");\n }\n\n private function anthropic(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('ANTHROPIC_API_KEY', '');\n $system = $systemOverride ?? ($input->config['system_prompt'] ?? null);\n\n $response = $this->http()\n ->baseUrl('https://api.anthropic.com/v1')\n ->withHeaders(['x-api-key' => $apiKey, 'anthropic-version' => '2023-06-01'])\n ->post('/messages', array_filter([\n 'model' => $input->config['model'] ?? 'claude-sonnet-4-6',\n 'max_tokens' => (int) ($input->config['max_tokens'] ?? 4096),\n 'system' => $system,\n 'messages' => [['role' => 'user', 'content' => $input->config['prompt'] ?? '']],\n ]));\n\n if (! $response->successful()) {\n return $this->fail(\"Anthropic API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function openai(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('OPENAI_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.openai.com/v1')\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'gpt-4o-mini',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function gemini(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('GEMINI_API_KEY', '');\n $model = $input->config['model'] ?? 'gemini-2.0-flash';\n $baseUrl = rtrim(env('GEMINI_URL', 'https://generativelanguage.googleapis.com/v1beta'), '/');\n\n $body = [\n 'contents' => [\n ['role' => 'user', 'parts' => [['text' => $input->config['prompt'] ?? '']]],\n ],\n ];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $body['systemInstruction'] = ['parts' => [['text' => $system]]];\n }\n\n if ($maxTokens = $input->config['max_tokens'] ?? null) {\n $body['generationConfig'] = ['maxOutputTokens' => (int) $maxTokens];\n }\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post(\"/models/{$model}:generateContent?key={$apiKey}\", $body);\n\n if (! $response->successful()) {\n return $this->fail(\"Gemini API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['candidates'][0]['content']['parts'][0]['text'] ?? '',\n 'usage' => [\n 'input_tokens' => $data['usageMetadata']['promptTokenCount'] ?? 0,\n 'output_tokens' => $data['usageMetadata']['candidatesTokenCount'] ?? 0,\n ],\n 'model' => $model,\n ]);\n }\n\n private function azure(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('AZURE_OPENAI_API_KEY', '');\n $endpoint = rtrim($input->credentials['endpoint'] ?? env('AZURE_OPENAI_URL', ''), '/');\n $deployment = $input->credentials['deployment'] ?? env('AZURE_OPENAI_DEPLOYMENT', 'gpt-4o');\n $apiVersion = $input->credentials['api_version'] ?? env('AZURE_OPENAI_API_VERSION', '2025-04-01-preview');\n\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $url = \"{$endpoint}/openai/deployments/{$deployment}/chat/completions?api-version={$apiVersion}\";\n\n $response = $this->http()\n ->withHeaders(['api-key' => $apiKey])\n ->post($url, ['messages' => $messages]);\n\n if (! $response->successful()) {\n return $this->fail(\"Azure OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $deployment,\n ]);\n }\n\n private function cohere(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('COHERE_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.cohere.com/v2')\n ->post('/chat', [\n 'model' => $input->config['model'] ?? 'command-r-plus',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Cohere API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['message']['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['id'] ?? '',\n ]);\n }\n\n private function ollama(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $baseUrl = rtrim($input->credentials['url'] ?? env('OLLAMA_URL', 'http://localhost:11434'), '/').'/v1';\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'llama3.2',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Ollama API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n /**\n * Shared handler for OpenAI-compatible providers (Groq, Mistral, DeepSeek, xAI, OpenRouter).\n */\n private function openaiCompatible(\n NodeInput $input,\n ?string $systemOverride,\n string $providerName,\n string $baseUrl,\n string $defaultModel,\n string $envKey,\n ): NodeResult {\n $apiKey = $input->credentials['api_key'] ?? env($envKey, '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? $defaultModel,\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"{$providerName} API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n}\n"}, "21c592d6ccaa4ffe7e20832965b479fa67ba0263": {"t": 1785760302.5444453, "n": 11782, "h": "57d73fd3d9a9aa60", "c": "<?php\n\nnamespace App\\Engine\\Nodes\\Apps\\Ai;\n\nuse App\\Engine\\NodeInput;\nuse App\\Engine\\NodeResult;\nuse App\\Engine\\Nodes\\Apps\\AppNode;\n\nclass LlmNode extends AppNode\n{\n protected function execute(string $operation, NodeInput $input): NodeResult\n {\n return match ($operation) {\n 'generate', 'complete', 'chat' => $this->generate($input),\n 'classify' => $this->classify($input),\n 'summarize' => $this->summarize($input),\n 'sentiment' => $this->sentiment($input),\n 'extract' => $this->extract($input),\n default => $this->fail(\"Llm: unknown operation '{$operation}'\"),\n };\n }\n\n private function generate(NodeInput $input, ?string $systemOverride = null): NodeResult\n {\n $provider = $input->config['provider'] ?? ($input->credentials['provider'] ?? 'anthropic');\n\n return match ($provider) {\n 'anthropic' => $this->anthropic($input, $systemOverride),\n 'openai' => $this->openai($input, $systemOverride),\n 'gemini' => $this->gemini($input, $systemOverride),\n 'azure' => $this->azure($input, $systemOverride),\n 'cohere' => $this->cohere($input, $systemOverride),\n 'ollama' => $this->ollama($input, $systemOverride),\n 'groq' => $this->openaiCompatible($input, $systemOverride, 'Groq', 'https://api.groq.com/openai/v1', 'llama-3.3-70b-versatile', 'GROQ_API_KEY'),\n 'mistral' => $this->openaiCompatible($input, $systemOverride, 'Mistral', 'https://api.mistral.ai/v1', 'mistral-small-latest', 'MISTRAL_API_KEY'),\n 'deepseek' => $this->openaiCompatible($input, $systemOverride, 'DeepSeek', 'https://api.deepseek.com/v1', 'deepseek-chat', 'DEEPSEEK_API_KEY'),\n 'xai' => $this->openaiCompatible($input, $systemOverride, 'xAI', 'https://api.x.ai/v1', 'grok-3-mini', 'XAI_API_KEY'),\n 'openrouter' => $this->openaiCompatible($input, $systemOverride, 'OpenRouter', 'https://openrouter.ai/api/v1', 'openai/gpt-4o-mini', 'OPENROUTER_API_KEY'),\n default => $this->fail(\"Llm: unknown provider '{$provider}'\"),\n };\n }\n\n private function classify(NodeInput $input): NodeResult\n {\n $categories = implode(', ', (array) ($input->config['categories'] ?? []));\n\n return $this->generate($input, \"Classify the user's text into exactly one of these categories: {$categories}. Respond with only the category name.\");\n }\n\n private function summarize(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Summarize the following text concisely.');\n }\n\n private function sentiment(NodeInput $input): NodeResult\n {\n return $this->generate($input, 'Analyze the sentiment of the text. Respond with only: positive, negative, or neutral.');\n }\n\n private function extract(NodeInput $input): NodeResult\n {\n $fields = json_encode($input->config['fields'] ?? []);\n\n return $this->generate($input, \"Extract the following fields from the text and respond with only valid JSON: {$fields}\");\n }\n\n private function anthropic(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('ANTHROPIC_API_KEY', '');\n $system = $systemOverride ?? ($input->config['system_prompt'] ?? null);\n\n $response = $this->http()\n ->baseUrl('https://api.anthropic.com/v1')\n ->withHeaders(['x-api-key' => $apiKey, 'anthropic-version' => '2023-06-01'])\n ->post('/messages', array_filter([\n 'model' => $input->config['model'] ?? 'claude-sonnet-4-6',\n 'max_tokens' => (int) ($input->config['max_tokens'] ?? 4096),\n 'system' => $system,\n 'messages' => [['role' => 'user', 'content' => $input->config['prompt'] ?? '']],\n ]));\n\n if (! $response->successful()) {\n return $this->fail(\"Anthropic API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function openai(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('OPENAI_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.openai.com/v1')\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'gpt-4o-mini',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n private function gemini(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('GEMINI_API_KEY', '');\n $model = $input->config['model'] ?? 'gemini-2.0-flash';\n $baseUrl = rtrim(env('GEMINI_URL', 'https://generativelanguage.googleapis.com/v1beta'), '/');\n\n $body = [\n 'contents' => [\n ['role' => 'user', 'parts' => [['text' => $input->config['prompt'] ?? '']]],\n ],\n ];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $body['systemInstruction'] = ['parts' => [['text' => $system]]];\n }\n\n if ($maxTokens = $input->config['max_tokens'] ?? null) {\n $body['generationConfig'] = ['maxOutputTokens' => (int) $maxTokens];\n }\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post(\"/models/{$model}:generateContent?key={$apiKey}\", $body);\n\n if (! $response->successful()) {\n return $this->fail(\"Gemini API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['candidates'][0]['content']['parts'][0]['text'] ?? '',\n 'usage' => [\n 'input_tokens' => $data['usageMetadata']['promptTokenCount'] ?? 0,\n 'output_tokens' => $data['usageMetadata']['candidatesTokenCount'] ?? 0,\n ],\n 'model' => $model,\n ]);\n }\n\n private function azure(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('AZURE_OPENAI_API_KEY', '');\n $endpoint = rtrim($input->credentials['endpoint'] ?? env('AZURE_OPENAI_URL', ''), '/');\n $deployment = $input->credentials['deployment'] ?? env('AZURE_OPENAI_DEPLOYMENT', 'gpt-4o');\n $apiVersion = $input->credentials['api_version'] ?? env('AZURE_OPENAI_API_VERSION', '2025-04-01-preview');\n\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $url = \"{$endpoint}/openai/deployments/{$deployment}/chat/completions?api-version={$apiVersion}\";\n\n $response = $this->http()\n ->withHeaders(['api-key' => $apiKey])\n ->post($url, ['messages' => $messages]);\n\n if (! $response->successful()) {\n return $this->fail(\"Azure OpenAI API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $deployment,\n ]);\n }\n\n private function cohere(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $apiKey = $input->credentials['api_key'] ?? env('COHERE_API_KEY', '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl('https://api.cohere.com/v2')\n ->post('/chat', [\n 'model' => $input->config['model'] ?? 'command-r-plus',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Cohere API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['message']['content'][0]['text'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['id'] ?? '',\n ]);\n }\n\n private function ollama(NodeInput $input, ?string $systemOverride): NodeResult\n {\n $baseUrl = rtrim($input->credentials['url'] ?? env('OLLAMA_URL', 'http://localhost:11434'), '/').'/v1';\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? 'llama3.2',\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"Ollama API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n\n /**\n * Shared handler for OpenAI-compatible providers (Groq, Mistral, DeepSeek, xAI, OpenRouter).\n */\n private function openaiCompatible(\n NodeInput $input,\n ?string $systemOverride,\n string $providerName,\n string $baseUrl,\n string $defaultModel,\n string $envKey,\n ): NodeResult {\n $apiKey = $input->credentials['api_key'] ?? env($envKey, '');\n $messages = [];\n\n if ($system = $systemOverride ?? ($input->config['system_prompt'] ?? null)) {\n $messages[] = ['role' => 'system', 'content' => $system];\n }\n\n $messages[] = ['role' => 'user', 'content' => $input->config['prompt'] ?? ''];\n\n $response = $this->http()\n ->withToken($apiKey)\n ->baseUrl($baseUrl)\n ->post('/chat/completions', [\n 'model' => $input->config['model'] ?? $defaultModel,\n 'messages' => $messages,\n ]);\n\n if (! $response->successful()) {\n return $this->fail(\"{$providerName} API error: {$response->body()}\");\n }\n\n $data = $response->json();\n\n return $this->success([\n 'response' => $data['choices'][0]['message']['content'] ?? '',\n 'usage' => $data['usage'] ?? [],\n 'model' => $data['model'] ?? '',\n ]);\n }\n}\n"}}}}