vector-bridge 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vector_bridge/__init__.py +489 -0
- vector_bridge/async_io/__init__.py +0 -0
- vector_bridge/async_io/admin/__init__.py +20 -0
- vector_bridge/async_io/admin/api_keys.py +87 -0
- vector_bridge/async_io/admin/integrations.py +347 -0
- vector_bridge/async_io/admin/organization.py +26 -0
- vector_bridge/async_io/admin/security_groups.py +128 -0
- vector_bridge/async_io/admin/settings.py +21 -0
- vector_bridge/async_io/admin/vector_db/__init__.py +12 -0
- vector_bridge/async_io/admin/vector_db/changeset.py +372 -0
- vector_bridge/async_io/admin/vector_db/state.py +240 -0
- vector_bridge/async_io/client/__init__.py +0 -0
- vector_bridge/async_io/client/ai_knowledge/__init__.py +12 -0
- vector_bridge/async_io/client/ai_knowledge/file_storage.py +671 -0
- vector_bridge/async_io/client/logs.py +51 -0
- vector_bridge/async_io/client/query.py +118 -0
- vector_bridge/async_io/client/usage.py +49 -0
- vector_bridge/async_io/client/user.py +224 -0
- vector_bridge/async_io/client/workflows.py +650 -0
- vector_bridge/schema/__init__.py +0 -0
- vector_bridge/schema/ai_knowledge/__init__.py +37 -0
- vector_bridge/schema/ai_knowledge/filesystem.py +720 -0
- vector_bridge/schema/api_keys.py +38 -0
- vector_bridge/schema/error.py +13 -0
- vector_bridge/schema/errors/__init__.py +0 -0
- vector_bridge/schema/errors/ai_knowledge.py +151 -0
- vector_bridge/schema/errors/api_keys.py +43 -0
- vector_bridge/schema/errors/base.py +31 -0
- vector_bridge/schema/errors/integrations.py +109 -0
- vector_bridge/schema/errors/logs.py +49 -0
- vector_bridge/schema/errors/message.py +61 -0
- vector_bridge/schema/errors/organization.py +73 -0
- vector_bridge/schema/errors/queries.py +43 -0
- vector_bridge/schema/errors/security_groups.py +85 -0
- vector_bridge/schema/errors/settings.py +9 -0
- vector_bridge/schema/errors/usage.py +61 -0
- vector_bridge/schema/errors/user.py +57 -0
- vector_bridge/schema/errors/vectordb_state_changeset.py +195 -0
- vector_bridge/schema/errors/workflows.py +49 -0
- vector_bridge/schema/helpers/__init__.py +0 -0
- vector_bridge/schema/helpers/enums.py +318 -0
- vector_bridge/schema/helpers/weaviate_schema.py +158 -0
- vector_bridge/schema/integrations.py +54 -0
- vector_bridge/schema/logs.py +28 -0
- vector_bridge/schema/messages.py +53 -0
- vector_bridge/schema/organization.py +24 -0
- vector_bridge/schema/queries.py +43 -0
- vector_bridge/schema/security_group.py +188 -0
- vector_bridge/schema/settings.py +29 -0
- vector_bridge/schema/usage.py +29 -0
- vector_bridge/schema/user.py +154 -0
- vector_bridge/schema/user_integrations.py +44 -0
- vector_bridge/schema/weaviate_schema.py +60 -0
- vector_bridge/schema/workflows.py +177 -0
- vector_bridge/sync_io/__init__.py +0 -0
- vector_bridge/sync_io/admin/__init__.py +20 -0
- vector_bridge/sync_io/admin/integrations.py +305 -0
- vector_bridge/sync_io/admin/organization.py +23 -0
- vector_bridge/sync_io/admin/security_groups.py +105 -0
- vector_bridge/sync_io/admin/settings.py +19 -0
- vector_bridge/sync_io/admin/vector_db/__init__.py +12 -0
- vector_bridge/sync_io/admin/vector_db/changeset.py +336 -0
- vector_bridge/sync_io/admin/vector_db/state.py +200 -0
- vector_bridge/sync_io/client/__init__.py +0 -0
- vector_bridge/sync_io/client/ai_knowledge/__init__.py +10 -0
- vector_bridge/sync_io/client/ai_knowledge/file_storage.py +613 -0
- vector_bridge/sync_io/client/api_keys.py +75 -0
- vector_bridge/sync_io/client/logs.py +48 -0
- vector_bridge/sync_io/client/query.py +107 -0
- vector_bridge/sync_io/client/usage.py +46 -0
- vector_bridge/sync_io/client/user.py +191 -0
- vector_bridge/sync_io/client/workflows.py +573 -0
- vector_bridge/utils.py +35 -0
- vector_bridge-0.0.1.dist-info/METADATA +468 -0
- vector_bridge-0.0.1.dist-info/RECORD +76 -0
- vector_bridge-0.0.1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any
|
|
3
|
+
from urllib.parse import urlparse
|
|
4
|
+
|
|
5
|
+
import aiohttp
|
|
6
|
+
import requests
|
|
7
|
+
from pydantic import BaseModel
|
|
8
|
+
from vector_bridge.schema.errors.base import raise_for_base_error_detail
|
|
9
|
+
from vector_bridge.schema.helpers.enums import UserType
|
|
10
|
+
from vector_bridge.schema.organization import OrganizationCreate
|
|
11
|
+
from vector_bridge.schema.user import UserCreate
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Token(BaseModel):
|
|
15
|
+
access_token: str
|
|
16
|
+
token_type: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseVectorBridgeClient:
|
|
20
|
+
"""Base class for VectorBridge clients with common functionality."""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
base_url: str = "http://vector_bridge:8000/",
|
|
25
|
+
api_key: str | None = None,
|
|
26
|
+
integration_name: str = "default",
|
|
27
|
+
):
|
|
28
|
+
self.base_url = base_url.rstrip("/")
|
|
29
|
+
self.access_token = None
|
|
30
|
+
self.api_key = api_key
|
|
31
|
+
self.integration_name = integration_name
|
|
32
|
+
|
|
33
|
+
self._parsed_url = urlparse(self.base_url)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def host(self) -> str:
|
|
37
|
+
return self._parsed_url.hostname or "localhost"
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def redis_url(self) -> str:
|
|
41
|
+
return f"redis://{self.host}:6379"
|
|
42
|
+
|
|
43
|
+
def _get_auth_headers(self) -> dict[str, str]:
|
|
44
|
+
"""Get headers with API key authentication and bearer token authentication."""
|
|
45
|
+
api_key_headers = {}
|
|
46
|
+
if self.api_key:
|
|
47
|
+
api_key_headers["Api-Key"] = self.api_key
|
|
48
|
+
if self.access_token:
|
|
49
|
+
api_key_headers["Authorization"] = f"Bearer {self.access_token}"
|
|
50
|
+
|
|
51
|
+
if not api_key_headers:
|
|
52
|
+
raise ValueError("Authentication or API key required. Call login() first or provide api_key.")
|
|
53
|
+
return api_key_headers
|
|
54
|
+
|
|
55
|
+
def _create_http_exception(self, status_code: int, error_data: Any, error_callable: Callable) -> Exception:
|
|
56
|
+
"""Create HTTPException from error response."""
|
|
57
|
+
if isinstance(error_data, dict):
|
|
58
|
+
detail = error_data.get("detail")
|
|
59
|
+
else:
|
|
60
|
+
detail = str(error_data)
|
|
61
|
+
|
|
62
|
+
return error_callable(detail)
|
|
63
|
+
|
|
64
|
+
def _print_welcome_message(self, username: str):
|
|
65
|
+
"""Print welcome message after login."""
|
|
66
|
+
print(f"Hey, {username}! You have been logged in...")
|
|
67
|
+
print(
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
██╗ ██╗███████╗ ██████╗████████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗██████╗ ██████╗ ███████╗ █████╗ ██╗
|
|
71
|
+
██║ ██║██╔════╝██╔════╝╚══██╔══╝██╔═══██╗██╔══██╗██╔══██╗██╔══██╗██║██╔══██╗██╔════╝ ██╔════╝ ██╔══██╗██║
|
|
72
|
+
██║ ██║█████╗ ██║ ██║ ██║ ██║██████╔╝██████╔╝██████╔╝██║██║ ██║██║ ███╗█████╗ ███████║██║
|
|
73
|
+
╚██╗ ██╔╝██╔══╝ ██║ ██║ ██║ ██║██╔══██╗██╔══██╗██╔══██╗██║██║ ██║██║ ██║██╔══╝ ██╔══██║██║
|
|
74
|
+
╚████╔╝ ███████╗╚██████╗ ██║ ╚██████╔╝██║ ██║██████╔╝██║ ██║██║██████╔╝╚██████╔╝███████╗██╗██║ ██║██║
|
|
75
|
+
╚═══╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝ ╚═╝╚═╝╚═════╝ ╚═════╝ ╚══════╝╚═╝╚═╝ ╚═╝╚═╝
|
|
76
|
+
DOCS: https://docs.vectorbridge.ai/ version: 0.0.1
|
|
77
|
+
|
|
78
|
+
"""
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class VectorBridgeClient(BaseVectorBridgeClient):
|
|
83
|
+
"""
|
|
84
|
+
Synchronous Python client for the VectorBridge.ai API.
|
|
85
|
+
|
|
86
|
+
Provides access to all functionality of the VectorBridge platform including
|
|
87
|
+
authentication, user management, AI processing, vector operations, and more.
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
def __init__(
|
|
91
|
+
self,
|
|
92
|
+
base_url: str = "http://vector_bridge:8000/",
|
|
93
|
+
api_key: str | None = None,
|
|
94
|
+
integration_name: str = "default",
|
|
95
|
+
):
|
|
96
|
+
"""
|
|
97
|
+
Initialize the VectorBridge client.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
base_url: The base URL of the VectorBridge API.
|
|
101
|
+
api_key: API key for authentication.
|
|
102
|
+
integration_name: Name of the integration.
|
|
103
|
+
"""
|
|
104
|
+
super().__init__(base_url, api_key, integration_name)
|
|
105
|
+
|
|
106
|
+
from vector_bridge.sync_io.admin import AdminClient
|
|
107
|
+
from vector_bridge.sync_io.client.ai_knowledge import AIKnowledge
|
|
108
|
+
from vector_bridge.sync_io.client.api_keys import APIKeysClient
|
|
109
|
+
from vector_bridge.sync_io.client.history import HistoryClient
|
|
110
|
+
from vector_bridge.sync_io.client.logs import LogsClient
|
|
111
|
+
from vector_bridge.sync_io.client.otp import OTPClient
|
|
112
|
+
from vector_bridge.sync_io.client.query import QueryClient
|
|
113
|
+
from vector_bridge.sync_io.client.usage import UsageClient
|
|
114
|
+
from vector_bridge.sync_io.client.user import UserClient
|
|
115
|
+
from vector_bridge.sync_io.client.workflows import WorkflowClient
|
|
116
|
+
|
|
117
|
+
self.session = requests.Session()
|
|
118
|
+
|
|
119
|
+
# Initialize client modules
|
|
120
|
+
self.admin = AdminClient(self)
|
|
121
|
+
self.api_keys = APIKeysClient(self)
|
|
122
|
+
self.ai_knowledge = AIKnowledge(self)
|
|
123
|
+
self.history = HistoryClient(self)
|
|
124
|
+
self.logs = LogsClient(self)
|
|
125
|
+
self.otp = OTPClient(self)
|
|
126
|
+
self.workflows = WorkflowClient(self)
|
|
127
|
+
self.queries = QueryClient(self)
|
|
128
|
+
self.users = UserClient(self)
|
|
129
|
+
self.usage = UsageClient(self)
|
|
130
|
+
|
|
131
|
+
def create_owner_with_organization(self, user: UserCreate, organization: OrganizationCreate) -> None:
|
|
132
|
+
"""
|
|
133
|
+
Create a new owner user and an associated organization.
|
|
134
|
+
|
|
135
|
+
This function first creates an owner user, then creates an organization
|
|
136
|
+
associated with that owner. Intended for bootstrapping a new organization
|
|
137
|
+
in the system.
|
|
138
|
+
|
|
139
|
+
Args:
|
|
140
|
+
user (UserCreate): The user data to create (will be forced to type=OWNER).
|
|
141
|
+
organization (OrganizationCreate): The organization details to create.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
None
|
|
145
|
+
"""
|
|
146
|
+
# Ensure user type is OWNER
|
|
147
|
+
user.user_type = UserType.OWNER
|
|
148
|
+
|
|
149
|
+
# Step 1: Create the owner user
|
|
150
|
+
user_url = f"{self.base_url}/v1/user/create-owner"
|
|
151
|
+
user_response = self.session.post(user_url, json=user.model_dump())
|
|
152
|
+
self._handle_response(response=user_response, error_callable=raise_for_base_error_detail)
|
|
153
|
+
|
|
154
|
+
self.login(username=user.email, password=user.password)
|
|
155
|
+
|
|
156
|
+
# Step 2: Create the organization
|
|
157
|
+
org_url = f"{self.base_url}/v1/admin/organization/create"
|
|
158
|
+
headers = self._get_auth_headers()
|
|
159
|
+
org_response = self.session.post(org_url, headers=headers, json=organization.model_dump())
|
|
160
|
+
self._handle_response(response=org_response, error_callable=raise_for_base_error_detail)
|
|
161
|
+
|
|
162
|
+
def login(self, username: str, password: str) -> Token:
|
|
163
|
+
"""
|
|
164
|
+
Log in to obtain an access token.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
username: User's email
|
|
168
|
+
password: User's password
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
Token object containing access_token and token_type
|
|
172
|
+
"""
|
|
173
|
+
url = f"{self.base_url}/token"
|
|
174
|
+
data = {
|
|
175
|
+
"username": username,
|
|
176
|
+
"password": password,
|
|
177
|
+
}
|
|
178
|
+
response = self.session.post(
|
|
179
|
+
url,
|
|
180
|
+
data=data,
|
|
181
|
+
headers={"Content-Type": "application/x-www-form-urlencoded"},
|
|
182
|
+
)
|
|
183
|
+
result = self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
184
|
+
self.access_token = result["access_token"]
|
|
185
|
+
|
|
186
|
+
self._print_welcome_message(username)
|
|
187
|
+
|
|
188
|
+
return Token(**result)
|
|
189
|
+
|
|
190
|
+
def _handle_response(self, response: requests.Response, error_callable: Callable) -> Any:
|
|
191
|
+
"""Handle API response and errors."""
|
|
192
|
+
if 200 <= response.status_code < 300:
|
|
193
|
+
if response.status_code == 204:
|
|
194
|
+
return None
|
|
195
|
+
try:
|
|
196
|
+
return response.json()
|
|
197
|
+
except ValueError:
|
|
198
|
+
return response.text
|
|
199
|
+
else:
|
|
200
|
+
try:
|
|
201
|
+
error_data = response.json()
|
|
202
|
+
except ValueError:
|
|
203
|
+
error_data = response.text
|
|
204
|
+
|
|
205
|
+
exc = self._create_http_exception(response.status_code, error_data, error_callable)
|
|
206
|
+
raise exc
|
|
207
|
+
|
|
208
|
+
def ping(self) -> str:
|
|
209
|
+
"""
|
|
210
|
+
Ping the API to check if it's available.
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Response string
|
|
214
|
+
"""
|
|
215
|
+
url = f"{self.base_url}/v1/ping"
|
|
216
|
+
response = self.session.get(url)
|
|
217
|
+
return self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
218
|
+
|
|
219
|
+
def generate_crypto_key(self) -> str:
|
|
220
|
+
"""
|
|
221
|
+
Generate a crypto key.
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Generated crypto key
|
|
225
|
+
"""
|
|
226
|
+
url = f"{self.base_url}/v1/secrets/generate-crypto-key"
|
|
227
|
+
response = self.session.get(url)
|
|
228
|
+
return self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
229
|
+
|
|
230
|
+
def check_db_connection(self, weaviate_url: str, weaviate_api_key: str) -> dict:
|
|
231
|
+
"""
|
|
232
|
+
Check database connection.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
weaviate_url: The VectorDB URL
|
|
236
|
+
weaviate_api_key: The VectorDB API key
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
Connection check response
|
|
240
|
+
"""
|
|
241
|
+
url = f"{self.base_url}/v1/check/db_connection"
|
|
242
|
+
data = {"url": weaviate_url, "api_key": weaviate_api_key}
|
|
243
|
+
response = self.session.post(url, json=data)
|
|
244
|
+
return self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
245
|
+
|
|
246
|
+
def close(self):
|
|
247
|
+
"""Close the session."""
|
|
248
|
+
self.session.close()
|
|
249
|
+
|
|
250
|
+
def __enter__(self):
|
|
251
|
+
return self
|
|
252
|
+
|
|
253
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
254
|
+
self.close()
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class AsyncVectorBridgeClient(BaseVectorBridgeClient):
|
|
258
|
+
"""
|
|
259
|
+
Asynchronous Python client for the VectorBridge.ai API.
|
|
260
|
+
|
|
261
|
+
Provides async access to all functionality of the VectorBridge platform including
|
|
262
|
+
authentication, user management, AI processing, vector operations, and more.
|
|
263
|
+
"""
|
|
264
|
+
|
|
265
|
+
def __init__(
|
|
266
|
+
self,
|
|
267
|
+
base_url: str = "http://vector_bridge:8000/",
|
|
268
|
+
api_key: str | None = None,
|
|
269
|
+
integration_name: str = "default",
|
|
270
|
+
connector: aiohttp.BaseConnector | None = None,
|
|
271
|
+
timeout: aiohttp.ClientTimeout | None = None,
|
|
272
|
+
):
|
|
273
|
+
"""
|
|
274
|
+
Initialize the async VectorBridge client.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
base_url: The base URL of the VectorBridge API.
|
|
278
|
+
api_key: API key for authentication.
|
|
279
|
+
integration_name: Name of the integration.
|
|
280
|
+
connector: aiohttp connector for custom connection handling.
|
|
281
|
+
timeout: Timeout configuration for requests.
|
|
282
|
+
"""
|
|
283
|
+
super().__init__(base_url, api_key, integration_name)
|
|
284
|
+
|
|
285
|
+
from vector_bridge.async_io.admin import AsyncAdminClient
|
|
286
|
+
from vector_bridge.async_io.admin.api_keys import AsyncAPIKeys
|
|
287
|
+
from vector_bridge.async_io.client.ai_knowledge import AsyncAIKnowledge
|
|
288
|
+
from vector_bridge.async_io.client.history import AsyncHistoryClient
|
|
289
|
+
from vector_bridge.async_io.client.logs import AsyncLogsClient
|
|
290
|
+
from vector_bridge.async_io.client.otp import AsyncOTPClient
|
|
291
|
+
from vector_bridge.async_io.client.query import AsyncQueryClient
|
|
292
|
+
from vector_bridge.async_io.client.usage import AsyncUsageClient
|
|
293
|
+
from vector_bridge.async_io.client.user import AsyncUserClient
|
|
294
|
+
from vector_bridge.async_io.client.workflows import AsyncWorkflowClient
|
|
295
|
+
|
|
296
|
+
self.session = None
|
|
297
|
+
self._connector = connector
|
|
298
|
+
self._timeout = timeout or aiohttp.ClientTimeout(total=30)
|
|
299
|
+
|
|
300
|
+
# Initialize async client modules
|
|
301
|
+
if AsyncAdminClient:
|
|
302
|
+
self.admin = AsyncAdminClient(self)
|
|
303
|
+
self.api_keys = AsyncAPIKeys(self)
|
|
304
|
+
self.ai_knowledge = AsyncAIKnowledge(self)
|
|
305
|
+
self.history = AsyncHistoryClient(self)
|
|
306
|
+
self.logs = AsyncLogsClient(self)
|
|
307
|
+
self.otp = AsyncOTPClient(self)
|
|
308
|
+
self.workflows = AsyncWorkflowClient(self)
|
|
309
|
+
self.queries = AsyncQueryClient(self)
|
|
310
|
+
self.users = AsyncUserClient(self)
|
|
311
|
+
self.usage = AsyncUsageClient(self)
|
|
312
|
+
|
|
313
|
+
async def __aenter__(self):
|
|
314
|
+
"""Async context manager entry."""
|
|
315
|
+
await self._ensure_session()
|
|
316
|
+
return self
|
|
317
|
+
|
|
318
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
319
|
+
"""Async context manager exit."""
|
|
320
|
+
await self.close()
|
|
321
|
+
|
|
322
|
+
async def _ensure_session(self):
|
|
323
|
+
"""Ensure aiohttp session is created."""
|
|
324
|
+
if self.session is None:
|
|
325
|
+
self.session = aiohttp.ClientSession(connector=self._connector, timeout=self._timeout)
|
|
326
|
+
|
|
327
|
+
async def create_owner_with_organization(self, user: UserCreate, organization: OrganizationCreate) -> None:
|
|
328
|
+
"""
|
|
329
|
+
Create a new owner user and an associated organization (async).
|
|
330
|
+
|
|
331
|
+
This function first creates an owner user, then creates an organization
|
|
332
|
+
associated with that owner. Intended for bootstrapping a new organization
|
|
333
|
+
in the system.
|
|
334
|
+
|
|
335
|
+
Args:
|
|
336
|
+
user (UserCreate): The user data to create (will be forced to type=OWNER).
|
|
337
|
+
organization (OrganizationCreate): The organization details to create.
|
|
338
|
+
|
|
339
|
+
Returns:
|
|
340
|
+
None
|
|
341
|
+
"""
|
|
342
|
+
await self._ensure_session()
|
|
343
|
+
|
|
344
|
+
# Ensure user type is OWNER
|
|
345
|
+
user.user_type = UserType.OWNER
|
|
346
|
+
|
|
347
|
+
# Step 1: Create the owner user
|
|
348
|
+
user_url = f"{self.base_url}/v1/user/create-owner"
|
|
349
|
+
async with self.session.post(user_url, json=user.model_dump()) as response:
|
|
350
|
+
await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
351
|
+
|
|
352
|
+
await self.login(username=user.email, password=user.password)
|
|
353
|
+
|
|
354
|
+
# Step 2: Create the organization
|
|
355
|
+
org_url = f"{self.base_url}/v1/admin/organization/create"
|
|
356
|
+
headers = self._get_auth_headers()
|
|
357
|
+
async with self.session.post(org_url, headers=headers, json=organization.model_dump()) as response:
|
|
358
|
+
await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
359
|
+
|
|
360
|
+
async def login(self, username: str, password: str) -> Token:
|
|
361
|
+
"""
|
|
362
|
+
Log in to obtain an access token.
|
|
363
|
+
|
|
364
|
+
Args:
|
|
365
|
+
username: User's email
|
|
366
|
+
password: User's password
|
|
367
|
+
|
|
368
|
+
Returns:
|
|
369
|
+
Token object containing access_token and token_type
|
|
370
|
+
"""
|
|
371
|
+
await self._ensure_session()
|
|
372
|
+
|
|
373
|
+
url = f"{self.base_url}/token"
|
|
374
|
+
data = aiohttp.FormData()
|
|
375
|
+
data.add_field("username", username)
|
|
376
|
+
data.add_field("password", password)
|
|
377
|
+
|
|
378
|
+
async with self.session.post(url, data=data) as response:
|
|
379
|
+
result = await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
380
|
+
self.access_token = result["access_token"]
|
|
381
|
+
|
|
382
|
+
# Print welcome message in sync context (or make it optional)
|
|
383
|
+
self._print_welcome_message(username)
|
|
384
|
+
|
|
385
|
+
return Token(**result)
|
|
386
|
+
|
|
387
|
+
async def _handle_response(self, response: aiohttp.ClientResponse, error_callable: Callable) -> Any:
|
|
388
|
+
"""Handle async API response and errors."""
|
|
389
|
+
if 200 <= response.status < 300:
|
|
390
|
+
if response.status == 204:
|
|
391
|
+
return None
|
|
392
|
+
try:
|
|
393
|
+
return await response.json()
|
|
394
|
+
except (ValueError, aiohttp.ContentTypeError):
|
|
395
|
+
return await response.text()
|
|
396
|
+
else:
|
|
397
|
+
try:
|
|
398
|
+
error_data = await response.json()
|
|
399
|
+
except (ValueError, aiohttp.ContentTypeError):
|
|
400
|
+
error_data = await response.text()
|
|
401
|
+
|
|
402
|
+
exc = self._create_http_exception(response.status, error_data, error_callable)
|
|
403
|
+
raise exc
|
|
404
|
+
|
|
405
|
+
async def ping(self) -> str:
|
|
406
|
+
"""
|
|
407
|
+
Ping the API to check if it's available.
|
|
408
|
+
|
|
409
|
+
Returns:
|
|
410
|
+
Response string
|
|
411
|
+
"""
|
|
412
|
+
await self._ensure_session()
|
|
413
|
+
|
|
414
|
+
url = f"{self.base_url}/v1/ping"
|
|
415
|
+
async with self.session.get(url) as response:
|
|
416
|
+
return await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
417
|
+
|
|
418
|
+
async def generate_crypto_key(self) -> str:
|
|
419
|
+
"""
|
|
420
|
+
Generate a crypto key.
|
|
421
|
+
|
|
422
|
+
Returns:
|
|
423
|
+
Generated crypto key
|
|
424
|
+
"""
|
|
425
|
+
await self._ensure_session()
|
|
426
|
+
|
|
427
|
+
url = f"{self.base_url}/v1/secrets/generate-crypto-key"
|
|
428
|
+
async with self.session.get(url) as response:
|
|
429
|
+
return await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
430
|
+
|
|
431
|
+
async def check_db_connection(self, weaviate_url: str, weaviate_api_key: str) -> dict:
|
|
432
|
+
"""
|
|
433
|
+
Check database connection.
|
|
434
|
+
|
|
435
|
+
Args:
|
|
436
|
+
weaviate_url: The VectorDB URL
|
|
437
|
+
weaviate_api_key: The VectorDB API key
|
|
438
|
+
|
|
439
|
+
Returns:
|
|
440
|
+
Connection check response
|
|
441
|
+
"""
|
|
442
|
+
await self._ensure_session()
|
|
443
|
+
|
|
444
|
+
url = f"{self.base_url}/v1/check/db_connection"
|
|
445
|
+
data = {"url": weaviate_url, "api_key": weaviate_api_key}
|
|
446
|
+
async with self.session.post(url, json=data) as response:
|
|
447
|
+
return await self._handle_response(response=response, error_callable=raise_for_base_error_detail)
|
|
448
|
+
|
|
449
|
+
async def close(self):
|
|
450
|
+
"""Close the async session."""
|
|
451
|
+
if self.session and not self.session.closed:
|
|
452
|
+
await self.session.close()
|
|
453
|
+
self.session = None
|
|
454
|
+
|
|
455
|
+
|
|
456
|
+
# Factory function for easier client creation
|
|
457
|
+
def create_client(
|
|
458
|
+
base_url: str = "http://vector_bridge:8000/",
|
|
459
|
+
api_key: str | None = None,
|
|
460
|
+
integration_name: str = "default",
|
|
461
|
+
async_client: bool = False,
|
|
462
|
+
**kwargs,
|
|
463
|
+
) -> VectorBridgeClient | AsyncVectorBridgeClient:
|
|
464
|
+
"""
|
|
465
|
+
Factory function to create either sync or async VectorBridge client.
|
|
466
|
+
|
|
467
|
+
Args:
|
|
468
|
+
base_url: The base URL of the VectorBridge API.
|
|
469
|
+
api_key: API key for authentication.
|
|
470
|
+
integration_name: Name of the integration.
|
|
471
|
+
async_client: If True, returns AsyncVectorBridgeClient, otherwise VectorBridgeClient.
|
|
472
|
+
**kwargs: Additional arguments passed to the client constructor.
|
|
473
|
+
|
|
474
|
+
Returns:
|
|
475
|
+
VectorBridgeClient or AsyncVectorBridgeClient instance.
|
|
476
|
+
"""
|
|
477
|
+
if async_client:
|
|
478
|
+
return AsyncVectorBridgeClient(
|
|
479
|
+
base_url=base_url,
|
|
480
|
+
api_key=api_key,
|
|
481
|
+
integration_name=integration_name,
|
|
482
|
+
**kwargs,
|
|
483
|
+
)
|
|
484
|
+
else:
|
|
485
|
+
return VectorBridgeClient(
|
|
486
|
+
base_url=base_url,
|
|
487
|
+
api_key=api_key,
|
|
488
|
+
integration_name=integration_name,
|
|
489
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from vector_bridge import AsyncVectorBridgeClient
|
|
2
|
+
from vector_bridge.async_io.admin.integrations import AsyncIntegrationsAdmin
|
|
3
|
+
from vector_bridge.async_io.admin.organization import AsyncOrganizationAdmin
|
|
4
|
+
from vector_bridge.async_io.admin.security_groups import AsyncSecurityGroupsAdmin
|
|
5
|
+
from vector_bridge.async_io.admin.settings import AsyncSettingsAdmin
|
|
6
|
+
from vector_bridge.async_io.admin.vector_db import AsyncVectorDBAdmin
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class AsyncAdminClient:
|
|
10
|
+
"""Async admin client providing access to all admin endpoints that require authentication."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, client: AsyncVectorBridgeClient):
|
|
13
|
+
self.client = client
|
|
14
|
+
|
|
15
|
+
# Initialize async admin subclients
|
|
16
|
+
self.settings = AsyncSettingsAdmin(client)
|
|
17
|
+
self.organization = AsyncOrganizationAdmin(client)
|
|
18
|
+
self.security_groups = AsyncSecurityGroupsAdmin(client)
|
|
19
|
+
self.integrations = AsyncIntegrationsAdmin(client)
|
|
20
|
+
self.vector_db = AsyncVectorDBAdmin(client)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from vector_bridge import AsyncVectorBridgeClient
|
|
2
|
+
from vector_bridge.schema.api_keys import APIKey, APIKeyCreate
|
|
3
|
+
from vector_bridge.schema.errors.api_keys import raise_for_api_key_detail
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AsyncAPIKeys:
|
|
7
|
+
"""Async client for API keys management endpoints."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, client: AsyncVectorBridgeClient):
|
|
10
|
+
self.client = client
|
|
11
|
+
|
|
12
|
+
async def create_api_key(self, api_key_data: APIKeyCreate) -> APIKey:
|
|
13
|
+
"""
|
|
14
|
+
Create a new API key for integrations.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
api_key_data: Details for the API key to create
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
Created API key
|
|
21
|
+
"""
|
|
22
|
+
await self.client._ensure_session()
|
|
23
|
+
|
|
24
|
+
url = f"{self.client.base_url}/v1/api_key/create"
|
|
25
|
+
headers = self.client._get_auth_headers()
|
|
26
|
+
|
|
27
|
+
async with self.client.session.post(url, headers=headers, json=api_key_data.model_dump()) as response:
|
|
28
|
+
result = await self.client._handle_response(response=response, error_callable=raise_for_api_key_detail)
|
|
29
|
+
return APIKey.model_validate(result)
|
|
30
|
+
|
|
31
|
+
async def get_api_key(self, api_key: str) -> APIKey:
|
|
32
|
+
"""
|
|
33
|
+
Retrieve details about a specific API key.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
api_key: The API key
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
API key details
|
|
40
|
+
"""
|
|
41
|
+
await self.client._ensure_session()
|
|
42
|
+
|
|
43
|
+
url = f"{self.client.base_url}/v1/api_key/{api_key}"
|
|
44
|
+
headers = self.client._get_auth_headers()
|
|
45
|
+
|
|
46
|
+
async with self.client.session.get(url, headers=headers) as response:
|
|
47
|
+
result = await self.client._handle_response(response=response, error_callable=raise_for_api_key_detail)
|
|
48
|
+
return APIKey.model_validate(result)
|
|
49
|
+
|
|
50
|
+
async def delete_api_key(self, api_key: str) -> None:
|
|
51
|
+
"""
|
|
52
|
+
Delete an API key.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
api_key: The API key to delete
|
|
56
|
+
"""
|
|
57
|
+
await self.client._ensure_session()
|
|
58
|
+
|
|
59
|
+
url = f"{self.client.base_url}/v1/api_key/{api_key}"
|
|
60
|
+
headers = self.client._get_auth_headers()
|
|
61
|
+
|
|
62
|
+
async with self.client.session.delete(url, headers=headers) as response:
|
|
63
|
+
if response.status != 204:
|
|
64
|
+
await self.client._handle_response(response=response, error_callable=raise_for_api_key_detail)
|
|
65
|
+
|
|
66
|
+
async def list_api_keys(self, integration_name: str | None = None) -> list[APIKey]:
|
|
67
|
+
"""
|
|
68
|
+
List all API keys.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
integration_name: Specifies the name of the integration module being queried
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of API keys
|
|
75
|
+
"""
|
|
76
|
+
await self.client._ensure_session()
|
|
77
|
+
|
|
78
|
+
url = f"{self.client.base_url}/v1/api_keys"
|
|
79
|
+
params = {}
|
|
80
|
+
if integration_name:
|
|
81
|
+
params["integration_name"] = integration_name
|
|
82
|
+
|
|
83
|
+
headers = self.client._get_auth_headers()
|
|
84
|
+
|
|
85
|
+
async with self.client.session.get(url, headers=headers, params=params) as response:
|
|
86
|
+
results = await self.client._handle_response(response=response, error_callable=raise_for_api_key_detail)
|
|
87
|
+
return [APIKey.model_validate(result) for result in results]
|