feat(models): verify provider connection when saving an AI model#495
Merged
Conversation
Saving the AI model form now runs a minimal, type-appropriate probe against the provider first (text: 1 short completion, embedding: one embed call, audio/video: tiny silent WAV transcription) and blocks the save with an actionable inline error (auth / not found / unreachable) when it fails. On edit the probe only runs when connection config changed and reuses the stored API key via model_id. Also fixes mapModelError to unwrap Result.tryPromise's UnhandledException wrapper so model routes return their intended status codes instead of 500. Closes #466
Contributor
|
| Filename | Overview |
|---|---|
| apps/api/src/routes/models.ts | Adds the model test endpoint, stored-key probe flow, validation before probing, and wrapped model-route error handling. |
| apps/frontend/components/admin/ModelFormDialog.tsx | Adds connection-change detection, pre-save probing, stored-key references on edit, and inline probe errors. |
| apps/frontend/lib/api/models.ts | Adds the frontend API helper for the model connection test endpoint. |
| packages/ai/src/probe.ts | Adds model probe execution, provider error classification, and a generated silent WAV payload for transcription probes. |
| packages/contracts/src/routes.ts | Adds the model test request and result contract types. |
Reviews (2): Last reviewed commit: "docs(api): note stored-key reuse trust m..." | Re-trigger Greptile
m43i
approved these changes
Jul 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Saving the AI model form now verifies the connection against the provider first. A new admin-only
POST /models/testendpoint runs a minimal, type-appropriate probe with the submitted configuration (without persisting anything); if it fails, the dialog blocks the save and shows an actionable inline error (auth / model not found / unreachable) including the provider's message.Type of Change
Changes Made
packages/ai/src/probe.ts(new):probeModelConfigurationsends a minimal probe per model type — text/subagent/extract/image: a tiny completion; embedding: one embed call; audio/video: transcription of a generated 0.5 s silent WAV — with a 15 s timeout and no retries, and classifies failures intoauth,not_found,unreachable, orunknownwith the provider message.POST /models/testinapps/api/src/routes/models.ts, gated byrequireOrganizationAdminlike the other model admin routes. A blank API key together withmodel_idreuses the stored (write-only) key, so the edit flow can test without re-entering credentials.ModelFormDialogruns the probe on save — on create always, on edit only when connection config changed (adapter, provider model, key, URL, resource name), so a pure rename never fails on an unreachable provider. Failures render inline above the footer and clear when a connection field changes. de + en strings.mapModelErrorto unwrapResult.tryPromise'sUnhandledExceptionwrapper (same pattern asmapChatError); previously every model-route error (including the existingINVALID_MODEL/MODEL_NOT_FOUNDpaths) surfaced as 500.Related Issues
Closes #466
Testing
Unit tests for the probe classification and WAV payload (
packages/ai/src/__tests__/probe.test.ts) plus newModelFormDialogtests for blocked saves, probe-skipping on rename, and the stored-key reference. Verified end-to-end against the dev stack: wrong key → auth, dead endpoint → unreachable, stored-key flow for text and embedding models → success; in the browser: save with a broken provider model shows the error and keeps the dialog open, a valid config saves and closes.Checklist
make generateif SQL queries were modified (backend)Screenshots (if applicable)
Failed probe blocks the save and shows the reason plus the provider detail inline above the dialog footer.