Skip to content

Feature request: Empower Gortex with a pluggable LLM layer#25

Merged
zzet merged 6 commits into
mainfrom
feature_request_empower_with_llm
May 14, 2026
Merged

Feature request: Empower Gortex with a pluggable LLM layer#25
zzet merged 6 commits into
mainfrom
feature_request_empower_with_llm

Conversation

@zzet
Copy link
Copy Markdown
Owner

@zzet zzet commented May 14, 2026

Adds an opt-in LLM capability to Gortex and generalizes it into a multi-provider backend. Three commits, building on each other.

1. Global LLM config

~/.config/gortex/config.yaml gains an llm: block. A repo-local .gortex.yaml llm: block layers over it per non-zero field (local wins), with ~/ model paths expanded against $HOME. Lets users keep model/tuning config in one place
across repos.

2. LLM-assisted search ranking

search_symbols gains an assist arg — auto / on / off / deep:

  • auto uses a cheap NL heuristic to skip identifier lookups
  • active modes run query expansion + name/signature rerank
  • deep adds a body-grounded verification pass that reads candidate bodies + callers and honestly drops irrelevant matches (an empty result is the load-bearing negative signal)

Backed by a pre-warmed assist context with LRU caches for expand/rerank/verify.

3. Pluggable multi-provider backend

Generalizes the LLM layer behind an llm.Provider interface, selected by the llm.provider config key:

  • local — in-process llama.cpp; the only -tags llama package, ships a non-llama stub
  • anthropic / openai / ollama — pure-Go HTTP clients, available in every build (forced tool-use / json_schema / format schema)

Provider is a single-method surface (Complete) over a provider-neutral []Message conversation; the ask agent loop and the three assist passes are all built on it. Tool calls travel as plain text so one message shape works across every
provider. Assist prompts are tiered by capability (small / frontier) keyed off the active provider.

Knock-on: agent and svc are now pure Go — the build-tag split is contained entirely in provider/local. The ask tool and assist modes work with any provider, not just llama builds; the stub files are deleted and registerLLMTools
is unconditional. CGO is now opt-in (only local needs it).

Test plan

  • go build ./... and go build -tags llama ./...
  • go vet — clean both tag configs
  • go test -race ./... — passes
  • go test -tags llama -race ./... — passes (3664 tests, 113 packages)
  • -tags llama e2e assist test exercises the local provider against a real GGUF model
  • New unit tests: provider config merge/defaults, prompt tiering, JSON schemas, and httptest-based request-shaping/response-parsing for all three HTTP providers
  • Manual: configure llm.provider: anthropic (+ ANTHROPIC_API_KEY) and confirm ask / search_symbols assist:deep work without a -tags llama build

zzet added 4 commits May 14, 2026 17:17
~/.config/gortex/config.yaml gains an `llm:` block. MergeLLMInto fills
zero fields of the repo-local llm config from the global one (local
non-zero values win, including an explicit per-repo override of an
inherited model path), with leading `~/` in model paths expanded
against $HOME. The daemon and `gortex mcp` startup paths both load and
merge the global config before SetupLLM; env vars still override last.
search_symbols gains an `assist` arg (auto/on/off/deep). `auto` uses a
cheap NL heuristic to skip identifier lookups; active modes run grammar-
constrained query expansion + name/signature rerank, and `deep` adds a
body-grounded verification pass that reads candidate bodies and callers
and honestly drops irrelevant matches — an empty result is preserved as
the load-bearing negative signal.

The svc layer adds a pre-warmed assist context with its own mutex and KV
cache so short assist calls don't head-of-line block a long `ask`, plus
LRU caches for expand/rerank/verify. The stub build returns
errServiceUnavailable for all three new methods.
Introduce an llm.Provider interface so the `ask` agent and the
search_symbols assist passes run on any of four backends, selected by
the `llm.provider` config key:

- local — in-process llama.cpp, the only `-tags llama` package; ships a
  non-llama stub so the provider factory always compiles
- anthropic / openai / ollama — pure-Go HTTP clients, available in every
  build, via forced tool-use / json_schema / `format` schema respectively

Provider is a single-method surface (Complete) over a provider-neutral
[]Message conversation; the agent tool-loop and the three assist passes
are all built on it. Tool calls travel as plain text (emulated protocol)
so one Message shape works across every provider.

llm.Config gains a `provider` key plus per-provider sub-blocks, replacing
the flat llama-only shape; MergedWith / MergeLLMInto merge per sub-block.
Assist prompts are tiered by capability (small / frontier) and keyed off
the active provider's name rather than carried per-provider.

Knock-on: agent and svc are now pure Go — the build-tag split is
contained entirely in provider/local. The `ask` tool and assist modes
work with any provider, not just llama builds; service_stub.go and
tools_llm_stub.go are deleted and registerLLMTools is unconditional.
SetupLLM logs provider-construction errors instead of silently disabling.
@zzet zzet self-assigned this May 14, 2026
@zzet zzet merged commit d4ace00 into main May 14, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant