feat(E): Unified Search — 24 Tasks complete
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
- SPIKE-E: FTS+Vector+Permission benchmark on 10k records (all <30ms) - E-PROV: supports_fts/vector/rag/graph capability flags on all providers - E-FTS/VEC: All 11 providers refactored to BaseSearchProvider with permission filtering - E-PERM: Over-fetch strategy for vector+permission (15x faster than ANY() filter) - E-FUSE: rrf_fusion_multi() for N-way RRF over FTS+Vector+RAG+Graph - E-LLM: Query understanding cleaned up to use central llm_complete() - E-CHUNK: Document chunking module + document_chunks table with HNSW index - E-EMB: Chunk embedding ARQ jobs (index_file_chunks, reindex_chunks) - E-RAG: RAG retrieval via FileSearchProvider.search_rag() - E-GRAPH: GraphRAG BFS traversal via GraphRAGSearchProvider.search_graph() - E-IX-EVT: Auto-indexing via outbox events + delete/cleanup handlers - E-IX-RE: Batch reindex with progress tracking + reindex_all job - E-DATA-LIFE: Lifecycle module (remove/rebuild/restore/correct) + API endpoints - E-K-MEM: AgentMemorySearchProvider - E-P-AI: AIChatSearchProvider - E-P-WF: WorkflowSearchProvider - E-P-COMM: ConversationSearchProvider verified (already on BaseSearchProvider) - E-API: Filter params (date_from/to, tags, sort) + /facets endpoint - E-TOOL: unified_search AI tool registered in ToolRegistry - E-MCP: Search tool in MCP server with normal RBAC/tenant checks - E-UI-CMD: CommandPalette (Cmd+K) with debounced search + recent searches - E-UI-FAC: SearchFacets, SearchResultCard, SavedSearches components - E-TEST: 40 new tests in test_unified_search_phase_e.py (105 total green) - E-DOC: api-documentation.md, plugin-development-guide.md, test-strategy.md updated 105 tests passing, TypeScript clean.
This commit is contained in:
+103
-7
@@ -324,16 +324,112 @@ Agent Builder, Automation Builder, Cron-Scheduler, Agent Runner.
|
||||
|
||||
### search (Unified Search)
|
||||
|
||||
7 endpoints for cross-entity search.
|
||||
Hybrid cross-entity search (PostgreSQL FTS + pgvector) with KI query understanding, RRF rank fusion, visibility filtering, and field-level RBAC.
|
||||
|
||||
| Method | Path | Description |
|
||||
|--------|------|-------------|
|
||||
| POST | `/api/v1/search` | Unified search across all entities. |
|
||||
| GET | `/api/v1/search/providers` | List search providers. |
|
||||
| POST | `/api/v1/search/reindex` | Rebuild search index. |
|
||||
| POST | `/api/v1/search/similar` | Find similar entities. |
|
||||
| GET | `/api/v1/search/suggest` | Search suggestions. |
|
||||
| GET | `/api/v1/search/stats` | Search index statistics. |
|
||||
| GET | `/api/v1/search` | Hybrid search via query params (same as POST). |
|
||||
| POST | `/api/v1/search` | Hybrid search with KI query understanding. |
|
||||
| GET | `/api/v1/search/suggest` | Autocomplete suggestions (FTS prefix). |
|
||||
| POST | `/api/v1/search/similar` | Find similar entities across all types by embedding. |
|
||||
| POST | `/api/v1/search/reindex` | Trigger reindexing of entity types (admin). |
|
||||
| GET | `/api/v1/search/providers` | List active search providers + capability flags. |
|
||||
| POST | `/api/v1/search/providers/{entity_type}/toggle` | Toggle a provider on/off (admin). |
|
||||
| GET | `/api/v1/search/stats` | Search index statistics (indexed/pending per table). |
|
||||
| GET | `/api/v1/search/facets` | Available facets (entity types, tags, date ranges). |
|
||||
| POST | `/api/v1/search/rebuild/{entity_type}/{entity_id}` | Rebuild index for a single entity (admin). |
|
||||
| POST | `/api/v1/search/purge/{entity_type}/{entity_id}` | Purge entity from index (admin, GDPR). |
|
||||
|
||||
> **MCP:** Unified search is also exposed as an MCP tool named `search` (category `search`, permission `search:read`) via the MCP server plugin (`app/plugins/builtins/mcp_server/tool_definitions.py`).
|
||||
|
||||
#### Search Request (POST `/api/v1/search`)
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "Max Mustermann",
|
||||
"entity_types": ["contact", "mail"],
|
||||
"limit": 20,
|
||||
"offset": 0,
|
||||
"date_from": "2026-01-01",
|
||||
"date_to": "2026-12-31",
|
||||
"tags": ["vip", "partner"],
|
||||
"sort": "relevance"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Default | Description |
|
||||
|-------|------|---------|-------------|
|
||||
| `query` | string | — | Search query (1–500 chars, required). |
|
||||
| `entity_types` | list[string] | all | Restrict search to these entity types. |
|
||||
| `limit` | int | 20 | Max results (1–100). |
|
||||
| `offset` | int | 0 | Pagination offset. |
|
||||
| `date_from` | string | null | ISO date `YYYY-MM-DD` — filter by `created_at`/`updated_at >= date_from`. |
|
||||
| `date_to` | string | null | ISO date `YYYY-MM-DD` — filter by `created_at`/`updated_at <= date_to`. |
|
||||
| `tags` | list[string] | null | Filter results by tags (comma-separated on entities). |
|
||||
| `sort` | string | `relevance` | Sort order: `relevance`, `date`, `name`. |
|
||||
|
||||
#### Search Response
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "Max Mustermann",
|
||||
"normalized_query": "max mustermann",
|
||||
"results": [
|
||||
{
|
||||
"entity_type": "contact",
|
||||
"entity_id": "uuid",
|
||||
"title": "Max Mustermann",
|
||||
"snippet": "max@example.com",
|
||||
"score": 0.95,
|
||||
"data": {"type": "person"}
|
||||
}
|
||||
],
|
||||
"facets": {"types": {"contact": 1}},
|
||||
"summary": "1 Ergebnis",
|
||||
"suggestions": []
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|-------|------|-------------|
|
||||
| `query` | string | Original query. |
|
||||
| `normalized_query` | string | KI-normalized query. |
|
||||
| `results` | list[SearchResult] | Ranked results (entity_type, entity_id, title, snippet, score, data). |
|
||||
| `facets` | object | KI-generated facet counts. |
|
||||
| `summary` | string | Human-readable summary. |
|
||||
| `suggestions` | list[string] | Suggested follow-up filters. |
|
||||
|
||||
#### GET `/api/v1/search` Query Params
|
||||
|
||||
Same fields as the POST body, passed as query parameters: `q` (required), `entity_types` (comma-separated), `limit`, `offset`, `date_from`, `date_to`, `tags` (comma-separated), `sort`.
|
||||
|
||||
#### GET `/api/v1/search/suggest`
|
||||
|
||||
Query params: `q` (required, 1–200), `limit` (default 10, 1–50). Returns `{"suggestions": ["..."]}`.
|
||||
|
||||
#### POST `/api/v1/search/similar`
|
||||
|
||||
Body: `{"entity_type": "contact", "entity_id": "uuid", "limit": 5}`. Returns `{"similar": {"mail": [SearchResult...], ...}}`.
|
||||
|
||||
#### POST `/api/v1/search/reindex`
|
||||
|
||||
Body: `{"entity_types": ["contact"], "include_chunks": true}`. Returns `{"status": "ok", "entity_types": [...], "include_chunks": true, "job_ids": [...]}`. Requires `search:admin`.
|
||||
|
||||
#### GET `/api/v1/search/providers`
|
||||
|
||||
Returns a list of providers: `{"entity_type", "plugin_name", "is_active", "supports_fts", "supports_vector", "supports_rag", "supports_graph"}`.
|
||||
|
||||
#### GET `/api/v1/search/facets`
|
||||
|
||||
Returns `{"entity_types": [...], "tags": [...], "date_ranges": {"contacts": {"min": "...", "max": "..."}, ...}}`.
|
||||
|
||||
#### GET `/api/v1/search/stats`
|
||||
|
||||
Returns per-table `{"total", "indexed", "pending"}` plus `recent_logs` (last 10 index log entries).
|
||||
|
||||
#### POST `/api/v1/search/rebuild/{entity_type}/{entity_id}` / `/purge/{entity_type}/{entity_id}`
|
||||
|
||||
Admin-only. Rebuild regenerates the embedding + TSV; purge sets embedding/TSV to NULL (and removes chunks for files). Returns `{"status": "ok"|"failed", "entity_type", "entity_id", "message"}`.
|
||||
|
||||
### reports (Report Generator)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user