synth-ai 0.2.12__py3-none-any.whl → 0.2.13.dev2__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.

Potentially problematic release.


This version of synth-ai might be problematic. Click here for more details.

Files changed (229) hide show
  1. examples/multi_step/configs/crafter_rl_outcome.toml +74 -0
  2. examples/multi_step/configs/crafter_rl_stepwise_hosted_judge.toml +186 -0
  3. examples/multi_step/configs/crafter_rl_stepwise_shaped.toml +83 -0
  4. examples/multi_step/configs/crafter_rl_stepwise_simple.toml +78 -0
  5. examples/multi_step/crafter_rl_lora.md +51 -10
  6. examples/multi_step/sse_metrics_streaming_notes.md +357 -0
  7. examples/multi_step/task_app_config_notes.md +7 -1
  8. examples/swe/task_app/grpo_swe_mini.py +55 -26
  9. examples/swe/task_app/hosted/rollout.py +40 -0
  10. examples/swe/task_app/hosted/test_service.py +5 -6
  11. examples/task_apps/TESTING.md +275 -0
  12. examples/task_apps/__init__.py +0 -0
  13. examples/task_apps/crafter/__init__.py +0 -0
  14. examples/task_apps/crafter/task_app/__init__.py +2 -0
  15. examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter.py +21 -46
  16. examples/{warming_up_to_rl → task_apps/crafter}/task_app/grpo_crafter_task_app.py +1 -1
  17. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/policy.py +60 -4
  18. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/openai_client.py +109 -45
  19. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/policy_routes.py +67 -49
  20. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/rollout.py +242 -193
  21. examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_service.py +5 -6
  22. examples/task_apps/dev/pokemon_emerald/__init__.py +2 -0
  23. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/README.md +811 -0
  24. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/__init__.py +120 -0
  25. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/action.py +160 -0
  26. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/memory.py +155 -0
  27. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/perception.py +69 -0
  28. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/planning.py +96 -0
  29. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/simple.py +1502 -0
  30. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/agent/system_prompt.py +4 -0
  31. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/grab_map.py +68 -0
  32. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/manual.py +216 -0
  33. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/__init__.py +35 -0
  34. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emerald_utils.py +631 -0
  35. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/emulator.py +1544 -0
  36. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/enums.py +1428 -0
  37. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/memory_reader.py +4848 -0
  38. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/types.py +41 -0
  39. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pokemon_env/utils.py +298 -0
  40. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/pyproject.toml +95 -0
  41. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/run.py +204 -0
  42. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/__init__.py +0 -0
  43. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/app.py +2152 -0
  44. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/client.py +429 -0
  45. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/server/frame_server.py +155 -0
  46. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/README.md +78 -0
  47. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/__init__.py +0 -0
  48. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/run_tests.py +122 -0
  49. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_direct.py +76 -0
  50. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_agent_prompts.py +413 -0
  51. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_battle_state_formatting.py +204 -0
  52. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection.py +133 -0
  53. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_dialogue_detection_comprehensive.py +229 -0
  54. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_direct_agent_emulator.py +300 -0
  55. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_fps_adjustment_pytest.py +205 -0
  56. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_direct.py +200 -0
  57. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_house_to_outside_transition.py +284 -0
  58. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_map_ground_truth_comparison.py +468 -0
  59. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_memory_map.py +575 -0
  60. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_server_map_validation.py +311 -0
  61. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/tests/test_torchic_state.py +259 -0
  62. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/__init__.py +0 -0
  63. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/anticheat.py +372 -0
  64. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/checkpoint.py +296 -0
  65. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/error_handler.py +275 -0
  66. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/get_local_ip.py +22 -0
  67. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/helpers.py +44 -0
  68. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/llm_logger.py +514 -0
  69. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_formatter.py +415 -0
  70. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher.py +1763 -0
  71. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_stitcher_singleton.py +33 -0
  72. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_trimmer.py +106 -0
  73. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/map_visualizer.py +334 -0
  74. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/ocr_dialogue.py +1020 -0
  75. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/recording.py +188 -0
  76. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/state_formatter.py +1481 -0
  77. examples/task_apps/dev/pokemon_emerald/external/pokeagent-speedrun/utils/vlm.py +862 -0
  78. examples/task_apps/dev/pokemon_emerald/modal_app.py +114 -0
  79. examples/task_apps/dev/pokemon_emerald/task_app/README.md +81 -0
  80. examples/task_apps/dev/pokemon_emerald/task_app/__init__.py +6 -0
  81. examples/task_apps/dev/pokemon_emerald/task_app/pokemon_emerald.py +685 -0
  82. examples/task_apps/enron/__init__.py +1 -0
  83. examples/task_apps/enron/eval_groq_qwen32.toml +16 -0
  84. examples/task_apps/enron/task_app/README.md +14 -0
  85. examples/task_apps/enron/task_app/__init__.py +1 -0
  86. examples/task_apps/enron/task_app/grpo_enron.py +906 -0
  87. examples/task_apps/enron/task_app/grpo_enron_task_app.py +146 -0
  88. examples/task_apps/enron/tests/__init__.py +2 -0
  89. examples/task_apps/enron/tests/conftest.py +115 -0
  90. examples/task_apps/enron/tests/integration/__init__.py +2 -0
  91. examples/task_apps/enron/tests/integration/test_enron_eval.py +177 -0
  92. examples/task_apps/enron/tests/integration/test_enron_rollout.py +135 -0
  93. examples/task_apps/enron/tests/unit/__init__.py +2 -0
  94. examples/task_apps/enron/tests/unit/test_enron_environment.py +126 -0
  95. examples/task_apps/math/__init__.py +0 -0
  96. examples/{rl/task_app → task_apps/math}/math_single_step.py +19 -10
  97. examples/task_apps/pokemon_battle/__init__.py +2 -0
  98. examples/task_apps/pokemon_battle/modal_app.py +104 -0
  99. examples/task_apps/pokemon_battle/task_app/README.md +68 -0
  100. examples/task_apps/pokemon_battle/task_app/__init__.py +6 -0
  101. examples/task_apps/pokemon_battle/task_app/pokemon_showdown.py +932 -0
  102. examples/task_apps/pokemon_red/README.md +357 -0
  103. examples/task_apps/pokemon_red/__init__.py +3 -0
  104. examples/task_apps/pokemon_red/eval_pokemon_red_policy.py +225 -0
  105. examples/task_apps/pokemon_red/pallet_town_rl_config.toml +73 -0
  106. examples/task_apps/pokemon_red/task_app.py +606 -0
  107. examples/task_apps/pokemon_red/test_pallet_town_rewards.py +191 -0
  108. examples/task_apps/sokoban/README.md +307 -0
  109. examples/task_apps/sokoban/__init__.py +3 -0
  110. examples/task_apps/sokoban/eval_groq_qwen32.toml +16 -0
  111. examples/task_apps/sokoban/eval_openai_gpt5.toml +16 -0
  112. examples/task_apps/sokoban/task_app.py +1058 -0
  113. examples/task_apps/sokoban/tests/__init__.py +2 -0
  114. examples/task_apps/sokoban/tests/conftest.py +113 -0
  115. examples/task_apps/sokoban/tests/integration/__init__.py +2 -0
  116. examples/task_apps/sokoban/tests/integration/test_sokoban_eval.py +57 -0
  117. examples/task_apps/sokoban/tests/integration/test_sokoban_rollout.py +198 -0
  118. examples/task_apps/sokoban/tests/unit/__init__.py +2 -0
  119. examples/task_apps/sokoban/tests/unit/test_sokoban_environment.py +114 -0
  120. examples/task_apps/verilog/__init__.py +1 -0
  121. examples/task_apps/verilog/eval_groq_qwen32b.toml +20 -0
  122. examples/task_apps/verilog/task_app/README.md +12 -0
  123. examples/task_apps/verilog/task_app/__init__.py +1 -0
  124. examples/task_apps/verilog/task_app/grpo_verilog.py +931 -0
  125. examples/task_apps/verilog/task_app/grpo_verilog_task_app.py +145 -0
  126. examples/task_apps/verilog/tests/__init__.py +2 -0
  127. examples/task_apps/verilog/tests/conftest.py +115 -0
  128. examples/task_apps/verilog/tests/integration/__init__.py +2 -0
  129. examples/task_apps/verilog/tests/integration/test_verilog_eval.py +179 -0
  130. examples/task_apps/verilog/tests/integration/test_verilog_rollout.py +55 -0
  131. examples/task_apps/verilog/tests/unit/__init__.py +2 -0
  132. examples/task_apps/verilog/tests/unit/test_verilog_scoring.py +118 -0
  133. examples/vlm/crafter_openai_vlm_agent.py +4 -4
  134. examples/vlm/run_crafter_vlm_benchmark.py +4 -4
  135. examples/warming_up_to_rl/configs/eval_stepwise_complex.toml +4 -2
  136. examples/warming_up_to_rl/configs/eval_stepwise_simple.toml +4 -2
  137. examples/warming_up_to_rl/run_eval.py +127 -18
  138. examples/workflows/__init__.py +0 -0
  139. examples/workflows/math_rl/__init__.py +0 -0
  140. examples/workflows/math_rl/download_dataset.py +80 -0
  141. synth_ai/__init__.py +41 -1
  142. synth_ai/api/train/builders.py +73 -29
  143. synth_ai/api/train/cli.py +12 -6
  144. synth_ai/api/train/configs/__init__.py +44 -0
  145. synth_ai/api/train/configs/rl.py +134 -0
  146. synth_ai/api/train/configs/sft.py +95 -0
  147. synth_ai/api/train/configs/shared.py +24 -0
  148. synth_ai/api/train/env_resolver.py +5 -2
  149. synth_ai/api/train/supported_algos.py +10 -5
  150. synth_ai/api/train/utils.py +7 -4
  151. synth_ai/cli/__init__.py +7 -51
  152. synth_ai/cli/_storage.py +4 -3
  153. synth_ai/cli/_validate_task_app.py +11 -0
  154. synth_ai/cli/balance.py +4 -3
  155. synth_ai/cli/calc.py +2 -2
  156. synth_ai/cli/demo.py +49 -43
  157. synth_ai/cli/legacy_root_backup.py +1 -1
  158. synth_ai/cli/rl_demo.py +86 -106
  159. synth_ai/cli/root.py +0 -97
  160. synth_ai/cli/task_apps.py +1710 -186
  161. synth_ai/demos/core/cli.py +121 -159
  162. synth_ai/demos/demo_task_apps/crafter/grpo_crafter_task_app.py +28 -16
  163. synth_ai/environments/examples/crafter_classic/environment.py +16 -0
  164. synth_ai/environments/examples/enron/engine.py +7 -2
  165. synth_ai/environments/examples/enron/environment.py +68 -0
  166. synth_ai/environments/examples/red/engine.py +27 -0
  167. synth_ai/environments/examples/red/engine_helpers/memory_map.py +7 -0
  168. synth_ai/environments/examples/red/engine_helpers/reward_library/pallet_town_progression.py +477 -0
  169. synth_ai/environments/examples/red/engine_helpers/state_extraction.py +32 -0
  170. synth_ai/environments/examples/red/environment.py +60 -0
  171. synth_ai/environments/examples/sokoban/taskset.py +116 -0
  172. synth_ai/environments/examples/verilog/engine.py +30 -4
  173. synth_ai/evals/__init__.py +15 -0
  174. synth_ai/evals/client.py +82 -0
  175. synth_ai/evals/types.py +42 -0
  176. synth_ai/jobs/client.py +16 -4
  177. synth_ai/judge_schemas.py +127 -0
  178. synth_ai/py.typed +0 -0
  179. synth_ai/task/__init__.py +14 -5
  180. synth_ai/task/contracts.py +124 -38
  181. synth_ai/task/proxy.py +48 -56
  182. synth_ai/task/rubrics/__init__.py +53 -0
  183. synth_ai/task/rubrics/loaders.py +133 -0
  184. synth_ai/task/rubrics/models.py +57 -0
  185. synth_ai/task/rubrics/scoring.py +113 -0
  186. synth_ai/task/rubrics/strict.py +149 -0
  187. synth_ai/task/server.py +8 -7
  188. synth_ai/task/validators.py +269 -6
  189. synth_ai/tracing_v3/decorators.py +7 -3
  190. synth_ai/tracing_v3/replica_sync.py +4 -4
  191. synth_ai/tracing_v3/serialization.py +130 -0
  192. synth_ai/tracing_v3/trace_utils.py +317 -0
  193. synth_ai/tracing_v3/turso/native_manager.py +3 -3
  194. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/METADATA +4 -1
  195. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/RECORD +228 -89
  196. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/entry_points.txt +0 -1
  197. synth_ai/task/rubrics.py +0 -219
  198. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/README.md +0 -0
  199. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/README.md +0 -0
  200. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/__init__.py +0 -0
  201. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/branching.py +0 -0
  202. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/environment_routes.py +0 -0
  203. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/__init__.py +0 -0
  204. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/__init__.py +0 -0
  205. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/app.py +0 -0
  206. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/environment.py +0 -0
  207. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/react_agent.py +0 -0
  208. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/shared.py +0 -0
  209. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/envs/crafter/tools.py +0 -0
  210. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/hosted_app.py +0 -0
  211. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/inference/__init__.py +0 -0
  212. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/main.py +0 -0
  213. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/registry.py +0 -0
  214. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/__init__.py +0 -0
  215. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/storage/volume.py +0 -0
  216. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/test_agents.py +0 -0
  217. /examples/{warming_up_to_rl → task_apps/crafter}/task_app/synth_envs_hosted/utils.py +0 -0
  218. /examples/{rl/task_app → task_apps/math}/README.md +0 -0
  219. /examples/{rl/task_app → task_apps/math}/math_task_app.py +0 -0
  220. /examples/{rl → workflows/math_rl}/configs/eval_base_qwen.toml +0 -0
  221. /examples/{rl → workflows/math_rl}/configs/eval_rl_qwen.toml +0 -0
  222. /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen.toml +0 -0
  223. /examples/{rl → workflows/math_rl}/configs/rl_from_base_qwen17.toml +0 -0
  224. /examples/{rl → workflows/math_rl}/configs/rl_from_ft_qwen.toml +0 -0
  225. /examples/{rl → workflows/math_rl}/run_eval.py +0 -0
  226. /examples/{rl → workflows/math_rl}/run_rl_and_save.py +0 -0
  227. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/WHEEL +0 -0
  228. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/licenses/LICENSE +0 -0
  229. {synth_ai-0.2.12.dist-info → synth_ai-0.2.13.dev2.dist-info}/top_level.txt +0 -0
