cloving 0.3.10 → 0.3.12
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/azureopenai.js +1 -1
- package/dist/cloving_gpt/index.js +31 -38
- package/dist/commands/config.js +45 -0
- package/dist/commands/generate/commit.js +1 -1
- package/dist/commands/generate/docs.js +11 -0
- package/dist/commands/generate/documentation.js +11 -0
- package/dist/commands/generate/review.js +1 -1
- package/dist/commands/tokens.js +24 -0
- package/dist/index.js +10 -0
- package/dist/managers/BlockManager.js +17 -13
- package/dist/managers/ChatManager.js +22 -208
- package/dist/managers/CodeManager.js +58 -55
- package/dist/managers/CommitManager.js +1 -1
- package/dist/managers/DocsManager.js +86 -0
- package/dist/managers/DocumentationManager.js +114 -0
- package/dist/managers/InitManager.js +2 -1
- package/dist/managers/ReviewManager.js +59 -169
- package/dist/managers/ShellManager.js +49 -0
- package/dist/managers/StreamManager.js +291 -0
- package/dist/managers/UnitTestManager.js +3 -3
- package/dist/package.json +2 -2
- package/dist/utils/config_utils.js +43 -0
- package/dist/utils/git_utils.js +29 -0
- package/dist/utils/prompt_utils.js +125 -307
- package/dist/utils/prompts/CODEGEN_COULDNT_APPLY.md +5 -0
- package/dist/utils/prompts/CODEGEN_EXAMPLES.md +82 -0
- package/dist/utils/prompts/CODEGEN_INSTRUCTIONS.md +42 -0
- package/dist/utils/prompts/DOCS_INSTRUCTIONS.md +9 -0
- package/dist/utils/prompts/INIT_INSTRUCTIONS.md +132 -0
- package/dist/utils/prompts/REVIEW_INSTRUCTIONS.md +49 -0
- package/dist/utils/prompts/SHELL_INSTRUCTIONS.md +15 -0
- package/dist/utils/prompts/SPECIAL_FILES.md +66 -0
- package/dist/utils/prompts/index.js +27 -0
- package/package.json +2 -2
|
@@ -0,0 +1,291 @@
|
|
|
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 = __importDefault(require("fs"));
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const events_1 = require("events");
|
|
10
|
+
const colors_1 = __importDefault(require("colors"));
|
|
11
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
12
|
+
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
13
|
+
const ChunkManager_1 = __importDefault(require("./ChunkManager"));
|
|
14
|
+
const BlockManager_1 = __importDefault(require("./BlockManager"));
|
|
15
|
+
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
16
|
+
const config_utils_1 = require("../utils/config_utils");
|
|
17
|
+
const prompt_utils_2 = require("../utils/prompt_utils");
|
|
18
|
+
/**
|
|
19
|
+
* StreamManager class
|
|
20
|
+
*
|
|
21
|
+
* This class extends EventEmitter and manages the streaming of responses from an AI model.
|
|
22
|
+
* It handles the processing of chunks, manages code blocks, and provides animation for code generation.
|
|
23
|
+
*/
|
|
24
|
+
class StreamManager extends events_1.EventEmitter {
|
|
25
|
+
/**
|
|
26
|
+
* Creates an instance of StreamManager.
|
|
27
|
+
* @param {any} options - Configuration options for the StreamManager.
|
|
28
|
+
*/
|
|
29
|
+
constructor(options) {
|
|
30
|
+
super();
|
|
31
|
+
this.options = options;
|
|
32
|
+
this.prompt = '';
|
|
33
|
+
this.responseString = '';
|
|
34
|
+
this.contextFiles = {};
|
|
35
|
+
this.chatHistory = [];
|
|
36
|
+
this.isProcessing = false;
|
|
37
|
+
this.animationInterval = null;
|
|
38
|
+
this.retryCount = 0;
|
|
39
|
+
this.maxRetries = 3;
|
|
40
|
+
this.gpt = new cloving_gpt_1.default(options);
|
|
41
|
+
this.chunkManager = new ChunkManager_1.default();
|
|
42
|
+
this.blockManager = new BlockManager_1.default();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Checks for the latest version of the app from GitHub and compares it with the current version.
|
|
46
|
+
* If a new version is available, it notifies the user.
|
|
47
|
+
* @private
|
|
48
|
+
* @returns {Promise<void>}
|
|
49
|
+
*/
|
|
50
|
+
async checkForLatestVersion() {
|
|
51
|
+
try {
|
|
52
|
+
const response = await axios_1.default.get('https://api.github.com/repos/cloving-ai/cloving-cli/releases/latest');
|
|
53
|
+
const latestVersion = response.data.tag_name;
|
|
54
|
+
const currentVersion = `v${(0, prompt_utils_1.getPackageVersion)()}`;
|
|
55
|
+
if (latestVersion !== currentVersion) {
|
|
56
|
+
console.log(colors_1.default.bgWhite.black(`\n 🚀 A new version of Cloving is available: ${latestVersion} `));
|
|
57
|
+
console.log(colors_1.default.bgWhite.black(` You are currently using version: ${currentVersion} `));
|
|
58
|
+
console.log(colors_1.default.bgWhite.black(` To upgrade, run: ${colors_1.default.bgWhite.black.bold('npm install -g cloving@latest')} `));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
// ignore errors
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Handles the response stream from the AI model.
|
|
67
|
+
* @param {any} responseStream - The stream of responses from the AI model.
|
|
68
|
+
*/
|
|
69
|
+
handleResponseStream(responseStream) {
|
|
70
|
+
this.responseString = '';
|
|
71
|
+
this.setupChunkManagerEvents();
|
|
72
|
+
this.setupBlockManagerEvents();
|
|
73
|
+
this.setupResponseStreamEvents(responseStream);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Sets up event listeners for the BlockManager.
|
|
77
|
+
* @private
|
|
78
|
+
*/
|
|
79
|
+
setupBlockManagerEvents() {
|
|
80
|
+
this.blockManager = new BlockManager_1.default();
|
|
81
|
+
this.blockManager.on('startGeneratingCode', () => {
|
|
82
|
+
this.setupAnimationInterval();
|
|
83
|
+
});
|
|
84
|
+
this.blockManager.on('endGeneratingCode', () => {
|
|
85
|
+
this.clearAnimation();
|
|
86
|
+
});
|
|
87
|
+
this.blockManager.on('content', (content) => {
|
|
88
|
+
process.stdout.write(content);
|
|
89
|
+
this.responseString += content;
|
|
90
|
+
});
|
|
91
|
+
this.blockManager.on('codeBlock', (codeBlock) => {
|
|
92
|
+
this.handleCodeBlock(codeBlock);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Sets up an animation interval for code generation visualization.
|
|
97
|
+
* @private
|
|
98
|
+
*/
|
|
99
|
+
setupAnimationInterval() {
|
|
100
|
+
process.stdout.write(colors_1.default.gray.bold('\nGenerating code... '));
|
|
101
|
+
let animationIndex = 0;
|
|
102
|
+
const animationChars = ['/', '|', '\\', '-'];
|
|
103
|
+
this.animationInterval = setInterval(() => {
|
|
104
|
+
process.stdout.write('\b'.repeat(1));
|
|
105
|
+
process.stdout.write(colors_1.default.gray.bold(animationChars[animationIndex]));
|
|
106
|
+
animationIndex = (animationIndex + 1) % animationChars.length;
|
|
107
|
+
}, 100);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Clears the animation interval.
|
|
111
|
+
* @private
|
|
112
|
+
*/
|
|
113
|
+
clearAnimation() {
|
|
114
|
+
if (!this.animationInterval)
|
|
115
|
+
return;
|
|
116
|
+
clearInterval(this.animationInterval);
|
|
117
|
+
process.stdout.write('\b'.repeat(100));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Handles the processing of a code block.
|
|
121
|
+
* @private
|
|
122
|
+
* @param {Object} codeBlock - The code block to process.
|
|
123
|
+
* @param {CurrentNewBlock} [codeBlock.currentNewBlock] - The current and new content of the code block.
|
|
124
|
+
* @param {string} [codeBlock.raw] - The raw content of the code block.
|
|
125
|
+
*/
|
|
126
|
+
handleCodeBlock(codeBlock) {
|
|
127
|
+
const { currentNewBlock, raw } = codeBlock;
|
|
128
|
+
if (currentNewBlock?.currentContent && currentNewBlock?.newContent) {
|
|
129
|
+
this.displayCurrentNewBlock(currentNewBlock);
|
|
130
|
+
}
|
|
131
|
+
else if (raw) {
|
|
132
|
+
this.displayRawCodeBlock(raw);
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
process.stdout.write(` \n`);
|
|
136
|
+
}
|
|
137
|
+
this.responseString += raw || currentNewBlock;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Displays the current and new content of a code block.
|
|
141
|
+
* @private
|
|
142
|
+
* @param {CurrentNewBlock} currentNewBlock - The current and new content of the code block.
|
|
143
|
+
*/
|
|
144
|
+
displayCurrentNewBlock(currentNewBlock) {
|
|
145
|
+
try {
|
|
146
|
+
process.stdout.write(colors_1.default.gray.bold(`\`\`\`${currentNewBlock.language} \n`));
|
|
147
|
+
process.stdout.write(colors_1.default.gray.bold(`<<<<<<< CURRENT ${currentNewBlock.filePath}\n`));
|
|
148
|
+
process.stdout.write((0, cli_highlight_1.default)(currentNewBlock.currentContent, { language: currentNewBlock.language }));
|
|
149
|
+
process.stdout.write(colors_1.default.gray.bold('\n=======\n'));
|
|
150
|
+
process.stdout.write((0, cli_highlight_1.default)(currentNewBlock.newContent, { language: currentNewBlock.language }));
|
|
151
|
+
process.stdout.write(colors_1.default.gray.bold('\n>>>>>>> NEW\n```'));
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
console.error(colors_1.default.red('Error displaying the code block:'), error);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Displays a raw code block.
|
|
159
|
+
* @private
|
|
160
|
+
* @param {string} raw - The raw content of the code block.
|
|
161
|
+
*/
|
|
162
|
+
displayRawCodeBlock(raw) {
|
|
163
|
+
process.stdout.write(` \n`);
|
|
164
|
+
process.stdout.write((0, cli_highlight_1.default)(raw));
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Sets up event listeners for the ChunkManager.
|
|
168
|
+
* @private
|
|
169
|
+
*/
|
|
170
|
+
setupChunkManagerEvents() {
|
|
171
|
+
this.chunkManager = new ChunkManager_1.default();
|
|
172
|
+
this.chunkManager.on('content', (buffer) => {
|
|
173
|
+
this.processChunkManagerContent(buffer);
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Processes the content received from the ChunkManager.
|
|
178
|
+
* @private
|
|
179
|
+
* @param {string} buffer - The buffer containing the chunk content.
|
|
180
|
+
*/
|
|
181
|
+
processChunkManagerContent(buffer) {
|
|
182
|
+
let convertedStream = this.gpt.convertStream(buffer);
|
|
183
|
+
while (convertedStream !== null) {
|
|
184
|
+
const { output, lastChar } = convertedStream;
|
|
185
|
+
this.blockManager.addContent(output);
|
|
186
|
+
this.chunkManager.clearBuffer(lastChar);
|
|
187
|
+
buffer = buffer.slice(lastChar);
|
|
188
|
+
convertedStream = this.gpt.convertStream(buffer);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Sets up event listeners for the response stream.
|
|
193
|
+
* @private
|
|
194
|
+
* @param {any} responseStream - The stream of responses from the AI model.
|
|
195
|
+
*/
|
|
196
|
+
setupResponseStreamEvents(responseStream) {
|
|
197
|
+
responseStream.data.on('data', this.handleResponseStreamData.bind(this));
|
|
198
|
+
responseStream.data.on('end', () => this.finalizeResponse());
|
|
199
|
+
responseStream.data.on('error', this.handleResponseStreamError.bind(this));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Handles the data received from the response stream.
|
|
203
|
+
* @private
|
|
204
|
+
* @param {Buffer | undefined} chunk - The chunk of data received from the stream.
|
|
205
|
+
*/
|
|
206
|
+
handleResponseStreamData(chunk) {
|
|
207
|
+
if (!chunk)
|
|
208
|
+
return;
|
|
209
|
+
const chunkString = chunk.toString();
|
|
210
|
+
this.chunkManager.addChunk(chunkString);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Handles errors that occur during the response stream.
|
|
214
|
+
* @private
|
|
215
|
+
* @param {Error} error - The error that occurred.
|
|
216
|
+
*/
|
|
217
|
+
handleResponseStreamError(error) {
|
|
218
|
+
console.error('Error streaming response:', error);
|
|
219
|
+
this.isProcessing = false;
|
|
220
|
+
process.stdout.write('\n');
|
|
221
|
+
this.emit('prompt');
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Finalizes the response processing.
|
|
225
|
+
* This method should be overridden in subclasses to provide specific finalization behavior.
|
|
226
|
+
* @protected
|
|
227
|
+
*/
|
|
228
|
+
finalizeResponse() {
|
|
229
|
+
this.isProcessing = false;
|
|
230
|
+
this.emit('responseFinalized', this.responseString);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Loads context files specified in the options or defaults to the primary language's directory.
|
|
234
|
+
* @private
|
|
235
|
+
* @returns {Promise<void>}
|
|
236
|
+
*/
|
|
237
|
+
async loadContextFiles() {
|
|
238
|
+
const config = (0, config_utils_1.getClovingConfig)();
|
|
239
|
+
const primaryLanguage = config.languages.find((lang) => lang.primary);
|
|
240
|
+
const defaultDirectory = primaryLanguage ? primaryLanguage.directory : '.';
|
|
241
|
+
const testingDirectories = config.testingFrameworks?.map((framework) => framework.directory) || [];
|
|
242
|
+
const testingDirectory = testingDirectories[0];
|
|
243
|
+
let files = this.options.files || [defaultDirectory, testingDirectory].filter(Boolean);
|
|
244
|
+
if (files.length > 0) {
|
|
245
|
+
console.log(`\nBuilding AI prompt context...\n`);
|
|
246
|
+
}
|
|
247
|
+
for (const file of files) {
|
|
248
|
+
// Skip if the file is not a string
|
|
249
|
+
if (!file)
|
|
250
|
+
continue;
|
|
251
|
+
const previousCount = Object.keys(this.contextFiles).length;
|
|
252
|
+
this.contextFiles = await (0, prompt_utils_2.addFileOrDirectoryToContext)(file, this.contextFiles, this.options);
|
|
253
|
+
const newCount = Object.keys(this.contextFiles).length;
|
|
254
|
+
const addedCount = newCount - previousCount;
|
|
255
|
+
const totalTokens = this.calculateTotalTokens();
|
|
256
|
+
console.log(colors_1.default.cyan(`📁 Loaded context from: ${colors_1.default.bold(file)}`));
|
|
257
|
+
console.log(colors_1.default.green(` ✅ Added ${addedCount} file(s) to context`));
|
|
258
|
+
console.log(colors_1.default.yellow(` 📊 Total tokens in context: ${totalTokens.toLocaleString()}\n`));
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
calculateTotalTokens() {
|
|
262
|
+
return Object.values(this.contextFiles).reduce((total, content) => {
|
|
263
|
+
return total + Math.ceil(content.length / 4);
|
|
264
|
+
}, 0);
|
|
265
|
+
}
|
|
266
|
+
async refreshContext() {
|
|
267
|
+
await this.reloadContextFiles();
|
|
268
|
+
const updatedSystemPrompt = (0, prompt_utils_2.generateCodegenPrompt)(this.contextFiles);
|
|
269
|
+
this.chatHistory[0] = { role: 'user', content: updatedSystemPrompt };
|
|
270
|
+
this.chatHistory[1] = { role: 'assistant', content: 'What would you like to do?' };
|
|
271
|
+
}
|
|
272
|
+
async reloadContextFiles() {
|
|
273
|
+
for (const filePath in this.contextFiles) {
|
|
274
|
+
try {
|
|
275
|
+
const content = await fs_1.default.promises.readFile(path_1.default.resolve(filePath), 'utf8');
|
|
276
|
+
this.contextFiles[filePath] = content;
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
console.error(`Error reading file ${filePath}:`, error);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
addUserPrompt(content) {
|
|
284
|
+
this.prompt = content;
|
|
285
|
+
this.chatHistory.push({ role: 'user', content });
|
|
286
|
+
}
|
|
287
|
+
addAssistantResponse(content) {
|
|
288
|
+
this.chatHistory.push({ role: 'assistant', content });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
exports.default = StreamManager;
|
|
@@ -8,7 +8,7 @@ const child_process_1 = require("child_process");
|
|
|
8
8
|
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
9
9
|
const prompts_1 = require("@inquirer/prompts");
|
|
10
10
|
const git_utils_1 = require("../utils/git_utils");
|
|
11
|
-
const
|
|
11
|
+
const prompts_2 = require("../utils/prompts");
|
|
12
12
|
const config_utils_1 = require("../utils/config_utils");
|
|
13
13
|
const string_utils_1 = require("../utils/string_utils");
|
|
14
14
|
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
@@ -197,7 +197,7 @@ Also, list any test files that might be relevant to these files.`;
|
|
|
197
197
|
## List of Files
|
|
198
198
|
${(files || []).join('\n')}
|
|
199
199
|
|
|
200
|
-
${
|
|
200
|
+
${prompts_2.CODEGEN_INSTRUCTIONS}
|
|
201
201
|
|
|
202
202
|
## Context
|
|
203
203
|
|
|
@@ -221,7 +221,7 @@ ${await (0, git_utils_1.getGitDiff)()}
|
|
|
221
221
|
|
|
222
222
|
${context.join('\n\n')}
|
|
223
223
|
|
|
224
|
-
${
|
|
224
|
+
${prompts_2.CODEGEN_INSTRUCTIONS}
|
|
225
225
|
|
|
226
226
|
## Prompt
|
|
227
227
|
|
package/dist/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloving",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"packageManager": "yarn@1.22.22",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
|
-
"build": "tsc && cp package.json dist/package.json",
|
|
8
|
+
"build": "tsc && cp package.json dist/package.json && cp src/utils/prompts/*.md dist/utils/prompts/",
|
|
9
9
|
"start": "node dist/index.js",
|
|
10
10
|
"watch": "tsc -w",
|
|
11
11
|
"check": "bash -c 'npx tsc --noEmit --skipLibCheck'",
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @file Configuration utilities for Cloving
|
|
4
|
+
* @module config_utils
|
|
5
|
+
*/
|
|
2
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
8
|
};
|
|
@@ -10,10 +14,19 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
10
14
|
const ini_1 = __importDefault(require("ini"));
|
|
11
15
|
const child_process_1 = require("child_process");
|
|
12
16
|
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
17
|
+
/** Path to the global Cloving configuration file */
|
|
13
18
|
exports.CLOVING_CONFIG_PATH = path_1.default.join(os_1.default.homedir(), '.clovingconfig');
|
|
19
|
+
/** Name of the local Cloving configuration file */
|
|
14
20
|
exports.CLOVINGFILE_PATH = 'cloving.json';
|
|
21
|
+
/** Path to the Cloving projects directory */
|
|
15
22
|
exports.CLOVINGPROJECT_PATH = '.clovingprojects';
|
|
23
|
+
/** Cached Cloving configuration */
|
|
16
24
|
let clovingConfig;
|
|
25
|
+
/**
|
|
26
|
+
* Retrieves the Cloving configuration
|
|
27
|
+
* @param {ClovingGPTOptions} options - Options for ClovingGPT
|
|
28
|
+
* @returns {ClovingConfig} The Cloving configuration
|
|
29
|
+
*/
|
|
17
30
|
const getConfig = (options) => {
|
|
18
31
|
try {
|
|
19
32
|
if (fs_1.default.existsSync(exports.CLOVING_CONFIG_PATH)) {
|
|
@@ -38,6 +51,7 @@ const getConfig = (options) => {
|
|
|
38
51
|
catch (err) {
|
|
39
52
|
console.error('Error reading configuration:', err);
|
|
40
53
|
}
|
|
54
|
+
// Fallback to environment variables if config file doesn't exist
|
|
41
55
|
if (process.env.CLOVING_MODEL) {
|
|
42
56
|
const [provider, ...modelParts] = process.env.CLOVING_MODEL.split(':');
|
|
43
57
|
const model = modelParts.join(':');
|
|
@@ -62,6 +76,11 @@ const getConfig = (options) => {
|
|
|
62
76
|
}
|
|
63
77
|
};
|
|
64
78
|
exports.getConfig = getConfig;
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves the local Cloving configuration
|
|
81
|
+
* @returns {ClovingfileConfig} The local Cloving configuration
|
|
82
|
+
* @throws {Error} If the cloving.json file is not found
|
|
83
|
+
*/
|
|
65
84
|
const getClovingConfig = () => {
|
|
66
85
|
if (clovingConfig) {
|
|
67
86
|
return clovingConfig;
|
|
@@ -77,12 +96,21 @@ const getClovingConfig = () => {
|
|
|
77
96
|
}
|
|
78
97
|
};
|
|
79
98
|
exports.getClovingConfig = getClovingConfig;
|
|
99
|
+
/**
|
|
100
|
+
* Saves the Cloving configuration to the config file
|
|
101
|
+
* @param {ClovingConfig} config - The configuration to save
|
|
102
|
+
*/
|
|
80
103
|
const saveConfig = (config) => {
|
|
81
104
|
const iniString = ini_1.default.stringify(config);
|
|
82
105
|
fs_1.default.writeFileSync(exports.CLOVING_CONFIG_PATH, iniString);
|
|
83
106
|
console.log(`Configuration saved to ${exports.CLOVING_CONFIG_PATH}`);
|
|
84
107
|
};
|
|
85
108
|
exports.saveConfig = saveConfig;
|
|
109
|
+
/**
|
|
110
|
+
* Retrieves the primary model configuration
|
|
111
|
+
* @param {string} [partialModel] - Partial model name to filter by
|
|
112
|
+
* @returns {Object | null} The primary model configuration or null if not found
|
|
113
|
+
*/
|
|
86
114
|
const getPrimaryModel = (partialModel) => {
|
|
87
115
|
try {
|
|
88
116
|
const config = (0, exports.getConfig)({});
|
|
@@ -107,6 +135,12 @@ const getPrimaryModel = (partialModel) => {
|
|
|
107
135
|
}
|
|
108
136
|
};
|
|
109
137
|
exports.getPrimaryModel = getPrimaryModel;
|
|
138
|
+
/**
|
|
139
|
+
* Retrieves the configuration for a specific project
|
|
140
|
+
* @param {string} name - The name of the project
|
|
141
|
+
* @returns {ProjectConfig} The project configuration
|
|
142
|
+
* @throws {Error} If the project configuration file is not found
|
|
143
|
+
*/
|
|
110
144
|
const getProjectConfig = (name) => {
|
|
111
145
|
const projectConfigPath = path_1.default.join(exports.CLOVINGPROJECT_PATH, name, 'config.ini');
|
|
112
146
|
if (fs_1.default.existsSync(projectConfigPath)) {
|
|
@@ -118,6 +152,11 @@ const getProjectConfig = (name) => {
|
|
|
118
152
|
}
|
|
119
153
|
};
|
|
120
154
|
exports.getProjectConfig = getProjectConfig;
|
|
155
|
+
/**
|
|
156
|
+
* Saves the configuration for a specific project
|
|
157
|
+
* @param {string} name - The name of the project
|
|
158
|
+
* @param {ProjectConfig} config - The project configuration to save
|
|
159
|
+
*/
|
|
121
160
|
const saveProjectConfig = (name, config) => {
|
|
122
161
|
const projectConfigPath = path_1.default.join(exports.CLOVINGPROJECT_PATH, name, 'config.ini');
|
|
123
162
|
const projectConfigDir = path_1.default.dirname(projectConfigPath);
|
|
@@ -130,6 +169,10 @@ const saveProjectConfig = (name, config) => {
|
|
|
130
169
|
console.log(`Configuration saved to ${projectConfigPath}`);
|
|
131
170
|
};
|
|
132
171
|
exports.saveProjectConfig = saveProjectConfig;
|
|
172
|
+
/**
|
|
173
|
+
* Removes the configuration file for a specific project
|
|
174
|
+
* @param {string} name - The name of the project
|
|
175
|
+
*/
|
|
133
176
|
const removeProjectConfig = (name) => {
|
|
134
177
|
const projectConfigPath = path_1.default.join(exports.CLOVINGPROJECT_PATH, name, 'config.ini');
|
|
135
178
|
if (fs_1.default.existsSync(projectConfigPath)) {
|
package/dist/utils/git_utils.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module git_utils
|
|
4
|
+
* @description Provides utility functions for Git operations and commit message generation.
|
|
5
|
+
*/
|
|
2
6
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
7
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
8
|
};
|
|
@@ -6,6 +10,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
10
|
exports.generateCommitMessagePrompt = exports.getCurrentBranchName = exports.getDefaultBranchName = exports.getGitDiff = void 0;
|
|
7
11
|
const child_process_1 = require("child_process");
|
|
8
12
|
const readline_1 = __importDefault(require("readline"));
|
|
13
|
+
/**
|
|
14
|
+
* Prompts the user with a question and returns their answer.
|
|
15
|
+
* @param {string} question - The question to ask the user.
|
|
16
|
+
* @returns {Promise<string>} A promise that resolves with the user's answer.
|
|
17
|
+
*/
|
|
9
18
|
const askQuestion = (question) => {
|
|
10
19
|
const rl = readline_1.default.createInterface({
|
|
11
20
|
input: process.stdin,
|
|
@@ -16,6 +25,11 @@ const askQuestion = (question) => {
|
|
|
16
25
|
resolve(answer);
|
|
17
26
|
}));
|
|
18
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves the Git diff between the current branch and the default branch.
|
|
30
|
+
* @returns {Promise<string>} A promise that resolves with the indented Git diff.
|
|
31
|
+
* @throws {Error} If there's an error getting the Git diff.
|
|
32
|
+
*/
|
|
19
33
|
const getGitDiff = async () => {
|
|
20
34
|
try {
|
|
21
35
|
const defaultBranchName = await (0, exports.getDefaultBranchName)();
|
|
@@ -33,6 +47,11 @@ const getGitDiff = async () => {
|
|
|
33
47
|
}
|
|
34
48
|
};
|
|
35
49
|
exports.getGitDiff = getGitDiff;
|
|
50
|
+
/**
|
|
51
|
+
* Determines the default branch name for the Git repository.
|
|
52
|
+
* @returns {Promise<string>} A promise that resolves with the default branch name.
|
|
53
|
+
* @throws {Error} If the default branch cannot be determined.
|
|
54
|
+
*/
|
|
36
55
|
const getDefaultBranchName = async () => {
|
|
37
56
|
let defaultBranchName = (0, child_process_1.execSync)("git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'")
|
|
38
57
|
.toString()
|
|
@@ -54,6 +73,11 @@ const getDefaultBranchName = async () => {
|
|
|
54
73
|
return defaultBranchName;
|
|
55
74
|
};
|
|
56
75
|
exports.getDefaultBranchName = getDefaultBranchName;
|
|
76
|
+
/**
|
|
77
|
+
* Retrieves the name of the current Git branch.
|
|
78
|
+
* @returns {string} The name of the current Git branch.
|
|
79
|
+
* @throws {Error} If there's an error getting the current branch name.
|
|
80
|
+
*/
|
|
57
81
|
const getCurrentBranchName = () => {
|
|
58
82
|
try {
|
|
59
83
|
return (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD').toString().trim();
|
|
@@ -64,6 +88,11 @@ const getCurrentBranchName = () => {
|
|
|
64
88
|
}
|
|
65
89
|
};
|
|
66
90
|
exports.getCurrentBranchName = getCurrentBranchName;
|
|
91
|
+
/**
|
|
92
|
+
* Generates a prompt for creating a commit message based on a Git diff.
|
|
93
|
+
* @param {string} diff - The Git diff to base the commit message on.
|
|
94
|
+
* @returns {string} A prompt string for generating a commit message.
|
|
95
|
+
*/
|
|
67
96
|
const generateCommitMessagePrompt = (diff) => {
|
|
68
97
|
return `Generate a concise and meaningful commit message based on a diff.
|
|
69
98
|
|