| Age | Commit message (Collapse) | Author |
|
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
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>
|
|
Replace time.After with time.NewTimer + defer timer.Stop() to prevent
a leaked goroutine when the context is cancelled before the timer fires.
|
|
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>
|
|
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>
|
|
- 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>
|
|
- 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>
|
|
- 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>
|
|
|
|
- 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>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
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>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
- 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>
|
|
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>
|
|
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>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Eliminates identical temperature resolution logic duplicated in
hexaiaction, hexaicli, and lsp packages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
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>
|
|
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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>
|