feat: terminal sudo blocking, token tracking, mermaid & consumption UI
All checks were successful
Beta Release / beta (push) Successful in 1m3s

- Block sudo/doas commands when not running as root
- Add real token counting from API responses
- Track and display consumption by provider/day
- Add Mermaid diagram rendering in Shell and Studio
- Add copy-to-clipboard buttons for code blocks
- Support tables in AI message rendering
- Update system prompt with context (date, time, root status)

💘 Generated with Crush

Assisted-by: MiniMax-M2.7 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-26 12:43:15 +02:00
parent 0830e64ae6
commit cb3d35756a
21 changed files with 2166 additions and 208 deletions

View File

@@ -458,6 +458,8 @@ input::placeholder { color: var(--text-disabled); }
.shell-ai-token-text { font-size: 10px; font-family: var(--font-mono); color: var(--text-tertiary); white-space: nowrap; }
.ai-panel-messages { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 8px; }
.ai-message { padding: 8px 12px; border-radius: var(--radius); font-size: 13px; line-height: 1.5; word-break: break-word; }
.ai-message.user { background: var(--bg-elevated); border-left: 3px solid var(--accent-bright); color: var(--text-primary); }
.ai-message.user.analysis { border-left-color: var(--info); background: color-mix(in srgb, var(--info) 8%, var(--bg-elevated)); }
.ai-message.assistant { background: var(--bg-card); border-left: 3px solid var(--accent); }
.ai-message.system { background: var(--bg-elevated); border-left: 3px solid var(--info); font-style: italic; color: var(--text-tertiary); font-size: 12px; }
.ai-message.assistant { background: var(--bg-card); border-left: 3px solid var(--accent); }
@@ -492,6 +494,23 @@ input::placeholder { color: var(--text-disabled); }
}
.shell-code-actions button:last-child { border-right: none; }
.shell-code-actions button:hover { background: var(--accent-bg); color: var(--accent); }
.shell-code-actions button.copied { background: var(--accent-bg); color: var(--accent); animation: copy-flash 0.3s ease; }
.shell-mermaid-container { padding: 12px; background: var(--bg); overflow-x: auto; display: flex; justify-content: center; }
.shell-mermaid-container svg { max-width: 100%; height: auto; }
.shell-mermaid-loading { padding: 16px; text-align: center; color: var(--text-tertiary); font-size: 12px; }
.shell-mermaid-error { padding: 10px 12px; color: var(--accent-bright); font-family: var(--font-mono); font-size: 12px; white-space: pre-wrap; }
.ai-message table { width: 100%; border-collapse: collapse; margin: 6px 0; font-size: 12px; }
.ai-message th { background: var(--bg-surface); padding: 6px 10px; text-align: left; font-weight: 600; border: 1px solid var(--border); color: var(--text-secondary); }
.ai-message td { padding: 5px 10px; border: 1px solid var(--border); color: var(--text-primary); }
.ai-message tr:nth-child(even) td { background: var(--bg-surface); }
@keyframes copy-flash {
0% { transform: scale(1); }
50% { transform: scale(1.05); background: color-mix(in srgb, var(--accent) 20%, transparent); }
100% { transform: scale(1); }
}
.shell-analysis-modal {
background: var(--bg-elevated); border: 1px solid var(--border);
@@ -720,6 +739,25 @@ input::placeholder { color: var(--text-disabled); }
white-space: nowrap;
}
/* Consumption */
.dash-consumption-list { display: flex; flex-direction: column; gap: 10px; max-height: 270px; overflow-y: auto; }
.dash-consumption-provider { display: flex; flex-direction: column; gap: 4px; }
.dash-consumption-head { display: flex; align-items: center; justify-content: space-between; }
.dash-consumption-name {
font-size: 11px; font-weight: 700; letter-spacing: 0.5px;
}
.dash-consumption-total {
font-size: 10px; font-family: var(--font-mono); color: var(--text-tertiary);
}
.dash-consumption-days {
display: flex; gap: 4px; flex-wrap: wrap;
}
.dash-consumption-day {
font-size: 9px; font-family: var(--font-mono); color: var(--text-tertiary);
background: var(--bg-input); padding: 1px 5px; border-radius: 4px;
}
.dash-consumption-day strong { color: var(--text-secondary); }
/* Processes */
.dash-proc-list { display: flex; flex-direction: column; gap: 4px; max-height: 270px; overflow-y: auto; }
.dash-proc-row {
@@ -933,11 +971,33 @@ input::placeholder { color: var(--text-disabled); }
background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius);
overflow: hidden; margin: 8px 0;
}
.studio-code-header {
display: flex; align-items: center; justify-content: space-between;
background: var(--bg-surface); border-bottom: 1px solid var(--border);
}
.studio-code-block pre { padding: 12px 16px; font-family: var(--font-mono); font-size: 13px; line-height: 1.5; overflow-x: auto; color: var(--text-primary); margin: 0; }
.studio-code-lang {
padding: 4px 12px; font-size: 11px; font-weight: 600; color: var(--text-tertiary);
background: var(--bg-surface); border-bottom: 1px solid var(--border); text-transform: uppercase; letter-spacing: 0.5px;
background: var(--bg-surface); text-transform: uppercase; letter-spacing: 0.5px;
}
.studio-copy-btn {
padding: 3px 10px; font-size: 10px; font-weight: 600; color: var(--text-tertiary);
background: transparent; border: none; border-left: 1px solid var(--border);
cursor: pointer; transition: all 0.15s; font-family: var(--font-sans);
white-space: nowrap;
}
.studio-copy-btn:hover { background: var(--accent-bg); color: var(--accent); }
.studio-copy-btn.copied { background: var(--accent-bg); color: var(--accent); }
.studio-mermaid-container { padding: 12px; background: var(--bg); overflow-x: auto; display: flex; justify-content: center; }
.studio-mermaid-container svg { max-width: 100%; height: auto; }
.studio-mermaid-loading { padding: 12px; text-align: center; color: var(--text-tertiary); font-size: 12px; }
.studio-mermaid-error { padding: 10px 12px; color: var(--accent-bright); font-family: var(--font-mono); font-size: 12px; white-space: pre-wrap; }
.feed-content table { width: 100%; border-collapse: collapse; margin: 8px 0; font-size: 13px; }
.feed-content th { background: var(--bg-surface); padding: 6px 12px; text-align: left; font-weight: 600; border: 1px solid var(--border); color: var(--text-secondary); }
.feed-content td { padding: 5px 12px; border: 1px solid var(--border); color: var(--text-primary); }
.feed-content tr:nth-child(even) td { background: var(--bg-surface); }
.inline-code { background: var(--bg-input); padding: 2px 6px; border-radius: 4px; font-family: var(--font-mono); font-size: 13px; color: var(--accent-muted); }
.msg-h3 { font-size: 16px; font-weight: 700; color: var(--text-primary); margin: 10px 0 4px; display: block; }
.msg-h4 { font-size: 14px; font-weight: 700; color: var(--text-secondary); margin: 8px 0 3px; display: block; }