@root-signals/scorable-cli 0.1.3 → 0.2.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.
Files changed (73) hide show
  1. package/README.md +94 -13
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/commands/evaluator/create.d.ts +3 -0
  4. package/dist/commands/evaluator/create.d.ts.map +1 -0
  5. package/dist/commands/evaluator/create.js +62 -0
  6. package/dist/commands/evaluator/delete.d.ts +3 -0
  7. package/dist/commands/evaluator/delete.d.ts.map +1 -0
  8. package/dist/commands/evaluator/delete.js +34 -0
  9. package/dist/commands/evaluator/duplicate.d.ts +3 -0
  10. package/dist/commands/evaluator/duplicate.d.ts.map +1 -0
  11. package/dist/commands/evaluator/duplicate.js +20 -0
  12. package/dist/commands/evaluator/execute-by-name.d.ts +17 -0
  13. package/dist/commands/evaluator/execute-by-name.d.ts.map +1 -0
  14. package/dist/commands/evaluator/execute-by-name.js +131 -0
  15. package/dist/commands/evaluator/execute.d.ts +17 -0
  16. package/dist/commands/evaluator/execute.d.ts.map +1 -0
  17. package/dist/commands/evaluator/execute.js +135 -0
  18. package/dist/commands/evaluator/get.d.ts +3 -0
  19. package/dist/commands/evaluator/get.d.ts.map +1 -0
  20. package/dist/commands/evaluator/get.js +20 -0
  21. package/dist/commands/evaluator/index.d.ts +3 -0
  22. package/dist/commands/evaluator/index.d.ts.map +1 -0
  23. package/dist/commands/evaluator/index.js +21 -0
  24. package/dist/commands/evaluator/list.d.ts +3 -0
  25. package/dist/commands/evaluator/list.d.ts.map +1 -0
  26. package/dist/commands/evaluator/list.js +39 -0
  27. package/dist/commands/evaluator/update.d.ts +3 -0
  28. package/dist/commands/evaluator/update.d.ts.map +1 -0
  29. package/dist/commands/evaluator/update.js +51 -0
  30. package/dist/commands/execution-log/get.d.ts +3 -0
  31. package/dist/commands/execution-log/get.d.ts.map +1 -0
  32. package/dist/commands/execution-log/get.js +19 -0
  33. package/dist/commands/execution-log/index.d.ts +3 -0
  34. package/dist/commands/execution-log/index.d.ts.map +1 -0
  35. package/dist/commands/execution-log/index.js +9 -0
  36. package/dist/commands/execution-log/list.d.ts +3 -0
  37. package/dist/commands/execution-log/list.d.ts.map +1 -0
  38. package/dist/commands/execution-log/list.js +60 -0
  39. package/dist/commands/judge/create.d.ts.map +1 -1
  40. package/dist/commands/judge/create.js +2 -5
  41. package/dist/commands/judge/delete.d.ts.map +1 -1
  42. package/dist/commands/judge/delete.js +5 -4
  43. package/dist/commands/judge/duplicate.d.ts.map +1 -1
  44. package/dist/commands/judge/duplicate.js +2 -5
  45. package/dist/commands/judge/exec-openai-generic.d.ts.map +1 -1
  46. package/dist/commands/judge/exec-openai-generic.js +2 -5
  47. package/dist/commands/judge/exec-openai.d.ts.map +1 -1
  48. package/dist/commands/judge/exec-openai.js +2 -5
  49. package/dist/commands/judge/execute-by-name.d.ts +1 -0
  50. package/dist/commands/judge/execute-by-name.d.ts.map +1 -1
  51. package/dist/commands/judge/execute-by-name.js +54 -16
  52. package/dist/commands/judge/execute.d.ts +1 -0
  53. package/dist/commands/judge/execute.d.ts.map +1 -1
  54. package/dist/commands/judge/execute.js +61 -16
  55. package/dist/commands/judge/get.d.ts.map +1 -1
  56. package/dist/commands/judge/get.js +2 -5
  57. package/dist/commands/judge/list.d.ts.map +1 -1
  58. package/dist/commands/judge/list.js +15 -34
  59. package/dist/commands/judge/update.d.ts.map +1 -1
  60. package/dist/commands/judge/update.js +2 -5
  61. package/dist/commands/prompt-test/run.d.ts.map +1 -1
  62. package/dist/commands/prompt-test/run.js +5 -6
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +4 -0
  65. package/dist/output.d.ts +4 -1
  66. package/dist/output.d.ts.map +1 -1
  67. package/dist/output.js +47 -4
  68. package/dist/types.d.ts +0 -15
  69. package/dist/types.d.ts.map +1 -1
  70. package/dist/utils.d.ts +5 -0
  71. package/dist/utils.d.ts.map +1 -0
  72. package/dist/utils.js +18 -0
  73. package/package.json +1 -3
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
  </a>
