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
|
@@ -3,20 +3,18 @@ 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 os_1 = __importDefault(require("os"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
const axios_1 = __importDefault(require("axios"));
|
|
10
|
-
const child_process_1 = require("child_process");
|
|
6
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
11
7
|
const process_1 = __importDefault(require("process"));
|
|
12
|
-
const prompts_1 = require("@inquirer/prompts");
|
|
13
8
|
const colors_1 = __importDefault(require("colors"));
|
|
9
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
10
|
+
const axios_1 = __importDefault(require("axios"));
|
|
14
11
|
const claude_1 = require("./adapters/claude");
|
|
15
12
|
const openai_1 = require("./adapters/openai");
|
|
16
13
|
const mistral_1 = require("./adapters/mistral");
|
|
17
14
|
const ollama_1 = require("./adapters/ollama");
|
|
18
15
|
const gemini_1 = require("./adapters/gemini");
|
|
19
16
|
const azureopenai_1 = require("./adapters/azureopenai");
|
|
17
|
+
const string_utils_1 = require("../utils/string_utils");
|
|
20
18
|
const config_utils_1 = require("../utils/config_utils");
|
|
21
19
|
class ClovingGPT {
|
|
22
20
|
constructor(options) {
|
|
@@ -75,41 +73,36 @@ class ClovingGPT {
|
|
|
75
73
|
default: true,
|
|
76
74
|
});
|
|
77
75
|
if (reviewPrompt) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const editedPrompt = fs_1.default.readFileSync(tempFile, 'utf-8').trim();
|
|
91
|
-
fs_1.default.unlinkSync(tempFile);
|
|
92
|
-
if (editedPrompt === '') {
|
|
93
|
-
console.log('Prompt is empty.');
|
|
94
|
-
resolve(null);
|
|
95
|
-
return;
|
|
76
|
+
(0, string_utils_1.parseMarkdownInstructions)(fullPrompt).map((code) => {
|
|
77
|
+
if (code.trim().startsWith('```')) {
|
|
78
|
+
const lines = code.split('\n');
|
|
79
|
+
const language = code.match(/```(\w+)/)?.[1] || 'default';
|
|
80
|
+
console.log(lines[0]);
|
|
81
|
+
try {
|
|
82
|
+
if (language === 'default') {
|
|
83
|
+
console.log((0, cli_highlight_1.default)(lines.slice(1, -1).join('\n')));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
console.log((0, cli_highlight_1.default)(lines.slice(1, -1).join('\n'), { language }));
|
|
87
|
+
}
|
|
96
88
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
});
|
|
101
|
-
if (!confirmPrompt) {
|
|
102
|
-
resolve(null);
|
|
103
|
-
return;
|
|
89
|
+
catch (error) {
|
|
90
|
+
// don't highlight if it fails
|
|
91
|
+
console.log(lines.slice(1, -1).join('\n'));
|
|
104
92
|
}
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
console.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
93
|
+
console.log(lines.slice(-1)[0]);
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
console.log((0, cli_highlight_1.default)(code, { language: 'markdown' }));
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
const confirmPrompt = await (0, prompts_1.confirm)({
|
|
100
|
+
message: `Are you sure you want to continue?`,
|
|
101
|
+
default: true,
|
|
112
102
|
});
|
|
103
|
+
if (!confirmPrompt) {
|
|
104
|
+
process_1.default.exit(1);
|
|
105
|
+
}
|
|
113
106
|
}
|
|
114
107
|
return prompt;
|
|
115
108
|
}
|
package/dist/commands/config.js
CHANGED
|
@@ -5,6 +5,11 @@ const config_utils_1 = require("../utils/config_utils");
|
|
|
5
5
|
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
6
6
|
// Add this type definition at the top of the file
|
|
7
7
|
const prompts_1 = require("@inquirer/prompts");
|
|
8
|
+
/**
|
|
9
|
+
* Configures the AI models by prompting the user for various settings.
|
|
10
|
+
*
|
|
11
|
+
* @returns {Promise<void>} A promise that resolves when the configuration is complete.
|
|
12
|
+
*/
|
|
8
13
|
const config = async () => {
|
|
9
14
|
let currentConfig = (0, config_utils_1.getConfig)({});
|
|
10
15
|
// Ensure models are initialized properly
|
|
@@ -19,23 +24,35 @@ const config = async () => {
|
|
|
19
24
|
let continueConfig = true;
|
|
20
25
|
while (continueConfig) {
|
|
21
26
|
const providers = [...new Set(models.map((model) => model.split(':')[0]))];
|
|
27
|
+
/**
|
|
28
|
+
* Prompts the user to select a provider from the available models.
|
|
29
|
+
*/
|
|
22
30
|
const selectedProvider = await (0, prompts_1.select)({
|
|
23
31
|
message: 'Select a provider:',
|
|
24
32
|
choices: providers.map((provider) => ({ name: provider, value: provider })),
|
|
25
33
|
});
|
|
26
34
|
const providerModels = models.filter((model) => model.startsWith(selectedProvider));
|
|
27
35
|
const modelCategories = [...new Set(providerModels.map((model) => model.split(':')[1]))];
|
|
36
|
+
/**
|
|
37
|
+
* Prompts the user to select a category from the selected provider's models.
|
|
38
|
+
*/
|
|
28
39
|
const selectedCategory = await (0, prompts_1.select)({
|
|
29
40
|
message: 'Select a category:',
|
|
30
41
|
choices: modelCategories.map((category) => ({ name: category, value: category })),
|
|
31
42
|
});
|
|
32
43
|
const specificModels = providerModels.filter((model) => model.split(':')[1] === selectedCategory);
|
|
44
|
+
/**
|
|
45
|
+
* Prompts the user to select a specific model from the selected category.
|
|
46
|
+
*/
|
|
33
47
|
const modelIndex = await (0, prompts_1.select)({
|
|
34
48
|
message: "Select an AI model you'd like to use:",
|
|
35
49
|
choices: specificModels.map((model, index) => ({ name: model, value: index })),
|
|
36
50
|
pageSize: specificModels.length,
|
|
37
51
|
});
|
|
38
52
|
const selectedModel = specificModels[modelIndex];
|
|
53
|
+
/**
|
|
54
|
+
* Prompts the user to enter the API key for the selected model.
|
|
55
|
+
*/
|
|
39
56
|
const apiKey = await (0, prompts_1.input)({
|
|
40
57
|
message: `Enter your API key for ${selectedModel}: `,
|
|
41
58
|
});
|
|
@@ -44,10 +61,18 @@ const config = async () => {
|
|
|
44
61
|
if (!currentConfig.models[provider]) {
|
|
45
62
|
currentConfig.models[provider] = {};
|
|
46
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Prompts the user to set the selected model as the primary model.
|
|
66
|
+
*/
|
|
47
67
|
const primary = await (0, prompts_1.confirm)({
|
|
48
68
|
message: 'Set this model as the primary? Primary models are used by default if your prompt fits within its context window. You can configure backup models for larger prompts.',
|
|
49
69
|
default: true,
|
|
50
70
|
});
|
|
71
|
+
/**
|
|
72
|
+
* Prompts the user to enter the priority for the selected model.
|
|
73
|
+
*
|
|
74
|
+
* @returns {string} The priority value as a string.
|
|
75
|
+
*/
|
|
51
76
|
const priority = await (0, prompts_1.input)({
|
|
52
77
|
message: 'Enter the priority for this model (0-100). Higher priority AI APIs are chosen as long as the prompt fits its context window:',
|
|
53
78
|
default: primary ? '100' : '0',
|
|
@@ -59,14 +84,25 @@ const config = async () => {
|
|
|
59
84
|
return true;
|
|
60
85
|
},
|
|
61
86
|
});
|
|
87
|
+
/**
|
|
88
|
+
* Prompts the user to decide if they want to review all prompts before they are sent to the selected model.
|
|
89
|
+
*/
|
|
62
90
|
const review = await (0, prompts_1.confirm)({
|
|
63
91
|
message: `Do you want to review all prompts before they are sent to ${selectedModel}?`,
|
|
64
92
|
default: true,
|
|
65
93
|
});
|
|
94
|
+
/**
|
|
95
|
+
* Prompts the user to decide if they trust the selected model with sensitive information.
|
|
96
|
+
*/
|
|
66
97
|
const trust = await (0, prompts_1.confirm)({
|
|
67
98
|
message: `Do you trust ${selectedModel} with sensitive information?`,
|
|
68
99
|
default: false,
|
|
69
100
|
});
|
|
101
|
+
/**
|
|
102
|
+
* Prompts the user to enter the temperature setting for the selected model.
|
|
103
|
+
*
|
|
104
|
+
* @returns {string} The temperature value as a string.
|
|
105
|
+
*/
|
|
70
106
|
const temperature = await (0, prompts_1.input)({
|
|
71
107
|
message: `Enter the temperature for ${selectedModel} (0.0 - 1.0): [0.2]`,
|
|
72
108
|
default: '0.2',
|
|
@@ -79,6 +115,9 @@ const config = async () => {
|
|
|
79
115
|
},
|
|
80
116
|
});
|
|
81
117
|
const parsedTemperature = parseFloat(temperature);
|
|
118
|
+
/**
|
|
119
|
+
* Constructs the model configuration object.
|
|
120
|
+
*/
|
|
82
121
|
let modelConfig = {
|
|
83
122
|
apiKey,
|
|
84
123
|
primary,
|
|
@@ -88,6 +127,9 @@ const config = async () => {
|
|
|
88
127
|
temperature: parsedTemperature,
|
|
89
128
|
};
|
|
90
129
|
if (provider === 'azureopenai') {
|
|
130
|
+
/**
|
|
131
|
+
* Prompts the user to enter the Azure OpenAI endpoint URL.
|
|
132
|
+
*/
|
|
91
133
|
const endpoint = await (0, prompts_1.input)({
|
|
92
134
|
message: 'Enter the Azure OpenAI endpoint URL:',
|
|
93
135
|
validate: (value) => {
|
|
@@ -110,6 +152,9 @@ const config = async () => {
|
|
|
110
152
|
}
|
|
111
153
|
}
|
|
112
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Prompts the user to decide if they want to configure another model.
|
|
157
|
+
*/
|
|
113
158
|
const anotherModel = await (0, prompts_1.confirm)({
|
|
114
159
|
message: 'Do you want to configure another model?',
|
|
115
160
|
default: true,
|
|
@@ -6,6 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const CommitManager_1 = __importDefault(require("../../managers/CommitManager"));
|
|
7
7
|
const commit = async (options) => {
|
|
8
8
|
const commitManager = new CommitManager_1.default(options);
|
|
9
|
-
await commitManager.
|
|
9
|
+
await commitManager.generateCommit();
|
|
10
10
|
};
|
|
11
11
|
exports.default = commit;
|
|
@@ -0,0 +1,11 @@
|
|
|
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 DocsManager_1 = __importDefault(require("../../managers/DocsManager"));
|
|
7
|
+
const docs = async (options) => {
|
|
8
|
+
const docsManager = new DocsManager_1.default(options);
|
|
9
|
+
await docsManager.generateDocs();
|
|
10
|
+
};
|
|
11
|
+
exports.default = docs;
|
|
@@ -0,0 +1,11 @@
|
|
|
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 DocumentationManager_1 = __importDefault(require("../../managers/DocumentationManager"));
|
|
7
|
+
const documentation = async (options) => {
|
|
8
|
+
const documentationManager = new DocumentationManager_1.default(options);
|
|
9
|
+
await documentationManager.generateDocumentation();
|
|
10
|
+
};
|
|
11
|
+
exports.default = documentation;
|
|
@@ -6,6 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
const ReviewManager_1 = __importDefault(require("../../managers/ReviewManager"));
|
|
7
7
|
const review = async (options) => {
|
|
8
8
|
const reviewManager = new ReviewManager_1.default(options);
|
|
9
|
-
await reviewManager.
|
|
9
|
+
await reviewManager.generateReview();
|
|
10
10
|
};
|
|
11
11
|
exports.default = review;
|
package/dist/commands/tokens.js
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @module tokens
|
|
4
|
+
* This module provides functionality to estimate the number of tokens in the context files
|
|
5
|
+
* and project description for GPT processing.
|
|
6
|
+
*/
|
|
2
7
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
8
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
9
|
};
|
|
@@ -7,10 +12,19 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
7
12
|
const path_1 = __importDefault(require("path"));
|
|
8
13
|
const config_utils_1 = require("../utils/config_utils");
|
|
9
14
|
const prompt_utils_1 = require("../utils/prompt_utils");
|
|
15
|
+
/**
|
|
16
|
+
* Calculates the estimated number of tokens for the given context files and project description.
|
|
17
|
+
* @param {ClovingGPTOptions} options - The options for token calculation, including file paths.
|
|
18
|
+
* @returns {Promise<void>} A promise that resolves when the token estimation is complete.
|
|
19
|
+
*/
|
|
10
20
|
const tokens = async (options) => {
|
|
11
21
|
let contextFiles = {};
|
|
12
22
|
let files = options.files || '.';
|
|
13
23
|
let prompt = '';
|
|
24
|
+
/**
|
|
25
|
+
* Expands the given file paths to include all files in directories.
|
|
26
|
+
* @type {string[]}
|
|
27
|
+
*/
|
|
14
28
|
let expandedFiles = [];
|
|
15
29
|
for (const file of files) {
|
|
16
30
|
const filePath = path_1.default.resolve(file);
|
|
@@ -26,6 +40,9 @@ const tokens = async (options) => {
|
|
|
26
40
|
}
|
|
27
41
|
}
|
|
28
42
|
files = expandedFiles;
|
|
43
|
+
/**
|
|
44
|
+
* Reads the content of each file and stores it in the contextFiles object.
|
|
45
|
+
*/
|
|
29
46
|
for (const file of files) {
|
|
30
47
|
const filePath = path_1.default.resolve(file);
|
|
31
48
|
if (await fs_1.default.promises
|
|
@@ -36,6 +53,9 @@ const tokens = async (options) => {
|
|
|
36
53
|
contextFiles[file] = content;
|
|
37
54
|
}
|
|
38
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Generates the prompt content by combining the app description and context file contents.
|
|
58
|
+
*/
|
|
39
59
|
const contextFileContents = Object.keys(contextFiles)
|
|
40
60
|
.map((file) => `### Contents of ${file}\n\n${contextFiles[file]}\n\n`)
|
|
41
61
|
.join('\n');
|
|
@@ -45,6 +65,10 @@ const tokens = async (options) => {
|
|
|
45
65
|
${JSON.stringify((0, config_utils_1.getClovingConfig)(), null, 2)}
|
|
46
66
|
|
|
47
67
|
${contextFileContents}`;
|
|
68
|
+
/**
|
|
69
|
+
* Estimates the number of tokens based on the prompt length.
|
|
70
|
+
* This is a rough estimation and may not be exact.
|
|
71
|
+
*/
|
|
48
72
|
const tokens = Math.ceil(prompt.length / 4).toLocaleString();
|
|
49
73
|
console.log(`Estimated tokens: ${tokens}`);
|
|
50
74
|
};
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ 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 docs_1 = __importDefault(require("./commands/generate/docs"));
|
|
20
21
|
const prompt_utils_1 = require("./utils/prompt_utils");
|
|
21
22
|
const program = new commander_1.Command();
|
|
22
23
|
program
|
|
@@ -121,4 +122,13 @@ generate
|
|
|
121
122
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
122
123
|
.option('-t, --temperature <temperature>', 'Temperature for the model (default 0.2)')
|
|
123
124
|
.action(review_1.default);
|
|
125
|
+
generate
|
|
126
|
+
.command('docs')
|
|
127
|
+
.alias('d')
|
|
128
|
+
.description('Generate documentation for the project')
|
|
129
|
+
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
130
|
+
.option('-f, --files <filenames...>', 'Specify filenames for files you want to document')
|
|
131
|
+
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
132
|
+
.option('-t, --temperature <temperature>', 'Temperature for the model (default 0.2)')
|
|
133
|
+
.action(docs_1.default);
|
|
124
134
|
program.parse(process.argv);
|
|
@@ -23,7 +23,17 @@ class BlockManager extends events_1.EventEmitter {
|
|
|
23
23
|
content = this.buffer + content;
|
|
24
24
|
this.buffer = '';
|
|
25
25
|
}
|
|
26
|
-
|
|
26
|
+
// if content has multiple \n``` in the string, then we need to split it up
|
|
27
|
+
if (content.includes('\n```')) {
|
|
28
|
+
while (content.includes('\n```')) {
|
|
29
|
+
const index = content.indexOf('\n```');
|
|
30
|
+
this.processCodeBlocks(content.slice(0, index + 4));
|
|
31
|
+
content = content.slice(index + 4);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (content !== '') {
|
|
35
|
+
this.processCodeBlocks(content);
|
|
36
|
+
}
|
|
27
37
|
}
|
|
28
38
|
processCodeBlocks(content) {
|
|
29
39
|
const codeBlockMarker = '\n```';
|
|
@@ -65,18 +75,12 @@ class BlockManager extends events_1.EventEmitter {
|
|
|
65
75
|
emitCodeBlock() {
|
|
66
76
|
if (this.codeBuffer.length > 0) {
|
|
67
77
|
const currentNewBlock = this.parseCodeBuffer();
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.clearBuffer();
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
this.emit('codeBlock', this.codeBuffer);
|
|
78
|
-
this.clearBuffer();
|
|
79
|
-
}
|
|
78
|
+
this.emit('codeBlock', {
|
|
79
|
+
currentNewBlock,
|
|
80
|
+
raw: this.codeBuffer,
|
|
81
|
+
});
|
|
82
|
+
this.emit('content', this.buffer);
|
|
83
|
+
this.clearBuffer();
|
|
80
84
|
}
|
|
81
85
|
}
|
|
82
86
|
/**
|