feat(web-search): use resource_url from credentials for DashScope endpoint

This commit is contained in:
pomelo-nwu
2025-11-04 16:59:30 +08:00
parent 512c91a969
commit d1507e73fe

View File

@@ -98,29 +98,53 @@ export class DashScopeProvider extends BaseWebSearchProvider {
} }
/** /**
* Get the access token for authentication. * Get the access token and API endpoint for authentication and web search.
* Tries OAuth credentials first, falls back to apiKey if OAuth is not available. * Tries OAuth credentials first, falls back to apiKey if OAuth is not available.
* Returns both token and endpoint to avoid loading credentials multiple times.
*/ */
private async getAccessToken(): Promise<string | null> { private async getAuthConfig(): Promise<{
// Try to load OAuth credentials first accessToken: string | null;
apiEndpoint: string;
}> {
// Load credentials once
const credentials = await loadQwenCredentials(); const credentials = await loadQwenCredentials();
// Get access token: try OAuth credentials first, fallback to apiKey
let accessToken: string | null = null;
if (credentials?.access_token) { if (credentials?.access_token) {
// Check if token is not expired // Check if token is not expired
if (credentials.expiry_date && credentials.expiry_date > Date.now()) { if (credentials.expiry_date && credentials.expiry_date > Date.now()) {
return credentials.access_token; accessToken = credentials.access_token;
} }
} }
if (!accessToken) {
accessToken = this.config.apiKey || null;
}
// Fallback to apiKey from config if OAuth is not available // Get API endpoint: use resource_url from credentials
return this.config.apiKey || null; if (!credentials?.resource_url) {
throw new Error(
'No resource_url found in credentials. Please authenticate using OAuth',
);
}
// Normalize the URL: add protocol if missing
const baseUrl = credentials.resource_url.startsWith('http')
? credentials.resource_url
: `https://${credentials.resource_url}`;
// Remove trailing slash if present
const normalizedBaseUrl = baseUrl.replace(/\/$/, '');
const apiEndpoint = `${normalizedBaseUrl}/api/v1/indices/plugin/web_search`;
return { accessToken, apiEndpoint };
} }
protected async performSearch( protected async performSearch(
query: string, query: string,
signal: AbortSignal, signal: AbortSignal,
): Promise<WebSearchResult> { ): Promise<WebSearchResult> {
// Get access token from OAuth credentials or fallback to apiKey // Get access token and API endpoint (loads credentials once)
const accessToken = await this.getAccessToken(); const { accessToken, apiEndpoint } = await this.getAuthConfig();
if (!accessToken) { if (!accessToken) {
throw new Error( throw new Error(
'No access token available. Please authenticate using OAuth', 'No access token available. Please authenticate using OAuth',
@@ -133,18 +157,15 @@ export class DashScopeProvider extends BaseWebSearchProvider {
rows: this.config.maxResults || 10, rows: this.config.maxResults || 10,
}; };
const response = await fetch( const response = await fetch(apiEndpoint, {
'https://pre-portal.qwen.ai/api/v1/indices/plugin/web_search', method: 'POST',
{ headers: {
method: 'POST', 'Content-Type': 'application/json',
headers: { Authorization: `Bearer ${accessToken}`,
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify(requestBody),
signal,
}, },
); body: JSON.stringify(requestBody),
signal,
});
if (!response.ok) { if (!response.ok) {
const text = await response.text().catch(() => ''); const text = await response.text().catch(() => '');