25
25
  </p>
26
26
 
27
- The `scorable` CLI is a command-line tool for interacting with the Scorable API. It lets you manage and execute Judges and run prompt testing experiments directly from the terminal.
27
+ The `scorable` CLI is a command-line tool for interacting with the Scorable API. It lets you manage and execute Judges and Evaluators, view execution logs, and run prompt testing experiments directly from the terminal.
28
28
 
29
29
  Requires **Node.js 20 or higher**.
30
30
 
@@ -68,7 +68,7 @@ If no API key is set, the CLI will offer to create a temporary key interactively
68
68
  scorable judge list
69
69
  ```
70
70
 
71
- Options: `--page-size`, `--cursor`, `--search`, `--name`, `--ordering`, `--is-preset / --not-is-preset`, `--is-public / --not-is-public`, `--show-global / --not-show-global`
71
+ Options: `--page-size`, `--cursor`, `--search`, `--name`, `--ordering`
72
72
 
73
73
  ### Get a judge
74
74
 
@@ -114,37 +114,118 @@ scorable judge duplicate <judge_id>
114
114
  scorable judge execute <judge_id> --request "What is the capital of France?" --response "Paris"
115
115
  ```
116
116
 
117
- Options: `--request`, `--response`, `--contexts` (JSON list), `--expected-output`, `--tag` (repeatable), `--user-id`, `--session-id`, `--system-prompt`
117
+ Options: `--request`, `--response`, `--turns` (JSON array of conversation turns), `--contexts` (JSON list), `--expected-output`, `--tag` (repeatable), `--user-id`, `--session-id`, `--system-prompt`
118
118
 
119
- Pipe input via stdin:
119
+ Pipe a response via stdin:
120
120
 
121
121
  ```bash
122
122
  echo "Paris" | scorable judge execute <judge_id> --request "What is the capital of France?"
123
123
  cat response.txt | scorable judge execute <judge_id>
124
124
  ```
125
125
 
126
+ For multi-turn conversations, pass the full history as a JSON array:
127
+
128
+ ```bash
129
+ scorable judge execute <judge_id> --turns '[{"role":"user","content":"Hi"},{"role":"assistant","content":"Hello!"}]'
130
+ ```
131
+
126
132
  ### Execute by name
127
133
 
128
134
  ```bash
129
135
  scorable judge execute-by-name "My Judge" --request "What is the capital of France?" --response "Paris"
130
136
  ```
131
137
 
