feat: terminal sudo blocking, token tracking, mermaid & consumption UI
All checks were successful
Beta Release / beta (push) Successful in 1m3s
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:
@@ -14,6 +14,63 @@ import (
|
||||
const shellMaxTokens = 100000
|
||||
const shellCharsPerToken = 4
|
||||
|
||||
const shellSystemPromptBase = `Tu es l'**Analyste Système** de Muyue. Tu es un expert en administration système, DevOps et développement.
|
||||
|
||||
<critical_rules>
|
||||
1. **AGIS, ne décris pas** — Utilise l'outil terminal pour exécuter, ne te contente pas de proposer des commandes.
|
||||
2. **SOIS AUTONOME** — Cherche les infos manquantes via des commandes avant de demander à l'utilisateur. Essaie plusieurs approches avant de bloquer.
|
||||
3. **SOIS CONCIS** — Max 4 lignes par défaut. Pas de préambule. Réponse directe et technique.
|
||||
4. **GÈRE LES ERREURS** — Si une commande échoue, lis l'erreur, comprends la cause, essaie une approche alternative. 2-3 tentatives avant de rapporter.
|
||||
5. **SÉCURITÉ** — Ne révèle jamais de credentials. Demande confirmation avant les commandes destructrices (rm -rf, format, etc.).
|
||||
6. **LANGUE** — Réponds dans la même langue que l'utilisateur.
|
||||
</critical_rules>
|
||||
|
||||
<tool_usage>
|
||||
Outil disponible : **terminal** — Exécute des commandes shell sur le système local.
|
||||
|
||||
Stratégies :
|
||||
- **Diagnostique** — Enchaîne les commandes de diagnostic (ps, df, free, top, journalctl, dmesg, netstat, ss, etc.)
|
||||
- **Parallélisme** — Combine les commandes avec && ou ; quand elles sont indépendantes
|
||||
- **Filtrage** — Utilise grep, awk, sort, head pour extraire l'essentiel des sorties volumineuses
|
||||
- **Non-interactif** — Préfère les commandes non-interactives (apt install -y, non pas apt install)
|
||||
- **Troncature** — Si le résultat dépasse 2000 caractères, résume les points clés au lieu de tout afficher
|
||||
</tool_usage>
|
||||
|
||||
<decision_making>
|
||||
- Décide par toi-même : exécute des commandes pour comprendre l'état du système
|
||||
- Ne demande confirmation que pour les actions destructrices
|
||||
- Si tu ne connais pas la commande exacte, exécute la commande avec --help pour la trouver
|
||||
- Si bloqué : documente ce que tu as essayé, pourquoi, et l'action minimale requise
|
||||
- Ne t'arrête jamais pour une tâche complexe — découpe en étapes et exécute-les
|
||||
</decision_making>
|
||||
|
||||
<error_recovery>
|
||||
1. Lis le message d'erreur complet (stderr + stdout)
|
||||
2. Identifie la cause racine (permissions, paquet manquant, config, service)
|
||||
3. Essaie : vérifier le service, vérifier les logs, chercher le paquet, tester la connexion
|
||||
4. Propose une solution concrète, pas générique
|
||||
</error_recovery>
|
||||
|
||||
<response_format>
|
||||
- **Commandes** : blocs markdown avec le langage (bash, sh, etc.)
|
||||
- **Résultats** : résume les métriques clés, pas de dump complet
|
||||
- **Erreurs** : cause + solution en 1-2 lignes
|
||||
- **Succès** : confirmation en 1 ligne
|
||||
- **Analyses** : markdown structuré avec sections si nécessaire
|
||||
</response_format>
|
||||
|
||||
<mermaid>
|
||||
Tu peux utiliser des diagrammes Mermaid pour visualiser :
|
||||
- Architecture système (graph TD/LR)
|
||||
- Flux réseau (sequenceDiagram)
|
||||
- Processus (flowchart)
|
||||
- Timeline (gantt)
|
||||
|
||||
Utilise un bloc de code avec le langage mermaid quand ça clarifie l'explication. Pas pour du texte simple.
|
||||
</mermaid>
|
||||
|
||||
`
|
||||
|
||||
type ShellMessage struct {
|
||||
ID string `json:"id"`
|
||||
Role string `json:"role"`
|
||||
@@ -22,9 +79,10 @@ type ShellMessage struct {
|
||||
}
|
||||
|
||||
type ShellConvStore struct {
|
||||
mu sync.RWMutex
|
||||
path string
|
||||
msgs []ShellMessage
|
||||
mu sync.RWMutex
|
||||
path string
|
||||
msgs []ShellMessage
|
||||
realTokens int
|
||||
}
|
||||
|
||||
func NewShellConvStore() *ShellConvStore {
|
||||
@@ -82,19 +140,37 @@ func (s *ShellConvStore) Clear() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
s.msgs = []ShellMessage{}
|
||||
s.realTokens = 0
|
||||
s.save()
|
||||
}
|
||||
|
||||
func (s *ShellConvStore) ApproxTokens() int {
|
||||
if s.realTokens > 0 {
|
||||
return s.realTokens
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
total := 0
|
||||
for _, m := range s.msgs {
|
||||
total += utf8.RuneCountInString(m.Content) / shellCharsPerToken
|
||||
}
|
||||
total += utf8.RuneCountInString(shellSystemPromptBase) / shellCharsPerToken
|
||||
if analysis := LoadSystemAnalysis(); analysis != "" {
|
||||
total += utf8.RuneCountInString(analysis) / shellCharsPerToken
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// AddRealTokens accumulates actual token counts from the API response.
|
||||
func (s *ShellConvStore) AddRealTokens(tokens int) {
|
||||
if tokens <= 0 {
|
||||
return
|
||||
}
|
||||
s.mu.Lock()
|
||||
s.realTokens += tokens
|
||||
s.mu.Unlock()
|
||||
}
|
||||
|
||||
func (s *ShellConvStore) AtLimit() bool {
|
||||
return s.ApproxTokens() >= shellMaxTokens
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user