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 };
