Skip to content

Replace the Rust provider with a declarative one, and add PKCE sign-in - #2

Merged
Lookoff-AIMLAPI merged 38 commits into
mainfrom
merge/aimlapi-into-fork
Sep 1, 2026
Merged

Replace the Rust provider with a declarative one, and add PKCE sign-in#2
Lookoff-AIMLAPI merged 38 commits into
mainfrom
merge/aimlapi-into-fork

Conversation

@Lookoff-AIMLAPI

Copy link
Copy Markdown
Member

Syncs the fork to current upstream and reworks the AI/ML API integration.

Why the existing provider had to go rather than stay alongside

crates/goose/src/providers/aimlapi.rs (from PR #1) registered the provider name aimlapi. The new declarative definition registers the same name, so the two could not coexist — one of them had to win.

Two things decided which:

  • The old one no longer builds. It is written on super::openai_compatible::OpenAiCompatibleProvider, and upstream has since deleted that module. The fork last synced on 2026-08-27; the breakage arrived with upstream changes after that, so it would have surfaced at the next sync regardless of this work.
  • Declarative is the path the maintainer named. He said a PR with just the declarative enhancement would be accepted; a hand-written Rust provider is a much larger ask for the same result.

Its four model ids had also gone stale (google/gemini-3-7-flash, deepseek/deepseek-v4-pro-0813).

What was worth keeping came across: the X-AIMLAPI-Source and X-AIMLAPI-Partner-ID attribution headers now ride on the definition's headers block. Without them a request serves fine and is silently untagged, which is how partner attribution quietly stops working.

What lands

Piece Notes
definitions/aimlapi.json 8 models with context limits read from the live catalog, not guessed; attribution headers; sorts first in the registry purely alphabetically
config/signup_aimlapi/ authorization-code + PKCE, built on the shape of the existing signup_openrouter
configure.rs an "AI/ML API Login" item, placed after the two existing sign-ins rather than above them
examples/aimlapi_auth.rs runs the flow without the TUI, mirroring their tetrate_auth example

Three deliberate departures from the OpenRouter flow it copies: the state is verified (OpenRouter's does not), the loopback port is 53682 rather than the commonly-occupied 3000, and an exchange failure is worded exactly as the server words it — the server does not distinguish an unknown code from a bad verifier from a real expiry, so neither does the client.

Verified, and not

Verified against a live environment, through this code rather than curl: authorization request registered, browser consent, redirect caught on the loopback listener, state matched, code exchanged, key issued. Then a real completion through the declarative provider with vendor-prefixed ids — anthropic/claude-sonnet-5 and openai/gpt-5-nano both round-tripped, so the prefix survives goose's wire path.

Not verified: the configure.rs edit does not typecheck here. goose-cli cannot build on this machine at all — bindgen needs libclang, which is absent, and it fails before reaching any of this code. goose and goose-providers both check clean. The CLI edit is a menu item plus a handler modelled directly on the OpenRouter one next to it, but it is unchecked, and CI should be the one to confirm it.

Before the upstream PR

  • tests, mirroring signup_openrouter/tests.rs
  • a demo video, which the maintainer asked for specifically if we do PKCE
  • decide whether to split: declarative first (he will take it quickly), PKCE second

kalvinnchau and others added 30 commits August 28, 2026 04:53
Co-authored-by: Lifei Zhou <lifei@squareup.com>
…un (aaif-goose#11673)

Signed-off-by: Michael Neale <michael.neale@gmail.com>
Signed-off-by: Michael Neale <michael.neale@gmail.com>
Co-authored-by: Galadriel <galadriel@buzz.agent>
Co-authored-by: Alphaxiaoteng <230277249+Alphaxiaoteng@users.noreply.github.com>
Signed-off-by: Jasper Hugo <jasper@spiral.xyz>
)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
…#11662)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…ose#11661)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…11659)

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Jasper Hugo <jasper@spiral.xyz>
Signed-off-by: Jasper Hugo <jasper@spiral.xyz>
jbg and others added 8 commits September 1, 2026 05:11
Signed-off-by: Jasper Hugo <jasper@spiral.xyz>
Signed-off-by: Jasper Hugo <jasper@spiral.xyz>
)

Signed-off-by: Seydi Charyyev <seydi.charyev@gmail.com>
Co-authored-by: Lifei Zhou <lifei@squareup.com>
Two pieces that stand on their own:

- a declarative provider definition (aimlapi.json). 300+ chat models
  behind one OpenAI-compatible key; the eight seeded ids and their context
  limits are read from the live catalog, not guessed. It sorts first in the
  registry only because of the alphabet.

- an authorization-code + PKCE sign-in, built on the same shape as
  signup_openrouter. AI/ML API starts the request server-side, so the CLI
  POSTs the challenge and its loopback redirect first, then opens the
  consent screen and exchanges the returned code for a key.

Three deliberate differences from the OpenRouter flow it mirrors:

- the state is verified. A redirect whose state is not the one we sent did
  not come from the request we started, so its code is not ours to redeem
  (RFC 6749 10.12).
- the loopback port is 53682, not 3000, which is commonly already taken by
  a dev server on a developer's machine.
- an exchange failure is reported exactly as the server words it. The
  server does not distinguish an unknown code from a bad verifier from a
  real expiry, and neither should the client.

There is no compiled-in partner id: shipping another integration's id, or
a staging-only test id, would silently attribute this traffic to the wrong
place. The flow requires AIMLAPI_PARTNER_ID and says so until goose's own
production partner exists.

Verified end to end against a live environment: request registered,
browser consent, redirect caught on the loopback listener, state matched,
code exchanged, key issued.
goose now has a registered AI/ML API partner, so the id compiles in and a
normal install needs no configuration. The environment variable stays, but
only as the testing escape hatch it was meant to be — alongside the two
URL overrides — rather than a hard requirement.

The previous commit deliberately shipped no default: the id that had been
there was another integration's, and sending it would have attributed
every goose sign-in to them.
Carried over from the fork's earlier Rust provider, which this definition
replaces. X-AIMLAPI-Source and X-AIMLAPI-Partner-ID are what let AI/ML API
attribute the traffic to goose; without them a request serves fine and is
silently untagged.

http-referer / x-title follow what the other aggregator definitions here
already send.
Brings the fork up to current upstream and replaces the earlier Rust
provider with a declarative definition plus a PKCE sign-in.

The old crates/goose/src/providers/aimlapi.rs is removed rather than kept
alongside: it registered the same provider name, so the two could not
coexist, and it was already broken against current upstream - it built on
super::openai_compatible::OpenAiCompatibleProvider, a module upstream has
since deleted. Its four hardcoded model ids had also gone stale.

What was worth keeping came across: the X-AIMLAPI-Source and
X-AIMLAPI-Partner-ID attribution headers now ride on the declarative
definition's headers block, so traffic stays tagged.

Also drops the AIMLAPI_HOST row from the provider docs - that was the old
provider's knob and no longer exists.
@Lookoff-AIMLAPI
Lookoff-AIMLAPI merged commit 6ed8623 into main Sep 1, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.