plato-sdk-v2 2.2.4__py3-none-any.whl → 2.3.3__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/worlds/runner.py CHANGED
@@ -246,12 +246,49 @@ def _extract_agent_images_from_config(config_data: dict) -> list[str]:
246
246
  return images
247
247
 
248
248
 
249
+ async def _create_chronos_session(
250
+ chronos_url: str,
251
+ api_key: str,
252
+ world_name: str,
253
+ world_config: dict,
254
+ plato_session_id: str | None = None,
255
+ ) -> tuple[str, str]:
256
+ """Create a session in Chronos.
257
+
258
+ Args:
259
+ chronos_url: Chronos base URL (e.g., https://chronos.plato.so)
260
+ api_key: Plato API key for authentication
261
+ world_name: Name of the world being run
262
+ world_config: World configuration dict
263
+ plato_session_id: Optional Plato session ID if already created
264
+
265
+ Returns:
266
+ Tuple of (session_id, callback_url)
267
+ """
268
+ import httpx
269
+
270
+ url = f"{chronos_url.rstrip('/')}/api/sessions"
271
+
272
+ async with httpx.AsyncClient(timeout=30.0) as client:
273
+ response = await client.post(
274
+ url,
275
+ json={
276
+ "world_name": world_name,
277
+ "world_config": world_config,
278
+ "plato_session_id": plato_session_id,
279
+ },
280
+ headers={"x-api-key": api_key},
281
+ )
282
+ response.raise_for_status()
283
+ data = response.json()
284
+
285
+ return data["public_id"], data["callback_url"]
286
+
287
+
249
288
  async def _run_dev(
250
289
  world_name: str,
251
290
  config_path: Path,
252
- env_timeout: int = 600,
253
- chronos_url: str | None = None,
254
- api_key: str | None = None,
291
+ env_timeout: int = 7200,
255
292
  agents_dir: Path | None = None,
256
293
  ) -> None:
257
294
  """Run a world locally with automatic environment creation.
@@ -260,22 +297,31 @@ async def _run_dev(
260
297
  1. Load and parse the config
261
298
  2. Build local agent images if --agents-dir is provided
262
299
  3. Create Plato session with all environments
263
- 4. Optionally initialize Chronos logging for callbacks
300
+ 4. Create Chronos session for logging/callbacks
264
301
  5. Run the world with the session attached
265
302
 
303
+ Requires environment variables:
304
+ CHRONOS_URL: Chronos base URL (e.g., https://chronos.plato.so)
305
+ PLATO_API_KEY: API key for Plato and Chronos authentication
306
+
266
307
  Args:
267
308
  world_name: Name of the world to run
268
309
  config_path: Path to the config JSON file
269
310
  env_timeout: Timeout for environment creation (seconds)
270
- chronos_url: Optional Chronos base URL for sending log events
271
- api_key: Optional Plato API key (used for Chronos session creation)
272
311
  agents_dir: Optional directory containing agent source code
273
312
  """
274
- from uuid import uuid4
275
-
276
313
  from plato.v2 import AsyncPlato
277
314
  from plato.worlds.base import get_world
278
315
 
316
+ # Get required env vars
317
+ chronos_url = os.environ.get("CHRONOS_URL")
318
+ api_key = os.environ.get("PLATO_API_KEY")
319
+
320
+ if not chronos_url:
321
+ raise ValueError("CHRONOS_URL environment variable is required")
322
+ if not api_key:
323
+ raise ValueError("PLATO_API_KEY environment variable is required")
324
+
279
325
  discover_worlds()
280
326
 
281
327
  world_cls = get_world(world_name)
