synth-ai 0.2.6.dev6__py3-none-any.whl → 0.2.8__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.

synth_ai/cli/demo.py CHANGED
@@ -35,64 +35,73 @@ def _forward_to_new(args: list[str]) -> None:
35
35
 
36
36
  def register(cli):
37
37
  @cli.group("demo", invoke_without_command=True)
38
+ @click.option("--force", is_flag=True, help="Overwrite existing files in CWD when initializing demo")
38
39
  @click.option("--list", "list_only", is_flag=True, help="List available legacy demos and exit")
39
40
  @click.option("-f", "filter_term", default="", help="Filter legacy demos by substring")
40
41
  @click.pass_context
41
- def demo(ctx: click.Context, list_only: bool, filter_term: str):
42
+ def demo(ctx: click.Context, force: bool, list_only: bool, filter_term: str):
42
43
  """Demo helpers.
43
44
 
44
- - Legacy mode (no subcommand): find and run examples/*/run_demo.sh
45
+ - Default (no subcommand): initialize RL demo files into ./synth_demo/ (alias of rl_demo init)
46
+ - Legacy mode: with --list, find and run examples/*/run_demo.sh
45
47
  - New RL demo subcommands: deploy, configure, run
46
48
  """
47
49
  if ctx.invoked_subcommand is not None:
48
50
  return
49
- # Legacy behavior: interactive examples runner
50
- repo_root = Path(os.getcwd())
51
- examples_dir = repo_root / "examples"
52
- demos = _find_demo_scripts(examples_dir)
53
- if filter_term:
54
- demos = [p for p in demos if filter_term.lower() in str(p).lower()]
55
-
56
- if not demos:
57
- click.echo("No run_demo.sh scripts found under examples/.")
58
- return
59
51
 
52
+ # If explicitly asked to list legacy demos, show interactive picker
60
53
  if list_only:
54
+ repo_root = Path(os.getcwd())
55
+ examples_dir = repo_root / "examples"
56
+ demos = _find_demo_scripts(examples_dir)
57
+ if filter_term:
58
+ demos = [p for p in demos if filter_term.lower() in str(p).lower()]
59
+
60
+ if not demos:
61
+ click.echo("No run_demo.sh scripts found under examples/.")
62
+ return
63
+
61
64
  click.echo("Available demos:")
62
- for p in demos:
63
- click.echo(f" - {p.relative_to(repo_root)}")
64
- return
65
+ for idx, p in enumerate(demos, start=1):
66
+ click.echo(f" {idx}. {p.relative_to(repo_root)}")
67
+ click.echo("")
68
+
69
+ def _validate_choice(val: str) -> int:
70
+ try:
71
+ i = int(val)
72
+ except Exception as err:
73
+ raise click.BadParameter("Enter a number from the list") from err
74
+ if i < 1 or i > len(demos):
75
+ raise click.BadParameter(f"Choose a number between 1 and {len(demos)}")
76
+ return i
77
+
78
+ choice = click.prompt("Select a demo to run", value_proc=_validate_choice)
79
+ script = demos[choice - 1]
65
80
 
66
- click.echo("Available demos:")
67
- for idx, p in enumerate(demos, start=1):
68
- click.echo(f" {idx}. {p.relative_to(repo_root)}")
69
- click.echo("")
81
+ click.echo("")
82
+ click.echo(f"🚀 Running {script.relative_to(repo_root)}\n")
70
83
 
71
- def _validate_choice(val: str) -> int:
72
84
  try:
73
- i = int(val)
74
- except Exception as err:
75
- raise click.BadParameter("Enter a number from the list") from err
76
- if i < 1 or i > len(demos):
77
- raise click.BadParameter(f"Choose a number between 1 and {len(demos)}")
78
- return i
79
-
80
- choice = click.prompt("Select a demo to run", value_proc=_validate_choice)
81
- script = demos[choice - 1]
82
-
83
- click.echo("")
84
- click.echo(f"🚀 Running {script.relative_to(repo_root)}\n")
85
-
86
- try:
87
- subprocess.run(["bash", str(script)], check=True)
88
- except subprocess.CalledProcessError as e:
89
- click.echo(f"❌ Demo exited with non-zero status: {e.returncode}")
90
- except KeyboardInterrupt:
91
- click.echo("\n🛑 Demo interrupted by user")
85
+ subprocess.run(["bash", str(script)], check=True)
86
+ except subprocess.CalledProcessError as e:
87
+ click.echo(f" Demo exited with non-zero status: {e.returncode}")
88
+ except KeyboardInterrupt:
89
+ click.echo("\n🛑 Demo interrupted by user")
90
+ return
91
+
92
+ # Default: forward to RL demo init behavior, optionally with --force
93
+ args: list[str] = ["rl_demo.init"]
94
+ if force:
95
+ args.append("--force")
96
+ _forward_to_new(args)
92
97
 
93
98
  # (prepare command removed; configure now prepares baseline TOML)
94
99
 
95
- @demo.command("deploy")
100
+ # Help pyright understand dynamic Click group attributes
101
+ from typing import Any, cast as _cast
102
+ _dg = _cast(Any, demo)
103
+
104
+ @_dg.command("deploy")
96
105
  @click.option("--local", is_flag=True, help="Run local FastAPI instead of Modal deploy")
97
106
  @click.option("--app", type=click.Path(), default=None, help="Path to Modal app.py for uv run modal deploy")
98
107
  @click.option("--name", type=str, default="synth-math-demo", help="Modal app name")
@@ -109,11 +118,15 @@ def register(cli):
109
118
  args.extend(["--script", script])
110
119
  _forward_to_new(args)
111
120
 
