116 lines
5.3 KiB
JavaScript
116 lines
5.3 KiB
JavaScript
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}`));
|