@firebase/ai 2.3.0-canary.7a7634f79 → 2.3.0-canary.ccbf7ba36
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 +10 -1
- package/dist/ai.d.ts +10 -1
- package/dist/esm/index.esm.js +44 -21
- package/dist/esm/index.esm.js.map +1 -1
- package/dist/esm/src/methods/live-session-helpers.d.ts +2 -2
- package/dist/esm/src/methods/live-session.d.ts +10 -1
- package/dist/esm/src/types/live-responses.d.ts +9 -1
- package/dist/index.cjs.js +44 -21
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.node.cjs.js +44 -21
- package/dist/index.node.cjs.js.map +1 -1
- package/dist/index.node.mjs +44 -21
- package/dist/index.node.mjs.map +1 -1
- package/dist/src/methods/live-session-helpers.d.ts +2 -2
- package/dist/src/methods/live-session.d.ts +10 -1
- package/dist/src/types/live-responses.d.ts +9 -1
- package/package.json +8 -8
package/dist/index.node.mjs
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.3.0-canary.
|
|
7
|
+
var version = "2.3.0-canary.ccbf7ba36";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* @license
|
|
@@ -1592,7 +1592,7 @@ function mapGenerateContentCandidates(candidates) {
|
|
|
1592
1592
|
// videoMetadata is not supported.
|
|
1593
1593
|
// Throw early since developers may send a long video as input and only expect to pay
|
|
1594
1594
|
// for inference on a small portion of the video.
|
|
1595
|
-
if (candidate.content?.parts
|
|
1595
|
+
if (candidate.content?.parts?.some(part => part?.videoMetadata)) {
|
|
1596
1596
|
throw new AIError(AIErrorCode.UNSUPPORTED, 'Part.videoMetadata is not supported in the Gemini Developer API. Please remove this property.');
|
|
1597
1597
|
}
|
|
1598
1598
|
const mappedCandidate = {
|
|
@@ -1694,6 +1694,14 @@ async function* generateResponseSequence(stream, apiSettings) {
|
|
|
1694
1694
|
else {
|
|
1695
1695
|
enhancedResponse = createEnhancedContentResponse(value);
|
|
1696
1696
|
}
|
|
1697
|
+
const firstCandidate = enhancedResponse.candidates?.[0];
|
|
1698
|
+
// Don't yield a response with no useful data for the developer.
|
|
1699
|
+
if (!firstCandidate?.content?.parts &&
|
|
1700
|
+
!firstCandidate?.finishReason &&
|
|
1701
|
+
!firstCandidate?.citationMetadata &&
|
|
1702
|
+
!firstCandidate?.urlContextMetadata) {
|
|
1703
|
+
continue;
|
|
1704
|
+
}
|
|
1697
1705
|
yield enhancedResponse;
|
|
1698
1706
|
}
|
|
1699
1707
|
}
|
|
@@ -1788,32 +1796,28 @@ function aggregateResponses(responses) {
|
|
|
1788
1796
|
* Candidates should always have content and parts, but this handles
|
|
1789
1797
|
* possible malformed responses.
|
|
1790
1798
|
*/
|
|
1791
|
-
if (candidate.content
|
|
1799
|
+
if (candidate.content) {
|
|
1800
|
+
// Skip a candidate without parts.
|
|
1801
|
+
if (!candidate.content.parts) {
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1792
1804
|
if (!aggregatedResponse.candidates[i].content) {
|
|
1793
1805
|
aggregatedResponse.candidates[i].content = {
|
|
1794
1806
|
role: candidate.content.role || 'user',
|
|
1795
1807
|
parts: []
|
|
1796
1808
|
};
|
|
1797
1809
|
}
|
|
1798
|
-
const newPart = {};
|
|
1799
1810
|
for (const part of candidate.content.parts) {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
}
|
|
1807
|
-
newPart.text = part.text;
|
|
1808
|
-
}
|
|
1809
|
-
if (part.functionCall) {
|
|
1810
|
-
newPart.functionCall = part.functionCall;
|
|
1811
|
+
const newPart = { ...part };
|
|
1812
|
+
// The backend can send empty text parts. If these are sent back
|
|
1813
|
+
// (e.g. in chat history), the backend will respond with an error.
|
|
1814
|
+
// To prevent this, ignore empty text parts.
|
|
1815
|
+
if (part.text === '') {
|
|
1816
|
+
continue;
|
|
1811
1817
|
}
|
|
1812
|
-
if (Object.keys(newPart).length
|
|
1813
|
-
|
|
1814
|
-
'by a malformed response from the backend.');
|
|
1818
|
+
if (Object.keys(newPart).length > 0) {
|
|
1819
|
+
aggregatedResponse.candidates[i].content.parts.push(newPart);
|
|
1815
1820
|
}
|
|
1816
|
-
aggregatedResponse.candidates[i].content.parts.push(newPart);
|
|
1817
1821
|
}
|
|
1818
1822
|
}
|
|
1819
1823
|
}
|
|
@@ -2519,6 +2523,25 @@ class LiveSession {
|
|
|
2519
2523
|
this.webSocketHandler.send(JSON.stringify(message));
|
|
2520
2524
|
});
|
|
2521
2525
|
}
|
|
2526
|
+
/**
|
|
2527
|
+
* Sends function responses to the server.
|
|
2528
|
+
*
|
|
2529
|
+
* @param functionResponses - The function responses to send.
|
|
2530
|
+
* @throws If this session has been closed.
|
|
2531
|
+
*
|
|
2532
|
+
* @beta
|
|
2533
|
+
*/
|
|
2534
|
+
async sendFunctionResponses(functionResponses) {
|
|
2535
|
+
if (this.isClosed) {
|
|
2536
|
+
throw new AIError(AIErrorCode.REQUEST_ERROR, 'This LiveSession has been closed and cannot be used.');
|
|
2537
|
+
}
|
|
2538
|
+
const message = {
|
|
2539
|
+
toolResponse: {
|
|
2540
|
+
functionResponses
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
this.webSocketHandler.send(JSON.stringify(message));
|
|
2544
|
+
}
|
|
2522
2545
|
/**
|
|
2523
2546
|
* Sends a stream of {@link GenerativeContentBlob}.
|
|
2524
2547
|
*
|
|
@@ -3500,9 +3523,9 @@ class AudioConversationRunner {
|
|
|
3500
3523
|
}
|
|
3501
3524
|
else {
|
|
3502
3525
|
try {
|
|
3503
|
-
const
|
|
3526
|
+
const functionResponse = await this.options.functionCallingHandler(message.functionCalls);
|
|
3504
3527
|
if (!this.isStopped) {
|
|
3505
|
-
void this.liveSession.
|
|
3528
|
+
void this.liveSession.sendFunctionResponses([functionResponse]);
|
|
3506
3529
|
}
|
|
3507
3530
|
}
|
|
3508
3531
|
catch (e) {
|