orizu 0.5.3 → 0.5.4

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.
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Runner/optimizer artifact pull (symmetric with `runners push` /
3
- * `optimizers push`): resolve the artifact by id or name, download the
4
- * content-addressed zip from storage, and extract it into --out. Version
5
- * metadata is written to .orizu/pull.json — .orizu/ is excluded from artifact
6
- * zips (see artifact-archive.ts), so a pulled directory re-pushes with an
7
- * identical content hash.
2
+ * Runner/optimizer artifact commands: list (discover names, version ids, and
3
+ * labels) and pull (symmetric with `runners push` / `optimizers push` —
4
+ * resolve by id or name, download the content-addressed zip from storage,
5
+ * and extract it into --out). Pull writes version metadata to
6
+ * .orizu/pull.json — .orizu/ is excluded from artifact zips (see
7
+ * artifact-archive.ts), so a pulled directory re-pushes with an identical
8
+ * content hash.
8
9
  *
9
10
  * Lives outside index.ts per the CLI index line ratchet (ALI-976): this module
10
11
  * owns its own argument parsing and printing via injected io.
@@ -49,7 +50,50 @@ async function parseJsonPayload(response, context) {
49
50
  `Body preview: ${sanitizeTerminalText(rawBody.slice(0, 180))}`);
50
51
  }
51
52
  }
