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

@@ -21,6 +21,7 @@ type ChatEngine struct {
tools json.RawMessage
onChunk func(map[string]interface{})
stream bool
TotalTokens int
}
// NewChatEngine creates a new ChatEngine instance.
@@ -71,6 +72,10 @@ func (ce *ChatEngine) RunWithTools(ctx context.Context, messages []orchestrator.
return finalContent, allToolCalls, allToolResults, err
}
if resp.Usage.TotalTokens > 0 {
ce.TotalTokens += resp.Usage.TotalTokens
}
choice := resp.Choices[0]
content := cleanThinkingTags(choice.Message.Content)
@@ -123,6 +128,11 @@ func (ce *ChatEngine) RunWithTools(ctx context.Context, messages []orchestrator.
"content": result.Content,
"is_error": result.IsError,
}
if result.Meta != nil {
for k, v := range result.Meta {
resultData[k] = v
}
}
allToolResults = append(allToolResults, map[string]interface{}{
"tool_call_id": tc.ID,
"name": tc.Function.Name,
@@ -149,6 +159,11 @@ func (ce *ChatEngine) RunWithTools(ctx context.Context, messages []orchestrator.
return finalContent, allToolCalls, allToolResults, nil
}
// ProviderName returns the name of the active provider used by the engine.
func (ce *ChatEngine) ProviderName() string {
return ce.orchestrator.ProviderName()
}
// RunNonStream executes chat without streaming content to client.
func (ce *ChatEngine) RunNonStream(ctx context.Context, messages []orchestrator.Message) (string, error) {
var finalContent string
@@ -159,6 +174,10 @@ func (ce *ChatEngine) RunNonStream(ctx context.Context, messages []orchestrator.
return finalContent, err
}
if resp.Usage.TotalTokens > 0 {
ce.TotalTokens += resp.Usage.TotalTokens
}
choice := resp.Choices[0]
content := cleanThinkingTags(choice.Message.Content)