@outputai/cli 0.1.4-dev.0 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/package.json +4 -4
  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,163 +0,0 @@
1
- import { input, confirm, password } from '@inquirer/prompts';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { ux } from '@oclif/core';
5
- import { getErrorMessage } from '#utils/error_utils.js';
6
- import { UserCancelledError } from '#types/errors.js';
7
- const COMMENT_LINE = /^\s*#/;
8
- const COMMENTED_VAR = /^\s*#\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/;
9
- const ACTIVE_VAR = /^\s*([A-Z_][A-Z0-9_]*)\s*=\s*(.*)$/;
10
- const VAR_IN_COMMENT = /^\s*#\s*[A-Z_]+=/;
11
- const SECRET_MARKER = '<SECRET>';
12
- function extractDescription(commentLine) {
13
- return commentLine.replace(/^\s*#\s*/, '').trim();
14
- }
15
- function isSecret(value) {
16
- return value.trim() === SECRET_MARKER;
17
- }
18
- function createEnvVariable(match, options) {
19
- return {
20
- key: match[1],
21
- value: match[2],
22
- description: options.lastComment ? extractDescription(options.lastComment) : undefined,
23
- lineNumber: options.lineNumber,
24
- isCommented: options.isCommented,
25
- originalLine: options.line,
26
- isSecret: isSecret(match[2])
27
- };
28
- }
29
- async function parseEnvFile(filePath) {
30
- const content = await fs.readFile(filePath, 'utf-8');
31
- const lines = content.split('\n');
32
- // Use an object to track state without reassigning
33
- const state = { lastComment: null };
34
- const variables = [];
35
- lines.forEach((line, i) => {
36
- // Check if line is a comment (but not a commented-out variable)
37
- if (line.match(COMMENT_LINE) && !line.match(VAR_IN_COMMENT)) {
38
- state.lastComment = line;
39
- return;
40
- }
41
- // Check for commented-out variable
42
- const commentedMatch = line.match(COMMENTED_VAR);
43
- if (commentedMatch) {
44
- variables.push(createEnvVariable(commentedMatch, {
45
- lineNumber: i,
46
- line,
47
- isCommented: true,
48
- lastComment: state.lastComment
49
- }));
50
- state.lastComment = null;
51
- return;
52
- }
53
- // Check for active variable
54
- const activeMatch = line.match(ACTIVE_VAR);
55
- if (activeMatch) {
56
- variables.push(createEnvVariable(activeMatch, {
57
- lineNumber: i,
58
- line,
59
- isCommented: false,
60
- lastComment: state.lastComment
61
- }));
62
- state.lastComment = null;
63
- return;
64
- }
65
- // Reset lastComment if we hit a blank line or non-comment line
66
- if (line.trim() === '' || !line.match(COMMENT_LINE)) {
67
- state.lastComment = null;
68
- }
69
- });
70
- return variables;
71
- }
72
- const isEmpty = (value) => value.trim() === '';
73
- const promptForVariables = async (variables) => variables.reduce(async (accPromise, variable) => {
74
- const acc = await accPromise;
75
- // Skip if value is not empty and not a secret marker
76
- if (!isEmpty(variable.value) && !variable.isSecret) {
77
- return [...acc, variable];
78
- }
79
- const description = variable.description ? ` (${variable.description})` : '';
80
- // Use password prompt for secrets, regular input for others
81
- const newValue = variable.isSecret ?
82
- await password({
83
- message: `${variable.key}${description} (secret):`,
84
- mask: true
85
- }) :
86
- await input({
87
- message: `${variable.key}${description}:`,
88
- default: ''
89
- });
90
- return [
91
- ...acc,
92
- {
93
- ...variable,
94
- value: newValue,
95
- isCommented: newValue ? false : variable.isCommented,
96
- isSecret: false // Clear the secret flag after getting the actual value
97
- }
98
- ];
99
- }, Promise.resolve([]));
100
- async function writeEnvFile(filePath, variables) {
101
- const content = await fs.readFile(filePath, 'utf-8');
102
- const lines = content.split('\n');
103
- const variableMap = new Map(variables.map(v => [v.lineNumber, v]));
104
- const outputLines = lines.map((line, i) => {
105
- const variable = variableMap.get(i);
106
- if (variable) {
107
- // Reconstruct the variable line
108
- return `${variable.isCommented ? '# ' : ''}${variable.key}=${variable.value}`;
109
- }
110
- // Preserve other lines (comments, blank lines, etc.)
111
- return line;
112
- });
113
- await fs.writeFile(filePath, outputLines.join('\n'), 'utf-8');
114
- }
115
- /**
116
- * Interactively configures environment variables for a project by prompting the user
117
- * to provide values for empty variables or variables marked as secrets.
118
- *
119
- * This function reads from .env.example and, when the user confirms configuration,
120
- * copies it to .env before prompting for values. The .env.example file remains
121
- * unchanged as a template for other developers.
122
- *
123
- * @param projectPath - The absolute path to the project directory containing the .env.example file
124
- * @param skipPrompt - If true, copies .env.example to .env without interactive prompts and returns false
125
- * @returns A promise that resolves to true if environment variables were successfully configured,
126
- * false if configuration was skipped (no .env.example file, user declined, no variables to configure,
127
- * or an error occurred)
128
- */
129
- export async function configureEnvironmentVariables(projectPath, skipPrompt = false) {
130
- try {
131
- ux.stdout('configuring environment variables...');
132
- const envExamplePath = path.join(projectPath, '.env.example');
133
- const envPath = path.join(projectPath, '.env');
134
- // Copy .env.example to .env before configuring
135
- await fs.copyFile(envExamplePath, envPath);
136
- if (skipPrompt) {
137
- return false;
138
- }
139
- const shouldConfigure = await confirm({
140
- message: 'Would you like to configure environment variables now?',
141
- default: true
142
- });
143
- if (!shouldConfigure) {
144
- return false;
145
- }
146
- const variables = await parseEnvFile(envPath);
147
- const variablesToConfigure = variables.filter(v => isEmpty(v.value) || v.isSecret);
148
- if (variablesToConfigure.length === 0) {
149
- return false;
150
- }
151
- const updated = await promptForVariables(variables);
152
- await writeEnvFile(envPath, updated);
153
- return true;
154
- }
155
- catch (error) {
156
- // Ctrl+C in @inquirer/prompts throws ExitPromptError - propagate as UserCancelledError
157
- if (error instanceof Error && error.name === 'ExitPromptError') {
158
- throw new UserCancelledError();
159
- }
160
- ux.warn(`Failed to configure environment variables: ${getErrorMessage(error)}`);
161
- return false;
162
- }
163
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,192 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
- import fs from 'node:fs/promises';
3
- import path from 'node:path';
4
- import { configureEnvironmentVariables } from './env_configurator.js';
5
- // Mock inquirer prompts
6
- vi.mock('@inquirer/prompts', () => ({
7
- input: vi.fn(),
8
- confirm: vi.fn(),
9
- password: vi.fn()
10
- }));
11
- describe('configureEnvironmentVariables', () => {
12
- const testState = { tempDir: '', envExamplePath: '', envPath: '' };
13
- beforeEach(async () => {
14
- // Clear all mocks before each test
15
- vi.clearAllMocks();
16
- // Create temporary directory for test files
17
- testState.tempDir = path.join('/tmp', `test-env-${Date.now()}`);
18
- await fs.mkdir(testState.tempDir, { recursive: true });
19
- testState.envExamplePath = path.join(testState.tempDir, '.env.example');
20
- testState.envPath = path.join(testState.tempDir, '.env');
21
- });
22
- afterEach(async () => {
23
- // Clean up temporary directory
24
- try {
25
- await fs.rm(testState.tempDir, { recursive: true, force: true });
26
- }
27
- catch {
28
- // Ignore cleanup errors
29
- }
30
- });
31
- it('should copy .env.example to .env when skipPrompt is true', async () => {
32
- const envExampleContent = 'API_KEY=<SECRET>\nDATABASE_URL=localhost';
33
- await fs.writeFile(testState.envExamplePath, envExampleContent);
34
- const result = await configureEnvironmentVariables(testState.tempDir, true);
35
- expect(result).toBe(false);
36
- const envContent = await fs.readFile(testState.envPath, 'utf-8');
37
- expect(envContent).toBe(envExampleContent);
38
- });
39
- it('should return false if .env.example file does not exist', async () => {
40
- const result = await configureEnvironmentVariables(testState.tempDir, false);
41
- expect(result).toBe(false);
42
- });
43
- it('should handle missing .env.example gracefully when skipPrompt is true', async () => {
44
- const result = await configureEnvironmentVariables(testState.tempDir, true);
45
- expect(result).toBe(false);
46
- });
47
- it('should return false if user declines configuration', async () => {
48
- const { confirm } = await import('@inquirer/prompts');
49
- vi.mocked(confirm).mockResolvedValue(false);
50
- await fs.writeFile(testState.envExamplePath, '# API key\nAPIKEY=');
51
- const result = await configureEnvironmentVariables(testState.tempDir, false);
52
- expect(result).toBe(false);
53
- expect(vi.mocked(confirm)).toHaveBeenCalled();
54
- });
55
- it('should return false if no empty variables exist', async () => {
56
- const { confirm } = await import('@inquirer/prompts');
57
- vi.mocked(confirm).mockResolvedValue(true);
58
- await fs.writeFile(testState.envExamplePath, 'APIKEY=my-secret-key');
59
- const result = await configureEnvironmentVariables(testState.tempDir, false);
60
- expect(result).toBe(false);
61
- });
62
- it('should copy .env.example to .env when user confirms configuration', async () => {
63
- const { input, confirm } = await import('@inquirer/prompts');
64
- vi.mocked(confirm).mockResolvedValue(true);
65
- vi.mocked(input).mockResolvedValueOnce('sk-proj-123');
66
- const originalContent = `# API key
67
- APIKEY=`;
68
- await fs.writeFile(testState.envExamplePath, originalContent);
69
- await configureEnvironmentVariables(testState.tempDir, false);
70
- // Both files should exist
71
- await expect(fs.access(testState.envExamplePath)).resolves.toBeUndefined();
72
- await expect(fs.access(testState.envPath)).resolves.toBeUndefined();
73
- });
74
- it('should write configured values to .env while leaving .env.example unchanged', async () => {
75
- const { input, confirm } = await import('@inquirer/prompts');
76
- vi.mocked(confirm).mockResolvedValue(true);
77
- vi.mocked(input).mockResolvedValueOnce('sk-proj-123');
78
- const originalContent = `# API key
79
- APIKEY=`;
80
- await fs.writeFile(testState.envExamplePath, originalContent);
81
- const result = await configureEnvironmentVariables(testState.tempDir, false);
82
- expect(result).toBe(true);
83
- // .env should have the configured value
84
- const envContent = await fs.readFile(testState.envPath, 'utf-8');
85
- expect(envContent).toContain('APIKEY=sk-proj-123');
86
- // .env.example should remain unchanged
87
- const envExampleContent = await fs.readFile(testState.envExamplePath, 'utf-8');
88
- expect(envExampleContent).toBe(originalContent);
89
- });
90
- it('should prompt for empty variables and update .env', async () => {
91
- const { input, confirm } = await import('@inquirer/prompts');
92
- vi.mocked(confirm).mockResolvedValue(true);
93
- vi.mocked(input).mockResolvedValueOnce('sk-proj-123');
94
- vi.mocked(input).mockResolvedValueOnce('');
95
- await fs.writeFile(testState.envExamplePath, `# API key for Anthropic
96
- ANTHROPIC_API_KEY=
97
-
98
- # API key for OpenAI
99
- OPENAI_API_KEY=`);
100
- const result = await configureEnvironmentVariables(testState.tempDir, false);
101
- expect(result).toBe(true);
102
- // Verify file was updated
103
- const content = await fs.readFile(testState.envPath, 'utf-8');
104
- expect(content).toContain('ANTHROPIC_API_KEY=sk-proj-123');
105
- expect(content).toContain('OPENAI_API_KEY=');
106
- });
107
- it('should preserve comments in .env file', async () => {
108
- const { input, confirm } = await import('@inquirer/prompts');
109
- vi.mocked(confirm).mockResolvedValue(true);
110
- vi.mocked(input).mockResolvedValueOnce('test-key');
111
- const originalContent = `# This is a comment
112
- # API key configuration
113
- APIKEY=
114
-
115
- # Another comment
116
- OTHER=value`;
117
- await fs.writeFile(testState.envExamplePath, originalContent);
118
- await configureEnvironmentVariables(testState.tempDir, false);
119
- const content = await fs.readFile(testState.envPath, 'utf-8');
120
- expect(content).toContain('# This is a comment');
121
- expect(content).toContain('# API key configuration');
122
- expect(content).toContain('# Another comment');
123
- expect(content).toContain('OTHER=value');
124
- });
125
- it('should skip placeholder values and only prompt for truly empty variables', async () => {
126
- const { input, confirm } = await import('@inquirer/prompts');
127
- vi.mocked(confirm).mockResolvedValue(true);
128
- vi.mocked(input).mockResolvedValueOnce('new-key');
129
- await fs.writeFile(testState.envExamplePath, `APIKEY=your_api_key_here
130
- EMPTY_KEY=`);
131
- const result = await configureEnvironmentVariables(testState.tempDir, false);
132
- expect(result).toBe(true);
133
- expect(vi.mocked(input)).toHaveBeenCalledTimes(1);
134
- expect(vi.mocked(input)).toHaveBeenCalledWith(expect.objectContaining({
135
- message: expect.stringContaining('EMPTY_KEY')
136
- }));
137
- });
138
- it('should skip variables with existing values', async () => {
139
- const { input, confirm } = await import('@inquirer/prompts');
140
- vi.mocked(confirm).mockResolvedValue(true);
141
- vi.mocked(input).mockResolvedValueOnce('new-key');
142
- await fs.writeFile(testState.envExamplePath, `EXISTING_KEY=existing-value
143
-
144
- EMPTY_KEY=`);
145
- await configureEnvironmentVariables(testState.tempDir, false);
146
- // Should only prompt for EMPTY_KEY, not EXISTING_KEY
147
- expect(vi.mocked(input)).toHaveBeenCalledTimes(1);
148
- });
149
- it('should handle case where .env already exists (overwrite with copy)', async () => {
150
- const { input, confirm } = await import('@inquirer/prompts');
151
- vi.mocked(confirm).mockResolvedValue(true);
152
- vi.mocked(input).mockResolvedValueOnce('new-configured-value');
153
- // Create existing .env with old content
154
- await fs.writeFile(testState.envPath, 'OLD_KEY=old-value');
155
- // Create .env.example with new content
156
- await fs.writeFile(testState.envExamplePath, 'NEW_KEY=');
157
- const result = await configureEnvironmentVariables(testState.tempDir, false);
158
- expect(result).toBe(true);
159
- // .env should be overwritten with .env.example content and configured values
160
- const envContent = await fs.readFile(testState.envPath, 'utf-8');
161
- expect(envContent).toContain('NEW_KEY=new-configured-value');
162
- expect(envContent).not.toContain('OLD_KEY');
163
- });
164
- it('should return false if an error occurs during parsing', async () => {
165
- const { confirm } = await import('@inquirer/prompts');
166
- vi.mocked(confirm).mockResolvedValue(true);
167
- await fs.writeFile(testState.envExamplePath, 'KEY=');
168
- // Delete the .env.example file after access check but before parsing would happen
169
- // We simulate this by deleting during the copy operation
170
- const originalCopyFile = fs.copyFile;
171
- vi.spyOn(fs, 'copyFile').mockImplementation(async () => {
172
- throw new Error('Copy failed');
173
- });
174
- const result = await configureEnvironmentVariables(testState.tempDir, false);
175
- // Should return false when error occurs
176
- expect(result).toBe(false);
177
- // Restore original function
178
- vi.mocked(fs.copyFile).mockImplementation(originalCopyFile);
179
- });
180
- it('should prompt for SECRET marker values with password input', async () => {
181
- const { password, confirm } = await import('@inquirer/prompts');
182
- vi.mocked(confirm).mockResolvedValue(true);
183
- vi.mocked(password).mockResolvedValueOnce('my-secret-api-key');
184
- await fs.writeFile(testState.envExamplePath, `# API Key
185
- ANTHROPIC_API_KEY=<SECRET>`);
186
- const result = await configureEnvironmentVariables(testState.tempDir, false);
187
- expect(result).toBe(true);
188
- expect(vi.mocked(password)).toHaveBeenCalledTimes(1);
189
- const envContent = await fs.readFile(testState.envPath, 'utf-8');
190
- expect(envContent).toContain('ANTHROPIC_API_KEY=my-secret-api-key');
191
- });
192
- });
@@ -1,24 +0,0 @@
1
- ---
2
- provider: anthropic
3
- model: claude-haiku-4-5
4
- temperature: 0.3
5
- ---
6
-
7
- <assistant>
8
- You are a semantic naming assistant. Generate concise, descriptive slugs for workflow plans.
9
- </assistant>
10
-
11
- <user>
12
- Convert this workflow description into a short, semantic slug (2-6 words max):
13
-
14
- "{{ description }}"
15
-
16
- Requirements:
17
- - Use snake_case format
18
- - Be descriptive but concise
19
- - Focus on the core action/purpose
20
- - Use common technical terms
21
- - Maximum 50 characters
22
-
23
- Return ONLY the slug, no quotes, no explanation.
24
- </user>
@@ -1,9 +0,0 @@
1
- /**
2
- * Success and informational messages for project initialization
3
- */
4
- export declare const getEjectSuccessMessage: (destPath: string, outputFile: string, binName: string) => string;
5
- export declare const getProjectSuccessMessage: (folderName: string, installSuccess: boolean, envConfigured?: boolean) => string;
6
- export declare const getWorkflowGenerateSuccessMessage: (workflowName: string, targetDir: string, filesCreated: string[]) => string;
7
- export declare const getDevSuccessMessage: (services: Array<{
8
- name: string;
9
- }>) => string;