invokeTool method
Implementation
Future<ToolCallOutput> invokeTool({
required String toolkit,
required String tool,
required ToolInput input,
String? participantId,
String? onBehalfOfId,
Map<String, dynamic>? callerContext,
}) async {
final toolCallId = _uuid.v4();
final controller = StreamController<Content>(
onCancel: () {
_toolCallStreams.remove(toolCallId);
},
);
_toolCallStreams[toolCallId] = controller;
final request = <String, dynamic>{
"toolkit": toolkit,
"tool": tool,
"participant_id": participantId,
"on_behalf_of_id": onBehalfOfId,
"caller_context": callerContext,
"tool_call_id": toolCallId,
};
Uint8List? invokeData;
Future<void>? inputTask;
if (input is ToolContentInput) {
final packedInput = unpackMessage(input.content.pack());
request["arguments"] = packedInput.header;
invokeData = packedInput.payload.isEmpty ? null : packedInput.payload;
} else if (input is ToolStreamInput) {
final openChunk = unpackMessage(ControlContent(method: "open").pack());
request["arguments"] = openChunk.header;
inputTask = _streamInvokeToolRequestChunks(toolCallId: toolCallId, inputChunks: input.chunks);
} else {
await _closeToolCallStream(toolCallId: toolCallId, controller: controller);
throw RoomServerException("invokeTool input must be ToolContentInput or ToolStreamInput");
}
try {
final response = await _awaitInvokeResponse(
toolCallId: toolCallId,
requestFuture: room.sendRequest("agent.invoke_tool", request, data: invokeData),
);
if (response is ControlContent && response.method == "open") {
if (inputTask != null) {
unawaited(
inputTask.catchError((Object error, StackTrace stackTrace) async {
final wrapped = error is RoomServerException ? error : RoomServerException("request stream failed: $error");
if (!controller.isClosed) {
controller.addError(wrapped, stackTrace);
}
await _closeToolCallStream(toolCallId: toolCallId, controller: controller);
}),
);
}
return ToolStreamOutput(controller.stream);
}
if (inputTask != null) {
await inputTask;
}
await _closeToolCallStream(toolCallId: toolCallId, controller: controller);
return ToolContentOutput(response);
} catch (error, stackTrace) {
if (inputTask != null) {
await Future.wait([inputTask.catchError((_) {})]);
}
if (!controller.isClosed) {
controller.addError(error, stackTrace);
}
await _closeToolCallStream(toolCallId: toolCallId, controller: controller);
rethrow;
}
}