@outputai/cli 0.1.3 → 0.1.4-dev.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.
Files changed (278) hide show
  1. package/dist/api/generated/api.d.ts +820 -0
  2. package/dist/api/generated/api.js +226 -0
  3. package/dist/api/http_client.d.ts +27 -0
  4. package/dist/api/http_client.js +71 -0
  5. package/dist/api/orval_post_process.d.ts +11 -0
  6. package/dist/api/orval_post_process.js +46 -0
  7. package/dist/api/parser.d.ts +17 -0
  8. package/dist/api/parser.js +68 -0
  9. package/dist/assets/config/costs.yml +309 -0
  10. package/dist/assets/docker/docker-compose-dev.yml +146 -0
  11. package/dist/commands/credentials/edit.d.ts +10 -0
  12. package/dist/commands/credentials/edit.js +67 -0
  13. package/dist/commands/credentials/edit.spec.d.ts +1 -0
  14. package/dist/commands/credentials/edit.spec.js +73 -0
  15. package/dist/commands/credentials/get.d.ts +13 -0
  16. package/dist/commands/credentials/get.js +46 -0
  17. package/dist/commands/credentials/get.spec.d.ts +1 -0
  18. package/dist/commands/credentials/get.spec.js +74 -0
  19. package/dist/commands/credentials/init.d.ts +11 -0
  20. package/dist/commands/credentials/init.js +45 -0
  21. package/dist/commands/credentials/init.spec.d.ts +1 -0
  22. package/dist/commands/credentials/init.spec.js +68 -0
  23. package/dist/commands/credentials/show.d.ts +10 -0
  24. package/dist/commands/credentials/show.js +33 -0
  25. package/dist/commands/credentials/show.spec.d.ts +1 -0
  26. package/dist/commands/credentials/show.spec.js +57 -0
  27. package/dist/commands/dev/eject.d.ts +11 -0
  28. package/dist/commands/dev/eject.js +58 -0
  29. package/dist/commands/dev/eject.spec.d.ts +1 -0
  30. package/dist/commands/dev/eject.spec.js +109 -0
  31. package/dist/commands/dev/index.d.ts +14 -0
  32. package/dist/commands/dev/index.js +173 -0
  33. package/dist/commands/dev/index.spec.d.ts +1 -0
  34. package/dist/commands/dev/index.spec.js +239 -0
  35. package/dist/commands/init.d.ts +12 -0
  36. package/dist/commands/init.js +37 -0
  37. package/dist/commands/init.spec.d.ts +1 -0
  38. package/dist/commands/init.spec.js +100 -0
  39. package/dist/commands/update.d.ts +14 -0
  40. package/dist/commands/update.js +120 -0
  41. package/dist/commands/update.spec.d.ts +1 -0
  42. package/dist/commands/update.spec.js +178 -0
  43. package/dist/commands/workflow/cost.d.ts +16 -0
  44. package/dist/commands/workflow/cost.js +71 -0
  45. package/dist/commands/workflow/cost.spec.d.ts +1 -0
  46. package/dist/commands/workflow/cost.spec.js +47 -0
  47. package/dist/commands/workflow/dataset/generate.d.ts +22 -0
  48. package/dist/commands/workflow/dataset/generate.js +143 -0
  49. package/dist/commands/workflow/dataset/list.d.ts +12 -0
  50. package/dist/commands/workflow/dataset/list.js +87 -0
  51. package/dist/commands/workflow/debug.d.ts +16 -0
  52. package/dist/commands/workflow/debug.js +60 -0
  53. package/dist/commands/workflow/debug.spec.d.ts +1 -0
  54. package/dist/commands/workflow/debug.spec.js +34 -0
  55. package/dist/commands/workflow/generate.d.ts +17 -0
  56. package/dist/commands/workflow/generate.js +85 -0
  57. package/dist/commands/workflow/generate.spec.d.ts +1 -0
  58. package/dist/commands/workflow/generate.spec.js +115 -0
  59. package/dist/commands/workflow/list.d.ts +22 -0
  60. package/dist/commands/workflow/list.js +152 -0
  61. package/dist/commands/workflow/list.spec.d.ts +1 -0
  62. package/dist/commands/workflow/list.spec.js +99 -0
  63. package/dist/commands/workflow/plan.d.ts +12 -0
  64. package/dist/commands/workflow/plan.js +66 -0
  65. package/dist/commands/workflow/plan.spec.d.ts +1 -0
  66. package/dist/commands/workflow/plan.spec.js +341 -0
  67. package/dist/commands/workflow/reset.d.ts +14 -0
  68. package/dist/commands/workflow/reset.js +51 -0
  69. package/dist/commands/workflow/result.d.ts +13 -0
  70. package/dist/commands/workflow/result.js +46 -0
  71. package/dist/commands/workflow/result.spec.d.ts +1 -0
  72. package/dist/commands/workflow/result.spec.js +23 -0
  73. package/dist/commands/workflow/run.d.ts +16 -0
  74. package/dist/commands/workflow/run.js +97 -0
  75. package/dist/commands/workflow/run.spec.d.ts +1 -0
  76. package/dist/commands/workflow/run.spec.js +110 -0
  77. package/dist/commands/workflow/runs/list.d.ts +14 -0
  78. package/dist/commands/workflow/runs/list.js +104 -0
  79. package/dist/commands/workflow/start.d.ts +15 -0
  80. package/dist/commands/workflow/start.js +62 -0
  81. package/dist/commands/workflow/start.spec.d.ts +1 -0
  82. package/dist/commands/workflow/start.spec.js +28 -0
  83. package/dist/commands/workflow/status.d.ts +13 -0
  84. package/dist/commands/workflow/status.js +57 -0
  85. package/dist/commands/workflow/status.spec.d.ts +1 -0
  86. package/dist/commands/workflow/status.spec.js +33 -0
  87. package/dist/commands/workflow/stop.d.ts +10 -0
  88. package/dist/commands/workflow/stop.js +31 -0
  89. package/dist/commands/workflow/stop.spec.d.ts +1 -0
  90. package/dist/commands/workflow/stop.spec.js +17 -0
  91. package/dist/commands/workflow/terminate.d.ts +13 -0
  92. package/dist/commands/workflow/terminate.js +39 -0
  93. package/dist/commands/workflow/test_eval.d.ts +20 -0
  94. package/dist/commands/workflow/test_eval.js +151 -0
  95. package/dist/config.d.ts +47 -0
  96. package/dist/config.js +47 -0
  97. package/dist/generated/framework_version.json +3 -0
  98. package/dist/hooks/init.d.ts +3 -0
  99. package/dist/hooks/init.js +30 -0
  100. package/dist/hooks/init.spec.d.ts +1 -0
  101. package/dist/hooks/init.spec.js +54 -0
  102. package/dist/index.d.ts +1 -0
  103. package/dist/index.js +1 -0
  104. package/dist/index.spec.d.ts +1 -0
  105. package/dist/index.spec.js +6 -0
  106. package/dist/services/claude_client.d.ts +30 -0
  107. package/dist/services/claude_client.integration.test.d.ts +1 -0
  108. package/dist/services/claude_client.integration.test.js +43 -0
  109. package/dist/services/claude_client.js +215 -0
  110. package/dist/services/claude_client.spec.d.ts +1 -0
  111. package/dist/services/claude_client.spec.js +145 -0
  112. package/dist/services/coding_agents.d.ts +36 -0
  113. package/dist/services/coding_agents.js +236 -0
  114. package/dist/services/coding_agents.spec.d.ts +1 -0
  115. package/dist/services/coding_agents.spec.js +256 -0
  116. package/dist/services/copy_assets.spec.d.ts +1 -0
  117. package/dist/services/copy_assets.spec.js +22 -0
  118. package/dist/services/cost_calculator.d.ts +18 -0
  119. package/dist/services/cost_calculator.js +359 -0
  120. package/dist/services/cost_calculator.spec.d.ts +1 -0
  121. package/dist/services/cost_calculator.spec.js +540 -0
  122. package/dist/services/credentials_service.d.ts +12 -0
  123. package/dist/services/credentials_service.integration.test.d.ts +1 -0
  124. package/dist/services/credentials_service.integration.test.js +66 -0
  125. package/dist/services/credentials_service.js +64 -0
  126. package/dist/services/credentials_service.spec.d.ts +1 -0
  127. package/dist/services/credentials_service.spec.js +106 -0
  128. package/dist/services/datasets.d.ts +20 -0
  129. package/dist/services/datasets.js +132 -0
  130. package/dist/services/docker.d.ts +39 -0
  131. package/dist/services/docker.js +160 -0
  132. package/dist/services/docker.spec.d.ts +1 -0
  133. package/dist/services/docker.spec.js +124 -0
  134. package/dist/services/env_configurator.d.ts +15 -0
  135. package/dist/services/env_configurator.js +163 -0
  136. package/dist/services/env_configurator.spec.d.ts +1 -0
  137. package/dist/services/env_configurator.spec.js +192 -0
  138. package/dist/services/generate_plan_name@v1.prompt +24 -0
  139. package/dist/services/messages.d.ts +9 -0
  140. package/dist/services/messages.js +338 -0
  141. package/dist/services/messages.spec.d.ts +1 -0
  142. package/dist/services/messages.spec.js +55 -0
  143. package/dist/services/npm_update_service.d.ts +6 -0
  144. package/dist/services/npm_update_service.js +87 -0
  145. package/dist/services/npm_update_service.spec.d.ts +1 -0
  146. package/dist/services/npm_update_service.spec.js +104 -0
  147. package/dist/services/project_scaffold.d.ts +31 -0
  148. package/dist/services/project_scaffold.js +212 -0
  149. package/dist/services/project_scaffold.spec.d.ts +1 -0
  150. package/dist/services/project_scaffold.spec.js +122 -0
  151. package/dist/services/s3_trace_downloader.d.ts +12 -0
  152. package/dist/services/s3_trace_downloader.js +57 -0
  153. package/dist/services/template_processor.d.ts +14 -0
  154. package/dist/services/template_processor.js +57 -0
  155. package/dist/services/trace_reader.d.ts +16 -0
  156. package/dist/services/trace_reader.js +57 -0
  157. package/dist/services/trace_reader.spec.d.ts +1 -0
  158. package/dist/services/trace_reader.spec.js +78 -0
  159. package/dist/services/version_check.d.ts +6 -0
  160. package/dist/services/version_check.js +52 -0
  161. package/dist/services/version_check.spec.d.ts +1 -0
  162. package/dist/services/version_check.spec.js +106 -0
  163. package/dist/services/workflow_builder.d.ts +16 -0
  164. package/dist/services/workflow_builder.js +86 -0
  165. package/dist/services/workflow_builder.spec.d.ts +1 -0
  166. package/dist/services/workflow_builder.spec.js +165 -0
  167. package/dist/services/workflow_generator.d.ts +5 -0
  168. package/dist/services/workflow_generator.js +40 -0
  169. package/dist/services/workflow_generator.spec.d.ts +1 -0
  170. package/dist/services/workflow_generator.spec.js +77 -0
  171. package/dist/services/workflow_planner.d.ts +15 -0
  172. package/dist/services/workflow_planner.js +48 -0
  173. package/dist/services/workflow_planner.spec.d.ts +1 -0
  174. package/dist/services/workflow_planner.spec.js +122 -0
  175. package/dist/services/workflow_runs.d.ts +14 -0
  176. package/dist/services/workflow_runs.js +25 -0
  177. package/dist/templates/agent_instructions/CLAUDE.md.template +19 -0
  178. package/dist/templates/agent_instructions/dotclaude/settings.json.template +29 -0
  179. package/dist/templates/project/.env.example.template +9 -0
  180. package/dist/templates/project/.gitignore.template +35 -0
  181. package/dist/templates/project/README.md.template +100 -0
  182. package/dist/templates/project/config/costs.yml.template +29 -0
  183. package/dist/templates/project/package.json.template +25 -0
  184. package/dist/templates/project/src/clients/jina.ts.template +30 -0
  185. package/dist/templates/project/src/shared/utils/string.ts.template +3 -0
  186. package/dist/templates/project/src/shared/utils/url.ts.template +15 -0
  187. package/dist/templates/project/src/workflows/blog_evaluator/evaluators.ts.template +23 -0
  188. package/dist/templates/project/src/workflows/blog_evaluator/prompts/signal_noise@v1.prompt.template +26 -0
  189. package/dist/templates/project/src/workflows/blog_evaluator/scenarios/paulgraham_hwh.json.template +3 -0
  190. package/dist/templates/project/src/workflows/blog_evaluator/steps.ts.template +27 -0
  191. package/dist/templates/project/src/workflows/blog_evaluator/types.ts.template +30 -0
  192. package/dist/templates/project/src/workflows/blog_evaluator/utils.ts.template +15 -0
  193. package/dist/templates/project/src/workflows/blog_evaluator/workflow.ts.template +27 -0
  194. package/dist/templates/project/tsconfig.json.template +20 -0
  195. package/dist/templates/workflow/README.md.template +216 -0
  196. package/dist/templates/workflow/evaluators.ts.template +21 -0
  197. package/dist/templates/workflow/prompts/example@v1.prompt.template +15 -0
  198. package/dist/templates/workflow/scenarios/test_input.json.template +3 -0
  199. package/dist/templates/workflow/steps.ts.template +20 -0
  200. package/dist/templates/workflow/types.ts.template +13 -0
  201. package/dist/templates/workflow/workflow.ts.template +23 -0
  202. package/dist/test_helpers/mocks.d.ts +38 -0
  203. package/dist/test_helpers/mocks.js +77 -0
  204. package/dist/types/cost.d.ts +149 -0
  205. package/dist/types/cost.js +6 -0
  206. package/dist/types/domain.d.ts +20 -0
  207. package/dist/types/domain.js +4 -0
  208. package/dist/types/errors.d.ts +68 -0
  209. package/dist/types/errors.js +100 -0
  210. package/dist/types/errors.spec.d.ts +1 -0
  211. package/dist/types/errors.spec.js +18 -0
  212. package/dist/types/generator.d.ts +26 -0
  213. package/dist/types/generator.js +1 -0
  214. package/dist/types/trace.d.ts +161 -0
  215. package/dist/types/trace.js +18 -0
  216. package/dist/utils/claude.d.ts +5 -0
  217. package/dist/utils/claude.js +19 -0
  218. package/dist/utils/claude.spec.d.ts +1 -0
  219. package/dist/utils/claude.spec.js +119 -0
  220. package/dist/utils/constants.d.ts +5 -0
  221. package/dist/utils/constants.js +4 -0
  222. package/dist/utils/cost_formatter.d.ts +5 -0
  223. package/dist/utils/cost_formatter.js +218 -0
  224. package/dist/utils/date_formatter.d.ts +23 -0
  225. package/dist/utils/date_formatter.js +49 -0
  226. package/dist/utils/env_loader.d.ts +1 -0
  227. package/dist/utils/env_loader.js +22 -0
  228. package/dist/utils/env_loader.spec.d.ts +1 -0
  229. package/dist/utils/env_loader.spec.js +43 -0
  230. package/dist/utils/error_handler.d.ts +8 -0
  231. package/dist/utils/error_handler.js +71 -0
  232. package/dist/utils/error_utils.d.ts +24 -0
  233. package/dist/utils/error_utils.js +87 -0
  234. package/dist/utils/file_system.d.ts +3 -0
  235. package/dist/utils/file_system.js +33 -0
  236. package/dist/utils/format_workflow_result.d.ts +5 -0
  237. package/dist/utils/format_workflow_result.js +18 -0
  238. package/dist/utils/format_workflow_result.spec.d.ts +1 -0
  239. package/dist/utils/format_workflow_result.spec.js +81 -0
  240. package/dist/utils/framework_version.d.ts +4 -0
  241. package/dist/utils/framework_version.js +4 -0
  242. package/dist/utils/framework_version.spec.d.ts +1 -0
  243. package/dist/utils/framework_version.spec.js +13 -0
  244. package/dist/utils/header_utils.d.ts +12 -0
  245. package/dist/utils/header_utils.js +29 -0
  246. package/dist/utils/header_utils.spec.d.ts +1 -0
  247. package/dist/utils/header_utils.spec.js +52 -0
  248. package/dist/utils/input_parser.d.ts +1 -0
  249. package/dist/utils/input_parser.js +19 -0
  250. package/dist/utils/output_formatter.d.ts +2 -0
  251. package/dist/utils/output_formatter.js +11 -0
  252. package/dist/utils/paths.d.ts +25 -0
  253. package/dist/utils/paths.js +36 -0
  254. package/dist/utils/process.d.ts +4 -0
  255. package/dist/utils/process.js +50 -0
  256. package/dist/utils/resolve_input.d.ts +1 -0
  257. package/dist/utils/resolve_input.js +22 -0
  258. package/dist/utils/scenario_resolver.d.ts +9 -0
  259. package/dist/utils/scenario_resolver.js +93 -0
  260. package/dist/utils/scenario_resolver.spec.d.ts +1 -0
  261. package/dist/utils/scenario_resolver.spec.js +214 -0
  262. package/dist/utils/secret_sanitizer.d.ts +1 -0
  263. package/dist/utils/secret_sanitizer.js +29 -0
  264. package/dist/utils/sleep.d.ts +5 -0
  265. package/dist/utils/sleep.js +5 -0
  266. package/dist/utils/template.d.ts +9 -0
  267. package/dist/utils/template.js +30 -0
  268. package/dist/utils/template.spec.d.ts +1 -0
  269. package/dist/utils/template.spec.js +77 -0
  270. package/dist/utils/trace_extractor.d.ts +27 -0
  271. package/dist/utils/trace_extractor.js +53 -0
  272. package/dist/utils/trace_formatter.d.ts +11 -0
  273. package/dist/utils/trace_formatter.js +402 -0
  274. package/dist/utils/validation.d.ts +13 -0
  275. package/dist/utils/validation.js +25 -0
  276. package/dist/utils/validation.spec.d.ts +1 -0
  277. package/dist/utils/validation.spec.js +140 -0
  278. package/package.json +4 -4
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WorkflowTerminate 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
+ reason: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ };
11
+ run(): Promise<void>;
12
+ catch(error: Error): Promise<void>;
13
+ }
@@ -0,0 +1,39 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { postWorkflowIdTerminate } from '#api/generated/api.js';
3
+ import { handleApiError } from '#utils/error_handler.js';
4
+ export default class WorkflowTerminate extends Command {
5
+ static description = 'Terminate a workflow execution (force stop)';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %> wf-12345',
8
+ '<%= config.bin %> <%= command.id %> wf-12345 --reason "Cleaning up old workflows"'
9
+ ];
10
+ static args = {
11
+ workflowId: Args.string({
12
+ description: 'The workflow ID to terminate',
13
+ required: true
14
+ })
15
+ };
16
+ static flags = {
17
+ reason: Flags.string({
18
+ char: 'r',
19
+ description: 'Reason for termination'
20
+ })
21
+ };
22
+ async run() {
23
+ const { args, flags } = await this.parse(WorkflowTerminate);
24
+ this.log(`Terminating workflow: ${args.workflowId}...`);
25
+ await postWorkflowIdTerminate(args.workflowId, { reason: flags.reason });
26
+ const output = [
27
+ 'Workflow terminated successfully',
28
+ '',
29
+ `Workflow ID: ${args.workflowId}`,
30
+ flags.reason ? `Reason: ${flags.reason}` : ''
31
+ ].filter(Boolean).join('\n');
32
+ this.log(`\n${output}`);
33
+ }
34
+ async catch(error) {
35
+ return handleApiError(error, (...args) => this.error(...args), {
36
+ 404: 'Workflow not found. Check the workflow ID.'
37
+ });
38
+ }
39
+ }
@@ -0,0 +1,20 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class WorkflowTest extends Command {
3
+ static aliases: string[];
4
+ static description: string;
5
+ static examples: string[];
6
+ static args: {
7
+ workflowName: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
8
+ };
9
+ static flags: {
10
+ cached: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ save: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ dataset: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
13
+ format: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ private validateDatasets;
17
+ private runWorkflowForDatasets;
18
+ private saveEvalResults;
19
+ catch(error: Error): Promise<void>;
20
+ }
@@ -0,0 +1,151 @@
1
+ import { join } from 'node:path';
2
+ import { Args, Command, Flags } from '@oclif/core';
3
+ import { postWorkflowRun } from '#api/generated/api.js';
4
+ import { readAllDatasets, writeDataset } from '#services/datasets.js';
5
+ import { handleApiError } from '#utils/error_handler.js';
6
+ import { getEvalWorkflowName, renderEvalOutput, computeExitCode, EvalOutputSchema } from '@outputai/evals';
7
+ export default class WorkflowTest extends Command {
8
+ static aliases = ['workflow:test'];
9
+ static description = 'Run evaluations against a workflow using its datasets';
10
+ static examples = [
11
+ '<%= config.bin %> <%= command.id %> simple',
12
+ '<%= config.bin %> <%= command.id %> simple --cached',
13
+ '<%= config.bin %> <%= command.id %> simple --save',
14
+ '<%= config.bin %> <%= command.id %> simple --dataset basic_input,edge_case',
15
+ '<%= config.bin %> <%= command.id %> simple --format json'
16
+ ];
17
+ static args = {
18
+ workflowName: Args.string({
19
+ description: 'Name of the workflow to test',
20
+ required: true
21
+ })
22
+ };
23
+ static flags = {
24
+ cached: Flags.boolean({
25
+ description: 'Use cached output from dataset files (skip workflow execution)',
26
+ default: false,
27
+ exclusive: ['save']
28
+ }),
29
+ save: Flags.boolean({
30
+ description: 'Run workflow and save output back to dataset files',
31
+ default: false,
32
+ exclusive: ['cached']
33
+ }),
34
+ dataset: Flags.string({
35
+ description: 'Comma-separated list of dataset names to run',
36
+ char: 'd'
37
+ }),
38
+ format: Flags.string({
39
+ char: 'f',
40
+ description: 'Output format',
41
+ options: ['json', 'text'],
42
+ default: 'text'
43
+ })
44
+ };
45
+ async run() {
46
+ const { args, flags } = await this.parse(WorkflowTest);
47
+ const filterNames = flags.dataset?.split(',').map(s => s.trim());
48
+ const { datasets, dir } = await readAllDatasets(args.workflowName, filterNames);
49
+ if (datasets.length === 0) {
50
+ this.error(`No datasets found for workflow "${args.workflowName}".\n` +
51
+ 'Generate datasets first: output workflow dataset generate', { exit: 1 });
52
+ }
53
+ const preparedDatasets = flags.cached ?
54
+ this.validateDatasets(datasets) :
55
+ await this.runWorkflowForDatasets(args.workflowName, datasets, flags.save, dir);
56
+ const evalName = getEvalWorkflowName(args.workflowName);
57
+ this.log(`Running eval workflow "${evalName}"...\n`);
58
+ const response = await postWorkflowRun({
59
+ workflowName: evalName,
60
+ input: { datasets: preparedDatasets }
61
+ }, {
62
+ config: { timeout: 600000 }
63
+ });
64
+ const evalData = response?.data;
65
+ if (!evalData?.output) {
66
+ this.error('Eval workflow returned no output', { exit: 1 });
67
+ }
68
+ const evalOutput = EvalOutputSchema.parse(evalData.output);
69
+ if (flags.save) {
70
+ await this.saveEvalResults(evalOutput, preparedDatasets, dir);
71
+ }
72
+ if (flags.format === 'json') {
73
+ this.log(JSON.stringify(evalOutput, null, 2));
74
+ }
75
+ else {
76
+ this.log(renderEvalOutput(evalOutput, evalName));
77
+ }
78
+ const exitCode = computeExitCode(evalOutput);
79
+ if (exitCode !== 0) {
80
+ this.exit(exitCode);
81
+ }
82
+ }
83
+ validateDatasets(datasets) {
84
+ const missing = datasets.filter(d => d.last_output?.output === undefined);
85
+ if (missing.length > 0) {
86
+ const names = missing.map(d => d.name).join(', ');
87
+ this.error(`Datasets missing cached output: ${names}\n` +
88
+ 'Run without --cached to execute the workflow, or use --save to cache output.', { exit: 1 });
89
+ }
90
+ return datasets;
91
+ }
92
+ async runWorkflowForDatasets(workflowName, datasets, save, dir) {
93
+ this.log(`Running workflow "${workflowName}" for ${datasets.length} dataset(s)...\n`);
94
+ const results = [];
95
+ for (const dataset of datasets) {
96
+ this.log(` Running "${dataset.name}"...`);
97
+ const startMs = Date.now();
98
+ const response = await postWorkflowRun({
99
+ workflowName,
100
+ input: dataset.input
101
+ }, {
102
+ config: { timeout: 600000 }
103
+ });
104
+ const executionTimeMs = Date.now() - startMs;
105
+ if (!response?.data) {
106
+ this.error(`Workflow execution failed for dataset "${dataset.name}"`, { exit: 1 });
107
+ }
108
+ const updated = {
109
+ ...dataset,
110
+ last_output: {
111
+ output: response.data.output,
112
+ executionTimeMs,
113
+ date: new Date().toISOString()
114
+ }
115
+ };
116
+ if (save) {
117
+ const filePath = join(dir, `${dataset.name}.yml`);
118
+ await writeDataset(updated, filePath);
119
+ this.log(` Saved output to ${filePath}`);
120
+ }
121
+ results.push(updated);
122
+ }
123
+ this.log('');
124
+ return results;
125
+ }
126
+ async saveEvalResults(evalOutput, datasets, dir) {
127
+ const now = new Date().toISOString();
128
+ for (const evalCase of evalOutput.cases) {
129
+ const dataset = datasets.find(d => d.name === evalCase.datasetName);
130
+ if (!dataset) {
131
+ continue;
132
+ }
133
+ const updated = {
134
+ ...dataset,
135
+ last_eval: {
136
+ output: evalCase,
137
+ date: now
138
+ }
139
+ };
140
+ const filePath = join(dir, `${dataset.name}.yml`);
141
+ await writeDataset(updated, filePath);
142
+ this.log(` Saved eval result to ${filePath}`);
143
+ }
144
+ }
145
+ async catch(error) {
146
+ return handleApiError(error, (...args) => this.error(...args), {
147
+ 404: 'Workflow or eval workflow not found. Check the workflow name.',
148
+ 500: 'Workflow execution failed.'
149
+ });
150
+ }
151
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * CLI configuration
3
+ */
4
+ export declare const config: {
5
+ /**
6
+ * Base URL for the Output.ai API server
7
+ * Can be overridden with OUTPUT_API_URL environment variable
8
+ */
9
+ apiUrl: string;
10
+ /**
11
+ * API authentication token
12
+ * Set via OUTPUT_API_AUTH_TOKEN environment variable
13
+ */
14
+ apiToken: string | undefined;
15
+ /**
16
+ * Default timeout for API requests (in milliseconds)
17
+ */
18
+ requestTimeout: number;
19
+ /**
20
+ * Docker Compose project name
21
+ * Can be overridden with DOCKER_SERVICE_NAME environment variable
22
+ */
23
+ dockerServiceName: string;
24
+ /**
25
+ * Set the debug mode
26
+ */
27
+ debugMode: boolean;
28
+ /**
29
+ * Where the env vars are stored, defaults to `.env`
30
+ */
31
+ envFile: string;
32
+ /**
33
+ * Agent configuration directory name
34
+ */
35
+ agentConfigDir: string;
36
+ /**
37
+ * S3 configuration for remote trace storage
38
+ * Set via OUTPUT_TRACE_REMOTE_S3_BUCKET, OUTPUT_AWS_REGION,
39
+ * OUTPUT_AWS_ACCESS_KEY_ID, and OUTPUT_AWS_SECRET_ACCESS_KEY environment variables
40
+ */
41
+ s3: {
42
+ bucket: string | undefined;
43
+ region: string | undefined;
44
+ accessKeyId: string | undefined;
45
+ secretAccessKey: string | undefined;
46
+ };
47
+ };
package/dist/config.js ADDED
@@ -0,0 +1,47 @@
1
+ /**
2
+ * CLI configuration
3
+ */
4
+ export const config = {
5
+ /**
6
+ * Base URL for the Output.ai API server
7
+ * Can be overridden with OUTPUT_API_URL environment variable
8
+ */
9
+ apiUrl: process.env.OUTPUT_API_URL || 'http://localhost:3001',
10
+ /**
11
+ * API authentication token
12
+ * Set via OUTPUT_API_AUTH_TOKEN environment variable
13
+ */
14
+ apiToken: process.env.OUTPUT_API_AUTH_TOKEN,
15
+ /**
16
+ * Default timeout for API requests (in milliseconds)
17
+ */
18
+ requestTimeout: 30000,
19
+ /**
20
+ * Docker Compose project name
21
+ * Can be overridden with DOCKER_SERVICE_NAME environment variable
22
+ */
23
+ dockerServiceName: process.env.DOCKER_SERVICE_NAME || 'output-sdk',
24
+ /**
25
+ * Set the debug mode
26
+ */
27
+ debugMode: process.env.OUTPUT_DEBUG === 'true',
28
+ /**
29
+ * Where the env vars are stored, defaults to `.env`
30
+ */
31
+ envFile: process.env.OUTPUT_CLI_ENV || '.env',
32
+ /**
33
+ * Agent configuration directory name
34
+ */
35
+ agentConfigDir: '.outputai',
36
+ /**
37
+ * S3 configuration for remote trace storage
38
+ * Set via OUTPUT_TRACE_REMOTE_S3_BUCKET, OUTPUT_AWS_REGION,
39
+ * OUTPUT_AWS_ACCESS_KEY_ID, and OUTPUT_AWS_SECRET_ACCESS_KEY environment variables
40
+ */
41
+ s3: {
42
+ bucket: process.env.OUTPUT_TRACE_REMOTE_S3_BUCKET,
43
+ region: process.env.OUTPUT_AWS_REGION,
44
+ accessKeyId: process.env.OUTPUT_AWS_ACCESS_KEY_ID,
45
+ secretAccessKey: process.env.OUTPUT_AWS_SECRET_ACCESS_KEY
46
+ }
47
+ };
@@ -0,0 +1,3 @@
1
+ {
2
+ "framework": "0.1.3"
3
+ }
@@ -0,0 +1,3 @@
1
+ import { Hook } from '@oclif/core';
2
+ declare const hook: Hook<'init'>;
3
+ export default hook;
@@ -0,0 +1,30 @@
1
+ import { ux } from '@oclif/core';
2
+ import { checkForUpdate } from '#services/version_check.js';
3
+ const hook = async function () {
4
+ try {
5
+ const result = await checkForUpdate(this.config.version, this.config.cacheDir);
6
+ if (!result.updateAvailable) {
7
+ return;
8
+ }
9
+ const border = ux.colorize('dim', '─'.repeat(80));
10
+ const warning = ux.colorize('yellow', 'Uhoh! Your Output.ai CLI is behind!');
11
+ const latestVer = ux.colorize('green', `v${result.latestVersion}`);
12
+ const currentVer = ux.colorize('yellow', `v${result.currentVersion}`);
13
+ const updateCmd = ux.colorize('cyan', 'npx output update');
14
+ ux.stdout('');
15
+ ux.stdout(border);
16
+ ux.stdout('');
17
+ ux.stdout(` ⚠️ ${warning}`);
18
+ ux.stdout('');
19
+ ux.stdout(` Latest is ${latestVer}, and you're using ${currentVer}`);
20
+ ux.stdout('');
21
+ ux.stdout(` Run \`${updateCmd}\` to update`);
22
+ ux.stdout('');
23
+ ux.stdout(border);
24
+ ux.stdout('');
25
+ }
26
+ catch {
27
+ // Never block CLI execution
28
+ }
29
+ };
30
+ export default hook;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,54 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { describe, it, expect, beforeEach, vi } from 'vitest';
3
+ import { checkForUpdate } from '#services/version_check.js';
4
+ vi.mock('#services/version_check.js', () => ({
5
+ checkForUpdate: vi.fn()
6
+ }));
7
+ vi.mock('@oclif/core', () => ({
8
+ ux: {
9
+ stdout: vi.fn(),
10
+ colorize: vi.fn((_color, text) => text)
11
+ }
12
+ }));
13
+ import { ux } from '@oclif/core';
14
+ import hook from './init.js';
15
+ describe('init hook', () => {
16
+ beforeEach(() => {
17
+ vi.clearAllMocks();
18
+ });
19
+ const createHookContext = (version = '0.8.4') => ({
20
+ config: { version, cacheDir: '/tmp/test-cache' }
21
+ });
22
+ it('should display warning when update is available', async () => {
23
+ vi.mocked(checkForUpdate).mockResolvedValue({
24
+ updateAvailable: true,
25
+ currentVersion: '0.8.4',
26
+ latestVersion: '1.0.0'
27
+ });
28
+ const ctx = createHookContext();
29
+ await hook.call(ctx, {});
30
+ expect(checkForUpdate).toHaveBeenCalledWith('0.8.4', '/tmp/test-cache');
31
+ expect(ux.stdout).toHaveBeenCalled();
32
+ const output = vi.mocked(ux.stdout).mock.calls.map(c => c[0]).join('\n');
33
+ expect(output).toContain('Uhoh');
34
+ expect(output).toContain('v1.0.0');
35
+ expect(output).toContain('v0.8.4');
36
+ expect(output).toContain('npx output update');
37
+ });
38
+ it('should not display anything when up to date', async () => {
39
+ vi.mocked(checkForUpdate).mockResolvedValue({
40
+ updateAvailable: false,
41
+ currentVersion: '0.8.4',
42
+ latestVersion: '0.8.4'
43
+ });
44
+ const ctx = createHookContext();
45
+ await hook.call(ctx, {});
46
+ expect(ux.stdout).not.toHaveBeenCalled();
47
+ });
48
+ it('should silently handle errors', async () => {
49
+ vi.mocked(checkForUpdate).mockRejectedValue(new Error('network failure'));
50
+ const ctx = createHookContext();
51
+ await hook.call(ctx, {});
52
+ expect(ux.stdout).not.toHaveBeenCalled();
53
+ });
54
+ });
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { run } from '@oclif/core';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ describe('CLI', () => {
3
+ it('should be initialized', () => {
4
+ expect(true).toBe(true);
5
+ });
6
+ });
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Claude Agent SDK client for workflow planning
3
+ */
4
+ import { Options } from '@anthropic-ai/claude-agent-sdk';
5
+ export declare const PLAN_COMMAND_OPTIONS: Options;
6
+ export declare const BUILD_COMMAND_OPTIONS: Options;
7
+ export declare class ClaudeInvocationError extends Error {
8
+ cause?: Error | undefined;
9
+ constructor(message: string, cause?: Error | undefined);
10
+ }
11
+ export declare function replyToClaude(message: string, options?: Options): Promise<string>;
12
+ /**
13
+ * Invoke claude-code with /outputai:plan_workflow slash command
14
+ * The SDK loads custom commands from .claude/commands/ when settingSources includes 'project'.
15
+ * ensureOutputAISystem() scaffolds the command files to that location.
16
+ * @param description - Workflow description
17
+ * @returns Plan output from claude-code
18
+ */
19
+ export declare function invokePlanWorkflow(description: string): Promise<string>;
20
+ /**
21
+ * Invoke claude-code with /outputai:build_workflow slash command
22
+ * The SDK loads custom commands from .claude/commands/ when settingSources includes 'project'.
23
+ * ensureOutputAISystem() scaffolds the command files to that location.
24
+ * @param planFilePath - Absolute path to the plan file
25
+ * @param workflowDir - Absolute path to the workflow directory
26
+ * @param workflowName - Name of the workflow
27
+ * @param additionalInstructions - Optional additional instructions
28
+ * @returns Implementation output from claude-code
29
+ */
30
+ export declare function invokeBuildWorkflow(planFilePath: string, workflowDir: string, workflowName: string, additionalInstructions?: string): Promise<string>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,43 @@
1
+ import { describe, it, expect, beforeEach } from 'vitest';
2
+ import { invokePlanWorkflow } from './claude_client.js';
3
+ import { query } from '@anthropic-ai/claude-agent-sdk';
4
+ describe('invokePlanWorkflow - Integration Tests', () => {
5
+ beforeEach(() => {
6
+ // Ensure API key is set
7
+ if (!process.env.ANTHROPIC_API_KEY) {
8
+ throw new Error('ANTHROPIC_API_KEY must be set for integration tests');
9
+ }
10
+ });
11
+ it('should debug actual message format from Claude Agent SDK', async () => {
12
+ const description = 'Simple test workflow that takes a number and returns it doubled';
13
+ console.log('\n===== DEBUGGING ACTUAL MESSAGE FORMAT =====');
14
+ console.log('Description:', description);
15
+ const messages = [];
16
+ try {
17
+ for await (const message of query({
18
+ prompt: `/outputai:plan_workflow ${description}`,
19
+ options: { maxTurns: 1 }
20
+ })) {
21
+ console.log('\nReceived message:', JSON.stringify(message, null, 2));
22
+ messages.push(message);
23
+ }
24
+ }
25
+ catch (error) {
26
+ console.error('Error during query:', error);
27
+ throw error;
28
+ }
29
+ console.log(`\nTotal messages received: ${messages.length}`);
30
+ console.log('===== END DEBUG =====');
31
+ // This test is just for debugging - we expect messages
32
+ expect(messages.length).toBeGreaterThan(0);
33
+ }, 60000); // 60 second timeout
34
+ it('should successfully invoke /outputai:plan_workflow slash command and return content', async () => {
35
+ const description = 'Simple workflow that takes a number and doubles it';
36
+ const result = await invokePlanWorkflow(description);
37
+ console.log('\n===== PLAN RESULT =====');
38
+ console.log(result);
39
+ console.log('===== END RESULT =====');
40
+ expect(result).toBeTruthy();
41
+ expect(result.length).toBeGreaterThan(0);
42
+ }, 60000); // 60 second timeout
43
+ });