fix(llm-pi-ai): withhold OAuth-only providers from the configurable directory
pi-ai resolves an OAuth provider from a stored OAuth credential alone, and this adapter builds its Models collection with no credential store and runs no login flow. `openai-codex` — the one installed provider declaring `auth.oauth` with no `auth.apiKey` — was therefore offered on the Models page with the keyless placeholder every pi-ai route carries, and every request on it failed `Provider is not configured` before going out. `catalogProviderTakesApiKey()` answers whether pi-ai's installed provider for a route declares the one method this adapter can supply, and the directory skips the catalog routes that fail it. Catalog membership is unchanged, so `declared` still answers what pi-ai ships; the profile half of the union stays unconditional, so a route a settings document already names keeps its entry and can be edited or deleted. Resolution is untouched: a profile naming `apiKeyEnv` on such a route still builds a working provider.
This commit is contained in:
@@ -933,4 +933,39 @@ describe('configurable-provider directory', () => {
|
||||
await ctx.settings.replace(settingsNamespace('llm-pi-ai'), {})
|
||||
expect(ctx.llm.listConfigurableProviders()).toHaveLength(catalogOnly)
|
||||
})
|
||||
|
||||
it('withholds a catalog route this adapter cannot authenticate', async () => {
|
||||
const ctx = await harness({})
|
||||
const offered = ctx.llm.listConfigurableProviders().map(entry => entry.provider)
|
||||
|
||||
// `openai-codex` is the one installed provider that authenticates through
|
||||
// OAuth alone. pi-ai resolves OAuth only from a *stored* credential, this
|
||||
// adapter constructs its collection with no credential store, and nothing
|
||||
// here runs a login flow — so every request on such a route fails with
|
||||
// `Provider is not configured` before it goes out. Offering it would put a
|
||||
// provider on the settings page that no amount of configuration can make
|
||||
// work.
|
||||
expect(offered).not.toContain('openai-codex')
|
||||
// A provider that offers OAuth *beside* an api-key method keeps its entry:
|
||||
// the key is a path this adapter can serve.
|
||||
expect(offered).toContain('anthropic')
|
||||
expect(offered).toContain('openai')
|
||||
})
|
||||
|
||||
it('still lists a withheld route a stored profile names, as a catalog route', async () => {
|
||||
// Withholding the offer must not strand a profile someone already stored:
|
||||
// the route keeps its entry so a configuration surface can edit or delete
|
||||
// it, and `declared` still answers catalog membership rather than the
|
||||
// offer, so the page does not mislabel it as a route this deployment
|
||||
// invented.
|
||||
const ctx = await harness({ providers: { 'openai-codex': { apiKeyEnv: KEY_ENV } } })
|
||||
|
||||
expect(ctx.llm.listConfigurableProviders()).toContainEqual({
|
||||
provider: 'openai-codex',
|
||||
displayName: 'openai-codex',
|
||||
settingsNs: 'llm-pi-ai',
|
||||
settingsPath: ['providers', 'openai-codex'],
|
||||
declared: false,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user