From 61061dfdcdaad30a9d2d0f1946bbe49aea1c6f0f Mon Sep 17 00:00:00 2001 From: Developers Digest <124798203+developersdigest@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:06:09 -0400 Subject: [PATCH 1/2] fix(cli): fall back to categories after unknown provider lookup --- src/__tests__/alexandria-beta.test.ts | 38 +++++++++++++++++++++++++++ src/commands/list.ts | 23 +++++++++++++--- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/__tests__/alexandria-beta.test.ts b/src/__tests__/alexandria-beta.test.ts index 83d7332bbf..b743132394 100644 --- a/src/__tests__/alexandria-beta.test.ts +++ b/src/__tests__/alexandria-beta.test.ts @@ -904,3 +904,41 @@ it('fails clearly on an unknown thread', async () => { expect(malformed.code).toBe(1); expect(requests).toHaveLength(1); }); + +it('falls back to category browsing after an unknown provider, but preserves other failures', async () => { + responseFor = (body) => + body.alexandria[0].options.providers + ? { + success: true, + data: { + alexandria: [ + { + provider: 'firecrawl', + capability: 'find-tools', + error: { + status: 400, + code: 'invalid_request', + message: + 'Unknown or unavailable providers. Browse the catalogue for accessible IDs; use query for natural-language search.', + }, + }, + ], + }, + } + : catalogue('providers', [{ id: 'amazon-com', provider: 'amazon-com' }]); + const result = await cli(['list', 'shopping', '--json']); + expect(result.code, JSON.stringify(result)).toBe(0); + expect(requests.map(({ body }) => body.alexandria[0].options)).toEqual([ + { providers: ['shopping'], level: 'tools', limit: 20 }, + { categories: ['shopping'], level: 'providers', limit: 20 }, + ]); + expect(result.stdout).toContain('amazon-com'); + requests.length = 0; + responseFor = () => ({ + success: false, + error: 'Rate limit exceeded', + code: 'rate_limited', + }); + expect((await cli(['list', 'shopping', '--json'])).code).toBe(1); + expect(requests).toHaveLength(1); +}); diff --git a/src/commands/list.ts b/src/commands/list.ts index 9dbdfe6565..4f095a81f1 100644 --- a/src/commands/list.ts +++ b/src/commands/list.ts @@ -371,13 +371,30 @@ export async function handleList( } let scope: Selectors = { providers: [path[0]] }; let remaining = path.slice(1); - let result = options.category - ? undefined - : await fetchPage({ + let result; + if (!options.category) { + try { + result = await fetchPage({ ...scope, level: remaining.length ? 'providers' : 'tools', limit, }); + } catch (error) { + const envelope = + error instanceof DiscoveryFailure ? error.envelope : undefined; + const failure = envelope?.data?.alexandria?.[0]?.error ?? envelope; + const message = failure?.message ?? failure?.error; + // An unknown provider can still be a category; other failures must surface. + if ( + failure?.code !== 'unknown_provider' && + !( + typeof message === 'string' && + message.startsWith('Unknown or unavailable providers.') + ) + ) + throw error; + } + } if (!result?.page.total) { scope = { categories: [path[0]] }; result = await fetchPage({ ...scope, level: 'providers', limit }); From cdcfc2c2dceb031cecd9d389e733a5586d690338 Mon Sep 17 00:00:00 2001 From: Developers Digest <124798203+developersdigest@users.noreply.github.com> Date: Thu, 17 Sep 2026 11:06:40 -0400 Subject: [PATCH 2/2] test: use complete API envelope for category fallback --- src/__tests__/alexandria-beta.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/__tests__/alexandria-beta.test.ts b/src/__tests__/alexandria-beta.test.ts index b743132394..3cc1456ea0 100644 --- a/src/__tests__/alexandria-beta.test.ts +++ b/src/__tests__/alexandria-beta.test.ts @@ -910,7 +910,9 @@ it('falls back to category browsing after an unknown provider, but preserves oth body.alexandria[0].options.providers ? { success: true, + scrape_id: 'discovery-1', data: { + creditsCost: 0, alexandria: [ { provider: 'firecrawl',