Skip to content

Commit 8917b51

Browse files
author
Mateusz
committed
fix: remove calls to non-existent fetchAvailableModels API
Updated health check and model discovery to use loadCodeAssist and hardcoded model lists respectively, avoiding 404 errors on standard Code Assist API endpoints.
1 parent 7267236 commit 8917b51

File tree

4 files changed

+555
-675
lines changed

4 files changed

+555
-675
lines changed

src/connectors/gemini_base/health_check_service.py

Lines changed: 51 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -102,104 +102,75 @@ async def ensure_healthy(self) -> None:
102102
self._backend_name,
103103
)
104104

105-
async def _perform_health_check(self) -> bool:
106-
"""Perform a health check by testing API connectivity.
107-
108-
This method tests actual API connectivity by making a simple request to verify
109-
the OAuth token works and the service is accessible.
110-
111-
Uses the fetchAvailableModels endpoint which is supported by all Code Assist API
112-
variants (standard and sandbox).
113-
114-
Returns:
115-
bool: True if health check passes, False otherwise
116-
"""
117-
try:
118-
# Ensure credentials are available
119-
credentials = self._credential_coordinator.credentials
105+
async def _perform_health_check(self) -> bool:
106+
"""Perform a health check by testing API connectivity.
107+
108+
This method tests actual API connectivity by making a simple request to verify
109+
the OAuth token works and the service is accessible.
110+
111+
Uses the loadCodeAssist endpoint which is supported by all Code Assist API
112+
variants (standard and sandbox).
113+
"""
114+
try:
115+
# Ensure credentials are available
116+
credentials = self._credential_coordinator.credentials
120117
if not credentials or not credentials.access_token:
121118
if logger.isEnabledFor(logging.WARNING):
122119
logger.warning(
123120
"Health check failed for %s - no access token available",
124121
self._backend_name,
125122
)
126-
return False
127-
128-
# Get base URL and headers from endpoint config
129-
base_url = self._endpoint_config.get_base_url().rstrip("/")
130-
headers = self._endpoint_config.get_api_headers(credentials.to_dict())
131-
132-
# Use fetchAvailableModels endpoint for health check
133-
# This endpoint is supported by all Code Assist API variants
134-
fetch_models_url = f"{base_url}/v1internal:fetchAvailableModels"
135-
try:
136-
response = await self._http_client.get(
137-
fetch_models_url, headers=headers, timeout=10.0
138-
)
139-
except httpx.TimeoutException as te:
140-
logger.error(
141-
f"Health check timeout calling {fetch_models_url} for {self._backend_name}: {te}",
142-
exc_info=True,
143-
)
144-
return False
145-
except httpx.RequestError as rexc:
146-
logger.error(
147-
f"Health check connection error calling {fetch_models_url} for {self._backend_name}: {rexc}",
148-
exc_info=True,
149-
)
150-
return False
151-
152-
if response.status_code == 200:
153-
if logger.isEnabledFor(logging.INFO):
154-
logger.info(
155-
"Health check passed for %s - API connectivity verified via fetchAvailableModels",
156-
self._backend_name,
157-
)
158-
return True
159-
160-
# Fallback: use loadCodeAssist which is reliable on Code Assist API
161-
load_url = f"{base_url}/v1internal:loadCodeAssist"
162-
payload = {
163-
"metadata": {
164-
"ideType": "IDE_UNSPECIFIED",
165-
"platform": "PLATFORM_UNSPECIFIED",
166-
"pluginType": "GEMINI",
167-
}
168-
}
169-
try:
170-
response = await self._http_client.post(
171-
load_url, headers=headers, json=payload, timeout=10.0
172-
)
173-
except httpx.TimeoutException as te:
174-
logger.error(
175-
f"Health check timeout calling {load_url} for {self._backend_name}: {te}",
176-
exc_info=True,
177-
)
178-
return False
179-
except httpx.RequestError as rexc:
180-
logger.error(
181-
f"Health check connection error calling {load_url} for {self._backend_name}: {rexc}",
182-
exc_info=True,
183-
)
184-
return False
185-
123+
return False
124+
125+
# Get base URL and headers from endpoint config
126+
base_url = self._endpoint_config.get_base_url().rstrip("/")
127+
headers = self._endpoint_config.get_api_headers(credentials.to_dict())
128+
129+
# Use loadCodeAssist for health check - it's reliable and supported by all variants.
130+
# We skip fetchAvailableModels as it is deprecated/non-existent on some endpoints.
131+
load_url = f"{base_url}/v1internal:loadCodeAssist"
132+
payload = {
133+
"metadata": {
134+
"ideType": "IDE_UNSPECIFIED",
135+
"platform": "PLATFORM_UNSPECIFIED",
136+
"pluginType": "GEMINI",
137+
}
138+
}
139+
try:
140+
response = await self._http_client.post(
141+
load_url, headers=headers, json=payload, timeout=10.0
142+
)
143+
except httpx.TimeoutException as te:
144+
logger.error(
145+
f"Health check timeout calling {load_url} for {self._backend_name}: {te}",
146+
exc_info=True,
147+
)
148+
return False
149+
except httpx.RequestError as rexc:
150+
logger.error(
151+
f"Health check connection error calling {load_url} for {self._backend_name}: {rexc}",
152+
exc_info=True,
153+
)
154+
return False
155+
186156
if response.status_code == 200:
187157
if logger.isEnabledFor(logging.INFO):
188158
logger.info(
189159
"Health check passed for %s via loadCodeAssist",
190160
self._backend_name,
191161
)
192-
return True
193-
162+
return True
163+
194164
if logger.isEnabledFor(logging.WARNING):
195165
logger.warning(
196166
"Health check failed for %s - API returned status %s",
197167
self._backend_name,
198168
response.status_code,
199169
)
200-
return False
201-
202-
except AuthenticationError as e:
170+
return False
171+
172+
except AuthenticationError as e:
173+
203174
logger.error(
204175
f"Health check failed for {self._backend_name} - authentication error: {e}",
205176
exc_info=True,

src/connectors/gemini_base/model_discovery.py

Lines changed: 31 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -43,68 +43,37 @@ def get_fallback_models(self) -> list[str]:
4343
"""
4444
return self._fallback_models.copy()
4545

46-
async def discover(
47-
self,
48-
client: "httpx.AsyncClient",
49-
headers: dict[str, str],
50-
base_url: str,
51-
) -> list[str]:
52-
"""Discover available models from fetchAvailableModels API.
53-
54-
Uses the v1internal:fetchAvailableModels endpoint which returns a dictionary
55-
of available models. The models are extracted from the "models" dictionary keys
56-
in the response.
57-
58-
Args:
59-
client: The HTTP client for API calls.
60-
headers: HTTP headers including authorization.
61-
base_url: The API base URL.
62-
63-
Returns:
64-
List of available model names.
65-
"""
66-
if self._cached_models:
67-
return self._cached_models.copy()
68-
69-
base_url = (base_url or "").rstrip("/")
70-
url = f"{base_url}/v1internal:fetchAvailableModels"
71-
72-
try:
73-
response = await client.get(url, headers=headers, timeout=15.0)
74-
except Exception as exc:
75-
logger.warning(
76-
"Failed to reach fetchAvailableModels endpoint %s: %s",
77-
url,
78-
exc,
79-
exc_info=True,
80-
)
81-
return self.get_fallback_models()
82-
83-
if response.status_code != 200:
84-
logger.debug(
85-
"fetchAvailableModels endpoint %s returned %s: %s",
86-
url,
87-
response.status_code,
88-
response.text[:200] if response.text else "",
89-
)
90-
return self.get_fallback_models()
91-
92-
try:
93-
data = response.json()
94-
models = self._extract_models_from_response(data)
95-
if models:
96-
self._cached_models = models
97-
logger.info(
98-
"Successfully discovered %d models from fetchAvailableModels",
99-
len(models),
100-
)
101-
return models
102-
except Exception as exc:
103-
logger.warning(
104-
"Failed to parse fetchAvailableModels response: %s", exc, exc_info=True
105-
)
106-
107-
return self.get_fallback_models()
46+
async def discover(
47+
self,
48+
client: "httpx.AsyncClient",
49+
headers: dict[str, str],
50+
base_url: str,
51+
) -> list[str]:
52+
"""Return hardcoded model list (API discovery is deprecated).
53+
54+
The v1internal:fetchAvailableModels endpoint is no longer supported on
55+
standard Code Assist API endpoints. This method now returns the hardcoded
56+
fallback list to avoid 404 errors.
57+
58+
Args:
59+
client: The HTTP client (unused).
60+
headers: HTTP headers (unused).
61+
base_url: The API base URL (unused).
62+
63+
Returns:
64+
List of available model names.
65+
"""
66+
if self._cached_models:
67+
return self._cached_models.copy()
68+
69+
if logger.isEnabledFor(logging.INFO):
70+
logger.info(
71+
"Skipping fetchAvailableModels API (deprecated); using hardcoded model list."
72+
)
73+
74+
self._cached_models = self.get_fallback_models()
75+
return self._cached_models.copy()
76+
10877

10978
def _extract_models_from_response(self, data: dict[str, Any]) -> list[str]:
11079
"""Extract model names from the API response.

0 commit comments

Comments
 (0)