52
- export async function pullArtifactCommand(args, io) {
53
+ export async function runnerOptimizerCommand(args, io) {
54
+ if (args[1] === 'list') {
55
+ await listArtifactsCommand(args, io);
56
+ return;
57
+ }
58
+ await pullArtifactCommand(args, io);
59
+ }
60
+ async function listArtifactsCommand(args, io) {
61
+ const kind = args[0] === 'runners' ? 'runner' : 'optimizer';
62
+ const plural = kind === 'runner' ? 'runners' : 'optimizers';
63
+ const fetcher = io.fetcher || authedFetch;
64
+ const project = argValue(args, '--project') || await io.resolveProjectSlug(null);
65
+ const response = await fetcher(`/api/cli/${plural}?project=${encodeURIComponent(project)}`);
66
+ if (!response.ok) {
67
+ throw new Error(`Failed to fetch ${plural}: ${await response.text()}`);
68
+ }
69
+ const data = await parseJsonPayload(response, `${plural} list`);
70
+ if (io.json) {
71
+ io.print(JSON.stringify(data));
72
+ return;
73
+ }
74
+ const items = data[plural] || [];
75
+ if (items.length === 0) {
76
+ io.print(`No ${plural} found.`);
77
+ return;
78
+ }
79
+ const rows = items.map(item => ({
80
+ id: sanitizeTerminalText(item.id),
81
+ name: sanitizeTerminalText(item.name),
82
+ versions: String(item.versionCount ?? 0),
83
+ latest: sanitizeTerminalText(item.latestVersionId || '-'),
84
+ labels: sanitizeTerminalText((item.labels || []).map(entry => entry.label).join(', ') || '-'),
85
+ }));
86
+ const idWidth = Math.max('ID'.length, ...rows.map(row => row.id.length));
87
+ const nameWidth = Math.max('NAME'.length, ...rows.map(row => row.name.length));
88
+ const versionsWidth = Math.max('VERSIONS'.length, ...rows.map(row => row.versions.length));
89
+ const latestWidth = Math.max('LATEST VERSION'.length, ...rows.map(row => row.latest.length));
90
+ io.print(`${'ID'.padEnd(idWidth)} ${'NAME'.padEnd(nameWidth)} ${'VERSIONS'.padEnd(versionsWidth)} ${'LATEST VERSION'.padEnd(latestWidth)} LABELS`);
91
+ io.print(`${'-'.repeat(idWidth)} ${'-'.repeat(nameWidth)} ${'-'.repeat(versionsWidth)} ${'-'.repeat(latestWidth)} ${'-'.repeat('LABELS'.length)}`);
92
+ rows.forEach(row => {
93
+ io.print(`${row.id.padEnd(idWidth)} ${row.name.padEnd(nameWidth)} ${row.versions.padEnd(versionsWidth)} ${row.latest.padEnd(latestWidth)} ${row.labels}`);
94
+ });
95
+ }
96
+ async function pullArtifactCommand(args, io) {
53
97
  const kind = args[0] === 'runners' ? 'runner' : 'optimizer';
54
98
  const fetcher = io.fetcher || authedFetch;
55
99
  const positionalRef = args[2];
package/dist/help.js CHANGED
@@ -344,6 +344,12 @@ export const COMMAND_DOCS = [
344
344
  summary: 'Push a local runner artifact directory.',
345
345
  group: 'Scorers and runners',
346
346
  },
347
+ {
348
+ path: ['runners', 'list'],
349
+ usage: 'orizu runners list [--project <team/project>] [--json]',
350
+ summary: 'List runner artifacts with version counts, latest version ids, and labels.',
351
+ group: 'Scorers and runners',
352
+ },
347
353
  {
348
354
  path: ['runners', 'pull'],
349
355
  usage: 'orizu runners pull <runner-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <version-id>] [--json]',
@@ -362,6 +368,12 @@ export const COMMAND_DOCS = [
362
368
  summary: 'Push a local optimizer artifact directory.',
363
369
  group: 'Optimizations',
364
370
  },
371
+ {
372
+ path: ['optimizers', 'list'],
373
+ usage: 'orizu optimizers list [--project <team/project>] [--json]',
374
+ summary: 'List optimizer artifacts with version counts, latest version ids, and labels.',
375
+ group: 'Optimizations',
376
+ },
365
377
  {
366
378
  path: ['optimizers', 'pull'],
367
379
  usage: 'orizu optimizers pull <optimizer-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <version-id>] [--json]',
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import { formatTaskCreateError } from './task-create-error.js';
27
27
  import { renderAgentSetupPrompt } from './setup-prompt.js';
28
28
  import { getWorkspaceRoot, initOrizuWorkspace, workspaceExists, } from './workspace.js';
29
29
  import { connectorsCommand } from './connectors-cli.js';
30
- import { ARTIFACT_MAX_BYTES, pullArtifactCommand } from './artifact-pull.js';
30
+ import { ARTIFACT_MAX_BYTES, runnerOptimizerCommand } from './artifact-pull.js';
31
31
  import { killSwitchCommand } from './kill-switch-cli.js';
32
32
  import { egressAllowlistCommand } from './egress-allowlist-cli.js';
33
33
  import { manifestsCommand } from './manifests-cli.js';
@@ -5001,8 +5001,8 @@ export async function main(rawArgs = process.argv.slice(2)) {
5001
5001
  await pushRunnerArtifact(command === 'runners' ? 'runner' : 'optimizer');
5002
5002
  return;
5003
5003
  }
5004
- if ((command === 'runners' || command === 'optimizers') && subcommand === 'pull') {
5005
- await pullArtifactCommand(cliArgs, { json: hasJsonFlag(), print: printLine, resolveProjectSlug });
5004
+ if ((command === 'runners' || command === 'optimizers') && (subcommand === 'pull' || subcommand === 'list')) {
5005
+ await runnerOptimizerCommand(cliArgs, { json: hasJsonFlag(), print: printLine, resolveProjectSlug });
5006
5006
  return;
5007
5007
  }
5008
5008
  if (command === 'runners' && subcommand === 'exec') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orizu",
3
- "version": "0.5.3",
3
+ "version": "0.5.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,10 +1,11 @@
1
1
  /**
2
- * Runner/optimizer artifact pull (symmetric with `runners push` /
3
- * `optimizers push`): resolve the artifact by id or name, download the
4
- * content-addressed zip from storage, and extract it into --out. Version
5
- * metadata is written to .orizu/pull.json — .orizu/ is excluded from artifact
6
- * zips (see artifact-archive.ts), so a pulled directory re-pushes with an
7
- * identical content hash.
2
+ * Runner/optimizer artifact commands: list (discover names, version ids, and
3
+ * labels) and pull (symmetric with `runners push` / `optimizers push` —
4
+ * resolve by id or name, download the content-addressed zip from storage,
5
+ * and extract it into --out). Pull writes version metadata to
6
+ * .orizu/pull.json — .orizu/ is excluded from artifact zips (see
7
+ * artifact-archive.ts), so a pulled directory re-pushes with an identical
8
+ * content hash.
8
9
  *
9
10
  * Lives outside index.ts per the CLI index line ratchet (ALI-976): this module
10
11
  * owns its own argument parsing and printing via injected io.
@@ -84,7 +85,67 @@ interface PullArtifactResponse {
84
85
  labels?: Array<{ label: string; runnerVersionId?: string; optimizerVersionId?: string }>
85
86
  }
86
87
 
87
- export async function pullArtifactCommand(args: string[], io: PullArtifactIo) {
88
+ interface ArtifactListEntry {
89
+ id: string
90
+ name: string
91
+ description?: string | null
92
+ optimizerFamily?: string | null
93
+ latestVersionId?: string | null
94
+ versionCount?: number
95
+ labels?: Array<{ label: string; runnerVersionId?: string; optimizerVersionId?: string }>
96
+ }
97
+
98
+ export async function runnerOptimizerCommand(args: string[], io: PullArtifactIo) {
99
+ if (args[1] === 'list') {
100
+ await listArtifactsCommand(args, io)
101
+ return
102
+ }
103
+ await pullArtifactCommand(args, io)
104
+ }
105
+
106
+ async function listArtifactsCommand(args: string[], io: PullArtifactIo) {
107
+ const kind: PullableArtifactKind = args[0] === 'runners' ? 'runner' : 'optimizer'
108
+ const plural = kind === 'runner' ? 'runners' : 'optimizers'
109
+ const fetcher = io.fetcher || authedFetch
110
+ const project = argValue(args, '--project') || await io.resolveProjectSlug(null)
111
+
112
+ const response = await fetcher(`/api/cli/${plural}?project=${encodeURIComponent(project)}`)
113
+ if (!response.ok) {
114
+ throw new Error(`Failed to fetch ${plural}: ${await response.text()}`)
115
+ }
116
+
117
+ const data = await parseJsonPayload<Record<string, ArtifactListEntry[]>>(response, `${plural} list`)
118
+ if (io.json) {
119
+ io.print(JSON.stringify(data))
120
+ return
121
+ }
122
+
123
+ const items = data[plural] || []
124
+ if (items.length === 0) {
125
+ io.print(`No ${plural} found.`)
126
+ return
127
+ }
128
+
129
+ const rows = items.map(item => ({
130
+ id: sanitizeTerminalText(item.id),
131
+ name: sanitizeTerminalText(item.name),
132
+ versions: String(item.versionCount ?? 0),
133
+ latest: sanitizeTerminalText(item.latestVersionId || '-'),
134
+ labels: sanitizeTerminalText((item.labels || []).map(entry => entry.label).join(', ') || '-'),
135
+ }))
136
+ const idWidth = Math.max('ID'.length, ...rows.map(row => row.id.length))
137
+ const nameWidth = Math.max('NAME'.length, ...rows.map(row => row.name.length))
138
+ const versionsWidth = Math.max('VERSIONS'.length, ...rows.map(row => row.versions.length))
139
+ const latestWidth = Math.max('LATEST VERSION'.length, ...rows.map(row => row.latest.length))
140
+
141
+ io.print(`${'ID'.padEnd(idWidth)} ${'NAME'.padEnd(nameWidth)} ${'VERSIONS'.padEnd(versionsWidth)} ${'LATEST VERSION'.padEnd(latestWidth)} LABELS`)
142
+ io.print(`${'-'.repeat(idWidth)} ${'-'.repeat(nameWidth)} ${'-'.repeat(versionsWidth)} ${'-'.repeat(latestWidth)} ${'-'.repeat('LABELS'.length)}`)
143
+ rows.forEach(row => {
144
+ io.print(`${row.id.padEnd(idWidth)} ${row.name.padEnd(nameWidth)} ${row.versions.padEnd(versionsWidth)} ${row.latest.padEnd(latestWidth)} ${row.labels}`)
145
+ })
146
+ }
147
+
148
+ async function pullArtifactCommand(args: string[], io: PullArtifactIo) {
88
149
  const kind: PullableArtifactKind = args[0] === 'runners' ? 'runner' : 'optimizer'
89
150
  const fetcher = io.fetcher || authedFetch
90
151
  const positionalRef = args[2]
package/src/help.ts CHANGED
@@ -369,6 +369,12 @@ export const COMMAND_DOCS: CliCommandDoc[] = [
369
369
  summary: 'Push a local runner artifact directory.',
370
370
  group: 'Scorers and runners',
371
371
  },
372
+ {
373
+ path: ['runners', 'list'],
374
+ usage: 'orizu runners list [--project <team/project>] [--json]',
375
+ summary: 'List runner artifacts with version counts, latest version ids, and labels.',
376
+ group: 'Scorers and runners',
377
+ },
372
378
  {
373
379
  path: ['runners', 'pull'],
374
380
  usage: 'orizu runners pull <runner-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <version-id>] [--json]',
@@ -387,6 +393,12 @@ export const COMMAND_DOCS: CliCommandDoc[] = [
387
393
  summary: 'Push a local optimizer artifact directory.',
388
394
  group: 'Optimizations',
389
395
  },
396
+ {
397
+ path: ['optimizers', 'list'],
398
+ usage: 'orizu optimizers list [--project <team/project>] [--json]',
399
+ summary: 'List optimizer artifacts with version counts, latest version ids, and labels.',
400
+ group: 'Optimizations',
401
+ },
390
402
  {
391
403
  path: ['optimizers', 'pull'],
392
404
  usage: 'orizu optimizers pull <optimizer-id-or-name> --project <team/project> --out <dir> [--label <label> | --version <version-id>] [--json]',
package/src/index.ts CHANGED
@@ -59,7 +59,7 @@ import {
59
59
  workspaceExists,
60
60
  } from './workspace.js'
61
61
  import { connectorsCommand } from './connectors-cli.js'
62
- import { ARTIFACT_MAX_BYTES, pullArtifactCommand } from './artifact-pull.js'
62
+ import { ARTIFACT_MAX_BYTES, runnerOptimizerCommand } from './artifact-pull.js'
63
63
  import { killSwitchCommand } from './kill-switch-cli.js'
64
64
  import { egressAllowlistCommand } from './egress-allowlist-cli.js'
65
65
  import { manifestsCommand } from './manifests-cli.js'
@@ -6467,8 +6467,8 @@ export async function main(rawArgs = process.argv.slice(2)) {
6467
6467
  return
6468
6468
  }
6469
6469
 
6470
- if ((command === 'runners' || command === 'optimizers') && subcommand === 'pull') {
6471
- await pullArtifactCommand(cliArgs, { json: hasJsonFlag(), print: printLine, resolveProjectSlug }); return
6470
+ if ((command === 'runners' || command === 'optimizers') && (subcommand === 'pull' || subcommand === 'list')) {
6471
+ await runnerOptimizerCommand(cliArgs, { json: hasJsonFlag(), print: printLine, resolveProjectSlug }); return
6472
6472
  }
6473
6473
 
6474
6474
  if (command === 'runners' && subcommand === 'exec') {