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/agents/build.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Build configuration for Plato agents.
|
|
2
|
+
|
|
3
|
+
Reads [tool.plato.build] from pyproject.toml to configure Docker builds.
|
|
4
|
+
|
|
5
|
+
Example pyproject.toml:
|
|
6
|
+
[tool.plato.build]
|
|
7
|
+
env = { "SOME_BUILD_ARG" = "value" }
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
from pydantic import BaseModel, Field
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
import tomllib
|
|
19
|
+
except ImportError:
|
|
20
|
+
import tomli as tomllib
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BuildConfig(BaseModel):
|
|
24
|
+
"""Docker build configuration for an agent.
|
|
25
|
+
|
|
26
|
+
Read from [tool.plato.build] in pyproject.toml.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
env: dict[str, str] = Field(
|
|
30
|
+
default_factory=dict,
|
|
31
|
+
description="Environment variables to pass as build args",
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
def to_dict(self) -> dict[str, Any]:
|
|
35
|
+
"""Convert to dict for schema output."""
|
|
36
|
+
return self.model_dump(exclude_defaults=False)
|
|
37
|
+
|
|
38
|
+
@classmethod
|
|
39
|
+
def get_json_schema(cls) -> dict[str, Any]:
|
|
40
|
+
"""Get JSON schema for build config."""
|
|
41
|
+
schema = cls.model_json_schema()
|
|
42
|
+
schema.pop("title", None)
|
|
43
|
+
return schema
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def from_pyproject(cls, path: str | Path) -> BuildConfig:
|
|
47
|
+
"""Load build config from pyproject.toml."""
|
|
48
|
+
path = Path(path)
|
|
49
|
+
if path.is_dir():
|
|
50
|
+
path = path / "pyproject.toml"
|
|
51
|
+
|
|
52
|
+
with open(path, "rb") as f:
|
|
53
|
+
data = tomllib.load(f)
|
|
54
|
+
|
|
55
|
+
build_config = data.get("tool", {}).get("plato", {}).get("build", {})
|
|
56
|
+
return cls(**build_config)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def load_build_config(agent_path: str | Path) -> BuildConfig:
|
|
60
|
+
"""Load build config from an agent directory."""
|
|
61
|
+
return BuildConfig.from_pyproject(agent_path)
|
plato/agents/config.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"""Typed configuration for Plato agents.
|
|
2
|
+
|
|
3
|
+
Provides base configuration classes that agents extend with their specific fields.
|
|
4
|
+
Secret fields are automatically loaded from environment variables using pydantic-settings.
|
|
5
|
+
|
|
6
|
+
Example:
|
|
7
|
+
from plato.agents import AgentConfig, Secret
|
|
8
|
+
from typing import Annotated
|
|
9
|
+
|
|
10
|
+
class OpenHandsConfig(AgentConfig):
|
|
11
|
+
model_name: str = "anthropic/claude-sonnet-4"
|
|
12
|
+
anthropic_api_key: Annotated[str | None, Secret(description="API key")] = None
|
|
13
|
+
|
|
14
|
+
# Secrets auto-loaded from env vars (ANTHROPIC_API_KEY -> anthropic_api_key)
|
|
15
|
+
config = OpenHandsConfig.from_file("/config.json")
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import json
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
from typing import Any
|
|
23
|
+
|
|
24
|
+
from pydantic import Field
|
|
25
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Secret:
|
|
29
|
+
"""Annotation marker for secret fields.
|
|
30
|
+
|
|
31
|
+
Fields annotated with Secret are automatically loaded from environment variables.
|
|
32
|
+
The env var name is the uppercase version of the field name (e.g., api_key -> API_KEY).
|
|
33
|
+
|
|
34
|
+
Usage:
|
|
35
|
+
api_key: Annotated[str, Secret(description="API key")]
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, description: str = "", required: bool = False):
|
|
39
|
+
self.description = description
|
|
40
|
+
self.required = required
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class AgentConfig(BaseSettings):
|
|
44
|
+
"""Base configuration for agents.
|
|
45
|
+
|
|
46
|
+
Extends pydantic-settings BaseSettings, so secret fields are automatically loaded
|
|
47
|
+
from environment variables. The env var name is the uppercase field name.
|
|
48
|
+
|
|
49
|
+
Subclass with agent-specific fields:
|
|
50
|
+
|
|
51
|
+
class OpenHandsConfig(AgentConfig):
|
|
52
|
+
model_name: str = "anthropic/claude-sonnet-4"
|
|
53
|
+
anthropic_api_key: Annotated[str | None, Secret(description="API key")] = None
|
|
54
|
+
|
|
55
|
+
# ANTHROPIC_API_KEY env var is automatically loaded into anthropic_api_key
|
|
56
|
+
config = OpenHandsConfig.from_file("/config.json")
|
|
57
|
+
|
|
58
|
+
Attributes:
|
|
59
|
+
logs_dir: Directory for agent logs and trajectory output.
|
|
60
|
+
checkpoint_paths: Directories to watch for checkpoint triggers (for workspace tracking).
|
|
61
|
+
checkpoint_debounce_ms: Debounce interval for checkpoints.
|
|
62
|
+
"""
|
|
63
|
+
|
|
64
|
+
model_config = SettingsConfigDict(
|
|
65
|
+
env_prefix="", # No prefix - ANTHROPIC_API_KEY maps to anthropic_api_key
|
|
66
|
+
extra="allow",
|
|
67
|
+
env_ignore_empty=True,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
logs_dir: str = "/logs"
|
|
71
|
+
checkpoint_paths: list[str] = Field(default_factory=list)
|
|
72
|
+
checkpoint_debounce_ms: int = 500
|
|
73
|
+
|
|
74
|
+
@classmethod
|
|
75
|
+
def get_field_secrets(cls) -> dict[str, Secret]:
|
|
76
|
+
"""Get Secret annotations for each field."""
|
|
77
|
+
result: dict[str, Secret] = {}
|
|
78
|
+
|
|
79
|
+
for field_name, field_info in cls.model_fields.items():
|
|
80
|
+
for meta in field_info.metadata:
|
|
81
|
+
if isinstance(meta, Secret):
|
|
82
|
+
result[field_name] = meta
|
|
83
|
+
break
|
|
84
|
+
|
|
85
|
+
return result
|
|
86
|
+
|
|
87
|
+
@classmethod
|
|
88
|
+
def get_json_schema(cls) -> dict:
|
|
89
|
+
"""Get JSON schema with secrets separated."""
|
|
90
|
+
full_schema = cls.model_json_schema()
|
|
91
|
+
full_schema.pop("title", None)
|
|
92
|
+
|
|
93
|
+
secrets_map = cls.get_field_secrets()
|
|
94
|
+
properties = full_schema.get("properties", {})
|
|
95
|
+
|
|
96
|
+
config_properties = {}
|
|
97
|
+
secrets = []
|
|
98
|
+
|
|
99
|
+
# Skip internal fields
|
|
100
|
+
internal_fields = {"logs_dir", "checkpoint_paths", "checkpoint_debounce_ms"}
|
|
101
|
+
|
|
102
|
+
for field_name, prop_schema in properties.items():
|
|
103
|
+
if field_name in internal_fields:
|
|
104
|
+
continue
|
|
105
|
+
|
|
106
|
+
if field_name in secrets_map:
|
|
107
|
+
secret = secrets_map[field_name]
|
|
108
|
+
secrets.append(
|
|
109
|
+
{
|
|
110
|
+
"name": field_name,
|
|
111
|
+
"description": secret.description,
|
|
112
|
+
"required": secret.required,
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
config_properties[field_name] = prop_schema
|
|
117
|
+
|
|
118
|
+
required = [r for r in full_schema.get("required", []) if r not in internal_fields and r not in secrets_map]
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
122
|
+
"type": "object",
|
|
123
|
+
"properties": config_properties,
|
|
124
|
+
"required": required,
|
|
125
|
+
"secrets": secrets,
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
def get_secrets_dict(self) -> dict[str, str]:
|
|
129
|
+
"""Extract secret values as a dict for environment variables."""
|
|
130
|
+
secrets_map = self.get_field_secrets()
|
|
131
|
+
result: dict[str, str] = {}
|
|
132
|
+
|
|
133
|
+
for field_name in secrets_map:
|
|
134
|
+
value = getattr(self, field_name, None)
|
|
135
|
+
if value is not None:
|
|
136
|
+
result[field_name] = value
|
|
137
|
+
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
def get_config_dict(self) -> dict[str, Any]:
|
|
141
|
+
"""Extract non-secret config values as a dict."""
|
|
142
|
+
secrets_map = self.get_field_secrets()
|
|
143
|
+
internal_fields = {"logs_dir", "checkpoint_paths", "checkpoint_debounce_ms"}
|
|
144
|
+
|
|
145
|
+
result: dict[str, Any] = {}
|
|
146
|
+
for field_name in self.model_fields:
|
|
147
|
+
if field_name not in secrets_map and field_name not in internal_fields:
|
|
148
|
+
value = getattr(self, field_name, None)
|
|
149
|
+
if value is not None:
|
|
150
|
+
result[field_name] = value
|
|
151
|
+
|
|
152
|
+
return result
|
|
153
|
+
|
|
154
|
+
@classmethod
|
|
155
|
+
def from_file(cls, path: str | Path) -> AgentConfig:
|
|
156
|
+
"""Load config from a JSON file."""
|
|
157
|
+
path = Path(path)
|
|
158
|
+
with open(path) as f:
|
|
159
|
+
data = json.load(f)
|
|
160
|
+
return cls(**data)
|