All files / src/providers/gemini GeminiProvider.ts

76.66% Statements 23/30
100% Branches 2/2
66.66% Functions 14/21
76.66% Lines 23/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105                                                                        19x 1x 1x 1x 2x 1x 1x             19x 19x 19x 19x 19x 19x 19x 19x 19x                           28x               9x       1x       2x       2x       3x       2x          
import {
  Provider,
  ChatRequest,
  ChatResponse,
  ModelInfo,
  ChatChunk,
  ImageRequest,
  ImageResponse,
  TranscriptionRequest,
  TranscriptionResponse,
  EmbeddingRequest,
  EmbeddingResponse
} from "../Provider.js";
import { BaseProvider } from "../BaseProvider.js";
import { Capabilities } from "./Capabilities.js";
import { GeminiChat } from "./Chat.js";
import { GeminiStreaming } from "./Streaming.js";
import { GeminiModels } from "./Models.js";
import { GeminiImage } from "./Image.js";
import { GeminiEmbeddings } from "./Embeddings.js";
import { GeminiTranscription } from "./Transcription.js";
 
export interface GeminiProviderOptions {
  apiKey: string;
  baseUrl?: string;
}
 
export class GeminiProvider extends BaseProvider implements Provider {
  private readonly baseUrl: string;
  private readonly chatHandler: GeminiChat;
  private readonly streamingHandler: GeminiStreaming;
  private readonly modelsHandler: GeminiModels;
  private readonly imageHandler: GeminiImage;
  private readonly embeddingHandler: GeminiEmbeddings;
  private readonly transcriptionHandler: GeminiTranscription;
 
  public capabilities = {
    supportsVision: (model: string) => Capabilities.supportsVision(model),
    supportsTools: (model: string) => Capabilities.supportsTools(model),
    supportsStructuredOutput: (model: string) => Capabilities.supportsStructuredOutput(model),
    supportsEmbeddings: (model: string) => Capabilities.supportsEmbeddings(model),
    supportsImageGeneration: (model: string) => Capabilities.supportsImageGeneration(model),
    supportsTranscription: (model: string) => Capabilities.supportsTranscription(model),
    supportsModeration: (model: string) => Capabilities.supportsModeration(model),
    supportsReasoning: (_model: string) => false,
    supportsDeveloperRole: (_model: string) => true,
    getContextWindow: (model: string) => Capabilities.getContextWindow(model)
  };
 
  constructor(private readonly options: GeminiProviderOptions) {
    super();
    this.baseUrl = options.baseUrl ?? "https://generativelanguage.googleapis.com/v1beta";
    this.chatHandler = new GeminiChat(this.baseUrl, options.apiKey);
    this.streamingHandler = new GeminiStreaming(this.baseUrl, options.apiKey);
    this.modelsHandler = new GeminiModels(this.baseUrl, options.apiKey);
    this.imageHandler = new GeminiImage(this.baseUrl, options.apiKey);
    this.embeddingHandler = new GeminiEmbeddings(this.baseUrl, options.apiKey);
    this.transcriptionHandler = new GeminiTranscription(this.baseUrl, options.apiKey);
  }
 
  public apiBase(): string {
    return this.baseUrl;
  }
 
  public headers(): Record<string, string> {
    return {
      "Content-Type": "application/json"
    };
  }
 
  protected providerName(): string {
    return "Gemini";
  }
 
  public override defaultModel(_feature?: string): string {
    return "gemini-2.0-flash-exp";
  }
 
  async chat(request: ChatRequest): Promise<ChatResponse> {
    return this.chatHandler.execute(request);
  }
 
  async *stream(request: ChatRequest): AsyncGenerator<ChatChunk> {
    yield* this.streamingHandler.execute(request);
  }
 
  async listModels(): Promise<ModelInfo[]> {
    return this.modelsHandler.execute();
  }
 
  async paint(request: ImageRequest): Promise<ImageResponse> {
    return this.imageHandler.execute(request);
  }
 
  async embed(request: EmbeddingRequest): Promise<EmbeddingResponse> {
    return this.embeddingHandler.execute(request);
  }
 
  async transcribe(request: TranscriptionRequest): Promise<TranscriptionResponse> {
    return this.transcriptionHandler.execute(request);
  }
 
  // Moderation is not supported - will use BaseProvider's default implementation
}