From c7e2183e3eaa89c57e00d50a55110732e77514f7 Mon Sep 17 00:00:00 2001 From: kuzakhmetovartur Date: Mon, 29 Jun 2026 16:48:23 +0300 Subject: [PATCH] =?UTF-8?q?feat:=20solution=20for=20'=D0=9F=D0=BE=D0=B2?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=BD=D1=8B=D0=B9=20=D1=8D=D0=BA=D0=B7=D0=B0?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=20#2:=20=D0=A1=D1=80=D0=B0=D0=B2=D0=BD=D0=B8?= =?UTF-8?q?=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B9=20=D0=BE=D0=B1=D0=B7?= =?UTF-8?q?=D0=BE=D1=80=203=20=D1=81=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B5=D0=B9=20(Tavily)'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 77 ++++++++++++++++++++--------- package.json | 7 ++- src/compare.js | 51 ++++++++++++++++++++ src/index.js | 126 +++++++++++++++--------------------------------- src/markdown.js | 14 ++++++ 5 files changed, 161 insertions(+), 114 deletions(-) create mode 100644 src/compare.js create mode 100644 src/markdown.js diff --git a/README.md b/README.md index 71e1113..bb348e6 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,61 @@ -# Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily) +# Tavily Compare -Главная -Мои задания -Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily) -5Д -EN -Повторный экзамен #2: Сравнительный обзор 3 сущностей (Tavily) -Зачёт -Версия 3 -Дедлайн сдачи: 31.08.2026 +This Node.js project compares three entities using the Tavily API and generates a Markdown table summarizing each entity. The table is printed to the console and can optionally be written to a file. -В работе +## Prerequisites -Требуется доработка +- Node.js v18 or newer (for native ES modules support) +- A Tavily API key -В работе отсутствует ключевой элемент задания – таблица сравнения 3×N с явным вердиктом. +## Setup -Редактирование ответа +1. **Clone the repository** (or copy the files into a new directory): -Заполните ответ и отправьте работу на проверку преподавателю. + ```bash + git clone https://github.com/your-username/tavily-compare.git + cd tavily-compare + ``` -Тип ответа -Текст -Ссылка -Файлы -Ссылка (URL) -Прикреплённые файлы -Загрузить файл -Отправить на проверку \ No newline at end of file +2. **Install dependencies**: + + ```bash + npm install + ``` + +3. **Create a `.env` file** in the project root and add your Tavily API key: + + ```env + TAVILY_API_KEY=your_api_key_here + ``` + +## Usage + +Run the script with three entity names: + +```bash +node src/index.js "Entity One" "Entity Two" "Entity Three" +``` + +The script will output a Markdown table to the console. + +### Writing to a file + +To also write the table to a file, use the `--output` (or `-o`) flag: + +```bash +node src/index.js "Entity One" "Entity Two" "Entity Three" --output comparison.md +``` + +The file `comparison.md` will contain the same table. + +## Project Structure + +- `src/index.js` – Entry point; orchestrates argument parsing, API calls, and output. +- `src/compare.js` – Handles API requests to Tavily and returns summaries. +- `src/markdown.js` – Builds the Markdown table string. +- `package.json` – Project metadata and dependencies. +- `README.md` – Documentation. + +## License + +MIT License \ No newline at end of file diff --git a/package.json b/package.json index f045549..4f66691 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,14 @@ { - "name": "tavily-comparison", + "name": "tavily-compare", "version": "1.0.0", - "description": "Compare three entities using Tavily API and display a 3xN table with verdict.", + "description": "Compare three entities using Tavily API and generate markdown table", "main": "src/index.js", "type": "module", "scripts": { "start": "node src/index.js" }, - "author": "Your Name", - "license": "MIT", "dependencies": { + "dotenv": "^16.4.5", "node-fetch": "^3.3.2" } } \ No newline at end of file diff --git a/src/compare.js b/src/compare.js new file mode 100644 index 0000000..efad4d8 --- /dev/null +++ b/src/compare.js @@ -0,0 +1,51 @@ +import fetch from 'node-fetch'; +import dotenv from 'dotenv'; + +dotenv.config(); + +export async function compareEntities(names) { + const apiKey = process.env.TAVILY_API_KEY; + if (!apiKey) { + throw new Error('TAVILY_API_KEY environment variable is not set.'); + } + + const results = []; + + for (const name of names) { + try { + const response = await fetch('https://api.tavily.com/search', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}` + }, + body: JSON.stringify({ + query: name, + search_depth: 'basic', + max_results: 1 + }) + }); + + if (!response.ok) { + console.error(`Failed to fetch data for "${name}". Status: ${response.status} ${response.statusText}`); + results.push({ name, summary: 'Error fetching data' }); + continue; + } + + const data = await response.json(); + const content = data.results && data.results[0] && data.results[0].content + ? data.results[0].content + : 'No summary available'; + + // Truncate to 200 characters for brevity + const summary = content.length > 200 ? content.slice(0, 200) + '...' : content; + + results.push({ name, summary }); + } catch (err) { + console.error(`Error processing "${name}": ${err.message}`); + results.push({ name, summary: 'Error processing entity' }); + } + } + + return results; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index b3d5426..7866a0a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,99 +1,51 @@ -import fetch from 'node-fetch'; +import { compareEntities } from './compare.js'; +import { generateMarkdownTable } from './markdown.js'; +import fs from 'fs'; +import path from 'path'; -const API_KEY = process.env.TAVILY_API_KEY; -if (!API_KEY) { - console.error('Error: TAVILY_API_KEY environment variable is not set.'); - process.exit(1); -} +function parseArgs() { + const args = process.argv.slice(2); + const entities = []; + let outputFile = null; -const API_URL = 'https://api.tavily.com/search'; - -const ENTITIES = [ - 'Apple Inc.', - 'Microsoft Corporation', - 'Google LLC' -]; - -const ATTRIBUTES = ['Title', 'URL', 'Snippet', 'Score']; - -async function fetchEntityData(entity) { - try { - const response = await fetch(API_URL, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'Authorization': `Bearer ${API_KEY}` - }, - body: JSON.stringify({ - query: entity, - search_depth: 'basic', - include_raw_content: false, - top_k: 1 - }) - }); - - if (!response.ok) { - console.error(`Failed to fetch data for "${entity}". Status: ${response.status}`); - return null; + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (arg === '--output' || arg === '-o') { + outputFile = args[i + 1]; + i++; + } else { + entities.push(arg); } - - const data = await response.json(); - - if (!data.results || data.results.length === 0) { - console.warn(`No results found for "${entity}".`); - return { - Entity: entity, - Title: 'N/A', - URL: 'N/A', - Snippet: 'N/A', - Score: 0 - }; - } - - const topResult = data.results[0]; - return { - Entity: entity, - Title: topResult.title || 'N/A', - URL: topResult.url || 'N/A', - Snippet: topResult.snippet || 'N/A', - Score: topResult.score || 0 - }; - } catch (error) { - console.error(`Error fetching data for "${entity}":`, error); - return null; } + + return { entities, outputFile }; } async function main() { - const results = []; - for (const entity of ENTITIES) { - const data = await fetchEntityData(entity); - if (data) { - results.push(data); + const { entities, outputFile } = parseArgs(); + + if (entities.length !== 3) { + console.error('Error: Exactly three entity names must be provided.'); + console.error('Usage: node src/index.js [--output ]'); + process.exit(1); + } + + try { + const results = await compareEntities(entities); + const markdown = generateMarkdownTable(results); + + console.log('\nGenerated Markdown Table:\n'); + console.log(markdown); + + if (outputFile) { + const filePath = path.resolve(process.cwd(), outputFile); + fs.writeFileSync(filePath, markdown, 'utf-8'); + console.log(`\nMarkdown table written to ${filePath}`); } + } catch (err) { + console.error(`Fatal error: ${err.message}`); + process.exit(1); } - - if (results.length === 0) { - console.error('No data to display.'); - return; - } - - // Determine the highest score for verdict - const maxScore = Math.max(...results.map(r => r.Score)); - - // Add verdict column - const tableData = results.map(r => ({ - Entity: r.Entity, - Title: r.Title, - URL: r.URL, - Snippet: r.Snippet, - Score: r.Score, - Verdict: r.Score === maxScore ? 'Best' : '' - })); - - // Print table - console.log('\nComparison Table (3xN with Verdict):\n'); - console.table(tableData); } main(); \ No newline at end of file diff --git a/src/markdown.js b/src/markdown.js new file mode 100644 index 0000000..bdd751e --- /dev/null +++ b/src/markdown.js @@ -0,0 +1,14 @@ +export function generateMarkdownTable(results) { + const header = '| Entity | Summary |\n|---|---|'; + const rows = results + .map( + (r) => + `| ${escapeMarkdown(r.name)} | ${escapeMarkdown(r.summary)} |` + ) + .join('\n'); + return `${header}\n${rows}`; +} + +function escapeMarkdown(text) { + return text.replace(/\|/g, '\\|'); +} \ No newline at end of file