Skip to content

feat: Integrate Google Gemini API support #859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

canweb221
Copy link

Adds support for using the Google Gemini API via an API key.

Key changes include:

  • Configuration:

    • Added geminiApiKey to defaultConfig in src/config/index.mjs.
    • Defined geminiApiModelKeys and added 'Gemini (API, Pro)' to Models and ModelGroups.
    • Added 'geminiApiPro' to the default activeApiModes.
  • API Client:

    • Created src/services/apis/gemini-api.mjs with logic to connect to the Gemini API using the configured API key. Includes placeholder for the exact API endpoint and payload structure.
  • User Interface:

    • Added an input field in src/popup/sections/GeneralPart.jsx for you to enter your Gemini API key. This field is conditionally displayed when a Gemini API model is active.
  • Integration:

    • Updated src/background/index.mjs to route requests to the generateAnswersWithGeminiApi client when a Gemini model is selected.

Manual testing with a valid Gemini API key is required to fully verify the functionality.

Adds support for using the Google Gemini API via an API key.

Key changes include:

- Configuration:
  - Added `geminiApiKey` to `defaultConfig` in `src/config/index.mjs`.
  - Defined `geminiApiModelKeys` and added 'Gemini (API, Pro)' to `Models` and `ModelGroups`.
  - Added 'geminiApiPro' to the default `activeApiModes`.

- API Client:
  - Created `src/services/apis/gemini-api.mjs` with logic to connect to the
    Gemini API using the configured API key. Includes placeholder for the
    exact API endpoint and payload structure.

- User Interface:
  - Added an input field in `src/popup/sections/GeneralPart.jsx` for you
    to enter your Gemini API key. This field is conditionally displayed
    when a Gemini API model is active.

- Integration:
  - Updated `src/background/index.mjs` to route requests to the
    `generateAnswersWithGeminiApi` client when a Gemini model is selected.

Manual testing with a valid Gemini API key is required to fully verify
the functionality.
@PeterDaveHello PeterDaveHello requested a review from Copilot May 31, 2025 20:18
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces support for the Google Gemini API by integrating a new API client, updating configuration, and adding a user interface input for the Gemini API key.

  • Added a new service module for communicating with the Gemini API.
  • Updated configuration and UI components to handle the Gemini API key.
  • Integrated Gemini API support in the background routing for generating answers.

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/services/apis/gemini-api.mjs New API client added to connect to the Gemini API.
src/popup/sections/GeneralPart.jsx Added conditional input field for Gemini API key.
src/config/index.mjs Updated configuration with Gemini API keys and models.
src/background/index.mjs Routed requests to the new Gemini API client.

{isUsingGeminiApiModel(config) && (
<input
type="password"
style="width: 50%;"
Copy link
Preview

Copilot AI May 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In React, the style prop should be provided as an object (e.g., style={{ width: '50%' }}) rather than a string literal to ensure proper rendering.

Suggested change
style="width: 50%;"
style={{ width: '50%' }}

Copilot uses AI. Check for mistakes.

@PeterDaveHello
Copy link
Member

/review

Copy link

qodo-merge-pro bot commented Jun 2, 2025

Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🧪 No relevant tests
🔒 Security concerns

Sensitive information exposure:
The PR adds a new API key field for Gemini in the UI. While the input is properly set as type="password" to mask the key visually, there should be additional checks to ensure the API key is stored securely and not exposed in logs or network requests (beyond the authenticated API call itself). The current implementation directly includes the API key as a query parameter in line 38, which could expose it in server logs. Consider using an Authorization header instead.

⚡ Recommended focus areas for review

Error Handling

The error handling in the Gemini API client could be improved. The code attempts to extract error messages from the response but may not handle all error scenarios correctly, especially when the response structure is different than expected.

if (!response.ok) {
  const errorData = await response.json().catch(() => ({ message: response.statusText }));
  console.error('Gemini API error:', errorData);
  port.postMessage({ error: `Gemini API error: ${errorData.error?.message || errorData.message || 'Unknown error'}`, done: true, session });
  return;
}
API Implementation

The Gemini API implementation is using placeholder structures that need verification against the actual API documentation. The payload structure and response parsing logic may need adjustments to match Google's Gemini API specifications.

// Construct the request payload
// This is a placeholder structure and needs to be verified against Gemini API documentation
const payload = {
  contents: [{
    parts: [{
      text: question,
    }],
  }],
  // generationConfig: { // Optional: configure temperature, maxOutputTokens, etc.
  //   temperature: config.temperature,
  //   maxOutputTokens: config.maxResponseTokenLength,
  // },
  // safetySettings: [ // Optional: configure safety settings
  //   { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  // ],
};

const response = await fetch(`${GEMINI_API_ENDPOINT}?key=${apiKey}`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload),
});

