fix(FEEDBACK-0001): complete iteration 0 - harden context search
This commit is contained in:
@@ -25,6 +25,7 @@ import {
|
||||
formatContextTxt,
|
||||
CORS_HEADERS
|
||||
} from '$lib/server/api/formatters';
|
||||
import type { ContextResponseMetadata } from '$lib/server/mappers/context-response.mapper';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Helpers
|
||||
@@ -67,7 +68,32 @@ function getRules(db: ReturnType<typeof getClient>, repositoryId: string): strin
|
||||
|
||||
interface RawRepoState {
|
||||
state: 'pending' | 'indexing' | 'indexed' | 'error';
|
||||
id: string;
|
||||
title: string;
|
||||
source: 'github' | 'local';
|
||||
source_url: string;
|
||||
branch: string | null;
|
||||
}
|
||||
|
||||
interface RawVersionRow {
|
||||
id: string;
|
||||
tag: string;
|
||||
}
|
||||
|
||||
function getSnippetVersionTags(
|
||||
db: ReturnType<typeof getClient>,
|
||||
versionIds: string[]
|
||||
): Record<string, string> {
|
||||
if (versionIds.length === 0) return {};
|
||||
|
||||
const placeholders = versionIds.map(() => '?').join(', ');
|
||||
const rows = db
|
||||
.prepare<string[], RawVersionRow>(
|
||||
`SELECT id, tag FROM repository_versions WHERE id IN (${placeholders})`
|
||||
)
|
||||
.all(...versionIds);
|
||||
|
||||
return Object.fromEntries(rows.map((row) => [row.id, row.tag]));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -131,7 +157,9 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||
|
||||
// Verify the repository exists and check its state.
|
||||
const repo = db
|
||||
.prepare<[string], RawRepoState>(`SELECT state, title FROM repositories WHERE id = ?`)
|
||||
.prepare<[string], RawRepoState>(
|
||||
`SELECT id, state, title, source, source_url, branch FROM repositories WHERE id = ?`
|
||||
)
|
||||
.get(parsed.repositoryId);
|
||||
|
||||
if (!repo) {
|
||||
@@ -162,15 +190,16 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||
|
||||
// Resolve version ID if a specific version was requested.
|
||||
let versionId: string | undefined;
|
||||
let resolvedVersion: RawVersionRow | undefined;
|
||||
if (parsed.version) {
|
||||
const versionRow = db
|
||||
.prepare<[string, string], { id: string }>(
|
||||
`SELECT id FROM repository_versions WHERE repository_id = ? AND tag = ?`
|
||||
resolvedVersion = db
|
||||
.prepare<[string, string], RawVersionRow>(
|
||||
`SELECT id, tag FROM repository_versions WHERE repository_id = ? AND tag = ?`
|
||||
)
|
||||
.get(parsed.repositoryId, parsed.version);
|
||||
|
||||
// Version not found is not fatal — fall back to default branch.
|
||||
versionId = versionRow?.id;
|
||||
versionId = resolvedVersion?.id;
|
||||
}
|
||||
|
||||
// Execute hybrid search (falls back to FTS5 when no embedding provider is set).
|
||||
@@ -193,11 +222,39 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||
return found;
|
||||
});
|
||||
|
||||
const snippetVersionIds = Array.from(
|
||||
new Set(
|
||||
selectedResults
|
||||
.map((result) => result.snippet.versionId)
|
||||
.filter((value): value is string => Boolean(value))
|
||||
)
|
||||
);
|
||||
const snippetVersions = getSnippetVersionTags(db, snippetVersionIds);
|
||||
const metadata: ContextResponseMetadata = {
|
||||
localSource: repo.source === 'local',
|
||||
resultCount: selectedResults.length,
|
||||
repository: {
|
||||
id: repo.id,
|
||||
title: repo.title,
|
||||
source: repo.source,
|
||||
sourceUrl: repo.source_url,
|
||||
branch: repo.branch
|
||||
},
|
||||
version: parsed.version || resolvedVersion
|
||||
? {
|
||||
requested: parsed.version ?? null,
|
||||
resolved: resolvedVersion?.tag ?? null,
|
||||
id: resolvedVersion?.id ?? null
|
||||
}
|
||||
: null,
|
||||
snippetVersions
|
||||
};
|
||||
|
||||
// Load rules from repository_configs.
|
||||
const rules = getRules(db, parsed.repositoryId);
|
||||
|
||||
if (responseType === 'txt') {
|
||||
const text = formatContextTxt(selectedResults, rules);
|
||||
const text = formatContextTxt(selectedResults, rules, metadata);
|
||||
return new Response(text, {
|
||||
status: 200,
|
||||
headers: {
|
||||
@@ -208,7 +265,7 @@ export const GET: RequestHandler = async ({ url }) => {
|
||||
}
|
||||
|
||||
// Default: JSON
|
||||
const body = formatContextJson(selectedResults, rules);
|
||||
const body = formatContextJson(selectedResults, rules, metadata);
|
||||
return dtoJsonResponse(body, {
|
||||
status: 200,
|
||||
headers: CORS_HEADERS
|
||||
|
||||
Reference in New Issue
Block a user