cloving 0.1.12 → 0.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/generate/code.js +122 -97
- package/dist/commands/generate/context.js +69 -0
- package/dist/commands/generate/shell.js +3 -1
- package/dist/commands/init.js +6 -13
- package/dist/index.js +8 -1
- package/dist/package.json +1 -1
- package/dist/utils/command_utils.js +34 -34
- package/package.json +1 -1
|
@@ -6,12 +6,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const copy_paste_1 = __importDefault(require("copy-paste"));
|
|
7
7
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
8
|
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
9
|
+
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
9
11
|
const command_utils_1 = require("../../utils/command_utils");
|
|
10
12
|
const config_utils_1 = require("../../utils/config_utils");
|
|
11
13
|
const string_utils_1 = require("../../utils/string_utils");
|
|
12
14
|
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
13
|
-
const fs_1 = __importDefault(require("fs"));
|
|
14
|
-
const path_1 = __importDefault(require("path"));
|
|
15
15
|
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');
|
|
@@ -62,29 +62,6 @@ Do not add any commentary or context to the message other than the commit messag
|
|
|
62
62
|
An example of the output for this should look like the following:
|
|
63
63
|
\`\`\`
|
|
64
64
|
|
|
65
|
-
2. **src/commands/generate/code.ts**
|
|
66
|
-
|
|
67
|
-
\`\`\`typescript
|
|
68
|
-
import ncp from 'copy-paste'
|
|
69
|
-
import inquirer from 'inquirer'
|
|
70
|
-
import highlight from 'cli-highlight'
|
|
71
|
-
import { collectSpecialFileContents } from '../../utils/command_utils'
|
|
72
|
-
import { getConfig, getClovingConfig, getAllFiles } from '../../utils/config_utils'
|
|
73
|
-
import { parseMarkdownInstructions, extractMarkdown } from '../../utils/string_utils'
|
|
74
|
-
import ClovingGPT from '../../cloving_gpt'
|
|
75
|
-
import type { ClovingGPTOptions } from '../../utils/types'
|
|
76
|
-
import fs from 'fs'
|
|
77
|
-
import path from 'path'
|
|
78
|
-
|
|
79
|
-
const generateCodePrompt = (prompt: string | undefined, files: string[], contextFiles: Record<string, string>, previousCode?: string): string => {
|
|
80
|
-
const specialFileContents = collectSpecialFileContents()
|
|
81
|
-
const specialFiles = Object.keys(specialFileContents).map((file) => \`### Contents of \${file}\\n\\n\${JSON.stringify(specialFileContents[file], null, 2)}\\n\\n\`).join('\\n')
|
|
82
|
-
const contextFileContents = Object.keys(contextFiles).map((file) => \`### Contents of \${file}\\n\\n\${contextFiles[file]}\\n\\n\`).join('\\n')
|
|
83
|
-
|
|
84
|
-
return 'Here is a description of my app:'
|
|
85
|
-
}
|
|
86
|
-
\`\`\`
|
|
87
|
-
|
|
88
65
|
### Request
|
|
89
66
|
|
|
90
67
|
Generate code that does the following: ${prompt}
|
|
@@ -94,8 +71,10 @@ Do not use any data from the example response structure, only use the structure.
|
|
|
94
71
|
};
|
|
95
72
|
const generateExplainCodePrompt = (prompt) => {
|
|
96
73
|
return `${prompt}
|
|
97
|
-
|
|
98
|
-
|
|
74
|
+
|
|
75
|
+
## Task
|
|
76
|
+
|
|
77
|
+
Please briefly explain how the code works in this.`;
|
|
99
78
|
};
|
|
100
79
|
const generateCode = async (gpt, prompt, allSrcFiles, contextFiles, previousCode) => {
|
|
101
80
|
const codePrompt = generateCodePrompt(prompt, allSrcFiles, contextFiles, previousCode);
|
|
@@ -121,8 +100,33 @@ const displayGeneratedCode = (rawCodeCommand) => {
|
|
|
121
100
|
}
|
|
122
101
|
});
|
|
123
102
|
};
|
|
124
|
-
const
|
|
103
|
+
const saveGeneratedFiles = async (files, fileContents) => {
|
|
104
|
+
for (const file of files) {
|
|
105
|
+
if (fileContents[file]) {
|
|
106
|
+
const filePath = path_1.default.resolve(file);
|
|
107
|
+
await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
108
|
+
await fs_1.default.promises.writeFile(filePath, fileContents[file]);
|
|
109
|
+
console.log(`${file} has been saved.`);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.log(`File content not found for ${file}.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const updateContextFiles = async (contextFiles, files, fileContents) => {
|
|
117
|
+
for (const file of files) {
|
|
118
|
+
if (fileContents[file]) {
|
|
119
|
+
contextFiles[file] = fileContents[file];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contextFiles, options) => {
|
|
125
124
|
const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
|
|
125
|
+
if (options.save) {
|
|
126
|
+
await saveGeneratedFiles(files, fileContents);
|
|
127
|
+
await updateContextFiles(contextFiles, files, fileContents);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
126
130
|
const { action } = await inquirer_1.default.prompt([
|
|
127
131
|
{
|
|
128
132
|
type: 'list',
|
|
@@ -148,9 +152,25 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
|
|
|
148
152
|
message: 'How would you like to modify the output:',
|
|
149
153
|
},
|
|
150
154
|
]);
|
|
155
|
+
let includeMoreFiles = true;
|
|
156
|
+
while (includeMoreFiles) {
|
|
157
|
+
const { contextFile } = await inquirer_1.default.prompt([
|
|
158
|
+
{
|
|
159
|
+
type: 'input',
|
|
160
|
+
name: 'contextFile',
|
|
161
|
+
message: 'Enter the relative path of a file or directory you would like to include as context (or press enter to continue):',
|
|
162
|
+
},
|
|
163
|
+
]);
|
|
164
|
+
if (contextFile) {
|
|
165
|
+
contextFiles = await (0, command_utils_1.addFileOrDirectoryToContext)(contextFile, contextFiles, options);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
includeMoreFiles = false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
151
171
|
const newRawCodeCommand = await generateCode(gpt, newPrompt, allSrcFiles, contextFiles, rawCodeCommand);
|
|
152
172
|
displayGeneratedCode(newRawCodeCommand);
|
|
153
|
-
await handleUserAction(gpt, newRawCodeCommand, newPrompt, allSrcFiles, contextFiles);
|
|
173
|
+
await handleUserAction(gpt, newRawCodeCommand, newPrompt, allSrcFiles, contextFiles, options);
|
|
154
174
|
break;
|
|
155
175
|
case 'explain':
|
|
156
176
|
const explainPrompt = generateExplainCodePrompt(rawCodeCommand);
|
|
@@ -205,9 +225,10 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
|
|
|
205
225
|
]);
|
|
206
226
|
if (fileContents[fileToSave]) {
|
|
207
227
|
const filePath = path_1.default.resolve(fileToSave);
|
|
208
|
-
fs_1.default.
|
|
209
|
-
fs_1.default.
|
|
228
|
+
await fs_1.default.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
229
|
+
await fs_1.default.promises.writeFile(filePath, fileContents[fileToSave]);
|
|
210
230
|
console.log(`${fileToSave} has been saved.`);
|
|
231
|
+
await updateContextFiles(contextFiles, [fileToSave], fileContents);
|
|
211
232
|
}
|
|
212
233
|
else {
|
|
213
234
|
console.log('File content not found.');
|
|
@@ -224,80 +245,45 @@ const handleUserAction = async (gpt, rawCodeCommand, prompt, allSrcFiles, contex
|
|
|
224
245
|
}
|
|
225
246
|
break;
|
|
226
247
|
case 'saveAll':
|
|
227
|
-
files
|
|
228
|
-
|
|
229
|
-
const filePath = path_1.default.resolve(file);
|
|
230
|
-
fs_1.default.mkdirSync(path_1.default.dirname(filePath), { recursive: true });
|
|
231
|
-
fs_1.default.writeFileSync(filePath, fileContents[file]);
|
|
232
|
-
console.log(`${file} has been saved.`);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
console.log(`File content not found for ${file}.`);
|
|
236
|
-
}
|
|
237
|
-
});
|
|
248
|
+
await saveGeneratedFiles(files, fileContents);
|
|
249
|
+
await updateContextFiles(contextFiles, files, fileContents);
|
|
238
250
|
console.log('All files have been saved.');
|
|
239
251
|
break;
|
|
240
252
|
case 'done':
|
|
241
253
|
break;
|
|
242
254
|
}
|
|
243
255
|
};
|
|
244
|
-
const addFilesToContext = async (contextFiles, filePath) => {
|
|
245
|
-
const stats = fs_1.default.statSync(filePath);
|
|
246
|
-
if (stats.isDirectory()) {
|
|
247
|
-
const files = fs_1.default.readdirSync(filePath);
|
|
248
|
-
for (const file of files) {
|
|
249
|
-
await addFilesToContext(contextFiles, path_1.default.join(filePath, file));
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
else if (stats.isFile()) {
|
|
253
|
-
const content = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
254
|
-
contextFiles[filePath] = content;
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
256
|
const code = async (options) => {
|
|
258
257
|
let { prompt, files } = options;
|
|
259
258
|
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
260
259
|
const gpt = new cloving_gpt_1.default(options);
|
|
261
260
|
const allSrcFiles = await (0, config_utils_1.getAllFiles)(options, false);
|
|
262
|
-
|
|
261
|
+
let contextFiles = {};
|
|
263
262
|
try {
|
|
264
263
|
if (files) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
264
|
+
for (const file of files) {
|
|
265
|
+
const filePath = path_1.default.resolve(file);
|
|
266
|
+
if (await fs_1.default.promises.stat(filePath).then(stat => stat.isFile()).catch(() => false)) {
|
|
267
|
+
const content = await fs_1.default.promises.readFile(filePath, 'utf-8');
|
|
268
|
+
contextFiles[file] = content;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
268
271
|
}
|
|
269
272
|
else {
|
|
270
|
-
let firstFile = true;
|
|
271
273
|
let includeMoreFiles = true;
|
|
272
274
|
while (includeMoreFiles) {
|
|
273
|
-
const {
|
|
275
|
+
const { contextFile } = await inquirer_1.default.prompt([
|
|
274
276
|
{
|
|
275
|
-
type: '
|
|
276
|
-
name: '
|
|
277
|
-
message: `
|
|
278
|
-
default: false,
|
|
277
|
+
type: 'input',
|
|
278
|
+
name: 'contextFile',
|
|
279
|
+
message: `Enter the relative path of a file or directory you would like to include as context (or press enter to continue):`,
|
|
279
280
|
},
|
|
280
281
|
]);
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
type: 'input',
|
|
287
|
-
name: 'contextFile',
|
|
288
|
-
message: 'Enter the relative path of a file or directory you would like to include as context:',
|
|
289
|
-
},
|
|
290
|
-
]);
|
|
291
|
-
if (contextFile) {
|
|
292
|
-
const filePath = path_1.default.resolve(contextFile);
|
|
293
|
-
if (fs_1.default.existsSync(filePath)) {
|
|
294
|
-
await addFilesToContext(contextFiles, filePath);
|
|
295
|
-
console.log(`Added ${filePath} to context.`);
|
|
296
|
-
}
|
|
297
|
-
else {
|
|
298
|
-
console.log(`File or directory ${contextFile} does not exist.`);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
282
|
+
if (contextFile) {
|
|
283
|
+
contextFiles = await (0, command_utils_1.addFileOrDirectoryToContext)(contextFile, contextFiles, options);
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
includeMoreFiles = false;
|
|
301
287
|
}
|
|
302
288
|
}
|
|
303
289
|
}
|
|
@@ -311,20 +297,59 @@ const code = async (options) => {
|
|
|
311
297
|
]);
|
|
312
298
|
prompt = userPrompt;
|
|
313
299
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
300
|
+
let rawCodeCommand = await generateCode(gpt, prompt, allSrcFiles, contextFiles);
|
|
301
|
+
displayGeneratedCode(rawCodeCommand);
|
|
302
|
+
if (options.save) {
|
|
303
|
+
const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
|
|
304
|
+
await saveGeneratedFiles(files, fileContents);
|
|
305
|
+
await updateContextFiles(contextFiles, files, fileContents);
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
await handleUserAction(gpt, rawCodeCommand, prompt, allSrcFiles, contextFiles, options);
|
|
309
|
+
}
|
|
310
|
+
if (options.interactive) {
|
|
311
|
+
let continueInteractive = true;
|
|
312
|
+
while (continueInteractive) {
|
|
313
|
+
const { newPrompt } = await inquirer_1.default.prompt([
|
|
314
|
+
{
|
|
315
|
+
type: 'input',
|
|
316
|
+
name: 'newPrompt',
|
|
317
|
+
message: 'Revise the code (or press enter to finish):',
|
|
318
|
+
},
|
|
319
|
+
]);
|
|
320
|
+
if (newPrompt.trim() === '') {
|
|
321
|
+
continueInteractive = false;
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
let includeMoreFiles = true;
|
|
325
|
+
while (includeMoreFiles) {
|
|
326
|
+
const { contextFile } = await inquirer_1.default.prompt([
|
|
327
|
+
{
|
|
328
|
+
type: 'input',
|
|
329
|
+
name: 'contextFile',
|
|
330
|
+
message: 'Enter the relative path of a file or directory you would like to include as context (or press enter to continue):',
|
|
331
|
+
},
|
|
332
|
+
]);
|
|
333
|
+
if (contextFile) {
|
|
334
|
+
contextFiles = await (0, command_utils_1.addFileOrDirectoryToContext)(contextFile, contextFiles, options);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
includeMoreFiles = false;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
rawCodeCommand = await generateCode(gpt, newPrompt, allSrcFiles, contextFiles, rawCodeCommand);
|
|
341
|
+
displayGeneratedCode(rawCodeCommand);
|
|
342
|
+
if (options.save || options.interactive) {
|
|
343
|
+
const [files, fileContents] = (0, string_utils_1.extractFilesAndContent)(rawCodeCommand);
|
|
344
|
+
await saveGeneratedFiles(files, fileContents);
|
|
345
|
+
await updateContextFiles(contextFiles, files, fileContents);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
await handleUserAction(gpt, rawCodeCommand, newPrompt, allSrcFiles, contextFiles, options);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
323
351
|
}
|
|
324
352
|
}
|
|
325
|
-
const rawCodeCommand = await generateCode(gpt, prompt, allSrcFiles, contextFiles);
|
|
326
|
-
displayGeneratedCode(rawCodeCommand);
|
|
327
|
-
await handleUserAction(gpt, rawCodeCommand, prompt, allSrcFiles, contextFiles);
|
|
328
353
|
}
|
|
329
354
|
catch (error) {
|
|
330
355
|
console.error('Could not generate code', error);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
7
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
8
|
+
const copy_paste_1 = __importDefault(require("copy-paste"));
|
|
9
|
+
const command_utils_1 = require("../../utils/command_utils");
|
|
10
|
+
const config_utils_1 = require("../../utils/config_utils");
|
|
11
|
+
const generateContextPrompt = (files, contextFiles) => {
|
|
12
|
+
const specialFileContents = (0, command_utils_1.collectSpecialFileContents)();
|
|
13
|
+
const specialFiles = Object.keys(specialFileContents).map((file) => `### Contents of ${file}\n\n${JSON.stringify(specialFileContents[file], null, 2)}\n\n`).join('\n');
|
|
14
|
+
const contextFileContents = Object.keys(contextFiles).map((file) => `### Contents of ${file}\n\n${contextFiles[file]}\n\n`).join('\n');
|
|
15
|
+
return `### Description of App
|
|
16
|
+
|
|
17
|
+
${JSON.stringify((0, config_utils_1.getClovingConfig)(), null, 2)}
|
|
18
|
+
|
|
19
|
+
${specialFiles}
|
|
20
|
+
|
|
21
|
+
${contextFileContents}
|
|
22
|
+
|
|
23
|
+
### Directory structure
|
|
24
|
+
|
|
25
|
+
${files.join('\n')}`;
|
|
26
|
+
};
|
|
27
|
+
const context = async (options) => {
|
|
28
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
29
|
+
const allSrcFiles = await (0, config_utils_1.getAllFiles)(options, false);
|
|
30
|
+
let contextFiles = {};
|
|
31
|
+
try {
|
|
32
|
+
let includeMoreFiles = true;
|
|
33
|
+
while (includeMoreFiles) {
|
|
34
|
+
const { contextFile } = await inquirer_1.default.prompt([
|
|
35
|
+
{
|
|
36
|
+
type: 'input',
|
|
37
|
+
name: 'contextFile',
|
|
38
|
+
message: `Enter the relative path of a file or directory you would like to include as context (or press enter to continue):`,
|
|
39
|
+
},
|
|
40
|
+
]);
|
|
41
|
+
if (contextFile) {
|
|
42
|
+
contextFiles = await (0, command_utils_1.addFileOrDirectoryToContext)(contextFile, contextFiles, options);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
includeMoreFiles = false;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const contextPrompt = generateContextPrompt(allSrcFiles, contextFiles);
|
|
49
|
+
console.log('\nGenerated Context Prompt:');
|
|
50
|
+
console.log((0, cli_highlight_1.default)(contextPrompt, { language: 'markdown' }));
|
|
51
|
+
const { copyToClipboard } = await inquirer_1.default.prompt([
|
|
52
|
+
{
|
|
53
|
+
type: 'confirm',
|
|
54
|
+
name: 'copyToClipboard',
|
|
55
|
+
message: 'Do you want to copy the context prompt to your clipboard?',
|
|
56
|
+
default: true,
|
|
57
|
+
},
|
|
58
|
+
]);
|
|
59
|
+
if (copyToClipboard) {
|
|
60
|
+
copy_paste_1.default.copy(contextPrompt, () => {
|
|
61
|
+
console.log('Context prompt copied to clipboard');
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.error('Could not generate context', error);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
exports.default = context;
|
package/dist/commands/init.js
CHANGED
|
@@ -42,18 +42,15 @@ technologies used. This will provide better context for future Cloving requests.
|
|
|
42
42
|
return;
|
|
43
43
|
}
|
|
44
44
|
if (!(0, command_utils_1.checkForSpecialFiles)()) {
|
|
45
|
-
const {
|
|
45
|
+
const { technologies } = await inquirer_1.default.prompt([
|
|
46
46
|
{
|
|
47
|
-
type: '
|
|
48
|
-
name: '
|
|
49
|
-
message: 'No special files detected.
|
|
50
|
-
|
|
47
|
+
type: 'input',
|
|
48
|
+
name: 'technologies',
|
|
49
|
+
message: 'No special files detected. Please describe the main technologies used in your project:',
|
|
50
|
+
validate: (input) => input.trim().length > 0 || 'Please provide a description of the technologies used.',
|
|
51
51
|
},
|
|
52
52
|
]);
|
|
53
|
-
|
|
54
|
-
console.log('Operation aborted by the user.');
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
53
|
+
specialFileContents['description'] = technologies;
|
|
57
54
|
}
|
|
58
55
|
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `describe_${Date.now()}.tmp`);
|
|
59
56
|
try {
|
|
@@ -73,10 +70,6 @@ technologies used. This will provide better context for future Cloving requests.
|
|
|
73
70
|
}
|
|
74
71
|
});
|
|
75
72
|
const limitedFileList = filteredFileList.slice(0, 100);
|
|
76
|
-
if (specialFileNames.length === 0) {
|
|
77
|
-
console.error('No special files found.');
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
73
|
const projectDetails = {
|
|
81
74
|
files: limitedFileList,
|
|
82
75
|
specialFiles: specialFileContents
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ const models_1 = __importDefault(require("./commands/models"));
|
|
|
13
13
|
const shell_1 = __importDefault(require("./commands/generate/shell"));
|
|
14
14
|
const code_1 = __importDefault(require("./commands/generate/code"));
|
|
15
15
|
const commit_1 = __importDefault(require("./commands/generate/commit"));
|
|
16
|
+
const context_1 = __importDefault(require("./commands/generate/context"));
|
|
16
17
|
const unit_tests_1 = __importDefault(require("./commands/generate/unit_tests"));
|
|
17
18
|
const review_1 = __importDefault(require("./commands/generate/review"));
|
|
18
19
|
const init_2 = __importDefault(require("./commands/project/init"));
|
|
@@ -69,8 +70,10 @@ generate
|
|
|
69
70
|
.command('code')
|
|
70
71
|
.alias('c')
|
|
71
72
|
.description('Generate code based on a prompt')
|
|
73
|
+
.option('--save', 'Automatically save all files after generating the code')
|
|
74
|
+
.option('-i, --interactive', 'Auto-save generated code and then show a new prompt with existing context to revise the code further')
|
|
72
75
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
73
|
-
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5
|
|
76
|
+
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5:sonnet-20240620)')
|
|
74
77
|
.option('-p, --prompt <prompt>', 'Specify the prompt to use')
|
|
75
78
|
.option('-f, --files <filenames...>', 'Specify filenames of files with context to use for generating code')
|
|
76
79
|
.action(code_1.default);
|
|
@@ -80,6 +83,10 @@ generate
|
|
|
80
83
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
81
84
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
82
85
|
.action(commit_1.default);
|
|
86
|
+
generate
|
|
87
|
+
.command('context')
|
|
88
|
+
.description('Create a context string for generating code')
|
|
89
|
+
.action(context_1.default);
|
|
83
90
|
generate
|
|
84
91
|
.command('unit-tests')
|
|
85
92
|
.alias('u')
|
package/dist/package.json
CHANGED
|
@@ -3,40 +3,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.readFileContent = exports.fetchModels = exports.runCommand = exports.generateFileList = exports.checkForSpecialFiles = exports.collectSpecialFileContents = exports.SPECIAL_FILES = void 0;
|
|
6
|
+
exports.addFileOrDirectoryToContext = exports.readFileContent = exports.fetchModels = exports.runCommand = exports.generateFileList = exports.checkForSpecialFiles = exports.collectSpecialFileContents = exports.SPECIAL_FILES = void 0;
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const config_utils_1 = require("./config_utils");
|
|
9
11
|
exports.SPECIAL_FILES = [
|
|
10
|
-
'package.json',
|
|
11
|
-
'
|
|
12
|
-
'
|
|
13
|
-
'
|
|
14
|
-
'
|
|
15
|
-
'pom.xml',
|
|
16
|
-
'build.gradle',
|
|
17
|
-
'.csproj',
|
|
18
|
-
'packages.config',
|
|
19
|
-
'composer.json',
|
|
20
|
-
'CMakeLists.txt',
|
|
21
|
-
'conanfile.txt',
|
|
22
|
-
'conanfile.py',
|
|
23
|
-
'go.mod',
|
|
24
|
-
'Cargo.toml',
|
|
25
|
-
'Package.swift',
|
|
26
|
-
'build.gradle.kts',
|
|
27
|
-
'Podfile',
|
|
28
|
-
'Cartfile',
|
|
29
|
-
'cpanfile',
|
|
30
|
-
'DESCRIPTION',
|
|
31
|
-
'mix.exs',
|
|
32
|
-
'build.sbt',
|
|
33
|
-
'pubspec.yaml',
|
|
34
|
-
'stack.yaml',
|
|
35
|
-
'cabal.project',
|
|
36
|
-
'Project.toml',
|
|
37
|
-
'rockspec',
|
|
38
|
-
'rebar.config',
|
|
39
|
-
'project.clj'
|
|
12
|
+
'package.json', 'Gemfile', 'requirements.txt', 'Pipfile', 'pyproject.toml', 'pom.xml', 'build.gradle',
|
|
13
|
+
'.csproj', 'packages.config', 'composer.json', 'CMakeLists.txt', 'conanfile.txt', 'conanfile.py',
|
|
14
|
+
'go.mod', 'Cargo.toml', 'Package.swift', 'build.gradle.kts', 'Podfile', 'Cartfile', 'cpanfile',
|
|
15
|
+
'DESCRIPTION', 'mix.exs', 'build.sbt', 'pubspec.yaml', 'stack.yaml', 'cabal.project', 'Project.toml',
|
|
16
|
+
'rockspec', 'rebar.config', 'project.clj'
|
|
40
17
|
];
|
|
41
18
|
const collectSpecialFileContents = () => {
|
|
42
19
|
const specialFileContents = {};
|
|
@@ -54,9 +31,7 @@ const collectSpecialFileContents = () => {
|
|
|
54
31
|
return specialFileContents;
|
|
55
32
|
};
|
|
56
33
|
exports.collectSpecialFileContents = collectSpecialFileContents;
|
|
57
|
-
const checkForSpecialFiles = () =>
|
|
58
|
-
return exports.SPECIAL_FILES.some(file => fs_1.default.existsSync(file));
|
|
59
|
-
};
|
|
34
|
+
const checkForSpecialFiles = () => exports.SPECIAL_FILES.some(file => fs_1.default.existsSync(file));
|
|
60
35
|
exports.checkForSpecialFiles = checkForSpecialFiles;
|
|
61
36
|
const generateFileList = async () => {
|
|
62
37
|
try {
|
|
@@ -115,3 +90,28 @@ const readFileContent = (file) => {
|
|
|
115
90
|
}
|
|
116
91
|
};
|
|
117
92
|
exports.readFileContent = readFileContent;
|
|
93
|
+
const addFileOrDirectoryToContext = async (contextFile, contextFiles, options) => {
|
|
94
|
+
const filePath = path_1.default.resolve(contextFile);
|
|
95
|
+
if (await fs_1.default.promises.stat(filePath).then(stat => stat.isDirectory()).catch(() => false)) {
|
|
96
|
+
// Add all files in the specified directory
|
|
97
|
+
const files = await (0, config_utils_1.getAllFiles)(options, false);
|
|
98
|
+
for (const file of files) {
|
|
99
|
+
// if the file is in the same directory as the context file, add it to the context
|
|
100
|
+
if (path_1.default.dirname(file) === path_1.default.dirname(filePath)) {
|
|
101
|
+
const content = await fs_1.default.promises.readFile(file, 'utf-8');
|
|
102
|
+
contextFiles[path_1.default.relative(process.cwd(), file)] = content;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
console.log(`Added contents of ${contextFile} to context.`);
|
|
106
|
+
}
|
|
107
|
+
else if (await fs_1.default.promises.stat(filePath).then(stat => stat.isFile()).catch(() => false)) {
|
|
108
|
+
const content = await fs_1.default.promises.readFile(filePath, 'utf-8');
|
|
109
|
+
contextFiles[contextFile] = content;
|
|
110
|
+
console.log(`Added ${filePath} to context.`);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
console.log(`File or directory ${contextFile} does not exist.`);
|
|
114
|
+
}
|
|
115
|
+
return contextFiles;
|
|
116
|
+
};
|
|
117
|
+
exports.addFileOrDirectoryToContext = addFileOrDirectoryToContext;
|