Repository navigation
feat(ai): add Requesty provider - #747
Thibaultjaigu wants to merge 1 commit into
Conversation
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.
|
@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. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
murongg
left a comment
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
[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; |
There was a problem hiding this comment.
[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.
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: newrequestytemplate (base URLhttps://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 forrequestypackages/providers/src/requests.ts: model list usesGET /models/managed(Requesty's curated list), and capabilities are read from thesupports_vision,supports_reasoningandsupports_tool_callingfields. Any id from the full/modelscatalog (e.g.openai/gpt-4o-mini) can still be added by handpackages/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, sendreasoning_effort: "high"and nothing else. When it is off, send nothingpackages/app/src/components/AiProviderBadge.tsxplusrequesty.svglogoRequesty 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
gpt-5.6-solor addopenai/gpt-4o-miniand run inline AI or the side panelVerification
pnpm --filter @markra/providers test: 54 passedpnpm --filter @markra/ai test: 266 passedpnpm --filter @markra/app test: 1639 passedapps/webandapps/desktopvitest: 50 and 175 passedpnpm run typecheck:test: passpnpm buildfor@markra/providers,@markra/ai,@markra/appandapps/web: pass (skipped the Tauri desktop build)fetchAiProviderModels,testAiProviderConnection,chatCompletionandchatCompletionStreamwith a real key: 159 managed models listed, valid key connects and an invalid key is rejected (403),openai/gpt-4o-minichat returned 200, andgpt-5.6-solstreamed with thinking on. I also checked every seeded model live withtemperature: 0.7andreasoning_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.