send method
Future<void>
send({
- required MeshDocument thread,
- required String path,
- required ChatMessage message,
- String messageType = "chat",
- String? remoteStoreParticipantName,
- bool storeLocally = true,
- bool useAgentMessages = false,
- String? turnId,
- TurnMcpConfig? mcp,
- List<
ClientToolkitDescription> ? clientToolkits, - AgentToolChoice? toolChoice,
- void onMessageSent()?,
Implementation
Future<void> send({
required MeshDocument thread,
required String path,
required ChatMessage message,
String messageType = "chat",
String? remoteStoreParticipantName,
bool storeLocally = true,
bool useAgentMessages = false,
String? turnId,
TurnMcpConfig? mcp,
List<ClientToolkitDescription>? clientToolkits,
AgentToolChoice? toolChoice,
void Function(ChatMessage)? onMessageSent,
}) async {
if (message.text.trim().isNotEmpty || message.attachments.isNotEmpty) {
if (storeLocally) {
insertMessage(thread: thread, message: message);
}
final normalizedParticipantName = remoteStoreParticipantName?.trim();
if (useAgentMessages) {
final room = _requireRoom('Sending an agent message');
final senderName = room.localParticipant?.getAttribute("name");
_markPendingAgentMessage(
message: PendingAgentMessage(
messageId: message.id,
messageType: messageType == "steer" ? agentTurnSteerType : agentTurnStartType,
threadPath: path,
text: message.text,
attachments: [for (final attachment in message.attachments) AgentFileContent(url: attachment)],
senderName: senderName is String && senderName.trim().isNotEmpty ? senderName.trim() : null,
createdAt: DateTime.now(),
matchByContentOnly: false,
awaitingAcceptance: true,
awaitingApplication: true,
awaitingOnline: false,
),
);
}
outboundStatus.markSending(message.id);
try {
final List<Future<void>> sentMessages = [];
if (notifyOnSend) {
var participants = _matchingRecipients(
thread: thread,
useAgentMessages: useAgentMessages,
participantName: normalizedParticipantName,
);
if (participants.isEmpty) {
final shouldWaitForRecipient = useAgentMessages || (normalizedParticipantName != null && normalizedParticipantName.isNotEmpty);
if (!shouldWaitForRecipient) {
throw StateError("no matching recipients are available for '$path'");
}
participants = await _waitForRecipients(
thread: thread,
path: path,
messageId: message.id,
useAgentMessages: useAgentMessages,
participantName: normalizedParticipantName,
);
}
for (final participant in participants) {
final participantName = participant.getAttribute("name");
final shouldStoreRemotely =
remoteStoreParticipantName != null && participantName is String && participantName == remoteStoreParticipantName;
sentMessages.add(
sendMessageToParticipant(
participant: participant,
path: path,
message: message,
messageType: messageType,
useAgentMessages: useAgentMessages,
turnId: turnId,
mcp: mcp,
clientToolkits: messageType == "steer" ? null : clientToolkits,
toolChoice: toolChoice,
store: shouldStoreRemotely,
),
);
}
}
await Future.wait(sentMessages);
outboundStatus.markDelivered(message.id);
onMessageSent?.call(message);
} on ChatSendCancelledException {
outboundStatus.clear(message.id);
if (useAgentMessages) {
_clearPendingAgentMessage(message.id);
}
rethrow;
} catch (error, stackTrace) {
outboundStatus.markFailed(message.id, error, stackTrace);
if (useAgentMessages) {
_clearPendingAgentMessage(message.id);
}
rethrow;
}
}
}