fix(mcp): relax library id and name matching
All checks were successful
Build and publish Docker image / Build and push CPU image (push) Successful in 2m11s
Build and publish Docker image / Build and push GPU image (push) Successful in 3m1s

- accept single-segment library ids like /whisper-rtx2080 returned by
  resolve-library-id in get-library-docs
- accept common owner-qualified aliases such as /mozempk/whisper-rtx2080
  when the indexed repo is stored as a single-segment name
- accept single-segment ids with explicit versions such as
  /whisper-rtx2080/v0.0.1
- relax resolve-library-id scoring across separator-only differences so
  queries like whisperrtx2080 still match whisper-rtx2080
- update MCP tool descriptions to document the accepted id formats

Validated with focused regression tests:
- TrueRefMcpToolsTest
- LibraryResolverTest
This commit is contained in:
moze
2026-05-06 10:53:09 +02:00
parent bfb6bb5e8c
commit 943a38fd36
4 changed files with 224 additions and 18 deletions

View File

@@ -28,6 +28,7 @@ public final class LibraryResolver implements ResolveLibraryId {
private static final Logger log = LoggerFactory.getLogger(LibraryResolver.class);
private static final Pattern SEMVER = Pattern.compile("^v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?.*$");
private static final Pattern NON_ALNUM = Pattern.compile("[^a-z0-9]+");
private final RepositoryStore store;
private final IndexVersion indexer;
@@ -72,7 +73,11 @@ public final class LibraryResolver implements ResolveLibraryId {
private double nameScore(String haystack, String needle) {
if (haystack.equals(needle)) return 1.0;
if (haystack.endsWith("/" + needle) || haystack.startsWith(needle + "/")) return 0.95;
String normalizedHaystack = normalizeName(haystack);
String normalizedNeedle = normalizeName(needle);
if (!normalizedHaystack.isEmpty() && normalizedHaystack.equals(normalizedNeedle)) return 0.92;
if (haystack.contains(needle)) return 0.8;
if (!normalizedNeedle.isEmpty() && normalizedHaystack.contains(normalizedNeedle)) return 0.76;
// token overlap
String[] hTok = haystack.split("[^a-z0-9]+");
String[] nTok = needle.split("[^a-z0-9]+");
@@ -87,6 +92,10 @@ public final class LibraryResolver implements ResolveLibraryId {
return 0.3 + 0.4 * ((double) hit / Math.max(1, nTok.length));
}
private static String normalizeName(String value) {
return NON_ALNUM.matcher(value).replaceAll("");
}
/**
* Maps a version string to the closest matching tag using the repo's configured mapping rules.
* Rules are tried in order.