cloving 0.1.10 → 0.1.11

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.
@@ -29,7 +29,7 @@ class ClaudeAdapter {
29
29
  { role: 'user', content: request.prompt }
30
30
  ],
31
31
  max_tokens: request.maxTokens || 4096,
32
- temperature: request.temperature || 0.7
32
+ temperature: request.temperature || 0.2
33
33
  };
34
34
  }
35
35
  extractResponse(data) {
@@ -31,7 +31,7 @@ class GeminiAdapter {
31
31
  }
32
32
  ],
33
33
  generationConfig: {
34
- temperature: 0.7,
34
+ temperature: 0.2,
35
35
  topK: 40,
36
36
  topP: 0.95,
37
37
  maxOutputTokens: 1024
@@ -24,7 +24,7 @@ class MistralAdapter {
24
24
  model: this.model.replace(':', '-'),
25
25
  messages: [{ role: "user", content: request.prompt }],
26
26
  max_tokens: request.maxTokens,
27
- temperature: request.temperature || 0.7,
27
+ temperature: request.temperature || 0.2,
28
28
  stream: false
29
29
  };
30
30
  }
@@ -24,7 +24,7 @@ class OpenAIAdapter {
24
24
  model: this.model.replace(':', '-'),
25
25
  messages: [{ role: "user", content: request.prompt }],
26
26
  max_tokens: request.maxTokens,
27
- temperature: request.temperature || 0.7
27
+ temperature: request.temperature || 0.2
28
28
  };
29
29
  }
30
30
  extractResponse(data) {
@@ -81,7 +81,7 @@ class ClovingGPT {
81
81
  }
82
82
  ]);
83
83
  if (!confirmContinue) {
84
- console.error('User cancelled the operation');
84
+ console.error('Operation cancelled');
85
85
  process_1.default.exit(1);
86
86
  }
87
87
  resolve();
