fix(web,llm): address review — document the card contract, pin the host diagnosis, gate the probe

This commit is contained in:
Yichen Jiang
2026-08-07 11:02:38 +08:00
parent 6b75bb0425
commit 1019f149c4
14 changed files with 104 additions and 15 deletions

View File

@@ -325,8 +325,10 @@ describe('probe key format', () => {
})
it('reports a blank probe key as a credential fault too', async () => {
// A cleared form field arrives as '', not an absent key; it must fail the
// same way a typed-in illegal key does, rather than probing unauthenticated.
// The Models page omits `apiKey` entirely for a cleared field rather than
// sending '', so this pins the contract for every other caller: a supplied
// key is judged, and only an absent one probes unauthenticated. '' means
// "I have a key" and is answered as the empty key it is.
await expect(discoverModels({
baseURL: 'https://acme.test',
api: 'openai-completions',

View File

@@ -145,11 +145,16 @@ export class LlmError extends HarnessError {
export function assertUsableApiKey(raw: string, pkg: string, ref: string): string {
const checked = normalizeApiKey(raw)
if (checked.ok) return checked.value
// The Models page is named as the writer it usually is, not as the only one:
// the same value can arrive from a hand-edited .env or a shell export in a
// composition that mounts no credentials seam at all, where directing the
// user to a page that deployment does not serve would be a dead end.
throw new LlmError(
checked.reason === 'empty'
? `${pkg}: the API key stored as ${ref} is blank; re-enter it on the web Models page`
: `${pkg}: the API key stored as ${ref} contains characters no HTTP header can carry;`
+ ' re-enter it on the web Models page, pasting the raw key only',
? `${pkg}: the API key resolved from ${ref} is blank; set ${ref} to the raw key`
+ ' (the web Models page writes it) or export it in the launching environment'
: `${pkg}: the API key resolved from ${ref} contains characters no HTTP header can carry;`
+ ` set ${ref} to the raw key alone (the web Models page writes it)`,
INVALID_CREDENTIAL_CODE,
)
}

View File

@@ -45,7 +45,7 @@ describe('assertUsableApiKey', () => {
it('refuses a blank stored credential, naming the reference', () => {
expect(() => assertUsableApiKey(' ', 'llm-deepseek', 'DEEPSEEK_API_KEY'))
.toThrow(/llm-deepseek: the API key stored as DEEPSEEK_API_KEY is blank/)
.toThrow(/llm-deepseek: the API key resolved from DEEPSEEK_API_KEY is blank/)
})
it('refuses an unusable stored credential with the invalid-credential code', () => {