synth_ai/cli/rl_demo.py CHANGED
@@ -15,20 +15,31 @@ For convenience, dotted aliases are also exposed:
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
+ import importlib
19
+ from typing import Any, cast
20
+
18
21
  import click
22
+ from click.exceptions import Exit
23
+
24
+ demo_commands = cast(Any, importlib.import_module("synth_ai.demos.core.cli"))
19
25
 
20
26
 
21
- def _forward(args: list[str]) -> None:
22
- import sys
27
+ def _run_demo_command(func, *args, **kwargs) -> None:
28
+ """Invoke a demo command and exit via Click on non-zero status codes."""
23
29
 
24
30
  try:
25
- from synth_ai.demos.core import cli as demo_cli # type: ignore
26
- except Exception as e: # pragma: no cover
27
- click.echo(f"Failed to import RL demo CLI: {e}")
28
- sys.exit(1)
29
- rc = int(demo_cli.main(args) or 0)
30
- if rc != 0:
31
- sys.exit(rc)
31
+ result = func(*args, **kwargs)
32
+ except SystemExit as exc: # pragma: no cover - defensive
33
+ raise Exit(exc.code or 1) from exc
34
+
35
+ if result is None:
36
+ return
37
+ try:
38
+ code = int(result)
39
+ except (TypeError, ValueError):
40
+ return
41
+ if code != 0:
42
+ raise Exit(code)
32
43
 
