From 078428881c1a4d0aaec1b1bf2f85bd3a21d4e646 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sat, 4 Apr 2026 11:30:57 +0200 Subject: [PATCH] =?UTF-8?q?agent:=20revert=20auto-nudge=20=E2=80=94=20mode?= =?UTF-8?q?l=20choice=20is=20the=20right=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- agent/loop.go | 56 --------------------------------------------------- main.go | 4 ---- 2 files changed, 60 deletions(-) diff --git a/agent/loop.go b/agent/loop.go index 5a05d99..0395962 100644 --- a/agent/loop.go +++ b/agent/loop.go @@ -12,29 +12,6 @@ import ( ) const maxRateLimitRetries = 3 -const maxNudges = 2 - -// nudgeMsg is injected as a user turn when the model narrates intent without -// acting. It is ephemeral — added to the history slice for the next ChatStream -// call but never persisted to State, so it won't appear in future sessions. -const nudgeMsg = "Continue. Use execute_code now — do not describe what you will do." - -// narrationPhrases are case-insensitive prefixes/substrings that indicate the -// model is narrating intent rather than acting. -var narrationPhrases = []string{ - "let me", - "i'll ", - "i will ", - "i'm going to", - "i am going to", - "i need to", - "first, i", - "first i'll", - "now i'll", - "now i will", - "to do this", - "i'll now", -} type ToolExecutor func(name string, args json.RawMessage) (string, error) type OutputFn func(msg OutputMsg) @@ -62,19 +39,11 @@ func Run(ctx context.Context, cfg Config, state State) error { maxSteps = 1 } - var pendingNudge string - nudgeCount := 0 - for step := range maxSteps { history := state.History() if cfg.SystemPrompt != "" { history = append([]backend.Message{{Role: "system", Content: cfg.SystemPrompt}}, history...) } - // Inject nudge from previous step if the model narrated instead of acted. - if pendingNudge != "" { - history = append(history, backend.Message{Role: "user", Content: pendingNudge}) - pendingNudge = "" - } // Stream the assistant's response, retrying on HTTP 429. var ch <-chan backend.StreamEvent @@ -161,14 +130,6 @@ func Run(ctx context.Context, cfg Config, state State) error { } if len(toolCalls) == 0 { - // If the model narrated intent without acting, nudge it to continue - // rather than treating the turn as completion. - if nudgeCount < maxNudges && isNarration(content.String()) { - nudgeCount++ - pendingNudge = nudgeMsg - emit(cfg, OutputMsg{Role: "nudge", Content: nudgeMsg}) - continue - } if err := state.MarkComplete(); err != nil { return fmt.Errorf("mark complete: %w", err) } @@ -182,23 +143,6 @@ func Run(ctx context.Context, cfg Config, state State) error { return nil } -// isNarration returns true when text looks like the model is describing what it -// is about to do rather than doing it. Only short responses are considered — -// a longer response likely contains actual content or analysis. -func isNarration(text string) bool { - text = strings.TrimSpace(text) - if text == "" || len(text) > 800 { - return false - } - lower := strings.ToLower(text) - for _, phrase := range narrationPhrases { - if strings.Contains(lower, phrase) { - return true - } - } - return false -} - func emit(cfg Config, msg OutputMsg) { if cfg.Output != nil { cfg.Output(msg) diff --git a/main.go b/main.go index 9856a42..7c58398 100644 --- a/main.go +++ b/main.go @@ -468,10 +468,6 @@ func (m *model) apply(am agentMsg) { } m.display = append(m.display, "= "+s) - case "nudge": - // Model narrated without acting; loop injected a continuation prompt. - m.display = append(m.display, "[nudge: continuing…]") - case "retry": m.state = agentRetrying if secs, err := strconv.Atoi(am.content); err == nil {