feat(adapters): Add config file API key support and LiteLLM gateway adapter - #1191
feat(adapters): Add config file API key support and LiteLLM gateway adapter#1191SpootyMcSpoot wants to merge 9 commits into
Conversation
Greptile SummaryThis PR adds two features: (1) Anthropic API key resolution from the config file for the Claude adapter, and (2) a new Key concerns:
Confidence Score: 1/5
Important Files Changed
|
|
Hey @SpootyMcSpoot @cryppadotta @devinfoley — thanks for pushing this forward! The LiteLLM gateway adapter looks solid after the redesign (promptTemplate rendering + SSE streaming + token tracking is exactly what we need for unified proxy routing). I've been running a custom LLM router (HiveRouter in my Hive AI OS stack) that handles similar multi-provider setups (Gemini pooled keys, OpenAI-compatible endpoint). It's helped a ton with Google's recent Gemini deprecations (e.g., 2.0 Flash series blocked with 404 "no longer available to new users" for newer keys). A few HiveRouter-inspired ideas that could make this adapter more robust/resilient without much extra work:
In execute.ts, check if requested model is aliased → swap before sending to LiteLLM. This auto-handles Google’s forced upgrades without users editing configs every time. |
|
Thanks for the detailed review. Most of the flagged issues (proxy_auth header validation, cross-package imports, secret in .claude/memory.md) are from commits that were accidentally included in this branch and will be separated into their own PRs. The core changes in this PR are:
For the LiteLLM-specific issue about cache fingerprint (hostname-only causing port collisions): Fixed - Updated baseUrlFingerprint to include port: function baseUrlFingerprint(baseUrl: string): string {
try {
const url = new URL(baseUrl);
return `${url.hostname}:${url.port || (url.protocol === "https:" ? "443" : "80")}`;
} catch {
return baseUrl.slice(0, 50);
}
}This resolves cache collisions when running multiple LiteLLM instances on the same host. Will clean up the branch to remove the proxy_auth/auth/CLI changes before merge. |
|
Thanks for the suggestions - these are great ideas for making the adapter more production-ready. The model aliasing, endpoint override, and fallback chain features would be valuable additions. For this initial PR, I've kept the adapter minimal to match the existing Paperclip adapter patterns (promptTemplate rendering, SSE streaming, token tracking). I'd suggest implementing these as follow-up enhancements:
These could be added incrementally after the base adapter lands. Happy to collaborate on implementation or review PRs for these features. Re: P0 issues - most are from unrelated commits accidentally included in this branch. Will clean those up before merge. |
- Add litellm_gateway adapter for OpenAI-compatible LiteLLM proxy - Support SSE streaming, token usage tracking, model discovery - Add API key resolution from config file with env var precedence - Add model discovery for local adapters via provider API with caching - Include port in LiteLLM cache fingerprint to avoid collisions
d112c34 to
60bcc95
Compare
|
@cryppadotta @devinfoley PR is g2g. |
ChandlerHardy
left a comment
There was a problem hiding this comment.
Code Review — APPROVED ✓
PR: feat(adapters): Add config file API key support and LiteLLM gateway adapter
Two well-scoped additions. Reviewed the security-critical paths carefully.
Phase 1: Config file API key support (claude-models.ts)
resolveAnthropicApiKey(): Env var wins over config file. Correct precedence.fingerprint(apiKey): Uses${length}:${last6}for cache invalidation. This never logs the full key — acceptable in-memory only.- 60s TTL model cache with graceful fallback to static models on fetch failure. Good.
- 5s request timeout to Anthropic models API. Good.
Phase 2: LiteLLM gateway adapter (execute.ts)
new URL(baseUrl)validation catches malformed URLs. Note: doesn't restrict to http(s) schemes, butfetch()will reject non-http(s) at runtime. Acceptable.resolveLiteLLMApiKey(): Config value wins overLITELLM_API_KEYenv var — note this is the opposite priority from the Anthropic key resolver. Flag for documentation/consistency if this causes operator confusion.- Custom headers are string-typed only before being sent. Correct.
Authorizationheader is always appended aftercustomHeaders, so it's not accidentally overridden by caller-supplied headers. ✓temperatureis clamped to[0, 2],maxTokenshas a floor of 1. Correct bounds.- SSE streaming is correctly parsed (skips
data: [DONE]lines, handles partial lines with buffer).
Minor notes
- API key precedence inconsistency: Anthropic = env var > config. LiteLLM = config > env var. This asymmetry should be documented.
- No tests: Neither the claude-models module nor the litellm execute module has unit tests. Understandable for a new adapter but worth tracking.
Dockerfilechange: addsplugin-sdkpackage.json copy and build step (same as PR #1214 but without the--frozen-lockfileremoval). Correct.
LGTM.
|
Sorry about the unsolicited review — my automated code reviewer (running on Paperclip) accidentally scanned this repo instead of just my own projects. Feel free to dismiss it. |
No worries, I appreciate the extra validation checks lol! |
STAX-Specific Configuration DetectedIssue: This PR contains STAX-specific infrastructure configuration that should not be in the public upstream repository. Found in PRProblem: Recommended FixOption 1: Remove the ci:
uses: Anomalous-Ventures/devops/.github/workflows/ci-nodejs.yml@main
with:
node-version: '22'
package-manager: 'pnpm'
# Removed docker-registry - use default or override in forks
secrets: inheritOption 2: Comment with instructions for users to override in their forks ci:
uses: Anomalous-Ventures/devops/.github/workflows/ci-nodejs.yml@main
with:
node-version: '22'
package-manager: 'pnpm'
# Override docker-registry in your fork's workflow file
# docker-registry: 'your-registry.example.com'
secrets: inheritRelated CleanupWe've completed a full audit of the fork and removed all STAX-specific references:
Recommendation: Before merging this PR, please remove the Let me know if you'd like me to update the PR to fix this issue! |
Remove hardcoded registry reference from public repository. Users can override docker-registry parameter in their fork if needed.
|
✅ Fixed in latest commit The STAX-specific docker registry reference has been removed in commit b8ab621. The CI workflow now uses a commented example, allowing users to override the docker-registry parameter in their forks without exposing proprietary infrastructure details in the upstream repository. |
Summary
This PR implements two new features for Paperclip adapters:
Phase 1: Config File API Key Support
Enables Anthropic API key configuration via config file in addition to environment variables.
Implementation:
server/src/adapters/claude-models.tswith model discoveryresolveAnthropicApiKey(): ChecksANTHROPIC_API_KEYenv var first, thenconfig.llm.apiKeylistClaudeModelsin adapter registryPhase 2: LiteLLM Gateway Adapter
New adapter to use LiteLLM proxy as a unified gateway to multiple LLM providers.
Implementation:
packages/adapters/litellm-gateway/packageonLog/v1/modelswith 60s cachingConfiguration Example:
```json
{
"type": "litellm_gateway",
"baseUrl": "http://localhost:4000",
"apiKey": "sk-litellm-...",
"model": "gpt-4",
"promptTemplate": "You are {{agent.name}}. Task: {{context.taskId}}",
"temperature": 0.7,
"maxTokens": 4096
}
```
Key Features
fetch)Testing
Local tests: All tests passing (53 test files, 228 tests)
Deployment test:
harbor.spooty.io/library/paperclip:feat-litellm-91dfb3bpaperclipnamespaceFiles Changed (Core Features)
server/src/adapters/claude-models.ts(new)server/src/adapters/registry.ts(modified)packages/adapters/litellm-gateway/(new package)packages/shared/src/constants.ts(addedlitellm_gatewaytype)server/package.json(added litellm adapter dependency)Dockerfile(added litellm package.json to build deps)docs/adapters/litellm-gateway.md(new documentation)pnpm-lock.yaml(updated)Note on Additional Changes
This branch accidentally includes commits for proxy_auth mode, local auth bypass, and provision-admin CLI features. These will be separated into their own PRs. The core changes for this PR are the Claude config file API key support and LiteLLM gateway adapter only.