33
44
 
34
45
  def register(cli):
@@ -37,14 +48,11 @@ def register(cli):
37
48
  """RL Demo commands (separate from legacy demo)."""
38
49
 
39
50
  # Help pyright understand dynamic Click group attributes
40
- from typing import Any
41
- from typing import cast as _cast
42
-
43
- _rlg = _cast(Any, rl_demo)
51
+ _rlg = cast(Any, rl_demo)
44
52
 
45
53
  @_rlg.command("setup")
46
54
  def rl_setup():
47
- _forward(["rl_demo.setup"]) # primary setup command
55
+ _run_demo_command(demo_commands.setup)
48
56
 
49
57
  # (prepare command removed; consolidated into configure)
50
58
 
@@ -64,34 +72,29 @@ def register(cli):
64
72
  help="Path to deploy_task_app.sh (optional legacy)",
65
73
  )
66
74
  def rl_deploy(local: bool, app: str | None, name: str, script: str | None):
67
- args: list[str] = ["rl_demo.deploy"]
68
- if local:
69
- args.append("--local")
70
- if app:
71
- args.extend(["--app", app])
72
- if name:
73
- args.extend(["--name", name])
74
- if script:
75
- args.extend(["--script", script])
76
- _forward(args)
75
+ _run_demo_command(
76
+ demo_commands.deploy,
77
+ local=local,
78
+ app=app,
79
+ name=name,
80
+ script=script,
81
+ )
77
82
 
