convertTool method

Map<String, dynamic> convertTool(
  1. Tool tool
)

Convert a Tool to Anthropic API format

Implementation

Map<String, dynamic> convertTool(Tool tool) {
  try {
    // Special handling for web_search tool
    // According to https://docs.claude.com/en/docs/agents-and-tools/tool-use/web-search-tool
    // web_search is a server-side tool with a different format
    if (tool.function.name == 'web_search') {
      final webSearchConfig =
          config.getExtension<WebSearchConfig>('webSearchConfig');

      // Base definition
      final toolDef = <String, dynamic>{
        'type': webSearchConfig?.mode ?? 'web_search_20250305',
        'name': 'web_search',
      };

      // Add optional parameters if webSearchConfig exists
      if (webSearchConfig != null) {
        if (webSearchConfig.maxUses != null) {
          toolDef['max_uses'] = webSearchConfig.maxUses;
        }
        if (webSearchConfig.allowedDomains != null &&
            webSearchConfig.allowedDomains!.isNotEmpty) {
          toolDef['allowed_domains'] = webSearchConfig.allowedDomains;
        }
        if (webSearchConfig.blockedDomains != null &&
            webSearchConfig.blockedDomains!.isNotEmpty) {
          toolDef['blocked_domains'] = webSearchConfig.blockedDomains;
        }
        if (webSearchConfig.location != null) {
          toolDef['user_location'] = {
            'type': 'approximate',
            'city': webSearchConfig.location!.city,
            'region': webSearchConfig.location!.region,
            'country': webSearchConfig.location!.country,
            if (webSearchConfig.location!.timezone != null)
              'timezone': webSearchConfig.location!.timezone,
          };
        }
      }

      return toolDef;
    }

    // Regular tool handling
    final schema = tool.function.parameters.toJson();

    // Anthropic requires input_schema to be a valid JSON Schema object
    // According to official docs, it should be type "object"
    if (schema['type'] != 'object') {
      // Provide helpful error message with suggestion
      throw ArgumentError(
          'Anthropic tools require input_schema to be of type "object". '
          'Tool "${tool.function.name}" has type "${schema['type']}". '
          '\n\nTo fix this, update your tool definition:\n'
          'ParametersSchema(\n'
          '  schemaType: "object",  // <- Change this to "object"\n'
          '  properties: {...},\n'
          '  required: [...],\n'
          ')\n\n'
          'See: https://docs.anthropic.com/en/api/messages#tools');
    }

    // Ensure required fields are present
    final inputSchema = Map<String, dynamic>.from(schema);

    // Add properties if missing (empty object is valid)
    if (!inputSchema.containsKey('properties')) {
      inputSchema['properties'] = <String, dynamic>{};
    }

    return {
      'name': tool.function.name,
      'description': tool.function.description.isNotEmpty
          ? tool.function.description
          : 'No description provided',
      'input_schema': inputSchema,
    };
  } catch (e) {
    // Re-throw with more context
    throw ArgumentError(
        'Failed to convert tool "${tool.function.name}" to Anthropic format: $e');
  }
}