Skip to content

Commit 757c6e8

Browse files
authored
make sure willContinue will only set when the parsed response has it. (#17772)
1 parent a52255e commit 757c6e8

File tree

2 files changed

+72
-6
lines changed

2 files changed

+72
-6
lines changed

packages/firebase_ai/firebase_ai/lib/src/content.dart

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,22 +141,34 @@ Part parsePart(Object? jsonObject) {
141141
throw unhandledFormat('codeExecutionResult', codeExecutionResult);
142142
}
143143
}
144+
145+
if (jsonObject.containsKey('inlineData')) {
146+
final inlineDataResult = jsonObject['inlineData'];
147+
if (inlineDataResult is Map &&
148+
inlineDataResult.containsKey('mimeType') &&
149+
inlineDataResult.containsKey('data')) {
150+
return InlineDataPart._(
151+
inlineDataResult['mimeType'] as String,
152+
base64Decode(inlineDataResult['data'] as String),
153+
willContinue: inlineDataResult['willContinue'] as bool?,
154+
isThought: isThought,
155+
thoughtSignature: thoughtSignature,
156+
);
157+
} else {
158+
throw unhandledFormat('inlineData', inlineDataResult);
159+
}
160+
}
144161
return switch (jsonObject) {
145162
{'text': final String text} => TextPart._(text,
146163
isThought: isThought, thoughtSignature: thoughtSignature),
147164
{
148165
'file_data': {
149166
'file_uri': final String fileUri,
150-
'mime_type': final String mimeType
167+
'mime_type': final String mimeType,
151168
}
152169
} =>
153170
FileData._(mimeType, fileUri,
154171
isThought: isThought, thoughtSignature: thoughtSignature),
155-
{'inlineData': {'mimeType': String mimeType, 'data': String bytes}} =>
156-
InlineDataPart._(mimeType, base64Decode(bytes),
157-
willContinue: false,
158-
isThought: isThought,
159-
thoughtSignature: thoughtSignature),
160172
_ => () {
161173
log('unhandled part format: $jsonObject');
162174
return UnknownPart(jsonObject);

packages/firebase_ai/firebase_ai/test/content_test.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,27 @@ void main() {
9393
final json = part.toJson();
9494
expect((json as Map)['inlineData']['mimeType'], 'image/png');
9595
expect(json['inlineData']['data'], '');
96+
expect(json['inlineData'].containsKey('willContinue'), false);
97+
});
98+
99+
test('DataPart with false willContinue toJson', () {
100+
final part =
101+
InlineDataPart('image/png', Uint8List(0), willContinue: false);
102+
final json = part.toJson();
103+
expect((json as Map)['inlineData']['mimeType'], 'image/png');
104+
expect(json['inlineData']['data'], '');
105+
expect(json['inlineData'].containsKey('willContinue'), true);
106+
expect(json['inlineData']['willContinue'], false);
107+
});
108+
109+
test('DataPart with true willContinue toJson', () {
110+
final part =
111+
InlineDataPart('image/png', Uint8List(0), willContinue: true);
112+
final json = part.toJson();
113+
expect((json as Map)['inlineData']['mimeType'], 'image/png');
114+
expect(json['inlineData']['data'], '');
115+
expect(json['inlineData'].containsKey('willContinue'), true);
116+
expect(json['inlineData']['willContinue'], true);
96117
});
97118

98119
test('FunctionCall toJson', () {
@@ -178,6 +199,38 @@ void main() {
178199
});
179200

180201
test('parses InlineDataPart correctly', () {
202+
final json = {
203+
'inlineData': {
204+
'mimeType': 'image/png',
205+
'data': base64Encode([1, 2, 3]),
206+
'willContinue': true
207+
}
208+
};
209+
final result = parsePart(json);
210+
expect(result, isA<InlineDataPart>());
211+
final inlineData = result as InlineDataPart;
212+
expect(inlineData.mimeType, 'image/png');
213+
expect(inlineData.bytes, [1, 2, 3]);
214+
expect(inlineData.willContinue, true);
215+
});
216+
217+
test('parses InlineDataPart with false willContinue', () {
218+
final json = {
219+
'inlineData': {
220+
'mimeType': 'image/png',
221+
'data': base64Encode([1, 2, 3]),
222+
'willContinue': false
223+
}
224+
};
225+
final result = parsePart(json);
226+
expect(result, isA<InlineDataPart>());
227+
final inlineData = result as InlineDataPart;
228+
expect(inlineData.mimeType, 'image/png');
229+
expect(inlineData.bytes, [1, 2, 3]);
230+
expect(inlineData.willContinue, false);
231+
});
232+
233+
test('parses InlineDataPart without willContinue', () {
181234
final json = {
182235
'inlineData': {
183236
'mimeType': 'image/png',
@@ -189,6 +242,7 @@ void main() {
189242
final inlineData = result as InlineDataPart;
190243
expect(inlineData.mimeType, 'image/png');
191244
expect(inlineData.bytes, [1, 2, 3]);
245+
expect(inlineData.willContinue, null);
192246
});
193247

194248
test('returns UnknownPart for functionResponse', () {

0 commit comments

Comments
 (0)