@outputai/cli 0.10.1-next.3d1f9bd.0 → 0.10.1-next.442c500.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/api/generated/api.d.ts +81 -26
- package/dist/api/generated/api.js +7 -4
- package/dist/assets/docker/docker-compose-dev.yml +2 -2
- package/dist/commands/workflow/monitor.d.ts +5 -20
- package/dist/commands/workflow/monitor.js +20 -182
- package/dist/commands/workflow/monitor.spec.js +82 -3
- package/dist/commands/workflow/result.js +2 -2
- package/dist/commands/workflow/result.spec.js +65 -1
- package/dist/commands/workflow/run.js +10 -3
- package/dist/commands/workflow/run.spec.js +42 -5
- package/dist/commands/workflow/start.d.ts +7 -1
- package/dist/commands/workflow/start.js +107 -12
- package/dist/commands/workflow/start.spec.js +282 -5
- package/dist/commands/workflow/status.spec.js +1 -1
- package/dist/commands/workflow/{test_eval.d.ts → test.d.ts} +0 -1
- package/dist/commands/workflow/{test_eval.js → test.js} +0 -1
- package/dist/commands/workflow/{test_eval.spec.js → test.spec.js} +4 -4
- package/dist/generated/framework_version.json +1 -1
- package/dist/services/monitor_stream.d.ts +62 -0
- package/dist/services/monitor_stream.js +285 -0
- package/dist/services/monitor_stream.spec.d.ts +1 -0
- package/dist/services/monitor_stream.spec.js +285 -0
- package/dist/services/workflow_history.js +2 -2
- package/dist/templates/agent_instructions/CLAUDE.md.template +4 -2
- package/dist/templates/project/README.md.template +3 -1
- package/dist/templates/project/package.json.template +2 -2
- package/dist/utils/env_loader.js +6 -2
- package/dist/utils/env_loader.spec.js +61 -32
- package/dist/utils/error_handler.d.ts +10 -0
- package/dist/utils/error_handler.js +14 -0
- package/dist/utils/error_handler.spec.d.ts +1 -0
- package/dist/utils/error_handler.spec.js +62 -0
- package/dist/utils/format_workflow_result.d.ts +15 -3
- package/dist/utils/format_workflow_result.js +39 -6
- package/dist/utils/format_workflow_result.spec.js +39 -6
- package/dist/utils/monitor_flags.d.ts +35 -0
- package/dist/utils/monitor_flags.js +76 -0
- package/dist/utils/normalize_workflow_status.d.ts +4 -3
- package/dist/utils/normalize_workflow_status.js +12 -3
- package/dist/utils/normalize_workflow_status.spec.js +3 -0
- package/dist/utils/resolve_input.d.ts +9 -1
- package/dist/utils/resolve_input.js +8 -2
- package/dist/utils/resolve_input.spec.d.ts +1 -0
- package/dist/utils/resolve_input.spec.js +75 -0
- package/dist/views/dev/components/workflow_status.js +1 -1
- package/dist/views/dev/hooks/use_run_detail.js +4 -4
- package/dist/views/dev/hooks/use_run_detail.spec.js +1 -1
- package/dist/views/dev/panels/runs_panel.js +2 -2
- package/oclif.manifest.json +54 -9
- package/package.json +6 -8
- /package/dist/commands/workflow/{test_eval.spec.d.ts → test.spec.d.ts} +0 -0
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
vi.mock('
|
|
3
|
+
vi.mock('#api/generated/api.js', () => ({
|
|
3
4
|
getWorkflowIdResult: vi.fn()
|
|
4
5
|
}));
|
|
5
6
|
describe('workflow result command', () => {
|
|
6
7
|
beforeEach(() => {
|
|
7
8
|
vi.clearAllMocks();
|
|
9
|
+
process.exitCode = undefined;
|
|
8
10
|
});
|
|
9
11
|
describe('command definition', () => {
|
|
10
12
|
it('should export a valid OCLIF command', async () => {
|
|
@@ -18,4 +20,66 @@ describe('workflow result command', () => {
|
|
|
18
20
|
expect(WorkflowResult.enableJsonFlag).toBe(true);
|
|
19
21
|
});
|
|
20
22
|
});
|
|
23
|
+
describe('run()', () => {
|
|
24
|
+
const runCommand = async (data) => {
|
|
25
|
+
const WorkflowResult = (await import('./result.js')).default;
|
|
26
|
+
const { getWorkflowIdResult } = await import('#api/generated/api.js');
|
|
27
|
+
const cmd = new WorkflowResult(['wf-1'], {});
|
|
28
|
+
cmd.log = vi.fn();
|
|
29
|
+
cmd.parse = vi.fn().mockResolvedValue({ args: { workflowId: 'wf-1' } });
|
|
30
|
+
vi.mocked(getWorkflowIdResult).mockResolvedValue({
|
|
31
|
+
data,
|
|
32
|
+
status: 200,
|
|
33
|
+
headers: new Headers()
|
|
34
|
+
});
|
|
35
|
+
const result = await cmd.run();
|
|
36
|
+
return { cmd, result, getWorkflowIdResult };
|
|
37
|
+
};
|
|
38
|
+
it('returns and formats a legacy result', async () => {
|
|
39
|
+
const data = {
|
|
40
|
+
workflowId: 'wf-1',
|
|
41
|
+
runId: 'run-1',
|
|
42
|
+
status: 'failed',
|
|
43
|
+
input: {},
|
|
44
|
+
output: null,
|
|
45
|
+
trace: null,
|
|
46
|
+
error: 'Legacy failure',
|
|
47
|
+
errorDetails: null
|
|
48
|
+
};
|
|
49
|
+
const { cmd, result, getWorkflowIdResult } = await runCommand(data);
|
|
50
|
+
expect(getWorkflowIdResult).toHaveBeenCalledWith('wf-1');
|
|
51
|
+
expect(cmd.log).toHaveBeenCalledWith(expect.stringContaining('Error: Legacy failure'));
|
|
52
|
+
expect(result).toEqual(data);
|
|
53
|
+
expect(process.exitCode).toBe(1);
|
|
54
|
+
});
|
|
55
|
+
it('returns and formats a current result', async () => {
|
|
56
|
+
const data = {
|
|
57
|
+
v: '2',
|
|
58
|
+
workflowId: 'wf-1',
|
|
59
|
+
runId: 'run-1',
|
|
60
|
+
status: 'failed',
|
|
61
|
+
input: {},
|
|
62
|
+
output: null,
|
|
63
|
+
trace: null,
|
|
64
|
+
error: { name: 'ValidationError', message: 'Invalid input' }
|
|
65
|
+
};
|
|
66
|
+
const { result } = await runCommand(data);
|
|
67
|
+
expect(result).toEqual(data);
|
|
68
|
+
expect(process.exitCode).toBe(1);
|
|
69
|
+
});
|
|
70
|
+
it('sets a failure exit code for the previous canceled spelling', async () => {
|
|
71
|
+
const data = {
|
|
72
|
+
workflowId: 'wf-1',
|
|
73
|
+
runId: 'run-1',
|
|
74
|
+
status: 'canceled',
|
|
75
|
+
input: {},
|
|
76
|
+
output: null,
|
|
77
|
+
trace: null,
|
|
78
|
+
error: 'Workflow was canceled',
|
|
79
|
+
errorDetails: null
|
|
80
|
+
};
|
|
81
|
+
await runCommand(data);
|
|
82
|
+
expect(process.exitCode).toBe(1);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
21
85
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { postWorkflowRun } from '#api/generated/api.js';
|
|
3
|
-
import { formatWorkflowResult,
|
|
3
|
+
import { formatWorkflowResult, isErrorStatus } from '#utils/format_workflow_result.js';
|
|
4
4
|
import { handleApiError } from '#utils/error_handler.js';
|
|
5
5
|
import { resolveInput } from '#utils/resolve_input.js';
|
|
6
6
|
import { getRetryDelayFromResponse } from '#utils/header_utils.js';
|
|
@@ -63,7 +63,14 @@ export default class WorkflowRun extends Command {
|
|
|
63
63
|
};
|
|
64
64
|
async run() {
|
|
65
65
|
const { args, flags } = await this.parse(WorkflowRun);
|
|
66
|
-
const input = await resolveInput(
|
|
66
|
+
const input = await resolveInput({
|
|
67
|
+
workflowName: args.workflowName,
|
|
68
|
+
scenario: args.scenario,
|
|
69
|
+
inputFlag: flags.input,
|
|
70
|
+
commandName: 'run',
|
|
71
|
+
catalog: flags.catalog,
|
|
72
|
+
json: this.jsonEnabled()
|
|
73
|
+
});
|
|
67
74
|
this.log(`Executing workflow: ${args.workflowName}...`);
|
|
68
75
|
const response = await executeWorkflow({
|
|
69
76
|
body: {
|
|
@@ -79,7 +86,7 @@ export default class WorkflowRun extends Command {
|
|
|
79
86
|
}
|
|
80
87
|
const data = response.data;
|
|
81
88
|
this.log(`\n${formatWorkflowResult(data)}`);
|
|
82
|
-
if (
|
|
89
|
+
if (isErrorStatus(data.status)) {
|
|
83
90
|
process.exitCode = 1;
|
|
84
91
|
}
|
|
85
92
|
return data;
|
|
@@ -59,12 +59,26 @@ describe('workflow run command', () => {
|
|
|
59
59
|
const { cmd, postWorkflowRun, resolveInput } = await createCommand();
|
|
60
60
|
resolveInput.mockResolvedValue({ key: 'value' });
|
|
61
61
|
postWorkflowRun.mockResolvedValue({
|
|
62
|
-
data: {
|
|
62
|
+
data: {
|
|
63
|
+
v: '2',
|
|
64
|
+
workflowId: 'wf-1',
|
|
65
|
+
runId: 'run-1',
|
|
66
|
+
status: 'completed',
|
|
67
|
+
input: { key: 'value' },
|
|
68
|
+
output: 'ok',
|
|
69
|
+
trace: null,
|
|
70
|
+
error: null
|
|
71
|
+
},
|
|
63
72
|
status: 200,
|
|
64
73
|
headers: new Headers()
|
|
65
74
|
});
|
|
66
75
|
await cmd.run();
|
|
67
|
-
expect(resolveInput).toHaveBeenCalledWith(
|
|
76
|
+
expect(resolveInput).toHaveBeenCalledWith(expect.objectContaining({
|
|
77
|
+
workflowName: 'my_workflow',
|
|
78
|
+
commandName: 'run',
|
|
79
|
+
catalog: undefined,
|
|
80
|
+
json: false
|
|
81
|
+
}));
|
|
68
82
|
expect(postWorkflowRun).toHaveBeenCalledTimes(1);
|
|
69
83
|
expect(postWorkflowRun).toHaveBeenCalledWith({ workflowName: 'my_workflow', input: { key: 'value' }, catalog: undefined }, expect.objectContaining({ config: { timeout: 600000 } }));
|
|
70
84
|
expect(cmd.log).toHaveBeenCalledWith('Executing workflow: my_workflow...');
|
|
@@ -78,12 +92,26 @@ describe('workflow run command', () => {
|
|
|
78
92
|
});
|
|
79
93
|
resolveInput.mockResolvedValue({ key: 'value' });
|
|
80
94
|
postWorkflowRun.mockResolvedValue({
|
|
81
|
-
data: {
|
|
95
|
+
data: {
|
|
96
|
+
v: '2',
|
|
97
|
+
workflowId: 'wf-1',
|
|
98
|
+
runId: 'run-1',
|
|
99
|
+
status: 'completed',
|
|
100
|
+
input: { key: 'value' },
|
|
101
|
+
output: {},
|
|
102
|
+
trace: null,
|
|
103
|
+
error: null
|
|
104
|
+
},
|
|
82
105
|
status: 200,
|
|
83
106
|
headers: new Headers()
|
|
84
107
|
});
|
|
85
108
|
await cmd.run();
|
|
86
|
-
expect(resolveInput).toHaveBeenCalledWith(
|
|
109
|
+
expect(resolveInput).toHaveBeenCalledWith(expect.objectContaining({
|
|
110
|
+
workflowName: 'my_workflow',
|
|
111
|
+
scenario: 'basic',
|
|
112
|
+
commandName: 'run',
|
|
113
|
+
catalog: 'my-catalog'
|
|
114
|
+
}));
|
|
87
115
|
expect(postWorkflowRun).toHaveBeenCalledWith(expect.objectContaining({ catalog: 'my-catalog' }), expect.anything());
|
|
88
116
|
});
|
|
89
117
|
it('retries when response has Retry-After and succeeds on second attempt', async () => {
|
|
@@ -93,7 +121,16 @@ describe('workflow run command', () => {
|
|
|
93
121
|
postWorkflowRun
|
|
94
122
|
.mockRejectedValueOnce(new HttpError('Unavailable', { status: 503, headers }))
|
|
95
123
|
.mockResolvedValueOnce({
|
|
96
|
-
data: {
|
|
124
|
+
data: {
|
|
125
|
+
v: '2',
|
|
126
|
+
workflowId: 'wf-1',
|
|
127
|
+
runId: 'run-1',
|
|
128
|
+
status: 'completed',
|
|
129
|
+
input: {},
|
|
130
|
+
output: {},
|
|
131
|
+
trace: null,
|
|
132
|
+
error: null
|
|
133
|
+
},
|
|
97
134
|
status: 200,
|
|
98
135
|
headers: new Headers()
|
|
99
136
|
});
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
|
+
import { type PostWorkflowStart200 } from '#api/generated/api.js';
|
|
2
3
|
export default class WorkflowStart extends Command {
|
|
3
4
|
static description: string;
|
|
5
|
+
static enableJsonFlag: boolean;
|
|
4
6
|
static examples: string[];
|
|
5
7
|
static args: {
|
|
6
8
|
workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
7
9
|
scenario: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
|
|
8
10
|
};
|
|
9
11
|
static flags: {
|
|
12
|
+
'include-payloads': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
|
+
interval: import("@oclif/core/interfaces").OptionFlag<number | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
color: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
15
|
input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
11
16
|
catalog: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
monitor: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
18
|
};
|
|
13
|
-
run(): Promise<
|
|
19
|
+
run(): Promise<PostWorkflowStart200>;
|
|
14
20
|
catch(error: Error): Promise<void>;
|
|
15
21
|
}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { postWorkflowStart } from '#api/generated/api.js';
|
|
3
|
-
import {
|
|
3
|
+
import { commandStreamIo, monitorErrorOverrides, streamWorkflowUpdates } from '#services/monitor_stream.js';
|
|
4
|
+
import { handleApiError, handleCommandError } from '#utils/error_handler.js';
|
|
5
|
+
import { isErrorStatus } from '#utils/format_workflow_result.js';
|
|
6
|
+
import { gatedMonitorStreamFlags, MONITOR_DEFAULTS } from '#utils/monitor_flags.js';
|
|
4
7
|
import { resolveInput } from '#utils/resolve_input.js';
|
|
8
|
+
/**
|
|
9
|
+
* Distinct from 1 (the workflow itself failed) and 2 (usage): the workflow was
|
|
10
|
+
* started and is still running, only the attached stream gave up. A caller that
|
|
11
|
+
* retries on exit 1 would otherwise re-submit a workflow that is already running.
|
|
12
|
+
*/
|
|
13
|
+
const MONITOR_FAILED_EXIT_CODE = 3;
|
|
5
14
|
export default class WorkflowStart extends Command {
|
|
6
15
|
static description = 'Start a workflow asynchronously without waiting for completion';
|
|
16
|
+
static enableJsonFlag = true;
|
|
7
17
|
static examples = [
|
|
8
18
|
'<%= config.bin %> <%= command.id %> simple basic_input',
|
|
9
19
|
'<%= config.bin %> <%= command.id %> simple --input \'{"values":[1,2,3]}\'',
|
|
10
20
|
'<%= config.bin %> <%= command.id %> simple --input input.json',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> simple --input
|
|
21
|
+
'<%= config.bin %> <%= command.id %> simple --input input.json --monitor',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> simple --input \'{"key":"value"}\' --catalog my-catalog',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> simple --json'
|
|
12
24
|
];
|
|
13
25
|
static args = {
|
|
14
26
|
workflowName: Args.string({
|
|
@@ -33,11 +45,45 @@ export default class WorkflowStart extends Command {
|
|
|
33
45
|
deprecateAliases: true,
|
|
34
46
|
description: 'Catalog name for workflow execution (defaults to OUTPUT_CATALOG_ID)',
|
|
35
47
|
env: 'OUTPUT_CATALOG_ID'
|
|
36
|
-
})
|
|
48
|
+
}),
|
|
49
|
+
// No `default: false`: a defaulted flag counts as present, so it would
|
|
50
|
+
// satisfy the `dependsOn` guard the three flags in `gatedMonitorStreamFlags`
|
|
51
|
+
// point at, letting `--interval` and friends be accepted (and then ignored)
|
|
52
|
+
// on a plain `workflow start`. Those three omit their own defaults for a
|
|
53
|
+
// different reason — see `gatedMonitorStreamFlags`.
|
|
54
|
+
//
|
|
55
|
+
// No `exclusive: [ 'json' ]` either: oclif's own rejection would fire first
|
|
56
|
+
// and print a bare "--json=true cannot also be provided", pre-empting the
|
|
57
|
+
// guard in `run()` that explains what to use instead. That guard covers both
|
|
58
|
+
// triggers (`--json` on argv, and `CONTENT_TYPE=json`) with one message.
|
|
59
|
+
monitor: Flags.boolean({
|
|
60
|
+
char: 'm',
|
|
61
|
+
description: 'After starting, attach and stream status updates until the workflow ends ' +
|
|
62
|
+
'(Ctrl+C detaches; the workflow keeps running). Cannot be combined with --json'
|
|
63
|
+
}),
|
|
64
|
+
...gatedMonitorStreamFlags('monitor')
|
|
37
65
|
};
|
|
38
66
|
async run() {
|
|
39
67
|
const { args, flags } = await this.parse(WorkflowStart);
|
|
40
|
-
|
|
68
|
+
// The built-in `--json` flag is injected by `enableJsonFlag`, and
|
|
69
|
+
// `CONTENT_TYPE=json` turns it on without it appearing on argv at all, so
|
|
70
|
+
// this runtime check — not an oclif flag relationship — is what catches
|
|
71
|
+
// every route into json mode. Streaming under `--json` is worse than
|
|
72
|
+
// useless: `Command.log()` is a no-op while json is enabled, so every update
|
|
73
|
+
// would be swallowed and the command would simply hang until the workflow
|
|
74
|
+
// ended.
|
|
75
|
+
if (flags.monitor && this.jsonEnabled()) {
|
|
76
|
+
this.error('Cannot combine --monitor with --json. Use "workflow run --json" to wait for the result, ' +
|
|
77
|
+
'or "workflow monitor <id> --format json" to stream newline-delimited JSON.', { exit: 2 });
|
|
78
|
+
}
|
|
79
|
+
const input = await resolveInput({
|
|
80
|
+
workflowName: args.workflowName,
|
|
81
|
+
scenario: args.scenario,
|
|
82
|
+
inputFlag: flags.input,
|
|
83
|
+
commandName: 'start',
|
|
84
|
+
catalog: flags.catalog,
|
|
85
|
+
json: this.jsonEnabled()
|
|
86
|
+
});
|
|
41
87
|
this.log(`Starting workflow: ${args.workflowName}...`);
|
|
42
88
|
const response = await postWorkflowStart({
|
|
43
89
|
workflowName: args.workflowName,
|
|
@@ -48,18 +94,67 @@ export default class WorkflowStart extends Command {
|
|
|
48
94
|
this.error('API returned invalid response', { exit: 1 });
|
|
49
95
|
}
|
|
50
96
|
const result = response.data;
|
|
51
|
-
const
|
|
97
|
+
const started = [
|
|
52
98
|
'Workflow started successfully',
|
|
53
99
|
'',
|
|
54
|
-
`Workflow ID: ${result.workflowId || 'unknown'}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
100
|
+
`Workflow ID: ${result.workflowId || 'unknown'}`
|
|
101
|
+
];
|
|
102
|
+
if (!flags.monitor) {
|
|
103
|
+
this.log(`\n${[
|
|
104
|
+
...started,
|
|
105
|
+
'',
|
|
106
|
+
`Use "workflow status ${result.workflowId || '<workflow-id>'}" to check the workflow status`,
|
|
107
|
+
`Use "workflow result ${result.workflowId || '<workflow-id>'}" to get the workflow result when complete`
|
|
108
|
+
].join('\n')}`);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
// Checked before the banner prints: "Workflow started successfully" followed
|
|
112
|
+
// immediately by a failure contradicts itself, and the `unknown` placeholder
|
|
113
|
+
// id it would show is not something the user can act on. Exit 3, not 1 — the
|
|
114
|
+
// start itself succeeded, so this is the "started but unmonitorable" case.
|
|
115
|
+
if (!result.workflowId) {
|
|
116
|
+
this.error('The workflow was started, but the API did not return a workflow ID, so it cannot be monitored. ' +
|
|
117
|
+
'Use "workflow runs list" to find it.', { exit: MONITOR_FAILED_EXIT_CODE });
|
|
118
|
+
}
|
|
119
|
+
this.log(`\n${started.join('\n')}`);
|
|
120
|
+
this.log('');
|
|
121
|
+
try {
|
|
122
|
+
const status = await streamWorkflowUpdates({
|
|
123
|
+
workflowId: result.workflowId,
|
|
124
|
+
// Pin to the run just started rather than letting the monitor resolve
|
|
125
|
+
// "latest run" — with a retry or a rapid re-start those can differ.
|
|
126
|
+
runId: result.runId ?? undefined,
|
|
127
|
+
includePayloads: flags['include-payloads'] ?? MONITOR_DEFAULTS.includePayloads,
|
|
128
|
+
interval: flags.interval ?? MONITOR_DEFAULTS.interval,
|
|
129
|
+
// Always text: monitoring under json mode is rejected above, so the
|
|
130
|
+
// NDJSON path is `workflow monitor --format json`.
|
|
131
|
+
json: false,
|
|
132
|
+
color: flags.color ?? MONITOR_DEFAULTS.color
|
|
133
|
+
}, commandStreamIo(this));
|
|
134
|
+
// Monitoring reports the workflow's *progress*; the return value still has
|
|
135
|
+
// to be fetched separately, so name the command that does it. A failed run
|
|
136
|
+
// has no result to fetch, so point at the one that explains the failure.
|
|
137
|
+
if (status) {
|
|
138
|
+
this.log(isErrorStatus(status) ?
|
|
139
|
+
`\nUse "workflow debug ${result.workflowId}" to inspect the failure` :
|
|
140
|
+
`\nUse "workflow result ${result.workflowId}" to get the workflow result`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
// The workflow was started and is still running — only the stream gave up.
|
|
145
|
+
// Say so explicitly and exit on a code of its own, so this can't be read
|
|
146
|
+
// (by a human or by a CI job retrying on exit 1) as a failed start.
|
|
147
|
+
//
|
|
148
|
+
// `handleApiError`, not `handleCommandError`: an error the stream raised
|
|
149
|
+
// through `io.error` is already a CLIError, and passing it through would
|
|
150
|
+
// report it as a plain exit-1 failure rather than a live workflow.
|
|
151
|
+
handleApiError(error, message => this.error(`Workflow ${result.workflowId} started, but monitoring stopped:\n${message}\n` +
|
|
152
|
+
`The workflow is still running. Use "workflow status ${result.workflowId}" to check on it.`, { exit: MONITOR_FAILED_EXIT_CODE }), monitorErrorOverrides(error));
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
60
155
|
}
|
|
61
156
|
async catch(error) {
|
|
62
|
-
return
|
|
157
|
+
return handleCommandError(error, (...args) => this.error(...args), {
|
|
63
158
|
404: 'Workflow not found. Check the workflow name.'
|
|
64
159
|
});
|
|
65
160
|
}
|