6d94be34a9
Send a test completion request after configuration to verify the model is reachable. If validation fails, warn the user and suggest trying a different model or checking their settings. Fixes #335
4.4 KiB
4.4 KiB
Test Spec: uwf setup model connectivity validation (#335)
Context
File: packages/cli-workflow/src/commands/setup.ts
Test file: packages/cli-workflow/src/__tests__/setup-validate.test.ts
After cmdSetup writes config, it should send a test chat completion request to verify the configured model is reachable. If validation fails, warn the user (don't abort — config is already saved).
Implementation Notes
- Add a
validateModel(baseUrl, apiKey, model)function that sends a minimal chat completion request (POST /chat/completionswithmessages: [{role:"user",content:"hi"}],max_tokens: 1) - Returns
Result<void, string>— ok if 2xx response, error with reason string otherwise - Use
AbortSignal.timeout(15_000)for the request - Both
cmdSetupandcmdSetupInteractiveshould call it after saving config cmdSetupreturns validation result in its return object:{ ...existing, validation: { ok: true } | { ok: false, error: string } }cmdSetupInteractiveprints a warning to console if validation fails, success message if it passes- Use the project logger (
createLogger) — no rawconsole.logexcept in interactive CLI output (per CLAUDE.md)
Test Cases (vitest)
1. validateModel — success path
- Mock
fetchto return{ status: 200, ok: true, json: () => ({}) } - Call
validateModel(baseUrl, apiKey, model) - Assert returns
{ ok: true, value: undefined } - Assert fetch was called with correct URL (
${baseUrl}/chat/completions), correct headers (Authorization: Bearer ${apiKey}), correct body (model, messages, max_tokens: 1)
2. validateModel — HTTP error (401 unauthorized)
- Mock
fetchto return{ status: 401, ok: false, statusText: "Unauthorized" } - Call
validateModel(baseUrl, apiKey, model) - Assert returns
{ ok: false, error: <string containing "401"> }
3. validateModel — HTTP error (404 model not found)
- Mock
fetchto return{ status: 404, ok: false, statusText: "Not Found" } - Assert returns
{ ok: false, error: <string containing "404"> }
4. validateModel — network timeout
- Mock
fetchto throwDOMExceptionwith nameAbortError - Assert returns
{ ok: false, error: <string containing "timeout" or "unreachable"> }
5. validateModel — network error (DNS failure, connection refused)
- Mock
fetchto throwTypeError("fetch failed") - Assert returns
{ ok: false, error: <string mentioning connectivity> }
6. cmdSetup — includes validation result on success
- Mock global
fetchfor/chat/completionsto succeed - Call
cmdSetup({ provider, baseUrl, apiKey, model, storageRoot }) - Assert returned object has
validation: { ok: true, value: undefined } - Assert config files are still written (existing behavior preserved)
7. cmdSetup — includes validation result on failure (config still saved)
- Mock global
fetchfor/chat/completionsto return 401 - Call
cmdSetup({ ... }) - Assert returned object has
validation: { ok: false, error: ... } - Assert
config.yamland.envare still written (validation failure doesn't prevent saving)
8. cmdSetupInteractive — prints success message on validation pass
- Mock
fetchfor both/modelsand/chat/completionsto succeed - Mock stdin to provide valid selections
- Capture console output
- Assert output contains a success message like "Model verified" or "✓"
9. cmdSetupInteractive — prints warning on validation failure
- Mock
fetch:/modelssucceeds,/chat/completionsreturns 401 - Mock stdin for valid selections
- Capture console output
- Assert output contains a warning about model not being reachable and suggests trying a different model
10. validateModel — request body correctness
- Mock
fetchto capture the request body - Call
validateModel(baseUrl, apiKey, "test-model") - Assert body is
{ model: "test-model", messages: [{role: "user", content: "hi"}], max_tokens: 1 }
Export Requirements
validateModelmust be exported (for direct unit testing)- Signature:
async function validateModel(baseUrl: string, apiKey: string, model: string): Promise<Result<void, string>> Resulttype:{ ok: true; value: T } | { ok: false; error: E }(project convention)
Files to Create/Modify
- New:
packages/cli-workflow/src/__tests__/setup-validate.test.ts— all test cases above - Modify:
packages/cli-workflow/src/commands/setup.ts— addvalidateModel, integrate intocmdSetupandcmdSetupInteractive