diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-02 14:43:42 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-02 14:43:42 +0200 |
| commit | bd1e20279725c03c0d7244d1bb4425fe07dac787 (patch) | |
| tree | 29c5ca759542c9ec8a74792e8a9ffe4d52669d31 /internal | |
| parent | 36c332b4a3deef68c93232416c68ec2b74f108fb (diff) | |
lsp: inject StatusSink to decouple core from tmux package (task 407)
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/hexailsp/run.go | 13 | ||||
| -rw-r--r-- | internal/lsp/handlers_init.go | 3 | ||||
| -rw-r--r-- | internal/lsp/handlers_utils.go | 4 | ||||
| -rw-r--r-- | internal/lsp/server.go | 23 |
4 files changed, 38 insertions, 5 deletions
diff --git a/internal/hexailsp/run.go b/internal/hexailsp/run.go index 09889ec..ca24016 100644 --- a/internal/hexailsp/run.go +++ b/internal/hexailsp/run.go @@ -18,6 +18,7 @@ import ( "codeberg.org/snonux/hexai/internal/lsp" "codeberg.org/snonux/hexai/internal/runtimeconfig" "codeberg.org/snonux/hexai/internal/stats" + tmx "codeberg.org/snonux/hexai/internal/tmux" ) // ServerRunner is the minimal interface satisfied by lsp.Server. @@ -29,6 +30,17 @@ type ConfigurableServerRunner interface { ApplyOptions(lsp.ServerOptions) } +type tmuxStatusSink struct{} + +func (tmuxStatusSink) SetLLMStart(provider, model string) error { + return tmx.SetStatus(tmx.FormatLLMStartStatus(provider, model)) +} + +func (tmuxStatusSink) SetGlobal(reqs int64, rpm float64, sent int64, recv int64, provider, model string, scopeRPM float64, scopeReqs int64, window time.Duration) error { + status := tmx.FormatGlobalStatusColored(reqs, rpm, sent, recv, provider, model, scopeRPM, scopeReqs, window) + return tmx.SetStatus(status) +} + // ServerFactory creates a ServerRunner. Default uses lsp.NewServer. type ServerFactory func(r io.Reader, w io.Writer, logger *log.Logger, opts lsp.ServerOptions) ServerRunner @@ -150,5 +162,6 @@ func makeServerOptions(cfg appconfig.App, logContext bool, client llm.Client, lo Config: &cfg, Client: client, IgnoreChecker: ignoreChecker, + StatusSink: tmuxStatusSink{}, } } diff --git a/internal/lsp/handlers_init.go b/internal/lsp/handlers_init.go index 0cecc6c..24789f7 100644 --- a/internal/lsp/handlers_init.go +++ b/internal/lsp/handlers_init.go @@ -4,7 +4,6 @@ package lsp import ( "codeberg.org/snonux/hexai/internal" "codeberg.org/snonux/hexai/internal/logging" - tmx "codeberg.org/snonux/hexai/internal/tmux" ) func (s *Server) handleInitialize(req Request) { @@ -31,7 +30,7 @@ func (s *Server) handleInitialized() { logging.Logf("lsp ", "client initialized") // Emit an initial tmux heartbeat with provider/model if client := s.currentLLMClient(); client != nil { - _ = tmx.SetStatus(tmx.FormatLLMStartStatus(client.Name(), client.DefaultModel())) + s.emitLLMStartStatus(client.Name(), client.DefaultModel()) } } diff --git a/internal/lsp/handlers_utils.go b/internal/lsp/handlers_utils.go index adc3b7e..4a5bf4a 100644 --- a/internal/lsp/handlers_utils.go +++ b/internal/lsp/handlers_utils.go @@ -13,7 +13,6 @@ import ( "codeberg.org/snonux/hexai/internal/logging" "codeberg.org/snonux/hexai/internal/stats" "codeberg.org/snonux/hexai/internal/textutil" - tmx "codeberg.org/snonux/hexai/internal/tmux" ) type surfaceKind string @@ -198,8 +197,7 @@ func (s *Server) logLLMStats(model string) { minsWin = 0.001 } scopeRPM := float64(scopeReqs) / minsWin - status := tmx.FormatGlobalStatusColored(snap.Global.Reqs, snap.RPM, snap.Global.Sent, snap.Global.Recv, provider, modelName, scopeRPM, scopeReqs, snap.Window) - _ = tmx.SetStatus(status) + s.emitGlobalStatus(snap.Global.Reqs, snap.RPM, snap.Global.Sent, snap.Global.Recv, provider, modelName, scopeRPM, scopeReqs, snap.Window) } } } diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 9516e37..b33147c 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -29,6 +29,7 @@ type Server struct { logger *log.Logger serverCtx context.Context serverCancel context.CancelFunc + statusSink StatusSink exited atomic.Bool mu sync.RWMutex docs map[string]*document @@ -74,6 +75,12 @@ type codeActionSubsystem struct { altClients map[string]llm.Client } +// StatusSink receives status updates from the LSP server. +type StatusSink interface { + SetLLMStart(provider, model string) error + SetGlobal(reqs int64, rpm float64, sent int64, recv int64, provider, model string, scopeRPM float64, scopeReqs int64, window time.Duration) error +} + // ServerOptions collects configuration for NewServer to avoid long parameter lists. type ServerOptions struct { LogContext bool @@ -84,6 +91,7 @@ type ServerOptions struct { Client llm.Client // Gitignore-aware file checker (optional) IgnoreChecker *ignore.Checker + StatusSink StatusSink } func NewServer(r io.Reader, w io.Writer, logger *log.Logger, opts ServerOptions) *Server { @@ -144,6 +152,9 @@ func (s *Server) applyOptions(opts ServerOptions) { if opts.IgnoreChecker != nil { s.ignoreChecker = opts.IgnoreChecker } + if opts.StatusSink != nil { + s.statusSink = opts.StatusSink + } } // ApplyOptions updates the server's configuration at runtime. @@ -412,6 +423,18 @@ func (s *Server) cancelRequests() { } } +func (s *Server) emitLLMStartStatus(provider, model string) { + if s.statusSink != nil { + _ = s.statusSink.SetLLMStart(provider, model) + } +} + +func (s *Server) emitGlobalStatus(reqs int64, rpm float64, sent int64, recv int64, provider, model string, scopeRPM float64, scopeReqs int64, window time.Duration) { + if s.statusSink != nil { + _ = s.statusSink.SetGlobal(reqs, rpm, sent, recv, provider, model, scopeRPM, scopeReqs, window) + } +} + func (s *Server) Run() error { defer s.cancelRequests() for { |
