Repository navigation
Conversation
The AI/ML gateway does not serve the legacy /v1/completions endpoint (it answers 404), so the built-in provider should not advertise it. Declare only the chat completions path, matching the other built-in providers that are chat-only (NVIDIA NIM, Mistral, Google, xAI). No preset routes AI/ML requests to the completion endpoint today, so this does not change request behavior; it keeps the registry accurate.
Send X-AIMLAPI-Source and X-AIMLAPI-Partner-ID on requests whose hostname is exactly api.aimlapi.com, next to the existing OpenRouter app attribution. This covers the built-in AI/ML provider and custom providers pointed at the same host. Requests to any other host get no AI/ML headers, including proxies copied from the AI/ML provider, look-alike hosts, subdomains, and URLs that only mention the host in their path.
The provider group and the provider registry call this provider "AI/ML", but its model entries were labelled "AIML (...)". Use the same "AI/ML (...)" prefix for the model entries so the picker shows one consistent provider name. Only display labels change; model keys and model IDs are unchanged.
Bring the AI/ML presets in line with the current gateway catalog (https://api.aimlapi.com/v1/models, checked 2026-10-27). Every preset value is now a model ID listed with an openai/chat-completions entry. Add current models from the main vendors on the gateway: - OpenAI: GPT-6.1 Sol, GPT-6 Astra, GPT-6 Luna - Anthropic: Claude Fable 5.1, Opus 5.5, Sonnet 5.5, Haiku 5.5 - Google: Gemini 4 Argon, Gemini 3.8 Flash - Moonshot: Kimi K3 Fix presets whose IDs are no longer listed as models: - Kimi K2.5 now uses moonshotai/kimi-k2.5; moonshot/kimi-k2-5 is gone from the catalog. - Gemini 3.1 Pro now uses google/gemini-3.1-pro-preview instead of the alias google/gemini-3-1-pro-preview. - Claude Sonnet 4.6 now uses anthropic/claude-sonnet-4.6 instead of the dated alias. Its key becomes aiml_claude_sonnet_4_6, and the old dated key is added to the legacy model key migrations so saved selections, modes and sessions move to the same model. Existing presets that are still listed are kept, so no saved selection is moved to a different model.
AI/ML had built-in presets but none in the default API modes, so users had to enable it by hand before it appeared in the model picker. Add AI/ML (GPT-6.1 Sol) next to the other aggregator defaults, the same way OpenRouter and NVIDIA NIM are exposed. The mode still needs an AI/ML API key before it sends any request.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Model catalog and key canonicalization src/config/index.mjs, src/config/model-key-migrations.mjs, tests/unit/config/* |
The catalog adds models, updates provider IDs and descriptions, and sets GPT-6.1 Sol as the AI/ML default. Dated Claude Sonnet keys migrate to the undated key. Tests cover the catalog predicates and user-config migration. |
Chat routing and request attribution src/services/apis/provider-registry.mjs, src/services/apis/openai-api.mjs, tests/unit/services/apis/* |
The AI/ML provider no longer configures a completions path, and its chat endpoint resolution remains covered. OpenAI-compatible requests to api.aimlapi.com receive AI/ML attribution headers; tests cover built-in and custom providers and hostname exclusions. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Feature
Sequence Diagram(s)
sequenceDiagram
participant OpenAICompatibleAPI as OpenAI-compatible API service
participant AttributionLookup as AI/ML attribution lookup
participant AIMLAPI as AI/ML API
OpenAICompatibleAPI->>AttributionLookup: Provide request hostname
AttributionLookup-->>OpenAICompatibleAPI: Return matching attribution headers
OpenAICompatibleAPI->>AIMLAPI: Send request with attribution headers
Suggested reviewers: peterdavehello
Merge Risk: 
Minimal · up to 09c50
-
No merge-blocking issue was established. Run the normal checks before merging.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 5 functions across 7 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches
-
🧪 Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Warning
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 @coderabbitai help to get the list of available commands.
PR Summary by QodoRefresh AI/ML presets and attribute direct API usage
AI Description
Diagram
High-Level Assessment
Files changed (8)
|
Code Review by Qodo
1. Redirected requests tag other hosts
|
|
|
||
| function getAimlAttributionHeaders(requestUrl) { | ||
| try { | ||
| if (new URL(requestUrl).hostname !== AIML_API_HOSTNAME) return {} |
There was a problem hiding this comment.
1. Redirected requests tag other hosts 🐞 Bug ≡ Correctness
getAimlAttributionHeaders checks only the initial request URL, while fetchSSE follows redirects without rechecking the destination or removing the attribution headers. If an AI/ML endpoint redirects to another hostname, the redirected request can carry both headers to a host that the exact-hostname check would otherwise exclude.
Agent Prompt
## Issue description
AI/ML attribution is scoped to the initial request URL, but automatically followed redirects can carry its headers to another host.
## Fix Focus Areas
- src/services/apis/openai-api.mjs[123-136]
- src/services/apis/openai-compatible-core.mjs[125-130]
- src/utils/fetch-sse.mjs[65-69]
## Recommended Fix
For requests carrying AI/ML attribution, either reject redirects or revalidate each destination and remove both attribution headers when the hostname differs. Preserve redirect behavior for unrelated providers and add a redirect regression test.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
[Medium impact] The PR appears safe to merge; no actionable defects were found. SummaryRefreshes AI/ML presets, adds one default AI/ML option, and migrates the dated Sonnet preset key.
No actionable issues were found. This review checked code paths; it did not run tests, builds, or live API requests.
Reviews (1) · Last reviewed commit: "Add an AI/ML preset to the default API m..." · Reviewed by Greptile |
There was a problem hiding this comment.
2 issues found across 8 files
Confidence score: 3/5
src/config/index.mjsuses an unlisted model ID, so Kimi K3 requests may fail validation. Switch to a supported Kimi K3 ID and update the label if the selected variant is K3.1 Pro.src/services/apis/openai-api.mjsfollows redirects by default, which can forward AI/ML attribution headers to another origin. Reject redirects for these requests or strip the headers before following a cross-origin redirect.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/config/index.mjs">
<violation number="1" location="src/config/index.mjs:745">
P2: This preset uses an unlisted AI/ML model ID, so Kimi K3 requests can fail model validation. Use a supported Kimi K3 ID, and update the label if the selected variant is K3.1 Pro.</violation>
</file>
<file name="src/services/apis/openai-api.mjs">
<violation number="1" location="src/services/apis/openai-api.mjs:125">
P2: Reject redirects for requests carrying AI/ML attribution, or remove these headers before following a cross-origin redirect. `fetch` follows redirects by default, so an AI/ML endpoint can otherwise forward both headers to another host.</violation>
</file>
Reply to a comment to ask cubic a question or push back. It learns from your replies.
View guided diff | Re-trigger cubic
| desc: 'AI/ML (Gemini 2.5 Flash)', | ||
| }, | ||
| aiml_moonshot_kimi_k3: { | ||
| value: 'moonshot/kimi-k3', |
There was a problem hiding this comment.
P2: This preset uses an unlisted AI/ML model ID, so Kimi K3 requests can fail model validation. Use a supported Kimi K3 ID, and update the label if the selected variant is K3.1 Pro.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/config/index.mjs, line 745:
<comment>This preset uses an unlisted AI/ML model ID, so Kimi K3 requests can fail model validation. Use a supported Kimi K3 ID, and update the label if the selected variant is K3.1 Pro.</comment>
<file context>
@@ -643,69 +653,109 @@ export const Models = {
+ desc: 'AI/ML (Gemini 2.5 Flash)',
+ },
+ aiml_moonshot_kimi_k3: {
+ value: 'moonshot/kimi-k3',
+ desc: 'AI/ML (Kimi K3)',
},
</file context>
|
|
||
| function getAimlAttributionHeaders(requestUrl) { | ||
| try { | ||
| if (new URL(requestUrl).hostname !== AIML_API_HOSTNAME) return {} |
There was a problem hiding this comment.
P2: Reject redirects for requests carrying AI/ML attribution, or remove these headers before following a cross-origin redirect. fetch follows redirects by default, so an AI/ML endpoint can otherwise forward both headers to another host.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At src/services/apis/openai-api.mjs, line 125:
<comment>Reject redirects for requests carrying AI/ML attribution, or remove these headers before following a cross-origin redirect. `fetch` follows redirects by default, so an AI/ML endpoint can otherwise forward both headers to another host.</comment>
<file context>
@@ -115,6 +120,22 @@ function getOpenRouterAttributionHeaders(requestUrl) {
+function getAimlAttributionHeaders(requestUrl) {
+ try {
+ if (new URL(requestUrl).hostname !== AIML_API_HOSTNAME) return {}
+ } catch {
+ return {}
</file context>
There was a problem hiding this comment.
ℹ️ No correctness issues — two design notes for the maintainer before merge.
Reviewed changes
- AI/ML preset refresh — adds GPT-6.1 Sol / GPT-6 Astra / GPT-6 Luna, Claude Fable 5.1 / Opus 5.5 / Sonnet 5.5 / Haiku 5.5, Gemini 4 Argon / 3.8 Flash, and Kimi K3; corrects the Gemini 3.1 Pro and Kimi K2.5 model IDs; renames the dated Claude Sonnet 4.6 preset with a migration; and standardises the
AI/MLlabel. Every new and renamed ID is present in the liveapi.aimlapi.comcatalog and exposesopenai/chat-completions, so each resolves through the extension's chat-completions path. - Usage attribution — adds
X-AIMLAPI-Source/X-AIMLAPI-Partner-ID, gated onnew URL(requestUrl).hostname === 'api.aimlapi.com'and composed alongside the existing OpenRouter headers. - Provider registry — drops the unused
completionsPathfrom the built-in AI/ML provider;endpointTypeforaimlModelKeysis alwayschat, so the removal is safe. - Tests — attribution scoping (look-alike/subdomain/parent-domain/path hosts, other built-ins, direct custom providers), endpoint resolution, model defaults/labels, and saved-config migration.
ℹ️ A hardcoded vendor partner identifier now ships in every AI/ML request
AIML_ATTRIBUTION_HEADERS embeds X-AIMLAPI-Partner-ID: part_suAsqzeIpC2a5yS8K1leCNtf and X-AIMLAPI-Source: agent/chatgptbox directly in the extension source. The scoping is correct — no header leaves the api.aimlapi.com host — but the value is vendor-controlled and becomes part of every shipped build, which is a maintainer decision rather than an incidental merge.
Technical details
# Hardcoded partner attribution in shipped extension
## Affected sites
- `src/services/apis/openai-api.mjs:47` — `AIML_ATTRIBUTION_HEADERS` constant (partner id + source tag)
- `src/services/apis/openai-api.mjs:132` — `getAppAttributionHeaders` merges it into every OpenAI-compatible request
## Required outcome
- Maintainers consciously accept shipping the fixed partner identifier, or move it to config.
## Open questions for the human
- Is `part_suAsqzeIpC2a5yS8K1leCNtf` intended to be stable/public, and does `agent/chatgptbox` match the agreed partner-program contract?ℹ️ The new default mode is auto-materialised for existing users
Appending aiml_openai_gpt_6_1_sol to defaultApiModeIds does more than surface it in the picker: reconcileMaterializedApiModeDefaults adds it to every existing user's customApiModes on next load, and the migration is additive-only, so removing it later would not clean it up for upgraders. Flagging so this product choice is made knowingly rather than as a side effect.
Technical details
# Default-mode materialization is one-way
## Affected sites
- `src/config/index.mjs:849` — `'aiml_openai_gpt_6_1_sol'` added to `defaultApiModeIds`
- `src/utils/model-name-convert.mjs:273` — `reconcileMaterializedApiModeDefaults` (appends unseen defaults, never prunes)
## Required outcome
- Confirm promoting a third-party provider to the default tier for all existing users is intended.
## Open questions for the human
- Should the preset be picker-visible but opt-in (i.e. omitted from `defaultApiModeIds`)?deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| }, | ||
| aiml_openai_gpt_6_1_sol: { | ||
| value: 'openai/gpt-6.1-sol', | ||
| desc: 'AI/ML (GPT-6.1 Sol)', |
There was a problem hiding this comment.
Register the new AI/ML labels in the English locale
When these new model descriptions are rendered, modelNameToDesc passes them through i18next, but src/_locales/en/main.json contains none of the new or renamed AI/ML (...) keys, so they bypass the English source of truth and cannot participate in the normal localization fallback/translation workflow. Add all labels introduced in this block to the English locale; the root AGENTS.md explicitly requires new source strings there before other locale work.
AGENTS.md reference: AGENTS.md:L211-L213
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
🔵 Needs a closer look
The updated model IDs, attribution headers, and default preset need an authenticated extension smoke test, since mocked fetch coverage cannot establish live provider acceptance or browser behavior.
No open issues 🎉
What changed in this PR
This PR refreshes ChatGPTBox’s existing AI/ML integration and adds hostname-scoped usage attribution for requests sent directly to AI/ML.
Changes:
- Expands model presets, standardizes AI/ML labels, and adds GPT-6.1 Sol to the default API modes.
- Migrates saved Claude Sonnet 4.6 selections to the canonical preset and removes the legacy completions endpoint declaration.
- Adds attribution headers and regression coverage for hostname scoping, configuration migration, defaults, and endpoint resolution.
| File | Description |
|---|---|
tests/unit/services/apis/provider-registry.test.mjs |
Verifies AI/ML’s chat endpoint configuration and resolution. |
tests/unit/services/apis/aiml-attribution.test.mjs |
Covers direct-request attribution, excluded hosts, and preserved OpenRouter attribution. |
tests/unit/config/migrate-user-config.test.mjs |
Checks migration of saved Sonnet 4.6 selections and API modes. |
tests/unit/config/config-predicates.test.mjs |
Checks AI/ML defaults, labels, and legacy-key recognition. |
src/services/apis/provider-registry.mjs |
Removes AI/ML’s legacy completions endpoint declaration. |
src/services/apis/openai-api.mjs |
Adds attribution headers scoped to api.aimlapi.com. |
src/config/model-key-migrations.mjs |
Maps dated Sonnet keys to the canonical preset. |
src/config/index.mjs |
Refreshes AI/ML presets, model IDs, labels, and default-mode availability. |
Review effort: Balanced

Hi! I'm Vito from aimlapi.com — an AI aggregator that gives access to 1000+ models in one API, trusted by 400k+ users.
We've been discussing the existing AI/ML API integration with @PeterDaveHello on X, including how much usage comes from chatGPTBox. Thanks for adding support for us independently! Since that integration was built without our involvement and doesn't include attribution, we currently can't identify usage originating from chatGPTBox or report those numbers back to you.
This PR builds on your existing integration by adding usage attribution, refreshing the model presets, and making an AI/ML option available among the default API modes. Attribution will let us measure the traffic chatGPTBox generates and provide the basis for a revenue-generating partnership.
aimlapi.com now operates with zero markup. Through our partner program, you can set your own markup on usage coming from this integration and earn revenue from it. We'd like to work with you on connecting the existing integration to that program.
My contacts: vito.b@aimlapi.com (email / Slack), Telegram: @vito_bush
Why
chatGPTBox already supports AI/ML API through an integration your team implemented independently. Following our conversation with @PeterDaveHello on X about usage from chatGPTBox, this PR adds attribution so we can measure that usage and report it back to you.
It also refreshes the model presets, exposes one AI/ML preset among the default API modes, and removes the legacy completions endpoint declaration.
Changes
AI/MLlabel consistently.AI/ML (GPT-6.1 Sol)to the default API modes. Using it still requires the user's AI/ML API key.X-AIMLAPI-Source: agent/chatgptboxandX-AIMLAPI-Partner-IDattribution headers only when the request hostname is exactlyapi.aimlapi.com. This covers built-in and direct custom-provider requests; proxies, look-alike hosts, and other providers receive no AI/ML attribution headers. Existing OpenRouter attribution is preserved.completionsPathfrom the built-in AI/ML provider and add regression coverage for endpoint resolution, model defaults/labels, saved-config migration, and attribution scoping.Validation
Reviewed all 8 changed files in the GitHub comparison. GitHub reports that the branches can be merged automatically. No GitHub Actions runs were found for
feat/aiml-refreshat the time of review. Tests, builds, and live API requests were not run during this browser review.To validate locally with Node.js 22 or later:
npm ci npm test npm run lint npm run pretty:check npm run buildFor a manual smoke test, load the built extension, configure an AI/ML API key, select an AI/ML preset, and send a chat message. Also check that an existing configuration using the dated Claude Sonnet 4.6 preset migrates to the canonical preset.
Notes
The attribution headers identify chatGPTBox as the source of requests; they do not add individual user identifiers. They provide the basis for measuring integration usage and attributing partner revenue. Partner-program setup and commercial terms can be coordinated separately.
Summary by CodeRabbit