@@ -16,6 +16,8 @@ import 'dart:convert';
1616import 'dart:developer' ;
1717import 'dart:typed_data' ;
1818
19+ import 'package:meta/meta.dart' ;
20+
1921import 'api.dart' ;
2022import 'error.dart' ;
2123
@@ -120,9 +122,11 @@ Part parsePart(Object? jsonObject) {
120122 if (executableCode is Map &&
121123 executableCode.containsKey ('language' ) &&
122124 executableCode.containsKey ('code' )) {
123- return ExecutableCodePart (
125+ return ExecutableCodePart ._ (
124126 language: CodeLanguage .parseValue (executableCode['language' ] as String ),
125127 code: executableCode['code' ] as String ,
128+ isThought: isThought,
129+ thoughtSignature: thoughtSignature,
126130 );
127131 } else {
128132 throw unhandledFormat ('executableCode' , executableCode);
@@ -133,9 +137,11 @@ Part parsePart(Object? jsonObject) {
133137 if (codeExecutionResult is Map &&
134138 codeExecutionResult.containsKey ('outcome' ) &&
135139 codeExecutionResult.containsKey ('output' )) {
136- return CodeExecutionResultPart (
140+ return CodeExecutionResultPart ._ (
137141 outcome: Outcome .parseValue (codeExecutionResult['outcome' ] as String ),
138142 output: codeExecutionResult['output' ] as String ,
143+ isThought: isThought,
144+ thoughtSignature: thoughtSignature,
139145 );
140146 } else {
141147 throw unhandledFormat ('codeExecutionResult' , codeExecutionResult);
@@ -188,7 +194,11 @@ sealed class Part {
188194 final String ? _thoughtSignature;
189195
190196 /// Convert the [Part] content to json format.
191- Object toJson ();
197+ Object toJson () => {
198+ if (isThought case final isThought? ) 'thought' : isThought,
199+ if (_thoughtSignature case final thoughtSignature? )
200+ 'thoughtSignature' : thoughtSignature,
201+ };
192202}
193203
194204/// A [Part] that contains unparsable data.
@@ -200,7 +210,10 @@ final class UnknownPart extends Part {
200210 final Map <String , Object ?> data;
201211
202212 @override
203- Object toJson () => data;
213+ Object toJson () {
214+ final superJson = super .toJson () as Map <String , Object ?>;
215+ return < String , Object ? > {...superJson, ...data};
216+ }
204217}
205218
206219/// A [Part] with the text content.
@@ -211,6 +224,18 @@ final class TextPart extends Part {
211224 isThought: isThought,
212225 thoughtSignature: null ,
213226 );
227+
228+ @visibleForTesting
229+ // ignore: public_member_api_docs
230+ const TextPart .forTest (
231+ this .text, {
232+ bool ? isThought,
233+ String ? thoughtSignature,
234+ }) : super (
235+ isThought: isThought,
236+ thoughtSignature: thoughtSignature,
237+ );
238+
214239 const TextPart ._(
215240 this .text, {
216241 bool ? isThought,
@@ -223,7 +248,10 @@ final class TextPart extends Part {
223248 /// The text content of the [Part]
224249 final String text;
225250 @override
226- Object toJson () => {'text' : text};
251+ Object toJson () {
252+ final superJson = super .toJson () as Map <String , Object ?>;
253+ return < String , Object ? > {...superJson, 'text' : text};
254+ }
227255}
228256
229257/// A [Part] with the byte content of a file.
@@ -238,6 +266,20 @@ final class InlineDataPart extends Part {
238266 isThought: isThought,
239267 thoughtSignature: null ,
240268 );
269+
270+ @visibleForTesting
271+ // ignore: public_member_api_docs
272+ const InlineDataPart .forTest (
273+ this .mimeType,
274+ this .bytes, {
275+ this .willContinue,
276+ bool ? isThought,
277+ String ? thoughtSignature,
278+ }) : super (
279+ isThought: isThought,
280+ thoughtSignature: thoughtSignature,
281+ );
282+
241283 const InlineDataPart ._(
242284 this .mimeType,
243285 this .bytes, {
@@ -259,13 +301,17 @@ final class InlineDataPart extends Part {
259301 /// Whether there's more inline data coming for streaming.
260302 final bool ? willContinue;
261303 @override
262- Object toJson () => {
263- 'inlineData' : {
264- 'data' : base64Encode (bytes),
265- 'mimeType' : mimeType,
266- if (willContinue != null ) 'willContinue' : willContinue,
267- }
268- };
304+ Object toJson () {
305+ final superJson = super .toJson () as Map <String , Object ?>;
306+ return < String , Object ? > {
307+ ...superJson,
308+ 'inlineData' : {
309+ 'data' : base64Encode (bytes),
310+ 'mimeType' : mimeType,
311+ if (willContinue != null ) 'willContinue' : willContinue,
312+ },
313+ };
314+ }
269315
270316 /// The representation of the data in media streaming chunk.
271317 Object toMediaChunkJson () => {
@@ -289,6 +335,20 @@ final class FunctionCall extends Part {
289335 isThought: isThought,
290336 thoughtSignature: null ,
291337 );
338+
339+ @visibleForTesting
340+ // ignore: public_member_api_docs
341+ const FunctionCall .forTest (
342+ this .name,
343+ this .args, {
344+ this .id,
345+ bool ? isThought,
346+ String ? thoughtSignature,
347+ }) : super (
348+ isThought: isThought,
349+ thoughtSignature: thoughtSignature,
350+ );
351+
292352 const FunctionCall ._(
293353 this .name,
294354 this .args, {
@@ -313,13 +373,17 @@ final class FunctionCall extends Part {
313373 final String ? id;
314374
315375 @override
316- Object toJson () => {
317- 'functionCall' : {
318- 'name' : name,
319- 'args' : args,
320- if (id != null ) 'id' : id,
321- }
322- };
376+ Object toJson () {
377+ final superJson = super .toJson () as Map <String , Object ?>;
378+ return < String , Object ? > {
379+ ...superJson,
380+ 'functionCall' : {
381+ 'name' : name,
382+ 'args' : args,
383+ if (id != null ) 'id' : id,
384+ },
385+ };
386+ }
323387}
324388
325389/// The response class for [FunctionCall]
@@ -350,13 +414,17 @@ final class FunctionResponse extends Part {
350414 final String ? id;
351415
352416 @override
353- Object toJson () => {
354- 'functionResponse' : {
355- 'name' : name,
356- 'response' : response,
357- if (id != null ) 'id' : id,
358- }
359- };
417+ Object toJson () {
418+ final superJson = super .toJson () as Map <String , Object ?>;
419+ return < String , Object ? > {
420+ ...superJson,
421+ 'functionResponse' : {
422+ 'name' : name,
423+ 'response' : response,
424+ if (id != null ) 'id' : id,
425+ },
426+ };
427+ }
360428}
361429
362430/// A [Part] with Firebase Storage uri as prompt content
@@ -370,6 +438,19 @@ final class FileData extends Part {
370438 isThought: isThought,
371439 thoughtSignature: null ,
372440 );
441+
442+ @visibleForTesting
443+ // ignore: public_member_api_docs
444+ const FileData .forTest (
445+ this .mimeType,
446+ this .fileUri, {
447+ bool ? isThought,
448+ String ? thoughtSignature,
449+ }) : super (
450+ isThought: isThought,
451+ thoughtSignature: thoughtSignature,
452+ );
453+
373454 const FileData ._(
374455 this .mimeType,
375456 this .fileUri, {
@@ -388,9 +469,13 @@ final class FileData extends Part {
388469 final String fileUri;
389470
390471 @override
391- Object toJson () => {
392- 'file_data' : {'file_uri' : fileUri, 'mime_type' : mimeType}
393- };
472+ Object toJson () {
473+ final superJson = super .toJson () as Map <String , Object ?>;
474+ return < String , Object ? > {
475+ ...superJson,
476+ 'file_data' : {'file_uri' : fileUri, 'mime_type' : mimeType},
477+ };
478+ }
394479}
395480
396481/// A `Part` that represents the code that is executed by the model.
@@ -405,16 +490,30 @@ final class ExecutableCodePart extends Part {
405490 thoughtSignature: null ,
406491 );
407492
493+ ExecutableCodePart ._({
494+ required this .language,
495+ required this .code,
496+ bool ? isThought,
497+ String ? thoughtSignature,
498+ }) : super (
499+ isThought: isThought,
500+ thoughtSignature: thoughtSignature,
501+ );
502+
408503 /// The programming language of the code.
409504 final CodeLanguage language;
410505
411506 /// The source code to be executed.
412507 final String code;
413508
414509 @override
415- Object toJson () => {
416- 'executableCode' : {'language' : language.toJson (), 'code' : code}
417- };
510+ Object toJson () {
511+ final superJson = super .toJson () as Map <String , Object ?>;
512+ return < String , Object ? > {
513+ ...superJson,
514+ 'executableCode' : {'language' : language.toJson (), 'code' : code},
515+ };
516+ }
418517}
419518
420519/// A `Part` that represents the code execution result from the model.
@@ -429,14 +528,28 @@ final class CodeExecutionResultPart extends Part {
429528 thoughtSignature: null ,
430529 );
431530
531+ CodeExecutionResultPart ._({
532+ required this .outcome,
533+ required this .output,
534+ bool ? isThought,
535+ String ? thoughtSignature,
536+ }) : super (
537+ isThought: isThought,
538+ thoughtSignature: thoughtSignature,
539+ );
540+
432541 /// The result of the execution.
433542 final Outcome outcome;
434543
435544 /// The stdout from the code execution, or an error message if it failed.
436545 final String output;
437546
438547 @override
439- Object toJson () => {
440- 'codeExecutionResult' : {'outcome' : outcome.toJson (), 'output' : output}
441- };
548+ Object toJson () {
549+ final superJson = super .toJson () as Map <String , Object ?>;
550+ return < String , Object ? > {
551+ ...superJson,
552+ 'codeExecutionResult' : {'outcome' : outcome.toJson (), 'output' : output},
553+ };
554+ }
442555}
0 commit comments