chore: establish learning module baseline
This commit is contained in:
commit
2d04197f3f
2409 files changed
+533050
No files matched your search
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
resolveServerWebSearchProviderId,
|
||||
resolveWebSearchApiKey,
|
||||
resolveWebSearchBaseUrl,
|
||||
resolveWebSearchModel,
|
||||
} from '@/lib/server/provider-config';
|
||||
import { WEB_SEARCH_PROVIDERS } from '@/lib/web-search/constants';
|
||||
import type { BaiduSubSources, WebSearchProviderId } from '@/lib/web-search/types';
|
||||
|
||||
const OFFICIAL_CLIENT_BASE_URLS: Record<WebSearchProviderId, string[]> = {
|
||||
tavily: ['https://api.tavily.com', 'https://api.tavily.com/search'],
|
||||
bocha: [
|
||||
'https://api.bocha.cn',
|
||||
'https://api.bocha.cn/v1',
|
||||
'https://api.bocha.cn/v1/web-search',
|
||||
'https://api.bochaai.com',
|
||||
'https://api.bochaai.com/v1',
|
||||
'https://api.bochaai.com/v1/web-search',
|
||||
],
|
||||
brave: [
|
||||
'https://search.brave.com',
|
||||
'https://search.brave.com/search',
|
||||
'https://api.search.brave.com',
|
||||
],
|
||||
baidu: ['https://qianfan.baidubce.com'],
|
||||
// The bare root is accepted for convenience; the Claude adapter normalizes it
|
||||
// to the /v1 root, since the AI SDK appends "/messages" to the base URL.
|
||||
claude: ['https://api.anthropic.com', 'https://api.anthropic.com/v1'],
|
||||
minimax: [
|
||||
'https://api.minimaxi.com',
|
||||
'https://api.minimaxi.com/v1',
|
||||
'https://api.minimaxi.com/v1/coding_plan',
|
||||
'https://api.minimaxi.com/v1/coding_plan/search',
|
||||
'https://api.minimax.io',
|
||||
'https://api.minimax.io/v1',
|
||||
'https://api.minimax.io/v1/coding_plan',
|
||||
'https://api.minimax.io/v1/coding_plan/search',
|
||||
],
|
||||
doubao: ['https://open.feedcoopapi.com', 'https://open.feedcoopapi.com/search_api/web_search'],
|
||||
searxng: [],
|
||||
};
|
||||
|
||||
function normalizeBaseUrl(value: string): string {
|
||||
return value.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function assertWebSearchProviderId(
|
||||
providerId: string | undefined,
|
||||
): providerId is WebSearchProviderId {
|
||||
return !!providerId && providerId in WEB_SEARCH_PROVIDERS;
|
||||
}
|
||||
|
||||
export function resolveSafeClientWebSearchBaseUrl(
|
||||
providerId: WebSearchProviderId,
|
||||
clientBaseUrl?: string,
|
||||
): string | undefined {
|
||||
const trimmed = clientBaseUrl?.trim();
|
||||
if (!trimmed) return undefined;
|
||||
|
||||
let normalized: string;
|
||||
try {
|
||||
const parsed = new URL(trimmed);
|
||||
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
||||
throw new Error('Invalid protocol');
|
||||
}
|
||||
normalized = normalizeBaseUrl(parsed.toString());
|
||||
} catch {
|
||||
throw new Error(`Unsupported ${WEB_SEARCH_PROVIDERS[providerId].name} base URL`);
|
||||
}
|
||||
|
||||
const allowed = OFFICIAL_CLIENT_BASE_URLS[providerId].map(normalizeBaseUrl);
|
||||
if (!allowed.includes(normalized)) {
|
||||
throw new Error(`Unsupported ${WEB_SEARCH_PROVIDERS[providerId].name} base URL`);
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
export function resolveWebSearchRouteBaseUrl(
|
||||
providerId: WebSearchProviderId,
|
||||
clientBaseUrl?: string,
|
||||
): string | undefined {
|
||||
const safeClientBaseUrl = resolveSafeClientWebSearchBaseUrl(providerId, clientBaseUrl);
|
||||
return resolveWebSearchBaseUrl(providerId, safeClientBaseUrl);
|
||||
}
|
||||
|
||||
export function resolveClassroomWebSearchConfig(input: {
|
||||
webSearchProviderId?: WebSearchProviderId;
|
||||
webSearchApiKey?: string;
|
||||
webSearchModelId?: string;
|
||||
baiduSubSources?: BaiduSubSources;
|
||||
}):
|
||||
| {
|
||||
providerId: WebSearchProviderId;
|
||||
apiKey: string;
|
||||
baseUrl?: string;
|
||||
baiduSubSources?: BaiduSubSources;
|
||||
claudeModelId?: string;
|
||||
}
|
||||
| undefined {
|
||||
const requestedProviderId = assertWebSearchProviderId(input.webSearchProviderId)
|
||||
? input.webSearchProviderId
|
||||
: undefined;
|
||||
const providerId =
|
||||
requestedProviderId ?? (resolveServerWebSearchProviderId() as WebSearchProviderId | undefined);
|
||||
if (!providerId) return undefined;
|
||||
|
||||
const provider = WEB_SEARCH_PROVIDERS[providerId];
|
||||
const apiKey = resolveWebSearchApiKey(providerId, input.webSearchApiKey);
|
||||
if (provider.requiresApiKey && !apiKey) return undefined;
|
||||
|
||||
const baseUrl = resolveWebSearchBaseUrl(providerId);
|
||||
if (provider.requiresBaseUrl && !baseUrl) return undefined;
|
||||
|
||||
return {
|
||||
providerId,
|
||||
apiKey,
|
||||
baseUrl,
|
||||
...(providerId === 'baidu' && input.baiduSubSources
|
||||
? { baiduSubSources: input.baiduSubSources }
|
||||
: {}),
|
||||
...(providerId === 'claude'
|
||||
? { claudeModelId: resolveWebSearchModel('claude', input.webSearchModelId) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user