132
- Accepts the same options as `execute`. Stdin piping works the same way.
138
+ Accepts the same options as `execute`. Stdin piping and `--turns` work the same way.
139
+
140
+ ## Evaluator Management
141
+
142
+ ### List evaluators
143
+
144
+ ```bash
145
+ scorable evaluator list
146
+ ```
147
+
148
+ Options: `--page-size`, `--cursor`, `--search`, `--name`, `--ordering`
149
+
150
+ ### Get an evaluator
151
+
152
+ ```bash
153
+ scorable evaluator get <evaluator_id>
154
+ ```
155
+
156
+ ### Create an evaluator
157
+
158
+ ```bash
159
+ scorable evaluator create \
160
+ --name "My Evaluator" \
161
+ --scoring-criteria "Does the {{ response }} directly answer the user's question?" \
162
+ --intent "Evaluate response relevance"
163
+ ```
164
+
165
+ Options: `--name` (required), `--scoring-criteria` (required — must contain `{{ request }}` and/or `{{ response }}`), `--intent` or `--objective-id` (one required), `--system-message`, `--models` (JSON array), `--overwrite`, `--objective-version-id`
166
+
167
+ ### Update an evaluator
168
+
169
+ ```bash
170
+ scorable evaluator update <evaluator_id> --name "Updated Name"
171
+ ```
172
+
173
+ Options: `--name`, `--scoring-criteria`, `--system-message`, `--models` (JSON array), `--objective-id`, `--objective-version-id`
174
+
175
+ ### Delete an evaluator
176
+
177
+ ```bash
178
+ scorable evaluator delete <evaluator_id>
179
+ ```
180
+
181
+ Prompts for confirmation. Use `--yes` to skip.
182
+
183
+ ### Duplicate an evaluator
184
+
185
+ ```bash
186
+ scorable evaluator duplicate <evaluator_id>
187
+ ```
188
+
189
+ ## Evaluator Execution
133
190
 
134
- ### Execute via OpenAI-compatible API
191
+ ### Execute by ID
135
192
 
136
193
  ```bash
137
- scorable judge exec-openai <judge_id> \
138
- --model gpt-4o \
139
- --messages '[{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there"}]'
194
+ scorable evaluator execute <evaluator_id> --request "What is 2+2?" --response "4"
140
195
  ```
141
196
 
142
- Generic variant (judge ID in the `model` field):
197
+ Options: `--request`, `--response`, `--turns` (JSON array of conversation turns), `--contexts` (JSON list), `--expected-output`, `--tag` (repeatable), `--user-id`, `--session-id`, `--system-prompt`, `--variables` (JSON object of extra template variables)
198
+
199
+ Stdin piping and `--turns` work the same way as for judge execution.
200
+
201
+ For evaluators with custom template placeholders beyond `{{request}}`/`{{response}}`:
202
+
203
+ ```bash
204
+ scorable evaluator execute <evaluator_id> --request "Hello" --variables '{"lang":"EN","topic":"science"}'
205
+ ```
206
+
207
+ ### Execute by name
208
+
209
+ ```bash
210
+ scorable evaluator execute-by-name "My Evaluator" --request "What is 2+2?" --response "4"
211
+ ```
212
+
213
+ Accepts the same options as `execute`, including `--variables`.
214
+
215
+ ## Execution Logs
216
+
217
+ ### List execution logs
218
+
219
+ ```bash
220
+ scorable execution-log list
221
+ ```
222
+
223
+ Options: `--page-size`, `--cursor`, `--search`, `--evaluator-id`, `--judge-id`, `--model`, `--tags`, `--score-min`, `--score-max`, `--created-at-after`, `--created-at-before`, `--owner-email`
224
+
225
+ ### Get an execution log
143
226
 
144
227
  ```bash
145
- scorable judge exec-openai-generic \
146
- --model <judge_id_or_name> \
147
- --messages '[{"role": "user", "content": "Hello"}, {"role": "assistant", "content": "Hi there"}]'
228
+ scorable execution-log get <log_id>
148
229
  ```
149
230
 
