llama-swap was http-only by DSN, pushing TLS-fronted instances onto the openai://
scheme (which loses the management/image methods). Add a "llama-swaps" scheme
that builds an https base URL, alongside "llama-swap" (http, local-first) —
mirroring redis/rediss. Both share one factory; llama-swaps is scheme-only (no
default built-in). The choice stays explicit because a DSN has no reliable
http-vs-https signal.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add provider/llamaswap, a tailored provider for llama-swap (the model-swapping
proxy over llama.cpp / stable-diffusion.cpp). Its chat path delegates to
provider/openai at {base}/v1 — no duplicated wire client (ADR-0007) — with
legacy max_tokens, a Bearer no-key placeholder for keyless local instances, and
a timeout-free client so cold model swaps rely on context deadlines. The
"tailored" surface is concrete management methods (ListModels / Running /
Unload) that don't belong on the canonical llm.Provider interface. The
llama-swap:// DSN scheme builds an http base URL (local-first); a no-URL
built-in errors clearly on use, mirroring foreman.
Add imagegen, a new canonical text-to-image interface separate from llm
(Request/Result/Model/Provider; Image = llm.ImagePart so generated images feed
straight back into chat). First backend is llama-swap via OpenAI
/v1/images/generations (b64_json, bytes-only). Re-exported from the root. v1 is
txt2img only.
Hermetic httptest coverage for chat delegation, management endpoints, image
decode, and scheme wiring. ADR-0015 + ADR-0016, README support matrix +
image-gen section, CLAUDE.md package map, and progress.md updated in the same
commit.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Records the PR workflow: push work to a PR (never straight to main), wait for
Gadfly to finish and weigh its findings, then grade each finding back to the
gadfly-reports MCP (record_finding_grade / list_findings / scoreboard) so the
telemetry can measure whether each model earns its keep.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A failover chain previously treated a successful-but-empty completion (no
content parts and no tool calls — a "stop with nothing") as a valid result
and returned it. The agent loop then ended the run with empty output, and
the configured backup models were never tried because no error was raised.
This let a single flaky model silently terminate an agent/skill run with
no answer (observed in the wild with ollama-cloud/glm-5.2 returning empty
completions right after a large tool/think turn).
- Add llm.ErrEmptyResponse (classified transient) and Response.IsEmpty():
true only when there are no tool calls and no meaningful content (no
parts, or whitespace-only text). A media/image part counts as content,
so image-only responses are NOT empty.
- chain.Generate converts an empty completion into ErrEmptyResponse so the
chain fails over to the next target. Unlike an ordinary transient it is
NOT retried on the same target (the model just produced it; these calls
are expensive) — the chain penalizes health (so a persistently-empty
target benches) and advances immediately.
- When every target returns empty the call fails with ErrChainExhausted
joined to ErrEmptyResponse — a visible error instead of a hollow success.
Single-element chains therefore also surface empties as errors.
Stream path is unchanged (can't inspect content before the consumer reads
it). Tests: Response.IsEmpty table; chain fails over past an empty head;
all-empty chain returns ErrChainExhausted/ErrEmptyResponse; repeated
empties bench the target across requests. Full suite green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- README + CLAUDE.md: upfront "this is a vibe-coded project" disclosure for
going public.
- Replace internal LAN hostnames (*.orgrimmar.dudenhoeffer.casa) with
example.com across README, ADR-0004, the envproviders example, and env_test.go
(assertions updated together; suite still green). Token was already a
"change-me" placeholder, not a real secret.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>