From dcc67b784556c01570fd7cb73020dc7fbd7a884e Mon Sep 17 00:00:00 2001 From: huaiyuWangh <34158348+huaiyuWangh@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:02:57 +0800 Subject: [PATCH] fix(app): fix goroutine leak, shutdown context, and model matching (#2298) - Add missing return after error send in RunNonInteractive goroutine - Use context.WithoutCancel for shutdown to preserve tracing context - Use strings.EqualFold for case-insensitive model matching - Preserve LSP ConnectedAt across state transitions --- internal/app/app.go | 3 ++- internal/app/lsp_events.go | 2 ++ internal/app/provider.go | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/app/app.go b/internal/app/app.go index e923a0337f125cab17192e94ef61e17d23ae6582..3755db0d5321029b88cc1c15d8fb99911f635bf3 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -246,6 +246,7 @@ func (app *App) RunNonInteractive(ctx context.Context, output io.Writer, prompt, done <- response{ err: fmt.Errorf("failed to start agent processing stream: %w", err), } + return } done <- response{ result: result, @@ -551,7 +552,7 @@ func (app *App) Shutdown() { var wg sync.WaitGroup // Shared shutdown context for all timeout-bounded cleanup. - shutdownCtx, cancel := context.WithTimeout(app.globalCtx, 5*time.Second) + shutdownCtx, cancel := context.WithTimeout(context.WithoutCancel(app.globalCtx), 5*time.Second) defer cancel() // Send exit event diff --git a/internal/app/lsp_events.go b/internal/app/lsp_events.go index 5292983d46cf867b9380ad45f7831007da54f0d7..babb9afe374108e1b80c4fb8910032f0c631f302 100644 --- a/internal/app/lsp_events.go +++ b/internal/app/lsp_events.go @@ -67,6 +67,8 @@ func updateLSPState(name string, state lsp.ServerState, err error, client *lsp.C } if state == lsp.StateReady { info.ConnectedAt = time.Now() + } else if existing, ok := lspStates.Get(name); ok { + info.ConnectedAt = existing.ConnectedAt } lspStates.Set(name, info) diff --git a/internal/app/provider.go b/internal/app/provider.go index 570edadf9e1647eeeeab32107d3da3a1d3494935..ea7c6ee110a74c17f80a667e7b891317437f6963 100644 --- a/internal/app/provider.go +++ b/internal/app/provider.go @@ -70,8 +70,8 @@ func findModels(providers map[string]config.ProviderConfig, largeModel, smallMod } func filter(modelFilter, providerFilter, model, provider string) bool { - return modelFilter != "" && model == modelFilter && - (providerFilter == "" || provider == providerFilter) + return modelFilter != "" && strings.EqualFold(model, modelFilter) && + (providerFilter == "" || strings.EqualFold(provider, providerFilter)) } // Validate and return a single match.