feat(providers): add aimlapi.com as an OpenAI-compatible gateway provider - #1
Open
Lookoff-AIMLAPI wants to merge 3 commits into
Open
feat(providers): add aimlapi.com as an OpenAI-compatible gateway provider#1Lookoff-AIMLAPI wants to merge 3 commits into
Lookoff-AIMLAPI wants to merge 3 commits into
Conversation
…ider Users who hold an aimlapi.com key currently have to fall back to a named custom provider: they must know the base URL, and they lose preset detection, the `nanobot status` label and the Settings model catalog. A registry entry buys all of that for the same twelve lines the other gateways cost. Model IDs are sent unchanged so the catalog's `vendor/model` form keeps working, and reasoning is the plain top-level `reasoning_effort` rather than OpenRouter's nested request shape, because the endpoint is OpenAI-compatible. The default headers identify nanobot to the gateway the same way the existing OpenRouter attribution block does. They live on this provider's spec, so they cannot ride a request to any other provider, and the factory builds a fresh dict per provider with user-supplied `extraHeaders` taking precedence. A malformed partner id is dropped silently upstream rather than rejected, so its shape is asserted in a test instead of being discovered in production.
Moves the aimlapi.com entry to the head of the gateway block in the registry and to the head of the gateway rows in both docs lists. The registry tuple's order is match priority, so this also makes aimlapi.com win gateway fallback ahead of the other gateways. This is placement, not function: nothing here is needed for the provider to work, and docs/providers.md states that the docs do not rank providers. It is kept as its own commit so it can be dropped before the change is offered upstream. The repository has no "recommended" or "featured" provider badge, and none was invented.
The placeholder part_hkudsnanobot was a readable stand-in chosen before the partner was registered. Registration mints the id server-side, so the real value is part_TcTxHfamJ2kkNiFsYzEVELTy. A wrong or unknown partner id is accepted with a 200 and silently not attributed, so this would not have surfaced at runtime.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Adds aimlapi.com as a built-in OpenAI-compatible gateway provider, following the
two-step recipe in
nanobot/providers/registry.py's own module docstring and theshape of the merged Eden AI provider (upstream HKUDS#4861).
providers.aimlapiwithAIMLAPI_API_KEYand the default base URLhttps://api.aimlapi.com/v1.vendor/modelform(
strip_model_prefix=False); the full ID is sent upstream.reasoning_effortas the normal top-level Chat Completions parameter,not OpenRouter's nested
{"reasoning": {"effort": ...}}shape.(brand logo, icon, and deferred model search — the catalog is ~900 entries, so
it belongs in
DEFERRED_MODEL_LIST_PROVIDERSalongside OpenRouter and AiHubMix).docs/providers.mdanddocs/configuration.md.The display label is
aimlapi.com; the machine identifier isaimlapi.Attribution headers
ProviderSpec.default_extra_headersalready exists and is already used(
kimi_codingships aUser-Agentthrough it), andopenai_compat_provider.pyalready sendsHTTP-Referer/X-OpenRouter-Titleidentifying nanobot to OpenRouter. This reuses that machinery rather than adding
any:
HTTP-RefererandX-Titlename nanobot, not the gateway — they identify thecalling application, which is the OpenRouter convention the repo already follows.
The headers hang off this provider's spec, so they cannot ride a request to any
other provider;
factory._provider_extra_headersbuilds a fresh dict per providerand lets a user's
providers.aimlapi.extraHeaderswin on a key clash, so theregistry constant is never mutated and user configuration is never dropped. A
malformed partner ID is dropped silently by the gateway rather than rejected, so
its shape is asserted in a test.
Commits
Two commits, deliberately separable:
feat(providers): add aimlapi.com as an OpenAI-compatible gateway provider—the provider itself.
chore(aimlapi): fork-only placement — do not send upstream— moves the entryto the head of the gateway block in the registry and to the head of the gateway
rows in both docs lists. This is placement, not function, and
docs/providers.mdsays in its own words that "The docs show concrete providernames so the JSON is copyable, not because nanobot ranks providers." Drop this
commit before offering the change upstream. The repository has no
"recommended"/"featured" provider badge and none was invented.
Verification
Python suite, same machine, same virtualenv,
-p no:randomly:main, d81aa5a)The one failure is identical on both:
tests/cli/test_tui_launcher.py::test_launcher_keeps_the_tui_alive_while_an_existing_gateway_recovers—
TypeError: 'FakeProcess' object does not support the context manager protocol,a local Python 3.13
subprocess.runincompatibility unrelated to this change.ruff check nanobot/— clean.uv run --no-sync basedpyright(afterinstall_channel_dependencies --all-channels)— 0 errors, 0 warnings, 0 notes.
webui:bun run test— 73 files / 1125 tests pass, identical to baseline;bun run buildsucceeds;uv build --wheelsucceeds.(The WebUI suite needs
NODE_OPTIONS=--localstorage-file=...on Node 26 to runat all — without it all 73 files fail in
src/tests/setup.tson bothmainandthis branch.)
Live inference
One real call through the added code path —
load_provider_snapshot()over theexact
config.jsonprinted indocs/providers.md, no mocks:Tool calling round-trips correctly. The WebUI catalog path
(
provider_models_payload) was also run live against the real endpoint:status available,catalog_kind catalog, 785 distinct model IDs.Model IDs
Every ID that appears in the docs was checked against the live catalog at
https://api.aimlapi.com/v1/models, against bothidandaliases, andrestricted to
type == "openai/chat-completions":openai/gpt-5,anthropic/claude-sonnet-4-6,google/gemini-3.1-pro-preview— all present and routable.
Not verified
reproduction of the documented CI commands.
change covers chat completions only, as the Eden AI provider does.