Repair sentence-transformer embedding config aliases
Patch stale sentence-transformer embedding provider/model aliases at the _model_config read/build boundary so memory embeddings use the intended local HuggingFace provider without adding provider-specific logic to models.py. Cover stale alias forms, the bare default alias, normal OpenAI embedding pass-through, and missing API-key detection with focused regression tests.
Alessandro committed
Jun 17, 2026 at 02:53 UTC
630bfc16f2cb8b7f918c4ac05ca158bc4a216d30
3 files changed
+85
-2
plugins/_model_config/AGENTS.md
+1
@@ -17,6 +17,7 @@
17
- Keep provider metadata and API-key checks safe around secrets.
18
- Coordinate OAuth-backed providers with `_oauth` instead of hardcoding provider-specific auth here.
19
- Applying a model preset may inherit durable tuning such as context windows and rate limits, but must replace or clear per-slot `kwargs` so provider-specific extra params never leak across model providers.
20
+- Repair provider-specific model-config aliases at the model-config read/build boundary; keep provider-specific repairs out of provider-agnostic core wrappers such as `models.py`.
21
22
## Work Guidance
23
plugins/_model_config/helpers/model_config.py
+20
-2
@@ -450,7 +450,25 @@ def get_utility_model_config(agent=None) -> dict:
450
def get_embedding_model_config(agent=None) -> dict:
451
"""Get embedding model config."""
452
cfg = get_config(agent)
453
- return cfg.get("embedding_model", {})
453
+ model_cfg = deepcopy(cfg.get("embedding_model", {}))
454
+ provider = str(model_cfg.get("provider") or "").strip().lower()
455
+ name = str(model_cfg.get("name") or "").strip().strip('"').strip("'")
456
+
457
+ if provider:
458
+ model_cfg["provider"] = provider
459
+ if name:
460
+ model_cfg["name"] = name
461
+
462
+ if name.startswith("huggingface/sentence-transformers/"):
463
+ model_cfg["provider"] = "huggingface"
464
+ model_cfg["name"] = name.removeprefix("huggingface/")
465
+ elif name.startswith("sentence-transformers/") and provider in {"", "openai", "other"}:
466
+ model_cfg["provider"] = "huggingface"
467
+ elif provider == "huggingface" and name == "all-MiniLM-L6-v2":
468
+ model_cfg["name"] = "sentence-transformers/all-MiniLM-L6-v2"
469
+
470
+ return model_cfg
471
+
472
473
def is_chat_override_allowed(agent=None) -> bool:
474
"""Check if per-chat model override is enabled."""
@@ -566,7 +584,7 @@ def get_missing_api_key_providers(agent=None) -> list[dict]:
584
checks = [
585
("Chat Model", cfg.get("chat_model", {})),
586
("Utility Model", cfg.get("utility_model", {})),
569
- ("Embedding Model", cfg.get("embedding_model", {})),
587
+ ("Embedding Model", get_embedding_model_config(agent)),
588
]
589
590
for label, model_cfg in checks:
tests/test_model_config_api_keys.py
+64
@@ -430,6 +430,70 @@ def test_local_provider_runtime_defaults_and_overrides(monkeypatch):
430
assert custom_vllm_chat.kwargs["api_key"] == "real-local-key"
431
432
433
+def test_embedding_config_repairs_sentence_transformer_aliases(monkeypatch):
434
+ from plugins._model_config.helpers import model_config
435
+
436
+ cases = [
437
+ (
438
+ {"provider": "", "name": "sentence-transformers/all-MiniLM-L6-v2"},
439
+ ("huggingface", "sentence-transformers/all-MiniLM-L6-v2"),
440
+ ),
441
+ (
442
+ {"provider": "openai", "name": "sentence-transformers/all-MiniLM-L6-v2"},
443
+ ("huggingface", "sentence-transformers/all-MiniLM-L6-v2"),
444
+ ),
445
+ (
446
+ {
447
+ "provider": "other",
448
+ "name": "huggingface/sentence-transformers/all-MiniLM-L6-v2",
449
+ },
450
+ ("huggingface", "sentence-transformers/all-MiniLM-L6-v2"),
451
+ ),
452
+ (
453
+ {"provider": "huggingface", "name": "all-MiniLM-L6-v2"},
454
+ ("huggingface", "sentence-transformers/all-MiniLM-L6-v2"),
455
+ ),
456
+ ]
457
+
458
+ for raw_embedding, expected in cases:
459
+ monkeypatch.setattr(
460
+ model_config,
461
+ "get_config",
462
+ lambda *args, raw_embedding=raw_embedding, **kwargs: {
463
+ "embedding_model": raw_embedding
464
+ },
465
+ )
466
+ cfg = model_config.get_embedding_model_config_object()
467
+
468
+ assert (cfg.provider, cfg.name) == expected
469
+
470
+ monkeypatch.setattr(
471
+ model_config,
472
+ "get_config",
473
+ lambda *args, **kwargs: {
474
+ "embedding_model": {
475
+ "provider": "openai",
476
+ "name": "text-embedding-3-small",
477
+ }
478
+ },
479
+ )
480
+ cfg = model_config.get_embedding_model_config_object()
481
+
482
+ assert (cfg.provider, cfg.name) == ("openai", "text-embedding-3-small")
483
+
484
+ monkeypatch.setattr(
485
+ model_config,
486
+ "get_config",
487
+ lambda *args, **kwargs: {
488
+ "embedding_model": {
489
+ "provider": "openai",
490
+ "name": "sentence-transformers/all-MiniLM-L6-v2",
491
+ }
492
+ },
493
+ )
494
+ assert model_config.get_missing_api_key_providers() == []
495
+
496
+
497
def test_docker_compose_maps_host_docker_internal_for_local_models():
498
import yaml
499