@outputai/cli 0.8.2-next.2da7213.0 → 0.8.2-next.e1cd79b.0
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/dist/assets/docker/docker-compose-dev.yml +1 -1
- package/dist/commands/workflow/cost.d.ts +2 -3
- package/dist/commands/workflow/cost.js +11 -4
- package/dist/commands/workflow/cost.spec.js +3 -1
- package/dist/commands/workflow/dataset/list.d.ts +1 -3
- package/dist/commands/workflow/dataset/list.js +14 -10
- package/dist/commands/workflow/debug.d.ts +6 -2
- package/dist/commands/workflow/debug.js +29 -10
- package/dist/commands/workflow/debug.spec.js +5 -2
- package/dist/commands/workflow/list.d.ts +1 -4
- package/dist/commands/workflow/list.js +19 -15
- package/dist/commands/workflow/list.spec.js +1 -2
- package/dist/commands/workflow/result.d.ts +4 -3
- package/dist/commands/workflow/result.js +15 -6
- package/dist/commands/workflow/result.spec.js +4 -2
- package/dist/commands/workflow/run.d.ts +2 -3
- package/dist/commands/workflow/run.js +11 -4
- package/dist/commands/workflow/run.spec.js +3 -1
- package/dist/commands/workflow/runs/list.d.ts +1 -3
- package/dist/commands/workflow/runs/list.js +15 -11
- package/dist/commands/workflow/status.d.ts +4 -3
- package/dist/commands/workflow/status.js +30 -20
- package/dist/commands/workflow/status.spec.js +4 -2
- package/dist/commands/workflow/test_eval.d.ts +2 -3
- package/dist/commands/workflow/test_eval.js +15 -5
- package/dist/generated/framework_version.json +1 -1
- package/dist/hooks/init.d.ts +0 -1
- package/dist/hooks/init.js +30 -40
- package/dist/hooks/init.spec.js +4 -28
- package/dist/utils/constants.d.ts +5 -0
- package/dist/utils/constants.js +4 -0
- package/dist/utils/format_workflow_result.spec.js +13 -0
- package/dist/utils/output_formatter.d.ts +2 -0
- package/dist/utils/output_formatter.js +11 -0
- package/dist/utils/trace_formatter.js +2 -1
- package/oclif.manifest.json +101 -82
- package/package.json +4 -4
- package/dist/commands/workflow/test_eval.spec.d.ts +0 -1
- package/dist/commands/workflow/test_eval.spec.js +0 -84
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import type { CostReport } from '#types/cost.js';
|
|
3
2
|
export default class WorkflowCost extends Command {
|
|
4
3
|
static description: string;
|
|
5
|
-
static enableJsonFlag: boolean;
|
|
6
4
|
static examples: string[];
|
|
7
5
|
static args: {
|
|
8
6
|
workflowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
7
|
tracePath: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
10
8
|
};
|
|
11
9
|
static flags: {
|
|
10
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
11
|
verbose: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
12
|
};
|
|
14
|
-
run(): Promise<
|
|
13
|
+
run(): Promise<void>;
|
|
15
14
|
private loadLocalTrace;
|
|
16
15
|
catch(error: Error): Promise<void>;
|
|
17
16
|
}
|
|
@@ -2,17 +2,18 @@ import { Args, Command, Flags } from '@oclif/core';
|
|
|
2
2
|
import { readFile } from 'node:fs/promises';
|
|
3
3
|
import { calculateCost, loadPricingConfig } from '#services/cost_calculator.js';
|
|
4
4
|
import { getTrace } from '#services/trace_reader.js';
|
|
5
|
+
import { OUTPUT_FORMAT } from '#utils/constants.js';
|
|
5
6
|
import { formatCostReport } from '#utils/cost_formatter.js';
|
|
6
7
|
import { getErrorCode } from '#utils/error_utils.js';
|
|
7
8
|
import { handleApiError } from '#utils/error_handler.js';
|
|
9
|
+
import { formatOutput } from '#utils/output_formatter.js';
|
|
8
10
|
export default class WorkflowCost extends Command {
|
|
9
11
|
static description = 'Calculate the cost of a workflow execution';
|
|
10
|
-
static enableJsonFlag = true;
|
|
11
12
|
static examples = [
|
|
12
13
|
'<%= config.bin %> <%= command.id %> my_workflow_id',
|
|
13
14
|
'<%= config.bin %> <%= command.id %> my_workflow_id --verbose',
|
|
14
15
|
'<%= config.bin %> <%= command.id %> my_workflow_id path/to/trace.json',
|
|
15
|
-
'<%= config.bin %> <%= command.id %> my_workflow_id --json'
|
|
16
|
+
'<%= config.bin %> <%= command.id %> my_workflow_id --format json'
|
|
16
17
|
];
|
|
17
18
|
static args = {
|
|
18
19
|
workflowId: Args.string({
|
|
@@ -25,6 +26,12 @@ export default class WorkflowCost extends Command {
|
|
|
25
26
|
})
|
|
26
27
|
};
|
|
27
28
|
static flags = {
|
|
29
|
+
format: Flags.string({
|
|
30
|
+
char: 'f',
|
|
31
|
+
description: 'Output format',
|
|
32
|
+
options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
33
|
+
default: OUTPUT_FORMAT.TEXT
|
|
34
|
+
}),
|
|
28
35
|
verbose: Flags.boolean({
|
|
29
36
|
description: 'Show detailed per-call breakdown',
|
|
30
37
|
default: false
|
|
@@ -38,8 +45,8 @@ export default class WorkflowCost extends Command {
|
|
|
38
45
|
const config = loadPricingConfig();
|
|
39
46
|
const traceNode = traceData;
|
|
40
47
|
const report = calculateCost(traceNode, config, traceFile);
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
const formatted = formatOutput(report, flags.format, r => formatCostReport(r, { verbose: flags.verbose }));
|
|
49
|
+
this.log(formatted);
|
|
43
50
|
}
|
|
44
51
|
async loadLocalTrace(tracePath) {
|
|
45
52
|
try {
|
|
@@ -20,6 +20,7 @@ describe('workflow cost command', () => {
|
|
|
20
20
|
expect(WorkflowCost).toBeDefined();
|
|
21
21
|
expect(WorkflowCost.description).toBeDefined();
|
|
22
22
|
expect(WorkflowCost.args).toHaveProperty('workflowId');
|
|
23
|
+
expect(WorkflowCost.flags).toHaveProperty('format');
|
|
23
24
|
expect(WorkflowCost.flags).toHaveProperty('verbose');
|
|
24
25
|
});
|
|
25
26
|
it('should have workflowId as required arg', async () => {
|
|
@@ -33,7 +34,8 @@ describe('workflow cost command', () => {
|
|
|
33
34
|
});
|
|
34
35
|
it('should have correct flag configuration', async () => {
|
|
35
36
|
const WorkflowCost = (await import('./cost.js')).default;
|
|
36
|
-
expect(WorkflowCost.
|
|
37
|
+
expect(WorkflowCost.flags.format.options).toEqual(['json', 'text']);
|
|
38
|
+
expect(WorkflowCost.flags.format.default).toBe('text');
|
|
37
39
|
expect(WorkflowCost.flags.verbose.default).toBe(false);
|
|
38
40
|
});
|
|
39
41
|
it('should have correct examples', async () => {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import type { DatasetInfo } from '#services/datasets.js';
|
|
3
2
|
export default class DatasetList extends Command {
|
|
4
3
|
static description: string;
|
|
5
|
-
static enableJsonFlag: boolean;
|
|
6
4
|
static examples: string[];
|
|
7
5
|
static args: {
|
|
8
6
|
workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -10,5 +8,5 @@ export default class DatasetList extends Command {
|
|
|
10
8
|
static flags: {
|
|
11
9
|
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
10
|
};
|
|
13
|
-
run(): Promise<
|
|
11
|
+
run(): Promise<void>;
|
|
14
12
|
}
|
|
@@ -3,6 +3,7 @@ import Table from 'cli-table3';
|
|
|
3
3
|
import { listDatasets } from '#services/datasets.js';
|
|
4
4
|
const OutputFormat = {
|
|
5
5
|
TABLE: 'table',
|
|
6
|
+
JSON: 'json',
|
|
6
7
|
TEXT: 'text'
|
|
7
8
|
};
|
|
8
9
|
function createDatasetsTable(datasets) {
|
|
@@ -36,7 +37,13 @@ function formatDatasetsAsText(datasets) {
|
|
|
36
37
|
return `${dataset.name} ${cached}${outputDate}${evalDate}`;
|
|
37
38
|
}).join('\n');
|
|
38
39
|
}
|
|
40
|
+
function formatDatasetsAsJson(datasets) {
|
|
41
|
+
return JSON.stringify(datasets, null, 2);
|
|
42
|
+
}
|
|
39
43
|
function formatDatasets(datasets, format) {
|
|
44
|
+
if (format === OutputFormat.JSON) {
|
|
45
|
+
return formatDatasetsAsJson(datasets);
|
|
46
|
+
}
|
|
40
47
|
if (format === OutputFormat.TABLE) {
|
|
41
48
|
return createDatasetsTable(datasets);
|
|
42
49
|
}
|
|
@@ -44,10 +51,9 @@ function formatDatasets(datasets, format) {
|
|
|
44
51
|
}
|
|
45
52
|
export default class DatasetList extends Command {
|
|
46
53
|
static description = 'List datasets for a workflow';
|
|
47
|
-
static enableJsonFlag = true;
|
|
48
54
|
static examples = [
|
|
49
55
|
'<%= config.bin %> <%= command.id %> simple',
|
|
50
|
-
'<%= config.bin %> <%= command.id %> simple --json',
|
|
56
|
+
'<%= config.bin %> <%= command.id %> simple --format json',
|
|
51
57
|
'<%= config.bin %> <%= command.id %> simple --format table'
|
|
52
58
|
];
|
|
53
59
|
static args = {
|
|
@@ -59,25 +65,23 @@ export default class DatasetList extends Command {
|
|
|
59
65
|
static flags = {
|
|
60
66
|
format: Flags.string({
|
|
61
67
|
char: 'f',
|
|
62
|
-
description: 'Output format
|
|
63
|
-
options: [OutputFormat.TABLE, OutputFormat.TEXT],
|
|
68
|
+
description: 'Output format',
|
|
69
|
+
options: [OutputFormat.TABLE, OutputFormat.JSON, OutputFormat.TEXT],
|
|
64
70
|
default: OutputFormat.TABLE
|
|
65
71
|
})
|
|
66
72
|
};
|
|
67
73
|
async run() {
|
|
68
74
|
const { args, flags } = await this.parse(DatasetList);
|
|
69
75
|
const datasets = await listDatasets(args.workflowName);
|
|
70
|
-
if (this.jsonEnabled()) {
|
|
71
|
-
return datasets;
|
|
72
|
-
}
|
|
73
76
|
if (datasets.length === 0) {
|
|
74
77
|
this.log(`No datasets found for workflow "${args.workflowName}".`);
|
|
75
78
|
this.log('Generate datasets with: output workflow dataset generate');
|
|
76
|
-
return
|
|
79
|
+
return;
|
|
77
80
|
}
|
|
78
81
|
const output = formatDatasets(datasets, flags.format);
|
|
79
82
|
this.log(output);
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
if (flags.format !== OutputFormat.JSON) {
|
|
84
|
+
this.log(`\nFound ${datasets.length} dataset(s) for "${args.workflowName}"`);
|
|
85
|
+
}
|
|
82
86
|
}
|
|
83
87
|
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
export default class WorkflowDebug extends Command {
|
|
3
3
|
static description: string;
|
|
4
|
-
static enableJsonFlag: boolean;
|
|
5
4
|
static examples: string[];
|
|
6
5
|
static args: {
|
|
7
6
|
workflowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
8
7
|
};
|
|
9
|
-
|
|
8
|
+
static flags: {
|
|
9
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
12
|
+
private conditionalLog;
|
|
13
|
+
private outputJson;
|
|
10
14
|
private displayTextTrace;
|
|
11
15
|
catch(error: Error): Promise<void>;
|
|
12
16
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { Args, Command } from '@oclif/core';
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import { OUTPUT_FORMAT } from '#utils/constants.js';
|
|
2
3
|
import { displayDebugTree } from '#utils/trace_formatter.js';
|
|
3
4
|
import { getTrace } from '#services/trace_reader.js';
|
|
4
5
|
import { handleApiError } from '#utils/error_handler.js';
|
|
5
6
|
export default class WorkflowDebug extends Command {
|
|
6
7
|
static description = 'Get and display workflow execution trace for debugging';
|
|
7
|
-
static enableJsonFlag = true;
|
|
8
8
|
static examples = [
|
|
9
9
|
'<%= config.bin %> <%= command.id %> wf-12345',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> wf-12345 --json'
|
|
10
|
+
'<%= config.bin %> <%= command.id %> wf-12345 --format json',
|
|
11
|
+
'<%= config.bin %> <%= command.id %> wf-12345 --format text'
|
|
11
12
|
];
|
|
12
13
|
static args = {
|
|
13
14
|
workflowId: Args.string({
|
|
@@ -15,23 +16,41 @@ export default class WorkflowDebug extends Command {
|
|
|
15
16
|
required: true
|
|
16
17
|
})
|
|
17
18
|
};
|
|
19
|
+
static flags = {
|
|
20
|
+
format: Flags.string({
|
|
21
|
+
char: 'f',
|
|
22
|
+
description: 'Output format',
|
|
23
|
+
options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
24
|
+
default: OUTPUT_FORMAT.TEXT
|
|
25
|
+
})
|
|
26
|
+
};
|
|
18
27
|
async run() {
|
|
19
|
-
const { args } = await this.parse(WorkflowDebug);
|
|
20
|
-
|
|
28
|
+
const { args, flags } = await this.parse(WorkflowDebug);
|
|
29
|
+
const isJsonFormat = flags.format === OUTPUT_FORMAT.JSON;
|
|
30
|
+
this.conditionalLog(`Fetching debug information for workflow: ${args.workflowId}...`, isJsonFormat);
|
|
21
31
|
const { data: traceData, location } = await getTrace(args.workflowId);
|
|
22
32
|
const source = location.isRemote ? 'remote' : 'local';
|
|
23
|
-
this.
|
|
24
|
-
if (
|
|
25
|
-
this.
|
|
33
|
+
this.conditionalLog(`Trace source: ${source}${!location.isRemote ? ` (${location.path})` : ''}`, isJsonFormat);
|
|
34
|
+
if (isJsonFormat) {
|
|
35
|
+
this.outputJson(traceData);
|
|
36
|
+
return;
|
|
26
37
|
}
|
|
27
|
-
|
|
38
|
+
this.displayTextTrace(traceData);
|
|
39
|
+
}
|
|
40
|
+
conditionalLog(message, disabled) {
|
|
41
|
+
if (!disabled) {
|
|
42
|
+
this.log(message);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
outputJson(data) {
|
|
46
|
+
this.log(JSON.stringify(data, null, 2));
|
|
28
47
|
}
|
|
29
48
|
displayTextTrace(traceData) {
|
|
30
49
|
this.log('\nTrace Log:');
|
|
31
50
|
this.log('─'.repeat(80));
|
|
32
51
|
this.log(displayDebugTree(traceData));
|
|
33
52
|
this.log('\n' + '─'.repeat(80));
|
|
34
|
-
this.log('Tip: Use --json for the full untruncated trace');
|
|
53
|
+
this.log('Tip: Use --format json for the full untruncated trace');
|
|
35
54
|
}
|
|
36
55
|
async catch(error) {
|
|
37
56
|
return handleApiError(error, (...args) => this.error(...args), {
|
|
@@ -17,10 +17,13 @@ describe('workflow debug command', () => {
|
|
|
17
17
|
expect(WorkflowDebug).toBeDefined();
|
|
18
18
|
expect(WorkflowDebug.description).toContain('Get and display workflow execution trace for debugging');
|
|
19
19
|
expect(WorkflowDebug.args).toHaveProperty('workflowId');
|
|
20
|
+
expect(WorkflowDebug.flags).toHaveProperty('format');
|
|
20
21
|
});
|
|
21
|
-
it('
|
|
22
|
+
it('should have correct flag configuration', async () => {
|
|
22
23
|
const WorkflowDebug = (await import('./debug.js')).default;
|
|
23
|
-
|
|
24
|
+
// Format flag
|
|
25
|
+
expect(WorkflowDebug.flags.format.options).toEqual(['json', 'text']);
|
|
26
|
+
expect(WorkflowDebug.flags.format.default).toBe('text');
|
|
24
27
|
});
|
|
25
28
|
it('should have correct examples', async () => {
|
|
26
29
|
const WorkflowDebug = (await import('./debug.js')).default;
|
|
@@ -12,7 +12,6 @@ export declare function parseWorkflowForDisplay(workflow: Workflow): WorkflowDis
|
|
|
12
12
|
export declare function formatWorkflowsAsList(workflows: Workflow[]): string;
|
|
13
13
|
export default class WorkflowList extends Command {
|
|
14
14
|
static description: string;
|
|
15
|
-
static enableJsonFlag: boolean;
|
|
16
15
|
static examples: string[];
|
|
17
16
|
static flags: {
|
|
18
17
|
catalog: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
@@ -20,9 +19,7 @@ export default class WorkflowList extends Command {
|
|
|
20
19
|
detailed: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
21
20
|
filter: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
21
|
};
|
|
23
|
-
run(): Promise<
|
|
24
|
-
workflows: unknown[];
|
|
25
|
-
}>;
|
|
22
|
+
run(): Promise<void>;
|
|
26
23
|
catch(error: Error): Promise<void>;
|
|
27
24
|
}
|
|
28
25
|
export {};
|
|
@@ -6,7 +6,8 @@ import { handleApiError } from '#utils/error_handler.js';
|
|
|
6
6
|
import { listScenariosForWorkflow } from '#utils/scenario_resolver.js';
|
|
7
7
|
const OUTPUT_FORMAT = {
|
|
8
8
|
LIST: 'list',
|
|
9
|
-
TABLE: 'table'
|
|
9
|
+
TABLE: 'table',
|
|
10
|
+
JSON: 'json'
|
|
10
11
|
};
|
|
11
12
|
export function parseWorkflowForDisplay(workflow) {
|
|
12
13
|
const parsed = parseWorkflowDefinition(workflow);
|
|
@@ -73,7 +74,7 @@ export function formatWorkflowsAsList(workflows) {
|
|
|
73
74
|
return `\nWorkflows:\n\n${lines.join('\n')}`;
|
|
74
75
|
}
|
|
75
76
|
function formatWorkflowsAsJson(workflows) {
|
|
76
|
-
|
|
77
|
+
const output = {
|
|
77
78
|
workflows: workflows.map(w => {
|
|
78
79
|
const display = parseWorkflowForDisplay(w);
|
|
79
80
|
return {
|
|
@@ -87,8 +88,12 @@ function formatWorkflowsAsJson(workflows) {
|
|
|
87
88
|
};
|
|
88
89
|
})
|
|
89
90
|
};
|
|
91
|
+
return JSON.stringify(output, null, 2);
|
|
90
92
|
}
|
|
91
93
|
function formatWorkflows(workflows, format, detailed) {
|
|
94
|
+
if (format === OUTPUT_FORMAT.JSON) {
|
|
95
|
+
return formatWorkflowsAsJson(workflows);
|
|
96
|
+
}
|
|
92
97
|
if (format === OUTPUT_FORMAT.TABLE) {
|
|
93
98
|
return createWorkflowTable(workflows, detailed);
|
|
94
99
|
}
|
|
@@ -96,11 +101,10 @@ function formatWorkflows(workflows, format, detailed) {
|
|
|
96
101
|
}
|
|
97
102
|
export default class WorkflowList extends Command {
|
|
98
103
|
static description = 'List available workflows from the catalog';
|
|
99
|
-
static enableJsonFlag = true;
|
|
100
104
|
static examples = [
|
|
101
105
|
'<%= config.bin %> <%= command.id %>',
|
|
102
106
|
'<%= config.bin %> <%= command.id %> --format table',
|
|
103
|
-
'<%= config.bin %> <%= command.id %> --json',
|
|
107
|
+
'<%= config.bin %> <%= command.id %> --format json',
|
|
104
108
|
'<%= config.bin %> <%= command.id %> --detailed',
|
|
105
109
|
'<%= config.bin %> <%= command.id %> --filter simple',
|
|
106
110
|
'<%= config.bin %> <%= command.id %> --catalog my-catalog'
|
|
@@ -116,8 +120,8 @@ export default class WorkflowList extends Command {
|
|
|
116
120
|
}),
|
|
117
121
|
format: Flags.string({
|
|
118
122
|
char: 'f',
|
|
119
|
-
description: 'Output format
|
|
120
|
-
options: [OUTPUT_FORMAT.LIST, OUTPUT_FORMAT.TABLE],
|
|
123
|
+
description: 'Output format',
|
|
124
|
+
options: [OUTPUT_FORMAT.LIST, OUTPUT_FORMAT.TABLE, OUTPUT_FORMAT.JSON],
|
|
121
125
|
default: OUTPUT_FORMAT.LIST
|
|
122
126
|
}),
|
|
123
127
|
detailed: Flags.boolean({
|
|
@@ -133,20 +137,20 @@ export default class WorkflowList extends Command {
|
|
|
133
137
|
const { flags } = await this.parse(WorkflowList);
|
|
134
138
|
this.log(flags.catalog ? `Fetching workflow catalog: ${flags.catalog}...` : 'Fetching workflow catalog...');
|
|
135
139
|
const catalogWorkflows = await fetchWorkflowCatalog(flags.catalog);
|
|
136
|
-
const workflows = flags.filter ?
|
|
137
|
-
catalogWorkflows.filter(matchName(flags.filter)) :
|
|
138
|
-
catalogWorkflows;
|
|
139
140
|
if (catalogWorkflows.length === 0) {
|
|
140
141
|
this.log('No workflows found in catalog.');
|
|
142
|
+
return;
|
|
141
143
|
}
|
|
142
|
-
|
|
144
|
+
const workflows = flags.filter ?
|
|
145
|
+
catalogWorkflows.filter(matchName(flags.filter)) :
|
|
146
|
+
catalogWorkflows;
|
|
147
|
+
if (workflows.length === 0 && flags.filter) {
|
|
143
148
|
this.log(`No workflows matching filter: ${flags.filter}`);
|
|
149
|
+
return;
|
|
144
150
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
return formatWorkflowsAsJson(workflows);
|
|
151
|
+
const output = formatWorkflows(workflows, flags.format, flags.detailed);
|
|
152
|
+
this.log(output);
|
|
153
|
+
this.log(`\nFound ${workflows.length} workflow(s)`);
|
|
150
154
|
}
|
|
151
155
|
async catch(error) {
|
|
152
156
|
return handleApiError(error, (...args) => this.error(...args), {
|
|
@@ -28,8 +28,7 @@ describe('workflow list command', () => {
|
|
|
28
28
|
});
|
|
29
29
|
it('should have correct flag configuration', async () => {
|
|
30
30
|
const WorkflowList = (await import('./list.js')).default;
|
|
31
|
-
expect(WorkflowList.
|
|
32
|
-
expect(WorkflowList.flags.format.options).toEqual(['list', 'table']);
|
|
31
|
+
expect(WorkflowList.flags.format.options).toEqual(['list', 'table', 'json']);
|
|
33
32
|
expect(WorkflowList.flags.format.default).toBe('list');
|
|
34
33
|
expect(WorkflowList.flags.detailed.default).toBe(false);
|
|
35
34
|
});
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { type WorkflowResultResponse } from '#api/generated/api.js';
|
|
3
2
|
export default class WorkflowResult extends Command {
|
|
4
3
|
static description: string;
|
|
5
|
-
static enableJsonFlag: boolean;
|
|
6
4
|
static examples: string[];
|
|
7
5
|
static args: {
|
|
8
6
|
workflowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
9
7
|
};
|
|
10
|
-
|
|
8
|
+
static flags: {
|
|
9
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
run(): Promise<void>;
|
|
11
12
|
catch(error: Error): Promise<void>;
|
|
12
13
|
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { Args, Command } from '@oclif/core';
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { getWorkflowIdResult } from '#api/generated/api.js';
|
|
3
|
+
import { OUTPUT_FORMAT } from '#utils/constants.js';
|
|
4
|
+
import { formatOutput } from '#utils/output_formatter.js';
|
|
3
5
|
import { formatWorkflowResult, ERROR_STATUSES } from '#utils/format_workflow_result.js';
|
|
4
6
|
import { handleApiError } from '#utils/error_handler.js';
|
|
5
7
|
export default class WorkflowResult extends Command {
|
|
6
8
|
static description = 'Get workflow execution result';
|
|
7
|
-
static enableJsonFlag = true;
|
|
8
9
|
static examples = [
|
|
9
10
|
'<%= config.bin %> <%= command.id %> wf-12345',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> wf-12345 --json'
|
|
11
|
+
'<%= config.bin %> <%= command.id %> wf-12345 --format json'
|
|
11
12
|
];
|
|
12
13
|
static args = {
|
|
13
14
|
workflowId: Args.string({
|
|
@@ -15,19 +16,27 @@ export default class WorkflowResult extends Command {
|
|
|
15
16
|
required: true
|
|
16
17
|
})
|
|
17
18
|
};
|
|
19
|
+
static flags = {
|
|
20
|
+
format: Flags.string({
|
|
21
|
+
char: 'f',
|
|
22
|
+
description: 'Output format',
|
|
23
|
+
options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
24
|
+
default: OUTPUT_FORMAT.TEXT
|
|
25
|
+
})
|
|
26
|
+
};
|
|
18
27
|
async run() {
|
|
19
|
-
const { args } = await this.parse(WorkflowResult);
|
|
28
|
+
const { args, flags } = await this.parse(WorkflowResult);
|
|
20
29
|
this.log(`Fetching result for workflow: ${args.workflowId}...`);
|
|
21
30
|
const response = await getWorkflowIdResult(args.workflowId);
|
|
22
31
|
if (!response || !response.data) {
|
|
23
32
|
this.error('API returned invalid response', { exit: 1 });
|
|
24
33
|
}
|
|
25
34
|
const data = response.data;
|
|
26
|
-
|
|
35
|
+
const output = formatOutput(data, flags.format, formatWorkflowResult);
|
|
36
|
+
this.log(`\n${output}`);
|
|
27
37
|
if (ERROR_STATUSES.has(data.status)) {
|
|
28
38
|
process.exitCode = 1;
|
|
29
39
|
}
|
|
30
|
-
return data;
|
|
31
40
|
}
|
|
32
41
|
async catch(error) {
|
|
33
42
|
return handleApiError(error, (...args) => this.error(...args), {
|
|
@@ -12,10 +12,12 @@ describe('workflow result command', () => {
|
|
|
12
12
|
expect(WorkflowResult).toBeDefined();
|
|
13
13
|
expect(WorkflowResult.description).toContain('Get workflow execution result');
|
|
14
14
|
expect(WorkflowResult.args).toHaveProperty('workflowId');
|
|
15
|
+
expect(WorkflowResult.flags).toHaveProperty('format');
|
|
15
16
|
});
|
|
16
|
-
it('
|
|
17
|
+
it('should have correct flag configuration', async () => {
|
|
17
18
|
const WorkflowResult = (await import('./result.js')).default;
|
|
18
|
-
expect(WorkflowResult.
|
|
19
|
+
expect(WorkflowResult.flags.format.options).toEqual(['json', 'text']);
|
|
20
|
+
expect(WorkflowResult.flags.format.default).toBe('text');
|
|
19
21
|
});
|
|
20
22
|
});
|
|
21
23
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { type WorkflowResultResponse } from '#api/generated/api.js';
|
|
3
2
|
export default class WorkflowRun extends Command {
|
|
4
3
|
static description: string;
|
|
5
|
-
static enableJsonFlag: boolean;
|
|
6
4
|
static examples: string[];
|
|
7
5
|
static args: {
|
|
8
6
|
workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
@@ -11,7 +9,8 @@ export default class WorkflowRun extends Command {
|
|
|
11
9
|
static flags: {
|
|
12
10
|
input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
11
|
catalog: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
13
|
};
|
|
15
|
-
run(): Promise<
|
|
14
|
+
run(): Promise<void>;
|
|
16
15
|
catch(error: Error): Promise<void>;
|
|
17
16
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { postWorkflowRun } from '#api/generated/api.js';
|
|
3
|
+
import { OUTPUT_FORMAT } from '#utils/constants.js';
|
|
4
|
+
import { formatOutput } from '#utils/output_formatter.js';
|
|
3
5
|
import { formatWorkflowResult, ERROR_STATUSES } from '#utils/format_workflow_result.js';
|
|
4
6
|
import { handleApiError } from '#utils/error_handler.js';
|
|
5
7
|
import { resolveInput } from '#utils/resolve_input.js';
|
|
@@ -28,10 +30,9 @@ async function executeWorkflow(args) {
|
|
|
28
30
|
}
|
|
29
31
|
export default class WorkflowRun extends Command {
|
|
30
32
|
static description = 'Execute a workflow synchronously and wait for completion';
|
|
31
|
-
static enableJsonFlag = true;
|
|
32
33
|
static examples = [
|
|
33
34
|
'<%= config.bin %> <%= command.id %> simple basic_input',
|
|
34
|
-
'<%= config.bin %> <%= command.id %> simple my_scenario --json',
|
|
35
|
+
'<%= config.bin %> <%= command.id %> simple my_scenario --format json',
|
|
35
36
|
'<%= config.bin %> <%= command.id %> simple --input \'{"values":[1,2,3]}\'',
|
|
36
37
|
'<%= config.bin %> <%= command.id %> simple --input input.json',
|
|
37
38
|
'<%= config.bin %> <%= command.id %> simple --input \'{"key":"value"}\' --catalog my-catalog'
|
|
@@ -59,6 +60,12 @@ export default class WorkflowRun extends Command {
|
|
|
59
60
|
deprecateAliases: true,
|
|
60
61
|
description: 'Catalog name for workflow execution (defaults to OUTPUT_CATALOG_ID)',
|
|
61
62
|
env: 'OUTPUT_CATALOG_ID'
|
|
63
|
+
}),
|
|
64
|
+
format: Flags.string({
|
|
65
|
+
char: 'f',
|
|
66
|
+
description: 'Output format',
|
|
67
|
+
options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
68
|
+
default: OUTPUT_FORMAT.TEXT
|
|
62
69
|
})
|
|
63
70
|
};
|
|
64
71
|
async run() {
|
|
@@ -78,11 +85,11 @@ export default class WorkflowRun extends Command {
|
|
|
78
85
|
this.error('API returned invalid response', { exit: 1 });
|
|
79
86
|
}
|
|
80
87
|
const data = response.data;
|
|
81
|
-
|
|
88
|
+
const output = formatOutput(data, flags.format, formatWorkflowResult);
|
|
89
|
+
this.log(`\n${output}`);
|
|
82
90
|
if (ERROR_STATUSES.has(data.status)) {
|
|
83
91
|
process.exitCode = 1;
|
|
84
92
|
}
|
|
85
|
-
return data;
|
|
86
93
|
}
|
|
87
94
|
async catch(error) {
|
|
88
95
|
return handleApiError(error, (...args) => this.error(...args), {
|
|
@@ -26,11 +26,13 @@ describe('workflow run command', () => {
|
|
|
26
26
|
expect(WorkflowRun.description).toContain('Execute a workflow');
|
|
27
27
|
expect(WorkflowRun.args).toHaveProperty('workflowName');
|
|
28
28
|
expect(WorkflowRun.flags).toHaveProperty('input');
|
|
29
|
+
expect(WorkflowRun.flags).toHaveProperty('format');
|
|
29
30
|
expect(WorkflowRun.flags).toHaveProperty('catalog');
|
|
30
31
|
});
|
|
31
32
|
it('should have correct flag configuration', async () => {
|
|
32
33
|
const WorkflowRun = (await import('./run.js')).default;
|
|
33
|
-
expect(WorkflowRun.
|
|
34
|
+
expect(WorkflowRun.flags.format.options).toEqual(['json', 'text']);
|
|
35
|
+
expect(WorkflowRun.flags.format.default).toBe('text');
|
|
34
36
|
expect(WorkflowRun.flags.input.required).toBe(false);
|
|
35
37
|
});
|
|
36
38
|
it('should have optional scenario argument', async () => {
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
-
import { type WorkflowRun } from '#services/workflow_runs.js';
|
|
3
2
|
export default class WorkflowRunsList extends Command {
|
|
4
3
|
static description: string;
|
|
5
|
-
static enableJsonFlag: boolean;
|
|
6
4
|
static examples: string[];
|
|
7
5
|
static args: {
|
|
8
6
|
workflowName: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
@@ -12,6 +10,6 @@ export default class WorkflowRunsList extends Command {
|
|
|
12
10
|
limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
11
|
format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
12
|
};
|
|
15
|
-
run(): Promise<
|
|
13
|
+
run(): Promise<void>;
|
|
16
14
|
catch(error: Error): Promise<void>;
|
|
17
15
|
}
|
|
@@ -5,6 +5,7 @@ import { formatDate, formatDurationFromTimestamps } from '#utils/date_formatter.
|
|
|
5
5
|
import { handleApiError } from '#utils/error_handler.js';
|
|
6
6
|
const OUTPUT_FORMAT = {
|
|
7
7
|
TABLE: 'table',
|
|
8
|
+
JSON: 'json',
|
|
8
9
|
TEXT: 'text'
|
|
9
10
|
};
|
|
10
11
|
function createRunsTable(runs) {
|
|
@@ -36,7 +37,13 @@ function formatRunsAsText(runs) {
|
|
|
36
37
|
return `${run.workflowId} (${run.workflowType}) - ${run.status} [${duration}]`;
|
|
37
38
|
}).join('\n');
|
|
38
39
|
}
|
|
40
|
+
function formatRunsAsJson(runs) {
|
|
41
|
+
return JSON.stringify(runs, null, 2);
|
|
42
|
+
}
|
|
39
43
|
function formatRuns(runs, format) {
|
|
44
|
+
if (format === OUTPUT_FORMAT.JSON) {
|
|
45
|
+
return formatRunsAsJson(runs);
|
|
46
|
+
}
|
|
40
47
|
if (format === OUTPUT_FORMAT.TABLE) {
|
|
41
48
|
return createRunsTable(runs);
|
|
42
49
|
}
|
|
@@ -44,13 +51,12 @@ function formatRuns(runs, format) {
|
|
|
44
51
|
}
|
|
45
52
|
export default class WorkflowRunsList extends Command {
|
|
46
53
|
static description = 'List workflow runs with optional filtering by workflow type';
|
|
47
|
-
static enableJsonFlag = true;
|
|
48
54
|
static examples = [
|
|
49
55
|
'<%= config.bin %> <%= command.id %>',
|
|
50
56
|
'<%= config.bin %> <%= command.id %> simple',
|
|
51
57
|
'<%= config.bin %> <%= command.id %> simple --limit 10',
|
|
52
58
|
'<%= config.bin %> <%= command.id %> --catalog my-catalog',
|
|
53
|
-
'<%= config.bin %> <%= command.id %> --json',
|
|
59
|
+
'<%= config.bin %> <%= command.id %> --format json',
|
|
54
60
|
'<%= config.bin %> <%= command.id %> --format table'
|
|
55
61
|
];
|
|
56
62
|
static args = {
|
|
@@ -72,8 +78,8 @@ export default class WorkflowRunsList extends Command {
|
|
|
72
78
|
}),
|
|
73
79
|
format: Flags.string({
|
|
74
80
|
char: 'f',
|
|
75
|
-
description: 'Output format
|
|
76
|
-
options: [OUTPUT_FORMAT.TABLE, OUTPUT_FORMAT.TEXT],
|
|
81
|
+
description: 'Output format',
|
|
82
|
+
options: [OUTPUT_FORMAT.TABLE, OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
|
|
77
83
|
default: OUTPUT_FORMAT.TABLE
|
|
78
84
|
})
|
|
79
85
|
};
|
|
@@ -84,19 +90,17 @@ export default class WorkflowRunsList extends Command {
|
|
|
84
90
|
catalog: flags.catalog,
|
|
85
91
|
limit: flags.limit
|
|
86
92
|
});
|
|
87
|
-
if (this.jsonEnabled()) {
|
|
88
|
-
return runs;
|
|
89
|
-
}
|
|
90
93
|
if (runs.length === 0) {
|
|
91
94
|
const filterMsg = args.workflowName ? ` for workflow type "${args.workflowName}"` : '';
|
|
92
95
|
this.log(`No workflow runs found${filterMsg}.`);
|
|
93
|
-
return
|
|
96
|
+
return;
|
|
94
97
|
}
|
|
95
98
|
const output = formatRuns(runs, flags.format);
|
|
96
99
|
this.log(output);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
+
if (flags.format !== OUTPUT_FORMAT.JSON) {
|
|
101
|
+
const filterMsg = args.workflowName ? ` of type "${args.workflowName}"` : '';
|
|
102
|
+
this.log(`\nFound ${count} run(s)${filterMsg}`);
|
|
103
|
+
}
|
|
100
104
|
}
|
|
101
105
|
async catch(error) {
|
|
102
106
|
return handleApiError(error, (...args) => this.error(...args), {
|