createRecommendPackagesTool function
Tool<Object, ToolOptions, Object>
createRecommendPackagesTool(
)
Implementation
Tool createRecommendPackagesTool() {
return Tool.fromFunction<RecommendPackagesInput, String>(
name: 'recommend_packages',
description:
'Intelligently compare multiple packages and recommend the best option based on comprehensive scoring. '
'SCORING: Combines objective metrics (pub points, popularity, likes, maintenance) with YOUR analysis. '
'YOU MUST: Assign descriptionScore (0.0-1.0) for each package based on how well it matches user requirements. '
'HOW: Read each package description/features, analyze fit for user needs, assign honest score. '
'Higher descriptionScore = better match. Be analytical and fair. '
'Returns: Ranked list with total scores, detailed breakdown, and recommendation reasoning.',
inputJsonSchema: object({
'packages': object({
'name':
string().min(1).meta(MetadataEntry(description: 'Package name')),
'pubPoints':
number().meta(MetadataEntry(description: 'Pub points scored')),
'popularity':
number().meta(MetadataEntry(description: 'Popularity percentage')),
'likes': number().meta(MetadataEntry(description: 'Number of likes')),
'descriptionScore': number()
.between(0, 1,
message:
'Description score must be between 0-1 it can be 0.1,0.2.0.5,0.9 and so on')
.meta(MetadataEntry(
description:
'YOUR ANALYSIS: How well does this package match user requirements? '
'1.0=perfect, 0.8-0.9=excellent, 0.6-0.7=good, 0.4-0.5=partial, 0.0-0.3=poor. '
'Analyze package description and features carefully.')),
'publisher':
string().meta(MetadataEntry(description: 'Package publisher')),
'lastUpdated': string()
.meta(MetadataEntry(description: 'Last updated date in ISO8601')),
})
.optionals(['publisher', 'lastUpdated', 'descriptionScore'])
.list()
.meta(MetadataEntry(
description: 'List of packages with their metrics')),
'userQuery': string().meta(
MetadataEntry(description: 'Original user search query for context')),
}).optionals(['userQuery']).toJsonSchema(),
func: (RecommendPackagesInput input) async {
if (input.packages.isEmpty) {
return 'No packages provided to compare.';
}
final metricsList = <PackageMetrics>[];
for (final pkgData in input.packages) {
try {
metricsList.add(PackageMetrics.fromPackageData(
name: pkgData['name'] as String,
grantedPoints: pkgData['pubPoints'] as int? ?? 0,
maxPoints: 140,
popularity: pkgData['popularity'] as int? ?? 0,
likes: pkgData['likes'] as int? ?? 0,
publisher: pkgData['publisher'] as String?,
lastUpdated: pkgData['lastUpdated'] != null
? DateTime.tryParse(pkgData['lastUpdated'] as String)
: null,
descriptionScore: (pkgData['descriptionScore'] as num?)?.toDouble(),
));
} catch (e) {
return '❌ Invalid package data: $pkgData\nError: $e';
}
}
return PackageRecommendationEngine.comparePackages(metricsList);
},
getInputFromJson: (json) => RecommendPackagesInput.fromJson(json),
handleToolError: (e) {
return 'Recommend packages tool error: ${e.toString()}';
},
);
}