diff --git a/Tuto_Qdrant.MD b/Tuto_Qdrant.MD new file mode 100644 index 0000000000..d38abf1c47 --- /dev/null +++ b/Tuto_Qdrant.MD @@ -0,0 +1,138 @@ +# Tutorial Qdrant no OmniRoute (Guia para vídeo) + +## 1) O que é o Qdrant no OmniRoute +O Qdrant é o banco vetorial usado para memória semântica. + +No OmniRoute, ele ajuda a: +- Encontrar contexto por significado (não só palavra exata). +- Reaproveitar memórias antigas com mais precisão. +- Melhorar respostas com base em histórico relevante. +- Escalar melhor quando a base de memória cresce. + +--- + +## 2) Quando o OmniRoute envia dados para o Qdrant +Com Qdrant habilitado e modelo de embedding configurado, o sistema envia vetores quando: +- Memórias são salvas (upsert de memória). +- Fluxos de chat recuperam contexto semântico/híbrido. +- Testes de busca no painel geram embedding e consultam a coleção. + +Resumo prático: +- Sem Qdrant: busca mais limitada (texto/chave). +- Com Qdrant: busca por similaridade semântica (mais inteligente). + +--- + +## 3) Pré-requisitos +Você precisa de: +- Instância Qdrant acessível (porta 6333). +- Coleção criada (ex.: `omniroute_memory`). +- Modelo de embedding válido (ex.: OpenRouter). +- Credencial do provider do embedding configurada no OmniRoute. + +Exemplo de modelo OpenRouter: +- `openrouter/nvidia/llama-nemotron-embed-v1-1b-v2:free` + +Importante: +- O texto do modelo deve estar em formato `provider/model`. +- Se usar modelo com dimensão diferente da coleção, a busca falha. + +--- + +## 4) Como configurar no painel do OmniRoute +No menu: +- `Admin > Settings > Qdrant (Memória vetorial)` + +Preencha: +- `Ativar Qdrant`: ligado. +- `Host`: IP ou URL do servidor Qdrant (sem porta no campo Host). +- `Porta`: `6333`. +- `Collection`: `omniroute_memory` (ou nome que você criou). +- `Modelo de embedding`: selecione da lista ou digite manualmente. +- `API Key`: opcional (preencha se seu Qdrant exigir). + +Depois: +1. Clique em `Salvar`. +2. Clique em `Testar conexão`. +3. No `Teste de busca`, digite um texto e clique em `Buscar`. + +--- + +## 5) Como criar a coleção no Dashboard do Qdrant (sem comando) +No Qdrant Dashboard: +1. Clique em `Create collection`. +2. Escolha `Global search`. +3. Em tipo de busca, use `Custom`. +4. Configure vetor: + - Vector name: `omniao` (padrão esperado pelo OmniRoute atualmente). + - Size: dimensão do seu modelo de embedding (ex.: 2048 em alguns modelos NVIDIA). + - Distance: `Cosine`. +5. Salve a coleção com nome `omniroute_memory`. + +Se já tinha coleção com dimensão errada: +- Recrie a coleção com dimensão correta. + +--- + +## 6) Como validar se está funcionando +Checklist rápido: +1. `Testar conexão` no OmniRoute retorna OK. +2. Busca no painel retorna resultados (não “Sem resultados”). +3. No Qdrant Dashboard, aparecem pontos na coleção (payload + vector). +4. Resultados de chat passam a recuperar contexto mais relevante. + +Sinal clássico de problema: +- Dados entram no Qdrant, mas busca do painel não retorna nada. + +Causas comuns: +- Dimensão do vetor incompatível. +- Nome do vetor diferente do esperado (`omniao`). +- Modelo inválido/incompleto no campo de embedding. +- Provider sem credencial ativa. + +--- + +## 7) O que melhorou com esta atualização +Nesta melhoria do OmniRoute: +- Suporte a embeddings de qualquer provider compatível (não só OpenAI fixo). +- Endpoint para carregar modelos de embedding na tela de configurações. +- Campo manual para modelo custom quando não aparecer na lista. +- Ajuda visual (`?`) com passo rápido de configuração Qdrant + OpenRouter. + +--- + +## 8) Roteiro curto para seu vídeo +Sugestão de demo (3-5 minutos): +1. Mostrar problema sem Qdrant (busca simples). +2. Abrir Settings e habilitar Qdrant. +3. Configurar host/porta/collection/modelo. +4. Salvar + testar conexão. +5. Fazer `Teste de busca` no painel. +6. Abrir Qdrant Dashboard e mostrar ponto salvo + vetor. +7. Rodar um chat e mostrar melhoria de recuperação semântica. + +Mensagem final para a galera: +- "Qdrant no OmniRoute transforma memória de palavra-chave em memória por significado." + +--- + +## 9) Referências de código (para equipe técnica) +- UI de configuração Qdrant: + - `src/app/(dashboard)/dashboard/settings/components/MemorySkillsTab.tsx` +- Endpoint de modelos de embedding para Qdrant: + - `src/app/api/settings/qdrant/embedding-models/route.ts` +- Integração backend com Qdrant (health, upsert, search, cleanup): + - `src/lib/memory/qdrant.ts` +- Recuperação de memórias no fluxo de chat: + - `src/lib/memory/retrieval.ts` + - `open-sse/handlers/chatCore.ts` + +--- + +## 10) Observação importante de segurança +Nunca exponha em vídeo: +- API key completa do OpenRouter. +- Tokens reais de produção. +- Endpoints internos sem proteção. + +Use chaves mascaradas e ambiente de demonstração. diff --git a/src/app/(dashboard)/dashboard/settings/components/MemorySkillsTab.tsx b/src/app/(dashboard)/dashboard/settings/components/MemorySkillsTab.tsx index 7b2dc38b8c..a2fc51e900 100644 --- a/src/app/(dashboard)/dashboard/settings/components/MemorySkillsTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/MemorySkillsTab.tsx @@ -13,6 +13,21 @@ interface MemoryConfig { skillsEnabled: boolean; } +interface QdrantSettings { + enabled: boolean; + host: string; + port: number; + collection: string; + embeddingModel: string; + hasApiKey: boolean; + apiKeyMasked: string | null; +} + +interface EmbeddingModelOption { + value: string; + label: string; +} + const STRATEGIES = [ { value: "recent", labelKey: "recent", descKey: "recentDesc" }, { value: "semantic", labelKey: "semantic", descKey: "semanticDesc" }, @@ -30,6 +45,35 @@ export default function MemorySkillsTab() { const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [status, setStatus] = useState(""); + + const [qdrant, setQdrant] = useState({ + enabled: false, + host: "", + port: 6333, + collection: "omniroute_memory", + embeddingModel: "openai/text-embedding-3-small", + hasApiKey: false, + apiKeyMasked: null, + }); + const [qdrantApiKeyInput, setQdrantApiKeyInput] = useState(""); + const [qdrantSaving, setQdrantSaving] = useState(false); + const [qdrantStatus, setQdrantStatus] = useState<"" | "saved" | "error">(""); + const [qdrantHealth, setQdrantHealth] = useState<{ + ok: boolean; + latencyMs: number; + error?: string; + } | null>(null); + const [qdrantChecking, setQdrantChecking] = useState(false); + const [qdrantQuery, setQdrantQuery] = useState(""); + const [qdrantSearching, setQdrantSearching] = useState(false); + const [qdrantResults, setQdrantResults] = useState< + Array<{ id: string; score: number; payload?: Record }> + >([]); + const [qdrantCleanupLoading, setQdrantCleanupLoading] = useState(false); + const [qdrantCleanupMsg, setQdrantCleanupMsg] = useState(""); + const [embeddingOptions, setEmbeddingOptions] = useState([]); + const [qdrantHelpOpen, setQdrantHelpOpen] = useState(false); + const [skillsmpApiKey, setSkillsmpApiKey] = useState(""); const [skillsmpSaving, setSkillsmpSaving] = useState(false); const [skillsmpStatus, setSkillsmpStatus] = useState(""); @@ -42,12 +86,21 @@ export default function MemorySkillsTab() { Promise.all([ fetch("/api/settings/memory").then((res) => (res.ok ? res.json() : null)), fetch("/api/settings").then((res) => (res.ok ? res.json() : null)), + fetch("/api/settings/qdrant").then((res) => (res.ok ? res.json() : null)), + fetch("/api/settings/qdrant/embedding-models").then((res) => (res.ok ? res.json() : null)), ]) - .then(([memData, settingsData]) => { + .then(([memData, settingsData, qdrantData, embeddingData]) => { if (memData) setConfig(memData); if (settingsData?.skillsmpApiKey) { setSkillsmpApiKey(settingsData.skillsmpApiKey); } + if (qdrantData) { + setQdrant(qdrantData); + setQdrantApiKeyInput(""); + } + if (embeddingData?.models && Array.isArray(embeddingData.models)) { + setEmbeddingOptions(embeddingData.models); + } if ( settingsData?.skillsProvider === "skillsmp" || settingsData?.skillsProvider === "skillssh" @@ -56,7 +109,111 @@ export default function MemorySkillsTab() { } }) .catch(() => {}) - .finally(() => setLoading(false)); + .finally(() => { + setLoading(false); + }); + }, []); + + const saveQdrant = useCallback( + async (updates: Partial & { apiKey?: string }) => { + const previous = qdrant; + const next = { ...qdrant, ...updates }; + setQdrant(next); + setQdrantSaving(true); + setQdrantStatus(""); + try { + const res = await fetch("/api/settings/qdrant", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + enabled: next.enabled, + host: next.host, + port: next.port, + collection: next.collection, + embeddingModel: next.embeddingModel, + ...(updates.apiKey !== undefined ? { apiKey: updates.apiKey } : {}), + }), + }); + if (res.ok) { + const data = await res.json().catch(() => next); + setQdrant(data); + setQdrantApiKeyInput(""); + setQdrantStatus("saved"); + setTimeout(() => setQdrantStatus(""), 2000); + } else { + setQdrant(previous); + setQdrantStatus("error"); + } + } catch { + setQdrant(previous); + setQdrantStatus("error"); + } finally { + setQdrantSaving(false); + } + }, + [qdrant] + ); + + const checkQdrant = useCallback(async () => { + setQdrantChecking(true); + try { + const res = await fetch("/api/settings/qdrant/health"); + if (res.ok) setQdrantHealth(await res.json()); + else setQdrantHealth({ ok: false, latencyMs: 0, error: "HTTP error" }); + } catch (e) { + setQdrantHealth({ + ok: false, + latencyMs: 0, + error: e instanceof Error ? e.message : String(e), + }); + } finally { + setQdrantChecking(false); + } + }, []); + + const testQdrantSearch = useCallback(async () => { + const q = qdrantQuery.trim(); + if (!q) return; + setQdrantSearching(true); + setQdrantResults([]); + try { + const res = await fetch("/api/settings/qdrant/search", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ query: q, topK: 5 }), + }); + const data = await res.json().catch(() => null); + if (res.ok && data?.ok) { + setQdrantResults(Array.isArray(data.results) ? data.results : []); + } else { + setQdrantResults([]); + } + } catch { + setQdrantResults([]); + } finally { + setQdrantSearching(false); + } + }, [qdrantQuery]); + + const runQdrantCleanup = useCallback(async () => { + setQdrantCleanupLoading(true); + setQdrantCleanupMsg(""); + try { + const res = await fetch("/api/settings/qdrant/cleanup", { method: "POST" }); + const data = await res.json().catch(() => null); + if (res.ok && data?.ok) { + setQdrantCleanupMsg( + `OK: removeu ${data.deletedCount ?? 0} ponto(s) (retencao: ${data.retentionDays} dias)` + ); + } else { + const err = data?.error || "Falha na limpeza"; + setQdrantCleanupMsg(`Erro: ${String(err)}`); + } + } catch (e) { + setQdrantCleanupMsg(`Erro: ${e instanceof Error ? e.message : String(e)}`); + } finally { + setQdrantCleanupLoading(false); + } }, []); const saveSkillsmpApiKey = useCallback(async () => { @@ -280,6 +437,280 @@ export default function MemorySkillsTab() { )} + {/* Qdrant (optional semantic memory index) */} + +
+
+ +
+
+

