handleOrphanedPermission function
Stream<Map<String, dynamic> >
handleOrphanedPermission({
- required Map<
String, dynamic> permissionResult, - required Map<
String, dynamic> assistantMessage, - required List<
Map< tools,String, dynamic> > - required List<
Map< mutableMessages,String, dynamic> > - required String sessionId,
- required bool persistSession,
- Future<
void> recordTranscript()?, - Stream<
Map< runToolUse()?,String, dynamic> >
Handle an orphaned permission by executing the tool.
Implementation
Stream<Map<String, dynamic>> handleOrphanedPermission({
required Map<String, dynamic> permissionResult,
required Map<String, dynamic> assistantMessage,
required List<Map<String, dynamic>> tools,
required List<Map<String, dynamic>> mutableMessages,
required String sessionId,
required bool persistSession,
Future<void> Function(List<Map<String, dynamic>>)? recordTranscript,
Stream<Map<String, dynamic>> Function(Map<String, dynamic>)? runToolUse,
}) async* {
final toolUseId = permissionResult['toolUseID'] as String?;
if (toolUseId == null) return;
final content = assistantMessage['message']?['content'];
Map<String, dynamic>? toolUseBlock;
if (content is List) {
for (final block in content) {
if (block is Map<String, dynamic> &&
block['type'] == 'tool_use' &&
block['id'] == toolUseId) {
toolUseBlock = block;
break;
}
}
}
if (toolUseBlock == null) return;
final toolName = toolUseBlock['name'] as String?;
if (toolName == null) return;
// Check if tool exists.
final toolDefinition = tools.firstWhere(
(t) => t['name'] == toolName,
orElse: () => <String, dynamic>{},
);
if (toolDefinition.isEmpty) return;
// Get final input.
var finalInput = toolUseBlock['input'];
if (permissionResult['behavior'] == 'allow' &&
permissionResult['updatedInput'] != null) {
finalInput = permissionResult['updatedInput'];
}
final finalToolUseBlock = {...toolUseBlock, 'input': finalInput};
// Add assistant message if not already present.
final alreadyPresent = mutableMessages.any((m) {
if (m['type'] != 'assistant') return false;
final c = m['message']?['content'];
if (c is! List) return false;
return c.any(
(b) =>
b is Map<String, dynamic> &&
b['type'] == 'tool_use' &&
b['id'] == toolUseId,
);
});
if (!alreadyPresent) {
mutableMessages.add(assistantMessage);
if (persistSession && recordTranscript != null) {
await recordTranscript(mutableMessages);
}
}
yield {
...assistantMessage,
'session_id': sessionId,
'parent_tool_use_id': null,
};
// Execute the tool.
if (runToolUse != null) {
await for (final update in runToolUse(finalToolUseBlock)) {
if (update.containsKey('message')) {
mutableMessages.add(update['message'] as Map<String, dynamic>);
if (persistSession && recordTranscript != null) {
await recordTranscript(mutableMessages);
}
yield {
...(update['message'] as Map<String, dynamic>),
'session_id': sessionId,
'parent_tool_use_id': null,
};
}
}
}
}