@firebase/ai 2.5.0 → 2.6.0-20251113021847

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.
@@ -4,7 +4,7 @@ import { FirebaseError, Deferred, getModularInstance } from '@firebase/util';
4
4
  import { Logger } from '@firebase/logger';
5
5
 
6
6
  var name = "@firebase/ai";
7
- var version = "2.5.0";
7
+ var version = "2.6.0-20251113021847";
8
8
 
9
9
  /**
10
10
  * @license
@@ -34,6 +34,62 @@ const DEFAULT_FETCH_TIMEOUT_MS = 180 * 1000;
34
34
  */
35
35
  const DEFAULT_HYBRID_IN_CLOUD_MODEL = 'gemini-2.0-flash-lite';
36
36
 
37
+ /**
38
+ * @license
39
+ * Copyright 2024 Google LLC
40
+ *
41
+ * Licensed under the Apache License, Version 2.0 (the "License");
42
+ * you may not use this file except in compliance with the License.
43
+ * You may obtain a copy of the License at
44
+ *
45
+ * http://www.apache.org/licenses/LICENSE-2.0
46
+ *
47
+ * Unless required by applicable law or agreed to in writing, software
48
+ * distributed under the License is distributed on an "AS IS" BASIS,
49
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
50
+ * See the License for the specific language governing permissions and
51
+ * limitations under the License.
52
+ */
53
+ /**
54
+ * Error class for the Firebase AI SDK.
55
+ *
56
+ * @public
57
+ */
58
+ class AIError extends FirebaseError {
59
+ /**
60
+ * Constructs a new instance of the `AIError` class.
61
+ *
62
+ * @param code - The error code from {@link (AIErrorCode:type)}.
63
+ * @param message - A human-readable message describing the error.
64
+ * @param customErrorData - Optional error data.
65
+ */
66
+ constructor(code, message, customErrorData) {
67
+ // Match error format used by FirebaseError from ErrorFactory
68
+ const service = AI_TYPE;
69
+ const fullCode = `${service}/${code}`;
70
+ const fullMessage = `${service}: ${message} (${fullCode})`;
71
+ super(code, fullMessage);
72
+ this.code = code;
73
+ this.customErrorData = customErrorData;
74
+ // FirebaseError initializes a stack trace, but it assumes the error is created from the error
75
+ // factory. Since we break this assumption, we set the stack trace to be originating from this
76
+ // constructor.
77
+ // This is only supported in V8.
78
+ if (Error.captureStackTrace) {
79
+ // Allows us to initialize the stack trace without including the constructor itself at the
80
+ // top level of the stack trace.
81
+ Error.captureStackTrace(this, AIError);
82
+ }
83
+ // Allows instanceof AIError in ES5/ES6
84
+ // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
85
+ // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
86
+ // which we can now use since we no longer target ES5.
87
+ Object.setPrototypeOf(this, AIError.prototype);
88
+ // Since Error is an interface, we don't inherit toString and so we define it ourselves.
89
+ this.toString = () => fullMessage;
90
+ }
91
+ }
92
+
37
93
  /**
38
94
  * @license
39
95
  * Copyright 2024 Google LLC
@@ -710,6 +766,18 @@ class GoogleAIBackend extends Backend {
710
766
  constructor() {
711
767
  super(BackendType.GOOGLE_AI);
712
768
  }
769
+ /**
770
+ * @internal
771
+ */
772
+ _getModelPath(project, model) {
773
+ return `/${DEFAULT_API_VERSION}/projects/${project}/${model}`;
774
+ }
775
+ /**
776
+ * @internal
777
+ */
778
+ _getTemplatePath(project, templateId) {
779
+ return `/${DEFAULT_API_VERSION}/projects/${project}/templates/${templateId}`;
780
+ }
713
781
  }
