orizu 0.3.4 → 0.3.5
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 +15 -0
- package/dist/index.js +192 -7
- package/dist/preview-runtime.js +857 -0
- package/package.json +10 -1
- package/src/index.ts +217 -8
- package/src/preview-runtime.ts +976 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +2 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +22 -56
- package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +31 -6
package/README.md
CHANGED
|
@@ -169,6 +169,21 @@ orizu logout
|
|
|
169
169
|
--output-schema ./schemas/support-output.json</code></pre>
|
|
170
170
|
</td>
|
|
171
171
|
</tr>
|
|
172
|
+
<tr>
|
|
173
|
+
<td>Preview an app locally</td>
|
|
174
|
+
<td>
|
|
175
|
+
<pre><code>orizu apps preview \
|
|
176
|
+
--file ./apps/SupportLabeler.tsx \
|
|
177
|
+
--input-schema ./schemas/support-input.json \
|
|
178
|
+
--output-schema ./schemas/support-output.json \
|
|
179
|
+
--sample-row ./fixtures/sample-row.json \
|
|
180
|
+
--screenshot ./preview.png</code></pre>
|
|
181
|
+
</td>
|
|
182
|
+
</tr>
|
|
183
|
+
<tr>
|
|
184
|
+
<td>Preview runtime</td>
|
|
185
|
+
<td>The CLI uses the live Orizu web checkout when it is nearby, otherwise it uses the bundled preview runtime snapshot shipped in this package.</td>
|
|
186
|
+
</tr>
|
|
172
187
|
<tr>
|
|
173
188
|
<td>Link a dataset to an app</td>
|
|
174
189
|
<td><code>orizu apps link-dataset --app <appId> --dataset <datasetId></code></td>
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { parseDatasetFile } from './file-parser.js';
|
|
|
14
14
|
import { streamJsonlRowChunks } from './jsonl-stream.js';
|
|
15
15
|
import { parseDatasetReference } from './dataset-download.js';
|
|
16
16
|
import { parseGlobalFlags } from './global-flags.js';
|
|
17
|
+
import { runLocalAppPreview } from './preview-runtime.js';
|
|
17
18
|
import { assertSecureTokenTransport, authedFetch, getBaseUrl, resolveLoginBaseUrl, setGlobalFlags, } from './http.js';
|
|
18
19
|
import { formatTaskCreateError } from './task-create-error.js';
|
|
19
20
|
const MAX_README_LENGTH = 200_000;
|
|
@@ -31,7 +32,11 @@ function printVersion() {
|
|
|
31
32
|
printLine(`orizu ${getCliVersion()}`);
|
|
32
33
|
}
|
|
33
34
|
function printUsage() {
|
|
34
|
-
printLine(`orizu global options:\n\n --local Use http://localhost:3000\n --server <url> Use a specific server origin (for example: https://preview.example.com)\n --version, -v Print the orizu CLI version\n\norizu commands:\n\n orizu login [--no-prompt-if-logged-in]\n orizu logout\n orizu whoami\n orizu env [--project <team/project>] [--project-id <projectId>]\n orizu log <event_type> --run-id <id> --sequence <n> --payload @event.json\n orizu teams list\n orizu teams create [--name <name>]\n orizu teams members list [--team <teamSlug>]\n orizu teams members add --email <email> [--team <teamSlug>]\n orizu teams members remove --email <email> [--team <teamSlug>]\n orizu teams members role --team <teamSlug> --email <email> --role <admin|member>\n orizu projects list [--team <teamSlug>]\n orizu projects create --name <name> [--team <teamSlug>]\n orizu prompts list --project <team/project>\n orizu prompts comments <prompt-id-or-name> --project <team/project> [--label <label> | --version <id>] [--json]\n orizu prompts pull <prompt-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <id>] [--json]\n orizu prompts push <dir> [--runner-version <id>] [--project <team/project>] [--parent <version-id>] [--json]\n orizu prompts labels set <prompt-name> <label> --version <version-id> [--project <team/project>] [--json]\n orizu prompts scorers set-headline <prompt-id> --scorer-version <id> [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu prompts scorers add <prompt-id> --scorer-version <id> [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu scorers list --project <team/project>\n orizu scorers register --project <team/project> --name <name> --manifest <manifest.json> [--prompt-version <id>] [--runner-version <id>] [--label <label>] [--json]\n orizu scorers detail <scorer-id-or-name> --project <team/project> [--json]\n orizu scorers labels set <scorer-name> <label> --version <scorer-version-id> [--project <team/project>] [--json]\n orizu scores submit <results.jsonl|results.json> --scorer-version <id> --subject-version <prompt-version-id> [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu judges list --project <team/project>\n orizu judges pull <judge-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <id>] [--json]\n orizu judges push <dir> [--runner-version <id>] [--project <team/project>] [--parent <version-id>] [--json]\n orizu runners push <dir> [--project <team/project>] [--name <name>] [--label <label>] [--json]\n orizu runners exec (--prompt <prompt-version-id> | --prompt-version <id> --runner-version <id> | --scorer-version <id>) --dataset-version <id> --split-set <id-or-name> --split <name> [--runner-dir <dir>] --out <results.jsonl|results.jsonl.gz>\n orizu optimizers push <dir> [--project <team/project>] [--name <name>] [--label <label>] [--json]\n orizu runs submit <results.jsonl|results.jsonl.gz> --prompt-version <id> --runner-version <id> --dataset-version <id> --split-set <id> --split <name> [--project <team/project>]\n orizu apps list [--project <team/project>]\n orizu apps create --project <team/project> --name <name> --dataset <datasetId> --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>]\n orizu apps update [--app <appId>] [--project <team/project>] --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>]\n orizu apps link-dataset --dataset <datasetId> [--app <appId>] [--project <team/project>] [--version <n>]\n orizu apps detail --app <appId> [--project <team/project>] [--json]\n orizu apps export [--app <appId>] [--project <team/project>] [--version <n>] [--out <path>]\n orizu tasks list [--project <team/project>]\n orizu tasks create --project <team/project> --dataset <datasetId> --app <appId> --title <title> --assignees <userIdOrEmail1,userIdOrEmail2> [--version <n>] [--instructions <text>] [--labels-per-item <n>] [--json]\n orizu tasks assign --task <taskId> --assignees <userId1,userId2>\n orizu tasks status --task <taskId> [--json]\n orizu tasks pause --task <taskId>\n orizu tasks unpause --task <taskId>\n orizu datasets upload --file <path> [--project <team/project>] [--name <name>] [--readme-file <README.md> | --readme-text <markdown>]\n orizu datasets push <path> [--project <team/project>] [--name <name>] [--readme-file <README.md> | --readme-text <markdown>] [--json]\n orizu datasets readme set <datasetId|dataset-name> [--project <team/project>] (--readme-file <README.md> | --readme-text <markdown>) [--json]\n orizu datasets versions create <datasetId|dataset-name> [--project <team/project>] [--label <label>] [--readme-file <README.md> | --readme-text <markdown>] [--json]\n orizu datasets splits create <datasetVersionId> [--from-file <split.json>] [--json]\n orizu datasets download [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--format <csv|json|jsonl>] [--out <path>]\n orizu datasets append [--dataset <datasetId|datasetUrl>] [--project <team/project>] --file <path>\n orizu datasets edit-rows [--dataset <datasetId|datasetUrl>] [--project <team/project>] --file <path>\n orizu datasets delete-rows [--dataset <datasetId|datasetUrl>] [--project <team/project>] --row-ids <id1,id2>\n orizu datasets delete [--dataset <datasetId|datasetUrl>] [--project <team/project>]\n orizu datasets lock [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--reason <text>]\n orizu datasets clone [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--name <name>]\n orizu tasks export [--task <taskId>] [--format <csv|json|jsonl>] [--out <path>]`);
|
|
35
|
+
printLine(`orizu global options:\n\n --local Use http://localhost:3000\n --server <url> Use a specific server origin (for example: https://preview.example.com)\n --version, -v Print the orizu CLI version\n\norizu commands:\n\n orizu login [--no-prompt-if-logged-in]\n orizu logout\n orizu whoami\n orizu env [--project <team/project>] [--project-id <projectId>]\n orizu log <event_type> --run-id <id> --sequence <n> --payload @event.json\n orizu teams list\n orizu teams create [--name <name>]\n orizu teams members list [--team <teamSlug>]\n orizu teams members add --email <email> [--team <teamSlug>]\n orizu teams members remove --email <email> [--team <teamSlug>]\n orizu teams members role --team <teamSlug> --email <email> --role <admin|member>\n orizu projects list [--team <teamSlug>]\n orizu projects create --name <name> [--team <teamSlug>]\n orizu prompts list --project <team/project>\n orizu prompts comments <prompt-id-or-name> --project <team/project> [--label <label> | --version <id>] [--json]\n orizu prompts pull <prompt-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <id>] [--json]\n orizu prompts push <dir> [--runner-version <id>] [--project <team/project>] [--parent <version-id>] [--json]\n orizu prompts labels set <prompt-name> <label> --version <version-id> [--project <team/project>] [--json]\n orizu prompts scorers set-headline <prompt-id> --scorer-version <id> [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu prompts scorers add <prompt-id> --scorer-version <id> [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu scorers list --project <team/project>\n orizu scorers register --project <team/project> --name <name> --manifest <manifest.json> [--prompt-version <id>] [--runner-version <id>] [--label <label>] [--json]\n orizu scorers detail <scorer-id-or-name> --project <team/project> [--json]\n orizu scorers labels set <scorer-name> <label> --version <scorer-version-id> [--project <team/project>] [--json]\n orizu scorers exec --scorer-version <id> (--subject-version <prompt-version-id> | --optimization-run <id> --candidate <id>) --dataset-version <id> --split-set <id> --split <name> [--subject-results <jsonl>] [--dependency-score-run <alias=id>] [--dependency-results <alias=path>] [--no-submit] [--out <score.json>] [--project <team/project>] [--json]\n orizu scores submit <results.jsonl|results.json> --scorer-version <id> (--subject-version <prompt-version-id> | --optimization-run <id> --candidate <id>) [--aggregate] [--dataset-version <id> --split-set <id> --split <name>] [--project <team/project>] [--json]\n orizu judges list --project <team/project>\n orizu judges pull <judge-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <id>] [--json]\n orizu judges push <dir> [--runner-version <id>] [--project <team/project>] [--parent <version-id>] [--json]\n orizu runners push <dir> [--project <team/project>] [--name <name>] [--label <label>] [--json]\n orizu runners exec (--prompt <prompt-version-id> | --prompt-version <id> --runner-version <id> | --scorer-version <id>) --dataset-version <id> --split-set <id-or-name> --split <name> [--runner-dir <dir>] --out <results.jsonl|results.jsonl.gz>\n orizu optimizers push <dir> [--project <team/project>] [--name <name>] [--label <label>] [--json]\n orizu runs submit <results.jsonl|results.jsonl.gz> --prompt-version <id> --runner-version <id> --dataset-version <id> --split-set <id> --split <name> [--project <team/project>]\n orizu apps list [--project <team/project>]\n orizu apps create --project <team/project> --name <name> --dataset <datasetId> --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>]\n orizu apps update [--app <appId>] [--project <team/project>] --file <path> --input-schema <json-path> --output-schema <json-path> [--component <name>]\n orizu apps link-dataset --dataset <datasetId> [--app <appId>] [--project <team/project>] [--version <n>]\n orizu apps detail --app <appId> [--project <team/project>] [--json]\n orizu apps export [--app <appId>] [--project <team/project>] [--version <n>] [--out <path>]\n orizu tasks list [--project <team/project>]\n orizu tasks create --project <team/project> --dataset <datasetId> --app <appId> --title <title> --assignees <userIdOrEmail1,userIdOrEmail2> [--version <n>] [--instructions <text>] [--labels-per-item <n>] [--json]\n orizu tasks assign --task <taskId> --assignees <userId1,userId2>\n orizu tasks status --task <taskId> [--json]\n orizu tasks pause --task <taskId>\n orizu tasks unpause --task <taskId>\n orizu datasets upload --file <path> [--project <team/project>] [--name <name>] [--readme-file <README.md> | --readme-text <markdown>]\n orizu datasets push <path> [--project <team/project>] [--name <name>] [--readme-file <README.md> | --readme-text <markdown>] [--json]\n orizu datasets readme set <datasetId|dataset-name> [--project <team/project>] (--readme-file <README.md> | --readme-text <markdown>) [--json]\n orizu datasets versions create <datasetId|dataset-name> [--project <team/project>] [--label <label>] [--readme-file <README.md> | --readme-text <markdown>] [--json]\n orizu datasets splits create <datasetVersionId> [--from-file <split.json>] [--json]\n orizu datasets download [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--format <csv|json|jsonl>] [--out <path>]\n orizu datasets append [--dataset <datasetId|datasetUrl>] [--project <team/project>] --file <path>\n orizu datasets edit-rows [--dataset <datasetId|datasetUrl>] [--project <team/project>] --file <path>\n orizu datasets delete-rows [--dataset <datasetId|datasetUrl>] [--project <team/project>] --row-ids <id1,id2>\n orizu datasets delete [--dataset <datasetId|datasetUrl>] [--project <team/project>]\n orizu datasets lock [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--reason <text>]\n orizu datasets clone [--dataset <datasetId|datasetUrl>] [--project <team/project>] [--name <name>]\n orizu tasks export [--task <taskId>] [--format <csv|json|jsonl>] [--out <path>]`);
|
|
36
|
+
printPreviewUsage();
|
|
37
|
+
}
|
|
38
|
+
function printPreviewUsage() {
|
|
39
|
+
printLine(`\nLocal app preview:\n\n orizu apps preview --file <path> --input-schema <json-path> --output-schema <json-path> --sample-row <json-path> [--screenshot <png-path>] [--headed] [--keep-open] [--component <name>]`);
|
|
35
40
|
}
|
|
36
41
|
function printOptimizationUsage() {
|
|
37
42
|
printLine(`\nOptimization lifecycle commands:\n\n orizu optimizations start --project <team/project> --optimizer-version <id> --prompt-version <id[,id]> --selection-scorer <id> [--reflection-scorer <id>] [--pareto-scorer <id>] [--best-scorer <id>] --dataset-version <id> --split-set <id> [--train-split <name>] [--validation-split <name>] [--metadata <json|@file>] [--json]\n orizu optimizations run-gepa --project <team/project> --optimizer-version-id <id> --candidate-version-id <id> --runner-version-id <id> --candidate-runner-dir <dir> --scorer-version-id <id> --scorer-runner-version-id <id> --scorer-runner-dir <dir> --dataset-version-id <id> --split-set-id <id> [--train-split train] [--val-split validation] [--log-dir logs]\n orizu optimizations export <run-id> [--out <path>] [--json]\n orizu optimizations pause <run-id> [--reason <text>] [--json]\n orizu optimizations resume <run-id> [--json]\n orizu optimizations finish <run-id> [--best-score <n>] [--best-candidate <id>] [--result-prompt-version <id>] [--report <markdown|@file> | --report-file <path>] [--metadata <json|@file>] [--json]\n orizu optimizations fail <run-id> [--reason <text>] [--report <markdown|@file> | --report-file <path>] [--metadata <json|@file>] [--json]\n orizu optimizations cancel <run-id> [--reason <text>] [--report <markdown|@file> | --report-file <path>] [--json]`);
|
|
@@ -1384,17 +1389,22 @@ async function submitScoreResults() {
|
|
|
1384
1389
|
const optimizationRunId = getArg('--optimization-run');
|
|
1385
1390
|
const candidateId = getArg('--candidate');
|
|
1386
1391
|
if (!resultsPath || !scorerVersionId || (!subjectPromptVersionId && (!optimizationRunId || !candidateId))) {
|
|
1387
|
-
throw new Error('Usage: orizu scores submit <results.jsonl|results.json> --project <team/project> --scorer-version <id> (--subject-version <prompt-version-id> | --optimization-run <id> --candidate <id>) [--dataset-version <id> --split-set <id> --split <name>] [--json]');
|
|
1392
|
+
throw new Error('Usage: orizu scores submit <results.jsonl|results.json> --project <team/project> --scorer-version <id> (--subject-version <prompt-version-id> | --optimization-run <id> --candidate <id>) [--aggregate] [--dataset-version <id> --split-set <id> --split <name>] [--json]');
|
|
1388
1393
|
}
|
|
1389
1394
|
const resultBytes = readSourceBytes(resultsPath);
|
|
1390
1395
|
const raw = resultsPath.endsWith('.gz')
|
|
1391
1396
|
? gunzipSync(resultBytes).toString('utf8')
|
|
1392
1397
|
: resultBytes.toString('utf8');
|
|
1393
|
-
const
|
|
1398
|
+
const scoreInput = normalizeScoreResultsInput(resultsPath, raw, hasArg('--aggregate'));
|
|
1399
|
+
if (scoreInput.aggregateWarning) {
|
|
1400
|
+
console.warn(scoreInput.aggregateWarning);
|
|
1401
|
+
}
|
|
1402
|
+
const aggregatePayload = scoreInput.aggregate || {};
|
|
1394
1403
|
const response = await authedFetch(`/api/cli/scores/submit?project=${encodeURIComponent(project)}`, {
|
|
1395
1404
|
method: 'POST',
|
|
1396
1405
|
headers: { 'Content-Type': 'application/json' },
|
|
1397
1406
|
body: JSON.stringify({
|
|
1407
|
+
...aggregatePayload,
|
|
1398
1408
|
scorerVersionId,
|
|
1399
1409
|
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
1400
1410
|
datasetVersionId: getArg('--dataset-version') || undefined,
|
|
@@ -1402,7 +1412,7 @@ async function submitScoreResults() {
|
|
|
1402
1412
|
splitName: getArg('--split') || undefined,
|
|
1403
1413
|
optimizationRunId: optimizationRunId || undefined,
|
|
1404
1414
|
candidateId: candidateId || undefined,
|
|
1405
|
-
resultsJsonl,
|
|
1415
|
+
resultsJsonl: scoreInput.resultsJsonl,
|
|
1406
1416
|
}),
|
|
1407
1417
|
});
|
|
1408
1418
|
if (!response.ok) {
|
|
@@ -1416,23 +1426,149 @@ async function submitScoreResults() {
|
|
|
1416
1426
|
printLine(`Submitted score ${sanitizeTerminalText(data.scoreRun.id)} ` +
|
|
1417
1427
|
`(${formatPercent(data.scoreRun.scoreValue)})`);
|
|
1418
1428
|
}
|
|
1419
|
-
function
|
|
1429
|
+
function looksLikeAggregateScoreObject(value) {
|
|
1430
|
+
return (value.scoreValue !== undefined ||
|
|
1431
|
+
value.score_value !== undefined ||
|
|
1432
|
+
value.diagnostics !== undefined ||
|
|
1433
|
+
value.feedbackSummary !== undefined ||
|
|
1434
|
+
value.feedback_summary !== undefined ||
|
|
1435
|
+
value.rowEvidence !== undefined ||
|
|
1436
|
+
value.row_evidence !== undefined ||
|
|
1437
|
+
value.dependencyScoreRunIds !== undefined ||
|
|
1438
|
+
value.dependency_score_run_ids !== undefined);
|
|
1439
|
+
}
|
|
1440
|
+
function numberFromUnknown(value) {
|
|
1441
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
1442
|
+
return value;
|
|
1443
|
+
if (typeof value === 'string' && value.trim()) {
|
|
1444
|
+
const parsed = Number(value);
|
|
1445
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1446
|
+
}
|
|
1447
|
+
if (typeof value === 'boolean')
|
|
1448
|
+
return value ? 1 : 0;
|
|
1449
|
+
return null;
|
|
1450
|
+
}
|
|
1451
|
+
function normalizeScoreResultsInput(sourcePath, raw, aggregateMode = false) {
|
|
1420
1452
|
const logicalPath = sourcePath.endsWith('.gz') ? sourcePath.slice(0, -3) : sourcePath;
|
|
1421
1453
|
if (!logicalPath.endsWith('.json'))
|
|
1422
|
-
return raw;
|
|
1454
|
+
return { resultsJsonl: raw };
|
|
1423
1455
|
try {
|
|
1424
1456
|
const parsed = JSON.parse(raw);
|
|
1457
|
+
if (aggregateMode) {
|
|
1458
|
+
if (!isRecord(parsed)) {
|
|
1459
|
+
throw new Error('Aggregate score results JSON must be an object');
|
|
1460
|
+
}
|
|
1461
|
+
return { aggregate: parsed };
|
|
1462
|
+
}
|
|
1463
|
+
if (isRecord(parsed) && looksLikeAggregateScoreObject(parsed)) {
|
|
1464
|
+
return {
|
|
1465
|
+
aggregate: parsed,
|
|
1466
|
+
aggregateWarning: 'Warning: aggregate score JSON detected. Pass --aggregate to make this explicit.',
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1425
1469
|
const rows = Array.isArray(parsed) ? parsed : [parsed];
|
|
1426
1470
|
if (rows.some(row => !isRecord(row))) {
|
|
1427
1471
|
throw new Error('JSON score results must be an object or an array of objects');
|
|
1428
1472
|
}
|
|
1429
|
-
return rows.map(row => JSON.stringify(row)).join('\n');
|
|
1473
|
+
return { resultsJsonl: rows.map(row => JSON.stringify(row)).join('\n') };
|
|
1430
1474
|
}
|
|
1431
1475
|
catch (error) {
|
|
1432
1476
|
const message = error instanceof Error ? error.message : String(error);
|
|
1433
1477
|
throw new Error(`Invalid score results JSON '${sourcePath}': ${message}`);
|
|
1434
1478
|
}
|
|
1435
1479
|
}
|
|
1480
|
+
function readOptionalJsonlFile(pathArg) {
|
|
1481
|
+
if (!pathArg)
|
|
1482
|
+
return undefined;
|
|
1483
|
+
const bytes = readSourceBytes(pathArg);
|
|
1484
|
+
return pathArg.endsWith('.gz')
|
|
1485
|
+
? gunzipSync(bytes).toString('utf8')
|
|
1486
|
+
: bytes.toString('utf8');
|
|
1487
|
+
}
|
|
1488
|
+
function parseAliasAssignments(value) {
|
|
1489
|
+
const result = {};
|
|
1490
|
+
if (!value)
|
|
1491
|
+
return result;
|
|
1492
|
+
for (const item of parseCommaSeparated(value)) {
|
|
1493
|
+
const equalsIndex = item.indexOf('=');
|
|
1494
|
+
if (equalsIndex <= 0 || equalsIndex === item.length - 1) {
|
|
1495
|
+
throw new Error(`Expected alias assignment in form alias=value, got '${item}'`);
|
|
1496
|
+
}
|
|
1497
|
+
result[item.slice(0, equalsIndex)] = item.slice(equalsIndex + 1);
|
|
1498
|
+
}
|
|
1499
|
+
return result;
|
|
1500
|
+
}
|
|
1501
|
+
function readDependencyResultAssignments(value) {
|
|
1502
|
+
const assignments = parseAliasAssignments(value);
|
|
1503
|
+
const result = {};
|
|
1504
|
+
for (const [alias, path] of Object.entries(assignments)) {
|
|
1505
|
+
result[alias] = readOptionalJsonlFile(path) || '';
|
|
1506
|
+
}
|
|
1507
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
1508
|
+
}
|
|
1509
|
+
async function execScorer() {
|
|
1510
|
+
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
1511
|
+
const scorerVersionId = getArg('--scorer-version');
|
|
1512
|
+
const subjectPromptVersionId = getArg('--subject-version') || getArg('--prompt-version');
|
|
1513
|
+
const optimizationRunId = getArg('--optimization-run');
|
|
1514
|
+
const candidateId = getArg('--candidate');
|
|
1515
|
+
const datasetVersionId = getArg('--dataset-version');
|
|
1516
|
+
const splitSetId = getArg('--split-set');
|
|
1517
|
+
const splitName = getArg('--split');
|
|
1518
|
+
const outPath = getArg('--out');
|
|
1519
|
+
if (!scorerVersionId ||
|
|
1520
|
+
(!subjectPromptVersionId && (!optimizationRunId || !candidateId)) ||
|
|
1521
|
+
!datasetVersionId ||
|
|
1522
|
+
!splitSetId ||
|
|
1523
|
+
!splitName) {
|
|
1524
|
+
throw new Error('Usage: orizu scorers exec --scorer-version <id> (--subject-version <prompt-version-id> | --optimization-run <id> --candidate <id>) --dataset-version <id> --split-set <id> --split <name> [--subject-results <jsonl>] [--dependency-score-run <alias=id>] [--dependency-results <alias=path>] [--no-submit] [--out <score.json>] [--project <team/project>] [--json]');
|
|
1525
|
+
}
|
|
1526
|
+
const response = await authedFetch(`/api/cli/scorers/exec?project=${encodeURIComponent(project)}`, {
|
|
1527
|
+
method: 'POST',
|
|
1528
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1529
|
+
body: JSON.stringify({
|
|
1530
|
+
scorerVersionId,
|
|
1531
|
+
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
1532
|
+
optimizationRunId: optimizationRunId || undefined,
|
|
1533
|
+
candidateId: candidateId || undefined,
|
|
1534
|
+
datasetVersionId,
|
|
1535
|
+
splitSetId,
|
|
1536
|
+
splitName,
|
|
1537
|
+
submit: !hasArg('--no-submit'),
|
|
1538
|
+
reuseExisting: !hasArg('--no-reuse-existing'),
|
|
1539
|
+
subjectResultsJsonl: readOptionalJsonlFile(getArg('--subject-results') || getArg('--outputs')),
|
|
1540
|
+
dependencyScoreRunIds: parseAliasAssignments(getArg('--dependency-score-run') || getArg('--dependency-score-runs')),
|
|
1541
|
+
dependencyResultsJsonl: readDependencyResultAssignments(getArg('--dependency-results')),
|
|
1542
|
+
}),
|
|
1543
|
+
});
|
|
1544
|
+
if (!response.ok) {
|
|
1545
|
+
throw new Error(`Failed to execute scorer: ${await response.text()}`);
|
|
1546
|
+
}
|
|
1547
|
+
const data = await parseJsonResponse(response, 'Scorer exec');
|
|
1548
|
+
if (outPath) {
|
|
1549
|
+
writeFileSync(expandHomePath(outPath), `${JSON.stringify(data.scoreResult || data, null, 2)}\n`);
|
|
1550
|
+
}
|
|
1551
|
+
if (hasJsonFlag()) {
|
|
1552
|
+
printJson(data);
|
|
1553
|
+
return;
|
|
1554
|
+
}
|
|
1555
|
+
const scoreRun = isRecord(data.scoreRun) ? data.scoreRun : null;
|
|
1556
|
+
const scoreResult = isRecord(data.scoreResult) ? data.scoreResult : null;
|
|
1557
|
+
const scoreValue = scoreRun
|
|
1558
|
+
? scoreRun.scoreValue
|
|
1559
|
+
: scoreResult
|
|
1560
|
+
? scoreResult.scoreValue
|
|
1561
|
+
: null;
|
|
1562
|
+
if (scoreRun && typeof scoreRun.id === 'string') {
|
|
1563
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} -> score ${sanitizeTerminalText(scoreRun.id)} (${formatPercent(numberFromUnknown(scoreValue))})`);
|
|
1564
|
+
}
|
|
1565
|
+
else {
|
|
1566
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} (${formatPercent(numberFromUnknown(scoreValue))})`);
|
|
1567
|
+
}
|
|
1568
|
+
if (outPath) {
|
|
1569
|
+
printLine(`Wrote scorer result to ${sanitizeTerminalText(outPath)}`);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1436
1572
|
const OPTIMIZATION_REPORT_MAX_BYTES = 2 * 1024 * 1024;
|
|
1437
1573
|
function parseOptionalNumberFlag(name) {
|
|
1438
1574
|
const value = getArg(name);
|
|
@@ -2020,10 +2156,51 @@ async function createAppFromFile() {
|
|
|
2020
2156
|
}
|
|
2021
2157
|
const data = await parseJsonResponse(response, 'App create');
|
|
2022
2158
|
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`);
|
|
2159
|
+
if (data.app.url) {
|
|
2160
|
+
printLine(`View app: ${formatTerminalLink(data.app.url)}`);
|
|
2161
|
+
}
|
|
2023
2162
|
if (data.warnings?.length) {
|
|
2024
2163
|
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`);
|
|
2025
2164
|
}
|
|
2026
2165
|
}
|
|
2166
|
+
async function previewAppFromFile() {
|
|
2167
|
+
const filePath = getArg('--file');
|
|
2168
|
+
const inputSchemaPath = getArg('--input-schema');
|
|
2169
|
+
const outputSchemaPath = getArg('--output-schema');
|
|
2170
|
+
const sampleRowPath = getArg('--sample-row');
|
|
2171
|
+
const screenshotPath = getArg('--screenshot');
|
|
2172
|
+
const component = getArg('--component') || undefined;
|
|
2173
|
+
const headed = hasArg('--headed');
|
|
2174
|
+
const keepOpen = hasArg('--keep-open');
|
|
2175
|
+
if (!filePath || !inputSchemaPath || !outputSchemaPath || !sampleRowPath) {
|
|
2176
|
+
throw new Error('Usage: orizu apps preview --file <path> --input-schema <json-path> --output-schema <json-path> --sample-row <json-path> [--screenshot <png-path>] [--headed] [--keep-open] [--component <name>]');
|
|
2177
|
+
}
|
|
2178
|
+
const expandedFilePath = realpathSync(expandHomePath(filePath));
|
|
2179
|
+
const inputJsonSchema = readJsonFile(inputSchemaPath);
|
|
2180
|
+
const outputJsonSchema = readJsonFile(outputSchemaPath);
|
|
2181
|
+
const sampleRow = readJsonFile(sampleRowPath);
|
|
2182
|
+
const expandedScreenshotPath = screenshotPath ? expandHomePath(screenshotPath) : undefined;
|
|
2183
|
+
const result = await runLocalAppPreview({
|
|
2184
|
+
filePath: expandedFilePath,
|
|
2185
|
+
inputSchema: inputJsonSchema,
|
|
2186
|
+
outputSchema: outputJsonSchema,
|
|
2187
|
+
sampleRow,
|
|
2188
|
+
screenshotPath: expandedScreenshotPath,
|
|
2189
|
+
componentName: component,
|
|
2190
|
+
headed,
|
|
2191
|
+
keepOpen,
|
|
2192
|
+
});
|
|
2193
|
+
printLine(`Preview rendered: ${formatTerminalLink(result.url)}`);
|
|
2194
|
+
if (result.screenshotPath) {
|
|
2195
|
+
printLine(`Screenshot: ${sanitizeTerminalText(result.screenshotPath)}`);
|
|
2196
|
+
}
|
|
2197
|
+
if (headed || keepOpen) {
|
|
2198
|
+
printLine('Headed preview is running. Close Chromium or stop the command when you are done.');
|
|
2199
|
+
}
|
|
2200
|
+
if (result.warnings.length > 0) {
|
|
2201
|
+
printLine(`Warnings: ${sanitizeTerminalText(result.warnings.join('; '))}`);
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2027
2204
|
async function updateAppFromFile() {
|
|
2028
2205
|
const filePath = getArg('--file');
|
|
2029
2206
|
const inputSchemaPath = getArg('--input-schema');
|
|
@@ -3240,6 +3417,10 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3240
3417
|
await setScorerLabel();
|
|
3241
3418
|
return;
|
|
3242
3419
|
}
|
|
3420
|
+
if (command === 'scorers' && subcommand === 'exec') {
|
|
3421
|
+
await execScorer();
|
|
3422
|
+
return;
|
|
3423
|
+
}
|
|
3243
3424
|
if (command === 'runners' && subcommand === 'push') {
|
|
3244
3425
|
await pushRunnerArtifact('runner');
|
|
3245
3426
|
return;
|
|
@@ -3289,6 +3470,10 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3289
3470
|
await createAppFromFile();
|
|
3290
3471
|
return;
|
|
3291
3472
|
}
|
|
3473
|
+
if (command === 'apps' && subcommand === 'preview') {
|
|
3474
|
+
await previewAppFromFile();
|
|
3475
|
+
return;
|
|
3476
|
+
}
|
|
3292
3477
|
if (command === 'apps' && subcommand === 'update') {
|
|
3293
3478
|
await updateAppFromFile();
|
|
3294
3479
|
return;
|