mirror of
https://github.com/Gitlawb/openclaude.git
synced 2026-11-06 12:50:54 -04:00
* feat(gateways): add Requesty hybrid gateway Register Requesty as an OpenAI-compatible gateway with a short curated catalog plus public /v1/models discovery. REQUESTY_API_KEY is only resolved for the exact https /v1 base on the global, EU, US and AP hosts. Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> * test(gateways): cover Requesty model mapping and credential boundary Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> * docs: add Requesty gateway setup Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> * test(env): cover loading REQUESTY_API_KEY from provider env files Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> * docs(env): keep the Requesty EU base URL copyable Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> * test(provider-manager): include Requesty in the preset picker order The ProviderManager tests navigate the preset list by index, so the new Requesty preset (between OrcaRouter and Runcrate) must be listed or the custom-provider tests stop one row short and time out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(providers): bind saved Requesty profile keys to the canonical endpoint Requesty's dedicated key was registered in the gateway descriptor, the request-time credential gate and the .env allowlist, but not in the saved-profile credential lifecycle that LLMTR and API Route use. So: - a keyed `requesty` profile retargeted to a non-Requesty URL installed and persisted its saved key as OPENAI_API_KEY for that URL; - an ambient REQUESTY_API_KEY overrode a canonical profile's saved key, both on profile application and on relaunch; - tmux teammates did not receive REQUESTY_API_KEY. Withhold the saved key for retargeted Requesty profiles in profile application and startup persistence, manage REQUESTY_API_KEY like the other profile dedicated keys (keyless canonical profiles keep the ambient key; relaunch prefers the selected profile's key and never carries it to a noncanonical URL), and forward it to teammates. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(providers): keep saved Requesty keys off shell-retargeted launches A relaunch with a shell OPENAI_BASE_URL that points a saved Requesty profile at a non-canonical URL still carried the profile's persisted OPENAI_API_KEY to that URL. Drop persisted generic credentials for that retarget, as the Merge and Runcrate guards already do; explicit shell credentials still apply. Also require the persisted profile to be a Requesty profile before its generic key is recovered as REQUESTY_API_KEY, so a shell retarget of another profile to Requesty no longer adopts that profile's key over a shell REQUESTY_API_KEY. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(providers): drop saved Requesty auth and headers on shell retarget The Requesty retarget boundary only gated the generic OPENAI_API_KEY selection. Requesty supports custom auth headers, so a saved profile's credential can also ride in the OPENAI_AUTH_* trio or ANTHROPIC_CUSTOM_HEADERS, and a shell OPENAI_BASE_URL retarget still sent those to the new endpoint. Apply the existing Runcrate retarget handling to a Requesty retarget away from its saved endpoint, so every credential channel follows the same rule. A canonical regional switch and a saved non-canonical profile relaunched at its own URL keep their saved auth, matching profile apply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(providers): bind saved Requesty credentials to a canonical saved URL The Requesty retarget boundary only checked the launch URL. A profile saved for a non-canonical Requesty-route URL and relaunched with a shell OPENAI_BASE_URL on canonical Requesty was not treated as a retarget, so its proxy key, REQUESTY_API_KEY, custom-auth trio and custom headers all reached Requesty. Profile apply already treats only a canonically saved Requesty profile's key as a Requesty key. Use the same rule on relaunch: saved credentials follow only between canonical Requesty URLs. Any other launch drops them, including the dedicated-key fallback. Explicit shell credentials still apply. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(requesty): require CLAUDE_CODE_USE_OPENAI=1 for raw env setup Without CLAUDE_CODE_USE_OPENAI=1, startup ignores a Requesty OPENAI_BASE_URL, OPENAI_MODEL and REQUESTY_API_KEY env and falls back to the default OpenGateway route. The README table row and the .env.example block listed only the base URL and model. Name the selector in both, as the PR description already does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): bind route identity and discovery to the canonical endpoint Requesty's credential was bound to the canonical https /v1 hosts, but the sibling sites that apply the same boundary for LLMTR, Merge, Command Code and API Route did not include Requesty: - URL route resolution, active-profile and capability resolution, and provider validation treated any Requesty host or retargeted profile as `requesty`, so validation accepted REQUESTY_API_KEY for a URL whose requests withhold it and capability surfaces kept the Requesty route. - Hybrid discovery forwarded a caller or saved key to a noncanonical base URL, and a retargeted profile still triggered startup discovery. - A profile saved for a noncanonical URL persisted no route identity, so the relaunch retarget guard missed it and its saved custom auth and headers followed a shell retarget onto canonical Requesty. - REQUESTY_API_KEY was not protected from settings overrides when the host manages the provider. Register Requesty at each of those sites, matching its siblings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(requesty): restore REQUESTY_API_KEY after discovery tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): clear a copied Requesty key on provider switch A saved Requesty profile mirrors its key into OPENAI_API_KEY. The copied-key detection in applyProviderFlag listed LLMTR and the other dedicated gateways but not Requesty, so --provider openai or openrouter kept the Requesty key as the generic credential for the new endpoint. An independent shell OPENAI_API_KEY is still preserved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): give a Requesty teammate override its own key Teammates now inherit REQUESTY_API_KEY, and Requesty prefers it over OPENAI_API_KEY. applyAgentProviderOverrideToEnv cleared and replaced the dedicated keys of Merge, OrcaRouter, Runcrate and Command Code, but not Requesty, so an agentModels Requesty override kept using the parent's key. Clear it for every override and install the configured key for a canonical Requesty endpoint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): prefer a mirrored Requesty key over a generic key pool The request executor treats an OPENAI_API_KEY equal to a dedicated key (LLMTR, Command Code, and others) as that provider's key and uses it before the generic OPENAI_API_KEYS pool. REQUESTY_API_KEY was missing from that list. A saved Requesty profile and a Requesty teammate override both mirror their key into OPENAI_API_KEY, so an inherited or ambient OPENAI_API_KEYS pool was sent to Requesty instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): scope the copied Requesty key to the Requesty routeccab79e2let an OPENAI_API_KEY equal to REQUESTY_API_KEY take precedence as a copied provider key on every route, so a stale mirror could be sent to another provider such as xAI instead of its own key. Count it as copied only when the active route is requesty. The pool test now sets the mirrored state directly instead of running the override helper against the shared process env. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): apply the dedicated proxy and placeholder guards to Requesty A saved Requesty proxy profile carries the requesty route id, but buildLaunchEnv's noncanonical-launch list and buildStartupEnvFromProfile's retained-proxy guard did not include Requesty. Ambient OPENAI_API_KEY, OPENAI_API_KEYS and REQUESTY_API_KEY could reach the proxy on relaunch, and a concrete shell selection skipped the guard entirely. LLMTR, Merge, Command Code and API Route already withhold them. REQUESTY_API_KEY was also missing from the placeholder-aware credential checks in validation, route credential resolution and the picker, so a template value such as SUA_CHAVE counted as usable and beat a real OPENAI_API_KEY. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): mirror a saved Requesty key on in-process profile apply A saved Requesty profile reaches the env through two producers. The startup env (buildOpenAICompatibleStartupEnv) writes the key as both OPENAI_API_KEY and REQUESTY_API_KEY and stamps the requesty route id. The in-process apply (applyProviderProfileToProcessEnv) wrote only OPENAI_API_KEY. Provider-flag switch-away recognizes a copied Requesty key only when the two match, so after applying a keyed profile and then selecting another provider, the Requesty secret stayed in OPENAI_API_KEY and was sent to the new endpoint. The in-process apply now writes the same mirror and route id as startup, like the ApiSmart, Concentrate, API Route and Command Code profiles in that block. The README, .env.example and website note now list the US and AP regional hosts beside EU. Those four URLs are the only ones that receive REQUESTY_API_KEY. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): keep a saved Requesty key from passing as shell input A keyed canonical Requesty profile writes its saved key into REQUESTY_API_KEY, both in the startup env and, since1ce28be5, on in-process apply. A keyless canonical Requesty profile adopts REQUESTY_API_KEY as shell input. Nothing recorded where that value came from, so selecting a keyless profile after a keyed one, in process or after a relaunch from the keyed startup file, sent requests on the keyed profile's account. Requesty now uses the origin marker that Runcrate already uses for the same keyless-adoption rule. CLAUDE_CODE_PROVIDER_PROFILE_REQUESTY_KEY_SHA256 is written where the saved key is installed (profile apply, startup bootstrap, profile update, launch env), kept across env reapply, forwarded to teammate panes, and cleared with the rest of the profile env. Keyless adoption and the alignment check refuse a key that carries the marker. Genuine shell input has no marker and still authenticates a keyless profile. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(requesty): restore a keyed Requesty profile's key on reconcile A keyed canonical Requesty profile installs its saved key as REQUESTY_API_KEY, and the request executor prefers that variable on the Requesty route. Settings env is merged into the process after the profile applies. applyActiveProviderProfileFromConfig then reapplies the profile only when isProcessEnvAlignedWithProfile reports drift, and that check compared ApiSmart, API Route and Command Code dedicated keys but not REQUESTY_API_KEY. A settings or shell REQUESTY_API_KEY therefore survived reconcile and was sent instead of the selected profile's saved key. The alignment check now compares REQUESTY_API_KEY for a keyed canonical Requesty profile, so reconcile restores the saved key. A keyless profile still uses shell or settings input. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(requesty): state where REQUESTY_API_KEY is sent REQUESTY_API_KEY is sent only to the four canonical Requesty URLs. Any other OPENAI_BASE_URL runs as a custom endpoint and uses OPENAI_API_KEY. The README row, .env.example and website note now say so. The website note also gains the CLAUDE_CODE_USE_OPENAI=1 raw-env requirement that0c467009added to the README and .env.example. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * revert(requesty): return Requesty to gateway scope Requesty is an OpenAI-compatible gateway, like Hicap and OpenRouter, not a first-class provider. The commits aftere04177c4added first-class credential ownership for it: saved-profile key handling across apply, startup, relaunch and reconcile, provider-switch cleanup, teammate forwarding and overrides, discovery and route-identity changes, host-managed env, placeholder registries and a key-origin marker. Each layer exposed another lifecycle edge for review to find, and none of it is needed for the gateway. Restore every code and test file toe04177c4:e3b95870,41f409bf,7d3dbb86,55b02074,89417454,b81ac70f,d84546e9,433b680a,ccab79e2,591f4a08,9b56ef2e,1ce28be5,025da9bband3c7caf25. Profile and lifecycle credential handling stays on the shared gateway baseline that Hicap and OpenRouter use on main. The request-time gate from the original integration is kept: REQUESTY_API_KEY is sent only to the exact https /v1 base on the global, EU, US and AP hosts. Any other OPENAI_BASE_URL uses OPENAI_API_KEY. The doc fixes that still match this code are kept: the CLAUDE_CODE_USE_OPENAI=1 raw-env note, all four hosts, and the key-scope sentence in the README, .env.example and website entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(requesty): cover the request-time credential gate end to end The Requesty key gate lives in resolveRouteCredentialValue and was tested only at the resolver. Drive the real OpenAI shim with a mocked fetch and check the Authorization header for each base URL. The four canonical https /v1 hosts get REQUESTY_API_KEY. http, a custom port and another host never do, and only an OPENAI_API_KEY the user set follows them. With the gate disabled, the test fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(requesty): isolate the credential gate test env The gate test cleared variables by prefix and restored the whole process env. It missed the provider-selection flags, so an inherited CLAUDE_CODE_USE_GEMINI=1 with GEMINI_API_KEY routed the request to Gemini and failed the test. The blanket restore could also overwrite unrelated variables. Use snapshotEnv with an explicit list of provider-selection and request-auth variables. Snapshot it after taking the shared lock, clear the list before each case, and restore only those keys before releasing the lock, as CONTRIBUTING.md asks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(requesty): run the credential gate test in a fresh process The in-process gate test depended on a hand-kept list of every variable the OpenAI shim reads. Each review found another one: provider flags, then OPENAI_AZURE_STYLE and the GitHub token hydration marker. Run the requests in a child process instead, the pattern the Merge gateway tests use. Its env is the parent's with clearManagedProfileEnv applied (the repo's managed provider key list) and a temporary config dir. Each case sets its own variables inside the child, so nothing inherited reaches the request and this process's env is never changed. The test asserts the Authorization header for every canonical and non-canonical URL, with and without OPENAI_API_KEY, and fails when the gate is disabled. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com> Co-authored-by: Thibault Jaigu <thibault.jaigu@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>