| 68 | }; |
| 69 | |
| 70 | export class GeminiEngine implements AiEngine { |
| 71 | config: GeminiConfig; |
| 72 | client: GoogleGenerativeAI; |
| 73 | |
| 74 | constructor(config) { |
| 75 | this.client = new GoogleGenerativeAI(config.apiKey); |
| 76 | this.config = config; |
| 77 | } |
| 78 | |
| 79 | async generateCommitMessage( |
| 80 | messages: Array<OpenAI.Chat.Completions.ChatCompletionMessageParam> |
| 81 | ): Promise<string | undefined> { |
| 82 | const systemInstruction = messages |
| 83 | .filter((m) => m.role === 'system') |
| 84 | .map((m) => m.content) |
| 85 | .join('\n'); |
| 86 | |
| 87 | const gemini = this.client.getGenerativeModel( |
| 88 | { |
| 89 | model: this.config.model, |
| 90 | systemInstruction |
| 91 | }, |
| 92 | { |
| 93 | baseUrl: this.config.baseURL |
| 94 | } |
| 95 | ); |
| 96 | |
| 97 | const contents = messages |
| 98 | .filter((m) => m.role !== 'system') |
| 99 | .map( |
| 100 | (m) => |
| 101 | ({ |
| 102 | parts: [{ text: m.content } as Part], |
| 103 | role: m.role === 'user' ? m.role : 'model' |
| 104 | } as Content) |
| 105 | ); |
| 106 | |
| 107 | try { |
| 108 | const result = await gemini.generateContent({ |
| 109 | contents, |
| 110 | safetySettings: [ |
| 111 | { |
| 112 | category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, |
| 113 | threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE |
| 114 | }, |
| 115 | { |
| 116 | category: HarmCategory.HARM_CATEGORY_HARASSMENT, |
| 117 | threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE |
| 118 | }, |
| 119 | { |
| 120 | category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, |
| 121 | threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE |
| 122 | }, |
| 123 | { |
| 124 | category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, |
| 125 | threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE |
| 126 | } |
| 127 | ], |
nothing calls this directly
no outgoing calls
no test coverage detected
searching dependent graphs…