@@ -316,29 +362,14 @@ async def _run_dev(
316
362
  # Create Plato client
317
363
  plato = AsyncPlato()
318
364
  session = None
319
-
320
- # Initialize Chronos logging if URL provided
321
- chronos_session_id: str | None = None
322
- if chronos_url:
323
- from plato.agents import init_logging
324
-
325
- chronos_session_id = f"dev-{uuid4().hex[:8]}"
326
- callback_url = f"{chronos_url.rstrip('/')}/api/v1/callback"
327
- init_logging(
328
- callback_url=callback_url,
329
- session_id=chronos_session_id,
330
- )
331
- logger.info(f"Chronos logging enabled: {callback_url} (session: {chronos_session_id})")
332
-
333
- # Update run_config with session info for agents
334
- run_config.session_id = chronos_session_id
335
- run_config.callback_url = callback_url
365
+ plato_session_id: str | None = None
336
366
 
337
367
  try:
338
368
  if env_configs:
339
369
  logger.info(f"Creating {len(env_configs)} environments...")
340
370
  session = await plato.sessions.create(envs=env_configs, timeout=env_timeout)
341
- logger.info(f"Created Plato session: {session.session_id}")
371
+ plato_session_id = session.session_id
372
+ logger.info(f"Created Plato session: {plato_session_id}")
342
373
  logger.info(f"Environments: {[e.alias for e in session.envs]}")
343
374
 
344
375
  # Serialize and add to config
@@ -347,6 +378,30 @@ async def _run_dev(
347
378
  else:
348
379
  logger.info("No environments defined for this world")
349
380
 
381
+ # Create Chronos session (after Plato session so we can link them)
382
+ logger.info(f"Creating Chronos session at {chronos_url}...")
383
+ chronos_session_id, callback_url = await _create_chronos_session(
384
+ chronos_url=chronos_url,
385
+ api_key=api_key,
386
+ world_name=world_name,
387
+ world_config=config_data,
388
+ plato_session_id=plato_session_id,
389
+ )
390
+ logger.info(f"Created Chronos session: {chronos_session_id}")
391
+ logger.info(f"View at: {chronos_url}/sessions/{chronos_session_id}")
392
+
393
+ # Initialize logging
394
+ from plato.agents import init_logging
395
+
396
+ init_logging(
397
+ callback_url=callback_url,
398
+ session_id=chronos_session_id,
399
+ )
400
+
401
+ # Update run_config with session info for agents
402
+ run_config.session_id = chronos_session_id
403
+ run_config.callback_url = callback_url
404
+
350
405
  # Run the world
351
406
  logger.info(f"Starting world '{world_name}'...")
352
407
  world_instance = world_cls()
@@ -360,10 +415,9 @@ async def _run_dev(
360
415
  await plato.close()
361
416
 
362
417
  # Reset logging
363
- if chronos_url:
364
- from plato.agents import reset_logging
418
+ from plato.agents import reset_logging
365
419
 
366
- reset_logging()
420
+ reset_logging()
367
421
 
368
422
 
369
423
  def _setup_colored_logging(verbose: bool = False) -> None:
@@ -410,11 +464,9 @@ def _setup_colored_logging(verbose: bool = False) -> None:
410
464
  def dev(
411
465
  world: Annotated[str, typer.Option("--world", "-w", help="World name to run")],
412
466
  config: Annotated[Path, typer.Option("--config", "-c", help="Path to config JSON file")],
413
- env_timeout: Annotated[int, typer.Option("--env-timeout", help="Timeout for environment creation (seconds)")] = 600,
414
- chronos_url: Annotated[
415
- str | None, typer.Option("--chronos-url", help="Chronos base URL for log events (e.g., http://localhost:8000)")
416
- ] = None,
417
- api_key: Annotated[str | None, typer.Option("--api-key", help="Plato API key for Chronos authentication")] = None,
467
+ env_timeout: Annotated[
468
+ int, typer.Option("--env-timeout", help="Timeout for environment creation (seconds)")
469
+ ] = 7200,
418
470
  agents_dir: Annotated[
419
471
  Path | None,
420
472
  typer.Option("--agents-dir", "-a", help="Directory containing agent source code (builds local images)"),
@@ -423,10 +475,8 @@ def dev(
423
475
  ) -> None:
424
476
  """Run a world locally for development/debugging.
425
477
 
426
- This creates Plato environments automatically (like Chronos does)
427
- and runs the world with the session attached.
428
-
429
- Optionally sends log events to a Chronos server for real-time monitoring.
478
+ This creates Plato environments automatically (like Chronos does),
479
+ creates a Chronos session for logging, and runs the world.
430
480
 
431
481
  Example config.json:
432
482
  {
@@ -440,18 +490,16 @@ def dev(
440
490
  }
441
491
  }
442
492
 
443
- Environment variables:
444
- PLATO_API_KEY: API key for Plato (required)
493
+ Required environment variables:
494
+ CHRONOS_URL: Chronos base URL (e.g., https://chronos.plato.so)
495
+ PLATO_API_KEY: API key for Plato and Chronos authentication
445
496
 
446
497
  Examples:
447
498
  # Basic usage
448
- plato-world-runner dev -w code -c config.json
499
+ CHRONOS_URL=https://chronos.plato.so plato-world-runner dev -w code -c config.json
449
500
 
450
501
  # With local agent builds (from plato-client repo)
451
502
  plato-world-runner dev -w code -c config.json --agents-dir ~/plato-client/agents
452
-
453
- # With Chronos logging
454
- plato-world-runner dev -w code -c config.json --chronos-url http://localhost:8000
455
503
  """
456
504
  # Setup colored logging with filtered noisy loggers
457
505
  _setup_colored_logging(verbose)
@@ -460,12 +508,16 @@ def dev(
460
508
  typer.echo(f"Error: Config file not found: {config}", err=True)
461
509
  raise typer.Exit(1)
462
510
 
511
+ if not os.environ.get("CHRONOS_URL"):
512
+ typer.echo("Error: CHRONOS_URL environment variable required", err=True)
513
+ raise typer.Exit(1)
514
+
463
515
  if not os.environ.get("PLATO_API_KEY"):
464
516
  typer.echo("Error: PLATO_API_KEY environment variable required", err=True)
465
517
  raise typer.Exit(1)
466
518
 
467
519
  try:
468
- asyncio.run(_run_dev(world, config, env_timeout, chronos_url, api_key, agents_dir))
520
+ asyncio.run(_run_dev(world, config, env_timeout, agents_dir))
469
521
  except Exception as e:
470
522
  logger.exception(f"World execution failed: {e}")
471
523
  raise typer.Exit(1)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plato-sdk-v2
3
- Version: 2.2.4
3
+ Version: 2.3.3
4
4
  Summary: Python SDK for the Plato API
5
5
  Author-email: Plato <support@plato.so>
6
6
  License-Expression: MIT
@@ -44,6 +44,8 @@ Description-Content-Type: text/markdown
44
44
 
45
45
  # Plato Python SDK
46
46
 
47
+
48
+
47
49
  Python SDK for the Plato platform. Uses [Harbor](https://harborframework.com) for agent execution.
48
50
 
49
51
  ## Installation
@@ -297,12 +297,12 @@ plato/_sims_generator/templates/python/errors.py.jinja,sha256=8L_FbHczBNLXJrbSlN
297
297
  plato/_sims_generator/templates/python/package_init.py.jinja,sha256=sOcJxUT0LuOWu5jOMGGKYxfCEjcYQv1hGF3n0iOA4hQ,986
298
298
  plato/_sims_generator/templates/python/tag_init.py.jinja,sha256=WB_9cv0JKIVg5TOXeSolET3tAfVg7sExjboh5jbCXz4,170
299
299
  plato/_sims_generator/templates/python/version_init.py.jinja,sha256=sGvFcYVfzXFyQDAe0PSOrg9yys93KE0XInFQNb1TvCY,179
300
- plato/agents/__init__.py,sha256=qslIFTVSe1yFeTRCKr8Z-mInWarj2HDbNZV4u6AiXek,2755
300
+ plato/agents/__init__.py,sha256=1l-Vw5SFydmPsl1toXdc2oH3eLhFwz6jtI_DKUx4vmo,2847
301
301
  plato/agents/base.py,sha256=vUbPQuNSo6Ka2lIB_ZOXgi4EoAjtAD7GIj9LnNotam0,4577
302
302
  plato/agents/build.py,sha256=CNMbVQFs2_pYit1dA29Davve28Yi4c7TNK9wBB7odrE,1621
303
303
  plato/agents/config.py,sha256=VZVMdCmEQnoR0VkrGdScG8p6zSKVFe7BZPd2h8lKNjI,5460
304
- plato/agents/logging.py,sha256=z9rDlGPbrpcTS8PephbK2rDqT7thC1KyLkua4ypUkv4,12210
305
- plato/agents/runner.py,sha256=YoqG1QdNScIjSSH0vPgnm42LlqeAeVsFT01VL77ony0,5565
304
+ plato/agents/logging.py,sha256=bL3Q14YeFxWCQydGKrQzQPgKQzBoCCXy_AAQPZpBylU,16307
305
+ plato/agents/runner.py,sha256=UQWg3gpYhWLnGLB6Bs595qH7nZV-ch-u5fPlkltT_kc,6812
306
306
  plato/agents/trajectory.py,sha256=WdiBmua0KvCrNaM3qgPI7-7B4xmSkfbP4oZ_9_8qHzU,10529
307
307
  plato/chronos/__init__.py,sha256=RHMvSrQS_-vkKOyTRuAkp2gKDP1HEuBLDnw8jcZs1Jg,739
308
308
  plato/chronos/client.py,sha256=YcOGtHWERyOD9z8LKt8bRMVL0cEwL2hiAP4qQgdZlUI,5495
@@ -392,13 +392,12 @@ plato/v1/sync_flow_executor.py,sha256=kgvNYOtA9FHeNfP7qb8ZPUIlTsfIss_Z98W8uX5vec
392
392
  plato/v1/sync_sdk.py,sha256=2sedg1QJiSxr1I3kCyfaLAnlAgHlbblc3QQP_47O30k,25697
393
393
  plato/v1/cli/__init__.py,sha256=om4b7PxgsoI7rEwuQelmQkqPdhMVn53_5qEN8kvksYw,105
394
394
  plato/v1/cli/agent.py,sha256=G6TV3blG_BqMDBWS-CG7GwzqoqcJTMsIKQ88jvLXb4k,43745
395
- plato/v1/cli/main.py,sha256=ZBF9J82Cp6TB-1mLkabJryxP44yNAYJoKE8K7LUNQng,6916
395
+ plato/v1/cli/main.py,sha256=ktPtBvMwykR7AjXmTQ6bmZkHdzpAjhX5Fq66cDbGSzA,6844
396
396
  plato/v1/cli/pm.py,sha256=uLM6WszKqxq9Czg1FraDyWb9_INUuHZq63imvRYfRLw,49734
397
- plato/v1/cli/sandbox.py,sha256=7VoiDIL6u2_8wZI4sj9J6CyI8IMfjHmHOp8FPiXs-3U,89411
398
- plato/v1/cli/sim.py,sha256=qF3H2RqMS96kQX8MwDpqXskZhpM4YFSgb283wcsMbfQ,266
399
- plato/v1/cli/ssh.py,sha256=pePHD0lFPwSkATZYSannpFtHfJWKImAdLyS2463aRRw,6287
397
+ plato/v1/cli/sandbox.py,sha256=5rth_jL73L72GC0VJ0meXRgZo2EpsJ_qI3ipFjfXzJY,95185
398
+ plato/v1/cli/ssh.py,sha256=10ag6S1sxMcAmvcg24qy-yYwXb1miWfqxkXOs4QX8u0,6623
400
399
  plato/v1/cli/utils.py,sha256=be-llK6T6NHnIQl_Kfs-8EPu9JhIuZ_k9tJ3Ts-AKt4,3887
401
- plato/v1/cli/verify.py,sha256=WZFxAqjpgq8vA0tc32g0VsNQjSZ1S0n4o_QoHQBkmsI,48404
400
+ plato/v1/cli/verify.py,sha256=7QmQwfOOkr8a51f8xfVIr2zif7wGl2E8HOZTbOaIoV0,20671
402
401
  plato/v1/cli/world.py,sha256=yBUadOJs1QYm6Jmx_ACDzogybRq5x4B-BnTvGO_ulQk,9757
403
402
  plato/v1/examples/doordash_tasks.py,sha256=8Sz9qx-vTmiOAiCAbrDRvZGsA1qQQBr1KHbxXdjr7OI,23233
404
403
  plato/v1/examples/loadtest.py,sha256=ZsQYNN_fZjE7CbrbVJb4KDc0OLaH7b66iPrEHDhuw0U,5609
@@ -449,26 +448,26 @@ plato/v2/types.py,sha256=MrHiE8AobOegeTfoKKHZ5JTccaFfS3-EW0arV7q8S5c,3533
449
448
  plato/v2/async_/__init__.py,sha256=zcNwuX2XD-WkUCFLvXtdRqFmCgeuY3-D4zGTRVwsAFI,484
450
449
  plato/v2/async_/artifact.py,sha256=JBWVQeVaZhkU2qn_knyzyA7wd5iQ8qxfLQ_l9GPhgYs,1217
451
450
  plato/v2/async_/client.py,sha256=GVgAgNN5gsDME8iV0zxqnwbsVS93J6cknOcq_VXwYN8,4209
452
- plato/v2/async_/environment.py,sha256=Dv_4QuQx5vLVp1m1mJR2fXybvbhz-Q4gLtZecCdyFT8,4622
451
+ plato/v2/async_/environment.py,sha256=M5IeWYLwREOIyuS2zqgBSqHE_x66_OZXrevA9Rkc8Is,5825
453
452
  plato/v2/async_/flow_executor.py,sha256=Tl4nRu1ZPWJFNNxyTGy-PxvebZEUD18ZDaz8T2chtzU,14188
454
- plato/v2/async_/session.py,sha256=3EL4SX1kiYDKd981dRWDZsEu1WtJOXkvbAdw3B5o_EI,35426
453
+ plato/v2/async_/session.py,sha256=ssTEFgfpDQElQEmeKulLWKLoW-wA3m_nI3UvEWb9lB0,36749
455
454
  plato/v2/sync/__init__.py,sha256=_WigxuehCC8A2yRy4mSaMQmIZhS0Gch4hhZC1VHyYXs,310
456
455
  plato/v2/sync/artifact.py,sha256=wTLC-tugG128wLvh-JqNPb0zsw5FXEJlZNahurSWink,1169
457
456
  plato/v2/sync/client.py,sha256=Q9fS1BF4KxTMMnceMwCMlb5dNFZ6LA4gsXWNLgsL2eE,3870
458
- plato/v2/sync/environment.py,sha256=EJS_MBXHQgdOYztmnvcDPyQV1Z0dV6BA-7UEJ_Z-bgE,3878
457
+ plato/v2/sync/environment.py,sha256=WnDzbyEHpwCSEP8XnfNSjIYS7rt7lYR4HGJjzprZmTQ,5066
459
458
  plato/v2/sync/flow_executor.py,sha256=N41-WCWIJVcCR2UmPUEiK7roNacYoeONkRXpR7lUgT8,13941
460
- plato/v2/sync/session.py,sha256=jl0leH3wENQCcOXQruqBcxhb47yo_9QBsdMMktgpnnw,27101
459
+ plato/v2/sync/session.py,sha256=jc71bZFb-1m4QTtU4V00OkNH8fHac3jyWTwq-uOK-BE,28409
461
460
  plato/v2/utils/__init__.py,sha256=XLeFFsjXkm9g2raMmo7Wt4QN4hhCrNZDJKnpffJ4LtM,38
462
461
  plato/v2/utils/db_cleanup.py,sha256=lnI5lsMHNHpG85Y99MaE4Rzc3618piuzhvH-uXO1zIc,8702
463
462
  plato/v2/utils/models.py,sha256=PwehSSnIRG-tM3tWL1PzZEH77ZHhIAZ9R0UPs6YknbM,1441
464
463
  plato/v2/utils/proxy_tunnel.py,sha256=8ZTd0jCGSfIHMvSv1fgEyacuISWnGPHLPbDglWroTzY,10463
465
464
  plato/worlds/README.md,sha256=TgG4aidude0ouJSCfY81Ev45hsUxPkO85HUIiWNqkcc,5463
466
- plato/worlds/__init__.py,sha256=crzpXFh4XD8eS4pYFTEUf3XgUf0wapFPT4npAu8sWwk,2078
467
- plato/worlds/base.py,sha256=254kR0YmRaaOyenDC1jlRhNlEsENgUpcq-crkWJcRe8,15200
465
+ plato/worlds/__init__.py,sha256=ALoou3l5lXvs_YZc5eH6HdMHpvhnpzKWqz__aSC1jFc,2152
466
+ plato/worlds/base.py,sha256=KsDq1TVVd4BKEFo42WodF4DPgodr00Gd1NrfzZEPqyw,25632
468
467
  plato/worlds/build_hook.py,sha256=KSoW0kqa5b7NyZ7MYOw2qsZ_2FkWuz0M3Ru7AKOP7Qw,3486
469
- plato/worlds/config.py,sha256=ggDcySspfeFry2KBUwhgnS6Po2KssYzwZNIDmVeGhPQ,9460
470
- plato/worlds/runner.py,sha256=RNnWFQ7rfEWE7TQ_tqgLHgLm1a4VxtP0mR7beALx4f0,15781
471
- plato_sdk_v2-2.2.4.dist-info/METADATA,sha256=hUWIc47BNWlYMW32HWQEeSNixo7licBxYJ0G9lnvhaU,8508
472
- plato_sdk_v2-2.2.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
473
- plato_sdk_v2-2.2.4.dist-info/entry_points.txt,sha256=upGMbJCx6YWUTKrPoYvYUYfFCqYr75nHDwhA-45m6p8,136
474
- plato_sdk_v2-2.2.4.dist-info/RECORD,,
468
+ plato/worlds/config.py,sha256=fkWoetCawIPf5xgj5EyJCvopmPPzZQAqt0Ke9P4hq5c,10845
469
+ plato/worlds/runner.py,sha256=qC7eIZScXgIb9xeuLkhpSQqgNjDkzmEPgqJFRkrEJD4,17271
470
+ plato_sdk_v2-2.3.3.dist-info/METADATA,sha256=U8DgV6t7AD7KedZtHsvH1tI86y6oGr9hKd7VYNjUvKM,8510
471
+ plato_sdk_v2-2.3.3.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
472
+ plato_sdk_v2-2.3.3.dist-info/entry_points.txt,sha256=upGMbJCx6YWUTKrPoYvYUYfFCqYr75nHDwhA-45m6p8,136
473
+ plato_sdk_v2-2.3.3.dist-info/RECORD,,
plato/v1/cli/sim.py DELETED
@@ -1,11 +0,0 @@
1
- """Plato CLI - Simulator commands (stub)."""
2
-
3
- import typer
4
-
5
- sim_app = typer.Typer(help="Simulator management commands (coming soon)")
6
-
7
-
8
- @sim_app.command()
9
- def list():
10
- """List available simulators."""
11
- typer.echo("Simulator list command not yet implemented.")