@firebase/ai 2.3.0-canary.0ffcb26af → 2.3.0-canary.2596dd1b5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/ai-public.d.ts +37 -28
  2. package/dist/ai.d.ts +37 -28
  3. package/dist/esm/index.esm.js +55 -32
  4. package/dist/esm/index.esm.js.map +1 -1
  5. package/dist/esm/src/api.d.ts +1 -1
  6. package/dist/esm/src/methods/live-session-helpers.d.ts +2 -2
  7. package/dist/esm/src/methods/live-session.d.ts +10 -1
  8. package/dist/esm/src/models/imagen-model.d.ts +2 -2
  9. package/dist/esm/src/requests/imagen-image-format.d.ts +3 -3
  10. package/dist/esm/src/types/content.d.ts +4 -4
  11. package/dist/esm/src/types/enums.d.ts +4 -4
  12. package/dist/esm/src/types/imagen/requests.d.ts +9 -9
  13. package/dist/esm/src/types/imagen/responses.d.ts +3 -3
  14. package/dist/esm/src/types/live-responses.d.ts +9 -1
  15. package/dist/esm/src/types/requests.d.ts +1 -1
  16. package/dist/index.cjs.js +55 -32
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.node.cjs.js +55 -32
  19. package/dist/index.node.cjs.js.map +1 -1
  20. package/dist/index.node.mjs +55 -32
  21. package/dist/index.node.mjs.map +1 -1
  22. package/dist/src/api.d.ts +1 -1
  23. package/dist/src/methods/live-session-helpers.d.ts +2 -2
  24. package/dist/src/methods/live-session.d.ts +10 -1
  25. package/dist/src/models/imagen-model.d.ts +2 -2
  26. package/dist/src/requests/imagen-image-format.d.ts +3 -3
  27. package/dist/src/types/content.d.ts +4 -4
  28. package/dist/src/types/enums.d.ts +4 -4
  29. package/dist/src/types/imagen/requests.d.ts +9 -9
  30. package/dist/src/types/imagen/responses.d.ts +3 -3
  31. package/dist/src/types/live-responses.d.ts +9 -1
  32. package/dist/src/types/requests.d.ts +1 -1
  33. package/package.json +8 -8
@@ -81,7 +81,7 @@ export declare function getGenerativeModel(ai: AI, modelParams: ModelParams | Hy
81
81
  * @throws If the `apiKey` or `projectId` fields are missing in your
82
82
  * Firebase config.
83
83
  *
84
- * @beta
84
+ * @public
85
85
  */
86
86
  export declare function getImagenModel(ai: AI, modelParams: ImagenModelParams, requestOptions?: RequestOptions): ImagenModel;
87
87
  /**
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { LiveServerToolCall, Part } from '../types';
17
+ import { FunctionCall, FunctionResponse } from '../types';
18
18
  import { LiveSession } from './live-session';
19
19
  /**
20
20
  * A controller for managing an active audio conversation.
@@ -39,7 +39,7 @@ export interface StartAudioConversationOptions {
39
39
  * The handler should perform the function call and return the result as a `Part`,
40
40
  * which will then be sent back to the model.
41
41
  */
42
- functionCallingHandler?: (functionCalls: LiveServerToolCall['functionCalls']) => Promise<Part>;
42
+ functionCallingHandler?: (functionCalls: FunctionCall[]) => Promise<FunctionResponse>;
43
43
  }
44
44
  /**
45
45
  * Dependencies needed by the {@link AudioConversationRunner}.
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { GenerativeContentBlob, LiveServerContent, LiveServerToolCall, LiveServerToolCallCancellation, Part } from '../public-types';
17
+ import { FunctionResponse, GenerativeContentBlob, LiveServerContent, LiveServerToolCall, LiveServerToolCallCancellation, Part } from '../public-types';
18
18
  import { WebSocketHandler } from '../websocket';
19
19
  /**
20
20
  * Represents an active, real-time, bidirectional conversation with the model.
@@ -61,6 +61,15 @@ export declare class LiveSession {
61
61
  * @beta
62
62
  */
