Phase 1C: Frontend unified contact UI

This commit is contained in:
Agent Zero
2026-07-23 17:17:32 +02:00
parent a8331fbc2b
commit 879106c4eb
62 changed files with 552 additions and 1276 deletions
@@ -181,7 +181,6 @@ async def index_entity(
table_map = {
"contact": "contacts",
"company": "contacts",
"mail": "mails",
"file": "files",
"event": "calendar_entries",
+2 -4
View File
@@ -122,7 +122,7 @@ async def index_contact(ctx: dict[str, Any], contact_id: str) -> None:
async def index_company(ctx: dict[str, Any], company_id: str) -> None:
"""Index a company: generate and store embedding."""
"""Index a company (contact with type='company'): generate and store embedding."""
from sqlalchemy import text
from app.plugins.builtins.unified_search.embedding import index_entity
@@ -137,7 +137,7 @@ async def index_company(ctx: dict[str, Any], company_id: str) -> None:
row = result.mappings().first()
if not row:
return
await index_entity("company", eid, row["tenant_id"], db)
await index_entity("contact", eid, row["tenant_id"], db)
except Exception:
logger.exception("Failed to index company %s", company_id)
@@ -170,7 +170,6 @@ async def reindex(ctx: dict[str, Any], entity_type: str) -> None:
table_map = {
"contact": "contacts",
"company": "contacts",
"mail": "mails",
"file": "files",
"event": "calendar_entries",
@@ -216,7 +215,6 @@ async def embedding_batch(ctx: dict[str, Any]) -> None:
table_map = {
"contact": "contacts",
"company": "contacts",
"mail": "mails",
"file": "files",
"event": "calendar_entries",
@@ -35,8 +35,6 @@ class UnifiedSearchPlugin(BasePlugin):
"file.uploaded",
"contact.created",
"contact.updated",
"company.created",
"company.updated",
"calendar.entry.created",
],
migrations=["0001_initial.sql", "0002_embeddings.sql"],
@@ -97,20 +95,6 @@ class UnifiedSearchPlugin(BasePlugin):
if contact_id:
await enqueue_job("index_contact", contact_id)
async def on_company_created(self, payload: dict[str, Any]) -> None:
from app.core.jobs import enqueue_job
company_id = payload.get("company_id")
if company_id:
await enqueue_job("index_company", company_id)
async def on_company_updated(self, payload: dict[str, Any]) -> None:
from app.core.jobs import enqueue_job
company_id = payload.get("company_id")
if company_id:
await enqueue_job("index_company", company_id)
async def on_calendar_entry_created(self, payload: dict[str, Any]) -> None:
from app.core.jobs import enqueue_job
@@ -103,9 +103,6 @@ async def auto_register_providers(db: AsyncSession) -> None:
from app.plugins.builtins.unified_search.providers.contact_provider import (
ContactSearchProvider,
)
from app.plugins.builtins.unified_search.providers.company_provider import (
CompanySearchProvider,
)
from app.plugins.builtins.unified_search.providers.mail_provider import (
MailSearchProvider,
)
@@ -122,7 +119,6 @@ async def auto_register_providers(db: AsyncSession) -> None:
# Register all built-in providers
for provider_cls in [
ContactSearchProvider,
CompanySearchProvider,
MailSearchProvider,
FileSearchProvider,
EventSearchProvider,
@@ -15,7 +15,7 @@ logger = logging.getLogger(__name__)
class CompanySearchProvider:
"""Search provider for Company entities (contacts with type='company')."""
entity_type = "company"
entity_type = "contact"
async def search_fts(
self,
@@ -117,5 +117,5 @@ class CompanySearchProvider:
"title": name,
"snippet": email[:200],
"score": 0.0,
"data": {},
"data": {"type": "company"},
}
@@ -70,7 +70,6 @@ async def search(
# Map entity_type to module name for field-level permissions
_ENTITY_TO_MODULE = {
"contact": "contacts",
"company": "contacts",
"mail": "mail",
"file": "dms",
"event": "calendar",
@@ -17,7 +17,6 @@ logger = logging.getLogger(__name__)
# Entity type -> (table_name, tsv_column, embedding_column)
SEARCHABLE_ENTITIES: dict[str, tuple[str, str, str]] = {
"contact": ("contacts", "search_tsv", "embedding"),
"company": ("companies", "search_tsv", "embedding"),
"mail": ("mails", "body_tsv", "embedding"),
"file": ("files", "content_tsv", "embedding"),
"event": ("calendar_entries", "search_tsv", "embedding"),