{t("qdrantTitle")}

+

{t("qdrantDesc")}

+
+ + + +
+ +
+
+

{t("qdrantEnable")}

+

{t("qdrantEnableDesc")}

+
+
+ + +
+
+ + {qdrantStatus === "saved" && ( +
+ check_circle{" "} + {t("qdrantSaved")} +
+ )} + {qdrantStatus === "error" && ( +
{t("qdrantSaveError")}
+ )} + +
+
+ + setQdrant((s) => ({ ...s, host: e.target.value }))} + placeholder="http://127.0.0.1" + className="w-full px-3 py-2 rounded-lg bg-background border border-border text-sm font-mono focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> +

{t("qdrantHostHint")}

+
+ +
+ + + setQdrant((s) => ({ + ...s, + port: Math.max(1, Math.min(65535, Number(e.target.value) || 0)), + })) + } + placeholder="6333" + className="w-full px-3 py-2 rounded-lg bg-background border border-border text-sm font-mono focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> +

{t("qdrantPortHint")}

+
+ +
+ + setQdrant((s) => ({ ...s, collection: e.target.value }))} + placeholder="omniroute_memory" + className="w-full px-3 py-2 rounded-lg bg-background border border-border text-sm font-mono focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> +

{t("qdrantCollectionHint")}

+
+ +
+
+ + +
+ {qdrantHelpOpen && ( +
+

{t("qdrantHelpQuickTitle")}

+

{t("qdrantHelpStep1")}

+

{t("qdrantHelpStep2")}

+

{t("qdrantHelpStep3")}

+

{t("qdrantHelpStep4")}

+
+ )} + + setQdrant((s) => ({ ...s, embeddingModel: e.target.value }))} + placeholder={t("qdrantEmbeddingInputPlaceholder")} + className="w-full px-3 py-2 rounded-lg bg-background border border-border text-sm font-mono focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> +

{t("qdrantEmbeddingHint")}

+
+ +
+ +
+ setQdrantApiKeyInput(e.target.value)} + placeholder={ + qdrant.hasApiKey + ? t("qdrantApiKeyPlaceholderKeep") + : t("qdrantApiKeyPlaceholderOptional") + } + className="flex-1 px-3 py-2 rounded-lg bg-background border border-border text-sm font-mono focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> + {qdrant.hasApiKey && ( + + )} + +
+