714
782
  /**
715
783
  * Configuration class for the Vertex AI Gemini API.
@@ -736,6 +804,76 @@ class VertexAIBackend extends Backend {
736
804
  this.location = location;
737
805
  }
738
806
  }
807
+ /**
808
+ * @internal
809
+ */
810
+ _getModelPath(project, model) {
811
+ return `/${DEFAULT_API_VERSION}/projects/${project}/locations/${this.location}/${model}`;
812
+ }
813
+ /**
814
+ * @internal
815
+ */
816
+ _getTemplatePath(project, templateId) {
817
+ return `/${DEFAULT_API_VERSION}/projects/${project}/locations/${this.location}/templates/${templateId}`;
818
+ }
819
+ }
820
+
821
+ /**
822
+ * @license
823
+ * Copyright 2025 Google LLC
824
+ *
825
+ * Licensed under the Apache License, Version 2.0 (the "License");
826
+ * you may not use this file except in compliance with the License.
827
+ * You may obtain a copy of the License at
828
+ *
829
+ * http://www.apache.org/licenses/LICENSE-2.0
830
+ *
831
+ * Unless required by applicable law or agreed to in writing, software
832
+ * distributed under the License is distributed on an "AS IS" BASIS,
833
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
834
+ * See the License for the specific language governing permissions and
835
+ * limitations under the License.
836
+ */
837
+ /**
838
+ * Encodes a {@link Backend} into a string that will be used to uniquely identify {@link AI}
839
+ * instances by backend type.
840
+ *
841
+ * @internal
842
+ */
843
+ function encodeInstanceIdentifier(backend) {
844
+ if (backend instanceof GoogleAIBackend) {
845
+ return `${AI_TYPE}/googleai`;
846
+ }
847
+ else if (backend instanceof VertexAIBackend) {
848
+ return `${AI_TYPE}/vertexai/${backend.location}`;
849
+ }
850
+ else {
851
+ throw new AIError(AIErrorCode.ERROR, `Invalid backend: ${JSON.stringify(backend.backendType)}`);
852
+ }
853
+ }
854
+ /**
855
+ * Decodes an instance identifier string into a {@link Backend}.
856
+ *
857
+ * @internal
858
+ */
859
+ function decodeInstanceIdentifier(instanceIdentifier) {
860
+ const identifierParts = instanceIdentifier.split('/');
861
+ if (identifierParts[0] !== AI_TYPE) {
862
+ throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier, unknown prefix '${identifierParts[0]}'`);
863
+ }
864
+ const backendType = identifierParts[1];
865
+ switch (backendType) {
866
+ case 'vertexai':
867
+ const location = identifierParts[2];
868
+ if (!location) {
869
+ throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier, unknown location '${instanceIdentifier}'`);
870
+ }
871
+ return new VertexAIBackend(location);
872
+ case 'googleai':
873
+ return new GoogleAIBackend();
874
+ default:
875
+ throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier string: '${instanceIdentifier}'`);
876
+ }
739
877
  }
740
878
 
741
879
  /**
@@ -783,7 +921,7 @@ class AIService {
783
921
 
784
922
  /**
785
923
  * @license
786
- * Copyright 2024 Google LLC
924
+ * Copyright 2025 Google LLC
787
925
  *
788
926
  * Licensed under the Apache License, Version 2.0 (the "License");
789
927
  * you may not use this file except in compliance with the License.
@@ -797,44 +935,16 @@ class AIService {
797
935
  * See the License for the specific language governing permissions and
798
936
  * limitations under the License.
799
937
  */
800
- /**
801
- * Error class for the Firebase AI SDK.
802
- *
803
- * @public
804
- */
805
- class AIError extends FirebaseError {
806
- /**
807
- * Constructs a new instance of the `AIError` class.
808
- *
809
- * @param code - The error code from {@link (AIErrorCode:type)}.
810
- * @param message - A human-readable message describing the error.
811
- * @param customErrorData - Optional error data.
812
- */
813
- constructor(code, message, customErrorData) {
814
- // Match error format used by FirebaseError from ErrorFactory
815
- const service = AI_TYPE;
816
- const fullCode = `${service}/${code}`;
817
- const fullMessage = `${service}: ${message} (${fullCode})`;
818
- super(code, fullMessage);
819
- this.code = code;
820
- this.customErrorData = customErrorData;
821
- // FirebaseError initializes a stack trace, but it assumes the error is created from the error
822
- // factory. Since we break this assumption, we set the stack trace to be originating from this
823
- // constructor.
824
- // This is only supported in V8.
825
- if (Error.captureStackTrace) {
826
- // Allows us to initialize the stack trace without including the constructor itself at the
827
- // top level of the stack trace.
828
- Error.captureStackTrace(this, AIError);
829
- }
830
- // Allows instanceof AIError in ES5/ES6
831
- // https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
832
- // TODO(dlarocque): Replace this with `new.target`: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
833
- // which we can now use since we no longer target ES5.
834
- Object.setPrototypeOf(this, AIError.prototype);
835
- // Since Error is an interface, we don't inherit toString and so we define it ourselves.
836
- this.toString = () => fullMessage;
837
- }
938
+ function factory(container, { instanceIdentifier }) {
939
+ if (!instanceIdentifier) {
940
+ throw new AIError(AIErrorCode.ERROR, 'AIService instance identifier is undefined.');
941
+ }
942
+ const backend = decodeInstanceIdentifier(instanceIdentifier);
943
+ // getImmediate for FirebaseApp will always succeed
944
+ const app = container.getProvider('app').getImmediate();
945
+ const auth = container.getProvider('auth-internal');
946
+ const appCheckProvider = container.getProvider('app-check-internal');
947
+ return new AIService(app, backend, auth, appCheckProvider);
838
948
  }
839
949
 
840
950
  /**
@@ -854,45 +964,48 @@ class AIError extends FirebaseError {
854
964
  * limitations under the License.
855
965
  */
856
966
  /**
857
- * Encodes a {@link Backend} into a string that will be used to uniquely identify {@link AI}
858
- * instances by backend type.
967
+ * Initializes an {@link ApiSettings} object from an {@link AI} instance.
859
968
  *
860
- * @internal
969
+ * If this is a Server App, the {@link ApiSettings} object's `getAppCheckToken()` will resolve
970
+ * with the `FirebaseServerAppSettings.appCheckToken`, instead of requiring that an App Check
971
+ * instance is initialized.
861
972
  */
862
- function encodeInstanceIdentifier(backend) {
863
- if (backend instanceof GoogleAIBackend) {
864
- return `${AI_TYPE}/googleai`;
865
- }
866
- else if (backend instanceof VertexAIBackend) {
867
- return `${AI_TYPE}/vertexai/${backend.location}`;
868
- }
869
- else {
870
- throw new AIError(AIErrorCode.ERROR, `Invalid backend: ${JSON.stringify(backend.backendType)}`);
973
+ function initApiSettings(ai) {
974
+ if (!ai.app?.options?.apiKey) {
975
+ 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.`);
976
+ }
977
+ else if (!ai.app?.options?.projectId) {
978
+ 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.`);
979
+ }
980
+ else if (!ai.app?.options?.appId) {
981
+ 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.`);
982
+ }
983
+ const apiSettings = {
984
+ apiKey: ai.app.options.apiKey,
985
+ project: ai.app.options.projectId,
986
+ appId: ai.app.options.appId,
987
+ automaticDataCollectionEnabled: ai.app.automaticDataCollectionEnabled,
988
+ location: ai.location,
989
+ backend: ai.backend
990
+ };
991
+ if (_isFirebaseServerApp(ai.app) && ai.app.settings.appCheckToken) {
992
+ const token = ai.app.settings.appCheckToken;
993
+ apiSettings.getAppCheckToken = () => {
994
+ return Promise.resolve({ token });
995
+ };
871
996
  }
