Files
foodlinkk-command-center/cockpit/templates/herman_chat.html
T

104 lines
5.0 KiB
HTML
Raw Normal View History

{% extends "base.html" %}
{% block content %}
<div x-data="hermanChat()" class="chat-layout">
<header class="page-header">
<h1>Herman</h1>
2026-06-09 10:41:13 +00:00
<p class="subtitle page-tip">Co-CEO orchestrator — delegeert naar specialist agents (packaging, design, …).</p>
</header>
2026-06-09 10:41:13 +00:00
<div class="card card-compact" style="margin-bottom:1rem;">
<h2 style="font-size:1rem;margin:0 0 .5rem;">Verpakking via Packaging agent</h2>
<p class="page-tip" style="margin:0 0 .5rem;">Start met <code>maak verpakking:</code> — de agent genereert het design, slaat op op NAS en rapporteert aan Herman.</p>
<p class="page-tip" style="margin:0;font-size:0.78rem">Voorbeeld: <em>maak verpakking: pouch 100×140 voor Halal Kip Curry project #5 halal-badge</em></p>
</div>
<div class="card card-compact" style="margin-bottom:1rem;">
<h2 style="font-size:1rem;margin:0 0 .5rem;">Foto genereren (ComfyUI)</h2>
<p class="page-tip" style="margin:0 0 .75rem;">Beschrijf wat je wilt zien. Op CPU duurt dit 13 minuten.</p>
<form class="chat-input" @submit.prevent="generateImage">
<input class="form-input" x-model="imagePrompt" placeholder="bijv. halal kipnuggets productfoto, studio licht" autocomplete="off" />
<button class="btn btn-primary" type="submit" :disabled="generating">
<span x-show="!generating">Genereer</span>
<span x-show="generating">Bezig…</span>
</button>
</form>
<div x-show="generating" class="page-tip" style="margin-top:.5rem;">Ik ga even de gegevens ophalen — afbeelding wordt gemaakt…</div>
<div x-show="lastImage" style="margin-top:1rem;">
<img :src="lastImage" alt="Gegenereerde afbeelding" style="max-width:100%;border-radius:8px;border:1px solid var(--border);" />
</div>
</div>
<div class="chat-messages" id="chat-log">
{% if user_message %}<div class="chat-msg user"><p>{{ user_message }}</p></div>{% endif %}
{% if last_reply %}<div class="chat-msg agent"><span class="badge">{{ last_agent }}</span><p>{{ last_reply }}</p></div>{% endif %}
{% for h in history[:10] %}
<div class="chat-msg agent"><small>{{ h.created_at }}</small><p>{{ h.title or h.body }}</p></div>
{% endfor %}
</div>
<form class="chat-input" @submit.prevent="send">
2026-06-09 10:41:13 +00:00
<input class="form-input" x-model="message" placeholder="Message Herman… (bijv. maak verpakking: doos 120×80×40 voor Chai N Masala project #3)" autocomplete="off" />
<button class="btn btn-primary" type="submit" :disabled="loading">Send</button>
</form>
</div>
{% endblock %}
{% block scripts %}
<script>
function esc(s) { const d = document.createElement('div'); d.textContent = s || ''; return d.innerHTML; }
function hermanChat() {
return {
message: '',
imagePrompt: '',
loading: false,
generating: false,
lastImage: '',
async send() {
if (!this.message.trim()) return;
this.loading = true;
const msg = this.message;
try {
const r = await Cockpit.api('/api/herman/chat', { method: 'POST', body: JSON.stringify({ message: msg }) });
const log = document.getElementById('chat-log');
log.innerHTML += '<div class="chat-msg user"><p>' + esc(msg) + '</p></div>';
let badge = esc(r.agent_label || 'Herman');
if (r.delegated_agents && r.delegated_agents.length > 1) {
badge += ' · ' + esc(r.delegated_agents.join(', '));
}
let html = '<div class="chat-msg agent"><span class="badge">' + badge + '</span><p>' + esc(r.reply || '') + '</p>';
if (r.image_url) {
html += '<img src="' + r.image_url + '" alt="Gegenereerd" style="max-width:100%;margin-top:.5rem;border-radius:8px;" />';
this.lastImage = r.image_url;
}
2026-06-09 10:41:13 +00:00
if (r.packaging_studio_url) {
html += '<p style="margin-top:.5rem"><a class="btn btn-sm" href="' + esc(r.packaging_studio_url) + '">📦 Open Packaging Studio</a>';
if (r.packaging_pdf_url) html += ' <a class="btn btn-sm btn-ghost" href="' + esc(r.packaging_pdf_url) + '" target="_blank">PDF</a>';
html += '</p>';
}
html += '</div>';
log.innerHTML += html;
this.message = '';
} catch (e) { Cockpit.toast(e.message, 'error'); }
this.loading = false;
},
async generateImage() {
if (!this.imagePrompt.trim()) return;
this.generating = true;
this.lastImage = '';
try {
const r = await Cockpit.api('/api/ai/generate-image', {
method: 'POST',
body: JSON.stringify({ prompt: this.imagePrompt, width: 512, height: 512, steps: 15 })
});
if (r.proxy_url) {
this.lastImage = r.proxy_url;
const log = document.getElementById('chat-log');
log.innerHTML += '<div class="chat-msg agent"><span class="badge">Design</span><p>Afbeelding klaar: ' + esc(this.imagePrompt) + '</p><img src="' + r.proxy_url + '" alt="Gegenereerd" style="max-width:100%;margin-top:.5rem;border-radius:8px;" /></div>';
}
Cockpit.toast('Afbeelding gegenereerd', 'success');
} catch (e) { Cockpit.toast(e.message, 'error'); }
this.generating = false;
}
};
}
</script>
{% endblock %}