feat: add aimlapi.com provider#1
Draft
ngrink wants to merge 19 commits into
Draft
Conversation
…in-v7.4.11 chore(jetbrains): bump CLI pin to v7.4.11
- inject aimlapi provider into the models.dev overlay (openai-compatible, AIMLAPI_API_KEY, dynamic model list from GET /models filtered to chat models; coding-tagged models carry recommendedIndex) - ModelCache: aimlapi fetcher with config/auth/env resolution (AIMLAPI_API_KEY, AIMLAPI_INFERENCE_URL overrides) - provider picker: aimlapi.com in Popular right after Kilo Gateway with "(1000+ models, one-click setup)" - settings metadata + en i18n note; changeset Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Selecting aimlapi.com now opens a guided setup instead of the generic API-key prompt: - paste an existing key (validated with a live balance probe), or - sign in by email: existing accounts get a 6-digit code and an auto-issued key; new accounts register passwordless, top up via the hosted checkout (browser + fallback link, session polling, idempotent retry) and receive their key automatically - reconfigure screen when the provider is already connected Implementation lives in the kilocode overlay (src/kilocode/aimlapi/): config with prod defaults + AIMLAPI_*_URL env overrides, HTTP client, UI-agnostic flow state machine (unit-tested), SolidJS TUI screens; wired through the existing KiloProvider.selectProvider hook. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Local dev tooling rewrote dependency lists unrelated to the aimlapi change; restore both files to the upstream state. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Provider.list drops catalog providers whose model list is empty, so requiring a key for the models fetch hid aimlapi.com from the connect picker for unauthenticated users. GET /models is public; attach the bearer only when a key is present. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The HTTP provider-list handler resolved the core models.dev layer, so overlay-injected providers (kilo catalog, apertis, aimlapi) were missing from the connect picker until connected. Wire the kilocode overlay layer (same service tag, superset catalog) into the server and app runtimes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The dialog inserts replacement components through a tracked render effect that unwraps function roots, so a bare <Switch> root re-created the whole component on every phase change — and the onMount start transition drove that re-creation into unbounded update-loop recursion (frozen TUI, eventual 'Maximum call stack size exceeded'). Wrap the screens in a static <box> root and enter the flow state machine before the first render. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The aimlapi /models endpoint exposes opt-in metadata sections via ?include=…; request capabilities+modalities and map them onto the model: reasoning (unlocks the host-generated reasoning-effort variants), image-input attachment, real input/output modalities, and the true output token limit. tool_call stays enabled across the board — the catalog's tools capability has false negatives that would hide working models. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…artup The public aimlapi catalog was fetched eagerly inside ModelsDev.get(), a hot path that runs at startup, on one-shot runs, and in tests — so every one of those blocked up to 10s on a live api.aimlapi.com request (e.g. tool-task-model timed out in CI). Mirror apertis: fetch eagerly only when the provider is configured (key via env/config/auth). Keyless, read whatever the cache holds and let the connect picker (provider.list) warm the public catalog on demand — that is the one place the pre-connect model list is actually needed, so the provider still appears there without any hot-path phone-home.
… order Adding aimlapi at order index 1 (second, right after kilo) shifts every following provider down one; openai's settings priority is now 4, not 3.
settings.providers.note.aimlapi existed only in en; the locale-completeness test (kilo-vscode i18n-keys) requires every English key in all 19 other locales. Add the translated note to each.
- submitKey: only treat a 401/403 as an invalid key; report network/timeout/ 5xx as transport errors instead of blaming the pasted key (+ test). - Drop the unreached topUpByKey client method (S12 existing-key top-up is not wired yet; re-add it when that path lands). - Use the DEFAULT_AMOUNT_USD_MINOR constant for the credits screen default instead of a hard-coded "25". - Changeset: 1000+ models, matching the picker/i18n copy. - Run prettier 3.6.2 over the touched files.
Models showed as "Free" because the fetcher never requested or mapped the pricing section. Request `?include=...,pricing` and translate `pricing.units` to models-dev cost (USD per 1M tokens): the unit `origin` is the discriminator (provided→input, generated→output, cached→cache_read, cache_write→cache_write), only text token charges count (audio/tool-call units are skipped), the first unit per origin wins, and price is normalized by `per`. Tiered pricing (thresholds/variants) is left to the base rate for now. Validated across the live catalog: 339/341 chat models resolve real prices, 2 are genuinely free.
The model-info panel reads its blurb from `options.description` (Kilo's convention — models.dev catalog entries carry none), which aimlapi models never set, so the panel showed no description. Decode `info.description` from the catalog (already in the default projection) and pass it through as `options.description`. 177/341 chat models carry a description.
Send X-AIMLAPI-Source: agent and X-AIMLAPI-Partner-ID on all traffic to aimlapi.com — inference, catalog, auth and checkout — not just sign-up, so the backend can attribute the traffic and mark agent-sourced accounts. - config: shared aimlapiAttributionHeaders() (source always; partner id when known, overridable via AIMLAPI_PARTNER_ID) - client: onboarding requests carry them via the shared request() - model-cache: catalog fetch carries them, and every model gets model.headers - provider overlay: patchModelsDevModel carries model.headers onto the resolved model so getSDK stamps them on inference calls
Set DefaultPartnerID to the partner provisioned with the same id on both the staging and production backends, so one build attributes correctly against either (only the AIMLAPI_*_URL endpoints differ); AIMLAPI_PARTNER_ID still overrides. Update the client test to assert the compiled-in default flows.
Some image models (openai/gpt-5-image, google/gemini-3.1-flash-image aka Nano Banana 2, etc.) reach /v1/models as type=openai/chat-completions but reject tool use, so a coding agent errors at runtime ("No endpoints found that support tool use"). Filter them out by id in the aimlapi model fetcher (+ unit test). Temporary until the catalog marks these models.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the AIMLAPI_PARTNER_ID env override and the resolvePartnerId indirection — the partner id is fixed for the aimlapi.com provider (same id on both backends), so it is now a plain constant used directly in the attribution headers and checkout. Updates the client/model-cache tests to assert the constant instead of an injected override. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Closes #2
Summary
Adds aimlapi.com as a built-in provider with a guided TUI onboarding flow: the user goes from "no provider" to a funded, working key without leaving Kilo. Reached by picking aimlapi.com from the provider picker (
/connect, orctrl+afrom the model dialog), where it shows in the Popular group with a "1000+ models, one-click setup" tagline.What changed
Provider + model catalog
aimlapiprovider (OpenAI-compatible transport,https://api.aimlapi.com/v1) through the overlay ModelsDev layer.GET /v1/models— the same per-provider fetcher pattern Kilo already uses forkilo/apertisinprovider/model-cache.ts(5-min cache + background refresh), filtered totype=openai/chat-completions.ctrl+t), and attribution headers on every request;playground:code-tagged models rank first in the picker.Guided onboarding (TUI)
A self-contained onboarding sub-flow wired into provider setup. Screens:
/v1/billing/balance).Tab).aimlapiprovider profile.aimlapiis already configured.Config
AIMLAPI_*_URLenv var — no staging URLs baked in.partnerId = "part_NcwZvHtWloCePPggbSypywxq"(rebate/attribution for Kilo Code).(amount, auto-top-up)intent survives retries.Why
Give Kilo users one-key access to a large multi-provider catalog and let them create + fund an account in-tool, following Kilo's existing dynamic-fetch pattern rather than a hardcoded model list.
Design notes
src/kilocode/aimlapi/…); shared OpenCode files carry only narrow registration hooks — small upstream-merge conflict surface.