872
- }
873
- /**
874
- * Decodes an instance identifier string into a {@link Backend}.
875
- *
876
- * @internal
877
- */
878
- function decodeInstanceIdentifier(instanceIdentifier) {
879
- const identifierParts = instanceIdentifier.split('/');
880
- if (identifierParts[0] !== AI_TYPE) {
881
- throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier, unknown prefix '${identifierParts[0]}'`);
997
+ else if (ai.appCheck) {
998
+ if (ai.options?.useLimitedUseAppCheckTokens) {
999
+ apiSettings.getAppCheckToken = () => ai.appCheck.getLimitedUseToken();
1000
+ }
1001
+ else {
1002
+ apiSettings.getAppCheckToken = () => ai.appCheck.getToken();
1003
+ }
882
1004
  }
883
- const backendType = identifierParts[1];
884
- switch (backendType) {
885
- case 'vertexai':
886
- const location = identifierParts[2];
887
- if (!location) {
888
- throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier, unknown location '${instanceIdentifier}'`);
889
- }
890
- return new VertexAIBackend(location);
891
- case 'googleai':
892
- return new GoogleAIBackend();
893
- default:
894
- throw new AIError(AIErrorCode.ERROR, `Invalid instance identifier string: '${instanceIdentifier}'`);
1005
+ if (ai.auth) {
1006
+ apiSettings.getAuthToken = () => ai.auth.getToken();
895
1007
  }
1008
+ return apiSettings;
896
1009
  }
897
1010
 
898
1011
  /**
@@ -938,43 +1051,8 @@ class AIModel {
938
1051
  * @internal
939
1052
  */
