plato-sdk-v2 2.5.0__py3-none-any.whl → 2.6.0__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.
- plato/_generated/__init__.py +1 -1
- plato/_generated/api/v1/evals/get_scores_by_user.py +7 -0
- plato/_generated/api/v1/testcases/get_testcases.py +14 -0
- plato/_generated/api/v2/sessions/setup_sandbox.py +2 -2
- plato/_generated/models/__init__.py +42 -2
- plato/chronos/api/admin/__init__.py +17 -0
- plato/chronos/api/admin/clear_database_api_admin_clear_db_post.py +57 -0
- plato/chronos/api/admin/sync_agents_api_admin_sync_agents_post.py +67 -0
- plato/chronos/api/admin/sync_all_api_admin_sync_all_post.py +67 -0
- plato/chronos/api/admin/sync_runtimes_api_admin_sync_runtimes_post.py +67 -0
- plato/chronos/api/admin/sync_worlds_api_admin_sync_worlds_post.py +67 -0
- plato/chronos/api/agents/list_agents.py +5 -5
- plato/chronos/api/checkpoints/__init__.py +8 -0
- plato/chronos/api/checkpoints/list_checkpoints.py +52 -0
- plato/chronos/api/checkpoints/preview_checkpoint.py +74 -0
- plato/chronos/api/events/__init__.py +8 -0
- plato/chronos/api/events/get_session_event.py +68 -0
- plato/chronos/api/events/list_session_events.py +62 -0
- plato/chronos/api/jobs/launch_job.py +8 -2
- plato/chronos/api/otel/__init__.py +8 -0
- plato/chronos/api/otel/get_session_traces_api_otel_sessions__session_id__traces_get.py +56 -0
- plato/chronos/api/otel/receive_traces_api_otel_v1_traces_post.py +49 -0
- plato/chronos/api/registry/list_registry_agents_api_registry_agents_get.py +5 -5
- plato/chronos/api/runtimes/__init__.py +2 -1
- plato/chronos/api/runtimes/get_runtime_logs.py +61 -0
- plato/chronos/api/sessions/__init__.py +24 -1
- plato/chronos/api/sessions/close_session.py +66 -0
- plato/chronos/api/sessions/complete_session.py +74 -0
- plato/chronos/api/sessions/create_session.py +69 -0
- plato/chronos/api/sessions/get_session.py +20 -2
- plato/chronos/api/sessions/get_session_bash_logs_download.py +61 -0
- plato/chronos/api/sessions/get_session_envs.py +62 -0
- plato/chronos/api/sessions/get_session_live_logs.py +62 -0
- plato/chronos/api/sessions/get_session_logs.py +3 -3
- plato/chronos/api/sessions/get_session_status.py +62 -0
- plato/chronos/api/sessions/list_sessions.py +20 -2
- plato/chronos/api/sessions/list_tags.py +80 -0
- plato/chronos/api/sessions/update_session_tags.py +68 -0
- plato/chronos/models/__init__.py +241 -196
- plato/v1/cli/chronos.py +62 -0
- plato/v2/__init__.py +8 -0
- plato/v2/async_/__init__.py +4 -0
- plato/v2/async_/chronos.py +419 -0
- plato/v2/sync/__init__.py +3 -0
- plato/v2/sync/chronos.py +419 -0
- plato/worlds/base.py +12 -2
- {plato_sdk_v2-2.5.0.dist-info → plato_sdk_v2-2.6.0.dist-info}/METADATA +1 -1
- {plato_sdk_v2-2.5.0.dist-info → plato_sdk_v2-2.6.0.dist-info}/RECORD +50 -23
- {plato_sdk_v2-2.5.0.dist-info → plato_sdk_v2-2.6.0.dist-info}/WHEEL +0 -0
- {plato_sdk_v2-2.5.0.dist-info → plato_sdk_v2-2.6.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Preview Checkpoint"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import PreviewResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
checkpoint_id: str,
|
|
15
|
+
) -> dict[str, Any]:
|
|
16
|
+
"""Build request arguments."""
|
|
17
|
+
url = f"/api/checkpoints/{checkpoint_id}/preview"
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
"method": "POST",
|
|
21
|
+
"url": url,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def sync(
|
|
26
|
+
client: httpx.Client,
|
|
27
|
+
checkpoint_id: str,
|
|
28
|
+
) -> PreviewResponse:
|
|
29
|
+
"""Launch a preview session from a checkpoint.
|
|
30
|
+
|
|
31
|
+
Creates an ephemeral Plato session using the checkpoint's artifact IDs.
|
|
32
|
+
Returns serialized session data that can be used with Session.load()
|
|
33
|
+
to send heartbeats and eventually close the session.
|
|
34
|
+
|
|
35
|
+
The frontend should:
|
|
36
|
+
1. Call this endpoint to get the serialized session
|
|
37
|
+
2. Use Session.load(serialized_session) to restore the session
|
|
38
|
+
3. Call session.start_heartbeat() to keep envs alive
|
|
39
|
+
4. Display env URLs/job IDs in a modal
|
|
40
|
+
5. Call session.stop_heartbeat() and session.close() when done"""
|
|
41
|
+
|
|
42
|
+
request_args = _build_request_args(
|
|
43
|
+
checkpoint_id=checkpoint_id,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
response = client.request(**request_args)
|
|
47
|
+
raise_for_status(response)
|
|
48
|
+
return PreviewResponse.model_validate(response.json())
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def asyncio(
|
|
52
|
+
client: httpx.AsyncClient,
|
|
53
|
+
checkpoint_id: str,
|
|
54
|
+
) -> PreviewResponse:
|
|
55
|
+
"""Launch a preview session from a checkpoint.
|
|
56
|
+
|
|
57
|
+
Creates an ephemeral Plato session using the checkpoint's artifact IDs.
|
|
58
|
+
Returns serialized session data that can be used with Session.load()
|
|
59
|
+
to send heartbeats and eventually close the session.
|
|
60
|
+
|
|
61
|
+
The frontend should:
|
|
62
|
+
1. Call this endpoint to get the serialized session
|
|
63
|
+
2. Use Session.load(serialized_session) to restore the session
|
|
64
|
+
3. Call session.start_heartbeat() to keep envs alive
|
|
65
|
+
4. Display env URLs/job IDs in a modal
|
|
66
|
+
5. Call session.stop_heartbeat() and session.close() when done"""
|
|
67
|
+
|
|
68
|
+
request_args = _build_request_args(
|
|
69
|
+
checkpoint_id=checkpoint_id,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
response = await client.request(**request_args)
|
|
73
|
+
raise_for_status(response)
|
|
74
|
+
return PreviewResponse.model_validate(response.json())
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Get Event"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import OTelSpan
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
span_id: str,
|
|
15
|
+
x_api_key: str | None = None,
|
|
16
|
+
) -> dict[str, Any]:
|
|
17
|
+
"""Build request arguments."""
|
|
18
|
+
url = f"/api/events/{span_id}"
|
|
19
|
+
|
|
20
|
+
headers: dict[str, str] = {}
|
|
21
|
+
if x_api_key is not None:
|
|
22
|
+
headers["X-API-Key"] = x_api_key
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
"method": "GET",
|
|
26
|
+
"url": url,
|
|
27
|
+
"headers": headers,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def sync(
|
|
32
|
+
client: httpx.Client,
|
|
33
|
+
span_id: str,
|
|
34
|
+
x_api_key: str | None = None,
|
|
35
|
+
) -> OTelSpan:
|
|
36
|
+
"""Get a span by ID.
|
|
37
|
+
|
|
38
|
+
Note: This requires scanning all batches, so it's not efficient.
|
|
39
|
+
Consider caching or indexing spans if this is used frequently."""
|
|
40
|
+
|
|
41
|
+
request_args = _build_request_args(
|
|
42
|
+
span_id=span_id,
|
|
43
|
+
x_api_key=x_api_key,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
response = client.request(**request_args)
|
|
47
|
+
raise_for_status(response)
|
|
48
|
+
return OTelSpan.model_validate(response.json())
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
async def asyncio(
|
|
52
|
+
client: httpx.AsyncClient,
|
|
53
|
+
span_id: str,
|
|
54
|
+
x_api_key: str | None = None,
|
|
55
|
+
) -> OTelSpan:
|
|
56
|
+
"""Get a span by ID.
|
|
57
|
+
|
|
58
|
+
Note: This requires scanning all batches, so it's not efficient.
|
|
59
|
+
Consider caching or indexing spans if this is used frequently."""
|
|
60
|
+
|
|
61
|
+
request_args = _build_request_args(
|
|
62
|
+
span_id=span_id,
|
|
63
|
+
x_api_key=x_api_key,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
response = await client.request(**request_args)
|
|
67
|
+
raise_for_status(response)
|
|
68
|
+
return OTelSpan.model_validate(response.json())
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"""List Events For Session"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import OTelSpanListResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
session_public_id: str,
|
|
15
|
+
x_api_key: str | None = None,
|
|
16
|
+
) -> dict[str, Any]:
|
|
17
|
+
"""Build request arguments."""
|
|
18
|
+
url = f"/api/events/session/{session_public_id}"
|
|
19
|
+
|
|
20
|
+
headers: dict[str, str] = {}
|
|
21
|
+
if x_api_key is not None:
|
|
22
|
+
headers["X-API-Key"] = x_api_key
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
"method": "GET",
|
|
26
|
+
"url": url,
|
|
27
|
+
"headers": headers,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def sync(
|
|
32
|
+
client: httpx.Client,
|
|
33
|
+
session_public_id: str,
|
|
34
|
+
x_api_key: str | None = None,
|
|
35
|
+
) -> OTelSpanListResponse:
|
|
36
|
+
"""List all OTel spans for a session."""
|
|
37
|
+
|
|
38
|
+
request_args = _build_request_args(
|
|
39
|
+
session_public_id=session_public_id,
|
|
40
|
+
x_api_key=x_api_key,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
response = client.request(**request_args)
|
|
44
|
+
raise_for_status(response)
|
|
45
|
+
return OTelSpanListResponse.model_validate(response.json())
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def asyncio(
|
|
49
|
+
client: httpx.AsyncClient,
|
|
50
|
+
session_public_id: str,
|
|
51
|
+
x_api_key: str | None = None,
|
|
52
|
+
) -> OTelSpanListResponse:
|
|
53
|
+
"""List all OTel spans for a session."""
|
|
54
|
+
|
|
55
|
+
request_args = _build_request_args(
|
|
56
|
+
session_public_id=session_public_id,
|
|
57
|
+
x_api_key=x_api_key,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
response = await client.request(**request_args)
|
|
61
|
+
raise_for_status(response)
|
|
62
|
+
return OTelSpanListResponse.model_validate(response.json())
|
|
@@ -34,7 +34,10 @@ def sync(
|
|
|
34
34
|
body: LaunchJobRequest,
|
|
35
35
|
x_api_key: str | None = None,
|
|
36
36
|
) -> LaunchJobResponse:
|
|
37
|
-
"""Launch a new Chronos job.
|
|
37
|
+
"""Launch a new Chronos job.
|
|
38
|
+
|
|
39
|
+
The world.config is passed directly to the world runner.
|
|
40
|
+
Agent and secret configs should be embedded in world.config."""
|
|
38
41
|
|
|
39
42
|
request_args = _build_request_args(
|
|
40
43
|
body=body,
|
|
@@ -51,7 +54,10 @@ async def asyncio(
|
|
|
51
54
|
body: LaunchJobRequest,
|
|
52
55
|
x_api_key: str | None = None,
|
|
53
56
|
) -> LaunchJobResponse:
|
|
54
|
-
"""Launch a new Chronos job.
|
|
57
|
+
"""Launch a new Chronos job.
|
|
58
|
+
|
|
59
|
+
The world.config is passed directly to the world runner.
|
|
60
|
+
Agent and secret configs should be embedded in world.config."""
|
|
55
61
|
|
|
56
62
|
request_args = _build_request_args(
|
|
57
63
|
body=body,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""API endpoints."""
|
|
2
|
+
|
|
3
|
+
from . import get_session_traces_api_otel_sessions__session_id__traces_get, receive_traces_api_otel_v1_traces_post
|
|
4
|
+
|
|
5
|
+
__all__ = [
|
|
6
|
+
"receive_traces_api_otel_v1_traces_post",
|
|
7
|
+
"get_session_traces_api_otel_sessions__session_id__traces_get",
|
|
8
|
+
]
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Get Session Traces"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import OTelTraceResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
session_id: str,
|
|
15
|
+
) -> dict[str, Any]:
|
|
16
|
+
"""Build request arguments."""
|
|
17
|
+
url = f"/api/otel/sessions/{session_id}/traces"
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
"method": "GET",
|
|
21
|
+
"url": url,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def sync(
|
|
26
|
+
client: httpx.Client,
|
|
27
|
+
session_id: str,
|
|
28
|
+
) -> OTelTraceResponse:
|
|
29
|
+
"""Get all parsed traces for a session.
|
|
30
|
+
|
|
31
|
+
Returns spans parsed from stored OTLP batches, suitable for UI rendering."""
|
|
32
|
+
|
|
33
|
+
request_args = _build_request_args(
|
|
34
|
+
session_id=session_id,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
response = client.request(**request_args)
|
|
38
|
+
raise_for_status(response)
|
|
39
|
+
return OTelTraceResponse.model_validate(response.json())
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
async def asyncio(
|
|
43
|
+
client: httpx.AsyncClient,
|
|
44
|
+
session_id: str,
|
|
45
|
+
) -> OTelTraceResponse:
|
|
46
|
+
"""Get all parsed traces for a session.
|
|
47
|
+
|
|
48
|
+
Returns spans parsed from stored OTLP batches, suitable for UI rendering."""
|
|
49
|
+
|
|
50
|
+
request_args = _build_request_args(
|
|
51
|
+
session_id=session_id,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
response = await client.request(**request_args)
|
|
55
|
+
raise_for_status(response)
|
|
56
|
+
return OTelTraceResponse.model_validate(response.json())
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Receive Traces"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _build_request_args() -> dict[str, Any]:
|
|
13
|
+
"""Build request arguments."""
|
|
14
|
+
url = "/api/otel/v1/traces"
|
|
15
|
+
|
|
16
|
+
return {
|
|
17
|
+
"method": "POST",
|
|
18
|
+
"url": url,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def sync(
|
|
23
|
+
client: httpx.Client,
|
|
24
|
+
) -> dict[str, Any]:
|
|
25
|
+
"""Receive OTLP trace data (JSON or protobuf) and store as JSON.
|
|
26
|
+
|
|
27
|
+
Resource attributes must include:
|
|
28
|
+
- plato.session.id: The Chronos session ID"""
|
|
29
|
+
|
|
30
|
+
request_args = _build_request_args()
|
|
31
|
+
|
|
32
|
+
response = client.request(**request_args)
|
|
33
|
+
raise_for_status(response)
|
|
34
|
+
return response.json()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
async def asyncio(
|
|
38
|
+
client: httpx.AsyncClient,
|
|
39
|
+
) -> dict[str, Any]:
|
|
40
|
+
"""Receive OTLP trace data (JSON or protobuf) and store as JSON.
|
|
41
|
+
|
|
42
|
+
Resource attributes must include:
|
|
43
|
+
- plato.session.id: The Chronos session ID"""
|
|
44
|
+
|
|
45
|
+
request_args = _build_request_args()
|
|
46
|
+
|
|
47
|
+
response = await client.request(**request_args)
|
|
48
|
+
raise_for_status(response)
|
|
49
|
+
return response.json()
|
|
@@ -7,7 +7,7 @@ from typing import Any
|
|
|
7
7
|
import httpx
|
|
8
8
|
|
|
9
9
|
from plato.chronos.errors import raise_for_status
|
|
10
|
-
from plato.chronos.models import
|
|
10
|
+
from plato.chronos.models import AgentListResponse
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _build_request_args() -> dict[str, Any]:
|
|
@@ -22,23 +22,23 @@ def _build_request_args() -> dict[str, Any]:
|
|
|
22
22
|
|
|
23
23
|
def sync(
|
|
24
24
|
client: httpx.Client,
|
|
25
|
-
) ->
|
|
25
|
+
) -> AgentListResponse:
|
|
26
26
|
"""List all agents from the registry with their ECR image URIs."""
|
|
27
27
|
|
|
28
28
|
request_args = _build_request_args()
|
|
29
29
|
|
|
30
30
|
response = client.request(**request_args)
|
|
31
31
|
raise_for_status(response)
|
|
32
|
-
return
|
|
32
|
+
return AgentListResponse.model_validate(response.json())
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
async def asyncio(
|
|
36
36
|
client: httpx.AsyncClient,
|
|
37
|
-
) ->
|
|
37
|
+
) -> AgentListResponse:
|
|
38
38
|
"""List all agents from the registry with their ECR image URIs."""
|
|
39
39
|
|
|
40
40
|
request_args = _build_request_args()
|
|
41
41
|
|
|
42
42
|
response = await client.request(**request_args)
|
|
43
43
|
raise_for_status(response)
|
|
44
|
-
return
|
|
44
|
+
return AgentListResponse.model_validate(response.json())
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"""API endpoints."""
|
|
2
2
|
|
|
3
|
-
from . import create_runtime, delete_runtime, get_runtime, list_runtimes, test_runtime
|
|
3
|
+
from . import create_runtime, delete_runtime, get_runtime, get_runtime_logs, list_runtimes, test_runtime
|
|
4
4
|
|
|
5
5
|
__all__ = [
|
|
6
6
|
"list_runtimes",
|
|
7
7
|
"create_runtime",
|
|
8
8
|
"get_runtime",
|
|
9
9
|
"delete_runtime",
|
|
10
|
+
"get_runtime_logs",
|
|
10
11
|
"test_runtime",
|
|
11
12
|
]
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Get Runtime Logs"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _build_request_args(
|
|
13
|
+
artifact_id: str,
|
|
14
|
+
x_api_key: str | None = None,
|
|
15
|
+
) -> dict[str, Any]:
|
|
16
|
+
"""Build request arguments."""
|
|
17
|
+
url = f"/api/runtimes/{artifact_id}/logs"
|
|
18
|
+
|
|
19
|
+
headers: dict[str, str] = {}
|
|
20
|
+
if x_api_key is not None:
|
|
21
|
+
headers["X-API-Key"] = x_api_key
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
"method": "GET",
|
|
25
|
+
"url": url,
|
|
26
|
+
"headers": headers,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def sync(
|
|
31
|
+
client: httpx.Client,
|
|
32
|
+
artifact_id: str,
|
|
33
|
+
x_api_key: str | None = None,
|
|
34
|
+
) -> dict[str, Any]:
|
|
35
|
+
"""Get live build logs for a runtime by connecting to the VM."""
|
|
36
|
+
|
|
37
|
+
request_args = _build_request_args(
|
|
38
|
+
artifact_id=artifact_id,
|
|
39
|
+
x_api_key=x_api_key,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
response = client.request(**request_args)
|
|
43
|
+
raise_for_status(response)
|
|
44
|
+
return response.json()
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def asyncio(
|
|
48
|
+
client: httpx.AsyncClient,
|
|
49
|
+
artifact_id: str,
|
|
50
|
+
x_api_key: str | None = None,
|
|
51
|
+
) -> dict[str, Any]:
|
|
52
|
+
"""Get live build logs for a runtime by connecting to the VM."""
|
|
53
|
+
|
|
54
|
+
request_args = _build_request_args(
|
|
55
|
+
artifact_id=artifact_id,
|
|
56
|
+
x_api_key=x_api_key,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
response = await client.request(**request_args)
|
|
60
|
+
raise_for_status(response)
|
|
61
|
+
return response.json()
|
|
@@ -1,10 +1,33 @@
|
|
|
1
1
|
"""API endpoints."""
|
|
2
2
|
|
|
3
|
-
from . import
|
|
3
|
+
from . import (
|
|
4
|
+
close_session,
|
|
5
|
+
complete_session,
|
|
6
|
+
create_session,
|
|
7
|
+
get_session,
|
|
8
|
+
get_session_bash_logs_download,
|
|
9
|
+
get_session_envs,
|
|
10
|
+
get_session_live_logs,
|
|
11
|
+
get_session_logs,
|
|
12
|
+
get_session_logs_download,
|
|
13
|
+
get_session_status,
|
|
14
|
+
list_sessions,
|
|
15
|
+
list_tags,
|
|
16
|
+
update_session_tags,
|
|
17
|
+
)
|
|
4
18
|
|
|
5
19
|
__all__ = [
|
|
6
20
|
"list_sessions",
|
|
21
|
+
"create_session",
|
|
22
|
+
"list_tags",
|
|
7
23
|
"get_session",
|
|
24
|
+
"get_session_status",
|
|
25
|
+
"update_session_tags",
|
|
26
|
+
"complete_session",
|
|
8
27
|
"get_session_logs",
|
|
9
28
|
"get_session_logs_download",
|
|
29
|
+
"get_session_bash_logs_download",
|
|
30
|
+
"get_session_envs",
|
|
31
|
+
"get_session_live_logs",
|
|
32
|
+
"close_session",
|
|
10
33
|
]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Close Session"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import CloseSessionResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
public_id: str,
|
|
15
|
+
x_api_key: str | None = None,
|
|
16
|
+
) -> dict[str, Any]:
|
|
17
|
+
"""Build request arguments."""
|
|
18
|
+
url = f"/api/sessions/{public_id}/close"
|
|
19
|
+
|
|
20
|
+
headers: dict[str, str] = {}
|
|
21
|
+
if x_api_key is not None:
|
|
22
|
+
headers["X-API-Key"] = x_api_key
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
"method": "POST",
|
|
26
|
+
"url": url,
|
|
27
|
+
"headers": headers,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def sync(
|
|
32
|
+
client: httpx.Client,
|
|
33
|
+
public_id: str,
|
|
34
|
+
x_api_key: str | None = None,
|
|
35
|
+
) -> CloseSessionResponse:
|
|
36
|
+
"""Close a running session.
|
|
37
|
+
|
|
38
|
+
Updates the session status to cancelled and closes the Plato session."""
|
|
39
|
+
|
|
40
|
+
request_args = _build_request_args(
|
|
41
|
+
public_id=public_id,
|
|
42
|
+
x_api_key=x_api_key,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
response = client.request(**request_args)
|
|
46
|
+
raise_for_status(response)
|
|
47
|
+
return CloseSessionResponse.model_validate(response.json())
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
async def asyncio(
|
|
51
|
+
client: httpx.AsyncClient,
|
|
52
|
+
public_id: str,
|
|
53
|
+
x_api_key: str | None = None,
|
|
54
|
+
) -> CloseSessionResponse:
|
|
55
|
+
"""Close a running session.
|
|
56
|
+
|
|
57
|
+
Updates the session status to cancelled and closes the Plato session."""
|
|
58
|
+
|
|
59
|
+
request_args = _build_request_args(
|
|
60
|
+
public_id=public_id,
|
|
61
|
+
x_api_key=x_api_key,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
response = await client.request(**request_args)
|
|
65
|
+
raise_for_status(response)
|
|
66
|
+
return CloseSessionResponse.model_validate(response.json())
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Complete Session"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
from plato.chronos.errors import raise_for_status
|
|
10
|
+
from plato.chronos.models import CompleteSessionRequest, SessionResponse
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _build_request_args(
|
|
14
|
+
public_id: str,
|
|
15
|
+
body: CompleteSessionRequest,
|
|
16
|
+
x_api_key: str | None = None,
|
|
17
|
+
) -> dict[str, Any]:
|
|
18
|
+
"""Build request arguments."""
|
|
19
|
+
url = f"/api/sessions/{public_id}/complete"
|
|
20
|
+
|
|
21
|
+
headers: dict[str, str] = {}
|
|
22
|
+
if x_api_key is not None:
|
|
23
|
+
headers["X-API-Key"] = x_api_key
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
"method": "POST",
|
|
27
|
+
"url": url,
|
|
28
|
+
"json": body.model_dump(mode="json", exclude_none=True),
|
|
29
|
+
"headers": headers,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def sync(
|
|
34
|
+
client: httpx.Client,
|
|
35
|
+
public_id: str,
|
|
36
|
+
body: CompleteSessionRequest,
|
|
37
|
+
x_api_key: str | None = None,
|
|
38
|
+
) -> SessionResponse:
|
|
39
|
+
"""Mark a session as completed or failed.
|
|
40
|
+
|
|
41
|
+
Called by the bootstrap script when the world runner finishes.
|
|
42
|
+
Uses API key auth (no org check) since it's called from the VM."""
|
|
43
|
+
|
|
44
|
+
request_args = _build_request_args(
|
|
45
|
+
public_id=public_id,
|
|
46
|
+
body=body,
|
|
47
|
+
x_api_key=x_api_key,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
response = client.request(**request_args)
|
|
51
|
+
raise_for_status(response)
|
|
52
|
+
return SessionResponse.model_validate(response.json())
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def asyncio(
|
|
56
|
+
client: httpx.AsyncClient,
|
|
57
|
+
public_id: str,
|
|
58
|
+
body: CompleteSessionRequest,
|
|
59
|
+
x_api_key: str | None = None,
|
|
60
|
+
) -> SessionResponse:
|
|
61
|
+
"""Mark a session as completed or failed.
|
|
62
|
+
|
|
63
|
+
Called by the bootstrap script when the world runner finishes.
|
|
64
|
+
Uses API key auth (no org check) since it's called from the VM."""
|
|
65
|
+
|
|
66
|
+
request_args = _build_request_args(
|
|
67
|
+
public_id=public_id,
|
|
68
|
+
body=body,
|
|
69
|
+
x_api_key=x_api_key,
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
response = await client.request(**request_args)
|
|
73
|
+
raise_for_status(response)
|
|
74
|
+
return SessionResponse.model_validate(response.json())
|