feat: solution for 'Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily)'

This commit is contained in:
2026-07-01 13:23:40 +03:00
parent f1bd10bd09
commit c11f8de6a7
8 changed files with 299 additions and 164 deletions
+39 -33
View File
@@ -1,40 +1,46 @@
const { search } = require('./api');
/**
* Compare three entities using the Tavily API.
*
* This module implements a single, unified approach: async/await
* with the tavilySearch helper from utils.js. The public API remains
* unchanged: compare(entity1, entity2, entity3) returns a Promise
* resolving to an object mapping each entity to its search result.
*
* The function handles errors gracefully and propagates meaningful
* error messages to the caller.
*/
import { tavilySearch } from './utils.js';
/**
* Compare three entities by querying the Tavily API.
* Compares three entities by performing a Tavily search for each.
*
* @param {string} entity1 - First entity to compare.
* @param {string} entity2 - Second entity to compare.
* @param {string} entity3 - Third entity to compare.
* @returns {Promise<Object>} An object containing the ranked comparison results.
* @throws {Error} If any entity is invalid or the API call fails.
* @param {string} entity1 - The first entity to compare.
* @param {string} entity2 - The second entity to compare.
* @param {string} entity3 - The third entity to compare.
* @returns {Promise<Object>} - An object with keys entity1, entity2, entity3
* mapping to the respective Tavily API responses.
* @throws {Error} - If any of the API calls fail.
*/
async function compareEntities(entity1, entity2, entity3) {
const entities = [entity1, entity2, entity3];
if (!entities.every(e => typeof e === 'string' && e.trim() !== '')) {
throw new Error('All entities must be non-empty strings.');
export async function compare(entity1, entity2, entity3) {
if (!entity1 || !entity2 || !entity3) {
throw new Error('All three entities must be provided.');
}
const [res1, res2, res3] = await Promise.all([
search(entity1),
search(entity2),
search(entity3),
]);
try {
const [res1, res2, res3] = await Promise.all([
tavilySearch(entity1),
tavilySearch(entity2),
tavilySearch(entity3)
]);
const results = [
{ entity: entity1, data: res1 },
{ entity: entity2, data: res2 },
{ entity: entity3, data: res3 },
];
// Simple ranking: number of results returned by the API
results.sort((a, b) => {
const aCount = a.data?.results?.length ?? 0;
const bCount = b.data?.results?.length ?? 0;
return bCount - aCount;
});
return { ranked: results };
}
module.exports = { compareEntities };
return {
[entity1]: res1,
[entity2]: res2,
[entity3]: res3
};
} catch (err) {
// Propagate a clear error message
throw new Error(`Comparison failed: ${err.message}`);
}
}
+7 -2
View File
@@ -1,3 +1,8 @@
const { compareEntities } = require('./compare');
/**
* Public entry point for the tavily-compare library.
*
* Exports the compare function while keeping the module's public API
* identical to the original implementation.
*/
module.exports = { compareEntities };
export { compare } from './compare.js';
+46
View File
@@ -0,0 +1,46 @@
/**
* Utility functions for interacting with the Tavily API.
*
* This module contains a single approach: async/await based HTTP requests
* using the native fetch API (via node-fetch). All functions return Promises
* and throw descriptive errors on failure.
*/
import fetch from 'node-fetch';
/**
* Performs a search query against the Tavily API.
*
* @param {string} query - The search query string.
* @returns {Promise<Object>} - The JSON response from Tavily.
* @throws {Error} - If the request fails or the API returns an error.
*/
export async function tavilySearch(query) {
const apiKey = process.env.TAVILY_API_KEY;
if (!apiKey) {
throw new Error('TAVILY_API_KEY environment variable is not set.');
}
const url = `https://api.tavily.com/search?query=${encodeURIComponent(query)}`;
try {
const response = await fetch(url, {
method: 'GET',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Accept': 'application/json'
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Tavily API error: ${response.status} ${response.statusText} - ${errorText}`);
}
const data = await response.json();
return data;
} catch (err) {
// Rethrow with a more descriptive message
throw new Error(`Failed to fetch from Tavily: ${err.message}`);
}
}