Protokoll #898
| ID | 898 |
|---|---|
| Zeitstempel | 2025-12-20 17:40:01.120795 |
| 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 | 2,654 (Input: 0, Output: 0) |
| Dauer | 380 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": "mcp__mcp-db__db_select",
"tool_input": {
"query": "SELECT * FROM file_backup_history ORDER BY id DESC LIMIT 5",
"database": "ki_dev"
}
}
Response
{
"tool_response": [
{
"type": "text",
"text": "{\n \"status\": \"success\",\n \"data\": [\n {\n \"id\": 44,\n \"file_path\": \"\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/AIConfig.php\",\n \"file_content\": \"<?php\\n\\ndeclare(strict_types=1);\\n\\nnamespace Infrastructure\\\\AI;\\n\\nuse RuntimeException;\\n\\n\/**\\n * Zentralisierte AI-Service-Konfiguration.\\n *\\n * Verwaltet alle Konfigurationswerte für AI-Services (Ollama, Qdrant, Claude)\\n * und stellt Factory-Methoden zur Service-Erstellung bereit.\\n *\\n * Diese Klasse:\\n * - Lädt Credentials sicher aus der credentials.md Datei\\n * - Definiert Default-Werte für alle Service-URLs und Modelle\\n * - Erstellt konfigurierte Service-Instanzen\\n * - Verhindert doppeltes Laden von API-Keys\\n *\\n * @package Infrastructure\\\\AI\\n * @author System Generated\\n * @version 1.0.0\\n *\/\\nfinal readonly class AIConfig\\n{\\n \/**\\n * Konstruiert eine neue AIConfig-Instanz.\\n *\\n * @param string $ollamaHost Ollama API Host-URL\\n * @param string $qdrantHost Qdrant API Host-URL\\n * @param string $anthropicApiKey Anthropic API Key\\n * @param string $embeddingModel Embedding-Modell für Ollama\\n * @param string $claudeModel Claude-Modell für Anthropic\\n * @param string $defaultCollection Standard-Collection für Qdrant\\n *\/\\n public function __construct(\\n public string $ollamaHost,\\n public string $qdrantHost,\\n public string $anthropicApiKey,\\n public string $embeddingModel,\\n public string $claudeModel,\\n public string $defaultCollection\\n ) {\\n }\\n\\n \/**\\n * Erstellt AIConfig aus Credentials-Datei mit Default-Werten.\\n *\\n * Lädt den Anthropic API Key aus der credentials.md Datei und\\n * verwendet Default-Werte für alle anderen Konfigurationsparameter.\\n *\\n * @param string $credentialsPath Pfad zur credentials.md Datei (default: \/var\/www\/docs\/credentials\/credentials.md)\\n *\\n * @return self Konfigurierte AIConfig-Instanz\\n *\\n * @throws RuntimeException Wenn Credentials-Datei nicht existiert\\n * @throws RuntimeException Wenn Credentials-Datei nicht gelesen werden kann\\n * @throws RuntimeException Wenn Anthropic API Key nicht gefunden wird\\n *\\n * @example\\n * $config = AIConfig::fromCredentialsFile();\\n * $chatService = $config->createChatService();\\n *\/\\n public static function fromCredentialsFile(\\n string $credentialsPath = '\/var\/www\/docs\/credentials\/credentials.md'\\n ): self {\\n $anthropicApiKey = self::loadAnthropicApiKey($credentialsPath);\\n\\n return new self(\\n ollamaHost: 'http:\/\/localhost:11434',\\n qdrantHost: 'http:\/\/localhost:6333',\\n anthropicApiKey: $anthropicApiKey,\\n embeddingModel: 'mxbai-embed-large',\\n claudeModel: 'claude-opus-4-5-20251101',\\n defaultCollection: 'documents'\\n );\\n }\\n\\n \/**\\n * Erstellt einen konfigurierten ChatService.\\n *\\n * Erzeugt alle benötigten Dependencies (OllamaService, QdrantService, ClaudeService)\\n * und liefert einen vollständig konfigurierten ChatService zurück.\\n *\\n * @return ChatService Konfigurierter ChatService\\n *\\n * @example\\n * $config = AIConfig::fromCredentialsFile();\\n * $chatService = $config->createChatService();\\n * $result = $chatService->chat('Was ist systemisches Coaching?');\\n *\/\\n public function createChatService(): ChatService\\n {\\n return new ChatService(\\n $this->createOllamaService(),\\n $this->createQdrantService(),\\n $this->createClaudeService()\\n );\\n }\\n\\n \/**\\n * Erstellt einen konfigurierten OllamaService.\\n *\\n * @return OllamaService Konfigurierter OllamaService\\n *\\n * @example\\n * $config = AIConfig::fromCredentialsFile();\\n * $ollama = $config->createOllamaService();\\n * $embedding = $ollama->getEmbedding('Hello World');\\n *\/\\n public function createOllamaService(): OllamaService\\n {\\n return new OllamaService($this->ollamaHost);\\n }\\n\\n \/**\\n * Erstellt einen konfigurierten QdrantService.\\n *\\n * @return QdrantService Konfigurierter QdrantService\\n *\\n * @example\\n * $config = AIConfig::fromCredentialsFile();\\n * $qdrant = $config->createQdrantService();\\n * $results = $qdrant->search($vector, 'documents');\\n *\/\\n public function createQdrantService(): QdrantService\\n {\\n return new QdrantService($this->qdrantHost);\\n }\\n\\n \/**\\n * Erstellt einen konfigurierten ClaudeService.\\n *\\n * @return ClaudeService Konfigurierter ClaudeService\\n *\\n * @example\\n * $config = AIConfig::fromCredentialsFile();\\n * $claude = $config->createClaudeService();\\n * $result = $claude->ask('Explain quantum computing');\\n *\/\\n public function createClaudeService(): ClaudeService\\n {\\n return new ClaudeService($this->anthropicApiKey);\\n }\\n\\n \/**\\n * Lädt den Anthropic API Key aus der Credentials-Datei.\\n *\\n * Sucht nach einer Zeile, die mit 'sk-ant-' beginnt und gibt diese zurück.\\n * API Key wird niemals in Exception-Messages geloggt.\\n *\\n * @param string $credentialsPath Pfad zur credentials.md Datei\\n *\\n * @return string Der gefundene API Key\\n *\\n * @throws RuntimeException Wenn Credentials-Datei nicht existiert\\n * @throws RuntimeException Wenn Credentials-Datei nicht gelesen werden kann\\n * @throws RuntimeException Wenn API Key nicht gefunden wird\\n *\/\\n private static function loadAnthropicApiKey(string $credentialsPath): string\\n {\\n if (!file_exists($credentialsPath)) {\\n throw new RuntimeException('Credentials file not found');\\n }\\n\\n $content = file_get_contents($credentialsPath);\\n\\n if ($content === false) {\\n throw new RuntimeException('Could not read credentials file');\\n }\\n\\n foreach (explode(\\\"\\\\n\\\", $content) as $line) {\\n $trimmedLine = trim($line);\\n if (str_starts_with($trimmedLine, 'sk-ant-')) {\\n return $trimmedLine;\\n }\\n }\\n\\n throw new RuntimeException('Anthropic API key not found in credentials file');\\n }\\n}\\n\",\n \"content_hash\": \"2ad822b274fadd54e6305f19e4f6dd7a321752eda0e0580f23c2e5e1e0237d8d\",\n \"file_size\": 5997,\n \"version\": 1,\n \"change_type\": \"modified\",\n \"changed_at\": \"2025-12-20T17:24:52\",\n \"changed_by\": \"claude-code-hook\",\n \"reason\": \"Claude Code Pre-Hook Backup vor Edit-Operation\",\n \"diff_summary\": null,\n \"affected_entities\": null\n },\n {\n \"id\": 43,\n \"file_path\": \"\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/AI\/AnthropicClient.php\",\n \"file_content\": \"<?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 $envFile = '\/var\/www\/docs\/credentials\/credentials.md';\\n if (file_exists($envFile)) {\\n $content = file_get_contents($envFile);\\n if (preg_match('\/ANTHROPIC_API_KEY[:\\\\s]+([a-zA-Z0-9_-]+)\/', $content, $matches)) {\\n return $matches[1];\\n }\\n }\\n\\n return '';\\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}\\\", $m... [TRUNCATED-7ff0c386f66fbad5]"
}
]
}