mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-14 20:17:20 +00:00
The Ollama integration never applied a correct context window, so agents
with real prompts (20k-100k tokens) were rejected with HTTP 400
exceed_context_size_error against a 4096-token default.
Three root causes fixed:
1. FetchOllamaModelContext issued a GET to /api/show, which Ollama answers
with 405 (the endpoint is POST-only). Now POSTs {"model": "<name>"}.
2. The response parser expected a flat model_info.context_length, but a real
Ollama server namespaces the key by architecture (gemma4.context_length,
qwen3.context_length, ...). extractContextLength now matches "context_length"
or any "*.context_length" key.
3. num_ctx was resolved once at startup for a hardcoded "llama3.3" model and
never for the model an agent actually uses. Resolution now happens per
request for the real model inside OllamaProvider.resolveNumCtx, cached under
an RWMutex, with an explicit settings override winning and the fetched value
bounded by OllamaDefaultNumCtx so an enormous advertised window (Qwen3.5
reports 262144) cannot balloon the KV cache beyond VRAM.
Also classify Ollama's "exceed_context_size" 400 as a context-overflow error so
the pipeline's emergency-compaction+retry path (Issue 958) engages gracefully
instead of surfacing a raw error.
Co-authored-by: Bruno Clermont <bruno.clermont@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
66 lines
2.1 KiB
Go
66 lines
2.1 KiB
Go
package providers
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestOllamaBuildRequest_ThinkDefaultsToFalse verifies that when no
|
|
// provider-level thinking override is configured, buildRequest disables
|
|
// thinking by default (matches the OpenAI-compat Ollama path).
|
|
func TestOllamaBuildRequest_ThinkDefaultsToFalse(t *testing.T) {
|
|
p := NewOllamaProvider("ollama", "http://localhost:11434", "llama3.3", nil, nil)
|
|
req := ChatRequest{Messages: []Message{{Role: "user", Content: "hi"}}}
|
|
ollamaReq := p.buildRequest(context.Background(), req, false)
|
|
|
|
require.NotNil(t, ollamaReq.Think)
|
|
value, ok := ollamaReq.Think.Value.(bool)
|
|
require.True(t, ok, "expected Think.Value to be a bool")
|
|
assert.False(t, value)
|
|
}
|
|
|
|
// TestOllamaBuildRequest_ThinkOverride verifies that WithThinkingEnabled
|
|
// correctly sets ollamaReq.Think for both true and false overrides.
|
|
func TestOllamaBuildRequest_ThinkOverride(t *testing.T) {
|
|
trueVal := true
|
|
falseVal := false
|
|
|
|
cases := []struct {
|
|
name string
|
|
override *bool
|
|
want bool
|
|
}{
|
|
{name: "override true enables thinking", override: &trueVal, want: true},
|
|
{name: "override false disables thinking", override: &falseVal, want: false},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
p := NewOllamaProvider("ollama", "http://localhost:11434", "llama3.3", nil, nil).
|
|
WithThinkingEnabled(tc.override)
|
|
req := ChatRequest{Messages: []Message{{Role: "user", Content: "hi"}}}
|
|
ollamaReq := p.buildRequest(context.Background(), req, false)
|
|
|
|
require.NotNil(t, ollamaReq.Think)
|
|
value, ok := ollamaReq.Think.Value.(bool)
|
|
require.True(t, ok, "expected Think.Value to be a bool")
|
|
assert.Equal(t, tc.want, value)
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestOllamaThinkingEnabledAccessor verifies the WithThinkingEnabled /
|
|
// ThinkingEnabled getter/setter round-trip.
|
|
func TestOllamaThinkingEnabledAccessor(t *testing.T) {
|
|
p := NewOllamaProvider("ollama", "http://localhost:11434", "llama3.3", nil, nil)
|
|
assert.Nil(t, p.ThinkingEnabled())
|
|
|
|
trueVal := true
|
|
p.WithThinkingEnabled(&trueVal)
|
|
require.NotNil(t, p.ThinkingEnabled())
|
|
assert.True(t, *p.ThinkingEnabled())
|
|
}
|