@@ -16,7 +16,7 @@ const generateCodePrompt = (prompt, files, contextFiles, previousCode) => {
16
16
  const specialFileContents = (0, command_utils_1.collectSpecialFileContents)();
17
17
  const specialFiles = Object.keys(specialFileContents).map((file) => `### Contents of ${file}\n\n${JSON.stringify(specialFileContents[file], null, 2)}\n\n`).join('\n');
18
18
  const contextFileContents = Object.keys(contextFiles).map((file) => `### Contents of ${file}\n\n${contextFiles[file]}\n\n`).join('\n');
19
- let promptText = `Here is a description of my app:
19
+ let promptText = `### Description of App
20
20
 
21
21
  ${JSON.stringify((0, config_utils_1.getClovingConfig)(), null, 2)}
22
22
 
@@ -87,7 +87,7 @@ const generateCodePrompt = (prompt: string | undefined, files: string[], context
87
87
 
88
88
  ### Request
89
89
 
90
- I would like to generate code that does the following: ${prompt}
90
+ Generate code that does the following: ${prompt}
91
91
 
92
92
  Do not use any data from the example response structure, only use the structure. Please generate the code and include filenames with paths to the code files mentioned and do not be lazy and ask me to keep the existing code or show things like previous code remains unchanged, always include existing code in the response.`;
93
93
  return promptText;
@@ -145,7 +145,8 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
145
145
  choices: [
146
146
  { name: 'Revise', value: 'revise' },
147
147
  { name: 'Explain', value: 'explain' },
148
- { name: 'Save Source Code to Files', value: 'save' },
148
+ { name: 'Save a Source Code File', value: 'save' },
149
+ { name: 'Save All Source Code Files', value: 'saveAll' },
149
150
  { name: 'Copy Source Code to Clipboard', value: 'copySource' },
150
151
  { name: 'Copy Entire Response to Clipboard', value: 'copyAll' },
151
152
  { name: 'Done', value: 'done' },
@@ -158,7 +159,7 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
158
159
  {
159
160
  type: 'input',
160
161
  name: 'newPrompt',
161
- message: 'Enter your revised prompt:',
162
+ message: 'How would you like to modify the output:',
162
163
  },
163
164
  ]);
164
165
  const newRawCodeCommand = await generateCode(gpt, newPrompt, allSrcFiles, contextFiles, rawCodeCommand);
@@ -194,7 +195,7 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
194
195
  type: 'confirm',
195
196
  name: 'copyMore',
196
197
  message: 'Do you want to copy another file?',
197
- default: false,
198
+ default: true,
198
199
  },
199
200
  ]);
200
201
  copyAnother = copyMore;
@@ -230,29 +231,96 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
230
231
  type: 'confirm',
231
232
  name: 'saveMore',
232
233
  message: 'Do you want to save another file?',
233
- default: false,
234
+ default: true,
234
235
  },
235
236
  ]);
236
237
  saveAnother = saveMore;
237
238
  }
238
239
  break;
240
+ case 'saveAll':
241
+ files.forEach(file => {
242
+ if (fileContents[file]) {
243
+ const filePath = path_1.default.resolve(file);
244
+ fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
245
+ fs_1.default.writeFileSync(filePath, fileContents[file]);
246
+ console.log(`${file} has been saved.`);
247
+ }
248
+ else {
249
+ console.log(`File content not found for ${file}.`);
250
+ }
251
+ });
252
+ console.log('All files have been saved.');
253
+ break;
239
254
  case 'done':
240
255
  break;
241
256
  }
242
257
  };
258
+ const addFilesToContext = async (contextFiles, filePath) => {
259
+ const stats = fs_1.default.statSync(filePath);
260
+ if (stats.isDirectory()) {
261
+ const files = fs_1.default.readdirSync(filePath);
262
+ for (const file of files) {
263
+ await addFilesToContext(contextFiles, path_1.default.join(filePath, file));
264
+ }
265
+ }
266
+ else if (stats.isFile()) {
267
+ const content = fs_1.default.readFileSync(filePath, 'utf-8');
268
+ contextFiles[filePath] = content;
269
+ }
270
+ };
243
271
  const code = async (options) => {
244
272
  let { prompt, files } = options;
245
273
  options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
246
274
  const gpt = new cloving_gpt_1.default(options);
247
- const allSrcFiles = await (0, config_utils_1.getAllFiles)(options, true);
275
+ const allSrcFiles = await (0, config_utils_1.getAllFiles)(options, false);
248
276
  const contextFiles = {};
249
277
  try {
278
+ if (files) {
279
+ files.forEach(async (file) => {
280
+ await addFilesToContext(contextFiles, file);
281
+ });
282
+ }
283
+ else {
284
+ let firstFile = true;
285
+ let includeMoreFiles = true;
286
+ while (includeMoreFiles) {
287
+ const { includeMore } = await inquirer_1.default.prompt([
288
+ {
289
+ type: 'confirm',
290
+ name: 'includeMore',
291
+ message: `Do you want to include any${firstFile ? '' : ' other'} files or directories as context for the prompt?`,
292
+ default: false,
293
+ },
294
+ ]);
295
+ firstFile = false;
296
+ includeMoreFiles = includeMore;
297
+ if (includeMoreFiles) {
298
+ const { contextFile } = await inquirer_1.default.prompt([
299
+ {
300
+ type: 'input',
301
+ name: 'contextFile',
302
+ message: 'Enter the relative path of a file or directory you would like to include as context:',
303
+ },
304
+ ]);
305
+ if (contextFile) {
306
+ const filePath = path_1.default.resolve(contextFile);
307
+ if (fs_1.default.existsSync(filePath)) {
308
+ await addFilesToContext(contextFiles, filePath);
309
+ console.log(`Added ${filePath} to context.`);
310
+ }
311
+ else {
312
+ console.log(`File or directory ${contextFile} does not exist.`);
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
250
318
  if (!prompt) {
251
319
  const { userPrompt } = await inquirer_1.default.prompt([
252
320
  {
253
321
  type: 'input',
254
322
  name: 'userPrompt',
255
- message: 'What would you like to build:',
323
+ message: 'What would you like the code to do:',
256
324
  },
257
325
  ]);
258
326
  prompt = userPrompt;
@@ -265,40 +333,7 @@ const code = async (options) => {
265
333
  }
266
334
  // Read the content of the provided files
267
335
  for (const file of files) {
268
- const content = fs_1.default.readFileSync(file, 'utf-8');
269
- contextFiles[file] = content;
270
- }
271
- }
272
- else {
273
- // Prompt for additional context files if no files were passed in options
274
- let includeMoreFiles = true;
275
- while (includeMoreFiles) {
276
- const { contextFile } = await inquirer_1.default.prompt([
277
- {
278
- type: 'input',
279
- name: 'contextFile',
280
- message: 'Relative path of an existing file you would like to include as context in the prompt [optional]:',
281
- },
282
- ]);
283
- if (contextFile) {
284
- const filePath = path_1.default.resolve(contextFile);
285
- if (fs_1.default.existsSync(filePath)) {
286
- const content = fs_1.default.readFileSync(filePath, 'utf-8');
287
- contextFiles[filePath] = content;
288
- }
289
- else {
290
- console.log(`File ${contextFile} does not exist.`);
291
- }
292
- }
293
- const { includeMore } = await inquirer_1.default.prompt([
294
- {
295
- type: 'confirm',
296
- name: 'includeMore',
297
- message: 'Do you want to include any other files?',
298
- default: false,
299
- },
300
- ]);
301
- includeMoreFiles = includeMore;
336
+ await addFilesToContext(contextFiles, file);
302
337
  }
303
338
  }
304
339
  const rawCodeCommand = await generateCode(gpt, prompt, allSrcFiles, contextFiles);
@@ -34,6 +34,68 @@ const generateExplainShellPrompt = (prompt) => {
34
34
 
35
35
  Please briefly explain how this shell script works.`;
36
36
  };
37
+ const generateShell = async (gpt, prompt) => {
38
+ const shellPrompt = generateShellPrompt(prompt);
39
+ return await gpt.generateText({ prompt: shellPrompt });
40
+ };
41
+ const displayGeneratedShell = (rawShellCommand) => {
42
+ const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
43
+ const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
44
+ console.log((0, cli_highlight_1.default)(generatedShellWithoutShebang));
45
+ };
46
+ const handleUserAction = async (gpt, rawShellCommand, prompt) => {
47
+ const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
48
+ const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
49
+ const { action } = await inquirer_1.default.prompt([
50
+ {
51
+ type: 'list',
52
+ name: 'action',
53
+ message: 'What would you like to do?',
54
+ choices: [
55
+ { name: 'Execute', value: 'execute' },
56
+ { name: 'Revise', value: 'revise' },
57
+ { name: 'Explain', value: 'explain' },
58
+ { name: 'Copy to Clipboard', value: 'copy' },
59
+ { name: 'Cancel', value: 'cancel' },
60
+ ],
61
+ },
62
+ ]);
63
+ switch (action) {
64
+ case 'execute':
65
+ (0, child_process_1.execSync)(generatedShellWithoutShebang, { stdio: 'inherit' });
66
+ break;
67
+ case 'revise':
68
+ const { newPrompt } = await inquirer_1.default.prompt([
69
+ {
70
+ type: 'input',
71
+ name: 'newPrompt',
72
+ message: 'How would you like to modify the output:',
73
+ },
74
+ ]);
75
+ const newRawShellCommand = await generateShell(gpt, newPrompt);
76
+ displayGeneratedShell(newRawShellCommand);
77
+ await handleUserAction(gpt, newRawShellCommand, newPrompt);
78
+ break;
79
+ case 'explain':
80
+ const explainPrompt = generateExplainShellPrompt(generatedShellWithoutShebang);
81
+ const explainShellCommand = await gpt.generateText({ prompt: explainPrompt });
82
+ console.log((0, cli_highlight_1.default)(explainShellCommand, { language: 'markdown' }));
83
+ break;
84
+ case 'copy':
85
+ copy_paste_1.default.copy(generatedShellWithoutShebang, (err) => {
86
+ if (err) {
87
+ console.error('Error: Unable to copy to clipboard.', err);
88
+ }
89
+ else {
90
+ console.log('Script copied to clipboard.');
91
+ }
92
+ });
93
+ break;
94
+ case 'cancel':
95
+ console.log('Operation cancelled.');
96
+ break;
97
+ }
98
+ };
37
99
  const shell = async (options) => {
38
100
  let { prompt } = options;
39
101
  options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
@@ -49,60 +111,12 @@ const shell = async (options) => {
49
111
  ]);
50
112
  prompt = userPrompt;
51
113
  }
52
- // Generate the prompt for commit message
53
- const shellPrompt = generateShellPrompt(prompt);
54
- // Instantiate ClovingGPT and get the commit message
55
- const rawShellCommand = await gpt.generateText({ prompt: shellPrompt });
56
- // Clean the commit message using extractMarkdown
57
- const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
58
- // remove #! from the generated shell script
59
- const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
60
- console.log((0, cli_highlight_1.default)(generatedShellWithoutShebang));
61
- // Inquirer prompt for further actions
62
- const { action } = await inquirer_1.default.prompt([
63
- {
64
- type: 'list',
65
- name: 'action',
66
- message: 'What would you like to do?',
67
- choices: [
68
- { name: 'Execute', value: 'execute' },
69
- { name: 'Revise', value: 'revise' },
70
- { name: 'Explain', value: 'explain' },
71
- { name: 'Copy to Clipboard', value: 'copy' },
72
- { name: 'Cancel', value: 'cancel' },
73
- ],
74
- },
75
- ]);
76
- switch (action) {
77
- case 'execute':
78
- (0, child_process_1.execSync)(generatedShellWithoutShebang, { stdio: 'inherit' });
79
- break;
80
- case 'revise':
81
- // Logic to revise the prompt (not implemented in this example)
82
- console.log('Revise option selected. Implement revision logic here.');
83
- break;
84
- case 'explain':
85
- const explainPrompt = generateExplainShellPrompt(generatedShellWithoutShebang);
86
- const explainShellCommand = await gpt.generateText({ prompt: explainPrompt });
87
- console.log((0, cli_highlight_1.default)(explainShellCommand, { language: 'markdown' }));
88
- break;
89
- case 'copy':
90
- copy_paste_1.default.copy(generatedShellWithoutShebang, (err) => {
91
- if (err) {
92
- console.error('Error: Unable to copy to clipboard.', err);
93
- }
94
- else {
95
- console.log('Script copied to clipboard.');
96
- }
97
- });
98
- break;
99
- case 'cancel':
100
- console.log('Operation cancelled.');
101
- break;
102
- }
114
+ const rawShellCommand = await generateShell(gpt, prompt);
115
+ displayGeneratedShell(rawShellCommand);
116
+ await handleUserAction(gpt, rawShellCommand, prompt);
103
117
  }
