Skip to content

feat(ai): add Requesty provider - #747

Open
Thibaultjaigu wants to merge 1 commit into
markrahq:v2from
Thibaultjaigu:add-requesty-provider
Open

Thibaultjaigu wants to merge 1 commit into
markrahq:v2from
Thibaultjaigu:add-requesty-provider

Conversation

@Thibaultjaigu

Copy link
Copy Markdown

Summary

Adds Requesty (an OpenAI-compatible LLM gateway) as a disabled built-in provider, following the same pattern as the OrcaRouter entry from #718. It uses the existing OpenAI-compatible transport, so no new request code paths.

Changes

  • packages/providers/src/catalog.ts: new requesty template (base URL https://router.requesty.ai/v1, disabled by default) seeded with managed model ids (gpt-5.6-sol, claude-fable-5, claude-opus-5, claude-sonnet-5, gemini-3.6-flash)
  • packages/providers/src/provider-capabilities.ts: enable model discovery for requesty
  • packages/providers/src/requests.ts: model list uses GET /models/managed (Requesty's curated list), and capabilities are read from the supports_vision, supports_reasoning and supports_tool_calling fields. Any id from the full /models catalog (e.g. openai/gpt-4o-mini) can still be added by hand
  • packages/providers/src/settings.ts: existing settings get the new entry appended, same as OrcaRouter (turned the single OrcaRouter block into a loop over both ids)
  • packages/providers/src/thinking-format.ts: when thinking is on, send reasoning_effort: "high" and nothing else. When it is off, send nothing
  • packages/app/src/components/AiProviderBadge.tsx plus requesty.svg logo
  • README (en and zh-CN) built-in provider list
  • Tests next to the OrcaRouter ones for the catalog entry, discovery, migration, thinking format, adapter request shape, streaming and the badge. The two OrcaRouter migration tests now expect one more appended provider

Requesty is not the default and is not added to any automatic selection. For EU routing, set the API URL to https://router.eu.requesty.ai/v1.

How to test

  1. Get a key at https://app.requesty.ai/api-keys (docs: https://docs.requesty.ai)
  2. Settings > AI > Requesty: paste the key, enable, click refresh models
  3. Pick gpt-5.6-sol or add openai/gpt-4o-mini and run inline AI or the side panel

Verification

  • pnpm --filter @markra/providers test: 54 passed
  • pnpm --filter @markra/ai test: 266 passed
  • pnpm --filter @markra/app test: 1639 passed
  • apps/web and apps/desktop vitest: 50 and 175 passed
  • pnpm run typecheck:test: pass
  • pnpm build for @markra/providers, @markra/ai, @markra/app and apps/web: pass (skipped the Tauri desktop build)
  • Live, through fetchAiProviderModels, testAiProviderConnection, chatCompletion and chatCompletionStream with a real key: 159 managed models listed, valid key connects and an invalid key is rejected (403), openai/gpt-4o-mini chat returned 200, and gpt-5.6-sol streamed with thinking on. I also checked every seeded model live with temperature: 0.7 and reasoning_effort: "high"

No UI layout changes apart from the new logo in the provider list.

Disclosure: I work at Requesty. Happy to adjust anything to match project conventions.

Add a disabled built-in Requesty entry on the existing OpenAI-compatible transport, list models from the managed models endpoint with capabilities from its metadata, keep saved settings intact during migration, and map reasoning to reasoning_effort.
@vercel

vercel Bot commented Sep 24, 2026

Copy link
Copy Markdown

@Thibaultjaigu is attempting to deploy a commit to the murongg's projects Team on Vercel.

A member of the Team first needs to authorize it.

@vercel

vercel Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
markra-web Ready Ready Preview Oct 5, 2026 12:32am UTC

@murongg murongg left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the two provider behavior issues below before merging.

Reviewed commit: a7b04d3.

Validation: 54 provider tests, 266 AI tests, and 13 focused app tests passed. Provider/AI builds and test typechecks, plus the app TypeScript build, passed. Supplemental synthetic probes reproduced the capability-metadata override and showed that explicitly disabled thinking produces the same request options as an unspecified setting. Public model-list and invalid-key responses were checked; live paid inference was not performed.

function inferRequestyCapabilities(record: Record<string, unknown>, id: string): AiModelCapability[] {
if (typeof record.api === "string" && record.api !== "chat") return [];

const capabilities = inferCapabilitiesFromId(id);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Respect explicit false capability metadata

Starting from inferCapabilitiesFromId(id) adds capabilities before reading Requesty's metadata, and the subsequent checks only append capabilities when a field is true. As a result, an explicit false never removes a capability inferred from the model name. For example, the public managed catalog reports supports_vision: false for gpt-5-mini@eu, but this parser still marks it as vision-capable, allowing the app to send unsupported image inputs.

A synthetic chat model named mock-gpt-5-text-only with all supports_* fields set to false is parsed as ["text", "vision", "reasoning", "tools", "web"] instead of ["text"].

Please prioritize explicit boolean metadata and use name-based inference only when the relevant metadata is absent. Also ensure default-model capability enrichment does not reintroduce capabilities explicitly denied by the catalog. Add a regression case where the model name matches a heuristic but the corresponding metadata is false.

// Omit effort when off: the gateway does not document a portable "none" value across upstreams.
if (config.id === "orcarouter") return thinkingState === "enabled" ? "reasoning-effort" : null;
// Requesty also maps reasoning_effort per upstream, so the same rule applies.
if (config.id === "requesty") return thinkingState === "enabled" ? "reasoning-effort" : null;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Distinguish explicitly disabled thinking from gateway defaults

For Requesty, thinkingEnabled: false returns null, so the generated options are {}, exactly the same as when thinking is unspecified. Models that reason by default therefore receive no instruction to disable or minimize reasoning, despite the UI setting being off.

Unlike the OrcaRouter assumption in the preceding comment, Requesty documents reasoning_effort: "none" / "min" as supported values that disable reasoning or select its minimum supported effort: https://docs.requesty.ai/features/reasoning.

Please preserve the distinction between unspecified (omit the parameter) and explicitly disabled (send the documented minimum/disable value), and cover the effective outgoing request, including the SDK route if applicable. The current test expecting {} for the disabled state locks in this loss of intent.

This branch was successfully deployed

1 active deployment
Preview — a7b04d30 Deployed Oct 5, 2026 by vercel[bot]
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.

2 participants