Skip to main content

sqlite_graphrag/i18n/validation/
messages_embedding.rs

1//! Embedding error message catalog (GAP-SG-132).
2//!
3//! EN+PT user-facing strings for `AppError::Embedding(String)`.
4//!
5//! `EmbeddingErrorKind::classify` matches English substrings case-insensitively:
6//! `oauth`, `quota`, `slot exhausted`, `backend mismatch`, and (`dim` + `zero`).
7//! Portuguese templates MUST retain those English markers so classification
8//! continues to work under either locale.
9
10use crate::i18n::{current, Language};
11use std::fmt::Display;
12
13// ── generic wrapper ──────────────────────────────────────────────────────────
14
15/// Wrap an external / dynamic error detail as an embedding payload.
16pub fn embedding_detail(err: impl Display) -> String {
17    match current() {
18        Language::English => format!("{err}"),
19        Language::Portuguese => format!("{err}"),
20    }
21}
22
23// ── OpenRouter HTTP / client ─────────────────────────────────────────────────
24
25/// Failed to build the reqwest HTTP client for OpenRouter embeddings.
26pub fn embedding_http_client_build_failed(err: impl Display) -> String {
27    match current() {
28        Language::English => format!("failed to build HTTP client: {err}"),
29        Language::Portuguese => format!("falha ao construir cliente HTTP: {err}"),
30    }
31}
32
33/// Empty `data` array in a successful OpenRouter embedding response.
34pub fn embedding_empty_response_from_openrouter() -> String {
35    match current() {
36        Language::English => "empty response from OpenRouter".to_string(),
37        Language::Portuguese => "resposta vazia do OpenRouter".to_string(),
38    }
39}
40
41/// Batch response length mismatch.
42pub fn embedding_expected_count(expected: usize, got: usize) -> String {
43    match current() {
44        Language::English => format!("expected {expected} embeddings, got {got}"),
45        Language::Portuguese => format!("esperados {expected} embeddings, obtidos {got}"),
46    }
47}
48
49/// Provider returned fewer dimensions than requested.
50pub fn embedding_dimension_less_than_requested(got: usize, requested: usize) -> String {
51    match current() {
52        Language::English => format!("embedding dimension {got} < requested {requested}"),
53        Language::Portuguese => {
54            format!("dimensão de embedding {got} < solicitada {requested}")
55        }
56    }
57}
58
59/// OpenRouter embedding request timed out.
60pub fn embedding_openrouter_request_timed_out() -> String {
61    match current() {
62        Language::English => "OpenRouter request timed out".to_string(),
63        Language::Portuguese => "requisição OpenRouter expirou (timeout)".to_string(),
64    }
65}
66
67/// Transient network failure during embedding HTTP.
68pub fn embedding_http_request_failed(err: impl Display) -> String {
69    match current() {
70        Language::English => format!("HTTP request failed: {err}"),
71        Language::Portuguese => format!("requisição HTTP falhou: {err}"),
72    }
73}
74
75/// Failed to read embedding response body.
76pub fn embedding_failed_to_read_response_body(err: impl Display) -> String {
77    match current() {
78        Language::English => format!("failed to read response body: {err}"),
79        Language::Portuguese => format!("falha ao ler corpo da resposta: {err}"),
80    }
81}
82
83/// HTTP 200 body had neither `data` nor `error`.
84pub fn embedding_openrouter_200_neither_data_nor_error() -> String {
85    match current() {
86        Language::English => "OpenRouter 200 response had neither data nor error".to_string(),
87        Language::Portuguese => "resposta OpenRouter 200 sem data nem error".to_string(),
88    }
89}
90
91/// Failed to parse embedding JSON body.
92pub fn embedding_failed_to_parse_response(err: impl Display) -> String {
93    match current() {
94        Language::English => format!("failed to parse embedding response: {err}"),
95        Language::Portuguese => format!("falha ao analisar resposta de embedding: {err}"),
96    }
97}
98
99/// Invalid OpenRouter API key (HTTP 401).
100pub fn embedding_openrouter_invalid_api_key_401() -> String {
101    match current() {
102        Language::English => "invalid OpenRouter API key (HTTP 401)".to_string(),
103        Language::Portuguese => "chave de API OpenRouter inválida (HTTP 401)".to_string(),
104    }
105}
106
107/// OpenRouter hard-failure status with body.
108pub fn embedding_openrouter_returned(status: impl Display, body: &str) -> String {
109    match current() {
110        Language::English => format!("OpenRouter returned {status}: {body}"),
111        Language::Portuguese => format!("OpenRouter retornou {status}: {body}"),
112    }
113}
114
115/// OpenRouter 5xx during embedding.
116pub fn embedding_openrouter_server_error(status: impl Display) -> String {
117    match current() {
118        Language::English => format!("OpenRouter server error: {status}"),
119        Language::Portuguese => format!("erro de servidor OpenRouter: {status}"),
120    }
121}
122
123/// Unexpected HTTP status with body snippet.
124pub fn embedding_unexpected_http(status: impl Display, body: &str) -> String {
125    match current() {
126        Language::English => format!("unexpected HTTP {status}: {body}"),
127        Language::Portuguese => format!("HTTP inesperado {status}: {body}"),
128    }
129}
130
131/// Max retries exhausted for OpenRouter embedding request.
132pub fn embedding_openrouter_max_retries() -> String {
133    match current() {
134        Language::English => "max retries exceeded for OpenRouter request".to_string(),
135        Language::Portuguese => {
136            "número máximo de tentativas excedido para requisição OpenRouter".to_string()
137        }
138    }
139}
140
141// ── runtime / singleton getters ──────────────────────────────────────────────
142
143/// Tokio multi-thread runtime failed to initialise.
144pub fn embedding_tokio_runtime_init_failed(err: impl Display) -> String {
145    match current() {
146        Language::English => format!("tokio runtime init failed: {err}"),
147        Language::Portuguese => format!("falha na inicialização do runtime tokio: {err}"),
148    }
149}
150
151/// Tokio runtime missing after set.
152pub fn embedding_tokio_runtime_unavailable() -> String {
153    match current() {
154        Language::English => "tokio runtime unavailable after initialisation".to_string(),
155        Language::Portuguese => "runtime tokio indisponível após inicialização".to_string(),
156    }
157}
158
159/// OpenRouter embed client singleton missing after set.
160pub fn embedding_openrouter_client_unavailable() -> String {
161    match current() {
162        Language::English => "openrouter client unavailable after initialisation".to_string(),
163        Language::Portuguese => "cliente openrouter indisponível após inicialização".to_string(),
164    }
165}
166
167/// OpenRouter chat client singleton missing after set.
168pub fn embedding_openrouter_chat_client_unavailable() -> String {
169    match current() {
170        Language::English => "openrouter chat client unavailable after initialisation".to_string(),
171        Language::Portuguese => {
172            "cliente de chat openrouter indisponível após inicialização".to_string()
173        }
174    }
175}
176
177// ── backend probes ───────────────────────────────────────────────────────────
178
179/// OpenRouter probe: client not initialised.
180pub fn embedding_openrouter_probe_not_initialised() -> String {
181    match current() {
182        Language::English => "openrouter probe: client not initialised (skip)".to_string(),
183        Language::Portuguese => "probe openrouter: cliente não inicializado (skip)".to_string(),
184    }
185}
186
187/// OpenRouter client not initialised for embed path.
188pub fn embedding_openrouter_client_not_initialised() -> String {
189    match current() {
190        Language::English => {
191            "OpenRouter client not initialised; call get_openrouter_embedder first".to_string()
192        }
193        Language::Portuguese => {
194            "cliente OpenRouter não inicializado; chame get_openrouter_embedder primeiro"
195                .to_string()
196        }
197    }
198}
199
200// ── dimension / validation ───────────────────────────────────────────────────
201
202/// KNN search dim mismatch (memories / entities).
203pub fn embedding_knn_search_dim_mismatch(got: usize, expected: usize) -> String {
204    match current() {
205        Language::English => {
206            format!("knn_search embedding has {got} dims, expected {expected}")
207        }
208        Language::Portuguese => {
209            format!("embedding knn_search tem {got} dims, esperado {expected}")
210        }
211    }
212}
213
214/// KNN search dim mismatch (chunks).
215pub fn embedding_knn_search_chunks_dim_mismatch(got: usize, expected: usize) -> String {
216    match current() {
217        Language::English => {
218            format!("knn_search_chunks embedding has {got} dims, expected {expected}")
219        }
220        Language::Portuguese => {
221            format!("embedding knn_search_chunks tem {got} dims, esperado {expected}")
222        }
223    }
224}
225
226// ── slot / fan-out / batch ───────────────────────────────────────────────────
227
228/// LLM slot semaphore exhausted (marker: `slot exhausted`).
229pub fn embedding_slot_exhausted(err: impl Display) -> String {
230    match current() {
231        Language::English => format!("slot exhausted: {err} (fall back to FTS5)"),
232        // Keep English marker "slot exhausted" for EmbeddingErrorKind::classify.
233        Language::Portuguese => {
234            format!("slot exhausted: {err} (fall back para FTS5)")
235        }
236    }
237}
238
239/// JoinSet join error while embedding.
240pub fn embedding_task_join_error(err: impl Display) -> String {
241    match current() {
242        Language::English => format!("embedding task join error: {err}"),
243        Language::Portuguese => format!("erro de join na tarefa de embedding: {err}"),
244    }
245}
246
247/// Entity embed cache produced a null slot.
248pub fn embedding_entity_cache_null() -> String {
249    match current() {
250        Language::English => "entity embed cache produced null result".to_string(),
251        Language::Portuguese => "cache de embed de entidade produziu resultado nulo".to_string(),
252    }
253}
254
255// ── LLM subprocess embedding ─────────────────────────────────────────────────
256
257// ── dry-run backend guards ───────────────────────────────────────────────────
258
259// ── opencode runner ──────────────────────────────────────────────────────────
260
261/// The legacy ONNX-backed embedding extraction backend was removed in
262/// v1.0.79; `extract` on it is unreachable and reports why.
263pub fn legacy_embedding_backend_removed(model_name: &str) -> String {
264    match current() {
265        Language::English => format!(
266            "legacy embedding backend ({model_name}) was removed in v1.0.79; use the llm backend"
267        ),
268        Language::Portuguese => format!(
269            "o backend de embedding legado ({model_name}) foi removido na v1.0.79; use o backend llm"
270        ),
271    }
272}