104
118
  catch (error) {
105
- console.error('Could not generate shell script');
119
+ console.error('Could not generate shell script', error);
106
120
  }
107
121
  };
108
122
  exports.default = shell;
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fs_1 = require("fs");
7
7
  const child_process_1 = require("child_process");
8
8
  const cli_highlight_1 = __importDefault(require("cli-highlight"));
9
+ const inquirer_1 = __importDefault(require("inquirer"));
10
+ const path_1 = __importDefault(require("path"));
9
11
  const git_utils_1 = require("../../utils/git_utils");
10
12
  const config_utils_1 = require("../../utils/config_utils");
11
13
  const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
@@ -20,33 +22,27 @@ const extractChangedFiles = (gitDiff) => {
20
22
  };
21
23
  const generatePrompt = (files, srcFiles, testFiles, gitDiff) => {
22
24
  const filesList = files.length > 0 ? files.join('\n') : 'No files provided';
23
- const diffSection = gitDiff ? `Here is my git diff:\n\n==== begin git diff ====\n${gitDiff}\n==== end git diff ====\n` : '';
24
- return `Here is a list of code files I want to generate unit tests for:
25
+ return `### List of Code Files
25
26
 
26
- ==== begin list of files ====
27
27
  ${filesList}
28
- ==== end list of files ====
29
28
 
30
- Here is a list of all my source files:
29
+ ### List of All Source Files
31
30
 
32
- ==== begin list of source files ====
33
31
  ${srcFiles}
34
- ==== end list of source files ====
35
32
 
36
- Here is a list of all my test files:
33
+ ### List of all test files
37
34
 
38
- ==== begin list of test files ====
39
35
  ${testFiles}
40
- ==== end list of test files ====
41
36
 
42
- ${diffSection}
37
+ ### Git Diff Content
43
38
 
44
- Please enumerate all the files in the provided list${gitDiff ? ' and git diff' : ''} as well as the file names of anything that these files interact with.
39
+ ${gitDiff}
45
40
 
46
- Also, list any test files that might be relevant to these files.
41
+ ## Example Output
47
42
 
48
43
  Give me this output format for your answer:
49
44
 
45
+ \`\`\`plaintext
50
46
  ## files
51
47
 
52
48
  app/models/foo.rb
@@ -55,7 +51,129 @@ app/views/baz/bar.html.erb
55
51
  ## relevant test files
56
52
 
57
53
  test/models/foo_test.rb
58
- test/controllers/baz_controller_test.rb`;
54
+ test/controllers/baz_controller_test.rb
55
+ \`\`\`
56
+
57
+ ### Request
58
+
59
+ Please enumerate all the files in the provided list${gitDiff ? ' and git diff' : ''} as well as the file names of anything that these files interact with.
60
+
61
+ Also, list any test files that might be relevant to these files.`;
62
+ };
63
+ const extractFilesAndContent = (analysis) => {
64
+ const files = [];
65
+ const fileContents = {};
66
+ const matches = analysis.match(/(\*{2})([^\*]+)(\*{2})/g);
67
+ if (!matches)
68
+ return [files, fileContents];
69
+ for (const match of matches) {
70
+ const fileName = match.replace(/\*{2}/g, '').trim();
71
+ const regex = new RegExp(`\\*\\*${fileName}\\*\\*\\n\\n\\\`{3}([\\s\\S]+?)\\\`{3}`, 'g');
72
+ const contentMatch = regex.exec(analysis);
73
+ if (contentMatch) {
74
+ files.push(fileName);
75
+ let content = contentMatch[1];
76
+ // Remove the first word after the opening triple backticks
77
+ content = content.split('\n').map((line, idx) => idx === 0 ? line.replace(/^\w+\s*/, '') : line).join('\n');
78
+ fileContents[fileName] = content;
79
+ }
80
+ }
81
+ return [files, fileContents];
82
+ };
83
+ const handleUserAction = async (analysis) => {
84
+ const [files, fileContents] = extractFilesAndContent(analysis);
85
+ const { action } = await inquirer_1.default.prompt([
86
+ {
87
+ type: 'list',
88
+ name: 'action',
89
+ message: 'What would you like to do?',
90
+ choices: [
91
+ { name: 'Save a Unit Test File', value: 'save' },
92
+ { name: 'Save All Unit Test Files', value: 'saveAll' },
93
+ { name: 'Copy Unit Test to Clipboard', value: 'copyTest' },
94
+ { name: 'Copy Entire Response to Clipboard', value: 'copyAll' },
95
+ { name: 'Done', value: 'done' },
96
+ ],
97
+ },
98
+ ]);
99
+ switch (action) {
100
+ case 'save':
101
+ let saveAnother = true;
102
+ while (saveAnother) {
103
+ const { fileToSave } = await inquirer_1.default.prompt([
104
+ {
105
+ type: 'list',
106
+ name: 'fileToSave',
107
+ message: 'Which unit test file do you want to save?',
108
+ choices: files.map(file => ({ name: file, value: file })),
109
+ },
110
+ ]);
111
+ if (fileContents[fileToSave]) {
112
+ const filePath = path_1.default.resolve(fileToSave);
113
+ fs_1.promises.mkdir(path_1.default.dirname(filePath), { recursive: true })
114
+ .then(() => fs_1.promises.writeFile(filePath, fileContents[fileToSave]))
115
+ .then(() => console.log(`${fileToSave} has been saved.`))
116
+ .catch((error) => console.error(`Error saving ${fileToSave}:`, error));
117
+ }
118
+ else {
119
+ console.log('File content not found.');
120
+ }
121
+ const { saveMore } = await inquirer_1.default.prompt([
122
+ {
123
+ type: 'confirm',
124
+ name: 'saveMore',
125
+ message: 'Do you want to save another file?',
126
+ default: false,
127
+ },
128
+ ]);
129
+ saveAnother = saveMore;
130
+ }
131
+ break;
132
+ case 'saveAll':
133
+ for (const file of files) {
134
+ if (fileContents[file]) {
135
+ const filePath = path_1.default.resolve(file);
136
+ fs_1.promises.mkdir(path_1.default.dirname(filePath), { recursive: true })
137
+ .then(() => fs_1.promises.writeFile(filePath, fileContents[file]))
138
+ .then(() => console.log(`${file} has been saved.`))
139
+ .catch((error) => console.error(`Error saving ${file}:`, error));
140
+ }
141
+ else {
142
+ console.log(`File content not found for ${file}.`);
143
+ }
144
+ }
145
+ console.log('All unit test files have been saved.');
146
+ break;
147
+ case 'copyTest':
148
+ const { fileToCopy } = await inquirer_1.default.prompt([
149
+ {
150
+ type: 'list',
151
+ name: 'fileToCopy',
152
+ message: 'Which unit test file do you want to copy to the clipboard?',
153
+ choices: files.map(file => ({ name: file, value: file })),
154
+ },
155
+ ]);
156
+ if (fileContents[fileToCopy]) {
157
+ process.nextTick(() => {
158
+ require('copy-paste').copy(fileContents[fileToCopy], () => {
159
+ console.log(`${fileToCopy} copied to clipboard`);
160
+ });
161
+ });
162
+ }
163
+ else {
164
+ console.log('File content not found.');
165
+ }
166
+ break;
167
+ case 'copyAll':
168
+ process.nextTick(() => {
169
+ require('copy-paste').copy(analysis, () => {
170
+ console.log('Entire response copied to clipboard');
171
+ });
172
+ });
173
+ break;
174
+ case 'done':
175
+ break;
176
+ }
59
177
  };
