Files
kamidso-back/kamidso/resources/registry.py
T
javadandCursor edbaa2acec Add native Didar connectors so chats can query CRM data reliably.
Connector calls, semantic rules, and DuckDB memory keep long runs stable, and stream retry stops chats from stalling.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 19:26:47 +03:30

79 lines
2.8 KiB
Python

from __future__ import annotations
from typing import Any, Dict, List, Optional
from kamidso.contracts.errors import KamidsoError, KamidsoErrorCode
from kamidso.contracts.resource import ResourceRef
from kamidso.contracts.user import CurrentUser
from kamidso.repositories.store import RepositoryStore
class ResourceRegistry:
def __init__(self, store: RepositoryStore) -> None:
self._store = store
async def authorize(self, user: CurrentUser, ref: ResourceRef) -> Dict[str, Any]:
if ref.type == "file":
doc = await self._store.get_file(user.workspace_id, ref.id)
elif ref.type == "datasource":
doc = await self._store.get_datasource(user.workspace_id, ref.id)
elif ref.type == "knowledge":
doc = await self._store.get_knowledge_source(user.workspace_id, ref.id)
elif ref.type == "connector":
doc = _authorize_connector(user, ref.id)
else:
raise KamidsoError(KamidsoErrorCode.RESOURCE_NOT_FOUND)
if doc is None:
raise KamidsoError(KamidsoErrorCode.RESOURCE_NOT_FOUND)
status = str(doc.get("status") or "ready")
if status not in {"ready", "active"}:
raise KamidsoError(KamidsoErrorCode.RESOURCE_NOT_READY)
return doc
async def authorize_many(
self, user: CurrentUser, refs: List[ResourceRef]
) -> List[Dict[str, Any]]:
return [await self.authorize(user, ref) for ref in refs]
async def bind_engine(
self,
*,
workspace_id: str,
resource_id: str,
engine: str,
engine_resource_id: str,
binding_type: str = "persistent",
) -> Dict[str, Any]:
return await self._store.upsert_resource_binding(
{
"workspace_id": workspace_id,
"resource_id": resource_id,
"engine": engine,
"engine_resource_id": engine_resource_id,
"binding_type": binding_type,
"status": "ready",
}
)
def _authorize_connector(user: CurrentUser, connector_id: str) -> Optional[Dict[str, Any]]:
"""Public connector row. Credentials stay in the encrypted connector table."""
from kamidso.native_connectors.resolve import load_public_instance
row = load_public_instance(connector_id)
if row is None:
return None
owner = str(row.get("user_name") or "")
if owner and owner != user.id:
return None
workspace = str(row.get("sys_code") or "")
if workspace and user.workspace_id and workspace != user.workspace_id:
return None
status = str(row.get("status") or "")
return {
"id": row.get("connector_id"),
"status": status,
"name": row.get("display_name") or connector_id,
"connector_type": row.get("connector_type"),
}