78
83
  @_rlg.command("configure")
79
84
  def rl_configure():
80
- _forward(["rl_demo.configure"])
85
+ _run_demo_command(demo_commands.run)
81
86
 
82
87
  @_rlg.command("init")
83
88
  @click.option("--template", type=str, default=None, help="Template id to instantiate")
84
89
  @click.option("--dest", type=click.Path(), default=None, help="Destination directory for files")
85
90
  @click.option("--force", is_flag=True, help="Overwrite existing files in destination")
86
91
  def rl_init(template: str | None, dest: str | None, force: bool):
87
- args = ["rl_demo.init"]
88
- if template:
89
- args.extend(["--template", template])
90
- if dest:
91
- args.extend(["--dest", dest])
92
- if force:
93
- args.append("--force")
94
- _forward(args)
92
+ _run_demo_command(
93
+ demo_commands.init,
94
+ template=template,
95
+ dest=dest,
96
+ force=force,
97
+ )
95
98
 
96
99
  @_rlg.command("run")
97
100
  @click.option(
@@ -110,29 +113,24 @@ def register(cli):
110
113
  timeout: int,
111
114
  dry_run: bool,
112
115
  ):
113
- args = ["rl_demo.run"]
114
- if config:
115
- args.extend(["--config", config])
116
- if batch_size is not None:
117
- args.extend(["--batch-size", str(batch_size)])
118
- if group_size is not None:
119
- args.extend(["--group-size", str(group_size)])
120
- if model:
121
- args.extend(["--model", model])
122
- if timeout is not None:
123
- args.extend(["--timeout", str(timeout)])
124
- if dry_run:
125
- args.append("--dry-run")
126
- _forward(args)
116
+ _run_demo_command(
117
+ demo_commands.run,
118
+ config=config,
119
+ batch_size=batch_size,
120
+ group_size=group_size,
121
+ model=model,
122
+ timeout=timeout,
123
+ dry_run=dry_run,
124
+ )
127
125
 
