orizu 0.3.5 → 0.3.7
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 +25 -3
- package/dist/help.js +611 -0
- package/dist/index.js +268 -15
- package/dist/skill-installer.js +180 -0
- package/package.json +3 -3
- package/scripts/vendor-orizu-skill.mjs +54 -0
- package/src/help.ts +676 -0
- package/src/index.ts +353 -15
- package/src/skill-installer.ts +260 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/__init__.py +4 -0
- package/vendor/orizu-gepa-python/src/orizu_gepa/cli.py +24 -1
- package/vendor/orizu-gepa-python/src/orizu_gepa/optimizer.py +469 -21
- package/vendor/skills/orizu-cli/SKILL.md +186 -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 +325 -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 +832 -0
- package/vendor/skills/orizu-cli/scripts/test-app.mjs +492 -0
package/src/index.ts
CHANGED
|
@@ -23,7 +23,9 @@ 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'
|
|
27
29
|
import { runLocalAppPreview } from './preview-runtime.js'
|
|
28
30
|
import {
|
|
29
31
|
assertSecureTokenTransport,
|
|
@@ -32,6 +34,14 @@ import {
|
|
|
32
34
|
resolveLoginBaseUrl,
|
|
33
35
|
setGlobalFlags,
|
|
34
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'
|
|
35
45
|
import { formatTaskCreateError } from './task-create-error.js'
|
|
36
46
|
import { LoginResponse } from './types.js'
|
|
37
47
|
|
|
@@ -270,8 +280,7 @@ function printVersion() {
|
|
|
270
280
|
}
|
|
271
281
|
|
|
272
282
|
function printUsage() {
|
|
273
|
-
printLine(
|
|
274
|
-
printPreviewUsage()
|
|
283
|
+
printLine(renderRootHelp())
|
|
275
284
|
}
|
|
276
285
|
|
|
277
286
|
function printPreviewUsage() {
|
|
@@ -279,10 +288,11 @@ function printPreviewUsage() {
|
|
|
279
288
|
}
|
|
280
289
|
|
|
281
290
|
function printOptimizationUsage() {
|
|
282
|
-
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] [--num-threads auto|N] [--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]`)
|
|
283
292
|
}
|
|
284
293
|
|
|
285
294
|
let cliArgs = process.argv.slice(2)
|
|
295
|
+
let cliJsonOutput = false
|
|
286
296
|
|
|
287
297
|
function getArg(name: string): string | null {
|
|
288
298
|
const index = cliArgs.indexOf(name)
|
|
@@ -293,6 +303,31 @@ function getArg(name: string): string | null {
|
|
|
293
303
|
return cliArgs[index + 1]
|
|
294
304
|
}
|
|
295
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
|
+
|
|
296
331
|
export function normalizeSlugInput(slug: string): string {
|
|
297
332
|
return slug.trim().toLowerCase()
|
|
298
333
|
}
|
|
@@ -2217,7 +2252,7 @@ async function execScorer() {
|
|
|
2217
2252
|
}
|
|
2218
2253
|
|
|
2219
2254
|
type OptimizationLifecycleAction = 'pause' | 'resume' | 'finish' | 'fail' | 'cancel'
|
|
2220
|
-
const
|
|
2255
|
+
const MARKDOWN_REPORT_MAX_BYTES = 2 * 1024 * 1024
|
|
2221
2256
|
|
|
2222
2257
|
function parseOptionalNumberFlag(name: string): number | undefined {
|
|
2223
2258
|
const value = getArg(name)
|
|
@@ -2237,10 +2272,15 @@ function hasObjectKeys(value: Record<string, unknown>): boolean {
|
|
|
2237
2272
|
return Object.keys(value).length > 0
|
|
2238
2273
|
}
|
|
2239
2274
|
|
|
2240
|
-
function
|
|
2275
|
+
function readMarkdownReportInput(
|
|
2276
|
+
reportLabel: 'Optimization' | 'Task'
|
|
2277
|
+
): { markdown: string; sourceName: string | null } | null {
|
|
2241
2278
|
const report = getArg('--report')
|
|
2242
2279
|
const reportFile = getArg('--report-file')
|
|
2243
2280
|
|
|
2281
|
+
rejectDashPrefixedOptionValue('--report', report)
|
|
2282
|
+
rejectDashPrefixedOptionValue('--report-file', reportFile)
|
|
2283
|
+
|
|
2244
2284
|
if (report && reportFile) {
|
|
2245
2285
|
throw new Error('Use either --report or --report-file, not both')
|
|
2246
2286
|
}
|
|
@@ -2267,16 +2307,24 @@ function readOptimizationReportInput(): { markdown: string; sourceName: string |
|
|
|
2267
2307
|
}
|
|
2268
2308
|
|
|
2269
2309
|
if (!markdown.trim()) {
|
|
2270
|
-
throw new Error(
|
|
2310
|
+
throw new Error(`${reportLabel} report markdown must not be blank`)
|
|
2271
2311
|
}
|
|
2272
2312
|
|
|
2273
|
-
if (Buffer.byteLength(markdown, 'utf8') >
|
|
2274
|
-
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`)
|
|
2275
2315
|
}
|
|
2276
2316
|
|
|
2277
2317
|
return { markdown, sourceName }
|
|
2278
2318
|
}
|
|
2279
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
|
+
|
|
2280
2328
|
async function startOptimizationRun() {
|
|
2281
2329
|
const project = getArg('--project') || await resolveProjectSlug(null)
|
|
2282
2330
|
const optimizerVersionId = getArg('--optimizer-version')
|
|
@@ -2674,13 +2722,120 @@ function readSourceBytes(pathArg: string): Buffer {
|
|
|
2674
2722
|
}
|
|
2675
2723
|
|
|
2676
2724
|
function hasJsonFlag(): boolean {
|
|
2677
|
-
return hasArg('--json')
|
|
2725
|
+
return cliJsonOutput || hasArg('--json')
|
|
2678
2726
|
}
|
|
2679
2727
|
|
|
2680
2728
|
function printJson(value: Record<string, unknown>) {
|
|
2681
2729
|
printLine(JSON.stringify(value))
|
|
2682
2730
|
}
|
|
2683
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
|
+
|
|
2684
2839
|
function readJsonFile(pathArg: string): Record<string, unknown> {
|
|
2685
2840
|
const raw = readSourceFile(pathArg)
|
|
2686
2841
|
try {
|
|
@@ -3104,6 +3259,7 @@ async function createTask() {
|
|
|
3104
3259
|
const appId = getArg('--app')
|
|
3105
3260
|
const title = getArg('--title')
|
|
3106
3261
|
const assignees = parseCommaSeparated(getArg('--assignees'))
|
|
3262
|
+
const publish = hasArg('--publish')
|
|
3107
3263
|
const versionArg = getArg('--version')
|
|
3108
3264
|
const instructions = getArg('--instructions')
|
|
3109
3265
|
const labelsPerItemArg = getArg('--labels-per-item')
|
|
@@ -3112,8 +3268,8 @@ async function createTask() {
|
|
|
3112
3268
|
const versionNum =
|
|
3113
3269
|
Number.isInteger(parsedVersionNum) && parsedVersionNum > 0 ? parsedVersionNum : null
|
|
3114
3270
|
|
|
3115
|
-
if (!projectSlug || !datasetId || !appId || !title || assignees.length === 0) {
|
|
3116
|
-
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]')
|
|
3117
3273
|
}
|
|
3118
3274
|
|
|
3119
3275
|
if (versionArg && versionNum === null) {
|
|
@@ -3130,6 +3286,7 @@ async function createTask() {
|
|
|
3130
3286
|
versionNum,
|
|
3131
3287
|
title,
|
|
3132
3288
|
memberIds: assignees,
|
|
3289
|
+
publish,
|
|
3133
3290
|
instructions,
|
|
3134
3291
|
requiredAssignmentsPerRow: labelsPerItem,
|
|
3135
3292
|
}),
|
|
@@ -3172,6 +3329,13 @@ async function createTask() {
|
|
|
3172
3329
|
status: data.task.status,
|
|
3173
3330
|
requiredAssignmentsPerRow: data.task.requiredAssignmentsPerRow,
|
|
3174
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
|
+
: {}),
|
|
3175
3339
|
...(data.assignmentShortfall !== undefined ? { assignmentShortfall: data.assignmentShortfall } : {}),
|
|
3176
3340
|
...(data.warning ? { warning: data.warning } : {}),
|
|
3177
3341
|
}, null, 2))
|
|
@@ -3180,15 +3344,76 @@ async function createTask() {
|
|
|
3180
3344
|
|
|
3181
3345
|
const baseUrl = getBaseUrl()
|
|
3182
3346
|
const taskUrl = `${baseUrl}/d/${projectSlug}/tasks/${data.task.id}`
|
|
3347
|
+
const isDraft = data.task.status === 'draft'
|
|
3183
3348
|
printLine(
|
|
3184
|
-
`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)}]` +
|
|
3185
3350
|
`\n Task ID: ${sanitizeTerminalText(data.task.id)}` +
|
|
3186
3351
|
`\n Dataset ID: ${sanitizeTerminalText(datasetId)}` +
|
|
3187
3352
|
`\n Version: v${data.task.versionNum} (${sanitizeTerminalText(data.task.versionId)})` +
|
|
3188
3353
|
`\n Labels/row: ${data.task.requiredAssignmentsPerRow}` +
|
|
3189
3354
|
`\n Assignments: ${data.assignmentsCreated}` +
|
|
3190
3355
|
(data.warning ? `\n Warning: ${sanitizeTerminalText(data.warning)}` : '') +
|
|
3191
|
-
`\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)}` : '')
|
|
3192
3417
|
)
|
|
3193
3418
|
}
|
|
3194
3419
|
|
|
@@ -3281,6 +3506,58 @@ async function updateTaskStatus(targetStatus: 'paused' | 'active') {
|
|
|
3281
3506
|
printLine(`${action} task ${sanitizeTerminalText(data.task.id)} [${sanitizeTerminalText(data.task.status)}]`)
|
|
3282
3507
|
}
|
|
3283
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
|
+
|
|
3284
3561
|
interface AppDetailPayload {
|
|
3285
3562
|
id: string
|
|
3286
3563
|
name: string
|
|
@@ -4435,11 +4712,45 @@ async function runnersExec() {
|
|
|
4435
4712
|
}
|
|
4436
4713
|
}
|
|
4437
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
|
+
|
|
4438
4737
|
export async function main(rawArgs = process.argv.slice(2)) {
|
|
4439
4738
|
const parsed = parseGlobalFlags(rawArgs)
|
|
4440
4739
|
setGlobalFlags(parsed.flags)
|
|
4441
4740
|
cliArgs = parsed.args
|
|
4442
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
|
+
|
|
4443
4754
|
const command = cliArgs[0]
|
|
4444
4755
|
const subcommand = cliArgs[1]
|
|
4445
4756
|
|
|
@@ -4450,10 +4761,24 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4450
4761
|
|
|
4451
4762
|
if (!command) {
|
|
4452
4763
|
printUsage()
|
|
4453
|
-
printOptimizationUsage()
|
|
4454
4764
|
process.exit(1)
|
|
4455
4765
|
}
|
|
4456
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
|
+
|
|
4457
4782
|
if (command === 'login') {
|
|
4458
4783
|
await login()
|
|
4459
4784
|
return
|
|
@@ -4691,6 +5016,11 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4691
5016
|
return
|
|
4692
5017
|
}
|
|
4693
5018
|
|
|
5019
|
+
if (command === 'tasks' && subcommand === 'publish') {
|
|
5020
|
+
await publishTask()
|
|
5021
|
+
return
|
|
5022
|
+
}
|
|
5023
|
+
|
|
4694
5024
|
if (command === 'tasks' && subcommand === 'assign') {
|
|
4695
5025
|
await assignTask()
|
|
4696
5026
|
return
|
|
@@ -4701,6 +5031,15 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4701
5031
|
return
|
|
4702
5032
|
}
|
|
4703
5033
|
|
|
5034
|
+
if (
|
|
5035
|
+
command === 'tasks' &&
|
|
5036
|
+
subcommand === 'report' &&
|
|
5037
|
+
(cliArgs[2] === 'set' || cliArgs[2] === 'upload')
|
|
5038
|
+
) {
|
|
5039
|
+
await setTaskReport()
|
|
5040
|
+
return
|
|
5041
|
+
}
|
|
5042
|
+
|
|
4704
5043
|
if (command === 'tasks' && subcommand === 'pause') {
|
|
4705
5044
|
await updateTaskStatus('paused')
|
|
4706
5045
|
return
|
|
@@ -4778,7 +5117,6 @@ export async function main(rawArgs = process.argv.slice(2)) {
|
|
|
4778
5117
|
}
|
|
4779
5118
|
|
|
4780
5119
|
printUsage()
|
|
4781
|
-
printOptimizationUsage()
|
|
4782
5120
|
process.exit(1)
|
|
4783
5121
|
}
|
|
4784
5122
|
|