mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-05-07 19:17:30 +08:00
p0: purge orphan tool outputs on pairing error to prevent repeated 400 loops
This commit is contained in:
@@ -611,6 +611,11 @@ func (al *AgentLoop) processMessage(ctx context.Context, msg bus.InboundMessage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errText := strings.ToLower(err.Error())
|
||||||
|
if strings.Contains(errText, "no tool call found for function call output") {
|
||||||
|
removed := al.sessions.PurgeOrphanToolOutputs(msg.SessionKey)
|
||||||
|
logger.WarnCF("agent", "Purged orphan tool outputs after provider pairing error", map[string]interface{}{"session_key": msg.SessionKey, "removed": removed})
|
||||||
|
}
|
||||||
logger.ErrorCF("agent", "LLM call failed",
|
logger.ErrorCF("agent", "LLM call failed",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"iteration": iteration,
|
"iteration": iteration,
|
||||||
@@ -885,6 +890,11 @@ func (al *AgentLoop) processSystemMessage(ctx context.Context, msg bus.InboundMe
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
errText := strings.ToLower(err.Error())
|
||||||
|
if strings.Contains(errText, "no tool call found for function call output") {
|
||||||
|
removed := al.sessions.PurgeOrphanToolOutputs(sessionKey)
|
||||||
|
logger.WarnCF("agent", "Purged orphan tool outputs after provider pairing error (system)", map[string]interface{}{"session_key": sessionKey, "removed": removed})
|
||||||
|
}
|
||||||
logger.ErrorCF("agent", "LLM call failed in system message",
|
logger.ErrorCF("agent", "LLM call failed in system message",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"iteration": iteration,
|
"iteration": iteration,
|
||||||
|
|||||||
@@ -246,6 +246,81 @@ func (sm *SessionManager) SetPreferredLanguage(key, lang string) {
|
|||||||
session.mu.Unlock()
|
session.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sm *SessionManager) PurgeOrphanToolOutputs(key string) int {
|
||||||
|
sm.mu.RLock()
|
||||||
|
session, ok := sm.sessions[key]
|
||||||
|
sm.mu.RUnlock()
|
||||||
|
if !ok {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
session.mu.Lock()
|
||||||
|
defer session.mu.Unlock()
|
||||||
|
pending := map[string]struct{}{}
|
||||||
|
kept := make([]providers.Message, 0, len(session.Messages))
|
||||||
|
removed := 0
|
||||||
|
for _, m := range session.Messages {
|
||||||
|
role := strings.ToLower(strings.TrimSpace(m.Role))
|
||||||
|
switch role {
|
||||||
|
case "assistant":
|
||||||
|
for _, tc := range m.ToolCalls {
|
||||||
|
id := strings.TrimSpace(tc.ID)
|
||||||
|
if id != "" {
|
||||||
|
pending[id] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kept = append(kept, m)
|
||||||
|
case "tool":
|
||||||
|
id := strings.TrimSpace(m.ToolCallID)
|
||||||
|
if id == "" {
|
||||||
|
removed++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := pending[id]; !ok {
|
||||||
|
removed++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
delete(pending, id)
|
||||||
|
kept = append(kept, m)
|
||||||
|
default:
|
||||||
|
kept = append(kept, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if removed == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
session.Messages = kept
|
||||||
|
session.Updated = time.Now()
|
||||||
|
if sm.storage != "" {
|
||||||
|
_ = sm.rewriteSessionFileLocked(session)
|
||||||
|
_ = sm.writeOpenClawSessionsIndex()
|
||||||
|
}
|
||||||
|
return removed
|
||||||
|
}
|
||||||
|
|
||||||
|
func (sm *SessionManager) rewriteSessionFileLocked(session *Session) error {
|
||||||
|
if sm.storage == "" || session == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
path := filepath.Join(sm.storage, session.Key+".jsonl")
|
||||||
|
f, err := os.Create(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
for _, msg := range session.Messages {
|
||||||
|
e := toOpenClawMessageEvent(msg)
|
||||||
|
b, err := json.Marshal(e)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := f.Write(append(b, '\n')); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sm *SessionManager) TruncateHistory(key string, keepLast int) {
|
func (sm *SessionManager) TruncateHistory(key string, keepLast int) {
|
||||||
sm.mu.RLock()
|
sm.mu.RLock()
|
||||||
session, ok := sm.sessions[key]
|
session, ok := sm.sessions[key]
|
||||||
|
|||||||
Reference in New Issue
Block a user