Skip to content

Commit 86d7e35

Browse files
authored
Merge branch 'main' into file
2 parents 3bf22de + 089a0d9 commit 86d7e35

File tree

8 files changed

+268
-78
lines changed

8 files changed

+268
-78
lines changed

package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,13 @@
6565
"@jupyterlab/rendermime": "^4.4.0",
6666
"@jupyterlab/settingregistry": "^4.4.0",
6767
"@jupyterlab/ui-components": "^4.4.0",
68-
"@langchain/anthropic": "^0.3.9",
69-
"@langchain/community": "^0.3.44",
70-
"@langchain/core": "^0.3.57",
71-
"@langchain/mistralai": "^0.1.1",
72-
"@langchain/ollama": "^0.2.0",
73-
"@langchain/openai": "^0.4.4",
68+
"@langchain/anthropic": "^0.3.22",
69+
"@langchain/community": "^0.3.46",
70+
"@langchain/core": "^0.3.58",
71+
"@langchain/google-genai": "^0.2.12",
72+
"@langchain/mistralai": "^0.2.1",
73+
"@langchain/ollama": "^0.2.2",
74+
"@langchain/openai": "^0.5.13",
7475
"@lumino/coreutils": "^2.1.2",
7576
"@lumino/polling": "^2.1.2",
7677
"@lumino/signaling": "^2.1.2",
@@ -115,6 +116,9 @@
115116
"typescript": "~5.8.3",
116117
"yjs": "^13.5.0"
117118
},
119+
"resolutions": {
120+
"zod": "^3.25.56"
121+
},
118122
"sideEffects": [
119123
"style/*.css",
120124
"style/index.js"

scripts/settings-checker.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ const providers = {
5252
type: 'ChromeAIInputs',
5353
excludedProps: ['systemPrompt']
5454
},
55+
ChatGoogleGenerativeAI: {
56+
path: 'node_modules/@langchain/google-genai/dist/chat_models.d.ts',
57+
type: 'ChatGoogleGenerativeAI'
58+
},
5559
MistralAI: {
5660
path: 'node_modules/@langchain/mistralai/dist/chat_models.d.ts',
5761
type: 'ChatMistralAIInput'
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {
2+
CompletionHandler,
3+
IInlineCompletionContext
4+
} from '@jupyterlab/completer';
5+
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
6+
import { AIMessage, SystemMessage } from '@langchain/core/messages';
7+
8+
import { BaseCompleter } from '../../base-completer';
9+
10+
export class GeminiCompleter extends BaseCompleter {
11+
constructor(options: BaseCompleter.IOptions) {
12+
super(options);
13+
this._completer = new ChatGoogleGenerativeAI({
14+
model: 'gemini-pro',
15+
...options.settings
16+
});
17+
}
18+
19+
async fetch(
20+
request: CompletionHandler.IRequest,
21+
context: IInlineCompletionContext
22+
) {
23+
const { text, offset: cursorOffset } = request;
24+
const prompt = text.slice(0, cursorOffset);
25+
26+
const trimmedPrompt = prompt.trim();
27+
28+
const messages = [
29+
new SystemMessage(this.systemPrompt),
30+
new AIMessage(trimmedPrompt)
31+
];
32+
33+
try {
34+
const response = await this._completer.invoke(messages);
35+
const items = [];
36+
37+
// Gemini can return string or complex content, a list of string/images/other.
38+
if (typeof response.content === 'string') {
39+
items.push({
40+
insertText: response.content
41+
});
42+
} else {
43+
response.content.forEach(content => {
44+
if (content.type !== 'text') {
45+
return;
46+
}
47+
items.push({
48+
insertText: content.text,
49+
filterText: prompt.substring(trimmedPrompt.length)
50+
});
51+
});
52+
}
53+
return { items };
54+
} catch (error) {
55+
console.error('Error fetching completions', error);
56+
return { items: [] };
57+
}
58+
}
59+
60+
protected _completer: ChatGoogleGenerativeAI;
61+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export default `
2+
<i class="fas fa-exclamation-triangle"></i> This extension is still very much experimental. It is not an official Google extension.
3+
4+
1. Go to <https://aistudio.google.com> and create an API key.
5+
6+
2. Open the JupyterLab settings and go to the **Ai providers** section to select the \`Gemini\`
7+
provider and add your API key (required).
8+
3. Open the chat, or use the inline completer.
9+
`;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"type": "object",
4+
"properties": {
5+
"temperature": {
6+
"type": "number",
7+
"description": "Amount of randomness injected into the response. Ranges from 0 to 1. Use temp closer to 0 for analytical / multiple choice, and temp closer to 1 for creative and generative tasks."
8+
},
9+
"topK": {
10+
"type": "number",
11+
"description": "Only sample from the top K options for each subsequent token. Used to remove \"long tail\" low probability responses."
12+
},
13+
"topP": {
14+
"type": "number",
15+
"description": "Nucleus sampling parameter. Only the smallest set of most probable tokens with probabilities that add up to top_p or higher are kept for generation."
16+
},
17+
"maxOutputTokens": {
18+
"type": "number",
19+
"description": "The maximum number of tokens to generate in the response."
20+
},
21+
"stopSequences": {
22+
"type": "array",
23+
"items": {
24+
"type": "string"
25+
},
26+
"description": "A list of strings upon which to stop generating. You probably want something like [\"\\n\\nHuman:\"] for chat conversations."
27+
},
28+
"streaming": {
29+
"type": "boolean",
30+
"description": "Whether to stream the results or not"
31+
},
32+
"apiKey": {
33+
"type": "string",
34+
"description": "Google AI Studio API key"
35+
},
36+
"model": {
37+
"type": "string",
38+
"description": "Model name to use (e.g., gemini-pro, gemini-2.0-flash, etc.)",
39+
"default": "gemini-pro"
40+
},
41+
"baseURL": {
42+
"type": "string",
43+
"description": "Base URL for the Google AI API"
44+
},
45+
"safetySettings": {
46+
"type": "array",
47+
"description": "Safety settings for content filtering",
48+
"items": {
49+
"type": "object",
50+
"properties": {
51+
"category": {
52+
"type": "string"
53+
},
54+
"threshold": {
55+
"type": "string"
56+
}
57+
}
58+
}
59+
}
60+
},
61+
"additionalProperties": false,
62+
"description": "Input to Google Generative AI Chat class.",
63+
"definitions": {}
64+
}

src/default-providers/MistralAI/completer.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,23 @@ export class CodestralCompleter extends BaseCompleter {
3636
false
3737
);
3838
const items = response.choices.map(choice => {
39-
const content = choice.message.content
40-
.replace(CODE_BLOCK_START_REGEX, '')
41-
.replace(CODE_BLOCK_END_REGEX, '');
39+
const messageContent = choice.message.content;
40+
let content = '';
41+
42+
if (typeof messageContent === 'string') {
43+
content = messageContent
44+
.replace(CODE_BLOCK_START_REGEX, '')
45+
.replace(CODE_BLOCK_END_REGEX, '');
46+
} else if (Array.isArray(messageContent)) {
47+
// Handle ContentChunk[] case - extract text content
48+
content = messageContent
49+
.filter(chunk => chunk.type === 'text')
50+
.map(chunk => chunk.text || '')
51+
.join('')
52+
.replace(CODE_BLOCK_START_REGEX, '')
53+
.replace(CODE_BLOCK_END_REGEX, '');
54+
}
55+
4256
return {
4357
insertText: content
4458
};

src/default-providers/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import { Notification } from '@jupyterlab/apputils';
77
import { ChatAnthropic } from '@langchain/anthropic';
88
import { ChatWebLLM } from '@langchain/community/chat_models/webllm';
99
import { ChromeAI } from '@langchain/community/experimental/llms/chrome_ai';
10+
import { ChatGoogleGenerativeAI } from '@langchain/google-genai';
1011
import { ChatMistralAI } from '@langchain/mistralai';
1112
import { ChatOllama } from '@langchain/ollama';
1213
import { ChatOpenAI } from '@langchain/openai';
1314

1415
// Import completers
1516
import { AnthropicCompleter } from './Anthropic/completer';
1617
import { ChromeCompleter } from './ChromeAI/completer';
18+
import { GeminiCompleter } from './Gemini/completer';
1719
import { CodestralCompleter } from './MistralAI/completer';
1820
import { OllamaCompleter } from './Ollama/completer';
1921
import { OpenAICompleter } from './OpenAI/completer';
@@ -22,6 +24,7 @@ import { WebLLMCompleter } from './WebLLM/completer';
2224
// Import Settings
2325
import AnthropicSettings from './Anthropic/settings-schema.json';
2426
import ChromeAISettings from './ChromeAI/settings-schema.json';
27+
import GeminiSettings from './Gemini/settings-schema.json';
2528
import MistralAISettings from './MistralAI/settings-schema.json';
2629
import OllamaAISettings from './Ollama/settings-schema.json';
2730
import OpenAISettings from './OpenAI/settings-schema.json';
@@ -31,6 +34,7 @@ import WebLLMSettings from './WebLLM/settings-schema.json';
3134
import ChromeAIInstructions, {
3235
compatibilityCheck as chromeAICompatibilityCheck
3336
} from './ChromeAI/instructions';
37+
import GeminiInstructions from './Gemini/instructions';
3438
import MistralAIInstructions from './MistralAI/instructions';
3539
import OllamaInstructions from './Ollama/instructions';
3640
import WebLLMInstructions, {
@@ -74,6 +78,13 @@ const AIProviders: IAIProvider[] = [
7478
instructions: OllamaInstructions,
7579
settingsSchema: OllamaAISettings
7680
},
81+
{
82+
name: 'Gemini',
83+
chat: ChatGoogleGenerativeAI,
84+
completer: GeminiCompleter,
85+
instructions: GeminiInstructions,
86+
settingsSchema: GeminiSettings
87+
},
7788
{
7889
name: 'OpenAI',
7990
chat: ChatOpenAI,

0 commit comments

Comments
 (0)