if (!response.ok) {
  const errorData = await response.json().catch(() => ({ message: response.statusText }));
  console.error('Gemini API error:', errorData);
  port.postMessage({ error: `Gemini API error: ${errorData.error?.message || errorData.message || 'Unknown error'}`, done: true, session });
  return;
}

const responseData = await response.json();

// Extract the answer from the responseData
// This is a placeholder and needs to be verified against actual Gemini API response structure
// Expected structure: responseData.candidates[0].content.parts[0].text
let answer = 'No response from Gemini API.';
if (responseData.candidates && responseData.candidates[0] && responseData.candidates[0].content && responseData.candidates[0].content.parts && responseData.candidates[0].content.parts[0]) {
  answer = responseData.candidates[0].content.parts[0].text;
} else {
    console.error('Unexpected Gemini API response structure:', responseData);
}
Missing Conversation History

The implementation doesn't appear to handle conversation history properly. Unlike other API implementations, it doesn't seem to send previous messages in the conversation to maintain context.

const payload = {
  contents: [{
    parts: [{
      text: question,
    }],
  }],
  // generationConfig: { // Optional: configure temperature, maxOutputTokens, etc.
  //   temperature: config.temperature,
  //   maxOutputTokens: config.maxResponseTokenLength,
  // },
  // safetySettings: [ // Optional: configure safety settings
  //   { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  //   { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
  // ],
};

@PeterDaveHello
Copy link
Member

/improve

Copy link

qodo-merge-pro bot commented Jun 2, 2025

Qodo Merge was enabled for this repository. To continue using it, please link your Git account with your Qodo account here.

PR Code Suggestions ✨

CategorySuggestion                                                                                                                                    Impact
Possible issue
Add conversation history support

Include conversation history in the Gemini API request to maintain context
across messages. The current implementation only sends the current question
without previous context, which will result in the AI not remembering previous
interactions.

src/services/apis/gemini-api.mjs [20-36]

 const payload = {
-  contents: [{
-    parts: [{
-      text: question,
-    }],
-  }],
+  contents: [
+    ...session.conversationRecords.map(record => ({
+      parts: [{ text: record.question }, { text: record.answer }]
+    })),
+    {
+      parts: [{
+        text: question,
+      }],
+    }
+  ],
   // generationConfig: { // Optional: configure temperature, maxOutputTokens, etc.
   //   temperature: config.temperature,
   //   maxResponseTokenLength: config.maxResponseTokenLength,
   // },
   // safetySettings: [ // Optional: configure safety settings
   //   { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
   //   { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
   //   { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
   //   { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_MEDIUM_AND_ABOVE' },
   // ],
 };
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: This addresses a significant functional issue where the API would lose conversation context between messages. Including session.conversationRecords in the payload is important for maintaining chat continuity.

Medium
Use dynamic model selection

Use the model specified in the session rather than hardcoding 'gemini-pro'. This
ensures the correct model is used when multiple Gemini models are supported in
the future, maintaining consistency with how other APIs are implemented.

src/services/apis/gemini-api.mjs [6]

-const GEMINI_API_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent';
+const GEMINI_API_ENDPOINT = `https://generativelanguage.googleapis.com/v1beta/models/${session.modelName}:generateContent`;
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: Good suggestion for future extensibility to support multiple Gemini models. Using session.modelName instead of hardcoding gemini-pro aligns with the architecture of other API implementations in the codebase.

Low
Fix configuration parameters

Uncomment and fix the generationConfig section to properly use the user's
configuration settings. The Gemini API uses maxOutputTokens but the code
incorrectly references maxResponseTokenLength.

src/services/apis/gemini-api.mjs [26-29]

-// generationConfig: { // Optional: configure temperature, maxOutputTokens, etc.
-//   temperature: config.temperature,
-//   maxResponseTokenLength: config.maxResponseTokenLength,
-// },
+generationConfig: {
+  temperature: config.temperature,
+  maxOutputTokens: config.maxTokens || 4096,
+},
  • Apply / Chat
Suggestion importance[1-10]: 5

__

Why: Correctly identifies that maxOutputTokens is the proper Gemini API parameter name, but assumes config.temperature and config.maxTokens exist when they're not defined in the PR's defaultConfig.

Low
  • More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants