plato-sdk-v2 2.0.50__py3-none-any.whl → 2.2.4__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/__init__.py +7 -6
- plato/_generated/__init__.py +1 -1
- plato/_generated/api/v1/env/evaluate_session.py +3 -3
- plato/_generated/api/v1/env/log_state_mutation.py +4 -4
- plato/_generated/api/v1/sandbox/checkpoint_vm.py +3 -3
- plato/_generated/api/v1/sandbox/save_vm_snapshot.py +3 -3
- plato/_generated/api/v1/sandbox/setup_sandbox.py +8 -8
- plato/_generated/api/v1/session/__init__.py +2 -0
- plato/_generated/api/v1/session/get_sessions_for_archival.py +100 -0
- plato/_generated/api/v1/testcases/__init__.py +6 -2
- plato/_generated/api/v1/testcases/get_mutation_groups_for_testcase.py +98 -0
- plato/_generated/api/v1/testcases/{get_next_output_testcase_for_scoring.py → get_next_testcase_for_scoring.py} +23 -10
- plato/_generated/api/v1/testcases/get_testcase_metadata_for_scoring.py +74 -0
- plato/_generated/api/v2/__init__.py +2 -1
- plato/_generated/api/v2/jobs/__init__.py +4 -0
- plato/_generated/api/v2/jobs/checkpoint.py +3 -3
- plato/_generated/api/v2/jobs/disk_snapshot.py +3 -3
- plato/_generated/api/v2/jobs/log_for_job.py +4 -39
- plato/_generated/api/v2/jobs/make.py +4 -4
- plato/_generated/api/v2/jobs/setup_sandbox.py +97 -0
- plato/_generated/api/v2/jobs/snapshot.py +3 -3
- plato/_generated/api/v2/jobs/snapshot_store.py +91 -0
- plato/_generated/api/v2/sessions/__init__.py +4 -0
- plato/_generated/api/v2/sessions/checkpoint.py +3 -3
- plato/_generated/api/v2/sessions/disk_snapshot.py +3 -3
- plato/_generated/api/v2/sessions/evaluate.py +3 -3
- plato/_generated/api/v2/sessions/log_job_mutation.py +4 -39
- plato/_generated/api/v2/sessions/make.py +4 -4
- plato/_generated/api/v2/sessions/setup_sandbox.py +98 -0
- plato/_generated/api/v2/sessions/snapshot.py +3 -3
- plato/_generated/api/v2/sessions/snapshot_store.py +94 -0
- plato/_generated/api/v2/user/__init__.py +7 -0
- plato/_generated/api/v2/user/get_current_user.py +76 -0
- plato/_generated/models/__init__.py +174 -23
- plato/_sims_generator/__init__.py +19 -4
- plato/_sims_generator/instruction.py +203 -0
- plato/_sims_generator/templates/instruction/helpers.py.jinja +161 -0
- plato/_sims_generator/templates/instruction/init.py.jinja +43 -0
- plato/agents/__init__.py +107 -517
- plato/agents/base.py +145 -0
- plato/agents/build.py +61 -0
- plato/agents/config.py +160 -0
- plato/agents/logging.py +401 -0
- plato/agents/runner.py +161 -0
- plato/agents/trajectory.py +266 -0
- plato/chronos/__init__.py +37 -0
- plato/chronos/api/__init__.py +3 -0
- plato/chronos/api/agents/__init__.py +13 -0
- plato/chronos/api/agents/create_agent.py +63 -0
- plato/chronos/api/agents/delete_agent.py +61 -0
- plato/chronos/api/agents/get_agent.py +62 -0
- plato/chronos/api/agents/get_agent_schema.py +72 -0
- plato/chronos/api/agents/get_agent_versions.py +62 -0
- plato/chronos/api/agents/list_agents.py +57 -0
- plato/chronos/api/agents/lookup_agent.py +74 -0
- plato/chronos/api/auth/__init__.py +9 -0
- plato/chronos/api/auth/debug_auth_api_auth_debug_get.py +43 -0
- plato/chronos/api/auth/get_auth_status_api_auth_status_get.py +61 -0
- plato/chronos/api/auth/get_current_user_route_api_auth_me_get.py +60 -0
- plato/chronos/api/callback/__init__.py +11 -0
- plato/chronos/api/callback/push_agent_logs.py +61 -0
- plato/chronos/api/callback/update_agent_status.py +57 -0
- plato/chronos/api/callback/upload_artifacts.py +59 -0
- plato/chronos/api/callback/upload_logs_zip.py +57 -0
- plato/chronos/api/callback/upload_trajectory.py +57 -0
- plato/chronos/api/default/__init__.py +7 -0
- plato/chronos/api/default/health.py +43 -0
- plato/chronos/api/jobs/__init__.py +7 -0
- plato/chronos/api/jobs/launch_job.py +63 -0
- plato/chronos/api/registry/__init__.py +19 -0
- plato/chronos/api/registry/get_agent_schema_api_registry_agents__agent_name__schema_get.py +62 -0
- plato/chronos/api/registry/get_agent_versions_api_registry_agents__agent_name__versions_get.py +52 -0
- plato/chronos/api/registry/get_world_schema_api_registry_worlds__package_name__schema_get.py +68 -0
- plato/chronos/api/registry/get_world_versions_api_registry_worlds__package_name__versions_get.py +52 -0
- plato/chronos/api/registry/list_registry_agents_api_registry_agents_get.py +44 -0
- plato/chronos/api/registry/list_registry_worlds_api_registry_worlds_get.py +44 -0
- plato/chronos/api/runtimes/__init__.py +11 -0
- plato/chronos/api/runtimes/create_runtime.py +63 -0
- plato/chronos/api/runtimes/delete_runtime.py +61 -0
- plato/chronos/api/runtimes/get_runtime.py +62 -0
- plato/chronos/api/runtimes/list_runtimes.py +57 -0
- plato/chronos/api/runtimes/test_runtime.py +67 -0
- plato/chronos/api/secrets/__init__.py +11 -0
- plato/chronos/api/secrets/create_secret.py +63 -0
- plato/chronos/api/secrets/delete_secret.py +61 -0
- plato/chronos/api/secrets/get_secret.py +62 -0
- plato/chronos/api/secrets/list_secrets.py +57 -0
- plato/chronos/api/secrets/update_secret.py +68 -0
- plato/chronos/api/sessions/__init__.py +10 -0
- plato/chronos/api/sessions/get_session.py +62 -0
- plato/chronos/api/sessions/get_session_logs.py +72 -0
- plato/chronos/api/sessions/get_session_logs_download.py +62 -0
- plato/chronos/api/sessions/list_sessions.py +57 -0
- plato/chronos/api/status/__init__.py +8 -0
- plato/chronos/api/status/get_status_api_status_get.py +44 -0
- plato/chronos/api/status/get_version_info_api_version_get.py +44 -0
- plato/chronos/api/templates/__init__.py +11 -0
- plato/chronos/api/templates/create_template.py +63 -0
- plato/chronos/api/templates/delete_template.py +61 -0
- plato/chronos/api/templates/get_template.py +62 -0
- plato/chronos/api/templates/list_templates.py +57 -0
- plato/chronos/api/templates/update_template.py +68 -0
- plato/chronos/api/trajectories/__init__.py +8 -0
- plato/chronos/api/trajectories/get_trajectory.py +62 -0
- plato/chronos/api/trajectories/list_trajectories.py +62 -0
- plato/chronos/api/worlds/__init__.py +10 -0
- plato/chronos/api/worlds/create_world.py +63 -0
- plato/chronos/api/worlds/delete_world.py +61 -0
- plato/chronos/api/worlds/get_world.py +62 -0
- plato/chronos/api/worlds/list_worlds.py +57 -0
- plato/chronos/client.py +171 -0
- plato/chronos/errors.py +141 -0
- plato/chronos/models/__init__.py +647 -0
- plato/chronos/py.typed +0 -0
- plato/sims/cli.py +299 -123
- plato/sims/registry.py +77 -4
- plato/v1/cli/agent.py +88 -84
- plato/v1/cli/main.py +2 -0
- plato/v1/cli/pm.py +441 -119
- plato/v1/cli/sandbox.py +747 -191
- plato/v1/cli/sim.py +11 -0
- plato/v1/cli/verify.py +1269 -0
- plato/v1/cli/world.py +3 -0
- plato/v1/flow_executor.py +21 -17
- plato/v1/models/env.py +11 -11
- plato/v1/sdk.py +2 -2
- plato/v1/sync_env.py +11 -11
- plato/v1/sync_flow_executor.py +21 -17
- plato/v1/sync_sdk.py +4 -2
- plato/v2/__init__.py +2 -0
- plato/v2/async_/environment.py +20 -1
- plato/v2/async_/session.py +54 -3
- plato/v2/sync/environment.py +2 -1
- plato/v2/sync/session.py +52 -2
- plato/worlds/README.md +218 -0
- plato/worlds/__init__.py +54 -18
- plato/worlds/base.py +304 -93
- plato/worlds/config.py +239 -73
- plato/worlds/runner.py +391 -80
- {plato_sdk_v2-2.0.50.dist-info → plato_sdk_v2-2.2.4.dist-info}/METADATA +1 -3
- {plato_sdk_v2-2.0.50.dist-info → plato_sdk_v2-2.2.4.dist-info}/RECORD +143 -68
- {plato_sdk_v2-2.0.50.dist-info → plato_sdk_v2-2.2.4.dist-info}/entry_points.txt +1 -0
- plato/_generated/api/v2/interfaces/__init__.py +0 -27
- plato/_generated/api/v2/interfaces/v2_interface_browser_create.py +0 -68
- plato/_generated/api/v2/interfaces/v2_interface_cdp_url.py +0 -65
- plato/_generated/api/v2/interfaces/v2_interface_click.py +0 -64
- plato/_generated/api/v2/interfaces/v2_interface_close.py +0 -59
- plato/_generated/api/v2/interfaces/v2_interface_computer_create.py +0 -68
- plato/_generated/api/v2/interfaces/v2_interface_cursor.py +0 -64
- plato/_generated/api/v2/interfaces/v2_interface_key.py +0 -68
- plato/_generated/api/v2/interfaces/v2_interface_screenshot.py +0 -65
- plato/_generated/api/v2/interfaces/v2_interface_scroll.py +0 -70
- plato/_generated/api/v2/interfaces/v2_interface_type.py +0 -64
- plato/world/__init__.py +0 -44
- plato/world/base.py +0 -267
- plato/world/config.py +0 -139
- plato/world/types.py +0 -47
- {plato_sdk_v2-2.0.50.dist-info → plato_sdk_v2-2.2.4.dist-info}/WHEEL +0 -0
plato/v2/sync/session.py
CHANGED
|
@@ -12,10 +12,13 @@ import uuid
|
|
|
12
12
|
from dataclasses import dataclass
|
|
13
13
|
from datetime import datetime
|
|
14
14
|
from pathlib import Path
|
|
15
|
+
from typing import TYPE_CHECKING
|
|
15
16
|
|
|
16
17
|
import httpx
|
|
17
18
|
import tenacity
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
if TYPE_CHECKING:
|
|
21
|
+
from playwright.sync_api import Browser, BrowserContext, Page
|
|
19
22
|
|
|
20
23
|
from plato._generated.api.v2.jobs import get_flows as jobs_get_flows
|
|
21
24
|
from plato._generated.api.v2.jobs import public_url as jobs_public_url
|
|
@@ -27,6 +30,7 @@ from plato._generated.api.v2.sessions import heartbeat as sessions_heartbeat
|
|
|
27
30
|
from plato._generated.api.v2.sessions import make as sessions_make
|
|
28
31
|
from plato._generated.api.v2.sessions import reset as sessions_reset
|
|
29
32
|
from plato._generated.api.v2.sessions import set_date as sessions_set_date
|
|
33
|
+
from plato._generated.api.v2.sessions import setup_sandbox as sessions_setup_sandbox
|
|
30
34
|
from plato._generated.api.v2.sessions import snapshot as sessions_snapshot
|
|
31
35
|
from plato._generated.api.v2.sessions import state as sessions_state
|
|
32
36
|
from plato._generated.api.v2.sessions import wait_for_ready as sessions_wait_for_ready
|
|
@@ -35,6 +39,8 @@ from plato._generated.models import (
|
|
|
35
39
|
AppApiV2SchemasSessionCreateSnapshotResponse,
|
|
36
40
|
AppApiV2SchemasSessionEvaluateResponse,
|
|
37
41
|
AppApiV2SchemasSessionHeartbeatResponse,
|
|
42
|
+
AppApiV2SchemasSessionSetupSandboxRequest,
|
|
43
|
+
AppApiV2SchemasSessionSetupSandboxResponse,
|
|
38
44
|
CreateDiskSnapshotRequest,
|
|
39
45
|
CreateDiskSnapshotResponse,
|
|
40
46
|
CreateSessionFromEnvs,
|
|
@@ -63,6 +69,8 @@ logger = logging.getLogger(__name__)
|
|
|
63
69
|
class LoginResult:
|
|
64
70
|
"""Result of login operation containing browser context and pages.
|
|
65
71
|
|
|
72
|
+
Requires playwright to be installed.
|
|
73
|
+
|
|
66
74
|
Attributes:
|
|
67
75
|
context: The Playwright BrowserContext used for all pages.
|
|
68
76
|
pages: Dict mapping env alias to the logged-in Page.
|
|
@@ -265,9 +273,10 @@ class Session:
|
|
|
265
273
|
)
|
|
266
274
|
|
|
267
275
|
# Use generated API function
|
|
276
|
+
# Note: API supports both CreateSessionFromEnvs and CreateSessionFromTask via discriminator
|
|
268
277
|
response = sessions_make.sync(
|
|
269
278
|
client=http_client,
|
|
270
|
-
body=request_body,
|
|
279
|
+
body=request_body, # type: ignore[arg-type]
|
|
271
280
|
x_api_key=api_key,
|
|
272
281
|
)
|
|
273
282
|
|
|
@@ -524,6 +533,38 @@ class Session:
|
|
|
524
533
|
x_api_key=self._api_key,
|
|
525
534
|
)
|
|
526
535
|
|
|
536
|
+
def setup_sandbox(
|
|
537
|
+
self,
|
|
538
|
+
timeout: int = 120,
|
|
539
|
+
) -> AppApiV2SchemasSessionSetupSandboxResponse:
|
|
540
|
+
"""Setup sandbox environment with Docker overlay on all environments.
|
|
541
|
+
|
|
542
|
+
This configures the VMs for Docker usage with overlay2 storage driver,
|
|
543
|
+
which is significantly faster than the default vfs driver. Should be called
|
|
544
|
+
after session creation and before pulling Docker images.
|
|
545
|
+
|
|
546
|
+
The setup includes:
|
|
547
|
+
- Mounting /dev/vdb to /mnt/docker for Docker storage
|
|
548
|
+
- Configuring Docker with overlay2 storage driver
|
|
549
|
+
- Setting up ECR and Docker Hub authentication
|
|
550
|
+
- Creating a docker-user service for non-root Docker access
|
|
551
|
+
|
|
552
|
+
Args:
|
|
553
|
+
timeout: Setup timeout in seconds (default: 120).
|
|
554
|
+
|
|
555
|
+
Returns:
|
|
556
|
+
SetupSandboxResponse with results per job_id.
|
|
557
|
+
"""
|
|
558
|
+
self._check_closed()
|
|
559
|
+
|
|
560
|
+
request = AppApiV2SchemasSessionSetupSandboxRequest(timeout=timeout)
|
|
561
|
+
return sessions_setup_sandbox.sync(
|
|
562
|
+
client=self._http,
|
|
563
|
+
session_id=self.session_id,
|
|
564
|
+
body=request,
|
|
565
|
+
x_api_key=self._api_key,
|
|
566
|
+
)
|
|
567
|
+
|
|
527
568
|
def evaluate(self, **kwargs) -> AppApiV2SchemasSessionEvaluateResponse:
|
|
528
569
|
"""Evaluate the session against task criteria.
|
|
529
570
|
|
|
@@ -600,6 +641,9 @@ class Session:
|
|
|
600
641
|
Navigates each page to the environment's public URL and executes
|
|
601
642
|
the login flow using the v1 SyncFlowExecutor.
|
|
602
643
|
|
|
644
|
+
Requires playwright to be installed:
|
|
645
|
+
pip install playwright
|
|
646
|
+
|
|
603
647
|
Args:
|
|
604
648
|
browser: Playwright Browser instance.
|
|
605
649
|
dataset: Dataset name for login flow (default: "base" uses "login" flow).
|
|
@@ -612,9 +656,15 @@ class Session:
|
|
|
612
656
|
|
|
613
657
|
Raises:
|
|
614
658
|
RuntimeError: If login fails.
|
|
659
|
+
ImportError: If playwright is not installed.
|
|
615
660
|
"""
|
|
616
661
|
self._check_closed()
|
|
617
662
|
|
|
663
|
+
import importlib.util
|
|
664
|
+
|
|
665
|
+
if importlib.util.find_spec("playwright") is None:
|
|
666
|
+
raise ImportError("The login() method requires playwright. Install it with: pip install playwright")
|
|
667
|
+
|
|
618
668
|
context = browser.new_context()
|
|
619
669
|
pages: dict[str, Page] = {}
|
|
620
670
|
|
plato/worlds/README.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Plato Worlds - Local Development Guide
|
|
2
|
+
|
|
3
|
+
Run Plato worlds locally for development and testing.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# List available worlds
|
|
9
|
+
plato-world-runner list
|
|
10
|
+
|
|
11
|
+
# Run a world with a config file
|
|
12
|
+
plato-world-runner run --world <name> --config config.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Config File Format
|
|
16
|
+
|
|
17
|
+
Create a JSON config file:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"repository_url": "https://github.com/example/repo",
|
|
22
|
+
"prompt": "Fix the bug in main.py",
|
|
23
|
+
"coder": {
|
|
24
|
+
"image": "my-agent:latest",
|
|
25
|
+
"config": {
|
|
26
|
+
"model": "gpt-4"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"git_token": "ghp_...",
|
|
30
|
+
"session_id": "local-test-001",
|
|
31
|
+
"callback_url": ""
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or with nested format (backwards compatible):
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"world_config": {
|
|
40
|
+
"repository_url": "https://github.com/example/repo",
|
|
41
|
+
"prompt": "Fix the bug in main.py"
|
|
42
|
+
},
|
|
43
|
+
"agents": {
|
|
44
|
+
"coder": {
|
|
45
|
+
"image": "my-agent:latest"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"secrets": {
|
|
49
|
+
"git_token": "ghp_..."
|
|
50
|
+
},
|
|
51
|
+
"session_id": "local-test-001"
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Creating a World
|
|
56
|
+
|
|
57
|
+
### 1. Define the Config and World Class
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from typing import Annotated
|
|
61
|
+
from plato.worlds import (
|
|
62
|
+
BaseWorld, RunConfig, Agent, Secret, AgentConfig,
|
|
63
|
+
Observation, StepResult, register_world
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
class MyWorldConfig(RunConfig):
|
|
67
|
+
"""Typed config - all fields accessible directly."""
|
|
68
|
+
|
|
69
|
+
# World-specific fields
|
|
70
|
+
prompt: str
|
|
71
|
+
max_steps: int = 10
|
|
72
|
+
|
|
73
|
+
# Agents (typed, no .get() needed)
|
|
74
|
+
worker: Annotated[AgentConfig, Agent(description="The main agent")]
|
|
75
|
+
|
|
76
|
+
# Secrets (typed, optional)
|
|
77
|
+
api_key: Annotated[str | None, Secret(description="API key")] = None
|
|
78
|
+
|
|
79
|
+
@register_world("my-world")
|
|
80
|
+
class MyWorld(BaseWorld[MyWorldConfig]):
|
|
81
|
+
name = "my-world"
|
|
82
|
+
description = "A simple example world"
|
|
83
|
+
|
|
84
|
+
async def reset(self) -> Observation:
|
|
85
|
+
"""Setup the world. Access config via self.config."""
|
|
86
|
+
# All access is typed - no .get() methods
|
|
87
|
+
prompt = self.config.prompt # str
|
|
88
|
+
worker = self.config.worker # AgentConfig
|
|
89
|
+
api_key = self.config.api_key # str | None
|
|
90
|
+
|
|
91
|
+
return Observation(data={"prompt": prompt})
|
|
92
|
+
|
|
93
|
+
async def step(self) -> StepResult:
|
|
94
|
+
"""Execute one step."""
|
|
95
|
+
return StepResult(
|
|
96
|
+
observation=Observation(data={"status": "done"}),
|
|
97
|
+
done=True,
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
async def close(self) -> None:
|
|
101
|
+
"""Cleanup resources."""
|
|
102
|
+
pass
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 2. Register via Entry Point
|
|
106
|
+
|
|
107
|
+
In your `pyproject.toml`:
|
|
108
|
+
|
|
109
|
+
```toml
|
|
110
|
+
[project.entry-points."plato.worlds"]
|
|
111
|
+
my-world = "my_world:MyWorld"
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3. Run It
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Install your package
|
|
118
|
+
pip install -e .
|
|
119
|
+
|
|
120
|
+
# Verify it's registered
|
|
121
|
+
plato-world-runner list
|
|
122
|
+
|
|
123
|
+
# Run with config
|
|
124
|
+
plato-world-runner run --world my-world --config config.json -v
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Programmatic Usage
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
import asyncio
|
|
131
|
+
from plato.worlds import run_world
|
|
132
|
+
from my_world import MyWorldConfig, AgentConfig
|
|
133
|
+
|
|
134
|
+
config = MyWorldConfig(
|
|
135
|
+
prompt="Hello world",
|
|
136
|
+
worker=AgentConfig(image="agent:latest"),
|
|
137
|
+
api_key="secret",
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
asyncio.run(run_world("my-world", config))
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Or load from a file:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
from my_world import MyWorldConfig
|
|
147
|
+
|
|
148
|
+
config = MyWorldConfig.from_file("config.json")
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## CLI Options
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
plato-world-runner [COMMAND] [OPTIONS]
|
|
155
|
+
|
|
156
|
+
Commands:
|
|
157
|
+
run Run a world with the given configuration
|
|
158
|
+
list List available worlds
|
|
159
|
+
|
|
160
|
+
Run options:
|
|
161
|
+
-w, --world TEXT World name to run (required)
|
|
162
|
+
-c, --config PATH Path to config JSON file (required)
|
|
163
|
+
-v, --verbose Enable debug logging
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## World Lifecycle
|
|
167
|
+
|
|
168
|
+
1. **Discovery**: Worlds are discovered via `plato.worlds` entry points
|
|
169
|
+
2. **Instantiation**: World class is instantiated
|
|
170
|
+
3. **Reset**: `reset()` is called to setup the world (config available via `self.config`)
|
|
171
|
+
4. **Step Loop**: `step()` is called repeatedly until `done=True`
|
|
172
|
+
5. **Cleanup**: `close()` is called to cleanup resources
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
┌───────────────────────────────────────────────┐
|
|
176
|
+
│ plato-world-runner run --world X --config Y │
|
|
177
|
+
└───────────────────────────────────────────────┘
|
|
178
|
+
│
|
|
179
|
+
▼
|
|
180
|
+
┌─────────────────┐
|
|
181
|
+
│ discover_worlds │
|
|
182
|
+
└─────────────────┘
|
|
183
|
+
│
|
|
184
|
+
▼
|
|
185
|
+
┌─────────────────┐
|
|
186
|
+
│ world.reset() │
|
|
187
|
+
└─────────────────┘
|
|
188
|
+
│
|
|
189
|
+
▼
|
|
190
|
+
┌─────────────────┐
|
|
191
|
+
│ world.step() │◄──┐
|
|
192
|
+
└─────────────────┘ │
|
|
193
|
+
│ │
|
|
194
|
+
┌───┴───┐ │
|
|
195
|
+
│ done? │───No──┘
|
|
196
|
+
└───┬───┘
|
|
197
|
+
Yes
|
|
198
|
+
│
|
|
199
|
+
▼
|
|
200
|
+
┌─────────────────┐
|
|
201
|
+
│ world.close() │
|
|
202
|
+
└─────────────────┘
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## Debugging
|
|
206
|
+
|
|
207
|
+
Enable verbose logging:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
plato-world-runner run --world my-world --config config.json --verbose
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Or set log level in code:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
import logging
|
|
217
|
+
logging.basicConfig(level=logging.DEBUG)
|
|
218
|
+
```
|
plato/worlds/__init__.py
CHANGED
|
@@ -1,44 +1,80 @@
|
|
|
1
|
-
"""Plato Worlds -
|
|
2
|
-
|
|
3
|
-
A World defines:
|
|
4
|
-
- Available agent slots (list of strings)
|
|
5
|
-
- Configuration schema
|
|
6
|
-
- Run logic (what happens when the world executes)
|
|
1
|
+
"""Plato Worlds - typed world definitions for agent execution.
|
|
7
2
|
|
|
8
3
|
Usage:
|
|
9
|
-
from plato.worlds import BaseWorld,
|
|
4
|
+
from plato.worlds import BaseWorld, RunConfig, Agent, Secret, Env, AgentConfig, EnvConfig, register_world
|
|
5
|
+
from plato._generated.models import EnvFromArtifact, EnvFromSimulator
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
class CodeWorldConfig(RunConfig):
|
|
9
|
+
# World-specific fields
|
|
10
|
+
repository_url: str
|
|
11
|
+
prompt: str
|
|
12
|
+
|
|
13
|
+
# Agents (typed)
|
|
14
|
+
coder: Annotated[AgentConfig, Agent(description="Coding agent")]
|
|
15
|
+
|
|
16
|
+
# Secrets (typed)
|
|
17
|
+
git_token: Annotated[str | None, Secret(description="GitHub token")] = None
|
|
18
|
+
|
|
19
|
+
# Environments (typed)
|
|
20
|
+
gitea: Annotated[EnvConfig, Env(description="Git server")] = EnvFromArtifact(
|
|
21
|
+
artifact_id="abc123",
|
|
22
|
+
alias="gitea",
|
|
23
|
+
)
|
|
10
24
|
|
|
11
25
|
@register_world("code")
|
|
12
|
-
class CodeWorld(BaseWorld):
|
|
13
|
-
|
|
26
|
+
class CodeWorld(BaseWorld[CodeWorldConfig]):
|
|
27
|
+
name = "code"
|
|
28
|
+
description = "Run coding agents"
|
|
29
|
+
|
|
30
|
+
async def reset(self) -> Observation:
|
|
31
|
+
# Fully typed access
|
|
32
|
+
url = self.config.repository_url
|
|
33
|
+
agent = self.config.coder
|
|
34
|
+
token = self.config.git_token
|
|
35
|
+
gitea = self.config.gitea # EnvConfig
|
|
14
36
|
|
|
15
|
-
async def
|
|
16
|
-
|
|
17
|
-
pass
|
|
37
|
+
async def step(self) -> StepResult:
|
|
38
|
+
...
|
|
18
39
|
"""
|
|
19
40
|
|
|
41
|
+
from plato._generated.models import (
|
|
42
|
+
EnvFromArtifact,
|
|
43
|
+
EnvFromResource,
|
|
44
|
+
EnvFromSimulator,
|
|
45
|
+
)
|
|
20
46
|
from plato.worlds.base import (
|
|
21
|
-
AgentSlot,
|
|
22
47
|
BaseWorld,
|
|
48
|
+
ConfigT,
|
|
23
49
|
Observation,
|
|
24
50
|
StepResult,
|
|
25
51
|
get_registered_worlds,
|
|
26
52
|
get_world,
|
|
27
53
|
register_world,
|
|
28
54
|
)
|
|
29
|
-
from plato.worlds.config import AgentConfig, RunConfig,
|
|
55
|
+
from plato.worlds.config import Agent, AgentConfig, Env, EnvConfig, RunConfig, Secret
|
|
30
56
|
from plato.worlds.runner import run_world
|
|
31
57
|
|
|
32
58
|
__all__ = [
|
|
59
|
+
# Base
|
|
33
60
|
"BaseWorld",
|
|
34
|
-
"
|
|
61
|
+
"ConfigT",
|
|
35
62
|
"Observation",
|
|
36
63
|
"StepResult",
|
|
37
|
-
"WorldConfig",
|
|
38
|
-
"AgentConfig",
|
|
39
|
-
"RunConfig",
|
|
40
64
|
"register_world",
|
|
41
65
|
"get_registered_worlds",
|
|
42
66
|
"get_world",
|
|
67
|
+
# Config
|
|
68
|
+
"RunConfig",
|
|
69
|
+
"AgentConfig",
|
|
70
|
+
"Agent",
|
|
71
|
+
"Secret",
|
|
72
|
+
"Env",
|
|
73
|
+
"EnvConfig",
|
|
74
|
+
# Env types (re-exported from generated models)
|
|
75
|
+
"EnvFromArtifact",
|
|
76
|
+
"EnvFromSimulator",
|
|
77
|
+
"EnvFromResource",
|
|
78
|
+
# Runner
|
|
43
79
|
"run_world",
|
|
44
80
|
]
|