feat(ai-providers): add aimlapi.com as a first-class AI provider - #1
Open
Lookoff-AIMLAPI wants to merge 2 commits into
Open
feat(ai-providers): add aimlapi.com as a first-class AI provider#1Lookoff-AIMLAPI wants to merge 2 commits into
Lookoff-AIMLAPI wants to merge 2 commits into
Conversation
added 2 commits
September 3, 2026 16:12
Admins can already reach AI/ML API through Other (OpenAI Compatible), so this buys discoverability and a correct model list rather than new capability: the catalog mixes 936 entries across chat, image, video, speech, embedding and batch surfaces, and only the 353 chat models belong in a text-model dropdown. It gets its own strategy file instead of an openAiCompatibleVendor entry because that factory validates a key by listing models, and api.aimlapi.com/v1/models is a public catalog that answers 200 with no Authorization header and 200 to a bogus bearer. Every typo would have saved as a working key and surfaced later as a broken model rather than a bad credential. GET /v1/key answers 401 for a missing, empty or wrong key, which is the same shape openRouterProvider already relies on for /auth/key, so the check is a real one without changing how the six existing vendors validate. Attribution rides only on requests to our own base URL, built fresh per request from a frozen constant so a caller's own headers still win and the constant cannot be mutated across providers. The partner id is silently ignored by the gateway when malformed, so its shape is asserted in a test rather than left to review. Both language-model switches are updated - the server factory and the piece's own copy - since a provider missing from the piece one connects, validates and lists models, then dies at step run time.
Placement and featuring are a partnership decision, not a technical one, so they are isolated here: dropping this commit leaves the provider fully working and positioned like any other vendor. SUPPORTED_AI_PROVIDERS is a hand-ordered literal with no sort at any call site, so the dropdown, the admin cards and the model picker all read it in file order. RECOMMENDED_PROVIDERS and recommendedTagline are the repo's existing featured-card mechanism, used today for Anthropic and OpenAI; nothing new was invented for this.
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.
Description
Adds
aimlapi.comas a first-class AI provider, alongside the six OpenAI-compatiblevendors added in activepieces#14987 and Vertex in activepieces#15139.
Admins can already reach AI/ML API today through Other (OpenAI Compatible) with a
custom base URL, so this buys discoverability, branding, a correct model list and
attribution — not new capability. Framed that way deliberately.
Why its own strategy file rather than
openAiCompatibleVendoropenai-compatible-vendor.ts:12-14validates a key by listing models:https://api.aimlapi.com/v1/modelsis a public catalog. Probed 2026-09-03:GET /v1/modelsnoAuthorizationheader200GET /v1/modelsBearer sk-definitely-not-a-real-key-000200GET /v1/modelsreal key200So through that factory any string would have saved as a working key, and the first
real failure would have surfaced at run time as "the model is broken" rather than
"your key is wrong" — made worse by the fact that
validateProviderCredentialsonlysurfaces the upstream message for Cloudflare Gateway.
aimlapi-provider.tsvalidates againstGET /v1/keyinstead, which answers200with key metadata for a live key and
401for a missing, empty or wrong one. That isthe same shape
openRouterProvideralready relies on for/auth/key, so no change wasmade to how the six existing vendors validate — that is their call to make, not this
PR's.
listModelsalso filters ontype === "openai/chat-completions". The catalog returns936 entries across 15 endpoint types (chat, image generation, video, TTS, STT,
embeddings, batches, OCR…). The generic factory maps every row to
AIProviderModelType.TEXT, which would have offered 218 video models and 132 imagemodels in a text dropdown. Filtered, the provider lists 353 chat models.
Attribution
Four headers on requests to our base URL only:
HTTP-Referer/X-Titlefollow the OpenRouter convention and identify Activepieces,the calling app — not the gateway. They are built fresh per request by spreading a frozen
constant, so a caller's own
extraHeaders/metadataHeadersstill win a key clash andthe constant cannot be mutated by one provider and read by another. A malformed partner id
is ignored silently by the gateway rather than rejected, so its shape is asserted in a test
rather than left to review.
Model ids and the API surface
there is no model list to rot.
.chatModel()is used, which posts to/v1/chat/completions. This matters:POST /v1/responsesexists on that API but serves only 50 of the 353 chat models, andPOST /v1/completionsdoes not exist at all. Verified on the wire — see below.null. Several models therereject
nullontemperature/top_p/seed/tools/response_formatwith a 400while others accept it, so a body carrying
"tools": nullbetween agent turns would 400on turn 2 with a green test suite. Verified on the wire — no key was sent as
null.How was this tested?
Bun 1.3.14,
bun install --frozen-lockfile --ignore-scripts(theisolated-vmnative buildfails against Node 26 on this machine; unrelated to this change and it affects only the
sandbox package).
Unit tests — baseline on a pristine checkout vs. after, same command,
--continueso onefailure does not abort the rest:
@activepieces/ai-providers@activepieces/shared@activepieces/sandbox@activepieces/server-utils@activepieces/core-execution@activepieces/core-utils@activepieces/pieces-frameworkee-embed-sdkworker@activepieces/enginewebThe 26 failures are identical on a clean tree: engine's
props-validator/timezone-dependent cases, and
web'stest/app/builder/shortcuts.test.tsx(
Cannot read properties of undefined (reading 'getItem')). Neither touches AI providers.The +6 in
@activepieces/ai-providersis 5 new assertions plus one extra case of theexisting
it.each(supportedProviders)now that the enum has another member.npx turbo run build --filter=api --filter=web --filter=@activepieces/piece-ai --filter=@activepieces/ai-providers— 19/19, exit 0, before and after.npm run lint-core— exit 0, 23/23 tasks, 0 errors and warning counts byte-identical tothe baseline in every package (api 490, web 72, engine 33, worker 29, shared 7, embed-sdk 6).
One real inference call through the code this PR adds, not a mock and not a raw curl —
aimlapiProviderandcreateLanguageModelimported from source and driven with a real keypassed through the environment:
The piece-side switch was exercised separately, because a provider missing from
buildLanguageModelinpackages/pieces/community/ai/.../ai-sdk.tsconnects, validates andlists models and then dies at step run time on
default:.createAIModelwas called againsta local stub of
GET /v1/ai-providers/aimlapi/configand the model then run for real:Attribution and the existing
x-ap-*metadata coexist on that path, with the metadatawinning any clash.
Edition paths
Not exercised. The provider is edition-agnostic — it adds an enum member, a strategy, two
switch cases and a UI row, with no
ee/import, no feature flag, no migration and no entity —but CE / EE / Cloud were not each brought up, so that is stated rather than claimed.
Not verified
https://cdn.activepieces.com/pieces/aimlapi.pngreturns404today(
moonshot-ai.pngreturns200). Per the repo's own note that a provider logo is an assetsomeone has to upload rather than something the code ships, the URL follows the convention
every other provider uses and needs the asset uploaded before merge, or the platform admin
list renders a broken-image icon. Nothing in CI catches this.
MODELS_DEV_PROVIDERintools/scripts/sync-model-catalog.tswasdeliberately left alone: models.dev publishes no
aimlapiprovider (checked againsthttps://models.dev/api.json), so there is no upstream id to map. Likecloudflare-gatewayand
custom, this provider legitimately has no source, and its models will show withoutcontext window or price until models.dev carries it.
GET /v1/keyreturns adisabledfield, so a key that is validbut switched off may still answer
200. That case could not be produced, so validation isleft on the HTTP status alone rather than shipping an untested branch.
NO_IMAGE_GENERATION_PROVIDERS), matching the six existingOpenAI-compatible vendors. That API does serve image models; wiring them is a separate change
with its own verification, not a claim smuggled into this one.
Two things worth knowing if you meter or cap on this provider
completion_tokensexcludes reasoning tokens on some models there (a Gemini 2.5 Flashcall reports prompt 12 + completion 3, total 86, with 71 reasoning). Anything metering spend
from
completion_tokenswill under-report.max_tokensdoes not reliably bound reasoning tokens: some models return several timesthe cap with
finish_reason: "stop", giving no signal at all, while others cap correctly andreport
length.Neither is introduced here, and neither is acted on here — flagged because the AI-credits
surfaces read those numbers.
Fixes # (issue)
Breaking change? (required — CI fails if this is left unedited)
Additive only: one new
AIProviderNamemember, one new member of the discriminatedProviderConfigUnion, and a new row in the provider list. No existing id is renamed, noschema is removed, and the untagged
AIProviderConfig/AIProviderAuthConfigunions areuntouched — the provider reuses the existing empty
OpenAiCompatibleVendorConfigandBaseAIProviderAuthConfigmembers, so the "order matters" hazard in those unions does notapply.
Security impact? (required — CI fails if this is left unedited)
Touches outbound HTTP and credential validation, so flagged rather than waved through:
safeHttp.axios, per.claude/rules/safe-http.md. The URLis a hardcoded constant with no admin-supplied component, so there is no SSRF surface to open —
and deliberately no
baseUrlconfig field, consistent with decision 000031.api.aimlapi.com, and the attribution headers are scoped tothe same origin so they cannot ride a request to another provider or a proxy fronting it.
connect time instead of being stored as valid.
can clobber it.
Second commit is fork-only
chore(aimlapi): fork-only placement — do not send upstreamis separated on purpose. Itcontains only placement and featuring — first in
SUPPORTED_AI_PROVIDERS, added to theexisting
RECOMMENDED_PROVIDERSwith a tagline, and first under Gateways in the adminguide. That is a partnership decision, not a technical one. Drop that commit and the provider
still works and still sits with the other vendors.
For the record on ordering:
SUPPORTED_AI_PROVIDERSis a hand-ordered literal with no sort atany call site, and the entry is placed last among concrete providers in the first commit — even
though alphabetical order by enum key would also have put
aimlapifirst — so that thenon-promotional position is unambiguous.