@root-signals/scorable-cli 0.13.0 → 0.15.0
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.
- package/README.md +113 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1 -0
- package/dist/commands/annotation/index.d.ts +3 -0
- package/dist/commands/annotation/index.d.ts.map +1 -0
- package/dist/commands/annotation/index.js +145 -0
- package/dist/commands/auth/index.d.ts.map +1 -1
- package/dist/commands/auth/index.js +68 -1
- package/dist/commands/calibration-run/index.d.ts +3 -0
- package/dist/commands/calibration-run/index.d.ts.map +1 -0
- package/dist/commands/calibration-run/index.js +83 -0
- package/dist/commands/dataset-item/index.d.ts +3 -0
- package/dist/commands/dataset-item/index.d.ts.map +1 -0
- package/dist/commands/dataset-item/index.js +160 -0
- package/dist/commands/evaluator/calibrate.d.ts +3 -0
- package/dist/commands/evaluator/calibrate.d.ts.map +1 -0
- package/dist/commands/evaluator/calibrate.js +29 -0
- package/dist/commands/evaluator/create.d.ts.map +1 -1
- package/dist/commands/evaluator/create.js +8 -0
- package/dist/commands/evaluator/duplicate.d.ts.map +1 -1
- package/dist/commands/evaluator/duplicate.js +5 -2
- package/dist/commands/evaluator/execute-by-name.d.ts +1 -0
- package/dist/commands/evaluator/execute-by-name.d.ts.map +1 -1
- package/dist/commands/evaluator/execute-by-name.js +5 -0
- package/dist/commands/evaluator/execute.d.ts +1 -0
- package/dist/commands/evaluator/execute.d.ts.map +1 -1
- package/dist/commands/evaluator/execute.js +5 -0
- package/dist/commands/evaluator/export-yaml.d.ts.map +1 -1
- package/dist/commands/evaluator/export-yaml.js +10 -1
- package/dist/commands/evaluator/import-yaml.d.ts.map +1 -1
- package/dist/commands/evaluator/import-yaml.js +10 -1
- package/dist/commands/evaluator/index.d.ts.map +1 -1
- package/dist/commands/evaluator/index.js +2 -0
- package/dist/commands/evaluator/list.d.ts.map +1 -1
- package/dist/commands/evaluator/list.js +5 -0
- package/dist/commands/evaluator/update.d.ts.map +1 -1
- package/dist/commands/evaluator/update.js +8 -0
- package/dist/commands/execution-log/list.d.ts.map +1 -1
- package/dist/commands/execution-log/list.js +5 -0
- package/dist/commands/judge/create.d.ts.map +1 -1
- package/dist/commands/judge/create.js +5 -0
- package/dist/commands/judge/duplicate.d.ts.map +1 -1
- package/dist/commands/judge/duplicate.js +5 -2
- package/dist/commands/judge/exec-openai-generic.d.ts.map +1 -1
- package/dist/commands/judge/exec-openai-generic.js +5 -0
- package/dist/commands/judge/exec-openai.d.ts.map +1 -1
- package/dist/commands/judge/exec-openai.js +5 -0
- package/dist/commands/judge/execute-by-name.d.ts +1 -0
- package/dist/commands/judge/execute-by-name.d.ts.map +1 -1
- package/dist/commands/judge/execute-by-name.js +5 -0
- package/dist/commands/judge/execute.d.ts +1 -0
- package/dist/commands/judge/execute.d.ts.map +1 -1
- package/dist/commands/judge/execute.js +5 -0
- package/dist/commands/judge/generate.d.ts.map +1 -1
- package/dist/commands/judge/generate.js +4 -0
- package/dist/commands/judge/list.d.ts.map +1 -1
- package/dist/commands/judge/list.js +5 -0
- package/dist/commands/judge/update.d.ts.map +1 -1
- package/dist/commands/judge/update.js +5 -0
- package/dist/commands/project/create.d.ts +3 -0
- package/dist/commands/project/create.d.ts.map +1 -0
- package/dist/commands/project/create.js +31 -0
- package/dist/commands/project/delete.d.ts +3 -0
- package/dist/commands/project/delete.d.ts.map +1 -0
- package/dist/commands/project/delete.js +37 -0
- package/dist/commands/project/get.d.ts +3 -0
- package/dist/commands/project/get.d.ts.map +1 -0
- package/dist/commands/project/get.js +23 -0
- package/dist/commands/project/index.d.ts +3 -0
- package/dist/commands/project/index.d.ts.map +1 -0
- package/dist/commands/project/index.js +17 -0
- package/dist/commands/project/list.d.ts +3 -0
- package/dist/commands/project/list.d.ts.map +1 -0
- package/dist/commands/project/list.js +39 -0
- package/dist/commands/project/set-default.d.ts +3 -0
- package/dist/commands/project/set-default.d.ts.map +1 -0
- package/dist/commands/project/set-default.js +23 -0
- package/dist/commands/project/update.d.ts +3 -0
- package/dist/commands/project/update.d.ts.map +1 -0
- package/dist/commands/project/update.js +37 -0
- package/dist/commands/prompt-test/init.d.ts.map +1 -1
- package/dist/commands/prompt-test/init.js +9 -2
- package/dist/commands/prompt-test/run.d.ts +1 -1
- package/dist/commands/prompt-test/run.d.ts.map +1 -1
- package/dist/commands/prompt-test/run.js +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/lib/project-id.d.ts +9 -0
- package/dist/lib/project-id.d.ts.map +1 -0
- package/dist/lib/project-id.js +23 -0
- package/dist/output.d.ts +2 -1
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +71 -12
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -78,6 +78,66 @@ export SCORABLE_API_KEY="sk-your-api-key"
|
|
|
78
78
|
|
|
79
79
|
The key lookup order is: `SCORABLE_API_KEY` env var → `api_key` in `~/.scorable/settings.json` → `temporary_api_key` in `~/.scorable/settings.json`.
|
|
80
80
|
|
|
81
|
+
## Projects
|
|
82
|
+
|
|
83
|
+
A **project** is a workspace inside your organization that groups related judges, evaluators, datasets, and execution logs. Every resource belongs to a project; omitting the project at create/execute time files things under the org's default project.
|
|
84
|
+
|
|
85
|
+
### Manage projects
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
scorable project list # list all projects (default marked)
|
|
89
|
+
scorable project get <project_id> # show a single project
|
|
90
|
+
scorable project create --name "Production" # create a project
|
|
91
|
+
scorable project create --name "Production" --is-default
|
|
92
|
+
scorable project update <project_id> --name "Renamed"
|
|
93
|
+
scorable project update <project_id> --is-default # promote to default
|
|
94
|
+
scorable project set-default <project_id> # convenience for `update --is-default`
|
|
95
|
+
scorable project delete <project_id>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `--project-id` on every project-aware command
|
|
99
|
+
|
|
100
|
+
Every command that creates, executes, lists, or filters a project-scoped resource accepts `--project-id <uuid>`:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Filter list endpoints
|
|
104
|
+
scorable judge list --project-id <project_id>
|
|
105
|
+
scorable evaluator list --project-id <project_id>
|
|
106
|
+
scorable execution-log list --project-id <project_id>
|
|
107
|
+
|
|
108
|
+
# Route an execution log to a project
|
|
109
|
+
scorable judge execute <judge_id> --project-id <project_id>
|
|
110
|
+
scorable evaluator execute <evaluator_id> --project-id <project_id>
|
|
111
|
+
|
|
112
|
+
# Pin a resource to a project at creation
|
|
113
|
+
scorable judge create --name X --intent Y --project-id <project_id>
|
|
114
|
+
scorable evaluator import-yaml --file evaluator.yaml --project-id <project_id>
|
|
115
|
+
|
|
116
|
+
# Move a resource between projects
|
|
117
|
+
scorable judge update <judge_id> --project-id <other_project_id>
|
|
118
|
+
|
|
119
|
+
# OpenAI-compat (translated to X-Project-Id header)
|
|
120
|
+
scorable judge exec-openai <judge_id> --project-id <project_id>
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Setting a default project for your shell
|
|
124
|
+
|
|
125
|
+
To avoid passing `--project-id` on every command, set an env var or persist a per-machine default:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Environment variable (great for CI)
|
|
129
|
+
export SCORABLE_PROJECT_ID=<project_id>
|
|
130
|
+
|
|
131
|
+
# Persistent default written to ~/.scorable/settings.json
|
|
132
|
+
scorable auth set-project <project_id>
|
|
133
|
+
scorable auth show-project # see what's resolved and from where
|
|
134
|
+
scorable auth unset-project # remove the saved default
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Resolution order: `--project-id` flag → `SCORABLE_PROJECT_ID` env var → `project_id` in `~/.scorable/settings.json` → omitted (backend resolves to org default). Pass `--project-id ""` to explicitly opt out of an inherited default for a single invocation.
|
|
138
|
+
|
|
139
|
+
`scorable auth logout` clears the entire auth section of `~/.scorable/settings.json`, including the saved project_id.
|
|
140
|
+
|
|
81
141
|
## Scorable Skills for AI Coding Agents
|
|
82
142
|
|
|
83
143
|
Install Scorable skills into your project so your AI coding agent (Claude Code, Cursor, etc.) can integrate evaluators automatically:
|
|
@@ -276,6 +336,59 @@ scorable evaluator execute-by-name "My Evaluator" --request "What is 2+2?" --res
|
|
|
276
336
|
|
|
277
337
|
Accepts the same options as `execute`, including `--variables`.
|
|
278
338
|
|
|
339
|
+
## Labelling & Calibration
|
|
340
|
+
|
|
341
|
+
Build a labelled dataset, then calibrate a saved evaluator against it to measure how well it agrees with your expected scores.
|
|
342
|
+
|
|
343
|
+
### Dataset items
|
|
344
|
+
|
|
345
|
+
Populate a `test`-type dataset with request/response items.
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
scorable dataset-item add <dataset_id> --response "Paris" --request "Capital of France?"
|
|
349
|
+
scorable dataset-item add-bulk <dataset_id> --items '[{"response":"Paris","request":"Capital of France?"}]'
|
|
350
|
+
scorable dataset-item list <dataset_id> # latest-version items (with embedded annotations)
|
|
351
|
+
scorable dataset-item list <dataset_id> --include-archived
|
|
352
|
+
scorable dataset-item get <dataset_id> <item_id>
|
|
353
|
+
scorable dataset-item update <dataset_id> <item_id> --response "Paris, France"
|
|
354
|
+
scorable dataset-item archive <dataset_id> <item_id>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Annotations
|
|
358
|
+
|
|
359
|
+
Label a dataset item (or execution log) with an expected score. Omitting `--score-config-id` uses the global identity "Score" config, so a raw expected score can be set with just `--value`.
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
scorable annotation create --dataset-item-id <item_id> --value 0.9
|
|
363
|
+
scorable annotation create --dataset-item-id <item_id> --category "👍" --score-config-id <config_id>
|
|
364
|
+
scorable annotation list --dataset <dataset_id>
|
|
365
|
+
scorable annotation get <annotation_id>
|
|
366
|
+
scorable annotation update <annotation_id> --value 0.8
|
|
367
|
+
scorable annotation delete <annotation_id>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Calibration runs
|
|
371
|
+
|
|
372
|
+
Start a calibration run against a labelled dataset and read its per-example results (human vs. evaluator score, disagreement, and the request/response that was scored).
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
scorable evaluator calibrate <evaluator_id> --dataset-id <dataset_id>
|
|
376
|
+
# ...or the equivalent calibration-run command:
|
|
377
|
+
scorable calibration-run create --evaluator-id <evaluator_id> --dataset-id <dataset_id>
|
|
378
|
+
scorable calibration-run get <run_id> # poll for status + metrics
|
|
379
|
+
scorable calibration-run list --evaluator-id <evaluator_id>
|
|
380
|
+
scorable calibration-run items <run_id> # per-example results
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Demonstrations
|
|
384
|
+
|
|
385
|
+
Attach a labelled dataset as few-shot demonstrations on an evaluator.
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
scorable evaluator create --name "My Evaluator" ... --demonstration-dataset <dataset_id>
|
|
389
|
+
scorable evaluator update <evaluator_id> --demonstration-dataset <dataset_id>
|
|
390
|
+
```
|
|
391
|
+
|
|
279
392
|
## Custom Model Management
|
|
280
393
|
|
|
281
394
|
Bring your own LLM (BYO-LLM) — register a custom or self-hosted model, then reference it from evaluators and judges.
|
package/dist/client.d.ts
CHANGED
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,UAAU,cAAc;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;CACf;AAQD,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAqD3B;AAKD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC,CAGlB"}
|
package/dist/client.js
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/annotation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiKjE"}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
4
|
+
import { printSuccess, printError, printJson, handleSdkError } from "../../output.js";
|
|
5
|
+
export function registerAnnotationCommands(program) {
|
|
6
|
+
const annotation = new Command("annotation").description("Annotation (labelling) commands");
|
|
7
|
+
annotation
|
|
8
|
+
.command("create")
|
|
9
|
+
.description("Create an annotation on a dataset item or execution log")
|
|
10
|
+
.option("--dataset-item-id <id>", "Dataset item to annotate (mutually exclusive with --execution-log-id)")
|
|
11
|
+
.option("--execution-log-id <id>", "Execution log to annotate (mutually exclusive with --dataset-item-id)")
|
|
12
|
+
.option("--value <number>", "Score for continuous configs", parseFloat)
|
|
13
|
+
.option("--category <label>", "Label for binary/categorical configs")
|
|
14
|
+
.option("--rationale <text>", "Optional free-text justification")
|
|
15
|
+
.option("--status <status>", "draft or published (default published)")
|
|
16
|
+
.option("--score-config-id <id>", "Score config; defaults to the global identity 'Score' config")
|
|
17
|
+
.action(async (opts) => {
|
|
18
|
+
if (!opts.datasetItemId === !opts.executionLogId) {
|
|
19
|
+
printError("Exactly one of --dataset-item-id or --execution-log-id must be provided.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const payload = {};
|
|
23
|
+
if (opts.datasetItemId)
|
|
24
|
+
payload.datasetItemId = opts.datasetItemId;
|
|
25
|
+
if (opts.executionLogId)
|
|
26
|
+
payload.executionLogId = opts.executionLogId;
|
|
27
|
+
if (opts.value !== undefined)
|
|
28
|
+
payload.value = opts.value;
|
|
29
|
+
if (opts.category !== undefined)
|
|
30
|
+
payload.category = opts.category;
|
|
31
|
+
if (opts.rationale !== undefined)
|
|
32
|
+
payload.rationale = opts.rationale;
|
|
33
|
+
if (opts.status !== undefined)
|
|
34
|
+
payload.status = opts.status;
|
|
35
|
+
if (opts.scoreConfigId)
|
|
36
|
+
payload.scoreConfigId = opts.scoreConfigId;
|
|
37
|
+
const spinner = ora("Creating annotation...").start();
|
|
38
|
+
try {
|
|
39
|
+
const client = getSdkClient(await requireApiKey());
|
|
40
|
+
const result = await client.annotations.create(payload);
|
|
41
|
+
spinner.stop();
|
|
42
|
+
printSuccess("Annotation created!");
|
|
43
|
+
printJson(result);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
spinner.stop();
|
|
47
|
+
handleSdkError(e);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
annotation
|
|
51
|
+
.command("list")
|
|
52
|
+
.description("List annotations")
|
|
53
|
+
.option("--dataset <id>", "Filter by the dataset the annotated items belong to")
|
|
54
|
+
.option("--score-config <id>", "Filter by score config id")
|
|
55
|
+
.option("--status <status>", "Filter by draft or published")
|
|
56
|
+
.option("--dataset-item <id>", "Filter by dataset item id")
|
|
57
|
+
.option("--execution-log <id>", "Filter by execution log id")
|
|
58
|
+
.action(async (opts) => {
|
|
59
|
+
const params = {};
|
|
60
|
+
if (opts.dataset)
|
|
61
|
+
params.dataset = opts.dataset;
|
|
62
|
+
if (opts.scoreConfig)
|
|
63
|
+
params.score_config = opts.scoreConfig;
|
|
64
|
+
if (opts.status)
|
|
65
|
+
params.status = opts.status;
|
|
66
|
+
if (opts.datasetItem)
|
|
67
|
+
params.dataset_item = opts.datasetItem;
|
|
68
|
+
if (opts.executionLog)
|
|
69
|
+
params.execution_log = opts.executionLog;
|
|
70
|
+
const spinner = ora("Listing annotations...").start();
|
|
71
|
+
try {
|
|
72
|
+
const client = getSdkClient(await requireApiKey());
|
|
73
|
+
const result = await client.annotations.list(params);
|
|
74
|
+
spinner.stop();
|
|
75
|
+
printJson(result.results);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
spinner.stop();
|
|
79
|
+
handleSdkError(e);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
annotation
|
|
83
|
+
.command("get <id>")
|
|
84
|
+
.description("Get an annotation by ID")
|
|
85
|
+
.action(async (id) => {
|
|
86
|
+
const spinner = ora("Fetching annotation...").start();
|
|
87
|
+
try {
|
|
88
|
+
const client = getSdkClient(await requireApiKey());
|
|
89
|
+
const result = await client.annotations.get(id);
|
|
90
|
+
spinner.stop();
|
|
91
|
+
printJson(result);
|
|
92
|
+
}
|
|
93
|
+
catch (e) {
|
|
94
|
+
spinner.stop();
|
|
95
|
+
handleSdkError(e);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
annotation
|
|
99
|
+
.command("update <id>")
|
|
100
|
+
.description("Update an annotation (target is immutable)")
|
|
101
|
+
.option("--value <number>", "New score for continuous configs", parseFloat)
|
|
102
|
+
.option("--category <label>", "New label for binary/categorical configs")
|
|
103
|
+
.option("--rationale <text>", "New rationale")
|
|
104
|
+
.option("--status <status>", "draft or published")
|
|
105
|
+
.action(async (id, opts) => {
|
|
106
|
+
const payload = {};
|
|
107
|
+
if (opts.value !== undefined)
|
|
108
|
+
payload.value = opts.value;
|
|
109
|
+
if (opts.category !== undefined)
|
|
110
|
+
payload.category = opts.category;
|
|
111
|
+
if (opts.rationale !== undefined)
|
|
112
|
+
payload.rationale = opts.rationale;
|
|
113
|
+
if (opts.status !== undefined)
|
|
114
|
+
payload.status = opts.status;
|
|
115
|
+
const spinner = ora("Updating annotation...").start();
|
|
116
|
+
try {
|
|
117
|
+
const client = getSdkClient(await requireApiKey());
|
|
118
|
+
const result = await client.annotations.update(id, payload);
|
|
119
|
+
spinner.stop();
|
|
120
|
+
printSuccess("Annotation updated!");
|
|
121
|
+
printJson(result);
|
|
122
|
+
}
|
|
123
|
+
catch (e) {
|
|
124
|
+
spinner.stop();
|
|
125
|
+
handleSdkError(e);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
annotation
|
|
129
|
+
.command("delete <id>")
|
|
130
|
+
.description("Delete an annotation")
|
|
131
|
+
.action(async (id) => {
|
|
132
|
+
const spinner = ora("Deleting annotation...").start();
|
|
133
|
+
try {
|
|
134
|
+
const client = getSdkClient(await requireApiKey());
|
|
135
|
+
await client.annotations.delete(id);
|
|
136
|
+
spinner.stop();
|
|
137
|
+
printSuccess(`Annotation ${id} deleted.`);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
spinner.stop();
|
|
141
|
+
handleSdkError(e);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
program.addCommand(annotation);
|
|
145
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/auth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsI3D"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import ora from "ora";
|
|
2
2
|
import { loadSettings, saveSettings, createDemoKey } from "../../auth.js";
|
|
3
|
-
import { printSuccess, printError } from "../../output.js";
|
|
3
|
+
import { printSuccess, printError, printInfo, printMessage } from "../../output.js";
|
|
4
|
+
import { resolveProjectId } from "../../lib/project-id.js";
|
|
4
5
|
import { CliError } from "../../types.js";
|
|
6
|
+
const AUTH_SETTINGS_KEYS = ["api_key", "temporary_api_key", "project_id"];
|
|
5
7
|
export function registerAuthCommands(program) {
|
|
6
8
|
const auth = program.command("auth").description("Manage authentication");
|
|
7
9
|
auth
|
|
@@ -39,6 +41,71 @@ export function registerAuthCommands(program) {
|
|
|
39
41
|
}
|
|
40
42
|
printSuccess("API key saved to ~/.scorable/settings.json");
|
|
41
43
|
});
|
|
44
|
+
auth
|
|
45
|
+
.command("set-project <projectId>")
|
|
46
|
+
.description("Persist a project_id to ~/.scorable/settings.json")
|
|
47
|
+
.action((projectId) => {
|
|
48
|
+
if (!projectId.trim()) {
|
|
49
|
+
printError("Project ID must not be empty.");
|
|
50
|
+
throw new CliError(1, "Empty project id");
|
|
51
|
+
}
|
|
52
|
+
const settings = loadSettings();
|
|
53
|
+
settings["project_id"] = projectId.trim();
|
|
54
|
+
if (!saveSettings(settings)) {
|
|
55
|
+
printError("Failed to save project_id to ~/.scorable/settings.json");
|
|
56
|
+
throw new CliError(1, "Failed to save project_id");
|
|
57
|
+
}
|
|
58
|
+
printSuccess(`project_id saved to ~/.scorable/settings.json`);
|
|
59
|
+
});
|
|
60
|
+
auth
|
|
61
|
+
.command("unset-project")
|
|
62
|
+
.description("Remove the persisted project_id from ~/.scorable/settings.json")
|
|
63
|
+
.action(() => {
|
|
64
|
+
const settings = loadSettings();
|
|
65
|
+
if (!("project_id" in settings)) {
|
|
66
|
+
printInfo("No project_id was set.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
delete settings["project_id"];
|
|
70
|
+
if (!saveSettings(settings)) {
|
|
71
|
+
printError("Failed to update ~/.scorable/settings.json");
|
|
72
|
+
throw new CliError(1, "Failed to update settings");
|
|
73
|
+
}
|
|
74
|
+
printSuccess("project_id removed from ~/.scorable/settings.json");
|
|
75
|
+
});
|
|
76
|
+
auth
|
|
77
|
+
.command("show-project")
|
|
78
|
+
.description("Print the resolved project_id and its source (flag/env/settings/none)")
|
|
79
|
+
.action(() => {
|
|
80
|
+
const resolved = resolveProjectId(undefined);
|
|
81
|
+
if (resolved.value === undefined) {
|
|
82
|
+
printMessage("project_id: <none> (source: none)");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
printMessage(`project_id: ${resolved.value} (source: ${resolved.source})`);
|
|
86
|
+
});
|
|
87
|
+
auth
|
|
88
|
+
.command("logout")
|
|
89
|
+
.description("Clear the auth section of ~/.scorable/settings.json (api keys + project_id)")
|
|
90
|
+
.action(() => {
|
|
91
|
+
const settings = loadSettings();
|
|
92
|
+
let touched = false;
|
|
93
|
+
for (const k of AUTH_SETTINGS_KEYS) {
|
|
94
|
+
if (k in settings) {
|
|
95
|
+
delete settings[k];
|
|
96
|
+
touched = true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (!touched) {
|
|
100
|
+
printInfo("Already logged out.");
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!saveSettings(settings)) {
|
|
104
|
+
printError("Failed to update ~/.scorable/settings.json");
|
|
105
|
+
throw new CliError(1, "Failed to update settings");
|
|
106
|
+
}
|
|
107
|
+
printSuccess("Logged out — cleared api_key, temporary_api_key, and project_id.");
|
|
108
|
+
});
|
|
42
109
|
auth
|
|
43
110
|
.command("demo-key")
|
|
44
111
|
.description("Create a free demo API key and save it to ~/.scorable/settings.json")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/calibration-run/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAiFrE"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
4
|
+
import { printSuccess, printJson, handleSdkError } from "../../output.js";
|
|
5
|
+
export function registerCalibrationRunCommands(program) {
|
|
6
|
+
const run = new Command("calibration-run").description("Calibration run commands");
|
|
7
|
+
run
|
|
8
|
+
.command("create")
|
|
9
|
+
.description("Start a calibration run against a labelled dataset")
|
|
10
|
+
.requiredOption("--evaluator-id <id>", "The saved evaluator to calibrate")
|
|
11
|
+
.requiredOption("--dataset-id <id>", "Dataset whose published annotations to calibrate against")
|
|
12
|
+
.option("--score-config-id <id>", "Score config (defaults to the dataset's continuous scores)")
|
|
13
|
+
.action(async (opts) => {
|
|
14
|
+
const payload = {
|
|
15
|
+
evaluatorId: opts.evaluatorId,
|
|
16
|
+
datasetId: opts.datasetId,
|
|
17
|
+
};
|
|
18
|
+
if (opts.scoreConfigId)
|
|
19
|
+
payload.scoreConfigId = opts.scoreConfigId;
|
|
20
|
+
const spinner = ora("Starting calibration run...").start();
|
|
21
|
+
try {
|
|
22
|
+
const client = getSdkClient(await requireApiKey());
|
|
23
|
+
const result = await client.calibrationRuns.create(payload);
|
|
24
|
+
spinner.stop();
|
|
25
|
+
printSuccess(`Calibration run ${result.id} started (status: ${result.status}).`);
|
|
26
|
+
printJson(result);
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
spinner.stop();
|
|
30
|
+
handleSdkError(e);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
run
|
|
34
|
+
.command("get <id>")
|
|
35
|
+
.description("Get a calibration run (poll for status and metrics)")
|
|
36
|
+
.action(async (id) => {
|
|
37
|
+
const spinner = ora("Fetching calibration run...").start();
|
|
38
|
+
try {
|
|
39
|
+
const client = getSdkClient(await requireApiKey());
|
|
40
|
+
const result = await client.calibrationRuns.get(id);
|
|
41
|
+
spinner.stop();
|
|
42
|
+
printJson(result);
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
spinner.stop();
|
|
46
|
+
handleSdkError(e);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
run
|
|
50
|
+
.command("list")
|
|
51
|
+
.description("List calibration runs")
|
|
52
|
+
.option("--evaluator-id <id>", "Filter by evaluator external id")
|
|
53
|
+
.action(async (opts) => {
|
|
54
|
+
const spinner = ora("Listing calibration runs...").start();
|
|
55
|
+
try {
|
|
56
|
+
const client = getSdkClient(await requireApiKey());
|
|
57
|
+
const result = await client.calibrationRuns.list(opts.evaluatorId ? { evaluatorId: opts.evaluatorId } : {});
|
|
58
|
+
spinner.stop();
|
|
59
|
+
printJson(result.results);
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
spinner.stop();
|
|
63
|
+
handleSdkError(e);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
run
|
|
67
|
+
.command("items <id>")
|
|
68
|
+
.description("List the per-example results of a calibration run")
|
|
69
|
+
.action(async (id) => {
|
|
70
|
+
const spinner = ora("Fetching calibration run items...").start();
|
|
71
|
+
try {
|
|
72
|
+
const client = getSdkClient(await requireApiKey());
|
|
73
|
+
const result = await client.calibrationRuns.listItems(id);
|
|
74
|
+
spinner.stop();
|
|
75
|
+
printJson(result.results);
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
spinner.stop();
|
|
79
|
+
handleSdkError(e);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
program.addCommand(run);
|
|
83
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dataset-item/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA4KlE"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import ora from "ora";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { requireApiKey, getSdkClient } from "../../auth.js";
|
|
5
|
+
import { printSuccess, printError, printJson, handleSdkError } from "../../output.js";
|
|
6
|
+
import { parseJsonArg } from "../../utils.js";
|
|
7
|
+
export function registerDatasetItemCommands(program) {
|
|
8
|
+
const item = new Command("dataset-item").description("Dataset item commands");
|
|
9
|
+
item
|
|
10
|
+
.command("add <datasetId>")
|
|
11
|
+
.description("Add a single item to a dataset")
|
|
12
|
+
.requiredOption("--response <text>", "The response text")
|
|
13
|
+
.option("--request <text>", "The request/prompt text")
|
|
14
|
+
.option("--expected-output <text>", "The expected output")
|
|
15
|
+
.option("--metadata <json>", "Metadata JSON object")
|
|
16
|
+
.option("--change-note <text>", "Change note for this version")
|
|
17
|
+
.action(async (datasetId, opts) => {
|
|
18
|
+
const body = { response: opts.response };
|
|
19
|
+
if (opts.request !== undefined)
|
|
20
|
+
body.request = opts.request;
|
|
21
|
+
if (opts.expectedOutput !== undefined)
|
|
22
|
+
body.expected_output = opts.expectedOutput;
|
|
23
|
+
if (opts.changeNote !== undefined)
|
|
24
|
+
body.change_note = opts.changeNote;
|
|
25
|
+
if (opts.metadata !== undefined) {
|
|
26
|
+
const r = parseJsonArg(opts.metadata, z.record(z.string(), z.unknown()));
|
|
27
|
+
if (!r.ok) {
|
|
28
|
+
printError("Invalid JSON for --metadata. Expected an object.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
body.metadata = r.value;
|
|
32
|
+
}
|
|
33
|
+
const spinner = ora("Adding item...").start();
|
|
34
|
+
try {
|
|
35
|
+
const client = getSdkClient(await requireApiKey());
|
|
36
|
+
const result = await client.datasets.addItem(datasetId, body);
|
|
37
|
+
spinner.stop();
|
|
38
|
+
printSuccess("Dataset item added!");
|
|
39
|
+
printJson(result);
|
|
40
|
+
}
|
|
41
|
+
catch (e) {
|
|
42
|
+
spinner.stop();
|
|
43
|
+
handleSdkError(e);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
item
|
|
47
|
+
.command("add-bulk <datasetId>")
|
|
48
|
+
.description("Bulk add items to a dataset (at most 5000)")
|
|
49
|
+
.requiredOption("--items <json>", "JSON array of item objects")
|
|
50
|
+
.action(async (datasetId, opts) => {
|
|
51
|
+
const r = parseJsonArg(opts.items, z.array(z.record(z.string(), z.unknown())));
|
|
52
|
+
if (!r.ok) {
|
|
53
|
+
printError("Invalid JSON for --items. Expected an array of item objects.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const spinner = ora("Bulk adding items...").start();
|
|
57
|
+
try {
|
|
58
|
+
const client = getSdkClient(await requireApiKey());
|
|
59
|
+
const result = await client.datasets.addItems(datasetId, r.value);
|
|
60
|
+
spinner.stop();
|
|
61
|
+
printSuccess(`Added ${result.length} dataset items.`);
|
|
62
|
+
printJson(result);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
spinner.stop();
|
|
66
|
+
handleSdkError(e);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
item
|
|
70
|
+
.command("list <datasetId>")
|
|
71
|
+
.description("List the latest-version items of a dataset (with embedded annotations)")
|
|
72
|
+
.option("--include-archived", "Include archived items", false)
|
|
73
|
+
.action(async (datasetId, opts) => {
|
|
74
|
+
const spinner = ora("Listing items...").start();
|
|
75
|
+
try {
|
|
76
|
+
const client = getSdkClient(await requireApiKey());
|
|
77
|
+
const result = await client.datasets.listItems(datasetId, {
|
|
78
|
+
includeArchived: opts.includeArchived ?? false,
|
|
79
|
+
});
|
|
80
|
+
spinner.stop();
|
|
81
|
+
printJson(result.results);
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
spinner.stop();
|
|
85
|
+
handleSdkError(e);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
item
|
|
89
|
+
.command("get <datasetId> <itemId>")
|
|
90
|
+
.description("Get a single dataset item")
|
|
91
|
+
.action(async (datasetId, itemId) => {
|
|
92
|
+
const spinner = ora("Fetching item...").start();
|
|
93
|
+
try {
|
|
94
|
+
const client = getSdkClient(await requireApiKey());
|
|
95
|
+
const result = await client.datasets.getItem(datasetId, itemId);
|
|
96
|
+
spinner.stop();
|
|
97
|
+
printJson(result);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
spinner.stop();
|
|
101
|
+
handleSdkError(e);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
item
|
|
105
|
+
.command("update <datasetId> <itemId>")
|
|
106
|
+
.description("Edit a dataset item (creates a new version)")
|
|
107
|
+
.option("--response <text>", "The response text")
|
|
108
|
+
.option("--request <text>", "The request/prompt text")
|
|
109
|
+
.option("--expected-output <text>", "The expected output")
|
|
110
|
+
.option("--metadata <json>", "Metadata JSON object")
|
|
111
|
+
.option("--change-note <text>", "Change note for this version")
|
|
112
|
+
.action(async (datasetId, itemId, opts) => {
|
|
113
|
+
const body = {};
|
|
114
|
+
if (opts.response !== undefined)
|
|
115
|
+
body.response = opts.response;
|
|
116
|
+
if (opts.request !== undefined)
|
|
117
|
+
body.request = opts.request;
|
|
118
|
+
if (opts.expectedOutput !== undefined)
|
|
119
|
+
body.expected_output = opts.expectedOutput;
|
|
120
|
+
if (opts.changeNote !== undefined)
|
|
121
|
+
body.change_note = opts.changeNote;
|
|
122
|
+
if (opts.metadata !== undefined) {
|
|
123
|
+
const r = parseJsonArg(opts.metadata, z.record(z.string(), z.unknown()));
|
|
124
|
+
if (!r.ok) {
|
|
125
|
+
printError("Invalid JSON for --metadata. Expected an object.");
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
body.metadata = r.value;
|
|
129
|
+
}
|
|
130
|
+
const spinner = ora("Updating item...").start();
|
|
131
|
+
try {
|
|
132
|
+
const client = getSdkClient(await requireApiKey());
|
|
133
|
+
const result = await client.datasets.updateItem(datasetId, itemId, body);
|
|
134
|
+
spinner.stop();
|
|
135
|
+
printSuccess("Dataset item updated!");
|
|
136
|
+
printJson(result);
|
|
137
|
+
}
|
|
138
|
+
catch (e) {
|
|
139
|
+
spinner.stop();
|
|
140
|
+
handleSdkError(e);
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
item
|
|
144
|
+
.command("archive <datasetId> <itemId>")
|
|
145
|
+
.description("Archive (soft-delete) a dataset item")
|
|
146
|
+
.action(async (datasetId, itemId) => {
|
|
147
|
+
const spinner = ora("Archiving item...").start();
|
|
148
|
+
try {
|
|
149
|
+
const client = getSdkClient(await requireApiKey());
|
|
150
|
+
await client.datasets.archiveItem(datasetId, itemId);
|
|
151
|
+
spinner.stop();
|
|
152
|
+
printSuccess(`Dataset item ${itemId} archived.`);
|
|
153
|
+
}
|
|
154
|
+
catch (e) {
|
|
155
|
+
spinner.stop();
|
|
156
|
+
handleSdkError(e);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
program.addCommand(item);
|
|
160
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calibrate.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/calibrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CA6BjE"}
|