Skip to content

Commit d2951e7

Browse files
committed
Update code to handle optional id for FunctionCall parse
1 parent c8bf5fe commit d2951e7

File tree

2 files changed

+89
-12
lines changed

2 files changed

+89
-12
lines changed

packages/firebase_vertexai/firebase_vertexai/lib/src/content.dart

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,22 @@ Content parseContent(Object jsonObject) {
8181

8282
/// Parse the [Part] from json object.
8383
Part parsePart(Object? jsonObject) {
84+
if (jsonObject is Map && jsonObject.containsKey('functionCall')) {
85+
final functionCall = jsonObject['functionCall'];
86+
if (functionCall is Map &&
87+
functionCall.containsKey('name') &&
88+
functionCall.containsKey('args')) {
89+
return FunctionCall(
90+
functionCall['name'] as String,
91+
functionCall['args'] as Map<String, Object?>,
92+
id: functionCall['id'] as String?,
93+
);
94+
} else {
95+
throw unhandledFormat('functionCall', functionCall);
96+
}
97+
}
8498
return switch (jsonObject) {
8599
{'text': final String text} => TextPart(text),
86-
{
87-
'functionCall': {
88-
'name': final String name,
89-
'args': final Map<String, Object?> args,
90-
'id': final String? id,
91-
}
92-
} =>
93-
FunctionCall(
94-
name,
95-
args,
96-
id: id,
97-
),
98100
{
99101
'file_data': {
100102
'file_uri': final String fileUri,

packages/firebase_vertexai/firebase_vertexai/test/content_test.dart

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
import 'dart:convert';
1516
import 'dart:typed_data';
1617

1718
import 'package:firebase_vertexai/src/content.dart';
19+
import 'package:firebase_vertexai/src/error.dart';
1820
import 'package:flutter_test/flutter_test.dart';
1921

2022
// Mock google_ai classes (if needed)
@@ -137,4 +139,77 @@ void main() {
137139
expect(json['file_data']['file_uri'], 'gs://bucket-name/path');
138140
});
139141
});
142+
143+
group('parsePart', () {
144+
test('parses TextPart correctly', () {
145+
final json = {'text': 'Hello, world!'};
146+
final result = parsePart(json);
147+
expect(result, isA<TextPart>());
148+
expect((result as TextPart).text, 'Hello, world!');
149+
});
150+
151+
test('parses FunctionCall correctly', () {
152+
final json = {
153+
'functionCall': {
154+
'name': 'myFunction',
155+
'args': {'arg1': 1, 'arg2': 'value'},
156+
'id': '123',
157+
}
158+
};
159+
final result = parsePart(json);
160+
expect(result, isA<FunctionCall>());
161+
final functionCall = result as FunctionCall;
162+
expect(functionCall.name, 'myFunction');
163+
expect(functionCall.args, {'arg1': 1, 'arg2': 'value'});
164+
expect(functionCall.id, '123');
165+
});
166+
167+
test('parses FileData correctly', () {
168+
final json = {
169+
'file_data': {
170+
'file_uri': 'file:///path/to/file.txt',
171+
'mime_type': 'text/plain',
172+
}
173+
};
174+
final result = parsePart(json);
175+
expect(result, isA<FileData>());
176+
final fileData = result as FileData;
177+
expect(fileData.fileUri, 'file:///path/to/file.txt');
178+
expect(fileData.mimeType, 'text/plain');
179+
});
180+
181+
test('parses InlineDataPart correctly', () {
182+
final json = {
183+
'inlineData': {
184+
'mimeType': 'image/png',
185+
'data': base64Encode([1, 2, 3])
186+
}
187+
};
188+
final result = parsePart(json);
189+
expect(result, isA<InlineDataPart>());
190+
final inlineData = result as InlineDataPart;
191+
expect(inlineData.mimeType, 'image/png');
192+
expect(inlineData.bytes, [1, 2, 3]);
193+
});
194+
195+
test('throws UnimplementedError for functionResponse', () {
196+
final json = {
197+
'functionResponse': {'name': 'test', 'response': {}}
198+
};
199+
expect(() => parsePart(json), throwsA(isA<VertexAISdkException>()));
200+
});
201+
202+
test('throws unhandledFormat for invalid JSON', () {
203+
final json = {'invalid': 'data'};
204+
expect(() => parsePart(json), throwsA(isA<Exception>()));
205+
});
206+
207+
test('throws unhandledFormat for null input', () {
208+
expect(() => parsePart(null), throwsA(isA<Exception>()));
209+
});
210+
211+
test('throws unhandledFormat for empty map', () {
212+
expect(() => parsePart({}), throwsA(isA<Exception>()));
213+
});
214+
});
140215
}

0 commit comments

Comments
 (0)