@firebase/ai 2.1.0-canary.5501791d0 → 2.1.0-canary.9b63cd60e
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/ai-public.d.ts +75 -4
- package/dist/ai.d.ts +90 -5
- package/dist/esm/index.esm.js +90 -60
- package/dist/esm/index.esm.js.map +1 -1
- package/dist/esm/src/index.d.ts +3 -0
- package/dist/esm/src/models/ai-model.d.ts +1 -1
- package/dist/esm/src/public-types.d.ts +10 -1
- package/dist/esm/src/requests/response-helpers.d.ts +9 -5
- package/dist/esm/src/service.d.ts +4 -1
- package/dist/esm/src/types/content.d.ts +25 -0
- package/dist/esm/src/types/requests.d.ts +9 -0
- package/dist/esm/src/types/responses.d.ts +23 -4
- package/dist/index.cjs.js +90 -59
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.node.cjs.js +77 -48
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +77 -48
- package/dist/index.node.mjs.map +1 -1
- package/dist/src/index.d.ts +3 -0
- package/dist/src/models/ai-model.d.ts +1 -1
- package/dist/src/public-types.d.ts +10 -1
- package/dist/src/requests/response-helpers.d.ts +9 -5
- package/dist/src/service.d.ts +4 -1
- package/dist/src/types/content.d.ts +25 -0
- package/dist/src/types/requests.d.ts +9 -0
- package/dist/src/types/responses.d.ts +23 -4
- package/package.json +8 -8
package/dist/index.node.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { FirebaseError, getModularInstance } from '@firebase/util';
|
|
|
4
4
|
import { Logger } from '@firebase/logger';
|
|
5
5
|
|
|
6
6
|
var name = "@firebase/ai";
|
|
7
|
-
var version = "2.1.0-canary.
|
|
7
|
+
var version = "2.1.0-canary.9b63cd60e";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @license
|
|
@@ -653,6 +653,12 @@ class AIService {
|
|
|
653
653
|
_delete() {
|
|
654
654
|
return Promise.resolve();
|
|
655
655
|
}
|
|
656
|
+
set options(optionsToSet) {
|
|
657
|
+
this._options = optionsToSet;
|
|
658
|
+
}
|
|
659
|
+
get options() {
|
|
660
|
+
return this._options;
|
|
661
|
+
}
|
|
656
662
|
}
|
|
657
663
|
|
|
658
664
|
/**
|
|
@@ -837,7 +843,12 @@ class AIModel {
|
|
|
837
843
|
};
|
|
838
844
|
}
|
|
839
845
|
else if (ai.appCheck) {
|
|
840
|
-
|
|
846
|
+
if (ai.options?.useLimitedUseAppCheckTokens) {
|
|
847
|
+
this._apiSettings.getAppCheckToken = () => ai.appCheck.getLimitedUseToken();
|
|
848
|
+
}
|
|
849
|
+
else {
|
|
850
|
+
this._apiSettings.getAppCheckToken = () => ai.appCheck.getToken();
|
|
851
|
+
}
|
|
841
852
|
}
|
|
842
853
|
if (ai.auth) {
|
|
843
854
|
this._apiSettings.getAuthToken = () => ai.auth.getToken();
|
|
@@ -1100,6 +1111,28 @@ async function makeRequest(model, task, apiSettings, stream, body, requestOption
|
|
|
1100
1111
|
* See the License for the specific language governing permissions and
|
|
1101
1112
|
* limitations under the License.
|
|
1102
1113
|
*/
|
|
1114
|
+
/**
|
|
1115
|
+
* Check that at least one candidate exists and does not have a bad
|
|
1116
|
+
* finish reason. Warns if multiple candidates exist.
|
|
1117
|
+
*/
|
|
1118
|
+
function hasValidCandidates(response) {
|
|
1119
|
+
if (response.candidates && response.candidates.length > 0) {
|
|
1120
|
+
if (response.candidates.length > 1) {
|
|
1121
|
+
logger.warn(`This response had ${response.candidates.length} ` +
|
|
1122
|
+
`candidates. Returning text from the first candidate only. ` +
|
|
1123
|
+
`Access response.candidates directly to use the other candidates.`);
|
|
1124
|
+
}
|
|
1125
|
+
if (hadBadFinishReason(response.candidates[0])) {
|
|
1126
|
+
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Response error: ${formatBlockErrorMessage(response)}. Response body stored in error.response`, {
|
|
1127
|
+
response
|
|
1128
|
+
});
|
|
1129
|
+
}
|
|
1130
|
+
return true;
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
return false;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1103
1136
|
/**
|
|
1104
1137
|
* Creates an EnhancedGenerateContentResponse object that has helper functions and
|
|
1105
1138
|
* other modifications that improve usability.
|
|
@@ -1123,18 +1156,8 @@ function createEnhancedContentResponse(response) {
|
|
|
1123
1156
|
*/
|
|
1124
1157
|
function addHelpers(response) {
|
|
1125
1158
|
response.text = () => {
|
|
1126
|
-
if (response
|
|
1127
|
-
|
|
1128
|
-
logger.warn(`This response had ${response.candidates.length} ` +
|
|
1129
|
-
`candidates. Returning text from the first candidate only. ` +
|
|
1130
|
-
`Access response.candidates directly to use the other candidates.`);
|
|
1131
|
-
}
|
|
1132
|
-
if (hadBadFinishReason(response.candidates[0])) {
|
|
1133
|
-
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Response error: ${formatBlockErrorMessage(response)}. Response body stored in error.response`, {
|
|
1134
|
-
response
|
|
1135
|
-
});
|
|
1136
|
-
}
|
|
1137
|
-
return getText(response);
|
|
1159
|
+
if (hasValidCandidates(response)) {
|
|
1160
|
+
return getText(response, part => !part.thought);
|
|
1138
1161
|
}
|
|
1139
1162
|
else if (response.promptFeedback) {
|
|
1140
1163
|
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Text not available. ${formatBlockErrorMessage(response)}`, {
|
|
@@ -1143,18 +1166,20 @@ function addHelpers(response) {
|
|
|
1143
1166
|
}
|
|
1144
1167
|
return '';
|
|
1145
1168
|
};
|
|
1169
|
+
response.thoughtSummary = () => {
|
|
1170
|
+
if (hasValidCandidates(response)) {
|
|
1171
|
+
const result = getText(response, part => !!part.thought);
|
|
1172
|
+
return result === '' ? undefined : result;
|
|
1173
|
+
}
|
|
1174
|
+
else if (response.promptFeedback) {
|
|
1175
|
+
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Thought summary not available. ${formatBlockErrorMessage(response)}`, {
|
|
1176
|
+
response
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
return undefined;
|
|
1180
|
+
};
|
|
1146
1181
|
response.inlineDataParts = () => {
|
|
1147
|
-
if (response
|
|
1148
|
-
if (response.candidates.length > 1) {
|
|
1149
|
-
logger.warn(`This response had ${response.candidates.length} ` +
|
|
1150
|
-
`candidates. Returning data from the first candidate only. ` +
|
|
1151
|
-
`Access response.candidates directly to use the other candidates.`);
|
|
1152
|
-
}
|
|
1153
|
-
if (hadBadFinishReason(response.candidates[0])) {
|
|
1154
|
-
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Response error: ${formatBlockErrorMessage(response)}. Response body stored in error.response`, {
|
|
1155
|
-
response
|
|
1156
|
-
});
|
|
1157
|
-
}
|
|
1182
|
+
if (hasValidCandidates(response)) {
|
|
1158
1183
|
return getInlineDataParts(response);
|
|
1159
1184
|
}
|
|
1160
1185
|
else if (response.promptFeedback) {
|
|
@@ -1165,17 +1190,7 @@ function addHelpers(response) {
|
|
|
1165
1190
|
return undefined;
|
|
1166
1191
|
};
|
|
1167
1192
|
response.functionCalls = () => {
|
|
1168
|
-
if (response
|
|
1169
|
-
if (response.candidates.length > 1) {
|
|
1170
|
-
logger.warn(`This response had ${response.candidates.length} ` +
|
|
1171
|
-
`candidates. Returning function calls from the first candidate only. ` +
|
|
1172
|
-
`Access response.candidates directly to use the other candidates.`);
|
|
1173
|
-
}
|
|
1174
|
-
if (hadBadFinishReason(response.candidates[0])) {
|
|
1175
|
-
throw new AIError(AIErrorCode.RESPONSE_ERROR, `Response error: ${formatBlockErrorMessage(response)}. Response body stored in error.response`, {
|
|
1176
|
-
response
|
|
1177
|
-
});
|
|
1178
|
-
}
|
|
1193
|
+
if (hasValidCandidates(response)) {
|
|
1179
1194
|
return getFunctionCalls(response);
|
|
1180
1195
|
}
|
|
1181
1196
|
else if (response.promptFeedback) {
|
|
@@ -1188,13 +1203,17 @@ function addHelpers(response) {
|
|
|
1188
1203
|
return response;
|
|
1189
1204
|
}
|
|
1190
1205
|
/**
|
|
1191
|
-
* Returns all text
|
|
1206
|
+
* Returns all text from the first candidate's parts, filtering by whether
|
|
1207
|
+
* `partFilter()` returns true.
|
|
1208
|
+
*
|
|
1209
|
+
* @param response - The `GenerateContentResponse` from which to extract text.
|
|
1210
|
+
* @param partFilter - Only return `Part`s for which this returns true
|
|
1192
1211
|
*/
|
|
1193
|
-
function getText(response) {
|
|
1212
|
+
function getText(response, partFilter) {
|
|
1194
1213
|
const textStrings = [];
|
|
1195
1214
|
if (response.candidates?.[0].content?.parts) {
|
|
1196
1215
|
for (const part of response.candidates?.[0].content?.parts) {
|
|
1197
|
-
if (part.text) {
|
|
1216
|
+
if (part.text && partFilter(part)) {
|
|
1198
1217
|
textStrings.push(part.text);
|
|
1199
1218
|
}
|
|
1200
1219
|
}
|
|
@@ -1207,7 +1226,7 @@ function getText(response) {
|
|
|
1207
1226
|
}
|
|
1208
1227
|
}
|
|
1209
1228
|
/**
|
|
1210
|
-
* Returns {@link FunctionCall}
|
|
1229
|
+
* Returns every {@link FunctionCall} associated with first candidate.
|
|
1211
1230
|
*/
|
|
1212
1231
|
function getFunctionCalls(response) {
|
|
1213
1232
|
const functionCalls = [];
|
|
@@ -1226,7 +1245,7 @@ function getFunctionCalls(response) {
|
|
|
1226
1245
|
}
|
|
1227
1246
|
}
|
|
1228
1247
|
/**
|
|
1229
|
-
* Returns {@link InlineDataPart}
|
|
1248
|
+
* Returns every {@link InlineDataPart} in the first candidate if present.
|
|
1230
1249
|
*
|
|
1231
1250
|
* @internal
|
|
1232
1251
|
*/
|
|
@@ -1874,12 +1893,14 @@ const VALID_PART_FIELDS = [
|
|
|
1874
1893
|
'text',
|
|
1875
1894
|
'inlineData',
|
|
1876
1895
|
'functionCall',
|
|
1877
|
-
'functionResponse'
|
|
1896
|
+
'functionResponse',
|
|
1897
|
+
'thought',
|
|
1898
|
+
'thoughtSignature'
|
|
1878
1899
|
];
|
|
1879
1900
|
const VALID_PARTS_PER_ROLE = {
|
|
1880
1901
|
user: ['text', 'inlineData'],
|
|
1881
1902
|
function: ['functionResponse'],
|
|
1882
|
-
model: ['text', 'functionCall'],
|
|
1903
|
+
model: ['text', 'functionCall', 'thought', 'thoughtSignature'],
|
|
1883
1904
|
// System instructions shouldn't be in history anyway.
|
|
1884
1905
|
system: ['text']
|
|
1885
1906
|
};
|
|
@@ -1901,7 +1922,7 @@ function validateChatHistory(history) {
|
|
|
1901
1922
|
throw new AIError(AIErrorCode.INVALID_CONTENT, `Each item should include role field. Got ${role} but valid roles are: ${JSON.stringify(POSSIBLE_ROLES)}`);
|
|
1902
1923
|
}
|
|
1903
1924
|
if (!Array.isArray(parts)) {
|
|
1904
|
-
throw new AIError(AIErrorCode.INVALID_CONTENT, `Content should have 'parts'
|
|
1925
|
+
throw new AIError(AIErrorCode.INVALID_CONTENT, `Content should have 'parts' property with an array of Parts`);
|
|
1905
1926
|
}
|
|
1906
1927
|
if (parts.length === 0) {
|
|
1907
1928
|
throw new AIError(AIErrorCode.INVALID_CONTENT, `Each Content should have at least one part`);
|
|
@@ -1910,7 +1931,9 @@ function validateChatHistory(history) {
|
|
|
1910
1931
|
text: 0,
|
|
1911
1932
|
inlineData: 0,
|
|
1912
1933
|
functionCall: 0,
|
|
1913
|
-
functionResponse: 0
|
|
1934
|
+
functionResponse: 0,
|
|
1935
|
+
thought: 0,
|
|
1936
|
+
thoughtSignature: 0
|
|
1914
1937
|
};
|
|
1915
1938
|
for (const part of parts) {
|
|
1916
1939
|
for (const key of VALID_PART_FIELDS) {
|
|
@@ -2959,14 +2982,20 @@ class ImagenImageFormat {
|
|
|
2959
2982
|
*
|
|
2960
2983
|
* @public
|
|
2961
2984
|
*/
|
|
2962
|
-
function getAI(app = getApp(), options
|
|
2985
|
+
function getAI(app = getApp(), options) {
|
|
2963
2986
|
app = getModularInstance(app);
|
|
2964
2987
|
// Dependencies
|
|
2965
2988
|
const AIProvider = _getProvider(app, AI_TYPE);
|
|
2966
|
-
const
|
|
2967
|
-
|
|
2989
|
+
const backend = options?.backend ?? new GoogleAIBackend();
|
|
2990
|
+
const finalOptions = {
|
|
2991
|
+
useLimitedUseAppCheckTokens: options?.useLimitedUseAppCheckTokens ?? false
|
|
2992
|
+
};
|
|
2993
|
+
const identifier = encodeInstanceIdentifier(backend);
|
|
2994
|
+
const aiInstance = AIProvider.getImmediate({
|
|
2968
2995
|
identifier
|
|
2969
2996
|
});
|
|
2997
|
+
aiInstance.options = finalOptions;
|
|
2998
|
+
return aiInstance;
|
|
2970
2999
|
}
|
|
2971
3000
|
/**
|
|
2972
3001
|
* Returns a {@link GenerativeModel} class with methods for inference
|