@firebase/ai 2.4.0 → 2.5.0-canary.0800a8bed
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 +134 -9
- package/dist/ai.d.ts +137 -9
- package/dist/esm/index.esm.js +202 -68
- package/dist/esm/index.esm.js.map +1 -1
- package/dist/esm/src/factory-node.d.ts +19 -0
- package/dist/esm/src/methods/chrome-adapter.d.ts +1 -1
- package/dist/esm/src/methods/live-session.d.ts +64 -9
- package/dist/esm/src/requests/hybrid-helpers.d.ts +7 -2
- package/dist/esm/src/requests/response-helpers.d.ts +2 -2
- package/dist/esm/src/requests/stream-reader.d.ts +2 -1
- package/dist/esm/src/service.d.ts +3 -4
- package/dist/esm/src/types/chrome-adapter.d.ts +5 -0
- package/dist/esm/src/types/enums.d.ts +15 -0
- package/dist/esm/src/types/live-responses.d.ts +21 -3
- package/dist/esm/src/types/requests.d.ts +23 -0
- package/dist/esm/src/types/responses.d.ts +28 -1
- package/dist/index.cjs.js +202 -67
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.node.cjs.js +306 -166
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +306 -167
- package/dist/index.node.mjs.map +1 -1
- package/dist/src/factory-node.d.ts +19 -0
- package/dist/src/methods/chrome-adapter.d.ts +1 -1
- package/dist/src/methods/live-session.d.ts +64 -9
- package/dist/src/requests/hybrid-helpers.d.ts +7 -2
- package/dist/src/requests/response-helpers.d.ts +2 -2
- package/dist/src/requests/stream-reader.d.ts +2 -1
- package/dist/src/service.d.ts +3 -4
- package/dist/src/types/chrome-adapter.d.ts +5 -0
- package/dist/src/types/enums.d.ts +15 -0
- package/dist/src/types/live-responses.d.ts +21 -3
- package/dist/src/types/requests.d.ts +23 -0
- package/dist/src/types/responses.d.ts +28 -1
- package/package.json +8 -8
package/dist/esm/index.esm.js
CHANGED
|
@@ -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.
|
|
7
|
+
var version = "2.5.0-canary.0800a8bed";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @license
|
|
@@ -379,6 +379,15 @@ const InferenceMode = {
|
|
|
379
379
|
'ONLY_IN_CLOUD': 'only_in_cloud',
|
|
380
380
|
'PREFER_IN_CLOUD': 'prefer_in_cloud'
|
|
381
381
|
};
|
|
382
|
+
/**
|
|
383
|
+
* Indicates whether inference happened on-device or in-cloud.
|
|
384
|
+
*
|
|
385
|
+
* @beta
|
|
386
|
+
*/
|
|
387
|
+
const InferenceSource = {
|
|
388
|
+
'ON_DEVICE': 'on_device',
|
|
389
|
+
'IN_CLOUD': 'in_cloud'
|
|
390
|
+
};
|
|
382
391
|
/**
|
|
383
392
|
* Represents the result of the code execution.
|
|
384
393
|
*
|
|
@@ -888,22 +897,35 @@ var Availability;
|
|
|
888
897
|
* See the License for the specific language governing permissions and
|
|
889
898
|
* limitations under the License.
|
|
890
899
|
*/
|
|
900
|
+
// Defaults to support image inputs for convenience.
|
|
901
|
+
const defaultExpectedInputs = [{ type: 'image' }];
|
|
891
902
|
/**
|
|
892
903
|
* Defines an inference "backend" that uses Chrome's on-device model,
|
|
893
904
|
* and encapsulates logic for detecting when on-device inference is
|
|
894
905
|
* possible.
|
|
895
906
|
*/
|
|
896
907
|
class ChromeAdapterImpl {
|
|
897
|
-
constructor(languageModelProvider, mode, onDeviceParams
|
|
898
|
-
createOptions: {
|
|
899
|
-
// Defaults to support image inputs for convenience.
|
|
900
|
-
expectedInputs: [{ type: 'image' }]
|
|
901
|
-
}
|
|
902
|
-
}) {
|
|
908
|
+
constructor(languageModelProvider, mode, onDeviceParams) {
|
|
903
909
|
this.languageModelProvider = languageModelProvider;
|
|
904
910
|
this.mode = mode;
|
|
905
|
-
this.onDeviceParams = onDeviceParams;
|
|
906
911
|
this.isDownloading = false;
|
|
912
|
+
this.onDeviceParams = {
|
|
913
|
+
createOptions: {
|
|
914
|
+
expectedInputs: defaultExpectedInputs
|
|
915
|
+
}
|
|
916
|
+
};
|
|
917
|
+
if (onDeviceParams) {
|
|
918
|
+
this.onDeviceParams = onDeviceParams;
|
|
919
|
+
if (!this.onDeviceParams.createOptions) {
|
|
920
|
+
this.onDeviceParams.createOptions = {
|
|
921
|
+
expectedInputs: defaultExpectedInputs
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
else if (!this.onDeviceParams.createOptions.expectedInputs) {
|
|
925
|
+
this.onDeviceParams.createOptions.expectedInputs =
|
|
926
|
+
defaultExpectedInputs;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
907
929
|
}
|
|
908
930
|
/**
|
|
909
931
|
* Checks if a given request can be made on-device.
|
|
@@ -1592,7 +1614,7 @@ function hasValidCandidates(response) {
|
|
|
1592
1614
|
* Creates an EnhancedGenerateContentResponse object that has helper functions and
|
|
1593
1615
|
* other modifications that improve usability.
|
|
1594
1616
|
*/
|
|
1595
|
-
function createEnhancedContentResponse(response) {
|
|
1617
|
+
function createEnhancedContentResponse(response, inferenceSource = InferenceSource.IN_CLOUD) {
|
|
1596
1618
|
/**
|
|
1597
1619
|
* The Vertex AI backend omits default values.
|
|
1598
1620
|
* This causes the `index` property to be omitted from the first candidate in the
|
|
@@ -1603,6 +1625,7 @@ function createEnhancedContentResponse(response) {
|
|
|
1603
1625
|
response.candidates[0].index = 0;
|
|
1604
1626
|
}
|
|
1605
1627
|
const responseWithHelpers = addHelpers(response);
|
|
1628
|
+
responseWithHelpers.inferenceSource = inferenceSource;
|
|
1606
1629
|
return responseWithHelpers;
|
|
1607
1630
|
}
|
|
1608
1631
|
/**
|
|
@@ -1979,16 +2002,16 @@ const responseLineRE = /^data\: (.*)(?:\n\n|\r\r|\r\n\r\n)/;
|
|
|
1979
2002
|
*
|
|
1980
2003
|
* @param response - Response from a fetch call
|
|
1981
2004
|
*/
|
|
1982
|
-
function processStream(response, apiSettings) {
|
|
2005
|
+
function processStream(response, apiSettings, inferenceSource) {
|
|
1983
2006
|
const inputStream = response.body.pipeThrough(new TextDecoderStream('utf8', { fatal: true }));
|
|
1984
2007
|
const responseStream = getResponseStream(inputStream);
|
|
1985
2008
|
const [stream1, stream2] = responseStream.tee();
|
|
1986
2009
|
return {
|
|
1987
|
-
stream: generateResponseSequence(stream1, apiSettings),
|
|
1988
|
-
response: getResponsePromise(stream2, apiSettings)
|
|
2010
|
+
stream: generateResponseSequence(stream1, apiSettings, inferenceSource),
|
|
2011
|
+
response: getResponsePromise(stream2, apiSettings, inferenceSource)
|
|
1989
2012
|
};
|
|
1990
2013
|
}
|
|
1991
|
-
async function getResponsePromise(stream, apiSettings) {
|
|
2014
|
+
async function getResponsePromise(stream, apiSettings, inferenceSource) {
|
|
1992
2015
|
const allResponses = [];
|
|
1993
2016
|
const reader = stream.getReader();
|
|
1994
2017
|
while (true) {
|
|
@@ -1998,12 +2021,12 @@ async function getResponsePromise(stream, apiSettings) {
|
|
|
1998
2021
|
if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
|
|
1999
2022
|
generateContentResponse = mapGenerateContentResponse(generateContentResponse);
|
|
2000
2023
|
}
|
|
2001
|
-
return createEnhancedContentResponse(generateContentResponse);
|
|
2024
|
+
return createEnhancedContentResponse(generateContentResponse, inferenceSource);
|
|
2002
2025
|
}
|
|
2003
2026
|
allResponses.push(value);
|
|
2004
2027
|
}
|
|
2005
2028
|
}
|
|
2006
|
-
async function* generateResponseSequence(stream, apiSettings) {
|
|
2029
|
+
async function* generateResponseSequence(stream, apiSettings, inferenceSource) {
|
|
2007
2030
|
const reader = stream.getReader();
|
|
2008
2031
|
while (true) {
|
|
2009
2032
|
const { value, done } = await reader.read();
|
|
@@ -2012,10 +2035,10 @@ async function* generateResponseSequence(stream, apiSettings) {
|
|
|
2012
2035
|
}
|
|
2013
2036
|
let enhancedResponse;
|
|
2014
2037
|
if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
|
|
2015
|
-
enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value));
|
|
2038
|
+
enhancedResponse = createEnhancedContentResponse(mapGenerateContentResponse(value), inferenceSource);
|
|
2016
2039
|
}
|
|
2017
2040
|
else {
|
|
2018
|
-
enhancedResponse = createEnhancedContentResponse(value);
|
|
2041
|
+
enhancedResponse = createEnhancedContentResponse(value, inferenceSource);
|
|
2019
2042
|
}
|
|
2020
2043
|
const firstCandidate = enhancedResponse.candidates?.[0];
|
|
2021
2044
|
// Don't yield a response with no useful data for the developer.
|
|
@@ -2185,31 +2208,52 @@ const errorsCausingFallback = [
|
|
|
2185
2208
|
*/
|
|
2186
2209
|
async function callCloudOrDevice(request, chromeAdapter, onDeviceCall, inCloudCall) {
|
|
2187
2210
|
if (!chromeAdapter) {
|
|
2188
|
-
return
|
|
2211
|
+
return {
|
|
2212
|
+
response: await inCloudCall(),
|
|
2213
|
+
inferenceSource: InferenceSource.IN_CLOUD
|
|
2214
|
+
};
|
|
2189
2215
|
}
|
|
2190
2216
|
switch (chromeAdapter.mode) {
|
|
2191
2217
|
case InferenceMode.ONLY_ON_DEVICE:
|
|
2192
2218
|
if (await chromeAdapter.isAvailable(request)) {
|
|
2193
|
-
return
|
|
2219
|
+
return {
|
|
2220
|
+
response: await onDeviceCall(),
|
|
2221
|
+
inferenceSource: InferenceSource.ON_DEVICE
|
|
2222
|
+
};
|
|
2194
2223
|
}
|
|
2195
2224
|
throw new AIError(AIErrorCode.UNSUPPORTED, 'Inference mode is ONLY_ON_DEVICE, but an on-device model is not available.');
|
|
2196
2225
|
case InferenceMode.ONLY_IN_CLOUD:
|
|
2197
|
-
return
|
|
2226
|
+
return {
|
|
2227
|
+
response: await inCloudCall(),
|
|
2228
|
+
inferenceSource: InferenceSource.IN_CLOUD
|
|
2229
|
+
};
|
|
2198
2230
|
case InferenceMode.PREFER_IN_CLOUD:
|
|
2199
2231
|
try {
|
|
2200
|
-
return
|
|
2232
|
+
return {
|
|
2233
|
+
response: await inCloudCall(),
|
|
2234
|
+
inferenceSource: InferenceSource.IN_CLOUD
|
|
2235
|
+
};
|
|
2201
2236
|
}
|
|
2202
2237
|
catch (e) {
|
|
2203
2238
|
if (e instanceof AIError && errorsCausingFallback.includes(e.code)) {
|
|
2204
|
-
return
|
|
2239
|
+
return {
|
|
2240
|
+
response: await onDeviceCall(),
|
|
2241
|
+
inferenceSource: InferenceSource.ON_DEVICE
|
|
2242
|
+
};
|
|
2205
2243
|
}
|
|
2206
2244
|
throw e;
|
|
2207
2245
|
}
|
|
2208
2246
|
case InferenceMode.PREFER_ON_DEVICE:
|
|
2209
2247
|
if (await chromeAdapter.isAvailable(request)) {
|
|
2210
|
-
return
|
|
2248
|
+
return {
|
|
2249
|
+
response: await onDeviceCall(),
|
|
2250
|
+
inferenceSource: InferenceSource.ON_DEVICE
|
|
2251
|
+
};
|
|
2211
2252
|
}
|
|
2212
|
-
return
|
|
2253
|
+
return {
|
|
2254
|
+
response: await inCloudCall(),
|
|
2255
|
+
inferenceSource: InferenceSource.IN_CLOUD
|
|
2256
|
+
};
|
|
2213
2257
|
default:
|
|
2214
2258
|
throw new AIError(AIErrorCode.ERROR, `Unexpected infererence mode: ${chromeAdapter.mode}`);
|
|
2215
2259
|
}
|
|
@@ -2239,8 +2283,8 @@ async function generateContentStreamOnCloud(apiSettings, model, params, requestO
|
|
|
2239
2283
|
/* stream */ true, JSON.stringify(params), requestOptions);
|
|
2240
2284
|
}
|
|
2241
2285
|
async function generateContentStream(apiSettings, model, params, chromeAdapter, requestOptions) {
|
|
2242
|
-
const
|
|
2243
|
-
return processStream(response, apiSettings); // TODO: Map streaming responses
|
|
2286
|
+
const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContentStream(params), () => generateContentStreamOnCloud(apiSettings, model, params, requestOptions));
|
|
2287
|
+
return processStream(callResult.response, apiSettings); // TODO: Map streaming responses
|
|
2244
2288
|
}
|
|
2245
2289
|
async function generateContentOnCloud(apiSettings, model, params, requestOptions) {
|
|
2246
2290
|
if (apiSettings.backend.backendType === BackendType.GOOGLE_AI) {
|
|
@@ -2250,9 +2294,9 @@ async function generateContentOnCloud(apiSettings, model, params, requestOptions
|
|
|
2250
2294
|
/* stream */ false, JSON.stringify(params), requestOptions);
|
|
2251
2295
|
}
|
|
2252
2296
|
async function generateContent(apiSettings, model, params, chromeAdapter, requestOptions) {
|
|
2253
|
-
const
|
|
2254
|
-
const generateContentResponse = await processGenerateContentResponse(response, apiSettings);
|
|
2255
|
-
const enhancedResponse = createEnhancedContentResponse(generateContentResponse);
|
|
2297
|
+
const callResult = await callCloudOrDevice(params, chromeAdapter, () => chromeAdapter.generateContent(params), () => generateContentOnCloud(apiSettings, model, params, requestOptions));
|
|
2298
|
+
const generateContentResponse = await processGenerateContentResponse(callResult.response, apiSettings);
|
|
2299
|
+
const enhancedResponse = createEnhancedContentResponse(generateContentResponse, callResult.inferenceSource);
|
|
2256
2300
|
return {
|
|
2257
2301
|
response: enhancedResponse
|
|
2258
2302
|
};
|
|
@@ -2826,75 +2870,104 @@ class LiveSession {
|
|
|
2826
2870
|
this.webSocketHandler.send(JSON.stringify(message));
|
|
2827
2871
|
}
|
|
2828
2872
|
/**
|
|
2829
|
-
* Sends
|
|
2873
|
+
* Sends text to the server in realtime.
|
|
2830
2874
|
*
|
|
2831
|
-
* @
|
|
2875
|
+
* @example
|
|
2876
|
+
* ```javascript
|
|
2877
|
+
* liveSession.sendTextRealtime("Hello, how are you?");
|
|
2878
|
+
* ```
|
|
2879
|
+
*
|
|
2880
|
+
* @param text - The text data to send.
|
|
2832
2881
|
* @throws If this session has been closed.
|
|
2833
2882
|
*
|
|
2834
2883
|
* @beta
|
|
2835
2884
|
*/
|
|
2836
|
-
async
|
|
2885
|
+
async sendTextRealtime(text) {
|
|
2837
2886
|
if (this.isClosed) {
|
|
2838
2887
|
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
2839
2888
|
}
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
this.webSocketHandler.send(JSON.stringify(message));
|
|
2847
|
-
});
|
|
2889
|
+
const message = {
|
|
2890
|
+
realtimeInput: {
|
|
2891
|
+
text
|
|
2892
|
+
}
|
|
2893
|
+
};
|
|
2894
|
+
this.webSocketHandler.send(JSON.stringify(message));
|
|
2848
2895
|
}
|
|
2849
2896
|
/**
|
|
2850
|
-
* Sends
|
|
2897
|
+
* Sends audio data to the server in realtime.
|
|
2851
2898
|
*
|
|
2852
|
-
* @
|
|
2899
|
+
* @remarks The server requires that the audio data is base64-encoded 16-bit PCM at 16kHz
|
|
2900
|
+
* little-endian.
|
|
2901
|
+
*
|
|
2902
|
+
* @example
|
|
2903
|
+
* ```javascript
|
|
2904
|
+
* // const pcmData = ... base64-encoded 16-bit PCM at 16kHz little-endian.
|
|
2905
|
+
* const blob = { mimeType: "audio/pcm", data: pcmData };
|
|
2906
|
+
* liveSession.sendAudioRealtime(blob);
|
|
2907
|
+
* ```
|
|
2908
|
+
*
|
|
2909
|
+
* @param blob - The base64-encoded PCM data to send to the server in realtime.
|
|
2853
2910
|
* @throws If this session has been closed.
|
|
2854
2911
|
*
|
|
2855
2912
|
* @beta
|
|
2856
2913
|
*/
|
|
2857
|
-
async
|
|
2914
|
+
async sendAudioRealtime(blob) {
|
|
2858
2915
|
if (this.isClosed) {
|
|
2859
2916
|
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
2860
2917
|
}
|
|
2861
2918
|
const message = {
|
|
2862
|
-
|
|
2863
|
-
|
|
2919
|
+
realtimeInput: {
|
|
2920
|
+
audio: blob
|
|
2864
2921
|
}
|
|
2865
2922
|
};
|
|
2866
2923
|
this.webSocketHandler.send(JSON.stringify(message));
|
|
2867
2924
|
}
|
|
2868
2925
|
/**
|
|
2869
|
-
* Sends
|
|
2926
|
+
* Sends video data to the server in realtime.
|
|
2870
2927
|
*
|
|
2871
|
-
* @
|
|
2928
|
+
* @remarks The server requires that the video is sent as individual video frames at 1 FPS. It
|
|
2929
|
+
* is recommended to set `mimeType` to `image/jpeg`.
|
|
2930
|
+
*
|
|
2931
|
+
* @example
|
|
2932
|
+
* ```javascript
|
|
2933
|
+
* // const videoFrame = ... base64-encoded JPEG data
|
|
2934
|
+
* const blob = { mimeType: "image/jpeg", data: videoFrame };
|
|
2935
|
+
* liveSession.sendVideoRealtime(blob);
|
|
2936
|
+
* ```
|
|
2937
|
+
* @param blob - The base64-encoded video data to send to the server in realtime.
|
|
2872
2938
|
* @throws If this session has been closed.
|
|
2873
2939
|
*
|
|
2874
2940
|
* @beta
|
|
2875
2941
|
*/
|
|
2876
|
-
async
|
|
2942
|
+
async sendVideoRealtime(blob) {
|
|
2877
2943
|
if (this.isClosed) {
|
|
2878
2944
|
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
2879
2945
|
}
|
|
2880
|
-
const
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
const { done, value } = await reader.read();
|
|
2884
|
-
if (done) {
|
|
2885
|
-
break;
|
|
2886
|
-
}
|
|
2887
|
-
else if (!value) {
|
|
2888
|
-
throw new Error('Missing chunk in reader, but reader is not done.');
|
|
2889
|
-
}
|
|
2890
|
-
await this.sendMediaChunks([value]);
|
|
2891
|
-
}
|
|
2892
|
-
catch (e) {
|
|
2893
|
-
// Re-throw any errors that occur during stream consumption or sending.
|
|
2894
|
-
const message = e instanceof Error ? e.message : 'Error processing media stream.';
|
|
2895
|
-
throw new AIError(AIErrorCode.REQUEST_ERROR, message);
|
|
2946
|
+
const message = {
|
|
2947
|
+
realtimeInput: {
|
|
2948
|
+
video: blob
|
|
2896
2949
|
}
|
|
2950
|
+
};
|
|
2951
|
+
this.webSocketHandler.send(JSON.stringify(message));
|
|
2952
|
+
}
|
|
2953
|
+
/**
|
|
2954
|
+
* Sends function responses to the server.
|
|
2955
|
+
*
|
|
2956
|
+
* @param functionResponses - The function responses to send.
|
|
2957
|
+
* @throws If this session has been closed.
|
|
2958
|
+
*
|
|
2959
|
+
* @beta
|
|
2960
|
+
*/
|
|
2961
|
+
async sendFunctionResponses(functionResponses) {
|
|
2962
|
+
if (this.isClosed) {
|
|
2963
|
+
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
2897
2964
|
}
|
|
2965
|
+
const message = {
|
|
2966
|
+
toolResponse: {
|
|
2967
|
+
functionResponses
|
|
2968
|
+
}
|
|
2969
|
+
};
|
|
2970
|
+
this.webSocketHandler.send(JSON.stringify(message));
|
|
2898
2971
|
}
|
|
2899
2972
|
/**
|
|
2900
2973
|
* Yields messages received from the server.
|
|
@@ -2952,6 +3025,62 @@ class LiveSession {
|
|
|
2952
3025
|
await this.webSocketHandler.close(1000, 'Client closed session.');
|
|
2953
3026
|
}
|
|
2954
3027
|
}
|
|
3028
|
+
/**
|
|
3029
|
+
* Sends realtime input to the server.
|
|
3030
|
+
*
|
|
3031
|
+
* @deprecated Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead.
|
|
3032
|
+
*
|
|
3033
|
+
* @param mediaChunks - The media chunks to send.
|
|
3034
|
+
* @throws If this session has been closed.
|
|
3035
|
+
*
|
|
3036
|
+
* @beta
|
|
3037
|
+
*/
|
|
3038
|
+
async sendMediaChunks(mediaChunks) {
|
|
3039
|
+
if (this.isClosed) {
|
|
3040
|
+
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
3041
|
+
}
|
|
3042
|
+
// The backend does not support sending more than one mediaChunk in one message.
|
|
3043
|
+
// Work around this limitation by sending mediaChunks in separate messages.
|
|
3044
|
+
mediaChunks.forEach(mediaChunk => {
|
|
3045
|
+
const message = {
|
|
3046
|
+
realtimeInput: { mediaChunks: [mediaChunk] }
|
|
3047
|
+
};
|
|
3048
|
+
this.webSocketHandler.send(JSON.stringify(message));
|
|
3049
|
+
});
|
|
3050
|
+
}
|
|
3051
|
+
/**
|
|
3052
|
+
* @deprecated Use `sendTextRealtime()`, `sendAudioRealtime()`, and `sendVideoRealtime()` instead.
|
|
3053
|
+
*
|
|
3054
|
+
* Sends a stream of {@link GenerativeContentBlob}.
|
|
3055
|
+
*
|
|
3056
|
+
* @param mediaChunkStream - The stream of {@link GenerativeContentBlob} to send.
|
|
3057
|
+
* @throws If this session has been closed.
|
|
3058
|
+
*
|
|
3059
|
+
* @beta
|
|
3060
|
+
*/
|
|
3061
|
+
async sendMediaStream(mediaChunkStream) {
|
|
3062
|
+
if (this.isClosed) {
|
|
3063
|
+
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
3064
|
+
}
|
|
3065
|
+
const reader = mediaChunkStream.getReader();
|
|
3066
|
+
while (true) {
|
|
3067
|
+
try {
|
|
3068
|
+
const { done, value } = await reader.read();
|
|
3069
|
+
if (done) {
|
|
3070
|
+
break;
|
|
3071
|
+
}
|
|
3072
|
+
else if (!value) {
|
|
3073
|
+
throw new Error('Missing chunk in reader, but reader is not done.');
|
|
3074
|
+
}
|
|
3075
|
+
await this.sendMediaChunks([value]);
|
|
3076
|
+
}
|
|
3077
|
+
catch (e) {
|
|
3078
|
+
// Re-throw any errors that occur during stream consumption or sending.
|
|
3079
|
+
const message = e instanceof Error ? e.message : 'Error processing media stream.';
|
|
3080
|
+
throw new AIError(AIErrorCode.REQUEST_ERROR, message);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
}
|
|
2955
3084
|
}
|
|
2956
3085
|
|
|
2957
3086
|
/**
|
|
@@ -3012,13 +3141,18 @@ class LiveGenerativeModel extends AIModel {
|
|
|
3012
3141
|
else {
|
|
3013
3142
|
fullModelPath = `projects/${this._apiSettings.project}/locations/${this._apiSettings.location}/${this.model}`;
|
|
3014
3143
|
}
|
|
3144
|
+
// inputAudioTranscription and outputAudioTranscription are on the generation config in the public API,
|
|
3145
|
+
// but the backend expects them to be in the `setup` message.
|
|
3146
|
+
const { inputAudioTranscription, outputAudioTranscription, ...generationConfig } = this.generationConfig;
|
|
3015
3147
|
const setupMessage = {
|
|
3016
3148
|
setup: {
|
|
3017
3149
|
model: fullModelPath,
|
|
3018
|
-
generationConfig
|
|
3150
|
+
generationConfig,
|
|
3019
3151
|
tools: this.tools,
|
|
3020
3152
|
toolConfig: this.toolConfig,
|
|
3021
|
-
systemInstruction: this.systemInstruction
|
|
3153
|
+
systemInstruction: this.systemInstruction,
|
|
3154
|
+
inputAudioTranscription,
|
|
3155
|
+
outputAudioTranscription
|
|
3022
3156
|
}
|
|
3023
3157
|
};
|
|
3024
3158
|
try {
|
|
@@ -3724,7 +3858,7 @@ class AudioConversationRunner {
|
|
|
3724
3858
|
mimeType: 'audio/pcm',
|
|
3725
3859
|
data: base64
|
|
3726
3860
|
};
|
|
3727
|
-
void this.liveSession.
|
|
3861
|
+
void this.liveSession.sendAudioRealtime(chunk);
|
|
3728
3862
|
};
|
|
3729
3863
|
}
|
|
3730
3864
|
/**
|
|
@@ -4109,5 +4243,5 @@ function registerAI() {
|
|
|
4109
4243
|
}
|
|
4110
4244
|
registerAI();
|
|
4111
4245
|
|
|
4112
|
-
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, IntegerSchema, Language, LiveGenerativeModel, LiveResponseType, LiveSession, Modality, NumberSchema, ObjectSchema, Outcome, POSSIBLE_ROLES, ResponseModality, Schema, SchemaType, StringSchema, URLRetrievalStatus, VertexAIBackend, getAI, getGenerativeModel, getImagenModel, getLiveGenerativeModel, startAudioConversation };
|
|
4246
|
+
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 };
|
|
4113
4247
|
//# sourceMappingURL=index.esm.js.map
|