@@ -17,8 +17,37 @@ part 'roots.dart';
17
17
part 'sampling.dart' ;
18
18
part 'tools.dart' ;
19
19
20
- /// The current protocol version
21
- const protocolVersion = '2024-11-05' ;
20
+ /// Enum of the known protocol versions.
21
+ enum ProtocolVersion {
22
+ v2024_11_05 ('2024-11-05' ),
23
+ v2025_03_26 ('2025-03-26' );
24
+
25
+ const ProtocolVersion (this .versionString);
26
+
27
+ /// Returns the [ProtocolVersion] based on the [version] string, or `null` if
28
+ /// it was not recognized.
29
+ static ProtocolVersion ? tryParse (String version) =>
30
+ values.firstWhereOrNull ((v) => v.versionString == version);
31
+
32
+ /// The oldest version supported by the current API.
33
+ static const oldestSupported = ProtocolVersion .v2024_11_05;
34
+
35
+ /// The most recent version supported by the current API.
36
+ static const latestSupported = ProtocolVersion .v2025_03_26;
37
+
38
+ /// The version string used over the wire to identify this version.
39
+ final String versionString;
40
+
41
+ /// Whether or not this API is compatible with the current version.
42
+ ///
43
+ /// **Note**: There may be extra fields included.
44
+ bool get isSupported => this >= oldestSupported && this <= latestSupported;
45
+
46
+ bool operator < (ProtocolVersion other) => index < other.index;
47
+ bool operator <= (ProtocolVersion other) => index <= other.index;
48
+ bool operator > (ProtocolVersion other) => index > other.index;
49
+ bool operator >= (ProtocolVersion other) => index >= other.index;
50
+ }
22
51
23
52
/// A progress token, used to associate progress notifications with the original
24
53
/// request.
@@ -136,14 +165,16 @@ extension type ProgressNotification.fromMap(Map<String, Object?> _value)
136
165
137
166
factory ProgressNotification ({
138
167
required ProgressToken progressToken,
139
- required int progress,
140
- int ? total,
168
+ required num progress,
169
+ num ? total,
141
170
Meta ? meta,
171
+ String ? message,
142
172
}) => ProgressNotification .fromMap ({
143
173
'progressToken' : progressToken,
144
174
'progress' : progress,
145
175
if (total != null ) 'total' : total,
146
176
if (meta != null ) '_meta' : meta,
177
+ if (message != null ) 'message' : message,
147
178
});
148
179
149
180
/// The progress token which was given in the initial request, used to
@@ -154,11 +185,14 @@ extension type ProgressNotification.fromMap(Map<String, Object?> _value)
154
185
///
155
186
/// This should increase every time progress is made, even if the total is
156
187
/// unknown.
157
- int get progress => _value['progress' ] as int ;
188
+ num get progress => _value['progress' ] as num ;
158
189
159
190
/// Total number of items to process (or total progress required), if
160
191
/// known.
161
- int ? get total => _value['total' ] as int ? ;
192
+ num ? get total => _value['total' ] as num ? ;
193
+
194
+ /// An optional message describing the current progress.
195
+ String ? get message => _value['message' ] as String ? ;
162
196
}
163
197
164
198
/// A "mixin"-like extension type for any request that contains a [Cursor] at
@@ -185,10 +219,11 @@ extension type PaginatedRequest._fromMap(Map<String, Object?> _value)
185
219
/// constructor.
186
220
extension type PaginatedResult ._fromMap (Map <String , Object ?> _value)
187
221
implements Result {
188
- Cursor ? get cursor => _value['cursor ' ] as Cursor ? ;
222
+ Cursor ? get nextCursor => _value['nextCursor ' ] as Cursor ? ;
189
223
}
190
224
191
- /// Could be either [TextContent] , [ImageContent] or [EmbeddedResource] .
225
+ /// Could be either [TextContent] , [ImageContent] , [AudioContent] or
226
+ /// [EmbeddedResource] .
192
227
///
193
228
/// Use [isText] , [isImage] and [isEmbeddedResource] before casting to the more
194
229
/// specific types, or switch on the [type] and then cast.
@@ -201,25 +236,40 @@ extension type Content._(Map<String, Object?> _value) {
201
236
return Content ._(value);
202
237
}
203
238
239
+ /// Alias for [TextContent.new] .
240
+ static const text = TextContent .new ;
241
+
242
+ /// Alias for [ImageContent.new] .
243
+ static const image = ImageContent .new ;
244
+
245
+ /// Alias for [AudioContent.new] .
246
+ static const audio = AudioContent .new ;
247
+
248
+ /// Alias for [EmbeddedResource.new] .
249
+ static const embeddedResource = EmbeddedResource .new ;
250
+
204
251
/// Whether or not this is a [TextContent] .
205
252
bool get isText => _value['type' ] == TextContent .expectedType;
206
253
207
- /// Whether or not this is a [ImageContent] .
254
+ /// Whether or not this is an [ImageContent] .
208
255
bool get isImage => _value['type' ] == ImageContent .expectedType;
209
256
257
+ /// Whether or not this is an [AudioContent] .
258
+ bool get isAudio => _value['type' ] == AudioContent .expectedType;
259
+
210
260
/// Whether or not this is an [EmbeddedResource] .
211
261
bool get isEmbeddedResource =>
212
262
_value['type' ] == EmbeddedResource .expectedType;
213
263
214
264
/// The type of content.
215
265
///
216
266
/// You can use this in a switch to handle the various types (see the static
217
- /// `expectedType` getters), or you can use [isText] , [isImage] , and
267
+ /// `expectedType` getters), or you can use [isText] , [isImage] , [isAudio] and
218
268
/// [isEmbeddedResource] to determine the type and then do the cast.
219
269
String get type => _value['type' ] as String ;
220
270
}
221
271
222
- /// Text provided to an LLM.
272
+ /// Text provided to or from an LLM.
223
273
extension type TextContent .fromMap (Map <String , Object ?> _value)
224
274
implements Content , Annotated {
225
275
static const expectedType = 'text' ;
@@ -241,7 +291,7 @@ extension type TextContent.fromMap(Map<String, Object?> _value)
241
291
String get text => _value['text' ] as String ;
242
292
}
243
293
244
- /// An image provided to an LLM.
294
+ /// An image provided to or from an LLM.
245
295
extension type ImageContent .fromMap (Map <String , Object ?> _value)
246
296
implements Content , Annotated {
247
297
static const expectedType = 'image' ;
@@ -263,11 +313,45 @@ extension type ImageContent.fromMap(Map<String, Object?> _value)
263
313
return type;
264
314
}
265
315
266
- /// If the [type] is `image` , this is the base64 encoded image data.
316
+ /// The base64 encoded image data.
267
317
String get data => _value['data' ] as String ;
268
318
269
- /// If the [type] is `image` , the MIME type of the image. Different providers
270
- /// may support different image types.
319
+ /// The MIME type of the image.
320
+ ///
321
+ /// Different providers may support different image types.
322
+ String get mimeType => _value['mimeType' ] as String ;
323
+ }
324
+
325
+ /// Audio provided to or from an LLM.
326
+ ///
327
+ /// Only supported since version [ProtocolVersion.v2025_03_26] .
328
+ extension type AudioContent .fromMap (Map <String , Object ?> _value)
329
+ implements Content , Annotated {
330
+ static const expectedType = 'audio' ;
331
+
332
+ factory AudioContent ({
333
+ required String data,
334
+ required String mimeType,
335
+ Annotations ? annotations,
336
+ }) => AudioContent .fromMap ({
337
+ 'data' : data,
338
+ 'mimeType' : mimeType,
339
+ 'type' : expectedType,
340
+ if (annotations != null ) 'annotations' : annotations,
341
+ });
342
+
343
+ String get type {
344
+ final type = _value['type' ] as String ;
345
+ assert (type == expectedType);
346
+ return type;
347
+ }
348
+
349
+ /// The base64 encoded audio data.
350
+ String get data => _value['data' ] as String ;
351
+
352
+ /// The MIME type of the audio.
353
+ ///
354
+ /// Different providers may support different audio types.
271
355
String get mimeType => _value['mimeType' ] as String ;
272
356
}
273
357
0 commit comments