@outputai/cli 0.1.1 → 0.1.2

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.
Files changed (278) hide show
  1. package/package.json +7 -7
  2. package/dist/api/generated/api.d.ts +0 -820
  3. package/dist/api/generated/api.js +0 -226
  4. package/dist/api/http_client.d.ts +0 -27
  5. package/dist/api/http_client.js +0 -71
  6. package/dist/api/orval_post_process.d.ts +0 -11
  7. package/dist/api/orval_post_process.js +0 -46
  8. package/dist/api/parser.d.ts +0 -17
  9. package/dist/api/parser.js +0 -68
  10. package/dist/assets/config/costs.yml +0 -309
  11. package/dist/assets/docker/docker-compose-dev.yml +0 -146
  12. package/dist/commands/credentials/edit.d.ts +0 -10
  13. package/dist/commands/credentials/edit.js +0 -67
  14. package/dist/commands/credentials/edit.spec.d.ts +0 -1
  15. package/dist/commands/credentials/edit.spec.js +0 -73
  16. package/dist/commands/credentials/get.d.ts +0 -13
  17. package/dist/commands/credentials/get.js +0 -46
  18. package/dist/commands/credentials/get.spec.d.ts +0 -1
  19. package/dist/commands/credentials/get.spec.js +0 -74
  20. package/dist/commands/credentials/init.d.ts +0 -11
  21. package/dist/commands/credentials/init.js +0 -45
  22. package/dist/commands/credentials/init.spec.d.ts +0 -1
  23. package/dist/commands/credentials/init.spec.js +0 -68
  24. package/dist/commands/credentials/show.d.ts +0 -10
  25. package/dist/commands/credentials/show.js +0 -33
  26. package/dist/commands/credentials/show.spec.d.ts +0 -1
  27. package/dist/commands/credentials/show.spec.js +0 -57
  28. package/dist/commands/dev/eject.d.ts +0 -11
  29. package/dist/commands/dev/eject.js +0 -58
  30. package/dist/commands/dev/eject.spec.d.ts +0 -1
  31. package/dist/commands/dev/eject.spec.js +0 -109
  32. package/dist/commands/dev/index.d.ts +0 -14
  33. package/dist/commands/dev/index.js +0 -173
  34. package/dist/commands/dev/index.spec.d.ts +0 -1
  35. package/dist/commands/dev/index.spec.js +0 -239
  36. package/dist/commands/init.d.ts +0 -12
  37. package/dist/commands/init.js +0 -37
  38. package/dist/commands/init.spec.d.ts +0 -1
  39. package/dist/commands/init.spec.js +0 -100
  40. package/dist/commands/update.d.ts +0 -14
  41. package/dist/commands/update.js +0 -120
  42. package/dist/commands/update.spec.d.ts +0 -1
  43. package/dist/commands/update.spec.js +0 -178
  44. package/dist/commands/workflow/cost.d.ts +0 -16
  45. package/dist/commands/workflow/cost.js +0 -71
  46. package/dist/commands/workflow/cost.spec.d.ts +0 -1
  47. package/dist/commands/workflow/cost.spec.js +0 -47
  48. package/dist/commands/workflow/dataset/generate.d.ts +0 -22
  49. package/dist/commands/workflow/dataset/generate.js +0 -143
  50. package/dist/commands/workflow/dataset/list.d.ts +0 -12
  51. package/dist/commands/workflow/dataset/list.js +0 -87
  52. package/dist/commands/workflow/debug.d.ts +0 -16
  53. package/dist/commands/workflow/debug.js +0 -60
  54. package/dist/commands/workflow/debug.spec.d.ts +0 -1
  55. package/dist/commands/workflow/debug.spec.js +0 -34
  56. package/dist/commands/workflow/generate.d.ts +0 -17
  57. package/dist/commands/workflow/generate.js +0 -85
  58. package/dist/commands/workflow/generate.spec.d.ts +0 -1
  59. package/dist/commands/workflow/generate.spec.js +0 -115
  60. package/dist/commands/workflow/list.d.ts +0 -22
  61. package/dist/commands/workflow/list.js +0 -152
  62. package/dist/commands/workflow/list.spec.d.ts +0 -1
  63. package/dist/commands/workflow/list.spec.js +0 -99
  64. package/dist/commands/workflow/plan.d.ts +0 -12
  65. package/dist/commands/workflow/plan.js +0 -66
  66. package/dist/commands/workflow/plan.spec.d.ts +0 -1
  67. package/dist/commands/workflow/plan.spec.js +0 -341
  68. package/dist/commands/workflow/reset.d.ts +0 -14
  69. package/dist/commands/workflow/reset.js +0 -51
  70. package/dist/commands/workflow/result.d.ts +0 -13
  71. package/dist/commands/workflow/result.js +0 -46
  72. package/dist/commands/workflow/result.spec.d.ts +0 -1
  73. package/dist/commands/workflow/result.spec.js +0 -23
  74. package/dist/commands/workflow/run.d.ts +0 -16
  75. package/dist/commands/workflow/run.js +0 -97
  76. package/dist/commands/workflow/run.spec.d.ts +0 -1
  77. package/dist/commands/workflow/run.spec.js +0 -110
  78. package/dist/commands/workflow/runs/list.d.ts +0 -14
  79. package/dist/commands/workflow/runs/list.js +0 -104
  80. package/dist/commands/workflow/start.d.ts +0 -15
  81. package/dist/commands/workflow/start.js +0 -62
  82. package/dist/commands/workflow/start.spec.d.ts +0 -1
  83. package/dist/commands/workflow/start.spec.js +0 -28
  84. package/dist/commands/workflow/status.d.ts +0 -13
  85. package/dist/commands/workflow/status.js +0 -57
  86. package/dist/commands/workflow/status.spec.d.ts +0 -1
  87. package/dist/commands/workflow/status.spec.js +0 -33
  88. package/dist/commands/workflow/stop.d.ts +0 -10
  89. package/dist/commands/workflow/stop.js +0 -31
  90. package/dist/commands/workflow/stop.spec.d.ts +0 -1
  91. package/dist/commands/workflow/stop.spec.js +0 -17
  92. package/dist/commands/workflow/terminate.d.ts +0 -13
  93. package/dist/commands/workflow/terminate.js +0 -39
  94. package/dist/commands/workflow/test_eval.d.ts +0 -20
  95. package/dist/commands/workflow/test_eval.js +0 -151
  96. package/dist/config.d.ts +0 -47
  97. package/dist/config.js +0 -47
  98. package/dist/generated/framework_version.json +0 -3
  99. package/dist/hooks/init.d.ts +0 -3
  100. package/dist/hooks/init.js +0 -30
  101. package/dist/hooks/init.spec.d.ts +0 -1
  102. package/dist/hooks/init.spec.js +0 -54
  103. package/dist/index.d.ts +0 -1
  104. package/dist/index.js +0 -1
  105. package/dist/index.spec.d.ts +0 -1
  106. package/dist/index.spec.js +0 -6
  107. package/dist/services/claude_client.d.ts +0 -30
  108. package/dist/services/claude_client.integration.test.d.ts +0 -1
  109. package/dist/services/claude_client.integration.test.js +0 -43
  110. package/dist/services/claude_client.js +0 -215
  111. package/dist/services/claude_client.spec.d.ts +0 -1
  112. package/dist/services/claude_client.spec.js +0 -145
  113. package/dist/services/coding_agents.d.ts +0 -36
  114. package/dist/services/coding_agents.js +0 -236
  115. package/dist/services/coding_agents.spec.d.ts +0 -1
  116. package/dist/services/coding_agents.spec.js +0 -256
  117. package/dist/services/copy_assets.spec.d.ts +0 -1
  118. package/dist/services/copy_assets.spec.js +0 -22
  119. package/dist/services/cost_calculator.d.ts +0 -18
  120. package/dist/services/cost_calculator.js +0 -359
  121. package/dist/services/cost_calculator.spec.d.ts +0 -1
  122. package/dist/services/cost_calculator.spec.js +0 -540
  123. package/dist/services/credentials_service.d.ts +0 -12
  124. package/dist/services/credentials_service.integration.test.d.ts +0 -1
  125. package/dist/services/credentials_service.integration.test.js +0 -66
  126. package/dist/services/credentials_service.js +0 -64
  127. package/dist/services/credentials_service.spec.d.ts +0 -1
  128. package/dist/services/credentials_service.spec.js +0 -106
  129. package/dist/services/datasets.d.ts +0 -20
  130. package/dist/services/datasets.js +0 -132
  131. package/dist/services/docker.d.ts +0 -39
  132. package/dist/services/docker.js +0 -160
  133. package/dist/services/docker.spec.d.ts +0 -1
  134. package/dist/services/docker.spec.js +0 -124
  135. package/dist/services/env_configurator.d.ts +0 -15
  136. package/dist/services/env_configurator.js +0 -163
  137. package/dist/services/env_configurator.spec.d.ts +0 -1
  138. package/dist/services/env_configurator.spec.js +0 -192
  139. package/dist/services/generate_plan_name@v1.prompt +0 -24
  140. package/dist/services/messages.d.ts +0 -9
  141. package/dist/services/messages.js +0 -338
  142. package/dist/services/messages.spec.d.ts +0 -1
  143. package/dist/services/messages.spec.js +0 -55
  144. package/dist/services/npm_update_service.d.ts +0 -6
  145. package/dist/services/npm_update_service.js +0 -87
  146. package/dist/services/npm_update_service.spec.d.ts +0 -1
  147. package/dist/services/npm_update_service.spec.js +0 -104
  148. package/dist/services/project_scaffold.d.ts +0 -31
  149. package/dist/services/project_scaffold.js +0 -212
  150. package/dist/services/project_scaffold.spec.d.ts +0 -1
  151. package/dist/services/project_scaffold.spec.js +0 -122
  152. package/dist/services/s3_trace_downloader.d.ts +0 -12
  153. package/dist/services/s3_trace_downloader.js +0 -57
  154. package/dist/services/template_processor.d.ts +0 -14
  155. package/dist/services/template_processor.js +0 -57
  156. package/dist/services/trace_reader.d.ts +0 -16
  157. package/dist/services/trace_reader.js +0 -57
  158. package/dist/services/trace_reader.spec.d.ts +0 -1
  159. package/dist/services/trace_reader.spec.js +0 -78
  160. package/dist/services/version_check.d.ts +0 -6
  161. package/dist/services/version_check.js +0 -52
  162. package/dist/services/version_check.spec.d.ts +0 -1
  163. package/dist/services/version_check.spec.js +0 -106
  164. package/dist/services/workflow_builder.d.ts +0 -16
  165. package/dist/services/workflow_builder.js +0 -86
  166. package/dist/services/workflow_builder.spec.d.ts +0 -1
  167. package/dist/services/workflow_builder.spec.js +0 -165
  168. package/dist/services/workflow_generator.d.ts +0 -5
  169. package/dist/services/workflow_generator.js +0 -40
  170. package/dist/services/workflow_generator.spec.d.ts +0 -1
  171. package/dist/services/workflow_generator.spec.js +0 -77
  172. package/dist/services/workflow_planner.d.ts +0 -15
  173. package/dist/services/workflow_planner.js +0 -48
  174. package/dist/services/workflow_planner.spec.d.ts +0 -1
  175. package/dist/services/workflow_planner.spec.js +0 -122
  176. package/dist/services/workflow_runs.d.ts +0 -14
  177. package/dist/services/workflow_runs.js +0 -25
  178. package/dist/templates/agent_instructions/CLAUDE.md.template +0 -19
  179. package/dist/templates/agent_instructions/dotclaude/settings.json.template +0 -29
  180. package/dist/templates/project/.env.example.template +0 -9
  181. package/dist/templates/project/.gitignore.template +0 -35
  182. package/dist/templates/project/README.md.template +0 -100
  183. package/dist/templates/project/config/costs.yml.template +0 -29
  184. package/dist/templates/project/package.json.template +0 -25
  185. package/dist/templates/project/src/clients/jina.ts.template +0 -30
  186. package/dist/templates/project/src/shared/utils/string.ts.template +0 -3
  187. package/dist/templates/project/src/shared/utils/url.ts.template +0 -15
  188. package/dist/templates/project/src/workflows/blog_evaluator/evaluators.ts.template +0 -23
  189. package/dist/templates/project/src/workflows/blog_evaluator/prompts/signal_noise@v1.prompt.template +0 -26
  190. package/dist/templates/project/src/workflows/blog_evaluator/scenarios/paulgraham_hwh.json.template +0 -3
  191. package/dist/templates/project/src/workflows/blog_evaluator/steps.ts.template +0 -27
  192. package/dist/templates/project/src/workflows/blog_evaluator/types.ts.template +0 -30
  193. package/dist/templates/project/src/workflows/blog_evaluator/utils.ts.template +0 -15
  194. package/dist/templates/project/src/workflows/blog_evaluator/workflow.ts.template +0 -27
  195. package/dist/templates/project/tsconfig.json.template +0 -20
  196. package/dist/templates/workflow/README.md.template +0 -216
  197. package/dist/templates/workflow/evaluators.ts.template +0 -21
  198. package/dist/templates/workflow/prompts/example@v1.prompt.template +0 -15
  199. package/dist/templates/workflow/scenarios/test_input.json.template +0 -3
  200. package/dist/templates/workflow/steps.ts.template +0 -20
  201. package/dist/templates/workflow/types.ts.template +0 -13
  202. package/dist/templates/workflow/workflow.ts.template +0 -23
  203. package/dist/test_helpers/mocks.d.ts +0 -38
  204. package/dist/test_helpers/mocks.js +0 -77
  205. package/dist/types/cost.d.ts +0 -149
  206. package/dist/types/cost.js +0 -6
  207. package/dist/types/domain.d.ts +0 -20
  208. package/dist/types/domain.js +0 -4
  209. package/dist/types/errors.d.ts +0 -68
  210. package/dist/types/errors.js +0 -100
  211. package/dist/types/errors.spec.d.ts +0 -1
  212. package/dist/types/errors.spec.js +0 -18
  213. package/dist/types/generator.d.ts +0 -26
  214. package/dist/types/generator.js +0 -1
  215. package/dist/types/trace.d.ts +0 -161
  216. package/dist/types/trace.js +0 -18
  217. package/dist/utils/claude.d.ts +0 -5
  218. package/dist/utils/claude.js +0 -19
  219. package/dist/utils/claude.spec.d.ts +0 -1
  220. package/dist/utils/claude.spec.js +0 -119
  221. package/dist/utils/constants.d.ts +0 -5
  222. package/dist/utils/constants.js +0 -4
  223. package/dist/utils/cost_formatter.d.ts +0 -5
  224. package/dist/utils/cost_formatter.js +0 -218
  225. package/dist/utils/date_formatter.d.ts +0 -23
  226. package/dist/utils/date_formatter.js +0 -49
  227. package/dist/utils/env_loader.d.ts +0 -1
  228. package/dist/utils/env_loader.js +0 -22
  229. package/dist/utils/env_loader.spec.d.ts +0 -1
  230. package/dist/utils/env_loader.spec.js +0 -43
  231. package/dist/utils/error_handler.d.ts +0 -8
  232. package/dist/utils/error_handler.js +0 -71
  233. package/dist/utils/error_utils.d.ts +0 -24
  234. package/dist/utils/error_utils.js +0 -87
  235. package/dist/utils/file_system.d.ts +0 -3
  236. package/dist/utils/file_system.js +0 -33
  237. package/dist/utils/format_workflow_result.d.ts +0 -5
  238. package/dist/utils/format_workflow_result.js +0 -18
  239. package/dist/utils/format_workflow_result.spec.d.ts +0 -1
  240. package/dist/utils/format_workflow_result.spec.js +0 -81
  241. package/dist/utils/framework_version.d.ts +0 -4
  242. package/dist/utils/framework_version.js +0 -4
  243. package/dist/utils/framework_version.spec.d.ts +0 -1
  244. package/dist/utils/framework_version.spec.js +0 -13
  245. package/dist/utils/header_utils.d.ts +0 -12
  246. package/dist/utils/header_utils.js +0 -29
  247. package/dist/utils/header_utils.spec.d.ts +0 -1
  248. package/dist/utils/header_utils.spec.js +0 -52
  249. package/dist/utils/input_parser.d.ts +0 -1
  250. package/dist/utils/input_parser.js +0 -19
  251. package/dist/utils/output_formatter.d.ts +0 -2
  252. package/dist/utils/output_formatter.js +0 -11
  253. package/dist/utils/paths.d.ts +0 -25
  254. package/dist/utils/paths.js +0 -36
  255. package/dist/utils/process.d.ts +0 -4
  256. package/dist/utils/process.js +0 -50
  257. package/dist/utils/resolve_input.d.ts +0 -1
  258. package/dist/utils/resolve_input.js +0 -22
  259. package/dist/utils/scenario_resolver.d.ts +0 -9
  260. package/dist/utils/scenario_resolver.js +0 -93
  261. package/dist/utils/scenario_resolver.spec.d.ts +0 -1
  262. package/dist/utils/scenario_resolver.spec.js +0 -214
  263. package/dist/utils/secret_sanitizer.d.ts +0 -1
  264. package/dist/utils/secret_sanitizer.js +0 -29
  265. package/dist/utils/sleep.d.ts +0 -5
  266. package/dist/utils/sleep.js +0 -5
  267. package/dist/utils/template.d.ts +0 -9
  268. package/dist/utils/template.js +0 -30
  269. package/dist/utils/template.spec.d.ts +0 -1
  270. package/dist/utils/template.spec.js +0 -77
  271. package/dist/utils/trace_extractor.d.ts +0 -27
  272. package/dist/utils/trace_extractor.js +0 -53
  273. package/dist/utils/trace_formatter.d.ts +0 -11
  274. package/dist/utils/trace_formatter.js +0 -402
  275. package/dist/utils/validation.d.ts +0 -13
  276. package/dist/utils/validation.js +0 -25
  277. package/dist/utils/validation.spec.d.ts +0 -1
  278. package/dist/utils/validation.spec.js +0 -140
