feat(embedding): gateway provider discovers dimension via GET /v1/models

External-mode tenant pods CrashLoop at startup: Qdrant collection init calls
get_dimension() before any embed(), but GatewayProvider only learns its
dimension lazily after the first embed, and the gateway model isn't an OpenAI
model so the base class can't know it statically.

- Add GatewayProvider._detect_dimension() — the async startup hook the
  vector-sync bootstrap already invokes (vector/qdrant_client.py:
  hasattr(provider, "_detect_dimension")) for Ollama. It GETs the gateway's
  GET /v1/models and sets _dimension from the entry whose id matches the
  configured model. Best-effort: any failure (old gateway, model absent,
  network) leaves _dimension unset so the inherited lazy detect-on-first-embed
  still applies — never fatal. Presents the M2M bearer when configured.
- Switch the default embedding_gateway_model to the gateway's provider-
  namespaced id "mistral/mistral-embed" (the gateway routes on the "/"-prefix
  and sends "mistral-embed" upstream); collapse a duplicated config field.

Pairs with astrolabe-cloud-website#229 (gateway /v1/models, namespaced ids).

Tests: discovery sets dim w/o embed, sends bearer, non-fatal on
404/absent/error, skips when already known.
This commit is contained in:
Chris Coutinho
2026-05-31 23:43:19 +02:00
parent c662d57c4f
commit d84a95842f
3 changed files with 195 additions and 5 deletions
+4 -3
View File
@@ -174,9 +174,10 @@ _DEFAULTS: dict[str, Any] = {
"fact_event_emitter": "none", # none | nats | stdout
"ingest_bus_url": None, # required when ingest_mode=external
"embedding_gateway_url": None, # required when embedding_provider=gateway
# Logical model the gateway routes on (e.g. mistral-embed → Mistral for
# the MVP). Only consulted when embedding_provider=gateway.
"embedding_gateway_model": "mistral-embed",
# Provider-namespaced model the gateway serves, "<provider>/<model>"
# (the gateway routes on the "/"-prefix; mistral/mistral-embed → Mistral
# for the MVP). Only consulted when embedding_provider=gateway.
"embedding_gateway_model": "mistral/mistral-embed",
# Gateway auth: the MCP server is an OIDC *client* in the gateway's own
# M2M realm (parallel to, and distinct from, the tenant realm it already
# serves). It obtains a client-credentials token and the gateway maps the