Skip to content

Add Requesty as a provider option#7

Open
Thibaultjaigu wants to merge 1 commit into
ZeroLeaks:mainfrom
Thibaultjaigu:add-requesty-provider
Open

Add Requesty as a provider option#7
Thibaultjaigu wants to merge 1 commit into
ZeroLeaks:mainfrom
Thibaultjaigu:add-requesty-provider

Conversation

@Thibaultjaigu

Copy link
Copy Markdown

This adds Requesty as an OpenAI-compatible provider option, mirroring the existing @openrouter/ai-sdk-provider usage.

Requesty (https://router.requesty.ai/v1) is an OpenAI-compatible LLM router. I used @requesty/ai-sdk@0.0.9 to match this repo's AI SDK v4 (@ai-sdk/provider@1.0.9, same as @openrouter/ai-sdk-provider@0.4.3).

Changes: attacker.ts/evaluator.ts select Requesty when a Requesty key is present (via createRequesty), the CLI accepts REQUESTY_API_KEY/--provider, and README/AGENTS note the option. The existing OpenRouter path is unchanged and remains the default.

I work at Requesty. This mirrors the existing OpenRouter provider as closely as possible. Happy to adjust or close it if it's not a fit.

Mirror the existing @openrouter/ai-sdk-provider usage to add Requesty
(https://router.requesty.ai/v1) via @requesty/ai-sdk, an OpenAI-compatible LLM router.
Requesty is selected when a Requesty key is present; the OpenRouter path is unchanged.

Signed-off-by: Thibault Jaigu <thibault.jaigu@gmail.com>
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds Requesty as an OpenAI-compatible provider alternative to OpenRouter, mirroring the existing @openrouter/ai-sdk-provider integration in attacker.ts and evaluator.ts, with CLI support via --provider requesty and REQUESTY_API_KEY.

  • Partial agent coverage: Only Attacker and Evaluator were updated; Strategist, Mutator, Inspector, InjectionEvaluator, and Target still call createOpenRouter unconditionally. When --provider requesty is used, ScanEngine passes the Requesty API key to all those agents, which then send it to the OpenRouter endpoint and receive auth errors — the scan fails on the first turn.
  • Model-name default bypass: The Requesty branches in attacker.ts/evaluator.ts default to hyphenated model IDs (anthropic/claude-sonnet-4-5), but ScanEngine.DEFAULT_CONFIG always supplies a dot-format model name, so the hyphenated fallback is never reached from the CLI path.
  • CLI and docs: Provider auto-detection and env-var propagation are logically sound; invalid --provider values are silently ignored rather than rejected, and the README "get your key" link points to the API endpoint instead of the web dashboard.

Confidence Score: 3/5

Not safe to merge in current form — a Requesty-only user running the CLI will hit auth errors on the first scan turn because the majority of agents still call OpenRouter with the Requesty key.

The attacker and evaluator changes are correct, but four other agents (Strategist, Mutator, Inspector, Target) and the injection evaluator remain OpenRouter-only. ScanEngine passes the resolved API key to all of them, so a Requesty key ends up at the OpenRouter endpoint and triggers authentication failures before the first attack turn completes. The model-name default issue compounds this: even if the other agents were fixed, the dot-vs-hyphen model ID mismatch could break Requesty calls when model names flow in from ScanEngine's defaults.

src/agents/engine.ts and the unmodified agent files (strategist.ts, mutator.ts, inspector.ts, injection-evaluator.ts, target.ts) need Requesty support added to match what was done in attacker.ts and evaluator.ts.

Important Files Changed

Filename Overview
src/agents/engine.ts Not directly changed, but exposes a gap: ScanEngine passes the resolved API key to Strategist, Mutator, Inspector, InjectionEvaluator, and Target without any Requesty awareness — these agents will send Requesty keys to OpenRouter, causing auth failures for Requesty-only users.
src/agents/attacker.ts Provider selection logic is correct in isolation, but the Requesty-specific hyphenated model default is never reached when called from ScanEngine because the engine always supplies a dot-format model name from DEFAULT_CONFIG.
src/agents/evaluator.ts Same provider-selection pattern as attacker.ts with the same model-name default reachability issue; otherwise mirrors the attacker change cleanly.
src/bin/cli.ts Provider resolution and env-var propagation are logically correct; invalid provider values are silently ignored rather than rejected, which is a minor UX gap.
package.json Adds @requesty/ai-sdk@0.0.9 as a dependency; version is pinned exactly (no caret), matching the PR's rationale about AI SDK v4 compatibility.
README.md Documentation is clear and accurate; the "get your API key" URL points to the router endpoint rather than the website dashboard.
AGENTS.md Updated cleanly to reflect both providers in the tech-stack and environment-variable sections.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    CLI["CLI: zeroleaks scan --provider requesty"]
    ENV["Sets process.env.REQUESTY_API_KEY = apiKey"]
    RUN["runSecurityScan({ apiKey: requestyKey })"]
    ENGINE["ScanEngine constructor\napiKey = config.apiKey (requestyKey)"]

    ENGINE --> ATK["createAttacker({ apiKey: requestyKey })\n✅ Auto-detects REQUESTY_API_KEY\nUses createRequesty()"]
    ENGINE --> EVAL["createEvaluator({ apiKey: requestyKey })\n✅ Auto-detects REQUESTY_API_KEY\nUses createRequesty()"]
    ENGINE --> STRAT["createStrategist({ apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> MUT["createMutator({ apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> INSP["createInspector(..., requestyKey)\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> TARGET["createTarget(prompt, { apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]

    CLI --> ENV --> RUN --> ENGINE
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    CLI["CLI: zeroleaks scan --provider requesty"]
    ENV["Sets process.env.REQUESTY_API_KEY = apiKey"]
    RUN["runSecurityScan({ apiKey: requestyKey })"]
    ENGINE["ScanEngine constructor\napiKey = config.apiKey (requestyKey)"]

    ENGINE --> ATK["createAttacker({ apiKey: requestyKey })\n✅ Auto-detects REQUESTY_API_KEY\nUses createRequesty()"]
    ENGINE --> EVAL["createEvaluator({ apiKey: requestyKey })\n✅ Auto-detects REQUESTY_API_KEY\nUses createRequesty()"]
    ENGINE --> STRAT["createStrategist({ apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> MUT["createMutator({ apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> INSP["createInspector(..., requestyKey)\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]
    ENGINE --> TARGET["createTarget(prompt, { apiKey: requestyKey })\n❌ Uses createOpenRouter(requestyKey)\n→ 401 on OpenRouter"]

    CLI --> ENV --> RUN --> ENGINE
Loading

Reviews (1): Last reviewed commit: "Add Requesty as a provider option" | Re-trigger Greptile

Comment thread src/agents/attacker.ts
Comment on lines +141 to +151
if (useRequesty) {
this.provider = createRequesty({
apiKey: config?.apiKey || requestyKey,
});
this.model = config?.model || "anthropic/claude-sonnet-4-5";
} else {
this.provider = createOpenRouter({
apiKey: config?.apiKey || openrouterKey,
});
this.model = config?.model || "anthropic/claude-sonnet-4.5";
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Requesty model-name default unreachable via ScanEngine

The Requesty branch sets this.model = config?.model || "anthropic/claude-sonnet-4-5" (hyphens), but ScanEngine.DEFAULT_CONFIG always provides a model ("anthropic/claude-sonnet-4.5" with dots). Because config?.model is always truthy when called from the engine, the hyphenated Requesty default is never used in the CLI path — the agent always receives the dot-format model name. If Requesty strictly requires hyphenated model IDs, every call from ScanEngine will fail. The same issue exists identically in evaluator.ts.

Comment thread src/bin/cli.ts
Comment on lines +70 to +75
const provider: "openrouter" | "requesty" =
options.provider === "requesty" || options.provider === "openrouter"
? options.provider
: requestyEnvKey && !openrouterEnvKey
? "requesty"
: "openrouter";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 An unrecognized --provider value (e.g. --provider gpt) silently falls through to "openrouter" with no warning. Users who make a typo will get a confusing auth failure instead of a clear validation error.

Suggested change
const provider: "openrouter" | "requesty" =
options.provider === "requesty" || options.provider === "openrouter"
? options.provider
: requestyEnvKey && !openrouterEnvKey
? "requesty"
: "openrouter";
if (options.provider && options.provider !== "requesty" && options.provider !== "openrouter") {
console.error(
`Error: Unknown provider "${options.provider}". Valid values: openrouter, requesty`,
);
process.exit(1);
}
const provider: "openrouter" | "requesty" =
options.provider === "requesty" || options.provider === "openrouter"
? options.provider
: requestyEnvKey && !openrouterEnvKey
? "requesty"
: "openrouter";

Comment thread README.md
| `REQUESTY_API_KEY` | Your Requesty API key — Requesty is an OpenAI-compatible alternative to OpenRouter (base URL `https://router.requesty.ai/v1`). Used automatically when set and `OPENROUTER_API_KEY` is not, or force it with `--provider requesty`. |

Get your API key at [openrouter.ai](https://openrouter.ai)
Get your API key at [openrouter.ai](https://openrouter.ai) or [requesty.ai](https://router.requesty.ai/v1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The "get your API key" link points to https://router.requesty.ai/v1, which is the API base URL, not the web dashboard where users sign up and obtain keys.

Suggested change
Get your API key at [openrouter.ai](https://openrouter.ai) or [requesty.ai](https://router.requesty.ai/v1)
Get your API key at [openrouter.ai](https://openrouter.ai) or [requesty.ai](https://requesty.ai)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@x1xhlol x1xhlol left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Reviewed the provider-selection path across the CLI, attacker, evaluator, and docs. The OpenRouter default appears preserved, and Requesty is only selected explicitly or when REQUESTY_API_KEY is present without OPENROUTER_API_KEY, which keeps existing users on the current path. No blocking changes from this pass; the main thing I would consider before merge is a small unit/CLI coverage check around provider resolution so the auto-detection rules do not regress later.

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