rony-llm-agent/pkg/llm
Victor Vargas 838eef642a fix(openai): make streaming actually work; honor configured model
The Stream() path was broken end to end:
- requests always went out with "stream": false, so the SSE parser found
  no data lines and every stream ended empty
- Config.Model was discarded at construction, and the agent loop never
  sets req.Model, so requests carried an empty model (hard API error)
- tool-call deltas were ignored entirely: the agent never executed tools
  over a stream with this provider (which also backs the ollama type)
- usage was neither requested nor parsed, so token tracking stayed at 0

Now mirrors the proven llamacpp client: stream flag + stream_options
.include_usage, per-index tool-call fragment accumulation flushed on
finish_reason, usage passthrough, a 4MB SSE scanner buffer (64KB default
kills the stream on large tool arguments), and an empty-choices guard in
toResponse instead of a panic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-12 16:14:01 -07:00
..
mock test(llm,embeddings): add unit tests for mock client, types, and Ollama embedder 2026-07-03 14:22:41 -07:00
providers fix(openai): make streaming actually work; honor configured model 2026-07-12 16:14:01 -07:00
README.es.md docs(i18n): translate all docs to English (with .es.md as Spanish alternative) 2026-06-30 13:40:37 -07:00
README.md docs(i18n): translate all docs to English (with .es.md as Spanish alternative) 2026-06-30 13:40:37 -07:00
types.go Fix tool call tracking and streaming assembly for all providers 2026-07-08 16:11:57 -07:00
types_test.go test(llm,embeddings): add unit tests for mock client, types, and Ollama embedder 2026-07-03 14:22:41 -07:00

pkg/llm

Multi-provider abstraction for language models.

Responsibility

Define a common interface (LLMClient) and adapters for the main providers.

Public API

type LLMClient interface {
    Generate(ctx context.Context, req CompletionRequest) (CompletionResponse, error)
    Stream(ctx context.Context, req CompletionRequest) iter.Seq2[StreamChunk, error]
    Name() string
    Capabilities() ProviderCapabilities
}

type CompletionRequest struct {
    Messages    []Message
    Tools       []tools.Tool
    ToolChoice  ToolChoice
    Model       string
    Temperature *float32
    MaxTokens   *int
}

type CompletionResponse struct {
    Content    string
    ToolCalls  []tools.Call
    Usage      TokenUsage
    StopReason string
}

type ProviderCapabilities struct {
    SupportsTools    bool
    SupportsVision   bool
    MaxContextWindow int
}

Included providers

Provider Package Tool support
OpenAI providers/openai
Anthropic providers/anthropic
Ollama providers/ollama (models that support it)
llama.cpp providers/llamacpp (with grammar)

Usage

import "github.com/VictorVargas/rony-llm-agent/pkg/llm/providers/anthropic"

client, err := anthropic.New(anthropic.Config{
    APIKey: os.Getenv("ANTHROPIC_API_KEY"),
    Model:  "claude-sonnet-4.5",
})

resp, err := client.Generate(ctx, llm.CompletionRequest{
    Messages: []llm.Message{
        {Role: llm.RoleUser, Content: "Hello"},
    },
})

Streaming

for chunk, err := range client.Stream(ctx, req) {
    if err != nil { return err }
    fmt.Print(chunk.Delta)
}

Mock for tests

import "github.com/VictorVargas/rony-llm-agent/pkg/llm/mock"

mockClient := mock.New(mock.Responses{
    {Match: "hello", Response: "Hi! How are you?"},
    {Match: "*",    Response: "default"},
})

See also