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
75 changes: 75 additions & 0 deletions sdks/js/anthropic/cases/2-multi-step.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* 2-multi-step: Multi-step Conversation
*
* Tests a multi-step conversation with conversation history using Anthropic SDK
* and verifies that Sentry captures all spans for both API calls.
*/

const { Sentry } = require("../setup");
const Anthropic = require("@anthropic-ai/sdk");
const { runTestCase } = require("../../_test-utils/test-runner.cjs");

async function testLogic(inputs) {
const { model, system, first_prompt, second_prompt } = inputs;

// Initialize Anthropic client
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});

// First call
const firstMessage = await anthropic.messages.create({
model: model,
max_tokens: 1024,
system: system,
messages: [
{
role: "user",
content: first_prompt,
},
],
});

if (!firstMessage.content || firstMessage.content.length === 0) {
throw new Error("No completion returned from Anthropic (first call)");
}

const firstText = firstMessage.content[0].text;

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` First response: ${firstText}`);
}

// Second call with conversation history
const secondMessage = await anthropic.messages.create({
model: model,
max_tokens: 1024,
system: system,
messages: [
{
role: "user",
content: first_prompt,
},
{
role: "assistant",
content: firstText,
},
{
role: "user",
content: second_prompt,
},
],
});

if (!secondMessage.content || secondMessage.content.length === 0) {
throw new Error("No completion returned from Anthropic (second call)");
}

const secondText = secondMessage.content[0].text;

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` Second response: ${secondText}`);
}
}

module.exports = runTestCase("2-multi-step", testLogic, Sentry);
5 changes: 5 additions & 0 deletions sdks/js/anthropic/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"model": "claude-haiku-4-5",
"gen_ai.request.model": "claude-haiku-4-5",
"gen_ai.response.model": "claude-haiku-4-5*"
},
"2-multi-step": {
"model": "claude-haiku-4-5",
"gen_ai.request.model": "claude-haiku-4-5",
"gen_ai.response.model": "claude-haiku-4-5*"
}
}
}
62 changes: 62 additions & 0 deletions sdks/js/google-genai/cases/2-multi-step.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* 2-multi-step: Multi-step Conversation
*
* Tests a multi-step conversation with conversation history using Google GenAI SDK
* and verifies that Sentry captures all spans for both API calls.
*/

const { Sentry } = require("../setup");
const { GoogleGenAI } = require("@google/genai");
const { runTestCase } = require("../../_test-utils/test-runner.cjs");

async function testLogic(inputs) {
const { model, system, first_prompt, second_prompt } = inputs;

const client = new GoogleGenAI({
apiKey: process.env.GOOGLE_GENAI_API_KEY,
});

// First call
const firstResponse = await client.models.generateContent({
model,
contents: first_prompt,
config: {
systemInstruction: [system],
},
});

const firstText = firstResponse.text;

if (!firstText) {
throw new Error("No completion returned from Google GenAI (first call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` First response: ${firstText}`);
}

// Second call with conversation history
const secondResponse = await client.models.generateContent({
model,
contents: [
{ role: "user", parts: [{ text: first_prompt }] },
{ role: "model", parts: [{ text: firstText }] },
{ role: "user", parts: [{ text: second_prompt }] },
],
config: {
systemInstruction: [system],
},
});

const secondText = secondResponse.text;

if (!secondText) {
throw new Error("No completion returned from Google GenAI (second call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` Second response: ${secondText}`);
}
}

module.exports = runTestCase("2-multi-step", testLogic, Sentry);
5 changes: 5 additions & 0 deletions sdks/js/google-genai/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
"model": "gemini-2.5-flash-lite",
"gen_ai.request.model": "gemini-2.5-flash-lite",
"gen_ai.response.model": "gemini-2.5-flash-lite"
},
"2-multi-step": {
"model": "gemini-2.5-flash-lite",
"gen_ai.request.model": "gemini-2.5-flash-lite",
"gen_ai.response.model": "gemini-2.5-flash-lite"
}
}
}
70 changes: 70 additions & 0 deletions sdks/js/langgraph/cases/2-multi-step.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* 2-multi-step: Multi-step Conversation
*
* Tests a multi-step conversation with conversation history using LangGraph SDK
* and verifies that Sentry captures all spans for both API calls.
*/

const { Sentry } = require("../setup");
const { ChatOpenAI } = require("@langchain/openai");
const { createReactAgent } = require("@langchain/langgraph/prebuilt");
const {
HumanMessage,
SystemMessage,
AIMessage,
} = require("@langchain/core/messages");
const { runTestCase } = require("../../_test-utils/test-runner.cjs");

