fix(ROUTING-0001): repair repo routing and isolate MCP filtering

This commit is contained in:
Giancarmine Salucci
2026-03-27 19:01:47 +01:00
parent da661efc91
commit d1381f7fc0
10 changed files with 252 additions and 644 deletions

View File

@@ -39,6 +39,7 @@ import { GET as getJobs } from './jobs/+server.js';
import { GET as getJob } from './jobs/[id]/+server.js';
import { GET as getVersions, POST as postVersions } from './libs/[id]/versions/+server.js';
import { GET as getContext } from './context/+server.js';
import { DEFAULT_TOKEN_BUDGET } from '$lib/server/api/token-budget.js';
const NOW_S = Math.floor(Date.now() / 1000);
@@ -325,6 +326,40 @@ describe('API contract integration', () => {
expect(body).toContain('Result count: 0');
});
it('GET /api/v1/context does not token-filter default JSON responses for the UI', async () => {
const repositoryId = seedRepo(db);
const documentId = seedDocument(db, repositoryId);
seedSnippet(db, {
documentId,
repositoryId,
type: 'info',
title: 'Large result',
content: 'Large result body',
tokenCount: DEFAULT_TOKEN_BUDGET + 1
});
seedSnippet(db, {
documentId,
repositoryId,
type: 'info',
title: 'Small result',
content: 'Small result body',
tokenCount: 5
});
const response = await getContext({
url: new URL(
`http://test/api/v1/context?libraryId=${encodeURIComponent(repositoryId)}&query=${encodeURIComponent('result')}`
)
} as never);
expect(response.status).toBe(200);
const body = await response.json();
expect(body.snippets).toHaveLength(2);
expect(body.resultCount).toBe(2);
});
it('GET /api/v1/context returns additive repository and version metadata for versioned results', async () => {
const repositoryId = seedRepo(db);
const versionId = seedVersion(db, repositoryId, 'v18.3.0');

View File

@@ -124,6 +124,7 @@ export const GET: RequestHandler = async ({ url }) => {
}
const responseType = url.searchParams.get('type') ?? 'json';
const applyTokenBudget = responseType === 'txt' || url.searchParams.has('tokens');
const tokensRaw = parseInt(url.searchParams.get('tokens') ?? String(DEFAULT_TOKEN_BUDGET), 10);
const maxTokens = isNaN(tokensRaw) || tokensRaw < 1 ? DEFAULT_TOKEN_BUDGET : tokensRaw;
@@ -212,15 +213,17 @@ export const GET: RequestHandler = async ({ url }) => {
profileId
});
// Apply token budget.
const snippets = searchResults.map((r) => r.snippet);
const selected = selectSnippetsWithinBudget(snippets, maxTokens);
const selectedResults = applyTokenBudget
? (() => {
const snippets = searchResults.map((r) => r.snippet);
const selected = selectSnippetsWithinBudget(snippets, maxTokens);
// Re-wrap selected snippets as SnippetSearchResult for formatters.
const selectedResults = selected.map((snippet) => {
const found = searchResults.find((r) => r.snippet.id === snippet.id)!;
return found;
});
return selected.map((snippet) => {
const found = searchResults.find((r) => r.snippet.id === snippet.id)!;
return found;
});
})()
: searchResults;
const snippetVersionIds = Array.from(
new Set(