feat(memory): add shared foundation types, Zod schemas, and roundtrip tests (plan 21 F1)

- src/lib/memory/embedding/types.ts — EmbeddingSource, EmbeddingProviderListing, EmbeddingResolution, EmbeddingResult, EmbeddingError (verbatim §3.1)
- src/shared/schemas/memory.ts — 7 Zod schemas (MemorySettingsExtended, MemoryUpdatePut, RetrievePreview, MemoryReindex, MemorySummarize, EmbeddingProviderListing, MemoryEngineStatus, RetrievePreviewResult) + z.infer types (verbatim §3.2)
- src/shared/schemas/qdrant.ts — 4 Zod schemas (QdrantSettings, QdrantSettingsUpdate, QdrantSearch, QdrantHealthResult) + z.infer types (verbatim §3.3)
- tests/unit/memory-schemas-roundtrip.test.ts — 34 assertions (≥22 required); all pass
This commit is contained in:
diegosouzapw
2026-05-27 22:54:18 -03:00
parent 722e9f41cd
commit 6236b604ec
4 changed files with 638 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
export type EmbeddingSource = "remote" | "static" | "transformers" | "auto";
export interface EmbeddingProviderListing {
provider: string; // e.g. "openai"
hasKey: boolean;
models: Array<{
id: string; // formato `provider/model`, e.g. "openai/text-embedding-3-small"
name: string;
dimensions: number | null;
}>;
}
export interface EmbeddingResolution {
/** Fonte ativa após resolveEmbeddingSource(settings). null = nenhuma disponível → degrada p/ FTS5. */
source: "remote" | "static" | "transformers" | null;
/** Modelo ativo (formato provider/model para remote, "potion-base-8M" para static, "Xenova/all-MiniLM-L6-v2" para transformers). */
model: string | null;
/** Dimensão do vetor produzido. null antes da 1ª chamada (lazy probe). */
dimensions: number | null;
/** Assinatura única usada como chave do vectorStore para detectar troca de modelo. */
signature: string; // ${source}:${model}:${dim}
/** Motivo da escolha (UI exibe no Engine status). */
reason: string; // e.g. "provider openai com key configurada"
}
export interface EmbeddingResult {
vector: Float32Array;
source: "remote" | "static" | "transformers";
model: string;
dimensions: number;
latencyMs: number;
cached: boolean;
}
export interface EmbeddingError {
source: "remote" | "static" | "transformers";
model: string | null;
reason: "no_key" | "model_load_failed" | "request_failed" | "rate_limited" | "timeout" | "unknown";
message: string; // ALWAYS via sanitizeErrorMessage()
}