async function testLogic(inputs) {
const { model, system, first_prompt, second_prompt } = inputs;

// Create LLM instance
const llm = new ChatOpenAI({
modelName: model,
apiKey: process.env.OPENAI_API_KEY,
});

// Create a simple react agent with no tools
const agent = createReactAgent({ llm, tools: [] });

// First call
const firstResult = await agent.invoke({
messages: [new SystemMessage(system), new HumanMessage(first_prompt)],
});

const firstMessages = firstResult.messages;
const firstLastMessage = firstMessages[firstMessages.length - 1];
const firstText = firstLastMessage.content;

if (!firstText) {
throw new Error("No completion returned from LangGraph (first call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` First response: ${firstText}`);
}

// Second call with conversation history
const secondResult = await agent.invoke({
messages: [
new SystemMessage(system),
new HumanMessage(first_prompt),
new AIMessage(firstText),
new HumanMessage(second_prompt),
],
});

const secondMessages = secondResult.messages;
const secondLastMessage = secondMessages[secondMessages.length - 1];
const secondText = secondLastMessage.content;

if (!secondText) {
throw new Error("No completion returned from LangGraph (second call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` Second response: ${secondText}`);
}
}

module.exports = runTestCase("2-multi-step", testLogic, Sentry);
55 changes: 55 additions & 0 deletions sdks/js/vercel/cases/2-multi-step.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* 2-multi-step: Multi-step Conversation
*
* Tests a multi-step conversation with conversation history using Vercel AI SDK
* and verifies that Sentry captures all spans for both API calls.
*/

const { Sentry } = require("../setup");
const { generateText } = require("ai");
const { openai } = require("@ai-sdk/openai");
const { runTestCase } = require("../../_test-utils/test-runner.cjs");

async function testLogic(inputs) {
const { model, system, first_prompt, second_prompt } = inputs;

// First call
const firstResult = await generateText({
model: openai(model),
system,
prompt: first_prompt,
});

const firstText = firstResult.text;

if (!firstText) {
throw new Error("No completion returned from Vercel AI (first call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` First response: ${firstText}`);
}

// Second call with conversation history
const secondResult = await generateText({
model: openai(model),
system,
messages: [
{ role: "user", content: first_prompt },
{ role: "assistant", content: firstText },
{ role: "user", content: second_prompt },
],
});

const secondText = secondResult.text;

if (!secondText) {
throw new Error("No completion returned from Vercel AI (second call)");
}

if (process.env.SENTRY_AI_TEST_VERBOSE === "true") {
console.log(` Second response: ${secondText}`);
}
}

module.exports = runTestCase("2-multi-step", testLogic, Sentry);
66 changes: 66 additions & 0 deletions sdks/py/anthropic/cases/2-multi-step.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
2-multi-step: Multi-step Conversation

Tests a multi-step conversation with conversation history using Anthropic SDK
and verifies that Sentry captures all spans for both API calls.
"""

import os
from anthropic import Anthropic
from test_runner import run_test_case


async def test_logic(inputs):
"""The actual test logic"""
model = inputs["model"]
system = inputs["system"]
first_prompt = inputs["first_prompt"]
second_prompt = inputs["second_prompt"]

client = Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))

# First call
first_response = client.messages.create(
model=model,
system=system,
messages=[
{"role": "user", "content": first_prompt}
],
max_tokens=1024,
)

first_text = first_response.content[0].text

if not first_text:
raise Exception("No output returned from Anthropic (first call)")

if os.getenv("SENTRY_AI_TEST_VERBOSE") == "true":
print(f" First response: {first_text}")

# Second call with conversation history
second_response = client.messages.create(
model=model,
system=system,
messages=[
{"role": "user", "content": first_prompt},
{"role": "assistant", "content": first_text},
{"role": "user", "content": second_prompt}
],
max_tokens=1024,
)

second_text = second_response.content[0].text

if not second_text:
raise Exception("No output returned from Anthropic (second call)")

if os.getenv("SENTRY_AI_TEST_VERBOSE") == "true":
print(f" Second response: {second_text}")

return second_text


# Export test case functions
test_case = run_test_case("2-multi-step", test_logic)
main = test_case["main"]
assert_sentry = test_case["assert_sentry"]
5 changes: 5 additions & 0 deletions sdks/py/anthropic/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@
"model": "claude-haiku-4-5",
"gen_ai.request.model": "claude-haiku-4-5",
"gen_ai.response.model": "claude-haiku-4-5*"
},
"2-multi-step": {
"model": "claude-haiku-4-5",
"gen_ai.request.model": "claude-haiku-4-5",
"gen_ai.response.model": "claude-haiku-4-5*"
}
}
}
Loading