newmeasure-cli 0.2.1__tar.gz → 0.3.0__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.
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/PKG-INFO +26 -2
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/README.md +25 -1
- newmeasure_cli-0.3.0/cli/commands/edit_task.py +73 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/main.py +18 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/pyproject.toml +1 -1
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/.gitignore +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/__init__.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/api_client.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/__init__.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/admin.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/artifacts.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/login.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/result.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/run.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/runs.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/tasks.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/commands/upload.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/config.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/errors.py +0 -0
- {newmeasure_cli-0.2.1 → newmeasure_cli-0.3.0}/cli/progress.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: newmeasure-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: NewMeasure eval CLI
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: httpx>=0.28
|
|
@@ -16,7 +16,7 @@ Description-Content-Type: text/markdown
|
|
|
16
16
|
|
|
17
17
|
*Upload eval tasks, start cloud runs, and download results with `newm`*
|
|
18
18
|
|
|
19
|
-
[Install](#install) • [Usage](#usage) • [Browser tasks](#browser-tasks) • [Commands](#commands) • [Development](#development)
|
|
19
|
+
[Install](#install) • [Usage](#usage) • [Browser tasks](#browser-tasks) • [Edit tasks](#edit-tasks) • [Commands](#commands) • [Development](#development)
|
|
20
20
|
|
|
21
21
|
</div>
|
|
22
22
|
|
|
@@ -120,6 +120,28 @@ Downloads include `outputs/` (the files the product generated, such as PDF and H
|
|
|
120
120
|
|
|
121
121
|
A browser task bundle contains `task.toml`, `instruction.md`, and, when present, `scenario.yaml`, `product.md` (or `../../shared/product.md`), and the `environment/` and `tests/` folders.
|
|
122
122
|
|
|
123
|
+
## Edit tasks
|
|
124
|
+
|
|
125
|
+
Turn a Solstice edit session into an Edit-suite task in the app. This uses the personal CLI token
|
|
126
|
+
from `newm login --evals`. Pass the session's `operation_id` or its asset URL
|
|
127
|
+
(`https://<tenant>.solstice.co/home/assets/<operation_id>`):
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# List the operation's turns, with their surface, whether starting HTML is ready, and the request
|
|
131
|
+
newm edit-task 0b7f2a7e-1111-4222-8333-444455556666
|
|
132
|
+
|
|
133
|
+
# Create a task from turn 2 (a turn number or turn ID)
|
|
134
|
+
newm edit-task 0b7f2a7e-1111-4222-8333-444455556666 --turn 2
|
|
135
|
+
|
|
136
|
+
# Merge consecutive turns into one task, with your own title
|
|
137
|
+
newm edit-task https://acme.solstice.co/home/assets/0b7f2a7e-1111-4222-8333-444455556666 \
|
|
138
|
+
-t 2 -t 3 --title "Swap headline and CTA"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The task's checks and title are drafted from the chosen turns; refine them in the app's Edits tab.
|
|
142
|
+
Turns listed as `awaiting` have no starting HTML yet: the task is created, but stays
|
|
143
|
+
`awaiting_html` until the HTML is imported.
|
|
144
|
+
|
|
123
145
|
## Commands
|
|
124
146
|
|
|
125
147
|
```bash
|
|
@@ -130,6 +152,8 @@ newm result <run-id> # run details and trial results
|
|
|
130
152
|
newm artifacts <run-id> <trial-id> [--output DIR]
|
|
131
153
|
newm tasks # list uploaded tasks
|
|
132
154
|
newm runs [<task-id>] # list runs
|
|
155
|
+
newm edit-task <operation> [-t <turn> ...] # list turns or create an edit task
|
|
156
|
+
newm logins # list saved logins
|
|
133
157
|
newm harbor ... # pass through to the Harbor CLI
|
|
134
158
|
newm --help
|
|
135
159
|
```
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
*Upload eval tasks, start cloud runs, and download results with `newm`*
|
|
7
7
|
|
|
8
|
-
[Install](#install) • [Usage](#usage) • [Browser tasks](#browser-tasks) • [Commands](#commands) • [Development](#development)
|
|
8
|
+
[Install](#install) • [Usage](#usage) • [Browser tasks](#browser-tasks) • [Edit tasks](#edit-tasks) • [Commands](#commands) • [Development](#development)
|
|
9
9
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
@@ -109,6 +109,28 @@ Downloads include `outputs/` (the files the product generated, such as PDF and H
|
|
|
109
109
|
|
|
110
110
|
A browser task bundle contains `task.toml`, `instruction.md`, and, when present, `scenario.yaml`, `product.md` (or `../../shared/product.md`), and the `environment/` and `tests/` folders.
|
|
111
111
|
|
|
112
|
+
## Edit tasks
|
|
113
|
+
|
|
114
|
+
Turn a Solstice edit session into an Edit-suite task in the app. This uses the personal CLI token
|
|
115
|
+
from `newm login --evals`. Pass the session's `operation_id` or its asset URL
|
|
116
|
+
(`https://<tenant>.solstice.co/home/assets/<operation_id>`):
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# List the operation's turns, with their surface, whether starting HTML is ready, and the request
|
|
120
|
+
newm edit-task 0b7f2a7e-1111-4222-8333-444455556666
|
|
121
|
+
|
|
122
|
+
# Create a task from turn 2 (a turn number or turn ID)
|
|
123
|
+
newm edit-task 0b7f2a7e-1111-4222-8333-444455556666 --turn 2
|
|
124
|
+
|
|
125
|
+
# Merge consecutive turns into one task, with your own title
|
|
126
|
+
newm edit-task https://acme.solstice.co/home/assets/0b7f2a7e-1111-4222-8333-444455556666 \
|
|
127
|
+
-t 2 -t 3 --title "Swap headline and CTA"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The task's checks and title are drafted from the chosen turns; refine them in the app's Edits tab.
|
|
131
|
+
Turns listed as `awaiting` have no starting HTML yet: the task is created, but stays
|
|
132
|
+
`awaiting_html` until the HTML is imported.
|
|
133
|
+
|
|
112
134
|
## Commands
|
|
113
135
|
|
|
114
136
|
```bash
|
|
@@ -119,6 +141,8 @@ newm result <run-id> # run details and trial results
|
|
|
119
141
|
newm artifacts <run-id> <trial-id> [--output DIR]
|
|
120
142
|
newm tasks # list uploaded tasks
|
|
121
143
|
newm runs [<task-id>] # list runs
|
|
144
|
+
newm edit-task <operation> [-t <turn> ...] # list turns or create an edit task
|
|
145
|
+
newm logins # list saved logins
|
|
122
146
|
newm harbor ... # pass through to the Harbor CLI
|
|
123
147
|
newm --help
|
|
124
148
|
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.table import Table
|
|
8
|
+
|
|
9
|
+
from cli.api_client import evals_client
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _turn_ids(turns: list[dict], picks: list[str]) -> list[str]:
|
|
15
|
+
"""Map 1-based turn numbers to turn IDs; pass turn IDs through."""
|
|
16
|
+
by_seq = {str(t["seq"]): t["turn_id"] for t in turns}
|
|
17
|
+
known = {t["turn_id"] for t in turns}
|
|
18
|
+
out = []
|
|
19
|
+
for pick in picks:
|
|
20
|
+
tid = by_seq.get(pick, pick)
|
|
21
|
+
if tid not in known:
|
|
22
|
+
raise typer.BadParameter(
|
|
23
|
+
f"Turn {pick!r} is not in this operation; run without --turn to list turns"
|
|
24
|
+
)
|
|
25
|
+
out.append(tid)
|
|
26
|
+
return out
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _show_turns(inspected: dict) -> None:
|
|
30
|
+
console.print(
|
|
31
|
+
f"Operation {inspected['operation_id']} {inspected.get('brand_label') or ''}"
|
|
32
|
+
f" {inspected.get('kind') or ''}"
|
|
33
|
+
)
|
|
34
|
+
table = Table()
|
|
35
|
+
for col in ("#", "Turn ID", "Surface", "HTML", "Request"):
|
|
36
|
+
table.add_column(col)
|
|
37
|
+
for t in inspected["turns"]:
|
|
38
|
+
request = " ".join((t.get("user_request") or "").split())
|
|
39
|
+
table.add_row(
|
|
40
|
+
str(t["seq"]),
|
|
41
|
+
t["turn_id"],
|
|
42
|
+
t.get("surface") or "",
|
|
43
|
+
("ready" if t.get("html_ready") else "awaiting")
|
|
44
|
+
+ (" (reverted)" if t.get("reverted") else ""),
|
|
45
|
+
request[:80] + ("…" if len(request) > 80 else ""),
|
|
46
|
+
)
|
|
47
|
+
console.print(table)
|
|
48
|
+
for task in inspected.get("existing_tasks") or []:
|
|
49
|
+
console.print(
|
|
50
|
+
f"Existing task {task['id']}: {task['title']} (turns {', '.join(task['turn_ids'])})"
|
|
51
|
+
)
|
|
52
|
+
console.print("Create a task with: newm edit-task <operation> --turn <#>")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def edit_task(operation: str, turns: list[str], title: str) -> None:
|
|
56
|
+
"""List an operation's turns, or create an edit task from the chosen turns."""
|
|
57
|
+
with evals_client() as c:
|
|
58
|
+
r = c.post("edit-tasks/inspect", json={"operation": operation})
|
|
59
|
+
r.raise_for_status()
|
|
60
|
+
inspected = r.json()
|
|
61
|
+
if not turns:
|
|
62
|
+
_show_turns(inspected)
|
|
63
|
+
return
|
|
64
|
+
r = c.post(
|
|
65
|
+
"edit-tasks",
|
|
66
|
+
json={
|
|
67
|
+
"operation": inspected["operation_id"],
|
|
68
|
+
"turn_ids": _turn_ids(inspected["turns"], turns),
|
|
69
|
+
"title": title,
|
|
70
|
+
},
|
|
71
|
+
)
|
|
72
|
+
r.raise_for_status()
|
|
73
|
+
typer.echo(json.dumps(r.json(), indent=1))
|
|
@@ -9,6 +9,7 @@ import typer
|
|
|
9
9
|
|
|
10
10
|
from cli.commands.admin import admin_app
|
|
11
11
|
from cli.commands.artifacts import artifacts as artifacts_cmd
|
|
12
|
+
from cli.commands.edit_task import edit_task as edit_task_cmd
|
|
12
13
|
from cli.commands.login import login as login_cmd
|
|
13
14
|
from cli.commands.result import result as result_cmd
|
|
14
15
|
from cli.commands.run import run as run_cmd
|
|
@@ -130,6 +131,23 @@ def result(run_id: str = typer.Argument(..., help="Run ID")):
|
|
|
130
131
|
result_cmd(run_id)
|
|
131
132
|
|
|
132
133
|
|
|
134
|
+
@app.command("edit-task")
|
|
135
|
+
def edit_task(
|
|
136
|
+
operation: str = typer.Argument(
|
|
137
|
+
..., help="Solstice operation ID or /home/assets/<id> URL"
|
|
138
|
+
),
|
|
139
|
+
turn: list[str] = typer.Option(
|
|
140
|
+
[],
|
|
141
|
+
"--turn",
|
|
142
|
+
"-t",
|
|
143
|
+
help="Turn number or turn ID to convert; repeat to merge turns. Omit to list turns",
|
|
144
|
+
),
|
|
145
|
+
title: str = typer.Option("", "--title", help="Task title (default: drafted)"),
|
|
146
|
+
):
|
|
147
|
+
"""Create an Edit-suite task from a Solstice operation."""
|
|
148
|
+
edit_task_cmd(operation, turn, title)
|
|
149
|
+
|
|
150
|
+
|
|
133
151
|
@app.command(
|
|
134
152
|
context_settings={"allow_extra_args": True, "ignore_unknown_options": True},
|
|
135
153
|
)
|
|
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
|