@@ -2,11 +2,14 @@ import { execSync } from "child_process";
22import fetch from "node-fetch" ;
33import { CohereClient } from "cohere-ai" ;
44import dotenv from "dotenv" ;
5+ import fs from "fs/promises" ;
6+ import path from "path" ;
57
68// Load environment variables
79dotenv . config ( ) ;
810
911const DEEPSEEK_API_URL = "https://api.deepseek.com/v1/chat/completions" ;
12+ const PERFORMANCE_LOG_FILE = "model_performance.jsonl" ;
1013
1114// Initialize Cohere client if API key is available
1215let cohereClient = null ;
@@ -16,67 +19,131 @@ if (process.env.COHERE_API_KEY) {
1619 } ) ;
1720}
1821
22+ const logPerformance = async ( data ) => {
23+ try {
24+ const logEntry = {
25+ ...data ,
26+ timestamp : new Date ( ) . toISOString ( ) ,
27+ git_hash : execSync ( "git rev-parse HEAD" ) . toString ( ) . trim ( ) ,
28+ files_changed : execSync ( "git diff --staged --name-only" )
29+ . toString ( )
30+ . split ( "\n" )
31+ . filter ( Boolean ) ,
32+ } ;
33+
34+ await fs . appendFile ( PERFORMANCE_LOG_FILE , JSON . stringify ( logEntry ) + "\n" ) ;
35+ } catch ( error ) {
36+ console . error ( "Failed to log performance:" , error ) ;
37+ }
38+ } ;
39+
1940const generateWithCohere = async ( prompt ) => {
2041 if ( ! cohereClient ) {
2142 throw new Error ( "Cohere API key not configured" ) ;
2243 }
2344
24- const response = await cohereClient . generate ( {
25- prompt : prompt ,
26- maxTokens : 50 ,
27- temperature : 0.05 ,
28- stopSequences : [ "\n" ] ,
29- } ) ;
45+ const startTime = Date . now ( ) ;
46+ try {
47+ const response = await cohereClient . generate ( {
48+ prompt : prompt ,
49+ maxTokens : 50 ,
50+ temperature : 0.05 ,
51+ stopSequences : [ "\n" ] ,
52+ } ) ;
3053
31- if ( ! response . generations || response . generations . length === 0 ) {
32- throw new Error ( "No response from Cohere API" ) ;
33- }
54+ if ( ! response . generations || response . generations . length === 0 ) {
55+ throw new Error ( "No response from Cohere API" ) ;
56+ }
57+
58+ const message = response . generations [ 0 ] . text . trim ( ) ;
59+ const duration = Date . now ( ) - startTime ;
3460
35- return response . generations [ 0 ] . text . trim ( ) ;
61+ await logPerformance ( {
62+ provider : "cohere" ,
63+ duration_ms : duration ,
64+ success : true ,
65+ tokens_used : response . generations [ 0 ] . tokens || 0 ,
66+ message,
67+ } ) ;
68+
69+ return message ;
70+ } catch ( error ) {
71+ const duration = Date . now ( ) - startTime ;
72+ await logPerformance ( {
73+ provider : "cohere" ,
74+ duration_ms : duration ,
75+ success : false ,
76+ error : error . message ,
77+ } ) ;
78+ throw error ;
79+ }
3680} ;
3781
3882const generateWithDeepseek = async ( prompt ) => {
3983 if ( ! process . env . DEEPSEEK_API_KEY ) {
4084 throw new Error ( "Deepseek API key not configured" ) ;
4185 }
4286
43- const response = await fetch ( DEEPSEEK_API_URL , {
44- method : "POST" ,
45- headers : {
46- "Content-Type" : "application/json" ,
47- Authorization : `Bearer ${ process . env . DEEPSEEK_API_KEY } ` ,
48- } ,
49- body : JSON . stringify ( {
50- model : "deepseek-chat" ,
51- messages : [
52- {
53- role : "system" ,
54- content :
55- "You are a commit message generator that follows conventional commit format strictly." ,
56- } ,
57- {
58- role : "user" ,
59- content : prompt ,
60- } ,
61- ] ,
62- max_tokens : 50 ,
63- temperature : 0.05 ,
64- stop : [ "\n" ] ,
65- } ) ,
66- } ) ;
87+ const startTime = Date . now ( ) ;
88+ try {
89+ const response = await fetch ( DEEPSEEK_API_URL , {
90+ method : "POST" ,
91+ headers : {
92+ "Content-Type" : "application/json" ,
93+ Authorization : `Bearer ${ process . env . DEEPSEEK_API_KEY } ` ,
94+ } ,
95+ body : JSON . stringify ( {
96+ model : "deepseek-chat" ,
97+ messages : [
98+ {
99+ role : "system" ,
100+ content :
101+ "You are a commit message generator that follows conventional commit format strictly." ,
102+ } ,
103+ {
104+ role : "user" ,
105+ content : prompt ,
106+ } ,
107+ ] ,
108+ max_tokens : 50 ,
109+ temperature : 0.05 ,
110+ stop : [ "\n" ] ,
111+ } ) ,
112+ } ) ;
67113
68- if ( ! response . ok ) {
69- throw new Error (
70- `Deepseek API error: ${ response . status } ${ response . statusText } `
71- ) ;
72- }
114+ if ( ! response . ok ) {
115+ throw new Error (
116+ `Deepseek API error: ${ response . status } ${ response . statusText } `
117+ ) ;
118+ }
73119
74- const data = await response . json ( ) ;
75- if ( ! data . choices || data . choices . length === 0 ) {
76- throw new Error ( "No response from Deepseek API" ) ;
77- }
120+ const data = await response . json ( ) ;
121+ if ( ! data . choices || data . choices . length === 0 ) {
122+ throw new Error ( "No response from Deepseek API" ) ;
123+ }
124+
125+ const message = data . choices [ 0 ] . message . content . trim ( ) ;
126+ const duration = Date . now ( ) - startTime ;
78127
79- return data . choices [ 0 ] . message . content . trim ( ) ;
128+ await logPerformance ( {
129+ provider : "deepseek" ,
130+ duration_ms : duration ,
131+ success : true ,
132+ tokens_used : data . usage ?. total_tokens || 0 ,
133+ message,
134+ } ) ;
135+
136+ return message ;
137+ } catch ( error ) {
138+ const duration = Date . now ( ) - startTime ;
139+ await logPerformance ( {
140+ provider : "deepseek" ,
141+ duration_ms : duration ,
142+ success : false ,
143+ error : error . message ,
144+ } ) ;
145+ throw error ;
146+ }
80147} ;
81148
82149export const generateAICommitMessage = async ( preferredProvider = "cohere" ) => {
@@ -145,12 +212,17 @@ export const generateAICommitMessage = async (preferredProvider = "cohere") => {
145212
146213 // Try preferred provider first, then fallback
147214 let message ;
215+ let usedFallback = false ;
216+ let finalProvider = preferredProvider ;
217+
148218 try {
149219 message = await ( preferredProvider === "deepseek"
150220 ? generateWithDeepseek ( prompt )
151221 : generateWithCohere ( prompt ) ) ;
152222 } catch ( error ) {
153223 console . log ( `Failed with ${ preferredProvider } , trying fallback...` ) ;
224+ usedFallback = true ;
225+ finalProvider = preferredProvider === "deepseek" ? "cohere" : "deepseek" ;
154226 message = await ( preferredProvider === "deepseek"
155227 ? generateWithCohere ( prompt )
156228 : generateWithDeepseek ( prompt ) ) ;
@@ -171,13 +243,28 @@ export const generateAICommitMessage = async (preferredProvider = "cohere") => {
171243 console . log ( "Cleaned message:" , message ) ;
172244
173245 // Validate the message follows conventional commit format
174- if ( ! isValidCommitMessage ( message ) ) {
246+ const isValid = isValidCommitMessage ( message ) ;
247+ if ( ! isValid ) {
175248 console . log ( "\nInvalid message generated:" , message ) ;
249+ await logPerformance ( {
250+ provider : finalProvider ,
251+ used_fallback : usedFallback ,
252+ message_valid : false ,
253+ final_message : message ,
254+ validation_error : "Does not follow conventional commit format" ,
255+ } ) ;
176256 throw new Error (
177257 "Generated message does not follow conventional commit format"
178258 ) ;
179259 }
180260
261+ await logPerformance ( {
262+ provider : finalProvider ,
263+ used_fallback : usedFallback ,
264+ message_valid : true ,
265+ final_message : message ,
266+ } ) ;
267+
181268 return message ;
182269 } catch ( error ) {
183270 console . error ( "Error generating AI commit message:" , error . message ) ;
0 commit comments