feat(providers): add Featherless preset - #1317
Conversation
|
Important Review skippedNo new commits to review since the last review. ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis change adds Featherless AI as an OpenAI-compatible provider. It adds authenticated model discovery, capability parsing, routing, request shaping, tests, registry parity, and localized documentation. ChangesFeatherless provider integration
Estimated code review effort: 3 (Moderate) | ~30 minutes Sequence Diagram(s)sequenceDiagram
participant ProviderRegistry
participant FeatherlessAPI
participant ModelCatalog
participant OpenAIChatAdapter
ProviderRegistry->>FeatherlessAPI: Request authenticated bounded /models catalog
FeatherlessAPI-->>ProviderRegistry: Return model records
ProviderRegistry->>ModelCatalog: Filter plan-available, ungated, tool-capable models
ModelCatalog-->>ProviderRegistry: Return model metadata and routes
OpenAIChatAdapter->>FeatherlessAPI: Send Bearer-authenticated chat request
Possibly related issues
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Wibias
left a comment
There was a problem hiding this comment.
Maintainer + security review verdict: REQUEST CHANGES.
I reviewed the registry/discovery policy, the shared provider-fetch.ts metadata change, request/auth path, filtering/bounds, same-name custom-provider preservation, fixtures/tests, current maintainer/CodeRabbit state, current dev, and Featherless's current first-party API/terms documentation.
What is good: the provider is useful for #572; the 128 KiB/100-row ceiling avoids the huge catalog; local predicates correctly re-check plan availability, gating, and tool support rather than trusting query filtering; slash IDs and custom destinations are preserved; the features metadata parsing extension is bounded and conservative. I found no secret logging, credential retarget, SSRF, or unbounded parsing issue.
Blocking correctness/security issue: Featherless explicitly documents /v1/models as callable in either an authenticated or unauthenticated context, with available_on_current_plan present only when authenticated. The generic validateApiKey() path currently treats any 2xx model-list response as proof that the supplied key is valid. The live invalid-key probe returning 401 today is useful evidence, but it is not a robust authentication contract for an endpoint that officially supports unauthenticated 2xx. This can become a false-positive key validation if invalid Authorization is ignored/falls back to anonymous behavior. Please either set this preset to apiKeyValidation: "unknown", or validate an authentication-only signal/endpoint (for example an auth-required contract such as /v1/plan, or equivalent proof that the response was authenticated) rather than status alone.
Other blocking changes:
- Rebase onto current
devand rerun full CI. This head is ~53devcommits behind, andsrc/codex/catalog/provider-fetch.tshas changed materially since the branch point. The old green CI does not validate the current integration result. - Fix the standalone provider counts. Current
devis 76 total / 64 key presets; this one-provider PR changes docs to 79 / 67. That is false if this PR lands alone. Update to the actual post-rebase/post-merge count or defer batch-count churn until sequential integration.
There are no unresolved prior review threads, but the key-validation boundary above needs correction before approval. Re-request security review on the new exact head after the rebase and fresh CI.
2189821 to
8949d4d
Compare
|
Addressed on
Ready for re-review on the new exact head. |
|
✅ Deterministic PR hygiene checks passed. |
✅ READY
Review readiness checklist
✅ 4/4 boxes ticked. This pull request is already Ready for Review. |
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs-site/src/content/docs/ja/guides/providers.md`:
- Around line 275-280: Update the Featherless discovery documentation in
docs-site/src/content/docs/ja/guides/providers.md lines 275-280,
docs-site/src/content/docs/ko/guides/providers.md lines 273-278,
docs-site/src/content/docs/ru/guides/providers.md lines 298-304, and
docs-site/src/content/docs/zh-cn/guides/providers.md lines 254-258. In each
locale, state that /v1/models may succeed with or without authentication and
therefore cannot validate the configured key, while chat requests still
authenticate using the configured Bearer key; write each statement in the
appropriate localized language.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ca13ed61-8859-4c8a-b69f-01b21b025938
📒 Files selected for processing (15)
docs-site/src/content/docs/getting-started/quickstart.mddocs-site/src/content/docs/guides/providers.mddocs-site/src/content/docs/ja/getting-started/quickstart.mddocs-site/src/content/docs/ja/guides/providers.mddocs-site/src/content/docs/ko/getting-started/quickstart.mddocs-site/src/content/docs/ko/guides/providers.mddocs-site/src/content/docs/ru/getting-started/quickstart.mddocs-site/src/content/docs/ru/guides/providers.mddocs-site/src/content/docs/zh-cn/getting-started/quickstart.mddocs-site/src/content/docs/zh-cn/guides/providers.mdsrc/codex/catalog/provider-fetch.tssrc/providers/registry.tstests/featherless-provider.test.tstests/fixtures/featherless-models.jsontests/provider-registry-parity.test.ts
|
|
|
|
🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== Current revision and changed files ==='
git rev-parse HEAD
git diff --name-status "$(git merge-base HEAD origin/dev)" HEAD
echo '=== Source structure ==='
ast-grep outline src/providers/registry.ts --items all --match 'featherless|Provider|modelDiscovery' || true
ast-grep outline src/codex/catalog/provider-fetch.ts --items all --match 'feature|capabilit|vision|modality' || true
ast-grep outline tests/featherless-provider.test.ts --items all || true
echo '=== Relevant registry and parser context ==='
rg -n -C 12 -i 'featherless|features|image_input|capabilit|vision' \
src/providers/registry.ts src/codex/catalog/provider-fetch.ts tests/featherless-provider.test.ts tests/provider-registry-parity.test.ts
echo '=== Changed diff ==='
git diff --find-renames --unified=80 "$(git merge-base HEAD origin/dev)" HEAD -- \
src/providers/registry.ts \
src/codex/catalog/provider-fetch.ts \
tests/featherless-provider.test.ts \
tests/fixtures/featherless-models.json \
tests/provider-registry-parity.test.ts \
docs-site/src/content/docsLength of output: 1707 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== Local refs ==='
git show-ref --heads --tags | sed -n '1,160p'
echo '=== Pull request metadata ==='
gh pr view 1317 --repo lidge-jun/opencodex \
--json number,baseRefName,baseRefOid,headRefOid,url \
--jq '{number, url, baseRefName, baseRefOid, headRefOid}'
base_sha="$(gh pr view 1317 --repo lidge-jun/opencodex --json baseRefOid --jq .baseRefOid)"
echo "=== Base commit availability: ${base_sha} ==="
git cat-file -e "${base_sha}^{commit}" 2>/dev/null && echo present || echo absent
if git cat-file -e "${base_sha}^{commit}" 2>/dev/null; then
echo '=== Changed files ==='
git diff --name-status "${base_sha}" HEAD
echo '=== Source structure ==='
ast-grep outline src/providers/registry.ts --items all --match 'featherless|Provider|modelDiscovery' || true
ast-grep outline src/codex/catalog/provider-fetch.ts --items all --match 'feature|capabilit|vision|modality' || true
ast-grep outline tests/featherless-provider.test.ts --items all || true
echo '=== Relevant implementation context ==='
rg -n -C 12 -i 'featherless|features|image_input|capabilit|vision' \
src/providers/registry.ts src/codex/catalog/provider-fetch.ts \
tests/featherless-provider.test.ts tests/provider-registry-parity.test.ts
echo '=== Diff ==='
git diff --find-renames --unified=80 "${base_sha}" HEAD -- \
src/providers/registry.ts \
src/codex/catalog/provider-fetch.ts \
tests/featherless-provider.test.ts \
tests/fixtures/featherless-models.json \
tests/provider-registry-parity.test.ts \
docs-site/src/content/docs
fiLength of output: 134031 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '=== Discovery and filtering symbols ==='
ast-grep outline src/providers/model-discovery.ts --items all || true
ast-grep outline src/codex/catalog/provider-fetch.ts --items all --match 'filter|discover|fetch|ModelsApi|parse' || true
echo '=== Discovery implementation ==='
rg -n -C 10 -P '\b(resolveProviderModelDiscovery|modelDiscovery|filter|matches.*Filter|fetch.*Models|ProviderModelsApiItem)\b' \
src/providers/model-discovery.ts src/codex/catalog/provider-fetch.ts src/providers/derive.ts src/types.ts
echo '=== API-item types and bounded response handling ==='
rg -n -C 10 -P '\b(ProviderModelsApiItem|maxResponseBytes|maxModels|redirect|response\.body|content-length)\b' \
src tests -g '*.ts'
echo '=== Parser test coverage outside Featherless ==='
rg -n -C 5 -P '\bcatalogHintsFromModelsApiItem\s*\(' tests src -g '*.ts'
echo '=== Exact changed source line numbers ==='
nl -ba src/providers/registry.ts | sed -n '1680,1765p'
nl -ba src/codex/catalog/provider-fetch.ts | sed -n '845,955p'Length of output: 187093
I found no blocking issues. The Featherless discovery policy is enforced at runtime. The implementation also preserves The review inspected the implementation and tests. It did not execute repository tests in this sandbox.
|
|
Tip For best results, initiate chat on the files or code changes.
The completed review found no blocking issues. You are interacting with an AI system. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/featherless-provider.test.ts`:
- Around line 199-222: Update the Featherless request test around
createOpenAIChatAdapter().buildRequest to assert that parallel_tool_calls is
omitted when parallelToolCalls is disabled, rather than expecting false. Modify
the OpenAI chat adapter serialization if it currently includes
parallel_tool_calls for false, while preserving serialization for providers that
enable parallel tool calls.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: eda02120-adbe-45de-86eb-5ec720766d4c
📒 Files selected for processing (15)
docs-site/src/content/docs/getting-started/quickstart.mddocs-site/src/content/docs/guides/providers.mddocs-site/src/content/docs/ja/getting-started/quickstart.mddocs-site/src/content/docs/ja/guides/providers.mddocs-site/src/content/docs/ko/getting-started/quickstart.mddocs-site/src/content/docs/ko/guides/providers.mddocs-site/src/content/docs/ru/getting-started/quickstart.mddocs-site/src/content/docs/ru/guides/providers.mddocs-site/src/content/docs/zh-cn/getting-started/quickstart.mddocs-site/src/content/docs/zh-cn/guides/providers.mdsrc/codex/catalog/provider-fetch.tssrc/providers/registry.tstests/featherless-provider.test.tstests/fixtures/featherless-models.jsontests/provider-registry-parity.test.ts
Featherless and other parallel-disabled OpenAI-compatible hosts should not receive an unsupported parallel_tool_calls field. NVIDIA NIM still sends explicit false because kimi rejects true and the registry documents that pin.
|
Tip For best results, initiate chat on the files or code changes.
The completed review found no blocking issues. You are interacting with an AI system. |
|
✅ Action performedReview finished.
|
|
✅ Action performedReview finished.
|
|
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/adapters/openai-chat.ts`:
- Around line 839-840: Update the else branch in the parsed options handling to
assign body.parallel_tool_calls only when parsed.options.parallelToolCalls is
explicitly true. Leave the field unset for false or undefined so providers
without the optional capability do not send it.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: bbda0856-1481-4cfa-8783-2e9aadd8bffa
📒 Files selected for processing (7)
src/adapters/openai-chat.tstests/chutes-provider.test.tstests/digitalocean-scaleway-provider.test.tstests/featherless-provider.test.tstests/nscale-vultr-provider.test.tstests/parallel-tool-calls-optin.test.tstests/sambanova-nebius-provider.test.ts
|
Tip For best results, initiate chat on the files or code changes.
You are interacting with an AI system. |
The openai-chat adapter now sends parallel_tool_calls only for providers with parallelToolCalls: true. Opted-out and unset providers omit the field; NIM still pins false.
|
Tip For best results, initiate chat on the files or code changes.
The pull request is ready for maintainer review. You are interacting with an AI system. |
|
|
|
|
|
|
|
Merged — thank you @olddonkey for the Featherless provider work and for iterating through the review feedback (auth boundary, localized docs, and parallel_tool_calls wire semantics). Appreciated! |
Summary
featherlessAPI-key preset for the fixed OpenAI-compatible endpointfeatures.tool_use: truefeaturesobjectRelates to #572. This PR intentionally does not close the umbrella issue.
Canonical evidence
Primary sources checked 2026-08-08:
https://api.featherless.ai/v1base URL, Bearer authentication, and OpenAI-compatible Chat Completionsavailable_on_current_plan, chat capability filtering, popularity sorting, and per-row feature metadataRead-only live probes found that the unqualified catalog is currently roughly 21,675 rows / 6.9 MiB.
per_page=100is honored, while the livegated=falsebehavior and combined capability filtering were not reliable enough to trust for admission. The preset therefore uses server query parameters only to bound the response and repeats every safety-relevant condition as a registry-owned local predicate. An invalid Bearer token withavailable_on_current_plan=truereturns 401, so the same bounded endpoint is a real key-validation boundary.Maintainer: @olddonkey. No affiliation with Featherless.
Security and behavior
config.jsonor the key-login mapreasoning_effortor parallel-tool-call claimThis touches authenticated provider discovery and key validation, so explicit security review is requested per
MAINTAINERS.md.Verification
bun test tests/featherless-provider.test.ts tests/provider-registry-parity.test.ts tests/provider-model-discovery-contract.test.ts— 68 pass, 0 failbun run typecheckbun run privacy:scanbun run test— 10,062 pass, 7 skip, 0 failgit diff --checkChecklist
devReview readiness
21898212.devcommit available when this checklist was completed (f310cc20).Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Review readiness checklist
This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:
All CI tests are green on my local testing.
I pushed my PR to the latest dev commit.
I resolved all correct Codex and CodeRabbit findings.
My PR is ready for review.