UNPKG

@genkit-ai/anthropic

Version:

Genkit AI framework plugin for Anthropic APIs.

140 lines (136 loc) 6.78 kB
import { Anthropic } from '@anthropic-ai/sdk'; import { DocumentBlockParam } from '@anthropic-ai/sdk/resources/messages'; import { Role, Part, MessageData, GenerateRequest, GenerateResponseData, GenerateResponseChunkData } from 'genkit'; import { ToolDefinition } from 'genkit/model'; import { ClaudeRunnerParams, MediaType, Media, ThinkingConfig, AnthropicConfigSchema } from '../types.mjs'; import { RunnerTypes, RunnerToolResponseContent, RunnerContentBlockParam, RunnerMessageParam, RunnerRequestBody, RunnerStreamingRequestBody, RunnerMessage, RunnerStream, RunnerStreamEvent } from './types.mjs'; /** * Copyright 2025 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * Shared runner logic for Anthropic SDK integrations. * * Concrete subclasses pass in their SDK-specific type bundle via `RunnerTypes`, * letting this base class handle message/tool translation once for both the * stable and beta APIs that share the same conceptual surface. */ declare abstract class BaseRunner<ApiTypes extends RunnerTypes> { protected name: string; protected client: Anthropic; /** * Default maximum output tokens for Claude models when not specified in the request. */ protected readonly DEFAULT_MAX_OUTPUT_TOKENS = 4096; constructor(params: ClaudeRunnerParams); /** * Converts a Genkit role to the corresponding Anthropic role. */ protected toAnthropicRole(role: Role, toolMessageType?: 'tool_use' | 'tool_result'): 'user' | 'assistant'; protected isMediaType(value: string): value is MediaType; protected isMediaObject(obj: unknown): obj is Media; /** * Checks if a URL is a data URL (starts with 'data:'). */ protected isDataUrl(url: string): boolean; protected extractDataFromBase64Url(url: string): { data: string; contentType: string; } | null; /** * Both the stable and beta Anthropic SDKs accept the same JSON shape for PDF * document sources (either `type: 'base64'` with a base64 payload or `type: 'url'` * with a public URL). Even though the return type references the stable SDK * union, TypeScript’s structural typing lets the beta runner reuse this helper. */ protected toPdfDocumentSource(media: Media): DocumentBlockParam['source']; /** * Normalizes Genkit `Media` into either a base64 payload or a remote URL * accepted by the Anthropic SDK. Anthropic supports both `data:` URLs (which * we forward as base64) and remote `https` URLs without additional handling. */ protected toImageSource(media: Media): { kind: 'base64'; data: string; mediaType: MediaType; } | { kind: 'url'; url: string; }; /** * Converts tool response output to the appropriate Anthropic content format. * Handles Media objects, data URLs, strings, and other outputs. */ protected toAnthropicToolResponseContent(part: Part): RunnerToolResponseContent<ApiTypes>; protected getThinkingSignature(part: Part): string | undefined; protected getRedactedThinkingData(part: Part): string | undefined; protected toAnthropicThinkingConfig(config: ThinkingConfig | undefined): { type: 'enabled'; budget_tokens: number; } | { type: 'disabled'; } | { type: 'adaptive'; display?: 'summarized' | 'omitted'; } | undefined; /** * Converts a Genkit Part to the corresponding Anthropic content block. * Each runner implements this to return its specific API type. */ protected abstract toAnthropicMessageContent(part: Part): RunnerContentBlockParam<ApiTypes>; /** * Converts Genkit messages to Anthropic format. * Extracts system message and converts remaining messages using the runner's * toAnthropicMessageContent implementation. */ protected toAnthropicMessages(messages: MessageData[]): { system?: RunnerContentBlockParam<ApiTypes>[]; messages: RunnerMessageParam<ApiTypes>[]; }; /** * Converts a Genkit ToolDefinition to an Anthropic Tool object. * * Anthropic requires `input_schema.type` to be present (usually `"object"`). * Genkit's `ToolDefinition` may have an empty schema (e.g. from `z.void()`) * which lacks the `type` field. We default to `{ type: "object" }` to * prevent 400 errors from the Anthropic API. */ protected toAnthropicTool(tool: ToolDefinition): ApiTypes['Tool']; /** * Converts an Anthropic request to a non-streaming Anthropic API request body. * @param modelName The name of the Anthropic model to use. * @param request The Genkit GenerateRequest to convert. * @returns The converted Anthropic API non-streaming request body. * @throws An error if an unsupported output format is requested. */ protected abstract toAnthropicRequestBody(modelName: string, request: GenerateRequest<typeof AnthropicConfigSchema>): RunnerRequestBody<ApiTypes>; /** * Converts an Anthropic request to a streaming Anthropic API request body. * @param modelName The name of the Anthropic model to use. * @param request The Genkit GenerateRequest to convert. * @returns The converted Anthropic API streaming request body. * @throws An error if an unsupported output format is requested. */ protected abstract toAnthropicStreamingRequestBody(modelName: string, request: GenerateRequest<typeof AnthropicConfigSchema>): RunnerStreamingRequestBody<ApiTypes>; protected abstract createMessage(body: RunnerRequestBody<ApiTypes>, abortSignal: AbortSignal): Promise<RunnerMessage<ApiTypes>>; protected abstract streamMessages(body: RunnerStreamingRequestBody<ApiTypes>, abortSignal: AbortSignal): RunnerStream<ApiTypes>; protected abstract toGenkitResponse(message: RunnerMessage<ApiTypes>): GenerateResponseData; protected abstract toGenkitPart(event: RunnerStreamEvent<ApiTypes>): Part | undefined; run(request: GenerateRequest<typeof AnthropicConfigSchema>, options: { streamingRequested: boolean; sendChunk: (chunk: GenerateResponseChunkData) => void; abortSignal: AbortSignal; }): Promise<GenerateResponseData>; } export { BaseRunner };