8000 ✨ feat: support white list for discover assistant (#5216) · lobehub/lobe-chat@90bb20d · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit 90bb20d

Browse files
authored
✨ feat: support white list for discover assistant (#5216)
* ✨ feat: support white list for discover assistant * improve error status
1 parent 5b0bd68 commit 90bb20d

File tree

7 files changed

+95
-30
lines changed

7 files changed

+95
-30
lines changed

src/app/(backend)/webapi/assistant/store/route.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { NextResponse } from 'next/server';
22

3-
import { DEFAULT_LANG } from '@/const/locale';
43
import { AssistantStore } from '@/server/modules/AssistantStore';
54

65
export const runtime = 'edge';
@@ -11,18 +10,10 @@ export const GET = async (req: Request) => {
1110

1211
const market = new AssistantStore();
1312

14-
let res: Response;
13+
const data = await market.getAgentIndex(locale as any);
1514

16-
res = await fetch(market.getAgentIndexUrl(locale as any));
17-
18-
if (res.status === 404) {
19-
res = await fetch(market.getAgentIndexUrl(DEFAULT_LANG));
20-
}
21-
22-
const data = await res.json();
2315
return NextResponse.json(data);
24-
} catch (e) {
25-
console.error(e);
16+
} catch {
2617
return new Response(`failed to fetch agent market index`, {
2718
headers: {
2819
'Access-Control-Allow-Origin': '*',

src/config/app.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ export const getAppConfig = () => {
4747
PLUGIN_SETTINGS: z.string().optional(),
4848

4949
APP_URL: z.string().optional(),
50+
VERCEL_EDGE_CONFIG: z.string().optional(),
51+
5052
CDN_USE_GLOBAL: z.boolean().optional(),
5153
CUSTOM_FONT_FAMILY: z.string().optional(),
5254
CUSTOM_FONT_URL: z.string().optional(),
@@ -75,6 +77,8 @@ export const getAppConfig = () => {
7577

7678
PLUGIN_SETTINGS: process.env.PLUGIN_SETTINGS,
7779

80+
VERCEL_EDGE_CONFIG: process.env.VERCEL_EDGE_CONFIG,
81+
7882
APP_URL,
7983
CUSTOM_FONT_FAMILY: process.env.CUSTOM_FONT_FAMILY,
8084
CUSTOM_FONT_URL: process.env.CUSTOM_FONT_URL,

src/server/modules/AssistantStore/index.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,35 +7,35 @@ const baseURL = 'https://registry.npmmirror.com/@lobehub/agents-index/v1/files/p
77
describe('AssistantStore', () => {
88
it('should return the default index URL when no language is provided', () => {
99
const agentMarket = new AssistantStore();
10-
const url = agentMarket.getAgentIndexUrl();
10+
const url = agentMarket['getAgentIndexUrl']();
1111
expect(url).toBe(`${baseURL}/index.en-US.json`);
1212
});
1313

1414
it('should return the index URL for a not supported language', () => {
1515
const agentMarket = new AssistantStore();
16-
const url = agentMarket.getAgentIndexUrl('xxx' as any);
16+
const url = agentMarket['getAgentIndexUrl']('xxx' as any);
1717
expect(url).toBe('https://registry.npmmirror.com/@lobehub/agents-index/v1/files/public');
1818
});
1919

2020
it('should return the zh-CN URL for zh locale', () => {
2121
const agentMarket = new AssistantStore();
22-
const url = agentMarket.getAgentIndexUrl('zh' as any);
22+
const url = agentMarket['getAgentIndexUrl']('zh' as any);
2323
expect(url).toBe(
2424
'https://registry.npmmirror.com/@lobehub/agents-index/v1/files/public/index.zh-CN.json',
2525
);
2626
});
2727

2828
it('should return the default URL for en locale', () => {
2929
const agentMarket = new AssistantStore();
30-
const url = agentMarket.getAgentIndexUrl('en' as any);
30+
const url = agentMarket['getAgentIndexUrl']('en' as any);
3131
expect(url).toBe(
3232
'https://registry.npmmirror.com/@lobehub/agents-index/v1/files/public/index.en-US.json',
3333
);
3434
});
3535

3636
it('should return the base URL if the provided language is not supported', () => {
3737
const agentMarket = new AssistantStore();
38-
const url = agentMarket.getAgentIndexUrl('fr' as any);
38+
const url = agentMarket['getAgentIndexUrl']('fr' as any);
3939
expect(url).toBe(baseURL);
4040
});
4141

src/server/modules/AssistantStore/index.ts

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import urlJoin from 'url-join';
33
import { appEnv } from '@/config/app';
44
import { DEFAULT_LANG, isLocaleNotSupport } from '@/const/locale';
55
import { Locales, normalizeLocale } from '@/locales/resources';
6+
import { EdgeConfig } from '@/server/modules/EdgeConfig';
7+
import { AgentStoreIndex } from '@/types/discover';
68

79
export class AssistantStore {
810
private readonly baseUrl: string;
@@ -11,7 +13,7 @@ export class AssistantStore {
1113
this.baseUrl = baseUrl || appEnv.AGENTS_INDEX_URL;
1214
}
1315

14-
getAgentIndexUrl = (lang: Locales = DEFAULT_LANG) => {
16+
private getAgentIndexUrl = (lang: Locales = DEFAULT_LANG) => {
1517
if (isLocaleNotSupport(lang)) return this.baseUrl;
1618

1719
return urlJoin(this.baseUrl, `index.${normalizeLocale(lang)}.json`);
@@ -22,4 +24,40 @@ export class AssistantStore {
2224

2325
return urlJoin(this.baseUrl, `${identifier}.${normalizeLocale(lang)}.json`);
2426
};
27+
28+
getAgentIndex = async (locale: Locales = DEFAULT_LANG, revalidate?: number) => {
29+
try {
30+
let res: Response;
31+
32+
res = await fetch(this.getAgentIndexUrl(locale as any), { next: { revalidate } });
33+
34+
if (res.status === 404) {
35+
res = await fetch(this.getAgentIndexUrl(DEFAULT_LANG), { next: { revalidate } });
36+
}
37+
38+
if (!res.ok) {
39+
console.error('fetch agent index error:', await res.text());
40+
return [];
41+
}
42+
43+
const data: AgentStoreIndex = await res.json();
44+
45+
// Get the assistant whitelist from Edge Config
46+
const edgeConfig = new EdgeConfig();
47+
48+
if (!!appEnv.VERCEL_EDGE_CONFIG) {
49+
const assistantWhitelist = await edgeConfig.getAgentWhitelist();
50+
51+
if (assistantWhitelist && assistantWhitelist?.length > 0) {
52+
data.agents = data.agents.filter((item) => assistantWhitelist.includes(item.identifier));
53+
}
54+
}
55+
56+
return data;
57+
} catch (e) {
58+
console.error('fetch agent index error:', e);
59+
60+
throw e;
61+
}
62+
};
2563
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { EdgeConfigClient, createClient } from '@vercel/edge-config';
2+
3+
import { appEnv } from '@/config/app';
4+
5+
enum EdgeConfigKeys {
6+
/**
7+
* Assistant whitelist
8+
*/
9+
AssistantWhitelist = 'assistant_whitelist',
10+
}
11+
12+
export class EdgeConfig {
13+
get client(): EdgeConfigClient {
14+
if (!appEnv.VERCEL_EDGE_CONFIG) {
15+
throw new Error('VERCEL_EDGE_CONFIG is not set');
16+
}
17+
return createClient(appEnv.VERCEL_EDGE_CONFIG);
18+
}
19+
20+
getAgentWhitelist = async (): Promise<string[] | undefined> => {
21+
return this.client.get<string[]>(EdgeConfigKeys.AssistantWhitelist);
22+
};
23+
}

src/server/services/discover/index.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,9 @@ export class DiscoverService {
5050
};
5151

5252
getAssistantList = async (locale: Locales): Promise<DiscoverAssistantItem[]> => {
53-
let res = await fetch(this.assistantStore.getAgentIndexUrl(locale), {
54-
next: { revalidate },
55-
});
56-
57-
if (!res.ok) {
58-
res = await fetch(this.assistantStore.getAgentIndexUrl(DEFAULT_LANG), {
59-
next: { revalidate },
60-
});
61-
}
62-
63-
if (!res.ok) return [];
64-
65-
const json = await res.json();
53+
const json = await this.assistantStore.getAgentIndex(locale, revalidate);
6654

55+
// @ts-expect-error 目前类型不一致,未来要统一
6756
return json.agents;
6857
};
6958

src/types/discover.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,23 @@ export interface FilterBy {
154154
token?: number;
155155
vision?: boolean;
156156
}
157+
158+
interface AgentIndexItem {
159+
author: string;
160+
createAt: string;
161+
createdAt: string;
162+
homepage: string;
163+
identifier: string;
164+
meta: {
165+
avatar: string;
166+
category: string;
167+
description: string;
168+
tags: string[];
169+
title: string;
170+
};
171+
}
172+
173+
export interface AgentStoreIndex {
174+
agents: AgentIndexItem[];
175+
schemaVersion: number;
176+
}

0 commit comments

Comments
 (0)
0