trustgraph-base 2.2.3__tar.gz → 2.2.4__tar.gz
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.
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/PKG-INFO +1 -1
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/async_socket_client.py +138 -69
- trustgraph_base-2.2.4/trustgraph/api/socket_client.py +892 -0
- trustgraph_base-2.2.4/trustgraph/base_version.py +1 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph_base.egg-info/PKG-INFO +1 -1
- trustgraph_base-2.2.3/trustgraph/api/socket_client.py +0 -1478
- trustgraph_base-2.2.3/trustgraph/base_version.py +0 -1
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/README.md +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/pyproject.toml +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/setup.cfg +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/api.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/async_bulk_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/async_flow.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/async_metrics.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/bulk_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/collection.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/config.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/exceptions.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/explainability.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/flow.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/knowledge.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/library.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/metrics.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/api/types.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/agent_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/agent_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/async_processor.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/backend.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/cassandra_config.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/chunking_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/collection_config_handler.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/consumer.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/consumer_spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/document_embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/document_embeddings_query_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/document_embeddings_store_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/dynamic_tool_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/embeddings_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/flow.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/flow_processor.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/graph_embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/graph_embeddings_query_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/graph_embeddings_store_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/graph_rag_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/llm_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/logging.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/metrics.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/parameter_spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/producer.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/producer_spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/prompt_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/publisher.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/pubsub.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/pulsar_backend.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/request_response_spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/row_embeddings_query_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/structured_query_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/subscriber.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/subscriber_spec.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/text_completion_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/tool_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/tool_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/tool_service_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/triples_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/triples_query_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/base/triples_store_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/agent_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/base.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/config_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/document_embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/document_rag_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/graph_embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/graph_rag_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/llm_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/prompt_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/row_embeddings_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/clients/triples_query_client.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/exceptions.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/defs.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/document.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/identifier.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/organization.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/knowledge/publication.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/log_level.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/registry.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/agent.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/base.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/collection.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/config.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/diagnosis.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/document_loading.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/embeddings.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/embeddings_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/flow.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/knowledge.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/library.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/metadata.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/nlp_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/primitives.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/prompt.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/retrieval.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/rows_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/structured_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/text_completion.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/tool.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/messaging/translators/triples.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/objects/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/objects/field.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/objects/object.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/agent.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/namespaces.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/triples.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/uris.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/provenance/vocabulary.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/rdf.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/core/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/core/metadata.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/core/primitives.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/core/topic.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/document.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/embeddings.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/graph.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/knowledge.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/nlp.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/object.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/rows.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/knowledge/structured.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/__init__.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/agent.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/collection.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/config.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/diagnosis.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/flow.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/library.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/llm.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/lookup.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/nlp_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/prompt.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/retrieval.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/rows_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/storage.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/structured_query.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph/schema/services/tool_service.py +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph_base.egg-info/SOURCES.txt +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph_base.egg-info/dependency_links.txt +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph_base.egg-info/requires.txt +0 -0
- {trustgraph_base-2.2.3 → trustgraph_base-2.2.4}/trustgraph_base.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: trustgraph-base
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.4
|
|
4
4
|
Summary: TrustGraph provides a means to run a pipeline of flexible AI processing components in a flexible means to achieve a processing pipeline.
|
|
5
5
|
Author-email: "trustgraph.ai" <security@trustgraph.ai>
|
|
6
6
|
Project-URL: Homepage, https://github.com/trustgraph-ai/trustgraph
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import json
|
|
3
|
+
import asyncio
|
|
3
4
|
import websockets
|
|
4
5
|
from typing import Optional, Dict, Any, AsyncIterator, Union
|
|
5
6
|
|
|
@@ -8,13 +9,29 @@ from . exceptions import ProtocolException, ApplicationException
|
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class AsyncSocketClient:
|
|
11
|
-
"""Asynchronous WebSocket client
|
|
12
|
+
"""Asynchronous WebSocket client with persistent connection.
|
|
13
|
+
|
|
14
|
+
Maintains a single websocket connection and multiplexes requests
|
|
15
|
+
by ID, routing responses via a background reader task.
|
|
16
|
+
|
|
17
|
+
Use as an async context manager for proper lifecycle management:
|
|
18
|
+
|
|
19
|
+
async with AsyncSocketClient(url, timeout, token) as client:
|
|
20
|
+
result = await client._send_request(...)
|
|
21
|
+
|
|
22
|
+
Or call connect()/aclose() manually.
|
|
23
|
+
"""
|
|
12
24
|
|
|
13
25
|
def __init__(self, url: str, timeout: int, token: Optional[str]):
|
|
14
26
|
self.url = self._convert_to_ws_url(url)
|
|
15
27
|
self.timeout = timeout
|
|
16
28
|
self.token = token
|
|
17
29
|
self._request_counter = 0
|
|
30
|
+
self._socket = None
|
|
31
|
+
self._connect_cm = None
|
|
32
|
+
self._reader_task = None
|
|
33
|
+
self._pending = {} # request_id -> asyncio.Queue
|
|
34
|
+
self._connected = False
|
|
18
35
|
|
|
19
36
|
def _convert_to_ws_url(self, url: str) -> str:
|
|
20
37
|
"""Convert HTTP URL to WebSocket URL"""
|
|
@@ -25,82 +42,123 @@ class AsyncSocketClient:
|
|
|
25
42
|
elif url.startswith("ws://") or url.startswith("wss://"):
|
|
26
43
|
return url
|
|
27
44
|
else:
|
|
28
|
-
# Assume ws://
|
|
29
45
|
return f"ws://{url}"
|
|
30
46
|
|
|
47
|
+
def _build_ws_url(self):
|
|
48
|
+
ws_url = f"{self.url.rstrip('/')}/api/v1/socket"
|
|
49
|
+
if self.token:
|
|
50
|
+
ws_url = f"{ws_url}?token={self.token}"
|
|
51
|
+
return ws_url
|
|
52
|
+
|
|
53
|
+
async def connect(self):
|
|
54
|
+
"""Establish the persistent websocket connection."""
|
|
55
|
+
if self._connected:
|
|
56
|
+
return
|
|
57
|
+
|
|
58
|
+
ws_url = self._build_ws_url()
|
|
59
|
+
self._connect_cm = websockets.connect(
|
|
60
|
+
ws_url, ping_interval=20, ping_timeout=self.timeout
|
|
61
|
+
)
|
|
62
|
+
self._socket = await self._connect_cm.__aenter__()
|
|
63
|
+
self._connected = True
|
|
64
|
+
self._reader_task = asyncio.create_task(self._reader())
|
|
65
|
+
|
|
66
|
+
async def __aenter__(self):
|
|
67
|
+
await self.connect()
|
|
68
|
+
return self
|
|
69
|
+
|
|
70
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
|
71
|
+
await self.aclose()
|
|
72
|
+
|
|
73
|
+
async def _ensure_connected(self):
|
|
74
|
+
"""Lazily connect if not already connected."""
|
|
75
|
+
if not self._connected:
|
|
76
|
+
await self.connect()
|
|
77
|
+
|
|
78
|
+
async def _reader(self):
|
|
79
|
+
"""Background task to read responses and route by request ID."""
|
|
80
|
+
try:
|
|
81
|
+
async for raw_message in self._socket:
|
|
82
|
+
response = json.loads(raw_message)
|
|
83
|
+
request_id = response.get("id")
|
|
84
|
+
|
|
85
|
+
if request_id and request_id in self._pending:
|
|
86
|
+
await self._pending[request_id].put(response)
|
|
87
|
+
# Ignore messages for unknown request IDs
|
|
88
|
+
|
|
89
|
+
except websockets.exceptions.ConnectionClosed:
|
|
90
|
+
pass
|
|
91
|
+
except Exception as e:
|
|
92
|
+
# Signal error to all pending requests
|
|
93
|
+
for queue in self._pending.values():
|
|
94
|
+
try:
|
|
95
|
+
await queue.put({"error": str(e)})
|
|
96
|
+
except:
|
|
97
|
+
pass
|
|
98
|
+
finally:
|
|
99
|
+
self._connected = False
|
|
100
|
+
|
|
101
|
+
def _next_request_id(self):
|
|
102
|
+
self._request_counter += 1
|
|
103
|
+
return f"req-{self._request_counter}"
|
|
104
|
+
|
|
31
105
|
def flow(self, flow_id: str):
|
|
32
106
|
"""Get async flow instance for WebSocket operations"""
|
|
33
107
|
return AsyncSocketFlowInstance(self, flow_id)
|
|
34
108
|
|
|
35
109
|
async def _send_request(self, service: str, flow: Optional[str], request: Dict[str, Any]):
|
|
36
|
-
"""
|
|
37
|
-
|
|
38
|
-
self._request_counter += 1
|
|
39
|
-
request_id = f"req-{self._request_counter}"
|
|
40
|
-
|
|
41
|
-
# Build WebSocket URL with optional token
|
|
42
|
-
ws_url = f"{self.url}/api/v1/socket"
|
|
43
|
-
if self.token:
|
|
44
|
-
ws_url = f"{ws_url}?token={self.token}"
|
|
110
|
+
"""Send a request and wait for a single response."""
|
|
111
|
+
await self._ensure_connected()
|
|
45
112
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"service": service,
|
|
50
|
-
"request": request
|
|
51
|
-
}
|
|
52
|
-
if flow:
|
|
53
|
-
message["flow"] = flow
|
|
113
|
+
request_id = self._next_request_id()
|
|
114
|
+
queue = asyncio.Queue()
|
|
115
|
+
self._pending[request_id] = queue
|
|
54
116
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
117
|
+
try:
|
|
118
|
+
message = {
|
|
119
|
+
"id": request_id,
|
|
120
|
+
"service": service,
|
|
121
|
+
"request": request
|
|
122
|
+
}
|
|
123
|
+
if flow:
|
|
124
|
+
message["flow"] = flow
|
|
58
125
|
|
|
59
|
-
|
|
60
|
-
raw_message = await websocket.recv()
|
|
61
|
-
response = json.loads(raw_message)
|
|
126
|
+
await self._socket.send(json.dumps(message))
|
|
62
127
|
|
|
63
|
-
|
|
64
|
-
raise ProtocolException(f"Response ID mismatch")
|
|
128
|
+
response = await queue.get()
|
|
65
129
|
|
|
66
130
|
if "error" in response:
|
|
67
131
|
raise ApplicationException(response["error"])
|
|
68
132
|
|
|
69
133
|
if "response" not in response:
|
|
70
|
-
raise ProtocolException(
|
|
134
|
+
raise ProtocolException("Missing response in message")
|
|
71
135
|
|
|
72
136
|
return response["response"]
|
|
73
137
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# Generate unique request ID
|
|
77
|
-
self._request_counter += 1
|
|
78
|
-
request_id = f"req-{self._request_counter}"
|
|
138
|
+
finally:
|
|
139
|
+
self._pending.pop(request_id, None)
|
|
79
140
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
ws_url = f"{ws_url}?token={self.token}"
|
|
141
|
+
async def _send_request_streaming(self, service: str, flow: Optional[str], request: Dict[str, Any]):
|
|
142
|
+
"""Send a request and yield streaming response chunks."""
|
|
143
|
+
await self._ensure_connected()
|
|
84
144
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"service": service,
|
|
89
|
-
"request": request
|
|
90
|
-
}
|
|
91
|
-
if flow:
|
|
92
|
-
message["flow"] = flow
|
|
145
|
+
request_id = self._next_request_id()
|
|
146
|
+
queue = asyncio.Queue()
|
|
147
|
+
self._pending[request_id] = queue
|
|
93
148
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
149
|
+
try:
|
|
150
|
+
message = {
|
|
151
|
+
"id": request_id,
|
|
152
|
+
"service": service,
|
|
153
|
+
"request": request
|
|
154
|
+
}
|
|
155
|
+
if flow:
|
|
156
|
+
message["flow"] = flow
|
|
97
157
|
|
|
98
|
-
|
|
99
|
-
async for raw_message in websocket:
|
|
100
|
-
response = json.loads(raw_message)
|
|
158
|
+
await self._socket.send(json.dumps(message))
|
|
101
159
|
|
|
102
|
-
|
|
103
|
-
|
|
160
|
+
while True:
|
|
161
|
+
response = await queue.get()
|
|
104
162
|
|
|
105
163
|
if "error" in response:
|
|
106
164
|
raise ApplicationException(response["error"])
|
|
@@ -108,18 +166,16 @@ class AsyncSocketClient:
|
|
|
108
166
|
if "response" in response:
|
|
109
167
|
resp = response["response"]
|
|
110
168
|
|
|
111
|
-
# Parse different chunk types
|
|
112
169
|
chunk = self._parse_chunk(resp)
|
|
113
|
-
if chunk is not None:
|
|
170
|
+
if chunk is not None:
|
|
114
171
|
yield chunk
|
|
115
172
|
|
|
116
|
-
# Check if this is the final message
|
|
117
|
-
# end_of_session indicates entire session is complete (including provenance)
|
|
118
|
-
# end_of_dialog is for agent dialogs
|
|
119
|
-
# complete is from the gateway envelope
|
|
120
173
|
if resp.get("end_of_session") or resp.get("end_of_dialog") or response.get("complete"):
|
|
121
174
|
break
|
|
122
175
|
|
|
176
|
+
finally:
|
|
177
|
+
self._pending.pop(request_id, None)
|
|
178
|
+
|
|
123
179
|
def _parse_chunk(self, resp: Dict[str, Any]):
|
|
124
180
|
"""Parse response chunk into appropriate type. Returns None for non-content messages."""
|
|
125
181
|
chunk_type = resp.get("chunk_type")
|
|
@@ -127,7 +183,6 @@ class AsyncSocketClient:
|
|
|
127
183
|
|
|
128
184
|
# Handle new GraphRAG message format with message_type
|
|
129
185
|
if message_type == "provenance":
|
|
130
|
-
# Provenance messages are not yielded to user - they're metadata
|
|
131
186
|
return None
|
|
132
187
|
|
|
133
188
|
if chunk_type == "thought":
|
|
@@ -147,25 +202,41 @@ class AsyncSocketClient:
|
|
|
147
202
|
end_of_dialog=resp.get("end_of_dialog", False)
|
|
148
203
|
)
|
|
149
204
|
elif chunk_type == "action":
|
|
150
|
-
# Agent action chunks - treat as thoughts for display purposes
|
|
151
205
|
return AgentThought(
|
|
152
206
|
content=resp.get("content", ""),
|
|
153
207
|
end_of_message=resp.get("end_of_message", False)
|
|
154
208
|
)
|
|
155
209
|
else:
|
|
156
|
-
# RAG-style chunk (or generic chunk with message_type="chunk")
|
|
157
|
-
# Text-completion uses "response" field, RAG uses "chunk" field, Prompt uses "text" field
|
|
158
210
|
content = resp.get("response", resp.get("chunk", resp.get("text", "")))
|
|
159
211
|
return RAGChunk(
|
|
160
212
|
content=content,
|
|
161
213
|
end_of_stream=resp.get("end_of_stream", False),
|
|
162
|
-
error=None
|
|
214
|
+
error=None
|
|
163
215
|
)
|
|
164
216
|
|
|
165
217
|
async def aclose(self):
|
|
166
|
-
"""Close WebSocket connection"""
|
|
167
|
-
#
|
|
168
|
-
|
|
218
|
+
"""Close the persistent WebSocket connection cleanly."""
|
|
219
|
+
# Wait for reader to finish (socket close will cause it to exit)
|
|
220
|
+
if self._reader_task:
|
|
221
|
+
self._reader_task.cancel()
|
|
222
|
+
try:
|
|
223
|
+
await self._reader_task
|
|
224
|
+
except asyncio.CancelledError:
|
|
225
|
+
pass
|
|
226
|
+
self._reader_task = None
|
|
227
|
+
|
|
228
|
+
# Exit the websockets context manager — this cleanly shuts down
|
|
229
|
+
# the connection and its keepalive task
|
|
230
|
+
if self._connect_cm:
|
|
231
|
+
try:
|
|
232
|
+
await self._connect_cm.__aexit__(None, None, None)
|
|
233
|
+
except Exception:
|
|
234
|
+
pass
|
|
235
|
+
self._connect_cm = None
|
|
236
|
+
|
|
237
|
+
self._socket = None
|
|
238
|
+
self._connected = False
|
|
239
|
+
self._pending.clear()
|
|
169
240
|
|
|
170
241
|
|
|
171
242
|
class AsyncSocketFlowInstance:
|
|
@@ -292,7 +363,6 @@ class AsyncSocketFlowInstance:
|
|
|
292
363
|
|
|
293
364
|
async def graph_embeddings_query(self, text: str, user: str, collection: str, limit: int = 10, **kwargs):
|
|
294
365
|
"""Query graph embeddings for semantic search"""
|
|
295
|
-
# First convert text to embedding vector
|
|
296
366
|
emb_result = await self.embeddings(texts=[text])
|
|
297
367
|
vector = emb_result.get("vectors", [[]])[0]
|
|
298
368
|
|
|
@@ -362,7 +432,6 @@ class AsyncSocketFlowInstance:
|
|
|
362
432
|
limit: int = 10, **kwargs
|
|
363
433
|
):
|
|
364
434
|
"""Query row embeddings for semantic search on structured data"""
|
|
365
|
-
# First convert text to embedding vector
|
|
366
435
|
emb_result = await self.embeddings(texts=[text])
|
|
367
436
|
vector = emb_result.get("vectors", [[]])[0]
|
|
368
437
|
|