{
"event": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Logging\/KiProtokollService.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Logging;\n\n\/\/ @responsibility: Crash-safe wrapper for KI-Protokoll logging (SRP extraction)\n\nuse Domain\\Repository\\KiProtokollRepositoryInterface;\n\n\/**\n * KiProtokollService provides crash-safe logging to ki_dev.protokoll.\n *\n * ALL methods are wrapped in try-catch to ensure the Chat continues\n * even if protokoll logging fails. This is critical for production stability.\n *\/\nfinal class KiProtokollService\n{\n public function __construct(\n private KiProtokollRepositoryInterface $repository\n ) {\n }\n\n \/**\n * Log a new LLM request (status: pending).\n *\n * @return int|null The protokoll ID, or null if logging failed\n *\/\n public function logRequest(\n string $clientName,\n string $request,\n string $model,\n string $requestIp\n ): ?int {\n try {\n return $this->repository->insert($clientName, $request, $model, $requestIp);\n } catch (\\Throwable $e) {\n error_log('KiProtokoll logRequest failed: ' . $e->getMessage());\n\n return null;\n }\n }\n\n \/**\n * Complete a pending protokoll entry with response data.\n * Silent fail - Chat continues regardless.\n *\/\n public function logSuccess(\n int $id,\n string $response,\n int $durationMs,\n ?int $tokensInput,\n ?int $tokensOutput\n ): void {\n try {\n $this->repository->complete($id, $response, $durationMs, $tokensInput, $tokensOutput);\n } catch (\\Throwable $e) {\n error_log(\"KiProtokoll logSuccess failed for ID {$id}: \" . $e->getMessage());\n }\n }\n\n \/**\n * Mark a protokoll entry as failed.\n * Silent fail - Chat continues regardless.\n *\/\n public function logFailure(int $id, string $errorMessage): void\n {\n try {\n $this->repository->fail($id, $errorMessage);\n } catch (\\Throwable $e) {\n error_log(\"KiProtokoll logFailure failed for ID {$id}: \" . $e->getMessage());\n }\n }\n\n \/**\n * Clean up stale pending entries (cron job).\n *\n * @return int Number of cleaned up entries, or 0 on failure\n *\/\n public function cleanupStale(int $minutesOld = 10): int\n {\n try {\n return $this->repository->cleanupStale($minutesOld);\n } catch (\\Throwable $e) {\n error_log('KiProtokoll cleanupStale failed: ' . $e->getMessage());\n\n return 0;\n }\n }\n}\n"
}
}
{
"tool_response": {
"type": "create",
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Logging\/KiProtokollService.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Logging;\n\n\/\/ @responsibility: Crash-safe wrapper for KI-Protokoll logging (SRP extraction)\n\nuse Domain\\Repository\\KiProtokollRepositoryInterface;\n\n\/**\n * KiProtokollService provides crash-safe logging to ki_dev.protokoll.\n *\n * ALL methods are wrapped in try-catch to ensure the Chat continues\n * even if protokoll logging fails. This is critical for production stability.\n *\/\nfinal class KiProtokollService\n{\n public function __construct(\n private KiProtokollRepositoryInterface $repository\n ) {\n }\n\n \/**\n * Log a new LLM request (status: pending).\n *\n * @return int|null The protokoll ID, or null if logging failed\n *\/\n public function logRequest(\n string $clientName,\n string $request,\n string $model,\n string $requestIp\n ): ?int {\n try {\n return $this->repository->insert($clientName, $request, $model, $requestIp);\n } catch (\\Throwable $e) {\n error_log('KiProtokoll logRequest failed: ' . $e->getMessage());\n\n return null;\n }\n }\n\n \/**\n * Complete a pending protokoll entry with response data.\n * Silent fail - Chat continues regardless.\n *\/\n public function logSuccess(\n int $id,\n string $response,\n int $durationMs,\n ?int $tokensInput,\n ?int $tokensOutput\n ): void {\n try {\n $this->repository->complete($id, $response, $durationMs, $tokensInput, $tokensOutput);\n } catch (\\Throwable $e) {\n error_log(\"KiProtokoll logSuccess failed for ID {$id}: \" . $e->getMessage());\n }\n }\n\n \/**\n * Mark a protokoll entry as failed.\n * Silent fail - Chat continues regardless.\n *\/\n public function logFailure(int $id, string $errorMessage): void\n {\n try {\n $this->repository->fail($id, $errorMessage);\n } catch (\\Throwable $e) {\n error_log(\"KiProtokoll logFailure failed for ID {$id}: \" . $e->getMessage());\n }\n }\n\n \/**\n * Clean up stale pending entries (cron job).\n *\n * @return int Number of cleaned up entries, or 0 on failure\n *\/\n public function cleanupStale(int $minutesOld = 10): int\n {\n try {\n return $this->repository->cleanupStale($minutesOld);\n } catch (\\Throwable $e) {\n error_log('KiProtokoll cleanupStale failed: ' . $e->getMessage());\n\n return 0;\n }\n }\n}\n",
"structuredPatch": [],
"originalFile": null
}
}