60
178
  const unitTests = async (options) => {
61
179
  const { files } = options;
@@ -88,9 +206,9 @@ const unitTests = async (options) => {
88
206
  }
89
207
  });
90
208
  for (const codeFile of lines) {
91
- if (await fs_1.promises?.stat(codeFile).then(stat => stat.isFile()).catch(() => false)) {
209
+ if (await fs_1.promises.stat(codeFile).then(stat => stat.isFile()).catch(() => false)) {
92
210
  const fileContents = await fs_1.promises.readFile(codeFile, 'utf-8');
93
- context.push(`### **Contents of ${codeFile}**\n\n${fileContents}\n\n### **End of ${codeFile}**`);
211
+ context.push(`### Contents of ${codeFile}\n\n${fileContents}\n\n### End of ${codeFile}`);
94
212
  }
95
213
  }
96
214
  // Generate the message for unit test creation
@@ -98,11 +216,11 @@ const unitTests = async (options) => {
98
216
  if ((files || []).length > 0) {
99
217
  const message = `please create unit tests for these files:
100
218
 
101
- ## begin list of files
219
+ ## Begin list of files
102
220
  ${(files || []).join('\n')}
103
- ## end list of files
221
+ ## End list of files
104
222
 
105
- ## context
223
+ ## Context
106
224
  ${context.join('\n\n')}`;
107
225
  // Get the model and analysis using ClovingGPT
108
226
  analysis = await gpt.generateText({ prompt: message });
@@ -110,16 +228,18 @@ ${context.join('\n\n')}`;
110
228
  else {
111
229
  const message = `please create unit tests for these changes:
112
230
 
113
- ## begin diff
231
+ ## Begin diff
114
232
  ${await (0, git_utils_1.getGitDiff)()}
115
- ## end diff
233
+ ## End diff
116
234
 
117
- ## context
235
+ ## Context
118
236
 
119
237
  ${context.join('\n\n')}`;
120
238
  // Get the model and analysis using ClovingGPT
121
239
  analysis = await gpt.generateText({ prompt: message });
122
240
  }
123
241
  console.log((0, cli_highlight_1.default)(analysis));
242
+ // Add the new user action handling
243
+ await handleUserAction(analysis);
124
244
  };
125
245
  exports.default = unitTests;
package/dist/index.js CHANGED
@@ -59,7 +59,7 @@ const generate = program
59
59
  .description('Generate various items like unit-tests and code reviews');
60
60
  generate
61
61
  .command('shell')
62
- .alias('s')
62
+ .alias('sh')
63
63
  .description('Generate a shell command based on a prompt')
64
64
  .option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
65
65
  .option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloving",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -61,7 +61,8 @@ const getClovingConfig = () => {
61
61
  return clovingConfig;
62
62
  }
63
63
  else {
64
- throw new Error(`${exports.CLOVING_CONFIG_PATH} file not found`);
64
+ console.log(`${exports.CLOVINGFILE_PATH} file not found, please run: cloving init`);
65
+ process.exit(1);
65
66
  }
66
67
  };
67
68
  exports.getClovingConfig = getClovingConfig;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloving",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "scripts": {
@@ -68,5 +68,10 @@
68
68
  "lint-staged": "^15.2.7",
69
69
  "ts-jest": "^29.2.0",
70
70
  "typescript": "^5.5.3"
71
+ },
72
+ "resolutions": {
73
+ "eslint": "8.57.0",
74
+ "eslint-plugin-n": "16.6.2",
75
+ "eslint-plugin-import": "2.29.1"
71
76
  }
72
77
  }