150
231
  ## Prompt Testing
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAMA,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,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;CAClB,GACA,OAAO,CAAC,OAAO,CAAC,CAoDlB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAQA,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,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;CAClB,GACA,OAAO,CAAC,OAAO,CAAC,CAoDlB"}
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerCreateCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=create.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAkF9D"}
@@ -0,0 +1,62 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, printError, printJson, handleSdkError } from "../../output.js";
3
+ export function registerCreateCommand(evaluator) {
4
+ evaluator
5
+ .command("create")
6
+ .description("Create a new evaluator")
7
+ .requiredOption("--name <name>", "The name for the new evaluator")
8
+ .requiredOption("--scoring-criteria <text>", "The scoring criteria prompt. Must contain {{ request }} and/or {{ response }} as placeholders.")
9
+ .option("--intent <intent>", "The intent for the evaluator (mutually exclusive with --objective-id)")
10
+ .option("--objective-id <id>", "Objective ID (mutually exclusive with --intent)")
11
+ .option("--system-message <text>", "System message for the evaluator")
12
+ .option("--models <json>", "JSON array of model names, in priority order. E.g., '[\"gpt-5-mini\"]'")
13
+ .option("--overwrite", "Overwrite if evaluator with same name exists")
14
+ .option("--objective-version-id <id>", "Objective version ID")
15
+ .action(async (opts) => {
16
+ if (!opts.intent && !opts.objectiveId) {
17
+ printError("Either --intent or --objective-id is required.");
18
+ return;
19
+ }
20
+ if (!/\{\{\s*request\s*\}\}/.test(opts.scoringCriteria) &&
21
+ !/\{\{\s*response\s*\}\}/.test(opts.scoringCriteria)) {
22
+ printError("The --scoring-criteria must contain at least one of {{ request }} or {{ response }} as a placeholder.\n" +
23
+ 'Example: "Does the {{ response }} directly answer the user\'s question?"');
24
+ return;
25
+ }
26
+ const payload = {
27
+ name: opts.name,
28
+ predicate: opts.scoringCriteria,
29
+ };
30
+ if (opts.intent)
31
+ payload.intent = opts.intent;
32
+ if (opts.objectiveId)
33
+ payload.objective_id = opts.objectiveId;
34
+ if (opts.systemMessage)
35
+ payload.system_message = opts.systemMessage;
36
+ if (opts.overwrite !== undefined)
37
+ payload.overwrite = opts.overwrite;
38
+ if (opts.objectiveVersionId)
39
+ payload.objective_version_id = opts.objectiveVersionId;
40
+ if (opts.models) {
41
+ try {
42
+ payload.models = JSON.parse(opts.models);
43
+ }
44
+ catch {
45
+ printError("Invalid JSON format for --models.");
46
+ return;
47
+ }
48
+ }
49
+ printInfo("Attempting to create evaluator with payload:");
50
+ printJson(payload);
51
+ try {
52
+ const apiKey = await requireApiKey();
53
+ const client = getSdkClient(apiKey);
54
+ const result = await client.evaluators.create(payload);
55
+ printSuccess("Evaluator created successfully!");
56
+ printJson(result);
57
+ }
58
+ catch (e) {
59
+ handleSdkError(e);
60
+ }
61
+ });
62
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerDeleteCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAmC9D"}
@@ -0,0 +1,34 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, handleSdkError } from "../../output.js";
3
+ import { CliError } from "../../types.js";
4
+ export function registerDeleteCommand(evaluator) {
5
+ evaluator
6
+ .command("delete <evaluatorId>")
7
+ .description("Delete an evaluator by its ID")
8
+ .option("--yes", "Skip confirmation prompt")
9
+ .action(async (evaluatorId, opts) => {
10
+ const apiKey = await requireApiKey();
11
+ if (!opts.yes) {
12
+ if (!process.stdin.isTTY && !process.stdout.isTTY) {
13
+ throw new CliError(1, "Refusing to prompt for confirmation in a non-interactive environment. Pass --yes to skip the prompt.");
14
+ }
15
+ const { confirm } = await import("@inquirer/prompts");
16
+ const ok = await confirm({
17
+ message: "Are you sure you want to delete this evaluator?",
18
+ default: false,
19
+ });
20
+ if (!ok) {
21
+ throw new CliError(1, "Aborted");
22
+ }
23
+ }
24
+ printInfo(`Deleting evaluator ${evaluatorId}...`);
25
+ try {
26
+ const client = getSdkClient(apiKey);
27
+ await client.evaluators.delete(evaluatorId);
28
+ printSuccess(`Evaluator ${evaluatorId} deleted successfully.`);
29
+ }
30
+ catch (e) {
31
+ handleSdkError(e);
32
+ }
33
+ });
34
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerDuplicateCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=duplicate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/duplicate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAiBjE"}
@@ -0,0 +1,20 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, printJson, handleSdkError } from "../../output.js";
3
+ export function registerDuplicateCommand(evaluator) {
4
+ evaluator
5
+ .command("duplicate <evaluatorId>")
6
+ .description("Duplicate an existing evaluator")
7
+ .action(async (evaluatorId) => {
8
+ const apiKey = await requireApiKey();
9
+ printInfo(`Duplicating evaluator ID: ${evaluatorId}...`);
10
+ try {
11
+ const client = getSdkClient(apiKey);
12
+ const result = await client.evaluators.duplicate(evaluatorId);
13
+ printSuccess(`Evaluator ${evaluatorId} duplicated successfully!`);
14
+ printJson(result);
15
+ }
16
+ catch (e) {
17
+ handleSdkError(e);
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,17 @@
1
+ import { Command } from "commander";
2
+ declare function readStdinDefault(): Promise<string>;
3
+ export declare function executeEvaluatorByName(evaluatorName: string, opts: {
4
+ request?: string;
5
+ response?: string;
6
+ turns?: string;
7
+ contexts?: string;
8
+ expectedOutput?: string;
9
+ tag?: string[];
10
+ userId?: string;
11
+ sessionId?: string;
12
+ systemPrompt?: string;
13
+ variables?: string;
14
+ }, readStdin?: typeof readStdinDefault): Promise<void>;
15
+ export declare function registerExecuteByNameCommand(evaluator: Command): void;
16
+ export {};
17
+ //# sourceMappingURL=execute-by-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute-by-name.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/execute-by-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,iBAAe,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAIjD;AAED,wBAAsB,sBAAsB,CAC1C,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,EACD,SAAS,0BAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAuEf;AAED,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CA4ErE"}
@@ -0,0 +1,131 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, printError, printJson, handleSdkError } from "../../output.js";
3
+ import { isTurnArray, isStringArray, isStringRecord } from "../../utils.js";
4
+ async function readStdinDefault() {
5
+ const chunks = [];
6
+ for await (const chunk of process.stdin)
7
+ chunks.push(chunk);
8
+ return Buffer.concat(chunks).toString().trim();
9
+ }
10
+ export async function executeEvaluatorByName(evaluatorName, opts, readStdin = readStdinDefault) {
11
+ const apiKey = await requireApiKey();
12
+ let response = opts.response;
13
+ if (!opts.request && !response && !opts.turns && !process.stdin.isTTY) {
14
+ response = await readStdin();
15
+ }
16
+ if (!opts.request && !response && !opts.turns) {
17
+ printError("Either --request, --response, or --turns must be provided.");
18
+ return;
19
+ }
20
+ const payload = {};
21
+ if (opts.request)
22
+ payload.request = opts.request;
23
+ if (response)
24
+ payload.response = response;
25
+ if (opts.expectedOutput)
26
+ payload.expected_output = opts.expectedOutput;
27
+ if (opts.tag?.length)
28
+ payload.tags = opts.tag;
29
+ if (opts.userId)
30
+ payload.user_id = opts.userId;
31
+ if (opts.sessionId)
32
+ payload.session_id = opts.sessionId;
33
+ if (opts.systemPrompt)
34
+ payload.system_prompt = opts.systemPrompt;
35
+ if (opts.turns) {
36
+ try {
37
+ const parsed = JSON.parse(opts.turns);
38
+ if (!isTurnArray(parsed)) {
39
+ printError("Invalid JSON for --turns.");
40
+ return;
41
+ }
42
+ payload.turns = parsed;
43
+ }
44
+ catch {
45
+ printError("Invalid JSON for --turns.");
46
+ return;
47
+ }
48
+ }
49
+ if (opts.contexts) {
50
+ try {
51
+ const parsed = JSON.parse(opts.contexts);
52
+ if (!isStringArray(parsed)) {
53
+ printError("Invalid JSON for --contexts. Skipping.");
54
+ return;
55
+ }
56
+ payload.contexts = parsed;
57
+ }
58
+ catch {
59
+ printError("Invalid JSON for --contexts. Skipping.");
60
+ return;
61
+ }
62
+ }
63
+ if (opts.variables) {
64
+ try {
65
+ const parsed = JSON.parse(opts.variables);
66
+ if (!isStringRecord(parsed)) {
67
+ printError("Invalid JSON for --variables.");
68
+ return;
69
+ }
70
+ payload.variables = parsed;
71
+ }
72
+ catch {
73
+ printError("Invalid JSON for --variables.");
74
+ return;
75
+ }
76
+ }
77
+ printInfo(`Attempting to execute evaluator '${evaluatorName}' with payload:`);
78
+ printJson(payload);
79
+ const client = getSdkClient(apiKey);
80
+ const result = await client.evaluators.executeByName(evaluatorName, payload);
81
+ printSuccess("Evaluator execution by name successful!");
82
+ printJson(result);
83
+ }
84
+ export function registerExecuteByNameCommand(evaluator) {
85
+ evaluator
86
+ .command("execute-by-name <evaluatorName>")
87
+ .description("Execute an evaluator by name with interaction details")
88
+ .option("--request <text>", "Request text")
89
+ .option("--response <text>", "Response text to evaluate")
90
+ .option("--contexts <json>", "JSON list of context strings. E.g., '[\"ctx1\"]'")
91
+ .option("--expected-output <text>", "Expected output text")
92
+ .option("--tag <tag>", "Add one or more tags", (v, a) => [...a, v], [])
93
+ .option("--user-id <id>", "User identifier for tracking purposes")
94
+ .option("--session-id <id>", "Session identifier for tracking purposes")
95
+ .option("--system-prompt <text>", "System prompt that was used for the LLM call")
96
+ .option("--turns <json>", 'JSON array of conversation turns. E.g., \'[{"role":"user","content":"Hello"}]\'')
97
+ .option("--variables <json>", 'JSON object of extra template variables. E.g., \'{"lang":"EN"}\'')
98
+ .addHelpText("after", `
99
+ Examples:
100
+ # Check helpfulness of a support response
101
+ $ scorable evaluator execute-by-name "Helpfulness" \\
102
+ --request "Where can I find the application instructions?" \\
103
+ --response "You can find the instructions from our Careers page."
104
+
105
+ # Network troubleshooting accuracy check
106
+ $ scorable evaluator execute-by-name "Network Troubleshooting" \\
107
+ --request "My internet is not working." \\
108
+ --response "Let's check the basics. Ensure the Ethernet cable is securely connected, then run \`ping 8.8.8.8\` and share the results."
109
+
110
+ # Faithfulness against retrieved context
111
+ $ scorable evaluator execute-by-name "Faithfulness" \\
112
+ --request "What is your return policy for electronics?" \\
113
+ --response "You can return electronics within 30 days, unused and in original packaging." \\
114
+ --contexts '["Returns for electronics: 30 days, unused, original packaging, valid receipt required."]'
115
+
116
+ # Multi-turn conversation
117
+ $ scorable evaluator execute-by-name "Helpfulness" \\
118
+ --turns '[{"role":"user","content":"Hello, I need help with my order"},{"role":"assistant","content":"I\\'d be happy to help! What\\'s your order number?"},{"role":"user","content":"It\\'s ORDER-12345"}]'
119
+
120
+ # Pipe a response from your app via stdin
121
+ $ ./my-app respond "Do you offer refunds?" | \\
122
+ scorable evaluator execute-by-name "Helpfulness" --request "Do you offer refunds?"`)
123
+ .action(async (evaluatorName, opts) => {
124
+ try {
125
+ await executeEvaluatorByName(evaluatorName, opts);
126
+ }
127
+ catch (e) {
128
+ handleSdkError(e);
129
+ }
130
+ });
131
+ }
@@ -0,0 +1,17 @@
1
+ import { Command } from "commander";
2
+ declare function readStdinDefault(): Promise<string>;
3
+ export declare function executeEvaluator(evaluatorId: string, opts: {
4
+ request?: string;
5
+ response?: string;
6
+ turns?: string;
7
+ contexts?: string;
8
+ expectedOutput?: string;
9
+ tag?: string[];
10
+ userId?: string;
11
+ sessionId?: string;
12
+ systemPrompt?: string;
13
+ variables?: string;
14
+ }, readStdin?: typeof readStdinDefault): Promise<void>;
15
+ export declare function registerExecuteCommand(evaluator: Command): void;
16
+ export {};
17
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/execute.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,iBAAe,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC,CAIjD;AAED,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE;IACJ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,EACD,SAAS,0BAAmB,GAC3B,OAAO,CAAC,IAAI,CAAC,CAuEf;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAgF/D"}
@@ -0,0 +1,135 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, printError, printJson, handleSdkError } from "../../output.js";
3
+ import { isTurnArray, isStringArray, isStringRecord } from "../../utils.js";
4
+ async function readStdinDefault() {
5
+ const chunks = [];
6
+ for await (const chunk of process.stdin)
7
+ chunks.push(chunk);
8
+ return Buffer.concat(chunks).toString().trim();
9
+ }
10
+ export async function executeEvaluator(evaluatorId, opts, readStdin = readStdinDefault) {
11
+ const apiKey = await requireApiKey();
12
+ let response = opts.response;
13
+ if (!opts.request && !response && !opts.turns && !process.stdin.isTTY) {
14
+ response = await readStdin();
15
+ }
16
+ if (!opts.request && !response && !opts.turns) {
17
+ printError("Either --request, --response, or --turns must be provided.");
18
+ return;
19
+ }
20
+ const payload = {};
21
+ if (opts.request)
22
+ payload.request = opts.request;
23
+ if (response)
24
+ payload.response = response;
25
+ if (opts.expectedOutput)
26
+ payload.expected_output = opts.expectedOutput;
27
+ if (opts.tag?.length)
28
+ payload.tags = opts.tag;
29
+ if (opts.userId)
30
+ payload.user_id = opts.userId;
31
+ if (opts.sessionId)
32
+ payload.session_id = opts.sessionId;
33
+ if (opts.systemPrompt)
34
+ payload.system_prompt = opts.systemPrompt;
35
+ if (opts.turns) {
36
+ try {
37
+ const parsed = JSON.parse(opts.turns);
38
+ if (!isTurnArray(parsed)) {
39
+ printError("Invalid JSON for --turns.");
40
+ return;
41
+ }
42
+ payload.turns = parsed;
43
+ }
44
+ catch {
45
+ printError("Invalid JSON for --turns.");
46
+ return;
47
+ }
48
+ }
49
+ if (opts.contexts) {
50
+ try {
51
+ const parsed = JSON.parse(opts.contexts);
52
+ if (!isStringArray(parsed)) {
53
+ printError("Invalid JSON for --contexts. Skipping.");
54
+ return;
55
+ }
56
+ payload.contexts = parsed;
57
+ }
58
+ catch {
59
+ printError("Invalid JSON for --contexts. Skipping.");
60
+ return;
61
+ }
62
+ }
63
+ if (opts.variables) {
64
+ try {
65
+ const parsed = JSON.parse(opts.variables);
66
+ if (!isStringRecord(parsed)) {
67
+ printError("Invalid JSON for --variables.");
68
+ return;
69
+ }
70
+ payload.variables = parsed;
71
+ }
72
+ catch {
73
+ printError("Invalid JSON for --variables.");
74
+ return;
75
+ }
76
+ }
77
+ printInfo(`Attempting to execute evaluator ${evaluatorId} with payload:`);
78
+ printJson(payload);
79
+ const client = getSdkClient(apiKey);
80
+ const result = await client.evaluators.execute(evaluatorId, payload);
81
+ printSuccess("Evaluator execution successful!");
82
+ printJson(result);
83
+ }
84
+ export function registerExecuteCommand(evaluator) {
85
+ evaluator
86
+ .command("execute <evaluatorId>")
87
+ .description("Execute an evaluator with interaction details")
88
+ .option("--request <text>", "Request text")
89
+ .option("--response <text>", "Response text to evaluate")
90
+ .option("--contexts <json>", "JSON list of context strings. E.g., '[\"ctx1\"]'")
91
+ .option("--expected-output <text>", "Expected output text")
92
+ .option("--tag <tag>", "Add one or more tags", (v, a) => [...a, v], [])
93
+ .option("--user-id <id>", "User identifier for tracking purposes")
94
+ .option("--session-id <id>", "Session identifier for tracking purposes")
95
+ .option("--system-prompt <text>", "System prompt that was used for the LLM call")
96
+ .option("--turns <json>", 'JSON array of conversation turns. E.g., \'[{"role":"user","content":"Hello"}]\'')
97
+ .option("--variables <json>", 'JSON object of extra template variables. E.g., \'{"lang":"EN"}\'')
98
+ .addHelpText("after", `
99
+ Examples:
100
+ # Check helpfulness of a support response
101
+ $ scorable evaluator execute <evaluatorId> \\
102
+ --request "Where can I find the application instructions?" \\
103
+ --response "You can find the instructions from our Careers page."
104
+
105
+ # Evaluate network troubleshooting response
106
+ $ scorable evaluator execute <evaluatorId> \\
107
+ --request "My internet is not working." \\
108
+ --response "Let's check the basics. Ensure the Ethernet cable is securely connected, then run \`ping 8.8.8.8\` in a terminal and share the results."
109
+
110
+ # RAG faithfulness check with context documents
111
+ $ scorable evaluator execute <evaluatorId> \\
112
+ --request "Was the number of pensioners working above 100k in 2023?" \\
113
+ --response "Yes, 150,000 pensioners were working in 2023." \\
114
+ --expected-output "In 2023, 150k pensioners were still working." \\
115
+ --contexts '["More than 150,000 pensioners were employed in 2023, the centre\\'s statistics reveal."]'
116
+
117
+ # Multi-turn conversation evaluation
118
+ $ scorable evaluator execute <evaluatorId> \\
119
+ --turns '[{"role":"user","content":"Hello, I need help with my order"},{"role":"assistant","content":"I\\'d be happy to help! What\\'s your order number?"},{"role":"user","content":"It\\'s ORDER-12345"},{"role":"assistant","content":"I found your order. It\\'s currently in transit."}]'
120
+
121
+ # With custom template variables and tracking
122
+ $ scorable evaluator execute <evaluatorId> \\
123
+ --request "How do I cancel my subscription?" \\
124
+ --response "You can cancel anytime from account settings under billing." \\
125
+ --variables '{"topic":"subscription"}' \\
126
+ --user-id user_123 --session-id session_abc --tag production`)
127
+ .action(async (evaluatorId, opts) => {
128
+ try {
129
+ await executeEvaluator(evaluatorId, opts);
130
+ }
131
+ catch (e) {
132
+ handleSdkError(e);
133
+ }
134
+ });
135
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerGetCommand(evaluator: Command): void;
3
+ //# sourceMappingURL=get.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAiB3D"}
@@ -0,0 +1,20 @@
1
+ import { requireApiKey, getSdkClient } from "../../auth.js";
2
+ import { printInfo, printSuccess, printJson, handleSdkError } from "../../output.js";
3
+ export function registerGetCommand(evaluator) {
4
+ evaluator
5
+ .command("get <evaluatorId>")
6
+ .description("Get a specific evaluator by its ID")
7
+ .action(async (evaluatorId) => {
8
+ const apiKey = await requireApiKey();
9
+ printInfo(`Fetching evaluator with ID: ${evaluatorId}...`);
10
+ try {
11
+ const client = getSdkClient(apiKey);
12
+ const result = await client.evaluators.get(evaluatorId);
13
+ printSuccess(`Evaluator '${result.name}' details:`);
14
+ printJson(result);
15
+ }
16
+ catch (e) {
17
+ handleSdkError(e);
18
+ }
19
+ });
20
+ }
@@ -0,0 +1,3 @@
1
+ import { Command } from "commander";
2
+ export declare function registerEvaluatorCommands(program: Command): void;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/evaluator/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAahE"}