@@ -1,23 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('../../api/generated/api.js', () => ({
3
- getWorkflowIdResult: vi.fn()
4
- }));
5
- describe('workflow result command', () => {
6
- beforeEach(() => {
7
- vi.clearAllMocks();
8
- });
9
- describe('command definition', () => {
10
- it('should export a valid OCLIF command', async () => {
11
- const WorkflowResult = (await import('./result.js')).default;
12
- expect(WorkflowResult).toBeDefined();
13
- expect(WorkflowResult.description).toContain('Get workflow execution result');
14
- expect(WorkflowResult.args).toHaveProperty('workflowId');
15
- expect(WorkflowResult.flags).toHaveProperty('format');
16
- });
17
- it('should have correct flag configuration', async () => {
18
- const WorkflowResult = (await import('./result.js')).default;
19
- expect(WorkflowResult.flags.format.options).toEqual(['json', 'text']);
20
- expect(WorkflowResult.flags.format.default).toBe('text');
21
- });
22
- });
23
- });
@@ -1,16 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class WorkflowRun extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
- scenario: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- 'task-queue': 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>;
13
- };
14
- run(): Promise<void>;
15
- catch(error: Error): Promise<void>;
16
- }
@@ -1,97 +0,0 @@
1
- import { Args, Command, Flags } from '@oclif/core';
2
- import { postWorkflowRun } from '#api/generated/api.js';
3
- import { OUTPUT_FORMAT } from '#utils/constants.js';
4
- import { formatOutput } from '#utils/output_formatter.js';
5
- import { formatWorkflowResult, ERROR_STATUSES } from '#utils/format_workflow_result.js';
6
- import { handleApiError } from '#utils/error_handler.js';
7
- import { resolveInput } from '#utils/resolve_input.js';
8
- import { getRetryDelayFromResponse } from '#utils/header_utils.js';
9
- import { sleep } from '#utils/sleep.js';
10
- import { HttpError } from '#api/http_client.js';
11
- const MAX_RETRIES = 3;
12
- async function executeWorkflow(args) {
13
- const { body, options, log, attempt = 0 } = args;
14
- try {
15
- return await postWorkflowRun(body, options);
16
- }
17
- catch (error) {
18
- if (!(error instanceof HttpError) || attempt >= MAX_RETRIES) {
19
- throw error;
20
- }
21
- const { response } = error;
22
- const delay = getRetryDelayFromResponse(response);
23
- if (delay === null) {
24
- throw error;
25
- }
26
- log(`Server returned ${response.status} with header "Retry-After". Retrying in ${delay / 1000}s...`);
27
- await sleep(delay);
28
- return executeWorkflow({ body, options, log, attempt: attempt + 1 });
29
- }
30
- }
31
- export default class WorkflowRun extends Command {
32
- static description = 'Execute a workflow synchronously and wait for completion';
33
- static examples = [
34
- '<%= config.bin %> <%= command.id %> simple basic_input',
35
- '<%= config.bin %> <%= command.id %> simple my_scenario --format json',
36
- '<%= config.bin %> <%= command.id %> simple --input \'{"values":[1,2,3]}\'',
37
- '<%= config.bin %> <%= command.id %> simple --input input.json',
38
- '<%= config.bin %> <%= command.id %> simple --input \'{"key":"value"}\' --task-queue my-queue'
39
- ];
40
- static args = {
41
- workflowName: Args.string({
42
- description: 'Name of the workflow to execute',
43
- required: true
44
- }),
45
- scenario: Args.string({
46
- description: 'Scenario name (resolved from the workflow\'s scenarios/ directory)',
47
- required: false
48
- })
49
- };
50
- static flags = {
51
- input: Flags.string({
52
- char: 'i',
53
- description: 'Workflow input as JSON string or file path (overrides scenario)',
54
- required: false
55
- }),
56
- 'task-queue': Flags.string({
57
- char: 'q',
58
- description: 'Task queue name for workflow execution'
59
- }),
60
- format: Flags.string({
61
- char: 'f',
62
- description: 'Output format',
63
- options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
64
- default: OUTPUT_FORMAT.TEXT
65
- })
66
- };
67
- async run() {
68
- const { args, flags } = await this.parse(WorkflowRun);
69
- const input = await resolveInput(args.workflowName, args.scenario, flags.input, 'run');
70
- this.log(`Executing workflow: ${args.workflowName}...`);
71
- const response = await executeWorkflow({
72
- body: {
73
- workflowName: args.workflowName,
74
- input,
75
- taskQueue: flags['task-queue']
76
- },
77
- options: { config: { timeout: 600000 } },
78
- log: msg => this.log(msg)
79
- });
80
- if (!response || !response.data) {
81
- this.error('API returned invalid response', { exit: 1 });
82
- }
83
- const data = response.data;
84
- const output = formatOutput(data, flags.format, formatWorkflowResult);
85
- this.log(`\n${output}`);
86
- if (ERROR_STATUSES.has(data.status)) {
87
- process.exitCode = 1;
88
- }
89
- }
90
- async catch(error) {
91
- return handleApiError(error, (...args) => this.error(...args), {
92
- 404: 'Workflow not found. Check the workflow name.',
93
- 500: 'Workflow execution failed.',
94
- 503: 'Workflow service temporarily unavailable.'
95
- });
96
- }
97
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,110 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
2
- import { describe, it, expect, vi, beforeEach } from 'vitest';
3
- import { HttpError } from '#api/http_client.js';
4
- vi.mock('#api/generated/api.js', () => ({
5
- postWorkflowRun: vi.fn()
6
- }));
7
- vi.mock('#utils/resolve_input.js', () => ({
8
- resolveInput: vi.fn()
9
- }));
10
- vi.mock('#utils/sleep.js', () => ({
11
- sleep: vi.fn().mockResolvedValue(undefined)
12
- }));
13
- describe('workflow run command', () => {
14
- beforeEach(async () => {
15
- vi.clearAllMocks();
16
- const { resolveInput } = await import('#utils/resolve_input.js');
17
- const { sleep } = await import('#utils/sleep.js');
18
- vi.mocked(resolveInput).mockResolvedValue({});
19
- vi.mocked(sleep).mockResolvedValue(undefined);
20
- });
21
- describe('command definition', () => {
22
- it('should export a valid OCLIF command', async () => {
23
- const WorkflowRun = (await import('./run.js')).default;
24
- expect(WorkflowRun).toBeDefined();
25
- expect(WorkflowRun.description).toContain('Execute a workflow');
26
- expect(WorkflowRun.args).toHaveProperty('workflowName');
27
- expect(WorkflowRun.flags).toHaveProperty('input');
28
- expect(WorkflowRun.flags).toHaveProperty('format');
29
- expect(WorkflowRun.flags).toHaveProperty('task-queue');
30
- });
31
- it('should have correct flag configuration', async () => {
32
- const WorkflowRun = (await import('./run.js')).default;
33
- expect(WorkflowRun.flags.format.options).toEqual(['json', 'text']);
34
- expect(WorkflowRun.flags.format.default).toBe('text');
35
- expect(WorkflowRun.flags.input.required).toBe(false);
36
- });
37
- it('should have optional scenario argument', async () => {
38
- const WorkflowRun = (await import('./run.js')).default;
39
- expect(WorkflowRun.args).toHaveProperty('scenario');
40
- expect(WorkflowRun.args.scenario.required).toBe(false);
41
- });
42
- });
43
- describe('run()', () => {
44
- const createCommand = async () => {
45
- const WorkflowRun = (await import('./run.js')).default;
46
- const { postWorkflowRun } = await import('#api/generated/api.js');
47
- const { resolveInput } = await import('#utils/resolve_input.js');
48
- const cmd = new WorkflowRun(['my_workflow'], {});
49
- cmd.log = vi.fn();
50
- cmd.error = vi.fn(() => {
51
- throw new Error('error called');
52
- });
53
- cmd.parse = vi.fn().mockResolvedValue({
54
- args: { workflowName: 'my_workflow', scenario: undefined },
55
- flags: { input: undefined, 'task-queue': undefined, format: 'text' }
56
- });
57
- return { cmd, postWorkflowRun: vi.mocked(postWorkflowRun), resolveInput: vi.mocked(resolveInput) };
58
- };
59
- it('calls postWorkflowRun and logs output on success', async () => {
60
- const { cmd, postWorkflowRun, resolveInput } = await createCommand();
61
- resolveInput.mockResolvedValue({ key: 'value' });
62
- postWorkflowRun.mockResolvedValue({
63
- data: { status: 'completed', result: { output: 'ok' } },
64
- status: 200,
65
- headers: new Headers()
66
- });
67
- await cmd.run();
68
- expect(postWorkflowRun).toHaveBeenCalledTimes(1);
69
- expect(postWorkflowRun).toHaveBeenCalledWith({ workflowName: 'my_workflow', input: { key: 'value' }, taskQueue: undefined }, expect.objectContaining({ config: { timeout: 600000 } }));
70
- expect(cmd.log).toHaveBeenCalledWith('Executing workflow: my_workflow...');
71
- expect(cmd.log).toHaveBeenCalledWith(expect.stringMatching(/\n/));
72
- });
73
- it('retries when response has Retry-After and succeeds on second attempt', async () => {
74
- const { cmd, postWorkflowRun, resolveInput } = await createCommand();
75
- resolveInput.mockResolvedValue({});
76
- const headers = new Headers({ 'Retry-After': '1' });
77
- postWorkflowRun
78
- .mockRejectedValueOnce(new HttpError('Unavailable', { status: 503, headers }))
79
- .mockResolvedValueOnce({
80
- data: { status: 'completed', result: {} },
81
- status: 200,
82
- headers: new Headers()
83
- });
84
- await cmd.run();
85
- expect(postWorkflowRun).toHaveBeenCalledTimes(2);
86
- expect(cmd.log).toHaveBeenCalledWith(expect.stringMatching(/Retry-After.*Retrying in/));
87
- });
88
- it('does not retry when response has no Retry-After and throws', async () => {
89
- const { cmd, postWorkflowRun, resolveInput } = await createCommand();
90
- resolveInput.mockResolvedValue({});
91
- postWorkflowRun.mockRejectedValue(new HttpError('Unavailable', { status: 503, headers: new Headers() }));
92
- await expect(cmd.run()).rejects.toThrow(HttpError);
93
- expect(postWorkflowRun).toHaveBeenCalledTimes(1);
94
- });
95
- it('does not retry on non-503 error and throws', async () => {
96
- const { cmd, postWorkflowRun, resolveInput } = await createCommand();
97
- resolveInput.mockResolvedValue({});
98
- postWorkflowRun.mockRejectedValue(new HttpError('Not found', { status: 404 }));
99
- await expect(cmd.run()).rejects.toThrow(HttpError);
100
- expect(postWorkflowRun).toHaveBeenCalledTimes(1);
101
- });
102
- it('calls error when API returns no data', async () => {
103
- const { cmd, postWorkflowRun, resolveInput } = await createCommand();
104
- resolveInput.mockResolvedValue({});
105
- postWorkflowRun.mockResolvedValue({ data: undefined, status: 200, headers: new Headers() });
106
- await expect(cmd.run()).rejects.toThrow('error called');
107
- expect(cmd.error).toHaveBeenCalledWith('API returned invalid response', { exit: 1 });
108
- });
109
- });
110
- });
@@ -1,14 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class WorkflowRunsList extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- workflowName: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
7
- };
8
- static flags: {
9
- limit: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
10
- format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
11
- };
12
- run(): Promise<void>;
13
- catch(error: Error): Promise<void>;
14
- }
@@ -1,104 +0,0 @@
1
- import { Args, Command, Flags } from '@oclif/core';
2
- import Table from 'cli-table3';
3
- import { fetchWorkflowRuns } from '#services/workflow_runs.js';
4
- import { formatDate, formatDurationFromTimestamps } from '#utils/date_formatter.js';
5
- import { handleApiError } from '#utils/error_handler.js';
6
- const OUTPUT_FORMAT = {
7
- TABLE: 'table',
8
- JSON: 'json',
9
- TEXT: 'text'
10
- };
11
- function createRunsTable(runs) {
12
- const table = new Table({
13
- head: ['Workflow ID', 'Type', 'Status', 'Started', 'Duration'],
14
- colWidths: [null, 20, 12, 22, 10],
15
- wordWrap: true,
16
- style: {
17
- head: ['cyan']
18
- }
19
- });
20
- runs.forEach(run => {
21
- table.push([
22
- run.workflowId || '-',
23
- run.workflowType || '-',
24
- run.status || '-',
25
- formatDate(run.startedAt),
26
- formatDurationFromTimestamps(run.startedAt || '', run.completedAt)
27
- ]);
28
- });
29
- return table.toString();
30
- }
31
- function formatRunsAsText(runs) {
32
- if (runs.length === 0) {
33
- return 'No workflow runs found.';
34
- }
35
- return runs.map(run => {
36
- const duration = formatDurationFromTimestamps(run.startedAt || '', run.completedAt);
37
- return `${run.workflowId} (${run.workflowType}) - ${run.status} [${duration}]`;
38
- }).join('\n');
39
- }
40
- function formatRunsAsJson(runs) {
41
- return JSON.stringify(runs, null, 2);
42
- }
43
- function formatRuns(runs, format) {
44
- if (format === OUTPUT_FORMAT.JSON) {
45
- return formatRunsAsJson(runs);
46
- }
47
- if (format === OUTPUT_FORMAT.TABLE) {
48
- return createRunsTable(runs);
49
- }
50
- return formatRunsAsText(runs);
51
- }
52
- export default class WorkflowRunsList extends Command {
53
- static description = 'List workflow runs with optional filtering by workflow type';
54
- static examples = [
55
- '<%= config.bin %> <%= command.id %>',
56
- '<%= config.bin %> <%= command.id %> simple',
57
- '<%= config.bin %> <%= command.id %> simple --limit 10',
58
- '<%= config.bin %> <%= command.id %> --format json',
59
- '<%= config.bin %> <%= command.id %> --format table'
60
- ];
61
- static args = {
62
- workflowName: Args.string({
63
- description: 'Filter by workflow type/name',
64
- required: false
65
- })
66
- };
67
- static flags = {
68
- limit: Flags.integer({
69
- char: 'l',
70
- description: 'Maximum number of runs to return',
71
- default: 100
72
- }),
73
- format: Flags.string({
74
- char: 'f',
75
- description: 'Output format',
76
- options: [OUTPUT_FORMAT.TABLE, OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
77
- default: OUTPUT_FORMAT.TABLE
78
- })
79
- };
80
- async run() {
81
- const { args, flags } = await this.parse(WorkflowRunsList);
82
- const { runs, count } = await fetchWorkflowRuns({
83
- workflowType: args.workflowName,
84
- limit: flags.limit
85
- });
86
- if (runs.length === 0) {
87
- const filterMsg = args.workflowName ? ` for workflow type "${args.workflowName}"` : '';
88
- this.log(`No workflow runs found${filterMsg}.`);
89
- return;
90
- }
91
- const output = formatRuns(runs, flags.format);
92
- this.log(output);
93
- if (flags.format !== OUTPUT_FORMAT.JSON) {
94
- const filterMsg = args.workflowName ? ` of type "${args.workflowName}"` : '';
95
- this.log(`\nFound ${count} run(s)${filterMsg}`);
96
- }
97
- }
98
- async catch(error) {
99
- return handleApiError(error, (...args) => this.error(...args), {
100
- 400: 'Invalid parameters provided.',
101
- 503: 'Workflow service temporarily unavailable.'
102
- });
103
- }
104
- }
@@ -1,15 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class WorkflowStart extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
- scenario: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
- };
9
- static flags: {
10
- input: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
- 'task-queue': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
- };
13
- run(): Promise<void>;
14
- catch(error: Error): Promise<void>;
15
- }
@@ -1,62 +0,0 @@
1
- import { Args, Command, Flags } from '@oclif/core';
2
- import { postWorkflowStart } from '#api/generated/api.js';
3
- import { handleApiError } from '#utils/error_handler.js';
4
- import { resolveInput } from '#utils/resolve_input.js';
5
- export default class WorkflowStart extends Command {
6
- static description = 'Start a workflow asynchronously without waiting for completion';
7
- static examples = [
8
- '<%= config.bin %> <%= command.id %> simple basic_input',
9
- '<%= config.bin %> <%= command.id %> simple --input \'{"values":[1,2,3]}\'',
10
- '<%= config.bin %> <%= command.id %> simple --input input.json',
11
- '<%= config.bin %> <%= command.id %> simple --input \'{"key":"value"}\' --task-queue my-queue'
12
- ];
13
- static args = {
14
- workflowName: Args.string({
15
- description: 'Name of the workflow to start',
16
- required: true
17
- }),
18
- scenario: Args.string({
19
- description: 'Scenario name (resolved from the workflow\'s scenarios/ directory)',
20
- required: false
21
- })
22
- };
23
- static flags = {
24
- input: Flags.string({
25
- char: 'i',
26
- description: 'Workflow input as JSON string or file path (overrides scenario)',
27
- required: false
28
- }),
29
- 'task-queue': Flags.string({
30
- char: 'q',
31
- description: 'Task queue name for workflow execution'
32
- })
33
- };
34
- async run() {
35
- const { args, flags } = await this.parse(WorkflowStart);
36
- const input = await resolveInput(args.workflowName, args.scenario, flags.input, 'start');
37
- this.log(`Starting workflow: ${args.workflowName}...`);
38
- const response = await postWorkflowStart({
39
- workflowName: args.workflowName,
40
- input,
41
- taskQueue: flags['task-queue']
42
- });
43
- if (!response || !response.data) {
44
- this.error('API returned invalid response', { exit: 1 });
45
- }
46
- const result = response.data;
47
- const output = [
48
- 'Workflow started successfully',
49
- '',
50
- `Workflow ID: ${result.workflowId || 'unknown'}`,
51
- '',
52
- `Use "workflow status ${result.workflowId || '<workflow-id>'}" to check the workflow status`,
53
- `Use "workflow result ${result.workflowId || '<workflow-id>'}" to get the workflow result when complete`
54
- ].join('\n');
55
- this.log(`\n${output}`);
56
- }
57
- async catch(error) {
58
- return handleApiError(error, (...args) => this.error(...args), {
59
- 404: 'Workflow not found. Check the workflow name.'
60
- });
61
- }
62
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,28 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('../../api/generated/api.js', () => ({
3
- postWorkflowStart: vi.fn()
4
- }));
5
- describe('workflow start command', () => {
6
- beforeEach(() => {
7
- vi.clearAllMocks();
8
- });
9
- describe('command definition', () => {
10
- it('should export a valid OCLIF command', async () => {
11
- const WorkflowStart = (await import('./start.js')).default;
12
- expect(WorkflowStart).toBeDefined();
13
- expect(WorkflowStart.description).toContain('Start a workflow');
14
- expect(WorkflowStart.args).toHaveProperty('workflowName');
15
- expect(WorkflowStart.flags).toHaveProperty('input');
16
- expect(WorkflowStart.flags).toHaveProperty('task-queue');
17
- });
18
- it('should have correct flag configuration', async () => {
19
- const WorkflowStart = (await import('./start.js')).default;
20
- expect(WorkflowStart.flags.input.required).toBe(false);
21
- });
22
- it('should have optional scenario argument', async () => {
23
- const WorkflowStart = (await import('./start.js')).default;
24
- expect(WorkflowStart.args).toHaveProperty('scenario');
25
- expect(WorkflowStart.args.scenario.required).toBe(false);
26
- });
27
- });
28
- });
@@ -1,13 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class WorkflowStatus extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- workflowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
- };
8
- static flags: {
9
- format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
10
- };
11
- run(): Promise<void>;
12
- catch(error: Error): Promise<void>;
13
- }
@@ -1,57 +0,0 @@
1
- import { Args, Command, Flags } from '@oclif/core';
2
- import { getWorkflowIdStatus } from '#api/generated/api.js';
3
- import { OUTPUT_FORMAT } from '#utils/constants.js';
4
- import { formatOutput } from '#utils/output_formatter.js';
5
- import { handleApiError } from '#utils/error_handler.js';
6
- export default class WorkflowStatus extends Command {
7
- static description = 'Get workflow execution status';
8
- static examples = [
9
- '<%= config.bin %> <%= command.id %> wf-12345',
10
- '<%= config.bin %> <%= command.id %> wf-12345 --format json'
11
- ];
12
- static args = {
13
- workflowId: Args.string({
14
- description: 'The workflow ID to check status for',
15
- required: true
16
- })
17
- };
18
- static flags = {
19
- format: Flags.string({
20
- char: 'f',
21
- description: 'Output format',
22
- options: [OUTPUT_FORMAT.JSON, OUTPUT_FORMAT.TEXT],
23
- default: OUTPUT_FORMAT.TEXT
24
- })
25
- };
26
- async run() {
27
- const { args, flags } = await this.parse(WorkflowStatus);
28
- this.log(`Fetching status for workflow: ${args.workflowId}...`);
29
- const response = await getWorkflowIdStatus(args.workflowId);
30
- if (!response || !response.data) {
31
- this.error('API returned invalid response', { exit: 1 });
32
- }
33
- const data = response.data;
34
- const output = formatOutput(data, flags.format, (result) => {
35
- const lines = [
36
- `Workflow ID: ${result.workflowId || 'unknown'}`,
37
- `Status: ${result.status || 'unknown'}`,
38
- ''
39
- ];
40
- if (result.startedAt) {
41
- const startDate = new Date(result.startedAt);
42
- lines.push(`Started At: ${startDate.toISOString()}`);
43
- }
44
- if (result.completedAt) {
45
- const completedDate = new Date(result.completedAt);
46
- lines.push(`Completed At: ${completedDate.toISOString()}`);
47
- }
48
- return lines.join('\n');
49
- });
50
- this.log(`\n${output}`);
51
- }
52
- async catch(error) {
53
- return handleApiError(error, (...args) => this.error(...args), {
54
- 404: 'Workflow not found. Check the workflow ID.'
55
- });
56
- }
57
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,33 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('../../api/generated/api.js', () => ({
3
- getWorkflowIdStatus: vi.fn(),
4
- GetWorkflowIdStatus200Status: {
5
- canceled: 'canceled',
6
- completed: 'completed',
7
- continued_as_new: 'continued_as_new',
8
- failed: 'failed',
9
- running: 'running',
10
- terminated: 'terminated',
11
- timed_out: 'timed_out',
12
- unspecified: 'unspecified'
13
- }
14
- }));
15
- describe('workflow status command', () => {
16
- beforeEach(() => {
17
- vi.clearAllMocks();
18
- });
19
- describe('command definition', () => {
20
- it('should export a valid OCLIF command', async () => {
21
- const WorkflowStatus = (await import('./status.js')).default;
22
- expect(WorkflowStatus).toBeDefined();
23
- expect(WorkflowStatus.description).toContain('Get workflow execution status');
24
- expect(WorkflowStatus.args).toHaveProperty('workflowId');
25
- expect(WorkflowStatus.flags).toHaveProperty('format');
26
- });
27
- it('should have correct flag configuration', async () => {
28
- const WorkflowStatus = (await import('./status.js')).default;
29
- expect(WorkflowStatus.flags.format.options).toEqual(['json', 'text']);
30
- expect(WorkflowStatus.flags.format.default).toBe('text');
31
- });
32
- });
33
- });
@@ -1,10 +0,0 @@
1
- import { Command } from '@oclif/core';
2
- export default class WorkflowStop extends Command {
3
- static description: string;
4
- static examples: string[];
5
- static args: {
6
- workflowId: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
7
- };
8
- run(): Promise<void>;
9
- catch(error: Error): Promise<void>;
10
- }
@@ -1,31 +0,0 @@
1
- import { Args, Command } from '@oclif/core';
2
- import { patchWorkflowIdStop } from '#api/generated/api.js';
3
- import { handleApiError } from '#utils/error_handler.js';
4
- export default class WorkflowStop extends Command {
5
- static description = 'Stop a workflow execution';
6
- static examples = [
7
- '<%= config.bin %> <%= command.id %> wf-12345'
8
- ];
9
- static args = {
10
- workflowId: Args.string({
11
- description: 'The workflow ID to stop',
12
- required: true
13
- })
14
- };
15
- async run() {
16
- const { args } = await this.parse(WorkflowStop);
17
- this.log(`Stopping workflow: ${args.workflowId}...`);
18
- await patchWorkflowIdStop(args.workflowId);
19
- const output = [
20
- 'Workflow stopped successfully',
21
- '',
22
- `Workflow ID: ${args.workflowId}`
23
- ].join('\n');
24
- this.log(`\n${output}`);
25
- }
26
- async catch(error) {
27
- return handleApiError(error, (...args) => this.error(...args), {
28
- 404: 'Workflow not found. Check the workflow ID.'
29
- });
30
- }
31
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- vi.mock('../../api/generated/api.js', () => ({
3
- patchWorkflowIdStop: vi.fn()
4
- }));
5
- describe('workflow stop command', () => {
6
- beforeEach(() => {
7
- vi.clearAllMocks();
8
- });
9
- describe('command definition', () => {
10
- it('should export a valid OCLIF command', async () => {
11
- const WorkflowStop = (await import('./stop.js')).default;
12
- expect(WorkflowStop).toBeDefined();
13
- expect(WorkflowStop.description).toContain('Stop a workflow execution');
14
- expect(WorkflowStop.args).toHaveProperty('workflowId');
15
- });
16
- });
17
- });