feat: AI task API, token-based context windows, SSH password auth, sudo bypass detection
Replace message-count context windows with token-budget based ones for both studio and shell. Add /api/ai/task endpoint for background tool check/install/update. Enhance sudo blocking to catch piped/chained elevation commands. Add SSH password support via sshpass and connection editing UI. Remove realTokens persistence in favor of consumption tracking. Bump to 0.4.1. 💘 Generated with Crush Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
@@ -4,12 +4,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/muyue/muyue/internal/agent"
|
||||
"github.com/muyue/muyue/internal/orchestrator"
|
||||
@@ -133,7 +135,6 @@ func (s *Server) handleShellChatStream(w http.ResponseWriter, orb *orchestrator.
|
||||
storeContent = string(storeJSON)
|
||||
}
|
||||
s.shellConvStore.Add("assistant", storeContent)
|
||||
s.shellConvStore.AddRealTokens(engine.TotalTokens)
|
||||
|
||||
s.consumption.Record(engine.ProviderName(), engine.TotalTokens)
|
||||
|
||||
@@ -155,7 +156,6 @@ func (s *Server) handleShellChatNonStream(w http.ResponseWriter, orb *orchestrat
|
||||
}
|
||||
|
||||
s.shellConvStore.Add("assistant", finalContent)
|
||||
s.shellConvStore.AddRealTokens(engine.TotalTokens)
|
||||
|
||||
s.consumption.Record(engine.ProviderName(), engine.TotalTokens)
|
||||
|
||||
@@ -167,13 +167,45 @@ func (s *Server) handleShellChatNonStream(w http.ResponseWriter, orb *orchestrat
|
||||
|
||||
func (s *Server) buildShellContextMessages() []orchestrator.Message {
|
||||
history := s.shellConvStore.Get()
|
||||
start := 0
|
||||
const shellContextWindow = 20
|
||||
if len(history) > shellContextWindow {
|
||||
start = len(history) - shellContextWindow
|
||||
|
||||
sysTokens := utf8.RuneCountInString(shellSystemPromptBase) / charsPerToken
|
||||
if analysis := LoadSystemAnalysis(); analysis != "" {
|
||||
sysTokens += utf8.RuneCountInString(analysis) / charsPerToken
|
||||
}
|
||||
sysTokens += 100
|
||||
toolsTokens := utf8.RuneCountInString(string(s.shellAgentToolsJSON)) / charsPerToken
|
||||
responseMargin := 4000
|
||||
|
||||
overhead := sysTokens + toolsTokens + responseMargin
|
||||
available := shellMaxTokens - overhead
|
||||
if available < 1000 {
|
||||
available = 1000
|
||||
}
|
||||
|
||||
messages := make([]orchestrator.Message, 0, len(history[start:]))
|
||||
included := 0
|
||||
tokensUsed := 0
|
||||
for i := len(history) - 1; i >= 0; i-- {
|
||||
msgTokens := utf8.RuneCountInString(history[i].Content) / charsPerToken
|
||||
if msgTokens == 0 {
|
||||
msgTokens = 1
|
||||
}
|
||||
if tokensUsed+msgTokens > available {
|
||||
break
|
||||
}
|
||||
tokensUsed += msgTokens
|
||||
included++
|
||||
}
|
||||
|
||||
start := len(history) - included
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
if start > 0 {
|
||||
log.Printf("[shell] context budget: %d/%d tokens, including %d/%d messages (dropped %d older)", tokensUsed+overhead, shellMaxTokens, included, len(history), start)
|
||||
}
|
||||
|
||||
messages := make([]orchestrator.Message, 0, included)
|
||||
|
||||
for _, m := range history[start:] {
|
||||
content := m.Content
|
||||
|
||||
Reference in New Issue
Block a user