feat: agent concurrency, conversation summaries, AI tools config, UI polish
Some checks failed
Stable Release / stable (push) Failing after 33s

- Agent slot limiter for concurrent tool execution
- Conversation summarization with soft-delete (MarkSummarized)
- ANSI stripping in terminal tool output
- Configurable crush-run timeout (default 600s, max 900s)
- Starship theme refactor, AI tools config grid, system update UI
- Streaming segments refactor, summarized messages block in feed
- CSS: headings, scrollbars, tool cards, summary block styles
- i18n additions (en+fr) for tools, updates, config

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
Augustin
2026-04-27 00:01:22 +02:00
parent d98110ce8a
commit 3740454201
23 changed files with 1028 additions and 556 deletions

View File

@@ -6,11 +6,18 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"sync"
"time"
)
var ansiRegex = regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b\][^\x1b]*\x1b\\|\x1b[()][AB012]|\[\]`)
func stripANSI(s string) string {
return ansiRegex.ReplaceAllString(s, "")
}
var (
sudoCache bool
sudoCacheSet bool
@@ -103,6 +110,7 @@ func NewTerminalTool() (*ToolDefinition, error) {
output, err := cmd.CombinedOutput()
result := string(output)
result = stripANSI(result)
if len(result) > 10000 {
result = result[:10000] + "\n... [truncated]"
}
@@ -116,7 +124,8 @@ func NewTerminalTool() (*ToolDefinition, error) {
}
type CrushRunParams struct {
Task string `json:"task" description:"The task description for Crush to execute"`
Task string `json:"task" description:"The task description for Crush to execute"`
Timeout int `json:"timeout,omitempty" description:"Maximum execution time in seconds (default 600, max 900)"`
}
func NewCrushRunTool() (*ToolDefinition, error) {
@@ -127,7 +136,14 @@ func NewCrushRunTool() (*ToolDefinition, error) {
return TextErrorResponse("task is required"), nil
}
ctx, cancel := context.WithTimeout(ctx, 300*time.Second)
timeout := time.Duration(p.Timeout) * time.Second
if timeout == 0 {
timeout = 600 * time.Second
}
if timeout > 900*time.Second {
timeout = 900 * time.Second
}
ctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
cmd := exec.CommandContext(ctx, "crush", "run", p.Task)
@@ -139,7 +155,14 @@ func NewCrushRunTool() (*ToolDefinition, error) {
}
if err != nil {
return TextErrorResponse(fmt.Sprintf("Crush error: %v\n\n%s", err, result)), nil
errMsg := fmt.Sprintf("Crush error: %v", err)
if ctx.Err() == context.DeadlineExceeded {
errMsg = fmt.Sprintf("Crush timed out after %d seconds. Try splitting the task into smaller parts.", int(timeout.Seconds()))
}
if result != "" {
errMsg += "\n\n" + result
}
return TextErrorResponse(errMsg), nil
}
return TextResponse(result), nil