feat: add llm.Foreman() constructor for foreman daemon integration #4

Closed
steve wants to merge 2 commits from feat/foreman-constructor into main
Owner

Summary

Adds llm.Foreman(baseURL, apiKey, opts...) to v2/constructors.go — a thin constructor that delegates to the existing native ollama provider. This is Level 0 of the foreman integration described in ADR-0011.

  • Zero new code paths. foreman speaks native Ollama on the wire (/api/chat), so the existing ollama provider handles streaming, tool use, and think transparently.
  • baseURL is positional and required — foreman has no default public address (it's a private daemon on the homelab/Tailscale).
  • apiKey can be empty for network-trusted deployments where the firewall/Tailscale is the auth boundary.
  • Includes DD#9 in v2/CLAUDE.md documenting the decision.

Usage

// Authenticated deployment
model := llm.Foreman("http://foreman.orgrimmar:8080", os.Getenv("FOREMAN_TOKEN")).Model("qwen3:30b")

// Network-trusted (no token)
model := llm.Foreman("http://foreman:8080", "").Model("qwen3:30b")

What this does NOT include

  • A dedicated foreman provider (Level 2) — deferred unless async /jobs or webhook integration is needed at the llm layer.
  • The foreman client package (Level 1 sync facade over /jobs) — that lives in the foreman repo.

Test plan

  • Verify go build ./... passes in v2/
  • Verify go vet ./... passes in v2/
  • Verify go test ./... passes in v2/
  • Manual: llm.Foreman(url, token).Model("qwen3:30b") produces a working client against a running foreman instance
## Summary Adds `llm.Foreman(baseURL, apiKey, opts...)` to `v2/constructors.go` — a thin constructor that delegates to the existing native ollama provider. This is Level 0 of the foreman integration described in [ADR-0011](https://gitea.stevedudenhoeffer.com/steve/foreman/src/branch/main/docs/adr/0011-go-client-and-go-llm-integration.md). - **Zero new code paths.** foreman speaks native Ollama on the wire (`/api/chat`), so the existing ollama provider handles streaming, tool use, and think transparently. - **`baseURL` is positional and required** — foreman has no default public address (it's a private daemon on the homelab/Tailscale). - **`apiKey` can be empty** for network-trusted deployments where the firewall/Tailscale is the auth boundary. - Includes DD#9 in `v2/CLAUDE.md` documenting the decision. ### Usage ```go // Authenticated deployment model := llm.Foreman("http://foreman.orgrimmar:8080", os.Getenv("FOREMAN_TOKEN")).Model("qwen3:30b") // Network-trusted (no token) model := llm.Foreman("http://foreman:8080", "").Model("qwen3:30b") ``` ### What this does NOT include - A dedicated foreman provider (Level 2) — deferred unless async `/jobs` or webhook integration is needed at the llm layer. - The foreman `client` package (Level 1 sync facade over `/jobs`) — that lives in the [foreman repo](https://gitea.stevedudenhoeffer.com/steve/foreman). ## Test plan - [ ] Verify `go build ./...` passes in `v2/` - [ ] Verify `go vet ./...` passes in `v2/` - [ ] Verify `go test ./...` passes in `v2/` - [ ] Manual: `llm.Foreman(url, token).Model("qwen3:30b")` produces a working client against a running foreman instance
steve added 2 commits 2026-05-23 22:37:14 +00:00
Foreman is a private queued Ollama endpoint with observability. Since it
speaks native Ollama on the wire, the constructor delegates to the existing
ollama provider — no new code paths. Streaming, tool use, and think all
work transparently.

baseURL is positional and required (no sensible default for a private
daemon). apiKey can be empty for network-trusted deployments.

See ADR-0011 in the foreman repo for the integration design.
docs: add DD#9 for foreman integration decision
CI / Root Module (pull_request) Failing after 6s
CI / Lint (pull_request) Failing after 6s
CI / V2 Module (pull_request) Successful in 1m25s
0c4e0081d8
steve closed this pull request 2026-05-24 15:14:46 +00:00
Some checks are pending
CI / Root Module (pull_request) Failing after 6s
CI / Lint (pull_request) Failing after 6s
CI / V2 Module (pull_request) Successful in 1m25s

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: steve/go-llm#4