Files
trueref-legacy/src/routes/api/v1/settings/embedding/test/+server.ts
Giancarmine Salucci 781d224adc feat(EMBEDDINGS-0001): enable local embedder by default and overhaul settings page
- Wire local embedding provider as the default on startup when no profile is configured
- Refactor embedding settings into dedicated service, DTOs, mappers and models
- Rebuild settings page with profile management UI and live test feedback
- Expose index summary (indexed versions + embedding count) on repo endpoints
- Harden indexing pipeline and context search with additional test coverage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 09:28:01 +01:00

104 lines
3.3 KiB
TypeScript

/**
* GET /api/v1/settings/embedding/test
*
* Tests the active default embedding profile by creating a provider instance
* and checking availability. Returns success with profile metadata or error.
*/
import { json } from '@sveltejs/kit';
import type { RequestHandler } from './$types';
import { LocalEmbeddingProvider } from '$lib/server/embeddings/local.provider';
import { createProviderFromProfile } from '$lib/server/embeddings/registry';
import { EmbeddingProfileEntity } from '$lib/server/models/embedding-profile';
import { EmbeddingProfileMapper } from '$lib/server/mappers/embedding-profile.mapper';
import { handleServiceError } from '$lib/server/utils/validation';
export const GET: RequestHandler = async () => {
try {
const provider = new LocalEmbeddingProvider();
const available = await provider.isAvailable();
return json({
available,
profile: {
id: 'local-default',
providerKind: 'local-transformers',
model: provider.model,
dimensions: provider.dimensions
}
});
} catch (err) {
return handleServiceError(err);
}
};
export const POST: RequestHandler = async ({ request }) => {
try {
const body = await request.json();
if (typeof body !== 'object' || body === null) {
throw new Error('Request body must be a JSON object');
}
const candidate = body as Record<string, unknown>;
if (candidate.providerKind !== 'openai-compatible') {
throw new Error('Only openai-compatible providers can be tested via this endpoint');
}
if (typeof candidate.model !== 'string' || typeof candidate.dimensions !== 'number') {
throw new Error('model and dimensions are required');
}
const provider = createProviderFromProfile(
EmbeddingProfileMapper.fromEntity(
new EmbeddingProfileEntity({
id: typeof candidate.id === 'string' ? candidate.id : 'test-openai-profile',
provider_kind: 'openai-compatible',
title: typeof candidate.title === 'string' ? candidate.title : 'Test Provider',
enabled: true,
is_default: false,
model: candidate.model,
dimensions: candidate.dimensions,
config:
typeof candidate.config === 'object' && candidate.config !== null
? (candidate.config as Record<string, unknown>)
: {},
created_at: Date.now(),
updated_at: Date.now()
})
)
);
const available = await provider.isAvailable();
if (!available) {
return new Response(
JSON.stringify({
error: 'Provider is not available. Check your configuration.'
}),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
// Perform a real embedding call to catch auth / model-name errors.
let dimensions: number;
try {
const results = await provider.embed(['test']);
if (results.length === 0) {
return new Response(
JSON.stringify({ error: 'Provider returned no embeddings for the test input.' }),
{ status: 400, headers: { 'Content-Type': 'application/json' } }
);
}
dimensions = results[0].dimensions;
} catch (embedErr) {
const message = embedErr instanceof Error ? embedErr.message : 'Embedding call failed';
return new Response(JSON.stringify({ error: message }), {
status: 400,
headers: { 'Content-Type': 'application/json' }
});
}
return json({ ok: true, dimensions });
} catch (err) {
return handleServiceError(err);
}
};