@firebase/ai 1.4.1-canary.f11b55294 → 1.4.1-canary.f18b25f73

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.
package/dist/index.cjs.js CHANGED
@@ -6,10 +6,9 @@ var app = require('@firebase/app');
6
6
  var component = require('@firebase/component');
7
7
  var util = require('@firebase/util');
8
8
  var logger$1 = require('@firebase/logger');
9
- var tslib = require('tslib');
10
9
 
11
10
  var name = "@firebase/ai";
12
- var version = "1.4.1-canary.f11b55294";
11
+ var version = "1.4.1-canary.f18b25f73";
13
12
 
14
13
  /**
15
14
  * @license
@@ -630,8 +629,8 @@ class AIService {
630
629
  constructor(app, backend, authProvider, appCheckProvider) {
631
630
  this.app = app;
632
631
  this.backend = backend;
633
- const appCheck = appCheckProvider === null || appCheckProvider === void 0 ? void 0 : appCheckProvider.getImmediate({ optional: true });
634
- const auth = authProvider === null || authProvider === void 0 ? void 0 : authProvider.getImmediate({ optional: true });
632
+ const appCheck = appCheckProvider?.getImmediate({ optional: true });
633
+ const auth = authProvider?.getImmediate({ optional: true });
635
634
  this.auth = auth || null;
636
635
  this.appCheck = appCheck || null;
637
636
  if (backend instanceof VertexAIBackend) {
@@ -803,14 +802,13 @@ class AIModel {
803
802
  * @internal
804
803
  */
