From 84c63696e8fe16045a605f602fd53bfcd60bdf01 Mon Sep 17 00:00:00 2001 From: wajeht <58354193+wajeht@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:28:12 -0600 Subject: [PATCH 1/2] chore(ci): Update CI workflow to include DEEPSEEK_API_KEY and deepseekAI --- .env.example | 1 + .github/workflows/ci.yml | 1 + .vscode/settings.json | 4 ++++ src/ai.ts | 38 ++++++++++++++++++++++++++++++++++++++ src/commit.sh | 4 ++-- src/config.ts | 5 +++++ src/handler.ts | 2 +- src/types.ts | 4 ++-- src/util.ts | 4 ++-- 9 files changed, 56 insertions(+), 7 deletions(-) diff --git a/.env.example b/.env.example index dd79847..848d17a 100644 --- a/.env.example +++ b/.env.example @@ -3,6 +3,7 @@ IPS="420.69.247.365" NODE_ENV="development" OPENAI_API_KEY="DEEZ" CLAUDE_API_KEY="NUTZ" +DEEPSEEK_API_KEY="BALLZ" # notify NOTIFY_URL="https://notify.jaw.dev" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5f4853..217f3d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,7 @@ env: NODE_ENV: 'testing' OPENAI_API_KEY: 'DEEZ' CLAUDE_API_KEY: 'NUTZ' + DEEPSEEK_API_KEY: 'BALLZ' DISCORD_WEBHOOK_URL: 'x' jobs: diff --git a/.vscode/settings.json b/.vscode/settings.json index fec1d2c..4390697 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,10 +2,14 @@ "cSpell.words": [ "adminjs", "aicommit", + "BALLZ", "claudeai", + "deepseek", + "DEEZ", "fastq", "healthz", "nofollow", + "NUTZ", "openai", "pacman", "Tahoma", diff --git a/src/ai.ts b/src/ai.ts index adeebd3..5cd4cc2 100644 --- a/src/ai.ts +++ b/src/ai.ts @@ -142,10 +142,48 @@ export const claudeAI: AIService = { }, }; +export const deepseekAI: AIService = { + generate: async (diff: string, apiKey?: string) => { + try { + const API_KEY = apiKey ? apiKey : appConfig.DEEPSEEK_API_KEY; + const chatCompletion = await new OpenAI({ + baseURL: 'https://api.deepseek.com', + apiKey: API_KEY, + }).chat.completions.create({ + model: 'deepseek-chat', + temperature: 0.7, + max_tokens: 200, + stream: false, + messages: [ + { + role: 'system', + content: prompt, + }, + { + role: 'user', + content: diff, + }, + ], + }); + const messages = chatCompletion.choices + .filter((choice) => choice.message?.content) + .map((choice) => choice.message.content); + return getRandomElement(messages); + } catch (error: any) { + if (error?.error?.type === 'invalid_api_key') { + throw new UnauthorizedError(error.message); + } + throw error; + } + }, +}; + export function ai(type?: Provider): AIService { switch (type) { case 'claudeai': return claudeAI; + case 'deepseek': + return deepseekAI; case 'openai': default: return openAI; diff --git a/src/commit.sh b/src/commit.sh index d57023d..42cad93 100755 --- a/src/commit.sh +++ b/src/commit.sh @@ -32,7 +32,7 @@ show_help() { printf "${YELLOW}Options:${NC}\n" printf " ${GREEN}-dr, --dry-run${NC} Run the script without making any changes\n" printf " ${GREEN}-nv, --no-verify${NC} Skip message selection\n" - printf " ${GREEN}-ai, --ai-provider${NC} Specify AI provider (openai or claude, default: openai)\n" + printf " ${GREEN}-ai, --ai-provider${NC} Specify AI provider (openai, claude or deepseek, default: openai)\n" printf " ${GREEN}-k, --api-key${NC} Specify the API key for the AI provider\n" printf " ${GREEN}-v, --verbose${NC} Enable verbose logging\n" printf " ${GREEN}-h, --help${NC} Display this help message\n" @@ -71,7 +71,7 @@ parse_arguments() { -ai|--ai-provider) AI_PROVIDER=$2 log_verbose "AI provider set to: " "$AI_PROVIDER" - if [[ "$AI_PROVIDER" != "openai" && "$AI_PROVIDER" != "claudeai" ]]; then + if [[ "$AI_PROVIDER" != "openai" && "$AI_PROVIDER" != "claudeai" && "$AI_PROVIDER" != "deepseek" ]]; then log_verbose "Invalid AI provider specified" echo -e "${RED}Invalid AI provider. Please use 'openai' or 'claudeai'.${NC}\n" exit 1 diff --git a/src/config.ts b/src/config.ts index 1fdc289..f23d0cc 100644 --- a/src/config.ts +++ b/src/config.ts @@ -42,4 +42,9 @@ export const appConfig = validateConfig({ required: false, type: (value: any) => value as 'development' | 'production', }, + DEEPSEEK_API_KEY: { + value: process.env.DEEPSEEK_API_KEY, + required: true, + type: (value: any) => String(value), + }, }); diff --git a/src/handler.ts b/src/handler.ts index 47d9474..d050321 100644 --- a/src/handler.ts +++ b/src/handler.ts @@ -120,7 +120,7 @@ export function postGenerateCommitMessageHandler(ai: (type?: Provider) => AIServ throw new ValidationError('Diff must not be empty!'); } - if (provider && provider !== 'openai' && provider !== 'claudeai') { + if (provider && provider !== 'openai' && provider !== 'claudeai' && provider !== 'deepseek') { throw new ValidationError('Invalid provider specified!'); } diff --git a/src/types.ts b/src/types.ts index 8e92780..c9566f3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,6 @@ import { Request } from 'express'; -export type Provider = 'openai' | 'claudeai'; +export type Provider = 'openai' | 'claudeai' | 'deepseek'; export interface GenerateCommitMessageRequest extends Request { body: { @@ -27,7 +27,7 @@ export interface ConfigItem { readonly required: boolean; } -export interface Logger { +export interface LoggerType { debug: (...value: any) => void; error: (...value: any) => void; info: (...value: any) => void; diff --git a/src/util.ts b/src/util.ts index 6fe1e1a..48a47ee 100644 --- a/src/util.ts +++ b/src/util.ts @@ -2,7 +2,7 @@ import fastq from 'fastq'; import { Request } from 'express'; import { styleText } from 'node:util'; import { appConfig } from './config'; -import { CacheType, ConfigItem, Logger } from './types'; +import { CacheType, ConfigItem, LoggerType } from './types'; export const sendNotificationQueue = fastq.promise(sendNotification, 1); @@ -81,7 +81,7 @@ function Cache(): CacheType { export const cache = Cache(); -export const logger: Logger = { +export const logger: LoggerType = { debug: (...value: any) => { const timestamp = new Date().toLocaleString(); console.debug(styleText('red', `🐛 ${timestamp} ${value}`)); From 4bad18450d16342f242295452d131fcbe657a0a3 Mon Sep 17 00:00:00 2001 From: wajeht <58354193+wajeht@users.noreply.github.com> Date: Wed, 22 Jan 2025 21:30:23 -0600 Subject: [PATCH 2/2] chore: Update package dependencies to latest versions --- .vscode/settings.json | 1 + package-lock.json | 64 +++++++++++++++++++++++-------------------- package.json | 12 ++++---- 3 files changed, 41 insertions(+), 36 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4390697..eb72211 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,6 +6,7 @@ "claudeai", "deepseek", "DEEZ", + "egenerate", "fastq", "healthz", "nofollow", diff --git a/package-lock.json b/package-lock.json index 288f3d2..11da120 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,26 +9,26 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@anthropic-ai/sdk": "^0.32.1", + "@anthropic-ai/sdk": "^0.35.0", "compression": "^1.7.5", "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^5.0.1", "express-rate-limit": "^7.5.0", - "fastq": "^1.17.1", + "fastq": "^1.18.0", "helmet": "^8.0.0", - "openai": "^4.77.0", - "typescript": "^5.7.2" + "openai": "^4.80.0", + "typescript": "^5.7.3" }, "devDependencies": { "@types/compression": "^1.7.5", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", - "@types/node": "^22.10.2", + "@types/node": "^22.10.8", "@typescript-eslint/eslint-plugin": "^7.16.1", "@typescript-eslint/parser": "^7.16.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-prettier": "^5.2.3", "husky": "^9.1.7", "prettier": "^3.4.2", "tsx": "^4.19.2" @@ -38,9 +38,9 @@ } }, "node_modules/@anthropic-ai/sdk": { - "version": "0.32.1", - "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.32.1.tgz", - "integrity": "sha512-U9JwTrDvdQ9iWuABVsMLj8nJVwAyQz6QXvgLsVhryhCEPkLsbcP/MXxm+jYcAwLoV8ESbaTTjnD4kuAFa+Hyjg==", + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.35.0.tgz", + "integrity": "sha512-JxVuNIRLjcXZbDW/rJa3vSIoYB5c0wgIQUPsjueeqli9OJyCJpInj0UlvKSSk6R2oCYyg0y2M0H8n8Wyt0l1IA==", "license": "MIT", "dependencies": { "@types/node": "^18.11.18", @@ -757,9 +757,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.10.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.8.tgz", + "integrity": "sha512-rk+QvAEGsbX/ZPiiyel6hJHNUS9cnSbPWVaZLvE+Er3tLqQFzWMz9JOfWW7XUmKvRPfxJfbl3qYWve+RGXncFw==", "license": "MIT", "dependencies": { "undici-types": "~6.20.0" @@ -1430,9 +1430,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, "license": "MIT", "peer": true, @@ -1721,9 +1721,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz", + "integrity": "sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw==", "dev": true, "license": "MIT", "dependencies": { @@ -2049,9 +2049,9 @@ "peer": true }, "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -2788,9 +2788,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -2960,9 +2960,9 @@ } }, "node_modules/openai": { - "version": "4.77.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.77.0.tgz", - "integrity": "sha512-WWacavtns/7pCUkOWvQIjyOfcdr9X+9n9Vvb0zFeKVDAqwCMDHB+iSr24SVaBAhplvSG6JrRXFpcNM9gWhOGIw==", + "version": "4.80.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.80.0.tgz", + "integrity": "sha512-5TqdNQgjOMxo3CkCvtjzuSwuznO/o3q5aak0MTy6IjRvPtvVA1wAFGJU3eZT1JHzhs2wFb/xtDG0o6Y/2KGCfw==", "license": "Apache-2.0", "dependencies": { "@types/node": "^18.11.18", @@ -2977,9 +2977,13 @@ "openai": "bin/cli" }, "peerDependencies": { + "ws": "^8.18.0", "zod": "^3.23.8" }, "peerDependenciesMeta": { + "ws": { + "optional": true + }, "zod": { "optional": true } @@ -3729,9 +3733,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index f5a5760..5d5dffe 100644 --- a/package.json +++ b/package.json @@ -33,26 +33,26 @@ "node": ">=22.3.0" }, "dependencies": { - "@anthropic-ai/sdk": "^0.32.1", + "@anthropic-ai/sdk": "^0.35.0", "compression": "^1.7.5", "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^5.0.1", "express-rate-limit": "^7.5.0", - "fastq": "^1.17.1", + "fastq": "^1.18.0", "helmet": "^8.0.0", - "openai": "^4.77.0", - "typescript": "^5.7.2" + "openai": "^4.80.0", + "typescript": "^5.7.3" }, "devDependencies": { "@types/compression": "^1.7.5", "@types/cors": "^2.8.17", "@types/express": "^5.0.0", - "@types/node": "^22.10.2", + "@types/node": "^22.10.8", "@typescript-eslint/eslint-plugin": "^7.16.1", "@typescript-eslint/parser": "^7.16.1", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-prettier": "^5.2.3", "husky": "^9.1.7", "prettier": "^3.4.2", "tsx": "^4.19.2"