128
126
  # Dotted aliases (top-level): legacy check → setup
129
127
  @cli.command("rl_demo.check")
130
128
  def rl_check_alias():
131
- _forward(["rl_demo.setup"])
129
+ _run_demo_command(demo_commands.setup)
132
130
 
133
131
  @cli.command("rl_demo.setup")
134
132
  def rl_setup_alias():
135
- _forward(["rl_demo.setup"])
133
+ _run_demo_command(demo_commands.setup)
136
134
 
137
135
  # (prepare alias removed)
138
136
 
@@ -152,34 +150,29 @@ def register(cli):
152
150
  help="Path to deploy_task_app.sh (optional legacy)",
153
151
  )
154
152
  def rl_deploy_alias(local: bool, app: str | None, name: str, script: str | None):
155
- args: list[str] = ["rl_demo.deploy"]
156
- if local:
157
- args.append("--local")
158
- if app:
159
- args.extend(["--app", app])
160
- if name:
161
- args.extend(["--name", name])
162
- if script:
163
- args.extend(["--script", script])
164
- _forward(args)
153
+ _run_demo_command(
154
+ demo_commands.deploy,
155
+ local=local,
156
+ app=app,
157
+ name=name,
158
+ script=script,
159
+ )
165
160
 
166
161
  @cli.command("rl_demo.configure")
