agent-lab-sdk 0.1.42.1__tar.gz → 0.1.43__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.
Potentially problematic release.
This version of agent-lab-sdk might be problematic. Click here for more details.
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/PKG-INFO +1 -1
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/agw_saver.py +58 -17
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/PKG-INFO +1 -1
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/pyproject.toml +1 -1
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/LICENSE +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/README.md +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/serde.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/agw_token_manager.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/gigachat_token_manager.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/llm.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/throttled.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/metrics.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/input_types.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/log_message.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/__init__.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage_v2.py +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/SOURCES.txt +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/dependency_links.txt +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/requires.txt +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/top_level.txt +0 -0
- {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/setup.cfg +0 -0
{agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/agw_saver.py
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import threading
|
|
4
5
|
import base64
|
|
5
6
|
import logging
|
|
6
7
|
import os
|
|
@@ -102,7 +103,10 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
102
103
|
super().__init__(serde=serde)
|
|
103
104
|
self.base_url = base_url.rstrip("/")
|
|
104
105
|
self.timeout = timeout
|
|
105
|
-
|
|
106
|
+
# Фоновый loop для sync-обёрток
|
|
107
|
+
self._bg_loop: asyncio.AbstractEventLoop | None = None
|
|
108
|
+
self._bg_thread: threading.Thread | None = None
|
|
109
|
+
self._loop_lock = threading.Lock()
|
|
106
110
|
|
|
107
111
|
raw_attempts = os.getenv("AGW_HTTP_MAX_RETRIES")
|
|
108
112
|
if raw_attempts is None:
|
|
@@ -175,6 +179,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
175
179
|
|
|
176
180
|
self._verify = verify
|
|
177
181
|
self._client: httpx.AsyncClient | None = None
|
|
182
|
+
self._client_loop: asyncio.AbstractEventLoop | None = None
|
|
178
183
|
|
|
179
184
|
def _create_client(self) -> httpx.AsyncClient:
|
|
180
185
|
return httpx.AsyncClient(
|
|
@@ -185,14 +190,23 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
185
190
|
trust_env=True,
|
|
186
191
|
)
|
|
187
192
|
|
|
188
|
-
def
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
193
|
+
def _ensure_bg_loop(self) -> asyncio.AbstractEventLoop:
|
|
194
|
+
with self._loop_lock:
|
|
195
|
+
if self._bg_loop and self._bg_loop.is_running():
|
|
196
|
+
return self._bg_loop
|
|
197
|
+
|
|
198
|
+
loop = asyncio.new_event_loop()
|
|
199
|
+
|
|
200
|
+
def runner():
|
|
201
|
+
asyncio.set_event_loop(loop)
|
|
202
|
+
loop.run_forever()
|
|
203
|
+
|
|
204
|
+
t = threading.Thread(target=runner, name="agw-checkpoint-loop", daemon=True)
|
|
205
|
+
t.start()
|
|
206
|
+
|
|
207
|
+
self._bg_loop = loop
|
|
208
|
+
self._bg_thread = t
|
|
209
|
+
return loop
|
|
196
210
|
|
|
197
211
|
def _compute_retry_delay(self, attempt: int) -> float:
|
|
198
212
|
if attempt <= 0:
|
|
@@ -218,6 +232,14 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
218
232
|
logger.debug("Failed to close AGW httpx.AsyncClient: %s", close_exc)
|
|
219
233
|
finally:
|
|
220
234
|
self._client = None
|
|
235
|
+
self._client_loop = None
|
|
236
|
+
# останавливаем фоновый loop, если поднимали
|
|
237
|
+
if self._bg_loop is not None:
|
|
238
|
+
try:
|
|
239
|
+
self._bg_loop.call_soon_threadsafe(self._bg_loop.stop)
|
|
240
|
+
finally:
|
|
241
|
+
self._bg_loop = None
|
|
242
|
+
self._bg_thread = None
|
|
221
243
|
|
|
222
244
|
# ----------------------- universal dump/load ---------------------
|
|
223
245
|
def _safe_dump(self, obj: Any) -> Any:
|
|
@@ -539,7 +561,18 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
539
561
|
|
|
540
562
|
attempt = 1
|
|
541
563
|
while True:
|
|
542
|
-
|
|
564
|
+
# клиент должен принадлежать текущему loop
|
|
565
|
+
current_loop = asyncio.get_running_loop()
|
|
566
|
+
client = self._client
|
|
567
|
+
if client is None or client.is_closed or self._client_loop is not current_loop:
|
|
568
|
+
if client is not None:
|
|
569
|
+
try:
|
|
570
|
+
await client.aclose()
|
|
571
|
+
except Exception as e:
|
|
572
|
+
logger.exception("ошибка при закрытии клиента", e)
|
|
573
|
+
client = self._create_client()
|
|
574
|
+
self._client = client
|
|
575
|
+
self._client_loop = current_loop
|
|
543
576
|
try:
|
|
544
577
|
resp = await client.request(method, path, **kw)
|
|
545
578
|
except httpx.RequestError as exc:
|
|
@@ -564,6 +597,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
564
597
|
)
|
|
565
598
|
finally:
|
|
566
599
|
self._client = None
|
|
600
|
+
self._client_loop = None
|
|
567
601
|
raise
|
|
568
602
|
|
|
569
603
|
if self._client is not None:
|
|
@@ -576,6 +610,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
576
610
|
)
|
|
577
611
|
finally:
|
|
578
612
|
self._client = None
|
|
613
|
+
self._client_loop = None
|
|
579
614
|
delay = self._compute_retry_delay(attempt)
|
|
580
615
|
if delay > 0:
|
|
581
616
|
await asyncio.sleep(delay)
|
|
@@ -611,6 +646,7 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
611
646
|
)
|
|
612
647
|
finally:
|
|
613
648
|
self._client = None
|
|
649
|
+
self._client_loop = None
|
|
614
650
|
delay = self._compute_retry_delay(attempt)
|
|
615
651
|
if delay > 0:
|
|
616
652
|
await asyncio.sleep(delay)
|
|
@@ -737,7 +773,10 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
737
773
|
# sync-обёртки
|
|
738
774
|
# =================================================================
|
|
739
775
|
def _run(self, coro):
|
|
740
|
-
|
|
776
|
+
# sync-обёртки всегда выполняем в собственном loop в отдельном потоке
|
|
777
|
+
loop = self._ensure_bg_loop()
|
|
778
|
+
fut = asyncio.run_coroutine_threadsafe(coro, loop)
|
|
779
|
+
return fut.result()
|
|
741
780
|
|
|
742
781
|
def list(
|
|
743
782
|
self,
|
|
@@ -747,12 +786,14 @@ class AsyncAGWCheckpointSaver(BaseCheckpointSaver):
|
|
|
747
786
|
before: RunnableConfig | None = None,
|
|
748
787
|
limit: int | None = None,
|
|
749
788
|
) -> Iterator[CheckpointTuple]:
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
789
|
+
async def _collect():
|
|
790
|
+
out = []
|
|
791
|
+
async for item in self.alist(cfg, filter=filter, before=before, limit=limit):
|
|
792
|
+
out.append(item)
|
|
793
|
+
return out
|
|
794
|
+
|
|
795
|
+
for item in self._run(_collect()):
|
|
796
|
+
yield item
|
|
756
797
|
|
|
757
798
|
def get_tuple(self, cfg: RunnableConfig) -> CheckpointTuple | None:
|
|
758
799
|
return self._run(self.aget_tuple(cfg))
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "agent-lab-sdk"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.43"
|
|
8
8
|
description = "SDK для работы с Agent Lab"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Proprietary and Confidential — All Rights Reserved" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|