112
- @demo.command("configure")
121
+ @_dg.command("configure")
113
122
  def demo_configure():
114
123
  _forward_to_new(["rl_demo.configure"])
115
124
 
116
- @demo.command("run")
125
+ @_dg.command("setup")
126
+ def demo_setup():
127
+ _forward_to_new(["rl_demo.setup"])
128
+
129
+ @_dg.command("run")
117
130
  @click.option("--batch-size", type=int, default=None)
118
131
  @click.option("--group-size", type=int, default=None)
119
132
  @click.option("--model", type=str, default=None)
synth_ai/cli/rl_demo.py CHANGED
@@ -7,6 +7,7 @@ Usage examples:
7
7
  uvx synth-ai rl_demo deploy --app /path/to/math_task_app.py --name synth-math-demo
8
8
  uvx synth-ai rl_demo configure
9
9
  uvx synth-ai rl_demo run --batch-size 4 --group-size 16 --model Qwen/Qwen3-0.6B
10
+ uvx synth-ai run --config demo_config.toml
10
11
 
11
12
  For convenience, dotted aliases are also exposed:
12
13
  uvx synth-ai rl_demo.check
@@ -38,9 +39,9 @@ def register(cli):
38
39
  from typing import Any, cast as _cast
39
40
  _rlg = _cast(Any, rl_demo)
40
41
 
41
- @_rlg.command("check")
42
- def rl_check():
43
- _forward(["rl_demo.check"]) # reuse same implementation
42
+ @_rlg.command("setup")
43
+ def rl_setup():
44
+ _forward(["rl_demo.setup"]) # primary setup command
44
45
 
45
46
  # (prepare command removed; consolidated into configure)
46
47
 
@@ -96,10 +97,14 @@ def register(cli):
96
97
  args.append("--dry-run")
97
98
  _forward(args)
98
99
 
99
- # Dotted aliases (top-level) for convenience: rl_demo.check etc.
100
+ # Dotted aliases (top-level): legacy check → setup
100
101
  @cli.command("rl_demo.check")
101
102
  def rl_check_alias():
102
- _forward(["rl_demo.check"])
103
+ _forward(["rl_demo.setup"])
104
+
105
+ @cli.command("rl_demo.setup")
106
+ def rl_setup_alias():
107
+ _forward(["rl_demo.setup"])
103
108
 
104
109
  # (prepare alias removed)
105
110
 
@@ -154,3 +159,44 @@ def register(cli):
154
159
  if dry_run:
155
160
  args.append("--dry-run")
156
161
  _forward(args)
162
+
163
+ # Top-level convenience alias: `synth-ai deploy`
164
+ @cli.command("deploy")
165
+ @click.option("--local", is_flag=True, help="Run local FastAPI instead of Modal deploy")
166
+ @click.option("--app", type=click.Path(), default=None, help="Path to Modal app.py for uv run modal deploy")
167
+ @click.option("--name", type=str, default="synth-math-demo", help="Modal app name")
168
+ @click.option("--script", type=click.Path(), default=None, help="Path to deploy_task_app.sh (optional legacy)")
169
+ def deploy_top(local: bool, app: str | None, name: str, script: str | None):
170
+ args: list[str] = ["rl_demo.deploy"]
171
+ if local:
172
+ args.append("--local")
173
+ if app:
174
+ args.extend(["--app", app])
175
+ if name:
176
+ args.extend(["--name", name])
177
+ if script:
178
+ args.extend(["--script", script])
179
+ _forward(args)
180
+
181
+ @cli.command("run")
182
+ @click.option("--config", type=click.Path(), default=None, help="Path to TOML config (skip prompt)")
183
+ @click.option("--batch-size", type=int, default=None)
184
+ @click.option("--group-size", type=int, default=None)
185
+ @click.option("--model", type=str, default=None)
186
+ @click.option("--timeout", type=int, default=600)
187
+ @click.option("--dry-run", is_flag=True, help="Print request body and exit")
188
+ def run_top(config: str | None, batch_size: int | None, group_size: int | None, model: str | None, timeout: int, dry_run: bool):
189
+ args = ["run"]
190
+ if config:
191
+ args.extend(["--config", config])
192
+ if batch_size is not None:
193
+ args.extend(["--batch-size", str(batch_size)])
194
+ if group_size is not None:
195
+ args.extend(["--group-size", str(group_size)])
196
+ if model:
197
+ args.extend(["--model", model])
198
+ if timeout is not None:
199
+ args.extend(["--timeout", str(timeout)])
200
+ if dry_run:
201
+ args.append("--dry-run")
202
+ _forward(args)
synth_ai/cli/root.py CHANGED
@@ -117,6 +117,12 @@ def configure():
117
117
  _forward_to_demo(["rl_demo.configure"])
118
118
 
119
119
 
120
+ @demo.command()
121
+ def setup():
122
+ """Perform SDK handshake and write keys to .env."""
123
+ _forward_to_demo(["rl_demo.setup"])
124
+
125
+
120
126
  @demo.command()
121
127
  @click.option("--batch-size", type=int, default=None)
122
128
  @click.option("--group-size", type=int, default=None)
@@ -136,6 +142,12 @@ def run(batch_size: int | None, group_size: int | None, model: str | None, timeo
136
142
  _forward_to_demo(args)
137
143
 
138
144
 
145
+ @cli.command()
146
+ def setup():
147
+ """Perform SDK handshake and write keys to .env."""
148
+ _forward_to_demo(["rl_demo.setup"])
149
+
150
+
139
151
  @cli.command()
140
152
  @click.option("--db-file", default="traces/v3/synth_ai.db", help="Database file path")
141
153
  @click.option("--sqld-port", default=8080, type=int, help="Port for sqld HTTP interface")