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/src/index.ts
CHANGED
|
@@ -23,7 +23,10 @@ import { clearServerCredentials, getServerCredentials, saveServerCredentials } f
|
|
|
23
23
|
import { parseDatasetFile } from './file-parser.js'
|
|
24
24
|
import { streamJsonlRowChunks } from './jsonl-stream.js'
|
|
25
25
|
import { parseDatasetReference } from './dataset-download.js'
|
|
26
|
+
import { extractErrorMessage } from './error-response.js'
|
|
26
27
|
import { parseGlobalFlags } from './global-flags.js'
|
|
28
|
+
import { getCapabilities, renderHelpForArgs, renderRootHelp } from './help.js'
|
|
29
|
+
import { runLocalAppPreview } from './preview-runtime.js'
|
|
27
30
|
import {
|
|
28
31
|
assertSecureTokenTransport,
|
|
29
32
|
authedFetch,
|
|
@@ -31,6 +34,14 @@ import {
|
|
|
31
34
|
resolveLoginBaseUrl,
|
|
32
35
|
setGlobalFlags,
|
|
33
36
|
} from './http.js'
|
|
37
|
+
import {
|
|
38
|
+
getSkillInstallPath,
|
|
39
|
+
installSkillTarget,
|
|
40
|
+
isSkillInstallTarget,
|
|
41
|
+
SKILL_INSTALL_TARGETS,
|
|
42
|
+
SkillInstallTarget,
|
|
43
|
+
targetNeedsOverwrite,
|
|
44
|
+
} from './skill-installer.js'
|
|
34
45
|
import { formatTaskCreateError } from './task-create-error.js'
|
|
35
46
|
import { LoginResponse } from './types.js'
|
|
36
47
|
|
|
@@ -163,6 +174,12 @@ interface ScorerSummary {
|
|
|
163
174
|
implementationKind: string
|
|
164
175
|
}
|
|
165
176
|
|
|
177
|
+
interface ScoreSubmitInput {
|
|
178
|
+
resultsJsonl?: string
|
|
179
|
+
aggregate?: Record<string, unknown>
|
|
180
|
+
aggregateWarning?: string
|
|
181
|
+
}
|
|
182
|
+
|
|
166
183
|
interface RunnerExecContext {
|
|
167
184
|
prompt: {
|
|
168
185
|
body: string | null
|
|
@@ -263,14 +280,19 @@ function printVersion() {
|
|
|
263
280
|
}
|
|
264
281
|
|
|
265
282
|
function printUsage() {
|
|
266
|
-
printLine(
|
|
283
|
+
printLine(renderRootHelp())
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function printPreviewUsage() {
|
|
287
|
+
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>]`)
|
|
267
288
|
}
|
|
268
289
|
|
|
269
290
|
function printOptimizationUsage() {
|
|
270
|
-
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]`)
|
|
291
|
+
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]`)
|
|
271
292
|
}
|
|
272
293
|
|
|
273
294
|
let cliArgs = process.argv.slice(2)
|
|
295
|
+
let cliJsonOutput = false
|
|
274
296
|
|
|
275
297
|
function getArg(name: string): string | null {
|
|
276
298
|
const index = cliArgs.indexOf(name)
|
|
@@ -281,6 +303,31 @@ function getArg(name: string): string | null {
|
|
|
281
303
|
return cliArgs[index + 1]
|
|
282
304
|
}
|
|
283
305
|
|
|
306
|
+
function getArgs(name: string): string[] {
|
|
307
|
+
const values: string[] = []
|
|
308
|
+
for (let index = 0; index < cliArgs.length; index += 1) {
|
|
309
|
+
if (cliArgs[index] !== name) {
|
|
310
|
+
continue
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const value = cliArgs[index + 1]
|
|
314
|
+
if (!value || value.startsWith('-')) {
|
|
315
|
+
throw new Error(`Usage: ${name} <value>`)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
values.push(value)
|
|
319
|
+
index += 1
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return values
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function rejectDashPrefixedOptionValue(name: string, value: string | null) {
|
|
326
|
+
if (value && value.startsWith('-')) {
|
|
327
|
+
throw new Error(`Invalid value for ${name}: option values cannot start with a dash`)
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
284
331
|
export function normalizeSlugInput(slug: string): string {
|
|
285
332
|
return slug.trim().toLowerCase()
|
|
286
333
|
}
|
|
@@ -2001,18 +2048,23 @@ async function submitScoreResults() {
|
|
|
2001
2048
|
const candidateId = getArg('--candidate')
|
|
2002
2049
|
|
|
2003
2050
|
if (!resultsPath || !scorerVersionId || (!subjectPromptVersionId && (!optimizationRunId || !candidateId))) {
|
|
2004
|
-
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]')
|
|
2051
|
+
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]')
|
|
2005
2052
|
}
|
|
2006
2053
|
|
|
2007
2054
|
const resultBytes = readSourceBytes(resultsPath)
|
|
2008
2055
|
const raw = resultsPath.endsWith('.gz')
|
|
2009
2056
|
? gunzipSync(resultBytes).toString('utf8')
|
|
2010
2057
|
: resultBytes.toString('utf8')
|
|
2011
|
-
const
|
|
2058
|
+
const scoreInput = normalizeScoreResultsInput(resultsPath, raw, hasArg('--aggregate'))
|
|
2059
|
+
if (scoreInput.aggregateWarning) {
|
|
2060
|
+
console.warn(scoreInput.aggregateWarning)
|
|
2061
|
+
}
|
|
2062
|
+
const aggregatePayload = scoreInput.aggregate || {}
|
|
2012
2063
|
const response = await authedFetch(`/api/cli/scores/submit?project=${encodeURIComponent(project)}`, {
|
|
2013
2064
|
method: 'POST',
|
|
2014
2065
|
headers: { 'Content-Type': 'application/json' },
|
|
2015
2066
|
body: JSON.stringify({
|
|
2067
|
+
...aggregatePayload,
|
|
2016
2068
|
scorerVersionId,
|
|
2017
2069
|
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
2018
2070
|
datasetVersionId: getArg('--dataset-version') || undefined,
|
|
@@ -2020,7 +2072,7 @@ async function submitScoreResults() {
|
|
|
2020
2072
|
splitName: getArg('--split') || undefined,
|
|
2021
2073
|
optimizationRunId: optimizationRunId || undefined,
|
|
2022
2074
|
candidateId: candidateId || undefined,
|
|
2023
|
-
resultsJsonl,
|
|
2075
|
+
resultsJsonl: scoreInput.resultsJsonl,
|
|
2024
2076
|
}),
|
|
2025
2077
|
})
|
|
2026
2078
|
|
|
@@ -2046,25 +2098,161 @@ async function submitScoreResults() {
|
|
|
2046
2098
|
)
|
|
2047
2099
|
}
|
|
2048
2100
|
|
|
2049
|
-
function
|
|
2101
|
+
function looksLikeAggregateScoreObject(value: Record<string, unknown>): boolean {
|
|
2102
|
+
return (
|
|
2103
|
+
value.scoreValue !== undefined ||
|
|
2104
|
+
value.score_value !== undefined ||
|
|
2105
|
+
value.diagnostics !== undefined ||
|
|
2106
|
+
value.feedbackSummary !== undefined ||
|
|
2107
|
+
value.feedback_summary !== undefined ||
|
|
2108
|
+
value.rowEvidence !== undefined ||
|
|
2109
|
+
value.row_evidence !== undefined ||
|
|
2110
|
+
value.dependencyScoreRunIds !== undefined ||
|
|
2111
|
+
value.dependency_score_run_ids !== undefined
|
|
2112
|
+
)
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
function numberFromUnknown(value: unknown): number | null {
|
|
2116
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value
|
|
2117
|
+
if (typeof value === 'string' && value.trim()) {
|
|
2118
|
+
const parsed = Number(value)
|
|
2119
|
+
return Number.isFinite(parsed) ? parsed : null
|
|
2120
|
+
}
|
|
2121
|
+
if (typeof value === 'boolean') return value ? 1 : 0
|
|
2122
|
+
return null
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
function normalizeScoreResultsInput(sourcePath: string, raw: string, aggregateMode = false): ScoreSubmitInput {
|
|
2050
2126
|
const logicalPath = sourcePath.endsWith('.gz') ? sourcePath.slice(0, -3) : sourcePath
|
|
2051
|
-
if (!logicalPath.endsWith('.json')) return raw
|
|
2127
|
+
if (!logicalPath.endsWith('.json')) return { resultsJsonl: raw }
|
|
2052
2128
|
|
|
2053
2129
|
try {
|
|
2054
2130
|
const parsed = JSON.parse(raw) as unknown
|
|
2131
|
+
if (aggregateMode) {
|
|
2132
|
+
if (!isRecord(parsed)) {
|
|
2133
|
+
throw new Error('Aggregate score results JSON must be an object')
|
|
2134
|
+
}
|
|
2135
|
+
return { aggregate: parsed }
|
|
2136
|
+
}
|
|
2137
|
+
if (isRecord(parsed) && looksLikeAggregateScoreObject(parsed)) {
|
|
2138
|
+
return {
|
|
2139
|
+
aggregate: parsed,
|
|
2140
|
+
aggregateWarning: 'Warning: aggregate score JSON detected. Pass --aggregate to make this explicit.',
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2055
2143
|
const rows = Array.isArray(parsed) ? parsed : [parsed]
|
|
2056
2144
|
if (rows.some(row => !isRecord(row))) {
|
|
2057
2145
|
throw new Error('JSON score results must be an object or an array of objects')
|
|
2058
2146
|
}
|
|
2059
|
-
return rows.map(row => JSON.stringify(row)).join('\n')
|
|
2147
|
+
return { resultsJsonl: rows.map(row => JSON.stringify(row)).join('\n') }
|
|
2060
2148
|
} catch (error) {
|
|
2061
2149
|
const message = error instanceof Error ? error.message : String(error)
|
|
2062
2150
|
throw new Error(`Invalid score results JSON '${sourcePath}': ${message}`)
|
|
2063
2151
|
}
|
|
2064
2152
|
}
|
|
2065
2153
|
|
|
2154
|
+
function readOptionalJsonlFile(pathArg: string | null): string | undefined {
|
|
2155
|
+
if (!pathArg) return undefined
|
|
2156
|
+
const bytes = readSourceBytes(pathArg)
|
|
2157
|
+
return pathArg.endsWith('.gz')
|
|
2158
|
+
? gunzipSync(bytes).toString('utf8')
|
|
2159
|
+
: bytes.toString('utf8')
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
function parseAliasAssignments(value: string | null): Record<string, string> {
|
|
2163
|
+
const result: Record<string, string> = {}
|
|
2164
|
+
if (!value) return result
|
|
2165
|
+
for (const item of parseCommaSeparated(value)) {
|
|
2166
|
+
const equalsIndex = item.indexOf('=')
|
|
2167
|
+
if (equalsIndex <= 0 || equalsIndex === item.length - 1) {
|
|
2168
|
+
throw new Error(`Expected alias assignment in form alias=value, got '${item}'`)
|
|
2169
|
+
}
|
|
2170
|
+
result[item.slice(0, equalsIndex)] = item.slice(equalsIndex + 1)
|
|
2171
|
+
}
|
|
2172
|
+
return result
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2175
|
+
function readDependencyResultAssignments(value: string | null): Record<string, string> | undefined {
|
|
2176
|
+
const assignments = parseAliasAssignments(value)
|
|
2177
|
+
const result: Record<string, string> = {}
|
|
2178
|
+
for (const [alias, path] of Object.entries(assignments)) {
|
|
2179
|
+
result[alias] = readOptionalJsonlFile(path) || ''
|
|
2180
|
+
}
|
|
2181
|
+
return Object.keys(result).length > 0 ? result : undefined
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
async function execScorer() {
|
|
2185
|
+
const project = getArg('--project') || await resolveProjectSlug(null)
|
|
2186
|
+
const scorerVersionId = getArg('--scorer-version')
|
|
2187
|
+
const subjectPromptVersionId = getArg('--subject-version') || getArg('--prompt-version')
|
|
2188
|
+
const optimizationRunId = getArg('--optimization-run')
|
|
2189
|
+
const candidateId = getArg('--candidate')
|
|
2190
|
+
const datasetVersionId = getArg('--dataset-version')
|
|
2191
|
+
const splitSetId = getArg('--split-set')
|
|
2192
|
+
const splitName = getArg('--split')
|
|
2193
|
+
const outPath = getArg('--out')
|
|
2194
|
+
|
|
2195
|
+
if (
|
|
2196
|
+
!scorerVersionId ||
|
|
2197
|
+
(!subjectPromptVersionId && (!optimizationRunId || !candidateId)) ||
|
|
2198
|
+
!datasetVersionId ||
|
|
2199
|
+
!splitSetId ||
|
|
2200
|
+
!splitName
|
|
2201
|
+
) {
|
|
2202
|
+
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]')
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
const response = await authedFetch(`/api/cli/scorers/exec?project=${encodeURIComponent(project)}`, {
|
|
2206
|
+
method: 'POST',
|
|
2207
|
+
headers: { 'Content-Type': 'application/json' },
|
|
2208
|
+
body: JSON.stringify({
|
|
2209
|
+
scorerVersionId,
|
|
2210
|
+
subjectPromptVersionId: subjectPromptVersionId || undefined,
|
|
2211
|
+
optimizationRunId: optimizationRunId || undefined,
|
|
2212
|
+
candidateId: candidateId || undefined,
|
|
2213
|
+
datasetVersionId,
|
|
2214
|
+
splitSetId,
|
|
2215
|
+
splitName,
|
|
2216
|
+
submit: !hasArg('--no-submit'),
|
|
2217
|
+
reuseExisting: !hasArg('--no-reuse-existing'),
|
|
2218
|
+
subjectResultsJsonl: readOptionalJsonlFile(getArg('--subject-results') || getArg('--outputs')),
|
|
2219
|
+
dependencyScoreRunIds: parseAliasAssignments(getArg('--dependency-score-run') || getArg('--dependency-score-runs')),
|
|
2220
|
+
dependencyResultsJsonl: readDependencyResultAssignments(getArg('--dependency-results')),
|
|
2221
|
+
}),
|
|
2222
|
+
})
|
|
2223
|
+
|
|
2224
|
+
if (!response.ok) {
|
|
2225
|
+
throw new Error(`Failed to execute scorer: ${await response.text()}`)
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
const data = await parseJsonResponse<Record<string, unknown>>(response, 'Scorer exec')
|
|
2229
|
+
if (outPath) {
|
|
2230
|
+
writeFileSync(expandHomePath(outPath), `${JSON.stringify(data.scoreResult || data, null, 2)}\n`)
|
|
2231
|
+
}
|
|
2232
|
+
if (hasJsonFlag()) {
|
|
2233
|
+
printJson(data)
|
|
2234
|
+
return
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
const scoreRun = isRecord(data.scoreRun) ? data.scoreRun : null
|
|
2238
|
+
const scoreResult = isRecord(data.scoreResult) ? data.scoreResult : null
|
|
2239
|
+
const scoreValue = scoreRun
|
|
2240
|
+
? scoreRun.scoreValue
|
|
2241
|
+
: scoreResult
|
|
2242
|
+
? scoreResult.scoreValue
|
|
2243
|
+
: null
|
|
2244
|
+
if (scoreRun && typeof scoreRun.id === 'string') {
|
|
2245
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} -> score ${sanitizeTerminalText(scoreRun.id)} (${formatPercent(numberFromUnknown(scoreValue))})`)
|
|
2246
|
+
} else {
|
|
2247
|
+
printLine(`Executed scorer ${sanitizeTerminalText(scorerVersionId)} (${formatPercent(numberFromUnknown(scoreValue))})`)
|
|
2248
|
+
}
|
|
2249
|
+
if (outPath) {
|
|
2250
|
+
printLine(`Wrote scorer result to ${sanitizeTerminalText(outPath)}`)
|
|
2251
|
+
}
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2066
2254
|
type OptimizationLifecycleAction = 'pause' | 'resume' | 'finish' | 'fail' | 'cancel'
|
|
2067
|
-
const
|
|
2255
|
+
const MARKDOWN_REPORT_MAX_BYTES = 2 * 1024 * 1024
|
|
2068
2256
|
|
|
2069
2257
|
function parseOptionalNumberFlag(name: string): number | undefined {
|
|
2070
2258
|
const value = getArg(name)
|
|
@@ -2084,10 +2272,15 @@ function hasObjectKeys(value: Record<string, unknown>): boolean {
|
|
|
2084
2272
|
return Object.keys(value).length > 0
|
|
2085
2273
|
}
|
|
2086
2274
|
|
|
2087
|
-
function
|
|
2275
|
+
function readMarkdownReportInput(
|
|
2276
|
+
reportLabel: 'Optimization' | 'Task'
|
|
2277
|
+
): { markdown: string; sourceName: string | null } | null {
|
|
2088
2278
|
const report = getArg('--report')
|
|
2089
2279
|
const reportFile = getArg('--report-file')
|
|
2090
2280
|
|
|
2281
|
+
rejectDashPrefixedOptionValue('--report', report)
|
|
2282
|
+
rejectDashPrefixedOptionValue('--report-file', reportFile)
|
|
2283
|
+
|
|
2091
2284
|
if (report && reportFile) {
|
|
2092
2285
|
throw new Error('Use either --report or --report-file, not both')
|
|
2093
2286
|
}
|
|
@@ -2114,16 +2307,24 @@ function readOptimizationReportInput(): { markdown: string; sourceName: string |
|
|
|
2114
2307
|
}
|
|
2115
2308
|
|
|
2116
2309
|
if (!markdown.trim()) {
|
|
2117
|
-
throw new Error(
|
|
2310
|
+
throw new Error(`${reportLabel} report markdown must not be blank`)
|
|
2118
2311
|
}
|
|
2119
2312
|
|
|
2120
|
-
if (Buffer.byteLength(markdown, 'utf8') >
|
|
2121
|
-
throw new Error(
|
|
2313
|
+
if (Buffer.byteLength(markdown, 'utf8') > MARKDOWN_REPORT_MAX_BYTES) {
|
|
2314
|
+
throw new Error(`${reportLabel} report exceeds ${MARKDOWN_REPORT_MAX_BYTES} bytes`)
|
|
2122
2315
|
}
|
|
2123
2316
|
|
|
2124
2317
|
return { markdown, sourceName }
|
|
2125
2318
|
}
|
|
2126
2319
|
|
|
2320
|
+
function readOptimizationReportInput(): { markdown: string; sourceName: string | null } | null {
|
|
2321
|
+
return readMarkdownReportInput('Optimization')
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
function readTaskReportInput(): { markdown: string; sourceName: string | null } | null {
|
|
2325
|
+
return readMarkdownReportInput('Task')
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2127
2328
|
async function startOptimizationRun() {
|
|
2128
2329
|
const project = getArg('--project') || await resolveProjectSlug(null)
|
|
2129
2330
|
const optimizerVersionId = getArg('--optimizer-version')
|
|
@@ -2521,13 +2722,120 @@ function readSourceBytes(pathArg: string): Buffer {
|
|
|
2521
2722
|
}
|
|
2522
2723
|
|
|
2523
2724
|
function hasJsonFlag(): boolean {
|
|
2524
|
-
return hasArg('--json')
|
|
2725
|
+
return cliJsonOutput || hasArg('--json')
|
|
2525
2726
|
}
|
|
2526
2727
|
|
|
2527
2728
|
function printJson(value: Record<string, unknown>) {
|
|
2528
2729
|
printLine(JSON.stringify(value))
|
|
2529
2730
|
}
|
|
2530
2731
|
|
|
2732
|
+
function printCapabilities() {
|
|
2733
|
+
const capabilities = getCapabilities(getCliVersion())
|
|
2734
|
+
if (hasJsonFlag()) {
|
|
2735
|
+
printLine(JSON.stringify(capabilities))
|
|
2736
|
+
return
|
|
2737
|
+
}
|
|
2738
|
+
|
|
2739
|
+
printLine('orizu capabilities')
|
|
2740
|
+
printLine('')
|
|
2741
|
+
printLine('Run `orizu capabilities --json` for a machine-readable command manifest.')
|
|
2742
|
+
printLine('')
|
|
2743
|
+
for (const command of capabilities.commands) {
|
|
2744
|
+
printLine(` ${command.name.padEnd(34)} ${command.help}`)
|
|
2745
|
+
}
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2748
|
+
async function askYesNo(question: string, defaultYes: boolean): Promise<boolean> {
|
|
2749
|
+
const rl = createInterface({ input, output })
|
|
2750
|
+
try {
|
|
2751
|
+
const suffix = defaultYes ? 'Y/n' : 'y/N'
|
|
2752
|
+
const answer = (await rl.question(`${question} (${suffix}) `)).trim().toLowerCase()
|
|
2753
|
+
if (!answer) {
|
|
2754
|
+
return defaultYes
|
|
2755
|
+
}
|
|
2756
|
+
return answer === 'y' || answer === 'yes'
|
|
2757
|
+
} finally {
|
|
2758
|
+
rl.close()
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
|
|
2762
|
+
async function promptSkillInstallTargets(): Promise<SkillInstallTarget[]> {
|
|
2763
|
+
if (!isInteractiveTerminal()) {
|
|
2764
|
+
throw new Error(
|
|
2765
|
+
`Usage: orizu install-skill --target <${SKILL_INSTALL_TARGETS.join('|')}> [--yes] [--dry-run]`
|
|
2766
|
+
)
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
printLine('Where should the Orizu CLI skill be installed?')
|
|
2770
|
+
const targets: SkillInstallTarget[] = []
|
|
2771
|
+
for (const target of SKILL_INSTALL_TARGETS) {
|
|
2772
|
+
const defaultYes = target === 'agent-user'
|
|
2773
|
+
if (await askYesNo(` Install to ${target}?`, defaultYes)) {
|
|
2774
|
+
targets.push(target)
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
|
|
2778
|
+
return targets
|
|
2779
|
+
}
|
|
2780
|
+
|
|
2781
|
+
function parseSkillInstallTargets(): SkillInstallTarget[] {
|
|
2782
|
+
const rawTargets = getArgs('--target')
|
|
2783
|
+
const targets: SkillInstallTarget[] = []
|
|
2784
|
+
for (const target of rawTargets) {
|
|
2785
|
+
if (!isSkillInstallTarget(target)) {
|
|
2786
|
+
throw new Error(
|
|
2787
|
+
`Unknown skill install target '${target}'. Available targets: ${SKILL_INSTALL_TARGETS.join(', ')}`
|
|
2788
|
+
)
|
|
2789
|
+
}
|
|
2790
|
+
if (!targets.includes(target)) {
|
|
2791
|
+
targets.push(target)
|
|
2792
|
+
}
|
|
2793
|
+
}
|
|
2794
|
+
return targets
|
|
2795
|
+
}
|
|
2796
|
+
|
|
2797
|
+
function formatSkillInstallAction(action: string): string {
|
|
2798
|
+
if (action === 'created') return 'Wrote'
|
|
2799
|
+
if (action === 'updated') return 'Updated'
|
|
2800
|
+
if (action === 'would-create') return 'Would write'
|
|
2801
|
+
return 'Would update'
|
|
2802
|
+
}
|
|
2803
|
+
|
|
2804
|
+
async function installSkillCommand() {
|
|
2805
|
+
const skipConfirm = hasArg('--yes')
|
|
2806
|
+
const dryRun = hasArg('--dry-run')
|
|
2807
|
+
let targets = parseSkillInstallTargets()
|
|
2808
|
+
if (targets.length === 0) {
|
|
2809
|
+
targets = await promptSkillInstallTargets()
|
|
2810
|
+
}
|
|
2811
|
+
|
|
2812
|
+
if (targets.length === 0) {
|
|
2813
|
+
printLine('No targets selected; nothing to do.')
|
|
2814
|
+
return
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
for (const target of targets) {
|
|
2818
|
+
let overwrite = skipConfirm
|
|
2819
|
+
const installPath = getSkillInstallPath(target)
|
|
2820
|
+
if (!dryRun && !overwrite && targetNeedsOverwrite(target)) {
|
|
2821
|
+
if (!isInteractiveTerminal()) {
|
|
2822
|
+
throw new Error(`${installPath} already exists. Pass --yes to replace it.`)
|
|
2823
|
+
}
|
|
2824
|
+
overwrite = await askYesNo(`Replace ${installPath}?`, true)
|
|
2825
|
+
if (!overwrite) {
|
|
2826
|
+
printLine(`Skipped ${installPath}`)
|
|
2827
|
+
continue
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
|
|
2831
|
+
const result = installSkillTarget(target, {
|
|
2832
|
+
overwrite,
|
|
2833
|
+
dryRun,
|
|
2834
|
+
})
|
|
2835
|
+
printLine(`${formatSkillInstallAction(result.action)} ${result.path}`)
|
|
2836
|
+
}
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2531
2839
|
function readJsonFile(pathArg: string): Record<string, unknown> {
|
|
2532
2840
|
const raw = readSourceFile(pathArg)
|
|
2533
2841
|
try {
|
|
@@ -2789,15 +3097,61 @@ async function createAppFromFile() {
|
|
|
2789
3097
|
}
|
|
2790
3098
|
|
|
2791
3099
|
const data = await parseJsonResponse<{
|
|
2792
|
-
app: { id: string; name: string; versionNum: number; componentName?: string }
|
|
3100
|
+
app: { id: string; name: string; versionNum: number; componentName?: string; url?: string }
|
|
2793
3101
|
warnings?: string[]
|
|
2794
3102
|
}>(response, 'App create')
|
|
2795
3103
|
printLine(`Created app ${sanitizeTerminalText(data.app.name)} (${sanitizeTerminalText(data.app.id)}) v${data.app.versionNum}`)
|
|
3104
|
+
if (data.app.url) {
|
|
3105
|
+
printLine(`View app: ${formatTerminalLink(data.app.url)}`)
|
|
3106
|
+
}
|
|
2796
3107
|
if (data.warnings?.length) {
|
|
2797
3108
|
printLine(`Warnings: ${sanitizeTerminalText(data.warnings.join('; '))}`)
|
|
2798
3109
|
}
|
|
2799
3110
|
}
|
|
2800
3111
|
|
|
3112
|
+
async function previewAppFromFile() {
|
|
3113
|
+
const filePath = getArg('--file')
|
|
3114
|
+
const inputSchemaPath = getArg('--input-schema')
|
|
3115
|
+
const outputSchemaPath = getArg('--output-schema')
|
|
3116
|
+
const sampleRowPath = getArg('--sample-row')
|
|
3117
|
+
const screenshotPath = getArg('--screenshot')
|
|
3118
|
+
const component = getArg('--component') || undefined
|
|
3119
|
+
const headed = hasArg('--headed')
|
|
3120
|
+
const keepOpen = hasArg('--keep-open')
|
|
3121
|
+
|
|
3122
|
+
if (!filePath || !inputSchemaPath || !outputSchemaPath || !sampleRowPath) {
|
|
3123
|
+
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>]')
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
const expandedFilePath = realpathSync(expandHomePath(filePath))
|
|
3127
|
+
const inputJsonSchema = readJsonFile(inputSchemaPath)
|
|
3128
|
+
const outputJsonSchema = readJsonFile(outputSchemaPath)
|
|
3129
|
+
const sampleRow = readJsonFile(sampleRowPath)
|
|
3130
|
+
const expandedScreenshotPath = screenshotPath ? expandHomePath(screenshotPath) : undefined
|
|
3131
|
+
|
|
3132
|
+
const result = await runLocalAppPreview({
|
|
3133
|
+
filePath: expandedFilePath,
|
|
3134
|
+
inputSchema: inputJsonSchema,
|
|
3135
|
+
outputSchema: outputJsonSchema,
|
|
3136
|
+
sampleRow,
|
|
3137
|
+
screenshotPath: expandedScreenshotPath,
|
|
3138
|
+
componentName: component,
|
|
3139
|
+
headed,
|
|
3140
|
+
keepOpen,
|
|
3141
|
+
})
|
|
3142
|
+
|
|
3143
|
+
printLine(`Preview rendered: ${formatTerminalLink(result.url)}`)
|
|
3144
|
+
if (result.screenshotPath) {
|
|
3145
|
+
printLine(`Screenshot: ${sanitizeTerminalText(result.screenshotPath)}`)
|
|
3146
|
+
}
|
|
3147
|
+
if (headed || keepOpen) {
|
|
3148
|
+
printLine('Headed preview is running. Close Chromium or stop the command when you are done.')
|
|
3149
|
+
}
|
|
3150
|
+
if (result.warnings.length > 0) {
|
|
3151
|
+
printLine(`Warnings: ${sanitizeTerminalText(result.warnings.join('; '))}`)
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
|
|
2801
3155
|
async function updateAppFromFile() {
|
|
2802
3156
|
const filePath = getArg('--file')
|
|
2803
3157
|
const inputSchemaPath = getArg('--input-schema')
|
|
@@ -2905,6 +3259,7 @@ async function createTask() {
|
|
|
2905
3259
|
const appId = getArg('--app')
|
|
2906
3260
|
const title = getArg('--title')
|
|
2907
3261
|
const assignees = parseCommaSeparated(getArg('--assignees'))
|
|
3262
|
+
const publish = hasArg('--publish')
|
|
2908
3263
|
const versionArg = getArg('--version')
|
|
2909
3264
|
const instructions = getArg('--instructions')
|
|
2910
3265
|
const labelsPerItemArg = getArg('--labels-per-item')
|
|
@@ -2913,8 +3268,8 @@ async function createTask() {
|
|
|
2913
3268
|
const versionNum =
|
|
2914
3269
|
Number.isInteger(parsedVersionNum) && parsedVersionNum > 0 ? parsedVersionNum : null
|
|
2915
3270
|
|
|
2916
|
-
if (!projectSlug || !datasetId || !appId || !title || assignees.length === 0) {
|
|
2917
|
-
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]')
|
|
3271
|
+
if (!projectSlug || !datasetId || !appId || !title || (publish && assignees.length === 0)) {
|
|
3272
|
+
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]')
|
|
2918
3273
|
}
|
|
2919
3274
|
|
|
2920
3275
|
if (versionArg && versionNum === null) {
|
|
@@ -2931,6 +3286,7 @@ async function createTask() {
|
|
|
2931
3286
|
versionNum,
|
|
2932
3287
|
title,
|
|
2933
3288
|
memberIds: assignees,
|
|
3289
|
+
publish,
|
|
2934
3290
|
instructions,
|
|
2935
3291
|
requiredAssignmentsPerRow: labelsPerItem,
|
|
2936
3292
|
}),
|
|
@@ -2973,6 +3329,13 @@ async function createTask() {
|
|
|
2973
3329
|
status: data.task.status,
|
|
2974
3330
|
requiredAssignmentsPerRow: data.task.requiredAssignmentsPerRow,
|
|
2975
3331
|
assignmentsCreated: data.assignmentsCreated,
|
|
3332
|
+
draft: data.task.status === 'draft',
|
|
3333
|
+
...(data.task.status === 'draft'
|
|
3334
|
+
? {
|
|
3335
|
+
message: 'Draft created. Test it manually before assigning.',
|
|
3336
|
+
publishCommand: `orizu tasks publish --task ${data.task.id} --assignees <userId1,userId2>`,
|
|
3337
|
+
}
|
|
3338
|
+
: {}),
|
|
2976
3339
|
...(data.assignmentShortfall !== undefined ? { assignmentShortfall: data.assignmentShortfall } : {}),
|
|
2977
3340
|
...(data.warning ? { warning: data.warning } : {}),
|
|
2978
3341
|
}, null, 2))
|
|
@@ -2981,15 +3344,76 @@ async function createTask() {
|
|
|
2981
3344
|
|
|
2982
3345
|
const baseUrl = getBaseUrl()
|
|
2983
3346
|
const taskUrl = `${baseUrl}/d/${projectSlug}/tasks/${data.task.id}`
|
|
3347
|
+
const isDraft = data.task.status === 'draft'
|
|
2984
3348
|
printLine(
|
|
2985
|
-
`Created task ${sanitizeTerminalText(data.task.title)} (${sanitizeTerminalText(data.task.id)}) [${sanitizeTerminalText(data.task.status)}]` +
|
|
3349
|
+
`Created ${isDraft ? 'draft ' : ''}task ${sanitizeTerminalText(data.task.title)} (${sanitizeTerminalText(data.task.id)}) [${sanitizeTerminalText(data.task.status)}]` +
|
|
2986
3350
|
`\n Task ID: ${sanitizeTerminalText(data.task.id)}` +
|
|
2987
3351
|
`\n Dataset ID: ${sanitizeTerminalText(datasetId)}` +
|
|
2988
3352
|
`\n Version: v${data.task.versionNum} (${sanitizeTerminalText(data.task.versionId)})` +
|
|
2989
3353
|
`\n Labels/row: ${data.task.requiredAssignmentsPerRow}` +
|
|
2990
3354
|
`\n Assignments: ${data.assignmentsCreated}` +
|
|
2991
3355
|
(data.warning ? `\n Warning: ${sanitizeTerminalText(data.warning)}` : '') +
|
|
2992
|
-
`\n URL: ${sanitizeTerminalText(taskUrl)}`
|
|
3356
|
+
`\n URL: ${sanitizeTerminalText(taskUrl)}` +
|
|
3357
|
+
(isDraft
|
|
3358
|
+
? `\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>`
|
|
3359
|
+
: '')
|
|
3360
|
+
)
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3363
|
+
async function publishTask() {
|
|
3364
|
+
const taskId = getArg('--task')
|
|
3365
|
+
const assignees = parseCommaSeparated(getArg('--assignees'))
|
|
3366
|
+
|
|
3367
|
+
if (!taskId || assignees.length === 0) {
|
|
3368
|
+
throw new Error('Usage: orizu tasks publish --task <taskId> --assignees <userId1,userId2> [--json]')
|
|
3369
|
+
}
|
|
3370
|
+
|
|
3371
|
+
const response = await authedFetch(`/api/cli/tasks/${encodeURIComponent(taskId)}/publish`, {
|
|
3372
|
+
method: 'POST',
|
|
3373
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3374
|
+
body: JSON.stringify({ memberIds: assignees }),
|
|
3375
|
+
})
|
|
3376
|
+
|
|
3377
|
+
if (!response.ok) {
|
|
3378
|
+
throw new Error(`Failed to publish task: ${await extractErrorMessage(response)}`)
|
|
3379
|
+
}
|
|
3380
|
+
|
|
3381
|
+
const data = await parseJsonResponse<{
|
|
3382
|
+
task: { id: string; status: string }
|
|
3383
|
+
assignmentsProcessed: number
|
|
3384
|
+
assignmentsCreated: number
|
|
3385
|
+
assignmentsRemoved?: number
|
|
3386
|
+
assignmentShortfall?: number
|
|
3387
|
+
warning?: string
|
|
3388
|
+
}>(
|
|
3389
|
+
response,
|
|
3390
|
+
'Task publish'
|
|
3391
|
+
)
|
|
3392
|
+
|
|
3393
|
+
if (hasArg('--json')) {
|
|
3394
|
+
printLine(JSON.stringify({
|
|
3395
|
+
taskId: data.task.id,
|
|
3396
|
+
status: data.task.status,
|
|
3397
|
+
assignmentsCreated: data.assignmentsCreated,
|
|
3398
|
+
assignmentsProcessed: data.assignmentsProcessed,
|
|
3399
|
+
...(data.assignmentsRemoved !== undefined
|
|
3400
|
+
? { assignmentsRemoved: data.assignmentsRemoved }
|
|
3401
|
+
: {}),
|
|
3402
|
+
...(data.assignmentShortfall !== undefined
|
|
3403
|
+
? { assignmentShortfall: data.assignmentShortfall }
|
|
3404
|
+
: {}),
|
|
3405
|
+
...(data.warning ? { warning: data.warning } : {}),
|
|
3406
|
+
}, null, 2))
|
|
3407
|
+
return
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3410
|
+
printLine(
|
|
3411
|
+
`Published task ${sanitizeTerminalText(data.task.id)} [${sanitizeTerminalText(data.task.status)}]` +
|
|
3412
|
+
`\n Assignments: ${data.assignmentsCreated}` +
|
|
3413
|
+
(data.assignmentsRemoved !== undefined
|
|
3414
|
+
? `\n Replaced: ${data.assignmentsRemoved} old assignments removed`
|
|
3415
|
+
: '') +
|
|
3416
|
+
(data.warning ? `\n Warning: ${sanitizeTerminalText(data.warning)}` : '')
|
|
2993
3417
|
)
|
|
2994
3418
|
}
|
|
2995
3419
|
|
|
@@ -3082,6 +3506,58 @@ async function updateTaskStatus(targetStatus: 'paused' | 'active') {
|
|
|
3082
3506
|
printLine(`${action} task ${sanitizeTerminalText(data.task.id)} [${sanitizeTerminalText(data.task.status)}]`)
|
|
3083
3507
|
}
|
|
3084
3508
|
|
|
3509
|
+
async function setTaskReport() {
|
|
3510
|
+
const taskId = getArg('--task')
|
|
3511
|
+
rejectDashPrefixedOptionValue('--task', taskId)
|
|
3512
|
+
if (!taskId) {
|
|
3513
|
+
throw new Error(
|
|
3514
|
+
'Usage: orizu tasks report set --task <taskId> (--report <markdown|@file> | --report-file <path>) [--json]'
|
|
3515
|
+
)
|
|
3516
|
+
}
|
|
3517
|
+
|
|
3518
|
+
const report = readTaskReportInput()
|
|
3519
|
+
if (!report) {
|
|
3520
|
+
throw new Error(
|
|
3521
|
+
'Usage: orizu tasks report set --task <taskId> (--report <markdown|@file> | --report-file <path>) [--json]'
|
|
3522
|
+
)
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
const response = await authedFetch(`/api/cli/tasks/${encodeURIComponent(taskId)}/report`, {
|
|
3526
|
+
method: 'PATCH',
|
|
3527
|
+
headers: { 'Content-Type': 'application/json' },
|
|
3528
|
+
body: JSON.stringify({
|
|
3529
|
+
reportMarkdown: report.markdown,
|
|
3530
|
+
reportSourceName: report.sourceName,
|
|
3531
|
+
}),
|
|
3532
|
+
})
|
|
3533
|
+
|
|
3534
|
+
if (!response.ok) {
|
|
3535
|
+
throw new Error(`Failed to update task report: ${await response.text()}`)
|
|
3536
|
+
}
|
|
3537
|
+
|
|
3538
|
+
const data = await parseJsonResponse<{
|
|
3539
|
+
task: {
|
|
3540
|
+
id: string
|
|
3541
|
+
status: string
|
|
3542
|
+
report: {
|
|
3543
|
+
markdown: string
|
|
3544
|
+
sourceName: string | null
|
|
3545
|
+
createdAt: string | null
|
|
3546
|
+
}
|
|
3547
|
+
}
|
|
3548
|
+
}>(response, 'Task report update')
|
|
3549
|
+
|
|
3550
|
+
if (hasJsonFlag()) {
|
|
3551
|
+
printJson(data)
|
|
3552
|
+
return
|
|
3553
|
+
}
|
|
3554
|
+
|
|
3555
|
+
printLine(
|
|
3556
|
+
`Uploaded task report for ${sanitizeTerminalText(data.task.id)} ` +
|
|
3557
|
+
`[${sanitizeTerminalText(data.task.status)}]`
|
|
3558
|
+
)
|
|
3559
|
+
}
|
|
3560
|
+
|
|
3085
3561
|
interface AppDetailPayload {
|
|
3086
3562
|
id: string
|
|
3087
3563
|
name: string
|
|
@@ -4236,11 +4712,45 @@ async function runnersExec() {
|
|
|
4236
4712
|
}
|
|
4237
4713
|
}
|
|
4238
4714
|
|
|
4715
|
+
function isHelpToken(value: string): boolean {
|
|
4716
|
+
return value === '--help' || value === '-h'
|
|
4717
|
+
}
|
|
4718
|
+
|
|
4719
|
+
function extractHelpTarget(args: string[]): string[] | null {
|
|
4720
|
+
if (args[0] === 'help') {
|
|
4721
|
+
return helpTargetFromArgs(args.slice(1))
|
|
4722
|
+
}
|
|
4723
|
+
|
|
4724
|
+
if (!args.some(isHelpToken)) {
|
|
4725
|
+
return null
|
|
4726
|
+
}
|
|
4727
|
+
|
|
4728
|
+
return helpTargetFromArgs(args)
|
|
4729
|
+
}
|
|
4730
|
+
|
|
4731
|
+
function helpTargetFromArgs(args: string[]): string[] {
|
|
4732
|
+
const targetArgs = args.filter(arg => !isHelpToken(arg) && arg !== '--json')
|
|
4733
|
+
const optionIndex = targetArgs.findIndex(arg => arg.startsWith('-'))
|
|
4734
|
+
return optionIndex === -1 ? targetArgs : targetArgs.slice(0, optionIndex)
|
|
4735
|
+
}
|
|
4736
|
+
|
|
4239
4737
|
export async function main(rawArgs = process.argv.slice(2)) {
|
|
4240
4738
|
const parsed = parseGlobalFlags(rawArgs)
|
|
4241
4739
|
setGlobalFlags(parsed.flags)
|
|
4242
4740
|
cliArgs = parsed.args
|
|
4243
4741
|
|
|
4742
|
+
cliJsonOutput = false
|
|
4743
|
+
if (cliArgs[0] === '--json') {
|
|
4744
|
+
cliJsonOutput = true
|
|
4745
|
+
cliArgs = cliArgs.slice(1)
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
const helpTarget = extractHelpTarget(cliArgs)
|
|
4749
|
+
if (helpTarget !== null) {
|
|
4750
|
+
printLine(renderHelpForArgs(helpTarget))
|
|
4751
|
+
return
|
|
4752
|
+
}
|
|
4753
|
+
|
|
4244
4754
|
const command = cliArgs[0]
|
|
4245
4755
|
const subcommand = cliArgs[1]
|
|
4246
4756
|
|
|
@@ -4251,10 +4761,24 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4251
4761
|
|
|
4252
4762
|
if (!command) {
|
|
4253
4763
|
printUsage()
|
|
4254
|
-
printOptimizationUsage()
|
|
4255
4764
|
process.exit(1)
|
|
4256
4765
|
}
|
|
4257
4766
|
|
|
4767
|
+
if (command === 'capabilities') {
|
|
4768
|
+
printCapabilities()
|
|
4769
|
+
return
|
|
4770
|
+
}
|
|
4771
|
+
|
|
4772
|
+
if (command === 'install-skill') {
|
|
4773
|
+
await installSkillCommand()
|
|
4774
|
+
return
|
|
4775
|
+
}
|
|
4776
|
+
|
|
4777
|
+
if (command === 'skills' && subcommand === 'install') {
|
|
4778
|
+
await installSkillCommand()
|
|
4779
|
+
return
|
|
4780
|
+
}
|
|
4781
|
+
|
|
4258
4782
|
if (command === 'login') {
|
|
4259
4783
|
await login()
|
|
4260
4784
|
return
|
|
@@ -4388,6 +4912,11 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4388
4912
|
return
|
|
4389
4913
|
}
|
|
4390
4914
|
|
|
4915
|
+
if (command === 'scorers' && subcommand === 'exec') {
|
|
4916
|
+
await execScorer()
|
|
4917
|
+
return
|
|
4918
|
+
}
|
|
4919
|
+
|
|
4391
4920
|
if (command === 'runners' && subcommand === 'push') {
|
|
4392
4921
|
await pushRunnerArtifact('runner')
|
|
4393
4922
|
return
|
|
@@ -4452,6 +4981,11 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4452
4981
|
return
|
|
4453
4982
|
}
|
|
4454
4983
|
|
|
4984
|
+
if (command === 'apps' && subcommand === 'preview') {
|
|
4985
|
+
await previewAppFromFile()
|
|
4986
|
+
return
|
|
4987
|
+
}
|
|
4988
|
+
|
|
4455
4989
|
if (command === 'apps' && subcommand === 'update') {
|
|
4456
4990
|
await updateAppFromFile()
|
|
4457
4991
|
return
|
|
@@ -4482,6 +5016,11 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4482
5016
|
return
|
|
4483
5017
|
}
|
|
4484
5018
|
|
|
5019
|
+
if (command === 'tasks' && subcommand === 'publish') {
|
|
5020
|
+
await publishTask()
|
|
5021
|
+
return
|
|
5022
|
+
}
|
|
5023
|
+
|
|
4485
5024
|
if (command === 'tasks' && subcommand === 'assign') {
|
|
4486
5025
|
await assignTask()
|
|
4487
5026
|
return
|
|
@@ -4492,6 +5031,15 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4492
5031
|
return
|
|
4493
5032
|
}
|
|
4494
5033
|
|
|
5034
|
+
if (
|
|
5035
|
+
command === 'tasks' &&
|
|
5036
|
+
subcommand === 'report' &&
|
|
5037
|
+
(cliArgs[2] === 'set' || cliArgs[2] === 'upload')
|
|
5038
|
+
) {
|
|
5039
|
+
await setTaskReport()
|
|
5040
|
+
return
|
|
5041
|
+
}
|
|
5042
|
+
|
|
4495
5043
|
if (command === 'tasks' && subcommand === 'pause') {
|
|
4496
5044
|
await updateTaskStatus('paused')
|
|
4497
5045
|
return
|
|
@@ -4569,7 +5117,6 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4569
5117
|
}
|
|
4570
5118
|
|
|
4571
5119
|
printUsage()
|
|
4572
|
-
printOptimizationUsage()
|
|
4573
5120
|
process.exit(1)
|
|
4574
5121
|
}
|
|
4575
5122
|
|