@@ -169,7 +169,8 @@ final class Candidate {
169
169
// TODO: token count?
170
170
// ignore: public_member_api_docs
171
171
Candidate (this .content, this .safetyRatings, this .citationMetadata,
172
- this .finishReason, this .finishMessage);
172
+ this .finishReason, this .finishMessage,
173
+ {this .groundingMetadata});
173
174
174
175
/// Generated content returned from the model.
175
176
final Content content;
@@ -194,6 +195,8 @@ final class Candidate {
194
195
/// Message for finish reason.
195
196
final String ? finishMessage;
196
197
198
+ final GroundingMetadata ? groundingMetadata;
199
+
197
200
/// The concatenation of the text parts of [content] , if any.
198
201
///
199
202
/// If this candidate was finished for a reason of [FinishReason.recitation]
@@ -225,6 +228,59 @@ final class Candidate {
225
228
}
226
229
}
227
230
231
+ final class Segment {
232
+ Segment (
233
+ {required this .partIndex,
234
+ required this .startIndex,
235
+ required this .endIndex,
236
+ required this .text});
237
+
238
+ final int partIndex;
239
+ final int startIndex;
240
+ final int endIndex;
241
+ final String text;
242
+ }
243
+
244
+ final class WebGroundingChunk {
245
+ WebGroundingChunk ({this .uri, this .title, this .domain});
246
+
247
+ final String ? uri;
248
+ final String ? title;
249
+ final String ? domain;
250
+ }
251
+
252
+ final class GroundingChunk {
253
+ GroundingChunk ({this .web});
254
+
255
+ final WebGroundingChunk ? web;
256
+ }
257
+
258
+ final class GroundingSupport {
259
+ GroundingSupport ({this .segment, required this .groundingChunkIndices});
260
+
261
+ final Segment ? segment;
262
+ final List <int > groundingChunkIndices;
263
+ }
264
+
265
+ final class SearchEntrypoint {
266
+ SearchEntrypoint ({this .renderedContent});
267
+
268
+ final String ? renderedContent;
269
+ }
270
+
271
+ final class GroundingMetadata {
272
+ GroundingMetadata (
273
+ {this .searchEntrypoint,
274
+ required this .groundingChunks,
275
+ required this .groundingSupport,
276
+ required this .webSearchQueries});
277
+
278
+ final SearchEntrypoint ? searchEntrypoint;
279
+ final List <GroundingChunk > groundingChunks;
280
+ final List <GroundingSupport > groundingSupport;
281
+ final List <String > webSearchQueries;
282
+ }
283
+
228
284
/// Safety rating for a piece of content.
229
285
///
230
286
/// The safety rating contains the category of harm and the harm probability
@@ -938,29 +994,33 @@ Candidate _parseCandidate(Object? jsonObject) {
938
994
}
939
995
940
996
return Candidate (
941
- jsonObject.containsKey ('content' )
942
- ? parseContent (jsonObject['content' ] as Object )
943
- : Content (null , []),
944
- switch (jsonObject) {
945
- {'safetyRatings' : final List <Object ?> safetyRatings} =>
946
- safetyRatings.map (_parseSafetyRating).toList (),
947
- _ => null
948
- },
949
- switch (jsonObject) {
950
- {'citationMetadata' : final Object citationMetadata} =>
951
- _parseCitationMetadata (citationMetadata),
952
- _ => null
953
- },
954
- switch (jsonObject) {
955
- {'finishReason' : final Object finishReason} =>
956
- FinishReason ._parseValue (finishReason),
957
- _ => null
958
- },
959
- switch (jsonObject) {
960
- {'finishMessage' : final String finishMessage} => finishMessage,
961
- _ => null
962
- },
963
- );
997
+ jsonObject.containsKey ('content' )
998
+ ? parseContent (jsonObject['content' ] as Object )
999
+ : Content (null , []),
1000
+ switch (jsonObject) {
1001
+ {'safetyRatings' : final List <Object ?> safetyRatings} =>
1002
+ safetyRatings.map (_parseSafetyRating).toList (),
1003
+ _ => null
1004
+ },
1005
+ switch (jsonObject) {
1006
+ {'citationMetadata' : final Object citationMetadata} =>
1007
+ _parseCitationMetadata (citationMetadata),
1008
+ _ => null
1009
+ },
1010
+ switch (jsonObject) {
1011
+ {'finishReason' : final Object finishReason} =>
1012
+ FinishReason ._parseValue (finishReason),
1013
+ _ => null
1014
+ },
1015
+ switch (jsonObject) {
1016
+ {'finishMessage' : final String finishMessage} => finishMessage,
1017
+ _ => null
1018
+ },
1019
+ groundingMetadata: switch (jsonObject) {
1020
+ {'groundingMetadata' : final Object groundingMetadata} =>
1021
+ _parseGroundingMetadata (groundingMetadata),
1022
+ _ => null
1023
+ });
964
1024
}
965
1025
966
1026
PromptFeedback _parsePromptFeedback (Object jsonObject) {
@@ -1074,3 +1134,97 @@ Citation _parseCitationSource(Object? jsonObject) {
1074
1134
jsonObject['license' ] as String ? ,
1075
1135
);
1076
1136
}
1137
+
1138
+ GroundingMetadata _parseGroundingMetadata (Object ? jsonObject) {
1139
+ if (jsonObject is ! Map ) {
1140
+ throw unhandledFormat ('GroundingMetadata' , jsonObject);
1141
+ }
1142
+
1143
+ final searchEntrypoint = switch (jsonObject) {
1144
+ {'searchEntrypoint' : final Object ? searchEntrypoint} =>
1145
+ _parseSearchEntrypoint (searchEntrypoint),
1146
+ _ => null ,
1147
+ };
1148
+ final groundingChunks = switch (jsonObject) {
1149
+ {'groundingChunks' : final List <Object ?> groundingChunks} =>
1150
+ groundingChunks.map (_parseGroundingChunk).toList (),
1151
+ _ => null ,
1152
+ } ??
1153
+ [];
1154
+ final groundingSupport = switch (jsonObject) {
1155
+ {'groundingSupport' : final List <Object ?> groundingSupport} =>
1156
+ groundingSupport.map (_parseGroundingSupport).toList (),
1157
+ _ => null ,
1158
+ } ??
1159
+ [];
1160
+ final webSearchQueries = switch (jsonObject) {
1161
+ {'webSearchQueries' : final List <String >? webSearchQueries} =>
1162
+ webSearchQueries,
1163
+ _ => null ,
1164
+ } ??
1165
+ [];
1166
+
1167
+ return GroundingMetadata (
1168
+ searchEntrypoint: searchEntrypoint,
1169
+ groundingChunks: groundingChunks,
1170
+ groundingSupport: groundingSupport,
1171
+ webSearchQueries: webSearchQueries);
1172
+ }
1173
+
1174
+ Segment _parseSegment (Object ? jsonObject) {
1175
+ if (jsonObject is ! Map ) {
1176
+ throw unhandledFormat ('Segment' , jsonObject);
1177
+ }
1178
+
1179
+ return Segment (
1180
+ partIndex: (jsonObject['partIndex' ] as int ? ) ?? 0 ,
1181
+ startIndex: (jsonObject['startIndex' ] as int ? ) ?? 0 ,
1182
+ endIndex: (jsonObject['endIndex' ] as int ? ) ?? 0 ,
1183
+ text: (jsonObject['text' ] as String ? ) ?? '' );
1184
+ }
1185
+
1186
+ WebGroundingChunk _parseWebGroundingChunk (Object ? jsonObject) {
1187
+ if (jsonObject is ! Map ) {
1188
+ throw unhandledFormat ('WebGroundingChunk' , jsonObject);
1189
+ }
1190
+
1191
+ return WebGroundingChunk (
1192
+ uri: jsonObject['uri' ] as String ? ,
1193
+ title: jsonObject['title' ] as String ? ,
1194
+ domain: jsonObject['domain' ] as String ? ,
1195
+ );
1196
+ }
1197
+
1198
+ GroundingChunk _parseGroundingChunk (Object ? jsonObject) {
1199
+ if (jsonObject is ! Map ) {
1200
+ throw unhandledFormat ('GroundingChunk' , jsonObject);
1201
+ }
1202
+
1203
+ return GroundingChunk (
1204
+ web: jsonObject['web' ] != null
1205
+ ? _parseWebGroundingChunk (jsonObject['web' ])
1206
+ : null ,
1207
+ );
1208
+ }
1209
+
1210
+ GroundingSupport _parseGroundingSupport (Object ? jsonObject) {
1211
+ if (jsonObject is ! Map ) {
1212
+ throw unhandledFormat ('GroundingSupport' , jsonObject);
1213
+ }
1214
+
1215
+ return GroundingSupport (
1216
+ segment: jsonObject['segment' ] != null
1217
+ ? _parseSegment (jsonObject['segment' ])
1218
+ : null ,
1219
+ groundingChunkIndices:
1220
+ (jsonObject['groundingChunkIndices' ] as List <int >? ) ?? []);
1221
+ }
1222
+
1223
+ SearchEntrypoint _parseSearchEntrypoint (Object ? jsonObject) {
1224
+ if (jsonObject is ! Map ) {
1225
+ throw unhandledFormat ('SearchEntrypoint' , jsonObject);
1226
+ }
1227
+
1228
+ return SearchEntrypoint (
1229
+ renderedContent: (jsonObject['renderedContent' ] as String ? ) ?? '' );
1230
+ }
0 commit comments