cloving 0.3.4 → 0.3.5
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/cloving_gpt/adapters/claude.js +7 -5
- package/dist/cloving_gpt/adapters/gemini.js +14 -9
- package/dist/cloving_gpt/adapters/mistral.js +9 -7
- package/dist/cloving_gpt/adapters/ollama.js +7 -7
- package/dist/cloving_gpt/adapters/openai.js +9 -7
- package/dist/cloving_gpt/index.js +12 -7
- package/dist/commands/config.js +7 -7
- package/dist/commands/generate/context.js +10 -3
- package/dist/commands/generate/unit_tests.js +3 -261
- package/dist/commands/init.js +6 -6
- package/dist/commands/tokens.js +12 -4
- package/dist/index.js +3 -6
- package/dist/managers/ChatManager.js +77 -33
- package/dist/managers/CodeManager.js +19 -5
- package/dist/managers/CommitManager.js +6 -3
- package/dist/managers/ProxyManager.js +22 -7
- package/dist/managers/ReviewManager.js +26 -10
- package/dist/managers/ShellManager.js +5 -2
- package/dist/managers/UnitTestManager.js +243 -0
- package/dist/package.json +13 -8
- package/dist/utils/command_utils.js +86 -34
- package/dist/utils/config_utils.js +15 -5
- package/dist/utils/git_utils.js +7 -4
- package/dist/utils/string_utils.js +119 -12
- package/package.json +13 -8
|
@@ -0,0 +1,243 @@
|
|
|
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 fs_1 = require("fs");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
9
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
10
|
+
const git_utils_1 = require("../utils/git_utils");
|
|
11
|
+
const command_utils_1 = require("../utils/command_utils");
|
|
12
|
+
const config_utils_1 = require("../utils/config_utils");
|
|
13
|
+
const string_utils_1 = require("../utils/string_utils");
|
|
14
|
+
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
15
|
+
class UnitTestManager {
|
|
16
|
+
constructor(options) {
|
|
17
|
+
this.options = options;
|
|
18
|
+
this.chatHistory = [];
|
|
19
|
+
this.gpt = new cloving_gpt_1.default(options);
|
|
20
|
+
}
|
|
21
|
+
extractChangedFiles(gitDiff) {
|
|
22
|
+
const fileRegex = /diff --git a\/(.+?) b\/(.+?)\n/g;
|
|
23
|
+
const files = new Set();
|
|
24
|
+
let match;
|
|
25
|
+
while ((match = fileRegex.exec(gitDiff)) !== null) {
|
|
26
|
+
files.add(match[1]);
|
|
27
|
+
}
|
|
28
|
+
return Array.from(files);
|
|
29
|
+
}
|
|
30
|
+
generateUnitTestPrompt(files, srcFiles, testFiles, gitDiff) {
|
|
31
|
+
if (this.chatHistory.length === 0) {
|
|
32
|
+
const systemPrompt = `### Example of a well-structured response
|
|
33
|
+
|
|
34
|
+
# Unit Test Generation
|
|
35
|
+
|
|
36
|
+
## Files Overview
|
|
37
|
+
|
|
38
|
+
These are the files that are relevant for generating unit tests:
|
|
39
|
+
|
|
40
|
+
1. **app/models/foo.rb**
|
|
41
|
+
2. **app/views/baz/bar.html.erb**
|
|
42
|
+
|
|
43
|
+
## Relevant Test Files
|
|
44
|
+
|
|
45
|
+
1. **test/models/foo_test.rb**
|
|
46
|
+
2. **test/controllers/baz_controller_test.rb**
|
|
47
|
+
|
|
48
|
+
## Task
|
|
49
|
+
|
|
50
|
+
Generate unit tests for the files listed above. Always show filenames for the generated code.`;
|
|
51
|
+
this.chatHistory.push({ role: 'user', content: systemPrompt });
|
|
52
|
+
this.chatHistory.push({ role: 'assistant', content: 'What would you like to do?' });
|
|
53
|
+
}
|
|
54
|
+
const filesList = files.length > 0 ? files.join('\n') : 'No files provided';
|
|
55
|
+
const prompt = `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.
|
|
56
|
+
Also, list any test files that might be relevant to these files.
|
|
57
|
+
|
|
58
|
+
### List of Code Files
|
|
59
|
+
|
|
60
|
+
${filesList}
|
|
61
|
+
|
|
62
|
+
### List of All Source Files
|
|
63
|
+
|
|
64
|
+
${srcFiles}
|
|
65
|
+
|
|
66
|
+
### List of all test files
|
|
67
|
+
|
|
68
|
+
${testFiles}
|
|
69
|
+
|
|
70
|
+
${gitDiff ? '### Git Diff Content' : ''}
|
|
71
|
+
|
|
72
|
+
${gitDiff || ''}
|
|
73
|
+
|
|
74
|
+
## Example Output
|
|
75
|
+
|
|
76
|
+
Here are the files that are relevant:
|
|
77
|
+
|
|
78
|
+
\`\`\`plaintext
|
|
79
|
+
## files
|
|
80
|
+
|
|
81
|
+
app/models/foo.rb
|
|
82
|
+
app/views/baz/bar.html.erb
|
|
83
|
+
|
|
84
|
+
## relevant test files
|
|
85
|
+
|
|
86
|
+
test/models/foo_test.rb
|
|
87
|
+
test/controllers/baz_controller_test.rb
|
|
88
|
+
\`\`\`
|
|
89
|
+
|
|
90
|
+
### Prompt
|
|
91
|
+
|
|
92
|
+
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.
|
|
93
|
+
Also, list any test files that might be relevant to these files.`;
|
|
94
|
+
this.chatHistory.push({ role: 'user', content: prompt });
|
|
95
|
+
return prompt;
|
|
96
|
+
}
|
|
97
|
+
async handleUserAction(analysis, autoSave = false) {
|
|
98
|
+
const blocks = (0, string_utils_1.extractCurrentNewBlocks)(analysis);
|
|
99
|
+
if (autoSave) {
|
|
100
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const files = Array.from(new Set(blocks.map((block) => block.filePath)));
|
|
104
|
+
const action = await (0, prompts_1.select)({
|
|
105
|
+
message: 'What would you like to do?',
|
|
106
|
+
choices: [
|
|
107
|
+
{ name: 'Save a Unit Test File', value: 'save' },
|
|
108
|
+
{ name: 'Save All Unit Test Files', value: 'saveAll' },
|
|
109
|
+
{ name: 'Copy Entire Response to Clipboard', value: 'copyAll' },
|
|
110
|
+
{ name: 'Done', value: 'done' },
|
|
111
|
+
],
|
|
112
|
+
});
|
|
113
|
+
switch (action) {
|
|
114
|
+
case 'save':
|
|
115
|
+
let saveAnother = true;
|
|
116
|
+
while (saveAnother) {
|
|
117
|
+
const fileToSave = await (0, prompts_1.select)({
|
|
118
|
+
message: 'Which unit test file do you want to save?',
|
|
119
|
+
choices: files.map((file) => ({ name: file, value: file })),
|
|
120
|
+
});
|
|
121
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks.filter((block) => block.filePath === fileToSave));
|
|
122
|
+
saveAnother = await (0, prompts_1.confirm)({
|
|
123
|
+
message: 'Do you want to save another file?',
|
|
124
|
+
default: false,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
case 'saveAll':
|
|
129
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
130
|
+
console.log('All unit test files have been saved.');
|
|
131
|
+
break;
|
|
132
|
+
case 'copyAll':
|
|
133
|
+
process.nextTick(() => {
|
|
134
|
+
require('copy-paste').copy(analysis, () => {
|
|
135
|
+
console.log('Entire response copied to clipboard');
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
break;
|
|
139
|
+
case 'done':
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
async generateUnitTests() {
|
|
144
|
+
const { files, save } = this.options;
|
|
145
|
+
const allSrcFiles = await (0, config_utils_1.getAllFiles)(this.options, true);
|
|
146
|
+
const testingDirectory = (0, config_utils_1.getTestingDirectory)();
|
|
147
|
+
if (allSrcFiles.length === 0 || !testingDirectory) {
|
|
148
|
+
console.error('Could not find any source files to generate unit tests. Please run: cloving init. Then try again.');
|
|
149
|
+
process.exit(1);
|
|
150
|
+
}
|
|
151
|
+
const testFiles = (0, child_process_1.execFileSync)('find', [testingDirectory, '-type', 'f']).toString().trim();
|
|
152
|
+
let contextFiles;
|
|
153
|
+
if (files) {
|
|
154
|
+
console.log('Generating unit tests for the provided files...');
|
|
155
|
+
console.log('Gathering a list of files related to the changes...');
|
|
156
|
+
const prompt = this.generateUnitTestPrompt(files, allSrcFiles.join('\n'), testFiles);
|
|
157
|
+
contextFiles = await this.gpt.generateText({ prompt, messages: this.chatHistory });
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
console.log('Generating unit tests for the git diff between this branch and the default branch...');
|
|
161
|
+
console.log('Gathering a list of files related to the changes...');
|
|
162
|
+
const gitDiff = await (0, git_utils_1.getGitDiff)();
|
|
163
|
+
const changedFiles = this.extractChangedFiles(gitDiff);
|
|
164
|
+
const prompt = this.generateUnitTestPrompt(changedFiles, allSrcFiles.join('\n'), testFiles, gitDiff);
|
|
165
|
+
contextFiles = await this.gpt.generateText({ prompt, messages: this.chatHistory });
|
|
166
|
+
}
|
|
167
|
+
this.chatHistory.push({ role: 'assistant', content: contextFiles });
|
|
168
|
+
contextFiles = (0, string_utils_1.extractMarkdown)(contextFiles);
|
|
169
|
+
console.log(contextFiles);
|
|
170
|
+
console.log('\nBuilding the tests for these files...');
|
|
171
|
+
// Initialize variables
|
|
172
|
+
const lines = [];
|
|
173
|
+
const context = [];
|
|
174
|
+
// Read each line of the context files
|
|
175
|
+
contextFiles.split('\n').forEach((line) => {
|
|
176
|
+
if (line.trim()) {
|
|
177
|
+
lines.push(line.trim());
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
for (const codeFile of lines) {
|
|
181
|
+
if (await fs_1.promises
|
|
182
|
+
.stat(codeFile)
|
|
183
|
+
.then((stat) => stat.isFile())
|
|
184
|
+
.catch(() => false)) {
|
|
185
|
+
const fileContents = await fs_1.promises.readFile(codeFile, 'utf-8');
|
|
186
|
+
context.push(`### Contents of **${codeFile}\n\n${fileContents
|
|
187
|
+
.split('\n')
|
|
188
|
+
.map((line) => ` ${line}`)
|
|
189
|
+
.join('\n')}**\n\n`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Generate the message for unit test creation
|
|
193
|
+
let analysis = '';
|
|
194
|
+
if ((files || []).length > 0) {
|
|
195
|
+
const message = `Create unit tests for the List of Files. Always show filenames for the generated code.
|
|
196
|
+
|
|
197
|
+
## List of Files
|
|
198
|
+
${(files || []).join('\n')}
|
|
199
|
+
|
|
200
|
+
${command_utils_1.CODEGEN_INSTRUCTIONS}
|
|
201
|
+
|
|
202
|
+
## Context
|
|
203
|
+
|
|
204
|
+
${context.join('\n\n')}
|
|
205
|
+
|
|
206
|
+
## Prompt
|
|
207
|
+
|
|
208
|
+
Create unit tests for the List of Files. Always show filenames for the generated code.`;
|
|
209
|
+
// Get the model and analysis using ClovingGPT
|
|
210
|
+
this.chatHistory.push({ role: 'user', content: message });
|
|
211
|
+
analysis = await this.gpt.generateText({ prompt: message, messages: this.chatHistory });
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const message = `Create unit tests for the Code Diff. Always show filenames for the generated code.
|
|
215
|
+
|
|
216
|
+
## Code Diff
|
|
217
|
+
|
|
218
|
+
${await (0, git_utils_1.getGitDiff)()}
|
|
219
|
+
|
|
220
|
+
## Context
|
|
221
|
+
|
|
222
|
+
${context.join('\n\n')}
|
|
223
|
+
|
|
224
|
+
${command_utils_1.CODEGEN_INSTRUCTIONS}
|
|
225
|
+
|
|
226
|
+
## Prompt
|
|
227
|
+
|
|
228
|
+
Create unit tests for the Code Diff. Always show filenames for the generated code.`;
|
|
229
|
+
// Get the model and analysis using ClovingGPT
|
|
230
|
+
this.chatHistory.push({ role: 'user', content: message });
|
|
231
|
+
analysis = await this.gpt.generateText({ prompt: message, messages: this.chatHistory });
|
|
232
|
+
}
|
|
233
|
+
if (analysis) {
|
|
234
|
+
console.log((0, cli_highlight_1.default)(analysis));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
console.log('No unit tests generated.');
|
|
238
|
+
}
|
|
239
|
+
// Add the new user action handling
|
|
240
|
+
await this.handleUserAction(analysis, save);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
exports.default = UnitTestManager;
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloving",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
4
4
|
"packageManager": "yarn@1.22.22",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"watch": "tsc -w",
|
|
11
11
|
"check": "bash -c 'npx tsc --noEmit --skipLibCheck'",
|
|
12
12
|
"test": "bash -c jest",
|
|
13
|
-
"prepare": "husky"
|
|
13
|
+
"prepare": "husky",
|
|
14
|
+
"format": "prettier --write \"src/**/*.ts\""
|
|
14
15
|
},
|
|
15
16
|
"bin": "./dist/index.js",
|
|
16
17
|
"files": [
|
|
@@ -23,7 +24,8 @@
|
|
|
23
24
|
"description": "",
|
|
24
25
|
"lint-staged": {
|
|
25
26
|
"*.ts": [
|
|
26
|
-
"yarn run check"
|
|
27
|
+
"yarn run check",
|
|
28
|
+
"prettier --write"
|
|
27
29
|
]
|
|
28
30
|
},
|
|
29
31
|
"lint-prepush": {
|
|
@@ -31,7 +33,8 @@
|
|
|
31
33
|
"tasks": {
|
|
32
34
|
"*.ts": [
|
|
33
35
|
"yarn run check",
|
|
34
|
-
"yarn run test"
|
|
36
|
+
"yarn run test",
|
|
37
|
+
"yarn run format"
|
|
35
38
|
]
|
|
36
39
|
}
|
|
37
40
|
},
|
|
@@ -42,14 +45,14 @@
|
|
|
42
45
|
"colors": "^1.4.0",
|
|
43
46
|
"commander": "^12.1.0",
|
|
44
47
|
"copy-paste": "^1.5.3",
|
|
45
|
-
"eslint": "^
|
|
48
|
+
"eslint": "^8.57.0",
|
|
46
49
|
"eslint-config-prettier": "^9.1.0",
|
|
47
50
|
"eslint-config-raine": "^0.5.0",
|
|
48
51
|
"eslint-config-standard": "^17.1.0",
|
|
49
52
|
"eslint-plugin-import": "^2.29.1",
|
|
50
53
|
"eslint-plugin-jsdoc": "^50.1.0",
|
|
51
|
-
"eslint-plugin-n": "^
|
|
52
|
-
"eslint-plugin-promise": "^
|
|
54
|
+
"eslint-plugin-n": "^16.6.2",
|
|
55
|
+
"eslint-plugin-promise": "^6.6.0",
|
|
53
56
|
"express": "^4.19.2",
|
|
54
57
|
"ignore": "^5.3.2",
|
|
55
58
|
"ini": "^4.1.3",
|
|
@@ -70,12 +73,14 @@
|
|
|
70
73
|
"jest": "^29.7.0",
|
|
71
74
|
"lint-prepush": "^2.2.2",
|
|
72
75
|
"lint-staged": "^15.2.9",
|
|
76
|
+
"prettier": "^3.2.5",
|
|
73
77
|
"ts-jest": "^29.2.4",
|
|
74
78
|
"typescript": "^5.5.4"
|
|
75
79
|
},
|
|
76
80
|
"resolutions": {
|
|
77
81
|
"eslint": "8.57.0",
|
|
78
82
|
"eslint-plugin-n": "16.6.2",
|
|
79
|
-
"eslint-plugin-import": "2.29.1"
|
|
83
|
+
"eslint-plugin-import": "2.29.1",
|
|
84
|
+
"eslint-plugin-promise": "6.6.0"
|
|
80
85
|
}
|
|
81
86
|
}
|
|
@@ -3,7 +3,7 @@ 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.addFileOrDirectoryToContext = exports.readFileContent = exports.fetchModels = exports.runCommand = exports.generateFileList = exports.getAllFilesInDirectory = exports.checkForSpecialFiles = exports.collectSpecialFileContents = exports.generateShellPrompt = exports.generateCodegenPrompt = exports.getPackageVersion = exports.SPECIAL_FILES = void 0;
|
|
6
|
+
exports.addFileOrDirectoryToContext = exports.readFileContent = exports.fetchModels = exports.runCommand = exports.generateFileList = exports.getAllFilesInDirectory = exports.checkForSpecialFiles = exports.collectSpecialFileContents = exports.generateShellPrompt = exports.generateCodegenPrompt = exports.getPackageVersion = exports.SPECIAL_FILES = exports.CODEGEN_INSTRUCTIONS = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const child_process_1 = require("child_process");
|
|
@@ -11,31 +11,7 @@ const isbinaryfile_1 = require("isbinaryfile");
|
|
|
11
11
|
const colors_1 = __importDefault(require("colors"));
|
|
12
12
|
const path_2 = require("path");
|
|
13
13
|
const config_utils_1 = require("./config_utils");
|
|
14
|
-
exports.
|
|
15
|
-
'package.json', 'Gemfile', 'requirements.txt', 'Pipfile', 'pyproject.toml', 'pom.xml', 'build.gradle',
|
|
16
|
-
'.csproj', 'packages.config', 'composer.json', 'CMakeLists.txt', 'conanfile.txt', 'conanfile.py',
|
|
17
|
-
'go.mod', 'Cargo.toml', 'Package.swift', 'build.gradle.kts', 'Podfile', 'Cartfile', 'cpanfile',
|
|
18
|
-
'DESCRIPTION', 'mix.exs', 'build.sbt', 'pubspec.yaml', 'stack.yaml', 'cabal.project', 'Project.toml',
|
|
19
|
-
'rockspec', 'rebar.config', 'project.clj', 'tsconfig.json', '.eslintrc.js', '.eslintrc.json', '.eslintrc.yaml',
|
|
20
|
-
'.eslintrc.yml', '.eslintrc', '.prettierrc', '.prettierrc.js', '.prettierrc.json', '.prettierrc.yaml',
|
|
21
|
-
'.prettierrc.yml', '.prettierrc', '.stylelintrc', '.stylelintrc.json', '.stylelintrc.yaml', '.stylelintrc.yml',
|
|
22
|
-
'.stylelintrc', 'jest.config.js', 'jest.config.json', 'jest.config.ts', 'jest.config.cjs', 'jest.config.mjs',
|
|
23
|
-
'webpack.config.js', 'webpack.config.ts', 'webpack.config.cjs', 'webpack.config.mjs', 'webpack.config.common.js',
|
|
24
|
-
];
|
|
25
|
-
const getPackageVersion = () => {
|
|
26
|
-
const packagePath = (0, path_2.join)(__dirname, '..', 'package.json');
|
|
27
|
-
const packageJson = JSON.parse(fs_1.default.readFileSync(packagePath, 'utf8'));
|
|
28
|
-
return packageJson.version;
|
|
29
|
-
};
|
|
30
|
-
exports.getPackageVersion = getPackageVersion;
|
|
31
|
-
const renderAsString = (contextFile) => {
|
|
32
|
-
if (typeof contextFile === 'string') {
|
|
33
|
-
return contextFile;
|
|
34
|
-
}
|
|
35
|
-
return JSON.stringify(contextFile, null, 2);
|
|
36
|
-
};
|
|
37
|
-
const generateCodegenPrompt = (contextFilesContent) => {
|
|
38
|
-
const instructions = `## AI Code Generation Instructions
|
|
14
|
+
exports.CODEGEN_INSTRUCTIONS = `## AI Code Generation Instructions
|
|
39
15
|
|
|
40
16
|
### General Guidelines
|
|
41
17
|
|
|
@@ -68,11 +44,87 @@ const generateCodegenPrompt = (contextFilesContent) => {
|
|
|
68
44
|
>>>>>>> NEW
|
|
69
45
|
7. **Close the block with three backticks.**
|
|
70
46
|
\`\`\``;
|
|
47
|
+
exports.SPECIAL_FILES = [
|
|
48
|
+
'package.json',
|
|
49
|
+
'Gemfile',
|
|
50
|
+
'requirements.txt',
|
|
51
|
+
'Pipfile',
|
|
52
|
+
'pyproject.toml',
|
|
53
|
+
'pom.xml',
|
|
54
|
+
'build.gradle',
|
|
55
|
+
'.csproj',
|
|
56
|
+
'packages.config',
|
|
57
|
+
'composer.json',
|
|
58
|
+
'CMakeLists.txt',
|
|
59
|
+
'conanfile.txt',
|
|
60
|
+
'conanfile.py',
|
|
61
|
+
'go.mod',
|
|
62
|
+
'Cargo.toml',
|
|
63
|
+
'Package.swift',
|
|
64
|
+
'build.gradle.kts',
|
|
65
|
+
'Podfile',
|
|
66
|
+
'Cartfile',
|
|
67
|
+
'cpanfile',
|
|
68
|
+
'DESCRIPTION',
|
|
69
|
+
'mix.exs',
|
|
70
|
+
'build.sbt',
|
|
71
|
+
'pubspec.yaml',
|
|
72
|
+
'stack.yaml',
|
|
73
|
+
'cabal.project',
|
|
74
|
+
'Project.toml',
|
|
75
|
+
'rockspec',
|
|
76
|
+
'rebar.config',
|
|
77
|
+
'project.clj',
|
|
78
|
+
'tsconfig.json',
|
|
79
|
+
'.eslintrc.js',
|
|
80
|
+
'.eslintrc.json',
|
|
81
|
+
'.eslintrc.yaml',
|
|
82
|
+
'.eslintrc.yml',
|
|
83
|
+
'.eslintrc',
|
|
84
|
+
'.prettierrc',
|
|
85
|
+
'.prettierrc.js',
|
|
86
|
+
'.prettierrc.json',
|
|
87
|
+
'.prettierrc.yaml',
|
|
88
|
+
'.prettierrc.yml',
|
|
89
|
+
'.prettierrc',
|
|
90
|
+
'.stylelintrc',
|
|
91
|
+
'.stylelintrc.json',
|
|
92
|
+
'.stylelintrc.yaml',
|
|
93
|
+
'.stylelintrc.yml',
|
|
94
|
+
'.stylelintrc',
|
|
95
|
+
'jest.config.js',
|
|
96
|
+
'jest.config.json',
|
|
97
|
+
'jest.config.ts',
|
|
98
|
+
'jest.config.cjs',
|
|
99
|
+
'jest.config.mjs',
|
|
100
|
+
'webpack.config.js',
|
|
101
|
+
'webpack.config.ts',
|
|
102
|
+
'webpack.config.cjs',
|
|
103
|
+
'webpack.config.mjs',
|
|
104
|
+
'webpack.config.common.js',
|
|
105
|
+
];
|
|
106
|
+
const getPackageVersion = () => {
|
|
107
|
+
const packagePath = (0, path_2.join)(__dirname, '..', 'package.json');
|
|
108
|
+
const packageJson = JSON.parse(fs_1.default.readFileSync(packagePath, 'utf8'));
|
|
109
|
+
return packageJson.version;
|
|
110
|
+
};
|
|
111
|
+
exports.getPackageVersion = getPackageVersion;
|
|
112
|
+
const renderAsString = (contextFile) => {
|
|
113
|
+
if (typeof contextFile === 'string') {
|
|
114
|
+
return contextFile;
|
|
115
|
+
}
|
|
116
|
+
return JSON.stringify(contextFile, null, 2);
|
|
117
|
+
};
|
|
118
|
+
const generateCodegenPrompt = (contextFilesContent) => {
|
|
71
119
|
const specialFileContents = (0, exports.collectSpecialFileContents)();
|
|
72
120
|
// detect if specialFileContents[file] is a string or an object
|
|
73
|
-
const specialFiles = Object.keys(specialFileContents)
|
|
74
|
-
|
|
75
|
-
|
|
121
|
+
const specialFiles = Object.keys(specialFileContents)
|
|
122
|
+
.map((file) => `### Contents of **${file}**\n\n\`\`\`\n${renderAsString(specialFileContents[file])}\n\`\`\`\n\n`)
|
|
123
|
+
.join('\n');
|
|
124
|
+
const contextFileContents = Object.keys(contextFilesContent)
|
|
125
|
+
.map((file) => `### Contents of **${file}**\n\n\`\`\`\n${contextFilesContent[file]}\n\`\`\`\n\n`)
|
|
126
|
+
.join('\n');
|
|
127
|
+
const prompt = `${exports.CODEGEN_INSTRUCTIONS}
|
|
76
128
|
|
|
77
129
|
## Description of App
|
|
78
130
|
|
|
@@ -92,7 +144,7 @@ ${contextFileContents.length > 0 ? contextFileContents : 'No context files provi
|
|
|
92
144
|
|
|
93
145
|
${Object.keys(contextFilesContent).join('\n')}
|
|
94
146
|
|
|
95
|
-
${
|
|
147
|
+
${exports.CODEGEN_INSTRUCTIONS}
|
|
96
148
|
|
|
97
149
|
### Example 1: Changing a Variable
|
|
98
150
|
|
|
@@ -211,7 +263,7 @@ const collectSpecialFileContents = () => {
|
|
|
211
263
|
return specialFileContents;
|
|
212
264
|
};
|
|
213
265
|
exports.collectSpecialFileContents = collectSpecialFileContents;
|
|
214
|
-
const checkForSpecialFiles = () => exports.SPECIAL_FILES.some(file => fs_1.default.existsSync(file));
|
|
266
|
+
const checkForSpecialFiles = () => exports.SPECIAL_FILES.some((file) => fs_1.default.existsSync(file));
|
|
215
267
|
exports.checkForSpecialFiles = checkForSpecialFiles;
|
|
216
268
|
const getAllFilesInDirectory = async (dir) => {
|
|
217
269
|
const subdirs = await fs_1.default.promises.readdir(dir);
|
|
@@ -236,10 +288,10 @@ const generateFileList = async () => {
|
|
|
236
288
|
try {
|
|
237
289
|
const lsOutput = await (0, exports.runCommand)('ls', []);
|
|
238
290
|
const findOutput = await (0, exports.runCommand)('find', ['.']);
|
|
239
|
-
const cleanedFindOutput = findOutput.map(file => file.startsWith('./') ? file.slice(2) : file);
|
|
291
|
+
const cleanedFindOutput = findOutput.map((file) => file.startsWith('./') ? file.slice(2) : file);
|
|
240
292
|
const files = [...lsOutput, ...cleanedFindOutput];
|
|
241
293
|
const uniqueFiles = Array.from(new Set(files));
|
|
242
|
-
return uniqueFiles.filter(file => file && !file.includes('.git') && !file.includes('node_modules') && !file.includes('tmp'));
|
|
294
|
+
return uniqueFiles.filter((file) => file && !file.includes('.git') && !file.includes('node_modules') && !file.includes('tmp'));
|
|
243
295
|
}
|
|
244
296
|
catch (error) {
|
|
245
297
|
console.error('Error generating file list:', error.message);
|
|
@@ -324,7 +376,7 @@ const addFileOrDirectoryToContext = async (contextFile, contextFiles, options) =
|
|
|
324
376
|
}
|
|
325
377
|
}
|
|
326
378
|
catch (error) {
|
|
327
|
-
console.error(`${colors_1.default.bold('Error')}: File or directory "${contextFile}" does not exist`);
|
|
379
|
+
console.error(colors_1.default.red(`${colors_1.default.bold('Error')}: File or directory "${contextFile}" does not exist`));
|
|
328
380
|
process.exit(1);
|
|
329
381
|
}
|
|
330
382
|
return contextFiles;
|
|
@@ -27,7 +27,8 @@ const getConfig = (options) => {
|
|
|
27
27
|
for (const model in config.models[provider]) {
|
|
28
28
|
if (config.models[provider][model].temperature !== undefined) {
|
|
29
29
|
const temp = config.models[provider][model].temperature;
|
|
30
|
-
config.models[provider][model].temperature =
|
|
30
|
+
config.models[provider][model].temperature =
|
|
31
|
+
typeof temp === 'string' ? parseFloat(temp) : temp;
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -50,10 +51,10 @@ const getConfig = (options) => {
|
|
|
50
51
|
silent: options.silent || false,
|
|
51
52
|
trust: false,
|
|
52
53
|
temperature: options.temperature || 0.2,
|
|
53
|
-
}
|
|
54
|
-
}
|
|
54
|
+
},
|
|
55
|
+
},
|
|
55
56
|
},
|
|
56
|
-
globalSilent: options.silent || false
|
|
57
|
+
globalSilent: options.silent || false,
|
|
57
58
|
};
|
|
58
59
|
}
|
|
59
60
|
else {
|
|
@@ -164,7 +165,16 @@ const getAllFiles = async (options, forTesting) => {
|
|
|
164
165
|
// Collect srcFiles for each language with specified directory and extension
|
|
165
166
|
for (const language of config.languages) {
|
|
166
167
|
if (language.directory && language.extension) {
|
|
167
|
-
const srcFiles = (0, child_process_1.execFileSync)('find', [
|
|
168
|
+
const srcFiles = (0, child_process_1.execFileSync)('find', [
|
|
169
|
+
language.directory,
|
|
170
|
+
'-type',
|
|
171
|
+
'f',
|
|
172
|
+
'-name',
|
|
173
|
+
`*${language.extension}`,
|
|
174
|
+
])
|
|
175
|
+
.toString()
|
|
176
|
+
.trim()
|
|
177
|
+
.split('\n');
|
|
168
178
|
allSrcFiles = allSrcFiles.concat(srcFiles);
|
|
169
179
|
}
|
|
170
180
|
}
|
package/dist/utils/git_utils.js
CHANGED
|
@@ -9,9 +9,9 @@ const readline_1 = __importDefault(require("readline"));
|
|
|
9
9
|
const askQuestion = (question) => {
|
|
10
10
|
const rl = readline_1.default.createInterface({
|
|
11
11
|
input: process.stdin,
|
|
12
|
-
output: process.stdout
|
|
12
|
+
output: process.stdout,
|
|
13
13
|
});
|
|
14
|
-
return new Promise(resolve => rl.question(question, answer => {
|
|
14
|
+
return new Promise((resolve) => rl.question(question, (answer) => {
|
|
15
15
|
rl.close();
|
|
16
16
|
resolve(answer);
|
|
17
17
|
}));
|
|
@@ -21,7 +21,10 @@ const getGitDiff = async () => {
|
|
|
21
21
|
const defaultBranchName = await (0, exports.getDefaultBranchName)();
|
|
22
22
|
const gitDiff = (0, child_process_1.execSync)(`git diff ${defaultBranchName} --`).toString().trim();
|
|
23
23
|
// Indent each line by four spaces
|
|
24
|
-
const indentedDiff = gitDiff
|
|
24
|
+
const indentedDiff = gitDiff
|
|
25
|
+
.split('\n')
|
|
26
|
+
.map((line) => ` ${line}`)
|
|
27
|
+
.join('\n');
|
|
25
28
|
return indentedDiff;
|
|
26
29
|
}
|
|
27
30
|
catch (error) {
|
|
@@ -31,7 +34,7 @@ const getGitDiff = async () => {
|
|
|
31
34
|
};
|
|
32
35
|
exports.getGitDiff = getGitDiff;
|
|
33
36
|
const getDefaultBranchName = async () => {
|
|
34
|
-
let defaultBranchName = (0, child_process_1.execSync)(
|
|
37
|
+
let defaultBranchName = (0, child_process_1.execSync)("git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'")
|
|
35
38
|
.toString()
|
|
36
39
|
.trim();
|
|
37
40
|
if (defaultBranchName === '') {
|