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.

Files changed (27) hide show
  1. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/PKG-INFO +1 -1
  2. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/agw_saver.py +58 -17
  3. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/PKG-INFO +1 -1
  4. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/pyproject.toml +1 -1
  5. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/LICENSE +0 -0
  6. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/README.md +0 -0
  7. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/__init__.py +0 -0
  8. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/__init__.py +0 -0
  9. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/langgraph/checkpoint/serde.py +0 -0
  10. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/__init__.py +0 -0
  11. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/agw_token_manager.py +0 -0
  12. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/gigachat_token_manager.py +0 -0
  13. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/llm.py +0 -0
  14. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/llm/throttled.py +0 -0
  15. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/__init__.py +0 -0
  16. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/metrics/metrics.py +0 -0
  17. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/__init__.py +0 -0
  18. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/input_types.py +0 -0
  19. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/schema/log_message.py +0 -0
  20. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/__init__.py +0 -0
  21. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage.py +0 -0
  22. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk/storage/storage_v2.py +0 -0
  23. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/SOURCES.txt +0 -0
  24. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/dependency_links.txt +0 -0
  25. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/requires.txt +0 -0
  26. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/agent_lab_sdk.egg-info/top_level.txt +0 -0
  27. {agent_lab_sdk-0.1.42.1 → agent_lab_sdk-0.1.43}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-lab-sdk
3
- Version: 0.1.42.1
3
+ Version: 0.1.43
4
4
  Summary: SDK для работы с Agent Lab
5
5
  Author-email: Andrew Ohurtsov <andermirik@yandex.com>
6
6
  License: Proprietary and Confidential — All Rights Reserved
@@ -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
- self.loop = asyncio.get_running_loop()
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 _ensure_client(self) -> httpx.AsyncClient:
189
- client = self._client
190
- if client is None or client.is_closed:
191
- if client is not None and client.is_closed:
192
- logger.debug("Recreating closed httpx.AsyncClient for AGW")
193
- client = self._create_client()
194
- self._client = client
195
- return client
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
- client = self._ensure_client()
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
- return asyncio.run_coroutine_threadsafe(coro, self.loop).result()
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
- aiter_ = self.alist(cfg, filter=filter, before=before, limit=limit)
751
- while True:
752
- try:
753
- yield self._run(anext(aiter_))
754
- except StopAsyncIteration:
755
- break
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))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-lab-sdk
3
- Version: 0.1.42.1
3
+ Version: 0.1.43
4
4
  Summary: SDK для работы с Agent Lab
5
5
  Author-email: Andrew Ohurtsov <andermirik@yandex.com>
6
6
  License: Proprietary and Confidential — All Rights Reserved
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-lab-sdk"
7
- version = "0.1.42.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