940
1053
  constructor(ai, modelName) {
941
- if (!ai.app?.options?.apiKey) {
942
- 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.`);
943
- }
944
- else if (!ai.app?.options?.projectId) {
945
- 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.`);
946
- }
947
- else if (!ai.app?.options?.appId) {
948
- 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.`);
949
- }
950
- else {
951
- this._apiSettings = {
952
- apiKey: ai.app.options.apiKey,
953
- project: ai.app.options.projectId,
954
- appId: ai.app.options.appId,
955
- automaticDataCollectionEnabled: ai.app.automaticDataCollectionEnabled,
956
- location: ai.location,
957
- backend: ai.backend
958
- };
959
- if (_isFirebaseServerApp(ai.app) && ai.app.settings.appCheckToken) {
960
- const token = ai.app.settings.appCheckToken;
961
- this._apiSettings.getAppCheckToken = () => {
962
- return Promise.resolve({ token });
963
- };
964
- }
965
- else if (ai.appCheck) {
966
- if (ai.options?.useLimitedUseAppCheckTokens) {
967
- this._apiSettings.getAppCheckToken = () => ai.appCheck.getLimitedUseToken();
968
- }
969
- else {
970
- this._apiSettings.getAppCheckToken = () => ai.appCheck.getToken();
971
- }
972
- }
973
- if (ai.auth) {
974
- this._apiSettings.getAuthToken = () => ai.auth.getToken();
975
- }
976
- this.model = AIModel.normalizeModelName(modelName, this._apiSettings.backend.backendType);
977
- }
1054
+ this._apiSettings = initApiSettings(ai);
1055
+ this.model = AIModel.normalizeModelName(modelName, this._apiSettings.backend.backendType);
978
1056
  }
979
1057
  /**
980
1058
  * Normalizes the given model name to a fully qualified model resource name.
@@ -1041,7 +1119,7 @@ const logger = new Logger('@firebase/vertexai');
1041
1119
 
1042
1120
  /**
1043
1121
  * @license
1044
- * Copyright 2024 Google LLC
1122
+ * Copyright 2025 Google LLC
1045
1123
  *
1046
1124
  * Licensed under the Apache License, Version 2.0 (the "License");
1047
1125
  * you may not use this file except in compliance with the License.
@@ -1055,47 +1133,33 @@ const logger = new Logger('@firebase/vertexai');
1055
1133
  * See the License for the specific language governing permissions and
1056
1134
  * limitations under the License.
1057
1135
  */
1058
- var Task;
1059
- (function (Task) {
1060
- Task["GENERATE_CONTENT"] = "generateContent";
1061
- Task["STREAM_GENERATE_CONTENT"] = "streamGenerateContent";
1062
- Task["COUNT_TOKENS"] = "countTokens";
1063
- Task["PREDICT"] = "predict";
1064
- })(Task || (Task = {}));
1065
- class RequestUrl {
1066
- constructor(model, task, apiSettings, stream, requestOptions) {
1067
- this.model = model;
1068
- this.task = task;
1069
- this.apiSettings = apiSettings;
1070
- this.stream = stream;
1071
- this.requestOptions = requestOptions;
1136
+ class RequestURL {
1137
+ constructor(params) {
1138
+ this.params = params;
1072
1139
  }
1073
1140
  toString() {
1074
1141
  const url = new URL(this.baseUrl); // Throws if the URL is invalid
1075
- url.pathname = `/${this.apiVersion}/${this.modelPath}:${this.task}`;
1142
+ url.pathname = this.pathname;
1076
1143
  url.search = this.queryParams.toString();
1077
1144
  return url.toString();
1078
1145
  }
1079
- get baseUrl() {
1080
- return this.requestOptions?.baseUrl || `https://${DEFAULT_DOMAIN}`;
1081
- }
1082
- get apiVersion() {
1083
- return DEFAULT_API_VERSION; // TODO: allow user-set options if that feature becomes available
1084
- }
1085
- get modelPath() {
1086
- if (this.apiSettings.backend instanceof GoogleAIBackend) {
1087
- return `projects/${this.apiSettings.project}/${this.model}`;
1088
- }
1089
- else if (this.apiSettings.backend instanceof VertexAIBackend) {
1090
- return `projects/${this.apiSettings.project}/locations/${this.apiSettings.backend.location}/${this.model}`;
1146
+ get pathname() {
1147
+ // We need to construct a different URL if the request is for server side prompt templates,
1148
+ // since the URL patterns are different. Server side prompt templates expect a templateId
1149
+ // instead of a model name.
1150
+ if (this.params.templateId) {
1151
+ return `${this.params.apiSettings.backend._getTemplatePath(this.params.apiSettings.project, this.params.templateId)}:${this.params.task}`;
1091
1152
  }
1092
1153
  else {
1093
- throw new AIError(AIErrorCode.ERROR, `Invalid backend: ${JSON.stringify(this.apiSettings.backend)}`);
1154
+ return `${this.params.apiSettings.backend._getModelPath(this.params.apiSettings.project, this.params.model)}:${this.params.task}`;
1094
1155
  }
1095
1156
  }
1157
+ get baseUrl() {
1158
+ return this.params.requestOptions?.baseUrl ?? `https://${DEFAULT_DOMAIN}`;
1159
+ }
1096
1160
  get queryParams() {
1097
1161
  const params = new URLSearchParams();
1098
- if (this.stream) {
1162
+ if (this.params.stream) {
1099
1163
  params.set('alt', 'sse');
1100
1164
  }
1101
1165
  return params;
@@ -1135,12 +1199,12 @@ async function getHeaders(url) {
1135
1199
  const headers = new Headers();
1136
1200
  headers.append('Content-Type', 'application/json');
1137
1201
  headers.append('x-goog-api-client', getClientHeaders());
1138
- headers.append('x-goog-api-key', url.apiSettings.apiKey);
1139
- if (url.apiSettings.automaticDataCollectionEnabled) {
1140
- headers.append('X-Firebase-Appid', url.apiSettings.appId);
1202
+ headers.append('x-goog-api-key', url.params.apiSettings.apiKey);
1203
+ if (url.params.apiSettings.automaticDataCollectionEnabled) {
1204
+ headers.append('X-Firebase-Appid', url.params.apiSettings.appId);
1141
1205
  }
1142
- if (url.apiSettings.getAppCheckToken) {
1143
- const appCheckToken = await url.apiSettings.getAppCheckToken();
1206
+ if (url.params.apiSettings.getAppCheckToken) {
1207
+ const appCheckToken = await url.params.apiSettings.getAppCheckToken();
1144
1208
  if (appCheckToken) {
1145
1209
  headers.append('X-Firebase-AppCheck', appCheckToken.token);
1146
1210
  if (appCheckToken.error) {
@@ -1148,39 +1212,33 @@ async function getHeaders(url) {
1148
1212
  }
1149
1213
  }
1150
1214
  }
1151
- if (url.apiSettings.getAuthToken) {
1152
- const authToken = await url.apiSettings.getAuthToken();
1215
+ if (url.params.apiSettings.getAuthToken) {
1216
+ const authToken = await url.params.apiSettings.getAuthToken();
1153
1217
  if (authToken) {
1154
1218
  headers.append('Authorization', `Firebase ${authToken.accessToken}`);
1155
1219
  }
1156
1220
  }
1157
1221
  return headers;
1158
1222
  }
1159
- async function constructRequest(model, task, apiSettings, stream, body, requestOptions) {
1160
- const url = new RequestUrl(model, task, apiSettings, stream, requestOptions);
1161
- return {
1162
- url: url.toString(),
1163
- fetchOptions: {
1164
- method: 'POST',
1165
- headers: await getHeaders(url),
1166
- body
1167
- }
1168
- };
1169
- }
1170
- async function makeRequest(model, task, apiSettings, stream, body, requestOptions) {
1171
- const url = new RequestUrl(model, task, apiSettings, stream, requestOptions);
1223
+ async function makeRequest(requestUrlParams, body) {
1224
+ const url = new RequestURL(requestUrlParams);
1172
1225
  let response;
1173
1226
  let fetchTimeoutId;
1174
1227
  try {
1175
- const request = await constructRequest(model, task, apiSettings, stream, body, requestOptions);
1176
- // Timeout is 180s by default
1177
- const timeoutMillis = requestOptions?.timeout != null && requestOptions.timeout >= 0
1178
- ? requestOptions.timeout
1228
+ const fetchOptions = {
1229
+ method: 'POST',
1230
+ headers: await getHeaders(url),
1231
+ body
1232
+ };
1233
+ // Timeout is 180s by default.
1234
+ const timeoutMillis = requestUrlParams.requestOptions?.timeout != null &&
1235
+ requestUrlParams.requestOptions.timeout >= 0
1236
+ ? requestUrlParams.requestOptions.timeout
1179
1237
  : DEFAULT_FETCH_TIMEOUT_MS;
1180
1238
  const abortController = new AbortController();
1181
1239
  fetchTimeoutId = setTimeout(() => abortController.abort(), timeoutMillis);
1182
- request.fetchOptions.signal = abortController.signal;
1183
- response = await fetch(request.url, request.fetchOptions);
1240
+ fetchOptions.signal = abortController.signal;
1241
+ response = await fetch(url.toString(), fetchOptions);
1184
1242
  if (!response.ok) {
1185
1243
  let message = '';
1186
1244
  let errorDetails;
@@ -1202,7 +1260,7 @@ async function makeRequest(model, task, apiSettings, stream, body, requestOption
1202
1260
  throw new AIError(AIErrorCode.API_NOT_ENABLED, `The Firebase AI SDK requires the Firebase AI ` +
1203
1261
  `API ('firebasevertexai.googleapis.com') to be enabled in your ` +
1204
1262
  `Firebase project. Enable this API by visiting the Firebase Console ` +
1205
- `at https://console.firebase.google.com/project/${url.apiSettings.project}/genai/ ` +
1263
+ `at https://console.firebase.google.com/project/${url.params.apiSettings.project}/genai/ ` +
1206
1264
  `and clicking "Get started". If you enabled this API recently, ` +
1207
1265
  `wait a few minutes for the action to propagate to our systems and ` +
1208
1266
  `then retry.`, {
@@ -1943,8 +2001,13 @@ async function generateContentStreamOnCloud(apiSettings, model, params, requestO
1943
2001
  if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
1944
2002
  params = mapGenerateContentRequest(params);
1945
2003
  }
1946
- return makeRequest(model, Task.STREAM_GENERATE_CONTENT, apiSettings,
1947
- /* stream */ true, JSON.stringify(params), requestOptions);
2004
+ return makeRequest({
2005
+ task: "streamGenerateContent" /* Task.STREAM_GENERATE_CONTENT */,
2006
+ model,
2007
+ apiSettings,
2008
+ stream: true,
2009
+ requestOptions
2010
+ }, JSON.stringify(params));
1948
2011
  }
1949
2012
  async function generateContentStream(apiSettings, model, params, chromeAdapter, requestOptions) {
1950
2013
  const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContentStream(params), () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions));
@@ -1954,8 +2017,37 @@ async function generateContentOnCloud(apiSettings, model, params, requestOptions
1954
2017
  if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
1955
2018
  params = mapGenerateContentRequest(params);
1956
2019
  }
1957
- return makeRequest(model, Task.GENERATE_CONTENT, apiSettings,
1958
- /* stream */ false, JSON.stringify(params), requestOptions);
2020
+ return makeRequest({
2021
+ model,
2022
+ task: "generateContent" /* Task.GENERATE_CONTENT */,
2023
+ apiSettings,
2024
+ stream: false,
2025
+ requestOptions
2026
+ }, JSON.stringify(params));
2027
+ }
2028
+ async function templateGenerateContent(apiSettings, templateId, templateParams, requestOptions) {
2029
+ const response = await makeRequest({
2030
+ task: "templateGenerateContent" /* ServerPromptTemplateTask.TEMPLATE_GENERATE_CONTENT */,
2031
+ templateId,
2032
+ apiSettings,
2033
+ stream: false,
2034
+ requestOptions
2035
+ }, JSON.stringify(templateParams));
2036
+ const generateContentResponse = await processGenerateContentResponse(response, apiSettings);
2037
+ const enhancedResponse = createEnhancedContentResponse(generateContentResponse);
2038
+ return {
2039
+ response: enhancedResponse
2040
+ };
2041
+ }
2042
+ async function templateGenerateContentStream(apiSettings, templateId, templateParams, requestOptions) {
2043
+ const response = await makeRequest({
2044
+ task: "templateStreamGenerateContent" /* ServerPromptTemplateTask.TEMPLATE_STREAM_GENERATE_CONTENT */,
2045
+ templateId,
2046
+ apiSettings,
2047
+ stream: true,
2048
+ requestOptions
2049
+ }, JSON.stringify(templateParams));
2050
+ return processStream(response, apiSettings);
1959
2051
  }
1960
2052
  async function generateContent(apiSettings, model, params, chromeAdapter, requestOptions) {
1961
2053
  const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContent(params), () => generateContentOnCloud(apiSettings, model, params, requestOptions));
@@ -2367,7 +2459,13 @@ async function countTokensOnCloud(apiSettings, model, params, requestOptions) {
2367
2459
  else {
2368
2460
  body = JSON.stringify(params);
2369
2461
  }
2370
- const response = await makeRequest(model, Task.COUNT_TOKENS, apiSettings, false, body, requestOptions);
2462
+ const response = await makeRequest({
2463
+ model,
2464
+ task: "countTokens" /* Task.COUNT_TOKENS */,
2465
+ apiSettings,
2466
+ stream: false,
2467
+ requestOptions
2468
+ }, body);
2371
2469
  return response.json();
2372
2470
  }
2373
2471
  async function countTokens(apiSettings, model, params, chromeAdapter, requestOptions) {
@@ -2920,8 +3018,13 @@ class ImagenModel extends AIModel {
2920
3018
  ...this.generationConfig,
2921
3019
  ...this.safetySettings
2922
3020
  });
2923
- const response = await makeRequest(this.model, Task.PREDICT, this._apiSettings,
2924
- /* stream */ false, JSON.stringify(body), this.requestOptions);
3021
+ const response = await makeRequest({
3022
+ task: "predict" /* Task.PREDICT */,
3023
+ model: this.model,
3024
+ apiSettings: this._apiSettings,
3025
+ stream: false,
3026
+ requestOptions: this.requestOptions
3027
+ }, JSON.stringify(body));
2925
3028
  return handlePredictResponse(response);
2926
3029
  }
2927
3030
  /**
@@ -2949,8 +3052,13 @@ class ImagenModel extends AIModel {
2949
3052
  ...this.generationConfig,
2950
3053
  ...this.safetySettings
2951
3054
  });
2952
- const response = await makeRequest(this.model, Task.PREDICT, this._apiSettings,
2953
- /* stream */ false, JSON.stringify(body), this.requestOptions);
3055
+ const response = await makeRequest({
3056
+ task: "predict" /* Task.PREDICT */,
3057
+ model: this.model,
3058
+ apiSettings: this._apiSettings,
3059
+ stream: false,
3060
+ requestOptions: this.requestOptions
3061
+ }, JSON.stringify(body));
2954
3062
  return handlePredictResponse(response);
2955
3063
  }
2956
3064
  }
@@ -3102,6 +3210,121 @@ class WebSocketHandlerImpl {
3102
3210
  }
3103
3211
  }
3104
3212
 
3213
+ /**
3214
+ * @license
3215
+ * Copyright 2025 Google LLC
3216
+ *
3217
+ * Licensed under the Apache License, Version 2.0 (the "License");
3218
+ * you may not use this file except in compliance with the License.
3219
+ * You may obtain a copy of the License at
3220
+ *
3221
+ * http://www.apache.org/licenses/LICENSE-2.0
3222
+ *
3223
+ * Unless required by applicable law or agreed to in writing, software
3224
+ * distributed under the License is distributed on an "AS IS" BASIS,
3225
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3226
+ * See the License for the specific language governing permissions and
3227
+ * limitations under the License.
3228
+ */
3229
+ /**
3230
+ * {@link GenerativeModel} APIs that execute on a server-side template.
3231
+ *
3232
+ * This class should only be instantiated with {@link getTemplateGenerativeModel}.
3233
+ *
3234
+ * @beta
3235
+ */
3236
+ class TemplateGenerativeModel {
3237
+ /**
3238
+ * @hideconstructor
3239
+ */
3240
+ constructor(ai, requestOptions) {
3241
+ this.requestOptions = requestOptions || {};
3242
+ this._apiSettings = initApiSettings(ai);
3243
+ }
3244
+ /**
3245
+ * Makes a single non-streaming call to the model and returns an object
3246
+ * containing a single {@link GenerateContentResponse}.
3247
+ *
3248
+ * @param templateId - The ID of the server-side template to execute.
3249
+ * @param templateVariables - A key-value map of variables to populate the
3250
+ * template with.
3251
+ *
3252
+ * @beta
3253
+ */
3254
+ async generateContent(templateId, templateVariables // anything!
3255
+ ) {
3256
+ return templateGenerateContent(this._apiSettings, templateId, { inputs: templateVariables }, this.requestOptions);
3257
+ }
3258
+ /**
3259
+ * Makes a single streaming call to the model and returns an object
3260
+ * containing an iterable stream that iterates over all chunks in the
3261
+ * streaming response as well as a promise that returns the final aggregated
3262
+ * response.
3263
+ *
3264
+ * @param templateId - The ID of the server-side template to execute.
3265
+ * @param templateVariables - A key-value map of variables to populate the
3266
+ * template with.
3267
+ *
3268
+ * @beta
3269
+ */
3270
+ async generateContentStream(templateId, templateVariables) {
3271
+ return templateGenerateContentStream(this._apiSettings, templateId, { inputs: templateVariables }, this.requestOptions);
3272
+ }
3273
+ }
3274
+
3275
+ /**
3276
+ * @license
3277
+ * Copyright 2025 Google LLC
3278
+ *
3279
+ * Licensed under the Apache License, Version 2.0 (the "License");
3280
+ * you may not use this file except in compliance with the License.
3281
+ * You may obtain a copy of the License at
3282
+ *
3283
+ * http://www.apache.org/licenses/LICENSE-2.0
3284
+ *
3285
+ * Unless required by applicable law or agreed to in writing, software
3286
+ * distributed under the License is distributed on an "AS IS" BASIS,
3287
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
3288
+ * See the License for the specific language governing permissions and
3289
+ * limitations under the License.
3290
+ */
3291
+ /**
3292
+ * Class for Imagen model APIs that execute on a server-side template.
3293
+ *
3294
+ * This class should only be instantiated with {@link getTemplateImagenModel}.
3295
+ *
3296
+ * @beta
3297
+ */
3298
+ class TemplateImagenModel {
3299
+ /**
3300
+ * @hideconstructor
3301
+ */
3302
+ constructor(ai, requestOptions) {
3303
+ this.requestOptions = requestOptions || {};
3304
+ this._apiSettings = initApiSettings(ai);
3305
+ }
3306
+ /**
3307
+ * Makes a single call to the model and returns an object containing a single
3308
+ * {@link ImagenGenerationResponse}.
3309
+ *
3310
+ * @param templateId - The ID of the server-side template to execute.
3311
+ * @param templateVariables - A key-value map of variables to populate the
3312
+ * template with.
3313
+ *
3314
+ * @beta
3315
+ */
3316
+ async generateImages(templateId, templateVariables) {
3317
+ const response = await makeRequest({
3318
+ task: "templatePredict" /* ServerPromptTemplateTask.TEMPLATE_PREDICT */,
3319
+ templateId,
3320
+ apiSettings: this._apiSettings,
3321
+ stream: false,
3322
+ requestOptions: this.requestOptions
3323
+ }, JSON.stringify({ inputs: templateVariables }));
3324
+ return handlePredictResponse(response);
3325
+ }
3326
+ }
3327
+
3105
3328
  /**
3106
3329
  * @license
3107
3330
  * Copyright 2024 Google LLC
@@ -3893,6 +4116,30 @@ function getLiveGenerativeModel(ai, modelParams) {
3893
4116
  const webSocketHandler = new WebSocketHandlerImpl();
3894
4117
  return new LiveGenerativeModel(ai, modelParams, webSocketHandler);
3895
4118
  }
4119
+ /**
4120
+ * Returns a {@link TemplateGenerativeModel} class for executing server-side
4121
+ * templates.
4122
+ *
4123
+ * @param ai - An {@link AI} instance.
4124
+ * @param requestOptions - Additional options to use when making requests.
4125
+ *
4126
+ * @beta
4127
+ */
4128
+ function getTemplateGenerativeModel(ai, requestOptions) {
4129
+ return new TemplateGenerativeModel(ai, requestOptions);
4130
+ }
4131
+ /**
4132
+ * Returns a {@link TemplateImagenModel} class for executing server-side
4133
+ * Imagen templates.
4134
+ *
4135
+ * @param ai - An {@link AI} instance.
4136
+ * @param requestOptions - Additional options to use when making requests.
4137
+ *
4138
+ * @beta
4139
+ */
4140
+ function getTemplateImagenModel(ai, requestOptions) {
4141
+ return new TemplateImagenModel(ai, requestOptions);
4142
+ }
3896
4143
 
3897
4144
  /**
3898
4145
  * The Firebase AI Web SDK.
@@ -3900,22 +4147,12 @@ function getLiveGenerativeModel(ai, modelParams) {
3900
4147
  * @packageDocumentation
3901
4148
  */
3902
4149
  function registerAI() {
3903
- _registerComponent(new Component(AI_TYPE, (container, { instanceIdentifier }) => {
3904
- if (!instanceIdentifier) {
3905
- throw new AIError(AIErrorCode.ERROR, 'AIService instance identifier is undefined.');
3906
- }
3907
- const backend = decodeInstanceIdentifier(instanceIdentifier);
3908
- // getImmediate for FirebaseApp will always succeed
3909
- const app = container.getProvider('app').getImmediate();
3910
- const auth = container.getProvider('auth-internal');
3911
- const appCheckProvider = container.getProvider('app-check-internal');
3912
- return new AIService(app, backend, auth, appCheckProvider);
3913
- }, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
4150
+ _registerComponent(new Component(AI_TYPE, factory, "PUBLIC" /* ComponentType.PUBLIC */).setMultipleInstances(true));
3914
4151
  registerVersion(name, version, 'node');
3915
4152
  // BUILD_TARGET will be replaced by values like esm, cjs, etc during the compilation
3916
4153
  registerVersion(name, version, 'esm2020');
3917
4154
  }
3918
4155
  registerAI();
3919
4156
 
3920
- export { AIError, AIErrorCode, AIModel, AnyOfSchema, ArraySchema, Backend, BackendType, BlockReason, BooleanSchema, ChatSession, FinishReason, FunctionCallingMode, GenerativeModel, GoogleAIBackend, HarmBlockMethod, HarmBlockThreshold, HarmCategory, HarmProbability, HarmSeverity, ImagenAspectRatio, ImagenImageFormat, ImagenModel, ImagenPersonFilterLevel, ImagenSafetyFilterLevel, InferenceMode, InferenceSource, IntegerSchema, Language, LiveGenerativeModel, LiveResponseType, LiveSession, Modality, NumberSchema, ObjectSchema, Outcome, POSSIBLE_ROLES, ResponseModality, Schema, SchemaType, StringSchema, URLRetrievalStatus, VertexAIBackend, getAI, getGenerativeModel, getImagenModel, getLiveGenerativeModel, startAudioConversation };
4157
+ export { AIError, AIErrorCode, AIModel, AnyOfSchema, ArraySchema, Backend, BackendType, BlockReason, BooleanSchema, ChatSession, FinishReason, FunctionCallingMode, GenerativeModel, GoogleAIBackend, HarmBlockMethod, HarmBlockThreshold, HarmCategory, HarmProbability, HarmSeverity, ImagenAspectRatio, ImagenImageFormat, ImagenModel, ImagenPersonFilterLevel, ImagenSafetyFilterLevel, InferenceMode, InferenceSource, IntegerSchema, Language, LiveGenerativeModel, LiveResponseType, LiveSession, Modality, NumberSchema, ObjectSchema, Outcome, POSSIBLE_ROLES, ResponseModality, Schema, SchemaType, StringSchema, TemplateGenerativeModel, TemplateImagenModel, URLRetrievalStatus, VertexAIBackend, getAI, getGenerativeModel, getImagenModel, getLiveGenerativeModel, getTemplateGenerativeModel, getTemplateImagenModel, startAudioConversation };
3921
4158
  //# sourceMappingURL=index.node.mjs.map