Dashboard: Badges für Sessions (Kontext) und Agents (Features, Skills, Model-Name)
- prettyModelName() von chat.js nach ui.js als globale Funktion verschoben - Session-Cards: Kontext-Badge mit Tooltip wenn context vorhanden - Agent-Cards: Badges für ToolChoice:any, AutoCommit, Soul, Identity, UserInfo, Memory - Agent-Cards: Skill-Badges pro aktiviertem Skill (parallel geladen) - Agent-Cards: Model-Name via prettyModelName() statt roher Model-ID - Neue CSS-Klassen: badge-feature, badge-forced-feature, badge-skill - Theme: primary/dangerous Farben angepasst - Chat: Input overflow hidden→auto
This commit is contained in:
1 parent
754b2aa3e3
commit
56d4d1be0a
6 files changed
+73
-29
No files matched your search
+1
-18
@@ -1,25 +1,8 @@
|
||||
// ── Helpers ──
|
||||
|
||||
function _prettyModelName(model) {
|
||||
if (!model) return '?';
|
||||
// claude-sonnet-4-20250514 → Sonnet 4
|
||||
// claude-opus-4-6 → Opus 4.6
|
||||
// claude-haiku-3-5 → Haiku 3.5
|
||||
const m = model.match(/claude-(\w+)-(\d+)(?:-(\d+))?/);
|
||||
if (m) {
|
||||
const family = m[1].charAt(0).toUpperCase() + m[1].slice(1);
|
||||
const major = m[2];
|
||||
const minor = m[3];
|
||||
// minor > 20000000 ist ein Datums-Suffix, kein Minor-Version
|
||||
if (minor && minor.length <= 2) return family + ' ' + major + '.' + minor;
|
||||
return family + ' ' + major;
|
||||
}
|
||||
return 'Unbekannt';
|
||||
}
|
||||
|
||||
function buildMetaBadges(d) {
|
||||
const badges = [];
|
||||
badges.push(_prettyModelName(d.model));
|
||||
badges.push(prettyModelName(d.model));
|
||||
badges.push('Tokens: ' + (d.inputTokens || 0) + ' / ' + (d.outputTokens || 0));
|
||||
if (d.cacheCreationTokens > 0 || d.cacheReadTokens > 0) {
|
||||
badges.push('Cache: ' + (d.cacheReadTokens || 0) + ' / ' + (d.cacheCreationTokens || 0));
|
||||
|
||||
@@ -29,12 +29,16 @@ registerPage('dashboard', {
|
||||
: '';
|
||||
const workspaceLabel = s.workspace ? s.workspace : '';
|
||||
|
||||
const sessionBadges = [];
|
||||
if (agent) sessionBadges.push(`<span class="badge">${esc(agent.name)}</span>`);
|
||||
if (s.context) sessionBadges.push(`<span class="badge badge-feature" title="${esc(s.context)}"><i class="fa fa-file-text-o"></i></span>`);
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="card-image">${s.image ? `<img src="${s.image}" alt="">` : ''}</div>
|
||||
<div class="card-body">
|
||||
<div class="card-title-row">
|
||||
<span class="card-title">${esc(s.name || 'Unbenannt')}</span>
|
||||
${agent ? `<span class="badge">${esc(agent.name)}</span>` : ''}
|
||||
${sessionBadges.join('')}
|
||||
<div class="card-menu">
|
||||
<button class="card-menu-trigger icon-btn"><i class="fa fa-ellipsis-v"></i></button>
|
||||
<div class="card-menu-dropdown" hidden>
|
||||
@@ -43,7 +47,6 @@ registerPage('dashboard', {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
${s.description ? `<div class="card-desc">${esc(s.description)}</div>` : ''}
|
||||
<div class="card-meta">
|
||||
${msgLabel ? `<span class="card-meta-item"><i class="fa fa-comment"></i> ${esc(msgLabel)}</span>` : ''}
|
||||
${workspaceLabel ? `<span class="card-meta-item card-workspace" title="${esc(workspaceLabel)}"><i class="fa fa-folder"></i> ${esc(workspaceLabel)}</span>` : ''}
|
||||
@@ -102,7 +105,7 @@ registerPage('dashboard', {
|
||||
|
||||
const gitEl = document.createElement('span');
|
||||
gitEl.className = 'card-meta-item card-git-status';
|
||||
gitEl.innerHTML = `<i class="fa fa-code-fork"></i> ${parts.join(' ')}`;
|
||||
gitEl.innerHTML = parts.join(' ');
|
||||
metaEl.appendChild(gitEl);
|
||||
});
|
||||
}
|
||||
@@ -119,15 +122,35 @@ registerPage('dashboard', {
|
||||
const agentGrid = document.getElementById('agentCards');
|
||||
agentGrid.innerHTML = '';
|
||||
|
||||
// Skills pro Agent parallel laden
|
||||
const agentSkillsMap = {};
|
||||
await Promise.all(agents.map(async a => {
|
||||
agentSkillsMap[a.agentId] = await apiGetAgentSkills(a.agentId);
|
||||
}));
|
||||
|
||||
for (const a of agents) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card';
|
||||
|
||||
const badges = [];
|
||||
if (a.toolChoice === 'any') badges.push('<span class="badge badge-forced-feature" title="Tool-Nutzung erzwingen"><i class="fa fa-wrench"></i> Erzwungen</span>');
|
||||
if (a.autoCommit) badges.push('<span class="badge badge-feature" title="Auto-Commit erlauben"><i class="fa fa-check-circle"></i> Auto-Commit</span>');
|
||||
if (a.useSoul) badges.push('<span class="badge badge-feature" title="Hat eine Seele (SOUL.md)"><i class="fa fa-heart"></i> Seele</span>');
|
||||
if (a.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 (a.useUserInfo) badges.push('<span class="badge badge-feature" title="Kennt sein Gegenüber (USER.md)"><i class="fa fa-user"></i> Du</span>');
|
||||
if (a.useMemory) badges.push('<span class="badge badge-feature" title="Auf Erinnerungen zugreifen (Memory-Tools)"><i class="fa fa-database"></i> Erinnerungen</span>');
|
||||
|
||||
const skills = agentSkillsMap[a.agentId] || [];
|
||||
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>`);
|
||||
}
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="card-image">${a.avatar ? `<img src="${a.avatar}" alt="">` : ''}</div>
|
||||
<div class="card-body">
|
||||
<div class="card-title-row">
|
||||
<span class="card-title">${esc(a.name)}</span>
|
||||
<span class="badge">${esc(a.model)}</span>
|
||||
<span class="badge">${prettyModelName(a.model)}</span>
|
||||
<div class="card-menu">
|
||||
<button class="card-menu-trigger icon-btn"><i class="fa fa-ellipsis-v"></i></button>
|
||||
<div class="card-menu-dropdown" hidden>
|
||||
@@ -135,8 +158,7 @@ registerPage('dashboard', {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
${a.description ? `<div class="card-desc">${esc(a.description)}</div>` : ''}
|
||||
${a.persona ? `<div class="card-meta"><span class="card-meta-item card-persona"><i class="fa fa-user-secret"></i> ${esc(a.persona)}</span></div>` : ''}
|
||||
<div class="card-badges">${badges.join('')}</div>
|
||||
</div>
|
||||
`;
|
||||
const menuTrigger = card.querySelector('.card-menu-trigger');
|
||||
|
||||
@@ -4,6 +4,21 @@ const $ = (sel) => document.querySelector(sel);
|
||||
const chatEl = () => $('#chat');
|
||||
const metaEl = () => $('#meta');
|
||||
|
||||
function prettyModelName(model) {
|
||||
if (!model) return '?';
|
||||
var m = model.match(/claude-(\w+)-(\d+)(?:-(\d+))?/);
|
||||
if (m) {
|
||||
var family = m[1].charAt(0).toUpperCase() + m[1].slice(1);
|
||||
var major = m[2];
|
||||
var minor = m[3];
|
||||
if (minor && minor.length <= 2) return family + ' ' + major + '.' + minor;
|
||||
return family + ' ' + major;
|
||||
}
|
||||
if (model == 'sonnet') return 'Sonnet'
|
||||
if (model == 'opus') return 'Opus'
|
||||
return 'Unbekannt (' + model + ')';
|
||||
}
|
||||
|
||||
// ── Markdown ──
|
||||
|
||||
marked.setOptions({ breaks: true, gfm: true });
|
||||
|
||||
Reference in new issue
Block a user