cloving 0.3.4 → 0.3.6
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/README.md +8 -2
- 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 +13 -8
- package/dist/commands/config.js +9 -9
- package/dist/commands/generate/context.js +13 -6
- package/dist/commands/generate/unit_tests.js +3 -261
- package/dist/commands/init.js +3 -218
- package/dist/commands/tokens.js +14 -6
- package/dist/index.js +5 -8
- package/dist/managers/BlockManager.js +121 -0
- package/dist/managers/ChatManager.js +202 -42
- package/dist/managers/ChunkManager.js +12 -0
- package/dist/managers/CodeManager.js +24 -10
- package/dist/managers/CommitManager.js +6 -3
- package/dist/managers/InitManager.js +216 -0
- package/dist/managers/ProxyManager.js +33 -10
- package/dist/managers/ReviewManager.js +40 -12
- package/dist/managers/ShellManager.js +7 -4
- 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/prompt_utils.js +515 -0
- package/dist/utils/string_utils.js +119 -12
- package/package.json +13 -8
|
@@ -3,267 +3,9 @@ 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
|
-
const
|
|
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 config_utils_1 = require("../../utils/config_utils");
|
|
12
|
-
const string_utils_1 = require("../../utils/string_utils");
|
|
13
|
-
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
14
|
-
const extractChangedFiles = (gitDiff) => {
|
|
15
|
-
const fileRegex = /diff --git a\/(.+?) b\/(.+?)\n/g;
|
|
16
|
-
const files = new Set();
|
|
17
|
-
let match;
|
|
18
|
-
while ((match = fileRegex.exec(gitDiff)) !== null) {
|
|
19
|
-
files.add(match[1]);
|
|
20
|
-
}
|
|
21
|
-
return Array.from(files);
|
|
22
|
-
};
|
|
23
|
-
const generatePrompt = (files, srcFiles, testFiles, gitDiff) => {
|
|
24
|
-
const filesList = files.length > 0 ? files.join('\n') : 'No files provided';
|
|
25
|
-
return `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.
|
|
26
|
-
Also, list any test files that might be relevant to these files.
|
|
27
|
-
|
|
28
|
-
### List of Code Files
|
|
29
|
-
|
|
30
|
-
${filesList}
|
|
31
|
-
|
|
32
|
-
### List of All Source Files
|
|
33
|
-
|
|
34
|
-
${srcFiles}
|
|
35
|
-
|
|
36
|
-
### List of all test files
|
|
37
|
-
|
|
38
|
-
${testFiles}
|
|
39
|
-
|
|
40
|
-
${gitDiff ? '### Git Diff Content' : ''}
|
|
41
|
-
|
|
42
|
-
${gitDiff || ''}
|
|
43
|
-
|
|
44
|
-
## Example Output
|
|
45
|
-
|
|
46
|
-
Here are the files that are relevant:
|
|
47
|
-
|
|
48
|
-
\`\`\`plaintext
|
|
49
|
-
## files
|
|
50
|
-
|
|
51
|
-
app/models/foo.rb
|
|
52
|
-
app/views/baz/bar.html.erb
|
|
53
|
-
|
|
54
|
-
## relevant test files
|
|
55
|
-
|
|
56
|
-
test/models/foo_test.rb
|
|
57
|
-
test/controllers/baz_controller_test.rb
|
|
58
|
-
\`\`\`
|
|
59
|
-
|
|
60
|
-
### Prompt
|
|
61
|
-
|
|
62
|
-
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.
|
|
63
|
-
Also, list any test files that might be relevant to these files.`;
|
|
64
|
-
};
|
|
65
|
-
const handleUserAction = async (analysis, autoSave = false) => {
|
|
66
|
-
const blocks = (0, string_utils_1.extractCurrentNewBlocks)(analysis);
|
|
67
|
-
if (autoSave) {
|
|
68
|
-
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
69
|
-
console.log('All unit test files have been saved.');
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const files = Array.from(new Set(blocks.map(block => block.filePath)));
|
|
73
|
-
const action = await (0, prompts_1.select)({
|
|
74
|
-
message: 'What would you like to do?',
|
|
75
|
-
choices: [
|
|
76
|
-
{ name: 'Save a Unit Test File', value: 'save' },
|
|
77
|
-
{ name: 'Save All Unit Test Files', value: 'saveAll' },
|
|
78
|
-
{ name: 'Copy Entire Response to Clipboard', value: 'copyAll' },
|
|
79
|
-
{ name: 'Done', value: 'done' },
|
|
80
|
-
],
|
|
81
|
-
});
|
|
82
|
-
switch (action) {
|
|
83
|
-
case 'save':
|
|
84
|
-
let saveAnother = true;
|
|
85
|
-
while (saveAnother) {
|
|
86
|
-
const fileToSave = await (0, prompts_1.select)({
|
|
87
|
-
message: 'Which unit test file do you want to save?',
|
|
88
|
-
choices: files.map(file => ({ name: file, value: file })),
|
|
89
|
-
});
|
|
90
|
-
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks.filter(block => block.filePath === fileToSave));
|
|
91
|
-
saveAnother = await (0, prompts_1.confirm)({
|
|
92
|
-
message: 'Do you want to save another file?',
|
|
93
|
-
default: false,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
break;
|
|
97
|
-
case 'saveAll':
|
|
98
|
-
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
99
|
-
console.log('All unit test files have been saved.');
|
|
100
|
-
break;
|
|
101
|
-
case 'copyAll':
|
|
102
|
-
process.nextTick(() => {
|
|
103
|
-
require('copy-paste').copy(analysis, () => {
|
|
104
|
-
console.log('Entire response copied to clipboard');
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
break;
|
|
108
|
-
case 'done':
|
|
109
|
-
break;
|
|
110
|
-
}
|
|
111
|
-
};
|
|
6
|
+
const UnitTestManager_1 = __importDefault(require("../../managers/UnitTestManager"));
|
|
112
7
|
const unitTests = async (options) => {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
const allSrcFiles = await (0, config_utils_1.getAllFiles)(options, true);
|
|
116
|
-
const testingDirectory = (0, config_utils_1.getTestingDirectory)();
|
|
117
|
-
if (allSrcFiles.length === 0 || !testingDirectory) {
|
|
118
|
-
console.error('Could not find any source files to generate unit tests. Please run: cloving init. Then try again.');
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
const testFiles = (0, child_process_1.execFileSync)('find', [testingDirectory, '-type', 'f']).toString().trim();
|
|
122
|
-
let contextFiles;
|
|
123
|
-
if (files) {
|
|
124
|
-
console.log('Generating unit tests for the provided files...');
|
|
125
|
-
console.log('Gathering a list of files related to the changes...');
|
|
126
|
-
const prompt = generatePrompt(files, allSrcFiles.join('\n'), testFiles);
|
|
127
|
-
contextFiles = await gpt.generateText({ prompt });
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
console.log('Generating unit tests for the git diff between this branch and the default branch...');
|
|
131
|
-
console.log('Gathering a list of files related to the changes...');
|
|
132
|
-
const gitDiff = await (0, git_utils_1.getGitDiff)();
|
|
133
|
-
const changedFiles = extractChangedFiles(gitDiff);
|
|
134
|
-
const prompt = generatePrompt(changedFiles, allSrcFiles.join('\n'), testFiles, gitDiff);
|
|
135
|
-
contextFiles = await gpt.generateText({ prompt });
|
|
136
|
-
}
|
|
137
|
-
contextFiles = (0, string_utils_1.extractMarkdown)(contextFiles);
|
|
138
|
-
console.log(contextFiles);
|
|
139
|
-
console.log('\nBuilding the tests for these files...');
|
|
140
|
-
// Initialize variables
|
|
141
|
-
const lines = [];
|
|
142
|
-
const context = [];
|
|
143
|
-
// Read each line of the context files
|
|
144
|
-
contextFiles.split('\n').forEach((line) => {
|
|
145
|
-
if (line.trim()) {
|
|
146
|
-
lines.push(line.trim());
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
for (const codeFile of lines) {
|
|
150
|
-
if (await fs_1.promises.stat(codeFile).then(stat => stat.isFile()).catch(() => false)) {
|
|
151
|
-
const fileContents = await fs_1.promises.readFile(codeFile, 'utf-8');
|
|
152
|
-
context.push(`### Contents of **${codeFile}\n\n${fileContents.split('\n').map(line => ` ${line}`).join('\n')}**\n\n`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Generate the message for unit test creation
|
|
156
|
-
let analysis = '';
|
|
157
|
-
if ((files || []).length > 0) {
|
|
158
|
-
const message = `Create unit tests for the List of Files. Always show filenames for the generated code.
|
|
159
|
-
|
|
160
|
-
## List of Files
|
|
161
|
-
${(files || []).join('\n')}
|
|
162
|
-
|
|
163
|
-
## Example Response Structure
|
|
164
|
-
|
|
165
|
-
Here are the unit tests for the provided list of files:
|
|
166
|
-
|
|
167
|
-
1. **tests/utils/model_utils.test.ts**
|
|
168
|
-
|
|
169
|
-
\`\`\`typescript
|
|
170
|
-
import { getModel } from '../../src/utils/model_utils'
|
|
171
|
-
|
|
172
|
-
describe('modelUtils', () => {
|
|
173
|
-
const originalEnv = process.env
|
|
174
|
-
|
|
175
|
-
beforeEach(() => {
|
|
176
|
-
jest.resetModules()
|
|
177
|
-
process.env = { ...originalEnv }
|
|
178
|
-
})
|
|
179
|
-
|
|
180
|
-
afterAll(() => {
|
|
181
|
-
process.env = originalEnv
|
|
182
|
-
})
|
|
183
|
-
|
|
184
|
-
test('getModel should return default model when CLOVING_MODEL is not set', () => {
|
|
185
|
-
delete process.env.CLOVING_MODEL
|
|
186
|
-
const result = getModel()
|
|
187
|
-
expect(result).toBe('claude:claude-3-5-sonnet-20240620')
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
test('getModel should return CLOVING_MODEL when it is set', () => {
|
|
191
|
-
process.env.CLOVING_MODEL = 'openai:gpt-4'
|
|
192
|
-
const result = getModel()
|
|
193
|
-
expect(result).toBe('openai:gpt-4')
|
|
194
|
-
})
|
|
195
|
-
})
|
|
196
|
-
\`\`\`
|
|
197
|
-
|
|
198
|
-
## Context
|
|
199
|
-
|
|
200
|
-
${context.join('\n\n')}
|
|
201
|
-
|
|
202
|
-
## Prompt
|
|
203
|
-
|
|
204
|
-
Create unit tests for the List of Files. Always show filenames for the generated code.`;
|
|
205
|
-
// Get the model and analysis using ClovingGPT
|
|
206
|
-
analysis = await gpt.generateText({ prompt: message });
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
const message = `Create unit tests for the Code Diff. Always show filenames for the generated code.
|
|
210
|
-
|
|
211
|
-
## Code Diff
|
|
212
|
-
|
|
213
|
-
${await (0, git_utils_1.getGitDiff)()}
|
|
214
|
-
|
|
215
|
-
## Context
|
|
216
|
-
|
|
217
|
-
${context.join('\n\n')}
|
|
218
|
-
|
|
219
|
-
## Example Response Structure
|
|
220
|
-
|
|
221
|
-
Here are the unit tests for the code diff:
|
|
222
|
-
|
|
223
|
-
1. **tests/utils/model_utils.test.ts**
|
|
224
|
-
|
|
225
|
-
\`\`\`typescript
|
|
226
|
-
import { getModel } from '../../src/utils/model_utils'
|
|
227
|
-
|
|
228
|
-
describe('modelUtils', () => {
|
|
229
|
-
const originalEnv = process.env
|
|
230
|
-
|
|
231
|
-
beforeEach(() => {
|
|
232
|
-
jest.resetModules()
|
|
233
|
-
process.env = { ...originalEnv }
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
afterAll(() => {
|
|
237
|
-
process.env = originalEnv
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
test('getModel should return default model when CLOVING_MODEL is not set', () => {
|
|
241
|
-
delete process.env.CLOVING_MODEL
|
|
242
|
-
const result = getModel()
|
|
243
|
-
expect(result).toBe('claude:claude-3-5-sonnet-20240620')
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
test('getModel should return CLOVING_MODEL when it is set', () => {
|
|
247
|
-
process.env.CLOVING_MODEL = 'openai:gpt-4'
|
|
248
|
-
const result = getModel()
|
|
249
|
-
expect(result).toBe('openai:gpt-4')
|
|
250
|
-
})
|
|
251
|
-
})
|
|
252
|
-
\`\`\`
|
|
253
|
-
|
|
254
|
-
## Prompt
|
|
255
|
-
|
|
256
|
-
Create unit tests for the Code Diff. Always show filenames for the generated code.`;
|
|
257
|
-
// Get the model and analysis using ClovingGPT
|
|
258
|
-
analysis = await gpt.generateText({ prompt: message });
|
|
259
|
-
}
|
|
260
|
-
if (analysis) {
|
|
261
|
-
console.log((0, cli_highlight_1.default)(analysis));
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
console.log('No unit tests generated.');
|
|
265
|
-
}
|
|
266
|
-
// Add the new user action handling
|
|
267
|
-
await handleUserAction(analysis, save);
|
|
8
|
+
const unitTestManager = new UnitTestManager_1.default(options);
|
|
9
|
+
await unitTestManager.generateUnitTests();
|
|
268
10
|
};
|
|
269
11
|
exports.default = unitTests;
|
package/dist/commands/init.js
CHANGED
|
@@ -4,225 +4,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.init = void 0;
|
|
7
|
-
const
|
|
8
|
-
const os_1 = __importDefault(require("os"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const prompts_1 = require("@inquirer/prompts");
|
|
11
|
-
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
12
|
-
const ignore_1 = __importDefault(require("ignore"));
|
|
13
|
-
const string_utils_1 = require("../utils/string_utils");
|
|
14
|
-
const config_utils_1 = require("../utils/config_utils");
|
|
15
|
-
const command_utils_1 = require("../utils/command_utils");
|
|
16
|
-
// Main function for the describe command
|
|
7
|
+
const InitManager_1 = __importDefault(require("../managers/InitManager"));
|
|
17
8
|
const init = async (options) => {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const specialFileContents = (0, command_utils_1.collectSpecialFileContents)();
|
|
21
|
-
const specialFileNames = Object.keys(specialFileContents).map(file => ' - ' + file);
|
|
22
|
-
// Initialize chat history
|
|
23
|
-
const chatHistory = [
|
|
24
|
-
{
|
|
25
|
-
role: 'system',
|
|
26
|
-
content: `You are an AI assistant helping to initialize a project by analyzing its structure and technologies.
|
|
27
|
-
|
|
28
|
-
Please return JSON-formatted metadata about the project, including:
|
|
29
|
-
|
|
30
|
-
- The programming language(s) used
|
|
31
|
-
- The detected framework(s) (if any)
|
|
32
|
-
- The version of the language(s)
|
|
33
|
-
|
|
34
|
-
Here is a typescript interface for the expected response:
|
|
35
|
-
|
|
36
|
-
interface LanguageConfig {
|
|
37
|
-
name: string
|
|
38
|
-
version?: string
|
|
39
|
-
primary?: boolean
|
|
40
|
-
directory: string
|
|
41
|
-
extension: string
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
interface FrameworkConfig {
|
|
45
|
-
name: string
|
|
46
|
-
type: string
|
|
47
|
-
version?: string
|
|
48
|
-
primary?: boolean
|
|
49
|
-
directory?: string
|
|
50
|
-
extension?: string
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
interface TestingFrameworkConfig {
|
|
54
|
-
name: string
|
|
55
|
-
type: string
|
|
56
|
-
version?: string
|
|
57
|
-
directory?: string
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
interface BuildToolConfig {
|
|
61
|
-
name: string
|
|
62
|
-
type: string
|
|
63
|
-
version?: string
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
interface LinterConfig {
|
|
67
|
-
name: string
|
|
68
|
-
version?: string
|
|
69
|
-
type?: string
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
interface DatabaseConfig {
|
|
73
|
-
name: string
|
|
74
|
-
primary?: boolean
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface ClovingfileConfig {
|
|
78
|
-
languages: LanguageConfig[]
|
|
79
|
-
frameworks: FrameworkConfig[]
|
|
80
|
-
testingFrameworks?: TestingFrameworkConfig[]
|
|
81
|
-
buildTools: BuildToolConfig[]
|
|
82
|
-
packageManager: string
|
|
83
|
-
linters: LinterConfig[]
|
|
84
|
-
databases?: DatabaseConfig[]
|
|
85
|
-
projectType: string
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
Here is an example response:
|
|
89
|
-
|
|
90
|
-
{
|
|
91
|
-
"languages": [
|
|
92
|
-
{
|
|
93
|
-
"name": "TypeScript",
|
|
94
|
-
"version": "~> 5.5.3"
|
|
95
|
-
"primary": true,
|
|
96
|
-
"directory": "src",
|
|
97
|
-
"extension": ".ts"
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
"name": "JavaScript",
|
|
101
|
-
"version": "ES6+",
|
|
102
|
-
"directory": "src",
|
|
103
|
-
"extension": ".js"
|
|
104
|
-
}
|
|
105
|
-
],
|
|
106
|
-
"frameworks": [
|
|
107
|
-
{
|
|
108
|
-
"name": "Node.js",
|
|
109
|
-
"type": "Runtime environment",
|
|
110
|
-
"primary": true,
|
|
111
|
-
"directory": "src",
|
|
112
|
-
"extension": ".js"
|
|
113
|
-
}
|
|
114
|
-
],
|
|
115
|
-
"testingFrameworks": [
|
|
116
|
-
{
|
|
117
|
-
"name": "Jest",
|
|
118
|
-
"type": "Testing framework",
|
|
119
|
-
"version": "29.7.0"
|
|
120
|
-
"directory": "tests"
|
|
121
|
-
},
|
|
122
|
-
],
|
|
123
|
-
"buildTools": [
|
|
124
|
-
{
|
|
125
|
-
"name": "TypeScript Compiler (tsc)",
|
|
126
|
-
"type": "Transpiler"
|
|
127
|
-
},
|
|
128
|
-
{
|
|
129
|
-
"name": "Vite",
|
|
130
|
-
"type": "Build tool",
|
|
131
|
-
"version": "5.3.3"
|
|
132
|
-
}
|
|
133
|
-
],
|
|
134
|
-
"packageManager": "Yarn",
|
|
135
|
-
"linters": [
|
|
136
|
-
{
|
|
137
|
-
"name": "ESLint",
|
|
138
|
-
"version": "9.6.0"
|
|
139
|
-
}
|
|
140
|
-
],
|
|
141
|
-
"databases": [
|
|
142
|
-
{
|
|
143
|
-
"name": "MongoDB",
|
|
144
|
-
"version": "5.0.3",
|
|
145
|
-
"primary": true
|
|
146
|
-
}
|
|
147
|
-
],
|
|
148
|
-
"projectType": "Command-line tool",
|
|
149
|
-
}`
|
|
150
|
-
}
|
|
151
|
-
];
|
|
152
|
-
if (!options.silent) {
|
|
153
|
-
if (specialFileNames.length > 0) {
|
|
154
|
-
console.log(`Cloving will analyze the list of files and the contents of the following files:
|
|
155
|
-
|
|
156
|
-
${specialFileNames.join("\n")}
|
|
157
|
-
|
|
158
|
-
Cloving will send AI a request to summarize the technologies used in this project.
|
|
159
|
-
|
|
160
|
-
This will provide better context for future Cloving requests.`);
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
console.log(`
|
|
164
|
-
This script will analyze the list of files in the current directory using GPT to summarize the
|
|
165
|
-
technologies used. This will provide better context for future Cloving requests.
|
|
166
|
-
`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
const config = (0, config_utils_1.getConfig)(options);
|
|
170
|
-
if (!config || !config?.models) {
|
|
171
|
-
console.error('No cloving configuration found. Please run `cloving config`');
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
if (!(0, command_utils_1.checkForSpecialFiles)()) {
|
|
175
|
-
console.error('No dependencies files detected. Please add a dependency file (e.g. package.json, Gemfile, requirements.txt, etc.) to your project and run `cloving init` again.');
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `describe_${Date.now()}.tmp`);
|
|
179
|
-
try {
|
|
180
|
-
const gitignorePath = path_1.default.join(process.cwd(), '.gitignore');
|
|
181
|
-
const ig = (0, ignore_1.default)();
|
|
182
|
-
if (fs_1.default.existsSync(gitignorePath)) {
|
|
183
|
-
const gitignoreContent = fs_1.default.readFileSync(gitignorePath, 'utf-8');
|
|
184
|
-
ig.add(gitignoreContent);
|
|
185
|
-
}
|
|
186
|
-
const fileList = await (0, command_utils_1.generateFileList)();
|
|
187
|
-
const filteredFileList = fileList.filter(file => {
|
|
188
|
-
try {
|
|
189
|
-
return !ig.ignores(file);
|
|
190
|
-
}
|
|
191
|
-
catch (error) {
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
const limitedFileList = filteredFileList.slice(0, 100);
|
|
196
|
-
const projectDetails = {
|
|
197
|
-
files: limitedFileList,
|
|
198
|
-
specialFiles: specialFileContents
|
|
199
|
-
};
|
|
200
|
-
const prompt = `Here is a JSON object describing my project:
|
|
201
|
-
${JSON.stringify(projectDetails, null, 2)}`;
|
|
202
|
-
chatHistory.push({ role: 'user', content: prompt });
|
|
203
|
-
const aiChatResponse = await gpt.generateText({ prompt, messages: chatHistory });
|
|
204
|
-
chatHistory.push({ role: 'assistant', content: aiChatResponse });
|
|
205
|
-
const cleanAiChatResponse = (0, string_utils_1.extractJsonMetadata)(aiChatResponse);
|
|
206
|
-
fs_1.default.writeFileSync(tempFilePath, cleanAiChatResponse);
|
|
207
|
-
// Save the AI chat response to cloving.json
|
|
208
|
-
fs_1.default.writeFileSync('cloving.json', cleanAiChatResponse);
|
|
209
|
-
console.log('Project data saved to cloving.json');
|
|
210
|
-
// Prompt the user if they want to review the generated cloving.json
|
|
211
|
-
if (!options.silent) {
|
|
212
|
-
const reviewAnswer = await (0, prompts_1.confirm)({
|
|
213
|
-
message: 'Do you want to review the generated data?',
|
|
214
|
-
default: true,
|
|
215
|
-
});
|
|
216
|
-
if (reviewAnswer) {
|
|
217
|
-
console.log(cleanAiChatResponse);
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
// Clean up
|
|
221
|
-
fs_1.default.unlinkSync(tempFilePath);
|
|
222
|
-
}
|
|
223
|
-
catch (error) {
|
|
224
|
-
console.error('Error describing the project:', error.message);
|
|
225
|
-
}
|
|
9
|
+
const initManager = new InitManager_1.default(options);
|
|
10
|
+
await initManager.initialize();
|
|
226
11
|
};
|
|
227
12
|
exports.init = init;
|
|
228
13
|
exports.default = exports.init;
|
package/dist/commands/tokens.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const fs_1 = __importDefault(require("fs"));
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
8
|
const config_utils_1 = require("../utils/config_utils");
|
|
9
|
-
const
|
|
9
|
+
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
10
10
|
const tokens = async (options) => {
|
|
11
11
|
let contextFiles = {};
|
|
12
12
|
let files = options.files || '.';
|
|
@@ -14,9 +14,12 @@ const tokens = async (options) => {
|
|
|
14
14
|
let expandedFiles = [];
|
|
15
15
|
for (const file of files) {
|
|
16
16
|
const filePath = path_1.default.resolve(file);
|
|
17
|
-
if (await fs_1.default.promises
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
if (await fs_1.default.promises
|
|
18
|
+
.stat(filePath)
|
|
19
|
+
.then((stat) => stat.isDirectory())
|
|
20
|
+
.catch(() => false)) {
|
|
21
|
+
const dirFiles = await (0, prompt_utils_1.getAllFilesInDirectory)(filePath);
|
|
22
|
+
expandedFiles = expandedFiles.concat(dirFiles.map((f) => path_1.default.relative(process.cwd(), f)));
|
|
20
23
|
}
|
|
21
24
|
else {
|
|
22
25
|
expandedFiles.push(path_1.default.relative(process.cwd(), filePath));
|
|
@@ -25,12 +28,17 @@ const tokens = async (options) => {
|
|
|
25
28
|
files = expandedFiles;
|
|
26
29
|
for (const file of files) {
|
|
27
30
|
const filePath = path_1.default.resolve(file);
|
|
28
|
-
if (await fs_1.default.promises
|
|
31
|
+
if (await fs_1.default.promises
|
|
32
|
+
.stat(filePath)
|
|
33
|
+
.then((stat) => stat.isFile())
|
|
34
|
+
.catch(() => false)) {
|
|
29
35
|
const content = await fs_1.default.promises.readFile(filePath, 'utf-8');
|
|
30
36
|
contextFiles[file] = content;
|
|
31
37
|
}
|
|
32
38
|
}
|
|
33
|
-
const contextFileContents = Object.keys(contextFiles)
|
|
39
|
+
const contextFileContents = Object.keys(contextFiles)
|
|
40
|
+
.map((file) => `### Contents of ${file}\n\n${contextFiles[file]}\n\n`)
|
|
41
|
+
.join('\n');
|
|
34
42
|
prompt += `
|
|
35
43
|
### Description of App
|
|
36
44
|
|
package/dist/index.js
CHANGED
|
@@ -17,12 +17,12 @@ const commit_1 = __importDefault(require("./commands/generate/commit"));
|
|
|
17
17
|
const context_1 = __importDefault(require("./commands/generate/context"));
|
|
18
18
|
const unit_tests_1 = __importDefault(require("./commands/generate/unit_tests"));
|
|
19
19
|
const review_1 = __importDefault(require("./commands/generate/review"));
|
|
20
|
-
const
|
|
20
|
+
const prompt_utils_1 = require("./utils/prompt_utils");
|
|
21
21
|
const program = new commander_1.Command();
|
|
22
22
|
program
|
|
23
23
|
.name('cloving')
|
|
24
24
|
.description('Integrate AI into your development workflow for generating commit messages, code reviews, and unit tests.')
|
|
25
|
-
.version((0,
|
|
25
|
+
.version((0, prompt_utils_1.getPackageVersion)());
|
|
26
26
|
program
|
|
27
27
|
.command('config')
|
|
28
28
|
.description('Configure cloving with your API key and models to use')
|
|
@@ -36,6 +36,7 @@ program
|
|
|
36
36
|
program
|
|
37
37
|
.command('chat')
|
|
38
38
|
.option('-f, --files <filenames...>', 'Specify filenames of files with context to use for generating code')
|
|
39
|
+
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
39
40
|
.option('-t, --temperature <temperature>', 'Temperature for the model (default 0.2)')
|
|
40
41
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5:sonnet-20240620)')
|
|
41
42
|
.description('Start an interactive chat with cloving')
|
|
@@ -47,11 +48,7 @@ program
|
|
|
47
48
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5:sonnet-20240620)')
|
|
48
49
|
.description('Start a proxy server to use with cloving')
|
|
49
50
|
.action(proxy_1.default);
|
|
50
|
-
program
|
|
51
|
-
.command('models')
|
|
52
|
-
.alias('m')
|
|
53
|
-
.description('List available models')
|
|
54
|
-
.action(models_1.default);
|
|
51
|
+
program.command('models').alias('m').description('List available models').action(models_1.default);
|
|
55
52
|
program
|
|
56
53
|
.command('tokens')
|
|
57
54
|
.alias('t')
|
|
@@ -106,7 +103,7 @@ generate
|
|
|
106
103
|
generate
|
|
107
104
|
.command('unit-tests')
|
|
108
105
|
.alias('u')
|
|
109
|
-
.description(
|
|
106
|
+
.description("Generate unit tests (if you don't specify filenames, it will generate tests for commited changes that differ from the main/master branch)")
|
|
110
107
|
.option('--save', 'Automatically save all files after generating the unit tests')
|
|
111
108
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
112
109
|
.option('-f, --files <filenames...>', 'Specify filenames for the unit tests')
|