release: v0.6.0 — security audit fixes + 7 new features
All checks were successful
PR Check / check (pull_request) Successful in 57s

Audit corrections (security, concurrency, stability):
- chat_engine: bound resp.Choices[0] access, release tool slot per-iteration
- conversation_multi: synchronous save under existing lock (was racy fire-and-forget)
- workflow/engine: short-circuit on failed deps (no more infinite busy-wait); track failed/skipped status
- handlers_workflow: rune-aware truncate for plan goal (UTF-8 safe)
- server: CORS limited to localhost origins (was wildcard)
- handlers_info / terminal: mask API keys and SSH passwords as "***" in GET responses; preserve stored secret if "***" sent on update
- terminal: sshpass uses -e + SSHPASS env var (was both -p and -e)
- handlers_chat: MaxBytesReader 50 MB on /api/chat
- image_cache: 10 MB cap per image
- handlers_config: font size <= 72; profile-save unmarshal errors propagated
- handlers_info: /lsp/auto-install ProjectDir restricted to user home
- Shell.jsx: parenthesized resize-condition (operator precedence)
- orchestrator_test: CleanAIResponse capitalization (fixes failing vet)

New features:
- platform: detect OS name (Debian, Ubuntu, Windows 11, macOS X.Y) and inject in Studio system prompt next to the date
- agents: default timeout 30 min for crush_run/claude_run (cap also 30 min)
- agents: new cwd, wsl_distro, wsl_user params; on Windows hosts launch via "wsl -d <distro> -u <user> --cd <cwd> --"
- agents: new claude_run tool (mirror of crush_run for Claude Code CLI)
- terminal: list installed WSL distros individually in new-tab menu (Windows only)
- studio: system prompt rewritten around BMAD-METHOD personas + mandatory delegation template
- studio: "Réflexion avancée" toggle — inactive provider produces a preliminary report injected as [RAPPORT PRÉALABLE] context for the active provider
- studio: "Historique compressé" toggle — collapses past tool calls to last action only, with "Tout afficher" expansion
This commit is contained in:
Muyue
2026-04-27 10:12:11 +02:00
parent 0753167fb9
commit 6a7b4d8001
22 changed files with 804 additions and 145 deletions

View File

@@ -65,11 +65,11 @@ func TestCleanAIResponse(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := cleanAIResponse(tt.input)
result := CleanAIResponse(tt.input)
result = strings.TrimSpace(result)
expected := strings.TrimSpace(tt.expected)
if result != expected {
t.Errorf("cleanAIResponse(%q) = %q, want %q", tt.input, result, expected)
t.Errorf("CleanAIResponse(%q) = %q, want %q", tt.input, result, expected)
}
})
}
@@ -77,34 +77,34 @@ func TestCleanAIResponse(t *testing.T) {
func TestCleanAIResponseThinkRegex(t *testing.T) {
input2 := "<Think>some reasoning</Think>actual response"
result2 := cleanAIResponse(input2)
result2 := CleanAIResponse(input2)
if result2 != "actual response" {
t.Errorf("Valid Think tags should be removed: %q", result2)
}
input3 := "<think\nmultiline\nreasoning</think visible"
result3 := cleanAIResponse(input3)
result3 := CleanAIResponse(input3)
// No closing > on opening tag, so won't match regex
if result3 != "<think\nmultiline\nreasoning</think visible" {
t.Errorf("Malformed think should not be removed: %q", result3)
}
input4 := "<think type=re>reasoning</think visible"
result4 := cleanAIResponse(input4)
result4 := CleanAIResponse(input4)
// </think followed by space, not >, so won't match
if result4 != "<think type=re>reasoning</think visible" {
t.Errorf("Malformed closing should not be removed: %q", result4)
}
input_real := "prefix<think reasoning here</think suffix"
result_real := cleanAIResponse(input_real)
result_real := CleanAIResponse(input_real)
// The closing </think has no > after it, so won't match
if result_real != "prefix<think reasoning here</think suffix" {
t.Errorf("Malformed tags should pass through: %q", result_real)
}
input_valid := "<Think>reasoning</Think>result"
result_valid := cleanAIResponse(input_valid)
result_valid := CleanAIResponse(input_valid)
if result_valid != "result" {
t.Errorf("Valid tags should be removed: %q", result_valid)
}