summaryrefslogtreecommitdiff
path: root/internal/lsp
AgeCommit message (Collapse)Author
2026-06-19ok0 document LSP and LLM exportsPaul Buetow
2026-06-11appconfig: split FeatureConfig into cohesive per-subsystem structsPaul Buetow
The FeatureConfig section was a grab-bag mixing five unrelated non-LLM subsystems (ignore filtering, stats, tmux popup editor, tmux action menu, MCP server). Decompose it into named per-subsystem structs (IgnoreConfig, StatsConfig, TmuxEditConfig, TmuxActionConfig, MCPConfig) embedded into FeatureConfig so the subsystem boundaries are explicit. Embedding keeps Go field promotion intact, so existing flat read access (e.g. cfg.MCPPromptsDir) and the JSON/TOML on-disk shape are unchanged; only composite literals that set these leaf fields directly were updated to the nested form. Add fine-grained, defensive-copy section accessors on App (IgnoreSection, StatsSection, TmuxEditSection, TmuxActionSection, MCPSection) so consumers can depend on a single subsystem's config instead of the whole App God-struct. Decouple slashcommands.NewSyncer to accept appconfig.MCPConfig rather than appconfig.App. All tests pass with -race; appconfig coverage 91.5%, total 86.2%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11Fix LSP panic: bounds-check stale line index in async chat applyPaul Buetow
When handleChatPrompt detects an in-editor chat prompt it captures the line index, then spawns a goroutine (requestChatResponse) that later calls applyChatEdits/buildChatHistory. If a concurrent didChange shrinks the document in the meantime, the captured lineIdx can exceed len(d.lines), causing an index-out-of-range panic in the chat goroutine. - applyChatEdits: skip the stale edit (and log) when lineIdx is < 0 or >= len(d.lines), rather than indexing d.lines[lineIdx] and panicking (or corrupting the already-changed document at the wrong position). - buildChatHistory: clamp the starting index to len(d.lines)-1 so the upward walk over d.lines[i] cannot read past the end. Adds regression test TestChatEdits_StaleLineIndexAfterShrink covering the shrink-then-apply race for both functions, including the one-past-the-end boundary and a negative index. Confirmed the test panics without the fix and passes with it; full `mage test` (-race) green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11Thread context.Context through blocking I/O entry pointsPaul Buetow
Accept ctx as the first parameter on the blocking I/O entry points and propagate it to downstream blocking calls so the work is cancellable from the process entry point: - appconfig.Load / LoadWithOptions: honor ctx before the blocking file reads, returning defaults on a cancelled context. - LSP: lsp.Server.Run(ctx) ties the serve loop to the caller context via a new watchParentContext bridge (cancels the server context, aborting in-flight LLM work). Threaded through hexailsp.Run/RunWithConfig/ RunWithFactory and runtimeconfig.Store.Reload. - MCP: mcp.Server.Run(ctx) stops accepting requests once ctx is cancelled; threaded through hexaimcp.Run/RunWithFactory/RunBackfill. - editor: RunEditor/OpenTempAndEdit/OpenFile take ctx and use exec.CommandContext so a cancelled context kills the editor subprocess; threaded through hexaicli, hexaiaction and askcli call sites. Top-level callers (cmd/hexai-lsp-server, cmd/hexai-mcp-server) now build a signal-cancelled context (SIGINT/SIGTERM) so shutdown tears the run down cleanly. Updated comments to explain the cancellation flow and added cancellation tests for the LSP/MCP loops, editor, and config load. All tests pass with -race; cross-package coverage 86.2%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11Extract shared chatrun package to eliminate chat-runner DRY violationsPaul Buetow
The CLI, LSP server and tmux code-action tool each carried near-identical chat-running logic: invoking the LLM (streaming-aware), collecting the response, and accounting sent/received bytes into the stats package. Introduce internal/chatrun with: - Invoke: streaming-aware LLM call that collects the full response and optionally mirrors chunks to a writer (nil writer = collect only). - SentBytes / Account: shared byte counting and stats.Update. Wire all three surfaces to it: - hexaicli: runChatRequest delegates to chatrun.Invoke; summarizeChatRun uses chatrun.Account. Removed the duplicated streaming/simple helpers. - hexaiaction: runOnce uses chatrun.Invoke + chatrun.Account, keeping the tmux status update local. - lsp: chatWithStats and the completion path use chatrun.SentBytes/Invoke; extracted unavailableClientError to keep chatWithStats small. chatrun has 100% test coverage; full suite passes with -race. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-11Refactor lsp.Server God Object: extract chat and completion subsystemsPaul Buetow
The Server type accumulated two large, tangled feature subsystems (in-editor chat and code completion) alongside its core LSP dispatch role. Pull them into cohesive types that own their state and logic while delegating shared infrastructure back to Server via a back-reference. - Add completionService (completion_service.go): owns the completion cache/throttle state (completionState) and all completion request-handling logic (handleCompletion, plan/jobs/execute, provider-native path, post-processing, message building, prefix heuristics). Methods moved off Server in handlers_completion.go to completionService. - Add chatService (chat_service.go + chat_handlers.go): owns the input-activity clock (lastInput, with its own mutex instead of Server.mu) and all in-editor chat logic (detection, transcript history, message building, edit application, inline prompts) plus the slash-command handlers (chat_commands.go). - Server now holds chat/completion fields, wires them in NewServer, and delegates (dispatch table, didChange, debounce gate) to them. Thin Server shims preserve the existing completion-state API for callers/tests. Pure refactor: no behavior or LSP protocol changes. Tests adjusted only to reach the relocated methods/state via the services. All tests pass with -race; coverage 86.1%. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10lsp: rename 'close' return to 'closeStr' in inlineMarkers to avoid shadowing ↵Paul Buetow
builtin The named return value 'close' in Server.inlineMarkers() shadowed the Go builtin 'close'. Renamed it to 'closeStr' (matching the 'openStr' naming used by callers) and added a comment explaining the reasoning. Callers use positional returns, so no call sites changed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-26fix(lsp): stop timer leak in deferShowDocumentPaul Buetow
Replace time.After with time.NewTimer + defer timer.Stop() to prevent a leaked goroutine when the context is cancelled before the timer fires.
2026-04-26feat: default to Ollama Cloud (kimi-k2.6) when no provider configuredPaul Buetow
Switches the in-code defaults so that hexai talks to Ollama Cloud (https://ollama.com) with model kimi-k2.6 when no provider is configured, instead of OpenAI. The example config, README, and configuration guide all reflect the new recommended setup; previous OpenAI / local-Ollama options are still documented as alternatives. Tests that depended on the implicit "openai" default now pin the provider explicitly so they continue to exercise the OpenAI / gpt-5 code paths they were designed to cover. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-03-23chore: bump version to v0.25.9v0.25.9Paul Buetow
Code quality fixes from audit: - Log silently discarded errors in status sinks and stats.Update call sites - Fix json.Marshal errors silently ignored in LSP handlers - Replace time.Sleep in tests with channel signaling (mcp) and fake clock (stats) - Make context cancellation work in production time.Sleep sites (handlers_document, cmdentry) - Remove init()-based provider registration from llm package; use explicit RegisterAllProviders() - Add WaitGroup goroutine tracking to MCP server Run() Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23refactor: split oversized functions, fix double logging, add %w wrappingPaul Buetow
- lsp/handlers_completion.go: extract buildNativeCompletionCacheKey and postProcessNativeCompletion; track collectFirstCompletion in inflight; remove redundant logLLMStats("") on error path - lsp/handlers.go: extract checkTriggerFromContext and checkTriggerFromCursorChar; isTriggerEvent reduced from 63→10 lines - lsp/transport.go: use %w for error wrapping in Content-Length parse - llm/ollama.go: extract parseOllamaStream; ChatStream reduced to ~35 lines - appconfig/config_load.go: extract decodeModelEntryFromMap; rename 'any' to 'found'; decodeModelEntry reduced to ~18 lines - llm/provider.go: document why providerRegistry is package-level - integrationtests/ask_test.go: add //go:build integration; move repoRoot init from init() to TestMain with diagnostic message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23fix: code quality improvements across lsp, askcli, appconfig, integrationtestsPaul Buetow
- lsp/handlers_completion.go: track collectFirstCompletion goroutine in inflight WaitGroup (goroutine leak fix) - lsp/transport.go: use %w instead of %v for error wrapping - askcli/command_list.go: extract handleListWithFilters shared helper; handleList/handleAll/handleReady are now single-liners - askcli/command_list.go, urgency.go, dep.go: log ParseTaskExport errors to stderr instead of returning 1 silently - appconfig/config_load.go: rename 'any' variable to 'found' to avoid shadowing the built-in identifier - llm/provider.go: add explanatory comment for package-level registry - integrationtests/ask_test.go: add //go:build integration tag; move repoRoot init from init() to TestMain with diagnostic error message Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23fix: address all HIGH-severity code quality audit findingsPaul Buetow
- lsp/server.go: track request goroutines in inflight WaitGroup to prevent use-after-close writes on shutdown - lsp/llm_client_registry.go: acquire write lock before calling build() to eliminate TOCTOU race on cache population - lsp/handlers_codeaction.go: resolveSimplifyCodeAction now uses PromptCodeActionSimplify{System,User} (was wrongly using rewrite prompts) - askcli/taskexport.go: remove exported MustParseTaskExport to prevent panic on malformed external input; move to unexported test helper - cmd/ask/main.go: print error to stderr before os.Exit - llm/{openai,ollama,openrouter}.go: add interface satisfaction assertions - integrationtests/ask_test.go: replace type assertions with errors.As for robust exec.ExitError unwrapping Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19Improve actionable error guidancePaul Buetow
2026-03-17Fix bugs, remove duplication, and clean up code quality issuesPaul Buetow
- Log swallowed JSON unmarshal errors in stats and LSP handlers - Fix debug log file handle leak in tmuxedit (return closer from initDebugLog) - Check f.Close() errors on write paths in promptstore and tmuxedit - Fix cacheGet TOCTOU race by using single write lock - Fix readInput to use passed stdin reader instead of os.Stdin.Stat() - Remove 45 'moved to' comment tombstones from lsp/handlers.go - Deduplicate canonicalProvider wrappers (use llmutils.CanonicalProvider directly) - Remove SetWindow side effect from stats.TakeSnapshot (pure read now) - Move duplicated splitLines to textutil.SplitLinesBytes - Collapse StatusSink.SetGlobal 10 params into GlobalStatus struct - Simplify LRU touchLocked to in-place delete-and-append Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16Strengthen LLM stats counter tests with value assertionsPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Fix byte vs UTF-16 indexing in LSP position handlingPaul Buetow
Adds utf16OffsetToByteOffset helper to correctly convert LSP character positions (UTF-16 code units) to Go string byte offsets. Fixes trigger detection, prefix heuristic, and completion text slicing for files containing multi-byte characters. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Extract LLM stats counters into llmStatsSubsystemPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Document lock ordering, fix test data races, correct stateMu guardPaul Buetow
- Add doc comments clarifying Server.mu and completionState.stateMu are independent (no ordering constraint). - Fix test using wrong lock (s.mu instead of stateMu) for lastLLMCall. - Replace time.Sleep polling in 7 tests with s.inflight.Wait() to eliminate data races under -race. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Add Snapshot.ScopeReqs/ScopeRPM and simplify 3 callersPaul Buetow
Centralizes the provider+model map traversal and window-minutes guard that was duplicated in hexaiaction, hexaicli, and lsp. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Track fire-and-forget goroutines with sync.WaitGroup for clean shutdownPaul Buetow
Adds inflight WaitGroup to Server and wraps inline-prompt, chat-response, and deferShowDocument goroutines. Run() waits for all in-flight work before returning. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Replace Summary: prefixes with standard Go package doc commentsPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Make deferShowDocument respect serverCtx for graceful shutdownPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Use atomic.Int64 for LLM stats counters instead of server-wide mutexPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Address review: add zero-temp test, remove unused surface parameterPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Centralize GPT-5 temperature override into llmutils.ResolveTemperaturePaul Buetow
Eliminates identical temperature resolution logic duplicated in hexaiaction, hexaicli, and lsp packages. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Add bounds checks to extractRangeText and split into helper functionsPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Use read lock for cache misses in completionState.cacheGetPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Replace interface{} with any in LSP typesPaul Buetow
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Add doc comments to exported types and functionsPaul Buetow
Document ~30 exported types in lsp/types.go and exported functions in llm/provider.go, lsp/server.go, and hexailsp/run.go. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16Decompose App God struct into embedded section structsPaul Buetow
Replace 60+ flat fields in App with 4 embedded section structs: CoreConfig, ProviderConfig, PromptConfig, FeatureConfig. Go field promotion preserves all existing field access patterns. Updated flattenAppConfig to recurse into embedded structs for runtimeconfig. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10task bf088a70: extract LSP client and completion statePaul Buetow
2026-03-02lsp: inject StatusSink to decouple core from tmux package (task 407)Paul Buetow
2026-03-02io: use errors.Is for EOF checks in lsp and mcp servers (task 409)Paul Buetow
2026-03-02gotest: extract Go codegen heuristics from lsp handlers (task 406)Paul Buetow
2026-03-02lsp: use appconfig.CustomAction directly for custom actions (task 411)Paul Buetow
2026-03-02lsp: decompose tryLLMCompletion orchestration helpers (task 415)Paul Buetow
2026-03-02lsp: decompose resolveGoTest workflow into helpers (task 416)Paul Buetow
2026-03-02lsp: decompose detectAndHandleChat into focused helpers (task 418)Paul Buetow
2026-03-02llmutils: remove remaining default-model wrappers in callers (task 413)Paul Buetow
2026-03-02lsp: cancel handler contexts on shutdown via server context (task 423)Paul Buetow
2026-03-02lsp: use context-mode registry for additional context dispatch (task 408)Paul Buetow
2026-03-02lsp: extract completion/chat/codeaction server subtypes (task 406)Paul Buetow
2026-03-02lsp: make exit flag atomic to avoid data race (task 406)Paul Buetow
2026-03-02lsp: handle code action payload marshal errors (task 406)Paul Buetow
2026-03-02lsp: simplify ServerOptions to config-first model (task 410)Paul Buetow
2026-03-02lsp: return cleanly on exit and propagate runner errors (task 410)Paul Buetow
2026-03-02llmutils: centralize provider normalization and client setup (task 410)Paul Buetow
2026-03-02codeaction: add Build/Resolve handler registries (task 410)Paul Buetow
2026-02-08add gitignore-aware file filtering for LSP completions and code actionsPaul Buetow
Files matching .gitignore patterns or user-configured extra patterns are now skipped for completions and code actions. Configurable via [ignore] section in config.toml with gitignore, extra_patterns, and lsp_notify_ignored options. Includes hot-reload support and env var overrides (HEXAI_IGNORE_*). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>