cloving 0.1.7 → 0.1.9
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 +0 -2
- package/dist/cloving_gpt/adapters/claude.js +5 -5
- package/dist/cloving_gpt/adapters/openai.js +5 -5
- package/dist/cloving_gpt/index.js +48 -56
- package/dist/commands/config.js +92 -23
- package/dist/commands/generate/code.js +187 -0
- package/dist/commands/generate/commit.js +30 -5
- package/dist/commands/generate/review.js +10 -3
- package/dist/commands/generate/sh.js +95 -0
- package/dist/commands/generate/shell.js +101 -0
- package/dist/commands/init.js +20 -8
- package/dist/commands/project/build.js +13 -11
- package/dist/commands/project/init.js +13 -3
- package/dist/index.js +41 -4
- package/dist/package.json +71 -0
- package/dist/utils/command_utils.js +11 -15
- package/dist/utils/config_utils.js +5 -5
- package/dist/utils/git_utils.js +1 -22
- package/dist/utils/string_utils.js +12 -17
- package/package.json +5 -2
|
@@ -0,0 +1,95 @@
|
|
|
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 inquirer_1 = __importDefault(require("inquirer"));
|
|
7
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const string_utils_1 = require("../../utils/string_utils");
|
|
10
|
+
const command_utils_1 = require("../../utils/command_utils");
|
|
11
|
+
const config_utils_1 = require("../../utils/config_utils");
|
|
12
|
+
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
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
|
+
Please briefly explain how this shell script works.`;
|
|
36
|
+
};
|
|
37
|
+
const sh = async (options) => {
|
|
38
|
+
let { prompt } = options;
|
|
39
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
40
|
+
const gpt = new cloving_gpt_1.default(options);
|
|
41
|
+
try {
|
|
42
|
+
if (!prompt) {
|
|
43
|
+
prompt = await (0, command_utils_1.promptUser)('What would you like to do: ');
|
|
44
|
+
}
|
|
45
|
+
// Generate the prompt for commit message
|
|
46
|
+
const shellPrompt = generateShellPrompt(prompt);
|
|
47
|
+
// Instantiate ClovingGPT and get the commit message
|
|
48
|
+
const rawShellCommand = await gpt.generateText({ prompt: shellPrompt });
|
|
49
|
+
// Clean the commit message using extractMarkdown
|
|
50
|
+
const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
|
|
51
|
+
// remove #! from the generated shell script
|
|
52
|
+
const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
|
|
53
|
+
console.log((0, cli_highlight_1.default)(generatedShellWithoutShebang));
|
|
54
|
+
// Inquirer prompt for further actions
|
|
55
|
+
const { action } = await inquirer_1.default.prompt([
|
|
56
|
+
{
|
|
57
|
+
type: 'list',
|
|
58
|
+
name: 'action',
|
|
59
|
+
message: 'What would you like to do?',
|
|
60
|
+
choices: [
|
|
61
|
+
{ name: 'Execute', value: 'execute' },
|
|
62
|
+
{ name: 'Revise', value: 'revise' },
|
|
63
|
+
{ name: 'Explain', value: 'explain' },
|
|
64
|
+
{ name: 'Copy to Clipboard', value: 'copy' },
|
|
65
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
]);
|
|
69
|
+
switch (action) {
|
|
70
|
+
case 'execute':
|
|
71
|
+
(0, child_process_1.execSync)(generatedShellWithoutShebang, { stdio: 'inherit' });
|
|
72
|
+
break;
|
|
73
|
+
case 'revise':
|
|
74
|
+
// Logic to revise the prompt (not implemented in this example)
|
|
75
|
+
console.log('Revise option selected. Implement revision logic here.');
|
|
76
|
+
break;
|
|
77
|
+
case 'explain':
|
|
78
|
+
const explainPrompt = generateExplainShellPrompt(generatedShellWithoutShebang);
|
|
79
|
+
const explainShellCommand = await gpt.generateText({ prompt: explainPrompt });
|
|
80
|
+
console.log((0, cli_highlight_1.default)(explainShellCommand, { language: 'markdown' }));
|
|
81
|
+
break;
|
|
82
|
+
case 'copy':
|
|
83
|
+
(0, child_process_1.execFileSync)('pbcopy', { input: generatedShellWithoutShebang });
|
|
84
|
+
console.log('Script copied to clipboard.');
|
|
85
|
+
break;
|
|
86
|
+
case 'cancel':
|
|
87
|
+
console.log('Operation cancelled.');
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.error('Could not generate shell script');
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
exports.default = sh;
|
|
@@ -0,0 +1,101 @@
|
|
|
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 inquirer_1 = __importDefault(require("inquirer"));
|
|
7
|
+
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
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 generateShellPrompt = (prompt) => {
|
|
13
|
+
const shell = (0, child_process_1.execSync)('echo $SHELL').toString().trim();
|
|
14
|
+
const os = (0, child_process_1.execSync)('echo $OSTYPE').toString().trim();
|
|
15
|
+
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.
|
|
16
|
+
|
|
17
|
+
Do not add any commentary or context to the message other than the commit message itself.
|
|
18
|
+
|
|
19
|
+
An example of the output for this should look like the following:
|
|
20
|
+
|
|
21
|
+
\`\`\`sh
|
|
22
|
+
find . -type f -name "*.ts" -exec sed -i '' 's/old/new/g' {} +
|
|
23
|
+
\`\`\`
|
|
24
|
+
|
|
25
|
+
Don't use that script, it is only an example.
|
|
26
|
+
|
|
27
|
+
Here is the description of what I want the script to do:
|
|
28
|
+
|
|
29
|
+
${prompt}`;
|
|
30
|
+
};
|
|
31
|
+
const generateExplainShellPrompt = (prompt) => {
|
|
32
|
+
return `${prompt}
|
|
33
|
+
|
|
34
|
+
Please briefly explain how this shell script works.`;
|
|
35
|
+
};
|
|
36
|
+
const shell = async (options) => {
|
|
37
|
+
let { prompt } = options;
|
|
38
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
39
|
+
const gpt = new cloving_gpt_1.default(options);
|
|
40
|
+
try {
|
|
41
|
+
if (!prompt) {
|
|
42
|
+
const { userPrompt } = await inquirer_1.default.prompt([
|
|
43
|
+
{
|
|
44
|
+
type: 'input',
|
|
45
|
+
name: 'userPrompt',
|
|
46
|
+
message: 'What would you like to do: '
|
|
47
|
+
}
|
|
48
|
+
]);
|
|
49
|
+
prompt = userPrompt;
|
|
50
|
+
}
|
|
51
|
+
// Generate the prompt for commit message
|
|
52
|
+
const shellPrompt = generateShellPrompt(prompt);
|
|
53
|
+
// Instantiate ClovingGPT and get the commit message
|
|
54
|
+
const rawShellCommand = await gpt.generateText({ prompt: shellPrompt });
|
|
55
|
+
// Clean the commit message using extractMarkdown
|
|
56
|
+
const generatedShell = (0, string_utils_1.extractMarkdown)(rawShellCommand);
|
|
57
|
+
// remove #! from the generated shell script
|
|
58
|
+
const generatedShellWithoutShebang = generatedShell.replace(/^#!.*?\s/, '');
|
|
59
|
+
console.log((0, cli_highlight_1.default)(generatedShellWithoutShebang));
|
|
60
|
+
// Inquirer prompt for further actions
|
|
61
|
+
const { action } = await inquirer_1.default.prompt([
|
|
62
|
+
{
|
|
63
|
+
type: 'list',
|
|
64
|
+
name: 'action',
|
|
65
|
+
message: 'What would you like to do?',
|
|
66
|
+
choices: [
|
|
67
|
+
{ name: 'Execute', value: 'execute' },
|
|
68
|
+
{ name: 'Revise', value: 'revise' },
|
|
69
|
+
{ name: 'Explain', value: 'explain' },
|
|
70
|
+
{ name: 'Copy to Clipboard', value: 'copy' },
|
|
71
|
+
{ name: 'Cancel', value: 'cancel' },
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
]);
|
|
75
|
+
switch (action) {
|
|
76
|
+
case 'execute':
|
|
77
|
+
(0, child_process_1.execSync)(generatedShellWithoutShebang, { stdio: 'inherit' });
|
|
78
|
+
break;
|
|
79
|
+
case 'revise':
|
|
80
|
+
// Logic to revise the prompt (not implemented in this example)
|
|
81
|
+
console.log('Revise option selected. Implement revision logic here.');
|
|
82
|
+
break;
|
|
83
|
+
case 'explain':
|
|
84
|
+
const explainPrompt = generateExplainShellPrompt(generatedShellWithoutShebang);
|
|
85
|
+
const explainShellCommand = await gpt.generateText({ prompt: explainPrompt });
|
|
86
|
+
console.log((0, cli_highlight_1.default)(explainShellCommand, { language: 'markdown' }));
|
|
87
|
+
break;
|
|
88
|
+
case 'copy':
|
|
89
|
+
(0, child_process_1.execFileSync)('pbcopy', { input: generatedShellWithoutShebang });
|
|
90
|
+
console.log('Script copied to clipboard.');
|
|
91
|
+
break;
|
|
92
|
+
case 'cancel':
|
|
93
|
+
console.log('Operation cancelled.');
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
console.error('Could not generate shell script');
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
exports.default = shell;
|
package/dist/commands/init.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.init = void 0;
|
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const os_1 = __importDefault(require("os"));
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
10
11
|
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
11
12
|
const ignore_1 = __importDefault(require("ignore"));
|
|
12
13
|
const string_utils_1 = require("../utils/string_utils");
|
|
@@ -26,10 +27,7 @@ ${specialFileNames.join("\n")}
|
|
|
26
27
|
|
|
27
28
|
Cloving will send AI a request to summarize the technologies used in this project.
|
|
28
29
|
|
|
29
|
-
This will provide better context for future Cloving requests
|
|
30
|
-
|
|
31
|
-
For increased privacy, you can run \`cloving config\` and make sure to configure a local ollama model (llama3:70b-instruct currently works well for this) so that this data is not sent to an AI service provider.
|
|
32
|
-
`);
|
|
30
|
+
This will provide better context for future Cloving requests.`);
|
|
33
31
|
}
|
|
34
32
|
else {
|
|
35
33
|
console.log(`
|
|
@@ -44,8 +42,15 @@ technologies used. This will provide better context for future Cloving requests.
|
|
|
44
42
|
return;
|
|
45
43
|
}
|
|
46
44
|
if (!(0, command_utils_1.checkForSpecialFiles)()) {
|
|
47
|
-
const continueAnswer = await
|
|
48
|
-
|
|
45
|
+
const { continueAnswer } = await inquirer_1.default.prompt([
|
|
46
|
+
{
|
|
47
|
+
type: 'confirm',
|
|
48
|
+
name: 'continueAnswer',
|
|
49
|
+
message: 'No special files detected. Are you currently inside a software project\'s main directory? Do you want to continue analyzing this directory for the Cloving setup process?',
|
|
50
|
+
default: true,
|
|
51
|
+
},
|
|
52
|
+
]);
|
|
53
|
+
if (!continueAnswer) {
|
|
49
54
|
console.log('Operation aborted by the user.');
|
|
50
55
|
return;
|
|
51
56
|
}
|
|
@@ -209,8 +214,15 @@ Here is an example response:
|
|
|
209
214
|
console.log('[done] Project data saved to cloving.json');
|
|
210
215
|
// Prompt the user if they want to review the generated cloving.json
|
|
211
216
|
if (!options.silent) {
|
|
212
|
-
const reviewAnswer = await
|
|
213
|
-
|
|
217
|
+
const { reviewAnswer } = await inquirer_1.default.prompt([
|
|
218
|
+
{
|
|
219
|
+
type: 'confirm',
|
|
220
|
+
name: 'reviewAnswer',
|
|
221
|
+
message: 'Do you want to review the generated data?',
|
|
222
|
+
default: true,
|
|
223
|
+
},
|
|
224
|
+
]);
|
|
225
|
+
if (reviewAnswer) {
|
|
214
226
|
console.log(cleanAiChatResponse);
|
|
215
227
|
}
|
|
216
228
|
}
|
|
@@ -4,15 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.buildProject = void 0;
|
|
7
|
+
const copy_paste_1 = __importDefault(require("copy-paste"));
|
|
7
8
|
const fs_1 = require("fs");
|
|
8
|
-
const child_process_1 = require("child_process");
|
|
9
9
|
const cli_highlight_1 = __importDefault(require("cli-highlight"));
|
|
10
10
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
11
11
|
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
12
12
|
const config_utils_1 = require("../../utils/config_utils");
|
|
13
13
|
const git_utils_1 = require("../../utils/git_utils");
|
|
14
14
|
const string_utils_1 = require("../../utils/string_utils");
|
|
15
|
-
const command_utils_1 = require("../../utils/command_utils");
|
|
16
15
|
const generatePrompt = async (projectName, projectTask, filesList, incompletePlanItem) => {
|
|
17
16
|
const context = [];
|
|
18
17
|
for (const codeFile of filesList) {
|
|
@@ -72,16 +71,19 @@ const buildProject = async (options) => {
|
|
|
72
71
|
console.log((0, cli_highlight_1.default)(code, { language: 'markdown' }));
|
|
73
72
|
}
|
|
74
73
|
});
|
|
75
|
-
// Prompt the user to copy the project to the clipboard
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
// Prompt the user to copy the project to the clipboard using inquirer
|
|
75
|
+
const { copyToClipboard } = await inquirer_1.default.prompt([
|
|
76
|
+
{
|
|
77
|
+
type: 'confirm',
|
|
78
|
+
name: 'copyToClipboard',
|
|
79
|
+
message: 'Do you want to copy this project to the clipboard?',
|
|
80
|
+
default: true,
|
|
81
|
+
},
|
|
82
|
+
]);
|
|
83
|
+
if (copyToClipboard) {
|
|
84
|
+
copy_paste_1.default.copy(projectCode, () => {
|
|
80
85
|
console.log('Project copied to clipboard');
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
console.error('Error: pbcopy command not found. Unable to copy to clipboard.');
|
|
84
|
-
}
|
|
86
|
+
});
|
|
85
87
|
}
|
|
86
88
|
};
|
|
87
89
|
exports.buildProject = buildProject;
|
|
@@ -5,14 +5,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.initProject = void 0;
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
|
+
const inquirer_1 = __importDefault(require("inquirer"));
|
|
8
9
|
const cloving_gpt_1 = __importDefault(require("../../cloving_gpt"));
|
|
9
10
|
const config_utils_1 = require("../../utils/config_utils");
|
|
10
|
-
const command_utils_1 = require("../../utils/command_utils");
|
|
11
11
|
const git_utils_1 = require("../../utils/git_utils");
|
|
12
12
|
const config_utils_2 = require("../../utils/config_utils");
|
|
13
13
|
const generatePrompt = async (projectName, projectTask) => {
|
|
14
14
|
const filesList = await (0, config_utils_2.getAllFiles)({}, false);
|
|
15
|
-
return `Here is a
|
|
15
|
+
return `Here is a description of my app:
|
|
16
|
+
|
|
17
|
+
${JSON.stringify((0, config_utils_2.getClovingConfig)(), null, 2)}
|
|
18
|
+
|
|
19
|
+
Here is a list of all my source files:
|
|
16
20
|
|
|
17
21
|
==== begin list of source files ====
|
|
18
22
|
${filesList.join("\n")}
|
|
@@ -48,7 +52,13 @@ const initProject = async (options) => {
|
|
|
48
52
|
console.log(`You are on the ${defaultBranchName} branch. Please checkout to a git branch and try again. For example: git branch -b my-new-project`);
|
|
49
53
|
process.exit(1);
|
|
50
54
|
}
|
|
51
|
-
const projectTask = await
|
|
55
|
+
const { projectTask } = await inquirer_1.default.prompt([
|
|
56
|
+
{
|
|
57
|
+
type: 'input',
|
|
58
|
+
name: 'projectTask',
|
|
59
|
+
message: 'Describe the task you want to accomplish with this project:',
|
|
60
|
+
},
|
|
61
|
+
]);
|
|
52
62
|
const prompt = await generatePrompt(projectName, projectTask);
|
|
53
63
|
const contextFiles = await gpt.generateText({ prompt });
|
|
54
64
|
// Initialize variables
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const commander_1 = require("commander");
|
|
8
|
+
const fs_1 = require("fs");
|
|
9
|
+
const path_1 = require("path");
|
|
8
10
|
const config_1 = __importDefault(require("./commands/config"));
|
|
9
11
|
const init_1 = __importDefault(require("./commands/init"));
|
|
10
12
|
const models_1 = __importDefault(require("./commands/models"));
|
|
13
|
+
const shell_1 = __importDefault(require("./commands/generate/shell"));
|
|
14
|
+
const code_1 = __importDefault(require("./commands/generate/code"));
|
|
11
15
|
const commit_1 = __importDefault(require("./commands/generate/commit"));
|
|
12
16
|
const unit_tests_1 = __importDefault(require("./commands/generate/unit_tests"));
|
|
13
17
|
const review_1 = __importDefault(require("./commands/generate/review"));
|
|
@@ -15,11 +19,17 @@ const init_2 = __importDefault(require("./commands/project/init"));
|
|
|
15
19
|
const plan_1 = __importDefault(require("./commands/project/plan"));
|
|
16
20
|
const build_1 = __importDefault(require("./commands/project/build"));
|
|
17
21
|
const complete_1 = __importDefault(require("./commands/project/complete"));
|
|
22
|
+
// Function to get version from package.json
|
|
23
|
+
const getPackageVersion = () => {
|
|
24
|
+
const packagePath = (0, path_1.join)(__dirname, 'package.json');
|
|
25
|
+
const packageJson = JSON.parse((0, fs_1.readFileSync)(packagePath, 'utf8'));
|
|
26
|
+
return packageJson.version;
|
|
27
|
+
};
|
|
18
28
|
const program = new commander_1.Command();
|
|
19
29
|
program
|
|
20
30
|
.name('cloving')
|
|
21
31
|
.description('Integrate AI into your development workflow for generating commit messages, code reviews, and unit tests.')
|
|
22
|
-
.version(
|
|
32
|
+
.version(getPackageVersion());
|
|
23
33
|
program
|
|
24
34
|
.command('config')
|
|
25
35
|
.description('Configure cloving with your API key and models to use')
|
|
@@ -32,10 +42,12 @@ program
|
|
|
32
42
|
.action(init_1.default);
|
|
33
43
|
program
|
|
34
44
|
.command('models')
|
|
45
|
+
.alias('m')
|
|
35
46
|
.description('List available models')
|
|
36
47
|
.action(models_1.default);
|
|
37
48
|
program
|
|
38
49
|
.command('commit')
|
|
50
|
+
.alias('c')
|
|
39
51
|
.description('Alias for cloving generate commit')
|
|
40
52
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
41
53
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
@@ -43,7 +55,25 @@ program
|
|
|
43
55
|
// Generate commands
|
|
44
56
|
const generate = program
|
|
45
57
|
.command('generate')
|
|
58
|
+
.alias('g')
|
|
46
59
|
.description('Generate various items like unit-tests and code reviews');
|
|
60
|
+
generate
|
|
61
|
+
.command('shell')
|
|
62
|
+
.alias('s')
|
|
63
|
+
.description('Generate a shell command based on a prompt')
|
|
64
|
+
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
65
|
+
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
66
|
+
.option('-p, --prompt <prompt>', 'Specify the prompt to use')
|
|
67
|
+
.action(shell_1.default);
|
|
68
|
+
generate
|
|
69
|
+
.command('code')
|
|
70
|
+
.alias('c')
|
|
71
|
+
.description('Generate code based on a prompt')
|
|
72
|
+
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
73
|
+
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
74
|
+
.option('-p, --prompt <prompt>', 'Specify the prompt to use')
|
|
75
|
+
.option('-f, --files <filenames...>', 'Specify filenames of files with context to use for generating code')
|
|
76
|
+
.action(code_1.default);
|
|
47
77
|
generate
|
|
48
78
|
.command('commit')
|
|
49
79
|
.description('Generate a commit message and commit the changes')
|
|
@@ -52,6 +82,7 @@ generate
|
|
|
52
82
|
.action(commit_1.default);
|
|
53
83
|
generate
|
|
54
84
|
.command('unit-tests')
|
|
85
|
+
.alias('u')
|
|
55
86
|
.description('Generate unit tests (if you don\'t specify filenames, it will generate tests for commited changes that differ from the main/master branch)')
|
|
56
87
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
57
88
|
.option('-f, --files <filenames...>', 'Specify filenames for the unit tests')
|
|
@@ -59,6 +90,7 @@ generate
|
|
|
59
90
|
.action(unit_tests_1.default);
|
|
60
91
|
generate
|
|
61
92
|
.command('review')
|
|
93
|
+
.alias('r')
|
|
62
94
|
.description('Review the code for commited changes that differ from the main/master branch')
|
|
63
95
|
.option('-s, --silent', 'Run the command without asking for confirmation of submitting prompts')
|
|
64
96
|
.option('-m, --model <model>', 'Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)')
|
|
@@ -66,21 +98,26 @@ generate
|
|
|
66
98
|
// Project commands
|
|
67
99
|
const project = program
|
|
68
100
|
.command('project')
|
|
101
|
+
.alias('p')
|
|
69
102
|
.description('Commands for cloving a project');
|
|
70
103
|
project
|
|
71
104
|
.command('init')
|
|
72
|
-
.
|
|
105
|
+
.alias('i')
|
|
106
|
+
.description('Setup a new cloving project inside a git branch')
|
|
73
107
|
.action(init_2.default);
|
|
74
108
|
project
|
|
75
109
|
.command('plan')
|
|
76
|
-
.
|
|
110
|
+
.alias('p')
|
|
111
|
+
.description('Plan the steps to complete the project')
|
|
77
112
|
.action(plan_1.default);
|
|
78
113
|
project
|
|
79
114
|
.command('build')
|
|
80
|
-
.
|
|
115
|
+
.alias('b')
|
|
116
|
+
.description('Generate code to build the project')
|
|
81
117
|
.action(build_1.default);
|
|
82
118
|
project
|
|
83
119
|
.command('complete')
|
|
120
|
+
.alias('c')
|
|
84
121
|
.description('Clean up and finalize the project')
|
|
85
122
|
.action(complete_1.default);
|
|
86
123
|
program.parse(process.argv);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "cloving",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"types": "dist/index.d.ts",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "tsc && cp package.json dist/package.json",
|
|
8
|
+
"start": "node dist/index.js",
|
|
9
|
+
"watch": "tsc -w",
|
|
10
|
+
"check": "bash -c 'npx tsc --noEmit --skipLibCheck'",
|
|
11
|
+
"test": "bash -c jest",
|
|
12
|
+
"prepare": "husky"
|
|
13
|
+
},
|
|
14
|
+
"bin": {
|
|
15
|
+
"cloving": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"!**/test/**"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [],
|
|
22
|
+
"author": "Lucas Carlson",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"description": "",
|
|
25
|
+
"lint-staged": {
|
|
26
|
+
"*.ts": [
|
|
27
|
+
"yarn run check"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"lint-prepush": {
|
|
31
|
+
"base": "main",
|
|
32
|
+
"tasks": {
|
|
33
|
+
"*.ts": [
|
|
34
|
+
"yarn run check",
|
|
35
|
+
"yarn run test"
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"axios": "^1.7.2",
|
|
41
|
+
"cli-highlight": "^2.1.11",
|
|
42
|
+
"clipboard-copy": "^4.0.1",
|
|
43
|
+
"commander": "^12.1.0",
|
|
44
|
+
"eslint": "^9.6.0",
|
|
45
|
+
"eslint-config-prettier": "^9.1.0",
|
|
46
|
+
"eslint-config-raine": "^0.5.0",
|
|
47
|
+
"eslint-config-standard": "^17.1.0",
|
|
48
|
+
"eslint-plugin-import": "^2.29.1",
|
|
49
|
+
"eslint-plugin-jsdoc": "^48.5.2",
|
|
50
|
+
"eslint-plugin-n": "^17.9.0",
|
|
51
|
+
"eslint-plugin-promise": "^6.4.0",
|
|
52
|
+
"ignore": "^5.3.1",
|
|
53
|
+
"ini": "^4.1.3",
|
|
54
|
+
"inquirer": "^10.0.1",
|
|
55
|
+
"nock": "^13.5.4",
|
|
56
|
+
"vite": "^5.3.3",
|
|
57
|
+
"vite-node": "^2.0.1"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/ini": "^4.1.1",
|
|
61
|
+
"@types/inquirer": "^9.0.7",
|
|
62
|
+
"@types/jest": "^29.5.12",
|
|
63
|
+
"@types/node": "^20.14.10",
|
|
64
|
+
"husky": "^9.0.11",
|
|
65
|
+
"jest": "^29.7.0",
|
|
66
|
+
"lint-prepush": "^2.2.2",
|
|
67
|
+
"lint-staged": "^15.2.7",
|
|
68
|
+
"ts-jest": "^29.2.0",
|
|
69
|
+
"typescript": "^5.5.3"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -3,9 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.readFileContent = exports.fetchModels = exports.runCommand = exports.generateFileList = exports.checkForSpecialFiles = exports.collectSpecialFileContents = exports.SPECIAL_FILES = void 0;
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
|
-
const readline_1 = __importDefault(require("readline"));
|
|
9
8
|
const fs_1 = __importDefault(require("fs"));
|
|
10
9
|
exports.SPECIAL_FILES = [
|
|
11
10
|
'package.json',
|
|
@@ -95,19 +94,6 @@ const runCommand = (command, args) => {
|
|
|
95
94
|
});
|
|
96
95
|
};
|
|
97
96
|
exports.runCommand = runCommand;
|
|
98
|
-
const promptUser = (question) => {
|
|
99
|
-
const rl = readline_1.default.createInterface({
|
|
100
|
-
input: process.stdin,
|
|
101
|
-
output: process.stdout
|
|
102
|
-
});
|
|
103
|
-
return new Promise((resolve) => {
|
|
104
|
-
rl.question(question, (answer) => {
|
|
105
|
-
rl.close();
|
|
106
|
-
resolve(answer.trim());
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
exports.promptUser = promptUser;
|
|
111
97
|
const fetchModels = async () => {
|
|
112
98
|
try {
|
|
113
99
|
const modelsOutput = await (0, exports.runCommand)('cloving', ['models']);
|
|
@@ -119,3 +105,13 @@ const fetchModels = async () => {
|
|
|
119
105
|
}
|
|
120
106
|
};
|
|
121
107
|
exports.fetchModels = fetchModels;
|
|
108
|
+
const readFileContent = (file) => {
|
|
109
|
+
try {
|
|
110
|
+
return fs_1.default.readFileSync(file, 'utf-8');
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error('Error reading file content:', error.message);
|
|
114
|
+
return '';
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
exports.readFileContent = readFileContent;
|
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getTestingDirectory = exports.getAllFiles = exports.removeProjectConfig = exports.saveProjectConfig = exports.getProjectConfig = exports.getPrimaryModel = exports.saveConfig = exports.
|
|
6
|
+
exports.getTestingDirectory = exports.getAllFiles = exports.removeProjectConfig = exports.saveProjectConfig = exports.getProjectConfig = exports.getPrimaryModel = exports.saveConfig = exports.getClovingConfig = exports.getConfig = exports.CLOVINGPROJECT_PATH = exports.CLOVINGFILE_PATH = exports.CLOVING_CONFIG_PATH = void 0;
|
|
7
7
|
const os_1 = __importDefault(require("os"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -51,7 +51,7 @@ const getConfig = (options) => {
|
|
|
51
51
|
}
|
|
52
52
|
};
|
|
53
53
|
exports.getConfig = getConfig;
|
|
54
|
-
const
|
|
54
|
+
const getClovingConfig = () => {
|
|
55
55
|
if (clovingConfig) {
|
|
56
56
|
return clovingConfig;
|
|
57
57
|
}
|
|
@@ -64,7 +64,7 @@ const readClovingConfig = () => {
|
|
|
64
64
|
throw new Error(`${exports.CLOVING_CONFIG_PATH} file not found`);
|
|
65
65
|
}
|
|
66
66
|
};
|
|
67
|
-
exports.
|
|
67
|
+
exports.getClovingConfig = getClovingConfig;
|
|
68
68
|
const saveConfig = (config) => {
|
|
69
69
|
const iniString = ini_1.default.stringify(config);
|
|
70
70
|
fs_1.default.writeFileSync(exports.CLOVING_CONFIG_PATH, iniString);
|
|
@@ -144,7 +144,7 @@ Please provide instructions on how to set up testing for this project.`;
|
|
|
144
144
|
const getAllFiles = async (options, forTesting) => {
|
|
145
145
|
const gpt = new cloving_gpt_1.default(options);
|
|
146
146
|
// Read the cloving.json file
|
|
147
|
-
const config = (0, exports.
|
|
147
|
+
const config = (0, exports.getClovingConfig)();
|
|
148
148
|
const testingDirectory = (0, exports.getTestingDirectory)();
|
|
149
149
|
let allSrcFiles = [];
|
|
150
150
|
if (forTesting && !testingDirectory) {
|
|
@@ -162,7 +162,7 @@ const getAllFiles = async (options, forTesting) => {
|
|
|
162
162
|
};
|
|
163
163
|
exports.getAllFiles = getAllFiles;
|
|
164
164
|
const getTestingDirectory = () => {
|
|
165
|
-
const config = (0, exports.
|
|
165
|
+
const config = (0, exports.getClovingConfig)();
|
|
166
166
|
return config.testingFrameworks?.find((framework) => framework.directory)?.directory;
|
|
167
167
|
};
|
|
168
168
|
exports.getTestingDirectory = getTestingDirectory;
|
package/dist/utils/git_utils.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getCurrentBranchName = exports.getDefaultBranchName = exports.getGitDiff =
|
|
6
|
+
exports.getCurrentBranchName = exports.getDefaultBranchName = exports.getGitDiff = void 0;
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const readline_1 = __importDefault(require("readline"));
|
|
9
9
|
const askQuestion = (question) => {
|
|
@@ -16,27 +16,6 @@ const askQuestion = (question) => {
|
|
|
16
16
|
resolve(answer);
|
|
17
17
|
}));
|
|
18
18
|
};
|
|
19
|
-
const generateCommitMessagePrompt = () => {
|
|
20
|
-
const diff = (0, child_process_1.execSync)('git diff HEAD').toString();
|
|
21
|
-
return `Generate a concise and meaningful commit message based on a diff.
|
|
22
|
-
|
|
23
|
-
Do not add any commentary or context to the message other than the commit message itself.
|
|
24
|
-
|
|
25
|
-
An example of the output for this should look like the following:
|
|
26
|
-
|
|
27
|
-
\`\`\`plaintext
|
|
28
|
-
Update dependencies and package versions
|
|
29
|
-
|
|
30
|
-
- Upgrade Ruby gems including aws-sdk, honeybadger, irb, and rubocop
|
|
31
|
-
- Update Node.js packages including esbuild, tinymce, and trix
|
|
32
|
-
- Bump TypeScript and ESLint related packages to latest versions
|
|
33
|
-
\`\`\`
|
|
34
|
-
|
|
35
|
-
Here is the diff to help you write the commit message:
|
|
36
|
-
|
|
37
|
-
${diff}`;
|
|
38
|
-
};
|
|
39
|
-
exports.generateCommitMessagePrompt = generateCommitMessagePrompt;
|
|
40
19
|
const getGitDiff = async () => {
|
|
41
20
|
try {
|
|
42
21
|
const defaultBranchName = await (0, exports.getDefaultBranchName)();
|