cloving 0.1.0 → 0.1.1-8.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 +168 -40
- package/dist/cloving_gpt/adapters/claude.js +6 -8
- package/dist/cloving_gpt/adapters/gemini.js +62 -0
- package/dist/cloving_gpt/adapters/mistral.js +46 -0
- package/dist/cloving_gpt/adapters/openai.js +7 -6
- package/dist/cloving_gpt/index.js +64 -63
- package/dist/commands/commit.js +2 -2
- package/dist/commands/config.js +86 -19
- package/dist/commands/generate/code.js +337 -0
- package/dist/commands/generate/commit.js +69 -0
- package/dist/commands/generate/context.js +75 -0
- package/dist/commands/generate/fizzbuzz.js +35 -0
- package/dist/commands/generate/review.js +146 -0
- package/dist/commands/generate/sh.js +95 -0
- package/dist/commands/generate/shell.js +111 -0
- package/dist/commands/generate/unit_tests.js +314 -0
- package/dist/commands/init.js +86 -33
- package/dist/commands/models.js +5 -2
- package/dist/commands/project/build.js +88 -0
- package/dist/commands/project/complete.js +12 -0
- package/dist/commands/project/init.js +82 -0
- package/dist/commands/project/plan.js +108 -0
- package/dist/commands/review.js +2 -2
- package/dist/commands/unit_tests.js +108 -77
- package/dist/index.js +111 -21
- package/dist/package.json +76 -0
- package/dist/utils/command_utils.js +36 -70
- package/dist/utils/config_utils.js +170 -0
- package/dist/utils/git_utils.js +37 -44
- package/dist/utils/string_utils.js +72 -18
- package/package.json +28 -17
package/README.md
CHANGED
|
@@ -1,26 +1,69 @@
|
|
|
1
|
-
# Cloving
|
|
1
|
+
# Cloving - CLI Code Generation with AI
|
|
2
2
|
|
|
3
|
-
Cloving is
|
|
3
|
+
Cloving CLI is a command line utility which integrates AI into your development workflow. It provides AI-powered code generation, commit message generation, code reviews, unit test generation, and more.
|
|
4
|
+
|
|
5
|
+
What makes the Cloving CLI different from other AI tools is that it builds sophisticated context-aware prompts to generate code, commit messages, and more.
|
|
6
|
+
|
|
7
|
+
Cloving gets to know your specific projects, the frameworks you use, the coding style you prefer, and the patterns you follow, and does its best to generate code that fits your existing project so that it actually works.
|
|
8
|
+
|
|
9
|
+
It delivers usable code that you can save directly into your project instead of copying and pasting code snippets from chat interactions.
|
|
10
|
+
|
|
11
|
+
**Read the [introduction announcement](https://cloving.ai/tutorials/introducing-the-cloving-cli).**
|
|
12
|
+
|
|
13
|
+
> [!WARNING]
|
|
14
|
+
>
|
|
15
|
+
> This project is still in the early stages of development and is not yet stable.
|
|
16
|
+
> Please use it with caution and [report any issues](https://github.com/cloving-ai/cloving-cli/issues) you encounter
|
|
4
17
|
|
|
5
18
|
## Features
|
|
6
19
|
|
|
20
|
+
- **Context-aware AI code generation**
|
|
7
21
|
- **AI-powered Git commit message generation**
|
|
8
22
|
- **Automated code reviews with AI insights**
|
|
9
23
|
- **AI-assisted unit test generation**
|
|
10
|
-
- **
|
|
11
|
-
|
|
24
|
+
- **Support for multiple AI models including OpenAI, Claude, and Ollama**
|
|
25
|
+
|
|
26
|
+
## Important
|
|
27
|
+
|
|
28
|
+
The cloving will ask you before submitting any prompt to the AI model. You can use the `-s` or `--silent` flag to run the command without asking for confirmation, but by default you will have the chance to review all prompts with all the context before submitting them. This is to ensure that you are aware of what is being sent to the AI model and can make any necessary changes before submitting the prompt.
|
|
12
29
|
|
|
13
30
|
## Prerequisites
|
|
14
31
|
|
|
15
32
|
- Node.js (version 20 or higher)
|
|
16
33
|
- Git
|
|
17
|
-
- API access to AI chat models (e.g., OpenAI GPT-
|
|
34
|
+
- API access to AI chat models (e.g., OpenAI GPT-4, Claude, Ollama, etc.)
|
|
18
35
|
|
|
19
36
|
## Installation
|
|
20
37
|
|
|
38
|
+
You have three options to install and use Cloving:
|
|
39
|
+
|
|
40
|
+
### 1. Global Installation via npm
|
|
41
|
+
|
|
42
|
+
Install Cloving globally using npm:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install cloving -g
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This allows you to run `cloving` commands from anywhere in your terminal.
|
|
49
|
+
|
|
50
|
+
### 2. Run with npx
|
|
51
|
+
|
|
52
|
+
You can use npx to run Cloving without installing it globally:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
npx cloving [command]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This method downloads and executes Cloving on-the-fly, ensuring you always use the latest version.
|
|
59
|
+
|
|
60
|
+
### 3. Clone and Install from Source
|
|
61
|
+
|
|
62
|
+
For development or to use the latest unreleased features:
|
|
63
|
+
|
|
21
64
|
1. Clone this repository:
|
|
22
65
|
```bash
|
|
23
|
-
git clone https://github.com/
|
|
66
|
+
git clone https://github.com/cloving-ai/cloving-cli.git
|
|
24
67
|
```
|
|
25
68
|
|
|
26
69
|
2. Navigate to the project directory:
|
|
@@ -28,82 +71,167 @@ Cloving is an innovative tool designed to seamlessly integrate AI into various a
|
|
|
28
71
|
cd cloving-cli
|
|
29
72
|
```
|
|
30
73
|
|
|
31
|
-
3. Install dependencies:
|
|
74
|
+
3. Install dependencies and link the package:
|
|
32
75
|
```bash
|
|
33
76
|
yarn install
|
|
77
|
+
yarn link
|
|
34
78
|
```
|
|
35
79
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
80
|
+
After installation, configure Cloving with your API key and preferred model:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
cloving config
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Choose the installation method that best suits your needs and workflow. The global npm installation is recommended for most users, while npx is great for one-off usage or trying out Cloving. Cloning from source is ideal for contributors or those who want the absolute latest features.
|
|
41
87
|
|
|
42
88
|
## Usage
|
|
43
89
|
|
|
44
90
|
Cloving provides several commands to help integrate AI into your development workflow:
|
|
45
91
|
|
|
92
|
+
### Configuration
|
|
93
|
+
|
|
94
|
+
Configure Cloving with your API key and model:
|
|
95
|
+
```bash
|
|
96
|
+
cloving config
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Initialization
|
|
100
|
+
|
|
101
|
+
Set up Cloving in the current project:
|
|
102
|
+
```bash
|
|
103
|
+
cloving init
|
|
104
|
+
```
|
|
105
|
+
Options:
|
|
106
|
+
- `-s, --silent`: Run without asking for confirmation of submitting prompts
|
|
107
|
+
- `-m, --model <model>`: Select the model to use
|
|
108
|
+
|
|
46
109
|
### Generating Commit Messages
|
|
47
110
|
|
|
48
|
-
|
|
111
|
+
Generate an AI-powered commit message:
|
|
49
112
|
```bash
|
|
50
113
|
cloving commit
|
|
51
114
|
```
|
|
52
|
-
|
|
115
|
+
or
|
|
116
|
+
```bash
|
|
117
|
+
cloving generate commit
|
|
118
|
+
```
|
|
119
|
+
Options:
|
|
120
|
+
- `-s, --silent`: Run without asking for confirmation
|
|
121
|
+
- `-m, --model <model>`: Select the model to use
|
|
53
122
|
|
|
54
123
|
### Code Reviews
|
|
55
124
|
|
|
56
|
-
|
|
125
|
+
Get an AI-powered code review:
|
|
57
126
|
```bash
|
|
58
|
-
cloving review
|
|
127
|
+
cloving generate review
|
|
59
128
|
```
|
|
129
|
+
Options:
|
|
130
|
+
- `-s, --silent`: Run without asking for confirmation
|
|
131
|
+
- `-m, --model <model>`: Select the model to use
|
|
60
132
|
|
|
61
|
-
### Generating
|
|
133
|
+
### Generating Code
|
|
62
134
|
|
|
63
|
-
|
|
135
|
+
Generate code based on a prompt:
|
|
64
136
|
```bash
|
|
65
|
-
cloving
|
|
137
|
+
cloving generate code
|
|
66
138
|
```
|
|
139
|
+
Options:
|
|
140
|
+
- `--save`: Automatically save all files after generating the code
|
|
141
|
+
- `-i, --interactive`: Auto-save generated code and then show a new prompt with existing context to revise the code further
|
|
142
|
+
- `-s, --silent`: Run the command without asking for confirmation of submitting prompts
|
|
143
|
+
- `-m, --model <model>`: Select the model to use
|
|
144
|
+
- `-p, --prompt <prompt>`: Specify the prompt to use
|
|
145
|
+
- `-f, --files <filenames...>`: Specify filenames of files with context to use for generating code
|
|
67
146
|
|
|
68
|
-
###
|
|
147
|
+
### Generating Shell Commands
|
|
69
148
|
|
|
70
|
-
|
|
149
|
+
Generate a shell command based on a prompt:
|
|
71
150
|
```bash
|
|
72
|
-
cloving
|
|
151
|
+
cloving generate shell
|
|
73
152
|
```
|
|
153
|
+
or
|
|
154
|
+
```bash
|
|
155
|
+
cloving generate sh
|
|
156
|
+
```
|
|
157
|
+
Options:
|
|
158
|
+
- `-s, --silent`: Run without asking for confirmation of submitting prompts
|
|
159
|
+
- `-m, --model <model>`: Select the model to use
|
|
160
|
+
- `-p, --prompt <prompt>`: Specify the prompt to use
|
|
74
161
|
|
|
75
|
-
###
|
|
162
|
+
### Generating Context
|
|
76
163
|
|
|
77
|
-
|
|
164
|
+
Create a context string for generating prompts outside of the cloving cli:
|
|
78
165
|
```bash
|
|
79
|
-
cloving
|
|
166
|
+
cloving generate context
|
|
80
167
|
```
|
|
168
|
+
Options:
|
|
169
|
+
- `-f, --files <filenames...>`: Specify filenames of files with context
|
|
81
170
|
|
|
82
|
-
###
|
|
171
|
+
### Generating Unit Tests
|
|
83
172
|
|
|
84
|
-
|
|
173
|
+
Generate unit tests for changes or specific files:
|
|
85
174
|
```bash
|
|
86
|
-
cloving
|
|
175
|
+
cloving generate unit-tests
|
|
87
176
|
```
|
|
177
|
+
Options:
|
|
178
|
+
- `-s, --silent`: Run without asking for confirmation
|
|
179
|
+
- `-f, --files <filenames...>`: Specify filenames for the unit tests
|
|
180
|
+
- `-m, --model <model>`: Select the model to use
|
|
88
181
|
|
|
89
|
-
|
|
182
|
+
### Project Commands
|
|
183
|
+
|
|
184
|
+
Cloving now includes commands for managing entire projects:
|
|
185
|
+
|
|
186
|
+
- Initialize a new project inside a git branch:
|
|
187
|
+
```bash
|
|
188
|
+
cloving project init
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
- Plan the steps to complete the project:
|
|
192
|
+
```bash
|
|
193
|
+
cloving project plan
|
|
194
|
+
```
|
|
90
195
|
|
|
91
|
-
|
|
196
|
+
- Generate code to build the project:
|
|
197
|
+
```bash
|
|
198
|
+
cloving project build
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- Clean up and finalize the project:
|
|
202
|
+
```bash
|
|
203
|
+
cloving project complete
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Command Line Options
|
|
92
207
|
|
|
93
|
-
|
|
208
|
+
Usage: `cloving [command] [options]`
|
|
94
209
|
|
|
95
210
|
Options:
|
|
96
|
-
- `-V, --version
|
|
97
|
-
- `-h, --help
|
|
211
|
+
- `-V, --version`: Output the version number
|
|
212
|
+
- `-h, --help`: Display help for command
|
|
98
213
|
|
|
99
214
|
Commands:
|
|
100
|
-
- `
|
|
101
|
-
- `
|
|
102
|
-
- `models
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
105
|
-
- `
|
|
106
|
-
- `
|
|
215
|
+
- `config`: Configure Cloving with your API key and models to use
|
|
216
|
+
- `init`: Setup Cloving in the current directory
|
|
217
|
+
- `models`: List available models
|
|
218
|
+
- `commit`: Alias for cloving generate commit
|
|
219
|
+
- `generate`: Generate various items like unit-tests and code reviews
|
|
220
|
+
- `commit`: Generate a commit message and commit the changes
|
|
221
|
+
- `code`: Generate code based on a prompt
|
|
222
|
+
- `context`: Generate context for building a prompt outside of cloving
|
|
223
|
+
- `shell`: Generate a shell command based on a prompt
|
|
224
|
+
- `unit-tests`: Generate unit tests
|
|
225
|
+
- `review`: Review the code for committed changes
|
|
226
|
+
- `project`: Commands for managing Cloving projects
|
|
227
|
+
- `init`: Setup a new Cloving project inside a git branch
|
|
228
|
+
- `plan`: Plan the steps to complete the project
|
|
229
|
+
- `build`: Generate code to build the project
|
|
230
|
+
- `complete`: Clean up and finalize the project
|
|
231
|
+
|
|
232
|
+
Most commands support the following options:
|
|
233
|
+
- `-s, --silent`: Run the command without asking for confirmation of submitting prompts
|
|
234
|
+
- `-m, --model <model>`: Select the model to use (e.g., openai, claude, ollama, ollama:llama3, claude:claude-3-5-sonnet-20240620)
|
|
107
235
|
|
|
108
236
|
## Contributing
|
|
109
237
|
|
|
@@ -23,13 +23,13 @@ class ClaudeAdapter {
|
|
|
23
23
|
}
|
|
24
24
|
getPayload(request) {
|
|
25
25
|
return {
|
|
26
|
-
model: this.model,
|
|
26
|
+
model: this.model.replace(':', '-'),
|
|
27
27
|
system: 'You are a computer programmer giving advice on how to write better code.',
|
|
28
28
|
messages: [
|
|
29
29
|
{ role: 'user', content: request.prompt }
|
|
30
30
|
],
|
|
31
31
|
max_tokens: request.maxTokens || 4096,
|
|
32
|
-
temperature: request.temperature || 0.
|
|
32
|
+
temperature: request.temperature || 0.2
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
35
|
extractResponse(data) {
|
|
@@ -50,11 +50,9 @@ class ClaudeAdapter {
|
|
|
50
50
|
}
|
|
51
51
|
exports.ClaudeAdapter = ClaudeAdapter;
|
|
52
52
|
ClaudeAdapter.supportedModels = [
|
|
53
|
-
'claude:claude-3-5
|
|
54
|
-
'claude:claude-3
|
|
55
|
-
'claude:claude-3
|
|
56
|
-
'claude:claude-3
|
|
53
|
+
'claude:claude-3-5:sonnet-20240620',
|
|
54
|
+
'claude:claude-3:opus-20240229',
|
|
55
|
+
'claude:claude-3:sonnet-20240229',
|
|
56
|
+
'claude:claude-3:haiku-20240307',
|
|
57
57
|
// Add more supported models here as needed
|
|
58
58
|
];
|
|
59
|
-
// Example usage:
|
|
60
|
-
// ClaudeAdapter.listSupportedModels()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GeminiAdapter = void 0;
|
|
4
|
+
class GeminiAdapter {
|
|
5
|
+
constructor(model) {
|
|
6
|
+
this.model = model;
|
|
7
|
+
}
|
|
8
|
+
static async listSupportedModels() {
|
|
9
|
+
GeminiAdapter.supportedModels.forEach(model => {
|
|
10
|
+
console.log(model);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
getEndpoint() {
|
|
14
|
+
return `https://generativelanguage.googleapis.com/v1beta/models/${this.model.replace(':', '-')}:generateContent`;
|
|
15
|
+
}
|
|
16
|
+
getHeaders(apiKey) {
|
|
17
|
+
return {
|
|
18
|
+
'Content-Type': 'application/json',
|
|
19
|
+
'x-goog-api-key': apiKey
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
getPayload(request) {
|
|
23
|
+
return {
|
|
24
|
+
contents: [
|
|
25
|
+
{
|
|
26
|
+
parts: [
|
|
27
|
+
{
|
|
28
|
+
text: request.prompt
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
generationConfig: {
|
|
34
|
+
temperature: 0.2,
|
|
35
|
+
topK: 40,
|
|
36
|
+
topP: 0.95,
|
|
37
|
+
maxOutputTokens: 1024
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
extractResponse(data) {
|
|
42
|
+
try {
|
|
43
|
+
if (data && data.candidates && data.candidates[0] && data.candidates[0].content && data.candidates[0].content.parts && data.candidates[0].content.parts[0]) {
|
|
44
|
+
return data.candidates[0].content.parts[0].text;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.error('Unexpected response structure:', data);
|
|
48
|
+
throw new Error('Invalid response structure');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (error) {
|
|
52
|
+
console.error('Error extracting response:', error);
|
|
53
|
+
throw error;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
exports.GeminiAdapter = GeminiAdapter;
|
|
58
|
+
GeminiAdapter.supportedModels = [
|
|
59
|
+
'gemini:gemini-1.5:pro-latest',
|
|
60
|
+
'gemini:gemini-1.5:flash-latest',
|
|
61
|
+
'gemini:gemini-1.0:pro-latest',
|
|
62
|
+
];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MistralAdapter = void 0;
|
|
4
|
+
class MistralAdapter {
|
|
5
|
+
static listSupportedModels() {
|
|
6
|
+
MistralAdapter.supportedModels.forEach(model => {
|
|
7
|
+
console.log(model);
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
constructor(model) {
|
|
11
|
+
this.model = model;
|
|
12
|
+
}
|
|
13
|
+
getEndpoint() {
|
|
14
|
+
return 'https://api.mistral.ai/v1/chat/completions';
|
|
15
|
+
}
|
|
16
|
+
getHeaders(apiKey) {
|
|
17
|
+
return {
|
|
18
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
19
|
+
'Content-Type': 'application/json'
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
getPayload(request) {
|
|
23
|
+
return {
|
|
24
|
+
model: this.model.replace(':', '-'),
|
|
25
|
+
messages: [{ role: "user", content: request.prompt }],
|
|
26
|
+
max_tokens: request.maxTokens,
|
|
27
|
+
temperature: request.temperature || 0.2,
|
|
28
|
+
stream: false
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
extractResponse(data) {
|
|
32
|
+
return data.choices[0].message.content;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
exports.MistralAdapter = MistralAdapter;
|
|
36
|
+
MistralAdapter.supportedModels = [
|
|
37
|
+
'mistral:mistral:embed',
|
|
38
|
+
'mistral:mistral:tiny-latest',
|
|
39
|
+
'mistral:mistral:small-latest',
|
|
40
|
+
'mistral:mistral:medium-latest',
|
|
41
|
+
'mistral:mistral:large-latest',
|
|
42
|
+
'mistral:open-mistral:7b',
|
|
43
|
+
'mistral:open-mixtral:8x7b',
|
|
44
|
+
'mistral:open-mixtral:8x22b',
|
|
45
|
+
'mistral:codestral:latest',
|
|
46
|
+
];
|
|
@@ -21,10 +21,10 @@ class OpenAIAdapter {
|
|
|
21
21
|
}
|
|
22
22
|
getPayload(request) {
|
|
23
23
|
return {
|
|
24
|
-
model: this.model,
|
|
24
|
+
model: this.model.replace(':', '-'),
|
|
25
25
|
messages: [{ role: "user", content: request.prompt }],
|
|
26
26
|
max_tokens: request.maxTokens,
|
|
27
|
-
temperature: request.temperature || 0.
|
|
27
|
+
temperature: request.temperature || 0.2
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
extractResponse(data) {
|
|
@@ -33,9 +33,10 @@ class OpenAIAdapter {
|
|
|
33
33
|
}
|
|
34
34
|
exports.OpenAIAdapter = OpenAIAdapter;
|
|
35
35
|
OpenAIAdapter.supportedModels = [
|
|
36
|
-
'openai:gpt
|
|
37
|
-
'openai:gpt-
|
|
38
|
-
'openai:gpt-
|
|
39
|
-
'openai:
|
|
36
|
+
'openai:gpt:4o',
|
|
37
|
+
'openai:gpt:4o-mini',
|
|
38
|
+
'openai:gpt:4-turbo',
|
|
39
|
+
'openai:gpt:3.5-turbo',
|
|
40
|
+
'openai:text-embedding:3-large',
|
|
40
41
|
// Add more supported models here as needed
|
|
41
42
|
];
|
|
@@ -4,98 +4,99 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const axios_1 = __importDefault(require("axios"));
|
|
7
|
-
const readline_1 = __importDefault(require("readline"));
|
|
8
7
|
const child_process_1 = require("child_process");
|
|
9
8
|
const process_1 = __importDefault(require("process"));
|
|
9
|
+
const prompts_1 = require("@inquirer/prompts");
|
|
10
10
|
const claude_1 = require("./adapters/claude");
|
|
11
11
|
const openai_1 = require("./adapters/openai");
|
|
12
|
-
const
|
|
12
|
+
const mistral_1 = require("./adapters/mistral");
|
|
13
13
|
const ollama_1 = require("./adapters/ollama");
|
|
14
|
-
const
|
|
14
|
+
const gemini_1 = require("./adapters/gemini");
|
|
15
|
+
const config_utils_1 = require("../utils/config_utils");
|
|
15
16
|
class ClovingGPT {
|
|
16
|
-
constructor(options
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
constructor(options) {
|
|
18
|
+
const { model: partialModel } = options;
|
|
19
|
+
const config = (0, config_utils_1.getConfig)(options);
|
|
20
|
+
if (!config || !config.models) {
|
|
21
|
+
console.log('No cloving configuration found. Please run: cloving config');
|
|
22
|
+
process_1.default.exit(1);
|
|
20
23
|
}
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const primaryModel = (0, config_utils_1.getPrimaryModel)(partialModel);
|
|
25
|
+
if (!primaryModel) {
|
|
26
|
+
console.log('No AI API models found in the cloving configuration. Please run: cloving config');
|
|
27
|
+
process_1.default.exit(1);
|
|
28
|
+
}
|
|
29
|
+
const { provider, model, config: modelConfig } = primaryModel;
|
|
30
|
+
this.apiKey = modelConfig.apiKey;
|
|
31
|
+
this.temperature = options.temperature || modelConfig.temperature || 0.2;
|
|
32
|
+
this.silent = options.silent || modelConfig.silent;
|
|
33
|
+
switch (provider) {
|
|
27
34
|
case 'claude':
|
|
28
35
|
this.adapter = new claude_1.ClaudeAdapter(model);
|
|
29
36
|
break;
|
|
30
37
|
case 'openai':
|
|
31
38
|
this.adapter = new openai_1.OpenAIAdapter(model);
|
|
32
39
|
break;
|
|
33
|
-
case '
|
|
34
|
-
this.adapter = new
|
|
40
|
+
case 'mistral':
|
|
41
|
+
this.adapter = new mistral_1.MistralAdapter(model);
|
|
35
42
|
break;
|
|
36
43
|
case 'ollama':
|
|
37
44
|
this.adapter = new ollama_1.OllamaAdapter(model);
|
|
38
45
|
break;
|
|
46
|
+
case 'gemini':
|
|
47
|
+
this.adapter = new gemini_1.GeminiAdapter(model);
|
|
48
|
+
break;
|
|
39
49
|
default:
|
|
40
|
-
throw new Error(`Unsupported provider: ${
|
|
50
|
+
throw new Error(`Unsupported provider: ${provider}`);
|
|
41
51
|
}
|
|
42
52
|
}
|
|
43
|
-
async
|
|
53
|
+
async reviewPrompt(prompt, endpoint) {
|
|
44
54
|
if (this.silent)
|
|
45
|
-
return
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
55
|
+
return;
|
|
56
|
+
const tokenCount = Math.ceil(prompt.length / 4).toLocaleString();
|
|
57
|
+
const reviewPrompt = await (0, prompts_1.confirm)({
|
|
58
|
+
message: `Do you want to review the ~${tokenCount} token prompt before sending it to ${endpoint}?`,
|
|
59
|
+
default: true
|
|
49
60
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const rlConfirm = readline_1.default.createInterface({
|
|
65
|
-
input: process_1.default.stdin,
|
|
66
|
-
output: process_1.default.stdout
|
|
67
|
-
});
|
|
68
|
-
rlConfirm.question('Do you still want to continue? [Yn]: ', (confirmAnswer) => {
|
|
69
|
-
rlConfirm.close();
|
|
70
|
-
confirmAnswer = confirmAnswer.trim().toLowerCase();
|
|
71
|
-
resolve(confirmAnswer === 'y' || confirmAnswer === '');
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
less.stdin.on('error', (err) => {
|
|
75
|
-
if (isNodeError(err) && err.code === 'EPIPE') {
|
|
76
|
-
resolve(true);
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
console.error('Pipeline error:', err);
|
|
80
|
-
resolve(false);
|
|
81
|
-
}
|
|
61
|
+
if (reviewPrompt) {
|
|
62
|
+
const less = (0, child_process_1.spawn)('less', ['-R'], { stdio: ['pipe', process_1.default.stdout, process_1.default.stderr] });
|
|
63
|
+
less.stdin.write(prompt);
|
|
64
|
+
less.stdin.end();
|
|
65
|
+
await new Promise((resolve, reject) => {
|
|
66
|
+
less.on('close', async (code) => {
|
|
67
|
+
if (code !== 0) {
|
|
68
|
+
console.error('less command exited with an error');
|
|
69
|
+
reject(new Error('Less command failed'));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const confirmContinue = await (0, prompts_1.confirm)({
|
|
73
|
+
message: 'Do you want to continue?',
|
|
74
|
+
default: true
|
|
82
75
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
76
|
+
if (!confirmContinue) {
|
|
77
|
+
console.error('Operation cancelled');
|
|
78
|
+
process_1.default.exit(1);
|
|
79
|
+
}
|
|
80
|
+
resolve();
|
|
81
|
+
});
|
|
82
|
+
less.stdin.on('error', (err) => {
|
|
83
|
+
if (isNodeError(err) && err.code === 'EPIPE') {
|
|
84
|
+
resolve();
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
console.error('Pipeline error:', err);
|
|
88
|
+
reject(err);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
87
91
|
});
|
|
88
|
-
}
|
|
92
|
+
}
|
|
89
93
|
}
|
|
90
94
|
async generateText(request) {
|
|
95
|
+
request.temperature || (request.temperature = this.temperature);
|
|
91
96
|
const endpoint = this.adapter.getEndpoint();
|
|
92
97
|
const payload = this.adapter.getPayload(request);
|
|
93
98
|
const headers = this.adapter.getHeaders(this.apiKey);
|
|
94
|
-
|
|
95
|
-
const shouldContinue = await this.askUserToConfirm(request.prompt, `Do you want to review the ~${tokenCount} token prompt before sending it to ${endpoint}? [Yn]: `);
|
|
96
|
-
if (!shouldContinue) {
|
|
97
|
-
throw 'Operation cancelled by the user.';
|
|
98
|
-
}
|
|
99
|
+
await this.reviewPrompt(request.prompt, endpoint);
|
|
99
100
|
try {
|
|
100
101
|
const response = await axios_1.default.post(endpoint, payload, { headers });
|
|
101
102
|
return this.adapter.extractResponse(response.data);
|
package/dist/commands/commit.js
CHANGED
|
@@ -8,10 +8,10 @@ const path_1 = __importDefault(require("path"));
|
|
|
8
8
|
const child_process_1 = require("child_process");
|
|
9
9
|
const git_utils_1 = require("../utils/git_utils");
|
|
10
10
|
const string_utils_1 = require("../utils/string_utils");
|
|
11
|
-
const
|
|
11
|
+
const config_utils_1 = require("../utils/config_utils");
|
|
12
12
|
const cloving_gpt_1 = __importDefault(require("../cloving_gpt"));
|
|
13
13
|
const generateAndCommitMessage = async (options) => {
|
|
14
|
-
options.silent = (0,
|
|
14
|
+
options.silent = (0, config_utils_1.getConfig)(options).globalSilent || false;
|
|
15
15
|
const gpt = new cloving_gpt_1.default(options);
|
|
16
16
|
try {
|
|
17
17
|
// Generate the prompt for commit message
|