plato-sdk-v2 2.0.64__py3-none-any.whl → 2.3.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 +0 -9
- 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 +99 -430
- plato/agents/base.py +145 -0
- plato/agents/build.py +61 -0
- plato/agents/config.py +160 -0
- plato/agents/logging.py +515 -0
- plato/agents/runner.py +191 -0
- plato/agents/trajectory.py +266 -0
- plato/chronos/models/__init__.py +1 -1
- plato/sims/cli.py +299 -123
- plato/sims/registry.py +77 -4
- plato/v1/cli/agent.py +88 -84
- plato/v1/cli/pm.py +84 -44
- plato/v1/cli/sandbox.py +241 -61
- plato/v1/cli/ssh.py +16 -4
- plato/v1/cli/verify.py +685 -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 +31 -0
- plato/v2/async_/session.py +72 -4
- plato/v2/sync/environment.py +31 -0
- plato/v2/sync/session.py +72 -4
- plato/worlds/README.md +71 -56
- plato/worlds/__init__.py +56 -18
- plato/worlds/base.py +578 -93
- plato/worlds/config.py +276 -74
- plato/worlds/runner.py +475 -80
- {plato_sdk_v2-2.0.64.dist-info → plato_sdk_v2-2.3.4.dist-info}/METADATA +3 -3
- {plato_sdk_v2-2.0.64.dist-info → plato_sdk_v2-2.3.4.dist-info}/RECORD +41 -36
- {plato_sdk_v2-2.0.64.dist-info → plato_sdk_v2-2.3.4.dist-info}/entry_points.txt +1 -0
- plato/agents/callback.py +0 -246
- 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.64.dist-info → plato_sdk_v2-2.3.4.dist-info}/WHEEL +0 -0
plato/v2/sync/session.py
CHANGED
|
@@ -30,7 +30,9 @@ from plato._generated.api.v2.sessions import heartbeat as sessions_heartbeat
|
|
|
30
30
|
from plato._generated.api.v2.sessions import make as sessions_make
|
|
31
31
|
from plato._generated.api.v2.sessions import reset as sessions_reset
|
|
32
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
|
|
33
34
|
from plato._generated.api.v2.sessions import snapshot as sessions_snapshot
|
|
35
|
+
from plato._generated.api.v2.sessions import snapshot_store as sessions_snapshot_store
|
|
34
36
|
from plato._generated.api.v2.sessions import state as sessions_state
|
|
35
37
|
from plato._generated.api.v2.sessions import wait_for_ready as sessions_wait_for_ready
|
|
36
38
|
from plato._generated.models import (
|
|
@@ -38,6 +40,8 @@ from plato._generated.models import (
|
|
|
38
40
|
AppApiV2SchemasSessionCreateSnapshotResponse,
|
|
39
41
|
AppApiV2SchemasSessionEvaluateResponse,
|
|
40
42
|
AppApiV2SchemasSessionHeartbeatResponse,
|
|
43
|
+
AppApiV2SchemasSessionSetupSandboxRequest,
|
|
44
|
+
AppApiV2SchemasSessionSetupSandboxResponse,
|
|
41
45
|
CreateDiskSnapshotRequest,
|
|
42
46
|
CreateDiskSnapshotResponse,
|
|
43
47
|
CreateSessionFromEnvs,
|
|
@@ -530,6 +534,38 @@ class Session:
|
|
|
530
534
|
x_api_key=self._api_key,
|
|
531
535
|
)
|
|
532
536
|
|
|
537
|
+
def setup_sandbox(
|
|
538
|
+
self,
|
|
539
|
+
timeout: int = 120,
|
|
540
|
+
) -> AppApiV2SchemasSessionSetupSandboxResponse:
|
|
541
|
+
"""Setup sandbox environment with Docker overlay on all environments.
|
|
542
|
+
|
|
543
|
+
This configures the VMs for Docker usage with overlay2 storage driver,
|
|
544
|
+
which is significantly faster than the default vfs driver. Should be called
|
|
545
|
+
after session creation and before pulling Docker images.
|
|
546
|
+
|
|
547
|
+
The setup includes:
|
|
548
|
+
- Mounting /dev/vdb to /mnt/docker for Docker storage
|
|
549
|
+
- Configuring Docker with overlay2 storage driver
|
|
550
|
+
- Setting up ECR and Docker Hub authentication
|
|
551
|
+
- Creating a docker-user service for non-root Docker access
|
|
552
|
+
|
|
553
|
+
Args:
|
|
554
|
+
timeout: Setup timeout in seconds (default: 120).
|
|
555
|
+
|
|
556
|
+
Returns:
|
|
557
|
+
SetupSandboxResponse with results per job_id.
|
|
558
|
+
"""
|
|
559
|
+
self._check_closed()
|
|
560
|
+
|
|
561
|
+
request = AppApiV2SchemasSessionSetupSandboxRequest(timeout=timeout)
|
|
562
|
+
return sessions_setup_sandbox.sync(
|
|
563
|
+
client=self._http,
|
|
564
|
+
session_id=self.session_id,
|
|
565
|
+
body=request,
|
|
566
|
+
x_api_key=self._api_key,
|
|
567
|
+
)
|
|
568
|
+
|
|
533
569
|
def evaluate(self, **kwargs) -> AppApiV2SchemasSessionEvaluateResponse:
|
|
534
570
|
"""Evaluate the session against task criteria.
|
|
535
571
|
|
|
@@ -560,6 +596,38 @@ class Session:
|
|
|
560
596
|
x_api_key=self._api_key,
|
|
561
597
|
)
|
|
562
598
|
|
|
599
|
+
def snapshot_store(
|
|
600
|
+
self,
|
|
601
|
+
override_service: str | None = None,
|
|
602
|
+
override_version: str | None = None,
|
|
603
|
+
override_dataset: str | None = None,
|
|
604
|
+
) -> AppApiV2SchemasSessionCreateSnapshotResponse:
|
|
605
|
+
"""Create a snapshot-store snapshot of all environments in the session.
|
|
606
|
+
|
|
607
|
+
Uses the snapshot-store pipeline for chunk-based deduplication and
|
|
608
|
+
efficient storage. This is the preferred method for new base snapshots.
|
|
609
|
+
|
|
610
|
+
Args:
|
|
611
|
+
override_service: Override simulator/service name in artifact metadata.
|
|
612
|
+
override_version: Override version/git_hash in artifact metadata.
|
|
613
|
+
override_dataset: Override dataset name in artifact metadata.
|
|
614
|
+
|
|
615
|
+
Returns:
|
|
616
|
+
Snapshot response with info per job_id.
|
|
617
|
+
"""
|
|
618
|
+
self._check_closed()
|
|
619
|
+
|
|
620
|
+
return sessions_snapshot_store.sync(
|
|
621
|
+
client=self._http,
|
|
622
|
+
session_id=self.session_id,
|
|
623
|
+
body=AppApiV2SchemasSessionCreateSnapshotRequest(
|
|
624
|
+
override_service=override_service,
|
|
625
|
+
override_version=override_version,
|
|
626
|
+
override_dataset=override_dataset,
|
|
627
|
+
),
|
|
628
|
+
x_api_key=self._api_key,
|
|
629
|
+
)
|
|
630
|
+
|
|
563
631
|
def disk_snapshot(
|
|
564
632
|
self,
|
|
565
633
|
override_service: str | None = None,
|
|
@@ -625,10 +693,10 @@ class Session:
|
|
|
625
693
|
"""
|
|
626
694
|
self._check_closed()
|
|
627
695
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
raise ImportError("The login() method requires playwright. Install it with: pip install playwright")
|
|
696
|
+
import importlib.util
|
|
697
|
+
|
|
698
|
+
if importlib.util.find_spec("playwright") is None:
|
|
699
|
+
raise ImportError("The login() method requires playwright. Install it with: pip install playwright")
|
|
632
700
|
|
|
633
701
|
context = browser.new_context()
|
|
634
702
|
pages: dict[str, Page] = {}
|
plato/worlds/README.md
CHANGED
|
@@ -6,15 +6,33 @@ Run Plato worlds locally for development and testing.
|
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
# List available worlds
|
|
9
|
-
plato-world-runner
|
|
9
|
+
plato-world-runner list
|
|
10
10
|
|
|
11
11
|
# Run a world with a config file
|
|
12
|
-
plato-world-runner --world <name> --config config.json
|
|
12
|
+
plato-world-runner run --world <name> --config config.json
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
## Config File Format
|
|
16
16
|
|
|
17
|
-
Create a JSON config file
|
|
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):
|
|
18
36
|
|
|
19
37
|
```json
|
|
20
38
|
{
|
|
@@ -24,62 +42,56 @@ Create a JSON config file with the following structure:
|
|
|
24
42
|
},
|
|
25
43
|
"agents": {
|
|
26
44
|
"coder": {
|
|
27
|
-
"image": "my-agent:latest"
|
|
28
|
-
"config": {
|
|
29
|
-
"model": "gpt-4"
|
|
30
|
-
}
|
|
45
|
+
"image": "my-agent:latest"
|
|
31
46
|
}
|
|
32
47
|
},
|
|
33
48
|
"secrets": {
|
|
34
|
-
"
|
|
49
|
+
"git_token": "ghp_..."
|
|
35
50
|
},
|
|
36
|
-
"session_id": "local-test-001"
|
|
37
|
-
"callback_url": ""
|
|
51
|
+
"session_id": "local-test-001"
|
|
38
52
|
}
|
|
39
53
|
```
|
|
40
54
|
|
|
41
|
-
### Fields
|
|
42
|
-
|
|
43
|
-
| Field | Description |
|
|
44
|
-
|-------|-------------|
|
|
45
|
-
| `world_config` | World-specific configuration (varies by world) |
|
|
46
|
-
| `agents` | Map of slot name to agent config (`image` + optional `config`) |
|
|
47
|
-
| `secrets` | Secret values (API keys, tokens) |
|
|
48
|
-
| `session_id` | Unique identifier for this run |
|
|
49
|
-
| `callback_url` | Full Chronos callback URL (e.g., `http://server/api/callback`), leave empty for local runs |
|
|
50
|
-
|
|
51
55
|
## Creating a World
|
|
52
56
|
|
|
53
|
-
### 1. Define the World Class
|
|
57
|
+
### 1. Define the Config and World Class
|
|
54
58
|
|
|
55
59
|
```python
|
|
56
|
-
|
|
57
|
-
from plato.worlds import
|
|
58
|
-
|
|
60
|
+
from typing import Annotated
|
|
61
|
+
from plato.worlds import (
|
|
62
|
+
BaseWorld, RunConfig, Agent, Secret, AgentConfig,
|
|
63
|
+
Observation, StepResult, register_world
|
|
64
|
+
)
|
|
59
65
|
|
|
60
|
-
class MyWorldConfig(
|
|
61
|
-
"""Typed config
|
|
66
|
+
class MyWorldConfig(RunConfig):
|
|
67
|
+
"""Typed config - all fields accessible directly."""
|
|
68
|
+
|
|
69
|
+
# World-specific fields
|
|
62
70
|
prompt: str
|
|
63
71
|
max_steps: int = 10
|
|
64
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
|
+
|
|
65
79
|
@register_world("my-world")
|
|
66
|
-
class MyWorld(BaseWorld):
|
|
80
|
+
class MyWorld(BaseWorld[MyWorldConfig]):
|
|
67
81
|
name = "my-world"
|
|
68
82
|
description = "A simple example world"
|
|
69
|
-
agents = [
|
|
70
|
-
AgentSlot(name="worker", description="The main agent", required=True),
|
|
71
|
-
]
|
|
72
|
-
secrets = ["API_KEY"]
|
|
73
|
-
config_class = MyWorldConfig
|
|
74
83
|
|
|
75
|
-
async def reset(self
|
|
76
|
-
"""Setup the world."""
|
|
77
|
-
|
|
78
|
-
|
|
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})
|
|
79
92
|
|
|
80
93
|
async def step(self) -> StepResult:
|
|
81
94
|
"""Execute one step."""
|
|
82
|
-
# Your world logic here
|
|
83
95
|
return StepResult(
|
|
84
96
|
observation=Observation(data={"status": "done"}),
|
|
85
97
|
done=True,
|
|
@@ -106,10 +118,10 @@ my-world = "my_world:MyWorld"
|
|
|
106
118
|
pip install -e .
|
|
107
119
|
|
|
108
120
|
# Verify it's registered
|
|
109
|
-
plato-world-runner
|
|
121
|
+
plato-world-runner list
|
|
110
122
|
|
|
111
123
|
# Run with config
|
|
112
|
-
plato-world-runner --world my-world --config config.json -v
|
|
124
|
+
plato-world-runner run --world my-world --config config.json -v
|
|
113
125
|
```
|
|
114
126
|
|
|
115
127
|
## Programmatic Usage
|
|
@@ -117,12 +129,12 @@ plato-world-runner --world my-world --config config.json -v
|
|
|
117
129
|
```python
|
|
118
130
|
import asyncio
|
|
119
131
|
from plato.worlds import run_world
|
|
120
|
-
from
|
|
132
|
+
from my_world import MyWorldConfig, AgentConfig
|
|
121
133
|
|
|
122
|
-
config =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
134
|
+
config = MyWorldConfig(
|
|
135
|
+
prompt="Hello world",
|
|
136
|
+
worker=AgentConfig(image="agent:latest"),
|
|
137
|
+
api_key="secret",
|
|
126
138
|
)
|
|
127
139
|
|
|
128
140
|
asyncio.run(run_world("my-world", config))
|
|
@@ -131,20 +143,23 @@ asyncio.run(run_world("my-world", config))
|
|
|
131
143
|
Or load from a file:
|
|
132
144
|
|
|
133
145
|
```python
|
|
134
|
-
from
|
|
146
|
+
from my_world import MyWorldConfig
|
|
135
147
|
|
|
136
|
-
config =
|
|
148
|
+
config = MyWorldConfig.from_file("config.json")
|
|
137
149
|
```
|
|
138
150
|
|
|
139
151
|
## CLI Options
|
|
140
152
|
|
|
141
153
|
```
|
|
142
|
-
plato-world-runner [OPTIONS]
|
|
154
|
+
plato-world-runner [COMMAND] [OPTIONS]
|
|
155
|
+
|
|
156
|
+
Commands:
|
|
157
|
+
run Run a world with the given configuration
|
|
158
|
+
list List available worlds
|
|
143
159
|
|
|
144
|
-
|
|
145
|
-
-w, --world TEXT World name to run
|
|
146
|
-
-c, --config PATH Path to config JSON file
|
|
147
|
-
-l, --list List available worlds
|
|
160
|
+
Run options:
|
|
161
|
+
-w, --world TEXT World name to run (required)
|
|
162
|
+
-c, --config PATH Path to config JSON file (required)
|
|
148
163
|
-v, --verbose Enable debug logging
|
|
149
164
|
```
|
|
150
165
|
|
|
@@ -152,14 +167,14 @@ Options:
|
|
|
152
167
|
|
|
153
168
|
1. **Discovery**: Worlds are discovered via `plato.worlds` entry points
|
|
154
169
|
2. **Instantiation**: World class is instantiated
|
|
155
|
-
3. **Reset**: `reset(
|
|
170
|
+
3. **Reset**: `reset()` is called to setup the world (config available via `self.config`)
|
|
156
171
|
4. **Step Loop**: `step()` is called repeatedly until `done=True`
|
|
157
172
|
5. **Cleanup**: `close()` is called to cleanup resources
|
|
158
173
|
|
|
159
174
|
```
|
|
160
|
-
|
|
161
|
-
│ plato-world-runner --world X --config │
|
|
162
|
-
|
|
175
|
+
┌───────────────────────────────────────────────┐
|
|
176
|
+
│ plato-world-runner run --world X --config Y │
|
|
177
|
+
└───────────────────────────────────────────────┘
|
|
163
178
|
│
|
|
164
179
|
▼
|
|
165
180
|
┌─────────────────┐
|
|
@@ -192,7 +207,7 @@ Options:
|
|
|
192
207
|
Enable verbose logging:
|
|
193
208
|
|
|
194
209
|
```bash
|
|
195
|
-
plato-world-runner --world my-world --config config.json --verbose
|
|
210
|
+
plato-world-runner run --world my-world --config config.json --verbose
|
|
196
211
|
```
|
|
197
212
|
|
|
198
213
|
Or set log level in code:
|
plato/worlds/__init__.py
CHANGED
|
@@ -1,44 +1,82 @@
|
|
|
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, CheckpointConfig, Env, EnvConfig, RunConfig, Secret, StateConfig
|
|
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
|
+
"CheckpointConfig",
|
|
70
|
+
"StateConfig",
|
|
71
|
+
"AgentConfig",
|
|
72
|
+
"Agent",
|
|
73
|
+
"Secret",
|
|
74
|
+
"Env",
|
|
75
|
+
"EnvConfig",
|
|
76
|
+
# Env types (re-exported from generated models)
|
|
77
|
+
"EnvFromArtifact",
|
|
78
|
+
"EnvFromSimulator",
|
|
79
|
+
"EnvFromResource",
|
|
80
|
+
# Runner
|
|
43
81
|
"run_world",
|
|
44
82
|
]
|