rhylthyme-cli-runner 0.2.6a0__tar.gz → 0.2.7a0__tar.gz
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.
- {rhylthyme_cli_runner-0.2.6a0/src/rhylthyme_cli_runner.egg-info → rhylthyme_cli_runner-0.2.7a0}/PKG-INFO +12 -3
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/README.md +11 -2
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/setup.py +1 -1
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/__init__.py +1 -1
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/import_cli.py +101 -3
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/checks.py +1 -1
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0/src/rhylthyme_cli_runner.egg-info}/PKG-INFO +12 -3
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_import_cli.py +63 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/LICENSE +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/pyproject.toml +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/setup.cfg +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/environment_icons.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/environment_loader.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/environment_schemas.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/__init__.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/compare.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/gold.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/harness.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/llm.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/matcher.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/metrics.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/__init__.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/authoring_guide.md +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/baseline.md +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/baseline.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/extract.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/patterns/four_turn.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/report.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/expand_replicates.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/__init__.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/calibrate.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/calibrate_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/evaluate.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/evaluate_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/factors.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/hash.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/predict.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/recorder.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/render.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/replay.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/report.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/report_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/store.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/synth.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/history/usable.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/instance_checks.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/program_planner.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/program_runner.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/__init__.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/auth.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/mcp_client.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/render_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/validate_program.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner.egg-info/SOURCES.txt +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner.egg-info/dependency_links.txt +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner.egg-info/entry_points.txt +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner.egg-info/requires.txt +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner.egg-info/top_level.txt +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_calibrate.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_eval_baseline.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_eval_harness.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_eval_providers.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_eval_scorer.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_evaluate.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_example_validation.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_examples_integration.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_expand_replicates.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_hash_parity.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_history_report.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_mcp_checks.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_planner_time_strings.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_predict.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_program_runner.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_remote.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_render_cli.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_replay.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_run_recorder.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_skill.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_synth.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_usable.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_validate_examples_ci.py +0 -0
- {rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_validate_program.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rhylthyme-cli-runner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7a0
|
|
4
4
|
Summary: CLI runner for Rhylthyme real-time program schedules
|
|
5
5
|
Home-page: https://github.com/rhylthyme/rhylthyme-cli-runner
|
|
6
6
|
Author: Rhylthyme Team
|
|
@@ -561,8 +561,17 @@ rhylthyme search "pad thai" -i spoonacular # then impo
|
|
|
561
561
|
```
|
|
562
562
|
|
|
563
563
|
**Options:** `-i IMPORTER` (default: chosen from the URL), `-o PATH`,
|
|
564
|
-
`--stdout`, `--publish` (and `--open`), `--no-validate`. `-` reads
|
|
565
|
-
source from stdin (with `-i`).
|
|
564
|
+
`--stdout`, `--publish` (and `--open`), `--no-validate`, `--review`. `-` reads
|
|
565
|
+
pasted source from stdin (with `-i`).
|
|
566
|
+
|
|
567
|
+
`--review` sends the import and its source to a model on the server (GPT-5.6
|
|
568
|
+
Luna, the model that related steps best in the paper's evaluation) and prints
|
|
569
|
+
what looks wrong: a default duration on "simmer until thick", a step the
|
|
570
|
+
parser dropped, steps chained that the source runs in parallel, a total that
|
|
571
|
+
disagrees with the source. It needs `rhylthyme login`, spends one model call
|
|
572
|
+
(capped per day), and changes nothing: the findings are yours to apply. On
|
|
573
|
+
rhylthyme.com the same review runs automatically after every import when you
|
|
574
|
+
are signed in.
|
|
566
575
|
|
|
567
576
|
### `rhylthyme render`
|
|
568
577
|
|
|
@@ -501,8 +501,17 @@ rhylthyme search "pad thai" -i spoonacular # then impo
|
|
|
501
501
|
```
|
|
502
502
|
|
|
503
503
|
**Options:** `-i IMPORTER` (default: chosen from the URL), `-o PATH`,
|
|
504
|
-
`--stdout`, `--publish` (and `--open`), `--no-validate`. `-` reads
|
|
505
|
-
source from stdin (with `-i`).
|
|
504
|
+
`--stdout`, `--publish` (and `--open`), `--no-validate`, `--review`. `-` reads
|
|
505
|
+
pasted source from stdin (with `-i`).
|
|
506
|
+
|
|
507
|
+
`--review` sends the import and its source to a model on the server (GPT-5.6
|
|
508
|
+
Luna, the model that related steps best in the paper's evaluation) and prints
|
|
509
|
+
what looks wrong: a default duration on "simmer until thick", a step the
|
|
510
|
+
parser dropped, steps chained that the source runs in parallel, a total that
|
|
511
|
+
disagrees with the source. It needs `rhylthyme login`, spends one model call
|
|
512
|
+
(capped per day), and changes nothing: the findings are yours to apply. On
|
|
513
|
+
rhylthyme.com the same review runs automatically after every import when you
|
|
514
|
+
are signed in.
|
|
506
515
|
|
|
507
516
|
### `rhylthyme render`
|
|
508
517
|
|
|
@@ -19,7 +19,7 @@ def read_readme():
|
|
|
19
19
|
|
|
20
20
|
setup(
|
|
21
21
|
name="rhylthyme-cli-runner",
|
|
22
|
-
version="0.2.
|
|
22
|
+
version="0.2.7a0",
|
|
23
23
|
description="CLI runner for Rhylthyme real-time program schedules",
|
|
24
24
|
long_description=read_readme(),
|
|
25
25
|
long_description_content_type="text/markdown",
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/__init__.py
RENAMED
|
@@ -6,7 +6,7 @@ This package provides the command-line interface for running and validating
|
|
|
6
6
|
Rhylthyme real-time program schedules.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
-
__version__ = "0.2.
|
|
9
|
+
__version__ = "0.2.7a0"
|
|
10
10
|
__author__ = "Rhylthyme Team"
|
|
11
11
|
__description__ = "CLI runner for Rhylthyme real-time program schedules"
|
|
12
12
|
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/import_cli.py
RENAMED
|
@@ -134,8 +134,21 @@ def _validation(program: dict):
|
|
|
134
134
|
@click.option(
|
|
135
135
|
"--no-validate", is_flag=True, help="Skip validation of the imported program."
|
|
136
136
|
)
|
|
137
|
+
@click.option(
|
|
138
|
+
"--review",
|
|
139
|
+
"do_review",
|
|
140
|
+
is_flag=True,
|
|
141
|
+
help="Have a model read the import against its source and report what looks wrong (needs `rhylthyme login`).",
|
|
142
|
+
)
|
|
137
143
|
def import_command(
|
|
138
|
-
source,
|
|
144
|
+
source,
|
|
145
|
+
importer_name,
|
|
146
|
+
output,
|
|
147
|
+
to_stdout,
|
|
148
|
+
do_publish,
|
|
149
|
+
open_url,
|
|
150
|
+
no_validate,
|
|
151
|
+
do_review,
|
|
139
152
|
):
|
|
140
153
|
"""Import a recipe, protocol or deck as a program.
|
|
141
154
|
|
|
@@ -145,6 +158,7 @@ def import_command(
|
|
|
145
158
|
.cook or .pptx file. `-` reads the source text from stdin (with -i).
|
|
146
159
|
rhylthyme import https://www.seriouseats.com/the-best-chili-recipe
|
|
147
160
|
rhylthyme import 52772 -i themealdb --publish
|
|
161
|
+
rhylthyme import recipe.cook -i cooklang --review # a second opinion on durations, order, gaps
|
|
148
162
|
rhylthyme import https://raw.githubusercontent.com/Opentrons/Protocols/develop/protocols/007992/rna_isolation.ot2.apiv2.py
|
|
149
163
|
rhylthyme importers # what is installed
|
|
150
164
|
"""
|
|
@@ -157,8 +171,22 @@ def import_command(
|
|
|
157
171
|
)
|
|
158
172
|
text = sys.stdin.read()
|
|
159
173
|
importer = _pick(registry, source, importer_name)
|
|
174
|
+
token = None
|
|
175
|
+
if do_review:
|
|
176
|
+
# Before any work: the review needs an account, say so now.
|
|
177
|
+
from .remote import auth
|
|
178
|
+
|
|
179
|
+
try:
|
|
180
|
+
token = auth.access_token()
|
|
181
|
+
except auth.AuthError as e:
|
|
182
|
+
raise click.ClickException(
|
|
183
|
+
f"{e} (--review sends the import to a model on the server, which needs your account.)"
|
|
184
|
+
)
|
|
160
185
|
click.echo(f"Importing with {importer.name}…", err=True)
|
|
161
186
|
result = _import_one(importer, source, text)
|
|
187
|
+
source_text = (
|
|
188
|
+
text if text is not None else _source_text_for_review(importer, source)
|
|
189
|
+
)
|
|
162
190
|
if not result.success:
|
|
163
191
|
raise click.ClickException(result.error or "import failed")
|
|
164
192
|
program = result.program
|
|
@@ -167,9 +195,10 @@ def import_command(
|
|
|
167
195
|
v = _validation(program)
|
|
168
196
|
errors = v.get("errors") or v.get("logic_errors") or []
|
|
169
197
|
if not v.get("is_valid", v.get("valid", True)):
|
|
170
|
-
for
|
|
198
|
+
for finding in errors[:8]:
|
|
171
199
|
click.echo(
|
|
172
|
-
f" ✗ {
|
|
200
|
+
f" ✗ {finding if isinstance(finding, str) else finding.get('message', finding)}",
|
|
201
|
+
err=True,
|
|
173
202
|
)
|
|
174
203
|
raise click.ClickException(
|
|
175
204
|
"The imported program does not validate; not published. Re-run with --no-validate to keep it anyway."
|
|
@@ -191,6 +220,14 @@ def import_command(
|
|
|
191
220
|
target.write_text(payload + "\n")
|
|
192
221
|
click.echo(f"Saved {target}", err=True)
|
|
193
222
|
|
|
223
|
+
if do_review:
|
|
224
|
+
_review(
|
|
225
|
+
program,
|
|
226
|
+
token,
|
|
227
|
+
source_text=source_text,
|
|
228
|
+
source_url=source if source.startswith(("http://", "https://")) else None,
|
|
229
|
+
)
|
|
230
|
+
|
|
194
231
|
if do_publish:
|
|
195
232
|
from .remote.cli import publish as publish_command
|
|
196
233
|
|
|
@@ -212,6 +249,67 @@ def import_command(
|
|
|
212
249
|
Path(tmp_path).unlink(missing_ok=True)
|
|
213
250
|
|
|
214
251
|
|
|
252
|
+
def _source_text_for_review(importer, source: str) -> Optional[str]:
|
|
253
|
+
"""The text the import came from, when the CLI has it: a local file, or
|
|
254
|
+
a URL the CLI fetched for a text importer. Recipe-site imports do not
|
|
255
|
+
keep the page, so the reviewer gets the URL instead."""
|
|
256
|
+
path = Path(source)
|
|
257
|
+
if path.is_file() and path.suffix.lower() in (".cook", ".py", ".txt", ".md"):
|
|
258
|
+
try:
|
|
259
|
+
return path.read_text()
|
|
260
|
+
except OSError:
|
|
261
|
+
return None
|
|
262
|
+
if (
|
|
263
|
+
source.startswith(("http://", "https://"))
|
|
264
|
+
and hasattr(importer, "import_from_source")
|
|
265
|
+
and not getattr(importer, "supported_domains", None)
|
|
266
|
+
):
|
|
267
|
+
try:
|
|
268
|
+
from .remote.cli import _fetch_bytes
|
|
269
|
+
|
|
270
|
+
return _fetch_bytes(source).decode("utf-8")
|
|
271
|
+
except Exception: # noqa: BLE001
|
|
272
|
+
return None
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def _review(
|
|
277
|
+
program: dict, token: str, *, source_text: Optional[str], source_url: Optional[str]
|
|
278
|
+
) -> None:
|
|
279
|
+
from .remote import mcp_client as MC
|
|
280
|
+
|
|
281
|
+
click.echo("Reviewing…", err=True)
|
|
282
|
+
client = MC.McpClient(url=MC.endpoint_for(None))
|
|
283
|
+
args = {"program": program, "token": token}
|
|
284
|
+
if source_text:
|
|
285
|
+
args["source_text"] = source_text
|
|
286
|
+
elif source_url:
|
|
287
|
+
args["source_url"] = source_url
|
|
288
|
+
try:
|
|
289
|
+
result = client.call_tool("review_program", args, timeout=150)
|
|
290
|
+
except MC.ToolError as e:
|
|
291
|
+
raise click.ClickException(f"Review failed: {e.text}")
|
|
292
|
+
except MC.McpError as e:
|
|
293
|
+
raise click.ClickException(f"Review failed: {e}")
|
|
294
|
+
review = result.structured or {}
|
|
295
|
+
findings = review.get("findings") or []
|
|
296
|
+
mark = {"error": "✗", "warning": "!", "note": "·"}
|
|
297
|
+
click.echo("")
|
|
298
|
+
click.echo(
|
|
299
|
+
review.get("summary")
|
|
300
|
+
or ("Review: no problems found." if not findings else "Review:")
|
|
301
|
+
)
|
|
302
|
+
for f in findings:
|
|
303
|
+
where = f" [{f['stepId']}]" if f.get("stepId") else ""
|
|
304
|
+
click.echo(f" {mark.get(f.get('severity'), '·')}{where} {f.get('message')}")
|
|
305
|
+
if f.get("suggestion"):
|
|
306
|
+
click.echo(f" → {f['suggestion']}")
|
|
307
|
+
if findings:
|
|
308
|
+
click.echo(
|
|
309
|
+
"\nThe file is unchanged; edit it and `rhylthyme validate` again.", err=True
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
|
|
215
313
|
@click.command("search")
|
|
216
314
|
@click.argument("query")
|
|
217
315
|
@click.option(
|
|
@@ -252,7 +252,7 @@ def check_initialize(client, endpoint, opts, state) -> str:
|
|
|
252
252
|
return f"{info['name']} {info.get('version', '?')}, protocol {result['protocolVersion']}"
|
|
253
253
|
|
|
254
254
|
|
|
255
|
-
TOOL_DEFINITION_BUDGET_CHARS =
|
|
255
|
+
TOOL_DEFINITION_BUDGET_CHARS = 17000
|
|
256
256
|
|
|
257
257
|
|
|
258
258
|
def check_tools(client, endpoint, opts, state) -> str:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rhylthyme-cli-runner
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.7a0
|
|
4
4
|
Summary: CLI runner for Rhylthyme real-time program schedules
|
|
5
5
|
Home-page: https://github.com/rhylthyme/rhylthyme-cli-runner
|
|
6
6
|
Author: Rhylthyme Team
|
|
@@ -561,8 +561,17 @@ rhylthyme search "pad thai" -i spoonacular # then impo
|
|
|
561
561
|
```
|
|
562
562
|
|
|
563
563
|
**Options:** `-i IMPORTER` (default: chosen from the URL), `-o PATH`,
|
|
564
|
-
`--stdout`, `--publish` (and `--open`), `--no-validate`. `-` reads
|
|
565
|
-
source from stdin (with `-i`).
|
|
564
|
+
`--stdout`, `--publish` (and `--open`), `--no-validate`, `--review`. `-` reads
|
|
565
|
+
pasted source from stdin (with `-i`).
|
|
566
|
+
|
|
567
|
+
`--review` sends the import and its source to a model on the server (GPT-5.6
|
|
568
|
+
Luna, the model that related steps best in the paper's evaluation) and prints
|
|
569
|
+
what looks wrong: a default duration on "simmer until thick", a step the
|
|
570
|
+
parser dropped, steps chained that the source runs in parallel, a total that
|
|
571
|
+
disagrees with the source. It needs `rhylthyme login`, spends one model call
|
|
572
|
+
(capped per day), and changes nothing: the findings are yours to apply. On
|
|
573
|
+
rhylthyme.com the same review runs automatically after every import when you
|
|
574
|
+
are signed in.
|
|
566
575
|
|
|
567
576
|
### `rhylthyme render`
|
|
568
577
|
|
|
@@ -248,3 +248,66 @@ def test_a_missing_local_file_says_so(fake, tmp_path):
|
|
|
248
248
|
)
|
|
249
249
|
assert r.exit_code != 0 and "No such file" in r.output
|
|
250
250
|
assert fake.calls == []
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def test_review_needs_a_login_before_any_work(fake, monkeypatch):
|
|
254
|
+
monkeypatch.delenv("RHYLTHYME_TOKEN", raising=False)
|
|
255
|
+
from rhylthyme_cli_runner.remote import auth
|
|
256
|
+
|
|
257
|
+
monkeypatch.setattr(auth, "load_credentials", lambda path=None: None)
|
|
258
|
+
r = CliRunner().invoke(
|
|
259
|
+
cli, ["import", "https://fake.example/dinner", "--review", "--stdout"]
|
|
260
|
+
)
|
|
261
|
+
assert r.exit_code != 0 and "rhylthyme login" in r.output
|
|
262
|
+
assert fake.calls == [], "nothing was imported"
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def test_review_sends_the_program_and_source_and_prints_findings(
|
|
266
|
+
fake, monkeypatch, tmp_path
|
|
267
|
+
):
|
|
268
|
+
monkeypatch.setenv("RHYLTHYME_TOKEN", "tok-1")
|
|
269
|
+
from rhylthyme_cli_runner.remote import mcp_client as MC
|
|
270
|
+
|
|
271
|
+
seen = {}
|
|
272
|
+
|
|
273
|
+
class FakeMcp:
|
|
274
|
+
def __init__(self, url=None, **kw):
|
|
275
|
+
seen["url"] = url
|
|
276
|
+
|
|
277
|
+
def call_tool(self, name, args, timeout=None, **kw):
|
|
278
|
+
seen["tool"], seen["args"] = name, args
|
|
279
|
+
return MC.ToolResult(
|
|
280
|
+
content=[{"type": "text", "text": "x"}],
|
|
281
|
+
structured={
|
|
282
|
+
"summary": "One problem.",
|
|
283
|
+
"usable": False,
|
|
284
|
+
"findings": [
|
|
285
|
+
{
|
|
286
|
+
"severity": "error",
|
|
287
|
+
"stepId": "s1",
|
|
288
|
+
"message": "Too short.",
|
|
289
|
+
"suggestion": "90m",
|
|
290
|
+
},
|
|
291
|
+
{"severity": "note", "message": "Fine."},
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
monkeypatch.setattr(MC, "McpClient", FakeMcp)
|
|
297
|
+
src = tmp_path / "dinner.cook"
|
|
298
|
+
src.write_text("Simmer @sauce for ~{90%minutes}.\n")
|
|
299
|
+
fake.supported_domains = []
|
|
300
|
+
r = CliRunner().invoke(
|
|
301
|
+
cli,
|
|
302
|
+
["import", str(src), "-i", "fake", "--review", "-o", str(tmp_path / "d.json")],
|
|
303
|
+
)
|
|
304
|
+
assert r.exit_code == 0, r.output
|
|
305
|
+
assert seen["tool"] == "review_program"
|
|
306
|
+
assert seen["args"]["token"] == "tok-1"
|
|
307
|
+
assert seen["args"]["program"]["programId"] == "fake-dinner"
|
|
308
|
+
assert seen["args"]["source_text"].startswith("Simmer @sauce")
|
|
309
|
+
assert (
|
|
310
|
+
"One problem." in r.output
|
|
311
|
+
and "✗ [s1] Too short." in r.output
|
|
312
|
+
and "→ 90m" in r.output
|
|
313
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/gold.py
RENAMED
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/eval/llm.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/remote/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/src/rhylthyme_cli_runner/render_cli.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_example_validation.py
RENAMED
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_examples_integration.py
RENAMED
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_expand_replicates.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_planner_time_strings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_validate_examples_ci.py
RENAMED
|
File without changes
|
{rhylthyme_cli_runner-0.2.6a0 → rhylthyme_cli_runner-0.2.7a0}/tests/test_validate_program.py
RENAMED
|
File without changes
|