fleet-python 0.2.127__tar.gz → 0.2.128__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.
- {fleet_python-0.2.127/fleet_python.egg-info → fleet_python-0.2.128}/PKG-INFO +1 -1
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/__init__.py +1 -7
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/__init__.py +1 -1
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/base.py +1 -1
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/client.py +34 -95
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/models.py +16 -2
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/tasks.py +52 -8
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/verifiers/verifier.py +38 -5
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/base.py +1 -1
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/client.py +33 -100
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/models.py +16 -2
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/tasks.py +54 -8
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/verifier.py +38 -5
- {fleet_python-0.2.127 → fleet_python-0.2.128/fleet_python.egg-info}/PKG-INFO +1 -1
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet_python.egg-info/SOURCES.txt +0 -2
- {fleet_python-0.2.127 → fleet_python-0.2.128}/pyproject.toml +1 -1
- fleet_python-0.2.127/fleet/_async/browser.py +0 -191
- fleet_python-0.2.127/fleet/browser.py +0 -216
- {fleet_python-0.2.127 → fleet_python-0.2.128}/LICENSE +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/README.md +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/diff_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/dsl_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/exampleResume.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_account.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_action_log.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_mcp_anthropic.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_mcp_openai.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_sync.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_task.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_tasks.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/example_verifier.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/export_tasks.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/export_tasks_filtered.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/fetch_tasks.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/gemini_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/import_tasks.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/iterate_verifiers.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/json_tasks_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/nova_act_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/openai_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/openai_simple_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/query_builder_example.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/quickstart.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/examples/test_cdp_logging.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/env/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/env/client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/exceptions.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/global_client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/instance/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/instance/base.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/instance/client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/judge.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/api.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/base.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/browser.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/filesystem.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/mcp.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/resources/sqlite.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/verifiers/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/_async/verifiers/bundler.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/Dockerfile +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/agent.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/mcp/main.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/mcp_server/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/mcp_server/main.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/mcp_server/tools.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/requirements.txt +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/gemini_cua/start.sh +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/orchestrator.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/types.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/agent/utils.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/cli.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/config.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/env/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/env/client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/eval/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/eval/uploader.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/exceptions.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/global_client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/instance/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/instance/base.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/instance/client.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/instance/models.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/judge.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/proxy/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/proxy/proxy.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/proxy/whitelist.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/api.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/base.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/browser.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/filesystem.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/mcp.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/resources/sqlite.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/types.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/utils/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/utils/http_logging.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/utils/logging.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/utils/playwright.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/bundler.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/code.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/db.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/decorator.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/parse.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet/verifiers/sql_differ.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet_python.egg-info/dependency_links.txt +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet_python.egg-info/entry_points.txt +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet_python.egg-info/requires.txt +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/fleet_python.egg-info/top_level.txt +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/scripts/fix_sync_imports.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/scripts/unasync.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/setup.cfg +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/__init__.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_app_method.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_expect_exactly.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_expect_only.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_instance_dispatch.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_sqlite_resource_dual_mode.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_sqlite_shared_memory_behavior.py +0 -0
- {fleet_python-0.2.127 → fleet_python-0.2.128}/tests/test_verifier_from_string.py +0 -0
|
@@ -26,8 +26,6 @@ from .exceptions import (
|
|
|
26
26
|
)
|
|
27
27
|
from .client import Fleet, SyncEnv, Session
|
|
28
28
|
from ._async.client import AsyncFleet, AsyncEnv, AsyncSession
|
|
29
|
-
from .browser import BrowserLease, host_from_url
|
|
30
|
-
from ._async.browser import AsyncBrowserLease
|
|
31
29
|
from .models import InstanceResponse, Environment, Run
|
|
32
30
|
from .instance.models import Resource, ResetResponse
|
|
33
31
|
|
|
@@ -78,7 +76,7 @@ from . import env
|
|
|
78
76
|
from . import global_client as _global_client
|
|
79
77
|
from ._async import global_client as _async_global_client
|
|
80
78
|
|
|
81
|
-
__version__ = "0.2.
|
|
79
|
+
__version__ = "0.2.128"
|
|
82
80
|
|
|
83
81
|
__all__ = [
|
|
84
82
|
# Core classes
|
|
@@ -86,10 +84,6 @@ __all__ = [
|
|
|
86
84
|
"SyncEnv",
|
|
87
85
|
"AsyncFleet",
|
|
88
86
|
"AsyncEnv",
|
|
89
|
-
# Browser lease (orchestrator-managed /v1/browser)
|
|
90
|
-
"BrowserLease",
|
|
91
|
-
"AsyncBrowserLease",
|
|
92
|
-
"host_from_url",
|
|
93
87
|
# Models
|
|
94
88
|
"InstanceResponse",
|
|
95
89
|
"SyncEnv",
|
|
@@ -171,15 +171,10 @@ from .instance.base import default_httpx_client
|
|
|
171
171
|
from .instance.client import ValidatorType
|
|
172
172
|
from .resources.base import Resource
|
|
173
173
|
from .resources.sqlite import AsyncSQLiteResource
|
|
174
|
+
from .resources.browser import AsyncBrowserResource
|
|
174
175
|
from .resources.filesystem import AsyncFilesystemResource
|
|
175
176
|
from .resources.mcp import AsyncMCPResource
|
|
176
177
|
from .resources.api import AsyncAPIResource
|
|
177
|
-
from .browser import (
|
|
178
|
-
AsyncBrowserLease,
|
|
179
|
-
create_browser as _create_browser_lease,
|
|
180
|
-
get_browser as _get_browser_lease,
|
|
181
|
-
host_from_url,
|
|
182
|
-
)
|
|
183
178
|
|
|
184
179
|
logger = logging.getLogger(__name__)
|
|
185
180
|
|
|
@@ -391,51 +386,8 @@ class AsyncEnv(EnvironmentBase):
|
|
|
391
386
|
def db(self, name: str = "current") -> AsyncSQLiteResource:
|
|
392
387
|
return self.instance.db(name)
|
|
393
388
|
|
|
394
|
-
|
|
395
|
-
self
|
|
396
|
-
ttl_seconds: int = 300,
|
|
397
|
-
*,
|
|
398
|
-
lease_id: Optional[str] = None,
|
|
399
|
-
allowed_hosts: Optional[List[str]] = None,
|
|
400
|
-
include_root_host: bool = True,
|
|
401
|
-
wait_until_running: bool = False,
|
|
402
|
-
wait_timeout: float = 60.0,
|
|
403
|
-
extra: Optional[Dict[str, Any]] = None,
|
|
404
|
-
jwt_token: Optional[str] = None,
|
|
405
|
-
team_id: Optional[str] = None,
|
|
406
|
-
) -> AsyncBrowserLease:
|
|
407
|
-
"""Spin up an orchestrator-managed Fleet Browser lease for this env.
|
|
408
|
-
|
|
409
|
-
``await env.browser()`` posts to ``/v1/browser`` and returns an
|
|
410
|
-
:class:`fleet._async.browser.AsyncBrowserLease` with ``cdp_url`` /
|
|
411
|
-
``mcp_url`` / ``stream_url`` and a ``mcp_tools()`` accessor. By
|
|
412
|
-
default the host derived from ``self.urls.root`` is prepended to
|
|
413
|
-
``allowed_hosts`` so the browser can reach the instance — pass
|
|
414
|
-
``include_root_host=False`` to opt out.
|
|
415
|
-
"""
|
|
416
|
-
hosts: Optional[List[str]] = list(allowed_hosts) if allowed_hosts else None
|
|
417
|
-
if include_root_host and self.urls and self.urls.root:
|
|
418
|
-
root_host = host_from_url(self.urls.root)
|
|
419
|
-
if root_host:
|
|
420
|
-
hosts = hosts or []
|
|
421
|
-
if root_host not in hosts:
|
|
422
|
-
hosts.insert(0, root_host)
|
|
423
|
-
return await _create_browser_lease(
|
|
424
|
-
self._load_client,
|
|
425
|
-
ttl_seconds=ttl_seconds,
|
|
426
|
-
lease_id=lease_id,
|
|
427
|
-
allowed_hosts=hosts,
|
|
428
|
-
extra=extra,
|
|
429
|
-
jwt_token=jwt_token,
|
|
430
|
-
team_id=team_id,
|
|
431
|
-
wait_until_running=wait_until_running,
|
|
432
|
-
wait_timeout=wait_timeout,
|
|
433
|
-
)
|
|
434
|
-
|
|
435
|
-
@property
|
|
436
|
-
def root_url(self) -> Optional[str]:
|
|
437
|
-
"""Convenience: ``self.urls.root`` if available."""
|
|
438
|
-
return self.urls.root if self.urls else None
|
|
389
|
+
def browser(self, name: str = "cdp") -> AsyncBrowserResource:
|
|
390
|
+
return self.instance.browser(name)
|
|
439
391
|
|
|
440
392
|
def fs(self) -> AsyncFilesystemResource:
|
|
441
393
|
"""Get a filesystem diff resource for inspecting file changes."""
|
|
@@ -530,6 +482,8 @@ class AsyncEnv(EnvironmentBase):
|
|
|
530
482
|
timeout: Optional[int] = 30,
|
|
531
483
|
needs_upload: bool = True,
|
|
532
484
|
verifier_runtime_version: Optional[str] = None,
|
|
485
|
+
async_: bool = False,
|
|
486
|
+
poll_interval: float = 5.0,
|
|
533
487
|
) -> VerifiersExecuteResponse:
|
|
534
488
|
return await _execute_verifier_remote(
|
|
535
489
|
self._load_client,
|
|
@@ -543,6 +497,8 @@ class AsyncEnv(EnvironmentBase):
|
|
|
543
497
|
timeout,
|
|
544
498
|
needs_upload,
|
|
545
499
|
verifier_runtime_version,
|
|
500
|
+
async_=async_,
|
|
501
|
+
poll_interval=poll_interval,
|
|
546
502
|
)
|
|
547
503
|
|
|
548
504
|
def __getstate__(self):
|
|
@@ -649,9 +605,7 @@ class AsyncFleet:
|
|
|
649
605
|
)
|
|
650
606
|
|
|
651
607
|
instance = AsyncEnv(client=self.client, **response.json())
|
|
652
|
-
|
|
653
|
-
# via `_load_resources()`, so we don't preload here. Eagerly loading would
|
|
654
|
-
# fail-fast with a 502 while the container is still warming up.
|
|
608
|
+
await instance.instance.load()
|
|
655
609
|
return instance
|
|
656
610
|
|
|
657
611
|
async def make_for_task(self, task: Task) -> AsyncEnv:
|
|
@@ -703,7 +657,7 @@ class AsyncFleet:
|
|
|
703
657
|
else:
|
|
704
658
|
response = await self.client.request("GET", f"/v1/env/instances/{instance_id}")
|
|
705
659
|
instance = AsyncEnv(client=self.client, **response.json())
|
|
706
|
-
|
|
660
|
+
await instance.instance.load()
|
|
707
661
|
return instance
|
|
708
662
|
|
|
709
663
|
def _create_url_instance(self, base_url: str) -> AsyncEnv:
|
|
@@ -844,45 +798,6 @@ class AsyncFleet:
|
|
|
844
798
|
self.client, bundle_data, args, kwargs, timeout
|
|
845
799
|
)
|
|
846
800
|
|
|
847
|
-
async def create_browser(
|
|
848
|
-
self,
|
|
849
|
-
ttl_seconds: int = 300,
|
|
850
|
-
*,
|
|
851
|
-
lease_id: Optional[str] = None,
|
|
852
|
-
allowed_hosts: Optional[List[str]] = None,
|
|
853
|
-
request_timestamp_ms: Optional[int] = None,
|
|
854
|
-
extra: Optional[Dict[str, Any]] = None,
|
|
855
|
-
jwt_token: Optional[str] = None,
|
|
856
|
-
team_id: Optional[str] = None,
|
|
857
|
-
wait_until_running: bool = False,
|
|
858
|
-
wait_timeout: float = 60.0,
|
|
859
|
-
) -> AsyncBrowserLease:
|
|
860
|
-
"""Create a Fleet Browser lease (``POST /v1/browser``)."""
|
|
861
|
-
return await _create_browser_lease(
|
|
862
|
-
self.client,
|
|
863
|
-
ttl_seconds=ttl_seconds,
|
|
864
|
-
lease_id=lease_id,
|
|
865
|
-
allowed_hosts=allowed_hosts,
|
|
866
|
-
request_timestamp_ms=request_timestamp_ms,
|
|
867
|
-
extra=extra,
|
|
868
|
-
jwt_token=jwt_token,
|
|
869
|
-
team_id=team_id,
|
|
870
|
-
wait_until_running=wait_until_running,
|
|
871
|
-
wait_timeout=wait_timeout,
|
|
872
|
-
)
|
|
873
|
-
|
|
874
|
-
async def get_browser(
|
|
875
|
-
self,
|
|
876
|
-
lease_id: str,
|
|
877
|
-
*,
|
|
878
|
-
jwt_token: Optional[str] = None,
|
|
879
|
-
team_id: Optional[str] = None,
|
|
880
|
-
) -> AsyncBrowserLease:
|
|
881
|
-
"""Inspect an existing browser lease (``GET /v1/browser/{lease_id}``)."""
|
|
882
|
-
return await _get_browser_lease(
|
|
883
|
-
self.client, lease_id, jwt_token=jwt_token, team_id=team_id
|
|
884
|
-
)
|
|
885
|
-
|
|
886
801
|
async def delete(self, instance_id: str) -> InstanceResponse:
|
|
887
802
|
return await _delete_instance(self.client, instance_id)
|
|
888
803
|
|
|
@@ -1814,6 +1729,8 @@ async def _execute_verifier_remote(
|
|
|
1814
1729
|
timeout: Optional[int] = 30,
|
|
1815
1730
|
needs_upload: bool = True,
|
|
1816
1731
|
verifier_runtime_version: Optional[str] = None,
|
|
1732
|
+
async_: bool = False,
|
|
1733
|
+
poll_interval: float = 5.0,
|
|
1817
1734
|
) -> VerifiersExecuteResponse:
|
|
1818
1735
|
# Pickle args and kwargs together
|
|
1819
1736
|
# The first arg should be None as a placeholder for env
|
|
@@ -1841,6 +1758,11 @@ async def _execute_verifier_remote(
|
|
|
1841
1758
|
if verifier_runtime_version:
|
|
1842
1759
|
request_data["verifier_runtime_version"] = verifier_runtime_version
|
|
1843
1760
|
|
|
1761
|
+
# Async submit-and-poll path. When async_ is False the behavior below is
|
|
1762
|
+
# identical to the original synchronous request.
|
|
1763
|
+
if async_:
|
|
1764
|
+
request_data["async"] = True
|
|
1765
|
+
|
|
1844
1766
|
# Debug logging
|
|
1845
1767
|
# logger.debug(
|
|
1846
1768
|
# f"Sending verifier execute request: key={key}, sha256={bundle_sha[:8]}..., function_name={function_name}"
|
|
@@ -1862,4 +1784,21 @@ async def _execute_verifier_remote(
|
|
|
1862
1784
|
response_json = response.json()
|
|
1863
1785
|
# logger.debug(f"Verifier execute response: {response_json}")
|
|
1864
1786
|
|
|
1865
|
-
|
|
1787
|
+
if not async_:
|
|
1788
|
+
return VerifiersExecuteResponse(**response_json)
|
|
1789
|
+
|
|
1790
|
+
# Async: the submit returns a job handle; poll until the job reaches a
|
|
1791
|
+
# terminal state (completed/failed). Branch on `status`, never `success`.
|
|
1792
|
+
job_id = response_json.get("job_id")
|
|
1793
|
+
if not job_id:
|
|
1794
|
+
# No job handle returned (e.g. server ran it inline) - surface as-is.
|
|
1795
|
+
return VerifiersExecuteResponse(**response_json)
|
|
1796
|
+
|
|
1797
|
+
while True:
|
|
1798
|
+
poll_response = await client.request(
|
|
1799
|
+
"GET", f"/v1/verifiers/jobs/{job_id}"
|
|
1800
|
+
)
|
|
1801
|
+
poll_json = poll_response.json()
|
|
1802
|
+
if poll_json.get("status") in ("completed", "failed"):
|
|
1803
|
+
return VerifiersExecuteResponse(**poll_json)
|
|
1804
|
+
await asyncio.sleep(poll_interval)
|
|
@@ -51,7 +51,6 @@ class Instance(BaseModel):
|
|
|
51
51
|
team_id: str = Field(..., title="Team Id")
|
|
52
52
|
region: str = Field(..., title="Region")
|
|
53
53
|
env_variables: Optional[Dict[str, Any]] = Field(None, title="Env Variables")
|
|
54
|
-
multi_env_list: Optional[List[str]] = Field(None, title="Multi Env List")
|
|
55
54
|
|
|
56
55
|
|
|
57
56
|
class InstanceRequest(BaseModel):
|
|
@@ -259,6 +258,12 @@ class VerifiersExecuteRequest(BaseModel):
|
|
|
259
258
|
display_src: Optional[str] = Field(
|
|
260
259
|
None, description="Display source code", title="Display Src"
|
|
261
260
|
)
|
|
261
|
+
async_: Optional[bool] = Field(
|
|
262
|
+
None,
|
|
263
|
+
alias="async",
|
|
264
|
+
description="Submit asynchronously and return a job handle instead of waiting",
|
|
265
|
+
title="Async",
|
|
266
|
+
)
|
|
262
267
|
|
|
263
268
|
|
|
264
269
|
class VerifiersExecuteResponse(BaseModel):
|
|
@@ -303,6 +308,16 @@ class VerifiersExecuteResponse(BaseModel):
|
|
|
303
308
|
stdout: Optional[str] = Field(
|
|
304
309
|
None, description="Captured stdout from execution", title="Stdout"
|
|
305
310
|
)
|
|
311
|
+
status: Optional[str] = Field(
|
|
312
|
+
None,
|
|
313
|
+
description="Job status for async execution (pending/running/completed/failed)",
|
|
314
|
+
title="Status",
|
|
315
|
+
)
|
|
316
|
+
job_id: Optional[str] = Field(
|
|
317
|
+
None,
|
|
318
|
+
description="Job handle for async execution; poll GET /v1/verifiers/jobs/{job_id}",
|
|
319
|
+
title="Job Id",
|
|
320
|
+
)
|
|
306
321
|
|
|
307
322
|
|
|
308
323
|
class DescribeResponse(BaseModel):
|
|
@@ -358,7 +373,6 @@ class InstanceResponse(BaseModel):
|
|
|
358
373
|
data_version: Optional[str] = Field(None, title="Data Version")
|
|
359
374
|
urls: Optional[InstanceURLs] = Field(None, title="Urls")
|
|
360
375
|
health: Optional[bool] = Field(None, title="Health")
|
|
361
|
-
multi_env_list: Optional[List[str]] = Field(None, title="Multi Env List")
|
|
362
376
|
|
|
363
377
|
|
|
364
378
|
class AccountResponse(BaseModel):
|
|
@@ -81,11 +81,23 @@ class Task(BaseModel):
|
|
|
81
81
|
# Allow arbitrary types for the verifier field
|
|
82
82
|
arbitrary_types_allowed = True
|
|
83
83
|
|
|
84
|
-
def verify(
|
|
84
|
+
def verify(
|
|
85
|
+
self,
|
|
86
|
+
env,
|
|
87
|
+
*args,
|
|
88
|
+
async_: bool = False,
|
|
89
|
+
poll_interval: float = 5.0,
|
|
90
|
+
**kwargs,
|
|
91
|
+
) -> float:
|
|
85
92
|
"""Verify the task using the verifier function (sync version).
|
|
86
93
|
|
|
87
94
|
For sync environments, calls the sync verifier directly.
|
|
88
95
|
For async verifiers, automatically runs them with asyncio.run().
|
|
96
|
+
|
|
97
|
+
When ``async_`` is True the verifier is submitted to run in the
|
|
98
|
+
background and polled (every ``poll_interval`` seconds) until it
|
|
99
|
+
completes, avoiding HTTP/edge idle timeouts for long-running
|
|
100
|
+
verifiers. When False the behavior is unchanged.
|
|
89
101
|
"""
|
|
90
102
|
# If verifier doesn't exist but verifier_func does, rebuild it
|
|
91
103
|
if not self.verifier and self.verifier_func:
|
|
@@ -95,7 +107,9 @@ class Task(BaseModel):
|
|
|
95
107
|
import asyncio
|
|
96
108
|
import inspect
|
|
97
109
|
|
|
98
|
-
result = self.verifier.remote(
|
|
110
|
+
result = self.verifier.remote(
|
|
111
|
+
env, *args, async_=async_, poll_interval=poll_interval, **kwargs
|
|
112
|
+
)
|
|
99
113
|
|
|
100
114
|
# If the result is a coroutine, we need to run it
|
|
101
115
|
if inspect.iscoroutine(result):
|
|
@@ -115,18 +129,27 @@ class Task(BaseModel):
|
|
|
115
129
|
else:
|
|
116
130
|
raise ValueError("No verifier function found for this task")
|
|
117
131
|
|
|
118
|
-
async def verify_async(
|
|
132
|
+
async def verify_async(
|
|
133
|
+
self, *args, async_: bool = False, poll_interval: float = 5.0, **kwargs
|
|
134
|
+
) -> float:
|
|
119
135
|
"""Verify the task using the verifier function (async version).
|
|
120
136
|
|
|
121
137
|
For async environments, awaits the async verifier.
|
|
122
138
|
Works with both sync and async verifiers in async contexts.
|
|
139
|
+
|
|
140
|
+
When ``async_`` is True the verifier is submitted to run in the
|
|
141
|
+
background and polled (every ``poll_interval`` seconds) until it
|
|
142
|
+
completes, avoiding HTTP/edge idle timeouts for long-running
|
|
143
|
+
verifiers. When False the behavior is unchanged.
|
|
123
144
|
"""
|
|
124
145
|
# If verifier doesn't exist but verifier_func does, rebuild it
|
|
125
146
|
if not self.verifier and self.verifier_func:
|
|
126
147
|
self._rebuild_verifier()
|
|
127
148
|
|
|
128
149
|
if self.verifier:
|
|
129
|
-
result = self.verifier.remote(
|
|
150
|
+
result = self.verifier.remote(
|
|
151
|
+
*args, async_=async_, poll_interval=poll_interval, **kwargs
|
|
152
|
+
)
|
|
130
153
|
# If it's a coroutine, await it
|
|
131
154
|
import inspect
|
|
132
155
|
|
|
@@ -138,19 +161,26 @@ class Task(BaseModel):
|
|
|
138
161
|
raise ValueError("No verifier function found for this task")
|
|
139
162
|
|
|
140
163
|
async def verify_detailed_async(
|
|
141
|
-
self, *args, **kwargs
|
|
164
|
+
self, *args, async_: bool = False, poll_interval: float = 5.0, **kwargs
|
|
142
165
|
) -> "VerifiersExecuteResponse":
|
|
143
166
|
"""Verify the task and return the full execute response model.
|
|
144
167
|
|
|
145
168
|
For async environments, awaits the async verifier.
|
|
146
169
|
Works with both sync and async verifiers in async contexts.
|
|
170
|
+
|
|
171
|
+
When ``async_`` is True the verifier is submitted to run in the
|
|
172
|
+
background and polled (every ``poll_interval`` seconds) until it
|
|
173
|
+
completes, avoiding HTTP/edge idle timeouts for long-running
|
|
174
|
+
verifiers. When False the behavior is unchanged.
|
|
147
175
|
"""
|
|
148
176
|
# If verifier doesn't exist but verifier_func does, rebuild it
|
|
149
177
|
if not self.verifier and self.verifier_func:
|
|
150
178
|
self._rebuild_verifier()
|
|
151
179
|
|
|
152
180
|
if self.verifier:
|
|
153
|
-
result = self.verifier.remote_with_response(
|
|
181
|
+
result = self.verifier.remote_with_response(
|
|
182
|
+
*args, async_=async_, poll_interval=poll_interval, **kwargs
|
|
183
|
+
)
|
|
154
184
|
# If it's a coroutine, await it
|
|
155
185
|
import inspect
|
|
156
186
|
|
|
@@ -161,11 +191,23 @@ class Task(BaseModel):
|
|
|
161
191
|
else:
|
|
162
192
|
raise ValueError("No verifier function found for this task")
|
|
163
193
|
|
|
164
|
-
def verify_detailed(
|
|
194
|
+
def verify_detailed(
|
|
195
|
+
self,
|
|
196
|
+
env,
|
|
197
|
+
*args,
|
|
198
|
+
async_: bool = False,
|
|
199
|
+
poll_interval: float = 5.0,
|
|
200
|
+
**kwargs,
|
|
201
|
+
) -> "VerifiersExecuteResponse":
|
|
165
202
|
"""Verify the task and return the full execute response model (sync version).
|
|
166
203
|
|
|
167
204
|
For sync environments, calls the sync verifier directly.
|
|
168
205
|
For async verifiers, automatically runs them with asyncio.run().
|
|
206
|
+
|
|
207
|
+
When ``async_`` is True the verifier is submitted to run in the
|
|
208
|
+
background and polled (every ``poll_interval`` seconds) until it
|
|
209
|
+
completes, avoiding HTTP/edge idle timeouts for long-running
|
|
210
|
+
verifiers. When False the behavior is unchanged.
|
|
169
211
|
"""
|
|
170
212
|
# If verifier doesn't exist but verifier_func does, rebuild it
|
|
171
213
|
if not self.verifier and self.verifier_func:
|
|
@@ -176,7 +218,9 @@ class Task(BaseModel):
|
|
|
176
218
|
import inspect
|
|
177
219
|
|
|
178
220
|
# Check if verifier has remote_with_response method (for decorated verifiers)
|
|
179
|
-
result = self.verifier.remote_with_response(
|
|
221
|
+
result = self.verifier.remote_with_response(
|
|
222
|
+
env, *args, async_=async_, poll_interval=poll_interval, **kwargs
|
|
223
|
+
)
|
|
180
224
|
|
|
181
225
|
# If the result is a coroutine, we need to run it
|
|
182
226
|
if inspect.iscoroutine(result):
|
|
@@ -154,9 +154,25 @@ class AsyncVerifierFunction:
|
|
|
154
154
|
# Return error score 0
|
|
155
155
|
return 0.0
|
|
156
156
|
|
|
157
|
-
async def remote(
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
async def remote(
|
|
158
|
+
self,
|
|
159
|
+
env: AsyncEnv,
|
|
160
|
+
*args,
|
|
161
|
+
async_: bool = False,
|
|
162
|
+
poll_interval: float = 5.0,
|
|
163
|
+
**kwargs,
|
|
164
|
+
) -> float:
|
|
165
|
+
"""Remote execution of the verifier function with SHA-based bundle caching.
|
|
166
|
+
|
|
167
|
+
When ``async_`` is True the verifier is submitted to run in the
|
|
168
|
+
background and the result is polled (every ``poll_interval`` seconds)
|
|
169
|
+
until it completes — this avoids HTTP/edge idle timeouts for
|
|
170
|
+
long-running verifiers. When False the behavior is unchanged (the
|
|
171
|
+
request blocks until the verifier finishes).
|
|
172
|
+
"""
|
|
173
|
+
response = await self.remote_with_response(
|
|
174
|
+
env, *args, async_=async_, poll_interval=poll_interval, **kwargs
|
|
175
|
+
)
|
|
160
176
|
|
|
161
177
|
# Handle response
|
|
162
178
|
if response.stdout:
|
|
@@ -228,9 +244,20 @@ Remote traceback:
|
|
|
228
244
|
)
|
|
229
245
|
|
|
230
246
|
async def remote_with_response(
|
|
231
|
-
self,
|
|
247
|
+
self,
|
|
248
|
+
env: "AsyncEnv",
|
|
249
|
+
*args,
|
|
250
|
+
async_: bool = False,
|
|
251
|
+
poll_interval: float = 5.0,
|
|
252
|
+
**kwargs,
|
|
232
253
|
) -> "VerifiersExecuteResponse":
|
|
233
|
-
"""Remote execution of the verifier function that returns the full response model.
|
|
254
|
+
"""Remote execution of the verifier function that returns the full response model.
|
|
255
|
+
|
|
256
|
+
When ``async_`` is True the verifier is submitted asynchronously and
|
|
257
|
+
polled (every ``poll_interval`` seconds) until it reaches a terminal
|
|
258
|
+
state; the returned response is the completed/failed job result. When
|
|
259
|
+
False the request blocks until the verifier finishes (unchanged).
|
|
260
|
+
"""
|
|
234
261
|
args_array = list(args)
|
|
235
262
|
args_array.append({"env": env.instance_id})
|
|
236
263
|
args = tuple(args_array)
|
|
@@ -254,6 +281,8 @@ Remote traceback:
|
|
|
254
281
|
kwargs=kwargs,
|
|
255
282
|
needs_upload=True,
|
|
256
283
|
verifier_runtime_version=self.verifier_runtime_version,
|
|
284
|
+
async_=async_,
|
|
285
|
+
poll_interval=poll_interval,
|
|
257
286
|
)
|
|
258
287
|
|
|
259
288
|
# logger.debug(f"Bundle {bundle_sha[:8]}... uploaded successfully")
|
|
@@ -271,6 +300,8 @@ Remote traceback:
|
|
|
271
300
|
kwargs=kwargs,
|
|
272
301
|
needs_upload=False,
|
|
273
302
|
verifier_runtime_version=self.verifier_runtime_version,
|
|
303
|
+
async_=async_,
|
|
304
|
+
poll_interval=poll_interval,
|
|
274
305
|
)
|
|
275
306
|
|
|
276
307
|
return response
|
|
@@ -292,6 +323,8 @@ Remote traceback:
|
|
|
292
323
|
kwargs=kwargs,
|
|
293
324
|
needs_upload=True,
|
|
294
325
|
verifier_runtime_version=self.verifier_runtime_version,
|
|
326
|
+
async_=async_,
|
|
327
|
+
poll_interval=poll_interval,
|
|
295
328
|
)
|
|
296
329
|
return response
|
|
297
330
|
else:
|