63
63
  sendMediaChunks(mediaChunks: GenerativeContentBlob[]): Promise<void>;
64
+ /**
65
+ * Sends function responses to the server.
66
+ *
67
+ * @param functionResponses - The function responses to send.
68
+ * @throws If this session has been closed.
69
+ *
70
+ * @beta
71
+ */
72
+ sendFunctionResponses(functionResponses: FunctionResponse[]): Promise<void>;
64
73
  /**
65
74
  * Sends a stream of {@link GenerativeContentBlob}.
66
75
  *
@@ -37,7 +37,7 @@ import { AIModel } from './ai-model';
37
37
  * }
38
38
  * ```
39
39
  *
40
- * @beta
40
+ * @public
41
41
  */
42
42
  export declare class ImagenModel extends AIModel {
43
43
  requestOptions?: RequestOptions | undefined;
@@ -76,7 +76,7 @@ export declare class ImagenModel extends AIModel {
76
76
  * returned object will have a `filteredReason` property.
77
77
  * If all images are filtered, the `images` array will be empty.
78
78
  *
79
- * @beta
79
+ * @public
80
80
  */
81
81
  generateImages(prompt: string): Promise<ImagenGenerationResponse<ImagenInlineImage>>;
82
82
  /**
@@ -29,7 +29,7 @@
29
29
  * }
30
30
  * ```
31
31
  *
32
- * @beta
32
+ * @public
33
33
  */
34
34
  export declare class ImagenImageFormat {
35
35
  /**
@@ -47,7 +47,7 @@ export declare class ImagenImageFormat {
47
47
  * @param compressionQuality - The level of compression (a number between 0 and 100).
48
48
  * @returns An {@link ImagenImageFormat} object for a JPEG image.
49
49
  *
50
- * @beta
50
+ * @public
51
51
  */
52
52
  static jpeg(compressionQuality?: number): ImagenImageFormat;
53
53
  /**
@@ -55,7 +55,7 @@ export declare class ImagenImageFormat {
55
55
  *
56
56
  * @returns An {@link ImagenImageFormat} object for a PNG image.
57
57
  *
58
- * @beta
58
+ * @public
59
59
  */
60
60
  static png(): ImagenImageFormat;
61
61
  }
@@ -138,7 +138,7 @@ export interface FileDataPart {
138
138
  /**
139
139
  * Represents the code that is executed by the model.
140
140
  *
141
- * @public
141
+ * @beta
142
142
  */
143
143
  export interface ExecutableCodePart {
144
144
  text?: never;
@@ -157,7 +157,7 @@ export interface ExecutableCodePart {
157
157
  /**
158
158
  * Represents the code execution result from the model.
159
159
  *
160
- * @public
160
+ * @beta
161
161
  */
162
162
  export interface CodeExecutionResultPart {
163
163
  text?: never;
@@ -176,7 +176,7 @@ export interface CodeExecutionResultPart {
176
176
  /**
177
177
  * An interface for executable code returned by the model.
178
178
  *
179
- * @public
179
+ * @beta
180
180
  */
181
181
  export interface ExecutableCode {
182
182
  /**
@@ -191,7 +191,7 @@ export interface ExecutableCode {
191
191
  /**
192
192
  * The results of code execution run by the model.
193
193
  *
194
- * @public
194
+ * @beta
195
195
  */
196
196
  export interface CodeExecutionResult {
197
197
  /**
@@ -352,7 +352,7 @@ export type InferenceMode = (typeof InferenceMode)[keyof typeof InferenceMode];
352
352
  /**
353
353
  * Represents the result of the code execution.
354
354
  *
355
- * @public
355
+ * @beta
356
356
  */
357
357
  export declare const Outcome: {
358
358
  UNSPECIFIED: string;
@@ -363,13 +363,13 @@ export declare const Outcome: {
363
363
  /**
364
364
  * Represents the result of the code execution.
365
365
  *
366
- * @public
366
+ * @beta
367
367
  */
368
368
  export type Outcome = (typeof Outcome)[keyof typeof Outcome];
369
369
  /**
370
370
  * The programming language of the code.
371
371
  *
372
- * @public
372
+ * @beta
373
373
  */
374
374
  export declare const Language: {
375
375
  UNSPECIFIED: string;
@@ -378,6 +378,6 @@ export declare const Language: {
378
378
  /**
379
379
  * The programming language of the code.
380
380
  *
381
- * @public
381
+ * @beta
382
382
  */
383
383
  export type Language = (typeof Language)[keyof typeof Language];
@@ -18,7 +18,7 @@ import { ImagenImageFormat } from '../../requests/imagen-image-format';
18
18
  /**
19
19
  * Parameters for configuring an {@link ImagenModel}.
20
20
  *
21
- * @beta
21
+ * @public
22
22
  */
23
23
  export interface ImagenModelParams {
24
24
  /**
@@ -46,7 +46,7 @@ export interface ImagenModelParams {
46
46
  * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images-imagen | documentation} for
47
47
  * more details.
48
48
  *
49
- * @beta
49
+ * @public
50
50
  */
51
51
  export interface ImagenGenerationConfig {
52
52
  /**
@@ -104,7 +104,7 @@ export interface ImagenGenerationConfig {
104
104
  * and the {@link https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters | Responsible AI and usage guidelines}
105
105
  * for more details.
106
106
  *
107
- * @beta
107
+ * @public
108
108
  */
109
109
  export declare const ImagenSafetyFilterLevel: {
110
110
  /**
@@ -137,7 +137,7 @@ export declare const ImagenSafetyFilterLevel: {
137
137
  * and the {@link https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters | Responsible AI and usage guidelines}
138
138
  * for more details.
139
139
  *
140
- * @beta
140
+ * @public
141
141
  */
142
142
  export type ImagenSafetyFilterLevel = (typeof ImagenSafetyFilterLevel)[keyof typeof ImagenSafetyFilterLevel];
143
143
  /**
@@ -146,7 +146,7 @@ export type ImagenSafetyFilterLevel = (typeof ImagenSafetyFilterLevel)[keyof typ
146
146
  * See the <a href="http://firebase.google.com/docs/vertex-ai/generate-images">personGeneration</a>
147
147
  * documentation for more details.
148
148
  *
149
- * @beta
149
+ * @public
150
150
  */
151
151
  export declare const ImagenPersonFilterLevel: {
152
152
  /**
@@ -176,7 +176,7 @@ export declare const ImagenPersonFilterLevel: {
176
176
  * See the <a href="http://firebase.google.com/docs/vertex-ai/generate-images">personGeneration</a>
177
177
  * documentation for more details.
178
178
  *
179
- * @beta
179
+ * @public
180
180
  */
181
181
  export type ImagenPersonFilterLevel = (typeof ImagenPersonFilterLevel)[keyof typeof ImagenPersonFilterLevel];
182
182
  /**
@@ -185,7 +185,7 @@ export type ImagenPersonFilterLevel = (typeof ImagenPersonFilterLevel)[keyof typ
185
185
  * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation }
186
186
  * for more details.
187
187
  *
188
- * @beta
188
+ * @public
189
189
  */
190
190
  export interface ImagenSafetySettings {
191
191
  /**
@@ -207,7 +207,7 @@ export interface ImagenSafetySettings {
207
207
  * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation }
208
208
  * for more details and examples of the supported aspect ratios.
209
209
  *
210
- * @beta
210
+ * @public
211
211
  */
212
212
  export declare const ImagenAspectRatio: {
213
213
  /**
@@ -240,6 +240,6 @@ export declare const ImagenAspectRatio: {
240
240
  * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation }
241
241
  * for more details and examples of the supported aspect ratios.
242
242
  *
243
- * @beta
243
+ * @public
244
244
  */
245
245
  export type ImagenAspectRatio = (typeof ImagenAspectRatio)[keyof typeof ImagenAspectRatio];
@@ -17,7 +17,7 @@
17
17
  /**
18
18
  * An image generated by Imagen, represented as inline data.
19
19
  *
20
- * @beta
20
+ * @public
21
21
  */
22
22
  export interface ImagenInlineImage {
23
23
  /**
@@ -35,7 +35,7 @@ export interface ImagenInlineImage {
35
35
  * An image generated by Imagen, stored in a Cloud Storage for Firebase bucket.
36
36
  *
37
37
  * This feature is not available yet.
38
- * @beta
38
+ * @public
39
39
  */
40
40
  export interface ImagenGCSImage {
41
41
  /**
@@ -54,7 +54,7 @@ export interface ImagenGCSImage {
54
54
  /**
55
55
  * The response from a request to generate images with Imagen.
56
56
  *
57
- * @beta
57
+ * @public
58
58
  */
59
59
  export interface ImagenGenerationResponse<T extends ImagenInlineImage | ImagenGCSImage> {
60
60
  /**
@@ -14,7 +14,7 @@
14
14
  * See the License for the specific language governing permissions and
15
15
  * limitations under the License.
16
16
  */
17
- import { Content, GenerativeContentBlob, Part } from './content';
17
+ import { Content, FunctionResponse, GenerativeContentBlob, Part } from './content';
18
18
  import { LiveGenerationConfig, Tool, ToolConfig } from './requests';
19
19
  /**
20
20
  * User input that is sent to the model.
@@ -37,6 +37,14 @@ export interface _LiveClientRealtimeInput {
37
37
  mediaChunks: GenerativeContentBlob[];
38
38
  };
39
39
  }
40
+ /**
41
+ * Function responses that are sent to the model in real time.
42
+ */
43
+ export interface _LiveClientToolResponse {
44
+ toolResponse: {
45
+ functionResponses: FunctionResponse[];
46
+ };
47
+ }
40
48
  /**
41
49
  * The first message in a Live session, used to configure generation options.
42
50
  *
@@ -273,7 +273,7 @@ export interface GoogleSearchTool {
273
273
  /**
274
274
  * A tool that enables the model to use code execution.
275
275
  *
276
- * @public
276
+ * @beta
277
277
  */
278
278
  export interface CodeExecutionTool {
279
279
  /**
package/dist/index.cjs.js CHANGED
@@ -8,7 +8,7 @@ var util = require('@firebase/util');
8
8
  var logger$1 = require('@firebase/logger');
9
9
 
10
10
  var name = "@firebase/ai";
11
- var version = "2.3.0-canary.0ffcb26af";
11
+ var version = "2.3.0-canary.2596dd1b5";
12
12
 
13
13
  /**
14
14
  * @license
@@ -386,7 +386,7 @@ const InferenceMode = {
386
386
  /**
387
387
  * Represents the result of the code execution.
388
388
  *
389
- * @public
389
+ * @beta
390
390
  */
391
391
  const Outcome = {
392
392
  UNSPECIFIED: 'OUTCOME_UNSPECIFIED',
@@ -397,7 +397,7 @@ const Outcome = {
397
397
  /**
398
398
  * The programming language of the code.
399
399
  *
400
- * @public
400
+ * @beta
401
401
  */
402
402
  const Language = {
403
403
  UNSPECIFIED: 'LANGUAGE_UNSPECIFIED',
@@ -585,7 +585,7 @@ const SchemaType = {
585
585
  * and the {@link https://cloud.google.com/vertex-ai/generative-ai/docs/image/responsible-ai-imagen#safety-filters | Responsible AI and usage guidelines}
586
586
  * for more details.
587
587
  *
588
- * @beta
588
+ * @public
589
589
  */
590
590
  const ImagenSafetyFilterLevel = {
591
591
  /**
@@ -614,7 +614,7 @@ const ImagenSafetyFilterLevel = {
614
614
  * See the <a href="http://firebase.google.com/docs/vertex-ai/generate-images">personGeneration</a>
615
615
  * documentation for more details.
616
616
  *
617
- * @beta
617
+ * @public
618
618
  */
619
619
  const ImagenPersonFilterLevel = {
620
620
  /**
@@ -647,7 +647,7 @@ const ImagenPersonFilterLevel = {
647
647
  * See the {@link http://firebase.google.com/docs/vertex-ai/generate-images | documentation }
648
648
  * for more details and examples of the supported aspect ratios.
649
649
  *
650
- * @beta
650
+ * @public
651
651
  */
652
652
  const ImagenAspectRatio = {
653
653
  /**
@@ -1919,7 +1919,7 @@ function mapGenerateContentCandidates(candidates) {
1919
1919
  // videoMetadata is not supported.
1920
1920
  // Throw early since developers may send a long video as input and only expect to pay
1921
1921
  // for inference on a small portion of the video.
1922
- if (candidate.content?.parts.some(part => part?.videoMetadata)) {
1922
+ if (candidate.content?.parts?.some(part => part?.videoMetadata)) {
1923
1923
  throw new AIError(AIErrorCode.UNSUPPORTED, 'Part.videoMetadata is not supported in the Gemini Developer API. Please remove this property.');
1924
1924
  }
1925
1925
  const mappedCandidate = {
@@ -2021,6 +2021,14 @@ async function* generateResponseSequence(stream, apiSettings) {
2021
2021
  else {
2022
2022
  enhancedResponse = createEnhancedContentResponse(value);
2023
2023
  }
2024
+ const firstCandidate = enhancedResponse.candidates?.[0];
2025
+ // Don't yield a response with no useful data for the developer.
2026
+ if (!firstCandidate?.content?.parts &&
2027
+ !firstCandidate?.finishReason &&
2028
+ !firstCandidate?.citationMetadata &&
2029
+ !firstCandidate?.urlContextMetadata) {
2030
+ continue;
2031
+ }
2024
2032
  yield enhancedResponse;
2025
2033
  }
2026
2034
  }
@@ -2115,32 +2123,28 @@ function aggregateResponses(responses) {
2115
2123
  * Candidates should always have content and parts, but this handles
2116
2124
  * possible malformed responses.
2117
2125
  */
2118
- if (candidate.content && candidate.content.parts) {
2126
+ if (candidate.content) {
2127
+ // Skip a candidate without parts.
2128
+ if (!candidate.content.parts) {
2129
+ continue;
2130
+ }
2119
2131
  if (!aggregatedResponse.candidates[i].content) {
2120
2132
  aggregatedResponse.candidates[i].content = {
2121
2133
  role: candidate.content.role || 'user',
2122
2134
  parts: []
2123
2135
  };
2124
2136
  }
2125
- const newPart = {};
2126
2137
  for (const part of candidate.content.parts) {
2127
- if (part.text !== undefined) {
2128
- // The backend can send empty text parts. If these are sent back
2129
- // (e.g. in chat history), the backend will respond with an error.
2130
- // To prevent this, ignore empty text parts.
2131
- if (part.text === '') {
2132
- continue;
2133
- }
2134
- newPart.text = part.text;
2138
+ const newPart = { ...part };
2139
+ // The backend can send empty text parts. If these are sent back
2140
+ // (e.g. in chat history), the backend will respond with an error.
2141
+ // To prevent this, ignore empty text parts.
2142
+ if (part.text === '') {
2143
+ continue;
2135
2144
  }
2136
- if (part.functionCall) {
2137
- newPart.functionCall = part.functionCall;
2145
+ if (Object.keys(newPart).length > 0) {
2146
+ aggregatedResponse.candidates[i].content.parts.push(newPart);
2138
2147
  }
2139
- if (Object.keys(newPart).length === 0) {
2140
- throw new AIError(AIErrorCode.INVALID_CONTENT, 'Part should have at least one property, but there are none. This is likely caused ' +
2141
- 'by a malformed response from the backend.');
2142
- }
2143
- aggregatedResponse.candidates[i].content.parts.push(newPart);
2144
2148
  }
2145
2149
  }
2146
2150
  }
@@ -2846,6 +2850,25 @@ class LiveSession {
2846
2850
  this.webSocketHandler.send(JSON.stringify(message));
2847
2851
  });
2848
2852
  }
2853
+ /**
2854
+ * Sends function responses to the server.
2855
+ *
2856
+ * @param functionResponses - The function responses to send.
2857
+ * @throws If this session has been closed.
2858
+ *
2859
+ * @beta
2860
+ */
2861
+ async sendFunctionResponses(functionResponses) {
2862
+ if (this.isClosed) {
2863
+ throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
2864
+ }
2865
+ const message = {
2866
+ toolResponse: {
2867
+ functionResponses
2868
+ }
2869
+ };
2870
+ this.webSocketHandler.send(JSON.stringify(message));
2871
+ }
2849
2872
  /**
2850
2873
  * Sends a stream of {@link GenerativeContentBlob}.
2851
2874
  *
@@ -3060,7 +3083,7 @@ class LiveGenerativeModel extends AIModel {
3060
3083
  * }
3061
3084
  * ```
3062
3085
  *
3063
- * @beta
3086
+ * @public
3064
3087
  */
3065
3088
  class ImagenModel extends AIModel {
3066
3089
  /**
@@ -3096,7 +3119,7 @@ class ImagenModel extends AIModel {
3096
3119
  * returned object will have a `filteredReason` property.
3097
3120
  * If all images are filtered, the `images` array will be empty.
3098
3121
  *
3099
- * @beta
3122
+ * @public
3100
3123
  */
3101
3124
  async generateImages(prompt) {
3102
3125
  const body = createPredictRequestBody(prompt, {
@@ -3559,7 +3582,7 @@ class AnyOfSchema extends Schema {
3559
3582
  * }
3560
3583
  * ```
3561
3584
  *
3562
- * @beta
3585
+ * @public
3563
3586
  */
3564
3587
  class ImagenImageFormat {
3565
3588
  constructor() {
@@ -3571,7 +3594,7 @@ class ImagenImageFormat {
3571
3594
  * @param compressionQuality - The level of compression (a number between 0 and 100).
3572
3595
  * @returns An {@link ImagenImageFormat} object for a JPEG image.
3573
3596
  *
3574
- * @beta
3597
+ * @public
3575
3598
  */
3576
3599
  static jpeg(compressionQuality) {
3577
3600
  if (compressionQuality &&
@@ -3585,7 +3608,7 @@ class ImagenImageFormat {
3585
3608
  *
3586
3609
  * @returns An {@link ImagenImageFormat} object for a PNG image.
3587
3610
  *
3588
- * @beta
3611
+ * @public
3589
3612
  */
3590
3613
  static png() {
3591
3614
  return { mimeType: 'image/png' };
@@ -3827,9 +3850,9 @@ class AudioConversationRunner {
3827
3850
  }
3828
3851
  else {
3829
3852
  try {
3830
- const resultPart = await this.options.functionCallingHandler(message.functionCalls);
3853
+ const functionResponse = await this.options.functionCallingHandler(message.functionCalls);
3831
3854
  if (!this.isStopped) {
3832
- void this.liveSession.send([resultPart]);
3855
+ void this.liveSession.sendFunctionResponses([functionResponse]);
3833
3856
  }
3834
3857
  }
3835
3858
  catch (e) {
@@ -4049,7 +4072,7 @@ function getGenerativeModel(ai, modelParams, requestOptions) {
4049
4072
  * @throws If the `apiKey` or `projectId` fields are missing in your
4050
4073
  * Firebase config.
4051
4074
  *
4052
- * @beta
4075
+ * @public
4053
4076
  */
4054
4077
  function getImagenModel(ai, modelParams, requestOptions) {
4055
4078
  if (!modelParams.model) {