251 lines
11 KiB
HTML
251 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru" data-theme="dark">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>ИИ-агент для задач</title>
|
||
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-components.css">
|
||
<link rel="stylesheet" href="design-system/kt-ai-page.css">
|
||
<style>
|
||
.agent-settings { display: grid; gap: var(--kt-ai-space-6); }
|
||
.chat-container { display: flex; flex-direction: column; height: 500px; }
|
||
.chat-messages { flex: 1; overflow-y: auto; padding: var(--kt-ai-space-4); border: 1px solid var(--kt-ai-border); border-radius: var(--kt-ai-radius-xl); margin-bottom: var(--kt-ai-space-4); }
|
||
.chat-message { margin-bottom: var(--kt-ai-space-3); padding: var(--kt-ai-space-3); border-radius: var(--kt-ai-radius-lg); max-width: 80%; }
|
||
.chat-message.user { background: var(--kt-ai-primary); color: white; margin-left: auto; }
|
||
.chat-message.assistant { background: var(--kt-ai-card-bg); border: 1px solid var(--kt-ai-card-border); }
|
||
.chat-input-area { display: flex; gap: var(--kt-ai-space-3); }
|
||
.chat-input-area input { flex: 1; }
|
||
.tool-chip { display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); padding: var(--kt-ai-space-2) var(--kt-ai-space-3); background: var(--kt-ai-bg-soft); border-radius: var(--kt-ai-radius-full); font-size: var(--kt-ai-text-sm); }
|
||
.tab-nav { display: flex; gap: var(--kt-ai-space-2); margin-bottom: var(--kt-ai-space-6); border-bottom: 1px solid var(--kt-ai-border); padding-bottom: var(--kt-ai-space-3); }
|
||
.tab-btn { background: none; border: none; padding: var(--kt-ai-space-2) var(--kt-ai-space-4); cursor: pointer; color: var(--kt-ai-fg-muted); font-size: var(--kt-ai-text-sm); }
|
||
.tab-btn.active { color: var(--kt-ai-fg); border-bottom: 2px solid var(--kt-ai-primary); }
|
||
.tab-content { display: none; }
|
||
.tab-content.active { display: block; }
|
||
.export-actions { display: flex; gap: var(--kt-ai-space-3); }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<header class="kt-ai-pagehead">
|
||
<div class="kt-ai-wrap kt-ai-pagehead-in">
|
||
<strong>ИИ-агент</strong>
|
||
<span class="kt-ai-spacer"></span>
|
||
<span style="color: var(--kt-ai-fg-muted); font-size: var(--kt-ai-text-sm)">Технологичный минимализм</span>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="kt-ai-wrap" style="padding: var(--kt-ai-space-12) 0">
|
||
<h1 style="margin-bottom: var(--kt-ai-space-8)">ИИ-агент для задач</h1>
|
||
|
||
<div class="tab-nav">
|
||
<button class="tab-btn active" data-tab="settings">Настройка</button>
|
||
<button class="tab-btn" data-tab="chat">Чат</button>
|
||
<button class="tab-btn" data-tab="tools">Инструменты</button>
|
||
<button class="tab-btn" data-tab="history">История</button>
|
||
<button class="tab-btn" data-tab="export">Экспорт</button>
|
||
</div>
|
||
|
||
<!-- Раздел 1: Настройка роли и поведения -->
|
||
<section id="settings" class="tab-content active">
|
||
<div class="kt-ai-card agent-settings">
|
||
<div class="kt-ai-field">
|
||
<label>Роль агента</label>
|
||
<input class="kt-ai-input" id="agent-role" placeholder="Например: Помощник, Аналитик, Креатор" value="Помощник">
|
||
</div>
|
||
<div class="kt-ai-field">
|
||
<label>Поведение</label>
|
||
<textarea class="kt-ai-textarea" id="agent-behavior" rows="3" placeholder="Опиши стиль общения: вежливый, точный, краткий и т.д.">Вежливый и точный</textarea>
|
||
</div>
|
||
<button class="kt-ai-btn" data-variant="primary" id="save-settings">Сохранить</button>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Раздел 2: Интерфейс чата -->
|
||
<section id="chat" class="tab-content">
|
||
<div class="chat-container">
|
||
<div class="chat-messages" id="chat-messages">
|
||
<div class="chat-message assistant">
|
||
<strong>ИИ-агент:</strong>
|
||
<p style="margin-top: var(--kt-ai-space-2)">Привет! Я готов помочь с задачами. Что нужно сделать?</p>
|
||
</div>
|
||
</div>
|
||
<form class="chat-input-area" id="chat-form">
|
||
<input class="kt-ai-input" id="chat-input" placeholder="Введите сообщение..." required>
|
||
<button class="kt-ai-btn" data-variant="primary" type="submit">Отправить</button>
|
||
</form>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Раздел 3: Подключение внешних инструментов -->
|
||
<section id="tools" class="tab-content">
|
||
<div class="kt-ai-card">
|
||
<h2 style="margin-bottom: var(--kt-ai-space-4)">Внешние инструменты</h2>
|
||
<div style="display: grid; gap: var(--kt-ai-space-4)">
|
||
<div class="tool-chip">
|
||
<span>🔍 Поиск</span>
|
||
<span style="color: var(--kt-ai-fg-muted)">Не подключено</span>
|
||
</div>
|
||
<div class="tool-chip">
|
||
<span>📊 Анализ данных</span>
|
||
<span style="color: var(--kt-ai-fg-muted)">Не подключено</span>
|
||
</div>
|
||
<div class="tool-chip">
|
||
<span>📝 Генерация текста</span>
|
||
<span style="color: var(--kt-ai-primary)">Активно</span>
|
||
</div>
|
||
</div>
|
||
<p style="margin-top: var(--kt-ai-space-6); color: var(--kt-ai-fg-muted)">
|
||
Инструменты подключаются через API. В текущей версии доступна только генерация текста.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Раздел 4: История диалогов -->
|
||
<section id="history" class="tab-content">
|
||
<div class="kt-ai-card">
|
||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--kt-ai-space-4)">
|
||
<h2>История диалогов</h2>
|
||
<button class="kt-ai-btn" data-variant="ghost" id="clear-history">Очистить</button>
|
||
</div>
|
||
<div id="history-list" style="display: grid; gap: var(--kt-ai-space-3)">
|
||
<p style="color: var(--kt-ai-fg-muted)">История пуста. Начните диалог в чате.</p>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- Раздел 5: Экспорт результатов -->
|
||
<section id="export" class="tab-content">
|
||
<div class="kt-ai-card">
|
||
<h2 style="margin-bottom: var(--kt-ai-space-4)">Экспорт результатов</h2>
|
||
<p style="color: var(--kt-ai-fg-muted); margin-bottom: var(--kt-ai-space-6)">
|
||
Сохраните историю диалога в удобном формате.
|
||
</p>
|
||
<div class="export-actions">
|
||
<button class="kt-ai-btn" data-variant="primary" id="export-txt">Экспорт в TXT</button>
|
||
<button class="kt-ai-btn" data-variant="ghost" id="export-json">Экспорт в JSON</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer class="kt-ai-wrap kt-ai-pagefoot">
|
||
<span>© 2026 ИИ-агент</span>
|
||
<span class="kt-ai-spacer"></span>
|
||
<span>Технологичный минимализм</span>
|
||
</footer>
|
||
|
||
<script>
|
||
// Переключение вкладок
|
||
document.querySelectorAll('.tab-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
||
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
document.getElementById(btn.dataset.tab).classList.add('active');
|
||
if (btn.dataset.tab === 'history') loadHistory();
|
||
});
|
||
});
|
||
|
||
// Сохранение настроек
|
||
document.getElementById('save-settings').addEventListener('click', async () => {
|
||
const role = document.getElementById('agent-role').value;
|
||
const behavior = document.getElementById('agent-behavior').value;
|
||
await fetch('/api/agent', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ role, behavior })
|
||
});
|
||
alert('Настройки сохранены!');
|
||
});
|
||
|
||
// Чат
|
||
const chatForm = document.getElementById('chat-form');
|
||
const chatInput = document.getElementById('chat-input');
|
||
const chatMessages = document.getElementById('chat-messages');
|
||
|
||
chatForm.addEventListener('submit', async (e) => {
|
||
e.preventDefault();
|
||
const message = chatInput.value.trim();
|
||
if (!message) return;
|
||
|
||
chatMessages.innerHTML += `
|
||
<div class="chat-message user">
|
||
<strong>Вы:</strong>
|
||
<p style="margin-top: var(--kt-ai-space-2)">${escapeHtml(message)}</p>
|
||
</div>
|
||
`;
|
||
chatInput.value = '';
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
|
||
const res = await fetch('/api/chat', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ message })
|
||
});
|
||
const data = await res.json();
|
||
|
||
chatMessages.innerHTML += `
|
||
<div class="chat-message assistant">
|
||
<strong>ИИ-агент:</strong>
|
||
<p style="margin-top: var(--kt-ai-space-2)">${escapeHtml(data.answer)}</p>
|
||
</div>
|
||
`;
|
||
chatMessages.scrollTop = chatMessages.scrollHeight;
|
||
});
|
||
|
||
// Загрузка истории
|
||
async function loadHistory() {
|
||
const res = await fetch('/api/history');
|
||
const data = await res.json();
|
||
const list = document.getElementById('history-list');
|
||
if (!data.conversations || data.conversations.length === 0) {
|
||
list.innerHTML = '<p style="color: var(--kt-ai-fg-muted)">История пуста.</p>';
|
||
return;
|
||
}
|
||
list.innerHTML = data.conversations.map(m => `
|
||
<div class="kt-ai-card" style="padding: var(--kt-ai-space-3)">
|
||
<strong style="color: ${m.role === 'user' ? 'var(--kt-ai-primary)' : 'var(--kt-ai-fg)'}">${m.role === 'user' ? 'Вы' : 'ИИ-агент'}</strong>
|
||
<p style="margin-top: var(--kt-ai-space-2); color: var(--kt-ai-fg-muted)">${escapeHtml(m.content)}</p>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Очистка истории
|
||
document.getElementById('clear-history').addEventListener('click', async () => {
|
||
await fetch('/api/history/clear', { method: 'POST' });
|
||
loadHistory();
|
||
});
|
||
|
||
// Экспорт
|
||
document.getElementById('export-txt').addEventListener('click', async () => {
|
||
await exportData('txt');
|
||
});
|
||
document.getElementById('export-json').addEventListener('click', async () => {
|
||
await exportData('json');
|
||
});
|
||
|
||
async function exportData(format) {
|
||
const res = await fetch('/api/export', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ format })
|
||
});
|
||
const blob = await res.blob();
|
||
const url = URL.createObjectURL(blob);
|
||
const a = document.createElement('a');
|
||
a.href = url;
|
||
a.download = 'export.' + format;
|
||
a.click();
|
||
URL.revokeObjectURL(url);
|
||
}
|
||
|
||
function escapeHtml(str) {
|
||
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||
}
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|