feat(ai): point the platform at any model, not just Anthropic #5561
ccantynzAI Reviewcommented 5d ago
AI Triage
(no summary)
Priority: medium Risk area: mixed
Suggested labels: (no label suggestions) Suggested reviewers: (no reviewer suggestions)
Suggestions only — nothing has been applied. The PR author stays in control.
gluecron[bot]🤖 botAI Reviewcommented 5d ago
AI review unavailable
The platform's AI balance is exhausted, so AI generation is temporarily unavailable. Nothing was lost. You can queue this as a repair for the internal agent from the repository's Health page, or try again once the balance is restored. The PR is otherwise unchanged.
Cross-repo impact
See what breaks downstream if this PR merges.
⮌ Merged
This pull request was merged into main.
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts
Closes the one objection that would have cost us developers at launch.
The objection was portability, not uptime
Git, CI and merges contain zero AI references, so an Anthropic outage could never take the platform down. But the question a developer evaluating Gluecron actually asks is "can I point this at my own model?" — and the answer was no, not without editing source.
That is what "solely dependent on Anthropic" would have come to mean in a launch thread. Not availability. Portability.
It was a one-function problem
Despite 53 files using AI, the entire codebase contained exactly one runtime construction of the Anthropic SDK, in
ai-client.getAnthropic(). The nineimport type Anthropiclines are erased at compile time, and the only other match lives inside a template string of generated user code.So a provider only has to satisfy the slice those 53 files actually consume:
ai-provider.tsspeaks that shape over an OpenAI-compatible/chat/completionsendpoint. Not a single call site changed.AI_PROVIDER=openai # or inferred from AI_BASE_URL alone AI_BASE_URL=http://localhost:11434 AI_MODEL=llama3 AI_API_KEY= # local runtimes need noneBecause the OpenAI chat shape is the de-facto standard, one adapter reaches Ollama, LM Studio, vLLM, llama.cpp, OpenRouter, Together, Groq, Fireworks, Azure OpenAI and OpenAI itself — including models running entirely on the operator's own hardware, with no key and no egress.
Two details that decide whether this is real or nominal
isAiAvailable()does not require a key on the OpenAI path. A model served by Ollama on the same box authenticates nothing. Demanding a key there would report "AI unavailable" on a working local install — exactly the false negative that makes self-hosting feel broken.modelForTask()/internalModel()yield toAI_MODEL. The light/standard split is a Claude-pricing optimisation that means nothing to a runtime serving one model, and without this every request would 400 on an unknown model id.Testing the failure that would otherwise hide
A dropped system prompt or a mis-read response returns an empty string — so every AI feature would appear to work while producing confident blanks. That is the failure mode the 12 new tests exist to catch: system-prompt placement, content flattening, legacy
textfields, malformed/empty responses, absent auth headers, and error bodies surfaced rather than swallowed.Usage counts floor to
0rather thanNaN, because a NaN propagates into the spend ledger and poisons every later total.Verification
bun run typecheckcleanai-ci-healer,ai-quota-metering,copilot— 35 pass, 0 failFollow-on
The launch page should now demo this rather than claim it:
AI_BASE_URLpointed at a local Ollama, running a real PR review, is a far stronger answer than any paragraph.🤖 Generated with Claude Code