feat(providers): optional AI Horde API key and live image catalog (#10542)

* feat(providers): optional AI Horde API key and live image catalog

Allow a registered Horde key on the no-auth connection and send it for
chat and image jobs. List only image models that currently have workers,
and generate through Horde's native async API.

# Conflicts:
#	open-sse/config/imageRegistry.ts
#	src/app/(dashboard)/dashboard/providers/[id]/ProviderDetailPageClient.tsx
#	src/shared/constants/providers.ts
#	src/sse/services/auth.ts

* fix(providers): validate AI Horde keys against find_user

The OpenAI-compatible /v1/models probe returns 200 for any Bearer token
on oai.aihorde.net, so Check always succeeded. Use Horde's /v2/find_user
lookup instead; an empty key still counts as the optional anonymous path.

* chore(changelog): name the AI Horde fragment for #10542

* fix(images): harden AI Horde optional-key selection and outbound fetches

- Optional-key selection now honors connection health (rate-limit cooldown
  and terminal/unavailable test status) before handing a stored key back,
  rotating to the next healthy key or falling back to the anonymous no-auth
  path instead of using an unhealthy stored key.
- Route the Horde submit/check/status/cancel and catalog calls through the
  repository's bounded outbound-fetch helper (timeout, no more bare fetch())
  and route R2 image downloads through the established bounded remote-image
  fetch (SSRF host guard, DNS-rebinding pin, streaming byte cap, redirect
  limit) instead of an unbounded fetch().
- Extend the generation deadline to cover the full request lifecycle
  (catalog freshness check, submit, polling, and image download), and add a
  regression test proving that exceeding the deadline issues a DELETE
  cancel to Horde's API rather than only timing out locally.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: pqr <pqr@soraka.ititti.es>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
pageragatz
2026-08-18 08:51:57 -05:00
committed by GitHub
parent f92075bb63
commit b9cd5ed138
20 changed files with 1525 additions and 26 deletions

View File

@@ -39,6 +39,10 @@ export const FREE_APIKEY_PROVIDER_IDS = new Set([
"auggie",
// zcode is a local app-server backend; auth stays in the ZCode profile.
"zcode",
// AI Horde works anonymously (`0000000000`) and also accepts a free registered
// key for higher queue priority. The no-auth page still enables the provider;
// this flag admits an optional apikey connection so that stored key is used.
"aihorde",
]);
export function supportsApiKeyOnFreeProvider(providerId: unknown): boolean {

View File

@@ -173,7 +173,7 @@ export const NOAUTH_PROVIDERS = {
freeNote:
"Crowdsourced inference from volunteer GPUs. Throughput is a shared queue, not a quota: there is no RPM/RPD cap, but waits grow when the network is busy.",
notice: {
text: "AI Horde routes to volunteer-run workers, so responses can take minutes and tool calling is unavailable. Model availability changes as workers come and go.",
text: "AI Horde routes to volunteer-run workers, so chat and image jobs can take minutes and tool calling is unavailable. Chat models come from the live oai.aihorde.net catalog. Image models are listed only while Horde reports at least one worker. An optional aihorde.net API key raises queue priority (kudos).",
},
},
};