167
162
  def rl_configure_alias():
168
- _forward(["rl_demo.configure"])
163
+ _run_demo_command(demo_commands.run)
169
164
 
170
165
  @cli.command("rl_demo.init")
171
166
  @click.option("--template", type=str, default=None, help="Template id to instantiate")
172
167
  @click.option("--dest", type=click.Path(), default=None, help="Destination directory for files")
173
168
  @click.option("--force", is_flag=True, help="Overwrite existing files in destination")
174
169
  def rl_init_alias(template: str | None, dest: str | None, force: bool):
175
- args = ["rl_demo.init"]
176
- if template:
177
- args.extend(["--template", template])
178
- if dest:
179
- args.extend(["--dest", dest])
180
- if force:
181
- args.append("--force")
182
- _forward(args)
170
+ _run_demo_command(
171
+ demo_commands.init,
172
+ template=template,
173
+ dest=dest,
174
+ force=force,
175
+ )
183
176
 
184
177
  @cli.command("rl_demo.run")
185
178
  @click.option(
@@ -198,20 +191,15 @@ def register(cli):
198
191
  timeout: int,
199
192
  dry_run: bool,
200
193
  ):
201
- args = ["rl_demo.run"]
202
- if config:
203
- args.extend(["--config", config])
204
- if batch_size is not None:
205
- args.extend(["--batch-size", str(batch_size)])
206
- if group_size is not None:
207
- args.extend(["--group-size", str(group_size)])
208
- if model:
209
- args.extend(["--model", model])
210
- if timeout is not None:
211
- args.extend(["--timeout", str(timeout)])
212
- if dry_run:
213
- args.append("--dry-run")
214
- _forward(args)
194
+ _run_demo_command(
195
+ demo_commands.run,
196
+ config=config,
197
+ batch_size=batch_size,
198
+ group_size=group_size,
199
+ model=model,
200
+ timeout=timeout,
201
+ dry_run=dry_run,
202
+ )
215
203
 
216
204
  # Top-level convenience alias: `synth-ai deploy`
217
205
  @cli.command("demo-deploy")
@@ -230,16 +218,13 @@ def register(cli):
230
218
  help="Path to deploy_task_app.sh (optional legacy)",
231
219
  )
232
220
  def deploy_demo(local: bool, app: str | None, name: str, script: str | None):
233
- args: list[str] = ["rl_demo.deploy"]
234
- if local:
235
- args.append("--local")
236
- if app:
237
- args.extend(["--app", app])
238
- if name:
239
- args.extend(["--name", name])
240
- if script:
241
- args.extend(["--script", script])
242
- _forward(args)
221
+ _run_demo_command(
222
+ demo_commands.deploy,
223
+ local=local,
224
+ app=app,
225
+ name=name,
226
+ script=script,
227
+ )
243
228
 
244
229
  @cli.command("run")
245
230
  @click.option(
@@ -258,17 +243,12 @@ def register(cli):
258
243
  timeout: int,
259
244
  dry_run: bool,
260
245
  ):
261
- args = ["run"]
262
- if config:
263
- args.extend(["--config", config])
264
- if batch_size is not None:
265
- args.extend(["--batch-size", str(batch_size)])
266
- if group_size is not None:
267
- args.extend(["--group-size", str(group_size)])
268
- if model:
269
- args.extend(["--model", model])
270
- if timeout is not None:
271
- args.extend(["--timeout", str(timeout)])
272
- if dry_run:
273
- args.append("--dry-run")
274
- _forward(args)
246
+ _run_demo_command(
247
+ demo_commands.run,
248
+ config=config,
249
+ batch_size=batch_size,
250
+ group_size=group_size,
251
+ model=model,
252
+ timeout=timeout,
253
+ dry_run=dry_run,
254
+ )
synth_ai/cli/root.py CHANGED
@@ -156,103 +156,6 @@ def cli():
156
156
  """Top-level command group for Synth AI."""
