plato-sdk-v2 2.1.15__py3-none-any.whl → 2.1.16__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/agents/runner.py CHANGED
@@ -9,7 +9,7 @@ import os
9
9
  import tempfile
10
10
  from pathlib import Path
11
11
 
12
- from plato.agents.logging import log_event, upload_artifacts
12
+ from plato.agents.logging import log_event, span, upload_artifacts
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
@@ -36,112 +36,115 @@ async def run_agent(
36
36
  """
37
37
  logs_dir = logs_dir or tempfile.mkdtemp(prefix="agent_logs_")
38
38
  agent_name = image.split("/")[-1].split(":")[0]
39
- logger.info(f"Starting agent: {agent_name} ({image})")
40
-
41
- # Pull image if requested
42
- if pull:
43
- logger.info(f"Pulling image: {image}")
44
- pull_proc = await asyncio.create_subprocess_exec(
45
- "docker",
46
- "pull",
47
- image,
48
- stdout=asyncio.subprocess.PIPE,
49
- stderr=asyncio.subprocess.STDOUT,
50
- )
51
- await pull_proc.wait()
52
-
53
- # Setup
54
- os.makedirs(os.path.join(logs_dir, "agent"), exist_ok=True)
55
- config_file = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
56
- json.dump(config, config_file)
57
- config_file.close()
58
-
59
- try:
60
- # Build docker command
61
- docker_cmd = ["docker", "run", "--rm"]
62
-
63
- # Check if iptables is available for network isolation
64
- try:
65
- proc = await asyncio.create_subprocess_exec(
66
- "iptables",
67
- "-L",
68
- "-n",
69
- stdout=asyncio.subprocess.DEVNULL,
70
- stderr=asyncio.subprocess.DEVNULL,
39
+
40
+ async with span(agent_name, span_type="agent", source="agent") as agent_span:
41
+ agent_span.log(f"Starting agent: {agent_name} ({image})")
42
+
43
+ # Pull image if requested
44
+ if pull:
45
+ agent_span.log(f"Pulling image: {image}")
46
+ pull_proc = await asyncio.create_subprocess_exec(
47
+ "docker",
48
+ "pull",
49
+ image,
50
+ stdout=asyncio.subprocess.PIPE,
51
+ stderr=asyncio.subprocess.STDOUT,
71
52
  )
72
- await proc.wait()
73
- has_iptables = proc.returncode == 0
74
- except (FileNotFoundError, PermissionError):
75
- has_iptables = False
76
-
77
- if not has_iptables:
78
- docker_cmd.extend(["--network=host", "--add-host=localhost:127.0.0.1"])
79
-
80
- docker_cmd.extend(
81
- [
82
- "-v",
83
- f"{workspace}:/workspace",
84
- "-v",
85
- f"{logs_dir}:/logs",
86
- "-v",
87
- f"{config_file.name}:/config.json:ro",
88
- "-w",
89
- "/workspace",
90
- ]
91
- )
92
-
93
- for key, value in secrets.items():
94
- docker_cmd.extend(["-e", f"{key.upper()}={value}"])
95
-
96
- docker_cmd.append(image)
97
- docker_cmd.extend(["--instruction", instruction])
98
-
99
- # Run container and stream output
100
- process = await asyncio.create_subprocess_exec(
101
- *docker_cmd,
102
- stdout=asyncio.subprocess.PIPE,
103
- stderr=asyncio.subprocess.STDOUT,
104
- )
105
-
106
- # Stream output line by line
107
- assert process.stdout is not None
108
- while True:
109
- line = await process.stdout.readline()
110
- if not line:
111
- break
112
- logger.info(f"[agent] {line.decode().rstrip()}")
113
-
114
- await process.wait()
115
-
116
- if process.returncode != 0:
117
- raise RuntimeError(f"Agent failed with exit code {process.returncode}")
118
-
119
- logger.info("Agent completed successfully")
120
-
121
- finally:
122
- os.unlink(config_file.name)
123
-
124
- # Upload artifacts (no-ops if logging not initialized)
125
- trajectory_path = Path(logs_dir) / "agent" / "trajectory.json"
126
- if trajectory_path.exists():
53
+ await pull_proc.wait()
54
+
55
+ # Setup
56
+ os.makedirs(os.path.join(logs_dir, "agent"), exist_ok=True)
57
+ config_file = tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False)
58
+ json.dump(config, config_file)
59
+ config_file.close()
60
+
61
+ try:
62
+ # Build docker command
63
+ docker_cmd = ["docker", "run", "--rm"]
64
+
65
+ # Check if iptables is available for network isolation
127
66
  try:
128
- with open(trajectory_path) as f:
129
- trajectory = json.load(f)
130
- if isinstance(trajectory, dict) and "schema_version" in trajectory:
131
- # Add agent image to trajectory
132
- agent = trajectory.get("agent", {})
133
- extra = agent.get("extra") or {}
134
- extra["image"] = image
135
- agent["extra"] = extra
136
- trajectory["agent"] = agent
137
-
138
- await log_event(
139
- span_type="trajectory",
140
- log_type="atif",
141
- extra=trajectory,
142
- source="agent",
143
- )
144
- except Exception as e:
145
- logger.warning(f"Failed to load trajectory: {e}")
146
-
147
- await upload_artifacts(logs_dir)
67
+ proc = await asyncio.create_subprocess_exec(
68
+ "iptables",
69
+ "-L",
70
+ "-n",
71
+ stdout=asyncio.subprocess.DEVNULL,
72
+ stderr=asyncio.subprocess.DEVNULL,
73
+ )
74
+ await proc.wait()
75
+ has_iptables = proc.returncode == 0
76
+ except (FileNotFoundError, PermissionError):
77
+ has_iptables = False
78
+
79
+ if not has_iptables:
80
+ docker_cmd.extend(["--network=host", "--add-host=localhost:127.0.0.1"])
81
+
82
+ docker_cmd.extend(
83
+ [
84
+ "-v",
85
+ f"{workspace}:/workspace",
86
+ "-v",
87
+ f"{logs_dir}:/logs",
88
+ "-v",
89
+ f"{config_file.name}:/config.json:ro",
90
+ "-w",
91
+ "/workspace",
92
+ ]
93
+ )
94
+
95
+ for key, value in secrets.items():
96
+ docker_cmd.extend(["-e", f"{key.upper()}={value}"])
97
+
98
+ docker_cmd.append(image)
99
+ docker_cmd.extend(["--instruction", instruction])
100
+
101
+ # Run container and stream output
102
+ process = await asyncio.create_subprocess_exec(
103
+ *docker_cmd,
104
+ stdout=asyncio.subprocess.PIPE,
105
+ stderr=asyncio.subprocess.STDOUT,
106
+ )
107
+
108
+ # Stream output line by line
109
+ assert process.stdout is not None
110
+ while True:
111
+ line = await process.stdout.readline()
112
+ if not line:
113
+ break
114
+ logger.info(f"[agent] {line.decode().rstrip()}")
115
+
116
+ await process.wait()
117
+
118
+ if process.returncode != 0:
119
+ raise RuntimeError(f"Agent failed with exit code {process.returncode}")
120
+
121
+ agent_span.log("Agent completed successfully")
122
+
123
+ finally:
124
+ os.unlink(config_file.name)
125
+
126
+ # Load trajectory and add to span
127
+ trajectory_path = Path(logs_dir) / "agent" / "trajectory.json"
128
+ if trajectory_path.exists():
129
+ try:
130
+ with open(trajectory_path) as f:
131
+ trajectory = json.load(f)
132
+ if isinstance(trajectory, dict) and "schema_version" in trajectory:
133
+ # Add agent image to trajectory
134
+ agent_data = trajectory.get("agent", {})
135
+ extra = agent_data.get("extra") or {}
136
+ extra["image"] = image
137
+ agent_data["extra"] = extra
138
+ trajectory["agent"] = agent_data
139
+
140
+ # Log trajectory as separate event
141
+ await log_event(
142
+ span_type="trajectory",
143
+ log_type="atif",
144
+ extra=trajectory,
145
+ source="agent",
146
+ )
147
+ except Exception as e:
148
+ logger.warning(f"Failed to load trajectory: {e}")
149
+
150
+ await upload_artifacts(logs_dir)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plato-sdk-v2
3
- Version: 2.1.15
3
+ Version: 2.1.16
4
4
  Summary: Python SDK for the Plato API
5
5
  Author-email: Plato <support@plato.so>
6
6
  License-Expression: MIT
@@ -299,7 +299,7 @@ plato/agents/base.py,sha256=vUbPQuNSo6Ka2lIB_ZOXgi4EoAjtAD7GIj9LnNotam0,4577
299
299
  plato/agents/build.py,sha256=CNMbVQFs2_pYit1dA29Davve28Yi4c7TNK9wBB7odrE,1621
300
300
  plato/agents/config.py,sha256=VZVMdCmEQnoR0VkrGdScG8p6zSKVFe7BZPd2h8lKNjI,5460
301
301
  plato/agents/logging.py,sha256=z9rDlGPbrpcTS8PephbK2rDqT7thC1KyLkua4ypUkv4,12210
302
- plato/agents/runner.py,sha256=rW46kigbbC66OQsn6QBoSuDENpLCrIK0K-SuF67JWUs,4599
302
+ plato/agents/runner.py,sha256=rOWYTSAhdola_FdrbviP955NBusNtBUy-q_c5fDA9to,5123
303
303
  plato/agents/trajectory.py,sha256=ayXEMCfYvIuXU2JkQWfPOVO9JywNSx8Kf6Ztrgsdh-I,10441
304
304
  plato/chronos/__init__.py,sha256=RHMvSrQS_-vkKOyTRuAkp2gKDP1HEuBLDnw8jcZs1Jg,739
305
305
  plato/chronos/client.py,sha256=YcOGtHWERyOD9z8LKt8bRMVL0cEwL2hiAP4qQgdZlUI,5495
@@ -463,7 +463,7 @@ plato/worlds/base.py,sha256=vLAHkYpYg4kl7LgftQ0uC6xXhASVqREogn6msNWA6Hk,9650
463
463
  plato/worlds/build_hook.py,sha256=KSoW0kqa5b7NyZ7MYOw2qsZ_2FkWuz0M3Ru7AKOP7Qw,3486
464
464
  plato/worlds/config.py,sha256=-K1dnlRL5I-DNYEoc1I4cKIsTw53X_1QrRY2SWJvRiQ,6256
465
465
  plato/worlds/runner.py,sha256=r9B2BxBae8_dM7y5cJf9xhThp_I1Qvf_tlPq2rs8qC8,4013
466
- plato_sdk_v2-2.1.15.dist-info/METADATA,sha256=jHsbu_NePI0IW_9sfReVw3o2ifWJxaqW5g8tqr3VfFI,8509
467
- plato_sdk_v2-2.1.15.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
468
- plato_sdk_v2-2.1.15.dist-info/entry_points.txt,sha256=upGMbJCx6YWUTKrPoYvYUYfFCqYr75nHDwhA-45m6p8,136
469
- plato_sdk_v2-2.1.15.dist-info/RECORD,,
466
+ plato_sdk_v2-2.1.16.dist-info/METADATA,sha256=5S_mx4Iij8UNv8od9y6b3n8T00t6gFzM01-1wS-rLdg,8509
467
+ plato_sdk_v2-2.1.16.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
468
+ plato_sdk_v2-2.1.16.dist-info/entry_points.txt,sha256=upGMbJCx6YWUTKrPoYvYUYfFCqYr75nHDwhA-45m6p8,136
469
+ plato_sdk_v2-2.1.16.dist-info/RECORD,,