orizu 0.3.4 → 0.3.6
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 +40 -3
- package/dist/help.js +611 -0
- package/dist/index.js +458 -20
- package/dist/preview-runtime.js +857 -0
- package/dist/skill-installer.js +180 -0
- package/package.json +12 -3
- package/scripts/vendor-orizu-skill.mjs +54 -0
- package/src/help.ts +676 -0
- package/src/index.ts +568 -21
- package/src/preview-runtime.ts +976 -0
- package/src/skill-installer.ts +260 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +16 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +68 -56
- package/vendor/orizu-gepa-python/src/orizu_gepa/reflection.py +31 -6
- package/vendor/skills/orizu-cli/SKILL.md +185 -0
- package/vendor/skills/orizu-cli/agents/openai.yaml +4 -0
- package/vendor/skills/orizu-cli/references/building-apps.md +1461 -0
- package/vendor/skills/orizu-cli/references/building-judges.md +218 -0
- package/vendor/skills/orizu-cli/references/cli-reference.md +324 -0
- package/vendor/skills/orizu-cli/references/optimization-reports.md +174 -0
- package/vendor/skills/orizu-cli/references/optimization-with-gepa.md +291 -0
- package/vendor/skills/orizu-cli/references/primer.md +245 -0
- package/vendor/skills/orizu-cli/references/prompt-control-plane.md +830 -0
- package/vendor/skills/orizu-cli/scripts/test-app.mjs +492 -0
package/dist/index.js
CHANGED
|
@@ -13,8 +13,12 @@ import { clearServerCredentials, getServerCredentials, saveServerCredentials } f
|
|
|
13
13
|
import { parseDatasetFile } from './file-parser.js';
|
|
14
14
|
import { streamJsonlRowChunks } from './jsonl-stream.js';
|
|
15
15
|
import { parseDatasetReference } from './dataset-download.js';
|
|
16
|
+
import { extractErrorMessage } from './error-response.js';
|
|
16
17
|
import { parseGlobalFlags } from './global-flags.js';
|
|
18
|
+
import { getCapabilities, renderHelpForArgs, renderRootHelp } from './help.js';
|
|
19
|
+
import { runLocalAppPreview } from './preview-runtime.js';
|
|
17
20
|
import { assertSecureTokenTransport, authedFetch, getBaseUrl, resolveLoginBaseUrl, setGlobalFlags, } from './http.js';
|
|
21
|
+
import { getSkillInstallPath, installSkillTarget, isSkillInstallTarget, SKILL_INSTALL_TARGETS, targetNeedsOverwrite, } from './skill-installer.js';
|
|
18
22
|
import { formatTaskCreateError } from './task-create-error.js';
|
|
19
23
|
const MAX_README_LENGTH = 200_000;
|
|
20
24
|
function getCliVersion() {
|
|
@@ -31,12 +35,16 @@ function printVersion() {
|
|
|
31
35
|
printLine(`orizu ${getCliVersion()}`);
|
|
32
36
|
}
|
|
33
37
|
function printUsage() {
|
|
34
|
-
printLine(
|
|
38
|
+
printLine(renderRootHelp());
|
|
39
|
+
}
|
|
40
|
+
function printPreviewUsage() {
|
|
41
|
+
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
42
|
}
|
|
36
43
|
function printOptimizationUsage() {
|
|
37
|
-
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]`);
|
|
44
|
+
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] [--no-skip-perfect-parent-reflection]\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]`);
|
|
38
45
|
}
|
|
39
46
|
let cliArgs = process.argv.slice(2);
|
|
47
|
+
let cliJsonOutput = false;
|
|
40
48
|
function getArg(name) {
|
|
41
49
|
const index = cliArgs.indexOf(name);
|
|
42
50
|
if (index === -1 || index + 1 >= cliArgs.length) {
|
|
@@ -44,6 +52,26 @@ function getArg(name) {
|
|
|
44
52
|
}
|
|
45
53
|
return cliArgs[index + 1];
|
|
46
54
|
}
|
|
55
|
+
function getArgs(name) {
|
|
56
|
+
const values = [];
|
|
57
|
+
for (let index = 0; index < cliArgs.length; index += 1) {
|
|
58
|
+
if (cliArgs[index] !== name) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const value = cliArgs[index + 1];
|
|
62
|
+
if (!value || value.startsWith('-')) {
|
|
63
|
+
throw new Error(`Usage: ${name} <value>`);
|
|
64
|
+
}
|
|
65
|
+
values.push(value);
|
|
66
|
+
index += 1;
|
|
67
|
+
}
|
|
68
|
+
return values;
|
|
69
|
+
}
|
|
70
|
+
function rejectDashPrefixedOptionValue(name, value) {
|
|
71
|
+
if (value && value.startsWith('-')) {
|
|
72
|
+
throw new Error(`Invalid value for ${name}: option values cannot start with a dash`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
47
75
|
export function normalizeSlugInput(slug) {
|
|
48
76
|
return slug.trim().toLowerCase();
|
|
49
77
|
}
|
|
@@ -1384,17 +1412,22 @@ async function submitScoreResults() {
|
|
|
1384
1412
|
const optimizationRunId = getArg('--optimization-run');
|
|
1385
1413
|
const candidateId = getArg('--candidate');
|
|
1386
1414
|
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]');
|
|
1415
|
+
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
1416
|
}
|
|
1389
1417
|
const resultBytes = readSourceBytes(resultsPath);
|
|
1390
1418
|
const raw = resultsPath.endsWith('.gz')
|
|
1391
1419
|
? gunzipSync(resultBytes).toString('utf8')
|
|
1392
1420
|
: resultBytes.toString('utf8');
|
|
1393
|
-
const
|
|
1421
|
+
const scoreInput = normalizeScoreResultsInput(resultsPath, raw, hasArg('--aggregate'));
|
|
1422
|
+
if (scoreInput.aggregateWarning) {
|
|
1423
|
+
console.warn(scoreInput.aggregateWarning);
|
|
1424
|
+
}
|
|
1425
|
+
const aggregatePayload = scoreInput.aggregate || {};
|
|
1394
1426
|
const response = await authedFetch(`/api/cli/scores/submit?project=${encodeURIComponent(project)}`, {
|
|
1395
1427
|
method: 'POST',
|
|
1396
1428
|
headers: { 'Content-Type': 'application/json' },
|
|
1397
1429
|
body: JSON.stringify({
|
|
1430
|
+
...aggregatePayload,
|
|
1398
1431
|
scorerVersionId,
|
|
1399
1432
|
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
1400
1433
|
datasetVersionId: getArg('--dataset-version') || undefined,
|
|
@@ -1402,7 +1435,7 @@ async function submitScoreResults() {
|
|
|
1402
1435
|
splitName: getArg('--split') || undefined,
|
|
1403
1436
|
optimizationRunId: optimizationRunId || undefined,
|
|
1404
1437
|
candidateId: candidateId || undefined,
|
|
1405
|
-
resultsJsonl,
|
|
1438
|
+
resultsJsonl: scoreInput.resultsJsonl,
|
|
1406
1439
|
}),
|
|
1407
1440
|
});
|
|
1408
1441
|
if (!response.ok) {
|
|
@@ -1416,24 +1449,150 @@ async function submitScoreResults() {
|
|
|
1416
1449
|
printLine(`Submitted score ${sanitizeTerminalText(data.scoreRun.id)} ` +
|
|
1417
1450
|
`(${formatPercent(data.scoreRun.scoreValue)})`);
|
|
1418
1451
|
}
|
|
1419
|
-
function
|
|
1452
|
+
function looksLikeAggregateScoreObject(value) {
|
|
1453
|
+
return (value.scoreValue !== undefined ||
|
|
1454
|
+
value.score_value !== undefined ||
|
|
1455
|
+
value.diagnostics !== undefined ||
|
|
1456
|
+
value.feedbackSummary !== undefined ||
|
|
1457
|
+
value.feedback_summary !== undefined ||
|
|
1458
|
+
value.rowEvidence !== undefined ||
|
|
1459
|
+
value.row_evidence !== undefined ||
|
|
1460
|
+
value.dependencyScoreRunIds !== undefined ||
|
|
1461
|
+
value.dependency_score_run_ids !== undefined);
|
|
1462
|
+
}
|
|
1463
|
+
function numberFromUnknown(value) {
|
|
1464
|
+
if (typeof value === 'number' && Number.isFinite(value))
|
|
1465
|
+
return value;
|
|
1466
|
+
if (typeof value === 'string' && value.trim()) {
|
|
1467
|
+
const parsed = Number(value);
|
|
1468
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
1469
|
+
}
|
|
1470
|
+
if (typeof value === 'boolean')
|
|
1471
|
+
return value ? 1 : 0;
|
|
1472
|
+
return null;
|
|
1473
|
+
}
|
|
1474
|
+
function normalizeScoreResultsInput(sourcePath, raw, aggregateMode = false) {
|
|
1420
1475
|
const logicalPath = sourcePath.endsWith('.gz') ? sourcePath.slice(0, -3) : sourcePath;
|
|
1421
1476
|
if (!logicalPath.endsWith('.json'))
|
|
1422
|
-
return raw;
|
|
1477
|
+
return { resultsJsonl: raw };
|
|
1423
1478
|
try {
|
|
1424
1479
|
const parsed = JSON.parse(raw);
|
|
1480
|
+
if (aggregateMode) {
|
|
1481
|
+
if (!isRecord(parsed)) {
|
|
1482
|
+
throw new Error('Aggregate score results JSON must be an object');
|
|
1483
|
+
}
|
|
1484
|
+
return { aggregate: parsed };
|
|
1485
|
+
}
|
|
1486
|
+
if (isRecord(parsed) && looksLikeAggregateScoreObject(parsed)) {
|
|
1487
|
+
return {
|
|
1488
|
+
aggregate: parsed,
|
|
1489
|
+
aggregateWarning: 'Warning: aggregate score JSON detected. Pass --aggregate to make this explicit.',
|
|
1490
|
+
};
|
|
1491
|
+
}
|
|
1425
1492
|
const rows = Array.isArray(parsed) ? parsed : [parsed];
|
|
1426
1493
|
if (rows.some(row => !isRecord(row))) {
|
|
1427
1494
|
throw new Error('JSON score results must be an object or an array of objects');
|
|
1428
1495
|
}
|
|
1429
|
-
return rows.map(row => JSON.stringify(row)).join('\n');
|
|
1496
|
+
return { resultsJsonl: rows.map(row => JSON.stringify(row)).join('\n') };
|
|
1430
1497
|
}
|
|
1431
1498
|
catch (error) {
|
|
1432
1499
|
const message = error instanceof Error ? error.message : String(error);
|
|
1433
1500
|
throw new Error(`Invalid score results JSON '${sourcePath}': ${message}`);
|
|
1434
1501
|
}
|
|
1435
1502
|
}
|
|
1436
|
-
|
|
1503
|
+
function readOptionalJsonlFile(pathArg) {
|
|
1504
|
+
if (!pathArg)
|
|
1505
|
+
return undefined;
|
|
1506
|
+
const bytes = readSourceBytes(pathArg);
|
|
1507
|
+
return pathArg.endsWith('.gz')
|
|
1508
|
+
? gunzipSync(bytes).toString('utf8')
|
|
1509
|
+
: bytes.toString('utf8');
|
|
1510
|
+
}
|
|
1511
|
+
function parseAliasAssignments(value) {
|
|
1512
|
+
const result = {};
|
|
1513
|
+
if (!value)
|
|
1514
|
+
return result;
|
|
1515
|
+
for (const item of parseCommaSeparated(value)) {
|
|
1516
|
+
const equalsIndex = item.indexOf('=');
|
|
1517
|
+
if (equalsIndex <= 0 || equalsIndex === item.length - 1) {
|
|
1518
|
+
throw new Error(`Expected alias assignment in form alias=value, got '${item}'`);
|
|
1519
|
+
}
|
|
1520
|
+
result[item.slice(0, equalsIndex)] = item.slice(equalsIndex + 1);
|
|
1521
|
+
}
|
|
1522
|
+
return result;
|
|
1523
|
+
}
|
|
1524
|
+
function readDependencyResultAssignments(value) {
|
|
1525
|
+
const assignments = parseAliasAssignments(value);
|
|
1526
|
+
const result = {};
|
|
1527
|
+
for (const [alias, path] of Object.entries(assignments)) {
|
|
1528
|
+
result[alias] = readOptionalJsonlFile(path) || '';
|
|
1529
|
+
}
|
|
1530
|
+
return Object.keys(result).length > 0 ? result : undefined;
|
|
1531
|
+
}
|
|
1532
|
+
async function execScorer() {
|
|
1533
|
+
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
1534
|
+
const scorerVersionId = getArg('--scorer-version');
|
|
1535
|
+
const subjectPromptVersionId = getArg('--subject-version') || getArg('--prompt-version');
|
|
1536
|
+
const optimizationRunId = getArg('--optimization-run');
|
|
1537
|
+
const candidateId = getArg('--candidate');
|
|
1538
|
+
const datasetVersionId = getArg('--dataset-version');
|
|
1539
|
+
const splitSetId = getArg('--split-set');
|
|
1540
|
+
const splitName = getArg('--split');
|
|
1541
|
+
const outPath = getArg('--out');
|
|
1542
|
+
if (!scorerVersionId ||
|
|
1543
|
+
(!subjectPromptVersionId && (!optimizationRunId || !candidateId)) ||
|
|
1544
|
+
!datasetVersionId ||
|
|
1545
|
+
!splitSetId ||
|
|
1546
|
+
!splitName) {
|
|
1547
|
+
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]');
|
|
1548
|
+
}
|
|
1549
|
+
const response = await authedFetch(`/api/cli/scorers/exec?project=${encodeURIComponent(project)}`, {
|
|
1550
|
+
method: 'POST',
|
|
1551
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1552
|
+
body: JSON.stringify({
|
|
1553
|
+
scorerVersionId,
|
|
1554
|
+
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
1555
|
+
optimizationRunId: optimizationRunId || undefined,
|
|
1556
|
+
candidateId: candidateId || undefined,
|
|
1557
|
+
datasetVersionId,
|
|
1558
|
+
splitSetId,
|
|
1559
|
+
splitName,
|
|
1560
|
+
submit: !hasArg('--no-submit'),
|
|
1561
|
+
reuseExisting: !hasArg('--no-reuse-existing'),
|
|
1562
|
+
subjectResultsJsonl: readOptionalJsonlFile(getArg('--subject-results') || getArg('--outputs')),
|
|
1563
|
+
dependencyScoreRunIds: parseAliasAssignments(getArg('--dependency-score-run') || getArg('--dependency-score-runs')),
|
|
1564
|
+
dependencyResultsJsonl: readDependencyResultAssignments(getArg('--dependency-results')),
|
|
1565
|
+
}),
|
|
1566
|
+
});
|
|
1567
|
+
if (!response.ok) {
|
|
1568
|
+
throw new Error(`Failed to execute scorer: ${await response.text()}`);
|
|
1569
|
+
}
|
|
1570
|
+
const data = await parseJsonResponse(response, 'Scorer exec');
|
|
1571
|
+
if (outPath) {
|
|
1572
|
+
writeFileSync(expandHomePath(outPath), `${JSON.stringify(data.scoreResult || data, null, 2)}\n`);
|
|
1573
|
+
}
|
|
1574
|
+
if (hasJsonFlag()) {
|
|
1575
|
+
printJson(data);
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1578
|
+
const scoreRun = isRecord(data.scoreRun) ? data.scoreRun : null;
|
|
1579
|
+
const scoreResult = isRecord(data.scoreResult) ? data.scoreResult : null;
|
|
1580
|
+
const scoreValue = scoreRun
|
|
1581
|
+
? scoreRun.scoreValue
|
|
1582
|
+
: scoreResult
|
|
1583
|
+
? scoreResult.scoreValue
|
|
1584
|
+
: null;
|
|
1585
|
+
if (scoreRun && typeof scoreRun.id === 'string') {
|
|
1586
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} -> score ${sanitizeTerminalText(scoreRun.id)} (${formatPercent(numberFromUnknown(scoreValue))})`);
|
|
1587
|
+
}
|
|
1588
|
+
else {
|
|
1589
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} (${formatPercent(numberFromUnknown(scoreValue))})`);
|
|
1590
|
+
}
|
|
1591
|
+
if (outPath) {
|
|
1592
|
+
printLine(`Wrote scorer result to ${sanitizeTerminalText(outPath)}`);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
const MARKDOWN_REPORT_MAX_BYTES = 2 * 1024 * 1024;
|
|
1437
1596
|
function parseOptionalNumberFlag(name) {
|
|
1438
1597
|
const value = getArg(name);
|
|
1439
1598
|
if (!value) {
|
|
@@ -1448,9 +1607,11 @@ function parseOptionalNumberFlag(name) {
|
|
|
1448
1607
|
function hasObjectKeys(value) {
|
|
1449
1608
|
return Object.keys(value).length > 0;
|
|
1450
1609
|
}
|
|
1451
|
-
function
|
|
1610
|
+
function readMarkdownReportInput(reportLabel) {
|
|
1452
1611
|
const report = getArg('--report');
|
|
1453
1612
|
const reportFile = getArg('--report-file');
|
|
1613
|
+
rejectDashPrefixedOptionValue('--report', report);
|
|
1614
|
+
rejectDashPrefixedOptionValue('--report-file', reportFile);
|
|
1454
1615
|
if (report && reportFile) {
|
|
1455
1616
|
throw new Error('Use either --report or --report-file, not both');
|
|
1456
1617
|
}
|
|
@@ -1475,13 +1636,19 @@ function readOptimizationReportInput() {
|
|
|
1475
1636
|
sourceName = 'inline';
|
|
1476
1637
|
}
|
|
1477
1638
|
if (!markdown.trim()) {
|
|
1478
|
-
throw new Error(
|
|
1639
|
+
throw new Error(`${reportLabel} report markdown must not be blank`);
|
|
1479
1640
|
}
|
|
1480
|
-
if (Buffer.byteLength(markdown, 'utf8') >
|
|
1481
|
-
throw new Error(
|
|
1641
|
+
if (Buffer.byteLength(markdown, 'utf8') > MARKDOWN_REPORT_MAX_BYTES) {
|
|
1642
|
+
throw new Error(`${reportLabel} report exceeds ${MARKDOWN_REPORT_MAX_BYTES} bytes`);
|
|
1482
1643
|
}
|
|
1483
1644
|
return { markdown, sourceName };
|
|
1484
1645
|
}
|
|
1646
|
+
function readOptimizationReportInput() {
|
|
1647
|
+
return readMarkdownReportInput('Optimization');
|
|
1648
|
+
}
|
|
1649
|
+
function readTaskReportInput() {
|
|
1650
|
+
return readMarkdownReportInput('Task');
|
|
1651
|
+
}
|
|
1485
1652
|
async function startOptimizationRun() {
|
|
1486
1653
|
const project = getArg('--project') || await resolveProjectSlug(null);
|
|
1487
1654
|
const optimizerVersionId = getArg('--optimizer-version');
|
|
@@ -1786,11 +1953,106 @@ function readSourceBytes(pathArg) {
|
|
|
1786
1953
|
}
|
|
1787
1954
|
}
|
|
1788
1955
|
function hasJsonFlag() {
|
|
1789
|
-
return hasArg('--json');
|
|
1956
|
+
return cliJsonOutput || hasArg('--json');
|
|
1790
1957
|
}
|
|
1791
1958
|
function printJson(value) {
|
|
1792
1959
|
printLine(JSON.stringify(value));
|
|
1793
1960
|
}
|
|
1961
|
+
function printCapabilities() {
|
|
1962
|
+
const capabilities = getCapabilities(getCliVersion());
|
|
1963
|
+
if (hasJsonFlag()) {
|
|
1964
|
+
printLine(JSON.stringify(capabilities));
|
|
1965
|
+
return;
|
|
1966
|
+
}
|
|
1967
|
+
printLine('orizu capabilities');
|
|
1968
|
+
printLine('');
|
|
1969
|
+
printLine('Run `orizu capabilities --json` for a machine-readable command manifest.');
|
|
1970
|
+
printLine('');
|
|
1971
|
+
for (const command of capabilities.commands) {
|
|
1972
|
+
printLine(` ${command.name.padEnd(34)} ${command.help}`);
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
async function askYesNo(question, defaultYes) {
|
|
1976
|
+
const rl = createInterface({ input, output });
|
|
1977
|
+
try {
|
|
1978
|
+
const suffix = defaultYes ? 'Y/n' : 'y/N';
|
|
1979
|
+
const answer = (await rl.question(`${question} (${suffix}) `)).trim().toLowerCase();
|
|
1980
|
+
if (!answer) {
|
|
1981
|
+
return defaultYes;
|
|
1982
|
+
}
|
|
1983
|
+
return answer === 'y' || answer === 'yes';
|
|
1984
|
+
}
|
|
1985
|
+
finally {
|
|
1986
|
+
rl.close();
|
|
1987
|
+
}
|
|
1988
|
+
}
|
|
1989
|
+
async function promptSkillInstallTargets() {
|
|
1990
|
+
if (!isInteractiveTerminal()) {
|
|
1991
|
+
throw new Error(`Usage: orizu install-skill --target <${SKILL_INSTALL_TARGETS.join('|')}> [--yes] [--dry-run]`);
|
|
1992
|
+
}
|
|
1993
|
+
printLine('Where should the Orizu CLI skill be installed?');
|
|
1994
|
+
const targets = [];
|
|
1995
|
+
for (const target of SKILL_INSTALL_TARGETS) {
|
|
1996
|
+
const defaultYes = target === 'agent-user';
|
|
1997
|
+
if (await askYesNo(` Install to ${target}?`, defaultYes)) {
|
|
1998
|
+
targets.push(target);
|
|
1999
|
+
}
|
|
2000
|
+
}
|
|
2001
|
+
return targets;
|
|
2002
|
+
}
|
|
2003
|
+
function parseSkillInstallTargets() {
|
|
2004
|
+
const rawTargets = getArgs('--target');
|
|
2005
|
+
const targets = [];
|
|
2006
|
+
for (const target of rawTargets) {
|
|
2007
|
+
if (!isSkillInstallTarget(target)) {
|
|
2008
|
+
throw new Error(`Unknown skill install target '${target}'. Available targets: ${SKILL_INSTALL_TARGETS.join(', ')}`);
|
|
2009
|
+
}
|
|
2010
|
+
if (!targets.includes(target)) {
|
|
2011
|
+
targets.push(target);
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
return targets;
|
|
2015
|
+
}
|
|
2016
|
+
function formatSkillInstallAction(action) {
|
|
2017
|
+
if (action === 'created')
|
|
2018
|
+
return 'Wrote';
|
|
2019
|
+
if (action === 'updated')
|
|
2020
|
+
return 'Updated';
|
|
2021
|
+
if (action === 'would-create')
|
|
2022
|
+
return 'Would write';
|
|
2023
|
+
return 'Would update';
|
|
2024
|
+
}
|
|
2025
|
+
async function installSkillCommand() {
|
|
2026
|
+
const skipConfirm = hasArg('--yes');
|
|
2027
|
+
const dryRun = hasArg('--dry-run');
|
|
2028
|
+
let targets = parseSkillInstallTargets();
|
|
2029
|
+
if (targets.length === 0) {
|
|
2030
|
+
targets = await promptSkillInstallTargets();
|
|
2031
|
+
}
|
|
2032
|
+
if (targets.length === 0) {
|
|
2033
|
+
printLine('No targets selected; nothing to do.');
|
|
2034
|
+
return;
|
|
2035
|
+
}
|
|
2036
|
+
for (const target of targets) {
|
|
2037
|
+
let overwrite = skipConfirm;
|
|
2038
|
+
const installPath = getSkillInstallPath(target);
|
|
2039
|
+
if (!dryRun && !overwrite && targetNeedsOverwrite(target)) {
|
|
2040
|
+
if (!isInteractiveTerminal()) {
|
|
2041
|
+
throw new Error(`${installPath} already exists. Pass --yes to replace it.`);
|
|
2042
|
+
}
|
|
2043
|
+
overwrite = await askYesNo(`Replace ${installPath}?`, true);
|
|
2044
|
+
if (!overwrite) {
|
|
2045
|
+
printLine(`Skipped ${installPath}`);
|
|
2046
|
+
continue;
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
const result = installSkillTarget(target, {
|
|
2050
|
+
overwrite,
|
|
2051
|
+
dryRun,
|
|
2052
|
+
});
|
|
2053
|
+
printLine(`${formatSkillInstallAction(result.action)} ${result.path}`);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
1794
2056
|
function readJsonFile(pathArg) {
|
|
1795
2057
|
const raw = readSourceFile(pathArg);
|
|
1796
2058
|
try {
|
|
@@ -2020,10 +2282,51 @@ async function createAppFromFile() {
|
|
|
2020
2282
|
}
|
|
2021
2283
|
const data = await parseJsonResponse(response, 'App create');
|
|
2022
2284
|
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`);
|
|
2285
|
+
if (data.app.url) {
|
|
2286
|
+
printLine(`View app: ${formatTerminalLink(data.app.url)}`);
|
|
2287
|
+
}
|
|
2023
2288
|
if (data.warnings?.length) {
|
|
2024
2289
|
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`);
|
|
2025
2290
|
}
|
|
2026
2291
|
}
|
|
2292
|
+
async function previewAppFromFile() {
|
|
2293
|
+
const filePath = getArg('--file');
|
|
2294
|
+
const inputSchemaPath = getArg('--input-schema');
|
|
2295
|
+
const outputSchemaPath = getArg('--output-schema');
|
|
2296
|
+
const sampleRowPath = getArg('--sample-row');
|
|
2297
|
+
const screenshotPath = getArg('--screenshot');
|
|
2298
|
+
const component = getArg('--component') || undefined;
|
|
2299
|
+
const headed = hasArg('--headed');
|
|
2300
|
+
const keepOpen = hasArg('--keep-open');
|
|
2301
|
+
if (!filePath || !inputSchemaPath || !outputSchemaPath || !sampleRowPath) {
|
|
2302
|
+
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>]');
|
|
2303
|
+
}
|
|
2304
|
+
const expandedFilePath = realpathSync(expandHomePath(filePath));
|
|
2305
|
+
const inputJsonSchema = readJsonFile(inputSchemaPath);
|
|
2306
|
+
const outputJsonSchema = readJsonFile(outputSchemaPath);
|
|
2307
|
+
const sampleRow = readJsonFile(sampleRowPath);
|
|
2308
|
+
const expandedScreenshotPath = screenshotPath ? expandHomePath(screenshotPath) : undefined;
|
|
2309
|
+
const result = await runLocalAppPreview({
|
|
2310
|
+
filePath: expandedFilePath,
|
|
2311
|
+
inputSchema: inputJsonSchema,
|
|
2312
|
+
outputSchema: outputJsonSchema,
|
|
2313
|
+
sampleRow,
|
|
2314
|
+
screenshotPath: expandedScreenshotPath,
|
|
2315
|
+
componentName: component,
|
|
2316
|
+
headed,
|
|
2317
|
+
keepOpen,
|
|
2318
|
+
});
|
|
2319
|
+
printLine(`Preview rendered: ${formatTerminalLink(result.url)}`);
|
|
2320
|
+
if (result.screenshotPath) {
|
|
2321
|
+
printLine(`Screenshot: ${sanitizeTerminalText(result.screenshotPath)}`);
|
|
2322
|
+
}
|
|
2323
|
+
if (headed || keepOpen) {
|
|
2324
|
+
printLine('Headed preview is running. Close Chromium or stop the command when you are done.');
|
|
2325
|
+
}
|
|
2326
|
+
if (result.warnings.length > 0) {
|
|
2327
|
+
printLine(`Warnings: ${sanitizeTerminalText(result.warnings.join('; '))}`);
|
|
2328
|
+
}
|
|
2329
|
+
}
|
|
2027
2330
|
async function updateAppFromFile() {
|
|
2028
2331
|
const filePath = getArg('--file');
|
|
2029
2332
|
const inputSchemaPath = getArg('--input-schema');
|
|
@@ -2106,14 +2409,15 @@ async function createTask() {
|
|
|
2106
2409
|
const appId = getArg('--app');
|
|
2107
2410
|
const title = getArg('--title');
|
|
2108
2411
|
const assignees = parseCommaSeparated(getArg('--assignees'));
|
|
2412
|
+
const publish = hasArg('--publish');
|
|
2109
2413
|
const versionArg = getArg('--version');
|
|
2110
2414
|
const instructions = getArg('--instructions');
|
|
2111
2415
|
const labelsPerItemArg = getArg('--labels-per-item');
|
|
2112
2416
|
const labelsPerItem = labelsPerItemArg ? Number(labelsPerItemArg) : 1;
|
|
2113
2417
|
const parsedVersionNum = versionArg ? Number(versionArg) : Number.NaN;
|
|
2114
2418
|
const versionNum = Number.isInteger(parsedVersionNum) && parsedVersionNum > 0 ? parsedVersionNum : null;
|
|
2115
|
-
if (!projectSlug || !datasetId || !appId || !title || assignees.length === 0) {
|
|
2116
|
-
throw new Error('Usage: orizu tasks create --project <team/project> --dataset <datasetId> --app <appId> --title <title> --assignees <userIdOrEmail1,userIdOrEmail2> [--version <n>] [--instructions <text>] [--labels-per-item <n>] [--json]');
|
|
2419
|
+
if (!projectSlug || !datasetId || !appId || !title || (publish && assignees.length === 0)) {
|
|
2420
|
+
throw new Error('Usage: orizu tasks create --project <team/project> --dataset <datasetId> --app <appId> --title <title> [--assignees <userIdOrEmail1,userIdOrEmail2>] [--publish] [--version <n>] [--instructions <text>] [--labels-per-item <n>] [--json]');
|
|
2117
2421
|
}
|
|
2118
2422
|
if (versionArg && versionNum === null) {
|
|
2119
2423
|
throw new Error('--version must be a positive integer');
|
|
@@ -2128,6 +2432,7 @@ async function createTask() {
|
|
|
2128
2432
|
versionNum,
|
|
2129
2433
|
title,
|
|
2130
2434
|
memberIds: assignees,
|
|
2435
|
+
publish,
|
|
2131
2436
|
instructions,
|
|
2132
2437
|
requiredAssignmentsPerRow: labelsPerItem,
|
|
2133
2438
|
}),
|
|
@@ -2155,6 +2460,13 @@ async function createTask() {
|
|
|
2155
2460
|
status: data.task.status,
|
|
2156
2461
|
requiredAssignmentsPerRow: data.task.requiredAssignmentsPerRow,
|
|
2157
2462
|
assignmentsCreated: data.assignmentsCreated,
|
|
2463
|
+
draft: data.task.status === 'draft',
|
|
2464
|
+
...(data.task.status === 'draft'
|
|
2465
|
+
? {
|
|
2466
|
+
message: 'Draft created. Test it manually before assigning.',
|
|
2467
|
+
publishCommand: `orizu tasks publish --task ${data.task.id} --assignees <userId1,userId2>`,
|
|
2468
|
+
}
|
|
2469
|
+
: {}),
|
|
2158
2470
|
...(data.assignmentShortfall !== undefined ? { assignmentShortfall: data.assignmentShortfall } : {}),
|
|
2159
2471
|
...(data.warning ? { warning: data.warning } : {}),
|
|
2160
2472
|
}, null, 2));
|
|
@@ -2162,14 +2474,56 @@ async function createTask() {
|
|
|
2162
2474
|
}
|
|
2163
2475
|
const baseUrl = getBaseUrl();
|
|
2164
2476
|
const taskUrl = `${baseUrl}/d/${projectSlug}/tasks/${data.task.id}`;
|
|
2165
|
-
|
|
2477
|
+
const isDraft = data.task.status === 'draft';
|
|
2478
|
+
printLine(`Created ${isDraft ? 'draft ' : ''}task ${sanitizeTerminalText(data.task.title)} (${sanitizeTerminalText(data.task.id)}) [${sanitizeTerminalText(data.task.status)}]` +
|
|
2166
2479
|
`\n Task ID: ${sanitizeTerminalText(data.task.id)}` +
|
|
2167
2480
|
`\n Dataset ID: ${sanitizeTerminalText(datasetId)}` +
|
|
2168
2481
|
`\n Version: v${data.task.versionNum} (${sanitizeTerminalText(data.task.versionId)})` +
|
|
2169
2482
|
`\n Labels/row: ${data.task.requiredAssignmentsPerRow}` +
|
|
2170
2483
|
`\n Assignments: ${data.assignmentsCreated}` +
|
|
2171
2484
|
(data.warning ? `\n Warning: ${sanitizeTerminalText(data.warning)}` : '') +
|
|
2172
|
-
`\n URL: ${sanitizeTerminalText(taskUrl)}`
|
|
2485
|
+
`\n URL: ${sanitizeTerminalText(taskUrl)}` +
|
|
2486
|
+
(isDraft
|
|
2487
|
+
? `\n\nThis task is a draft. Test it manually before assigning.\nPublish after approval: orizu tasks publish --task ${sanitizeTerminalText(data.task.id)} --assignees <userId1,userId2>`
|
|
2488
|
+
: ''));
|
|
2489
|
+
}
|
|
2490
|
+
async function publishTask() {
|
|
2491
|
+
const taskId = getArg('--task');
|
|
2492
|
+
const assignees = parseCommaSeparated(getArg('--assignees'));
|
|
2493
|
+
if (!taskId || assignees.length === 0) {
|
|
2494
|
+
throw new Error('Usage: orizu tasks publish --task <taskId> --assignees <userId1,userId2> [--json]');
|
|
2495
|
+
}
|
|
2496
|
+
const response = await authedFetch(`/api/cli/tasks/${encodeURIComponent(taskId)}/publish`, {
|
|
2497
|
+
method: 'POST',
|
|
2498
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2499
|
+
body: JSON.stringify({ memberIds: assignees }),
|
|
2500
|
+
});
|
|
2501
|
+
if (!response.ok) {
|
|
2502
|
+
throw new Error(`Failed to publish task: ${await extractErrorMessage(response)}`);
|
|
2503
|
+
}
|
|
2504
|
+
const data = await parseJsonResponse(response, 'Task publish');
|
|
2505
|
+
if (hasArg('--json')) {
|
|
2506
|
+
printLine(JSON.stringify({
|
|
2507
|
+
taskId: data.task.id,
|
|
2508
|
+
status: data.task.status,
|
|
2509
|
+
assignmentsCreated: data.assignmentsCreated,
|
|
2510
|
+
assignmentsProcessed: data.assignmentsProcessed,
|
|
2511
|
+
...(data.assignmentsRemoved !== undefined
|
|
2512
|
+
? { assignmentsRemoved: data.assignmentsRemoved }
|
|
2513
|
+
: {}),
|
|
2514
|
+
...(data.assignmentShortfall !== undefined
|
|
2515
|
+
? { assignmentShortfall: data.assignmentShortfall }
|
|
2516
|
+
: {}),
|
|
2517
|
+
...(data.warning ? { warning: data.warning } : {}),
|
|
2518
|
+
}, null, 2));
|
|
2519
|
+
return;
|
|
2520
|
+
}
|
|
2521
|
+
printLine(`Published task ${sanitizeTerminalText(data.task.id)} [${sanitizeTerminalText(data.task.status)}]` +
|
|
2522
|
+
`\n Assignments: ${data.assignmentsCreated}` +
|
|
2523
|
+
(data.assignmentsRemoved !== undefined
|
|
2524
|
+
? `\n Replaced: ${data.assignmentsRemoved} old assignments removed`
|
|
2525
|
+
: '') +
|
|
2526
|
+
(data.warning ? `\n Warning: ${sanitizeTerminalText(data.warning)}` : ''));
|
|
2173
2527
|
}
|
|
2174
2528
|
async function assignTask() {
|
|
2175
2529
|
const taskId = getArg('--task');
|
|
@@ -2248,6 +2602,35 @@ async function updateTaskStatus(targetStatus) {
|
|
|
2248
2602
|
const action = targetStatus === 'paused' ? 'Paused' : 'Unpaused';
|
|
2249
2603
|
printLine(`${action} task ${sanitizeTerminalText(data.task.id)} [${sanitizeTerminalText(data.task.status)}]`);
|
|
2250
2604
|
}
|
|
2605
|
+
async function setTaskReport() {
|
|
2606
|
+
const taskId = getArg('--task');
|
|
2607
|
+
rejectDashPrefixedOptionValue('--task', taskId);
|
|
2608
|
+
if (!taskId) {
|
|
2609
|
+
throw new Error('Usage: orizu tasks report set --task <taskId> (--report <markdown|@file> | --report-file <path>) [--json]');
|
|
2610
|
+
}
|
|
2611
|
+
const report = readTaskReportInput();
|
|
2612
|
+
if (!report) {
|
|
2613
|
+
throw new Error('Usage: orizu tasks report set --task <taskId> (--report <markdown|@file> | --report-file <path>) [--json]');
|
|
2614
|
+
}
|
|
2615
|
+
const response = await authedFetch(`/api/cli/tasks/${encodeURIComponent(taskId)}/report`, {
|
|
2616
|
+
method: 'PATCH',
|
|
2617
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2618
|
+
body: JSON.stringify({
|
|
2619
|
+
reportMarkdown: report.markdown,
|
|
2620
|
+
reportSourceName: report.sourceName,
|
|
2621
|
+
}),
|
|
2622
|
+
});
|
|
2623
|
+
if (!response.ok) {
|
|
2624
|
+
throw new Error(`Failed to update task report: ${await response.text()}`);
|
|
2625
|
+
}
|
|
2626
|
+
const data = await parseJsonResponse(response, 'Task report update');
|
|
2627
|
+
if (hasJsonFlag()) {
|
|
2628
|
+
printJson(data);
|
|
2629
|
+
return;
|
|
2630
|
+
}
|
|
2631
|
+
printLine(`Uploaded task report for ${sanitizeTerminalText(data.task.id)} ` +
|
|
2632
|
+
`[${sanitizeTerminalText(data.task.status)}]`);
|
|
2633
|
+
}
|
|
2251
2634
|
function defaultAppExportFilename(appName, versionNum) {
|
|
2252
2635
|
const safeName = appName
|
|
2253
2636
|
.trim()
|
|
@@ -3116,10 +3499,37 @@ async function runnersExec() {
|
|
|
3116
3499
|
materializedRunner.cleanup();
|
|
3117
3500
|
}
|
|
3118
3501
|
}
|
|
3502
|
+
function isHelpToken(value) {
|
|
3503
|
+
return value === '--help' || value === '-h';
|
|
3504
|
+
}
|
|
3505
|
+
function extractHelpTarget(args) {
|
|
3506
|
+
if (args[0] === 'help') {
|
|
3507
|
+
return helpTargetFromArgs(args.slice(1));
|
|
3508
|
+
}
|
|
3509
|
+
if (!args.some(isHelpToken)) {
|
|
3510
|
+
return null;
|
|
3511
|
+
}
|
|
3512
|
+
return helpTargetFromArgs(args);
|
|
3513
|
+
}
|
|
3514
|
+
function helpTargetFromArgs(args) {
|
|
3515
|
+
const targetArgs = args.filter(arg => !isHelpToken(arg) && arg !== '--json');
|
|
3516
|
+
const optionIndex = targetArgs.findIndex(arg => arg.startsWith('-'));
|
|
3517
|
+
return optionIndex === -1 ? targetArgs : targetArgs.slice(0, optionIndex);
|
|
3518
|
+
}
|
|
3119
3519
|
export async function main(rawArgs = process.argv.slice(2)) {
|
|
3120
3520
|
const parsed = parseGlobalFlags(rawArgs);
|
|
3121
3521
|
setGlobalFlags(parsed.flags);
|
|
3122
3522
|
cliArgs = parsed.args;
|
|
3523
|
+
cliJsonOutput = false;
|
|
3524
|
+
if (cliArgs[0] === '--json') {
|
|
3525
|
+
cliJsonOutput = true;
|
|
3526
|
+
cliArgs = cliArgs.slice(1);
|
|
3527
|
+
}
|
|
3528
|
+
const helpTarget = extractHelpTarget(cliArgs);
|
|
3529
|
+
if (helpTarget !== null) {
|
|
3530
|
+
printLine(renderHelpForArgs(helpTarget));
|
|
3531
|
+
return;
|
|
3532
|
+
}
|
|
3123
3533
|
const command = cliArgs[0];
|
|
3124
3534
|
const subcommand = cliArgs[1];
|
|
3125
3535
|
if (command === '--version' || command === '-v') {
|
|
@@ -3128,9 +3538,20 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3128
3538
|
}
|
|
3129
3539
|
if (!command) {
|
|
3130
3540
|
printUsage();
|
|
3131
|
-
printOptimizationUsage();
|
|
3132
3541
|
process.exit(1);
|
|
3133
3542
|
}
|
|
3543
|
+
if (command === 'capabilities') {
|
|
3544
|
+
printCapabilities();
|
|
3545
|
+
return;
|
|
3546
|
+
}
|
|
3547
|
+
if (command === 'install-skill') {
|
|
3548
|
+
await installSkillCommand();
|
|
3549
|
+
return;
|
|
3550
|
+
}
|
|
3551
|
+
if (command === 'skills' && subcommand === 'install') {
|
|
3552
|
+
await installSkillCommand();
|
|
3553
|
+
return;
|
|
3554
|
+
}
|
|
3134
3555
|
if (command === 'login') {
|
|
3135
3556
|
await login();
|
|
3136
3557
|
return;
|
|
@@ -3240,6 +3661,10 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3240
3661
|
await setScorerLabel();
|
|
3241
3662
|
return;
|
|
3242
3663
|
}
|
|
3664
|
+
if (command === 'scorers' && subcommand === 'exec') {
|
|
3665
|
+
await execScorer();
|
|
3666
|
+
return;
|
|
3667
|
+
}
|
|
3243
3668
|
if (command === 'runners' && subcommand === 'push') {
|
|
3244
3669
|
await pushRunnerArtifact('runner');
|
|
3245
3670
|
return;
|
|
@@ -3289,6 +3714,10 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3289
3714
|
await createAppFromFile();
|
|
3290
3715
|
return;
|
|
3291
3716
|
}
|
|
3717
|
+
if (command === 'apps' && subcommand === 'preview') {
|
|
3718
|
+
await previewAppFromFile();
|
|
3719
|
+
return;
|
|
3720
|
+
}
|
|
3292
3721
|
if (command === 'apps' && subcommand === 'update') {
|
|
3293
3722
|
await updateAppFromFile();
|
|
3294
3723
|
return;
|
|
@@ -3313,6 +3742,10 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3313
3742
|
await createTask();
|
|
3314
3743
|
return;
|
|
3315
3744
|
}
|
|
3745
|
+
if (command === 'tasks' && subcommand === 'publish') {
|
|
3746
|
+
await publishTask();
|
|
3747
|
+
return;
|
|
3748
|
+
}
|
|
3316
3749
|
if (command === 'tasks' && subcommand === 'assign') {
|
|
3317
3750
|
await assignTask();
|
|
3318
3751
|
return;
|
|
@@ -3321,6 +3754,12 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3321
3754
|
await taskStatus();
|
|
3322
3755
|
return;
|
|
3323
3756
|
}
|
|
3757
|
+
if (command === 'tasks' &&
|
|
3758
|
+
subcommand === 'report' &&
|
|
3759
|
+
(cliArgs[2] === 'set' || cliArgs[2] === 'upload')) {
|
|
3760
|
+
await setTaskReport();
|
|
3761
|
+
return;
|
|
3762
|
+
}
|
|
3324
3763
|
if (command === 'tasks' && subcommand === 'pause') {
|
|
3325
3764
|
await updateTaskStatus('paused');
|
|
3326
3765
|
return;
|
|
@@ -3383,7 +3822,6 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
3383
3822
|
return;
|
|
3384
3823
|
}
|
|
3385
3824
|
printUsage();
|
|
3386
|
-
printOptimizationUsage();
|
|
3387
3825
|
process.exit(1);
|
|
3388
3826
|
}
|
|
3389
3827
|
function isCliEntrypoint() {
|