123-3/server.js

116 lines
5.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const http = require('http');
const url = require('url');
const port = process.env.PORT || 3000;
const ALEM_BASE_URL = process.env.ALEM_BASE_URL;
const ALEM_API_KEY = process.env.ALEM_API_KEY;
const ALEM_TEMPLATE_ID = process.env.ALEM_TEMPLATE_ID;
async function callAlem(prompt) {
const headers = {
'Content-Type': 'application/json',
'Authorization': `Bearer ${ALEM_API_KEY}`,
};
const sessRes = await fetch(`${ALEM_BASE_URL}/api/v1/open-api/conversation`, {
method: 'POST',
headers,
body: JSON.stringify({ template_id: ALEM_TEMPLATE_ID, title: 'OKTRU', user_id: 'dauren-oktru' }),
});
const sessData = await sessRes.json();
const sessionId = sessData.session_id || sessData.data?.session_id;
if (!sessionId) throw new Error('Нет session_id');
const sendRes = await fetch(`${ALEM_BASE_URL}/api/v1/open-api/conversation/${sessionId}/send`, {
method: 'POST',
headers,
body: JSON.stringify({ content: prompt, user_id: 'dauren-oktru', model_api_key: ALEM_API_KEY }),
});
const text = await sendRes.text();
console.log(`--- Сырой SSE (${text.length} байт) ---`);
console.log(text.slice(0, 3000));
let result = '';
for (const line of text.split('\n')) {
if (line.startsWith('data:')) {
try { const evt = JSON.parse(line.slice(5)); if ((evt.type || evt.event) === 'message_result' && evt.detail?.full_content) result = evt.detail.full_content; } catch {}
}
}
return result || '(пустой ответ)';
}
function page(resultBlock, logBlock) {
return `<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Поиск кода ОКТРУ</title>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#0f172a;color:#e2e8f0;min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px}
.card{background:#1e293b;border-radius:16px;padding:40px;width:100%;max-width:520px;box-shadow:0 25px 50px rgba(0,0,0,.4)}
h1{font-size:22px;margin-bottom:8px;color:#f8fafc}
.sub{font-size:14px;color:#94a3b8;margin-bottom:28px}
label{display:block;font-size:14px;color:#cbd5e1;margin-bottom:8px}
input[type=text]{width:100%;padding:14px 16px;border-radius:10px;border:2px solid #334155;background:#0f172a;color:#f1f5f9;font-size:15px;outline:none;transition:border-color .2s}
input[type=text]:focus{border-color:#3b82f6}
button{width:100%;padding:14px;border:none;border-radius:10px;background:#2563eb;color:#fff;font-size:15px;font-weight:600;cursor:pointer;margin-top:16px;transition:background .2s}
button:hover{background:#1d4ed8}
.log{margin-top:16px;padding:12px;border-radius:8px;font-size:12px;color:#94a3b8;background:#0f172a;font-family:monospace;white-space:pre-wrap;line-height:1.5;max-height:200px;overflow-y:auto;display:none}
.log.show{display:block}
.res{margin-top:20px;padding:18px;border-radius:10px;line-height:1.6;font-size:14px;white-space:pre-wrap}
.ok{background:#064e3b;border:1px solid #059669;color:#d1fae5}
.err{background:#450a0a;border:1px solid #dc2626;color:#fecaca}
</style>
</head>
<body>
<div class="card">
<h1>🔍 Поиск кода ОКТРУ</h1>
<p class="sub">Введите название товара — агент найдёт подходящий код</p>
<form method="POST">
<label>Название товара</label>
<input type="text" name="q" placeholder='Например: ноутбук Dell' value="" autocomplete="off">
<button type="submit">Проверить</button>
</form>
${resultBlock}
<div class="log show">${logBlock}</div>
</div>
</body>
</html>`;
}
http.createServer(async (req, res) => {
let q = '';
if (req.method === 'POST') {
let body = '';
await new Promise(resolve => { req.on('data', c => body += c); req.on('end', resolve); });
const params = new URLSearchParams(body);
q = (params.get('q') || '').trim();
} else {
const parsed = url.parse(req.url, true);
q = (parsed.query.q || '').trim();
}
if (q) {
const logs = [];
try {
logs.push(`[${new Date().toLocaleTimeString('ru')}] 📨 Запрос: "${q}"`);
console.log(`Запрос: "${q}"`);
logs.push(`[${new Date().toLocaleTimeString('ru')}] ⏱ Вызываю агент Alem...`);
const answer = await callAlem(`Найди код ОКТРУ для товара: ${q}. Ответь кратко — только код и название позиции.`);
logs.push(`[${new Date().toLocaleTimeString('ru')}] ✅ Ответ получен (${answer.length} символов)`);
console.log(`Ответ: ${answer.slice(0, 200)}`);
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(page(`<div class="res ok">${answer}</div>`, logs.join('\n')));
} catch (e) {
logs.push(`[${new Date().toLocaleTimeString('ru')}] ❌ Ошибка: ${e.message}`);
console.error('Ошибка:', e.message);
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(page(`<div class="res err">Ошибка: ${e.message}</div>`, logs.join('\n')));
}
} else {
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(page('', ''));
}
}).listen(port, () => console.log(`Сервер запущен на порту ${port}`));