Protokoll #3967
| ID | 3967 |
|---|---|
| Zeitstempel | 2025-12-22 08:54:17.180013 |
| Client | root |
| IP | Warning: Undefined array key "request_ip" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13 |
| Modell | claude-sonnet-4-20250514 |
| Status | completed |
| Tokens | 1,895 (Input: 0, Output: 0) |
| Dauer | 94 ms |
| Request-Zeit | Warning: Undefined array key "request_timestamp" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 18 |
| Response-Zeit | - |
Warning: Undefined array key "error_message" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 22
Request
{
"event": "PreToolUse",
"tool_name": "Edit",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/AnthropicClient.php",
"old_string": " $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n $durationMs = (int) ((microtime(true) - $startTime) * 1000);\n\n if ($error !== '') {\n return AIResponse::error(\"cURL Error: {$error}\", $model);\n }\n\n $data = json_decode($response, true);",
"new_string": " $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n $durationMs = (int) ((microtime(true) - $startTime) * 1000);\n\n if ($response === false || $error !== '') {\n return AIResponse::error(\"cURL Error: {$error}\", $model);\n }\n\n $data = json_decode($response, true);"
}
}
Response
{
"tool_response": {
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/AnthropicClient.php",
"oldString": " $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n $durationMs = (int) ((microtime(true) - $startTime) * 1000);\n\n if ($error !== '') {\n return AIResponse::error(\"cURL Error: {$error}\", $model);\n }\n\n $data = json_decode($response, true);",
"newString": " $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n $durationMs = (int) ((microtime(true) - $startTime) * 1000);\n\n if ($response === false || $error !== '') {\n return AIResponse::error(\"cURL Error: {$error}\", $model);\n }\n\n $data = json_decode($response, true);",
"originalFile": "<?php\n\nnamespace Infrastructure\\AI;\n\nclass AnthropicClient implements AIClientInterface\n{\n private string $apiKey;\n private string $model;\n private string $baseUrl;\n private int $timeout;\n\n private const PRICING = [\n 'claude-sonnet-4-20250514' => ['input' => 3.0, 'output' => 15.0],\n 'claude-opus-4-20250514' => ['input' => 15.0, 'output' => 75.0],\n 'claude-haiku-3-20250514' => ['input' => 0.25, 'output' => 1.25],\n ];\n\n public function __construct(\n string $apiKey = '',\n string $model = 'claude-sonnet-4-20250514',\n int $timeout = 120\n ) {\n $this->apiKey = $apiKey !== '' ? $apiKey : $this->loadApiKey();\n $this->model = $model;\n $this->baseUrl = 'https:\/\/api.anthropic.com\/v1';\n $this->timeout = $timeout;\n }\n\n private function loadApiKey(): string\n {\n if (defined('ANTHROPIC_API_KEY')) {\n return ANTHROPIC_API_KEY;\n }\n\n return \\Infrastructure\\Config\\CredentialService::getAnthropicApiKey();\n }\n\n public function execute(string $prompt, array $options = []): AIResponse\n {\n if ($this->apiKey === '') {\n return AIResponse::error('Anthropic API Key not configured', $this->model);\n }\n\n $model = $options['model'] ?? $this->model;\n $startTime = microtime(true);\n\n try {\n $ch = curl_init($this->baseUrl . '\/messages');\n\n $messages = [\n ['role' => 'user', 'content' => $prompt],\n ];\n\n $payload = [\n 'model' => $model,\n 'max_tokens' => $options['max_tokens'] ?? 4096,\n 'messages' => $messages,\n ];\n\n if (isset($options['system'])) {\n $payload['system'] = $options['system'];\n }\n\n if (isset($options['temperature'])) {\n $payload['temperature'] = $options['temperature'];\n }\n\n curl_setopt_array($ch, [\n CURLOPT_POST => true,\n CURLOPT_POSTFIELDS => json_encode($payload),\n CURLOPT_RETURNTRANSFER => true,\n CURLOPT_HTTPHEADER => [\n 'Content-Type: application\/json',\n 'x-api-key: ' . $this->apiKey,\n 'anthropic-version: 2023-06-01',\n ],\n CURLOPT_TIMEOUT => $this->timeout,\n ]);\n\n $response = curl_exec($ch);\n $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);\n $error = curl_error($ch);\n curl_close($ch);\n\n $durationMs = (int) ((microtime(true) - $startTime) * 1000);\n\n if ($error !== '') {\n return AIResponse::error(\"cURL Error: {$error}\", $model);\n }\n\n $data = json_decode($response, true);\n\n if ($httpCode !== 200) {\n $errorMsg = $data['error']['message'] ?? \"HTTP Error: {$httpCode}\";\n\n return AIResponse::error($errorMsg, $model);\n }\n\n if (!isset($data['content'][0]['text'])) {\n return AIResponse::error('Invalid response format', $model);\n }\n\n $tokensInput = $data['usage']['input_tokens'] ?? null;\n $tokensOutput = $data['usage']['output_tokens'] ?? null;\n\n $cost = $this->calculateCost($model, $tokensInput, $tokensOutput);\n\n return AIResponse::success(\n $data['content'][0]['text'],\n $tokensInput,\n $tokensOutput,\n $durationMs,\n $model,\n [\n 'stop_reason' => $data['stop_reason'] ?? null,\n 'cost_usd' => $cost,\n ]\n );\n } catch (\\Exception $e) {\n return AIResponse::error($e->getMessage(), $model);\n }\n }\n\n public function isAvailable(): bool\n {\n return $this->apiKey !== '';\n }\n\n public function getClientName(): string\n {\n return 'anthropic_api';\n }\n\n public function getModelName(): string\n {\n return $this->model;\n }\n\n private function calculateCost(string $model, ?int $inputTokens, ?int $outputTokens): ?float\n {\n if ($inputTokens === null || $outputTokens === null) {\n return null;\n }\n\n $pricing = self::PRICING[$model] ?? self::PRICING['claude-sonnet-4-20250514'];\n\n $inputCost = ($inputTokens \/ 1_000_000) * $pricing['input'];\n $outputCost = ($outputTokens \/ 1_000_000) * $pricing['output'];\n\n return round($inputCost + $outputCost, 6);\n }\n\n public function setModel(string $model): self\n {\n $this->model = $model;\n\n return $this;\n }\n\n public static function getAvailableModels(): array\n {\n return array_keys(self::PRICING);\n }\n}\n",
"structuredPatch": [
{
"oldStart": 84,
"oldLines": 7,
"newStart": 84,
"newLines": 7,
"lines": [
" ",
" $durationMs = (int) ((microtime(true) - $startTime) * 1000);",
" ",
"- if ($error !== '') {",
"+ if ($response === false || $error !== '') {",
" return AIResponse::error(\"cURL Error: {$error}\", $model);",
" }",
" "
]
}
],
"userModified": false,
"replaceAll": false
}
}