query method
Future<Message>
query({
- required List<
Message> messages, - OnTextDelta? onTextDelta,
- OnToolUse? onToolUse,
- OnToolResult? onToolResult,
- OnApiError? onError,
- OnPermissionRequest? onPermissionRequest,
- OnCompaction? onCompaction,
- void onStreamEvent()?,
Run a full query with tool use loop (streaming).
Implementation
Future<Message> query({
required List<Message> messages,
OnTextDelta? onTextDelta,
OnToolUse? onToolUse,
OnToolResult? onToolResult,
OnApiError? onError,
OnPermissionRequest? onPermissionRequest,
OnCompaction? onCompaction,
void Function(StreamEvent)? onStreamEvent,
}) async {
var conversationMessages = List<Message>.from(messages);
var turn = 0;
while (turn < config.maxTurns) {
turn++;
// Phase 1: Microcompact old tool results before API call
if (config.enableMicrocompact && compactionService != null) {
conversationMessages = compactionService!.microcompact(
conversationMessages,
);
}
// Phase 2: Auto-compact if approaching context limit
if (config.enableCompaction && compactionService != null) {
final compactionResult = await compactionService!.autoCompactIfNeeded(
messages: conversationMessages,
systemPrompt: systemPrompt,
contextWindow: config.contextWindow,
);
if (compactionResult != null) {
conversationMessages = compactionResult.compactedMessages;
onCompaction?.call(compactionResult);
}
}
// API call
final assistantMessage = await _streamOneRound(
messages: conversationMessages,
onTextDelta: onTextDelta,
onStreamEvent: onStreamEvent,
);
conversationMessages.add(assistantMessage);
// Track for session memory
sessionMemory?.trackMessage(assistantMessage);
final toolUses = assistantMessage.toolUses;
if (toolUses.isEmpty) {
return assistantMessage;
}
// Execute all tool calls with permission checks
final toolResults = <ContentBlock>[];
for (final toolUse in toolUses) {
final tool = toolRegistry.get(toolUse.name);
// Permission check
if (tool != null && onPermissionRequest != null) {
final permResult = await _checkPermission(
tool,
toolUse.input,
onPermissionRequest,
);
if (!permResult) {
toolResults.add(
ToolResultBlock(
toolUseId: toolUse.id,
content: 'Permission denied by user for ${toolUse.name}.',
isError: true,
),
);
continue;
}
}
onToolUse?.call(toolUse.name, toolUse.input);
final result = await toolRegistry.execute(toolUse.name, toolUse.input);
onToolResult?.call(toolUse.name, result);
toolResults.add(
ToolResultBlock(
toolUseId: toolUse.id,
content: result.content,
isError: result.isError,
),
);
}
final userMessage = Message(role: MessageRole.user, content: toolResults);
conversationMessages.add(userMessage);
// Track tool results for session memory
sessionMemory?.trackMessage(userMessage);
}
return Message.assistant(
'[Max turns reached (${config.maxTurns}). Stopping tool use loop.]',
);
}