{t("qdrantSaveHint")}

+
+
+ +
+
+
+

{t("qdrantSearchTestTitle")}

+

{t("qdrantSearchTestDesc")}

+
+ +
+
+ setQdrantQuery(e.target.value)} + placeholder={t("qdrantSearchPlaceholder")} + className="flex-1 px-3 py-2 rounded-lg bg-background border border-border text-sm focus:outline-none focus:ring-1 focus:ring-emerald-500" + /> +
+ {qdrantResults.length > 0 && ( +
+ {qdrantResults.map((r) => ( +
+
+ {r.id} + + score {r.score.toFixed(4)} + +
+
+ {(r.payload?.key as string) ? `key: ${String(r.payload?.key)}` : null} +
+
+ ))} +
+ )} + {qdrantResults.length === 0 && qdrantQuery.trim().length > 0 && !qdrantSearching && ( +

{t("qdrantNoResults")}

+ )} +
+ +
+
+
+

{t("qdrantCleanupTitle")}

+

+ {t("qdrantCleanupDesc")} {t("retentionDays")} ({config.retentionDays} {t("days")}). +

+
+ +
+ {qdrantCleanupMsg &&

{qdrantCleanupMsg}

} +
+
+ + {/* Skills Settings (placeholder) */}
diff --git a/src/app/api/settings/qdrant/embedding-models/route.ts b/src/app/api/settings/qdrant/embedding-models/route.ts new file mode 100644 index 0000000000..5de80a1488 --- /dev/null +++ b/src/app/api/settings/qdrant/embedding-models/route.ts @@ -0,0 +1,93 @@ +import { NextRequest, NextResponse } from "next/server"; +import { isAuthenticated } from "@/shared/utils/apiAuth"; +import { AI_MODELS } from "@/shared/constants/models"; +import { getProviderConnections } from "@/lib/db/providers"; + +type EmbeddingModelOption = { + value: string; + label: string; +}; + +function isLikelyEmbeddingModel(provider: string, model: string, name: string): boolean { + const haystack = `${provider}/${model} ${name}`.toLowerCase(); + if (haystack.includes("embedding")) return true; + if (haystack.includes("embed")) return true; + if (haystack.includes("text-embedding")) return true; + return false; +} + +export async function GET(request: NextRequest) { + if (!(await isAuthenticated(request))) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } + + try { + const options: EmbeddingModelOption[] = AI_MODELS.filter((m: any) => + isLikelyEmbeddingModel(String(m.provider || ""), String(m.model || ""), String(m.name || "")) + ) + .map((m: any) => ({ + value: `${m.provider}/${m.model}`, + label: `${m.provider}/${m.model} - ${m.name}`, + })) + .sort((a, b) => a.value.localeCompare(b.value)); + + // Add OpenRouter account models that explicitly support embeddings. + try { + const connections = (await getProviderConnections({ + provider: "openrouter", + isActive: true, + })) as Array>; + const apiKey = connections.find( + (c) => typeof c.apiKey === "string" && (c.apiKey as string).trim().length > 0 + )?.apiKey as string | undefined; + + if (apiKey) { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 7000); + let res: Response; + try { + res = await fetch("https://openrouter.ai/api/v1/models?output_modalities=embeddings", { + method: "GET", + headers: { + Authorization: `Bearer ${apiKey}`, + }, + cache: "no-store", + signal: controller.signal, + }); + } finally { + clearTimeout(timeout); + } + if (res.ok) { + const data = (await res.json().catch(() => null)) as any; + const rows = Array.isArray(data?.data) ? data.data : []; + for (const row of rows) { + const id = typeof row?.id === "string" ? row.id.trim() : ""; + if (!id) continue; + const value = `openrouter/${id}`; + if (options.some((o) => o.value === value)) continue; + options.push({ + value, + label: `${value} - ${String(row?.name || id)}`, + }); + } + } + } + } catch { + // Best effort only: keep endpoint fast and resilient. + } + + // Ensure the default always exists as a safe fallback. + if (!options.some((o) => o.value === "openai/text-embedding-3-small")) { + options.unshift({ + value: "openai/text-embedding-3-small", + label: "openai/text-embedding-3-small - OpenAI Text Embedding 3 Small", + }); + } + + options.sort((a, b) => a.value.localeCompare(b.value)); + + return NextResponse.json({ models: options }); + } catch (error) { + return NextResponse.json({ error: String(error), models: [] }, { status: 500 }); + } +} diff --git a/src/app/api/v1/embeddings/route.ts b/src/app/api/v1/embeddings/route.ts index 0bd0b4b246..0cf3bbd16d 100644 --- a/src/app/api/v1/embeddings/route.ts +++ b/src/app/api/v1/embeddings/route.ts @@ -1,35 +1,22 @@ -import { handleEmbedding } from "@omniroute/open-sse/handlers/embeddings.ts"; -import { - getProviderCredentials, - clearRecoveredProviderState, - extractApiKey, - isValidApiKey, -} from "@/sse/services/auth"; import { parseEmbeddingModel, getAllEmbeddingModels, - getEmbeddingProvider, - buildDynamicEmbeddingProvider, - type EmbeddingProviderNodeRow, - type EmbeddingProvider, } from "@omniroute/open-sse/config/embeddingRegistry.ts"; -import { errorResponse, unavailableResponse } from "@omniroute/open-sse/utils/error.ts"; +import { errorResponse } from "@omniroute/open-sse/utils/error.ts"; import { HTTP_STATUS } from "@omniroute/open-sse/config/constants.ts"; import * as log from "@/sse/utils/logger"; -import { toJsonErrorPayload } from "@/shared/utils/upstreamError"; import { enforceApiKeyPolicy } from "@/shared/utils/apiKeyPolicy"; import { v1EmbeddingsSchema } from "@/shared/validation/schemas"; import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; -import { getAllCustomModels, getProviderNodes, getApiKeyMetadata } from "@/lib/localDb"; +import { getAllCustomModels, getApiKeyMetadata } from "@/lib/localDb"; +import { createEmbeddingResponse, type EmbeddingHandlerOptions } from "@/lib/embeddings/service"; +import { extractApiKey, isValidApiKey } from "@/sse/services/auth"; function toProviderScopedModelId(providerId: string, modelId: string): string { return modelId.startsWith(`${providerId}/`) ? modelId : `${providerId}/${modelId}`; } -/** - * Handle CORS preflight - */ export async function OPTIONS() { return new Response(null, { headers: { @@ -39,9 +26,6 @@ export async function OPTIONS() { }); } -/** - * GET /v1/embeddings — list available embedding models - */ export async function GET() { const builtInModels = getAllEmbeddingModels(); const timestamp = Math.floor(Date.now() / 1000); @@ -55,7 +39,6 @@ export async function GET() { dimensions: m.dimensions, })); - // Include custom models tagged for embeddings try { const customModelsMap = (await getAllCustomModels()) as Record; for (const [providerId, models] of Object.entries(customModelsMap)) { @@ -82,163 +65,13 @@ export async function GET() { }); } -/** - * POST /v1/embeddings — create embeddings - */ type ValidatedEmbeddingBody = Record & { model: string }; -interface EmbeddingHandlerOptions { - clientRawRequest?: { - endpoint: string; - body: Record; - headers: Record; - }; - apiKeyId?: string | null; - apiKeyName?: string | null; - connectionId?: string | null; -} - export async function handleValidatedEmbeddingRequestBody( body: ValidatedEmbeddingBody, options: EmbeddingHandlerOptions = {} ) { - // Load local provider_nodes for embedding routing (only localhost — prevents auth bypass/SSRF) - let dynamicProviders: ReturnType[] = []; - try { - const nodes = (await getProviderNodes()) as unknown as EmbeddingProviderNodeRow[]; - dynamicProviders = (Array.isArray(nodes) ? nodes : []) - .filter((n) => { - // provider_nodes apiType is "chat", "responses" or "embeddings" — local OpenAI-compatible - // backends expose /embeddings under the same base URL as chat, so we build the URL as baseUrl + /embeddings. - const validTypes = ["chat", "responses", "embeddings"]; - if (!validTypes.includes(n.apiType || "")) return false; - try { - const hostname = new URL(n.baseUrl).hostname; - // Strictly matching 172.16.0.0/12 (Docker/local) and explicitly blocking ::1 per SSRF hardening - return ( - hostname === "localhost" || - hostname === "127.0.0.1" || - /^172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3}$/.test(hostname) - ); - } catch { - return false; - } - }) - .map((n) => { - try { - return buildDynamicEmbeddingProvider(n); - } catch (err) { - log.error("EMBED", `Skipping invalid provider_node ${n.prefix}: ${err}`); - return null; - } - }) - .filter((p): p is NonNullable => p !== null); - } catch (err) { - log.error("EMBED", `Failed to load provider_nodes for embeddings: ${err}`); - } - - // Parse model to get provider - const { provider, model: resolvedModel } = parseEmbeddingModel(body.model, dynamicProviders); - if (!provider) { - return errorResponse( - HTTP_STATUS.BAD_REQUEST, - `Invalid embedding model: ${body.model}. Use format: provider/model` - ); - } - - // Resolve provider config — dynamic first (local override), then hardcoded - let providerConfig: EmbeddingProvider | null = - dynamicProviders.find((dp) => dp.id === provider) || getEmbeddingProvider(provider) || null; - let credentialsProviderId = provider; - - // #496: Fallback — resolve from ALL provider_nodes (not just localhost) - // This enables custom embedding models (e.g. google/gemini-embedding-001) whose - // providers have remote baseUrls. Safe because getProviderCredentials() authenticates. - if (!providerConfig) { - try { - const allNodes = (await getProviderNodes()) as unknown as EmbeddingProviderNodeRow[]; - const matchingNode = (Array.isArray(allNodes) ? allNodes : []).find( - (n) => - n.prefix === provider && - (n.apiType === "chat" || n.apiType === "responses" || n.apiType === "embeddings") && - n.baseUrl - ); - if (matchingNode) { - const baseUrl = String(matchingNode.baseUrl).replace(/\/+$/, ""); - providerConfig = { - id: matchingNode.prefix, - baseUrl: `${baseUrl}/embeddings`, - authType: "apikey", - authHeader: "bearer", - models: [], - }; - credentialsProviderId = matchingNode.id || provider; - log.info( - "EMBED", - `Resolved custom embedding provider: ${provider} → ${providerConfig.baseUrl}` - ); - } - } catch (err) { - log.error("EMBED", `Failed to resolve custom embedding provider ${provider}: ${err}`); - } - } - - if (!providerConfig) { - return errorResponse( - HTTP_STATUS.BAD_REQUEST, - `Unknown embedding provider: ${provider}. No matching hardcoded or local provider found.` - ); - } - - // Get credentials — skip for local providers (authType: "none") - let credentials = null; - if (providerConfig && providerConfig.authType !== "none") { - credentials = await getProviderCredentials(credentialsProviderId); - if (!credentials) { - return errorResponse( - HTTP_STATUS.BAD_REQUEST, - `No credentials for embedding provider: ${provider}` - ); - } - if (credentials.allRateLimited) { - return unavailableResponse( - HTTP_STATUS.RATE_LIMITED, - `[${provider}] All accounts rate limited`, - credentials.retryAfter, - credentials.retryAfterHuman - ); - } - } - - const result = await handleEmbedding({ - body, - credentials, - log, - resolvedProvider: providerConfig, - resolvedModel, - clientRawRequest: options.clientRawRequest || null, - apiKeyId: options.apiKeyId || null, - apiKeyName: options.apiKeyName || null, - connectionId: options.connectionId || null, - }); - - const responseHeaders = new Headers(result.headers); - - if (result.success) { - if (credentials) await clearRecoveredProviderState(credentials); - responseHeaders.set("Content-Type", "application/json"); - return new Response(JSON.stringify(result.data), { - status: result.status, - headers: responseHeaders, - }); - } - - responseHeaders.set("Content-Type", "application/json"); - const errorPayload = toJsonErrorPayload(result.error, "Embedding provider error"); - return new Response(JSON.stringify(errorPayload), { - status: result.status, - headers: responseHeaders, - }); + return createEmbeddingResponse(body, options); } export async function POST(request) { diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json index 6c3fd9e732..1fec4d9588 100644 --- a/src/i18n/messages/ar.json +++ b/src/i18n/messages/ar.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json index 039acafb3f..615b046d2f 100644 --- a/src/i18n/messages/bg.json +++ b/src/i18n/messages/bg.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/bn.json b/src/i18n/messages/bn.json index b7b05a2aea..f710c34764 100644 --- a/src/i18n/messages/bn.json +++ b/src/i18n/messages/bn.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json index e4efa3613c..7017c186e9 100644 --- a/src/i18n/messages/cs.json +++ b/src/i18n/messages/cs.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json index 0024a90698..5336c71495 100644 --- a/src/i18n/messages/da.json +++ b/src/i18n/messages/da.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json index cb8eb95601..0639d215b7 100644 --- a/src/i18n/messages/de.json +++ b/src/i18n/messages/de.json @@ -3331,7 +3331,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 1d29ba0b34..07b6ef1647 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -3758,7 +3758,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json index a65f9a5c2c..7ca0ac2d41 100644 --- a/src/i18n/messages/es.json +++ b/src/i18n/messages/es.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fa.json b/src/i18n/messages/fa.json index 2c4523b284..7360b369ea 100644 --- a/src/i18n/messages/fa.json +++ b/src/i18n/messages/fa.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json index 483c73dbc1..4e75a03fbf 100644 --- a/src/i18n/messages/fi.json +++ b/src/i18n/messages/fi.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json index 486d3977b5..44326e348d 100644 --- a/src/i18n/messages/fr.json +++ b/src/i18n/messages/fr.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/gu.json b/src/i18n/messages/gu.json index 87a2e40382..1204fe8a7f 100644 --- a/src/i18n/messages/gu.json +++ b/src/i18n/messages/gu.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json index 991232f1a5..e733ca551a 100644 --- a/src/i18n/messages/he.json +++ b/src/i18n/messages/he.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json index 88bbf6aed5..6213615420 100644 --- a/src/i18n/messages/hi.json +++ b/src/i18n/messages/hi.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json index 1d83d74677..0695fbfa9d 100644 --- a/src/i18n/messages/hu.json +++ b/src/i18n/messages/hu.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json index f168e40513..2b554d7928 100644 --- a/src/i18n/messages/id.json +++ b/src/i18n/messages/id.json @@ -3319,7 +3319,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/in.json b/src/i18n/messages/in.json index 46b56fa969..001d49628d 100644 --- a/src/i18n/messages/in.json +++ b/src/i18n/messages/in.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json index 956ee050d6..bdeb16216a 100644 --- a/src/i18n/messages/it.json +++ b/src/i18n/messages/it.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json index f1e57ef338..6f20f605ad 100644 --- a/src/i18n/messages/ja.json +++ b/src/i18n/messages/ja.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json index 9a7682b850..b0200c0c6f 100644 --- a/src/i18n/messages/ko.json +++ b/src/i18n/messages/ko.json @@ -3317,7 +3317,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/mr.json b/src/i18n/messages/mr.json index 53bb9d18de..a05d8fc744 100644 --- a/src/i18n/messages/mr.json +++ b/src/i18n/messages/mr.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json index 85c752a7e8..2745bbf818 100644 --- a/src/i18n/messages/ms.json +++ b/src/i18n/messages/ms.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json index c4b6218998..a72d112ff3 100644 --- a/src/i18n/messages/nl.json +++ b/src/i18n/messages/nl.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json index 006b8cfc9f..5b5a755318 100644 --- a/src/i18n/messages/no.json +++ b/src/i18n/messages/no.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json index c04130056b..35e1d22574 100644 --- a/src/i18n/messages/phi.json +++ b/src/i18n/messages/phi.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json index 54fb413ffa..05ac37dde6 100644 --- a/src/i18n/messages/pl.json +++ b/src/i18n/messages/pl.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json index 999d5eddfc..948ecf47c1 100644 --- a/src/i18n/messages/pt-BR.json +++ b/src/i18n/messages/pt-BR.json @@ -3432,7 +3432,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Memoria vetorial)", + "qdrantDesc": "Opcional. Indexa memorias semanticas em um banco vetorial externo para busca mais rapida.", + "qdrantStatusActive": "Ativo", + "qdrantStatusError": "Com erro", + "qdrantStatusDisabled": "Desativado", + "qdrantEnable": "Ativar Qdrant", + "qdrantEnableDesc": "Quando ativo, a estrategia semantic/hybrid pode usar Qdrant para recuperar memorias.", + "qdrantTesting": "Testando...", + "qdrantTestConnection": "Testar conexao", + "qdrantSaved": "Configuracao salva", + "qdrantSaveError": "Falha ao salvar configuracao", + "qdrantHostHint": "Sem a porta. Ex: 127.0.0.1 ou http://qdrant", + "qdrantPort": "Porta", + "qdrantPortHint": "Padrao do Qdrant: 6333", + "qdrantCollectionHint": "Onde os pontos de memoria serao gravados.", + "qdrantEmbeddingModel": "Modelo de embedding", + "qdrantHelpTitle": "Ajuda rapida de configuracao", + "qdrantHelpQuickTitle": "Configuracao rapida (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: IP/URL do Qdrant, Porta: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. Se usar nvidia/llama-nemotron-embed-vl-1b-v2:free, use dimensao 2048 na collection.", + "qdrantHelpStep3": "3. Modelo no campo: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Salvar, testar conexao e depois testar busca.", + "qdrantEmbeddingQuickSelect": "Selecao rapida de modelos descobertos...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Formato: provider/model. Precisa ter credencial desse provider configurada.", + "qdrantApiKeyPlaceholderKeep": "(deixe vazio para manter)", + "qdrantApiKeyPlaceholderOptional": "(deixe vazio se nao usar)", + "qdrantSaveHint": "Dica: edite host/porta/collection/modelo e clique em Salvar. A chave e opcional.", + "qdrantSearchTestTitle": "Teste de busca", + "qdrantSearchTestDesc": "Gera embedding e faz search no Qdrant.", + "qdrantSearchPlaceholder": "Ex: preferencias do usuario, historico, etc", + "qdrantNoResults": "Sem resultados (ou Qdrant desconfigurado).", + "qdrantCleanupTitle": "Retencao e limpeza", + "qdrantCleanupDesc": "Remove pontos expirados e antigos, baseado em", + "searching": "Buscando...", + "cleaning": "Limpando...", + "cleanNow": "Limpar agora" }, "contextRtk": { "title": "Motor RTK", diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json index 6d5573406e..ebe95cadcb 100644 --- a/src/i18n/messages/pt.json +++ b/src/i18n/messages/pt.json @@ -3402,7 +3402,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Memoria vetorial)", + "qdrantDesc": "Opcional. Indexa memorias semanticas em um banco vetorial externo para busca mais rapida.", + "qdrantStatusActive": "Ativo", + "qdrantStatusError": "Com erro", + "qdrantStatusDisabled": "Desativado", + "qdrantEnable": "Ativar Qdrant", + "qdrantEnableDesc": "Quando ativo, a estrategia semantic/hybrid pode usar Qdrant para recuperar memorias.", + "qdrantTesting": "Testando...", + "qdrantTestConnection": "Testar conexao", + "qdrantSaved": "Configuracao salva", + "qdrantSaveError": "Falha ao salvar configuracao", + "qdrantHostHint": "Sem a porta. Ex: 127.0.0.1 ou http://qdrant", + "qdrantPort": "Porta", + "qdrantPortHint": "Padrao do Qdrant: 6333", + "qdrantCollectionHint": "Onde os pontos de memoria serao gravados.", + "qdrantEmbeddingModel": "Modelo de embedding", + "qdrantHelpTitle": "Ajuda rapida de configuracao", + "qdrantHelpQuickTitle": "Configuracao rapida (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: IP/URL do Qdrant, Porta: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. Se usar nvidia/llama-nemotron-embed-vl-1b-v2:free, use dimensao 2048 na collection.", + "qdrantHelpStep3": "3. Modelo no campo: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Salvar, testar conexao e depois testar busca.", + "qdrantEmbeddingQuickSelect": "Selecao rapida de modelos descobertos...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Formato: provider/model. Precisa ter credencial desse provider configurada.", + "qdrantApiKeyPlaceholderKeep": "(deixe vazio para manter)", + "qdrantApiKeyPlaceholderOptional": "(deixe vazio se nao usar)", + "qdrantSaveHint": "Dica: edite host/porta/collection/modelo e clique em Salvar. A chave e opcional.", + "qdrantSearchTestTitle": "Teste de busca", + "qdrantSearchTestDesc": "Gera embedding e faz search no Qdrant.", + "qdrantSearchPlaceholder": "Ex: preferencias do usuario, historico, etc", + "qdrantNoResults": "Sem resultados (ou Qdrant desconfigurado).", + "qdrantCleanupTitle": "Retencao e limpeza", + "qdrantCleanupDesc": "Remove pontos expirados e antigos, baseado em", + "searching": "Buscando...", + "cleaning": "Limpando...", + "cleanNow": "Limpar agora" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json index dda797a7da..5c510d65e7 100644 --- a/src/i18n/messages/ro.json +++ b/src/i18n/messages/ro.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json index f54a54a5a9..f5e7c2c66c 100644 --- a/src/i18n/messages/ru.json +++ b/src/i18n/messages/ru.json @@ -3339,7 +3339,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json index 2f188e676b..5a0666bf2f 100644 --- a/src/i18n/messages/sk.json +++ b/src/i18n/messages/sk.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json index b65cfdc8ed..4819a48984 100644 --- a/src/i18n/messages/sv.json +++ b/src/i18n/messages/sv.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/sw.json b/src/i18n/messages/sw.json index 46b56fa969..001d49628d 100644 --- a/src/i18n/messages/sw.json +++ b/src/i18n/messages/sw.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ta.json b/src/i18n/messages/ta.json index d198ac96ad..da7cff7a34 100644 --- a/src/i18n/messages/ta.json +++ b/src/i18n/messages/ta.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/te.json b/src/i18n/messages/te.json index a0010cf116..834dfe46e8 100644 --- a/src/i18n/messages/te.json +++ b/src/i18n/messages/te.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json index cc6c537156..8776c4f00a 100644 --- a/src/i18n/messages/th.json +++ b/src/i18n/messages/th.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json index c84ded9329..8bc0fb18d9 100644 --- a/src/i18n/messages/tr.json +++ b/src/i18n/messages/tr.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json index 22bb4570c8..f8d744939d 100644 --- a/src/i18n/messages/uk-UA.json +++ b/src/i18n/messages/uk-UA.json @@ -3315,7 +3315,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/ur.json b/src/i18n/messages/ur.json index bfb0fe242f..e2844cebaf 100644 --- a/src/i18n/messages/ur.json +++ b/src/i18n/messages/ur.json @@ -3472,7 +3472,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json index 4d3c86a0f6..221a85193e 100644 --- a/src/i18n/messages/vi.json +++ b/src/i18n/messages/vi.json @@ -3315,7 +3315,44 @@ "requestBodyLimitSaveFailed": "Failed to save request body limit", "requestBodyLimitSaving": "Saving...", "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}" + "requestBodyLimitCurrent": "Current: {value}", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index d31fab777d..e6cd0d6ca5 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -3424,7 +3424,44 @@ "compressionModeRtk": "RTK", "compressionModeRtkDesc": "Command-aware tool output filtering", "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression" + "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", + "qdrantTitle": "Qdrant (Vector memory)", + "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", + "qdrantStatusActive": "Active", + "qdrantStatusError": "Error", + "qdrantStatusDisabled": "Disabled", + "qdrantEnable": "Enable Qdrant", + "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", + "qdrantTesting": "Testing...", + "qdrantTestConnection": "Test connection", + "qdrantSaved": "Configuration saved", + "qdrantSaveError": "Failed to save configuration", + "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", + "qdrantPort": "Port", + "qdrantPortHint": "Qdrant default: 6333", + "qdrantCollectionHint": "Where memory points will be stored.", + "qdrantEmbeddingModel": "Embedding model", + "qdrantHelpTitle": "Quick setup help", + "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", + "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", + "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", + "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", + "qdrantHelpStep4": "4. Save, test connection, then test search.", + "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", + "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", + "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", + "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", + "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", + "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", + "qdrantSearchTestTitle": "Search test", + "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", + "qdrantSearchPlaceholder": "Example: user preferences, history, etc", + "qdrantNoResults": "No results (or Qdrant is not configured).", + "qdrantCleanupTitle": "Retention and cleanup", + "qdrantCleanupDesc": "Removes expired and old points based on", + "searching": "Searching...", + "cleaning": "Cleaning...", + "cleanNow": "Clean now" }, "contextRtk": { "title": "RTK Engine", diff --git a/src/lib/embeddings/service.ts b/src/lib/embeddings/service.ts new file mode 100644 index 0000000000..a3c5443687 --- /dev/null +++ b/src/lib/embeddings/service.ts @@ -0,0 +1,160 @@ +import { handleEmbedding } from "@omniroute/open-sse/handlers/embeddings.ts"; +import { + parseEmbeddingModel, + getEmbeddingProvider, + buildDynamicEmbeddingProvider, + type EmbeddingProviderNodeRow, + type EmbeddingProvider, +} from "@omniroute/open-sse/config/embeddingRegistry.ts"; +import { errorResponse, unavailableResponse } from "@omniroute/open-sse/utils/error.ts"; +import { HTTP_STATUS } from "@omniroute/open-sse/config/constants.ts"; +import * as log from "@/sse/utils/logger"; +import { toJsonErrorPayload } from "@/shared/utils/upstreamError"; +import { getProviderCredentials, clearRecoveredProviderState } from "@/sse/services/auth"; +import { getProviderNodes } from "@/lib/localDb"; + +type ValidatedEmbeddingBody = Record & { model: string }; + +interface EmbeddingHandlerOptions { + clientRawRequest?: { + endpoint: string; + body: Record; + headers: Record; + }; + apiKeyId?: string | null; + apiKeyName?: string | null; + connectionId?: string | null; +} + +export async function createEmbeddingResponse( + body: ValidatedEmbeddingBody, + options: EmbeddingHandlerOptions = {} +): Promise { + let dynamicProviders: ReturnType[] = []; + try { + const nodes = (await getProviderNodes()) as unknown as EmbeddingProviderNodeRow[]; + dynamicProviders = (Array.isArray(nodes) ? nodes : []) + .filter((n) => { + const validTypes = ["chat", "responses", "embeddings"]; + if (!validTypes.includes(n.apiType || "")) return false; + try { + const hostname = new URL(n.baseUrl).hostname; + return ( + hostname === "localhost" || + hostname === "127.0.0.1" || + /^172\.(1[6-9]|2[0-9]|3[0-1])\.\d{1,3}\.\d{1,3}$/.test(hostname) + ); + } catch { + return false; + } + }) + .map((n) => { + try { + return buildDynamicEmbeddingProvider(n); + } catch (err) { + log.error("EMBED", `Skipping invalid provider_node ${n.prefix}: ${err}`); + return null; + } + }) + .filter((p): p is NonNullable => p !== null); + } catch (err) { + log.error("EMBED", `Failed to load provider_nodes for embeddings: ${err}`); + } + + const { provider, model: resolvedModel } = parseEmbeddingModel(body.model, dynamicProviders); + if (!provider) { + return errorResponse( + HTTP_STATUS.BAD_REQUEST, + `Invalid embedding model: ${body.model}. Use format: provider/model` + ); + } + + let providerConfig: EmbeddingProvider | null = + dynamicProviders.find((dp) => dp.id === provider) || getEmbeddingProvider(provider) || null; + let credentialsProviderId = provider; + + if (!providerConfig) { + try { + const allNodes = (await getProviderNodes()) as unknown as EmbeddingProviderNodeRow[]; + const matchingNode = (Array.isArray(allNodes) ? allNodes : []).find( + (n) => + n.prefix === provider && + (n.apiType === "chat" || n.apiType === "responses" || n.apiType === "embeddings") && + n.baseUrl + ); + if (matchingNode) { + const baseUrl = String(matchingNode.baseUrl).replace(/\/+$/, ""); + providerConfig = { + id: matchingNode.prefix, + baseUrl: `${baseUrl}/embeddings`, + authType: "apikey", + authHeader: "bearer", + models: [], + }; + credentialsProviderId = matchingNode.id || provider; + log.info( + "EMBED", + `Resolved custom embedding provider: ${provider} -> ${providerConfig.baseUrl}` + ); + } + } catch (err) { + log.error("EMBED", `Failed to resolve custom embedding provider ${provider}: ${err}`); + } + } + + if (!providerConfig) { + return errorResponse( + HTTP_STATUS.BAD_REQUEST, + `Unknown embedding provider: ${provider}. No matching hardcoded or local provider found.` + ); + } + + let credentials = null; + if (providerConfig.authType !== "none") { + credentials = await getProviderCredentials(credentialsProviderId); + if (!credentials) { + return errorResponse( + HTTP_STATUS.BAD_REQUEST, + `No credentials for embedding provider: ${provider}` + ); + } + if (credentials.allRateLimited) { + return unavailableResponse( + HTTP_STATUS.RATE_LIMITED, + `[${provider}] All accounts rate limited`, + credentials.retryAfter, + credentials.retryAfterHuman + ); + } + } + + const result = await handleEmbedding({ + body, + credentials, + log, + resolvedProvider: providerConfig, + resolvedModel, + clientRawRequest: options.clientRawRequest || null, + apiKeyId: options.apiKeyId || null, + apiKeyName: options.apiKeyName || null, + connectionId: options.connectionId || null, + }); + + const responseHeaders = new Headers(result.headers); + + if (result.success) { + if (credentials) await clearRecoveredProviderState(credentials); + responseHeaders.set("Content-Type", "application/json"); + return new Response(JSON.stringify(result.data), { + status: result.status, + headers: responseHeaders, + }); + } + + responseHeaders.set("Content-Type", "application/json"); + const errorPayload = toJsonErrorPayload(result.error, "Embedding provider error"); + return new Response(JSON.stringify(errorPayload), { + status: result.status, + headers: responseHeaders, + }); +} diff --git a/src/lib/memory/qdrant.ts b/src/lib/memory/qdrant.ts new file mode 100644 index 0000000000..7b5282ace2 --- /dev/null +++ b/src/lib/memory/qdrant.ts @@ -0,0 +1,409 @@ +import { getSettings } from "@/lib/db/settings"; +import { createEmbeddingResponse } from "@/lib/embeddings/service"; + +type JsonRecord = Record; + +export type QdrantConfig = { + enabled: boolean; + host: string; + port: number; + apiKey: string | null; + collection: string; + embeddingModel: string; +}; + +export function normalizeQdrantConfig(settings: Record): QdrantConfig { + const host = typeof settings.qdrantHost === "string" ? settings.qdrantHost.trim() : ""; + const portRaw = settings.qdrantPort; + const port = + typeof portRaw === "number" && Number.isFinite(portRaw) + ? Math.round(portRaw) + : typeof portRaw === "string" + ? Math.round(Number(portRaw) || 6333) + : 6333; + const apiKey = + typeof settings.qdrantApiKey === "string" && settings.qdrantApiKey.trim().length > 0 + ? settings.qdrantApiKey.trim() + : null; + const collection = + typeof settings.qdrantCollection === "string" && settings.qdrantCollection.trim().length > 0 + ? settings.qdrantCollection.trim() + : "omniroute_memory"; + const embeddingModel = + typeof settings.qdrantEmbeddingModel === "string" && + settings.qdrantEmbeddingModel.trim().length > 0 + ? settings.qdrantEmbeddingModel.trim() + : "openai/text-embedding-3-small"; + const enabled = settings.qdrantEnabled === true; + + return { enabled, host, port, apiKey, collection, embeddingModel }; +} + +export async function getQdrantConfig(): Promise { + const settings = (await getSettings()) as Record; + return normalizeQdrantConfig(settings); +} + +function baseUrl(cfg: QdrantConfig): string { + const host = cfg.host.replace(/\/+$/, ""); + const withProto = + host.startsWith("http://") || host.startsWith("https://") ? host : `http://${host}`; + try { + const url = new URL(withProto); + if (!url.port) url.port = String(cfg.port); + return url.toString().replace(/\/+$/, ""); + } catch { + return `${withProto}:${cfg.port}`; + } +} + +async function qdrantFetch(cfg: QdrantConfig, path: string, init?: RequestInit): Promise { + const headers: Record = { + "content-type": "application/json", + ...(init?.headers as Record | undefined), + }; + if (cfg.apiKey) headers["api-key"] = cfg.apiKey; + + return fetch(`${baseUrl(cfg)}${path}`, { + ...init, + headers, + }); +} + +export async function checkQdrantHealth(): Promise<{ + ok: boolean; + latencyMs: number; + error?: string; +}> { + const cfg = await getQdrantConfig(); + const start = Date.now(); + if (!cfg.enabled || !cfg.host) { + return { ok: false, latencyMs: 0, error: "not_configured" }; + } + + try { + const res = await qdrantFetch(cfg, "/readyz", { method: "GET" }); + const latencyMs = Date.now() - start; + if (!res.ok) { + const text = await res.text().catch(() => ""); + return { ok: false, latencyMs, error: text.slice(0, 200) || `HTTP ${res.status}` }; + } + return { ok: true, latencyMs }; + } catch (err) { + return { + ok: false, + latencyMs: Date.now() - start, + error: err instanceof Error ? err.message : String(err), + }; + } +} + +async function ensureCollection(cfg: QdrantConfig, vectorSize: number): Promise { + const getRes = await qdrantFetch(cfg, `/collections/${encodeURIComponent(cfg.collection)}`, { + method: "GET", + }); + if (getRes.ok) return; + + const createRes = await qdrantFetch(cfg, `/collections/${encodeURIComponent(cfg.collection)}`, { + method: "PUT", + body: JSON.stringify({ + vectors: { size: vectorSize, distance: "Cosine" }, + }), + }); + if (!createRes.ok) { + const text = await createRes.text().catch(() => ""); + throw new Error(text.slice(0, 300) || `Failed to create collection (${createRes.status})`); + } +} + +async function getCollectionVectorName(cfg: QdrantConfig): Promise { + const res = await qdrantFetch(cfg, `/collections/${encodeURIComponent(cfg.collection)}`, { + method: "GET", + }); + if (!res.ok) return null; + const data = (await res.json().catch(() => null)) as any; + const vectors = data?.result?.config?.params?.vectors; + if (!vectors || typeof vectors !== "object" || Array.isArray(vectors)) { + return null; + } + // Unnamed/single-vector config: { size, distance, ... } (not a named map) + if ( + Object.prototype.hasOwnProperty.call(vectors, "size") && + (typeof vectors.size === "number" || typeof vectors.size === "string") + ) { + return null; + } + const names = Object.keys(vectors); + if (names.length === 0) return null; + return names[0] || null; +} + +async function embedText(cfg: QdrantConfig, text: string): Promise { + const modelStr = cfg.embeddingModel.trim(); + if (!modelStr.includes("/")) { + throw new Error(`Invalid embedding model '${modelStr}'. Use provider/model format.`); + } + + const res = await createEmbeddingResponse({ + model: modelStr, + input: text, + }); + if (!res.ok) { + const txt = await res.text().catch(() => ""); + throw new Error(txt.slice(0, 300) || `Embeddings request failed (${res.status})`); + } + const data = (await res.json().catch(() => null)) as any; + const vec = data?.data?.[0]?.embedding; + if (!Array.isArray(vec) || vec.length === 0) { + throw new Error("Embedding response missing vector"); + } + return vec as number[]; +} + +export async function upsertSemanticMemoryPoint(input: { + id: string; + apiKeyId: string; + sessionId: string; + key: string; + content: string; + metadata: JsonRecord; + createdAt: string; + expiresAt: string | null; +}): Promise<{ ok: boolean; latencyMs: number; error?: string }> { + const cfg = await getQdrantConfig(); + if (!cfg.enabled || !cfg.host) return { ok: false, latencyMs: 0, error: "not_configured" }; + + const start = Date.now(); + try { + const vector = await embedText(cfg, `${input.key}\n\n${input.content}`); + await ensureCollection(cfg, vector.length); + const vectorName = await getCollectionVectorName(cfg); + + const createdAtUnix = Math.floor(new Date(input.createdAt).getTime() / 1000); + const expiresAtUnix = input.expiresAt + ? Math.floor(new Date(input.expiresAt).getTime() / 1000) + : null; + + const payload = { + kind: "omniroute_memory", + memoryId: input.id, + apiKeyId: input.apiKeyId || "", + sessionId: input.sessionId || "", + type: "semantic", + key: input.key || "", + content: input.content || "", + metadata: input.metadata || {}, + createdAtUnix, + expiresAtUnix, + }; + + const res = await qdrantFetch( + cfg, + `/collections/${encodeURIComponent(cfg.collection)}/points?wait=true`, + { + method: "PUT", + body: JSON.stringify({ + points: [ + { + id: input.id, + vector: vectorName ? { [vectorName]: vector } : vector, + payload, + }, + ], + }), + } + ); + + const latencyMs = Date.now() - start; + if (!res.ok) { + const text = await res.text().catch(() => ""); + return { ok: false, latencyMs, error: text.slice(0, 300) || `HTTP ${res.status}` }; + } + return { ok: true, latencyMs }; + } catch (err) { + return { + ok: false, + latencyMs: Date.now() - start, + error: err instanceof Error ? err.message : String(err), + }; + } +} + +export async function searchSemanticMemory( + query: string, + topK = 5, + scope?: { apiKeyId?: string; sessionId?: string | null } +): Promise<{ + ok: boolean; + latencyMs: number; + results?: Array<{ id: string; score: number; payload?: JsonRecord }>; + error?: string; +}> { + const cfg = await getQdrantConfig(); + if (!cfg.enabled || !cfg.host) return { ok: false, latencyMs: 0, error: "not_configured" }; + const start = Date.now(); + try { + const vector = await embedText(cfg, query); + await ensureCollection(cfg, vector.length); + const vectorName = await getCollectionVectorName(cfg); + + const res = await qdrantFetch( + cfg, + `/collections/${encodeURIComponent(cfg.collection)}/points/search`, + { + method: "POST", + body: JSON.stringify({ + vector: vectorName ? { name: vectorName, vector } : vector, + limit: Math.max(1, Math.min(20, topK)), + filter: { + must: [ + { key: "kind", match: { value: "omniroute_memory" } }, + ...(scope?.apiKeyId ? [{ key: "apiKeyId", match: { value: scope.apiKeyId } }] : []), + ...(scope?.sessionId + ? [{ key: "sessionId", match: { value: String(scope.sessionId) } }] + : []), + ], + }, + with_payload: true, + }), + } + ); + + const latencyMs = Date.now() - start; + if (!res.ok) { + const text = await res.text().catch(() => ""); + return { ok: false, latencyMs, error: text.slice(0, 300) || `HTTP ${res.status}` }; + } + const data = (await res.json().catch(() => null)) as any; + const result = Array.isArray(data?.result) ? data.result : []; + return { + ok: true, + latencyMs, + results: result.map((r: any) => ({ + id: String(r.id), + score: typeof r.score === "number" ? r.score : 0, + payload: r.payload && typeof r.payload === "object" ? (r.payload as JsonRecord) : undefined, + })), + }; + } catch (err) { + return { + ok: false, + latencyMs: Date.now() - start, + error: err instanceof Error ? err.message : String(err), + }; + } +} + +export async function deleteSemanticMemoryPoint( + id: string +): Promise<{ ok: boolean; latencyMs: number; error?: string }> { + const cfg = await getQdrantConfig(); + if (!cfg.enabled || !cfg.host) return { ok: false, latencyMs: 0, error: "not_configured" }; + const start = Date.now(); + try { + const res = await qdrantFetch( + cfg, + `/collections/${encodeURIComponent(cfg.collection)}/points/delete?wait=true`, + { + method: "POST", + body: JSON.stringify({ points: [id] }), + } + ); + const latencyMs = Date.now() - start; + if (!res.ok) { + const text = await res.text().catch(() => ""); + return { ok: false, latencyMs, error: text.slice(0, 300) || `HTTP ${res.status}` }; + } + return { ok: true, latencyMs }; + } catch (err) { + return { + ok: false, + latencyMs: Date.now() - start, + error: err instanceof Error ? err.message : String(err), + }; + } +} + +export async function cleanupSemanticMemoryPoints(input: { + retentionDays: number; +}): Promise<{ ok: boolean; deletedCount: number; latencyMs: number; error?: string }> { + const cfg = await getQdrantConfig(); + if (!cfg.enabled || !cfg.host) + return { ok: false, deletedCount: 0, latencyMs: 0, error: "not_configured" }; + + const retentionDays = + typeof input.retentionDays === "number" && Number.isFinite(input.retentionDays) + ? Math.max(1, Math.min(3650, Math.round(input.retentionDays))) + : 30; + + const start = Date.now(); + try { + const nowUnix = Math.floor(Date.now() / 1000); + const cutoffUnix = nowUnix - retentionDays * 24 * 60 * 60; + + const filter: Record = { + must: [{ key: "kind", match: { value: "omniroute_memory" } }], + should: [ + { key: "expiresAtUnix", range: { lt: nowUnix } }, + { key: "createdAtUnix", range: { lt: cutoffUnix } }, + ], + }; + + // Count first (so we can show an actual number in the dashboard) + const countRes = await qdrantFetch( + cfg, + `/collections/${encodeURIComponent(cfg.collection)}/points/count`, + { + method: "POST", + body: JSON.stringify({ filter, exact: true }), + } + ); + if (!countRes.ok) { + const text = await countRes.text().catch(() => ""); + return { + ok: false, + deletedCount: 0, + latencyMs: Date.now() - start, + error: text.slice(0, 300) || `HTTP ${countRes.status}`, + }; + } + const countData = (await countRes.json().catch(() => null)) as any; + const toDelete = + typeof countData?.result?.count === "number" && Number.isFinite(countData.result.count) + ? Math.max(0, Math.round(countData.result.count)) + : 0; + + if (toDelete === 0) { + return { ok: true, deletedCount: 0, latencyMs: Date.now() - start }; + } + + const delRes = await qdrantFetch( + cfg, + `/collections/${encodeURIComponent(cfg.collection)}/points/delete?wait=true`, + { + method: "POST", + body: JSON.stringify({ + filter, + }), + } + ); + if (!delRes.ok) { + const text = await delRes.text().catch(() => ""); + return { + ok: false, + deletedCount: 0, + latencyMs: Date.now() - start, + error: text.slice(0, 300) || `HTTP ${delRes.status}`, + }; + } + + return { ok: true, deletedCount: toDelete, latencyMs: Date.now() - start }; + } catch (err) { + return { + ok: false, + deletedCount: 0, + latencyMs: Date.now() - start, + error: err instanceof Error ? err.message : String(err), + }; + } +}