plato-sdk-v2 2.8.8__py3-none-any.whl → 2.9.1__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.
@@ -0,0 +1,63 @@
1
+ """Annotation markers for Plato world configurations."""
2
+
3
+ from __future__ import annotations
4
+
5
+
6
+ class Agent:
7
+ """Annotation marker for agent fields.
8
+
9
+ Usage:
10
+ coder: Annotated[AgentConfig, Agent(description="Coding agent")]
11
+ """
12
+
13
+ def __init__(self, description: str = "", required: bool = True):
14
+ self.description = description
15
+ self.required = required
16
+
17
+
18
+ class Secret:
19
+ """Annotation marker for secret fields.
20
+
21
+ Usage:
22
+ api_key: Annotated[str | None, Secret(description="API key")] = None
23
+ """
24
+
25
+ def __init__(self, description: str = "", required: bool = False):
26
+ self.description = description
27
+ self.required = required
28
+
29
+
30
+ class Env:
31
+ """Annotation marker for single environment fields.
32
+
33
+ Environments are VMs that run alongside the world's runtime.
34
+ They can be specified by artifact ID, simulator name, or resource config.
35
+
36
+ Usage:
37
+ database: Annotated[EnvConfig, Env(description="Database server")] = EnvFromArtifact(
38
+ artifact_id="abc123",
39
+ alias="database",
40
+ )
41
+ """
42
+
43
+ def __init__(self, description: str = "", required: bool = True):
44
+ self.description = description
45
+ self.required = required
46
+
47
+
48
+ class EnvList:
49
+ """Annotation marker for a list of arbitrary environments.
50
+
51
+ Use this when the world accepts a dynamic list of environments
52
+ rather than named, fixed environment fields.
53
+
54
+ Usage:
55
+ envs: Annotated[
56
+ list[EnvFromSimulator | EnvFromArtifact | EnvFromResource],
57
+ EnvList(description="Environments to create for this task"),
58
+ Field(discriminator="type"),
59
+ ] = []
60
+ """
61
+
62
+ def __init__(self, description: str = ""):
63
+ self.description = description
plato/worlds/models.py ADDED
@@ -0,0 +1,23 @@
1
+ """Data models for Plato worlds."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+
10
+ class Observation(BaseModel):
11
+ """Observation returned from reset/step."""
12
+
13
+ data: dict[str, Any] = Field(default_factory=dict)
14
+
15
+ model_config = {"extra": "allow"}
16
+
17
+
18
+ class StepResult(BaseModel):
19
+ """Result of a step."""
20
+
21
+ observation: Observation
22
+ done: bool = False
23
+ info: dict[str, Any] = Field(default_factory=dict)
plato/worlds/schema.py ADDED
@@ -0,0 +1,154 @@
1
+ """JSON schema generation for Plato world configurations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from plato.worlds.markers import Agent, Env, EnvList, Secret
8
+
9
+ if TYPE_CHECKING:
10
+ from plato.worlds.config import RunConfig
11
+
12
+
13
+ def get_field_annotations(config_cls: type[RunConfig]) -> dict[str, Agent | Secret | Env | EnvList | None]:
14
+ """Get Agent/Secret/Env/EnvList annotations for each field.
15
+
16
+ Args:
17
+ config_cls: The RunConfig subclass to inspect
18
+
19
+ Returns:
20
+ Dict mapping field name to annotation marker (or None if no marker)
21
+ """
22
+ result: dict[str, Agent | Secret | Env | EnvList | None] = {}
23
+
24
+ for field_name, field_info in config_cls.model_fields.items():
25
+ marker = None
26
+
27
+ for meta in field_info.metadata:
28
+ if isinstance(meta, (Agent, Secret, Env, EnvList)):
29
+ marker = meta
30
+ break
31
+
32
+ result[field_name] = marker
33
+
34
+ return result
35
+
36
+
37
+ def get_world_config_schema(config_cls: type[RunConfig]) -> dict[str, Any]:
38
+ """Get JSON schema for a world config with agents, secrets, and envs separated.
39
+
40
+ Args:
41
+ config_cls: The RunConfig subclass to generate schema for
42
+
43
+ Returns:
44
+ JSON schema dict with properties, required, agents, secrets, and envs fields
45
+ """
46
+ full_schema = config_cls.model_json_schema()
47
+ full_schema.pop("title", None)
48
+
49
+ annotations = get_field_annotations(config_cls)
50
+ properties = full_schema.get("properties", {})
51
+
52
+ world_properties: dict[str, Any] = {}
53
+ agents: list[dict[str, Any]] = []
54
+ secrets: list[dict[str, Any]] = []
55
+ envs: list[dict[str, Any]] = []
56
+ env_list_field: dict[str, Any] | None = None
57
+
58
+ # Skip runtime fields
59
+ runtime_fields = {"session_id", "otel_url", "upload_url", "plato_session", "checkpoint", "state"}
60
+
61
+ for field_name, prop_schema in properties.items():
62
+ if field_name in runtime_fields:
63
+ continue
64
+
65
+ marker = annotations.get(field_name)
66
+
67
+ if isinstance(marker, Agent):
68
+ agents.append(
69
+ {
70
+ "name": field_name,
71
+ "description": marker.description,
72
+ "required": marker.required,
73
+ }
74
+ )
75
+ elif isinstance(marker, Secret):
76
+ secrets.append(
77
+ {
78
+ "name": field_name,
79
+ "description": marker.description,
80
+ "required": marker.required,
81
+ }
82
+ )
83
+ elif isinstance(marker, Env):
84
+ # Get default value for this env field
85
+ field_info = config_cls.model_fields.get(field_name)
86
+ default_value = None
87
+ if field_info and field_info.default is not None:
88
+ default_env = field_info.default
89
+ if hasattr(default_env, "model_dump"):
90
+ default_value = default_env.model_dump()
91
+ elif isinstance(default_env, dict):
92
+ default_value = default_env
93
+
94
+ envs.append(
95
+ {
96
+ "name": field_name,
97
+ "description": marker.description,
98
+ "required": marker.required,
99
+ "default": default_value,
100
+ }
101
+ )
102
+ elif isinstance(marker, EnvList):
103
+ env_list_field = {
104
+ "name": field_name,
105
+ "description": marker.description,
106
+ }
107
+ else:
108
+ world_properties[field_name] = prop_schema
109
+
110
+ # Compute required fields (excluding runtime and annotated fields)
111
+ required = [r for r in full_schema.get("required", []) if r not in runtime_fields and annotations.get(r) is None]
112
+
113
+ result: dict[str, Any] = {
114
+ "properties": world_properties,
115
+ "required": required,
116
+ "agents": agents,
117
+ "secrets": secrets,
118
+ "envs": envs,
119
+ }
120
+
121
+ # Include $defs if present (for nested type references)
122
+ if "$defs" in full_schema:
123
+ result["$defs"] = full_schema["$defs"]
124
+
125
+ # Add env_list if present (for worlds with arbitrary environment lists)
126
+ if env_list_field:
127
+ result["env_list"] = env_list_field
128
+
129
+ return result
130
+
131
+
132
+ def get_world_schema(world_cls: type) -> dict[str, Any]:
133
+ """Get full schema for a world including config, agents, secrets, and envs.
134
+
135
+ Args:
136
+ world_cls: The BaseWorld subclass to generate schema for
137
+
138
+ Returns:
139
+ JSON schema dict with all schema sections
140
+ """
141
+ config_class = world_cls.get_config_class()
142
+ schema = get_world_config_schema(config_class)
143
+
144
+ return {
145
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
146
+ "type": "object",
147
+ "properties": schema.get("properties", {}),
148
+ "required": schema.get("required", []),
149
+ "agents": schema.get("agents", []),
150
+ "secrets": schema.get("secrets", []),
151
+ "envs": schema.get("envs", []),
152
+ "$defs": schema.get("$defs"),
153
+ "env_list": schema.get("env_list"),
154
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plato-sdk-v2
3
- Version: 2.8.8
3
+ Version: 2.9.1
4
4
  Summary: Python SDK for the Plato API
5
5
  Author-email: Plato <support@plato.so>
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  plato/__init__.py,sha256=a9E0KS1602GWHHStnf7wDEuvPCvh2GpPh0Sf8oKZx5Q,1795
2
2
  plato/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- plato/_generated/__init__.py,sha256=QYMNzMRKMtV-VVoZAH6LWQGUdf0juNNaYQNUoUf_DtU,738
3
+ plato/_generated/__init__.py,sha256=fu4NDoHmSX5gCLo8mYxDWyv9fcFcoJ8H-IkKzAeYsC0,738
4
4
  plato/_generated/client.py,sha256=_oMKXyAShQVddCaIKnfB2zPkRsDlCwLp-N3RFoKq_v8,5489
5
5
  plato/_generated/errors.py,sha256=goTGrZ4rrujGZ-BoOonoyaGwdGDkGO6GyeubIkQVv9E,4197
6
6
  plato/_generated/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -192,7 +192,7 @@ plato/_generated/api/v1/testcases/get_organization_test_case_assignments.py,sha2
192
192
  plato/_generated/api/v1/testcases/get_testcase.py,sha256=EydIk-2zdS6XT9-btLWCE5i-N2lT7AlAe5amQQJNn-c,866
193
193
  plato/_generated/api/v1/testcases/get_testcase_metadata_for_scoring.py,sha256=i4xUaUisTUKsKnaV8sv2B-H1lgyBd9vKxR1TpOtvbcw,1948
194
194
  plato/_generated/api/v1/testcases/get_testcase_sets.py,sha256=NSqnYWvj_G3ivnuuV797g85NGzHXi3z-UlvvRoFMwRM,1375
195
- plato/_generated/api/v1/testcases/get_testcases.py,sha256=AjsC2aw1VJOtGEe-Km36uVktdxR6IRahhbHCjeAUxcY,5756
195
+ plato/_generated/api/v1/testcases/get_testcases.py,sha256=KV8H4Yf3PYMqMpHIDGty59CHPqPdHvcPNZ-WD2H17Z4,6586
196
196
  plato/_generated/api/v1/testcases/get_testcases_in_set.py,sha256=TJK2KHmGC5lNmBPoAXbZ6FktUael9v8Ecl4M8XAhceg,1501
197
197
  plato/_generated/api/v1/testcases/mark_organization_test_case_completed.py,sha256=bbtE5PWIA9X0EkyrSXE8YN0gp6x6sfno0rc02AK_-l0,1521
198
198
  plato/_generated/api/v1/testcases/update_testcase.py,sha256=-kTW31ioDzQvr2AmOv9gHL7jN6K9qhGyjnJfNHETwhA,1699
@@ -315,7 +315,7 @@ plato/_generated/api/v2/work_orders/get_work_order.py,sha256=dOOTdoS_tJSoLKYlvUb
315
315
  plato/_generated/api/v2/work_orders/list_work_orders.py,sha256=buAOqkAbCma9aODSEKRt0es36oVDdv_Y4jb-EkkC668,2026
316
316
  plato/_generated/api/version/__init__.py,sha256=dQXTYrXjD1RZcvWwnlqXWAZ-eAV-V-6JSNuY7uaca7o,70
317
317
  plato/_generated/api/version/check.py,sha256=HTVNw0oi9gbvX4pOVoH4y4JywCxdl1pJTCk2PjJFwJ4,778
318
- plato/_generated/models/__init__.py,sha256=goJEywXdEra3Su3zZ2qknqMomKvQM88zNLU-MbdgwNE,173217
318
+ plato/_generated/models/__init__.py,sha256=7YoPXRoeRyVIPvRE5zMBg3OKSF69CmaMyJrXGJ0uFBs,173719
319
319
  plato/_sims_generator/__init__.py,sha256=Km4QOl9wxjQ5dgpdhk9QnBFJFFc9eq3rPbMWIQRjIn0,1602
320
320
  plato/_sims_generator/cli.py,sha256=mzolN-dxfMkVAdA-vC0esnai-cGg-i4ozOw8dACefV4,2709
321
321
  plato/_sims_generator/instruction.py,sha256=Na9M-jIdBPhp_fLuBPTicoFnWriRyi8YiZ-eQBj64HI,6644
@@ -332,11 +332,13 @@ plato/_sims_generator/templates/python/tag_init.py.jinja,sha256=WB_9cv0JKIVg5TOX
332
332
  plato/_sims_generator/templates/python/version_init.py.jinja,sha256=sGvFcYVfzXFyQDAe0PSOrg9yys93KE0XInFQNb1TvCY,179
333
333
  plato/agents/__init__.py,sha256=Cxc-HUMwRGQ4D1hHnFo9vt2AV5upPRYP4e3y8X6Hzr0,3052
334
334
  plato/agents/artifacts.py,sha256=ljeI0wzsp7Q6uKqMb-k7kTb680Vizs54ohtM-d7zvOg,2929
335
- plato/agents/base.py,sha256=vUbPQuNSo6Ka2lIB_ZOXgi4EoAjtAD7GIj9LnNotam0,4577
335
+ plato/agents/base.py,sha256=5vRIENOr4hzDSMgcKJFggbIdf9pS0OXLb1KAIjUmFJM,4423
336
336
  plato/agents/build.py,sha256=CNMbVQFs2_pYit1dA29Davve28Yi4c7TNK9wBB7odrE,1621
337
- plato/agents/config.py,sha256=GWXEAbruNVI2q3XIWpQ9vGLK2wGhsFPYA-oekmAlrg8,5392
338
- plato/agents/otel.py,sha256=A2LkkjBtjSe0eztr9UvYvSUOwfmShCgPg3OUN8nOyIo,9159
337
+ plato/agents/config.py,sha256=1OcidjteU-kPUZhFnYwscsboEBliC8LcpxpkFKumCuI,3608
338
+ plato/agents/markers.py,sha256=fZSke6Btm2IFsTFhRQMrRcr6W2c594FwD3n45vb6JRQ,559
339
+ plato/agents/otel.py,sha256=_aEKZbLard8jdUAIZDS46LSutdcT8J7vY-FrN8c4SUE,7247
339
340
  plato/agents/runner.py,sha256=Y-e5fCfPJpG1Wo1ICLco8kHzm7u-kbzwgbvLH3XBN-w,7969
341
+ plato/agents/schema.py,sha256=FuBfDu0mrSXgyI3-egFOvCQmRk6VsWUCN1YZ9t8vYbI,2747
340
342
  plato/agents/trajectory.py,sha256=WdiBmua0KvCrNaM3qgPI7-7B4xmSkfbP4oZ_9_8qHzU,10529
341
343
  plato/chronos/__init__.py,sha256=RHMvSrQS_-vkKOyTRuAkp2gKDP1HEuBLDnw8jcZs1Jg,739
342
344
  plato/chronos/client.py,sha256=YcOGtHWERyOD9z8LKt8bRMVL0cEwL2hiAP4qQgdZlUI,5495
@@ -426,11 +428,11 @@ plato/chronos/api/worlds/create_world.py,sha256=H6yl5QIazNXgryOR5rvscSIMf8Y9kjc6
426
428
  plato/chronos/api/worlds/delete_world.py,sha256=UETu3Zk0e2VkDdAyMilv1ev-0g_j-oujH1Dc8DBqQOc,1239
427
429
  plato/chronos/api/worlds/get_world.py,sha256=eHTM1U5JiNTaZwYLh7x4QVBoRQeI5kaJ9o6xSi4-nos,1356
428
430
  plato/chronos/api/worlds/list_worlds.py,sha256=hBAuGb69tlasyn-kV_LNr9x6Rr7SHhST5hXJn1uqMf8,1253
429
- plato/chronos/models/__init__.py,sha256=M2dV42UmYgsNC4M76jOO4vILgzNvM6m3BGpf6McfFwE,23198
431
+ plato/chronos/models/__init__.py,sha256=fGWDhReLc8IfOAM7fk2oVnqDKopwMNm6IVYlviQw2S4,23194
430
432
  plato/cli/__init__.py,sha256=UsKj-69eWKuAlk-Fiwlrz0GJiBfuOmcf-ZLmZJb21Vo,102
431
433
  plato/cli/agent.py,sha256=5qA0T1n0H0JQ5ZB-fAVKm3Nw-y_M-GiSQx1OTcKgkrI,44050
432
434
  plato/cli/audit_ui.py,sha256=AfnC3wngGV3ujg9POHNYQhal2S6Hr0ZhcXrAAxtVfMg,12307
433
- plato/cli/chronos.py,sha256=yZeP837trC9lSgyZ0mCTkNIMamz14Rd7YY1TyVgvTGc,31008
435
+ plato/cli/chronos.py,sha256=6QkHVdZxLyevbLJm43HFPJDCpkzFPRFikVhJ_fZR5D4,27863
434
436
  plato/cli/compose.py,sha256=MIUBFbYeRO8TyUadUSnhgtWsh1M3LQHF-WLEbmFxIW0,51802
435
437
  plato/cli/main.py,sha256=euLI0aw42SG2KIAX1xzMZ2A1LYWNOYayZ2ZCZo10ws4,6984
436
438
  plato/cli/pm.py,sha256=eex5K2JucJWzlK81tyBfJrntwZiX_QrmgeKQluv0XKc,54829
@@ -536,12 +538,15 @@ plato/v2/utils/gateway_tunnel.py,sha256=eWgwf4VV8-jx6iCuHFgCISsAOVmNOOjCB56EuZLs
536
538
  plato/v2/utils/models.py,sha256=PwehSSnIRG-tM3tWL1PzZEH77ZHhIAZ9R0UPs6YknbM,1441
537
539
  plato/v2/utils/proxy_tunnel.py,sha256=8ZTd0jCGSfIHMvSv1fgEyacuISWnGPHLPbDglWroTzY,10463
538
540
  plato/worlds/README.md,sha256=XFOkEA3cNNcrWkk-Cxnsl-zn-y0kvUENKQRSqFKpdqw,5479
539
- plato/worlds/__init__.py,sha256=nwuEerEkP2TSfadPiOMcUE3p6u1vhaS7ZxfTh2zNcF8,2217
540
- plato/worlds/base.py,sha256=-RR71bSxEFI5yydtrtq-AAbuw98CIjvmrbztqzB9oIc,31041
541
+ plato/worlds/__init__.py,sha256=1n23AAev3RZrKHpeSXoCnCVJ5TRtP88jVvagLMxISgg,2256
542
+ plato/worlds/base.py,sha256=pjriEuu-_PcpgBqc0tQmMQnsa08oZrCP83lC586liKo,28237
541
543
  plato/worlds/build_hook.py,sha256=KSoW0kqa5b7NyZ7MYOw2qsZ_2FkWuz0M3Ru7AKOP7Qw,3486
542
- plato/worlds/config.py,sha256=O1lUXzxp-Z_M7izslT8naXgE6XujjzwYFFrDDzUOueI,12736
544
+ plato/worlds/config.py,sha256=pmeOxVHLwL-DI5zzU04Pa5wng66LX2suCxd4ey9lAfU,7486
545
+ plato/worlds/markers.py,sha256=dB4jOVYHWFm82LqskjQ4igrFp89H2FSgv8nfBXMf550,1762
546
+ plato/worlds/models.py,sha256=dN_Lsmy4yBuyd5D17kbL4Qy9VKc-06Ea1ombXC3b-Gk,477
543
547
  plato/worlds/runner.py,sha256=r9B2BxBae8_dM7y5cJf9xhThp_I1Qvf_tlPq2rs8qC8,4013
544
- plato_sdk_v2-2.8.8.dist-info/METADATA,sha256=nWIt8b0h91AbIIvkuTwin5Uq9cLaIlqExgbdnvpM-oA,8652
545
- plato_sdk_v2-2.8.8.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
546
- plato_sdk_v2-2.8.8.dist-info/entry_points.txt,sha256=iynJvTkU7E4MZNtSozVF0Wh083yPm6cuKV362Ol_ez8,133
547
- plato_sdk_v2-2.8.8.dist-info/RECORD,,
548
+ plato/worlds/schema.py,sha256=Wn_nwvOyVYWZAVQwzMtHMxnyBWcGT4X55sbiTruwQZs,5035
549
+ plato_sdk_v2-2.9.1.dist-info/METADATA,sha256=_YVWdGOSys1TJ2umD2Y-Kgy0QEbITJpeVetH5Mb1k0Q,8652
550
+ plato_sdk_v2-2.9.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
551
+ plato_sdk_v2-2.9.1.dist-info/entry_points.txt,sha256=iynJvTkU7E4MZNtSozVF0Wh083yPm6cuKV362Ol_ez8,133
552
+ plato_sdk_v2-2.9.1.dist-info/RECORD,,