Files
gott/wwwroot/js/cards.js
T
MelekiandClaude Opus 4.8 e6770bb5f8 Fix shared-bot Telegram agent resolution and add effort badge
- TelegramService: build the chat context with the session owner instead
  of the bot owner, so a public/shared bot resolves the agent for foreign
  sessions; credentials/CLI permission stay with the bot owner.
- Agent cards: render an effort badge next to the model badge when an
  agent has an explicit reasoning effort set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:56:42 +02:00

172 lines
8.2 KiB
JavaScript
Raw 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.
// ── Avatar Transform Helper ──
function _buildAvatarTransformStyle(obj) {
const parts = [];
if (obj.avatarScale && obj.avatarScale !== 1) parts.push(`scale(${obj.avatarScale})`);
if (obj.avatarOffsetX || obj.avatarOffsetY) parts.push(`translate(${obj.avatarOffsetX || 0}%, ${obj.avatarOffsetY || 0}%)`);
return parts.length ? ` style="transform: ${parts.join(' ')}"` : '';
}
// ── Session Card Helper ──
// Erzeugt ein .card-Element für eine Session (wiederverwendbar für Dashboard + Picker).
function buildSessionCard(session, agent) {
const card = document.createElement('div');
card.className = 'card';
const transformStyle = _buildAvatarTransformStyle(session);
const imageHtml = session.image ? `<img src="${session.image}" alt=""${transformStyle}>` : '';
// Badges
const badges = [];
if (agent) badges.push(`<span class="badge">${esc(agent.name)}</span>`);
if (session.reviewAgentId) badges.push(`<span class="badge badge-feature" title="Review-Agent"><i class="fa fa-check-circle-o"></i></span>`);
if (session.finalizerAgentId) badges.push(`<span class="badge badge-feature" title="Finalizer-Agent"><i class="fa fa-flag-checkered"></i></span>`);
if (session.context) badges.push(`<span class="badge badge-feature" title="${esc(session.context)}"><i class="fa fa-file-text-o"></i></span>`);
if (session.telegramConfigured) badges.push(`<span class="badge ${session.telegramLinked ? 'badge-feature' : 'badge-off'}" title="Telegram ${session.telegramLinked ? 'verbunden' : 'konfiguriert'}"><i class="fa fa-paper-plane"></i></span>`);
// Meta
const metaParts = [];
if (session.messageCount) metaParts.push(`<span class="card-meta-item"><i class="fa fa-comment"></i> ${esc(session.messageCount + ' Nachrichten')}</span>`);
if (session.archiveMessageCount) metaParts.push(`<span class="card-meta-item"><i class="fa fa-archive"></i> ${esc(session.archiveMessageCount + ' Nachrichten archiviert')}</span>`);
if (session.workspace) metaParts.push(`<span class="card-meta-item card-workspace" title="${esc(session.workspace)}"><i class="fa fa-folder"></i> ${esc(session.workspace)}</span>`);
card.innerHTML = `
<div class="card-image">${imageHtml}</div>
<div class="card-body">
<div class="card-title-row">
<span class="card-title">${esc(session.name || 'Unbenannt')}</span>
${badges.join('')}
</div>
${metaParts.length ? `<div class="card-meta">${metaParts.join('')}</div>` : ''}
</div>
`;
return card;
}
// ── Telegram Bot Card Helper ──
function buildTelegramBotCard(bot) {
const card = document.createElement('div');
card.className = 'card card-compact';
const badges = [];
if (bot.isPublic) {
badges.push('<span class="badge badge-feature"><i class="fa fa-globe"></i> Public</span>');
}
if (bot.isOwner === false) {
badges.push('<span class="badge badge-off"><i class="fa fa-user"></i> Fremd</span>');
}
if (bot.sessionCount > 0) {
badges.push(`<span class="badge badge-feature"><i class="fa fa-comment"></i> ${bot.sessionCount} ${bot.sessionCount === 1 ? 'Session' : 'Sessions'}</span>`);
}
// Meta-Items nur anzeigen wenn Daten vorhanden
const metaParts = [];
if (bot.botToken) {
const maskedToken = '•••' + bot.botToken.slice(-4);
metaParts.push(`<span class="card-meta-item"><i class="fa fa-key"></i> ${esc(maskedToken)}</span>`);
}
if (bot.createdAt) {
metaParts.push(`<span class="card-meta-item"><i class="fa fa-clock-o"></i> ${formatDate(bot.createdAt)}</span>`);
}
card.innerHTML = `
<div class="card-body">
<div class="card-title-row">
<span class="card-title"><i class="fa fa-paper-plane"></i> ${esc(bot.name)}</span>
${badges.join('')}
</div>
${metaParts.length ? `<div class="card-meta">${metaParts.join('')}</div>` : ''}
</div>
`;
return card;
}
// ── User Card Helper ──
// Erzeugt ein kompaktes .card-Element für einen Benutzer (für den Zuweisungs-Picker).
function buildUserCard(user) {
const card = document.createElement('div');
card.className = 'card card-compact';
const badges = [];
if (user.isAdmin) {
badges.push('<span class="badge badge-feature"><i class="fa fa-shield"></i> Admin</span>');
}
const metaParts = [];
metaParts.push(`<span class="card-meta-item"><i class="fa fa-at"></i> ${esc(user.username)}</span>`);
const title = user.displayName || user.username;
card.innerHTML = `
<div class="card-body">
<div class="card-title-row">
<span class="card-title"><i class="fa fa-user"></i> ${esc(title)}</span>
${badges.join('')}
</div>
${metaParts.length ? `<div class="card-meta">${metaParts.join('')}</div>` : ''}
</div>
`;
return card;
}
// ── Agent Card Helper ──
// Erzeugt ein .card-Element für einen Agent (wiederverwendbar für Dashboard + Picker).
function buildAgentCard(agent, skills) {
const card = document.createElement('div');
card.className = 'card';
const agentTransformStyle = _buildAvatarTransformStyle(agent);
const imageHtml = agent.avatar ? `<img src="${agent.avatar}" alt=""${agentTransformStyle}>` : '';
// Badges
const badges = [];
if (agent.allowUserChoice) badges.push('<span class="badge badge-feature" title="Rückfragen per Auswahl erlaubt"><i class="fa fa-question-circle"></i> Rückfragen</span>');
if (agent.autoCommit === 'mention') badges.push('<span class="badge badge-feature" title="Git-Commits nur auf Anweisung"><i class="fa fa-code-fork"></i> Anmerken</span>');
if (agent.autoCommit === 'enforce') badges.push('<span class="badge badge-forced-feature" title="Git-Commits nach jeder Änderung erzwungen"><i class="fa fa-code-fork"></i> Erzwungen</span>');
if (agent.autoCommit === 'forbid') badges.push('<span class="badge badge-forced-feature" title="Git-Commits strikt verboten"><i class="fa fa-code-fork"></i> Verboten</span>');
if (agent.useSoul) badges.push('<span class="badge badge-feature" title="Hat eine Seele (SOUL.md)"><i class="fa fa-heart"></i> Seele</span>');
if (agent.useIdentity) badges.push('<span class="badge badge-feature" title="Hat eine Identität (IDENTITY.md)"><i class="fa fa-id-badge"></i> Ich</span>');
if (agent.useUserInfo) badges.push('<span class="badge badge-feature" title="Kennt sein Gegenüber (Benutzer-Persona)"><i class="fa fa-user"></i> Du</span>');
if (agent.useMemory) badges.push('<span class="badge badge-feature" title="Zugriff auf Erinnerungen (Memory-Tools)"><i class="fa fa-database"></i> Erinnerungen</span>');
if (agent.useAutoContext) badges.push('<span class="badge badge-feature" title="Relevante Erinnerungen werden automatisch abgerufen"><i class="fa fa-magic"></i> Auto-Kontext</span>');
if (agent.useGitHubSearch) badges.push('<span class="badge badge-feature" title="Öffentlichen Code auf GitHub durchsuchen"><i class="fa fa-github"></i> GitHub Search</span>');
if (agent.useSerperSearch) badges.push('<span class="badge badge-feature" title="Google-Suche via Serper.dev API"><i class="fa fa-google"></i> Serper Search</span>');
if (agent.webSearchVersion) {
const wsYear = agent.webSearchVersion.includes('2025') ? 'Version 2025' : 'v2026';
badges.push(`<span class="badge badge-feature" title="Web-Suche - ${wsYear}"><i class="fa fa-search"></i> Web-Suche</span>`);
}
if (agent.isPublic) badges.push('<span class="badge badge-feature" title="Public – für alle User verfügbar"><i class="fa fa-globe"></i> Public</span>');
if (agent.isOwner === false) badges.push('<span class="badge badge-other" title="Gehört einem anderen User"><i class="fa fa-user-o"></i> Fremd</span>');
if (skills) {
for (const skill of skills) {
badges.push(`<span class="badge badge-skill" title="${esc(skill.description || skill.slug)}"><i class="fa fa-puzzle-piece"></i> ${esc(skill.name)}</span>`);
}
}
const effort = (agent.effort || ``).toLowerCase()
card.innerHTML = `
<div class="card-image">${imageHtml}</div>
<div class="card-body">
<div class="card-title-row">
<span class="card-title">${esc(agent.name)}</span>
<span class="badge">${prettyModelName(agent.model)}</span>
${effort ? `<span class="badge badge-effort">${effort}</span>` : ``}
</div>
${badges.length ? `<div class="card-badges">${badges.join('')}</div>` : ''}
</div>
`;
return card;
}