805
804
  constructor(ai, modelName) {
806
- var _a, _b, _c, _d, _e, _f;
807
- if (!((_b = (_a = ai.app) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.apiKey)) {
805
+ if (!ai.app?.options?.apiKey) {
808
806
  throw new AIError(AIErrorCode.NO_API_KEY, `The "apiKey" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid API key.`);
809
807
  }
810
- else if (!((_d = (_c = ai.app) === null || _c === void 0 ? void 0 : _c.options) === null || _d === void 0 ? void 0 : _d.projectId)) {
808
+ else if (!ai.app?.options?.projectId) {
811
809
  throw new AIError(AIErrorCode.NO_PROJECT_ID, `The "projectId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid project ID.`);
812
810
  }
813
- else if (!((_f = (_e = ai.app) === null || _e === void 0 ? void 0 : _e.options) === null || _f === void 0 ? void 0 : _f.appId)) {
811
+ else if (!ai.app?.options?.appId) {
814
812
  throw new AIError(AIErrorCode.NO_APP_ID, `The "appId" field is empty in the local Firebase config. Firebase AI requires this field to contain a valid app ID.`);
815
813
  }
816
814
  else {
@@ -938,8 +936,7 @@ class RequestUrl {
938
936
  return url.toString();
939
937
  }
940
938
  get baseUrl() {
941
- var _a;
942
- return ((_a = this.requestOptions) === null || _a === void 0 ? void 0 : _a.baseUrl) || DEFAULT_BASE_URL;
939
+ return this.requestOptions?.baseUrl || DEFAULT_BASE_URL;
943
940
  }
944
941
  get apiVersion() {
945
942
  return DEFAULT_API_VERSION; // TODO: allow user-set options if that feature becomes available
@@ -1015,7 +1012,7 @@ async function makeRequest(model, task, apiSettings, stream, body, requestOption
1015
1012
  try {
1016
1013
  const request = await constructRequest(model, task, apiSettings, stream, body, requestOptions);
1017
1014
  // Timeout is 180s by default
1018
- const timeoutMillis = (requestOptions === null || requestOptions === void 0 ? void 0 : requestOptions.timeout) != null && requestOptions.timeout >= 0
1015
+ const timeoutMillis = requestOptions?.timeout != null && requestOptions.timeout >= 0
1019
1016
  ? requestOptions.timeout
1020
1017
  : DEFAULT_FETCH_TIMEOUT_MS;
1021
1018
  const abortController = new AbortController();
@@ -1039,10 +1036,7 @@ async function makeRequest(model, task, apiSettings, stream, body, requestOption
1039
1036
  if (response.status === 403 &&
1040
1037
  errorDetails &&
1041
1038
  errorDetails.some((detail) => detail.reason === 'SERVICE_DISABLED') &&
1042
- errorDetails.some((detail) => {
1043
- var _a, _b;
1044
- return (_b = (_a = detail.links) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.description.includes('Google developers console API activation');
1045
- })) {
1039
+ errorDetails.some((detail) => detail.links?.[0]?.description.includes('Google developers console API activation'))) {
1046
1040
  throw new AIError(AIErrorCode.API_NOT_ENABLED, `The Firebase AI SDK requires the Firebase AI ` +
1047
1041
  `API ('firebasevertexai.googleapis.com') to be enabled in your ` +
1048
1042
  `Firebase project. Enable this API by visiting the Firebase Console ` +
@@ -1187,10 +1181,9 @@ function addHelpers(response) {
1187
1181
  * Returns all text found in all parts of first candidate.
1188
1182
  */
1189
1183
  function getText(response) {
1190
- var _a, _b, _c, _d;
1191
1184
  const textStrings = [];
1192
- if ((_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0].content) === null || _b === void 0 ? void 0 : _b.parts) {
1193
- for (const part of (_d = (_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0].content) === null || _d === void 0 ? void 0 : _d.parts) {
1185
+ if (response.candidates?.[0].content?.parts) {
1186
+ for (const part of response.candidates?.[0].content?.parts) {
1194
1187
  if (part.text) {
1195
1188
  textStrings.push(part.text);
1196
1189
  }
@@ -1207,10 +1200,9 @@ function getText(response) {
1207
1200
  * Returns {@link FunctionCall}s associated with first candidate.
1208
1201
  */
1209
1202
  function getFunctionCalls(response) {
1210
- var _a, _b, _c, _d;
1211
1203
  const functionCalls = [];
1212
- if ((_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0].content) === null || _b === void 0 ? void 0 : _b.parts) {
1213
- for (const part of (_d = (_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0].content) === null || _d === void 0 ? void 0 : _d.parts) {
1204
+ if (response.candidates?.[0].content?.parts) {
1205
+ for (const part of response.candidates?.[0].content?.parts) {
1214
1206
  if (part.functionCall) {
1215
1207
  functionCalls.push(part.functionCall);
1216
1208
  }
@@ -1229,10 +1221,9 @@ function getFunctionCalls(response) {
1229
1221
  * @internal
1230
1222
  */
1231
1223
  function getInlineDataParts(response) {
1232
- var _a, _b, _c, _d;
1233
1224
  const data = [];
1234
- if ((_b = (_a = response.candidates) === null || _a === void 0 ? void 0 : _a[0].content) === null || _b === void 0 ? void 0 : _b.parts) {
1235
- for (const part of (_d = (_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0].content) === null || _d === void 0 ? void 0 : _d.parts) {
1225
+ if (response.candidates?.[0].content?.parts) {
1226
+ for (const part of response.candidates?.[0].content?.parts) {
1236
1227
  if (part.inlineData) {
1237
1228
  data.push(part);
1238
1229
  }
@@ -1251,19 +1242,18 @@ function hadBadFinishReason(candidate) {
1251
1242
  badFinishReasons.some(reason => reason === candidate.finishReason));
1252
1243
  }
1253
1244
  function formatBlockErrorMessage(response) {
1254
- var _a, _b, _c;
1255
1245
  let message = '';
1256
1246
  if ((!response.candidates || response.candidates.length === 0) &&
1257
1247
  response.promptFeedback) {
1258
1248
  message += 'Response was blocked';
1259
- if ((_a = response.promptFeedback) === null || _a === void 0 ? void 0 : _a.blockReason) {
1249
+ if (response.promptFeedback?.blockReason) {
1260
1250
  message += ` due to ${response.promptFeedback.blockReason}`;
1261
1251
  }
1262
- if ((_b = response.promptFeedback) === null || _b === void 0 ? void 0 : _b.blockReasonMessage) {
1252
+ if (response.promptFeedback?.blockReasonMessage) {
1263
1253
  message += `: ${response.promptFeedback.blockReasonMessage}`;
1264
1254
  }
1265
1255
  }
1266
- else if ((_c = response.candidates) === null || _c === void 0 ? void 0 : _c[0]) {
1256
+ else if (response.candidates?.[0]) {
1267
1257
  const firstCandidate = response.candidates[0];
1268
1258
  if (hadBadFinishReason(firstCandidate)) {
1269
1259
  message += `Candidate was blocked due to ${firstCandidate.finishReason}`;
@@ -1282,12 +1272,11 @@ function formatBlockErrorMessage(response) {
1282
1272
  * @internal
1283
1273
  */
1284
1274
  async function handlePredictResponse(response) {
1285
- var _a;
1286
1275
  const responseJson = await response.json();
1287
1276
  const images = [];
1288
1277
  let filteredReason = undefined;
1289
1278
  // The backend should always send a non-empty array of predictions if the response was successful.
1290
- if (!responseJson.predictions || ((_a = responseJson.predictions) === null || _a === void 0 ? void 0 : _a.length) === 0) {
1279
+ if (!responseJson.predictions || responseJson.predictions?.length === 0) {
1291
1280
  throw new AIError(AIErrorCode.RESPONSE_ERROR, 'No predictions or filtered reason received from Vertex AI. Please report this issue with the full error details at https://github.com/firebase/firebase-js-sdk/issues.');
1292
1281
  }
1293
1282
  for (const prediction of responseJson.predictions) {
@@ -1351,13 +1340,12 @@ async function handlePredictResponse(response) {
1351
1340
  * @internal
1352
1341
  */
1353
1342
  function mapGenerateContentRequest(generateContentRequest) {
1354
- var _a, _b;
1355
- (_a = generateContentRequest.safetySettings) === null || _a === void 0 ? void 0 : _a.forEach(safetySetting => {
1343
+ generateContentRequest.safetySettings?.forEach(safetySetting => {
1356
1344
  if (safetySetting.method) {
1357
1345
  throw new AIError(AIErrorCode.UNSUPPORTED, 'SafetySetting.method is not supported in the the Gemini Developer API. Please remove this property.');
1358
1346
  }
1359
1347
  });
1360
- if ((_b = generateContentRequest.generationConfig) === null || _b === void 0 ? void 0 : _b.topK) {
1348
+ if (generateContentRequest.generationConfig?.topK) {
1361
1349
  const roundedTopK = Math.round(generateContentRequest.generationConfig.topK);
1362
1350
  if (roundedTopK !== generateContentRequest.generationConfig.topK) {
1363
1351
  logger.warn('topK in GenerationConfig has been rounded to the nearest integer to match the format for requests to the Gemini Developer API.');
@@ -1398,7 +1386,10 @@ function mapGenerateContentResponse(googleAIResponse) {
1398
1386
  */
1399
1387
  function mapCountTokensRequest(countTokensRequest, model) {
1400
1388
  const mappedCountTokensRequest = {
1401
- generateContentRequest: Object.assign({ model }, countTokensRequest)
1389
+ generateContentRequest: {
1390
+ model,
1391
+ ...countTokensRequest
1392
+ }
1402
1393
  };
1403
1394
  return mappedCountTokensRequest;
1404
1395
  }
@@ -1418,7 +1409,6 @@ function mapGenerateContentCandidates(candidates) {
1418
1409
  let mappedSafetyRatings;
1419
1410
  if (mappedCandidates) {
1420
1411
  candidates.forEach(candidate => {
1421
- var _a;
1422
1412
  // Map citationSources to citations.
1423
1413
  let citationMetadata;
1424
1414
  if (candidate.citationMetadata) {
@@ -1429,14 +1419,18 @@ function mapGenerateContentCandidates(candidates) {
1429
1419
  // Assign missing candidate SafetyRatings properties to their defaults if undefined.
1430
1420
  if (candidate.safetyRatings) {
1431
1421
  mappedSafetyRatings = candidate.safetyRatings.map(safetyRating => {
1432
- var _a, _b, _c;
1433
- return Object.assign(Object.assign({}, safetyRating), { severity: (_a = safetyRating.severity) !== null && _a !== void 0 ? _a : HarmSeverity.HARM_SEVERITY_UNSUPPORTED, probabilityScore: (_b = safetyRating.probabilityScore) !== null && _b !== void 0 ? _b : 0, severityScore: (_c = safetyRating.severityScore) !== null && _c !== void 0 ? _c : 0 });
1422
+ return {
1423
+ ...safetyRating,
1424
+ severity: safetyRating.severity ?? HarmSeverity.HARM_SEVERITY_UNSUPPORTED,
1425
+ probabilityScore: safetyRating.probabilityScore ?? 0,
1426
+ severityScore: safetyRating.severityScore ?? 0
1427
+ };
1434
1428
  });
1435
1429
  }
1436
1430
  // videoMetadata is not supported.
1437
1431
  // Throw early since developers may send a long video as input and only expect to pay
1438
1432
  // for inference on a small portion of the video.
1439
- if ((_a = candidate.content) === null || _a === void 0 ? void 0 : _a.parts.some(part => part === null || part === void 0 ? void 0 : part.videoMetadata)) {
1433
+ if (candidate.content?.parts.some(part => part?.videoMetadata)) {
1440
1434
  throw new AIError(AIErrorCode.UNSUPPORTED, 'Part.videoMetadata is not supported in the Gemini Developer API. Please remove this property.');
1441
1435
  }
1442
1436
  const mappedCandidate = {
@@ -1457,13 +1451,12 @@ function mapPromptFeedback(promptFeedback) {
1457
1451
  // Assign missing SafetyRating properties to their defaults if undefined.
1458
1452
  const mappedSafetyRatings = [];
1459
1453
  promptFeedback.safetyRatings.forEach(safetyRating => {
1460
- var _a, _b, _c;
1461
1454
  mappedSafetyRatings.push({
1462
1455
  category: safetyRating.category,
1463
1456
  probability: safetyRating.probability,
1464
- severity: (_a = safetyRating.severity) !== null && _a !== void 0 ? _a : HarmSeverity.HARM_SEVERITY_UNSUPPORTED,
1465
- probabilityScore: (_b = safetyRating.probabilityScore) !== null && _b !== void 0 ? _b : 0,
1466
- severityScore: (_c = safetyRating.severityScore) !== null && _c !== void 0 ? _c : 0,
1457
+ severity: safetyRating.severity ?? HarmSeverity.HARM_SEVERITY_UNSUPPORTED,
1458
+ probabilityScore: safetyRating.probabilityScore ?? 0,
1459
+ severityScore: safetyRating.severityScore ?? 0,
1467
1460
  blocked: safetyRating.blocked
1468
1461
  });
1469
1462
  });
@@ -1524,24 +1517,22 @@ async function getResponsePromise(stream, apiSettings) {
1524
1517
  allResponses.push(value);
1525
1518
  }
1526
1519
  }
1527
- function generateResponseSequence(stream, apiSettings) {
1528
- return tslib.__asyncGenerator(this, arguments, function* generateResponseSequence_1() {
1529
- const reader = stream.getReader();
1530
- while (true) {
1531
- const { value, done } = yield tslib.__await(reader.read());
1532
- if (done) {
1533
- break;
1534
- }
1535
- let enhancedResponse;
1536
- if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
1537
- enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value));
1538
- }
1539
- else {
1540
- enhancedResponse = createEnhancedContentResponse(value);
1541
- }
1542
- yield yield tslib.__await(enhancedResponse);
1520
+ async function* generateResponseSequence(stream, apiSettings) {
1521
+ const reader = stream.getReader();
1522
+ while (true) {
1523
+ const { value, done } = await reader.read();
1524
+ if (done) {
1525
+ break;
1543
1526
  }
1544
- });
1527
+ let enhancedResponse;
1528
+ if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
1529
+ enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value));
1530
+ }
1531
+ else {
1532
+ enhancedResponse = createEnhancedContentResponse(value);
1533
+ }
1534
+ yield enhancedResponse;
1535
+ }
1545
1536
  }
1546
1537
  /**
1547
1538
  * Reads a raw stream from the fetch response and join incomplete
@@ -1593,7 +1584,7 @@ function getResponseStream(inputStream) {
1593
1584
  function aggregateResponses(responses) {
1594
1585
  const lastResponse = responses[responses.length - 1];
1595
1586
  const aggregatedResponse = {
1596
- promptFeedback: lastResponse === null || lastResponse === void 0 ? void 0 : lastResponse.promptFeedback
1587
+ promptFeedback: lastResponse?.promptFeedback
1597
1588
  };
1598
1589
  for (const response of responses) {
1599
1590
  if (response.candidates) {
@@ -1950,7 +1941,7 @@ class ChatSession {
1950
1941
  this._history = [];
1951
1942
  this._sendPromise = Promise.resolve();
1952
1943
  this._apiSettings = apiSettings;
1953
- if (params === null || params === void 0 ? void 0 : params.history) {
1944
+ if (params?.history) {
1954
1945
  validateChatHistory(params.history);
1955
1946
  this._history = params.history;
1956
1947
  }
@@ -1969,15 +1960,14 @@ class ChatSession {
1969
1960
  * {@link GenerateContentResult}
1970
1961
  */
1971
1962
  async sendMessage(request) {
1972
- var _a, _b, _c, _d, _e;
1973
1963
  await this._sendPromise;
1974
1964
  const newContent = formatNewContent(request);
1975
1965
  const generateContentRequest = {
1976
- safetySettings: (_a = this.params) === null || _a === void 0 ? void 0 : _a.safetySettings,
1977
- generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
1978
- tools: (_c = this.params) === null || _c === void 0 ? void 0 : _c.tools,
1979
- toolConfig: (_d = this.params) === null || _d === void 0 ? void 0 : _d.toolConfig,
1980
- systemInstruction: (_e = this.params) === null || _e === void 0 ? void 0 : _e.systemInstruction,
1966
+ safetySettings: this.params?.safetySettings,
1967
+ generationConfig: this.params?.generationConfig,
1968
+ tools: this.params?.tools,
1969
+ toolConfig: this.params?.toolConfig,
1970
+ systemInstruction: this.params?.systemInstruction,
1981
1971
  contents: [...this._history, newContent]
1982
1972
  };
1983
1973
  let finalResult = {};
@@ -1985,14 +1975,13 @@ class ChatSession {
1985
1975
  this._sendPromise = this._sendPromise
1986
1976
  .then(() => generateContent(this._apiSettings, this.model, generateContentRequest, this.requestOptions))
1987
1977
  .then(result => {
1988
- var _a, _b;
1989
1978
  if (result.response.candidates &&
1990
1979
  result.response.candidates.length > 0) {
1991
1980
  this._history.push(newContent);
1992
1981
  const responseContent = {
1993
- parts: ((_a = result.response.candidates) === null || _a === void 0 ? void 0 : _a[0].content.parts) || [],
1982
+ parts: result.response.candidates?.[0].content.parts || [],
1994
1983
  // Response seems to come back without a role set.
1995
- role: ((_b = result.response.candidates) === null || _b === void 0 ? void 0 : _b[0].content.role) || 'model'
1984
+ role: result.response.candidates?.[0].content.role || 'model'
1996
1985
  };
1997
1986
  this._history.push(responseContent);
1998
1987
  }
@@ -2013,15 +2002,14 @@ class ChatSession {
2013
2002
  * and a response promise.
2014
2003
  */
2015
2004
  async sendMessageStream(request) {
2016
- var _a, _b, _c, _d, _e;
2017
2005
  await this._sendPromise;
2018
2006
  const newContent = formatNewContent(request);
2019
2007
  const generateContentRequest = {
2020
- safetySettings: (_a = this.params) === null || _a === void 0 ? void 0 : _a.safetySettings,
2021
- generationConfig: (_b = this.params) === null || _b === void 0 ? void 0 : _b.generationConfig,
2022
- tools: (_c = this.params) === null || _c === void 0 ? void 0 : _c.tools,
2023
- toolConfig: (_d = this.params) === null || _d === void 0 ? void 0 : _d.toolConfig,
2024
- systemInstruction: (_e = this.params) === null || _e === void 0 ? void 0 : _e.systemInstruction,
2008
+ safetySettings: this.params?.safetySettings,
2009
+ generationConfig: this.params?.generationConfig,
2010
+ tools: this.params?.tools,
2011
+ toolConfig: this.params?.toolConfig,
2012
+ systemInstruction: this.params?.systemInstruction,
2025
2013
  contents: [...this._history, newContent]
2026
2014
  };
2027
2015
  const streamPromise = generateContentStream(this._apiSettings, this.model, generateContentRequest, this.requestOptions);
@@ -2037,7 +2025,7 @@ class ChatSession {
2037
2025
  .then(response => {
2038
2026
  if (response.candidates && response.candidates.length > 0) {
2039
2027
  this._history.push(newContent);
2040
- const responseContent = Object.assign({}, response.candidates[0].content);
2028
+ const responseContent = { ...response.candidates[0].content };
2041
2029
  // Response seems to come back without a role set.
2042
2030
  if (!responseContent.role) {
2043
2031
  responseContent.role = 'model';
@@ -2130,7 +2118,14 @@ class GenerativeModel extends AIModel {
2130
2118
  */
2131
2119
  async generateContent(request) {
2132
2120
  const formattedParams = formatGenerateContentInput(request);
2133
- return generateContent(this._apiSettings, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction }, formattedParams), this.requestOptions);
2121
+ return generateContent(this._apiSettings, this.model, {
2122
+ generationConfig: this.generationConfig,
2123
+ safetySettings: this.safetySettings,
2124
+ tools: this.tools,
2125
+ toolConfig: this.toolConfig,
2126
+ systemInstruction: this.systemInstruction,
2127
+ ...formattedParams
2128
+ }, this.requestOptions);
2134
2129
  }
2135
2130
  /**
2136
2131
  * Makes a single streaming call to the model
@@ -2140,14 +2135,33 @@ class GenerativeModel extends AIModel {
2140
2135
  */
2141
2136
  async generateContentStream(request) {
2142
2137
  const formattedParams = formatGenerateContentInput(request);
2143
- return generateContentStream(this._apiSettings, this.model, Object.assign({ generationConfig: this.generationConfig, safetySettings: this.safetySettings, tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction }, formattedParams), this.requestOptions);
2138
+ return generateContentStream(this._apiSettings, this.model, {
2139
+ generationConfig: this.generationConfig,
2140
+ safetySettings: this.safetySettings,
2141
+ tools: this.tools,
2142
+ toolConfig: this.toolConfig,
2143
+ systemInstruction: this.systemInstruction,
2144
+ ...formattedParams
2145
+ }, this.requestOptions);
2144
2146
  }
2145
2147
  /**
2146
2148
  * Gets a new {@link ChatSession} instance which can be used for
2147
2149
  * multi-turn chats.
2148
2150
  */
2149
2151
  startChat(startChatParams) {
2150
- return new ChatSession(this._apiSettings, this.model, Object.assign({ tools: this.tools, toolConfig: this.toolConfig, systemInstruction: this.systemInstruction, generationConfig: this.generationConfig, safetySettings: this.safetySettings }, startChatParams), this.requestOptions);
2152
+ return new ChatSession(this._apiSettings, this.model, {
2153
+ tools: this.tools,
2154
+ toolConfig: this.toolConfig,
2155
+ systemInstruction: this.systemInstruction,
2156
+ generationConfig: this.generationConfig,
2157
+ safetySettings: this.safetySettings,
2158
+ /**
2159
+ * Overrides params inherited from GenerativeModel with those explicitly set in the
2160
+ * StartChatParams. For example, if startChatParams.generationConfig is set, it'll override
2161
+ * this.generationConfig.
2162
+ */
2163
+ ...startChatParams
2164
+ }, this.requestOptions);
2151
2165
  }
2152
2166
  /**
2153
2167
  * Counts the tokens in the provided request.
@@ -2233,7 +2247,10 @@ class ImagenModel extends AIModel {
2233
2247
  * @beta
2234
2248
  */
2235
2249
  async generateImages(prompt) {
2236
- const body = createPredictRequestBody(prompt, Object.assign(Object.assign({}, this.generationConfig), this.safetySettings));
2250
+ const body = createPredictRequestBody(prompt, {
2251
+ ...this.generationConfig,
2252
+ ...this.safetySettings
2253
+ });
2237
2254
  const response = await makeRequest(this.model, Task.PREDICT, this._apiSettings,
2238
2255
  /* stream */ false, JSON.stringify(body), this.requestOptions);
2239
2256
  return handlePredictResponse(response);
@@ -2258,7 +2275,11 @@ class ImagenModel extends AIModel {
2258
2275
  * If all images are filtered, the `images` array will be empty.
2259
2276
  */
2260
2277
  async generateImagesGCS(prompt, gcsURI) {
2261
- const body = createPredictRequestBody(prompt, Object.assign(Object.assign({ gcsURI }, this.generationConfig), this.safetySettings));
2278
+ const body = createPredictRequestBody(prompt, {
2279
+ gcsURI,
2280
+ ...this.generationConfig,
2281
+ ...this.safetySettings
2282
+ });
2262
2283
  const response = await makeRequest(this.model, Task.PREDICT, this._apiSettings,
2263
2284
  /* stream */ false, JSON.stringify(body), this.requestOptions);
2264
2285
  return handlePredictResponse(response);
@@ -2290,12 +2311,19 @@ class ImagenModel extends AIModel {
2290
2311
  */
2291
2312
  class Schema {
2292
2313
  constructor(schemaParams) {
2314
+ // TODO(dlarocque): Enforce this with union types
2315
+ if (!schemaParams.type && !schemaParams.anyOf) {
2316
+ throw new AIError(AIErrorCode.INVALID_SCHEMA, "A schema must have either a 'type' or an 'anyOf' array of sub-schemas.");
2317
+ }
2293
2318
  // eslint-disable-next-line guard-for-in
2294
2319
  for (const paramKey in schemaParams) {
2295
2320
  this[paramKey] = schemaParams[paramKey];
2296
2321
  }
2297
2322
  // Ensure these are explicitly set to avoid TS errors.
2298
2323
  this.type = schemaParams.type;
2324
+ this.format = schemaParams.hasOwnProperty('format')
2325
+ ? schemaParams.format
2326
+ : undefined;
2299
2327
  this.nullable = schemaParams.hasOwnProperty('nullable')
2300
2328
  ? !!schemaParams.nullable
2301
2329
  : false;
@@ -2342,6 +2370,9 @@ class Schema {
2342
2370
  static boolean(booleanParams) {
2343
2371
  return new BooleanSchema(booleanParams);
2344
2372
  }
2373
+ static anyOf(anyOfParams) {
2374
+ return new AnyOfSchema(anyOfParams);
2375
+ }
2345
2376
  }
2346
2377
  /**
2347
2378
  * Schema class for "integer" types.
@@ -2349,7 +2380,10 @@ class Schema {
2349
2380
  */
2350
2381
  class IntegerSchema extends Schema {
2351
2382
  constructor(schemaParams) {
2352
- super(Object.assign({ type: SchemaType.INTEGER }, schemaParams));
2383
+ super({
2384
+ type: SchemaType.INTEGER,
2385
+ ...schemaParams
2386
+ });
2353
2387
  }
2354
2388
  }
2355
2389
  /**
@@ -2358,7 +2392,10 @@ class IntegerSchema extends Schema {
2358
2392
  */
2359
2393
  class NumberSchema extends Schema {
2360
2394
  constructor(schemaParams) {
2361
- super(Object.assign({ type: SchemaType.NUMBER }, schemaParams));
2395
+ super({
2396
+ type: SchemaType.NUMBER,
2397
+ ...schemaParams
2398
+ });
2362
2399
  }
2363
2400
  }
2364
2401
  /**
@@ -2367,7 +2404,10 @@ class NumberSchema extends Schema {
2367
2404
  */
2368
2405
  class BooleanSchema extends Schema {
2369
2406
  constructor(schemaParams) {
2370
- super(Object.assign({ type: SchemaType.BOOLEAN }, schemaParams));
2407
+ super({
2408
+ type: SchemaType.BOOLEAN,
2409
+ ...schemaParams
2410
+ });
2371
2411
  }
2372
2412
  }
2373
2413
  /**
@@ -2377,7 +2417,10 @@ class BooleanSchema extends Schema {
2377
2417
  */
2378
2418
  class StringSchema extends Schema {
2379
2419
  constructor(schemaParams, enumValues) {
2380
- super(Object.assign({ type: SchemaType.STRING }, schemaParams));
2420
+ super({
2421
+ type: SchemaType.STRING,
2422
+ ...schemaParams
2423
+ });
2381
2424
  this.enum = enumValues;
2382
2425
  }
2383
2426
  /**
@@ -2399,7 +2442,10 @@ class StringSchema extends Schema {
2399
2442
  */
2400
2443
  class ArraySchema extends Schema {
2401
2444
  constructor(schemaParams, items) {
2402
- super(Object.assign({ type: SchemaType.ARRAY }, schemaParams));
2445
+ super({
2446
+ type: SchemaType.ARRAY,
2447
+ ...schemaParams
2448
+ });
2403
2449
  this.items = items;
2404
2450
  }
2405
2451
  /**
@@ -2418,7 +2464,10 @@ class ArraySchema extends Schema {
2418
2464
  */
2419
2465
  class ObjectSchema extends Schema {
2420
2466
  constructor(schemaParams, properties, optionalProperties = []) {
2421
- super(Object.assign({ type: SchemaType.OBJECT }, schemaParams));
2467
+ super({
2468
+ type: SchemaType.OBJECT,
2469
+ ...schemaParams
2470
+ });
2422
2471
  this.properties = properties;
2423
2472
  this.optionalProperties = optionalProperties;
2424
2473
  }
@@ -2427,7 +2476,7 @@ class ObjectSchema extends Schema {
2427
2476
  */
2428
2477
  toJSON() {
2429
2478
  const obj = super.toJSON();
2430
- obj.properties = Object.assign({}, this.properties);
2479
+ obj.properties = { ...this.properties };
2431
2480
  const required = [];
2432
2481
  if (this.optionalProperties) {
2433
2482
  for (const propertyKey of this.optionalProperties) {
@@ -2451,6 +2500,34 @@ class ObjectSchema extends Schema {
2451
2500
  return obj;
2452
2501
  }
2453
2502
  }
2503
+ /**
2504
+ * Schema class representing a value that can conform to any of the provided sub-schemas. This is
2505
+ * useful when a field can accept multiple distinct types or structures.
2506
+ * @public
2507
+ */
2508
+ class AnyOfSchema extends Schema {
2509
+ constructor(schemaParams) {
2510
+ if (schemaParams.anyOf.length === 0) {
2511
+ throw new AIError(AIErrorCode.INVALID_SCHEMA, "The 'anyOf' array must not be empty.");
2512
+ }
2513
+ super({
2514
+ ...schemaParams,
2515
+ type: undefined // anyOf schemas do not have an explicit type
2516
+ });
2517
+ this.anyOf = schemaParams.anyOf;
2518
+ }
2519
+ /**
2520
+ * @internal
2521
+ */
2522
+ toJSON() {
2523
+ const obj = super.toJSON();
2524
+ // Ensure the 'anyOf' property contains serialized SchemaRequest objects.
2525
+ if (this.anyOf && Array.isArray(this.anyOf)) {
2526
+ obj.anyOf = this.anyOf.map(s => s.toJSON());
2527
+ }
2528
+ return obj;
2529
+ }
2530
+ }
2454
2531
 
2455
2532
  /**
2456
2533
  * @license
@@ -2620,14 +2697,15 @@ function registerAI() {
2620
2697
  return new AIService(app, backend, auth, appCheckProvider);
2621
2698
  }, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
2622
2699
  app.registerVersion(name, version);
2623
- // BUILD_TARGET will be replaced by values like esm2017, cjs2017, etc during the compilation
2624
- app.registerVersion(name, version, 'cjs2017');
2700
+ // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
2701
+ app.registerVersion(name, version, 'cjs2020');
2625
2702
  }
2626
2703
  registerAI();
2627
2704
 
2628
2705
  exports.AIError = AIError;
2629
2706
  exports.AIErrorCode = AIErrorCode;
2630
2707
  exports.AIModel = AIModel;
2708
+ exports.AnyOfSchema = AnyOfSchema;
2631
2709
  exports.ArraySchema = ArraySchema;
2632
2710
  exports.Backend = Backend;
2633
2711
  exports.BackendType = BackendType;