{
"event": "PreToolUse",
"tool_name": "Write",
"tool_input": {
"file_path": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Docs\/ChunkSearchService.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Docs;\n\n\/\/ @responsibility: Semantische Suche in Dokumentations-Chunks via Qdrant\n\nuse Infrastructure\\AI\\OllamaService;\nuse Infrastructure\\AI\\QdrantClient;\n\nfinal class ChunkSearchService\n{\n private const string COLLECTION = 'dokumentation_chunks';\n\n public function __construct(\n private QdrantClient $qdrant,\n private OllamaService $ollama\n ) {\n }\n\n \/**\n * Searches for similar chunks using semantic search.\n *\n * @param array<string, mixed>|null $filter Optional filter for taxonomy\/entities\n * @return array<array{id: int, doc_id: int, path: string, title: string, content: string, score: float, taxonomy: array<string>, entities: array<mixed>}>\n *\/\n public function search(string $query, int $limit = 5, ?array $filter = null): array\n {\n $embedding = $this->ollama->getEmbedding($query);\n\n $results = $this->qdrant->search(self::COLLECTION, $embedding, $limit, $filter);\n\n return array_map(static function (array $item): array {\n $payload = $item['payload'] ?? [];\n\n return [\n 'id' => (int) ($payload['chunk_id'] ?? 0),\n 'doc_id' => (int) ($payload['doc_id'] ?? 0),\n 'path' => (string) ($payload['path'] ?? ''),\n 'title' => (string) ($payload['title'] ?? ''),\n 'content' => (string) ($payload['content_preview'] ?? ''),\n 'score' => (float) ($item['score'] ?? 0),\n 'taxonomy' => is_array($payload['taxonomy'] ?? null) ? $payload['taxonomy'] : [],\n 'entities' => is_array($payload['entities'] ?? null) ? $payload['entities'] : [],\n ];\n }, $results);\n }\n\n \/**\n * Searches with taxonomy filter.\n *\n * @return array<array<string, mixed>>\n *\/\n public function searchByTaxonomy(string $query, string $category, int $limit = 5): array\n {\n $filter = [\n 'must' => [\n [\n 'key' => 'taxonomy_category',\n 'match' => ['value' => $category],\n ],\n ],\n ];\n\n return $this->search($query, $limit, $filter);\n }\n\n \/**\n * Gets collection statistics.\n *\n * @return array{points_count: int, status: string}|null\n *\/\n public function getStats(): ?array\n {\n return $this->qdrant->getCollectionStats(self::COLLECTION);\n }\n}\n"
}
}
{
"tool_response": {
"type": "create",
"filePath": "\/var\/www\/dev.campus.systemische-tools.de\/src\/Infrastructure\/Docs\/ChunkSearchService.php",
"content": "<?php\n\ndeclare(strict_types=1);\n\nnamespace Infrastructure\\Docs;\n\n\/\/ @responsibility: Semantische Suche in Dokumentations-Chunks via Qdrant\n\nuse Infrastructure\\AI\\OllamaService;\nuse Infrastructure\\AI\\QdrantClient;\n\nfinal class ChunkSearchService\n{\n private const string COLLECTION = 'dokumentation_chunks';\n\n public function __construct(\n private QdrantClient $qdrant,\n private OllamaService $ollama\n ) {\n }\n\n \/**\n * Searches for similar chunks using semantic search.\n *\n * @param array<string, mixed>|null $filter Optional filter for taxonomy\/entities\n * @return array<array{id: int, doc_id: int, path: string, title: string, content: string, score: float, taxonomy: array<string>, entities: array<mixed>}>\n *\/\n public function search(string $query, int $limit = 5, ?array $filter = null): array\n {\n $embedding = $this->ollama->getEmbedding($query);\n\n $results = $this->qdrant->search(self::COLLECTION, $embedding, $limit, $filter);\n\n return array_map(static function (array $item): array {\n $payload = $item['payload'] ?? [];\n\n return [\n 'id' => (int) ($payload['chunk_id'] ?? 0),\n 'doc_id' => (int) ($payload['doc_id'] ?? 0),\n 'path' => (string) ($payload['path'] ?? ''),\n 'title' => (string) ($payload['title'] ?? ''),\n 'content' => (string) ($payload['content_preview'] ?? ''),\n 'score' => (float) ($item['score'] ?? 0),\n 'taxonomy' => is_array($payload['taxonomy'] ?? null) ? $payload['taxonomy'] : [],\n 'entities' => is_array($payload['entities'] ?? null) ? $payload['entities'] : [],\n ];\n }, $results);\n }\n\n \/**\n * Searches with taxonomy filter.\n *\n * @return array<array<string, mixed>>\n *\/\n public function searchByTaxonomy(string $query, string $category, int $limit = 5): array\n {\n $filter = [\n 'must' => [\n [\n 'key' => 'taxonomy_category',\n 'match' => ['value' => $category],\n ],\n ],\n ];\n\n return $this->search($query, $limit, $filter);\n }\n\n \/**\n * Gets collection statistics.\n *\n * @return array{points_count: int, status: string}|null\n *\/\n public function getStats(): ?array\n {\n return $this->qdrant->getCollectionStats(self::COLLECTION);\n }\n}\n",
"structuredPatch": [],
"originalFile": null
}
}