import { MessageData, Part, Operation, GenerateResponseData } from 'genkit'; import { ToolDefinition } from 'genkit/model'; import { InteractionTool, CodeExecutionCallStep, CodeExecutionResultStep, GoogleSearchCallStep, GoogleSearchResultStep, GeminiInteraction, Content, StepDeltaData, Step, FunctionCallContent, FunctionCallStep, FunctionResultContent, FunctionResultStep, ModelGenerationConfig, InteractionGoogleSearchTool, ResponseModality, InteractionSafetySetting, InteractionToolChoiceConfig } from './interaction-types.mjs'; import './types.mjs'; /** * Copyright 2026 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. */ /** * Ensures that all tool requests and responses in a list of messages have unique reference IDs. * * This function performs two passes: * 1. Assigns generated IDs to tool requests that lack a `ref`. * 2. Assigns matching IDs to tool responses that lack a `ref`, assuming they correspond * sequentially to the requests. If a response has no matching request, it gets an orphaned ID. * * @param messages - The list of messages to process. * @returns A deep copy of the messages with tool IDs ensured. */ declare function ensureToolIds(messages: MessageData[]): MessageData[]; /** * Converts a Genkit ToolDefinition to an InteractionTool format. * * Maps the name, description, and input schema (cleaned) to the interaction tool structure. * * @param tool - The Genkit tool definition. * @returns The converted InteractionTool. */ declare function toInteractionTool(tool: ToolDefinition): InteractionTool; declare function toInteractionConfigTool(toolRaw: unknown): InteractionTool; /** * Copies a `retrievalConfig.latLng` user location onto the Interactions * `google_maps` tools, which take `latitude`/`longitude` directly (there is no * retrieval config on the Interactions path). A location already set on a tool * is kept. * * @returns Whether there was a `google_maps` tool to apply the location to. */ declare function applyLatLngToGoogleMapsTools(tools: InteractionTool[], latLng: { latitude?: number; longitude?: number; }): boolean; /** * Picks the messages to send to the Interactions API and the interaction to * continue, if any. * * Without `store`, the server keeps no history, so every message is sent. * With `store`, the last model message's `metadata.interactionId` is * continued and only the newer messages are sent. An explicit * `previousInteractionId` (which requires `store`) overrides the metadata; * messages up to the last model message are still left out. * * @throws GenkitError (INVALID_ARGUMENT) if `previousInteractionId` is set * without `store`. */ declare function selectInteractionInput(messages: MessageData[], store: boolean, previousInteractionIdFromConfig?: string): { messages: MessageData[]; previousInteractionId?: string; }; /** * Converts `functionCallingConfig` (or, without it, the request's * `toolChoice`) to the Interactions `generation_config.tool_choice`. * Returns `undefined` when neither sets anything. */ declare function toInteractionToolChoice(functionCallingConfig?: { mode?: string; allowedFunctionNames?: string[]; }, toolChoice?: string): InteractionToolChoiceConfig | undefined; declare function toInteractionGoogleSearch(gs: boolean | unknown): InteractionGoogleSearchTool; /** * Converts generateContent-style safety settings to the Interactions API * shape: `type` without the `HARM_CATEGORY_` prefix, and lower-case values * (`HARM_CATEGORY_HATE_SPEECH` / `BLOCK_LOW_AND_ABOVE` -> `hate_speech` / * `block_low_and_above`). The server rejects the upper-case values with a * 400. `method` (`SEVERITY` / `PROBABILITY`) is lower-cased too. * `HARM_CATEGORY_UNSPECIFIED` has no equivalent and is left out. Other * fields are passed through. */ declare function toInteractionSafetySettings(settings?: { category: string; threshold: string; method?: unknown; }[]): InteractionSafetySetting[] | undefined; declare function toInteractionResponseModalities(modalities: string[]): ResponseModality[]; /** * Converts a Genkit/generateContent-style `speechConfig` to the Interactions * API `speech_config`. * * - `voiceConfig.prebuiltVoiceConfig.voiceName` becomes `[{ voice }]`. * - `multiSpeakerVoiceConfig.speakerVoiceConfigs[]` becomes * `{ speakers: [{ speaker, voice }, ...] }`. Each text part must then name * its speaker via `metadata.speechMetadata.speaker`. * - A top-level `languageCode` is applied to every entry as `language`. * * Returns `undefined` if no voice or language is set. */ declare function toInteractionSpeechConfig(speechConfig: unknown): ModelGenerationConfig['speech_config']; /** * Converts the remaining request config into the Interactions * `generation_config`. * * The API rejects unknown `generation_config` fields with a 400, so config * fields this plugin defines are mapped explicitly: * - `speechConfig` is converted to `speech_config`; * - `thinkingConfig.thinkingLevel` / `includeThoughts` become * `thinking_level` / `thinking_summaries`. There is no `thinking_config`, * so other thinking fields (e.g. `thinkingBudget`) are dropped; * - `contextCache` (not implemented by this plugin) is dropped. * Everything else, including keys the user passes through that aren't in the * schema, is forwarded in snake_case. * * @param config The request config, without fields handled elsewhere. * @param onDropped Called with the name of each config field that was dropped. */ declare function toInteractionGenerationConfig(config: Record, onDropped?: (field: string) => void): ModelGenerationConfig; /** * Converts the `audioFormat` config (`{ mimeType, sampleRate }`) into an * Interactions audio `response_format`. Returns `undefined` if it isn't set, * so the server defaults apply. */ declare function toInteractionAudioResponseFormat(audioFormat: unknown): Record | undefined; /** * Converts the `videoFormat` config (`{ aspectRatio, resolution }`) into an * Interactions video `response_format`. Returns `undefined` if it isn't set, * so the server defaults apply (16:9, 720p). */ declare function toInteractionVideoResponseFormat(videoFormat: unknown): Record | undefined; /** * Converts a Genkit Part to an Interaction Content object. * * Handles various part types including text, media, tool requests (mapped to function calls), * and tool responses (mapped to function results). * * @param part - The Genkit message part. * @returns The corresponding Interaction Content object. * @throws Error if the part type is unsupported. */ declare function toInteractionContent(part: Part): Content | undefined; /** * Maps a Genkit message role to the corresponding Interaction API role. * * - 'user' -> 'user' * - 'model' -> 'model' * - 'tool' -> 'user' (Tool outputs are treated as user turns in this context) * * @param role - The Genkit message role. * @returns The mapped Interaction role string. * @throws Error if the role is 'system', as system instructions are handled separately. */ declare function toInteractionRole(role: MessageData['role']): string; /** * Converts an array of Genkit MessageData objects into an array of Interaction Steps. */ declare function toInteractionSteps(messages: MessageData[]): Step[]; /** * Converts a streamed step delta into Genkit Parts for a stream chunk. * * @param delta - The `delta` of a `step.delta` SSE event. * @returns The corresponding Genkit Parts (empty for deltas with nothing to * emit, such as partial function call arguments). */ declare function fromInteractionDelta(delta: StepDeltaData): Part[]; /** * Converts an Interaction Content object back into a Genkit Part. * * Supports text, image, audio, document, video, thought, function calls, and * function results. Unknown content types are returned as a custom part. * * @param content - The Interaction Content object. * @returns The corresponding Genkit Part. */ declare function fromInteractionContent(content: Content): Part; declare function fromGoogleSearchCall(step: GoogleSearchCallStep): Part; declare function fromGoogleSearchResult(step: GoogleSearchResultStep): Part; declare function fromCodeExecutionCall(step: CodeExecutionCallStep): Part; declare function fromCodeExecutionResult(step: CodeExecutionResultStep): Part; declare function fromPendingFunctionCall(step: FunctionCallContent | FunctionCallStep): Part; declare function fromServerFunctionCall(step: FunctionCallContent | FunctionCallStep): Part; declare function fromServerFunctionResult(step: FunctionResultContent | FunctionResultStep): Part; declare function fromInteractionStep(step: Step, isPending?: boolean): Part[]; declare function fromInteractionSync(interaction: GeminiInteraction): GenerateResponseData; /** * Removes ID3 tags from the start of a headerless audio part. * * The server sometimes sends a C2PA manifest, in an ID3 tag, at the start of a * streamed `audio/l16` chunk (seen with gemini-3.8-flash-lite-tts and two * speakers). The tag isn't audio: played or joined as raw audio it is noise, * and its odd size shifts every sample after it by one byte. This has been * reported to the Gemini API team; until it's fixed, the tag is removed so * the audio plays correctly. That manifest is dropped. The tag has only been * seen whole at the start of a chunk; a tag that doesn't fit in the chunk is * left in, since bytes that can't be checked as a tag might be audio. */ declare function removeId3FromAudio(part: Part): Part; /** * Joins streamed audio chunks in the final response into one part, in the * format the server returned: * - consecutive headerless chunks (`audio/l16`, `audio/mulaw`, `audio/alaw`) * of the same type are joined end to end; * - a streamed `audio/wav` request starts with a small complete WAV file and * continues with `audio/l16` chunks (seen live). Those chunks go into the * WAV's `data` chunk, giving one WAV like a non-streamed response. * Other parts are kept as they are. */ declare function mergeStreamedAudio(parts: Part[]): Part[]; declare function fromInteraction(interaction: GeminiInteraction): Operation; export { applyLatLngToGoogleMapsTools, ensureToolIds, fromCodeExecutionCall, fromCodeExecutionResult, fromGoogleSearchCall, fromGoogleSearchResult, fromInteraction, fromInteractionContent, fromInteractionDelta, fromInteractionStep, fromInteractionSync, fromPendingFunctionCall, fromServerFunctionCall, fromServerFunctionResult, mergeStreamedAudio, removeId3FromAudio, selectInteractionInput, toInteractionAudioResponseFormat, toInteractionConfigTool, toInteractionContent, toInteractionGenerationConfig, toInteractionGoogleSearch, toInteractionResponseModalities, toInteractionRole, toInteractionSafetySettings, toInteractionSpeechConfig, toInteractionSteps, toInteractionTool, toInteractionToolChoice, toInteractionVideoResponseFormat };