157
157
 
158
158
 
159
- # === Legacy demo command group (aliases new rl_demo implementation) ===
160
- @cli.group()
161
- def demo():
162
- """Demo helpers (deploy, configure, run)."""
163
-
164
-
165
- def _forward_to_demo(args: list[str]) -> None:
166
- # Lazy import to avoid loading demo deps unless needed
167
- try:
168
- from synth_ai.demos.core import cli as demo_cli # type: ignore
169
- except Exception as e: # pragma: no cover
170
- click.echo(f"Failed to import demo CLI: {e}")
171
- sys.exit(1)
172
- rc = int(demo_cli.main(args) or 0) # type: ignore[attr-defined]
173
- if rc != 0:
174
- sys.exit(rc)
175
-
176
-
177
- # (prepare command removed; handled by configure)
178
-
179
-
180
- @demo.command()
181
- @click.option("--local", is_flag=True, help="Run local FastAPI instead of Modal deploy")
182
- @click.option(
183
- "--app", type=click.Path(), default=None, help="Path to Modal app.py for uv run modal deploy"
184
- )
185
- @click.option("--name", type=str, default="synth-math-demo", help="Modal app name")
186
- @click.option(
187
- "--script", type=click.Path(), default=None, help="Path to deploy_task_app.sh (optional legacy)"
188
- )
189
- def deploy(local: bool, app: str | None, name: str, script: str | None):
190
- """Deploy the Math Task App (Modal by default)."""
191
- args: list[str] = ["rl_demo.deploy"]
192
- if local:
193
- args.append("--local")
194
- if app:
195
- args.extend(["--app", app])
196
- if name:
197
- args.extend(["--name", name])
198
- if script:
199
- args.extend(["--script", script])
200
- _forward_to_demo(args)
201
-
202
-
203
- @demo.command()
204
- def configure():
205
- """Print resolved environment and config path."""
206
- _forward_to_demo(["rl_demo.configure"])
207
-
208
-
209
- @demo.command()
210
- def setup():
211
- """Perform SDK handshake and write keys to .env."""
212
- _forward_to_demo(["rl_demo.setup"])
213
-
214
-
215
- @demo.command()
216
- @click.option("--template", type=str, default=None, help="Template id to instantiate")
217
- @click.option("--dest", type=str, default=None, help="Destination directory for files")
218
- @click.option("--force", is_flag=True, help="Overwrite existing files in destination")
219
- def init(template: str | None, dest: str | None, force: bool):
220
- """Copy demo task app template into the current directory."""
221
- args: list[str] = ["demo.init"]
222
- if template:
223
- args.extend(["--template", template])
224
- if dest:
225
- args.extend(["--dest", dest])
226
- if force:
227
- args.append("--force")
228
- _forward_to_demo(args)
229
-
230
-
231
- @demo.command()
232
- @click.option("--batch-size", type=int, default=None)
233
- @click.option("--group-size", type=int, default=None)
234
- @click.option("--model", type=str, default=None)
235
- @click.option("--timeout", type=int, default=600)
236
- def run(batch_size: int | None, group_size: int | None, model: str | None, timeout: int):
237
- """Kick off a short RL job using the prepared TOML."""
238
- args = ["rl_demo.run"]
239
- if batch_size is not None:
240
- args.extend(["--batch-size", str(batch_size)])
241
- if group_size is not None:
242
- args.extend(["--group-size", str(group_size)])
243
- if model:
244
- args.extend(["--model", model])
245
- if timeout:
246
- args.extend(["--timeout", str(timeout)])
247
- _forward_to_demo(args)
248
-
249
-
250
- @cli.command(name="setup")
251
- def setup_command():
252
- """Perform SDK handshake and write keys to .env."""
253
- _forward_to_demo(["rl_demo.setup"])
254
-
255
-
256
159
  @cli.command()
257
160
  @click.option("--db-file", default="traces/v3/synth_ai.db", help="Database file path")
258
161
  @click.option("--sqld-port", default=8080, type=int, help="Port for sqld HTTP interface")