50/50 RevShare Integration: OpenFang & AIML API - #1292
Open
hugoaimlapi wants to merge 2 commits into
Open
hugoaimlapi wants to merge 2 commits into
hugoaimlapi wants to merge 2 commits into
Conversation
OpenFang already routes every OpenAI-compatible vendor through the shared driver tables, so a gateway needs a base-URL constant, a provider-defaults arm, a ProviderInfo row and a handful of catalog rows rather than a new driver file. This follows the Requesty (issue RightNow-AI#995) and Novita wiring exactly so there is one shape to maintain, not two. The five catalog rows are gateway-priced rather than upstream-priced: the same model costs a different amount through a router than direct, and letting `aimlapi/anthropic/claude-sonnet-4.6` fall through to the generic `contains("sonnet")` arm would silently bill it at Anthropic's own rate. The metering fallback carries matching arms scoped to the `aimlapi/` prefix, with a test that fails if those rates ever drift from the catalog. Attribution headers are keyed on the request *origin*, not on the configured provider name. A user can point any provider at any base_url, and partner headers must never ride a request to a different vendor or to a third-party proxy that merely fronts the same API. `with_extra_headers` now appends instead of assigning, so attribution cannot silently discard headers an earlier caller configured (Copilot's IDE auth is the existing caller). The partner id shape is asserted in a unit test because a malformed id is accepted by the gateway and then ignored — it fails silently, earning nothing, with no runtime error to notice.
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.
Hi! I'm Hugo from aimlapi.com — an AI aggregator that gives access to 1000+ models in one API, trusted by 400k+ users.
We'd love to be available as a verified provider option inside OpenFang — so we went ahead and did all the technical work on our side, in our fork: https://github.com/aimlapi/openfang-aimlapi
To build our partnership, we offer a 50/50 revenue share on all traffic from this integration.
My contacts: hugo@aimlapi.com (email / Slack), Telegram: @hug0the
Summary
Adds aimlapi.com as a built-in OpenAI-compatible provider (
provider = "aimlapi", key inAIMLAPI_API_KEY, base URLhttps://api.aimlapi.com/v1). It follows the Requesty pattern: a base-URL constant, aprovider_defaultsarm, aProviderInforow and catalog rows. No new driver.Requests to
api.aimlapi.comcarry four attribution headers. They identify traffic from OpenFang to aimlapi.com; the partner ID is what the revenue share is counted on.Changes
openfang-types:AIMLAPI_BASE_URL = "https://api.aimlapi.com/v1".drivers/mod.rs:provider_defaults("aimlapi"):AIMLAPI_API_KEY, key required. UsesOpenAIDriver;base_urlin config still overrides the default.aimlapi_attribution_headers(base_url): headers only when the parsed URL host isapi.aimlapi.com(case-insensitive), otherwise nothing. Headers:HTTP-Referer: https://github.com/RightNow-AI/openfang,X-Title: OpenFang,X-AIMLAPI-Source: agent/openfang,X-AIMLAPI-Partner-ID: part_Z6HbToJ3l2ht1dFSzHC98vk6.create_driver(known provider, and custom provider withbase_url) pass these headers to the driver. The check is on the resolved URL, not the provider name: a custom provider pointed atapi.aimlapi.comgets them; other hosts, look-alike hosts and proxies never do. There's no setting to turn them off. No key, prompt or user data in them.drivers/openai.rs:with_extra_headersappends instead of replacing, so a second call can't drop headers set earlier. The only other caller (copilot.rs) calls it once on a new driver, so its behaviour is unchanged.model_catalog.rs:aimlapiprovider row and 5 models at the gateway's prices:aimlapi/anthropic/claude-sonnet-4.6,aimlapi/openai/gpt-5-5,aimlapi/google/gemini-2.5-flash,aimlapi/alibaba/qwen-max,aimlapi/meta-llama/Llama-3.3-70B-Instruct-Turbo.strip_provider_prefixsends<vendor>/<model>on the wire.metering.rs:estimate_costrates for those 5 ids, matched only under theaimlapi/prefix. Without themaimlapi/anthropic/claude-sonnet-4.6would be priced at Anthropic's direct rate throughcontains("sonnet").openfang init: aimlapi.com entry after OpenRouter, default modelaimlapi/google/gemini-2.5-flash.aimlapigrouped under "Aggregators & Gateways"..env.example:# AIMLAPI_API_KEY=....Testing
cargo clippy --workspace --all-targets -- -D warningspassescargo test --workspacepassesNew tests:
drivers/mod.rs: provider defaults, partner id format (^part_[A-Za-z0-9]{1,64}$), headers forapi.aimlapi.com, none for OpenRouter/OpenAI/proxy/look-alike/invalid URLs, headers for a custom provider onapi.aimlapi.com, missing-key error.drivers/openai.rs:with_extra_headersmerges; unset optional request fields are omitted, not sent asnull.model_catalog.rs: provider row and models present, every aimlapi id isaimlapi/-prefixed. Provider count 42 → 43.metering.rs: fallback rates equal catalog rates and don't apply to bare<vendor>/<model>ids.rustfmt --checkon the touched.rsfiles: no diff. All 5 model ids are in the live catalog.Security
base_urlis parsed withreqwest::Url::parsebefore the host check, an unparsable URL gets no headers)