@genkit-ai/anthropic
Version:
Genkit AI framework plugin for Anthropic APIs.
140 lines (136 loc) • 6.77 kB
TypeScript
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.js';
import { RunnerTypes, RunnerToolResponseContent, RunnerContentBlockParam, RunnerMessageParam, RunnerRequestBody, RunnerStreamingRequestBody, RunnerMessage, RunnerStream, RunnerStreamEvent } from './types.js';
/**
* 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 };