|
|
@ -40,11 +40,15 @@ export class FetchService implements OnModuleInit { |
|
|
|
|
|
|
|
|
const url = input instanceof Request ? input.url : input.toString(); |
|
|
const url = input instanceof Request ? input.url : input.toString(); |
|
|
const urlRedacted = this.redactUrl(url); |
|
|
const urlRedacted = this.redactUrl(url); |
|
|
|
|
|
const matchedWebFetchDomain = this.getMatchingWebFetchDomain(url, method); |
|
|
|
|
|
|
|
|
Logger.debug(`${method} ${urlRedacted}`, 'FetchService'); |
|
|
Logger.debug(`${method} ${urlRedacted}`, 'FetchService'); |
|
|
|
|
|
|
|
|
if (method === 'GET' && this.matchesWebFetchDomain(url)) { |
|
|
if (matchedWebFetchDomain) { |
|
|
const response = await this.fetchViaWebFetchTool(url); |
|
|
const response = await this.fetchViaWebFetchTool( |
|
|
|
|
|
url, |
|
|
|
|
|
matchedWebFetchDomain |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
if (response) { |
|
|
if (response) { |
|
|
return response; |
|
|
return response; |
|
|
@ -71,7 +75,8 @@ export class FetchService implements OnModuleInit { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private async fetchViaWebFetchTool( |
|
|
private async fetchViaWebFetchTool( |
|
|
url: string |
|
|
url: string, |
|
|
|
|
|
webFetchDomain: WebFetchDomain |
|
|
): Promise<Response | undefined> { |
|
|
): Promise<Response | undefined> { |
|
|
const [openRouterApiKey, openRouterModel] = await Promise.all([ |
|
|
const [openRouterApiKey, openRouterModel] = await Promise.all([ |
|
|
this.propertyService.getByKey<string>(PROPERTY_API_KEY_OPENROUTER), |
|
|
this.propertyService.getByKey<string>(PROPERTY_API_KEY_OPENROUTER), |
|
|
@ -107,7 +112,7 @@ export class FetchService implements OnModuleInit { |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
const candidates = [ |
|
|
const candidates = [ |
|
|
...sources.map((source) => { |
|
|
...(sources ?? []).map((source) => { |
|
|
return source.providerMetadata?.openrouter?.content; |
|
|
return source.providerMetadata?.openrouter?.content; |
|
|
}), |
|
|
}), |
|
|
text |
|
|
text |
|
|
@ -120,19 +125,25 @@ export class FetchService implements OnModuleInit { |
|
|
|
|
|
|
|
|
const body = candidate.trim(); |
|
|
const body = candidate.trim(); |
|
|
|
|
|
|
|
|
try { |
|
|
if (!body) { |
|
|
JSON.parse(body); |
|
|
|
|
|
} catch { |
|
|
|
|
|
continue; |
|
|
continue; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (webFetchDomain.responseContentType.includes('application/json')) { |
|
|
|
|
|
try { |
|
|
|
|
|
JSON.parse(body); |
|
|
|
|
|
} catch { |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
Logger.debug( |
|
|
Logger.debug( |
|
|
`Routed ${this.redactUrl(url)} via web fetch tool`, |
|
|
`Routed ${this.redactUrl(url)} via web fetch tool`, |
|
|
'FetchService' |
|
|
'FetchService' |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
return new Response(body, { |
|
|
return new Response(body, { |
|
|
headers: { 'content-type': 'application/json' } |
|
|
headers: { 'content-type': webFetchDomain.responseContentType } |
|
|
}); |
|
|
}); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -149,15 +160,22 @@ export class FetchService implements OnModuleInit { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private matchesWebFetchDomain(rawUrl: string): boolean { |
|
|
private getMatchingWebFetchDomain( |
|
|
|
|
|
rawUrl: string, |
|
|
|
|
|
method: string |
|
|
|
|
|
): WebFetchDomain | undefined { |
|
|
try { |
|
|
try { |
|
|
const { hostname } = new URL(rawUrl); |
|
|
const { hostname } = new URL(rawUrl); |
|
|
|
|
|
|
|
|
return this.webFetchDomains.some(({ domain }) => { |
|
|
return this.webFetchDomains.find((webFetchDomain) => { |
|
|
return hostname === domain || hostname.endsWith(`.${domain}`); |
|
|
const { domain, methods } = webFetchDomain; |
|
|
|
|
|
const matchesDomain = |
|
|
|
|
|
hostname === domain || hostname.endsWith(`.${domain}`); |
|
|
|
|
|
|
|
|
|
|
|
return matchesDomain && methods.includes(method); |
|
|
}); |
|
|
}); |
|
|
} catch { |
|
|
} catch { |
|
|
return false; |
|
|
return undefined; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|