cloving 0.2.1 → 0.3.1
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 +1 -1
- package/dist/cloving_gpt/adapters/claude.js +7 -4
- package/dist/cloving_gpt/adapters/gemini.js +2 -1
- package/dist/cloving_gpt/adapters/mistral.js +1 -1
- package/dist/cloving_gpt/adapters/openai.js +1 -1
- package/dist/cloving_gpt/index.js +16 -7
- package/dist/commands/config.js +7 -5
- package/dist/commands/generate/code.js +3 -13
- package/dist/commands/generate/commit.js +3 -43
- package/dist/commands/generate/init.js +15 -0
- package/dist/commands/generate/review.js +1 -5
- package/dist/commands/generate/shell.js +3 -103
- package/dist/commands/generate/unit_tests.js +5 -51
- package/dist/commands/init.js +62 -53
- package/dist/file2.js +4 -0
- package/dist/managers/ChatManager.js +438 -128
- package/dist/managers/CodeManager.js +66 -185
- package/dist/managers/CommitManager.js +55 -0
- package/dist/managers/ProxyManager.js +2 -2
- package/dist/managers/ReviewManager.js +28 -23
- package/dist/managers/ShellManager.js +106 -0
- package/dist/newfile.js +2 -0
- package/dist/package.json +11 -10
- package/dist/utils/command_utils.js +195 -20
- package/dist/utils/config_utils.js +9 -0
- package/dist/utils/string_utils.js +222 -60
- package/package.json +11 -10
package/README.md
CHANGED
|
@@ -254,5 +254,5 @@ This project is licensed under the [MIT License](LICENSE).
|
|
|
254
254
|
|
|
255
255
|
## Acknowledgements
|
|
256
256
|
|
|
257
|
-
- This project is inspired by [aichat](https://github.com/sigoden/aichat)
|
|
257
|
+
- This project is inspired by [aichat](https://github.com/sigoden/aichat) and [aider](https://github.com/paul-gauthier/aider)
|
|
258
258
|
- Special thanks to the open-source community for inspiration and support.
|
|
@@ -22,12 +22,15 @@ class ClaudeAdapter {
|
|
|
22
22
|
};
|
|
23
23
|
}
|
|
24
24
|
getPayload(request, stream = false) {
|
|
25
|
+
let system = 'You are a computer programmer giving advice on how to write better code.';
|
|
26
|
+
if (request.messages && request.messages.length > 0 && request.messages[0].role === 'system') {
|
|
27
|
+
system = request.messages[0].content;
|
|
28
|
+
request = { ...request, messages: request.messages.slice(1) };
|
|
29
|
+
}
|
|
25
30
|
return {
|
|
26
31
|
model: this.model.replace(':', '-'),
|
|
27
|
-
system
|
|
28
|
-
messages: [
|
|
29
|
-
{ role: 'user', content: request.prompt }
|
|
30
|
-
],
|
|
32
|
+
system,
|
|
33
|
+
messages: request.messages && request.messages.length > 0 ? request.messages : [{ role: "user", content: request.prompt }],
|
|
31
34
|
max_tokens: request.maxTokens || 4096,
|
|
32
35
|
temperature: request.temperature || 0.2,
|
|
33
36
|
stream
|
|
@@ -28,12 +28,13 @@ class GeminiAdapter {
|
|
|
28
28
|
return {
|
|
29
29
|
contents: [
|
|
30
30
|
{
|
|
31
|
+
role: 'user', // or 'model' if generated from the model
|
|
31
32
|
parts: [
|
|
32
33
|
{
|
|
33
34
|
text: request.prompt
|
|
34
35
|
}
|
|
35
36
|
]
|
|
36
|
-
}
|
|
37
|
+
},
|
|
37
38
|
],
|
|
38
39
|
generationConfig: {
|
|
39
40
|
temperature: request.temperature || 0.2,
|
|
@@ -22,7 +22,7 @@ class MistralAdapter {
|
|
|
22
22
|
getPayload(request, stream = false) {
|
|
23
23
|
return {
|
|
24
24
|
model: this.model.replace(':', '-'),
|
|
25
|
-
messages: [{ role: "user", content: request.prompt }],
|
|
25
|
+
messages: request.messages && request.messages.length > 0 ? request.messages : [{ role: "user", content: request.prompt }],
|
|
26
26
|
max_tokens: request.maxTokens,
|
|
27
27
|
temperature: request.temperature || 0.2,
|
|
28
28
|
stream
|
|
@@ -22,7 +22,7 @@ class OpenAIAdapter {
|
|
|
22
22
|
getPayload(request, stream = false) {
|
|
23
23
|
return {
|
|
24
24
|
model: this.model.replace(':', '-'),
|
|
25
|
-
messages: [{ role: "user", content: request.prompt }],
|
|
25
|
+
messages: request.messages && request.messages.length > 0 ? request.messages : [{ role: "user", content: request.prompt }],
|
|
26
26
|
max_tokens: request.maxTokens,
|
|
27
27
|
temperature: request.temperature || 0.2,
|
|
28
28
|
stream
|
|
@@ -55,18 +55,19 @@ class ClovingGPT {
|
|
|
55
55
|
throw new Error(`Unsupported provider: ${provider}`);
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
-
async reviewPrompt(prompt, endpoint) {
|
|
58
|
+
async reviewPrompt(prompt, messages, endpoint) {
|
|
59
59
|
if (this.silent)
|
|
60
60
|
return prompt;
|
|
61
|
-
const
|
|
61
|
+
const fullPrompt = messages.map(m => m.role === 'user' ? `# Task\n\n${m.content}` : m.content).join('\n\n');
|
|
62
|
+
const tokenCount = Math.ceil(fullPrompt.length / 4).toLocaleString();
|
|
62
63
|
const reviewPrompt = await (0, prompts_1.confirm)({
|
|
63
|
-
message: `Do you want to review
|
|
64
|
+
message: `Do you want to review the ~${tokenCount} token prompt before sending it to ${endpoint}?`,
|
|
64
65
|
default: true
|
|
65
66
|
});
|
|
66
67
|
if (reviewPrompt) {
|
|
67
68
|
const tempFile = path_1.default.join(os_1.default.tmpdir(), `cloving_prompt_${Date.now()}.txt`);
|
|
68
|
-
fs_1.default.writeFileSync(tempFile,
|
|
69
|
-
const editor =
|
|
69
|
+
fs_1.default.writeFileSync(tempFile, fullPrompt);
|
|
70
|
+
const editor = 'less';
|
|
70
71
|
const editProcess = (0, child_process_1.spawn)(editor, [tempFile], { stdio: 'inherit' });
|
|
71
72
|
return new Promise((resolve, reject) => {
|
|
72
73
|
editProcess.on('close', async (code) => {
|
|
@@ -83,6 +84,14 @@ class ClovingGPT {
|
|
|
83
84
|
resolve(null);
|
|
84
85
|
return;
|
|
85
86
|
}
|
|
87
|
+
const confirmPrompt = await (0, prompts_1.confirm)({
|
|
88
|
+
message: `Are you sure you want to continue?`,
|
|
89
|
+
default: true
|
|
90
|
+
});
|
|
91
|
+
if (!confirmPrompt) {
|
|
92
|
+
resolve(null);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
86
95
|
resolve(editedPrompt);
|
|
87
96
|
});
|
|
88
97
|
editProcess.on('error', (err) => {
|
|
@@ -100,7 +109,7 @@ class ClovingGPT {
|
|
|
100
109
|
const endpoint = this.adapter.getEndpoint(this.stream);
|
|
101
110
|
const payload = this.adapter.getPayload(request, this.stream);
|
|
102
111
|
const headers = this.adapter.getHeaders(this.apiKey);
|
|
103
|
-
const reviewedPrompt = await this.reviewPrompt(request.prompt, endpoint);
|
|
112
|
+
const reviewedPrompt = await this.reviewPrompt(request.prompt, request.messages || [], endpoint);
|
|
104
113
|
if (reviewedPrompt === null) {
|
|
105
114
|
throw new Error('Operation cancelled by user');
|
|
106
115
|
}
|
|
@@ -140,7 +149,7 @@ class ClovingGPT {
|
|
|
140
149
|
const endpoint = this.adapter.getEndpoint(this.stream);
|
|
141
150
|
const payload = this.adapter.getPayload(request, this.stream);
|
|
142
151
|
const headers = this.adapter.getHeaders(this.apiKey);
|
|
143
|
-
const reviewedPrompt = await this.reviewPrompt(request.prompt, endpoint);
|
|
152
|
+
const reviewedPrompt = await this.reviewPrompt(request.prompt, request.messages || [], endpoint);
|
|
144
153
|
if (reviewedPrompt === null) {
|
|
145
154
|
throw new Error('Operation cancelled by user');
|
|
146
155
|
}
|
package/dist/commands/config.js
CHANGED
|
@@ -66,23 +66,25 @@ const config = async () => {
|
|
|
66
66
|
message: `Do you trust ${selectedModel} with sensitive information?`,
|
|
67
67
|
default: false,
|
|
68
68
|
});
|
|
69
|
-
const temperature = await (0, prompts_1.
|
|
69
|
+
const temperature = await (0, prompts_1.input)({
|
|
70
70
|
message: `Enter the temperature for ${selectedModel} (0.0 - 1.0): [0.2]`,
|
|
71
|
-
default: 0.2,
|
|
71
|
+
default: '0.2',
|
|
72
72
|
validate: (value) => {
|
|
73
|
-
|
|
73
|
+
const num = parseFloat(value);
|
|
74
|
+
if (isNaN(num) || num < 0 || num > 1) {
|
|
74
75
|
return 'Please enter a valid number between 0.0 and 1.0.';
|
|
75
76
|
}
|
|
76
77
|
return true;
|
|
77
78
|
},
|
|
78
|
-
})
|
|
79
|
+
});
|
|
80
|
+
const parsedTemperature = parseFloat(temperature);
|
|
79
81
|
const modelConfig = {
|
|
80
82
|
apiKey,
|
|
81
83
|
primary,
|
|
82
84
|
priority: parseInt(priority, 10),
|
|
83
85
|
silent: !review,
|
|
84
86
|
trust,
|
|
85
|
-
temperature,
|
|
87
|
+
temperature: parsedTemperature,
|
|
86
88
|
};
|
|
87
89
|
currentConfig.models[provider][model] = modelConfig;
|
|
88
90
|
if (primary) {
|
|
@@ -4,28 +4,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const config_utils_1 = require("../../utils/config_utils");
|
|
7
|
-
const config_utils_2 = require("../../utils/config_utils");
|
|
8
|
-
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
9
7
|
const ChatManager_1 = __importDefault(require("../../managers/ChatManager"));
|
|
10
8
|
const CodeManager_1 = __importDefault(require("../../managers/CodeManager"));
|
|
11
9
|
const code = async (options) => {
|
|
12
|
-
options.silent = (0, config_utils_2.getConfig)(options).globalSilent || false;
|
|
13
|
-
const gpt = new cloving_gpt_1.default(options);
|
|
14
10
|
if (options.interactive) {
|
|
15
|
-
options.silent = (0,
|
|
11
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
16
12
|
options.stream = true;
|
|
17
13
|
const chatManager = new ChatManager_1.default(options);
|
|
18
14
|
await chatManager.initialize();
|
|
19
15
|
}
|
|
20
16
|
else {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
if (options.prompt) {
|
|
24
|
-
await codeManager.processCode(options.prompt);
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
console.error('No prompt provided.');
|
|
28
|
-
}
|
|
17
|
+
const codeManager = new CodeManager_1.default(options);
|
|
18
|
+
await codeManager.initialize();
|
|
29
19
|
}
|
|
30
20
|
};
|
|
31
21
|
exports.default = code;
|
|
@@ -3,49 +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 path_1 = __importDefault(require("path"));
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
|
-
const string_utils_1 = require("../../utils/string_utils");
|
|
10
|
-
const git_utils_1 = require("../../utils/git_utils");
|
|
11
|
-
const config_utils_1 = require("../../utils/config_utils");
|
|
12
|
-
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
6
|
+
const CommitManager_1 = __importDefault(require("../../managers/CommitManager"));
|
|
13
7
|
const commit = async (options) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// Get the git diff
|
|
18
|
-
const diff = (0, child_process_1.execSync)('git diff HEAD').toString().trim();
|
|
19
|
-
// Check if the diff is blank
|
|
20
|
-
if (!diff) {
|
|
21
|
-
console.error('No changes to commit.');
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
// Generate the prompt for commit message
|
|
25
|
-
const prompt = (0, git_utils_1.generateCommitMessagePrompt)(diff);
|
|
26
|
-
// Instantiate ClovingGPT and get the commit message
|
|
27
|
-
const rawCommitMessage = await gpt.generateText({ prompt });
|
|
28
|
-
// Clean the commit message using extractMarkdown
|
|
29
|
-
const commitMessage = (0, string_utils_1.extractMarkdown)(rawCommitMessage);
|
|
30
|
-
// Write the commit message to a temporary file
|
|
31
|
-
const tempCommitFilePath = path_1.default.join('.git', 'SUGGESTED_COMMIT_EDITMSG');
|
|
32
|
-
fs_1.default.writeFileSync(tempCommitFilePath, commitMessage);
|
|
33
|
-
// Commit the changes using the generated commit message
|
|
34
|
-
try {
|
|
35
|
-
(0, child_process_1.execFileSync)('git', ['commit', '-a', '--edit', '--file', tempCommitFilePath], { stdio: 'inherit' });
|
|
36
|
-
}
|
|
37
|
-
catch (commitError) {
|
|
38
|
-
// If commit is canceled (non-zero exit), handle it here
|
|
39
|
-
console.log('Commit was canceled or failed.');
|
|
40
|
-
}
|
|
41
|
-
// Remove the temporary file using fs
|
|
42
|
-
fs_1.default.unlink(tempCommitFilePath, (err) => {
|
|
43
|
-
if (err)
|
|
44
|
-
throw err;
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
console.error('Could not generate commit message:', error);
|
|
49
|
-
}
|
|
8
|
+
const commitManager = new CommitManager_1.default(options);
|
|
9
|
+
await commitManager.commit();
|
|
50
10
|
};
|
|
51
11
|
exports.default = commit;
|
|
@@ -0,0 +1,15 @@
|
|
|
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 cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
7
|
+
const config_utils_1 = require("../../utils/config_utils");
|
|
8
|
+
class InitCommand {
|
|
9
|
+
constructor(options) {
|
|
10
|
+
this.options = options;
|
|
11
|
+
this.chatHistory = [];
|
|
12
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
13
|
+
this.gpt = new cloving_gpt_1.default(options);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -3,13 +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 cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
7
6
|
const ReviewManager_1 = __importDefault(require("../../managers/ReviewManager"));
|
|
8
|
-
const config_utils_1 = require("../../utils/config_utils");
|
|
9
7
|
const review = async (options) => {
|
|
10
|
-
|
|
11
|
-
const gpt = new cloving_gpt_1.default(options);
|
|
12
|
-
const reviewManager = new ReviewManager_1.default(gpt, options);
|
|
8
|
+
const reviewManager = new ReviewManager_1.default(options);
|
|
13
9
|
await reviewManager.review();
|
|
14
10
|
};
|
|
15
11
|
exports.default = review;
|
|
@@ -3,109 +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 cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
8
|
-
const copy_paste_1 = __importDefault(require("copy-paste"));
|
|
9
|
-
const string_utils_1 = require("../../utils/string_utils");
|
|
10
|
-
const config_utils_1 = require("../../utils/config_utils");
|
|
11
|
-
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
12
|
-
const prompts_1 = require("@inquirer/prompts");
|
|
13
|
-
const generateShellPrompt = (prompt) => {
|
|
14
|
-
const shell = (0, child_process_1.execSync)('echo $SHELL').toString().trim();
|
|
15
|
-
const os = (0, child_process_1.execSync)('echo $OSTYPE').toString().trim();
|
|
16
|
-
return `Generate an executable ${shell} script that works on ${os}. Try to make it a single line if possible and as simple and straightforward as possible.
|
|
17
|
-
|
|
18
|
-
Do not add any commentary or context to the message other than the commit message itself.
|
|
19
|
-
|
|
20
|
-
An example of the output for this should look like the following:
|
|
21
|
-
|
|
22
|
-
\`\`\`sh
|
|
23
|
-
find . -type f -name "*.ts" -exec sed -i '' 's/old/new/g' {} +
|
|
24
|
-
\`\`\`
|
|
25
|
-
|
|
26
|
-
Don't use that script, it is only an example.
|
|
27
|
-
|
|
28
|
-
Here is the description of what I want the script to do:
|
|
29
|
-
|
|
30
|
-
${prompt}`;
|
|
31
|
-
};
|
|
32
|
-
const generateExplainShellPrompt = (prompt) => {
|
|
33
|
-
return `${prompt}
|
|
34
|
-
|
|
35
|
-
## Task
|
|
36
|
-
|
|
37
|
-
Please briefly explain how this shell script works.`;
|
|
38
|
-
};
|
|
39
|
-
const generateShell = async (gpt, prompt) => {
|
|
40
|
-
const shellPrompt = generateShellPrompt(prompt);
|
|
41
|
-
return await gpt.generateText({ prompt: shellPrompt });
|
|
42
|
-
};
|
|
43
|
-
const displayGeneratedShell = (rawShellCommand) => {
|
|
44
|
-
const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
|
|
45
|
-
const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
|
|
46
|
-
console.log((0, cli_highlight_1.default)(generatedShellWithoutShebang));
|
|
47
|
-
};
|
|
48
|
-
const handleUserAction = async (gpt, rawShellCommand, prompt) => {
|
|
49
|
-
const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
|
|
50
|
-
const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
|
|
51
|
-
const action = await (0, prompts_1.select)({
|
|
52
|
-
message: 'What would you like to do?',
|
|
53
|
-
choices: [
|
|
54
|
-
{ name: 'Execute', value: 'execute' },
|
|
55
|
-
{ name: 'Revise', value: 'revise' },
|
|
56
|
-
{ name: 'Explain', value: 'explain' },
|
|
57
|
-
{ name: 'Copy to Clipboard', value: 'copy' },
|
|
58
|
-
{ name: 'Cancel', value: 'cancel' },
|
|
59
|
-
],
|
|
60
|
-
});
|
|
61
|
-
switch (action) {
|
|
62
|
-
case 'execute':
|
|
63
|
-
(0, child_process_1.execSync)(generatedShellWithoutShebang, { stdio: 'inherit' });
|
|
64
|
-
break;
|
|
65
|
-
case 'revise':
|
|
66
|
-
const newPrompt = await (0, prompts_1.input)({
|
|
67
|
-
message: 'How would you like to modify the output:',
|
|
68
|
-
});
|
|
69
|
-
const newRawShellCommand = await generateShell(gpt, newPrompt);
|
|
70
|
-
displayGeneratedShell(newRawShellCommand);
|
|
71
|
-
await handleUserAction(gpt, newRawShellCommand, newPrompt);
|
|
72
|
-
break;
|
|
73
|
-
case 'explain':
|
|
74
|
-
const explainPrompt = generateExplainShellPrompt(generatedShellWithoutShebang);
|
|
75
|
-
const explainShellCommand = await gpt.generateText({ prompt: explainPrompt });
|
|
76
|
-
console.log((0, cli_highlight_1.default)(explainShellCommand, { language: 'markdown' }));
|
|
77
|
-
break;
|
|
78
|
-
case 'copy':
|
|
79
|
-
copy_paste_1.default.copy(generatedShellWithoutShebang, (err) => {
|
|
80
|
-
if (err) {
|
|
81
|
-
console.error('Error: Unable to copy to clipboard.', err);
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
console.log('Script copied to clipboard.');
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
break;
|
|
88
|
-
case 'cancel':
|
|
89
|
-
console.log('Operation cancelled.');
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
};
|
|
6
|
+
const ShellManager_1 = __importDefault(require("../../managers/ShellManager"));
|
|
93
7
|
const shell = async (options) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const gpt = new cloving_gpt_1.default(options);
|
|
97
|
-
try {
|
|
98
|
-
if (!userPrompt) {
|
|
99
|
-
userPrompt = await (0, prompts_1.input)({
|
|
100
|
-
message: 'What would you like to do: '
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
const rawShellCommand = await generateShell(gpt, userPrompt);
|
|
104
|
-
displayGeneratedShell(rawShellCommand);
|
|
105
|
-
await handleUserAction(gpt, rawShellCommand, userPrompt);
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
console.error('Could not generate shell script', error);
|
|
109
|
-
}
|
|
8
|
+
const shellManager = new ShellManager_1.default(options);
|
|
9
|
+
await shellManager.generateAndHandleShell();
|
|
110
10
|
};
|
|
111
11
|
exports.default = shell;
|
|
@@ -7,7 +7,6 @@ const fs_1 = require("fs");
|
|
|
7
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
|
-
const path_1 = __importDefault(require("path"));
|
|
11
10
|
const git_utils_1 = require("../../utils/git_utils");
|
|
12
11
|
const config_utils_1 = require("../../utils/config_utils");
|
|
13
12
|
const string_utils_1 = require("../../utils/string_utils");
|
|
@@ -64,29 +63,18 @@ Enumerate all the files in the provided list${gitDiff ? ' and git diff' : ''} as
|
|
|
64
63
|
Also, list any test files that might be relevant to these files.`;
|
|
65
64
|
};
|
|
66
65
|
const handleUserAction = async (analysis, autoSave = false) => {
|
|
67
|
-
const
|
|
68
|
-
const files = Object.keys(fileContents);
|
|
66
|
+
const blocks = (0, string_utils_1.extractCurrentNewBlocks)(analysis);
|
|
69
67
|
if (autoSave) {
|
|
70
|
-
|
|
71
|
-
if (fileContents[file]) {
|
|
72
|
-
const filePath = path_1.default.resolve(file);
|
|
73
|
-
await fs_1.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
74
|
-
await fs_1.promises.writeFile(filePath, fileContents[file]);
|
|
75
|
-
console.log(`${file} has been saved.`);
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
console.log(`File content not found for ${file}.`);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
68
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
81
69
|
console.log('All unit test files have been saved.');
|
|
82
70
|
return;
|
|
83
71
|
}
|
|
72
|
+
const files = Array.from(new Set(blocks.map(block => block.filePath)));
|
|
84
73
|
const action = await (0, prompts_1.select)({
|
|
85
74
|
message: 'What would you like to do?',
|
|
86
75
|
choices: [
|
|
87
76
|
{ name: 'Save a Unit Test File', value: 'save' },
|
|
88
77
|
{ name: 'Save All Unit Test Files', value: 'saveAll' },
|
|
89
|
-
{ name: 'Copy Unit Test to Clipboard', value: 'copyTest' },
|
|
90
78
|
{ name: 'Copy Entire Response to Clipboard', value: 'copyAll' },
|
|
91
79
|
{ name: 'Done', value: 'done' },
|
|
92
80
|
],
|
|
@@ -99,15 +87,7 @@ const handleUserAction = async (analysis, autoSave = false) => {
|
|
|
99
87
|
message: 'Which unit test file do you want to save?',
|
|
100
88
|
choices: files.map(file => ({ name: file, value: file })),
|
|
101
89
|
});
|
|
102
|
-
|
|
103
|
-
const filePath = path_1.default.resolve(fileToSave);
|
|
104
|
-
await fs_1.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
105
|
-
await fs_1.promises.writeFile(filePath, fileContents[fileToSave]);
|
|
106
|
-
console.log(`${fileToSave} has been saved.`);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
console.log('File content not found.');
|
|
110
|
-
}
|
|
90
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks.filter(block => block.filePath === fileToSave));
|
|
111
91
|
saveAnother = await (0, prompts_1.confirm)({
|
|
112
92
|
message: 'Do you want to save another file?',
|
|
113
93
|
default: false,
|
|
@@ -115,35 +95,9 @@ const handleUserAction = async (analysis, autoSave = false) => {
|
|
|
115
95
|
}
|
|
116
96
|
break;
|
|
117
97
|
case 'saveAll':
|
|
118
|
-
|
|
119
|
-
if (fileContents[file]) {
|
|
120
|
-
const filePath = path_1.default.resolve(file);
|
|
121
|
-
await fs_1.promises.mkdir(path_1.default.dirname(filePath), { recursive: true });
|
|
122
|
-
await fs_1.promises.writeFile(filePath, fileContents[file]);
|
|
123
|
-
console.log(`${file} has been saved.`);
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
console.log(`File content not found for ${file}.`);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
98
|
+
await (0, string_utils_1.applyAndSaveCurrentNewBlocks)(blocks);
|
|
129
99
|
console.log('All unit test files have been saved.');
|
|
130
100
|
break;
|
|
131
|
-
case 'copyTest':
|
|
132
|
-
const fileToCopy = await (0, prompts_1.select)({
|
|
133
|
-
message: 'Which unit test file do you want to copy to the clipboard?',
|
|
134
|
-
choices: files.map(file => ({ name: file, value: file })),
|
|
135
|
-
});
|
|
136
|
-
if (fileContents[fileToCopy]) {
|
|
137
|
-
process.nextTick(() => {
|
|
138
|
-
require('copy-paste').copy(fileContents[fileToCopy], () => {
|
|
139
|
-
console.log(`${fileToCopy} copied to clipboard`);
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
console.log('File content not found.');
|
|
145
|
-
}
|
|
146
|
-
break;
|
|
147
101
|
case 'copyAll':
|
|
148
102
|
process.nextTick(() => {
|
|
149
103
|
require('copy-paste').copy(analysis, () => {
|
package/dist/commands/init.js
CHANGED
|
@@ -19,56 +19,11 @@ const init = async (options) => {
|
|
|
19
19
|
const gpt = new cloving_gpt_1.default(options);
|
|
20
20
|
const specialFileContents = (0, command_utils_1.collectSpecialFileContents)();
|
|
21
21
|
const specialFileNames = Object.keys(specialFileContents).map(file => ' - ' + file);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
Cloving will send AI a request to summarize the technologies used in this project.
|
|
29
|
-
|
|
30
|
-
This will provide better context for future Cloving requests.`);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
console.log(`
|
|
34
|
-
This script will analyze the list of files in the current directory using GPT to summarize the
|
|
35
|
-
technologies used. This will provide better context for future Cloving requests.
|
|
36
|
-
`);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
const config = (0, config_utils_1.getConfig)(options);
|
|
40
|
-
if (!config || !config?.models) {
|
|
41
|
-
console.error('No cloving configuration found. Please run `cloving config`');
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
if (!(0, command_utils_1.checkForSpecialFiles)()) {
|
|
45
|
-
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.');
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const tempFilePath = path_1.default.join(os_1.default.tmpdir(), `describe_${Date.now()}.tmp`);
|
|
49
|
-
try {
|
|
50
|
-
const gitignorePath = path_1.default.join(process.cwd(), '.gitignore');
|
|
51
|
-
const ig = (0, ignore_1.default)();
|
|
52
|
-
if (fs_1.default.existsSync(gitignorePath)) {
|
|
53
|
-
const gitignoreContent = fs_1.default.readFileSync(gitignorePath, 'utf-8');
|
|
54
|
-
ig.add(gitignoreContent);
|
|
55
|
-
}
|
|
56
|
-
const fileList = await (0, command_utils_1.generateFileList)();
|
|
57
|
-
const filteredFileList = fileList.filter(file => {
|
|
58
|
-
try {
|
|
59
|
-
return !ig.ignores(file);
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
return false;
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
const limitedFileList = filteredFileList.slice(0, 100);
|
|
66
|
-
const projectDetails = {
|
|
67
|
-
files: limitedFileList,
|
|
68
|
-
specialFiles: specialFileContents
|
|
69
|
-
};
|
|
70
|
-
const prompt = `Here is a JSON object describing my project:
|
|
71
|
-
${JSON.stringify(projectDetails, null, 2)}
|
|
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.
|
|
72
27
|
|
|
73
28
|
Please return JSON-formatted metadata about the project, including:
|
|
74
29
|
|
|
@@ -191,13 +146,67 @@ Here is an example response:
|
|
|
191
146
|
}
|
|
192
147
|
],
|
|
193
148
|
"projectType": "Command-line tool",
|
|
194
|
-
}
|
|
195
|
-
|
|
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 });
|
|
196
205
|
const cleanAiChatResponse = (0, string_utils_1.extractJsonMetadata)(aiChatResponse);
|
|
197
206
|
fs_1.default.writeFileSync(tempFilePath, cleanAiChatResponse);
|
|
198
207
|
// Save the AI chat response to cloving.json
|
|
199
208
|
fs_1.default.writeFileSync('cloving.json', cleanAiChatResponse);
|
|
200
|
-
console.log('
|
|
209
|
+
console.log('Project data saved to cloving.json');
|
|
201
210
|
// Prompt the user if they want to review the generated cloving.json
|
|
202
211
|
if (!options.silent) {
|
|
203
212
|
const reviewAnswer = await (0, prompts_1.confirm)({
|
package/dist/file2.js
ADDED