diff --git a/common/api-review/ai.api.md b/common/api-review/ai.api.md index 199b97b10a9..f92593c69d2 100644 --- a/common/api-review/ai.api.md +++ b/common/api-review/ai.api.md @@ -32,6 +32,7 @@ export const AIErrorCode: { readonly REQUEST_ERROR: "request-error"; readonly RESPONSE_ERROR: "response-error"; readonly FETCH_ERROR: "fetch-error"; + readonly SESSION_CLOSED: "session-closed"; readonly INVALID_CONTENT: "invalid-content"; readonly API_NOT_ENABLED: "api-not-enabled"; readonly INVALID_SCHEMA: "invalid-schema"; @@ -262,6 +263,7 @@ export type FinishReason = (typeof FinishReason)[keyof typeof FinishReason]; export interface FunctionCall { // (undocumented) args: object; + id?: string; // (undocumented) name: string; } @@ -310,6 +312,7 @@ export interface FunctionDeclarationsTool { // @public export interface FunctionResponse { + id?: string; // (undocumented) name: string; // (undocumented) @@ -444,6 +447,9 @@ export function getGenerativeModel(ai: AI, modelParams: ModelParams, requestOpti // @beta export function getImagenModel(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions): ImagenModel; +// @beta +export function getLiveGenerativeModel(ai: AI, modelParams: LiveModelParams): LiveGenerativeModel; + // @public export class GoogleAIBackend extends Backend { constructor(); @@ -699,6 +705,96 @@ export class IntegerSchema extends Schema { constructor(schemaParams?: SchemaParams); } +// @beta +export interface LiveGenerationConfig { + candidateCount?: number; + frequencyPenalty?: number; + maxOutputTokens?: number; + presencePenalty?: number; + responseModalities?: [ResponseModality]; + speechConfig?: SpeechConfig; + temperature?: number; + topK?: number; + topP?: number; +} + +// @beta +export class LiveGenerativeModel extends AIModel { + // Warning: (ae-forgotten-export) The symbol "WebSocketHandler" needs to be exported by the entry point index.d.ts + // + // @internal + constructor(ai: AI, modelParams: LiveModelParams, + _webSocketHandler: WebSocketHandler); + connect(): Promise; + // (undocumented) + generationConfig: LiveGenerationConfig; + // (undocumented) + systemInstruction?: Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; + } + +// @beta +export interface LiveModelParams { + // (undocumented) + generationConfig?: LiveGenerationConfig; + // (undocumented) + model: string; + // (undocumented) + systemInstruction?: string | Part | Content; + // (undocumented) + toolConfig?: ToolConfig; + // (undocumented) + tools?: Tool[]; +} + +// @beta +export const LiveResponseType: { + SERVER_CONTENT: string; + TOOL_CALL: string; + TOOL_CALL_CANCELLATION: string; +}; + +// @beta +export type LiveResponseType = (typeof LiveResponseType)[keyof typeof LiveResponseType]; + +// @beta +export interface LiveServerContent { + interrupted?: boolean; + modelTurn?: Content; + turnComplete?: boolean; + // (undocumented) + type: 'serverContent'; +} + +// @beta +export interface LiveServerToolCall { + functionCalls: FunctionCall[]; + // (undocumented) + type: 'toolCall'; +} + +// @beta +export interface LiveServerToolCallCancellation { + functionIds: string[]; + // (undocumented) + type: 'toolCallCancellation'; +} + +// @beta +export class LiveSession { + // @internal + constructor(webSocketHandler: WebSocketHandler, serverMessages: AsyncGenerator); + close(): Promise; + isClosed: boolean; + receive(): AsyncGenerator; + send(request: string | Array, turnComplete?: boolean): Promise; + sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise; + sendMediaStream(mediaChunkStream: ReadableStream): Promise; + } + // @public export const Modality: { readonly MODALITY_UNSPECIFIED: "MODALITY_UNSPECIFIED"; @@ -763,6 +859,11 @@ export type Part = TextPart | InlineDataPart | FunctionCallPart | FunctionRespon // @public export const POSSIBLE_ROLES: readonly ["user", "model", "function", "system"]; +// @beta +export interface PrebuiltVoiceConfig { + voiceConfig?: string; +} + // @public export interface PromptFeedback { // (undocumented) @@ -926,6 +1027,11 @@ export interface Segment { text: string; } +// @beta +export interface SpeechConfig { + voiceConfig?: VoiceConfig; +} + // @public export interface StartChatParams extends BaseParams { // (undocumented) @@ -1003,6 +1109,11 @@ export interface VideoMetadata { startOffset: string; } +// @beta +export interface VoiceConfig { + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + // @public (undocumented) export interface WebAttribution { // (undocumented) diff --git a/docs-devsite/_toc.yaml b/docs-devsite/_toc.yaml index 6d548ffd8d6..6979b475536 100644 --- a/docs-devsite/_toc.yaml +++ b/docs-devsite/_toc.yaml @@ -108,6 +108,20 @@ toc: path: /docs/reference/js/ai.inlinedatapart.md - title: IntegerSchema path: /docs/reference/js/ai.integerschema.md + - title: LiveGenerationConfig + path: /docs/reference/js/ai.livegenerationconfig.md + - title: LiveGenerativeModel + path: /docs/reference/js/ai.livegenerativemodel.md + - title: LiveModelParams + path: /docs/reference/js/ai.livemodelparams.md + - title: LiveServerContent + path: /docs/reference/js/ai.liveservercontent.md + - title: LiveServerToolCall + path: /docs/reference/js/ai.liveservertoolcall.md + - title: LiveServerToolCallCancellation + path: /docs/reference/js/ai.liveservertoolcallcancellation.md + - title: LiveSession + path: /docs/reference/js/ai.livesession.md - title: ModalityTokenCount path: /docs/reference/js/ai.modalitytokencount.md - title: ModelParams @@ -118,6 +132,8 @@ toc: path: /docs/reference/js/ai.objectschema.md - title: ObjectSchemaRequest path: /docs/reference/js/ai.objectschemarequest.md + - title: PrebuiltVoiceConfig + path: /docs/reference/js/ai.prebuiltvoiceconfig.md - title: PromptFeedback path: /docs/reference/js/ai.promptfeedback.md - title: RequestOptions @@ -142,6 +158,8 @@ toc: path: /docs/reference/js/ai.searchentrypoint.md - title: Segment path: /docs/reference/js/ai.segment.md + - title: SpeechConfig + path: /docs/reference/js/ai.speechconfig.md - title: StartChatParams path: /docs/reference/js/ai.startchatparams.md - title: StringSchema @@ -158,6 +176,8 @@ toc: path: /docs/reference/js/ai.vertexaibackend.md - title: VideoMetadata path: /docs/reference/js/ai.videometadata.md + - title: VoiceConfig + path: /docs/reference/js/ai.voiceconfig.md - title: WebAttribution path: /docs/reference/js/ai.webattribution.md - title: WebGroundingChunk diff --git a/docs-devsite/ai.functioncall.md b/docs-devsite/ai.functioncall.md index 1c789784fe1..b0bb2424a10 100644 --- a/docs-devsite/ai.functioncall.md +++ b/docs-devsite/ai.functioncall.md @@ -23,6 +23,7 @@ export interface FunctionCall | Property | Type | Description | | --- | --- | --- | | [args](./ai.functioncall.md#functioncallargs) | object | | +| [id](./ai.functioncall.md#functioncallid) | string | The id of the function call. This must be sent back in the associated [FunctionResponse](./ai.functionresponse.md#functionresponse_interface). | | [name](./ai.functioncall.md#functioncallname) | string | | ## FunctionCall.args @@ -33,6 +34,18 @@ export interface FunctionCall args: object; ``` +## FunctionCall.id + +The id of the function call. This must be sent back in the associated [FunctionResponse](./ai.functionresponse.md#functionresponse_interface). + +This property is only supported in the Gemini Developer API ([GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class)). When using the Gemini Developer API ([GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class)), this property will be `undefined`. + +Signature: + +```typescript +id?: string; +``` + ## FunctionCall.name Signature: diff --git a/docs-devsite/ai.functionresponse.md b/docs-devsite/ai.functionresponse.md index e0838cf515a..980d964f703 100644 --- a/docs-devsite/ai.functionresponse.md +++ b/docs-devsite/ai.functionresponse.md @@ -22,9 +22,22 @@ export interface FunctionResponse | Property | Type | Description | | --- | --- | --- | +| [id](./ai.functionresponse.md#functionresponseid) | string | The id of the [FunctionCall](./ai.functioncall.md#functioncall_interface). | | [name](./ai.functionresponse.md#functionresponsename) | string | | | [response](./ai.functionresponse.md#functionresponseresponse) | object | | +## FunctionResponse.id + +The id of the [FunctionCall](./ai.functioncall.md#functioncall_interface). + +This property is only supported in the Gemini Developer API ([GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class)). When using the Gemini Developer API ([GoogleAIBackend](./ai.googleaibackend.md#googleaibackend_class)), this property will be `undefined`. + +Signature: + +```typescript +id?: string; +``` + ## FunctionResponse.name Signature: diff --git a/docs-devsite/ai.livegenerationconfig.md b/docs-devsite/ai.livegenerationconfig.md new file mode 100644 index 00000000000..6630b3ffb4c --- /dev/null +++ b/docs-devsite/ai.livegenerationconfig.md @@ -0,0 +1,153 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveGenerationConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configuration parameters used by [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) to control live content generation. + +Signature: + +```typescript +export interface LiveGenerationConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [candidateCount](./ai.livegenerationconfig.md#livegenerationconfigcandidatecount) | number | (Public Preview) The maximum number of generated response messages to return. This value must be between 1 and 8. If unset, this will default to 1. | +| [frequencyPenalty](./ai.livegenerationconfig.md#livegenerationconfigfrequencypenalty) | number | (Public Preview) Frequency penalties. | +| [maxOutputTokens](./ai.livegenerationconfig.md#livegenerationconfigmaxoutputtokens) | number | (Public Preview) Specifies the maximum number of tokens that can be generated in the response. The number of tokens per word varies depending on the language outputted. Defaults to 0. | +| [presencePenalty](./ai.livegenerationconfig.md#livegenerationconfigpresencepenalty) | number | (Public Preview) Positive penalties. | +| [responseModalities](./ai.livegenerationconfig.md#livegenerationconfigresponsemodalities) | \[[ResponseModality](./ai.md#responsemodality)\] | (Public Preview) The modalities of the response. | +| [speechConfig](./ai.livegenerationconfig.md#livegenerationconfigspeechconfig) | [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configuration for speech synthesis. | +| [temperature](./ai.livegenerationconfig.md#livegenerationconfigtemperature) | number | (Public Preview) Controls the degree of randomness in token selection. A temperature value of 0 means that the highest probability tokens are always selected. In this case, responses for a given prompt are mostly deterministic, but a small amount of variation is still possible. | +| [topK](./ai.livegenerationconfig.md#livegenerationconfigtopk) | number | (Public Preview) Changes how the model selects token for output. A topK value of 1 means the select token is the most probable among all tokens in the model's vocabulary, while a topK value 3 means that the next token is selected from among the 3 most probably using probabilities sampled. Tokens are then further filtered with the highest selected temperature sampling. Defaults to 40 if unspecified. | +| [topP](./ai.livegenerationconfig.md#livegenerationconfigtopp) | number | (Public Preview) Changes how the model selects tokens for output. Tokens are selected from the most to least probable until the sum of their probabilities equals the topP value. For example, if tokens A, B, and C have probabilities of 0.3, 0.2, and 0.1 respectively and the topP value is 0.5, then the model will select either A or B as the next token by using the temperature and exclude C as a candidate. Defaults to 0.95 if unset. | + +## LiveGenerationConfig.candidateCount + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The maximum number of generated response messages to return. This value must be between 1 and 8. If unset, this will default to 1. + +Signature: + +```typescript +candidateCount?: number; +``` + +## LiveGenerationConfig.frequencyPenalty + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Frequency penalties. + +Signature: + +```typescript +frequencyPenalty?: number; +``` + +## LiveGenerationConfig.maxOutputTokens + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Specifies the maximum number of tokens that can be generated in the response. The number of tokens per word varies depending on the language outputted. Defaults to 0. + +Signature: + +```typescript +maxOutputTokens?: number; +``` + +## LiveGenerationConfig.presencePenalty + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Positive penalties. + +Signature: + +```typescript +presencePenalty?: number; +``` + +## LiveGenerationConfig.responseModalities + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The modalities of the response. + +Signature: + +```typescript +responseModalities?: [ResponseModality]; +``` + +## LiveGenerationConfig.speechConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configuration for speech synthesis. + +Signature: + +```typescript +speechConfig?: SpeechConfig; +``` + +## LiveGenerationConfig.temperature + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Controls the degree of randomness in token selection. A `temperature` value of 0 means that the highest probability tokens are always selected. In this case, responses for a given prompt are mostly deterministic, but a small amount of variation is still possible. + +Signature: + +```typescript +temperature?: number; +``` + +## LiveGenerationConfig.topK + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Changes how the model selects token for output. A `topK` value of 1 means the select token is the most probable among all tokens in the model's vocabulary, while a `topK` value 3 means that the next token is selected from among the 3 most probably using probabilities sampled. Tokens are then further filtered with the highest selected `temperature` sampling. Defaults to 40 if unspecified. + +Signature: + +```typescript +topK?: number; +``` + +## LiveGenerationConfig.topP + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Changes how the model selects tokens for output. Tokens are selected from the most to least probable until the sum of their probabilities equals the `topP` value. For example, if tokens A, B, and C have probabilities of 0.3, 0.2, and 0.1 respectively and the `topP` value is 0.5, then the model will select either A or B as the next token by using the `temperature` and exclude C as a candidate. Defaults to 0.95 if unset. + +Signature: + +```typescript +topP?: number; +``` diff --git a/docs-devsite/ai.livegenerativemodel.md b/docs-devsite/ai.livegenerativemodel.md new file mode 100644 index 00000000000..7c52cad1a33 --- /dev/null +++ b/docs-devsite/ai.livegenerativemodel.md @@ -0,0 +1,109 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveGenerativeModel class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Class for Live generative model APIs. The Live API enables low-latency, two-way multimodal interactions with Gemini. + +This class should only be instantiated with [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `LiveGenerativeModel` class. + +Signature: + +```typescript +export declare class LiveGenerativeModel extends AIModel +``` +Extends: [AIModel](./ai.aimodel.md#aimodel_class) + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [generationConfig](./ai.livegenerativemodel.md#livegenerativemodelgenerationconfig) | | [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface) | (Public Preview) | +| [systemInstruction](./ai.livegenerativemodel.md#livegenerativemodelsysteminstruction) | | [Content](./ai.content.md#content_interface) | (Public Preview) | +| [toolConfig](./ai.livegenerativemodel.md#livegenerativemodeltoolconfig) | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | (Public Preview) | +| [tools](./ai.livegenerativemodel.md#livegenerativemodeltools) | | [Tool](./ai.md#tool)\[\] | (Public Preview) | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [connect()](./ai.livegenerativemodel.md#livegenerativemodelconnect) | | (Public Preview) Starts a [LiveSession](./ai.livesession.md#livesession_class). | + +## LiveGenerativeModel.generationConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +generationConfig: LiveGenerationConfig; +``` + +## LiveGenerativeModel.systemInstruction + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +systemInstruction?: Content; +``` + +## LiveGenerativeModel.toolConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## LiveGenerativeModel.tools + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +tools?: Tool[]; +``` + +## LiveGenerativeModel.connect() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Starts a [LiveSession](./ai.livesession.md#livesession_class). + +Signature: + +```typescript +connect(): Promise; +``` +Returns: + +Promise<[LiveSession](./ai.livesession.md#livesession_class)> + +A [LiveSession](./ai.livesession.md#livesession_class). + +#### Exceptions + +If the connection failed to be established with the server. + diff --git a/docs-devsite/ai.livemodelparams.md b/docs-devsite/ai.livemodelparams.md new file mode 100644 index 00000000000..fddca4f0e14 --- /dev/null +++ b/docs-devsite/ai.livemodelparams.md @@ -0,0 +1,87 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveModelParams interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Params passed to [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). + +Signature: + +```typescript +export interface LiveModelParams +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [generationConfig](./ai.livemodelparams.md#livemodelparamsgenerationconfig) | [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface) | (Public Preview) | +| [model](./ai.livemodelparams.md#livemodelparamsmodel) | string | (Public Preview) | +| [systemInstruction](./ai.livemodelparams.md#livemodelparamssysteminstruction) | string \| [Part](./ai.md#part) \| [Content](./ai.content.md#content_interface) | (Public Preview) | +| [toolConfig](./ai.livemodelparams.md#livemodelparamstoolconfig) | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | (Public Preview) | +| [tools](./ai.livemodelparams.md#livemodelparamstools) | [Tool](./ai.md#tool)\[\] | (Public Preview) | + +## LiveModelParams.generationConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +generationConfig?: LiveGenerationConfig; +``` + +## LiveModelParams.model + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +model: string; +``` + +## LiveModelParams.systemInstruction + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +systemInstruction?: string | Part | Content; +``` + +## LiveModelParams.toolConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +toolConfig?: ToolConfig; +``` + +## LiveModelParams.tools + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +tools?: Tool[]; +``` diff --git a/docs-devsite/ai.liveservercontent.md b/docs-devsite/ai.liveservercontent.md new file mode 100644 index 00000000000..f9c3ca1de79 --- /dev/null +++ b/docs-devsite/ai.liveservercontent.md @@ -0,0 +1,81 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveServerContent interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An incremental content update from the model. + +Signature: + +```typescript +export interface LiveServerContent +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [interrupted](./ai.liveservercontent.md#liveservercontentinterrupted) | boolean | (Public Preview) Indicates whether the model was interrupted by the client. An interruption occurs when the client sends a message before the model finishes it's turn. This is undefined if the model was not interrupted. | +| [modelTurn](./ai.liveservercontent.md#liveservercontentmodelturn) | [Content](./ai.content.md#content_interface) | (Public Preview) The content that the model has generated as part of the current conversation with the user. | +| [turnComplete](./ai.liveservercontent.md#liveservercontentturncomplete) | boolean | (Public Preview) Indicates whether the turn is complete. This is undefined if the turn is not complete. | +| [type](./ai.liveservercontent.md#liveservercontenttype) | 'serverContent' | (Public Preview) | + +## LiveServerContent.interrupted + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether the model was interrupted by the client. An interruption occurs when the client sends a message before the model finishes it's turn. This is `undefined` if the model was not interrupted. + +Signature: + +```typescript +interrupted?: boolean; +``` + +## LiveServerContent.modelTurn + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The content that the model has generated as part of the current conversation with the user. + +Signature: + +```typescript +modelTurn?: Content; +``` + +## LiveServerContent.turnComplete + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether the turn is complete. This is `undefined` if the turn is not complete. + +Signature: + +```typescript +turnComplete?: boolean; +``` + +## LiveServerContent.type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +type: 'serverContent'; +``` diff --git a/docs-devsite/ai.liveservertoolcall.md b/docs-devsite/ai.liveservertoolcall.md new file mode 100644 index 00000000000..51ef6bb5d4b --- /dev/null +++ b/docs-devsite/ai.liveservertoolcall.md @@ -0,0 +1,53 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveServerToolCall interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +A request from the model for the client to execute one or more functions. + +Signature: + +```typescript +export interface LiveServerToolCall +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionCalls](./ai.liveservertoolcall.md#liveservertoolcallfunctioncalls) | [FunctionCall](./ai.functioncall.md#functioncall_interface)\[\] | (Public Preview) An array of function calls to run. | +| [type](./ai.liveservertoolcall.md#liveservertoolcalltype) | 'toolCall' | (Public Preview) | + +## LiveServerToolCall.functionCalls + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +An array of function calls to run. + +Signature: + +```typescript +functionCalls: FunctionCall[]; +``` + +## LiveServerToolCall.type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +type: 'toolCall'; +``` diff --git a/docs-devsite/ai.liveservertoolcallcancellation.md b/docs-devsite/ai.liveservertoolcallcancellation.md new file mode 100644 index 00000000000..2e9a63a81e7 --- /dev/null +++ b/docs-devsite/ai.liveservertoolcallcancellation.md @@ -0,0 +1,53 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveServerToolCallCancellation interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Notification to cancel a previous function call triggered by [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface). + +Signature: + +```typescript +export interface LiveServerToolCallCancellation +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [functionIds](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellationfunctionids) | string\[\] | (Public Preview) IDs of function calls that were cancelled. These refer to the id property of a [FunctionCall](./ai.functioncall.md#functioncall_interface). | +| [type](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellationtype) | 'toolCallCancellation' | (Public Preview) | + +## LiveServerToolCallCancellation.functionIds + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +IDs of function calls that were cancelled. These refer to the `id` property of a [FunctionCall](./ai.functioncall.md#functioncall_interface). + +Signature: + +```typescript +functionIds: string[]; +``` + +## LiveServerToolCallCancellation.type + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Signature: + +```typescript +type: 'toolCallCancellation'; +``` diff --git a/docs-devsite/ai.livesession.md b/docs-devsite/ai.livesession.md new file mode 100644 index 00000000000..bb2eca88b89 --- /dev/null +++ b/docs-devsite/ai.livesession.md @@ -0,0 +1,176 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# LiveSession class +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Represents an active, real-time, bidirectional conversation with the model. + +This class should only be instantiated by calling [LiveGenerativeModel.connect()](./ai.livegenerativemodel.md#livegenerativemodelconnect). + +The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the `LiveSession` class. + +Signature: + +```typescript +export declare class LiveSession +``` + +## Properties + +| Property | Modifiers | Type | Description | +| --- | --- | --- | --- | +| [isClosed](./ai.livesession.md#livesessionisclosed) | | boolean | (Public Preview) Indicates whether this Live session is closed. | + +## Methods + +| Method | Modifiers | Description | +| --- | --- | --- | +| [close()](./ai.livesession.md#livesessionclose) | | (Public Preview) Closes this session. All methods on this session will throw an error once this resolves. | +| [receive()](./ai.livesession.md#livesessionreceive) | | (Public Preview) Yields messages received from the server. This can only be used by one consumer at a time. | +| [send(request, turnComplete)](./ai.livesession.md#livesessionsend) | | (Public Preview) Sends content to the server. | +| [sendMediaChunks(mediaChunks)](./ai.livesession.md#livesessionsendmediachunks) | | (Public Preview) Sends realtime input to the server. | +| [sendMediaStream(mediaChunkStream)](./ai.livesession.md#livesessionsendmediastream) | | (Public Preview) Sends a stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface). | + +## LiveSession.isClosed + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Indicates whether this Live session is closed. + +Signature: + +```typescript +isClosed: boolean; +``` + +## LiveSession.close() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Closes this session. All methods on this session will throw an error once this resolves. + +Signature: + +```typescript +close(): Promise; +``` +Returns: + +Promise<void> + +## LiveSession.receive() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Yields messages received from the server. This can only be used by one consumer at a time. + +Signature: + +```typescript +receive(): AsyncGenerator; +``` +Returns: + +AsyncGenerator<[LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) \| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) \| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface)> + +An `AsyncGenerator` that yields server messages as they arrive. + +#### Exceptions + +If the session is already closed, or if we receive a response that we don't support. + +## LiveSession.send() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends content to the server. + +Signature: + +```typescript +send(request: string | Array, turnComplete?: boolean): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| request | string \| Array<string \| [Part](./ai.md#part)> | The message to send to the model. | +| turnComplete | boolean | Indicates if the turn is complete. Defaults to false. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + +## LiveSession.sendMediaChunks() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends realtime input to the server. + +Signature: + +```typescript +sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mediaChunks | [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface)\[\] | The media chunks to send. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + +## LiveSession.sendMediaStream() + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Sends a stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface). + +Signature: + +```typescript +sendMediaStream(mediaChunkStream: ReadableStream): Promise; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| mediaChunkStream | ReadableStream<[GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface)> | The stream of [GenerativeContentBlob](./ai.generativecontentblob.md#generativecontentblob_interface) to send. | + +Returns: + +Promise<void> + +#### Exceptions + +If this session has been closed. + diff --git a/docs-devsite/ai.md b/docs-devsite/ai.md index 9900b3ecccc..a70772dc763 100644 --- a/docs-devsite/ai.md +++ b/docs-devsite/ai.md @@ -21,6 +21,7 @@ The Firebase AI Web SDK. | function(ai, ...) | | [getGenerativeModel(ai, modelParams, requestOptions)](./ai.md#getgenerativemodel_80bd839) | Returns a [GenerativeModel](./ai.generativemodel.md#generativemodel_class) class with methods for inference and other functionality. | | [getImagenModel(ai, modelParams, requestOptions)](./ai.md#getimagenmodel_e1f6645) | (Public Preview) Returns an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class) class with methods for using Imagen.Only Imagen 3 models (named imagen-3.0-*) are supported. | +| [getLiveGenerativeModel(ai, modelParams)](./ai.md#getlivegenerativemodel_f2099ac) | (Public Preview) Returns a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) class for real-time, bidirectional communication.The Live API is only supported in modern browser windows and Node >= 22. | ## Classes @@ -38,6 +39,8 @@ The Firebase AI Web SDK. | [ImagenImageFormat](./ai.imagenimageformat.md#imagenimageformat_class) | (Public Preview) Defines the image format for images generated by Imagen.Use this class to specify the desired format (JPEG or PNG) and compression quality for images generated by Imagen. This is typically included as part of [ImagenModelParams](./ai.imagenmodelparams.md#imagenmodelparams_interface). | | [ImagenModel](./ai.imagenmodel.md#imagenmodel_class) | (Public Preview) Class for Imagen model APIs.This class provides methods for generating images using the Imagen model. | | [IntegerSchema](./ai.integerschema.md#integerschema_class) | Schema class for "integer" types. | +| [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) | (Public Preview) Class for Live generative model APIs. The Live API enables low-latency, two-way multimodal interactions with Gemini.This class should only be instantiated with [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). | +| [LiveSession](./ai.livesession.md#livesession_class) | (Public Preview) Represents an active, real-time, bidirectional conversation with the model.This class should only be instantiated by calling [LiveGenerativeModel.connect()](./ai.livegenerativemodel.md#livegenerativemodelconnect). | | [NumberSchema](./ai.numberschema.md#numberschema_class) | Schema class for "number" types. | | [ObjectSchema](./ai.objectschema.md#objectschema_class) | Schema class for "object" types. The properties param must be a map of Schema objects. | | [Schema](./ai.schema.md#schema_class) | Parent class encompassing all Schema types, with static methods that allow building specific Schema types. This class can be converted with JSON.stringify() into a JSON string accepted by Vertex AI REST endpoints. (This string conversion is automatically done when calling SDK methods.) | @@ -88,9 +91,15 @@ The Firebase AI Web SDK. | [ImagenModelParams](./ai.imagenmodelparams.md#imagenmodelparams_interface) | (Public Preview) Parameters for configuring an [ImagenModel](./ai.imagenmodel.md#imagenmodel_class). | | [ImagenSafetySettings](./ai.imagensafetysettings.md#imagensafetysettings_interface) | (Public Preview) Settings for controlling the aggressiveness of filtering out sensitive content.See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details. | | [InlineDataPart](./ai.inlinedatapart.md#inlinedatapart_interface) | Content part interface if the part represents an image. | +| [LiveGenerationConfig](./ai.livegenerationconfig.md#livegenerationconfig_interface) | (Public Preview) Configuration parameters used by [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) to control live content generation. | +| [LiveModelParams](./ai.livemodelparams.md#livemodelparams_interface) | (Public Preview) Params passed to [getLiveGenerativeModel()](./ai.md#getlivegenerativemodel_f2099ac). | +| [LiveServerContent](./ai.liveservercontent.md#liveservercontent_interface) | (Public Preview) An incremental content update from the model. | +| [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface) | (Public Preview) A request from the model for the client to execute one or more functions. | +| [LiveServerToolCallCancellation](./ai.liveservertoolcallcancellation.md#liveservertoolcallcancellation_interface) | (Public Preview) Notification to cancel a previous function call triggered by [LiveServerToolCall](./ai.liveservertoolcall.md#liveservertoolcall_interface). | | [ModalityTokenCount](./ai.modalitytokencount.md#modalitytokencount_interface) | Represents token counting info for a single modality. | | [ModelParams](./ai.modelparams.md#modelparams_interface) | Params passed to [getGenerativeModel()](./ai.md#getgenerativemodel_80bd839). | | [ObjectSchemaRequest](./ai.objectschemarequest.md#objectschemarequest_interface) | Interface for JSON parameters in a schema of "object" when not using the Schema.object() helper. | +| [PrebuiltVoiceConfig](./ai.prebuiltvoiceconfig.md#prebuiltvoiceconfig_interface) | (Public Preview) Configuration for a pre-built voice. | | [PromptFeedback](./ai.promptfeedback.md#promptfeedback_interface) | If the prompt was blocked, this will be populated with blockReason and the relevant safetyRatings. | | [RequestOptions](./ai.requestoptions.md#requestoptions_interface) | Params passed to [getGenerativeModel()](./ai.md#getgenerativemodel_80bd839). | | [RetrievedContextAttribution](./ai.retrievedcontextattribution.md#retrievedcontextattribution_interface) | | @@ -102,12 +111,14 @@ The Firebase AI Web SDK. | [SchemaShared](./ai.schemashared.md#schemashared_interface) | Basic [Schema](./ai.schema.md#schema_class) properties shared across several Schema-related types. | | [SearchEntrypoint](./ai.searchentrypoint.md#searchentrypoint_interface) | Google search entry point. | | [Segment](./ai.segment.md#segment_interface) | Represents a specific segment within a [Content](./ai.content.md#content_interface) object, often used to pinpoint the exact location of text or data that grounding information refers to. | +| [SpeechConfig](./ai.speechconfig.md#speechconfig_interface) | (Public Preview) Configures speech synthesis. | | [StartChatParams](./ai.startchatparams.md#startchatparams_interface) | Params for [GenerativeModel.startChat()](./ai.generativemodel.md#generativemodelstartchat). | | [TextPart](./ai.textpart.md#textpart_interface) | Content part interface if the part represents a text string. | | [ThinkingConfig](./ai.thinkingconfig.md#thinkingconfig_interface) | Configuration for "thinking" behavior of compatible Gemini models.Certain models utilize a thinking process before generating a response. This allows them to reason through complex problems and plan a more coherent and accurate answer. | | [ToolConfig](./ai.toolconfig.md#toolconfig_interface) | Tool config. This config is shared for all tools provided in the request. | | [UsageMetadata](./ai.usagemetadata.md#usagemetadata_interface) | Usage metadata about a [GenerateContentResponse](./ai.generatecontentresponse.md#generatecontentresponse_interface). | | [VideoMetadata](./ai.videometadata.md#videometadata_interface) | Describes the input video content. | +| [VoiceConfig](./ai.voiceconfig.md#voiceconfig_interface) | (Public Preview) Configuration for the voice to used in speech synthesis. | | [WebAttribution](./ai.webattribution.md#webattribution_interface) | | | [WebGroundingChunk](./ai.webgroundingchunk.md#webgroundingchunk_interface) | A grounding chunk from the web.Important: If using Grounding with Google Search, you are required to comply with the [Service Specific Terms](https://cloud.google.com/terms/service-terms) for "Grounding with Google Search". | @@ -128,6 +139,7 @@ The Firebase AI Web SDK. | [ImagenAspectRatio](./ai.md#imagenaspectratio) | (Public Preview) Aspect ratios for Imagen images.To specify an aspect ratio for generated images, set the aspectRatio property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface).See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. | | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | (Public Preview) A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | (Public Preview) A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | +| [LiveResponseType](./ai.md#liveresponsetype) | (Public Preview) The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). | | [Modality](./ai.md#modality) | Content part modality. | | [POSSIBLE\_ROLES](./ai.md#possible_roles) | Possible roles. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | @@ -150,6 +162,7 @@ The Firebase AI Web SDK. | [ImagenAspectRatio](./ai.md#imagenaspectratio) | (Public Preview) Aspect ratios for Imagen images.To specify an aspect ratio for generated images, set the aspectRatio property in your [ImagenGenerationConfig](./ai.imagengenerationconfig.md#imagengenerationconfig_interface).See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) for more details and examples of the supported aspect ratios. | | [ImagenPersonFilterLevel](./ai.md#imagenpersonfilterlevel) | (Public Preview) A filter level controlling whether generation of images containing people or faces is allowed.See the personGeneration documentation for more details. | | [ImagenSafetyFilterLevel](./ai.md#imagensafetyfilterlevel) | (Public Preview) A filter level controlling how aggressively to filter sensitive content.Text prompts provided as inputs and images (generated or uploaded) through Imagen on Vertex AI are assessed against a list of safety filters, which include 'harmful categories' (for example, violence, sexual, derogatory, and toxic). This filter level controls how aggressively to filter out potentially harmful content from responses. See the [documentation](http://firebase.google.com/docs/vertex-ai/generate-images) and the [Responsible AI and usage guidelines](https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters) for more details. | +| [LiveResponseType](./ai.md#liveresponsetype) | (Public Preview) The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). This is a property on all messages that can be used for type narrowing. This property is not returned by the server, it is assigned to a server message object once it's parsed. | | [Modality](./ai.md#modality) | Content part modality. | | [Part](./ai.md#part) | Content part - includes text, image/video, or function call/response part types. | | [ResponseModality](./ai.md#responsemodality) | (Public Preview) Generation modalities to be returned in generation responses. | @@ -264,6 +277,36 @@ export declare function getImagenModel(ai: AI, modelParams: ImagenModelParams, r If the `apiKey` or `projectId` fields are missing in your Firebase config. +### getLiveGenerativeModel(ai, modelParams) {:#getlivegenerativemodel_f2099ac} + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Returns a [LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) class for real-time, bidirectional communication. + +The Live API is only supported in modern browser windows and Node >= 22. + +Signature: + +```typescript +export declare function getLiveGenerativeModel(ai: AI, modelParams: LiveModelParams): LiveGenerativeModel; +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| ai | [AI](./ai.ai.md#ai_interface) | An [AI](./ai.ai.md#ai_interface) instance. | +| modelParams | [LiveModelParams](./ai.livemodelparams.md#livemodelparams_interface) | Parameters to use when setting up a [LiveSession](./ai.livesession.md#livesession_class). | + +Returns: + +[LiveGenerativeModel](./ai.livegenerativemodel.md#livegenerativemodel_class) + +#### Exceptions + +If the `apiKey` or `projectId` fields are missing in your Firebase config. + ## AIErrorCode Standardized error codes that [AIError](./ai.aierror.md#aierror_class) can have. @@ -276,6 +319,7 @@ AIErrorCode: { readonly REQUEST_ERROR: "request-error"; readonly RESPONSE_ERROR: "response-error"; readonly FETCH_ERROR: "fetch-error"; + readonly SESSION_CLOSED: "session-closed"; readonly INVALID_CONTENT: "invalid-content"; readonly API_NOT_ENABLED: "api-not-enabled"; readonly INVALID_SCHEMA: "invalid-schema"; @@ -488,6 +532,23 @@ ImagenSafetyFilterLevel: { } ``` +## LiveResponseType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). + +Signature: + +```typescript +LiveResponseType: { + SERVER_CONTENT: string; + TOOL_CALL: string; + TOOL_CALL_CANCELLATION: string; +} +``` + ## Modality Content part modality. @@ -693,6 +754,19 @@ Text prompts provided as inputs and images (generated or uploaded) through Image export type ImagenSafetyFilterLevel = (typeof ImagenSafetyFilterLevel)[keyof typeof ImagenSafetyFilterLevel]; ``` +## LiveResponseType + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The types of responses that can be returned by [LiveSession.receive()](./ai.livesession.md#livesessionreceive). This is a property on all messages that can be used for type narrowing. This property is not returned by the server, it is assigned to a server message object once it's parsed. + +Signature: + +```typescript +export type LiveResponseType = (typeof LiveResponseType)[keyof typeof LiveResponseType]; +``` + ## Modality Content part modality. diff --git a/docs-devsite/ai.prebuiltvoiceconfig.md b/docs-devsite/ai.prebuiltvoiceconfig.md new file mode 100644 index 00000000000..4b0a90b1a21 --- /dev/null +++ b/docs-devsite/ai.prebuiltvoiceconfig.md @@ -0,0 +1,43 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# PrebuiltVoiceConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configuration for a pre-built voice. + +Signature: + +```typescript +export interface PrebuiltVoiceConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [voiceConfig](./ai.prebuiltvoiceconfig.md#prebuiltvoiceconfigvoiceconfig) | string | (Public Preview) The voice name to use for speech synthesis.See https://cloud.google.com/text-to-speech/docs/chirp3-hd for names and sound demos. | + +## PrebuiltVoiceConfig.voiceConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +The voice name to use for speech synthesis. + +See https://cloud.google.com/text-to-speech/docs/chirp3-hd for names and sound demos. + +Signature: + +```typescript +voiceConfig?: string; +``` diff --git a/docs-devsite/ai.speechconfig.md b/docs-devsite/ai.speechconfig.md new file mode 100644 index 00000000000..95c63964974 --- /dev/null +++ b/docs-devsite/ai.speechconfig.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# SpeechConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configures speech synthesis. + +Signature: + +```typescript +export interface SpeechConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [voiceConfig](./ai.speechconfig.md#speechconfigvoiceconfig) | [VoiceConfig](./ai.voiceconfig.md#voiceconfig_interface) | (Public Preview) Configures the voice to be used in speech synthesis. | + +## SpeechConfig.voiceConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configures the voice to be used in speech synthesis. + +Signature: + +```typescript +voiceConfig?: VoiceConfig; +``` diff --git a/docs-devsite/ai.voiceconfig.md b/docs-devsite/ai.voiceconfig.md new file mode 100644 index 00000000000..b22ac7e104c --- /dev/null +++ b/docs-devsite/ai.voiceconfig.md @@ -0,0 +1,41 @@ +Project: /docs/reference/js/_project.yaml +Book: /docs/reference/_book.yaml +page_type: reference + +{% comment %} +DO NOT EDIT THIS FILE! +This is generated by the JS SDK team, and any local changes will be +overwritten. Changes should be made in the source code at +https://github.com/firebase/firebase-js-sdk +{% endcomment %} + +# VoiceConfig interface +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configuration for the voice to used in speech synthesis. + +Signature: + +```typescript +export interface VoiceConfig +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [prebuiltVoiceConfig](./ai.voiceconfig.md#voiceconfigprebuiltvoiceconfig) | [PrebuiltVoiceConfig](./ai.prebuiltvoiceconfig.md#prebuiltvoiceconfig_interface) | (Public Preview) Configures the voice using a pre-built voice configuration. | + +## VoiceConfig.prebuiltVoiceConfig + +> This API is provided as a preview for developers and may change based on feedback that we receive. Do not use this API in a production environment. +> + +Configures the voice using a pre-built voice configuration. + +Signature: + +```typescript +prebuiltVoiceConfig?: PrebuiltVoiceConfig; +``` diff --git a/packages/ai/integration/constants.ts b/packages/ai/integration/constants.ts index 1adfa4f47a0..f4a74e75039 100644 --- a/packages/ai/integration/constants.ts +++ b/packages/ai/integration/constants.ts @@ -54,6 +54,12 @@ const backendNames: Map = new Map([ const modelNames: readonly string[] = ['gemini-2.0-flash', 'gemini-2.5-flash']; +// The Live API requires a different set of models, and they're different for each backend. +const liveModelNames: Map = new Map([ + [BackendType.GOOGLE_AI, ['gemini-live-2.5-flash-preview']], + [BackendType.VERTEX_AI, ['gemini-2.0-flash-exp']] +]); + /** * Array of test configurations that is iterated over to get full coverage * of backends and models. Contains all combinations of backends and models. @@ -69,6 +75,25 @@ export const testConfigs: readonly TestConfig[] = backends.flatMap(backend => { }); }); +/** + * Test configurations used for the Live API integration tests. + */ +export const liveTestConfigs: readonly TestConfig[] = backends.flatMap( + backend => { + const testConfigs: TestConfig[] = []; + liveModelNames.get(backend.backendType)!.forEach(modelName => { + const ai = getAI(app, { backend }); + testConfigs.push({ + ai, + model: modelName, + toString: () => formatConfigAsString({ ai, model: modelName }) + }); + }); + + return testConfigs; + } +); + export const TINY_IMG_BASE64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII='; export const IMAGE_MIME_TYPE = 'image/png'; diff --git a/packages/ai/integration/live.test.ts b/packages/ai/integration/live.test.ts new file mode 100644 index 00000000000..caa18970ab7 --- /dev/null +++ b/packages/ai/integration/live.test.ts @@ -0,0 +1,327 @@ +/** + * @license + * 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. + */ + +import { expect } from 'chai'; +import { + BackendType, + getLiveGenerativeModel, + LiveGenerationConfig, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation, + ResponseModality +} from '../src'; +import { liveTestConfigs } from './constants'; +import { HELLO_AUDIO_PCM_BASE64 } from './sample-data/hello-audio'; + +// A helper function to consume the generator and collect text parts from one turn. +async function nextTurnText( + stream: AsyncGenerator< + LiveServerContent | LiveServerToolCall | LiveServerToolCallCancellation + > +): Promise { + let text = ''; + // We don't use `for await...of` on the generator, because that would automatically close the generator. + // We want to keep the generator open so that we can pass it to this function again to get the + // next turn's text. + let result = await stream.next(); + while (!result.done) { + const chunk = result.value as + | LiveServerContent + | LiveServerToolCall + | LiveServerToolCallCancellation; + switch (chunk.type) { + case 'serverContent': + if (chunk.turnComplete) { + return text; + } + + const parts = chunk.modelTurn?.parts; + if (parts) { + parts.forEach(part => { + if (part.text) { + text += part.text; + } else { + throw Error(`Expected TextPart but got ${JSON.stringify(part)}`); + } + }); + } + break; + default: + throw new Error(`Unexpected chunk type '${(chunk as any).type}'`); + } + + result = await stream.next(); + } + + return text; +} + +describe('Live', function () { + this.timeout(20000); + + const textLiveGenerationConfig: LiveGenerationConfig = { + responseModalities: [ResponseModality.TEXT], + temperature: 0, + topP: 0 + }; + + liveTestConfigs.forEach(testConfig => { + if (testConfig.ai.backend.backendType === BackendType.VERTEX_AI) { + return; + } + describe(`${testConfig.toString()}`, () => { + describe('Live', () => { + it('should connect, send a message, receive a response, and close', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + await session.send( + 'Where is Google headquarters located? Answer with the city name only.' + ); + const responseText = await responsePromise; + expect(responseText).to.exist; + expect(responseText).to.include('Mountain View'); + await session.close(); + }); + it('should handle multiple messages in a session', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const generator = session.receive(); + + await session.send( + 'Where is Google headquarters located? Answer with the city name only.' + ); + + const responsePromise1 = nextTurnText(generator); + const responseText1 = await responsePromise1; // Wait for the turn to complete + expect(responseText1).to.include('Mountain View'); + + await session.send( + 'What state is that in? Answer with the state name only.' + ); + + const responsePromise2 = nextTurnText(generator); + const responseText2 = await responsePromise2; // Wait for the second turn to complete + expect(responseText2).to.include('California'); + + await session.close(); + }); + + it('close() should be idempotent and terminate the stream', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model + }); + const session = await model.connect(); + const generator = session.receive(); + + // Start consuming but don't wait for it to finish yet + const consumptionPromise = (async () => { + // This loop should terminate cleanly when close() is called + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for await (const _ of generator) { + } + })(); + + await session.close(); + + // Calling it again should not throw an error + await session.close(); + + // Should resolve without timing out + await consumptionPromise; + }); + }); + + describe('sendMediaChunks()', () => { + it('should send a single audio chunk and receive a response', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + + await session.sendMediaChunks([ + { + data: HELLO_AUDIO_PCM_BASE64, // "Hey, can you hear me?" + mimeType: 'audio/pcm' + } + ]); + + const responseText = await responsePromise; + expect(responseText).to.include('Yes'); + + await session.close(); + }); + + it('should send multiple audio chunks in a single batch call', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + + // TODO (dlarocque): Pass two PCM files with different audio, and validate that the model + // heard both. + await session.sendMediaChunks([ + { data: HELLO_AUDIO_PCM_BASE64, mimeType: 'audio/pcm' }, + { data: HELLO_AUDIO_PCM_BASE64, mimeType: 'audio/pcm' } + ]); + + const responseText = await responsePromise; + expect(responseText).to.include('Yes'); + + await session.close(); + }); + }); + + describe('sendMediaStream()', () => { + it('should consume a stream with multiple chunks and receive a response', async () => { + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const responsePromise = nextTurnText(session.receive()); + + // TODO (dlarocque): Pass two PCM files with different audio, and validate that the model + // heard both. + const testStream = new ReadableStream({ + start(controller) { + controller.enqueue({ + data: HELLO_AUDIO_PCM_BASE64, + mimeType: 'audio/pcm' + }); + controller.enqueue({ + data: HELLO_AUDIO_PCM_BASE64, + mimeType: 'audio/pcm' + }); + controller.close(); + } + }); + + await session.sendMediaStream(testStream); + const responseText = await responsePromise; + expect(responseText).to.include('Yes'); + + await session.close(); + }); + }); + + /** + * These tests are currently very unreliable. Their behavior seems to change frequently. + * Skipping them for now. + */ + /* + describe('function calling', () => { + // When this tests runs against the Google AI backend, the first message we get back + // has an `executableCode` part, and then + it('should trigger a function call', async () => { + const tool: FunctionDeclarationsTool = { + functionDeclarations: [ + { + name: 'fetchWeather', + description: + 'Get the weather conditions for a specific city on a specific date.', + parameters: Schema.object({ + properties: { + location: Schema.string({ + description: 'The city of the location' + }), + date: Schema.string({ + description: 'The date to fetch weather for.' + }) + } + }) + } + ] + }; + const model = getLiveGenerativeModel(testConfig.ai, { + model: testConfig.model, + tools: [tool], + generationConfig: textLiveGenerationConfig + }); + const session = await model.connect(); + const generator = session.receive(); + + const streamPromise = new Promise(async resolve => { + let text = ''; + let turnNum = 0; + for await (const chunk of generator) { + console.log('chunk', JSON.stringify(chunk)) + switch (chunk.type) { + case 'serverContent': + if (chunk.turnComplete) { + // Vertex AI only: + // For some unknown reason, the model's first turn will not be a toolCall, but + // will instead be an executableCode part in Google AI, and a groundingMetadata in Vertex AI. + // Let's skip this unexpected first message, waiting until the second turn to resolve with the text. This will definitely break if/when + // that bug is fixed. + if (turnNum === 0) { + turnNum = 1; + } else { + return resolve(text); + } + } else { + const parts = chunk.modelTurn?.parts; + if (parts) { + text += parts.flatMap(part => part.text).join(''); + } + } + break; + case 'toolCall': + // Send a fake function response + const functionResponse: FunctionResponsePart = { + functionResponse: { + id: chunk.functionCalls[0].id, // Only defined in Google AI + name: chunk.functionCalls[0].name, + response: { degrees: '22' } + } + }; + console.log('sending', JSON.stringify(functionResponse)) + await session.send([functionResponse]); + break; + case 'toolCallCancellation': + throw Error('Unexpected tool call cancellation'); + default: + throw Error('Unexpected chunk type'); + } + } + }); + + // Send a message that should trigger a function call to fetchWeather + await session.send('Whats the weather on June 15, 2025 in Toronto?'); + + const finalResponseText = await streamPromise; + expect(finalResponseText).to.include('22'); // Should include the result of our function call + + await session.close(); + }); + }); + */ + }); + }); +}); diff --git a/packages/ai/integration/sample-data/hello-audio.ts b/packages/ai/integration/sample-data/hello-audio.ts new file mode 100644 index 00000000000..7c3b8f2f693 --- /dev/null +++ b/packages/ai/integration/sample-data/hello-audio.ts @@ -0,0 +1,19 @@ +/** + * @license + * 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. + */ + +export const HELLO_AUDIO_PCM_BASE64 = + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAP//AAAAAAAAAQABAAEAAQAAAAAAAAD///7//v8AAAIAAgAAAP7/AgAKAAcA7P+1/3r/Xf9x/67/8v8dACgAIAAZABgAGwAZABIADQAKAAkACAAGAAYACAALAAsACQAJAAsADwATABUAFQATABIAEAARABIAFAAVABMAEAANAAsACwALAAoACgAKAAoACgAKAAoACQAJAAkACAAIAAgACAAIAAgACAAHAAcABwAHAAYABgAGAAYABQAFAAUABQAFAAUABAAEAAQAAwADAAMAAwADAAMAAgACAAIAAgABAAEAAQAAAAAAAAAAAAAAAAAAAAAA/////////////////v/+//7//v/+//7//v/+//7//v/+//7//f/9//3//f/9//3//f/9//3//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z/+//7//v//P/8//v/+//7//v/+//7//v/+//7//v/+//8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//z//P/8//3//f/9//3//f/9//z//P/8//z//P/8//3//f/9//3//f/9//3//f/9//3//f/9//3//v/+//7//v/+//7//v/+//7//v/+//7//v/+//7//v////////////////////7//v//////////////////////AAAAAAAA///9//3/AAADAAQAAQD9//r//P8BAAUABAAAAP3//P///wEAAQAAAP//AAACAAIAAgABAAEAAQABAAEAAQAAAAAAAQABAAEAAQABAAEAAQABAAEAAgACAAIAAgACAAIAAgABAAEAAQACAAIAAgACAAIAAgACAAEAAQABAAEAAQABAAEAAgACAAIAAgACAAIAAgACAAIAAgACAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgACAAIAAgABAAEAAQABAAEAAQABAAEAAQACAAIAAgACAAIAAgABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAEAAQABAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////////////////////////////wAAAAD///////////////////////////////////////////////////////////////////////////////////////8AAAAAAAAAAAAAAAAAAAAA//////////////////8AAAAAAAD///////////////////////////////////////////7//v//////////////////////////////////////AAAAAAAAAQABAAEAAQABAAEAAQABAAIAAgACAAIAAgABAAEAAQABAAAAAAAAAAAAAAD//wAA//////7//v/+//7//f/9//z//f/9//3//f/9//z//P/7//z//P/8//z//P/8//z/+//6//r/+v/6//r/+v/6//n/+f/5//n/+f/5//n/+f/5//n/+P/3//f/9//3//j/+P/3//f/9v/2//f/+f/5//n/+v/7//v//f/9////AQABAAIABAADAAMABQAHAAgACQALAAwADAAMAAsACgAKAAkACwAMAAsACgAJAAkABwAFAAUABgAHAAUABQAFAAQABAACAAQABQACAAEAAQACAAIAAAABAAMAAgACAAMABgAEAAIAAwAEAAIAAQADAAYABQAEAAUABgAIAAYAAwAJAAwACgAJAA4AEAARABAADwAUABgAFQAUABwAHAAVABQAFwAWABEADwASABEACwAHAAYABQAGAAcACgAPABAADgANAA4ADgARABIAFgAaABsAGQAVABEAEwAXABgAFAATABcAEQAIAAoADwAMAAYAAgAAAAAA/v/7//v/+P/4//7/AAD3//D/8f/0//D/7v/1//r/9//z//X/+P/z/+v/7f/v/+z/6f/q/+3/7v/u/+r/5f/l/+f/6v/w//D/6P/p/+r/5f/m/+z/7f/p/+f/5P/f/+b/7f/w//L/7P/m/+7/9f/3//7/BAABAPr/+P/8/wEAAgADAAYABAD9//v///8GAAkAAwAAAAAA+P/x//b/9//0//T/+/8AAPr/9//+/wIA/f/2//r/AQD+//3/CwAYABMADwANAAoAEQAZABAACQALAA4AEQANAAEA/v8FAAMAAQAFAAAA9//u/+b/5//p/+L/4v/n/9v/zv/O/8//zf/O/9X/4f/m/9v/1//b/9//5P/m/+b/1//R/9T/3v/m/+P/2//O/8j/xf/B/9H/4//h/+v/8f/y//T/+/8MAAoABgAFAP7/EQAWAA8AJQAzACoANAA+AC0AHQATABsAKQAjABYAHQAWAAsAFwAkADUAPQAzACsAHwAMAAkAIAArACYAGgAIAAkADQAPABsALwA0ACsAKgArABwAGQAdABgAFAAHAO7/7f/v/+v/6f/3/+r/yf/I/8//yP/G/77/uP/H/8b/0f/Z/9T/1f/L/8D/zf/Q/83/2P/b/9j/2//i/9n/4v/u/97/4P/k/9j/9f/7/9v/6v/6//H/CQAnACoAEQAHABgAJAApACkAKAA4AEUAOgA1ACgAFwAQABoAAQDl/93/0f/C/8P/uf+1/6n/lf+V/7D/s/+2/+L/6f/U//P/+P/n//j/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UwBdAFQATAA/ADwALwAcAAkACgAAAOz/8v/6//X/7//v//b/5//T/83/yf+//7r/t/+o/7r/v/+2/7f/xf/A/7T/sv+9/8n/yP/C/8r/uv/B/8b/wv+6/7//wf+x/7P/uf+5/8D/vv+4/8H/u//Q/7r/vv/E/8b/y//X/+7/DQAmACoAVgBoAGsAeAByAHUAdQBoAHUAhgCEAIcAjQCRAIgAkACEAIYAfwB1AGUAVgBJAEkARAA9ACwAMAAuAC8AMwBDADsAQgBCADkAOgA5ADcANgBCAEcAQwBCAD4ARAAzACUAJAA2ACsAQAAyACYAJAAJAP3/DAAJAAkACQD6/+r/9P/1/+z/7v/o/+r/+v/2/wQAAQAQABoAIwAqACsAKwAxACoAJQAgABEADgAHAPz//P8IAA8AEQD7//b/6f/f/+P/1//a/8X/yf+3/8f/wf+9/7f/sf+5/7D/vP+u/7b/q/+r/7f/sf+m/53/rP+d/53/of+v/67/qv/A/8P/0//r////DgAMAB0AKAA3ADAAOgA1ADsAOwA1AB4AJwAmAB8AGwAJAAAA///o/+//8f8FAA4ADgATAPr/7//6//X/9P/m/+f/5//f/+f/1v/Y/9//4//l/+//9P/4//f/6//6//b/9//0//f/7f/l/9j/2P/e/8P/vf+3/7j/tP+8/7T/xv+x/67/o/+k/6n/sP+v/7X/rP+2/73/xP/B/77/yv/N/9P/2P/3//r//f8BAP//CwAVABcAIQApACwANgA0AD8ARQBAAEIARwBBADUAOgBBADsAPABKAFAASQBKAFQAVABUAGIAZgBeAFwAXABLAE8ARwBTAEwAOAAsADIALQAoADgAKQAuADEAKgA2ACsAMAArACMAKgApACcAMwAkAB4ADgASAAYA+/8BAAAAGQAHAAsACwADAPz/CwD9//f/7//Y/9X/1v/T/8j/0P/W/8v/5v/h//T/AAAIABcAEwAMABMAFwD8/woA/v/9//z/AAD9/+P/AADy/+7/+f////7/+v8MAAUABwANABQAGwAcADEAKQA5AEwATgBPAE0AXABNAFwAaABcAGAAVgBhAF0AUwBIADwAQQAvACsAKgAoACEAIgAhABgAHQATACUAHwAdAB4AGAAbABAACwAKAAIABQD0//7/+//+//b/+P/x/9j/3//U/93/zP/N/8z/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iv+N/5H/nP+j/6z/sf+4/77/xP/O/9n/6v/7/wgAEAAWACEAKgAuADIANwA2ADoAOwA4ACsAGwAWABEADwAKAAQAAQD3/+r/5f/g/+T/4//d/9z/1P/Y/9b/0//Q/83/x//F/8n/yP/H/8H/wf/F/8n/1P/C/9P/6//9/w0ACQATABMAGwAmACQAJAAmACwALwAqAC0AMAAzADEAJAAgABoAFwAVAA4ACwABAPz/9v/y//P/6f/o/+n/7P/z//3/CAAHAAQAAwD9//j/+v/4/+z/2v/S/9r/5//q/+H/1P/U/+H/7/8AAAAA/v/9/wYAIQA6AEcAPQAyADoAVQB2AIsAiQB+AIYAlgClAKUAnQCVAIkAewBwAGYAXgBWAEwATwBQAFAAUwBXAFIASgBIAEkASABFADQAIgAkAC8ALAAhABAACQAPABIADAAAAPv/+v/3//T/8P/u/+7/8v/8/wcAEwAeACMAIQAhACMAJwAiABwADQD///z/+//6//v/9v/5/wIADAARABIAFQAYAB8AKgAxADYAOgA9AD4AQABEAE0AWQBdAFcAVQBbAGYAawBlAGMAZABoAGsAYwBbAF0AXgBhAGIAWQBHAD0AMwApACEAHQAeACEAKwAyADMAKgAYAA4ABQD5//L/7P/h/83/xv/Y/+//8//Z/83/2v/l/+b/2f/I/8X/zf/F/6//ov+a/5j/k/+J/4L/hP+J/5L/nP+j/67/tv+1/7n/vP+3/7L/r/+1/7j/s/+v/6n/pP+p/7P/tv+5/8T/x//D/8L/yf/S/9X/1P/R/9n/4P/h/+T/5//w//b/8//q/+n/7P/t/+3/6//w//H/8v/0//P/7//o/+v/7//x//L/9P///wwAFwAaABkAGgAcABwAFAAGAPz//P////n/8P/w//f/+//+////AAABAAEAAgAIAA0ADgAPABEADgAQABIAHAAkACgAKwAnABwAEwAPAAkA/v/x/+n/6v/u//L/9P/1//L/8f/t/+b/4//g/+H/6P/u/+7/8P/4//7/AgAIAA8AGQAjACwAKgAlACEAHwAeABgAEgATABMAEgAPAA4ADQAKAAoACwANAA8AEwATABMAGQAaABgAGgAgACMAIAAnAC4ALwAyADEANgA7ADkAMAAlACAAIgAoACgAJgAfABUADAADAAAAAgACAAIA/P/6//j/8f/q/+T/4//Y/8z/xv++/7b/qf+g/5r/kf+J/4P/gf+E/4f/i/+R/57/pP+n/6z/sf+3/7//x//K/9D/0v/U/9f/2f/X/9P/z//K/8n/zP/V/9r/3//h/9v/2P/X/9X/1//d/+P/4//i/+P/4v/g/9z/1P/T/9L/1v/c/+P/7f/4//z//f8DAAIAAwAGAAMABwAMAAoADAAMAAwADAABAPn/+//+/wAA/v/5//f/+/8AAAEA/////wIABgAQABoAIQArADAAMwA3ADwARABMAEkAPwA5ADYAOwBCAEIAQABDAEUASgBMAEwAUABUAFUAVQBWAFkAYABfAFUATwBXAGQAaQBfAFQAWwBnAF8ARwA3AD8AUQBRADgAIAAcACMAGwAGAPv/+f/2/+7/4v/Z/9P/z//L/8r/zf/V/9f/0v/K/8b/zP/W/9T/zP/M/8f/vv+6/7v/u/+z/6z/qv+z/7z/vf+8/8X/1P/o//L/8P/w//b///8EABMAJAArACcAIwApADMAOAAzADEANwA4ADIAKgAkACQAIAAbAB4AHQAdABwAFQAOAA8ADAAMAAoAAAD2//T/9//5//f/9//9/wIACAAQABYAGgAfACwAOQA/AEYATQBNAFAAVgBdAGQAZwBpAGoAagBrAHEAcQBlAFYASQBAADkAMAAtACcAKAApACIAHgAgACkAKgAnACMAHwAZABEADAACAPv/8//m/9v/0f/J/8b/wP+1/6z/qP+g/5X/kP+Q/5P/j/+L/43/lP+c/6L/qP+x/77/wv/G/8z/0v/W/9L/zP/M/8v/zP/K/8b/wf/A/8L/vf+5/7j/uf+6/7z/v/++/77/u/+3/7b/tf+1/7n/vf/C/8P/yf/S/9b/0v/G/8D/wv/C/8L/x//M/9P/2f/Z/9v/5P/z/wQAFAAnADoATQBiAGYAYwBhAFgAVABVAFQAUQBPAE4ATgBIAEoATABNAE0ARwBGAEoASwBJAD8ANQA5AD0ANgAuACgAJAAgABwAGQAaAB0AIAAfABgAFgATABUAHQAjAC8ANgAzAC0AKgAbABYADwAJAA0ACQAHAAUACwAQAA0AEgARAA8ACgACAAQACAALABAADwACAPT/3//S/8f/wf/F/8n/zf/H/73/t/+v/6T/l/+T/5f/pf+v/67/sP+t/6z/rv+0/7r/wv/H/9D/3f/n//D/9v/2//P/8P/3//7/BgASACEALQAsACsAJgAmAC0AMwA+AFAAXgBrAHUAcgB0AHEAYQBaAE8ARgBGAEcAQwA5ADAAJgAdABgAEgAJAP7//f/4/+v/6v/l/9//5f/m/9r/4P/g/9X/1v/R/8b/xP+7/7H/rP+u/7f/w//L/83/0P/Q/8//z//V/+T/6//x//f/AgALAAsABwAHAAoADQASABgAFgAWABoAGwAaABAACwAMAAkACQAYACUAKgArAC8ALAAoACsALgAxADAAKgAmACAAHQAXAA8ADQAIAA0AHAAdABwAFgAQAAgA/v/1/+P/4f/c/9b/2P/V/9X/2P/W/8f/xf/M/8f/wv+4/7X/sv+t/63/pf+a/5f/nv+s/7v/xf/O/9f/2P/a/9//4f/f/+D/7P/1//j/8P/i/9j/0P/I/8H/wf/F/87/1P/V/9v/5f/t//L/8//2//3/AwALAA4AEQAZABsAHgAiACEAJgArAC8AMAAyADYANgA6AEAAQQA8ADkANwA3ADkAMwAtACsAGwAIAPX/6P/k/9r/1f/P/8P/vf+0/63/rv+z/7T/tf+z/63/qf+r/7D/sP+x/7j/wf/G/8f/zf/U/93/6//7/wYADQAWACAALAA2ADgAQgBOAE8AVQBZAF4AZQBjAFgASQBFAEgASwBLAEgARgBIAEUAQQBAADsAOAA+AD4ANAAwACkAJAAjABoAEwANAAQA/v/6//L/6//u/+3/5P/c/9H/zf/L/8v/0P/N/9H/0P/O/9X/zv/O/9P/1f/W/9D/zv/R/9j/3f/k/+r/6//t/+3/6//u//L/9f/2//n//f8EAA8AFwAeACAAJQAlACYALwAwACoAIgAhACQAIwAhAB8AJwAmACcAJwAgACcALwAyADMANgA6ADgAMQAkACEAJgAmACcALQA0ADcANQAvACUAKQAuAC4AKgAlACMAIAAeABoADgAJAAgACwAQABAAFgAWABYAGAAWABYAEgATABUAGQAZABgAGgAkACoAHwAeABsAHQAmACYAJgApADEAMgAwACoAJQAnACgAJAAoACkAIgAmACsAKwA1ADkAQABKAE4AUQBUAFYAVQBZAF4AYgBfAFwAUQBFADoAMQAmAB4AHAAWABEADQALAAkACAAKABEAEAANAAoA///0/+//5f/g/+P/4f/i/+H/3f/e/+X/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vv+9/73/t/+w/6b/of+n/7D/t/++/8b/zv/U/9r/3v/e/+D/3v/d/93/2//d/+L/4v/j/+L/3//Z/9X/0v/U/9j/1f/U/9P/0v/V/9b/1//X/9z/4//p/+n/6P/q/+//9f/7/wIABwANABQAHwAjAB8AFQAQABQAGwAgACMAJwAuAC4ALAAoACcAJwAsADMANwA3ADAALAApACMAHgAcABYAEAAQABUAHQAfACEAJgAoACgAJwAmACQAKAApACgAJgAkAB8AGwAbABoAGQAQAAwADQANAA8AEQARABIAFAASABEAFwAfACUAIwAjACUAJQAmACQAJwApACoAKwAtADUAOgA+AD8ARgBNAFAASwBFAEMAPgA4ADEAMAAtACcAHAAXABYAFQATABAADwAMAAoACgANAA0ADwAHAAIA/f/7//v/9v/z/+//7//u/+z/6f/x//r/AAD///j/9f/5//3//f8AAAYACAAIAAYABQAEAP///v/+//7/+f/w/+n/5v/k/93/2f/V/9L/0v/R/9P/0P/O/83/y//N/8v/y//L/9H/1//Z/9n/2P/a/9v/3v/b/9v/3v/g/+f/9P8AAAsAGAAjACoALQAqACgAJQAiAB8AIwAjACEAKAAxADYAPwBCAEQARgBLAE8AVQBeAGYAaABmAF4AVABIAD0AMQAnACQAHQAQAAEA9f/v/+b/1f/E/7//wf/F/8X/wv/D/8f/y//Q/9D/1P/b/93/3f/Z/9n/1f/R/9H/0f/N/8r/vv+4/7H/rP+k/53/nv+d/6L/pf+p/6z/q/+u/7H/sv+4/7//w//I/83/3P/p//D/+v/+/wIABQAEAAAA+f/2//X/8f/y//X/8f/u/+7/8P/u//H/9//4//n/9v/3//b/+P///wMA/v/3/+3/4//f/93/3//i/+P/4v/l/+f/6P/p/+f/5v/k/+H/3f/e/+D/6P/u//P/+v///wIAAwAHAAkACwAHAAUABgABAPz/+f/2//n/+//8/wMACgAUAB4AIwAkACYAKQApACYAIAAgAB4AHwAdABgADgAHAP///P/8//f/8f/w//D/8v/2/wIAEgAZAB0AIQAsADMAOAA0ADIAKgAfABMABAD+//b/7//k/9r/0f/I/8T/xP/H/83/zv/O/9H/2f/f/+L/6P/s//L/9P/z//T/8//t/+f/4//f/+D/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KgArACIAGgAZABUAEQAMAAoABAD5/+//7f/u/+X/2v/O/8H/s/+p/6f/p/+n/6n/sf+t/6D/nP+Y/5r/p/+r/6//v//I/87/zf/N/9X/3//f/9b/0//P/8v/z//T/9b/2f/Y/9n/3P/Z/93/4P/c/9v/3f/c/+L/5P/k/+P/3//c/+D/4f/g/+b/8v/2//n/+f/5//X/7P/n/+b/3f/Z/9z/2f/a/97/3//c/9X/zf/C/7T/p/+Y/5n/nf+Z/4v/f/99/3n/bf9o/2X/Zv9o/2z/bv9u/27/cP90/3T/eP91/3f/gP+G/4n/jP+O/47/lP+b/6T/pv+h/53/nv+e/6X/q/+s/7P/u//C/83/1f/U/9f/4//p//H/+P8BAAgABwAFAAgACQAKAAsACQAIAAEA8v/s/+f/4v/b/9X/0f/Q/9L/1P/U/9f/3P/b/9T/z//L/9H/2//b/9z/2//d/9z/4//l/+n/8P/t/+f/4f/W/9T/zv/G/8X/w/+8/7n/uP+3/7D/rf+t/6z/qP+i/6T/p/+r/7v/yv/N/8//0//R/9j/3v/k/+3/9f/7//z/AgAPAB0AJQAsADAALAAwADAALQApACkAKgAvADIAMQA0AD8ASABUAGQAbQB2AH0AggCQAJ4AogCxAMAAxgDMANEA2gDkAOoA8gD4APoA+QD3APMA9ADyAOoA6ADnAOIA4ADgAN0A3ADXANAAzQDLAMQAwQDCAL8AuACsAJ8AkwCKAIkAhgCDAIEAegBxAG4AagBjAFgAUQBDADUALgAmACMAHwAbABcAEgANAPr/5//f/+D/3v/X/9H/zv/K/8r/0f/R/8v/v//A/7j/sv+4/73/zf/V/9v/4f/m//L/+v/+/wkAGAAhACMALAA2ADQALgAsACwALgAtAC0ALwA1ADoAOwA5ADoAPQA+ADwAPAA9AD8APQA2ADUAMwA6AEEARgBOAFEAVQBgAGIAXwBgAGMAZgBgAFcATQBDAEEANgApACAAGwAWABAAAQDv/+3/7f/l/93/1P/J/77/sv+j/5r/kv+I/4T/f/+C/4f/iP+N/47/jf+H/3//gP+C/33/e/96/3//hP+K/47/i/+I/4X/hP+D/3v/cP9v/2j/Yf9h/17/Vv9S/1H/T/9W/13/Yv9m/2z/d/+D/5P/oP+r/7D/s/+2/7r/wf/H/83/1P/X/9j/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7//x//D/9v/3//L/8f8GABkAGQAaABoAIQAsADEAMgAvADYAOQA3AC0AKgAnACgAKgAdABcADwAGAPv/+P/3//r/8//u//b/+f8EAAMABwAAAPH/5//e/9T/0//a/9H/yP/E/7n/uf/B/77/xP/L/8X/wv/D/83/1P/V/9n/2v/g/+r/7P/0//j//v8GAAIA//8BAAQAAAD+/wEABwARABIAEgAaABwAHgAgACQALwAwACwAMQA3ADAAKwAnACcAIgAcABkAEwAUABAAEgAXAB0AIwAoADAANQA+AEAAOwA2ADMANAA1ADYALwAoACwAJAANAP7/9P/r/9b/xP++/6//qP+e/53/pf+k/6P/pP+q/6//qf+o/7T/uv+3/7H/s/+6/8X/yP/J/9P/3f/k/+n/7//5/wUADgAaACsANwBJAFEAUgBeAF4AYgBhAFUAVQBZAF4AXgBfAGUAZQBmAF4AWABZAFkATwBFAD4AOwA8AC8AJwAbABAAAwD3//T/8f/y/+z/5v/g/93/1P/Y/9//4v/i/93/2f/X/9T/2P/g/+P/8f/v/+n/9P/x/+b/5P/n/+3/7P/j/+P/6v/j/9//2v/a/9f/1v/e/+P/8f8EAAUACgAKAA0AEgAJAPn/7f/p/+T/3f/e/+T/3//T/8//z//K/8T/w//B/8T/yf/N/8//1P/Z/9j/1v/S/9X/2//e/9v/4P/e/9f/1v/T/9r/4//t//L//f8JABQAGwAgABkAEAAZABwAHwAhACYAJwAgABUACAAGAAkADAAKAA4AFQAaABQAGgAVABQADwAJAAwABwAJABAAEQAaAB8AIAAiACoAMgAtACoALwAmABgAGQAfAB0AFgAUABEADgAOAAwACAAGAAcABwAAAAsAGQAiAC0AKgAoACIAJwAuAC8AMgA4ADoAMQAqACMAJAAiAB8AFwABAPD/5f/b/9n/1P/T/9X/1P/V/+L/7f/7/wMAAgAOABgAFwAVABYAHAAaABYAGwAiAB8AGwARAAQABQALAAoABwD9//r//f8DAAMACAAfACgAJAAgACoALAAlACAAHAAdABsAFwASABIAFQATAA8AFQAaABAABwAAAPn/8//4//z/9v/8/wMAAwD9//z///8AAPL/7P/v//f//f/v/+b/6f/x/+//7P/q//X/9v/z//L/9/8CAAwAFgAQAAwADQAOAAsABgD/////+//u/+v/3P/Q/9D/w//A/8P/uv+z/6z/p/+r/6b/p/+v/6//r/+9/8H/xv/Z/9P/2f/p/+z/8v8AAAwAIAAkACoAOAA+AEUARgBJAFQAXABZAFUATwBLAEoASgBCADUALwArACcAIQAoADUAMAAuACEAGQAeACUAIgAsADYALgAvAC4ALQAvADMAMAAxACwAJAAhACIAJQAaABkAGQAaABcAEAAPAAwABAD+//n/8v/o/+j/6//n/+f/3//m/+j/2v/Q/9D/1P/W/8z/w//I/8n/wP+8/7b/t/+0/6j/o/+n/7X/v//G/8v/1f/U/8r/yP/I/7//vP+5/7n/tf+7/7//vP/G/8X/wv/C/8X/3f/q/+3/8v/7//z//f/y//L/AQAHAAgABQAHABEAMAApADAAMgAOAOX/6P/s/8j/zf/p/+D/2/8BABIAFgAjABoACwD//wcADgALABEAEgABAPL/7//q/+//8f/3//X/6v/k/9j/0v+7/6z/pf+c/5L/lP+m/7X/vv+9/8X/yv/B/7//x//R/9r/5P/x/wMAHgAiACsAOgBDAE0ATgBfAGsAbwBvAG4AewB6AHEAYwBbAFoAUABMAFcAXgBaAFQASABFAFQATgBCAEAAPwA2ACcAHgAeACIAEQAMAAcACAADAOf/1v/W/9r/zP/L/9D/zf/E/7r/rv+r/6j/m/+b/6L/p/+o/7T/vv++/8b/1v/g/+L/4f/c/9f/3P/p/+3/9//w/+r/+P/7/wUACAARABYAEQAUAB4AKQAxADIALgArADEASgBMAFwAYQBtAGoAeQCBAIUAkgCOAJoAmQCfAKUAowCdAJgAkwCPAJAAhwB+AHMAeQCAAH0AdwByAHMAcQB1AGMAVQBWAEwARQA1ADUAPAA7ACcAIAAUABUADAACAP3//P/5/+r/5f/d/9P/yv/E/7H/sf+p/6f/pf+Y/5L/if+B/3T/cf94/33/c/9u/2b/aP9q/27/c/94/3//d/93/3T/e/9+/3b/cv90/3P/b/9x/3b/fv+H/5P/m/+p/7X/wf/D/87/1//Y/93/7f/4//z/9f/v//7/AgD9//n/AQABAPb/8P/y//P/9P/y//P/AAANAAwACwAOABIAFQAQABcAEwATAAYADQATABEAEAAOAAkACQALAAMACgD7////EAATABgAFQAMAAwABwABAAkAAAACAP3//P/2//P/7P/v/+//3v/h/+3//f///wEA9/8BAAkAAgD8//f/+P/1//b/+f/7//X/8v/0//b/AAAJAAsACwALABAADwAJAAAAAAACAPz/8f/p/+j/7P/j/9T/zP/G/8j/uv++/7z/wv/C/8n/z//Q/9X/3P/d/9r/2P/V/9//4//t/+//AAAHAAgABwAIAA4AEQAZACQALwA0ADMALwAlACUAIwApACwAIQAmACgAKAApACgAKgAcABsAJAApADkAPgBAAEQASwBLAE0AVwBWAFsAWABaAFwAXABZAE0AUgBLAEUAOAAvACsALAAzAC8AMAAsAC4AJAAiAC0ANAA5ADkAPQA2ADEAKwAxADEAMQAzADIAKQApAC0AMQAyADEALwAqACoAJgAbACQAHQAbABsABwAFAAMA/f/x/+X/2//c/9z/1//U/9P/0f/N/8X/wP+6/73/zP/W/+L/6P/y//b//f8EAA0AJQA2ADoAMgA0ADUAMwA1AD8ASgBZAGAAYABuAGgAbgBoAGsAZwBqAGYAYwByAG0AbgBlAFwAWABOAEIAOAAzACgAIwAXABMABQAKAAMA8//g/9T/0v/N/87/zP/R/8f/xv+8/7n/tv+m/5z/mf+X/5L/lf+Z/6r/rP+k/6H/oP+k/6j/tP/A/8//0f/T/8f/w//A/7z/wf/C/8//yv/S/9b/3v/e/9j/2//Y/9f/3//k/+X/6//u/+X/3//i/+T/5f/k/+H/3v/e/9//2//X/9//3//g/9P/1f/S/8//y//E/8n/xv/E/8X/w//B/7//wf/K/9T/1//V/9j/2v/d/+D/5P/o//D/9P/u/+r/5//l/+H/4//e/93/2//i/+n/6v/u/+X/4P/i/+H/3v/T/83/zP/O/8n/v//E/8L/uv+p/6D/qP+w/7z/uv/I/9n/zP/H/8v/zP/R/9T/0v/S/8//zf/G/8b/zP/Y/8//0P/b/+L/7P/o/+z/+P8EAAkAFAAfACYANwA2ADoAPQBHAEoATgBhAGwAbwBsAG8AbwB1AG0AZABoAF4AYABbAFsAagB0AHcAeQBzAGYAXABRAD8AMwAfABUACgD6/+T/zv/P/8b/w/+5/7P/wP/A/8D/vv/D/9H/2v/Y/9r/7v/5/wEAAgADAA0AEQADAPn/+f/4//n/9P/8/woAEwAOABYAHgAcACUAJQAgACIAFQATABcAEAALAPz/8//v//P/8f/u/+L/3P/Z/8//zP/P/9L/1f/P/77/vf/H/83/x//I/8b/wf+2/7j/yv/Z/97/2f/e/+P/9v/7//7/CgAOABoAJQA/AFAAYABqAH0AiACLAJkAowCtALUAugDEAMEAwADFAMAAwwC+AMkAywDEALwAsgCyAKkAqgCgAJUAjACDAHQAXgBPAEoARQA7ADUAMQAtACwAHwAUABQAFQAaABsAGwAZABIADwAPAAsACAAAAAYABAACAAsADwAXABUAFQAOAA4ACwATABkAEgASABMAGQAcACIAHgAfABgADQAUABMAEQAaABAACAD//+//9v/0/+3/7P/e/9P/0f/P/87/zf+//7H/qv+g/5X/lP+I/4H/ff94/3b/ef9+/4X/j/+J/5X/nP+b/63/vP+//8v/0P/K/9r/3P/V/9r/4//r//b/8f/y//7/AgALAB0ALAA/AE0ASQBCADcANwA/AEUAPwA0ACsALgAtACoAIwAhABkACQD///f/+/8CAAIA8f/l/9r/xP+//7T/qP+a/4f/gP+D/4j/gf+B/3b/ff99/33/gP95/3v/c/9t/2j/a/9n/2n/c/9z/2v/dP92/27/cf9x/3j/f/+E/4P/k/+m/6j/uf/C/8r/0f/Y/97/5f/x//f/+v8AAAkABgAIAAcAAwALAAoAEQAdACgALAAmADEAPgA5AD0AQgBCAE8AUwBbAF8AYABWAEoASQBNAEMANQAtADUAPwBHAD8ALQAqACUAGgAOAPv/9f/s/+P/5f/h/9//2P/W/8//zv/V/9f/3v/V/9n/2//r//D/+P/7//b//P/8/wkACwAaACYAIgAeABUAFwAaABYAGAAcACMAHQAaABsAHAAmADAAKwAnACMAKgAvADEALwAlACkAHAAZACUANAA+AEAAQgA3ADcANgBDAEkATABSAFQARwBMAFUAVQBZAEsAQgA2ADwANwAwACkAIwAoACEAHgAXABUAGAAWABMA///9//L/4//m/9P/2f/f/+X/5v/Y/9H/xP/C/8n/1f/V/9T/1v/R/8v/yv/L/9H/4v/e/+L/5v/w//n/DAAVAB8AHAAaAB8AHgAnABoAGAAZABcAEwASABQADgAHAPr/9P/w//T/7//h/9z/1//j/9v/0v/R/9X/0//V/8//2//y//z/BQALABUAFAAfABsAGgAiAB8AKQA4AD8ATABTAFYAZQBiAGkAbABxAH8AgwCHAIMAfAB8AH8AfwCCAHsAeACCAHoAcQBnAFkAWABMAEMAQgAyACMAEwAFAP3/9P/n/+P/5v/m/+n/4v/S/87/w/+5/6z/p/+j/6T/ov+b/6b/uf/J/9D/yv/H/8r/zv/b/+f/6v/v//b/AgAOABUAJgAoADgASABWAFgAXQBuAHgAegBxAHEAaQBeAFsAVwBTAE0AQwAyAB4AHgAYAA0A+v/p/+f/7f/v/+r/7P/u/+f/2f/f/+v/7v/q/+D/3P/a/9n/1v/W/9f/0//E/7v/u/++/7n/s/+r/7L/tv+v/6r/r/+7/7v/s/+x/7n/wv/G/77/uf+1/7f/tf+4/8L/uv+y/6b/qP+q/7H/qP+m/6H/lv+S/5b/nv+i/5r/k/+c/6X/of+j/63/t/+8/7//x//K/8b/xf/H/8j/0v/X/9v/3f/V/8z/zP/N/8P/yv/S/9X/3f/d/9r/3f/W/9X/4f/f/+T/2f/W/9b/0v/N/8n/xP+9/7T/qP+k/6L/o/+Z/5D/gP97/3T/cP9r/23/c/9x/4D/hf+N/4//k/+V/5r/nP+a/5z/o/+x/7f/wv/I/9D/1v/d/+3/9P/y//j/BgAPAB8ALQAwADYASQBRAGAAbwB9AHwAdgB5AIUAhQCLAJQAmACVAIkAiwCGAJAAlQCUAJIAgwBzAHAAbgB0AHgAdQBwAGIAWQBYAFUAVgBOAE8AVABLAEQANwA2ADcAMQAnACIAIgAmACoALQA3ADwAOAA2AD0AQABHAEwATgBVAEwAPgBBAEwAVABaAFIAVwBcAGIAZQBmAGcAbAByAHAAcwB4AHcAeACAAIAAfQBwAGoAbgBvAHgAagBqAGgAZgBxAGwAdgBtAHMAcwBwAHcAdAB5AHkAdwB5AHQAeQB2AHUAgAB+AIUAiACIAIIAfgB4AHAAdgBpAFsAWABQAE8ARgBAAD0AOwA3ADMALgA4ADwAMQAmABcACAAGAP3//f/y/+b/4f/W/8v/wv+2/7P/tP+y/7D/s/+9/8j/0v/U/9P/1v/W/9r/3//o/+//8//6//r////7//b/5P/Z/9j/2P/i/9//1v/W/9L/y//F/77/wf/B/77/u//B/7z/s/+s/6P/p/+p/5z/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GAAdACMAKgAwADUANQAxAC4ALgAwADYAOwBAAEAAPwA/AEAAQgBFAEgASABHAEcATABTAFkAXQBfAF8AXQBaAFgAWABcAGEAYgBeAFkAVQBSAFAATwBSAFMAUABNAEoASwBRAFQAUgBOAEkAPwA0ACkAHwAYABAADAANABMAHgAkACcAKgApACkAJgAkACEAHgAXAA0ABQABAPv/7//m/+T/6P/r/+//8f/u/+r/6//v//j/+//5//r//f8HABEAFgAaABoAHgAmADAAOgBDAEgATQBRAFUAVgBWAE8AQgA5ADgAPgBCAEIARABHAEQAPgA8ADcAMAAsACUAGQAIAPf/6P/a/8z/wP+3/63/oP+X/5P/j/+N/4z/kP+W/5z/ov+n/6z/sf+6/8P/yf/P/9T/1v/Z/97/5//x//b/+/8CAAsAEwAWABkAGwAcABwAHQAgACAAGgAWABkAHQAcABcAFgAeACUAIwAWAAwACgAKAAQA+P/p/9//1//K/8D/u/+7/7T/q/+i/6D/p/+w/7f/u/++/7//vP+1/7L/uv/F/8v/0P/X/9//5P/q//T/+////wIADAAVABcAFgAZABkAFwASAAsABQABAAAA///7//H/6v/p/+v/5v/h/+D/4f/m/+b/5f/k/+T/4//h/97/3P/c/9n/1P/T/9T/2v/e/+X/6v/t//L/9f/5//v/+v/+/wMABwAKABAAFwAbACAAKAAvADIANQA1ADUANgA3ADYANQA2ADgAOwA7ADkANQAuACwAKwAsACwALQAoACAAGgAYABcAEgAJAAQABwAJAAQA///6//n/+P/3//r///8DAAQABAADAAEA/v8AAAQADAASABUAFgAcACIAJwAnACQAJgArADEANwA+AEUATQBQAFMAVgBbAF4AWwBZAFoAWABSAEsASQBLAEcAPQAzACkAHAASAAgA/f/1//T/8//u/+b/4f/h/+P/5f/l/9//1v/T/9T/0//R/9D/zf/K/8f/xP/A/7j/sf+r/6j/pP+k/6j/r/+z/7b/uP+4/7b/t/+7/8H/xP/B/8H/w//G/8f/yf/P/9T/2f/h/+b/6v/t//P/9//2//f/AAALAA8ADgAPABYAIQApADAANgA9AEIAQwBFAEcARQBAADoAOgA9AD8AOAAuACkAJwAmAB4AEQACAPn/8//x/+3/5P/b/9L/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9v/8//3/AAAJABcAJwA0ADwAQgBEAEQARQBEAD8AOgA4ADsAQwBMAFAAVABYAFsAWwBZAFcAVgBUAFIAUABNAFAAVgBdAFoAVABPAEsARgBBAD8APgBAAEMARQBIAE0AUQBPAEsARwBFAEUAQwA/ADoAMwAqAB4AFgATABIAFgAcAB8AIgAjACAAHgAcABgAEwARAA8ADwAKAAYABgACAPr/8//t/+r/5f/i/+D/4v/i/+P/4v/d/9T/x/+8/7L/q/+n/6T/ov+d/5j/kf+Q/5L/lP+U/5X/mf+e/6L/pv+u/7f/v//F/8//1v/b/+D/6P/v//H/9P/5//3/AwAOABQAFwAaAB4AIgAhAB0AHQAhAB4AFwASABIAEwAVABkAHAAiACkALQAwADMANQAzADMAOQA9AD4APAA3ADMANQA9AEEAQwBBAD8APgA/AD0AOQA4ADoAPgBHAE4AUwBQAEoARwBGAEIAOwAyACgAHgASAAgA/v/1//D/7v/o/97/1//R/8r/v/+z/6f/n/+c/5b/j/+I/4P/fv95/3b/df96/4D/iv+V/57/pP+n/6n/rP+u/6z/p/+o/6//u//E/8r/0P/V/9//6//y//f/+v/+/wIABAAFAAcACgAOABQAFwAYABcAFQAWABkAGAAWABQAFgAZABsAGAAQAAkACAALABAAEAANAAkABwAFAAAA+P/0//f//v8EAAsAFgAdACEAJQAsADEAMwA1ADUAMgAvACsAKQAkAB8AGwASAAoABwAIAAoACAAGAAYABQAAAP7//f/7//j/9P/u/+j/5v/q//P//f8JABQAHQAeABQABwD///n/+f/5//b/8f/r/+j/5f/k/+X/5f/i/9//3f/g/+b/7P/w//P/7//q/+T/4P/f/+H/5P/n/+j/4//f/+P/6//z//v/BAAMABIAEwATABQAFQAQAAgAAgABAAUABwAHAAcABQD+//b/8v/x//D/7f/s/+3/6//r/+r/5v/e/9b/zf/E/77/vv++/8H/xf/M/9f/4v/t//X//P8GABUAIwAuADgARABOAFMAUgBSAFAATgBPAFIAVABVAFUAUABGADwANgA1ADIALQAqACcAJwAoACkAKwAsAC4ALwAuAC4ALgAsACYAIQAiACAAGAAQAAwADAAQABEADgALAAsAEQAUABEADgAOAAsABAD7//f/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6P/3/wUAEgAWABYAFwAWABUAFAAcACMAJgAeABQACwAHAAQAAgD+//3//v/6//D/5//l/+P/3v/Z/9P/0P/V/97/5P/m/+f/5P/f/93/3P/a/9P/zf/K/8r/yP/C/7z/t/+0/7b/vv/I/87/z//P/9H/1//c/+L/6v/v//T/9P/y/+3/6v/o/+n/5//j/93/3P/e/+D/4f/i/+b/6P/r//D/9P/9/wUAEAAcACEAJgAuADgAPwBCAEQARgBGAEUARABFAEkARgBAADoAMgAuACwAMgA1ADUAOABAAEUARgBDAEUASwBPAFIAUgBXAFwAXQBeAFsAWABbAF4AYwBrAHcAhACMAJEAkQCOAIsAhQCAAHwAdQBuAGgAYQBZAFEATgBOAEwARwBAADYALAAdAAwA///5//j/9//z/+3/5//g/97/4P/l/+j/6v/w//L/9f/4//n/+f/6//v//f/7//r/9//1//X/8v/x//H/8v/2//r//P/8//z/+P/x/+n/4//f/9z/2P/V/9L/z//N/8//0//U/9X/2f/e/+D/4v/n/+j/6f/r/+//9v/9/wMABwAKABIAHAAlACsALgAzADwARABEAEIAQgBDAEQARQBGAEkASQBDADsALwAfAA8ABAD7//H/6v/l/+X/5f/l/+b/5P/i/+T/5P/h/+H/5v/r/+v/6f/l/+D/2//U/8//z//R/8//zf/H/8P/wP+7/7b/sv+v/6n/ov+b/5f/kv+M/4j/hv+F/4f/if+J/4X/gv9+/37/gP+B/4L/gP+B/4j/jP+Q/5b/of+y/8P/zf/P/9H/1//b/9//4f/i/+f/7P/t//D/7v/r/+f/4f/f/97/3//i/+f/7f/x/+//6P/l/+j/8f/9/woAEgAdACoAMgA4AD4ASABQAFQAVgBcAGMAaABoAGMAXQBbAFoAVwBSAE4ATgBNAEsASABFADwALgAiABsAFAAJAP//9//x/+r/3//U/8//zv/M/8b/v/+8/7v/uv+6/7r/uP+4/7f/uP+5/7v/wP/G/8r/zv/S/9f/3P/e/+H/5P/m/+f/6f/y//z/AwAIAAsADgASABQAFQAUABQAFwAeACIAIAAaABcAFgATAAcA/v/+/wMABAADAAcACwAOABAAFAAZABoAGQAaABwAHAAYABYAGQAeACUALQA3AEYAVgBjAG4AeQCBAIkA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kf+b/7r/uP+n/63/wv/k//j/6f8gAD0AJwD6//H/BwD6//n/4v/V/9j/zP8DAAQADQAcAA0ADwBQAFMAZwApAPf/BgD3//r//P8DAP//AgAFAAkACQAFAAEA/v/7//n/+v/5//3/AAABAAIABgAHAAcABgAHAAkACAAHAAsACwALAA4ADgAOAA0ACwAJAAYAAwABAAAA//8AAAIAAgAEAAYABwAHAAgACAAHAAUAAwAAAP7//P/6//n/+f/4//j/+P/5//r//P/+/wAAAQACAAMAAwACAAEA///+//7//f/9////AQAGAAoADQASABUAFgAXABYAFAARAA4ACwAIAAUABAADAAMAAwADAAQABAAEAAMAAgAAAP7//P/6//j/9//2//T/9P/1//X/9f/1//b/9//5//v//f///wEAAgADAAQABAADAAMAAwACAAIAAwAEAAYACQALAA4AEAARABIAEQAPAA0ACQAHAAQAAQD///7//v//////AAABAAIAAgABAAEAAAD///7//f/8//z/+//7//z//P/9//3//v///wAAAQACAAQABAAEAAMAAwADAAIAAQABAAAAAAAAAAEAAQACAAQABAAFAAUABgAGAAUABQAFAAMAAwAEAAIAAgACAAIAAgABAAAAAAD///3//v/+//7//v///wEAAwAFAAQAAQD9//3//P///wEABAD6//3/BwACAAUA/P///wEA/f/9/wIA/v8FAAMAAAD///3/AQD+////AwACAP3/+f8BAAQAAgD///7/AQADAAEAAQAAAP//AwADAP///v8CAAIA///+/wAAAQAAAAAAAQAAAAAAAQAAAAAAAAA='; diff --git a/packages/ai/package.json b/packages/ai/package.json index d2ca2142b67..cc23d52af9a 100644 --- a/packages/ai/package.json +++ b/packages/ai/package.json @@ -41,6 +41,7 @@ "test:browser": "yarn testsetup && karma start", "test:node": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha --require ts-node/register --require src/index.node.ts 'src/**/*.test.ts' --config ../../config/mocharc.node.js", "test:integration": "karma start --integration", + "test:integration:node": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha integration/**/*.test.ts --config ../../config/mocharc.node.js", "api-report": "api-extractor run --local --verbose", "typings:public": "node ../../scripts/build/use_typings.js ./dist/ai-public.d.ts", "trusted-type-check": "tsec -p tsconfig.json --noEmit" diff --git a/packages/ai/src/api.test.ts b/packages/ai/src/api.test.ts index 27237b4edd3..7a281739b4a 100644 --- a/packages/ai/src/api.test.ts +++ b/packages/ai/src/api.test.ts @@ -16,7 +16,13 @@ */ import { ImagenModelParams, ModelParams, AIErrorCode } from './types'; import { AIError } from './errors'; -import { ImagenModel, getGenerativeModel, getImagenModel } from './api'; +import { + ImagenModel, + LiveGenerativeModel, + getGenerativeModel, + getImagenModel, + getLiveGenerativeModel +} from './api'; import { expect } from 'chai'; import { AI } from './public-types'; import { GenerativeModel } from './models/generative-model'; @@ -166,4 +172,62 @@ describe('Top level API', () => { expect(genModel).to.be.an.instanceOf(ImagenModel); expect(genModel.model).to.equal('publishers/google/models/my-model'); }); + + it('getLiveGenerativeModel throws if no apiKey is provided', () => { + const fakeVertexNoApiKey = { + ...fakeAI, + app: { options: { projectId: 'my-project', appId: 'my-appid' } } + } as AI; + try { + getLiveGenerativeModel(fakeVertexNoApiKey, { model: 'my-model' }); + } catch (e) { + expect((e as AIError).code).includes(AIErrorCode.NO_API_KEY); + expect((e as AIError).message).equals( + `AI: The "apiKey" field is empty in the local ` + + `Firebase config. Firebase AI requires this field to` + + ` contain a valid API key. (${AI_TYPE}/${AIErrorCode.NO_API_KEY})` + ); + } + }); + it('getLiveGenerativeModel throws if no projectId is provided', () => { + const fakeVertexNoProject = { + ...fakeAI, + app: { options: { apiKey: 'my-key', appId: 'my-appid' } } + } as AI; + try { + getLiveGenerativeModel(fakeVertexNoProject, { model: 'my-model' }); + } catch (e) { + expect((e as AIError).code).includes(AIErrorCode.NO_PROJECT_ID); + expect((e as AIError).message).equals( + `AI: The "projectId" field is empty in the local` + + ` Firebase config. Firebase AI requires this field ` + + `to contain a valid project ID. (${AI_TYPE}/${AIErrorCode.NO_PROJECT_ID})` + ); + } + }); + it('getLiveGenerativeModel throws if no appId is provided', () => { + const fakeVertexNoProject = { + ...fakeAI, + app: { options: { apiKey: 'my-key', projectId: 'my-project' } } + } as AI; + try { + getLiveGenerativeModel(fakeVertexNoProject, { model: 'my-model' }); + } catch (e) { + expect((e as AIError).code).includes(AIErrorCode.NO_APP_ID); + expect((e as AIError).message).equals( + `AI: The "appId" field is empty in the local` + + ` Firebase config. Firebase AI requires this field ` + + `to contain a valid app ID. (${AI_TYPE}/${AIErrorCode.NO_APP_ID})` + ); + } + }); + it('getLiveGenerativeModel gets a LiveGenerativeModel', () => { + const liveGenerativeModel = getLiveGenerativeModel(fakeAI, { + model: 'my-model' + }); + expect(liveGenerativeModel).to.be.an.instanceOf(LiveGenerativeModel); + expect(liveGenerativeModel.model).to.equal( + 'publishers/google/models/my-model' + ); + }); }); diff --git a/packages/ai/src/api.ts b/packages/ai/src/api.ts index e9264262145..af177f750d4 100644 --- a/packages/ai/src/api.ts +++ b/packages/ai/src/api.ts @@ -25,17 +25,25 @@ import { ImagenModelParams, ModelParams, RequestOptions, - AIErrorCode + AIErrorCode, + LiveModelParams } from './types'; import { AIError } from './errors'; -import { AIModel, GenerativeModel, ImagenModel } from './models'; +import { + AIModel, + GenerativeModel, + LiveGenerativeModel, + ImagenModel +} from './models'; import { encodeInstanceIdentifier } from './helpers'; import { GoogleAIBackend } from './backend'; +import { createWebSocketHandler } from './platform/websocket'; export { ChatSession } from './methods/chat-session'; +export { LiveSession } from './methods/live-session'; export * from './requests/schema-builder'; export { ImagenImageFormat } from './requests/imagen-image-format'; -export { AIModel, GenerativeModel, ImagenModel, AIError }; +export { AIModel, GenerativeModel, LiveGenerativeModel, ImagenModel, AIError }; export { Backend, VertexAIBackend, GoogleAIBackend } from './backend'; declare module '@firebase/component' { @@ -133,3 +141,29 @@ export function getImagenModel( } return new ImagenModel(ai, modelParams, requestOptions); } + +/** + * Returns a {@link LiveGenerativeModel} class for real-time, bidirectional communication. + * + * The Live API is only supported in modern browser windows and Node >= 22. + * + * @param ai - An {@link AI} instance. + * @param modelParams - Parameters to use when setting up a {@link LiveSession}. + * @throws If the `apiKey` or `projectId` fields are missing in your + * Firebase config. + * + * @beta + */ +export function getLiveGenerativeModel( + ai: AI, + modelParams: LiveModelParams +): LiveGenerativeModel { + if (!modelParams.model) { + throw new AIError( + AIErrorCode.NO_MODEL, + `Must provide a model name for getLiveGenerativeModel. Example: getLiveGenerativeModel(ai, { model: 'my-model-name' })` + ); + } + const webSocketHandler = createWebSocketHandler(); + return new LiveGenerativeModel(ai, modelParams, webSocketHandler); +} diff --git a/packages/ai/src/constants.ts b/packages/ai/src/constants.ts index cb54567735a..93b6a80871a 100644 --- a/packages/ai/src/constants.ts +++ b/packages/ai/src/constants.ts @@ -21,7 +21,7 @@ export const AI_TYPE = 'AI'; export const DEFAULT_LOCATION = 'us-central1'; -export const DEFAULT_BASE_URL = 'https://firebasevertexai.googleapis.com'; +export const DEFAULT_DOMAIN = 'firebasevertexai.googleapis.com'; export const DEFAULT_API_VERSION = 'v1beta'; diff --git a/packages/ai/src/methods/live-session.test.ts b/packages/ai/src/methods/live-session.test.ts new file mode 100644 index 00000000000..454c20402c2 --- /dev/null +++ b/packages/ai/src/methods/live-session.test.ts @@ -0,0 +1,294 @@ +/** + * @license + * 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. + */ + +import { expect, use } from 'chai'; +import { spy, stub } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import { + LiveResponseType, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation +} from '../types'; +import { LiveSession } from './live-session'; +import { WebSocketHandler } from '../platform/websocket'; +import { AIError } from '../errors'; +import { logger } from '../logger'; + +use(sinonChai); +use(chaiAsPromised); + +class MockWebSocketHandler implements WebSocketHandler { + connect = stub().resolves(); + send = spy(); + close = stub().resolves(); + + private messageQueue: unknown[] = []; + private streamClosed = false; + private listenerPromiseResolver: (() => void) | null = null; + + async *listen(): AsyncGenerator { + while (!this.streamClosed) { + if (this.messageQueue.length > 0) { + yield this.messageQueue.shift(); + } else { + // Wait until a new message is pushed or the stream is ended. + await new Promise(resolve => { + this.listenerPromiseResolver = resolve; + }); + } + } + } + + simulateServerMessage(message: object): void { + this.messageQueue.push(message); + if (this.listenerPromiseResolver) { + // listener is waiting for our message + this.listenerPromiseResolver(); + this.listenerPromiseResolver = null; + } + } + + endStream(): void { + this.streamClosed = true; + if (this.listenerPromiseResolver) { + this.listenerPromiseResolver(); + this.listenerPromiseResolver = null; + } + } +} + +describe('LiveSession', () => { + let mockHandler: MockWebSocketHandler; + let session: LiveSession; + let serverMessagesGenerator: AsyncGenerator; + + beforeEach(() => { + mockHandler = new MockWebSocketHandler(); + serverMessagesGenerator = mockHandler.listen(); + session = new LiveSession(mockHandler, serverMessagesGenerator); + }); + + describe('send()', () => { + it('should format and send a valid text message', async () => { + await session.send('Hello there'); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData).to.deep.equal({ + clientContent: { + turns: [{ role: 'user', parts: [{ text: 'Hello there' }] }], + turnComplete: true + } + }); + }); + + it('should format and send a message with an array of Parts', async () => { + const parts = [ + { text: 'Part 1' }, + { inlineData: { mimeType: 'image/png', data: 'base64==' } } + ]; + await session.send(parts); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData.clientContent.turns[0].parts).to.deep.equal(parts); + }); + }); + + describe('sendMediaChunks()', () => { + it('should send a correctly formatted realtimeInput message', async () => { + const chunks = [{ data: 'base64', mimeType: 'audio/webm' }]; + await session.sendMediaChunks(chunks); + expect(mockHandler.send).to.have.been.calledOnce; + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData).to.deep.equal({ + realtimeInput: { mediaChunks: chunks } + }); + }); + }); + + describe('sendMediaStream()', () => { + it('should send multiple chunks from a stream', async () => { + const stream = new ReadableStream({ + start(controller) { + controller.enqueue({ data: 'chunk1', mimeType: 'audio/webm' }); + controller.enqueue({ data: 'chunk2', mimeType: 'audio/webm' }); + controller.close(); + } + }); + + await session.sendMediaStream(stream); + + expect(mockHandler.send).to.have.been.calledTwice; + const firstCall = JSON.parse(mockHandler.send.getCall(0).args[0]); + const secondCall = JSON.parse(mockHandler.send.getCall(1).args[0]); + expect(firstCall.realtimeInput.mediaChunks[0].data).to.equal('chunk1'); + expect(secondCall.realtimeInput.mediaChunks[0].data).to.equal('chunk2'); + }); + + it('should re-throw an AIError if the stream reader throws', async () => { + const errorStream = new ReadableStream({ + pull(controller) { + controller.error(new Error('Stream failed!')); + } + }); + await expect(session.sendMediaStream(errorStream)).to.be.rejectedWith( + AIError, + /Stream failed!/ + ); + }); + }); + + describe('receive()', () => { + it('should correctly parse and transform all server message types', async () => { + const receivePromise = (async () => { + const responses = []; + for await (const response of session.receive()) { + responses.push(response); + } + return responses; + })(); + + mockHandler.simulateServerMessage({ + serverContent: { modelTurn: { parts: [{ text: 'response 1' }] } } + }); + mockHandler.simulateServerMessage({ + toolCall: { functionCalls: [{ name: 'test_func' }] } + }); + mockHandler.simulateServerMessage({ + toolCallCancellation: { functionIds: ['123'] } + }); + mockHandler.simulateServerMessage({ + serverContent: { turnComplete: true } + }); + await new Promise(r => setTimeout(() => r(), 10)); // Wait for the listener to process messages + mockHandler.endStream(); + + const responses = await receivePromise; + expect(responses).to.have.lengthOf(4); + expect(responses[0]).to.deep.equal({ + type: LiveResponseType.SERVER_CONTENT, + modelTurn: { parts: [{ text: 'response 1' }] } + } as LiveServerContent); + expect(responses[1]).to.deep.equal({ + type: LiveResponseType.TOOL_CALL, + functionCalls: [{ name: 'test_func' }] + } as LiveServerToolCall); + expect(responses[2]).to.deep.equal({ + type: LiveResponseType.TOOL_CALL_CANCELLATION, + functionIds: ['123'] + } as LiveServerToolCallCancellation); + }); + + it('should log a warning and skip messages that are not objects', async () => { + const loggerStub = stub(logger, 'warn'); + const receivePromise = (async () => { + const responses = []; + for await (const response of session.receive()) { + responses.push(response); + } + return responses; + })(); + + mockHandler.simulateServerMessage(null as any); + mockHandler.simulateServerMessage('not an object' as any); + await new Promise(r => setTimeout(() => r(), 10)); // Wait for the listener to process messages + mockHandler.endStream(); + + const responses = await receivePromise; + expect(responses).to.be.empty; + expect(loggerStub).to.have.been.calledTwice; + expect(loggerStub).to.have.been.calledWithMatch( + /Received an invalid message/ + ); + + loggerStub.restore(); + }); + + it('should log a warning and skip objects of unknown type', async () => { + const loggerStub = stub(logger, 'warn'); + const receivePromise = (async () => { + const responses = []; + for await (const response of session.receive()) { + responses.push(response); + } + return responses; + })(); + + mockHandler.simulateServerMessage({ unknownType: { data: 'test' } }); + await new Promise(r => setTimeout(() => r(), 10)); // Wait for the listener to process messages + mockHandler.endStream(); + + const responses = await receivePromise; + expect(responses).to.be.empty; + expect(loggerStub).to.have.been.calledOnce; + expect(loggerStub).to.have.been.calledWithMatch( + /Received an unknown message type/ + ); + + loggerStub.restore(); + }); + }); + + describe('close()', () => { + it('should call the handler, set the isClosed flag, and be idempotent', async () => { + expect(session.isClosed).to.be.false; + await session.close(); + expect(mockHandler.close).to.have.been.calledOnce; + expect(session.isClosed).to.be.true; + + // Call again to test idempotency + await session.close(); + expect(mockHandler.close).to.have.been.calledOnce; // Should not be called again + }); + + it('should terminate an active receive() loop', async () => { + const received: unknown[] = []; + const receivePromise = (async () => { + for await (const msg of session.receive()) { + received.push(msg); + } + })(); + + mockHandler.simulateServerMessage({ + serverContent: { modelTurn: { parts: [{ text: 'one' }] } } + }); + // Allow the first message to be processed + await new Promise(r => setTimeout(r, 10)); + expect(received).to.have.lengthOf(1); + + await session.close(); + mockHandler.endStream(); // End the mock stream + + await receivePromise; // This should now resolve + + // No more messages should have been processed + expect(received).to.have.lengthOf(1); + }); + + it('methods should throw after session is closed', async () => { + await session.close(); + await expect(session.send('test')).to.be.rejectedWith(AIError, /closed/); + await expect(session.sendMediaChunks([])).to.be.rejectedWith( + AIError, + /closed/ + ); + const generator = session.receive(); + await expect(generator.next()).to.be.rejectedWith(AIError, /closed/); + }); + }); +}); diff --git a/packages/ai/src/methods/live-session.ts b/packages/ai/src/methods/live-session.ts new file mode 100644 index 00000000000..40d35800737 --- /dev/null +++ b/packages/ai/src/methods/live-session.ts @@ -0,0 +1,228 @@ +/** + * @license + * 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. + */ + +import { + AIErrorCode, + GenerativeContentBlob, + LiveResponseType, + LiveServerContent, + LiveServerToolCall, + LiveServerToolCallCancellation, + Part +} from '../public-types'; +import { formatNewContent } from '../requests/request-helpers'; +import { AIError } from '../errors'; +import { WebSocketHandler } from '../platform/websocket'; +import { logger } from '../logger'; +import { + _LiveClientContent, + _LiveClientRealtimeInput +} from '../types/live-responses'; + +/** + * Represents an active, real-time, bidirectional conversation with the model. + * + * This class should only be instantiated by calling {@link LiveGenerativeModel.connect}. + * + * @beta + */ +export class LiveSession { + /** + * Indicates whether this Live session is closed. + * + * @beta + */ + isClosed = false; + + /** + * @internal + */ + constructor( + private webSocketHandler: WebSocketHandler, + private serverMessages: AsyncGenerator + ) {} + + /** + * Sends content to the server. + * + * @param request - The message to send to the model. + * @param turnComplete - Indicates if the turn is complete. Defaults to false. + * @throws If this session has been closed. + * + * @beta + */ + async send( + request: string | Array, + turnComplete = true + ): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } + + const newContent = formatNewContent(request); + + const message: _LiveClientContent = { + clientContent: { + turns: [newContent], + turnComplete + } + }; + this.webSocketHandler.send(JSON.stringify(message)); + } + + /** + * Sends realtime input to the server. + * + * @param mediaChunks - The media chunks to send. + * @throws If this session has been closed. + * + * @beta + */ + async sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } + + // The backend does not support sending more than one mediaChunk in one message. + // Work around this limitation by sending mediaChunks in separate messages. + mediaChunks.forEach(mediaChunk => { + const message: _LiveClientRealtimeInput = { + realtimeInput: { mediaChunks: [mediaChunk] } + }; + this.webSocketHandler.send(JSON.stringify(message)); + }); + } + + /** + * Sends a stream of {@link GenerativeContentBlob}. + * + * @param mediaChunkStream - The stream of {@link GenerativeContentBlob} to send. + * @throws If this session has been closed. + * + * @beta + */ + async sendMediaStream( + mediaChunkStream: ReadableStream + ): Promise { + if (this.isClosed) { + throw new AIError( + AIErrorCode.REQUEST_ERROR, + 'This LiveSession has been closed and cannot be used.' + ); + } + + const reader = mediaChunkStream.getReader(); + while (true) { + try { + const { done, value } = await reader.read(); + + if (done) { + break; + } else if (!value) { + throw new Error('Missing chunk in reader, but reader is not done.'); + } + + await this.sendMediaChunks([value]); + } catch (e) { + // Re-throw any errors that occur during stream consumption or sending. + const message = + e instanceof Error ? e.message : 'Error processing media stream.'; + throw new AIError(AIErrorCode.REQUEST_ERROR, message); + } + } + } + + /** + * Yields messages received from the server. + * This can only be used by one consumer at a time. + * + * @returns An `AsyncGenerator` that yields server messages as they arrive. + * @throws If the session is already closed, or if we receive a response that we don't support. + * + * @beta + */ + async *receive(): AsyncGenerator< + LiveServerContent | LiveServerToolCall | LiveServerToolCallCancellation + > { + if (this.isClosed) { + throw new AIError( + AIErrorCode.SESSION_CLOSED, + 'Cannot read from a Live session that is closed. Try starting a new Live session.' + ); + } + for await (const message of this.serverMessages) { + if (message && typeof message === 'object') { + if (LiveResponseType.SERVER_CONTENT in message) { + yield { + type: 'serverContent', + ...(message as { serverContent: Omit }) + .serverContent + } as LiveServerContent; + } else if (LiveResponseType.TOOL_CALL in message) { + yield { + type: 'toolCall', + ...(message as { toolCall: Omit }) + .toolCall + } as LiveServerToolCall; + } else if (LiveResponseType.TOOL_CALL_CANCELLATION in message) { + yield { + type: 'toolCallCancellation', + ...( + message as { + toolCallCancellation: Omit< + LiveServerToolCallCancellation, + 'type' + >; + } + ).toolCallCancellation + } as LiveServerToolCallCancellation; + } else { + logger.warn( + `Received an unknown message type from the server: ${JSON.stringify( + message + )}` + ); + } + } else { + logger.warn( + `Received an invalid message from the server: ${JSON.stringify( + message + )}` + ); + } + } + } + + /** + * Closes this session. + * All methods on this session will throw an error once this resolves. + * + * @beta + */ + async close(): Promise { + if (!this.isClosed) { + this.isClosed = true; + await this.webSocketHandler.close(1000, 'Client closed session.'); + } + } +} diff --git a/packages/ai/src/models/index.ts b/packages/ai/src/models/index.ts index cb694a5360b..5d2492d6784 100644 --- a/packages/ai/src/models/index.ts +++ b/packages/ai/src/models/index.ts @@ -17,4 +17,5 @@ export * from './ai-model'; export * from './generative-model'; +export * from './live-generative-model'; export * from './imagen-model'; diff --git a/packages/ai/src/models/live-generative-model.test.ts b/packages/ai/src/models/live-generative-model.test.ts new file mode 100644 index 00000000000..6278d5e182f --- /dev/null +++ b/packages/ai/src/models/live-generative-model.test.ts @@ -0,0 +1,171 @@ +/** + * @license + * 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. + */ +import { use, expect } from 'chai'; +import sinon, { SinonFakeTimers, stub } from 'sinon'; +import sinonChai from 'sinon-chai'; +import chaiAsPromised from 'chai-as-promised'; +import { AI } from '../public-types'; +import { LiveSession } from '../methods/live-session'; +import { WebSocketHandler } from '../platform/websocket'; +import { GoogleAIBackend } from '../backend'; +import { LiveGenerativeModel } from './live-generative-model'; +import { AIError } from '../errors'; + +use(sinonChai); +use(chaiAsPromised); + +// A controllable mock for the WebSocketHandler interface +class MockWebSocketHandler implements WebSocketHandler { + connect = stub().resolves(); + send = stub(); + close = stub().resolves(); + + private serverMessages: unknown[] = []; + private generatorController: { + resolve: () => void; + promise: Promise; + } | null = null; + + async *listen(): AsyncGenerator { + while (true) { + if (this.serverMessages.length > 0) { + yield this.serverMessages.shift(); + } else { + const promise = new Promise(resolve => { + this.generatorController = { resolve, promise: null! }; + }); + await promise; + } + } + } + + // Test method to simulate a message from the server + simulateServerMessage(message: object): void { + this.serverMessages.push(message); + if (this.generatorController) { + this.generatorController.resolve(); + this.generatorController = null; + } + } +} + +const fakeAI: AI = { + app: { + name: 'DEFAULT', + automaticDataCollectionEnabled: true, + options: { + apiKey: 'key', + projectId: 'my-project', + appId: 'my-appid' + } + }, + backend: new GoogleAIBackend(), + location: 'us-central1' +}; + +describe('LiveGenerativeModel', () => { + let mockHandler: MockWebSocketHandler; + let clock: SinonFakeTimers; + + beforeEach(() => { + mockHandler = new MockWebSocketHandler(); + clock = sinon.useFakeTimers(); + }); + + afterEach(() => { + sinon.restore(); + clock.restore(); + }); + + it('connect() should call handler.connect and send setup message', async () => { + const model = new LiveGenerativeModel( + fakeAI, + { model: 'my-model' }, + mockHandler + ); + const connectPromise = model.connect(); + + // Ensure connect was called before simulating server response + expect(mockHandler.connect).to.have.been.calledOnce; + + // Wait for the setup message to be sent + await clock.runAllAsync(); + + expect(mockHandler.send).to.have.been.calledOnce; + const setupMessage = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(setupMessage.setup.model).to.include('my-model'); + + // Simulate successful handshake and resolve the promise + mockHandler.simulateServerMessage({ setupComplete: true }); + const session = await connectPromise; + expect(session).to.be.an.instanceOf(LiveSession); + await session.close(); + }); + + it('connect() should throw if handshake fails', async () => { + const model = new LiveGenerativeModel( + fakeAI, + { model: 'my-model' }, + mockHandler + ); + const connectPromise = model.connect(); + + // Wait for setup message + await clock.runAllAsync(); + + // Simulate a failed handshake + mockHandler.simulateServerMessage({ error: 'handshake failed' }); + await expect(connectPromise).to.be.rejectedWith( + AIError, + /Server connection handshake failed/ + ); + }); + + it('connect() should pass through connection errors', async () => { + mockHandler.connect.rejects(new Error('Connection refused')); + const model = new LiveGenerativeModel( + fakeAI, + { model: 'my-model' }, + mockHandler + ); + await expect(model.connect()).to.be.rejectedWith('Connection refused'); + }); + + it('connect() should pass through setup parameters correctly', async () => { + const model = new LiveGenerativeModel( + fakeAI, + { + model: 'gemini-pro', + generationConfig: { temperature: 0.8 }, + systemInstruction: { role: 'system', parts: [{ text: 'Be a pirate' }] } + }, + mockHandler + ); + const connectPromise = model.connect(); + + // Wait for setup message + await clock.runAllAsync(); + + const sentData = JSON.parse(mockHandler.send.getCall(0).args[0]); + expect(sentData.setup.generationConfig).to.deep.equal({ temperature: 0.8 }); + expect(sentData.setup.systemInstruction.parts[0].text).to.equal( + 'Be a pirate' + ); + mockHandler.simulateServerMessage({ setupComplete: true }); + await connectPromise; + }); +}); diff --git a/packages/ai/src/models/live-generative-model.ts b/packages/ai/src/models/live-generative-model.ts new file mode 100644 index 00000000000..67d74bba95e --- /dev/null +++ b/packages/ai/src/models/live-generative-model.ts @@ -0,0 +1,125 @@ +/** + * @license + * 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. + */ + +import { AIModel } from './ai-model'; +import { LiveSession } from '../methods/live-session'; +import { AIError } from '../errors'; +import { + AI, + AIErrorCode, + BackendType, + Content, + LiveGenerationConfig, + LiveModelParams, + Tool, + ToolConfig +} from '../public-types'; +import { WebSocketHandler } from '../platform/websocket'; +import { WebSocketUrl } from '../requests/request'; +import { formatSystemInstruction } from '../requests/request-helpers'; +import { _LiveClientSetup } from '../types/live-responses'; + +/** + * Class for Live generative model APIs. The Live API enables low-latency, two-way multimodal + * interactions with Gemini. + * + * This class should only be instantiated with {@link getLiveGenerativeModel}. + * + * @beta + */ +export class LiveGenerativeModel extends AIModel { + generationConfig: LiveGenerationConfig; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: Content; + + /** + * @internal + */ + constructor( + ai: AI, + modelParams: LiveModelParams, + /** + * @internal + */ + private _webSocketHandler: WebSocketHandler + ) { + super(ai, modelParams.model); + this.generationConfig = modelParams.generationConfig || {}; + this.tools = modelParams.tools; + this.toolConfig = modelParams.toolConfig; + this.systemInstruction = formatSystemInstruction( + modelParams.systemInstruction + ); + } + + /** + * Starts a {@link LiveSession}. + * + * @returns A {@link LiveSession}. + * @throws If the connection failed to be established with the server. + * + * @beta + */ + async connect(): Promise { + const url = new WebSocketUrl(this._apiSettings); + await this._webSocketHandler.connect(url.toString()); + + let fullModelPath: string; + if (this._apiSettings.backend.backendType === BackendType.GOOGLE_AI) { + fullModelPath = `projects/${this._apiSettings.project}/${this.model}`; + } else { + fullModelPath = `projects/${this._apiSettings.project}/locations/${this._apiSettings.location}/${this.model}`; + } + + const setupMessage: _LiveClientSetup = { + setup: { + model: fullModelPath, + generationConfig: this.generationConfig, + tools: this.tools, + toolConfig: this.toolConfig, + systemInstruction: this.systemInstruction + } + }; + + try { + // Begin listening for server messages, and begin the handshake by sending the 'setupMessage' + const serverMessages = this._webSocketHandler.listen(); + this._webSocketHandler.send(JSON.stringify(setupMessage)); + + // Verify we received the handshake response 'setupComplete' + const firstMessage = (await serverMessages.next()).value; + if ( + !firstMessage || + !(typeof firstMessage === 'object') || + !('setupComplete' in firstMessage) + ) { + await this._webSocketHandler.close(1011, 'Handshake failure'); + throw new AIError( + AIErrorCode.RESPONSE_ERROR, + 'Server connection handshake failed. The server did not respond with a setupComplete message.' + ); + } + + return new LiveSession(this._webSocketHandler, serverMessages); + } catch (e) { + // Ensure connection is closed on any setup error + await this._webSocketHandler.close(); + throw e; + } + } +} diff --git a/packages/ai/src/platform/browser/websocket.test.ts b/packages/ai/src/platform/browser/websocket.test.ts index 5f211363576..07e35cd8299 100644 --- a/packages/ai/src/platform/browser/websocket.test.ts +++ b/packages/ai/src/platform/browser/websocket.test.ts @@ -134,7 +134,7 @@ describe('BrowserWebSocketHandler', () => { await expect(connectPromise).to.be.rejectedWith( AIError, - /Failed to establish WebSocket connection/ + /Error event raised on WebSocket/ ); }); }); diff --git a/packages/ai/src/platform/browser/websocket.ts b/packages/ai/src/platform/browser/websocket.ts index 16e5bd843a9..884bef776e6 100644 --- a/packages/ai/src/platform/browser/websocket.ts +++ b/packages/ai/src/platform/browser/websocket.ts @@ -16,6 +16,7 @@ */ import { AIError } from '../../errors'; +import { logger } from '../../logger'; import { AIErrorCode } from '../../types'; import { WebSocketHandler } from '../websocket'; @@ -51,11 +52,16 @@ export class BrowserWebSocketHandler implements WebSocketHandler { reject( new AIError( AIErrorCode.FETCH_ERROR, - 'Failed to establish WebSocket connection' + `Error event raised on WebSocket` ) ), { once: true } ); + this.ws!.addEventListener('close', (closeEvent: CloseEvent) => { + logger.warn( + `WebSocket connection closed by server. Reason: '${closeEvent.reason}'` + ); + }); }); } @@ -128,7 +134,12 @@ export class BrowserWebSocketHandler implements WebSocketHandler { } }; - const closeListener = (): void => { + const closeListener = (event: CloseEvent): void => { + if (event.reason) { + logger.warn( + `WebSocket connection closed by the server with reason: ${event.reason}` + ); + } isClosed = true; if (resolvePromise) { resolvePromise(); diff --git a/packages/ai/src/platform/node/websocket.ts b/packages/ai/src/platform/node/websocket.ts index 156ee988785..36a963953bf 100644 --- a/packages/ai/src/platform/node/websocket.ts +++ b/packages/ai/src/platform/node/websocket.ts @@ -16,6 +16,7 @@ */ import { AIError } from '../../errors'; +import { logger } from '../../logger'; import { AIErrorCode } from '../../types'; import { WebSocketHandler } from '../websocket'; @@ -62,13 +63,13 @@ export class NodeWebSocketHandler implements WebSocketHandler { this.ws = new WebSocket(url); this.ws.binaryType = 'blob'; this.ws!.addEventListener('open', () => resolve(), { once: true }); - this.ws!.addEventListener( + this.ws.addEventListener( 'error', () => reject( new AIError( AIErrorCode.FETCH_ERROR, - 'Failed to establish WebSocket connection' + `Error event raised on WebSocket` ) ), { once: true } @@ -145,7 +146,12 @@ export class NodeWebSocketHandler implements WebSocketHandler { } }; - const closeListener = (): void => { + const closeListener = (event: CloseEvent): void => { + if (event.reason) { + logger.warn( + `WebSocket connection closed by the server with reason: ${event.reason}` + ); + } isClosed = true; if (resolvePromise) { resolvePromise(); diff --git a/packages/ai/src/requests/request.ts b/packages/ai/src/requests/request.ts index 3fa0b33012f..90195b4b788 100644 --- a/packages/ai/src/requests/request.ts +++ b/packages/ai/src/requests/request.ts @@ -20,13 +20,14 @@ import { AIError } from '../errors'; import { ApiSettings } from '../types/internal'; import { DEFAULT_API_VERSION, - DEFAULT_BASE_URL, + DEFAULT_DOMAIN, DEFAULT_FETCH_TIMEOUT_MS, LANGUAGE_TAG, PACKAGE_VERSION } from '../constants'; import { logger } from '../logger'; import { GoogleAIBackend, VertexAIBackend } from '../backend'; +import { BackendType } from '../public-types'; export enum Task { GENERATE_CONTENT = 'generateContent', @@ -51,7 +52,7 @@ export class RequestUrl { } private get baseUrl(): string { - return this.requestOptions?.baseUrl || DEFAULT_BASE_URL; + return this.requestOptions?.baseUrl || `https://${DEFAULT_DOMAIN}`; } private get apiVersion(): string { @@ -81,6 +82,28 @@ export class RequestUrl { } } +export class WebSocketUrl { + constructor(public apiSettings: ApiSettings) {} + toString(): string { + const url = new URL(`wss://${DEFAULT_DOMAIN}`); + url.pathname = this.pathname; + + const queryParams = new URLSearchParams(); + queryParams.set('key', this.apiSettings.apiKey); + url.search = queryParams.toString(); + + return url.toString(); + } + + private get pathname(): string { + if (this.apiSettings.backend.backendType === BackendType.GOOGLE_AI) { + return 'ws/google.firebase.vertexai.v1beta.GenerativeService/BidiGenerateContent'; + } else { + return `ws/google.firebase.vertexai.v1beta.LlmBidiService/BidiGenerateContent/locations/${this.apiSettings.location}`; + } + } +} + /** * Log language and "fire/version" to x-goog-api-client */ diff --git a/packages/ai/src/types/content.ts b/packages/ai/src/types/content.ts index ad2906671e4..4dd65b6c1d7 100644 --- a/packages/ai/src/types/content.ts +++ b/packages/ai/src/types/content.ts @@ -122,6 +122,15 @@ export interface FileDataPart { * @public */ export interface FunctionCall { + /** + * The id of the function call. This must be sent back in the associated {@link FunctionResponse}. + * + * + * @remarks This property is only supported in the Gemini Developer API ({@link GoogleAIBackend}). + * When using the Gemini Developer API ({@link GoogleAIBackend}), this property will be + * `undefined`. + */ + id?: string; name: string; args: object; } @@ -136,6 +145,14 @@ export interface FunctionCall { * @public */ export interface FunctionResponse { + /** + * The id of the {@link FunctionCall}. + * + * @remarks This property is only supported in the Gemini Developer API ({@link GoogleAIBackend}). + * When using the Gemini Developer API ({@link GoogleAIBackend}), this property will be + * `undefined`. + */ + id?: string; name: string; response: object; } diff --git a/packages/ai/src/types/error.ts b/packages/ai/src/types/error.ts index d6ed22e047c..a230f683f37 100644 --- a/packages/ai/src/types/error.ts +++ b/packages/ai/src/types/error.ts @@ -75,6 +75,9 @@ export const AIErrorCode = { /** An error occurred while performing a fetch. */ FETCH_ERROR: 'fetch-error', + /** An error occurred because an operation was attempted on a closed session. */ + SESSION_CLOSED: 'session-closed', + /** An error associated with a Content object. */ INVALID_CONTENT: 'invalid-content', diff --git a/packages/ai/src/types/live-responses.ts b/packages/ai/src/types/live-responses.ts new file mode 100644 index 00000000000..66170f1a5ab --- /dev/null +++ b/packages/ai/src/types/live-responses.ts @@ -0,0 +1,59 @@ +/** + * @license + * 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. + */ + +import { Content, GenerativeContentBlob, Part } from './content'; +import { LiveGenerationConfig, Tool, ToolConfig } from './requests'; + +/** + * User input that is sent to the model. + * + * @internal + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export interface _LiveClientContent { + clientContent: { + turns: [Content]; + turnComplete: boolean; + }; +} + +/** + * User input that is sent to the model in real time. + * + * @internal + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export interface _LiveClientRealtimeInput { + realtimeInput: { + mediaChunks: GenerativeContentBlob[]; + }; +} +/** + * The first message in a Live session, used to configure generation options. + * + * @internal + */ +// eslint-disable-next-line @typescript-eslint/naming-convention +export interface _LiveClientSetup { + setup: { + model: string; + generationConfig?: LiveGenerationConfig; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: string | Part | Content; + }; +} diff --git a/packages/ai/src/types/requests.ts b/packages/ai/src/types/requests.ts index e68f3af161d..546ea63c058 100644 --- a/packages/ai/src/types/requests.ts +++ b/packages/ai/src/types/requests.ts @@ -46,6 +46,17 @@ export interface ModelParams extends BaseParams { systemInstruction?: string | Part | Content; } +/** + * Params passed to {@link getLiveGenerativeModel}. + * @beta + */ +export interface LiveModelParams { + model: string; + generationConfig?: LiveGenerationConfig; + tools?: Tool[]; + toolConfig?: ToolConfig; + systemInstruction?: string | Part | Content; +} /** * Request sent through {@link GenerativeModel.generateContent} * @public @@ -119,6 +130,62 @@ export interface GenerationConfig { thinkingConfig?: ThinkingConfig; } +/** + * Configuration parameters used by {@link LiveGenerativeModel} to control live content generation. + * + * @beta + */ +export interface LiveGenerationConfig { + /** + * Configuration for speech synthesis. + */ + speechConfig?: SpeechConfig; + /** + * The maximum number of generated response messages to return. This value must be between + * 1 and 8. If unset, this will default to 1. + */ + candidateCount?: number; + /** + * Specifies the maximum number of tokens that can be generated in the response. The number of + * tokens per word varies depending on the language outputted. Defaults to 0. + */ + maxOutputTokens?: number; + /** + * Controls the degree of randomness in token selection. A `temperature` value of 0 means that the highest + * probability tokens are always selected. In this case, responses for a given prompt are mostly + * deterministic, but a small amount of variation is still possible. + */ + temperature?: number; + /** + * Changes how the model selects tokens for output. Tokens are + * selected from the most to least probable until the sum of their probabilities equals the `topP` + * value. For example, if tokens A, B, and C have probabilities of 0.3, 0.2, and 0.1 respectively + * and the `topP` value is 0.5, then the model will select either A or B as the next token by using + * the `temperature` and exclude C as a candidate. Defaults to 0.95 if unset. + */ + topP?: number; + /** + * Changes how the model selects token for output. A `topK` value of 1 means the select token is + * the most probable among all tokens in the model's vocabulary, while a `topK` value 3 means that + * the next token is selected from among the 3 most probably using probabilities sampled. Tokens + * are then further filtered with the highest selected `temperature` sampling. Defaults to 40 + * if unspecified. + */ + topK?: number; + /** + * Positive penalties. + */ + presencePenalty?: number; + /** + * Frequency penalties. + */ + frequencyPenalty?: number; + /** + * The modalities of the response. + */ + responseModalities?: [ResponseModality]; +} + /** * Params for {@link GenerativeModel.startChat}. * @public @@ -295,3 +362,42 @@ export interface ThinkingConfig { */ thinkingBudget?: number; } + +/** + * Configuration for a pre-built voice. + * + * @beta + */ +export interface PrebuiltVoiceConfig { + /** + * The voice name to use for speech synthesis. + * + * See https://cloud.google.com/text-to-speech/docs/chirp3-hd for names and + * sound demos. + */ + voiceConfig?: string; +} + +/** + * Configuration for the voice to used in speech synthesis. + * + * @beta + */ +export interface VoiceConfig { + /** + * Configures the voice using a pre-built voice configuration. + */ + prebuiltVoiceConfig?: PrebuiltVoiceConfig; +} + +/** + * Configures speech synthesis. + * + * @beta + */ +export interface SpeechConfig { + /** + * Configures the voice to be used in speech synthesis. + */ + voiceConfig?: VoiceConfig; +} diff --git a/packages/ai/src/types/responses.ts b/packages/ai/src/types/responses.ts index 323699e646b..e0bf04116d6 100644 --- a/packages/ai/src/types/responses.ts +++ b/packages/ai/src/types/responses.ts @@ -408,3 +408,73 @@ export interface CountTokensResponse { */ promptTokensDetails?: ModalityTokenCount[]; } + +/** + * An incremental content update from the model. + * + * @beta + */ +export interface LiveServerContent { + type: 'serverContent'; + /** + * The content that the model has generated as part of the current conversation with the user. + */ + modelTurn?: Content; + /** + * Indicates whether the turn is complete. This is `undefined` if the turn is not complete. + */ + turnComplete?: boolean; + /** + * Indicates whether the model was interrupted by the client. An interruption occurs when + * the client sends a message before the model finishes it's turn. This is `undefined` if the + * model was not interrupted. + */ + interrupted?: boolean; +} + +/** + * A request from the model for the client to execute one or more functions. + * + * @beta + */ +export interface LiveServerToolCall { + type: 'toolCall'; + /** + * An array of function calls to run. + */ + functionCalls: FunctionCall[]; +} + +/** + * Notification to cancel a previous function call triggered by {@link LiveServerToolCall}. + * + * @beta + */ +export interface LiveServerToolCallCancellation { + type: 'toolCallCancellation'; + /** + * IDs of function calls that were cancelled. These refer to the `id` property of a {@link FunctionCall}. + */ + functionIds: string[]; +} + +/** + * The types of responses that can be returned by {@link LiveSession.receive}. + * + * @beta + */ +export const LiveResponseType = { + SERVER_CONTENT: 'serverContent', + TOOL_CALL: 'toolCall', + TOOL_CALL_CANCELLATION: 'toolCallCancellation' +}; + +/** + * The types of responses that can be returned by {@link LiveSession.receive}. + * This is a property on all messages that can be used for type narrowing. This property is not + * returned by the server, it is assigned to a server message object once it's parsed. + * + * @beta + */ +export type LiveResponseType = + (typeof LiveResponseType)[keyof typeof LiveResponseType];