Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ jobs:
run: pnpm eval:ci evals
continue-on-error: true
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
EMBEDDED_AGENT_PROVIDER: openrouter

- name: Create eval status check
uses: actions/github-script@v7
Expand Down
2 changes: 1 addition & 1 deletion docs/testing/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ describeEval("tool-name", {
### Running Evals

```bash
# Requires OPENAI_API_KEY in .env
# Requires OPENROUTER_API_KEY in .env
pnpm eval

# Run specific eval
Expand Down
5 changes: 4 additions & 1 deletion packages/mcp-server-evals/src/bin/start-mock-stdio.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { ServerContext } from "@sentry/mcp-core/types";

mswServer.listen({
onUnhandledRequest: (req, print) => {
if (req.url.startsWith("https://api.openai.com/")) {
if (
req.url.startsWith("https://api.openai.com/") ||
req.url.startsWith("https://openrouter.ai/")
) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-server-evals/src/evals/search-events.eval.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describeEval } from "vitest-evals";
import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";

// Note: This eval requires OPENAI_API_KEY to be set in the environment
// Note: This eval requires OPENROUTER_API_KEY to be set in the environment
// The search_events tool uses the AI SDK to translate natural language queries
describeEval("search-events", {
data: async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describeEval } from "vitest-evals";
import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";

// Note: This eval requires OPENAI_API_KEY to be set in the environment
// Note: This eval requires OPENROUTER_API_KEY to be set in the environment
// The search_issue_events tool uses the AI SDK to translate natural language queries
describeEval("search-issue-events", {
data: async () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-server-evals/src/evals/search-issues.eval.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describeEval } from "vitest-evals";
import { FIXTURES, NoOpTaskRunner, ToolPredictionScorer } from "./utils";

// Note: This eval requires OPENAI_API_KEY to be set in the environment
// Note: This eval requires OPENROUTER_API_KEY to be set in the environment
// The search_issues tool uses the AI SDK to translate natural language queries
describeEval("search-issues", {
data: async () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { experimental_createMCPClient } from "@ai-sdk/mcp";
import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio";
import { openai } from "@ai-sdk/openai";
import { getOpenRouterModel } from "@sentry/mcp-core/internal/agents/openrouter-provider";
import { generateText, stepCountIs, type LanguageModel } from "ai";

const defaultModel = openai("gpt-4o");

function toToolCall(call: { toolName: string; input: unknown }) {
const input =
call.input && typeof call.input === "object" && !Array.isArray(call.input)
Expand All @@ -18,7 +16,7 @@ function toToolCall(call: { toolName: string; input: unknown }) {
}

export function McpToolCallTaskRunner(
model: LanguageModel = defaultModel,
model: LanguageModel = getOpenRouterModel(),
maxSteps = 6,
) {
return async function McpToolCallTaskRunner(input: string) {
Expand Down
16 changes: 11 additions & 5 deletions packages/mcp-server-evals/src/evals/utils/toolPredictionScorer.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { openai } from "@ai-sdk/openai";
import { generateObject, type LanguageModel } from "ai";
import { z } from "zod";
import { experimental_createMCPClient } from "@ai-sdk/mcp";
import { Experimental_StdioMCPTransport } from "@ai-sdk/mcp/mcp-stdio";
import { getOpenRouterModel } from "@sentry/mcp-core/internal/agents/openrouter-provider";

// Cache for available tools to avoid reconnecting for each test
let cachedTools: string[] | null = null;
Expand Down Expand Up @@ -64,8 +64,6 @@ interface ToolPredictionScorerOptions {
result?: any;
}

const defaultModel = openai("gpt-4o");

const predictionSchema = z.object({
score: z.number().min(0).max(1).describe("Score from 0 to 1"),
rationale: z.string().describe("Explanation of the score"),
Expand Down Expand Up @@ -129,7 +127,7 @@ CRITICAL: The expected tools represent the actual realistic behavior for this sp
* A scorer that uses AI to predict what tools would be called without executing them.
* This is much faster than actually running the tools and checking what was called.
*
* @param model - Optional language model to use for predictions (defaults to gpt-4o)
* @param model - Optional language model to use for predictions (defaults to OpenRouter)
* @returns A scorer function that compares predicted vs expected tool calls
*
* @example
Expand Down Expand Up @@ -170,7 +168,9 @@ CRITICAL: The expected tools represent the actual realistic behavior for this sp
* If `expectedTools` is not provided in test data, the scorer is automatically skipped
* and returns `{ score: null }` to allow other scorers to run without interference.
*/
export function ToolPredictionScorer(model: LanguageModel = defaultModel) {
export function ToolPredictionScorer(
model: LanguageModel = getOpenRouterModel(),
) {
Comment thread
cursor[bot] marked this conversation as resolved.
return async function ToolPredictionScorer(
opts: ToolPredictionScorerOptions,
) {
Expand Down Expand Up @@ -205,6 +205,12 @@ export function ToolPredictionScorer(model: LanguageModel = defaultModel) {
expectedDescription,
),
schema: predictionSchema,
providerOptions: {
openai: {
structuredOutputs: false,
strictJsonSchema: false,
},
},
experimental_telemetry: {
isEnabled: true,
functionId: "tool_prediction_scorer",
Expand Down
8 changes: 6 additions & 2 deletions packages/mcp-server-mocks/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ export function startMockServer(options?: {

mswServer.listen({
onUnhandledRequest: (req: any, print: any) => {
// Ignore OpenAI requests if specified (default behavior for AI agent tests)
if (ignoreOpenAI && req.url.startsWith("https://api.openai.com/")) {
// Ignore LLM provider requests if specified (default behavior for AI agent tests)
if (
ignoreOpenAI &&
(req.url.startsWith("https://api.openai.com/") ||
req.url.startsWith("https://openrouter.ai/"))
) {
return;
}

Expand Down
Loading