3.2.6
This commit is contained in:
@@ -106,7 +106,7 @@ Create a `.env` file and add OpenCommit config variables there like this:
|
|||||||
|
|
||||||
```env
|
```env
|
||||||
...
|
...
|
||||||
OCO_AI_PROVIDER=<openai (default), anthropic, azure, ollama, gemini, flowise>
|
OCO_AI_PROVIDER=<openai (default), anthropic, azure, ollama, gemini, flowise, deepseek>
|
||||||
OCO_API_KEY=<your OpenAI API token> // or other LLM provider API token
|
OCO_API_KEY=<your OpenAI API token> // or other LLM provider API token
|
||||||
OCO_API_URL=<may be used to set proxy path to OpenAI api>
|
OCO_API_URL=<may be used to set proxy path to OpenAI api>
|
||||||
OCO_TOKENS_MAX_INPUT=<max model token limit (default: 4096)>
|
OCO_TOKENS_MAX_INPUT=<max model token limit (default: 4096)>
|
||||||
|
|||||||
+19311
-25
File diff suppressed because it is too large
Load Diff
+19278
-2
File diff suppressed because it is too large
Load Diff
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "opencommit",
|
"name": "opencommit",
|
||||||
"version": "3.2.2",
|
"version": "3.2.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "opencommit",
|
"name": "opencommit",
|
||||||
"version": "3.2.2",
|
"version": "3.2.5",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@actions/core": "^1.10.0",
|
"@actions/core": "^1.10.0",
|
||||||
|
|||||||
+4
-4
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "opencommit",
|
"name": "opencommit",
|
||||||
"version": "3.2.2",
|
"version": "3.2.5",
|
||||||
"description": "Auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
|
"description": "Auto-generate impressive commits in 1 second. Killing lame commits with AI 🤯🔫",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"git",
|
"git",
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
],
|
],
|
||||||
"main": "cli.js",
|
"main": "cli.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"opencommit": "./out/cli.cjs",
|
"opencommit": "out/cli.cjs",
|
||||||
"oco": "./out/cli.cjs"
|
"oco": "out/cli.cjs"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "https://github.com/di-sukharev/opencommit"
|
"url": "git+https://github.com/di-sukharev/opencommit.git"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "https://github.com/di-sukharev",
|
"author": "https://github.com/di-sukharev",
|
||||||
|
|||||||
+11
-6
@@ -127,8 +127,9 @@ export const MODEL_LIST = {
|
|||||||
'pixtral-12b-latest',
|
'pixtral-12b-latest',
|
||||||
'mistral-embed',
|
'mistral-embed',
|
||||||
'mistral-moderation-2411',
|
'mistral-moderation-2411',
|
||||||
'mistral-moderation-latest',
|
'mistral-moderation-latest'
|
||||||
]
|
],
|
||||||
|
deepseek: ['deepseek-chat', 'deepseek-reasoner']
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDefaultModel = (provider: string | undefined): string => {
|
const getDefaultModel = (provider: string | undefined): string => {
|
||||||
@@ -145,6 +146,8 @@ const getDefaultModel = (provider: string | undefined): string => {
|
|||||||
return MODEL_LIST.groq[0];
|
return MODEL_LIST.groq[0];
|
||||||
case 'mistral':
|
case 'mistral':
|
||||||
return MODEL_LIST.mistral[0];
|
return MODEL_LIST.mistral[0];
|
||||||
|
case 'deepseek':
|
||||||
|
return MODEL_LIST.deepseek[0];
|
||||||
default:
|
default:
|
||||||
return MODEL_LIST.openai[0];
|
return MODEL_LIST.openai[0];
|
||||||
}
|
}
|
||||||
@@ -184,7 +187,7 @@ export const configValidators = {
|
|||||||
validateConfig(
|
validateConfig(
|
||||||
'OCO_API_KEY',
|
'OCO_API_KEY',
|
||||||
value,
|
value,
|
||||||
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "mlx" or "azure" or "gemini" or "flowise" or "anthropic". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
|
'You need to provide the OCO_API_KEY when OCO_AI_PROVIDER set to "openai" (default) or "ollama" or "mlx" or "azure" or "gemini" or "flowise" or "anthropic" or "deepseek". Run `oco config set OCO_API_KEY=your_key OCO_AI_PROVIDER=openai`'
|
||||||
);
|
);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -307,9 +310,10 @@ export const configValidators = {
|
|||||||
'azure',
|
'azure',
|
||||||
'test',
|
'test',
|
||||||
'flowise',
|
'flowise',
|
||||||
'groq'
|
'groq',
|
||||||
|
'deepseek'
|
||||||
].includes(value) || value.startsWith('ollama'),
|
].includes(value) || value.startsWith('ollama'),
|
||||||
`${value} is not supported yet, use 'ollama', 'mlx', 'anthropic', 'azure', 'gemini', 'flowise', 'mistral' or 'openai' (default)`
|
`${value} is not supported yet, use 'ollama', 'mlx', 'anthropic', 'azure', 'gemini', 'flowise', 'mistral', 'deepseek' or 'openai' (default)`
|
||||||
);
|
);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
@@ -356,7 +360,8 @@ export enum OCO_AI_PROVIDER_ENUM {
|
|||||||
FLOWISE = 'flowise',
|
FLOWISE = 'flowise',
|
||||||
GROQ = 'groq',
|
GROQ = 'groq',
|
||||||
MISTRAL = 'mistral',
|
MISTRAL = 'mistral',
|
||||||
MLX = 'mlx'
|
MLX = 'mlx',
|
||||||
|
DEEPSEEK = 'deepseek'
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ConfigType = {
|
export type ConfigType = {
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { OpenAI } from 'openai';
|
||||||
|
import { GenerateCommitMessageErrorEnum } from '../generateCommitMessageFromGitDiff';
|
||||||
|
import { tokenCount } from '../utils/tokenCount';
|
||||||
|
import { OpenAiEngine, OpenAiConfig } from './openAI';
|
||||||
|
|
||||||
|
export interface DeepseekConfig extends OpenAiConfig {}
|
||||||
|
|
||||||
|
export class DeepseekEngine extends OpenAiEngine {
|
||||||
|
constructor(config: DeepseekConfig) {
|
||||||
|
// Call OpenAIEngine constructor with forced Deepseek baseURL
|
||||||
|
super({
|
||||||
|
...config,
|
||||||
|
baseURL: 'https://api.deepseek.com/v1'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identical method from OpenAiEngine, re-implemented here
|
||||||
|
public generateCommitMessage = async (
|
||||||
|
messages: Array<OpenAI.Chat.Completions.ChatCompletionMessageParam>
|
||||||
|
): Promise<string | null> => {
|
||||||
|
const params = {
|
||||||
|
model: this.config.model,
|
||||||
|
messages,
|
||||||
|
temperature: 0,
|
||||||
|
top_p: 0.1,
|
||||||
|
max_tokens: this.config.maxTokensOutput
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
const REQUEST_TOKENS = messages
|
||||||
|
.map((msg) => tokenCount(msg.content as string) + 4)
|
||||||
|
.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
if (
|
||||||
|
REQUEST_TOKENS >
|
||||||
|
this.config.maxTokensInput - this.config.maxTokensOutput
|
||||||
|
)
|
||||||
|
throw new Error(GenerateCommitMessageErrorEnum.tooMuchTokens);
|
||||||
|
|
||||||
|
const completion = await this.client.chat.completions.create(params);
|
||||||
|
|
||||||
|
const message = completion.choices[0].message;
|
||||||
|
|
||||||
|
return message?.content;
|
||||||
|
} catch (error) {
|
||||||
|
const err = error as Error;
|
||||||
|
if (
|
||||||
|
axios.isAxiosError<{ error?: { message: string } }>(error) &&
|
||||||
|
error.response?.status === 401
|
||||||
|
) {
|
||||||
|
const openAiError = error.response.data.error;
|
||||||
|
|
||||||
|
if (openAiError) throw new Error(openAiError.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,9 +33,14 @@ export class OllamaEngine implements AiEngine {
|
|||||||
params
|
params
|
||||||
);
|
);
|
||||||
|
|
||||||
const message = response.data.message;
|
const { message } = response.data;
|
||||||
|
let content = message?.content;
|
||||||
|
|
||||||
return message?.content;
|
if (content && content.includes('<think>')) {
|
||||||
|
return content.replace(/<think>[\s\S]*?<\/think>/g, '').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const message = err.response?.data?.error ?? err.message;
|
const message = err.response?.data?.error ?? err.message;
|
||||||
throw new Error(`Ollama provider error: ${message}`);
|
throw new Error(`Ollama provider error: ${message}`);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { MistralAiEngine } from '../engine/mistral';
|
|||||||
import { TestAi, TestMockType } from '../engine/testAi';
|
import { TestAi, TestMockType } from '../engine/testAi';
|
||||||
import { GroqEngine } from '../engine/groq';
|
import { GroqEngine } from '../engine/groq';
|
||||||
import { MLXEngine } from '../engine/mlx';
|
import { MLXEngine } from '../engine/mlx';
|
||||||
|
import { DeepseekEngine } from '../engine/deepseek';
|
||||||
|
|
||||||
export function getEngine(): AiEngine {
|
export function getEngine(): AiEngine {
|
||||||
const config = getConfig();
|
const config = getConfig();
|
||||||
@@ -51,6 +52,9 @@ export function getEngine(): AiEngine {
|
|||||||
case OCO_AI_PROVIDER_ENUM.MLX:
|
case OCO_AI_PROVIDER_ENUM.MLX:
|
||||||
return new MLXEngine(DEFAULT_CONFIG);
|
return new MLXEngine(DEFAULT_CONFIG);
|
||||||
|
|
||||||
|
case OCO_AI_PROVIDER_ENUM.DEEPSEEK:
|
||||||
|
return new DeepseekEngine(DEFAULT_CONFIG);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return new OpenAiEngine(DEFAULT_CONFIG);
|
return new OpenAiEngine(DEFAULT_CONFIG);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user